Loading arch/mips/Kconfig +18 −0 Original line number Original line Diff line number Diff line Loading @@ -642,6 +642,10 @@ config SGI_IP32 help help If you want this kernel to run on SGI O2 workstation, say Y here. If you want this kernel to run on SGI O2 workstation, say Y here. config SOC_AU1200 bool select SOC_AU1X00 config SOC_AU1X00 config SOC_AU1X00 bool "Support for AMD/Alchemy Au1X00 SOCs" bool "Support for AMD/Alchemy Au1X00 SOCs" select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_32BIT_KERNEL Loading Loading @@ -702,6 +706,13 @@ config MIPS_PB1550 select HW_HAS_PCI select HW_HAS_PCI select MIPS_DISABLE_OBSOLETE_IDE select MIPS_DISABLE_OBSOLETE_IDE config MIPS_PB1200 bool "AMD Alchemy PB1200 board" select SOC_AU1200 select DMA_NONCOHERENT select MIPS_DISABLE_OBSOLETE_IDE select SYS_SUPPORTS_LITTLE_ENDIAN config MIPS_DB1000 config MIPS_DB1000 bool "DB1000 board" bool "DB1000 board" depends on SOC_AU1000 depends on SOC_AU1000 Loading Loading @@ -732,6 +743,13 @@ config MIPS_BOSPORUS depends on SOC_AU1500 depends on SOC_AU1500 select DMA_NONCOHERENT select DMA_NONCOHERENT config MIPS_DB1200 bool "AMD Alchemy DB1200 board" select SOC_AU1200 select DMA_NONCOHERENT select MIPS_DISABLE_OBSOLETE_IDE select SYS_SUPPORTS_LITTLE_ENDIAN config MIPS_MIRAGE config MIPS_MIRAGE bool "Mirage board" bool "Mirage board" depends on SOC_AU1500 depends on SOC_AU1500 Loading arch/mips/Makefile +14 −0 Original line number Original line Diff line number Diff line Loading @@ -265,6 +265,13 @@ libs-$(CONFIG_MIPS_PB1550) += arch/mips/au1000/pb1550/ cflags-$(CONFIG_MIPS_PB1550) += -Iinclude/asm-mips/mach-pb1x00 cflags-$(CONFIG_MIPS_PB1550) += -Iinclude/asm-mips/mach-pb1x00 load-$(CONFIG_MIPS_PB1550) += 0xffffffff80100000 load-$(CONFIG_MIPS_PB1550) += 0xffffffff80100000 # # AMD Alchemy Pb1200 eval board # libs-$(CONFIG_MIPS_PB1200) += arch/mips/au1000/pb1200/ cflags-$(CONFIG_MIPS_PB1200) += -Iinclude/asm-mips/mach-pb1x00 load-$(CONFIG_MIPS_PB1200) += 0xffffffff80100000 # # # AMD Alchemy Db1000 eval board # AMD Alchemy Db1000 eval board # # Loading Loading @@ -293,6 +300,13 @@ libs-$(CONFIG_MIPS_DB1550) += arch/mips/au1000/db1x00/ cflags-$(CONFIG_MIPS_DB1550) += -Iinclude/asm-mips/mach-db1x00 cflags-$(CONFIG_MIPS_DB1550) += -Iinclude/asm-mips/mach-db1x00 load-$(CONFIG_MIPS_DB1550) += 0xffffffff80100000 load-$(CONFIG_MIPS_DB1550) += 0xffffffff80100000 # # AMD Alchemy Db1200 eval board # libs-$(CONFIG_MIPS_DB1200) += arch/mips/au1000/pb1200/ cflags-$(CONFIG_MIPS_DB1200) += -Iinclude/asm-mips/mach-db1x00 load-$(CONFIG_MIPS_DB1200) += 0xffffffff80100000 # # # AMD Alchemy Bosporus eval board # AMD Alchemy Bosporus eval board # # Loading arch/mips/au1000/common/au1xxx_irqmap.c +16 −16 Original line number Original line Diff line number Diff line Loading @@ -173,14 +173,14 @@ au1xxx_irq_map_t au1xxx_ic0_map[] = { { AU1550_PSC1_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1550_PSC1_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1550_PSC2_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1550_PSC2_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1550_PSC3_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1550_PSC3_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1550_TOY_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, { AU1550_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, { AU1550_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, { AU1550_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, { AU1550_RTC_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, { AU1550_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, { AU1550_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, { AU1550_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, { AU1550_NAND_INT, INTC_INT_RISE_EDGE, 0}, { AU1550_NAND_INT, INTC_INT_RISE_EDGE, 0}, { AU1550_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 }, { AU1550_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 }, { AU1550_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, { AU1550_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, Loading @@ -201,14 +201,14 @@ au1xxx_irq_map_t au1xxx_ic0_map[] = { { AU1200_PSC1_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1200_PSC1_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1200_AES_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1200_AES_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1200_CAMERA_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1200_CAMERA_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1200_TOY_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, { AU1200_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, { AU1200_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, { AU1200_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, { AU1200_RTC_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, { AU1200_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, { AU1200_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, { AU1200_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, { AU1200_NAND_INT, INTC_INT_RISE_EDGE, 0}, { AU1200_NAND_INT, INTC_INT_RISE_EDGE, 0}, { AU1200_USB_INT, INTC_INT_HIGH_LEVEL, 0 }, { AU1200_USB_INT, INTC_INT_HIGH_LEVEL, 0 }, { AU1200_LCD_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1200_LCD_INT, INTC_INT_HIGH_LEVEL, 0}, Loading arch/mips/au1000/common/cputable.c +2 −1 Original line number Original line Diff line number Diff line Loading @@ -37,7 +37,8 @@ struct cpu_spec cpu_specs[] = { { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1 }, { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1 }, { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1 }, { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1 }, { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1 }, { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1 }, { 0xffffffff, 0x04030200, "Au1200 AA", 0, 1 }, { 0xffffffff, 0x04030200, "Au1200 AB", 0, 0 }, { 0xffffffff, 0x04030201, "Au1200 AC", 0, 1 }, { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0 }, { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0 }, }; }; Loading arch/mips/au1000/common/dbdma.c +219 −79 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. * 675 Mass Ave, Cambridge, MA 02139, USA. * * */ */ #include <linux/config.h> #include <linux/config.h> #include <linux/kernel.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/errno.h> Loading @@ -42,6 +43,8 @@ #include <asm/mach-au1x00/au1xxx_dbdma.h> #include <asm/mach-au1x00/au1xxx_dbdma.h> #include <asm/system.h> #include <asm/system.h> /* #include <linux/module.h> */ #if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) #if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) /* /* Loading @@ -55,43 +58,16 @@ * functions. The drivers allocate the data buffers and assign them * functions. The drivers allocate the data buffers and assign them * to the descriptors. * to the descriptors. */ */ static DEFINE_SPINLOCK(au1xxx_dbdma_spin_lock); static spinlock_t au1xxx_dbdma_spin_lock = SPIN_LOCK_UNLOCKED; /* I couldn't find a macro that did this...... /* I couldn't find a macro that did this...... */ */ #define ALIGN_ADDR(x, a) ((((u32)(x)) + (a-1)) & ~(a-1)) #define ALIGN_ADDR(x, a) ((((u32)(x)) + (a-1)) & ~(a-1)) static volatile dbdma_global_t *dbdma_gptr = (dbdma_global_t *)DDMA_GLOBAL_BASE; static dbdma_global_t *dbdma_gptr = (dbdma_global_t *)DDMA_GLOBAL_BASE; static int dbdma_initialized; static int dbdma_initialized=0; static void au1xxx_dbdma_init(void); static void au1xxx_dbdma_init(void); typedef struct dbdma_device_table { u32 dev_id; u32 dev_flags; u32 dev_tsize; u32 dev_devwidth; u32 dev_physaddr; /* If FIFO */ u32 dev_intlevel; u32 dev_intpolarity; } dbdev_tab_t; typedef struct dbdma_chan_config { u32 chan_flags; u32 chan_index; dbdev_tab_t *chan_src; dbdev_tab_t *chan_dest; au1x_dma_chan_t *chan_ptr; au1x_ddma_desc_t *chan_desc_base; au1x_ddma_desc_t *get_ptr, *put_ptr, *cur_ptr; void *chan_callparam; void (*chan_callback)(int, void *, struct pt_regs *); } chan_tab_t; #define DEV_FLAGS_INUSE (1 << 0) #define DEV_FLAGS_ANYUSE (1 << 1) #define DEV_FLAGS_OUT (1 << 2) #define DEV_FLAGS_IN (1 << 3) static dbdev_tab_t dbdev_tab[] = { static dbdev_tab_t dbdev_tab[] = { #ifdef CONFIG_SOC_AU1550 #ifdef CONFIG_SOC_AU1550 /* UARTS */ /* UARTS */ Loading Loading @@ -157,13 +133,13 @@ static dbdev_tab_t dbdev_tab[] = { { DSCR_CMD0_MAE_BOTH, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_MAE_BOTH, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_LCD, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_LCD, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 4, 8, 0x10600000, 0, 0 }, { DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 4, 8, 0x10600004, 0, 0 }, { DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 4, 8, 0x10680000, 0, 0 }, { DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN, 4, 8, 0x10680004, 0, 0 }, { DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_AES_RX, DEV_FLAGS_IN , 4, 32, 0x10300008, 0, 0 }, { DSCR_CMD0_AES_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 4, 32, 0x10300004, 0, 0 }, { DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 }, { DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 }, { DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 0, 0x11a0001c, 0, 0 }, { DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 0, 0x11a0001c, 0, 0 }, Loading @@ -173,9 +149,9 @@ static dbdev_tab_t dbdev_tab[] = { { DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 0, 0x11b0001c, 0, 0 }, { DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 0, 0x11b0001c, 0, 0 }, { DSCR_CMD0_PSC1_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_PSC1_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_CIM_RXA, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_CIM_RXA, DEV_FLAGS_IN, 0, 32, 0x14004020, 0, 0 }, { DSCR_CMD0_CIM_RXB, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_CIM_RXB, DEV_FLAGS_IN, 0, 32, 0x14004040, 0, 0 }, { DSCR_CMD0_CIM_RXC, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_CIM_RXC, DEV_FLAGS_IN, 0, 32, 0x14004060, 0, 0 }, { DSCR_CMD0_CIM_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_CIM_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_NAND_FLASH, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_NAND_FLASH, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, Loading @@ -184,6 +160,24 @@ static dbdev_tab_t dbdev_tab[] = { { DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, /* Provide 16 user definable device types */ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, }; }; #define DBDEV_TAB_SIZE (sizeof(dbdev_tab) / sizeof(dbdev_tab_t)) #define DBDEV_TAB_SIZE (sizeof(dbdev_tab) / sizeof(dbdev_tab_t)) Loading @@ -203,6 +197,30 @@ find_dbdev_id (u32 id) return NULL; return NULL; } } u32 au1xxx_ddma_add_device(dbdev_tab_t *dev) { u32 ret = 0; dbdev_tab_t *p=NULL; static u16 new_id=0x1000; p = find_dbdev_id(0); if ( NULL != p ) { memcpy(p, dev, sizeof(dbdev_tab_t)); p->dev_id = DSCR_DEV2CUSTOM_ID(new_id,dev->dev_id); ret = p->dev_id; new_id++; #if 0 printk("add_device: id:%x flags:%x padd:%x\n", p->dev_id, p->dev_flags, p->dev_physaddr ); #endif } return ret; } EXPORT_SYMBOL(au1xxx_ddma_add_device); /* Allocate a channel and return a non-zero descriptor if successful. /* Allocate a channel and return a non-zero descriptor if successful. */ */ u32 u32 Loading @@ -215,7 +233,7 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, int i; int i; dbdev_tab_t *stp, *dtp; dbdev_tab_t *stp, *dtp; chan_tab_t *ctp; chan_tab_t *ctp; volatile au1x_dma_chan_t *cp; au1x_dma_chan_t *cp; /* We do the intialization on the first channel allocation. /* We do the intialization on the first channel allocation. * We have to wait because of the interrupt handler initialization * We have to wait because of the interrupt handler initialization Loading @@ -225,9 +243,6 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, au1xxx_dbdma_init(); au1xxx_dbdma_init(); dbdma_initialized = 1; dbdma_initialized = 1; if ((srcid > DSCR_NDEV_IDS) || (destid > DSCR_NDEV_IDS)) return 0; if ((stp = find_dbdev_id(srcid)) == NULL) return 0; if ((stp = find_dbdev_id(srcid)) == NULL) return 0; if ((dtp = find_dbdev_id(destid)) == NULL) return 0; if ((dtp = find_dbdev_id(destid)) == NULL) return 0; Loading Loading @@ -269,9 +284,9 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, /* If kmalloc fails, it is caught below same /* If kmalloc fails, it is caught below same * as a channel not available. * as a channel not available. */ */ ctp = kmalloc(sizeof(chan_tab_t), GFP_KERNEL); ctp = (chan_tab_t *) kmalloc(sizeof(chan_tab_t), GFP_KERNEL); chan_tab_ptr[i] = ctp; chan_tab_ptr[i] = ctp; ctp->chan_index = chan = i; break; break; } } } } Loading @@ -279,10 +294,11 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, if (ctp != NULL) { if (ctp != NULL) { memset(ctp, 0, sizeof(chan_tab_t)); memset(ctp, 0, sizeof(chan_tab_t)); ctp->chan_index = chan = i; dcp = DDMA_CHANNEL_BASE; dcp = DDMA_CHANNEL_BASE; dcp += (0x0100 * chan); dcp += (0x0100 * chan); ctp->chan_ptr = (au1x_dma_chan_t *)dcp; ctp->chan_ptr = (au1x_dma_chan_t *)dcp; cp = (volatile au1x_dma_chan_t *)dcp; cp = (au1x_dma_chan_t *)dcp; ctp->chan_src = stp; ctp->chan_src = stp; ctp->chan_dest = dtp; ctp->chan_dest = dtp; ctp->chan_callback = callback; ctp->chan_callback = callback; Loading @@ -299,6 +315,9 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, i |= DDMA_CFG_DED; i |= DDMA_CFG_DED; if (dtp->dev_intpolarity) if (dtp->dev_intpolarity) i |= DDMA_CFG_DP; i |= DDMA_CFG_DP; if ((stp->dev_flags & DEV_FLAGS_SYNC) || (dtp->dev_flags & DEV_FLAGS_SYNC)) i |= DDMA_CFG_SYNC; cp->ddma_cfg = i; cp->ddma_cfg = i; au_sync(); au_sync(); Loading @@ -309,14 +328,14 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, rv = (u32)(&chan_tab_ptr[chan]); rv = (u32)(&chan_tab_ptr[chan]); } } else { else { /* Release devices. /* Release devices */ */ stp->dev_flags &= ~DEV_FLAGS_INUSE; stp->dev_flags &= ~DEV_FLAGS_INUSE; dtp->dev_flags &= ~DEV_FLAGS_INUSE; dtp->dev_flags &= ~DEV_FLAGS_INUSE; } } } } return rv; return rv; } } EXPORT_SYMBOL(au1xxx_dbdma_chan_alloc); /* Set the device width if source or destination is a FIFO. /* Set the device width if source or destination is a FIFO. * Should be 8, 16, or 32 bits. * Should be 8, 16, or 32 bits. Loading Loading @@ -344,6 +363,7 @@ au1xxx_dbdma_set_devwidth(u32 chanid, int bits) return rv; return rv; } } EXPORT_SYMBOL(au1xxx_dbdma_set_devwidth); /* Allocate a descriptor ring, initializing as much as possible. /* Allocate a descriptor ring, initializing as much as possible. */ */ Loading @@ -370,7 +390,8 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) * and if we try that first we are likely to not waste larger * and if we try that first we are likely to not waste larger * slabs of memory. * slabs of memory. */ */ desc_base = (u32)kmalloc(entries * sizeof(au1x_ddma_desc_t), GFP_KERNEL); desc_base = (u32)kmalloc(entries * sizeof(au1x_ddma_desc_t), GFP_KERNEL|GFP_DMA); if (desc_base == 0) if (desc_base == 0) return 0; return 0; Loading @@ -381,7 +402,7 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) kfree((const void *)desc_base); kfree((const void *)desc_base); i = entries * sizeof(au1x_ddma_desc_t); i = entries * sizeof(au1x_ddma_desc_t); i += (sizeof(au1x_ddma_desc_t) - 1); i += (sizeof(au1x_ddma_desc_t) - 1); if ((desc_base = (u32)kmalloc(i, GFP_KERNEL)) == 0) if ((desc_base = (u32)kmalloc(i, GFP_KERNEL|GFP_DMA)) == 0) return 0; return 0; desc_base = ALIGN_ADDR(desc_base, sizeof(au1x_ddma_desc_t)); desc_base = ALIGN_ADDR(desc_base, sizeof(au1x_ddma_desc_t)); Loading Loading @@ -461,9 +482,14 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) /* If source input is fifo, set static address. /* If source input is fifo, set static address. */ */ if (stp->dev_flags & DEV_FLAGS_IN) { if (stp->dev_flags & DEV_FLAGS_IN) { src0 = stp->dev_physaddr; if ( stp->dev_flags & DEV_FLAGS_BURSTABLE ) src1 |= DSCR_SRC1_SAM(DSCR_xAM_BURST); else src1 |= DSCR_SRC1_SAM(DSCR_xAM_STATIC); src1 |= DSCR_SRC1_SAM(DSCR_xAM_STATIC); } } if (stp->dev_physaddr) src0 = stp->dev_physaddr; /* Set up dest1. For now, assume no stride and increment. /* Set up dest1. For now, assume no stride and increment. * A channel attribute update can change this later. * A channel attribute update can change this later. Loading @@ -487,10 +513,18 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) /* If destination output is fifo, set static address. /* If destination output is fifo, set static address. */ */ if (dtp->dev_flags & DEV_FLAGS_OUT) { if (dtp->dev_flags & DEV_FLAGS_OUT) { dest0 = dtp->dev_physaddr; if ( dtp->dev_flags & DEV_FLAGS_BURSTABLE ) dest1 |= DSCR_DEST1_DAM(DSCR_xAM_BURST); else dest1 |= DSCR_DEST1_DAM(DSCR_xAM_STATIC); dest1 |= DSCR_DEST1_DAM(DSCR_xAM_STATIC); } } if (dtp->dev_physaddr) dest0 = dtp->dev_physaddr; #if 0 printk("did:%x sid:%x cmd0:%x cmd1:%x source0:%x source1:%x dest0:%x dest1:%x\n", dtp->dev_id, stp->dev_id, cmd0, cmd1, src0, src1, dest0, dest1 ); #endif for (i=0; i<entries; i++) { for (i=0; i<entries; i++) { dp->dscr_cmd0 = cmd0; dp->dscr_cmd0 = cmd0; dp->dscr_cmd1 = cmd1; dp->dscr_cmd1 = cmd1; Loading @@ -499,6 +533,7 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) dp->dscr_dest0 = dest0; dp->dscr_dest0 = dest0; dp->dscr_dest1 = dest1; dp->dscr_dest1 = dest1; dp->dscr_stat = 0; dp->dscr_stat = 0; dp->sw_context = dp->sw_status = 0; dp->dscr_nxtptr = DSCR_NXTPTR(virt_to_phys(dp + 1)); dp->dscr_nxtptr = DSCR_NXTPTR(virt_to_phys(dp + 1)); dp++; dp++; } } Loading @@ -511,13 +546,14 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) return (u32)(ctp->chan_desc_base); return (u32)(ctp->chan_desc_base); } } EXPORT_SYMBOL(au1xxx_dbdma_ring_alloc); /* Put a source buffer into the DMA ring. /* Put a source buffer into the DMA ring. * This updates the source pointer and byte count. Normally used * This updates the source pointer and byte count. Normally used * for memory to fifo transfers. * for memory to fifo transfers. */ */ u32 u32 au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes) _au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes, u32 flags) { { chan_tab_t *ctp; chan_tab_t *ctp; au1x_ddma_desc_t *dp; au1x_ddma_desc_t *dp; Loading @@ -544,24 +580,40 @@ au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes) */ */ dp->dscr_source0 = virt_to_phys(buf); dp->dscr_source0 = virt_to_phys(buf); dp->dscr_cmd1 = nbytes; dp->dscr_cmd1 = nbytes; dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */ /* Check flags */ ctp->chan_ptr->ddma_dbell = 0xffffffff; /* Make it go */ if (flags & DDMA_FLAGS_IE) dp->dscr_cmd0 |= DSCR_CMD0_IE; if (flags & DDMA_FLAGS_NOIE) dp->dscr_cmd0 &= ~DSCR_CMD0_IE; /* Get next descriptor pointer. /* Get next descriptor pointer. */ */ ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); /* * There is an errata on the Au1200/Au1550 parts that could result * in "stale" data being DMA'd. It has to do with the snoop logic on * the dache eviction buffer. NONCOHERENT_IO is on by default for * these parts. If it is fixedin the future, these dma_cache_inv will * just be nothing more than empty macros. See io.h. * */ dma_cache_wback_inv(buf,nbytes); dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */ au_sync(); dma_cache_wback_inv(dp, sizeof(dp)); ctp->chan_ptr->ddma_dbell = 0; /* return something not zero. /* return something not zero. */ */ return nbytes; return nbytes; } } EXPORT_SYMBOL(_au1xxx_dbdma_put_source); /* Put a destination buffer into the DMA ring. /* Put a destination buffer into the DMA ring. * This updates the destination pointer and byte count. Normally used * This updates the destination pointer and byte count. Normally used * to place an empty buffer into the ring for fifo to memory transfers. * to place an empty buffer into the ring for fifo to memory transfers. */ */ u32 u32 au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes) _au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes, u32 flags) { { chan_tab_t *ctp; chan_tab_t *ctp; au1x_ddma_desc_t *dp; au1x_ddma_desc_t *dp; Loading @@ -583,11 +635,33 @@ au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes) if (dp->dscr_cmd0 & DSCR_CMD0_V) if (dp->dscr_cmd0 & DSCR_CMD0_V) return 0; return 0; /* Load up buffer address and byte count. /* Load up buffer address and byte count */ */ /* Check flags */ if (flags & DDMA_FLAGS_IE) dp->dscr_cmd0 |= DSCR_CMD0_IE; if (flags & DDMA_FLAGS_NOIE) dp->dscr_cmd0 &= ~DSCR_CMD0_IE; dp->dscr_dest0 = virt_to_phys(buf); dp->dscr_dest0 = virt_to_phys(buf); dp->dscr_cmd1 = nbytes; dp->dscr_cmd1 = nbytes; #if 0 printk("cmd0:%x cmd1:%x source0:%x source1:%x dest0:%x dest1:%x\n", dp->dscr_cmd0, dp->dscr_cmd1, dp->dscr_source0, dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1 ); #endif /* * There is an errata on the Au1200/Au1550 parts that could result in * "stale" data being DMA'd. It has to do with the snoop logic on the * dache eviction buffer. NONCOHERENT_IO is on by default for these * parts. If it is fixedin the future, these dma_cache_inv will just * be nothing more than empty macros. See io.h. * */ dma_cache_inv(buf,nbytes); dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */ dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */ au_sync(); dma_cache_wback_inv(dp, sizeof(dp)); ctp->chan_ptr->ddma_dbell = 0; /* Get next descriptor pointer. /* Get next descriptor pointer. */ */ Loading @@ -597,6 +671,7 @@ au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes) */ */ return nbytes; return nbytes; } } EXPORT_SYMBOL(_au1xxx_dbdma_put_dest); /* Get a destination buffer into the DMA ring. /* Get a destination buffer into the DMA ring. * Normally used to get a full buffer from the ring during fifo * Normally used to get a full buffer from the ring during fifo Loading Loading @@ -646,7 +721,7 @@ void au1xxx_dbdma_stop(u32 chanid) au1xxx_dbdma_stop(u32 chanid) { { chan_tab_t *ctp; chan_tab_t *ctp; volatile au1x_dma_chan_t *cp; au1x_dma_chan_t *cp; int halt_timeout = 0; int halt_timeout = 0; ctp = *((chan_tab_t **)chanid); ctp = *((chan_tab_t **)chanid); Loading @@ -666,6 +741,7 @@ au1xxx_dbdma_stop(u32 chanid) cp->ddma_stat |= (DDMA_STAT_DB | DDMA_STAT_V); cp->ddma_stat |= (DDMA_STAT_DB | DDMA_STAT_V); au_sync(); au_sync(); } } EXPORT_SYMBOL(au1xxx_dbdma_stop); /* Start using the current descriptor pointer. If the dbdma encounters /* Start using the current descriptor pointer. If the dbdma encounters * a not valid descriptor, it will stop. In this case, we can just * a not valid descriptor, it will stop. In this case, we can just Loading @@ -675,17 +751,17 @@ void au1xxx_dbdma_start(u32 chanid) au1xxx_dbdma_start(u32 chanid) { { chan_tab_t *ctp; chan_tab_t *ctp; volatile au1x_dma_chan_t *cp; au1x_dma_chan_t *cp; ctp = *((chan_tab_t **)chanid); ctp = *((chan_tab_t **)chanid); cp = ctp->chan_ptr; cp = ctp->chan_ptr; cp->ddma_desptr = virt_to_phys(ctp->cur_ptr); cp->ddma_desptr = virt_to_phys(ctp->cur_ptr); cp->ddma_cfg |= DDMA_CFG_EN; /* Enable channel */ cp->ddma_cfg |= DDMA_CFG_EN; /* Enable channel */ au_sync(); au_sync(); cp->ddma_dbell = 0xffffffff; /* Make it go */ cp->ddma_dbell = 0; au_sync(); au_sync(); } } EXPORT_SYMBOL(au1xxx_dbdma_start); void void au1xxx_dbdma_reset(u32 chanid) au1xxx_dbdma_reset(u32 chanid) Loading @@ -704,15 +780,21 @@ au1xxx_dbdma_reset(u32 chanid) do { do { dp->dscr_cmd0 &= ~DSCR_CMD0_V; dp->dscr_cmd0 &= ~DSCR_CMD0_V; /* reset our SW status -- this is used to determine * if a descriptor is in use by upper level SW. Since * posting can reset 'V' bit. */ dp->sw_status = 0; dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); } while (dp != ctp->chan_desc_base); } while (dp != ctp->chan_desc_base); } } EXPORT_SYMBOL(au1xxx_dbdma_reset); u32 u32 au1xxx_get_dma_residue(u32 chanid) au1xxx_get_dma_residue(u32 chanid) { { chan_tab_t *ctp; chan_tab_t *ctp; volatile au1x_dma_chan_t *cp; au1x_dma_chan_t *cp; u32 rv; u32 rv; ctp = *((chan_tab_t **)chanid); ctp = *((chan_tab_t **)chanid); Loading Loading @@ -747,15 +829,16 @@ au1xxx_dbdma_chan_free(u32 chanid) kfree(ctp); kfree(ctp); } } EXPORT_SYMBOL(au1xxx_dbdma_chan_free); static irqreturn_t static void dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs) dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs) { { u32 intstat; u32 intstat, flags; u32 chan_index; u32 chan_index; chan_tab_t *ctp; chan_tab_t *ctp; au1x_ddma_desc_t *dp; au1x_ddma_desc_t *dp; volatile au1x_dma_chan_t *cp; au1x_dma_chan_t *cp; intstat = dbdma_gptr->ddma_intstat; intstat = dbdma_gptr->ddma_intstat; au_sync(); au_sync(); Loading @@ -774,19 +857,26 @@ dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs) (ctp->chan_callback)(irq, ctp->chan_callparam, regs); (ctp->chan_callback)(irq, ctp->chan_callparam, regs); ctp->cur_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); ctp->cur_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); return IRQ_HANDLED; } } static void static void au1xxx_dbdma_init(void) au1xxx_dbdma_init(void) { { int irq_nr; dbdma_gptr->ddma_config = 0; dbdma_gptr->ddma_config = 0; dbdma_gptr->ddma_throttle = 0; dbdma_gptr->ddma_throttle = 0; dbdma_gptr->ddma_inten = 0xffff; dbdma_gptr->ddma_inten = 0xffff; au_sync(); au_sync(); if (request_irq(AU1550_DDMA_INT, dbdma_interrupt, SA_INTERRUPT, #if defined(CONFIG_SOC_AU1550) irq_nr = AU1550_DDMA_INT; #elif defined(CONFIG_SOC_AU1200) irq_nr = AU1200_DDMA_INT; #else #error Unknown Au1x00 SOC #endif if (request_irq(irq_nr, dbdma_interrupt, SA_INTERRUPT, "Au1xxx dbdma", (void *)dbdma_gptr)) "Au1xxx dbdma", (void *)dbdma_gptr)) printk("Can't get 1550 dbdma irq"); printk("Can't get 1550 dbdma irq"); } } Loading @@ -797,7 +887,8 @@ au1xxx_dbdma_dump(u32 chanid) chan_tab_t *ctp; chan_tab_t *ctp; au1x_ddma_desc_t *dp; au1x_ddma_desc_t *dp; dbdev_tab_t *stp, *dtp; dbdev_tab_t *stp, *dtp; volatile au1x_dma_chan_t *cp; au1x_dma_chan_t *cp; u32 i = 0; ctp = *((chan_tab_t **)chanid); ctp = *((chan_tab_t **)chanid); stp = ctp->chan_src; stp = ctp->chan_src; Loading @@ -822,15 +913,64 @@ au1xxx_dbdma_dump(u32 chanid) dp = ctp->chan_desc_base; dp = ctp->chan_desc_base; do { do { printk("dp %08x, cmd0 %08x, cmd1 %08x\n", printk("Dp[%d]= %08x, cmd0 %08x, cmd1 %08x\n", (u32)dp, dp->dscr_cmd0, dp->dscr_cmd1); i++, (u32)dp, dp->dscr_cmd0, dp->dscr_cmd1); printk("src0 %08x, src1 %08x, dest0 %08x\n", printk("src0 %08x, src1 %08x, dest0 %08x, dest1 %08x\n", dp->dscr_source0, dp->dscr_source1, dp->dscr_dest0); dp->dscr_source0, dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1); printk("dest1 %08x, stat %08x, nxtptr %08x\n", printk("stat %08x, nxtptr %08x\n", dp->dscr_dest1, dp->dscr_stat, dp->dscr_nxtptr); dp->dscr_stat, dp->dscr_nxtptr); dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); } while (dp != ctp->chan_desc_base); } while (dp != ctp->chan_desc_base); } } /* Put a descriptor into the DMA ring. * This updates the source/destination pointers and byte count. */ u32 au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr ) { chan_tab_t *ctp; au1x_ddma_desc_t *dp; u32 nbytes=0; /* I guess we could check this to be within the * range of the table...... */ ctp = *((chan_tab_t **)chanid); /* We should have multiple callers for a particular channel, * an interrupt doesn't affect this pointer nor the descriptor, * so no locking should be needed. */ dp = ctp->put_ptr; /* If the descriptor is valid, we are way ahead of the DMA * engine, so just return an error condition. */ if (dp->dscr_cmd0 & DSCR_CMD0_V) return 0; /* Load up buffer addresses and byte count. */ dp->dscr_dest0 = dscr->dscr_dest0; dp->dscr_source0 = dscr->dscr_source0; dp->dscr_dest1 = dscr->dscr_dest1; dp->dscr_source1 = dscr->dscr_source1; dp->dscr_cmd1 = dscr->dscr_cmd1; nbytes = dscr->dscr_cmd1; /* Allow the caller to specifiy if an interrupt is generated */ dp->dscr_cmd0 &= ~DSCR_CMD0_IE; dp->dscr_cmd0 |= dscr->dscr_cmd0 | DSCR_CMD0_V; ctp->chan_ptr->ddma_dbell = 0; /* Get next descriptor pointer. */ ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); /* return something not zero. */ return nbytes; } #endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */ #endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */ Loading
arch/mips/Kconfig +18 −0 Original line number Original line Diff line number Diff line Loading @@ -642,6 +642,10 @@ config SGI_IP32 help help If you want this kernel to run on SGI O2 workstation, say Y here. If you want this kernel to run on SGI O2 workstation, say Y here. config SOC_AU1200 bool select SOC_AU1X00 config SOC_AU1X00 config SOC_AU1X00 bool "Support for AMD/Alchemy Au1X00 SOCs" bool "Support for AMD/Alchemy Au1X00 SOCs" select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_32BIT_KERNEL Loading Loading @@ -702,6 +706,13 @@ config MIPS_PB1550 select HW_HAS_PCI select HW_HAS_PCI select MIPS_DISABLE_OBSOLETE_IDE select MIPS_DISABLE_OBSOLETE_IDE config MIPS_PB1200 bool "AMD Alchemy PB1200 board" select SOC_AU1200 select DMA_NONCOHERENT select MIPS_DISABLE_OBSOLETE_IDE select SYS_SUPPORTS_LITTLE_ENDIAN config MIPS_DB1000 config MIPS_DB1000 bool "DB1000 board" bool "DB1000 board" depends on SOC_AU1000 depends on SOC_AU1000 Loading Loading @@ -732,6 +743,13 @@ config MIPS_BOSPORUS depends on SOC_AU1500 depends on SOC_AU1500 select DMA_NONCOHERENT select DMA_NONCOHERENT config MIPS_DB1200 bool "AMD Alchemy DB1200 board" select SOC_AU1200 select DMA_NONCOHERENT select MIPS_DISABLE_OBSOLETE_IDE select SYS_SUPPORTS_LITTLE_ENDIAN config MIPS_MIRAGE config MIPS_MIRAGE bool "Mirage board" bool "Mirage board" depends on SOC_AU1500 depends on SOC_AU1500 Loading
arch/mips/Makefile +14 −0 Original line number Original line Diff line number Diff line Loading @@ -265,6 +265,13 @@ libs-$(CONFIG_MIPS_PB1550) += arch/mips/au1000/pb1550/ cflags-$(CONFIG_MIPS_PB1550) += -Iinclude/asm-mips/mach-pb1x00 cflags-$(CONFIG_MIPS_PB1550) += -Iinclude/asm-mips/mach-pb1x00 load-$(CONFIG_MIPS_PB1550) += 0xffffffff80100000 load-$(CONFIG_MIPS_PB1550) += 0xffffffff80100000 # # AMD Alchemy Pb1200 eval board # libs-$(CONFIG_MIPS_PB1200) += arch/mips/au1000/pb1200/ cflags-$(CONFIG_MIPS_PB1200) += -Iinclude/asm-mips/mach-pb1x00 load-$(CONFIG_MIPS_PB1200) += 0xffffffff80100000 # # # AMD Alchemy Db1000 eval board # AMD Alchemy Db1000 eval board # # Loading Loading @@ -293,6 +300,13 @@ libs-$(CONFIG_MIPS_DB1550) += arch/mips/au1000/db1x00/ cflags-$(CONFIG_MIPS_DB1550) += -Iinclude/asm-mips/mach-db1x00 cflags-$(CONFIG_MIPS_DB1550) += -Iinclude/asm-mips/mach-db1x00 load-$(CONFIG_MIPS_DB1550) += 0xffffffff80100000 load-$(CONFIG_MIPS_DB1550) += 0xffffffff80100000 # # AMD Alchemy Db1200 eval board # libs-$(CONFIG_MIPS_DB1200) += arch/mips/au1000/pb1200/ cflags-$(CONFIG_MIPS_DB1200) += -Iinclude/asm-mips/mach-db1x00 load-$(CONFIG_MIPS_DB1200) += 0xffffffff80100000 # # # AMD Alchemy Bosporus eval board # AMD Alchemy Bosporus eval board # # Loading
arch/mips/au1000/common/au1xxx_irqmap.c +16 −16 Original line number Original line Diff line number Diff line Loading @@ -173,14 +173,14 @@ au1xxx_irq_map_t au1xxx_ic0_map[] = { { AU1550_PSC1_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1550_PSC1_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1550_PSC2_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1550_PSC2_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1550_PSC3_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1550_PSC3_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1550_TOY_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, { AU1550_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, { AU1550_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, { AU1550_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, { AU1550_RTC_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, { AU1550_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, { AU1550_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, { AU1550_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, { AU1550_NAND_INT, INTC_INT_RISE_EDGE, 0}, { AU1550_NAND_INT, INTC_INT_RISE_EDGE, 0}, { AU1550_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 }, { AU1550_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 }, { AU1550_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, { AU1550_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, Loading @@ -201,14 +201,14 @@ au1xxx_irq_map_t au1xxx_ic0_map[] = { { AU1200_PSC1_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1200_PSC1_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1200_AES_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1200_AES_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1200_CAMERA_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1200_CAMERA_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1200_TOY_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, { AU1200_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, { AU1200_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, { AU1200_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, { AU1200_RTC_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, { AU1200_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, { AU1200_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, { AU1200_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, { AU1200_NAND_INT, INTC_INT_RISE_EDGE, 0}, { AU1200_NAND_INT, INTC_INT_RISE_EDGE, 0}, { AU1200_USB_INT, INTC_INT_HIGH_LEVEL, 0 }, { AU1200_USB_INT, INTC_INT_HIGH_LEVEL, 0 }, { AU1200_LCD_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1200_LCD_INT, INTC_INT_HIGH_LEVEL, 0}, Loading
arch/mips/au1000/common/cputable.c +2 −1 Original line number Original line Diff line number Diff line Loading @@ -37,7 +37,8 @@ struct cpu_spec cpu_specs[] = { { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1 }, { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1 }, { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1 }, { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1 }, { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1 }, { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1 }, { 0xffffffff, 0x04030200, "Au1200 AA", 0, 1 }, { 0xffffffff, 0x04030200, "Au1200 AB", 0, 0 }, { 0xffffffff, 0x04030201, "Au1200 AC", 0, 1 }, { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0 }, { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0 }, }; }; Loading
arch/mips/au1000/common/dbdma.c +219 −79 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. * 675 Mass Ave, Cambridge, MA 02139, USA. * * */ */ #include <linux/config.h> #include <linux/config.h> #include <linux/kernel.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/errno.h> Loading @@ -42,6 +43,8 @@ #include <asm/mach-au1x00/au1xxx_dbdma.h> #include <asm/mach-au1x00/au1xxx_dbdma.h> #include <asm/system.h> #include <asm/system.h> /* #include <linux/module.h> */ #if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) #if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) /* /* Loading @@ -55,43 +58,16 @@ * functions. The drivers allocate the data buffers and assign them * functions. The drivers allocate the data buffers and assign them * to the descriptors. * to the descriptors. */ */ static DEFINE_SPINLOCK(au1xxx_dbdma_spin_lock); static spinlock_t au1xxx_dbdma_spin_lock = SPIN_LOCK_UNLOCKED; /* I couldn't find a macro that did this...... /* I couldn't find a macro that did this...... */ */ #define ALIGN_ADDR(x, a) ((((u32)(x)) + (a-1)) & ~(a-1)) #define ALIGN_ADDR(x, a) ((((u32)(x)) + (a-1)) & ~(a-1)) static volatile dbdma_global_t *dbdma_gptr = (dbdma_global_t *)DDMA_GLOBAL_BASE; static dbdma_global_t *dbdma_gptr = (dbdma_global_t *)DDMA_GLOBAL_BASE; static int dbdma_initialized; static int dbdma_initialized=0; static void au1xxx_dbdma_init(void); static void au1xxx_dbdma_init(void); typedef struct dbdma_device_table { u32 dev_id; u32 dev_flags; u32 dev_tsize; u32 dev_devwidth; u32 dev_physaddr; /* If FIFO */ u32 dev_intlevel; u32 dev_intpolarity; } dbdev_tab_t; typedef struct dbdma_chan_config { u32 chan_flags; u32 chan_index; dbdev_tab_t *chan_src; dbdev_tab_t *chan_dest; au1x_dma_chan_t *chan_ptr; au1x_ddma_desc_t *chan_desc_base; au1x_ddma_desc_t *get_ptr, *put_ptr, *cur_ptr; void *chan_callparam; void (*chan_callback)(int, void *, struct pt_regs *); } chan_tab_t; #define DEV_FLAGS_INUSE (1 << 0) #define DEV_FLAGS_ANYUSE (1 << 1) #define DEV_FLAGS_OUT (1 << 2) #define DEV_FLAGS_IN (1 << 3) static dbdev_tab_t dbdev_tab[] = { static dbdev_tab_t dbdev_tab[] = { #ifdef CONFIG_SOC_AU1550 #ifdef CONFIG_SOC_AU1550 /* UARTS */ /* UARTS */ Loading Loading @@ -157,13 +133,13 @@ static dbdev_tab_t dbdev_tab[] = { { DSCR_CMD0_MAE_BOTH, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_MAE_BOTH, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_LCD, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_LCD, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 4, 8, 0x10600000, 0, 0 }, { DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 4, 8, 0x10600004, 0, 0 }, { DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 4, 8, 0x10680000, 0, 0 }, { DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN, 4, 8, 0x10680004, 0, 0 }, { DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_AES_RX, DEV_FLAGS_IN , 4, 32, 0x10300008, 0, 0 }, { DSCR_CMD0_AES_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 4, 32, 0x10300004, 0, 0 }, { DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 }, { DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 }, { DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 0, 0x11a0001c, 0, 0 }, { DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 0, 0x11a0001c, 0, 0 }, Loading @@ -173,9 +149,9 @@ static dbdev_tab_t dbdev_tab[] = { { DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 0, 0x11b0001c, 0, 0 }, { DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 0, 0x11b0001c, 0, 0 }, { DSCR_CMD0_PSC1_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_PSC1_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_CIM_RXA, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_CIM_RXA, DEV_FLAGS_IN, 0, 32, 0x14004020, 0, 0 }, { DSCR_CMD0_CIM_RXB, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_CIM_RXB, DEV_FLAGS_IN, 0, 32, 0x14004040, 0, 0 }, { DSCR_CMD0_CIM_RXC, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_CIM_RXC, DEV_FLAGS_IN, 0, 32, 0x14004060, 0, 0 }, { DSCR_CMD0_CIM_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_CIM_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_NAND_FLASH, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_NAND_FLASH, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, Loading @@ -184,6 +160,24 @@ static dbdev_tab_t dbdev_tab[] = { { DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, /* Provide 16 user definable device types */ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, }; }; #define DBDEV_TAB_SIZE (sizeof(dbdev_tab) / sizeof(dbdev_tab_t)) #define DBDEV_TAB_SIZE (sizeof(dbdev_tab) / sizeof(dbdev_tab_t)) Loading @@ -203,6 +197,30 @@ find_dbdev_id (u32 id) return NULL; return NULL; } } u32 au1xxx_ddma_add_device(dbdev_tab_t *dev) { u32 ret = 0; dbdev_tab_t *p=NULL; static u16 new_id=0x1000; p = find_dbdev_id(0); if ( NULL != p ) { memcpy(p, dev, sizeof(dbdev_tab_t)); p->dev_id = DSCR_DEV2CUSTOM_ID(new_id,dev->dev_id); ret = p->dev_id; new_id++; #if 0 printk("add_device: id:%x flags:%x padd:%x\n", p->dev_id, p->dev_flags, p->dev_physaddr ); #endif } return ret; } EXPORT_SYMBOL(au1xxx_ddma_add_device); /* Allocate a channel and return a non-zero descriptor if successful. /* Allocate a channel and return a non-zero descriptor if successful. */ */ u32 u32 Loading @@ -215,7 +233,7 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, int i; int i; dbdev_tab_t *stp, *dtp; dbdev_tab_t *stp, *dtp; chan_tab_t *ctp; chan_tab_t *ctp; volatile au1x_dma_chan_t *cp; au1x_dma_chan_t *cp; /* We do the intialization on the first channel allocation. /* We do the intialization on the first channel allocation. * We have to wait because of the interrupt handler initialization * We have to wait because of the interrupt handler initialization Loading @@ -225,9 +243,6 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, au1xxx_dbdma_init(); au1xxx_dbdma_init(); dbdma_initialized = 1; dbdma_initialized = 1; if ((srcid > DSCR_NDEV_IDS) || (destid > DSCR_NDEV_IDS)) return 0; if ((stp = find_dbdev_id(srcid)) == NULL) return 0; if ((stp = find_dbdev_id(srcid)) == NULL) return 0; if ((dtp = find_dbdev_id(destid)) == NULL) return 0; if ((dtp = find_dbdev_id(destid)) == NULL) return 0; Loading Loading @@ -269,9 +284,9 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, /* If kmalloc fails, it is caught below same /* If kmalloc fails, it is caught below same * as a channel not available. * as a channel not available. */ */ ctp = kmalloc(sizeof(chan_tab_t), GFP_KERNEL); ctp = (chan_tab_t *) kmalloc(sizeof(chan_tab_t), GFP_KERNEL); chan_tab_ptr[i] = ctp; chan_tab_ptr[i] = ctp; ctp->chan_index = chan = i; break; break; } } } } Loading @@ -279,10 +294,11 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, if (ctp != NULL) { if (ctp != NULL) { memset(ctp, 0, sizeof(chan_tab_t)); memset(ctp, 0, sizeof(chan_tab_t)); ctp->chan_index = chan = i; dcp = DDMA_CHANNEL_BASE; dcp = DDMA_CHANNEL_BASE; dcp += (0x0100 * chan); dcp += (0x0100 * chan); ctp->chan_ptr = (au1x_dma_chan_t *)dcp; ctp->chan_ptr = (au1x_dma_chan_t *)dcp; cp = (volatile au1x_dma_chan_t *)dcp; cp = (au1x_dma_chan_t *)dcp; ctp->chan_src = stp; ctp->chan_src = stp; ctp->chan_dest = dtp; ctp->chan_dest = dtp; ctp->chan_callback = callback; ctp->chan_callback = callback; Loading @@ -299,6 +315,9 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, i |= DDMA_CFG_DED; i |= DDMA_CFG_DED; if (dtp->dev_intpolarity) if (dtp->dev_intpolarity) i |= DDMA_CFG_DP; i |= DDMA_CFG_DP; if ((stp->dev_flags & DEV_FLAGS_SYNC) || (dtp->dev_flags & DEV_FLAGS_SYNC)) i |= DDMA_CFG_SYNC; cp->ddma_cfg = i; cp->ddma_cfg = i; au_sync(); au_sync(); Loading @@ -309,14 +328,14 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, rv = (u32)(&chan_tab_ptr[chan]); rv = (u32)(&chan_tab_ptr[chan]); } } else { else { /* Release devices. /* Release devices */ */ stp->dev_flags &= ~DEV_FLAGS_INUSE; stp->dev_flags &= ~DEV_FLAGS_INUSE; dtp->dev_flags &= ~DEV_FLAGS_INUSE; dtp->dev_flags &= ~DEV_FLAGS_INUSE; } } } } return rv; return rv; } } EXPORT_SYMBOL(au1xxx_dbdma_chan_alloc); /* Set the device width if source or destination is a FIFO. /* Set the device width if source or destination is a FIFO. * Should be 8, 16, or 32 bits. * Should be 8, 16, or 32 bits. Loading Loading @@ -344,6 +363,7 @@ au1xxx_dbdma_set_devwidth(u32 chanid, int bits) return rv; return rv; } } EXPORT_SYMBOL(au1xxx_dbdma_set_devwidth); /* Allocate a descriptor ring, initializing as much as possible. /* Allocate a descriptor ring, initializing as much as possible. */ */ Loading @@ -370,7 +390,8 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) * and if we try that first we are likely to not waste larger * and if we try that first we are likely to not waste larger * slabs of memory. * slabs of memory. */ */ desc_base = (u32)kmalloc(entries * sizeof(au1x_ddma_desc_t), GFP_KERNEL); desc_base = (u32)kmalloc(entries * sizeof(au1x_ddma_desc_t), GFP_KERNEL|GFP_DMA); if (desc_base == 0) if (desc_base == 0) return 0; return 0; Loading @@ -381,7 +402,7 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) kfree((const void *)desc_base); kfree((const void *)desc_base); i = entries * sizeof(au1x_ddma_desc_t); i = entries * sizeof(au1x_ddma_desc_t); i += (sizeof(au1x_ddma_desc_t) - 1); i += (sizeof(au1x_ddma_desc_t) - 1); if ((desc_base = (u32)kmalloc(i, GFP_KERNEL)) == 0) if ((desc_base = (u32)kmalloc(i, GFP_KERNEL|GFP_DMA)) == 0) return 0; return 0; desc_base = ALIGN_ADDR(desc_base, sizeof(au1x_ddma_desc_t)); desc_base = ALIGN_ADDR(desc_base, sizeof(au1x_ddma_desc_t)); Loading Loading @@ -461,9 +482,14 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) /* If source input is fifo, set static address. /* If source input is fifo, set static address. */ */ if (stp->dev_flags & DEV_FLAGS_IN) { if (stp->dev_flags & DEV_FLAGS_IN) { src0 = stp->dev_physaddr; if ( stp->dev_flags & DEV_FLAGS_BURSTABLE ) src1 |= DSCR_SRC1_SAM(DSCR_xAM_BURST); else src1 |= DSCR_SRC1_SAM(DSCR_xAM_STATIC); src1 |= DSCR_SRC1_SAM(DSCR_xAM_STATIC); } } if (stp->dev_physaddr) src0 = stp->dev_physaddr; /* Set up dest1. For now, assume no stride and increment. /* Set up dest1. For now, assume no stride and increment. * A channel attribute update can change this later. * A channel attribute update can change this later. Loading @@ -487,10 +513,18 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) /* If destination output is fifo, set static address. /* If destination output is fifo, set static address. */ */ if (dtp->dev_flags & DEV_FLAGS_OUT) { if (dtp->dev_flags & DEV_FLAGS_OUT) { dest0 = dtp->dev_physaddr; if ( dtp->dev_flags & DEV_FLAGS_BURSTABLE ) dest1 |= DSCR_DEST1_DAM(DSCR_xAM_BURST); else dest1 |= DSCR_DEST1_DAM(DSCR_xAM_STATIC); dest1 |= DSCR_DEST1_DAM(DSCR_xAM_STATIC); } } if (dtp->dev_physaddr) dest0 = dtp->dev_physaddr; #if 0 printk("did:%x sid:%x cmd0:%x cmd1:%x source0:%x source1:%x dest0:%x dest1:%x\n", dtp->dev_id, stp->dev_id, cmd0, cmd1, src0, src1, dest0, dest1 ); #endif for (i=0; i<entries; i++) { for (i=0; i<entries; i++) { dp->dscr_cmd0 = cmd0; dp->dscr_cmd0 = cmd0; dp->dscr_cmd1 = cmd1; dp->dscr_cmd1 = cmd1; Loading @@ -499,6 +533,7 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) dp->dscr_dest0 = dest0; dp->dscr_dest0 = dest0; dp->dscr_dest1 = dest1; dp->dscr_dest1 = dest1; dp->dscr_stat = 0; dp->dscr_stat = 0; dp->sw_context = dp->sw_status = 0; dp->dscr_nxtptr = DSCR_NXTPTR(virt_to_phys(dp + 1)); dp->dscr_nxtptr = DSCR_NXTPTR(virt_to_phys(dp + 1)); dp++; dp++; } } Loading @@ -511,13 +546,14 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) return (u32)(ctp->chan_desc_base); return (u32)(ctp->chan_desc_base); } } EXPORT_SYMBOL(au1xxx_dbdma_ring_alloc); /* Put a source buffer into the DMA ring. /* Put a source buffer into the DMA ring. * This updates the source pointer and byte count. Normally used * This updates the source pointer and byte count. Normally used * for memory to fifo transfers. * for memory to fifo transfers. */ */ u32 u32 au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes) _au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes, u32 flags) { { chan_tab_t *ctp; chan_tab_t *ctp; au1x_ddma_desc_t *dp; au1x_ddma_desc_t *dp; Loading @@ -544,24 +580,40 @@ au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes) */ */ dp->dscr_source0 = virt_to_phys(buf); dp->dscr_source0 = virt_to_phys(buf); dp->dscr_cmd1 = nbytes; dp->dscr_cmd1 = nbytes; dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */ /* Check flags */ ctp->chan_ptr->ddma_dbell = 0xffffffff; /* Make it go */ if (flags & DDMA_FLAGS_IE) dp->dscr_cmd0 |= DSCR_CMD0_IE; if (flags & DDMA_FLAGS_NOIE) dp->dscr_cmd0 &= ~DSCR_CMD0_IE; /* Get next descriptor pointer. /* Get next descriptor pointer. */ */ ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); /* * There is an errata on the Au1200/Au1550 parts that could result * in "stale" data being DMA'd. It has to do with the snoop logic on * the dache eviction buffer. NONCOHERENT_IO is on by default for * these parts. If it is fixedin the future, these dma_cache_inv will * just be nothing more than empty macros. See io.h. * */ dma_cache_wback_inv(buf,nbytes); dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */ au_sync(); dma_cache_wback_inv(dp, sizeof(dp)); ctp->chan_ptr->ddma_dbell = 0; /* return something not zero. /* return something not zero. */ */ return nbytes; return nbytes; } } EXPORT_SYMBOL(_au1xxx_dbdma_put_source); /* Put a destination buffer into the DMA ring. /* Put a destination buffer into the DMA ring. * This updates the destination pointer and byte count. Normally used * This updates the destination pointer and byte count. Normally used * to place an empty buffer into the ring for fifo to memory transfers. * to place an empty buffer into the ring for fifo to memory transfers. */ */ u32 u32 au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes) _au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes, u32 flags) { { chan_tab_t *ctp; chan_tab_t *ctp; au1x_ddma_desc_t *dp; au1x_ddma_desc_t *dp; Loading @@ -583,11 +635,33 @@ au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes) if (dp->dscr_cmd0 & DSCR_CMD0_V) if (dp->dscr_cmd0 & DSCR_CMD0_V) return 0; return 0; /* Load up buffer address and byte count. /* Load up buffer address and byte count */ */ /* Check flags */ if (flags & DDMA_FLAGS_IE) dp->dscr_cmd0 |= DSCR_CMD0_IE; if (flags & DDMA_FLAGS_NOIE) dp->dscr_cmd0 &= ~DSCR_CMD0_IE; dp->dscr_dest0 = virt_to_phys(buf); dp->dscr_dest0 = virt_to_phys(buf); dp->dscr_cmd1 = nbytes; dp->dscr_cmd1 = nbytes; #if 0 printk("cmd0:%x cmd1:%x source0:%x source1:%x dest0:%x dest1:%x\n", dp->dscr_cmd0, dp->dscr_cmd1, dp->dscr_source0, dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1 ); #endif /* * There is an errata on the Au1200/Au1550 parts that could result in * "stale" data being DMA'd. It has to do with the snoop logic on the * dache eviction buffer. NONCOHERENT_IO is on by default for these * parts. If it is fixedin the future, these dma_cache_inv will just * be nothing more than empty macros. See io.h. * */ dma_cache_inv(buf,nbytes); dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */ dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */ au_sync(); dma_cache_wback_inv(dp, sizeof(dp)); ctp->chan_ptr->ddma_dbell = 0; /* Get next descriptor pointer. /* Get next descriptor pointer. */ */ Loading @@ -597,6 +671,7 @@ au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes) */ */ return nbytes; return nbytes; } } EXPORT_SYMBOL(_au1xxx_dbdma_put_dest); /* Get a destination buffer into the DMA ring. /* Get a destination buffer into the DMA ring. * Normally used to get a full buffer from the ring during fifo * Normally used to get a full buffer from the ring during fifo Loading Loading @@ -646,7 +721,7 @@ void au1xxx_dbdma_stop(u32 chanid) au1xxx_dbdma_stop(u32 chanid) { { chan_tab_t *ctp; chan_tab_t *ctp; volatile au1x_dma_chan_t *cp; au1x_dma_chan_t *cp; int halt_timeout = 0; int halt_timeout = 0; ctp = *((chan_tab_t **)chanid); ctp = *((chan_tab_t **)chanid); Loading @@ -666,6 +741,7 @@ au1xxx_dbdma_stop(u32 chanid) cp->ddma_stat |= (DDMA_STAT_DB | DDMA_STAT_V); cp->ddma_stat |= (DDMA_STAT_DB | DDMA_STAT_V); au_sync(); au_sync(); } } EXPORT_SYMBOL(au1xxx_dbdma_stop); /* Start using the current descriptor pointer. If the dbdma encounters /* Start using the current descriptor pointer. If the dbdma encounters * a not valid descriptor, it will stop. In this case, we can just * a not valid descriptor, it will stop. In this case, we can just Loading @@ -675,17 +751,17 @@ void au1xxx_dbdma_start(u32 chanid) au1xxx_dbdma_start(u32 chanid) { { chan_tab_t *ctp; chan_tab_t *ctp; volatile au1x_dma_chan_t *cp; au1x_dma_chan_t *cp; ctp = *((chan_tab_t **)chanid); ctp = *((chan_tab_t **)chanid); cp = ctp->chan_ptr; cp = ctp->chan_ptr; cp->ddma_desptr = virt_to_phys(ctp->cur_ptr); cp->ddma_desptr = virt_to_phys(ctp->cur_ptr); cp->ddma_cfg |= DDMA_CFG_EN; /* Enable channel */ cp->ddma_cfg |= DDMA_CFG_EN; /* Enable channel */ au_sync(); au_sync(); cp->ddma_dbell = 0xffffffff; /* Make it go */ cp->ddma_dbell = 0; au_sync(); au_sync(); } } EXPORT_SYMBOL(au1xxx_dbdma_start); void void au1xxx_dbdma_reset(u32 chanid) au1xxx_dbdma_reset(u32 chanid) Loading @@ -704,15 +780,21 @@ au1xxx_dbdma_reset(u32 chanid) do { do { dp->dscr_cmd0 &= ~DSCR_CMD0_V; dp->dscr_cmd0 &= ~DSCR_CMD0_V; /* reset our SW status -- this is used to determine * if a descriptor is in use by upper level SW. Since * posting can reset 'V' bit. */ dp->sw_status = 0; dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); } while (dp != ctp->chan_desc_base); } while (dp != ctp->chan_desc_base); } } EXPORT_SYMBOL(au1xxx_dbdma_reset); u32 u32 au1xxx_get_dma_residue(u32 chanid) au1xxx_get_dma_residue(u32 chanid) { { chan_tab_t *ctp; chan_tab_t *ctp; volatile au1x_dma_chan_t *cp; au1x_dma_chan_t *cp; u32 rv; u32 rv; ctp = *((chan_tab_t **)chanid); ctp = *((chan_tab_t **)chanid); Loading Loading @@ -747,15 +829,16 @@ au1xxx_dbdma_chan_free(u32 chanid) kfree(ctp); kfree(ctp); } } EXPORT_SYMBOL(au1xxx_dbdma_chan_free); static irqreturn_t static void dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs) dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs) { { u32 intstat; u32 intstat, flags; u32 chan_index; u32 chan_index; chan_tab_t *ctp; chan_tab_t *ctp; au1x_ddma_desc_t *dp; au1x_ddma_desc_t *dp; volatile au1x_dma_chan_t *cp; au1x_dma_chan_t *cp; intstat = dbdma_gptr->ddma_intstat; intstat = dbdma_gptr->ddma_intstat; au_sync(); au_sync(); Loading @@ -774,19 +857,26 @@ dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs) (ctp->chan_callback)(irq, ctp->chan_callparam, regs); (ctp->chan_callback)(irq, ctp->chan_callparam, regs); ctp->cur_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); ctp->cur_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); return IRQ_HANDLED; } } static void static void au1xxx_dbdma_init(void) au1xxx_dbdma_init(void) { { int irq_nr; dbdma_gptr->ddma_config = 0; dbdma_gptr->ddma_config = 0; dbdma_gptr->ddma_throttle = 0; dbdma_gptr->ddma_throttle = 0; dbdma_gptr->ddma_inten = 0xffff; dbdma_gptr->ddma_inten = 0xffff; au_sync(); au_sync(); if (request_irq(AU1550_DDMA_INT, dbdma_interrupt, SA_INTERRUPT, #if defined(CONFIG_SOC_AU1550) irq_nr = AU1550_DDMA_INT; #elif defined(CONFIG_SOC_AU1200) irq_nr = AU1200_DDMA_INT; #else #error Unknown Au1x00 SOC #endif if (request_irq(irq_nr, dbdma_interrupt, SA_INTERRUPT, "Au1xxx dbdma", (void *)dbdma_gptr)) "Au1xxx dbdma", (void *)dbdma_gptr)) printk("Can't get 1550 dbdma irq"); printk("Can't get 1550 dbdma irq"); } } Loading @@ -797,7 +887,8 @@ au1xxx_dbdma_dump(u32 chanid) chan_tab_t *ctp; chan_tab_t *ctp; au1x_ddma_desc_t *dp; au1x_ddma_desc_t *dp; dbdev_tab_t *stp, *dtp; dbdev_tab_t *stp, *dtp; volatile au1x_dma_chan_t *cp; au1x_dma_chan_t *cp; u32 i = 0; ctp = *((chan_tab_t **)chanid); ctp = *((chan_tab_t **)chanid); stp = ctp->chan_src; stp = ctp->chan_src; Loading @@ -822,15 +913,64 @@ au1xxx_dbdma_dump(u32 chanid) dp = ctp->chan_desc_base; dp = ctp->chan_desc_base; do { do { printk("dp %08x, cmd0 %08x, cmd1 %08x\n", printk("Dp[%d]= %08x, cmd0 %08x, cmd1 %08x\n", (u32)dp, dp->dscr_cmd0, dp->dscr_cmd1); i++, (u32)dp, dp->dscr_cmd0, dp->dscr_cmd1); printk("src0 %08x, src1 %08x, dest0 %08x\n", printk("src0 %08x, src1 %08x, dest0 %08x, dest1 %08x\n", dp->dscr_source0, dp->dscr_source1, dp->dscr_dest0); dp->dscr_source0, dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1); printk("dest1 %08x, stat %08x, nxtptr %08x\n", printk("stat %08x, nxtptr %08x\n", dp->dscr_dest1, dp->dscr_stat, dp->dscr_nxtptr); dp->dscr_stat, dp->dscr_nxtptr); dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); } while (dp != ctp->chan_desc_base); } while (dp != ctp->chan_desc_base); } } /* Put a descriptor into the DMA ring. * This updates the source/destination pointers and byte count. */ u32 au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr ) { chan_tab_t *ctp; au1x_ddma_desc_t *dp; u32 nbytes=0; /* I guess we could check this to be within the * range of the table...... */ ctp = *((chan_tab_t **)chanid); /* We should have multiple callers for a particular channel, * an interrupt doesn't affect this pointer nor the descriptor, * so no locking should be needed. */ dp = ctp->put_ptr; /* If the descriptor is valid, we are way ahead of the DMA * engine, so just return an error condition. */ if (dp->dscr_cmd0 & DSCR_CMD0_V) return 0; /* Load up buffer addresses and byte count. */ dp->dscr_dest0 = dscr->dscr_dest0; dp->dscr_source0 = dscr->dscr_source0; dp->dscr_dest1 = dscr->dscr_dest1; dp->dscr_source1 = dscr->dscr_source1; dp->dscr_cmd1 = dscr->dscr_cmd1; nbytes = dscr->dscr_cmd1; /* Allow the caller to specifiy if an interrupt is generated */ dp->dscr_cmd0 &= ~DSCR_CMD0_IE; dp->dscr_cmd0 |= dscr->dscr_cmd0 | DSCR_CMD0_V; ctp->chan_ptr->ddma_dbell = 0; /* Get next descriptor pointer. */ ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); /* return something not zero. */ return nbytes; } #endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */ #endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */