108-v5.18-mtd-rawnand-brcmnand-Add-BCMA-shim.patch 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. From: Florian Fainelli <[email protected]>
  2. Subject: [PATCH v3 9/9] mtd: rawnand: brcmnand: Add BCMA shim
  3. Date: Fri, 07 Jan 2022 10:46:14 -0800
  4. Content-Type: text/plain; charset="utf-8"
  5. Add a BCMA shim to allow us to register the brcmnand driver using the
  6. BCMA bus which provides indirect memory mapped access to SoC registers.
  7. There are a number of registers that need to be byte swapped because
  8. they are natively big endian, coming directly from the NAND chip, and
  9. there is no bus interface unlike the iProc or STB platforms that
  10. performs the byte swapping for us.
  11. Signed-off-by: Florian Fainelli <[email protected]>
  12. ---
  13. drivers/mtd/nand/raw/Kconfig | 13 +++
  14. drivers/mtd/nand/raw/brcmnand/Makefile | 2 +
  15. drivers/mtd/nand/raw/brcmnand/bcma_nand.c | 132 ++++++++++++++++++++++
  16. drivers/mtd/nand/raw/brcmnand/brcmnand.c | 4 +
  17. 4 files changed, 151 insertions(+)
  18. create mode 100644 drivers/mtd/nand/raw/brcmnand/bcma_nand.c
  19. --- a/drivers/mtd/nand/raw/Kconfig
  20. +++ b/drivers/mtd/nand/raw/Kconfig
  21. @@ -208,6 +208,19 @@ config MTD_NAND_BRCMNAND
  22. originally designed for Set-Top Box but is used on various BCM7xxx,
  23. BCM3xxx, BCM63xxx, iProc/Cygnus and more.
  24. +if MTD_NAND_BRCMNAND
  25. +
  26. +config MTD_NAND_BRCMNAND_BCMA
  27. + tristate "Broadcom BCMA NAND controller"
  28. + depends on BCMA_NFLASH
  29. + depends on BCMA
  30. + help
  31. + Enables the BRCMNAND controller over BCMA on BCM47186/BCM5358 SoCs.
  32. + The glue driver will take care of performing the low-level I/O
  33. + operations to interface the BRCMNAND controller over the BCMA bus.
  34. +
  35. +endif # MTD_NAND_BRCMNAND
  36. +
  37. config MTD_NAND_BCM47XXNFLASH
  38. tristate "BCM4706 BCMA NAND controller"
  39. depends on BCMA_NFLASH
  40. --- a/drivers/mtd/nand/raw/brcmnand/Makefile
  41. +++ b/drivers/mtd/nand/raw/brcmnand/Makefile
  42. @@ -6,3 +6,5 @@ obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm6
  43. obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm6368_nand.o
  44. obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmstb_nand.o
  45. obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand.o
  46. +
  47. +obj-$(CONFIG_MTD_NAND_BRCMNAND_BCMA) += bcma_nand.o
  48. --- /dev/null
  49. +++ b/drivers/mtd/nand/raw/brcmnand/bcma_nand.c
  50. @@ -0,0 +1,132 @@
  51. +// SPDX-License-Identifier: GPL-2.0-only
  52. +/*
  53. + * Copyright © 2021 Broadcom
  54. + */
  55. +#include <linux/bcma/bcma.h>
  56. +#include <linux/bcma/bcma_driver_chipcommon.h>
  57. +#include <linux/device.h>
  58. +#include <linux/module.h>
  59. +#include <linux/platform_device.h>
  60. +
  61. +#include "brcmnand.h"
  62. +
  63. +struct brcmnand_bcma_soc {
  64. + struct brcmnand_soc soc;
  65. + struct bcma_drv_cc *cc;
  66. +};
  67. +
  68. +static inline bool brcmnand_bcma_needs_swapping(u32 offset)
  69. +{
  70. + switch (offset) {
  71. + case BCMA_CC_NAND_SPARE_RD0:
  72. + case BCMA_CC_NAND_SPARE_RD4:
  73. + case BCMA_CC_NAND_SPARE_RD8:
  74. + case BCMA_CC_NAND_SPARE_RD12:
  75. + case BCMA_CC_NAND_SPARE_WR0:
  76. + case BCMA_CC_NAND_SPARE_WR4:
  77. + case BCMA_CC_NAND_SPARE_WR8:
  78. + case BCMA_CC_NAND_SPARE_WR12:
  79. + case BCMA_CC_NAND_DEVID:
  80. + case BCMA_CC_NAND_DEVID_X:
  81. + case BCMA_CC_NAND_SPARE_RD16:
  82. + case BCMA_CC_NAND_SPARE_RD20:
  83. + case BCMA_CC_NAND_SPARE_RD24:
  84. + case BCMA_CC_NAND_SPARE_RD28:
  85. + return true;
  86. + }
  87. +
  88. + return false;
  89. +}
  90. +
  91. +static inline struct brcmnand_bcma_soc *to_bcma_soc(struct brcmnand_soc *soc)
  92. +{
  93. + return container_of(soc, struct brcmnand_bcma_soc, soc);
  94. +}
  95. +
  96. +static u32 brcmnand_bcma_read_reg(struct brcmnand_soc *soc, u32 offset)
  97. +{
  98. + struct brcmnand_bcma_soc *sc = to_bcma_soc(soc);
  99. + u32 val;
  100. +
  101. + /* Offset into the NAND block and deal with the flash cache separately */
  102. + if (offset == BRCMNAND_NON_MMIO_FC_ADDR)
  103. + offset = BCMA_CC_NAND_CACHE_DATA;
  104. + else
  105. + offset += BCMA_CC_NAND_REVISION;
  106. +
  107. + val = bcma_cc_read32(sc->cc, offset);
  108. +
  109. + /* Swap if necessary */
  110. + if (brcmnand_bcma_needs_swapping(offset))
  111. + val = be32_to_cpu(val);
  112. + return val;
  113. +}
  114. +
  115. +static void brcmnand_bcma_write_reg(struct brcmnand_soc *soc, u32 val,
  116. + u32 offset)
  117. +{
  118. + struct brcmnand_bcma_soc *sc = to_bcma_soc(soc);
  119. +
  120. + /* Offset into the NAND block */
  121. + if (offset == BRCMNAND_NON_MMIO_FC_ADDR)
  122. + offset = BCMA_CC_NAND_CACHE_DATA;
  123. + else
  124. + offset += BCMA_CC_NAND_REVISION;
  125. +
  126. + /* Swap if necessary */
  127. + if (brcmnand_bcma_needs_swapping(offset))
  128. + val = cpu_to_be32(val);
  129. +
  130. + bcma_cc_write32(sc->cc, offset, val);
  131. +}
  132. +
  133. +static struct brcmnand_io_ops brcmnand_bcma_io_ops = {
  134. + .read_reg = brcmnand_bcma_read_reg,
  135. + .write_reg = brcmnand_bcma_write_reg,
  136. +};
  137. +
  138. +static void brcmnand_bcma_prepare_data_bus(struct brcmnand_soc *soc, bool prepare,
  139. + bool is_param)
  140. +{
  141. + struct brcmnand_bcma_soc *sc = to_bcma_soc(soc);
  142. +
  143. + /* Reset the cache address to ensure we are already accessing the
  144. + * beginning of a sub-page.
  145. + */
  146. + bcma_cc_write32(sc->cc, BCMA_CC_NAND_CACHE_ADDR, 0);
  147. +}
  148. +
  149. +static int brcmnand_bcma_nand_probe(struct platform_device *pdev)
  150. +{
  151. + struct bcma_nflash *nflash = dev_get_platdata(&pdev->dev);
  152. + struct brcmnand_bcma_soc *soc;
  153. +
  154. + soc = devm_kzalloc(&pdev->dev, sizeof(*soc), GFP_KERNEL);
  155. + if (!soc)
  156. + return -ENOMEM;
  157. +
  158. + soc->cc = container_of(nflash, struct bcma_drv_cc, nflash);
  159. + soc->soc.prepare_data_bus = brcmnand_bcma_prepare_data_bus;
  160. + soc->soc.ops = &brcmnand_bcma_io_ops;
  161. +
  162. + if (soc->cc->core->bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
  163. + dev_err(&pdev->dev, "Use bcm47xxnflash for 4706!\n");
  164. + return -ENODEV;
  165. + }
  166. +
  167. + return brcmnand_probe(pdev, &soc->soc);
  168. +}
  169. +
  170. +static struct platform_driver brcmnand_bcma_nand_driver = {
  171. + .probe = brcmnand_bcma_nand_probe,
  172. + .remove = brcmnand_remove,
  173. + .driver = {
  174. + .name = "bcma_brcmnand",
  175. + .pm = &brcmnand_pm_ops,
  176. + }
  177. +};
  178. +module_platform_driver(brcmnand_bcma_nand_driver);
  179. +
  180. +MODULE_LICENSE("GPL v2");
  181. +MODULE_AUTHOR("Broadcom");
  182. +MODULE_DESCRIPTION("NAND controller driver glue for BCMA chips");
  183. --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
  184. +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
  185. @@ -627,7 +627,11 @@ enum {
  186. static inline bool brcmnand_non_mmio_ops(struct brcmnand_controller *ctrl)
  187. {
  188. +#if IS_ENABLED(CONFIG_MTD_NAND_BRCMNAND_BCMA)
  189. return static_branch_unlikely(&brcmnand_soc_has_ops_key);
  190. +#else
  191. + return false;
  192. +#endif
  193. }
  194. static inline u32 nand_readreg(struct brcmnand_controller *ctrl, u32 offs)