Linux Audio

Check our new training course

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