Update the pcfiic driver for the new i2c device enumeration scheme. Push the multiple-channels complexity up into the ebus front-end, as that specific to a particular Sun model of controller. Now the BBC-type controllers get multiple I2C bus instances attached to them.diff -r1.7 -r1.7.6.1 src/sys/arch/sparc64/dev/pcfiic_ebus.c
(thorpej)
--- src/sys/arch/sparc64/dev/pcfiic_ebus.c 2020/10/23 15:18:10 1.7
+++ src/sys/arch/sparc64/dev/pcfiic_ebus.c 2021/05/14 06:53:14 1.7.6.1
@@ -1,106 +1,235 @@ | @@ -1,106 +1,235 @@ | |||
1 | /* $NetBSD: pcfiic_ebus.c,v 1.7 2020/10/23 15:18:10 jdc Exp $ */ | 1 | /* $NetBSD: pcfiic_ebus.c,v 1.7.6.1 2021/05/14 06:53:14 thorpej Exp $ */ | |
2 | /* $OpenBSD: pcfiic_ebus.c,v 1.13 2008/06/08 03:07:40 deraadt Exp $ */ | 2 | /* $OpenBSD: pcfiic_ebus.c,v 1.13 2008/06/08 03:07:40 deraadt Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (c) 2021 The NetBSD Foundation, Inc. | |||
6 | * All rights reserved. | |||
7 | * | |||
8 | * This code is derived from software contributed to The NetBSD Foundation | |||
9 | * by Jason R. Thorpe. | |||
10 | * | |||
11 | * Redistribution and use in source and binary forms, with or without | |||
12 | * modification, are permitted provided that the following conditions | |||
13 | * are met: | |||
14 | * 1. Redistributions of source code must retain the above copyright | |||
15 | * notice, this list of conditions and the following disclaimer. | |||
16 | * 2. Redistributions in binary form must reproduce the above copyright | |||
17 | * notice, this list of conditions and the following disclaimer in the | |||
18 | * documentation and/or other materials provided with the distribution. | |||
19 | * | |||
20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |||
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |||
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |||
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |||
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |||
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |||
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |||
30 | * POSSIBILITY OF SUCH DAMAGE. | |||
31 | */ | |||
32 | ||||
33 | /* | |||
5 | * Copyright (c) 2006 David Gwynne <dlg@openbsd.org> | 34 | * Copyright (c) 2006 David Gwynne <dlg@openbsd.org> | |
6 | * | 35 | * | |
7 | * Permission to use, copy, modify, and distribute this software for any | 36 | * Permission to use, copy, modify, and distribute this software for any | |
8 | * purpose with or without fee is hereby granted, provided that the above | 37 | * purpose with or without fee is hereby granted, provided that the above | |
9 | * copyright notice and this permission notice appear in all copies. | 38 | * copyright notice and this permission notice appear in all copies. | |
10 | * | 39 | * | |
11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | 40 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | 41 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | 42 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | 43 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | 44 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | 45 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 46 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
18 | */ | 47 | */ | |
19 | 48 | |||
20 | #include <sys/cdefs.h> | 49 | #include <sys/cdefs.h> | |
21 | __KERNEL_RCSID(0, "$NetBSD: pcfiic_ebus.c,v 1.7 2020/10/23 15:18:10 jdc Exp $"); | 50 | __KERNEL_RCSID(0, "$NetBSD: pcfiic_ebus.c,v 1.7.6.1 2021/05/14 06:53:14 thorpej Exp $"); | |
22 | 51 | |||
23 | /* | 52 | /* | |
24 | * Device specific driver for the EBus i2c devices found on some sun4u | 53 | * Device specific driver for the EBus i2c devices found on some sun4u | |
25 | * systems. On systems not having a boot-bus controller the i2c devices | 54 | * systems. On systems not having a boot-bus controller the i2c devices | |
26 | * are PCF8584. | 55 | * are PCF8584. | |
27 | */ | 56 | */ | |
28 | 57 | |||
29 | #include <sys/param.h> | 58 | #include <sys/param.h> | |
30 | #include <sys/systm.h> | 59 | #include <sys/systm.h> | |
31 | #include <sys/device.h> | 60 | #include <sys/device.h> | |
32 | #include <sys/kernel.h> | 61 | #include <sys/kernel.h> | |
33 | #include <sys/rwlock.h> | 62 | #include <sys/kmem.h> | |
63 | #include <sys/mutex.h> | |||
34 | 64 | |||
35 | #include <sys/bus.h> | 65 | #include <sys/bus.h> | |
36 | #include <machine/openfirm.h> | 66 | #include <machine/openfirm.h> | |
37 | #include <machine/autoconf.h> | 67 | #include <machine/autoconf.h> | |
38 | 68 | |||
39 | #include <dev/ebus/ebusreg.h> | 69 | #include <dev/ebus/ebusreg.h> | |
40 | #include <dev/ebus/ebusvar.h> | 70 | #include <dev/ebus/ebusvar.h> | |
41 | 71 | |||
42 | #include <dev/i2c/i2cvar.h> | 72 | #include <dev/i2c/i2cvar.h> | |
43 | 73 | |||
44 | #include <dev/ic/pcf8584var.h> | 74 | #include <dev/ic/pcf8584var.h> | |
45 | #include <dev/ic/pcf8584reg.h> | 75 | #include <dev/ic/pcf8584reg.h> | |
46 | 76 | |||
47 | int pcfiic_ebus_match(device_t, struct cfdata *, void *); | |||
48 | void pcfiic_ebus_attach(device_t, device_t, void *); | |||
49 | ||||
50 | struct pcfiic_ebus_softc { | 77 | struct pcfiic_ebus_softc { | |
51 | struct pcfiic_softc esc_sc; | 78 | struct pcfiic_softc esc_sc; | |
52 | 79 | |||
53 | int esc_node; | 80 | kmutex_t esc_ctrl_lock; | |
81 | bus_space_handle_t esc_ioh; /* for channel selection */ | |||
82 | ||||
54 | void *esc_ih; | 83 | void *esc_ih; | |
55 | }; | 84 | }; | |
56 | 85 | |||
57 | CFATTACH_DECL_NEW(pcfiic, sizeof(struct pcfiic_ebus_softc), | 86 | static void | |
58 | pcfiic_ebus_match, pcfiic_ebus_attach, NULL, NULL); | 87 | bbc_select_channel(struct pcfiic_ebus_softc *esc, uint8_t channel) | |
88 | { | |||
89 | bus_space_write_1(esc->esc_sc.sc_iot, esc->esc_ioh, 0, channel); | |||
90 | bus_space_barrier(esc->esc_sc.sc_iot, esc->esc_ioh, 0, 1, | |||
91 | BUS_SPACE_BARRIER_WRITE); | |||
92 | } | |||
93 | ||||
94 | static int | |||
95 | bbc_acquire_bus(void *v, int flags) | |||
96 | { | |||
97 | struct pcfiic_channel *ch = v; | |||
98 | struct pcfiic_ebus_softc *esc = container_of(ch->ch_sc, | |||
99 | struct pcfiic_ebus_softc, esc_sc); | |||
100 | ||||
101 | if (flags & I2C_F_POLL) { | |||
102 | if (! mutex_tryenter(&esc->esc_ctrl_lock)) { | |||
103 | return EBUSY; | |||
104 | } | |||
105 | } else { | |||
106 | mutex_enter(&esc->esc_ctrl_lock); | |||
107 | } | |||
108 | ||||
109 | bbc_select_channel(esc, (uint8_t)ch->ch_channel); | |||
110 | return 0; | |||
111 | } | |||
112 | ||||
113 | static void | |||
114 | bbc_release_bus(void *v, int flags) | |||
115 | { | |||
116 | struct pcfiic_channel *ch = v; | |||
117 | struct pcfiic_ebus_softc *esc = container_of(ch->ch_sc, | |||
118 | struct pcfiic_ebus_softc, esc_sc); | |||
59 | 119 | |||
60 | int | 120 | mutex_exit(&esc->esc_ctrl_lock); | |
121 | } | |||
122 | ||||
123 | static void | |||
124 | bbc_initialize_channels(struct pcfiic_ebus_softc *esc) | |||
125 | { | |||
126 | struct pcfiic_softc *sc = &esc->esc_sc; | |||
127 | struct pcfiic_channel *ch; | |||
128 | devhandle_t devhandle = device_handle(sc->sc_dev); | |||
129 | unsigned int busmap = 0; | |||
130 | int node = devhandle_to_of(devhandle); | |||
131 | uint32_t reg[2]; | |||
132 | uint32_t channel; | |||
133 | int i, nchannels; | |||
134 | ||||
135 | /* | |||
136 | * Two physical I2C busses share a single controller. The | |||
137 | * devices are not distinct, so it's not easy to treat it | |||
138 | * it as a mux. | |||
139 | * | |||
140 | * The locking order is: | |||
141 | * | |||
142 | * iic bus mutex -> ctrl_lock | |||
143 | * | |||
144 | * ctrl_lock is taken in bbc_acquire_bus. | |||
145 | */ | |||
146 | mutex_init(&esc->esc_ctrl_lock, MUTEX_DEFAULT, IPL_NONE); | |||
147 | sc->sc_acquire_bus = bbc_acquire_bus; | |||
148 | sc->sc_release_bus = bbc_release_bus; | |||
149 | ||||
150 | /* | |||
151 | * The Sun device tree has all devices, no matter the | |||
152 | * channel, as direct children of this node. Figure | |||
153 | * out which channel numbers are listed, count them, | |||
154 | * and then populate the channel structures. | |||
155 | */ | |||
156 | for (node = OF_child(node); node != 0; node = OF_peer(node)) { | |||
157 | if (OF_getprop(node, "reg", reg, sizeof(reg)) != sizeof(reg)) { | |||
158 | continue; | |||
159 | } | |||
160 | ||||
161 | /* Channel is in the first cell. */ | |||
162 | channel = be32toh(reg[0]); | |||
163 | KASSERT(channel < 32); | |||
164 | ||||
165 | busmap |= __BIT(channel); | |||
166 | } | |||
167 | ||||
168 | nchannels = popcount(busmap); | |||
169 | if (nchannels == 0) { | |||
170 | /* No child devices. */ | |||
171 | return; | |||
172 | } | |||
173 | ||||
174 | ch = kmem_alloc(nchannels * sizeof(*ch), KM_SLEEP); | |||
175 | for (i = 0; i < nchannels; i++) { | |||
176 | channel = ffs(busmap); | |||
177 | KASSERT(channel != 0); | |||
178 | channel--; /* ffs() returns 0 if no bits set. */ | |||
179 | busmap &= ~__BIT(channel); | |||
180 | ||||
181 | ch[i].ch_channel = channel; | |||
182 | ch[i].ch_devhandle = devhandle; | |||
183 | } | |||
184 | ||||
185 | sc->sc_channels = ch; | |||
186 | sc->sc_nchannels = nchannels; | |||
187 | } | |||
188 | ||||
189 | static int | |||
61 | pcfiic_ebus_match(device_t parent, struct cfdata *match, void *aux) | 190 | pcfiic_ebus_match(device_t parent, struct cfdata *match, void *aux) | |
62 | { | 191 | { | |
63 | struct ebus_attach_args *ea = aux; | 192 | struct ebus_attach_args *ea = aux; | |
64 | char compat[32]; | 193 | char compat[32]; | |
65 | 194 | |||
66 | if (strcmp(ea->ea_name, "SUNW,envctrl") == 0 || | 195 | if (strcmp(ea->ea_name, "SUNW,envctrl") == 0 || | |
67 | strcmp(ea->ea_name, "SUNW,envctrltwo") == 0) | 196 | strcmp(ea->ea_name, "SUNW,envctrltwo") == 0) | |
68 | return (1); | 197 | return (1); | |
69 | 198 | |||
70 | if (strcmp(ea->ea_name, "i2c") != 0) | 199 | if (strcmp(ea->ea_name, "i2c") != 0) | |
71 | return (0); | 200 | return (0); | |
72 | 201 | |||
73 | if (OF_getprop(ea->ea_node, "compatible", compat, sizeof(compat)) == -1) | 202 | if (OF_getprop(ea->ea_node, "compatible", compat, sizeof(compat)) == -1) | |
74 | return (0); | 203 | return (0); | |
75 | 204 | |||
76 | if (strcmp(compat, "pcf8584") == 0 || | 205 | if (strcmp(compat, "pcf8584") == 0 || | |
77 | strcmp(compat, "i2cpcf,8584") == 0 || | 206 | strcmp(compat, "i2cpcf,8584") == 0 || | |
78 | strcmp(compat, "SUNW,i2c-pic16f747") == 0 || | 207 | strcmp(compat, "SUNW,i2c-pic16f747") == 0 || | |
79 | strcmp(compat, "SUNW,bbc-i2c") == 0) | 208 | strcmp(compat, "SUNW,bbc-i2c") == 0) | |
80 | return (1); | 209 | return (1); | |
81 | 210 | |||
82 | return (0); | 211 | return (0); | |
83 | } | 212 | } | |
84 | 213 | |||
85 | void | 214 | static void | |
86 | pcfiic_ebus_attach(device_t parent, device_t self, void *aux) | 215 | pcfiic_ebus_attach(device_t parent, device_t self, void *aux) | |
87 | { | 216 | { | |
88 | struct pcfiic_ebus_softc *esc = device_private(self); | 217 | struct pcfiic_ebus_softc *esc = device_private(self); | |
89 | struct pcfiic_softc *sc = &esc->esc_sc; | 218 | struct pcfiic_softc *sc = &esc->esc_sc; | |
90 | struct ebus_attach_args *ea = aux; | 219 | struct ebus_attach_args *ea = aux; | |
91 | char compat[32]; | 220 | char compat[32]; | |
92 | u_int64_t addr; | 221 | uint32_t addr[2]; | |
93 | u_int8_t clock = PCF8584_CLK_12 | PCF8584_SCL_90; | 222 | uint8_t clock = PCF8584_CLK_12 | PCF8584_SCL_90; | |
94 | int swapregs = 0; | 223 | int swapregs = 0; | |
95 | 224 | |||
96 | if (ea->ea_nreg < 1 || ea->ea_nreg > 2) { | 225 | if (ea->ea_nreg < 1 || ea->ea_nreg > 2) { | |
97 | printf(": expected 1 or 2 registers, got %d\n", ea->ea_nreg); | 226 | printf(": expected 1 or 2 registers, got %d\n", ea->ea_nreg); | |
98 | return; | 227 | return; | |
99 | } | 228 | } | |
100 | 229 | |||
101 | /* E450 and E250 have a different clock */ | 230 | /* E450 and E250 have a different clock */ | |
102 | if ((strcmp(ea->ea_name, "SUNW,envctrl") == 0) || | 231 | if ((strcmp(ea->ea_name, "SUNW,envctrl") == 0) || | |
103 | (strcmp(ea->ea_name, "SUNW,envctrltwo") == 0)) | 232 | (strcmp(ea->ea_name, "SUNW,envctrltwo") == 0)) | |
104 | clock = PCF8584_CLK_12 | PCF8584_SCL_45; | 233 | clock = PCF8584_CLK_12 | PCF8584_SCL_45; | |
105 | 234 | |||
106 | sc->sc_dev = self; | 235 | sc->sc_dev = self; | |
@@ -111,54 +240,56 @@ pcfiic_ebus_attach(device_t parent, devi | @@ -111,54 +240,56 @@ pcfiic_ebus_attach(device_t parent, devi | |||
111 | * the registers on their clone pcf, plus they feed | 240 | * the registers on their clone pcf, plus they feed | |
112 | * it a non-standard clock. | 241 | * it a non-standard clock. | |
113 | */ | 242 | */ | |
114 | int clk = prom_getpropint(findroot(), "clock-frequency", 0); | 243 | int clk = prom_getpropint(findroot(), "clock-frequency", 0); | |
115 | 244 | |||
116 | if (clk < 105000000) | 245 | if (clk < 105000000) | |
117 | clock = PCF8584_CLK_3 | PCF8584_SCL_90; | 246 | clock = PCF8584_CLK_3 | PCF8584_SCL_90; | |
118 | else if (clk < 160000000) | 247 | else if (clk < 160000000) | |
119 | clock = PCF8584_CLK_4_43 | PCF8584_SCL_90; | 248 | clock = PCF8584_CLK_4_43 | PCF8584_SCL_90; | |
120 | swapregs = 1; | 249 | swapregs = 1; | |
121 | } | 250 | } | |
122 | 251 | |||
123 | if (OF_getprop(ea->ea_node, "own-address", &addr, sizeof(addr)) == -1) { | 252 | if (OF_getprop(ea->ea_node, "own-address", &addr, sizeof(addr)) == -1) { | |
124 | addr = 0xaa; | 253 | addr[0] = 0; | |
125 | } else if (addr == 0x00 || addr > 0xff) { | 254 | addr[1] = 0x55 << 1; | |
255 | } else if (addr[1] == 0x00 || addr[1] > 0xff) { | |||
126 | printf(": invalid address on I2C bus"); | 256 | printf(": invalid address on I2C bus"); | |
127 | return; | 257 | return; | |
128 | } | 258 | } | |
129 | 259 | |||
130 | if (bus_space_map(ea->ea_bustag, | 260 | if (bus_space_map(ea->ea_bustag, EBUS_ADDR_FROM_REG(&ea->ea_reg[0]), | |
131 | EBUS_ADDR_FROM_REG(&ea->ea_reg[0]), | 261 | ea->ea_reg[0].size, 0, &sc->sc_ioh) == 0) { | |
132 | ea->ea_reg[0].size, 0, &sc->sc_ioh) == 0) { | |||
133 | sc->sc_iot = ea->ea_bustag; | 262 | sc->sc_iot = ea->ea_bustag; | |
134 | } else { | 263 | } else { | |
135 | printf(": can't map register space\n"); | 264 | printf(": can't map register space\n"); | |
136 | return; | 265 | return; | |
137 | } | 266 | } | |
138 | 267 | |||
139 | if (ea->ea_nreg == 2) { | 268 | if (ea->ea_nreg == 2) { | |
140 | /* | 269 | /* | |
141 | * Second register only occurs on BBC-based machines, | 270 | * Second register only occurs on BBC-based machines, | |
142 | * and is likely not prom mapped | 271 | * and is likely not prom mapped | |
143 | */ | 272 | */ | |
144 | if (bus_space_map(sc->sc_iot, EBUS_ADDR_FROM_REG(&ea->ea_reg[1]), | 273 | if (bus_space_map(sc->sc_iot, | |
145 | ea->ea_reg[1].size, 0, &sc->sc_ioh2) != 0) { | 274 | EBUS_ADDR_FROM_REG(&ea->ea_reg[1]), | |
275 | ea->ea_reg[1].size, 0, &esc->esc_ioh) != 0) { | |||
146 | printf(": can't map 2nd register space\n"); | 276 | printf(": can't map 2nd register space\n"); | |
147 | return; | 277 | return; | |
148 | } | 278 | } | |
149 | sc->sc_master = 1; | 279 | bbc_initialize_channels(esc); | |
150 | printf(": iic mux present"); | |||
151 | } | 280 | } | |
152 | 281 | |||
153 | if (ea->ea_nintr >= 1) | 282 | if (ea->ea_nintr >= 1) | |
154 | esc->esc_ih = bus_intr_establish(sc->sc_iot, ea->ea_intr[0], | 283 | esc->esc_ih = bus_intr_establish(sc->sc_iot, ea->ea_intr[0], | |
155 | IPL_BIO, pcfiic_intr, sc); | 284 | IPL_BIO, pcfiic_intr, sc); | |
156 | else | 285 | else | |
157 | esc->esc_ih = NULL; | 286 | esc->esc_ih = NULL; | |
158 | 287 | |||
159 | ||||
160 | if (esc->esc_ih == NULL) | 288 | if (esc->esc_ih == NULL) | |
161 | sc->sc_poll = 1; | 289 | sc->sc_poll = 1; | |
162 | 290 | |||
163 | pcfiic_attach(sc, (i2c_addr_t)(addr >> 1), clock, swapregs); | 291 | pcfiic_attach(sc, (i2c_addr_t)(addr[1] >> 1), clock, swapregs); | |
164 | } | 292 | } | |
293 | ||||
294 | CFATTACH_DECL_NEW(pcfiic, sizeof(struct pcfiic_ebus_softc), | |||
295 | pcfiic_ebus_match, pcfiic_ebus_attach, NULL, NULL); |
--- src/sys/dev/ic/pcf8584.c 2021/04/24 23:36:55 1.18
+++ src/sys/dev/ic/pcf8584.c 2021/05/14 06:53:14 1.18.2.1
@@ -1,141 +1,192 @@ | @@ -1,141 +1,192 @@ | |||
1 | /* $NetBSD: pcf8584.c,v 1.18 2021/04/24 23:36:55 thorpej Exp $ */ | 1 | /* $NetBSD: pcf8584.c,v 1.18.2.1 2021/05/14 06:53:14 thorpej Exp $ */ | |
2 | /* $OpenBSD: pcf8584.c,v 1.9 2007/10/20 18:46:21 kettenis Exp $ */ | 2 | /* $OpenBSD: pcf8584.c,v 1.9 2007/10/20 18:46:21 kettenis Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (c) 2021 The NetBSD Foundation, Inc. | |||
6 | * All rights reserved. | |||
7 | * | |||
8 | * This code is derived from software contributed to The NetBSD Foundation | |||
9 | * by Jason R. Thorpe. | |||
10 | * | |||
11 | * Redistribution and use in source and binary forms, with or without | |||
12 | * modification, are permitted provided that the following conditions | |||
13 | * are met: | |||
14 | * 1. Redistributions of source code must retain the above copyright | |||
15 | * notice, this list of conditions and the following disclaimer. | |||
16 | * 2. Redistributions in binary form must reproduce the above copyright | |||
17 | * notice, this list of conditions and the following disclaimer in the | |||
18 | * documentation and/or other materials provided with the distribution. | |||
19 | * | |||
20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |||
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |||
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |||
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |||
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |||
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |||
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |||
30 | * POSSIBILITY OF SUCH DAMAGE. | |||
31 | */ | |||
32 | ||||
33 | /* | |||
5 | * Copyright (c) 2006 David Gwynne <dlg@openbsd.org> | 34 | * Copyright (c) 2006 David Gwynne <dlg@openbsd.org> | |
6 | * | 35 | * | |
7 | * Permission to use, copy, modify, and distribute this software for any | 36 | * Permission to use, copy, modify, and distribute this software for any | |
8 | * purpose with or without fee is hereby granted, provided that the above | 37 | * purpose with or without fee is hereby granted, provided that the above | |
9 | * copyright notice and this permission notice appear in all copies. | 38 | * copyright notice and this permission notice appear in all copies. | |
10 | * | 39 | * | |
11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | 40 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | 41 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | 42 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | 43 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | 44 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | 45 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 46 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
18 | */ | 47 | */ | |
19 | 48 | |||
20 | #include <sys/param.h> | 49 | #include <sys/param.h> | |
21 | #include <sys/systm.h> | 50 | #include <sys/systm.h> | |
22 | #include <sys/device.h> | 51 | #include <sys/device.h> | |
23 | #include <sys/malloc.h> | 52 | #include <sys/kmem.h> | |
24 | #include <sys/kernel.h> | 53 | #include <sys/kernel.h> | |
25 | #include <sys/proc.h> | 54 | #include <sys/proc.h> | |
26 | #include <sys/bus.h> | 55 | #include <sys/bus.h> | |
27 | 56 | |||
28 | #include <dev/i2c/i2cvar.h> | 57 | #include <dev/i2c/i2cvar.h> | |
29 | 58 | |||
30 | #include <dev/ic/pcf8584var.h> | 59 | #include <dev/ic/pcf8584var.h> | |
31 | #include <dev/ic/pcf8584reg.h> | 60 | #include <dev/ic/pcf8584reg.h> | |
32 | 61 | |||
62 | #include "locators.h" | |||
63 | ||||
33 | /* Internal registers */ | 64 | /* Internal registers */ | |
34 | #define PCF8584_S0 0x00 | 65 | #define PCF8584_S0 0x00 | |
35 | #define PCF8584_S1 0x01 | 66 | #define PCF8584_S1 0x01 | |
36 | #define PCF8584_S2 0x02 | 67 | #define PCF8584_S2 0x02 | |
37 | #define PCF8584_S3 0x03 | 68 | #define PCF8584_S3 0x03 | |
38 | 69 | |||
39 | void pcfiic_init(struct pcfiic_softc *); | 70 | void pcfiic_init(struct pcfiic_softc *); | |
40 | int pcfiic_i2c_acquire_bus(void *, int); | |||
41 | void pcfiic_i2c_release_bus(void *, int); | |||
42 | int pcfiic_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, | 71 | int pcfiic_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, | |
43 | size_t, void *, size_t, int); | 72 | size_t, void *, size_t, int); | |
44 | 73 | |||
45 | int pcfiic_xmit(struct pcfiic_softc *, u_int8_t, const u_int8_t *, | 74 | int pcfiic_xmit(struct pcfiic_softc *, u_int8_t, const u_int8_t *, | |
46 | size_t, const u_int8_t *, size_t); | 75 | size_t, const u_int8_t *, size_t); | |
47 | int pcfiic_recv(struct pcfiic_softc *, u_int8_t, u_int8_t *, | 76 | int pcfiic_recv(struct pcfiic_softc *, u_int8_t, u_int8_t *, | |
48 | size_t); | 77 | size_t); | |
49 | 78 | |||
50 | u_int8_t pcfiic_read(struct pcfiic_softc *, bus_size_t); | 79 | u_int8_t pcfiic_read(struct pcfiic_softc *, bus_size_t); | |
51 | void pcfiic_write(struct pcfiic_softc *, bus_size_t, u_int8_t); | 80 | void pcfiic_write(struct pcfiic_softc *, bus_size_t, u_int8_t); | |
52 | void pcfiic_choose_bus(struct pcfiic_softc *, u_int8_t); | |||
53 | int pcfiic_wait_BBN(struct pcfiic_softc *); | 81 | int pcfiic_wait_BBN(struct pcfiic_softc *); | |
54 | int pcfiic_wait_pin(struct pcfiic_softc *, volatile u_int8_t *); | 82 | int pcfiic_wait_pin(struct pcfiic_softc *, volatile u_int8_t *); | |
55 | 83 | |||
56 | void | 84 | void | |
57 | pcfiic_init(struct pcfiic_softc *sc) | 85 | pcfiic_init(struct pcfiic_softc *sc) | |
58 | { | 86 | { | |
59 | /* init S1 */ | 87 | /* init S1 */ | |
60 | pcfiic_write(sc, PCF8584_S1, PCF8584_CTRL_PIN); | 88 | pcfiic_write(sc, PCF8584_S1, PCF8584_CTRL_PIN); | |
61 | /* own address */ | 89 | /* own address */ | |
62 | pcfiic_write(sc, PCF8584_S0, sc->sc_addr); | 90 | pcfiic_write(sc, PCF8584_S0, sc->sc_addr); | |
63 | 91 | |||
64 | /* select clock reg */ | 92 | /* select clock reg */ | |
65 | pcfiic_write(sc, PCF8584_S1, PCF8584_CTRL_PIN | PCF8584_CTRL_ES1); | 93 | pcfiic_write(sc, PCF8584_S1, PCF8584_CTRL_PIN | PCF8584_CTRL_ES1); | |
66 | pcfiic_write(sc, PCF8584_S0, sc->sc_clock); | 94 | pcfiic_write(sc, PCF8584_S0, sc->sc_clock); | |
67 | 95 | |||
68 | pcfiic_write(sc, PCF8584_S1, PCF8584_CMD_IDLE); | 96 | pcfiic_write(sc, PCF8584_S1, PCF8584_CMD_IDLE); | |
69 | 97 | |||
70 | delay(200000); /* Multi-Master mode, wait for longest i2c message */ | 98 | delay(200000); /* Multi-Master mode, wait for longest i2c message */ | |
71 | } | 99 | } | |
72 | 100 | |||
73 | void | 101 | void | |
74 | pcfiic_attach(struct pcfiic_softc *sc, i2c_addr_t addr, u_int8_t clock, | 102 | pcfiic_attach(struct pcfiic_softc *sc, i2c_addr_t addr, uint8_t clock, | |
75 | int swapregs) | 103 | int swapregs) | |
76 | { | 104 | { | |
77 | struct i2cbus_attach_args iba; | 105 | struct i2cbus_attach_args iba; | |
106 | struct pcfiic_channel *ch; | |||
107 | int i; | |||
78 | 108 | |||
79 | if (swapregs) { | 109 | if (swapregs) { | |
80 | sc->sc_regmap[PCF8584_S1] = PCF8584_S0; | 110 | sc->sc_regmap[PCF8584_S1] = PCF8584_S0; | |
81 | sc->sc_regmap[PCF8584_S0] = PCF8584_S1; | 111 | sc->sc_regmap[PCF8584_S0] = PCF8584_S1; | |
82 | } else { | 112 | } else { | |
83 | sc->sc_regmap[PCF8584_S0] = PCF8584_S0; | 113 | sc->sc_regmap[PCF8584_S0] = PCF8584_S0; | |
84 | sc->sc_regmap[PCF8584_S1] = PCF8584_S1; | 114 | sc->sc_regmap[PCF8584_S1] = PCF8584_S1; | |
85 | } | 115 | } | |
86 | sc->sc_clock = clock; | 116 | sc->sc_clock = clock; | |
87 | sc->sc_addr = addr; | 117 | sc->sc_addr = addr; | |
88 | 118 | |||
89 | pcfiic_init(sc); | 119 | pcfiic_init(sc); | |
90 | 120 | |||
91 | printf("\n"); | 121 | printf("\n"); | |
92 | 122 | |||
93 | if (sc->sc_master) | 123 | if (sc->sc_channels == NULL) { | |
94 | pcfiic_choose_bus(sc, 0); | 124 | KASSERT(sc->sc_nchannels == 0); | |
125 | ch = kmem_alloc(sizeof(*sc->sc_channels), KM_SLEEP); | |||
126 | ch->ch_channel = 0; | |||
127 | ch->ch_devhandle = device_handle(sc->sc_dev); | |||
95 | 128 | |||
96 | iic_tag_init(&sc->sc_i2c); | 129 | sc->sc_channels = ch; | |
97 | sc->sc_i2c.ic_cookie = sc; | 130 | sc->sc_nchannels = 1; | |
98 | sc->sc_i2c.ic_exec = pcfiic_i2c_exec; | 131 | } else { | |
99 | 132 | KASSERT(sc->sc_nchannels != 0); | ||
100 | bzero(&iba, sizeof(iba)); | 133 | } | |
101 | iba.iba_tag = &sc->sc_i2c; | 134 | ||
102 | config_found(sc->sc_dev, &iba, iicbus_print, CFARG_EOL); | 135 | for (i = 0; i < sc->sc_nchannels; i++) { | |
136 | int locs[I2CBUSCF_NLOCS]; | |||
137 | ||||
138 | ch = &sc->sc_channels[i]; | |||
139 | ch->ch_sc = sc; | |||
140 | iic_tag_init(&ch->ch_i2c); | |||
141 | ch->ch_i2c.ic_cookie = ch; | |||
142 | ch->ch_i2c.ic_exec = pcfiic_i2c_exec; | |||
143 | ch->ch_i2c.ic_acquire_bus = sc->sc_acquire_bus; | |||
144 | ch->ch_i2c.ic_release_bus = sc->sc_release_bus; | |||
145 | ||||
146 | locs[I2CBUSCF_BUS] = ch->ch_i2c.ic_channel; | |||
147 | ||||
148 | memset(&iba, 0, sizeof(iba)); | |||
149 | iba.iba_tag = &ch->ch_i2c; | |||
150 | config_found(sc->sc_dev, &iba, | |||
151 | sc->sc_nchannels == 1 ? iicbus_print : iicbus_print_multi, | |||
152 | CFARG_SUBMATCH, config_stdsubmatch, | |||
153 | CFARG_LOCATORS, locs, | |||
154 | CFARG_DEVHANDLE, ch->ch_devhandle, | |||
155 | CFARG_EOL); | |||
156 | } | |||
103 | } | 157 | } | |
104 | 158 | |||
105 | int | 159 | int | |
106 | pcfiic_intr(void *arg) | 160 | pcfiic_intr(void *arg) | |
107 | { | 161 | { | |
108 | return (0); | 162 | return (0); | |
109 | } | 163 | } | |
110 | 164 | |||
111 | int | 165 | int | |
112 | pcfiic_i2c_exec(void *arg, i2c_op_t op, i2c_addr_t addr, | 166 | pcfiic_i2c_exec(void *arg, i2c_op_t op, i2c_addr_t addr, | |
113 | const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags) | 167 | const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags) | |
114 | { | 168 | { | |
115 | struct pcfiic_softc *sc = arg; | 169 | struct pcfiic_softc *sc = arg; | |
116 | int ret = 0; | 170 | int ret = 0; | |
117 | 171 | |||
118 | #if 0 | 172 | #if 0 | |
119 | printf("%s: exec op: %d addr: 0x%x cmdlen: %d len: %d flags 0x%x\n", | 173 | printf("%s: exec op: %d addr: 0x%x cmdlen: %d len: %d flags 0x%x\n", | |
120 | device_xname(sc->sc_dev), op, addr, (int)cmdlen, (int)len, flags); | 174 | device_xname(sc->sc_dev), op, addr, (int)cmdlen, (int)len, flags); | |
121 | #endif | 175 | #endif | |
122 | 176 | |||
123 | if (sc->sc_poll) | 177 | if (sc->sc_poll) | |
124 | flags |= I2C_F_POLL; | 178 | flags |= I2C_F_POLL; | |
125 | 179 | |||
126 | if (sc->sc_master) | |||
127 | pcfiic_choose_bus(sc, addr >> 7); | |||
128 | ||||
129 | /* | 180 | /* | |
130 | * If we are writing, write address, cmdbuf, buf. | 181 | * If we are writing, write address, cmdbuf, buf. | |
131 | * If we are reading, write address, cmdbuf, then read address, buf. | 182 | * If we are reading, write address, cmdbuf, then read address, buf. | |
132 | */ | 183 | */ | |
133 | if (I2C_OP_WRITE_P(op)) { | 184 | if (I2C_OP_WRITE_P(op)) { | |
134 | ret = pcfiic_xmit(sc, addr & 0x7f, cmdbuf, cmdlen, buf, len); | 185 | ret = pcfiic_xmit(sc, addr & 0x7f, cmdbuf, cmdlen, buf, len); | |
135 | } else { | 186 | } else { | |
136 | if (pcfiic_xmit(sc, addr & 0x7f, cmdbuf, cmdlen, NULL, 0) != 0) | 187 | if (pcfiic_xmit(sc, addr & 0x7f, cmdbuf, cmdlen, NULL, 0) != 0) | |
137 | return (1); | 188 | return (1); | |
138 | ret = pcfiic_recv(sc, addr & 0x7f, buf, len); | 189 | ret = pcfiic_recv(sc, addr & 0x7f, buf, len); | |
139 | } | 190 | } | |
140 | return (ret); | 191 | return (ret); | |
141 | } | 192 | } | |
@@ -214,34 +265,26 @@ pcfiic_read(struct pcfiic_softc *sc, bus | @@ -214,34 +265,26 @@ pcfiic_read(struct pcfiic_softc *sc, bus | |||
214 | { | 265 | { | |
215 | bus_space_barrier(sc->sc_iot, sc->sc_ioh, sc->sc_regmap[r], 1, | 266 | bus_space_barrier(sc->sc_iot, sc->sc_ioh, sc->sc_regmap[r], 1, | |
216 | BUS_SPACE_BARRIER_READ); | 267 | BUS_SPACE_BARRIER_READ); | |
217 | return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->sc_regmap[r])); | 268 | return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->sc_regmap[r])); | |
218 | } | 269 | } | |
219 | 270 | |||
220 | void | 271 | void | |
221 | pcfiic_write(struct pcfiic_softc *sc, bus_size_t r, u_int8_t v) | 272 | pcfiic_write(struct pcfiic_softc *sc, bus_size_t r, u_int8_t v) | |
222 | { | 273 | { | |
223 | bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->sc_regmap[r], v); | 274 | bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->sc_regmap[r], v); | |
224 | (void)bus_space_read_1(sc->sc_iot, sc->sc_ioh, PCF8584_S1); | 275 | (void)bus_space_read_1(sc->sc_iot, sc->sc_ioh, PCF8584_S1); | |
225 | } | 276 | } | |
226 | 277 | |||
227 | void | |||
228 | pcfiic_choose_bus(struct pcfiic_softc *sc, u_int8_t bus) | |||
229 | { | |||
230 | bus_space_write_1(sc->sc_iot, sc->sc_ioh2, 0, bus); | |||
231 | bus_space_barrier(sc->sc_iot, sc->sc_ioh2, 0, 1, | |||
232 | BUS_SPACE_BARRIER_WRITE); | |||
233 | } | |||
234 | ||||
235 | int | 278 | int | |
236 | pcfiic_wait_BBN(struct pcfiic_softc *sc) | 279 | pcfiic_wait_BBN(struct pcfiic_softc *sc) | |
237 | { | 280 | { | |
238 | int i; | 281 | int i; | |
239 | 282 | |||
240 | for (i = 0; i < 1000; i++) { | 283 | for (i = 0; i < 1000; i++) { | |
241 | if (pcfiic_read(sc, PCF8584_S1) & PCF8584_STATUS_BBN) | 284 | if (pcfiic_read(sc, PCF8584_S1) & PCF8584_STATUS_BBN) | |
242 | return (0); | 285 | return (0); | |
243 | delay(1000); | 286 | delay(1000); | |
244 | } | 287 | } | |
245 | return (1); | 288 | return (1); | |
246 | } | 289 | } | |
247 | 290 |
--- src/sys/dev/ic/pcf8584var.h 2019/12/22 23:23:32 1.6
+++ src/sys/dev/ic/pcf8584var.h 2021/05/14 06:53:14 1.6.12.1
@@ -1,37 +1,57 @@ | @@ -1,37 +1,57 @@ | |||
1 | /* $NetBSD: pcf8584var.h,v 1.6 2019/12/22 23:23:32 thorpej Exp $ */ | 1 | /* $NetBSD: pcf8584var.h,v 1.6.12.1 2021/05/14 06:53:14 thorpej Exp $ */ | |
2 | /* $OpenBSD: pcf8584var.h,v 1.5 2007/10/20 18:46:21 kettenis Exp $ */ | 2 | /* $OpenBSD: pcf8584var.h,v 1.5 2007/10/20 18:46:21 kettenis Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (c) 2006 David Gwynne <dlg@openbsd.org> | 5 | * Copyright (c) 2006 David Gwynne <dlg@openbsd.org> | |
6 | * | 6 | * | |
7 | * Permission to use, copy, modify, and distribute this software for any | 7 | * Permission to use, copy, modify, and distribute this software for any | |
8 | * purpose with or without fee is hereby granted, provided that the above | 8 | * purpose with or without fee is hereby granted, provided that the above | |
9 | * copyright notice and this permission notice appear in all copies. | 9 | * copyright notice and this permission notice appear in all copies. | |
10 | * | 10 | * | |
11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | 15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | 16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
18 | */ | 18 | */ | |
19 | 19 | |||
20 | #ifndef _DEV_IC_PCF8584VAR_H_ | |||
21 | #define _DEV_IC_PCF8584VAR_H_ | |||
22 | ||||
23 | struct pcfiic_channel { | |||
24 | struct i2c_controller ch_i2c; | |||
25 | struct pcfiic_softc *ch_sc; | |||
26 | devhandle_t ch_devhandle; | |||
27 | int ch_channel; | |||
28 | }; | |||
29 | ||||
20 | struct pcfiic_softc { | 30 | struct pcfiic_softc { | |
21 | device_t sc_dev; | 31 | device_t sc_dev; | |
22 | 32 | |||
23 | bus_space_tag_t sc_iot; | 33 | bus_space_tag_t sc_iot; | |
24 | bus_space_handle_t sc_ioh; | 34 | bus_space_handle_t sc_ioh; | |
25 | bus_space_handle_t sc_ioh2; | 35 | uint8_t sc_addr; | |
26 | int sc_master; | 36 | uint8_t sc_clock; | |
27 | u_int8_t sc_addr; | 37 | uint8_t sc_regmap[2]; | |
28 | u_int8_t sc_clock; | |||
29 | u_int8_t sc_regmap[2]; | |||
30 | 38 | |||
31 | int sc_poll; | 39 | int sc_poll; | |
32 | 40 | |||
33 | struct i2c_controller sc_i2c; | 41 | /* | |
42 | * Some Sun clones of the this i2c controller support | |||
43 | * multiple channels. The specific attachment will | |||
44 | * initialize these fields for controllers that support | |||
45 | * this. If not, the core driver will assume a single | |||
46 | * channel. | |||
47 | */ | |||
48 | struct pcfiic_channel *sc_channels; | |||
49 | int sc_nchannels; | |||
50 | int (*sc_acquire_bus)(void *, int); | |||
51 | void (*sc_release_bus)(void *, int); | |||
34 | }; | 52 | }; | |
35 | 53 | |||
36 | void pcfiic_attach(struct pcfiic_softc *, i2c_addr_t, u_int8_t, int); | 54 | void pcfiic_attach(struct pcfiic_softc *, i2c_addr_t, uint8_t, int); | |
37 | int pcfiic_intr(void *); | 55 | int pcfiic_intr(void *); | |
56 | ||||
57 | #endif /* _DEV_IC_PCF8584VAR_H_ */ |