mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
fpga: xilinx-selectmap: control CSI_B and RDWR_B during configuration
The driver requests the optional CSI_B and RDWR_B GPIOs with GPIOD_OUT_HIGH and never touches them again. That flag carries a logical value, so both signals end up asserted from probe on, whatever polarity the device tree states, and they stay asserted for the lifetime of the device. Neither signal belongs to the driver's lifetime. CSI_B (Chip Select) selects the device on the SelectMAP port, RDWR_B (Read/Write) selects the transfer direction, so both belong to the data transfer. A device that is never deselected never lets go of the port, and a port pinned to write mode cannot be read back. Keep the two descriptors in the driver private data, request them deasserted, and assert them only around the configuration data transfer. RDWR_B is asserted first, UG470 describes in chapter "SelectMAP ABORT" that changing it while the device is selected aborts the configuration on the next CCLK. Signed-off-by: Heiko Schocher <hs@nabladev.com> Reviewed-by: Xu Yilun <yilun.xu@intel.com> Link: https://lore.kernel.org/r/20260909112200.13256-1-hs@nabladev.com Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
This commit is contained in:
parent
a090601269
commit
4e3ca71894
|
|
@ -19,6 +19,8 @@
|
|||
struct xilinx_selectmap_conf {
|
||||
struct xilinx_fpga_core core;
|
||||
void __iomem *base;
|
||||
struct gpio_desc *csi_b;
|
||||
struct gpio_desc *rdwr_b;
|
||||
};
|
||||
|
||||
#define to_xilinx_selectmap_conf(obj) \
|
||||
|
|
@ -30,16 +32,28 @@ static int xilinx_selectmap_write(struct xilinx_fpga_core *core,
|
|||
struct xilinx_selectmap_conf *conf = to_xilinx_selectmap_conf(core);
|
||||
size_t i;
|
||||
|
||||
/*
|
||||
* Select this device and put its SelectMAP port into write mode.
|
||||
*
|
||||
* RDWR_B is set before CSI_B. UG470 describes in chapter
|
||||
* "SelectMAP ABORT" that changing RDWR_B while the device is
|
||||
* selected aborts the configuration on the next CCLK.
|
||||
*/
|
||||
gpiod_set_value(conf->rdwr_b, 1);
|
||||
gpiod_set_value(conf->csi_b, 1);
|
||||
|
||||
for (i = 0; i < count; ++i)
|
||||
writeb(buf[i], conf->base);
|
||||
|
||||
gpiod_set_value(conf->csi_b, 0);
|
||||
gpiod_set_value(conf->rdwr_b, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xilinx_selectmap_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct xilinx_selectmap_conf *conf;
|
||||
struct gpio_desc *gpio;
|
||||
void __iomem *base;
|
||||
|
||||
conf = devm_kzalloc(&pdev->dev, sizeof(*conf), GFP_KERNEL);
|
||||
|
|
@ -55,16 +69,23 @@ static int xilinx_selectmap_probe(struct platform_device *pdev)
|
|||
"ioremap error\n");
|
||||
conf->base = base;
|
||||
|
||||
/* CSI_B is active low */
|
||||
gpio = devm_gpiod_get_optional(&pdev->dev, "csi", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(gpio))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(gpio),
|
||||
/*
|
||||
* Request both signals deasserted, so a device sharing the SelectMAP
|
||||
* bus with others stays off that bus until its bitstream is written.
|
||||
*
|
||||
* The value in the gpiod flags is logical, gpiolib drives the line
|
||||
* high for GPIOD_OUT_LOW when the firmware describes it active low.
|
||||
*/
|
||||
conf->csi_b = devm_gpiod_get_optional(&pdev->dev, "csi",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(conf->csi_b))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(conf->csi_b),
|
||||
"Failed to get CSI_B gpio\n");
|
||||
|
||||
/* RDWR_B is active low */
|
||||
gpio = devm_gpiod_get_optional(&pdev->dev, "rdwr", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(gpio))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(gpio),
|
||||
conf->rdwr_b = devm_gpiod_get_optional(&pdev->dev, "rdwr",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(conf->rdwr_b))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(conf->rdwr_b),
|
||||
"Failed to get RDWR_B gpio\n");
|
||||
|
||||
return xilinx_core_probe(&conf->core);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user