xref: /openbsd-src/sys/dev/pci/nviic.c (revision 8d2c75e49a1f1e140a0efd2b93f23844e8cb679f)
1 /*	$OpenBSD: nviic.c,v 1.18 2022/03/11 18:00:51 mpi Exp $ */
2 
3 /*
4  * Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/device.h>
22 #include <sys/rwlock.h>
23 
24 #include <machine/bus.h>
25 
26 #include <dev/pci/pcidevs.h>
27 #include <dev/pci/pcireg.h>
28 #include <dev/pci/pcivar.h>
29 
30 #include <dev/i2c/i2cvar.h>
31 
32 /* PCI Configuration space registers */
33 #define NVI_PCI_SMBASE1		0x20
34 #define NVI_PCI_SMBASE2		0x24
35 
36 #define NVI_OLD_PCI_SMBASE1	0x50
37 #define NVI_OLD_PCI_SMBASE2	0x54
38 
39 #define NVI_SMBASE(x)		((x) & 0xfffc)
40 #define NVI_SMBASE_SIZE		8
41 
42 /* SMBus 2.0 registers */
43 #define NVI_SMB_PRTCL		0x00	/* protocol, PEC */
44 #define NVI_SMB_STS		0x01	/* status */
45 #define NVI_SMB_ADDR		0x02	/* address */
46 #define NVI_SMB_CMD		0x03	/* command */
47 #define NVI_SMB_DATA(o)		(0x04 + (o))	/* 32 data registers */
48 #define NVI_SMB_BCNT		0x24	/* number of data bytes */
49 #define NVI_SMB_ALRM_A		0x25	/* alarm address */
50 #define NVI_SMB_ALRM_D		0x26	/* 2 bytes alarm data */
51 
52 #define NVI_SMB_STS_DONE	0x80
53 #define NVI_SMB_STS_ALRM	0x40
54 #define NVI_SMB_STS_RES		0x20
55 #define NVI_SMB_STS_STATUS	0x1f
56 
57 #define NVI_SMB_PRTCL_WRITE	0x00
58 #define NVI_SMB_PRTCL_READ	0x01
59 #define NVI_SMB_PRTCL_QUICK	0x02
60 #define NVI_SMB_PRTCL_BYTE	0x04
61 #define NVI_SMB_PRTCL_BYTE_DATA	0x06
62 #define NVI_SMB_PRTCL_WORD_DATA	0x08
63 #define NVI_SMB_PRTCL_BLOCK_DATA 0x0a
64 #define NVI_SMB_PRTCL_PROC_CALL	0x0c
65 #define NVI_SMB_PRTCL_BLOCK_PROC_CALL 0x0d
66 #define NVI_SMB_PRTCL_PEC	0x80
67 
68 #ifdef NVIIC_DEBUG
69 #define DPRINTF(x...)		do { if (nviic_debug) printf(x); } while (0)
70 int nviic_debug = 1;
71 #else
72 #define DPRINTF(x...)		/* x */
73 #endif
74 
75 /* there are two iic busses on this pci device */
76 #define NVIIC_NBUS		2
77 
78 int		nviic_match(struct device *, void *, void *);
79 void		nviic_attach(struct device *, struct device *, void *);
80 
81 struct nviic_softc;
82 
83 struct nviic_controller {
84 	struct nviic_softc	*nc_sc;
85 	bus_space_handle_t	nc_ioh;
86 	struct rwlock		nc_lock;
87 	struct i2c_controller	nc_i2c;
88 };
89 
90 struct nviic_softc {
91 	struct device		sc_dev;
92 	bus_space_tag_t		sc_iot;
93 	struct nviic_controller	sc_nc[NVIIC_NBUS];
94 };
95 
96 const struct cfattach nviic_ca = {
97 	sizeof(struct nviic_softc), nviic_match, nviic_attach
98 };
99 
100 struct cfdriver nviic_cd = {
101 	NULL, "nviic", DV_DULL
102 };
103 
104 int		nviic_i2c_acquire_bus(void *, int);
105 void		nviic_i2c_release_bus(void *, int);
106 int		nviic_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *,
107 		    size_t, void *, size_t, int);
108 
109 u_int8_t	nviic_read(struct nviic_controller *, bus_size_t);
110 void		nviic_write(struct nviic_controller *, bus_size_t, u_int8_t);
111 
112 #define DEVNAME(s)		((sc)->sc_dev.dv_xname)
113 
114 const struct pci_matchid nviic_ids[] = {
115 	{ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_SMB },
116 	{ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_400_SMB },
117 	{ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_SMB },
118 	{ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_250_SMB },
119 	{ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE4_SMB },
120 	{ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP51_SMB },
121 	{ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP55_SMB },
122 	{ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_SMB },
123 	{ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_SMB },
124 	{ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_SMB },
125 	{ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_SMB },
126 	{ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_SMB },
127 	{ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_SMB },
128 	{ PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP89_SMB }
129 };
130 
131 int
nviic_match(struct device * parent,void * match,void * aux)132 nviic_match(struct device *parent, void *match, void *aux)
133 {
134 	return (pci_matchbyid(aux, nviic_ids,
135 	    sizeof(nviic_ids) / sizeof(nviic_ids[0])));
136 }
137 
138 void
nviic_attach(struct device * parent,struct device * self,void * aux)139 nviic_attach(struct device *parent, struct device *self, void *aux)
140 {
141 	struct nviic_softc		*sc = (struct nviic_softc *)self;
142 	struct pci_attach_args		*pa = aux;
143 	struct nviic_controller		*nc;
144 	struct i2cbus_attach_args	iba;
145 	int				baseregs[NVIIC_NBUS];
146 	pcireg_t			reg;
147 	int				i;
148 
149 	sc->sc_iot = pa->pa_iot;
150 
151 	printf("\n");
152 
153 	/* Older chipsets used non-standard BARs */
154 	switch (PCI_PRODUCT(pa->pa_id)) {
155 	case PCI_PRODUCT_NVIDIA_NFORCE2_SMB:
156 	case PCI_PRODUCT_NVIDIA_NFORCE2_400_SMB:
157 	case PCI_PRODUCT_NVIDIA_NFORCE3_SMB:
158 	case PCI_PRODUCT_NVIDIA_NFORCE3_250_SMB:
159 	case PCI_PRODUCT_NVIDIA_NFORCE4_SMB:
160 		baseregs[0] = NVI_OLD_PCI_SMBASE1;
161 		baseregs[1] = NVI_OLD_PCI_SMBASE2;
162 		break;
163 	default:
164 		baseregs[0] = NVI_PCI_SMBASE1;
165 		baseregs[1] = NVI_PCI_SMBASE2;
166 	}
167 
168 	for (i = 0; i < NVIIC_NBUS; i++) {
169 		nc = &sc->sc_nc[i];
170 
171 		reg = pci_conf_read(pa->pa_pc, pa->pa_tag, baseregs[i]);
172 		if (NVI_SMBASE(reg) == 0 ||
173 		    bus_space_map(sc->sc_iot, NVI_SMBASE(reg), NVI_SMBASE_SIZE,
174 		    0, &nc->nc_ioh)) {
175 			printf("%s: unable to map space for bus %d\n",
176 			    DEVNAME(sc), i);
177 			continue;
178 		}
179 
180 		nc->nc_sc = sc;
181 		rw_init(&nc->nc_lock, "nviic");
182 		nc->nc_i2c.ic_cookie = nc;
183 		nc->nc_i2c.ic_acquire_bus = nviic_i2c_acquire_bus;
184 		nc->nc_i2c.ic_release_bus = nviic_i2c_release_bus;
185 		nc->nc_i2c.ic_exec = nviic_i2c_exec;
186 
187 		bzero(&iba, sizeof(iba));
188 		iba.iba_name = "iic";
189 		iba.iba_tag = &nc->nc_i2c;
190 		config_found(self, &iba, iicbus_print);
191 	}
192 }
193 
194 int
nviic_i2c_acquire_bus(void * arg,int flags)195 nviic_i2c_acquire_bus(void *arg, int flags)
196 {
197 	struct nviic_controller		*nc = arg;
198 
199 	if (cold || (flags & I2C_F_POLL))
200 		return (0);
201 
202 	return (rw_enter(&nc->nc_lock, RW_WRITE | RW_INTR));
203 }
204 
205 void
nviic_i2c_release_bus(void * arg,int flags)206 nviic_i2c_release_bus(void *arg, int flags)
207 {
208 	struct nviic_controller		*nc = arg;
209 
210 	if (cold || (flags & I2C_F_POLL))
211 		return;
212 
213 	rw_exit(&nc->nc_lock);
214 }
215 
216 int
nviic_i2c_exec(void * arg,i2c_op_t op,i2c_addr_t addr,const void * cmdbuf,size_t cmdlen,void * buf,size_t len,int flags)217 nviic_i2c_exec(void *arg, i2c_op_t op, i2c_addr_t addr,
218     const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags)
219 {
220 	struct nviic_controller		*nc = arg;
221 #ifdef NVIIC_DEBUG
222 	struct nviic_softc		*sc = nc->nc_sc;
223 #endif
224 	u_int8_t			protocol;
225 	u_int8_t			*b;
226 	u_int8_t			sts;
227 	int				i;
228 
229 	DPRINTF("%s: exec op: %d addr: 0x%x cmdlen: %d len: %d flags 0x%x\n",
230 	    DEVNAME(sc), op, addr, cmdlen, len, flags);
231 
232 	if (cold)
233 		flags |= I2C_F_POLL;
234 
235 	if (I2C_OP_STOP_P(op) == 0 || cmdlen > 1 || len > 2)
236 		return (1);
237 
238 	/* set slave address */
239 	nviic_write(nc, NVI_SMB_ADDR, addr << 1);
240 
241 	/* set command byte */
242 	if (cmdlen > 0) {
243 		b = (u_int8_t *)cmdbuf;
244 		nviic_write(nc, NVI_SMB_CMD, b[0]);
245 	}
246 
247 	b = (u_int8_t *)buf;
248 
249 	/* write data */
250 	if (I2C_OP_WRITE_P(op)) {
251 		for (i = 0; i < len; i++)
252 			nviic_write(nc, NVI_SMB_DATA(i), b[i]);
253 	}
254 
255 	switch (len) {
256 	case 0:
257 		protocol = NVI_SMB_PRTCL_BYTE;
258 		break;
259 	case 1:
260 		protocol = NVI_SMB_PRTCL_BYTE_DATA;
261 		break;
262 	case 2:
263 		protocol = NVI_SMB_PRTCL_WORD_DATA;
264 		break;
265 	}
266 
267 	/* set direction */
268 	if (I2C_OP_READ_P(op))
269 		protocol |= NVI_SMB_PRTCL_READ;
270 
271 	/* start transaction */
272 	nviic_write(nc, NVI_SMB_PRTCL, protocol);
273 
274 	for (i = 1000; i > 0; i--) {
275 		delay(100);
276 		if (nviic_read(nc, NVI_SMB_PRTCL) == 0)
277 			break;
278 	}
279 	if (i == 0) {
280 		DPRINTF("%s: timeout\n", DEVNAME(sc));
281 		return (1);
282 	}
283 
284 	sts = nviic_read(nc, NVI_SMB_STS);
285 	if (sts & NVI_SMB_STS_STATUS)
286 		return (1);
287 
288 	/* read data */
289 	if (I2C_OP_READ_P(op)) {
290 		for (i = 0; i < len; i++)
291 			b[i] = nviic_read(nc, NVI_SMB_DATA(i));
292 	}
293 
294 	return (0);
295 }
296 
297 u_int8_t
nviic_read(struct nviic_controller * nc,bus_size_t r)298 nviic_read(struct nviic_controller *nc, bus_size_t r)
299 {
300 	struct nviic_softc		*sc = nc->nc_sc;
301 
302 	bus_space_barrier(sc->sc_iot, nc->nc_ioh, r, 1,
303 	    BUS_SPACE_BARRIER_READ);
304 	return (bus_space_read_1(sc->sc_iot, nc->nc_ioh, r));
305 }
306 
307 void
nviic_write(struct nviic_controller * nc,bus_size_t r,u_int8_t v)308 nviic_write(struct nviic_controller *nc, bus_size_t r, u_int8_t v)
309 {
310 	struct nviic_softc		*sc = nc->nc_sc;
311 
312 	bus_space_write_1(sc->sc_iot, nc->nc_ioh, r, v);
313 	bus_space_barrier(sc->sc_iot, nc->nc_ioh, r, 1,
314 	    BUS_SPACE_BARRIER_WRITE);
315 }
316