101-mtd-rawnand-brcmnand-Allow-SoC-to-provide-I-O-operations.patch 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. From: Florian Fainelli <[email protected]>
  2. Subject: [PATCH v3 2/9] mtd: rawnand: brcmnand: Allow SoC to provide I/O operations
  3. Date: Fri, 07 Jan 2022 10:46:07 -0800
  4. Content-Type: text/plain; charset="utf-8"
  5. Allow a brcmnand_soc instance to provide a custom set of I/O operations
  6. which we will require when using this driver on a BCMA bus which is not
  7. directly memory mapped I/O. Update the nand_{read,write}_reg accordingly
  8. to use the SoC operations if provided.
  9. To minimize the penalty on other SoCs which do support standard MMIO
  10. accesses, we use a static key which is disabled by default and gets
  11. enabled if a soc implementation does provide I/O operations.
  12. Signed-off-by: Florian Fainelli <[email protected]>
  13. ---
  14. drivers/mtd/nand/raw/brcmnand/brcmnand.c | 28 +++++++++++++++++++++--
  15. drivers/mtd/nand/raw/brcmnand/brcmnand.h | 29 ++++++++++++++++++++++++
  16. 2 files changed, 55 insertions(+), 2 deletions(-)
  17. --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
  18. +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
  19. @@ -25,6 +25,7 @@
  20. #include <linux/of.h>
  21. #include <linux/of_platform.h>
  22. #include <linux/slab.h>
  23. +#include <linux/static_key.h>
  24. #include <linux/list.h>
  25. #include <linux/log2.h>
  26. @@ -207,6 +208,8 @@ enum {
  27. struct brcmnand_host;
  28. +static DEFINE_STATIC_KEY_FALSE(brcmnand_soc_has_ops_key);
  29. +
  30. struct brcmnand_controller {
  31. struct device *dev;
  32. struct nand_controller controller;
  33. @@ -589,15 +592,25 @@ enum {
  34. INTFC_CTLR_READY = BIT(31),
  35. };
  36. +static inline bool brcmnand_non_mmio_ops(struct brcmnand_controller *ctrl)
  37. +{
  38. + return static_branch_unlikely(&brcmnand_soc_has_ops_key);
  39. +}
  40. +
  41. static inline u32 nand_readreg(struct brcmnand_controller *ctrl, u32 offs)
  42. {
  43. + if (brcmnand_non_mmio_ops(ctrl))
  44. + return brcmnand_soc_read(ctrl->soc, offs);
  45. return brcmnand_readl(ctrl->nand_base + offs);
  46. }
  47. static inline void nand_writereg(struct brcmnand_controller *ctrl, u32 offs,
  48. u32 val)
  49. {
  50. - brcmnand_writel(val, ctrl->nand_base + offs);
  51. + if (brcmnand_non_mmio_ops(ctrl))
  52. + brcmnand_soc_write(ctrl->soc, val, offs);
  53. + else
  54. + brcmnand_writel(val, ctrl->nand_base + offs);
  55. }
  56. static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
  57. @@ -763,13 +776,18 @@ static inline void brcmnand_rmw_reg(stru
  58. static inline u32 brcmnand_read_fc(struct brcmnand_controller *ctrl, int word)
  59. {
  60. + if (brcmnand_non_mmio_ops(ctrl))
  61. + return brcmnand_soc_read(ctrl->soc, BRCMNAND_NON_MMIO_FC_ADDR);
  62. return __raw_readl(ctrl->nand_fc + word * 4);
  63. }
  64. static inline void brcmnand_write_fc(struct brcmnand_controller *ctrl,
  65. int word, u32 val)
  66. {
  67. - __raw_writel(val, ctrl->nand_fc + word * 4);
  68. + if (brcmnand_non_mmio_ops(ctrl))
  69. + brcmnand_soc_write(ctrl->soc, val, BRCMNAND_NON_MMIO_FC_ADDR);
  70. + else
  71. + __raw_writel(val, ctrl->nand_fc + word * 4);
  72. }
  73. static inline void edu_writel(struct brcmnand_controller *ctrl,
  74. @@ -2951,6 +2969,12 @@ int brcmnand_probe(struct platform_devic
  75. ctrl->dev = dev;
  76. ctrl->soc = soc;
  77. + /* Enable the static key if the soc provides I/O operations indicating
  78. + * that a non-memory mapped IO access path must be used
  79. + */
  80. + if (brcmnand_soc_has_ops(ctrl->soc))
  81. + static_branch_enable(&brcmnand_soc_has_ops_key);
  82. +
  83. init_completion(&ctrl->done);
  84. init_completion(&ctrl->dma_done);
  85. init_completion(&ctrl->edu_done);
  86. --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.h
  87. +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.h
  88. @@ -11,12 +11,25 @@
  89. struct platform_device;
  90. struct dev_pm_ops;
  91. +struct brcmnand_io_ops;
  92. +
  93. +/* Special register offset constant to intercept a non-MMIO access
  94. + * to the flash cache register space. This is intentionally large
  95. + * not to overlap with an existing offset.
  96. + */
  97. +#define BRCMNAND_NON_MMIO_FC_ADDR 0xffffffff
  98. struct brcmnand_soc {
  99. bool (*ctlrdy_ack)(struct brcmnand_soc *soc);
  100. void (*ctlrdy_set_enabled)(struct brcmnand_soc *soc, bool en);
  101. void (*prepare_data_bus)(struct brcmnand_soc *soc, bool prepare,
  102. bool is_param);
  103. + const struct brcmnand_io_ops *ops;
  104. +};
  105. +
  106. +struct brcmnand_io_ops {
  107. + u32 (*read_reg)(struct brcmnand_soc *soc, u32 offset);
  108. + void (*write_reg)(struct brcmnand_soc *soc, u32 val, u32 offset);
  109. };
  110. static inline void brcmnand_soc_data_bus_prepare(struct brcmnand_soc *soc,
  111. @@ -58,6 +71,22 @@ static inline void brcmnand_writel(u32 v
  112. writel_relaxed(val, addr);
  113. }
  114. +static inline bool brcmnand_soc_has_ops(struct brcmnand_soc *soc)
  115. +{
  116. + return soc && soc->ops && soc->ops->read_reg && soc->ops->write_reg;
  117. +}
  118. +
  119. +static inline u32 brcmnand_soc_read(struct brcmnand_soc *soc, u32 offset)
  120. +{
  121. + return soc->ops->read_reg(soc, offset);
  122. +}
  123. +
  124. +static inline void brcmnand_soc_write(struct brcmnand_soc *soc, u32 val,
  125. + u32 offset)
  126. +{
  127. + soc->ops->write_reg(soc, val, offset);
  128. +}
  129. +
  130. int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc);
  131. int brcmnand_remove(struct platform_device *pdev);