xref: /openbmc/linux/drivers/mfd/atmel-smc.c (revision f130faeb)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2fe9d7cb2SBoris Brezillon /*
3fe9d7cb2SBoris Brezillon  * Atmel SMC (Static Memory Controller) helper functions.
4fe9d7cb2SBoris Brezillon  *
5fe9d7cb2SBoris Brezillon  * Copyright (C) 2017 Atmel
6fe9d7cb2SBoris Brezillon  * Copyright (C) 2017 Free Electrons
7fe9d7cb2SBoris Brezillon  *
8fe9d7cb2SBoris Brezillon  * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
9fe9d7cb2SBoris Brezillon  */
10fe9d7cb2SBoris Brezillon 
11fe9d7cb2SBoris Brezillon #include <linux/mfd/syscon/atmel-smc.h>
12cadb2b12SSebastian Andrzej Siewior #include <linux/string.h>
13fe9d7cb2SBoris Brezillon 
14fe9d7cb2SBoris Brezillon /**
15fe9d7cb2SBoris Brezillon  * atmel_smc_cs_conf_init - initialize a SMC CS conf
16fe9d7cb2SBoris Brezillon  * @conf: the SMC CS conf to initialize
17fe9d7cb2SBoris Brezillon  *
18fe9d7cb2SBoris Brezillon  * Set all fields to 0 so that one can start defining a new config.
19fe9d7cb2SBoris Brezillon  */
atmel_smc_cs_conf_init(struct atmel_smc_cs_conf * conf)20fe9d7cb2SBoris Brezillon void atmel_smc_cs_conf_init(struct atmel_smc_cs_conf *conf)
21fe9d7cb2SBoris Brezillon {
22fe9d7cb2SBoris Brezillon 	memset(conf, 0, sizeof(*conf));
23fe9d7cb2SBoris Brezillon }
24fe9d7cb2SBoris Brezillon EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_init);
25fe9d7cb2SBoris Brezillon 
26fe9d7cb2SBoris Brezillon /**
27fe9d7cb2SBoris Brezillon  * atmel_smc_cs_encode_ncycles - encode a number of MCK clk cycles in the
28fe9d7cb2SBoris Brezillon  *				 format expected by the SMC engine
29fe9d7cb2SBoris Brezillon  * @ncycles: number of MCK clk cycles
30fe9d7cb2SBoris Brezillon  * @msbpos: position of the MSB part of the timing field
31fe9d7cb2SBoris Brezillon  * @msbwidth: width of the MSB part of the timing field
32fe9d7cb2SBoris Brezillon  * @msbfactor: factor applied to the MSB
33fe9d7cb2SBoris Brezillon  * @encodedval: param used to store the encoding result
34fe9d7cb2SBoris Brezillon  *
35fe9d7cb2SBoris Brezillon  * This function encodes the @ncycles value as described in the datasheet
36fe9d7cb2SBoris Brezillon  * (section "SMC Setup/Pulse/Cycle/Timings Register"). This is a generic
37fe9d7cb2SBoris Brezillon  * helper which called with different parameter depending on the encoding
38fe9d7cb2SBoris Brezillon  * scheme.
39fe9d7cb2SBoris Brezillon  *
40fe9d7cb2SBoris Brezillon  * If the @ncycles value is too big to be encoded, -ERANGE is returned and
41fe9d7cb2SBoris Brezillon  * the encodedval is contains the maximum val. Otherwise, 0 is returned.
42fe9d7cb2SBoris Brezillon  */
atmel_smc_cs_encode_ncycles(unsigned int ncycles,unsigned int msbpos,unsigned int msbwidth,unsigned int msbfactor,unsigned int * encodedval)43fe9d7cb2SBoris Brezillon static int atmel_smc_cs_encode_ncycles(unsigned int ncycles,
44fe9d7cb2SBoris Brezillon 				       unsigned int msbpos,
45fe9d7cb2SBoris Brezillon 				       unsigned int msbwidth,
46fe9d7cb2SBoris Brezillon 				       unsigned int msbfactor,
47fe9d7cb2SBoris Brezillon 				       unsigned int *encodedval)
48fe9d7cb2SBoris Brezillon {
49fe9d7cb2SBoris Brezillon 	unsigned int lsbmask = GENMASK(msbpos - 1, 0);
50fe9d7cb2SBoris Brezillon 	unsigned int msbmask = GENMASK(msbwidth - 1, 0);
51fe9d7cb2SBoris Brezillon 	unsigned int msb, lsb;
52fe9d7cb2SBoris Brezillon 	int ret = 0;
53fe9d7cb2SBoris Brezillon 
54fe9d7cb2SBoris Brezillon 	msb = ncycles / msbfactor;
55fe9d7cb2SBoris Brezillon 	lsb = ncycles % msbfactor;
56fe9d7cb2SBoris Brezillon 
57fe9d7cb2SBoris Brezillon 	if (lsb > lsbmask) {
58fe9d7cb2SBoris Brezillon 		lsb = 0;
59fe9d7cb2SBoris Brezillon 		msb++;
60fe9d7cb2SBoris Brezillon 	}
61fe9d7cb2SBoris Brezillon 
62fe9d7cb2SBoris Brezillon 	/*
63fe9d7cb2SBoris Brezillon 	 * Let's just put the maximum we can if the requested setting does
64fe9d7cb2SBoris Brezillon 	 * not fit in the register field.
65fe9d7cb2SBoris Brezillon 	 * We still return -ERANGE in case the caller cares.
66fe9d7cb2SBoris Brezillon 	 */
67fe9d7cb2SBoris Brezillon 	if (msb > msbmask) {
68fe9d7cb2SBoris Brezillon 		msb = msbmask;
69fe9d7cb2SBoris Brezillon 		lsb = lsbmask;
70fe9d7cb2SBoris Brezillon 		ret = -ERANGE;
71fe9d7cb2SBoris Brezillon 	}
72fe9d7cb2SBoris Brezillon 
73fe9d7cb2SBoris Brezillon 	*encodedval = (msb << msbpos) | lsb;
74fe9d7cb2SBoris Brezillon 
75fe9d7cb2SBoris Brezillon 	return ret;
76fe9d7cb2SBoris Brezillon }
77fe9d7cb2SBoris Brezillon 
78fe9d7cb2SBoris Brezillon /**
79fe9d7cb2SBoris Brezillon  * atmel_smc_cs_conf_set_timing - set the SMC CS conf Txx parameter to a
80fe9d7cb2SBoris Brezillon  *				  specific value
81fe9d7cb2SBoris Brezillon  * @conf: SMC CS conf descriptor
82fe9d7cb2SBoris Brezillon  * @shift: the position of the Txx field in the TIMINGS register
83fe9d7cb2SBoris Brezillon  * @ncycles: value (expressed in MCK clk cycles) to assign to this Txx
84fe9d7cb2SBoris Brezillon  *	     parameter
85fe9d7cb2SBoris Brezillon  *
86fe9d7cb2SBoris Brezillon  * This function encodes the @ncycles value as described in the datasheet
87fe9d7cb2SBoris Brezillon  * (section "SMC Timings Register"), and then stores the result in the
88fe9d7cb2SBoris Brezillon  * @conf->timings field at @shift position.
89fe9d7cb2SBoris Brezillon  *
90fe9d7cb2SBoris Brezillon  * Returns -EINVAL if shift is invalid, -ERANGE if ncycles does not fit in
91fe9d7cb2SBoris Brezillon  * the field, and 0 otherwise.
92fe9d7cb2SBoris Brezillon  */
atmel_smc_cs_conf_set_timing(struct atmel_smc_cs_conf * conf,unsigned int shift,unsigned int ncycles)93fe9d7cb2SBoris Brezillon int atmel_smc_cs_conf_set_timing(struct atmel_smc_cs_conf *conf,
94fe9d7cb2SBoris Brezillon 				 unsigned int shift, unsigned int ncycles)
95fe9d7cb2SBoris Brezillon {
96fe9d7cb2SBoris Brezillon 	unsigned int val;
97fe9d7cb2SBoris Brezillon 	int ret;
98fe9d7cb2SBoris Brezillon 
99fe9d7cb2SBoris Brezillon 	if (shift != ATMEL_HSMC_TIMINGS_TCLR_SHIFT &&
100fe9d7cb2SBoris Brezillon 	    shift != ATMEL_HSMC_TIMINGS_TADL_SHIFT &&
101fe9d7cb2SBoris Brezillon 	    shift != ATMEL_HSMC_TIMINGS_TAR_SHIFT &&
102fe9d7cb2SBoris Brezillon 	    shift != ATMEL_HSMC_TIMINGS_TRR_SHIFT &&
103fe9d7cb2SBoris Brezillon 	    shift != ATMEL_HSMC_TIMINGS_TWB_SHIFT)
104fe9d7cb2SBoris Brezillon 		return -EINVAL;
105fe9d7cb2SBoris Brezillon 
106fe9d7cb2SBoris Brezillon 	/*
107fe9d7cb2SBoris Brezillon 	 * The formula described in atmel datasheets (section "HSMC Timings
108fe9d7cb2SBoris Brezillon 	 * Register"):
109fe9d7cb2SBoris Brezillon 	 *
110fe9d7cb2SBoris Brezillon 	 * ncycles = (Txx[3] * 64) + Txx[2:0]
111fe9d7cb2SBoris Brezillon 	 */
112fe9d7cb2SBoris Brezillon 	ret = atmel_smc_cs_encode_ncycles(ncycles, 3, 1, 64, &val);
113fe9d7cb2SBoris Brezillon 	conf->timings &= ~GENMASK(shift + 3, shift);
114fe9d7cb2SBoris Brezillon 	conf->timings |= val << shift;
115fe9d7cb2SBoris Brezillon 
116fe9d7cb2SBoris Brezillon 	return ret;
117fe9d7cb2SBoris Brezillon }
118fe9d7cb2SBoris Brezillon EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_set_timing);
119fe9d7cb2SBoris Brezillon 
120fe9d7cb2SBoris Brezillon /**
121fe9d7cb2SBoris Brezillon  * atmel_smc_cs_conf_set_setup - set the SMC CS conf xx_SETUP parameter to a
122fe9d7cb2SBoris Brezillon  *				 specific value
123fe9d7cb2SBoris Brezillon  * @conf: SMC CS conf descriptor
124fe9d7cb2SBoris Brezillon  * @shift: the position of the xx_SETUP field in the SETUP register
125fe9d7cb2SBoris Brezillon  * @ncycles: value (expressed in MCK clk cycles) to assign to this xx_SETUP
126fe9d7cb2SBoris Brezillon  *	     parameter
127fe9d7cb2SBoris Brezillon  *
128fe9d7cb2SBoris Brezillon  * This function encodes the @ncycles value as described in the datasheet
129fe9d7cb2SBoris Brezillon  * (section "SMC Setup Register"), and then stores the result in the
130fe9d7cb2SBoris Brezillon  * @conf->setup field at @shift position.
131fe9d7cb2SBoris Brezillon  *
132fe9d7cb2SBoris Brezillon  * Returns -EINVAL if @shift is invalid, -ERANGE if @ncycles does not fit in
133fe9d7cb2SBoris Brezillon  * the field, and 0 otherwise.
134fe9d7cb2SBoris Brezillon  */
atmel_smc_cs_conf_set_setup(struct atmel_smc_cs_conf * conf,unsigned int shift,unsigned int ncycles)135fe9d7cb2SBoris Brezillon int atmel_smc_cs_conf_set_setup(struct atmel_smc_cs_conf *conf,
136fe9d7cb2SBoris Brezillon 				unsigned int shift, unsigned int ncycles)
137fe9d7cb2SBoris Brezillon {
138fe9d7cb2SBoris Brezillon 	unsigned int val;
139fe9d7cb2SBoris Brezillon 	int ret;
140fe9d7cb2SBoris Brezillon 
141fe9d7cb2SBoris Brezillon 	if (shift != ATMEL_SMC_NWE_SHIFT && shift != ATMEL_SMC_NCS_WR_SHIFT &&
142fe9d7cb2SBoris Brezillon 	    shift != ATMEL_SMC_NRD_SHIFT && shift != ATMEL_SMC_NCS_RD_SHIFT)
143fe9d7cb2SBoris Brezillon 		return -EINVAL;
144fe9d7cb2SBoris Brezillon 
145fe9d7cb2SBoris Brezillon 	/*
146fe9d7cb2SBoris Brezillon 	 * The formula described in atmel datasheets (section "SMC Setup
147fe9d7cb2SBoris Brezillon 	 * Register"):
148fe9d7cb2SBoris Brezillon 	 *
149fe9d7cb2SBoris Brezillon 	 * ncycles = (128 * xx_SETUP[5]) + xx_SETUP[4:0]
150fe9d7cb2SBoris Brezillon 	 */
151fe9d7cb2SBoris Brezillon 	ret = atmel_smc_cs_encode_ncycles(ncycles, 5, 1, 128, &val);
152fe9d7cb2SBoris Brezillon 	conf->setup &= ~GENMASK(shift + 7, shift);
153fe9d7cb2SBoris Brezillon 	conf->setup |= val << shift;
154fe9d7cb2SBoris Brezillon 
155fe9d7cb2SBoris Brezillon 	return ret;
156fe9d7cb2SBoris Brezillon }
157fe9d7cb2SBoris Brezillon EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_set_setup);
158fe9d7cb2SBoris Brezillon 
159fe9d7cb2SBoris Brezillon /**
160fe9d7cb2SBoris Brezillon  * atmel_smc_cs_conf_set_pulse - set the SMC CS conf xx_PULSE parameter to a
161fe9d7cb2SBoris Brezillon  *				 specific value
162fe9d7cb2SBoris Brezillon  * @conf: SMC CS conf descriptor
163fe9d7cb2SBoris Brezillon  * @shift: the position of the xx_PULSE field in the PULSE register
164fe9d7cb2SBoris Brezillon  * @ncycles: value (expressed in MCK clk cycles) to assign to this xx_PULSE
165fe9d7cb2SBoris Brezillon  *	     parameter
166fe9d7cb2SBoris Brezillon  *
167fe9d7cb2SBoris Brezillon  * This function encodes the @ncycles value as described in the datasheet
168fe9d7cb2SBoris Brezillon  * (section "SMC Pulse Register"), and then stores the result in the
169fe9d7cb2SBoris Brezillon  * @conf->setup field at @shift position.
170fe9d7cb2SBoris Brezillon  *
171fe9d7cb2SBoris Brezillon  * Returns -EINVAL if @shift is invalid, -ERANGE if @ncycles does not fit in
172fe9d7cb2SBoris Brezillon  * the field, and 0 otherwise.
173fe9d7cb2SBoris Brezillon  */
atmel_smc_cs_conf_set_pulse(struct atmel_smc_cs_conf * conf,unsigned int shift,unsigned int ncycles)174fe9d7cb2SBoris Brezillon int atmel_smc_cs_conf_set_pulse(struct atmel_smc_cs_conf *conf,
175fe9d7cb2SBoris Brezillon 				unsigned int shift, unsigned int ncycles)
176fe9d7cb2SBoris Brezillon {
177fe9d7cb2SBoris Brezillon 	unsigned int val;
178fe9d7cb2SBoris Brezillon 	int ret;
179fe9d7cb2SBoris Brezillon 
180fe9d7cb2SBoris Brezillon 	if (shift != ATMEL_SMC_NWE_SHIFT && shift != ATMEL_SMC_NCS_WR_SHIFT &&
181fe9d7cb2SBoris Brezillon 	    shift != ATMEL_SMC_NRD_SHIFT && shift != ATMEL_SMC_NCS_RD_SHIFT)
182fe9d7cb2SBoris Brezillon 		return -EINVAL;
183fe9d7cb2SBoris Brezillon 
184fe9d7cb2SBoris Brezillon 	/*
185fe9d7cb2SBoris Brezillon 	 * The formula described in atmel datasheets (section "SMC Pulse
186fe9d7cb2SBoris Brezillon 	 * Register"):
187fe9d7cb2SBoris Brezillon 	 *
188fe9d7cb2SBoris Brezillon 	 * ncycles = (256 * xx_PULSE[6]) + xx_PULSE[5:0]
189fe9d7cb2SBoris Brezillon 	 */
190fe9d7cb2SBoris Brezillon 	ret = atmel_smc_cs_encode_ncycles(ncycles, 6, 1, 256, &val);
191fe9d7cb2SBoris Brezillon 	conf->pulse &= ~GENMASK(shift + 7, shift);
192fe9d7cb2SBoris Brezillon 	conf->pulse |= val << shift;
193fe9d7cb2SBoris Brezillon 
194fe9d7cb2SBoris Brezillon 	return ret;
195fe9d7cb2SBoris Brezillon }
196fe9d7cb2SBoris Brezillon EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_set_pulse);
197fe9d7cb2SBoris Brezillon 
198fe9d7cb2SBoris Brezillon /**
199fe9d7cb2SBoris Brezillon  * atmel_smc_cs_conf_set_cycle - set the SMC CS conf xx_CYCLE parameter to a
200fe9d7cb2SBoris Brezillon  *				 specific value
201fe9d7cb2SBoris Brezillon  * @conf: SMC CS conf descriptor
202fe9d7cb2SBoris Brezillon  * @shift: the position of the xx_CYCLE field in the CYCLE register
203fe9d7cb2SBoris Brezillon  * @ncycles: value (expressed in MCK clk cycles) to assign to this xx_CYCLE
204fe9d7cb2SBoris Brezillon  *	     parameter
205fe9d7cb2SBoris Brezillon  *
206fe9d7cb2SBoris Brezillon  * This function encodes the @ncycles value as described in the datasheet
2073fb3b3c4SAlexander Dahl  * (section "SMC Cycle Register"), and then stores the result in the
208fe9d7cb2SBoris Brezillon  * @conf->setup field at @shift position.
209fe9d7cb2SBoris Brezillon  *
210fe9d7cb2SBoris Brezillon  * Returns -EINVAL if @shift is invalid, -ERANGE if @ncycles does not fit in
211fe9d7cb2SBoris Brezillon  * the field, and 0 otherwise.
212fe9d7cb2SBoris Brezillon  */
atmel_smc_cs_conf_set_cycle(struct atmel_smc_cs_conf * conf,unsigned int shift,unsigned int ncycles)213fe9d7cb2SBoris Brezillon int atmel_smc_cs_conf_set_cycle(struct atmel_smc_cs_conf *conf,
214fe9d7cb2SBoris Brezillon 				unsigned int shift, unsigned int ncycles)
215fe9d7cb2SBoris Brezillon {
216fe9d7cb2SBoris Brezillon 	unsigned int val;
217fe9d7cb2SBoris Brezillon 	int ret;
218fe9d7cb2SBoris Brezillon 
219fe9d7cb2SBoris Brezillon 	if (shift != ATMEL_SMC_NWE_SHIFT && shift != ATMEL_SMC_NRD_SHIFT)
220fe9d7cb2SBoris Brezillon 		return -EINVAL;
221fe9d7cb2SBoris Brezillon 
222fe9d7cb2SBoris Brezillon 	/*
223fe9d7cb2SBoris Brezillon 	 * The formula described in atmel datasheets (section "SMC Cycle
224fe9d7cb2SBoris Brezillon 	 * Register"):
225fe9d7cb2SBoris Brezillon 	 *
226fe9d7cb2SBoris Brezillon 	 * ncycles = (xx_CYCLE[8:7] * 256) + xx_CYCLE[6:0]
227fe9d7cb2SBoris Brezillon 	 */
228fe9d7cb2SBoris Brezillon 	ret = atmel_smc_cs_encode_ncycles(ncycles, 7, 2, 256, &val);
229fe9d7cb2SBoris Brezillon 	conf->cycle &= ~GENMASK(shift + 15, shift);
230fe9d7cb2SBoris Brezillon 	conf->cycle |= val << shift;
231fe9d7cb2SBoris Brezillon 
232fe9d7cb2SBoris Brezillon 	return ret;
233fe9d7cb2SBoris Brezillon }
234fe9d7cb2SBoris Brezillon EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_set_cycle);
235fe9d7cb2SBoris Brezillon 
236fe9d7cb2SBoris Brezillon /**
237fe9d7cb2SBoris Brezillon  * atmel_smc_cs_conf_apply - apply an SMC CS conf
238fe9d7cb2SBoris Brezillon  * @regmap: the SMC regmap
239fe9d7cb2SBoris Brezillon  * @cs: the CS id
2401574360aSLee Jones  * @conf: the SMC CS conf to apply
241fe9d7cb2SBoris Brezillon  *
242fe9d7cb2SBoris Brezillon  * Applies an SMC CS configuration.
24353291cb2SHans-Christian Noren Egtvedt  * Only valid on at91sam9 SoCs.
244fe9d7cb2SBoris Brezillon  */
atmel_smc_cs_conf_apply(struct regmap * regmap,int cs,const struct atmel_smc_cs_conf * conf)245fe9d7cb2SBoris Brezillon void atmel_smc_cs_conf_apply(struct regmap *regmap, int cs,
246fe9d7cb2SBoris Brezillon 			     const struct atmel_smc_cs_conf *conf)
247fe9d7cb2SBoris Brezillon {
248fe9d7cb2SBoris Brezillon 	regmap_write(regmap, ATMEL_SMC_SETUP(cs), conf->setup);
249fe9d7cb2SBoris Brezillon 	regmap_write(regmap, ATMEL_SMC_PULSE(cs), conf->pulse);
250fe9d7cb2SBoris Brezillon 	regmap_write(regmap, ATMEL_SMC_CYCLE(cs), conf->cycle);
251fe9d7cb2SBoris Brezillon 	regmap_write(regmap, ATMEL_SMC_MODE(cs), conf->mode);
252fe9d7cb2SBoris Brezillon }
253fe9d7cb2SBoris Brezillon EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_apply);
254fe9d7cb2SBoris Brezillon 
255fe9d7cb2SBoris Brezillon /**
256fe9d7cb2SBoris Brezillon  * atmel_hsmc_cs_conf_apply - apply an SMC CS conf
257fe9d7cb2SBoris Brezillon  * @regmap: the HSMC regmap
258fe9d7cb2SBoris Brezillon  * @cs: the CS id
259b0f3ab20SLudovic Desroches  * @layout: the layout of registers
2601574360aSLee Jones  * @conf: the SMC CS conf to apply
261fe9d7cb2SBoris Brezillon  *
262fe9d7cb2SBoris Brezillon  * Applies an SMC CS configuration.
263fe9d7cb2SBoris Brezillon  * Only valid on post-sama5 SoCs.
264fe9d7cb2SBoris Brezillon  */
atmel_hsmc_cs_conf_apply(struct regmap * regmap,const struct atmel_hsmc_reg_layout * layout,int cs,const struct atmel_smc_cs_conf * conf)265b0f3ab20SLudovic Desroches void atmel_hsmc_cs_conf_apply(struct regmap *regmap,
266b0f3ab20SLudovic Desroches 			      const struct atmel_hsmc_reg_layout *layout,
267b0f3ab20SLudovic Desroches 			      int cs, const struct atmel_smc_cs_conf *conf)
268fe9d7cb2SBoris Brezillon {
269b0f3ab20SLudovic Desroches 	regmap_write(regmap, ATMEL_HSMC_SETUP(layout, cs), conf->setup);
270b0f3ab20SLudovic Desroches 	regmap_write(regmap, ATMEL_HSMC_PULSE(layout, cs), conf->pulse);
271b0f3ab20SLudovic Desroches 	regmap_write(regmap, ATMEL_HSMC_CYCLE(layout, cs), conf->cycle);
272b0f3ab20SLudovic Desroches 	regmap_write(regmap, ATMEL_HSMC_TIMINGS(layout, cs), conf->timings);
273b0f3ab20SLudovic Desroches 	regmap_write(regmap, ATMEL_HSMC_MODE(layout, cs), conf->mode);
274fe9d7cb2SBoris Brezillon }
275fe9d7cb2SBoris Brezillon EXPORT_SYMBOL_GPL(atmel_hsmc_cs_conf_apply);
276fe9d7cb2SBoris Brezillon 
277fe9d7cb2SBoris Brezillon /**
278fe9d7cb2SBoris Brezillon  * atmel_smc_cs_conf_get - retrieve the current SMC CS conf
279fe9d7cb2SBoris Brezillon  * @regmap: the SMC regmap
280fe9d7cb2SBoris Brezillon  * @cs: the CS id
281fe9d7cb2SBoris Brezillon  * @conf: the SMC CS conf object to store the current conf
282fe9d7cb2SBoris Brezillon  *
283fe9d7cb2SBoris Brezillon  * Retrieve the SMC CS configuration.
28453291cb2SHans-Christian Noren Egtvedt  * Only valid on at91sam9 SoCs.
285fe9d7cb2SBoris Brezillon  */
atmel_smc_cs_conf_get(struct regmap * regmap,int cs,struct atmel_smc_cs_conf * conf)286fe9d7cb2SBoris Brezillon void atmel_smc_cs_conf_get(struct regmap *regmap, int cs,
287fe9d7cb2SBoris Brezillon 			   struct atmel_smc_cs_conf *conf)
288fe9d7cb2SBoris Brezillon {
289fe9d7cb2SBoris Brezillon 	regmap_read(regmap, ATMEL_SMC_SETUP(cs), &conf->setup);
290fe9d7cb2SBoris Brezillon 	regmap_read(regmap, ATMEL_SMC_PULSE(cs), &conf->pulse);
291fe9d7cb2SBoris Brezillon 	regmap_read(regmap, ATMEL_SMC_CYCLE(cs), &conf->cycle);
292fe9d7cb2SBoris Brezillon 	regmap_read(regmap, ATMEL_SMC_MODE(cs), &conf->mode);
293fe9d7cb2SBoris Brezillon }
294fe9d7cb2SBoris Brezillon EXPORT_SYMBOL_GPL(atmel_smc_cs_conf_get);
295fe9d7cb2SBoris Brezillon 
296fe9d7cb2SBoris Brezillon /**
297fe9d7cb2SBoris Brezillon  * atmel_hsmc_cs_conf_get - retrieve the current SMC CS conf
298fe9d7cb2SBoris Brezillon  * @regmap: the HSMC regmap
299fe9d7cb2SBoris Brezillon  * @cs: the CS id
300b0f3ab20SLudovic Desroches  * @layout: the layout of registers
301fe9d7cb2SBoris Brezillon  * @conf: the SMC CS conf object to store the current conf
302fe9d7cb2SBoris Brezillon  *
303fe9d7cb2SBoris Brezillon  * Retrieve the SMC CS configuration.
304fe9d7cb2SBoris Brezillon  * Only valid on post-sama5 SoCs.
305fe9d7cb2SBoris Brezillon  */
atmel_hsmc_cs_conf_get(struct regmap * regmap,const struct atmel_hsmc_reg_layout * layout,int cs,struct atmel_smc_cs_conf * conf)306b0f3ab20SLudovic Desroches void atmel_hsmc_cs_conf_get(struct regmap *regmap,
307b0f3ab20SLudovic Desroches 			    const struct atmel_hsmc_reg_layout *layout,
308b0f3ab20SLudovic Desroches 			    int cs, struct atmel_smc_cs_conf *conf)
309fe9d7cb2SBoris Brezillon {
310b0f3ab20SLudovic Desroches 	regmap_read(regmap, ATMEL_HSMC_SETUP(layout, cs), &conf->setup);
311b0f3ab20SLudovic Desroches 	regmap_read(regmap, ATMEL_HSMC_PULSE(layout, cs), &conf->pulse);
312b0f3ab20SLudovic Desroches 	regmap_read(regmap, ATMEL_HSMC_CYCLE(layout, cs), &conf->cycle);
313b0f3ab20SLudovic Desroches 	regmap_read(regmap, ATMEL_HSMC_TIMINGS(layout, cs), &conf->timings);
314b0f3ab20SLudovic Desroches 	regmap_read(regmap, ATMEL_HSMC_MODE(layout, cs), &conf->mode);
315fe9d7cb2SBoris Brezillon }
316fe9d7cb2SBoris Brezillon EXPORT_SYMBOL_GPL(atmel_hsmc_cs_conf_get);
317b0f3ab20SLudovic Desroches 
318b0f3ab20SLudovic Desroches static const struct atmel_hsmc_reg_layout sama5d3_reg_layout = {
319b0f3ab20SLudovic Desroches 	.timing_regs_offset = 0x600,
320b0f3ab20SLudovic Desroches };
321b0f3ab20SLudovic Desroches 
322b0f3ab20SLudovic Desroches static const struct atmel_hsmc_reg_layout sama5d2_reg_layout = {
323b0f3ab20SLudovic Desroches 	.timing_regs_offset = 0x700,
324b0f3ab20SLudovic Desroches };
325b0f3ab20SLudovic Desroches 
326*f130faebSKrzysztof Kozlowski static const struct of_device_id atmel_smc_ids[] __maybe_unused = {
327b0f3ab20SLudovic Desroches 	{ .compatible = "atmel,at91sam9260-smc", .data = NULL },
328b0f3ab20SLudovic Desroches 	{ .compatible = "atmel,sama5d3-smc", .data = &sama5d3_reg_layout },
329b0f3ab20SLudovic Desroches 	{ .compatible = "atmel,sama5d2-smc", .data = &sama5d2_reg_layout },
330b0f3ab20SLudovic Desroches 	{ /* sentinel */ },
331b0f3ab20SLudovic Desroches };
332b0f3ab20SLudovic Desroches 
333b0f3ab20SLudovic Desroches /**
334b0f3ab20SLudovic Desroches  * atmel_hsmc_get_reg_layout - retrieve the layout of HSMC registers
335b0f3ab20SLudovic Desroches  * @np: the HSMC regmap
336b0f3ab20SLudovic Desroches  *
337b0f3ab20SLudovic Desroches  * Retrieve the layout of HSMC registers.
338b0f3ab20SLudovic Desroches  *
339b0f3ab20SLudovic Desroches  * Returns NULL in case of SMC, a struct atmel_hsmc_reg_layout pointer
340b0f3ab20SLudovic Desroches  * in HSMC case, otherwise ERR_PTR(-EINVAL).
341b0f3ab20SLudovic Desroches  */
342b0f3ab20SLudovic Desroches const struct atmel_hsmc_reg_layout *
atmel_hsmc_get_reg_layout(struct device_node * np)343b0f3ab20SLudovic Desroches atmel_hsmc_get_reg_layout(struct device_node *np)
344b0f3ab20SLudovic Desroches {
345b0f3ab20SLudovic Desroches 	const struct of_device_id *match;
346b0f3ab20SLudovic Desroches 
347b0f3ab20SLudovic Desroches 	match = of_match_node(atmel_smc_ids, np);
348b0f3ab20SLudovic Desroches 
349b0f3ab20SLudovic Desroches 	return match ? match->data : ERR_PTR(-EINVAL);
350b0f3ab20SLudovic Desroches }
351b0f3ab20SLudovic Desroches EXPORT_SYMBOL_GPL(atmel_hsmc_get_reg_layout);
352