FPGA Manager changes for 5.8

Here's the first set of changes for the 5.8-rc1 merge window.
 
 Dominic's change adds support for accessing AFU regions with gdb.
 Gustavo's change is a cleanup patch regarding variable lenght arrays.
 Richard's changes update dt-bindings and add support for stratix and agilex.
 Sergiu's changes update spi transfers with the new delay field.
 Xu's change addresses an issue with a wrong return value.
 Shubhrajyoti's change makes the Zynq FPGA driver return -EPROBE_DEFER on
 check of devm_clk_get failure.
 Xu's change for DFL enables multiple opens.
 
 All of these patches have been reviewed, have appropriate Acked-by's and
 have been in the last few linux-next releases without issues.
 
 Signed-off-by: Moritz Fischer <mdf@kernel.org>
 -----BEGIN PGP SIGNATURE-----
 
 iIUEABYIAC0WIQS/ea/a56fFi9QbQeJ+E8eWOj6VqQUCXrbxaw8cbWRmQGtlcm5l
 bC5vcmcACgkQfhPHljo+lamnQAD/dQa0AzlcPyIbo6pcufwyeZPgjKEunXiCd0vc
 nb1caZEBAMV69oNK441+vYy911LuY6x/hdz0Ch4E4NQK0zjUrAcM
 =LWCH
 -----END PGP SIGNATURE-----

Merge tag 'fpga-for-5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/mdf/linux-fpga into char-misc-next

Moritz writes:

FPGA Manager changes for 5.8

Here's the first set of changes for the 5.8-rc1 merge window.

Dominic's change adds support for accessing AFU regions with gdb.
Gustavo's change is a cleanup patch regarding variable lenght arrays.
Richard's changes update dt-bindings and add support for stratix and agilex.
Sergiu's changes update spi transfers with the new delay field.
Xu's change addresses an issue with a wrong return value.
Shubhrajyoti's change makes the Zynq FPGA driver return -EPROBE_DEFER on
check of devm_clk_get failure.
Xu's change for DFL enables multiple opens.

All of these patches have been reviewed, have appropriate Acked-by's and
have been in the last few linux-next releases without issues.

Signed-off-by: Moritz Fischer <mdf@kernel.org>

* tag 'fpga-for-5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/mdf/linux-fpga:
  fpga: dfl: afu: support debug access to memory-mapped afu regions
  fpga: dfl.h: Replace zero-length array with flexible-array member
  arm64: dts: agilex: correct service layer driver's compatible value
  dt-bindings, firmware: add compatible value Intel Stratix10 service layer binding
  fpga: stratix10-soc: add compatible property value for intel agilex
  arm64: dts: agilex: correct FPGA manager driver's compatible value
  dt-bindings: fpga: add compatible value to Stratix10 SoC FPGA manager binding
  fpga: machxo2-spi: Use new structure for SPI transfer delays
  fpga: ice40-spi: Use new structure for SPI transfer delays
  fpga: dfl: support multiple opens on feature device node.
This commit is contained in:
Greg Kroah-Hartman 2020-05-15 16:09:24 +02:00
commit f877a18c08
10 changed files with 100 additions and 40 deletions

View File

@ -23,7 +23,7 @@ Required properties:
The svc node has the following mandatory properties, must be located under The svc node has the following mandatory properties, must be located under
the firmware node. the firmware node.
- compatible: "intel,stratix10-svc" - compatible: "intel,stratix10-svc" or "intel,agilex-svc"
- method: smc or hvc - method: smc or hvc
smc - Secure Monitor Call smc - Secure Monitor Call
hvc - Hypervisor Call hvc - Hypervisor Call

View File

@ -4,7 +4,8 @@ Required properties:
The fpga_mgr node has the following mandatory property, must be located under The fpga_mgr node has the following mandatory property, must be located under
firmware/svc node. firmware/svc node.
- compatible : should contain "intel,stratix10-soc-fpga-mgr" - compatible : should contain "intel,stratix10-soc-fpga-mgr" or
"intel,agilex-soc-fpga-mgr"
Example: Example:

View File

