mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
fsicom: Add support for fsi core2 and core3
fsicom driver updated to support fsicom channels without notification. With notification disabled channels fsicom can support all four cores of FSI Bug 4805453 DOS-SHR-10636 Change-Id: I6cf4dd36c1570505dbcf582499189bd974ed095f Signed-off-by: Praveen James <pjames@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3197598 (cherry picked from commit 1dbdf63d67b102908c845671d18ddf4d14ae498f) Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3206768 Reviewed-by: Kovid Kumar <kovidk@nvidia.com> Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com> GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3217458
This commit is contained in:
committed by
Jon Hunter
parent
1fb5a4f931
commit
55847ce7a0
@@ -57,7 +57,7 @@ static struct fsi_hsp *fsi_hsp_v[MAX_FSI_CORE];
|
|||||||
|
|
||||||
static bool enable_deinit_notify;
|
static bool enable_deinit_notify;
|
||||||
|
|
||||||
static int sgMaxCore;
|
static struct fsi_core fsi_core;
|
||||||
|
|
||||||
static LIST_HEAD(fsi_dev_list);
|
static LIST_HEAD(fsi_dev_list);
|
||||||
static DEFINE_MUTEX(fsi_dev_list_mutex);
|
static DEFINE_MUTEX(fsi_dev_list_mutex);
|
||||||
@@ -74,8 +74,8 @@ static int fsicom_fsi_pm_notify(u32 state)
|
|||||||
pdata[3] = PM_STATE_UNI_CODE;
|
pdata[3] = PM_STATE_UNI_CODE;
|
||||||
|
|
||||||
/* send pm state to fsi */
|
/* send pm state to fsi */
|
||||||
for (lCoreId = sgMaxCore - 1; lCoreId >= 0; lCoreId--) {
|
for (lCoreId = fsi_core.notify_cnt - 1; lCoreId >= 0; lCoreId--) {
|
||||||
ret = mbox_send_message(fsi_hsp_v[lCoreId]->tx.chan,
|
ret = mbox_send_message(fsi_hsp_v[fsi_core.notify_list[lCoreId]]->tx.chan,
|
||||||
(void *)pdata);
|
(void *)pdata);
|
||||||
}
|
}
|
||||||
return ret < 0 ? ret : 0;
|
return ret < 0 ? ret : 0;
|
||||||
@@ -115,37 +115,39 @@ static int tegra_hsp_mb_init(struct device *dev)
|
|||||||
char lTxStr[100] = {0};
|
char lTxStr[100] = {0};
|
||||||
char lRxStr[100] = {0};
|
char lRxStr[100] = {0};
|
||||||
|
|
||||||
for (lCoreId = 0; lCoreId < sgMaxCore; lCoreId++) {
|
for (lCoreId = 0; lCoreId < fsi_core.notify_cnt; lCoreId++) {
|
||||||
fsi_hsp_v[lCoreId] = devm_kzalloc(dev, sizeof(*fsi_hsp_v[lCoreId]), GFP_KERNEL);
|
fsi_hsp_v[fsi_core.notify_list[lCoreId]] = devm_kzalloc(dev,
|
||||||
|
sizeof(*fsi_hsp_v[fsi_core.notify_list[lCoreId]]),
|
||||||
|
GFP_KERNEL);
|
||||||
if (!fsi_hsp_v[lCoreId])
|
if (!fsi_hsp_v[lCoreId])
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)))
|
if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)))
|
||||||
dev_err(dev, "FsiCom: setting DMA MASK failed!\n");
|
dev_err(dev, "FsiCom: setting DMA MASK failed!\n");
|
||||||
|
|
||||||
fsi_hsp_v[lCoreId]->tx.client.dev = dev;
|
fsi_hsp_v[fsi_core.notify_list[lCoreId]]->tx.client.dev = dev;
|
||||||
fsi_hsp_v[lCoreId]->rx.client.dev = dev;
|
fsi_hsp_v[fsi_core.notify_list[lCoreId]]->rx.client.dev = dev;
|
||||||
fsi_hsp_v[lCoreId]->tx.client.tx_block = true;
|
fsi_hsp_v[fsi_core.notify_list[lCoreId]]->tx.client.tx_block = true;
|
||||||
fsi_hsp_v[lCoreId]->tx.client.tx_tout = TIMEOUT;
|
fsi_hsp_v[fsi_core.notify_list[lCoreId]]->tx.client.tx_tout = TIMEOUT;
|
||||||
fsi_hsp_v[lCoreId]->rx.client.rx_callback = tegra_hsp_rx_notify;
|
fsi_hsp_v[fsi_core.notify_list[lCoreId]]->rx.client.rx_callback = tegra_hsp_rx_notify;
|
||||||
fsi_hsp_v[lCoreId]->tx.client.tx_done = tegra_hsp_tx_empty_notify;
|
fsi_hsp_v[fsi_core.notify_list[lCoreId]]->tx.client.tx_done = tegra_hsp_tx_empty_notify;
|
||||||
|
|
||||||
(void)snprintf(lTxStr, sizeof(lTxStr), "fsi-tx-cpu%d", lCoreId);
|
(void)snprintf(lTxStr, sizeof(lTxStr), "fsi-tx-cpu%d", fsi_core.notify_list[lCoreId]);
|
||||||
fsi_hsp_v[lCoreId]->tx.chan = mbox_request_channel_byname(
|
fsi_hsp_v[fsi_core.notify_list[lCoreId]]->tx.chan = mbox_request_channel_byname(
|
||||||
&fsi_hsp_v[lCoreId]->tx.client,
|
&fsi_hsp_v[fsi_core.notify_list[lCoreId]]->tx.client,
|
||||||
lTxStr);
|
lTxStr);
|
||||||
if (IS_ERR(fsi_hsp_v[lCoreId]->tx.chan)) {
|
if (IS_ERR(fsi_hsp_v[fsi_core.notify_list[lCoreId]]->tx.chan)) {
|
||||||
err = PTR_ERR(fsi_hsp_v[lCoreId]->tx.chan);
|
err = PTR_ERR(fsi_hsp_v[fsi_core.notify_list[lCoreId]]->tx.chan);
|
||||||
dev_err(dev, "failed to get tx mailbox: %d\n", err);
|
dev_err(dev, "failed to get tx mailbox: %d\n", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)snprintf(lRxStr, sizeof(lRxStr), "fsi-rx-cpu%d", lCoreId);
|
(void)snprintf(lRxStr, sizeof(lRxStr), "fsi-rx-cpu%d", fsi_core.notify_list[lCoreId]);
|
||||||
fsi_hsp_v[lCoreId]->rx.chan = mbox_request_channel_byname(
|
fsi_hsp_v[fsi_core.notify_list[lCoreId]]->rx.chan = mbox_request_channel_byname(
|
||||||
&fsi_hsp_v[lCoreId]->rx.client,
|
&fsi_hsp_v[fsi_core.notify_list[lCoreId]]->rx.client,
|
||||||
lRxStr);
|
lRxStr);
|
||||||
if (IS_ERR(fsi_hsp_v[lCoreId]->rx.chan)) {
|
if (IS_ERR(fsi_hsp_v[fsi_core.notify_list[lCoreId]]->rx.chan)) {
|
||||||
err = PTR_ERR(fsi_hsp_v[lCoreId]->rx.chan);
|
err = PTR_ERR(fsi_hsp_v[fsi_core.notify_list[lCoreId]]->rx.chan);
|
||||||
dev_err(dev, "failed to get rx mailbox: %d\n", err);
|
dev_err(dev, "failed to get rx mailbox: %d\n", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -228,10 +230,12 @@ static ssize_t device_file_ioctl(
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
uint32_t pdata[4] = {0};
|
uint32_t pdata[4] = {0};
|
||||||
struct iova_data ldata;
|
struct iova_data ldata;
|
||||||
struct rw_data *user_input;
|
struct fsi_core *fsi_core_input;
|
||||||
|
int8_t iterator = 0;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
|
|
||||||
|
iterator = 0;
|
||||||
case NVMAP_SMMU_MAP:
|
case NVMAP_SMMU_MAP:
|
||||||
ret = smmu_buff_map(arg);
|
ret = smmu_buff_map(arg);
|
||||||
break;
|
break;
|
||||||
@@ -251,7 +255,12 @@ static ssize_t device_file_ioctl(
|
|||||||
if (copy_from_user(&input, (void __user *)arg,
|
if (copy_from_user(&input, (void __user *)arg,
|
||||||
sizeof(struct rw_data)))
|
sizeof(struct rw_data)))
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
if (input.coreid >= sgMaxCore)
|
while (iterator < fsi_core.notify_cnt) {
|
||||||
|
if (input.coreid == fsi_core.notify_list[iterator])
|
||||||
|
break;
|
||||||
|
iterator++;
|
||||||
|
}
|
||||||
|
if (iterator == fsi_core.notify_cnt)
|
||||||
return -ECHRNG;
|
return -ECHRNG;
|
||||||
pdata[0] = input.handle;
|
pdata[0] = input.handle;
|
||||||
ret = mbox_send_message(fsi_hsp_v[input.coreid]->tx.chan,
|
ret = mbox_send_message(fsi_hsp_v[input.coreid]->tx.chan,
|
||||||
@@ -260,9 +269,21 @@ static ssize_t device_file_ioctl(
|
|||||||
|
|
||||||
case TEGRA_SIGNAL_REG:
|
case TEGRA_SIGNAL_REG:
|
||||||
task = get_current();
|
task = get_current();
|
||||||
user_input = (struct rw_data *)arg;
|
fsi_core_input = (struct fsi_core *)arg;
|
||||||
if (copy_to_user((void __user *)&user_input->coreid,
|
if (copy_to_user((void __user *)&fsi_core_input->max_core,
|
||||||
(void *)&sgMaxCore, sizeof(uint8_t)))
|
(void *)&fsi_core.max_core, sizeof(uint32_t)))
|
||||||
|
return -EACCES;
|
||||||
|
if (copy_to_user((void __user *)&fsi_core_input->notify_cnt,
|
||||||
|
(void *)&fsi_core.notify_cnt, sizeof(uint32_t)))
|
||||||
|
return -EACCES;
|
||||||
|
if (copy_to_user((void __user *)&fsi_core_input->polling_cnt,
|
||||||
|
(void *)&fsi_core.polling_cnt, sizeof(uint32_t)))
|
||||||
|
return -EACCES;
|
||||||
|
if (copy_to_user((void __user *)&fsi_core_input->notify_list,
|
||||||
|
(void *)&fsi_core.notify_list, sizeof(uint32_t)*MAX_FSI_CORE))
|
||||||
|
return -EACCES;
|
||||||
|
if (copy_to_user((void __user *)&fsi_core_input->polling_list,
|
||||||
|
(void *)&fsi_core.polling_list, sizeof(uint32_t)*MAX_FSI_CORE))
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -270,9 +291,13 @@ static ssize_t device_file_ioctl(
|
|||||||
if (copy_from_user(&ldata, (void __user *)arg,
|
if (copy_from_user(&ldata, (void __user *)arg,
|
||||||
sizeof(struct iova_data)))
|
sizeof(struct iova_data)))
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
if (ldata.coreid >= sgMaxCore)
|
while (iterator < fsi_core.notify_cnt) {
|
||||||
|
if (ldata.coreid == fsi_core.notify_list[iterator])
|
||||||
|
break;
|
||||||
|
iterator++;
|
||||||
|
}
|
||||||
|
if (iterator == fsi_core.notify_cnt)
|
||||||
return -ECHRNG;
|
return -ECHRNG;
|
||||||
|
|
||||||
pdata[0] = ldata.offset;
|
pdata[0] = ldata.offset;
|
||||||
pdata[1] = ldata.iova;
|
pdata[1] = ldata.iova;
|
||||||
pdata[2] = ldata.chid;
|
pdata[2] = ldata.chid;
|
||||||
@@ -349,6 +374,7 @@ static int fsicom_client_probe(struct platform_device *pdev)
|
|||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
const struct device_node *np = dev->of_node;
|
const struct device_node *np = dev->of_node;
|
||||||
struct fsi_dev_ctx *ctx;
|
struct fsi_dev_ctx *ctx;
|
||||||
|
int iterator = 0;
|
||||||
|
|
||||||
ret = of_property_read_u32(np, "smmu_inst", &val);
|
ret = of_property_read_u32(np, "smmu_inst", &val);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@@ -356,17 +382,32 @@ static int fsicom_client_probe(struct platform_device *pdev)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (val == 0) {
|
if (val == 0) {
|
||||||
ret = of_property_read_u32(pdev->dev.of_node, "max_fsi_core", &sgMaxCore);
|
ret = of_property_read_u32(pdev->dev.of_node, "max_fsi_core", &fsi_core.max_core);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("failed to read smmu_inst\n");
|
pr_err("failed to read max_core count\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (sgMaxCore > MAX_FSI_CORE)
|
if (fsi_core.max_core > MAX_FSI_CORE)
|
||||||
return -1;
|
return -1;
|
||||||
|
ret = of_property_read_variable_u32_array(pdev->dev.of_node, "fsi_core_notify",
|
||||||
|
&fsi_core.notify_list[0], 1, fsi_core.max_core);
|
||||||
|
if (ret > 0) {
|
||||||
|
fsi_core.notify_cnt = ret;
|
||||||
|
} else {
|
||||||
|
/* FSI core 0 and core 1 is configured as notification core by default */
|
||||||
|
fsi_core.notify_cnt = fsi_core.max_core;
|
||||||
|
for (iterator = 0; iterator < fsi_core.notify_cnt; iterator++) {
|
||||||
|
fsi_core.notify_list[iterator] = iterator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = of_property_read_variable_u32_array(pdev->dev.of_node, "fsi_core_polling",
|
||||||
|
&fsi_core.polling_list[0], 1, fsi_core.max_core);
|
||||||
|
if (ret > 0) {
|
||||||
|
fsi_core.polling_cnt = ret;
|
||||||
|
}
|
||||||
fsicom_register_device();
|
fsicom_register_device();
|
||||||
ret = tegra_hsp_mb_init(&pdev->dev);
|
ret = tegra_hsp_mb_init(&pdev->dev);
|
||||||
pdev_local = pdev;
|
pdev_local = pdev;
|
||||||
|
|
||||||
if (of_property_read_bool(np, "enable-deinit-notify"))
|
if (of_property_read_bool(np, "enable-deinit-notify"))
|
||||||
enable_deinit_notify = true;
|
enable_deinit_notify = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,15 @@
|
|||||||
|
|
||||||
#include <linux/ioctl.h>
|
#include <linux/ioctl.h>
|
||||||
|
|
||||||
#define MAX_FSI_CORE 2
|
#define MAX_FSI_CORE 4
|
||||||
|
|
||||||
|
struct fsi_core {
|
||||||
|
uint32_t max_core;
|
||||||
|
uint32_t notify_cnt;
|
||||||
|
uint32_t polling_cnt;
|
||||||
|
uint32_t notify_list[MAX_FSI_CORE];
|
||||||
|
uint32_t polling_list[MAX_FSI_CORE];
|
||||||
|
};
|
||||||
|
|
||||||
struct rw_data {
|
struct rw_data {
|
||||||
uint8_t coreid;
|
uint8_t coreid;
|
||||||
@@ -36,7 +44,7 @@ struct iova_data {
|
|||||||
#define NVMAP_SMMU_MAP _IOWR('q', 1, struct rw_data *)
|
#define NVMAP_SMMU_MAP _IOWR('q', 1, struct rw_data *)
|
||||||
#define NVMAP_SMMU_UNMAP _IOWR('q', 2, struct rw_data *)
|
#define NVMAP_SMMU_UNMAP _IOWR('q', 2, struct rw_data *)
|
||||||
#define TEGRA_HSP_WRITE _IOWR('q', 3, struct rw_data *)
|
#define TEGRA_HSP_WRITE _IOWR('q', 3, struct rw_data *)
|
||||||
#define TEGRA_SIGNAL_REG _IOWR('q', 4, struct rw_data *)
|
#define TEGRA_SIGNAL_REG _IOWR('q', 4, struct fsi_core *)
|
||||||
#define TEGRA_IOVA_DATA _IOWR('q', 5, struct iova_data *)
|
#define TEGRA_IOVA_DATA _IOWR('q', 5, struct iova_data *)
|
||||||
|
|
||||||
#endif /* _UAPI_TEGRA_FSICOM_H_ */
|
#endif /* _UAPI_TEGRA_FSICOM_H_ */
|
||||||
|
|||||||
Reference in New Issue
Block a user