pcmcia.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  1. /*
  2. * Sonics Silicon Backplane
  3. * PCMCIA-Hostbus related functions
  4. *
  5. * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
  6. * Copyright 2007-2008 Michael Buesch <mb@bu3sch.de>
  7. *
  8. * Licensed under the GNU/GPL. See COPYING for details.
  9. */
  10. #include <linux/ssb/ssb.h>
  11. #include <linux/delay.h>
  12. #include <linux/io.h>
  13. #include <linux/etherdevice.h>
  14. #include <pcmcia/cs.h>
  15. #include <pcmcia/cistpl.h>
  16. #include <pcmcia/ciscode.h>
  17. #include <pcmcia/ds.h>
  18. #include <pcmcia/cisreg.h>
  19. #include "ssb_private.h"
  20. /* Define the following to 1 to enable a printk on each coreswitch. */
  21. #define SSB_VERBOSE_PCMCIACORESWITCH_DEBUG 0
  22. /* PCMCIA configuration registers */
  23. #define SSB_PCMCIA_ADDRESS0 0x2E
  24. #define SSB_PCMCIA_ADDRESS1 0x30
  25. #define SSB_PCMCIA_ADDRESS2 0x32
  26. #define SSB_PCMCIA_MEMSEG 0x34
  27. #define SSB_PCMCIA_SPROMCTL 0x36
  28. #define SSB_PCMCIA_SPROMCTL_IDLE 0
  29. #define SSB_PCMCIA_SPROMCTL_WRITE 1
  30. #define SSB_PCMCIA_SPROMCTL_READ 2
  31. #define SSB_PCMCIA_SPROMCTL_WRITEEN 4
  32. #define SSB_PCMCIA_SPROMCTL_WRITEDIS 7
  33. #define SSB_PCMCIA_SPROMCTL_DONE 8
  34. #define SSB_PCMCIA_SPROM_DATALO 0x38
  35. #define SSB_PCMCIA_SPROM_DATAHI 0x3A
  36. #define SSB_PCMCIA_SPROM_ADDRLO 0x3C
  37. #define SSB_PCMCIA_SPROM_ADDRHI 0x3E
  38. /* Hardware invariants CIS tuples */
  39. #define SSB_PCMCIA_CIS 0x80
  40. #define SSB_PCMCIA_CIS_ID 0x01
  41. #define SSB_PCMCIA_CIS_BOARDREV 0x02
  42. #define SSB_PCMCIA_CIS_PA 0x03
  43. #define SSB_PCMCIA_CIS_PA_PA0B0_LO 0
  44. #define SSB_PCMCIA_CIS_PA_PA0B0_HI 1
  45. #define SSB_PCMCIA_CIS_PA_PA0B1_LO 2
  46. #define SSB_PCMCIA_CIS_PA_PA0B1_HI 3
  47. #define SSB_PCMCIA_CIS_PA_PA0B2_LO 4
  48. #define SSB_PCMCIA_CIS_PA_PA0B2_HI 5
  49. #define SSB_PCMCIA_CIS_PA_ITSSI 6
  50. #define SSB_PCMCIA_CIS_PA_MAXPOW 7
  51. #define SSB_PCMCIA_CIS_OEMNAME 0x04
  52. #define SSB_PCMCIA_CIS_CCODE 0x05
  53. #define SSB_PCMCIA_CIS_ANTENNA 0x06
  54. #define SSB_PCMCIA_CIS_ANTGAIN 0x07
  55. #define SSB_PCMCIA_CIS_BFLAGS 0x08
  56. #define SSB_PCMCIA_CIS_LEDS 0x09
  57. /* PCMCIA SPROM size. */
  58. #define SSB_PCMCIA_SPROM_SIZE 256
  59. #define SSB_PCMCIA_SPROM_SIZE_BYTES (SSB_PCMCIA_SPROM_SIZE * sizeof(u16))
  60. /* Write to a PCMCIA configuration register. */
  61. static int ssb_pcmcia_cfg_write(struct ssb_bus *bus, u8 offset, u8 value)
  62. {
  63. conf_reg_t reg;
  64. int res;
  65. memset(&reg, 0, sizeof(reg));
  66. reg.Offset = offset;
  67. reg.Action = CS_WRITE;
  68. reg.Value = value;
  69. res = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
  70. if (unlikely(res != 0))
  71. return -EBUSY;
  72. return 0;
  73. }
  74. /* Read from a PCMCIA configuration register. */
  75. static int ssb_pcmcia_cfg_read(struct ssb_bus *bus, u8 offset, u8 *value)
  76. {
  77. conf_reg_t reg;
  78. int res;
  79. memset(&reg, 0, sizeof(reg));
  80. reg.Offset = offset;
  81. reg.Action = CS_READ;
  82. res = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
  83. if (unlikely(res != 0))
  84. return -EBUSY;
  85. *value = reg.Value;
  86. return 0;
  87. }
  88. int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
  89. u8 coreidx)
  90. {
  91. int err;
  92. int attempts = 0;
  93. u32 cur_core;
  94. u32 addr;
  95. u32 read_addr;
  96. u8 val;
  97. addr = (coreidx * SSB_CORE_SIZE) + SSB_ENUM_BASE;
  98. while (1) {
  99. err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS0,
  100. (addr & 0x0000F000) >> 12);
  101. if (err)
  102. goto error;
  103. err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS1,
  104. (addr & 0x00FF0000) >> 16);
  105. if (err)
  106. goto error;
  107. err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS2,
  108. (addr & 0xFF000000) >> 24);
  109. if (err)
  110. goto error;
  111. read_addr = 0;
  112. err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS0, &val);
  113. if (err)
  114. goto error;
  115. read_addr |= ((u32)(val & 0x0F)) << 12;
  116. err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS1, &val);
  117. if (err)
  118. goto error;
  119. read_addr |= ((u32)val) << 16;
  120. err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS2, &val);
  121. if (err)
  122. goto error;
  123. read_addr |= ((u32)val) << 24;
  124. cur_core = (read_addr - SSB_ENUM_BASE) / SSB_CORE_SIZE;
  125. if (cur_core == coreidx)
  126. break;
  127. err = -ETIMEDOUT;
  128. if (attempts++ > SSB_BAR0_MAX_RETRIES)
  129. goto error;
  130. udelay(10);
  131. }
  132. return 0;
  133. error:
  134. ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
  135. return err;
  136. }
  137. int ssb_pcmcia_switch_core(struct ssb_bus *bus,
  138. struct ssb_device *dev)
  139. {
  140. int err;
  141. #if SSB_VERBOSE_PCMCIACORESWITCH_DEBUG
  142. ssb_printk(KERN_INFO PFX
  143. "Switching to %s core, index %d\n",
  144. ssb_core_name(dev->id.coreid),
  145. dev->core_index);
  146. #endif
  147. err = ssb_pcmcia_switch_coreidx(bus, dev->core_index);
  148. if (!err)
  149. bus->mapped_device = dev;
  150. return err;
  151. }
  152. int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg)
  153. {
  154. int attempts = 0;
  155. int err;
  156. u8 val;
  157. SSB_WARN_ON((seg != 0) && (seg != 1));
  158. while (1) {
  159. err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_MEMSEG, seg);
  160. if (err)
  161. goto error;
  162. err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_MEMSEG, &val);
  163. if (err)
  164. goto error;
  165. if (val == seg)
  166. break;
  167. err = -ETIMEDOUT;
  168. if (unlikely(attempts++ > SSB_BAR0_MAX_RETRIES))
  169. goto error;
  170. udelay(10);
  171. }
  172. bus->mapped_pcmcia_seg = seg;
  173. return 0;
  174. error:
  175. ssb_printk(KERN_ERR PFX "Failed to switch pcmcia segment\n");
  176. return err;
  177. }
  178. static int select_core_and_segment(struct ssb_device *dev,
  179. u16 *offset)
  180. {
  181. struct ssb_bus *bus = dev->bus;
  182. int err;
  183. u8 need_segment;
  184. if (*offset >= 0x800) {
  185. *offset -= 0x800;
  186. need_segment = 1;
  187. } else
  188. need_segment = 0;
  189. if (unlikely(dev != bus->mapped_device)) {
  190. err = ssb_pcmcia_switch_core(bus, dev);
  191. if (unlikely(err))
  192. return err;
  193. }
  194. if (unlikely(need_segment != bus->mapped_pcmcia_seg)) {
  195. err = ssb_pcmcia_switch_segment(bus, need_segment);
  196. if (unlikely(err))
  197. return err;
  198. }
  199. return 0;
  200. }
  201. static u8 ssb_pcmcia_read8(struct ssb_device *dev, u16 offset)
  202. {
  203. struct ssb_bus *bus = dev->bus;
  204. unsigned long flags;
  205. int err;
  206. u8 value = 0xFF;
  207. spin_lock_irqsave(&bus->bar_lock, flags);
  208. err = select_core_and_segment(dev, &offset);
  209. if (likely(!err))
  210. value = readb(bus->mmio + offset);
  211. spin_unlock_irqrestore(&bus->bar_lock, flags);
  212. return value;
  213. }
  214. static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset)
  215. {
  216. struct ssb_bus *bus = dev->bus;
  217. unsigned long flags;
  218. int err;
  219. u16 value = 0xFFFF;
  220. spin_lock_irqsave(&bus->bar_lock, flags);
  221. err = select_core_and_segment(dev, &offset);
  222. if (likely(!err))
  223. value = readw(bus->mmio + offset);
  224. spin_unlock_irqrestore(&bus->bar_lock, flags);
  225. return value;
  226. }
  227. static u32 ssb_pcmcia_read32(struct ssb_device *dev, u16 offset)
  228. {
  229. struct ssb_bus *bus = dev->bus;
  230. unsigned long flags;
  231. int err;
  232. u32 lo = 0xFFFFFFFF, hi = 0xFFFFFFFF;
  233. spin_lock_irqsave(&bus->bar_lock, flags);
  234. err = select_core_and_segment(dev, &offset);
  235. if (likely(!err)) {
  236. lo = readw(bus->mmio + offset);
  237. hi = readw(bus->mmio + offset + 2);
  238. }
  239. spin_unlock_irqrestore(&bus->bar_lock, flags);
  240. return (lo | (hi << 16));
  241. }
  242. #ifdef CONFIG_SSB_BLOCKIO
  243. static void ssb_pcmcia_block_read(struct ssb_device *dev, void *buffer,
  244. size_t count, u16 offset, u8 reg_width)
  245. {
  246. struct ssb_bus *bus = dev->bus;
  247. unsigned long flags;
  248. void __iomem *addr = bus->mmio + offset;
  249. int err;
  250. spin_lock_irqsave(&bus->bar_lock, flags);
  251. err = select_core_and_segment(dev, &offset);
  252. if (unlikely(err)) {
  253. memset(buffer, 0xFF, count);
  254. goto unlock;
  255. }
  256. switch (reg_width) {
  257. case sizeof(u8): {
  258. u8 *buf = buffer;
  259. while (count) {
  260. *buf = __raw_readb(addr);
  261. buf++;
  262. count--;
  263. }
  264. break;
  265. }
  266. case sizeof(u16): {
  267. __le16 *buf = buffer;
  268. SSB_WARN_ON(count & 1);
  269. while (count) {
  270. *buf = (__force __le16)__raw_readw(addr);
  271. buf++;
  272. count -= 2;
  273. }
  274. break;
  275. }
  276. case sizeof(u32): {
  277. __le16 *buf = buffer;
  278. SSB_WARN_ON(count & 3);
  279. while (count) {
  280. *buf = (__force __le16)__raw_readw(addr);
  281. buf++;
  282. *buf = (__force __le16)__raw_readw(addr + 2);
  283. buf++;
  284. count -= 4;
  285. }
  286. break;
  287. }
  288. default:
  289. SSB_WARN_ON(1);
  290. }
  291. unlock:
  292. spin_unlock_irqrestore(&bus->bar_lock, flags);
  293. }
  294. #endif /* CONFIG_SSB_BLOCKIO */
  295. static void ssb_pcmcia_write8(struct ssb_device *dev, u16 offset, u8 value)
  296. {
  297. struct ssb_bus *bus = dev->bus;
  298. unsigned long flags;
  299. int err;
  300. spin_lock_irqsave(&bus->bar_lock, flags);
  301. err = select_core_and_segment(dev, &offset);
  302. if (likely(!err))
  303. writeb(value, bus->mmio + offset);
  304. mmiowb();
  305. spin_unlock_irqrestore(&bus->bar_lock, flags);
  306. }
  307. static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value)
  308. {
  309. struct ssb_bus *bus = dev->bus;
  310. unsigned long flags;
  311. int err;
  312. spin_lock_irqsave(&bus->bar_lock, flags);
  313. err = select_core_and_segment(dev, &offset);
  314. if (likely(!err))
  315. writew(value, bus->mmio + offset);
  316. mmiowb();
  317. spin_unlock_irqrestore(&bus->bar_lock, flags);
  318. }
  319. static void ssb_pcmcia_write32(struct ssb_device *dev, u16 offset, u32 value)
  320. {
  321. struct ssb_bus *bus = dev->bus;
  322. unsigned long flags;
  323. int err;
  324. spin_lock_irqsave(&bus->bar_lock, flags);
  325. err = select_core_and_segment(dev, &offset);
  326. if (likely(!err)) {
  327. writew((value & 0x0000FFFF), bus->mmio + offset);
  328. writew(((value & 0xFFFF0000) >> 16), bus->mmio + offset + 2);
  329. }
  330. mmiowb();
  331. spin_unlock_irqrestore(&bus->bar_lock, flags);
  332. }
  333. #ifdef CONFIG_SSB_BLOCKIO
  334. static void ssb_pcmcia_block_write(struct ssb_device *dev, const void *buffer,
  335. size_t count, u16 offset, u8 reg_width)
  336. {
  337. struct ssb_bus *bus = dev->bus;
  338. unsigned long flags;
  339. void __iomem *addr = bus->mmio + offset;
  340. int err;
  341. spin_lock_irqsave(&bus->bar_lock, flags);
  342. err = select_core_and_segment(dev, &offset);
  343. if (unlikely(err))
  344. goto unlock;
  345. switch (reg_width) {
  346. case sizeof(u8): {
  347. const u8 *buf = buffer;
  348. while (count) {
  349. __raw_writeb(*buf, addr);
  350. buf++;
  351. count--;
  352. }
  353. break;
  354. }
  355. case sizeof(u16): {
  356. const __le16 *buf = buffer;
  357. SSB_WARN_ON(count & 1);
  358. while (count) {
  359. __raw_writew((__force u16)(*buf), addr);
  360. buf++;
  361. count -= 2;
  362. }
  363. break;
  364. }
  365. case sizeof(u32): {
  366. const __le16 *buf = buffer;
  367. SSB_WARN_ON(count & 3);
  368. while (count) {
  369. __raw_writew((__force u16)(*buf), addr);
  370. buf++;
  371. __raw_writew((__force u16)(*buf), addr + 2);
  372. buf++;
  373. count -= 4;
  374. }
  375. break;
  376. }
  377. default:
  378. SSB_WARN_ON(1);
  379. }
  380. unlock:
  381. mmiowb();
  382. spin_unlock_irqrestore(&bus->bar_lock, flags);
  383. }
  384. #endif /* CONFIG_SSB_BLOCKIO */
  385. /* Not "static", as it's used in main.c */
  386. const struct ssb_bus_ops ssb_pcmcia_ops = {
  387. .read8 = ssb_pcmcia_read8,
  388. .read16 = ssb_pcmcia_read16,
  389. .read32 = ssb_pcmcia_read32,
  390. .write8 = ssb_pcmcia_write8,
  391. .write16 = ssb_pcmcia_write16,
  392. .write32 = ssb_pcmcia_write32,
  393. #ifdef CONFIG_SSB_BLOCKIO
  394. .block_read = ssb_pcmcia_block_read,
  395. .block_write = ssb_pcmcia_block_write,
  396. #endif
  397. };
  398. static int ssb_pcmcia_sprom_command(struct ssb_bus *bus, u8 command)
  399. {
  400. unsigned int i;
  401. int err;
  402. u8 value;
  403. err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROMCTL, command);
  404. if (err)
  405. return err;
  406. for (i = 0; i < 1000; i++) {
  407. err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROMCTL, &value);
  408. if (err)
  409. return err;
  410. if (value & SSB_PCMCIA_SPROMCTL_DONE)
  411. return 0;
  412. udelay(10);
  413. }
  414. return -ETIMEDOUT;
  415. }
  416. /* offset is the 16bit word offset */
  417. static int ssb_pcmcia_sprom_read(struct ssb_bus *bus, u16 offset, u16 *value)
  418. {
  419. int err;
  420. u8 lo, hi;
  421. offset *= 2; /* Make byte offset */
  422. err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRLO,
  423. (offset & 0x00FF));
  424. if (err)
  425. return err;
  426. err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRHI,
  427. (offset & 0xFF00) >> 8);
  428. if (err)
  429. return err;
  430. err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_READ);
  431. if (err)
  432. return err;
  433. err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROM_DATALO, &lo);
  434. if (err)
  435. return err;
  436. err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROM_DATAHI, &hi);
  437. if (err)
  438. return err;
  439. *value = (lo | (((u16)hi) << 8));
  440. return 0;
  441. }
  442. /* offset is the 16bit word offset */
  443. static int ssb_pcmcia_sprom_write(struct ssb_bus *bus, u16 offset, u16 value)
  444. {
  445. int err;
  446. offset *= 2; /* Make byte offset */
  447. err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRLO,
  448. (offset & 0x00FF));
  449. if (err)
  450. return err;
  451. err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRHI,
  452. (offset & 0xFF00) >> 8);
  453. if (err)
  454. return err;
  455. err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_DATALO,
  456. (value & 0x00FF));
  457. if (err)
  458. return err;
  459. err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_DATAHI,
  460. (value & 0xFF00) >> 8);
  461. if (err)
  462. return err;
  463. err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITE);
  464. if (err)
  465. return err;
  466. msleep(20);
  467. return 0;
  468. }
  469. /* Read the SPROM image. bufsize is in 16bit words. */
  470. static int ssb_pcmcia_sprom_read_all(struct ssb_bus *bus, u16 *sprom)
  471. {
  472. int err, i;
  473. for (i = 0; i < SSB_PCMCIA_SPROM_SIZE; i++) {
  474. err = ssb_pcmcia_sprom_read(bus, i, &sprom[i]);
  475. if (err)
  476. return err;
  477. }
  478. return 0;
  479. }
  480. /* Write the SPROM image. size is in 16bit words. */
  481. static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom)
  482. {
  483. int i, err;
  484. bool failed = 0;
  485. size_t size = SSB_PCMCIA_SPROM_SIZE;
  486. ssb_printk(KERN_NOTICE PFX
  487. "Writing SPROM. Do NOT turn off the power! "
  488. "Please stand by...\n");
  489. err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEEN);
  490. if (err) {
  491. ssb_printk(KERN_NOTICE PFX
  492. "Could not enable SPROM write access.\n");
  493. return -EBUSY;
  494. }
  495. ssb_printk(KERN_NOTICE PFX "[ 0%%");
  496. msleep(500);
  497. for (i = 0; i < size; i++) {
  498. if (i == size / 4)
  499. ssb_printk("25%%");
  500. else if (i == size / 2)
  501. ssb_printk("50%%");
  502. else if (i == (size * 3) / 4)
  503. ssb_printk("75%%");
  504. else if (i % 2)
  505. ssb_printk(".");
  506. err = ssb_pcmcia_sprom_write(bus, i, sprom[i]);
  507. if (err) {
  508. ssb_printk(KERN_NOTICE PFX
  509. "Failed to write to SPROM.\n");
  510. failed = 1;
  511. break;
  512. }
  513. }
  514. err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS);
  515. if (err) {
  516. ssb_printk(KERN_NOTICE PFX
  517. "Could not disable SPROM write access.\n");
  518. failed = 1;
  519. }
  520. msleep(500);
  521. if (!failed) {
  522. ssb_printk("100%% ]\n");
  523. ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
  524. }
  525. return failed ? -EBUSY : 0;
  526. }
  527. static int ssb_pcmcia_sprom_check_crc(const u16 *sprom, size_t size)
  528. {
  529. //TODO
  530. return 0;
  531. }
  532. #define GOTO_ERROR_ON(condition, description) do { \
  533. if (unlikely(condition)) { \
  534. error_description = description; \
  535. goto error; \
  536. } \
  537. } while (0)
  538. static int ssb_pcmcia_get_mac(struct pcmcia_device *p_dev,
  539. tuple_t *tuple,
  540. void *priv)
  541. {
  542. struct ssb_sprom *sprom = priv;
  543. if (tuple->TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID)
  544. return -EINVAL;
  545. if (tuple->TupleDataLen != ETH_ALEN + 2)
  546. return -EINVAL;
  547. if (tuple->TupleData[1] != ETH_ALEN)
  548. return -EINVAL;
  549. memcpy(sprom->il0mac, &tuple->TupleData[2], ETH_ALEN);
  550. return 0;
  551. };
  552. static int ssb_pcmcia_do_get_invariants(struct pcmcia_device *p_dev,
  553. tuple_t *tuple,
  554. void *priv)
  555. {
  556. struct ssb_init_invariants *iv = priv;
  557. struct ssb_sprom *sprom = &iv->sprom;
  558. struct ssb_boardinfo *bi = &iv->boardinfo;
  559. const char *error_description;
  560. GOTO_ERROR_ON(tuple->TupleDataLen < 1, "VEN tpl < 1");
  561. switch (tuple->TupleData[0]) {
  562. case SSB_PCMCIA_CIS_ID:
  563. GOTO_ERROR_ON((tuple->TupleDataLen != 5) &&
  564. (tuple->TupleDataLen != 7),
  565. "id tpl size");
  566. bi->vendor = tuple->TupleData[1] |
  567. ((u16)tuple->TupleData[2] << 8);
  568. break;
  569. case SSB_PCMCIA_CIS_BOARDREV:
  570. GOTO_ERROR_ON(tuple->TupleDataLen != 2,
  571. "boardrev tpl size");
  572. sprom->board_rev = tuple->TupleData[1];
  573. break;
  574. case SSB_PCMCIA_CIS_PA:
  575. GOTO_ERROR_ON((tuple->TupleDataLen != 9) &&
  576. (tuple->TupleDataLen != 10),
  577. "pa tpl size");
  578. sprom->pa0b0 = tuple->TupleData[1] |
  579. ((u16)tuple->TupleData[2] << 8);
  580. sprom->pa0b1 = tuple->TupleData[3] |
  581. ((u16)tuple->TupleData[4] << 8);
  582. sprom->pa0b2 = tuple->TupleData[5] |
  583. ((u16)tuple->TupleData[6] << 8);
  584. sprom->itssi_a = tuple->TupleData[7];
  585. sprom->itssi_bg = tuple->TupleData[7];
  586. sprom->maxpwr_a = tuple->TupleData[8];
  587. sprom->maxpwr_bg = tuple->TupleData[8];
  588. break;
  589. case SSB_PCMCIA_CIS_OEMNAME:
  590. /* We ignore this. */
  591. break;
  592. case SSB_PCMCIA_CIS_CCODE:
  593. GOTO_ERROR_ON(tuple->TupleDataLen != 2,
  594. "ccode tpl size");
  595. sprom->country_code = tuple->TupleData[1];
  596. break;
  597. case SSB_PCMCIA_CIS_ANTENNA:
  598. GOTO_ERROR_ON(tuple->TupleDataLen != 2,
  599. "ant tpl size");
  600. sprom->ant_available_a = tuple->TupleData[1];
  601. sprom->ant_available_bg = tuple->TupleData[1];
  602. break;
  603. case SSB_PCMCIA_CIS_ANTGAIN:
  604. GOTO_ERROR_ON(tuple->TupleDataLen != 2,
  605. "antg tpl size");
  606. sprom->antenna_gain.ghz24.a0 = tuple->TupleData[1];
  607. sprom->antenna_gain.ghz24.a1 = tuple->TupleData[1];
  608. sprom->antenna_gain.ghz24.a2 = tuple->TupleData[1];
  609. sprom->antenna_gain.ghz24.a3 = tuple->TupleData[1];
  610. sprom->antenna_gain.ghz5.a0 = tuple->TupleData[1];
  611. sprom->antenna_gain.ghz5.a1 = tuple->TupleData[1];
  612. sprom->antenna_gain.ghz5.a2 = tuple->TupleData[1];
  613. sprom->antenna_gain.ghz5.a3 = tuple->TupleData[1];
  614. break;
  615. case SSB_PCMCIA_CIS_BFLAGS:
  616. GOTO_ERROR_ON((tuple->TupleDataLen != 3) &&
  617. (tuple->TupleDataLen != 5),
  618. "bfl tpl size");
  619. sprom->boardflags_lo = tuple->TupleData[1] |
  620. ((u16)tuple->TupleData[2] << 8);
  621. break;
  622. case SSB_PCMCIA_CIS_LEDS:
  623. GOTO_ERROR_ON(tuple->TupleDataLen != 5,
  624. "leds tpl size");
  625. sprom->gpio0 = tuple->TupleData[1];
  626. sprom->gpio1 = tuple->TupleData[2];
  627. sprom->gpio2 = tuple->TupleData[3];
  628. sprom->gpio3 = tuple->TupleData[4];
  629. break;
  630. }
  631. return -ENOSPC; /* continue with next entry */
  632. error:
  633. ssb_printk(KERN_ERR PFX
  634. "PCMCIA: Failed to fetch device invariants: %s\n",
  635. error_description);
  636. return -ENODEV;
  637. }
  638. int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
  639. struct ssb_init_invariants *iv)
  640. {
  641. struct ssb_sprom *sprom = &iv->sprom;
  642. int res;
  643. memset(sprom, 0xFF, sizeof(*sprom));
  644. sprom->revision = 1;
  645. sprom->boardflags_lo = 0;
  646. sprom->boardflags_hi = 0;
  647. /* First fetch the MAC address. */
  648. res = pcmcia_loop_tuple(bus->host_pcmcia, CISTPL_FUNCE,
  649. ssb_pcmcia_get_mac, sprom);
  650. if (res != 0) {
  651. ssb_printk(KERN_ERR PFX
  652. "PCMCIA: Failed to fetch MAC address\n");
  653. return -ENODEV;
  654. }
  655. /* Fetch the vendor specific tuples. */
  656. res = pcmcia_loop_tuple(bus->host_pcmcia, SSB_PCMCIA_CIS,
  657. ssb_pcmcia_do_get_invariants, sprom);
  658. if ((res == 0) || (res == -ENOSPC))
  659. return 0;
  660. ssb_printk(KERN_ERR PFX
  661. "PCMCIA: Failed to fetch device invariants\n");
  662. return -ENODEV;
  663. }
  664. static ssize_t ssb_pcmcia_attr_sprom_show(struct device *pcmciadev,
  665. struct device_attribute *attr,
  666. char *buf)
  667. {
  668. struct pcmcia_device *pdev =
  669. container_of(pcmciadev, struct pcmcia_device, dev);
  670. struct ssb_bus *bus;
  671. bus = ssb_pcmcia_dev_to_bus(pdev);
  672. if (!bus)
  673. return -ENODEV;
  674. return ssb_attr_sprom_show(bus, buf,
  675. ssb_pcmcia_sprom_read_all);
  676. }
  677. static ssize_t ssb_pcmcia_attr_sprom_store(struct device *pcmciadev,
  678. struct device_attribute *attr,
  679. const char *buf, size_t count)
  680. {
  681. struct pcmcia_device *pdev =
  682. container_of(pcmciadev, struct pcmcia_device, dev);
  683. struct ssb_bus *bus;
  684. bus = ssb_pcmcia_dev_to_bus(pdev);
  685. if (!bus)
  686. return -ENODEV;
  687. return ssb_attr_sprom_store(bus, buf, count,
  688. ssb_pcmcia_sprom_check_crc,
  689. ssb_pcmcia_sprom_write_all);
  690. }
  691. static DEVICE_ATTR(ssb_sprom, 0600,
  692. ssb_pcmcia_attr_sprom_show,
  693. ssb_pcmcia_attr_sprom_store);
  694. static int ssb_pcmcia_cor_setup(struct ssb_bus *bus, u8 cor)
  695. {
  696. u8 val;
  697. int err;
  698. err = ssb_pcmcia_cfg_read(bus, cor, &val);
  699. if (err)
  700. return err;
  701. val &= ~COR_SOFT_RESET;
  702. val |= COR_FUNC_ENA | COR_IREQ_ENA | COR_LEVEL_REQ;
  703. err = ssb_pcmcia_cfg_write(bus, cor, val);
  704. if (err)
  705. return err;
  706. msleep(40);
  707. return 0;
  708. }
  709. /* Initialize the PCMCIA hardware. This is called on Init and Resume. */
  710. int ssb_pcmcia_hardware_setup(struct ssb_bus *bus)
  711. {
  712. int err;
  713. if (bus->bustype != SSB_BUSTYPE_PCMCIA)
  714. return 0;
  715. /* Switch segment to a known state and sync
  716. * bus->mapped_pcmcia_seg with hardware state. */
  717. ssb_pcmcia_switch_segment(bus, 0);
  718. /* Init the COR register. */
  719. err = ssb_pcmcia_cor_setup(bus, CISREG_COR);
  720. if (err)
  721. return err;
  722. /* Some cards also need this register to get poked. */
  723. err = ssb_pcmcia_cor_setup(bus, CISREG_COR + 0x80);
  724. if (err)
  725. return err;
  726. return 0;
  727. }
  728. void ssb_pcmcia_exit(struct ssb_bus *bus)
  729. {
  730. if (bus->bustype != SSB_BUSTYPE_PCMCIA)
  731. return;
  732. device_remove_file(&bus->host_pcmcia->dev, &dev_attr_ssb_sprom);
  733. }
  734. int ssb_pcmcia_init(struct ssb_bus *bus)
  735. {
  736. int err;
  737. if (bus->bustype != SSB_BUSTYPE_PCMCIA)
  738. return 0;
  739. err = ssb_pcmcia_hardware_setup(bus);
  740. if (err)
  741. goto error;
  742. bus->sprom_size = SSB_PCMCIA_SPROM_SIZE;
  743. mutex_init(&bus->sprom_mutex);
  744. err = device_create_file(&bus->host_pcmcia->dev, &dev_attr_ssb_sprom);
  745. if (err)
  746. goto error;
  747. return 0;
  748. error:
  749. ssb_printk(KERN_ERR PFX "Failed to initialize PCMCIA host device\n");
  750. return err;
  751. }