@ -539,12 +539,12 @@ qspi: spi@ff8d2000 {
firmware { firmware {
svc { svc {
compatible = "intel,stratix10-svc"; compatible = "intel,agilex-svc";
method = "smc"; method = "smc";
memory-region = <&service_reserved>; memory-region = <&service_reserved>;
fpga_mgr: fpga-mgr { fpga_mgr: fpga-mgr {
compatible = "intel,stratix10-soc-fpga-mgr"; compatible = "intel,agilex-soc-fpga-mgr";
}; };
}; };
}; };

View File

@ -561,14 +561,16 @@ static int afu_open(struct inode *inode, struct file *filp)
if (WARN_ON(!pdata)) if (WARN_ON(!pdata))
return -ENODEV; return -ENODEV;
ret = dfl_feature_dev_use_begin(pdata); mutex_lock(&pdata->lock);
if (ret) ret = dfl_feature_dev_use_begin(pdata, filp->f_flags & O_EXCL);
return ret; if (!ret) {
dev_dbg(&fdev->dev, "Device File Opened %d Times\n",
dfl_feature_dev_use_count(pdata));
filp->private_data = fdev;
}
mutex_unlock(&pdata->lock);
dev_dbg(&fdev->dev, "Device File Open\n"); return ret;
filp->private_data = fdev;
return 0;
} }
static int afu_release(struct inode *inode, struct file *filp) static int afu_release(struct inode *inode, struct file *filp)
@ -581,12 +583,14 @@ static int afu_release(struct inode *inode, struct file *filp)
pdata = dev_get_platdata(&pdev->dev); pdata = dev_get_platdata(&pdev->dev);
mutex_lock(&pdata->lock); mutex_lock(&pdata->lock);
__port_reset(pdev);
afu_dma_region_destroy(pdata);
mutex_unlock(&pdata->lock);
dfl_feature_dev_use_end(pdata); dfl_feature_dev_use_end(pdata);
if (!dfl_feature_dev_use_count(pdata)) {
__port_reset(pdev);
afu_dma_region_destroy(pdata);
}
mutex_unlock(&pdata->lock);
return 0; return 0;
} }
@ -746,6 +750,12 @@ static long afu_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return -EINVAL; return -EINVAL;
} }
static const struct vm_operations_struct afu_vma_ops = {
#ifdef CONFIG_HAVE_IOREMAP_PROT
.access = generic_access_phys,
#endif
};
static int afu_mmap(struct file *filp, struct vm_area_struct *vma) static int afu_mmap(struct file *filp, struct vm_area_struct *vma)
{ {
struct platform_device *pdev = filp->private_data; struct platform_device *pdev = filp->private_data;
@ -775,6 +785,9 @@ static int afu_mmap(struct file *filp, struct vm_area_struct *vma)
!(region.flags & DFL_PORT_REGION_WRITE)) !(region.flags & DFL_PORT_REGION_WRITE))
return -EPERM; return -EPERM;
/* Support debug access to the mapping */
vma->vm_ops = &afu_vma_ops;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
return remap_pfn_range(vma, vma->vm_start, return remap_pfn_range(vma, vma->vm_start,

View File

@ -604,14 +604,16 @@ static int fme_open(struct inode *inode, struct file *filp)
if (WARN_ON(!pdata)) if (WARN_ON(!pdata))
return -ENODEV; return -ENODEV;
ret = dfl_feature_dev_use_begin(pdata); mutex_lock(&pdata->lock);
if (ret) ret = dfl_feature_dev_use_begin(pdata, filp->f_flags & O_EXCL);
return ret; if (!ret) {
dev_dbg(&fdev->dev, "Device File Opened %d Times\n",
dfl_feature_dev_use_count(pdata));
filp->private_data = pdata;
}
mutex_unlock(&pdata->lock);
dev_dbg(&fdev->dev, "Device File Open\n"); return ret;
filp->private_data = pdata;
return 0;
} }
static int fme_release(struct inode *inode, struct file *filp) static int fme_release(struct inode *inode, struct file *filp)
@ -620,7 +622,10 @@ static int fme_release(struct inode *inode, struct file *filp)
struct platform_device *pdev = pdata->dev; struct platform_device *pdev = pdata->dev;
dev_dbg(&pdev->dev, "Device File Release\n"); dev_dbg(&pdev->dev, "Device File Release\n");
mutex_lock(&pdata->lock);
dfl_feature_dev_use_end(pdata); dfl_feature_dev_use_end(pdata);
mutex_unlock(&pdata->lock);
return 0; return 0;
} }

View File

