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