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