npcm_pspi.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) 2021 Nuvoton Technology.
  4. */
  5. #include <common.h>
  6. #include <dm.h>
  7. #include <spi.h>
  8. #include <clk.h>
  9. #include <asm/gpio.h>
  10. #include <linux/iopoll.h>
  11. #define MAX_DIV 127
  12. /* Register offsets */
  13. #define PSPI_DATA 0
  14. #define PSPI_CTL1 2
  15. #define PSPI_STAT 4
  16. /* PSPI_CTL1 fields */
  17. #define PSPI_CTL1_SPIEN BIT(0)
  18. #define PSPI_CTL1_SCM BIT(7)
  19. #define PSPI_CTL1_SCIDL BIT(8)
  20. #define PSPI_CTL1_SCDV_MASK GENMASK(15, 9)
  21. #define PSPI_CTL1_SCDV_SHIFT 9
  22. /* PSPI_STAT fields */
  23. #define PSPI_STAT_BSY BIT(0)
  24. #define PSPI_STAT_RBF BIT(1)
  25. struct npcm_pspi_priv {
  26. void __iomem *base;
  27. struct clk clk;
  28. struct gpio_desc cs_gpio;
  29. u32 max_hz;
  30. };
  31. static inline void spi_cs_activate(struct udevice *dev)
  32. {
  33. struct udevice *bus = dev->parent;
  34. struct npcm_pspi_priv *priv = dev_get_priv(bus);
  35. dm_gpio_set_value(&priv->cs_gpio, 1);
  36. }
  37. static inline void spi_cs_deactivate(struct udevice *dev)
  38. {
  39. struct udevice *bus = dev->parent;
  40. struct npcm_pspi_priv *priv = dev_get_priv(bus);
  41. dm_gpio_set_value(&priv->cs_gpio, 0);
  42. }
  43. static inline void npcm_pspi_enable(struct npcm_pspi_priv *priv)
  44. {
  45. u16 val;
  46. val = readw(priv->base + PSPI_CTL1);
  47. val |= PSPI_CTL1_SPIEN;
  48. writew(val, priv->base + PSPI_CTL1);
  49. }
  50. static inline void npcm_pspi_disable(struct npcm_pspi_priv *priv)
  51. {
  52. u16 val;
  53. val = readw(priv->base + PSPI_CTL1);
  54. val &= ~PSPI_CTL1_SPIEN;
  55. writew(val, priv->base + PSPI_CTL1);
  56. }
  57. static int npcm_pspi_xfer(struct udevice *dev, unsigned int bitlen,
  58. const void *dout, void *din, unsigned long flags)
  59. {
  60. struct udevice *bus = dev->parent;
  61. struct npcm_pspi_priv *priv = dev_get_priv(bus);
  62. void __iomem *base = priv->base;
  63. const u8 *tx = dout;
  64. u8 *rx = din;
  65. u32 bytes = bitlen / 8;
  66. u8 tmp;
  67. u32 val;
  68. int i, ret = 0;
  69. npcm_pspi_enable(priv);
  70. if (flags & SPI_XFER_BEGIN)
  71. spi_cs_activate(dev);
  72. for (i = 0; i < bytes; i++) {
  73. /* Making sure we can write */
  74. ret = readb_poll_timeout(base + PSPI_STAT, val,
  75. !(val & PSPI_STAT_BSY),
  76. 1000000);
  77. if (ret < 0)
  78. break;
  79. if (tx)
  80. writeb(*tx++, base + PSPI_DATA);
  81. else
  82. writeb(0, base + PSPI_DATA);
  83. /* Wait till write completed */
  84. ret = readb_poll_timeout(base + PSPI_STAT, val,
  85. !(val & PSPI_STAT_BSY),
  86. 1000000);
  87. if (ret < 0)
  88. break;
  89. /* Wait till read buffer full */
  90. ret = readb_poll_timeout(base + PSPI_STAT, val,
  91. (val & PSPI_STAT_RBF),
  92. 1000000);
  93. if (ret < 0)
  94. break;
  95. tmp = readb(base + PSPI_DATA);
  96. if (rx)
  97. *rx++ = tmp;
  98. }
  99. if (flags & SPI_XFER_END)
  100. spi_cs_deactivate(dev);
  101. debug("npcm_pspi_xfer: slave %s:%s dout %08X din %08X bitlen %u\n",
  102. dev->parent->name, dev->name, *(uint *)tx, *(uint *)rx, bitlen);
  103. npcm_pspi_disable(priv);
  104. return ret;
  105. }
  106. static int npcm_pspi_set_speed(struct udevice *bus, uint speed)
  107. {
  108. struct npcm_pspi_priv *priv = dev_get_priv(bus);
  109. ulong apb_clock;
  110. u32 divisor;
  111. u16 val;
  112. apb_clock = clk_get_rate(&priv->clk);
  113. if (!apb_clock)
  114. return -EINVAL;
  115. if (speed > priv->max_hz)
  116. speed = priv->max_hz;
  117. divisor = DIV_ROUND_CLOSEST(apb_clock, (2 * speed) - 1);
  118. if (divisor > MAX_DIV)
  119. divisor = MAX_DIV;
  120. val = readw(priv->base + PSPI_CTL1);
  121. val &= ~PSPI_CTL1_SCDV_MASK;
  122. val |= divisor << PSPI_CTL1_SCDV_SHIFT;
  123. writew(val, priv->base + PSPI_CTL1);
  124. debug("%s: apb_clock=%lu speed=%d divisor=%u\n",
  125. __func__, apb_clock, speed, divisor);
  126. return 0;
  127. }
  128. static int npcm_pspi_set_mode(struct udevice *bus, uint mode)
  129. {
  130. struct npcm_pspi_priv *priv = dev_get_priv(bus);
  131. u16 pspi_mode, val;
  132. switch (mode & (SPI_CPOL | SPI_CPHA)) {
  133. case SPI_MODE_0:
  134. pspi_mode = 0;
  135. break;
  136. case SPI_MODE_1:
  137. pspi_mode = PSPI_CTL1_SCM;
  138. break;
  139. case SPI_MODE_2:
  140. pspi_mode = PSPI_CTL1_SCIDL;
  141. break;
  142. case SPI_MODE_3:
  143. pspi_mode = PSPI_CTL1_SCIDL | PSPI_CTL1_SCM;
  144. break;
  145. default:
  146. break;
  147. }
  148. val = readw(priv->base + PSPI_CTL1);
  149. val &= ~(PSPI_CTL1_SCIDL | PSPI_CTL1_SCM);
  150. val |= pspi_mode;
  151. writew(val, priv->base + PSPI_CTL1);
  152. debug("%s: mode=%u\n", __func__, mode);
  153. return 0;
  154. }
  155. static int npcm_pspi_probe(struct udevice *bus)
  156. {
  157. struct npcm_pspi_priv *priv = dev_get_priv(bus);
  158. int node = dev_of_offset(bus);
  159. int ret;
  160. ret = clk_get_by_index(bus, 0, &priv->clk);
  161. if (ret < 0)
  162. return ret;
  163. priv->base = dev_read_addr_ptr(bus);
  164. priv->max_hz = dev_read_u32_default(bus, "spi-max-frequency", 1000000);
  165. gpio_request_by_name_nodev(offset_to_ofnode(node), "cs-gpios", 0,
  166. &priv->cs_gpio, GPIOD_IS_OUT| GPIOD_ACTIVE_LOW);
  167. return 0;
  168. }
  169. static const struct dm_spi_ops npcm_pspi_ops = {
  170. .xfer = npcm_pspi_xfer,
  171. .set_speed = npcm_pspi_set_speed,
  172. .set_mode = npcm_pspi_set_mode,
  173. };
  174. static const struct udevice_id npcm_pspi_ids[] = {
  175. { .compatible = "nuvoton,npcm845-pspi"},
  176. { .compatible = "nuvoton,npcm750-pspi"},
  177. { }
  178. };
  179. U_BOOT_DRIVER(npcm_pspi) = {
  180. .name = "npcm_pspi",
  181. .id = UCLASS_SPI,
  182. .of_match = npcm_pspi_ids,
  183. .ops = &npcm_pspi_ops,
  184. .priv_auto = sizeof(struct npcm_pspi_priv),
  185. .probe = npcm_pspi_probe,
  186. };