0001-nand-brcmnand-add-iproc-support.patch 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. From 854dc4b790ce1291326d52b8405ebe771bff2edd Mon Sep 17 00:00:00 2001
  2. From: Linus Walleij <[email protected]>
  3. Date: Wed, 8 Mar 2023 22:42:31 +0100
  4. Subject: [PATCH 1/5] nand: brcmnand: add iproc support
  5. Add support for the iproc Broadcom NAND controller,
  6. used in Northstar SoCs for example. Based on the Linux
  7. driver.
  8. Cc: Philippe Reynes <[email protected]>
  9. Cc: Dario Binacchi <[email protected]>
  10. Reviewed-by: Michael Trimarchi <[email protected]>
  11. Signed-off-by: Linus Walleij <[email protected]>
  12. Acked-by: William Zhang <[email protected]>
  13. Link: https://lore.kernel.org/all/[email protected]/
  14. Signed-off-by: Dario Binacchi <[email protected]>
  15. ---
  16. drivers/mtd/nand/raw/Kconfig | 7 +
  17. drivers/mtd/nand/raw/brcmnand/Makefile | 1 +
  18. drivers/mtd/nand/raw/brcmnand/iproc_nand.c | 148 +++++++++++++++++++++
  19. 3 files changed, 156 insertions(+)
  20. create mode 100644 drivers/mtd/nand/raw/brcmnand/iproc_nand.c
  21. --- a/drivers/mtd/nand/raw/Kconfig
  22. +++ b/drivers/mtd/nand/raw/Kconfig
  23. @@ -156,6 +156,13 @@ config NAND_BRCMNAND_63158
  24. help
  25. Enable support for broadcom nand driver on bcm63158.
  26. +config NAND_BRCMNAND_IPROC
  27. + bool "Support Broadcom NAND controller on the iproc family"
  28. + depends on NAND_BRCMNAND
  29. + help
  30. + Enable support for broadcom nand driver on the Broadcom
  31. + iproc family such as Northstar (BCM5301x, BCM4708...)
  32. +
  33. config NAND_DAVINCI
  34. bool "Support TI Davinci NAND controller"
  35. select SYS_NAND_SELF_INIT if TARGET_DA850EVM
  36. --- a/drivers/mtd/nand/raw/brcmnand/Makefile
  37. +++ b/drivers/mtd/nand/raw/brcmnand/Makefile
  38. @@ -6,5 +6,6 @@ obj-$(CONFIG_NAND_BRCMNAND_6753) += bcm6
  39. obj-$(CONFIG_NAND_BRCMNAND_68360) += bcm68360_nand.o
  40. obj-$(CONFIG_NAND_BRCMNAND_6838) += bcm6838_nand.o
  41. obj-$(CONFIG_NAND_BRCMNAND_6858) += bcm6858_nand.o
  42. +obj-$(CONFIG_NAND_BRCMNAND_IPROC) += iproc_nand.o
  43. obj-$(CONFIG_NAND_BRCMNAND) += brcmnand.o
  44. obj-$(CONFIG_NAND_BRCMNAND) += brcmnand_compat.o
  45. --- /dev/null
  46. +++ b/drivers/mtd/nand/raw/brcmnand/iproc_nand.c
  47. @@ -0,0 +1,148 @@
  48. +// SPDX-License-Identifier: GPL-2.0
  49. +/*
  50. + * Code borrowed from the Linux driver
  51. + * Copyright (C) 2015 Broadcom Corporation
  52. + */
  53. +
  54. +#include <common.h>
  55. +#include <asm/io.h>
  56. +#include <memalign.h>
  57. +#include <nand.h>
  58. +#include <linux/bitops.h>
  59. +#include <linux/err.h>
  60. +#include <linux/errno.h>
  61. +#include <linux/io.h>
  62. +#include <linux/ioport.h>
  63. +#include <dm.h>
  64. +
  65. +#include "brcmnand.h"
  66. +
  67. +struct iproc_nand_soc {
  68. + struct brcmnand_soc soc;
  69. + void __iomem *idm_base;
  70. + void __iomem *ext_base;
  71. +};
  72. +
  73. +#define IPROC_NAND_CTLR_READY_OFFSET 0x10
  74. +#define IPROC_NAND_CTLR_READY BIT(0)
  75. +
  76. +#define IPROC_NAND_IO_CTRL_OFFSET 0x00
  77. +#define IPROC_NAND_APB_LE_MODE BIT(24)
  78. +#define IPROC_NAND_INT_CTRL_READ_ENABLE BIT(6)
  79. +
  80. +static bool iproc_nand_intc_ack(struct brcmnand_soc *soc)
  81. +{
  82. + struct iproc_nand_soc *priv =
  83. + container_of(soc, struct iproc_nand_soc, soc);
  84. + void __iomem *mmio = priv->ext_base + IPROC_NAND_CTLR_READY_OFFSET;
  85. + u32 val = brcmnand_readl(mmio);
  86. +
  87. + if (val & IPROC_NAND_CTLR_READY) {
  88. + brcmnand_writel(IPROC_NAND_CTLR_READY, mmio);
  89. + return true;
  90. + }
  91. +
  92. + return false;
  93. +}
  94. +
  95. +static void iproc_nand_intc_set(struct brcmnand_soc *soc, bool en)
  96. +{
  97. + struct iproc_nand_soc *priv =
  98. + container_of(soc, struct iproc_nand_soc, soc);
  99. + void __iomem *mmio = priv->idm_base + IPROC_NAND_IO_CTRL_OFFSET;
  100. + u32 val = brcmnand_readl(mmio);
  101. +
  102. + if (en)
  103. + val |= IPROC_NAND_INT_CTRL_READ_ENABLE;
  104. + else
  105. + val &= ~IPROC_NAND_INT_CTRL_READ_ENABLE;
  106. +
  107. + brcmnand_writel(val, mmio);
  108. +}
  109. +
  110. +static void iproc_nand_apb_access(struct brcmnand_soc *soc, bool prepare,
  111. + bool is_param)
  112. +{
  113. + struct iproc_nand_soc *priv =
  114. + container_of(soc, struct iproc_nand_soc, soc);
  115. + void __iomem *mmio = priv->idm_base + IPROC_NAND_IO_CTRL_OFFSET;
  116. + u32 val;
  117. +
  118. + val = brcmnand_readl(mmio);
  119. +
  120. + /*
  121. + * In the case of BE or when dealing with NAND data, always configure
  122. + * the APB bus to LE mode before accessing the FIFO and back to BE mode
  123. + * after the access is done
  124. + */
  125. + if (IS_ENABLED(CONFIG_SYS_BIG_ENDIAN) || !is_param) {
  126. + if (prepare)
  127. + val |= IPROC_NAND_APB_LE_MODE;
  128. + else
  129. + val &= ~IPROC_NAND_APB_LE_MODE;
  130. + } else { /* when in LE accessing the parameter page, keep APB in BE */
  131. + val &= ~IPROC_NAND_APB_LE_MODE;
  132. + }
  133. +
  134. + brcmnand_writel(val, mmio);
  135. +}
  136. +
  137. +static int iproc_nand_probe(struct udevice *dev)
  138. +{
  139. + struct udevice *pdev = dev;
  140. + struct iproc_nand_soc *priv = dev_get_priv(dev);
  141. + struct brcmnand_soc *soc;
  142. + struct resource res;
  143. + int ret;
  144. +
  145. + soc = &priv->soc;
  146. +
  147. + ret = dev_read_resource_byname(pdev, "iproc-idm", &res);
  148. + if (ret)
  149. + return ret;
  150. +
  151. + priv->idm_base = devm_ioremap(dev, res.start, resource_size(&res));
  152. + if (IS_ERR(priv->idm_base))
  153. + return PTR_ERR(priv->idm_base);
  154. +
  155. + ret = dev_read_resource_byname(pdev, "iproc-ext", &res);
  156. + if (ret)
  157. + return ret;
  158. +
  159. + priv->ext_base = devm_ioremap(dev, res.start, resource_size(&res));
  160. + if (IS_ERR(priv->ext_base))
  161. + return PTR_ERR(priv->ext_base);
  162. +
  163. + soc->ctlrdy_ack = iproc_nand_intc_ack;
  164. + soc->ctlrdy_set_enabled = iproc_nand_intc_set;
  165. + soc->prepare_data_bus = iproc_nand_apb_access;
  166. +
  167. + return brcmnand_probe(pdev, soc);
  168. +}
  169. +
  170. +static const struct udevice_id iproc_nand_dt_ids[] = {
  171. + {
  172. + .compatible = "brcm,nand-iproc",
  173. + },
  174. + { /* sentinel */ }
  175. +};
  176. +
  177. +U_BOOT_DRIVER(iproc_nand) = {
  178. + .name = "iproc-nand",
  179. + .id = UCLASS_MTD,
  180. + .of_match = iproc_nand_dt_ids,
  181. + .probe = iproc_nand_probe,
  182. + .priv_auto = sizeof(struct iproc_nand_soc),
  183. +};
  184. +
  185. +void board_nand_init(void)
  186. +{
  187. + struct udevice *dev;
  188. + int ret;
  189. +
  190. + ret = uclass_get_device_by_driver(UCLASS_MTD,
  191. + DM_DRIVER_GET(iproc_nand), &dev);
  192. + if (ret && ret != -ENODEV)
  193. + pr_err("Failed to initialize %s. (error %d)\n", dev->name,
  194. + ret);
  195. +}