From cab1458c8c4fdfc993e86454eef785bc39517dd8 Mon Sep 17 00:00:00 2001 From: Afzal Mohammed Date: Mon, 17 Dec 2012 16:02:11 -0800 Subject: rtc: omap: kicker mechanism support OMAP RTC IP can have kicker feature. This prevents spurious writes to register. To write to registers kicker lock has to be released. Procedure to do it as follows, 1. write to kick0 register, 0x83e70b13 2. write to kick1 register, 0x95a4f1e0 Writing value other than 0x83e70b13 to kick0 enables write locking, more details about kicker mechanism can be found in section 20.3.3.5.3 of AM335X TRM @www.ti.com/am335x Here id table information is added and is used to distinguish those that require kicker handling and the ones that doesn't need it. There are more features in the newer IP's compared to legacy ones other than kicker, which driver currently doesn't handle, supporting additional features would be easier with the addition of id table. Older IP (of OMAP1) doesn't have revision register as per TRM, so revision register can't be relied always to find features, hence id table is being used. While at it, replace __raw_writeb/__raw_readb with writeb/readb; this driver is used on ARMv7 (AM335X SoC) Signed-off-by: Afzal Mohammed Acked-by: Sekhar Nori Cc: Grant Likely Cc: Sekhar Nori Cc: Kevin Hilman Cc: Russell King Cc: Alessandro Zummo Cc: Daniel Mack Cc: Vaibhav Hiremath Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-omap.c | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) (limited to 'drivers/rtc/rtc-omap.c') diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 0b614e32653..d948426283d 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -38,6 +38,8 @@ * the SoC). See the BOARD-SPECIFIC CUSTOMIZATION comment. */ +#define DRIVER_NAME "omap_rtc" + #define OMAP_RTC_BASE 0xfffb4800 /* RTC registers */ @@ -64,6 +66,9 @@ #define OMAP_RTC_COMP_MSB_REG 0x50 #define OMAP_RTC_OSC_REG 0x54 +#define OMAP_RTC_KICK0_REG 0x6c +#define OMAP_RTC_KICK1_REG 0x70 + /* OMAP_RTC_CTRL_REG bit fields: */ #define OMAP_RTC_CTRL_SPLIT (1<<7) #define OMAP_RTC_CTRL_DISABLE (1<<6) @@ -88,10 +93,18 @@ #define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3) #define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2) +/* OMAP_RTC_KICKER values */ +#define KICK0_VALUE 0x83e70b13 +#define KICK1_VALUE 0x95a4f1e0 + +#define OMAP_RTC_HAS_KICKER 0x1 + static void __iomem *rtc_base; -#define rtc_read(addr) __raw_readb(rtc_base + (addr)) -#define rtc_write(val, addr) __raw_writeb(val, rtc_base + (addr)) +#define rtc_read(addr) readb(rtc_base + (addr)) +#define rtc_write(val, addr) writeb(val, rtc_base + (addr)) + +#define rtc_writel(val, addr) writel(val, rtc_base + (addr)) /* we rely on the rtc framework to handle locking (rtc->ops_lock), @@ -285,11 +298,23 @@ static struct rtc_class_ops omap_rtc_ops = { static int omap_rtc_alarm; static int omap_rtc_timer; +static struct platform_device_id omap_rtc_devtype[] = { + { + .name = DRIVER_NAME, + }, { + .name = "da830-rtc", + .driver_data = OMAP_RTC_HAS_KICKER, + }, + {}, +}; +MODULE_DEVICE_TABLE(platform, omap_rtc_devtype); + static int __init omap_rtc_probe(struct platform_device *pdev) { struct resource *res, *mem; struct rtc_device *rtc; u8 reg, new_ctrl; + const struct platform_device_id *id_entry; omap_rtc_timer = platform_get_irq(pdev, 0); if (omap_rtc_timer <= 0) { @@ -322,6 +347,12 @@ static int __init omap_rtc_probe(struct platform_device *pdev) goto fail; } + id_entry = platform_get_device_id(pdev); + if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) { + rtc_writel(KICK0_VALUE, OMAP_RTC_KICK0_REG); + rtc_writel(KICK1_VALUE, OMAP_RTC_KICK1_REG); + } + rtc = rtc_device_register(pdev->name, &pdev->dev, &omap_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { @@ -398,6 +429,8 @@ fail2: fail1: rtc_device_unregister(rtc); fail0: + if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) + rtc_writel(0, OMAP_RTC_KICK0_REG); iounmap(rtc_base); fail: release_mem_region(mem->start, resource_size(mem)); @@ -408,6 +441,8 @@ static int __exit omap_rtc_remove(struct platform_device *pdev) { struct rtc_device *rtc = platform_get_drvdata(pdev); struct resource *mem = dev_get_drvdata(&rtc->dev); + const struct platform_device_id *id_entry = + platform_get_device_id(pdev); device_init_wakeup(&pdev->dev, 0); @@ -420,6 +455,8 @@ static int __exit omap_rtc_remove(struct platform_device *pdev) free_irq(omap_rtc_alarm, rtc); rtc_device_unregister(rtc); + if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) + rtc_writel(0, OMAP_RTC_KICK0_REG); iounmap(rtc_base); release_mem_region(mem->start, resource_size(mem)); return 0; @@ -471,9 +508,10 @@ static struct platform_driver omap_rtc_driver = { .resume = omap_rtc_resume, .shutdown = omap_rtc_shutdown, .driver = { - .name = "omap_rtc", + .name = DRIVER_NAME, .owner = THIS_MODULE, }, + .id_table = omap_rtc_devtype, }; static int __init rtc_init(void) -- cgit v1.2.3-70-g09d2 From 9e0344dcc225fe1a0e8b8af9ff7df44ec4613580 Mon Sep 17 00:00:00 2001 From: Afzal Mohammed Date: Mon, 17 Dec 2012 16:02:15 -0800 Subject: rtc: omap: dt support Enhance rtc-omap driver with DT capability Signed-off-by: Afzal Mohammed Acked-by: Sekhar Nori Cc: Grant Likely Cc: Sekhar Nori Cc: Kevin Hilman Cc: Russell King Cc: Alessandro Zummo Cc: Daniel Mack Cc: Vaibhav Hiremath Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/devicetree/bindings/rtc/rtc-omap.txt | 17 +++++++++++++++++ drivers/rtc/rtc-omap.c | 18 ++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 Documentation/devicetree/bindings/rtc/rtc-omap.txt (limited to 'drivers/rtc/rtc-omap.c') diff --git a/Documentation/devicetree/bindings/rtc/rtc-omap.txt b/Documentation/devicetree/bindings/rtc/rtc-omap.txt new file mode 100644 index 00000000000..b47aa415c82 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/rtc-omap.txt @@ -0,0 +1,17 @@ +TI Real Time Clock + +Required properties: +- compatible: "ti,da830-rtc" +- reg: Address range of rtc register set +- interrupts: rtc timer, alarm interrupts in order +- interrupt-parent: phandle for the interrupt controller + +Example: + +rtc@1c23000 { + compatible = "ti,da830-rtc"; + reg = <0x23000 0x1000>; + interrupts = <19 + 19>; + interrupt-parent = <&intc>; +}; diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index d948426283d..dff9ff476b0 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include @@ -298,6 +300,8 @@ static struct rtc_class_ops omap_rtc_ops = { static int omap_rtc_alarm; static int omap_rtc_timer; +#define OMAP_RTC_DATA_DA830_IDX 1 + static struct platform_device_id omap_rtc_devtype[] = { { .name = DRIVER_NAME, @@ -309,12 +313,25 @@ static struct platform_device_id omap_rtc_devtype[] = { }; MODULE_DEVICE_TABLE(platform, omap_rtc_devtype); +static const struct of_device_id omap_rtc_of_match[] = { + { .compatible = "ti,da830-rtc", + .data = &omap_rtc_devtype[OMAP_RTC_DATA_DA830_IDX], + }, + {}, +}; +MODULE_DEVICE_TABLE(of, omap_rtc_of_match); + static int __init omap_rtc_probe(struct platform_device *pdev) { struct resource *res, *mem; struct rtc_device *rtc; u8 reg, new_ctrl; const struct platform_device_id *id_entry; + const struct of_device_id *of_id; + + of_id = of_match_device(omap_rtc_of_match, &pdev->dev); + if (of_id) + pdev->id_entry = of_id->data; omap_rtc_timer = platform_get_irq(pdev, 0); if (omap_rtc_timer <= 0) { @@ -510,6 +527,7 @@ static struct platform_driver omap_rtc_driver = { .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, + .of_match_table = of_match_ptr(omap_rtc_of_match), }, .id_table = omap_rtc_devtype, }; -- cgit v1.2.3-70-g09d2 From fc9bd9022e8d5863f3efce34cc38cb0c6187271c Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 17 Dec 2012 16:02:18 -0800 Subject: rtc: omap: add runtime pm support OMAP1 RTC driver is used in multiple devices like, OMAPL138 and AM33XX. Driver currently doesn't handle any clocks, which may be right for OMAP1 architecture but in case of AM33XX, the clock/module needs to be enabled in order to access the registers. So convert this driver to runtime pm, which internally handles rest. [afzal@ti.com: handle error path] Signed-off-by: Vaibhav Hiremath Signed-off-by: Afzal Mohammed Acked-by: Sekhar Nori Cc: Grant Likely Cc: Sekhar Nori Cc: Kevin Hilman Cc: Russell King Cc: Alessandro Zummo Cc: Daniel Mack Cc: Vaibhav Hiremath Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-omap.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/rtc/rtc-omap.c') diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index dff9ff476b0..600971407aa 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -364,6 +365,10 @@ static int __init omap_rtc_probe(struct platform_device *pdev) goto fail; } + /* Enable the clock/module so that we can access the registers */ + pm_runtime_enable(&pdev->dev); + pm_runtime_get_sync(&pdev->dev); + id_entry = platform_get_device_id(pdev); if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) { rtc_writel(KICK0_VALUE, OMAP_RTC_KICK0_REG); @@ -448,6 +453,8 @@ fail1: fail0: if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) rtc_writel(0, OMAP_RTC_KICK0_REG); + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); iounmap(rtc_base); fail: release_mem_region(mem->start, resource_size(mem)); @@ -474,6 +481,11 @@ static int __exit omap_rtc_remove(struct platform_device *pdev) rtc_device_unregister(rtc); if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) rtc_writel(0, OMAP_RTC_KICK0_REG); + + /* Disable the clock/module */ + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); + iounmap(rtc_base); release_mem_region(mem->start, resource_size(mem)); return 0; @@ -496,11 +508,17 @@ static int omap_rtc_suspend(struct platform_device *pdev, pm_message_t state) else rtc_write(0, OMAP_RTC_INTERRUPTS_REG); + /* Disable the clock/module */ + pm_runtime_put_sync(&pdev->dev); + return 0; } static int omap_rtc_resume(struct platform_device *pdev) { + /* Enable the clock/module so that we can access the registers */ + pm_runtime_get_sync(&pdev->dev); + if (device_may_wakeup(&pdev->dev)) disable_irq_wake(omap_rtc_alarm); else -- cgit v1.2.3-70-g09d2