diff options
| author | Jett.Zhou <jtzhou@marvell.com> | 2011-11-29 23:26:23 -0500 |
|---|---|---|
| committer | Arnd Bergmann <arnd@arndb.de> | 2011-12-28 05:42:38 -0500 |
| commit | 7cea00657dd4daef66ad95e976d5d67ed94cb97e (patch) | |
| tree | aac948c4fbc5e12c53e7c7eeb1cb11e2e9afb199 /drivers/rtc | |
| parent | 42874759d7494648e42e6e0465fc9c4f3752bba4 (diff) | |
RTC: sa1100: support sa1100, pxa and mmp soc families
Since the regmap of rtc on sa1100, pxa and mmp Marvell soc families are
almost the same, so re-arch the rtc-sa1100 to support them.
Signed-off-by: Jett.Zhou <jtzhou@marvell.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Haojian Zhuang <haojian.zhuang@gmail.com>
Acked-by: Robert Jarzmik <robert.jarzmik@free.fr>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'drivers/rtc')
| -rw-r--r-- | drivers/rtc/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/rtc/rtc-sa1100.c | 256 |
2 files changed, 178 insertions, 80 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 53eb4e55b289..877cf6fdcf24 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
| @@ -774,7 +774,7 @@ config RTC_DRV_EP93XX | |||
| 774 | 774 | ||
| 775 | config RTC_DRV_SA1100 | 775 | config RTC_DRV_SA1100 |
| 776 | tristate "SA11x0/PXA2xx" | 776 | tristate "SA11x0/PXA2xx" |
| 777 | depends on ARCH_SA1100 || ARCH_PXA | 777 | depends on ARCH_SA1100 || ARCH_PXA || ARCH_MMP |
| 778 | help | 778 | help |
| 779 | If you say Y here you will get access to the real time clock | 779 | If you say Y here you will get access to the real time clock |
| 780 | built into your SA11x0 or PXA2xx CPU. | 780 | built into your SA11x0 or PXA2xx CPU. |
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index d268cf11b367..fc1ffe97fca1 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c | |||
| @@ -27,24 +27,42 @@ | |||
| 27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
| 28 | #include <linux/fs.h> | 28 | #include <linux/fs.h> |
| 29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
| 30 | #include <linux/string.h> | ||
| 31 | #include <linux/pm.h> | 30 | #include <linux/pm.h> |
| 32 | #include <linux/bitops.h> | 31 | #include <linux/slab.h> |
| 32 | #include <linux/clk.h> | ||
| 33 | #include <linux/io.h> | ||
| 33 | 34 | ||
| 34 | #include <mach/hardware.h> | 35 | #include <mach/hardware.h> |
| 35 | #include <asm/irq.h> | 36 | #include <asm/irq.h> |
| 36 | 37 | ||
| 37 | #ifdef CONFIG_ARCH_PXA | ||
| 38 | #include <mach/regs-rtc.h> | ||
| 39 | #endif | ||
| 40 | |||
| 41 | #define RTC_DEF_DIVIDER (32768 - 1) | 38 | #define RTC_DEF_DIVIDER (32768 - 1) |
| 42 | #define RTC_DEF_TRIM 0 | 39 | #define RTC_DEF_TRIM 0 |
| 43 | 40 | #define RTC_FREQ 1024 | |
| 44 | static const unsigned long RTC_FREQ = 1024; | 41 | |
| 45 | static struct rtc_time rtc_alarm; | 42 | #define RCNR 0x00 /* RTC Count Register */ |
| 46 | static DEFINE_SPINLOCK(sa1100_rtc_lock); | 43 | #define RTAR 0x04 /* RTC Alarm Register */ |
| 47 | 44 | #define RTSR 0x08 /* RTC Status Register */ | |
| 45 | #define RTTR 0x0c /* RTC Timer Trim Register */ | ||
| 46 | |||
| 47 | #define RTSR_HZE (1 << 3) /* HZ interrupt enable */ | ||
| 48 | #define RTSR_ALE (1 << 2) /* RTC alarm interrupt enable */ | ||
| 49 | #define RTSR_HZ (1 << 1) /* HZ rising-edge detected */ | ||
| 50 | #define RTSR_AL (1 << 0) /* RTC alarm detected */ | ||
| 51 | |||
| 52 | #define rtc_readl(sa1100_rtc, reg) \ | ||
| 53 | readl_relaxed((sa1100_rtc)->base + (reg)) | ||
| 54 | #define rtc_writel(sa1100_rtc, reg, value) \ | ||
| 55 | writel_relaxed((value), (sa1100_rtc)->base + (reg)) | ||
| 56 | |||
| 57 | struct sa1100_rtc { | ||
| 58 | struct resource *ress; | ||
| 59 | void __iomem *base; | ||
| 60 | struct clk *clk; | ||
| 61 | int irq_1Hz; | ||
| 62 | int irq_Alrm; | ||
| 63 | struct rtc_device *rtc; | ||
| 64 | spinlock_t lock; /* Protects this structure */ | ||
| 65 | }; | ||
| 48 | /* | 66 | /* |
| 49 | * Calculate the next alarm time given the requested alarm time mask | 67 | * Calculate the next alarm time given the requested alarm time mask |
| 50 | * and the current time. | 68 | * and the current time. |
| @@ -75,22 +93,23 @@ static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, | |||
| 75 | static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) | 93 | static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) |
| 76 | { | 94 | { |
| 77 | struct platform_device *pdev = to_platform_device(dev_id); | 95 | struct platform_device *pdev = to_platform_device(dev_id); |
| 78 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 96 | struct sa1100_rtc *sa1100_rtc = platform_get_drvdata(pdev); |
| 79 | unsigned int rtsr; | 97 | unsigned int rtsr; |
| 80 | unsigned long events = 0; | 98 | unsigned long events = 0; |
| 81 | 99 | ||
| 82 | spin_lock(&sa1100_rtc_lock); | 100 | spin_lock(&sa1100_rtc->lock); |
| 83 | 101 | ||
| 84 | rtsr = RTSR; | ||
| 85 | /* clear interrupt sources */ | 102 | /* clear interrupt sources */ |
| 86 | RTSR = 0; | 103 | rtsr = rtc_readl(sa1100_rtc, RTSR); |
| 104 | rtc_writel(sa1100_rtc, RTSR, 0); | ||
| 105 | |||
| 87 | /* Fix for a nasty initialization problem the in SA11xx RTSR register. | 106 | /* Fix for a nasty initialization problem the in SA11xx RTSR register. |
| 88 | * See also the comments in sa1100_rtc_probe(). */ | 107 | * See also the comments in sa1100_rtc_probe(). */ |
| 89 | if (rtsr & (RTSR_ALE | RTSR_HZE)) { | 108 | if (rtsr & (RTSR_ALE | RTSR_HZE)) { |
| 90 | /* This is the original code, before there was the if test | 109 | /* This is the original code, before there was the if test |
| 91 | * above. This code does not clear interrupts that were not | 110 | * above. This code does not clear interrupts that were not |
| 92 | * enabled. */ | 111 | * enabled. */ |
| 93 | RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2); | 112 | rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ) & (rtsr >> 2)); |
| 94 | } else { | 113 | } else { |
| 95 | /* For some reason, it is possible to enter this routine | 114 | /* For some reason, it is possible to enter this routine |
| 96 | * without interruptions enabled, it has been tested with | 115 | * without interruptions enabled, it has been tested with |
| @@ -99,13 +118,13 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) | |||
| 99 | * This situation leads to an infinite "loop" of interrupt | 118 | * This situation leads to an infinite "loop" of interrupt |
| 100 | * routine calling and as a result the processor seems to | 119 | * routine calling and as a result the processor seems to |
| 101 | * lock on its first call to open(). */ | 120 | * lock on its first call to open(). */ |
| 102 | RTSR = RTSR_AL | RTSR_HZ; | 121 | rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ)); |
| 103 | } | 122 | } |
| 104 | 123 | ||
| 105 | /* clear alarm interrupt if it has occurred */ | 124 | /* clear alarm interrupt if it has occurred */ |
| 106 | if (rtsr & RTSR_AL) | 125 | if (rtsr & RTSR_AL) |
| 107 | rtsr &= ~RTSR_ALE; | 126 | rtsr &= ~RTSR_ALE; |
| 108 | RTSR = rtsr & (RTSR_ALE | RTSR_HZE); | 127 | rtc_writel(sa1100_rtc, RTSR, rtsr & (RTSR_ALE | RTSR_HZE)); |
| 109 | 128 | ||
| 110 | /* update irq data & counter */ | 129 | /* update irq data & counter */ |
| 111 | if (rtsr & RTSR_AL) | 130 | if (rtsr & RTSR_AL) |
| @@ -113,86 +132,100 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) | |||
| 113 | if (rtsr & RTSR_HZ) | 132 | if (rtsr & RTSR_HZ) |
| 114 | events |= RTC_UF | RTC_IRQF; | 133 | events |= RTC_UF | RTC_IRQF; |
| 115 | 134 | ||
| 116 | rtc_update_irq(rtc, 1, events); | 135 | rtc_update_irq(sa1100_rtc->rtc, 1, events); |
| 117 | 136 | ||
| 118 | spin_unlock(&sa1100_rtc_lock); | 137 | spin_unlock(&sa1100_rtc->lock); |
| 119 | 138 | ||
| 120 | return IRQ_HANDLED; | 139 | return IRQ_HANDLED; |
| 121 | } | 140 | } |
| 122 | 141 | ||
| 123 | static int sa1100_rtc_open(struct device *dev) | 142 | static int sa1100_rtc_open(struct device *dev) |
| 124 | { | 143 | { |
| 144 | struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); | ||
| 125 | int ret; | 145 | int ret; |
| 126 | struct platform_device *plat_dev = to_platform_device(dev); | ||
| 127 | struct rtc_device *rtc = platform_get_drvdata(plat_dev); | ||
| 128 | 146 | ||
| 129 | ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED, | 147 | ret = request_irq(sa1100_rtc->irq_1Hz, sa1100_rtc_interrupt, |
| 130 | "rtc 1Hz", dev); | 148 | IRQF_DISABLED, "rtc 1Hz", dev); |
| 131 | if (ret) { | 149 | if (ret) { |
| 132 | dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz); | 150 | dev_err(dev, "IRQ %d already in use.\n", sa1100_rtc->irq_1Hz); |
| 133 | goto fail_ui; | 151 | goto fail_ui; |
| 134 | } | 152 | } |
| 135 | ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED, | 153 | ret = request_irq(sa1100_rtc->irq_Alrm, sa1100_rtc_interrupt, |
| 136 | "rtc Alrm", dev); | 154 | IRQF_DISABLED, "rtc Alrm", dev); |
| 137 | if (ret) { | 155 | if (ret) { |
| 138 | dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm); | 156 | dev_err(dev, "IRQ %d already in use.\n", sa1100_rtc->irq_Alrm); |
| 139 | goto fail_ai; | 157 | goto fail_ai; |
| 140 | } | 158 | } |
| 141 | rtc->max_user_freq = RTC_FREQ; | 159 | sa1100_rtc->rtc->max_user_freq = RTC_FREQ; |
| 142 | rtc_irq_set_freq(rtc, NULL, RTC_FREQ); | 160 | rtc_irq_set_freq(sa1100_rtc->rtc, NULL, RTC_FREQ); |
| 143 | 161 | ||
| 144 | return 0; | 162 | return 0; |
| 145 | 163 | ||
| 146 | fail_ai: | 164 | fail_ai: |
| 147 | free_irq(IRQ_RTC1Hz, dev); | 165 | free_irq(sa1100_rtc->irq_1Hz, dev); |
| 148 | fail_ui: | 166 | fail_ui: |
| 149 | return ret; | 167 | return ret; |
| 150 | } | 168 | } |
| 151 | 169 | ||
| 152 | static void sa1100_rtc_release(struct device *dev) | 170 | static void sa1100_rtc_release(struct device *dev) |
| 153 | { | 171 | { |
| 154 | spin_lock_irq(&sa1100_rtc_lock); | 172 | struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); |
| 155 | RTSR = 0; | ||
| 156 | spin_unlock_irq(&sa1100_rtc_lock); | ||
| 157 | 173 | ||
| 158 | free_irq(IRQ_RTCAlrm, dev); | 174 | spin_lock_irq(&sa1100_rtc->lock); |
| 159 | free_irq(IRQ_RTC1Hz, dev); | 175 | rtc_writel(sa1100_rtc, RTSR, 0); |
| 176 | spin_unlock_irq(&sa1100_rtc->lock); | ||
| 177 | |||
| 178 | free_irq(sa1100_rtc->irq_Alrm, dev); | ||
| 179 | free_irq(sa1100_rtc->irq_1Hz, dev); | ||
| 160 | } | 180 | } |
| 161 | 181 | ||
| 162 | static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | 182 | static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
| 163 | { | 183 | { |
| 164 | spin_lock_irq(&sa1100_rtc_lock); | 184 | struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); |
| 185 | unsigned int rtsr; | ||
| 186 | |||
| 187 | spin_lock_irq(&sa1100_rtc->lock); | ||
| 188 | |||
| 189 | rtsr = rtc_readl(sa1100_rtc, RTSR); | ||
| 165 | if (enabled) | 190 | if (enabled) |
| 166 | RTSR |= RTSR_ALE; | 191 | rtsr |= RTSR_ALE; |
| 167 | else | 192 | else |
| 168 | RTSR &= ~RTSR_ALE; | 193 | rtsr &= ~RTSR_ALE; |
| 169 | spin_unlock_irq(&sa1100_rtc_lock); | 194 | rtc_writel(sa1100_rtc, RTSR, rtsr); |
| 195 | |||
| 196 | spin_unlock_irq(&sa1100_rtc->lock); | ||
| 170 | return 0; | 197 | return 0; |
| 171 | } | 198 | } |
| 172 | 199 | ||
| 173 | static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm) | 200 | static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm) |
| 174 | { | 201 | { |
| 175 | rtc_time_to_tm(RCNR, tm); | 202 | struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); |
| 203 | |||
| 204 | rtc_time_to_tm(rtc_readl(sa1100_rtc, RCNR), tm); | ||
| 176 | return 0; | 205 | return 0; |
| 177 | } | 206 | } |
| 178 | 207 | ||
| 179 | static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm) | 208 | static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm) |
| 180 | { | 209 | { |
| 210 | struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); | ||
| 181 | unsigned long time; | 211 | unsigned long time; |
| 182 | int ret; | 212 | int ret; |
| 183 | 213 | ||
| 184 | ret = rtc_tm_to_time(tm, &time); | 214 | ret = rtc_tm_to_time(tm, &time); |
| 185 | if (ret == 0) | 215 | if (ret == 0) |
| 186 | RCNR = time; | 216 | rtc_writel(sa1100_rtc, RCNR, time); |
| 187 | return ret; | 217 | return ret; |
| 188 | } | 218 | } |
| 189 | 219 | ||
| 190 | static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 220 | static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
| 191 | { | 221 | { |
| 192 | u32 rtsr; | 222 | struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); |
| 223 | unsigned long time; | ||
| 224 | unsigned int rtsr; | ||
| 193 | 225 | ||
| 194 | memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time)); | 226 | time = rtc_readl(sa1100_rtc, RCNR); |
| 195 | rtsr = RTSR; | 227 | rtc_time_to_tm(time, &alrm->time); |
| 228 | rtsr = rtc_readl(sa1100_rtc, RTSR); | ||
| 196 | alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0; | 229 | alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0; |
| 197 | alrm->pending = (rtsr & RTSR_AL) ? 1 : 0; | 230 | alrm->pending = (rtsr & RTSR_AL) ? 1 : 0; |
| 198 | return 0; | 231 | return 0; |
| @@ -200,31 +233,39 @@ static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 200 | 233 | ||
| 201 | static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 234 | static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
| 202 | { | 235 | { |
| 236 | struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); | ||
| 203 | struct rtc_time now_tm, alarm_tm; | 237 | struct rtc_time now_tm, alarm_tm; |
| 204 | int ret; | 238 | unsigned long time, alarm; |
| 239 | unsigned int rtsr; | ||
| 240 | |||
| 241 | spin_lock_irq(&sa1100_rtc->lock); | ||
| 205 | 242 | ||
| 206 | spin_lock_irq(&sa1100_rtc_lock); | 243 | time = rtc_readl(sa1100_rtc, RCNR); |
| 244 | rtc_time_to_tm(time, &now_tm); | ||
| 245 | rtc_next_alarm_time(&alarm_tm, &now_tm, &alrm->time); | ||
| 246 | rtc_tm_to_time(&alarm_tm, &alarm); | ||
| 247 | rtc_writel(sa1100_rtc, RTAR, alarm); | ||
| 207 | 248 | ||
| 208 | now = RCNR; | 249 | rtsr = rtc_readl(sa1100_rtc, RTSR); |
| 209 | rtc_time_to_tm(now, &now_tm); | ||
| 210 | rtc_next_alarm_time(&alarm_tm, &now_tm, alrm->time); | ||
| 211 | rtc_tm_to_time(&alarm_tm, &time); | ||
| 212 | RTAR = time; | ||
| 213 | if (alrm->enabled) | 250 | if (alrm->enabled) |
| 214 | RTSR |= RTSR_ALE; | 251 | rtsr |= RTSR_ALE; |
| 215 | else | 252 | else |
| 216 | RTSR &= ~RTSR_ALE; | 253 | rtsr &= ~RTSR_ALE; |
| 254 | rtc_writel(sa1100_rtc, RTSR, rtsr); | ||
| 217 | 255 | ||
| 218 | spin_unlock_irq(&sa1100_rtc_lock); | 256 | spin_unlock_irq(&sa1100_rtc->lock); |
| 219 | 257 | ||
| 220 | return ret; | 258 | return 0; |
| 221 | } | 259 | } |
| 222 | 260 | ||
| 223 | static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) | 261 | static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) |
| 224 | { | 262 | { |
| 225 | seq_printf(seq, "trim/divider\t\t: 0x%08x\n", (u32) RTTR); | 263 | struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); |
| 226 | seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", (u32)RTSR); | ||
| 227 | 264 | ||
| 265 | seq_printf(seq, "trim/divider\t\t: 0x%08x\n", | ||
| 266 | rtc_readl(sa1100_rtc, RTTR)); | ||
| 267 | seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", | ||
| 268 | rtc_readl(sa1100_rtc, RTSR)); | ||
| 228 | return 0; | 269 | return 0; |
| 229 | } | 270 | } |
| 230 | 271 | ||
| @@ -241,7 +282,51 @@ static const struct rtc_class_ops sa1100_rtc_ops = { | |||
| 241 | 282 | ||
| 242 | static int sa1100_rtc_probe(struct platform_device *pdev) | 283 | static int sa1100_rtc_probe(struct platform_device *pdev) |
| 243 | { | 284 | { |
| 244 | struct rtc_device *rtc; | 285 | struct sa1100_rtc *sa1100_rtc; |
| 286 | unsigned int rttr; | ||
| 287 | int ret; | ||
| 288 | |||
| 289 | sa1100_rtc = kzalloc(sizeof(struct sa1100_rtc), GFP_KERNEL); | ||
| 290 | if (!sa1100_rtc) | ||
| 291 | return -ENOMEM; | ||
| 292 | |||
| 293 | spin_lock_init(&sa1100_rtc->lock); | ||
| 294 | platform_set_drvdata(pdev, sa1100_rtc); | ||
| 295 | |||
| 296 | ret = -ENXIO; | ||
| 297 | sa1100_rtc->ress = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 298 | if (!sa1100_rtc->ress) { | ||
| 299 | dev_err(&pdev->dev, "No I/O memory resource defined\n"); | ||
| 300 | goto err_ress; | ||
| 301 | } | ||
| 302 | |||
| 303 | sa1100_rtc->irq_1Hz = platform_get_irq(pdev, 0); | ||
| 304 | if (sa1100_rtc->irq_1Hz < 0) { | ||
| 305 | dev_err(&pdev->dev, "No 1Hz IRQ resource defined\n"); | ||
| 306 | goto err_ress; | ||
| 307 | } | ||
| 308 | sa1100_rtc->irq_Alrm = platform_get_irq(pdev, 1); | ||
| 309 | if (sa1100_rtc->irq_Alrm < 0) { | ||
| 310 | dev_err(&pdev->dev, "No alarm IRQ resource defined\n"); | ||
| 311 | goto err_ress; | ||
| 312 | } | ||
| 313 | |||
| 314 | ret = -ENOMEM; | ||
| 315 | sa1100_rtc->base = ioremap(sa1100_rtc->ress->start, | ||
| 316 | resource_size(sa1100_rtc->ress)); | ||
| 317 | if (!sa1100_rtc->base) { | ||
| 318 | dev_err(&pdev->dev, "Unable to map pxa RTC I/O memory\n"); | ||
| 319 | goto err_map; | ||
| 320 | } | ||
| 321 | |||
| 322 | sa1100_rtc->clk = clk_get(&pdev->dev, NULL); | ||
| 323 | if (IS_ERR(sa1100_rtc->clk)) { | ||
| 324 | dev_err(&pdev->dev, "failed to find rtc clock source\n"); | ||
| 325 | ret = PTR_ERR(sa1100_rtc->clk); | ||
| 326 | goto err_clk; | ||
| 327 | } | ||
| 328 | clk_prepare(sa1100_rtc->clk); | ||
| 329 | clk_enable(sa1100_rtc->clk); | ||
| 245 | 330 | ||
| 246 | /* | 331 | /* |
| 247 | * According to the manual we should be able to let RTTR be zero | 332 | * According to the manual we should be able to let RTTR be zero |
| @@ -250,24 +335,24 @@ static int sa1100_rtc_probe(struct platform_device *pdev) | |||
| 250 | * If the clock divider is uninitialized then reset it to the | 335 | * If the clock divider is uninitialized then reset it to the |
| 251 | * default value to get the 1Hz clock. | 336 | * default value to get the 1Hz clock. |
| 252 | */ | 337 | */ |
| 253 | if (RTTR == 0) { | 338 | if (rtc_readl(sa1100_rtc, RTTR) == 0) { |
| 254 | RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16); | 339 | rttr = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16); |
| 255 | dev_warn(&pdev->dev, "warning: " | 340 | rtc_writel(sa1100_rtc, RTTR, rttr); |
| 256 | "initializing default clock divider/trim value\n"); | 341 | dev_warn(&pdev->dev, "warning: initializing default clock" |
| 342 | " divider/trim value\n"); | ||
| 257 | /* The current RTC value probably doesn't make sense either */ | 343 | /* The current RTC value probably doesn't make sense either */ |
| 258 | RCNR = 0; | 344 | rtc_writel(sa1100_rtc, RCNR, 0); |
| 259 | } | 345 | } |
| 260 | 346 | ||
| 261 | device_init_wakeup(&pdev->dev, 1); | 347 | device_init_wakeup(&pdev->dev, 1); |
| 262 | 348 | ||
| 263 | rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops, | 349 | sa1100_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, |
| 264 | THIS_MODULE); | 350 | &sa1100_rtc_ops, THIS_MODULE); |
| 265 | 351 | if (IS_ERR(sa1100_rtc->rtc)) { | |
| 266 | if (IS_ERR(rtc)) | 352 | dev_err(&pdev->dev, "Failed to register RTC device -> %d\n", |
| 267 | return PTR_ERR(rtc); | 353 | ret); |
| 268 | 354 | goto err_rtc_reg; | |
| 269 | platform_set_drvdata(pdev, rtc); | 355 | } |
| 270 | |||
| 271 | /* Fix for a nasty initialization problem the in SA11xx RTSR register. | 356 | /* Fix for a nasty initialization problem the in SA11xx RTSR register. |
| 272 | * See also the comments in sa1100_rtc_interrupt(). | 357 | * See also the comments in sa1100_rtc_interrupt(). |
| 273 | * | 358 | * |
| @@ -290,33 +375,46 @@ static int sa1100_rtc_probe(struct platform_device *pdev) | |||
| 290 | * | 375 | * |
| 291 | * Notice that clearing bit 1 and 0 is accomplished by writting ONES to | 376 | * Notice that clearing bit 1 and 0 is accomplished by writting ONES to |
| 292 | * the corresponding bits in RTSR. */ | 377 | * the corresponding bits in RTSR. */ |
| 293 | RTSR = RTSR_AL | RTSR_HZ; | 378 | rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ)); |
| 294 | 379 | ||
| 295 | return 0; | 380 | return 0; |
| 381 | |||
| 382 | err_rtc_reg: | ||
| 383 | err_clk: | ||
| 384 | iounmap(sa1100_rtc->base); | ||
| 385 | err_ress: | ||
| 386 | err_map: | ||
| 387 | kfree(sa1100_rtc); | ||
| 388 | return ret; | ||
| 296 | } | 389 | } |
| 297 | 390 | ||
| 298 | static int sa1100_rtc_remove(struct platform_device *pdev) | 391 | static int sa1100_rtc_remove(struct platform_device *pdev) |
| 299 | { | 392 | { |
| 300 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 393 | struct sa1100_rtc *sa1100_rtc = platform_get_drvdata(pdev); |
| 301 | |||
| 302 | if (rtc) | ||
| 303 | rtc_device_unregister(rtc); | ||
| 304 | 394 | ||
| 395 | rtc_device_unregister(sa1100_rtc->rtc); | ||
| 396 | clk_disable(sa1100_rtc->clk); | ||
| 397 | clk_unprepare(sa1100_rtc->clk); | ||
| 398 | iounmap(sa1100_rtc->base); | ||
| 305 | return 0; | 399 | return 0; |
| 306 | } | 400 | } |
| 307 | 401 | ||
| 308 | #ifdef CONFIG_PM | 402 | #ifdef CONFIG_PM |
| 309 | static int sa1100_rtc_suspend(struct device *dev) | 403 | static int sa1100_rtc_suspend(struct device *dev) |
| 310 | { | 404 | { |
| 405 | struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); | ||
| 406 | |||
| 311 | if (device_may_wakeup(dev)) | 407 | if (device_may_wakeup(dev)) |
| 312 | enable_irq_wake(IRQ_RTCAlrm); | 408 | enable_irq_wake(sa1100_rtc->irq_Alrm); |
| 313 | return 0; | 409 | return 0; |
| 314 | } | 410 | } |
| 315 | 411 | ||
| 316 | static int sa1100_rtc_resume(struct device *dev) | 412 | static int sa1100_rtc_resume(struct device *dev) |
| 317 | { | 413 | { |
| 414 | struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); | ||
| 415 | |||
| 318 | if (device_may_wakeup(dev)) | 416 | if (device_may_wakeup(dev)) |
| 319 | disable_irq_wake(IRQ_RTCAlrm); | 417 | disable_irq_wake(sa1100_rtc->irq_Alrm); |
| 320 | return 0; | 418 | return 0; |
| 321 | } | 419 | } |
| 322 | 420 | ||
