ARM/dmaengine: pl08x: pass reasonable memcpy settings
authorLinus Walleij <linus.walleij@linaro.org>
Sat, 20 May 2017 21:42:50 +0000 (23:42 +0200)
committerVinod Koul <vinod.koul@intel.com>
Wed, 24 May 2017 04:14:32 +0000 (09:44 +0530)
We cannot use bits from configuration registers as API between
platforms and driver like this, abstract it out to two enums
and mimic the stuff passed as device tree data.

This is done to make it possible for the driver to generate the
ccfg word on-the-fly so we can support more PL08x derivatives.

Acked-by: Olof Johansson <olof@lixom.net>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
arch/arm/mach-lpc32xx/phy3250.c
arch/arm/mach-s3c64xx/pl080.c
arch/arm/mach-spear/spear3xx.c
arch/arm/mach-spear/spear6xx.c
drivers/dma/amba-pl08x.c
include/linux/amba/pl08x.h

index 6c52bd32610e1096f1638d1c79cac07f9a0b3d8b..e48cc06c2aec04855d91c500e1bfce0aa3a4a6d9 100644 (file)
@@ -137,6 +137,9 @@ static void pl08x_put_signal(const struct pl08x_channel_data *cd, int ch)
 }
 
 static struct pl08x_platform_data pl08x_pd = {
+       /* Some reasonable memcpy defaults */
+       .memcpy_burst_size = PL08X_BURST_SZ_256,
+       .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS,
        .slave_channels = &pl08x_slave_channels[0],
        .num_slave_channels = ARRAY_SIZE(pl08x_slave_channels),
        .get_xfer_signal = pl08x_get_signal,
index 261820a855ecfb7a7472d15b75a4c547fa36b169..66fc774b70ec238548c0f3a99fd749baf4062787 100644 (file)
@@ -137,16 +137,10 @@ static const struct dma_slave_map s3c64xx_dma0_slave_map[] = {
 };
 
 struct pl08x_platform_data s3c64xx_dma0_plat_data = {
-       .memcpy_channel = {
-               .bus_id = "memcpy",
-               .cctl_memcpy =
-                       (PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
-                       PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
-                       PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
-                       PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
-                       PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
-                       PL080_CONTROL_PROT_SYS),
-       },
+       .memcpy_burst_size = PL08X_BURST_SZ_4,
+       .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS,
+       .memcpy_prot_buff = true,
+       .memcpy_prot_cache = true,
        .lli_buses = PL08X_AHB1,
        .mem_buses = PL08X_AHB1,
        .get_xfer_signal = pl08x_get_xfer_signal,
@@ -238,16 +232,10 @@ static const struct dma_slave_map s3c64xx_dma1_slave_map[] = {
 };
 
 struct pl08x_platform_data s3c64xx_dma1_plat_data = {
-       .memcpy_channel = {
-               .bus_id = "memcpy",
-               .cctl_memcpy =
-                       (PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
-                       PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
-                       PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
-                       PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
-                       PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
-                       PL080_CONTROL_PROT_SYS),
-       },
+       .memcpy_burst_size = PL08X_BURST_SZ_4,
+       .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS,
+       .memcpy_prot_buff = true,
+       .memcpy_prot_cache = true,
        .lli_buses = PL08X_AHB1,
        .mem_buses = PL08X_AHB1,
        .get_xfer_signal = pl08x_get_xfer_signal,
index 23394ac76cf22886e40cb5ec1e098586a43a774d..8537fcffe5a86e765df492bcd24275f8369987bd 100644 (file)
@@ -44,16 +44,10 @@ struct pl022_ssp_controller pl022_plat_data = {
 
 /* dmac device registration */
 struct pl08x_platform_data pl080_plat_data = {
-       .memcpy_channel = {
-               .bus_id = "memcpy",
-               .cctl_memcpy =
-                       (PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT | \
-                       PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT | \
-                       PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | \
-                       PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT | \
-                       PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE | \
-                       PL080_CONTROL_PROT_SYS),
-       },
+       .memcpy_burst_size = PL08X_BURST_SZ_16,
+       .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS,
+       .memcpy_prot_buff = true,
+       .memcpy_prot_cache = true,
        .lli_buses = PL08X_AHB1,
        .mem_buses = PL08X_AHB1,
        .get_xfer_signal = pl080_get_signal,
index ccf3573b831c47be90a207f8190aeb2bd85363d7..c5fc110134ba66950664f7e17d0940a947047adc 100644 (file)
@@ -322,16 +322,10 @@ static struct pl08x_channel_data spear600_dma_info[] = {
 };
 
 static struct pl08x_platform_data spear6xx_pl080_plat_data = {
-       .memcpy_channel = {
-               .bus_id = "memcpy",
-               .cctl_memcpy =
-                       (PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT | \
-                       PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT | \
-                       PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | \
-                       PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT | \
-                       PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE | \
-                       PL080_CONTROL_PROT_SYS),
-       },
+       .memcpy_burst_size = PL08X_BURST_SZ_16,
+       .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS,
+       .memcpy_prot_buff = true,
+       .memcpy_prot_cache = true,
        .lli_buses = PL08X_AHB1,
        .mem_buses = PL08X_AHB1,
        .get_xfer_signal = pl080_get_signal,
index 6bb8813ca2753838d36b188aed1e20e0afb44d58..d3d660a36ad76f6c44c9522a6ab227e7efa6dc5c 100644 (file)
@@ -1433,6 +1433,7 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_memcpy(
        struct pl08x_driver_data *pl08x = plchan->host;
        struct pl08x_txd *txd;
        struct pl08x_sg *dsg;
+       u32 cctl = 0;
        int ret;
 
        txd = pl08x_get_txd(plchan);
@@ -1455,15 +1456,83 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_memcpy(
 
        /* Set platform data for m2m */
        txd->ccfg |= PL080_FLOW_MEM2MEM << PL080_CONFIG_FLOW_CONTROL_SHIFT;
-       txd->cctl = pl08x->pd->memcpy_channel.cctl_memcpy &
-                       ~(PL080_CONTROL_DST_AHB2 | PL080_CONTROL_SRC_AHB2);
+
+       /* Conjure cctl */
+       switch (pl08x->pd->memcpy_burst_size) {
+       default:
+               dev_err(&pl08x->adev->dev,
+                       "illegal burst size for memcpy, set to 1\n");
+               /* Fall through */
+       case PL08X_BURST_SZ_1:
+               cctl |= PL080_BSIZE_1 << PL080_CONTROL_SB_SIZE_SHIFT |
+                       PL080_BSIZE_1 << PL080_CONTROL_DB_SIZE_SHIFT;
+               break;
+       case PL08X_BURST_SZ_4:
+               cctl |= PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
+                       PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT;
+               break;
+       case PL08X_BURST_SZ_8:
+               cctl |= PL080_BSIZE_8 << PL080_CONTROL_SB_SIZE_SHIFT |
+                       PL080_BSIZE_8 << PL080_CONTROL_DB_SIZE_SHIFT;
+               break;
+       case PL08X_BURST_SZ_16:
+               cctl |= PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT |
+                       PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT;
+               break;
+       case PL08X_BURST_SZ_32:
+               cctl |= PL080_BSIZE_32 << PL080_CONTROL_SB_SIZE_SHIFT |
+                       PL080_BSIZE_32 << PL080_CONTROL_DB_SIZE_SHIFT;
+               break;
+       case PL08X_BURST_SZ_64:
+               cctl |= PL080_BSIZE_64 << PL080_CONTROL_SB_SIZE_SHIFT |
+                       PL080_BSIZE_64 << PL080_CONTROL_DB_SIZE_SHIFT;
+               break;
+       case PL08X_BURST_SZ_128:
+               cctl |= PL080_BSIZE_128 << PL080_CONTROL_SB_SIZE_SHIFT |
+                       PL080_BSIZE_128 << PL080_CONTROL_DB_SIZE_SHIFT;
+               break;
+       case PL08X_BURST_SZ_256:
+               cctl |= PL080_BSIZE_256 << PL080_CONTROL_SB_SIZE_SHIFT |
+                       PL080_BSIZE_256 << PL080_CONTROL_DB_SIZE_SHIFT;
+               break;
+       }
+
+       switch (pl08x->pd->memcpy_bus_width) {
+       default:
+               dev_err(&pl08x->adev->dev,
+                       "illegal bus width for memcpy, set to 8 bits\n");
+               /* Fall through */
+       case PL08X_BUS_WIDTH_8_BITS:
+               cctl |= PL080_WIDTH_8BIT << PL080_CONTROL_SWIDTH_SHIFT |
+                       PL080_WIDTH_8BIT << PL080_CONTROL_DWIDTH_SHIFT;
+               break;
+       case PL08X_BUS_WIDTH_16_BITS:
+               cctl |= PL080_WIDTH_16BIT << PL080_CONTROL_SWIDTH_SHIFT |
+                       PL080_WIDTH_16BIT << PL080_CONTROL_DWIDTH_SHIFT;
+               break;
+       case PL08X_BUS_WIDTH_32_BITS:
+               cctl |= PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
+                       PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT;
+               break;
+       }
+
+       /* Protection flags */
+       if (pl08x->pd->memcpy_prot_buff)
+               cctl |= PL080_CONTROL_PROT_BUFF;
+       if (pl08x->pd->memcpy_prot_cache)
+               cctl |= PL080_CONTROL_PROT_CACHE;
+
+       /* We are the kernel, so we are in privileged mode */
+       cctl |= PL080_CONTROL_PROT_SYS;
 
        /* Both to be incremented or the code will break */
-       txd->cctl |= PL080_CONTROL_SRC_INCR | PL080_CONTROL_DST_INCR;
+       cctl |= PL080_CONTROL_SRC_INCR | PL080_CONTROL_DST_INCR;
 
        if (pl08x->vd->dualmaster)
-               txd->cctl |= pl08x_select_bus(pl08x->mem_buses,
-                                             pl08x->mem_buses);
+               cctl |= pl08x_select_bus(pl08x->mem_buses,
+                                        pl08x->mem_buses);
+
+       txd->cctl = cctl;
 
        ret = pl08x_fill_llis_for_desc(plchan->host, txd);
        if (!ret) {
@@ -1925,9 +1994,16 @@ static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
                        chan->signal = i;
                        pl08x_dma_slave_init(chan);
                } else {
-                       chan->cd = &pl08x->pd->memcpy_channel;
+                       chan->cd = kzalloc(sizeof(*chan->cd), GFP_KERNEL);
+                       if (!chan->cd) {
+                               kfree(chan);
+                               return -ENOMEM;
+                       }
+                       chan->cd->bus_id = "memcpy";
+                       chan->cd->periph_buses = pl08x->pd->mem_buses;
                        chan->name = kasprintf(GFP_KERNEL, "memcpy%d", i);
                        if (!chan->name) {
+                               kfree(chan->cd);
                                kfree(chan);
                                return -ENOMEM;
                        }
@@ -2099,7 +2175,6 @@ static int pl08x_of_probe(struct amba_device *adev,
 {
        struct pl08x_platform_data *pd;
        struct pl08x_channel_data *chanp = NULL;
-       u32 cctl_memcpy = 0;
        u32 val;
        int ret;
        int i;
@@ -2139,36 +2214,28 @@ static int pl08x_of_probe(struct amba_device *adev,
                dev_err(&adev->dev, "illegal burst size for memcpy, set to 1\n");
                /* Fall through */
        case 1:
-               cctl_memcpy |= PL080_BSIZE_1 << PL080_CONTROL_SB_SIZE_SHIFT |
-                              PL080_BSIZE_1 << PL080_CONTROL_DB_SIZE_SHIFT;
+               pd->memcpy_burst_size = PL08X_BURST_SZ_1;
                break;
        case 4:
-               cctl_memcpy |= PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
-                              PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT;
+               pd->memcpy_burst_size = PL08X_BURST_SZ_4;
                break;
        case 8:
-               cctl_memcpy |= PL080_BSIZE_8 << PL080_CONTROL_SB_SIZE_SHIFT |
-                              PL080_BSIZE_8 << PL080_CONTROL_DB_SIZE_SHIFT;
+               pd->memcpy_burst_size = PL08X_BURST_SZ_8;
                break;
        case 16:
-               cctl_memcpy |= PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT |
-                              PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT;
+               pd->memcpy_burst_size = PL08X_BURST_SZ_16;
                break;
        case 32:
-               cctl_memcpy |= PL080_BSIZE_32 << PL080_CONTROL_SB_SIZE_SHIFT |
-                              PL080_BSIZE_32 << PL080_CONTROL_DB_SIZE_SHIFT;
+               pd->memcpy_burst_size = PL08X_BURST_SZ_32;
                break;
        case 64:
-               cctl_memcpy |= PL080_BSIZE_64 << PL080_CONTROL_SB_SIZE_SHIFT |
-                              PL080_BSIZE_64 << PL080_CONTROL_DB_SIZE_SHIFT;
+               pd->memcpy_burst_size = PL08X_BURST_SZ_64;
                break;
        case 128:
-               cctl_memcpy |= PL080_BSIZE_128 << PL080_CONTROL_SB_SIZE_SHIFT |
-                              PL080_BSIZE_128 << PL080_CONTROL_DB_SIZE_SHIFT;
+               pd->memcpy_burst_size = PL08X_BURST_SZ_128;
                break;
        case 256:
-               cctl_memcpy |= PL080_BSIZE_256 << PL080_CONTROL_SB_SIZE_SHIFT |
-                              PL080_BSIZE_256 << PL080_CONTROL_DB_SIZE_SHIFT;
+               pd->memcpy_burst_size = PL08X_BURST_SZ_256;
                break;
        }
 
@@ -2182,28 +2249,16 @@ static int pl08x_of_probe(struct amba_device *adev,
                dev_err(&adev->dev, "illegal bus width for memcpy, set to 8 bits\n");
                /* Fall through */
        case 8:
-               cctl_memcpy |= PL080_WIDTH_8BIT << PL080_CONTROL_SWIDTH_SHIFT |
-                              PL080_WIDTH_8BIT << PL080_CONTROL_DWIDTH_SHIFT;
+               pd->memcpy_bus_width = PL08X_BUS_WIDTH_8_BITS;
                break;
        case 16:
-               cctl_memcpy |= PL080_WIDTH_16BIT << PL080_CONTROL_SWIDTH_SHIFT |
-                              PL080_WIDTH_16BIT << PL080_CONTROL_DWIDTH_SHIFT;
+               pd->memcpy_bus_width = PL08X_BUS_WIDTH_16_BITS;
                break;
        case 32:
-               cctl_memcpy |= PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
-                              PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT;
+               pd->memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS;
                break;
        }
 
-       /* This is currently the only thing making sense */
-       cctl_memcpy |= PL080_CONTROL_PROT_SYS;
-
-       /* Set up memcpy channel */
-       pd->memcpy_channel.bus_id = "memcpy";
-       pd->memcpy_channel.cctl_memcpy = cctl_memcpy;
-       /* Use the buses that can access memory, obviously */
-       pd->memcpy_channel.periph_buses = pd->mem_buses;
-
        /*
         * Allocate channel data for all possible slave channels (one
         * for each possible signal), channels will then be allocated
index 5308eae9ce35712b369415cc61ba91b884f7f70d..79d1bcee738d2cac6f9961c2bc1b9cf5bb33b0d6 100644 (file)
@@ -47,8 +47,6 @@ enum {
  * devices with static assignments
  * @muxval: a number usually used to poke into some mux regiser to
  * mux in the signal to this channel
- * @cctl_memcpy: options for the channel control register for memcpy
- *  *** not used for slave channels ***
  * @addr: source/target address in physical memory for this DMA channel,
  * can be the address of a FIFO register for burst requests for example.
  * This can be left undefined if the PrimeCell API is used for configuring
@@ -63,12 +61,28 @@ struct pl08x_channel_data {
        int min_signal;
        int max_signal;
        u32 muxval;
-       u32 cctl_memcpy;
        dma_addr_t addr;
        bool single;
        u8 periph_buses;
 };
 
+enum pl08x_burst_size {
+       PL08X_BURST_SZ_1,
+       PL08X_BURST_SZ_4,
+       PL08X_BURST_SZ_8,
+       PL08X_BURST_SZ_16,
+       PL08X_BURST_SZ_32,
+       PL08X_BURST_SZ_64,
+       PL08X_BURST_SZ_128,
+       PL08X_BURST_SZ_256,
+};
+
+enum pl08x_bus_width {
+       PL08X_BUS_WIDTH_8_BITS,
+       PL08X_BUS_WIDTH_16_BITS,
+       PL08X_BUS_WIDTH_32_BITS,
+};
+
 /**
  * struct pl08x_platform_data - the platform configuration for the PL08x
  * PrimeCells.
@@ -76,6 +90,11 @@ struct pl08x_channel_data {
  * platform, all inclusive, including multiplexed channels. The available
  * physical channels will be multiplexed around these signals as they are
  * requested, just enumerate all possible channels.
+ * @num_slave_channels: number of elements in the slave channel array
+ * @memcpy_burst_size: the appropriate burst size for memcpy operations
+ * @memcpy_bus_width: memory bus width
+ * @memcpy_prot_buff: whether memcpy DMA is bufferable
+ * @memcpy_prot_cache: whether memcpy DMA is cacheable
  * @get_xfer_signal: request a physical signal to be used for a DMA transfer
  * immediately: if there is some multiplexing or similar blocking the use
  * of the channel the transfer can be denied by returning less than zero,
@@ -90,7 +109,10 @@ struct pl08x_channel_data {
 struct pl08x_platform_data {
        struct pl08x_channel_data *slave_channels;
        unsigned int num_slave_channels;
-       struct pl08x_channel_data memcpy_channel;
+       enum pl08x_burst_size memcpy_burst_size;
+       enum pl08x_bus_width memcpy_bus_width;
+       bool memcpy_prot_buff;
+       bool memcpy_prot_cache;
        int (*get_xfer_signal)(const struct pl08x_channel_data *);
        void (*put_xfer_signal)(const struct pl08x_channel_data *, int);
        u8 lli_buses;