* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
-
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/delay.h>
+#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-au1x00/au1xxx_dbdma.h>
#include <asm/system.h>
+#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
+
/*
* The Descriptor Based DMA supports up to 16 channels.
*
* functions. The drivers allocate the data buffers and assign them
* to the descriptors.
*/
-static spinlock_t au1xxx_dbdma_spin_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(au1xxx_dbdma_spin_lock);
/* I couldn't find a macro that did this......
*/
static void au1xxx_dbdma_init(void);
typedef struct dbdma_device_table {
+ u32 dev_id;
u32 dev_flags;
u32 dev_tsize;
u32 dev_devwidth;
#define DEV_FLAGS_IN (1 << 3)
static dbdev_tab_t dbdev_tab[] = {
+#ifdef CONFIG_SOC_AU1550
/* UARTS */
- { DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 },
- { DEV_FLAGS_IN, 0, 8, 0x11100000, 0, 0 },
- { DEV_FLAGS_OUT, 0, 8, 0x11400004, 0, 0 },
- { DEV_FLAGS_IN, 0, 8, 0x11400000, 0, 0 },
+ { DSCR_CMD0_UART0_TX, DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 },
+ { DSCR_CMD0_UART0_RX, DEV_FLAGS_IN, 0, 8, 0x11100000, 0, 0 },
+ { DSCR_CMD0_UART3_TX, DEV_FLAGS_OUT, 0, 8, 0x11400004, 0, 0 },
+ { DSCR_CMD0_UART3_RX, DEV_FLAGS_IN, 0, 8, 0x11400000, 0, 0 },
/* EXT DMA */
- { 0, 0, 0, 0x00000000, 0, 0 },
- { 0, 0, 0, 0x00000000, 0, 0 },
- { 0, 0, 0, 0x00000000, 0, 0 },
- { 0, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_DMA_REQ0, 0, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_DMA_REQ1, 0, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_DMA_REQ2, 0, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_DMA_REQ3, 0, 0, 0, 0x00000000, 0, 0 },
/* USB DEV */
- { DEV_FLAGS_IN, 4, 8, 0x10200000, 0, 0 },
- { DEV_FLAGS_OUT, 4, 8, 0x10200004, 0, 0 },
- { DEV_FLAGS_OUT, 4, 8, 0x10200008, 0, 0 },
- { DEV_FLAGS_OUT, 4, 8, 0x1020000c, 0, 0 },
- { DEV_FLAGS_IN, 4, 8, 0x10200010, 0, 0 },
- { DEV_FLAGS_IN, 4, 8, 0x10200014, 0, 0 },
+ { DSCR_CMD0_USBDEV_RX0, DEV_FLAGS_IN, 4, 8, 0x10200000, 0, 0 },
+ { DSCR_CMD0_USBDEV_TX0, DEV_FLAGS_OUT, 4, 8, 0x10200004, 0, 0 },
+ { DSCR_CMD0_USBDEV_TX1, DEV_FLAGS_OUT, 4, 8, 0x10200008, 0, 0 },
+ { DSCR_CMD0_USBDEV_TX2, DEV_FLAGS_OUT, 4, 8, 0x1020000c, 0, 0 },
+ { DSCR_CMD0_USBDEV_RX3, DEV_FLAGS_IN, 4, 8, 0x10200010, 0, 0 },
+ { DSCR_CMD0_USBDEV_RX4, DEV_FLAGS_IN, 4, 8, 0x10200014, 0, 0 },
/* PSC 0 */
- { DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 },
- { DEV_FLAGS_IN, 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 },
/* PSC 1 */
- { DEV_FLAGS_OUT, 0, 0, 0x11b0001c, 0, 0 },
- { DEV_FLAGS_IN, 0, 0, 0x11b0001c, 0, 0 },
+ { DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 0, 0x11b0001c, 0, 0 },
+ { DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 0, 0x11b0001c, 0, 0 },
/* PSC 2 */
- { DEV_FLAGS_OUT, 0, 0, 0x10a0001c, 0, 0 },
- { DEV_FLAGS_IN, 0, 0, 0x10a0001c, 0, 0 },
+ { DSCR_CMD0_PSC2_TX, DEV_FLAGS_OUT, 0, 0, 0x10a0001c, 0, 0 },
+ { DSCR_CMD0_PSC2_RX, DEV_FLAGS_IN, 0, 0, 0x10a0001c, 0, 0 },
/* PSC 3 */
- { DEV_FLAGS_OUT, 0, 0, 0x10b0001c, 0, 0 },
- { DEV_FLAGS_IN, 0, 0, 0x10b0001c, 0, 0 },
+ { DSCR_CMD0_PSC3_TX, DEV_FLAGS_OUT, 0, 0, 0x10b0001c, 0, 0 },
+ { DSCR_CMD0_PSC3_RX, DEV_FLAGS_IN, 0, 0, 0x10b0001c, 0, 0 },
- { 0, 0, 0, 0x00000000, 0, 0 }, /* PCI */
- { 0, 0, 0, 0x00000000, 0, 0 }, /* NAND */
+ { DSCR_CMD0_PCI_WRITE, 0, 0, 0, 0x00000000, 0, 0 }, /* PCI */
+ { DSCR_CMD0_NAND_FLASH, 0, 0, 0, 0x00000000, 0, 0 }, /* NAND */
/* MAC 0 */
- { DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
- { DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_MAC0_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_MAC0_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
/* MAC 1 */
- { DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
- { DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_MAC1_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_MAC1_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
+
+#endif /* CONFIG_SOC_AU1550 */
+
+#ifdef CONFIG_SOC_AU1200
+ { DSCR_CMD0_UART0_TX, DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 },
+ { DSCR_CMD0_UART0_RX, DEV_FLAGS_IN, 0, 8, 0x11100000, 0, 0 },
+ { DSCR_CMD0_UART1_TX, DEV_FLAGS_OUT, 0, 8, 0x11200004, 0, 0 },
+ { DSCR_CMD0_UART1_RX, DEV_FLAGS_IN, 0, 8, 0x11200000, 0, 0 },
+
+ { DSCR_CMD0_DMA_REQ0, 0, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_DMA_REQ1, 0, 0, 0, 0x00000000, 0, 0 },
+
+ { DSCR_CMD0_MAE_BE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_MAE_FE, 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_SDMS_TX0, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+
+ { DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_AES_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 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_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+
+ { DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 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_CIM_RXA, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_CIM_RXB, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_CIM_RXC, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_CIM_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
- /* reserved */
- { DEV_FLAGS_INUSE, 0, 0, 0x00000000, 0, 0 },
- { DEV_FLAGS_INUSE, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_NAND_FLASH, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
- /* Memory */
- { DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, /* throttle */
- { DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, /* always */
+#endif // CONFIG_SOC_AU1200
+
+ { DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
};
+#define DBDEV_TAB_SIZE (sizeof(dbdev_tab) / sizeof(dbdev_tab_t))
+
static chan_tab_t *chan_tab_ptr[NUM_DBDMA_CHANS];
+static dbdev_tab_t *
+find_dbdev_id (u32 id)
+{
+ int i;
+ dbdev_tab_t *p;
+ for (i = 0; i < DBDEV_TAB_SIZE; ++i) {
+ p = &dbdev_tab[i];
+ if (p->dev_id == id)
+ return p;
+ }
+ return NULL;
+}
+
/* Allocate a channel and return a non-zero descriptor if successful.
*/
u32
if ((srcid > DSCR_NDEV_IDS) || (destid > DSCR_NDEV_IDS))
return 0;
- stp = &dbdev_tab[srcid];
- dtp = &dbdev_tab[destid];
+ if ((stp = find_dbdev_id(srcid)) == NULL) return 0;
+ if ((dtp = find_dbdev_id(destid)) == NULL) return 0;
+
used = 0;
rv = 0;
/* If kmalloc fails, it is caught below same
* as a channel not available.
*/
- ctp = (chan_tab_t *)kmalloc(sizeof(chan_tab_t), GFP_KERNEL);
+ ctp = kmalloc(sizeof(chan_tab_t), GFP_KERNEL);
chan_tab_ptr[i] = ctp;
ctp->chan_index = chan = i;
break;
/* Initialize the rings with as much information as we know.
*/
- srcid = stp - dbdev_tab; /* Index is channel device ID */
- destid = dtp - dbdev_tab;
+ srcid = stp->dev_id;
+ destid = dtp->dev_id;
cmd0 = cmd1 = src1 = dest1 = 0;
src0 = dest0 = 0;
kfree(ctp);
}
-static void
+static irqreturn_t
dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
u32 intstat;
ctp->cur_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
+ return IRQ_HANDLED;
}
static void
dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
} while (dp != ctp->chan_desc_base);
}
+
+#endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */
+