Skip to contentSkip to conversation

rtc: omap: Add support for regulator supply

PATCH Superseded Lokesh Vutla 3 participants 12 messages Sep 25, 2014 – Oct 8, 2014

Subsystems (2)

v2 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

v2 cover rtc: omap: Add support for regulator supply

This series cleans up the OMAP RTC driver to use per device data structure. And adds support for regulator supply.

Testing:
RTC functionality test on:
DRA742-evm: http://hastebin.com/avowiyegut.xml
DRA722-evm: http://hastebin.com/hujuyuyato.xml
Beagle Bone Black: http://hastebin.com/fawahapuyi.rb
AM4372-GP-evm: http://hastebin.com/iyitiqeyev.rb (Used an out of tree patch for enabling rtc)

Tested rtc wake using an internal tree with these patches applied:
DRA742-evm: http://hastebin.com/banejadaci.coffee
DRA722-evm: http://hastebin.com/adifefetax.vhdl
Beagle Bone Black: http://hastebin.com/uxezamokiy.coffee
AM4372-GP-evm: http://hastebin.com/ruvetigico.coffee

Lokesh Vutla (3):
rtc: omap: Introduce rtc_omap_dev structure to include per device data
rtc: omap: Adopt driver to support probe deferral
rtc: omap: Support regulator supply for RTC

Tero Kristo (1):
rtc: omap: Update Kconfig for OMAP RTC

 Documentation/devicetree/bindings/rtc/rtc-omap.txt |   3 +
 drivers/rtc/Kconfig                                |   6 +-
 drivers/rtc/rtc-omap.c                             | 290 +++++++++++++--------
 3 files changed, 182 insertions(+), 117 deletions(-)
Signature · 1 line
1.9.1
#1 lore raw

PATCH v2 1/4 rtc: omap: Introduce rtc_omap_dev structure to include per device data

Currently all the device data is declared globally which will be a problem if more than one instance of device is present. So consolidate all the data into rtc_omap_dev struct and adopt the driver to use this.

---
Changes since v1:
- New patch as suggested by Felipe.

 drivers/rtc/rtc-omap.c | 257 ++++++++++++++++++++++++++++---------------------
 1 file changed, 147 insertions(+), 110 deletions(-)
drivers/rtc/rtc-omap.c +147 -110
index 21142e6..4e90b50 100644
@@ -41,8 +41,6 @@
 
 #define	DRIVER_NAME			"omap_rtc"
 
-#define OMAP_RTC_BASE			0xfffb4800
-
 /* RTC registers */
 #define OMAP_RTC_SECONDS_REG		0x00
 #define OMAP_RTC_MINUTES_REG		0x04
@@ -120,26 +118,53 @@
  */
 #define OMAP_RTC_HAS_32KCLK_EN		BIT(2)
 
-static void __iomem	*rtc_base;
+/**
+ * struct rtc_omap_dev - Per device static data for driver's use
+ * @rtc_device :	Pointer to generic RTC interface.
+ * @device:		Device Pointer.
+ * pdata :		Copy of saved platform data.
+ * rtc_base :		Base address of memory-mapped IO registers.
+ * rtc_alarm :		RTC alarm interrupt number.
+ * rtc_timer :		RTC timer interrupt number.
+ * irq_stat :		Copy of Interrupt status register.
+ */
+struct rtc_omap_dev {
+	struct rtc_device	*rtc;
+	struct device		*dev;
+	unsigned long		pdata;
+	void __iomem		*rtc_base;
+	u32			rtc_alarm;
+	u32			rtc_timer;
+	u8			irqstat;
+};
 
-#define rtc_read(addr)		readb(rtc_base + (addr))
-#define rtc_write(val, addr)	writeb(val, rtc_base + (addr))
+static inline u8 rtc_read(struct rtc_omap_dev *rtc_omap, u32 off)
+{
+	return readb(rtc_omap->rtc_base + off);
+}
 
-#define rtc_writel(val, addr)	writel(val, rtc_base + (addr))
+static inline void rtc_write(u8 val, struct rtc_omap_dev *rtc_omap, u32 off)
+{
+	writeb(val, rtc_omap->rtc_base + off);
+}
 
+static inline void rtc_writel(u32 val, struct rtc_omap_dev *rtc_omap, u32 off)
+{
+	writel(val, rtc_omap->rtc_base + off);
+}
 
 /* we rely on the rtc framework to handle locking (rtc->ops_lock),
  * so the only other requirement is that register accesses which
  * require BUSY to be clear are made with IRQs locally disabled
  */
-static void rtc_wait_not_busy(void)
+static void rtc_wait_not_busy(struct rtc_omap_dev *rtc_omap)
 {
 	int	count = 0;
 	u8	status;
 
 	/* BUSY may stay active for 1/32768 second (~30 usec) */
 	for (count = 0; count < 50; count++) {
-		status = rtc_read(OMAP_RTC_STATUS_REG);
+		status = rtc_read(rtc_omap, OMAP_RTC_STATUS_REG);
 		if ((status & (u8)OMAP_RTC_STATUS_BUSY) == 0)
 			break;
 		udelay(1);
@@ -147,16 +172,17 @@ static void rtc_wait_not_busy(void)
 	/* now we have ~15 usec to read/write various registers */
 }
 
-static irqreturn_t rtc_irq(int irq, void *rtc)
+static irqreturn_t rtc_irq(int irq, void *id)
 {
+	struct rtc_omap_dev *rtc_omap = (struct rtc_omap_dev *)id;
 	unsigned long		events = 0;
 	u8			irq_data;
 
-	irq_data = rtc_read(OMAP_RTC_STATUS_REG);
+	irq_data = rtc_read(rtc_omap, OMAP_RTC_STATUS_REG);
 
 	/* alarm irq? */
 	if (irq_data & OMAP_RTC_STATUS_ALARM) {
-		rtc_write(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG);
+		rtc_write(OMAP_RTC_STATUS_ALARM, rtc_omap, OMAP_RTC_STATUS_REG);
 		events |= RTC_IRQF | RTC_AF;
 	}
 
@@ -164,7 +190,7 @@ static irqreturn_t rtc_irq(int irq, void *rtc)
 	if (irq_data & OMAP_RTC_STATUS_1S_EVENT)
 		events |= RTC_IRQF | RTC_UF;
 
-	rtc_update_irq(rtc, 1, events);
+	rtc_update_irq(rtc_omap->rtc, 1, events);
 
 	return IRQ_HANDLED;
 }
@@ -172,15 +198,13 @@ static irqreturn_t rtc_irq(int irq, void *rtc)
 static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	u8 reg, irqwake_reg = 0;
-	struct platform_device *pdev = to_platform_device(dev);
-	const struct platform_device_id *id_entry =
-					platform_get_device_id(pdev);
+	struct rtc_omap_dev *rtc_omap = dev_get_drvdata(dev);
 
 	local_irq_disable();
-	rtc_wait_not_busy();
-	reg = rtc_read(OMAP_RTC_INTERRUPTS_REG);
-	if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN)
-		irqwake_reg = rtc_read(OMAP_RTC_IRQWAKEEN);
+	rtc_wait_not_busy(rtc_omap);
+	reg = rtc_read(rtc_omap, OMAP_RTC_INTERRUPTS_REG);
+	if (rtc_omap->pdata & OMAP_RTC_HAS_IRQWAKEEN)
+		irqwake_reg = rtc_read(rtc_omap, OMAP_RTC_IRQWAKEEN);
 
 	if (enabled) {
 		reg |= OMAP_RTC_INTERRUPTS_IT_ALARM;
@@ -189,10 +213,10 @@ static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 		reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM;
 		irqwake_reg &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
 	}
-	rtc_wait_not_busy();
-	rtc_write(reg, OMAP_RTC_INTERRUPTS_REG);
-	if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN)
-		rtc_write(irqwake_reg, OMAP_RTC_IRQWAKEEN);
+	rtc_wait_not_busy(rtc_omap);
+	rtc_write(reg, rtc_omap, OMAP_RTC_INTERRUPTS_REG);
+	if (rtc_omap->pdata & OMAP_RTC_HAS_IRQWAKEEN)
+		rtc_write(irqwake_reg, rtc_omap, OMAP_RTC_IRQWAKEEN);
 	local_irq_enable();
 
 	return 0;
@@ -233,16 +257,18 @@ static void bcd2tm(struct rtc_time *tm)
 
 static int omap_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
+	struct rtc_omap_dev *rtc_omap = dev_get_drvdata(dev);
+
 	/* we don't report wday/yday/isdst ... */
 	local_irq_disable();
-	rtc_wait_not_busy();
+	rtc_wait_not_busy(rtc_omap);
 
-	tm->tm_sec = rtc_read(OMAP_RTC_SECONDS_REG);
-	tm->tm_min = rtc_read(OMAP_RTC_MINUTES_REG);
-	tm->tm_hour = rtc_read(OMAP_RTC_HOURS_REG);
-	tm->tm_mday = rtc_read(OMAP_RTC_DAYS_REG);
-	tm->tm_mon = rtc_read(OMAP_RTC_MONTHS_REG);
-	tm->tm_year = rtc_read(OMAP_RTC_YEARS_REG);
+	tm->tm_sec = rtc_read(rtc_omap, OMAP_RTC_SECONDS_REG);
+	tm->tm_min = rtc_read(rtc_omap, OMAP_RTC_MINUTES_REG);
+	tm->tm_hour = rtc_read(rtc_omap, OMAP_RTC_HOURS_REG);
+	tm->tm_mday = rtc_read(rtc_omap, OMAP_RTC_DAYS_REG);
+	tm->tm_mon = rtc_read(rtc_omap, OMAP_RTC_MONTHS_REG);
+	tm->tm_year = rtc_read(rtc_omap, OMAP_RTC_YEARS_REG);
 
 	local_irq_enable();
 
