From d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 11 Dec 2023 02:45:28 +0000 Subject: [PATCH] add boot partition size --- kernel/drivers/dma/sh/rcar-dmac.c | 98 ++++++++++++++++++++++++++++++++++--------------- 1 files changed, 68 insertions(+), 30 deletions(-) diff --git a/kernel/drivers/dma/sh/rcar-dmac.c b/kernel/drivers/dma/sh/rcar-dmac.c index 29c5176..7c268d1 100644 --- a/kernel/drivers/dma/sh/rcar-dmac.c +++ b/kernel/drivers/dma/sh/rcar-dmac.c @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Renesas R-Car Gen2 DMA Controller Driver + * Renesas R-Car Gen2/Gen3 DMA Controller Driver * - * Copyright (C) 2014 Renesas Electronics Inc. + * Copyright (C) 2014-2019 Renesas Electronics Inc. * * Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com> */ @@ -192,27 +192,36 @@ * @iomem: remapped I/O memory base * @n_channels: number of available channels * @channels: array of DMAC channels + * @channels_mask: bitfield of which DMA channels are managed by this driver * @modules: bitmask of client modules in use */ struct rcar_dmac { struct dma_device engine; struct device *dev; void __iomem *iomem; - struct device_dma_parameters parms; unsigned int n_channels; struct rcar_dmac_chan *channels; + u32 channels_mask; DECLARE_BITMAP(modules, 256); }; #define to_rcar_dmac(d) container_of(d, struct rcar_dmac, engine) +/* + * struct rcar_dmac_of_data - This driver's OF data + * @chan_offset_base: DMAC channels base offset + * @chan_offset_stride: DMAC channels offset stride + */ +struct rcar_dmac_of_data { + u32 chan_offset_base; + u32 chan_offset_stride; +}; + /* ----------------------------------------------------------------------------- * Registers */ - -#define RCAR_DMAC_CHAN_OFFSET(i) (0x8000 + 0x80 * (i)) #define RCAR_DMAISTA 0x0020 #define RCAR_DMASEC 0x0030 @@ -438,7 +447,7 @@ u16 dmaor; /* Clear all channels and enable the DMAC globally. */ - rcar_dmac_write(dmac, RCAR_DMACHCLR, GENMASK(dmac->n_channels - 1, 0)); + rcar_dmac_write(dmac, RCAR_DMACHCLR, dmac->channels_mask); rcar_dmac_write(dmac, RCAR_DMAOR, RCAR_DMAOR_PRI_FIXED | RCAR_DMAOR_DME); @@ -813,6 +822,9 @@ /* Stop all channels. */ for (i = 0; i < dmac->n_channels; ++i) { struct rcar_dmac_chan *chan = &dmac->channels[i]; + + if (!(dmac->channels_mask & BIT(i))) + continue; /* Stop and reinitialize the channel. */ spin_lock_irq(&chan->lock); @@ -1206,7 +1218,7 @@ sg_len = buf_len / period_len; if (sg_len > RCAR_DMAC_MAX_SG_LEN) { dev_err(chan->device->dev, - "chan%u: sg length %d exceds limit %d", + "chan%u: sg length %d exceeds limit %d", rchan->index, sg_len, RCAR_DMAC_MAX_SG_LEN); return NULL; } @@ -1215,7 +1227,7 @@ * Allocate the sg list dynamically as it would consume too much stack * space. */ - sgl = kcalloc(sg_len, sizeof(*sgl), GFP_NOWAIT); + sgl = kmalloc_array(sg_len, sizeof(*sgl), GFP_NOWAIT); if (!sgl) return NULL; @@ -1654,8 +1666,7 @@ * Forcing it to call dma_request_channel() and iterate through all * channels from all controllers is just pointless. */ - if (chan->device->device_config != rcar_dmac_device_config || - dma_spec->np != chan->device->dev->of_node) + if (chan->device->device_config != rcar_dmac_device_config) return false; return !test_and_set_bit(dma_spec->args[0], dmac->modules); @@ -1675,7 +1686,8 @@ dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); - chan = dma_request_channel(mask, rcar_dmac_chan_filter, dma_spec); + chan = __dma_request_channel(&mask, rcar_dmac_chan_filter, dma_spec, + ofdma->of_node); if (!chan) return NULL; @@ -1721,6 +1733,7 @@ static int rcar_dmac_chan_probe(struct rcar_dmac *dmac, struct rcar_dmac_chan *rchan, + const struct rcar_dmac_of_data *data, unsigned int index) { struct platform_device *pdev = to_platform_device(dmac->dev); @@ -1730,7 +1743,8 @@ int ret; rchan->index = index; - rchan->iomem = dmac->iomem + RCAR_DMAC_CHAN_OFFSET(index); + rchan->iomem = dmac->iomem + data->chan_offset_base + + data->chan_offset_stride * index; rchan->mid_rid = -EINVAL; spin_lock_init(&rchan->lock); @@ -1744,10 +1758,8 @@ /* Request the channel interrupt. */ sprintf(pdev_irqname, "ch%u", index); rchan->irq = platform_get_irq_byname(pdev, pdev_irqname); - if (rchan->irq < 0) { - dev_err(dmac->dev, "no IRQ specified for channel %u\n", index); + if (rchan->irq < 0) return -ENODEV; - } irqname = devm_kasprintf(dmac->dev, GFP_KERNEL, "%s:%u", dev_name(dmac->dev), index); @@ -1776,6 +1788,8 @@ return 0; } +#define RCAR_DMAC_MAX_CHANNELS 32 + static int rcar_dmac_parse_of(struct device *dev, struct rcar_dmac *dmac) { struct device_node *np = dev->of_node; @@ -1787,11 +1801,23 @@ return ret; } - if (dmac->n_channels <= 0 || dmac->n_channels >= 100) { + /* The hardware and driver don't support more than 32 bits in CHCLR */ + if (dmac->n_channels <= 0 || + dmac->n_channels >= RCAR_DMAC_MAX_CHANNELS) { dev_err(dev, "invalid number of channels %u\n", dmac->n_channels); return -EINVAL; } + + /* + * If the driver is unable to read dma-channel-mask property, + * the driver assumes that it can use all channels. + */ + dmac->channels_mask = GENMASK(dmac->n_channels - 1, 0); + of_property_read_u32(np, "dma-channel-mask", &dmac->channels_mask); + + /* If the property has out-of-channel mask, this driver clears it */ + dmac->channels_mask &= GENMASK(dmac->n_channels - 1, 0); return 0; } @@ -1802,12 +1828,15 @@ DMA_SLAVE_BUSWIDTH_2_BYTES | DMA_SLAVE_BUSWIDTH_4_BYTES | DMA_SLAVE_BUSWIDTH_8_BYTES | DMA_SLAVE_BUSWIDTH_16_BYTES | DMA_SLAVE_BUSWIDTH_32_BYTES | DMA_SLAVE_BUSWIDTH_64_BYTES; - unsigned int channels_offset = 0; struct dma_device *engine; struct rcar_dmac *dmac; - struct resource *mem; + const struct rcar_dmac_of_data *data; unsigned int i; int ret; + + data = of_device_get_match_data(&pdev->dev); + if (!data) + return -EINVAL; dmac = devm_kzalloc(&pdev->dev, sizeof(*dmac), GFP_KERNEL); if (!dmac) @@ -1815,8 +1844,10 @@ dmac->dev = &pdev->dev; platform_set_drvdata(pdev, dmac); - dmac->dev->dma_parms = &dmac->parms; - dma_set_max_seg_size(dmac->dev, RCAR_DMATCR_MASK); + ret = dma_set_max_seg_size(dmac->dev, RCAR_DMATCR_MASK); + if (ret) + return ret; + ret = dma_set_mask_and_coherent(dmac->dev, DMA_BIT_MASK(40)); if (ret) return ret; @@ -1833,10 +1864,8 @@ * level we can't disable it selectively, so ignore channel 0 for now if * the device is part of an IOMMU group. */ - if (pdev->dev.iommu_group) { - dmac->n_channels--; - channels_offset = 1; - } + if (device_iommu_mapped(&pdev->dev)) + dmac->channels_mask &= ~BIT(0); dmac->channels = devm_kcalloc(&pdev->dev, dmac->n_channels, sizeof(*dmac->channels), GFP_KERNEL); @@ -1844,14 +1873,13 @@ return -ENOMEM; /* Request resources. */ - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dmac->iomem = devm_ioremap_resource(&pdev->dev, mem); + dmac->iomem = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(dmac->iomem)) return PTR_ERR(dmac->iomem); /* Enable runtime PM and initialize the device. */ pm_runtime_enable(&pdev->dev); - ret = pm_runtime_get_sync(&pdev->dev); + ret = pm_runtime_resume_and_get(&pdev->dev); if (ret < 0) { dev_err(&pdev->dev, "runtime PM get sync failed (%d)\n", ret); return ret; @@ -1894,8 +1922,10 @@ INIT_LIST_HEAD(&engine->channels); for (i = 0; i < dmac->n_channels; ++i) { - ret = rcar_dmac_chan_probe(dmac, &dmac->channels[i], - i + channels_offset); + if (!(dmac->channels_mask & BIT(i))) + continue; + + ret = rcar_dmac_chan_probe(dmac, &dmac->channels[i], data, i); if (ret < 0) goto error; } @@ -1942,8 +1972,16 @@ rcar_dmac_stop_all_chan(dmac); } +static const struct rcar_dmac_of_data rcar_dmac_data = { + .chan_offset_base = 0x8000, + .chan_offset_stride = 0x80, +}; + static const struct of_device_id rcar_dmac_of_ids[] = { - { .compatible = "renesas,rcar-dmac", }, + { + .compatible = "renesas,rcar-dmac", + .data = &rcar_dmac_data, + }, { /* Sentinel */ } }; MODULE_DEVICE_TABLE(of, rcar_dmac_of_ids); -- Gitblit v1.6.2