File: | dev/pci/nviic.c |
Warning: | line 233, column 3 Value stored to 'flags' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: nviic.c,v 1.17 2015/03/14 03:38:48 jsg 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_SMBASE10x20 0x20 |
34 | #define NVI_PCI_SMBASE20x24 0x24 |
35 | |
36 | #define NVI_OLD_PCI_SMBASE10x50 0x50 |
37 | #define NVI_OLD_PCI_SMBASE20x54 0x54 |
38 | |
39 | #define NVI_SMBASE(x)((x) & 0xfffc) ((x) & 0xfffc) |
40 | #define NVI_SMBASE_SIZE8 8 |
41 | |
42 | /* SMBus 2.0 registers */ |
43 | #define NVI_SMB_PRTCL0x00 0x00 /* protocol, PEC */ |
44 | #define NVI_SMB_STS0x01 0x01 /* status */ |
45 | #define NVI_SMB_ADDR0x02 0x02 /* address */ |
46 | #define NVI_SMB_CMD0x03 0x03 /* command */ |
47 | #define NVI_SMB_DATA(o)(0x04 + (o)) (0x04 + (o)) /* 32 data registers */ |
48 | #define NVI_SMB_BCNT0x24 0x24 /* number of data bytes */ |
49 | #define NVI_SMB_ALRM_A0x25 0x25 /* alarm address */ |
50 | #define NVI_SMB_ALRM_D0x26 0x26 /* 2 bytes alarm data */ |
51 | |
52 | #define NVI_SMB_STS_DONE0x80 0x80 |
53 | #define NVI_SMB_STS_ALRM0x40 0x40 |
54 | #define NVI_SMB_STS_RES0x20 0x20 |
55 | #define NVI_SMB_STS_STATUS0x1f 0x1f |
56 | |
57 | #define NVI_SMB_PRTCL_WRITE0x00 0x00 |
58 | #define NVI_SMB_PRTCL_READ0x01 0x01 |
59 | #define NVI_SMB_PRTCL_QUICK0x02 0x02 |
60 | #define NVI_SMB_PRTCL_BYTE0x04 0x04 |
61 | #define NVI_SMB_PRTCL_BYTE_DATA0x06 0x06 |
62 | #define NVI_SMB_PRTCL_WORD_DATA0x08 0x08 |
63 | #define NVI_SMB_PRTCL_BLOCK_DATA0x0a 0x0a |
64 | #define NVI_SMB_PRTCL_PROC_CALL0x0c 0x0c |
65 | #define NVI_SMB_PRTCL_BLOCK_PROC_CALL0x0d 0x0d |
66 | #define NVI_SMB_PRTCL_PEC0x80 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_NBUS2 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_NBUS2]; |
94 | }; |
95 | |
96 | struct cfattach nviic_ca = { |
97 | sizeof(struct nviic_softc), nviic_match, nviic_attach |
98 | }; |
99 | |
100 | struct cfdriver nviic_cd = { |
101 | NULL((void *)0), "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) ((sc)->sc_dev.dv_xname) |
113 | |
114 | const struct pci_matchid nviic_ids[] = { |
115 | { PCI_VENDOR_NVIDIA0x10de, PCI_PRODUCT_NVIDIA_NFORCE2_SMB0x0064 }, |
116 | { PCI_VENDOR_NVIDIA0x10de, PCI_PRODUCT_NVIDIA_NFORCE2_400_SMB0x0084 }, |
117 | { PCI_VENDOR_NVIDIA0x10de, PCI_PRODUCT_NVIDIA_NFORCE3_SMB0x00d4 }, |
118 | { PCI_VENDOR_NVIDIA0x10de, PCI_PRODUCT_NVIDIA_NFORCE3_250_SMB0x00e4 }, |
119 | { PCI_VENDOR_NVIDIA0x10de, PCI_PRODUCT_NVIDIA_NFORCE4_SMB0x0052 }, |
120 | { PCI_VENDOR_NVIDIA0x10de, PCI_PRODUCT_NVIDIA_MCP51_SMB0x0264 }, |
121 | { PCI_VENDOR_NVIDIA0x10de, PCI_PRODUCT_NVIDIA_MCP55_SMB0x0368 }, |
122 | { PCI_VENDOR_NVIDIA0x10de, PCI_PRODUCT_NVIDIA_MCP61_SMB0x03eb }, |
123 | { PCI_VENDOR_NVIDIA0x10de, PCI_PRODUCT_NVIDIA_MCP65_SMB0x0446 }, |
124 | { PCI_VENDOR_NVIDIA0x10de, PCI_PRODUCT_NVIDIA_MCP67_SMB0x0542 }, |
125 | { PCI_VENDOR_NVIDIA0x10de, PCI_PRODUCT_NVIDIA_MCP73_SMB0x07d8 }, |
126 | { PCI_VENDOR_NVIDIA0x10de, PCI_PRODUCT_NVIDIA_MCP77_SMB0x0752 }, |
127 | { PCI_VENDOR_NVIDIA0x10de, PCI_PRODUCT_NVIDIA_MCP79_SMB0x0aa2 }, |
128 | { PCI_VENDOR_NVIDIA0x10de, PCI_PRODUCT_NVIDIA_MCP89_SMB0x0d79 } |
129 | }; |
130 | |
131 | int |
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 |
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_NBUS2]; |
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)(((pa->pa_id) >> 16) & 0xffff)) { |
155 | case PCI_PRODUCT_NVIDIA_NFORCE2_SMB0x0064: |
156 | case PCI_PRODUCT_NVIDIA_NFORCE2_400_SMB0x0084: |
157 | case PCI_PRODUCT_NVIDIA_NFORCE3_SMB0x00d4: |
158 | case PCI_PRODUCT_NVIDIA_NFORCE3_250_SMB0x00e4: |
159 | case PCI_PRODUCT_NVIDIA_NFORCE4_SMB0x0052: |
160 | baseregs[0] = NVI_OLD_PCI_SMBASE10x50; |
161 | baseregs[1] = NVI_OLD_PCI_SMBASE20x54; |
162 | break; |
163 | default: |
164 | baseregs[0] = NVI_PCI_SMBASE10x20; |
165 | baseregs[1] = NVI_PCI_SMBASE20x24; |
166 | } |
167 | |
168 | for (i = 0; i < NVIIC_NBUS2; 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)((reg) & 0xfffc) == 0 || |
173 | bus_space_map(sc->sc_iot, NVI_SMBASE(reg)((reg) & 0xfffc), NVI_SMBASE_SIZE8, |
174 | 0, &nc->nc_ioh)) { |
175 | printf("%s: unable to map space for bus %d\n", |
176 | DEVNAME(sc)((sc)->sc_dev.dv_xname), i); |
177 | continue; |
178 | } |
179 | |
180 | nc->nc_sc = sc; |
181 | rw_init(&nc->nc_lock, "nviic")_rw_init_flags(&nc->nc_lock, "nviic", 0, ((void *)0)); |
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))__builtin_bzero((&iba), (sizeof(iba))); |
188 | iba.iba_name = "iic"; |
189 | iba.iba_tag = &nc->nc_i2c; |
190 | config_found(self, &iba, iicbus_print)config_found_sm((self), (&iba), (iicbus_print), ((void *) 0)); |
191 | } |
192 | } |
193 | |
194 | int |
195 | nviic_i2c_acquire_bus(void *arg, int flags) |
196 | { |
197 | struct nviic_controller *nc = arg; |
198 | |
199 | if (cold || (flags & I2C_F_POLL0x08)) |
200 | return (0); |
201 | |
202 | return (rw_enter(&nc->nc_lock, RW_WRITE0x0001UL | RW_INTR0x0010UL)); |
203 | } |
204 | |
205 | void |
206 | nviic_i2c_release_bus(void *arg, int flags) |
207 | { |
208 | struct nviic_controller *nc = arg; |
209 | |
210 | if (cold || (flags & I2C_F_POLL0x08)) |
211 | return; |
212 | |
213 | rw_exit(&nc->nc_lock); |
214 | } |
215 | |
216 | int |
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_POLL0x08; |
Value stored to 'flags' is never read | |
234 | |
235 | if (I2C_OP_STOP_P(op)(((int)(op) & 1) != 0) == 0 || cmdlen > 1 || len > 2) |
236 | return (1); |
237 | |
238 | /* set slave address */ |
239 | nviic_write(nc, NVI_SMB_ADDR0x02, addr << 1); |
240 | |
241 | /* set command byte */ |
242 | if (cmdlen > 0) { |
243 | b = (u_int8_t *)cmdbuf; |
244 | nviic_write(nc, NVI_SMB_CMD0x03, b[0]); |
245 | } |
246 | |
247 | b = (u_int8_t *)buf; |
248 | |
249 | /* write data */ |
250 | if (I2C_OP_WRITE_P(op)(((int)(op) & 2) != 0)) { |
251 | for (i = 0; i < len; i++) |
252 | nviic_write(nc, NVI_SMB_DATA(i)(0x04 + (i)), b[i]); |
253 | } |
254 | |
255 | switch (len) { |
256 | case 0: |
257 | protocol = NVI_SMB_PRTCL_BYTE0x04; |
258 | break; |
259 | case 1: |
260 | protocol = NVI_SMB_PRTCL_BYTE_DATA0x06; |
261 | break; |
262 | case 2: |
263 | protocol = NVI_SMB_PRTCL_WORD_DATA0x08; |
264 | break; |
265 | } |
266 | |
267 | /* set direction */ |
268 | if (I2C_OP_READ_P(op)(!(((int)(op) & 2) != 0))) |
269 | protocol |= NVI_SMB_PRTCL_READ0x01; |
270 | |
271 | /* start transaction */ |
272 | nviic_write(nc, NVI_SMB_PRTCL0x00, protocol); |
273 | |
274 | for (i = 1000; i > 0; i--) { |
275 | delay(100)(*delay_func)(100); |
276 | if (nviic_read(nc, NVI_SMB_PRTCL0x00) == 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_STS0x01); |
285 | if (sts & NVI_SMB_STS_STATUS0x1f) |
286 | return (1); |
287 | |
288 | /* read data */ |
289 | if (I2C_OP_READ_P(op)(!(((int)(op) & 2) != 0))) { |
290 | for (i = 0; i < len; i++) |
291 | b[i] = nviic_read(nc, NVI_SMB_DATA(i)(0x04 + (i))); |
292 | } |
293 | |
294 | return (0); |
295 | } |
296 | |
297 | u_int8_t |
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_READ0x01); |
304 | return (bus_space_read_1(sc->sc_iot, nc->nc_ioh, r)((sc->sc_iot)->read_1((nc->nc_ioh), (r)))); |
305 | } |
306 | |
307 | void |
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)((sc->sc_iot)->write_1((nc->nc_ioh), (r), (v))); |
313 | bus_space_barrier(sc->sc_iot, nc->nc_ioh, r, 1, |
314 | BUS_SPACE_BARRIER_WRITE0x02); |
315 | } |