@@ -252,17 +278,19 @@ static int omap_rtc_read_time(struct device *dev, struct rtc_time *tm)
 
 static int omap_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
+	struct rtc_omap_dev *rtc_omap = dev_get_drvdata(dev);
+
 	if (tm2bcd(tm) < 0)
 		return -EINVAL;
 	local_irq_disable();
-	rtc_wait_not_busy();
+	rtc_wait_not_busy(rtc_omap);
 
-	rtc_write(tm->tm_year, OMAP_RTC_YEARS_REG);
-	rtc_write(tm->tm_mon, OMAP_RTC_MONTHS_REG);
-	rtc_write(tm->tm_mday, OMAP_RTC_DAYS_REG);
-	rtc_write(tm->tm_hour, OMAP_RTC_HOURS_REG);
-	rtc_write(tm->tm_min, OMAP_RTC_MINUTES_REG);
-	rtc_write(tm->tm_sec, OMAP_RTC_SECONDS_REG);
+	rtc_write(tm->tm_year, rtc_omap, OMAP_RTC_YEARS_REG);
+	rtc_write(tm->tm_mon, rtc_omap, OMAP_RTC_MONTHS_REG);
+	rtc_write(tm->tm_mday, rtc_omap, OMAP_RTC_DAYS_REG);
+	rtc_write(tm->tm_hour, rtc_omap, OMAP_RTC_HOURS_REG);
+	rtc_write(tm->tm_min, rtc_omap, OMAP_RTC_MINUTES_REG);
+	rtc_write(tm->tm_sec, rtc_omap, OMAP_RTC_SECONDS_REG);
 
 	local_irq_enable();
 
@@ -271,20 +299,22 @@ static int omap_rtc_set_time(struct device *dev, struct rtc_time *tm)
 
 static int omap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 {
+	struct rtc_omap_dev *rtc_omap = dev_get_drvdata(dev);
+
 	local_irq_disable();
-	rtc_wait_not_busy();
+	rtc_wait_not_busy(rtc_omap);
 
-	alm->time.tm_sec = rtc_read(OMAP_RTC_ALARM_SECONDS_REG);
-	alm->time.tm_min = rtc_read(OMAP_RTC_ALARM_MINUTES_REG);
-	alm->time.tm_hour = rtc_read(OMAP_RTC_ALARM_HOURS_REG);
-	alm->time.tm_mday = rtc_read(OMAP_RTC_ALARM_DAYS_REG);
-	alm->time.tm_mon = rtc_read(OMAP_RTC_ALARM_MONTHS_REG);
-	alm->time.tm_year = rtc_read(OMAP_RTC_ALARM_YEARS_REG);
+	alm->time.tm_sec = rtc_read(rtc_omap, OMAP_RTC_ALARM_SECONDS_REG);
+	alm->time.tm_min = rtc_read(rtc_omap, OMAP_RTC_ALARM_MINUTES_REG);
+	alm->time.tm_hour = rtc_read(rtc_omap, OMAP_RTC_ALARM_HOURS_REG);
+	alm->time.tm_mday = rtc_read(rtc_omap, OMAP_RTC_ALARM_DAYS_REG);
+	alm->time.tm_mon = rtc_read(rtc_omap, OMAP_RTC_ALARM_MONTHS_REG);
+	alm->time.tm_year = rtc_read(rtc_omap, OMAP_RTC_ALARM_YEARS_REG);
 
 	local_irq_enable();
 
 	bcd2tm(&alm->time);
-	alm->enabled = !!(rtc_read(OMAP_RTC_INTERRUPTS_REG)
+	alm->enabled = !!(rtc_read(rtc_omap, OMAP_RTC_INTERRUPTS_REG)
 			& OMAP_RTC_INTERRUPTS_IT_ALARM);
 
 	return 0;
@@ -293,26 +323,24 @@ static int omap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 {
 	u8 reg, irqwake_reg = 0;
-	struct platform_device *pdev = to_platform_device(dev);
-	const struct platform_device_id *id_entry =
-					platform_get_device_id(pdev);
+	struct rtc_omap_dev *rtc_omap = dev_get_drvdata(dev);
 
 	if (tm2bcd(&alm->time) < 0)
 		return -EINVAL;
 
 	local_irq_disable();
-	rtc_wait_not_busy();
+	rtc_wait_not_busy(rtc_omap);
 
-	rtc_write(alm->time.tm_year, OMAP_RTC_ALARM_YEARS_REG);
-	rtc_write(alm->time.tm_mon, OMAP_RTC_ALARM_MONTHS_REG);
-	rtc_write(alm->time.tm_mday, OMAP_RTC_ALARM_DAYS_REG);
-	rtc_write(alm->time.tm_hour, OMAP_RTC_ALARM_HOURS_REG);
-	rtc_write(alm->time.tm_min, OMAP_RTC_ALARM_MINUTES_REG);
-	rtc_write(alm->time.tm_sec, OMAP_RTC_ALARM_SECONDS_REG);
+	rtc_write(alm->time.tm_year, rtc_omap, OMAP_RTC_ALARM_YEARS_REG);
+	rtc_write(alm->time.tm_mon, rtc_omap, OMAP_RTC_ALARM_MONTHS_REG);
+	rtc_write(alm->time.tm_mday, rtc_omap, OMAP_RTC_ALARM_DAYS_REG);
+	rtc_write(alm->time.tm_hour, rtc_omap, OMAP_RTC_ALARM_HOURS_REG);
+	rtc_write(alm->time.tm_min, rtc_omap, OMAP_RTC_ALARM_MINUTES_REG);
+	rtc_write(alm->time.tm_sec, rtc_omap, OMAP_RTC_ALARM_SECONDS_REG);
 
-	reg = rtc_read(OMAP_RTC_INTERRUPTS_REG);
-	if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN)
-		irqwake_reg = rtc_read(OMAP_RTC_IRQWAKEEN);
+	reg = rtc_read(rtc_omap, OMAP_RTC_INTERRUPTS_REG);
+	if (rtc_omap->pdata & OMAP_RTC_HAS_IRQWAKEEN)
+		irqwake_reg = rtc_read(rtc_omap, OMAP_RTC_IRQWAKEEN);
 
 	if (alm->enabled) {
 		reg |= OMAP_RTC_INTERRUPTS_IT_ALARM;
@@ -321,9 +349,9 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 		reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM;
 		irqwake_reg &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
 	}
-	rtc_write(reg, OMAP_RTC_INTERRUPTS_REG);
-	if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN)
-		rtc_write(irqwake_reg, OMAP_RTC_IRQWAKEEN);
+	rtc_write(reg, rtc_omap, OMAP_RTC_INTERRUPTS_REG);
+	if (rtc_omap->pdata & OMAP_RTC_HAS_IRQWAKEEN)
+		rtc_write(irqwake_reg, rtc_omap, OMAP_RTC_IRQWAKEEN);
 
 	local_irq_enable();
 
@@ -338,13 +366,10 @@ static struct rtc_class_ops omap_rtc_ops = {
 	.alarm_irq_enable = omap_rtc_alarm_irq_enable,
 };
 
-static int omap_rtc_alarm;
-static int omap_rtc_timer;
-
 #define	OMAP_RTC_DATA_AM3352_IDX	1
 #define	OMAP_RTC_DATA_DA830_IDX		2
 
-static struct platform_device_id omap_rtc_devtype[] = {
+static const struct platform_device_id omap_rtc_devtype[] = {
 	{
 		.name	= DRIVER_NAME,
 	},
@@ -375,11 +400,18 @@ MODULE_DEVICE_TABLE(of, omap_rtc_of_match);
 static int __init omap_rtc_probe(struct platform_device *pdev)
 {
 	struct resource		*res;
-	struct rtc_device	*rtc;
+	struct rtc_omap_dev	*rtc_omap;
 	u8			reg, new_ctrl;
 	const struct platform_device_id *id_entry;
 	const struct of_device_id *of_id;
 
+	rtc_omap = devm_kzalloc(&pdev->dev, sizeof(*rtc_omap), GFP_KERNEL);
+	if (!rtc_omap)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, rtc_omap);
+	rtc_omap->dev = &pdev->dev;
+
 	of_id = of_match_device(omap_rtc_of_match, &pdev->dev);
 	if (of_id)
 		pdev->id_entry = of_id->data;
@@ -389,78 +421,79 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "no matching device entry\n");
 		return -ENODEV;
 	}
+	rtc_omap->pdata = id_entry->driver_data;
 
-	omap_rtc_timer = platform_get_irq(pdev, 0);
-	if (omap_rtc_timer <= 0) {
+	rtc_omap->rtc_timer = platform_get_irq(pdev, 0);
+	if (rtc_omap->rtc_timer <= 0) {
 		pr_debug("%s: no update irq?\n", pdev->name);
 		return -ENOENT;
 	}
 
-	omap_rtc_alarm = platform_get_irq(pdev, 1);
-	if (omap_rtc_alarm <= 0) {
+	rtc_omap->rtc_alarm = platform_get_irq(pdev, 1);
+	if (rtc_omap->rtc_alarm <= 0) {
 		pr_debug("%s: no alarm irq?\n", pdev->name);
 		return -ENOENT;
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	rtc_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(rtc_base))
-		return PTR_ERR(rtc_base);
+	rtc_omap->rtc_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(rtc_omap->rtc_base))
+		return PTR_ERR(rtc_omap->rtc_base);
 
 	/* Enable the clock/module so that we can access the registers */
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_get_sync(&pdev->dev);
 
-	if (id_entry->driver_data & OMAP_RTC_HAS_KICKER) {
-		rtc_writel(KICK0_VALUE, OMAP_RTC_KICK0_REG);
-		rtc_writel(KICK1_VALUE, OMAP_RTC_KICK1_REG);
+	if (rtc_omap->pdata & OMAP_RTC_HAS_KICKER) {
+		rtc_writel(KICK0_VALUE, rtc_omap, OMAP_RTC_KICK0_REG);
+		rtc_writel(KICK1_VALUE, rtc_omap, OMAP_RTC_KICK1_REG);
 	}
 
-	rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
+	rtc_omap->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 			&omap_rtc_ops, THIS_MODULE);
-	if (IS_ERR(rtc)) {
+	if (IS_ERR(rtc_omap->rtc)) {
 		pr_debug("%s: can't register RTC device, err %ld\n",
-			pdev->name, PTR_ERR(rtc));
+			pdev->name, PTR_ERR(rtc_omap->rtc));
 		goto fail0;
 	}
-	platform_set_drvdata(pdev, rtc);
 
 	/* clear pending irqs, and set 1/second periodic,
 	 * which we'll use instead of update irqs
 	 */
-	rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
+	rtc_write(0, rtc_omap, OMAP_RTC_INTERRUPTS_REG);
 
 	/* enable RTC functional clock */
-	if (id_entry->driver_data & OMAP_RTC_HAS_32KCLK_EN)
-		rtc_writel(OMAP_RTC_OSC_32KCLK_EN, OMAP_RTC_OSC_REG);
+	if (rtc_omap->pdata & OMAP_RTC_HAS_32KCLK_EN)
+		rtc_writel(OMAP_RTC_OSC_32KCLK_EN, rtc_omap, OMAP_RTC_OSC_REG);
 
 	/* clear old status */
-	reg = rtc_read(OMAP_RTC_STATUS_REG);
+	reg = rtc_read(rtc_omap, OMAP_RTC_STATUS_REG);
 	if (reg & (u8) OMAP_RTC_STATUS_POWER_UP) {
 		pr_info("%s: RTC power up reset detected\n",
 			pdev->name);
-		rtc_write(OMAP_RTC_STATUS_POWER_UP, OMAP_RTC_STATUS_REG);
+		rtc_write(OMAP_RTC_STATUS_POWER_UP, rtc_omap,
+			  OMAP_RTC_STATUS_REG);
 	}
 	if (reg & (u8) OMAP_RTC_STATUS_ALARM)
-		rtc_write(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG);
+		rtc_write(OMAP_RTC_STATUS_ALARM, rtc_omap, OMAP_RTC_STATUS_REG);
 
 	/* handle periodic and alarm irqs */
-	if (devm_request_irq(&pdev->dev, omap_rtc_timer, rtc_irq, 0,
-			dev_name(&rtc->dev), rtc)) {
+	if (devm_request_irq(&pdev->dev, rtc_omap->rtc_timer, rtc_irq, 0,
+			     dev_name(&pdev->dev), rtc_omap)) {
 		pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n",
-			pdev->name, omap_rtc_timer);
+			pdev->name, rtc_omap->rtc_timer);
 		goto fail0;
 	}
-	if ((omap_rtc_timer != omap_rtc_alarm) &&
-		(devm_request_irq(&pdev->dev, omap_rtc_alarm, rtc_irq, 0,
-			dev_name(&rtc->dev), rtc))) {
+	if ((rtc_omap->rtc_timer != rtc_omap->rtc_alarm) &&
+	    (devm_request_irq(&pdev->dev, rtc_omap->rtc_alarm, rtc_irq, 0,
+			      dev_name(&pdev->dev), rtc_omap))) {
 		pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n",
-			pdev->name, omap_rtc_alarm);
+			pdev->name, rtc_omap->rtc_alarm);
 		goto fail0;
 	}
 
 	/* On boards with split power, RTC_ON_NOFF won't reset the RTC */
