0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include "ssb_private.h"
0016
0017 #include <linux/ssb/ssb.h>
0018 #include <linux/delay.h>
0019 #include <linux/io.h>
0020 #include <linux/etherdevice.h>
0021 #include <linux/mmc/sdio_func.h>
0022
0023
0024 #define SSB_VERBOSE_SDIOCORESWITCH_DEBUG 0
0025
0026
0027
0028 #define SSB_SDIO_CIS 0x80
0029 #define SSB_SDIO_CIS_SROMREV 0x00
0030 #define SSB_SDIO_CIS_ID 0x01
0031 #define SSB_SDIO_CIS_BOARDREV 0x02
0032 #define SSB_SDIO_CIS_PA 0x03
0033 #define SSB_SDIO_CIS_PA_PA0B0_LO 0
0034 #define SSB_SDIO_CIS_PA_PA0B0_HI 1
0035 #define SSB_SDIO_CIS_PA_PA0B1_LO 2
0036 #define SSB_SDIO_CIS_PA_PA0B1_HI 3
0037 #define SSB_SDIO_CIS_PA_PA0B2_LO 4
0038 #define SSB_SDIO_CIS_PA_PA0B2_HI 5
0039 #define SSB_SDIO_CIS_PA_ITSSI 6
0040 #define SSB_SDIO_CIS_PA_MAXPOW 7
0041 #define SSB_SDIO_CIS_OEMNAME 0x04
0042 #define SSB_SDIO_CIS_CCODE 0x05
0043 #define SSB_SDIO_CIS_ANTENNA 0x06
0044 #define SSB_SDIO_CIS_ANTGAIN 0x07
0045 #define SSB_SDIO_CIS_BFLAGS 0x08
0046 #define SSB_SDIO_CIS_LEDS 0x09
0047
0048 #define CISTPL_FUNCE_LAN_NODE_ID 0x04
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059 #define SBSDIO_FUNC1_SBADDRLOW 0x1000a
0060 #define SBSDIO_FUNC1_SBADDRMID 0x1000b
0061 #define SBSDIO_FUNC1_SBADDRHIGH 0x1000c
0062
0063
0064 #define SBSDIO_SBADDRLOW_MASK 0x80
0065 #define SBSDIO_SBADDRMID_MASK 0xff
0066 #define SBSDIO_SBADDRHIGH_MASK 0xff
0067
0068 #define SBSDIO_SB_OFT_ADDR_MASK 0x7FFF
0069
0070
0071 #define SBSDIO_SB_ACCESS_2_4B_FLAG 0x8000
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104 static inline struct device *ssb_sdio_dev(struct ssb_bus *bus)
0105 {
0106 return &bus->host_sdio->dev;
0107 }
0108
0109
0110 static int ssb_sdio_writeb(struct ssb_bus *bus, unsigned int addr, u8 val)
0111 {
0112 int error = 0;
0113
0114 sdio_writeb(bus->host_sdio, val, addr, &error);
0115 if (unlikely(error)) {
0116 dev_dbg(ssb_sdio_dev(bus), "%08X <- %02x, error %d\n",
0117 addr, val, error);
0118 }
0119
0120 return error;
0121 }
0122
0123 #if 0
0124 static u8 ssb_sdio_readb(struct ssb_bus *bus, unsigned int addr)
0125 {
0126 u8 val;
0127 int error = 0;
0128
0129 val = sdio_readb(bus->host_sdio, addr, &error);
0130 if (unlikely(error)) {
0131 dev_dbg(ssb_sdio_dev(bus), "%08X -> %02x, error %d\n",
0132 addr, val, error);
0133 }
0134
0135 return val;
0136 }
0137 #endif
0138
0139
0140 static int ssb_sdio_set_sbaddr_window(struct ssb_bus *bus, u32 address)
0141 {
0142 int error;
0143
0144 error = ssb_sdio_writeb(bus, SBSDIO_FUNC1_SBADDRLOW,
0145 (address >> 8) & SBSDIO_SBADDRLOW_MASK);
0146 if (error)
0147 goto out;
0148 error = ssb_sdio_writeb(bus, SBSDIO_FUNC1_SBADDRMID,
0149 (address >> 16) & SBSDIO_SBADDRMID_MASK);
0150 if (error)
0151 goto out;
0152 error = ssb_sdio_writeb(bus, SBSDIO_FUNC1_SBADDRHIGH,
0153 (address >> 24) & SBSDIO_SBADDRHIGH_MASK);
0154 if (error)
0155 goto out;
0156 bus->sdio_sbaddr = address;
0157 out:
0158 if (error) {
0159 dev_dbg(ssb_sdio_dev(bus), "failed to set address window"
0160 " to 0x%08x, error %d\n", address, error);
0161 }
0162
0163 return error;
0164 }
0165
0166
0167 u32 ssb_sdio_scan_read32(struct ssb_bus *bus, u16 offset)
0168 {
0169 u32 val;
0170 int error;
0171
0172 sdio_claim_host(bus->host_sdio);
0173 val = sdio_readl(bus->host_sdio, offset, &error);
0174 sdio_release_host(bus->host_sdio);
0175 if (unlikely(error)) {
0176 dev_dbg(ssb_sdio_dev(bus), "%04X:%04X > %08x, error %d\n",
0177 bus->sdio_sbaddr >> 16, offset, val, error);
0178 }
0179
0180 return val;
0181 }
0182
0183
0184 int ssb_sdio_scan_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
0185 {
0186 u32 sbaddr;
0187 int error;
0188
0189 sbaddr = (coreidx * SSB_CORE_SIZE) + SSB_ENUM_BASE;
0190 sdio_claim_host(bus->host_sdio);
0191 error = ssb_sdio_set_sbaddr_window(bus, sbaddr);
0192 sdio_release_host(bus->host_sdio);
0193 if (error) {
0194 dev_err(ssb_sdio_dev(bus), "failed to switch to core %u,"
0195 " error %d\n", coreidx, error);
0196 goto out;
0197 }
0198 out:
0199 return error;
0200 }
0201
0202
0203 static int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev)
0204 {
0205 u8 coreidx = dev->core_index;
0206 u32 sbaddr;
0207 int error = 0;
0208
0209 sbaddr = (coreidx * SSB_CORE_SIZE) + SSB_ENUM_BASE;
0210 if (unlikely(bus->sdio_sbaddr != sbaddr)) {
0211 #if SSB_VERBOSE_SDIOCORESWITCH_DEBUG
0212 dev_info(ssb_sdio_dev(bus),
0213 "switching to %s core, index %d\n",
0214 ssb_core_name(dev->id.coreid), coreidx);
0215 #endif
0216 error = ssb_sdio_set_sbaddr_window(bus, sbaddr);
0217 if (error) {
0218 dev_dbg(ssb_sdio_dev(bus), "failed to switch to"
0219 " core %u, error %d\n", coreidx, error);
0220 goto out;
0221 }
0222 bus->mapped_device = dev;
0223 }
0224
0225 out:
0226 return error;
0227 }
0228
0229 static u8 ssb_sdio_read8(struct ssb_device *dev, u16 offset)
0230 {
0231 struct ssb_bus *bus = dev->bus;
0232 u8 val = 0xff;
0233 int error = 0;
0234
0235 sdio_claim_host(bus->host_sdio);
0236 if (unlikely(ssb_sdio_switch_core(bus, dev)))
0237 goto out;
0238 offset |= bus->sdio_sbaddr & 0xffff;
0239 offset &= SBSDIO_SB_OFT_ADDR_MASK;
0240 val = sdio_readb(bus->host_sdio, offset, &error);
0241 if (error) {
0242 dev_dbg(ssb_sdio_dev(bus), "%04X:%04X > %02x, error %d\n",
0243 bus->sdio_sbaddr >> 16, offset, val, error);
0244 }
0245 out:
0246 sdio_release_host(bus->host_sdio);
0247
0248 return val;
0249 }
0250
0251 static u16 ssb_sdio_read16(struct ssb_device *dev, u16 offset)
0252 {
0253 struct ssb_bus *bus = dev->bus;
0254 u16 val = 0xffff;
0255 int error = 0;
0256
0257 sdio_claim_host(bus->host_sdio);
0258 if (unlikely(ssb_sdio_switch_core(bus, dev)))
0259 goto out;
0260 offset |= bus->sdio_sbaddr & 0xffff;
0261 offset &= SBSDIO_SB_OFT_ADDR_MASK;
0262 val = sdio_readw(bus->host_sdio, offset, &error);
0263 if (error) {
0264 dev_dbg(ssb_sdio_dev(bus), "%04X:%04X > %04x, error %d\n",
0265 bus->sdio_sbaddr >> 16, offset, val, error);
0266 }
0267 out:
0268 sdio_release_host(bus->host_sdio);
0269
0270 return val;
0271 }
0272
0273 static u32 ssb_sdio_read32(struct ssb_device *dev, u16 offset)
0274 {
0275 struct ssb_bus *bus = dev->bus;
0276 u32 val = 0xffffffff;
0277 int error = 0;
0278
0279 sdio_claim_host(bus->host_sdio);
0280 if (unlikely(ssb_sdio_switch_core(bus, dev)))
0281 goto out;
0282 offset |= bus->sdio_sbaddr & 0xffff;
0283 offset &= SBSDIO_SB_OFT_ADDR_MASK;
0284 offset |= SBSDIO_SB_ACCESS_2_4B_FLAG;
0285 val = sdio_readl(bus->host_sdio, offset, &error);
0286 if (error) {
0287 dev_dbg(ssb_sdio_dev(bus), "%04X:%04X > %08x, error %d\n",
0288 bus->sdio_sbaddr >> 16, offset, val, error);
0289 }
0290 out:
0291 sdio_release_host(bus->host_sdio);
0292
0293 return val;
0294 }
0295
0296 #ifdef CONFIG_SSB_BLOCKIO
0297 static void ssb_sdio_block_read(struct ssb_device *dev, void *buffer,
0298 size_t count, u16 offset, u8 reg_width)
0299 {
0300 size_t saved_count = count;
0301 struct ssb_bus *bus = dev->bus;
0302 int error = 0;
0303
0304 sdio_claim_host(bus->host_sdio);
0305 if (unlikely(ssb_sdio_switch_core(bus, dev))) {
0306 error = -EIO;
0307 memset(buffer, 0xff, count);
0308 goto err_out;
0309 }
0310 offset |= bus->sdio_sbaddr & 0xffff;
0311 offset &= SBSDIO_SB_OFT_ADDR_MASK;
0312
0313 switch (reg_width) {
0314 case sizeof(u8): {
0315 error = sdio_readsb(bus->host_sdio, buffer, offset, count);
0316 break;
0317 }
0318 case sizeof(u16): {
0319 WARN_ON(count & 1);
0320 error = sdio_readsb(bus->host_sdio, buffer, offset, count);
0321 break;
0322 }
0323 case sizeof(u32): {
0324 WARN_ON(count & 3);
0325 offset |= SBSDIO_SB_ACCESS_2_4B_FLAG;
0326 error = sdio_readsb(bus->host_sdio, buffer, offset, count);
0327 break;
0328 }
0329 default:
0330 WARN_ON(1);
0331 }
0332 if (!error)
0333 goto out;
0334
0335 err_out:
0336 dev_dbg(ssb_sdio_dev(bus), "%04X:%04X (width=%u, len=%zu), error %d\n",
0337 bus->sdio_sbaddr >> 16, offset, reg_width, saved_count, error);
0338 out:
0339 sdio_release_host(bus->host_sdio);
0340 }
0341 #endif
0342
0343 static void ssb_sdio_write8(struct ssb_device *dev, u16 offset, u8 val)
0344 {
0345 struct ssb_bus *bus = dev->bus;
0346 int error = 0;
0347
0348 sdio_claim_host(bus->host_sdio);
0349 if (unlikely(ssb_sdio_switch_core(bus, dev)))
0350 goto out;
0351 offset |= bus->sdio_sbaddr & 0xffff;
0352 offset &= SBSDIO_SB_OFT_ADDR_MASK;
0353 sdio_writeb(bus->host_sdio, val, offset, &error);
0354 if (error) {
0355 dev_dbg(ssb_sdio_dev(bus), "%04X:%04X < %02x, error %d\n",
0356 bus->sdio_sbaddr >> 16, offset, val, error);
0357 }
0358 out:
0359 sdio_release_host(bus->host_sdio);
0360 }
0361
0362 static void ssb_sdio_write16(struct ssb_device *dev, u16 offset, u16 val)
0363 {
0364 struct ssb_bus *bus = dev->bus;
0365 int error = 0;
0366
0367 sdio_claim_host(bus->host_sdio);
0368 if (unlikely(ssb_sdio_switch_core(bus, dev)))
0369 goto out;
0370 offset |= bus->sdio_sbaddr & 0xffff;
0371 offset &= SBSDIO_SB_OFT_ADDR_MASK;
0372 sdio_writew(bus->host_sdio, val, offset, &error);
0373 if (error) {
0374 dev_dbg(ssb_sdio_dev(bus), "%04X:%04X < %04x, error %d\n",
0375 bus->sdio_sbaddr >> 16, offset, val, error);
0376 }
0377 out:
0378 sdio_release_host(bus->host_sdio);
0379 }
0380
0381 static void ssb_sdio_write32(struct ssb_device *dev, u16 offset, u32 val)
0382 {
0383 struct ssb_bus *bus = dev->bus;
0384 int error = 0;
0385
0386 sdio_claim_host(bus->host_sdio);
0387 if (unlikely(ssb_sdio_switch_core(bus, dev)))
0388 goto out;
0389 offset |= bus->sdio_sbaddr & 0xffff;
0390 offset &= SBSDIO_SB_OFT_ADDR_MASK;
0391 offset |= SBSDIO_SB_ACCESS_2_4B_FLAG;
0392 sdio_writel(bus->host_sdio, val, offset, &error);
0393 if (error) {
0394 dev_dbg(ssb_sdio_dev(bus), "%04X:%04X < %08x, error %d\n",
0395 bus->sdio_sbaddr >> 16, offset, val, error);
0396 }
0397 if (bus->quirks & SSB_QUIRK_SDIO_READ_AFTER_WRITE32)
0398 sdio_readl(bus->host_sdio, 0, &error);
0399 out:
0400 sdio_release_host(bus->host_sdio);
0401 }
0402
0403 #ifdef CONFIG_SSB_BLOCKIO
0404 static void ssb_sdio_block_write(struct ssb_device *dev, const void *buffer,
0405 size_t count, u16 offset, u8 reg_width)
0406 {
0407 size_t saved_count = count;
0408 struct ssb_bus *bus = dev->bus;
0409 int error = 0;
0410
0411 sdio_claim_host(bus->host_sdio);
0412 if (unlikely(ssb_sdio_switch_core(bus, dev))) {
0413 error = -EIO;
0414 goto err_out;
0415 }
0416 offset |= bus->sdio_sbaddr & 0xffff;
0417 offset &= SBSDIO_SB_OFT_ADDR_MASK;
0418
0419 switch (reg_width) {
0420 case sizeof(u8):
0421 error = sdio_writesb(bus->host_sdio, offset,
0422 (void *)buffer, count);
0423 break;
0424 case sizeof(u16):
0425 WARN_ON(count & 1);
0426 error = sdio_writesb(bus->host_sdio, offset,
0427 (void *)buffer, count);
0428 break;
0429 case sizeof(u32):
0430 WARN_ON(count & 3);
0431 offset |= SBSDIO_SB_ACCESS_2_4B_FLAG;
0432 error = sdio_writesb(bus->host_sdio, offset,
0433 (void *)buffer, count);
0434 break;
0435 default:
0436 WARN_ON(1);
0437 }
0438 if (!error)
0439 goto out;
0440
0441 err_out:
0442 dev_dbg(ssb_sdio_dev(bus), "%04X:%04X (width=%u, len=%zu), error %d\n",
0443 bus->sdio_sbaddr >> 16, offset, reg_width, saved_count, error);
0444 out:
0445 sdio_release_host(bus->host_sdio);
0446 }
0447
0448 #endif
0449
0450
0451 const struct ssb_bus_ops ssb_sdio_ops = {
0452 .read8 = ssb_sdio_read8,
0453 .read16 = ssb_sdio_read16,
0454 .read32 = ssb_sdio_read32,
0455 .write8 = ssb_sdio_write8,
0456 .write16 = ssb_sdio_write16,
0457 .write32 = ssb_sdio_write32,
0458 #ifdef CONFIG_SSB_BLOCKIO
0459 .block_read = ssb_sdio_block_read,
0460 .block_write = ssb_sdio_block_write,
0461 #endif
0462 };
0463
0464 #define GOTO_ERROR_ON(condition, description) do { \
0465 if (unlikely(condition)) { \
0466 error_description = description; \
0467 goto error; \
0468 } \
0469 } while (0)
0470
0471 int ssb_sdio_get_invariants(struct ssb_bus *bus,
0472 struct ssb_init_invariants *iv)
0473 {
0474 struct ssb_sprom *sprom = &iv->sprom;
0475 struct ssb_boardinfo *bi = &iv->boardinfo;
0476 const char *error_description = "none";
0477 struct sdio_func_tuple *tuple;
0478 void *mac;
0479
0480 memset(sprom, 0xFF, sizeof(*sprom));
0481 sprom->boardflags_lo = 0;
0482 sprom->boardflags_hi = 0;
0483
0484 tuple = bus->host_sdio->tuples;
0485 while (tuple) {
0486 switch (tuple->code) {
0487 case 0x22:
0488 switch (tuple->data[0]) {
0489 case CISTPL_FUNCE_LAN_NODE_ID:
0490 GOTO_ERROR_ON((tuple->size != 7) &&
0491 (tuple->data[1] != 6),
0492 "mac tpl size");
0493
0494 mac = tuple->data + 2;
0495 memcpy(sprom->il0mac, mac, ETH_ALEN);
0496 memcpy(sprom->et1mac, mac, ETH_ALEN);
0497 break;
0498 default:
0499 break;
0500 }
0501 break;
0502 case 0x80:
0503 switch (tuple->data[0]) {
0504 case SSB_SDIO_CIS_SROMREV:
0505 GOTO_ERROR_ON(tuple->size != 2,
0506 "sromrev tpl size");
0507 sprom->revision = tuple->data[1];
0508 break;
0509 case SSB_SDIO_CIS_ID:
0510 GOTO_ERROR_ON((tuple->size != 5) &&
0511 (tuple->size != 7),
0512 "id tpl size");
0513 bi->vendor = tuple->data[1] |
0514 (tuple->data[2]<<8);
0515 break;
0516 case SSB_SDIO_CIS_BOARDREV:
0517 GOTO_ERROR_ON(tuple->size != 2,
0518 "boardrev tpl size");
0519 sprom->board_rev = tuple->data[1];
0520 break;
0521 case SSB_SDIO_CIS_PA:
0522 GOTO_ERROR_ON((tuple->size != 9) &&
0523 (tuple->size != 10),
0524 "pa tpl size");
0525 sprom->pa0b0 = tuple->data[1] |
0526 ((u16)tuple->data[2] << 8);
0527 sprom->pa0b1 = tuple->data[3] |
0528 ((u16)tuple->data[4] << 8);
0529 sprom->pa0b2 = tuple->data[5] |
0530 ((u16)tuple->data[6] << 8);
0531 sprom->itssi_a = tuple->data[7];
0532 sprom->itssi_bg = tuple->data[7];
0533 sprom->maxpwr_a = tuple->data[8];
0534 sprom->maxpwr_bg = tuple->data[8];
0535 break;
0536 case SSB_SDIO_CIS_OEMNAME:
0537
0538 break;
0539 case SSB_SDIO_CIS_CCODE:
0540 GOTO_ERROR_ON(tuple->size != 2,
0541 "ccode tpl size");
0542 sprom->country_code = tuple->data[1];
0543 break;
0544 case SSB_SDIO_CIS_ANTENNA:
0545 GOTO_ERROR_ON(tuple->size != 2,
0546 "ant tpl size");
0547 sprom->ant_available_a = tuple->data[1];
0548 sprom->ant_available_bg = tuple->data[1];
0549 break;
0550 case SSB_SDIO_CIS_ANTGAIN:
0551 GOTO_ERROR_ON(tuple->size != 2,
0552 "antg tpl size");
0553 sprom->antenna_gain.a0 = tuple->data[1];
0554 sprom->antenna_gain.a1 = tuple->data[1];
0555 sprom->antenna_gain.a2 = tuple->data[1];
0556 sprom->antenna_gain.a3 = tuple->data[1];
0557 break;
0558 case SSB_SDIO_CIS_BFLAGS:
0559 GOTO_ERROR_ON((tuple->size != 3) &&
0560 (tuple->size != 5),
0561 "bfl tpl size");
0562 sprom->boardflags_lo = tuple->data[1] |
0563 ((u16)tuple->data[2] << 8);
0564 break;
0565 case SSB_SDIO_CIS_LEDS:
0566 GOTO_ERROR_ON(tuple->size != 5,
0567 "leds tpl size");
0568 sprom->gpio0 = tuple->data[1];
0569 sprom->gpio1 = tuple->data[2];
0570 sprom->gpio2 = tuple->data[3];
0571 sprom->gpio3 = tuple->data[4];
0572 break;
0573 default:
0574 break;
0575 }
0576 break;
0577 default:
0578 break;
0579 }
0580 tuple = tuple->next;
0581 }
0582
0583 return 0;
0584 error:
0585 dev_err(ssb_sdio_dev(bus), "failed to fetch device invariants: %s\n",
0586 error_description);
0587 return -ENODEV;
0588 }
0589
0590 void ssb_sdio_exit(struct ssb_bus *bus)
0591 {
0592 if (bus->bustype != SSB_BUSTYPE_SDIO)
0593 return;
0594
0595 }
0596
0597 int ssb_sdio_init(struct ssb_bus *bus)
0598 {
0599 if (bus->bustype != SSB_BUSTYPE_SDIO)
0600 return 0;
0601
0602 bus->sdio_sbaddr = ~0;
0603
0604 return 0;
0605 }