Linux 5.15-rc6
[muen/linux.git] / drivers / memory / atmel-ebi.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * EBI driver for Atmel chips
4  * inspired by the fsl weim bus driver
5  *
6  * Copyright (C) 2013 Jean-Jacques Hiblot <jjhiblot@traphandler.com>
7  */
8
9 #include <linux/clk.h>
10 #include <linux/io.h>
11 #include <linux/mfd/syscon.h>
12 #include <linux/mfd/syscon/atmel-matrix.h>
13 #include <linux/mfd/syscon/atmel-smc.h>
14 #include <linux/init.h>
15 #include <linux/of_device.h>
16 #include <linux/regmap.h>
17 #include <soc/at91/atmel-sfr.h>
18
19 #define AT91_EBI_NUM_CS         8
20
21 struct atmel_ebi_dev_config {
22         int cs;
23         struct atmel_smc_cs_conf smcconf;
24 };
25
26 struct atmel_ebi;
27
28 struct atmel_ebi_dev {
29         struct list_head node;
30         struct atmel_ebi *ebi;
31         u32 mode;
32         int numcs;
33         struct atmel_ebi_dev_config configs[];
34 };
35
36 struct atmel_ebi_caps {
37         unsigned int available_cs;
38         unsigned int ebi_csa_offs;
39         const char *regmap_name;
40         void (*get_config)(struct atmel_ebi_dev *ebid,
41                            struct atmel_ebi_dev_config *conf);
42         int (*xlate_config)(struct atmel_ebi_dev *ebid,
43                             struct device_node *configs_np,
44                             struct atmel_ebi_dev_config *conf);
45         void (*apply_config)(struct atmel_ebi_dev *ebid,
46                              struct atmel_ebi_dev_config *conf);
47 };
48
49 struct atmel_ebi {
50         struct clk *clk;
51         struct regmap *regmap;
52         struct  {
53                 struct regmap *regmap;
54                 struct clk *clk;
55                 const struct atmel_hsmc_reg_layout *layout;
56         } smc;
57
58         struct device *dev;
59         const struct atmel_ebi_caps *caps;
60         struct list_head devs;
61 };
62
63 struct atmel_smc_timing_xlate {
64         const char *name;
65         int (*converter)(struct atmel_smc_cs_conf *conf,
66                          unsigned int shift, unsigned int nycles);
67         unsigned int shift;
68 };
69
70 #define ATMEL_SMC_SETUP_XLATE(nm, pos)  \
71         { .name = nm, .converter = atmel_smc_cs_conf_set_setup, .shift = pos}
72
73 #define ATMEL_SMC_PULSE_XLATE(nm, pos)  \
74         { .name = nm, .converter = atmel_smc_cs_conf_set_pulse, .shift = pos}
75
76 #define ATMEL_SMC_CYCLE_XLATE(nm, pos)  \
77         { .name = nm, .converter = atmel_smc_cs_conf_set_cycle, .shift = pos}
78
79 static void at91sam9_ebi_get_config(struct atmel_ebi_dev *ebid,
80                                     struct atmel_ebi_dev_config *conf)
81 {
82         atmel_smc_cs_conf_get(ebid->ebi->smc.regmap, conf->cs,
83                               &conf->smcconf);
84 }
85
86 static void sama5_ebi_get_config(struct atmel_ebi_dev *ebid,
87                                  struct atmel_ebi_dev_config *conf)
88 {
89         atmel_hsmc_cs_conf_get(ebid->ebi->smc.regmap, ebid->ebi->smc.layout,
90                                conf->cs, &conf->smcconf);
91 }
92
93 static const struct atmel_smc_timing_xlate timings_xlate_table[] = {
94         ATMEL_SMC_SETUP_XLATE("atmel,smc-ncs-rd-setup-ns",
95                               ATMEL_SMC_NCS_RD_SHIFT),
96         ATMEL_SMC_SETUP_XLATE("atmel,smc-ncs-wr-setup-ns",
97                               ATMEL_SMC_NCS_WR_SHIFT),
98         ATMEL_SMC_SETUP_XLATE("atmel,smc-nrd-setup-ns", ATMEL_SMC_NRD_SHIFT),
99         ATMEL_SMC_SETUP_XLATE("atmel,smc-nwe-setup-ns", ATMEL_SMC_NWE_SHIFT),
100         ATMEL_SMC_PULSE_XLATE("atmel,smc-ncs-rd-pulse-ns",
101                               ATMEL_SMC_NCS_RD_SHIFT),
102         ATMEL_SMC_PULSE_XLATE("atmel,smc-ncs-wr-pulse-ns",
103                               ATMEL_SMC_NCS_WR_SHIFT),
104         ATMEL_SMC_PULSE_XLATE("atmel,smc-nrd-pulse-ns", ATMEL_SMC_NRD_SHIFT),
105         ATMEL_SMC_PULSE_XLATE("atmel,smc-nwe-pulse-ns", ATMEL_SMC_NWE_SHIFT),
106         ATMEL_SMC_CYCLE_XLATE("atmel,smc-nrd-cycle-ns", ATMEL_SMC_NRD_SHIFT),
107         ATMEL_SMC_CYCLE_XLATE("atmel,smc-nwe-cycle-ns", ATMEL_SMC_NWE_SHIFT),
108 };
109
110 static int atmel_ebi_xslate_smc_timings(struct atmel_ebi_dev *ebid,
111                                         struct device_node *np,
112                                         struct atmel_smc_cs_conf *smcconf)
113 {
114         unsigned int clk_rate = clk_get_rate(ebid->ebi->clk);
115         unsigned int clk_period_ns = NSEC_PER_SEC / clk_rate;
116         bool required = false;
117         unsigned int ncycles;
118         int ret, i;
119         u32 val;
120
121         ret = of_property_read_u32(np, "atmel,smc-tdf-ns", &val);
122         if (!ret) {
123                 required = true;
124                 ncycles = DIV_ROUND_UP(val, clk_period_ns);
125                 if (ncycles > ATMEL_SMC_MODE_TDF_MAX) {
126                         ret = -EINVAL;
127                         goto out;
128                 }
129
130                 if (ncycles < ATMEL_SMC_MODE_TDF_MIN)
131                         ncycles = ATMEL_SMC_MODE_TDF_MIN;
132
133                 smcconf->mode |= ATMEL_SMC_MODE_TDF(ncycles);
134         }
135
136         for (i = 0; i < ARRAY_SIZE(timings_xlate_table); i++) {
137                 const struct atmel_smc_timing_xlate *xlate;
138
139                 xlate = &timings_xlate_table[i];
140
141                 ret = of_property_read_u32(np, xlate->name, &val);
142                 if (ret) {
143                         if (!required)
144                                 continue;
145                         else
146                                 break;
147                 }
148
149                 if (!required) {
150                         ret = -EINVAL;
151                         break;
152                 }
153
154                 ncycles = DIV_ROUND_UP(val, clk_period_ns);
155                 ret = xlate->converter(smcconf, xlate->shift, ncycles);
156                 if (ret)
157                         goto out;
158         }
159
160 out:
161         if (ret) {
162                 dev_err(ebid->ebi->dev,
163                         "missing or invalid timings definition in %pOF",
164                         np);
165                 return ret;
166         }
167
168         return required;
169 }
170
171 static int atmel_ebi_xslate_smc_config(struct atmel_ebi_dev *ebid,
172                                        struct device_node *np,
173                                        struct atmel_ebi_dev_config *conf)
174 {
175         struct atmel_smc_cs_conf *smcconf = &conf->smcconf;
176         bool required = false;
177         const char *tmp_str;
178         u32 tmp;
179         int ret;
180
181         ret = of_property_read_u32(np, "atmel,smc-bus-width", &tmp);
182         if (!ret) {
183                 switch (tmp) {
184                 case 8:
185                         smcconf->mode |= ATMEL_SMC_MODE_DBW_8;
186                         break;
187
188                 case 16:
189                         smcconf->mode |= ATMEL_SMC_MODE_DBW_16;
190                         break;
191
192                 case 32:
193                         smcconf->mode |= ATMEL_SMC_MODE_DBW_32;
194                         break;
195
196                 default:
197                         return -EINVAL;
198                 }
199
200                 required = true;
201         }
202
203         if (of_property_read_bool(np, "atmel,smc-tdf-optimized")) {
204                 smcconf->mode |= ATMEL_SMC_MODE_TDFMODE_OPTIMIZED;
205                 required = true;
206         }
207
208         tmp_str = NULL;
209         of_property_read_string(np, "atmel,smc-byte-access-type", &tmp_str);
210         if (tmp_str && !strcmp(tmp_str, "write")) {
211                 smcconf->mode |= ATMEL_SMC_MODE_BAT_WRITE;
212                 required = true;
213         }
214
215         tmp_str = NULL;
216         of_property_read_string(np, "atmel,smc-read-mode", &tmp_str);
217         if (tmp_str && !strcmp(tmp_str, "nrd")) {
218                 smcconf->mode |= ATMEL_SMC_MODE_READMODE_NRD;
219                 required = true;
220         }
221
222         tmp_str = NULL;
223         of_property_read_string(np, "atmel,smc-write-mode", &tmp_str);
224         if (tmp_str && !strcmp(tmp_str, "nwe")) {
225                 smcconf->mode |= ATMEL_SMC_MODE_WRITEMODE_NWE;
226                 required = true;
227         }
228
229         tmp_str = NULL;
230         of_property_read_string(np, "atmel,smc-exnw-mode", &tmp_str);
231         if (tmp_str) {
232                 if (!strcmp(tmp_str, "frozen"))
233                         smcconf->mode |= ATMEL_SMC_MODE_EXNWMODE_FROZEN;
234                 else if (!strcmp(tmp_str, "ready"))
235                         smcconf->mode |= ATMEL_SMC_MODE_EXNWMODE_READY;
236                 else if (strcmp(tmp_str, "disabled"))
237                         return -EINVAL;
238
239                 required = true;
240         }
241
242         ret = of_property_read_u32(np, "atmel,smc-page-mode", &tmp);
243         if (!ret) {
244                 switch (tmp) {
245                 case 4:
246                         smcconf->mode |= ATMEL_SMC_MODE_PS_4;
247                         break;
248
249                 case 8:
250                         smcconf->mode |= ATMEL_SMC_MODE_PS_8;
251                         break;
252
253                 case 16:
254                         smcconf->mode |= ATMEL_SMC_MODE_PS_16;
255                         break;
256
257                 case 32:
258                         smcconf->mode |= ATMEL_SMC_MODE_PS_32;
259                         break;
260
261                 default:
262                         return -EINVAL;
263                 }
264
265                 smcconf->mode |= ATMEL_SMC_MODE_PMEN;
266                 required = true;
267         }
268
269         ret = atmel_ebi_xslate_smc_timings(ebid, np, &conf->smcconf);
270         if (ret < 0)
271                 return -EINVAL;
272
273         if ((ret > 0 && !required) || (!ret && required)) {
274                 dev_err(ebid->ebi->dev, "missing atmel,smc- properties in %pOF",
275                         np);
276                 return -EINVAL;
277         }
278
279         return required;
280 }
281
282 static void at91sam9_ebi_apply_config(struct atmel_ebi_dev *ebid,
283                                       struct atmel_ebi_dev_config *conf)
284 {
285         atmel_smc_cs_conf_apply(ebid->ebi->smc.regmap, conf->cs,
286                                 &conf->smcconf);
287 }
288
289 static void sama5_ebi_apply_config(struct atmel_ebi_dev *ebid,
290                                    struct atmel_ebi_dev_config *conf)
291 {
292         atmel_hsmc_cs_conf_apply(ebid->ebi->smc.regmap, ebid->ebi->smc.layout,
293                                  conf->cs, &conf->smcconf);
294 }
295
296 static int atmel_ebi_dev_setup(struct atmel_ebi *ebi, struct device_node *np,
297                                int reg_cells)
298 {
299         const struct atmel_ebi_caps *caps = ebi->caps;
300         struct atmel_ebi_dev_config conf = { };
301         struct device *dev = ebi->dev;
302         struct atmel_ebi_dev *ebid;
303         unsigned long cslines = 0;
304         int ret, numcs = 0, nentries, i;
305         bool apply = false;
306         u32 cs;
307
308         nentries = of_property_count_elems_of_size(np, "reg",
309                                                    reg_cells * sizeof(u32));
310         for (i = 0; i < nentries; i++) {
311                 ret = of_property_read_u32_index(np, "reg", i * reg_cells,
312                                                  &cs);
313                 if (ret)
314                         return ret;
315
316                 if (cs >= AT91_EBI_NUM_CS ||
317                     !(ebi->caps->available_cs & BIT(cs))) {
318                         dev_err(dev, "invalid reg property in %pOF\n", np);
319                         return -EINVAL;
320                 }
321
322                 if (!test_and_set_bit(cs, &cslines))
323                         numcs++;
324         }
325
326         if (!numcs) {
327                 dev_err(dev, "invalid reg property in %pOF\n", np);
328                 return -EINVAL;
329         }
330
331         ebid = devm_kzalloc(ebi->dev, struct_size(ebid, configs, numcs),
332                             GFP_KERNEL);
333         if (!ebid)
334                 return -ENOMEM;
335
336         ebid->ebi = ebi;
337         ebid->numcs = numcs;
338
339         ret = caps->xlate_config(ebid, np, &conf);
340         if (ret < 0)
341                 return ret;
342         else if (ret)
343                 apply = true;
344
345         i = 0;
346         for_each_set_bit(cs, &cslines, AT91_EBI_NUM_CS) {
347                 ebid->configs[i].cs = cs;
348
349                 if (apply) {
350                         conf.cs = cs;
351                         caps->apply_config(ebid, &conf);
352                 }
353
354                 caps->get_config(ebid, &ebid->configs[i]);
355
356                 /*
357                  * Attach the EBI device to the generic SMC logic if at least
358                  * one "atmel,smc-" property is present.
359                  */
360                 if (ebi->caps->ebi_csa_offs && apply)
361                         regmap_update_bits(ebi->regmap,
362                                            ebi->caps->ebi_csa_offs,
363                                            BIT(cs), 0);
364
365                 i++;
366         }
367
368         list_add_tail(&ebid->node, &ebi->devs);
369
370         return 0;
371 }
372
373 static const struct atmel_ebi_caps at91sam9260_ebi_caps = {
374         .available_cs = 0xff,
375         .ebi_csa_offs = AT91SAM9260_MATRIX_EBICSA,
376         .regmap_name = "atmel,matrix",
377         .get_config = at91sam9_ebi_get_config,
378         .xlate_config = atmel_ebi_xslate_smc_config,
379         .apply_config = at91sam9_ebi_apply_config,
380 };
381
382 static const struct atmel_ebi_caps at91sam9261_ebi_caps = {
383         .available_cs = 0xff,
384         .ebi_csa_offs = AT91SAM9261_MATRIX_EBICSA,
385         .regmap_name = "atmel,matrix",
386         .get_config = at91sam9_ebi_get_config,
387         .xlate_config = atmel_ebi_xslate_smc_config,
388         .apply_config = at91sam9_ebi_apply_config,
389 };
390
391 static const struct atmel_ebi_caps at91sam9263_ebi0_caps = {
392         .available_cs = 0x3f,
393         .ebi_csa_offs = AT91SAM9263_MATRIX_EBI0CSA,
394         .regmap_name = "atmel,matrix",
395         .get_config = at91sam9_ebi_get_config,
396         .xlate_config = atmel_ebi_xslate_smc_config,
397         .apply_config = at91sam9_ebi_apply_config,
398 };
399
400 static const struct atmel_ebi_caps at91sam9263_ebi1_caps = {
401         .available_cs = 0x7,
402         .ebi_csa_offs = AT91SAM9263_MATRIX_EBI1CSA,
403         .regmap_name = "atmel,matrix",
404         .get_config = at91sam9_ebi_get_config,
405         .xlate_config = atmel_ebi_xslate_smc_config,
406         .apply_config = at91sam9_ebi_apply_config,
407 };
408
409 static const struct atmel_ebi_caps at91sam9rl_ebi_caps = {
410         .available_cs = 0x3f,
411         .ebi_csa_offs = AT91SAM9RL_MATRIX_EBICSA,
412         .regmap_name = "atmel,matrix",
413         .get_config = at91sam9_ebi_get_config,
414         .xlate_config = atmel_ebi_xslate_smc_config,
415         .apply_config = at91sam9_ebi_apply_config,
416 };
417
418 static const struct atmel_ebi_caps at91sam9g45_ebi_caps = {
419         .available_cs = 0x3f,
420         .ebi_csa_offs = AT91SAM9G45_MATRIX_EBICSA,
421         .regmap_name = "atmel,matrix",
422         .get_config = at91sam9_ebi_get_config,
423         .xlate_config = atmel_ebi_xslate_smc_config,
424         .apply_config = at91sam9_ebi_apply_config,
425 };
426
427 static const struct atmel_ebi_caps at91sam9x5_ebi_caps = {
428         .available_cs = 0x3f,
429         .ebi_csa_offs = AT91SAM9X5_MATRIX_EBICSA,
430         .regmap_name = "atmel,matrix",
431         .get_config = at91sam9_ebi_get_config,
432         .xlate_config = atmel_ebi_xslate_smc_config,
433         .apply_config = at91sam9_ebi_apply_config,
434 };
435
436 static const struct atmel_ebi_caps sama5d3_ebi_caps = {
437         .available_cs = 0xf,
438         .get_config = sama5_ebi_get_config,
439         .xlate_config = atmel_ebi_xslate_smc_config,
440         .apply_config = sama5_ebi_apply_config,
441 };
442
443 static const struct atmel_ebi_caps sam9x60_ebi_caps = {
444         .available_cs = 0x3f,
445         .ebi_csa_offs = AT91_SFR_CCFG_EBICSA,
446         .regmap_name = "microchip,sfr",
447         .get_config = at91sam9_ebi_get_config,
448         .xlate_config = atmel_ebi_xslate_smc_config,
449         .apply_config = at91sam9_ebi_apply_config,
450 };
451
452 static const struct of_device_id atmel_ebi_id_table[] = {
453         {
454                 .compatible = "atmel,at91sam9260-ebi",
455                 .data = &at91sam9260_ebi_caps,
456         },
457         {
458                 .compatible = "atmel,at91sam9261-ebi",
459                 .data = &at91sam9261_ebi_caps,
460         },
461         {
462                 .compatible = "atmel,at91sam9263-ebi0",
463                 .data = &at91sam9263_ebi0_caps,
464         },
465         {
466                 .compatible = "atmel,at91sam9263-ebi1",
467                 .data = &at91sam9263_ebi1_caps,
468         },
469         {
470                 .compatible = "atmel,at91sam9rl-ebi",
471                 .data = &at91sam9rl_ebi_caps,
472         },
473         {
474                 .compatible = "atmel,at91sam9g45-ebi",
475                 .data = &at91sam9g45_ebi_caps,
476         },
477         {
478                 .compatible = "atmel,at91sam9x5-ebi",
479                 .data = &at91sam9x5_ebi_caps,
480         },
481         {
482                 .compatible = "atmel,sama5d3-ebi",
483                 .data = &sama5d3_ebi_caps,
484         },
485         {
486                 .compatible = "microchip,sam9x60-ebi",
487                 .data = &sam9x60_ebi_caps,
488         },
489         { /* sentinel */ }
490 };
491
492 static int atmel_ebi_dev_disable(struct atmel_ebi *ebi, struct device_node *np)
493 {
494         struct device *dev = ebi->dev;
495         struct property *newprop;
496
497         newprop = devm_kzalloc(dev, sizeof(*newprop), GFP_KERNEL);
498         if (!newprop)
499                 return -ENOMEM;
500
501         newprop->name = devm_kstrdup(dev, "status", GFP_KERNEL);
502         if (!newprop->name)
503                 return -ENOMEM;
504
505         newprop->value = devm_kstrdup(dev, "disabled", GFP_KERNEL);
506         if (!newprop->value)
507                 return -ENOMEM;
508
509         newprop->length = sizeof("disabled");
510
511         return of_update_property(np, newprop);
512 }
513
514 static int atmel_ebi_probe(struct platform_device *pdev)
515 {
516         struct device *dev = &pdev->dev;
517         struct device_node *child, *np = dev->of_node, *smc_np;
518         const struct of_device_id *match;
519         struct atmel_ebi *ebi;
520         int ret, reg_cells;
521         struct clk *clk;
522         u32 val;
523
524         match = of_match_device(atmel_ebi_id_table, dev);
525         if (!match || !match->data)
526                 return -EINVAL;
527
528         ebi = devm_kzalloc(dev, sizeof(*ebi), GFP_KERNEL);
529         if (!ebi)
530                 return -ENOMEM;
531
532         platform_set_drvdata(pdev, ebi);
533
534         INIT_LIST_HEAD(&ebi->devs);
535         ebi->caps = match->data;
536         ebi->dev = dev;
537
538         clk = devm_clk_get(dev, NULL);
539         if (IS_ERR(clk))
540                 return PTR_ERR(clk);
541
542         ebi->clk = clk;
543
544         smc_np = of_parse_phandle(dev->of_node, "atmel,smc", 0);
545
546         ebi->smc.regmap = syscon_node_to_regmap(smc_np);
547         if (IS_ERR(ebi->smc.regmap))
548                 return PTR_ERR(ebi->smc.regmap);
549
550         ebi->smc.layout = atmel_hsmc_get_reg_layout(smc_np);
551         if (IS_ERR(ebi->smc.layout))
552                 return PTR_ERR(ebi->smc.layout);
553
554         ebi->smc.clk = of_clk_get(smc_np, 0);
555         if (IS_ERR(ebi->smc.clk)) {
556                 if (PTR_ERR(ebi->smc.clk) != -ENOENT)
557                         return PTR_ERR(ebi->smc.clk);
558
559                 ebi->smc.clk = NULL;
560         }
561         ret = clk_prepare_enable(ebi->smc.clk);
562         if (ret)
563                 return ret;
564
565         /*
566          * The sama5d3 does not provide an EBICSA register and thus does need
567          * to access it.
568          */
569         if (ebi->caps->ebi_csa_offs) {
570                 ebi->regmap =
571                         syscon_regmap_lookup_by_phandle(np,
572                                                         ebi->caps->regmap_name);
573                 if (IS_ERR(ebi->regmap))
574                         return PTR_ERR(ebi->regmap);
575         }
576
577         ret = of_property_read_u32(np, "#address-cells", &val);
578         if (ret) {
579                 dev_err(dev, "missing #address-cells property\n");
580                 return ret;
581         }
582
583         reg_cells = val;
584
585         ret = of_property_read_u32(np, "#size-cells", &val);
586         if (ret) {
587                 dev_err(dev, "missing #address-cells property\n");
588                 return ret;
589         }
590
591         reg_cells += val;
592
593         for_each_available_child_of_node(np, child) {
594                 if (!of_find_property(child, "reg", NULL))
595                         continue;
596
597                 ret = atmel_ebi_dev_setup(ebi, child, reg_cells);
598                 if (ret) {
599                         dev_err(dev, "failed to configure EBI bus for %pOF, disabling the device",
600                                 child);
601
602                         ret = atmel_ebi_dev_disable(ebi, child);
603                         if (ret) {
604                                 of_node_put(child);
605                                 return ret;
606                         }
607                 }
608         }
609
610         return of_platform_populate(np, NULL, NULL, dev);
611 }
612
613 static __maybe_unused int atmel_ebi_resume(struct device *dev)
614 {
615         struct atmel_ebi *ebi = dev_get_drvdata(dev);
616         struct atmel_ebi_dev *ebid;
617
618         list_for_each_entry(ebid, &ebi->devs, node) {
619                 int i;
620
621                 for (i = 0; i < ebid->numcs; i++)
622                         ebid->ebi->caps->apply_config(ebid, &ebid->configs[i]);
623         }
624
625         return 0;
626 }
627
628 static SIMPLE_DEV_PM_OPS(atmel_ebi_pm_ops, NULL, atmel_ebi_resume);
629
630 static struct platform_driver atmel_ebi_driver = {
631         .driver = {
632                 .name = "atmel-ebi",
633                 .of_match_table = atmel_ebi_id_table,
634                 .pm = &atmel_ebi_pm_ops,
635         },
636 };
637 builtin_platform_driver_probe(atmel_ebi_driver, atmel_ebi_probe);