xref: /OK3568_Linux_fs/u-boot/drivers/spi/rockchip_sfc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Rockchip Serial Flash Controller Driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (c) 2017-2021, Rockchip Inc.
6*4882a593Smuzhiyun  * Author: Shawn Lin <shawn.lin@rock-chips.com>
7*4882a593Smuzhiyun  *	   Chris Morgan <macromorgan@hotmail.com>
8*4882a593Smuzhiyun  *	   Jon Lin <Jon.lin@rock-chips.com>
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <asm/io.h>
12*4882a593Smuzhiyun #include <bouncebuf.h>
13*4882a593Smuzhiyun #include <clk.h>
14*4882a593Smuzhiyun #include <dm.h>
15*4882a593Smuzhiyun #include <linux/bitops.h>
16*4882a593Smuzhiyun #include <linux/delay.h>
17*4882a593Smuzhiyun #include <linux/iopoll.h>
18*4882a593Smuzhiyun #include <spi.h>
19*4882a593Smuzhiyun #include <spi-mem.h>
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun /* System control */
22*4882a593Smuzhiyun #define SFC_CTRL			0x0
23*4882a593Smuzhiyun #define  SFC_CTRL_PHASE_SEL_NEGETIVE	BIT(1)
24*4882a593Smuzhiyun #define  SFC_CTRL_CMD_BITS_SHIFT	8
25*4882a593Smuzhiyun #define  SFC_CTRL_ADDR_BITS_SHIFT	10
26*4882a593Smuzhiyun #define  SFC_CTRL_DATA_BITS_SHIFT	12
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun /* Interrupt mask */
29*4882a593Smuzhiyun #define SFC_IMR				0x4
30*4882a593Smuzhiyun #define  SFC_IMR_RX_FULL		BIT(0)
31*4882a593Smuzhiyun #define  SFC_IMR_RX_UFLOW		BIT(1)
32*4882a593Smuzhiyun #define  SFC_IMR_TX_OFLOW		BIT(2)
33*4882a593Smuzhiyun #define  SFC_IMR_TX_EMPTY		BIT(3)
34*4882a593Smuzhiyun #define  SFC_IMR_TRAN_FINISH		BIT(4)
35*4882a593Smuzhiyun #define  SFC_IMR_BUS_ERR		BIT(5)
36*4882a593Smuzhiyun #define  SFC_IMR_NSPI_ERR		BIT(6)
37*4882a593Smuzhiyun #define  SFC_IMR_DMA			BIT(7)
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun /* Interrupt clear */
40*4882a593Smuzhiyun #define SFC_ICLR			0x8
41*4882a593Smuzhiyun #define  SFC_ICLR_RX_FULL		BIT(0)
42*4882a593Smuzhiyun #define  SFC_ICLR_RX_UFLOW		BIT(1)
43*4882a593Smuzhiyun #define  SFC_ICLR_TX_OFLOW		BIT(2)
44*4882a593Smuzhiyun #define  SFC_ICLR_TX_EMPTY		BIT(3)
45*4882a593Smuzhiyun #define  SFC_ICLR_TRAN_FINISH		BIT(4)
46*4882a593Smuzhiyun #define  SFC_ICLR_BUS_ERR		BIT(5)
47*4882a593Smuzhiyun #define  SFC_ICLR_NSPI_ERR		BIT(6)
48*4882a593Smuzhiyun #define  SFC_ICLR_DMA			BIT(7)
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun /* FIFO threshold level */
51*4882a593Smuzhiyun #define SFC_FTLR			0xc
52*4882a593Smuzhiyun #define  SFC_FTLR_TX_SHIFT		0
53*4882a593Smuzhiyun #define  SFC_FTLR_TX_MASK		0x1f
54*4882a593Smuzhiyun #define  SFC_FTLR_RX_SHIFT		8
55*4882a593Smuzhiyun #define  SFC_FTLR_RX_MASK		0x1f
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun /* Reset FSM and FIFO */
58*4882a593Smuzhiyun #define SFC_RCVR			0x10
59*4882a593Smuzhiyun #define  SFC_RCVR_RESET			BIT(0)
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun /* Enhanced mode */
62*4882a593Smuzhiyun #define SFC_AX				0x14
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun /* Address Bit number */
65*4882a593Smuzhiyun #define SFC_ABIT			0x18
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun /* Interrupt status */
68*4882a593Smuzhiyun #define SFC_ISR				0x1c
69*4882a593Smuzhiyun #define  SFC_ISR_RX_FULL_SHIFT		BIT(0)
70*4882a593Smuzhiyun #define  SFC_ISR_RX_UFLOW_SHIFT		BIT(1)
71*4882a593Smuzhiyun #define  SFC_ISR_TX_OFLOW_SHIFT		BIT(2)
72*4882a593Smuzhiyun #define  SFC_ISR_TX_EMPTY_SHIFT		BIT(3)
73*4882a593Smuzhiyun #define  SFC_ISR_TX_FINISH_SHIFT	BIT(4)
74*4882a593Smuzhiyun #define  SFC_ISR_BUS_ERR_SHIFT		BIT(5)
75*4882a593Smuzhiyun #define  SFC_ISR_NSPI_ERR_SHIFT		BIT(6)
76*4882a593Smuzhiyun #define  SFC_ISR_DMA_SHIFT		BIT(7)
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun /* FIFO status */
79*4882a593Smuzhiyun #define SFC_FSR				0x20
80*4882a593Smuzhiyun #define  SFC_FSR_TX_IS_FULL		BIT(0)
81*4882a593Smuzhiyun #define  SFC_FSR_TX_IS_EMPTY		BIT(1)
82*4882a593Smuzhiyun #define  SFC_FSR_RX_IS_EMPTY		BIT(2)
83*4882a593Smuzhiyun #define  SFC_FSR_RX_IS_FULL		BIT(3)
84*4882a593Smuzhiyun #define  SFC_FSR_TXLV_MASK		GENMASK(12, 8)
85*4882a593Smuzhiyun #define  SFC_FSR_TXLV_SHIFT		8
86*4882a593Smuzhiyun #define  SFC_FSR_RXLV_MASK		GENMASK(20, 16)
87*4882a593Smuzhiyun #define  SFC_FSR_RXLV_SHIFT		16
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun /* FSM status */
90*4882a593Smuzhiyun #define SFC_SR				0x24
91*4882a593Smuzhiyun #define  SFC_SR_IS_IDLE			0x0
92*4882a593Smuzhiyun #define  SFC_SR_IS_BUSY			0x1
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun /* Raw interrupt status */
95*4882a593Smuzhiyun #define SFC_RISR			0x28
96*4882a593Smuzhiyun #define  SFC_RISR_RX_FULL		BIT(0)
97*4882a593Smuzhiyun #define  SFC_RISR_RX_UNDERFLOW		BIT(1)
98*4882a593Smuzhiyun #define  SFC_RISR_TX_OVERFLOW		BIT(2)
99*4882a593Smuzhiyun #define  SFC_RISR_TX_EMPTY		BIT(3)
100*4882a593Smuzhiyun #define  SFC_RISR_TRAN_FINISH		BIT(4)
101*4882a593Smuzhiyun #define  SFC_RISR_BUS_ERR		BIT(5)
102*4882a593Smuzhiyun #define  SFC_RISR_NSPI_ERR		BIT(6)
103*4882a593Smuzhiyun #define  SFC_RISR_DMA			BIT(7)
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun /* Version */
106*4882a593Smuzhiyun #define SFC_VER				0x2C
107*4882a593Smuzhiyun #define  SFC_VER_3			0x3
108*4882a593Smuzhiyun #define  SFC_VER_4			0x4
109*4882a593Smuzhiyun #define  SFC_VER_5			0x5
110*4882a593Smuzhiyun #define  SFC_VER_6			0x6
111*4882a593Smuzhiyun #define  SFC_VER_8			0x8
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun /* Delay line controller resiter */
114*4882a593Smuzhiyun #define SFC_DLL_CTRL0			0x3C
115*4882a593Smuzhiyun #define SFC_DLL_CTRL0_SCLK_SMP_DLL	BIT(15)
116*4882a593Smuzhiyun #define SFC_DLL_CTRL0_DLL_MAX_VER4	0xFFU
117*4882a593Smuzhiyun #define SFC_DLL_CTRL0_DLL_MAX_VER5	0x1FFU
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun /* Master trigger */
120*4882a593Smuzhiyun #define SFC_DMA_TRIGGER			0x80
121*4882a593Smuzhiyun #define SFC_DMA_TRIGGER_START		1
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun /* Src or Dst addr for master */
124*4882a593Smuzhiyun #define SFC_DMA_ADDR			0x84
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun /* Length control register extension 32GB */
127*4882a593Smuzhiyun #define SFC_LEN_CTRL			0x88
128*4882a593Smuzhiyun #define SFC_LEN_CTRL_TRB_SEL		1
129*4882a593Smuzhiyun #define SFC_LEN_EXT			0x8C
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun /* Command */
132*4882a593Smuzhiyun #define SFC_CMD				0x100
133*4882a593Smuzhiyun #define  SFC_CMD_IDX_SHIFT		0
134*4882a593Smuzhiyun #define  SFC_CMD_DUMMY_SHIFT		8
135*4882a593Smuzhiyun #define  SFC_CMD_DIR_SHIFT		12
136*4882a593Smuzhiyun #define  SFC_CMD_DIR_RD			0
137*4882a593Smuzhiyun #define  SFC_CMD_DIR_WR			1
138*4882a593Smuzhiyun #define  SFC_CMD_ADDR_SHIFT		14
139*4882a593Smuzhiyun #define  SFC_CMD_ADDR_0BITS		0
140*4882a593Smuzhiyun #define  SFC_CMD_ADDR_24BITS		1
141*4882a593Smuzhiyun #define  SFC_CMD_ADDR_32BITS		2
142*4882a593Smuzhiyun #define  SFC_CMD_ADDR_XBITS		3
143*4882a593Smuzhiyun #define  SFC_CMD_TRAN_BYTES_SHIFT	16
144*4882a593Smuzhiyun #define  SFC_CMD_CS_SHIFT		30
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun /* Address */
147*4882a593Smuzhiyun #define SFC_ADDR			0x104
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun /* Data */
150*4882a593Smuzhiyun #define SFC_DATA			0x108
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun /* The controller and documentation reports that it supports up to 4 CS
153*4882a593Smuzhiyun  * devices (0-3), however I have only been able to test a single CS (CS 0)
154*4882a593Smuzhiyun  * due to the configuration of my device.
155*4882a593Smuzhiyun  */
156*4882a593Smuzhiyun #define SFC_MAX_CHIPSELECT_NUM		4
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun /* The SFC can transfer max 16KB - 1 at one time
159*4882a593Smuzhiyun  * we set it to 15.5KB here for alignment.
160*4882a593Smuzhiyun  */
161*4882a593Smuzhiyun #define SFC_MAX_IOSIZE_VER3		(512 * 31)
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun #define SFC_MAX_IOSIZE_VER4		(0xFFFFFFFFU)
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun /* DMA is only enabled for large data transmission */
166*4882a593Smuzhiyun #define SFC_DMA_TRANS_THRETHOLD		(0x40)
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun /* Maximum clock values from datasheet suggest keeping clock value under
169*4882a593Smuzhiyun  * 150MHz. No minimum or average value is suggested.
170*4882a593Smuzhiyun  */
171*4882a593Smuzhiyun #define SFC_MAX_SPEED		(150 * 1000 * 1000)
172*4882a593Smuzhiyun #define SFC_DLL_THRESHOLD_RATE	(50 * 1000 * 1000)
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun #define SFC_DLL_TRANING_STEP		10		/* Training step */
175*4882a593Smuzhiyun #define SFC_DLL_TRANING_VALID_WINDOW	80		/* Training Valid DLL winbow */
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun struct rockchip_sfc {
178*4882a593Smuzhiyun 	struct udevice *dev;
179*4882a593Smuzhiyun 	void __iomem *regbase;
180*4882a593Smuzhiyun 	struct clk hclk;
181*4882a593Smuzhiyun 	struct clk clk;
182*4882a593Smuzhiyun 	u32 max_freq;
183*4882a593Smuzhiyun 	u32 speed;
184*4882a593Smuzhiyun 	bool use_dma;
185*4882a593Smuzhiyun 	u32 max_iosize;
186*4882a593Smuzhiyun 	u16 version;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	u32 last_async_size;
189*4882a593Smuzhiyun 	u32 async;
190*4882a593Smuzhiyun 	u32 dll_cells;
191*4882a593Smuzhiyun 	u32 max_dll_cells;
192*4882a593Smuzhiyun };
193*4882a593Smuzhiyun 
rockchip_sfc_reset(struct rockchip_sfc * sfc)194*4882a593Smuzhiyun static int rockchip_sfc_reset(struct rockchip_sfc *sfc)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun 	int err;
197*4882a593Smuzhiyun 	u32 status;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	writel(SFC_RCVR_RESET, sfc->regbase + SFC_RCVR);
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	err = readl_poll_timeout(sfc->regbase + SFC_RCVR, status,
202*4882a593Smuzhiyun 				 !(status & SFC_RCVR_RESET),
203*4882a593Smuzhiyun 				 1000000);
204*4882a593Smuzhiyun 	if (err)
205*4882a593Smuzhiyun 		printf("SFC reset never finished\n");
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	/* Still need to clear the masked interrupt from RISR */
208*4882a593Smuzhiyun 	writel(0xFFFFFFFF, sfc->regbase + SFC_ICLR);
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	return err;
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun 
rockchip_sfc_get_version(struct rockchip_sfc * sfc)213*4882a593Smuzhiyun static u16 rockchip_sfc_get_version(struct rockchip_sfc *sfc)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun 	return  (u16)(readl(sfc->regbase + SFC_VER) & 0xffff);
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun 
rockchip_sfc_get_max_iosize(struct rockchip_sfc * sfc)218*4882a593Smuzhiyun static u32 rockchip_sfc_get_max_iosize(struct rockchip_sfc *sfc)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun 	if (rockchip_sfc_get_version(sfc) >= SFC_VER_4)
221*4882a593Smuzhiyun 		return SFC_MAX_IOSIZE_VER4;
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	return SFC_MAX_IOSIZE_VER3;
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun 
rockchip_sfc_get_max_dll_cells(struct rockchip_sfc * sfc)226*4882a593Smuzhiyun static u32 rockchip_sfc_get_max_dll_cells(struct rockchip_sfc *sfc)
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun 	switch (rockchip_sfc_get_version(sfc)) {
229*4882a593Smuzhiyun 	case SFC_VER_8:
230*4882a593Smuzhiyun 	case SFC_VER_6:
231*4882a593Smuzhiyun 	case SFC_VER_5:
232*4882a593Smuzhiyun 		return SFC_DLL_CTRL0_DLL_MAX_VER5;
233*4882a593Smuzhiyun 	case SFC_VER_4:
234*4882a593Smuzhiyun 		return SFC_DLL_CTRL0_DLL_MAX_VER4;
235*4882a593Smuzhiyun 	default:
236*4882a593Smuzhiyun 		return 0;
237*4882a593Smuzhiyun 	}
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun 
rockchip_sfc_set_delay_lines(struct rockchip_sfc * sfc,u16 cells)240*4882a593Smuzhiyun static __maybe_unused void rockchip_sfc_set_delay_lines(struct rockchip_sfc *sfc, u16 cells)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun 	u16 cell_max = (u16)rockchip_sfc_get_max_dll_cells(sfc);
243*4882a593Smuzhiyun 	u32 val = 0;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	if (cells > cell_max)
246*4882a593Smuzhiyun 		cells = cell_max;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	if (cells)
249*4882a593Smuzhiyun 		val = SFC_DLL_CTRL0_SCLK_SMP_DLL | cells;
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	writel(val, sfc->regbase + SFC_DLL_CTRL0);
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun 
rockchip_sfc_init(struct rockchip_sfc * sfc)254*4882a593Smuzhiyun static int rockchip_sfc_init(struct rockchip_sfc *sfc)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun 	writel(0, sfc->regbase + SFC_CTRL);
257*4882a593Smuzhiyun 	if (rockchip_sfc_get_version(sfc) >= SFC_VER_4)
258*4882a593Smuzhiyun 		writel(SFC_LEN_CTRL_TRB_SEL, sfc->regbase + SFC_LEN_CTRL);
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	return 0;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun 
rockchip_sfc_ofdata_to_platdata(struct udevice * bus)263*4882a593Smuzhiyun static int rockchip_sfc_ofdata_to_platdata(struct udevice *bus)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun 	struct rockchip_sfc *sfc = dev_get_platdata(bus);
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	sfc->regbase = dev_read_addr_ptr(bus);
268*4882a593Smuzhiyun 	if (ofnode_read_bool(dev_ofnode(bus), "sfc-no-dma"))
269*4882a593Smuzhiyun 		sfc->use_dma = false;
270*4882a593Smuzhiyun 	else
271*4882a593Smuzhiyun 		sfc->use_dma = true;
272*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(CLK)
273*4882a593Smuzhiyun 	int ret;
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 	ret = clk_get_by_index(bus, 0, &sfc->clk);
276*4882a593Smuzhiyun 	if (ret < 0) {
277*4882a593Smuzhiyun 		printf("Could not get clock for %s: %d\n", bus->name, ret);
278*4882a593Smuzhiyun 		return ret;
279*4882a593Smuzhiyun 	}
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	ret = clk_get_by_index(bus, 1, &sfc->hclk);
282*4882a593Smuzhiyun 	if (ret < 0) {
283*4882a593Smuzhiyun 		printf("Could not get ahb clock for %s: %d\n", bus->name, ret);
284*4882a593Smuzhiyun 		return ret;
285*4882a593Smuzhiyun 	}
286*4882a593Smuzhiyun #endif
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	return 0;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun 
rockchip_sfc_probe(struct udevice * bus)291*4882a593Smuzhiyun static int rockchip_sfc_probe(struct udevice *bus)
292*4882a593Smuzhiyun {
293*4882a593Smuzhiyun 	struct rockchip_sfc *sfc = dev_get_platdata(bus);
294*4882a593Smuzhiyun 	int ret;
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(CLK)
297*4882a593Smuzhiyun 	ret = clk_enable(&sfc->hclk);
298*4882a593Smuzhiyun 	if (ret)
299*4882a593Smuzhiyun 		dev_dbg(sfc->dev, "sfc Enable ahb clock fail %s: %d\n", bus->name, ret);
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun 	ret = clk_enable(&sfc->clk);
302*4882a593Smuzhiyun 	if (ret)
303*4882a593Smuzhiyun 		dev_dbg(sfc->dev, "sfc Enable clock fail for %s: %d\n", bus->name, ret);
304*4882a593Smuzhiyun #endif
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 	ret = rockchip_sfc_init(sfc);
307*4882a593Smuzhiyun 	if (ret)
308*4882a593Smuzhiyun 		goto err_init;
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	sfc->max_iosize = rockchip_sfc_get_max_iosize(sfc);
311*4882a593Smuzhiyun 	sfc->version = rockchip_sfc_get_version(sfc);
312*4882a593Smuzhiyun 	sfc->max_freq = SFC_MAX_SPEED;
313*4882a593Smuzhiyun 	sfc->dev = bus;
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	return 0;
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun err_init:
318*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(CLK)
319*4882a593Smuzhiyun 	clk_disable(&sfc->clk);
320*4882a593Smuzhiyun 	clk_disable(&sfc->hclk);
321*4882a593Smuzhiyun #endif
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 	return ret;
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun 
rockchip_sfc_wait_txfifo_ready(struct rockchip_sfc * sfc,u32 timeout_us)326*4882a593Smuzhiyun static int rockchip_sfc_wait_txfifo_ready(struct rockchip_sfc *sfc, u32 timeout_us)
327*4882a593Smuzhiyun {
328*4882a593Smuzhiyun 	int ret = 0;
329*4882a593Smuzhiyun 	u32 status;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	ret = readl_poll_timeout(sfc->regbase + SFC_FSR, status,
332*4882a593Smuzhiyun 				 status & SFC_FSR_TXLV_MASK,
333*4882a593Smuzhiyun 				 timeout_us);
334*4882a593Smuzhiyun 	if (ret) {
335*4882a593Smuzhiyun 		dev_dbg(sfc->dev, "sfc wait tx fifo timeout\n");
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 		return -ETIMEDOUT;
338*4882a593Smuzhiyun 	}
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	return (status & SFC_FSR_TXLV_MASK) >> SFC_FSR_TXLV_SHIFT;
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun 
rockchip_sfc_wait_rxfifo_ready(struct rockchip_sfc * sfc,u32 timeout_us)343*4882a593Smuzhiyun static int rockchip_sfc_wait_rxfifo_ready(struct rockchip_sfc *sfc, u32 timeout_us)
344*4882a593Smuzhiyun {
345*4882a593Smuzhiyun 	int ret = 0;
346*4882a593Smuzhiyun 	u32 status;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	ret = readl_poll_timeout(sfc->regbase + SFC_FSR, status,
349*4882a593Smuzhiyun 				 status & SFC_FSR_RXLV_MASK,
350*4882a593Smuzhiyun 				 timeout_us);
351*4882a593Smuzhiyun 	if (ret) {
352*4882a593Smuzhiyun 		dev_dbg(sfc->dev, "sfc wait rx fifo timeout\n");
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 		return -ETIMEDOUT;
355*4882a593Smuzhiyun 	}
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 	return (status & SFC_FSR_RXLV_MASK) >> SFC_FSR_RXLV_SHIFT;
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun 
rockchip_sfc_adjust_op_work(struct spi_mem_op * op)360*4882a593Smuzhiyun static void rockchip_sfc_adjust_op_work(struct spi_mem_op *op)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun 	if (unlikely(op->dummy.nbytes && !op->addr.nbytes)) {
363*4882a593Smuzhiyun 		/*
364*4882a593Smuzhiyun 		 * SFC not support output DUMMY cycles right after CMD cycles, so
365*4882a593Smuzhiyun 		 * treat it as ADDR cycles.
366*4882a593Smuzhiyun 		 */
367*4882a593Smuzhiyun 		op->addr.nbytes = op->dummy.nbytes;
368*4882a593Smuzhiyun 		op->addr.buswidth = op->dummy.buswidth;
369*4882a593Smuzhiyun 		op->addr.val = 0xFFFFFFFFF;
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 		op->dummy.nbytes = 0;
372*4882a593Smuzhiyun 	}
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun 
rockchip_sfc_wait_for_dma_finished(struct rockchip_sfc * sfc,int timeout)375*4882a593Smuzhiyun static int rockchip_sfc_wait_for_dma_finished(struct rockchip_sfc *sfc, int timeout)
376*4882a593Smuzhiyun {
377*4882a593Smuzhiyun 	unsigned long tbase;
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun 	/* Wait for the DMA interrupt status */
380*4882a593Smuzhiyun 	tbase = get_timer(0);
381*4882a593Smuzhiyun 	while (!(readl(sfc->regbase + SFC_RISR) & SFC_RISR_DMA)) {
382*4882a593Smuzhiyun 		if (get_timer(tbase) > timeout) {
383*4882a593Smuzhiyun 			printf("dma timeout\n");
384*4882a593Smuzhiyun 			rockchip_sfc_reset(sfc);
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 			return -ETIMEDOUT;
387*4882a593Smuzhiyun 		}
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 		udelay(1);
390*4882a593Smuzhiyun 	}
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	writel(0xFFFFFFFF, sfc->regbase + SFC_ICLR);
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	return 0;
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun 
rockchip_sfc_xfer_setup(struct rockchip_sfc * sfc,struct spi_slave * mem,const struct spi_mem_op * op,u32 len)397*4882a593Smuzhiyun static int rockchip_sfc_xfer_setup(struct rockchip_sfc *sfc,
398*4882a593Smuzhiyun 				   struct spi_slave *mem,
399*4882a593Smuzhiyun 				   const struct spi_mem_op *op,
400*4882a593Smuzhiyun 				   u32 len)
401*4882a593Smuzhiyun {
402*4882a593Smuzhiyun 	struct dm_spi_slave_platdata *plat = dev_get_platdata(sfc->dev);
403*4882a593Smuzhiyun 	u32 ctrl = 0, cmd = 0;
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	/* set CMD */
406*4882a593Smuzhiyun 	cmd = op->cmd.opcode;
407*4882a593Smuzhiyun 	ctrl |= ((op->cmd.buswidth >> 1) << SFC_CTRL_CMD_BITS_SHIFT);
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 	/* set ADDR */
410*4882a593Smuzhiyun 	if (op->addr.nbytes) {
411*4882a593Smuzhiyun 		if (op->addr.nbytes == 4) {
412*4882a593Smuzhiyun 			cmd |= SFC_CMD_ADDR_32BITS << SFC_CMD_ADDR_SHIFT;
413*4882a593Smuzhiyun 		} else if (op->addr.nbytes == 3) {
414*4882a593Smuzhiyun 			cmd |= SFC_CMD_ADDR_24BITS << SFC_CMD_ADDR_SHIFT;
415*4882a593Smuzhiyun 		} else {
416*4882a593Smuzhiyun 			cmd |= SFC_CMD_ADDR_XBITS << SFC_CMD_ADDR_SHIFT;
417*4882a593Smuzhiyun 			writel(op->addr.nbytes * 8 - 1, sfc->regbase + SFC_ABIT);
418*4882a593Smuzhiyun 		}
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun 		ctrl |= ((op->addr.buswidth >> 1) << SFC_CTRL_ADDR_BITS_SHIFT);
421*4882a593Smuzhiyun 	}
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	/* set DUMMY */
424*4882a593Smuzhiyun 	if (op->dummy.nbytes) {
425*4882a593Smuzhiyun 		if (op->dummy.buswidth == 4)
426*4882a593Smuzhiyun 			cmd |= op->dummy.nbytes * 2 << SFC_CMD_DUMMY_SHIFT;
427*4882a593Smuzhiyun 		else if (op->dummy.buswidth == 2)
428*4882a593Smuzhiyun 			cmd |= op->dummy.nbytes * 4 << SFC_CMD_DUMMY_SHIFT;
429*4882a593Smuzhiyun 		else
430*4882a593Smuzhiyun 			cmd |= op->dummy.nbytes * 8 << SFC_CMD_DUMMY_SHIFT;
431*4882a593Smuzhiyun 	}
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	/* set DATA */
434*4882a593Smuzhiyun 	if (sfc->version >= SFC_VER_4) /* Clear it if no data to transfer */
435*4882a593Smuzhiyun 		writel(len, sfc->regbase + SFC_LEN_EXT);
436*4882a593Smuzhiyun 	else
437*4882a593Smuzhiyun 		cmd |= len << SFC_CMD_TRAN_BYTES_SHIFT;
438*4882a593Smuzhiyun 	if (len) {
439*4882a593Smuzhiyun 		if (op->data.dir == SPI_MEM_DATA_OUT)
440*4882a593Smuzhiyun 			cmd |= SFC_CMD_DIR_WR << SFC_CMD_DIR_SHIFT;
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 		ctrl |= ((op->data.buswidth >> 1) << SFC_CTRL_DATA_BITS_SHIFT);
443*4882a593Smuzhiyun 	}
444*4882a593Smuzhiyun 	if (!len && op->addr.nbytes)
445*4882a593Smuzhiyun 		cmd |= SFC_CMD_DIR_WR << SFC_CMD_DIR_SHIFT;
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	/* set the Controller */
448*4882a593Smuzhiyun 	ctrl |= SFC_CTRL_PHASE_SEL_NEGETIVE;
449*4882a593Smuzhiyun 	cmd |= plat->cs << SFC_CMD_CS_SHIFT;
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun 	dev_dbg(sfc->dev, "sfc addr.nbytes=%x(x%d) dummy.nbytes=%x(x%d)\n",
452*4882a593Smuzhiyun 		op->addr.nbytes, op->addr.buswidth,
453*4882a593Smuzhiyun 		op->dummy.nbytes, op->dummy.buswidth);
454*4882a593Smuzhiyun 	dev_dbg(sfc->dev, "sfc ctrl=%x cmd=%x addr=%llx len=%x\n",
455*4882a593Smuzhiyun 		ctrl, cmd, op->addr.val, len);
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun 	writel(ctrl, sfc->regbase + SFC_CTRL);
458*4882a593Smuzhiyun 	writel(cmd, sfc->regbase + SFC_CMD);
459*4882a593Smuzhiyun 	if (op->addr.nbytes)
460*4882a593Smuzhiyun 		writel(op->addr.val, sfc->regbase + SFC_ADDR);
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	return 0;
463*4882a593Smuzhiyun }
464*4882a593Smuzhiyun 
rockchip_sfc_write_fifo(struct rockchip_sfc * sfc,const u8 * buf,int len)465*4882a593Smuzhiyun static int rockchip_sfc_write_fifo(struct rockchip_sfc *sfc, const u8 *buf, int len)
466*4882a593Smuzhiyun {
467*4882a593Smuzhiyun 	u8 bytes = len & 0x3;
468*4882a593Smuzhiyun 	u32 dwords;
469*4882a593Smuzhiyun 	int tx_level;
470*4882a593Smuzhiyun 	u32 write_words;
471*4882a593Smuzhiyun 	u32 tmp = 0;
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun 	dwords = len >> 2;
474*4882a593Smuzhiyun 	while (dwords) {
475*4882a593Smuzhiyun 		tx_level = rockchip_sfc_wait_txfifo_ready(sfc, 1000);
476*4882a593Smuzhiyun 		if (tx_level < 0)
477*4882a593Smuzhiyun 			return tx_level;
478*4882a593Smuzhiyun 		write_words = min_t(u32, tx_level, dwords);
479*4882a593Smuzhiyun 		writesl(sfc->regbase + SFC_DATA, buf, write_words);
480*4882a593Smuzhiyun 		buf += write_words << 2;
481*4882a593Smuzhiyun 		dwords -= write_words;
482*4882a593Smuzhiyun 	}
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	/* write the rest non word aligned bytes */
485*4882a593Smuzhiyun 	if (bytes) {
486*4882a593Smuzhiyun 		tx_level = rockchip_sfc_wait_txfifo_ready(sfc, 1000);
487*4882a593Smuzhiyun 		if (tx_level < 0)
488*4882a593Smuzhiyun 			return tx_level;
489*4882a593Smuzhiyun 		memcpy(&tmp, buf, bytes);
490*4882a593Smuzhiyun 		writel(tmp, sfc->regbase + SFC_DATA);
491*4882a593Smuzhiyun 	}
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun 	return len;
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun 
rockchip_sfc_read_fifo(struct rockchip_sfc * sfc,u8 * buf,int len)496*4882a593Smuzhiyun static int rockchip_sfc_read_fifo(struct rockchip_sfc *sfc, u8 *buf, int len)
497*4882a593Smuzhiyun {
498*4882a593Smuzhiyun 	u8 bytes = len & 0x3;
499*4882a593Smuzhiyun 	u32 dwords;
500*4882a593Smuzhiyun 	u8 read_words;
501*4882a593Smuzhiyun 	int rx_level;
502*4882a593Smuzhiyun 	int tmp;
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun 	/* word aligned access only */
505*4882a593Smuzhiyun 	dwords = len >> 2;
506*4882a593Smuzhiyun 	while (dwords) {
507*4882a593Smuzhiyun 		rx_level = rockchip_sfc_wait_rxfifo_ready(sfc, 1000);
508*4882a593Smuzhiyun 		if (rx_level < 0)
509*4882a593Smuzhiyun 			return rx_level;
510*4882a593Smuzhiyun 		read_words = min_t(u32, rx_level, dwords);
511*4882a593Smuzhiyun 		readsl(sfc->regbase + SFC_DATA, buf, read_words);
512*4882a593Smuzhiyun 		buf += read_words << 2;
513*4882a593Smuzhiyun 		dwords -= read_words;
514*4882a593Smuzhiyun 	}
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	/* read the rest non word aligned bytes */
517*4882a593Smuzhiyun 	if (bytes) {
518*4882a593Smuzhiyun 		rx_level = rockchip_sfc_wait_rxfifo_ready(sfc, 1000);
519*4882a593Smuzhiyun 		if (rx_level < 0)
520*4882a593Smuzhiyun 			return rx_level;
521*4882a593Smuzhiyun 		tmp = readl(sfc->regbase + SFC_DATA);
522*4882a593Smuzhiyun 		memcpy(buf, &tmp, bytes);
523*4882a593Smuzhiyun 	}
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 	return len;
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun 
rockchip_sfc_fifo_transfer_dma(struct rockchip_sfc * sfc,dma_addr_t dma_buf,size_t len)528*4882a593Smuzhiyun static int rockchip_sfc_fifo_transfer_dma(struct rockchip_sfc *sfc, dma_addr_t dma_buf, size_t len)
529*4882a593Smuzhiyun {
530*4882a593Smuzhiyun 	writel(0xFFFFFFFF, sfc->regbase + SFC_ICLR);
531*4882a593Smuzhiyun 	writel((u32)dma_buf, sfc->regbase + SFC_DMA_ADDR);
532*4882a593Smuzhiyun 	writel(SFC_DMA_TRIGGER_START, sfc->regbase + SFC_DMA_TRIGGER);
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun 	return len;
535*4882a593Smuzhiyun }
536*4882a593Smuzhiyun 
rockchip_sfc_xfer_data_poll(struct rockchip_sfc * sfc,const struct spi_mem_op * op,u32 len)537*4882a593Smuzhiyun static int rockchip_sfc_xfer_data_poll(struct rockchip_sfc *sfc,
538*4882a593Smuzhiyun 				       const struct spi_mem_op *op, u32 len)
539*4882a593Smuzhiyun {
540*4882a593Smuzhiyun 	dev_dbg(sfc->dev, "sfc xfer_poll len=%x\n", len);
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun 	if (op->data.dir == SPI_MEM_DATA_OUT)
543*4882a593Smuzhiyun 		return rockchip_sfc_write_fifo(sfc, op->data.buf.out, len);
544*4882a593Smuzhiyun 	else
545*4882a593Smuzhiyun 		return rockchip_sfc_read_fifo(sfc, op->data.buf.in, len);
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun 
rockchip_sfc_xfer_data_dma(struct rockchip_sfc * sfc,const struct spi_mem_op * op,u32 len)548*4882a593Smuzhiyun static int rockchip_sfc_xfer_data_dma(struct rockchip_sfc *sfc,
549*4882a593Smuzhiyun 				      const struct spi_mem_op *op, u32 len)
550*4882a593Smuzhiyun {
551*4882a593Smuzhiyun 	struct bounce_buffer bb;
552*4882a593Smuzhiyun 	unsigned int bb_flags;
553*4882a593Smuzhiyun 	void *dma_buf;
554*4882a593Smuzhiyun 	int ret;
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun 	dev_dbg(sfc->dev, "sfc xfer_dma len=%x\n", len);
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun 	if (op->data.dir == SPI_MEM_DATA_OUT) {
559*4882a593Smuzhiyun 		dma_buf = (void *)op->data.buf.out;
560*4882a593Smuzhiyun 		bb_flags = GEN_BB_READ;
561*4882a593Smuzhiyun 	} else {
562*4882a593Smuzhiyun 		dma_buf = (void *)op->data.buf.in;
563*4882a593Smuzhiyun 		bb_flags = GEN_BB_WRITE;
564*4882a593Smuzhiyun 	}
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun 	ret = bounce_buffer_start(&bb, dma_buf, len, bb_flags);
567*4882a593Smuzhiyun 	if (ret)
568*4882a593Smuzhiyun 		return ret;
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun 	ret = rockchip_sfc_fifo_transfer_dma(sfc, (dma_addr_t)bb.bounce_buffer, len);
571*4882a593Smuzhiyun 	rockchip_sfc_wait_for_dma_finished(sfc, len * 10);
572*4882a593Smuzhiyun 	bounce_buffer_stop(&bb);
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun 	return ret;
575*4882a593Smuzhiyun }
576*4882a593Smuzhiyun 
rockchip_sfc_xfer_data_dma_async(struct rockchip_sfc * sfc,const struct spi_mem_op * op,u32 len)577*4882a593Smuzhiyun static int rockchip_sfc_xfer_data_dma_async(struct rockchip_sfc *sfc,
578*4882a593Smuzhiyun 					    const struct spi_mem_op *op, u32 len)
579*4882a593Smuzhiyun {
580*4882a593Smuzhiyun 	void *dma_buf;
581*4882a593Smuzhiyun 
582*4882a593Smuzhiyun 	if (op->data.dir == SPI_MEM_DATA_OUT) {
583*4882a593Smuzhiyun 		dma_buf = (void *)op->data.buf.out;
584*4882a593Smuzhiyun 		flush_dcache_range((unsigned long)dma_buf,
585*4882a593Smuzhiyun 				   (unsigned long)dma_buf + len);
586*4882a593Smuzhiyun 	} else {
587*4882a593Smuzhiyun 		dma_buf = (void *)op->data.buf.in;
588*4882a593Smuzhiyun 	}
589*4882a593Smuzhiyun 
590*4882a593Smuzhiyun 	dev_dbg(sfc->dev, "xfer_dma_async len=%x %p\n", len, dma_buf);
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun 	rockchip_sfc_fifo_transfer_dma(sfc, (dma_addr_t)dma_buf, len);
593*4882a593Smuzhiyun 	sfc->last_async_size = len;
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun 	return 0;
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun 
rockchip_sfc_xfer_done(struct rockchip_sfc * sfc,u32 timeout_us)598*4882a593Smuzhiyun static int rockchip_sfc_xfer_done(struct rockchip_sfc *sfc, u32 timeout_us)
599*4882a593Smuzhiyun {
600*4882a593Smuzhiyun 	int ret = 0;
601*4882a593Smuzhiyun 	u32 status;
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun 	ret = readl_poll_timeout(sfc->regbase + SFC_SR, status,
604*4882a593Smuzhiyun 				 !(status & SFC_SR_IS_BUSY),
605*4882a593Smuzhiyun 				 timeout_us);
606*4882a593Smuzhiyun 	if (ret) {
607*4882a593Smuzhiyun 		dev_err(sfc->dev, "wait sfc idle timeout\n");
608*4882a593Smuzhiyun 		rockchip_sfc_reset(sfc);
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun 		ret = -EIO;
611*4882a593Smuzhiyun 	}
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun 	return ret;
614*4882a593Smuzhiyun }
615*4882a593Smuzhiyun 
rockchip_sfc_exec_op(struct spi_slave * mem,const struct spi_mem_op * op)616*4882a593Smuzhiyun static int rockchip_sfc_exec_op(struct spi_slave *mem,
617*4882a593Smuzhiyun 				const struct spi_mem_op *op)
618*4882a593Smuzhiyun {
619*4882a593Smuzhiyun 	struct rockchip_sfc *sfc = dev_get_platdata(mem->dev->parent);
620*4882a593Smuzhiyun 	u32 len = min_t(u32, op->data.nbytes, sfc->max_iosize);
621*4882a593Smuzhiyun 	int ret;
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 	/* Wait for last async transfer finished */
624*4882a593Smuzhiyun 	if (sfc->last_async_size) {
625*4882a593Smuzhiyun 		rockchip_sfc_wait_for_dma_finished(sfc, sfc->last_async_size);
626*4882a593Smuzhiyun 		sfc->last_async_size = 0;
627*4882a593Smuzhiyun 	}
628*4882a593Smuzhiyun 	rockchip_sfc_adjust_op_work((struct spi_mem_op *)op);
629*4882a593Smuzhiyun 	rockchip_sfc_xfer_setup(sfc, mem, op, len);
630*4882a593Smuzhiyun 	if (len) {
631*4882a593Smuzhiyun 		if (likely(sfc->use_dma) && len >= SFC_DMA_TRANS_THRETHOLD) {
632*4882a593Smuzhiyun 			if (mem->mode & SPI_DMA_PREPARE)
633*4882a593Smuzhiyun 				return rockchip_sfc_xfer_data_dma_async(sfc, op, len);
634*4882a593Smuzhiyun 			ret = rockchip_sfc_xfer_data_dma(sfc, op, len);
635*4882a593Smuzhiyun 		} else {
636*4882a593Smuzhiyun 			ret = rockchip_sfc_xfer_data_poll(sfc, op, len);
637*4882a593Smuzhiyun 		}
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun 		if (ret != len) {
640*4882a593Smuzhiyun 			dev_err(sfc->dev, "xfer data failed ret %d dir %d\n", ret, op->data.dir);
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun 			return -EIO;
643*4882a593Smuzhiyun 		}
644*4882a593Smuzhiyun 	}
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun 	return rockchip_sfc_xfer_done(sfc, 100000);
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun 
rockchip_sfc_adjust_op_size(struct spi_slave * mem,struct spi_mem_op * op)649*4882a593Smuzhiyun static int rockchip_sfc_adjust_op_size(struct spi_slave *mem, struct spi_mem_op *op)
650*4882a593Smuzhiyun {
651*4882a593Smuzhiyun 	struct rockchip_sfc *sfc = dev_get_platdata(mem->dev->parent);
652*4882a593Smuzhiyun 
653*4882a593Smuzhiyun 	op->data.nbytes = min(op->data.nbytes, sfc->max_iosize);
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun 	return 0;
656*4882a593Smuzhiyun }
657*4882a593Smuzhiyun 
658*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(CLK)
rockchip_sfc_exec_op_bypass(struct rockchip_sfc * sfc,struct spi_slave * mem,const struct spi_mem_op * op)659*4882a593Smuzhiyun static int rockchip_sfc_exec_op_bypass(struct rockchip_sfc *sfc,
660*4882a593Smuzhiyun 				       struct spi_slave *mem,
661*4882a593Smuzhiyun 				       const struct spi_mem_op *op)
662*4882a593Smuzhiyun {
663*4882a593Smuzhiyun 	u32 len = min_t(u32, op->data.nbytes, sfc->max_iosize);
664*4882a593Smuzhiyun 	u32 ret;
665*4882a593Smuzhiyun 
666*4882a593Smuzhiyun 	rockchip_sfc_adjust_op_work((struct spi_mem_op *)op);
667*4882a593Smuzhiyun 	rockchip_sfc_xfer_setup(sfc, mem, op, len);
668*4882a593Smuzhiyun 	ret = rockchip_sfc_xfer_data_poll(sfc, op, len);
669*4882a593Smuzhiyun 	if (ret != len) {
670*4882a593Smuzhiyun 		dev_err(sfc->dev, "xfer data failed ret %d\n", ret);
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun 		return -EIO;
673*4882a593Smuzhiyun 	}
674*4882a593Smuzhiyun 
675*4882a593Smuzhiyun 	return rockchip_sfc_xfer_done(sfc, 100000);
676*4882a593Smuzhiyun }
677*4882a593Smuzhiyun 
rockchip_sfc_delay_lines_tuning(struct rockchip_sfc * sfc,struct spi_slave * mem)678*4882a593Smuzhiyun static void rockchip_sfc_delay_lines_tuning(struct rockchip_sfc *sfc, struct spi_slave *mem)
679*4882a593Smuzhiyun {
680*4882a593Smuzhiyun 	struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(0x9F, 1),
681*4882a593Smuzhiyun 						SPI_MEM_OP_NO_ADDR,
682*4882a593Smuzhiyun 						SPI_MEM_OP_NO_DUMMY,
683*4882a593Smuzhiyun 						SPI_MEM_OP_DATA_IN(3, NULL, 1));
684*4882a593Smuzhiyun 	u8 id[3], id_temp[3];
685*4882a593Smuzhiyun 	u16 cell_max = (u16)rockchip_sfc_get_max_dll_cells(sfc);
686*4882a593Smuzhiyun 	u16 right, left = 0;
687*4882a593Smuzhiyun 	u16 step = SFC_DLL_TRANING_STEP;
688*4882a593Smuzhiyun 	bool dll_valid = false;
689*4882a593Smuzhiyun 
690*4882a593Smuzhiyun 	clk_set_rate(&sfc->clk, SFC_DLL_THRESHOLD_RATE);
691*4882a593Smuzhiyun 	op.data.buf.in = &id;
692*4882a593Smuzhiyun 	rockchip_sfc_exec_op_bypass(sfc, mem, &op);
693*4882a593Smuzhiyun 	if ((0xFF == id[0] && 0xFF == id[1]) ||
694*4882a593Smuzhiyun 	    (0x00 == id[0] && 0x00 == id[1])) {
695*4882a593Smuzhiyun 		dev_dbg(sfc->dev, "no dev, dll by pass\n");
696*4882a593Smuzhiyun 		clk_set_rate(&sfc->clk, sfc->speed);
697*4882a593Smuzhiyun 
698*4882a593Smuzhiyun 		return;
699*4882a593Smuzhiyun 	}
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 	clk_set_rate(&sfc->clk, sfc->speed);
702*4882a593Smuzhiyun 	op.data.buf.in = &id_temp;
703*4882a593Smuzhiyun 	for (right = 0; right <= cell_max; right += step) {
704*4882a593Smuzhiyun 		int ret;
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun 		rockchip_sfc_set_delay_lines(sfc, right);
707*4882a593Smuzhiyun 		rockchip_sfc_exec_op_bypass(sfc, mem, &op);
708*4882a593Smuzhiyun 		dev_dbg(sfc->dev, "dll read flash id:%x %x %x\n",
709*4882a593Smuzhiyun 			id_temp[0], id_temp[1], id_temp[2]);
710*4882a593Smuzhiyun 
711*4882a593Smuzhiyun 		ret = memcmp(&id, &id_temp, 3);
712*4882a593Smuzhiyun 		if (dll_valid && ret) {
713*4882a593Smuzhiyun 			right -= step;
714*4882a593Smuzhiyun 
715*4882a593Smuzhiyun 			break;
716*4882a593Smuzhiyun 		}
717*4882a593Smuzhiyun 		if (!dll_valid && !ret)
718*4882a593Smuzhiyun 			left = right;
719*4882a593Smuzhiyun 
720*4882a593Smuzhiyun 		if (!ret)
721*4882a593Smuzhiyun 			dll_valid = true;
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun 		/* Add cell_max to loop */
724*4882a593Smuzhiyun 		if (right == cell_max)
725*4882a593Smuzhiyun 			break;
726*4882a593Smuzhiyun 		if (right + step > cell_max)
727*4882a593Smuzhiyun 			right = cell_max - step;
728*4882a593Smuzhiyun 	}
729*4882a593Smuzhiyun 
730*4882a593Smuzhiyun 	if (dll_valid && (right - left) >= SFC_DLL_TRANING_VALID_WINDOW) {
731*4882a593Smuzhiyun 		if (left == 0 && right < cell_max)
732*4882a593Smuzhiyun 			sfc->dll_cells = left + (right - left) * 2 / 5;
733*4882a593Smuzhiyun 		else
734*4882a593Smuzhiyun 			sfc->dll_cells = left + (right - left) / 2;
735*4882a593Smuzhiyun 	} else {
736*4882a593Smuzhiyun 		sfc->dll_cells = 0;
737*4882a593Smuzhiyun 	}
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	if (sfc->dll_cells) {
740*4882a593Smuzhiyun 		dev_dbg(sfc->dev, "%d %d %d dll training success in %dMHz max_cells=%u sfc_ver=%d\n",
741*4882a593Smuzhiyun 			left, right, sfc->dll_cells, sfc->speed,
742*4882a593Smuzhiyun 			rockchip_sfc_get_max_dll_cells(sfc), rockchip_sfc_get_version(sfc));
743*4882a593Smuzhiyun 		rockchip_sfc_set_delay_lines(sfc, (u16)sfc->dll_cells);
744*4882a593Smuzhiyun 	} else {
745*4882a593Smuzhiyun 		dev_err(sfc->dev, "%d %d dll training failed in %dMHz, reduce the speed\n",
746*4882a593Smuzhiyun 			left, right, sfc->speed);
747*4882a593Smuzhiyun 		rockchip_sfc_set_delay_lines(sfc, 0);
748*4882a593Smuzhiyun 		clk_set_rate(&sfc->clk, SFC_DLL_THRESHOLD_RATE);
749*4882a593Smuzhiyun 		sfc->speed = clk_get_rate(&sfc->clk);
750*4882a593Smuzhiyun 	}
751*4882a593Smuzhiyun }
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun #endif
754*4882a593Smuzhiyun 
rockchip_sfc_set_speed(struct udevice * bus,uint speed)755*4882a593Smuzhiyun static int rockchip_sfc_set_speed(struct udevice *bus, uint speed)
756*4882a593Smuzhiyun {
757*4882a593Smuzhiyun 	struct rockchip_sfc *sfc = dev_get_platdata(bus);
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun 	if (speed > sfc->max_freq)
760*4882a593Smuzhiyun 		speed = sfc->max_freq;
761*4882a593Smuzhiyun 
762*4882a593Smuzhiyun 	if (speed == sfc->speed)
763*4882a593Smuzhiyun 		return 0;
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(CLK)
766*4882a593Smuzhiyun 	int ret = clk_set_rate(&sfc->clk, speed);
767*4882a593Smuzhiyun 
768*4882a593Smuzhiyun 	if (ret < 0) {
769*4882a593Smuzhiyun 		dev_err(sfc->dev, "set_freq=%dHz fail, check if it's the cru support level\n",
770*4882a593Smuzhiyun 			speed);
771*4882a593Smuzhiyun 		return ret;
772*4882a593Smuzhiyun 	}
773*4882a593Smuzhiyun 	sfc->speed = speed;
774*4882a593Smuzhiyun 	if (rockchip_sfc_get_version(sfc) >= SFC_VER_4) {
775*4882a593Smuzhiyun 		if (clk_get_rate(&sfc->clk) > SFC_DLL_THRESHOLD_RATE)
776*4882a593Smuzhiyun 			rockchip_sfc_delay_lines_tuning(sfc, NULL);
777*4882a593Smuzhiyun 		else
778*4882a593Smuzhiyun 			rockchip_sfc_set_delay_lines(sfc, 0);
779*4882a593Smuzhiyun 	}
780*4882a593Smuzhiyun 
781*4882a593Smuzhiyun 	dev_dbg(sfc->dev, "set_freq=%dHz real_freq=%ldHz\n",
782*4882a593Smuzhiyun 		sfc->speed, clk_get_rate(&sfc->clk));
783*4882a593Smuzhiyun #else
784*4882a593Smuzhiyun 	dev_dbg(sfc->dev, "sfc failed, CLK not support\n");
785*4882a593Smuzhiyun #endif
786*4882a593Smuzhiyun 	return 0;
787*4882a593Smuzhiyun }
788*4882a593Smuzhiyun 
rockchip_sfc_set_mode(struct udevice * bus,uint mode)789*4882a593Smuzhiyun static int rockchip_sfc_set_mode(struct udevice *bus, uint mode)
790*4882a593Smuzhiyun {
791*4882a593Smuzhiyun 	return 0;
792*4882a593Smuzhiyun }
793*4882a593Smuzhiyun 
794*4882a593Smuzhiyun static const struct spi_controller_mem_ops rockchip_sfc_mem_ops = {
795*4882a593Smuzhiyun 	.adjust_op_size	= rockchip_sfc_adjust_op_size,
796*4882a593Smuzhiyun 	.exec_op	= rockchip_sfc_exec_op,
797*4882a593Smuzhiyun };
798*4882a593Smuzhiyun 
799*4882a593Smuzhiyun static const struct dm_spi_ops rockchip_sfc_ops = {
800*4882a593Smuzhiyun 	.mem_ops	= &rockchip_sfc_mem_ops,
801*4882a593Smuzhiyun 	.set_speed	= rockchip_sfc_set_speed,
802*4882a593Smuzhiyun 	.set_mode	= rockchip_sfc_set_mode,
803*4882a593Smuzhiyun };
804*4882a593Smuzhiyun 
805*4882a593Smuzhiyun static const struct udevice_id rockchip_sfc_ids[] = {
806*4882a593Smuzhiyun 	{ .compatible = "rockchip,sfc"},
807*4882a593Smuzhiyun 	{},
808*4882a593Smuzhiyun };
809*4882a593Smuzhiyun 
810*4882a593Smuzhiyun U_BOOT_DRIVER(rockchip_sfc_driver) = {
811*4882a593Smuzhiyun 	.name   = "rockchip_sfc",
812*4882a593Smuzhiyun 	.id     = UCLASS_SPI,
813*4882a593Smuzhiyun 	.of_match = rockchip_sfc_ids,
814*4882a593Smuzhiyun 	.ops    = &rockchip_sfc_ops,
815*4882a593Smuzhiyun 	.ofdata_to_platdata = rockchip_sfc_ofdata_to_platdata,
816*4882a593Smuzhiyun 	.platdata_auto_alloc_size = sizeof(struct rockchip_sfc),
817*4882a593Smuzhiyun 	.probe  = rockchip_sfc_probe,
818*4882a593Smuzhiyun };
819