From patchwork Thu Jul 20 11:29:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikita Shubin via B4 Relay X-Patchwork-Id: 13320057 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BF15317FFE for ; Thu, 20 Jul 2023 08:30:03 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id EAA58C433B8; Thu, 20 Jul 2023 08:29:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1689841798; bh=B41VfWjJUYNCAgyaPP+TYEOPCZQ82oy+u4UZlDn4QsA=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=JbFJwH4VeKiXMfCUHpVso7qsQGWoIaii0h9/KOgKuOmXuJPD2HDtJGfP2hhmAJHxC +pQbmKCmhbwsEguNTRmA2D+rDhOkch1IvxtZ3nfOJcF7EJyjwQpjnngBybe5dZanSJ 9eMFeYHk77c3GVyLiEJdwhn/CSe8ZlWIOGW1gWDU5svMQPs37EKPmMpBlWjHvypHGF bGwFHGMWC/iuaDNyoNYO1Vvpu6/CmHl7fydPnTW09qsL4AGGqSJYW3Z4A0n9wUsHo6 HyYJFjtY23oN/ZuOpgwZld0RmezpuiTpdOGSLCsDAi/Wkpq1ApNxyOxmaT0mcqyIC9 kIKobMurH5jHA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id D1844C05053; Thu, 20 Jul 2023 08:29:57 +0000 (UTC) From: Nikita Shubin via B4 Relay Date: Thu, 20 Jul 2023 14:29:22 +0300 Subject: [PATCH v3 22/42] dma: cirrus: add DT support for Cirrus EP93xx Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20230605-ep93xx-v3-22-3d63a5f1103e@maquefel.me> References: <20230605-ep93xx-v3-0-3d63a5f1103e@maquefel.me> In-Reply-To: <20230605-ep93xx-v3-0-3d63a5f1103e@maquefel.me> List-Id: To: Hartley Sweeten , Lennert Buytenhek , Alexander Sverdlin , Russell King , Lukasz Majewski , Linus Walleij , Bartosz Golaszewski , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Nikita Shubin , Daniel Lezcano , Thomas Gleixner , Alessandro Zummo , Alexandre Belloni , Wim Van Sebroeck , Guenter Roeck , Sebastian Reichel , Thierry Reding , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Mark Brown , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Vinod Koul , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Damien Le Moal , Sergey Shtylyov , Dmitry Torokhov , Arnd Bergmann , Olof Johansson , soc@kernel.org, Liam Girdwood , Jaroslav Kysela , Takashi Iwai , Andy Shevchenko , Michael Peters , Kris Bahnsen Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-rtc@vger.kernel.org, linux-watchdog@vger.kernel.org, linux-pm@vger.kernel.org, linux-pwm@vger.kernel.org, linux-spi@vger.kernel.org, netdev@vger.kernel.org, dmaengine@vger.kernel.org, linux-mtd@lists.infradead.org, linux-ide@vger.kernel.org, linux-input@vger.kernel.org, alsa-devel@alsa-project.org X-Mailer: b4 0.12.1 X-Developer-Signature: v=1; a=ed25519-sha256; t=1689852591; l=6877; i=nikita.shubin@maquefel.me; s=20230718; h=from:subject:message-id; bh=Q54A7sVkI/IbwRjo56tAXtqK4EnifqnuJhkrT/M+cqk=; =?utf-8?q?b=3DkUkeyK+easjH?= =?utf-8?q?jaYYKYrZA2DfE76vfQBnaBtNnVU8gi1hrFaI3Ojm3MURz8q9fZxHR99C49v5LdLC?= GUIPIt4yA1sfmEh79rsMOnL2V983f+1lJlTJr9y7vFYhk+DFeKMv X-Developer-Key: i=nikita.shubin@maquefel.me; a=ed25519; pk=vqf5YIUJ7BJv3EJFaNNxWZgGuMgDH6rwufTLflwU9ac= X-Endpoint-Received: by B4 Relay for nikita.shubin@maquefel.me/20230718 with auth_id=65 X-Original-From: Nikita Shubin Reply-To: From: Nikita Shubin - drop subsys_initcall code - add OF ID match table with data - add of_probe for device tree Co-developed-by: Alexander Sverdlin Signed-off-by: Alexander Sverdlin Signed-off-by: Nikita Shubin --- drivers/dma/ep93xx_dma.c | 131 ++++++++++++++++++++++++++++--- include/linux/platform_data/dma-ep93xx.h | 4 + 2 files changed, 122 insertions(+), 13 deletions(-) diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c index 5338a94f1a69..1b38180e2a2c 100644 --- a/drivers/dma/ep93xx_dma.c +++ b/drivers/dma/ep93xx_dma.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include @@ -104,6 +106,11 @@ #define DMA_MAX_CHAN_BYTES 0xffff #define DMA_MAX_CHAN_DESCRIPTORS 32 +enum ep93xx_dma_type { + M2P_DMA, + M2M_DMA, +}; + struct ep93xx_dma_engine; static int ep93xx_dma_slave_config_write(struct dma_chan *chan, enum dma_transfer_direction dir, @@ -216,6 +223,11 @@ struct ep93xx_dma_engine { struct ep93xx_dma_chan channels[]; }; +struct ep93xx_edma_data { + u32 id; + size_t num_channels; +}; + static inline struct device *chan2dev(struct ep93xx_dma_chan *edmac) { return &edmac->chan.dev->device; @@ -1315,22 +1327,82 @@ static void ep93xx_dma_issue_pending(struct dma_chan *chan) ep93xx_dma_advance_work(to_ep93xx_dma_chan(chan)); } -static int __init ep93xx_dma_probe(struct platform_device *pdev) + +#ifdef CONFIG_OF +static struct ep93xx_dma_engine *ep93xx_dma_of_probe(struct platform_device *pdev) { - struct ep93xx_dma_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct device_node *np = pdev->dev.of_node; + const struct ep93xx_edma_data *data; struct ep93xx_dma_engine *edma; struct dma_device *dma_dev; - size_t edma_size; - int ret, i; + int i; + + data = of_device_get_match_data(&pdev->dev); + if (!data) + return ERR_PTR(dev_err_probe(&pdev->dev, -ENODEV, "No device match found\n")); - edma_size = pdata->num_channels * sizeof(struct ep93xx_dma_chan); - edma = kzalloc(sizeof(*edma) + edma_size, GFP_KERNEL); + edma = devm_kzalloc(&pdev->dev, + struct_size(edma, channels, data->num_channels), + GFP_KERNEL); if (!edma) - return -ENOMEM; + return ERR_PTR(-ENOMEM); + edma->m2m = data->id; + edma->num_channels = data->num_channels; dma_dev = &edma->dma_dev; + + INIT_LIST_HEAD(&dma_dev->channels); + for (i = 0; i < edma->num_channels; i++) { + struct ep93xx_dma_chan *edmac = &edma->channels[i]; + + edmac->chan.device = dma_dev; + edmac->regs = devm_platform_ioremap_resource(pdev, i); + edmac->irq = platform_get_irq(pdev, i); + edmac->edma = edma; + + edmac->clk = of_clk_get(np, i); + + if (IS_ERR(edmac->clk)) { + dev_warn(&pdev->dev, "failed to get clock\n"); + continue; + } + + spin_lock_init(&edmac->lock); + INIT_LIST_HEAD(&edmac->active); + INIT_LIST_HEAD(&edmac->queue); + INIT_LIST_HEAD(&edmac->free_list); + tasklet_setup(&edmac->tasklet, ep93xx_dma_tasklet); + + list_add_tail(&edmac->chan.device_node, + &dma_dev->channels); + } + + return edma; +} +#else +static int ep93xx_dma_of_probe(struct platform_device *pdev, + struct ep93xx_dma_engine *edma) +{ + return -EINVAL; +} +#endif + +static struct ep93xx_dma_engine *ep93xx_init_from_pdata(struct platform_device *pdev) +{ + struct ep93xx_dma_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct ep93xx_dma_engine *edma; + struct dma_device *dma_dev; + int i; + + edma = devm_kzalloc(&pdev->dev, + struct_size(edma, channels, pdata->num_channels), + GFP_KERNEL); + if (!edma) + return ERR_PTR(-ENOMEM); + edma->m2m = platform_get_device_id(pdev)->driver_data; edma->num_channels = pdata->num_channels; + dma_dev = &edma->dma_dev; INIT_LIST_HEAD(&dma_dev->channels); for (i = 0; i < pdata->num_channels; i++) { @@ -1359,6 +1431,25 @@ static int __init ep93xx_dma_probe(struct platform_device *pdev) &dma_dev->channels); } + return edma; +} + +static int ep93xx_dma_probe(struct platform_device *pdev) +{ + struct ep93xx_dma_engine *edma; + struct dma_device *dma_dev; + int ret, i; + + if (platform_get_device_id(pdev)) + edma = ep93xx_init_from_pdata(pdev); + else + edma = ep93xx_dma_of_probe(pdev); + + if (!edma) + return PTR_ERR(edma); + + dma_dev = &edma->dma_dev; + dma_cap_zero(dma_dev->cap_mask); dma_cap_set(DMA_SLAVE, dma_dev->cap_mask); dma_cap_set(DMA_CYCLIC, dma_dev->cap_mask); @@ -1410,6 +1501,23 @@ static int __init ep93xx_dma_probe(struct platform_device *pdev) return ret; } +static const struct ep93xx_edma_data edma_m2p = { + .id = M2P_DMA, + .num_channels = 10, +}; + +static const struct ep93xx_edma_data edma_m2m = { + .id = M2M_DMA, + .num_channels = 2, +}; + +static const struct of_device_id ep93xx_dma_of_ids[] = { + { .compatible = "cirrus,ep9301-dma-m2p", .data = &edma_m2p }, + { .compatible = "cirrus,ep9301-dma-m2m", .data = &edma_m2m }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, ep93xx_dma_of_ids); + static const struct platform_device_id ep93xx_dma_driver_ids[] = { { "ep93xx-dma-m2p", 0 }, { "ep93xx-dma-m2m", 1 }, @@ -1419,15 +1527,12 @@ static const struct platform_device_id ep93xx_dma_driver_ids[] = { static struct platform_driver ep93xx_dma_driver = { .driver = { .name = "ep93xx-dma", + .of_match_table = ep93xx_dma_of_ids, }, .id_table = ep93xx_dma_driver_ids, + .probe = ep93xx_dma_probe, }; -static int __init ep93xx_dma_module_init(void) -{ - return platform_driver_probe(&ep93xx_dma_driver, ep93xx_dma_probe); -} -subsys_initcall(ep93xx_dma_module_init); - +module_platform_driver(ep93xx_dma_driver); MODULE_AUTHOR("Mika Westerberg "); MODULE_DESCRIPTION("EP93xx DMA driver"); diff --git a/include/linux/platform_data/dma-ep93xx.h b/include/linux/platform_data/dma-ep93xx.h index 54b41d1468ef..b5b4bd5f9a9e 100644 --- a/include/linux/platform_data/dma-ep93xx.h +++ b/include/linux/platform_data/dma-ep93xx.h @@ -5,6 +5,7 @@ #include #include #include +#include #include /** @@ -51,6 +52,9 @@ struct ep93xx_dma_platform_data { static inline bool ep93xx_dma_chan_is_m2p(struct dma_chan *chan) { + if (of_device_is_compatible(dev_of_node(chan->device->dev), "cirrus,ep9301-dma-m2p")) + return true; + return !strcmp(dev_name(chan->device->dev), "ep93xx-dma-m2p"); }