diff options
author | Chris Verges <chrisv@cyberswitching.com> | 2009-09-22 19:46:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-23 10:39:45 -0400 |
commit | f3d2570a1482a6d897ba29276964965f6fe970d8 (patch) | |
tree | 33d2652cd0ebd753b997addff0ed1c4a9460c971 /drivers/rtc/rtc-pcf2123.c | |
parent | 7f3923a184bb8e7ede5e5f58f1114bf7b8c611ea (diff) |
rtc-philips-pcf2123-rtc-spi-driver-updates
Signed-off: Chris Verges <chrisv@cyberswitching.com>
Cc: Christian Pellegrin <chripell@fsfe.org>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rtc/rtc-pcf2123.c')
-rw-r--r-- | drivers/rtc/rtc-pcf2123.c | 44 |
1 files changed, 32 insertions, 12 deletions
diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index d07b199a0c94..e75df9d50e27 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c | |||
@@ -42,7 +42,7 @@ | |||
42 | #include <linux/rtc.h> | 42 | #include <linux/rtc.h> |
43 | #include <linux/spi/spi.h> | 43 | #include <linux/spi/spi.h> |
44 | 44 | ||
45 | #define DRV_VERSION "0.5" | 45 | #define DRV_VERSION "0.6" |
46 | 46 | ||
47 | #define PCF2123_REG_CTRL1 (0x00) /* Control Register 1 */ | 47 | #define PCF2123_REG_CTRL1 (0x00) /* Control Register 1 */ |
48 | #define PCF2123_REG_CTRL2 (0x01) /* Control Register 2 */ | 48 | #define PCF2123_REG_CTRL2 (0x01) /* Control Register 2 */ |
@@ -61,7 +61,7 @@ | |||
61 | static struct spi_driver pcf2123_driver; | 61 | static struct spi_driver pcf2123_driver; |
62 | 62 | ||
63 | struct pcf2123_sysfs_reg { | 63 | struct pcf2123_sysfs_reg { |
64 | struct device_attribute attr; /* must be first */ | 64 | struct device_attribute attr; |
65 | char name[2]; | 65 | char name[2]; |
66 | }; | 66 | }; |
67 | 67 | ||
@@ -84,27 +84,42 @@ static ssize_t pcf2123_show(struct device *dev, struct device_attribute *attr, | |||
84 | char *buffer) | 84 | char *buffer) |
85 | { | 85 | { |
86 | struct spi_device *spi = to_spi_device(dev); | 86 | struct spi_device *spi = to_spi_device(dev); |
87 | struct pcf2123_sysfs_reg *r = (struct pcf2123_sysfs_reg *) attr; | 87 | struct pcf2123_sysfs_reg *r; |
88 | u8 txbuf[1], rxbuf[1]; | 88 | u8 txbuf[1], rxbuf[1]; |
89 | unsigned long reg; | ||
89 | int ret; | 90 | int ret; |
90 | 91 | ||
91 | txbuf[0] = PCF2123_READ | simple_strtoul(r->name, NULL, 16); | 92 | r = container_of(attr, struct pcf2123_sysfs_reg, attr); |
93 | |||
94 | if (strict_strtoul(r->name, 16, ®)) | ||
95 | return -EINVAL; | ||
96 | |||
97 | txbuf[0] = PCF2123_READ | reg; | ||
92 | ret = spi_write_then_read(spi, txbuf, 1, rxbuf, 1); | 98 | ret = spi_write_then_read(spi, txbuf, 1, rxbuf, 1); |
93 | if (ret < 0) | 99 | if (ret < 0) |
94 | return sprintf(buffer, "error: %d", ret); | 100 | return -EIO; |
95 | pcf2123_delay_trec(); | 101 | pcf2123_delay_trec(); |
96 | return sprintf(buffer, "0x%x", rxbuf[0]); | 102 | return sprintf(buffer, "0x%x\n", rxbuf[0]); |
97 | } | 103 | } |
98 | 104 | ||
99 | static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr, | 105 | static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr, |
100 | const char *buffer, size_t count) { | 106 | const char *buffer, size_t count) { |
101 | struct spi_device *spi = to_spi_device(dev); | 107 | struct spi_device *spi = to_spi_device(dev); |
102 | struct pcf2123_sysfs_reg *r = (struct pcf2123_sysfs_reg *) attr; | 108 | struct pcf2123_sysfs_reg *r; |
103 | u8 txbuf[2]; | 109 | u8 txbuf[2]; |
110 | unsigned long reg; | ||
111 | unsigned long val; | ||
112 | |||
104 | int ret; | 113 | int ret; |
105 | 114 | ||
106 | txbuf[0] = PCF2123_WRITE | simple_strtoul(r->name, NULL, 16); | 115 | r = container_of(attr, struct pcf2123_sysfs_reg, attr); |
107 | txbuf[1] = simple_strtoul(buffer, NULL, 0); | 116 | |
117 | if (strict_strtoul(r->name, 16, ®) | ||
118 | || strict_strtoul(buffer, 10, &val)) | ||
119 | return -EINVAL; | ||
120 | |||
121 | txbuf[0] = PCF2123_WRITE | reg; | ||
122 | txbuf[1] = val; | ||
108 | ret = spi_write(spi, txbuf, sizeof(txbuf)); | 123 | ret = spi_write(spi, txbuf, sizeof(txbuf)); |
109 | if (ret < 0) | 124 | if (ret < 0) |
110 | return -EIO; | 125 | return -EIO; |
@@ -220,7 +235,7 @@ static int __devinit pcf2123_probe(struct spi_device *spi) | |||
220 | txbuf[0], txbuf[1]); | 235 | txbuf[0], txbuf[1]); |
221 | ret = spi_write(spi, txbuf, 2 * sizeof(u8)); | 236 | ret = spi_write(spi, txbuf, 2 * sizeof(u8)); |
222 | if (ret < 0) | 237 | if (ret < 0) |
223 | return ret; | 238 | goto kfree_exit; |
224 | pcf2123_delay_trec(); | 239 | pcf2123_delay_trec(); |
225 | 240 | ||
226 | /* Stop the counter */ | 241 | /* Stop the counter */ |
@@ -230,7 +245,7 @@ static int __devinit pcf2123_probe(struct spi_device *spi) | |||
230 | txbuf[0], txbuf[1]); | 245 | txbuf[0], txbuf[1]); |
231 | ret = spi_write(spi, txbuf, 2 * sizeof(u8)); | 246 | ret = spi_write(spi, txbuf, 2 * sizeof(u8)); |
232 | if (ret < 0) | 247 | if (ret < 0) |
233 | return ret; | 248 | goto kfree_exit; |
234 | pcf2123_delay_trec(); | 249 | pcf2123_delay_trec(); |
235 | 250 | ||
236 | /* See if the counter was actually stopped */ | 251 | /* See if the counter was actually stopped */ |
@@ -284,11 +299,16 @@ static int __devinit pcf2123_probe(struct spi_device *spi) | |||
284 | if (ret) { | 299 | if (ret) { |
285 | dev_err(&spi->dev, "Unable to create sysfs %s\n", | 300 | dev_err(&spi->dev, "Unable to create sysfs %s\n", |
286 | pdata->regs[i].name); | 301 | pdata->regs[i].name); |
287 | pdata->regs[i].name[0] = '\0'; | 302 | goto sysfs_exit; |
288 | } | 303 | } |
289 | } | 304 | } |
290 | 305 | ||
291 | return 0; | 306 | return 0; |
307 | |||
308 | sysfs_exit: | ||
309 | for (i--; i >= 0; i--) | ||
310 | device_remove_file(&spi->dev, &pdata->regs[i].attr); | ||
311 | |||
292 | kfree_exit: | 312 | kfree_exit: |
293 | kfree(pdata); | 313 | kfree(pdata); |
294 | spi->dev.platform_data = NULL; | 314 | spi->dev.platform_data = NULL; |