1 /* $NetBSD: pca9564.c,v 1.5 2021/08/07 16:19:12 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 2010 NONAKA Kimihiro <nonaka@netbsd.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: pca9564.c,v 1.5 2021/08/07 16:19:12 thorpej Exp $");
30
31 #include <sys/param.h>
32 #include <sys/device.h>
33 #include <sys/mutex.h>
34 #include <sys/bus.h>
35
36 #include <dev/i2c/i2cvar.h>
37
38 #include <dev/ic/pca9564reg.h>
39 #include <dev/ic/pca9564var.h>
40
41 #if defined(PCA9564_DEBUG)
42 int pca9564debug = 0;
43 #define DPRINTF(s) if (pca9564debug) printf s
44 #else
45 #define DPRINTF(s)
46 #endif
47
48 static int pca9564_acquire_bus(void *, int);
49 static void pca9564_release_bus(void *, int);
50
51 static int pca9564_send_start(void *, int);
52 static int pca9564_send_stop(void *, int);
53 static int pca9564_initiate_xfer(void *, uint16_t, int);
54 static int pca9564_read_byte(void *, uint8_t *, int);
55 static int pca9564_write_byte(void *, uint8_t, int);
56
57 static int pca9564_ack(void *, bool, int);
58
59 #define CSR_READ(sc, r) (*sc->sc_ios.read_byte)(sc->sc_dev, r)
60 #define CSR_WRITE(sc, r, v) (*sc->sc_ios.write_byte)(sc->sc_dev, r, v)
61
62 void
pca9564_attach(struct pca9564_softc * sc)63 pca9564_attach(struct pca9564_softc *sc)
64 {
65 struct i2cbus_attach_args iba;
66
67 aprint_naive("\n");
68 aprint_normal(": PCA9564 I2C Controller\n");
69
70 iic_tag_init(&sc->sc_i2c);
71 sc->sc_i2c.ic_cookie = sc;
72 sc->sc_i2c.ic_acquire_bus = pca9564_acquire_bus;
73 sc->sc_i2c.ic_release_bus = pca9564_release_bus;
74 sc->sc_i2c.ic_send_start = pca9564_send_start;
75 sc->sc_i2c.ic_send_stop = pca9564_send_stop;
76 sc->sc_i2c.ic_initiate_xfer = pca9564_initiate_xfer;
77 sc->sc_i2c.ic_read_byte = pca9564_read_byte;
78 sc->sc_i2c.ic_write_byte = pca9564_write_byte;
79
80 /* set serial clock rate */
81 switch (sc->sc_i2c_clock) {
82 case 330000: /* 330kHz */
83 sc->sc_i2c_clock = I2CCON_CR_330KHZ;
84 break;
85 case 288000: /* 288kHz */
86 sc->sc_i2c_clock = I2CCON_CR_288KHZ;
87 break;
88 case 217000: /* 217kHz */
89 sc->sc_i2c_clock = I2CCON_CR_217KHZ;
90 break;
91 case 146000: /* 146kHz */
92 sc->sc_i2c_clock = I2CCON_CR_146KHZ;
93 break;
94 case 88000: /* 88kHz */
95 sc->sc_i2c_clock = I2CCON_CR_88KHZ;
96 break;
97 case 0: /* default */
98 case 59000: /* 59kHz */
99 sc->sc_i2c_clock = I2CCON_CR_59KHZ;
100 break;
101 case 44000: /* 44kHz */
102 sc->sc_i2c_clock = I2CCON_CR_44KHZ;
103 break;
104 case 36000: /* 36kHz */
105 sc->sc_i2c_clock = I2CCON_CR_36KHZ;
106 break;
107 default:
108 aprint_error_dev(sc->sc_dev, "unknown i2c clock %dHz\n",
109 sc->sc_i2c_clock);
110 sc->sc_i2c_clock = I2CCON_CR_59KHZ;
111 break;
112 }
113
114 memset(&iba, 0, sizeof(iba));
115 iba.iba_tag = &sc->sc_i2c;
116 config_found(sc->sc_dev, &iba, iicbus_print, CFARGS_NONE);
117 }
118
119 static int
pca9564_acquire_bus(void * cookie,int flags)120 pca9564_acquire_bus(void *cookie, int flags)
121 {
122 struct pca9564_softc *sc = cookie;
123 uint8_t control;
124
125 /* Enable SIO and set clock */
126 control = CSR_READ(sc, PCA9564_I2CCON);
127 control |= I2CCON_ENSIO;
128 control &= ~(I2CCON_STA|I2CCON_STO|I2CCON_SI|I2CCON_AA);
129 control &= ~I2CCON_CR_MASK;
130 control |= sc->sc_i2c_clock;
131 CSR_WRITE(sc, PCA9564_I2CCON, control);
132 delay(500);
133
134 return 0;
135 }
136
137 static void
pca9564_release_bus(void * cookie,int flags)138 pca9564_release_bus(void *cookie, int flags)
139 {
140 struct pca9564_softc *sc = cookie;
141 uint8_t control;
142
143 /* Disable SIO */
144 control = CSR_READ(sc, PCA9564_I2CCON);
145 control &= ~I2CCON_ENSIO;
146 CSR_WRITE(sc, PCA9564_I2CCON, control);
147 }
148
149 #define PCA9564_TIMEOUT 100 /* protocol timeout, in uSecs */
150
151 static int
pca9564_wait(struct pca9564_softc * sc,int flags)152 pca9564_wait(struct pca9564_softc *sc, int flags)
153 {
154 int timeout;
155
156 DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
157 for (timeout = PCA9564_TIMEOUT; timeout > 0; timeout--) {
158 if (CSR_READ(sc, PCA9564_I2CCON) & I2CCON_SI)
159 break;
160 delay(1);
161 }
162 DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
163 if (timeout == 0) {
164 aprint_error_dev(sc->sc_dev, "timeout\n");
165 return ETIMEDOUT;
166 }
167 return 0;
168 }
169
170 static int
pca9564_send_start(void * cookie,int flags)171 pca9564_send_start(void *cookie, int flags)
172 {
173 struct pca9564_softc *sc = cookie;
174 uint8_t control;
175
176 DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
177 control = CSR_READ(sc, PCA9564_I2CCON);
178 control |= I2CCON_STA;
179 control &= ~(I2CCON_STO|I2CCON_SI);
180 CSR_WRITE(sc, PCA9564_I2CCON, control);
181 DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
182
183 return pca9564_wait(sc, flags);
184 }
185
186 static int
pca9564_send_stop(void * cookie,int flags)187 pca9564_send_stop(void *cookie, int flags)
188 {
189 struct pca9564_softc *sc = cookie;
190 uint8_t control;
191
192 DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
193 control = CSR_READ(sc, PCA9564_I2CCON);
194 control |= I2CCON_STO;
195 control &= ~(I2CCON_STA|I2CCON_SI);
196 CSR_WRITE(sc, PCA9564_I2CCON, control);
197 DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
198
199 return 0;
200 }
201
202 static int
pca9564_initiate_xfer(void * cookie,uint16_t addr,int flags)203 pca9564_initiate_xfer(void *cookie, uint16_t addr, int flags)
204 {
205 struct pca9564_softc *sc = cookie;
206 int error, rd_req = (flags & I2C_F_READ) != 0;
207 uint8_t data, control;
208
209 error = pca9564_send_start(sc, flags);
210 if (error) {
211 aprint_error_dev(sc->sc_dev, "failed to send start %s xfer\n",
212 rd_req ? "read" : "write");
213 return error;
214 }
215
216 DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
217 control = CSR_READ(sc, PCA9564_I2CCON);
218
219 data = (addr << 1) | (rd_req ? 1 : 0);
220 CSR_WRITE(sc, PCA9564_I2CDAT, data);
221
222 control &= ~(I2CCON_STO|I2CCON_STA|I2CCON_SI);
223 CSR_WRITE(sc, PCA9564_I2CCON, control);
224 DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
225
226 error = pca9564_wait(sc, flags);
227 if (error)
228 aprint_error_dev(sc->sc_dev, "failed to initiate %s xfer\n",
229 rd_req ? "read" : "write");
230 return error;
231 }
232
233 static int
pca9564_read_byte(void * cookie,uint8_t * bytep,int flags)234 pca9564_read_byte(void *cookie, uint8_t *bytep, int flags)
235 {
236 struct pca9564_softc *sc = cookie;
237 int send_stop = (flags & I2C_F_STOP) != 0;
238 int error;
239
240 error = pca9564_ack(sc, !send_stop, flags);
241 if (error) {
242 aprint_error_dev(sc->sc_dev, "failed to ack\n");
243 return error;
244 }
245
246 DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
247 *bytep = CSR_READ(sc, PCA9564_I2CDAT);
248 DPRINTF(("%s: status=%#x, byte=%#x\n", __func__,
249 CSR_READ(sc, PCA9564_I2CSTA), *bytep));
250
251 if (send_stop)
252 pca9564_send_stop(sc, flags);
253
254 return 0;
255 }
256
257 static int
pca9564_write_byte(void * cookie,uint8_t byte,int flags)258 pca9564_write_byte(void *cookie, uint8_t byte, int flags)
259 {
260 struct pca9564_softc *sc = cookie;
261 int send_stop = (flags & I2C_F_STOP) != 0;
262 int error;
263 uint8_t control;
264
265 DPRINTF(("%s: status=%#x, byte=%#x\n", __func__,
266 CSR_READ(sc, PCA9564_I2CSTA), byte));
267 control = CSR_READ(sc, PCA9564_I2CCON);
268
269 CSR_WRITE(sc, PCA9564_I2CDAT, byte);
270
271 control &= ~(I2CCON_STO|I2CCON_STA|I2CCON_SI);
272 CSR_WRITE(sc, PCA9564_I2CCON, control);
273 DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
274
275 error = pca9564_wait(sc, flags);
276 if (error)
277 aprint_error_dev(sc->sc_dev, "write byte failed\n");
278
279 if (send_stop)
280 pca9564_send_stop(sc, flags);
281
282 return error;
283 }
284
285 static int
pca9564_ack(void * cookie,bool ack,int flags)286 pca9564_ack(void *cookie, bool ack, int flags)
287 {
288 struct pca9564_softc *sc = cookie;
289 uint8_t control;
290
291 DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
292 control = CSR_READ(sc, PCA9564_I2CCON);
293 control &= ~(I2CCON_STO|I2CCON_STA|I2CCON_SI|I2CCON_AA);
294 if (ack)
295 control |= I2CCON_AA;
296 CSR_WRITE(sc, PCA9564_I2CCON, control);
297 DPRINTF(("%s: status=%#x\n", __func__, CSR_READ(sc, PCA9564_I2CSTA)));
298
299 return pca9564_wait(sc, flags);
300 }
301