summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPraneeth Bajjuri <praneeth@ti.com>2015-02-03 14:27:36 -0600
committerPraneeth Bajjuri <praneeth@ti.com>2015-02-03 14:27:36 -0600
commit29044f4094cf5a2bf4231664150fac80ed4c3bdd (patch)
tree783591d24377374ee144ccb34a03bda411a59f8a
parentb2a6a3d144669701732568cde5cce17aa37c1ae1 (diff)
parent2b84d7abbc77c51bee46026e4b9e31e3e583be29 (diff)
Merge branch 'ti-linux-3.14.y' of git://git.ti.com/ti-linux-kernel/ti-linux-kernel into p-ti-linux-3.14.y-common
* 'ti-linux-3.14.y' of git://git.ti.com/ti-linux-kernel/ti-linux-kernel: remoteproc/pruss: fix shutdown for manually booted PRU cores remoteproc/pruss: fix the cleanup path in pru_rproc_probe() iommu/omap: Fix a sleeping function invocation in atomic context bug remoteproc/pruss: use match data instead of platform data for PRUs remoteproc/pruss: fix a crash with platform_device_unregister iommu/omap: Fix a minor typo in debugfs output Change-Id: I320e320a4da0b4a44e2eecd60dc4f85b559b3c5b Signed-off-by: Praneeth Bajjuri <praneeth@ti.com>
-rw-r--r--drivers/iommu/omap-iommu-debug.c2
-rw-r--r--drivers/iommu/omap-iommu.c4
-rw-r--r--drivers/remoteproc/pruss_remoteproc.c143
3 files changed, 114 insertions, 35 deletions
diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c
index 0b7dfaa3767..5ef2cf7613d 100644
--- a/drivers/iommu/omap-iommu-debug.c
+++ b/drivers/iommu/omap-iommu-debug.c
@@ -118,7 +118,7 @@ static void dump_ioptable(struct seq_file *s)
continue;
da = (i << IOPGD_SHIFT) + (j << IOPTE_SHIFT);
- seq_printf(s, "1: 0x%08x 0x%08x\n", da, *iopte);
+ seq_printf(s, "2: 0x%08x 0x%08x\n", da, *iopte);
}
}
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index c34e3ce5428..693f23c46a6 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -1187,13 +1187,13 @@ static int omap_iommu_attach_init(struct device *dev,
return -EINVAL;
odomain->iommus = kzalloc(odomain->num_iommus * sizeof(*iommu),
- GFP_KERNEL);
+ GFP_ATOMIC);
if (!odomain->iommus)
return -ENOMEM;
iommu = odomain->iommus;
for (i = 0; i < odomain->num_iommus; i++, iommu++) {
- iommu->pgtable = kzalloc(IOPGD_TABLE_SIZE, GFP_KERNEL);
+ iommu->pgtable = kzalloc(IOPGD_TABLE_SIZE, GFP_ATOMIC);
if (!iommu->pgtable)
return -ENOMEM;
diff --git a/drivers/remoteproc/pruss_remoteproc.c b/drivers/remoteproc/pruss_remoteproc.c
index abfe217cc16..d498ee3b534 100644
--- a/drivers/remoteproc/pruss_remoteproc.c
+++ b/drivers/remoteproc/pruss_remoteproc.c
@@ -126,16 +126,26 @@ enum pru_mem {
};
/**
- * struct pru_rproc_platform_data - PRU core platform data
+ * struct pru_private_data - PRU core private data
* @id: PRU index
* @fw_name: firmware name to be used for the PRU core
*/
-struct pru_rproc_platform_data {
+struct pru_private_data {
u32 id;
const char *fw_name;
};
/**
+ * struct pru_match_private_data - match private data to handle multiple instances
+ * @device_name: device name of the PRU processor core instance
+ * @priv_data: PRU driver private data for this PRU processor core instance
+ */
+struct pru_match_private_data {
+ const char *device_name;
+ struct pru_private_data *priv_data;
+};
+
+/**
* struct pruss_private_data - PRUSS driver private data
* @num_irqs: number of interrupts to MPU
* @host_events: bit mask of PRU host interrupts that are routed to MPU
@@ -765,13 +775,34 @@ static struct rproc_ops pru_rproc_ops = {
.da_to_va = pru_da_to_va,
};
+static const struct of_device_id pru_rproc_match[];
+
+static const struct pru_private_data *pru_rproc_get_private_data(
+ struct platform_device *pdev)
+{
+ const struct pru_match_private_data *data;
+ const struct of_device_id *match;
+
+ match = of_match_device(pru_rproc_match, &pdev->dev);
+ if (!match)
+ return ERR_PTR(-ENODEV);
+
+ data = match->data;
+ for (; data && data->device_name; data++) {
+ if (!strcmp(dev_name(&pdev->dev), data->device_name))
+ return data->priv_data;
+ }
+
+ return NULL;
+}
+
static int pru_rproc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct platform_device *ppdev = to_platform_device(dev->parent);
struct pru_rproc *pru;
- struct pru_rproc_platform_data *pdata = dev_get_platdata(dev);
+ const struct pru_private_data *pdata;
struct rproc *rproc = NULL;
struct mbox_client *client;
struct resource *res;
@@ -783,8 +814,9 @@ static int pru_rproc_probe(struct platform_device *pdev)
return -ENODEV;
}
- if (!pdata || !pdata->fw_name) {
- dev_err(dev, "platform data (PRU-private) missing\n");
+ pdata = pru_rproc_get_private_data(pdev);
+ if (IS_ERR_OR_NULL(pdata) || !pdata->fw_name) {
+ dev_err(dev, "missing or incomplete PRU-private data\n");
return -ENODEV;
}
@@ -858,7 +890,7 @@ static int pru_rproc_probe(struct platform_device *pdev)
ret = rproc_boot(pru->rproc);
if (ret) {
dev_err(dev, "rproc_boot failed\n");
- goto put_mbox;
+ goto del_rproc;
}
}
@@ -869,6 +901,8 @@ static int pru_rproc_probe(struct platform_device *pdev)
return 0;
+del_rproc:
+ rproc_del(pru->rproc);
put_mbox:
mbox_free_channel(pru->mbox);
free_rproc:
@@ -884,6 +918,11 @@ static int pru_rproc_remove(struct platform_device *pdev)
dev_info(dev, "%s: removing rproc %s\n", __func__, rproc->name);
+ if (list_empty(&pru->rproc->rvdevs)) {
+ dev_info(dev, "stopping the manually booted PRU core\n");
+ rproc_shutdown(pru->rproc);
+ }
+
mbox_free_channel(pru->mbox);
rproc_del(rproc);
@@ -1096,7 +1135,7 @@ static int pru_rproc_unregister(struct device *dev, void *data)
{
struct platform_device *pdev = to_platform_device(dev);
- platform_device_unregister(pdev);
+ of_device_unregister(pdev);
return 0;
}
@@ -1118,73 +1157,113 @@ static int pruss_remove(struct platform_device *pdev)
return 0;
}
-/* PRU0 core-specific platform data */
-static struct pru_rproc_platform_data pru0_rproc_pdata = {
+/* PRU0 core-specific private data */
+static struct pru_private_data pru0_rproc_pdata = {
.id = 0,
.fw_name = "rproc-pru0-fw",
};
-/* PRU1 core-specific platform data */
-static struct pru_rproc_platform_data pru1_rproc_pdata = {
+/* PRU1 core-specific private data */
+static struct pru_private_data pru1_rproc_pdata = {
.id = 1,
.fw_name = "rproc-pru1-fw",
};
-static struct pru_rproc_platform_data pru1_0_rproc_pdata = {
+static struct pru_private_data pru1_0_rproc_pdata = {
.id = 0,
.fw_name = "am57xx-pru1_0-fw",
};
-static struct pru_rproc_platform_data pru1_1_rproc_pdata = {
+static struct pru_private_data pru1_1_rproc_pdata = {
.id = 1,
.fw_name = "am57xx-pru1_1-fw",
};
-static struct pru_rproc_platform_data pru2_0_rproc_pdata = {
+static struct pru_private_data pru2_0_rproc_pdata = {
.id = 0,
.fw_name = "am57xx-pru2_0-fw",
};
-static struct pru_rproc_platform_data pru2_1_rproc_pdata = {
+static struct pru_private_data pru2_1_rproc_pdata = {
.id = 1,
.fw_name = "am57xx-pru2_1-fw",
};
/* platform data to be added when creating the PRU platform devices */
static struct of_dev_auxdata am335x_pru_rproc_auxdata_lookup[] = {
- OF_DEV_AUXDATA("ti,pru-rproc", 0x4a334000, "4a334000.pru0",
- &pru0_rproc_pdata),
- OF_DEV_AUXDATA("ti,pru-rproc", 0x4a338000, "4a338000.pru1",
- &pru1_rproc_pdata),
+ OF_DEV_AUXDATA("ti,pru-rproc", 0x4a334000, "4a334000.pru0", NULL),
+ OF_DEV_AUXDATA("ti,pru-rproc", 0x4a338000, "4a338000.pru1", NULL),
{ /* sentinel */ },
};
static struct of_dev_auxdata am4372_pru_rproc_auxdata_lookup[] = {
- OF_DEV_AUXDATA("ti,pru-rproc", 0x54434000, "54434000.pru0",
- &pru0_rproc_pdata),
- OF_DEV_AUXDATA("ti,pru-rproc", 0x54438000, "54438000.pru1",
- &pru1_rproc_pdata),
+ OF_DEV_AUXDATA("ti,pru-rproc", 0x54434000, "54434000.pru0", NULL),
+ OF_DEV_AUXDATA("ti,pru-rproc", 0x54438000, "54438000.pru1", NULL),
{ /* sentinel */ },
};
static struct of_dev_auxdata am5728_pruss1_rproc_auxdata_lookup[] = {
- OF_DEV_AUXDATA("ti,pru-rproc", 0x4b234000, "4b234000.pru0",
- &pru1_0_rproc_pdata),
- OF_DEV_AUXDATA("ti,pru-rproc", 0x4b238000, "4b238000.pru1",
- &pru1_1_rproc_pdata),
+ OF_DEV_AUXDATA("ti,pru-rproc", 0x4b234000, "4b234000.pru0", NULL),
+ OF_DEV_AUXDATA("ti,pru-rproc", 0x4b238000, "4b238000.pru1", NULL),
{ /* sentinel */ },
};
static struct of_dev_auxdata am5728_pruss2_rproc_auxdata_lookup[] = {
- OF_DEV_AUXDATA("ti,pru-rproc", 0x4b2b4000, "4b2b4000.pru0",
- &pru2_0_rproc_pdata),
- OF_DEV_AUXDATA("ti,pru-rproc", 0x4b2b8000, "4b2b8000.pru1",
- &pru2_1_rproc_pdata),
+ OF_DEV_AUXDATA("ti,pru-rproc", 0x4b2b4000, "4b2b4000.pru0", NULL),
+ OF_DEV_AUXDATA("ti,pru-rproc", 0x4b2b8000, "4b2b8000.pru1", NULL),
{ /* sentinel */ },
};
+/*
+ * A single match structure is used against a unified compatible
+ * string "ti,pru-rproc" as the addresses of the different PRU cores
+ * are unique across all the applicable SoCs.
+ * XXX: A SoC-specific compatible string is probably a better option
+ * for the future to allow more flexibility.
+ */
+static struct pru_match_private_data pru_match_data[] = {
+ /* AM33xx SoC-specific data */
+ {
+ .device_name = "4a334000.pru0",
+ .priv_data = &pru0_rproc_pdata,
+ },
+ {
+ .device_name = "4b280000.pru1",
+ .priv_data = &pru1_rproc_pdata,
+ },
+ /* AM43xx SoC-specific data */
+ {
+ .device_name = "54434000.pru0",
+ .priv_data = &pru0_rproc_pdata,
+ },
+ {
+ .device_name = "54438000.pru1",
+ .priv_data = &pru1_rproc_pdata,
+ },
+ /* AM57xx SoC-specific data */
+ {
+ .device_name = "4b234000.pru0",
+ .priv_data = &pru1_0_rproc_pdata,
+ },
+ {
+ .device_name = "4b238000.pru1",
+ .priv_data = &pru1_1_rproc_pdata,
+ },
+ {
+ .device_name = "4b2b4000.pru0",
+ .priv_data = &pru2_0_rproc_pdata,
+ },
+ {
+ .device_name = "4b2b8000.pru1",
+ .priv_data = &pru2_1_rproc_pdata,
+ },
+ {
+ /* sentinel */
+ },
+};
+
static const struct of_device_id pru_rproc_match[] = {
- { .compatible = "ti,pru-rproc", .data = NULL, },
+ { .compatible = "ti,pru-rproc", .data = pru_match_data, },
{},
};
MODULE_DEVICE_TABLE(of, pru_rproc_match);