| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: if_bwfm_sdio.c,v 1.1 2017/11/07 16:30:32 khorben Exp $ */ | | 1 | /* $NetBSD: if_bwfm_sdio.c,v 1.2 2018/03/11 00:17:28 khorben Exp $ */ |
2 | /* $OpenBSD: if_bwfm_sdio.c,v 1.1 2017/10/11 17:19:50 patrick Exp $ */ | | 2 | /* $OpenBSD: if_bwfm_sdio.c,v 1.1 2017/10/11 17:19:50 patrick Exp $ */ |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2010-2016 Broadcom Corporation | | 4 | * Copyright (c) 2010-2016 Broadcom Corporation |
5 | * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se> | | 5 | * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se> |
6 | * | | 6 | * |
7 | * Permission to use, copy, modify, and/or distribute this software for any | | 7 | * Permission to use, copy, modify, and/or 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 |
| @@ -63,26 +63,27 @@ static int bwfm_debug = 2; | | | @@ -63,26 +63,27 @@ static int bwfm_debug = 2; |
63 | | | 63 | |
64 | #define DEVNAME(sc) device_xname((sc)->sc_sc.sc_dev) | | 64 | #define DEVNAME(sc) device_xname((sc)->sc_sc.sc_dev) |
65 | | | 65 | |
66 | struct bwfm_sdio_softc { | | 66 | struct bwfm_sdio_softc { |
67 | struct bwfm_softc sc_sc; | | 67 | struct bwfm_softc sc_sc; |
68 | struct sdmmc_function **sc_sf; | | 68 | struct sdmmc_function **sc_sf; |
69 | uint32_t sc_bar0; | | 69 | uint32_t sc_bar0; |
70 | }; | | 70 | }; |
71 | | | 71 | |
72 | int bwfm_sdio_match(device_t, cfdata_t, void *); | | 72 | int bwfm_sdio_match(device_t, cfdata_t, void *); |
73 | void bwfm_sdio_attach(device_t, struct device *, void *); | | 73 | void bwfm_sdio_attach(device_t, struct device *, void *); |
74 | int bwfm_sdio_detach(device_t, int); | | 74 | int bwfm_sdio_detach(device_t, int); |
75 | | | 75 | |
| | | 76 | void bwfm_sdio_backplane(struct bwfm_sdio_softc *, uint32_t); |
76 | uint8_t bwfm_sdio_read_1(struct bwfm_sdio_softc *, uint32_t); | | 77 | uint8_t bwfm_sdio_read_1(struct bwfm_sdio_softc *, uint32_t); |
77 | uint32_t bwfm_sdio_read_4(struct bwfm_sdio_softc *, uint32_t); | | 78 | uint32_t bwfm_sdio_read_4(struct bwfm_sdio_softc *, uint32_t); |
78 | void bwfm_sdio_write_1(struct bwfm_sdio_softc *, uint32_t, | | 79 | void bwfm_sdio_write_1(struct bwfm_sdio_softc *, uint32_t, |
79 | uint8_t); | | 80 | uint8_t); |
80 | void bwfm_sdio_write_4(struct bwfm_sdio_softc *, uint32_t, | | 81 | void bwfm_sdio_write_4(struct bwfm_sdio_softc *, uint32_t, |
81 | uint32_t); | | 82 | uint32_t); |
82 | | | 83 | |
83 | uint32_t bwfm_sdio_buscore_read(struct bwfm_softc *, uint32_t); | | 84 | uint32_t bwfm_sdio_buscore_read(struct bwfm_softc *, uint32_t); |
84 | void bwfm_sdio_buscore_write(struct bwfm_softc *, uint32_t, | | 85 | void bwfm_sdio_buscore_write(struct bwfm_softc *, uint32_t, |
85 | uint32_t); | | 86 | uint32_t); |
86 | int bwfm_sdio_buscore_prepare(struct bwfm_softc *); | | 87 | int bwfm_sdio_buscore_prepare(struct bwfm_softc *); |
87 | void bwfm_sdio_buscore_activate(struct bwfm_softc *, uint32_t); | | 88 | void bwfm_sdio_buscore_activate(struct bwfm_softc *, uint32_t); |
88 | | | 89 | |
| @@ -208,26 +209,41 @@ err: | | | @@ -208,26 +209,41 @@ err: |
208 | | | 209 | |
209 | int | | 210 | int |
210 | bwfm_sdio_detach(struct device *self, int flags) | | 211 | bwfm_sdio_detach(struct device *self, int flags) |
211 | { | | 212 | { |
212 | struct bwfm_sdio_softc *sc = (struct bwfm_sdio_softc *)self; | | 213 | struct bwfm_sdio_softc *sc = (struct bwfm_sdio_softc *)self; |
213 | | | 214 | |
214 | bwfm_detach(&sc->sc_sc, flags); | | 215 | bwfm_detach(&sc->sc_sc, flags); |
215 | | | 216 | |
216 | free(sc->sc_sf, M_DEVBUF); | | 217 | free(sc->sc_sf, M_DEVBUF); |
217 | | | 218 | |
218 | return 0; | | 219 | return 0; |
219 | } | | 220 | } |
220 | | | 221 | |
| | | 222 | void |
| | | 223 | bwfm_sdio_backplane(struct bwfm_sdio_softc *sc, uint32_t bar0) |
| | | 224 | { |
| | | 225 | if (sc->sc_bar0 == bar0) |
| | | 226 | return; |
| | | 227 | |
| | | 228 | bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRLOW, |
| | | 229 | (bar0 >> 8) & 0x80); |
| | | 230 | bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRMID, |
| | | 231 | (bar0 >> 16) & 0xff); |
| | | 232 | bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRHIGH, |
| | | 233 | (bar0 >> 24) & 0xff); |
| | | 234 | sc->sc_bar0 = bar0; |
| | | 235 | } |
| | | 236 | |
221 | uint8_t | | 237 | uint8_t |
222 | bwfm_sdio_read_1(struct bwfm_sdio_softc *sc, uint32_t addr) | | 238 | bwfm_sdio_read_1(struct bwfm_sdio_softc *sc, uint32_t addr) |
223 | { | | 239 | { |
224 | struct sdmmc_function *sf; | | 240 | struct sdmmc_function *sf; |
225 | uint8_t rv; | | 241 | uint8_t rv; |
226 | | | 242 | |
227 | /* | | 243 | /* |
228 | * figure out how to read the register based on address range | | 244 | * figure out how to read the register based on address range |
229 | * 0x00 ~ 0x7FF: function 0 CCCR and FBR | | 245 | * 0x00 ~ 0x7FF: function 0 CCCR and FBR |
230 | * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers | | 246 | * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers |
231 | * The rest: function 1 silicon backplane core registers | | 247 | * The rest: function 1 silicon backplane core registers |
232 | */ | | 248 | */ |
233 | if ((addr & ~0x7ff) == 0) | | 249 | if ((addr & ~0x7ff) == 0) |
| @@ -236,35 +252,27 @@ bwfm_sdio_read_1(struct bwfm_sdio_softc | | | @@ -236,35 +252,27 @@ bwfm_sdio_read_1(struct bwfm_sdio_softc |
236 | sf = sc->sc_sf[1]; | | 252 | sf = sc->sc_sf[1]; |
237 | | | 253 | |
238 | rv = sdmmc_io_read_1(sf, addr); | | 254 | rv = sdmmc_io_read_1(sf, addr); |
239 | return rv; | | 255 | return rv; |
240 | } | | 256 | } |
241 | | | 257 | |
242 | uint32_t | | 258 | uint32_t |
243 | bwfm_sdio_read_4(struct bwfm_sdio_softc *sc, uint32_t addr) | | 259 | bwfm_sdio_read_4(struct bwfm_sdio_softc *sc, uint32_t addr) |
244 | { | | 260 | { |
245 | struct sdmmc_function *sf; | | 261 | struct sdmmc_function *sf; |
246 | uint32_t bar0 = addr & ~BWFM_SDIO_SB_OFT_ADDR_MASK; | | 262 | uint32_t bar0 = addr & ~BWFM_SDIO_SB_OFT_ADDR_MASK; |
247 | uint32_t rv; | | 263 | uint32_t rv; |
248 | | | 264 | |
249 | if (sc->sc_bar0 != bar0) { | | 265 | bwfm_sdio_backplane(sc, bar0); |
250 | bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRLOW, | | | |
251 | (bar0 >> 8) & 0x80); | | | |
252 | bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRMID, | | | |
253 | (bar0 >> 16) & 0xff); | | | |
254 | bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRHIGH, | | | |
255 | (bar0 >> 24) & 0xff); | | | |
256 | sc->sc_bar0 = bar0; | | | |
257 | } | | | |
258 | | | 266 | |
259 | addr &= BWFM_SDIO_SB_OFT_ADDR_MASK; | | 267 | addr &= BWFM_SDIO_SB_OFT_ADDR_MASK; |
260 | addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG; | | 268 | addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG; |
261 | | | 269 | |
262 | /* | | 270 | /* |
263 | * figure out how to read the register based on address range | | 271 | * figure out how to read the register based on address range |
264 | * 0x00 ~ 0x7FF: function 0 CCCR and FBR | | 272 | * 0x00 ~ 0x7FF: function 0 CCCR and FBR |
265 | * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers | | 273 | * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers |
266 | * The rest: function 1 silicon backplane core registers | | 274 | * The rest: function 1 silicon backplane core registers |
267 | */ | | 275 | */ |
268 | if ((addr & ~0x7ff) == 0) | | 276 | if ((addr & ~0x7ff) == 0) |
269 | sf = sc->sc_sf[0]; | | 277 | sf = sc->sc_sf[0]; |
270 | else | | 278 | else |
| @@ -289,35 +297,27 @@ bwfm_sdio_write_1(struct bwfm_sdio_softc | | | @@ -289,35 +297,27 @@ bwfm_sdio_write_1(struct bwfm_sdio_softc |
289 | sf = sc->sc_sf[0]; | | 297 | sf = sc->sc_sf[0]; |
290 | else | | 298 | else |
291 | sf = sc->sc_sf[1]; | | 299 | sf = sc->sc_sf[1]; |
292 | | | 300 | |
293 | sdmmc_io_write_1(sf, addr, data); | | 301 | sdmmc_io_write_1(sf, addr, data); |
294 | } | | 302 | } |
295 | | | 303 | |
296 | void | | 304 | void |
297 | bwfm_sdio_write_4(struct bwfm_sdio_softc *sc, uint32_t addr, uint32_t data) | | 305 | bwfm_sdio_write_4(struct bwfm_sdio_softc *sc, uint32_t addr, uint32_t data) |
298 | { | | 306 | { |
299 | struct sdmmc_function *sf; | | 307 | struct sdmmc_function *sf; |
300 | uint32_t bar0 = addr & ~BWFM_SDIO_SB_OFT_ADDR_MASK; | | 308 | uint32_t bar0 = addr & ~BWFM_SDIO_SB_OFT_ADDR_MASK; |
301 | | | 309 | |
302 | if (sc->sc_bar0 != bar0) { | | 310 | bwfm_sdio_backplane(sc, bar0); |
303 | bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRLOW, | | | |
304 | (bar0 >> 8) & 0x80); | | | |
305 | bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRMID, | | | |
306 | (bar0 >> 16) & 0xff); | | | |
307 | bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_SBADDRHIGH, | | | |
308 | (bar0 >> 24) & 0xff); | | | |
309 | sc->sc_bar0 = bar0; | | | |
310 | } | | | |
311 | | | 311 | |
312 | addr &= BWFM_SDIO_SB_OFT_ADDR_MASK; | | 312 | addr &= BWFM_SDIO_SB_OFT_ADDR_MASK; |
313 | addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG; | | 313 | addr |= BWFM_SDIO_SB_ACCESS_2_4B_FLAG; |
314 | | | 314 | |
315 | /* | | 315 | /* |
316 | * figure out how to read the register based on address range | | 316 | * figure out how to read the register based on address range |
317 | * 0x00 ~ 0x7FF: function 0 CCCR and FBR | | 317 | * 0x00 ~ 0x7FF: function 0 CCCR and FBR |
318 | * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers | | 318 | * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers |
319 | * The rest: function 1 silicon backplane core registers | | 319 | * The rest: function 1 silicon backplane core registers |
320 | */ | | 320 | */ |
321 | if ((addr & ~0x7ff) == 0) | | 321 | if ((addr & ~0x7ff) == 0) |
322 | sf = sc->sc_sf[0]; | | 322 | sf = sc->sc_sf[0]; |
323 | else | | 323 | else |