summaryrefslogtreecommitdiff
path: root/drivers/fsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/fsi')
-rw-r--r--drivers/fsi/fsi-core.c11
-rw-r--r--drivers/fsi/fsi-master-ast-cf.c2
-rw-r--r--drivers/fsi/fsi-master.h2
-rw-r--r--drivers/fsi/fsi-occ.c66
-rw-r--r--drivers/fsi/fsi-sbefifo.c15
5 files changed, 73 insertions, 23 deletions
diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 3a7b78e36701..694e80c06665 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -392,8 +392,8 @@ int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
}
EXPORT_SYMBOL_GPL(fsi_slave_write);
-extern int fsi_slave_claim_range(struct fsi_slave *slave,
- uint32_t addr, uint32_t size)
+int fsi_slave_claim_range(struct fsi_slave *slave,
+ uint32_t addr, uint32_t size)
{
if (addr + size < addr)
return -EINVAL;
@@ -406,8 +406,8 @@ extern int fsi_slave_claim_range(struct fsi_slave *slave,
}
EXPORT_SYMBOL_GPL(fsi_slave_claim_range);
-extern void fsi_slave_release_range(struct fsi_slave *slave,
- uint32_t addr, uint32_t size)
+void fsi_slave_release_range(struct fsi_slave *slave,
+ uint32_t addr, uint32_t size)
{
}
EXPORT_SYMBOL_GPL(fsi_slave_release_range);
@@ -1314,6 +1314,9 @@ int fsi_master_register(struct fsi_master *master)
mutex_init(&master->scan_lock);
master->idx = ida_simple_get(&master_ida, 0, INT_MAX, GFP_KERNEL);
+ if (master->idx < 0)
+ return master->idx;
+
dev_set_name(&master->dev, "fsi%d", master->idx);
master->dev.class = &fsi_master_class;
diff --git a/drivers/fsi/fsi-master-ast-cf.c b/drivers/fsi/fsi-master-ast-cf.c
index 24292acdbaf8..5f608ef8b53c 100644
--- a/drivers/fsi/fsi-master-ast-cf.c
+++ b/drivers/fsi/fsi-master-ast-cf.c
@@ -1324,12 +1324,14 @@ static int fsi_master_acf_probe(struct platform_device *pdev)
}
master->cvic = devm_of_iomap(&pdev->dev, np, 0, NULL);
if (IS_ERR(master->cvic)) {
+ of_node_put(np);
rc = PTR_ERR(master->cvic);
dev_err(&pdev->dev, "Error %d mapping CVIC\n", rc);
goto err_free;
}
rc = of_property_read_u32(np, "copro-sw-interrupts",
&master->cvic_sw_irq);
+ of_node_put(np);
if (rc) {
dev_err(&pdev->dev, "Can't find coprocessor SW interrupt\n");
goto err_free;
diff --git a/drivers/fsi/fsi-master.h b/drivers/fsi/fsi-master.h
index cd6bee5e12a7..4762315a46ba 100644
--- a/drivers/fsi/fsi-master.h
+++ b/drivers/fsi/fsi-master.h
@@ -51,7 +51,7 @@
#define FSI_MMODE_CRS1SHFT 8 /* Clk rate selection 1 shift */
#define FSI_MMODE_CRS1MASK 0x3ff /* Clk rate selection 1 mask */
-/* MRESB: Reset brindge */
+/* MRESB: Reset bridge */
#define FSI_MRESB_RST_GEN 0x80000000 /* General reset */
#define FSI_MRESB_RST_ERR 0x40000000 /* Error Reset */
diff --git a/drivers/fsi/fsi-occ.c b/drivers/fsi/fsi-occ.c
index c9cc75fbdfb9..abdd37d5507f 100644
--- a/drivers/fsi/fsi-occ.c
+++ b/drivers/fsi/fsi-occ.c
@@ -44,6 +44,7 @@ struct occ {
struct device *sbefifo;
char name[32];
int idx;
+ bool platform_hwmon;
u8 sequence_number;
void *buffer;
void *client_buffer;
@@ -94,6 +95,7 @@ static int occ_open(struct inode *inode, struct file *file)
client->occ = occ;
mutex_init(&client->lock);
file->private_data = client;
+ get_device(occ->dev);
/* We allocate a 1-page buffer, make sure it all fits */
BUILD_BUG_ON((OCC_CMD_DATA_BYTES + 3) > PAGE_SIZE);
@@ -197,6 +199,7 @@ static int occ_release(struct inode *inode, struct file *file)
{
struct occ_client *client = file->private_data;
+ put_device(client->occ->dev);
free_page((unsigned long)client->buffer);
kfree(client);
@@ -246,7 +249,7 @@ static int occ_verify_checksum(struct occ *occ, struct occ_response *resp,
if (checksum != checksum_resp) {
dev_err(occ->dev, "Bad checksum: %04x!=%04x\n", checksum,
checksum_resp);
- return -EBADMSG;
+ return -EBADE;
}
return 0;
@@ -493,12 +496,19 @@ int fsi_occ_submit(struct device *dev, const void *request, size_t req_len,
for (i = 1; i < req_len - 2; ++i)
checksum += byte_request[i];
- mutex_lock(&occ->occ_lock);
+ rc = mutex_lock_interruptible(&occ->occ_lock);
+ if (rc)
+ return rc;
occ->client_buffer = response;
occ->client_buffer_size = user_resp_len;
occ->client_response_size = 0;
+ if (!occ->buffer) {
+ rc = -ENOENT;
+ goto done;
+ }
+
/*
* Get a sequence number and update the counter. Avoid a sequence
* number of 0 which would pass the response check below even if the
@@ -575,8 +585,11 @@ int fsi_occ_submit(struct device *dev, const void *request, size_t req_len,
dev_dbg(dev, "resp_status=%02x resp_data_len=%d\n",
resp->return_status, resp_data_length);
- occ->client_response_size = resp_data_length + 7;
rc = occ_verify_checksum(occ, resp, resp_data_length);
+ if (rc)
+ goto done;
+
+ occ->client_response_size = resp_data_length + 7;
done:
*resp_len = occ->client_response_size;
@@ -586,7 +599,7 @@ int fsi_occ_submit(struct device *dev, const void *request, size_t req_len,
}
EXPORT_SYMBOL_GPL(fsi_occ_submit);
-static int occ_unregister_child(struct device *dev, void *data)
+static int occ_unregister_platform_child(struct device *dev, void *data)
{
struct platform_device *hwmon_dev = to_platform_device(dev);
@@ -595,12 +608,25 @@ static int occ_unregister_child(struct device *dev, void *data)
return 0;
}
+static int occ_unregister_of_child(struct device *dev, void *data)
+{
+ struct platform_device *hwmon_dev = to_platform_device(dev);
+
+ of_device_unregister(hwmon_dev);
+ if (dev->of_node)
+ of_node_clear_flag(dev->of_node, OF_POPULATED);
+
+ return 0;
+}
+
static int occ_probe(struct platform_device *pdev)
{
int rc;
u32 reg;
+ char child_name[32];
struct occ *occ;
- struct platform_device *hwmon_dev;
+ struct platform_device *hwmon_dev = NULL;
+ struct device_node *hwmon_node;
struct device *dev = &pdev->dev;
struct platform_device_info hwmon_dev_info = {
.parent = dev,
@@ -659,10 +685,20 @@ static int occ_probe(struct platform_device *pdev)
return rc;
}
- hwmon_dev_info.id = occ->idx;
- hwmon_dev = platform_device_register_full(&hwmon_dev_info);
- if (IS_ERR(hwmon_dev))
- dev_warn(dev, "failed to create hwmon device\n");
+ hwmon_node = of_get_child_by_name(dev->of_node, hwmon_dev_info.name);
+ if (hwmon_node) {
+ snprintf(child_name, sizeof(child_name), "%s.%d", hwmon_dev_info.name, occ->idx);
+ hwmon_dev = of_platform_device_create(hwmon_node, child_name, dev);
+ of_node_put(hwmon_node);
+ }
+
+ if (!hwmon_dev) {
+ occ->platform_hwmon = true;
+ hwmon_dev_info.id = occ->idx;
+ hwmon_dev = platform_device_register_full(&hwmon_dev_info);
+ if (IS_ERR(hwmon_dev))
+ dev_warn(dev, "failed to create hwmon device\n");
+ }
return 0;
}
@@ -671,11 +707,17 @@ static int occ_remove(struct platform_device *pdev)
{
struct occ *occ = platform_get_drvdata(pdev);
- kvfree(occ->buffer);
-
misc_deregister(&occ->mdev);
- device_for_each_child(&pdev->dev, NULL, occ_unregister_child);
+ mutex_lock(&occ->occ_lock);
+ kvfree(occ->buffer);
+ occ->buffer = NULL;
+ mutex_unlock(&occ->occ_lock);
+
+ if (occ->platform_hwmon)
+ device_for_each_child(&pdev->dev, NULL, occ_unregister_platform_child);
+ else
+ device_for_each_child(&pdev->dev, NULL, occ_unregister_of_child);
ida_simple_remove(&occ_ida, occ->idx);
diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c
index f52a912cdf16..5f93a53846aa 100644
--- a/drivers/fsi/fsi-sbefifo.c
+++ b/drivers/fsi/fsi-sbefifo.c
@@ -477,7 +477,8 @@ static int sbefifo_wait(struct sbefifo *sbefifo, bool up,
if (!ready) {
sysfs_notify(&sbefifo->dev.kobj, NULL, dev_attr_timeout.attr.name);
sbefifo->timed_out = true;
- dev_err(dev, "%s FIFO Timeout ! status=%08x\n", up ? "UP" : "DOWN", sts);
+ dev_err(dev, "%s FIFO Timeout (%u ms)! status=%08x\n",
+ up ? "UP" : "DOWN", jiffies_to_msecs(timeout), sts);
return -ETIMEDOUT;
}
dev_vdbg(dev, "End of wait status: %08x\n", sts);
@@ -497,8 +498,8 @@ static int sbefifo_send_command(struct sbefifo *sbefifo,
u32 status;
int rc;
- dev_vdbg(dev, "sending command (%zd words, cmd=%04x)\n",
- cmd_len, be32_to_cpu(command[1]));
+ dev_dbg(dev, "sending command (%zd words, cmd=%04x)\n",
+ cmd_len, be32_to_cpu(command[1]));
/* As long as there's something to send */
timeout = msecs_to_jiffies(SBEFIFO_TIMEOUT_START_CMD);
@@ -551,21 +552,23 @@ static int sbefifo_read_response(struct sbefifo *sbefifo, struct iov_iter *respo
size_t len;
int rc;
- dev_vdbg(dev, "reading response, buflen = %zd\n", iov_iter_count(response));
+ dev_dbg(dev, "reading response, buflen = %zd\n", iov_iter_count(response));
timeout = msecs_to_jiffies(sbefifo->timeout_start_rsp_ms);
for (;;) {
/* Grab FIFO status (this will handle parity errors) */
rc = sbefifo_wait(sbefifo, false, &status, timeout);
- if (rc < 0)
+ if (rc < 0) {
+ dev_dbg(dev, "timeout waiting (%u ms)\n", jiffies_to_msecs(timeout));
return rc;
+ }
timeout = msecs_to_jiffies(SBEFIFO_TIMEOUT_IN_RSP);
/* Decode status */
len = sbefifo_populated(status);
eot_set = sbefifo_eot_set(status);
- dev_vdbg(dev, " chunk size %zd eot_set=0x%x\n", len, eot_set);
+ dev_dbg(dev, " chunk size %zd eot_set=0x%x\n", len, eot_set);
/* Go through the chunk */
while(len--) {