source: branches/backfire/target/linux/lantiq/patches-2.6.32/0010-MIPS-Lantiq-Add-DMA-support.patch @ 27546

Last change on this file since 27546 was 27546, checked in by blogic, 5 years ago

add new lantiq target

File size: 11.6 KB
  • arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h

    From bd620ec1ca053bab8ce2562968700e6f80e4ff83 Mon Sep 17 00:00:00 2001
    From: John Crispin <blogic@openwrt.org>
    Date: Fri, 6 May 2011 00:10:00 +0200
    Subject: [PATCH 10/13] MIPS: Lantiq: Add DMA support
    
    This patch adds support for the DMA engine found inside the XWAY family of
    SoCs. The engine has 5 ports and 20 channels.
    
    Signed-off-by: John Crispin <blogic@openwrt.org>
    Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>
    Cc: linux-mips@linux-mips.org
    Patchwork: https://patchwork.linux-mips.org/patch/2355/
    Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
    ---
     .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |    3 +-
     arch/mips/include/asm/mach-lantiq/xway/xway_dma.h  |   60 +++++
     arch/mips/lantiq/xway/Makefile                     |    2 +-
     arch/mips/lantiq/xway/devices.h                    |    1 +
     arch/mips/lantiq/xway/dma.c                        |  253 ++++++++++++++++++++
     5 files changed, 317 insertions(+), 2 deletions(-)
     create mode 100644 arch/mips/include/asm/mach-lantiq/xway/xway_dma.h
     create mode 100644 arch/mips/lantiq/xway/dma.c
    
    diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
    index 343e82c..4827afb 100644
    a b  
    8686#define LTQ_PPE32_SIZE          0x40000 
    8787 
    8888/* DMA */ 
    89 #define LTQ_DMA_BASE_ADDR       0xBE104100 
     89#define LTQ_DMA_BASE_ADDR       0x1E104100 
     90#define LTQ_DMA_SIZE            0x800 
    9091 
    9192/* PCI */ 
    9293#define PCI_CR_BASE_ADDR        0x1E105400 
  • new file arch/mips/include/asm/mach-lantiq/xway/xway_dma.h

    diff --git a/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h b/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h
    new file mode 100644
    index 0000000..872943a
    - +  
     1/* 
     2 *   This program is free software; you can redistribute it and/or modify it 
     3 *   under the terms of the GNU General Public License version 2 as published 
     4 *   by the Free Software Foundation. 
     5 * 
     6 *   This program is distributed in the hope that it will be useful, 
     7 *   but WITHOUT ANY WARRANTY; without even the implied warranty of 
     8 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     9 *   GNU General Public License for more details. 
     10 * 
     11 *   You should have received a copy of the GNU General Public License 
     12 *   along with this program; if not, write to the Free Software 
     13 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 
     14 * 
     15 *   Copyright (C) 2011 John Crispin <blogic@openwrt.org> 
     16 */ 
     17 
     18#ifndef LTQ_DMA_H__ 
     19#define LTQ_DMA_H__ 
     20 
     21#define LTQ_DESC_SIZE           0x08    /* each descriptor is 64bit */ 
     22#define LTQ_DESC_NUM            0x40    /* 64 descriptors / channel */ 
     23 
     24#define LTQ_DMA_OWN             BIT(31) /* owner bit */ 
     25#define LTQ_DMA_C               BIT(30) /* complete bit */ 
     26#define LTQ_DMA_SOP             BIT(29) /* start of packet */ 
     27#define LTQ_DMA_EOP             BIT(28) /* end of packet */ 
     28#define LTQ_DMA_TX_OFFSET(x)    ((x & 0x1f) << 23) /* data bytes offset */ 
     29#define LTQ_DMA_RX_OFFSET(x)    ((x & 0x7) << 23) /* data bytes offset */ 
     30#define LTQ_DMA_SIZE_MASK       (0xffff) /* the size field is 16 bit */ 
     31 
     32struct ltq_dma_desc { 
     33        u32 ctl; 
     34        u32 addr; 
     35}; 
     36 
     37struct ltq_dma_channel { 
     38        int nr;                         /* the channel number */ 
     39        int irq;                        /* the mapped irq */ 
     40        int desc;                       /* the current descriptor */ 
     41        struct ltq_dma_desc *desc_base; /* the descriptor base */ 
     42        int phys;                       /* physical addr */ 
     43}; 
     44 
     45enum { 
     46        DMA_PORT_ETOP = 0, 
     47        DMA_PORT_DEU, 
     48}; 
     49 
     50extern void ltq_dma_enable_irq(struct ltq_dma_channel *ch); 
     51extern void ltq_dma_disable_irq(struct ltq_dma_channel *ch); 
     52extern void ltq_dma_ack_irq(struct ltq_dma_channel *ch); 
     53extern void ltq_dma_open(struct ltq_dma_channel *ch); 
     54extern void ltq_dma_close(struct ltq_dma_channel *ch); 
     55extern void ltq_dma_alloc_tx(struct ltq_dma_channel *ch); 
     56extern void ltq_dma_alloc_rx(struct ltq_dma_channel *ch); 
     57extern void ltq_dma_free(struct ltq_dma_channel *ch); 
     58extern void ltq_dma_init_port(int p); 
     59 
     60#endif 
  • arch/mips/lantiq/xway/Makefile

    diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
    index 6b5e07e..c517f2e 100644
    a b  
    1 obj-y := pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o 
     1obj-y := pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o 
    22 
    33obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o setup-xway.o 
    44obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o setup-ase.o 
  • arch/mips/lantiq/xway/devices.h

    diff --git a/arch/mips/lantiq/xway/devices.h b/arch/mips/lantiq/xway/devices.h
    index 51f56b5..d573084 100644
    a b  
    1010#define _LTQ_DEVICES_XWAY_H__ 
    1111 
    1212#include "../devices.h" 
     13#include <linux/phy.h> 
    1314 
    1415extern void ltq_register_gpio(void); 
    1516extern void ltq_register_gpio_stp(void); 
  • new file arch/mips/lantiq/xway/dma.c

    diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c
    new file mode 100644
    index 0000000..4278a45
    - +  
     1/* 
     2 *   This program is free software; you can redistribute it and/or modify it 
     3 *   under the terms of the GNU General Public License version 2 as published 
     4 *   by the Free Software Foundation. 
     5 * 
     6 *   This program is distributed in the hope that it will be useful, 
     7 *   but WITHOUT ANY WARRANTY; without even the implied warranty of 
     8 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     9 *   GNU General Public License for more details. 
     10 * 
     11 *   You should have received a copy of the GNU General Public License 
     12 *   along with this program; if not, write to the Free Software 
     13 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 
     14 * 
     15 *   Copyright (C) 2011 John Crispin <blogic@openwrt.org> 
     16 */ 
     17 
     18#include <linux/init.h> 
     19#include <linux/platform_device.h> 
     20#include <linux/io.h> 
     21#include <linux/dma-mapping.h> 
     22 
     23#include <lantiq_soc.h> 
     24#include <xway_dma.h> 
     25 
     26#define LTQ_DMA_CTRL            0x10 
     27#define LTQ_DMA_CPOLL           0x14 
     28#define LTQ_DMA_CS              0x18 
     29#define LTQ_DMA_CCTRL           0x1C 
     30#define LTQ_DMA_CDBA            0x20 
     31#define LTQ_DMA_CDLEN           0x24 
     32#define LTQ_DMA_CIS             0x28 
     33#define LTQ_DMA_CIE             0x2C 
     34#define LTQ_DMA_PS              0x40 
     35#define LTQ_DMA_PCTRL           0x44 
     36#define LTQ_DMA_IRNEN           0xf4 
     37 
     38#define DMA_DESCPT              BIT(3)          /* descriptor complete irq */ 
     39#define DMA_TX                  BIT(8)          /* TX channel direction */ 
     40#define DMA_CHAN_ON             BIT(0)          /* channel on / off bit */ 
     41#define DMA_PDEN                BIT(6)          /* enable packet drop */ 
     42#define DMA_CHAN_RST            BIT(1)          /* channel on / off bit */ 
     43#define DMA_RESET               BIT(0)          /* channel on / off bit */ 
     44#define DMA_IRQ_ACK             0x7e            /* IRQ status register */ 
     45#define DMA_POLL                BIT(31)         /* turn on channel polling */ 
     46#define DMA_CLK_DIV4            BIT(6)          /* polling clock divider */ 
     47#define DMA_2W_BURST            BIT(1)          /* 2 word burst length */ 
     48#define DMA_MAX_CHANNEL         20              /* the soc has 20 channels */ 
     49#define DMA_ETOP_ENDIANESS      (0xf << 8) /* endianess swap etop channels */ 
     50#define DMA_WEIGHT      (BIT(17) | BIT(16))     /* default channel wheight */ 
     51 
     52#define ltq_dma_r32(x)                  ltq_r32(ltq_dma_membase + (x)) 
     53#define ltq_dma_w32(x, y)               ltq_w32(x, ltq_dma_membase + (y)) 
     54#define ltq_dma_w32_mask(x, y, z)       ltq_w32_mask(x, y, \ 
     55                                                ltq_dma_membase + (z)) 
     56 
     57static struct resource ltq_dma_resource = { 
     58        .name   = "dma", 
     59        .start  = LTQ_DMA_BASE_ADDR, 
     60        .end    = LTQ_DMA_BASE_ADDR + LTQ_DMA_SIZE - 1, 
     61        .flags  = IORESOURCE_MEM, 
     62}; 
     63 
     64static void __iomem *ltq_dma_membase; 
     65 
     66void 
     67ltq_dma_enable_irq(struct ltq_dma_channel *ch) 
     68{ 
     69        unsigned long flags; 
     70 
     71        local_irq_save(flags); 
     72        ltq_dma_w32(ch->nr, LTQ_DMA_CS); 
     73        ltq_dma_w32_mask(0, 1 << ch->nr, LTQ_DMA_IRNEN); 
     74        local_irq_restore(flags); 
     75} 
     76EXPORT_SYMBOL_GPL(ltq_dma_enable_irq); 
     77 
     78void 
     79ltq_dma_disable_irq(struct ltq_dma_channel *ch) 
     80{ 
     81        unsigned long flags; 
     82 
     83        local_irq_save(flags); 
     84        ltq_dma_w32(ch->nr, LTQ_DMA_CS); 
     85        ltq_dma_w32_mask(1 << ch->nr, 0, LTQ_DMA_IRNEN); 
     86        local_irq_restore(flags); 
     87} 
     88EXPORT_SYMBOL_GPL(ltq_dma_disable_irq); 
     89 
     90void 
     91ltq_dma_ack_irq(struct ltq_dma_channel *ch) 
     92{ 
     93        unsigned long flags; 
     94 
     95        local_irq_save(flags); 
     96        ltq_dma_w32(ch->nr, LTQ_DMA_CS); 
     97        ltq_dma_w32(DMA_IRQ_ACK, LTQ_DMA_CIS); 
     98        local_irq_restore(flags); 
     99} 
     100EXPORT_SYMBOL_GPL(ltq_dma_ack_irq); 
     101 
     102void 
     103ltq_dma_open(struct ltq_dma_channel *ch) 
     104{ 
     105        unsigned long flag; 
     106 
     107        local_irq_save(flag); 
     108        ltq_dma_w32(ch->nr, LTQ_DMA_CS); 
     109        ltq_dma_w32_mask(0, DMA_CHAN_ON, LTQ_DMA_CCTRL); 
     110        ltq_dma_enable_irq(ch); 
     111        local_irq_restore(flag); 
     112} 
     113EXPORT_SYMBOL_GPL(ltq_dma_open); 
     114 
     115void 
     116ltq_dma_close(struct ltq_dma_channel *ch) 
     117{ 
     118        unsigned long flag; 
     119 
     120        local_irq_save(flag); 
     121        ltq_dma_w32(ch->nr, LTQ_DMA_CS); 
     122        ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL); 
     123        ltq_dma_disable_irq(ch); 
     124        local_irq_restore(flag); 
     125} 
     126EXPORT_SYMBOL_GPL(ltq_dma_close); 
     127 
     128static void 
     129ltq_dma_alloc(struct ltq_dma_channel *ch) 
     130{ 
     131        unsigned long flags; 
     132 
     133        ch->desc = 0; 
     134        ch->desc_base = dma_alloc_coherent(NULL, 
     135                                LTQ_DESC_NUM * LTQ_DESC_SIZE, 
     136                                &ch->phys, GFP_ATOMIC); 
     137        memset(ch->desc_base, 0, LTQ_DESC_NUM * LTQ_DESC_SIZE); 
     138 
     139        local_irq_save(flags); 
     140        ltq_dma_w32(ch->nr, LTQ_DMA_CS); 
     141        ltq_dma_w32(ch->phys, LTQ_DMA_CDBA); 
     142        ltq_dma_w32(LTQ_DESC_NUM, LTQ_DMA_CDLEN); 
     143        ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL); 
     144        wmb(); 
     145        ltq_dma_w32_mask(0, DMA_CHAN_RST, LTQ_DMA_CCTRL); 
     146        while (ltq_dma_r32(LTQ_DMA_CCTRL) & DMA_CHAN_RST) 
     147                ; 
     148        local_irq_restore(flags); 
     149} 
     150 
     151void 
     152ltq_dma_alloc_tx(struct ltq_dma_channel *ch) 
     153{ 
     154        unsigned long flags; 
     155 
     156        ltq_dma_alloc(ch); 
     157 
     158        local_irq_save(flags); 
     159        ltq_dma_w32(DMA_DESCPT, LTQ_DMA_CIE); 
     160        ltq_dma_w32_mask(0, 1 << ch->nr, LTQ_DMA_IRNEN); 
     161        ltq_dma_w32(DMA_WEIGHT | DMA_TX, LTQ_DMA_CCTRL); 
     162        local_irq_restore(flags); 
     163} 
     164EXPORT_SYMBOL_GPL(ltq_dma_alloc_tx); 
     165 
     166void 
     167ltq_dma_alloc_rx(struct ltq_dma_channel *ch) 
     168{ 
     169        unsigned long flags; 
     170 
     171        ltq_dma_alloc(ch); 
     172 
     173        local_irq_save(flags); 
     174        ltq_dma_w32(DMA_DESCPT, LTQ_DMA_CIE); 
     175        ltq_dma_w32_mask(0, 1 << ch->nr, LTQ_DMA_IRNEN); 
     176        ltq_dma_w32(DMA_WEIGHT, LTQ_DMA_CCTRL); 
     177        local_irq_restore(flags); 
     178} 
     179EXPORT_SYMBOL_GPL(ltq_dma_alloc_rx); 
     180 
     181void 
     182ltq_dma_free(struct ltq_dma_channel *ch) 
     183{ 
     184        if (!ch->desc_base) 
     185                return; 
     186        ltq_dma_close(ch); 
     187        dma_free_coherent(NULL, LTQ_DESC_NUM * LTQ_DESC_SIZE, 
     188                ch->desc_base, ch->phys); 
     189} 
     190EXPORT_SYMBOL_GPL(ltq_dma_free); 
     191 
     192void 
     193ltq_dma_init_port(int p) 
     194{ 
     195        ltq_dma_w32(p, LTQ_DMA_PS); 
     196        switch (p) { 
     197        case DMA_PORT_ETOP: 
     198                /* 
     199                 * Tell the DMA engine to swap the endianess of data frames and 
     200                 * drop packets if the channel arbitration fails. 
     201                 */ 
     202                ltq_dma_w32_mask(0, DMA_ETOP_ENDIANESS | DMA_PDEN, 
     203                        LTQ_DMA_PCTRL); 
     204                break; 
     205 
     206        case DMA_PORT_DEU: 
     207                ltq_dma_w32((DMA_2W_BURST << 4) | (DMA_2W_BURST << 2), 
     208                        LTQ_DMA_PCTRL); 
     209                break; 
     210 
     211        default: 
     212                break; 
     213        } 
     214} 
     215EXPORT_SYMBOL_GPL(ltq_dma_init_port); 
     216 
     217int __init 
     218ltq_dma_init(void) 
     219{ 
     220        int i; 
     221 
     222        /* insert and request the memory region */ 
     223        if (insert_resource(&iomem_resource, &ltq_dma_resource) < 0) 
     224                panic("Failed to insert dma memory\n"); 
     225 
     226        if (request_mem_region(ltq_dma_resource.start, 
     227                        resource_size(&ltq_dma_resource), "dma") < 0) 
     228                panic("Failed to request dma memory\n"); 
     229 
     230        /* remap dma register range */ 
     231        ltq_dma_membase = ioremap_nocache(ltq_dma_resource.start, 
     232                                resource_size(&ltq_dma_resource)); 
     233        if (!ltq_dma_membase) 
     234                panic("Failed to remap dma memory\n"); 
     235 
     236        /* power up and reset the dma engine */ 
     237        ltq_pmu_enable(PMU_DMA); 
     238        ltq_dma_w32_mask(0, DMA_RESET, LTQ_DMA_CTRL); 
     239 
     240        /* disable all interrupts */ 
     241        ltq_dma_w32(0, LTQ_DMA_IRNEN); 
     242 
     243        /* reset/configure each channel */ 
     244        for (i = 0; i < DMA_MAX_CHANNEL; i++) { 
     245                ltq_dma_w32(i, LTQ_DMA_CS); 
     246                ltq_dma_w32(DMA_CHAN_RST, LTQ_DMA_CCTRL); 
     247                ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL); 
     248                ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL); 
     249        } 
     250        return 0; 
     251} 
     252 
     253postcore_initcall(ltq_dma_init); 
Note: See TracBrowser for help on using the repository browser.