Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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