From: Tomasz Figa <tomasz.figa-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
To: Florian Meier <florian.meier-oZ8rN/sblLk@public.gmane.org>
Cc: Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>,
Vinod Koul <vinod.koul-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
Dan Williams
<dan.j.williams-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
linux-rpi-kernel
<linux-rpi-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org>,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
dmaengine-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Liam Girdwood <lgirdwood-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw@public.gmane.org
Subject: Re: [PATCH] dmaengine: Add support for BCM2835.
Date: Wed, 13 Nov 2013 16:02:16 +0100 [thread overview]
Message-ID: <4133885.XyqaHYljiZ@flatron> (raw)
In-Reply-To: <527D1DDA.2040004-oZ8rN/sblLk@public.gmane.org>
Hi Florian,
Most of technical issues have been already mentioned by Russell, but let
me also point those that I found. Please see my comments inline.
On Friday 08 of November 2013 18:22:34 Florian Meier wrote:
> Add support for DMA controller of BCM2835 as used in the Raspberry Pi.
> Currently it only supports cyclic DMA for serving the I2S driver.
>
> Signed-off-by: Florian Meier <florian.meier-oZ8rN/sblLk@public.gmane.org>
> ---
> arch/arm/boot/dts/bcm2835.dtsi | 22 +
> drivers/dma/Kconfig | 6 +
> drivers/dma/Makefile | 1 +
> drivers/dma/bcm2835-dma.c | 880 ++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 909 insertions(+)
> create mode 100644 drivers/dma/bcm2835-dma.c
>
> diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi
> index 1e12aef..1514198 100644
> --- a/arch/arm/boot/dts/bcm2835.dtsi
> +++ b/arch/arm/boot/dts/bcm2835.dtsi
> @@ -103,6 +103,28 @@
> clocks = <&clk_mmc>;
> status = "disabled";
> };
> +
> + dma: dma@7e007000 {
> + compatible = "brcm,bcm2835-dma";
> + reg = <0x7e007000 0xf00>;
> + interrupts = <1 16
> + 1 17
> + 1 18
> + 1 19
> + 1 20
> + 1 21
> + 1 22
> + 1 23
> + 1 24
> + 1 25
> + 1 26
> + 1 27
> + 1 28>;
> +
> + #dma-cells = <1>;
> + dma-channels = <15>; /* DMA channel 15 is not handled yet */
This should represent the real configuration of the hardware, regardless
of what the driver supports.
> + dma-requests = <32>;
> + };
> };
>
> clocks {
This should be a separate patch, following the one adding the driver.
In addition, you are introducing a new device tree binding with this
patch, so you should document it in appropriate location under
Documentation/devicetree/bindings.
> diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
> new file mode 100644
> index 0000000..c3e53b3
> --- /dev/null
> +++ b/drivers/dma/bcm2835-dma.c
> @@ -0,0 +1,880 @@
[snip]
> +struct bcm2835_dma_cb {
> + unsigned long info;
> + unsigned long src;
> + unsigned long dst;
> + unsigned long length;
> + unsigned long stride;
> + unsigned long next;
> + unsigned long pad[2];
> +};
Is unsigned long really what you want here, not some explicitly sized
types, such as u32 or uint32_t? This seems to be some kind of hardware
interface, so the latter sounds more reasonable to me.
[snip]
> +#if defined(CONFIG_OF)
> +static const struct of_device_id bcm2835_dma_of_match[] = {
> + {
> + .compatible = "brcm,bcm2835-dma",
> + }
A dummy terminating entry is needed here.
> +};
> +MODULE_DEVICE_TABLE(of, bcm2835_dma_of_match);
> +#endif
> +
> +static int bcm2835_dma_probe(struct platform_device *pdev)
> +{
> + struct bcm2835_dmadev *od;
> + struct resource *dma_res = NULL;
> + void __iomem *dma_base = NULL;
> + int rc = 0;
> + int i;
> + struct resource *irq;
> + int irq_resources;
> +
> + od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL);
> + if (!od)
> + return -ENOMEM;
> +
> + dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + dma_base = devm_ioremap_resource(&pdev->dev, dma_res);
> + if (IS_ERR(dma_base))
> + return PTR_ERR(dma_base);
> +
> + od->dma_base = dma_base;
> + od->chans_available = BCM2835_DMA_CHANNEL_MASK;
> +
> + dma_cap_set(DMA_SLAVE, od->ddev.cap_mask);
> + dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask);
> + od->ddev.device_alloc_chan_resources = bcm2835_dma_alloc_chan_resources;
> + od->ddev.device_free_chan_resources = bcm2835_dma_free_chan_resources;
> + od->ddev.device_tx_status = bcm2835_dma_tx_status;
> + od->ddev.device_issue_pending = bcm2835_dma_issue_pending;
> + od->ddev.device_prep_dma_cyclic = bcm2835_dma_prep_dma_cyclic;
> + od->ddev.device_control = bcm2835_dma_control;
> + od->ddev.dev = &pdev->dev;
> + INIT_LIST_HEAD(&od->ddev.channels);
> + INIT_LIST_HEAD(&od->pending);
> + spin_lock_init(&od->lock);
> +
> + tasklet_init(&od->task, bcm2835_dma_sched, (unsigned long)od);
Just a question out of curiosity, as I don't really know much about the
DMA engine subsystem:
What is the reason to use tasklets here instead of, let's say, a workqueue?
> +
> + irq_resources = 0;
> +
> + for (i = 0; i < pdev->num_resources; i++) {
> + if (IORESOURCE_IRQ == resource_type(&pdev->resource[i]))
> + irq_resources++;
> + }
> +
> + od->dma_irq_numbers = devm_kzalloc(&pdev->dev,
> + irq_resources*sizeof(int), GFP_KERNEL);
> + if (!od)
> + return -ENOMEM;
> +
> + for (i = 0; i < irq_resources; i++) {
You could call platform_get_irq() here and break out of the loop if it
fails with -ENXIO. Then the IRQ number could be passed to
bcm2835_dma_chan_init() and stored in per-channel struct. This way you
could remove the ugly IRQ counting code above and IRQ array allocation.
> + rc = bcm2835_dma_chan_init(od, i);
> + if (rc) {
> + bcm2835_dma_free(od);
> + return rc;
> + }
> +
> + irq = platform_get_resource(pdev, IORESOURCE_IRQ, i);
There is platform_get_irq() for reading IRQ resources specifically.
> + if (!irq) {
> + dev_err(&pdev->dev,
> + "No IRQ resource for channel %i\n", i);
> + return -ENODEV;
> + }
> + od->dma_irq_numbers[i] = irq->start;
> + }
> +
> + rc = dma_async_device_register(&od->ddev);
This should be called at the end of probe, to ensure that any potential
users can start generating requests to your DMA engine as soon as
it is registered.
> + if (rc) {
> + dev_err(&pdev->dev,
> + "Failed to register slave DMA engine device: %d\n", rc);
> + bcm2835_dma_free(od);
> + return rc;
> + }
> +
> + platform_set_drvdata(pdev, od);
[snip]
> +
> +static const struct platform_device_info bcm2835_dma_dev_info = {
> + .name = "bcm2835-dma",
> + .id = -1,
> + .dma_mask = DMA_BIT_MASK(32),
> +};
What's this?
> +
> +static int bcm2835_dma_init(void)
> +{
> + int rc = platform_driver_register(&bcm2835_dma_driver);
> + return rc;
> +}
> +subsys_initcall(bcm2835_dma_init);
Do you really need subsys_initcall here?
Best regards,
Tomasz
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
prev parent reply other threads:[~2013-11-13 15:02 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-11-08 17:22 [PATCH] dmaengine: Add support for BCM2835 Florian Meier
2013-11-08 18:17 ` Mark Brown
[not found] ` <20131108181743.GR2493-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
2013-11-13 5:00 ` Vinod Koul
[not found] ` <20131113050017.GO8834-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2013-11-13 12:51 ` Mark Brown
[not found] ` <20131113125111.GE878-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
2013-11-13 13:35 ` Vinod Koul
2013-11-13 14:54 ` Mark Brown
2013-11-13 14:31 ` Vinod Koul
[not found] ` <20131113143101.GD8834-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2013-11-13 16:30 ` Mark Brown
[not found] ` <527D1DDA.2040004-oZ8rN/sblLk@public.gmane.org>
2013-11-08 19:11 ` Russell King - ARM Linux
[not found] ` <20131108191117.GT16735-l+eeeJia6m9vn6HldHNs0ANdhmdF6hFW@public.gmane.org>
2013-11-11 12:36 ` Florian Meier
2013-11-13 15:02 ` Tomasz Figa [this message]
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=4133885.XyqaHYljiZ@flatron \
--to=tomasz.figa-re5jqeeqqe8avxtiumwx3w@public.gmane.org \
--cc=alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw@public.gmane.org \
--cc=broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
--cc=dan.j.williams-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
--cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=dmaengine-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=florian.meier-oZ8rN/sblLk@public.gmane.org \
--cc=lgirdwood-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
--cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
--cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-rpi-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
--cc=swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org \
--cc=vinod.koul-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
/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).