Hi Tero, On Fri, Dec 13, 2019 at 02:55:24PM +0200, Tero Kristo wrote: > From: Suman Anna <s-anna@xxxxxx> > > OMAP4+ SoCs support device tree boot only. The OMAP remoteproc > driver is enhanced to support remoteproc devices created through > Device Tree, support for legacy platform devices has been > deprecated. The current DT support handles the IPU and DSP > processor subsystems on OMAP4 and OMAP5 SoCs. > > The OMAP remoteproc driver relies on the ti-sysc, reset, and > syscon layers for performing clock, reset and boot vector > management (DSP remoteprocs only) of the devices, but some of > these are limited only to the machine-specific layers > in arch/arm. The dependency against control module API for boot > vector management of the DSP remoteprocs has now been removed > with added logic to parse the boot register from the DT node > and program it appropriately directly within the driver. > > The OMAP remoteproc driver expects the firmware names to be > provided via device tree entries (firmware-name.) These are used > to load the proper firmware during boot of the remote processor. > > Cc: Tony Lindgren <tony@xxxxxxxxxxx> > Signed-off-by: Suman Anna <s-anna@xxxxxx> > [t-kristo@xxxxxx: converted to use ti-sysc framework] > Signed-off-by: Tero Kristo <t-kristo@xxxxxx> > --- > drivers/remoteproc/omap_remoteproc.c | 191 +++++++++++++++++++++++---- > 1 file changed, 168 insertions(+), 23 deletions(-) > > diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c > index 6398194075aa..558634624590 100644 > --- a/drivers/remoteproc/omap_remoteproc.c > +++ b/drivers/remoteproc/omap_remoteproc.c > @@ -2,7 +2,7 @@ > /* > * OMAP Remote Processor driver > * > - * Copyright (C) 2011 Texas Instruments, Inc. > + * Copyright (C) 2011-2019 Texas Instruments Incorporated - http://www.ti.com/ > * Copyright (C) 2011 Google, Inc. > * > * Ohad Ben-Cohen <ohad@xxxxxxxxxx> > @@ -16,27 +16,53 @@ > #include <linux/kernel.h> > #include <linux/module.h> > #include <linux/err.h> > +#include <linux/of_device.h> > #include <linux/platform_device.h> > #include <linux/dma-mapping.h> > #include <linux/remoteproc.h> > #include <linux/mailbox_client.h> > #include <linux/omap-mailbox.h> > - > -#include <linux/platform_data/remoteproc-omap.h> > +#include <linux/regmap.h> > +#include <linux/mfd/syscon.h> > +#include <linux/reset.h> > > #include "omap_remoteproc.h" > #include "remoteproc_internal.h" > > +/** > + * struct omap_rproc_boot_data - boot data structure for the DSP omap rprocs > + * @syscon: regmap handle for the system control configuration module > + * @boot_reg: boot register offset within the @syscon regmap > + */ > +struct omap_rproc_boot_data { > + struct regmap *syscon; > + unsigned int boot_reg; > +}; > + > /** > * struct omap_rproc - omap remote processor state > * @mbox: mailbox channel handle > * @client: mailbox client to request the mailbox channel > + * @boot_data: boot data structure for setting processor boot address > * @rproc: rproc handle > + * @reset: reset handle > */ > struct omap_rproc { > struct mbox_chan *mbox; > struct mbox_client client; > + struct omap_rproc_boot_data *boot_data; > struct rproc *rproc; > + struct reset_control *reset; > +}; > + > +/** > + * struct omap_rproc_dev_data - device data for the omap remote processor > + * @device_name: device name of the remote processor > + * @has_bootreg: true if this remote processor has boot register > + */ > +struct omap_rproc_dev_data { > + const char *device_name; > + bool has_bootreg; > }; > > /** > @@ -92,6 +118,21 @@ static void omap_rproc_kick(struct rproc *rproc, int vqid) > ret); > } > > +/** > + * omap_rproc_write_dsp_boot_addr - set boot address for a DSP remote processor > + * @rproc: handle of a remote processor > + * > + * Set boot address for a supported DSP remote processor. > + */ > +static void omap_rproc_write_dsp_boot_addr(struct rproc *rproc) > +{ > + struct omap_rproc *oproc = rproc->priv; > + struct omap_rproc_boot_data *bdata = oproc->boot_data; > + u32 offset = bdata->boot_reg; > + > + regmap_write(bdata->syscon, offset, rproc->bootaddr); > +} > + > /* > * Power up the remote processor. > * > @@ -103,13 +144,11 @@ static int omap_rproc_start(struct rproc *rproc) > { > struct omap_rproc *oproc = rproc->priv; > struct device *dev = rproc->dev.parent; > - struct platform_device *pdev = to_platform_device(dev); > - struct omap_rproc_pdata *pdata = pdev->dev.platform_data; > int ret; > struct mbox_client *client = &oproc->client; > > - if (pdata->set_bootaddr) > - pdata->set_bootaddr(rproc->bootaddr); > + if (oproc->boot_data) > + omap_rproc_write_dsp_boot_addr(rproc); > > client->dev = dev; > client->tx_done = NULL; > @@ -117,7 +156,7 @@ static int omap_rproc_start(struct rproc *rproc) > client->tx_block = false; > client->knows_txdone = false; > > - oproc->mbox = omap_mbox_request_channel(client, pdata->mbox_name); > + oproc->mbox = mbox_request_channel(client, 0); > if (IS_ERR(oproc->mbox)) { > ret = -EBUSY; > dev_err(dev, "mbox_request_channel failed: %ld\n", > @@ -138,11 +177,7 @@ static int omap_rproc_start(struct rproc *rproc) > goto put_mbox; > } > > - ret = pdata->device_enable(pdev); > - if (ret) { > - dev_err(dev, "omap_device_enable failed: %d\n", ret); > - goto put_mbox; > - } > + reset_control_deassert(oproc->reset); > > return 0; > > @@ -154,15 +189,9 @@ static int omap_rproc_start(struct rproc *rproc) > /* power off the remote processor */ > static int omap_rproc_stop(struct rproc *rproc) > { > - struct device *dev = rproc->dev.parent; > - struct platform_device *pdev = to_platform_device(dev); > - struct omap_rproc_pdata *pdata = pdev->dev.platform_data; > struct omap_rproc *oproc = rproc->priv; > - int ret; > > - ret = pdata->device_shutdown(pdev); > - if (ret) > - return ret; > + reset_control_assert(oproc->reset); > > mbox_free_channel(oproc->mbox); > > @@ -175,12 +204,122 @@ static const struct rproc_ops omap_rproc_ops = { > .kick = omap_rproc_kick, > }; > > +static const struct omap_rproc_dev_data omap4_dsp_dev_data = { > + .device_name = "dsp", > + .has_bootreg = true, > +}; > + > +static const struct omap_rproc_dev_data omap4_ipu_dev_data = { > + .device_name = "ipu", > +}; > + > +static const struct omap_rproc_dev_data omap5_dsp_dev_data = { > + .device_name = "dsp", > + .has_bootreg = true, > +}; > + > +static const struct omap_rproc_dev_data omap5_ipu_dev_data = { > + .device_name = "ipu", > +}; > + > +static const struct of_device_id omap_rproc_of_match[] = { > + { > + .compatible = "ti,omap4-dsp", > + .data = &omap4_dsp_dev_data, > + }, > + { > + .compatible = "ti,omap4-ipu", > + .data = &omap4_ipu_dev_data, > + }, > + { > + .compatible = "ti,omap5-dsp", > + .data = &omap5_dsp_dev_data, > + }, > + { > + .compatible = "ti,omap5-ipu", > + .data = &omap5_ipu_dev_data, > + }, > + { > + /* end */ > + }, > +}; > +MODULE_DEVICE_TABLE(of, omap_rproc_of_match); > + > +static const char *omap_rproc_get_firmware(struct platform_device *pdev) > +{ > + const char *fw_name; > + int ret; > + > + ret = of_property_read_string(pdev->dev.of_node, "firmware-name", > + &fw_name); > + if (ret) > + return ERR_PTR(ret); > + > + return fw_name; > +} > + > +static int omap_rproc_get_boot_data(struct platform_device *pdev, > + struct rproc *rproc) > +{ > + struct device_node *np = pdev->dev.of_node; > + struct omap_rproc *oproc = rproc->priv; > + const struct omap_rproc_dev_data *data; > + int ret; > + > + data = of_device_get_match_data(&pdev->dev); > + if (!data) > + return -ENODEV; > + > + if (!data->has_bootreg) > + return 0; > + > + oproc->boot_data = devm_kzalloc(&pdev->dev, sizeof(*oproc->boot_data), > + GFP_KERNEL); > + if (!oproc->boot_data) > + return -ENOMEM; > + > + if (!of_property_read_bool(np, "ti,bootreg")) { > + dev_err(&pdev->dev, "ti,bootreg property is missing\n"); > + return -EINVAL; > + } > + > + oproc->boot_data->syscon = > + syscon_regmap_lookup_by_phandle(np, "ti,bootreg"); > + if (IS_ERR(oproc->boot_data->syscon)) { > + ret = PTR_ERR(oproc->boot_data->syscon); > + return ret; > + } > + > + if (of_property_read_u32_index(np, "ti,bootreg", 1, > + &oproc->boot_data->boot_reg)) { > + dev_err(&pdev->dev, "couldn't get the boot register\n"); > + return -EINVAL; > + } > + > + return 0; > +} > + > static int omap_rproc_probe(struct platform_device *pdev) > { > - struct omap_rproc_pdata *pdata = pdev->dev.platform_data; > + struct device_node *np = pdev->dev.of_node; > struct omap_rproc *oproc; > struct rproc *rproc; > + const char *firmware; > int ret; > + struct reset_control *reset; > + > + if (!np) { > + dev_err(&pdev->dev, "only DT-based devices are supported\n"); > + return -ENODEV; > + } > + > + reset = devm_reset_control_array_get_optional_exclusive(&pdev->dev); > + if (IS_ERR(reset)) > + return PTR_ERR(reset); Definition of a reset is listed as "required" in the bindings but here it is optional. If this is really what you want then adding a comment to exlain your choice is probably a good idea. > + > + firmware = omap_rproc_get_firmware(pdev); > + if (IS_ERR(firmware)) > + return PTR_ERR(firmware); > > ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); > if (ret) { > @@ -188,16 +327,21 @@ static int omap_rproc_probe(struct platform_device *pdev) > return ret; > } > > - rproc = rproc_alloc(&pdev->dev, pdata->name, &omap_rproc_ops, > - pdata->firmware, sizeof(*oproc)); > + rproc = rproc_alloc(&pdev->dev, dev_name(&pdev->dev), &omap_rproc_ops, > + firmware, sizeof(*oproc)); > if (!rproc) > return -ENOMEM; > > oproc = rproc->priv; > oproc->rproc = rproc; > + oproc->reset = reset; > /* All existing OMAP IPU and DSP processors have an MMU */ > rproc->has_iommu = true; > > + ret = omap_rproc_get_boot_data(pdev, rproc); > + if (ret) > + goto free_rproc; > + > platform_set_drvdata(pdev, rproc); > > ret = rproc_add(rproc); > @@ -226,6 +370,7 @@ static struct platform_driver omap_rproc_driver = { > .remove = omap_rproc_remove, > .driver = { > .name = "omap-rproc", > + .of_match_table = omap_rproc_of_match, .of_match_table = of_match_ptr(omap_rproc_of_match), Thanks, Mathieu > }, > }; > > -- > 2.17.1 > > -- > Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki