xref: /netbsd-src/sys/dev/ic/pca9564.c (revision c7fb772b85b2b5d4cfb282f868f454b4701534fd)
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