1/* 2 * TX4939 internal RTC driver 3 * Based on RBTX49xx patch from CELF patch archive. 4 * 5 * This file is subject to the terms and conditions of the GNU General Public 6 * License. See the file "COPYING" in the main directory of this archive 7 * for more details. 8 * 9 * (C) Copyright TOSHIBA CORPORATION 2005-2007 10 */ 11#include <linux/rtc.h> 12#include <linux/platform_device.h> 13#include <linux/interrupt.h> 14#include <linux/module.h> 15#include <linux/io.h> 16#include <linux/gfp.h> 17#include <asm/txx9/tx4939.h> 18 19struct tx4939rtc_plat_data { 20 struct rtc_device *rtc; 21 struct tx4939_rtc_reg __iomem *rtcreg; 22 spinlock_t lock; 23}; 24 25static struct tx4939rtc_plat_data *get_tx4939rtc_plat_data(struct device *dev) 26{ 27 return platform_get_drvdata(to_platform_device(dev)); 28} 29 30static int tx4939_rtc_cmd(struct tx4939_rtc_reg __iomem *rtcreg, int cmd) 31{ 32 int i = 0; 33 34 __raw_writel(cmd, &rtcreg->ctl); 35 /* This might take 30us (next 32.768KHz clock) */ 36 while (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_BUSY) { 37 /* timeout on approx. 100us (@ GBUS200MHz) */ 38 if (i++ > 200 * 100) 39 return -EBUSY; 40 cpu_relax(); 41 } 42 return 0; 43} 44 45static int tx4939_rtc_set_mmss(struct device *dev, unsigned long secs) 46{ 47 struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev); 48 struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; 49 int i, ret; 50 unsigned char buf[6]; 51 52 buf[0] = 0; 53 buf[1] = 0; 54 buf[2] = secs; 55 buf[3] = secs >> 8; 56 buf[4] = secs >> 16; 57 buf[5] = secs >> 24; 58 spin_lock_irq(&pdata->lock); 59 __raw_writel(0, &rtcreg->adr); 60 for (i = 0; i < 6; i++) 61 __raw_writel(buf[i], &rtcreg->dat); 62 ret = tx4939_rtc_cmd(rtcreg, 63 TX4939_RTCCTL_COMMAND_SETTIME | 64 (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); 65 spin_unlock_irq(&pdata->lock); 66 return ret; 67} 68 69static int tx4939_rtc_read_time(struct device *dev, struct rtc_time *tm) 70{ 71 struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev); 72 struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; 73 int i, ret; 74 unsigned long sec; 75 unsigned char buf[6]; 76 77 spin_lock_irq(&pdata->lock); 78 ret = tx4939_rtc_cmd(rtcreg, 79 TX4939_RTCCTL_COMMAND_GETTIME | 80 (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); 81 if (ret) { 82 spin_unlock_irq(&pdata->lock); 83 return ret; 84 } 85 __raw_writel(2, &rtcreg->adr); 86 for (i = 2; i < 6; i++) 87 buf[i] = __raw_readl(&rtcreg->dat); 88 spin_unlock_irq(&pdata->lock); 89 sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; 90 rtc_time_to_tm(sec, tm); 91 return rtc_valid_tm(tm); 92} 93 94static int tx4939_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 95{ 96 struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev); 97 struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; 98 int i, ret; 99 unsigned long sec; 100 unsigned char buf[6]; 101 102 if (alrm->time.tm_sec < 0 || 103 alrm->time.tm_min < 0 || 104 alrm->time.tm_hour < 0 || 105 alrm->time.tm_mday < 0 || 106 alrm->time.tm_mon < 0 || 107 alrm->time.tm_year < 0) 108 return -EINVAL; 109 rtc_tm_to_time(&alrm->time, &sec); 110 buf[0] = 0; 111 buf[1] = 0; 112 buf[2] = sec; 113 buf[3] = sec >> 8; 114 buf[4] = sec >> 16; 115 buf[5] = sec >> 24; 116 spin_lock_irq(&pdata->lock); 117 __raw_writel(0, &rtcreg->adr); 118 for (i = 0; i < 6; i++) 119 __raw_writel(buf[i], &rtcreg->dat); 120 ret = tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_SETALARM | 121 (alrm->enabled ? TX4939_RTCCTL_ALME : 0)); 122 spin_unlock_irq(&pdata->lock); 123 return ret; 124} 125 126static int tx4939_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) 127{ 128 struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev); 129 struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; 130 int i, ret; 131 unsigned long sec; 132 unsigned char buf[6]; 133 u32 ctl; 134 135 spin_lock_irq(&pdata->lock); 136 ret = tx4939_rtc_cmd(rtcreg, 137 TX4939_RTCCTL_COMMAND_GETALARM | 138 (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); 139 if (ret) { 140 spin_unlock_irq(&pdata->lock); 141 return ret; 142 } 143 __raw_writel(2, &rtcreg->adr); 144 for (i = 2; i < 6; i++) 145 buf[i] = __raw_readl(&rtcreg->dat); 146 ctl = __raw_readl(&rtcreg->ctl); 147 alrm->enabled = (ctl & TX4939_RTCCTL_ALME) ? 1 : 0; 148 alrm->pending = (ctl & TX4939_RTCCTL_ALMD) ? 1 : 0; 149 spin_unlock_irq(&pdata->lock); 150 sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; 151 rtc_time_to_tm(sec, &alrm->time); 152 return rtc_valid_tm(&alrm->time); 153} 154 155static int tx4939_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) 156{ 157 struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev); 158 159 spin_lock_irq(&pdata->lock); 160 tx4939_rtc_cmd(pdata->rtcreg, 161 TX4939_RTCCTL_COMMAND_NOP | 162 (enabled ? TX4939_RTCCTL_ALME : 0)); 163 spin_unlock_irq(&pdata->lock); 164 return 0; 165} 166 167static irqreturn_t tx4939_rtc_interrupt(int irq, void *dev_id) 168{ 169 struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev_id); 170 struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; 171 unsigned long events = RTC_IRQF; 172 173 spin_lock(&pdata->lock); 174 if (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALMD) { 175 events |= RTC_AF; 176 tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_NOP); 177 } 178 spin_unlock(&pdata->lock); 179 rtc_update_irq(pdata->rtc, 1, events); 180 181 return IRQ_HANDLED; 182} 183 184static const struct rtc_class_ops tx4939_rtc_ops = { 185 .read_time = tx4939_rtc_read_time, 186 .read_alarm = tx4939_rtc_read_alarm, 187 .set_alarm = tx4939_rtc_set_alarm, 188 .set_mmss = tx4939_rtc_set_mmss, 189 .alarm_irq_enable = tx4939_rtc_alarm_irq_enable, 190}; 191 192static ssize_t tx4939_rtc_nvram_read(struct file *filp, struct kobject *kobj, 193 struct bin_attribute *bin_attr, 194 char *buf, loff_t pos, size_t size) 195{ 196 struct device *dev = container_of(kobj, struct device, kobj); 197 struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev); 198 struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; 199 ssize_t count; 200 201 spin_lock_irq(&pdata->lock); 202 for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE; 203 count++, size--) { 204 __raw_writel(pos++, &rtcreg->adr); 205 *buf++ = __raw_readl(&rtcreg->dat); 206 } 207 spin_unlock_irq(&pdata->lock); 208 return count; 209} 210 211static ssize_t tx4939_rtc_nvram_write(struct file *filp, struct kobject *kobj, 212 struct bin_attribute *bin_attr, 213 char *buf, loff_t pos, size_t size) 214{ 215 struct device *dev = container_of(kobj, struct device, kobj); 216 struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev); 217 struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; 218 ssize_t count; 219 220 spin_lock_irq(&pdata->lock); 221 for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE; 222 count++, size--) { 223 __raw_writel(pos++, &rtcreg->adr); 224 __raw_writel(*buf++, &rtcreg->dat); 225 } 226 spin_unlock_irq(&pdata->lock); 227 return count; 228} 229 230static struct bin_attribute tx4939_rtc_nvram_attr = { 231 .attr = { 232 .name = "nvram", 233 .mode = S_IRUGO | S_IWUSR, 234 }, 235 .size = TX4939_RTC_REG_RAMSIZE, 236 .read = tx4939_rtc_nvram_read, 237 .write = tx4939_rtc_nvram_write, 238}; 239 240static int __init tx4939_rtc_probe(struct platform_device *pdev) 241{ 242 struct rtc_device *rtc; 243 struct tx4939rtc_plat_data *pdata; 244 struct resource *res; 245 int irq, ret; 246 247 irq = platform_get_irq(pdev, 0); 248 if (irq < 0) 249 return -ENODEV; 250 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); 251 if (!pdata) 252 return -ENOMEM; 253 platform_set_drvdata(pdev, pdata); 254 255 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 256 pdata->rtcreg = devm_ioremap_resource(&pdev->dev, res); 257 if (IS_ERR(pdata->rtcreg)) 258 return PTR_ERR(pdata->rtcreg); 259 260 spin_lock_init(&pdata->lock); 261 tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP); 262 if (devm_request_irq(&pdev->dev, irq, tx4939_rtc_interrupt, 263 0, pdev->name, &pdev->dev) < 0) 264 return -EBUSY; 265 rtc = devm_rtc_device_register(&pdev->dev, pdev->name, 266 &tx4939_rtc_ops, THIS_MODULE); 267 if (IS_ERR(rtc)) 268 return PTR_ERR(rtc); 269 pdata->rtc = rtc; 270 ret = sysfs_create_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr); 271 272 return ret; 273} 274 275static int __exit tx4939_rtc_remove(struct platform_device *pdev) 276{ 277 struct tx4939rtc_plat_data *pdata = platform_get_drvdata(pdev); 278 279 sysfs_remove_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr); 280 spin_lock_irq(&pdata->lock); 281 tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP); 282 spin_unlock_irq(&pdata->lock); 283 return 0; 284} 285 286static struct platform_driver tx4939_rtc_driver = { 287 .remove = __exit_p(tx4939_rtc_remove), 288 .driver = { 289 .name = "tx4939rtc", 290 .owner = THIS_MODULE, 291 }, 292}; 293 294module_platform_driver_probe(tx4939_rtc_driver, tx4939_rtc_probe); 295 296MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); 297MODULE_DESCRIPTION("TX4939 internal RTC driver"); 298MODULE_LICENSE("GPL"); 299MODULE_ALIAS("platform:tx4939rtc"); 300