aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAkinobu Mita <akinobu.mita@gmail.com>2016-03-14 10:44:59 -0400
committerAlexandre Belloni <alexandre.belloni@free-electrons.com>2016-03-14 12:08:40 -0400
commit907b3262583c700ef48f6a45b2b48878b524b2ef (patch)
tree5b77236ecb9b77ca66ba167a5979f91b4beb06d3
parenta696b31e2feeaa0ef99242adb9e771b0d3369a81 (diff)
rtc: pcf2127: convert to use regmap
pcf2127 has selectable I2C-bus and SPI-bus interface support. Currently rtc-pcf2127 driver only supports I2C. This is preparation for support for SPI interface. Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Alexandre Belloni <alexandre.belloni@free-electrons.com> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
-rw-r--r--drivers/rtc/rtc-pcf2127.c214
1 files changed, 144 insertions, 70 deletions
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index 629bfdf8c745..fa492cd84e2a 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -19,6 +19,7 @@
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/of.h> 21#include <linux/of.h>
22#include <linux/regmap.h>
22 23
23#define PCF2127_REG_CTRL1 (0x00) /* Control Register 1 */ 24#define PCF2127_REG_CTRL1 (0x00) /* Control Register 1 */
24#define PCF2127_REG_CTRL2 (0x01) /* Control Register 2 */ 25#define PCF2127_REG_CTRL2 (0x01) /* Control Register 2 */
@@ -36,29 +37,30 @@
36 37
37#define PCF2127_OSF BIT(7) /* Oscillator Fail flag */ 38#define PCF2127_OSF BIT(7) /* Oscillator Fail flag */
38 39
39static struct i2c_driver pcf2127_driver;
40
41struct pcf2127 { 40struct pcf2127 {
42 struct rtc_device *rtc; 41 struct rtc_device *rtc;
42 struct regmap *regmap;
43}; 43};
44 44
45/* 45/*
46 * In the routines that deal directly with the pcf2127 hardware, we use 46 * In the routines that deal directly with the pcf2127 hardware, we use
47 * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. 47 * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
48 */ 48 */
49static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm) 49static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm)
50{ 50{
51 unsigned char buf[10] = { PCF2127_REG_CTRL1 }; 51 struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
52 unsigned char buf[10];
53 int ret;
52 54
53 /* read registers */ 55 ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_CTRL1, buf,
54 if (i2c_master_send(client, buf, 1) != 1 || 56 sizeof(buf));
55 i2c_master_recv(client, buf, sizeof(buf)) != sizeof(buf)) { 57 if (ret) {
56 dev_err(&client->dev, "%s: read error\n", __func__); 58 dev_err(dev, "%s: read error\n", __func__);
57 return -EIO; 59 return ret;
58 } 60 }
59 61
60 if (buf[PCF2127_REG_CTRL3] & PCF2127_REG_CTRL3_BLF) 62 if (buf[PCF2127_REG_CTRL3] & PCF2127_REG_CTRL3_BLF)
61 dev_info(&client->dev, 63 dev_info(dev,
62 "low voltage detected, check/replace RTC battery.\n"); 64 "low voltage detected, check/replace RTC battery.\n");
63 65
64 if (buf[PCF2127_REG_SC] & PCF2127_OSF) { 66 if (buf[PCF2127_REG_SC] & PCF2127_OSF) {
@@ -66,12 +68,12 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
66 * no need clear the flag here, 68 * no need clear the flag here,
67 * it will be cleared once the new date is saved 69 * it will be cleared once the new date is saved
68 */ 70 */
69 dev_warn(&client->dev, 71 dev_warn(dev,
70 "oscillator stop detected, date/time is not reliable\n"); 72 "oscillator stop detected, date/time is not reliable\n");
71 return -EINVAL; 73 return -EINVAL;
72 } 74 }
73 75
74 dev_dbg(&client->dev, 76 dev_dbg(dev,
75 "%s: raw data is cr1=%02x, cr2=%02x, cr3=%02x, " 77 "%s: raw data is cr1=%02x, cr2=%02x, cr3=%02x, "
76 "sec=%02x, min=%02x, hr=%02x, " 78 "sec=%02x, min=%02x, hr=%02x, "
77 "mday=%02x, wday=%02x, mon=%02x, year=%02x\n", 79 "mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
@@ -91,7 +93,7 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
91 if (tm->tm_year < 70) 93 if (tm->tm_year < 70)
92 tm->tm_year += 100; /* assume we are in 1970...2069 */ 94 tm->tm_year += 100; /* assume we are in 1970...2069 */
93 95
94 dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " 96 dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
95 "mday=%d, mon=%d, year=%d, wday=%d\n", 97 "mday=%d, mon=%d, year=%d, wday=%d\n",
96 __func__, 98 __func__,
97 tm->tm_sec, tm->tm_min, tm->tm_hour, 99 tm->tm_sec, tm->tm_min, tm->tm_hour,
@@ -100,20 +102,18 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
100 return rtc_valid_tm(tm); 102 return rtc_valid_tm(tm);
101} 103}
102 104
103static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm) 105static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm)
104{ 106{
105 unsigned char buf[8]; 107 struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
108 unsigned char buf[7];
106 int i = 0, err; 109 int i = 0, err;
107 110
108 dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " 111 dev_dbg(dev, "%s: secs=%d, mins=%d, hours=%d, "
109 "mday=%d, mon=%d, year=%d, wday=%d\n", 112 "mday=%d, mon=%d, year=%d, wday=%d\n",
110 __func__, 113 __func__,
111 tm->tm_sec, tm->tm_min, tm->tm_hour, 114 tm->tm_sec, tm->tm_min, tm->tm_hour,
112 tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); 115 tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
113 116
114 /* start register address */
115 buf[i++] = PCF2127_REG_SC;
116
117 /* hours, minutes and seconds */ 117 /* hours, minutes and seconds */
118 buf[i++] = bin2bcd(tm->tm_sec); /* this will also clear OSF flag */ 118 buf[i++] = bin2bcd(tm->tm_sec); /* this will also clear OSF flag */
119 buf[i++] = bin2bcd(tm->tm_min); 119 buf[i++] = bin2bcd(tm->tm_min);
@@ -128,11 +128,11 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
128 buf[i++] = bin2bcd(tm->tm_year % 100); 128 buf[i++] = bin2bcd(tm->tm_year % 100);
129 129
130 /* write register's data */ 130 /* write register's data */
131 err = i2c_master_send(client, buf, i); 131 err = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_SC, buf, i);
132 if (err != i) { 132 if (err) {
133 dev_err(&client->dev, 133 dev_err(dev,
134 "%s: err=%d", __func__, err); 134 "%s: err=%d", __func__, err);
135 return -EIO; 135 return err;
136 } 136 }
137 137
138 return 0; 138 return 0;
@@ -142,26 +142,17 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
142static int pcf2127_rtc_ioctl(struct device *dev, 142static int pcf2127_rtc_ioctl(struct device *dev,
143 unsigned int cmd, unsigned long arg) 143 unsigned int cmd, unsigned long arg)
144{ 144{
145 struct i2c_client *client = to_i2c_client(dev); 145 struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
146 unsigned char buf = PCF2127_REG_CTRL3;
147 int touser; 146 int touser;
148 int ret; 147 int ret;
149 148
150 switch (cmd) { 149 switch (cmd) {
151 case RTC_VL_READ: 150 case RTC_VL_READ:
152 ret = i2c_master_send(client, &buf, 1); 151 ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &touser);
153 if (!ret) 152 if (ret)
154 ret = -EIO;
155 if (ret < 0)
156 return ret;
157
158 ret = i2c_master_recv(client, &buf, 1);
159 if (!ret)
160 ret = -EIO;
161 if (ret < 0)
162 return ret; 153 return ret;
163 154
164 touser = buf & PCF2127_REG_CTRL3_BLF ? 1 : 0; 155 touser = touser & PCF2127_REG_CTRL3_BLF ? 1 : 0;
165 156
166 if (copy_to_user((void __user *)arg, &touser, sizeof(int))) 157 if (copy_to_user((void __user *)arg, &touser, sizeof(int)))
167 return -EFAULT; 158 return -EFAULT;
@@ -174,52 +165,33 @@ static int pcf2127_rtc_ioctl(struct device *dev,
174#define pcf2127_rtc_ioctl NULL 165#define pcf2127_rtc_ioctl NULL
175#endif 166#endif
176 167
177static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm)
178{
179 return pcf2127_get_datetime(to_i2c_client(dev), tm);
180}
181
182static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm)
183{
184 return pcf2127_set_datetime(to_i2c_client(dev), tm);
185}
186
187static const struct rtc_class_ops pcf2127_rtc_ops = { 168static const struct rtc_class_ops pcf2127_rtc_ops = {
188 .ioctl = pcf2127_rtc_ioctl, 169 .ioctl = pcf2127_rtc_ioctl,
189 .read_time = pcf2127_rtc_read_time, 170 .read_time = pcf2127_rtc_read_time,
190 .set_time = pcf2127_rtc_set_time, 171 .set_time = pcf2127_rtc_set_time,
191}; 172};
192 173
193static int pcf2127_probe(struct i2c_client *client, 174static int pcf2127_probe(struct device *dev, struct regmap *regmap,
194 const struct i2c_device_id *id) 175 const char *name)
195{ 176{
196 struct pcf2127 *pcf2127; 177 struct pcf2127 *pcf2127;
197 178
198 dev_dbg(&client->dev, "%s\n", __func__); 179 dev_dbg(dev, "%s\n", __func__);
199
200 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
201 return -ENODEV;
202 180
203 pcf2127 = devm_kzalloc(&client->dev, sizeof(struct pcf2127), 181 pcf2127 = devm_kzalloc(dev, sizeof(*pcf2127), GFP_KERNEL);
204 GFP_KERNEL);
205 if (!pcf2127) 182 if (!pcf2127)
206 return -ENOMEM; 183 return -ENOMEM;
207 184
208 i2c_set_clientdata(client, pcf2127); 185 pcf2127->regmap = regmap;
209 186
210 pcf2127->rtc = devm_rtc_device_register(&client->dev, 187 dev_set_drvdata(dev, pcf2127);
211 pcf2127_driver.driver.name, 188
212 &pcf2127_rtc_ops, THIS_MODULE); 189 pcf2127->rtc = devm_rtc_device_register(dev, name, &pcf2127_rtc_ops,
190 THIS_MODULE);
213 191
214 return PTR_ERR_OR_ZERO(pcf2127->rtc); 192 return PTR_ERR_OR_ZERO(pcf2127->rtc);
215} 193}
216 194
217static const struct i2c_device_id pcf2127_id[] = {
218 { "pcf2127", 0 },
219 { }
220};
221MODULE_DEVICE_TABLE(i2c, pcf2127_id);
222
223#ifdef CONFIG_OF 195#ifdef CONFIG_OF
224static const struct of_device_id pcf2127_of_match[] = { 196static const struct of_device_id pcf2127_of_match[] = {
225 { .compatible = "nxp,pcf2127" }, 197 { .compatible = "nxp,pcf2127" },
@@ -228,16 +200,118 @@ static const struct of_device_id pcf2127_of_match[] = {
228MODULE_DEVICE_TABLE(of, pcf2127_of_match); 200MODULE_DEVICE_TABLE(of, pcf2127_of_match);
229#endif 201#endif
230 202
231static struct i2c_driver pcf2127_driver = { 203static int pcf2127_i2c_write(void *context, const void *data, size_t count)
204{
205 struct device *dev = context;
206 struct i2c_client *client = to_i2c_client(dev);
207 int ret;
208
209 ret = i2c_master_send(client, data, count);
210 if (ret != count)
211 return ret < 0 ? ret : -EIO;
212
213 return 0;
214}
215
216static int pcf2127_i2c_gather_write(void *context,
217 const void *reg, size_t reg_size,
218 const void *val, size_t val_size)
219{
220 struct device *dev = context;
221 struct i2c_client *client = to_i2c_client(dev);
222 int ret;
223 void *buf;
224
225 if (WARN_ON(reg_size != 1))
226 return -EINVAL;
227
228 buf = kmalloc(val_size + 1, GFP_KERNEL);
229 if (!buf)
230 return -ENOMEM;
231
232 memcpy(buf, reg, 1);
233 memcpy(buf + 1, val, val_size);
234
235 ret = i2c_master_send(client, buf, val_size + 1);
236 if (ret != val_size + 1)
237 return ret < 0 ? ret : -EIO;
238
239 return 0;
240}
241
242static int pcf2127_i2c_read(void *context, const void *reg, size_t reg_size,
243 void *val, size_t val_size)
244{
245 struct device *dev = context;
246 struct i2c_client *client = to_i2c_client(dev);
247 int ret;
248
249 if (WARN_ON(reg_size != 1))
250 return -EINVAL;
251
252 ret = i2c_master_send(client, reg, 1);
253 if (ret != 1)
254 return ret < 0 ? ret : -EIO;
255
256 ret = i2c_master_recv(client, val, val_size);
257 if (ret != val_size)
258 return ret < 0 ? ret : -EIO;
259
260 return 0;
261}
262
263/*
264 * The reason we need this custom regmap_bus instead of using regmap_init_i2c()
265 * is that the STOP condition is required between set register address and
266 * read register data when reading from registers.
267 */
268static const struct regmap_bus pcf2127_i2c_regmap = {
269 .write = pcf2127_i2c_write,
270 .gather_write = pcf2127_i2c_gather_write,
271 .read = pcf2127_i2c_read,
272};
273
274static struct i2c_driver pcf2127_i2c_driver;
275
276static int pcf2127_i2c_probe(struct i2c_client *client,
277 const struct i2c_device_id *id)
278{
279 struct regmap *regmap;
280 static const struct regmap_config config = {
281 .reg_bits = 8,
282 .val_bits = 8,
283 };
284
285 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
286 return -ENODEV;
287
288 regmap = devm_regmap_init(&client->dev, &pcf2127_i2c_regmap,
289 &client->dev, &config);
290 if (IS_ERR(regmap)) {
291 dev_err(&client->dev, "%s: regmap allocation failed: %ld\n",
292 __func__, PTR_ERR(regmap));
293 return PTR_ERR(regmap);
294 }
295
296 return pcf2127_probe(&client->dev, regmap,
297 pcf2127_i2c_driver.driver.name);
298}
299
300static const struct i2c_device_id pcf2127_i2c_id[] = {
301 { "pcf2127", 0 },
302 { }
303};
304MODULE_DEVICE_TABLE(i2c, pcf2127_i2c_id);
305
306static struct i2c_driver pcf2127_i2c_driver = {
232 .driver = { 307 .driver = {
233 .name = "rtc-pcf2127", 308 .name = "rtc-pcf2127-i2c",
234 .of_match_table = of_match_ptr(pcf2127_of_match), 309 .of_match_table = of_match_ptr(pcf2127_of_match),
235 }, 310 },
236 .probe = pcf2127_probe, 311 .probe = pcf2127_i2c_probe,
237 .id_table = pcf2127_id, 312 .id_table = pcf2127_i2c_id,
238}; 313};
239 314module_i2c_driver(pcf2127_i2c_driver);
240module_i2c_driver(pcf2127_driver);
241 315
242MODULE_AUTHOR("Renaud Cerrato <r.cerrato@til-technologies.fr>"); 316MODULE_AUTHOR("Renaud Cerrato <r.cerrato@til-technologies.fr>");
243MODULE_DESCRIPTION("NXP PCF2127 RTC driver"); 317MODULE_DESCRIPTION("NXP PCF2127 RTC driver");