diff options
Diffstat (limited to 'drivers/rtc/rtc-nuc900.c')
| -rw-r--r-- | drivers/rtc/rtc-nuc900.c | 64 | 
1 files changed, 33 insertions, 31 deletions
| diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c index a351bd5d8176..62de66af0a68 100644 --- a/drivers/rtc/rtc-nuc900.c +++ b/drivers/rtc/rtc-nuc900.c | |||
| @@ -85,25 +85,24 @@ static irqreturn_t nuc900_rtc_interrupt(int irq, void *_rtc) | |||
| 85 | 85 | ||
| 86 | static int *check_rtc_access_enable(struct nuc900_rtc *nuc900_rtc) | 86 | static int *check_rtc_access_enable(struct nuc900_rtc *nuc900_rtc) | 
| 87 | { | 87 | { | 
| 88 | unsigned int i; | 88 | unsigned int timeout = 0x1000; | 
| 89 | __raw_writel(INIRRESET, nuc900_rtc->rtc_reg + REG_RTC_INIR); | 89 | __raw_writel(INIRRESET, nuc900_rtc->rtc_reg + REG_RTC_INIR); | 
| 90 | 90 | ||
| 91 | mdelay(10); | 91 | mdelay(10); | 
| 92 | 92 | ||
| 93 | __raw_writel(AERPOWERON, nuc900_rtc->rtc_reg + REG_RTC_AER); | 93 | __raw_writel(AERPOWERON, nuc900_rtc->rtc_reg + REG_RTC_AER); | 
| 94 | 94 | ||
| 95 | for (i = 0; i < 1000; i++) { | 95 | while (!(__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_AER) & AERRWENB) | 
| 96 | if (__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_AER) & AERRWENB) | 96 | && timeout--) | 
| 97 | return 0; | 97 | mdelay(1); | 
| 98 | } | ||
| 99 | 98 | ||
| 100 | if ((__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_AER) & AERRWENB) == 0x0) | 99 | if (!timeout) | 
| 101 | return ERR_PTR(-ENODEV); | 100 | return ERR_PTR(-EPERM); | 
| 102 | 101 | ||
| 103 | return ERR_PTR(-EPERM); | 102 | return 0; | 
| 104 | } | 103 | } | 
| 105 | 104 | ||
| 106 | static void nuc900_rtc_bcd2bin(unsigned int timereg, | 105 | static int nuc900_rtc_bcd2bin(unsigned int timereg, | 
| 107 | unsigned int calreg, struct rtc_time *tm) | 106 | unsigned int calreg, struct rtc_time *tm) | 
| 108 | { | 107 | { | 
| 109 | tm->tm_mday = bcd2bin(calreg >> 0); | 108 | tm->tm_mday = bcd2bin(calreg >> 0); | 
| @@ -114,15 +113,21 @@ static void nuc900_rtc_bcd2bin(unsigned int timereg, | |||
| 114 | tm->tm_min = bcd2bin(timereg >> 8); | 113 | tm->tm_min = bcd2bin(timereg >> 8); | 
| 115 | tm->tm_hour = bcd2bin(timereg >> 16); | 114 | tm->tm_hour = bcd2bin(timereg >> 16); | 
| 116 | 115 | ||
| 117 | rtc_valid_tm(tm); | 116 | return rtc_valid_tm(tm); | 
| 118 | } | 117 | } | 
| 119 | 118 | ||
| 120 | static void nuc900_rtc_bin2bcd(struct rtc_time *settm, | 119 | static void nuc900_rtc_bin2bcd(struct device *dev, struct rtc_time *settm, | 
| 121 | struct nuc900_bcd_time *gettm) | 120 | struct nuc900_bcd_time *gettm) | 
| 122 | { | 121 | { | 
| 123 | gettm->bcd_mday = bin2bcd(settm->tm_mday) << 0; | 122 | gettm->bcd_mday = bin2bcd(settm->tm_mday) << 0; | 
| 124 | gettm->bcd_mon = bin2bcd(settm->tm_mon) << 8; | 123 | gettm->bcd_mon = bin2bcd(settm->tm_mon) << 8; | 
| 125 | gettm->bcd_year = bin2bcd(settm->tm_year - 100) << 16; | 124 | |
| 125 | if (settm->tm_year < 100) { | ||
| 126 | dev_warn(dev, "The year will be between 1970-1999, right?\n"); | ||
| 127 | gettm->bcd_year = bin2bcd(settm->tm_year) << 16; | ||
| 128 | } else { | ||
| 129 | gettm->bcd_year = bin2bcd(settm->tm_year - 100) << 16; | ||
| 130 | } | ||
| 126 | 131 | ||
| 127 | gettm->bcd_sec = bin2bcd(settm->tm_sec) << 0; | 132 | gettm->bcd_sec = bin2bcd(settm->tm_sec) << 0; | 
| 128 | gettm->bcd_min = bin2bcd(settm->tm_min) << 8; | 133 | gettm->bcd_min = bin2bcd(settm->tm_min) << 8; | 
| @@ -165,9 +170,7 @@ static int nuc900_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
| 165 | timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TLR); | 170 | timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TLR); | 
| 166 | clrval = __raw_readl(rtc->rtc_reg + REG_RTC_CLR); | 171 | clrval = __raw_readl(rtc->rtc_reg + REG_RTC_CLR); | 
| 167 | 172 | ||
| 168 | nuc900_rtc_bcd2bin(timeval, clrval, tm); | 173 | return nuc900_rtc_bcd2bin(timeval, clrval, tm); | 
| 169 | |||
| 170 | return 0; | ||
| 171 | } | 174 | } | 
| 172 | 175 | ||
| 173 | static int nuc900_rtc_set_time(struct device *dev, struct rtc_time *tm) | 176 | static int nuc900_rtc_set_time(struct device *dev, struct rtc_time *tm) | 
| @@ -177,7 +180,7 @@ static int nuc900_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
| 177 | unsigned long val; | 180 | unsigned long val; | 
| 178 | int *err; | 181 | int *err; | 
| 179 | 182 | ||
| 180 | nuc900_rtc_bin2bcd(tm, &gettm); | 183 | nuc900_rtc_bin2bcd(dev, tm, &gettm); | 
| 181 | 184 | ||
| 182 | err = check_rtc_access_enable(rtc); | 185 | err = check_rtc_access_enable(rtc); | 
| 183 | if (IS_ERR(err)) | 186 | if (IS_ERR(err)) | 
| @@ -200,9 +203,7 @@ static int nuc900_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 200 | timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TAR); | 203 | timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TAR); | 
| 201 | carval = __raw_readl(rtc->rtc_reg + REG_RTC_CAR); | 204 | carval = __raw_readl(rtc->rtc_reg + REG_RTC_CAR); | 
| 202 | 205 | ||
| 203 | nuc900_rtc_bcd2bin(timeval, carval, &alrm->time); | 206 | return nuc900_rtc_bcd2bin(timeval, carval, &alrm->time); | 
| 204 | |||
| 205 | return 0; | ||
| 206 | } | 207 | } | 
| 207 | 208 | ||
| 208 | static int nuc900_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 209 | static int nuc900_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 
| @@ -212,7 +213,7 @@ static int nuc900_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 212 | unsigned long val; | 213 | unsigned long val; | 
| 213 | int *err; | 214 | int *err; | 
| 214 | 215 | ||
| 215 | nuc900_rtc_bin2bcd(&alrm->time, &tm); | 216 | nuc900_rtc_bin2bcd(dev, &alrm->time, &tm); | 
| 216 | 217 | ||
| 217 | err = check_rtc_access_enable(rtc); | 218 | err = check_rtc_access_enable(rtc); | 
| 218 | if (IS_ERR(err)) | 219 | if (IS_ERR(err)) | 
| @@ -268,29 +269,30 @@ static int __devinit nuc900_rtc_probe(struct platform_device *pdev) | |||
| 268 | goto fail2; | 269 | goto fail2; | 
| 269 | } | 270 | } | 
| 270 | 271 | ||
| 271 | nuc900_rtc->irq_num = platform_get_irq(pdev, 0); | 272 | platform_set_drvdata(pdev, nuc900_rtc); | 
| 272 | if (request_irq(nuc900_rtc->irq_num, nuc900_rtc_interrupt, | ||
| 273 | IRQF_DISABLED, "nuc900rtc", nuc900_rtc)) { | ||
| 274 | dev_err(&pdev->dev, "NUC900 RTC request irq failed\n"); | ||
| 275 | err = -EBUSY; | ||
| 276 | goto fail3; | ||
| 277 | } | ||
| 278 | 273 | ||
| 279 | nuc900_rtc->rtcdev = rtc_device_register(pdev->name, &pdev->dev, | 274 | nuc900_rtc->rtcdev = rtc_device_register(pdev->name, &pdev->dev, | 
| 280 | &nuc900_rtc_ops, THIS_MODULE); | 275 | &nuc900_rtc_ops, THIS_MODULE); | 
| 281 | if (IS_ERR(nuc900_rtc->rtcdev)) { | 276 | if (IS_ERR(nuc900_rtc->rtcdev)) { | 
| 282 | dev_err(&pdev->dev, "rtc device register faild\n"); | 277 | dev_err(&pdev->dev, "rtc device register faild\n"); | 
| 283 | err = PTR_ERR(nuc900_rtc->rtcdev); | 278 | err = PTR_ERR(nuc900_rtc->rtcdev); | 
| 284 | goto fail4; | 279 | goto fail3; | 
| 285 | } | 280 | } | 
| 286 | 281 | ||
| 287 | platform_set_drvdata(pdev, nuc900_rtc); | ||
| 288 | __raw_writel(__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_TSSR) | MODE24, | 282 | __raw_writel(__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_TSSR) | MODE24, | 
| 289 | nuc900_rtc->rtc_reg + REG_RTC_TSSR); | 283 | nuc900_rtc->rtc_reg + REG_RTC_TSSR); | 
| 290 | 284 | ||
| 285 | nuc900_rtc->irq_num = platform_get_irq(pdev, 0); | ||
| 286 | if (request_irq(nuc900_rtc->irq_num, nuc900_rtc_interrupt, | ||
| 287 | IRQF_DISABLED, "nuc900rtc", nuc900_rtc)) { | ||
| 288 | dev_err(&pdev->dev, "NUC900 RTC request irq failed\n"); | ||
| 289 | err = -EBUSY; | ||
| 290 | goto fail4; | ||
| 291 | } | ||
| 292 | |||
| 291 | return 0; | 293 | return 0; | 
| 292 | 294 | ||
| 293 | fail4: free_irq(nuc900_rtc->irq_num, nuc900_rtc); | 295 | fail4: rtc_device_unregister(nuc900_rtc->rtcdev); | 
| 294 | fail3: iounmap(nuc900_rtc->rtc_reg); | 296 | fail3: iounmap(nuc900_rtc->rtc_reg); | 
| 295 | fail2: release_mem_region(res->start, resource_size(res)); | 297 | fail2: release_mem_region(res->start, resource_size(res)); | 
| 296 | fail1: kfree(nuc900_rtc); | 298 | fail1: kfree(nuc900_rtc); | 
| @@ -302,8 +304,8 @@ static int __devexit nuc900_rtc_remove(struct platform_device *pdev) | |||
| 302 | struct nuc900_rtc *nuc900_rtc = platform_get_drvdata(pdev); | 304 | struct nuc900_rtc *nuc900_rtc = platform_get_drvdata(pdev); | 
| 303 | struct resource *res; | 305 | struct resource *res; | 
| 304 | 306 | ||
| 305 | rtc_device_unregister(nuc900_rtc->rtcdev); | ||
| 306 | free_irq(nuc900_rtc->irq_num, nuc900_rtc); | 307 | free_irq(nuc900_rtc->irq_num, nuc900_rtc); | 
| 308 | rtc_device_unregister(nuc900_rtc->rtcdev); | ||
| 307 | iounmap(nuc900_rtc->rtc_reg); | 309 | iounmap(nuc900_rtc->rtc_reg); | 
| 308 | 310 | ||
| 309 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 311 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 
