From: Bjorn Andersson <bjorn.andersson@linaro.org>
To: Peter Griffin <peter.griffin@linaro.org>
Cc: linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, srinivas.kandagatla@gmail.com,
maxime.coquelin@st.com, patrice.chotard@st.com,
vinod.koul@intel.com, ohad@wizery.com, arnd@arndb.de,
lee.jones@linaro.org, devicetree@vger.kernel.org,
dmaengine@vger.kernel.org, linux-remoteproc@vger.kernel.org
Subject: Re: [PATCH v4 01/18] remoteproc: st_xp70_rproc: add a xp70 slimcore rproc driver
Date: Wed, 25 May 2016 10:10:43 -0700 [thread overview]
Message-ID: <20160525171043.GT1256@tuxbot> (raw)
In-Reply-To: <1464192412-16386-3-git-send-email-peter.griffin@linaro.org>
On Wed 25 May 09:06 PDT 2016, Peter Griffin wrote:
> XP70 slim core is used as a basis for many IPs in the STi
> chipsets such as fdma, display, and demux. To avoid
> duplicating the elf loading code in each device driver
> an xp70 rproc driver has been created.
>
I like this approach.
[..]
> diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
[..]
>
> +config ST_XP70_REMOTEPROC
> + tristate "XP70 slim remoteproc support"
As this "driver" in itself doesn't do anything I don't think it makes
sense to have it user selectable. Please make the "clients" select it
instead.
> + depends on ARCH_STI
> + select REMOTEPROC
> + help
> + Say y here to support xp70 slim core.
> + If unsure say N.
> +
> endmenu
> diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
[..]
> +#include <linux/clk.h>
> +#include <linux/elf.h>
You should be able to drop inclusion of elf.h now.
[..]
> +static int xp70_clk_get(struct st_xp70_rproc *xp70_rproc, struct device *dev)
> +{
> + int clk, err = 0;
No need to initialize err.
> +
> + for (clk = 0; clk < XP70_MAX_CLK; clk++) {
> + xp70_rproc->clks[clk] = of_clk_get(dev->of_node, clk);
> + if (IS_ERR(xp70_rproc->clks[clk])) {
> + err = PTR_ERR(xp70_rproc->clks[clk]);
> + if (err == -EPROBE_DEFER)
> + goto err_put_clks;
> + xp70_rproc->clks[clk] = NULL;
> + break;
> + }
> + }
> +
> + return 0;
> +
> +err_put_clks:
> + while (--clk >= 0)
> + clk_put(xp70_rproc->clks[clk]);
> +
> + return err;
> +}
> +
[..]
> +/**
> + * Remoteproc xp70 specific device handlers
> + */
> +static int xp70_rproc_start(struct rproc *rproc)
> +{
> + struct device *dev = &rproc->dev;
> + struct st_xp70_rproc *xp70_rproc = rproc->priv;
> + unsigned long hw_id, hw_ver, fw_rev;
> + u32 val, ret = 0;
ret should be signed and there's no need to initialize it.
> +
> + ret = xp70_clk_enable(xp70_rproc);
> + if (ret) {
> + dev_err(dev, "Failed to enable clocks\n");
> + goto err_clk;
> + }
[..]
> +
> + dev_dbg(dev, "XP70 started\n");
> +
> +err_clk:
> + return ret;
> +}
> +
> +static int xp70_rproc_stop(struct rproc *rproc)
> +{
> + struct st_xp70_rproc *xp70_rproc = rproc->priv;
> + u32 val;
> +
> + /* mask all (cmd & int) channels */
> + writel_relaxed(0UL, xp70_rproc->peri + XP70_INT_MASK_OFST);
> + writel_relaxed(0UL, xp70_rproc->peri + XP70_CMD_MASK_OFST);
> +
> + /* disable cpu pipeline clock */
> + writel_relaxed(XP70_CLK_GATE_DIS
> + , xp70_rproc->slimcore + XP70_CLK_GATE_OFST);
> +
> + writel_relaxed(!XP70_EN_RUN, xp70_rproc->slimcore + XP70_EN_OFST);
Don't you want to ensure ordering of these writes? Perhaps making this
last one a writel()?
> +
> + val = readl_relaxed(xp70_rproc->slimcore + XP70_EN_OFST);
> + if (val & XP70_EN_RUN)
> + dev_warn(&rproc->dev, "Failed to disable XP70");
> +
> + xp70_clk_disable(xp70_rproc);
> +
> + dev_dbg(&rproc->dev, "xp70 stopped\n");
> +
> + return 0;
> +}
> +
> +static void *xp70_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> +{
> + struct st_xp70_rproc *xp70_rproc = rproc->priv;
> + void *va = NULL;
> + int i;
> +
> + for (i = 0; i < XP70_MEM_MAX; i++) {
> +
> + if (da != xp70_rproc->mem[i].bus_addr)
> + continue;
> +
> + va = xp70_rproc->mem[i].cpu_addr;
> + break;
> + }
Please clean up the indentation and drop the extra newline at the
beginning in this loop.
> +
> + dev_dbg(&rproc->dev, "%s: da = 0x%llx len = 0x%x va = 0x%p\n"
> + , __func__, da, len, va);
> +
> + return va;
> +}
> +
> +static struct rproc_ops xp70_rproc_ops = {
> + .start = xp70_rproc_start,
> + .stop = xp70_rproc_stop,
> + .da_to_va = xp70_rproc_da_to_va,
> +};
> +
> +/**
> + * Firmware handler operations: sanity, boot address, load ...
> + */
> +
> +static struct resource_table empty_rsc_tbl = {
> + .ver = 1,
> + .num = 0,
> +};
I'm looking at making the resource table optional, good to see another
vote for that. Looks good for now though.
[..]
> +
> +/**
> + * xp70_rproc_alloc - allocate and initialise xp70 rproc
Drop one of the two spaces indenting this block and add () after then
function name.
> + * @pdev: Pointer to the platform_device struct
> + * @fw_name: Name of firmware for rproc to use
> + *
> + * Function for allocating and initialising a xp70 rproc for use by
> + * device drivers whose IP is based around the xp70 slim core. It
> + * obtains and enables any clocks required by the xp70 core and also
> + * ioremaps the various IO.
> + *
> + * Returns rproc pointer or PTR_ERR() on error.
> + */
> +
> +struct rproc *xp70_rproc_alloc(struct platform_device *pdev, char *fw_name)
> +{
> + struct device *dev = &pdev->dev;
> + struct st_xp70_rproc *xp70_rproc;
> + struct device_node *np = dev->of_node;
> + struct rproc *rproc;
> + struct resource *res;
> + int err, i;
> + const struct rproc_fw_ops *elf_ops;
> +
> + if (!np || !fw_name)
> + return ERR_PTR(-EINVAL);
This should, I believe, only ever happen in development. So if you want
to keep it to aid developers feel free to throw in a WARN_ON() in the
condition.
> +
> + if (!of_device_is_compatible(np, "st,xp70-rproc"))
> + return ERR_PTR(-EINVAL);
> +
> + rproc = rproc_alloc(dev, np->name, &xp70_rproc_ops,
> + fw_name, sizeof(*xp70_rproc));
> + if (!rproc)
> + return ERR_PTR(-ENOMEM);
> +
> + rproc->has_iommu = false;
> +
> + xp70_rproc = rproc->priv;
> + xp70_rproc->rproc = rproc;
> +
> + /* Get standard ELF ops */
> + elf_ops = rproc_get_elf_ops();
> +
> + /* Use some generic elf ops */
> + xp70_rproc_fw_ops.load = elf_ops->load;
> + xp70_rproc_fw_ops.sanity_check = elf_ops->sanity_check;
> +
> + rproc->fw_ops = &xp70_rproc_fw_ops;
> +
> + /* get imem and dmem */
> + for (i = 0; i < ARRAY_SIZE(mem_names); i++) {
> + res = xp70_rproc->mem[i].io_res;
> +
io_res is NULL here, and res is directly assigned again. So drop this
and io_res from the struct.
> + res = platform_get_resource_byname
> + (pdev, IORESOURCE_MEM, mem_names[i]);
> +
> + xp70_rproc->mem[i].cpu_addr = devm_ioremap_resource(dev, res);
> + if (IS_ERR(xp70_rproc->mem[i].cpu_addr)) {
> + dev_err(&pdev->dev, "devm_ioremap_resource failed\n");
> + err = PTR_ERR(xp70_rproc->mem[i].cpu_addr);
> + goto err;
> + }
> + xp70_rproc->mem[i].bus_addr = res->start;
> + xp70_rproc->mem[i].size = resource_size(res);
> + }
> +
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "slimcore");
> +
> + xp70_rproc->slimcore = devm_ioremap_resource(dev, res);
> + if (IS_ERR(xp70_rproc->slimcore)) {
> + dev_err(&pdev->dev, "devm_ioremap_resource failed for slimcore\n");
> + err = PTR_ERR(xp70_rproc->slimcore);
> + goto err;
> + }
> +
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "peripherals");
> +
> + xp70_rproc->peri = devm_ioremap_resource(dev, res);
> + if (IS_ERR(xp70_rproc->peri)) {
> + dev_err(&pdev->dev, "devm_ioremap_resource failed for peri\n");
> + err = PTR_ERR(xp70_rproc->peri);
> + goto err;
> + }
> +
> + err = xp70_clk_get(xp70_rproc, dev);
> + if (err)
> + goto err;
> +
> + /* Register as a remoteproc device */
> + err = rproc_add(rproc);
> + if (err) {
> + dev_err(dev, "registration of xp70 remoteproc failed\n");
> + goto err;
In this case you should also put the clocks.
> + }
> +
> + dev_dbg(dev, "XP70 rproc init successful\n");
> + return rproc;
> +
> +err:
> + rproc_put(rproc);
> + return ERR_PTR(err);
> +}
> +EXPORT_SYMBOL(xp70_rproc_alloc);
> +
> +/**
> + * xp70_rproc_put - put xp70 rproc resources
> + * @xp70_rproc: Pointer to the st_xp70_rproc struct
> + *
> + * Function for calling respective _put() functions on
> + * xp70_rproc resources.
> + *
> + * Returns rproc pointer or PTR_ERR() on error.
> + */
> +void xp70_rproc_put(struct st_xp70_rproc *xp70_rproc)
> +{
> + int clk;
> +
> + if (!xp70_rproc)
> + return;
> +
> + rproc_put(xp70_rproc->rproc);
> +
> + for (clk = 0; clk < XP70_MAX_CLK && xp70_rproc->clks[clk]; clk++)
> + clk_put(xp70_rproc->clks[clk]);
rproc_put() will free your private data, i.e. xp70_rproc, so you must
put your clocks before that.
> +
> +}
> +EXPORT_SYMBOL(xp70_rproc_put);
> +
> +MODULE_AUTHOR("Peter Griffin");
> +MODULE_DESCRIPTION("STMicroelectronics XP70 rproc driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/remoteproc/st_xp70_rproc.h b/include/linux/remoteproc/st_xp70_rproc.h
[..]
> +
> +#define XP70_MEM_MAX 2
> +#define XP70_MAX_CLK 4
> +#define NAME_SZ 10
NAME_SZ seems unused and would be too generic.
> +
> +enum {
> + DMEM,
> + IMEM,
These are too generic for a header file.
> +};
> +
> +/**
> + * struct xp70_mem - xp70 internal memory structure
> + * @cpu_addr: MPU virtual address of the memory region
> + * @bus_addr: Bus address used to access the memory region
> + * @dev_addr: Device address from Wakeup M3 view
> + * @size: Size of the memory region
> + */
> +struct xp70_mem {
> + void __iomem *cpu_addr;
> + phys_addr_t bus_addr;
> + u32 dev_addr;
dev_addr is unused.
> + size_t size;
> + struct resource *io_res;
io_res is unused.
> +};
> +
> +/**
> + * struct st_xp70_rproc - XP70 slim core
> + * @rproc: rproc handle
> + * @pdev: pointer to platform device
> + * @mem: xp70 memory information
> + * @slimcore: xp70 slimcore regs
> + * @peri: xp70 peripheral regs
> + * @clks: xp70 clocks
> + */
> +struct st_xp70_rproc {
> + struct rproc *rproc;
> + struct platform_device *pdev;
pdev is unused.
> + struct xp70_mem mem[XP70_MEM_MAX];
> + void __iomem *slimcore;
> + void __iomem *peri;
> + struct clk *clks[XP70_MAX_CLK];
> +};
I generally don't like sharing a struct like this between two
implementations, but I don't think it's worth working around it in this
case.
Perhaps you can group the members into a section of "public" and a
section of "private" members; with a /* st_xp70_rproc private */ heading
the latter?
> +
> +struct rproc *xp70_rproc_alloc(struct platform_device *pdev, char *fw_name);
For consistency I think xp70_rproc_alloc() should return a st_xp70_rproc
reference, rather than forcing the clients pull that pointer out of
rproc->priv.
> +void xp70_rproc_put(struct st_xp70_rproc *xp70_rproc);
> +
> +#endif
Regards,
Bjorn
next prev parent reply other threads:[~2016-05-25 17:10 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-05-25 16:06 [PATCH 00/18] Add support for FDMA DMA controller and xp70 rproc found on STi chipsets Peter Griffin
2016-05-25 16:06 ` [PATCH v4 " Peter Griffin
2016-05-25 16:06 ` [PATCH v4 01/18] remoteproc: st_xp70_rproc: add a xp70 slimcore rproc driver Peter Griffin
2016-05-25 17:10 ` Bjorn Andersson [this message]
2016-06-06 7:22 ` Peter Griffin
2016-05-27 13:15 ` Patrice Chotard
[not found] ` <57484867.6030608-qxv4g6HH51o@public.gmane.org>
2016-05-27 16:13 ` Peter Griffin
2016-05-25 16:06 ` [PATCH v4 02/18] ARM: multi_v7_defconfig: enable st xp70 " Peter Griffin
2016-05-25 16:06 ` [PATCH v4 03/18] MAINTAINERS: Add st xp70 rproc driver to STi section Peter Griffin
2016-05-25 16:06 ` [PATCH v4 04/18] dmaengine: st_fdma: Add STMicroelectronics FDMA DT binding documentation Peter Griffin
[not found] ` <1464192412-16386-6-git-send-email-peter.griffin-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2016-05-27 15:44 ` Rob Herring
2016-05-25 16:06 ` [PATCH v4 05/18] dmaengine: st_fdma: Add STMicroelectronics FDMA driver header file Peter Griffin
2016-06-06 4:36 ` Vinod Koul
2016-06-06 17:40 ` Peter Griffin
2016-05-25 16:06 ` [PATCH v4 06/18] dmaengine: st_fdma: Add STMicroelectronics FDMA engine driver support Peter Griffin
2016-05-25 17:27 ` Bjorn Andersson
[not found] ` <1464192412-16386-8-git-send-email-peter.griffin-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2016-06-06 4:54 ` Vinod Koul
2016-06-06 17:38 ` Peter Griffin
2016-05-25 16:06 ` [PATCH v4 07/18] ARM: STi: DT: STiH407: Add FDMA driver dt nodes Peter Griffin
2016-05-25 16:06 ` [PATCH v4 08/18] MAINTAINERS: Add FDMA driver files to STi section Peter Griffin
2016-05-25 16:06 ` [PATCH v4 09/18] ARM: multi_v7_defconfig: Enable STi FDMA driver Peter Griffin
2016-05-25 16:06 ` [PATCH v4 10/18] ASoC: sti: Update DT example to match the driver code Peter Griffin
[not found] ` <1464192412-16386-12-git-send-email-peter.griffin-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2016-05-27 15:47 ` Rob Herring
2016-05-27 17:14 ` Mark Brown
2016-06-03 13:05 ` Peter Griffin
2016-05-25 16:06 ` [PATCH v4 11/18] ARM: multi_v7_defconfig: Enable STi and simple-card drivers Peter Griffin
2016-05-31 8:55 ` Arnaud Pouliquen
[not found] ` <574D5178.5030200-qxv4g6HH51o@public.gmane.org>
2016-06-03 12:39 ` Peter Griffin
2016-05-25 16:06 ` [PATCH v4 12/18] ARM: DT: STiH407: Add i2s_out pinctrl configuration Peter Griffin
2016-05-25 16:06 ` [PATCH v4 13/18] ARM: DT: STiH407: Add i2s_in " Peter Griffin
2016-05-25 16:06 ` [PATCH v4 14/18] ARM: DT: STiH407: Add spdif_out pinctrl config Peter Griffin
2016-05-25 16:06 ` [PATCH v4 15/18] ARM: STi: DT: STiH407: Add sti-sasg-codec dt node Peter Griffin
2016-05-31 9:05 ` Arnaud Pouliquen
2016-06-03 13:00 ` Peter Griffin
2016-05-25 16:06 ` [PATCH v4 17/18] ARM: STi: DT: STiH407: Add uniperif reader dt nodes Peter Griffin
2016-05-31 9:18 ` Arnaud Pouliquen
[not found] ` <574D56CE.5020802-qxv4g6HH51o@public.gmane.org>
2016-06-03 12:50 ` Peter Griffin
2016-05-25 16:06 ` [PATCH v4 18/18] ARM: DT: STi: stihxxx-b2120: Add DT nodes for STi audio card Peter Griffin
2016-05-31 10:16 ` Arnaud Pouliquen
2016-06-03 12:47 ` Peter Griffin
[not found] ` <1464192412-16386-1-git-send-email-peter.griffin-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2016-05-25 16:06 ` [PATCH v4 16/18] ARM: STi: DT: STiH407: Add uniperif player dt nodes Peter Griffin
[not found] ` <1464192412-16386-18-git-send-email-peter.griffin-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2016-05-31 9:14 ` Arnaud Pouliquen
2016-06-03 12:56 ` Peter Griffin
2016-06-06 5:01 ` [PATCH 00/18] Add support for FDMA DMA controller and xp70 rproc found on STi chipsets Vinod Koul
2016-06-06 15:09 ` Peter Griffin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160525171043.GT1256@tuxbot \
--to=bjorn.andersson@linaro.org \
--cc=arnd@arndb.de \
--cc=devicetree@vger.kernel.org \
--cc=dmaengine@vger.kernel.org \
--cc=lee.jones@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-remoteproc@vger.kernel.org \
--cc=maxime.coquelin@st.com \
--cc=ohad@wizery.com \
--cc=patrice.chotard@st.com \
--cc=peter.griffin@linaro.org \
--cc=srinivas.kandagatla@gmail.com \
--cc=vinod.koul@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).