1*2f16049cSEmmanuel Vadot /*-
2*2f16049cSEmmanuel Vadot * SPDX-License-Identifier: BSD-2-Clause
3*2f16049cSEmmanuel Vadot *
4*2f16049cSEmmanuel Vadot * Copyright (c) 2017 Ian Lepore <ian@freebsd.org>
5*2f16049cSEmmanuel Vadot *
6*2f16049cSEmmanuel Vadot * Redistribution and use in source and binary forms, with or without
7*2f16049cSEmmanuel Vadot * modification, are permitted provided that the following conditions
8*2f16049cSEmmanuel Vadot * are met:
9*2f16049cSEmmanuel Vadot * 1. Redistributions of source code must retain the above copyright
10*2f16049cSEmmanuel Vadot * notice, this list of conditions and the following disclaimer.
11*2f16049cSEmmanuel Vadot * 2. Redistributions in binary form must reproduce the above copyright
12*2f16049cSEmmanuel Vadot * notice, this list of conditions and the following disclaimer in the
13*2f16049cSEmmanuel Vadot * documentation and/or other materials provided with the distribution.
14*2f16049cSEmmanuel Vadot *
15*2f16049cSEmmanuel Vadot * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*2f16049cSEmmanuel Vadot * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*2f16049cSEmmanuel Vadot * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*2f16049cSEmmanuel Vadot * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*2f16049cSEmmanuel Vadot * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*2f16049cSEmmanuel Vadot * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*2f16049cSEmmanuel Vadot * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*2f16049cSEmmanuel Vadot * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*2f16049cSEmmanuel Vadot * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*2f16049cSEmmanuel Vadot * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*2f16049cSEmmanuel Vadot * SUCH DAMAGE.
26*2f16049cSEmmanuel Vadot */
27*2f16049cSEmmanuel Vadot
28*2f16049cSEmmanuel Vadot #include <sys/cdefs.h>
29*2f16049cSEmmanuel Vadot /*
30*2f16049cSEmmanuel Vadot * Driver for NXP real-time clock/calendar chips:
31*2f16049cSEmmanuel Vadot * - PCF8563 = low power, countdown timer
32*2f16049cSEmmanuel Vadot * - PCA8565 = like PCF8563, automotive temperature range
33*2f16049cSEmmanuel Vadot * - PCF8523 = low power, countdown timer, oscillator freq tuning, 2 timers
34*2f16049cSEmmanuel Vadot * - PCF2127 = like PCF8523, industrial, tcxo, tamper/ts, i2c & spi, 512B ram
35*2f16049cSEmmanuel Vadot * - PCA2129 = like PCF8523, automotive, tcxo, tamper/ts, i2c & spi, (note 1)
36*2f16049cSEmmanuel Vadot * - PCF2129 = like PCF8523, industrial, tcxo, tamper/ts, i2c & spi, (note 1)
37*2f16049cSEmmanuel Vadot *
38*2f16049cSEmmanuel Vadot * Most chips have a countdown timer, ostensibly intended to generate periodic
39*2f16049cSEmmanuel Vadot * interrupt signals on an output pin. The timer is driven from the same
40*2f16049cSEmmanuel Vadot * divider chain that clocks the time of day registers, and they start counting
41*2f16049cSEmmanuel Vadot * in sync when the STOP bit is cleared after the time and timer registers are
42*2f16049cSEmmanuel Vadot * set. The timer register can also be read on the fly, so we use it to count
43*2f16049cSEmmanuel Vadot * fractional seconds and get a resolution of ~15ms.
44*2f16049cSEmmanuel Vadot *
45*2f16049cSEmmanuel Vadot * [1] Note that the datasheets for the PCx2129 chips state that they have only
46*2f16049cSEmmanuel Vadot * a watchdog timer, not a countdown timer. Empirical testing shows that the
47*2f16049cSEmmanuel Vadot * countdown timer is actually there and it works fine, except that it can't
48*2f16049cSEmmanuel Vadot * trigger an interrupt or toggle an output pin like it can on other chips. We
49*2f16049cSEmmanuel Vadot * don't care about interrupts and output pins, we just read the timer register
50*2f16049cSEmmanuel Vadot * to get better resolution.
51*2f16049cSEmmanuel Vadot */
52*2f16049cSEmmanuel Vadot
53*2f16049cSEmmanuel Vadot #include "opt_platform.h"
54*2f16049cSEmmanuel Vadot
55*2f16049cSEmmanuel Vadot #include <sys/param.h>
56*2f16049cSEmmanuel Vadot #include <sys/systm.h>
57*2f16049cSEmmanuel Vadot #include <sys/bus.h>
58*2f16049cSEmmanuel Vadot #include <sys/clock.h>
59*2f16049cSEmmanuel Vadot #include <sys/kernel.h>
60*2f16049cSEmmanuel Vadot #include <sys/libkern.h>
61*2f16049cSEmmanuel Vadot #include <sys/module.h>
62*2f16049cSEmmanuel Vadot #include <sys/sysctl.h>
63*2f16049cSEmmanuel Vadot
64*2f16049cSEmmanuel Vadot #include <dev/iicbus/iicbus.h>
65*2f16049cSEmmanuel Vadot #include <dev/iicbus/iiconf.h>
66*2f16049cSEmmanuel Vadot #ifdef FDT
67*2f16049cSEmmanuel Vadot #include <dev/ofw/openfirm.h>
68*2f16049cSEmmanuel Vadot #include <dev/ofw/ofw_bus.h>
69*2f16049cSEmmanuel Vadot #include <dev/ofw/ofw_bus_subr.h>
70*2f16049cSEmmanuel Vadot #endif
71*2f16049cSEmmanuel Vadot
72*2f16049cSEmmanuel Vadot #include "clock_if.h"
73*2f16049cSEmmanuel Vadot #include "iicbus_if.h"
74*2f16049cSEmmanuel Vadot
75*2f16049cSEmmanuel Vadot /*
76*2f16049cSEmmanuel Vadot * I2C address 1010 001x : PCA2129 PCF2127 PCF2129 PCF8563 PCF8565
77*2f16049cSEmmanuel Vadot * I2C address 1101 000x : PCF8523
78*2f16049cSEmmanuel Vadot */
79*2f16049cSEmmanuel Vadot #define PCF8563_ADDR 0xa2
80*2f16049cSEmmanuel Vadot #define PCF8523_ADDR 0xd0
81*2f16049cSEmmanuel Vadot
82*2f16049cSEmmanuel Vadot /*
83*2f16049cSEmmanuel Vadot * Registers, bits within them, and masks that are common to all chip types.
84*2f16049cSEmmanuel Vadot */
85*2f16049cSEmmanuel Vadot #define PCF85xx_R_CS1 0x00 /* CS1 and CS2 control regs are in */
86*2f16049cSEmmanuel Vadot #define PCF85xx_R_CS2 0x01 /* the same location on all chips. */
87*2f16049cSEmmanuel Vadot
88*2f16049cSEmmanuel Vadot #define PCF85xx_B_CS1_STOP 0x20 /* Stop time incrementing bit */
89*2f16049cSEmmanuel Vadot #define PCF85xx_B_SECOND_OS 0x80 /* Oscillator Stopped bit */
90*2f16049cSEmmanuel Vadot
91*2f16049cSEmmanuel Vadot #define PCF85xx_M_SECOND 0x7f /* Masks for all BCD time regs... */
92*2f16049cSEmmanuel Vadot #define PCF85xx_M_MINUTE 0x7f
93*2f16049cSEmmanuel Vadot #define PCF85xx_M_12HOUR 0x1f
94*2f16049cSEmmanuel Vadot #define PCF85xx_M_24HOUR 0x3f
95*2f16049cSEmmanuel Vadot #define PCF85xx_M_DAY 0x3f
96*2f16049cSEmmanuel Vadot #define PCF85xx_M_MONTH 0x1f
97*2f16049cSEmmanuel Vadot #define PCF85xx_M_YEAR 0xff
98*2f16049cSEmmanuel Vadot
99*2f16049cSEmmanuel Vadot /*
100*2f16049cSEmmanuel Vadot * PCF2127-specific registers, bits, and masks.
101*2f16049cSEmmanuel Vadot */
102*2f16049cSEmmanuel Vadot #define PCF2127_R_TMR_CTL 0x10 /* Timer/watchdog control */
103*2f16049cSEmmanuel Vadot
104*2f16049cSEmmanuel Vadot #define PCF2127_M_TMR_CTRL 0xe3 /* Mask off undef bits */
105*2f16049cSEmmanuel Vadot
106*2f16049cSEmmanuel Vadot #define PCF2127_B_TMR_CD 0x40 /* Run in countdown mode */
107*2f16049cSEmmanuel Vadot #define PCF2127_B_TMR_64HZ 0x01 /* Timer frequency 64Hz */
108*2f16049cSEmmanuel Vadot
109*2f16049cSEmmanuel Vadot #define PCF2127_R_TS_CTL 0x12 /* Timestamp control */
110*2f16049cSEmmanuel Vadot #define PCF2127_B_TSOFF 0x40 /* Turn off timestamp function */
111*2f16049cSEmmanuel Vadot
112*2f16049cSEmmanuel Vadot #define PCF2127_R_AGING_OFFSET 0x19 /* Frequency aging offset in PPM */
113*2f16049cSEmmanuel Vadot
114*2f16049cSEmmanuel Vadot /*
115*2f16049cSEmmanuel Vadot * PCA/PCF2129-specific registers, bits, and masks.
116*2f16049cSEmmanuel Vadot */
117*2f16049cSEmmanuel Vadot #define PCF2129_B_CS1_12HR 0x04 /* Use 12-hour (AM/PM) mode bit */
118*2f16049cSEmmanuel Vadot #define PCF2129_B_CLKOUT_OTPR 0x20 /* OTP refresh command */
119*2f16049cSEmmanuel Vadot #define PCF2129_B_CLKOUT_HIGHZ 0x07 /* Clock Out Freq = disable */
120*2f16049cSEmmanuel Vadot
121*2f16049cSEmmanuel Vadot /*
122*2f16049cSEmmanuel Vadot * PCF8523-specific registers, bits, and masks.
123*2f16049cSEmmanuel Vadot */
124*2f16049cSEmmanuel Vadot #define PCF8523_R_CS3 0x02 /* Control and status reg 3 */
125*2f16049cSEmmanuel Vadot #define PCF8523_R_SECOND 0x03 /* Seconds */
126*2f16049cSEmmanuel Vadot #define PCF8523_R_TMR_CLKOUT 0x0F /* Timer and clockout control */
127*2f16049cSEmmanuel Vadot #define PCF8523_R_TMR_A_FREQ 0x10 /* Timer A frequency control */
128*2f16049cSEmmanuel Vadot #define PCF8523_R_TMR_A_COUNT 0x11 /* Timer A count */
129*2f16049cSEmmanuel Vadot
130*2f16049cSEmmanuel Vadot #define PCF8523_M_TMR_A_FREQ 0x07 /* Mask off undef bits */
131*2f16049cSEmmanuel Vadot
132*2f16049cSEmmanuel Vadot #define PCF8523_B_HOUR_PM 0x20 /* PM bit */
133*2f16049cSEmmanuel Vadot #define PCF8523_B_CS1_SOFTRESET 0x58 /* Initiate Soft Reset bits */
134*2f16049cSEmmanuel Vadot #define PCF8523_B_CS1_12HR 0x08 /* Use 12-hour (AM/PM) mode bit */
135*2f16049cSEmmanuel Vadot #define PCF8523_B_CLKOUT_TACD 0x02 /* TimerA runs in CountDown mode */
136*2f16049cSEmmanuel Vadot #define PCF8523_B_CLKOUT_HIGHZ 0x38 /* Clock Out Freq = disable */
137*2f16049cSEmmanuel Vadot #define PCF8523_B_TMR_A_64HZ 0x01 /* Timer A freq 64Hz */
138*2f16049cSEmmanuel Vadot
139*2f16049cSEmmanuel Vadot #define PCF8523_M_CS3_PM 0xE0 /* Power mode mask */
140*2f16049cSEmmanuel Vadot #define PCF8523_B_CS3_PM_NOBAT 0xE0 /* PM bits: no battery usage */
141*2f16049cSEmmanuel Vadot #define PCF8523_B_CS3_PM_STD 0x00 /* PM bits: standard */
142*2f16049cSEmmanuel Vadot #define PCF8523_B_CS3_PM_DSNBM 0xa0 /* PM bits: direct switch, no bat mon */
143*2f16049cSEmmanuel Vadot #define PCF8523_B_CS3_BLF 0x04 /* Battery Low Flag bit */
144*2f16049cSEmmanuel Vadot
145*2f16049cSEmmanuel Vadot /*
146*2f16049cSEmmanuel Vadot * PCF8563-specific registers, bits, and masks.
147*2f16049cSEmmanuel Vadot */
148*2f16049cSEmmanuel Vadot #define PCF8563_R_SECOND 0x02 /* Seconds */
149*2f16049cSEmmanuel Vadot
150*2f16049cSEmmanuel Vadot #define PCF8563_R_CLKOUT 0x0d /* Clock output control */
151*2f16049cSEmmanuel Vadot
152*2f16049cSEmmanuel Vadot #define PCF8563_R_TMR_CTRL 0x0e /* Timer control */
153*2f16049cSEmmanuel Vadot #define PCF8563_R_TMR_COUNT 0x0f /* Timer count */
154*2f16049cSEmmanuel Vadot
155*2f16049cSEmmanuel Vadot #define PCF8563_M_TMR_CTRL 0x93 /* Mask off undef bits */
156*2f16049cSEmmanuel Vadot
157*2f16049cSEmmanuel Vadot #define PCF8563_B_TMR_ENABLE 0x80 /* Enable countdown timer */
158*2f16049cSEmmanuel Vadot #define PCF8563_B_TMR_64HZ 0x01 /* Timer frequency 64Hz */
159*2f16049cSEmmanuel Vadot
160*2f16049cSEmmanuel Vadot #define PCF8563_B_MONTH_C 0x80 /* Century bit */
161*2f16049cSEmmanuel Vadot
162*2f16049cSEmmanuel Vadot /*
163*2f16049cSEmmanuel Vadot * We use the countdown timer for fractional seconds. We program it for 64 Hz,
164*2f16049cSEmmanuel Vadot * the fastest available rate that doesn't roll over in less than a second.
165*2f16049cSEmmanuel Vadot */
166*2f16049cSEmmanuel Vadot #define TMR_TICKS_SEC 64
167*2f16049cSEmmanuel Vadot #define TMR_TICKS_HALFSEC 32
168*2f16049cSEmmanuel Vadot
169*2f16049cSEmmanuel Vadot /*
170*2f16049cSEmmanuel Vadot * The chip types we support.
171*2f16049cSEmmanuel Vadot */
172*2f16049cSEmmanuel Vadot enum {
173*2f16049cSEmmanuel Vadot TYPE_NONE,
174*2f16049cSEmmanuel Vadot TYPE_PCA2129,
175*2f16049cSEmmanuel Vadot TYPE_PCA8565,
176*2f16049cSEmmanuel Vadot TYPE_PCF2127,
177*2f16049cSEmmanuel Vadot TYPE_PCF2129,
178*2f16049cSEmmanuel Vadot TYPE_PCF8523,
179*2f16049cSEmmanuel Vadot TYPE_PCF8563,
180*2f16049cSEmmanuel Vadot
181*2f16049cSEmmanuel Vadot TYPE_COUNT
182*2f16049cSEmmanuel Vadot };
183*2f16049cSEmmanuel Vadot static const char *desc_strings[] = {
184*2f16049cSEmmanuel Vadot "",
185*2f16049cSEmmanuel Vadot "NXP PCA2129 RTC",
186*2f16049cSEmmanuel Vadot "NXP PCA8565 RTC",
187*2f16049cSEmmanuel Vadot "NXP PCF2127 RTC",
188*2f16049cSEmmanuel Vadot "NXP PCF2129 RTC",
189*2f16049cSEmmanuel Vadot "NXP PCF8523 RTC",
190*2f16049cSEmmanuel Vadot "NXP PCF8563 RTC",
191*2f16049cSEmmanuel Vadot };
192*2f16049cSEmmanuel Vadot CTASSERT(nitems(desc_strings) == TYPE_COUNT);
193*2f16049cSEmmanuel Vadot
194*2f16049cSEmmanuel Vadot /*
195*2f16049cSEmmanuel Vadot * The time registers in the order they are laid out in hardware.
196*2f16049cSEmmanuel Vadot */
197*2f16049cSEmmanuel Vadot struct time_regs {
198*2f16049cSEmmanuel Vadot uint8_t sec, min, hour, day, wday, month, year;
199*2f16049cSEmmanuel Vadot };
200*2f16049cSEmmanuel Vadot
201*2f16049cSEmmanuel Vadot struct nxprtc_softc {
202*2f16049cSEmmanuel Vadot device_t dev;
203*2f16049cSEmmanuel Vadot device_t busdev;
204*2f16049cSEmmanuel Vadot struct intr_config_hook
205*2f16049cSEmmanuel Vadot config_hook;
206*2f16049cSEmmanuel Vadot u_int flags; /* SC_F_* flags */
207*2f16049cSEmmanuel Vadot u_int chiptype; /* Type of PCF85xx chip */
208*2f16049cSEmmanuel Vadot time_t bat_time; /* Next time to check battery */
209*2f16049cSEmmanuel Vadot int freqadj; /* Current freq adj in PPM */
210*2f16049cSEmmanuel Vadot uint8_t secaddr; /* Address of seconds register */
211*2f16049cSEmmanuel Vadot uint8_t tmcaddr; /* Address of timer count register */
212*2f16049cSEmmanuel Vadot bool use_timer; /* Use timer for fractional sec */
213*2f16049cSEmmanuel Vadot bool use_ampm; /* Chip is set to use am/pm mode */
214*2f16049cSEmmanuel Vadot bool is212x; /* Chip type is 2127 or 2129 */
215*2f16049cSEmmanuel Vadot };
216*2f16049cSEmmanuel Vadot
217*2f16049cSEmmanuel Vadot #define SC_F_CPOL (1 << 0) /* Century bit means 19xx */
218*2f16049cSEmmanuel Vadot
219*2f16049cSEmmanuel Vadot /*
220*2f16049cSEmmanuel Vadot * When doing i2c IO, indicate that we need to wait for exclusive bus ownership,
221*2f16049cSEmmanuel Vadot * but that we should not wait if we already own the bus. This lets us put
222*2f16049cSEmmanuel Vadot * iicbus_acquire_bus() calls with a non-recursive wait at the entry of our API
223*2f16049cSEmmanuel Vadot * functions to ensure that only one client at a time accesses the hardware for
224*2f16049cSEmmanuel Vadot * the entire series of operations it takes to read or write the clock.
225*2f16049cSEmmanuel Vadot */
226*2f16049cSEmmanuel Vadot #define WAITFLAGS (IIC_WAIT | IIC_RECURSIVE)
227*2f16049cSEmmanuel Vadot
228*2f16049cSEmmanuel Vadot /*
229*2f16049cSEmmanuel Vadot * We use the compat_data table to look up hint strings in the non-FDT case, so
230*2f16049cSEmmanuel Vadot * define the struct locally when we don't get it from ofw_bus_subr.h.
231*2f16049cSEmmanuel Vadot */
232*2f16049cSEmmanuel Vadot #ifdef FDT
233*2f16049cSEmmanuel Vadot typedef struct ofw_compat_data nxprtc_compat_data;
234*2f16049cSEmmanuel Vadot #else
235*2f16049cSEmmanuel Vadot typedef struct {
236*2f16049cSEmmanuel Vadot const char *ocd_str;
237*2f16049cSEmmanuel Vadot uintptr_t ocd_data;
238*2f16049cSEmmanuel Vadot } nxprtc_compat_data;
239*2f16049cSEmmanuel Vadot #endif
240*2f16049cSEmmanuel Vadot
241*2f16049cSEmmanuel Vadot static nxprtc_compat_data compat_data[] = {
242*2f16049cSEmmanuel Vadot {"nxp,pca2129", TYPE_PCA2129},
243*2f16049cSEmmanuel Vadot {"nxp,pca8565", TYPE_PCA8565},
244*2f16049cSEmmanuel Vadot {"nxp,pcf2127", TYPE_PCF2127},
245*2f16049cSEmmanuel Vadot {"nxp,pcf2129", TYPE_PCF2129},
246*2f16049cSEmmanuel Vadot {"nxp,pcf8523", TYPE_PCF8523},
247*2f16049cSEmmanuel Vadot {"nxp,pcf8563", TYPE_PCF8563},
248*2f16049cSEmmanuel Vadot
249*2f16049cSEmmanuel Vadot /* Undocumented compat strings known to exist in the wild... */
250*2f16049cSEmmanuel Vadot {"pcf8563", TYPE_PCF8563},
251*2f16049cSEmmanuel Vadot {"phg,pcf8563", TYPE_PCF8563},
252*2f16049cSEmmanuel Vadot {"philips,pcf8563", TYPE_PCF8563},
253*2f16049cSEmmanuel Vadot
254*2f16049cSEmmanuel Vadot {NULL, TYPE_NONE},
255*2f16049cSEmmanuel Vadot };
256*2f16049cSEmmanuel Vadot
257*2f16049cSEmmanuel Vadot static int
nxprtc_readfrom(device_t slavedev,uint8_t regaddr,void * buffer,uint16_t buflen,int waithow)258*2f16049cSEmmanuel Vadot nxprtc_readfrom(device_t slavedev, uint8_t regaddr, void *buffer,
259*2f16049cSEmmanuel Vadot uint16_t buflen, int waithow)
260*2f16049cSEmmanuel Vadot {
261*2f16049cSEmmanuel Vadot struct iic_msg msg;
262*2f16049cSEmmanuel Vadot int err;
263*2f16049cSEmmanuel Vadot uint8_t slaveaddr;
264*2f16049cSEmmanuel Vadot
265*2f16049cSEmmanuel Vadot /*
266*2f16049cSEmmanuel Vadot * Two transfers back to back with a stop and start between them; first we
267*2f16049cSEmmanuel Vadot * write the address-within-device, then we read from the device. This
268*2f16049cSEmmanuel Vadot * is used instead of the standard iicdev_readfrom() because some of the
269*2f16049cSEmmanuel Vadot * chips we service don't support i2c repeat-start operations (grrrrr)
270*2f16049cSEmmanuel Vadot * so we do two completely separate transfers with a full stop between.
271*2f16049cSEmmanuel Vadot */
272*2f16049cSEmmanuel Vadot slaveaddr = iicbus_get_addr(slavedev);
273*2f16049cSEmmanuel Vadot
274*2f16049cSEmmanuel Vadot msg.slave = slaveaddr;
275*2f16049cSEmmanuel Vadot msg.flags = IIC_M_WR;
276*2f16049cSEmmanuel Vadot msg.len = 1;
277*2f16049cSEmmanuel Vadot msg.buf = ®addr;
278*2f16049cSEmmanuel Vadot
279*2f16049cSEmmanuel Vadot if ((err = iicbus_transfer_excl(slavedev, &msg, 1, waithow)) != 0)
280*2f16049cSEmmanuel Vadot return (err);
281*2f16049cSEmmanuel Vadot
282*2f16049cSEmmanuel Vadot msg.slave = slaveaddr;
283*2f16049cSEmmanuel Vadot msg.flags = IIC_M_RD;
284*2f16049cSEmmanuel Vadot msg.len = buflen;
285*2f16049cSEmmanuel Vadot msg.buf = buffer;
286*2f16049cSEmmanuel Vadot
287*2f16049cSEmmanuel Vadot return (iicbus_transfer_excl(slavedev, &msg, 1, waithow));
288*2f16049cSEmmanuel Vadot }
289*2f16049cSEmmanuel Vadot
290*2f16049cSEmmanuel Vadot static int
read_reg(struct nxprtc_softc * sc,uint8_t reg,uint8_t * val)291*2f16049cSEmmanuel Vadot read_reg(struct nxprtc_softc *sc, uint8_t reg, uint8_t *val)
292*2f16049cSEmmanuel Vadot {
293*2f16049cSEmmanuel Vadot
294*2f16049cSEmmanuel Vadot return (nxprtc_readfrom(sc->dev, reg, val, sizeof(*val), WAITFLAGS));
295*2f16049cSEmmanuel Vadot }
296*2f16049cSEmmanuel Vadot
297*2f16049cSEmmanuel Vadot static int
write_reg(struct nxprtc_softc * sc,uint8_t reg,uint8_t val)298*2f16049cSEmmanuel Vadot write_reg(struct nxprtc_softc *sc, uint8_t reg, uint8_t val)
299*2f16049cSEmmanuel Vadot {
300*2f16049cSEmmanuel Vadot
301*2f16049cSEmmanuel Vadot return (iicdev_writeto(sc->dev, reg, &val, sizeof(val), WAITFLAGS));
302*2f16049cSEmmanuel Vadot }
303*2f16049cSEmmanuel Vadot
304*2f16049cSEmmanuel Vadot static int
read_timeregs(struct nxprtc_softc * sc,struct time_regs * tregs,uint8_t * tmr)305*2f16049cSEmmanuel Vadot read_timeregs(struct nxprtc_softc *sc, struct time_regs *tregs, uint8_t *tmr)
306*2f16049cSEmmanuel Vadot {
307*2f16049cSEmmanuel Vadot int err;
308*2f16049cSEmmanuel Vadot uint8_t sec, tmr1, tmr2;
309*2f16049cSEmmanuel Vadot
310*2f16049cSEmmanuel Vadot /*
311*2f16049cSEmmanuel Vadot * The datasheet says loop to read the same timer value twice because it
312*2f16049cSEmmanuel Vadot * does not freeze while reading. To that we add our own logic that
313*2f16049cSEmmanuel Vadot * the seconds register must be the same before and after reading the
314*2f16049cSEmmanuel Vadot * timer, ensuring the fractional part is from the same second as tregs.
315*2f16049cSEmmanuel Vadot */
316*2f16049cSEmmanuel Vadot do {
317*2f16049cSEmmanuel Vadot if (sc->use_timer) {
318*2f16049cSEmmanuel Vadot if ((err = read_reg(sc, sc->secaddr, &sec)) != 0)
319*2f16049cSEmmanuel Vadot break;
320*2f16049cSEmmanuel Vadot if ((err = read_reg(sc, sc->tmcaddr, &tmr1)) != 0)
321*2f16049cSEmmanuel Vadot break;
322*2f16049cSEmmanuel Vadot if ((err = read_reg(sc, sc->tmcaddr, &tmr2)) != 0)
323*2f16049cSEmmanuel Vadot break;
324*2f16049cSEmmanuel Vadot if (tmr1 != tmr2)
325*2f16049cSEmmanuel Vadot continue;
326*2f16049cSEmmanuel Vadot }
327*2f16049cSEmmanuel Vadot if ((err = nxprtc_readfrom(sc->dev, sc->secaddr, tregs,
328*2f16049cSEmmanuel Vadot sizeof(*tregs), WAITFLAGS)) != 0)
329*2f16049cSEmmanuel Vadot break;
330*2f16049cSEmmanuel Vadot } while (sc->use_timer && tregs->sec != sec);
331*2f16049cSEmmanuel Vadot
332*2f16049cSEmmanuel Vadot /*
333*2f16049cSEmmanuel Vadot * If the timer value is greater than our hz rate (or is zero),
334*2f16049cSEmmanuel Vadot * something is wrong. Maybe some other OS used the timer differently?
335*2f16049cSEmmanuel Vadot * Just set it to zero. Likewise if we're not using the timer. After
336*2f16049cSEmmanuel Vadot * the offset calc below, the zero turns into 32, the mid-second point,
337*2f16049cSEmmanuel Vadot * which in effect performs 4/5 rounding, which is just the right thing
338*2f16049cSEmmanuel Vadot * to do if we don't have fine-grained time.
339*2f16049cSEmmanuel Vadot */
340*2f16049cSEmmanuel Vadot if (!sc->use_timer || tmr1 > TMR_TICKS_SEC)
341*2f16049cSEmmanuel Vadot tmr1 = 0;
342*2f16049cSEmmanuel Vadot
343*2f16049cSEmmanuel Vadot /*
344*2f16049cSEmmanuel Vadot * Turn the downcounter into an upcounter. The timer starts counting at
345*2f16049cSEmmanuel Vadot * and rolls over at mid-second, so add half a second worth of ticks to
346*2f16049cSEmmanuel Vadot * get its zero point back in sync with the tregs.sec rollover.
347*2f16049cSEmmanuel Vadot */
348*2f16049cSEmmanuel Vadot *tmr = (TMR_TICKS_SEC - tmr1 + TMR_TICKS_HALFSEC) % TMR_TICKS_SEC;
349*2f16049cSEmmanuel Vadot
350*2f16049cSEmmanuel Vadot return (err);
351*2f16049cSEmmanuel Vadot }
352*2f16049cSEmmanuel Vadot
353*2f16049cSEmmanuel Vadot static int
write_timeregs(struct nxprtc_softc * sc,struct time_regs * tregs)354*2f16049cSEmmanuel Vadot write_timeregs(struct nxprtc_softc *sc, struct time_regs *tregs)
355*2f16049cSEmmanuel Vadot {
356*2f16049cSEmmanuel Vadot
357*2f16049cSEmmanuel Vadot return (iicdev_writeto(sc->dev, sc->secaddr, tregs,
358*2f16049cSEmmanuel Vadot sizeof(*tregs), WAITFLAGS));
359*2f16049cSEmmanuel Vadot }
360*2f16049cSEmmanuel Vadot
361*2f16049cSEmmanuel Vadot static int
freqadj_sysctl(SYSCTL_HANDLER_ARGS)362*2f16049cSEmmanuel Vadot freqadj_sysctl(SYSCTL_HANDLER_ARGS)
363*2f16049cSEmmanuel Vadot {
364*2f16049cSEmmanuel Vadot struct nxprtc_softc *sc;
365*2f16049cSEmmanuel Vadot int err, freqppm, newppm;
366*2f16049cSEmmanuel Vadot
367*2f16049cSEmmanuel Vadot sc = arg1;
368*2f16049cSEmmanuel Vadot
369*2f16049cSEmmanuel Vadot /* PPM range [-7,8] maps to reg value range [0,15] */
370*2f16049cSEmmanuel Vadot freqppm = newppm = 8 - sc->freqadj;
371*2f16049cSEmmanuel Vadot
372*2f16049cSEmmanuel Vadot err = sysctl_handle_int(oidp, &newppm, 0, req);
373*2f16049cSEmmanuel Vadot if (err != 0 || req->newptr == NULL)
374*2f16049cSEmmanuel Vadot return (err);
375*2f16049cSEmmanuel Vadot if (freqppm != newppm) {
376*2f16049cSEmmanuel Vadot if (newppm < -7 || newppm > 8)
377*2f16049cSEmmanuel Vadot return (EINVAL);
378*2f16049cSEmmanuel Vadot sc->freqadj = 8 - newppm;
379*2f16049cSEmmanuel Vadot err = write_reg(sc, PCF2127_R_AGING_OFFSET, sc->freqadj);
380*2f16049cSEmmanuel Vadot }
381*2f16049cSEmmanuel Vadot
382*2f16049cSEmmanuel Vadot return (err);
383*2f16049cSEmmanuel Vadot }
384*2f16049cSEmmanuel Vadot
385*2f16049cSEmmanuel Vadot static int
pcf8523_battery_check(struct nxprtc_softc * sc)386*2f16049cSEmmanuel Vadot pcf8523_battery_check(struct nxprtc_softc *sc)
387*2f16049cSEmmanuel Vadot {
388*2f16049cSEmmanuel Vadot struct timespec ts;
389*2f16049cSEmmanuel Vadot int err;
390*2f16049cSEmmanuel Vadot uint8_t cs3;
391*2f16049cSEmmanuel Vadot
392*2f16049cSEmmanuel Vadot /* We check the battery when starting up, and then only once a day. */
393*2f16049cSEmmanuel Vadot getnanouptime(&ts);
394*2f16049cSEmmanuel Vadot if (ts.tv_sec < sc->bat_time)
395*2f16049cSEmmanuel Vadot return (0);
396*2f16049cSEmmanuel Vadot sc->bat_time = ts.tv_sec + (60 * 60 * 24);
397*2f16049cSEmmanuel Vadot
398*2f16049cSEmmanuel Vadot /*
399*2f16049cSEmmanuel Vadot * The 8523, 2127, and 2129 chips have a "power manager" which includes
400*2f16049cSEmmanuel Vadot * an optional battery voltage monitor and several choices for power
401*2f16049cSEmmanuel Vadot * switching modes. The battery monitor uses a lot of current and it
402*2f16049cSEmmanuel Vadot * remains active when running from battery, making it the "drain my
403*2f16049cSEmmanuel Vadot * battery twice as fast" mode. So, we run the chip in direct-switching
404*2f16049cSEmmanuel Vadot * mode with the battery monitor disabled, reducing the current draw
405*2f16049cSEmmanuel Vadot * when running on battery from 1930nA to 880nA. While it's not clear
406*2f16049cSEmmanuel Vadot * from the datasheets, empirical testing shows that both disabling the
407*2f16049cSEmmanuel Vadot * battery monitor and using direct-switch mode are required to get the
408*2f16049cSEmmanuel Vadot * full power savings.
409*2f16049cSEmmanuel Vadot *
410*2f16049cSEmmanuel Vadot * There isn't any need to continuously monitor the battery voltage, so
411*2f16049cSEmmanuel Vadot * this function is used to periodically enable the monitor, check the
412*2f16049cSEmmanuel Vadot * voltage, then return to the low-power monitor-disabled mode.
413*2f16049cSEmmanuel Vadot */
414*2f16049cSEmmanuel Vadot err = write_reg(sc, PCF8523_R_CS3, PCF8523_B_CS3_PM_STD);
415*2f16049cSEmmanuel Vadot if (err != 0) {
416*2f16049cSEmmanuel Vadot device_printf(sc->dev, "cannot write CS3 reg\n");
417*2f16049cSEmmanuel Vadot return (err);
418*2f16049cSEmmanuel Vadot }
419*2f16049cSEmmanuel Vadot pause_sbt("nxpbat", mstosbt(100), 0, 0);
420*2f16049cSEmmanuel Vadot if ((err = read_reg(sc, PCF8523_R_CS3, &cs3)) != 0) {
421*2f16049cSEmmanuel Vadot device_printf(sc->dev, "cannot read CS3 reg\n");
422*2f16049cSEmmanuel Vadot return (err);
423*2f16049cSEmmanuel Vadot }
424*2f16049cSEmmanuel Vadot err = write_reg(sc, PCF8523_R_CS3, PCF8523_B_CS3_PM_DSNBM);
425*2f16049cSEmmanuel Vadot if (err != 0) {
426*2f16049cSEmmanuel Vadot device_printf(sc->dev, "cannot write CS3 reg\n");
427*2f16049cSEmmanuel Vadot return (err);
428*2f16049cSEmmanuel Vadot }
429*2f16049cSEmmanuel Vadot
430*2f16049cSEmmanuel Vadot if (cs3 & PCF8523_B_CS3_BLF)
431*2f16049cSEmmanuel Vadot device_printf(sc->dev, "WARNING: RTC battery is low\n");
432*2f16049cSEmmanuel Vadot
433*2f16049cSEmmanuel Vadot return (0);
434*2f16049cSEmmanuel Vadot }
435*2f16049cSEmmanuel Vadot
436*2f16049cSEmmanuel Vadot static int
pcf8523_start(struct nxprtc_softc * sc)437*2f16049cSEmmanuel Vadot pcf8523_start(struct nxprtc_softc *sc)
438*2f16049cSEmmanuel Vadot {
439*2f16049cSEmmanuel Vadot struct sysctl_ctx_list *ctx;
440*2f16049cSEmmanuel Vadot struct sysctl_oid_list *tree;
441*2f16049cSEmmanuel Vadot struct csr {
442*2f16049cSEmmanuel Vadot uint8_t cs1;
443*2f16049cSEmmanuel Vadot uint8_t cs2;
444*2f16049cSEmmanuel Vadot uint8_t cs3;
445*2f16049cSEmmanuel Vadot uint8_t sec;
446*2f16049cSEmmanuel Vadot } csr;
447*2f16049cSEmmanuel Vadot int err;
448*2f16049cSEmmanuel Vadot uint8_t clkout, freqadj;
449*2f16049cSEmmanuel Vadot
450*2f16049cSEmmanuel Vadot /* Read the control and status registers. */
451*2f16049cSEmmanuel Vadot if ((err = nxprtc_readfrom(sc->dev, PCF85xx_R_CS1, &csr,
452*2f16049cSEmmanuel Vadot sizeof(csr), WAITFLAGS)) != 0){
453*2f16049cSEmmanuel Vadot device_printf(sc->dev, "cannot read RTC control regs\n");
454*2f16049cSEmmanuel Vadot return (err);
455*2f16049cSEmmanuel Vadot }
456*2f16049cSEmmanuel Vadot
457*2f16049cSEmmanuel Vadot /*
458*2f16049cSEmmanuel Vadot * Do a full init if...
459*2f16049cSEmmanuel Vadot * - The chip power manager is in battery-disable mode.
460*2f16049cSEmmanuel Vadot * - The OS (oscillator stopped) bit is set (all power was lost).
461*2f16049cSEmmanuel Vadot * - The clock-increment STOP flag is set (this is just insane).
462*2f16049cSEmmanuel Vadot */
463*2f16049cSEmmanuel Vadot if ((csr.cs3 & PCF8523_M_CS3_PM) == PCF8523_B_CS3_PM_NOBAT ||
464*2f16049cSEmmanuel Vadot (csr.cs1 & PCF85xx_B_CS1_STOP) || (csr.sec & PCF85xx_B_SECOND_OS)) {
465*2f16049cSEmmanuel Vadot device_printf(sc->dev,
466*2f16049cSEmmanuel Vadot "WARNING: RTC battery failed; time is invalid\n");
467*2f16049cSEmmanuel Vadot
468*2f16049cSEmmanuel Vadot /*
469*2f16049cSEmmanuel Vadot * For 212x series...
470*2f16049cSEmmanuel Vadot * - Turn off the POR-Override bit (used for mfg test only),
471*2f16049cSEmmanuel Vadot * by writing zero to cs 1 (all other bits power on as zero).
472*2f16049cSEmmanuel Vadot * - Turn off the timestamp option to save the power used to
473*2f16049cSEmmanuel Vadot * monitor that input pin.
474*2f16049cSEmmanuel Vadot * - Trigger OTP refresh by forcing the OTPR bit to zero then
475*2f16049cSEmmanuel Vadot * back to 1, then wait 100ms for the refresh.
476*2f16049cSEmmanuel Vadot */
477*2f16049cSEmmanuel Vadot if (sc->is212x) {
478*2f16049cSEmmanuel Vadot err = write_reg(sc, PCF85xx_R_CS1, 0);
479*2f16049cSEmmanuel Vadot if (err != 0) {
480*2f16049cSEmmanuel Vadot device_printf(sc->dev,
481*2f16049cSEmmanuel Vadot "cannot write CS1 reg\n");
482*2f16049cSEmmanuel Vadot return (err);
483*2f16049cSEmmanuel Vadot }
484*2f16049cSEmmanuel Vadot
485*2f16049cSEmmanuel Vadot err = write_reg(sc, PCF2127_R_TS_CTL, PCF2127_B_TSOFF);
486*2f16049cSEmmanuel Vadot if (err != 0) {
487*2f16049cSEmmanuel Vadot device_printf(sc->dev,
488*2f16049cSEmmanuel Vadot "cannot write timestamp control\n");
489*2f16049cSEmmanuel Vadot return (err);
490*2f16049cSEmmanuel Vadot }
491*2f16049cSEmmanuel Vadot
492*2f16049cSEmmanuel Vadot clkout = PCF2129_B_CLKOUT_HIGHZ;
493*2f16049cSEmmanuel Vadot err = write_reg(sc, PCF8523_R_TMR_CLKOUT, clkout);
494*2f16049cSEmmanuel Vadot if (err == 0)
495*2f16049cSEmmanuel Vadot err = write_reg(sc, PCF8523_R_TMR_CLKOUT,
496*2f16049cSEmmanuel Vadot clkout | PCF2129_B_CLKOUT_OTPR);
497*2f16049cSEmmanuel Vadot if (err != 0) {
498*2f16049cSEmmanuel Vadot device_printf(sc->dev,
499*2f16049cSEmmanuel Vadot "cannot write CLKOUT control\n");
500*2f16049cSEmmanuel Vadot return (err);
501*2f16049cSEmmanuel Vadot }
502*2f16049cSEmmanuel Vadot pause_sbt("nxpotp", mstosbt(100), mstosbt(10), 0);
503*2f16049cSEmmanuel Vadot } else
504*2f16049cSEmmanuel Vadot clkout = PCF8523_B_CLKOUT_HIGHZ;
505*2f16049cSEmmanuel Vadot
506*2f16049cSEmmanuel Vadot /* All chips: set clock output pin to high-z to save power */
507*2f16049cSEmmanuel Vadot if ((err = write_reg(sc, PCF8523_R_TMR_CLKOUT, clkout)) != 0) {
508*2f16049cSEmmanuel Vadot device_printf(sc->dev, "cannot write CLKOUT control\n");
509*2f16049cSEmmanuel Vadot return (err);
510*2f16049cSEmmanuel Vadot }
511*2f16049cSEmmanuel Vadot }
512*2f16049cSEmmanuel Vadot
513*2f16049cSEmmanuel Vadot /*
514*2f16049cSEmmanuel Vadot * Check the battery voltage and report if it's low. This also has the
515*2f16049cSEmmanuel Vadot * side effect of (re-)initializing the power manager to low-power mode
516*2f16049cSEmmanuel Vadot * when we come up after a power fail.
517*2f16049cSEmmanuel Vadot */
518*2f16049cSEmmanuel Vadot pcf8523_battery_check(sc);
519*2f16049cSEmmanuel Vadot
520*2f16049cSEmmanuel Vadot /*
521*2f16049cSEmmanuel Vadot * Remember whether we're running in AM/PM mode. The chip default is
522*2f16049cSEmmanuel Vadot * 24-hour mode, but if we're co-existing with some other OS that
523*2f16049cSEmmanuel Vadot * prefers AM/PM we can run that way too.
524*2f16049cSEmmanuel Vadot *
525*2f16049cSEmmanuel Vadot * Also, for 212x chips, retrieve the current frequency aging offset,
526*2f16049cSEmmanuel Vadot * and set up the sysctl handler for reading/setting it.
527*2f16049cSEmmanuel Vadot */
528*2f16049cSEmmanuel Vadot if (sc->is212x) {
529*2f16049cSEmmanuel Vadot if (csr.cs1 & PCF2129_B_CS1_12HR)
530*2f16049cSEmmanuel Vadot sc->use_ampm = true;
531*2f16049cSEmmanuel Vadot
532*2f16049cSEmmanuel Vadot err = read_reg(sc, PCF2127_R_AGING_OFFSET, &freqadj);
533*2f16049cSEmmanuel Vadot if (err != 0) {
534*2f16049cSEmmanuel Vadot device_printf(sc->dev,
535*2f16049cSEmmanuel Vadot "cannot read AGINGOFFSET register\n");
536*2f16049cSEmmanuel Vadot return (err);
537*2f16049cSEmmanuel Vadot }
538*2f16049cSEmmanuel Vadot sc->freqadj = (int8_t)freqadj;
539*2f16049cSEmmanuel Vadot
540*2f16049cSEmmanuel Vadot ctx = device_get_sysctl_ctx(sc->dev);
541*2f16049cSEmmanuel Vadot tree = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev));
542*2f16049cSEmmanuel Vadot
543*2f16049cSEmmanuel Vadot SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "freqadj",
544*2f16049cSEmmanuel Vadot CTLFLAG_RWTUN | CTLTYPE_INT | CTLFLAG_MPSAFE, sc, 0,
545*2f16049cSEmmanuel Vadot freqadj_sysctl, "I", "Frequency adjust in PPM, range [-7,+8]");
546*2f16049cSEmmanuel Vadot } else {
547*2f16049cSEmmanuel Vadot if (csr.cs1 & PCF8523_B_CS1_12HR)
548*2f16049cSEmmanuel Vadot sc->use_ampm = true;
549*2f16049cSEmmanuel Vadot }
550*2f16049cSEmmanuel Vadot
551*2f16049cSEmmanuel Vadot return (0);
552*2f16049cSEmmanuel Vadot }
553*2f16049cSEmmanuel Vadot static int
pcf8523_start_timer(struct nxprtc_softc * sc)554*2f16049cSEmmanuel Vadot pcf8523_start_timer(struct nxprtc_softc *sc)
555*2f16049cSEmmanuel Vadot {
556*2f16049cSEmmanuel Vadot int err;
557*2f16049cSEmmanuel Vadot uint8_t clkout, stdclk, stdfreq, tmrfreq;
558*2f16049cSEmmanuel Vadot
559*2f16049cSEmmanuel Vadot /*
560*2f16049cSEmmanuel Vadot * Read the timer control and frequency regs. If they don't have the
561*2f16049cSEmmanuel Vadot * values we normally program into them then the timer count doesn't
562*2f16049cSEmmanuel Vadot * contain a valid fractional second, so zero it to prevent using a bad
563*2f16049cSEmmanuel Vadot * value. Then program the normal timer values so that on the first
564*2f16049cSEmmanuel Vadot * settime call we'll begin to use fractional time.
565*2f16049cSEmmanuel Vadot */
566*2f16049cSEmmanuel Vadot if ((err = read_reg(sc, PCF8523_R_TMR_A_FREQ, &tmrfreq)) != 0)
567*2f16049cSEmmanuel Vadot return (err);
568*2f16049cSEmmanuel Vadot if ((err = read_reg(sc, PCF8523_R_TMR_CLKOUT, &clkout)) != 0)
569*2f16049cSEmmanuel Vadot return (err);
570*2f16049cSEmmanuel Vadot
571*2f16049cSEmmanuel Vadot stdfreq = PCF8523_B_TMR_A_64HZ;
572*2f16049cSEmmanuel Vadot stdclk = PCF8523_B_CLKOUT_TACD | PCF8523_B_CLKOUT_HIGHZ;
573*2f16049cSEmmanuel Vadot
574*2f16049cSEmmanuel Vadot if (clkout != stdclk || (tmrfreq & PCF8523_M_TMR_A_FREQ) != stdfreq) {
575*2f16049cSEmmanuel Vadot if ((err = write_reg(sc, sc->tmcaddr, 0)) != 0)
576*2f16049cSEmmanuel Vadot return (err);
577*2f16049cSEmmanuel Vadot if ((err = write_reg(sc, PCF8523_R_TMR_A_FREQ, stdfreq)) != 0)
578*2f16049cSEmmanuel Vadot return (err);
579*2f16049cSEmmanuel Vadot if ((err = write_reg(sc, PCF8523_R_TMR_CLKOUT, stdclk)) != 0)
580*2f16049cSEmmanuel Vadot return (err);
581*2f16049cSEmmanuel Vadot }
582*2f16049cSEmmanuel Vadot return (0);
583*2f16049cSEmmanuel Vadot }
584*2f16049cSEmmanuel Vadot
585*2f16049cSEmmanuel Vadot static int
pcf2127_start_timer(struct nxprtc_softc * sc)586*2f16049cSEmmanuel Vadot pcf2127_start_timer(struct nxprtc_softc *sc)
587*2f16049cSEmmanuel Vadot {
588*2f16049cSEmmanuel Vadot int err;
589*2f16049cSEmmanuel Vadot uint8_t stdctl, tmrctl;
590*2f16049cSEmmanuel Vadot
591*2f16049cSEmmanuel Vadot /*
592*2f16049cSEmmanuel Vadot * Set up timer if it's not already in the mode we normally run it. See
593*2f16049cSEmmanuel Vadot * the comment in pcf8523_start_timer() for more details.
594*2f16049cSEmmanuel Vadot *
595*2f16049cSEmmanuel Vadot * Note that the PCF2129 datasheet says it has no countdown timer, but
596*2f16049cSEmmanuel Vadot * empirical testing shows that it works just fine for our purposes.
597*2f16049cSEmmanuel Vadot */
598*2f16049cSEmmanuel Vadot if ((err = read_reg(sc, PCF2127_R_TMR_CTL, &tmrctl)) != 0)
599*2f16049cSEmmanuel Vadot return (err);
600*2f16049cSEmmanuel Vadot
601*2f16049cSEmmanuel Vadot stdctl = PCF2127_B_TMR_CD | PCF8523_B_TMR_A_64HZ;
602*2f16049cSEmmanuel Vadot
603*2f16049cSEmmanuel Vadot if ((tmrctl & PCF2127_M_TMR_CTRL) != stdctl) {
604*2f16049cSEmmanuel Vadot if ((err = write_reg(sc, sc->tmcaddr, 0)) != 0)
605*2f16049cSEmmanuel Vadot return (err);
606*2f16049cSEmmanuel Vadot if ((err = write_reg(sc, PCF2127_R_TMR_CTL, stdctl)) != 0)
607*2f16049cSEmmanuel Vadot return (err);
608*2f16049cSEmmanuel Vadot }
609*2f16049cSEmmanuel Vadot return (0);
610*2f16049cSEmmanuel Vadot }
611*2f16049cSEmmanuel Vadot
612*2f16049cSEmmanuel Vadot static int
pcf8563_start(struct nxprtc_softc * sc)613*2f16049cSEmmanuel Vadot pcf8563_start(struct nxprtc_softc *sc)
614*2f16049cSEmmanuel Vadot {
615*2f16049cSEmmanuel Vadot struct csr {
616*2f16049cSEmmanuel Vadot uint8_t cs1;
617*2f16049cSEmmanuel Vadot uint8_t cs2;
618*2f16049cSEmmanuel Vadot uint8_t sec;
619*2f16049cSEmmanuel Vadot } csr;
620*2f16049cSEmmanuel Vadot int err;
621*2f16049cSEmmanuel Vadot
622*2f16049cSEmmanuel Vadot /* Read the control and status registers. */
623*2f16049cSEmmanuel Vadot if ((err = nxprtc_readfrom(sc->dev, PCF85xx_R_CS1, &csr,
624*2f16049cSEmmanuel Vadot sizeof(csr), WAITFLAGS)) != 0){
625*2f16049cSEmmanuel Vadot device_printf(sc->dev, "cannot read RTC control regs\n");
626*2f16049cSEmmanuel Vadot return (err);
627*2f16049cSEmmanuel Vadot }
628*2f16049cSEmmanuel Vadot
629*2f16049cSEmmanuel Vadot /*
630*2f16049cSEmmanuel Vadot * Do a full init if...
631*2f16049cSEmmanuel Vadot * - The OS (oscillator stopped) bit is set (all power was lost). This
632*2f16049cSEmmanuel Vadot * bit is called VL (Voltage Low) in the 8563 datasheet.
633*2f16049cSEmmanuel Vadot * - The clock-increment STOP flag is set (this is just insane).
634*2f16049cSEmmanuel Vadot */
635*2f16049cSEmmanuel Vadot if ((csr.cs1 & PCF85xx_B_CS1_STOP) || (csr.sec & PCF85xx_B_SECOND_OS)) {
636*2f16049cSEmmanuel Vadot device_printf(sc->dev,
637*2f16049cSEmmanuel Vadot "WARNING: RTC battery failed; time is invalid\n");
638*2f16049cSEmmanuel Vadot /*
639*2f16049cSEmmanuel Vadot * - Turn off the POR-Override bit (used for mfg test only), by
640*2f16049cSEmmanuel Vadot * writing zero to cs 1 (all other bits power on as zero).
641*2f16049cSEmmanuel Vadot * - Turn off the clock output pin (to save battery power), by
642*2f16049cSEmmanuel Vadot * writing zero to the clkout control reg.
643*2f16049cSEmmanuel Vadot */
644*2f16049cSEmmanuel Vadot if ((err = write_reg(sc, PCF85xx_R_CS1, 0)) != 0) {
645*2f16049cSEmmanuel Vadot device_printf(sc->dev, "cannot write CS1 reg\n");
646*2f16049cSEmmanuel Vadot return (err);
647*2f16049cSEmmanuel Vadot }
648*2f16049cSEmmanuel Vadot
649*2f16049cSEmmanuel Vadot if ((err = write_reg(sc, PCF8563_R_CLKOUT, 0)) != 0) {
650*2f16049cSEmmanuel Vadot device_printf(sc->dev, "cannot write CS1 reg\n");
651*2f16049cSEmmanuel Vadot return (err);
652*2f16049cSEmmanuel Vadot }
653*2f16049cSEmmanuel Vadot }
654*2f16049cSEmmanuel Vadot
655*2f16049cSEmmanuel Vadot return (0);
656*2f16049cSEmmanuel Vadot }
657*2f16049cSEmmanuel Vadot
658*2f16049cSEmmanuel Vadot static int
pcf8563_start_timer(struct nxprtc_softc * sc)659*2f16049cSEmmanuel Vadot pcf8563_start_timer(struct nxprtc_softc *sc)
660*2f16049cSEmmanuel Vadot {
661*2f16049cSEmmanuel Vadot int err;
662*2f16049cSEmmanuel Vadot uint8_t stdctl, tmrctl;
663*2f16049cSEmmanuel Vadot
664*2f16049cSEmmanuel Vadot /* See comment in pcf8523_start_timer(). */
665*2f16049cSEmmanuel Vadot if ((err = read_reg(sc, PCF8563_R_TMR_CTRL, &tmrctl)) != 0)
666*2f16049cSEmmanuel Vadot return (err);
667*2f16049cSEmmanuel Vadot
668*2f16049cSEmmanuel Vadot stdctl = PCF8563_B_TMR_ENABLE | PCF8563_B_TMR_64HZ;
669*2f16049cSEmmanuel Vadot
670*2f16049cSEmmanuel Vadot if ((tmrctl & PCF8563_M_TMR_CTRL) != stdctl) {
671*2f16049cSEmmanuel Vadot if ((err = write_reg(sc, sc->tmcaddr, 0)) != 0)
672*2f16049cSEmmanuel Vadot return (err);
673*2f16049cSEmmanuel Vadot if ((err = write_reg(sc, PCF8563_R_TMR_CTRL, stdctl)) != 0)
674*2f16049cSEmmanuel Vadot return (err);
675*2f16049cSEmmanuel Vadot }
676*2f16049cSEmmanuel Vadot return (0);
677*2f16049cSEmmanuel Vadot }
678*2f16049cSEmmanuel Vadot
679*2f16049cSEmmanuel Vadot static void
nxprtc_start(void * dev)680*2f16049cSEmmanuel Vadot nxprtc_start(void *dev)
681*2f16049cSEmmanuel Vadot {
682*2f16049cSEmmanuel Vadot struct nxprtc_softc *sc;
683*2f16049cSEmmanuel Vadot int clockflags, resolution;
684*2f16049cSEmmanuel Vadot
685*2f16049cSEmmanuel Vadot sc = device_get_softc((device_t)dev);
686*2f16049cSEmmanuel Vadot config_intrhook_disestablish(&sc->config_hook);
687*2f16049cSEmmanuel Vadot
688*2f16049cSEmmanuel Vadot /* First do chip-specific inits. */
689*2f16049cSEmmanuel Vadot switch (sc->chiptype) {
690*2f16049cSEmmanuel Vadot case TYPE_PCA2129:
691*2f16049cSEmmanuel Vadot case TYPE_PCF2129:
692*2f16049cSEmmanuel Vadot case TYPE_PCF2127:
693*2f16049cSEmmanuel Vadot sc->is212x = true;
694*2f16049cSEmmanuel Vadot if (pcf8523_start(sc) != 0)
695*2f16049cSEmmanuel Vadot return;
696*2f16049cSEmmanuel Vadot if (pcf2127_start_timer(sc) != 0) {
697*2f16049cSEmmanuel Vadot device_printf(sc->dev, "cannot set up timer\n");
698*2f16049cSEmmanuel Vadot return;
699*2f16049cSEmmanuel Vadot }
700*2f16049cSEmmanuel Vadot break;
701*2f16049cSEmmanuel Vadot case TYPE_PCF8523:
702*2f16049cSEmmanuel Vadot if (pcf8523_start(sc) != 0)
703*2f16049cSEmmanuel Vadot return;
704*2f16049cSEmmanuel Vadot if (pcf8523_start_timer(sc) != 0) {
705*2f16049cSEmmanuel Vadot device_printf(sc->dev, "cannot set up timer\n");
706*2f16049cSEmmanuel Vadot return;
707*2f16049cSEmmanuel Vadot }
708*2f16049cSEmmanuel Vadot break;
709*2f16049cSEmmanuel Vadot case TYPE_PCA8565:
710*2f16049cSEmmanuel Vadot case TYPE_PCF8563:
711*2f16049cSEmmanuel Vadot if (pcf8563_start(sc) != 0)
712*2f16049cSEmmanuel Vadot return;
713*2f16049cSEmmanuel Vadot if (pcf8563_start_timer(sc) != 0) {
714*2f16049cSEmmanuel Vadot device_printf(sc->dev, "cannot set up timer\n");
715*2f16049cSEmmanuel Vadot return;
716*2f16049cSEmmanuel Vadot }
717*2f16049cSEmmanuel Vadot break;
718*2f16049cSEmmanuel Vadot default:
719*2f16049cSEmmanuel Vadot device_printf(sc->dev, "missing init code for this chiptype\n");
720*2f16049cSEmmanuel Vadot return;
721*2f16049cSEmmanuel Vadot }
722*2f16049cSEmmanuel Vadot
723*2f16049cSEmmanuel Vadot /*
724*2f16049cSEmmanuel Vadot * Everything looks good if we make it to here; register as an RTC. If
725*2f16049cSEmmanuel Vadot * we're using the timer to count fractional seconds, our resolution is
726*2f16049cSEmmanuel Vadot * 1e6/64, about 15.6ms. Without the timer we still align the RTC clock
727*2f16049cSEmmanuel Vadot * when setting it so our error is an average .5s when reading it.
728*2f16049cSEmmanuel Vadot * Schedule our clock_settime() method to be called at a .495ms offset
729*2f16049cSEmmanuel Vadot * into the second, because the clock hardware resets the divider chain
730*2f16049cSEmmanuel Vadot * to the mid-second point when you set the time and it takes about 5ms
731*2f16049cSEmmanuel Vadot * of i2c bus activity to set the clock.
732*2f16049cSEmmanuel Vadot */
733*2f16049cSEmmanuel Vadot resolution = sc->use_timer ? 1000000 / TMR_TICKS_SEC : 1000000 / 2;
734*2f16049cSEmmanuel Vadot clockflags = CLOCKF_GETTIME_NO_ADJ | CLOCKF_SETTIME_NO_TS;
735*2f16049cSEmmanuel Vadot clock_register_flags(sc->dev, resolution, clockflags);
736*2f16049cSEmmanuel Vadot clock_schedule(sc->dev, 495000000);
737*2f16049cSEmmanuel Vadot }
738*2f16049cSEmmanuel Vadot
739*2f16049cSEmmanuel Vadot static int
nxprtc_gettime(device_t dev,struct timespec * ts)740*2f16049cSEmmanuel Vadot nxprtc_gettime(device_t dev, struct timespec *ts)
741*2f16049cSEmmanuel Vadot {
742*2f16049cSEmmanuel Vadot struct bcd_clocktime bct;
743*2f16049cSEmmanuel Vadot struct time_regs tregs;
744*2f16049cSEmmanuel Vadot struct nxprtc_softc *sc;
745*2f16049cSEmmanuel Vadot int err;
746*2f16049cSEmmanuel Vadot uint8_t cs1, hourmask, tmrcount;
747*2f16049cSEmmanuel Vadot
748*2f16049cSEmmanuel Vadot sc = device_get_softc(dev);
749*2f16049cSEmmanuel Vadot
750*2f16049cSEmmanuel Vadot /*
751*2f16049cSEmmanuel Vadot * Read the time, but before using it, validate that the oscillator-
752*2f16049cSEmmanuel Vadot * stopped/power-fail bit is not set, and that the time-increment STOP
753*2f16049cSEmmanuel Vadot * bit is not set in the control reg. The latter can happen if there
754*2f16049cSEmmanuel Vadot * was an error when setting the time.
755*2f16049cSEmmanuel Vadot */
756*2f16049cSEmmanuel Vadot if ((err = iicbus_request_bus(sc->busdev, sc->dev, IIC_WAIT)) == 0) {
757*2f16049cSEmmanuel Vadot if ((err = read_timeregs(sc, &tregs, &tmrcount)) == 0) {
758*2f16049cSEmmanuel Vadot err = read_reg(sc, PCF85xx_R_CS1, &cs1);
759*2f16049cSEmmanuel Vadot }
760*2f16049cSEmmanuel Vadot iicbus_release_bus(sc->busdev, sc->dev);
761*2f16049cSEmmanuel Vadot }
762*2f16049cSEmmanuel Vadot if (err != 0)
763*2f16049cSEmmanuel Vadot return (err);
764*2f16049cSEmmanuel Vadot
765*2f16049cSEmmanuel Vadot if ((tregs.sec & PCF85xx_B_SECOND_OS) || (cs1 & PCF85xx_B_CS1_STOP)) {
766*2f16049cSEmmanuel Vadot device_printf(dev, "RTC clock not running\n");
767*2f16049cSEmmanuel Vadot return (EINVAL); /* hardware is good, time is not. */
768*2f16049cSEmmanuel Vadot }
769*2f16049cSEmmanuel Vadot
770*2f16049cSEmmanuel Vadot if (sc->use_ampm)
771*2f16049cSEmmanuel Vadot hourmask = PCF85xx_M_12HOUR;
772*2f16049cSEmmanuel Vadot else
773*2f16049cSEmmanuel Vadot hourmask = PCF85xx_M_24HOUR;
774*2f16049cSEmmanuel Vadot
775*2f16049cSEmmanuel Vadot bct.nsec = ((uint64_t)tmrcount * 1000000000) / TMR_TICKS_SEC;
776*2f16049cSEmmanuel Vadot bct.ispm = (tregs.hour & PCF8523_B_HOUR_PM) != 0;
777*2f16049cSEmmanuel Vadot bct.sec = tregs.sec & PCF85xx_M_SECOND;
778*2f16049cSEmmanuel Vadot bct.min = tregs.min & PCF85xx_M_MINUTE;
779*2f16049cSEmmanuel Vadot bct.hour = tregs.hour & hourmask;
780*2f16049cSEmmanuel Vadot bct.day = tregs.day & PCF85xx_M_DAY;
781*2f16049cSEmmanuel Vadot bct.mon = tregs.month & PCF85xx_M_MONTH;
782*2f16049cSEmmanuel Vadot bct.year = tregs.year & PCF85xx_M_YEAR;
783*2f16049cSEmmanuel Vadot
784*2f16049cSEmmanuel Vadot /*
785*2f16049cSEmmanuel Vadot * Old PCF8563 datasheets recommended that the C bit be 1 for 19xx and 0
786*2f16049cSEmmanuel Vadot * for 20xx; newer datasheets don't recommend that. We don't care,
787*2f16049cSEmmanuel Vadot * but we may co-exist with other OSes sharing the hardware. Determine
788*2f16049cSEmmanuel Vadot * existing polarity on a read so that we can preserve it on a write.
789*2f16049cSEmmanuel Vadot */
790*2f16049cSEmmanuel Vadot if (sc->chiptype == TYPE_PCF8563) {
791*2f16049cSEmmanuel Vadot if (tregs.month & PCF8563_B_MONTH_C) {
792*2f16049cSEmmanuel Vadot if (bct.year < 0x70)
793*2f16049cSEmmanuel Vadot sc->flags |= SC_F_CPOL;
794*2f16049cSEmmanuel Vadot } else if (bct.year >= 0x70)
795*2f16049cSEmmanuel Vadot sc->flags |= SC_F_CPOL;
796*2f16049cSEmmanuel Vadot }
797*2f16049cSEmmanuel Vadot
798*2f16049cSEmmanuel Vadot clock_dbgprint_bcd(sc->dev, CLOCK_DBG_READ, &bct);
799*2f16049cSEmmanuel Vadot err = clock_bcd_to_ts(&bct, ts, sc->use_ampm);
800*2f16049cSEmmanuel Vadot ts->tv_sec += utc_offset();
801*2f16049cSEmmanuel Vadot
802*2f16049cSEmmanuel Vadot return (err);
803*2f16049cSEmmanuel Vadot }
804*2f16049cSEmmanuel Vadot
805*2f16049cSEmmanuel Vadot static int
nxprtc_settime(device_t dev,struct timespec * ts)806*2f16049cSEmmanuel Vadot nxprtc_settime(device_t dev, struct timespec *ts)
807*2f16049cSEmmanuel Vadot {
808*2f16049cSEmmanuel Vadot struct bcd_clocktime bct;
809*2f16049cSEmmanuel Vadot struct time_regs tregs;
810*2f16049cSEmmanuel Vadot struct nxprtc_softc *sc;
811*2f16049cSEmmanuel Vadot int err;
812*2f16049cSEmmanuel Vadot uint8_t cflag, cs1;
813*2f16049cSEmmanuel Vadot
814*2f16049cSEmmanuel Vadot sc = device_get_softc(dev);
815*2f16049cSEmmanuel Vadot
816*2f16049cSEmmanuel Vadot /*
817*2f16049cSEmmanuel Vadot * We stop the clock, set the time, then restart the clock. Half a
818*2f16049cSEmmanuel Vadot * second after restarting the clock it ticks over to the next second.
819*2f16049cSEmmanuel Vadot * So to align the RTC, we schedule this function to be called when
820*2f16049cSEmmanuel Vadot * system time is roughly halfway (.495) through the current second.
821*2f16049cSEmmanuel Vadot *
822*2f16049cSEmmanuel Vadot * Reserve use of the i2c bus and stop the RTC clock. Note that if
823*2f16049cSEmmanuel Vadot * anything goes wrong from this point on, we leave the clock stopped,
824*2f16049cSEmmanuel Vadot * because we don't really know what state it's in.
825*2f16049cSEmmanuel Vadot */
826*2f16049cSEmmanuel Vadot if ((err = iicbus_request_bus(sc->busdev, sc->dev, IIC_WAIT)) != 0)
827*2f16049cSEmmanuel Vadot return (err);
828*2f16049cSEmmanuel Vadot if ((err = read_reg(sc, PCF85xx_R_CS1, &cs1)) != 0)
829*2f16049cSEmmanuel Vadot goto errout;
830*2f16049cSEmmanuel Vadot cs1 |= PCF85xx_B_CS1_STOP;
831*2f16049cSEmmanuel Vadot if ((err = write_reg(sc, PCF85xx_R_CS1, cs1)) != 0)
832*2f16049cSEmmanuel Vadot goto errout;
833*2f16049cSEmmanuel Vadot
834*2f16049cSEmmanuel Vadot /* Grab a fresh post-sleep idea of what time it is. */
835*2f16049cSEmmanuel Vadot getnanotime(ts);
836*2f16049cSEmmanuel Vadot ts->tv_sec -= utc_offset();
837*2f16049cSEmmanuel Vadot ts->tv_nsec = 0;
838*2f16049cSEmmanuel Vadot clock_ts_to_bcd(ts, &bct, sc->use_ampm);
839*2f16049cSEmmanuel Vadot clock_dbgprint_bcd(sc->dev, CLOCK_DBG_WRITE, &bct);
840*2f16049cSEmmanuel Vadot
841*2f16049cSEmmanuel Vadot /* On 8563 set the century based on the polarity seen when reading. */
842*2f16049cSEmmanuel Vadot cflag = 0;
843*2f16049cSEmmanuel Vadot if (sc->chiptype == TYPE_PCF8563) {
844*2f16049cSEmmanuel Vadot if ((sc->flags & SC_F_CPOL) != 0) {
845*2f16049cSEmmanuel Vadot if (bct.year >= 0x2000)
846*2f16049cSEmmanuel Vadot cflag = PCF8563_B_MONTH_C;
847*2f16049cSEmmanuel Vadot } else if (bct.year < 0x2000)
848*2f16049cSEmmanuel Vadot cflag = PCF8563_B_MONTH_C;
849*2f16049cSEmmanuel Vadot }
850*2f16049cSEmmanuel Vadot
851*2f16049cSEmmanuel Vadot tregs.sec = bct.sec;
852*2f16049cSEmmanuel Vadot tregs.min = bct.min;
853*2f16049cSEmmanuel Vadot tregs.hour = bct.hour | (bct.ispm ? PCF8523_B_HOUR_PM : 0);
854*2f16049cSEmmanuel Vadot tregs.day = bct.day;
855*2f16049cSEmmanuel Vadot tregs.month = bct.mon;
856*2f16049cSEmmanuel Vadot tregs.year = (bct.year & 0xff) | cflag;
857*2f16049cSEmmanuel Vadot tregs.wday = bct.dow;
858*2f16049cSEmmanuel Vadot
859*2f16049cSEmmanuel Vadot /*
860*2f16049cSEmmanuel Vadot * Set the time, reset the timer count register, then start the clocks.
861*2f16049cSEmmanuel Vadot */
862*2f16049cSEmmanuel Vadot if ((err = write_timeregs(sc, &tregs)) != 0)
863*2f16049cSEmmanuel Vadot goto errout;
864*2f16049cSEmmanuel Vadot
865*2f16049cSEmmanuel Vadot if ((err = write_reg(sc, sc->tmcaddr, TMR_TICKS_SEC)) != 0)
866*2f16049cSEmmanuel Vadot return (err);
867*2f16049cSEmmanuel Vadot
868*2f16049cSEmmanuel Vadot cs1 &= ~PCF85xx_B_CS1_STOP;
869*2f16049cSEmmanuel Vadot err = write_reg(sc, PCF85xx_R_CS1, cs1);
870*2f16049cSEmmanuel Vadot
871*2f16049cSEmmanuel Vadot /*
872*2f16049cSEmmanuel Vadot * Check for battery-low. The actual check is throttled to only occur
873*2f16049cSEmmanuel Vadot * once a day, mostly to avoid spamming the user with frequent warnings.
874*2f16049cSEmmanuel Vadot */
875*2f16049cSEmmanuel Vadot pcf8523_battery_check(sc);
876*2f16049cSEmmanuel Vadot
877*2f16049cSEmmanuel Vadot errout:
878*2f16049cSEmmanuel Vadot
879*2f16049cSEmmanuel Vadot iicbus_release_bus(sc->busdev, sc->dev);
880*2f16049cSEmmanuel Vadot
881*2f16049cSEmmanuel Vadot if (err != 0)
882*2f16049cSEmmanuel Vadot device_printf(dev, "cannot write RTC time\n");
883*2f16049cSEmmanuel Vadot
884*2f16049cSEmmanuel Vadot return (err);
885*2f16049cSEmmanuel Vadot }
886*2f16049cSEmmanuel Vadot
887*2f16049cSEmmanuel Vadot static int
nxprtc_get_chiptype(device_t dev)888*2f16049cSEmmanuel Vadot nxprtc_get_chiptype(device_t dev)
889*2f16049cSEmmanuel Vadot {
890*2f16049cSEmmanuel Vadot #ifdef FDT
891*2f16049cSEmmanuel Vadot
892*2f16049cSEmmanuel Vadot return (ofw_bus_search_compatible(dev, compat_data)->ocd_data);
893*2f16049cSEmmanuel Vadot #else
894*2f16049cSEmmanuel Vadot nxprtc_compat_data *cdata;
895*2f16049cSEmmanuel Vadot const char *htype;
896*2f16049cSEmmanuel Vadot int chiptype;
897*2f16049cSEmmanuel Vadot
898*2f16049cSEmmanuel Vadot /*
899*2f16049cSEmmanuel Vadot * If given a chiptype hint string, loop through the ofw compat data
900*2f16049cSEmmanuel Vadot * comparing the hinted chip type to the compat strings. The table end
901*2f16049cSEmmanuel Vadot * marker ocd_data is TYPE_NONE.
902*2f16049cSEmmanuel Vadot */
903*2f16049cSEmmanuel Vadot if (resource_string_value(device_get_name(dev),
904*2f16049cSEmmanuel Vadot device_get_unit(dev), "compatible", &htype) == 0) {
905*2f16049cSEmmanuel Vadot for (cdata = compat_data; cdata->ocd_str != NULL; ++cdata) {
906*2f16049cSEmmanuel Vadot if (strcmp(htype, cdata->ocd_str) == 0)
907*2f16049cSEmmanuel Vadot break;
908*2f16049cSEmmanuel Vadot }
909*2f16049cSEmmanuel Vadot chiptype = cdata->ocd_data;
910*2f16049cSEmmanuel Vadot } else
911*2f16049cSEmmanuel Vadot chiptype = TYPE_NONE;
912*2f16049cSEmmanuel Vadot
913*2f16049cSEmmanuel Vadot /*
914*2f16049cSEmmanuel Vadot * On non-FDT systems the historical behavior of this driver was to
915*2f16049cSEmmanuel Vadot * assume a PCF8563; keep doing that for compatibility.
916*2f16049cSEmmanuel Vadot */
917*2f16049cSEmmanuel Vadot if (chiptype == TYPE_NONE)
918*2f16049cSEmmanuel Vadot return (TYPE_PCF8563);
919*2f16049cSEmmanuel Vadot else
920*2f16049cSEmmanuel Vadot return (chiptype);
921*2f16049cSEmmanuel Vadot #endif
922*2f16049cSEmmanuel Vadot }
923*2f16049cSEmmanuel Vadot
924*2f16049cSEmmanuel Vadot static int
nxprtc_probe(device_t dev)925*2f16049cSEmmanuel Vadot nxprtc_probe(device_t dev)
926*2f16049cSEmmanuel Vadot {
927*2f16049cSEmmanuel Vadot int chiptype, rv;
928*2f16049cSEmmanuel Vadot
929*2f16049cSEmmanuel Vadot #ifdef FDT
930*2f16049cSEmmanuel Vadot if (!ofw_bus_status_okay(dev))
931*2f16049cSEmmanuel Vadot return (ENXIO);
932*2f16049cSEmmanuel Vadot rv = BUS_PROBE_GENERIC;
933*2f16049cSEmmanuel Vadot #else
934*2f16049cSEmmanuel Vadot rv = BUS_PROBE_NOWILDCARD;
935*2f16049cSEmmanuel Vadot #endif
936*2f16049cSEmmanuel Vadot if ((chiptype = nxprtc_get_chiptype(dev)) == TYPE_NONE)
937*2f16049cSEmmanuel Vadot return (ENXIO);
938*2f16049cSEmmanuel Vadot
939*2f16049cSEmmanuel Vadot device_set_desc(dev, desc_strings[chiptype]);
940*2f16049cSEmmanuel Vadot return (rv);
941*2f16049cSEmmanuel Vadot }
942*2f16049cSEmmanuel Vadot
943*2f16049cSEmmanuel Vadot static int
nxprtc_attach(device_t dev)944*2f16049cSEmmanuel Vadot nxprtc_attach(device_t dev)
945*2f16049cSEmmanuel Vadot {
946*2f16049cSEmmanuel Vadot struct nxprtc_softc *sc;
947*2f16049cSEmmanuel Vadot
948*2f16049cSEmmanuel Vadot sc = device_get_softc(dev);
949*2f16049cSEmmanuel Vadot sc->dev = dev;
950*2f16049cSEmmanuel Vadot sc->busdev = device_get_parent(dev);
951*2f16049cSEmmanuel Vadot
952*2f16049cSEmmanuel Vadot /* We need to know what kind of chip we're driving. */
953*2f16049cSEmmanuel Vadot sc->chiptype = nxprtc_get_chiptype(dev);
954*2f16049cSEmmanuel Vadot
955*2f16049cSEmmanuel Vadot /* The features and some register addresses vary by chip type. */
956*2f16049cSEmmanuel Vadot switch (sc->chiptype) {
957*2f16049cSEmmanuel Vadot case TYPE_PCA2129:
958*2f16049cSEmmanuel Vadot case TYPE_PCF2129:
959*2f16049cSEmmanuel Vadot case TYPE_PCF2127:
960*2f16049cSEmmanuel Vadot case TYPE_PCF8523:
961*2f16049cSEmmanuel Vadot sc->secaddr = PCF8523_R_SECOND;
962*2f16049cSEmmanuel Vadot sc->tmcaddr = PCF8523_R_TMR_A_COUNT;
963*2f16049cSEmmanuel Vadot sc->use_timer = true;
964*2f16049cSEmmanuel Vadot break;
965*2f16049cSEmmanuel Vadot case TYPE_PCA8565:
966*2f16049cSEmmanuel Vadot case TYPE_PCF8563:
967*2f16049cSEmmanuel Vadot sc->secaddr = PCF8563_R_SECOND;
968*2f16049cSEmmanuel Vadot sc->tmcaddr = PCF8563_R_TMR_COUNT;
969*2f16049cSEmmanuel Vadot sc->use_timer = true;
970*2f16049cSEmmanuel Vadot break;
971*2f16049cSEmmanuel Vadot default:
972*2f16049cSEmmanuel Vadot device_printf(dev, "impossible: cannot determine chip type\n");
973*2f16049cSEmmanuel Vadot return (ENXIO);
974*2f16049cSEmmanuel Vadot }
975*2f16049cSEmmanuel Vadot
976*2f16049cSEmmanuel Vadot /*
977*2f16049cSEmmanuel Vadot * We have to wait until interrupts are enabled. Sometimes I2C read
978*2f16049cSEmmanuel Vadot * and write only works when the interrupts are available.
979*2f16049cSEmmanuel Vadot */
980*2f16049cSEmmanuel Vadot sc->config_hook.ich_func = nxprtc_start;
981*2f16049cSEmmanuel Vadot sc->config_hook.ich_arg = dev;
982*2f16049cSEmmanuel Vadot if (config_intrhook_establish(&sc->config_hook) != 0)
983*2f16049cSEmmanuel Vadot return (ENOMEM);
984*2f16049cSEmmanuel Vadot
985*2f16049cSEmmanuel Vadot return (0);
986*2f16049cSEmmanuel Vadot }
987*2f16049cSEmmanuel Vadot
988*2f16049cSEmmanuel Vadot static int
nxprtc_detach(device_t dev)989*2f16049cSEmmanuel Vadot nxprtc_detach(device_t dev)
990*2f16049cSEmmanuel Vadot {
991*2f16049cSEmmanuel Vadot
992*2f16049cSEmmanuel Vadot clock_unregister(dev);
993*2f16049cSEmmanuel Vadot return (0);
994*2f16049cSEmmanuel Vadot }
995*2f16049cSEmmanuel Vadot
996*2f16049cSEmmanuel Vadot static device_method_t nxprtc_methods[] = {
997*2f16049cSEmmanuel Vadot DEVMETHOD(device_probe, nxprtc_probe),
998*2f16049cSEmmanuel Vadot DEVMETHOD(device_attach, nxprtc_attach),
999*2f16049cSEmmanuel Vadot DEVMETHOD(device_detach, nxprtc_detach),
1000*2f16049cSEmmanuel Vadot
1001*2f16049cSEmmanuel Vadot DEVMETHOD(clock_gettime, nxprtc_gettime),
1002*2f16049cSEmmanuel Vadot DEVMETHOD(clock_settime, nxprtc_settime),
1003*2f16049cSEmmanuel Vadot
1004*2f16049cSEmmanuel Vadot DEVMETHOD_END
1005*2f16049cSEmmanuel Vadot };
1006*2f16049cSEmmanuel Vadot
1007*2f16049cSEmmanuel Vadot static driver_t nxprtc_driver = {
1008*2f16049cSEmmanuel Vadot "nxprtc",
1009*2f16049cSEmmanuel Vadot nxprtc_methods,
1010*2f16049cSEmmanuel Vadot sizeof(struct nxprtc_softc),
1011*2f16049cSEmmanuel Vadot };
1012*2f16049cSEmmanuel Vadot
1013*2f16049cSEmmanuel Vadot DRIVER_MODULE(nxprtc, iicbus, nxprtc_driver, NULL, NULL);
1014*2f16049cSEmmanuel Vadot MODULE_VERSION(nxprtc, 1);
1015*2f16049cSEmmanuel Vadot MODULE_DEPEND(nxprtc, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
1016*2f16049cSEmmanuel Vadot IICBUS_FDT_PNP_INFO(compat_data);
1017