1
2
3
4
5
6
7
8
9
10
11
12#include <linux/clk.h>
13#include <linux/init.h>
14#include <linux/math64.h>
15#include <linux/of.h>
16#include <linux/of_address.h>
17#include <linux/of_device.h>
18#include <linux/of_platform.h>
19#include <linux/platform_device.h>
20#include <linux/slab.h>
21#include <linux/spinlock.h>
22
23#include <linux/jz4780-nemc.h>
24
25#define NEMC_SMCRn(n) (0x14 + (((n) - 1) * 4))
26#define NEMC_NFCSR 0x50
27
28#define NEMC_SMCR_SMT BIT(0)
29#define NEMC_SMCR_BW_SHIFT 6
30#define NEMC_SMCR_BW_MASK (0x3 << NEMC_SMCR_BW_SHIFT)
31#define NEMC_SMCR_BW_8 (0 << 6)
32#define NEMC_SMCR_TAS_SHIFT 8
33#define NEMC_SMCR_TAS_MASK (0xf << NEMC_SMCR_TAS_SHIFT)
34#define NEMC_SMCR_TAH_SHIFT 12
35#define NEMC_SMCR_TAH_MASK (0xf << NEMC_SMCR_TAH_SHIFT)
36#define NEMC_SMCR_TBP_SHIFT 16
37#define NEMC_SMCR_TBP_MASK (0xf << NEMC_SMCR_TBP_SHIFT)
38#define NEMC_SMCR_TAW_SHIFT 20
39#define NEMC_SMCR_TAW_MASK (0xf << NEMC_SMCR_TAW_SHIFT)
40#define NEMC_SMCR_TSTRV_SHIFT 24
41#define NEMC_SMCR_TSTRV_MASK (0x3f << NEMC_SMCR_TSTRV_SHIFT)
42
43#define NEMC_NFCSR_NFEn(n) BIT(((n) - 1) << 1)
44#define NEMC_NFCSR_NFCEn(n) BIT((((n) - 1) << 1) + 1)
45#define NEMC_NFCSR_TNFEn(n) BIT(16 + (n) - 1)
46
47struct jz4780_nemc {
48 spinlock_t lock;
49 struct device *dev;
50 void __iomem *base;
51 struct clk *clk;
52 uint32_t clk_period;
53 unsigned long banks_present;
54};
55
56
57
58
59
60
61
62
63
64unsigned int jz4780_nemc_num_banks(struct device *dev)
65{
66 const __be32 *prop;
67 unsigned int bank, count = 0;
68 unsigned long referenced = 0;
69 int i = 0;
70
71 while ((prop = of_get_address(dev->of_node, i++, NULL, NULL))) {
72 bank = of_read_number(prop, 1);
73 if (!(referenced & BIT(bank))) {
74 referenced |= BIT(bank);
75 count++;
76 }
77 }
78
79 return count;
80}
81EXPORT_SYMBOL(jz4780_nemc_num_banks);
82
83
84
85
86
87
88
89void jz4780_nemc_set_type(struct device *dev, unsigned int bank,
90 enum jz4780_nemc_bank_type type)
91{
92 struct jz4780_nemc *nemc = dev_get_drvdata(dev->parent);
93 uint32_t nfcsr;
94
95 nfcsr = readl(nemc->base + NEMC_NFCSR);
96
97
98 switch (type) {
99 case JZ4780_NEMC_BANK_SRAM:
100 nfcsr &= ~(NEMC_NFCSR_TNFEn(bank) | NEMC_NFCSR_NFEn(bank));
101 break;
102 case JZ4780_NEMC_BANK_NAND:
103 nfcsr &= ~NEMC_NFCSR_TNFEn(bank);
104 nfcsr |= NEMC_NFCSR_NFEn(bank);
105 break;
106 }
107
108 writel(nfcsr, nemc->base + NEMC_NFCSR);
109}
110EXPORT_SYMBOL(jz4780_nemc_set_type);
111
112
113
114
115
116
117
118
119
120
121void jz4780_nemc_assert(struct device *dev, unsigned int bank, bool assert)
122{
123 struct jz4780_nemc *nemc = dev_get_drvdata(dev->parent);
124 uint32_t nfcsr;
125
126 nfcsr = readl(nemc->base + NEMC_NFCSR);
127
128 if (assert)
129 nfcsr |= NEMC_NFCSR_NFCEn(bank);
130 else
131 nfcsr &= ~NEMC_NFCSR_NFCEn(bank);
132
133 writel(nfcsr, nemc->base + NEMC_NFCSR);
134}
135EXPORT_SYMBOL(jz4780_nemc_assert);
136
137static uint32_t jz4780_nemc_clk_period(struct jz4780_nemc *nemc)
138{
139 unsigned long rate;
140
141 rate = clk_get_rate(nemc->clk);
142 if (!rate)
143 return 0;
144
145
146 return div64_ul(1000000000000ull, rate);
147}
148
149static uint32_t jz4780_nemc_ns_to_cycles(struct jz4780_nemc *nemc, uint32_t ns)
150{
151 return ((ns * 1000) + nemc->clk_period - 1) / nemc->clk_period;
152}
153
154static bool jz4780_nemc_configure_bank(struct jz4780_nemc *nemc,
155 unsigned int bank,
156 struct device_node *node)
157{
158 uint32_t smcr, val, cycles;
159
160
161
162
163
164 static const uint32_t convert_tBP_tAW[] = {
165 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
166
167
168 11, 11,
169
170
171 12, 12, 12,
172
173
174 13, 13, 13, 13, 13,
175
176
177 14, 14, 14, 14, 14,
178
179
180 15, 15, 15, 15, 15, 15
181 };
182
183 smcr = readl(nemc->base + NEMC_SMCRn(bank));
184 smcr &= ~NEMC_SMCR_SMT;
185
186 if (!of_property_read_u32(node, "ingenic,nemc-bus-width", &val)) {
187 smcr &= ~NEMC_SMCR_BW_MASK;
188 switch (val) {
189 case 8:
190 smcr |= NEMC_SMCR_BW_8;
191 break;
192 default:
193
194
195
196
197 dev_err(nemc->dev, "unsupported bus width: %u\n", val);
198 return false;
199 }
200 }
201
202 if (of_property_read_u32(node, "ingenic,nemc-tAS", &val) == 0) {
203 smcr &= ~NEMC_SMCR_TAS_MASK;
204 cycles = jz4780_nemc_ns_to_cycles(nemc, val);
205 if (cycles > 15) {
206 dev_err(nemc->dev, "tAS %u is too high (%u cycles)\n",
207 val, cycles);
208 return false;
209 }
210
211 smcr |= cycles << NEMC_SMCR_TAS_SHIFT;
212 }
213
214 if (of_property_read_u32(node, "ingenic,nemc-tAH", &val) == 0) {
215 smcr &= ~NEMC_SMCR_TAH_MASK;
216 cycles = jz4780_nemc_ns_to_cycles(nemc, val);
217 if (cycles > 15) {
218 dev_err(nemc->dev, "tAH %u is too high (%u cycles)\n",
219 val, cycles);
220 return false;
221 }
222
223 smcr |= cycles << NEMC_SMCR_TAH_SHIFT;
224 }
225
226 if (of_property_read_u32(node, "ingenic,nemc-tBP", &val) == 0) {
227 smcr &= ~NEMC_SMCR_TBP_MASK;
228 cycles = jz4780_nemc_ns_to_cycles(nemc, val);
229 if (cycles > 31) {
230 dev_err(nemc->dev, "tBP %u is too high (%u cycles)\n",
231 val, cycles);
232 return false;
233 }
234
235 smcr |= convert_tBP_tAW[cycles] << NEMC_SMCR_TBP_SHIFT;
236 }
237
238 if (of_property_read_u32(node, "ingenic,nemc-tAW", &val) == 0) {
239 smcr &= ~NEMC_SMCR_TAW_MASK;
240 cycles = jz4780_nemc_ns_to_cycles(nemc, val);
241 if (cycles > 31) {
242 dev_err(nemc->dev, "tAW %u is too high (%u cycles)\n",
243 val, cycles);
244 return false;
245 }
246
247 smcr |= convert_tBP_tAW[cycles] << NEMC_SMCR_TAW_SHIFT;
248 }
249
250 if (of_property_read_u32(node, "ingenic,nemc-tSTRV", &val) == 0) {
251 smcr &= ~NEMC_SMCR_TSTRV_MASK;
252 cycles = jz4780_nemc_ns_to_cycles(nemc, val);
253 if (cycles > 63) {
254 dev_err(nemc->dev, "tSTRV %u is too high (%u cycles)\n",
255 val, cycles);
256 return false;
257 }
258
259 smcr |= cycles << NEMC_SMCR_TSTRV_SHIFT;
260 }
261
262 writel(smcr, nemc->base + NEMC_SMCRn(bank));
263 return true;
264}
265
266static int jz4780_nemc_probe(struct platform_device *pdev)
267{
268 struct device *dev = &pdev->dev;
269 struct jz4780_nemc *nemc;
270 struct resource *res;
271 struct device_node *child;
272 const __be32 *prop;
273 unsigned int bank;
274 unsigned long referenced;
275 int i, ret;
276
277 nemc = devm_kzalloc(dev, sizeof(*nemc), GFP_KERNEL);
278 if (!nemc)
279 return -ENOMEM;
280
281 spin_lock_init(&nemc->lock);
282 nemc->dev = dev;
283
284 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
285 nemc->base = devm_ioremap_resource(dev, res);
286 if (IS_ERR(nemc->base)) {
287 dev_err(dev, "failed to get I/O memory\n");
288 return PTR_ERR(nemc->base);
289 }
290
291 writel(0, nemc->base + NEMC_NFCSR);
292
293 nemc->clk = devm_clk_get(dev, NULL);
294 if (IS_ERR(nemc->clk)) {
295 dev_err(dev, "failed to get clock\n");
296 return PTR_ERR(nemc->clk);
297 }
298
299 ret = clk_prepare_enable(nemc->clk);
300 if (ret) {
301 dev_err(dev, "failed to enable clock: %d\n", ret);
302 return ret;
303 }
304
305 nemc->clk_period = jz4780_nemc_clk_period(nemc);
306 if (!nemc->clk_period) {
307 dev_err(dev, "failed to calculate clock period\n");
308 clk_disable_unprepare(nemc->clk);
309 return -EINVAL;
310 }
311
312
313
314
315
316
317
318 for_each_child_of_node(nemc->dev->of_node, child) {
319 referenced = 0;
320 i = 0;
321 while ((prop = of_get_address(child, i++, NULL, NULL))) {
322 bank = of_read_number(prop, 1);
323 if (bank < 1 || bank >= JZ4780_NEMC_NUM_BANKS) {
324 dev_err(nemc->dev,
325 "%pOF requests invalid bank %u\n",
326 child, bank);
327
328
329 referenced = 0;
330 break;
331 }
332
333 referenced |= BIT(bank);
334 }
335
336 if (!referenced) {
337 dev_err(nemc->dev, "%pOF has no addresses\n",
338 child);
339 continue;
340 } else if (nemc->banks_present & referenced) {
341 dev_err(nemc->dev, "%pOF conflicts with another node\n",
342 child);
343 continue;
344 }
345
346
347 for_each_set_bit(bank, &referenced, JZ4780_NEMC_NUM_BANKS) {
348 if (!jz4780_nemc_configure_bank(nemc, bank, child)) {
349 referenced = 0;
350 break;
351 }
352 }
353
354 if (referenced) {
355 if (of_platform_device_create(child, NULL, nemc->dev))
356 nemc->banks_present |= referenced;
357 }
358 }
359
360 platform_set_drvdata(pdev, nemc);
361 dev_info(dev, "JZ4780 NEMC initialised\n");
362 return 0;
363}
364
365static int jz4780_nemc_remove(struct platform_device *pdev)
366{
367 struct jz4780_nemc *nemc = platform_get_drvdata(pdev);
368
369 clk_disable_unprepare(nemc->clk);
370 return 0;
371}
372
373static const struct of_device_id jz4780_nemc_dt_match[] = {
374 { .compatible = "ingenic,jz4780-nemc" },
375 {},
376};
377
378static struct platform_driver jz4780_nemc_driver = {
379 .probe = jz4780_nemc_probe,
380 .remove = jz4780_nemc_remove,
381 .driver = {
382 .name = "jz4780-nemc",
383 .of_match_table = of_match_ptr(jz4780_nemc_dt_match),
384 },
385};
386
387static int __init jz4780_nemc_init(void)
388{
389 return platform_driver_register(&jz4780_nemc_driver);
390}
391subsys_initcall(jz4780_nemc_init);
392