Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'at91-ab-4.8-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux into next/drivers

Drivers for 4.8:
- Add a driver for the EBI

* tag 'at91-ab-4.8-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux:
memory: atmel-ebi: add DT bindings documentation
memory: add Atmel EBI (External Bus Interface) driver

Signed-off-by: Olof Johansson <olof@lixom.net>

+919
+136
Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
··· 1 + * Device tree bindings for Atmel EBI 2 + 3 + The External Bus Interface (EBI) controller is a bus where you can connect 4 + asynchronous (NAND, NOR, SRAM, ....) and synchronous memories (SDR/DDR SDRAMs). 5 + The EBI provides a glue-less interface to asynchronous memories through the SMC 6 + (Static Memory Controller). 7 + 8 + Required properties: 9 + 10 + - compatible: "atmel,at91sam9260-ebi" 11 + "atmel,at91sam9261-ebi" 12 + "atmel,at91sam9263-ebi0" 13 + "atmel,at91sam9263-ebi1" 14 + "atmel,at91sam9rl-ebi" 15 + "atmel,at91sam9g45-ebi" 16 + "atmel,at91sam9x5-ebi" 17 + "atmel,sama5d3-ebi" 18 + 19 + - reg: Contains offset/length value for EBI memory mapping. 20 + This property might contain several entries if the EBI 21 + memory range is not contiguous 22 + 23 + - #address-cells: Must be 2. 24 + The first cell encodes the CS. 25 + The second cell encode the offset into the CS memory 26 + range. 27 + 28 + - #size-cells: Must be set to 1. 29 + 30 + - ranges: Encodes CS to memory region association. 31 + 32 + - clocks: Clock feeding the EBI controller. 33 + See clock-bindings.txt 34 + 35 + Children device nodes are representing device connected to the EBI bus. 36 + 37 + Required device node properties: 38 + 39 + - reg: Contains the chip-select id, the offset and the length 40 + of the memory region requested by the device. 41 + 42 + EBI bus configuration will be defined directly in the device subnode. 43 + 44 + Optional EBI/SMC properties: 45 + 46 + - atmel,smc-bus-width: width of the asynchronous device's data bus 47 + 8, 16 or 32. 48 + Default to 8 when undefined. 49 + 50 + - atmel,smc-byte-access-type "write" or "select" (see Atmel datasheet). 51 + Default to "select" when undefined. 52 + 53 + - atmel,smc-read-mode "nrd" or "ncs". 54 + Default to "ncs" when undefined. 55 + 56 + - atmel,smc-write-mode "nwe" or "ncs". 57 + Default to "ncs" when undefined. 58 + 59 + - atmel,smc-exnw-mode "disabled", "frozen" or "ready". 60 + Default to "disabled" when undefined. 61 + 62 + - atmel,smc-page-mode enable page mode if present. The provided value 63 + defines the page size (supported values: 4, 8, 64 + 16 and 32). 65 + 66 + - atmel,smc-tdf-mode: "normal" or "optimized". When set to 67 + "optimized" the data float time is optimized 68 + depending on the next device being accessed 69 + (next device setup time is subtracted to the 70 + current device data float time). 71 + Default to "normal" when undefined. 72 + 73 + If at least one atmel,smc- property is defined the following SMC timing 74 + properties become mandatory. In the other hand, if none of the atmel,smc- 75 + properties are specified, we assume that the EBI bus configuration will be 76 + handled by the sub-device driver, and none of those properties should be 77 + defined. 78 + 79 + All the timings are expressed in nanoseconds (see Atmel datasheet for a full 80 + description). 81 + 82 + - atmel,smc-ncs-rd-setup-ns 83 + - atmel,smc-nrd-setup-ns 84 + - atmel,smc-ncs-wr-setup-ns 85 + - atmel,smc-nwe-setup-ns 86 + - atmel,smc-ncs-rd-pulse-ns 87 + - atmel,smc-nrd-pulse-ns 88 + - atmel,smc-ncs-wr-pulse-ns 89 + - atmel,smc-nwe-pulse-ns 90 + - atmel,smc-nwe-cycle-ns 91 + - atmel,smc-nrd-cycle-ns 92 + - atmel,smc-tdf-ns 93 + 94 + Example: 95 + 96 + ebi: ebi@10000000 { 97 + compatible = "atmel,sama5d3-ebi"; 98 + #address-cells = <2>; 99 + #size-cells = <1>; 100 + atmel,smc = <&hsmc>; 101 + atmel,matrix = <&matrix>; 102 + reg = <0x10000000 0x10000000 103 + 0x40000000 0x30000000>; 104 + ranges = <0x0 0x0 0x10000000 0x10000000 105 + 0x1 0x0 0x40000000 0x10000000 106 + 0x2 0x0 0x50000000 0x10000000 107 + 0x3 0x0 0x60000000 0x10000000>; 108 + clocks = <&mck>; 109 + 110 + pinctrl-names = "default"; 111 + pinctrl-0 = <&pinctrl_ebi_addr>; 112 + 113 + nor: flash@0,0 { 114 + compatible = "cfi-flash"; 115 + #address-cells = <1>; 116 + #size-cells = <1>; 117 + reg = <0x0 0x0 0x1000000>; 118 + bank-width = <2>; 119 + 120 + atmel,smc-read-mode = "nrd"; 121 + atmel,smc-write-mode = "nwe"; 122 + atmel,smc-bus-width = <16>; 123 + atmel,smc-ncs-rd-setup-ns = <0>; 124 + atmel,smc-ncs-wr-setup-ns = <0>; 125 + atmel,smc-nwe-setup-ns = <8>; 126 + atmel,smc-nrd-setup-ns = <16>; 127 + atmel,smc-ncs-rd-pulse-ns = <84>; 128 + atmel,smc-ncs-wr-pulse-ns = <84>; 129 + atmel,smc-nrd-pulse-ns = <76>; 130 + atmel,smc-nwe-pulse-ns = <76>; 131 + atmel,smc-nrd-cycle-ns = <107>; 132 + atmel,smc-nwe-cycle-ns = <84>; 133 + atmel,smc-tdf-ns = <16>; 134 + }; 135 + }; 136 +
+11
drivers/memory/Kconfig
··· 25 25 Starting with the at91sam9g45, this controller supports SDR, DDR and 26 26 LP-DDR memories. 27 27 28 + config ATMEL_EBI 29 + bool "Atmel EBI driver" 30 + default y 31 + depends on ARCH_AT91 && OF 32 + select MFD_SYSCON 33 + help 34 + Driver for Atmel EBI controller. 35 + Used to configure the EBI (external bus interface) when the device- 36 + tree is used. This bus supports NANDs, external ethernet controller, 37 + SRAMs, ATA devices, etc. 38 + 28 39 config TI_AEMIF 29 40 tristate "Texas Instruments AEMIF driver" 30 41 depends on (ARCH_DAVINCI || ARCH_KEYSTONE) && OF
+1
drivers/memory/Makefile
··· 7 7 endif 8 8 obj-$(CONFIG_ARM_PL172_MPMC) += pl172.o 9 9 obj-$(CONFIG_ATMEL_SDRAMC) += atmel-sdramc.o 10 + obj-$(CONFIG_ATMEL_EBI) += atmel-ebi.o 10 11 obj-$(CONFIG_TI_AEMIF) += ti-aemif.o 11 12 obj-$(CONFIG_TI_EMIF) += emif.o 12 13 obj-$(CONFIG_OMAP_GPMC) += omap-gpmc.o
+771
drivers/memory/atmel-ebi.c
··· 1 + /* 2 + * EBI driver for Atmel chips 3 + * inspired by the fsl weim bus driver 4 + * 5 + * Copyright (C) 2013 Jean-Jacques Hiblot <jjhiblot@traphandler.com> 6 + * 7 + * This file is licensed under the terms of the GNU General Public 8 + * License version 2. This program is licensed "as is" without any 9 + * warranty of any kind, whether express or implied. 10 + */ 11 + 12 + #include <linux/clk.h> 13 + #include <linux/io.h> 14 + #include <linux/mfd/syscon.h> 15 + #include <linux/mfd/syscon/atmel-matrix.h> 16 + #include <linux/mfd/syscon/atmel-smc.h> 17 + #include <linux/module.h> 18 + #include <linux/of_device.h> 19 + #include <linux/regmap.h> 20 + 21 + struct at91sam9_smc_timings { 22 + u32 ncs_rd_setup_ns; 23 + u32 nrd_setup_ns; 24 + u32 ncs_wr_setup_ns; 25 + u32 nwe_setup_ns; 26 + u32 ncs_rd_pulse_ns; 27 + u32 nrd_pulse_ns; 28 + u32 ncs_wr_pulse_ns; 29 + u32 nwe_pulse_ns; 30 + u32 nrd_cycle_ns; 31 + u32 nwe_cycle_ns; 32 + u32 tdf_ns; 33 + }; 34 + 35 + struct at91sam9_smc_generic_fields { 36 + struct regmap_field *setup; 37 + struct regmap_field *pulse; 38 + struct regmap_field *cycle; 39 + struct regmap_field *mode; 40 + }; 41 + 42 + struct at91sam9_ebi_dev_config { 43 + struct at91sam9_smc_timings timings; 44 + u32 mode; 45 + }; 46 + 47 + struct at91_ebi_dev_config { 48 + int cs; 49 + union { 50 + struct at91sam9_ebi_dev_config sam9; 51 + }; 52 + }; 53 + 54 + struct at91_ebi; 55 + 56 + struct at91_ebi_dev { 57 + struct list_head node; 58 + struct at91_ebi *ebi; 59 + u32 mode; 60 + int numcs; 61 + struct at91_ebi_dev_config configs[]; 62 + }; 63 + 64 + struct at91_ebi_caps { 65 + unsigned int available_cs; 66 + const struct reg_field *ebi_csa; 67 + void (*get_config)(struct at91_ebi_dev *ebid, 68 + struct at91_ebi_dev_config *conf); 69 + int (*xlate_config)(struct at91_ebi_dev *ebid, 70 + struct device_node *configs_np, 71 + struct at91_ebi_dev_config *conf); 72 + int (*apply_config)(struct at91_ebi_dev *ebid, 73 + struct at91_ebi_dev_config *conf); 74 + int (*init)(struct at91_ebi *ebi); 75 + }; 76 + 77 + struct at91_ebi { 78 + struct clk *clk; 79 + struct regmap *smc; 80 + struct regmap *matrix; 81 + 82 + struct regmap_field *ebi_csa; 83 + 84 + struct device *dev; 85 + const struct at91_ebi_caps *caps; 86 + struct list_head devs; 87 + union { 88 + struct at91sam9_smc_generic_fields sam9; 89 + }; 90 + }; 91 + 92 + static void at91sam9_ebi_get_config(struct at91_ebi_dev *ebid, 93 + struct at91_ebi_dev_config *conf) 94 + { 95 + struct at91sam9_smc_generic_fields *fields = &ebid->ebi->sam9; 96 + unsigned int clk_rate = clk_get_rate(ebid->ebi->clk); 97 + struct at91sam9_ebi_dev_config *config = &conf->sam9; 98 + struct at91sam9_smc_timings *timings = &config->timings; 99 + unsigned int val; 100 + 101 + regmap_fields_read(fields->mode, conf->cs, &val); 102 + config->mode = val & ~AT91_SMC_TDF; 103 + 104 + val = (val & AT91_SMC_TDF) >> 16; 105 + timings->tdf_ns = clk_rate * val; 106 + 107 + regmap_fields_read(fields->setup, conf->cs, &val); 108 + timings->ncs_rd_setup_ns = (val >> 24) & 0x1f; 109 + timings->ncs_rd_setup_ns += ((val >> 29) & 0x1) * 128; 110 + timings->ncs_rd_setup_ns *= clk_rate; 111 + timings->nrd_setup_ns = (val >> 16) & 0x1f; 112 + timings->nrd_setup_ns += ((val >> 21) & 0x1) * 128; 113 + timings->nrd_setup_ns *= clk_rate; 114 + timings->ncs_wr_setup_ns = (val >> 8) & 0x1f; 115 + timings->ncs_wr_setup_ns += ((val >> 13) & 0x1) * 128; 116 + timings->ncs_wr_setup_ns *= clk_rate; 117 + timings->nwe_setup_ns = val & 0x1f; 118 + timings->nwe_setup_ns += ((val >> 5) & 0x1) * 128; 119 + timings->nwe_setup_ns *= clk_rate; 120 + 121 + regmap_fields_read(fields->pulse, conf->cs, &val); 122 + timings->ncs_rd_pulse_ns = (val >> 24) & 0x3f; 123 + timings->ncs_rd_pulse_ns += ((val >> 30) & 0x1) * 256; 124 + timings->ncs_rd_pulse_ns *= clk_rate; 125 + timings->nrd_pulse_ns = (val >> 16) & 0x3f; 126 + timings->nrd_pulse_ns += ((val >> 22) & 0x1) * 256; 127 + timings->nrd_pulse_ns *= clk_rate; 128 + timings->ncs_wr_pulse_ns = (val >> 8) & 0x3f; 129 + timings->ncs_wr_pulse_ns += ((val >> 14) & 0x1) * 256; 130 + timings->ncs_wr_pulse_ns *= clk_rate; 131 + timings->nwe_pulse_ns = val & 0x3f; 132 + timings->nwe_pulse_ns += ((val >> 6) & 0x1) * 256; 133 + timings->nwe_pulse_ns *= clk_rate; 134 + 135 + regmap_fields_read(fields->cycle, conf->cs, &val); 136 + timings->nrd_cycle_ns = (val >> 16) & 0x7f; 137 + timings->nrd_cycle_ns += ((val >> 23) & 0x3) * 256; 138 + timings->nrd_cycle_ns *= clk_rate; 139 + timings->nwe_cycle_ns = val & 0x7f; 140 + timings->nwe_cycle_ns += ((val >> 7) & 0x3) * 256; 141 + timings->nwe_cycle_ns *= clk_rate; 142 + } 143 + 144 + static int at91_xlate_timing(struct device_node *np, const char *prop, 145 + u32 *val, bool *required) 146 + { 147 + if (!of_property_read_u32(np, prop, val)) { 148 + *required = true; 149 + return 0; 150 + } 151 + 152 + if (*required) 153 + return -EINVAL; 154 + 155 + return 0; 156 + } 157 + 158 + static int at91sam9_smc_xslate_timings(struct at91_ebi_dev *ebid, 159 + struct device_node *np, 160 + struct at91sam9_smc_timings *timings, 161 + bool *required) 162 + { 163 + int ret; 164 + 165 + ret = at91_xlate_timing(np, "atmel,smc-ncs-rd-setup-ns", 166 + &timings->ncs_rd_setup_ns, required); 167 + if (ret) 168 + goto out; 169 + 170 + ret = at91_xlate_timing(np, "atmel,smc-nrd-setup-ns", 171 + &timings->nrd_setup_ns, required); 172 + if (ret) 173 + goto out; 174 + 175 + ret = at91_xlate_timing(np, "atmel,smc-ncs-wr-setup-ns", 176 + &timings->ncs_wr_setup_ns, required); 177 + if (ret) 178 + goto out; 179 + 180 + ret = at91_xlate_timing(np, "atmel,smc-nwe-setup-ns", 181 + &timings->nwe_setup_ns, required); 182 + if (ret) 183 + goto out; 184 + 185 + ret = at91_xlate_timing(np, "atmel,smc-ncs-rd-pulse-ns", 186 + &timings->ncs_rd_pulse_ns, required); 187 + if (ret) 188 + goto out; 189 + 190 + ret = at91_xlate_timing(np, "atmel,smc-nrd-pulse-ns", 191 + &timings->nrd_pulse_ns, required); 192 + if (ret) 193 + goto out; 194 + 195 + ret = at91_xlate_timing(np, "atmel,smc-ncs-wr-pulse-ns", 196 + &timings->ncs_wr_pulse_ns, required); 197 + if (ret) 198 + goto out; 199 + 200 + ret = at91_xlate_timing(np, "atmel,smc-nwe-pulse-ns", 201 + &timings->nwe_pulse_ns, required); 202 + if (ret) 203 + goto out; 204 + 205 + ret = at91_xlate_timing(np, "atmel,smc-nwe-cycle-ns", 206 + &timings->nwe_cycle_ns, required); 207 + if (ret) 208 + goto out; 209 + 210 + ret = at91_xlate_timing(np, "atmel,smc-nrd-cycle-ns", 211 + &timings->nrd_cycle_ns, required); 212 + if (ret) 213 + goto out; 214 + 215 + ret = at91_xlate_timing(np, "atmel,smc-tdf-ns", 216 + &timings->tdf_ns, required); 217 + 218 + out: 219 + if (ret) 220 + dev_err(ebid->ebi->dev, 221 + "missing or invalid timings definition in %s", 222 + np->full_name); 223 + 224 + return ret; 225 + } 226 + 227 + static int at91sam9_ebi_xslate_config(struct at91_ebi_dev *ebid, 228 + struct device_node *np, 229 + struct at91_ebi_dev_config *conf) 230 + { 231 + struct at91sam9_ebi_dev_config *config = &conf->sam9; 232 + bool required = false; 233 + const char *tmp_str; 234 + u32 tmp; 235 + int ret; 236 + 237 + ret = of_property_read_u32(np, "atmel,smc-bus-width", &tmp); 238 + if (!ret) { 239 + switch (tmp) { 240 + case 8: 241 + config->mode |= AT91_SMC_DBW_8; 242 + break; 243 + 244 + case 16: 245 + config->mode |= AT91_SMC_DBW_16; 246 + break; 247 + 248 + case 32: 249 + config->mode |= AT91_SMC_DBW_32; 250 + break; 251 + 252 + default: 253 + return -EINVAL; 254 + } 255 + 256 + required = true; 257 + } 258 + 259 + if (of_property_read_bool(np, "atmel,smc-tdf-optimized")) { 260 + config->mode |= AT91_SMC_TDFMODE_OPTIMIZED; 261 + required = true; 262 + } 263 + 264 + tmp_str = NULL; 265 + of_property_read_string(np, "atmel,smc-byte-access-type", &tmp_str); 266 + if (tmp_str && !strcmp(tmp_str, "write")) { 267 + config->mode |= AT91_SMC_BAT_WRITE; 268 + required = true; 269 + } 270 + 271 + tmp_str = NULL; 272 + of_property_read_string(np, "atmel,smc-read-mode", &tmp_str); 273 + if (tmp_str && !strcmp(tmp_str, "nrd")) { 274 + config->mode |= AT91_SMC_READMODE_NRD; 275 + required = true; 276 + } 277 + 278 + tmp_str = NULL; 279 + of_property_read_string(np, "atmel,smc-write-mode", &tmp_str); 280 + if (tmp_str && !strcmp(tmp_str, "nwe")) { 281 + config->mode |= AT91_SMC_WRITEMODE_NWE; 282 + required = true; 283 + } 284 + 285 + tmp_str = NULL; 286 + of_property_read_string(np, "atmel,smc-exnw-mode", &tmp_str); 287 + if (tmp_str) { 288 + if (!strcmp(tmp_str, "frozen")) 289 + config->mode |= AT91_SMC_EXNWMODE_FROZEN; 290 + else if (!strcmp(tmp_str, "ready")) 291 + config->mode |= AT91_SMC_EXNWMODE_READY; 292 + else if (strcmp(tmp_str, "disabled")) 293 + return -EINVAL; 294 + 295 + required = true; 296 + } 297 + 298 + ret = of_property_read_u32(np, "atmel,smc-page-mode", &tmp); 299 + if (!ret) { 300 + switch (tmp) { 301 + case 4: 302 + config->mode |= AT91_SMC_PS_4; 303 + break; 304 + 305 + case 8: 306 + config->mode |= AT91_SMC_PS_8; 307 + break; 308 + 309 + case 16: 310 + config->mode |= AT91_SMC_PS_16; 311 + break; 312 + 313 + case 32: 314 + config->mode |= AT91_SMC_PS_32; 315 + break; 316 + 317 + default: 318 + return -EINVAL; 319 + } 320 + 321 + config->mode |= AT91_SMC_PMEN; 322 + required = true; 323 + } 324 + 325 + ret = at91sam9_smc_xslate_timings(ebid, np, &config->timings, 326 + &required); 327 + if (ret) 328 + return ret; 329 + 330 + return required; 331 + } 332 + 333 + static int at91sam9_ebi_apply_config(struct at91_ebi_dev *ebid, 334 + struct at91_ebi_dev_config *conf) 335 + { 336 + unsigned int clk_rate = clk_get_rate(ebid->ebi->clk); 337 + struct at91sam9_ebi_dev_config *config = &conf->sam9; 338 + struct at91sam9_smc_timings *timings = &config->timings; 339 + struct at91sam9_smc_generic_fields *fields = &ebid->ebi->sam9; 340 + u32 coded_val; 341 + u32 val; 342 + 343 + coded_val = at91sam9_smc_setup_ns_to_cycles(clk_rate, 344 + timings->ncs_rd_setup_ns); 345 + val = AT91SAM9_SMC_NCS_NRDSETUP(coded_val); 346 + coded_val = at91sam9_smc_setup_ns_to_cycles(clk_rate, 347 + timings->nrd_setup_ns); 348 + val |= AT91SAM9_SMC_NRDSETUP(coded_val); 349 + coded_val = at91sam9_smc_setup_ns_to_cycles(clk_rate, 350 + timings->ncs_wr_setup_ns); 351 + val |= AT91SAM9_SMC_NCS_WRSETUP(coded_val); 352 + coded_val = at91sam9_smc_setup_ns_to_cycles(clk_rate, 353 + timings->nwe_setup_ns); 354 + val |= AT91SAM9_SMC_NWESETUP(coded_val); 355 + regmap_fields_write(fields->setup, conf->cs, val); 356 + 357 + coded_val = at91sam9_smc_pulse_ns_to_cycles(clk_rate, 358 + timings->ncs_rd_pulse_ns); 359 + val = AT91SAM9_SMC_NCS_NRDPULSE(coded_val); 360 + coded_val = at91sam9_smc_pulse_ns_to_cycles(clk_rate, 361 + timings->nrd_pulse_ns); 362 + val |= AT91SAM9_SMC_NRDPULSE(coded_val); 363 + coded_val = at91sam9_smc_pulse_ns_to_cycles(clk_rate, 364 + timings->ncs_wr_pulse_ns); 365 + val |= AT91SAM9_SMC_NCS_WRPULSE(coded_val); 366 + coded_val = at91sam9_smc_pulse_ns_to_cycles(clk_rate, 367 + timings->nwe_pulse_ns); 368 + val |= AT91SAM9_SMC_NWEPULSE(coded_val); 369 + regmap_fields_write(fields->pulse, conf->cs, val); 370 + 371 + coded_val = at91sam9_smc_cycle_ns_to_cycles(clk_rate, 372 + timings->nrd_cycle_ns); 373 + val = AT91SAM9_SMC_NRDCYCLE(coded_val); 374 + coded_val = at91sam9_smc_cycle_ns_to_cycles(clk_rate, 375 + timings->nwe_cycle_ns); 376 + val |= AT91SAM9_SMC_NWECYCLE(coded_val); 377 + regmap_fields_write(fields->cycle, conf->cs, val); 378 + 379 + val = DIV_ROUND_UP(timings->tdf_ns, clk_rate); 380 + if (val > AT91_SMC_TDF_MAX) 381 + val = AT91_SMC_TDF_MAX; 382 + regmap_fields_write(fields->mode, conf->cs, 383 + config->mode | AT91_SMC_TDF_(val)); 384 + 385 + return 0; 386 + } 387 + 388 + static int at91sam9_ebi_init(struct at91_ebi *ebi) 389 + { 390 + struct at91sam9_smc_generic_fields *fields = &ebi->sam9; 391 + struct reg_field field = REG_FIELD(0, 0, 31); 392 + 393 + field.id_size = fls(ebi->caps->available_cs); 394 + field.id_offset = AT91SAM9_SMC_GENERIC_BLK_SZ; 395 + 396 + field.reg = AT91SAM9_SMC_SETUP(AT91SAM9_SMC_GENERIC); 397 + fields->setup = devm_regmap_field_alloc(ebi->dev, ebi->smc, field); 398 + if (IS_ERR(fields->setup)) 399 + return PTR_ERR(fields->setup); 400 + 401 + field.reg = AT91SAM9_SMC_PULSE(AT91SAM9_SMC_GENERIC); 402 + fields->pulse = devm_regmap_field_alloc(ebi->dev, ebi->smc, field); 403 + if (IS_ERR(fields->pulse)) 404 + return PTR_ERR(fields->pulse); 405 + 406 + field.reg = AT91SAM9_SMC_CYCLE(AT91SAM9_SMC_GENERIC); 407 + fields->cycle = devm_regmap_field_alloc(ebi->dev, ebi->smc, field); 408 + if (IS_ERR(fields->cycle)) 409 + return PTR_ERR(fields->cycle); 410 + 411 + field.reg = AT91SAM9_SMC_MODE(AT91SAM9_SMC_GENERIC); 412 + fields->mode = devm_regmap_field_alloc(ebi->dev, ebi->smc, field); 413 + if (IS_ERR(fields->mode)) 414 + return PTR_ERR(fields->mode); 415 + 416 + return 0; 417 + } 418 + 419 + static int sama5d3_ebi_init(struct at91_ebi *ebi) 420 + { 421 + struct at91sam9_smc_generic_fields *fields = &ebi->sam9; 422 + struct reg_field field = REG_FIELD(0, 0, 31); 423 + 424 + field.id_size = fls(ebi->caps->available_cs); 425 + field.id_offset = SAMA5_SMC_GENERIC_BLK_SZ; 426 + 427 + field.reg = AT91SAM9_SMC_SETUP(SAMA5_SMC_GENERIC); 428 + fields->setup = devm_regmap_field_alloc(ebi->dev, ebi->smc, field); 429 + if (IS_ERR(fields->setup)) 430 + return PTR_ERR(fields->setup); 431 + 432 + field.reg = AT91SAM9_SMC_PULSE(SAMA5_SMC_GENERIC); 433 + fields->pulse = devm_regmap_field_alloc(ebi->dev, ebi->smc, field); 434 + if (IS_ERR(fields->pulse)) 435 + return PTR_ERR(fields->pulse); 436 + 437 + field.reg = AT91SAM9_SMC_CYCLE(SAMA5_SMC_GENERIC); 438 + fields->cycle = devm_regmap_field_alloc(ebi->dev, ebi->smc, field); 439 + if (IS_ERR(fields->cycle)) 440 + return PTR_ERR(fields->cycle); 441 + 442 + field.reg = SAMA5_SMC_MODE(SAMA5_SMC_GENERIC); 443 + fields->mode = devm_regmap_field_alloc(ebi->dev, ebi->smc, field); 444 + if (IS_ERR(fields->mode)) 445 + return PTR_ERR(fields->mode); 446 + 447 + return 0; 448 + } 449 + 450 + static int at91_ebi_dev_setup(struct at91_ebi *ebi, struct device_node *np, 451 + int reg_cells) 452 + { 453 + const struct at91_ebi_caps *caps = ebi->caps; 454 + struct at91_ebi_dev_config conf = { }; 455 + struct device *dev = ebi->dev; 456 + struct at91_ebi_dev *ebid; 457 + int ret, numcs = 0, i; 458 + bool apply = false; 459 + 460 + numcs = of_property_count_elems_of_size(np, "reg", 461 + reg_cells * sizeof(u32)); 462 + if (numcs <= 0) { 463 + dev_err(dev, "invalid reg property in %s\n", np->full_name); 464 + return -EINVAL; 465 + } 466 + 467 + ebid = devm_kzalloc(ebi->dev, 468 + sizeof(*ebid) + (numcs * sizeof(*ebid->configs)), 469 + GFP_KERNEL); 470 + if (!ebid) 471 + return -ENOMEM; 472 + 473 + ebid->ebi = ebi; 474 + 475 + ret = caps->xlate_config(ebid, np, &conf); 476 + if (ret < 0) 477 + return ret; 478 + else if (ret) 479 + apply = true; 480 + 481 + for (i = 0; i < numcs; i++) { 482 + u32 cs; 483 + 484 + ret = of_property_read_u32_index(np, "reg", i * reg_cells, 485 + &cs); 486 + if (ret) 487 + return ret; 488 + 489 + if (cs > AT91_MATRIX_EBI_NUM_CS || 490 + !(ebi->caps->available_cs & BIT(cs))) { 491 + dev_err(dev, "invalid reg property in %s\n", 492 + np->full_name); 493 + return -EINVAL; 494 + } 495 + 496 + ebid->configs[i].cs = cs; 497 + 498 + if (apply) { 499 + conf.cs = cs; 500 + ret = caps->apply_config(ebid, &conf); 501 + if (ret) 502 + return ret; 503 + } 504 + 505 + caps->get_config(ebid, &ebid->configs[i]); 506 + 507 + /* 508 + * Attach the EBI device to the generic SMC logic if at least 509 + * one "atmel,smc-" property is present. 510 + */ 511 + if (ebi->ebi_csa && ret) 512 + regmap_field_update_bits(ebi->ebi_csa, 513 + BIT(cs), 0); 514 + } 515 + 516 + list_add_tail(&ebid->node, &ebi->devs); 517 + 518 + return 0; 519 + } 520 + 521 + static const struct reg_field at91sam9260_ebi_csa = 522 + REG_FIELD(AT91SAM9260_MATRIX_EBICSA, 0, 523 + AT91_MATRIX_EBI_NUM_CS - 1); 524 + 525 + static const struct at91_ebi_caps at91sam9260_ebi_caps = { 526 + .available_cs = 0xff, 527 + .ebi_csa = &at91sam9260_ebi_csa, 528 + .get_config = at91sam9_ebi_get_config, 529 + .xlate_config = at91sam9_ebi_xslate_config, 530 + .apply_config = at91sam9_ebi_apply_config, 531 + .init = at91sam9_ebi_init, 532 + }; 533 + 534 + static const struct reg_field at91sam9261_ebi_csa = 535 + REG_FIELD(AT91SAM9261_MATRIX_EBICSA, 0, 536 + AT91_MATRIX_EBI_NUM_CS - 1); 537 + 538 + static const struct at91_ebi_caps at91sam9261_ebi_caps = { 539 + .available_cs = 0xff, 540 + .ebi_csa = &at91sam9261_ebi_csa, 541 + .get_config = at91sam9_ebi_get_config, 542 + .xlate_config = at91sam9_ebi_xslate_config, 543 + .apply_config = at91sam9_ebi_apply_config, 544 + .init = at91sam9_ebi_init, 545 + }; 546 + 547 + static const struct reg_field at91sam9263_ebi0_csa = 548 + REG_FIELD(AT91SAM9263_MATRIX_EBI0CSA, 0, 549 + AT91_MATRIX_EBI_NUM_CS - 1); 550 + 551 + static const struct at91_ebi_caps at91sam9263_ebi0_caps = { 552 + .available_cs = 0x3f, 553 + .ebi_csa = &at91sam9263_ebi0_csa, 554 + .get_config = at91sam9_ebi_get_config, 555 + .xlate_config = at91sam9_ebi_xslate_config, 556 + .apply_config = at91sam9_ebi_apply_config, 557 + .init = at91sam9_ebi_init, 558 + }; 559 + 560 + static const struct reg_field at91sam9263_ebi1_csa = 561 + REG_FIELD(AT91SAM9263_MATRIX_EBI1CSA, 0, 562 + AT91_MATRIX_EBI_NUM_CS - 1); 563 + 564 + static const struct at91_ebi_caps at91sam9263_ebi1_caps = { 565 + .available_cs = 0x7, 566 + .ebi_csa = &at91sam9263_ebi1_csa, 567 + .get_config = at91sam9_ebi_get_config, 568 + .xlate_config = at91sam9_ebi_xslate_config, 569 + .apply_config = at91sam9_ebi_apply_config, 570 + .init = at91sam9_ebi_init, 571 + }; 572 + 573 + static const struct reg_field at91sam9rl_ebi_csa = 574 + REG_FIELD(AT91SAM9RL_MATRIX_EBICSA, 0, 575 + AT91_MATRIX_EBI_NUM_CS - 1); 576 + 577 + static const struct at91_ebi_caps at91sam9rl_ebi_caps = { 578 + .available_cs = 0x3f, 579 + .ebi_csa = &at91sam9rl_ebi_csa, 580 + .get_config = at91sam9_ebi_get_config, 581 + .xlate_config = at91sam9_ebi_xslate_config, 582 + .apply_config = at91sam9_ebi_apply_config, 583 + .init = at91sam9_ebi_init, 584 + }; 585 + 586 + static const struct reg_field at91sam9g45_ebi_csa = 587 + REG_FIELD(AT91SAM9G45_MATRIX_EBICSA, 0, 588 + AT91_MATRIX_EBI_NUM_CS - 1); 589 + 590 + static const struct at91_ebi_caps at91sam9g45_ebi_caps = { 591 + .available_cs = 0x3f, 592 + .ebi_csa = &at91sam9g45_ebi_csa, 593 + .get_config = at91sam9_ebi_get_config, 594 + .xlate_config = at91sam9_ebi_xslate_config, 595 + .apply_config = at91sam9_ebi_apply_config, 596 + .init = at91sam9_ebi_init, 597 + }; 598 + 599 + static const struct at91_ebi_caps at91sam9x5_ebi_caps = { 600 + .available_cs = 0x3f, 601 + .ebi_csa = &at91sam9263_ebi0_csa, 602 + .get_config = at91sam9_ebi_get_config, 603 + .xlate_config = at91sam9_ebi_xslate_config, 604 + .apply_config = at91sam9_ebi_apply_config, 605 + .init = at91sam9_ebi_init, 606 + }; 607 + 608 + static const struct at91_ebi_caps sama5d3_ebi_caps = { 609 + .available_cs = 0xf, 610 + .get_config = at91sam9_ebi_get_config, 611 + .xlate_config = at91sam9_ebi_xslate_config, 612 + .apply_config = at91sam9_ebi_apply_config, 613 + .init = sama5d3_ebi_init, 614 + }; 615 + 616 + static const struct of_device_id at91_ebi_id_table[] = { 617 + { 618 + .compatible = "atmel,at91sam9260-ebi", 619 + .data = &at91sam9260_ebi_caps, 620 + }, 621 + { 622 + .compatible = "atmel,at91sam9261-ebi", 623 + .data = &at91sam9261_ebi_caps, 624 + }, 625 + { 626 + .compatible = "atmel,at91sam9263-ebi0", 627 + .data = &at91sam9263_ebi0_caps, 628 + }, 629 + { 630 + .compatible = "atmel,at91sam9263-ebi1", 631 + .data = &at91sam9263_ebi1_caps, 632 + }, 633 + { 634 + .compatible = "atmel,at91sam9rl-ebi", 635 + .data = &at91sam9rl_ebi_caps, 636 + }, 637 + { 638 + .compatible = "atmel,at91sam9g45-ebi", 639 + .data = &at91sam9g45_ebi_caps, 640 + }, 641 + { 642 + .compatible = "atmel,at91sam9x5-ebi", 643 + .data = &at91sam9x5_ebi_caps, 644 + }, 645 + { 646 + .compatible = "atmel,sama5d3-ebi", 647 + .data = &sama5d3_ebi_caps, 648 + }, 649 + { /* sentinel */ } 650 + }; 651 + MODULE_DEVICE_TABLE(of, at91_ebi_id_table); 652 + 653 + static int at91_ebi_dev_disable(struct at91_ebi *ebi, struct device_node *np) 654 + { 655 + struct device *dev = ebi->dev; 656 + struct property *newprop; 657 + 658 + newprop = devm_kzalloc(dev, sizeof(*newprop), GFP_KERNEL); 659 + if (!newprop) 660 + return -ENOMEM; 661 + 662 + newprop->name = devm_kstrdup(dev, "status", GFP_KERNEL); 663 + if (!newprop->name) 664 + return -ENOMEM; 665 + 666 + newprop->value = devm_kstrdup(dev, "disabled", GFP_KERNEL); 667 + if (!newprop->name) 668 + return -ENOMEM; 669 + 670 + newprop->length = sizeof("disabled"); 671 + 672 + return of_update_property(np, newprop); 673 + } 674 + 675 + static int at91_ebi_probe(struct platform_device *pdev) 676 + { 677 + struct device *dev = &pdev->dev; 678 + struct device_node *child, *np = dev->of_node; 679 + const struct of_device_id *match; 680 + struct at91_ebi *ebi; 681 + int ret, reg_cells; 682 + struct clk *clk; 683 + u32 val; 684 + 685 + match = of_match_device(at91_ebi_id_table, dev); 686 + if (!match || !match->data) 687 + return -EINVAL; 688 + 689 + ebi = devm_kzalloc(dev, sizeof(*ebi), GFP_KERNEL); 690 + if (!ebi) 691 + return -ENOMEM; 692 + 693 + INIT_LIST_HEAD(&ebi->devs); 694 + ebi->caps = match->data; 695 + ebi->dev = dev; 696 + 697 + clk = devm_clk_get(dev, NULL); 698 + if (IS_ERR(clk)) 699 + return PTR_ERR(clk); 700 + 701 + ebi->clk = clk; 702 + 703 + ebi->smc = syscon_regmap_lookup_by_phandle(np, "atmel,smc"); 704 + if (IS_ERR(ebi->smc)) 705 + return PTR_ERR(ebi->smc); 706 + 707 + /* 708 + * The sama5d3 does not provide an EBICSA register and thus does need 709 + * to access the matrix registers. 710 + */ 711 + if (ebi->caps->ebi_csa) { 712 + ebi->matrix = 713 + syscon_regmap_lookup_by_phandle(np, "atmel,matrix"); 714 + if (IS_ERR(ebi->matrix)) 715 + return PTR_ERR(ebi->matrix); 716 + 717 + ebi->ebi_csa = regmap_field_alloc(ebi->matrix, 718 + *ebi->caps->ebi_csa); 719 + if (IS_ERR(ebi->ebi_csa)) 720 + return PTR_ERR(ebi->ebi_csa); 721 + } 722 + 723 + ret = ebi->caps->init(ebi); 724 + if (ret) 725 + return ret; 726 + 727 + ret = of_property_read_u32(np, "#address-cells", &val); 728 + if (ret) { 729 + dev_err(dev, "missing #address-cells property\n"); 730 + return ret; 731 + } 732 + 733 + reg_cells = val; 734 + 735 + ret = of_property_read_u32(np, "#size-cells", &val); 736 + if (ret) { 737 + dev_err(dev, "missing #address-cells property\n"); 738 + return ret; 739 + } 740 + 741 + reg_cells += val; 742 + 743 + for_each_available_child_of_node(np, child) { 744 + if (!of_find_property(child, "reg", NULL)) 745 + continue; 746 + 747 + ret = at91_ebi_dev_setup(ebi, child, reg_cells); 748 + if (ret) { 749 + dev_err(dev, "failed to configure EBI bus for %s, disabling the device", 750 + child->full_name); 751 + 752 + ret = at91_ebi_dev_disable(ebi, child); 753 + if (ret) 754 + return ret; 755 + } 756 + } 757 + 758 + return of_platform_populate(np, NULL, NULL, dev); 759 + } 760 + 761 + static struct platform_driver at91_ebi_driver = { 762 + .driver = { 763 + .name = "atmel-ebi", 764 + .of_match_table = at91_ebi_id_table, 765 + }, 766 + }; 767 + module_platform_driver_probe(at91_ebi_driver, at91_ebi_probe); 768 + 769 + MODULE_AUTHOR("Jean-Jacques Hiblot <jjhiblot@traphandler.com>"); 770 + MODULE_DESCRIPTION("Atmel EBI driver"); 771 + MODULE_LICENSE("GPL");