forked from luck/tmp_suning_uos_patched
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:
commit
f877a18c08
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
@ -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";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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"},
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user