Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  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");