aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-pcf2123.c
diff options
context:
space:
mode:
authorChris Verges <chrisv@cyberswitching.com>2009-09-22 19:46:22 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-23 10:39:45 -0400
commitf3d2570a1482a6d897ba29276964965f6fe970d8 (patch)
tree33d2652cd0ebd753b997addff0ed1c4a9460c971 /drivers/rtc/rtc-pcf2123.c
parent7f3923a184bb8e7ede5e5f58f1114bf7b8c611ea (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.c44
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 @@
61static struct spi_driver pcf2123_driver; 61static struct spi_driver pcf2123_driver;
62 62
63struct pcf2123_sysfs_reg { 63struct 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, &reg))
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
99static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr, 105static 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, &reg)
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
308sysfs_exit:
309 for (i--; i >= 0; i--)
310 device_remove_file(&spi->dev, &pdata->regs[i].attr);
311
292kfree_exit: 312kfree_exit:
293 kfree(pdata); 313 kfree(pdata);
294 spi->dev.platform_data = NULL; 314 spi->dev.platform_data = NULL;