Fri May 14 06:53:14 2021 UTC ()
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.


(thorpej)
diff -r1.7 -r1.7.6.1 src/sys/arch/sparc64/dev/pcfiic_ebus.c
diff -r1.18 -r1.18.2.1 src/sys/dev/ic/pcf8584.c
diff -r1.6 -r1.6.12.1 src/sys/dev/ic/pcf8584var.h

cvs diff -r1.7 -r1.7.6.1 src/sys/arch/sparc64/dev/pcfiic_ebus.c (expand / switch to unified diff)

--- 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
47int pcfiic_ebus_match(device_t, struct cfdata *, void *); 
48void pcfiic_ebus_attach(device_t, device_t, void *); 
49 
50struct pcfiic_ebus_softc { 77struct 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
57CFATTACH_DECL_NEW(pcfiic, sizeof(struct pcfiic_ebus_softc), 86static void
58 pcfiic_ebus_match, pcfiic_ebus_attach, NULL, NULL); 87bbc_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
 94static int
 95bbc_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
 113static void
 114bbc_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
60int 120 mutex_exit(&esc->esc_ctrl_lock);
 121}
 122
 123static void
 124bbc_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
 189static int
61pcfiic_ebus_match(device_t parent, struct cfdata *match, void *aux) 190pcfiic_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
85void 214static void
86pcfiic_ebus_attach(device_t parent, device_t self, void *aux) 215pcfiic_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
 294CFATTACH_DECL_NEW(pcfiic, sizeof(struct pcfiic_ebus_softc),
 295 pcfiic_ebus_match, pcfiic_ebus_attach, NULL, NULL);

cvs diff -r1.18 -r1.18.2.1 src/sys/dev/ic/pcf8584.c (expand / switch to unified diff)

--- 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
39void pcfiic_init(struct pcfiic_softc *); 70void pcfiic_init(struct pcfiic_softc *);
40int pcfiic_i2c_acquire_bus(void *, int); 
41void pcfiic_i2c_release_bus(void *, int); 
42int pcfiic_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, 71int 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
45int pcfiic_xmit(struct pcfiic_softc *, u_int8_t, const u_int8_t *, 74int 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);
47int pcfiic_recv(struct pcfiic_softc *, u_int8_t, u_int8_t *, 76int pcfiic_recv(struct pcfiic_softc *, u_int8_t, u_int8_t *,
48 size_t); 77 size_t);
49 78
50u_int8_t pcfiic_read(struct pcfiic_softc *, bus_size_t); 79u_int8_t pcfiic_read(struct pcfiic_softc *, bus_size_t);
51void pcfiic_write(struct pcfiic_softc *, bus_size_t, u_int8_t); 80void pcfiic_write(struct pcfiic_softc *, bus_size_t, u_int8_t);
52void pcfiic_choose_bus(struct pcfiic_softc *, u_int8_t); 
53int pcfiic_wait_BBN(struct pcfiic_softc *); 81int pcfiic_wait_BBN(struct pcfiic_softc *);
54int pcfiic_wait_pin(struct pcfiic_softc *, volatile u_int8_t *); 82int pcfiic_wait_pin(struct pcfiic_softc *, volatile u_int8_t *);
55 83
56void 84void
57pcfiic_init(struct pcfiic_softc *sc) 85pcfiic_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
73void 101void
74pcfiic_attach(struct pcfiic_softc *sc, i2c_addr_t addr, u_int8_t clock, 102pcfiic_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
105int 159int
106pcfiic_intr(void *arg) 160pcfiic_intr(void *arg)
107{ 161{
108 return (0); 162 return (0);
109} 163}
110 164
111int 165int
112pcfiic_i2c_exec(void *arg, i2c_op_t op, i2c_addr_t addr, 166pcfiic_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
220void 271void
221pcfiic_write(struct pcfiic_softc *sc, bus_size_t r, u_int8_t v) 272pcfiic_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
227void 
228pcfiic_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 
235int 278int
236pcfiic_wait_BBN(struct pcfiic_softc *sc) 279pcfiic_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

cvs diff -r1.6 -r1.6.12.1 src/sys/dev/ic/pcf8584var.h (expand / switch to unified diff)

--- 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
 23struct 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
20struct pcfiic_softc { 30struct 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
36void pcfiic_attach(struct pcfiic_softc *, i2c_addr_t, u_int8_t, int); 54void pcfiic_attach(struct pcfiic_softc *, i2c_addr_t, uint8_t, int);
37int pcfiic_intr(void *); 55int pcfiic_intr(void *);
 56
 57#endif /* _DEV_IC_PCF8584VAR_H_ */