bcm47xxsflash.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. #include <linux/kernel.h>
  2. #include <linux/module.h>
  3. #include <linux/slab.h>
  4. #include <linux/delay.h>
  5. #include <linux/mtd/mtd.h>
  6. #include <linux/platform_device.h>
  7. #include <linux/bcma/bcma.h>
  8. #include "bcm47xxsflash.h"
  9. MODULE_LICENSE("GPL");
  10. MODULE_DESCRIPTION("Serial flash driver for BCMA bus");
  11. static const char * const probes[] = { "bcm47xxpart", NULL };
  12. /**************************************************
  13. * Various helpers
  14. **************************************************/
  15. static void bcm47xxsflash_cmd(struct bcm47xxsflash *b47s, u32 opcode)
  16. {
  17. int i;
  18. b47s->cc_write(b47s, BCMA_CC_FLASHCTL, BCMA_CC_FLASHCTL_START | opcode);
  19. for (i = 0; i < 1000; i++) {
  20. if (!(b47s->cc_read(b47s, BCMA_CC_FLASHCTL) &
  21. BCMA_CC_FLASHCTL_BUSY))
  22. return;
  23. cpu_relax();
  24. }
  25. pr_err("Control command failed (timeout)!\n");
  26. }
  27. static int bcm47xxsflash_poll(struct bcm47xxsflash *b47s, int timeout)
  28. {
  29. unsigned long deadline = jiffies + timeout;
  30. do {
  31. switch (b47s->type) {
  32. case BCM47XXSFLASH_TYPE_ST:
  33. bcm47xxsflash_cmd(b47s, OPCODE_ST_RDSR);
  34. if (!(b47s->cc_read(b47s, BCMA_CC_FLASHDATA) &
  35. SR_ST_WIP))
  36. return 0;
  37. break;
  38. case BCM47XXSFLASH_TYPE_ATMEL:
  39. bcm47xxsflash_cmd(b47s, OPCODE_AT_STATUS);
  40. if (b47s->cc_read(b47s, BCMA_CC_FLASHDATA) &
  41. SR_AT_READY)
  42. return 0;
  43. break;
  44. }
  45. cpu_relax();
  46. udelay(1);
  47. } while (!time_after_eq(jiffies, deadline));
  48. pr_err("Timeout waiting for flash to be ready!\n");
  49. return -EBUSY;
  50. }
  51. /**************************************************
  52. * MTD ops
  53. **************************************************/
  54. static int bcm47xxsflash_erase(struct mtd_info *mtd, struct erase_info *erase)
  55. {
  56. struct bcm47xxsflash *b47s = mtd->priv;
  57. int err;
  58. switch (b47s->type) {
  59. case BCM47XXSFLASH_TYPE_ST:
  60. bcm47xxsflash_cmd(b47s, OPCODE_ST_WREN);
  61. b47s->cc_write(b47s, BCMA_CC_FLASHADDR, erase->addr);
  62. /* Newer flashes have "sub-sectors" which can be erased
  63. * independently with a new command: ST_SSE. The ST_SE command
  64. * erases 64KB just as before.
  65. */
  66. if (b47s->blocksize < (64 * 1024))
  67. bcm47xxsflash_cmd(b47s, OPCODE_ST_SSE);
  68. else
  69. bcm47xxsflash_cmd(b47s, OPCODE_ST_SE);
  70. break;
  71. case BCM47XXSFLASH_TYPE_ATMEL:
  72. b47s->cc_write(b47s, BCMA_CC_FLASHADDR, erase->addr << 1);
  73. bcm47xxsflash_cmd(b47s, OPCODE_AT_PAGE_ERASE);
  74. break;
  75. }
  76. err = bcm47xxsflash_poll(b47s, HZ);
  77. if (err)
  78. erase->state = MTD_ERASE_FAILED;
  79. else
  80. erase->state = MTD_ERASE_DONE;
  81. if (erase->callback)
  82. erase->callback(erase);
  83. return err;
  84. }
  85. static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len,
  86. size_t *retlen, u_char *buf)
  87. {
  88. struct bcm47xxsflash *b47s = mtd->priv;
  89. /* Check address range */
  90. if ((from + len) > mtd->size)
  91. return -EINVAL;
  92. memcpy_fromio(buf, (void __iomem *)KSEG0ADDR(b47s->window + from),
  93. len);
  94. *retlen = len;
  95. return len;
  96. }
  97. static int bcm47xxsflash_write_st(struct mtd_info *mtd, u32 offset, size_t len,
  98. const u_char *buf)
  99. {
  100. struct bcm47xxsflash *b47s = mtd->priv;
  101. int written = 0;
  102. /* Enable writes */
  103. bcm47xxsflash_cmd(b47s, OPCODE_ST_WREN);
  104. /* Write first byte */
  105. b47s->cc_write(b47s, BCMA_CC_FLASHADDR, offset);
  106. b47s->cc_write(b47s, BCMA_CC_FLASHDATA, *buf++);
  107. /* Program page */
  108. if (b47s->bcma_cc->core->id.rev < 20) {
  109. bcm47xxsflash_cmd(b47s, OPCODE_ST_PP);
  110. return 1; /* 1B written */
  111. }
  112. /* Program page and set CSA (on newer chips we can continue writing) */
  113. bcm47xxsflash_cmd(b47s, OPCODE_ST_CSA | OPCODE_ST_PP);
  114. offset++;
  115. len--;
  116. written++;
  117. while (len > 0) {
  118. /* Page boundary, another function call is needed */
  119. if ((offset & 0xFF) == 0)
  120. break;
  121. bcm47xxsflash_cmd(b47s, OPCODE_ST_CSA | *buf++);
  122. offset++;
  123. len--;
  124. written++;
  125. }
  126. /* All done, drop CSA & poll */
  127. b47s->cc_write(b47s, BCMA_CC_FLASHCTL, 0);
  128. udelay(1);
  129. if (bcm47xxsflash_poll(b47s, HZ / 10))
  130. pr_err("Flash rejected dropping CSA\n");
  131. return written;
  132. }
  133. static int bcm47xxsflash_write_at(struct mtd_info *mtd, u32 offset, size_t len,
  134. const u_char *buf)
  135. {
  136. struct bcm47xxsflash *b47s = mtd->priv;
  137. u32 mask = b47s->blocksize - 1;
  138. u32 page = (offset & ~mask) << 1;
  139. u32 byte = offset & mask;
  140. int written = 0;
  141. /* If we don't overwrite whole page, read it to the buffer first */
  142. if (byte || (len < b47s->blocksize)) {
  143. int err;
  144. b47s->cc_write(b47s, BCMA_CC_FLASHADDR, page);
  145. bcm47xxsflash_cmd(b47s, OPCODE_AT_BUF1_LOAD);
  146. /* 250 us for AT45DB321B */
  147. err = bcm47xxsflash_poll(b47s, HZ / 1000);
  148. if (err) {
  149. pr_err("Timeout reading page 0x%X info buffer\n", page);
  150. return err;
  151. }
  152. }
  153. /* Change buffer content with our data */
  154. while (len > 0) {
  155. /* Page boundary, another function call is needed */
  156. if (byte == b47s->blocksize)
  157. break;
  158. b47s->cc_write(b47s, BCMA_CC_FLASHADDR, byte++);
  159. b47s->cc_write(b47s, BCMA_CC_FLASHDATA, *buf++);
  160. bcm47xxsflash_cmd(b47s, OPCODE_AT_BUF1_WRITE);
  161. len--;
  162. written++;
  163. }
  164. /* Program page with the buffer content */
  165. b47s->cc_write(b47s, BCMA_CC_FLASHADDR, page);
  166. bcm47xxsflash_cmd(b47s, OPCODE_AT_BUF1_PROGRAM);
  167. return written;
  168. }
  169. static int bcm47xxsflash_write(struct mtd_info *mtd, loff_t to, size_t len,
  170. size_t *retlen, const u_char *buf)
  171. {
  172. struct bcm47xxsflash *b47s = mtd->priv;
  173. int written;
  174. /* Writing functions can return without writing all passed data, for
  175. * example when the hardware is too old or when we git page boundary.
  176. */
  177. while (len > 0) {
  178. switch (b47s->type) {
  179. case BCM47XXSFLASH_TYPE_ST:
  180. written = bcm47xxsflash_write_st(mtd, to, len, buf);
  181. break;
  182. case BCM47XXSFLASH_TYPE_ATMEL:
  183. written = bcm47xxsflash_write_at(mtd, to, len, buf);
  184. break;
  185. default:
  186. BUG_ON(1);
  187. }
  188. if (written < 0) {
  189. pr_err("Error writing at offset 0x%llX\n", to);
  190. return written;
  191. }
  192. to += (loff_t)written;
  193. len -= written;
  194. *retlen += written;
  195. buf += written;
  196. }
  197. return 0;
  198. }
  199. static void bcm47xxsflash_fill_mtd(struct bcm47xxsflash *b47s,
  200. struct device *dev)
  201. {
  202. struct mtd_info *mtd = &b47s->mtd;
  203. mtd->priv = b47s;
  204. mtd->dev.parent = dev;
  205. mtd->name = "bcm47xxsflash";
  206. mtd->type = MTD_NORFLASH;
  207. mtd->flags = MTD_CAP_NORFLASH;
  208. mtd->size = b47s->size;
  209. mtd->erasesize = b47s->blocksize;
  210. mtd->writesize = 1;
  211. mtd->writebufsize = 1;
  212. mtd->_erase = bcm47xxsflash_erase;
  213. mtd->_read = bcm47xxsflash_read;
  214. mtd->_write = bcm47xxsflash_write;
  215. }
  216. /**************************************************
  217. * BCMA
  218. **************************************************/
  219. static int bcm47xxsflash_bcma_cc_read(struct bcm47xxsflash *b47s, u16 offset)
  220. {
  221. return bcma_cc_read32(b47s->bcma_cc, offset);
  222. }
  223. static void bcm47xxsflash_bcma_cc_write(struct bcm47xxsflash *b47s, u16 offset,
  224. u32 value)
  225. {
  226. bcma_cc_write32(b47s->bcma_cc, offset, value);
  227. }
  228. static int bcm47xxsflash_bcma_probe(struct platform_device *pdev)
  229. {
  230. struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev);
  231. struct bcm47xxsflash *b47s;
  232. int err;
  233. b47s = devm_kzalloc(&pdev->dev, sizeof(*b47s), GFP_KERNEL);
  234. if (!b47s)
  235. return -ENOMEM;
  236. sflash->priv = b47s;
  237. b47s->bcma_cc = container_of(sflash, struct bcma_drv_cc, sflash);
  238. b47s->cc_read = bcm47xxsflash_bcma_cc_read;
  239. b47s->cc_write = bcm47xxsflash_bcma_cc_write;
  240. switch (b47s->bcma_cc->capabilities & BCMA_CC_CAP_FLASHT) {
  241. case BCMA_CC_FLASHT_STSER:
  242. b47s->type = BCM47XXSFLASH_TYPE_ST;
  243. break;
  244. case BCMA_CC_FLASHT_ATSER:
  245. b47s->type = BCM47XXSFLASH_TYPE_ATMEL;
  246. break;
  247. }
  248. b47s->window = sflash->window;
  249. b47s->blocksize = sflash->blocksize;
  250. b47s->numblocks = sflash->numblocks;
  251. b47s->size = sflash->size;
  252. bcm47xxsflash_fill_mtd(b47s, &pdev->dev);
  253. err = mtd_device_parse_register(&b47s->mtd, probes, NULL, NULL, 0);
  254. if (err) {
  255. pr_err("Failed to register MTD device: %d\n", err);
  256. return err;
  257. }
  258. if (bcm47xxsflash_poll(b47s, HZ / 10))
  259. pr_warn("Serial flash busy\n");
  260. return 0;
  261. }
  262. static int bcm47xxsflash_bcma_remove(struct platform_device *pdev)
  263. {
  264. struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev);
  265. struct bcm47xxsflash *b47s = sflash->priv;
  266. mtd_device_unregister(&b47s->mtd);
  267. return 0;
  268. }
  269. static struct platform_driver bcma_sflash_driver = {
  270. .probe = bcm47xxsflash_bcma_probe,
  271. .remove = bcm47xxsflash_bcma_remove,
  272. .driver = {
  273. .name = "bcma_sflash",
  274. },
  275. };
  276. /**************************************************
  277. * Init
  278. **************************************************/
  279. module_platform_driver(bcma_sflash_driver);