diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-05 19:20:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-05 19:20:22 -0400 |
commit | abf7dba7c4f77d781f6df50fefb19a64c5dc331f (patch) | |
tree | 38648731b502d5aec508f3b33f6616190e598eb6 /drivers/fpga | |
parent | 07c4dd3435aa387d3b58f4e941dc516513f14507 (diff) | |
parent | b23220fe054e92f616b82450fae8cd3ab176cc60 (diff) |
Merge tag 'char-misc-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver updates from Greg KH:
"Here is the "big" char and misc driver patches for 4.18-rc1.
It's not a lot of stuff here, but there are some highlights:
- coreboot driver updates
- soundwire driver updates
- android binder updates
- fpga big sync, mostly documentation
- lots of minor driver updates
All of these have been in linux-next for a while with no reported
issues"
* tag 'char-misc-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (81 commits)
vmw_balloon: fixing double free when batching mode is off
MAINTAINERS: Add driver-api/fpga path
fpga: clarify that unregister functions also free
documentation: fpga: move fpga-region.txt to driver-api
documentation: fpga: add bridge document to driver-api
documentation: fpga: move fpga-mgr.txt to driver-api
Documentation: fpga: move fpga overview to driver-api
fpga: region: kernel-doc fixes
fpga: bridge: kernel-doc fixes
fpga: mgr: kernel-doc fixes
fpga: use SPDX
fpga: region: change api, add fpga_region_create/free
fpga: bridge: change api, don't use drvdata
fpga: manager: change api, don't use drvdata
fpga: region: don't use drvdata in common fpga code
Drivers: hv: vmbus: Removed an unnecessary cast from void *
ver_linux: Drop redundant calls to system() to test if file is readable
ver_linux: Move stderr redirection from function parameter to function body
misc: IBM Virtual Management Channel Driver (VMC)
rpmsg: Correct support for MODULE_DEVICE_TABLE()
...
Diffstat (limited to 'drivers/fpga')
-rw-r--r-- | drivers/fpga/Kconfig | 8 | ||||
-rw-r--r-- | drivers/fpga/Makefile | 1 | ||||
-rw-r--r-- | drivers/fpga/altera-cvp.c | 19 | ||||
-rw-r--r-- | drivers/fpga/altera-fpga2sdram.c | 34 | ||||
-rw-r--r-- | drivers/fpga/altera-freeze-bridge.c | 35 | ||||
-rw-r--r-- | drivers/fpga/altera-hps2fpga.c | 37 | ||||
-rw-r--r-- | drivers/fpga/altera-pr-ip-core-plat.c | 13 | ||||
-rw-r--r-- | drivers/fpga/altera-pr-ip-core.c | 31 | ||||
-rw-r--r-- | drivers/fpga/altera-ps-spi.c | 20 | ||||
-rw-r--r-- | drivers/fpga/fpga-bridge.c | 86 | ||||
-rw-r--r-- | drivers/fpga/fpga-mgr.c | 129 | ||||
-rw-r--r-- | drivers/fpga/fpga-region.c | 91 | ||||
-rw-r--r-- | drivers/fpga/ice40-spi.c | 21 | ||||
-rw-r--r-- | drivers/fpga/machxo2-spi.c | 415 | ||||
-rw-r--r-- | drivers/fpga/of-fpga-region.c | 28 | ||||
-rw-r--r-- | drivers/fpga/socfpga-a10.c | 28 | ||||
-rw-r--r-- | drivers/fpga/socfpga.c | 32 | ||||
-rw-r--r-- | drivers/fpga/ts73xx-fpga.c | 20 | ||||
-rw-r--r-- | drivers/fpga/xilinx-pr-decoupler.c | 22 | ||||
-rw-r--r-- | drivers/fpga/xilinx-spi.c | 20 | ||||
-rw-r--r-- | drivers/fpga/zynq-fpga.c | 14 |
21 files changed, 839 insertions, 265 deletions
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index f47ef848bcd0..ee9c5420c47f 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig | |||
@@ -53,7 +53,6 @@ config FPGA_MGR_ALTERA_CVP | |||
53 | config FPGA_MGR_ZYNQ_FPGA | 53 | config FPGA_MGR_ZYNQ_FPGA |
54 | tristate "Xilinx Zynq FPGA" | 54 | tristate "Xilinx Zynq FPGA" |
55 | depends on ARCH_ZYNQ || COMPILE_TEST | 55 | depends on ARCH_ZYNQ || COMPILE_TEST |
56 | depends on HAS_DMA | ||
57 | help | 56 | help |
58 | FPGA manager driver support for Xilinx Zynq FPGAs. | 57 | FPGA manager driver support for Xilinx Zynq FPGAs. |
59 | 58 | ||
@@ -70,6 +69,13 @@ config FPGA_MGR_ICE40_SPI | |||
70 | help | 69 | help |
71 | FPGA manager driver support for Lattice iCE40 FPGAs over SPI. | 70 | FPGA manager driver support for Lattice iCE40 FPGAs over SPI. |
72 | 71 | ||
72 | config FPGA_MGR_MACHXO2_SPI | ||
73 | tristate "Lattice MachXO2 SPI" | ||
74 | depends on SPI | ||
75 | help | ||
76 | FPGA manager driver support for Lattice MachXO2 configuration | ||
77 | over slave SPI interface. | ||
78 | |||
73 | config FPGA_MGR_TS73XX | 79 | config FPGA_MGR_TS73XX |
74 | tristate "Technologic Systems TS-73xx SBC FPGA Manager" | 80 | tristate "Technologic Systems TS-73xx SBC FPGA Manager" |
75 | depends on ARCH_EP93XX && MACH_TS72XX | 81 | depends on ARCH_EP93XX && MACH_TS72XX |
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index 3cb276a0f88d..f9803dad6919 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile | |||
@@ -10,6 +10,7 @@ obj-$(CONFIG_FPGA) += fpga-mgr.o | |||
10 | obj-$(CONFIG_FPGA_MGR_ALTERA_CVP) += altera-cvp.o | 10 | obj-$(CONFIG_FPGA_MGR_ALTERA_CVP) += altera-cvp.o |
11 | obj-$(CONFIG_FPGA_MGR_ALTERA_PS_SPI) += altera-ps-spi.o | 11 | obj-$(CONFIG_FPGA_MGR_ALTERA_PS_SPI) += altera-ps-spi.o |
12 | obj-$(CONFIG_FPGA_MGR_ICE40_SPI) += ice40-spi.o | 12 | obj-$(CONFIG_FPGA_MGR_ICE40_SPI) += ice40-spi.o |
13 | obj-$(CONFIG_FPGA_MGR_MACHXO2_SPI) += machxo2-spi.o | ||
13 | obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o | 14 | obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o |
14 | obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += socfpga-a10.o | 15 | obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += socfpga-a10.o |
15 | obj-$(CONFIG_FPGA_MGR_TS73XX) += ts73xx-fpga.o | 16 | obj-$(CONFIG_FPGA_MGR_TS73XX) += ts73xx-fpga.o |
diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c index 77b04e4b3254..dd4edd8f22ce 100644 --- a/drivers/fpga/altera-cvp.c +++ b/drivers/fpga/altera-cvp.c | |||
@@ -401,6 +401,7 @@ static int altera_cvp_probe(struct pci_dev *pdev, | |||
401 | const struct pci_device_id *dev_id) | 401 | const struct pci_device_id *dev_id) |
402 | { | 402 | { |
403 | struct altera_cvp_conf *conf; | 403 | struct altera_cvp_conf *conf; |
404 | struct fpga_manager *mgr; | ||
404 | u16 cmd, val; | 405 | u16 cmd, val; |
405 | int ret; | 406 | int ret; |
406 | 407 | ||
@@ -452,16 +453,24 @@ static int altera_cvp_probe(struct pci_dev *pdev, | |||
452 | snprintf(conf->mgr_name, sizeof(conf->mgr_name), "%s @%s", | 453 | snprintf(conf->mgr_name, sizeof(conf->mgr_name), "%s @%s", |
453 | ALTERA_CVP_MGR_NAME, pci_name(pdev)); | 454 | ALTERA_CVP_MGR_NAME, pci_name(pdev)); |
454 | 455 | ||
455 | ret = fpga_mgr_register(&pdev->dev, conf->mgr_name, | 456 | mgr = fpga_mgr_create(&pdev->dev, conf->mgr_name, |
456 | &altera_cvp_ops, conf); | 457 | &altera_cvp_ops, conf); |
457 | if (ret) | 458 | if (!mgr) |
459 | return -ENOMEM; | ||
460 | |||
461 | pci_set_drvdata(pdev, mgr); | ||
462 | |||
463 | ret = fpga_mgr_register(mgr); | ||
464 | if (ret) { | ||
465 | fpga_mgr_free(mgr); | ||
458 | goto err_unmap; | 466 | goto err_unmap; |
467 | } | ||
459 | 468 | ||
460 | ret = driver_create_file(&altera_cvp_driver.driver, | 469 | ret = driver_create_file(&altera_cvp_driver.driver, |
461 | &driver_attr_chkcfg); | 470 | &driver_attr_chkcfg); |
462 | if (ret) { | 471 | if (ret) { |
463 | dev_err(&pdev->dev, "Can't create sysfs chkcfg file\n"); | 472 | dev_err(&pdev->dev, "Can't create sysfs chkcfg file\n"); |
464 | fpga_mgr_unregister(&pdev->dev); | 473 | fpga_mgr_unregister(mgr); |
465 | goto err_unmap; | 474 | goto err_unmap; |
466 | } | 475 | } |
467 | 476 | ||
@@ -483,7 +492,7 @@ static void altera_cvp_remove(struct pci_dev *pdev) | |||
483 | u16 cmd; | 492 | u16 cmd; |
484 | 493 | ||
485 | driver_remove_file(&altera_cvp_driver.driver, &driver_attr_chkcfg); | 494 | driver_remove_file(&altera_cvp_driver.driver, &driver_attr_chkcfg); |
486 | fpga_mgr_unregister(&pdev->dev); | 495 | fpga_mgr_unregister(mgr); |
487 | pci_iounmap(pdev, conf->map); | 496 | pci_iounmap(pdev, conf->map); |
488 | pci_release_region(pdev, CVP_BAR); | 497 | pci_release_region(pdev, CVP_BAR); |
489 | pci_read_config_word(pdev, PCI_COMMAND, &cmd); | 498 | pci_read_config_word(pdev, PCI_COMMAND, &cmd); |
diff --git a/drivers/fpga/altera-fpga2sdram.c b/drivers/fpga/altera-fpga2sdram.c index d4eeb74388da..23660ccd634b 100644 --- a/drivers/fpga/altera-fpga2sdram.c +++ b/drivers/fpga/altera-fpga2sdram.c | |||
@@ -1,19 +1,8 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * FPGA to SDRAM Bridge Driver for Altera SoCFPGA Devices | 3 | * FPGA to SDRAM Bridge Driver for Altera SoCFPGA Devices |
3 | * | 4 | * |
4 | * Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved. | 5 | * Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved. |
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 | */ | 6 | */ |
18 | 7 | ||
19 | /* | 8 | /* |
@@ -106,6 +95,7 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) | |||
106 | { | 95 | { |
107 | struct device *dev = &pdev->dev; | 96 | struct device *dev = &pdev->dev; |
108 | struct alt_fpga2sdram_data *priv; | 97 | struct alt_fpga2sdram_data *priv; |
98 | struct fpga_bridge *br; | ||
109 | u32 enable; | 99 | u32 enable; |
110 | struct regmap *sysmgr; | 100 | struct regmap *sysmgr; |
111 | int ret = 0; | 101 | int ret = 0; |
@@ -131,10 +121,18 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) | |||
131 | /* Get f2s bridge configuration saved in handoff register */ | 121 | /* Get f2s bridge configuration saved in handoff register */ |
132 | regmap_read(sysmgr, SYSMGR_ISWGRP_HANDOFF3, &priv->mask); | 122 | regmap_read(sysmgr, SYSMGR_ISWGRP_HANDOFF3, &priv->mask); |
133 | 123 | ||
134 | ret = fpga_bridge_register(dev, F2S_BRIDGE_NAME, | 124 | br = fpga_bridge_create(dev, F2S_BRIDGE_NAME, |
135 | &altera_fpga2sdram_br_ops, priv); | 125 | &altera_fpga2sdram_br_ops, priv); |
136 | if (ret) | 126 | if (!br) |
127 | return -ENOMEM; | ||
128 | |||
129 | platform_set_drvdata(pdev, br); | ||
130 | |||
131 | ret = fpga_bridge_register(br); | ||
132 | if (ret) { | ||
133 | fpga_bridge_free(br); | ||
137 | return ret; | 134 | return ret; |
135 | } | ||
138 | 136 | ||
139 | dev_info(dev, "driver initialized with handoff %08x\n", priv->mask); | 137 | dev_info(dev, "driver initialized with handoff %08x\n", priv->mask); |
140 | 138 | ||
@@ -146,7 +144,7 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) | |||
146 | (enable ? "enabling" : "disabling")); | 144 | (enable ? "enabling" : "disabling")); |
147 | ret = _alt_fpga2sdram_enable_set(priv, enable); | 145 | ret = _alt_fpga2sdram_enable_set(priv, enable); |
148 | if (ret) { | 146 | if (ret) { |
149 | fpga_bridge_unregister(&pdev->dev); | 147 | fpga_bridge_unregister(br); |
150 | return ret; | 148 | return ret; |
151 | } | 149 | } |
152 | } | 150 | } |
@@ -157,7 +155,9 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) | |||
157 | 155 | ||
158 | static int alt_fpga_bridge_remove(struct platform_device *pdev) | 156 | static int alt_fpga_bridge_remove(struct platform_device *pdev) |
159 | { | 157 | { |
160 | fpga_bridge_unregister(&pdev->dev); | 158 | struct fpga_bridge *br = platform_get_drvdata(pdev); |
159 | |||
160 | fpga_bridge_unregister(br); | ||
161 | 161 | ||
162 | return 0; | 162 | return 0; |
163 | } | 163 | } |
diff --git a/drivers/fpga/altera-freeze-bridge.c b/drivers/fpga/altera-freeze-bridge.c index 6159cfcf78a2..ffd586c48ecf 100644 --- a/drivers/fpga/altera-freeze-bridge.c +++ b/drivers/fpga/altera-freeze-bridge.c | |||
@@ -1,19 +1,8 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * FPGA Freeze Bridge Controller | 3 | * FPGA Freeze Bridge Controller |
3 | * | 4 | * |
4 | * Copyright (C) 2016 Altera Corporation. All rights reserved. | 5 | * Copyright (C) 2016 Altera Corporation. All rights reserved. |
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 | */ | 6 | */ |
18 | #include <linux/delay.h> | 7 | #include <linux/delay.h> |
19 | #include <linux/io.h> | 8 | #include <linux/io.h> |
@@ -221,8 +210,10 @@ static int altera_freeze_br_probe(struct platform_device *pdev) | |||
221 | struct device_node *np = pdev->dev.of_node; | 210 | struct device_node *np = pdev->dev.of_node; |
222 | void __iomem *base_addr; | 211 | void __iomem *base_addr; |
223 | struct altera_freeze_br_data *priv; | 212 | struct altera_freeze_br_data *priv; |
213 | struct fpga_bridge *br; | ||
224 | struct resource *res; | 214 | struct resource *res; |
225 | u32 status, revision; | 215 | u32 status, revision; |
216 | int ret; | ||
226 | 217 | ||
227 | if (!np) | 218 | if (!np) |
228 | return -ENODEV; | 219 | return -ENODEV; |
@@ -254,13 +245,27 @@ static int altera_freeze_br_probe(struct platform_device *pdev) | |||
254 | 245 | ||
255 | priv->base_addr = base_addr; | 246 | priv->base_addr = base_addr; |
256 | 247 | ||
257 | return fpga_bridge_register(dev, FREEZE_BRIDGE_NAME, | 248 | br = fpga_bridge_create(dev, FREEZE_BRIDGE_NAME, |
258 | &altera_freeze_br_br_ops, priv); | 249 | &altera_freeze_br_br_ops, priv); |
250 | if (!br) | ||
251 | return -ENOMEM; | ||
252 | |||
253 | platform_set_drvdata(pdev, br); | ||
254 | |||
255 | ret = fpga_bridge_register(br); | ||
256 | if (ret) { | ||
257 | fpga_bridge_free(br); | ||
258 | return ret; | ||
259 | } | ||
260 | |||
261 | return 0; | ||
259 | } | 262 | } |
260 | 263 | ||
261 | static int altera_freeze_br_remove(struct platform_device *pdev) | 264 | static int altera_freeze_br_remove(struct platform_device *pdev) |
262 | { | 265 | { |
263 | fpga_bridge_unregister(&pdev->dev); | 266 | struct fpga_bridge *br = platform_get_drvdata(pdev); |
267 | |||
268 | fpga_bridge_unregister(br); | ||
264 | 269 | ||
265 | return 0; | 270 | return 0; |
266 | } | 271 | } |
diff --git a/drivers/fpga/altera-hps2fpga.c b/drivers/fpga/altera-hps2fpga.c index 406d2f10741f..a974d3f60321 100644 --- a/drivers/fpga/altera-hps2fpga.c +++ b/drivers/fpga/altera-hps2fpga.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * FPGA to/from HPS Bridge Driver for Altera SoCFPGA Devices | 3 | * FPGA to/from HPS Bridge Driver for Altera SoCFPGA Devices |
3 | * | 4 | * |
@@ -6,18 +7,6 @@ | |||
6 | * Includes this patch from the mailing list: | 7 | * Includes this patch from the mailing list: |
7 | * fpga: altera-hps2fpga: fix HPS2FPGA bridge visibility to L3 masters | 8 | * fpga: altera-hps2fpga: fix HPS2FPGA bridge visibility to L3 masters |
8 | * Signed-off-by: Anatolij Gustschin <agust@denx.de> | 9 | * Signed-off-by: Anatolij Gustschin <agust@denx.de> |
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms and conditions of the GNU General Public License, | ||
12 | * version 2, as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
17 | * more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along with | ||
20 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
21 | */ | 10 | */ |
22 | 11 | ||
23 | /* | 12 | /* |
@@ -139,6 +128,7 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) | |||
139 | struct device *dev = &pdev->dev; | 128 | struct device *dev = &pdev->dev; |
140 | struct altera_hps2fpga_data *priv; | 129 | struct altera_hps2fpga_data *priv; |
141 | const struct of_device_id *of_id; | 130 | const struct of_device_id *of_id; |
131 | struct fpga_bridge *br; | ||
142 | u32 enable; | 132 | u32 enable; |
143 | int ret; | 133 | int ret; |
144 | 134 | ||
@@ -190,11 +180,24 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) | |||
190 | } | 180 | } |
191 | } | 181 | } |
192 | 182 | ||
193 | ret = fpga_bridge_register(dev, priv->name, &altera_hps2fpga_br_ops, | 183 | br = fpga_bridge_create(dev, priv->name, &altera_hps2fpga_br_ops, priv); |
194 | priv); | 184 | if (!br) { |
195 | err: | 185 | ret = -ENOMEM; |
186 | goto err; | ||
187 | } | ||
188 | |||
189 | platform_set_drvdata(pdev, br); | ||
190 | |||
191 | ret = fpga_bridge_register(br); | ||
196 | if (ret) | 192 | if (ret) |
197 | clk_disable_unprepare(priv->clk); | 193 | goto err_free; |
194 | |||
195 | return 0; | ||
196 | |||
197 | err_free: | ||
198 | fpga_bridge_free(br); | ||
199 | err: | ||
200 | clk_disable_unprepare(priv->clk); | ||
198 | 201 | ||
199 | return ret; | 202 | return ret; |
200 | } | 203 | } |
@@ -204,7 +207,7 @@ static int alt_fpga_bridge_remove(struct platform_device *pdev) | |||
204 | struct fpga_bridge *bridge = platform_get_drvdata(pdev); | 207 | struct fpga_bridge *bridge = platform_get_drvdata(pdev); |
205 | struct altera_hps2fpga_data *priv = bridge->priv; | 208 | struct altera_hps2fpga_data *priv = bridge->priv; |
206 | 209 | ||
207 | fpga_bridge_unregister(&pdev->dev); | 210 | fpga_bridge_unregister(bridge); |
208 | 211 | ||
209 | clk_disable_unprepare(priv->clk); | 212 | clk_disable_unprepare(priv->clk); |
210 | 213 | ||
diff --git a/drivers/fpga/altera-pr-ip-core-plat.c b/drivers/fpga/altera-pr-ip-core-plat.c index 8fb36b8b4648..b293d83143f1 100644 --- a/drivers/fpga/altera-pr-ip-core-plat.c +++ b/drivers/fpga/altera-pr-ip-core-plat.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Driver for Altera Partial Reconfiguration IP Core | 3 | * Driver for Altera Partial Reconfiguration IP Core |
3 | * | 4 | * |
@@ -5,18 +6,6 @@ | |||
5 | * | 6 | * |
6 | * Based on socfpga-a10.c Copyright (C) 2015-2016 Altera Corporation | 7 | * Based on socfpga-a10.c Copyright (C) 2015-2016 Altera Corporation |
7 | * by Alan Tull <atull@opensource.altera.com> | 8 | * by Alan Tull <atull@opensource.altera.com> |
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms and conditions of the GNU General Public License, | ||
11 | * version 2, as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | */ | 9 | */ |
21 | #include <linux/fpga/altera-pr-ip-core.h> | 10 | #include <linux/fpga/altera-pr-ip-core.h> |
22 | #include <linux/module.h> | 11 | #include <linux/module.h> |
diff --git a/drivers/fpga/altera-pr-ip-core.c b/drivers/fpga/altera-pr-ip-core.c index a7b31f9797ce..65e0b6a2c031 100644 --- a/drivers/fpga/altera-pr-ip-core.c +++ b/drivers/fpga/altera-pr-ip-core.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Driver for Altera Partial Reconfiguration IP Core | 3 | * Driver for Altera Partial Reconfiguration IP Core |
3 | * | 4 | * |
@@ -5,18 +6,6 @@ | |||
5 | * | 6 | * |
6 | * Based on socfpga-a10.c Copyright (C) 2015-2016 Altera Corporation | 7 | * Based on socfpga-a10.c Copyright (C) 2015-2016 Altera Corporation |
7 | * by Alan Tull <atull@opensource.altera.com> | 8 | * by Alan Tull <atull@opensource.altera.com> |
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms and conditions of the GNU General Public License, | ||
11 | * version 2, as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | */ | 9 | */ |
21 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
22 | #include <linux/fpga/altera-pr-ip-core.h> | 11 | #include <linux/fpga/altera-pr-ip-core.h> |
@@ -187,6 +176,8 @@ static const struct fpga_manager_ops alt_pr_ops = { | |||
187 | int alt_pr_register(struct device *dev, void __iomem *reg_base) | 176 | int alt_pr_register(struct device *dev, void __iomem *reg_base) |
188 | { | 177 | { |
189 | struct alt_pr_priv *priv; | 178 | struct alt_pr_priv *priv; |
179 | struct fpga_manager *mgr; | ||
180 | int ret; | ||
190 | u32 val; | 181 | u32 val; |
191 | 182 | ||
192 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | 183 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
@@ -201,15 +192,27 @@ int alt_pr_register(struct device *dev, void __iomem *reg_base) | |||
201 | (val & ALT_PR_CSR_STATUS_MSK) >> ALT_PR_CSR_STATUS_SFT, | 192 | (val & ALT_PR_CSR_STATUS_MSK) >> ALT_PR_CSR_STATUS_SFT, |
202 | (int)(val & ALT_PR_CSR_PR_START)); | 193 | (int)(val & ALT_PR_CSR_PR_START)); |
203 | 194 | ||
204 | return fpga_mgr_register(dev, dev_name(dev), &alt_pr_ops, priv); | 195 | mgr = fpga_mgr_create(dev, dev_name(dev), &alt_pr_ops, priv); |
196 | if (!mgr) | ||
197 | return -ENOMEM; | ||
198 | |||
199 | dev_set_drvdata(dev, mgr); | ||
200 | |||
201 | ret = fpga_mgr_register(mgr); | ||
202 | if (ret) | ||
203 | fpga_mgr_free(mgr); | ||
204 | |||
205 | return ret; | ||
205 | } | 206 | } |
206 | EXPORT_SYMBOL_GPL(alt_pr_register); | 207 | EXPORT_SYMBOL_GPL(alt_pr_register); |
207 | 208 | ||
208 | int alt_pr_unregister(struct device *dev) | 209 | int alt_pr_unregister(struct device *dev) |
209 | { | 210 | { |
211 | struct fpga_manager *mgr = dev_get_drvdata(dev); | ||
212 | |||
210 | dev_dbg(dev, "%s\n", __func__); | 213 | dev_dbg(dev, "%s\n", __func__); |
211 | 214 | ||
212 | fpga_mgr_unregister(dev); | 215 | fpga_mgr_unregister(mgr); |
213 | 216 | ||
214 | return 0; | 217 | return 0; |
215 | } | 218 | } |
diff --git a/drivers/fpga/altera-ps-spi.c b/drivers/fpga/altera-ps-spi.c index 06d212a3d49d..24b25c626036 100644 --- a/drivers/fpga/altera-ps-spi.c +++ b/drivers/fpga/altera-ps-spi.c | |||
@@ -238,6 +238,8 @@ static int altera_ps_probe(struct spi_device *spi) | |||
238 | { | 238 | { |
239 | struct altera_ps_conf *conf; | 239 | struct altera_ps_conf *conf; |
240 | const struct of_device_id *of_id; | 240 | const struct of_device_id *of_id; |
241 | struct fpga_manager *mgr; | ||
242 | int ret; | ||
241 | 243 | ||
242 | conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL); | 244 | conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL); |
243 | if (!conf) | 245 | if (!conf) |
@@ -273,13 +275,25 @@ static int altera_ps_probe(struct spi_device *spi) | |||
273 | snprintf(conf->mgr_name, sizeof(conf->mgr_name), "%s %s", | 275 | snprintf(conf->mgr_name, sizeof(conf->mgr_name), "%s %s", |
274 | dev_driver_string(&spi->dev), dev_name(&spi->dev)); | 276 | dev_driver_string(&spi->dev), dev_name(&spi->dev)); |
275 | 277 | ||
276 | return fpga_mgr_register(&spi->dev, conf->mgr_name, | 278 | mgr = fpga_mgr_create(&spi->dev, conf->mgr_name, |
277 | &altera_ps_ops, conf); | 279 | &altera_ps_ops, conf); |
280 | if (!mgr) | ||
281 | return -ENOMEM; | ||
282 | |||
283 | spi_set_drvdata(spi, mgr); | ||
284 | |||
285 | ret = fpga_mgr_register(mgr); | ||
286 | if (ret) | ||
287 | fpga_mgr_free(mgr); | ||
288 | |||
289 | return ret; | ||
278 | } | 290 | } |
279 | 291 | ||
280 | static int altera_ps_remove(struct spi_device *spi) | 292 | static int altera_ps_remove(struct spi_device *spi) |
281 | { | 293 | { |
282 | fpga_mgr_unregister(&spi->dev); | 294 | struct fpga_manager *mgr = spi_get_drvdata(spi); |
295 | |||
296 | fpga_mgr_unregister(mgr); | ||
283 | 297 | ||
284 | return 0; | 298 | return 0; |
285 | } | 299 | } |
diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c index 31bd2c59c305..24b8f98b73ec 100644 --- a/drivers/fpga/fpga-bridge.c +++ b/drivers/fpga/fpga-bridge.c | |||
@@ -1,20 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * FPGA Bridge Framework Driver | 3 | * FPGA Bridge Framework Driver |
3 | * | 4 | * |
4 | * Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved. | 5 | * Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved. |
5 | * Copyright (C) 2017 Intel Corporation | 6 | * Copyright (C) 2017 Intel Corporation |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms and conditions of the GNU General Public License, | ||
9 | * version 2, as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | 7 | */ |
19 | #include <linux/fpga/fpga-bridge.h> | 8 | #include <linux/fpga/fpga-bridge.h> |
20 | #include <linux/idr.h> | 9 | #include <linux/idr.h> |
@@ -132,6 +121,7 @@ static int fpga_bridge_dev_match(struct device *dev, const void *data) | |||
132 | /** | 121 | /** |
133 | * fpga_bridge_get - get an exclusive reference to a fpga bridge | 122 | * fpga_bridge_get - get an exclusive reference to a fpga bridge |
134 | * @dev: parent device that fpga bridge was registered with | 123 | * @dev: parent device that fpga bridge was registered with |
124 | * @info: fpga manager info | ||
135 | * | 125 | * |
136 | * Given a device, get an exclusive reference to a fpga bridge. | 126 | * Given a device, get an exclusive reference to a fpga bridge. |
137 | * | 127 | * |
@@ -328,28 +318,29 @@ static struct attribute *fpga_bridge_attrs[] = { | |||
328 | ATTRIBUTE_GROUPS(fpga_bridge); | 318 | ATTRIBUTE_GROUPS(fpga_bridge); |
329 | 319 | ||
330 | /** | 320 | /** |
331 | * fpga_bridge_register - register a fpga bridge driver | 321 | * fpga_bridge_create - create and initialize a struct fpga_bridge |
332 | * @dev: FPGA bridge device from pdev | 322 | * @dev: FPGA bridge device from pdev |
333 | * @name: FPGA bridge name | 323 | * @name: FPGA bridge name |
334 | * @br_ops: pointer to structure of fpga bridge ops | 324 | * @br_ops: pointer to structure of fpga bridge ops |
335 | * @priv: FPGA bridge private data | 325 | * @priv: FPGA bridge private data |
336 | * | 326 | * |
337 | * Return: 0 for success, error code otherwise. | 327 | * Return: struct fpga_bridge or NULL |
338 | */ | 328 | */ |
339 | int fpga_bridge_register(struct device *dev, const char *name, | 329 | struct fpga_bridge *fpga_bridge_create(struct device *dev, const char *name, |
340 | const struct fpga_bridge_ops *br_ops, void *priv) | 330 | const struct fpga_bridge_ops *br_ops, |
331 | void *priv) | ||
341 | { | 332 | { |
342 | struct fpga_bridge *bridge; | 333 | struct fpga_bridge *bridge; |
343 | int id, ret = 0; | 334 | int id, ret = 0; |
344 | 335 | ||
345 | if (!name || !strlen(name)) { | 336 | if (!name || !strlen(name)) { |
346 | dev_err(dev, "Attempt to register with no name!\n"); | 337 | dev_err(dev, "Attempt to register with no name!\n"); |
347 | return -EINVAL; | 338 | return NULL; |
348 | } | 339 | } |
349 | 340 | ||
350 | bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); | 341 | bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); |
351 | if (!bridge) | 342 | if (!bridge) |
352 | return -ENOMEM; | 343 | return NULL; |
353 | 344 | ||
354 | id = ida_simple_get(&fpga_bridge_ida, 0, 0, GFP_KERNEL); | 345 | id = ida_simple_get(&fpga_bridge_ida, 0, 0, GFP_KERNEL); |
355 | if (id < 0) { | 346 | if (id < 0) { |
@@ -370,40 +361,62 @@ int fpga_bridge_register(struct device *dev, const char *name, | |||
370 | bridge->dev.parent = dev; | 361 | bridge->dev.parent = dev; |
371 | bridge->dev.of_node = dev->of_node; | 362 | bridge->dev.of_node = dev->of_node; |
372 | bridge->dev.id = id; | 363 | bridge->dev.id = id; |
373 | dev_set_drvdata(dev, bridge); | ||
374 | 364 | ||
375 | ret = dev_set_name(&bridge->dev, "br%d", id); | 365 | ret = dev_set_name(&bridge->dev, "br%d", id); |
376 | if (ret) | 366 | if (ret) |
377 | goto error_device; | 367 | goto error_device; |
378 | 368 | ||
379 | ret = device_add(&bridge->dev); | 369 | return bridge; |
380 | if (ret) | ||
381 | goto error_device; | ||
382 | |||
383 | of_platform_populate(dev->of_node, NULL, NULL, dev); | ||
384 | |||
385 | dev_info(bridge->dev.parent, "fpga bridge [%s] registered\n", | ||
386 | bridge->name); | ||
387 | |||
388 | return 0; | ||
389 | 370 | ||
390 | error_device: | 371 | error_device: |
391 | ida_simple_remove(&fpga_bridge_ida, id); | 372 | ida_simple_remove(&fpga_bridge_ida, id); |
392 | error_kfree: | 373 | error_kfree: |
393 | kfree(bridge); | 374 | kfree(bridge); |
394 | 375 | ||
395 | return ret; | 376 | return NULL; |
396 | } | 377 | } |
397 | EXPORT_SYMBOL_GPL(fpga_bridge_register); | 378 | EXPORT_SYMBOL_GPL(fpga_bridge_create); |
398 | 379 | ||
399 | /** | 380 | /** |
400 | * fpga_bridge_unregister - unregister a fpga bridge driver | 381 | * fpga_bridge_free - free a fpga bridge and its id |
401 | * @dev: FPGA bridge device from pdev | 382 | * @bridge: FPGA bridge struct created by fpga_bridge_create |
402 | */ | 383 | */ |
403 | void fpga_bridge_unregister(struct device *dev) | 384 | void fpga_bridge_free(struct fpga_bridge *bridge) |
404 | { | 385 | { |
405 | struct fpga_bridge *bridge = dev_get_drvdata(dev); | 386 | ida_simple_remove(&fpga_bridge_ida, bridge->dev.id); |
387 | kfree(bridge); | ||
388 | } | ||
389 | EXPORT_SYMBOL_GPL(fpga_bridge_free); | ||
406 | 390 | ||
391 | /** | ||
392 | * fpga_bridge_register - register a fpga bridge | ||
393 | * @bridge: FPGA bridge struct created by fpga_bridge_create | ||
394 | * | ||
395 | * Return: 0 for success, error code otherwise. | ||
396 | */ | ||
397 | int fpga_bridge_register(struct fpga_bridge *bridge) | ||
398 | { | ||
399 | struct device *dev = &bridge->dev; | ||
400 | int ret; | ||
401 | |||
402 | ret = device_add(dev); | ||
403 | if (ret) | ||
404 | return ret; | ||
405 | |||
406 | of_platform_populate(dev->of_node, NULL, NULL, dev); | ||
407 | |||
408 | dev_info(dev->parent, "fpga bridge [%s] registered\n", bridge->name); | ||
409 | |||
410 | return 0; | ||
411 | } | ||
412 | EXPORT_SYMBOL_GPL(fpga_bridge_register); | ||
413 | |||
414 | /** | ||
415 | * fpga_bridge_unregister - unregister and free a fpga bridge | ||
416 | * @bridge: FPGA bridge struct created by fpga_bridge_create | ||
417 | */ | ||
418 | void fpga_bridge_unregister(struct fpga_bridge *bridge) | ||
419 | { | ||
407 | /* | 420 | /* |
408 | * If the low level driver provides a method for putting bridge into | 421 | * If the low level driver provides a method for putting bridge into |
409 | * a desired state upon unregister, do it. | 422 | * a desired state upon unregister, do it. |
@@ -419,8 +432,7 @@ static void fpga_bridge_dev_release(struct device *dev) | |||
419 | { | 432 | { |
420 | struct fpga_bridge *bridge = to_fpga_bridge(dev); | 433 | struct fpga_bridge *bridge = to_fpga_bridge(dev); |
421 | 434 | ||
422 | ida_simple_remove(&fpga_bridge_ida, bridge->dev.id); | 435 | fpga_bridge_free(bridge); |
423 | kfree(bridge); | ||
424 | } | 436 | } |
425 | 437 | ||
426 | static int __init fpga_bridge_dev_init(void) | 438 | static int __init fpga_bridge_dev_init(void) |
diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index 9939d2cbc9a6..c1564cf827fe 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * FPGA Manager Core | 3 | * FPGA Manager Core |
3 | * | 4 | * |
@@ -6,18 +7,6 @@ | |||
6 | * | 7 | * |
7 | * With code from the mailing list: | 8 | * With code from the mailing list: |
8 | * Copyright (C) 2013 Xilinx, Inc. | 9 | * Copyright (C) 2013 Xilinx, Inc. |
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms and conditions of the GNU General Public License, | ||
12 | * version 2, as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
17 | * more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along with | ||
20 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
21 | */ | 10 | */ |
22 | #include <linux/firmware.h> | 11 | #include <linux/firmware.h> |
23 | #include <linux/fpga/fpga-mgr.h> | 12 | #include <linux/fpga/fpga-mgr.h> |
@@ -32,6 +21,12 @@ | |||
32 | static DEFINE_IDA(fpga_mgr_ida); | 21 | static DEFINE_IDA(fpga_mgr_ida); |
33 | static struct class *fpga_mgr_class; | 22 | static struct class *fpga_mgr_class; |
34 | 23 | ||
24 | /** | ||
25 | * fpga_image_info_alloc - Allocate a FPGA image info struct | ||
26 | * @dev: owning device | ||
27 | * | ||
28 | * Return: struct fpga_image_info or NULL | ||
29 | */ | ||
35 | struct fpga_image_info *fpga_image_info_alloc(struct device *dev) | 30 | struct fpga_image_info *fpga_image_info_alloc(struct device *dev) |
36 | { | 31 | { |
37 | struct fpga_image_info *info; | 32 | struct fpga_image_info *info; |
@@ -50,6 +45,10 @@ struct fpga_image_info *fpga_image_info_alloc(struct device *dev) | |||
50 | } | 45 | } |
51 | EXPORT_SYMBOL_GPL(fpga_image_info_alloc); | 46 | EXPORT_SYMBOL_GPL(fpga_image_info_alloc); |
52 | 47 | ||
48 | /** | ||
49 | * fpga_image_info_free - Free a FPGA image info struct | ||
50 | * @info: FPGA image info struct to free | ||
51 | */ | ||
53 | void fpga_image_info_free(struct fpga_image_info *info) | 52 | void fpga_image_info_free(struct fpga_image_info *info) |
54 | { | 53 | { |
55 | struct device *dev; | 54 | struct device *dev; |
@@ -234,7 +233,7 @@ static int fpga_mgr_buf_load_mapped(struct fpga_manager *mgr, | |||
234 | /** | 233 | /** |
235 | * fpga_mgr_buf_load - load fpga from image in buffer | 234 | * fpga_mgr_buf_load - load fpga from image in buffer |
236 | * @mgr: fpga manager | 235 | * @mgr: fpga manager |
237 | * @flags: flags setting fpga confuration modes | 236 | * @info: fpga image info |
238 | * @buf: buffer contain fpga image | 237 | * @buf: buffer contain fpga image |
239 | * @count: byte count of buf | 238 | * @count: byte count of buf |
240 | * | 239 | * |
@@ -343,6 +342,16 @@ static int fpga_mgr_firmware_load(struct fpga_manager *mgr, | |||
343 | return ret; | 342 | return ret; |
344 | } | 343 | } |
345 | 344 | ||
345 | /** | ||
346 | * fpga_mgr_load - load FPGA from scatter/gather table, buffer, or firmware | ||
347 | * @mgr: fpga manager | ||
348 | * @info: fpga image information. | ||
349 | * | ||
350 | * Load the FPGA from an image which is indicated in @info. If successful, the | ||
351 | * FPGA ends up in operating mode. | ||
352 | * | ||
353 | * Return: 0 on success, negative error code otherwise. | ||
354 | */ | ||
346 | int fpga_mgr_load(struct fpga_manager *mgr, struct fpga_image_info *info) | 355 | int fpga_mgr_load(struct fpga_manager *mgr, struct fpga_image_info *info) |
347 | { | 356 | { |
348 | if (info->sgt) | 357 | if (info->sgt) |
@@ -429,11 +438,9 @@ static int fpga_mgr_dev_match(struct device *dev, const void *data) | |||
429 | } | 438 | } |
430 | 439 | ||
431 | /** | 440 | /** |
432 | * fpga_mgr_get - get a reference to a fpga mgr | 441 | * fpga_mgr_get - Given a device, get a reference to a fpga mgr. |
433 | * @dev: parent device that fpga mgr was registered with | 442 | * @dev: parent device that fpga mgr was registered with |
434 | * | 443 | * |
435 | * Given a device, get a reference to a fpga mgr. | ||
436 | * | ||
437 | * Return: fpga manager struct or IS_ERR() condition containing error code. | 444 | * Return: fpga manager struct or IS_ERR() condition containing error code. |
438 | */ | 445 | */ |
439 | struct fpga_manager *fpga_mgr_get(struct device *dev) | 446 | struct fpga_manager *fpga_mgr_get(struct device *dev) |
@@ -453,10 +460,9 @@ static int fpga_mgr_of_node_match(struct device *dev, const void *data) | |||
453 | } | 460 | } |
454 | 461 | ||
455 | /** | 462 | /** |
456 | * of_fpga_mgr_get - get a reference to a fpga mgr | 463 | * of_fpga_mgr_get - Given a device node, get a reference to a fpga mgr. |
457 | * @node: device node | ||
458 | * | 464 | * |
459 | * Given a device node, get a reference to a fpga mgr. | 465 | * @node: device node |
460 | * | 466 | * |
461 | * Return: fpga manager struct or IS_ERR() condition containing error code. | 467 | * Return: fpga manager struct or IS_ERR() condition containing error code. |
462 | */ | 468 | */ |
@@ -489,7 +495,10 @@ EXPORT_SYMBOL_GPL(fpga_mgr_put); | |||
489 | * @mgr: fpga manager | 495 | * @mgr: fpga manager |
490 | * | 496 | * |
491 | * Given a pointer to FPGA Manager (from fpga_mgr_get() or | 497 | * Given a pointer to FPGA Manager (from fpga_mgr_get() or |
492 | * of_fpga_mgr_put()) attempt to get the mutex. | 498 | * of_fpga_mgr_put()) attempt to get the mutex. The user should call |
499 | * fpga_mgr_lock() and verify that it returns 0 before attempting to | ||
500 | * program the FPGA. Likewise, the user should call fpga_mgr_unlock | ||
501 | * when done programming the FPGA. | ||
493 | * | 502 | * |
494 | * Return: 0 for success or -EBUSY | 503 | * Return: 0 for success or -EBUSY |
495 | */ | 504 | */ |
@@ -505,7 +514,7 @@ int fpga_mgr_lock(struct fpga_manager *mgr) | |||
505 | EXPORT_SYMBOL_GPL(fpga_mgr_lock); | 514 | EXPORT_SYMBOL_GPL(fpga_mgr_lock); |
506 | 515 | ||
507 | /** | 516 | /** |
508 | * fpga_mgr_unlock - Unlock FPGA manager | 517 | * fpga_mgr_unlock - Unlock FPGA manager after done programming |
509 | * @mgr: fpga manager | 518 | * @mgr: fpga manager |
510 | */ | 519 | */ |
511 | void fpga_mgr_unlock(struct fpga_manager *mgr) | 520 | void fpga_mgr_unlock(struct fpga_manager *mgr) |
@@ -515,17 +524,17 @@ void fpga_mgr_unlock(struct fpga_manager *mgr) | |||
515 | EXPORT_SYMBOL_GPL(fpga_mgr_unlock); | 524 | EXPORT_SYMBOL_GPL(fpga_mgr_unlock); |
516 | 525 | ||
517 | /** | 526 | /** |
518 | * fpga_mgr_register - register a low level fpga manager driver | 527 | * fpga_mgr_create - create and initialize a FPGA manager struct |
519 | * @dev: fpga manager device from pdev | 528 | * @dev: fpga manager device from pdev |
520 | * @name: fpga manager name | 529 | * @name: fpga manager name |
521 | * @mops: pointer to structure of fpga manager ops | 530 | * @mops: pointer to structure of fpga manager ops |
522 | * @priv: fpga manager private data | 531 | * @priv: fpga manager private data |
523 | * | 532 | * |
524 | * Return: 0 on success, negative error code otherwise. | 533 | * Return: pointer to struct fpga_manager or NULL |
525 | */ | 534 | */ |
526 | int fpga_mgr_register(struct device *dev, const char *name, | 535 | struct fpga_manager *fpga_mgr_create(struct device *dev, const char *name, |
527 | const struct fpga_manager_ops *mops, | 536 | const struct fpga_manager_ops *mops, |
528 | void *priv) | 537 | void *priv) |
529 | { | 538 | { |
530 | struct fpga_manager *mgr; | 539 | struct fpga_manager *mgr; |
531 | int id, ret; | 540 | int id, ret; |
@@ -534,17 +543,17 @@ int fpga_mgr_register(struct device *dev, const char *name, | |||
534 | !mops->write_init || (!mops->write && !mops->write_sg) || | 543 | !mops->write_init || (!mops->write && !mops->write_sg) || |
535 | (mops->write && mops->write_sg)) { | 544 | (mops->write && mops->write_sg)) { |
536 | dev_err(dev, "Attempt to register without fpga_manager_ops\n"); | 545 | dev_err(dev, "Attempt to register without fpga_manager_ops\n"); |
537 | return -EINVAL; | 546 | return NULL; |
538 | } | 547 | } |
539 | 548 | ||
540 | if (!name || !strlen(name)) { | 549 | if (!name || !strlen(name)) { |
541 | dev_err(dev, "Attempt to register with no name!\n"); | 550 | dev_err(dev, "Attempt to register with no name!\n"); |
542 | return -EINVAL; | 551 | return NULL; |
543 | } | 552 | } |
544 | 553 | ||
545 | mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); | 554 | mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); |
546 | if (!mgr) | 555 | if (!mgr) |
547 | return -ENOMEM; | 556 | return NULL; |
548 | 557 | ||
549 | id = ida_simple_get(&fpga_mgr_ida, 0, 0, GFP_KERNEL); | 558 | id = ida_simple_get(&fpga_mgr_ida, 0, 0, GFP_KERNEL); |
550 | if (id < 0) { | 559 | if (id < 0) { |
@@ -558,25 +567,56 @@ int fpga_mgr_register(struct device *dev, const char *name, | |||
558 | mgr->mops = mops; | 567 | mgr->mops = mops; |
559 | mgr->priv = priv; | 568 | mgr->priv = priv; |
560 | 569 | ||
561 | /* | ||
562 | * Initialize framework state by requesting low level driver read state | ||
563 | * from device. FPGA may be in reset mode or may have been programmed | ||
564 | * by bootloader or EEPROM. | ||
565 | */ | ||
566 | mgr->state = mgr->mops->state(mgr); | ||
567 | |||
568 | device_initialize(&mgr->dev); | 570 | device_initialize(&mgr->dev); |
569 | mgr->dev.class = fpga_mgr_class; | 571 | mgr->dev.class = fpga_mgr_class; |
570 | mgr->dev.groups = mops->groups; | 572 | mgr->dev.groups = mops->groups; |
571 | mgr->dev.parent = dev; | 573 | mgr->dev.parent = dev; |
572 | mgr->dev.of_node = dev->of_node; | 574 | mgr->dev.of_node = dev->of_node; |
573 | mgr->dev.id = id; | 575 | mgr->dev.id = id; |
574 | dev_set_drvdata(dev, mgr); | ||
575 | 576 | ||
576 | ret = dev_set_name(&mgr->dev, "fpga%d", id); | 577 | ret = dev_set_name(&mgr->dev, "fpga%d", id); |
577 | if (ret) | 578 | if (ret) |
578 | goto error_device; | 579 | goto error_device; |
579 | 580 | ||
581 | return mgr; | ||
582 | |||
583 | error_device: | ||
584 | ida_simple_remove(&fpga_mgr_ida, id); | ||
585 | error_kfree: | ||
586 | kfree(mgr); | ||
587 | |||
588 | return NULL; | ||
589 | } | ||
590 | EXPORT_SYMBOL_GPL(fpga_mgr_create); | ||
591 | |||
592 | /** | ||
593 | * fpga_mgr_free - deallocate a FPGA manager | ||
594 | * @mgr: fpga manager struct created by fpga_mgr_create | ||
595 | */ | ||
596 | void fpga_mgr_free(struct fpga_manager *mgr) | ||
597 | { | ||
598 | ida_simple_remove(&fpga_mgr_ida, mgr->dev.id); | ||
599 | kfree(mgr); | ||
600 | } | ||
601 | EXPORT_SYMBOL_GPL(fpga_mgr_free); | ||
602 | |||
603 | /** | ||
604 | * fpga_mgr_register - register a FPGA manager | ||
605 | * @mgr: fpga manager struct created by fpga_mgr_create | ||
606 | * | ||
607 | * Return: 0 on success, negative error code otherwise. | ||
608 | */ | ||
609 | int fpga_mgr_register(struct fpga_manager *mgr) | ||
610 | { | ||
611 | int ret; | ||
612 | |||
613 | /* | ||
614 | * Initialize framework state by requesting low level driver read state | ||
615 | * from device. FPGA may be in reset mode or may have been programmed | ||
616 | * by bootloader or EEPROM. | ||
617 | */ | ||
618 | mgr->state = mgr->mops->state(mgr); | ||
619 | |||
580 | ret = device_add(&mgr->dev); | 620 | ret = device_add(&mgr->dev); |
581 | if (ret) | 621 | if (ret) |
582 | goto error_device; | 622 | goto error_device; |
@@ -586,22 +626,18 @@ int fpga_mgr_register(struct device *dev, const char *name, | |||
586 | return 0; | 626 | return 0; |
587 | 627 | ||
588 | error_device: | 628 | error_device: |
589 | ida_simple_remove(&fpga_mgr_ida, id); | 629 | ida_simple_remove(&fpga_mgr_ida, mgr->dev.id); |
590 | error_kfree: | ||
591 | kfree(mgr); | ||
592 | 630 | ||
593 | return ret; | 631 | return ret; |
594 | } | 632 | } |
595 | EXPORT_SYMBOL_GPL(fpga_mgr_register); | 633 | EXPORT_SYMBOL_GPL(fpga_mgr_register); |
596 | 634 | ||
597 | /** | 635 | /** |
598 | * fpga_mgr_unregister - unregister a low level fpga manager driver | 636 | * fpga_mgr_unregister - unregister and free a FPGA manager |
599 | * @dev: fpga manager device from pdev | 637 | * @mgr: fpga manager struct |
600 | */ | 638 | */ |
601 | void fpga_mgr_unregister(struct device *dev) | 639 | void fpga_mgr_unregister(struct fpga_manager *mgr) |
602 | { | 640 | { |
603 | struct fpga_manager *mgr = dev_get_drvdata(dev); | ||
604 | |||
605 | dev_info(&mgr->dev, "%s %s\n", __func__, mgr->name); | 641 | dev_info(&mgr->dev, "%s %s\n", __func__, mgr->name); |
606 | 642 | ||
607 | /* | 643 | /* |
@@ -619,8 +655,7 @@ static void fpga_mgr_dev_release(struct device *dev) | |||
619 | { | 655 | { |
620 | struct fpga_manager *mgr = to_fpga_manager(dev); | 656 | struct fpga_manager *mgr = to_fpga_manager(dev); |
621 | 657 | ||
622 | ida_simple_remove(&fpga_mgr_ida, mgr->dev.id); | 658 | fpga_mgr_free(mgr); |
623 | kfree(mgr); | ||
624 | } | 659 | } |
625 | 660 | ||
626 | static int __init fpga_mgr_class_init(void) | 661 | static int __init fpga_mgr_class_init(void) |
diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index edab2a2e03ef..6d214d75c7be 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c | |||
@@ -1,22 +1,10 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * FPGA Region - Device Tree support for FPGA programming under Linux | 3 | * FPGA Region - Device Tree support for FPGA programming under Linux |
3 | * | 4 | * |
4 | * Copyright (C) 2013-2016 Altera Corporation | 5 | * Copyright (C) 2013-2016 Altera Corporation |
5 | * Copyright (C) 2017 Intel Corporation | 6 | * Copyright (C) 2017 Intel Corporation |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms and conditions of the GNU General Public License, | ||
9 | * version 2, as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | 7 | */ |
19 | |||
20 | #include <linux/fpga/fpga-bridge.h> | 8 | #include <linux/fpga/fpga-bridge.h> |
21 | #include <linux/fpga/fpga-mgr.h> | 9 | #include <linux/fpga/fpga-mgr.h> |
22 | #include <linux/fpga/fpga-region.h> | 10 | #include <linux/fpga/fpga-region.h> |
@@ -93,8 +81,16 @@ static void fpga_region_put(struct fpga_region *region) | |||
93 | 81 | ||
94 | /** | 82 | /** |
95 | * fpga_region_program_fpga - program FPGA | 83 | * fpga_region_program_fpga - program FPGA |
84 | * | ||
96 | * @region: FPGA region | 85 | * @region: FPGA region |
86 | * | ||
97 | * Program an FPGA using fpga image info (region->info). | 87 | * Program an FPGA using fpga image info (region->info). |
88 | * If the region has a get_bridges function, the exclusive reference for the | ||
89 | * bridges will be held if programming succeeds. This is intended to prevent | ||
90 | * reprogramming the region until the caller considers it safe to do so. | ||
91 | * The caller will need to call fpga_bridges_put() before attempting to | ||
92 | * reprogram the region. | ||
93 | * | ||
98 | * Return 0 for success or negative error code. | 94 | * Return 0 for success or negative error code. |
99 | */ | 95 | */ |
100 | int fpga_region_program_fpga(struct fpga_region *region) | 96 | int fpga_region_program_fpga(struct fpga_region *region) |
@@ -162,45 +158,86 @@ err_put_region: | |||
162 | } | 158 | } |
163 | EXPORT_SYMBOL_GPL(fpga_region_program_fpga); | 159 | EXPORT_SYMBOL_GPL(fpga_region_program_fpga); |
164 | 160 | ||
165 | int fpga_region_register(struct device *dev, struct fpga_region *region) | 161 | /** |
162 | * fpga_region_create - alloc and init a struct fpga_region | ||
163 | * @dev: device parent | ||
164 | * @mgr: manager that programs this region | ||
165 | * @get_bridges: optional function to get bridges to a list | ||
166 | * | ||
167 | * Return: struct fpga_region or NULL | ||
168 | */ | ||
169 | struct fpga_region | ||
170 | *fpga_region_create(struct device *dev, | ||
171 | struct fpga_manager *mgr, | ||
172 | int (*get_bridges)(struct fpga_region *)) | ||
166 | { | 173 | { |
174 | struct fpga_region *region; | ||
167 | int id, ret = 0; | 175 | int id, ret = 0; |
168 | 176 | ||
177 | region = kzalloc(sizeof(*region), GFP_KERNEL); | ||
178 | if (!region) | ||
179 | return NULL; | ||
180 | |||
169 | id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL); | 181 | id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL); |
170 | if (id < 0) | 182 | if (id < 0) |
171 | return id; | 183 | goto err_free; |
172 | 184 | ||
185 | region->mgr = mgr; | ||
186 | region->get_bridges = get_bridges; | ||
173 | mutex_init(®ion->mutex); | 187 | mutex_init(®ion->mutex); |
174 | INIT_LIST_HEAD(®ion->bridge_list); | 188 | INIT_LIST_HEAD(®ion->bridge_list); |
189 | |||
175 | device_initialize(®ion->dev); | 190 | device_initialize(®ion->dev); |
176 | region->dev.groups = region->groups; | ||
177 | region->dev.class = fpga_region_class; | 191 | region->dev.class = fpga_region_class; |
178 | region->dev.parent = dev; | 192 | region->dev.parent = dev; |
179 | region->dev.of_node = dev->of_node; | 193 | region->dev.of_node = dev->of_node; |
180 | region->dev.id = id; | 194 | region->dev.id = id; |
181 | dev_set_drvdata(dev, region); | ||
182 | 195 | ||
183 | ret = dev_set_name(®ion->dev, "region%d", id); | 196 | ret = dev_set_name(®ion->dev, "region%d", id); |
184 | if (ret) | 197 | if (ret) |
185 | goto err_remove; | 198 | goto err_remove; |
186 | 199 | ||
187 | ret = device_add(®ion->dev); | 200 | return region; |
188 | if (ret) | ||
189 | goto err_remove; | ||
190 | |||
191 | return 0; | ||
192 | 201 | ||
193 | err_remove: | 202 | err_remove: |
194 | ida_simple_remove(&fpga_region_ida, id); | 203 | ida_simple_remove(&fpga_region_ida, id); |
195 | return ret; | 204 | err_free: |
205 | kfree(region); | ||
206 | |||
207 | return NULL; | ||
208 | } | ||
209 | EXPORT_SYMBOL_GPL(fpga_region_create); | ||
210 | |||
211 | /** | ||
212 | * fpga_region_free - free a struct fpga_region | ||
213 | * @region: FPGA region created by fpga_region_create | ||
214 | */ | ||
215 | void fpga_region_free(struct fpga_region *region) | ||
216 | { | ||
217 | ida_simple_remove(&fpga_region_ida, region->dev.id); | ||
218 | kfree(region); | ||
219 | } | ||
220 | EXPORT_SYMBOL_GPL(fpga_region_free); | ||
221 | |||
222 | /** | ||
223 | * fpga_region_register - register a FPGA region | ||
224 | * @region: FPGA region created by fpga_region_create | ||
225 | * Return: 0 or -errno | ||
226 | */ | ||
227 | int fpga_region_register(struct fpga_region *region) | ||
228 | { | ||
229 | return device_add(®ion->dev); | ||
230 | |||
196 | } | 231 | } |
197 | EXPORT_SYMBOL_GPL(fpga_region_register); | 232 | EXPORT_SYMBOL_GPL(fpga_region_register); |
198 | 233 | ||
199 | int fpga_region_unregister(struct fpga_region *region) | 234 | /** |
235 | * fpga_region_unregister - unregister and free a FPGA region | ||
236 | * @region: FPGA region | ||
237 | */ | ||
238 | void fpga_region_unregister(struct fpga_region *region) | ||
200 | { | 239 | { |
201 | device_unregister(®ion->dev); | 240 | device_unregister(®ion->dev); |
202 | |||
203 | return 0; | ||
204 | } | 241 | } |
205 | EXPORT_SYMBOL_GPL(fpga_region_unregister); | 242 | EXPORT_SYMBOL_GPL(fpga_region_unregister); |
206 | 243 | ||
@@ -208,7 +245,7 @@ static void fpga_region_dev_release(struct device *dev) | |||
208 | { | 245 | { |
209 | struct fpga_region *region = to_fpga_region(dev); | 246 | struct fpga_region *region = to_fpga_region(dev); |
210 | 247 | ||
211 | ida_simple_remove(&fpga_region_ida, region->dev.id); | 248 | fpga_region_free(region); |
212 | } | 249 | } |
213 | 250 | ||
214 | /** | 251 | /** |
diff --git a/drivers/fpga/ice40-spi.c b/drivers/fpga/ice40-spi.c index 7fca82023062..5981c7ee7a7d 100644 --- a/drivers/fpga/ice40-spi.c +++ b/drivers/fpga/ice40-spi.c | |||
@@ -133,6 +133,7 @@ static int ice40_fpga_probe(struct spi_device *spi) | |||
133 | { | 133 | { |
134 | struct device *dev = &spi->dev; | 134 | struct device *dev = &spi->dev; |
135 | struct ice40_fpga_priv *priv; | 135 | struct ice40_fpga_priv *priv; |
136 | struct fpga_manager *mgr; | ||
136 | int ret; | 137 | int ret; |
137 | 138 | ||
138 | priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL); | 139 | priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL); |
@@ -174,14 +175,26 @@ static int ice40_fpga_probe(struct spi_device *spi) | |||
174 | return ret; | 175 | return ret; |
175 | } | 176 | } |
176 | 177 | ||
177 | /* Register with the FPGA manager */ | 178 | mgr = fpga_mgr_create(dev, "Lattice iCE40 FPGA Manager", |
178 | return fpga_mgr_register(dev, "Lattice iCE40 FPGA Manager", | 179 | &ice40_fpga_ops, priv); |
179 | &ice40_fpga_ops, priv); | 180 | if (!mgr) |
181 | return -ENOMEM; | ||
182 | |||
183 | spi_set_drvdata(spi, mgr); | ||
184 | |||
185 | ret = fpga_mgr_register(mgr); | ||
186 | if (ret) | ||
187 | fpga_mgr_free(mgr); | ||
188 | |||
189 | return ret; | ||
180 | } | 190 | } |
181 | 191 | ||
182 | static int ice40_fpga_remove(struct spi_device *spi) | 192 | static int ice40_fpga_remove(struct spi_device *spi) |
183 | { | 193 | { |
184 | fpga_mgr_unregister(&spi->dev); | 194 | struct fpga_manager *mgr = spi_get_drvdata(spi); |
195 | |||
196 | fpga_mgr_unregister(mgr); | ||
197 | |||
185 | return 0; | 198 | return 0; |
186 | } | 199 | } |
187 | 200 | ||
diff --git a/drivers/fpga/machxo2-spi.c b/drivers/fpga/machxo2-spi.c new file mode 100644 index 000000000000..a582e0000c97 --- /dev/null +++ b/drivers/fpga/machxo2-spi.c | |||
@@ -0,0 +1,415 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Lattice MachXO2 Slave SPI Driver | ||
4 | * | ||
5 | * Manage Lattice FPGA firmware that is loaded over SPI using | ||
6 | * the slave serial configuration interface. | ||
7 | * | ||
8 | * Copyright (C) 2018 Paolo Pisati <p.pisati@gmail.com> | ||
9 | */ | ||
10 | |||
11 | #include <linux/delay.h> | ||
12 | #include <linux/fpga/fpga-mgr.h> | ||
13 | #include <linux/gpio/consumer.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/of.h> | ||
16 | #include <linux/spi/spi.h> | ||
17 | |||
18 | /* MachXO2 Programming Guide - sysCONFIG Programming Commands */ | ||
19 | #define IDCODE_PUB {0xe0, 0x00, 0x00, 0x00} | ||
20 | #define ISC_ENABLE {0xc6, 0x08, 0x00, 0x00} | ||
21 | #define ISC_ERASE {0x0e, 0x04, 0x00, 0x00} | ||
22 | #define ISC_PROGRAMDONE {0x5e, 0x00, 0x00, 0x00} | ||
23 | #define LSC_INITADDRESS {0x46, 0x00, 0x00, 0x00} | ||
24 | #define LSC_PROGINCRNV {0x70, 0x00, 0x00, 0x01} | ||
25 | #define LSC_READ_STATUS {0x3c, 0x00, 0x00, 0x00} | ||
26 | #define LSC_REFRESH {0x79, 0x00, 0x00, 0x00} | ||
27 | |||
28 | /* | ||
29 | * Max CCLK in Slave SPI mode according to 'MachXO2 Family Data | ||
30 | * Sheet' sysCONFIG Port Timing Specifications (3-36) | ||
31 | */ | ||
32 | #define MACHXO2_MAX_SPEED 66000000 | ||
33 | |||
34 | #define MACHXO2_LOW_DELAY_USEC 5 | ||
35 | #define MACHXO2_HIGH_DELAY_USEC 200 | ||
36 | #define MACHXO2_REFRESH_USEC 4800 | ||
37 | #define MACHXO2_MAX_BUSY_LOOP 128 | ||
38 | #define MACHXO2_MAX_REFRESH_LOOP 16 | ||
39 | |||
40 | #define MACHXO2_PAGE_SIZE 16 | ||
41 | #define MACHXO2_BUF_SIZE (MACHXO2_PAGE_SIZE + 4) | ||
42 | |||
43 | /* Status register bits, errors and error mask */ | ||
44 | #define BUSY 12 | ||
45 | #define DONE 8 | ||
46 | #define DVER 27 | ||
47 | #define ENAB 9 | ||
48 | #define ERRBITS 23 | ||
49 | #define ERRMASK 7 | ||
50 | #define FAIL 13 | ||
51 | |||
52 | #define ENOERR 0 /* no error */ | ||
53 | #define EID 1 | ||
54 | #define ECMD 2 | ||
55 | #define ECRC 3 | ||
56 | #define EPREAM 4 /* preamble error */ | ||
57 | #define EABRT 5 /* abort error */ | ||
58 | #define EOVERFL 6 /* overflow error */ | ||
59 | #define ESDMEOF 7 /* SDM EOF */ | ||
60 | |||
61 | static inline u8 get_err(unsigned long *status) | ||
62 | { | ||
63 | return (*status >> ERRBITS) & ERRMASK; | ||
64 | } | ||
65 | |||
66 | static int get_status(struct spi_device *spi, unsigned long *status) | ||
67 | { | ||
68 | struct spi_message msg; | ||
69 | struct spi_transfer rx, tx; | ||
70 | static const u8 cmd[] = LSC_READ_STATUS; | ||
71 | int ret; | ||
72 | |||
73 | memset(&rx, 0, sizeof(rx)); | ||
74 | memset(&tx, 0, sizeof(tx)); | ||
75 | tx.tx_buf = cmd; | ||
76 | tx.len = sizeof(cmd); | ||
77 | rx.rx_buf = status; | ||
78 | rx.len = 4; | ||
79 | spi_message_init(&msg); | ||
80 | spi_message_add_tail(&tx, &msg); | ||
81 | spi_message_add_tail(&rx, &msg); | ||
82 | ret = spi_sync(spi, &msg); | ||
83 | if (ret) | ||
84 | return ret; | ||
85 | |||
86 | *status = be32_to_cpu(*status); | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | #ifdef DEBUG | ||
92 | static const char *get_err_string(u8 err) | ||
93 | { | ||
94 | switch (err) { | ||
95 | case ENOERR: return "No Error"; | ||
96 | case EID: return "ID ERR"; | ||
97 | case ECMD: return "CMD ERR"; | ||
98 | case ECRC: return "CRC ERR"; | ||
99 | case EPREAM: return "Preamble ERR"; | ||
100 | case EABRT: return "Abort ERR"; | ||
101 | case EOVERFL: return "Overflow ERR"; | ||
102 | case ESDMEOF: return "SDM EOF"; | ||
103 | } | ||
104 | |||
105 | return "Default switch case"; | ||
106 | } | ||
107 | #endif | ||
108 | |||
109 | static void dump_status_reg(unsigned long *status) | ||
110 | { | ||
111 | #ifdef DEBUG | ||
112 | pr_debug("machxo2 status: 0x%08lX - done=%d, cfgena=%d, busy=%d, fail=%d, devver=%d, err=%s\n", | ||
113 | *status, test_bit(DONE, status), test_bit(ENAB, status), | ||
114 | test_bit(BUSY, status), test_bit(FAIL, status), | ||
115 | test_bit(DVER, status), get_err_string(get_err(status))); | ||
116 | #endif | ||
117 | } | ||
118 | |||
119 | static int wait_until_not_busy(struct spi_device *spi) | ||
120 | { | ||
121 | unsigned long status; | ||
122 | int ret, loop = 0; | ||
123 | |||
124 | do { | ||
125 | ret = get_status(spi, &status); | ||
126 | if (ret) | ||
127 | return ret; | ||
128 | if (++loop >= MACHXO2_MAX_BUSY_LOOP) | ||
129 | return -EBUSY; | ||
130 | } while (test_bit(BUSY, &status)); | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static int machxo2_cleanup(struct fpga_manager *mgr) | ||
136 | { | ||
137 | struct spi_device *spi = mgr->priv; | ||
138 | struct spi_message msg; | ||
139 | struct spi_transfer tx[2]; | ||
140 | static const u8 erase[] = ISC_ERASE; | ||
141 | static const u8 refresh[] = LSC_REFRESH; | ||
142 | int ret; | ||
143 | |||
144 | memset(tx, 0, sizeof(tx)); | ||
145 | spi_message_init(&msg); | ||
146 | tx[0].tx_buf = &erase; | ||
147 | tx[0].len = sizeof(erase); | ||
148 | spi_message_add_tail(&tx[0], &msg); | ||
149 | ret = spi_sync(spi, &msg); | ||
150 | if (ret) | ||
151 | goto fail; | ||
152 | |||
153 | ret = wait_until_not_busy(spi); | ||
154 | if (ret) | ||
155 | goto fail; | ||
156 | |||
157 | spi_message_init(&msg); | ||
158 | tx[1].tx_buf = &refresh; | ||
159 | tx[1].len = sizeof(refresh); | ||
160 | tx[1].delay_usecs = MACHXO2_REFRESH_USEC; | ||
161 | spi_message_add_tail(&tx[1], &msg); | ||
162 | ret = spi_sync(spi, &msg); | ||
163 | if (ret) | ||
164 | goto fail; | ||
165 | |||
166 | return 0; | ||
167 | fail: | ||
168 | dev_err(&mgr->dev, "Cleanup failed\n"); | ||
169 | |||
170 | return ret; | ||
171 | } | ||
172 | |||
173 | static enum fpga_mgr_states machxo2_spi_state(struct fpga_manager *mgr) | ||
174 | { | ||
175 | struct spi_device *spi = mgr->priv; | ||
176 | unsigned long status; | ||
177 | |||
178 | get_status(spi, &status); | ||
179 | if (!test_bit(BUSY, &status) && test_bit(DONE, &status) && | ||
180 | get_err(&status) == ENOERR) | ||
181 | return FPGA_MGR_STATE_OPERATING; | ||
182 | |||
183 | return FPGA_MGR_STATE_UNKNOWN; | ||
184 | } | ||
185 | |||
186 | static int machxo2_write_init(struct fpga_manager *mgr, | ||
187 | struct fpga_image_info *info, | ||
188 | const char *buf, size_t count) | ||
189 | { | ||
190 | struct spi_device *spi = mgr->priv; | ||
191 | struct spi_message msg; | ||
192 | struct spi_transfer tx[3]; | ||
193 | static const u8 enable[] = ISC_ENABLE; | ||
194 | static const u8 erase[] = ISC_ERASE; | ||
195 | static const u8 initaddr[] = LSC_INITADDRESS; | ||
196 | unsigned long status; | ||
197 | int ret; | ||
198 | |||
199 | if ((info->flags & FPGA_MGR_PARTIAL_RECONFIG)) { | ||
200 | dev_err(&mgr->dev, | ||
201 | "Partial reconfiguration is not supported\n"); | ||
202 | return -ENOTSUPP; | ||
203 | } | ||
204 | |||
205 | get_status(spi, &status); | ||
206 | dump_status_reg(&status); | ||
207 | memset(tx, 0, sizeof(tx)); | ||
208 | spi_message_init(&msg); | ||
209 | tx[0].tx_buf = &enable; | ||
210 | tx[0].len = sizeof(enable); | ||
211 | tx[0].delay_usecs = MACHXO2_LOW_DELAY_USEC; | ||
212 | spi_message_add_tail(&tx[0], &msg); | ||
213 | |||
214 | tx[1].tx_buf = &erase; | ||
215 | tx[1].len = sizeof(erase); | ||
216 | spi_message_add_tail(&tx[1], &msg); | ||
217 | ret = spi_sync(spi, &msg); | ||
218 | if (ret) | ||
219 | goto fail; | ||
220 | |||
221 | ret = wait_until_not_busy(spi); | ||
222 | if (ret) | ||
223 | goto fail; | ||
224 | |||
225 | get_status(spi, &status); | ||
226 | if (test_bit(FAIL, &status)) | ||
227 | goto fail; | ||
228 | dump_status_reg(&status); | ||
229 | |||
230 | spi_message_init(&msg); | ||
231 | tx[2].tx_buf = &initaddr; | ||
232 | tx[2].len = sizeof(initaddr); | ||
233 | spi_message_add_tail(&tx[2], &msg); | ||
234 | ret = spi_sync(spi, &msg); | ||
235 | if (ret) | ||
236 | goto fail; | ||
237 | |||
238 | get_status(spi, &status); | ||
239 | dump_status_reg(&status); | ||
240 | |||
241 | return 0; | ||
242 | fail: | ||
243 | dev_err(&mgr->dev, "Error during FPGA init.\n"); | ||
244 | |||
245 | return ret; | ||
246 | } | ||
247 | |||
248 | static int machxo2_write(struct fpga_manager *mgr, const char *buf, | ||
249 | size_t count) | ||
250 | { | ||
251 | struct spi_device *spi = mgr->priv; | ||
252 | struct spi_message msg; | ||
253 | struct spi_transfer tx; | ||
254 | static const u8 progincr[] = LSC_PROGINCRNV; | ||
255 | u8 payload[MACHXO2_BUF_SIZE]; | ||
256 | unsigned long status; | ||
257 | int i, ret; | ||
258 | |||
259 | if (count % MACHXO2_PAGE_SIZE != 0) { | ||
260 | dev_err(&mgr->dev, "Malformed payload.\n"); | ||
261 | return -EINVAL; | ||
262 | } | ||
263 | get_status(spi, &status); | ||
264 | dump_status_reg(&status); | ||
265 | memcpy(payload, &progincr, sizeof(progincr)); | ||
266 | for (i = 0; i < count; i += MACHXO2_PAGE_SIZE) { | ||
267 | memcpy(&payload[sizeof(progincr)], &buf[i], MACHXO2_PAGE_SIZE); | ||
268 | memset(&tx, 0, sizeof(tx)); | ||
269 | spi_message_init(&msg); | ||
270 | tx.tx_buf = payload; | ||
271 | tx.len = MACHXO2_BUF_SIZE; | ||
272 | tx.delay_usecs = MACHXO2_HIGH_DELAY_USEC; | ||
273 | spi_message_add_tail(&tx, &msg); | ||
274 | ret = spi_sync(spi, &msg); | ||
275 | if (ret) { | ||
276 | dev_err(&mgr->dev, "Error loading the bitstream.\n"); | ||
277 | return ret; | ||
278 | } | ||
279 | } | ||
280 | get_status(spi, &status); | ||
281 | dump_status_reg(&status); | ||
282 | |||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | static int machxo2_write_complete(struct fpga_manager *mgr, | ||
287 | struct fpga_image_info *info) | ||
288 | { | ||
289 | struct spi_device *spi = mgr->priv; | ||
290 | struct spi_message msg; | ||
291 | struct spi_transfer tx[2]; | ||
292 | static const u8 progdone[] = ISC_PROGRAMDONE; | ||
293 | static const u8 refresh[] = LSC_REFRESH; | ||
294 | unsigned long status; | ||
295 | int ret, refreshloop = 0; | ||
296 | |||
297 | memset(tx, 0, sizeof(tx)); | ||
298 | spi_message_init(&msg); | ||
299 | tx[0].tx_buf = &progdone; | ||
300 | tx[0].len = sizeof(progdone); | ||
301 | spi_message_add_tail(&tx[0], &msg); | ||
302 | ret = spi_sync(spi, &msg); | ||
303 | if (ret) | ||
304 | goto fail; | ||
305 | ret = wait_until_not_busy(spi); | ||
306 | if (ret) | ||
307 | goto fail; | ||
308 | |||
309 | get_status(spi, &status); | ||
310 | dump_status_reg(&status); | ||
311 | if (!test_bit(DONE, &status)) { | ||
312 | machxo2_cleanup(mgr); | ||
313 | goto fail; | ||
314 | } | ||
315 | |||
316 | do { | ||
317 | spi_message_init(&msg); | ||
318 | tx[1].tx_buf = &refresh; | ||
319 | tx[1].len = sizeof(refresh); | ||
320 | tx[1].delay_usecs = MACHXO2_REFRESH_USEC; | ||
321 | spi_message_add_tail(&tx[1], &msg); | ||
322 | ret = spi_sync(spi, &msg); | ||
323 | if (ret) | ||
324 | goto fail; | ||
325 | |||
326 | /* check refresh status */ | ||
327 | get_status(spi, &status); | ||
328 | dump_status_reg(&status); | ||
329 | if (!test_bit(BUSY, &status) && test_bit(DONE, &status) && | ||
330 | get_err(&status) == ENOERR) | ||
331 | break; | ||
332 | if (++refreshloop == MACHXO2_MAX_REFRESH_LOOP) { | ||
333 | machxo2_cleanup(mgr); | ||
334 | goto fail; | ||
335 | } | ||
336 | } while (1); | ||
337 | |||
338 | get_status(spi, &status); | ||
339 | dump_status_reg(&status); | ||
340 | |||
341 | return 0; | ||
342 | fail: | ||
343 | dev_err(&mgr->dev, "Refresh failed.\n"); | ||
344 | |||
345 | return ret; | ||
346 | } | ||
347 | |||
348 | static const struct fpga_manager_ops machxo2_ops = { | ||
349 | .state = machxo2_spi_state, | ||
350 | .write_init = machxo2_write_init, | ||
351 | .write = machxo2_write, | ||
352 | .write_complete = machxo2_write_complete, | ||
353 | }; | ||
354 | |||
355 | static int machxo2_spi_probe(struct spi_device *spi) | ||
356 | { | ||
357 | struct device *dev = &spi->dev; | ||
358 | struct fpga_manager *mgr; | ||
359 | int ret; | ||
360 | |||
361 | if (spi->max_speed_hz > MACHXO2_MAX_SPEED) { | ||
362 | dev_err(dev, "Speed is too high\n"); | ||
363 | return -EINVAL; | ||
364 | } | ||
365 | |||
366 | mgr = fpga_mgr_create(dev, "Lattice MachXO2 SPI FPGA Manager", | ||
367 | &machxo2_ops, spi); | ||
368 | if (!mgr) | ||
369 | return -ENOMEM; | ||
370 | |||
371 | spi_set_drvdata(spi, mgr); | ||
372 | |||
373 | ret = fpga_mgr_register(mgr); | ||
374 | if (ret) | ||
375 | fpga_mgr_free(mgr); | ||
376 | |||
377 | return ret; | ||
378 | } | ||
379 | |||
380 | static int machxo2_spi_remove(struct spi_device *spi) | ||
381 | { | ||
382 | struct fpga_manager *mgr = spi_get_drvdata(spi); | ||
383 | |||
384 | fpga_mgr_unregister(mgr); | ||
385 | |||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | static const struct of_device_id of_match[] = { | ||
390 | { .compatible = "lattice,machxo2-slave-spi", }, | ||
391 | {} | ||
392 | }; | ||
393 | MODULE_DEVICE_TABLE(of, of_match); | ||
394 | |||
395 | static const struct spi_device_id lattice_ids[] = { | ||
396 | { "machxo2-slave-spi", 0 }, | ||
397 | { }, | ||
398 | }; | ||
399 | MODULE_DEVICE_TABLE(spi, lattice_ids); | ||
400 | |||
401 | static struct spi_driver machxo2_spi_driver = { | ||
402 | .driver = { | ||
403 | .name = "machxo2-slave-spi", | ||
404 | .of_match_table = of_match_ptr(of_match), | ||
405 | }, | ||
406 | .probe = machxo2_spi_probe, | ||
407 | .remove = machxo2_spi_remove, | ||
408 | .id_table = lattice_ids, | ||
409 | }; | ||
410 | |||
411 | module_spi_driver(machxo2_spi_driver) | ||
412 | |||
413 | MODULE_AUTHOR("Paolo Pisati <p.pisati@gmail.com>"); | ||
414 | MODULE_DESCRIPTION("Load Lattice FPGA firmware over SPI"); | ||
415 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c index 119ff75522f1..35fabb8083fb 100644 --- a/drivers/fpga/of-fpga-region.c +++ b/drivers/fpga/of-fpga-region.c | |||
@@ -1,22 +1,10 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * FPGA Region - Device Tree support for FPGA programming under Linux | 3 | * FPGA Region - Device Tree support for FPGA programming under Linux |
3 | * | 4 | * |
4 | * Copyright (C) 2013-2016 Altera Corporation | 5 | * Copyright (C) 2013-2016 Altera Corporation |
5 | * Copyright (C) 2017 Intel Corporation | 6 | * Copyright (C) 2017 Intel Corporation |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms and conditions of the GNU General Public License, | ||
9 | * version 2, as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | 7 | */ |
19 | |||
20 | #include <linux/fpga/fpga-bridge.h> | 8 | #include <linux/fpga/fpga-bridge.h> |
21 | #include <linux/fpga/fpga-mgr.h> | 9 | #include <linux/fpga/fpga-mgr.h> |
22 | #include <linux/fpga/fpga-region.h> | 10 | #include <linux/fpga/fpga-region.h> |
@@ -422,27 +410,25 @@ static int of_fpga_region_probe(struct platform_device *pdev) | |||
422 | if (IS_ERR(mgr)) | 410 | if (IS_ERR(mgr)) |
423 | return -EPROBE_DEFER; | 411 | return -EPROBE_DEFER; |
424 | 412 | ||
425 | region = devm_kzalloc(dev, sizeof(*region), GFP_KERNEL); | 413 | region = fpga_region_create(dev, mgr, of_fpga_region_get_bridges); |
426 | if (!region) { | 414 | if (!region) { |
427 | ret = -ENOMEM; | 415 | ret = -ENOMEM; |
428 | goto eprobe_mgr_put; | 416 | goto eprobe_mgr_put; |
429 | } | 417 | } |
430 | 418 | ||
431 | region->mgr = mgr; | 419 | ret = fpga_region_register(region); |
432 | |||
433 | /* Specify how to get bridges for this type of region. */ | ||
434 | region->get_bridges = of_fpga_region_get_bridges; | ||
435 | |||
436 | ret = fpga_region_register(dev, region); | ||
437 | if (ret) | 420 | if (ret) |
438 | goto eprobe_mgr_put; | 421 | goto eprobe_free; |
439 | 422 | ||
440 | of_platform_populate(np, fpga_region_of_match, NULL, ®ion->dev); | 423 | of_platform_populate(np, fpga_region_of_match, NULL, ®ion->dev); |
424 | dev_set_drvdata(dev, region); | ||
441 | 425 | ||
442 | dev_info(dev, "FPGA Region probed\n"); | 426 | dev_info(dev, "FPGA Region probed\n"); |
443 | 427 | ||
444 | return 0; | 428 | return 0; |
445 | 429 | ||
430 | eprobe_free: | ||
431 | fpga_region_free(region); | ||
446 | eprobe_mgr_put: | 432 | eprobe_mgr_put: |
447 | fpga_mgr_put(mgr); | 433 | fpga_mgr_put(mgr); |
448 | return ret; | 434 | return ret; |
diff --git a/drivers/fpga/socfpga-a10.c b/drivers/fpga/socfpga-a10.c index a46e343a5b72..be30c48eb6e4 100644 --- a/drivers/fpga/socfpga-a10.c +++ b/drivers/fpga/socfpga-a10.c | |||
@@ -1,21 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * FPGA Manager Driver for Altera Arria10 SoCFPGA | 3 | * FPGA Manager Driver for Altera Arria10 SoCFPGA |
3 | * | 4 | * |
4 | * Copyright (C) 2015-2016 Altera Corporation | 5 | * 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 | */ | 6 | */ |
18 | |||
19 | #include <linux/clk.h> | 7 | #include <linux/clk.h> |
20 | #include <linux/device.h> | 8 | #include <linux/device.h> |
21 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
@@ -482,6 +470,7 @@ static int socfpga_a10_fpga_probe(struct platform_device *pdev) | |||
482 | struct device *dev = &pdev->dev; | 470 | struct device *dev = &pdev->dev; |
483 | struct a10_fpga_priv *priv; | 471 | struct a10_fpga_priv *priv; |
484 | void __iomem *reg_base; | 472 | void __iomem *reg_base; |
473 | struct fpga_manager *mgr; | ||
485 | struct resource *res; | 474 | struct resource *res; |
486 | int ret; | 475 | int ret; |
487 | 476 | ||
@@ -519,9 +508,16 @@ static int socfpga_a10_fpga_probe(struct platform_device *pdev) | |||
519 | return -EBUSY; | 508 | return -EBUSY; |
520 | } | 509 | } |
521 | 510 | ||
522 | ret = fpga_mgr_register(dev, "SoCFPGA Arria10 FPGA Manager", | 511 | mgr = fpga_mgr_create(dev, "SoCFPGA Arria10 FPGA Manager", |
523 | &socfpga_a10_fpga_mgr_ops, priv); | 512 | &socfpga_a10_fpga_mgr_ops, priv); |
513 | if (!mgr) | ||
514 | return -ENOMEM; | ||
515 | |||
516 | platform_set_drvdata(pdev, mgr); | ||
517 | |||
518 | ret = fpga_mgr_register(mgr); | ||
524 | if (ret) { | 519 | if (ret) { |
520 | fpga_mgr_free(mgr); | ||
525 | clk_disable_unprepare(priv->clk); | 521 | clk_disable_unprepare(priv->clk); |
526 | return ret; | 522 | return ret; |
527 | } | 523 | } |
@@ -534,7 +530,7 @@ static int socfpga_a10_fpga_remove(struct platform_device *pdev) | |||
534 | struct fpga_manager *mgr = platform_get_drvdata(pdev); | 530 | struct fpga_manager *mgr = platform_get_drvdata(pdev); |
535 | struct a10_fpga_priv *priv = mgr->priv; | 531 | struct a10_fpga_priv *priv = mgr->priv; |
536 | 532 | ||
537 | fpga_mgr_unregister(&pdev->dev); | 533 | fpga_mgr_unregister(mgr); |
538 | clk_disable_unprepare(priv->clk); | 534 | clk_disable_unprepare(priv->clk); |
539 | 535 | ||
540 | return 0; | 536 | return 0; |
diff --git a/drivers/fpga/socfpga.c b/drivers/fpga/socfpga.c index b6672e66cda6..959d71f26896 100644 --- a/drivers/fpga/socfpga.c +++ b/drivers/fpga/socfpga.c | |||
@@ -1,19 +1,8 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * FPGA Manager Driver for Altera SOCFPGA | 3 | * FPGA Manager Driver for Altera SOCFPGA |
3 | * | 4 | * |
4 | * Copyright (C) 2013-2015 Altera Corporation | 5 | * Copyright (C) 2013-2015 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 | */ | 6 | */ |
18 | #include <linux/completion.h> | 7 | #include <linux/completion.h> |
19 | #include <linux/delay.h> | 8 | #include <linux/delay.h> |
@@ -555,6 +544,7 @@ static int socfpga_fpga_probe(struct platform_device *pdev) | |||
555 | { | 544 | { |
556 | struct device *dev = &pdev->dev; | 545 | struct device *dev = &pdev->dev; |
557 | struct socfpga_fpga_priv *priv; | 546 | struct socfpga_fpga_priv *priv; |
547 | struct fpga_manager *mgr; | ||
558 | struct resource *res; | 548 | struct resource *res; |
559 | int ret; | 549 | int ret; |
560 | 550 | ||
@@ -581,13 +571,25 @@ static int socfpga_fpga_probe(struct platform_device *pdev) | |||
581 | if (ret) | 571 | if (ret) |
582 | return ret; | 572 | return ret; |
583 | 573 | ||
584 | return fpga_mgr_register(dev, "Altera SOCFPGA FPGA Manager", | 574 | mgr = fpga_mgr_create(dev, "Altera SOCFPGA FPGA Manager", |
585 | &socfpga_fpga_ops, priv); | 575 | &socfpga_fpga_ops, priv); |
576 | if (!mgr) | ||
577 | return -ENOMEM; | ||
578 | |||
579 | platform_set_drvdata(pdev, mgr); | ||
580 | |||
581 | ret = fpga_mgr_register(mgr); | ||
582 | if (ret) | ||
583 | fpga_mgr_free(mgr); | ||
584 | |||
585 | return ret; | ||
586 | } | 586 | } |
587 | 587 | ||
588 | static int socfpga_fpga_remove(struct platform_device *pdev) | 588 | static int socfpga_fpga_remove(struct platform_device *pdev) |
589 | { | 589 | { |
590 | fpga_mgr_unregister(&pdev->dev); | 590 | struct fpga_manager *mgr = platform_get_drvdata(pdev); |
591 | |||
592 | fpga_mgr_unregister(mgr); | ||
591 | 593 | ||
592 | return 0; | 594 | return 0; |
593 | } | 595 | } |
diff --git a/drivers/fpga/ts73xx-fpga.c b/drivers/fpga/ts73xx-fpga.c index f6a96b42e2ca..08efd1895b1b 100644 --- a/drivers/fpga/ts73xx-fpga.c +++ b/drivers/fpga/ts73xx-fpga.c | |||
@@ -116,7 +116,9 @@ static int ts73xx_fpga_probe(struct platform_device *pdev) | |||
116 | { | 116 | { |
117 | struct device *kdev = &pdev->dev; | 117 | struct device *kdev = &pdev->dev; |
118 | struct ts73xx_fpga_priv *priv; | 118 | struct ts73xx_fpga_priv *priv; |
119 | struct fpga_manager *mgr; | ||
119 | struct resource *res; | 120 | struct resource *res; |
121 | int ret; | ||
120 | 122 | ||
121 | priv = devm_kzalloc(kdev, sizeof(*priv), GFP_KERNEL); | 123 | priv = devm_kzalloc(kdev, sizeof(*priv), GFP_KERNEL); |
122 | if (!priv) | 124 | if (!priv) |
@@ -131,13 +133,25 @@ static int ts73xx_fpga_probe(struct platform_device *pdev) | |||
131 | return PTR_ERR(priv->io_base); | 133 | return PTR_ERR(priv->io_base); |
132 | } | 134 | } |
133 | 135 | ||
134 | return fpga_mgr_register(kdev, "TS-73xx FPGA Manager", | 136 | mgr = fpga_mgr_create(kdev, "TS-73xx FPGA Manager", |
135 | &ts73xx_fpga_ops, priv); | 137 | &ts73xx_fpga_ops, priv); |
138 | if (!mgr) | ||
139 | return -ENOMEM; | ||
140 | |||
141 | platform_set_drvdata(pdev, mgr); | ||
142 | |||
143 | ret = fpga_mgr_register(mgr); | ||
144 | if (ret) | ||
145 | fpga_mgr_free(mgr); | ||
146 | |||
147 | return ret; | ||
136 | } | 148 | } |
137 | 149 | ||
138 | static int ts73xx_fpga_remove(struct platform_device *pdev) | 150 | static int ts73xx_fpga_remove(struct platform_device *pdev) |
139 | { | 151 | { |
140 | fpga_mgr_unregister(&pdev->dev); | 152 | struct fpga_manager *mgr = platform_get_drvdata(pdev); |
153 | |||
154 | fpga_mgr_unregister(mgr); | ||
141 | 155 | ||
142 | return 0; | 156 | return 0; |
143 | } | 157 | } |
diff --git a/drivers/fpga/xilinx-pr-decoupler.c b/drivers/fpga/xilinx-pr-decoupler.c index 0d7743089414..07ba1539e82c 100644 --- a/drivers/fpga/xilinx-pr-decoupler.c +++ b/drivers/fpga/xilinx-pr-decoupler.c | |||
@@ -94,6 +94,7 @@ MODULE_DEVICE_TABLE(of, xlnx_pr_decoupler_of_match); | |||
94 | static int xlnx_pr_decoupler_probe(struct platform_device *pdev) | 94 | static int xlnx_pr_decoupler_probe(struct platform_device *pdev) |
95 | { | 95 | { |
96 | struct xlnx_pr_decoupler_data *priv; | 96 | struct xlnx_pr_decoupler_data *priv; |
97 | struct fpga_bridge *br; | ||
97 | int err; | 98 | int err; |
98 | struct resource *res; | 99 | struct resource *res; |
99 | 100 | ||
@@ -120,16 +121,27 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev) | |||
120 | 121 | ||
121 | clk_disable(priv->clk); | 122 | clk_disable(priv->clk); |
122 | 123 | ||
123 | err = fpga_bridge_register(&pdev->dev, "Xilinx PR Decoupler", | 124 | br = fpga_bridge_create(&pdev->dev, "Xilinx PR Decoupler", |
124 | &xlnx_pr_decoupler_br_ops, priv); | 125 | &xlnx_pr_decoupler_br_ops, priv); |
126 | if (!br) { | ||
127 | err = -ENOMEM; | ||
128 | goto err_clk; | ||
129 | } | ||
130 | |||
131 | platform_set_drvdata(pdev, br); | ||
125 | 132 | ||
133 | err = fpga_bridge_register(br); | ||
126 | if (err) { | 134 | if (err) { |
127 | dev_err(&pdev->dev, "unable to register Xilinx PR Decoupler"); | 135 | dev_err(&pdev->dev, "unable to register Xilinx PR Decoupler"); |
128 | clk_unprepare(priv->clk); | 136 | goto err_clk; |
129 | return err; | ||
130 | } | 137 | } |
131 | 138 | ||
132 | return 0; | 139 | return 0; |
140 | |||
141 | err_clk: | ||
142 | clk_unprepare(priv->clk); | ||
143 | |||
144 | return err; | ||
133 | } | 145 | } |
134 | 146 | ||
135 | static int xlnx_pr_decoupler_remove(struct platform_device *pdev) | 147 | static int xlnx_pr_decoupler_remove(struct platform_device *pdev) |
@@ -137,7 +149,7 @@ static int xlnx_pr_decoupler_remove(struct platform_device *pdev) | |||
137 | struct fpga_bridge *bridge = platform_get_drvdata(pdev); | 149 | struct fpga_bridge *bridge = platform_get_drvdata(pdev); |
138 | struct xlnx_pr_decoupler_data *p = bridge->priv; | 150 | struct xlnx_pr_decoupler_data *p = bridge->priv; |
139 | 151 | ||
140 | fpga_bridge_unregister(&pdev->dev); | 152 | fpga_bridge_unregister(bridge); |
141 | 153 | ||
142 | clk_unprepare(p->clk); | 154 | clk_unprepare(p->clk); |
143 | 155 | ||
diff --git a/drivers/fpga/xilinx-spi.c b/drivers/fpga/xilinx-spi.c index 9b62a4c2a3df..8d1945966533 100644 --- a/drivers/fpga/xilinx-spi.c +++ b/drivers/fpga/xilinx-spi.c | |||
@@ -143,6 +143,8 @@ static const struct fpga_manager_ops xilinx_spi_ops = { | |||
143 | static int xilinx_spi_probe(struct spi_device *spi) | 143 | static int xilinx_spi_probe(struct spi_device *spi) |
144 | { | 144 | { |
145 | struct xilinx_spi_conf *conf; | 145 | struct xilinx_spi_conf *conf; |
146 | struct fpga_manager *mgr; | ||
147 | int ret; | ||
146 | 148 | ||
147 | conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL); | 149 | conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL); |
148 | if (!conf) | 150 | if (!conf) |
@@ -165,13 +167,25 @@ static int xilinx_spi_probe(struct spi_device *spi) | |||
165 | return PTR_ERR(conf->done); | 167 | return PTR_ERR(conf->done); |
166 | } | 168 | } |
167 | 169 | ||
168 | return fpga_mgr_register(&spi->dev, "Xilinx Slave Serial FPGA Manager", | 170 | mgr = fpga_mgr_create(&spi->dev, "Xilinx Slave Serial FPGA Manager", |
169 | &xilinx_spi_ops, conf); | 171 | &xilinx_spi_ops, conf); |
172 | if (!mgr) | ||
173 | return -ENOMEM; | ||
174 | |||
175 | spi_set_drvdata(spi, mgr); | ||
176 | |||
177 | ret = fpga_mgr_register(mgr); | ||
178 | if (ret) | ||
179 | fpga_mgr_free(mgr); | ||
180 | |||
181 | return ret; | ||
170 | } | 182 | } |
171 | 183 | ||
172 | static int xilinx_spi_remove(struct spi_device *spi) | 184 | static int xilinx_spi_remove(struct spi_device *spi) |
173 | { | 185 | { |
174 | fpga_mgr_unregister(&spi->dev); | 186 | struct fpga_manager *mgr = spi_get_drvdata(spi); |
187 | |||
188 | fpga_mgr_unregister(mgr); | ||
175 | 189 | ||
176 | return 0; | 190 | return 0; |
177 | } | 191 | } |
diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c index 70b15b303471..3110e00121ca 100644 --- a/drivers/fpga/zynq-fpga.c +++ b/drivers/fpga/zynq-fpga.c | |||
@@ -558,6 +558,7 @@ static int zynq_fpga_probe(struct platform_device *pdev) | |||
558 | { | 558 | { |
559 | struct device *dev = &pdev->dev; | 559 | struct device *dev = &pdev->dev; |
560 | struct zynq_fpga_priv *priv; | 560 | struct zynq_fpga_priv *priv; |
561 | struct fpga_manager *mgr; | ||
561 | struct resource *res; | 562 | struct resource *res; |
562 | int err; | 563 | int err; |
563 | 564 | ||
@@ -613,10 +614,17 @@ static int zynq_fpga_probe(struct platform_device *pdev) | |||
613 | 614 | ||
614 | clk_disable(priv->clk); | 615 | clk_disable(priv->clk); |
615 | 616 | ||
616 | err = fpga_mgr_register(dev, "Xilinx Zynq FPGA Manager", | 617 | mgr = fpga_mgr_create(dev, "Xilinx Zynq FPGA Manager", |
617 | &zynq_fpga_ops, priv); | 618 | &zynq_fpga_ops, priv); |
619 | if (!mgr) | ||
620 | return -ENOMEM; | ||
621 | |||
622 | platform_set_drvdata(pdev, mgr); | ||
623 | |||
624 | err = fpga_mgr_register(mgr); | ||
618 | if (err) { | 625 | if (err) { |
619 | dev_err(dev, "unable to register FPGA manager\n"); | 626 | dev_err(dev, "unable to register FPGA manager\n"); |
627 | fpga_mgr_free(mgr); | ||
620 | clk_unprepare(priv->clk); | 628 | clk_unprepare(priv->clk); |
621 | return err; | 629 | return err; |
622 | } | 630 | } |
@@ -632,7 +640,7 @@ static int zynq_fpga_remove(struct platform_device *pdev) | |||
632 | mgr = platform_get_drvdata(pdev); | 640 | mgr = platform_get_drvdata(pdev); |
633 | priv = mgr->priv; | 641 | priv = mgr->priv; |
634 | 642 | ||
635 | fpga_mgr_unregister(&pdev->dev); | 643 | fpga_mgr_unregister(mgr); |
636 | 644 | ||
637 | clk_unprepare(priv->clk); | 645 | clk_unprepare(priv->clk); |
638 | 646 | ||