diff options
author | Praneeth Bajjuri <praneeth@ti.com> | 2015-02-03 14:27:36 -0600 |
---|---|---|
committer | Praneeth Bajjuri <praneeth@ti.com> | 2015-02-03 14:27:36 -0600 |
commit | 29044f4094cf5a2bf4231664150fac80ed4c3bdd (patch) | |
tree | 783591d24377374ee144ccb34a03bda411a59f8a | |
parent | b2a6a3d144669701732568cde5cce17aa37c1ae1 (diff) | |
parent | 2b84d7abbc77c51bee46026e4b9e31e3e583be29 (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.c | 2 | ||||
-rw-r--r-- | drivers/iommu/omap-iommu.c | 4 | ||||
-rw-r--r-- | drivers/remoteproc/pruss_remoteproc.c | 143 |
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); |