From 68d641efd86d901d000b888eeab5481257d49f12 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 14 Oct 2009 02:12:33 +0400 Subject: mfd: Fix memleak in pcf50633_client_dev_register Since platform_device_add_data copies the passed data, the allocated subdev_pdata is never freed. A simple fix would be to either free subdev_pdata or put it onto the stack. But since the pcf50633 child devices can rely on beeing children of the pcf50633 core device it's much more elegant to get access to pcf50633 core structure through that link. This allows to get completly rid of pcf5033_subdev_pdata. Signed-off-by: Lars-Peter Clausen Signed-off-by: Paul Fertser Signed-off-by: Samuel Ortiz --- drivers/rtc/rtc-pcf50633.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/rtc') diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c index 4c5d5d0c4cfc..9b74e9c9151c 100644 --- a/drivers/rtc/rtc-pcf50633.c +++ b/drivers/rtc/rtc-pcf50633.c @@ -277,16 +277,13 @@ static void pcf50633_rtc_irq(int irq, void *data) static int __devinit pcf50633_rtc_probe(struct platform_device *pdev) { - struct pcf50633_subdev_pdata *pdata; struct pcf50633_rtc *rtc; - rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); if (!rtc) return -ENOMEM; - pdata = pdev->dev.platform_data; - rtc->pcf = pdata->pcf; + rtc->pcf = dev_to_pcf50633(pdev->dev.parent); platform_set_drvdata(pdev, rtc); rtc->rtc_dev = rtc_device_register("pcf50633-rtc", &pdev->dev, &pcf50633_rtc_ops, THIS_MODULE); -- cgit v1.2.3 From 5a65edbc12b6b34ef912114f1fc8215786f85b25 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 4 Nov 2009 16:10:51 +0000 Subject: mfd: Convert wm8350 IRQ handlers to irq_handler_t This is done as simple code transformation, the semantics of the IRQ API provided by the core are are still very different to those of genirq (mainly with regard to masking). Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/rtc/rtc-wm8350.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers/rtc') diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c index c91edc572eb6..56e56e552813 100644 --- a/drivers/rtc/rtc-wm8350.c +++ b/drivers/rtc/rtc-wm8350.c @@ -315,9 +315,9 @@ static int wm8350_rtc_update_irq_enable(struct device *dev, return 0; } -static void wm8350_rtc_alarm_handler(struct wm8350 *wm8350, int irq, - void *data) +static irqreturn_t wm8350_rtc_alarm_handler(int irq, void *data) { + struct wm8350 *wm8350 = data; struct rtc_device *rtc = wm8350->rtc.rtc; int ret; @@ -330,14 +330,18 @@ static void wm8350_rtc_alarm_handler(struct wm8350 *wm8350, int irq, dev_err(&(wm8350->rtc.pdev->dev), "Failed to disable alarm: %d\n", ret); } + + return IRQ_HANDLED; } -static void wm8350_rtc_update_handler(struct wm8350 *wm8350, int irq, - void *data) +static irqreturn_t wm8350_rtc_update_handler(int irq, void *data) { + struct wm8350 *wm8350 = data; struct rtc_device *rtc = wm8350->rtc.rtc; rtc_update_irq(rtc, 1, RTC_IRQF | RTC_UF); + + return IRQ_HANDLED; } static const struct rtc_class_ops wm8350_rtc_ops = { @@ -459,10 +463,12 @@ static int wm8350_rtc_probe(struct platform_device *pdev) wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_PER); wm8350_register_irq(wm8350, WM8350_IRQ_RTC_SEC, - wm8350_rtc_update_handler, NULL); + wm8350_rtc_update_handler, 0, + "RTC Seconds", wm8350); wm8350_register_irq(wm8350, WM8350_IRQ_RTC_ALM, - wm8350_rtc_alarm_handler, NULL); + wm8350_rtc_alarm_handler, 0, + "RTC Alarm", wm8350); wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_ALM); return 0; -- cgit v1.2.3 From 6a6127462eb9096419fd4b3115ec5971d83a600f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 4 Nov 2009 16:10:52 +0000 Subject: mfd: Mask and unmask wm8350 IRQs on request and free Bring the WM8350 IRQ API more in line with the generic IRQ API by masking and unmasking interrupts as they are requested and freed. This is mostly just a case of deleting the mask and unmask calls from the individual drivers. The RTC driver is changed to mask the periodic IRQ after requesting it rather than only unmasking the alarm IRQ. If the periodic IRQ fires in the period where it is reqested then there will be a spurious notification but there should be no serious consequences from this. The CODEC drive is changed to explicitly disable headphone jack detection prior to requesting the IRQs. This will avoid the IRQ firing with no jack set up. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/rtc/rtc-wm8350.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/rtc') diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c index 56e56e552813..f16486635a8e 100644 --- a/drivers/rtc/rtc-wm8350.c +++ b/drivers/rtc/rtc-wm8350.c @@ -459,17 +459,14 @@ static int wm8350_rtc_probe(struct platform_device *pdev) return ret; } - wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); - wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_PER); - wm8350_register_irq(wm8350, WM8350_IRQ_RTC_SEC, wm8350_rtc_update_handler, 0, "RTC Seconds", wm8350); + wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); wm8350_register_irq(wm8350, WM8350_IRQ_RTC_ALM, wm8350_rtc_alarm_handler, 0, "RTC Alarm", wm8350); - wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_ALM); return 0; } @@ -479,8 +476,6 @@ static int __devexit wm8350_rtc_remove(struct platform_device *pdev) struct wm8350 *wm8350 = platform_get_drvdata(pdev); struct wm8350_rtc *wm_rtc = &wm8350->rtc; - wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); - wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC); wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM); -- cgit v1.2.3 From b07682b6056eb6701f8cb86aa5800e6f2ea7919b Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Sun, 13 Dec 2009 20:05:51 +0100 Subject: mfd: Rename twl4030* driver files to enable re-use The upcoming TWL6030 is companion chip for OMAP4 like the current TWL4030 for OMAP3. The common modules like RTC, Regulator creates opportunity to re-use the most of the code from twl4030. This patch renames few common drivers twl4030* files to twl* to enable the code re-use. Signed-off-by: Rajendra Nayak Signed-off-by: Balaji T K Signed-off-by: Santosh Shilimkar Acked-by: Kevin Hilman Signed-off-by: Samuel Ortiz --- drivers/rtc/Makefile | 2 +- drivers/rtc/rtc-twl.c | 540 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/rtc/rtc-twl4030.c | 540 ---------------------------------------------- 3 files changed, 541 insertions(+), 541 deletions(-) create mode 100644 drivers/rtc/rtc-twl.c delete mode 100644 drivers/rtc/rtc-twl4030.c (limited to 'drivers/rtc') diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index af1ba7ae2857..7da6efb3e953 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -80,7 +80,7 @@ obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o -obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl4030.o +obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c new file mode 100644 index 000000000000..93565be12fae --- /dev/null +++ b/drivers/rtc/rtc-twl.c @@ -0,0 +1,540 @@ +/* + * rtc-twl4030.c -- TWL4030 Real Time Clock interface + * + * Copyright (C) 2007 MontaVista Software, Inc + * Author: Alexandre Rusev + * + * Based on original TI driver twl4030-rtc.c + * Copyright (C) 2006 Texas Instruments, Inc. + * + * Based on rtc-omap.c + * Copyright (C) 2003 MontaVista Software, Inc. + * Author: George G. Davis or + * Copyright (C) 2006 David Brownell + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +/* + * RTC block register offsets (use TWL_MODULE_RTC) + */ +#define REG_SECONDS_REG 0x00 +#define REG_MINUTES_REG 0x01 +#define REG_HOURS_REG 0x02 +#define REG_DAYS_REG 0x03 +#define REG_MONTHS_REG 0x04 +#define REG_YEARS_REG 0x05 +#define REG_WEEKS_REG 0x06 + +#define REG_ALARM_SECONDS_REG 0x07 +#define REG_ALARM_MINUTES_REG 0x08 +#define REG_ALARM_HOURS_REG 0x09 +#define REG_ALARM_DAYS_REG 0x0A +#define REG_ALARM_MONTHS_REG 0x0B +#define REG_ALARM_YEARS_REG 0x0C + +#define REG_RTC_CTRL_REG 0x0D +#define REG_RTC_STATUS_REG 0x0E +#define REG_RTC_INTERRUPTS_REG 0x0F + +#define REG_RTC_COMP_LSB_REG 0x10 +#define REG_RTC_COMP_MSB_REG 0x11 + +/* RTC_CTRL_REG bitfields */ +#define BIT_RTC_CTRL_REG_STOP_RTC_M 0x01 +#define BIT_RTC_CTRL_REG_ROUND_30S_M 0x02 +#define BIT_RTC_CTRL_REG_AUTO_COMP_M 0x04 +#define BIT_RTC_CTRL_REG_MODE_12_24_M 0x08 +#define BIT_RTC_CTRL_REG_TEST_MODE_M 0x10 +#define BIT_RTC_CTRL_REG_SET_32_COUNTER_M 0x20 +#define BIT_RTC_CTRL_REG_GET_TIME_M 0x40 + +/* RTC_STATUS_REG bitfields */ +#define BIT_RTC_STATUS_REG_RUN_M 0x02 +#define BIT_RTC_STATUS_REG_1S_EVENT_M 0x04 +#define BIT_RTC_STATUS_REG_1M_EVENT_M 0x08 +#define BIT_RTC_STATUS_REG_1H_EVENT_M 0x10 +#define BIT_RTC_STATUS_REG_1D_EVENT_M 0x20 +#define BIT_RTC_STATUS_REG_ALARM_M 0x40 +#define BIT_RTC_STATUS_REG_POWER_UP_M 0x80 + +/* RTC_INTERRUPTS_REG bitfields */ +#define BIT_RTC_INTERRUPTS_REG_EVERY_M 0x03 +#define BIT_RTC_INTERRUPTS_REG_IT_TIMER_M 0x04 +#define BIT_RTC_INTERRUPTS_REG_IT_ALARM_M 0x08 + + +/* REG_SECONDS_REG through REG_YEARS_REG is how many registers? */ +#define ALL_TIME_REGS 6 + +/*----------------------------------------------------------------------*/ + +/* + * Supports 1 byte read from TWL4030 RTC register. + */ +static int twl4030_rtc_read_u8(u8 *data, u8 reg) +{ + int ret; + + ret = twl4030_i2c_read_u8(TWL4030_MODULE_RTC, data, reg); + if (ret < 0) + pr_err("twl4030_rtc: Could not read TWL4030" + "register %X - error %d\n", reg, ret); + return ret; +} + +/* + * Supports 1 byte write to TWL4030 RTC registers. + */ +static int twl4030_rtc_write_u8(u8 data, u8 reg) +{ + int ret; + + ret = twl4030_i2c_write_u8(TWL4030_MODULE_RTC, data, reg); + if (ret < 0) + pr_err("twl4030_rtc: Could not write TWL4030" + "register %X - error %d\n", reg, ret); + return ret; +} + +/* + * Cache the value for timer/alarm interrupts register; this is + * only changed by callers holding rtc ops lock (or resume). + */ +static unsigned char rtc_irq_bits; + +/* + * Enable 1/second update and/or alarm interrupts. + */ +static int set_rtc_irq_bit(unsigned char bit) +{ + unsigned char val; + int ret; + + val = rtc_irq_bits | bit; + val &= ~BIT_RTC_INTERRUPTS_REG_EVERY_M; + ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); + if (ret == 0) + rtc_irq_bits = val; + + return ret; +} + +/* + * Disable update and/or alarm interrupts. + */ +static int mask_rtc_irq_bit(unsigned char bit) +{ + unsigned char val; + int ret; + + val = rtc_irq_bits & ~bit; + ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); + if (ret == 0) + rtc_irq_bits = val; + + return ret; +} + +static int twl4030_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) +{ + int ret; + + if (enabled) + ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); + else + ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); + + return ret; +} + +static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled) +{ + int ret; + + if (enabled) + ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); + else + ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); + + return ret; +} + +/* + * Gets current TWL4030 RTC time and date parameters. + * + * The RTC's time/alarm representation is not what gmtime(3) requires + * Linux to use: + * + * - Months are 1..12 vs Linux 0-11 + * - Years are 0..99 vs Linux 1900..N (we assume 21st century) + */ +static int twl4030_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + unsigned char rtc_data[ALL_TIME_REGS + 1]; + int ret; + u8 save_control; + + ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); + if (ret < 0) + return ret; + + save_control |= BIT_RTC_CTRL_REG_GET_TIME_M; + + ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); + if (ret < 0) + return ret; + + ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data, + REG_SECONDS_REG, ALL_TIME_REGS); + + if (ret < 0) { + dev_err(dev, "rtc_read_time error %d\n", ret); + return ret; + } + + tm->tm_sec = bcd2bin(rtc_data[0]); + tm->tm_min = bcd2bin(rtc_data[1]); + tm->tm_hour = bcd2bin(rtc_data[2]); + tm->tm_mday = bcd2bin(rtc_data[3]); + tm->tm_mon = bcd2bin(rtc_data[4]) - 1; + tm->tm_year = bcd2bin(rtc_data[5]) + 100; + + return ret; +} + +static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + unsigned char save_control; + unsigned char rtc_data[ALL_TIME_REGS + 1]; + int ret; + + rtc_data[1] = bin2bcd(tm->tm_sec); + rtc_data[2] = bin2bcd(tm->tm_min); + rtc_data[3] = bin2bcd(tm->tm_hour); + rtc_data[4] = bin2bcd(tm->tm_mday); + rtc_data[5] = bin2bcd(tm->tm_mon + 1); + rtc_data[6] = bin2bcd(tm->tm_year - 100); + + /* Stop RTC while updating the TC registers */ + ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); + if (ret < 0) + goto out; + + save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M; + twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); + if (ret < 0) + goto out; + + /* update all the time registers in one shot */ + ret = twl4030_i2c_write(TWL4030_MODULE_RTC, rtc_data, + REG_SECONDS_REG, ALL_TIME_REGS); + if (ret < 0) { + dev_err(dev, "rtc_set_time error %d\n", ret); + goto out; + } + + /* Start back RTC */ + save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M; + ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); + +out: + return ret; +} + +/* + * Gets current TWL4030 RTC alarm time. + */ +static int twl4030_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) +{ + unsigned char rtc_data[ALL_TIME_REGS + 1]; + int ret; + + ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data, + REG_ALARM_SECONDS_REG, ALL_TIME_REGS); + if (ret < 0) { + dev_err(dev, "rtc_read_alarm error %d\n", ret); + return ret; + } + + /* some of these fields may be wildcard/"match all" */ + alm->time.tm_sec = bcd2bin(rtc_data[0]); + alm->time.tm_min = bcd2bin(rtc_data[1]); + alm->time.tm_hour = bcd2bin(rtc_data[2]); + alm->time.tm_mday = bcd2bin(rtc_data[3]); + alm->time.tm_mon = bcd2bin(rtc_data[4]) - 1; + alm->time.tm_year = bcd2bin(rtc_data[5]) + 100; + + /* report cached alarm enable state */ + if (rtc_irq_bits & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M) + alm->enabled = 1; + + return ret; +} + +static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) +{ + unsigned char alarm_data[ALL_TIME_REGS + 1]; + int ret; + + ret = twl4030_rtc_alarm_irq_enable(dev, 0); + if (ret) + goto out; + + alarm_data[1] = bin2bcd(alm->time.tm_sec); + alarm_data[2] = bin2bcd(alm->time.tm_min); + alarm_data[3] = bin2bcd(alm->time.tm_hour); + alarm_data[4] = bin2bcd(alm->time.tm_mday); + alarm_data[5] = bin2bcd(alm->time.tm_mon + 1); + alarm_data[6] = bin2bcd(alm->time.tm_year - 100); + + /* update all the alarm registers in one shot */ + ret = twl4030_i2c_write(TWL4030_MODULE_RTC, alarm_data, + REG_ALARM_SECONDS_REG, ALL_TIME_REGS); + if (ret) { + dev_err(dev, "rtc_set_alarm error %d\n", ret); + goto out; + } + + if (alm->enabled) + ret = twl4030_rtc_alarm_irq_enable(dev, 1); +out: + return ret; +} + +static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) +{ + unsigned long events = 0; + int ret = IRQ_NONE; + int res; + u8 rd_reg; + +#ifdef CONFIG_LOCKDEP + /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which + * we don't want and can't tolerate. Although it might be + * friendlier not to borrow this thread context... + */ + local_irq_enable(); +#endif + + res = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); + if (res) + goto out; + /* + * Figure out source of interrupt: ALARM or TIMER in RTC_STATUS_REG. + * only one (ALARM or RTC) interrupt source may be enabled + * at time, we also could check our results + * by reading RTS_INTERRUPTS_REGISTER[IT_TIMER,IT_ALARM] + */ + if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M) + events |= RTC_IRQF | RTC_AF; + else + events |= RTC_IRQF | RTC_UF; + + res = twl4030_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M, + REG_RTC_STATUS_REG); + if (res) + goto out; + + /* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1 + * needs 2 reads to clear the interrupt. One read is done in + * do_twl4030_pwrirq(). Doing the second read, to clear + * the bit. + * + * FIXME the reason PWR_ISR1 needs an extra read is that + * RTC_IF retriggered until we cleared REG_ALARM_M above. + * But re-reading like this is a bad hack; by doing so we + * risk wrongly clearing status for some other IRQ (losing + * the interrupt). Be smarter about handling RTC_UF ... + */ + res = twl4030_i2c_read_u8(TWL4030_MODULE_INT, + &rd_reg, TWL4030_INT_PWR_ISR1); + if (res) + goto out; + + /* Notify RTC core on event */ + rtc_update_irq(rtc, 1, events); + + ret = IRQ_HANDLED; +out: + return ret; +} + +static struct rtc_class_ops twl4030_rtc_ops = { + .read_time = twl4030_rtc_read_time, + .set_time = twl4030_rtc_set_time, + .read_alarm = twl4030_rtc_read_alarm, + .set_alarm = twl4030_rtc_set_alarm, + .alarm_irq_enable = twl4030_rtc_alarm_irq_enable, + .update_irq_enable = twl4030_rtc_update_irq_enable, +}; + +/*----------------------------------------------------------------------*/ + +static int __devinit twl4030_rtc_probe(struct platform_device *pdev) +{ + struct rtc_device *rtc; + int ret = 0; + int irq = platform_get_irq(pdev, 0); + u8 rd_reg; + + if (irq <= 0) + return -EINVAL; + + rtc = rtc_device_register(pdev->name, + &pdev->dev, &twl4030_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) { + ret = PTR_ERR(rtc); + dev_err(&pdev->dev, "can't register RTC device, err %ld\n", + PTR_ERR(rtc)); + goto out0; + + } + + platform_set_drvdata(pdev, rtc); + + ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); + if (ret < 0) + goto out1; + + if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M) + dev_warn(&pdev->dev, "Power up reset detected.\n"); + + if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M) + dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n"); + + /* Clear RTC Power up reset and pending alarm interrupts */ + ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); + if (ret < 0) + goto out1; + + ret = request_irq(irq, twl4030_rtc_interrupt, + IRQF_TRIGGER_RISING, + dev_name(&rtc->dev), rtc); + if (ret < 0) { + dev_err(&pdev->dev, "IRQ is not free.\n"); + goto out1; + } + + /* Check RTC module status, Enable if it is off */ + ret = twl4030_rtc_read_u8(&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 TWL4030-RTC.\n"); + rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; + ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); + if (ret < 0) + goto out2; + } + + /* init cached IRQ enable bits */ + ret = twl4030_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); + if (ret < 0) + goto out2; + + return ret; + +out2: + free_irq(irq, rtc); +out1: + rtc_device_unregister(rtc); +out0: + return ret; +} + +/* + * Disable all TWL4030 RTC module interrupts. + * Sets status flag to free. + */ +static int __devexit twl4030_rtc_remove(struct platform_device *pdev) +{ + /* leave rtc running, but disable irqs */ + struct rtc_device *rtc = platform_get_drvdata(pdev); + 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); + + free_irq(irq, rtc); + + rtc_device_unregister(rtc); + platform_set_drvdata(pdev, NULL); + return 0; +} + +static void twl4030_rtc_shutdown(struct platform_device *pdev) +{ + /* 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); +} + +#ifdef CONFIG_PM + +static unsigned char irqstat; + +static int twl4030_rtc_suspend(struct platform_device *pdev, pm_message_t state) +{ + irqstat = rtc_irq_bits; + + mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); + return 0; +} + +static int twl4030_rtc_resume(struct platform_device *pdev) +{ + set_rtc_irq_bit(irqstat); + return 0; +} + +#else +#define twl4030_rtc_suspend NULL +#define twl4030_rtc_resume NULL +#endif + +MODULE_ALIAS("platform:twl4030_rtc"); + +static struct platform_driver twl4030rtc_driver = { + .probe = twl4030_rtc_probe, + .remove = __devexit_p(twl4030_rtc_remove), + .shutdown = twl4030_rtc_shutdown, + .suspend = twl4030_rtc_suspend, + .resume = twl4030_rtc_resume, + .driver = { + .owner = THIS_MODULE, + .name = "twl4030_rtc", + }, +}; + +static int __init twl4030_rtc_init(void) +{ + return platform_driver_register(&twl4030rtc_driver); +} +module_init(twl4030_rtc_init); + +static void __exit twl4030_rtc_exit(void) +{ + platform_driver_unregister(&twl4030rtc_driver); +} +module_exit(twl4030_rtc_exit); + +MODULE_AUTHOR("Texas Instruments, MontaVista Software"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-twl4030.c b/drivers/rtc/rtc-twl4030.c deleted file mode 100644 index 9c8c70c497dc..000000000000 --- a/drivers/rtc/rtc-twl4030.c +++ /dev/null @@ -1,540 +0,0 @@ -/* - * rtc-twl4030.c -- TWL4030 Real Time Clock interface - * - * Copyright (C) 2007 MontaVista Software, Inc - * Author: Alexandre Rusev - * - * Based on original TI driver twl4030-rtc.c - * Copyright (C) 2006 Texas Instruments, Inc. - * - * Based on rtc-omap.c - * Copyright (C) 2003 MontaVista Software, Inc. - * Author: George G. Davis or - * Copyright (C) 2006 David Brownell - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - - -/* - * RTC block register offsets (use TWL_MODULE_RTC) - */ -#define REG_SECONDS_REG 0x00 -#define REG_MINUTES_REG 0x01 -#define REG_HOURS_REG 0x02 -#define REG_DAYS_REG 0x03 -#define REG_MONTHS_REG 0x04 -#define REG_YEARS_REG 0x05 -#define REG_WEEKS_REG 0x06 - -#define REG_ALARM_SECONDS_REG 0x07 -#define REG_ALARM_MINUTES_REG 0x08 -#define REG_ALARM_HOURS_REG 0x09 -#define REG_ALARM_DAYS_REG 0x0A -#define REG_ALARM_MONTHS_REG 0x0B -#define REG_ALARM_YEARS_REG 0x0C - -#define REG_RTC_CTRL_REG 0x0D -#define REG_RTC_STATUS_REG 0x0E -#define REG_RTC_INTERRUPTS_REG 0x0F - -#define REG_RTC_COMP_LSB_REG 0x10 -#define REG_RTC_COMP_MSB_REG 0x11 - -/* RTC_CTRL_REG bitfields */ -#define BIT_RTC_CTRL_REG_STOP_RTC_M 0x01 -#define BIT_RTC_CTRL_REG_ROUND_30S_M 0x02 -#define BIT_RTC_CTRL_REG_AUTO_COMP_M 0x04 -#define BIT_RTC_CTRL_REG_MODE_12_24_M 0x08 -#define BIT_RTC_CTRL_REG_TEST_MODE_M 0x10 -#define BIT_RTC_CTRL_REG_SET_32_COUNTER_M 0x20 -#define BIT_RTC_CTRL_REG_GET_TIME_M 0x40 - -/* RTC_STATUS_REG bitfields */ -#define BIT_RTC_STATUS_REG_RUN_M 0x02 -#define BIT_RTC_STATUS_REG_1S_EVENT_M 0x04 -#define BIT_RTC_STATUS_REG_1M_EVENT_M 0x08 -#define BIT_RTC_STATUS_REG_1H_EVENT_M 0x10 -#define BIT_RTC_STATUS_REG_1D_EVENT_M 0x20 -#define BIT_RTC_STATUS_REG_ALARM_M 0x40 -#define BIT_RTC_STATUS_REG_POWER_UP_M 0x80 - -/* RTC_INTERRUPTS_REG bitfields */ -#define BIT_RTC_INTERRUPTS_REG_EVERY_M 0x03 -#define BIT_RTC_INTERRUPTS_REG_IT_TIMER_M 0x04 -#define BIT_RTC_INTERRUPTS_REG_IT_ALARM_M 0x08 - - -/* REG_SECONDS_REG through REG_YEARS_REG is how many registers? */ -#define ALL_TIME_REGS 6 - -/*----------------------------------------------------------------------*/ - -/* - * Supports 1 byte read from TWL4030 RTC register. - */ -static int twl4030_rtc_read_u8(u8 *data, u8 reg) -{ - int ret; - - ret = twl4030_i2c_read_u8(TWL4030_MODULE_RTC, data, reg); - if (ret < 0) - pr_err("twl4030_rtc: Could not read TWL4030" - "register %X - error %d\n", reg, ret); - return ret; -} - -/* - * Supports 1 byte write to TWL4030 RTC registers. - */ -static int twl4030_rtc_write_u8(u8 data, u8 reg) -{ - int ret; - - ret = twl4030_i2c_write_u8(TWL4030_MODULE_RTC, data, reg); - if (ret < 0) - pr_err("twl4030_rtc: Could not write TWL4030" - "register %X - error %d\n", reg, ret); - return ret; -} - -/* - * Cache the value for timer/alarm interrupts register; this is - * only changed by callers holding rtc ops lock (or resume). - */ -static unsigned char rtc_irq_bits; - -/* - * Enable 1/second update and/or alarm interrupts. - */ -static int set_rtc_irq_bit(unsigned char bit) -{ - unsigned char val; - int ret; - - val = rtc_irq_bits | bit; - val &= ~BIT_RTC_INTERRUPTS_REG_EVERY_M; - ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); - if (ret == 0) - rtc_irq_bits = val; - - return ret; -} - -/* - * Disable update and/or alarm interrupts. - */ -static int mask_rtc_irq_bit(unsigned char bit) -{ - unsigned char val; - int ret; - - val = rtc_irq_bits & ~bit; - ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); - if (ret == 0) - rtc_irq_bits = val; - - return ret; -} - -static int twl4030_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) -{ - int ret; - - if (enabled) - ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); - else - ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); - - return ret; -} - -static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled) -{ - int ret; - - if (enabled) - ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); - else - ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); - - return ret; -} - -/* - * Gets current TWL4030 RTC time and date parameters. - * - * The RTC's time/alarm representation is not what gmtime(3) requires - * Linux to use: - * - * - Months are 1..12 vs Linux 0-11 - * - Years are 0..99 vs Linux 1900..N (we assume 21st century) - */ -static int twl4030_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - unsigned char rtc_data[ALL_TIME_REGS + 1]; - int ret; - u8 save_control; - - ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); - if (ret < 0) - return ret; - - save_control |= BIT_RTC_CTRL_REG_GET_TIME_M; - - ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); - if (ret < 0) - return ret; - - ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data, - REG_SECONDS_REG, ALL_TIME_REGS); - - if (ret < 0) { - dev_err(dev, "rtc_read_time error %d\n", ret); - return ret; - } - - tm->tm_sec = bcd2bin(rtc_data[0]); - tm->tm_min = bcd2bin(rtc_data[1]); - tm->tm_hour = bcd2bin(rtc_data[2]); - tm->tm_mday = bcd2bin(rtc_data[3]); - tm->tm_mon = bcd2bin(rtc_data[4]) - 1; - tm->tm_year = bcd2bin(rtc_data[5]) + 100; - - return ret; -} - -static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - unsigned char save_control; - unsigned char rtc_data[ALL_TIME_REGS + 1]; - int ret; - - rtc_data[1] = bin2bcd(tm->tm_sec); - rtc_data[2] = bin2bcd(tm->tm_min); - rtc_data[3] = bin2bcd(tm->tm_hour); - rtc_data[4] = bin2bcd(tm->tm_mday); - rtc_data[5] = bin2bcd(tm->tm_mon + 1); - rtc_data[6] = bin2bcd(tm->tm_year - 100); - - /* Stop RTC while updating the TC registers */ - ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); - if (ret < 0) - goto out; - - save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M; - twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); - if (ret < 0) - goto out; - - /* update all the time registers in one shot */ - ret = twl4030_i2c_write(TWL4030_MODULE_RTC, rtc_data, - REG_SECONDS_REG, ALL_TIME_REGS); - if (ret < 0) { - dev_err(dev, "rtc_set_time error %d\n", ret); - goto out; - } - - /* Start back RTC */ - save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M; - ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); - -out: - return ret; -} - -/* - * Gets current TWL4030 RTC alarm time. - */ -static int twl4030_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) -{ - unsigned char rtc_data[ALL_TIME_REGS + 1]; - int ret; - - ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data, - REG_ALARM_SECONDS_REG, ALL_TIME_REGS); - if (ret < 0) { - dev_err(dev, "rtc_read_alarm error %d\n", ret); - return ret; - } - - /* some of these fields may be wildcard/"match all" */ - alm->time.tm_sec = bcd2bin(rtc_data[0]); - alm->time.tm_min = bcd2bin(rtc_data[1]); - alm->time.tm_hour = bcd2bin(rtc_data[2]); - alm->time.tm_mday = bcd2bin(rtc_data[3]); - alm->time.tm_mon = bcd2bin(rtc_data[4]) - 1; - alm->time.tm_year = bcd2bin(rtc_data[5]) + 100; - - /* report cached alarm enable state */ - if (rtc_irq_bits & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M) - alm->enabled = 1; - - return ret; -} - -static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) -{ - unsigned char alarm_data[ALL_TIME_REGS + 1]; - int ret; - - ret = twl4030_rtc_alarm_irq_enable(dev, 0); - if (ret) - goto out; - - alarm_data[1] = bin2bcd(alm->time.tm_sec); - alarm_data[2] = bin2bcd(alm->time.tm_min); - alarm_data[3] = bin2bcd(alm->time.tm_hour); - alarm_data[4] = bin2bcd(alm->time.tm_mday); - alarm_data[5] = bin2bcd(alm->time.tm_mon + 1); - alarm_data[6] = bin2bcd(alm->time.tm_year - 100); - - /* update all the alarm registers in one shot */ - ret = twl4030_i2c_write(TWL4030_MODULE_RTC, alarm_data, - REG_ALARM_SECONDS_REG, ALL_TIME_REGS); - if (ret) { - dev_err(dev, "rtc_set_alarm error %d\n", ret); - goto out; - } - - if (alm->enabled) - ret = twl4030_rtc_alarm_irq_enable(dev, 1); -out: - return ret; -} - -static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) -{ - unsigned long events = 0; - int ret = IRQ_NONE; - int res; - u8 rd_reg; - -#ifdef CONFIG_LOCKDEP - /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which - * we don't want and can't tolerate. Although it might be - * friendlier not to borrow this thread context... - */ - local_irq_enable(); -#endif - - res = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); - if (res) - goto out; - /* - * Figure out source of interrupt: ALARM or TIMER in RTC_STATUS_REG. - * only one (ALARM or RTC) interrupt source may be enabled - * at time, we also could check our results - * by reading RTS_INTERRUPTS_REGISTER[IT_TIMER,IT_ALARM] - */ - if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M) - events |= RTC_IRQF | RTC_AF; - else - events |= RTC_IRQF | RTC_UF; - - res = twl4030_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M, - REG_RTC_STATUS_REG); - if (res) - goto out; - - /* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1 - * needs 2 reads to clear the interrupt. One read is done in - * do_twl4030_pwrirq(). Doing the second read, to clear - * the bit. - * - * FIXME the reason PWR_ISR1 needs an extra read is that - * RTC_IF retriggered until we cleared REG_ALARM_M above. - * But re-reading like this is a bad hack; by doing so we - * risk wrongly clearing status for some other IRQ (losing - * the interrupt). Be smarter about handling RTC_UF ... - */ - res = twl4030_i2c_read_u8(TWL4030_MODULE_INT, - &rd_reg, TWL4030_INT_PWR_ISR1); - if (res) - goto out; - - /* Notify RTC core on event */ - rtc_update_irq(rtc, 1, events); - - ret = IRQ_HANDLED; -out: - return ret; -} - -static struct rtc_class_ops twl4030_rtc_ops = { - .read_time = twl4030_rtc_read_time, - .set_time = twl4030_rtc_set_time, - .read_alarm = twl4030_rtc_read_alarm, - .set_alarm = twl4030_rtc_set_alarm, - .alarm_irq_enable = twl4030_rtc_alarm_irq_enable, - .update_irq_enable = twl4030_rtc_update_irq_enable, -}; - -/*----------------------------------------------------------------------*/ - -static int __devinit twl4030_rtc_probe(struct platform_device *pdev) -{ - struct rtc_device *rtc; - int ret = 0; - int irq = platform_get_irq(pdev, 0); - u8 rd_reg; - - if (irq <= 0) - return -EINVAL; - - rtc = rtc_device_register(pdev->name, - &pdev->dev, &twl4030_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc)) { - ret = PTR_ERR(rtc); - dev_err(&pdev->dev, "can't register RTC device, err %ld\n", - PTR_ERR(rtc)); - goto out0; - - } - - platform_set_drvdata(pdev, rtc); - - ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); - if (ret < 0) - goto out1; - - if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M) - dev_warn(&pdev->dev, "Power up reset detected.\n"); - - if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M) - dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n"); - - /* Clear RTC Power up reset and pending alarm interrupts */ - ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); - if (ret < 0) - goto out1; - - ret = request_irq(irq, twl4030_rtc_interrupt, - IRQF_TRIGGER_RISING, - dev_name(&rtc->dev), rtc); - if (ret < 0) { - dev_err(&pdev->dev, "IRQ is not free.\n"); - goto out1; - } - - /* Check RTC module status, Enable if it is off */ - ret = twl4030_rtc_read_u8(&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 TWL4030-RTC.\n"); - rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; - ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); - if (ret < 0) - goto out2; - } - - /* init cached IRQ enable bits */ - ret = twl4030_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); - if (ret < 0) - goto out2; - - return ret; - -out2: - free_irq(irq, rtc); -out1: - rtc_device_unregister(rtc); -out0: - return ret; -} - -/* - * Disable all TWL4030 RTC module interrupts. - * Sets status flag to free. - */ -static int __devexit twl4030_rtc_remove(struct platform_device *pdev) -{ - /* leave rtc running, but disable irqs */ - struct rtc_device *rtc = platform_get_drvdata(pdev); - 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); - - free_irq(irq, rtc); - - rtc_device_unregister(rtc); - platform_set_drvdata(pdev, NULL); - return 0; -} - -static void twl4030_rtc_shutdown(struct platform_device *pdev) -{ - /* 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); -} - -#ifdef CONFIG_PM - -static unsigned char irqstat; - -static int twl4030_rtc_suspend(struct platform_device *pdev, pm_message_t state) -{ - irqstat = rtc_irq_bits; - - mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); - return 0; -} - -static int twl4030_rtc_resume(struct platform_device *pdev) -{ - set_rtc_irq_bit(irqstat); - return 0; -} - -#else -#define twl4030_rtc_suspend NULL -#define twl4030_rtc_resume NULL -#endif - -MODULE_ALIAS("platform:twl4030_rtc"); - -static struct platform_driver twl4030rtc_driver = { - .probe = twl4030_rtc_probe, - .remove = __devexit_p(twl4030_rtc_remove), - .shutdown = twl4030_rtc_shutdown, - .suspend = twl4030_rtc_suspend, - .resume = twl4030_rtc_resume, - .driver = { - .owner = THIS_MODULE, - .name = "twl4030_rtc", - }, -}; - -static int __init twl4030_rtc_init(void) -{ - return platform_driver_register(&twl4030rtc_driver); -} -module_init(twl4030_rtc_init); - -static void __exit twl4030_rtc_exit(void) -{ - platform_driver_unregister(&twl4030rtc_driver); -} -module_exit(twl4030_rtc_exit); - -MODULE_AUTHOR("Texas Instruments, MontaVista Software"); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From fc7b92fca4e546184557f1c53f84ad57c66b7695 Mon Sep 17 00:00:00 2001 From: Balaji T K Date: Sun, 13 Dec 2009 21:23:33 +0100 Subject: mfd: Rename all twl4030_i2c* This patch renames function names like twl4030_i2c_write_u8, twl4030_i2c_read_u8 to twl_i2c_write_u8, twl_i2c_read_u8 and also common variable in twl-core.c Signed-off-by: Rajendra Nayak Signed-off-by: Balaji T K Signed-off-by: Santosh Shilimkar Acked-by: Kevin Hilman Signed-off-by: Samuel Ortiz --- drivers/rtc/rtc-twl.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/rtc') diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index 93565be12fae..6119712cc8de 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c @@ -92,7 +92,7 @@ static int twl4030_rtc_read_u8(u8 *data, u8 reg) { int ret; - ret = twl4030_i2c_read_u8(TWL4030_MODULE_RTC, data, reg); + ret = twl_i2c_read_u8(TWL4030_MODULE_RTC, data, reg); if (ret < 0) pr_err("twl4030_rtc: Could not read TWL4030" "register %X - error %d\n", reg, ret); @@ -106,7 +106,7 @@ static int twl4030_rtc_write_u8(u8 data, u8 reg) { int ret; - ret = twl4030_i2c_write_u8(TWL4030_MODULE_RTC, data, reg); + ret = twl_i2c_write_u8(TWL4030_MODULE_RTC, data, reg); if (ret < 0) pr_err("twl4030_rtc: Could not write TWL4030" "register %X - error %d\n", reg, ret); @@ -201,7 +201,7 @@ static int twl4030_rtc_read_time(struct device *dev, struct rtc_time *tm) if (ret < 0) return ret; - ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data, + ret = twl_i2c_read(TWL4030_MODULE_RTC, rtc_data, REG_SECONDS_REG, ALL_TIME_REGS); if (ret < 0) { @@ -243,7 +243,7 @@ static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm) goto out; /* update all the time registers in one shot */ - ret = twl4030_i2c_write(TWL4030_MODULE_RTC, rtc_data, + ret = twl_i2c_write(TWL4030_MODULE_RTC, rtc_data, REG_SECONDS_REG, ALL_TIME_REGS); if (ret < 0) { dev_err(dev, "rtc_set_time error %d\n", ret); @@ -266,7 +266,7 @@ static int twl4030_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) unsigned char rtc_data[ALL_TIME_REGS + 1]; int ret; - ret = twl4030_i2c_read(TWL4030_MODULE_RTC, rtc_data, + ret = twl_i2c_read(TWL4030_MODULE_RTC, rtc_data, REG_ALARM_SECONDS_REG, ALL_TIME_REGS); if (ret < 0) { dev_err(dev, "rtc_read_alarm error %d\n", ret); @@ -305,7 +305,7 @@ static int twl4030_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 = twl4030_i2c_write(TWL4030_MODULE_RTC, alarm_data, + ret = twl_i2c_write(TWL4030_MODULE_RTC, alarm_data, REG_ALARM_SECONDS_REG, ALL_TIME_REGS); if (ret) { dev_err(dev, "rtc_set_alarm error %d\n", ret); @@ -363,7 +363,7 @@ static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) * risk wrongly clearing status for some other IRQ (losing * the interrupt). Be smarter about handling RTC_UF ... */ - res = twl4030_i2c_read_u8(TWL4030_MODULE_INT, + res = twl_i2c_read_u8(TWL4030_MODULE_INT, &rd_reg, TWL4030_INT_PWR_ISR1); if (res) goto out; -- cgit v1.2.3 From ef3b7d0d3ed6c53917367003af90a4002f409d3d Mon Sep 17 00:00:00 2001 From: Balaji T K Date: Sun, 13 Dec 2009 21:30:48 +0100 Subject: mfd: Rename twl4030_ routines in rtc-twl.c This patch renames all twl4030_ functions to twl_ so that RTC driver can be shared between Triton and Phoenix. Signed-off-by: Balaji T K Signed-off-by: Nayak Rajendra Signed-off-by: Santosh Shilimkar Acked-by: Kevin Hilman Signed-off-by: Samuel Ortiz --- drivers/rtc/rtc-twl.c | 136 +++++++++++++++++++++++++------------------------- 1 file changed, 68 insertions(+), 68 deletions(-) (limited to 'drivers/rtc') diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index 6119712cc8de..7cea920ff6ac 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c @@ -1,5 +1,5 @@ /* - * rtc-twl4030.c -- TWL4030 Real Time Clock interface + * rtc-twl.c -- TWL Real Time Clock interface * * Copyright (C) 2007 MontaVista Software, Inc * Author: Alexandre Rusev @@ -86,29 +86,29 @@ /*----------------------------------------------------------------------*/ /* - * Supports 1 byte read from TWL4030 RTC register. + * Supports 1 byte read from TWL RTC register. */ -static int twl4030_rtc_read_u8(u8 *data, u8 reg) +static int twl_rtc_read_u8(u8 *data, u8 reg) { int ret; - ret = twl_i2c_read_u8(TWL4030_MODULE_RTC, data, reg); + ret = twl_i2c_read_u8(TWL_MODULE_RTC, data, reg); if (ret < 0) - pr_err("twl4030_rtc: Could not read TWL4030" + pr_err("twl_rtc: Could not read TWL" "register %X - error %d\n", reg, ret); return ret; } /* - * Supports 1 byte write to TWL4030 RTC registers. + * Supports 1 byte write to TWL RTC registers. */ -static int twl4030_rtc_write_u8(u8 data, u8 reg) +static int twl_rtc_write_u8(u8 data, u8 reg) { int ret; - ret = twl_i2c_write_u8(TWL4030_MODULE_RTC, data, reg); + ret = twl_i2c_write_u8(TWL_MODULE_RTC, data, reg); if (ret < 0) - pr_err("twl4030_rtc: Could not write TWL4030" + pr_err("twl_rtc: Could not write TWL" "register %X - error %d\n", reg, ret); return ret; } @@ -129,7 +129,7 @@ static int set_rtc_irq_bit(unsigned char bit) val = rtc_irq_bits | bit; val &= ~BIT_RTC_INTERRUPTS_REG_EVERY_M; - ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); + ret = twl_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); if (ret == 0) rtc_irq_bits = val; @@ -145,14 +145,14 @@ static int mask_rtc_irq_bit(unsigned char bit) int ret; val = rtc_irq_bits & ~bit; - ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); + ret = twl_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); if (ret == 0) rtc_irq_bits = val; return ret; } -static int twl4030_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) +static int twl_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) { int ret; @@ -164,7 +164,7 @@ static int twl4030_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) return ret; } -static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled) +static int twl_rtc_update_irq_enable(struct device *dev, unsigned enabled) { int ret; @@ -177,7 +177,7 @@ static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled) } /* - * Gets current TWL4030 RTC time and date parameters. + * Gets current TWL RTC time and date parameters. * * The RTC's time/alarm representation is not what gmtime(3) requires * Linux to use: @@ -185,23 +185,23 @@ static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled) * - Months are 1..12 vs Linux 0-11 * - Years are 0..99 vs Linux 1900..N (we assume 21st century) */ -static int twl4030_rtc_read_time(struct device *dev, struct rtc_time *tm) +static int twl_rtc_read_time(struct device *dev, struct rtc_time *tm) { unsigned char rtc_data[ALL_TIME_REGS + 1]; int ret; u8 save_control; - ret = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); + ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); if (ret < 0) return ret; save_control |= BIT_RTC_CTRL_REG_GET_TIME_M; - ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); + ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); if (ret < 0) return ret; - ret = twl_i2c_read(TWL4030_MODULE_RTC, rtc_data, + ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data, REG_SECONDS_REG, ALL_TIME_REGS); if (ret < 0) { @@ -219,7 +219,7 @@ static int twl4030_rtc_read_time(struct device *dev, struct rtc_time *tm) return ret; } -static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm) +static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm) { unsigned char save_control; unsigned char rtc_data[ALL_TIME_REGS + 1]; @@ -233,17 +233,17 @@ static int twl4030_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 = twl4030_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); + ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG); if (ret < 0) goto out; save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M; - twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); + twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); if (ret < 0) goto out; /* update all the time registers in one shot */ - ret = twl_i2c_write(TWL4030_MODULE_RTC, rtc_data, + ret = twl_i2c_write(TWL_MODULE_RTC, rtc_data, REG_SECONDS_REG, ALL_TIME_REGS); if (ret < 0) { dev_err(dev, "rtc_set_time error %d\n", ret); @@ -252,21 +252,21 @@ static int twl4030_rtc_set_time(struct device *dev, struct rtc_time *tm) /* Start back RTC */ save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M; - ret = twl4030_rtc_write_u8(save_control, REG_RTC_CTRL_REG); + ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); out: return ret; } /* - * Gets current TWL4030 RTC alarm time. + * Gets current TWL RTC alarm time. */ -static int twl4030_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) +static int twl_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) { unsigned char rtc_data[ALL_TIME_REGS + 1]; int ret; - ret = twl_i2c_read(TWL4030_MODULE_RTC, rtc_data, + ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data, REG_ALARM_SECONDS_REG, ALL_TIME_REGS); if (ret < 0) { dev_err(dev, "rtc_read_alarm error %d\n", ret); @@ -288,12 +288,12 @@ static int twl4030_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) return ret; } -static int twl4030_rtc_set_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]; int ret; - ret = twl4030_rtc_alarm_irq_enable(dev, 0); + ret = twl_rtc_alarm_irq_enable(dev, 0); if (ret) goto out; @@ -305,7 +305,7 @@ static int twl4030_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(TWL4030_MODULE_RTC, alarm_data, + ret = twl_i2c_write(TWL_MODULE_RTC, alarm_data, REG_ALARM_SECONDS_REG, ALL_TIME_REGS); if (ret) { dev_err(dev, "rtc_set_alarm error %d\n", ret); @@ -313,12 +313,12 @@ static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) } if (alm->enabled) - ret = twl4030_rtc_alarm_irq_enable(dev, 1); + ret = twl_rtc_alarm_irq_enable(dev, 1); out: return ret; } -static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) +static irqreturn_t twl_rtc_interrupt(int irq, void *rtc) { unsigned long events = 0; int ret = IRQ_NONE; @@ -333,7 +333,7 @@ static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) local_irq_enable(); #endif - res = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); + res = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); if (res) goto out; /* @@ -347,14 +347,14 @@ static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) else events |= RTC_IRQF | RTC_UF; - res = twl4030_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M, + res = twl_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M, REG_RTC_STATUS_REG); if (res) goto out; /* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1 * needs 2 reads to clear the interrupt. One read is done in - * do_twl4030_pwrirq(). Doing the second read, to clear + * do_twl_pwrirq(). Doing the second read, to clear * the bit. * * FIXME the reason PWR_ISR1 needs an extra read is that @@ -376,18 +376,18 @@ out: return ret; } -static struct rtc_class_ops twl4030_rtc_ops = { - .read_time = twl4030_rtc_read_time, - .set_time = twl4030_rtc_set_time, - .read_alarm = twl4030_rtc_read_alarm, - .set_alarm = twl4030_rtc_set_alarm, - .alarm_irq_enable = twl4030_rtc_alarm_irq_enable, - .update_irq_enable = twl4030_rtc_update_irq_enable, +static struct rtc_class_ops twl_rtc_ops = { + .read_time = twl_rtc_read_time, + .set_time = twl_rtc_set_time, + .read_alarm = twl_rtc_read_alarm, + .set_alarm = twl_rtc_set_alarm, + .alarm_irq_enable = twl_rtc_alarm_irq_enable, + .update_irq_enable = twl_rtc_update_irq_enable, }; /*----------------------------------------------------------------------*/ -static int __devinit twl4030_rtc_probe(struct platform_device *pdev) +static int __devinit twl_rtc_probe(struct platform_device *pdev) { struct rtc_device *rtc; int ret = 0; @@ -398,7 +398,7 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) return -EINVAL; rtc = rtc_device_register(pdev->name, - &pdev->dev, &twl4030_rtc_ops, THIS_MODULE); + &pdev->dev, &twl_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { ret = PTR_ERR(rtc); dev_err(&pdev->dev, "can't register RTC device, err %ld\n", @@ -409,7 +409,7 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc); - ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); + ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); if (ret < 0) goto out1; @@ -420,11 +420,11 @@ static int __devinit twl4030_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 = twl4030_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); + ret = twl_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); if (ret < 0) goto out1; - ret = request_irq(irq, twl4030_rtc_interrupt, + ret = request_irq(irq, twl_rtc_interrupt, IRQF_TRIGGER_RISING, dev_name(&rtc->dev), rtc); if (ret < 0) { @@ -433,20 +433,20 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) } /* Check RTC module status, Enable if it is off */ - ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); + ret = twl_rtc_read_u8(&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 TWL4030-RTC.\n"); + dev_info(&pdev->dev, "Enabling TWL-RTC.\n"); rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; - ret = twl4030_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); + ret = twl_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); if (ret < 0) goto out2; } /* init cached IRQ enable bits */ - ret = twl4030_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); + ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); if (ret < 0) goto out2; @@ -461,10 +461,10 @@ out0: } /* - * Disable all TWL4030 RTC module interrupts. + * Disable all TWL RTC module interrupts. * Sets status flag to free. */ -static int __devexit twl4030_rtc_remove(struct platform_device *pdev) +static int __devexit twl_rtc_remove(struct platform_device *pdev) { /* leave rtc running, but disable irqs */ struct rtc_device *rtc = platform_get_drvdata(pdev); @@ -480,7 +480,7 @@ static int __devexit twl4030_rtc_remove(struct platform_device *pdev) return 0; } -static void twl4030_rtc_shutdown(struct platform_device *pdev) +static void twl_rtc_shutdown(struct platform_device *pdev) { /* mask timer interrupts, but leave alarm interrupts on to enable power-on when alarm is triggered */ @@ -491,7 +491,7 @@ static void twl4030_rtc_shutdown(struct platform_device *pdev) static unsigned char irqstat; -static int twl4030_rtc_suspend(struct platform_device *pdev, pm_message_t state) +static int twl_rtc_suspend(struct platform_device *pdev, pm_message_t state) { irqstat = rtc_irq_bits; @@ -499,42 +499,42 @@ static int twl4030_rtc_suspend(struct platform_device *pdev, pm_message_t state) return 0; } -static int twl4030_rtc_resume(struct platform_device *pdev) +static int twl_rtc_resume(struct platform_device *pdev) { set_rtc_irq_bit(irqstat); return 0; } #else -#define twl4030_rtc_suspend NULL -#define twl4030_rtc_resume NULL +#define twl_rtc_suspend NULL +#define twl_rtc_resume NULL #endif -MODULE_ALIAS("platform:twl4030_rtc"); +MODULE_ALIAS("platform:twl_rtc"); static struct platform_driver twl4030rtc_driver = { - .probe = twl4030_rtc_probe, - .remove = __devexit_p(twl4030_rtc_remove), - .shutdown = twl4030_rtc_shutdown, - .suspend = twl4030_rtc_suspend, - .resume = twl4030_rtc_resume, + .probe = twl_rtc_probe, + .remove = __devexit_p(twl_rtc_remove), + .shutdown = twl_rtc_shutdown, + .suspend = twl_rtc_suspend, + .resume = twl_rtc_resume, .driver = { .owner = THIS_MODULE, - .name = "twl4030_rtc", + .name = "twl_rtc", }, }; -static int __init twl4030_rtc_init(void) +static int __init twl_rtc_init(void) { return platform_driver_register(&twl4030rtc_driver); } -module_init(twl4030_rtc_init); +module_init(twl_rtc_init); -static void __exit twl4030_rtc_exit(void) +static void __exit twl_rtc_exit(void) { platform_driver_unregister(&twl4030rtc_driver); } -module_exit(twl4030_rtc_exit); +module_exit(twl_rtc_exit); MODULE_AUTHOR("Texas Instruments, MontaVista Software"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From a6b49ffd2d4bba53ad172b1e78ee51fe15ab195e Mon Sep 17 00:00:00 2001 From: Balaji T K Date: Sun, 13 Dec 2009 22:16:31 +0100 Subject: rtc: Add twl6030 RTC support This patch adds support for RTC in phoenix TWL6030. Register offset addresses have changed in TWL6030 rtc-twl.c will hence forth support all twl RTC (4030, 5030, 6030 ..) Signed-off-by: Balaji T K Signed-off-by: Santosh Shilimkar Reviewed-by: Tony Lindgren Reviewed-by: Kevin Hilman Signed-off-by: Samuel Ortiz --- drivers/rtc/Kconfig | 6 +- drivers/rtc/rtc-twl.c | 152 ++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 114 insertions(+), 44 deletions(-) (limited to 'drivers/rtc') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index f2e1004d12c7..71fbd6e8edf7 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -258,14 +258,14 @@ config RTC_DRV_TWL92330 the Menelaus driver; it's not separate module. config RTC_DRV_TWL4030 - tristate "TI TWL4030/TWL5030/TPS659x0" + tristate "TI TWL4030/TWL5030/TWL6030/TPS659x0" depends on RTC_CLASS && TWL4030_CORE help If you say yes here you get support for the RTC on the - TWL4030 family chips, used mostly with OMAP3 platforms. + TWL4030/TWL5030/TWL6030 family chips, used mostly with OMAP3 platforms. This driver can also be built as a module. If so, the module - will be called rtc-twl4030. + will be called rtc-twl. config RTC_DRV_S35390A tristate "Seiko Instruments S-35390A" diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index 7cea920ff6ac..c6a83a2a722c 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c @@ -34,27 +34,75 @@ /* * RTC block register offsets (use TWL_MODULE_RTC) */ -#define REG_SECONDS_REG 0x00 -#define REG_MINUTES_REG 0x01 -#define REG_HOURS_REG 0x02 -#define REG_DAYS_REG 0x03 -#define REG_MONTHS_REG 0x04 -#define REG_YEARS_REG 0x05 -#define REG_WEEKS_REG 0x06 - -#define REG_ALARM_SECONDS_REG 0x07 -#define REG_ALARM_MINUTES_REG 0x08 -#define REG_ALARM_HOURS_REG 0x09 -#define REG_ALARM_DAYS_REG 0x0A -#define REG_ALARM_MONTHS_REG 0x0B -#define REG_ALARM_YEARS_REG 0x0C - -#define REG_RTC_CTRL_REG 0x0D -#define REG_RTC_STATUS_REG 0x0E -#define REG_RTC_INTERRUPTS_REG 0x0F - -#define REG_RTC_COMP_LSB_REG 0x10 -#define REG_RTC_COMP_MSB_REG 0x11 +enum { + REG_SECONDS_REG = 0, + REG_MINUTES_REG, + REG_HOURS_REG, + REG_DAYS_REG, + REG_MONTHS_REG, + REG_YEARS_REG, + REG_WEEKS_REG, + + REG_ALARM_SECONDS_REG, + REG_ALARM_MINUTES_REG, + REG_ALARM_HOURS_REG, + REG_ALARM_DAYS_REG, + REG_ALARM_MONTHS_REG, + REG_ALARM_YEARS_REG, + + REG_RTC_CTRL_REG, + REG_RTC_STATUS_REG, + REG_RTC_INTERRUPTS_REG, + + REG_RTC_COMP_LSB_REG, + REG_RTC_COMP_MSB_REG, +}; +const static u8 twl4030_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] = 0x07, + [REG_ALARM_MINUTES_REG] = 0x08, + [REG_ALARM_HOURS_REG] = 0x09, + [REG_ALARM_DAYS_REG] = 0x0A, + [REG_ALARM_MONTHS_REG] = 0x0B, + [REG_ALARM_YEARS_REG] = 0x0C, + + [REG_RTC_CTRL_REG] = 0x0D, + [REG_RTC_STATUS_REG] = 0x0E, + [REG_RTC_INTERRUPTS_REG] = 0x0F, + + [REG_RTC_COMP_LSB_REG] = 0x10, + [REG_RTC_COMP_MSB_REG] = 0x11, +}; +const static u8 twl6030_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, +}; /* RTC_CTRL_REG bitfields */ #define BIT_RTC_CTRL_REG_STOP_RTC_M 0x01 @@ -84,6 +132,7 @@ #define ALL_TIME_REGS 6 /*----------------------------------------------------------------------*/ +static u8 *rtc_reg_map; /* * Supports 1 byte read from TWL RTC register. @@ -92,7 +141,7 @@ static int twl_rtc_read_u8(u8 *data, u8 reg) { int ret; - ret = twl_i2c_read_u8(TWL_MODULE_RTC, data, reg); + 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); @@ -106,7 +155,7 @@ static int twl_rtc_write_u8(u8 data, u8 reg) { int ret; - ret = twl_i2c_write_u8(TWL_MODULE_RTC, data, reg); + 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); @@ -202,7 +251,7 @@ static int twl_rtc_read_time(struct device *dev, struct rtc_time *tm) return ret; ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data, - REG_SECONDS_REG, ALL_TIME_REGS); + (rtc_reg_map[REG_SECONDS_REG]), ALL_TIME_REGS); if (ret < 0) { dev_err(dev, "rtc_read_time error %d\n", ret); @@ -244,7 +293,7 @@ static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm) /* update all the time registers in one shot */ ret = twl_i2c_write(TWL_MODULE_RTC, rtc_data, - REG_SECONDS_REG, ALL_TIME_REGS); + (rtc_reg_map[REG_SECONDS_REG]), ALL_TIME_REGS); if (ret < 0) { dev_err(dev, "rtc_set_time error %d\n", ret); goto out; @@ -267,7 +316,7 @@ static int twl_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) int ret; ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data, - REG_ALARM_SECONDS_REG, ALL_TIME_REGS); + (rtc_reg_map[REG_ALARM_SECONDS_REG]), ALL_TIME_REGS); if (ret < 0) { dev_err(dev, "rtc_read_alarm error %d\n", ret); return ret; @@ -306,7 +355,7 @@ static int twl_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) /* update all the alarm registers in one shot */ ret = twl_i2c_write(TWL_MODULE_RTC, alarm_data, - REG_ALARM_SECONDS_REG, ALL_TIME_REGS); + (rtc_reg_map[REG_ALARM_SECONDS_REG]), ALL_TIME_REGS); if (ret) { dev_err(dev, "rtc_set_alarm error %d\n", ret); goto out; @@ -352,21 +401,23 @@ static irqreturn_t twl_rtc_interrupt(int irq, void *rtc) if (res) goto out; - /* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1 - * needs 2 reads to clear the interrupt. One read is done in - * do_twl_pwrirq(). Doing the second read, to clear - * the bit. - * - * FIXME the reason PWR_ISR1 needs an extra read is that - * RTC_IF retriggered until we cleared REG_ALARM_M above. - * But re-reading like this is a bad hack; by doing so we - * risk wrongly clearing status for some other IRQ (losing - * the interrupt). Be smarter about handling RTC_UF ... - */ - res = twl_i2c_read_u8(TWL4030_MODULE_INT, + if (twl_class_is_4030()) { + /* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1 + * needs 2 reads to clear the interrupt. One read is done in + * do_twl_pwrirq(). Doing the second read, to clear + * the bit. + * + * FIXME the reason PWR_ISR1 needs an extra read is that + * RTC_IF retriggered until we cleared REG_ALARM_M above. + * But re-reading like this is a bad hack; by doing so we + * risk wrongly clearing status for some other IRQ (losing + * the interrupt). Be smarter about handling RTC_UF ... + */ + res = twl_i2c_read_u8(TWL4030_MODULE_INT, &rd_reg, TWL4030_INT_PWR_ISR1); - if (res) - goto out; + if (res) + goto out; + } /* Notify RTC core on event */ rtc_update_irq(rtc, 1, events); @@ -432,6 +483,13 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev) goto out1; } + if (twl_class_is_6030()) { + twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, + 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); if (ret < 0) @@ -472,6 +530,13 @@ static int __devexit twl_rtc_remove(struct platform_device *pdev) mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); + if (twl_class_is_6030()) { + twl6030_interrupt_mask(TWL6030_RTC_INT_MASK, + REG_INT_MSK_LINE_A); + twl6030_interrupt_mask(TWL6030_RTC_INT_MASK, + REG_INT_MSK_STS_A); + } + free_irq(irq, rtc); @@ -526,6 +591,11 @@ static struct platform_driver twl4030rtc_driver = { static int __init twl_rtc_init(void) { + if (twl_class_is_4030()) + rtc_reg_map = (u8 *) twl4030_rtc_reg_map; + else + rtc_reg_map = (u8 *) twl6030_rtc_reg_map; + return platform_driver_register(&twl4030rtc_driver); } module_init(twl_rtc_init); -- cgit v1.2.3