xref: /freebsd/sys/compat/linuxkpi/common/src/linux_i2cbb.c (revision 1961a14a47437595fb7fcdc20e327440e3eb51e2)
1*1961a14aSEmmanuel Vadot /*-
2*1961a14aSEmmanuel Vadot  * Copyright (c) 2021 Beckhoff Automation GmbH & Co. KG
3*1961a14aSEmmanuel Vadot  *
4*1961a14aSEmmanuel Vadot  * Redistribution and use in source and binary forms, with or without
5*1961a14aSEmmanuel Vadot  * modification, are permitted provided that the following conditions
6*1961a14aSEmmanuel Vadot  * are met:
7*1961a14aSEmmanuel Vadot  * 1. Redistributions of source code must retain the above copyright
8*1961a14aSEmmanuel Vadot  *    notice, this list of conditions and the following disclaimer.
9*1961a14aSEmmanuel Vadot  * 2. Redistributions in binary form must reproduce the above copyright
10*1961a14aSEmmanuel Vadot  *    notice, this list of conditions and the following disclaimer in the
11*1961a14aSEmmanuel Vadot  *    documentation and/or other materials provided with the distribution.
12*1961a14aSEmmanuel Vadot  *
13*1961a14aSEmmanuel Vadot  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14*1961a14aSEmmanuel Vadot  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15*1961a14aSEmmanuel Vadot  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16*1961a14aSEmmanuel Vadot  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17*1961a14aSEmmanuel Vadot  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18*1961a14aSEmmanuel Vadot  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19*1961a14aSEmmanuel Vadot  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20*1961a14aSEmmanuel Vadot  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21*1961a14aSEmmanuel Vadot  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22*1961a14aSEmmanuel Vadot  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23*1961a14aSEmmanuel Vadot  * SUCH DAMAGE.
24*1961a14aSEmmanuel Vadot  *
25*1961a14aSEmmanuel Vadot  */
26*1961a14aSEmmanuel Vadot 
27*1961a14aSEmmanuel Vadot #include <sys/cdefs.h>
28*1961a14aSEmmanuel Vadot __FBSDID("$FreeBSD$");
29*1961a14aSEmmanuel Vadot 
30*1961a14aSEmmanuel Vadot #include <sys/param.h>
31*1961a14aSEmmanuel Vadot #include <sys/systm.h>
32*1961a14aSEmmanuel Vadot #include <sys/bus.h>
33*1961a14aSEmmanuel Vadot #include <sys/malloc.h>
34*1961a14aSEmmanuel Vadot 
35*1961a14aSEmmanuel Vadot #include <dev/iicbus/iicbus.h>
36*1961a14aSEmmanuel Vadot #include <dev/iicbus/iiconf.h>
37*1961a14aSEmmanuel Vadot 
38*1961a14aSEmmanuel Vadot #include <linux/device.h>
39*1961a14aSEmmanuel Vadot #include <linux/i2c.h>
40*1961a14aSEmmanuel Vadot #include <linux/i2c-algo-bit.h>
41*1961a14aSEmmanuel Vadot #include <linux/list.h>
42*1961a14aSEmmanuel Vadot #include <linux/pci.h>
43*1961a14aSEmmanuel Vadot 
44*1961a14aSEmmanuel Vadot #include "iicbb_if.h"
45*1961a14aSEmmanuel Vadot #include "lkpi_iic_if.h"
46*1961a14aSEmmanuel Vadot 
47*1961a14aSEmmanuel Vadot static void lkpi_iicbb_setsda(device_t dev, int val);
48*1961a14aSEmmanuel Vadot static void lkpi_iicbb_setscl(device_t dev, int val);
49*1961a14aSEmmanuel Vadot static int lkpi_iicbb_getscl(device_t dev);
50*1961a14aSEmmanuel Vadot static int lkpi_iicbb_getsda(device_t dev);
51*1961a14aSEmmanuel Vadot static int lkpi_iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr);
52*1961a14aSEmmanuel Vadot 
53*1961a14aSEmmanuel Vadot struct lkpi_iicbb_softc {
54*1961a14aSEmmanuel Vadot 	device_t		iicbb;
55*1961a14aSEmmanuel Vadot 	struct i2c_adapter	*adapter;
56*1961a14aSEmmanuel Vadot };
57*1961a14aSEmmanuel Vadot 
58*1961a14aSEmmanuel Vadot static int
59*1961a14aSEmmanuel Vadot lkpi_iicbb_probe(device_t dev)
60*1961a14aSEmmanuel Vadot {
61*1961a14aSEmmanuel Vadot 
62*1961a14aSEmmanuel Vadot 	device_set_desc(dev, "LinuxKPI I2CBB");
63*1961a14aSEmmanuel Vadot 	return (BUS_PROBE_NOWILDCARD);
64*1961a14aSEmmanuel Vadot }
65*1961a14aSEmmanuel Vadot 
66*1961a14aSEmmanuel Vadot static int
67*1961a14aSEmmanuel Vadot lkpi_iicbb_attach(device_t dev)
68*1961a14aSEmmanuel Vadot {
69*1961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
70*1961a14aSEmmanuel Vadot 
71*1961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
72*1961a14aSEmmanuel Vadot 	sc->iicbb = device_add_child(dev, "iicbb", -1);
73*1961a14aSEmmanuel Vadot 	if (sc->iicbb == NULL) {
74*1961a14aSEmmanuel Vadot 		device_printf(dev, "Couldn't add iicbb child, aborting\n");
75*1961a14aSEmmanuel Vadot 		return (ENXIO);
76*1961a14aSEmmanuel Vadot 	}
77*1961a14aSEmmanuel Vadot 	bus_generic_attach(dev);
78*1961a14aSEmmanuel Vadot 	return (0);
79*1961a14aSEmmanuel Vadot }
80*1961a14aSEmmanuel Vadot 
81*1961a14aSEmmanuel Vadot static int
82*1961a14aSEmmanuel Vadot lkpi_iicbb_detach(device_t dev)
83*1961a14aSEmmanuel Vadot {
84*1961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
85*1961a14aSEmmanuel Vadot 
86*1961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
87*1961a14aSEmmanuel Vadot 	if (sc->iicbb)
88*1961a14aSEmmanuel Vadot 		device_delete_child(dev, sc->iicbb);
89*1961a14aSEmmanuel Vadot 	return (0);
90*1961a14aSEmmanuel Vadot }
91*1961a14aSEmmanuel Vadot 
92*1961a14aSEmmanuel Vadot static int
93*1961a14aSEmmanuel Vadot lkpi_iicbb_add_adapter(device_t dev, struct i2c_adapter *adapter)
94*1961a14aSEmmanuel Vadot {
95*1961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
96*1961a14aSEmmanuel Vadot 
97*1961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
98*1961a14aSEmmanuel Vadot 	sc->adapter = adapter;
99*1961a14aSEmmanuel Vadot 
100*1961a14aSEmmanuel Vadot 	return (0);
101*1961a14aSEmmanuel Vadot }
102*1961a14aSEmmanuel Vadot 
103*1961a14aSEmmanuel Vadot static device_method_t lkpi_iicbb_methods[] = {
104*1961a14aSEmmanuel Vadot 	/* device interface */
105*1961a14aSEmmanuel Vadot 	DEVMETHOD(device_probe,		lkpi_iicbb_probe),
106*1961a14aSEmmanuel Vadot 	DEVMETHOD(device_attach,	lkpi_iicbb_attach),
107*1961a14aSEmmanuel Vadot 	DEVMETHOD(device_detach,	lkpi_iicbb_detach),
108*1961a14aSEmmanuel Vadot 	DEVMETHOD(device_suspend,	bus_generic_suspend),
109*1961a14aSEmmanuel Vadot 	DEVMETHOD(device_resume,	bus_generic_resume),
110*1961a14aSEmmanuel Vadot 
111*1961a14aSEmmanuel Vadot 	/* iicbb interface */
112*1961a14aSEmmanuel Vadot 	DEVMETHOD(iicbb_setsda,		lkpi_iicbb_setsda),
113*1961a14aSEmmanuel Vadot 	DEVMETHOD(iicbb_setscl,		lkpi_iicbb_setscl),
114*1961a14aSEmmanuel Vadot 	DEVMETHOD(iicbb_getsda,		lkpi_iicbb_getsda),
115*1961a14aSEmmanuel Vadot 	DEVMETHOD(iicbb_getscl,		lkpi_iicbb_getscl),
116*1961a14aSEmmanuel Vadot 	DEVMETHOD(iicbb_reset,		lkpi_iicbb_reset),
117*1961a14aSEmmanuel Vadot 
118*1961a14aSEmmanuel Vadot 	/* lkpi_iicbb interface */
119*1961a14aSEmmanuel Vadot 	DEVMETHOD(lkpi_iic_add_adapter,	lkpi_iicbb_add_adapter),
120*1961a14aSEmmanuel Vadot 
121*1961a14aSEmmanuel Vadot 	DEVMETHOD_END
122*1961a14aSEmmanuel Vadot };
123*1961a14aSEmmanuel Vadot 
124*1961a14aSEmmanuel Vadot static devclass_t lkpi_iicbb_devclass;
125*1961a14aSEmmanuel Vadot 
126*1961a14aSEmmanuel Vadot driver_t lkpi_iicbb_driver = {
127*1961a14aSEmmanuel Vadot 	"lkpi_iicbb",
128*1961a14aSEmmanuel Vadot 	lkpi_iicbb_methods,
129*1961a14aSEmmanuel Vadot 	sizeof(struct lkpi_iicbb_softc),
130*1961a14aSEmmanuel Vadot };
131*1961a14aSEmmanuel Vadot 
132*1961a14aSEmmanuel Vadot DRIVER_MODULE(lkpi_iicbb, lkpi_iic, lkpi_iicbb_driver, lkpi_iicbb_devclass, 0, 0);
133*1961a14aSEmmanuel Vadot DRIVER_MODULE(iicbb, lkpi_iicbb, iicbb_driver, iicbb_devclass, 0, 0);
134*1961a14aSEmmanuel Vadot MODULE_DEPEND(lkpi_iicbb, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER);
135*1961a14aSEmmanuel Vadot 
136*1961a14aSEmmanuel Vadot static void
137*1961a14aSEmmanuel Vadot lkpi_iicbb_setsda(device_t dev, int val)
138*1961a14aSEmmanuel Vadot {
139*1961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
140*1961a14aSEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
141*1961a14aSEmmanuel Vadot 
142*1961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
143*1961a14aSEmmanuel Vadot 	algo_data = (struct i2c_algo_bit_data *)sc->adapter->algo_data;
144*1961a14aSEmmanuel Vadot 	algo_data->setsda(algo_data->data, val);
145*1961a14aSEmmanuel Vadot 	cpu_spinwait();
146*1961a14aSEmmanuel Vadot 	DELAY(algo_data->udelay);
147*1961a14aSEmmanuel Vadot }
148*1961a14aSEmmanuel Vadot 
149*1961a14aSEmmanuel Vadot static void
150*1961a14aSEmmanuel Vadot lkpi_iicbb_setscl(device_t dev, int val)
151*1961a14aSEmmanuel Vadot {
152*1961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
153*1961a14aSEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
154*1961a14aSEmmanuel Vadot 
155*1961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
156*1961a14aSEmmanuel Vadot 
157*1961a14aSEmmanuel Vadot 	algo_data = (struct i2c_algo_bit_data *)sc->adapter->algo_data;
158*1961a14aSEmmanuel Vadot 	algo_data->setscl(algo_data->data, val);
159*1961a14aSEmmanuel Vadot 	cpu_spinwait();
160*1961a14aSEmmanuel Vadot 	DELAY(algo_data->udelay);
161*1961a14aSEmmanuel Vadot }
162*1961a14aSEmmanuel Vadot 
163*1961a14aSEmmanuel Vadot static int
164*1961a14aSEmmanuel Vadot lkpi_iicbb_getscl(device_t dev)
165*1961a14aSEmmanuel Vadot {
166*1961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
167*1961a14aSEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
168*1961a14aSEmmanuel Vadot 	unsigned long orig_ticks;
169*1961a14aSEmmanuel Vadot 	int ret = 0;
170*1961a14aSEmmanuel Vadot 
171*1961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
172*1961a14aSEmmanuel Vadot 
173*1961a14aSEmmanuel Vadot 	algo_data = (struct i2c_algo_bit_data *)sc->adapter->algo_data;
174*1961a14aSEmmanuel Vadot 
175*1961a14aSEmmanuel Vadot 	orig_ticks = ticks;
176*1961a14aSEmmanuel Vadot 	while (!ret) {
177*1961a14aSEmmanuel Vadot 		ret = algo_data->getscl(algo_data->data);
178*1961a14aSEmmanuel Vadot 
179*1961a14aSEmmanuel Vadot 		if (ret)
180*1961a14aSEmmanuel Vadot 			break;
181*1961a14aSEmmanuel Vadot 
182*1961a14aSEmmanuel Vadot 		if (ticks > orig_ticks + algo_data->timeout)
183*1961a14aSEmmanuel Vadot 			return (ETIMEDOUT);
184*1961a14aSEmmanuel Vadot 
185*1961a14aSEmmanuel Vadot 		cpu_spinwait();
186*1961a14aSEmmanuel Vadot 		DELAY(algo_data->udelay);
187*1961a14aSEmmanuel Vadot 	}
188*1961a14aSEmmanuel Vadot 	DELAY(algo_data->udelay);
189*1961a14aSEmmanuel Vadot 	return (ret);
190*1961a14aSEmmanuel Vadot }
191*1961a14aSEmmanuel Vadot 
192*1961a14aSEmmanuel Vadot static int
193*1961a14aSEmmanuel Vadot lkpi_iicbb_getsda(device_t dev)
194*1961a14aSEmmanuel Vadot {
195*1961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
196*1961a14aSEmmanuel Vadot 	struct i2c_algo_bit_data *algo_data;
197*1961a14aSEmmanuel Vadot 	int ret = 0;
198*1961a14aSEmmanuel Vadot 
199*1961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
200*1961a14aSEmmanuel Vadot 	algo_data = (struct i2c_algo_bit_data *)sc->adapter->algo_data;
201*1961a14aSEmmanuel Vadot 
202*1961a14aSEmmanuel Vadot 	cpu_spinwait();
203*1961a14aSEmmanuel Vadot 	DELAY(algo_data->udelay);
204*1961a14aSEmmanuel Vadot 	ret = algo_data->getsda(algo_data->data);
205*1961a14aSEmmanuel Vadot 	cpu_spinwait();
206*1961a14aSEmmanuel Vadot 	DELAY(algo_data->udelay);
207*1961a14aSEmmanuel Vadot 	return (ret);
208*1961a14aSEmmanuel Vadot }
209*1961a14aSEmmanuel Vadot 
210*1961a14aSEmmanuel Vadot static int
211*1961a14aSEmmanuel Vadot lkpi_iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
212*1961a14aSEmmanuel Vadot {
213*1961a14aSEmmanuel Vadot 	struct lkpi_iicbb_softc *sc;
214*1961a14aSEmmanuel Vadot 
215*1961a14aSEmmanuel Vadot 	sc = device_get_softc(dev);
216*1961a14aSEmmanuel Vadot 
217*1961a14aSEmmanuel Vadot 	return (0);
218*1961a14aSEmmanuel Vadot }
219*1961a14aSEmmanuel Vadot 
220*1961a14aSEmmanuel Vadot int
221*1961a14aSEmmanuel Vadot lkpi_i2cbb_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int nmsgs)
222*1961a14aSEmmanuel Vadot {
223*1961a14aSEmmanuel Vadot 
224*1961a14aSEmmanuel Vadot 	/* TODO: convert from i2c_msg to iic_msg and call IICBUS_TRANFER */
225*1961a14aSEmmanuel Vadot 	return (0);
226*1961a14aSEmmanuel Vadot }
227*1961a14aSEmmanuel Vadot 
228*1961a14aSEmmanuel Vadot int
229*1961a14aSEmmanuel Vadot lkpi_i2c_bit_add_bus(struct i2c_adapter *adapter)
230*1961a14aSEmmanuel Vadot {
231*1961a14aSEmmanuel Vadot 	device_t lkpi_iicbb;
232*1961a14aSEmmanuel Vadot 	int error;
233*1961a14aSEmmanuel Vadot 
234*1961a14aSEmmanuel Vadot 	if (bootverbose)
235*1961a14aSEmmanuel Vadot 		device_printf(adapter->dev.parent->bsddev,
236*1961a14aSEmmanuel Vadot 		    "Adding i2c adapter %s\n", adapter->name);
237*1961a14aSEmmanuel Vadot 	lkpi_iicbb = device_add_child(adapter->dev.parent->bsddev, "lkpi_iicbb", -1);
238*1961a14aSEmmanuel Vadot 	if (lkpi_iicbb == NULL) {
239*1961a14aSEmmanuel Vadot 		device_printf(adapter->dev.parent->bsddev, "Couldn't add lkpi_iicbb\n");
240*1961a14aSEmmanuel Vadot 		return (ENXIO);
241*1961a14aSEmmanuel Vadot 	}
242*1961a14aSEmmanuel Vadot 
243*1961a14aSEmmanuel Vadot 	error = bus_generic_attach(adapter->dev.parent->bsddev);
244*1961a14aSEmmanuel Vadot 	if (error) {
245*1961a14aSEmmanuel Vadot 		device_printf(adapter->dev.parent->bsddev,
246*1961a14aSEmmanuel Vadot 		  "failed to attach child: error %d\n", error);
247*1961a14aSEmmanuel Vadot 		return (ENXIO);
248*1961a14aSEmmanuel Vadot 	}
249*1961a14aSEmmanuel Vadot 	LKPI_IIC_ADD_ADAPTER(lkpi_iicbb, adapter);
250*1961a14aSEmmanuel Vadot 	return (0);
251*1961a14aSEmmanuel Vadot }
252*1961a14aSEmmanuel Vadot 
253