MIPS: lantiq: dma: reset correct number of channel
authorAleksander Jan Bajkowski <olek2@wp.pl>
Tue, 14 Sep 2021 21:20:59 +0000 (23:20 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 18 Nov 2021 18:16:09 +0000 (19:16 +0100)
[ Upstream commit 5ca9ce2ba4d5884cd94d1a856c675ab1242cd242 ]

Different SoCs have a different number of channels, e.g .:
* amazon-se has 10 channels,
* danube+ar9 have 20 channels,
* vr9 has 28 channels,
* ar10 has 24 channels.

We can read the ID register and, depending on the reported
number of channels, reset the appropriate number of channels.

Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
arch/mips/lantiq/xway/dma.c

index 2784715..364ab39 100644 (file)
@@ -31,6 +31,7 @@
 #define LTQ_DMA_PCTRL          0x44
 #define LTQ_DMA_IRNEN          0xf4
 
+#define DMA_ID_CHNR            GENMASK(26, 20) /* channel number */
 #define DMA_DESCPT             BIT(3)          /* descriptor complete irq */
 #define DMA_TX                 BIT(8)          /* TX channel direction */
 #define DMA_CHAN_ON            BIT(0)          /* channel on / off bit */
@@ -41,7 +42,6 @@
 #define DMA_POLL               BIT(31)         /* turn on channel polling */
 #define DMA_CLK_DIV4           BIT(6)          /* polling clock divider */
 #define DMA_2W_BURST           BIT(1)          /* 2 word burst length */
-#define DMA_MAX_CHANNEL                20              /* the soc has 20 channels */
 #define DMA_ETOP_ENDIANNESS    (0xf << 8) /* endianness swap etop channels */
 #define DMA_WEIGHT     (BIT(17) | BIT(16))     /* default channel wheight */
 
@@ -207,7 +207,7 @@ ltq_dma_init(struct platform_device *pdev)
 {
        struct clk *clk;
        struct resource *res;
-       unsigned id;
+       unsigned int id, nchannels;
        int i;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -229,17 +229,18 @@ ltq_dma_init(struct platform_device *pdev)
        ltq_dma_w32(0, LTQ_DMA_IRNEN);
 
        /* reset/configure each channel */
-       for (i = 0; i < DMA_MAX_CHANNEL; i++) {
+       id = ltq_dma_r32(LTQ_DMA_ID);
+       nchannels = ((id & DMA_ID_CHNR) >> 20);
+       for (i = 0; i < nchannels; i++) {
                ltq_dma_w32(i, LTQ_DMA_CS);
                ltq_dma_w32(DMA_CHAN_RST, LTQ_DMA_CCTRL);
                ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL);
                ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
        }
 
-       id = ltq_dma_r32(LTQ_DMA_ID);
        dev_info(&pdev->dev,
                "Init done - hw rev: %X, ports: %d, channels: %d\n",
-               id & 0x1f, (id >> 16) & 0xf, id >> 20);
+               id & 0x1f, (id >> 16) & 0xf, nchannels);
 
        return 0;
 }