xref: /openbmc/linux/drivers/fpga/socfpga-a10.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1473f01f7SAlan Tull // SPDX-License-Identifier: GPL-2.0
2acbb910aSAlan Tull /*
3acbb910aSAlan Tull  * FPGA Manager Driver for Altera Arria10 SoCFPGA
4acbb910aSAlan Tull  *
5acbb910aSAlan Tull  * Copyright (C) 2015-2016 Altera Corporation
6acbb910aSAlan Tull  */
7acbb910aSAlan Tull #include <linux/clk.h>
8acbb910aSAlan Tull #include <linux/device.h>
9acbb910aSAlan Tull #include <linux/delay.h>
10acbb910aSAlan Tull #include <linux/fpga/fpga-mgr.h>
11acbb910aSAlan Tull #include <linux/io.h>
12acbb910aSAlan Tull #include <linux/module.h>
13acbb910aSAlan Tull #include <linux/of_address.h>
14acbb910aSAlan Tull #include <linux/regmap.h>
15acbb910aSAlan Tull 
16acbb910aSAlan Tull #define A10_FPGAMGR_DCLKCNT_OFST				0x08
17acbb910aSAlan Tull #define A10_FPGAMGR_DCLKSTAT_OFST				0x0c
18acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_CTL_00_OFST				0x70
19acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_CTL_01_OFST				0x74
20acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_CTL_02_OFST				0x78
21acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_STAT_OFST				0x80
22acbb910aSAlan Tull 
23acbb910aSAlan Tull #define A10_FPGAMGR_DCLKSTAT_DCLKDONE				BIT(0)
24acbb910aSAlan Tull 
25acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NCONFIG		BIT(0)
26acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NSTATUS		BIT(1)
27acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_CONDONE		BIT(2)
28acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG			BIT(8)
29acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NSTATUS_OE		BIT(16)
30acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_CTL_00_S2F_CONDONE_OE		BIT(24)
31acbb910aSAlan Tull 
32acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG		BIT(0)
33acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST		BIT(16)
34acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_CTL_01_S2F_NCE			BIT(24)
35acbb910aSAlan Tull 
36acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL			BIT(0)
37acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_MASK		(BIT(16) | BIT(17))
38acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_SHIFT			16
39acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH			BIT(24)
40acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH_SHIFT		24
41acbb910aSAlan Tull 
42acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_STAT_F2S_CRC_ERROR			BIT(0)
43acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_STAT_F2S_EARLY_USERMODE		BIT(1)
44acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_STAT_F2S_USERMODE			BIT(2)
45acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN			BIT(4)
46acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN			BIT(6)
47acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_STAT_F2S_PR_READY			BIT(9)
48acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_STAT_F2S_PR_DONE			BIT(10)
49acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_STAT_F2S_PR_ERROR			BIT(11)
50acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_STAT_F2S_NCONFIG_PIN			BIT(12)
51acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_MASK	(BIT(16) | BIT(17) | BIT(18))
52acbb910aSAlan Tull #define A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_SHIFT		        16
53acbb910aSAlan Tull 
54acbb910aSAlan Tull /* FPGA CD Ratio Value */
55acbb910aSAlan Tull #define CDRATIO_x1						0x0
56acbb910aSAlan Tull #define CDRATIO_x2						0x1
57acbb910aSAlan Tull #define CDRATIO_x4						0x2
58acbb910aSAlan Tull #define CDRATIO_x8						0x3
59acbb910aSAlan Tull 
60acbb910aSAlan Tull /* Configuration width 16/32 bit */
61acbb910aSAlan Tull #define CFGWDTH_32						1
62acbb910aSAlan Tull #define CFGWDTH_16						0
63acbb910aSAlan Tull 
64acbb910aSAlan Tull /*
65acbb910aSAlan Tull  * struct a10_fpga_priv - private data for fpga manager
66acbb910aSAlan Tull  * @regmap: regmap for register access
67acbb910aSAlan Tull  * @fpga_data_addr: iomap for single address data register to FPGA
68acbb910aSAlan Tull  * @clk: clock
69acbb910aSAlan Tull  */
70acbb910aSAlan Tull struct a10_fpga_priv {
71acbb910aSAlan Tull 	struct regmap *regmap;
72acbb910aSAlan Tull 	void __iomem *fpga_data_addr;
73acbb910aSAlan Tull 	struct clk *clk;
74acbb910aSAlan Tull };
75acbb910aSAlan Tull 
socfpga_a10_fpga_writeable_reg(struct device * dev,unsigned int reg)76acbb910aSAlan Tull static bool socfpga_a10_fpga_writeable_reg(struct device *dev, unsigned int reg)
77acbb910aSAlan Tull {
78acbb910aSAlan Tull 	switch (reg) {
79acbb910aSAlan Tull 	case A10_FPGAMGR_DCLKCNT_OFST:
80acbb910aSAlan Tull 	case A10_FPGAMGR_DCLKSTAT_OFST:
81acbb910aSAlan Tull 	case A10_FPGAMGR_IMGCFG_CTL_00_OFST:
82acbb910aSAlan Tull 	case A10_FPGAMGR_IMGCFG_CTL_01_OFST:
83acbb910aSAlan Tull 	case A10_FPGAMGR_IMGCFG_CTL_02_OFST:
84acbb910aSAlan Tull 		return true;
85acbb910aSAlan Tull 	}
86acbb910aSAlan Tull 	return false;
87acbb910aSAlan Tull }
88acbb910aSAlan Tull 
socfpga_a10_fpga_readable_reg(struct device * dev,unsigned int reg)89acbb910aSAlan Tull static bool socfpga_a10_fpga_readable_reg(struct device *dev, unsigned int reg)
90acbb910aSAlan Tull {
91acbb910aSAlan Tull 	switch (reg) {
92acbb910aSAlan Tull 	case A10_FPGAMGR_DCLKCNT_OFST:
93acbb910aSAlan Tull 	case A10_FPGAMGR_DCLKSTAT_OFST:
94acbb910aSAlan Tull 	case A10_FPGAMGR_IMGCFG_CTL_00_OFST:
95acbb910aSAlan Tull 	case A10_FPGAMGR_IMGCFG_CTL_01_OFST:
96acbb910aSAlan Tull 	case A10_FPGAMGR_IMGCFG_CTL_02_OFST:
97acbb910aSAlan Tull 	case A10_FPGAMGR_IMGCFG_STAT_OFST:
98acbb910aSAlan Tull 		return true;
99acbb910aSAlan Tull 	}
100acbb910aSAlan Tull 	return false;
101acbb910aSAlan Tull }
102acbb910aSAlan Tull 
103acbb910aSAlan Tull static const struct regmap_config socfpga_a10_fpga_regmap_config = {
104acbb910aSAlan Tull 	.reg_bits = 32,
105acbb910aSAlan Tull 	.reg_stride = 4,
106acbb910aSAlan Tull 	.val_bits = 32,
107acbb910aSAlan Tull 	.writeable_reg = socfpga_a10_fpga_writeable_reg,
108acbb910aSAlan Tull 	.readable_reg = socfpga_a10_fpga_readable_reg,
109acbb910aSAlan Tull 	.max_register = A10_FPGAMGR_IMGCFG_STAT_OFST,
110acbb910aSAlan Tull 	.cache_type = REGCACHE_NONE,
111acbb910aSAlan Tull };
112acbb910aSAlan Tull 
113acbb910aSAlan Tull /*
114acbb910aSAlan Tull  * from the register map description of cdratio in imgcfg_ctrl_02:
115acbb910aSAlan Tull  *  Normal Configuration    : 32bit Passive Parallel
116acbb910aSAlan Tull  *  Partial Reconfiguration : 16bit Passive Parallel
117acbb910aSAlan Tull  */
socfpga_a10_fpga_set_cfg_width(struct a10_fpga_priv * priv,int width)118acbb910aSAlan Tull static void socfpga_a10_fpga_set_cfg_width(struct a10_fpga_priv *priv,
119acbb910aSAlan Tull 					   int width)
120acbb910aSAlan Tull {
121acbb910aSAlan Tull 	width <<= A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH_SHIFT;
122acbb910aSAlan Tull 
123acbb910aSAlan Tull 	regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_02_OFST,
124acbb910aSAlan Tull 			   A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH, width);
125acbb910aSAlan Tull }
126acbb910aSAlan Tull 
socfpga_a10_fpga_generate_dclks(struct a10_fpga_priv * priv,u32 count)127acbb910aSAlan Tull static void socfpga_a10_fpga_generate_dclks(struct a10_fpga_priv *priv,
128acbb910aSAlan Tull 					    u32 count)
129acbb910aSAlan Tull {
130acbb910aSAlan Tull 	u32 val;
131acbb910aSAlan Tull 
132acbb910aSAlan Tull 	/* Clear any existing DONE status. */
133acbb910aSAlan Tull 	regmap_write(priv->regmap, A10_FPGAMGR_DCLKSTAT_OFST,
134acbb910aSAlan Tull 		     A10_FPGAMGR_DCLKSTAT_DCLKDONE);
135acbb910aSAlan Tull 
136acbb910aSAlan Tull 	/* Issue the DCLK regmap. */
137acbb910aSAlan Tull 	regmap_write(priv->regmap, A10_FPGAMGR_DCLKCNT_OFST, count);
138acbb910aSAlan Tull 
139acbb910aSAlan Tull 	/* wait till the dclkcnt done */
140acbb910aSAlan Tull 	regmap_read_poll_timeout(priv->regmap, A10_FPGAMGR_DCLKSTAT_OFST, val,
141acbb910aSAlan Tull 				 val, 1, 100);
142acbb910aSAlan Tull 
143acbb910aSAlan Tull 	/* Clear DONE status. */
144acbb910aSAlan Tull 	regmap_write(priv->regmap, A10_FPGAMGR_DCLKSTAT_OFST,
145acbb910aSAlan Tull 		     A10_FPGAMGR_DCLKSTAT_DCLKDONE);
146acbb910aSAlan Tull }
147acbb910aSAlan Tull 
148acbb910aSAlan Tull #define RBF_ENCRYPTION_MODE_OFFSET		69
149acbb910aSAlan Tull #define RBF_DECOMPRESS_OFFSET			229
150acbb910aSAlan Tull 
socfpga_a10_fpga_encrypted(u32 * buf32,size_t buf32_size)151acbb910aSAlan Tull static int socfpga_a10_fpga_encrypted(u32 *buf32, size_t buf32_size)
152acbb910aSAlan Tull {
153acbb910aSAlan Tull 	if (buf32_size < RBF_ENCRYPTION_MODE_OFFSET + 1)
154acbb910aSAlan Tull 		return -EINVAL;
155acbb910aSAlan Tull 
156acbb910aSAlan Tull 	/* Is the bitstream encrypted? */
157acbb910aSAlan Tull 	return ((buf32[RBF_ENCRYPTION_MODE_OFFSET] >> 2) & 3) != 0;
158acbb910aSAlan Tull }
159acbb910aSAlan Tull 
socfpga_a10_fpga_compressed(u32 * buf32,size_t buf32_size)160acbb910aSAlan Tull static int socfpga_a10_fpga_compressed(u32 *buf32, size_t buf32_size)
161acbb910aSAlan Tull {
162acbb910aSAlan Tull 	if (buf32_size < RBF_DECOMPRESS_OFFSET + 1)
163acbb910aSAlan Tull 		return -EINVAL;
164acbb910aSAlan Tull 
165acbb910aSAlan Tull 	/* Is the bitstream compressed? */
166acbb910aSAlan Tull 	return !((buf32[RBF_DECOMPRESS_OFFSET] >> 1) & 1);
167acbb910aSAlan Tull }
168acbb910aSAlan Tull 
socfpga_a10_fpga_get_cd_ratio(unsigned int cfg_width,bool encrypt,bool compress)169acbb910aSAlan Tull static unsigned int socfpga_a10_fpga_get_cd_ratio(unsigned int cfg_width,
170acbb910aSAlan Tull 						  bool encrypt, bool compress)
171acbb910aSAlan Tull {
172acbb910aSAlan Tull 	unsigned int cd_ratio;
173acbb910aSAlan Tull 
174acbb910aSAlan Tull 	/*
175acbb910aSAlan Tull 	 * cd ratio is dependent on cfg width and whether the bitstream
176acbb910aSAlan Tull 	 * is encrypted and/or compressed.
177acbb910aSAlan Tull 	 *
178acbb910aSAlan Tull 	 * | width | encr. | compr. | cd ratio |
179acbb910aSAlan Tull 	 * |  16   |   0   |   0    |     1    |
180acbb910aSAlan Tull 	 * |  16   |   0   |   1    |     4    |
181acbb910aSAlan Tull 	 * |  16   |   1   |   0    |     2    |
182acbb910aSAlan Tull 	 * |  16   |   1   |   1    |     4    |
183acbb910aSAlan Tull 	 * |  32   |   0   |   0    |     1    |
184acbb910aSAlan Tull 	 * |  32   |   0   |   1    |     8    |
185acbb910aSAlan Tull 	 * |  32   |   1   |   0    |     4    |
186acbb910aSAlan Tull 	 * |  32   |   1   |   1    |     8    |
187acbb910aSAlan Tull 	 */
188acbb910aSAlan Tull 	if (!compress && !encrypt)
189acbb910aSAlan Tull 		return CDRATIO_x1;
190acbb910aSAlan Tull 
191acbb910aSAlan Tull 	if (compress)
192acbb910aSAlan Tull 		cd_ratio = CDRATIO_x4;
193acbb910aSAlan Tull 	else
194acbb910aSAlan Tull 		cd_ratio = CDRATIO_x2;
195acbb910aSAlan Tull 
196acbb910aSAlan Tull 	/* If 32 bit, double the cd ratio by incrementing the field  */
197acbb910aSAlan Tull 	if (cfg_width == CFGWDTH_32)
198acbb910aSAlan Tull 		cd_ratio += 1;
199acbb910aSAlan Tull 
200acbb910aSAlan Tull 	return cd_ratio;
201acbb910aSAlan Tull }
202acbb910aSAlan Tull 
socfpga_a10_fpga_set_cdratio(struct fpga_manager * mgr,unsigned int cfg_width,const char * buf,size_t count)203acbb910aSAlan Tull static int socfpga_a10_fpga_set_cdratio(struct fpga_manager *mgr,
204acbb910aSAlan Tull 					unsigned int cfg_width,
205acbb910aSAlan Tull 					const char *buf, size_t count)
206acbb910aSAlan Tull {
207acbb910aSAlan Tull 	struct a10_fpga_priv *priv = mgr->priv;
208acbb910aSAlan Tull 	unsigned int cd_ratio;
209acbb910aSAlan Tull 	int encrypt, compress;
210acbb910aSAlan Tull 
211acbb910aSAlan Tull 	encrypt = socfpga_a10_fpga_encrypted((u32 *)buf, count / 4);
212acbb910aSAlan Tull 	if (encrypt < 0)
213acbb910aSAlan Tull 		return -EINVAL;
214acbb910aSAlan Tull 
215acbb910aSAlan Tull 	compress = socfpga_a10_fpga_compressed((u32 *)buf, count / 4);
216acbb910aSAlan Tull 	if (compress < 0)
217acbb910aSAlan Tull 		return -EINVAL;
218acbb910aSAlan Tull 
219acbb910aSAlan Tull 	cd_ratio = socfpga_a10_fpga_get_cd_ratio(cfg_width, encrypt, compress);
220acbb910aSAlan Tull 
221acbb910aSAlan Tull 	regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_02_OFST,
222acbb910aSAlan Tull 			   A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_MASK,
223acbb910aSAlan Tull 			   cd_ratio << A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_SHIFT);
224acbb910aSAlan Tull 
225acbb910aSAlan Tull 	return 0;
226acbb910aSAlan Tull }
227acbb910aSAlan Tull 
socfpga_a10_fpga_read_stat(struct a10_fpga_priv * priv)228acbb910aSAlan Tull static u32 socfpga_a10_fpga_read_stat(struct a10_fpga_priv *priv)
229acbb910aSAlan Tull {
230acbb910aSAlan Tull 	u32 val;
231acbb910aSAlan Tull 
232acbb910aSAlan Tull 	regmap_read(priv->regmap, A10_FPGAMGR_IMGCFG_STAT_OFST, &val);
233acbb910aSAlan Tull 
234acbb910aSAlan Tull 	return val;
235acbb910aSAlan Tull }
236acbb910aSAlan Tull 
socfpga_a10_fpga_wait_for_pr_ready(struct a10_fpga_priv * priv)237acbb910aSAlan Tull static int socfpga_a10_fpga_wait_for_pr_ready(struct a10_fpga_priv *priv)
238acbb910aSAlan Tull {
239acbb910aSAlan Tull 	u32 reg, i;
240acbb910aSAlan Tull 
241acbb910aSAlan Tull 	for (i = 0; i < 10 ; i++) {
242acbb910aSAlan Tull 		reg = socfpga_a10_fpga_read_stat(priv);
243acbb910aSAlan Tull 
244acbb910aSAlan Tull 		if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_ERROR)
245acbb910aSAlan Tull 			return -EINVAL;
246acbb910aSAlan Tull 
247acbb910aSAlan Tull 		if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_READY)
248acbb910aSAlan Tull 			return 0;
249acbb910aSAlan Tull 	}
250acbb910aSAlan Tull 
251acbb910aSAlan Tull 	return -ETIMEDOUT;
252acbb910aSAlan Tull }
253acbb910aSAlan Tull 
socfpga_a10_fpga_wait_for_pr_done(struct a10_fpga_priv * priv)254acbb910aSAlan Tull static int socfpga_a10_fpga_wait_for_pr_done(struct a10_fpga_priv *priv)
255acbb910aSAlan Tull {
256acbb910aSAlan Tull 	u32 reg, i;
257acbb910aSAlan Tull 
258acbb910aSAlan Tull 	for (i = 0; i < 10 ; i++) {
259acbb910aSAlan Tull 		reg = socfpga_a10_fpga_read_stat(priv);
260acbb910aSAlan Tull 
261acbb910aSAlan Tull 		if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_ERROR)
262acbb910aSAlan Tull 			return -EINVAL;
263acbb910aSAlan Tull 
264acbb910aSAlan Tull 		if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_DONE)
265acbb910aSAlan Tull 			return 0;
266acbb910aSAlan Tull 	}
267acbb910aSAlan Tull 
268acbb910aSAlan Tull 	return -ETIMEDOUT;
269acbb910aSAlan Tull }
270acbb910aSAlan Tull 
271acbb910aSAlan Tull /* Start the FPGA programming by initialize the FPGA Manager */
socfpga_a10_fpga_write_init(struct fpga_manager * mgr,struct fpga_image_info * info,const char * buf,size_t count)272acbb910aSAlan Tull static int socfpga_a10_fpga_write_init(struct fpga_manager *mgr,
273acbb910aSAlan Tull 				       struct fpga_image_info *info,
274acbb910aSAlan Tull 				       const char *buf, size_t count)
275acbb910aSAlan Tull {
276acbb910aSAlan Tull 	struct a10_fpga_priv *priv = mgr->priv;
277acbb910aSAlan Tull 	unsigned int cfg_width;
278acbb910aSAlan Tull 	u32 msel, stat, mask;
279acbb910aSAlan Tull 	int ret;
280acbb910aSAlan Tull 
281acbb910aSAlan Tull 	if (info->flags & FPGA_MGR_PARTIAL_RECONFIG)
282acbb910aSAlan Tull 		cfg_width = CFGWDTH_16;
283acbb910aSAlan Tull 	else
284acbb910aSAlan Tull 		return -EINVAL;
285acbb910aSAlan Tull 
286acbb910aSAlan Tull 	/* Check for passive parallel (msel == 000 or 001) */
287acbb910aSAlan Tull 	msel = socfpga_a10_fpga_read_stat(priv);
288acbb910aSAlan Tull 	msel &= A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_MASK;
289acbb910aSAlan Tull 	msel >>= A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_SHIFT;
290acbb910aSAlan Tull 	if ((msel != 0) && (msel != 1)) {
291acbb910aSAlan Tull 		dev_dbg(&mgr->dev, "Fail: invalid msel=%d\n", msel);
292acbb910aSAlan Tull 		return -EINVAL;
293acbb910aSAlan Tull 	}
294acbb910aSAlan Tull 
295acbb910aSAlan Tull 	/* Make sure no external devices are interfering */
296acbb910aSAlan Tull 	stat = socfpga_a10_fpga_read_stat(priv);
297acbb910aSAlan Tull 	mask = A10_FPGAMGR_IMGCFG_STAT_F2S_NCONFIG_PIN |
298acbb910aSAlan Tull 	       A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN;
299acbb910aSAlan Tull 	if ((stat & mask) != mask)
300acbb910aSAlan Tull 		return -EINVAL;
301acbb910aSAlan Tull 
302acbb910aSAlan Tull 	/* Set cfg width */
303acbb910aSAlan Tull 	socfpga_a10_fpga_set_cfg_width(priv, cfg_width);
304acbb910aSAlan Tull 
305acbb910aSAlan Tull 	/* Determine cd ratio from bitstream header and set cd ratio */
306acbb910aSAlan Tull 	ret = socfpga_a10_fpga_set_cdratio(mgr, cfg_width, buf, count);
307acbb910aSAlan Tull 	if (ret)
308acbb910aSAlan Tull 		return ret;
309acbb910aSAlan Tull 
310acbb910aSAlan Tull 	/*
311acbb910aSAlan Tull 	 * Clear s2f_nce to enable chip select.  Leave pr_request
312acbb910aSAlan Tull 	 * unasserted and override disabled.
313acbb910aSAlan Tull 	 */
314acbb910aSAlan Tull 	regmap_write(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,
315acbb910aSAlan Tull 		     A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG);
316acbb910aSAlan Tull 
317acbb910aSAlan Tull 	/* Set cfg_ctrl to enable s2f dclk and data */
318acbb910aSAlan Tull 	regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_02_OFST,
319acbb910aSAlan Tull 			   A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL,
320acbb910aSAlan Tull 			   A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL);
321acbb910aSAlan Tull 
322acbb910aSAlan Tull 	/*
323acbb910aSAlan Tull 	 * Disable overrides not needed for pr.
324acbb910aSAlan Tull 	 * s2f_config==1 leaves reset deasseted.
325acbb910aSAlan Tull 	 */
326acbb910aSAlan Tull 	regmap_write(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_00_OFST,
327acbb910aSAlan Tull 		     A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NCONFIG |
328acbb910aSAlan Tull 		     A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NSTATUS |
329acbb910aSAlan Tull 		     A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_CONDONE |
330acbb910aSAlan Tull 		     A10_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG);
331acbb910aSAlan Tull 
332acbb910aSAlan Tull 	/* Enable override for data, dclk, nce, and pr_request to CSS */
333acbb910aSAlan Tull 	regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,
334acbb910aSAlan Tull 			   A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG, 0);
335acbb910aSAlan Tull 
336acbb910aSAlan Tull 	/* Send some clocks to clear out any errors */
337acbb910aSAlan Tull 	socfpga_a10_fpga_generate_dclks(priv, 256);
338acbb910aSAlan Tull 
339acbb910aSAlan Tull 	/* Assert pr_request */
340acbb910aSAlan Tull 	regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,
341acbb910aSAlan Tull 			   A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST,
342acbb910aSAlan Tull 			   A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST);
343acbb910aSAlan Tull 
344acbb910aSAlan Tull 	/* Provide 2048 DCLKs before starting the config data streaming. */
345acbb910aSAlan Tull 	socfpga_a10_fpga_generate_dclks(priv, 0x7ff);
346acbb910aSAlan Tull 
347acbb910aSAlan Tull 	/* Wait for pr_ready */
348acbb910aSAlan Tull 	return socfpga_a10_fpga_wait_for_pr_ready(priv);
349acbb910aSAlan Tull }
350acbb910aSAlan Tull 
351acbb910aSAlan Tull /*
352acbb910aSAlan Tull  * write data to the FPGA data register
353acbb910aSAlan Tull  */
socfpga_a10_fpga_write(struct fpga_manager * mgr,const char * buf,size_t count)354acbb910aSAlan Tull static int socfpga_a10_fpga_write(struct fpga_manager *mgr, const char *buf,
355acbb910aSAlan Tull 				  size_t count)
356acbb910aSAlan Tull {
357acbb910aSAlan Tull 	struct a10_fpga_priv *priv = mgr->priv;
358acbb910aSAlan Tull 	u32 *buffer_32 = (u32 *)buf;
359acbb910aSAlan Tull 	size_t i = 0;
360acbb910aSAlan Tull 
361acbb910aSAlan Tull 	if (count <= 0)
362acbb910aSAlan Tull 		return -EINVAL;
363acbb910aSAlan Tull 
364acbb910aSAlan Tull 	/* Write out the complete 32-bit chunks */
365acbb910aSAlan Tull 	while (count >= sizeof(u32)) {
366acbb910aSAlan Tull 		writel(buffer_32[i++], priv->fpga_data_addr);
367acbb910aSAlan Tull 		count -= sizeof(u32);
368acbb910aSAlan Tull 	}
369acbb910aSAlan Tull 
370acbb910aSAlan Tull 	/* Write out remaining non 32-bit chunks */
371acbb910aSAlan Tull 	switch (count) {
372acbb910aSAlan Tull 	case 3:
373acbb910aSAlan Tull 		writel(buffer_32[i++] & 0x00ffffff, priv->fpga_data_addr);
374acbb910aSAlan Tull 		break;
375acbb910aSAlan Tull 	case 2:
376acbb910aSAlan Tull 		writel(buffer_32[i++] & 0x0000ffff, priv->fpga_data_addr);
377acbb910aSAlan Tull 		break;
378acbb910aSAlan Tull 	case 1:
379acbb910aSAlan Tull 		writel(buffer_32[i++] & 0x000000ff, priv->fpga_data_addr);
380acbb910aSAlan Tull 		break;
381acbb910aSAlan Tull 	case 0:
382acbb910aSAlan Tull 		break;
383acbb910aSAlan Tull 	default:
384acbb910aSAlan Tull 		/* This will never happen */
385acbb910aSAlan Tull 		return -EFAULT;
386acbb910aSAlan Tull 	}
387acbb910aSAlan Tull 
388acbb910aSAlan Tull 	return 0;
389acbb910aSAlan Tull }
390acbb910aSAlan Tull 
socfpga_a10_fpga_write_complete(struct fpga_manager * mgr,struct fpga_image_info * info)391acbb910aSAlan Tull static int socfpga_a10_fpga_write_complete(struct fpga_manager *mgr,
392acbb910aSAlan Tull 					   struct fpga_image_info *info)
393acbb910aSAlan Tull {
394acbb910aSAlan Tull 	struct a10_fpga_priv *priv = mgr->priv;
395acbb910aSAlan Tull 	u32 reg;
396acbb910aSAlan Tull 	int ret;
397acbb910aSAlan Tull 
398acbb910aSAlan Tull 	/* Wait for pr_done */
399acbb910aSAlan Tull 	ret = socfpga_a10_fpga_wait_for_pr_done(priv);
400acbb910aSAlan Tull 
401acbb910aSAlan Tull 	/* Clear pr_request */
402acbb910aSAlan Tull 	regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,
403acbb910aSAlan Tull 			   A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST, 0);
404acbb910aSAlan Tull 
405acbb910aSAlan Tull 	/* Send some clocks to clear out any errors */
406acbb910aSAlan Tull 	socfpga_a10_fpga_generate_dclks(priv, 256);
407acbb910aSAlan Tull 
408acbb910aSAlan Tull 	/* Disable s2f dclk and data */
409acbb910aSAlan Tull 	regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_02_OFST,
410acbb910aSAlan Tull 			   A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL, 0);
411acbb910aSAlan Tull 
412acbb910aSAlan Tull 	/* Deassert chip select */
413acbb910aSAlan Tull 	regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,
414acbb910aSAlan Tull 			   A10_FPGAMGR_IMGCFG_CTL_01_S2F_NCE,
415acbb910aSAlan Tull 			   A10_FPGAMGR_IMGCFG_CTL_01_S2F_NCE);
416acbb910aSAlan Tull 
417acbb910aSAlan Tull 	/* Disable data, dclk, nce, and pr_request override to CSS */
418acbb910aSAlan Tull 	regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,
419acbb910aSAlan Tull 			   A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG,
420acbb910aSAlan Tull 			   A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG);
421acbb910aSAlan Tull 
422acbb910aSAlan Tull 	/* Return any errors regarding pr_done or pr_error */
423acbb910aSAlan Tull 	if (ret)
424acbb910aSAlan Tull 		return ret;
425acbb910aSAlan Tull 
426acbb910aSAlan Tull 	/* Final check */
427acbb910aSAlan Tull 	reg = socfpga_a10_fpga_read_stat(priv);
428acbb910aSAlan Tull 
429acbb910aSAlan Tull 	if (((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_USERMODE) == 0) ||
430acbb910aSAlan Tull 	    ((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN) == 0) ||
431acbb910aSAlan Tull 	    ((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN) == 0)) {
432acbb910aSAlan Tull 		dev_dbg(&mgr->dev,
433acbb910aSAlan Tull 			"Timeout in final check. Status=%08xf\n", reg);
434acbb910aSAlan Tull 		return -ETIMEDOUT;
435acbb910aSAlan Tull 	}
436acbb910aSAlan Tull 
437acbb910aSAlan Tull 	return 0;
438acbb910aSAlan Tull }
439acbb910aSAlan Tull 
socfpga_a10_fpga_state(struct fpga_manager * mgr)440acbb910aSAlan Tull static enum fpga_mgr_states socfpga_a10_fpga_state(struct fpga_manager *mgr)
441acbb910aSAlan Tull {
442acbb910aSAlan Tull 	struct a10_fpga_priv *priv = mgr->priv;
443acbb910aSAlan Tull 	u32 reg = socfpga_a10_fpga_read_stat(priv);
444acbb910aSAlan Tull 
445acbb910aSAlan Tull 	if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_USERMODE)
446acbb910aSAlan Tull 		return FPGA_MGR_STATE_OPERATING;
447acbb910aSAlan Tull 
448acbb910aSAlan Tull 	if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_READY)
449acbb910aSAlan Tull 		return FPGA_MGR_STATE_WRITE;
450acbb910aSAlan Tull 
451acbb910aSAlan Tull 	if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_CRC_ERROR)
452acbb910aSAlan Tull 		return FPGA_MGR_STATE_WRITE_COMPLETE_ERR;
453acbb910aSAlan Tull 
454acbb910aSAlan Tull 	if ((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN) == 0)
455acbb910aSAlan Tull 		return FPGA_MGR_STATE_RESET;
456acbb910aSAlan Tull 
457acbb910aSAlan Tull 	return FPGA_MGR_STATE_UNKNOWN;
458acbb910aSAlan Tull }
459acbb910aSAlan Tull 
460acbb910aSAlan Tull static const struct fpga_manager_ops socfpga_a10_fpga_mgr_ops = {
4611d7f1589SJason Gunthorpe 	.initial_header_size = (RBF_DECOMPRESS_OFFSET + 1) * 4,
462acbb910aSAlan Tull 	.state = socfpga_a10_fpga_state,
463acbb910aSAlan Tull 	.write_init = socfpga_a10_fpga_write_init,
464acbb910aSAlan Tull 	.write = socfpga_a10_fpga_write,
465acbb910aSAlan Tull 	.write_complete = socfpga_a10_fpga_write_complete,
466acbb910aSAlan Tull };
467acbb910aSAlan Tull 
socfpga_a10_fpga_probe(struct platform_device * pdev)468acbb910aSAlan Tull static int socfpga_a10_fpga_probe(struct platform_device *pdev)
469acbb910aSAlan Tull {
470acbb910aSAlan Tull 	struct device *dev = &pdev->dev;
471acbb910aSAlan Tull 	struct a10_fpga_priv *priv;
472acbb910aSAlan Tull 	void __iomem *reg_base;
4737085e2a9SAlan Tull 	struct fpga_manager *mgr;
474acbb910aSAlan Tull 	int ret;
475acbb910aSAlan Tull 
476acbb910aSAlan Tull 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
477acbb910aSAlan Tull 	if (!priv)
478acbb910aSAlan Tull 		return -ENOMEM;
479acbb910aSAlan Tull 
480acbb910aSAlan Tull 	/* First mmio base is for register access */
481*dbe5038aSYangtao Li 	reg_base = devm_platform_ioremap_resource(pdev, 0);
482acbb910aSAlan Tull 	if (IS_ERR(reg_base))
483acbb910aSAlan Tull 		return PTR_ERR(reg_base);
484acbb910aSAlan Tull 
485acbb910aSAlan Tull 	/* Second mmio base is for writing FPGA image data */
486*dbe5038aSYangtao Li 	priv->fpga_data_addr = devm_platform_ioremap_resource(pdev, 1);
487acbb910aSAlan Tull 	if (IS_ERR(priv->fpga_data_addr))
488acbb910aSAlan Tull 		return PTR_ERR(priv->fpga_data_addr);
489acbb910aSAlan Tull 
490acbb910aSAlan Tull 	/* regmap for register access */
491acbb910aSAlan Tull 	priv->regmap = devm_regmap_init_mmio(dev, reg_base,
492acbb910aSAlan Tull 					     &socfpga_a10_fpga_regmap_config);
493acbb910aSAlan Tull 	if (IS_ERR(priv->regmap))
494acbb910aSAlan Tull 		return -ENODEV;
495acbb910aSAlan Tull 
496acbb910aSAlan Tull 	priv->clk = devm_clk_get(dev, NULL);
497acbb910aSAlan Tull 	if (IS_ERR(priv->clk)) {
498acbb910aSAlan Tull 		dev_err(dev, "no clock specified\n");
499acbb910aSAlan Tull 		return PTR_ERR(priv->clk);
500acbb910aSAlan Tull 	}
501acbb910aSAlan Tull 
502acbb910aSAlan Tull 	ret = clk_prepare_enable(priv->clk);
503acbb910aSAlan Tull 	if (ret) {
504acbb910aSAlan Tull 		dev_err(dev, "could not enable clock\n");
505acbb910aSAlan Tull 		return -EBUSY;
506acbb910aSAlan Tull 	}
507acbb910aSAlan Tull 
5084ba0b2c2SRuss Weight 	mgr = fpga_mgr_register(dev, "SoCFPGA Arria10 FPGA Manager",
509acbb910aSAlan Tull 				&socfpga_a10_fpga_mgr_ops, priv);
5104ba0b2c2SRuss Weight 	if (IS_ERR(mgr)) {
5114ba0b2c2SRuss Weight 		clk_disable_unprepare(priv->clk);
5124ba0b2c2SRuss Weight 		return PTR_ERR(mgr);
5134ba0b2c2SRuss Weight 	}
5147085e2a9SAlan Tull 
5157085e2a9SAlan Tull 	platform_set_drvdata(pdev, mgr);
5167085e2a9SAlan Tull 
517d9cc5a0eSAlexey Khoroshilov 	return 0;
518acbb910aSAlan Tull }
519acbb910aSAlan Tull 
socfpga_a10_fpga_remove(struct platform_device * pdev)520acbb910aSAlan Tull static int socfpga_a10_fpga_remove(struct platform_device *pdev)
521acbb910aSAlan Tull {
522acbb910aSAlan Tull 	struct fpga_manager *mgr = platform_get_drvdata(pdev);
523acbb910aSAlan Tull 	struct a10_fpga_priv *priv = mgr->priv;
524acbb910aSAlan Tull 
5257085e2a9SAlan Tull 	fpga_mgr_unregister(mgr);
526acbb910aSAlan Tull 	clk_disable_unprepare(priv->clk);
527acbb910aSAlan Tull 
528acbb910aSAlan Tull 	return 0;
529acbb910aSAlan Tull }
530acbb910aSAlan Tull 
531acbb910aSAlan Tull static const struct of_device_id socfpga_a10_fpga_of_match[] = {
532acbb910aSAlan Tull 	{ .compatible = "altr,socfpga-a10-fpga-mgr", },
533acbb910aSAlan Tull 	{},
534acbb910aSAlan Tull };
535acbb910aSAlan Tull 
536acbb910aSAlan Tull MODULE_DEVICE_TABLE(of, socfpga_a10_fpga_of_match);
537acbb910aSAlan Tull 
538acbb910aSAlan Tull static struct platform_driver socfpga_a10_fpga_driver = {
539acbb910aSAlan Tull 	.probe = socfpga_a10_fpga_probe,
540acbb910aSAlan Tull 	.remove = socfpga_a10_fpga_remove,
541acbb910aSAlan Tull 	.driver = {
542acbb910aSAlan Tull 		.name	= "socfpga_a10_fpga_manager",
543acbb910aSAlan Tull 		.of_match_table = socfpga_a10_fpga_of_match,
544acbb910aSAlan Tull 	},
545acbb910aSAlan Tull };
546acbb910aSAlan Tull 
547acbb910aSAlan Tull module_platform_driver(socfpga_a10_fpga_driver);
548acbb910aSAlan Tull 
549acbb910aSAlan Tull MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
550acbb910aSAlan Tull MODULE_DESCRIPTION("SoCFPGA Arria10 FPGA Manager");
551acbb910aSAlan Tull MODULE_LICENSE("GPL v2");
552