002-0016-spi-add-support-for-MediaTek-spi-mem-controller.patch 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. From e6b225ff8990635dc2d6d8dbd72e78dec1f36c62 Mon Sep 17 00:00:00 2001
  2. From: Weijie Gao <[email protected]>
  3. Date: Wed, 31 Aug 2022 19:04:45 +0800
  4. Subject: [PATCH 16/32] spi: add support for MediaTek spi-mem controller
  5. This patch adds support for spi-mem controller found on newer MediaTek SoCs
  6. This controller supports Single/Dual/Quad SPI mode.
  7. Reviewed-by: Simon Glass <[email protected]>
  8. Signed-off-by: SkyLake.Huang <[email protected]>
  9. ---
  10. drivers/spi/Kconfig | 8 +
  11. drivers/spi/Makefile | 1 +
  12. drivers/spi/mtk_spim.c | 701 +++++++++++++++++++++++++++++++++++++++++
  13. 3 files changed, 710 insertions(+)
  14. create mode 100644 drivers/spi/mtk_spim.c
  15. --- a/drivers/spi/Kconfig
  16. +++ b/drivers/spi/Kconfig
  17. @@ -276,6 +276,14 @@ config MTK_SNFI_SPI
  18. used to access SPI memory devices like SPI-NOR or SPI-NAND on
  19. platforms embedding this IP core, like MT7622/M7629.
  20. +config MTK_SPIM
  21. + bool "Mediatek SPI-MEM master controller driver"
  22. + depends on SPI_MEM
  23. + help
  24. + Enable MediaTek SPI-MEM master controller driver. This driver mainly
  25. + supports SPI flashes. You can use single, dual or quad mode
  26. + transmission on this controller.
  27. +
  28. config MVEBU_A3700_SPI
  29. bool "Marvell Armada 3700 SPI driver"
  30. select CLK_ARMADA_3720
  31. --- a/drivers/spi/Makefile
  32. +++ b/drivers/spi/Makefile
  33. @@ -43,6 +43,7 @@ obj-$(CONFIG_MPC8XX_SPI) += mpc8xx_spi.o
  34. obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
  35. obj-$(CONFIG_MTK_SNFI_SPI) += mtk_snfi_spi.o
  36. obj-$(CONFIG_MTK_SNOR) += mtk_snor.o
  37. +obj-$(CONFIG_MTK_SPIM) += mtk_spim.o
  38. obj-$(CONFIG_MT7620_SPI) += mt7620_spi.o
  39. obj-$(CONFIG_MT7621_SPI) += mt7621_spi.o
  40. obj-$(CONFIG_MSCC_BB_SPI) += mscc_bb_spi.o
  41. --- /dev/null
  42. +++ b/drivers/spi/mtk_spim.c
  43. @@ -0,0 +1,701 @@
  44. +// SPDX-License-Identifier: GPL-2.0
  45. +/*
  46. + * Copyright (C) 2022 MediaTek Inc. All Rights Reserved.
  47. + *
  48. + * Author: SkyLake.Huang <[email protected]>
  49. + */
  50. +
  51. +#include <clk.h>
  52. +#include <cpu_func.h>
  53. +#include <div64.h>
  54. +#include <dm.h>
  55. +#include <spi.h>
  56. +#include <spi-mem.h>
  57. +#include <stdbool.h>
  58. +#include <watchdog.h>
  59. +#include <dm/device.h>
  60. +#include <dm/device_compat.h>
  61. +#include <dm/devres.h>
  62. +#include <dm/pinctrl.h>
  63. +#include <linux/bitops.h>
  64. +#include <linux/completion.h>
  65. +#include <linux/dma-mapping.h>
  66. +#include <linux/io.h>
  67. +#include <linux/iopoll.h>
  68. +
  69. +#define SPI_CFG0_REG 0x0000
  70. +#define SPI_CFG1_REG 0x0004
  71. +#define SPI_TX_SRC_REG 0x0008
  72. +#define SPI_RX_DST_REG 0x000c
  73. +#define SPI_TX_DATA_REG 0x0010
  74. +#define SPI_RX_DATA_REG 0x0014
  75. +#define SPI_CMD_REG 0x0018
  76. +#define SPI_IRQ_REG 0x001c
  77. +#define SPI_STATUS_REG 0x0020
  78. +#define SPI_PAD_SEL_REG 0x0024
  79. +#define SPI_CFG2_REG 0x0028
  80. +#define SPI_TX_SRC_REG_64 0x002c
  81. +#define SPI_RX_DST_REG_64 0x0030
  82. +#define SPI_CFG3_IPM_REG 0x0040
  83. +
  84. +#define SPI_CFG0_SCK_HIGH_OFFSET 0
  85. +#define SPI_CFG0_SCK_LOW_OFFSET 8
  86. +#define SPI_CFG0_CS_HOLD_OFFSET 16
  87. +#define SPI_CFG0_CS_SETUP_OFFSET 24
  88. +#define SPI_ADJUST_CFG0_CS_HOLD_OFFSET 0
  89. +#define SPI_ADJUST_CFG0_CS_SETUP_OFFSET 16
  90. +
  91. +#define SPI_CFG1_CS_IDLE_OFFSET 0
  92. +#define SPI_CFG1_PACKET_LOOP_OFFSET 8
  93. +#define SPI_CFG1_PACKET_LENGTH_OFFSET 16
  94. +#define SPI_CFG1_GET_TICKDLY_OFFSET 29
  95. +
  96. +#define SPI_CFG1_GET_TICKDLY_MASK GENMASK(31, 29)
  97. +#define SPI_CFG1_CS_IDLE_MASK 0xff
  98. +#define SPI_CFG1_PACKET_LOOP_MASK 0xff00
  99. +#define SPI_CFG1_PACKET_LENGTH_MASK 0x3ff0000
  100. +#define SPI_CFG1_IPM_PACKET_LENGTH_MASK GENMASK(31, 16)
  101. +#define SPI_CFG2_SCK_HIGH_OFFSET 0
  102. +#define SPI_CFG2_SCK_LOW_OFFSET 16
  103. +#define SPI_CFG2_SCK_HIGH_MASK GENMASK(15, 0)
  104. +#define SPI_CFG2_SCK_LOW_MASK GENMASK(31, 16)
  105. +
  106. +#define SPI_CMD_ACT BIT(0)
  107. +#define SPI_CMD_RESUME BIT(1)
  108. +#define SPI_CMD_RST BIT(2)
  109. +#define SPI_CMD_PAUSE_EN BIT(4)
  110. +#define SPI_CMD_DEASSERT BIT(5)
  111. +#define SPI_CMD_SAMPLE_SEL BIT(6)
  112. +#define SPI_CMD_CS_POL BIT(7)
  113. +#define SPI_CMD_CPHA BIT(8)
  114. +#define SPI_CMD_CPOL BIT(9)
  115. +#define SPI_CMD_RX_DMA BIT(10)
  116. +#define SPI_CMD_TX_DMA BIT(11)
  117. +#define SPI_CMD_TXMSBF BIT(12)
  118. +#define SPI_CMD_RXMSBF BIT(13)
  119. +#define SPI_CMD_RX_ENDIAN BIT(14)
  120. +#define SPI_CMD_TX_ENDIAN BIT(15)
  121. +#define SPI_CMD_FINISH_IE BIT(16)
  122. +#define SPI_CMD_PAUSE_IE BIT(17)
  123. +#define SPI_CMD_IPM_NONIDLE_MODE BIT(19)
  124. +#define SPI_CMD_IPM_SPIM_LOOP BIT(21)
  125. +#define SPI_CMD_IPM_GET_TICKDLY_OFFSET 22
  126. +
  127. +#define SPI_CMD_IPM_GET_TICKDLY_MASK GENMASK(24, 22)
  128. +
  129. +#define PIN_MODE_CFG(x) ((x) / 2)
  130. +
  131. +#define SPI_CFG3_IPM_PIN_MODE_OFFSET 0
  132. +#define SPI_CFG3_IPM_HALF_DUPLEX_DIR BIT(2)
  133. +#define SPI_CFG3_IPM_HALF_DUPLEX_EN BIT(3)
  134. +#define SPI_CFG3_IPM_XMODE_EN BIT(4)
  135. +#define SPI_CFG3_IPM_NODATA_FLAG BIT(5)
  136. +#define SPI_CFG3_IPM_CMD_BYTELEN_OFFSET 8
  137. +#define SPI_CFG3_IPM_ADDR_BYTELEN_OFFSET 12
  138. +#define SPI_CFG3_IPM_DUMMY_BYTELEN_OFFSET 16
  139. +
  140. +#define SPI_CFG3_IPM_CMD_PIN_MODE_MASK GENMASK(1, 0)
  141. +#define SPI_CFG3_IPM_CMD_BYTELEN_MASK GENMASK(11, 8)
  142. +#define SPI_CFG3_IPM_ADDR_BYTELEN_MASK GENMASK(15, 12)
  143. +#define SPI_CFG3_IPM_DUMMY_BYTELEN_MASK GENMASK(19, 16)
  144. +
  145. +#define MT8173_SPI_MAX_PAD_SEL 3
  146. +
  147. +#define MTK_SPI_PAUSE_INT_STATUS 0x2
  148. +
  149. +#define MTK_SPI_IDLE 0
  150. +#define MTK_SPI_PAUSED 1
  151. +
  152. +#define MTK_SPI_MAX_FIFO_SIZE 32U
  153. +#define MTK_SPI_PACKET_SIZE 1024
  154. +#define MTK_SPI_IPM_PACKET_SIZE SZ_64K
  155. +#define MTK_SPI_IPM_PACKET_LOOP SZ_256
  156. +
  157. +#define MTK_SPI_32BITS_MASK 0xffffffff
  158. +
  159. +#define DMA_ADDR_EXT_BITS 36
  160. +#define DMA_ADDR_DEF_BITS 32
  161. +
  162. +#define CLK_TO_US(freq, clkcnt) DIV_ROUND_UP((clkcnt), (freq) / 1000000)
  163. +
  164. +/* struct mtk_spim_capability
  165. + * @enhance_timing: Some IC design adjust cfg register to enhance time accuracy
  166. + * @dma_ext: Some IC support DMA addr extension
  167. + * @ipm_design: The IPM IP design improves some features, and supports dual/quad mode
  168. + * @support_quad: Whether quad mode is supported
  169. + */
  170. +struct mtk_spim_capability {
  171. + bool enhance_timing;
  172. + bool dma_ext;
  173. + bool ipm_design;
  174. + bool support_quad;
  175. +};
  176. +
  177. +/* struct mtk_spim_priv
  178. + * @base: Base address of the spi controller
  179. + * @state: Controller state
  180. + * @sel_clk: Pad clock
  181. + * @spi_clk: Core clock
  182. + * @xfer_len: Current length of data for transfer
  183. + * @hw_cap: Controller capabilities
  184. + * @tick_dly: Used to postpone SPI sampling time
  185. + * @sample_sel: Sample edge of MISO
  186. + * @dev: udevice of this spi controller
  187. + * @tx_dma: Tx DMA address
  188. + * @rx_dma: Rx DMA address
  189. + */
  190. +struct mtk_spim_priv {
  191. + void __iomem *base;
  192. + u32 state;
  193. + struct clk sel_clk, spi_clk;
  194. + u32 xfer_len;
  195. + struct mtk_spim_capability hw_cap;
  196. + u32 tick_dly;
  197. + u32 sample_sel;
  198. +
  199. + struct device *dev;
  200. + dma_addr_t tx_dma;
  201. + dma_addr_t rx_dma;
  202. +};
  203. +
  204. +static void mtk_spim_reset(struct mtk_spim_priv *priv)
  205. +{
  206. + /* set the software reset bit in SPI_CMD_REG. */
  207. + setbits_le32(priv->base + SPI_CMD_REG, SPI_CMD_RST);
  208. + clrbits_le32(priv->base + SPI_CMD_REG, SPI_CMD_RST);
  209. +}
  210. +
  211. +static int mtk_spim_hw_init(struct spi_slave *slave)
  212. +{
  213. + struct udevice *bus = dev_get_parent(slave->dev);
  214. + struct mtk_spim_priv *priv = dev_get_priv(bus);
  215. + u16 cpha, cpol;
  216. + u32 reg_val;
  217. +
  218. + cpha = slave->mode & SPI_CPHA ? 1 : 0;
  219. + cpol = slave->mode & SPI_CPOL ? 1 : 0;
  220. +
  221. + if (priv->hw_cap.enhance_timing) {
  222. + if (priv->hw_cap.ipm_design) {
  223. + /* CFG3 reg only used for spi-mem,
  224. + * here write to default value
  225. + */
  226. + writel(0x0, priv->base + SPI_CFG3_IPM_REG);
  227. + clrsetbits_le32(priv->base + SPI_CMD_REG,
  228. + SPI_CMD_IPM_GET_TICKDLY_MASK,
  229. + priv->tick_dly <<
  230. + SPI_CMD_IPM_GET_TICKDLY_OFFSET);
  231. + } else {
  232. + clrsetbits_le32(priv->base + SPI_CFG1_REG,
  233. + SPI_CFG1_GET_TICKDLY_MASK,
  234. + priv->tick_dly <<
  235. + SPI_CFG1_GET_TICKDLY_OFFSET);
  236. + }
  237. + }
  238. +
  239. + reg_val = readl(priv->base + SPI_CMD_REG);
  240. + if (priv->hw_cap.ipm_design) {
  241. + /* SPI transfer without idle time until packet length done */
  242. + reg_val |= SPI_CMD_IPM_NONIDLE_MODE;
  243. + if (slave->mode & SPI_LOOP)
  244. + reg_val |= SPI_CMD_IPM_SPIM_LOOP;
  245. + else
  246. + reg_val &= ~SPI_CMD_IPM_SPIM_LOOP;
  247. + }
  248. +
  249. + if (cpha)
  250. + reg_val |= SPI_CMD_CPHA;
  251. + else
  252. + reg_val &= ~SPI_CMD_CPHA;
  253. + if (cpol)
  254. + reg_val |= SPI_CMD_CPOL;
  255. + else
  256. + reg_val &= ~SPI_CMD_CPOL;
  257. +
  258. + /* set the mlsbx and mlsbtx */
  259. + if (slave->mode & SPI_LSB_FIRST) {
  260. + reg_val &= ~SPI_CMD_TXMSBF;
  261. + reg_val &= ~SPI_CMD_RXMSBF;
  262. + } else {
  263. + reg_val |= SPI_CMD_TXMSBF;
  264. + reg_val |= SPI_CMD_RXMSBF;
  265. + }
  266. +
  267. + /* do not reverse tx/rx endian */
  268. + reg_val &= ~SPI_CMD_TX_ENDIAN;
  269. + reg_val &= ~SPI_CMD_RX_ENDIAN;
  270. +
  271. + if (priv->hw_cap.enhance_timing) {
  272. + /* set CS polarity */
  273. + if (slave->mode & SPI_CS_HIGH)
  274. + reg_val |= SPI_CMD_CS_POL;
  275. + else
  276. + reg_val &= ~SPI_CMD_CS_POL;
  277. +
  278. + if (priv->sample_sel)
  279. + reg_val |= SPI_CMD_SAMPLE_SEL;
  280. + else
  281. + reg_val &= ~SPI_CMD_SAMPLE_SEL;
  282. + }
  283. +
  284. + /* disable dma mode */
  285. + reg_val &= ~(SPI_CMD_TX_DMA | SPI_CMD_RX_DMA);
  286. +
  287. + /* disable deassert mode */
  288. + reg_val &= ~SPI_CMD_DEASSERT;
  289. +
  290. + writel(reg_val, priv->base + SPI_CMD_REG);
  291. +
  292. + return 0;
  293. +}
  294. +
  295. +static void mtk_spim_prepare_transfer(struct mtk_spim_priv *priv,
  296. + u32 speed_hz)
  297. +{
  298. + u32 spi_clk_hz, div, sck_time, cs_time, reg_val;
  299. +
  300. + spi_clk_hz = clk_get_rate(&priv->spi_clk);
  301. + if (speed_hz <= spi_clk_hz / 4)
  302. + div = DIV_ROUND_UP(spi_clk_hz, speed_hz);
  303. + else
  304. + div = 4;
  305. +
  306. + sck_time = (div + 1) / 2;
  307. + cs_time = sck_time * 2;
  308. +
  309. + if (priv->hw_cap.enhance_timing) {
  310. + reg_val = ((sck_time - 1) & 0xffff)
  311. + << SPI_CFG2_SCK_HIGH_OFFSET;
  312. + reg_val |= ((sck_time - 1) & 0xffff)
  313. + << SPI_CFG2_SCK_LOW_OFFSET;
  314. + writel(reg_val, priv->base + SPI_CFG2_REG);
  315. +
  316. + reg_val = ((cs_time - 1) & 0xffff)
  317. + << SPI_ADJUST_CFG0_CS_HOLD_OFFSET;
  318. + reg_val |= ((cs_time - 1) & 0xffff)
  319. + << SPI_ADJUST_CFG0_CS_SETUP_OFFSET;
  320. + writel(reg_val, priv->base + SPI_CFG0_REG);
  321. + } else {
  322. + reg_val = ((sck_time - 1) & 0xff)
  323. + << SPI_CFG0_SCK_HIGH_OFFSET;
  324. + reg_val |= ((sck_time - 1) & 0xff) << SPI_CFG0_SCK_LOW_OFFSET;
  325. + reg_val |= ((cs_time - 1) & 0xff) << SPI_CFG0_CS_HOLD_OFFSET;
  326. + reg_val |= ((cs_time - 1) & 0xff) << SPI_CFG0_CS_SETUP_OFFSET;
  327. + writel(reg_val, priv->base + SPI_CFG0_REG);
  328. + }
  329. +
  330. + reg_val = readl(priv->base + SPI_CFG1_REG);
  331. + reg_val &= ~SPI_CFG1_CS_IDLE_MASK;
  332. + reg_val |= ((cs_time - 1) & 0xff) << SPI_CFG1_CS_IDLE_OFFSET;
  333. + writel(reg_val, priv->base + SPI_CFG1_REG);
  334. +}
  335. +
  336. +/**
  337. + * mtk_spim_setup_packet() - setup packet format.
  338. + * @priv: controller priv
  339. + *
  340. + * This controller sents/receives data in packets. The packet size is
  341. + * configurable.
  342. + *
  343. + * This function calculates the maximum packet size available for current
  344. + * data, and calculates the number of packets required to sent/receive data
  345. + * as much as possible.
  346. + */
  347. +static void mtk_spim_setup_packet(struct mtk_spim_priv *priv)
  348. +{
  349. + u32 packet_size, packet_loop, reg_val;
  350. +
  351. + /* Calculate maximum packet size */
  352. + if (priv->hw_cap.ipm_design)
  353. + packet_size = min_t(u32,
  354. + priv->xfer_len,
  355. + MTK_SPI_IPM_PACKET_SIZE);
  356. + else
  357. + packet_size = min_t(u32,
  358. + priv->xfer_len,
  359. + MTK_SPI_PACKET_SIZE);
  360. +
  361. + /* Calculates number of packets to sent/receive */
  362. + packet_loop = priv->xfer_len / packet_size;
  363. +
  364. + reg_val = readl(priv->base + SPI_CFG1_REG);
  365. + if (priv->hw_cap.ipm_design)
  366. + reg_val &= ~SPI_CFG1_IPM_PACKET_LENGTH_MASK;
  367. + else
  368. + reg_val &= ~SPI_CFG1_PACKET_LENGTH_MASK;
  369. +
  370. + reg_val |= (packet_size - 1) << SPI_CFG1_PACKET_LENGTH_OFFSET;
  371. +
  372. + reg_val &= ~SPI_CFG1_PACKET_LOOP_MASK;
  373. +
  374. + reg_val |= (packet_loop - 1) << SPI_CFG1_PACKET_LOOP_OFFSET;
  375. +
  376. + writel(reg_val, priv->base + SPI_CFG1_REG);
  377. +}
  378. +
  379. +static void mtk_spim_enable_transfer(struct mtk_spim_priv *priv)
  380. +{
  381. + u32 cmd;
  382. +
  383. + cmd = readl(priv->base + SPI_CMD_REG);
  384. + if (priv->state == MTK_SPI_IDLE)
  385. + cmd |= SPI_CMD_ACT;
  386. + else
  387. + cmd |= SPI_CMD_RESUME;
  388. + writel(cmd, priv->base + SPI_CMD_REG);
  389. +}
  390. +
  391. +static bool mtk_spim_supports_op(struct spi_slave *slave,
  392. + const struct spi_mem_op *op)
  393. +{
  394. + struct udevice *bus = dev_get_parent(slave->dev);
  395. + struct mtk_spim_priv *priv = dev_get_priv(bus);
  396. +
  397. + if (op->cmd.buswidth == 0 || op->cmd.buswidth > 4 ||
  398. + op->addr.buswidth > 4 || op->dummy.buswidth > 4 ||
  399. + op->data.buswidth > 4)
  400. + return false;
  401. +
  402. + if (!priv->hw_cap.support_quad && (op->cmd.buswidth > 2 ||
  403. + op->addr.buswidth > 2 || op->dummy.buswidth > 2 ||
  404. + op->data.buswidth > 2))
  405. + return false;
  406. +
  407. + if (op->addr.nbytes && op->dummy.nbytes &&
  408. + op->addr.buswidth != op->dummy.buswidth)
  409. + return false;
  410. +
  411. + if (op->addr.nbytes + op->dummy.nbytes > 16)
  412. + return false;
  413. +
  414. + if (op->data.nbytes > MTK_SPI_IPM_PACKET_SIZE) {
  415. + if (op->data.nbytes / MTK_SPI_IPM_PACKET_SIZE >
  416. + MTK_SPI_IPM_PACKET_LOOP ||
  417. + op->data.nbytes % MTK_SPI_IPM_PACKET_SIZE != 0)
  418. + return false;
  419. + }
  420. +
  421. + return true;
  422. +}
  423. +
  424. +static void mtk_spim_setup_dma_xfer(struct mtk_spim_priv *priv,
  425. + const struct spi_mem_op *op)
  426. +{
  427. + writel((u32)(priv->tx_dma & MTK_SPI_32BITS_MASK),
  428. + priv->base + SPI_TX_SRC_REG);
  429. +
  430. + if (priv->hw_cap.dma_ext)
  431. + writel((u32)(priv->tx_dma >> 32),
  432. + priv->base + SPI_TX_SRC_REG_64);
  433. +
  434. + if (op->data.dir == SPI_MEM_DATA_IN) {
  435. + writel((u32)(priv->rx_dma & MTK_SPI_32BITS_MASK),
  436. + priv->base + SPI_RX_DST_REG);
  437. +
  438. + if (priv->hw_cap.dma_ext)
  439. + writel((u32)(priv->rx_dma >> 32),
  440. + priv->base + SPI_RX_DST_REG_64);
  441. + }
  442. +}
  443. +
  444. +static int mtk_spim_transfer_wait(struct spi_slave *slave,
  445. + const struct spi_mem_op *op)
  446. +{
  447. + struct udevice *bus = dev_get_parent(slave->dev);
  448. + struct mtk_spim_priv *priv = dev_get_priv(bus);
  449. + u32 sck_l, sck_h, spi_bus_clk, clk_count, reg;
  450. + ulong us = 1;
  451. + int ret = 0;
  452. +
  453. + if (op->data.dir == SPI_MEM_NO_DATA)
  454. + clk_count = 32;
  455. + else
  456. + clk_count = op->data.nbytes;
  457. +
  458. + spi_bus_clk = clk_get_rate(&priv->spi_clk);
  459. + sck_l = readl(priv->base + SPI_CFG2_REG) >> SPI_CFG2_SCK_LOW_OFFSET;
  460. + sck_h = readl(priv->base + SPI_CFG2_REG) & SPI_CFG2_SCK_HIGH_MASK;
  461. + do_div(spi_bus_clk, sck_l + sck_h + 2);
  462. +
  463. + us = CLK_TO_US(spi_bus_clk, clk_count * 8);
  464. + us += 1000 * 1000; /* 1s tolerance */
  465. +
  466. + if (us > UINT_MAX)
  467. + us = UINT_MAX;
  468. +
  469. + ret = readl_poll_timeout(priv->base + SPI_STATUS_REG, reg,
  470. + reg & 0x1, us);
  471. + if (ret < 0) {
  472. + dev_err(priv->dev, "transfer timeout, val: 0x%lx\n", us);
  473. + return -ETIMEDOUT;
  474. + }
  475. +
  476. + return 0;
  477. +}
  478. +
  479. +static int mtk_spim_exec_op(struct spi_slave *slave,
  480. + const struct spi_mem_op *op)
  481. +{
  482. + struct udevice *bus = dev_get_parent(slave->dev);
  483. + struct mtk_spim_priv *priv = dev_get_priv(bus);
  484. + u32 reg_val, nio = 1, tx_size;
  485. + char *tx_tmp_buf;
  486. + char *rx_tmp_buf;
  487. + int i, ret = 0;
  488. +
  489. + mtk_spim_reset(priv);
  490. + mtk_spim_hw_init(slave);
  491. + mtk_spim_prepare_transfer(priv, slave->max_hz);
  492. +
  493. + reg_val = readl(priv->base + SPI_CFG3_IPM_REG);
  494. + /* opcode byte len */
  495. + reg_val &= ~SPI_CFG3_IPM_CMD_BYTELEN_MASK;
  496. + reg_val |= 1 << SPI_CFG3_IPM_CMD_BYTELEN_OFFSET;
  497. +
  498. + /* addr & dummy byte len */
  499. + if (op->addr.nbytes || op->dummy.nbytes)
  500. + reg_val |= (op->addr.nbytes + op->dummy.nbytes) <<
  501. + SPI_CFG3_IPM_ADDR_BYTELEN_OFFSET;
  502. +
  503. + /* data byte len */
  504. + if (!op->data.nbytes) {
  505. + reg_val |= SPI_CFG3_IPM_NODATA_FLAG;
  506. + writel(0, priv->base + SPI_CFG1_REG);
  507. + } else {
  508. + reg_val &= ~SPI_CFG3_IPM_NODATA_FLAG;
  509. + priv->xfer_len = op->data.nbytes;
  510. + mtk_spim_setup_packet(priv);
  511. + }
  512. +
  513. + if (op->addr.nbytes || op->dummy.nbytes) {
  514. + if (op->addr.buswidth == 1 || op->dummy.buswidth == 1)
  515. + reg_val |= SPI_CFG3_IPM_XMODE_EN;
  516. + else
  517. + reg_val &= ~SPI_CFG3_IPM_XMODE_EN;
  518. + }
  519. +
  520. + if (op->addr.buswidth == 2 ||
  521. + op->dummy.buswidth == 2 ||
  522. + op->data.buswidth == 2)
  523. + nio = 2;
  524. + else if (op->addr.buswidth == 4 ||
  525. + op->dummy.buswidth == 4 ||
  526. + op->data.buswidth == 4)
  527. + nio = 4;
  528. +
  529. + reg_val &= ~SPI_CFG3_IPM_CMD_PIN_MODE_MASK;
  530. + reg_val |= PIN_MODE_CFG(nio) << SPI_CFG3_IPM_PIN_MODE_OFFSET;
  531. +
  532. + reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_EN;
  533. + if (op->data.dir == SPI_MEM_DATA_IN)
  534. + reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_DIR;
  535. + else
  536. + reg_val &= ~SPI_CFG3_IPM_HALF_DUPLEX_DIR;
  537. + writel(reg_val, priv->base + SPI_CFG3_IPM_REG);
  538. +
  539. + tx_size = 1 + op->addr.nbytes + op->dummy.nbytes;
  540. + if (op->data.dir == SPI_MEM_DATA_OUT)
  541. + tx_size += op->data.nbytes;
  542. +
  543. + tx_size = max(tx_size, (u32)32);
  544. +
  545. + /* Fill up tx data */
  546. + tx_tmp_buf = kzalloc(tx_size, GFP_KERNEL);
  547. + if (!tx_tmp_buf) {
  548. + ret = -ENOMEM;
  549. + goto exit;
  550. + }
  551. +
  552. + tx_tmp_buf[0] = op->cmd.opcode;
  553. +
  554. + if (op->addr.nbytes) {
  555. + for (i = 0; i < op->addr.nbytes; i++)
  556. + tx_tmp_buf[i + 1] = op->addr.val >>
  557. + (8 * (op->addr.nbytes - i - 1));
  558. + }
  559. +
  560. + if (op->dummy.nbytes)
  561. + memset(tx_tmp_buf + op->addr.nbytes + 1, 0xff,
  562. + op->dummy.nbytes);
  563. +
  564. + if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT)
  565. + memcpy(tx_tmp_buf + op->dummy.nbytes + op->addr.nbytes + 1,
  566. + op->data.buf.out, op->data.nbytes);
  567. + /* Finish filling up tx data */
  568. +
  569. + priv->tx_dma = dma_map_single(tx_tmp_buf, tx_size, DMA_TO_DEVICE);
  570. + if (dma_mapping_error(priv->dev, priv->tx_dma)) {
  571. + ret = -ENOMEM;
  572. + goto tx_free;
  573. + }
  574. +
  575. + if (op->data.dir == SPI_MEM_DATA_IN) {
  576. + if (!IS_ALIGNED((size_t)op->data.buf.in, 4)) {
  577. + rx_tmp_buf = kzalloc(op->data.nbytes, GFP_KERNEL);
  578. + if (!rx_tmp_buf) {
  579. + ret = -ENOMEM;
  580. + goto tx_unmap;
  581. + }
  582. + } else {
  583. + rx_tmp_buf = op->data.buf.in;
  584. + }
  585. +
  586. + priv->rx_dma = dma_map_single(rx_tmp_buf, op->data.nbytes,
  587. + DMA_FROM_DEVICE);
  588. + if (dma_mapping_error(priv->dev, priv->rx_dma)) {
  589. + ret = -ENOMEM;
  590. + goto rx_free;
  591. + }
  592. + }
  593. +
  594. + reg_val = readl(priv->base + SPI_CMD_REG);
  595. + reg_val |= SPI_CMD_TX_DMA;
  596. + if (op->data.dir == SPI_MEM_DATA_IN)
  597. + reg_val |= SPI_CMD_RX_DMA;
  598. +
  599. + writel(reg_val, priv->base + SPI_CMD_REG);
  600. +
  601. + mtk_spim_setup_dma_xfer(priv, op);
  602. +
  603. + mtk_spim_enable_transfer(priv);
  604. +
  605. + /* Wait for the interrupt. */
  606. + ret = mtk_spim_transfer_wait(slave, op);
  607. + if (ret)
  608. + goto rx_unmap;
  609. +
  610. + if (op->data.dir == SPI_MEM_DATA_IN &&
  611. + !IS_ALIGNED((size_t)op->data.buf.in, 4))
  612. + memcpy(op->data.buf.in, rx_tmp_buf, op->data.nbytes);
  613. +
  614. +rx_unmap:
  615. + /* spi disable dma */
  616. + reg_val = readl(priv->base + SPI_CMD_REG);
  617. + reg_val &= ~SPI_CMD_TX_DMA;
  618. + if (op->data.dir == SPI_MEM_DATA_IN)
  619. + reg_val &= ~SPI_CMD_RX_DMA;
  620. + writel(reg_val, priv->base + SPI_CMD_REG);
  621. +
  622. + writel(0, priv->base + SPI_TX_SRC_REG);
  623. + writel(0, priv->base + SPI_RX_DST_REG);
  624. +
  625. + if (op->data.dir == SPI_MEM_DATA_IN)
  626. + dma_unmap_single(priv->rx_dma,
  627. + op->data.nbytes, DMA_FROM_DEVICE);
  628. +rx_free:
  629. + if (op->data.dir == SPI_MEM_DATA_IN &&
  630. + !IS_ALIGNED((size_t)op->data.buf.in, 4))
  631. + kfree(rx_tmp_buf);
  632. +tx_unmap:
  633. + dma_unmap_single(priv->tx_dma,
  634. + tx_size, DMA_TO_DEVICE);
  635. +tx_free:
  636. + kfree(tx_tmp_buf);
  637. +exit:
  638. + return ret;
  639. +}
  640. +
  641. +static int mtk_spim_adjust_op_size(struct spi_slave *slave,
  642. + struct spi_mem_op *op)
  643. +{
  644. + int opcode_len;
  645. +
  646. + if (!op->data.nbytes)
  647. + return 0;
  648. +
  649. + if (op->data.dir != SPI_MEM_NO_DATA) {
  650. + opcode_len = 1 + op->addr.nbytes + op->dummy.nbytes;
  651. + if (opcode_len + op->data.nbytes > MTK_SPI_IPM_PACKET_SIZE) {
  652. + op->data.nbytes = MTK_SPI_IPM_PACKET_SIZE - opcode_len;
  653. + /* force data buffer dma-aligned. */
  654. + op->data.nbytes -= op->data.nbytes % 4;
  655. + }
  656. + }
  657. +
  658. + return 0;
  659. +}
  660. +
  661. +static int mtk_spim_get_attr(struct mtk_spim_priv *priv, struct udevice *dev)
  662. +{
  663. + int ret;
  664. +
  665. + priv->hw_cap.enhance_timing = dev_read_bool(dev, "enhance_timing");
  666. + priv->hw_cap.dma_ext = dev_read_bool(dev, "dma_ext");
  667. + priv->hw_cap.ipm_design = dev_read_bool(dev, "ipm_design");
  668. + priv->hw_cap.support_quad = dev_read_bool(dev, "support_quad");
  669. +
  670. + ret = dev_read_u32(dev, "tick_dly", &priv->tick_dly);
  671. + if (ret < 0)
  672. + dev_err(priv->dev, "tick dly not set.\n");
  673. +
  674. + ret = dev_read_u32(dev, "sample_sel", &priv->sample_sel);
  675. + if (ret < 0)
  676. + dev_err(priv->dev, "sample sel not set.\n");
  677. +
  678. + return ret;
  679. +}
  680. +
  681. +static int mtk_spim_probe(struct udevice *dev)
  682. +{
  683. + struct mtk_spim_priv *priv = dev_get_priv(dev);
  684. + int ret;
  685. +
  686. + priv->base = (void __iomem *)devfdt_get_addr(dev);
  687. + if (!priv->base)
  688. + return -EINVAL;
  689. +
  690. + mtk_spim_get_attr(priv, dev);
  691. +
  692. + ret = clk_get_by_name(dev, "sel-clk", &priv->sel_clk);
  693. + if (ret < 0) {
  694. + dev_err(dev, "failed to get sel-clk\n");
  695. + return ret;
  696. + }
  697. +
  698. + ret = clk_get_by_name(dev, "spi-clk", &priv->spi_clk);
  699. + if (ret < 0) {
  700. + dev_err(dev, "failed to get spi-clk\n");
  701. + return ret;
  702. + }
  703. +
  704. + clk_enable(&priv->sel_clk);
  705. + clk_enable(&priv->spi_clk);
  706. +
  707. + return 0;
  708. +}
  709. +
  710. +static int mtk_spim_set_speed(struct udevice *dev, uint speed)
  711. +{
  712. + return 0;
  713. +}
  714. +
  715. +static int mtk_spim_set_mode(struct udevice *dev, uint mode)
  716. +{
  717. + return 0;
  718. +}
  719. +
  720. +static const struct spi_controller_mem_ops mtk_spim_mem_ops = {
  721. + .adjust_op_size = mtk_spim_adjust_op_size,
  722. + .supports_op = mtk_spim_supports_op,
  723. + .exec_op = mtk_spim_exec_op
  724. +};
  725. +
  726. +static const struct dm_spi_ops mtk_spim_ops = {
  727. + .mem_ops = &mtk_spim_mem_ops,
  728. + .set_speed = mtk_spim_set_speed,
  729. + .set_mode = mtk_spim_set_mode,
  730. +};
  731. +
  732. +static const struct udevice_id mtk_spim_ids[] = {
  733. + { .compatible = "mediatek,ipm-spi" },
  734. + {}
  735. +};
  736. +
  737. +U_BOOT_DRIVER(mtk_spim) = {
  738. + .name = "mtk_spim",
  739. + .id = UCLASS_SPI,
  740. + .of_match = mtk_spim_ids,
  741. + .ops = &mtk_spim_ops,
  742. + .priv_auto = sizeof(struct mtk_spim_priv),
  743. + .probe = mtk_spim_probe,
  744. +};