cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

atmel-ebi.c (15677B)


      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
     21struct atmel_ebi_dev_config {
     22	int cs;
     23	struct atmel_smc_cs_conf smcconf;
     24};
     25
     26struct atmel_ebi;
     27
     28struct 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
     36struct 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
     49struct 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
     63struct 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
     79static 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
     86static 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
     93static 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
    110static 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
    160out:
    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
    171static 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
    282static 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
    289static 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
    296static 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
    373static 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
    382static 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
    391static 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
    400static 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
    409static 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
    418static 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
    427static 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
    436static 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
    443static 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
    452static 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
    492static 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
    514static 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		ret = PTR_ERR(ebi->smc.regmap);
    549		goto put_node;
    550	}
    551
    552	ebi->smc.layout = atmel_hsmc_get_reg_layout(smc_np);
    553	if (IS_ERR(ebi->smc.layout)) {
    554		ret = PTR_ERR(ebi->smc.layout);
    555		goto put_node;
    556	}
    557
    558	ebi->smc.clk = of_clk_get(smc_np, 0);
    559	if (IS_ERR(ebi->smc.clk)) {
    560		if (PTR_ERR(ebi->smc.clk) != -ENOENT) {
    561			ret = PTR_ERR(ebi->smc.clk);
    562			goto put_node;
    563		}
    564
    565		ebi->smc.clk = NULL;
    566	}
    567	of_node_put(smc_np);
    568	ret = clk_prepare_enable(ebi->smc.clk);
    569	if (ret)
    570		return ret;
    571
    572	/*
    573	 * The sama5d3 does not provide an EBICSA register and thus does need
    574	 * to access it.
    575	 */
    576	if (ebi->caps->ebi_csa_offs) {
    577		ebi->regmap =
    578			syscon_regmap_lookup_by_phandle(np,
    579							ebi->caps->regmap_name);
    580		if (IS_ERR(ebi->regmap))
    581			return PTR_ERR(ebi->regmap);
    582	}
    583
    584	ret = of_property_read_u32(np, "#address-cells", &val);
    585	if (ret) {
    586		dev_err(dev, "missing #address-cells property\n");
    587		return ret;
    588	}
    589
    590	reg_cells = val;
    591
    592	ret = of_property_read_u32(np, "#size-cells", &val);
    593	if (ret) {
    594		dev_err(dev, "missing #address-cells property\n");
    595		return ret;
    596	}
    597
    598	reg_cells += val;
    599
    600	for_each_available_child_of_node(np, child) {
    601		if (!of_find_property(child, "reg", NULL))
    602			continue;
    603
    604		ret = atmel_ebi_dev_setup(ebi, child, reg_cells);
    605		if (ret) {
    606			dev_err(dev, "failed to configure EBI bus for %pOF, disabling the device",
    607				child);
    608
    609			ret = atmel_ebi_dev_disable(ebi, child);
    610			if (ret) {
    611				of_node_put(child);
    612				return ret;
    613			}
    614		}
    615	}
    616
    617	return of_platform_populate(np, NULL, NULL, dev);
    618
    619put_node:
    620	of_node_put(smc_np);
    621	return ret;
    622}
    623
    624static __maybe_unused int atmel_ebi_resume(struct device *dev)
    625{
    626	struct atmel_ebi *ebi = dev_get_drvdata(dev);
    627	struct atmel_ebi_dev *ebid;
    628
    629	list_for_each_entry(ebid, &ebi->devs, node) {
    630		int i;
    631
    632		for (i = 0; i < ebid->numcs; i++)
    633			ebid->ebi->caps->apply_config(ebid, &ebid->configs[i]);
    634	}
    635
    636	return 0;
    637}
    638
    639static SIMPLE_DEV_PM_OPS(atmel_ebi_pm_ops, NULL, atmel_ebi_resume);
    640
    641static struct platform_driver atmel_ebi_driver = {
    642	.driver = {
    643		.name = "atmel-ebi",
    644		.of_match_table	= atmel_ebi_id_table,
    645		.pm = &atmel_ebi_pm_ops,
    646	},
    647};
    648builtin_platform_driver_probe(atmel_ebi_driver, atmel_ebi_probe);