fsl_ifc.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /*
  2. * Copyright 2011 Freescale Semiconductor, Inc
  3. *
  4. * Freescale Integrated Flash Controller
  5. *
  6. * Author: Dipen Dudhat <Dipen.Dudhat@freescale.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by the
  10. * Free Software Foundation; either version 2 of the License, or (at your
  11. * option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21. */
  22. #include <linux/module.h>
  23. #include <linux/kernel.h>
  24. #include <linux/compiler.h>
  25. #include <linux/sched.h>
  26. #include <linux/spinlock.h>
  27. #include <linux/types.h>
  28. #include <linux/slab.h>
  29. #include <linux/io.h>
  30. #include <linux/of.h>
  31. #include <linux/of_device.h>
  32. #include <linux/platform_device.h>
  33. #include <linux/fsl_ifc.h>
  34. #include <linux/irqdomain.h>
  35. #include <linux/of_address.h>
  36. #include <linux/of_irq.h>
  37. struct fsl_ifc_ctrl *fsl_ifc_ctrl_dev;
  38. EXPORT_SYMBOL(fsl_ifc_ctrl_dev);
  39. /*
  40. * convert_ifc_address - convert the base address
  41. * @addr_base: base address of the memory bank
  42. */
  43. unsigned int convert_ifc_address(phys_addr_t addr_base)
  44. {
  45. return addr_base & CSPR_BA;
  46. }
  47. EXPORT_SYMBOL(convert_ifc_address);
  48. /*
  49. * fsl_ifc_find - find IFC bank
  50. * @addr_base: base address of the memory bank
  51. *
  52. * This function walks IFC banks comparing "Base address" field of the CSPR
  53. * registers with the supplied addr_base argument. When bases match this
  54. * function returns bank number (starting with 0), otherwise it returns
  55. * appropriate errno value.
  56. */
  57. int fsl_ifc_find(phys_addr_t addr_base)
  58. {
  59. int i = 0;
  60. if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->gregs)
  61. return -ENODEV;
  62. for (i = 0; i < fsl_ifc_ctrl_dev->banks; i++) {
  63. u32 cspr = ifc_in32(&fsl_ifc_ctrl_dev->gregs->cspr_cs[i].cspr);
  64. if (cspr & CSPR_V && (cspr & CSPR_BA) ==
  65. convert_ifc_address(addr_base))
  66. return i;
  67. }
  68. return -ENOENT;
  69. }
  70. EXPORT_SYMBOL(fsl_ifc_find);
  71. static int fsl_ifc_ctrl_init(struct fsl_ifc_ctrl *ctrl)
  72. {
  73. struct fsl_ifc_global __iomem *ifc = ctrl->gregs;
  74. /*
  75. * Clear all the common status and event registers
  76. */
  77. if (ifc_in32(&ifc->cm_evter_stat) & IFC_CM_EVTER_STAT_CSER)
  78. ifc_out32(IFC_CM_EVTER_STAT_CSER, &ifc->cm_evter_stat);
  79. /* enable all error and events */
  80. ifc_out32(IFC_CM_EVTER_EN_CSEREN, &ifc->cm_evter_en);
  81. /* enable all error and event interrupts */
  82. ifc_out32(IFC_CM_EVTER_INTR_EN_CSERIREN, &ifc->cm_evter_intr_en);
  83. ifc_out32(0x0, &ifc->cm_erattr0);
  84. ifc_out32(0x0, &ifc->cm_erattr1);
  85. return 0;
  86. }
  87. static int fsl_ifc_ctrl_remove(struct platform_device *dev)
  88. {
  89. struct fsl_ifc_ctrl *ctrl = dev_get_drvdata(&dev->dev);
  90. free_irq(ctrl->nand_irq, ctrl);
  91. free_irq(ctrl->irq, ctrl);
  92. irq_dispose_mapping(ctrl->nand_irq);
  93. irq_dispose_mapping(ctrl->irq);
  94. iounmap(ctrl->gregs);
  95. dev_set_drvdata(&dev->dev, NULL);
  96. kfree(ctrl);
  97. return 0;
  98. }
  99. /*
  100. * NAND events are split between an operational interrupt which only
  101. * receives OPC, and an error interrupt that receives everything else,
  102. * including non-NAND errors. Whichever interrupt gets to it first
  103. * records the status and wakes the wait queue.
  104. */
  105. static DEFINE_SPINLOCK(nand_irq_lock);
  106. static u32 check_nand_stat(struct fsl_ifc_ctrl *ctrl)
  107. {
  108. struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs;
  109. unsigned long flags;
  110. u32 stat;
  111. spin_lock_irqsave(&nand_irq_lock, flags);
  112. stat = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
  113. if (stat) {
  114. ifc_out32(stat, &ifc->ifc_nand.nand_evter_stat);
  115. ctrl->nand_stat = stat;
  116. wake_up(&ctrl->nand_wait);
  117. }
  118. spin_unlock_irqrestore(&nand_irq_lock, flags);
  119. return stat;
  120. }
  121. static irqreturn_t fsl_ifc_nand_irq(int irqno, void *data)
  122. {
  123. struct fsl_ifc_ctrl *ctrl = data;
  124. if (check_nand_stat(ctrl))
  125. return IRQ_HANDLED;
  126. return IRQ_NONE;
  127. }
  128. /*
  129. * NOTE: This interrupt is used to report ifc events of various kinds,
  130. * such as transaction errors on the chipselects.
  131. */
  132. static irqreturn_t fsl_ifc_ctrl_irq(int irqno, void *data)
  133. {
  134. struct fsl_ifc_ctrl *ctrl = data;
  135. struct fsl_ifc_global __iomem *ifc = ctrl->gregs;
  136. u32 err_axiid, err_srcid, status, cs_err, err_addr;
  137. irqreturn_t ret = IRQ_NONE;
  138. /* read for chip select error */
  139. cs_err = ifc_in32(&ifc->cm_evter_stat);
  140. if (cs_err) {
  141. dev_err(ctrl->dev, "transaction sent to IFC is not mapped to"
  142. "any memory bank 0x%08X\n", cs_err);
  143. /* clear the chip select error */
  144. ifc_out32(IFC_CM_EVTER_STAT_CSER, &ifc->cm_evter_stat);
  145. /* read error attribute registers print the error information */
  146. status = ifc_in32(&ifc->cm_erattr0);
  147. err_addr = ifc_in32(&ifc->cm_erattr1);
  148. if (status & IFC_CM_ERATTR0_ERTYP_READ)
  149. dev_err(ctrl->dev, "Read transaction error"
  150. "CM_ERATTR0 0x%08X\n", status);
  151. else
  152. dev_err(ctrl->dev, "Write transaction error"
  153. "CM_ERATTR0 0x%08X\n", status);
  154. err_axiid = (status & IFC_CM_ERATTR0_ERAID) >>
  155. IFC_CM_ERATTR0_ERAID_SHIFT;
  156. dev_err(ctrl->dev, "AXI ID of the error"
  157. "transaction 0x%08X\n", err_axiid);
  158. err_srcid = (status & IFC_CM_ERATTR0_ESRCID) >>
  159. IFC_CM_ERATTR0_ESRCID_SHIFT;
  160. dev_err(ctrl->dev, "SRC ID of the error"
  161. "transaction 0x%08X\n", err_srcid);
  162. dev_err(ctrl->dev, "Transaction Address corresponding to error"
  163. "ERADDR 0x%08X\n", err_addr);
  164. ret = IRQ_HANDLED;
  165. }
  166. if (check_nand_stat(ctrl))
  167. ret = IRQ_HANDLED;
  168. return ret;
  169. }
  170. /*
  171. * fsl_ifc_ctrl_probe
  172. *
  173. * called by device layer when it finds a device matching
  174. * one our driver can handled. This code allocates all of
  175. * the resources needed for the controller only. The
  176. * resources for the NAND banks themselves are allocated
  177. * in the chip probe function.
  178. */
  179. static int fsl_ifc_ctrl_probe(struct platform_device *dev)
  180. {
  181. int ret = 0;
  182. int version, banks;
  183. void __iomem *addr;
  184. dev_info(&dev->dev, "Freescale Integrated Flash Controller\n");
  185. fsl_ifc_ctrl_dev = kzalloc(sizeof(*fsl_ifc_ctrl_dev), GFP_KERNEL);
  186. if (!fsl_ifc_ctrl_dev)
  187. return -ENOMEM;
  188. dev_set_drvdata(&dev->dev, fsl_ifc_ctrl_dev);
  189. /* IOMAP the entire IFC region */
  190. fsl_ifc_ctrl_dev->gregs = of_iomap(dev->dev.of_node, 0);
  191. if (!fsl_ifc_ctrl_dev->gregs) {
  192. dev_err(&dev->dev, "failed to get memory region\n");
  193. ret = -ENODEV;
  194. goto err;
  195. }
  196. if (of_property_read_bool(dev->dev.of_node, "little-endian")) {
  197. fsl_ifc_ctrl_dev->little_endian = true;
  198. dev_dbg(&dev->dev, "IFC REGISTERS are LITTLE endian\n");
  199. } else {
  200. fsl_ifc_ctrl_dev->little_endian = false;
  201. dev_dbg(&dev->dev, "IFC REGISTERS are BIG endian\n");
  202. }
  203. version = ifc_in32(&fsl_ifc_ctrl_dev->gregs->ifc_rev) &
  204. FSL_IFC_VERSION_MASK;
  205. banks = (version == FSL_IFC_VERSION_1_0_0) ? 4 : 8;
  206. dev_info(&dev->dev, "IFC version %d.%d, %d banks\n",
  207. version >> 24, (version >> 16) & 0xf, banks);
  208. fsl_ifc_ctrl_dev->version = version;
  209. fsl_ifc_ctrl_dev->banks = banks;
  210. addr = fsl_ifc_ctrl_dev->gregs;
  211. if (version >= FSL_IFC_VERSION_2_0_0)
  212. addr += PGOFFSET_64K;
  213. else
  214. addr += PGOFFSET_4K;
  215. fsl_ifc_ctrl_dev->rregs = addr;
  216. /* get the Controller level irq */
  217. fsl_ifc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0);
  218. if (fsl_ifc_ctrl_dev->irq == 0) {
  219. dev_err(&dev->dev, "failed to get irq resource "
  220. "for IFC\n");
  221. ret = -ENODEV;
  222. goto err;
  223. }
  224. /* get the nand machine irq */
  225. fsl_ifc_ctrl_dev->nand_irq =
  226. irq_of_parse_and_map(dev->dev.of_node, 1);
  227. fsl_ifc_ctrl_dev->dev = &dev->dev;
  228. ret = fsl_ifc_ctrl_init(fsl_ifc_ctrl_dev);
  229. if (ret < 0)
  230. goto err;
  231. init_waitqueue_head(&fsl_ifc_ctrl_dev->nand_wait);
  232. ret = request_irq(fsl_ifc_ctrl_dev->irq, fsl_ifc_ctrl_irq, IRQF_SHARED,
  233. "fsl-ifc", fsl_ifc_ctrl_dev);
  234. if (ret != 0) {
  235. dev_err(&dev->dev, "failed to install irq (%d)\n",
  236. fsl_ifc_ctrl_dev->irq);
  237. goto err_irq;
  238. }
  239. if (fsl_ifc_ctrl_dev->nand_irq) {
  240. ret = request_irq(fsl_ifc_ctrl_dev->nand_irq, fsl_ifc_nand_irq,
  241. 0, "fsl-ifc-nand", fsl_ifc_ctrl_dev);
  242. if (ret != 0) {
  243. dev_err(&dev->dev, "failed to install irq (%d)\n",
  244. fsl_ifc_ctrl_dev->nand_irq);
  245. goto err_nandirq;
  246. }
  247. }
  248. return 0;
  249. err_nandirq:
  250. free_irq(fsl_ifc_ctrl_dev->nand_irq, fsl_ifc_ctrl_dev);
  251. irq_dispose_mapping(fsl_ifc_ctrl_dev->nand_irq);
  252. err_irq:
  253. free_irq(fsl_ifc_ctrl_dev->irq, fsl_ifc_ctrl_dev);
  254. irq_dispose_mapping(fsl_ifc_ctrl_dev->irq);
  255. err:
  256. return ret;
  257. }
  258. static const struct of_device_id fsl_ifc_match[] = {
  259. {
  260. .compatible = "fsl,ifc",
  261. },
  262. {},
  263. };
  264. static struct platform_driver fsl_ifc_ctrl_driver = {
  265. .driver = {
  266. .name = "fsl-ifc",
  267. .of_match_table = fsl_ifc_match,
  268. },
  269. .probe = fsl_ifc_ctrl_probe,
  270. .remove = fsl_ifc_ctrl_remove,
  271. };
  272. static int __init fsl_ifc_init(void)
  273. {
  274. return platform_driver_register(&fsl_ifc_ctrl_driver);
  275. }
  276. subsys_initcall(fsl_ifc_init);
  277. MODULE_LICENSE("GPL");
  278. MODULE_AUTHOR("Freescale Semiconductor");
  279. MODULE_DESCRIPTION("Freescale Integrated Flash Controller driver");