-	reg = rtc_read(OMAP_RTC_CTRL_REG);
+	reg = rtc_read(rtc_omap, OMAP_RTC_CTRL_REG);
 	if (reg & (u8) OMAP_RTC_CTRL_STOP)
 		pr_info("%s: already running\n", pdev->name);
 
@@ -488,13 +521,13 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
 		pr_info("%s: split power mode\n", pdev->name);
 
 	if (reg != new_ctrl)
-		rtc_write(new_ctrl, OMAP_RTC_CTRL_REG);
+		rtc_write(new_ctrl, rtc_omap, OMAP_RTC_CTRL_REG);
 
 	return 0;
 
 fail0:
-	if (id_entry->driver_data & OMAP_RTC_HAS_KICKER)
-		rtc_writel(0, OMAP_RTC_KICK0_REG);
+	if (rtc_omap->pdata & OMAP_RTC_HAS_KICKER)
+		rtc_writel(0, rtc_omap, OMAP_RTC_KICK0_REG);
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	return -EIO;
@@ -502,16 +535,15 @@ fail0:
 
 static int __exit omap_rtc_remove(struct platform_device *pdev)
 {
-	const struct platform_device_id *id_entry =
-				platform_get_device_id(pdev);
+	struct rtc_omap_dev *rtc_omap = platform_get_drvdata(pdev);
 
 	device_init_wakeup(&pdev->dev, 0);
 
 	/* leave rtc running, but disable irqs */
-	rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
+	rtc_write(0, rtc_omap, OMAP_RTC_INTERRUPTS_REG);
 
-	if (id_entry->driver_data & OMAP_RTC_HAS_KICKER)
-		rtc_writel(0, OMAP_RTC_KICK0_REG);
+	if (rtc_omap->pdata & OMAP_RTC_HAS_KICKER)
+		rtc_writel(0, rtc_omap, OMAP_RTC_KICK0_REG);
 
 	/* Disable the clock/module */
 	pm_runtime_put_sync(&pdev->dev);
@@ -521,20 +553,21 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM_SLEEP
-static u8 irqstat;
 
 static int omap_rtc_suspend(struct device *dev)
 {
-	irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG);
+	struct rtc_omap_dev *rtc_omap = dev_get_drvdata(dev);
+
+	rtc_omap->irqstat = rtc_read(rtc_omap, OMAP_RTC_INTERRUPTS_REG);
 
 	/* FIXME the RTC alarm is not currently acting as a wakeup event
 	 * source on some platforms, and in fact this enable() call is just
 	 * saving a flag that's never used...
 	 */
 	if (device_may_wakeup(dev))
-		enable_irq_wake(omap_rtc_alarm);
+		enable_irq_wake(rtc_omap->rtc_alarm);
 	else
-		rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
+		rtc_write(0, rtc_omap, OMAP_RTC_INTERRUPTS_REG);
 
 	/* Disable the clock/module */
 	pm_runtime_put_sync(dev);
@@ -544,13 +577,15 @@ static int omap_rtc_suspend(struct device *dev)
 
 static int omap_rtc_resume(struct device *dev)
 {
+	struct rtc_omap_dev *rtc_omap = dev_get_drvdata(dev);
+
 	/* Enable the clock/module so that we can access the registers */
 	pm_runtime_get_sync(dev);
 
 	if (device_may_wakeup(dev))
-		disable_irq_wake(omap_rtc_alarm);
+		disable_irq_wake(rtc_omap->rtc_alarm);
 	else
-		rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG);
+		rtc_write(rtc_omap->irqstat, rtc_omap, OMAP_RTC_INTERRUPTS_REG);
 
 	return 0;
 }
@@ -560,10 +595,11 @@ static SIMPLE_DEV_PM_OPS(omap_rtc_pm_ops, omap_rtc_suspend, omap_rtc_resume);
 
 static void omap_rtc_shutdown(struct platform_device *pdev)
 {
-	rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
+	struct rtc_omap_dev *rtc_omap = platform_get_drvdata(pdev);
+
+	rtc_write(0, rtc_omap, OMAP_RTC_INTERRUPTS_REG);
 }
 