@ -1079,6 +1079,7 @@ static int __init dfl_fpga_init(void)
*/ */
int dfl_fpga_cdev_release_port(struct dfl_fpga_cdev *cdev, int port_id) int dfl_fpga_cdev_release_port(struct dfl_fpga_cdev *cdev, int port_id)
{ {
struct dfl_feature_platform_data *pdata;
struct platform_device *port_pdev; struct platform_device *port_pdev;
int ret = -ENODEV; int ret = -ENODEV;
@ -1093,7 +1094,11 @@ int dfl_fpga_cdev_release_port(struct dfl_fpga_cdev *cdev, int port_id)
goto put_dev_exit; goto put_dev_exit;
} }
ret = dfl_feature_dev_use_begin(dev_get_platdata(&port_pdev->dev)); pdata = dev_get_platdata(&port_pdev->dev);
mutex_lock(&pdata->lock);
ret = dfl_feature_dev_use_begin(pdata, true);
mutex_unlock(&pdata->lock);
if (ret) if (ret)
goto put_dev_exit; goto put_dev_exit;
@ -1120,6 +1125,7 @@ EXPORT_SYMBOL_GPL(dfl_fpga_cdev_release_port);
*/ */
int dfl_fpga_cdev_assign_port(struct dfl_fpga_cdev *cdev, int port_id) int dfl_fpga_cdev_assign_port(struct dfl_fpga_cdev *cdev, int port_id)
{ {
struct dfl_feature_platform_data *pdata;
struct platform_device *port_pdev; struct platform_device *port_pdev;
int ret = -ENODEV; int ret = -ENODEV;
@ -1138,7 +1144,12 @@ int dfl_fpga_cdev_assign_port(struct dfl_fpga_cdev *cdev, int port_id)
if (ret) if (ret)
goto put_dev_exit; goto put_dev_exit;
dfl_feature_dev_use_end(dev_get_platdata(&port_pdev->dev)); pdata = dev_get_platdata(&port_pdev->dev);
mutex_lock(&pdata->lock);
dfl_feature_dev_use_end(pdata);
mutex_unlock(&pdata->lock);
cdev->released_port_num--; cdev->released_port_num--;
put_dev_exit: put_dev_exit:
put_device(&port_pdev->dev); put_device(&port_pdev->dev);

View File

@ -207,8 +207,6 @@ struct dfl_feature {
void *priv; void *priv;
}; };
#define DEV_STATUS_IN_USE 0
#define FEATURE_DEV_ID_UNUSED (-1) #define FEATURE_DEV_ID_UNUSED (-1)
/** /**
@ -221,8 +219,9 @@ struct dfl_feature {
* @dfl_cdev: ptr to container device. * @dfl_cdev: ptr to container device.
* @id: id used for this feature device. * @id: id used for this feature device.
* @disable_count: count for port disable. * @disable_count: count for port disable.
* @excl_open: set on feature device exclusive open.
* @open_count: count for feature device open.
* @num: number for sub features. * @num: number for sub features.
* @dev_status: dev status (e.g. DEV_STATUS_IN_USE).
* @private: ptr to feature dev private data. * @private: ptr to feature dev private data.
* @features: sub features of this feature dev. * @features: sub features of this feature dev.
*/ */
@ -234,26 +233,46 @@ struct dfl_feature_platform_data {
struct dfl_fpga_cdev *dfl_cdev; struct dfl_fpga_cdev *dfl_cdev;
int id; int id;
unsigned int disable_count; unsigned int disable_count;
unsigned long dev_status; bool excl_open;
int open_count;
void *private; void *private;
int num; int num;
struct dfl_feature features[0]; struct dfl_feature features[];
}; };
static inline static inline
int dfl_feature_dev_use_begin(struct dfl_feature_platform_data *pdata) int dfl_feature_dev_use_begin(struct dfl_feature_platform_data *pdata,
bool excl)
{ {
/* Test and set IN_USE flags to ensure file is exclusively used */ if (pdata->excl_open)
if (test_and_set_bit_lock(DEV_STATUS_IN_USE, &pdata->dev_status))
return -EBUSY; return -EBUSY;
if (excl) {
if (pdata->open_count)
return -EBUSY;
pdata->excl_open = true;
}
pdata->open_count++;
return 0; return 0;
} }
static inline static inline
void dfl_feature_dev_use_end(struct dfl_feature_platform_data *pdata) void dfl_feature_dev_use_end(struct dfl_feature_platform_data *pdata)
{ {
clear_bit_unlock(DEV_STATUS_IN_USE, &pdata->dev_status); pdata->excl_open = false;
if (WARN_ON(pdata->open_count <= 0))
return;
pdata->open_count--;
}
static inline
int dfl_feature_dev_use_count(struct dfl_feature_platform_data *pdata)
{
return pdata->open_count;
} }
static inline static inline

