Blame view
drivers/rtc/rtc-pcf2123.c
12.3 KB
d2912cb15 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
7f3923a18 rtc: Philips PCF2... |
2 3 4 5 6 7 8 9 10 11 12 13 |
/* * An SPI driver for the Philips PCF2123 RTC * Copyright 2009 Cyber Switching, Inc. * * Author: Chris Verges <chrisv@cyberswitching.com> * Maintainers: http://www.cyberswitching.com * * based on the RS5C348 driver in this same directory. * * Thanks to Christian Pellegrin <chripell@fsfe.org> for * the sysfs contributions to this driver. * |
7f3923a18 rtc: Philips PCF2... |
14 15 16 17 |
* Please note that the CS is active high, so platform data * should look something like: * * static struct spi_board_info ek_spi_devices[] = { |
369015fbd drivers/rtc/rtc-p... |
18 19 20 21 22 |
* ... * { * .modalias = "rtc-pcf2123", * .chip_select = 1, * .controller_data = (void *)AT91_PIN_PA10, |
7f3923a18 rtc: Philips PCF2... |
23 24 25 26 27 28 |
* .max_speed_hz = 1000 * 1000, * .mode = SPI_CS_HIGH, * .bus_num = 0, * }, * ... *}; |
7f3923a18 rtc: Philips PCF2... |
29 30 31 32 33 34 35 36 |
*/ #include <linux/bcd.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/errno.h> #include <linux/init.h> #include <linux/kernel.h> |
3fc70077e drivers/rtc/rtc-p... |
37 |
#include <linux/of.h> |
7f3923a18 rtc: Philips PCF2... |
38 |
#include <linux/string.h> |
5a0e3ad6a include cleanup: ... |
39 |
#include <linux/slab.h> |
7f3923a18 rtc: Philips PCF2... |
40 41 |
#include <linux/rtc.h> #include <linux/spi/spi.h> |
2113852b2 rtc: Add module.h... |
42 |
#include <linux/module.h> |
790d03393 rtc: pcf2123: por... |
43 |
#include <linux/regmap.h> |
7f3923a18 rtc: Philips PCF2... |
44 |
|
245cb74be rtc: pcf2123: def... |
45 |
/* REGISTERS */ |
7f3923a18 rtc: Philips PCF2... |
46 47 48 49 50 51 52 53 54 |
#define PCF2123_REG_CTRL1 (0x00) /* Control Register 1 */ #define PCF2123_REG_CTRL2 (0x01) /* Control Register 2 */ #define PCF2123_REG_SC (0x02) /* datetime */ #define PCF2123_REG_MN (0x03) #define PCF2123_REG_HR (0x04) #define PCF2123_REG_DM (0x05) #define PCF2123_REG_DW (0x06) #define PCF2123_REG_MO (0x07) #define PCF2123_REG_YR (0x08) |
245cb74be rtc: pcf2123: def... |
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
#define PCF2123_REG_ALRM_MN (0x09) /* Alarm Registers */ #define PCF2123_REG_ALRM_HR (0x0a) #define PCF2123_REG_ALRM_DM (0x0b) #define PCF2123_REG_ALRM_DW (0x0c) #define PCF2123_REG_OFFSET (0x0d) /* Clock Rate Offset Register */ #define PCF2123_REG_TMR_CLKOUT (0x0e) /* Timer Registers */ #define PCF2123_REG_CTDWN_TMR (0x0f) /* PCF2123_REG_CTRL1 BITS */ #define CTRL1_CLEAR (0) /* Clear */ #define CTRL1_CORR_INT BIT(1) /* Correction irq enable */ #define CTRL1_12_HOUR BIT(2) /* 12 hour time */ #define CTRL1_SW_RESET (BIT(3) | BIT(4) | BIT(6)) /* Software reset */ #define CTRL1_STOP BIT(5) /* Stop the clock */ #define CTRL1_EXT_TEST BIT(7) /* External clock test mode */ /* PCF2123_REG_CTRL2 BITS */ #define CTRL2_TIE BIT(0) /* Countdown timer irq enable */ #define CTRL2_AIE BIT(1) /* Alarm irq enable */ #define CTRL2_TF BIT(2) /* Countdown timer flag */ #define CTRL2_AF BIT(3) /* Alarm flag */ #define CTRL2_TI_TP BIT(4) /* Irq pin generates pulse */ #define CTRL2_MSF BIT(5) /* Minute or second irq flag */ #define CTRL2_SI BIT(6) /* Second irq enable */ #define CTRL2_MI BIT(7) /* Minute irq enable */ /* PCF2123_REG_SC BITS */ #define OSC_HAS_STOPPED BIT(7) /* Clock has been stopped */ /* PCF2123_REG_ALRM_XX BITS */ |
5bdf40dab rtc: pcf2123: don... |
85 |
#define ALRM_DISABLE BIT(7) /* MN, HR, DM, or DW alarm matching */ |
245cb74be rtc: pcf2123: def... |
86 87 88 89 90 91 92 93 94 |
/* PCF2123_REG_TMR_CLKOUT BITS */ #define CD_TMR_4096KHZ (0) /* 4096 KHz countdown timer */ #define CD_TMR_64HZ (1) /* 64 Hz countdown timer */ #define CD_TMR_1HZ (2) /* 1 Hz countdown timer */ #define CD_TMR_60th_HZ (3) /* 60th Hz countdown timer */ #define CD_TMR_TE BIT(3) /* Countdown timer enable */ /* PCF2123_REG_OFFSET BITS */ |
82df3e045 rtc: pcf2123: use... |
95 |
#define OFFSET_SIGN_BIT 6 /* 2's complement sign bit */ |
245cb74be rtc: pcf2123: def... |
96 |
#define OFFSET_COARSE BIT(7) /* Coarse mode offset */ |
bae2f6470 rtc: pcf2123: imp... |
97 |
#define OFFSET_STEP (2170) /* Offset step in parts per billion */ |
790d03393 rtc: pcf2123: por... |
98 |
#define OFFSET_MASK GENMASK(6, 0) /* Offset value */ |
245cb74be rtc: pcf2123: def... |
99 100 101 102 |
/* READ/WRITE ADDRESS BITS */ #define PCF2123_WRITE BIT(4) #define PCF2123_READ (BIT(4) | BIT(7)) |
7f3923a18 rtc: Philips PCF2... |
103 |
|
7f3923a18 rtc: Philips PCF2... |
104 105 |
static struct spi_driver pcf2123_driver; |
9126a2b16 rtc: pcf2123: ren... |
106 |
struct pcf2123_data { |
7f3923a18 rtc: Philips PCF2... |
107 |
struct rtc_device *rtc; |
790d03393 rtc: pcf2123: por... |
108 |
struct regmap *map; |
7f3923a18 rtc: Philips PCF2... |
109 |
}; |
790d03393 rtc: pcf2123: por... |
110 111 112 113 114 115 116 |
static const struct regmap_config pcf2123_regmap_config = { .reg_bits = 8, .val_bits = 8, .read_flag_mask = PCF2123_READ, .write_flag_mask = PCF2123_WRITE, .max_register = PCF2123_REG_CTDWN_TMR, }; |
7f3923a18 rtc: Philips PCF2... |
117 |
|
bae2f6470 rtc: pcf2123: imp... |
118 |
static int pcf2123_read_offset(struct device *dev, long *offset) |
83ab7dad0 rtc: pcf2123: Add... |
119 |
{ |
9126a2b16 rtc: pcf2123: ren... |
120 |
struct pcf2123_data *pcf2123 = dev_get_drvdata(dev); |
790d03393 rtc: pcf2123: por... |
121 122 |
int ret, val; unsigned int reg; |
7f3923a18 rtc: Philips PCF2... |
123 |
|
9126a2b16 rtc: pcf2123: ren... |
124 |
ret = regmap_read(pcf2123->map, PCF2123_REG_OFFSET, ®); |
4c5591c1e drivers/rtc/rtc-p... |
125 126 |
if (ret) return ret; |
790d03393 rtc: pcf2123: por... |
127 |
val = sign_extend32((reg & OFFSET_MASK), OFFSET_SIGN_BIT); |
bae2f6470 rtc: pcf2123: imp... |
128 129 |
if (reg & OFFSET_COARSE) |
790d03393 rtc: pcf2123: por... |
130 |
val *= 2; |
bae2f6470 rtc: pcf2123: imp... |
131 |
|
790d03393 rtc: pcf2123: por... |
132 |
*offset = ((long)val) * OFFSET_STEP; |
bae2f6470 rtc: pcf2123: imp... |
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
return 0; } /* * The offset register is a 7 bit signed value with a coarse bit in bit 7. * The main difference between the two is normal offset adjusts the first * second of n minutes every other hour, with 61, 62 and 63 being shoved * into the 60th minute. * The coarse adjustment does the same, but every hour. * the two overlap, with every even normal offset value corresponding * to a coarse offset. Based on this algorithm, it seems that despite the * name, coarse offset is a better fit for overlapping values. */ static int pcf2123_set_offset(struct device *dev, long offset) { |
9126a2b16 rtc: pcf2123: ren... |
149 |
struct pcf2123_data *pcf2123 = dev_get_drvdata(dev); |
bae2f6470 rtc: pcf2123: imp... |
150 151 152 153 154 155 156 |
s8 reg; if (offset > OFFSET_STEP * 127) reg = 127; else if (offset < OFFSET_STEP * -128) reg = -128; else |
fedc459a3 rtc: pcf2123: fix... |
157 |
reg = DIV_ROUND_CLOSEST(offset, OFFSET_STEP); |
bae2f6470 rtc: pcf2123: imp... |
158 159 160 161 162 163 164 165 166 167 |
/* choose fine offset only for odd values in the normal range */ if (reg & 1 && reg <= 63 && reg >= -64) { /* Normal offset. Clear the coarse bit */ reg &= ~OFFSET_COARSE; } else { /* Coarse offset. Divide by 2 and set the coarse bit */ reg >>= 1; reg |= OFFSET_COARSE; } |
9126a2b16 rtc: pcf2123: ren... |
168 |
return regmap_write(pcf2123->map, PCF2123_REG_OFFSET, (unsigned int)reg); |
bae2f6470 rtc: pcf2123: imp... |
169 |
} |
7f3923a18 rtc: Philips PCF2... |
170 171 |
static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm) { |
9126a2b16 rtc: pcf2123: ren... |
172 |
struct pcf2123_data *pcf2123 = dev_get_drvdata(dev); |
66c056d6a rtc: pcf2123: cle... |
173 |
u8 rxbuf[7]; |
7f3923a18 rtc: Philips PCF2... |
174 |
int ret; |
9126a2b16 rtc: pcf2123: ren... |
175 |
ret = regmap_bulk_read(pcf2123->map, PCF2123_REG_SC, rxbuf, |
790d03393 rtc: pcf2123: por... |
176 177 |
sizeof(rxbuf)); if (ret) |
7f3923a18 rtc: Philips PCF2... |
178 |
return ret; |
7f3923a18 rtc: Philips PCF2... |
179 |
|
f07fa9242 rtc: pcf2123: avo... |
180 181 182 183 184 |
if (rxbuf[0] & OSC_HAS_STOPPED) { dev_info(dev, "clock was stopped. Time is not valid "); return -EINVAL; } |
7f3923a18 rtc: Philips PCF2... |
185 186 187 188 189 190 |
tm->tm_sec = bcd2bin(rxbuf[0] & 0x7F); tm->tm_min = bcd2bin(rxbuf[1] & 0x7F); tm->tm_hour = bcd2bin(rxbuf[2] & 0x3F); /* rtc hr 0-23 */ tm->tm_mday = bcd2bin(rxbuf[3] & 0x3F); tm->tm_wday = rxbuf[4] & 0x07; tm->tm_mon = bcd2bin(rxbuf[5] & 0x1F) - 1; /* rtc mn 1-12 */ |
d5b626e13 rtc: pcf2123: let... |
191 |
tm->tm_year = bcd2bin(rxbuf[6]) + 100; |
7f3923a18 rtc: Philips PCF2... |
192 |
|
c33850bbc rtc: pcf2123: use... |
193 194 |
dev_dbg(dev, "%s: tm is %ptR ", __func__, tm); |
7f3923a18 rtc: Philips PCF2... |
195 |
|
22652ba72 rtc: stop validat... |
196 |
return 0; |
7f3923a18 rtc: Philips PCF2... |
197 198 199 200 |
} static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm) { |
9126a2b16 rtc: pcf2123: ren... |
201 |
struct pcf2123_data *pcf2123 = dev_get_drvdata(dev); |
790d03393 rtc: pcf2123: por... |
202 |
u8 txbuf[7]; |
7f3923a18 rtc: Philips PCF2... |
203 |
int ret; |
c33850bbc rtc: pcf2123: use... |
204 205 |
dev_dbg(dev, "%s: tm is %ptR ", __func__, tm); |
7f3923a18 rtc: Philips PCF2... |
206 207 |
/* Stop the counter first */ |
9126a2b16 rtc: pcf2123: ren... |
208 |
ret = regmap_write(pcf2123->map, PCF2123_REG_CTRL1, CTRL1_STOP); |
790d03393 rtc: pcf2123: por... |
209 |
if (ret) |
7f3923a18 rtc: Philips PCF2... |
210 |
return ret; |
7f3923a18 rtc: Philips PCF2... |
211 212 |
/* Set the new time */ |
790d03393 rtc: pcf2123: por... |
213 214 215 216 217 218 |
txbuf[0] = bin2bcd(tm->tm_sec & 0x7F); txbuf[1] = bin2bcd(tm->tm_min & 0x7F); txbuf[2] = bin2bcd(tm->tm_hour & 0x3F); txbuf[3] = bin2bcd(tm->tm_mday & 0x3F); txbuf[4] = tm->tm_wday & 0x07; txbuf[5] = bin2bcd((tm->tm_mon + 1) & 0x1F); /* rtc mn 1-12 */ |
d5b626e13 rtc: pcf2123: let... |
219 |
txbuf[6] = bin2bcd(tm->tm_year - 100); |
790d03393 rtc: pcf2123: por... |
220 |
|
9126a2b16 rtc: pcf2123: ren... |
221 |
ret = regmap_bulk_write(pcf2123->map, PCF2123_REG_SC, txbuf, |
790d03393 rtc: pcf2123: por... |
222 223 |
sizeof(txbuf)); if (ret) |
7f3923a18 rtc: Philips PCF2... |
224 |
return ret; |
7f3923a18 rtc: Philips PCF2... |
225 226 |
/* Start the counter */ |
9126a2b16 rtc: pcf2123: ren... |
227 |
ret = regmap_write(pcf2123->map, PCF2123_REG_CTRL1, CTRL1_CLEAR); |
790d03393 rtc: pcf2123: por... |
228 |
if (ret) |
7f3923a18 rtc: Philips PCF2... |
229 |
return ret; |
7f3923a18 rtc: Philips PCF2... |
230 231 232 |
return 0; } |
577f64820 rtc: pcf2123: imp... |
233 234 |
static int pcf2123_rtc_alarm_irq_enable(struct device *dev, unsigned int en) { |
9126a2b16 rtc: pcf2123: ren... |
235 |
struct pcf2123_data *pcf2123 = dev_get_drvdata(dev); |
577f64820 rtc: pcf2123: imp... |
236 |
|
9126a2b16 rtc: pcf2123: ren... |
237 |
return regmap_update_bits(pcf2123->map, PCF2123_REG_CTRL2, CTRL2_AIE, |
577f64820 rtc: pcf2123: imp... |
238 239 |
en ? CTRL2_AIE : 0); } |
e32e60a2d rtc: pcf2123: add... |
240 241 |
static int pcf2123_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) { |
9126a2b16 rtc: pcf2123: ren... |
242 |
struct pcf2123_data *pcf2123 = dev_get_drvdata(dev); |
e32e60a2d rtc: pcf2123: add... |
243 244 245 |
u8 rxbuf[4]; int ret; unsigned int val = 0; |
9126a2b16 rtc: pcf2123: ren... |
246 |
ret = regmap_bulk_read(pcf2123->map, PCF2123_REG_ALRM_MN, rxbuf, |
e32e60a2d rtc: pcf2123: add... |
247 248 249 250 251 252 253 254 255 256 257 |
sizeof(rxbuf)); if (ret) return ret; alm->time.tm_min = bcd2bin(rxbuf[0] & 0x7F); alm->time.tm_hour = bcd2bin(rxbuf[1] & 0x3F); alm->time.tm_mday = bcd2bin(rxbuf[2] & 0x3F); alm->time.tm_wday = bcd2bin(rxbuf[3] & 0x07); dev_dbg(dev, "%s: alm is %ptR ", __func__, &alm->time); |
9126a2b16 rtc: pcf2123: ren... |
258 |
ret = regmap_read(pcf2123->map, PCF2123_REG_CTRL2, &val); |
e32e60a2d rtc: pcf2123: add... |
259 260 261 262 263 264 265 266 267 268 |
if (ret) return ret; alm->enabled = !!(val & CTRL2_AIE); return 0; } static int pcf2123_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) { |
9126a2b16 rtc: pcf2123: ren... |
269 |
struct pcf2123_data *pcf2123 = dev_get_drvdata(dev); |
e32e60a2d rtc: pcf2123: add... |
270 271 272 273 274 |
u8 txbuf[4]; int ret; dev_dbg(dev, "%s: alm is %ptR ", __func__, &alm->time); |
d0ce6ef71 rtc; pcf2123: fix... |
275 |
/* Disable alarm interrupt */ |
9126a2b16 rtc: pcf2123: ren... |
276 |
ret = regmap_update_bits(pcf2123->map, PCF2123_REG_CTRL2, CTRL2_AIE, 0); |
e32e60a2d rtc: pcf2123: add... |
277 |
if (ret) |
7f3923a18 rtc: Philips PCF2... |
278 |
return ret; |
7f3923a18 rtc: Philips PCF2... |
279 |
|
d0ce6ef71 rtc; pcf2123: fix... |
280 |
/* Ensure alarm flag is clear */ |
9126a2b16 rtc: pcf2123: ren... |
281 |
ret = regmap_update_bits(pcf2123->map, PCF2123_REG_CTRL2, CTRL2_AF, 0); |
e32e60a2d rtc: pcf2123: add... |
282 283 284 285 286 287 288 |
if (ret) return ret; /* Set new alarm */ txbuf[0] = bin2bcd(alm->time.tm_min & 0x7F); txbuf[1] = bin2bcd(alm->time.tm_hour & 0x3F); txbuf[2] = bin2bcd(alm->time.tm_mday & 0x3F); |
5bdf40dab rtc: pcf2123: don... |
289 |
txbuf[3] = ALRM_DISABLE; |
e32e60a2d rtc: pcf2123: add... |
290 |
|
9126a2b16 rtc: pcf2123: ren... |
291 |
ret = regmap_bulk_write(pcf2123->map, PCF2123_REG_ALRM_MN, txbuf, |
e32e60a2d rtc: pcf2123: add... |
292 293 294 |
sizeof(txbuf)); if (ret) return ret; |
577f64820 rtc: pcf2123: imp... |
295 |
return pcf2123_rtc_alarm_irq_enable(dev, alm->enabled); |
7f3923a18 rtc: Philips PCF2... |
296 |
} |
e32e60a2d rtc: pcf2123: add... |
297 298 |
static irqreturn_t pcf2123_rtc_irq(int irq, void *dev) { |
9126a2b16 rtc: pcf2123: ren... |
299 300 |
struct pcf2123_data *pcf2123 = dev_get_drvdata(dev); struct mutex *lock = &pcf2123->rtc->ops_lock; |
e32e60a2d rtc: pcf2123: add... |
301 302 303 304 |
unsigned int val = 0; int ret = IRQ_NONE; mutex_lock(lock); |
9126a2b16 rtc: pcf2123: ren... |
305 |
regmap_read(pcf2123->map, PCF2123_REG_CTRL2, &val); |
e32e60a2d rtc: pcf2123: add... |
306 307 308 309 310 311 |
/* Alarm? */ if (val & CTRL2_AF) { ret = IRQ_HANDLED; /* Clear alarm flag */ |
9126a2b16 rtc: pcf2123: ren... |
312 |
regmap_update_bits(pcf2123->map, PCF2123_REG_CTRL2, CTRL2_AF, 0); |
e32e60a2d rtc: pcf2123: add... |
313 |
|
9126a2b16 rtc: pcf2123: ren... |
314 |
rtc_update_irq(pcf2123->rtc, 1, RTC_IRQF | RTC_AF); |
e32e60a2d rtc: pcf2123: add... |
315 316 317 318 319 320 |
} mutex_unlock(lock); return ret; } |
1e094b946 rtc: pcf2123: ref... |
321 322 |
static int pcf2123_reset(struct device *dev) { |
9126a2b16 rtc: pcf2123: ren... |
323 |
struct pcf2123_data *pcf2123 = dev_get_drvdata(dev); |
1e094b946 rtc: pcf2123: ref... |
324 |
int ret; |
790d03393 rtc: pcf2123: por... |
325 |
unsigned int val = 0; |
1e094b946 rtc: pcf2123: ref... |
326 |
|
9126a2b16 rtc: pcf2123: ren... |
327 |
ret = regmap_write(pcf2123->map, PCF2123_REG_CTRL1, CTRL1_SW_RESET); |
790d03393 rtc: pcf2123: por... |
328 |
if (ret) |
1e094b946 rtc: pcf2123: ref... |
329 330 331 332 333 |
return ret; /* Stop the counter */ dev_dbg(dev, "stopping RTC "); |
9126a2b16 rtc: pcf2123: ren... |
334 |
ret = regmap_write(pcf2123->map, PCF2123_REG_CTRL1, CTRL1_STOP); |
790d03393 rtc: pcf2123: por... |
335 |
if (ret) |
1e094b946 rtc: pcf2123: ref... |
336 337 338 339 340 |
return ret; /* See if the counter was actually stopped */ dev_dbg(dev, "checking for presence of RTC "); |
9126a2b16 rtc: pcf2123: ren... |
341 |
ret = regmap_read(pcf2123->map, PCF2123_REG_CTRL1, &val); |
790d03393 rtc: pcf2123: por... |
342 |
if (ret) |
1e094b946 rtc: pcf2123: ref... |
343 |
return ret; |
790d03393 rtc: pcf2123: por... |
344 345 346 |
dev_dbg(dev, "received data from RTC (0x%08X) ", val); if (!(val & CTRL1_STOP)) |
1e094b946 rtc: pcf2123: ref... |
347 348 349 |
return -ENODEV; /* Start the counter */ |
9126a2b16 rtc: pcf2123: ren... |
350 |
ret = regmap_write(pcf2123->map, PCF2123_REG_CTRL1, CTRL1_CLEAR); |
790d03393 rtc: pcf2123: por... |
351 |
if (ret) |
1e094b946 rtc: pcf2123: ref... |
352 353 354 355 |
return ret; return 0; } |
7f3923a18 rtc: Philips PCF2... |
356 357 358 |
static const struct rtc_class_ops pcf2123_rtc_ops = { .read_time = pcf2123_rtc_read_time, .set_time = pcf2123_rtc_set_time, |
bae2f6470 rtc: pcf2123: imp... |
359 360 |
.read_offset = pcf2123_read_offset, .set_offset = pcf2123_set_offset, |
e32e60a2d rtc: pcf2123: add... |
361 362 |
.read_alarm = pcf2123_rtc_read_alarm, .set_alarm = pcf2123_rtc_set_alarm, |
577f64820 rtc: pcf2123: imp... |
363 |
.alarm_irq_enable = pcf2123_rtc_alarm_irq_enable, |
7f3923a18 rtc: Philips PCF2... |
364 |
}; |
5a167f454 Drivers: rtc: rem... |
365 |
static int pcf2123_probe(struct spi_device *spi) |
7f3923a18 rtc: Philips PCF2... |
366 367 |
{ struct rtc_device *rtc; |
f07fa9242 rtc: pcf2123: avo... |
368 |
struct rtc_time tm; |
9126a2b16 rtc: pcf2123: ren... |
369 |
struct pcf2123_data *pcf2123; |
e32e60a2d rtc: pcf2123: add... |
370 |
int ret = 0; |
7f3923a18 rtc: Philips PCF2... |
371 |
|
9126a2b16 rtc: pcf2123: ren... |
372 |
pcf2123 = devm_kzalloc(&spi->dev, sizeof(struct pcf2123_data), |
dd48ccc49 rtc: rtc-pcf2123:... |
373 |
GFP_KERNEL); |
9126a2b16 rtc: pcf2123: ren... |
374 |
if (!pcf2123) |
7f3923a18 rtc: Philips PCF2... |
375 |
return -ENOMEM; |
d3bad6026 rtc: pcf2123: sto... |
376 |
|
9126a2b16 rtc: pcf2123: ren... |
377 |
dev_set_drvdata(&spi->dev, pcf2123); |
7f3923a18 rtc: Philips PCF2... |
378 |
|
9126a2b16 rtc: pcf2123: ren... |
379 |
pcf2123->map = devm_regmap_init_spi(spi, &pcf2123_regmap_config); |
9126a2b16 rtc: pcf2123: ren... |
380 |
if (IS_ERR(pcf2123->map)) { |
790d03393 rtc: pcf2123: por... |
381 382 |
dev_err(&spi->dev, "regmap init failed. "); |
9a5aeaad7 rtc: pcf2123: rem... |
383 |
return PTR_ERR(pcf2123->map); |
790d03393 rtc: pcf2123: por... |
384 |
} |
f07fa9242 rtc: pcf2123: avo... |
385 |
ret = pcf2123_rtc_read_time(&spi->dev, &tm); |
1e094b946 rtc: pcf2123: ref... |
386 |
if (ret < 0) { |
f07fa9242 rtc: pcf2123: avo... |
387 388 389 390 |
ret = pcf2123_reset(&spi->dev); if (ret < 0) { dev_err(&spi->dev, "chip not found "); |
9a5aeaad7 rtc: pcf2123: rem... |
391 |
return ret; |
f07fa9242 rtc: pcf2123: avo... |
392 |
} |
7f3923a18 rtc: Philips PCF2... |
393 |
} |
7f3923a18 rtc: Philips PCF2... |
394 395 396 |
dev_info(&spi->dev, "spiclk %u KHz. ", (spi->max_speed_hz + 500) / 1000); |
7f3923a18 rtc: Philips PCF2... |
397 |
/* Finalize the initialization */ |
935a7f459 rtc: pcf2123: con... |
398 399 |
rtc = devm_rtc_allocate_device(&spi->dev); if (IS_ERR(rtc)) |
9a5aeaad7 rtc: pcf2123: rem... |
400 |
return PTR_ERR(rtc); |
7f3923a18 rtc: Philips PCF2... |
401 |
|
9126a2b16 rtc: pcf2123: ren... |
402 |
pcf2123->rtc = rtc; |
7f3923a18 rtc: Philips PCF2... |
403 |
|
e32e60a2d rtc: pcf2123: add... |
404 405 406 407 408 409 410 411 412 413 414 |
/* Register alarm irq */ if (spi->irq > 0) { ret = devm_request_threaded_irq(&spi->dev, spi->irq, NULL, pcf2123_rtc_irq, IRQF_TRIGGER_LOW | IRQF_ONESHOT, pcf2123_driver.driver.name, &spi->dev); if (!ret) device_init_wakeup(&spi->dev, true); else dev_err(&spi->dev, "could not request irq. "); |
7f3923a18 rtc: Philips PCF2... |
415 |
} |
e32e60a2d rtc: pcf2123: add... |
416 417 418 419 |
/* The PCF2123's alarm only has minute accuracy. Must add timer * support to this driver to generate interrupts more than once * per minute. */ |
935a7f459 rtc: pcf2123: con... |
420 421 |
rtc->uie_unsupported = 1; rtc->ops = &pcf2123_rtc_ops; |
d5b626e13 rtc: pcf2123: let... |
422 423 424 |
rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; rtc->range_max = RTC_TIMESTAMP_END_2099; rtc->set_start_time = true; |
935a7f459 rtc: pcf2123: con... |
425 426 427 428 |
ret = rtc_register_device(rtc); if (ret) return ret; |
f3d2570a1 rtc-philips-pcf21... |
429 |
|
7f3923a18 rtc: Philips PCF2... |
430 |
return 0; |
7f3923a18 rtc: Philips PCF2... |
431 |
} |
3fc70077e drivers/rtc/rtc-p... |
432 433 |
#ifdef CONFIG_OF static const struct of_device_id pcf2123_dt_ids[] = { |
cb36cf803 rtc: pcf2123: add... |
434 |
{ .compatible = "nxp,pcf2123", }, |
3c3d71013 rtc: pcf2123: Add... |
435 |
{ .compatible = "microcrystal,rv2123", }, |
cb36cf803 rtc: pcf2123: add... |
436 437 |
/* Deprecated, do not use */ { .compatible = "nxp,rtc-pcf2123", }, |
3fc70077e drivers/rtc/rtc-p... |
438 439 440 441 |
{ /* sentinel */ } }; MODULE_DEVICE_TABLE(of, pcf2123_dt_ids); #endif |
7f3923a18 rtc: Philips PCF2... |
442 443 444 |
static struct spi_driver pcf2123_driver = { .driver = { .name = "rtc-pcf2123", |
3fc70077e drivers/rtc/rtc-p... |
445 |
.of_match_table = of_match_ptr(pcf2123_dt_ids), |
7f3923a18 rtc: Philips PCF2... |
446 447 |
}, .probe = pcf2123_probe, |
7f3923a18 rtc: Philips PCF2... |
448 |
}; |
109e94184 rtc: convert rtc ... |
449 |
module_spi_driver(pcf2123_driver); |
7f3923a18 rtc: Philips PCF2... |
450 451 452 453 |
MODULE_AUTHOR("Chris Verges <chrisv@cyberswitching.com>"); MODULE_DESCRIPTION("NXP PCF2123 RTC driver"); MODULE_LICENSE("GPL"); |