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