ki2c.c revision 1.32.2.2 1 1.32.2.2 thorpej /* $NetBSD: ki2c.c,v 1.32.2.2 2021/09/10 15:45:28 thorpej Exp $ */
2 1.1 grant /* Id: ki2c.c,v 1.7 2002/10/05 09:56:05 tsubai Exp */
3 1.1 grant
4 1.1 grant /*-
5 1.1 grant * Copyright (c) 2001 Tsubai Masanari. All rights reserved.
6 1.1 grant *
7 1.1 grant * Redistribution and use in source and binary forms, with or without
8 1.1 grant * modification, are permitted provided that the following conditions
9 1.1 grant * are met:
10 1.1 grant * 1. Redistributions of source code must retain the above copyright
11 1.1 grant * notice, this list of conditions and the following disclaimer.
12 1.1 grant * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 grant * notice, this list of conditions and the following disclaimer in the
14 1.1 grant * documentation and/or other materials provided with the distribution.
15 1.1 grant * 3. The name of the author may not be used to endorse or promote products
16 1.1 grant * derived from this software without specific prior written permission.
17 1.1 grant *
18 1.1 grant * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 1.1 grant * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 1.1 grant * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 1.1 grant * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 1.1 grant * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 1.1 grant * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 1.1 grant * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 1.1 grant * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 1.1 grant * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 1.1 grant * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 1.1 grant */
29 1.1 grant
30 1.1 grant #include <sys/param.h>
31 1.1 grant #include <sys/device.h>
32 1.1 grant #include <sys/systm.h>
33 1.32.2.1 thorpej #include <sys/kmem.h>
34 1.11 ad #include <sys/mutex.h>
35 1.1 grant
36 1.1 grant #include <dev/ofw/openfirm.h>
37 1.1 grant #include <machine/autoconf.h>
38 1.1 grant
39 1.29 macallan #include "opt_ki2c.h"
40 1.3 macallan #include <macppc/dev/ki2cvar.h>
41 1.1 grant
42 1.32.2.1 thorpej #include "locators.h"
43 1.32.2.1 thorpej
44 1.20 macallan #ifdef KI2C_DEBUG
45 1.20 macallan #define DPRINTF printf
46 1.20 macallan #else
47 1.20 macallan #define DPRINTF while (0) printf
48 1.20 macallan #endif
49 1.20 macallan
50 1.32.2.1 thorpej static int ki2c_match(device_t, cfdata_t, void *);
51 1.32.2.1 thorpej static void ki2c_attach(device_t, device_t, void *);
52 1.32.2.1 thorpej static int ki2c_intr(struct ki2c_softc *);
53 1.3 macallan
54 1.3 macallan /* I2C glue */
55 1.32.2.1 thorpej static int ki2c_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *,
56 1.32.2.1 thorpej size_t, void *, size_t, int);
57 1.32.2.1 thorpej static int ki2c_i2c_acquire_bus(void *, int);
58 1.32.2.1 thorpej static void ki2c_i2c_release_bus(void *, int);
59 1.1 grant
60 1.18 macallan CFATTACH_DECL_NEW(ki2c, sizeof(struct ki2c_softc), ki2c_match, ki2c_attach,
61 1.9 dogcow NULL, NULL);
62 1.1 grant
63 1.32.2.1 thorpej static prop_dictionary_t
64 1.32.2.1 thorpej ki2c_i2c_device_props(struct ki2c_softc *sc, int node)
65 1.32.2.1 thorpej {
66 1.32.2.1 thorpej prop_dictionary_t props = prop_dictionary_create();
67 1.32.2.1 thorpej uint32_t reg;
68 1.32.2.1 thorpej char descr[32], num[8];
69 1.32.2.1 thorpej
70 1.32.2.1 thorpej /* We're fetching descriptions for sensors. */
71 1.32.2.2 thorpej /* XXX This is a terrible hack and should not be done this way XXX */
72 1.32.2.1 thorpej
73 1.32.2.1 thorpej for (node = OF_child(node); node != 0; node = OF_peer(node)) {
74 1.32.2.1 thorpej if (of_getprop_uint32(node, "reg", ®) == -1) {
75 1.32.2.1 thorpej continue;
76 1.32.2.1 thorpej }
77 1.32.2.1 thorpej if (OF_getprop(node, "location", descr, sizeof(descr)) <= 0) {
78 1.32.2.1 thorpej continue;
79 1.32.2.1 thorpej }
80 1.32.2.1 thorpej snprintf(num, sizeof(num), "s%02x", reg);
81 1.32.2.1 thorpej
82 1.32.2.1 thorpej aprint_debug_dev(sc->sc_dev,
83 1.32.2.1 thorpej "%s: sensor %s -> %s\n", __func__, num, descr);
84 1.32.2.1 thorpej
85 1.32.2.1 thorpej prop_dictionary_set_string(props, num, descr);
86 1.32.2.1 thorpej }
87 1.32.2.1 thorpej
88 1.32.2.1 thorpej return props;
89 1.32.2.1 thorpej }
90 1.32.2.1 thorpej
91 1.32.2.1 thorpej static bool
92 1.32.2.1 thorpej ki2c_i2c_enumerate_device(struct ki2c_softc *sc, device_t dev, int node,
93 1.32.2.1 thorpej const char *name, uint32_t addr,
94 1.32.2.1 thorpej struct i2c_enumerate_devices_args * const args)
95 1.32.2.1 thorpej {
96 1.32.2.1 thorpej int compat_size;
97 1.32.2.1 thorpej prop_dictionary_t props;
98 1.32.2.1 thorpej char compat_buf[32];
99 1.32.2.1 thorpej char *compat;
100 1.32.2.1 thorpej bool cbrv;
101 1.32.2.1 thorpej
102 1.32.2.1 thorpej compat_size = OF_getproplen(node, "compatible");
103 1.32.2.1 thorpej if (compat_size <= 0) {
104 1.32.2.1 thorpej /* some i2c device nodes don't have 'compatible' */
105 1.32.2.1 thorpej aprint_debug_dev(sc->sc_dev,
106 1.32.2.1 thorpej "no compatible property for phandle %d; using '%s'\n",
107 1.32.2.1 thorpej node, name);
108 1.32.2.1 thorpej compat = compat_buf;
109 1.32.2.1 thorpej strlcpy(compat, name, sizeof(compat));
110 1.32.2.1 thorpej compat_size = strlen(compat) + 1;
111 1.32.2.1 thorpej } else {
112 1.32.2.1 thorpej compat = kmem_tmpbuf_alloc(compat_size, compat_buf,
113 1.32.2.1 thorpej sizeof(compat_buf), KM_SLEEP);
114 1.32.2.1 thorpej if (OF_getprop(node, "compatible", compat,
115 1.32.2.1 thorpej sizeof(compat)) <= 0) {
116 1.32.2.1 thorpej aprint_error_dev(sc->sc_dev,
117 1.32.2.1 thorpej "unable to get compatible property for "
118 1.32.2.1 thorpej "phandle %d ('%s')\n", node, name);
119 1.32.2.1 thorpej goto bad;
120 1.32.2.1 thorpej }
121 1.32.2.1 thorpej }
122 1.32.2.1 thorpej
123 1.32.2.1 thorpej props = ki2c_i2c_device_props(sc, node);
124 1.32.2.1 thorpej
125 1.32.2.1 thorpej args->ia->ia_addr = (i2c_addr_t)addr;
126 1.32.2.1 thorpej args->ia->ia_name = name;
127 1.32.2.1 thorpej args->ia->ia_clist = compat;
128 1.32.2.1 thorpej args->ia->ia_clist_size = compat_size;
129 1.32.2.1 thorpej args->ia->ia_prop = props;
130 1.32.2.1 thorpej args->ia->ia_devhandle = devhandle_from_of(node);
131 1.32.2.1 thorpej
132 1.32.2.1 thorpej cbrv = args->callback(dev, args);
133 1.32.2.1 thorpej
134 1.32.2.1 thorpej prop_object_release(props);
135 1.32.2.1 thorpej
136 1.32.2.1 thorpej return cbrv; /* callback decides if we keep enumerating */
137 1.32.2.1 thorpej
138 1.32.2.1 thorpej bad:
139 1.32.2.1 thorpej if (compat != compat_buf) {
140 1.32.2.1 thorpej kmem_tmpbuf_free(compat, compat_size, compat_buf);
141 1.32.2.1 thorpej }
142 1.32.2.1 thorpej return true; /* keep enumerating */
143 1.32.2.1 thorpej }
144 1.32.2.1 thorpej
145 1.32.2.1 thorpej static int
146 1.32.2.1 thorpej ki2c_i2c_enumerate_devices(device_t dev, devhandle_t call_handle, void *v)
147 1.32.2.1 thorpej {
148 1.32.2.1 thorpej struct i2c_enumerate_devices_args *args = v;
149 1.32.2.1 thorpej int bus_phandle, node;
150 1.32.2.1 thorpej uint32_t addr;
151 1.32.2.1 thorpej char name[32];
152 1.32.2.1 thorpej
153 1.32.2.1 thorpej /* dev is the "iic" bus instance. ki2c channel is in args. */
154 1.32.2.1 thorpej struct ki2c_channel *ch = args->ia->ia_tag->ic_cookie;
155 1.32.2.1 thorpej struct ki2c_softc *sc = ch->ch_ki2c;
156 1.32.2.1 thorpej
157 1.32.2.1 thorpej /*
158 1.32.2.1 thorpej * If we're not using the separate nodes scheme, we need
159 1.32.2.1 thorpej * to filter out devices from the other channel. We detect
160 1.32.2.1 thorpej * this by comparing the bus phandle to the controller phandle,
161 1.32.2.1 thorpej * and if they match, we are NOT using the separate nodes
162 1.32.2.1 thorpej * scheme.
163 1.32.2.1 thorpej */
164 1.32.2.1 thorpej bus_phandle = devhandle_to_of(device_handle(dev));
165 1.32.2.1 thorpej bool filter_by_channel =
166 1.32.2.1 thorpej bus_phandle == devhandle_to_of(device_handle(sc->sc_dev));
167 1.32.2.1 thorpej
168 1.32.2.1 thorpej for (node = OF_child(bus_phandle); node != 0; node = OF_peer(node)) {
169 1.32.2.1 thorpej if (OF_getprop(node, "name", name, sizeof(name)) <= 0) {
170 1.32.2.1 thorpej aprint_error_dev(sc->sc_dev,
171 1.32.2.1 thorpej "unable to get name property for phandle %d\n",
172 1.32.2.1 thorpej node);
173 1.32.2.1 thorpej continue;
174 1.32.2.1 thorpej }
175 1.32.2.1 thorpej if (of_getprop_uint32(node, "reg", &addr) == -1 &&
176 1.32.2.1 thorpej of_getprop_uint32(node, "i2c-address", &addr) == -1) {
177 1.32.2.1 thorpej aprint_error_dev(sc->sc_dev,
178 1.32.2.1 thorpej "unable to get i2c address for phandle %d ('%s')\n",
179 1.32.2.1 thorpej node, name);
180 1.32.2.1 thorpej continue;
181 1.32.2.1 thorpej }
182 1.32.2.1 thorpej if (filter_by_channel && ((addr >> 8) & 1) != ch->ch_channel) {
183 1.32.2.1 thorpej continue;
184 1.32.2.1 thorpej }
185 1.32.2.1 thorpej addr = (addr & 0xff) >> 1;
186 1.32.2.1 thorpej if (!ki2c_i2c_enumerate_device(sc, dev, node, name, addr,
187 1.32.2.1 thorpej args)) {
188 1.32.2.1 thorpej break;
189 1.32.2.1 thorpej }
190 1.32.2.1 thorpej }
191 1.32.2.1 thorpej
192 1.32.2.1 thorpej return 0;
193 1.32.2.1 thorpej }
194 1.32.2.1 thorpej
195 1.32.2.1 thorpej static device_call_t
196 1.32.2.1 thorpej ki2c_devhandle_lookup_device_call(devhandle_t handle, const char *name,
197 1.32.2.1 thorpej devhandle_t *call_handlep)
198 1.32.2.1 thorpej {
199 1.32.2.1 thorpej if (strcmp(name, "i2c-enumerate-devices") == 0) {
200 1.32.2.1 thorpej return ki2c_i2c_enumerate_devices;
201 1.32.2.1 thorpej }
202 1.32.2.1 thorpej
203 1.32.2.1 thorpej /* Defer everything else to the "super". */
204 1.32.2.1 thorpej return NULL;
205 1.32.2.1 thorpej }
206 1.32.2.1 thorpej
207 1.32.2.1 thorpej static inline uint8_t
208 1.32.2.1 thorpej ki2c_readreg(struct ki2c_softc *sc, int reg)
209 1.32.2.1 thorpej {
210 1.32.2.1 thorpej
211 1.32.2.1 thorpej return bus_space_read_1(sc->sc_tag, sc->sc_bh, sc->sc_regstep * reg);
212 1.32.2.1 thorpej }
213 1.32.2.1 thorpej
214 1.32.2.1 thorpej static inline void
215 1.32.2.1 thorpej ki2c_writereg(struct ki2c_softc *sc, int reg, uint8_t val)
216 1.32.2.1 thorpej {
217 1.32.2.1 thorpej
218 1.32.2.1 thorpej bus_space_write_1(sc->sc_tag, sc->sc_bh, reg * sc->sc_regstep, val);
219 1.32.2.1 thorpej delay(10);
220 1.32.2.1 thorpej }
221 1.32.2.1 thorpej
222 1.32.2.1 thorpej #if 0
223 1.32.2.1 thorpej static u_int
224 1.32.2.1 thorpej ki2c_getmode(struct ki2c_softc *sc)
225 1.32.2.1 thorpej {
226 1.32.2.1 thorpej return ki2c_readreg(sc, MODE) & I2C_MODE;
227 1.32.2.1 thorpej }
228 1.32.2.1 thorpej #endif
229 1.32.2.1 thorpej
230 1.32.2.1 thorpej static void
231 1.32.2.1 thorpej ki2c_setmode(struct ki2c_softc *sc, u_int mode)
232 1.32.2.1 thorpej {
233 1.32.2.1 thorpej ki2c_writereg(sc, MODE, mode);
234 1.32.2.1 thorpej }
235 1.32.2.1 thorpej
236 1.32.2.1 thorpej #if 0
237 1.32.2.1 thorpej static u_int
238 1.32.2.1 thorpej ki2c_getspeed(struct ki2c_softc *sc)
239 1.32.2.1 thorpej {
240 1.32.2.1 thorpej return ki2c_readreg(sc, MODE) & I2C_SPEED;
241 1.32.2.1 thorpej }
242 1.32.2.1 thorpej #endif
243 1.32.2.1 thorpej
244 1.32.2.1 thorpej static void
245 1.32.2.1 thorpej ki2c_setspeed(struct ki2c_softc *sc, u_int speed)
246 1.32.2.1 thorpej {
247 1.32.2.1 thorpej u_int x;
248 1.32.2.1 thorpej
249 1.32.2.1 thorpej KASSERT((speed & ~I2C_SPEED) == 0);
250 1.32.2.1 thorpej x = ki2c_readreg(sc, MODE);
251 1.32.2.1 thorpej x &= ~I2C_SPEED;
252 1.32.2.1 thorpej x |= speed;
253 1.32.2.1 thorpej ki2c_writereg(sc, MODE, x);
254 1.32.2.1 thorpej }
255 1.32.2.1 thorpej
256 1.32.2.1 thorpej static int
257 1.17 matt ki2c_match(device_t parent, cfdata_t match, void *aux)
258 1.1 grant {
259 1.1 grant struct confargs *ca = aux;
260 1.1 grant
261 1.1 grant if (strcmp(ca->ca_name, "i2c") == 0)
262 1.1 grant return 1;
263 1.1 grant
264 1.1 grant return 0;
265 1.1 grant }
266 1.1 grant
267 1.32.2.1 thorpej static void
268 1.17 matt ki2c_attach(device_t parent, device_t self, void *aux)
269 1.1 grant {
270 1.17 matt struct ki2c_softc *sc = device_private(self);
271 1.1 grant struct confargs *ca = aux;
272 1.32.2.1 thorpej struct ki2c_channel *ch;
273 1.1 grant int node = ca->ca_node;
274 1.32.2.1 thorpej uint32_t channel, addr;
275 1.32.2.1 thorpej int i, rate, child;
276 1.3 macallan struct i2cbus_attach_args iba;
277 1.32.2.1 thorpej devhandle_t devhandle;
278 1.3 macallan char name[32];
279 1.18 macallan
280 1.18 macallan sc->sc_dev = self;
281 1.21 macallan sc->sc_tag = ca->ca_tag;
282 1.1 grant ca->ca_reg[0] += ca->ca_baseaddr;
283 1.1 grant
284 1.1 grant if (OF_getprop(node, "AAPL,i2c-rate", &rate, 4) != 4) {
285 1.20 macallan aprint_error(": cannot get i2c-rate\n");
286 1.1 grant return;
287 1.1 grant }
288 1.20 macallan if (OF_getprop(node, "AAPL,address", &addr, 4) != 4) {
289 1.20 macallan aprint_error(": unable to find i2c address\n");
290 1.1 grant return;
291 1.1 grant }
292 1.21 macallan if (bus_space_map(sc->sc_tag, addr, PAGE_SIZE, 0, &sc->sc_bh) != 0) {
293 1.21 macallan aprint_error_dev(sc->sc_dev, "failed to map registers\n");
294 1.21 macallan return;
295 1.21 macallan }
296 1.21 macallan
297 1.1 grant if (OF_getprop(node, "AAPL,address-step", &sc->sc_regstep, 4) != 4) {
298 1.20 macallan aprint_error(": unable to find i2c address step\n");
299 1.1 grant return;
300 1.1 grant }
301 1.1 grant
302 1.1 grant printf("\n");
303 1.1 grant
304 1.1 grant ki2c_writereg(sc, STATUS, 0);
305 1.1 grant ki2c_writereg(sc, ISR, 0);
306 1.1 grant ki2c_writereg(sc, IER, 0);
307 1.1 grant
308 1.1 grant ki2c_setmode(sc, I2C_STDSUBMODE);
309 1.1 grant ki2c_setspeed(sc, I2C_100kHz); /* XXX rate */
310 1.3 macallan
311 1.3 macallan ki2c_writereg(sc, IER,I2C_INT_DATA|I2C_INT_ADDR|I2C_INT_STOP);
312 1.32.2.1 thorpej
313 1.32.2.1 thorpej /*
314 1.32.2.1 thorpej * Two physical I2C busses share a single controller. It's not
315 1.32.2.1 thorpej * quite a mux, which is why we don't attach it that way.
316 1.32.2.1 thorpej *
317 1.32.2.1 thorpej * The locking order is:
318 1.25 macallan *
319 1.32.2.1 thorpej * iic bus mutex -> ctrl_lock
320 1.32.2.1 thorpej *
321 1.32.2.1 thorpej * ctrl_lock is taken in ki2c_i2c_acquire_bus.
322 1.4 macallan */
323 1.32.2.1 thorpej mutex_init(&sc->sc_ctrl_lock, MUTEX_DEFAULT, IPL_NONE);
324 1.32.2.1 thorpej
325 1.32.2.1 thorpej /* Set up the channel structures. */
326 1.32.2.1 thorpej for (i = 0; i < KI2C_MAX_I2C_CHANNELS; i++) {
327 1.32.2.1 thorpej ch = &sc->sc_channels[i];
328 1.32.2.1 thorpej
329 1.32.2.1 thorpej iic_tag_init(&ch->ch_i2c);
330 1.32.2.1 thorpej ch->ch_i2c.ic_channel = ch->ch_channel = i;
331 1.32.2.1 thorpej ch->ch_i2c.ic_cookie = ch;
332 1.32.2.1 thorpej ch->ch_i2c.ic_acquire_bus = ki2c_i2c_acquire_bus;
333 1.32.2.1 thorpej ch->ch_i2c.ic_release_bus = ki2c_i2c_release_bus;
334 1.32.2.1 thorpej ch->ch_i2c.ic_exec = ki2c_i2c_exec;
335 1.28 macallan
336 1.32.2.1 thorpej ch->ch_ki2c = sc;
337 1.32.2.1 thorpej }
338 1.32.2.1 thorpej
339 1.32.2.1 thorpej /*
340 1.32.2.1 thorpej * Different systems have different I2C device tree topologies.
341 1.32.2.1 thorpej *
342 1.32.2.1 thorpej * Some systems use a scheme like this:
343 1.32.2.1 thorpej *
344 1.32.2.1 thorpej * /u3@0,f8000000/i2c@f8001000/temp-monitor@98
345 1.32.2.1 thorpej * /u3@0,f8000000/i2c@f8001000/fan@15e
346 1.32.2.1 thorpej *
347 1.32.2.1 thorpej * Here, we see the channel encoded in bit #8 of the address.
348 1.32.2.1 thorpej *
349 1.32.2.1 thorpej * Other systems use a scheme like this:
350 1.32.2.1 thorpej *
351 1.32.2.1 thorpej * /ht@0,f2000000/pci@4000,0,0/mac-io@7/i2c@18000/i2c-bus@0
352 1.32.2.1 thorpej * /ht@0,f2000000/pci@4000,0,0/mac-io@7/i2c@18000/i2c-bus@0/codec@8c
353 1.32.2.1 thorpej *
354 1.32.2.1 thorpej * /u4@0,f8000000/i2c@f8001000/i2c-bus@1
355 1.32.2.1 thorpej * /u4@0,f8000000/i2c@f8001000/i2c-bus@1/temp-monitor@94
356 1.32.2.1 thorpej *
357 1.32.2.1 thorpej * Here, a separate device tree node represents the channel.
358 1.32.2.1 thorpej * Note that in BOTH cases, the I2C address of the devices are
359 1.32.2.1 thorpej * shifted left by 1 (as it would be on the wire to leave room
360 1.32.2.1 thorpej * for the read/write bit).
361 1.32.2.1 thorpej *
362 1.32.2.1 thorpej * So, what we're going to do here is look for i2c-bus nodes. If
363 1.32.2.1 thorpej * we find them, we remember those phandles, and will use them for
364 1.32.2.1 thorpej * device enumeration. If we don't, then we will use the controller
365 1.32.2.1 thorpej * phandle for device enumeration and filter based on the channel
366 1.32.2.1 thorpej * bit in the "reg" property.
367 1.32.2.1 thorpej */
368 1.32.2.1 thorpej int i2c_bus_phandles[KI2C_MAX_I2C_CHANNELS] = { 0 };
369 1.32.2.1 thorpej bool separate_nodes_scheme = false;
370 1.32.2.1 thorpej for (child = OF_child(node); child != 0; child = OF_peer(child)) {
371 1.4 macallan OF_getprop(child, "name", name, sizeof(name));
372 1.25 macallan if (strcmp(name, "i2c-bus") == 0) {
373 1.32.2.1 thorpej separate_nodes_scheme = true;
374 1.32.2.1 thorpej if (of_getprop_uint32(child, "reg", &channel) == -1) {
375 1.32.2.1 thorpej continue;
376 1.32.2.1 thorpej }
377 1.32.2.1 thorpej if (channel >= KI2C_MAX_I2C_CHANNELS) {
378 1.32.2.1 thorpej continue;
379 1.28 macallan }
380 1.32.2.1 thorpej i2c_bus_phandles[channel] = child;
381 1.26 macallan }
382 1.3 macallan }
383 1.3 macallan
384 1.32.2.1 thorpej /*
385 1.32.2.1 thorpej * Set up our handle implementation (we provide our own
386 1.32.2.1 thorpej * i2c enumeration call).
387 1.32.2.1 thorpej */
388 1.32.2.1 thorpej devhandle = device_handle(self);
389 1.32.2.1 thorpej devhandle_impl_inherit(&sc->sc_devhandle_impl, devhandle.impl);
390 1.32.2.1 thorpej sc->sc_devhandle_impl.lookup_device_call =
391 1.32.2.1 thorpej ki2c_devhandle_lookup_device_call;
392 1.32.2.1 thorpej
393 1.32.2.1 thorpej for (i = 0; i < KI2C_MAX_I2C_CHANNELS; i++) {
394 1.32.2.1 thorpej int locs[I2CBUSCF_NLOCS];
395 1.32.2.1 thorpej
396 1.32.2.1 thorpej ch = &sc->sc_channels[i];
397 1.32.2.1 thorpej
398 1.32.2.1 thorpej if (separate_nodes_scheme) {
399 1.32.2.1 thorpej if (i2c_bus_phandles[i] == 0) {
400 1.32.2.1 thorpej /*
401 1.32.2.1 thorpej * This wasn't represented (either at all
402 1.32.2.1 thorpej * or not correctly) in the device tree,
403 1.32.2.1 thorpej * so skip attaching the "iic" instance.
404 1.32.2.1 thorpej */
405 1.32.2.1 thorpej continue;
406 1.32.2.1 thorpej }
407 1.32.2.1 thorpej devhandle = devhandle_from_of(i2c_bus_phandles[i]);
408 1.32.2.1 thorpej } else {
409 1.32.2.1 thorpej devhandle = device_handle(self);
410 1.32.2.1 thorpej }
411 1.32.2.1 thorpej devhandle.impl = &sc->sc_devhandle_impl;
412 1.1 grant
413 1.32.2.1 thorpej locs[I2CBUSCF_BUS] = ch->ch_i2c.ic_channel;
414 1.1 grant
415 1.32.2.1 thorpej memset(&iba, 0, sizeof(iba));
416 1.32.2.1 thorpej iba.iba_tag = &ch->ch_i2c;
417 1.32.2.1 thorpej config_found(sc->sc_dev, &iba, iicbus_print_multi,
418 1.32.2.1 thorpej CFARGS(.submatch = config_stdsubmatch,
419 1.32.2.1 thorpej .locators = locs,
420 1.32.2.1 thorpej .devhandle = devhandle));
421 1.32.2.1 thorpej }
422 1.1 grant
423 1.1 grant }
424 1.1 grant
425 1.32.2.1 thorpej static int
426 1.14 dsl ki2c_intr(struct ki2c_softc *sc)
427 1.1 grant {
428 1.1 grant u_int isr, x;
429 1.1 grant
430 1.1 grant isr = ki2c_readreg(sc, ISR);
431 1.1 grant if (isr & I2C_INT_ADDR) {
432 1.1 grant #if 0
433 1.1 grant if ((ki2c_readreg(sc, STATUS) & I2C_ST_LASTAAK) == 0) {
434 1.1 grant /* No slave responded. */
435 1.1 grant sc->sc_flags |= I2C_ERROR;
436 1.1 grant goto out;
437 1.1 grant }
438 1.1 grant #endif
439 1.1 grant
440 1.1 grant if (sc->sc_flags & I2C_READING) {
441 1.1 grant if (sc->sc_resid > 1) {
442 1.1 grant x = ki2c_readreg(sc, CONTROL);
443 1.1 grant x |= I2C_CT_AAK;
444 1.1 grant ki2c_writereg(sc, CONTROL, x);
445 1.1 grant }
446 1.1 grant } else {
447 1.1 grant ki2c_writereg(sc, DATA, *sc->sc_data++);
448 1.1 grant sc->sc_resid--;
449 1.1 grant }
450 1.1 grant }
451 1.1 grant
452 1.1 grant if (isr & I2C_INT_DATA) {
453 1.1 grant if (sc->sc_flags & I2C_READING) {
454 1.1 grant *sc->sc_data++ = ki2c_readreg(sc, DATA);
455 1.1 grant sc->sc_resid--;
456 1.1 grant
457 1.1 grant if (sc->sc_resid == 0) { /* Completed */
458 1.1 grant ki2c_writereg(sc, CONTROL, 0);
459 1.1 grant goto out;
460 1.1 grant }
461 1.1 grant } else {
462 1.1 grant #if 0
463 1.1 grant if ((ki2c_readreg(sc, STATUS) & I2C_ST_LASTAAK) == 0) {
464 1.1 grant /* No slave responded. */
465 1.1 grant sc->sc_flags |= I2C_ERROR;
466 1.1 grant goto out;
467 1.1 grant }
468 1.1 grant #endif
469 1.1 grant
470 1.1 grant if (sc->sc_resid == 0) {
471 1.1 grant x = ki2c_readreg(sc, CONTROL) | I2C_CT_STOP;
472 1.1 grant ki2c_writereg(sc, CONTROL, x);
473 1.1 grant } else {
474 1.1 grant ki2c_writereg(sc, DATA, *sc->sc_data++);
475 1.1 grant sc->sc_resid--;
476 1.1 grant }
477 1.1 grant }
478 1.1 grant }
479 1.1 grant
480 1.1 grant out:
481 1.1 grant if (isr & I2C_INT_STOP) {
482 1.1 grant ki2c_writereg(sc, CONTROL, 0);
483 1.1 grant sc->sc_flags &= ~I2C_BUSY;
484 1.1 grant }
485 1.1 grant
486 1.1 grant ki2c_writereg(sc, ISR, isr);
487 1.1 grant
488 1.1 grant return 1;
489 1.1 grant }
490 1.1 grant
491 1.32.2.1 thorpej static int
492 1.14 dsl ki2c_poll(struct ki2c_softc *sc, int timo)
493 1.1 grant {
494 1.1 grant while (sc->sc_flags & I2C_BUSY) {
495 1.1 grant if (ki2c_readreg(sc, ISR))
496 1.1 grant ki2c_intr(sc);
497 1.1 grant timo -= 100;
498 1.1 grant if (timo < 0) {
499 1.20 macallan DPRINTF("i2c_poll: timeout\n");
500 1.32.2.1 thorpej return ETIMEDOUT;
501 1.1 grant }
502 1.1 grant delay(100);
503 1.1 grant }
504 1.1 grant return 0;
505 1.1 grant }
506 1.1 grant
507 1.32.2.1 thorpej static int
508 1.15 dsl ki2c_start(struct ki2c_softc *sc, int addr, int subaddr, void *data, int len)
509 1.1 grant {
510 1.1 grant int rw = (sc->sc_flags & I2C_READING) ? 1 : 0;
511 1.32.2.1 thorpej int error, timo, x;
512 1.1 grant
513 1.1 grant KASSERT((addr & 1) == 0);
514 1.1 grant
515 1.1 grant sc->sc_data = data;
516 1.1 grant sc->sc_resid = len;
517 1.1 grant sc->sc_flags |= I2C_BUSY;
518 1.1 grant
519 1.1 grant timo = 1000 + len * 200;
520 1.1 grant
521 1.1 grant /* XXX TAS3001 sometimes takes 50ms to finish writing registers. */
522 1.1 grant /* if (addr == 0x68) */
523 1.1 grant timo += 100000;
524 1.1 grant
525 1.1 grant ki2c_writereg(sc, ADDR, addr | rw);
526 1.1 grant ki2c_writereg(sc, SUBADDR, subaddr);
527 1.1 grant
528 1.1 grant x = ki2c_readreg(sc, CONTROL) | I2C_CT_ADDR;
529 1.1 grant ki2c_writereg(sc, CONTROL, x);
530 1.1 grant
531 1.32.2.1 thorpej if ((error = ki2c_poll(sc, timo)) != 0)
532 1.32.2.1 thorpej return error;
533 1.32.2.1 thorpej
534 1.1 grant if (sc->sc_flags & I2C_ERROR) {
535 1.20 macallan DPRINTF("I2C_ERROR\n");
536 1.32.2.1 thorpej return EIO;
537 1.1 grant }
538 1.1 grant return 0;
539 1.1 grant }
540 1.1 grant
541 1.32.2.1 thorpej static int
542 1.15 dsl ki2c_read(struct ki2c_softc *sc, int addr, int subaddr, void *data, int len)
543 1.1 grant {
544 1.1 grant sc->sc_flags = I2C_READING;
545 1.20 macallan DPRINTF("ki2c_read: %02x %d\n", addr, len);
546 1.1 grant return ki2c_start(sc, addr, subaddr, data, len);
547 1.1 grant }
548 1.1 grant
549 1.32.2.1 thorpej static int
550 1.15 dsl ki2c_write(struct ki2c_softc *sc, int addr, int subaddr, void *data, int len)
551 1.1 grant {
552 1.1 grant sc->sc_flags = 0;
553 1.20 macallan DPRINTF("ki2c_write: %02x %d\n",addr,len);
554 1.3 macallan return ki2c_start(sc, addr, subaddr, data, len);
555 1.3 macallan }
556 1.3 macallan
557 1.32.2.1 thorpej static int
558 1.32.2.1 thorpej ki2c_i2c_acquire_bus(void * const v, int const flags)
559 1.32.2.1 thorpej {
560 1.32.2.1 thorpej struct ki2c_channel *ch = v;
561 1.32.2.1 thorpej struct ki2c_softc *sc = ch->ch_ki2c;
562 1.32.2.1 thorpej
563 1.32.2.1 thorpej if (flags & I2C_F_POLL) {
564 1.32.2.1 thorpej if (! mutex_tryenter(&sc->sc_ctrl_lock)) {
565 1.32.2.1 thorpej return EBUSY;
566 1.32.2.1 thorpej }
567 1.32.2.1 thorpej } else {
568 1.32.2.1 thorpej mutex_enter(&sc->sc_ctrl_lock);
569 1.32.2.1 thorpej }
570 1.32.2.1 thorpej return 0;
571 1.32.2.1 thorpej }
572 1.32.2.1 thorpej
573 1.32.2.1 thorpej static void
574 1.32.2.1 thorpej ki2c_i2c_release_bus(void * const v, int const flags)
575 1.32.2.1 thorpej {
576 1.32.2.1 thorpej struct ki2c_channel *ch = v;
577 1.32.2.1 thorpej struct ki2c_softc *sc = ch->ch_ki2c;
578 1.32.2.1 thorpej
579 1.32.2.1 thorpej mutex_exit(&sc->sc_ctrl_lock);
580 1.32.2.1 thorpej }
581 1.32.2.1 thorpej
582 1.3 macallan int
583 1.3 macallan ki2c_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *vcmd,
584 1.3 macallan size_t cmdlen, void *vbuf, size_t buflen, int flags)
585 1.3 macallan {
586 1.32.2.1 thorpej struct ki2c_channel *ch = cookie;
587 1.32.2.1 thorpej struct ki2c_softc *sc = ch->ch_ki2c;
588 1.32.2.1 thorpej int i, error;
589 1.12 pgoyette size_t w_len;
590 1.12 pgoyette uint8_t *wp;
591 1.12 pgoyette uint8_t wrbuf[I2C_EXEC_MAX_CMDLEN + I2C_EXEC_MAX_CMDLEN];
592 1.25 macallan uint8_t channel;
593 1.12 pgoyette
594 1.12 pgoyette /*
595 1.12 pgoyette * We don't have any idea if the ki2c controller can execute
596 1.12 pgoyette * i2c quick_{read,write} operations, so if someone tries one,
597 1.12 pgoyette * return an error.
598 1.12 pgoyette */
599 1.12 pgoyette if (cmdlen == 0 && buflen == 0)
600 1.32.2.1 thorpej return ENOTSUP;
601 1.12 pgoyette
602 1.32.2.1 thorpej /* Don't support 10-bit addressing. */
603 1.32.2.1 thorpej if (addr > 0x7f)
604 1.32.2.1 thorpej return ENOTSUP;
605 1.32.2.1 thorpej
606 1.32.2.1 thorpej channel = ch->ch_channel == 1 ? 0x10 : 0x00;
607 1.25 macallan
608 1.3 macallan /* we handle the subaddress stuff ourselves */
609 1.25 macallan ki2c_setmode(sc, channel | I2C_STDMODE);
610 1.28 macallan ki2c_setspeed(sc, I2C_50kHz);
611 1.3 macallan
612 1.12 pgoyette /* Write-buffer defaults to vcmd */
613 1.12 pgoyette wp = (uint8_t *)(__UNCONST(vcmd));
614 1.12 pgoyette w_len = cmdlen;
615 1.12 pgoyette
616 1.12 pgoyette /*
617 1.12 pgoyette * Concatenate vcmd and vbuf for write operations
618 1.12 pgoyette *
619 1.12 pgoyette * Drivers written specifically for ki2c might already do this,
620 1.12 pgoyette * but "generic" i2c drivers still provide separate arguments
621 1.12 pgoyette * for the cmd and buf parts of iic_smbus_write_{byte,word}.
622 1.12 pgoyette */
623 1.12 pgoyette if (I2C_OP_WRITE_P(op) && buflen != 0) {
624 1.12 pgoyette if (cmdlen == 0) {
625 1.12 pgoyette wp = (uint8_t *)vbuf;
626 1.12 pgoyette w_len = buflen;
627 1.12 pgoyette } else {
628 1.12 pgoyette KASSERT((cmdlen + buflen) <= sizeof(wrbuf));
629 1.12 pgoyette wp = (uint8_t *)(__UNCONST(vcmd));
630 1.12 pgoyette w_len = 0;
631 1.12 pgoyette for (i = 0; i < cmdlen; i++)
632 1.12 pgoyette wrbuf[w_len++] = *wp++;
633 1.12 pgoyette wp = (uint8_t *)vbuf;
634 1.12 pgoyette for (i = 0; i < buflen; i++)
635 1.12 pgoyette wrbuf[w_len++] = *wp++;
636 1.12 pgoyette wp = wrbuf;
637 1.12 pgoyette }
638 1.12 pgoyette }
639 1.12 pgoyette
640 1.32.2.1 thorpej if (w_len > 0) {
641 1.32.2.1 thorpej error = ki2c_write(sc, addr << 1, 0, wp, w_len);
642 1.32.2.1 thorpej if (error) {
643 1.32.2.1 thorpej return error;
644 1.32.2.1 thorpej }
645 1.32.2.1 thorpej }
646 1.10 garbled
647 1.10 garbled if (I2C_OP_READ_P(op)) {
648 1.32.2.1 thorpej error = ki2c_read(sc, addr << 1, 0, vbuf, buflen);
649 1.32.2.1 thorpej if (error) {
650 1.32.2.1 thorpej return error;
651 1.32.2.1 thorpej }
652 1.3 macallan }
653 1.3 macallan return 0;
654 1.1 grant }
655