diff -Nur linux-2.4.30/Makefile linux-2.4.30-mips/Makefile --- linux-2.4.30/Makefile 2005-04-04 03:42:20.000000000 +0200 +++ linux-2.4.30-mips/Makefile 2005-04-05 21:09:54.000000000 +0200 @@ -5,7 +5,7 @@ KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) -ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) +ARCH = mips KERNELPATH=kernel-$(shell echo $(KERNELRELEASE) | sed -e "s/-//g") CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ @@ -462,10 +462,11 @@ $(MAKE) -C Documentation/DocBook mrproper distclean: mrproper - rm -f core `find . \( -not -type d \) -and \ - \( -name '*.orig' -o -name '*.rej' -o -name '*~' \ - -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \ - -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -type f -print` TAGS tags + find . \( -not -type d \) -and \ + \( -name core -o -name '*.orig' -o -name '*.rej' \ + -o -name '*~' -o -name '*.bak' -o -name '#*#' \ + -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \ + -o -name TAGS -o -name tags \) -print | env -i xargs rm -f backup: mrproper cd .. && tar cf - linux/ | gzip -9 > backup.gz @@ -492,7 +493,7 @@ $(MAKE) -C Documentation/DocBook man sums: - find . -type f -print | sort | xargs sum > .SUMS + find . -type f -print | sort | env -i xargs sum > .SUMS dep-files: scripts/mkdep archdep include/linux/version.h rm -f .depend .hdepend diff -Nur linux-2.4.30/arch/mips/Makefile linux-2.4.30-mips/arch/mips/Makefile --- linux-2.4.30/arch/mips/Makefile 2005-01-19 15:09:26.000000000 +0100 +++ linux-2.4.30-mips/arch/mips/Makefile 2005-01-30 09:01:26.000000000 +0100 @@ -211,7 +211,7 @@ endif # -# Au1000 (Alchemy Semi PB1000) eval board +# Au1x AMD Alchemy eval boards # ifdef CONFIG_MIPS_PB1000 LIBS += arch/mips/au1000/pb1000/pb1000.o \ @@ -220,9 +220,6 @@ LOADADDR := 0x80100000 endif -# -# Au1100 (Alchemy Semi PB1100) eval board -# ifdef CONFIG_MIPS_PB1100 LIBS += arch/mips/au1000/pb1100/pb1100.o \ arch/mips/au1000/common/au1000.o @@ -230,9 +227,6 @@ LOADADDR += 0x80100000 endif -# -# Au1500 (Alchemy Semi PB1500) eval board -# ifdef CONFIG_MIPS_PB1500 LIBS += arch/mips/au1000/pb1500/pb1500.o \ arch/mips/au1000/common/au1000.o @@ -240,9 +234,6 @@ LOADADDR := 0x80100000 endif -# -# Au1x00 (AMD/Alchemy) eval boards -# ifdef CONFIG_MIPS_DB1000 LIBS += arch/mips/au1000/db1x00/db1x00.o \ arch/mips/au1000/common/au1000.o @@ -313,6 +304,27 @@ LOADADDR += 0x80100000 endif +ifdef CONFIG_MIPS_PB1200 +LIBS += arch/mips/au1000/pb1200/pb1200.o \ + arch/mips/au1000/common/au1000.o +SUBDIRS += arch/mips/au1000/pb1200 arch/mips/au1000/common +LOADADDR += 0x80100000 +endif + +ifdef CONFIG_MIPS_DB1200 +LIBS += arch/mips/au1000/pb1200/pb1200.o \ + arch/mips/au1000/common/au1000.o +SUBDIRS += arch/mips/au1000/pb1200 arch/mips/au1000/common +LOADADDR += 0x80100000 +endif + +ifdef CONFIG_MIPS_FICMMP +LIBS += arch/mips/au1000/ficmmp/ficmmp.o \ + arch/mips/au1000/common/au1000.o +SUBDIRS += arch/mips/au1000/ficmmp arch/mips/au1000/common +LOADADDR += 0x80100000 +endif + # # Cogent CSB250 diff -Nur linux-2.4.30/arch/mips/au1000/common/Makefile linux-2.4.30-mips/arch/mips/au1000/common/Makefile --- linux-2.4.30/arch/mips/au1000/common/Makefile 2005-01-19 15:09:26.000000000 +0100 +++ linux-2.4.30-mips/arch/mips/au1000/common/Makefile 2005-01-30 09:01:27.000000000 +0100 @@ -19,9 +19,9 @@ export-objs = prom.o clocks.o power.o usbdev.o obj-y := prom.o int-handler.o irq.o puts.o time.o reset.o cputable.o \ - au1xxx_irqmap.o clocks.o power.o setup.o sleeper.o dma.o dbdma.o + au1xxx_irqmap.o clocks.o power.o setup.o sleeper.o dma.o dbdma.o gpio.o -export-objs += dma.o dbdma.o +export-objs += dma.o dbdma.o gpio.o obj-$(CONFIG_AU1X00_USB_DEVICE) += usbdev.o obj-$(CONFIG_KGDB) += dbg_io.o diff -Nur linux-2.4.30/arch/mips/au1000/common/au1xxx_irqmap.c linux-2.4.30-mips/arch/mips/au1000/common/au1xxx_irqmap.c --- linux-2.4.30/arch/mips/au1000/common/au1xxx_irqmap.c 2005-01-19 15:09:26.000000000 +0100 +++ linux-2.4.30-mips/arch/mips/au1000/common/au1xxx_irqmap.c 2005-01-30 09:01:27.000000000 +0100 @@ -172,14 +172,14 @@ { AU1550_PSC1_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1550_PSC2_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1550_PSC3_INT, INTC_INT_HIGH_LEVEL, 0}, - { AU1550_TOY_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1550_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1550_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1550_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, - { AU1550_RTC_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1550_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1550_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1550_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, + { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH2_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_SUS_INT, INTC_INT_RISE_EDGE, 0 }, @@ -200,14 +200,14 @@ { AU1200_PSC1_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1200_AES_INT, INTC_INT_HIGH_LEVEL, 0}, { AU1200_CAMERA_INT, INTC_INT_HIGH_LEVEL, 0}, - { AU1200_TOY_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1200_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1200_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1200_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, - { AU1200_RTC_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1200_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1200_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, - { AU1200_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, + { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, { AU1200_NAND_INT, INTC_INT_RISE_EDGE, 0}, { AU1200_USB_INT, INTC_INT_HIGH_LEVEL, 0 }, { AU1200_LCD_INT, INTC_INT_HIGH_LEVEL, 0}, diff -Nur linux-2.4.30/arch/mips/au1000/common/cputable.c linux-2.4.30-mips/arch/mips/au1000/common/cputable.c --- linux-2.4.30/arch/mips/au1000/common/cputable.c 2005-01-19 15:09:26.000000000 +0100 +++ linux-2.4.30-mips/arch/mips/au1000/common/cputable.c 2005-01-30 09:01:27.000000000 +0100 @@ -39,7 +39,8 @@ { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1 }, { 0xffffffff, 0x02030204, "Au1100 BE", 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, 0 }, { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0 }, }; diff -Nur linux-2.4.30/arch/mips/au1000/common/dbdma.c linux-2.4.30-mips/arch/mips/au1000/common/dbdma.c --- linux-2.4.30/arch/mips/au1000/common/dbdma.c 2005-01-19 15:09:26.000000000 +0100 +++ linux-2.4.30-mips/arch/mips/au1000/common/dbdma.c 2005-02-08 07:28:37.000000000 +0100 @@ -41,6 +41,8 @@ #include #include +#include + #if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) /* @@ -60,37 +62,10 @@ */ #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 int dbdma_initialized; +static dbdma_global_t *dbdma_gptr = (dbdma_global_t *)DDMA_GLOBAL_BASE; +static int dbdma_initialized=0; 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[] = { #ifdef CONFIG_SOC_AU1550 /* UARTS */ @@ -156,13 +131,13 @@ { 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_SDMS_TX0, DEV_FLAGS_OUT, 4, 8, 0x10600000, 0, 0 }, + { DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 4, 8, 0x10600004, 0, 0 }, + { DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 4, 8, 0x10680000, 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, 0, 0, 0x00000000, 0, 0 }, + { DSCR_CMD0_AES_RX, DEV_FLAGS_IN , 4, 32, 0x10300008, 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_RX, DEV_FLAGS_IN, 0, 0, 0x11a0001c, 0, 0 }, @@ -172,9 +147,9 @@ { 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_RXA, DEV_FLAGS_IN, 0, 32, 0x14004020, 0, 0 }, + { DSCR_CMD0_CIM_RXB, DEV_FLAGS_IN, 0, 32, 0x14004040, 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_NAND_FLASH, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, @@ -183,6 +158,24 @@ { DSCR_CMD0_THROTTLE, 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)) @@ -202,6 +195,30 @@ 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. */ u32 @@ -214,7 +231,7 @@ int i; dbdev_tab_t *stp, *dtp; 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 have to wait because of the interrupt handler initialization @@ -224,9 +241,6 @@ au1xxx_dbdma_init(); dbdma_initialized = 1; - if ((srcid > DSCR_NDEV_IDS) || (destid > DSCR_NDEV_IDS)) - return 0; - if ((stp = find_dbdev_id(srcid)) == NULL) return 0; if ((dtp = find_dbdev_id(destid)) == NULL) return 0; @@ -268,9 +282,9 @@ /* 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 = (chan_tab_t *) + kmalloc(sizeof(chan_tab_t), GFP_KERNEL); chan_tab_ptr[i] = ctp; - ctp->chan_index = chan = i; break; } } @@ -278,10 +292,11 @@ if (ctp != NULL) { memset(ctp, 0, sizeof(chan_tab_t)); + ctp->chan_index = chan = i; dcp = DDMA_CHANNEL_BASE; dcp += (0x0100 * chan); 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_dest = dtp; ctp->chan_callback = callback; @@ -298,6 +313,9 @@ i |= DDMA_CFG_DED; if (dtp->dev_intpolarity) 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; au_sync(); @@ -308,14 +326,14 @@ rv = (u32)(&chan_tab_ptr[chan]); } else { - /* Release devices. - */ + /* Release devices */ stp->dev_flags &= ~DEV_FLAGS_INUSE; dtp->dev_flags &= ~DEV_FLAGS_INUSE; } } return rv; } +EXPORT_SYMBOL(au1xxx_dbdma_chan_alloc); /* Set the device width if source or destination is a FIFO. * Should be 8, 16, or 32 bits. @@ -343,6 +361,7 @@ return rv; } +EXPORT_SYMBOL(au1xxx_dbdma_set_devwidth); /* Allocate a descriptor ring, initializing as much as possible. */ @@ -369,7 +388,8 @@ * and if we try that first we are likely to not waste larger * 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) return 0; @@ -380,7 +400,7 @@ kfree((const void *)desc_base); i = entries * sizeof(au1x_ddma_desc_t); 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; desc_base = ALIGN_ADDR(desc_base, sizeof(au1x_ddma_desc_t)); @@ -460,9 +480,14 @@ /* If source input is fifo, set static address. */ if (stp->dev_flags & DEV_FLAGS_IN) { - src0 = stp->dev_physaddr; - src1 |= DSCR_SRC1_SAM(DSCR_xAM_STATIC); + if ( stp->dev_flags & DEV_FLAGS_BURSTABLE ) + src1 |= DSCR_SRC1_SAM(DSCR_xAM_BURST); + else + 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. * A channel attribute update can change this later. @@ -486,10 +511,18 @@ /* If destination output is fifo, set static address. */ 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); } + 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; idscr_cmd0 = cmd0; dp->dscr_cmd1 = cmd1; @@ -498,6 +531,7 @@ dp->dscr_dest0 = dest0; dp->dscr_dest1 = dest1; dp->dscr_stat = 0; + dp->sw_context = dp->sw_status = 0; dp->dscr_nxtptr = DSCR_NXTPTR(virt_to_phys(dp + 1)); dp++; } @@ -510,13 +544,14 @@ return (u32)(ctp->chan_desc_base); } +EXPORT_SYMBOL(au1xxx_dbdma_ring_alloc); /* Put a source buffer into the DMA ring. * This updates the source pointer and byte count. Normally used * for memory to fifo transfers. */ 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; au1x_ddma_desc_t *dp; @@ -543,24 +578,40 @@ */ dp->dscr_source0 = virt_to_phys(buf); dp->dscr_cmd1 = nbytes; - dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */ - ctp->chan_ptr->ddma_dbell = 0xffffffff; /* Make it go */ - + /* Check flags */ + 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. */ 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 nbytes; } +EXPORT_SYMBOL(_au1xxx_dbdma_put_source); /* Put a destination buffer into the DMA ring. * This updates the destination pointer and byte count. Normally used * to place an empty buffer into the ring for fifo to memory transfers. */ 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; au1x_ddma_desc_t *dp; @@ -582,11 +633,33 @@ if (dp->dscr_cmd0 & DSCR_CMD0_V) 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_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 */ + au_sync(); + dma_cache_wback_inv(dp, sizeof(dp)); + ctp->chan_ptr->ddma_dbell = 0; /* Get next descriptor pointer. */ @@ -596,6 +669,7 @@ */ return nbytes; } +EXPORT_SYMBOL(_au1xxx_dbdma_put_dest); /* Get a destination buffer into the DMA ring. * Normally used to get a full buffer from the ring during fifo @@ -645,7 +719,7 @@ au1xxx_dbdma_stop(u32 chanid) { chan_tab_t *ctp; - volatile au1x_dma_chan_t *cp; + au1x_dma_chan_t *cp; int halt_timeout = 0; ctp = *((chan_tab_t **)chanid); @@ -665,6 +739,7 @@ cp->ddma_stat |= (DDMA_STAT_DB | DDMA_STAT_V); au_sync(); } +EXPORT_SYMBOL(au1xxx_dbdma_stop); /* Start using the current descriptor pointer. If the dbdma encounters * a not valid descriptor, it will stop. In this case, we can just @@ -674,17 +749,17 @@ au1xxx_dbdma_start(u32 chanid) { chan_tab_t *ctp; - volatile au1x_dma_chan_t *cp; + au1x_dma_chan_t *cp; ctp = *((chan_tab_t **)chanid); - cp = ctp->chan_ptr; cp->ddma_desptr = virt_to_phys(ctp->cur_ptr); cp->ddma_cfg |= DDMA_CFG_EN; /* Enable channel */ au_sync(); - cp->ddma_dbell = 0xffffffff; /* Make it go */ + cp->ddma_dbell = 0; au_sync(); } +EXPORT_SYMBOL(au1xxx_dbdma_start); void au1xxx_dbdma_reset(u32 chanid) @@ -703,15 +778,21 @@ do { 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)); } while (dp != ctp->chan_desc_base); } +EXPORT_SYMBOL(au1xxx_dbdma_reset); u32 au1xxx_get_dma_residue(u32 chanid) { chan_tab_t *ctp; - volatile au1x_dma_chan_t *cp; + au1x_dma_chan_t *cp; u32 rv; ctp = *((chan_tab_t **)chanid); @@ -746,15 +827,16 @@ kfree(ctp); } +EXPORT_SYMBOL(au1xxx_dbdma_chan_free); static void dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - u32 intstat; + u32 intstat, flags; u32 chan_index; chan_tab_t *ctp; au1x_ddma_desc_t *dp; - volatile au1x_dma_chan_t *cp; + au1x_dma_chan_t *cp; intstat = dbdma_gptr->ddma_intstat; au_sync(); @@ -773,18 +855,26 @@ (ctp->chan_callback)(irq, ctp->chan_callparam, regs); ctp->cur_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); - } -static void -au1xxx_dbdma_init(void) +static void au1xxx_dbdma_init(void) { + int irq_nr; + dbdma_gptr->ddma_config = 0; dbdma_gptr->ddma_throttle = 0; dbdma_gptr->ddma_inten = 0xffff; 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)) printk("Can't get 1550 dbdma irq"); } @@ -795,7 +885,8 @@ chan_tab_t *ctp; au1x_ddma_desc_t *dp; dbdev_tab_t *stp, *dtp; - volatile au1x_dma_chan_t *cp; + au1x_dma_chan_t *cp; + u32 i = 0; ctp = *((chan_tab_t **)chanid); stp = ctp->chan_src; @@ -820,15 +911,64 @@ dp = ctp->chan_desc_base; do { - printk("dp %08x, cmd0 %08x, cmd1 %08x\n", - (u32)dp, dp->dscr_cmd0, dp->dscr_cmd1); - printk("src0 %08x, src1 %08x, dest0 %08x\n", - dp->dscr_source0, dp->dscr_source1, dp->dscr_dest0); - printk("dest1 %08x, stat %08x, nxtptr %08x\n", - dp->dscr_dest1, dp->dscr_stat, dp->dscr_nxtptr); + printk("Dp[%d]= %08x, cmd0 %08x, cmd1 %08x\n", + i++, (u32)dp, dp->dscr_cmd0, dp->dscr_cmd1); + printk("src0 %08x, src1 %08x, dest0 %08x, dest1 %08x\n", + dp->dscr_source0, dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1); + printk("stat %08x, nxtptr %08x\n", + dp->dscr_stat, dp->dscr_nxtptr); dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); } 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) */ diff -Nur linux-2.4.30/arch/mips/au1000/common/gpio.c linux-2.4.30-mips/arch/mips/au1000/common/gpio.c --- linux-2.4.30/arch/mips/au1000/common/gpio.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.30-mips/arch/mips/au1000/common/gpio.c 2005-01-30 09:01:27.000000000 +0100 @@ -0,0 +1,118 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#define gpio1 sys +#if !defined(CONFIG_SOC_AU1000) +static AU1X00_GPIO2 * const gpio2 = (AU1X00_GPIO2 *)GPIO2_BASE; + +#define GPIO2_OUTPUT_ENABLE_MASK 0x00010000 + +int au1xxx_gpio2_read(int signal) +{ + signal -= 200; +/* gpio2->dir &= ~(0x01 << signal); //Set GPIO to input */ + return ((gpio2->pinstate >> signal) & 0x01); +} + +void au1xxx_gpio2_write(int signal, int value) +{ + signal -= 200; + + gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << signal) | + (value << signal); +} + +void au1xxx_gpio2_tristate(int signal) +{ + signal -= 200; + gpio2->dir &= ~(0x01 << signal); /* Set GPIO to input */ +} +#endif + +int au1xxx_gpio1_read(int signal) +{ +/* gpio1->trioutclr |= (0x01 << signal); */ + return ((gpio1->pinstaterd >> signal) & 0x01); +} + +void au1xxx_gpio1_write(int signal, int value) +{ + if(value) + gpio1->outputset = (0x01 << signal); + else + gpio1->outputclr = (0x01 << signal); /* Output a Zero */ +} + +void au1xxx_gpio1_tristate(int signal) +{ + gpio1->trioutclr = (0x01 << signal); /* Tristate signal */ +} + + +int au1xxx_gpio_read(int signal) +{ + if(signal >= 200) +#if defined(CONFIG_SOC_AU1000) + return 0; +#else + return au1xxx_gpio2_read(signal); +#endif + else + return au1xxx_gpio1_read(signal); +} + +void au1xxx_gpio_write(int signal, int value) +{ + if(signal >= 200) +#if defined(CONFIG_SOC_AU1000) + ; +#else + au1xxx_gpio2_write(signal, value); +#endif + else + au1xxx_gpio1_write(signal, value); +} + +void au1xxx_gpio_tristate(int signal) +{ + if(signal >= 200) +#if defined(CONFIG_SOC_AU1000) + ; +#else + au1xxx_gpio2_tristate(signal); +#endif + else + au1xxx_gpio1_tristate(signal); +} + +void au1xxx_gpio1_set_inputs(void) +{ + gpio1->pininputen = 0; +} + +EXPORT_SYMBOL(au1xxx_gpio1_set_inputs); +EXPORT_SYMBOL(au1xxx_gpio_tristate); +EXPORT_SYMBOL(au1xxx_gpio_write); +EXPORT_SYMBOL(au1xxx_gpio_read); diff -Nur linux-2.4.30/arch/mips/au1000/common/irq.c linux-2.4.30-mips/arch/mips/au1000/common/irq.c --- linux-2.4.30/arch/mips/au1000/common/irq.c 2005-01-19 15:09:26.000000000 +0100 +++ linux-2.4.30-mips/arch/mips/au1000/common/irq.c 2005-03-13 08:56:57.000000000 +0100 @@ -303,8 +303,30 @@ }; #ifdef CONFIG_PM -void startup_match20_interrupt(void) +void startup_match20_interrupt(void (*handler)(int, void *, struct pt_regs *)) { + static struct irqaction action; + /* This is a big problem.... since we didn't use request_irq + when kernel/irq.c calls probe_irq_xxx this interrupt will + be probed for usage. This will end up disabling the device :( + + Give it a bogus "action" pointer -- this will keep it from + getting auto-probed! + + By setting the status to match that of request_irq() we + can avoid it. --cgray + */ + action.dev_id = handler; + action.flags = 0; + action.mask = 0; + action.name = "Au1xxx TOY"; + action.handler = handler; + action.next = NULL; + + irq_desc[AU1000_TOY_MATCH2_INT].action = &action; + irq_desc[AU1000_TOY_MATCH2_INT].status + &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); + local_enable_irq(AU1000_TOY_MATCH2_INT); } #endif @@ -508,6 +530,7 @@ if (!intc0_req0) return; +#ifdef AU1000_USB_DEV_REQ_INT /* * Because of the tight timing of SETUP token to reply * transactions, the USB devices-side packet complete @@ -518,6 +541,7 @@ do_IRQ(AU1000_USB_DEV_REQ_INT, regs); return; } +#endif irq = au_ffs(intc0_req0) - 1; intc0_req0 &= ~(1<bus->number; unsigned int dev_fn = dev->devfn; @@ -170,7 +171,6 @@ unsigned long offset, status; unsigned long cfg_base; unsigned long flags; - int error = PCIBIOS_SUCCESSFUL; unsigned long entryLo0, entryLo1; if (device > 19) { @@ -205,9 +205,8 @@ last_entryLo0 = last_entryLo1 = 0xffffffff; } - /* Since the Au1xxx doesn't do the idsel timing exactly to spec, - * many board vendors implement their own off-chip idsel, so call - * it now. If it doesn't succeed, may as well bail out at this point. + /* Allow board vendors to implement their own off-chip idsel. + * If it doesn't succeed, may as well bail out at this point. */ if (board_pci_idsel) { if (board_pci_idsel(device, 1) == 0) { @@ -271,8 +270,11 @@ } local_irq_restore(flags); - return error; +#else + /* Fake out Config space access with no responder */ + *data = 0xFFFFFFFF; #endif + return error; } #endif diff -Nur linux-2.4.30/arch/mips/au1000/common/power.c linux-2.4.30-mips/arch/mips/au1000/common/power.c --- linux-2.4.30/arch/mips/au1000/common/power.c 2005-01-19 15:09:26.000000000 +0100 +++ linux-2.4.30-mips/arch/mips/au1000/common/power.c 2005-04-07 02:37:19.000000000 +0200 @@ -50,7 +50,6 @@ static void calibrate_delay(void); -extern void set_au1x00_speed(unsigned int new_freq); extern unsigned int get_au1x00_speed(void); extern unsigned long get_au1x00_uart_baud_base(void); extern void set_au1x00_uart_baud_base(unsigned long new_baud_base); @@ -116,6 +115,7 @@ sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK); sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL); +#ifndef CONFIG_SOC_AU1200 /* Shutdown USB host/device. */ sleep_usbhost_enable = au_readl(USB_HOST_CONFIG); @@ -127,6 +127,7 @@ sleep_usbdev_enable = au_readl(USBD_ENABLE); au_writel(0, USBD_ENABLE); au_sync(); +#endif /* Save interrupt controller state. */ @@ -212,14 +213,12 @@ int au_sleep(void) { unsigned long wakeup, flags; - extern void save_and_sleep(void); + extern unsigned int save_and_sleep(void); spin_lock_irqsave(&pm_lock,flags); save_core_regs(); - flush_cache_all(); - /** The code below is all system dependent and we should probably ** have a function call out of here to set this up. You need ** to configure the GPIO or timer interrupts that will bring @@ -227,27 +226,26 @@ ** For testing, the TOY counter wakeup is useful. **/ -#if 0 +#if 1 au_writel(au_readl(SYS_PINSTATERD) & ~(1 << 11), SYS_PINSTATERD); /* gpio 6 can cause a wake up event */ wakeup = au_readl(SYS_WAKEMSK); wakeup &= ~(1 << 8); /* turn off match20 wakeup */ - wakeup |= 1 << 6; /* turn on gpio 6 wakeup */ + wakeup = 1 << 5; /* turn on gpio 6 wakeup */ #else - /* For testing, allow match20 to wake us up. - */ + /* For testing, allow match20 to wake us up. */ #ifdef SLEEP_TEST_TIMEOUT wakeup_counter0_set(sleep_ticks); #endif wakeup = 1 << 8; /* turn on match20 wakeup */ wakeup = 0; #endif - au_writel(1, SYS_WAKESRC); /* clear cause */ + au_writel(0, SYS_WAKESRC); /* clear cause */ au_sync(); au_writel(wakeup, SYS_WAKEMSK); au_sync(); - + DPRINTK("Entering sleep!\n"); save_and_sleep(); /* after a wakeup, the cpu vectors back to 0x1fc00000 so @@ -255,6 +253,7 @@ */ restore_core_regs(); spin_unlock_irqrestore(&pm_lock, flags); + DPRINTK("Leaving sleep!\n"); return 0; } @@ -285,7 +284,6 @@ if (retval) return retval; - au_sleep(); retval = pm_send_all(PM_RESUME, (void *) 0); } @@ -296,7 +294,6 @@ void *buffer, size_t * len) { int retval = 0; - void au1k_wait(void); if (!write) { *len = 0; @@ -305,119 +302,9 @@ if (retval) return retval; suspend_mode = 1; - au1k_wait(); - retval = pm_send_all(PM_RESUME, (void *) 0); - } - return retval; -} - -static int pm_do_freq(ctl_table * ctl, int write, struct file *file, - void *buffer, size_t * len) -{ - int retval = 0, i; - unsigned long val, pll; -#define TMPBUFLEN 64 -#define MAX_CPU_FREQ 396 - char buf[TMPBUFLEN], *p; - unsigned long flags, intc0_mask, intc1_mask; - unsigned long old_baud_base, old_cpu_freq, baud_rate, old_clk, - old_refresh; - unsigned long new_baud_base, new_cpu_freq, new_clk, new_refresh; - - spin_lock_irqsave(&pm_lock, flags); - if (!write) { - *len = 0; - } else { - /* Parse the new frequency */ - if (*len > TMPBUFLEN - 1) { - spin_unlock_irqrestore(&pm_lock, flags); - return -EFAULT; - } - if (copy_from_user(buf, buffer, *len)) { - spin_unlock_irqrestore(&pm_lock, flags); - return -EFAULT; - } - buf[*len] = 0; - p = buf; - val = simple_strtoul(p, &p, 0); - if (val > MAX_CPU_FREQ) { - spin_unlock_irqrestore(&pm_lock, flags); - return -EFAULT; - } - - pll = val / 12; - if ((pll > 33) || (pll < 7)) { /* 396 MHz max, 84 MHz min */ - /* revisit this for higher speed cpus */ - spin_unlock_irqrestore(&pm_lock, flags); - return -EFAULT; - } - - old_baud_base = get_au1x00_uart_baud_base(); - old_cpu_freq = get_au1x00_speed(); - - new_cpu_freq = pll * 12 * 1000000; - new_baud_base = (new_cpu_freq / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16)); - set_au1x00_speed(new_cpu_freq); - set_au1x00_uart_baud_base(new_baud_base); - - old_refresh = au_readl(MEM_SDREFCFG) & 0x1ffffff; - new_refresh = - ((old_refresh * new_cpu_freq) / - old_cpu_freq) | (au_readl(MEM_SDREFCFG) & ~0x1ffffff); - - au_writel(pll, SYS_CPUPLL); - au_sync_delay(1); - au_writel(new_refresh, MEM_SDREFCFG); - au_sync_delay(1); - - for (i = 0; i < 4; i++) { - if (au_readl - (UART_BASE + UART_MOD_CNTRL + - i * 0x00100000) == 3) { - old_clk = - au_readl(UART_BASE + UART_CLK + - i * 0x00100000); - // baud_rate = baud_base/clk - baud_rate = old_baud_base / old_clk; - /* we won't get an exact baud rate and the error - * could be significant enough that our new - * calculation will result in a clock that will - * give us a baud rate that's too far off from - * what we really want. - */ - if (baud_rate > 100000) - baud_rate = 115200; - else if (baud_rate > 50000) - baud_rate = 57600; - else if (baud_rate > 30000) - baud_rate = 38400; - else if (baud_rate > 17000) - baud_rate = 19200; - else - (baud_rate = 9600); - // new_clk = new_baud_base/baud_rate - new_clk = new_baud_base / baud_rate; - au_writel(new_clk, - UART_BASE + UART_CLK + - i * 0x00100000); - au_sync_delay(10); - } - } + retval = pm_send_all(PM_RESUME, (void *) 0); } - - - /* We don't want _any_ interrupts other than - * match20. Otherwise our calibrate_delay() - * calculation will be off, potentially a lot. - */ - intc0_mask = save_local_and_disable(0); - intc1_mask = save_local_and_disable(1); - local_enable_irq(AU1000_TOY_MATCH2_INT); - spin_unlock_irqrestore(&pm_lock, flags); - calibrate_delay(); - restore_local_and_enable(0, intc0_mask); - restore_local_and_enable(1, intc1_mask); return retval; } @@ -425,7 +312,6 @@ static struct ctl_table pm_table[] = { {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, &pm_do_suspend}, {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &pm_do_sleep}, - {CTL_ACPI, "freq", NULL, 0, 0600, NULL, &pm_do_freq}, {0} }; diff -Nur linux-2.4.30/arch/mips/au1000/common/reset.c linux-2.4.30-mips/arch/mips/au1000/common/reset.c --- linux-2.4.30/arch/mips/au1000/common/reset.c 2005-01-19 15:09:26.000000000 +0100 +++ linux-2.4.30-mips/arch/mips/au1000/common/reset.c 2005-03-19 08:17:51.000000000 +0100 @@ -37,8 +37,6 @@ #include #include -extern int au_sleep(void); - void au1000_restart(char *command) { /* Set all integrated peripherals to disabled states */ @@ -144,6 +142,26 @@ au_writel(0x00, 0xb1900064); /* sys_auxpll */ au_writel(0x00, 0xb1900100); /* sys_pininputen */ break; + case 0x04000000: /* Au1200 */ + au_writel(0x00, 0xb400300c); /* ddma */ + au_writel(0x00, 0xb1a00004); /* psc 0 */ + au_writel(0x00, 0xb1b00004); /* psc 1 */ + au_writel(0x00d02000, 0xb4020004); /* ehci, ohci, udc, otg */ + au_writel(0x00, 0xb5000004); /* lcd */ + au_writel(0x00, 0xb060000c); /* sd0 */ + au_writel(0x00, 0xb068000c); /* sd1 */ + au_writel(0x00, 0xb1100100); /* swcnt */ + au_writel(0x00, 0xb0300000); /* aes */ + au_writel(0x00, 0xb4004000); /* cim */ + au_writel(0x00, 0xb1100100); /* uart0_enable */ + au_writel(0x00, 0xb1200100); /* uart1_enable */ + au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */ + au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */ + au_writel(0x00, 0xb1900028); /* sys_clksrc */ + au_writel(0x10, 0xb1900060); /* sys_cpupll */ + au_writel(0x00, 0xb1900064); /* sys_auxpll */ + au_writel(0x00, 0xb1900100); /* sys_pininputen */ + break; default: break; @@ -163,32 +181,23 @@ void au1000_halt(void) { -#if defined(CONFIG_MIPS_PB1550) - /* power off system */ - printk("\n** Powering off Pb1550\n"); - au_writew(au_readw(0xAF00001C) | (3<<14), 0xAF00001C); - au_sync(); - while(1); /* should not get here */ -#endif - printk(KERN_NOTICE "\n** You can safely turn off the power\n"); -#ifdef CONFIG_MIPS_MIRAGE - au_writel((1 << 26) | (1 << 10), GPIO2_OUTPUT); -#endif -#ifdef CONFIG_PM - au_sleep(); - - /* should not get here */ - printk(KERN_ERR "Unable to put cpu in sleep mode\n"); - while(1); -#else - while (1) + /* Use WAIT in a low-power infinite spin loop */ + while (1) { __asm__(".set\tmips3\n\t" "wait\n\t" ".set\tmips0"); -#endif + } } void au1000_power_off(void) { + extern void board_power_off (void); + + printk(KERN_NOTICE "\n** You can safely turn off the power\n"); + + /* Give board a chance to power-off */ + board_power_off(); + + /* If board can't power-off, spin forever */ au1000_halt(); } diff -Nur linux-2.4.30/arch/mips/au1000/common/setup.c linux-2.4.30-mips/arch/mips/au1000/common/setup.c --- linux-2.4.30/arch/mips/au1000/common/setup.c 2005-01-19 15:09:26.000000000 +0100 +++ linux-2.4.30-mips/arch/mips/au1000/common/setup.c 2005-01-30 09:01:27.000000000 +0100 @@ -174,6 +174,40 @@ initrd_end = (unsigned long)&__rd_end; #endif +#if defined(CONFIG_SOC_AU1200) +#ifdef CONFIG_USB_EHCI_HCD + if ((argptr = strstr(argptr, "usb_ehci=")) == NULL) { + char usb_args[80]; + argptr = prom_getcmdline(); + memset(usb_args, 0, sizeof(usb_args)); + sprintf(usb_args, " usb_ehci=base:0x%x,len:0x%x,irq:%d", + USB_EHCI_BASE, USB_EHCI_LEN, AU1000_USB_HOST_INT); + strcat(argptr, usb_args); + } +#ifdef CONFIG_USB_AMD5536UDC + /* enable EHC + OHC + UDC clocks, memory and bus mastering */ +/* au_writel( 0x00DF207F, USB_MSR_BASE + 4); */ + au_writel( 0xC0DF207F, USB_MSR_BASE + 4); // incl. prefetch +#else + /* enable EHC + OHC clocks, memory and bus mastering */ +/* au_writel( 0x00DB200F, USB_MSR_BASE + 4); */ + au_writel( 0xC0DB200F, USB_MSR_BASE + 4); /* incl. prefetch */ +#endif + udelay(1000); + +#else /* CONFIG_USB_EHCI_HCD */ + +#ifdef CONFIG_USB_AMD5536UDC +#ifndef CONFIG_USB_OHCI + /* enable UDC clocks, memory and bus mastering */ +/* au_writel( 0x00DC2070, USB_MSR_BASE + 4); */ + au_writel( 0xC0DC2070, USB_MSR_BASE + 4); // incl. prefetch + udelay(1000); +#endif +#endif +#endif /* CONFIG_USB_EHCI_HCD */ +#endif /* CONFIG_SOC_AU1200 */ + #if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) #ifdef CONFIG_USB_OHCI if ((argptr = strstr(argptr, "usb_ohci=")) == NULL) { @@ -187,19 +221,38 @@ #endif #ifdef CONFIG_USB_OHCI - // enable host controller and wait for reset done +#if defined(CONFIG_SOC_AU1200) +#ifndef CONFIG_USB_EHCI_HCD +#ifdef CONFIG_USB_AMD5536UDC + /* enable OHC + UDC clocks, memory and bus mastering */ +/* au_writel( 0x00DD2073, USB_MSR_BASE + 4); */ + au_writel( 0xC0DD2073, USB_MSR_BASE + 4); // incl. prefetch +#else + /* enable OHC clocks, memory and bus mastering */ + au_writel( 0x00D12003, USB_MSR_BASE + 4); +#endif + udelay(1000); +printk("DEBUG: Reading Au1200 USB2 reg 0x%x\n", au_readl(USB_MSR_BASE + 4)); +#endif +#else + /* Au1000, Au1500, Au1100, Au1550 */ + /* enable host controller and wait for reset done */ au_writel(0x08, USB_HOST_CONFIG); udelay(1000); au_writel(0x0E, USB_HOST_CONFIG); udelay(1000); - au_readl(USB_HOST_CONFIG); // throw away first read + au_readl(USB_HOST_CONFIG); /* throw away first read */ while (!(au_readl(USB_HOST_CONFIG) & 0x10)) au_readl(USB_HOST_CONFIG); +#endif /* CONFIG_SOC_AU1200 */ #endif -#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) +#else + +#endif /* defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) */ + #ifdef CONFIG_FB - // Needed if PCI video card in use + /* Needed if PCI video card in use */ conswitchp = &dummy_con; #endif @@ -209,8 +262,7 @@ #endif #ifdef CONFIG_BLK_DEV_IDE - /* Board setup takes precedence for unique devices. - */ + /* Board setup takes precedence for unique devices. */ if ((ide_ops == NULL) || (ide_ops == &no_ide_ops)) ide_ops = &std_ide_ops; #endif diff -Nur linux-2.4.30/arch/mips/au1000/common/sleeper.S linux-2.4.30-mips/arch/mips/au1000/common/sleeper.S --- linux-2.4.30/arch/mips/au1000/common/sleeper.S 2004-02-18 14:36:30.000000000 +0100 +++ linux-2.4.30-mips/arch/mips/au1000/common/sleeper.S 2005-01-30 09:01:27.000000000 +0100 @@ -15,17 +15,48 @@ #include #include #include +#include + +/* + * Note: This file is *not* conditional on CONFIG_PM since Alchemy sleep + * need not be tied to any particular power management scheme. + */ + + .extern ___flush_cache_all .text - .set macro - .set noat .align 5 -/* Save all of the processor general registers and go to sleep. - * A wakeup condition will get us back here to restore the registers. +/* + * Save the processor general registers and go to sleep. A wakeup + * condition will get us back here to restore the registers. */ -LEAF(save_and_sleep) +/* still need to fix alignment issues here */ +save_and_sleep_frmsz = 48 +NESTED(save_and_sleep, save_and_sleep_frmsz, ra) + .set noreorder + .set nomacro + .set noat + subu sp, save_and_sleep_frmsz + sw ra, save_and_sleep_frmsz-4(sp) + sw s0, save_and_sleep_frmsz-8(sp) + sw s1, save_and_sleep_frmsz-12(sp) + sw s2, save_and_sleep_frmsz-16(sp) + sw s3, save_and_sleep_frmsz-20(sp) + sw s4, save_and_sleep_frmsz-24(sp) + sw s5, save_and_sleep_frmsz-28(sp) + sw s6, save_and_sleep_frmsz-32(sp) + sw s7, save_and_sleep_frmsz-36(sp) + sw s8, save_and_sleep_frmsz-40(sp) + sw gp, save_and_sleep_frmsz-44(sp) + + /* We only need to save the registers that the calling function + * hasn't saved for us. 0 is always zero. 8 - 15, 24 and 25 are + * temporaries and can be used without saving. 26 and 27 are reserved + * for interrupt/trap handling and expected to change. 29 is the + * stack pointer which is handled as a special case here. + */ subu sp, PT_SIZE sw $1, PT_R1(sp) sw $2, PT_R2(sp) @@ -34,14 +65,6 @@ sw $5, PT_R5(sp) sw $6, PT_R6(sp) sw $7, PT_R7(sp) - sw $8, PT_R8(sp) - sw $9, PT_R9(sp) - sw $10, PT_R10(sp) - sw $11, PT_R11(sp) - sw $12, PT_R12(sp) - sw $13, PT_R13(sp) - sw $14, PT_R14(sp) - sw $15, PT_R15(sp) sw $16, PT_R16(sp) sw $17, PT_R17(sp) sw $18, PT_R18(sp) @@ -50,32 +73,47 @@ sw $21, PT_R21(sp) sw $22, PT_R22(sp) sw $23, PT_R23(sp) - sw $24, PT_R24(sp) - sw $25, PT_R25(sp) - sw $26, PT_R26(sp) - sw $27, PT_R27(sp) sw $28, PT_R28(sp) - sw $29, PT_R29(sp) sw $30, PT_R30(sp) sw $31, PT_R31(sp) +#define PT_C0STATUS PT_LO +#define PT_CONTEXT PT_HI +#define PT_PAGEMASK PT_EPC +#define PT_CONFIG PT_BVADDR mfc0 k0, CP0_STATUS - sw k0, 0x20(sp) + sw k0, PT_C0STATUS(sp) // 0x20 mfc0 k0, CP0_CONTEXT - sw k0, 0x1c(sp) + sw k0, PT_CONTEXT(sp) // 0x1c mfc0 k0, CP0_PAGEMASK - sw k0, 0x18(sp) + sw k0, PT_PAGEMASK(sp) // 0x18 mfc0 k0, CP0_CONFIG - sw k0, 0x14(sp) + sw k0, PT_CONFIG(sp) // 0x14 + + .set macro + .set at + + li t0, SYS_SLPPWR + sw zero, 0(t0) /* Get the processor ready to sleep */ + sync /* Now set up the scratch registers so the boot rom will * return to this point upon wakeup. + * sys_scratch0 : SP + * sys_scratch1 : RA + */ + li t0, SYS_SCRATCH0 + li t1, SYS_SCRATCH1 + sw sp, 0(t0) + la k0, resume_from_sleep + sw k0, 0(t1) + +/* + * Flush DCACHE to make sure context is in memory */ - la k0, 1f - lui k1, 0xb190 - ori k1, 0x18 - sw sp, 0(k1) - ori k1, 0x1c - sw k0, 0(k1) + la t1,___flush_cache_all /* _flush_cache_all is a function pointer */ + lw t0,0(t1) + jal t0 + nop /* Put SDRAM into self refresh. Preload instructions into cache, * issue a precharge, then auto refresh, then sleep commands to it. @@ -88,30 +126,65 @@ cache 0x14, 96(t0) .set mips0 + /* Put SDRAM to sleep */ sdsleep: - lui k0, 0xb400 - sw zero, 0x001c(k0) /* Precharge */ - sw zero, 0x0020(k0) /* Auto refresh */ - sw zero, 0x0030(k0) /* SDRAM sleep */ + li a0, MEM_PHYS_ADDR + or a0, a0, 0xA0000000 +#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100) || defined(CONFIG_SOC_AU1500) + lw k0, MEM_SDMODE0(a0) + sw zero, MEM_SDPRECMD(a0) /* Precharge */ + sw zero, MEM_SDAUTOREF(a0) /* Auto Refresh */ + sw zero, MEM_SDSLEEP(a0) /* Sleep */ sync - - lui k1, 0xb190 - sw zero, 0x0078(k1) /* get ready to sleep */ +#endif +#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) + sw zero, MEM_SDPRECMD(a0) /* Precharge */ + sw zero, MEM_SDSREF(a0) + + #lw t0, MEM_SDSTAT(a0) + #and t0, t0, 0x01000000 + li t0, 0x01000000 +refresh_not_set: + lw t1, MEM_SDSTAT(a0) + and t2, t1, t0 + beq zero, t2, refresh_not_set + nop + + li t0, ~0x30000000 + lw t1, MEM_SDCONFIGA(a0) + and t1, t0, t1 + sw t1, MEM_SDCONFIGA(a0) sync - sw zero, 0x007c(k1) /* Put processor to sleep */ +#endif + + li t0, SYS_SLEEP + sw zero, 0(t0) /* Put processor to sleep */ sync + nop + nop + nop + nop + nop + nop + nop + nop + /* This is where we return upon wakeup. * Reload all of the registers and return. */ -1: nop - lw k0, 0x20(sp) +resume_from_sleep: + nop + .set nomacro + .set noat + + lw k0, PT_C0STATUS(sp) // 0x20 mtc0 k0, CP0_STATUS - lw k0, 0x1c(sp) + lw k0, PT_CONTEXT(sp) // 0x1c mtc0 k0, CP0_CONTEXT - lw k0, 0x18(sp) + lw k0, PT_PAGEMASK(sp) // 0x18 mtc0 k0, CP0_PAGEMASK - lw k0, 0x14(sp) + lw k0, PT_CONFIG(sp) // 0x14 mtc0 k0, CP0_CONFIG lw $1, PT_R1(sp) lw $2, PT_R2(sp) @@ -120,14 +193,6 @@ lw $5, PT_R5(sp) lw $6, PT_R6(sp) lw $7, PT_R7(sp) - lw $8, PT_R8(sp) - lw $9, PT_R9(sp) - lw $10, PT_R10(sp) - lw $11, PT_R11(sp) - lw $12, PT_R12(sp) - lw $13, PT_R13(sp) - lw $14, PT_R14(sp) - lw $15, PT_R15(sp) lw $16, PT_R16(sp) lw $17, PT_R17(sp) lw $18, PT_R18(sp) @@ -136,15 +201,36 @@ lw $21, PT_R21(sp) lw $22, PT_R22(sp) lw $23, PT_R23(sp) - lw $24, PT_R24(sp) - lw $25, PT_R25(sp) - lw $26, PT_R26(sp) - lw $27, PT_R27(sp) lw $28, PT_R28(sp) - lw $29, PT_R29(sp) lw $30, PT_R30(sp) lw $31, PT_R31(sp) + + .set macro + .set at + + /* clear the wake source, but save it as the return value of the function */ + li t0, SYS_WAKESRC + lw v0, 0(t0) + sw v0, PT_R2(sp) + sw zero, 0(t0) + addiu sp, PT_SIZE + lw gp, save_and_sleep_frmsz-44(sp) + lw s8, save_and_sleep_frmsz-40(sp) + lw s7, save_and_sleep_frmsz-36(sp) + lw s6, save_and_sleep_frmsz-32(sp) + lw s5, save_and_sleep_frmsz-28(sp) + lw s4, save_and_sleep_frmsz-24(sp) + lw s3, save_and_sleep_frmsz-20(sp) + lw s2, save_and_sleep_frmsz-16(sp) + lw s1, save_and_sleep_frmsz-12(sp) + lw s0, save_and_sleep_frmsz-8(sp) + lw ra, save_and_sleep_frmsz-4(sp) + + addu sp, save_and_sleep_frmsz jr ra + nop + .set reorder END(save_and_sleep) + diff -Nur linux-2.4.30/arch/mips/au1000/common/time.c linux-2.4.30-mips/arch/mips/au1000/common/time.c --- linux-2.4.30/arch/mips/au1000/common/time.c 2005-01-19 15:09:26.000000000 +0100 +++ linux-2.4.30-mips/arch/mips/au1000/common/time.c 2005-04-08 10:33:17.000000000 +0200 @@ -50,7 +50,6 @@ #include #include -extern void startup_match20_interrupt(void); extern void do_softirq(void); extern volatile unsigned long wall_jiffies; unsigned long missed_heart_beats = 0; @@ -59,14 +58,14 @@ static unsigned long r4k_cur; /* What counter should be at next timer irq */ extern rwlock_t xtime_lock; int no_au1xxx_32khz; -void (*au1k_wait_ptr)(void); +extern int allow_au1k_wait; /* default off for CP0 Counter */ /* Cycle counter value at the previous timer interrupt.. */ static unsigned int timerhi = 0, timerlo = 0; #ifdef CONFIG_PM #define MATCH20_INC 328 -extern void startup_match20_interrupt(void); +extern void startup_match20_interrupt(void (*handler)(int, void *, struct pt_regs *)); static unsigned long last_pc0, last_match20; #endif @@ -385,7 +384,6 @@ { unsigned int est_freq; extern unsigned long (*do_gettimeoffset)(void); - extern void au1k_wait(void); printk("calculating r4koff... "); r4k_offset = cal_r4koff(); @@ -437,9 +435,6 @@ au_writel(0, SYS_TOYWRITE); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); - au_writel(au_readl(SYS_WAKEMSK) | (1<<8), SYS_WAKEMSK); - au_writel(~0, SYS_WAKESRC); - au_sync(); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); /* setup match20 to interrupt once every 10ms */ @@ -447,13 +442,13 @@ au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); au_sync(); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); - startup_match20_interrupt(); + startup_match20_interrupt(counter0_irq); do_gettimeoffset = do_fast_pm_gettimeoffset; /* We can use the real 'wait' instruction. */ - au1k_wait_ptr = au1k_wait; + allow_au1k_wait = 1; } #else diff -Nur linux-2.4.30/arch/mips/au1000/db1x00/Makefile linux-2.4.30-mips/arch/mips/au1000/db1x00/Makefile --- linux-2.4.30/arch/mips/au1000/db1x00/Makefile 2005-01-19 15:09:26.000000000 +0100 +++ linux-2.4.30-mips/arch/mips/au1000/db1x00/Makefile 2005-01-30 09:06:19.000000000 +0100 @@ -17,4 +17,11 @@ obj-y := init.o board_setup.o irqmap.o obj-$(CONFIG_WM97XX_COMODULE) += mirage_ts.o +ifdef CONFIG_MIPS_DB1100 +ifdef CONFIG_MMC +obj-y += mmc_support.o +export-objs += mmc_support.o +endif +endif + include $(TOPDIR)/Rules.make diff -Nur linux-2.4.30/arch/mips/au1000/db1x00/board_setup.c linux-2.4.30-mips/arch/mips/au1000/db1x00/board_setup.c --- linux-2.4.30/arch/mips/au1000/db1x00/board_setup.c 2005-01-19 15:09:26.000000000 +0100 +++ linux-2.4.30-mips/arch/mips/au1000/db1x00/board_setup.c 2005-03-19 08:17:51.000000000 +0100 @@ -46,10 +46,22 @@ #include #include -extern struct rtc_ops no_rtc_ops; +#if defined(CONFIG_BLK_DEV_IDE_AU1XXX) && defined(CONFIG_MIPS_DB1550) +#include +extern struct ide_ops *ide_ops; +extern struct ide_ops au1xxx_ide_ops; +extern u32 au1xxx_ide_virtbase; +extern u64 au1xxx_ide_physbase; +extern int au1xxx_ide_irq; + +/* Ddma */ +chan_tab_t *ide_read_ch, *ide_write_ch; +u32 au1xxx_ide_ddma_enable = 0, switch4ddma = 1; // PIO+ddma + +dbdev_tab_t new_dbdev_tab_element = { DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }; +#endif /* end CONFIG_BLK_DEV_IDE_AU1XXX */ -/* not correct for db1550 */ -static BCSR * const bcsr = (BCSR *)0xAE000000; +extern struct rtc_ops no_rtc_ops; void board_reset (void) { @@ -57,6 +69,13 @@ au_writel(0x00000000, 0xAE00001C); } +void board_power_off (void) +{ +#ifdef CONFIG_MIPS_MIRAGE + au_writel((1 << 26) | (1 << 10), GPIO2_OUTPUT); +#endif +} + void __init board_setup(void) { u32 pin_func; @@ -108,8 +127,42 @@ au_writel(0x02000200, GPIO2_OUTPUT); #endif +#if defined(CONFIG_AU1XXX_SMC91111) +#define CPLD_CONTROL (0xAF00000C) + { + extern uint32_t au1xxx_smc91111_base; + extern unsigned int au1xxx_smc91111_irq; + extern int au1xxx_smc91111_nowait; + + au1xxx_smc91111_base = 0xAC000300; + au1xxx_smc91111_irq = AU1000_GPIO_8; + au1xxx_smc91111_nowait = 1; + + /* set up the Static Bus timing - only 396Mhz */ + bcsr->resets |= 0x7; + au_writel(0x00010003, MEM_STCFG0); + au_writel(0x000c00c0, MEM_STCFG2); + au_writel(0x85E1900D, MEM_STTIME2); + } +#endif /* end CONFIG_SMC91111 */ au_sync(); +#if defined(CONFIG_BLK_DEV_IDE_AU1XXX) && defined(CONFIG_MIPS_DB1550) + /* + * Iniz IDE parameters + */ + ide_ops = &au1xxx_ide_ops; + au1xxx_ide_irq = DAUGHTER_CARD_IRQ; + au1xxx_ide_physbase = AU1XXX_ATA_PHYS_ADDR; + au1xxx_ide_virtbase = KSEG1ADDR(AU1XXX_ATA_PHYS_ADDR); + + /* + * change PIO or PIO+Ddma + * check the GPIO-6 pin condition. db1550:s6_dot + */ + switch4ddma = (au_readl(SYS_PINSTATERD) & (1 << 6)) ? 1 : 0; +#endif + #ifdef CONFIG_MIPS_DB1000 printk("AMD Alchemy Au1000/Db1000 Board\n"); #endif diff -Nur linux-2.4.30/arch/mips/au1000/db1x00/irqmap.c linux-2.4.30-mips/arch/mips/au1000/db1x00/irqmap.c --- linux-2.4.30/arch/mips/au1000/db1x00/irqmap.c 2005-01-19 15:09:26.000000000 +0100 +++ linux-2.4.30-mips/arch/mips/au1000/db1x00/irqmap.c 2005-01-30 09:06:19.000000000 +0100 @@ -53,6 +53,7 @@ #ifdef CONFIG_MIPS_DB1550 { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 0 IRQ# { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 1 IRQ# + { AU1000_GPIO_8, INTC_INT_LOW_LEVEL, 0 }, // Daughtercard IRQ# #else { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 0 Fully_Interted# { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 0 STSCHG# diff -Nur linux-2.4.30/arch/mips/au1000/db1x00/mmc_support.c linux-2.4.30-mips/arch/mips/au1000/db1x00/mmc_support.c --- linux-2.4.30/arch/mips/au1000/db1x00/mmc_support.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.30-mips/arch/mips/au1000/db1x00/mmc_support.c 2005-01-30 09:07:01.000000000 +0100 @@ -0,0 +1,126 @@ +/* + * BRIEF MODULE DESCRIPTION + * + * MMC support routines for DB1100. + * + * + * Copyright (c) 2003-2004 Embedded Edge, LLC. + * Author: Embedded Edge, LLC. + * Contact: dan@embeddededge.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + + +#include +#include +#include +#include + +#include +#include +#include +#include + + +/* SD/MMC controller support functions */ + +/* + * Detect card. + */ +void mmc_card_inserted(int _n_, int *_res_) +{ + u32 gpios = au_readl(SYS_PINSTATERD); + u32 emptybit = (_n_) ? (1<<20) : (1<<19); + *_res_ = ((gpios & emptybit) == 0); +} + +/* + * Check card write protection. + */ +void mmc_card_writable(int _n_, int *_res_) +{ + BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR; + unsigned long mmc_wp, board_specific; + + if (_n_) { + mmc_wp = BCSR_BOARD_SD1_WP; + } else { + mmc_wp = BCSR_BOARD_SD0_WP; + } + + board_specific = au_readl((unsigned long)(&bcsr->specific)); + + if (!(board_specific & mmc_wp)) {/* low means card writable */ + *_res_ = 1; + } else { + *_res_ = 0; + } +} + +/* + * Apply power to card slot. + */ +void mmc_power_on(int _n_) +{ + BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR; + unsigned long mmc_pwr, board_specific; + + if (_n_) { + mmc_pwr = BCSR_BOARD_SD1_PWR; + } else { + mmc_pwr = BCSR_BOARD_SD0_PWR; + } + + board_specific = au_readl((unsigned long)(&bcsr->specific)); + board_specific |= mmc_pwr; + + au_writel(board_specific, (int)(&bcsr->specific)); + au_sync_delay(1); +} + +/* + * Remove power from card slot. + */ +void mmc_power_off(int _n_) +{ + BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR; + unsigned long mmc_pwr, board_specific; + + if (_n_) { + mmc_pwr = BCSR_BOARD_SD1_PWR; + } else { + mmc_pwr = BCSR_BOARD_SD0_PWR; + } + + board_specific = au_readl((unsigned long)(&bcsr->specific)); + board_specific &= ~mmc_pwr; + + au_writel(board_specific, (int)(&bcsr->specific)); + au_sync_delay(1); +} + +EXPORT_SYMBOL(mmc_card_inserted); +EXPORT_SYMBOL(mmc_card_writable); +EXPORT_SYMBOL(mmc_power_on); +EXPORT_SYMBOL(mmc_power_off); + diff -Nur linux-2.4.30/arch/mips/au1000/ficmmp/Makefile linux-2.4.30-mips/arch/mips/au1000/ficmmp/Makefile --- linux-2.4.30/arch/mips/au1000/ficmmp/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.30-mips/arch/mips/au1000/ficmmp/Makefile 2005-01-30 09:01:27.000000000 +0100 @@ -0,0 +1,25 @@ +# +# Copyright 2000 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# ppopov@mvista.com or source@mvista.com +# +# Makefile for the Alchemy Semiconductor FIC board. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +USE_STANDARD_AS_RULE := true + +O_TARGET := ficmmp.o + +obj-y := init.o board_setup.o irqmap.o au1200_ibutton.o au1xxx_dock.o + +ifdef CONFIG_MMC +obj-y += mmc_support.o +export-objs +=mmc_support.o +endif + + +include $(TOPDIR)/Rules.make diff -Nur linux-2.4.30/arch/mips/au1000/ficmmp/au1200_ibutton.c linux-2.4.30-mips/arch/mips/au1000/ficmmp/au1200_ibutton.c --- linux-2.4.30/arch/mips/au1000/ficmmp/au1200_ibutton.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.30-mips/arch/mips/au1000/ficmmp/au1200_ibutton.c 2005-02-03 07:35:29.000000000 +0100 @@ -0,0 +1,270 @@ +/* ---------------------------------------------------------------------- + * mtwilson_keys.c + * + * Copyright (C) 2003 Intrinsyc Software Inc. + * + * Intel Personal Media Player buttons + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * May 02, 2003 : Initial version [FB] + * + ------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define DRIVER_VERSION "V1.0" +#define DRIVER_AUTHOR "FIC" +#define DRIVER_DESC "FIC Travis Media Player Button Driver" +#define DRIVER_NAME "Au1200Button" + +#define BUTTON_MAIN (1<<1) +#define BUTTON_SELECT (1<<6) +#define BUTTON_GUIDE (1<<12) +#define BUTTON_DOWN (1<<17) +#define BUTTON_LEFT (1<<19) +#define BUTTON_RIGHT (1<<26) +#define BUTTON_UP (1<<28) + +#define BUTTON_MASK (\ + BUTTON_MAIN \ + | BUTTON_SELECT \ + | BUTTON_GUIDE \ + | BUTTON_DOWN \ + | BUTTON_LEFT \ + | BUTTON_RIGHT \ + | BUTTON_UP \ + ) + +#define BUTTON_INVERT (\ + BUTTON_MAIN \ + | 0 \ + | BUTTON_GUIDE \ + | 0 \ + | 0 \ + | 0 \ + | 0 \ + ) + +char button_map[32]={0,KEY_S,0,0,0,0,KEY_ENTER,0,0,0,0,0,KEY_G,0,0,0,0,KEY_DOWN,0,KEY_LEFT,0,0,0,0,0,0,KEY_RIGHT,0,KEY_UP,0,0,0}; +//char button_map[32]={0,0,0,0,0,0,KEY_ENTER,0,0,0,0,0,KEY_G,0,0,0,0,KEY_DOWN,0,KEY_LEFT,0,0,0,0,0,0,KEY_RIGHT,0,KEY_UP,0,0,0}; + +//char button_map[32]={0,KEY_TAB,0,0,0,0,KEY_M,0,0,0,0,0,KEY_S,0,0,0,0,KEY_DOWN,0,KEY_LEFT,0,0,0,0,0,0,KEY_RIGHT,0,KEY_UP,0,0,0}; +//char button_map[32]={0,0,0,0,0,0,KEY_M,0,0,0,0,0,KEY_S,0,0,0,0,KEY_DOWN,0,KEY_LEFT,0,0,0,0,0,0,KEY_RIGHT,0,KEY_UP,0,0,0}; + +#define BUTTON_COUNT (sizeof (button_map) / sizeof (button_map[0])) + +struct input_dev dev; +struct timeval cur_tv; + +static unsigned int old_tv_usec = 0; + +static unsigned int read_button_state(void) +{ + unsigned int state; + + state = au_readl(SYS_PINSTATERD) & BUTTON_MASK; /* get gpio status */ + + state ^= BUTTON_INVERT; /* invert main & guide button */ + + /* printk("au1200_ibutton.c: button state [0x%X]\r\n",state); */ + return state; +} + +//This function returns 0 if the allowed microseconds have elapsed since the last call to ths function, otherwise it returns 1 to indicate a bounce condition +static unsigned int bounce() +{ + + unsigned int elapsed_time; + + do_gettimeofday (&cur_tv); + + if (!old_tv_usec) { + old_tv_usec = cur_tv.tv_usec; + return 0; + } + + if(cur_tv.tv_usec > old_tv_usec) { + /* If there hasn't been rollover */ + elapsed_time = ((cur_tv.tv_usec - old_tv_usec)); + } + else { + /* Accounting for rollover */ + elapsed_time = ((1000000 - old_tv_usec + cur_tv.tv_usec)); + } + + if (elapsed_time > 250000) { + old_tv_usec = 0; /* reset the bounce time */ + return 0; + } + + return 1; +} + +/* button interrupt handler */ +static void button_interrupt(int irq, void *dev, struct pt_regs *regs) +{ + + unsigned int i,bit_mask, key_choice; + u32 button_state; + + /* Report state to upper level */ + + button_state = read_button_state() & BUTTON_MASK; /* get new gpio status */ + + /* Return if this is a repeated (bouncing) event */ + if(bounce()) + return; + + /* we want to make keystrokes */ + for( i=0; i< BUTTON_COUNT; i++) { + bit_mask = 1<