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