All of lore.kernel.org
 help / color / mirror / Atom feed
* [RTC] TWL: RTC: Allow rtc driver to be used by tps65910
@ 2011-05-06 22:11 Jorge Eduardo Candelaria
  2011-05-08 17:56 ` Liam Girdwood
  0 siblings, 1 reply; 2+ messages in thread
From: Jorge Eduardo Candelaria @ 2011-05-06 22:11 UTC (permalink / raw)
  To: linux-kernel; +Cc: lrg, Graeme Gregory, a.zummo

TPS65910 PMIC contains an RTC module. This module is identical to
the one found on TWL chips.

The twl-rtc code should allow other PMICs to use the driver,
avoiding the need to create new drivers for the same modules.

Signed-off-by: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>
---
 drivers/mfd/tps65910.c       |   23 ++++-
 drivers/rtc/rtc-twl.c        |  199 ++++++++++++++++++++++++++++++++---------
 include/linux/mfd/tps65910.h |    5 +
 3 files changed, 180 insertions(+), 47 deletions(-)

diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
index 2cf05bb..6206389 100644
--- a/drivers/mfd/tps65910.c
+++ b/drivers/mfd/tps65910.c
@@ -22,6 +22,9 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/tps65910.h>
 
+#define PMIC_CELL		0
+#define RTC_CELL		1
+
 static struct mfd_cell tps65910s[] = {
 	{
 		.name = "tps65910-pmic",
@@ -39,6 +42,9 @@ static struct mfd_cell tps65911s[] = {
 		.name = "tps65910-pmic",
 	},
 	{
+		.name = "twl_rtc",
+	},
+	{
 		.name = "tps65911-comparator",
 	},
 };
@@ -145,6 +151,7 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
 	struct tps65910 *tps65910;
 	struct tps65910_board *pmic_plat_data;
 	struct tps65910_platform_data *init_data;
+	struct pmic_data *pmic_data;
 	int ret = 0;
 
 	tps65910->id = id->driver_data;
@@ -164,6 +171,10 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
 	if (tps65910 == NULL)
 		return -ENOMEM;
 
+	pmic_data = kzalloc(sizeof(struct pmic_data), GFP_KERNEL);
+	if (pmic_data == NULL)
+		return -ENOMEM;
+
 	i2c_set_clientdata(i2c, tps65910);
 	tps65910->dev = &i2c->dev;
 	tps65910->i2c_client = i2c;
@@ -171,14 +182,20 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
 	tps65910->write = tps65910_i2c_write;
 	mutex_init(&tps65910->io_mutex);
 
-	if (tps65910->id == TPS65910)
+	pmic_data->id = id->driver_data;
+	pmic_data->pmic = tps65910;
+
+	if (tps65910->id == TPS65910) {
+		tps65910s[RTC_CELL].mfd_data = pmic_data;
 		ret = mfd_add_devices(tps65910->dev, -1,
 			      tps65910s, ARRAY_SIZE(tps65910s),
 			      NULL, 0);
-	else if (tps65910->id == TPS65911)
+	} else if (tps65910->id == TPS65911) {
+		tps65911s[RTC_CELL].mfd_data = pmic_data;
 		ret = mfd_add_devices(tps65910->dev, -1,
 				tps65911s, ARRAY_SIZE(tps65911s),
-				NULL, 0);
+				NULL, init_data->irq_base);
+	}
 
 	if (ret < 0)
 		goto err;
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
index f9a2799..8f0f023 100644
--- a/drivers/rtc/rtc-twl.c
+++ b/drivers/rtc/rtc-twl.c
@@ -27,8 +27,10 @@
 #include <linux/bcd.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
+#include <linux/gpio.h>
 
 #include <linux/i2c/twl.h>
+#include <linux/mfd/tps65910.h>
 
 
 /*
@@ -103,6 +105,34 @@ static const u8 twl6030_rtc_reg_map[] = {
 	[REG_RTC_COMP_LSB_REG] = 0x13,
 	[REG_RTC_COMP_MSB_REG] = 0x14,
 };
+static const u8 tps65910_rtc_reg_map[] = {
+	[REG_SECONDS_REG] = 0x00,
+	[REG_MINUTES_REG] = 0x01,
+	[REG_HOURS_REG] = 0x02,
+	[REG_DAYS_REG] = 0x03,
+	[REG_MONTHS_REG] = 0x04,
+	[REG_YEARS_REG] = 0x05,
+	[REG_WEEKS_REG] = 0x06,
+
+	[REG_ALARM_SECONDS_REG] = 0x08,
+	[REG_ALARM_MINUTES_REG] = 0x09,
+	[REG_ALARM_HOURS_REG] = 0x0A,
+	[REG_ALARM_DAYS_REG] = 0x0B,
+	[REG_ALARM_MONTHS_REG] = 0x0C,
+	[REG_ALARM_YEARS_REG] = 0x0D,
+
+	[REG_RTC_CTRL_REG] = 0x10,
+	[REG_RTC_STATUS_REG] = 0x11,
+	[REG_RTC_INTERRUPTS_REG] = 0x12,
+
+	[REG_RTC_COMP_LSB_REG] = 0x13,
+	[REG_RTC_COMP_MSB_REG] = 0x14,
+
+	/* TODO: Add the following registers for tps 
+	[REG_RTC_RES_PROG_REG] = 0x15,
+	[REG_RTC_RESET_STATUS_REG] = 0x16,
+	*/
+};
 
 /* RTC_CTRL_REG bitfields */
 #define BIT_RTC_CTRL_REG_STOP_RTC_M              0x01
@@ -137,11 +167,18 @@ static u8  *rtc_reg_map;
 /*
  * Supports 1 byte read from TWL RTC register.
  */
-static int twl_rtc_read_u8(u8 *data, u8 reg)
+static int rtc_read_u8(struct pmic_data *pmic_data, u8 *data, u8 reg)
 {
+	struct tps65910 *tps65910;
+	int pmic_id = pmic_data->id;
 	int ret;
 
-	ret = twl_i2c_read_u8(TWL_MODULE_RTC, data, (rtc_reg_map[reg]));
+	if (pmic_id == tps65910_chip_id(tps65910)) {
+		tps65910 = (struct tps65910 *)pmic_data->pmic;
+		ret = tps65910->read(tps65910, (rtc_reg_map[reg]), 1, data);
+	} else {
+		ret = twl_i2c_read_u8(TWL_MODULE_RTC, data, (rtc_reg_map[reg]));
+	}
 	if (ret < 0)
 		pr_err("twl_rtc: Could not read TWL"
 		       "register %X - error %d\n", reg, ret);
@@ -151,15 +188,65 @@ static int twl_rtc_read_u8(u8 *data, u8 reg)
 /*
  * Supports 1 byte write to TWL RTC registers.
  */
-static int twl_rtc_write_u8(u8 data, u8 reg)
+static int rtc_write_u8(struct pmic_data *pmic_data, u8 data, u8 reg)
+{
+	struct tps65910 *tps65910;
+	int pmic_id = pmic_data->id;
+	int ret;
+
+	if (pmic_id == tps65910_chip_id(tps65910)) {
+		tps65910 = (struct tps65910 *)pmic_data->pmic;
+		ret = tps65910->write(tps65910, (rtc_reg_map[reg]), 1, &data);
+	} else {
+		ret = twl_i2c_write_u8(TWL_MODULE_RTC, data,
+					(rtc_reg_map[reg]));
+	}
+	if (ret < 0)
+		pr_err("twl_rtc: Could not write TWL"
+		       "register %X - error %d\n", reg, ret);
+	return ret;
+}
+
+static int rtc_read_array(struct pmic_data *pmic_data,
+				char *data, int size, u8 reg)
 {
+	struct tps65910 *tps65910;
+	int pmic_id = pmic_data->id;
 	int ret;
 
-	ret = twl_i2c_write_u8(TWL_MODULE_RTC, data, (rtc_reg_map[reg]));
+	if (pmic_id == tps65910_chip_id(tps65910)) {
+		tps65910 = (struct tps65910 *)pmic_data->pmic;
+		ret = tps65910->read(tps65910, reg, size, data);
+	} else {
+		ret = twl_i2c_read(TWL_MODULE_RTC, data,
+					(rtc_reg_map[reg]), size);
+	}
+	if (ret < 0)
+		pr_err("twl_rtc: Could not read TWL"
+		       "register %X - error %d\n", reg, ret);
+	return ret;
+
+}
+
+static int rtc_write_array(struct pmic_data *pmic_data,
+				char *data, int size, u8 reg)
+{
+	struct tps65910 *tps65910;
+	int pmic_id = pmic_data->id;
+	int ret;
+
+	if (pmic_id == tps65910_chip_id(tps65910)) {
+		tps65910 = (struct tps65910 *)pmic_data->pmic;
+		ret = tps65910->write(tps65910, reg, size, &data);
+	} else {
+		ret = twl_i2c_write(TWL_MODULE_RTC, data,
+				(rtc_reg_map[reg]), size);
+	}
 	if (ret < 0)
 		pr_err("twl_rtc: Could not write TWL"
 		       "register %X - error %d\n", reg, ret);
 	return ret;
+
 }
 
 /*
@@ -171,14 +258,14 @@ static unsigned char rtc_irq_bits;
 /*
  * Enable 1/second update and/or alarm interrupts.
  */
-static int set_rtc_irq_bit(unsigned char bit)
+static int set_rtc_irq_bit(struct pmic_data *pmic, unsigned char bit)
 {
 	unsigned char val;
 	int ret;
 
 	val = rtc_irq_bits | bit;
 	val &= ~BIT_RTC_INTERRUPTS_REG_EVERY_M;
-	ret = twl_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG);
+	ret = rtc_write_u8(pmic, val, REG_RTC_INTERRUPTS_REG);
 	if (ret == 0)
 		rtc_irq_bits = val;
 
@@ -188,13 +275,13 @@ static int set_rtc_irq_bit(unsigned char bit)
 /*
  * Disable update and/or alarm interrupts.
  */
-static int mask_rtc_irq_bit(unsigned char bit)
+static int mask_rtc_irq_bit(struct pmic_data *pmic, unsigned char bit)
 {
 	unsigned char val;
 	int ret;
 
 	val = rtc_irq_bits & ~bit;
-	ret = twl_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG);
+	ret = rtc_write_u8(pmic, val, REG_RTC_INTERRUPTS_REG);
 	if (ret == 0)
 		rtc_irq_bits = val;
 
@@ -203,12 +290,13 @@ static int mask_rtc_irq_bit(unsigned char bit)
 
 static int twl_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
 {
+	struct pmic_data *pmic = dev_get_platdata(dev);
 	int ret;
 
 	if (enabled)
-		ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
+		ret = set_rtc_irq_bit(pmic, BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
 	else
-		ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
+		ret = mask_rtc_irq_bit(pmic, BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
 
 	return ret;
 }
@@ -224,22 +312,23 @@ static int twl_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
  */
 static int twl_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
+	struct pmic_data *pmic = dev_get_platdata(dev);
 	unsigned char rtc_data[ALL_TIME_REGS + 1];
 	int ret;
 	u8 save_control;
 
-	ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG);
+	ret = rtc_read_u8(pmic, &save_control, REG_RTC_CTRL_REG);
 	if (ret < 0)
 		return ret;
 
 	save_control |= BIT_RTC_CTRL_REG_GET_TIME_M;
 
-	ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
+	ret = rtc_write_u8(pmic, save_control, REG_RTC_CTRL_REG);
 	if (ret < 0)
 		return ret;
 
-	ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data,
-			(rtc_reg_map[REG_SECONDS_REG]), ALL_TIME_REGS);
+	ret = rtc_read_array(pmic, rtc_data, ALL_TIME_REGS,
+					rtc_reg_map[REG_SECONDS_REG]);
 
 	if (ret < 0) {
 		dev_err(dev, "rtc_read_time error %d\n", ret);
@@ -258,8 +347,9 @@ static int twl_rtc_read_time(struct device *dev, struct rtc_time *tm)
 
 static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
+	struct pmic_data *pmic = dev_get_platdata(dev);
 	unsigned char save_control;
-	unsigned char rtc_data[ALL_TIME_REGS + 1];
+	char rtc_data[ALL_TIME_REGS + 1];
 	int ret;
 
 	rtc_data[1] = bin2bcd(tm->tm_sec);
@@ -270,18 +360,18 @@ static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm)
 	rtc_data[6] = bin2bcd(tm->tm_year - 100);
 
 	/* Stop RTC while updating the TC registers */
-	ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG);
+	ret = rtc_read_u8(pmic, &save_control, REG_RTC_CTRL_REG);
 	if (ret < 0)
 		goto out;
 
 	save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M;
-	twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
+	ret = rtc_write_u8(pmic, save_control, REG_RTC_CTRL_REG);
 	if (ret < 0)
 		goto out;
 
 	/* update all the time registers in one shot */
-	ret = twl_i2c_write(TWL_MODULE_RTC, rtc_data,
-		(rtc_reg_map[REG_SECONDS_REG]), ALL_TIME_REGS);
+	ret = rtc_write_array(pmic, rtc_data, ALL_TIME_REGS,
+				rtc_reg_map[REG_SECONDS_REG]);
 	if (ret < 0) {
 		dev_err(dev, "rtc_set_time error %d\n", ret);
 		goto out;
@@ -289,7 +379,7 @@ static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm)
 
 	/* Start back RTC */
 	save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M;
-	ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
+	ret = rtc_write_u8(pmic, save_control, REG_RTC_CTRL_REG);
 
 out:
 	return ret;
@@ -300,11 +390,12 @@ out:
  */
 static int twl_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 {
+	struct pmic_data *pmic = dev_get_platdata(dev);
 	unsigned char rtc_data[ALL_TIME_REGS + 1];
 	int ret;
 
-	ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data,
-			(rtc_reg_map[REG_ALARM_SECONDS_REG]), ALL_TIME_REGS);
+	ret = rtc_read_array(pmic, rtc_data, ALL_TIME_REGS,
+					rtc_reg_map[REG_ALARM_SECONDS_REG]);
 	if (ret < 0) {
 		dev_err(dev, "rtc_read_alarm error %d\n", ret);
 		return ret;
@@ -327,7 +418,8 @@ static int twl_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 
 static int twl_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 {
-	unsigned char alarm_data[ALL_TIME_REGS + 1];
+	struct pmic_data *pmic = dev_get_platdata(dev);
+	char alarm_data[ALL_TIME_REGS + 1];
 	int ret;
 
 	ret = twl_rtc_alarm_irq_enable(dev, 0);
@@ -342,8 +434,9 @@ static int twl_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 	alarm_data[6] = bin2bcd(alm->time.tm_year - 100);
 
 	/* update all the alarm registers in one shot */
-	ret = twl_i2c_write(TWL_MODULE_RTC, alarm_data,
-		(rtc_reg_map[REG_ALARM_SECONDS_REG]), ALL_TIME_REGS);
+	ret = rtc_write_array(pmic, alarm_data, ALL_TIME_REGS,
+				(rtc_reg_map[REG_ALARM_SECONDS_REG])); 
+	
 	if (ret) {
 		dev_err(dev, "rtc_set_alarm error %d\n", ret);
 		goto out;
@@ -355,8 +448,11 @@ out:
 	return ret;
 }
 
-static irqreturn_t twl_rtc_interrupt(int irq, void *rtc)
+static irqreturn_t twl_rtc_interrupt(int irq, void *data)
 {
+	struct rtc_device *rtc = data;
+	struct device *dev = &rtc->dev;
+	struct pmic_data *pmic = dev_get_platdata(dev);
 	unsigned long events = 0;
 	int ret = IRQ_NONE;
 	int res;
@@ -370,7 +466,7 @@ static irqreturn_t twl_rtc_interrupt(int irq, void *rtc)
 	local_irq_enable();
 #endif
 
-	res = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);
+	res = rtc_read_u8(pmic, &rd_reg, REG_RTC_STATUS_REG);
 	if (res)
 		goto out;
 	/*
@@ -384,8 +480,8 @@ static irqreturn_t twl_rtc_interrupt(int irq, void *rtc)
 	else
 		events |= RTC_IRQF | RTC_UF;
 
-	res = twl_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M,
-				   REG_RTC_STATUS_REG);
+	res = rtc_write_u8(pmic,rd_reg | BIT_RTC_STATUS_REG_ALARM_M,
+						REG_RTC_STATUS_REG);
 	if (res)
 		goto out;
 
@@ -408,7 +504,7 @@ static irqreturn_t twl_rtc_interrupt(int irq, void *rtc)
 	}
 
 	/* Notify RTC core on event */
-	rtc_update_irq(rtc, 1, events);
+	rtc_update_irq(data, 1, events);
 
 	ret = IRQ_HANDLED;
 out:
@@ -428,10 +524,13 @@ static struct rtc_class_ops twl_rtc_ops = {
 static int __devinit twl_rtc_probe(struct platform_device *pdev)
 {
 	struct rtc_device *rtc;
+	struct pmic_data *pmic = dev_get_platdata(&pdev->dev);
 	int ret = 0;
 	int irq = platform_get_irq(pdev, 0);
 	u8 rd_reg;
 
+	dev_err(&pdev->dev, "%d\n", pmic->id);
+
 	if (irq <= 0)
 		return -EINVAL;
 
@@ -446,8 +545,8 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev)
 	}
 
 	platform_set_drvdata(pdev, rtc);
-
-	ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);
+	
+	ret = rtc_read_u8(pmic, &rd_reg, REG_RTC_STATUS_REG);
 	if (ret < 0)
 		goto out1;
 
@@ -458,7 +557,7 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev)
 		dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n");
 
 	/* Clear RTC Power up reset and pending alarm interrupts */
-	ret = twl_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG);
+	ret = rtc_write_u8(pmic, rd_reg, REG_RTC_STATUS_REG);
 	if (ret < 0)
 		goto out1;
 
@@ -466,7 +565,7 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev)
 				IRQF_TRIGGER_RISING,
 				dev_name(&rtc->dev), rtc);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "IRQ is not free.\n");
+		dev_err(&pdev->dev, "IRQ %d is not free.\n", irq);
 		goto out1;
 	}
 
@@ -475,23 +574,23 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev)
 			REG_INT_MSK_LINE_A);
 		twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK,
 			REG_INT_MSK_STS_A);
-	}
+	} 
 
 	/* Check RTC module status, Enable if it is off */
-	ret = twl_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG);
+	ret = rtc_read_u8(pmic, &rd_reg, REG_RTC_CTRL_REG);
 	if (ret < 0)
 		goto out2;
 
 	if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) {
 		dev_info(&pdev->dev, "Enabling TWL-RTC.\n");
 		rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M;
-		ret = twl_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG);
+		ret = rtc_write_u8(pmic, rd_reg, REG_RTC_CTRL_REG);
 		if (ret < 0)
 			goto out2;
 	}
 
 	/* init cached IRQ enable bits */
-	ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG);
+	ret = rtc_read_u8(pmic, &rtc_irq_bits, REG_RTC_INTERRUPTS_REG);
 	if (ret < 0)
 		goto out2;
 
@@ -513,10 +612,12 @@ static int __devexit twl_rtc_remove(struct platform_device *pdev)
 {
 	/* leave rtc running, but disable irqs */
 	struct rtc_device *rtc = platform_get_drvdata(pdev);
+	struct device *dev = &pdev->dev;
+	struct pmic_data *pmic = dev_get_platdata(dev);
 	int irq = platform_get_irq(pdev, 0);
 
-	mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
-	mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
+	mask_rtc_irq_bit(pmic, BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
+	mask_rtc_irq_bit(pmic, BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
 	if (twl_class_is_6030()) {
 		twl6030_interrupt_mask(TWL6030_RTC_INT_MASK,
 			REG_INT_MSK_LINE_A);
@@ -534,9 +635,12 @@ static int __devexit twl_rtc_remove(struct platform_device *pdev)
 
 static void twl_rtc_shutdown(struct platform_device *pdev)
 {
+	struct device *dev = &pdev->dev;
+	struct pmic_data *pmic = dev_get_platdata(dev);
+
 	/* mask timer interrupts, but leave alarm interrupts on to enable
 	   power-on when alarm is triggered */
-	mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
+	mask_rtc_irq_bit(pmic, BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
 }
 
 #ifdef CONFIG_PM
@@ -545,15 +649,19 @@ static unsigned char irqstat;
 
 static int twl_rtc_suspend(struct platform_device *pdev, pm_message_t state)
 {
+	struct device *dev = &pdev->dev;
+	struct pmic_data *pmic = dev_get_platdata(dev);
 	irqstat = rtc_irq_bits;
 
-	mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
+	mask_rtc_irq_bit(pmic, BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
 	return 0;
 }
 
 static int twl_rtc_resume(struct platform_device *pdev)
 {
-	set_rtc_irq_bit(irqstat);
+	struct device *dev = &pdev->dev;
+	struct pmic_data *pmic = dev_get_platdata(dev);
+	set_rtc_irq_bit(pmic, irqstat);
 	return 0;
 }
 
@@ -580,8 +688,11 @@ static int __init twl_rtc_init(void)
 {
 	if (twl_class_is_4030())
 		rtc_reg_map = (u8 *) twl4030_rtc_reg_map;
-	else
+	else if (twl_class_is_6030())
 		rtc_reg_map = (u8 *) twl6030_rtc_reg_map;
+	/* TODO: Verify that rtc parent is tps65910 */
+	else
+		rtc_reg_map = (u8 *) tps65910_rtc_reg_map;
 
 	return platform_driver_register(&twl4030rtc_driver);
 }
diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h
index 8bb85b9..520e7e2 100644
--- a/include/linux/mfd/tps65910.h
+++ b/include/linux/mfd/tps65910.h
@@ -786,6 +786,11 @@ struct tps65910_platform_data {
 	int irq_base;
 };
 
+struct pmic_data {
+	int id;
+	void * pmic;
+};
+
 int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask);
 int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask);
 void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base);
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [RTC] TWL: RTC: Allow rtc driver to be used by tps65910
  2011-05-06 22:11 [RTC] TWL: RTC: Allow rtc driver to be used by tps65910 Jorge Eduardo Candelaria
@ 2011-05-08 17:56 ` Liam Girdwood
  0 siblings, 0 replies; 2+ messages in thread
