1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * ARM PL353 SMC driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2012 - 2018 Xilinx, Inc
6*4882a593Smuzhiyun * Author: Punnaiah Choudary Kalluri <punnaiah@xilinx.com>
7*4882a593Smuzhiyun * Author: Naga Sureshkumar Relli <nagasure@xilinx.com>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/clk.h>
11*4882a593Smuzhiyun #include <linux/io.h>
12*4882a593Smuzhiyun #include <linux/kernel.h>
13*4882a593Smuzhiyun #include <linux/module.h>
14*4882a593Smuzhiyun #include <linux/of_platform.h>
15*4882a593Smuzhiyun #include <linux/platform_device.h>
16*4882a593Smuzhiyun #include <linux/slab.h>
17*4882a593Smuzhiyun #include <linux/pl353-smc.h>
18*4882a593Smuzhiyun #include <linux/amba/bus.h>
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun /* Register definitions */
21*4882a593Smuzhiyun #define PL353_SMC_MEMC_STATUS_OFFS 0 /* Controller status reg, RO */
22*4882a593Smuzhiyun #define PL353_SMC_CFG_CLR_OFFS 0xC /* Clear config reg, WO */
23*4882a593Smuzhiyun #define PL353_SMC_DIRECT_CMD_OFFS 0x10 /* Direct command reg, WO */
24*4882a593Smuzhiyun #define PL353_SMC_SET_CYCLES_OFFS 0x14 /* Set cycles register, WO */
25*4882a593Smuzhiyun #define PL353_SMC_SET_OPMODE_OFFS 0x18 /* Set opmode register, WO */
26*4882a593Smuzhiyun #define PL353_SMC_ECC_STATUS_OFFS 0x400 /* ECC status register */
27*4882a593Smuzhiyun #define PL353_SMC_ECC_MEMCFG_OFFS 0x404 /* ECC mem config reg */
28*4882a593Smuzhiyun #define PL353_SMC_ECC_MEMCMD1_OFFS 0x408 /* ECC mem cmd1 reg */
29*4882a593Smuzhiyun #define PL353_SMC_ECC_MEMCMD2_OFFS 0x40C /* ECC mem cmd2 reg */
30*4882a593Smuzhiyun #define PL353_SMC_ECC_VALUE0_OFFS 0x418 /* ECC value 0 reg */
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun /* Controller status register specific constants */
33*4882a593Smuzhiyun #define PL353_SMC_MEMC_STATUS_RAW_INT_1_SHIFT 6
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun /* Clear configuration register specific constants */
36*4882a593Smuzhiyun #define PL353_SMC_CFG_CLR_INT_CLR_1 0x10
37*4882a593Smuzhiyun #define PL353_SMC_CFG_CLR_ECC_INT_DIS_1 0x40
38*4882a593Smuzhiyun #define PL353_SMC_CFG_CLR_INT_DIS_1 0x2
39*4882a593Smuzhiyun #define PL353_SMC_CFG_CLR_DEFAULT_MASK (PL353_SMC_CFG_CLR_INT_CLR_1 | \
40*4882a593Smuzhiyun PL353_SMC_CFG_CLR_ECC_INT_DIS_1 | \
41*4882a593Smuzhiyun PL353_SMC_CFG_CLR_INT_DIS_1)
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun /* Set cycles register specific constants */
44*4882a593Smuzhiyun #define PL353_SMC_SET_CYCLES_T0_MASK 0xF
45*4882a593Smuzhiyun #define PL353_SMC_SET_CYCLES_T0_SHIFT 0
46*4882a593Smuzhiyun #define PL353_SMC_SET_CYCLES_T1_MASK 0xF
47*4882a593Smuzhiyun #define PL353_SMC_SET_CYCLES_T1_SHIFT 4
48*4882a593Smuzhiyun #define PL353_SMC_SET_CYCLES_T2_MASK 0x7
49*4882a593Smuzhiyun #define PL353_SMC_SET_CYCLES_T2_SHIFT 8
50*4882a593Smuzhiyun #define PL353_SMC_SET_CYCLES_T3_MASK 0x7
51*4882a593Smuzhiyun #define PL353_SMC_SET_CYCLES_T3_SHIFT 11
52*4882a593Smuzhiyun #define PL353_SMC_SET_CYCLES_T4_MASK 0x7
53*4882a593Smuzhiyun #define PL353_SMC_SET_CYCLES_T4_SHIFT 14
54*4882a593Smuzhiyun #define PL353_SMC_SET_CYCLES_T5_MASK 0x7
55*4882a593Smuzhiyun #define PL353_SMC_SET_CYCLES_T5_SHIFT 17
56*4882a593Smuzhiyun #define PL353_SMC_SET_CYCLES_T6_MASK 0xF
57*4882a593Smuzhiyun #define PL353_SMC_SET_CYCLES_T6_SHIFT 20
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun /* ECC status register specific constants */
60*4882a593Smuzhiyun #define PL353_SMC_ECC_STATUS_BUSY BIT(6)
61*4882a593Smuzhiyun #define PL353_SMC_ECC_REG_SIZE_OFFS 4
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun /* ECC memory config register specific constants */
64*4882a593Smuzhiyun #define PL353_SMC_ECC_MEMCFG_MODE_MASK 0xC
65*4882a593Smuzhiyun #define PL353_SMC_ECC_MEMCFG_MODE_SHIFT 2
66*4882a593Smuzhiyun #define PL353_SMC_ECC_MEMCFG_PGSIZE_MASK 0x3
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun #define PL353_SMC_DC_UPT_NAND_REGS ((4 << 23) | /* CS: NAND chip */ \
69*4882a593Smuzhiyun (2 << 21)) /* UpdateRegs operation */
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun #define PL353_NAND_ECC_CMD1 ((0x80) | /* Write command */ \
72*4882a593Smuzhiyun (0 << 8) | /* Read command */ \
73*4882a593Smuzhiyun (0x30 << 16) | /* Read End command */ \
74*4882a593Smuzhiyun (1 << 24)) /* Read End command calid */
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun #define PL353_NAND_ECC_CMD2 ((0x85) | /* Write col change cmd */ \
77*4882a593Smuzhiyun (5 << 8) | /* Read col change cmd */ \
78*4882a593Smuzhiyun (0xE0 << 16) | /* Read col change end cmd */ \
79*4882a593Smuzhiyun (1 << 24)) /* Read col change end cmd valid */
80*4882a593Smuzhiyun #define PL353_NAND_ECC_BUSY_TIMEOUT (1 * HZ)
81*4882a593Smuzhiyun /**
82*4882a593Smuzhiyun * struct pl353_smc_data - Private smc driver structure
83*4882a593Smuzhiyun * @memclk: Pointer to the peripheral clock
84*4882a593Smuzhiyun * @aclk: Pointer to the APER clock
85*4882a593Smuzhiyun */
86*4882a593Smuzhiyun struct pl353_smc_data {
87*4882a593Smuzhiyun struct clk *memclk;
88*4882a593Smuzhiyun struct clk *aclk;
89*4882a593Smuzhiyun };
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun /* SMC virtual register base */
92*4882a593Smuzhiyun static void __iomem *pl353_smc_base;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun /**
95*4882a593Smuzhiyun * pl353_smc_set_buswidth - Set memory buswidth
96*4882a593Smuzhiyun * @bw: Memory buswidth (8 | 16)
97*4882a593Smuzhiyun * Return: 0 on success or negative errno.
98*4882a593Smuzhiyun */
pl353_smc_set_buswidth(unsigned int bw)99*4882a593Smuzhiyun int pl353_smc_set_buswidth(unsigned int bw)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun if (bw != PL353_SMC_MEM_WIDTH_8 && bw != PL353_SMC_MEM_WIDTH_16)
102*4882a593Smuzhiyun return -EINVAL;
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun writel(bw, pl353_smc_base + PL353_SMC_SET_OPMODE_OFFS);
105*4882a593Smuzhiyun writel(PL353_SMC_DC_UPT_NAND_REGS, pl353_smc_base +
106*4882a593Smuzhiyun PL353_SMC_DIRECT_CMD_OFFS);
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun return 0;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(pl353_smc_set_buswidth);
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun /**
113*4882a593Smuzhiyun * pl353_smc_set_cycles - Set memory timing parameters
114*4882a593Smuzhiyun * @timings: NAND controller timing parameters
115*4882a593Smuzhiyun *
116*4882a593Smuzhiyun * Sets NAND chip specific timing parameters.
117*4882a593Smuzhiyun */
pl353_smc_set_cycles(u32 timings[])118*4882a593Smuzhiyun void pl353_smc_set_cycles(u32 timings[])
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun /*
121*4882a593Smuzhiyun * Set write pulse timing. This one is easy to extract:
122*4882a593Smuzhiyun *
123*4882a593Smuzhiyun * NWE_PULSE = tWP
124*4882a593Smuzhiyun */
125*4882a593Smuzhiyun timings[0] &= PL353_SMC_SET_CYCLES_T0_MASK;
126*4882a593Smuzhiyun timings[1] = (timings[1] & PL353_SMC_SET_CYCLES_T1_MASK) <<
127*4882a593Smuzhiyun PL353_SMC_SET_CYCLES_T1_SHIFT;
128*4882a593Smuzhiyun timings[2] = (timings[2] & PL353_SMC_SET_CYCLES_T2_MASK) <<
129*4882a593Smuzhiyun PL353_SMC_SET_CYCLES_T2_SHIFT;
130*4882a593Smuzhiyun timings[3] = (timings[3] & PL353_SMC_SET_CYCLES_T3_MASK) <<
131*4882a593Smuzhiyun PL353_SMC_SET_CYCLES_T3_SHIFT;
132*4882a593Smuzhiyun timings[4] = (timings[4] & PL353_SMC_SET_CYCLES_T4_MASK) <<
133*4882a593Smuzhiyun PL353_SMC_SET_CYCLES_T4_SHIFT;
134*4882a593Smuzhiyun timings[5] = (timings[5] & PL353_SMC_SET_CYCLES_T5_MASK) <<
135*4882a593Smuzhiyun PL353_SMC_SET_CYCLES_T5_SHIFT;
136*4882a593Smuzhiyun timings[6] = (timings[6] & PL353_SMC_SET_CYCLES_T6_MASK) <<
137*4882a593Smuzhiyun PL353_SMC_SET_CYCLES_T6_SHIFT;
138*4882a593Smuzhiyun timings[0] |= timings[1] | timings[2] | timings[3] |
139*4882a593Smuzhiyun timings[4] | timings[5] | timings[6];
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun writel(timings[0], pl353_smc_base + PL353_SMC_SET_CYCLES_OFFS);
142*4882a593Smuzhiyun writel(PL353_SMC_DC_UPT_NAND_REGS, pl353_smc_base +
143*4882a593Smuzhiyun PL353_SMC_DIRECT_CMD_OFFS);
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(pl353_smc_set_cycles);
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun /**
148*4882a593Smuzhiyun * pl353_smc_ecc_is_busy - Read ecc busy flag
149*4882a593Smuzhiyun * Return: the ecc_status bit from the ecc_status register. 1 = busy, 0 = idle
150*4882a593Smuzhiyun */
pl353_smc_ecc_is_busy(void)151*4882a593Smuzhiyun bool pl353_smc_ecc_is_busy(void)
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun return ((readl(pl353_smc_base + PL353_SMC_ECC_STATUS_OFFS) &
154*4882a593Smuzhiyun PL353_SMC_ECC_STATUS_BUSY) == PL353_SMC_ECC_STATUS_BUSY);
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(pl353_smc_ecc_is_busy);
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun /**
159*4882a593Smuzhiyun * pl353_smc_get_ecc_val - Read ecc_valueN registers
160*4882a593Smuzhiyun * @ecc_reg: Index of the ecc_value reg (0..3)
161*4882a593Smuzhiyun * Return: the content of the requested ecc_value register.
162*4882a593Smuzhiyun *
163*4882a593Smuzhiyun * There are four valid ecc_value registers. The argument is truncated to stay
164*4882a593Smuzhiyun * within this valid boundary.
165*4882a593Smuzhiyun */
pl353_smc_get_ecc_val(int ecc_reg)166*4882a593Smuzhiyun u32 pl353_smc_get_ecc_val(int ecc_reg)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun u32 addr, reg;
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun addr = PL353_SMC_ECC_VALUE0_OFFS +
171*4882a593Smuzhiyun (ecc_reg * PL353_SMC_ECC_REG_SIZE_OFFS);
172*4882a593Smuzhiyun reg = readl(pl353_smc_base + addr);
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun return reg;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(pl353_smc_get_ecc_val);
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun /**
179*4882a593Smuzhiyun * pl353_smc_get_nand_int_status_raw - Get NAND interrupt status bit
180*4882a593Smuzhiyun * Return: the raw_int_status1 bit from the memc_status register
181*4882a593Smuzhiyun */
pl353_smc_get_nand_int_status_raw(void)182*4882a593Smuzhiyun int pl353_smc_get_nand_int_status_raw(void)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun u32 reg;
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun reg = readl(pl353_smc_base + PL353_SMC_MEMC_STATUS_OFFS);
187*4882a593Smuzhiyun reg >>= PL353_SMC_MEMC_STATUS_RAW_INT_1_SHIFT;
188*4882a593Smuzhiyun reg &= 1;
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun return reg;
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(pl353_smc_get_nand_int_status_raw);
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun /**
195*4882a593Smuzhiyun * pl353_smc_clr_nand_int - Clear NAND interrupt
196*4882a593Smuzhiyun */
pl353_smc_clr_nand_int(void)197*4882a593Smuzhiyun void pl353_smc_clr_nand_int(void)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun writel(PL353_SMC_CFG_CLR_INT_CLR_1,
200*4882a593Smuzhiyun pl353_smc_base + PL353_SMC_CFG_CLR_OFFS);
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(pl353_smc_clr_nand_int);
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun /**
205*4882a593Smuzhiyun * pl353_smc_set_ecc_mode - Set SMC ECC mode
206*4882a593Smuzhiyun * @mode: ECC mode (BYPASS, APB, MEM)
207*4882a593Smuzhiyun * Return: 0 on success or negative errno.
208*4882a593Smuzhiyun */
pl353_smc_set_ecc_mode(enum pl353_smc_ecc_mode mode)209*4882a593Smuzhiyun int pl353_smc_set_ecc_mode(enum pl353_smc_ecc_mode mode)
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun u32 reg;
212*4882a593Smuzhiyun int ret = 0;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun switch (mode) {
215*4882a593Smuzhiyun case PL353_SMC_ECCMODE_BYPASS:
216*4882a593Smuzhiyun case PL353_SMC_ECCMODE_APB:
217*4882a593Smuzhiyun case PL353_SMC_ECCMODE_MEM:
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun reg = readl(pl353_smc_base + PL353_SMC_ECC_MEMCFG_OFFS);
220*4882a593Smuzhiyun reg &= ~PL353_SMC_ECC_MEMCFG_MODE_MASK;
221*4882a593Smuzhiyun reg |= mode << PL353_SMC_ECC_MEMCFG_MODE_SHIFT;
222*4882a593Smuzhiyun writel(reg, pl353_smc_base + PL353_SMC_ECC_MEMCFG_OFFS);
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun break;
225*4882a593Smuzhiyun default:
226*4882a593Smuzhiyun ret = -EINVAL;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun return ret;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(pl353_smc_set_ecc_mode);
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun /**
234*4882a593Smuzhiyun * pl353_smc_set_ecc_pg_size - Set SMC ECC page size
235*4882a593Smuzhiyun * @pg_sz: ECC page size
236*4882a593Smuzhiyun * Return: 0 on success or negative errno.
237*4882a593Smuzhiyun */
pl353_smc_set_ecc_pg_size(unsigned int pg_sz)238*4882a593Smuzhiyun int pl353_smc_set_ecc_pg_size(unsigned int pg_sz)
239*4882a593Smuzhiyun {
240*4882a593Smuzhiyun u32 reg, sz;
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun switch (pg_sz) {
243*4882a593Smuzhiyun case 0:
244*4882a593Smuzhiyun sz = 0;
245*4882a593Smuzhiyun break;
246*4882a593Smuzhiyun case SZ_512:
247*4882a593Smuzhiyun sz = 1;
248*4882a593Smuzhiyun break;
249*4882a593Smuzhiyun case SZ_1K:
250*4882a593Smuzhiyun sz = 2;
251*4882a593Smuzhiyun break;
252*4882a593Smuzhiyun case SZ_2K:
253*4882a593Smuzhiyun sz = 3;
254*4882a593Smuzhiyun break;
255*4882a593Smuzhiyun default:
256*4882a593Smuzhiyun return -EINVAL;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun reg = readl(pl353_smc_base + PL353_SMC_ECC_MEMCFG_OFFS);
260*4882a593Smuzhiyun reg &= ~PL353_SMC_ECC_MEMCFG_PGSIZE_MASK;
261*4882a593Smuzhiyun reg |= sz;
262*4882a593Smuzhiyun writel(reg, pl353_smc_base + PL353_SMC_ECC_MEMCFG_OFFS);
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun return 0;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(pl353_smc_set_ecc_pg_size);
267*4882a593Smuzhiyun
pl353_smc_suspend(struct device * dev)268*4882a593Smuzhiyun static int __maybe_unused pl353_smc_suspend(struct device *dev)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun struct pl353_smc_data *pl353_smc = dev_get_drvdata(dev);
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun clk_disable(pl353_smc->memclk);
273*4882a593Smuzhiyun clk_disable(pl353_smc->aclk);
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun return 0;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
pl353_smc_resume(struct device * dev)278*4882a593Smuzhiyun static int __maybe_unused pl353_smc_resume(struct device *dev)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun int ret;
281*4882a593Smuzhiyun struct pl353_smc_data *pl353_smc = dev_get_drvdata(dev);
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun ret = clk_enable(pl353_smc->aclk);
284*4882a593Smuzhiyun if (ret) {
285*4882a593Smuzhiyun dev_err(dev, "Cannot enable axi domain clock.\n");
286*4882a593Smuzhiyun return ret;
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun ret = clk_enable(pl353_smc->memclk);
290*4882a593Smuzhiyun if (ret) {
291*4882a593Smuzhiyun dev_err(dev, "Cannot enable memory clock.\n");
292*4882a593Smuzhiyun clk_disable(pl353_smc->aclk);
293*4882a593Smuzhiyun return ret;
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun return ret;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun static struct amba_driver pl353_smc_driver;
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun static SIMPLE_DEV_PM_OPS(pl353_smc_dev_pm_ops, pl353_smc_suspend,
302*4882a593Smuzhiyun pl353_smc_resume);
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun /**
305*4882a593Smuzhiyun * pl353_smc_init_nand_interface - Initialize the NAND interface
306*4882a593Smuzhiyun * @adev: Pointer to the amba_device struct
307*4882a593Smuzhiyun * @nand_node: Pointer to the pl353_nand device_node struct
308*4882a593Smuzhiyun */
pl353_smc_init_nand_interface(struct amba_device * adev,struct device_node * nand_node)309*4882a593Smuzhiyun static void pl353_smc_init_nand_interface(struct amba_device *adev,
310*4882a593Smuzhiyun struct device_node *nand_node)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun unsigned long timeout;
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun pl353_smc_set_buswidth(PL353_SMC_MEM_WIDTH_8);
315*4882a593Smuzhiyun writel(PL353_SMC_CFG_CLR_INT_CLR_1,
316*4882a593Smuzhiyun pl353_smc_base + PL353_SMC_CFG_CLR_OFFS);
317*4882a593Smuzhiyun writel(PL353_SMC_DC_UPT_NAND_REGS, pl353_smc_base +
318*4882a593Smuzhiyun PL353_SMC_DIRECT_CMD_OFFS);
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun timeout = jiffies + PL353_NAND_ECC_BUSY_TIMEOUT;
321*4882a593Smuzhiyun /* Wait till the ECC operation is complete */
322*4882a593Smuzhiyun do {
323*4882a593Smuzhiyun if (pl353_smc_ecc_is_busy())
324*4882a593Smuzhiyun cpu_relax();
325*4882a593Smuzhiyun else
326*4882a593Smuzhiyun break;
327*4882a593Smuzhiyun } while (!time_after_eq(jiffies, timeout));
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun if (time_after_eq(jiffies, timeout))
330*4882a593Smuzhiyun return;
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun writel(PL353_NAND_ECC_CMD1,
333*4882a593Smuzhiyun pl353_smc_base + PL353_SMC_ECC_MEMCMD1_OFFS);
334*4882a593Smuzhiyun writel(PL353_NAND_ECC_CMD2,
335*4882a593Smuzhiyun pl353_smc_base + PL353_SMC_ECC_MEMCMD2_OFFS);
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun static const struct of_device_id pl353_smc_supported_children[] = {
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun .compatible = "cfi-flash"
341*4882a593Smuzhiyun },
342*4882a593Smuzhiyun {
343*4882a593Smuzhiyun .compatible = "arm,pl353-nand-r2p1",
344*4882a593Smuzhiyun .data = pl353_smc_init_nand_interface
345*4882a593Smuzhiyun },
346*4882a593Smuzhiyun {}
347*4882a593Smuzhiyun };
348*4882a593Smuzhiyun
pl353_smc_probe(struct amba_device * adev,const struct amba_id * id)349*4882a593Smuzhiyun static int pl353_smc_probe(struct amba_device *adev, const struct amba_id *id)
350*4882a593Smuzhiyun {
351*4882a593Smuzhiyun struct pl353_smc_data *pl353_smc;
352*4882a593Smuzhiyun struct device_node *child;
353*4882a593Smuzhiyun struct resource *res;
354*4882a593Smuzhiyun int err;
355*4882a593Smuzhiyun struct device_node *of_node = adev->dev.of_node;
356*4882a593Smuzhiyun static void (*init)(struct amba_device *adev,
357*4882a593Smuzhiyun struct device_node *nand_node);
358*4882a593Smuzhiyun const struct of_device_id *match = NULL;
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun pl353_smc = devm_kzalloc(&adev->dev, sizeof(*pl353_smc), GFP_KERNEL);
361*4882a593Smuzhiyun if (!pl353_smc)
362*4882a593Smuzhiyun return -ENOMEM;
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun /* Get the NAND controller virtual address */
365*4882a593Smuzhiyun res = &adev->res;
366*4882a593Smuzhiyun pl353_smc_base = devm_ioremap_resource(&adev->dev, res);
367*4882a593Smuzhiyun if (IS_ERR(pl353_smc_base))
368*4882a593Smuzhiyun return PTR_ERR(pl353_smc_base);
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun pl353_smc->aclk = devm_clk_get(&adev->dev, "apb_pclk");
371*4882a593Smuzhiyun if (IS_ERR(pl353_smc->aclk)) {
372*4882a593Smuzhiyun dev_err(&adev->dev, "aclk clock not found.\n");
373*4882a593Smuzhiyun return PTR_ERR(pl353_smc->aclk);
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun pl353_smc->memclk = devm_clk_get(&adev->dev, "memclk");
377*4882a593Smuzhiyun if (IS_ERR(pl353_smc->memclk)) {
378*4882a593Smuzhiyun dev_err(&adev->dev, "memclk clock not found.\n");
379*4882a593Smuzhiyun return PTR_ERR(pl353_smc->memclk);
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun err = clk_prepare_enable(pl353_smc->aclk);
383*4882a593Smuzhiyun if (err) {
384*4882a593Smuzhiyun dev_err(&adev->dev, "Unable to enable AXI clock.\n");
385*4882a593Smuzhiyun return err;
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun err = clk_prepare_enable(pl353_smc->memclk);
389*4882a593Smuzhiyun if (err) {
390*4882a593Smuzhiyun dev_err(&adev->dev, "Unable to enable memory clock.\n");
391*4882a593Smuzhiyun goto out_clk_dis_aper;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun amba_set_drvdata(adev, pl353_smc);
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun /* clear interrupts */
397*4882a593Smuzhiyun writel(PL353_SMC_CFG_CLR_DEFAULT_MASK,
398*4882a593Smuzhiyun pl353_smc_base + PL353_SMC_CFG_CLR_OFFS);
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun /* Find compatible children. Only a single child is supported */
401*4882a593Smuzhiyun for_each_available_child_of_node(of_node, child) {
402*4882a593Smuzhiyun match = of_match_node(pl353_smc_supported_children, child);
403*4882a593Smuzhiyun if (!match) {
404*4882a593Smuzhiyun dev_warn(&adev->dev, "unsupported child node\n");
405*4882a593Smuzhiyun continue;
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun break;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun if (!match) {
410*4882a593Smuzhiyun err = -ENODEV;
411*4882a593Smuzhiyun dev_err(&adev->dev, "no matching children\n");
412*4882a593Smuzhiyun goto out_clk_disable;
413*4882a593Smuzhiyun }
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun init = match->data;
416*4882a593Smuzhiyun if (init)
417*4882a593Smuzhiyun init(adev, child);
418*4882a593Smuzhiyun of_platform_device_create(child, NULL, &adev->dev);
419*4882a593Smuzhiyun of_node_put(child);
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun return 0;
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun out_clk_disable:
424*4882a593Smuzhiyun clk_disable_unprepare(pl353_smc->memclk);
425*4882a593Smuzhiyun out_clk_dis_aper:
426*4882a593Smuzhiyun clk_disable_unprepare(pl353_smc->aclk);
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun return err;
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun
pl353_smc_remove(struct amba_device * adev)431*4882a593Smuzhiyun static void pl353_smc_remove(struct amba_device *adev)
432*4882a593Smuzhiyun {
433*4882a593Smuzhiyun struct pl353_smc_data *pl353_smc = amba_get_drvdata(adev);
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun clk_disable_unprepare(pl353_smc->memclk);
436*4882a593Smuzhiyun clk_disable_unprepare(pl353_smc->aclk);
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun static const struct amba_id pl353_ids[] = {
440*4882a593Smuzhiyun {
441*4882a593Smuzhiyun .id = 0x00041353,
442*4882a593Smuzhiyun .mask = 0x000fffff,
443*4882a593Smuzhiyun },
444*4882a593Smuzhiyun { 0, 0 },
445*4882a593Smuzhiyun };
446*4882a593Smuzhiyun MODULE_DEVICE_TABLE(amba, pl353_ids);
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun static struct amba_driver pl353_smc_driver = {
449*4882a593Smuzhiyun .drv = {
450*4882a593Smuzhiyun .owner = THIS_MODULE,
451*4882a593Smuzhiyun .name = "pl353-smc",
452*4882a593Smuzhiyun .pm = &pl353_smc_dev_pm_ops,
453*4882a593Smuzhiyun },
454*4882a593Smuzhiyun .id_table = pl353_ids,
455*4882a593Smuzhiyun .probe = pl353_smc_probe,
456*4882a593Smuzhiyun .remove = pl353_smc_remove,
457*4882a593Smuzhiyun };
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun module_amba_driver(pl353_smc_driver);
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun MODULE_AUTHOR("Xilinx, Inc.");
462*4882a593Smuzhiyun MODULE_DESCRIPTION("ARM PL353 SMC Driver");
463*4882a593Smuzhiyun MODULE_LICENSE("GPL");
464