Merge tag 'char-misc-5.8-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 large set of char/misc driver patches for 5.8-rc1 Included in here are: - habanalabs driver updates, loads - mhi bus driver updates - extcon driver updates - clk driver updates (approved by the clock maintainer) - firmware driver updates - fpga driver updates - gnss driver updates - coresight driver updates - interconnect driver updates - parport driver updates (it's still alive!) - nvmem driver updates - soundwire driver updates - visorbus driver updates - w1 driver updates - various misc driver updates In short, loads of different driver subsystem updates along with the drivers as well. All have been in linux-next for a while with no reported issues" * tag 'char-misc-5.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (233 commits) habanalabs: correctly cast u64 to void* habanalabs: initialize variable to default value extcon: arizona: Fix runtime PM imbalance on error extcon: max14577: Add proper dt-compatible strings extcon: adc-jack: Fix an error handling path in 'adc_jack_probe()' extcon: remove redundant assignment to variable idx w1: omap-hdq: print dev_err if irq flags are not cleared w1: omap-hdq: fix interrupt handling which did show spurious timeouts w1: omap-hdq: fix return value to be -1 if there is a timeout w1: omap-hdq: cleanup to add missing newline for some dev_dbg /dev/mem: Revoke mappings when a driver claims the region misc: xilinx-sdfec: convert get_user_pages() --> pin_user_pages() misc: xilinx-sdfec: cleanup return value in xsdfec_table_write() misc: xilinx-sdfec: improve get_user_pages_fast() error handling nvmem: qfprom: remove incorrect write support habanalabs: handle MMU cache invalidation timeout habanalabs: don't allow hard reset with open processes habanalabs: GAUDI does not support soft-reset habanalabs: add print for soft reset due to event habanalabs: improve MMU cache invalidation code ...
This commit is contained in:
@@ -156,7 +156,7 @@ config FPGA_DFL
|
||||
|
||||
config FPGA_DFL_FME
|
||||
tristate "FPGA DFL FME Driver"
|
||||
depends on FPGA_DFL && HWMON
|
||||
depends on FPGA_DFL && HWMON && PERF_EVENTS
|
||||
help
|
||||
The FPGA Management Engine (FME) is a feature device implemented
|
||||
under Device Feature List (DFL) framework. Select this option to
|
||||
|
||||
@@ -40,6 +40,7 @@ obj-$(CONFIG_FPGA_DFL_FME_REGION) += dfl-fme-region.o
|
||||
obj-$(CONFIG_FPGA_DFL_AFU) += dfl-afu.o
|
||||
|
||||
dfl-fme-objs := dfl-fme-main.o dfl-fme-pr.o dfl-fme-error.o
|
||||
dfl-fme-objs += dfl-fme-perf.o
|
||||
dfl-afu-objs := dfl-afu-main.o dfl-afu-region.o dfl-afu-dma-region.o
|
||||
dfl-afu-objs += dfl-afu-error.o
|
||||
|
||||
|
||||
@@ -61,10 +61,10 @@ static int afu_dma_pin_pages(struct dfl_feature_platform_data *pdata,
|
||||
region->pages);
|
||||
if (pinned < 0) {
|
||||
ret = pinned;
|
||||
goto put_pages;
|
||||
goto free_pages;
|
||||
} else if (pinned != npages) {
|
||||
ret = -EFAULT;
|
||||
goto free_pages;
|
||||
goto put_pages;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "%d pages pinned\n", pinned);
|
||||
|
||||
@@ -561,14 +561,16 @@ static int afu_open(struct inode *inode, struct file *filp)
|
||||
if (WARN_ON(!pdata))
|
||||
return -ENODEV;
|
||||
|
||||
ret = dfl_feature_dev_use_begin(pdata);
|
||||
if (ret)
|
||||
return ret;
|
||||
mutex_lock(&pdata->lock);
|
||||
ret = dfl_feature_dev_use_begin(pdata, filp->f_flags & O_EXCL);
|
||||
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");
|
||||
filp->private_data = fdev;
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
mutex_lock(&pdata->lock);
|
||||
__port_reset(pdev);
|
||||
afu_dma_region_destroy(pdata);
|
||||
mutex_unlock(&pdata->lock);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -746,6 +750,12 @@ static long afu_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
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)
|
||||
{
|
||||
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))
|
||||
return -EPERM;
|
||||
|
||||
/* Support debug access to the mapping */
|
||||
vma->vm_ops = &afu_vma_ops;
|
||||
|
||||
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
|
||||
|
||||
return remap_pfn_range(vma, vma->vm_start,
|
||||
|
||||
@@ -579,6 +579,10 @@ static struct dfl_feature_driver fme_feature_drvs[] = {
|
||||
.id_table = fme_power_mgmt_id_table,
|
||||
.ops = &fme_power_mgmt_ops,
|
||||
},
|
||||
{
|
||||
.id_table = fme_perf_id_table,
|
||||
.ops = &fme_perf_ops,
|
||||
},
|
||||
{
|
||||
.ops = NULL,
|
||||
},
|
||||
@@ -600,14 +604,16 @@ static int fme_open(struct inode *inode, struct file *filp)
|
||||
if (WARN_ON(!pdata))
|
||||
return -ENODEV;
|
||||
|
||||
ret = dfl_feature_dev_use_begin(pdata);
|
||||
if (ret)
|
||||
return ret;
|
||||
mutex_lock(&pdata->lock);
|
||||
ret = dfl_feature_dev_use_begin(pdata, filp->f_flags & O_EXCL);
|
||||
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");
|
||||
filp->private_data = pdata;
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fme_release(struct inode *inode, struct file *filp)
|
||||
@@ -616,7 +622,10 @@ static int fme_release(struct inode *inode, struct file *filp)
|
||||
struct platform_device *pdev = pdata->dev;
|
||||
|
||||
dev_dbg(&pdev->dev, "Device File Release\n");
|
||||
|
||||
mutex_lock(&pdata->lock);
|
||||
dfl_feature_dev_use_end(pdata);
|
||||
mutex_unlock(&pdata->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
1020
drivers/fpga/dfl-fme-perf.c
Normal file
1020
drivers/fpga/dfl-fme-perf.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -38,5 +38,7 @@ extern const struct dfl_feature_id fme_pr_mgmt_id_table[];
|
||||
extern const struct dfl_feature_ops fme_global_err_ops;
|
||||
extern const struct dfl_feature_id fme_global_err_id_table[];
|
||||
extern const struct attribute_group fme_global_err_group;
|
||||
extern const struct dfl_feature_ops fme_perf_ops;
|
||||
extern const struct dfl_feature_id fme_perf_id_table[];
|
||||
|
||||
#endif /* __DFL_FME_H */
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
struct dfl_feature_platform_data *pdata;
|
||||
struct platform_device *port_pdev;
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
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)
|
||||
{
|
||||
struct dfl_feature_platform_data *pdata;
|
||||
struct platform_device *port_pdev;
|
||||
int ret = -ENODEV;
|
||||
|
||||
@@ -1138,7 +1144,12 @@ int dfl_fpga_cdev_assign_port(struct dfl_fpga_cdev *cdev, int port_id)
|
||||
if (ret)
|
||||
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--;
|
||||
put_dev_exit:
|
||||
put_device(&port_pdev->dev);
|
||||
|
||||
@@ -197,16 +197,16 @@ struct dfl_feature_driver {
|
||||
* feature dev (platform device)'s reources.
|
||||
* @ioaddr: mapped mmio resource address.
|
||||
* @ops: ops of this sub feature.
|
||||
* @priv: priv data of this feature.
|
||||
*/
|
||||
struct dfl_feature {
|
||||
u64 id;
|
||||
int resource_index;
|
||||
void __iomem *ioaddr;
|
||||
const struct dfl_feature_ops *ops;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
#define DEV_STATUS_IN_USE 0
|
||||
|
||||
#define FEATURE_DEV_ID_UNUSED (-1)
|
||||
|
||||
/**
|
||||
@@ -219,8 +219,9 @@ struct dfl_feature {
|
||||
* @dfl_cdev: ptr to container device.
|
||||
* @id: id used for this feature device.
|
||||
* @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.
|
||||
* @dev_status: dev status (e.g. DEV_STATUS_IN_USE).
|
||||
* @private: ptr to feature dev private data.
|
||||
* @features: sub features of this feature dev.
|
||||
*/
|
||||
@@ -232,26 +233,46 @@ struct dfl_feature_platform_data {
|
||||
struct dfl_fpga_cdev *dfl_cdev;
|
||||
int id;
|
||||
unsigned int disable_count;
|
||||
unsigned long dev_status;
|
||||
bool excl_open;
|
||||
int open_count;
|
||||
void *private;
|
||||
int num;
|
||||
struct dfl_feature features[0];
|
||||
struct dfl_feature features[];
|
||||
};
|
||||
|
||||
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 (test_and_set_bit_lock(DEV_STATUS_IN_USE, &pdata->dev_status))
|
||||
if (pdata->excl_open)
|
||||
return -EBUSY;
|
||||
|
||||
if (excl) {
|
||||
if (pdata->open_count)
|
||||
return -EBUSY;
|
||||
|
||||
pdata->excl_open = true;
|
||||
}
|
||||
pdata->open_count++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
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
|
||||
|
||||
@@ -46,10 +46,16 @@ static int ice40_fpga_ops_write_init(struct fpga_manager *mgr,
|
||||
struct spi_message message;
|
||||
struct spi_transfer assert_cs_then_reset_delay = {
|
||||
.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 = {
|
||||
.delay_usecs = ICE40_SPI_HOUSEKEEPING_DELAY
|
||||
.delay = {
|
||||
.value = ICE40_SPI_HOUSEKEEPING_DELAY,
|
||||
.unit = SPI_DELAY_UNIT_USECS
|
||||
}
|
||||
};
|
||||
int ret;
|
||||
|
||||
|
||||
@@ -157,7 +157,8 @@ static int machxo2_cleanup(struct fpga_manager *mgr)
|
||||
spi_message_init(&msg);
|
||||
tx[1].tx_buf = &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);
|
||||
ret = spi_sync(spi, &msg);
|
||||
if (ret)
|
||||
@@ -208,7 +209,8 @@ static int machxo2_write_init(struct fpga_manager *mgr,
|
||||
spi_message_init(&msg);
|
||||
tx[0].tx_buf = &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);
|
||||
|
||||
tx[1].tx_buf = &erase;
|
||||
@@ -269,7 +271,8 @@ static int machxo2_write(struct fpga_manager *mgr, const char *buf,
|
||||
spi_message_init(&msg);
|
||||
tx.tx_buf = payload;
|
||||
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);
|
||||
ret = spi_sync(spi, &msg);
|
||||
if (ret) {
|
||||
@@ -317,7 +320,8 @@ static int machxo2_write_complete(struct fpga_manager *mgr,
|
||||
spi_message_init(&msg);
|
||||
tx[1].tx_buf = &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);
|
||||
ret = spi_sync(spi, &msg);
|
||||
if (ret)
|
||||
|
||||
@@ -154,11 +154,11 @@ static void s10_receive_callback(struct stratix10_svc_client *client,
|
||||
* Here we set status bits as we receive them. Elsewhere, we always use
|
||||
* test_and_clear_bit() to check status in priv->status
|
||||
*/
|
||||
for (i = 0; i <= SVC_STATUS_RECONFIG_ERROR; i++)
|
||||
for (i = 0; i <= SVC_STATUS_ERROR; i++)
|
||||
if (status & (1 << i))
|
||||
set_bit(i, &priv->status);
|
||||
|
||||
if (status & BIT(SVC_STATUS_RECONFIG_BUFFER_DONE)) {
|
||||
if (status & BIT(SVC_STATUS_BUFFER_DONE)) {
|
||||
s10_unlock_bufs(priv, data->kaddr1);
|
||||
s10_unlock_bufs(priv, data->kaddr2);
|
||||
s10_unlock_bufs(priv, data->kaddr3);
|
||||
@@ -209,8 +209,7 @@ static int s10_ops_write_init(struct fpga_manager *mgr,
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
if (!test_and_clear_bit(SVC_STATUS_RECONFIG_REQUEST_OK,
|
||||
&priv->status)) {
|
||||
if (!test_and_clear_bit(SVC_STATUS_OK, &priv->status)) {
|
||||
ret = -ETIMEDOUT;
|
||||
goto init_done;
|
||||
}
|
||||
@@ -323,17 +322,15 @@ static int s10_ops_write(struct fpga_manager *mgr, const char *buf,
|
||||
&priv->status_return_completion,
|
||||
S10_BUFFER_TIMEOUT);
|
||||
|
||||
if (test_and_clear_bit(SVC_STATUS_RECONFIG_BUFFER_DONE,
|
||||
&priv->status) ||
|
||||
test_and_clear_bit(SVC_STATUS_RECONFIG_BUFFER_SUBMITTED,
|
||||
if (test_and_clear_bit(SVC_STATUS_BUFFER_DONE, &priv->status) ||
|
||||
test_and_clear_bit(SVC_STATUS_BUFFER_SUBMITTED,
|
||||
&priv->status)) {
|
||||
ret = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(SVC_STATUS_RECONFIG_ERROR,
|
||||
&priv->status)) {
|
||||
dev_err(dev, "ERROR - giving up - SVC_STATUS_RECONFIG_ERROR\n");
|
||||
if (test_and_clear_bit(SVC_STATUS_ERROR, &priv->status)) {
|
||||
dev_err(dev, "ERROR - giving up - SVC_STATUS_ERROR\n");
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
@@ -393,13 +390,11 @@ static int s10_ops_write_complete(struct fpga_manager *mgr,
|
||||
timeout = ret;
|
||||
ret = 0;
|
||||
|
||||
if (test_and_clear_bit(SVC_STATUS_RECONFIG_COMPLETED,
|
||||
&priv->status))
|
||||
if (test_and_clear_bit(SVC_STATUS_COMPLETED, &priv->status))
|
||||
break;
|
||||
|
||||
if (test_and_clear_bit(SVC_STATUS_RECONFIG_ERROR,
|
||||
&priv->status)) {
|
||||
dev_err(dev, "ERROR - giving up - SVC_STATUS_RECONFIG_ERROR\n");
|
||||
if (test_and_clear_bit(SVC_STATUS_ERROR, &priv->status)) {
|
||||
dev_err(dev, "ERROR - giving up - SVC_STATUS_ERROR\n");
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
@@ -482,7 +477,8 @@ static int s10_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
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"},
|
||||
{},
|
||||
};
|
||||
|
||||
|
||||
@@ -40,16 +40,12 @@ static int zynqmp_fpga_ops_write_init(struct fpga_manager *mgr,
|
||||
static int zynqmp_fpga_ops_write(struct fpga_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
struct zynqmp_fpga_priv *priv;
|
||||
dma_addr_t dma_addr;
|
||||
u32 eemi_flags = 0;
|
||||
char *kbuf;
|
||||
int ret;
|
||||
|
||||
if (IS_ERR_OR_NULL(eemi_ops) || !eemi_ops->fpga_load)
|
||||
return -ENXIO;
|
||||
|
||||
priv = mgr->priv;
|
||||
|
||||
kbuf = dma_alloc_coherent(priv->dev, size, &dma_addr, GFP_KERNEL);
|
||||
@@ -63,7 +59,7 @@ static int zynqmp_fpga_ops_write(struct fpga_manager *mgr,
|
||||
if (priv->flags & FPGA_MGR_PARTIAL_RECONFIG)
|
||||
eemi_flags |= XILINX_ZYNQMP_PM_FPGA_PARTIAL;
|
||||
|
||||
ret = eemi_ops->fpga_load(dma_addr, size, eemi_flags);
|
||||
ret = zynqmp_pm_fpga_load(dma_addr, size, eemi_flags);
|
||||
|
||||
dma_free_coherent(priv->dev, size, kbuf, dma_addr);
|
||||
|
||||
@@ -78,13 +74,9 @@ static int zynqmp_fpga_ops_write_complete(struct fpga_manager *mgr,
|
||||
|
||||
static enum fpga_mgr_states zynqmp_fpga_ops_state(struct fpga_manager *mgr)
|
||||
{
|
||||
const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
u32 status;
|
||||
u32 status = 0;
|
||||
|
||||
if (IS_ERR_OR_NULL(eemi_ops) || !eemi_ops->fpga_get_status)
|
||||
return FPGA_MGR_STATE_UNKNOWN;
|
||||
|
||||
eemi_ops->fpga_get_status(&status);
|
||||
zynqmp_pm_fpga_get_status(&status);
|
||||
if (status & IXR_FPGA_DONE_MASK)
|
||||
return FPGA_MGR_STATE_OPERATING;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user