View File

@ -46,10 +46,16 @@ static int ice40_fpga_ops_write_init(struct fpga_manager *mgr,
struct spi_message message; struct spi_message message;
struct spi_transfer assert_cs_then_reset_delay = { struct spi_transfer assert_cs_then_reset_delay = {
.cs_change = 1, .cs_change = 1,
.delay_usecs = ICE40_SPI_RESET_DELAY .delay = {
.value = ICE40_SPI_RESET_DELAY,
.unit = SPI_DELAY_UNIT_USECS
}
}; };
struct spi_transfer housekeeping_delay_then_release_cs = { struct spi_transfer housekeeping_delay_then_release_cs = {
.delay_usecs = ICE40_SPI_HOUSEKEEPING_DELAY .delay = {
.value = ICE40_SPI_HOUSEKEEPING_DELAY,
.unit = SPI_DELAY_UNIT_USECS
}
}; };
int ret; int ret;

View File

@ -157,7 +157,8 @@ static int machxo2_cleanup(struct fpga_manager *mgr)
spi_message_init(&msg); spi_message_init(&msg);
tx[1].tx_buf = &refresh; tx[1].tx_buf = &refresh;
tx[1].len = sizeof(refresh); tx[1].len = sizeof(refresh);
tx[1].delay_usecs = MACHXO2_REFRESH_USEC; tx[1].delay.value = MACHXO2_REFRESH_USEC;
tx[1].delay.unit = SPI_DELAY_UNIT_USECS;
spi_message_add_tail(&tx[1], &msg); spi_message_add_tail(&tx[1], &msg);
ret = spi_sync(spi, &msg); ret = spi_sync(spi, &msg);
if (ret) if (ret)
@ -208,7 +209,8 @@ static int machxo2_write_init(struct fpga_manager *mgr,
spi_message_init(&msg); spi_message_init(&msg);
tx[0].tx_buf = &enable; tx[0].tx_buf = &enable;
tx[0].len = sizeof(enable); tx[0].len = sizeof(enable);
tx[0].delay_usecs = MACHXO2_LOW_DELAY_USEC; tx[0].delay.value = MACHXO2_LOW_DELAY_USEC;
tx[0].delay.unit = SPI_DELAY_UNIT_USECS;
spi_message_add_tail(&tx[0], &msg); spi_message_add_tail(&tx[0], &msg);
tx[1].tx_buf = &erase; tx[1].tx_buf = &erase;
@ -269,7 +271,8 @@ static int machxo2_write(struct fpga_manager *mgr, const char *buf,
spi_message_init(&msg); spi_message_init(&msg);
tx.tx_buf = payload; tx.tx_buf = payload;
tx.len = MACHXO2_BUF_SIZE; tx.len = MACHXO2_BUF_SIZE;
tx.delay_usecs = MACHXO2_HIGH_DELAY_USEC; tx.delay.value = MACHXO2_HIGH_DELAY_USEC;
tx.delay.unit = SPI_DELAY_UNIT_USECS;
spi_message_add_tail(&tx, &msg); spi_message_add_tail(&tx, &msg);
ret = spi_sync(spi, &msg); ret = spi_sync(spi, &msg);
if (ret) { if (ret) {
@ -317,7 +320,8 @@ static int machxo2_write_complete(struct fpga_manager *mgr,
spi_message_init(&msg); spi_message_init(&msg);
tx[1].tx_buf = &refresh; tx[1].tx_buf = &refresh;
tx[1].len = sizeof(refresh); tx[1].len = sizeof(refresh);
tx[1].delay_usecs = MACHXO2_REFRESH_USEC; tx[1].delay.value = MACHXO2_REFRESH_USEC;
tx[1].delay.unit = SPI_DELAY_UNIT_USECS;
spi_message_add_tail(&tx[1], &msg); spi_message_add_tail(&tx[1], &msg);
ret = spi_sync(spi, &msg); ret = spi_sync(spi, &msg);
if (ret) if (ret)

View File

@ -477,7 +477,8 @@ static int s10_remove(struct platform_device *pdev)
} }
static const struct of_device_id s10_of_match[] = { static const struct of_device_id s10_of_match[] = {
{ .compatible = "intel,stratix10-soc-fpga-mgr", }, {.compatible = "intel,stratix10-soc-fpga-mgr"},
{.compatible = "intel,agilex-soc-fpga-mgr"},
{}, {},
}; };