xref: /freebsd-12.1/sys/dev/bktr/bktr_i2c.c (revision 718cf2cc)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 1998, 2001 Nicolas Souchu
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 AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 /*
33  * I2C support for the bti2c chipset.
34  *
35  * From brooktree848.c <[email protected]>
36  */
37 
38 #include "opt_bktr.h"
39 
40 #include <sys/param.h>
41 #include <sys/kernel.h>
42 #include <sys/malloc.h>
43 #include <sys/systm.h>
44 #include <sys/module.h>
45 #include <sys/bus.h>
46 #include <sys/uio.h>
47 
48 #if __FreeBSD_version < 500014
49 #include <sys/select.h>
50 #else
51 #include <sys/selinfo.h>
52 #endif
53 
54 #if (__FreeBSD_version < 500000)
55 #include <pci/pcivar.h>
56 #include <pci/pcireg.h>
57 #else
58 #include <dev/pci/pcivar.h>
59 #include <dev/pci/pcireg.h>
60 #endif
61 
62 #include <machine/bus.h>
63 #include <sys/bus.h>
64 
65 #include <dev/bktr/ioctl_meteor.h>
66 #include <dev/bktr/ioctl_bt848.h>	/* extensions to ioctl_meteor.h */
67 #include <dev/bktr/bktr_reg.h>
68 #include <dev/bktr/bktr_i2c.h>
69 
70 #include <dev/smbus/smbconf.h>
71 #include <dev/iicbus/iiconf.h>
72 
73 /* Compilation is void if BKTR_USE_FREEBSD_SMBUS is not
74  * defined. This allows bktr owners to have smbus active for there
75  * motherboard and still use their bktr without smbus.
76  */
77 #if defined(BKTR_USE_FREEBSD_SMBUS)
78 
79 #define BTI2C_DEBUG(x)	if (bti2c_debug) (x)
80 static int bti2c_debug = 0;
81 
82 /*
83  * Call this to pass the address of the bktr device to the
84  * bti2c_i2c layer and initialize all the I2C bus architecture
85  */
bt848_i2c_attach(device_t dev)86 int bt848_i2c_attach(device_t dev)
87 {
88 	struct bktr_softc *bktr_sc = (struct bktr_softc *)device_get_softc(dev);
89 	struct bktr_i2c_softc *sc = &bktr_sc->i2c_sc;
90 
91 	sc->smbus = device_add_child(dev, "smbus", -1);
92 	sc->iicbb = device_add_child(dev, "iicbb", -1);
93 
94 	if (!sc->iicbb || !sc->smbus)
95 		return ENXIO;
96 
97 	bus_generic_attach(dev);
98 
99 	return (0);
100 };
101 
bt848_i2c_detach(device_t dev)102 int bt848_i2c_detach(device_t dev)
103 {
104 	struct bktr_softc *bktr_sc = (struct bktr_softc *)device_get_softc(dev);
105 	struct bktr_i2c_softc *sc = &bktr_sc->i2c_sc;
106 	int error = 0;
107 
108 	if ((error = bus_generic_detach(dev)))
109 		goto error;
110 
111 	if (sc->iicbb && (error = device_delete_child(dev, sc->iicbb)))
112 		goto error;
113 
114 	if (sc->smbus && (error = device_delete_child(dev, sc->smbus)))
115 		goto error;
116 
117 error:
118 	return (error);
119 }
120 
bti2c_smb_callback(device_t dev,int index,void * data)121 int bti2c_smb_callback(device_t dev, int index, void *data)
122 {
123 	struct bktr_softc *bktr_sc = (struct bktr_softc *)device_get_softc(dev);
124 	struct bktr_i2c_softc *sc = &bktr_sc->i2c_sc;
125 	int error = 0;
126 
127 	/* test each time if we already have/haven't the iicbus
128 	 * to avoid deadlocks
129 	 */
130 	switch (index) {
131 	case SMB_REQUEST_BUS:
132 		/* XXX test & set */
133 		mtx_lock(&Giant);
134 		if (!sc->bus_owned) {
135 			sc->bus_owned = 1;
136 		} else
137 			error = EWOULDBLOCK;
138 		mtx_unlock(&Giant);
139 		break;
140 
141 	case SMB_RELEASE_BUS:
142 		/* XXX test & set */
143 		mtx_lock(&Giant);
144 		if (sc->bus_owned) {
145 			sc->bus_owned = 0;
146 		} else
147 			error = EINVAL;
148 		mtx_unlock(&Giant);
149 		break;
150 
151 	default:
152 		error = EINVAL;
153 	}
154 
155 	return (error);
156 }
157 
bti2c_iic_callback(device_t dev,int index,caddr_t * data)158 int bti2c_iic_callback(device_t dev, int index, caddr_t *data)
159 {
160 	struct bktr_softc *bktr_sc = (struct bktr_softc *)device_get_softc(dev);
161 	struct bktr_i2c_softc *sc = &bktr_sc->i2c_sc;
162 	int error = 0;
163 
164 	/* test each time if we already have/haven't the smbus
165 	 * to avoid deadlocks
166 	 */
167 	switch (index) {
168 	case IIC_REQUEST_BUS:
169 		/* XXX test & set */
170 		mtx_lock(&Giant);
171 		if (!sc->bus_owned) {
172 			sc->bus_owned = 1;
173 		} else
174 			error = EWOULDBLOCK;
175 		mtx_unlock(&Giant);
176 		break;
177 
178 	case IIC_RELEASE_BUS:
179 		/* XXX test & set */
180 		mtx_lock(&Giant);
181 		if (sc->bus_owned) {
182 			sc->bus_owned = 0;
183 		} else
184 			error = EINVAL;
185 		mtx_unlock(&Giant);
186 		break;
187 
188 	default:
189 		error = EINVAL;
190 	}
191 
192 	return (error);
193 }
194 
bti2c_iic_reset(device_t dev,u_char speed,u_char addr,u_char * oldaddr)195 int bti2c_iic_reset(device_t dev, u_char speed, u_char addr, u_char * oldaddr)
196 {
197 	mtx_lock(&Giant);
198 	if (oldaddr)
199 		*oldaddr = 0;			/* XXX */
200 	mtx_unlock(&Giant);
201 
202 	return (IIC_ENOADDR);
203 }
204 
bti2c_iic_setsda(device_t dev,int val)205 void bti2c_iic_setsda(device_t dev, int val)
206 {
207 	struct bktr_softc *sc  = (struct bktr_softc *)device_get_softc(dev);
208 	int clock;
209 
210 	mtx_lock(&Giant);
211 	clock = INL(sc, BKTR_I2C_DATA_CTL) & 0x2;
212 
213 	if (val)
214 		OUTL(sc, BKTR_I2C_DATA_CTL, clock | 1);
215 	else
216 		OUTL(sc, BKTR_I2C_DATA_CTL, clock);
217 	mtx_unlock(&Giant);
218 
219 	return;
220 }
221 
bti2c_iic_setscl(device_t dev,int val)222 void bti2c_iic_setscl(device_t dev, int val)
223 {
224 	struct bktr_softc *sc  = (struct bktr_softc *)device_get_softc(dev);
225 	int data;
226 
227 	mtx_lock(&Giant);
228 	data = INL(sc, BKTR_I2C_DATA_CTL) & 0x1;
229 
230 	if (val)
231 		OUTL(sc, BKTR_I2C_DATA_CTL, 0x2 | data);
232 	else
233 		OUTL(sc, BKTR_I2C_DATA_CTL, data);
234 	mtx_unlock(&Giant);
235 
236 	return;
237 }
238 
239 int
bti2c_iic_getsda(device_t dev)240 bti2c_iic_getsda(device_t dev)
241 {
242 	struct bktr_softc *sc  = (struct bktr_softc *)device_get_softc(dev);
243 	int retval;
244 
245 	mtx_lock(&Giant);
246 	retval = INL(sc,BKTR_I2C_DATA_CTL) & 0x1;
247 	mtx_unlock(&Giant);
248 	return (retval);
249 }
250 
251 int
bti2c_iic_getscl(device_t dev)252 bti2c_iic_getscl(device_t dev)
253 {
254 	return (0);
255 }
256 
257 static int
bti2c_write(struct bktr_softc * sc,u_long data)258 bti2c_write(struct bktr_softc *sc, u_long data)
259 {
260 	u_long		x;
261 
262 	mtx_lock(&Giant);
263 
264 	/* clear status bits */
265 	OUTL(sc, BKTR_INT_STAT, (BT848_INT_RACK | BT848_INT_I2CDONE));
266 
267 	BTI2C_DEBUG(printf("w%lx", data));
268 
269 	/* write the address and data */
270 	OUTL(sc, BKTR_I2C_DATA_CTL, data);
271 
272 	/* wait for completion */
273 	for ( x = 0x7fffffff; x; --x ) {	/* safety valve */
274 		if ( INL(sc, BKTR_INT_STAT) & BT848_INT_I2CDONE )
275 			break;
276 	}
277 
278 	/* check for ACK */
279 	if ( !x || !( INL(sc, BKTR_INT_STAT) & BT848_INT_RACK) ) {
280 		BTI2C_DEBUG(printf("%c%c", (!x)?'+':'-',
281 			(!( INL(sc, BKTR_INT_STAT) & BT848_INT_RACK))?'+':'-'));
282 		mtx_unlock(&Giant);
283 		return (SMB_ENOACK);
284 	}
285 	BTI2C_DEBUG(printf("+"));
286 	mtx_unlock(&Giant);
287 
288 	/* return OK */
289 	return( 0 );
290 }
291 
292 int
bti2c_smb_writeb(device_t dev,u_char slave,char cmd,char byte)293 bti2c_smb_writeb(device_t dev, u_char slave, char cmd, char byte)
294 {
295 	struct bktr_softc *sc  = (struct bktr_softc *)device_get_softc(dev);
296 	u_long data;
297 
298 	data = ((slave & 0xff) << 24) | ((byte & 0xff) << 16) | (u_char)cmd;
299 
300 	return (bti2c_write(sc, data));
301 }
302 
303 /*
304  * byte1 becomes low byte of word
305  * byte2 becomes high byte of word
306  */
307 int
bti2c_smb_writew(device_t dev,u_char slave,char cmd,short word)308 bti2c_smb_writew(device_t dev, u_char slave, char cmd, short word)
309 {
310 	struct bktr_softc *sc  = (struct bktr_softc *)device_get_softc(dev);
311 	u_long data;
312 	char low, high;
313 
314 	low = (char)(word & 0xff);
315 	high = (char)((word & 0xff00) >> 8);
316 
317 	data = ((slave & 0xff) << 24) | ((low & 0xff) << 16) |
318 		((high & 0xff) << 8) | BT848_DATA_CTL_I2CW3B | (u_char)cmd;
319 
320 	return (bti2c_write(sc, data));
321 }
322 
323 /*
324  * The Bt878 and Bt879 differed on the treatment of i2c commands
325  */
326 int
bti2c_smb_readb(device_t dev,u_char slave,char cmd,char * byte)327 bti2c_smb_readb(device_t dev, u_char slave, char cmd, char *byte)
328 {
329 	struct bktr_softc *sc  = (struct bktr_softc *)device_get_softc(dev);
330 	u_long		x;
331 
332 	mtx_lock(&Giant);
333 	/* clear status bits */
334 	OUTL(sc,BKTR_INT_STAT, (BT848_INT_RACK | BT848_INT_I2CDONE));
335 
336 	OUTL(sc,BKTR_I2C_DATA_CTL, ((slave & 0xff) << 24) | (u_char)cmd);
337 
338 	BTI2C_DEBUG(printf("r%lx/", (u_long)(((slave & 0xff) << 24) | (u_char)cmd)));
339 
340 	/* wait for completion */
341 	for ( x = 0x7fffffff; x; --x ) {	/* safety valve */
342 		if ( INL(sc,BKTR_INT_STAT) & BT848_INT_I2CDONE )
343 			break;
344 	}
345 
346 	/* check for ACK */
347 	if ( !x || !(INL(sc,BKTR_INT_STAT) & BT848_INT_RACK) ) {
348 		BTI2C_DEBUG(printf("r%c%c", (!x)?'+':'-',
349 			(!( INL(sc,BKTR_INT_STAT) & BT848_INT_RACK))?'+':'-'));
350 		mtx_unlock(&Giant);
351 		return (SMB_ENOACK);
352 	}
353 
354 	*byte = (char)((INL(sc,BKTR_I2C_DATA_CTL) >> 8) & 0xff);
355 	BTI2C_DEBUG(printf("r%x+", *byte));
356 	mtx_unlock(&Giant);
357 
358 	return (0);
359 }
360 
361 DRIVER_MODULE(iicbb, bktr, iicbb_driver, iicbb_devclass, 0, 0);
362 DRIVER_MODULE(smbus, bktr, smbus_driver, smbus_devclass, 0, 0);
363 
364 #endif /* defined(BKTR_USE_FREEBSD_SMBUS) */
365