-MODULE_ALIAS("platform:omap_rtc");
 static struct platform_driver omap_rtc_driver = {
 	.remove		= __exit_p(omap_rtc_remove),
 	.shutdown	= omap_rtc_shutdown,
@@ -578,5 +614,6 @@ static struct platform_driver omap_rtc_driver = {
 
 module_platform_driver_probe(omap_rtc_driver, omap_rtc_probe);
 
+MODULE_ALIAS("platform:omap_rtc");
 MODULE_AUTHOR("George G. Davis (and others)");
 MODULE_LICENSE("GPL");
Signature · 1 line
1.9.1
#2 lore raw

PATCH v2 1/4 rtc: omap: Introduce rtc_omap_dev structure to include per device data

Quoted 26 lines · Lokesh Vutla

Currently all the device data is declared globally which will be a problem if more than one instance of device is present. So consolidate all the data into rtc_omap_dev struct and adopt the driver to use this.

---
Changes since v1:
- New patch as suggested by Felipe.

 drivers/rtc/rtc-omap.c | 257 ++++++++++++++++++++++++++++---------------------
 1 file changed, 147 insertions(+), 110 deletions(-)
drivers/rtc/rtc-omap.c +0 -2
index 21142e6..4e90b50 100644
@@ -41,8 +41,6 @@
 
 #define	DRIVER_NAME			"omap_rtc"
 
-#define OMAP_RTC_BASE			0xfffb4800
-
 /* RTC registers */
 #define OMAP_RTC_SECONDS_REG		0x00
 #define OMAP_RTC_MINUTES_REG		0x04

drivers/rtc/rtc-omap.c line 123

Quoted 7 lines
drivers/rtc/rtc-omap.c +3 -1
@@ -120,26 +118,53 @@
  */
 #define OMAP_RTC_HAS_32KCLK_EN		BIT(2)
 
-static void __iomem	*rtc_base;
+/**
+ * struct rtc_omap_dev - Per device static data for driver's use
+ * @rtc_device :	Pointer to generic RTC interface.

Member name in comment doesn't match actual name ("rtc").

drivers/rtc/rtc-omap.c line 125

Quoted 2 lines
drivers/rtc/rtc-omap.c +2 -0
+ * @device:		Device Pointer.
+ * pdata :		Copy of saved platform data.

Use a more descriptive name here to describe what it's really for (feature flags), perhaps just call it "flags".

Please prepend all members with a '@' (and remove the space before ':').

drivers/rtc/rtc-omap.c line 128

Quoted 3 lines
drivers/rtc/rtc-omap.c +3 -0
+ * rtc_base :		Base address of memory-mapped IO registers.
+ * rtc_alarm :		RTC alarm interrupt number.
+ * rtc_timer :		RTC timer interrupt number.

All these rtc_ prefixes are now quite redundant (and non-descriptive).

Call the interrupt fields irq_alarm and irq_timer instead.

drivers/rtc/rtc-omap.c line 129

Quoted 1 line
drivers/rtc/rtc-omap.c +1 -0
+ * irq_stat :		Copy of Interrupt status register.

And then rename this after the register, e.g. "interrupts_reg", or call it irq_mask.

Update the comment as well to describe what the field is used for (i.e. to store the interrupt mask while suspended).

Quoted 10 lines
drivers/rtc/rtc-omap.c +10 -0
+ */
+struct rtc_omap_dev {
+	struct rtc_device	*rtc;
+	struct device		*dev;
+	unsigned long		pdata;
+	void __iomem		*rtc_base;
+	u32			rtc_alarm;
+	u32			rtc_timer;
+	u8			irqstat;
+};

drivers/rtc/rtc-omap.c line 146

Quoted 10 lines
drivers/rtc/rtc-omap.c +5 -3
 
-#define rtc_read(addr)		readb(rtc_base + (addr))
-#define rtc_write(val, addr)	writeb(val, rtc_base + (addr))
+static inline u8 rtc_read(struct rtc_omap_dev *rtc_omap, u32 off)
+{
+	return readb(rtc_omap->rtc_base + off);
+}
 
-#define rtc_writel(val, addr)	writel(val, rtc_base + (addr))
+static inline void rtc_write(u8 val, struct rtc_omap_dev *rtc_omap, u32 off)

Please make the rtc_omap_dev the first argument of both read and write.

It doesn't hurt making the value argument the last one.

drivers/rtc/rtc-omap.c line 151

Quoted 5 lines
drivers/rtc/rtc-omap.c +4 -0
+{
+	writeb(val, rtc_omap->rtc_base + off);
+}
 
+static inline void rtc_writel(u32 val, struct rtc_omap_dev *rtc_omap, u32 off)

Same here.

Quoted 224 lines
drivers/rtc/rtc-omap.c +61 -55
+{
+	writel(val, rtc_omap->rtc_base + off);
+}
 
 /* we rely on the rtc framework to handle locking (rtc->ops_lock),
  * so the only other requirement is that register accesses which
  * require BUSY to be clear are made with IRQs locally disabled
  */
-static void rtc_wait_not_busy(void)
+static void rtc_wait_not_busy(struct rtc_omap_dev *rtc_omap)
 {
 	int	count = 0;
 	u8	status;
 
 	/* BUSY may stay active for 1/32768 second (~30 usec) */
 	for (count = 0; count < 50; count++) {
-		status = rtc_read(OMAP_RTC_STATUS_REG);
+		status = rtc_read(rtc_omap, OMAP_RTC_STATUS_REG);
 		if ((status & (u8)OMAP_RTC_STATUS_BUSY) == 0)
 			break;
 		udelay(1);
@@ -147,16 +172,17 @@ static void rtc_wait_not_busy(void)
 	/* now we have ~15 usec to read/write various registers */
 }
 
-static irqreturn_t rtc_irq(int irq, void *rtc)
+static irqreturn_t rtc_irq(int irq, void *id)
 {
+	struct rtc_omap_dev *rtc_omap = (struct rtc_omap_dev *)id;
 	unsigned long		events = 0;
 	u8			irq_data;
 
-	irq_data = rtc_read(OMAP_RTC_STATUS_REG);
+	irq_data = rtc_read(rtc_omap, OMAP_RTC_STATUS_REG);
 
 	/* alarm irq? */
 	if (irq_data & OMAP_RTC_STATUS_ALARM) {
-		rtc_write(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG);
+		rtc_write(OMAP_RTC_STATUS_ALARM, rtc_omap, OMAP_RTC_STATUS_REG);
 		events |= RTC_IRQF | RTC_AF;
 	}
 
@@ -164,7 +190,7 @@ static irqreturn_t rtc_irq(int irq, void *rtc)
 	if (irq_data & OMAP_RTC_STATUS_1S_EVENT)
 		events |= RTC_IRQF | RTC_UF;
 
-	rtc_update_irq(rtc, 1, events);
+	rtc_update_irq(rtc_omap->rtc, 1, events);
 
 	return IRQ_HANDLED;
 }
@@ -172,15 +198,13 @@ static irqreturn_t rtc_irq(int irq, void *rtc)
 static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	u8 reg, irqwake_reg = 0;
-	struct platform_device *pdev = to_platform_device(dev);
-	const struct platform_device_id *id_entry =
-					platform_get_device_id(pdev);
+	struct rtc_omap_dev *rtc_omap = dev_get_drvdata(dev);
 
 	local_irq_disable();
-	rtc_wait_not_busy();
-	reg = rtc_read(OMAP_RTC_INTERRUPTS_REG);
-	if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN)
-		irqwake_reg = rtc_read(OMAP_RTC_IRQWAKEEN);
+	rtc_wait_not_busy(rtc_omap);
+	reg = rtc_read(rtc_omap, OMAP_RTC_INTERRUPTS_REG);
+	if (rtc_omap->pdata & OMAP_RTC_HAS_IRQWAKEEN)
+		irqwake_reg = rtc_read(rtc_omap, OMAP_RTC_IRQWAKEEN);
 
 	if (enabled) {
 		reg |= OMAP_RTC_INTERRUPTS_IT_ALARM;
@@ -189,10 +213,10 @@ static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 		reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM;
 		irqwake_reg &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
 	}
-	rtc_wait_not_busy();
-	rtc_write(reg, OMAP_RTC_INTERRUPTS_REG);
-	if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN)
-		rtc_write(irqwake_reg, OMAP_RTC_IRQWAKEEN);
+	rtc_wait_not_busy(rtc_omap);
+	rtc_write(reg, rtc_omap, OMAP_RTC_INTERRUPTS_REG);
+	if (rtc_omap->pdata & OMAP_RTC_HAS_IRQWAKEEN)
+		rtc_write(irqwake_reg, rtc_omap, OMAP_RTC_IRQWAKEEN);
 	local_irq_enable();
 
 	return 0;
@@ -233,16 +257,18 @@ static void bcd2tm(struct rtc_time *tm)
 
 static int omap_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
+	struct rtc_omap_dev *rtc_omap = dev_get_drvdata(dev);
+
 	/* we don't report wday/yday/isdst ... */
 	local_irq_disable();
-	rtc_wait_not_busy();
+	rtc_wait_not_busy(rtc_omap);
 
-	tm->tm_sec = rtc_read(OMAP_RTC_SECONDS_REG);
-	tm->tm_min = rtc_read(OMAP_RTC_MINUTES_REG);
-	tm->tm_hour = rtc_read(OMAP_RTC_HOURS_REG);
-	tm->tm_mday = rtc_read(OMAP_RTC_DAYS_REG);
-	tm->tm_mon = rtc_read(OMAP_RTC_MONTHS_REG);
-	tm->tm_year = rtc_read(OMAP_RTC_YEARS_REG);
+	tm->tm_sec = rtc_read(rtc_omap, OMAP_RTC_SECONDS_REG);
+	tm->tm_min = rtc_read(rtc_omap, OMAP_RTC_MINUTES_REG);
+	tm->tm_hour = rtc_read(rtc_omap, OMAP_RTC_HOURS_REG);
+	tm->tm_mday = rtc_read(rtc_omap, OMAP_RTC_DAYS_REG);
+	tm->tm_mon = rtc_read(rtc_omap, OMAP_RTC_MONTHS_REG);
+	tm->tm_year = rtc_read(rtc_omap, OMAP_RTC_YEARS_REG);
 
 	local_irq_enable();
 
@@ -252,17 +278,19 @@ static int omap_rtc_read_time(struct device *dev, struct rtc_time *tm)
 
 static int omap_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
+	struct rtc_omap_dev *rtc_omap = dev_get_drvdata(dev);
+
 	if (tm2bcd(tm) < 0)
 		return -EINVAL;
 	local_irq_disable();
-	rtc_wait_not_busy();
+	rtc_wait_not_busy(rtc_omap);
 
-	rtc_write(tm->tm_year, OMAP_RTC_YEARS_REG);
-	rtc_write(tm->tm_mon, OMAP_RTC_MONTHS_REG);
-	rtc_write(tm->tm_mday, OMAP_RTC_DAYS_REG);
-	rtc_write(tm->tm_hour, OMAP_RTC_HOURS_REG);
-	rtc_write(tm->tm_min, OMAP_RTC_MINUTES_REG);
-	rtc_write(tm->tm_sec, OMAP_RTC_SECONDS_REG);
+	rtc_write(tm->tm_year, rtc_omap, OMAP_RTC_YEARS_REG);
+	rtc_write(tm->tm_mon, rtc_omap, OMAP_RTC_MONTHS_REG);
+	rtc_write(tm->tm_mday, rtc_omap, OMAP_RTC_DAYS_REG);
+	rtc_write(tm->tm_hour, rtc_omap, OMAP_RTC_HOURS_REG);
+	rtc_write(tm->tm_min, rtc_omap, OMAP_RTC_MINUTES_REG);
+	rtc_write(tm->tm_sec, rtc_omap, OMAP_RTC_SECONDS_REG);
 
 	local_irq_enable();
 
@@ -271,20 +299,22 @@ static int omap_rtc_set_time(struct device *dev, struct rtc_time *tm)
 
 static int omap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 {
+	struct rtc_omap_dev *rtc_omap = dev_get_drvdata(dev);
+
 	local_irq_disable();
-	rtc_wait_not_busy();
+	rtc_wait_not_busy(rtc_omap);
 
-	alm->time.tm_sec = rtc_read(OMAP_RTC_ALARM_SECONDS_REG);
-	alm->time.tm_min = rtc_read(OMAP_RTC_ALARM_MINUTES_REG);
-	alm->time.tm_hour = rtc_read(OMAP_RTC_ALARM_HOURS_REG);
-	alm->time.tm_mday = rtc_read(OMAP_RTC_ALARM_DAYS_REG);
-	alm->time.tm_mon = rtc_read(OMAP_RTC_ALARM_MONTHS_REG);
-	alm->time.tm_year = rtc_read(OMAP_RTC_ALARM_YEARS_REG);
+	alm->time.tm_sec = rtc_read(rtc_omap, OMAP_RTC_ALARM_SECONDS_REG);
+	alm->time.tm_min = rtc_read(rtc_omap, OMAP_RTC_ALARM_MINUTES_REG);
+	alm->time.tm_hour = rtc_read(rtc_omap, OMAP_RTC_ALARM_HOURS_REG);
+	alm->time.tm_mday = rtc_read(rtc_omap, OMAP_RTC_ALARM_DAYS_REG);
+	alm->time.tm_mon = rtc_read(rtc_omap, OMAP_RTC_ALARM_MONTHS_REG);
+	alm->time.tm_year = rtc_read(rtc_omap, OMAP_RTC_ALARM_YEARS_REG);
 
 	local_irq_enable();
 
 	bcd2tm(&alm->time);
-	alm->enabled = !!(rtc_read(OMAP_RTC_INTERRUPTS_REG)
+	alm->enabled = !!(rtc_read(rtc_omap, OMAP_RTC_INTERRUPTS_REG)
 			& OMAP_RTC_INTERRUPTS_IT_ALARM);
 
 	return 0;
@@ -293,26 +323,24 @@ static int omap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 {
 	u8 reg, irqwake_reg = 0;
-	struct platform_device *pdev = to_platform_device(dev);
-	const struct platform_device_id *id_entry =
-					platform_get_device_id(pdev);
+	struct rtc_omap_dev *rtc_omap = dev_get_drvdata(dev);
 
 	if (tm2bcd(&alm->time) < 0)
 		return -EINVAL;
 
 	local_irq_disable();
-	rtc_wait_not_busy();
+	rtc_wait_not_busy(rtc_omap);
 
-	rtc_write(alm->time.tm_year, OMAP_RTC_ALARM_YEARS_REG);
-	rtc_write(alm->time.tm_mon, OMAP_RTC_ALARM_MONTHS_REG);
-	rtc_write(alm->time.tm_mday, OMAP_RTC_ALARM_DAYS_REG);
-	rtc_write(alm->time.tm_hour, OMAP_RTC_ALARM_HOURS_REG);
-	rtc_write(alm->time.tm_min, OMAP_RTC_ALARM_MINUTES_REG);
-	rtc_write(alm->time.tm_sec, OMAP_RTC_ALARM_SECONDS_REG);
+	rtc_write(alm->time.tm_year, rtc_omap, OMAP_RTC_ALARM_YEARS_REG);
+	rtc_write(alm->time.tm_mon, rtc_omap, OMAP_RTC_ALARM_MONTHS_REG);
+	rtc_write(alm->time.tm_mday, rtc_omap, OMAP_RTC_ALARM_DAYS_REG);
+	rtc_write(alm->time.tm_hour, rtc_omap, OMAP_RTC_ALARM_HOURS_REG);
+	rtc_write(alm->time.tm_min, rtc_omap, OMAP_RTC_ALARM_MINUTES_REG);
+	rtc_write(alm->time.tm_sec, rtc_omap, OMAP_RTC_ALARM_SECONDS_REG);
 
-	reg = rtc_read(OMAP_RTC_INTERRUPTS_REG);
-	if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN)
-		irqwake_reg = rtc_read(OMAP_RTC_IRQWAKEEN);
+	reg = rtc_read(rtc_omap, OMAP_RTC_INTERRUPTS_REG);
+	if (rtc_omap->pdata & OMAP_RTC_HAS_IRQWAKEEN)
+		irqwake_reg = rtc_read(rtc_omap, OMAP_RTC_IRQWAKEEN);
 
 	if (alm->enabled) {
 		reg |= OMAP_RTC_INTERRUPTS_IT_ALARM;
@@ -321,9 +349,9 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 		reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM;
 		irqwake_reg &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
 	}
-	rtc_write(reg, OMAP_RTC_INTERRUPTS_REG);
-	if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN)
-		rtc_write(irqwake_reg, OMAP_RTC_IRQWAKEEN);
+	rtc_write(reg, rtc_omap, OMAP_RTC_INTERRUPTS_REG);
+	if (rtc_omap->pdata & OMAP_RTC_HAS_IRQWAKEEN)
+		rtc_write(irqwake_reg, rtc_omap, OMAP_RTC_IRQWAKEEN);
 
 	local_irq_enable();
 
@@ -338,13 +366,10 @@ static struct rtc_class_ops omap_rtc_ops = {
 	.alarm_irq_enable = omap_rtc_alarm_irq_enable,

drivers/rtc/rtc-omap.c static struct rtc_class_ops omap_rtc_ops = { · line 372

Quoted 10 lines
drivers/rtc/rtc-omap.c +1 -4
 };
 
-static int omap_rtc_alarm;
-static int omap_rtc_timer;
-
 #define	OMAP_RTC_DATA_AM3352_IDX	1
 #define	OMAP_RTC_DATA_DA830_IDX		2
 
-static struct platform_device_id omap_rtc_devtype[] = {
+static const struct platform_device_id omap_rtc_devtype[] = {

This is an unrelated clean up and should go in a different patch.

Quoted 9 lines
drivers/rtc/rtc-omap.c +1 -1
 	{
 		.name	= DRIVER_NAME,
 	},
@@ -375,11 +400,18 @@ MODULE_DEVICE_TABLE(of, omap_rtc_of_match);
 static int __init omap_rtc_probe(struct platform_device *pdev)
 {
 	struct resource		*res;
-	struct rtc_device	*rtc;
+	struct rtc_omap_dev	*rtc_omap;

drivers/rtc/rtc-omap.c MODULE_DEVICE_TABLE(of, omap_rtc_of_match); · line 413

Quoted 10 lines
drivers/rtc/rtc-omap.c +6 -0
 	u8			reg, new_ctrl;
 	const struct platform_device_id *id_entry;
 	const struct of_device_id *of_id;
 
+	rtc_omap = devm_kzalloc(&pdev->dev, sizeof(*rtc_omap), GFP_KERNEL);
+	if (!rtc_omap)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, rtc_omap);
+	rtc_omap->dev = &pdev->dev;

You never use this one directly, so why store it?

Quoted 209 lines
drivers/rtc/rtc-omap.c +49 -44
+
 	of_id = of_match_device(omap_rtc_of_match, &pdev->dev);
 	if (of_id)
 		pdev->id_entry = of_id->data;
@@ -389,78 +421,79 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "no matching device entry\n");
 		return -ENODEV;
 	}
+	rtc_omap->pdata = id_entry->driver_data;
 
-	omap_rtc_timer = platform_get_irq(pdev, 0);
-	if (omap_rtc_timer <= 0) {
+	rtc_omap->rtc_timer = platform_get_irq(pdev, 0);
+	if (rtc_omap->rtc_timer <= 0) {
 		pr_debug("%s: no update irq?\n", pdev->name);
 		return -ENOENT;
 	}
 
-	omap_rtc_alarm = platform_get_irq(pdev, 1);
-	if (omap_rtc_alarm <= 0) {
+	rtc_omap->rtc_alarm = platform_get_irq(pdev, 1);
+	if (rtc_omap->rtc_alarm <= 0) {
 		pr_debug("%s: no alarm irq?\n", pdev->name);
 		return -ENOENT;
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	rtc_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(rtc_base))
-		return PTR_ERR(rtc_base);
+	rtc_omap->rtc_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(rtc_omap->rtc_base))
+		return PTR_ERR(rtc_omap->rtc_base);
 
 	/* Enable the clock/module so that we can access the registers */
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_get_sync(&pdev->dev);
 
-	if (id_entry->driver_data & OMAP_RTC_HAS_KICKER) {
-		rtc_writel(KICK0_VALUE, OMAP_RTC_KICK0_REG);
-		rtc_writel(KICK1_VALUE, OMAP_RTC_KICK1_REG);
+	if (rtc_omap->pdata & OMAP_RTC_HAS_KICKER) {
+		rtc_writel(KICK0_VALUE, rtc_omap, OMAP_RTC_KICK0_REG);
+		rtc_writel(KICK1_VALUE, rtc_omap, OMAP_RTC_KICK1_REG);
 	}
 
-	rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
+	rtc_omap->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 			&omap_rtc_ops, THIS_MODULE);
-	if (IS_ERR(rtc)) {
+	if (IS_ERR(rtc_omap->rtc)) {
 		pr_debug("%s: can't register RTC device, err %ld\n",
-			pdev->name, PTR_ERR(rtc));
+			pdev->name, PTR_ERR(rtc_omap->rtc));
 		goto fail0;
 	}
-	platform_set_drvdata(pdev, rtc);
 
 	/* clear pending irqs, and set 1/second periodic,
 	 * which we'll use instead of update irqs
 	 */
-	rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
+	rtc_write(0, rtc_omap, OMAP_RTC_INTERRUPTS_REG);
 
 	/* enable RTC functional clock */
-	if (id_entry->driver_data & OMAP_RTC_HAS_32KCLK_EN)
-		rtc_writel(OMAP_RTC_OSC_32KCLK_EN, OMAP_RTC_OSC_REG);
+	if (rtc_omap->pdata & OMAP_RTC_HAS_32KCLK_EN)
+		rtc_writel(OMAP_RTC_OSC_32KCLK_EN, rtc_omap, OMAP_RTC_OSC_REG);
 
 	/* clear old status */
-	reg = rtc_read(OMAP_RTC_STATUS_REG);
+	reg = rtc_read(rtc_omap, OMAP_RTC_STATUS_REG);
 	if (reg & (u8) OMAP_RTC_STATUS_POWER_UP) {
 		pr_info("%s: RTC power up reset detected\n",
 			pdev->name);
-		rtc_write(OMAP_RTC_STATUS_POWER_UP, OMAP_RTC_STATUS_REG);
+		rtc_write(OMAP_RTC_STATUS_POWER_UP, rtc_omap,
+			  OMAP_RTC_STATUS_REG);
 	}
 	if (reg & (u8) OMAP_RTC_STATUS_ALARM)
-		rtc_write(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG);
+		rtc_write(OMAP_RTC_STATUS_ALARM, rtc_omap, OMAP_RTC_STATUS_REG);
 
 	/* handle periodic and alarm irqs */
-	if (devm_request_irq(&pdev->dev, omap_rtc_timer, rtc_irq, 0,
-			dev_name(&rtc->dev), rtc)) {
+	if (devm_request_irq(&pdev->dev, rtc_omap->rtc_timer, rtc_irq, 0,
+			     dev_name(&pdev->dev), rtc_omap)) {
 		pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n",
-			pdev->name, omap_rtc_timer);
+			pdev->name, rtc_omap->rtc_timer);
 		goto fail0;
 	}
-	if ((omap_rtc_timer != omap_rtc_alarm) &&
-		(devm_request_irq(&pdev->dev, omap_rtc_alarm, rtc_irq, 0,
-			dev_name(&rtc->dev), rtc))) {
+	if ((rtc_omap->rtc_timer != rtc_omap->rtc_alarm) &&
+	    (devm_request_irq(&pdev->dev, rtc_omap->rtc_alarm, rtc_irq, 0,
+			      dev_name(&pdev->dev), rtc_omap))) {
 		pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n",
-			pdev->name, omap_rtc_alarm);
+			pdev->name, rtc_omap->rtc_alarm);
 		goto fail0;
 	}
 
 	/* On boards with split power, RTC_ON_NOFF won't reset the RTC */
-	reg = rtc_read(OMAP_RTC_CTRL_REG);
+	reg = rtc_read(rtc_omap, OMAP_RTC_CTRL_REG);
 	if (reg & (u8) OMAP_RTC_CTRL_STOP)
 		pr_info("%s: already running\n", pdev->name);
 
@@ -488,13 +521,13 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
 		pr_info("%s: split power mode\n", pdev->name);
 
 	if (reg != new_ctrl)
-		rtc_write(new_ctrl, OMAP_RTC_CTRL_REG);
+		rtc_write(new_ctrl, rtc_omap, OMAP_RTC_CTRL_REG);
 
 	return 0;
 
 fail0:
-	if (id_entry->driver_data & OMAP_RTC_HAS_KICKER)
-		rtc_writel(0, OMAP_RTC_KICK0_REG);
+	if (rtc_omap->pdata & OMAP_RTC_HAS_KICKER)
+		rtc_writel(0, rtc_omap, OMAP_RTC_KICK0_REG);
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	return -EIO;
@@ -502,16 +535,15 @@ fail0:
 
 static int __exit omap_rtc_remove(struct platform_device *pdev)
 {
-	const struct platform_device_id *id_entry =
-				platform_get_device_id(pdev);
+	struct rtc_omap_dev *rtc_omap = platform_get_drvdata(pdev);
 
 	device_init_wakeup(&pdev->dev, 0);
 
 	/* leave rtc running, but disable irqs */
-	rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
+	rtc_write(0, rtc_omap, OMAP_RTC_INTERRUPTS_REG);
 
-	if (id_entry->driver_data & OMAP_RTC_HAS_KICKER)
-		rtc_writel(0, OMAP_RTC_KICK0_REG);
+	if (rtc_omap->pdata & OMAP_RTC_HAS_KICKER)
+		rtc_writel(0, rtc_omap, OMAP_RTC_KICK0_REG);
 
 	/* Disable the clock/module */
 	pm_runtime_put_sync(&pdev->dev);
@@ -521,20 +553,21 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM_SLEEP
-static u8 irqstat;
 
 static int omap_rtc_suspend(struct device *dev)
 {
-	irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG);
+	struct rtc_omap_dev *rtc_omap = dev_get_drvdata(dev);
+
+	rtc_omap->irqstat = rtc_read(rtc_omap, OMAP_RTC_INTERRUPTS_REG);
 
 	/* FIXME the RTC alarm is not currently acting as a wakeup event
 	 * source on some platforms, and in fact this enable() call is just
 	 * saving a flag that's never used...
 	 */
 	if (device_may_wakeup(dev))
-		enable_irq_wake(omap_rtc_alarm);
+		enable_irq_wake(rtc_omap->rtc_alarm);
 	else
-		rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
+		rtc_write(0, rtc_omap, OMAP_RTC_INTERRUPTS_REG);
 
 	/* Disable the clock/module */
 	pm_runtime_put_sync(dev);
@@ -544,13 +577,15 @@ static int omap_rtc_suspend(struct device *dev)
 
 static int omap_rtc_resume(struct device *dev)
 {
+	struct rtc_omap_dev *rtc_omap = dev_get_drvdata(dev);
+
 	/* Enable the clock/module so that we can access the registers */
 	pm_runtime_get_sync(dev);
 
 	if (device_may_wakeup(dev))
-		disable_irq_wake(omap_rtc_alarm);
+		disable_irq_wake(rtc_omap->rtc_alarm);
 	else
-		rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG);
+		rtc_write(rtc_omap->irqstat, rtc_omap, OMAP_RTC_INTERRUPTS_REG);
 
 	return 0;
 }
@@ -560,10 +595,11 @@ static SIMPLE_DEV_PM_OPS(omap_rtc_pm_ops, omap_rtc_suspend, omap_rtc_resume);
 
 static void omap_rtc_shutdown(struct platform_device *pdev)
 {
-	rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
+	struct rtc_omap_dev *rtc_omap = platform_get_drvdata(pdev);
+
+	rtc_write(0, rtc_omap, OMAP_RTC_INTERRUPTS_REG);
 }
 
-MODULE_ALIAS("platform:omap_rtc");
 static struct platform_driver omap_rtc_driver = {
 	.remove		= __exit_p(omap_rtc_remove),
 	.shutdown	= omap_rtc_shutdown,

drivers/rtc/rtc-omap.c static struct platform_driver omap_rtc_driver = { · line 617

Quoted 4 lines
drivers/rtc/rtc-omap.c +1 -0
@@ -578,5 +614,6 @@ static struct platform_driver omap_rtc_driver = {
 
 module_platform_driver_probe(omap_rtc_driver, omap_rtc_probe);
 
+MODULE_ALIAS("platform:omap_rtc");

This is another unrelated clean up that should go in a different patch.

drivers/rtc/rtc-omap.c static struct platform_driver omap_rtc_driver = { · line 619

Quoted 2 lines
drivers/rtc/rtc-omap.c +0 -0
 MODULE_AUTHOR("George G. Davis (and others)");
 MODULE_LICENSE("GPL");

Johan

#3 lore raw

PATCH v2 2/4 rtc: omap: Adopt driver to support probe deferral

In reply to Lokesh Vutla

module_platform_driver_probe() prevents driver from requesting probe deferral. So using module_platform_drive() to support probe deferral.

---
Changes since V1:
- New patch, seperated from patch 4/4.

 drivers/rtc/rtc-omap.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/rtc/rtc-omap.c +3 -2
index 4e90b50..93c5424 100644
@@ -397,7 +397,7 @@ static const struct of_device_id omap_rtc_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, omap_rtc_of_match);
 
-static int __init omap_rtc_probe(struct platform_device *pdev)
+static int omap_rtc_probe(struct platform_device *pdev)
 {
 	struct resource		*res;
 	struct rtc_omap_dev	*rtc_omap;
@@ -601,6 +601,7 @@ static void omap_rtc_shutdown(struct platform_device *pdev)
 }
 
 static struct platform_driver omap_rtc_driver = {
+	.probe		= omap_rtc_probe,
 	.remove		= __exit_p(omap_rtc_remove),
 	.shutdown	= omap_rtc_shutdown,
 	.driver		= {
@@ -612,7 +613,7 @@ static struct platform_driver omap_rtc_driver = {
 	.id_table	= omap_rtc_devtype,
 };
 
-module_platform_driver_probe(omap_rtc_driver, omap_rtc_probe);
+module_platform_driver(omap_rtc_driver);
 
 MODULE_ALIAS("platform:omap_rtc");
 MODULE_AUTHOR("George G. Davis (and others)");
Signature · 1 line
1.9.1
#4 lore raw

PATCH v2 2/4 rtc: omap: Adopt driver to support probe deferral

On Thu, Sep 25, 2014 at 03:02:07PM +0530, Lokesh Vutla wrote:

Perhaps the subject should simply be "use module_platform_driver", then you can explain your motive for the change in the body as you already do.

Quoted 24 lines

module_platform_driver_probe() prevents driver from requesting probe deferral. So using module_platform_drive() to support probe deferral.

---
Changes since V1:
- New patch, seperated from patch 4/4.

 drivers/rtc/rtc-omap.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/rtc/rtc-omap.c +1 -1
index 4e90b50..93c5424 100644
@@ -397,7 +397,7 @@ static const struct of_device_id omap_rtc_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, omap_rtc_of_match);
 
-static int __init omap_rtc_probe(struct platform_device *pdev)
+static int omap_rtc_probe(struct platform_device *pdev)
 {
 	struct resource		*res;
 	struct rtc_omap_dev	*rtc_omap;

drivers/rtc/rtc-omap.c static void omap_rtc_shutdown(struct platform_device *pdev) · line 607

Quoted 7 lines
drivers/rtc/rtc-omap.c +1 -0
@@ -601,6 +601,7 @@ static void omap_rtc_shutdown(struct platform_device *pdev)
 }
 
 static struct platform_driver omap_rtc_driver = {
+	.probe		= omap_rtc_probe,
 	.remove		= __exit_p(omap_rtc_remove),
 	.shutdown	= omap_rtc_shutdown,
 	.driver		= {

You should also drop the .owner field of .driver, which is set by the module_platform_driver macro.

drivers/rtc/rtc-omap.c static struct platform_driver omap_rtc_driver = { · line 619

Quoted 9 lines
drivers/rtc/rtc-omap.c +1 -1
@@ -612,7 +613,7 @@ static struct platform_driver omap_rtc_driver = {
 	.id_table	= omap_rtc_devtype,
 };
 
-module_platform_driver_probe(omap_rtc_driver, omap_rtc_probe);
+module_platform_driver(omap_rtc_driver);
 
 MODULE_ALIAS("platform:omap_rtc");
 MODULE_AUTHOR("George G. Davis (and others)");

Johan

#5 lore raw

PATCH v2 3/4 rtc: omap: Update Kconfig for OMAP RTC

In reply to Lokesh Vutla

From: Tero Kristo <[email protected]>

RTC is present in AM43xx and DRA7xx also. Updating the same in Kconfig.

---
Changes since v1:
- New patch

 drivers/rtc/Kconfig    | 6 +++---
 drivers/rtc/rtc-omap.c | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)
drivers/rtc/Kconfig +3 -3
index a168e96..b092e2f 100644
@@ -971,11 +971,11 @@ config RTC_DRV_IMXDI
 	   will be called "rtc-imxdi".
 
 config RTC_DRV_OMAP
-	tristate "TI OMAP1"
-	depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX || SOC_AM33XX
+	tristate "TI OMAP Real Time Clock"
+	depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX || SOC_AM33XX || SOC_DRA7XX || SOC_AM43XX
 	help
 	  Say "yes" here to support the on chip real time clock
-	  present on TI OMAP1, AM33xx and DA8xx/OMAP-L13x.
+	  present on TI OMAP1, AM33xx, DA8xx/OMAP-L13x, AM43xx and DRA7xx.
 
 	  This driver can also be built as a module, if so, module
 	  will be called rtc-omap.
drivers/rtc/rtc-omap.c +2 -2
index 93c5424..f28f1fd 100644
@@ -1,5 +1,5 @@
 /*
- * TI OMAP1 Real Time Clock interface for Linux
+ * TI OMAP Real Time Clock interface for Linux
  *
  * Copyright (C) 2003 MontaVista Software, Inc.
  * Author: George G. Davis <[email protected]> or <[email protected]>
@@ -25,7 +25,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/io.h>
 
-/* The OMAP1 RTC is a year/month/day/hours/minutes/seconds BCD clock
+/* The OMAP RTC is a year/month/day/hours/minutes/seconds BCD clock
  * with century-range alarm matching, driven by the 32kHz clock.
  *
  * The main user-visible ways it differs from PC RTCs are by omitting
Signature · 1 line
1.9.1
#6 lore raw

PATCH v2 3/4 rtc: omap: Update Kconfig for OMAP RTC

Quoted 19 lines · Lokesh Vutla

From: Tero Kristo <[email protected]>

RTC is present in AM43xx and DRA7xx also. Updating the same in Kconfig.

---
Changes since v1:
- New patch

 drivers/rtc/Kconfig    | 6 +++---
 drivers/rtc/rtc-omap.c | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)
drivers/rtc/Kconfig +0 -0
index a168e96..b092e2f 100644

drivers/rtc/Kconfig config RTC_DRV_IMXDI · line 975

Quoted 7 lines
drivers/rtc/Kconfig +2 -2
@@ -971,11 +971,11 @@ config RTC_DRV_IMXDI
 	   will be called "rtc-imxdi".
 
 config RTC_DRV_OMAP
-	tristate "TI OMAP1"
-	depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX || SOC_AM33XX
+	tristate "TI OMAP Real Time Clock"
+	depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX || SOC_AM33XX || SOC_DRA7XX || SOC_AM43XX

do you mind if we just make this "depends on ARCH_OMAP || ARCH_DAVINCI" ? Pretty much every incarnation has this anyway.

Signature · 8 lines
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140925/2002baf7/attachment.sig>
#7 lore raw

PATCH v2 3/4 rtc: omap: Update Kconfig for OMAP RTC

Quoted 22 lines · Felipe Balbi
Quoted 21 lines · Lokesh Vutla

From: Tero Kristo <[email protected]>

RTC is present in AM43xx and DRA7xx also. Updating the same in Kconfig.

---
Changes since v1:
- New patch

 drivers/rtc/Kconfig    | 6 +++---
 drivers/rtc/rtc-omap.c | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)
drivers/rtc/Kconfig +0 -0
index a168e96..b092e2f 100644
@@ -971,11 +971,11 @@ config RTC_DRV_IMXDI
 	   will be called "rtc-imxdi".
 
Quoted 8 lines

drivers/rtc/Kconfig config RTC_DRV_IMXDI · line 975

Quoted 5 lines
drivers/rtc/Kconfig +2 -2
 config RTC_DRV_OMAP
-	tristate "TI OMAP1"
-	depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX || SOC_AM33XX
+	tristate "TI OMAP Real Time Clock"
+	depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX || SOC_AM33XX || SOC_DRA7XX || SOC_AM43XX

do you mind if we just make this "depends on ARCH_OMAP || ARCH_DAVINCI" ? Pretty much every incarnation has this anyway.

Ok..will update it and repost.

Thanks and regards,
Lokesh

Quoted 1 line
#8 lore raw

PATCH v3 3/4 rtc: omap: Update Kconfig for OMAP RTC

In reply to Lokesh Vutla

From: Tero Kristo <[email protected]>

RTC is present in AM43xx and DRA7xx also. Updating the Kconfig to depend on ARCH_OMAP or ARCH_DAVINCI

---
Changes since v2:
- Updated depends on in Kconfig.

 drivers/rtc/Kconfig    | 6 +++---
 drivers/rtc/rtc-omap.c | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)
drivers/rtc/Kconfig +3 -3
index a168e96..f14d200 100644
@@ -971,11 +971,11 @@ config RTC_DRV_IMXDI
 	   will be called "rtc-imxdi".
 
 config RTC_DRV_OMAP
-	tristate "TI OMAP1"
-	depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX || SOC_AM33XX
+	tristate "TI OMAP Real Time Clock"
+	depends on ARCH_OMAP || ARCH_DAVINCI
 	help
 	  Say "yes" here to support the on chip real time clock
-	  present on TI OMAP1, AM33xx and DA8xx/OMAP-L13x.
+	  present on TI OMAP1, AM33xx, DA8xx/OMAP-L13x, AM43xx and DRA7xx.
 
 	  This driver can also be built as a module, if so, module
 	  will be called rtc-omap.
drivers/rtc/rtc-omap.c +2 -2
index 93c5424..f28f1fd 100644
@@ -1,5 +1,5 @@
 /*
- * TI OMAP1 Real Time Clock interface for Linux
+ * TI OMAP Real Time Clock interface for Linux
  *
  * Copyright (C) 2003 MontaVista Software, Inc.
  * Author: George G. Davis <[email protected]> or <[email protected]>
@@ -25,7 +25,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/io.h>
 
-/* The OMAP1 RTC is a year/month/day/hours/minutes/seconds BCD clock
+/* The OMAP RTC is a year/month/day/hours/minutes/seconds BCD clock
  * with century-range alarm matching, driven by the 32kHz clock.
  *
  * The main user-visible ways it differs from PC RTCs are by omitting
Signature · 1 line
1.9.1
#9 lore raw

PATCH v3 3/4 rtc: omap: Update Kconfig for OMAP RTC

Quoted 7 lines · Lokesh Vutla

From: Tero Kristo <[email protected]>

RTC is present in AM43xx and DRA7xx also. Updating the Kconfig to depend on ARCH_OMAP or ARCH_DAVINCI

Signature · 8 lines
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140929/1a2473f9/attachment.sig>
#10 lore raw

PATCH v2 4/4 rtc: omap: Support regulator supply for RTC

In reply to Lokesh Vutla

On some Soc's RTC is powered by an external power regulator. e.g. RTC on DRA7 SoC. Make the OMAP RTC driver support a power regulator.

---
Changes since v1:
- Separated probe deferral supporting into a new patch.

 Documentation/devicetree/bindings/rtc/rtc-omap.txt |  3 +++
 drivers/rtc/rtc-omap.c                             | 24 ++++++++++++++++++++++
 2 files changed, 27 insertions(+)
Documentation/devicetree/bindings/rtc/rtc-omap.txt +3 -0
index 5a0f02d..c67a775 100644
@@ -10,6 +10,9 @@ Required properties:
 - interrupts: rtc timer, alarm interrupts in order
 - interrupt-parent: phandle for the interrupt controller
 
+Optional Properties:
+- rtc-supply : phandle to the regulator device tree node if needed
+
 Example:
 
 rtc at 1c23000 {
drivers/rtc/rtc-omap.c +24 -0
index f28f1fd..8a8df2b 100644
@@ -24,6 +24,7 @@
 #include <linux/of_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/io.h>
+#include <linux/regulator/consumer.h>
 
 /* The OMAP RTC is a year/month/day/hours/minutes/seconds BCD clock
  * with century-range alarm matching, driven by the 32kHz clock.
@@ -124,6 +125,7 @@
  * @device:		Device Pointer.
  * pdata :		Copy of saved platform data.
  * rtc_base :		Base address of memory-mapped IO registers.
+ * rtc_reg :		Pointer to RTC power regulator.
  * rtc_alarm :		RTC alarm interrupt number.
  * rtc_timer :		RTC timer interrupt number.
  * irq_stat :		Copy of Interrupt status register.
@@ -133,6 +135,7 @@ struct rtc_omap_dev {
 	struct device		*dev;
 	unsigned long		pdata;
 	void __iomem		*rtc_base;
+	struct regulator	*rtc_reg;
 	u32			rtc_alarm;
 	u32			rtc_timer;
 	u8			irqstat;
@@ -402,6 +405,7 @@ static int omap_rtc_probe(struct platform_device *pdev)
 	struct resource		*res;
 	struct rtc_omap_dev	*rtc_omap;
 	u8			reg, new_ctrl;
+	int			ret;
 	const struct platform_device_id *id_entry;
 	const struct of_device_id *of_id;
 
@@ -440,6 +444,23 @@ static int omap_rtc_probe(struct platform_device *pdev)
 	if (IS_ERR(rtc_omap->rtc_base))
 		return PTR_ERR(rtc_omap->rtc_base);
 
+	rtc_omap->rtc_reg =  devm_regulator_get_optional(&pdev->dev, "rtc");
+	if (IS_ERR(rtc_omap->rtc_reg)) {
+		if (PTR_ERR(rtc_omap->rtc_reg) == -EPROBE_DEFER) {
+			dev_err(&pdev->dev, "regulator not ready, retry\n");
+			return -EPROBE_DEFER;
+		}
+		rtc_omap->rtc_reg = NULL;
+	}
+
+	if (rtc_omap->rtc_reg) {
+		ret = regulator_enable(rtc_omap->rtc_reg);
+		if (ret) {
+			dev_dbg(&pdev->dev, "regulator enable failed\n");
+			return ret;
+		}
+	}
+
 	/* Enable the clock/module so that we can access the registers */
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_get_sync(&pdev->dev);
@@ -549,6 +570,9 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 
+	if (rtc_omap->rtc_reg)
+		regulator_disable(rtc_omap->rtc_reg);
+
 	return 0;
 }
 
Signature · 1 line
1.9.1
#11 lore raw

PATCH v2 4/4 rtc: omap: Support regulator supply for RTC

Quoted 17 lines · Lokesh Vutla

On some Soc's RTC is powered by an external power regulator. e.g. RTC on DRA7 SoC. Make the OMAP RTC driver support a power regulator.

---
Changes since v1:
- Separated probe deferral supporting into a new patch.

 Documentation/devicetree/bindings/rtc/rtc-omap.txt |  3 +++
 drivers/rtc/rtc-omap.c                             | 24 ++++++++++++++++++++++
 2 files changed, 27 insertions(+)
Documentation/devicetree/bindings/rtc/rtc-omap.txt +0 -0
index 5a0f02d..c67a775 100644

Documentation/devicetree/bindings/rtc/rtc-omap.txt Required properties: · line 14

Quoted 5 lines
Documentation/devicetree/bindings/rtc/rtc-omap.txt +2 -0
@@ -10,6 +10,9 @@ Required properties:
 - interrupts: rtc timer, alarm interrupts in order
 - interrupt-parent: phandle for the interrupt controller
 
+Optional Properties:
+- rtc-supply : phandle to the regulator device tree node if needed

"vrtc-supply"?

No space before ':'.

Documentation/devicetree/bindings/rtc/rtc-omap.txt Required properties: · line 18

Quoted 4 lines
Documentation/devicetree/bindings/rtc/rtc-omap.txt +1 -0
+
 Example:
 
 rtc at 1c23000 {

Update the example as well?

Quoted 37 lines
drivers/rtc/rtc-omap.c +4 -0
index f28f1fd..8a8df2b 100644
@@ -24,6 +24,7 @@
 #include <linux/of_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/io.h>
+#include <linux/regulator/consumer.h>
 
 /* The OMAP RTC is a year/month/day/hours/minutes/seconds BCD clock
  * with century-range alarm matching, driven by the 32kHz clock.
@@ -124,6 +125,7 @@
  * @device:		Device Pointer.
  * pdata :		Copy of saved platform data.
  * rtc_base :		Base address of memory-mapped IO registers.
+ * rtc_reg :		Pointer to RTC power regulator.
  * rtc_alarm :		RTC alarm interrupt number.
  * rtc_timer :		RTC timer interrupt number.
  * irq_stat :		Copy of Interrupt status register.
@@ -133,6 +135,7 @@ struct rtc_omap_dev {
 	struct device		*dev;
 	unsigned long		pdata;
 	void __iomem		*rtc_base;
+	struct regulator	*rtc_reg;
 	u32			rtc_alarm;
 	u32			rtc_timer;
 	u8			irqstat;
@@ -402,6 +405,7 @@ static int omap_rtc_probe(struct platform_device *pdev)
 	struct resource		*res;
 	struct rtc_omap_dev	*rtc_omap;
 	u8			reg, new_ctrl;
+	int			ret;
 	const struct platform_device_id *id_entry;
 	const struct of_device_id *of_id;
 

drivers/rtc/rtc-omap.c static int omap_rtc_probe(struct platform_device *pdev) · line 447

Quoted 4 lines
drivers/rtc/rtc-omap.c +1 -0
@@ -440,6 +444,23 @@ static int omap_rtc_probe(struct platform_device *pdev)
 	if (IS_ERR(rtc_omap->rtc_base))
 		return PTR_ERR(rtc_omap->rtc_base);
 
+	rtc_omap->rtc_reg =  devm_regulator_get_optional(&pdev->dev, "rtc");

Extra space after '='.

drivers/rtc/rtc-omap.c static int omap_rtc_probe(struct platform_device *pdev) · line 450

Quoted 3 lines
drivers/rtc/rtc-omap.c +3 -0
+	if (IS_ERR(rtc_omap->rtc_reg)) {
+		if (PTR_ERR(rtc_omap->rtc_reg) == -EPROBE_DEFER) {
+			dev_err(&pdev->dev, "regulator not ready, retry\n");

This is not an error, and the probe deferral will be logged by driver core anyway. Just drop the dev_err.

drivers/rtc/rtc-omap.c static int omap_rtc_probe(struct platform_device *pdev) · line 459

Quoted 9 lines
drivers/rtc/rtc-omap.c +9 -0
+			return -EPROBE_DEFER;
+		}
+		rtc_omap->rtc_reg = NULL;
+	}
+
+	if (rtc_omap->rtc_reg) {
+		ret = regulator_enable(rtc_omap->rtc_reg);
+		if (ret) {
+			dev_dbg(&pdev->dev, "regulator enable failed\n");

dev_err?

drivers/rtc/rtc-omap.c static int omap_rtc_probe(struct platform_device *pdev) · line 462

Quoted 3 lines
drivers/rtc/rtc-omap.c +3 -0
+			return ret;
+		}
+	}

You never disable the regulator in the probe error path.

drivers/rtc/rtc-omap.c static int __exit omap_rtc_remove(struct platform_device *pdev) · line 577

Quoted 13 lines
drivers/rtc/rtc-omap.c +4 -0
+
 	/* Enable the clock/module so that we can access the registers */
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_get_sync(&pdev->dev);
@@ -549,6 +570,9 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 
+	if (rtc_omap->rtc_reg)
+		regulator_disable(rtc_omap->rtc_reg);
+
 	return 0;
 }

Johan