pci.c (ac82fab44f6b981e3f6b53784e2f23838f4908e1) | pci.c (c272ef4403c271799a7f09a4ab7a236c86643843) |
---|---|
1/* 2 * Sonics Silicon Backplane PCI-Hostbus related functions. 3 * 4 * Copyright (C) 2005-2006 Michael Buesch <mb@bu3sch.de> 5 * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de> 6 * Copyright (C) 2005 Stefano Brivio <st3@riseup.net> 7 * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org> 8 * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch> --- 198 unchanged lines hidden (view full) --- 207 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, 208 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, 209 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, 210 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F, 211 }; 212 return t[crc ^ data]; 213} 214 | 1/* 2 * Sonics Silicon Backplane PCI-Hostbus related functions. 3 * 4 * Copyright (C) 2005-2006 Michael Buesch <mb@bu3sch.de> 5 * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de> 6 * Copyright (C) 2005 Stefano Brivio <st3@riseup.net> 7 * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org> 8 * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch> --- 198 unchanged lines hidden (view full) --- 207 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, 208 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, 209 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, 210 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F, 211 }; 212 return t[crc ^ data]; 213} 214 |
215static u8 ssb_sprom_crc(const u16 *sprom) | 215static u8 ssb_sprom_crc(const u16 *sprom, u16 size) |
216{ 217 int word; 218 u8 crc = 0xFF; 219 | 216{ 217 int word; 218 u8 crc = 0xFF; 219 |
220 for (word = 0; word < SSB_SPROMSIZE_WORDS - 1; word++) { | 220 for (word = 0; word < size - 1; word++) { |
221 crc = ssb_crc8(crc, sprom[word] & 0x00FF); 222 crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8); 223 } | 221 crc = ssb_crc8(crc, sprom[word] & 0x00FF); 222 crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8); 223 } |
224 crc = ssb_crc8(crc, sprom[SPOFF(SSB_SPROM_REVISION)] & 0x00FF); | 224 crc = ssb_crc8(crc, sprom[size - 1] & 0x00FF); |
225 crc ^= 0xFF; 226 227 return crc; 228} 229 | 225 crc ^= 0xFF; 226 227 return crc; 228} 229 |
230static int sprom_check_crc(const u16 *sprom) | 230static int sprom_check_crc(const u16 *sprom, u16 size) |
231{ 232 u8 crc; 233 u8 expected_crc; 234 u16 tmp; 235 | 231{ 232 u8 crc; 233 u8 expected_crc; 234 u16 tmp; 235 |
236 crc = ssb_sprom_crc(sprom); 237 tmp = sprom[SPOFF(SSB_SPROM_REVISION)] & SSB_SPROM_REVISION_CRC; | 236 crc = ssb_sprom_crc(sprom, size); 237 tmp = sprom[size - 1] & SSB_SPROM_REVISION_CRC; |
238 expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT; 239 if (crc != expected_crc) 240 return -EPROTO; 241 242 return 0; 243} 244 245static void sprom_do_read(struct ssb_bus *bus, u16 *sprom) 246{ 247 int i; 248 | 238 expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT; 239 if (crc != expected_crc) 240 return -EPROTO; 241 242 return 0; 243} 244 245static void sprom_do_read(struct ssb_bus *bus, u16 *sprom) 246{ 247 int i; 248 |
249 for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) | 249 for (i = 0; i < bus->sprom_size; i++) |
250 sprom[i] = readw(bus->mmio + SSB_SPROM_BASE + (i * 2)); 251} 252 253static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) 254{ 255 struct pci_dev *pdev = bus->host_pci; 256 int i, err; 257 u32 spromctl; | 250 sprom[i] = readw(bus->mmio + SSB_SPROM_BASE + (i * 2)); 251} 252 253static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) 254{ 255 struct pci_dev *pdev = bus->host_pci; 256 int i, err; 257 u32 spromctl; |
258 u16 size = bus->sprom_size; |
|
258 259 ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n"); 260 err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl); 261 if (err) 262 goto err_ctlreg; 263 spromctl |= SSB_SPROMCTL_WE; 264 err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl); 265 if (err) 266 goto err_ctlreg; 267 ssb_printk(KERN_NOTICE PFX "[ 0%%"); 268 msleep(500); | 259 260 ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n"); 261 err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl); 262 if (err) 263 goto err_ctlreg; 264 spromctl |= SSB_SPROMCTL_WE; 265 err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl); 266 if (err) 267 goto err_ctlreg; 268 ssb_printk(KERN_NOTICE PFX "[ 0%%"); 269 msleep(500); |
269 for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) { 270 if (i == SSB_SPROMSIZE_WORDS / 4) | 270 for (i = 0; i < size; i++) { 271 if (i == size / 4) |
271 ssb_printk("25%%"); | 272 ssb_printk("25%%"); |
272 else if (i == SSB_SPROMSIZE_WORDS / 2) | 273 else if (i == size / 2) |
273 ssb_printk("50%%"); | 274 ssb_printk("50%%"); |
274 else if (i == (SSB_SPROMSIZE_WORDS / 4) * 3) | 275 else if (i == (size * 3) / 4) |
275 ssb_printk("75%%"); 276 else if (i % 2) 277 ssb_printk("."); 278 writew(sprom[i], bus->mmio + SSB_SPROM_BASE + (i * 2)); 279 mmiowb(); 280 msleep(20); 281 } 282 err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl); --- 62 unchanged lines hidden (view full) --- 345 SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0); 346 SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A, 347 SSB_SPROM1_ITSSI_A_SHIFT); 348 SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0); 349 SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0); 350 SPEX(antenna_gain_a, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_A, 0); 351 SPEX(antenna_gain_bg, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_BG, 352 SSB_SPROM1_AGAIN_BG_SHIFT); | 276 ssb_printk("75%%"); 277 else if (i % 2) 278 ssb_printk("."); 279 writew(sprom[i], bus->mmio + SSB_SPROM_BASE + (i * 2)); 280 mmiowb(); 281 msleep(20); 282 } 283 err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl); --- 62 unchanged lines hidden (view full) --- 346 SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0); 347 SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A, 348 SSB_SPROM1_ITSSI_A_SHIFT); 349 SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0); 350 SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0); 351 SPEX(antenna_gain_a, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_A, 0); 352 SPEX(antenna_gain_bg, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_BG, 353 SSB_SPROM1_AGAIN_BG_SHIFT); |
353 for (i = 0; i < 4; i++) { 354 v = in[SPOFF(SSB_SPROM1_OEM) + i]; 355 *(((__le16 *)out->oem) + i) = cpu_to_le16(v); 356 } | |
357} 358 | 354} 355 |
359static void sprom_extract_r2(struct ssb_sprom_r2 *out, const u16 *in) | 356static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) |
360{ 361 int i; 362 u16 v; | 357{ 358 int i; 359 u16 v; |
360 u16 loc[3]; |
|
363 | 361 |
364 SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0); 365 SPEX(maxpwr_a_hi, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0); 366 SPEX(maxpwr_a_lo, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO, 367 SSB_SPROM2_MAXP_A_LO_SHIFT); 368 SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0); 369 SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0); 370 SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0); 371 SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0); 372 SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0); 373 SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0); 374 SPEX(ofdm_pwr_off, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0); 375 for (i = 0; i < 4; i++) { 376 v = in[SPOFF(SSB_SPROM2_CCODE) + i]; 377 *(((__le16 *)out->country_str) + i) = cpu_to_le16(v); | 362 if (out->revision == 3) { /* rev 3 moved MAC */ 363 loc[0] = SSB_SPROM3_IL0MAC; 364 loc[1] = SSB_SPROM3_ET0MAC; 365 loc[2] = SSB_SPROM3_ET1MAC; 366 } else { 367 loc[0] = SSB_SPROM1_IL0MAC; 368 loc[1] = SSB_SPROM1_ET0MAC; 369 loc[2] = SSB_SPROM1_ET1MAC; |
378 } | 370 } |
371 for (i = 0; i < 3; i++) { 372 v = in[SPOFF(loc[0]) + i]; 373 *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); 374 } 375 for (i = 0; i < 3; i++) { 376 v = in[SPOFF(loc[1]) + i]; 377 *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v); 378 } 379 for (i = 0; i < 3; i++) { 380 v = in[SPOFF(loc[2]) + i]; 381 *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v); 382 } 383 SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); 384 SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, 385 SSB_SPROM1_ETHPHY_ET1A_SHIFT); 386 SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE, 387 SSB_SPROM1_BINF_CCODE_SHIFT); 388 SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0); 389 SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0); 390 SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0); 391 SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0); 392 SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0); 393 SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0); 394 SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0); 395 SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1, 396 SSB_SPROM1_GPIOA_P1_SHIFT); 397 SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0); 398 SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3, 399 SSB_SPROM1_GPIOB_P3_SHIFT); 400 SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A, 401 SSB_SPROM1_MAXPWR_A_SHIFT); 402 SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0); 403 SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A, 404 SSB_SPROM1_ITSSI_A_SHIFT); 405 SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0); 406 SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0); 407 SPEX(antenna_gain_a, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_A, 0); 408 SPEX(antenna_gain_bg, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_BG, 409 SSB_SPROM1_AGAIN_BG_SHIFT); |
|
379} 380 | 410} 411 |
381static void sprom_extract_r3(struct ssb_sprom_r3 *out, const u16 *in) | 412static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in) |
382{ | 413{ |
383 out->ofdmapo = (in[SPOFF(SSB_SPROM3_OFDMAPO) + 0] & 0xFF00) >> 8; 384 out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 0] & 0x00FF) << 8; 385 out->ofdmapo <<= 16; 386 out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 1] & 0xFF00) >> 8; 387 out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 1] & 0x00FF) << 8; | 414 int i; 415 u16 v; |
388 | 416 |
389 out->ofdmalpo = (in[SPOFF(SSB_SPROM3_OFDMALPO) + 0] & 0xFF00) >> 8; 390 out->ofdmalpo |= (in[SPOFF(SSB_SPROM3_OFDMALPO) + 0] & 0x00FF) << 8; 391 out->ofdmalpo <<= 16; 392 out->ofdmalpo |= (in[SPOFF(SSB_SPROM3_OFDMALPO) + 1] & 0xFF00) >> 8; 393 out->ofdmalpo |= (in[SPOFF(SSB_SPROM3_OFDMALPO) + 1] & 0x00FF) << 8; 394 395 out->ofdmahpo = (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 0] & 0xFF00) >> 8; 396 out->ofdmahpo |= (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 0] & 0x00FF) << 8; 397 out->ofdmahpo <<= 16; 398 out->ofdmahpo |= (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 1] & 0xFF00) >> 8; 399 out->ofdmahpo |= (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 1] & 0x00FF) << 8; 400 401 SPEX(gpioldc_on_cnt, SSB_SPROM3_GPIOLDC, SSB_SPROM3_GPIOLDC_ON, 402 SSB_SPROM3_GPIOLDC_ON_SHIFT); 403 SPEX(gpioldc_off_cnt, SSB_SPROM3_GPIOLDC, SSB_SPROM3_GPIOLDC_OFF, 404 SSB_SPROM3_GPIOLDC_OFF_SHIFT); 405 SPEX(cckpo_1M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_1M, 0); 406 SPEX(cckpo_2M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_2M, 407 SSB_SPROM3_CCKPO_2M_SHIFT); 408 SPEX(cckpo_55M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_55M, 409 SSB_SPROM3_CCKPO_55M_SHIFT); 410 SPEX(cckpo_11M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_11M, 411 SSB_SPROM3_CCKPO_11M_SHIFT); 412 413 out->ofdmgpo = (in[SPOFF(SSB_SPROM3_OFDMGPO) + 0] & 0xFF00) >> 8; 414 out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 0] & 0x00FF) << 8; 415 out->ofdmgpo <<= 16; 416 out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 1] & 0xFF00) >> 8; 417 out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 1] & 0x00FF) << 8; | 417 /* extract the r1 variables */ 418 for (i = 0; i < 3; i++) { 419 v = in[SPOFF(SSB_SPROM4_IL0MAC) + i]; 420 *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); 421 } 422 for (i = 0; i < 3; i++) { 423 v = in[SPOFF(SSB_SPROM4_ET0MAC) + i]; 424 *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v); 425 } 426 for (i = 0; i < 3; i++) { 427 v = in[SPOFF(SSB_SPROM4_ET1MAC) + i]; 428 *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v); 429 } 430 SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0); 431 SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A, 432 SSB_SPROM4_ETHPHY_ET1A_SHIFT); 433 SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0); 434 SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0); 435 SPEX(antenna_gain_a, SSB_SPROM4_AGAIN, SSB_SPROM4_AGAIN_0, 0); 436 SPEX(antenna_gain_bg, SSB_SPROM4_AGAIN, SSB_SPROM4_AGAIN_1, 437 SSB_SPROM4_AGAIN_1_SHIFT); 438 /* TODO - get remaining rev 4 stuff needed */ |
418} 419 | 439} 440 |
420static int sprom_extract(struct ssb_bus *bus, 421 struct ssb_sprom *out, const u16 *in) | 441static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, 442 const u16 *in, u16 size) |
422{ 423 memset(out, 0, sizeof(*out)); 424 | 443{ 444 memset(out, 0, sizeof(*out)); 445 |
425 SPEX(revision, SSB_SPROM_REVISION, SSB_SPROM_REVISION_REV, 0); 426 | 446 out->revision = in[size - 1] & 0x00FF; |
427 if ((bus->chip_id & 0xFF00) == 0x4400) { 428 /* Workaround: The BCM44XX chip has a stupid revision 429 * number stored in the SPROM. 430 * Always extract r1. */ | 447 if ((bus->chip_id & 0xFF00) == 0x4400) { 448 /* Workaround: The BCM44XX chip has a stupid revision 449 * number stored in the SPROM. 450 * Always extract r1. */ |
451 out->revision = 1; 452 sprom_extract_r123(out, in); |
|
431 sprom_extract_r1(&out->r1, in); | 453 sprom_extract_r1(&out->r1, in); |
454 } else if (bus->chip_id == 0x4321) { 455 /* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */ 456 out->revision = 4; 457 sprom_extract_r4(out, in); |
|
432 } else { 433 if (out->revision == 0) 434 goto unsupported; | 458 } else { 459 if (out->revision == 0) 460 goto unsupported; |
435 if (out->revision >= 1 && out->revision <= 3) | 461 if (out->revision >= 1 && out->revision <= 3) { 462 sprom_extract_r123(out, in); |
436 sprom_extract_r1(&out->r1, in); | 463 sprom_extract_r1(&out->r1, in); |
437 if (out->revision >= 2 && out->revision <= 3) 438 sprom_extract_r2(&out->r2, in); 439 if (out->revision == 3) 440 sprom_extract_r3(&out->r3, in); 441 if (out->revision >= 4) | 464 } 465 if (out->revision == 4) 466 sprom_extract_r4(out, in); 467 if (out->revision >= 5) |
442 goto unsupported; 443 } 444 445 return 0; 446unsupported: 447 ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d " 448 "detected. Will extract v1\n", out->revision); 449 sprom_extract_r1(&out->r1, in); 450 return 0; 451} 452 453static int ssb_pci_sprom_get(struct ssb_bus *bus, 454 struct ssb_sprom *sprom) 455{ 456 int err = -ENOMEM; 457 u16 *buf; 458 | 468 goto unsupported; 469 } 470 471 return 0; 472unsupported: 473 ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d " 474 "detected. Will extract v1\n", out->revision); 475 sprom_extract_r1(&out->r1, in); 476 return 0; 477} 478 479static int ssb_pci_sprom_get(struct ssb_bus *bus, 480 struct ssb_sprom *sprom) 481{ 482 int err = -ENOMEM; 483 u16 *buf; 484 |
459 buf = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL); | 485 buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); |
460 if (!buf) 461 goto out; | 486 if (!buf) 487 goto out; |
488 bus->sprom_size = SSB_SPROMSIZE_WORDS_R123; |
|
462 sprom_do_read(bus, buf); | 489 sprom_do_read(bus, buf); |
463 err = sprom_check_crc(buf); | 490 err = sprom_check_crc(buf, bus->sprom_size); |
464 if (err) { | 491 if (err) { |
465 ssb_printk(KERN_WARNING PFX 466 "WARNING: Invalid SPROM CRC (corrupt SPROM)\n"); | 492 /* check for rev 4 sprom - has special signature */ 493 if (buf [32] == 0x5372) { 494 ssb_printk(KERN_WARNING PFX "Extracting a rev 4" 495 " SPROM\n"); 496 kfree(buf); 497 buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), 498 GFP_KERNEL); 499 if (!buf) 500 goto out; 501 bus->sprom_size = SSB_SPROMSIZE_WORDS_R4; 502 sprom_do_read(bus, buf); 503 err = sprom_check_crc(buf, bus->sprom_size); 504 } 505 if (err) 506 ssb_printk(KERN_WARNING PFX "WARNING: Invalid" 507 " SPROM CRC (corrupt SPROM)\n"); |
467 } | 508 } |
468 err = sprom_extract(bus, sprom, buf); | 509 err = sprom_extract(bus, sprom, buf, bus->sprom_size); |
469 470 kfree(buf); 471out: 472 return err; 473} 474 475static void ssb_pci_get_boardinfo(struct ssb_bus *bus, 476 struct ssb_boardinfo *bi) --- 97 unchanged lines hidden (view full) --- 574/* Not "static", as it's used in main.c */ 575const struct ssb_bus_ops ssb_pci_ops = { 576 .read16 = ssb_pci_read16, 577 .read32 = ssb_pci_read32, 578 .write16 = ssb_pci_write16, 579 .write32 = ssb_pci_write32, 580}; 581 | 510 511 kfree(buf); 512out: 513 return err; 514} 515 516static void ssb_pci_get_boardinfo(struct ssb_bus *bus, 517 struct ssb_boardinfo *bi) --- 97 unchanged lines hidden (view full) --- 615/* Not "static", as it's used in main.c */ 616const struct ssb_bus_ops ssb_pci_ops = { 617 .read16 = ssb_pci_read16, 618 .read32 = ssb_pci_read32, 619 .write16 = ssb_pci_write16, 620 .write32 = ssb_pci_write32, 621}; 622 |
582static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len) | 623static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len, u16 size) |
583{ 584 int i, pos = 0; 585 | 624{ 625 int i, pos = 0; 626 |
586 for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) { | 627 for (i = 0; i < size; i++) |
587 pos += snprintf(buf + pos, buf_len - pos - 1, 588 "%04X", swab16(sprom[i]) & 0xFFFF); | 628 pos += snprintf(buf + pos, buf_len - pos - 1, 629 "%04X", swab16(sprom[i]) & 0xFFFF); |
589 } | |
590 pos += snprintf(buf + pos, buf_len - pos - 1, "\n"); 591 592 return pos + 1; 593} 594 | 630 pos += snprintf(buf + pos, buf_len - pos - 1, "\n"); 631 632 return pos + 1; 633} 634 |
595static int hex2sprom(u16 *sprom, const char *dump, size_t len) | 635static int hex2sprom(u16 *sprom, const char *dump, size_t len, u16 size) |
596{ 597 char tmp[5] = { 0 }; 598 int cnt = 0; 599 unsigned long parsed; 600 | 636{ 637 char tmp[5] = { 0 }; 638 int cnt = 0; 639 unsigned long parsed; 640 |
601 if (len < SSB_SPROMSIZE_BYTES * 2) | 641 if (len < size * 2) |
602 return -EINVAL; 603 | 642 return -EINVAL; 643 |
604 while (cnt < SSB_SPROMSIZE_WORDS) { | 644 while (cnt < size) { |
605 memcpy(tmp, dump, 4); 606 dump += 4; 607 parsed = simple_strtoul(tmp, NULL, 16); 608 sprom[cnt++] = swab16((u16)parsed); 609 } 610 611 return 0; 612} --- 7 unchanged lines hidden (view full) --- 620 u16 *sprom; 621 int err = -ENODEV; 622 ssize_t count = 0; 623 624 bus = ssb_pci_dev_to_bus(pdev); 625 if (!bus) 626 goto out; 627 err = -ENOMEM; | 645 memcpy(tmp, dump, 4); 646 dump += 4; 647 parsed = simple_strtoul(tmp, NULL, 16); 648 sprom[cnt++] = swab16((u16)parsed); 649 } 650 651 return 0; 652} --- 7 unchanged lines hidden (view full) --- 660 u16 *sprom; 661 int err = -ENODEV; 662 ssize_t count = 0; 663 664 bus = ssb_pci_dev_to_bus(pdev); 665 if (!bus) 666 goto out; 667 err = -ENOMEM; |
628 sprom = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL); | 668 sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL); |
629 if (!sprom) 630 goto out; 631 632 /* Use interruptible locking, as the SPROM write might 633 * be holding the lock for several seconds. So allow userspace 634 * to cancel operation. */ 635 err = -ERESTARTSYS; 636 if (mutex_lock_interruptible(&bus->pci_sprom_mutex)) 637 goto out_kfree; 638 sprom_do_read(bus, sprom); 639 mutex_unlock(&bus->pci_sprom_mutex); 640 | 669 if (!sprom) 670 goto out; 671 672 /* Use interruptible locking, as the SPROM write might 673 * be holding the lock for several seconds. So allow userspace 674 * to cancel operation. */ 675 err = -ERESTARTSYS; 676 if (mutex_lock_interruptible(&bus->pci_sprom_mutex)) 677 goto out_kfree; 678 sprom_do_read(bus, sprom); 679 mutex_unlock(&bus->pci_sprom_mutex); 680 |
641 count = sprom2hex(sprom, buf, PAGE_SIZE); | 681 count = sprom2hex(sprom, buf, PAGE_SIZE, bus->sprom_size); |
642 err = 0; 643 644out_kfree: 645 kfree(sprom); 646out: 647 return err ? err : count; 648} 649 --- 5 unchanged lines hidden (view full) --- 655 struct ssb_bus *bus; 656 u16 *sprom; 657 int res = 0, err = -ENODEV; 658 659 bus = ssb_pci_dev_to_bus(pdev); 660 if (!bus) 661 goto out; 662 err = -ENOMEM; | 682 err = 0; 683 684out_kfree: 685 kfree(sprom); 686out: 687 return err ? err : count; 688} 689 --- 5 unchanged lines hidden (view full) --- 695 struct ssb_bus *bus; 696 u16 *sprom; 697 int res = 0, err = -ENODEV; 698 699 bus = ssb_pci_dev_to_bus(pdev); 700 if (!bus) 701 goto out; 702 err = -ENOMEM; |
663 sprom = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL); | 703 sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL); |
664 if (!sprom) 665 goto out; | 704 if (!sprom) 705 goto out; |
666 err = hex2sprom(sprom, buf, count); | 706 err = hex2sprom(sprom, buf, count, bus->sprom_size); |
667 if (err) { 668 err = -EINVAL; 669 goto out_kfree; 670 } | 707 if (err) { 708 err = -EINVAL; 709 goto out_kfree; 710 } |
671 err = sprom_check_crc(sprom); | 711 err = sprom_check_crc(sprom, bus->sprom_size); |
672 if (err) { 673 err = -EINVAL; 674 goto out_kfree; 675 } 676 677 /* Use interruptible locking, as the SPROM write might 678 * be holding the lock for several seconds. So allow userspace 679 * to cancel operation. */ --- 59 unchanged lines hidden --- | 712 if (err) { 713 err = -EINVAL; 714 goto out_kfree; 715 } 716 717 /* Use interruptible locking, as the SPROM write might 718 * be holding the lock for several seconds. So allow userspace 719 * to cancel operation. */ --- 59 unchanged lines hidden --- |