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.31-rc5 413 lines 9.6 kB view raw
1/* drivers/rtc/rtc-v3020.c 2 * 3 * Copyright (C) 2006 8D Technologies inc. 4 * Copyright (C) 2004 Compulab Ltd. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * Driver for the V3020 RTC 11 * 12 * Changelog: 13 * 14 * 10-May-2006: Raphael Assenat <raph@8d.com> 15 * - Converted to platform driver 16 * - Use the generic rtc class 17 * 18 * ??-???-2004: Someone at Compulab 19 * - Initial driver creation. 20 * 21 */ 22#include <linux/platform_device.h> 23#include <linux/module.h> 24#include <linux/init.h> 25#include <linux/rtc.h> 26#include <linux/types.h> 27#include <linux/bcd.h> 28#include <linux/rtc-v3020.h> 29#include <linux/delay.h> 30#include <linux/gpio.h> 31 32#include <linux/io.h> 33 34#undef DEBUG 35 36struct v3020; 37 38struct v3020_chip_ops { 39 int (*map_io)(struct v3020 *chip, struct platform_device *pdev, 40 struct v3020_platform_data *pdata); 41 void (*unmap_io)(struct v3020 *chip); 42 unsigned char (*read_bit)(struct v3020 *chip); 43 void (*write_bit)(struct v3020 *chip, unsigned char bit); 44}; 45 46#define V3020_CS 0 47#define V3020_WR 1 48#define V3020_RD 2 49#define V3020_IO 3 50 51struct v3020_gpio { 52 const char *name; 53 unsigned int gpio; 54}; 55 56struct v3020 { 57 /* MMIO access */ 58 void __iomem *ioaddress; 59 int leftshift; 60 61 /* GPIO access */ 62 struct v3020_gpio *gpio; 63 64 struct v3020_chip_ops *ops; 65 66 struct rtc_device *rtc; 67}; 68 69 70static int v3020_mmio_map(struct v3020 *chip, struct platform_device *pdev, 71 struct v3020_platform_data *pdata) 72{ 73 if (pdev->num_resources != 1) 74 return -EBUSY; 75 76 if (pdev->resource[0].flags != IORESOURCE_MEM) 77 return -EBUSY; 78 79 chip->leftshift = pdata->leftshift; 80 chip->ioaddress = ioremap(pdev->resource[0].start, 1); 81 if (chip->ioaddress == NULL) 82 return -EBUSY; 83 84 return 0; 85} 86 87static void v3020_mmio_unmap(struct v3020 *chip) 88{ 89 iounmap(chip->ioaddress); 90} 91 92static void v3020_mmio_write_bit(struct v3020 *chip, unsigned char bit) 93{ 94 writel(bit << chip->leftshift, chip->ioaddress); 95} 96 97static unsigned char v3020_mmio_read_bit(struct v3020 *chip) 98{ 99 return readl(chip->ioaddress) & (1 << chip->leftshift); 100} 101 102static struct v3020_chip_ops v3020_mmio_ops = { 103 .map_io = v3020_mmio_map, 104 .unmap_io = v3020_mmio_unmap, 105 .read_bit = v3020_mmio_read_bit, 106 .write_bit = v3020_mmio_write_bit, 107}; 108 109static struct v3020_gpio v3020_gpio[] = { 110 { "RTC CS", 0 }, 111 { "RTC WR", 0 }, 112 { "RTC RD", 0 }, 113 { "RTC IO", 0 }, 114}; 115 116static int v3020_gpio_map(struct v3020 *chip, struct platform_device *pdev, 117 struct v3020_platform_data *pdata) 118{ 119 int i, err; 120 121 v3020_gpio[V3020_CS].gpio = pdata->gpio_cs; 122 v3020_gpio[V3020_WR].gpio = pdata->gpio_wr; 123 v3020_gpio[V3020_RD].gpio = pdata->gpio_rd; 124 v3020_gpio[V3020_IO].gpio = pdata->gpio_io; 125 126 for (i = 0; i < ARRAY_SIZE(v3020_gpio); i++) { 127 err = gpio_request(v3020_gpio[i].gpio, v3020_gpio[i].name); 128 if (err) 129 goto err_request; 130 131 gpio_direction_output(v3020_gpio[i].gpio, 1); 132 } 133 134 chip->gpio = v3020_gpio; 135 136 return 0; 137 138err_request: 139 while (--i >= 0) 140 gpio_free(v3020_gpio[i].gpio); 141 142 return err; 143} 144 145static void v3020_gpio_unmap(struct v3020 *chip) 146{ 147 int i; 148 149 for (i = 0; i < ARRAY_SIZE(v3020_gpio); i++) 150 gpio_free(v3020_gpio[i].gpio); 151} 152 153static void v3020_gpio_write_bit(struct v3020 *chip, unsigned char bit) 154{ 155 gpio_direction_output(chip->gpio[V3020_IO].gpio, bit); 156 gpio_set_value(chip->gpio[V3020_CS].gpio, 0); 157 gpio_set_value(chip->gpio[V3020_WR].gpio, 0); 158 udelay(1); 159 gpio_set_value(chip->gpio[V3020_WR].gpio, 1); 160 gpio_set_value(chip->gpio[V3020_CS].gpio, 1); 161} 162 163static unsigned char v3020_gpio_read_bit(struct v3020 *chip) 164{ 165 int bit; 166 167 gpio_direction_input(chip->gpio[V3020_IO].gpio); 168 gpio_set_value(chip->gpio[V3020_CS].gpio, 0); 169 gpio_set_value(chip->gpio[V3020_RD].gpio, 0); 170 udelay(1); 171 bit = !!gpio_get_value(chip->gpio[V3020_IO].gpio); 172 udelay(1); 173 gpio_set_value(chip->gpio[V3020_RD].gpio, 1); 174 gpio_set_value(chip->gpio[V3020_CS].gpio, 1); 175 176 return bit; 177} 178 179static struct v3020_chip_ops v3020_gpio_ops = { 180 .map_io = v3020_gpio_map, 181 .unmap_io = v3020_gpio_unmap, 182 .read_bit = v3020_gpio_read_bit, 183 .write_bit = v3020_gpio_write_bit, 184}; 185 186static void v3020_set_reg(struct v3020 *chip, unsigned char address, 187 unsigned char data) 188{ 189 int i; 190 unsigned char tmp; 191 192 tmp = address; 193 for (i = 0; i < 4; i++) { 194 chip->ops->write_bit(chip, (tmp & 1)); 195 tmp >>= 1; 196 udelay(1); 197 } 198 199 /* Commands dont have data */ 200 if (!V3020_IS_COMMAND(address)) { 201 for (i = 0; i < 8; i++) { 202 chip->ops->write_bit(chip, (data & 1)); 203 data >>= 1; 204 udelay(1); 205 } 206 } 207} 208 209static unsigned char v3020_get_reg(struct v3020 *chip, unsigned char address) 210{ 211 unsigned int data = 0; 212 int i; 213 214 for (i = 0; i < 4; i++) { 215 chip->ops->write_bit(chip, (address & 1)); 216 address >>= 1; 217 udelay(1); 218 } 219 220 for (i = 0; i < 8; i++) { 221 data >>= 1; 222 if (chip->ops->read_bit(chip)) 223 data |= 0x80; 224 udelay(1); 225 } 226 227 return data; 228} 229 230static int v3020_read_time(struct device *dev, struct rtc_time *dt) 231{ 232 struct v3020 *chip = dev_get_drvdata(dev); 233 int tmp; 234 235 /* Copy the current time to ram... */ 236 v3020_set_reg(chip, V3020_CMD_CLOCK2RAM, 0); 237 238 /* ...and then read constant values. */ 239 tmp = v3020_get_reg(chip, V3020_SECONDS); 240 dt->tm_sec = bcd2bin(tmp); 241 tmp = v3020_get_reg(chip, V3020_MINUTES); 242 dt->tm_min = bcd2bin(tmp); 243 tmp = v3020_get_reg(chip, V3020_HOURS); 244 dt->tm_hour = bcd2bin(tmp); 245 tmp = v3020_get_reg(chip, V3020_MONTH_DAY); 246 dt->tm_mday = bcd2bin(tmp); 247 tmp = v3020_get_reg(chip, V3020_MONTH); 248 dt->tm_mon = bcd2bin(tmp) - 1; 249 tmp = v3020_get_reg(chip, V3020_WEEK_DAY); 250 dt->tm_wday = bcd2bin(tmp); 251 tmp = v3020_get_reg(chip, V3020_YEAR); 252 dt->tm_year = bcd2bin(tmp)+100; 253 254 dev_dbg(dev, "\n%s : Read RTC values\n", __func__); 255 dev_dbg(dev, "tm_hour: %i\n", dt->tm_hour); 256 dev_dbg(dev, "tm_min : %i\n", dt->tm_min); 257 dev_dbg(dev, "tm_sec : %i\n", dt->tm_sec); 258 dev_dbg(dev, "tm_year: %i\n", dt->tm_year); 259 dev_dbg(dev, "tm_mon : %i\n", dt->tm_mon); 260 dev_dbg(dev, "tm_mday: %i\n", dt->tm_mday); 261 dev_dbg(dev, "tm_wday: %i\n", dt->tm_wday); 262 263 return 0; 264} 265 266 267static int v3020_set_time(struct device *dev, struct rtc_time *dt) 268{ 269 struct v3020 *chip = dev_get_drvdata(dev); 270 271 dev_dbg(dev, "\n%s : Setting RTC values\n", __func__); 272 dev_dbg(dev, "tm_sec : %i\n", dt->tm_sec); 273 dev_dbg(dev, "tm_min : %i\n", dt->tm_min); 274 dev_dbg(dev, "tm_hour: %i\n", dt->tm_hour); 275 dev_dbg(dev, "tm_mday: %i\n", dt->tm_mday); 276 dev_dbg(dev, "tm_wday: %i\n", dt->tm_wday); 277 dev_dbg(dev, "tm_year: %i\n", dt->tm_year); 278 279 /* Write all the values to ram... */ 280 v3020_set_reg(chip, V3020_SECONDS, bin2bcd(dt->tm_sec)); 281 v3020_set_reg(chip, V3020_MINUTES, bin2bcd(dt->tm_min)); 282 v3020_set_reg(chip, V3020_HOURS, bin2bcd(dt->tm_hour)); 283 v3020_set_reg(chip, V3020_MONTH_DAY, bin2bcd(dt->tm_mday)); 284 v3020_set_reg(chip, V3020_MONTH, bin2bcd(dt->tm_mon + 1)); 285 v3020_set_reg(chip, V3020_WEEK_DAY, bin2bcd(dt->tm_wday)); 286 v3020_set_reg(chip, V3020_YEAR, bin2bcd(dt->tm_year % 100)); 287 288 /* ...and set the clock. */ 289 v3020_set_reg(chip, V3020_CMD_RAM2CLOCK, 0); 290 291 /* Compulab used this delay here. I dont know why, 292 * the datasheet does not specify a delay. */ 293 /*mdelay(5);*/ 294 295 return 0; 296} 297 298static const struct rtc_class_ops v3020_rtc_ops = { 299 .read_time = v3020_read_time, 300 .set_time = v3020_set_time, 301}; 302 303static int rtc_probe(struct platform_device *pdev) 304{ 305 struct v3020_platform_data *pdata = pdev->dev.platform_data; 306 struct v3020 *chip; 307 struct rtc_device *rtc; 308 int retval = -EBUSY; 309 int i; 310 int temp; 311 312 chip = kzalloc(sizeof *chip, GFP_KERNEL); 313 if (!chip) 314 return -ENOMEM; 315 316 if (pdata->use_gpio) 317 chip->ops = &v3020_gpio_ops; 318 else 319 chip->ops = &v3020_mmio_ops; 320 321 retval = chip->ops->map_io(chip, pdev, pdata); 322 if (retval) 323 goto err_chip; 324 325 /* Make sure the v3020 expects a communication cycle 326 * by reading 8 times */ 327 for (i = 0; i < 8; i++) 328 temp = chip->ops->read_bit(chip); 329 330 /* Test chip by doing a write/read sequence 331 * to the chip ram */ 332 v3020_set_reg(chip, V3020_SECONDS, 0x33); 333 if (v3020_get_reg(chip, V3020_SECONDS) != 0x33) { 334 retval = -ENODEV; 335 goto err_io; 336 } 337 338 /* Make sure frequency measurment mode, test modes, and lock 339 * are all disabled */ 340 v3020_set_reg(chip, V3020_STATUS_0, 0x0); 341 342 if (pdata->use_gpio) 343 dev_info(&pdev->dev, "Chip available at GPIOs " 344 "%d, %d, %d, %d\n", 345 chip->gpio[V3020_CS].gpio, chip->gpio[V3020_WR].gpio, 346 chip->gpio[V3020_RD].gpio, chip->gpio[V3020_IO].gpio); 347 else 348 dev_info(&pdev->dev, "Chip available at " 349 "physical address 0x%llx," 350 "data connected to D%d\n", 351 (unsigned long long)pdev->resource[0].start, 352 chip->leftshift); 353 354 platform_set_drvdata(pdev, chip); 355 356 rtc = rtc_device_register("v3020", 357 &pdev->dev, &v3020_rtc_ops, THIS_MODULE); 358 if (IS_ERR(rtc)) { 359 retval = PTR_ERR(rtc); 360 goto err_io; 361 } 362 chip->rtc = rtc; 363 364 return 0; 365 366err_io: 367 chip->ops->unmap_io(chip); 368err_chip: 369 kfree(chip); 370 371 return retval; 372} 373 374static int rtc_remove(struct platform_device *dev) 375{ 376 struct v3020 *chip = platform_get_drvdata(dev); 377 struct rtc_device *rtc = chip->rtc; 378 379 if (rtc) 380 rtc_device_unregister(rtc); 381 382 chip->ops->unmap_io(chip); 383 kfree(chip); 384 385 return 0; 386} 387 388static struct platform_driver rtc_device_driver = { 389 .probe = rtc_probe, 390 .remove = rtc_remove, 391 .driver = { 392 .name = "v3020", 393 .owner = THIS_MODULE, 394 }, 395}; 396 397static __init int v3020_init(void) 398{ 399 return platform_driver_register(&rtc_device_driver); 400} 401 402static __exit void v3020_exit(void) 403{ 404 platform_driver_unregister(&rtc_device_driver); 405} 406 407module_init(v3020_init); 408module_exit(v3020_exit); 409 410MODULE_DESCRIPTION("V3020 RTC"); 411MODULE_AUTHOR("Raphael Assenat"); 412MODULE_LICENSE("GPL"); 413MODULE_ALIAS("platform:v3020");