From: Liam Girdwood @ 2011-05-08 17:56 UTC (permalink / raw)
  To: Jorge Eduardo Candelaria; +Cc: linux-kernel, Graeme Gregory, a.zummo

On 06/05/11 23:11, Jorge Eduardo Candelaria wrote:
> TPS65910 PMIC contains an RTC module. This module is identical to
> the one found on TWL chips.
> 
> The twl-rtc code should allow other PMICs to use the driver,
> avoiding the need to create new drivers for the same modules.

Ok, so this just basically adds a RTC register mapping for tps65910 and tps65910 IO. Seems fair enough, just some comments below :-

> 
> Signed-off-by: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>
> ---
>  drivers/mfd/tps65910.c       |   23 ++++-
>  drivers/rtc/rtc-twl.c        |  199 ++++++++++++++++++++++++++++++++---------
>  include/linux/mfd/tps65910.h |    5 +
>  3 files changed, 180 insertions(+), 47 deletions(-)
> 
> diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
> index 2cf05bb..6206389 100644
> --- a/drivers/mfd/tps65910.c
> +++ b/drivers/mfd/tps65910.c
> @@ -22,6 +22,9 @@
>  #include <linux/mfd/core.h>
>  #include <linux/mfd/tps65910.h>
> 
> +#define PMIC_CELL              0
> +#define RTC_CELL               1
> +
>  static struct mfd_cell tps65910s[] = {
>         {
>                 .name = "tps65910-pmic",
> @@ -39,6 +42,9 @@ static struct mfd_cell tps65911s[] = {
>                 .name = "tps65910-pmic",
>         },
>         {
> +               .name = "twl_rtc",
> +       },
> +       {
>                 .name = "tps65911-comparator",
>         },
>  };
> @@ -145,6 +151,7 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
>         struct tps65910 *tps65910;
>         struct tps65910_board *pmic_plat_data;
>         struct tps65910_platform_data *init_data;
> +       struct pmic_data *pmic_data;
>         int ret = 0;
> 
>         tps65910->id = id->driver_data;
> @@ -164,6 +171,10 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
>         if (tps65910 == NULL)
>                 return -ENOMEM;
> 
> +       pmic_data = kzalloc(sizeof(struct pmic_data), GFP_KERNEL);
> +       if (pmic_data == NULL)
> +               return -ENOMEM;
> +
>         i2c_set_clientdata(i2c, tps65910);
>         tps65910->dev = &i2c->dev;
>         tps65910->i2c_client = i2c;
> @@ -171,14 +182,20 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
>         tps65910->write = tps65910_i2c_write;
>         mutex_init(&tps65910->io_mutex);
> 
> -       if (tps65910->id == TPS65910)
> +       pmic_data->id = id->driver_data;
> +       pmic_data->pmic = tps65910;
> +
> +       if (tps65910->id == TPS65910) {
> +               tps65910s[RTC_CELL].mfd_data = pmic_data;
>                 ret = mfd_add_devices(tps65910->dev, -1,
>                               tps65910s, ARRAY_SIZE(tps65910s),
>                               NULL, 0);
> -       else if (tps65910->id == TPS65911)
> +       } else if (tps65910->id == TPS65911) {
> +               tps65911s[RTC_CELL].mfd_data = pmic_data;
>                 ret = mfd_add_devices(tps65910->dev, -1,
>                                 tps65911s, ARRAY_SIZE(tps65911s),
> -                               NULL, 0);
> +                               NULL, init_data->irq_base);
> +       }
> 
>         if (ret < 0)
>                 goto err;
> diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
> index f9a2799..8f0f023 100644
> --- a/drivers/rtc/rtc-twl.c
> +++ b/drivers/rtc/rtc-twl.c
> @@ -27,8 +27,10 @@
>  #include <linux/bcd.h>
>  #include <linux/platform_device.h>
>  #include <linux/interrupt.h>
> +#include <linux/gpio.h>
> 
>  #include <linux/i2c/twl.h>
> +#include <linux/mfd/tps65910.h>
> 
> 
>  /*
> @@ -103,6 +105,34 @@ static const u8 twl6030_rtc_reg_map[] = {
>         [REG_RTC_COMP_LSB_REG] = 0x13,
>         [REG_RTC_COMP_MSB_REG] = 0x14,
>  };
> +static const u8 tps65910_rtc_reg_map[] = {
> +       [REG_SECONDS_REG] = 0x00,
> +       [REG_MINUTES_REG] = 0x01,
> +       [REG_HOURS_REG] = 0x02,
> +       [REG_DAYS_REG] = 0x03,
> +       [REG_MONTHS_REG] = 0x04,
> +       [REG_YEARS_REG] = 0x05,
> +       [REG_WEEKS_REG] = 0x06,
> +
> +       [REG_ALARM_SECONDS_REG] = 0x08,
> +       [REG_ALARM_MINUTES_REG] = 0x09,
> +       [REG_ALARM_HOURS_REG] = 0x0A,
> +       [REG_ALARM_DAYS_REG] = 0x0B,
> +       [REG_ALARM_MONTHS_REG] = 0x0C,
> +       [REG_ALARM_YEARS_REG] = 0x0D,
> +
> +       [REG_RTC_CTRL_REG] = 0x10,
> +       [REG_RTC_STATUS_REG] = 0x11,
> +       [REG_RTC_INTERRUPTS_REG] = 0x12,
> +
> +       [REG_RTC_COMP_LSB_REG] = 0x13,
> +       [REG_RTC_COMP_MSB_REG] = 0x14,
> +
> +       /* TODO: Add the following registers for tps
> +       [REG_RTC_RES_PROG_REG] = 0x15,
> +       [REG_RTC_RESET_STATUS_REG] = 0x16,
> +       */
> +};
> 
>  /* RTC_CTRL_REG bitfields */
>  #define BIT_RTC_CTRL_REG_STOP_RTC_M              0x01
> @@ -137,11 +167,18 @@ static u8  *rtc_reg_map;
>  /*
>   * Supports 1 byte read from TWL RTC register.
>   */
> -static int twl_rtc_read_u8(u8 *data, u8 reg)
> +static int rtc_read_u8(struct pmic_data *pmic_data, u8 *data, u8 reg)
>  {
> +       struct tps65910 *tps65910;
> +       int pmic_id = pmic_data->id;

I'd rename these tps_chip and rtc_id since other tps devices share the RTC IP.

>         int ret;
> 
> -       ret = twl_i2c_read_u8(TWL_MODULE_RTC, data, (rtc_reg_map[reg]));
> +       if (pmic_id == tps65910_chip_id(tps65910)) {
> +               tps65910 = (struct tps65910 *)pmic_data->pmic;
> +               ret = tps65910->read(tps65910, (rtc_reg_map[reg]), 1, data);
> +       } else {
> +               ret = twl_i2c_read_u8(TWL_MODULE_RTC, data, (rtc_reg_map[reg]));
> +       }
>         if (ret < 0)
>                 pr_err("twl_rtc: Could not read TWL"
>                        "register %X - error %d\n", reg, ret);


It's best to setup the correct register IO functions at probe() time rather than checking on each register IO call.
Although, this may be a difficult here since sadly the twl is a singleton driver and doesnt have a device handle for most of it's API calls.

> @@ -151,15 +188,65 @@ static int twl_rtc_read_u8(u8 *data, u8 reg)
>  /*
>   * Supports 1 byte write to TWL RTC registers.
>   */
> -static int twl_rtc_write_u8(u8 data, u8 reg)
> +static int rtc_write_u8(struct pmic_data *pmic_data, u8 data, u8 reg)
> +{
> +       struct tps65910 *tps65910;
> +       int pmic_id = pmic_data->id;
> +       int ret;
> +
> +       if (pmic_id == tps65910_chip_id(tps65910)) {
> +               tps65910 = (struct tps65910 *)pmic_data->pmic;
> +               ret = tps65910->write(tps65910, (rtc_reg_map[reg]), 1, &data);
> +       } else {
> +               ret = twl_i2c_write_u8(TWL_MODULE_RTC, data,
> +                                       (rtc_reg_map[reg]));
> +       }
> +       if (ret < 0)
> +               pr_err("twl_rtc: Could not write TWL"
> +                      "register %X - error %d\n", reg, ret);
> +       return ret;
> +}
> +
> +static int rtc_read_array(struct pmic_data *pmic_data,
> +                               char *data, int size, u8 reg)
>  {
> +       struct tps65910 *tps65910;
> +       int pmic_id = pmic_data->id;
>         int ret;
> 
> -       ret = twl_i2c_write_u8(TWL_MODULE_RTC, data, (rtc_reg_map[reg]));
> +       if (pmic_id == tps65910_chip_id(tps65910)) {
> +               tps65910 = (struct tps65910 *)pmic_data->pmic;
> +               ret = tps65910->read(tps65910, reg, size, data);
> +       } else {
> +               ret = twl_i2c_read(TWL_MODULE_RTC, data,
> +                                       (rtc_reg_map[reg]), size);
> +       }
> +       if (ret < 0)
> +               pr_err("twl_rtc: Could not read TWL"
> +                      "register %X - error %d\n", reg, ret);
> +       return ret;
> +
> +}
> +
> +static int rtc_write_array(struct pmic_data *pmic_data,
> +                               char *data, int size, u8 reg)
> +{
> +       struct tps65910 *tps65910;
> +       int pmic_id = pmic_data->id;
> +       int ret;
> +
> +       if (pmic_id == tps65910_chip_id(tps65910)) {
> +               tps65910 = (struct tps65910 *)pmic_data->pmic;
> +               ret = tps65910->write(tps65910, reg, size, &data);
> +       } else {
> +               ret = twl_i2c_write(TWL_MODULE_RTC, data,
> +                               (rtc_reg_map[reg]), size);
> +       }
>         if (ret < 0)
>                 pr_err("twl_rtc: Could not write TWL"
>                        "register %X - error %d\n", reg, ret);
>         return ret;
> +
>  }
> 
>  /*
> @@ -171,14 +258,14 @@ static unsigned char rtc_irq_bits;
>  /*
>   * Enable 1/second update and/or alarm interrupts.
>   */
> -static int set_rtc_irq_bit(unsigned char bit)
> +static int set_rtc_irq_bit(struct pmic_data *pmic, unsigned char bit)
>  {
>         unsigned char val;
>         int ret;
> 
>         val = rtc_irq_bits | bit;
>         val &= ~BIT_RTC_INTERRUPTS_REG_EVERY_M;
> -       ret = twl_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG);
> +       ret = rtc_write_u8(pmic, val, REG_RTC_INTERRUPTS_REG);
>         if (ret == 0)
>                 rtc_irq_bits = val;
> 
> @@ -188,13 +275,13 @@ static int set_rtc_irq_bit(unsigned char bit)
>  /*
>   * Disable update and/or alarm interrupts.
>   */
> -static int mask_rtc_irq_bit(unsigned char bit)
> +static int mask_rtc_irq_bit(struct pmic_data *pmic, unsigned char bit)
>  {
>         unsigned char val;
>         int ret;
> 
>         val = rtc_irq_bits & ~bit;
> -       ret = twl_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG);
> +       ret = rtc_write_u8(pmic, val, REG_RTC_INTERRUPTS_REG);
>         if (ret == 0)
>                 rtc_irq_bits = val;
> 
> @@ -203,12 +290,13 @@ static int mask_rtc_irq_bit(unsigned char bit)
> 
>  static int twl_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
>  {
> +       struct pmic_data *pmic = dev_get_platdata(dev);
>         int ret;
> 
>         if (enabled)
> -               ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
> +               ret = set_rtc_irq_bit(pmic, BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
>         else
> -               ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
> +               ret = mask_rtc_irq_bit(pmic, BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
> 
>         return ret;
>  }
> @@ -224,22 +312,23 @@ static int twl_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
>   */
>  static int twl_rtc_read_time(struct device *dev, struct rtc_time *tm)
>  {
> +       struct pmic_data *pmic = dev_get_platdata(dev);
>         unsigned char rtc_data[ALL_TIME_REGS + 1];
>         int ret;
>         u8 save_control;
> 
> -       ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG);
> +       ret = rtc_read_u8(pmic, &save_control, REG_RTC_CTRL_REG);
>         if (ret < 0)
>                 return ret;
> 
>         save_control |= BIT_RTC_CTRL_REG_GET_TIME_M;
> 
> -       ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
> +       ret = rtc_write_u8(pmic, save_control, REG_RTC_CTRL_REG);
>         if (ret < 0)
>                 return ret;
> 
> -       ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data,
> -                       (rtc_reg_map[REG_SECONDS_REG]), ALL_TIME_REGS);
> +       ret = rtc_read_array(pmic, rtc_data, ALL_TIME_REGS,
> +                                       rtc_reg_map[REG_SECONDS_REG]);
> 
>         if (ret < 0) {
>                 dev_err(dev, "rtc_read_time error %d\n", ret);
> @@ -258,8 +347,9 @@ static int twl_rtc_read_time(struct device *dev, struct rtc_time *tm)
> 
>  static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm)
>  {
> +       struct pmic_data *pmic = dev_get_platdata(dev);
>         unsigned char save_control;
> -       unsigned char rtc_data[ALL_TIME_REGS + 1];
> +       char rtc_data[ALL_TIME_REGS + 1];
>         int ret;
> 
>         rtc_data[1] = bin2bcd(tm->tm_sec);
> @@ -270,18 +360,18 @@ static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm)
>         rtc_data[6] = bin2bcd(tm->tm_year - 100);
> 
>         /* Stop RTC while updating the TC registers */
> -       ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG);
> +       ret = rtc_read_u8(pmic, &save_control, REG_RTC_CTRL_REG);
>         if (ret < 0)
>                 goto out;
> 
>         save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M;
> -       twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
> +       ret = rtc_write_u8(pmic, save_control, REG_RTC_CTRL_REG);
>         if (ret < 0)
>                 goto out;
> 
>         /* update all the time registers in one shot */
> -       ret = twl_i2c_write(TWL_MODULE_RTC, rtc_data,
> -               (rtc_reg_map[REG_SECONDS_REG]), ALL_TIME_REGS);
> +       ret = rtc_write_array(pmic, rtc_data, ALL_TIME_REGS,
> +                               rtc_reg_map[REG_SECONDS_REG]);
>         if (ret < 0) {
>                 dev_err(dev, "rtc_set_time error %d\n", ret);
>                 goto out;
> @@ -289,7 +379,7 @@ static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm)
> 
>         /* Start back RTC */
>         save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M;
> -       ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
> +       ret = rtc_write_u8(pmic, save_control, REG_RTC_CTRL_REG);
> 
>  out:
>         return ret;
> @@ -300,11 +390,12 @@ out:
>   */
>  static int twl_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
>  {
> +       struct pmic_data *pmic = dev_get_platdata(dev);
>         unsigned char rtc_data[ALL_TIME_REGS + 1];
>         int ret;
> 
> -       ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data,
> -                       (rtc_reg_map[REG_ALARM_SECONDS_REG]), ALL_TIME_REGS);
> +       ret = rtc_read_array(pmic, rtc_data, ALL_TIME_REGS,
> +                                       rtc_reg_map[REG_ALARM_SECONDS_REG]);
>         if (ret < 0) {
>                 dev_err(dev, "rtc_read_alarm error %d\n", ret);
>                 return ret;
> @@ -327,7 +418,8 @@ static int twl_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
> 
>  static int twl_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
>  {
> -       unsigned char alarm_data[ALL_TIME_REGS + 1];
> +       struct pmic_data *pmic = dev_get_platdata(dev);
> +       char alarm_data[ALL_TIME_REGS + 1];
>         int ret;
> 
>         ret = twl_rtc_alarm_irq_enable(dev, 0);
> @@ -342,8 +434,9 @@ static int twl_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
>         alarm_data[6] = bin2bcd(alm->time.tm_year - 100);
> 
>         /* update all the alarm registers in one shot */
> -       ret = twl_i2c_write(TWL_MODULE_RTC, alarm_data,
> -               (rtc_reg_map[REG_ALARM_SECONDS_REG]), ALL_TIME_REGS);
> +       ret = rtc_write_array(pmic, alarm_data, ALL_TIME_REGS,
> +                               (rtc_reg_map[REG_ALARM_SECONDS_REG]));
> +
>         if (ret) {
>                 dev_err(dev, "rtc_set_alarm error %d\n", ret);
>                 goto out;
> @@ -355,8 +448,11 @@ out:
>         return ret;
>  }
> 
> -static irqreturn_t twl_rtc_interrupt(int irq, void *rtc)
> +static irqreturn_t twl_rtc_interrupt(int irq, void *data)
>  {
> +       struct rtc_device *rtc = data;
> +       struct device *dev = &rtc->dev;
> +       struct pmic_data *pmic = dev_get_platdata(dev);
>         unsigned long events = 0;
>         int ret = IRQ_NONE;
>         int res;
> @@ -370,7 +466,7 @@ static irqreturn_t twl_rtc_interrupt(int irq, void *rtc)
>         local_irq_enable();
>  #endif
> 
> -       res = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);
> +       res = rtc_read_u8(pmic, &rd_reg, REG_RTC_STATUS_REG);
>         if (res)
>                 goto out;
>         /*
> @@ -384,8 +480,8 @@ static irqreturn_t twl_rtc_interrupt(int irq, void *rtc)
>         else
>                 events |= RTC_IRQF | RTC_UF;
> 
> -       res = twl_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M,
> -                                  REG_RTC_STATUS_REG);
> +       res = rtc_write_u8(pmic,rd_reg | BIT_RTC_STATUS_REG_ALARM_M,
> +                                               REG_RTC_STATUS_REG);
>         if (res)
>                 goto out;
> 
> @@ -408,7 +504,7 @@ static irqreturn_t twl_rtc_interrupt(int irq, void *rtc)
>         }
> 
>         /* Notify RTC core on event */
> -       rtc_update_irq(rtc, 1, events);
> +       rtc_update_irq(data, 1, events);
> 
>         ret = IRQ_HANDLED;
>  out:
> @@ -428,10 +524,13 @@ static struct rtc_class_ops twl_rtc_ops = {
>  static int __devinit twl_rtc_probe(struct platform_device *pdev)
>  {
>         struct rtc_device *rtc;
> +       struct pmic_data *pmic = dev_get_platdata(&pdev->dev);
>         int ret = 0;
>         int irq = platform_get_irq(pdev, 0);
>         u8 rd_reg;
> 
> +       dev_err(&pdev->dev, "%d\n", pmic->id);
> +
>         if (irq <= 0)
>                 return -EINVAL;
> 
> @@ -446,8 +545,8 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev)
>         }
> 
>         platform_set_drvdata(pdev, rtc);
> -
> -       ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);
> +
> +       ret = rtc_read_u8(pmic, &rd_reg, REG_RTC_STATUS_REG);
>         if (ret < 0)
>                 goto out1;
> 
> @@ -458,7 +557,7 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev)
>                 dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n");
> 
>         /* Clear RTC Power up reset and pending alarm interrupts */
> -       ret = twl_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG);
> +       ret = rtc_write_u8(pmic, rd_reg, REG_RTC_STATUS_REG);
>         if (ret < 0)
>                 goto out1;
> 
> @@ -466,7 +565,7 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev)
>                                 IRQF_TRIGGER_RISING,
>                                 dev_name(&rtc->dev), rtc);
>         if (ret < 0) {
> -               dev_err(&pdev->dev, "IRQ is not free.\n");
> +               dev_err(&pdev->dev, "IRQ %d is not free.\n", irq);
>                 goto out1;
>         }
> 
> @@ -475,23 +574,23 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev)
>                         REG_INT_MSK_LINE_A);
>                 twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK,
>                         REG_INT_MSK_STS_A);
> -       }
> +       }
> 
>         /* Check RTC module status, Enable if it is off */
> -       ret = twl_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG);
> +       ret = rtc_read_u8(pmic, &rd_reg, REG_RTC_CTRL_REG);
>         if (ret < 0)
>                 goto out2;
> 
>         if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) {
>                 dev_info(&pdev->dev, "Enabling TWL-RTC.\n");
>                 rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M;
> -               ret = twl_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG);
> +               ret = rtc_write_u8(pmic, rd_reg, REG_RTC_CTRL_REG);
>                 if (ret < 0)
>                         goto out2;
>         }
> 
>         /* init cached IRQ enable bits */
> -       ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG);
> +       ret = rtc_read_u8(pmic, &rtc_irq_bits, REG_RTC_INTERRUPTS_REG);
>         if (ret < 0)
>                 goto out2;
> 
> @@ -513,10 +612,12 @@ static int __devexit twl_rtc_remove(struct platform_device *pdev)
>  {
>         /* leave rtc running, but disable irqs */
>         struct rtc_device *rtc = platform_get_drvdata(pdev);
> +       struct device *dev = &pdev->dev;
> +       struct pmic_data *pmic = dev_get_platdata(dev);
>         int irq = platform_get_irq(pdev, 0);
> 
> -       mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
> -       mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
> +       mask_rtc_irq_bit(pmic, BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
> +       mask_rtc_irq_bit(pmic, BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
>         if (twl_class_is_6030()) {
>                 twl6030_interrupt_mask(TWL6030_RTC_INT_MASK,
>                         REG_INT_MSK_LINE_A);
> @@ -534,9 +635,12 @@ static int __devexit twl_rtc_remove(struct platform_device *pdev)
> 
>  static void twl_rtc_shutdown(struct platform_device *pdev)
>  {
> +       struct device *dev = &pdev->dev;
> +       struct pmic_data *pmic = dev_get_platdata(dev);
> +
>         /* mask timer interrupts, but leave alarm interrupts on to enable
>            power-on when alarm is triggered */
> -       mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
> +       mask_rtc_irq_bit(pmic, BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
>  }
> 
>  #ifdef CONFIG_PM
> @@ -545,15 +649,19 @@ static unsigned char irqstat;
> 
>  static int twl_rtc_suspend(struct platform_device *pdev, pm_message_t state)
>  {
> +       struct device *dev = &pdev->dev;
> +       struct pmic_data *pmic = dev_get_platdata(dev);
>         irqstat = rtc_irq_bits;
> 
> -       mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
> +       mask_rtc_irq_bit(pmic, BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
>         return 0;
>  }
> 
>  static int twl_rtc_resume(struct platform_device *pdev)
>  {
> -       set_rtc_irq_bit(irqstat);
> +       struct device *dev = &pdev->dev;
> +       struct pmic_data *pmic = dev_get_platdata(dev);
> +       set_rtc_irq_bit(pmic, irqstat);
>         return 0;
>  }
> 
> @@ -580,8 +688,11 @@ static int __init twl_rtc_init(void)
>  {
>         if (twl_class_is_4030())
>                 rtc_reg_map = (u8 *) twl4030_rtc_reg_map;
> -       else
> +       else if (twl_class_is_6030())
>                 rtc_reg_map = (u8 *) twl6030_rtc_reg_map;
> +       /* TODO: Verify that rtc parent is tps65910 */
> +       else
> +               rtc_reg_map = (u8 *) tps65910_rtc_reg_map;

This should all be moved into probe().

> 
>         return platform_driver_register(&twl4030rtc_driver);
>  }
> diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h
> index 8bb85b9..520e7e2 100644
> --- a/include/linux/mfd/tps65910.h
> +++ b/include/linux/mfd/tps65910.h
> @@ -786,6 +786,11 @@ struct tps65910_platform_data {
>         int irq_base;
>  };
> 
> +struct pmic_data {
> +       int id;
> +       void * pmic;
> +};

This struct should really be in twl.h and renamed as rtc_data. It should also contain the rtc_reg_map pointer too and this should be set in probe(). 

> +
>  int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask);
>  int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask);
>  void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base);
> --
> 1.7.1
> 


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2011-05-08 17:57 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-06 22:11 [RTC] TWL: RTC: Allow rtc driver to be used by tps65910 Jorge Eduardo Candelaria
2011-05-08 17:56 ` Liam Girdwood

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.