* NEC VR5701 support
@ 2006-02-23 15:36 Sergey Podstavin
0 siblings, 0 replies; 9+ messages in thread
From: Sergey Podstavin @ 2006-02-23 15:36 UTC (permalink / raw)
To: linux-mips
[-- Attachment #1: Type: text/plain, Size: 1 bytes --]
[-- Attachment #2: pro_mips_nec_vr5701.patch --]
[-- Type: text/x-patch, Size: 223683 bytes --]
Source: MontaVista Software, Inc. Sergey Podstavin <spodstavin@ru.mvista.com>
MR: 11590
Type: Enhancement
Disposition: needs submitting to linuxmips-embedded mailing list
Signed-off-by: Sergey Podstavin <spodstavin@ru.mvista.com>
Description:
NEC Electronics Corporation VR5701 SolutionGearII board LSP
Index: linux-2.6.10/arch/mips/vr5701/tcube/irq_vr5701.c
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/tcube/irq_vr5701.c
@@ -0,0 +1,194 @@
+/*
+ * arch/mips/vr5701/tcube/irq_vr5701.c
+ *
+ * This file defines the irq handler for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+/*
+ * NEC Electronics Corporation VR5701 SolutionGearII defines 32 IRQs.
+ *
+ */
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+
+#include <asm/debug.h>
+#include <asm/tcube.h>
+
+static int vr5701_irq_base = -1;
+
+void ll_vr5701_irq_disable(int vr5701_irq, int ack);
+
+static void vr5701_irq_enable(unsigned int irq)
+{
+ ll_vr5701_irq_enable(irq - vr5701_irq_base);
+}
+
+static void vr5701_irq_disable(unsigned int irq)
+{
+ ll_vr5701_irq_disable(irq - vr5701_irq_base, 0);
+}
+
+static unsigned int vr5701_irq_startup(unsigned int irq)
+{
+ vr5701_irq_enable(irq);
+ return 0;
+}
+
+static void vr5701_irq_ack(unsigned int irq)
+{
+ unsigned long flags;
+ local_irq_save(flags);
+
+ /* clear the interrupt bit for edge trigger */
+ /* some irqs require the driver to clear the sources */
+ if (irq < vr5701_irq_base + NUM_5701_IRQ) {
+ ddb_out32(INT_CLR, 1 << (irq - vr5701_irq_base));
+ }
+ /* don't need for PCIs, for they are level triger */
+
+ /* disable interrupt - some handler will re-enable the irq
+ * and if the interrupt is leveled, we will have infinite loop
+ */
+ ll_vr5701_irq_disable(irq - vr5701_irq_base, 1);
+ local_irq_restore(flags);
+}
+
+static void vr5701_irq_end(unsigned int irq)
+{
+ unsigned long flags;
+ local_irq_save(flags);
+
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+ ll_vr5701_irq_enable(irq - vr5701_irq_base);
+ }
+ local_irq_restore(flags);
+}
+
+struct hw_interrupt_type vr5701_irq_type = {
+ "vr5701_irq",
+ vr5701_irq_startup,
+ vr5701_irq_disable,
+ vr5701_irq_enable,
+ vr5701_irq_disable,
+ vr5701_irq_ack,
+ vr5701_irq_end,
+ NULL /* no affinity stuff for UP */
+};
+
+void vr5701_irq_init(u32 irq_base)
+{
+ extern irq_desc_t irq_desc[];
+ u32 i;
+ vr5701_irq_base = irq_base;
+ for (i = irq_base;
+ i < irq_base + NUM_5701_IRQ + NUM_EPCI_IRQ + NUM_IPCI_IRQ; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &vr5701_irq_type;
+ }
+}
+
+int vr5701_irq_to_irq(int irq)
+{
+ return irq + vr5701_irq_base;
+}
+
+void ll_vr5701_irq_route(int vr5701_irq, int ip)
+{
+ u32 reg_value;
+ u32 reg_bitmask;
+ u32 reg_index;
+
+ if (vr5701_irq >= NUM_5701_IRQ) {
+ if (vr5701_irq >= NUM_5701_IRQ + NUM_EPCI_IRQ) {
+ vr5701_irq = 7;
+ } else {
+ vr5701_irq = 6;
+ }
+ }
+ reg_index = INT_ROUTE0 + vr5701_irq / 8 * 4;
+ reg_value = ddb_in32(reg_index);
+ reg_bitmask = 7 << (vr5701_irq % 8 * 4);
+ reg_value &= ~reg_bitmask;
+ reg_value |= ip << (vr5701_irq % 8 * 4);
+ ddb_out32(reg_index, reg_value);
+}
+
+void ll_vr5701_irq_enable(int vr5701_irq)
+{
+ u16 reg_value;
+ u32 reg_bitmask;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ irq_desc[vr5701_irq_base + vr5701_irq].depth++;
+
+ if (vr5701_irq >= NUM_5701_IRQ) {
+ if (vr5701_irq >= NUM_5701_IRQ + NUM_EPCI_IRQ) {
+ reg_value = ddb_in32(IPCI_INTM);
+ reg_bitmask =
+ 1 << (vr5701_irq - NUM_5701_IRQ - NUM_EPCI_IRQ);
+ ddb_out32(IPCI_INTM, reg_value | reg_bitmask);
+ vr5701_irq = 7;
+ } else {
+ reg_value = ddb_in32(EPCI_INTM);
+ reg_bitmask = 1 << (vr5701_irq - NUM_5701_IRQ);
+ ddb_out32(EPCI_INTM, reg_value | reg_bitmask);
+ vr5701_irq = 6;
+ }
+ }
+ reg_value = ddb_in32(INT_MASK);
+ ddb_out32(INT_MASK, reg_value | (1 << vr5701_irq));
+ local_irq_restore(flags);
+}
+
+void ll_vr5701_irq_disable(int vr5701_irq, int ack)
+{
+ u16 reg_value;
+ u32 udummy;
+ u32 reg_bitmask;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ if (!ack) {
+ irq_desc[vr5701_irq_base + vr5701_irq].depth--;
+ if (irq_desc[vr5701_irq_base + vr5701_irq].depth) {
+ local_irq_restore(flags);
+ return;
+ }
+ }
+
+ if (vr5701_irq >= NUM_5701_IRQ) {
+ if (vr5701_irq >= NUM_5701_IRQ + NUM_EPCI_IRQ) {
+ goto DISABLE_IRQ_IPCI;
+ } else {
+ goto DISABLE_IRQ_EPCI;
+ }
+ }
+ reg_value = ddb_in32(INT_MASK);
+ ddb_out32(INT_MASK, reg_value & ~(1 << vr5701_irq));
+ udummy = ddb_in32(INT_MASK);
+ local_irq_restore(flags);
+ return;
+
+ DISABLE_IRQ_IPCI:
+ reg_value = ddb_in32(IPCI_INTM);
+ reg_bitmask = 1 << (vr5701_irq - NUM_5701_IRQ - NUM_EPCI_IRQ);
+ ddb_out32(IPCI_INTM, reg_value & ~reg_bitmask);
+ local_irq_restore(flags);
+ return;
+
+ DISABLE_IRQ_EPCI:
+ reg_value = ddb_in32(EPCI_INTM);
+ reg_bitmask = 1 << (vr5701_irq - NUM_5701_IRQ);
+ ddb_out32(EPCI_INTM, reg_value & ~reg_bitmask);
+ local_irq_restore(flags);
+}
Index: linux-2.6.10/arch/mips/pci/pci-tcube.c
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/pci/pci-tcube.c
@@ -0,0 +1,126 @@
+/*
+ * arch/mips/pci/pci-tcube.c
+ *
+ * A code for PCI controllers on NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <asm/bootinfo.h>
+#include <asm/debug.h>
+#include <asm/byteorder.h>
+#include <asm/tcube.h>
+
+static struct resource extpci_io_resource = {
+ "ext pci IO space",
+ 0x00001000,
+ 0x007FFFFF,
+ IORESOURCE_IO
+};
+
+static struct resource extpci_mem_resource = {
+ "ext pci memory space",
+ 0x10000000,
+ 0x17FFFFFF,
+ IORESOURCE_MEM
+};
+
+static struct resource iopci_io_resource = {
+ "io pci IO space",
+ 0x01000000,
+ 0x017FFFFF,
+ IORESOURCE_IO
+};
+
+static struct resource iopci_mem_resource = {
+ "io pci memory space",
+ 0x18800000,
+ 0x18FFFFFF,
+ IORESOURCE_MEM
+};
+
+struct pci_controller VR5701_ext_controller = {
+ .pci_ops = &VR5701_ext_pci_ops,
+ .io_resource = &extpci_io_resource,
+ .mem_resource = &extpci_mem_resource
+};
+
+struct pci_controller VR5701_io_controller = {
+ .pci_ops = &VR5701_io_pci_ops,
+ .io_resource = &iopci_io_resource,
+ .mem_resource = &iopci_mem_resource
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ int slot_num;
+ int k = 0;
+
+ slot_num = PCI_SLOT(dev->devfn);
+
+ if (dev->bus->number == 0) { /* EPCI */
+ switch (slot_num) {
+ case 24 - 11: /* INTD# */
+ k = NUM_5701_IRQS + 3;
+ break;
+ case 25 - 11: /* INTC# */
+ k = NUM_5701_IRQS + 2;
+ break;
+ case 26 - 11: /* INTB# */
+ k = NUM_5701_IRQS + 1;
+ break;
+ case 27 - 11: /* INTA# */
+ k = NUM_5701_IRQS + 0;
+ break;
+ }
+ } else { /* IPCI */
+ switch (slot_num) {
+ case 29 - 11: /* INTC# */
+ k = NUM_5701_IRQS + NUM_5701_EPCI_IRQ + 2;
+ break;
+ case 30 - 11: /* INTB# */
+ k = NUM_5701_IRQS + NUM_5701_EPCI_IRQ + 1;
+ break;
+ case 31 - 11: /* INTA# */
+ k = NUM_5701_IRQS + NUM_5701_EPCI_IRQ + 0;
+ break;
+ }
+ }
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, k);
+ dev->irq = k + 8;
+ return dev->irq;
+}
+
+void ddb_pci_reset_bus(void)
+{
+ u32 temp;
+
+ temp = ddb_in32(EPCI_CTRLH);
+ temp |= 0x80000000;
+ ddb_out32(EPCI_CTRLH, temp);
+ udelay(100);
+ temp &= ~0xc0000000;
+ ddb_out32(EPCI_CTRLH, temp);
+
+ temp = ddb_in32(IPCI_CTRLH);
+ temp |= 0x80000000;
+ ddb_out32(IPCI_CTRLH, temp);
+ udelay(100);
+ temp &= ~0xc0000000;
+ ddb_out32(IPCI_CTRLH, temp);
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
Index: linux-2.6.10/include/asm-mips/serial.h
===================================================================
--- linux-2.6.10.orig/include/asm-mips/serial.h
+++ linux-2.6.10/include/asm-mips/serial.h
@@ -412,6 +412,21 @@
#define DDB5477_SERIAL_PORT_DEFNS
#endif
+#ifdef CONFIG_TCUBE
+#include <asm/tcube.h>
+#define TCUBE_SERIAL_PORT_DEFNS \
+ { baud_base: BASE_BAUD, irq: 16, flags: STD_COM_FLAGS, \
+ iomem_base: (u8*)0xbe000a00, iomem_reg_shift: 3, \
+ io_type: SERIAL_IO_MEM},\
+ { baud_base: BASE_BAUD, irq: 17, flags: STD_COM_FLAGS, \
+ iomem_base: (u8*)0xbe000a40, iomem_reg_shift: 3, \
+ io_type: SERIAL_IO_MEM},
+#else
+#define TCUBE_SERIAL_PORT_DEFNS
+#endif
+
+
+
#ifdef CONFIG_SGI_IP32
/*
* The IP32 (SGI O2) has standard serial ports (UART 16550A) mapped in memory
@@ -439,6 +454,7 @@
MOMENCO_OCELOT_SERIAL_PORT_DEFNS \
MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS \
TXX927_SERIAL_PORT_DEFNS \
- AU1000_SERIAL_PORT_DEFNS
+ AU1000_SERIAL_PORT_DEFNS \
+ TCUBE_SERIAL_PORT_DEFNS
#endif /* _ASM_SERIAL_H */
Index: linux-2.6.10/drivers/ide/pci/Makefile
===================================================================
--- linux-2.6.10.orig/drivers/ide/pci/Makefile
+++ linux-2.6.10/drivers/ide/pci/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_BLK_DEV_SLC90E66) += slc90
obj-$(CONFIG_BLK_DEV_TRIFLEX) += triflex.o
obj-$(CONFIG_BLK_DEV_TRM290) += trm290.o
obj-$(CONFIG_BLK_DEV_VIA82CXXX) += via82cxxx.o
+obj-$(CONFIG_BLK_DEV_NEC_VR5701_SG2) += nec_vr5701_sg2.o
# Must appear at the end of the block
obj-$(CONFIG_BLK_DEV_GENERIC) += generic.o
Index: linux-2.6.10/drivers/ide/pci/nec_vr5701_sg2.c
===================================================================
--- /dev/null
+++ linux-2.6.10/drivers/ide/pci/nec_vr5701_sg2.c
@@ -0,0 +1,111 @@
+/*
+ * drivers/ide/pci/nec_vr5701_sg2.c
+ *
+ * NEC Electronics Corporation VR5701 SolutionGearII IDE controller driver
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/config.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+#include <asm/io.h>
+
+static unsigned int __init init_chipset_nec_vr5701(struct pci_dev *dev,
+ const char *name)
+{
+ return 0;
+}
+
+static void __init init_hwif_nec_vr5701(ide_hwif_t * hwif)
+{
+ if (!(hwif->dma_base))
+ return;
+
+ hwif->atapi_dma = 1;
+ hwif->ultra_mask = 0x7f;
+ hwif->mwdma_mask = 0x07;
+ hwif->swdma_mask = 0x07;
+
+ if (!noautodma)
+ hwif->autodma = 1;
+ hwif->drives[0].autodma = hwif->autodma;
+ hwif->drives[1].autodma = hwif->autodma;
+}
+
+static ide_pci_device_t nec_vr5701_chipset __devinitdata = {
+ .name = "NEC Electronics Corporation VR5701 SolutionGearII",
+ .init_chipset = init_chipset_nec_vr5701,
+ .init_hwif = init_hwif_nec_vr5701,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .bootable = ON_BOARD,
+};
+
+static int __devinit nec_vr5701_init_one(struct pci_dev *dev,
+ const struct pci_device_id *id)
+{
+ ide_pci_device_t *d = &nec_vr5701_chipset;
+ u16 command;
+
+ if (dev->vendor == PCI_VENDOR_ID_NEC &&
+ dev->device == PCI_DEVICE_ID_NEC_USB_AND_IDE &&
+ dev->class == 0x0c0310)
+ return 1;
+ udelay(100);
+ pci_enable_device(dev);
+ *(volatile unsigned char *)0xb9001010 = 6;
+ asm("sync");
+ udelay(100);
+
+ pci_read_config_word(dev, PCI_COMMAND, &command);
+ if (!(command & PCI_COMMAND_IO)) {
+ printk(KERN_INFO "Skipping disabled %s IDE controller.\n",
+ d->name);
+ return 1;
+ }
+ ide_setup_pci_device(dev, d);
+ return 0;
+}
+
+static struct pci_device_id nec_vr5701_pci_tbl[] = {
+ {PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB_AND_IDE, PCI_ANY_ID,
+ PCI_ANY_ID, 0x010185, 0xffffff, 0},
+ {0,},
+};
+
+MODULE_DEVICE_TABLE(pci, nec_vr5701_pci_tbl);
+
+static struct pci_driver driver = {
+ .name = "nec_vr5701_IDE",
+ .id_table = nec_vr5701_pci_tbl,
+ .probe = nec_vr5701_init_one,
+};
+
+static int nec_vr5701_ide_init(void)
+{
+ return ide_pci_register_driver(&driver);
+}
+
+module_init(nec_vr5701_ide_init);
+
+MODULE_AUTHOR("Sergey Podstavin");
+MODULE_DESCRIPTION("PCI driver module for NEC Electronics Corporation VR5701 SolutionGearII IDE");
+MODULE_LICENSE("GPL");
Index: linux-2.6.10/arch/mips/Makefile
===================================================================
--- linux-2.6.10.orig/arch/mips/Makefile
+++ linux-2.6.10/arch/mips/Makefile
@@ -183,6 +183,10 @@ cflags-$(CONFIG_CPU_R5432) += \
$(call set_gccflags,r5400,mips4,r5000,mips4,mips2) \
-Wa,--trap
+cflags-$(CONFIG_CPU_R5500) += \
+ $(call set_gccflags,mips32,mips4,r5000,mips4,mips2) \
+ -Wa,--trap
+
cflags-$(CONFIG_CPU_NEVADA) += \
$(call set_gccflags,rm5200,mips4,r5000,mips4,mips2) \
-Wa,--trap
@@ -472,6 +476,13 @@ load-$(CONFIG_DDB5476) += 0xffffffff800
core-$(CONFIG_DDB5477) += arch/mips/ddb5xxx/ddb5477/
load-$(CONFIG_DDB5477) += 0xffffffff80100000
+#
+# NEC TCUBE
+#
+core-$(CONFIG_TCUBE) += arch/mips/vr5701/common/
+core-$(CONFIG_TCUBE) += arch/mips/vr5701/tcube/
+load-$(CONFIG_TCUBE) += 0xffffffff80080000
+
core-$(CONFIG_LASAT) += arch/mips/lasat/
cflags-$(CONFIG_LASAT) += -Iinclude/asm-mips/mach-lasat
load-$(CONFIG_LASAT) += 0xffffffff80000000
Index: linux-2.6.10/include/asm-mips/tlb.h
===================================================================
--- linux-2.6.10.orig/include/asm-mips/tlb.h
+++ linux-2.6.10/include/asm-mips/tlb.h
@@ -6,7 +6,7 @@
* we need to flush cache for area to be unmapped.
*/
#ifdef CONFIG_PREEMPT_RT
-#ifdef CONFIG_CPU_MIPS32
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_R5500)
/*
* We need the cache flush in case of such processors, eg. MIPS Malta
*/
Index: linux-2.6.10/arch/mips/mm/Makefile
===================================================================
--- linux-2.6.10.orig/arch/mips/mm/Makefile
+++ linux-2.6.10/arch/mips/mm/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_CPU_R4300) += c-r4k.o cex-
obj-$(CONFIG_CPU_R4X00) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
obj-$(CONFIG_CPU_R5000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
obj-$(CONFIG_CPU_R5432) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+obj-$(CONFIG_CPU_R5500) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
obj-$(CONFIG_CPU_R8000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r8k.o
obj-$(CONFIG_CPU_RM7000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
obj-$(CONFIG_CPU_RM9000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
Index: linux-2.6.10/include/asm-mips/vr5701.h
===================================================================
--- /dev/null
+++ linux-2.6.10/include/asm-mips/vr5701.h
@@ -0,0 +1,96 @@
+/*
+ * include/asm-mips/vr5701.h
+ *
+ * A header for NEC Electronics Corporation VR5701 SolutionGearII CPU
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __VR5701_H
+#define __VR5701_H
+
+#define VR5701_IO_BASE 0xbe000000
+
+/* PADR registers */
+#define PADR_SDRAM01 0x40
+#define PADR_LOCALCS0 0x80
+#define PADR_PCIW0 0xC0
+#define PADR_PCIW1 0xC8
+#define PADR_EPCIW0 0xC0
+#define PADR_IOPCIW0 0xE0
+#define PADR_IOPCIW1 0xE8
+/* INT registers */
+#define INT0_STAT 0x100
+#define INT1_STAT 0x108
+#define INT2_STAT 0x110
+#define INT3_STAT 0x118
+#define INT4_STAT 0x120
+#define NMI_STAT 0x130
+#define INT_CLR 0x140
+#define INT_MASK 0x150
+#define INT_ROUTE0 0x160
+#define INT_ROUTE1 0x168
+#define INT_ROUTE2 0x170
+#define INT_ROUTE3 0x178
+/* LOCAL registers */
+#define LOCAL_CST0 0x400
+#define LOCAL_CFG 0x440
+/* EPCI registers */
+#define EPCI_CTRLH 0x604
+#define EPCI_INIT0 0x610
+#define EPCI_INIT1 0x618
+#define EPCI_ERR 0x628
+#define EPCI_INTS 0x630
+#define EPCI_INTM 0x638
+/* PCI registers */
+#define PCI_MLTIM 0x70D
+#define PCI_BAR_MEM01 0x710
+#define PCI_BAR_LCS0 0x740
+#define PCI_BAR_LCS1 0x748
+#define PCI_BAR_LCS2 0x750
+#define PCI_BAR_LCS3 0x758
+#define PCI_BAR_IPCIW0 0x7A0
+#define PCI_BAR_IPCIW1 0x7A8
+#define PCI_BAR_IREG 0x7C0
+
+/* PIB registers*/
+#define PIB_RESET 0x800
+#define PIB_MISC 0x830
+
+/* GPIO registers*/
+#define GIU_PIO0 0x940
+#define GIU_DIR0 0x950
+#define GIU_DIR1 0x958
+#define GIU_FUNCSEL0 0x960
+#define GIU_FUNCSEL1 0x968
+
+/* CSI1 registers*/
+#define CSI1_MODE 0xB80
+#define CSI1_SIRB 0xB88
+#define CSI1_SOTB 0xB90
+#define CSI1_SOTBF 0xBA0
+#define CSI1_CNT 0xBC0
+#define CSI1_INT 0xBC8
+
+/* IPCI registers*/
+#define IPCI_CTRLH 0xE04
+#define IPCI_INIT0 0xE10
+#define IPCI_INIT1 0xE18
+#define IPCI_ERR 0xE28
+#define IPCI_INTS 0xE30
+#define IPCI_INTM 0xE38
+/* PCI registers */
+#define IPCI_MLTIM 0xF0D
+#define IPCI_BAR_LCS0 0xF40
+#define IPCI_BAR_LCS1 0xF48
+#define IPCI_BAR_LCS2 0xF50
+#define IPCI_BAR_LCS3 0xF58
+#define IPCI_BAR_EPCIW0 0xF80
+#define IPCI_BAR_EPCIW1 0xF88
+#define IPCI_BAR_IREG 0xFC0
+
+#endif /* __VR5701_H */
Index: linux-2.6.10/arch/mips/vr5701/tcube/int-handler.S
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/tcube/int-handler.S
@@ -0,0 +1,77 @@
+/*
+ * arch/mips/vr5701/tcube/int-handler.S
+ *
+ * First-level interrupt dispatcher for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/config.h>
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/tcube.h>
+
+/*
+ * first level interrupt dispatcher for ocelot board -
+ * We check for the timer first, then check PCI ints A and D.
+ * Then check for serial IRQ and fall through.
+ */
+ .align 5
+ NESTED(tcube_handle_int, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+ .set at
+ .set noreorder
+ mfc0 t0, CP0_CAUSE
+ mfc0 t2, CP0_STATUS
+
+ and t0, t2
+
+ andi t1, t0, STATUSF_IP7 /* cpu timer */
+ bnez t1, ll_cputimer_irq
+ andi t1, t0, (STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6 )
+ bnez t1, ll_tcube_irq
+ andi t1, t0, STATUSF_IP0 /* software int 0 */
+ bnez t1, ll_cpu_ip0
+ andi t1, t0, STATUSF_IP1 /* software int 1 */
+ bnez t1, ll_cpu_ip1
+ nop
+ .set reorder
+
+ /* wrong alarm or masked ... */
+ j spurious_interrupt
+ nop
+ END(tcube_handle_int)
+
+ .align 5
+
+ll_tcube_irq:
+ move a0, sp
+ jal tcube_irq_dispatch
+ j ret_from_irq
+
+ll_cputimer_irq:
+ li a0, 7
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+
+ll_cpu_ip0:
+ li a0, 0
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cpu_ip1:
+ li a0, 1
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
Index: linux-2.6.10/include/asm-mips/tcube.h
===================================================================
--- /dev/null
+++ linux-2.6.10/include/asm-mips/tcube.h
@@ -0,0 +1,200 @@
+/*
+ * include/asm-mips/tcube.h
+ *
+ * Flash memory access on NEC Electronics Corporation VR5701 SolutionGearII board.
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __TCUBE_H
+#define __TCUBE_H
+
+#include <asm/vr5701.h>
+
+#define TCUBE_SDRAM_SIZE 0x10000000
+
+#ifndef __ASSEMBLY__
+#include <asm/delay.h>
+
+/*
+ * PCI Master Registers
+ */
+
+#define DDB_PCICMD_IACK 0 /* PCI Interrupt Acknowledge */
+#define DDB_PCICMD_IO 1 /* PCI I/O Space */
+#define DDB_PCICMD_MEM 3 /* PCI Memory Space */
+#define DDB_PCICMD_CFG 5 /* PCI Configuration Space */
+
+/*
+ * additional options for pci init reg (no shifting needed)
+ */
+#define DDB_PCI_CFGTYPE1 0x200 /* for pci init0/1 regs */
+#define DDB_PCI_ACCESS_32 0x10 /* for pci init0/1 regs */
+#define NUM_5701_IRQS 32
+#define NUM_5701_EPCI_IRQ 4
+
+/* A Real Time Clock interface for Linux on NEC Electronics Corporation VR5701 SolutionGearII */
+#define SET_32_BIT 0xffffffff
+#define CLR_32_BIT 0x00000000
+
+#define GPIO_3_INTR (0x1 << 3)
+#define GPIO_4_CE (0x1 << 4)
+#define GPIO_25_S1CLK (0x1 << 25)
+#define GPIO_26_S1DO (0x1 << 26)
+#define GPIO_27_S1DI (0x1 << 27)
+#define GPIO_CSI1_PIN (GPIO_25_S1CLK | GPIO_26_S1DO | GPIO_27_S1DI)
+
+#define CSIn_MODE_CKP (0x1 << 12)
+#define CSIn_MODE_DAP (0x1 << 11)
+#define CSIn_MODE_CKS_MASK (0x7 << 8)
+#define CSIn_MODE_CKS_833333MHZ (0x1 << 8)
+#define CSIn_MODE_CKS_416667MHZ (0x2 << 8)
+#define CSIn_MODE_CKS_208333MHZ (0x3 << 8)
+#define CSIn_MODE_CKS_104167MHZ (0x4 << 8)
+#define CSIn_MODE_CKS_052083MHZ (0x5 << 8)
+#define CSIn_MODE_CKS_0260417HZ (0x6 << 8) /* Default */
+#define CSIn_MODE_CSIE (0x1 << 7)
+#define CSIn_MODE_TRMD (0x1 << 6)
+#define CSIn_MODE_CCL_16 (0x1 << 5)
+#define CSIn_MODE_DIR_LSB (0x1 << 4)
+#define CSIn_MODE_AUTO (0x1 << 2)
+#define CSIn_MODE_CSOT (0x1 << 0)
+
+#define CSIn_INT_CSIEND (0x1 << 15)
+#define CSIn_INT_T_EMP (0x1 << 8)
+#define CSIn_INT_R_OVER (0x1 << 0)
+
+/* IRQs */
+#define ACTIVE_LOW 1
+#define ACTIVE_HIGH 0
+
+#define LEVEL_SENSE 2
+#define EDGE_TRIGGER 0
+
+#define NUM_5701_IRQS 32
+#define NUM_5701_EPCI_IRQS 4
+#define NUM_5701_IPCI_IRQS 8
+#define NUM_5701_IRQ 32
+#define NUM_EPCI_IRQ 4
+#define NUM_IPCI_IRQ 8
+
+#define INTA 0
+#define INTB 1
+#define INTC 2
+#define INTD 3
+#define INTE 4
+
+/* Timers */
+#define CPU_COUNTER_FREQUENCY 166666666
+
+#define ddb_sync io_sync
+#define ddb_out32(x,y) io_out32(x,y)
+#define ddb_out16(x,y) io_out16(x,y)
+#define ddb_out8(x,y) io_out8(x,y)
+#define ddb_in32(x) io_in32(x)
+#define ddb_in16(x) io_in16(x)
+#define ddb_in8(x) io_in8(x)
+
+static inline void io_sync(void)
+{
+ asm("sync");
+}
+
+static inline void io_out32(u32 offset, u32 val)
+{
+ *(volatile u32 *)(VR5701_IO_BASE + offset) = val;
+ io_sync();
+}
+
+static inline u32 io_in32(u32 offset)
+{
+ u32 val = *(volatile u32 *)(VR5701_IO_BASE + offset);
+ io_sync();
+ return val;
+}
+
+static inline void io_out16(u32 offset, u16 val)
+{
+ *(volatile u16 *)(VR5701_IO_BASE + offset) = val;
+ io_sync();
+}
+
+static inline u16 io_in16(u32 offset)
+{
+ u16 val = *(volatile u16 *)(VR5701_IO_BASE + offset);
+ io_sync();
+ return val;
+}
+
+static inline void io_reset16(unsigned long adr,
+ unsigned short val1,
+ unsigned delay, unsigned short val2)
+{
+ io_out16(adr, val1);
+ __delay(delay);
+ io_out16(adr, val2);
+}
+
+static inline void io_out8(u32 offset, u8 val)
+{
+ *(volatile u8 *)(VR5701_IO_BASE + offset) = val;
+ io_sync();
+}
+
+static inline u8 io_in8(u32 offset)
+{
+ u8 val = *(volatile u8 *)(VR5701_IO_BASE + offset);
+ io_sync();
+ return val;
+}
+
+static inline void io_set16(u32 offset, u16 mask, u16 val)
+{
+ u16 val0 = io_in16(offset);
+ io_out16(offset, (val & mask) | (val0 & ~mask));
+}
+
+static inline void reg_set32(u32 offset, u32 mask, u32 val)
+{
+ u32 val0 = io_in32(offset);
+ io_out32(offset, (val & mask) | (val0 & ~mask));
+}
+
+static inline void csi1_reset(void)
+{
+ /* CSI1 reset */
+ reg_set32(CSI1_CNT, 0x00008000, SET_32_BIT); /* set CSIRST bit */
+ __delay(100000);
+ reg_set32(CSI1_CNT, 0x00008000, CLR_32_BIT); /* clear CSIRST bit */
+ /* set clock phase */
+ while (io_in32(CSI1_MODE) & 1) ;
+ reg_set32(CSI1_MODE, CSIn_MODE_CSIE, CLR_32_BIT);
+ reg_set32(CSI1_MODE, CSIn_MODE_CKP, SET_32_BIT);
+ reg_set32(CSI1_MODE, CSIn_MODE_CKS_104167MHZ, SET_32_BIT);
+ reg_set32(CSI1_MODE, CSIn_MODE_CSIE, SET_32_BIT);
+ while (io_in32(CSI1_MODE) & CSIn_MODE_CSOT) ;
+}
+
+extern void ll_vr5701_irq_route(int vr5701_irq, int ip);
+extern void ll_vr5701_irq_enable(int vr5701_irq);
+extern void ddb_set_pdar(u32, u32, u32, int, int, int);
+extern void ddb_set_pmr(u32 pmr, u32 type, u32 addr, u32 options);
+extern void ddb_set_bar(u32 bar, u32 phys, int prefetchable);
+extern void ddb_pci_reset_bus(void);
+extern struct pci_ops VR5701_ext_pci_ops;
+extern struct pci_ops VR5701_io_pci_ops;
+extern struct pci_controller VR5701_ext_controller;
+extern struct pci_controller VR5701_io_controller;
+extern int shima_tcube_setup(void);
+extern void tcube_irq_init(u32 base);
+extern void mips_cpu_irq_init(u32 base);
+extern asmlinkage void tcube_handle_int(void);
+extern void vr5701_irq_init(u32 irq_base);
+extern int panic_timeout;
+
+#endif
+#endif
Index: linux-2.6.10/drivers/video/Makefile
===================================================================
--- linux-2.6.10.orig/drivers/video/Makefile
+++ linux-2.6.10/drivers/video/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_FB_I810) += cfb
vgastate.o
obj-$(CONFIG_FB_INTEL) += cfbfillrect.o cfbcopyarea.o \
cfbimgblt.o
+obj-$(CONFIG_FB_SM) += smi/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_RADEON_OLD) += radeonfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_NEOMAGIC) += neofb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o vgastate.o
Index: linux-2.6.10/arch/mips/kernel/Makefile
===================================================================
--- linux-2.6.10.orig/arch/mips/kernel/Makefile
+++ linux-2.6.10/arch/mips/kernel/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_CPU_R4300) += r4k_fpu.o r4
obj-$(CONFIG_CPU_R4X00) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R5000) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R5432) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_R5500) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R8000) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_RM7000) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_RM9000) += r4k_fpu.o r4k_switch.o
Index: linux-2.6.10/arch/mips/pci/Makefile
===================================================================
--- linux-2.6.10.orig/arch/mips/pci/Makefile
+++ linux-2.6.10/arch/mips/pci/Makefile
@@ -52,3 +52,4 @@ obj-$(CONFIG_TOSHIBA_JMR3927) += fixup-j
obj-$(CONFIG_TOSHIBA_RBTX4927) += fixup-rbtx4927.o ops-tx4927.o
obj-$(CONFIG_VICTOR_MPC30X) += fixup-mpc30x.o
obj-$(CONFIG_ZAO_CAPCELLA) += fixup-capcella.o
+obj-$(CONFIG_TCUBE) += pci-tcube.o ops-tcube.o
Index: linux-2.6.10/drivers/video/smi/smi_hw.c
===================================================================
--- /dev/null
+++ linux-2.6.10/drivers/video/smi/smi_hw.c
@@ -0,0 +1,188 @@
+/*
+ * drivers/video/smi/smi_hw.c
+ *
+ * LynxEM+/EM4+(Silicon Motion Inc.) fb driver for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include "smifb.h"
+#include "smi_hw.h"
+#include "smi_params.h"
+
+/*
+ * set mode registers
+ */
+void
+smi_set_moderegs(struct smifb_info *sinfo,
+ int bpp, int width, int height,
+ int hDisplaySize,
+ int hDisplay, int hStart, int hEnd, int hTotal,
+ int vDisplay, int vStart, int vEnd, int vTotal,
+ int dotClock, int sync)
+{
+ int i;
+ int tmp_mode = SMI_DEFAULT_MODE;
+ int lineLength;
+ struct smi_mode_regs curMode;
+
+ pr_debug("smi_set_moderegs");
+ pr_debug("bpp = %d, width = %d, height = %d\n", bpp, width, height);
+ pr_debug("hDisplaySize = %d\n", hDisplaySize);
+ pr_debug("hDisplay = %d, hStart = %d, hEnd = %d, hTotal = %d\n",
+ hDisplay, hStart, hEnd, hTotal);
+ pr_debug("vDisplay = %d, vStart = %d, vEnd = %d, vTotal = %d\n",
+ vDisplay, vStart, vEnd, vTotal);
+ pr_debug("dotClock = %d\n", dotClock);
+
+ lineLength = width * bpp / 8;
+
+ switch (bpp) {
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ if (hDisplaySize <= 640)
+ tmp_mode = DISPLAY_640x480x8;
+ else if (width <= 800)
+ tmp_mode = DISPLAY_800x600x8;
+ else if (width <= 1024)
+ tmp_mode = DISPLAY_1024x768x8;
+ else if (width <= 1280)
+ tmp_mode = DISPLAY_1280x1024x8;
+ reg_DPR10(sinfo) = (lineLength << 16) | lineLength; /* RowPitch */
+ reg_DPR1E(sinfo) = 0x0005;
+ reg_DPR3C(sinfo) = (lineLength << 16) | lineLength; /* Dst & Src Window Width */
+ reg_VPR00(sinfo) = 0x0 << 16;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ if (hDisplaySize <= 400)
+ tmp_mode = DISPLAY_LCD_400x232x16;
+ if (hDisplaySize <= 640)
+ tmp_mode = DISPLAY_640x480x16;
+ else if (width <= 800)
+ tmp_mode = DISPLAY_800x600x16;
+ else if (width <= 1024)
+ tmp_mode = DISPLAY_1024x768x16;
+ reg_DPR10(sinfo) = (lineLength / 2 << 16) | lineLength / 2; /* RowPitch */
+ reg_DPR1E(sinfo) = 0x0015;
+ reg_DPR3C(sinfo) = (lineLength / 2 << 16) | lineLength / 2; /* Dst & Src Window Width */
+ reg_VPR00(sinfo) = 0x2 << 16;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ if (hDisplaySize <= 640)
+ tmp_mode = DISPLAY_640x480x24;
+ else if (width <= 800)
+ tmp_mode = DISPLAY_800x600x24;
+ reg_DPR10(sinfo) = (lineLength / 3 << 16) | lineLength / 3; /* RowPitch */
+ reg_DPR1E(sinfo) = 0x0035;
+ reg_DPR3C(sinfo) = (lineLength / 3 << 16) | lineLength / 3; /* Dst & Src Window Width */
+ reg_VPR00(sinfo) = 0x4 << 16;
+ break;
+#endif
+ };
+
+ for (i = 0; i < modeNums; i++) {
+ if (ModeInitParams[i].mode == tmp_mode)
+ break;
+ }
+ if (i == modeNums)
+ tmp_mode = SMI_DEFAULT_MODE;
+
+ memcpy(&curMode, &ModeInitParams[tmp_mode],
+ sizeof(struct smi_mode_regs));
+
+ /*
+ * Override some Mode Params
+ */
+ /* MISC Reg */
+ curMode.reg_MISC = 0x30 | (hDisplay == 640) ? 0x03 : 0x0b;
+ if (sync & FB_SYNC_HOR_HIGH_ACT)
+ curMode.reg_MISC |= 0x40;
+ if (sync & FB_SYNC_VERT_HIGH_ACT)
+ curMode.reg_MISC |= 0x80;
+
+ /* CRTC */
+ curMode.reg_CR00_CR18[0x00] = (u8) (hTotal - 4);
+ curMode.reg_CR00_CR18[0x01] = (u8) hDisplay;
+ curMode.reg_CR00_CR18[0x02] = (u8) hDisplay;
+ curMode.reg_CR00_CR18[0x03] = 0x00;
+ curMode.reg_CR00_CR18[0x04] = (u8) hStart;
+ curMode.reg_CR00_CR18[0x05] = (hEnd & 0x1f);
+ curMode.reg_CR00_CR18[0x06] = (u8) (vTotal & 0xff);
+ curMode.reg_CR00_CR18[0x07] = (u8) (((vStart >> 9) & 0x01) << 7)
+ | (u8) (((vDisplay >> 9) & 0x01) << 6)
+ | (u8) (((vTotal >> 9) & 0x01) << 5)
+ | 1 << 4 /* D (LC) */
+ | (u8) (((vStart >> 8) & 0x01) << 2)
+ | (u8) (((vDisplay >> 8) & 0x01) << 1)
+ | (u8) ((vTotal >> 8) & 0x01);
+
+ curMode.reg_CR00_CR18[0x09] = (u8) (vDisplay >> 9) << 5 | 1 << 6; /* D (LC bit9) */
+ curMode.reg_CR00_CR18[0x10] = (u8) (vStart & 0xff);
+ curMode.reg_CR00_CR18[0x11] = (u8) (vEnd & 0xf);
+ curMode.reg_CR00_CR18[0x12] = (u8) (vDisplay & 0xff);
+ curMode.reg_CR00_CR18[0x13] = ((width / 8) * ((bpp + 1) / 8)) & 0xFF;
+ curMode.reg_CR00_CR18[0x15] = (u8) (vDisplay & 0xff);
+ curMode.reg_CR00_CR18[0x16] = 0x00;
+ curMode.reg_CR00_CR18[0x14] = (hDisplaySize > 1024) ? 0x00 : 0x40; /* D *//* Underline Location */
+
+ /* Extended CRTC */
+ curMode.reg_CR30_CR4D[0x30 - 0x30] = (u8) (((vTotal >> 10) & 0x01) << 3)
+ | (u8) (((vDisplay >> 10) & 0x01) << 1)
+ | (u8) ((vStart >> 10) & 0x1); /* D (CRTD) (CVDER) */
+
+ curMode.reg_SR30_SR75[0x32] = 0xff; /* (Memory Type and Timig Control Reg) */
+
+ for (i = 0; i <= SIZE_SR00_SR04; i++)
+ regSR_write(sinfo->mmio, 0x00 + i, curMode.reg_SR00_SR04[i]);
+ for (i = 0; i <= SIZE_SR10_SR24; i++)
+ regSR_write(sinfo->mmio, 0x10 + i, curMode.reg_SR10_SR24[i]);
+ for (i = 0; i <= SIZE_SR30_SR75; i++) {
+ regSR_write(sinfo->mmio, 0x30 + i, curMode.reg_SR30_SR75[i]);
+ }
+ for (i = 0; i <= SIZE_SR80_SR93; i++)
+ regSR_write(sinfo->mmio, 0x80 + i, curMode.reg_SR80_SR93[i]);
+ for (i = 0; i <= SIZE_SRA0_SRAF; i++)
+ regSR_write(sinfo->mmio, 0xA0 + i, curMode.reg_SRA0_SRAF[i]);
+ for (i = 0; i <= SIZE_GR00_GR08; i++)
+ regGR_write(sinfo->mmio, 0x00 + i, curMode.reg_GR00_GR08[i]);
+ for (i = 0; i <= SIZE_AR00_AR14; i++)
+ regAR_write(sinfo->mmio, 0x00 + i, curMode.reg_AR00_AR14[i]);
+ for (i = 0; i <= SIZE_CR00_CR18; i++)
+ regCR_write(sinfo->mmio, 0x00 + i, curMode.reg_CR00_CR18[i]);
+ for (i = 0; i <= SIZE_CR30_CR4D; i++)
+ regCR_write(sinfo->mmio, 0x30 + i, curMode.reg_CR30_CR4D[i]);
+ for (i = 0; i <= SIZE_CR90_CRA7; i++)
+ regCR_write(sinfo->mmio, 0x90 + i, curMode.reg_CR90_CRA7[i]);
+
+ /* SetMemoryMapRegisters */
+ reg_DPR14(sinfo) = 0xffffffff; /* FG color */
+ reg_DPR18(sinfo) = 0x00000000; /* BG color */
+ reg_DPR24(sinfo) = 0xffffffff; /* Color Mask */
+ reg_DPR28(sinfo) = 0xffff; /* Masks */
+ reg_DPR2C(sinfo) = 0;
+ reg_DPR30(sinfo) = 0;
+ reg_DPR34(sinfo) = 0xffffffff;
+ reg_DPR38(sinfo) = 0xffffffff;
+ reg_DPR40(sinfo) = 0;
+ reg_DPR44(sinfo) = 0;
+ reg_VPR0C(sinfo) = 0;
+ reg_VPR10(sinfo) = ((lineLength / 8 + 2) << 16) | (lineLength / 8);
+ reg_VPR40(sinfo) = 0;
+ reg_VPR28(sinfo) = 0x00000000;
+ reg_VPR2C(sinfo) = ((hDisplaySize - 1) << 16) | (vDisplay);
+ reg_VPR30(sinfo) = 0x00000000;
+ reg_VPR34(sinfo) = (lineLength << 16) | lineLength;
+}
Index: linux-2.6.10/include/linux/pci_ids.h
===================================================================
--- linux-2.6.10.orig/include/linux/pci_ids.h
+++ linux-2.6.10/include/linux/pci_ids.h
@@ -555,6 +555,7 @@
#define PCI_DEVICE_ID_MIRO_DC30PLUS 0xd801
#define PCI_VENDOR_ID_NEC 0x1033
+#define PCI_DEVICE_ID_NEC_USB_AND_IDE 0x0000 /* USB 1.1 or IDE Controller*/
#define PCI_DEVICE_ID_NEC_CBUS_1 0x0001 /* PCI-Cbus Bridge */
#define PCI_DEVICE_ID_NEC_LOCAL 0x0002 /* Local Bridge */
#define PCI_DEVICE_ID_NEC_ATM 0x0003 /* ATM LAN Controller */
@@ -1643,6 +1644,11 @@
#define PCI_DEVICE_ID_SATSAGEM_PCR2101 0x5352
#define PCI_DEVICE_ID_SATSAGEM_TELSATTURBO 0x5a4b
+#define PCI_VENDOR_ID_SMI 0x126f
+#define PCI_DEVICE_ID_SMI_LYNX_EM 0x0710
+#define PCI_DEVICE_ID_SMI_LYNX_EM_PLUS 0x0712
+#define PCI_DEVICE_ID_SMI_LYNX_3DM 0x0720
+
#define PCI_VENDOR_ID_HUGHES 0x1273
#define PCI_DEVICE_ID_HUGHES_DIRECPC 0x0002
Index: linux-2.6.10/drivers/video/smi/smi_base.c
===================================================================
--- /dev/null
+++ linux-2.6.10/drivers/video/smi/smi_base.c
@@ -0,0 +1,512 @@
+/*
+ * drivers/video/smi/smi_base.c
+ *
+ * LynxEM+/EM4+(Silicon Motion Inc.) fb driver for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/selection.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/console.h>
+#include "../console/fbcon.h"
+#include "smifb.h"
+#include "smi_hw.h"
+
+/*
+ * Card Identification
+ *
+ */
+static struct pci_device_id smifb_pci_tbl[] __devinitdata = {
+ {PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_LYNX_EM_PLUS,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* Lynx EM+/EM4+ */
+ {PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_LYNX_3DM,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* Lynx 3DM/3DM+/3DM4+ */
+ {0,} /* terminate list */
+};
+
+MODULE_DEVICE_TABLE(pci, smifb_pci_tbl);
+
+/*
+ *
+ * global variables
+ *
+ */
+
+#ifdef CONFIG_DISPLAY_1024x768
+/* 1024x768, 16bpp, 60Hz */
+static struct fb_var_screeninfo smifb_default_var = {
+ xres:1024,
+ yres:768,
+ xres_virtual:1024,
+ yres_virtual:768,
+ xoffset:0,
+ yoffset:0,
+ bits_per_pixel:16,
+ grayscale:0,
+ red:{11, 5, 0},
+ green:{5, 6, 0},
+ blue:{0, 5, 0},
+ transp:{0, 0, 0},
+ nonstd:0,
+ activate:0,
+ height:-1,
+ width:-1,
+ accel_flags:0,
+ pixclock:39721, /* D */
+ left_margin:138,
+ right_margin:24,
+ upper_margin:24,
+ lower_margin:4,
+ hsync_len:160,
+ vsync_len:6,
+ sync:0,
+ vmode:FB_VMODE_NONINTERLACED
+};
+#else
+/* 640x480, 16bpp, 60Hz */
+static struct fb_var_screeninfo smifb_default_var = {
+ xres:640,
+ yres:480,
+ xres_virtual:640,
+ yres_virtual:480,
+ xoffset:0,
+ yoffset:0,
+ bits_per_pixel:16,
+ grayscale:0,
+ red:{11, 5, 0},
+ green:{5, 6, 0},
+ blue:{0, 5, 0},
+ transp:{0, 0, 0},
+ nonstd:0,
+ activate:0,
+ height:-1,
+ width:-1,
+ accel_flags:0,
+ pixclock:39721, /* D */
+ left_margin:82,
+ right_margin:16,
+ upper_margin:19,
+ lower_margin:1,
+ hsync_len:152,
+ vsync_len:4,
+ sync:0,
+ vmode:FB_VMODE_NONINTERLACED
+};
+#endif
+
+static char drvrname[] = "NEC video driver for SMI LynxEM+";
+
+/*
+ *
+ * general utility functions
+ *
+ */
+
+static void
+smi_load_video_mode(struct smifb_info *sinfo,
+ struct fb_var_screeninfo *video_mode)
+{
+ int bpp, width, height;
+ int hDisplaySize, hDisplay, hStart, hEnd, hTotal;
+ int vDisplay, vStart, vEnd, vTotal;
+ int dotClock;
+
+ pr_debug("smi_load_video_mode: video_mode->xres = %d\n",
+ video_mode->xres);
+ pr_debug(" : yres = %d\n",
+ video_mode->yres);
+ pr_debug(" : xres_virtual = %d\n",
+ video_mode->xres_virtual);
+ pr_debug(" : yres_virtual = %d\n",
+ video_mode->yres_virtual);
+ pr_debug(" : xoffset = %d\n",
+ video_mode->xoffset);
+ pr_debug(" : yoffset = %d\n",
+ video_mode->yoffset);
+ pr_debug(" : bits_per_pixel = %d\n",
+ video_mode->bits_per_pixel);
+
+ /* smifb_blank(1, (struct fb_info*)sinfo); */
+ bpp = video_mode->bits_per_pixel;
+ if (bpp == 16 && video_mode->green.length == 5)
+ bpp = 15;
+
+ /* horizontal params */
+ width = video_mode->xres_virtual;
+ hDisplaySize = video_mode->xres; /* number of pixels for one horizontal line */
+ hDisplay = (hDisplaySize / 8) - 1; /* number of character clocks */
+ hStart = (hDisplaySize + video_mode->right_margin) / 8 + 2; /* h-blank start character clocks */
+ hEnd = (hDisplaySize + video_mode->right_margin + video_mode->hsync_len) / 8 - 1; /* h-sync end */
+ hTotal = (hDisplaySize + video_mode->right_margin + video_mode->hsync_len + video_mode->left_margin) / 8 - 1; /* character clock from h-sync to next h-sync */
+
+ /* vertical params */
+ height = video_mode->yres_virtual;
+ vDisplay = video_mode->yres - 1; /* number of lines */
+ vStart = video_mode->yres + video_mode->lower_margin - 1; /* v-sync pulse start */
+ vEnd = video_mode->yres + video_mode->lower_margin + video_mode->vsync_len - 1; /* v-sync end */
+ vTotal = video_mode->yres + video_mode->lower_margin + video_mode->vsync_len + video_mode->upper_margin + 2; /* number of scanlines (v-blank end) */
+
+ dotClock = 1000000000 / video_mode->pixclock;
+
+ smi_set_moderegs(sinfo, bpp, width, height,
+ hDisplaySize,
+ hDisplay, hStart, hEnd, hTotal,
+ vDisplay, vStart, vEnd, vTotal,
+ dotClock, video_mode->sync);
+}
+
+/*
+ *
+ * framebuffer operations
+ *
+ */
+static int
+smifb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+{
+ struct smifb_info *sinfo = (struct smifb_info *)info;
+
+ pr_debug("smifb_get_fix");
+ fix->smem_start = sinfo->fb_base_phys;
+ fix->smem_len = sinfo->fbsize;
+ fix->mmio_start = sinfo->dpr_base_phys;
+ fix->mmio_len = sinfo->dpport_size;
+
+ fix->xpanstep = 0; /* FIXME: no xpanstep for now */
+ fix->ypanstep = 1; /* FIXME: no ypanstep for now */
+ fix->ywrapstep = 0; /* FIXME: no ywrap for now */
+
+ return 0;
+}
+
+static int vgxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp, struct fb_info *info)
+{
+ if (regno > 15)
+ return 1;
+
+ ((u16 *) (info->pseudo_palette))[regno] =
+ (red & 0xf800) | (green & 0xfc00 >> 5) | (blue & 0xf800 >> 11);
+ return 0;
+}
+
+/*
+ * Initialization helper functions
+ *
+ */
+/* kernel interface */
+static struct fb_ops smifb_ops = {
+ .owner = THIS_MODULE,
+ .fb_setcolreg = vgxfb_setcolreg,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_cursor = soft_cursor,
+};
+
+/*
+ * VGA registers
+ *
+ */
+static void Unlock(struct smifb_info *sinfo)
+{
+ pr_debug("Unlock");
+ regSR_write(sinfo->mmio, 0x33, regSR_read(sinfo->mmio, 0x33) & 0x20);
+}
+
+static void UnlockVGA(struct smifb_info *sinfo)
+{
+ pr_debug("UnlockVGA");
+ regCR_write(sinfo->mmio, 0x11, regCR_read(sinfo->mmio, 0x11) & 0x7f);
+}
+
+static struct fb_fix_screeninfo vgxfb_fix = {
+ .id = "vgxFB",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
+#ifdef CONFIG_DISPLAY_1024x768
+ .line_length = 1024 * 2,
+#else
+ .line_length = 640 * 2,
+#endif
+ .accel = FB_ACCEL_NONE,
+};
+
+static u32 colreg[17];
+
+/*
+ * PCI bus
+ *
+ */
+static int __devinit
+smifb_probe(struct pci_dev *pd, const struct pci_device_id *ent)
+{
+ int len;
+ int res;
+ u16 cmd;
+ struct smifb_info *sinfo;
+ struct fb_info *info;
+
+ pr_debug("smifb_probe");
+
+ pr_debug("vendor id %04x\n", pd->vendor);
+ pr_debug("device id %04x\n", pd->device);
+ pr_debug("sub vendor id %04x\n", pd->subsystem_vendor);
+ pr_debug("sub device id %04x\n", pd->subsystem_device);
+
+ pr_debug("base0 start addr %08x\n",
+ (unsigned int)pci_resource_start(pd, 0));
+ pr_debug("base0 end addr %08x\n",
+ (unsigned int)pci_resource_end(pd, 0));
+ pr_debug("base0 region len %08x\n",
+ (unsigned int)pci_resource_len(pd, 0));
+ pr_debug("base0 flags %08x\n",
+ (unsigned int)pci_resource_flags(pd, 0));
+
+ pci_read_config_word(pd, PCI_STATUS, &cmd);
+ pr_debug("PCI status %04x\n", cmd);
+
+ pci_read_config_word(pd, PCI_COMMAND, &cmd);
+ pr_debug("PCI command %04x\n", cmd);
+
+ cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
+ pci_write_config_word(pd, PCI_COMMAND, cmd);
+
+ pci_read_config_word(pd, PCI_STATUS, &cmd);
+ pr_debug("PCI status %04x\n", cmd);
+ pci_read_config_word(pd, PCI_COMMAND, &cmd);
+ pr_debug("PCI command %04x\n", cmd);
+
+ /* allocate memory resources */
+ sinfo = kmalloc(sizeof(struct smifb_info), GFP_KERNEL);
+ if (!sinfo) {
+ goto err_out;
+ }
+ memset(sinfo, 0, sizeof(struct smifb_info));
+
+ /* driver name */
+ sinfo->drvr_name = drvrname;
+
+ sinfo->pd = pd;
+ sinfo->base_phys = pci_resource_start(sinfo->pd, 0); /* Frame Buffer base address */
+ len = pci_resource_len(sinfo->pd, 0);
+ pr_debug("len = %lX\n", len);
+ if (!request_mem_region(sinfo->base_phys, len, "smifb")) {
+ printk(KERN_ERR "cannot reserve FrameBuffer and MMIO region\n");
+ goto err_out_kfree;
+ }
+
+ if ((res = pci_enable_device(sinfo->pd)) < 0) {
+ printk(KERN_ERR "smifb: failed to enable -- err %d\n", res);
+ goto err_out_free_base;
+ }
+
+ pci_read_config_word(pd, PCI_COMMAND, &cmd);
+ pr_debug(KERN_INFO "PCI command %04x\n", cmd);
+
+ {
+ unsigned int pseudo_io, pseudo_io_len;
+ unsigned char *pseudo_io_p;
+
+ *(unsigned long *)0xbe000610 = 0x10000012; /* CHANGE to PCI IO ACCESS */
+ asm("sync");
+ pseudo_io = pci_resource_start(sinfo->pd, 0);
+ pseudo_io_len = pci_resource_len(sinfo->pd, 0);
+ pseudo_io_p = ioremap(pseudo_io, pseudo_io_len);
+
+ VGA_WRITE8(pseudo_io_p, 0x3c3, 0x40);
+ regSR_write(pseudo_io_p, 0x00, 0x00);
+ regSR_write(pseudo_io_p, 0x17, 0xe2);
+ regSR_write(pseudo_io_p, 0x18, 0xff);
+
+ iounmap(pseudo_io_p);
+ *(unsigned long *)0xbe000610 = 0x10000016; /* PCI MEM ACCESS */
+ asm("sync");
+ }
+ sinfo->base = ioremap(sinfo->base_phys, len); /* FB+DPD+DPR+VPR+CPR+MMIO */
+ if (!sinfo->base) {
+ goto err_out_free_base;
+ }
+ switch ((sinfo->pd)->device) {
+ case PCI_DEVICE_ID_SMI_LYNX_EM_PLUS:
+ sinfo->dpport = (caddr_t) (sinfo->base + DPPORT_BASE_OFFSET);
+ sinfo->dpr = (caddr_t) (sinfo->base + DP_BASE_OFFSET);
+ sinfo->vpr = (caddr_t) (sinfo->base + VP_BASE_OFFSET);
+ sinfo->cpr = (caddr_t) (sinfo->base + CP_BASE_OFFSET);
+ sinfo->mmio = (caddr_t) (sinfo->base + IO_BASE_OFFSET);
+ sinfo->fb_base = (caddr_t) (sinfo->base + 0);
+ break;
+ case PCI_DEVICE_ID_SMI_LYNX_3DM:
+ sinfo->dpport =
+ (caddr_t) (sinfo->base + LYNX3DM_DPPORT_BASE_OFFSET);
+ sinfo->dpr = (caddr_t) (sinfo->base + LYNX3DM_DP_BASE_OFFSET);
+ sinfo->vpr = (caddr_t) (sinfo->base + LYNX3DM_VP_BASE_OFFSET);
+ sinfo->cpr = (caddr_t) (sinfo->base + LYNX3DM_CP_BASE_OFFSET);
+ sinfo->mmio = (caddr_t) (sinfo->base + LYNX3DM_IO_BASE_OFFSET);
+ sinfo->fb_base =
+ (caddr_t) (sinfo->base + LYNX3DM_FB_BASE_OFFSET);
+ break;
+ }
+ regSR_write(sinfo->mmio, 0x18, 0x11);
+
+ pr_debug("sinfo->dpport = 0x%08x\n", (u_int32_t) sinfo->dpport);
+ pr_debug("sinfo->dpr = 0x%08x, sinfo->vpr = 0x%08x\n",
+ (unsigned int)sinfo->dpr, (unsigned int)sinfo->vpr);
+ pr_debug("sinfo->cpr = 0x%08x, sinfo->mmio = 0x%08x\n",
+ (unsigned int)sinfo->cpr, (unsigned int)sinfo->mmio);
+
+ /* Set the chip in color mode and unlock the registers */
+ VGA_WRITE8(sinfo->mmio, 0x3c2, 0x2b); /* Miscellaneous Output Register ( write 0x3c2, read 0x3cc ) */
+
+ Unlock(sinfo);
+ UnlockVGA(sinfo);
+
+ /* save the current chip status */
+ switch ((sinfo->pd)->device) {
+ case PCI_DEVICE_ID_SMI_LYNX_EM_PLUS:
+ regSR_write(sinfo->mmio, 0x62, 0xff);
+ regSR_write(sinfo->mmio, 0x6a, 0x0c);
+ regSR_write(sinfo->mmio, 0x6b, 0x02);
+
+ *(u32 *) (sinfo->fb_base + 4) = 0xaa551133;
+ pr_debug(" *(u32 *)(sinfo->fb_base +4) = 0x%08x\n",
+ *(u32 *) (sinfo->fb_base + 4));
+ if (*(u32 *) (sinfo->fb_base + 4) != 0xaa551133) {
+ /* Program the MCLK to 130MHz */
+ regSR_write(sinfo->mmio, 0x6a, 0x10);
+ regSR_write(sinfo->mmio, 0x6b, 0x02);
+ regSR_write(sinfo->mmio, 0x62, 0x3e);
+ sinfo->fbsize = 2 * 1024 * 1024; /* LynxEM+ */
+ pr_debug
+ ("ChipID = LynxEM+. Force the MCLK to 85MHz and the memory size to 2MiB\n");
+ } else {
+ sinfo->fbsize = 4 * 1024 * 1024; /* LynxEM4+ */
+ pr_debug
+ ("ChipID = LynxEM4+. Force the MCLK to 85MHz and the memory size to 4MiB\n");
+ }
+ sinfo->fb_base_phys = sinfo->base_phys;
+ break;
+ case PCI_DEVICE_ID_SMI_LYNX_3DM:
+ {
+ int tmp;
+ int mem_table[4] = { 8, 16, 0, 4 };
+ tmp = (regSR_read(sinfo->mmio, 0x76) & 0xff);
+ pr_debug("%02x\n", tmp);
+ sinfo->fbsize = mem_table[(tmp >> 6)] * 1024 * 1024;
+
+ regSR_write(sinfo->mmio, 0x62, 0xff);
+ regSR_write(sinfo->mmio, 0x6a, 0x0c);
+ regSR_write(sinfo->mmio, 0x6b, 0x02);
+
+ sinfo->fb_base_phys =
+ sinfo->base_phys + LYNX3DM_FB_BASE_OFFSET;
+ }
+ break;
+ default:
+ /* this driver supports only LynxEM+/EM4+ */
+ goto err_out_free_base;
+ };
+
+ info = &(sinfo->info);
+ smifb_get_fix(&vgxfb_fix, -1, info);
+
+ info->flags = FBINFO_FLAG_DEFAULT;
+ info->fbops = &smifb_ops;
+ info->var = smifb_default_var;
+ info->fix = vgxfb_fix;
+ info->pseudo_palette = colreg;
+ info->screen_base = sinfo->fb_base;
+
+ smi_load_video_mode(sinfo, &smifb_default_var);
+
+ if (register_framebuffer(&sinfo->info) < 0) {
+ goto err_out_free_base;
+ }
+ pci_set_drvdata(pd, sinfo);
+
+ printk(KERN_INFO "smifb: " "framebuffer (%s)\n", sinfo->drvr_name);
+
+ return 0;
+
+ err_out_free_base:
+ release_mem_region(sinfo->base_phys, len);
+ err_out_kfree:
+ kfree(sinfo);
+ err_out:
+ return -ENODEV;
+}
+
+static void __devexit smifb_remove(struct pci_dev *pd)
+{
+ struct smifb_info *sinfo = pci_get_drvdata(pd);
+ pr_debug("smifb_remove");
+
+ if (!sinfo)
+ return;
+
+ unregister_framebuffer(&sinfo->info);
+
+ /* stop the lynx chip */
+ release_mem_region(sinfo->base_phys, pci_resource_len(sinfo->pd, 0));
+ kfree(sinfo);
+ pci_set_drvdata(pd, NULL);
+}
+
+/*
+ * Initialization
+ *
+ */
+#ifndef MODULE
+int __init smifb_setup(char *options)
+{
+ pr_debug("smifb_setup");
+
+ if (!options || options)
+ return 0;
+ return 0;
+}
+#endif /* not MODULE */
+
+static struct pci_driver smifb_driver = {
+ .name = "smifb",
+ .id_table = smifb_pci_tbl,
+ .probe = smifb_probe,
+ .remove = __devexit_p(smifb_remove),
+};
+
+/*
+ * Driver initialization
+ */
+int __init smifb_init(void)
+{
+ pr_debug("smifb_init");
+ return pci_module_init(&smifb_driver);
+}
+
+void __exit smifb_exit(void)
+{
+ pci_unregister_driver(&smifb_driver);
+}
+
+module_init(smifb_init);
+module_exit(smifb_exit);
+
+MODULE_AUTHOR("Sergey Podstavin");
+MODULE_DESCRIPTION("Framebuffer driver for NEC Electronics Corporation VR5701 SolutionGearII");
+MODULE_LICENSE("GPL");
Index: linux-2.6.10/drivers/video/smi/smi_hw.h
===================================================================
--- /dev/null
+++ linux-2.6.10/drivers/video/smi/smi_hw.h
@@ -0,0 +1,197 @@
+/*
+ * drivers/video/smi/smi_hw.h
+ *
+ * LynxEM+/EM4+(Silicon Motion Inc.) fb driver for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __SMI_HW_H__
+#define __SMI_HW_H__
+
+#include "smifb.h"
+
+#define DPPORT_BASE_OFFSET 0x400000
+#define DP_BASE_OFFSET 0x408000
+#define VP_BASE_OFFSET 0x40c000
+#define CP_BASE_OFFSET 0x40e000
+#define IO_BASE_OFFSET 0x700000
+
+#define DPPORT_REGION_SIZE (32*1024)
+#define DPREG_REGION_SIZE (16*1024)
+#define VPREG_REGION_SIZE (8*1024)
+#define CPREG_REGION_SIZE (8*1024)
+#define MMIO_REGION_SIZE (1*1024*1024)
+
+#define LYNX3DM_DPPORT_BASE_OFFSET 0x100000
+#define LYNX3DM_DP_BASE_OFFSET 0x000000
+#define LYNX3DM_VP_BASE_OFFSET 0x000800
+#define LYNX3DM_CP_BASE_OFFSET 0x001000
+#define LYNX3DM_IO_BASE_OFFSET 0x0c0000
+#define LYNX3DM_FB_BASE_OFFSET 0x200000
+
+#define LYNX3DM_DPPORT_REGION_SIZE (1024*1024)
+#define LYNX3DM_DPREG_REGION_SIZE (2*1024)
+#define LYNX3DM_VPREG_REGION_SIZE (2*1024)
+#define LYNX3DM_CPREG_REGION_SIZE (2*1024)
+#define LYNX3DM_MMIO_REGION_SIZE (256*1024)
+
+extern void smi_set_moderegs(struct smifb_info *sinfo,
+ int bpp, int width, int height,
+ int hDisplaySize,
+ int hDisplay, int hStart, int hEnd, int hTotal,
+ int vDisplay, int vStart, int vEnd, int vTotal,
+ int dotClock, int sync);
+
+#define MMIO_OUT8(p, r, d) (((volatile u8 *)(p))[r] = (d))
+#define MMIO_OUT16(p, r, d) (((volatile u16 *)(p))[(r)>>1] = (d))
+#define MMIO_OUT32(p, r, d) (((volatile u32 *)(p))[(r)>>2] = (d))
+#define MMIO_IN8(p, r) (((volatile u8 *)(p))[(r)])
+#define MMIO_IN16(p, r) (((volatile u16 *)(p))[(r)>>1])
+#define MMIO_IN32(p, r) (((volatile u32 *)(p))[(r)>>2])
+
+static inline u8 VGA_READ8(u8 * base, uint reg)
+{
+ return MMIO_IN8(base, reg);
+}
+
+static inline void VGA_WRITE8(u8 * base, uint reg, u8 data)
+{
+ MMIO_OUT8(base, reg, data);
+}
+
+static inline u8 VGA_READ8_INDEX(u8 * base, u8 index)
+{
+ VGA_WRITE8(base, 0x3c4, index);
+ return VGA_READ8(base, 0x3c5);
+}
+
+static inline void VGA_WRITE8_INDEX(u8 * base, u8 index, u8 data)
+{
+ VGA_WRITE8(base, 0x3c4, index);
+ VGA_WRITE8(base, 0x3c5, data);
+}
+
+static inline u8 regSR_read(u8 * base, u8 index)
+{
+ VGA_WRITE8(base, 0x3c4, index);
+ return VGA_READ8(base, 0x3c5);
+}
+
+static inline void regSR_write(u8 * base, u8 index, u8 data)
+{
+ VGA_WRITE8(base, 0x3c4, index);
+ VGA_WRITE8(base, 0x3c5, data);
+}
+
+static inline u8 regCR_read(u8 * base, u8 index)
+{
+ VGA_WRITE8(base, 0x3d4, index);
+ return VGA_READ8(base, 0x3d5);
+}
+
+static inline void regCR_write(u8 * base, u8 index, u8 data)
+{
+ VGA_WRITE8(base, 0x3d4, index);
+ VGA_WRITE8(base, 0x3d5, data);
+}
+
+static inline u8 regGR_read(u8 * base, u8 index)
+{
+ VGA_WRITE8(base, 0x3ce, index);
+ return VGA_READ8(base, 0x3cf);
+}
+
+static inline void regGR_write(u8 * base, u8 index, u8 data)
+{
+ VGA_WRITE8(base, 0x3ce, index);
+ VGA_WRITE8(base, 0x3cf, data);
+}
+
+static inline u8 regAR_read(u8 * base, u8 index)
+{
+ (void)VGA_READ8(base, 0x3da); /* reset flip-flop */
+ VGA_WRITE8(base, 0x3c0, index);
+ return VGA_READ8(base, 0x3c1);
+}
+
+static inline void regAR_write(u8 * base, u8 index, u8 data)
+{
+ (void)VGA_READ8(base, 0x3da); /* reset flip-flop */
+ VGA_WRITE8(base, 0x3c0, index);
+ VGA_WRITE8(base, 0x3c0, data);
+}
+
+/*
+ * LynxEM+ registers
+ */
+
+/* Drawing Engine Control Registers */
+#define reg_DPR00(x) *(u16 *)((x)->dpr+0x00) /* Source Y or K2 */
+#define reg_DPR02(x) *(u16 *)((x)->dpr+0x02) /* Source X or K1 */
+#define reg_DPR04(x) *(u16 *)((x)->dpr+0x04) /* Destination Y or Start Y */
+#define reg_DPR06(x) *(u16 *)((x)->dpr+0x06) /* Destination X or Start X */
+#define reg_DPR08(x) *(u16 *)((x)->dpr+0x08) /* Dimension Y or Error Term */
+#define reg_DPR0A(x) *(u16 *)((x)->dpr+0x0A) /* Dimension X or Vector Length */
+#define reg_DPR0C(x) *(u16 *)((x)->dpr+0x0C) /* ROP and Miscellaneous Control */
+#define reg_DPR0E(x) *(u16 *)((x)->dpr+0x0E) /* Drawing Engine Commands and Control */
+#define reg_DPR10(x) *(u16 *)((x)->dpr+0x10) /* Source Row Pitch */
+#define reg_DPR12(x) *(u16 *)((x)->dpr+0x12) /* Destination Row Picth */
+#define reg_DPR14(x) *(u32 *)((x)->dpr+0x14) /* Foreground Colors */
+#define reg_DPR18(x) *(u32 *)((x)->dpr+0x18) /* Background Colors */
+#define reg_DPR1C(x) *(u16 *)((x)->dpr+0x1C) /* Stretch Source Height Y */
+#define reg_DPR1E(x) *(u16 *)((x)->dpr+0x1E) /* Drawing Engine DataFormat and Location Format Select */
+#define reg_DPR20(x) *(u32 *)((x)->dpr+0x20) /* Color Compare */
+#define reg_DPR24(x) *(u32 *)((x)->dpr+0x24) /* Color Compare Mask */
+#define reg_DPR28(x) *(u16 *)((x)->dpr+0x28) /* Bit Mask */
+#define reg_DPR2A(x) *(u16 *)((x)->dpr+0x2A) /* Byte Mask Enable */
+#define reg_DPR2C(x) *(u16 *)((x)->dpr+0x2C) /* Scisors Left and Control */
+#define reg_DPR2E(x) *(u16 *)((x)->dpr+0x2E) /* Scisors Top */
+#define reg_DPR30(x) *(u16 *)((x)->dpr+0x30) /* Scisors Right */
+#define reg_DPR32(x) *(u16 *)((x)->dpr+0x32) /* Scisors Bottom */
+#define reg_DPR34(x) *(u32 *)((x)->dpr+0x34) /* Mono Pattern Low */
+#define reg_DPR38(x) *(u32 *)((x)->dpr+0x38) /* Mono Pattern High */
+#define reg_DPR3C(x) *(u32 *)((x)->dpr+0x3C) /* XY Addressing Destination & Source Window Widths */
+#define reg_DPR40(x) *(u32 *)((x)->dpr+0x40) /* Source Base Address */
+#define reg_DPR44(x) *(u32 *)((x)->dpr+0x44) /* Destination Base Address */
+
+/* Video Processor Control Registers */
+#define reg_VPR00(x) *(u32 *)((x)->vpr+0x00) /* Miscellaneous Graphics and Video Control */
+#define reg_VPR04(x) *(u32 *)((x)->vpr+0x04) /* Color Keys */
+#define reg_VPR08(x) *(u32 *)((x)->vpr+0x08) /* Color Key Masks */
+#define reg_VPR0C(x) *(u32 *)((x)->vpr+0x0C) /* Data Source Start Address for Extended Graphics Modes */
+#define reg_VPR10(x) *(u32 *)((x)->vpr+0x10) /* Data Source Width and Offset for Extended Graphics Modes */
+#define reg_VPR14(x) *(u32 *)((x)->vpr+0x14) /* Video Window I Left and Top Boundaries */
+#define reg_VPR18(x) *(u32 *)((x)->vpr+0x18) /* Video Window I Right and Bottom Boundaries */
+#define reg_VPR1C(x) *(u32 *)((x)->vpr+0x1C) /* Video Window I Source Start Address */
+#define reg_VPR20(x) *(u32 *)((x)->vpr+0x20) /* Video Window I Source Width and Offset */
+#define reg_VPR24(x) *(u32 *)((x)->vpr+0x24) /* Video Window I Stretch Factor */
+#define reg_VPR28(x) *(u32 *)((x)->vpr+0x28) /* Video Window II Left and Top Boundaries */
+#define reg_VPR2C(x) *(u32 *)((x)->vpr+0x2C) /* Video Window II Right and Bottom Boundaries */
+#define reg_VPR30(x) *(u32 *)((x)->vpr+0x30) /* Video Window II Source Start Address */
+#define reg_VPR34(x) *(u32 *)((x)->vpr+0x34) /* Video Window II Source Width and Offset */
+#define reg_VPR38(x) *(u32 *)((x)->vpr+0x38) /* Video Window II Stretch Factor */
+#define reg_VPR3C(x) *(u32 *)((x)->vpr+0x3C) /* Graphics and Video Controll II */
+#define reg_VPR40(x) *(u32 *)((x)->vpr+0x40) /* Graphic Scale Factor */
+#define reg_VPR54(x) *(u32 *)((x)->vpr+0x54) /* FIFO Priority Control */
+#define reg_VPR58(x) *(u32 *)((x)->vpr+0x58) /* FIFO Empty Request level Control */
+#define reg_VPR5C(x) *(u32 *)((x)->vpr+0x5C) /* YUV to RGB Conversion Constant */
+#define reg_VPR60(x) *(u32 *)((x)->vpr+0x60) /* Current Scan Line Position */
+#define reg_VPR64(x) *(u32 *)((x)->vpr+0x64) /* Signature Analyzer Control and Status */
+#define reg_VPR68(x) *(u32 *)((x)->vpr+0x68) /* Video Window I Stretch Factor */
+#define reg_VPR6C(x) *(u32 *)((x)->vpr+0x6C) /* Video Window II Stretch Factor */
+
+/* Capture Processor Control Registers */
+#define reg_CPR00(x) *(u32 *)((x)->cpr+0x00) /* Capture Port Control */
+#define reg_CPR04(x) *(u32 *)((x)->cpr+0x04) /* Video Source Clipping Control */
+#define reg_CPR08(x) *(u32 *)((x)->cpr+0x08) /* Video Source Capture Size Control */
+#define reg_CPR0C(x) *(u32 *)((x)->cpr+0x0C) /* Capture Port Buffer I Source Start Address */
+#define reg_CPR10(x) *(u32 *)((x)->cpr+0x10) /* Capture Port Buffer II Source Start Address */
+#define reg_CPR14(x) *(u32 *)((x)->cpr+0x14) /* Capture Port Source Offset Address */
+#define reg_CPR18(x) *(u32 *)((x)->cpr+0x18) /* Capture FIFO Empty Request level Control */
+
+#endif /* __SMI_HW_H__ */
Index: linux-2.6.10/arch/mips/Kconfig
===================================================================
--- linux-2.6.10.orig/arch/mips/Kconfig
+++ linux-2.6.10/arch/mips/Kconfig
@@ -449,6 +449,17 @@ config DDB5477_BUS_FREQUENCY
depends on DDB5477
default 0
+config TCUBE
+ bool "Support for NEC Electronics Corporation VR5701 SolutionGearII"
+ select IRQ_CPU
+ select HW_HAS_PCI
+ select DMA_NONCOHERENT
+ help
+ This enables support for the VR5500 - based NEC Electronics Corporation
+ VR5701 SolutionGearII evaluation board.
+
+
+
config NEC_OSPREY
bool "Support for NEC Osprey board"
select DMA_NONCOHERENT
@@ -1204,6 +1215,11 @@ config CPU_R5000
config CPU_R5432
bool "R5432"
+config CPU_R5500
+ bool "R5500"
+ help
+ MIPS Technologies Vr5500 - series processors.
+
config CPU_R6000
bool "R6000"
depends on MIPS32 && EXPERIMENTAL
Index: linux-2.6.10/arch/mips/vr5701/tcube/Makefile
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/tcube/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the NEC Electronics Corporation VR5701 SolutionGearII specific kernel interface routines
+# under Linux.
+#
+
+obj-y += setup.o irq.o int-handler.o irq_vr5701.o
+EXTRA_AFLAGS: = $(CFLAGS)
Index: linux-2.6.10/arch/mips/vr5701/common/rtc_rx5c348.c
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/common/rtc_rx5c348.c
@@ -0,0 +1,182 @@
+/*
+ * arch/mips/vr5701/common/rtc_rx5c348.c Version 0.02 April 11, 2005
+ *
+ * A Real Time Clock interface for Linux on NEC Electronics Corporation VR5701 SolutionGearII
+ * (RICOH Co., Ltd., Rx5C348B)
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/kernel.h>
+#include <linux/bcd.h>
+
+#include <asm/time.h>
+#include <asm/addrspace.h>
+#include <asm/delay.h>
+#include <asm/debug.h>
+#include <asm/tcube.h>
+
+#undef DEBUG
+#undef RTC_DELAY
+
+void static rtc_set_ce(u32 val)
+{
+ pr_debug("rtc_set_ce(%d)\n", val);
+ reg_set32(GIU_PIO0, GPIO_4_CE, val ? SET_32_BIT : 0);
+#ifdef RTC_DELAY
+ __delay(100000);
+#endif
+}
+
+void static rtc_write_burst(int adr, unsigned char *data, int dataLen)
+{
+ int i;
+ for (i = 0; i < dataLen; i++)
+ pr_debug(" rtc_write_burst : data=%08x\n", data[i]);
+ pr_debug(" rtc_write_burst : adr=0x%02x\n", adr);
+ csi1_reset();
+ while (io_in32(CSI1_MODE) & CSIn_MODE_CSOT) ;
+ reg_set32(CSI1_MODE, CSIn_MODE_AUTO, SET_32_BIT);
+ reg_set32(CSI1_MODE, CSIn_MODE_TRMD, SET_32_BIT);
+ io_out32(CSI1_INT, CSIn_INT_CSIEND);
+ rtc_set_ce(1);
+
+ pr_debug(" rtc_write_burst : CSI1_MODE=%08x\n", io_in32(CSI1_MODE));
+ pr_debug(" rtc_write_burst : CSI1_CNT=%08x\n", io_in32(CSI1_CNT));
+ io_out32(CSI1_SOTBF, ((adr << 4) | 0x00));
+
+ for (i = 0; i < dataLen; i++) {
+ io_out32(CSI1_SOTB, data[i]);
+ while (!(io_in32(CSI1_INT) & CSIn_INT_CSIEND)) ;
+ io_out32(CSI1_INT, CSIn_INT_CSIEND);
+ }
+ while (io_in32(CSI1_MODE) & CSIn_MODE_CSOT) ;
+ rtc_set_ce(0);
+}
+
+void static rtc_read_burst(int adr, unsigned char *data, int dataLen)
+{
+ int i;
+ pr_debug(" rtc_read_burst : adr=0x%02x\n", adr);
+ while (io_in32(CSI1_MODE) & CSIn_MODE_CSOT) ;
+ reg_set32(CSI1_MODE, CSIn_MODE_AUTO, CLR_32_BIT);
+ reg_set32(CSI1_MODE, CSIn_MODE_TRMD, SET_32_BIT);
+ io_out32(CSI1_INT, CSIn_INT_CSIEND);
+ rtc_set_ce(1);
+
+ pr_debug(" rtc_read_burst : CSI1_MODE=%08x\n", io_in32(CSI1_MODE));
+ pr_debug(" rtc_read_burst : CSI1_CNT=%08x\n", io_in32(CSI1_CNT));
+ io_out32(CSI1_SOTB, (((adr & 0xf) << 4) | 0x04));
+ while (!(io_in32(CSI1_INT) & CSIn_INT_CSIEND)) ;
+
+ while (io_in32(CSI1_MODE) & CSIn_MODE_CSOT) ;
+ reg_set32(CSI1_MODE, CSIn_MODE_TRMD, CLR_32_BIT);
+ io_out32(CSI1_INT, CSIn_INT_CSIEND);
+
+ udelay(50);
+ pr_debug(" rtc_read_burst : CSI1_MODE=%08x\n", io_in32(CSI1_MODE));
+ pr_debug(" rtc_read_burst : CSI1_CNT=%08x\n", io_in32(CSI1_CNT));
+ io_in32(CSI1_SIRB); /* dummy read */
+
+ for (i = 0; i < dataLen; i++) {
+ while (!(io_in32(CSI1_INT) & CSIn_INT_CSIEND)) ;
+ io_out32(CSI1_INT, CSIn_INT_CSIEND);
+ data[i] = io_in32(CSI1_SIRB);
+ }
+ while (io_in32(CSI1_MODE) & CSIn_MODE_CSOT) ;
+ rtc_set_ce(0);
+ for (i = 0; i < dataLen; i++)
+ pr_debug(" rtc_read_burst : data=%08x\n", data[i]);
+}
+
+static unsigned long rtc_ricoh_rx5c348_get_time(void)
+{
+ u8 date[7];
+ unsigned int year, month, day, hour, minute, second;
+
+ rtc_read_burst(0, date, sizeof(date));
+
+ year = BCD2BIN(date[6]) + (date[5] & 0x80 ? 2000 : 1900);
+ month = BCD2BIN(date[5] & 0x1f);
+ day = BCD2BIN(date[4]);
+ hour = BCD2BIN(date[2]);
+ minute = BCD2BIN(date[1]);
+ second = BCD2BIN(date[0]);
+
+ pr_debug(KERN_INFO
+ "rtc_ricoh_rx5c348_get_time: %d/%02d/%02d %02d:%02d:%02d\n",
+ year, month, day, hour, minute, second);
+ return mktime(year, month, day, hour, minute, second);
+}
+
+static int rtc_ricoh_rx5c348_set_time(unsigned long t)
+{
+ u8 date[7];
+ struct rtc_time tm;
+
+ to_tm(t, &tm);
+ date[0] = BIN2BCD(tm.tm_sec);
+ date[1] = BIN2BCD(tm.tm_min);
+ date[2] = BIN2BCD(tm.tm_hour);
+ date[4] = BIN2BCD(tm.tm_mday);
+ date[5] = BIN2BCD(tm.tm_mon + 1) + (tm.tm_year > 1999 ? 0x80 : 0);
+ date[6] =
+ BIN2BCD(tm.tm_year > 1999 ? tm.tm_year - 2000 : tm.tm_year - 1900);
+
+ rtc_write_burst(0, date, 3);
+ rtc_write_burst(4, date + 4, 3);
+
+ pr_debug(KERN_INFO
+ "rtc_ricoh_rx5c348_set_time:t=%ld %d/%02d/%02d %02d:%02d:%02d\n",
+ t, tm.tm_year, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
+ tm.tm_min, tm.tm_sec);
+ return 0;
+}
+
+static int __devinit rtc_ricoh_rx5c348_init(void)
+{
+ unsigned char data;
+ /* CSI1 reset */
+ io_set16(PIB_RESET, 0x40, 0xffff);
+ __delay(10000);
+ io_set16(PIB_RESET, 0x40, 0x0000);
+
+ /* set GPIO3 , GPIO4 */
+ reg_set32(GIU_FUNCSEL0, (GPIO_4_CE | GPIO_3_INTR), SET_32_BIT);
+ /* clear GPIO25 , GPIO26 , GPIO27 */
+ reg_set32(GIU_FUNCSEL0, GPIO_CSI1_PIN, CLR_32_BIT);
+ /* make GPIO4 output */
+ reg_set32(GIU_DIR0, GPIO_4_CE, SET_32_BIT);
+ /* make GPIO3 input */
+ reg_set32(GIU_DIR0, GPIO_3_INTR, CLR_32_BIT);
+
+ csi1_reset();
+
+ rtc_read_burst(0x0e, &data, 1);
+ if ((data & 0x20) == 0) { /* 24 hour */
+ data |= 0x20;
+ rtc_write_burst(0x0e, &data, 1);
+#ifdef RTC_DELAY
+ __delay(10000);
+#endif
+ }
+
+ /* set the function pointers */
+ rtc_get_time = rtc_ricoh_rx5c348_get_time;
+ rtc_set_time = rtc_ricoh_rx5c348_set_time;
+ return 0;
+}
+
+module_init(rtc_ricoh_rx5c348_init);
+
+MODULE_AUTHOR("Sergey Podstavin");
+MODULE_DESCRIPTION("Real Time Clock interface for Linux on NEC Electronics Corporation VR5701 SolutionGearII");
+MODULE_LICENSE("GPL");
Index: linux-2.6.10/drivers/pci/pci.ids
===================================================================
--- linux-2.6.10.orig/drivers/pci/pci.ids
+++ linux-2.6.10/drivers/pci/pci.ids
@@ -1451,7 +1451,7 @@
6057 MiroVideo DC10/DC30+
1032 Compaq
1033 NEC Corporation
- 0000 Vr4181A USB Host or Function Control Unit
+ 0000 Vr4181A USB Host or IDE Controller
0001 PCI to 486-like bus Bridge
0002 PCI to VL98 Bridge
0003 ATM Controller
@@ -1491,7 +1491,7 @@
1033 8014 RCV56ACF 56k Voice Modem
009b Vrc5476
00a5 VRC4173
- 00a6 VRC5477 AC97
+ 00a6 VRC5477 or VR5701 AC97 Controller
00cd IEEE 1394 [OrangeLink] Host Controller
12ee 8011 Root hub
00ce IEEE 1394 Host Controller
Index: linux-2.6.10/drivers/video/smi/Makefile
===================================================================
--- /dev/null
+++ linux-2.6.10/drivers/video/smi/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for LynxEM+/EM4+(Silicon Motion Inc.) fb driver for NEC Electronics Corporation VR5701 SolutionGearII
+# under Linux.
+#
+
+obj-$(CONFIG_FB_SM) += smfb.o
+
+smfb-objs := smi_base.o smi_hw.o
+
Index: linux-2.6.10/arch/mips/vr5701/tcube/setup.c
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/tcube/setup.c
@@ -0,0 +1,188 @@
+/*
+ * arch/mips/vr5701/tcube/setup.c
+ *
+ * Setup file for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/console.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/fs.h> /* for ROOT_DEV */
+#include <linux/ioport.h>
+#include <linux/param.h> /* for HZ */
+#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+#include <asm/time.h>
+#include <asm/bcache.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+#include <asm/gdb-stub.h>
+#include <asm/debug.h>
+#include <asm/tcube.h>
+
+static void tcube_machine_restart(char *command)
+{
+ static void (*back_to_prom) (void) = (void (*)(void))0xbfc00000;
+ back_to_prom();
+}
+
+static void tcube_machine_halt(void)
+{
+ printk(KERN_CRIT "NEC Electronics Corporation VR5701 SolutionGearII halted.\n");
+ while (1) ;
+}
+
+static void tcube_machine_power_off(void)
+{
+ printk(KERN_CRIT "NEC Electronics Corporation VR5701 SolutionGearII halted. Please turn off the power.\n");
+ while (1) ;
+}
+
+static void __init tcube_time_init(void)
+{
+ mips_hpt_frequency = CPU_COUNTER_FREQUENCY;
+}
+
+static void __init tcube_timer_setup(struct irqaction *irq)
+{
+ unsigned int count;
+ irq->flags |= SA_NODELAY;
+
+ /* we are using the cpu counter for timer interrupts */
+ setup_irq(7, irq);
+
+ /* to generate the first timer interrupt */
+ count = read_c0_count();
+ write_c0_compare(count + 10000);
+}
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+extern unsigned long __rd_start, __rd_end, initrd_start, initrd_end;
+#endif
+
+static void chk_init_5701_reg(unsigned long addr, unsigned long data)
+{
+ unsigned long a = ddb_in32(addr);
+
+ if (a != data) {
+ printk(KERN_INFO
+ "Unexpected 5701 reg : addr = %08lX, expected = %08lX, read = %08lX\n",
+ addr + VR5701_IO_BASE, data, a);
+ }
+}
+
+static void __init tcube_board_init(void)
+{
+ chk_init_5701_reg(0, 0x1e00008f);
+ chk_init_5701_reg(PADR_SDRAM01, 0x000000a8);
+ chk_init_5701_reg(PADR_LOCALCS0, 0x1f00004c);
+ chk_init_5701_reg(LOCAL_CST0, 0x00088622);
+ chk_init_5701_reg(LOCAL_CFG, 0x000f0000);
+
+ /* setup PCI windows - window0 for MEM/config, window1 for IO */
+ ddb_set_pdar(PADR_PCIW0, 0x10000000, 0x08000000, 32, 0, 1);
+ ddb_set_pdar(PADR_PCIW1, 0x18000000, 0x00800000, 32, 0, 1);
+ ddb_set_pdar(PADR_IOPCIW0, 0x18800000, 0x00800000, 32, 0, 1);
+ ddb_set_pdar(PADR_IOPCIW1, 0x19000000, 0x00800000, 32, 0, 1);
+ /* ------------ reset PCI bus and BARs ----------------- */
+ ddb_pci_reset_bus();
+ /* Ext. PCI memory space */
+ ddb_out32(PCI_BAR_MEM01, 0x00000008);
+ ddb_out8(PCI_MLTIM, 0x40);
+
+ ddb_out32(PCI_BAR_LCS0, 0xffffffff);
+ ddb_out32(PCI_BAR_LCS1, 0xffffffff);
+ ddb_out32(PCI_BAR_LCS2, 0xffffffff);
+ ddb_out32(PCI_BAR_LCS3, 0xffffffff);
+ /* Int. PCI memory space */
+ ddb_out8(IPCI_MLTIM, 0x40);
+
+ ddb_out32(IPCI_BAR_LCS0, 0xffffffff);
+ ddb_out32(IPCI_BAR_LCS1, 0xffffffff);
+ ddb_out32(IPCI_BAR_LCS2, 0xffffffff);
+ ddb_out32(IPCI_BAR_LCS3, 0xffffffff);
+ ddb_out32(IPCI_BAR_IREG, 0xffffffff);
+
+ /*
+ * We use pci master register 0 for memory space / config space
+ * And we use register 1 for IO space.
+ * Note that for memory space, we bump up the pci base address
+ * so that we have 1:1 mapping between PCI memory and cpu physical.
+ * For PCI IO space, it starts from 0 in PCI IO space but with
+ * IO_BASE in CPU physical address space.
+ */
+ ddb_set_pmr(EPCI_INIT0, DDB_PCICMD_MEM, 0x10000000, DDB_PCI_ACCESS_32);
+ ddb_set_pmr(EPCI_INIT1, DDB_PCICMD_IO, 0x00001000, DDB_PCI_ACCESS_32);
+ ddb_set_pmr(IPCI_INIT0, DDB_PCICMD_MEM, 0x18800000, DDB_PCI_ACCESS_32);
+ ddb_set_pmr(IPCI_INIT1, DDB_PCICMD_IO, 0x01000000, DDB_PCI_ACCESS_32);
+
+ /* PCI cross window should be set properly */
+ ddb_set_pdar(PCI_BAR_IPCIW0, 0x18800000, 0x00800000, 32, 0, 1);
+ ddb_set_pdar(PCI_BAR_IPCIW1, 0x19000000, 0x00800000, 32, 0, 1);
+ ddb_set_pdar(IPCI_BAR_EPCIW0, 0x10000000, 0x08000000, 32, 0, 1);
+ ddb_set_pdar(IPCI_BAR_EPCIW1, 0x18000000, 0x00800000, 32, 0, 1);
+
+ /* setup GPIO */
+ ddb_out32(GIU_DIR0, 0xf7ebffdf);
+ ddb_out32(GIU_DIR1, 0x000007fa);
+ ddb_out32(GIU_FUNCSEL0, 0xf1c1ffff);
+ ddb_out32(GIU_FUNCSEL1, 0x000007f0);
+ chk_init_5701_reg(GIU_DIR0, 0xf7ebffdf);
+ chk_init_5701_reg(GIU_DIR1, 0x000007fa);
+ chk_init_5701_reg(GIU_FUNCSEL0, 0xf1c1ffff);
+ chk_init_5701_reg(GIU_FUNCSEL1, 0x000007f0);
+
+ /* enable USB input buffers */
+ ddb_out32(PIB_MISC, (ddb_in32(PIB_MISC) | 0x00000031));
+}
+
+int __init shima_tcube_setup(void)
+{
+ set_io_port_base(0xB8000000);
+
+ board_time_init = tcube_time_init;
+ board_timer_setup = tcube_timer_setup;
+
+ _machine_restart = tcube_machine_restart;
+ _machine_halt = tcube_machine_halt;
+ _machine_power_off = tcube_machine_power_off;
+
+ /* setup resource limits */
+ ioport_resource.end = 0x02000000;
+ iomem_resource.end = 0xffffffff;
+
+ /* Reboot on panic */
+ panic_timeout = 30;
+
+#ifdef CONFIG_FB
+ conswitchp = &dummy_con;
+#endif
+
+ tcube_board_init();
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+ initrd_start = (unsigned long)&__rd_start;
+ initrd_end = (unsigned long)&__rd_end;
+#endif
+ register_pci_controller(&VR5701_ext_controller);
+ register_pci_controller(&VR5701_io_controller);
+ return 0;
+}
+
+void __init bus_error_init(void)
+{
+ /* do nothing */
+}
+
+early_initcall(shima_tcube_setup);
Index: linux-2.6.10/drivers/ide/Kconfig
===================================================================
--- linux-2.6.10.orig/drivers/ide/Kconfig
+++ linux-2.6.10/drivers/ide/Kconfig
@@ -836,6 +836,13 @@ config BLK_DEV_GAYLE
Note that you also have to enable Zorro bus support if you want to
use Gayle IDE interfaces on the Zorro expansion bus.
+config BLK_DEV_NEC_VR5701_SG2
+ tristate "NEC Electronics Corporation VR5701 SolutionGearII IDE interface support"
+ depends on TCUBE
+ help
+ This is the IDE driver for the NEC Electronics Corporation VR5701
+ SolutionGearII IDE interface.
+
config BLK_DEV_IDEDOUBLER
bool "Amiga IDE Doubler support (EXPERIMENTAL)"
depends on BLK_DEV_GAYLE && EXPERIMENTAL
Index: linux-2.6.10/arch/mips/vr5701/tcube/irq.c
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/tcube/irq.c
@@ -0,0 +1,146 @@
+/*
+ * arch/mips/vr5701/tcube/irq.c
+ *
+ * The irq setup and misc routines for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <asm/system.h>
+#include <asm/mipsregs.h>
+#include <asm/debug.h>
+#include <asm/tcube.h>
+/*
+ * IRQ mapping
+ *
+ * 0-7: 8 CPU interrupts
+ * 0 - software interrupt 0
+ * 1 - software interrupt 1
+ * 2 - most Vrc5477 interrupts are routed to this pin
+ * 3 - (optional) some other interrupts routed to this pin for debugg
+ * 4 - not used
+ * 5 - not used
+ * 6 - not used
+ * 7 - cpu timer (used by default)
+ *
+ */
+
+void tcube_irq_setup(void)
+{
+ pr_debug("NEC Electronics Corporation VR5701 SolutionGearII irq setup invoked.\n");
+
+ /* by default, we disable all interrupts and route all vr5701
+ * interrupts to pin 0 (irq 2) */
+ ddb_out32(INT_ROUTE0, 0);
+ ddb_out32(INT_ROUTE1, 0);
+ ddb_out32(INT_ROUTE2, 0);
+ ddb_out32(INT_ROUTE3, 0);
+ ddb_out32(INT_MASK, 0);
+ ddb_out32(INT_CLR, ~0x0);
+
+ clear_c0_status(0xff00);
+ set_c0_status(0x0400);
+
+ ll_vr5701_irq_route(24, 1);
+ ll_vr5701_irq_enable(24);
+ ll_vr5701_irq_route(25, 1);
+ ll_vr5701_irq_enable(25);
+ ll_vr5701_irq_route(28, 1);
+ ll_vr5701_irq_enable(28);
+ ll_vr5701_irq_route(29, 1);
+ ll_vr5701_irq_enable(29);
+ ll_vr5701_irq_route(30, 1);
+ ll_vr5701_irq_enable(30);
+ ll_vr5701_irq_route(31, 1);
+ ll_vr5701_irq_enable(31);
+ set_c0_status(0x0800);
+ set_except_vector(0, tcube_handle_int);
+ /* init all controllers */
+ mips_cpu_irq_init(0);
+ vr5701_irq_init(8);
+}
+
+/*
+ * the first level int-handler will jump here if it is a vr7701 irq
+ */
+
+asmlinkage void tcube_irq_dispatch(struct pt_regs *regs)
+{
+ u32 intStatus;
+ u32 bitmask;
+ u32 i;
+ u32 intPCIStatus;
+ if (ddb_in32(INT1_STAT) != 0) {
+ printk(KERN_CRIT "NMI = %x\n", ddb_in32(NMI_STAT));
+ printk(KERN_CRIT "INT0 = %x\n", ddb_in32(INT0_STAT));
+ printk(KERN_CRIT "INT1 = %x\n", ddb_in32(INT1_STAT));
+ printk(KERN_CRIT "INT2 = %x\n", ddb_in32(INT2_STAT));
+ printk(KERN_CRIT "INT3 = %x\n", ddb_in32(INT3_STAT));
+ printk(KERN_CRIT "INT4 = %x\n", ddb_in32(INT4_STAT));
+ printk(KERN_CRIT "EPCI_ERR = %x\n", ddb_in32(EPCI_ERR));
+ printk(KERN_CRIT "IPCI_ERR = %x\n", ddb_in32(IPCI_ERR));
+
+ panic("error interrupt has happened.");
+ }
+
+ intStatus = ddb_in32(INT0_STAT);
+
+ if (intStatus & 1 << 6)
+ goto IRQ_EPCI;
+
+ if (intStatus & 1 << 7)
+ goto IRQ_IPCI;
+
+ IRQ_OTHER:
+ for (i = 0, bitmask = 1; i <= NUM_5701_IRQS; bitmask <<= 1, i++) {
+ /* do we need to "and" with the int mask? */
+ if (intStatus & bitmask) {
+ do_IRQ(8 + i, regs);
+ }
+ }
+ return;
+
+ IRQ_EPCI:
+ intStatus &= ~(1 << 6); /* unset Status flag */
+ intPCIStatus = ddb_in32(EPCI_INTS);
+ for (i = 0, bitmask = 1; i < NUM_5701_EPCI_IRQS; bitmask <<= 1, i++) {
+ if (intPCIStatus & bitmask) {
+ do_IRQ(8 + NUM_5701_IRQS + i, regs);
+ }
+ }
+ if (!intStatus)
+ return;
+
+ IRQ_IPCI:
+ intStatus &= ~(1 << 7);
+ intPCIStatus = ddb_in32(IPCI_INTS);
+ if (!intPCIStatus)
+ goto IRQ_OTHER;
+
+ for (i = 0, bitmask = 1; i < NUM_5701_IPCI_IRQS; bitmask <<= 1, i++) {
+ if (intPCIStatus & bitmask) {
+ do_IRQ(8 + NUM_5701_IRQS + NUM_5701_EPCI_IRQS + i,
+ regs);
+ }
+ }
+
+ if (!intStatus)
+ return;
+
+ goto IRQ_OTHER;
+}
+
+void __init arch_init_irq(void)
+{
+ /* invoke board-specific irq setup */
+ tcube_irq_setup();
+}
Index: linux-2.6.10/arch/mips/pci/ops-tcube.c
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/pci/ops-tcube.c
@@ -0,0 +1,267 @@
+/*
+ * arch/mips/pci/ops-tcube.c
+ *
+ * A config access for PCI controllers on NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/addrspace.h>
+#include <asm/debug.h>
+#include <asm/tcube.h>
+
+/*
+ * config_swap structure records what set of pdar/pmr are used
+ * to access pci config space. It also provides a place hold the
+ * original values for future restoring.
+ */
+struct pci_config_swap {
+ u32 pdar;
+ u32 pmr;
+ u32 config_base;
+ u32 config_size;
+ u32 pdar_backup;
+ u32 pmr_backup;
+};
+
+/*
+ * On VR5701-SG2, we have two sets of swap registers, for ext PCI and IOPCI.
+ */
+struct pci_config_swap ext_pci_swap = {
+ PADR_EPCIW0,
+ EPCI_INIT0,
+ 0x10000000,
+ 0x08000000
+};
+struct pci_config_swap io_pci_swap = {
+ PADR_IOPCIW0,
+ IPCI_INIT0,
+ 0x18800000,
+ 0x00800000
+};
+
+/*
+ * access config space
+ */
+static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus, /* 0 means top level bus */
+ u32 slot_num)
+{
+ u32 pci_addr = 0;
+ u32 pciinit_offset = 0;
+ u32 virt_addr;
+ u32 option;
+
+ /* minimum pdar (window) size is 2MB */
+ db_assert(swap->config_size >= (2 << 20));
+ db_assert(slot_num < (1 << 5));
+ db_assert(bus < (1 << 8));
+
+ /* backup registers */
+ swap->pdar_backup = ddb_in32(swap->pdar);
+ swap->pmr_backup = ddb_in32(swap->pmr);
+
+ /* set the pdar (pci window) register */
+ ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32, /* 32 bit wide */
+ 0, /* not on local memory bus */
+ 0); /* not visible from PCI bus (N/A) */
+
+ /*
+ * calcuate the absolute pci config addr;
+ * according to the spec, we start scanning from adr:11 (0x800)
+ */
+ if (bus == 0) {
+ /* type 0 config */
+ pci_addr = 0x800 << slot_num;
+ } else {
+ /* type 1 config */
+ pci_addr = (bus << 16) | (slot_num << 11);
+ }
+
+ /*
+ * if pci_addr is less than pci config window size, we set
+ * pciinit_offset to 0 and adjust the virt_address.
+ * Otherwise we will try to adjust pciinit_offset.
+ */
+ if (pci_addr < swap->config_size) {
+ virt_addr = KSEG1ADDR(swap->config_base + pci_addr);
+ pciinit_offset = 0;
+ } else {
+ db_assert((pci_addr & (swap->config_size - 1)) == 0);
+ virt_addr = KSEG1ADDR(swap->config_base);
+ pciinit_offset = pci_addr;
+ }
+
+ /* set the pmr register */
+ option = DDB_PCI_ACCESS_32;
+ if (bus != 0)
+ option |= DDB_PCI_CFGTYPE1;
+
+ ddb_out32(swap->pmr,
+ (DDB_PCICMD_CFG << 1) | (pciinit_offset & 0xffe00000) |
+ option);
+ ddb_out32(swap->pmr + 4, 0);
+
+ return virt_addr;
+}
+
+static inline void ddb_close_config_base(struct pci_config_swap *swap)
+{
+ ddb_out32(swap->pdar, swap->pdar_backup);
+ ddb_out32(swap->pmr, swap->pmr_backup);
+}
+
+static int read_config_dword(struct pci_config_swap *swap,
+ struct pci_bus *bus, u32 devfn, u32 where,
+ u32 * val)
+{
+ u32 bus_num, slot_num, func_num;
+ u32 base;
+
+ db_assert((where & 3) == 0);
+ db_assert(where < (1 << 8));
+
+ /* check if the bus is top-level */
+ if (bus->parent != NULL) {
+ bus_num = bus->number;
+ db_assert(bus_num != 0);
+ } else {
+ bus_num = 0;
+ }
+ slot_num = PCI_SLOT(devfn);
+ func_num = PCI_FUNC(devfn);
+ base = ddb_access_config_base(swap, bus_num, slot_num);
+ *val = *(volatile u32 *)(base + (func_num << 8) + where);
+ ddb_close_config_base(swap);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int read_config_word(struct pci_config_swap *swap,
+ struct pci_bus *bus, u32 devfn, u32 where,
+ u16 * val)
+{
+ int status;
+ u32 result;
+
+ db_assert((where & 1) == 0);
+
+ status = read_config_dword(swap, bus, devfn, where & ~3, &result);
+ if (where & 2)
+ result >>= 16;
+ *val = result & 0xffff;
+ return status;
+}
+
+static int read_config_byte(struct pci_config_swap *swap,
+ struct pci_bus *bus, u32 devfn, u32 where, u8 * val)
+{
+ int status;
+ u32 result;
+
+ status = read_config_dword(swap, bus, devfn, where & ~3, &result);
+ if (where & 1)
+ result >>= 8;
+ if (where & 2)
+ result >>= 16;
+ *val = result & 0xff;
+
+ return status;
+}
+
+static int write_config_dword(struct pci_config_swap *swap,
+ struct pci_bus *bus, u32 devfn, u32 where,
+ u32 val)
+{
+ u32 bus_num, slot_num, func_num;
+ u32 base;
+
+ db_assert((where & 3) == 0);
+ db_assert(where < (1 << 8));
+
+ /* check if the bus is top-level */
+ if (bus->parent != NULL) {
+ bus_num = bus->number;
+ db_assert(bus_num != 0);
+ } else {
+ bus_num = 0;
+ }
+
+ slot_num = PCI_SLOT(devfn);
+ func_num = PCI_FUNC(devfn);
+ base = ddb_access_config_base(swap, bus_num, slot_num);
+ *(volatile u32 *)(base + (func_num << 8) + where) = val;
+ ddb_close_config_base(swap);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int write_config_word(struct pci_config_swap *swap,
+ struct pci_bus *bus, u32 devfn, u32 where, u16 val)
+{
+ int status, shift = 0;
+ u32 result;
+
+ db_assert((where & 1) == 0);
+
+ status = read_config_dword(swap, bus, devfn, where & ~3, &result);
+ if (status != PCIBIOS_SUCCESSFUL)
+ return status;
+
+ if (where & 2)
+ shift += 16;
+ result &= ~(0xffff << shift);
+ result |= val << shift;
+ return write_config_dword(swap, bus, devfn, where & ~3, result);
+}
+
+static int write_config_byte(struct pci_config_swap *swap,
+ struct pci_bus *bus, u32 devfn, u32 where, u8 val)
+{
+ int status, shift = 0;
+ u32 result;
+
+ status = read_config_dword(swap, bus, devfn, where & ~3, &result);
+ if (status != PCIBIOS_SUCCESSFUL)
+ return status;
+
+ if (where & 2)
+ shift += 16;
+ if (where & 1)
+ shift += 8;
+ result &= ~(0xff << shift);
+ result |= val << shift;
+ return write_config_dword(swap, bus, devfn, where & ~3, result);
+}
+
+#define MAKE_PCI_OPS(prefix, rw, pciswap, star) \
+static int prefix##_##rw##_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 star val) \
+{ \
+ if (size == 1) \
+ return rw##_config_byte(pciswap, bus, devfn, where, (u8 star)val); \
+ else if (size == 2) \
+ return rw##_config_word(pciswap, bus, devfn, where, (u16 star)val); \
+ /* Size must be 4 */ \
+ return rw##_config_dword(pciswap, bus, devfn, where, val); \
+}
+
+MAKE_PCI_OPS(extpci, read, &ext_pci_swap, *)
+ MAKE_PCI_OPS(extpci, write, &ext_pci_swap,)
+
+ MAKE_PCI_OPS(iopci, read, &io_pci_swap, *)
+ MAKE_PCI_OPS(iopci, write, &io_pci_swap,)
+
+struct pci_ops VR5701_ext_pci_ops = {
+ .read = extpci_read_config,
+ .write = extpci_write_config
+};
+
+struct pci_ops VR5701_io_pci_ops = {
+ .read = iopci_read_config,
+ .write = iopci_write_config
+};
Index: linux-2.6.10/arch/mips/vr5701/common/Makefile
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/common/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the common code of NEC Electronics Corporation VR5701 SolutionGearII board
+#
+
+obj-y += nec_vrxxxx.o prom.o rtc_rx5c348.o
Index: linux-2.6.10/include/asm-mips/bootinfo.h
===================================================================
--- linux-2.6.10.orig/include/asm-mips/bootinfo.h
+++ linux-2.6.10/include/asm-mips/bootinfo.h
@@ -213,6 +213,12 @@
#define MACH_GROUP_TITAN 22 /* PMC-Sierra Titan */
#define MACH_TITAN_YOSEMITE 1 /* PMC-Sierra Yosemite */
+/*
+ * Valid machtype for group SHIMA
+ */
+#define MACH_GROUP_SHIMA 24 /* SHIMAFUJI */
+#define MACH_SHIMA_TCUBE 0 /* SHIMAFUJI T-Cube(Vr5701) */
+
#define CL_SIZE COMMAND_LINE_SIZE
const char *get_system_type(void);
Index: linux-2.6.10/drivers/video/smi/smifb.h
===================================================================
--- /dev/null
+++ linux-2.6.10/drivers/video/smi/smifb.h
@@ -0,0 +1,89 @@
+/*
+ * drivers/video/smi/smifb.h
+ *
+ * LynxEM+/EM4+(Silicon Motion Inc.) fb driver for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __SMIFB_H__
+#define __SMIFB_H__
+
+#define FBCON_HAS_CFB16
+
+enum ScreenModes {
+ DISPLAY_640x480x16,
+ DISPLAY_800x600x16,
+ DISPLAY_1024x768x16,
+ DISPLAY_640x480x24,
+ DISPLAY_800x600x24,
+ DISPLAY_LCD_400x232x16,
+ modeNums,
+};
+
+#define SMI_DEFAULT_MODE DISPLAY_640x480x16
+
+#define SIZE_SR00_SR04 (0x04 - 0x00 + 1)
+#define SIZE_SR10_SR24 (0x24 - 0x10 + 1)
+#define SIZE_SR30_SR75 (0x75 - 0x30 + 1)
+#define SIZE_SR80_SR93 (0x93 - 0x80 + 1)
+#define SIZE_SRA0_SRAF (0xAF - 0xA0 + 1)
+#define SIZE_GR00_GR08 (0x08 - 0x00 + 1)
+#define SIZE_AR00_AR14 (0x14 - 0x00 + 1)
+#define SIZE_CR00_CR18 (0x18 - 0x00 + 1)
+#define SIZE_CR30_CR4D (0x4D - 0x30 + 1)
+#define SIZE_CR90_CRA7 (0xA7 - 0x90 + 1)
+
+struct smi_mode_regs {
+ int mode;
+ u8 reg_MISC;
+ u8 reg_SR00_SR04[SIZE_SR00_SR04]; /* SEQ00--04 (SEQ) */
+ u8 reg_SR10_SR24[SIZE_SR10_SR24]; /* SCR10--1F, PDR20--24 (SYS),(PWR) */
+ u8 reg_SR30_SR75[SIZE_SR30_SR75]; /* FPR30--5A, MCR60--62, CCR65--6F GPR70--75 (LCD),(MEM),(CLK),(GP) */
+ u8 reg_SR80_SR93[SIZE_SR80_SR93]; /* PHR80-81, POP82--86, HCR88-8D, POP90--93 (CURS),(ICON),(CURS),(ICON) */
+ u8 reg_SRA0_SRAF[SIZE_SRA0_SRAF]; /* FPRA0--AF (LCD) */
+ u8 reg_GR00_GR08[SIZE_GR00_GR08]; /* GR00--08 (GC) */
+ u8 reg_AR00_AR14[SIZE_AR00_AR14]; /* ATR00--14 (ATTR) */
+ u8 reg_CR00_CR18[SIZE_CR00_CR18]; /* CRT00--18 (CRTC) */
+ u8 reg_CR30_CR4D[SIZE_CR30_CR4D]; /* CRT30--3F, SVR40--4D (ECRTC),(SHADOW) */
+ u8 reg_CR90_CRA7[SIZE_CR90_CRA7]; /* CRT90--9B,9E,9F,A0--A5,A6,A7, (DDA),(EC2),(EC1)(VCLUT),(VC),(HC) */
+};
+
+typedef struct {
+ unsigned char red, green, blue, transp;
+} smi_cfb8_cmap_t;
+
+struct smifb_info;
+struct smifb_info {
+ struct fb_info info; /* kernel framebuffer info */
+ const char *drvr_name; /* Silicon Motion hardware board type */
+ struct pci_dev *pd; /* descripbe the PCI device */
+ unsigned long base_phys; /* physical base address */
+
+ /* PCI base physical addresses */
+ unsigned long fb_base_phys; /* physical Frame Buffer base address */
+ unsigned long dpr_base_phys; /* physical Drawing Processor base address */
+ unsigned long vpr_base_phys; /* physical Video Processor base address */
+ unsigned long cpr_base_phys; /* physical Capture Processor base address */
+ unsigned long mmio_base_phys; /* physical MMIO spase (VGA + SMI regs ?) base address */
+ unsigned long dpport_base_phys; /* physical Drawing Processor Data Port base address */
+ int dpport_size; /* size of Drawin Processor Data Port memory space */
+
+ /* PCI base virtual addresses */
+ caddr_t base; /* address of base */
+ caddr_t fb_base; /* address of frame buffer base */
+ caddr_t dpr; /* Drawing Processor Registers */
+ caddr_t vpr; /* Video Processor Registers */
+ caddr_t cpr; /* Capture Processor Registers */
+ caddr_t mmio; /* Memory Mapped I/O Port */
+ caddr_t dpport; /* Drawing Processor Data */
+
+ int fbsize; /* Frame-Buffer memory size */
+};
+
+#endif /* __SMIFB_H__ */
Index: linux-2.6.10/arch/mips/mm/tlbex.c
===================================================================
--- linux-2.6.10.orig/arch/mips/mm/tlbex.c
+++ linux-2.6.10/arch/mips/mm/tlbex.c
@@ -784,6 +784,7 @@ static __init void __attribute__((unused
case CPU_R5000:
case CPU_R5000A:
case CPU_NEVADA:
+ case CPU_R5500:
i_nop(p);
i_tlbp(p);
break;
@@ -831,6 +832,7 @@ static __init void build_tlb_write_entry
case CPU_R4600:
case CPU_R4700:
case CPU_R5000:
+ case CPU_R5500:
case CPU_R5000A:
case CPU_5KC:
case CPU_TX49XX:
Index: linux-2.6.10/arch/mips/vr5701/common/prom.c
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/common/prom.c
@@ -0,0 +1,53 @@
+/*
+ * arch/mips/vr5701/common/prom.c
+ *
+ * A code for prom routines on NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/debug.h>
+#include <asm/tcube.h>
+
+const char *get_system_type(void)
+{
+ return "NEC Electronics Corporation VR5701 SolutionGearII";
+}
+
+void __init prom_init(void)
+{
+ int i;
+ int argc = fw_arg0;
+ char **arg = (char **)fw_arg1;
+
+ /* if user passes kernel args, ignore the default one */
+ if (argc > 1)
+ arcs_cmdline[0] = '\0';
+
+ /* arg[0] is "g", the rest is boot parameters */
+ for (i = 1; i < argc; i++) {
+ if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
+ >= sizeof(arcs_cmdline))
+ break;
+ strcat(arcs_cmdline, arg[i]);
+ strcat(arcs_cmdline, " ");
+ }
+ mips_machgroup = MACH_GROUP_SHIMA;
+ mips_machtype = MACH_SHIMA_TCUBE;
+ add_memory_region(0, TCUBE_SDRAM_SIZE, BOOT_MEM_RAM);
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
Index: linux-2.6.10/arch/mips/lib-64/Makefile
===================================================================
--- linux-2.6.10.orig/arch/mips/lib-64/Makefile
+++ linux-2.6.10/arch/mips/lib-64/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_CPU_R4300) += dump_tlb.o
obj-$(CONFIG_CPU_R4X00) += dump_tlb.o
obj-$(CONFIG_CPU_R5000) += dump_tlb.o
obj-$(CONFIG_CPU_R5432) += dump_tlb.o
+obj-$(CONFIG_CPU_R5500) += dump_tlb.o
obj-$(CONFIG_CPU_R6000) +=
obj-$(CONFIG_CPU_R8000) +=
obj-$(CONFIG_CPU_RM7000) += dump_tlb.o
Index: linux-2.6.10/arch/mips/lib-32/Makefile
===================================================================
--- linux-2.6.10.orig/arch/mips/lib-32/Makefile
+++ linux-2.6.10/arch/mips/lib-32/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_CPU_R4300) += dump_tlb.o
obj-$(CONFIG_CPU_R4X00) += dump_tlb.o
obj-$(CONFIG_CPU_R5000) += dump_tlb.o
obj-$(CONFIG_CPU_R5432) += dump_tlb.o
+obj-$(CONFIG_CPU_R5500) += dump_tlb.o
obj-$(CONFIG_CPU_R6000) +=
obj-$(CONFIG_CPU_R8000) +=
obj-$(CONFIG_CPU_RM7000) += dump_tlb.o
Index: linux-2.6.10/sound/oss/Kconfig
===================================================================
--- linux-2.6.10.orig/sound/oss/Kconfig
+++ linux-2.6.10/sound/oss/Kconfig
@@ -233,6 +233,13 @@ config SOUND_VRC5477
integrated, multi-function controller chip for MIPS CPUs. Works
with the AC97 codec.
+config SOUND_VR5701
+ tristate "NEC Electronics Corporation VR5701 SolutionGearII AC97 sound"
+ depends on SOUND_PRIME!=n && TCUBE && SOUND
+ help
+ Say Y here to enable sound support for the NEC Electronics Corporation
+ VR5701 SolutionGearII AC97 sound. Works with the AC97 codec.
+
config SOUND_AU1000
tristate "Au1000 Sound"
depends on SOUND_PRIME!=n && (SOC_AU1000 || SOC_AU1100 || SOC_AU1500) && SOUND
Index: linux-2.6.10/drivers/video/Kconfig
===================================================================
--- linux-2.6.10.orig/drivers/video/Kconfig
+++ linux-2.6.10/drivers/video/Kconfig
@@ -795,6 +795,25 @@ config FB_ATY_GX
is at
<http://support.ati.com/products/pc/mach64/graphics_xpression.html>.
+config FB_SM
+ tristate "Silicon Motion SM722 support"
+ depends on FB && PCI
+ help
+ SM722
+
+choice
+ prompt "Display size"
+ depends on FB_SM
+ default DISPLAY_640x480
+
+config DISPLAY_640x480
+ bool "640x480"
+
+config DISPLAY_1024x768
+ bool "1024x768"
+
+endchoice
+
config FB_SAVAGE
tristate "S3 Savage support"
depends on FB && PCI && EXPERIMENTAL
Index: linux-2.6.10/arch/mips/kernel/cpu-probe.c
===================================================================
--- linux-2.6.10.orig/arch/mips/kernel/cpu-probe.c
+++ linux-2.6.10/arch/mips/kernel/cpu-probe.c
@@ -98,6 +98,7 @@ static inline void check_wait(void)
case CPU_R4650:
case CPU_R4700:
case CPU_R5000:
+ case CPU_R5500:
case CPU_NEVADA:
case CPU_RM7000:
case CPU_RM9000:
Index: linux-2.6.10/drivers/video/smi/smi_params.h
===================================================================
--- /dev/null
+++ linux-2.6.10/drivers/video/smi/smi_params.h
@@ -0,0 +1,442 @@
+/*
+ * drivers/video/smi/smi_params.h
+ *
+ * LynxEM+/EM4+(Silicon Motion Inc.) fb driver for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __SMI_REGS_H__
+#define __SMI_REGS_H__
+
+/* register settings */
+struct smi_mode_regs ModeInitParams[modeNums] = {
+ /* mode#4 640 x 480 16Bpp 60Hz */
+ {
+ DISPLAY_640x480x16,
+ /* reg_MISC */
+ 0xE3,
+ /* reg_SR00_SR04 */
+ {
+ 0x03, 0x01, 0x0F, 0x00, 0x0E,
+ },
+ /* reg_SR10_SR24 */
+ {
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x10, 0x2C,
+ 0x59, 0x00, 0x20, 0x00, 0x00, 0x0F, 0x0F, 0x00,
+ 0xC4, 0x30, 0x02, 0x01, 0x01,
+ },
+
+ /* reg_SR30_SR75 */
+ {
+ 0xAA, 0x03, 0xA0, 0x89, 0xC0, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x03, 0xFF,
+ 0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
+ 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0xAA,
+ 0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
+ 0x04, 0x50, 0x19, 0xAA, 0xAA, 0x00, 0x00, 0xAA,
+ 0x01, 0x80, 0xFF, 0x1A, 0x1A, 0x00, 0x03, 0x00,
+ 0x50, 0x03, 0x0D, 0x02, 0x07, 0x82, 0x07, 0x04,
+ 0x00, 0x45, 0x30, 0x0C, 0x40, 0x30,
+ },
+ /* reg_SR80_SR93 */
+ {
+ 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0xAA,
+ 0x40, 0x01, 0xF0, 0x00, 0xFF, 0x00, 0xAA, 0xAA,
+ 0x00, 0x00, 0x00, 0x00,
+ },
+ /* reg_SRA0_SRAF */
+ {
+ 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+ 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
+ },
+ /* reg_GR00_GR08 */
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+ 0xFF,
+ },
+ /* reg_AR00_AR14 */
+ {
+ 0x3F, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x00, 0x12, 0x00, 0x04,
+ },
+ /* reg_CR00_CR18 */
+ {
+ 0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
+ 0xFF,
+ },
+ /* reg_CR30_CR4D */
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
+ 0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
+ 0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
+ },
+ /* reg_CR90_CRA7 */
+ {
+ 0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
+ 0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
+ 0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
+ },
+ },
+ /* mode#5 800 x 600 16Bpp 60Hz */
+ {
+ DISPLAY_800x600x16,
+ /* reg_MISC */
+ 0x2B,
+ /* reg_SR00_SR04 */
+ {
+ 0x03, 0x01, 0x0F, 0x03, 0x0E,
+ },
+ /* reg_SR10_SR24 */
+ {
+ 0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0xe2,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xC4, 0x30, 0x02, 0x01, 0x01,
+ },
+ /* reg_SR30_SR75 */
+ {
+ 0x36, 0x03, 0x20, 0x09, 0xC0, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x03, 0xFF,
+ 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+ 0x20, 0x0C, 0x44, 0x20, 0x00, 0x36, 0x36, 0x36,
+ 0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
+ 0x04, 0x55, 0x59, 0x36, 0x36, 0x00, 0x00, 0x36,
+ 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+ 0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
+ 0x02, 0x45, 0x30, 0x30, 0x40, 0x20,
+ },
+ /* reg_SR80_SR93 */
+ {
+ 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x36,
+ 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x36, 0x36,
+ 0x00, 0x00, 0x00, 0x00,
+ },
+ /* reg_SRA0_SRAF */
+ {
+ 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+ 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
+ },
+ /* reg_GR00_GR08 */
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+ 0xFF,
+ },
+ /* reg_AR00_AR14 */
+ {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x41, 0x00, 0x0F, 0x00, 0x00,
+ },
+ /* reg_CR00_CR18 */
+ {
+ 0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
+ 0xFF,
+ },
+ /* reg_CR30_CR4D */
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
+ 0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
+ 0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
+ },
+ /* reg_CR90_CRA7 */
+ {
+ 0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
+ 0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
+ 0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
+ },
+ },
+ /* mode#6 1024 x 768 16Bpp 60Hz * */
+ {
+ DISPLAY_1024x768x16,
+ /* reg_MISC */
+ 0xEB,
+ /* reg_SR00_SR04 */
+ {
+ 0x03, 0x01, 0x0F, 0x03, 0x0E,
+ },
+ /* reg_SR10_SR24 */
+ {
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x10, 0x2c,
+ 0x59, 0x02, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00,
+ 0xC4, 0x30, 0x02, 0x01, 0x01,
+ },
+ /* reg_SR30_SR75 */
+ {
+ 0xAA, 0x03, 0x20, 0x89, 0xC0, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x03, 0xFF,
+ 0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
+ 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0xAA,
+ 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
+ 0x00, 0x60, 0x59, 0xAA, 0xAA, 0x00, 0x00, 0xAA,
+ 0x01, 0x80, 0xFF, 0x1A, 0x1A, 0x00, 0x03, 0x00,
+ 0x50, 0x03, 0x0D, 0x02, 0x12, 0x82, 0x09, 0x02,
+ 0x04, 0x45, 0x30, 0x0C, 0x40, 0x20,
+ },
+ /* reg_SR80_SR93 */
+ {
+ 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA,
+ 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xAA, 0xAA,
+ 0x00, 0x00, 0x00, 0x00,
+ },
+ /* reg_SRA0_SRAF */
+ {
+ 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
+ 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
+ },
+ /* reg_GR00_GR08 */
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+ 0xFF,
+ },
+ /* reg_AR00_AR14 */
+ {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x41, 0x11, 0x0F, 0x13, 0x00,
+ },
+ /* reg_CR00_CR18 */
+ {
+ 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
+ 0xFF,
+ },
+ /* reg_CR30_CR4D */
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
+ 0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
+ 0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
+ },
+ /* reg_CR90_CRA7 */
+ {
+ 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
+ 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
+ },
+ },
+ /* mode#7 640 x 480 24Bpp 60Hz */
+ {
+ DISPLAY_640x480x24,
+ /* reg_MISC */
+ 0xE3,
+ /* reg_SR00_SR04 */
+ {
+ 0x03, 0x01, 0x0F, 0x00, 0x0E,
+ },
+ /* reg_SR10_SR24 */
+ {
+ 0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0xe2,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xC4, 0x30, 0x02, 0x01, 0x01,
+ },
+ /* reg_SR30_SR75 */
+ {
+ 0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
+ 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
+ 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+ 0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
+ 0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
+ 0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
+ 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+ 0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
+ 0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
+ },
+ /* reg_SR80_SR93 */
+ {
+ 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
+ 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
+ 0x00, 0x00, 0x00, 0x00,
+ },
+ /* reg_SRA0_SRAF */
+ {
+ 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+ 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
+ },
+ /* reg_GR00_GR08 */
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+ 0xFF,
+ },
+ /* reg_AR00_AR14 */
+ {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x41, 0x00, 0x0F, 0x00, 0x00,
+ },
+ /* reg_CR00_CR18 */
+ {
+ 0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
+ 0xFF,
+ },
+ /* reg_CR30_CR4D */
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
+ 0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
+ 0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
+ },
+ /* reg_CR90_CRA7 */
+ {
+ 0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
+ 0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
+ 0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
+ },
+ },
+ /* mode#8 800 x 600 24Bpp 60Hz */
+ {
+ DISPLAY_800x600x24,
+ /* reg_MISC */
+ 0x2B,
+ /* reg_SR00_SR04 */
+ {
+ 0x03, 0x01, 0x0F, 0x03, 0x0E,
+ },
+ /* reg_SR10_SR24 */
+ {
+ 0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0xe2,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xC4, 0x30, 0x02, 0x01, 0x01,
+ },
+ /* reg_SR30_SR75 */
+ {
+ 0x36, 0x03, 0x20, 0x09, 0xC0, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x03, 0xFF,
+ 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+ 0x20, 0x0C, 0x44, 0x20, 0x00, 0x36, 0x36, 0x36,
+ 0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
+ 0x04, 0x55, 0x59, 0x36, 0x36, 0x00, 0x00, 0x36,
+ 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+ 0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
+ 0x02, 0x45, 0x30, 0x30, 0x40, 0x20,
+ },
+ /* reg_SR80_SR93 */
+ {
+ 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x36,
+ 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x36, 0x36,
+ 0x00, 0x00, 0x00, 0x00,
+ },
+ /* reg_SRA0_SRAF */
+ {
+ 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+ 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
+ },
+ /* reg_GR00_GR08 */
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+ 0xFF,
+ },
+ /* reg_AR00_AR14 */
+ {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x41, 0x00, 0x0F, 0x00, 0x00,
+ },
+ /* reg_CR00_CR18 */
+ {
+ 0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
+ 0xFF,
+ },
+ /* reg_CR30_CR4D */
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
+ 0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
+ 0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
+ },
+ /* reg_CR90_CRA7 */
+ {
+ 0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
+ 0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
+ 0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
+ },
+ },
+ /* mode#9 400 x 232 16Bpp 60Hz */
+ {
+ DISPLAY_LCD_400x232x16,
+ /* reg_MISC */
+ 0x2B,
+ /* reg_SR00_SR04 */
+ {
+ 0x03, 0x01, 0x0F, 0x03, 0x0E,
+ },
+ /* reg_SR10_SR24 */
+ {
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x2C,
+ 0x59, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00,
+ 0x84, 0x00, 0x02, 0x00, 0x31,
+ },
+ /* reg_SR30_SR75 */
+ {
+ 0xB7, 0x43, 0x98, 0x01, 0xC0, 0xB7, 0xB7, 0xB7,
+ 0xB7, 0xB7, 0xB7, 0xB7, 0x00, 0x00, 0x85, 0x2C,
+ 0xC0, 0xE1, 0x00, 0x00, 0x40, 0xF0, 0x80, 0xC4,
+ 0x40, 0x3C, 0xA1, 0x40, 0x00, 0x00, 0x01, 0xB7,
+ 0x02, 0x24, 0xD9, 0xC7, 0xCC, 0x31, 0x2C, 0x2D,
+ 0x07, 0x57, 0x19, 0xB7, 0xB7, 0x00, 0x00, 0xB7,
+ 0x01, 0x00, 0xFF, 0x1A, 0x1A, 0x01, 0x03, 0x00,
+ 0xD4, 0x07, 0x0D, 0x02, 0x23, 0x3F, 0x35, 0x13,
+ 0x83, 0xDD, 0x02, 0x0C, 0x05, 0x00,
+ },
+ /* reg_SR80_SR93 */
+ {
+ 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x09, 0xB7,
+ 0x48, 0x00, 0x36, 0x00, 0xFF, 0x00, 0xB7, 0xB7,
+ 0x00, 0x00, 0x00, 0x00,
+ },
+ /* reg_SRA0_SRAF */
+ {
+ 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+ 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
+ },
+ /* reg_GR00_GR08 */
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+ 0xFF,
+ },
+ /* reg_AR00_AR14 */
+ {
+ 0x00, 0x02, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x00, 0x12, 0x00, 0x04,
+ },
+ /* reg_CR00_CR18 */
+ {
+ 0x3B, 0x31, 0x31, 0x00, 0x3A, 0x00, 0x06, 0x11,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xF1, 0x85, 0xE9, 0x32, 0x40, 0xE9, 0x00, 0xEB,
+ 0xFF,
+ },
+ /* reg_CR30_CR4D */
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x02, 0x10,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0x20, 0x00, 0x00,
+ 0x3B, 0x31, 0x00, 0x3A, 0x00, 0x06, 0xEA, 0x00,
+ 0xF2, 0x05, 0x01, 0x00, 0x31, 0xE9,
+ },
+ /* reg_CR90_CRA7 */
+ {
+ 0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
+ 0xDB, 0x2A, 0xDF, 0x33, 0xFF, 0xFF, 0x1B, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ },
+};
+
+#endif /* __SMI_REGS_H__ */
Index: linux-2.6.10/arch/mips/vr5701/common/nec_vrxxxx.c
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/common/nec_vrxxxx.c
@@ -0,0 +1,119 @@
+/*
+ * arch/mips/vr5701/common/nec_vrxxxx.c
+ *
+ * A code for low-level routines on NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <asm/tcube.h>
+
+u32
+ddb_calc_pdar(u32 phys, u32 size, int width, int on_memory_bus, int pci_visible)
+{
+ u32 maskbits;
+ u32 widthbits;
+
+ switch (size) {
+ case 0x80000000: /* 2 GB */
+ maskbits = 5;
+ break;
+ case 0x40000000: /* 1 GB */
+ maskbits = 6;
+ break;
+ case 0x20000000: /* 512 MB */
+ maskbits = 7;
+ break;
+ case 0x10000000: /* 256 MB */
+ maskbits = 8;
+ break;
+ case 0x08000000: /* 128 MB */
+ maskbits = 9;
+ break;
+ case 0x04000000: /* 64 MB */
+ maskbits = 10;
+ break;
+ case 0x02000000: /* 32 MB */
+ maskbits = 11;
+ break;
+ case 0x01000000: /* 16 MB */
+ maskbits = 12;
+ break;
+ case 0x00800000: /* 8 MB */
+ maskbits = 13;
+ break;
+ case 0x00400000: /* 4 MB */
+ maskbits = 14;
+ break;
+ case 0x00200000: /* 2 MB */
+ maskbits = 15;
+ break;
+ case 0: /* OFF */
+ maskbits = 0;
+ break;
+ default:
+ panic("VR5701_set_pdar: unsupported size %p", (void *)size);
+ }
+ switch (width) {
+ case 8:
+ widthbits = 0;
+ break;
+ case 16:
+ widthbits = 1;
+ break;
+ case 32:
+ widthbits = 2;
+ break;
+ case 64:
+ widthbits = 3;
+ break;
+ default:
+ panic("VR5701_set_pdar: unsupported width %d", width);
+ }
+
+ return maskbits | (on_memory_bus ? 0x10 : 0) |
+ (pci_visible ? 0x20 : 0) | (widthbits << 6) | (phys & 0xffe00000);
+}
+
+void
+ddb_set_pdar(u32 pdar, u32 phys, u32 size, int width,
+ int on_memory_bus, int pci_visible)
+{
+ u32 temp = ddb_calc_pdar(phys, size, width, on_memory_bus, pci_visible);
+ ddb_out32(pdar, temp);
+ ddb_out32(pdar + 4, 0);
+ ddb_in32(pdar);
+ ddb_in32(pdar + 4);
+}
+
+/*
+ * routines that mess with PCIINITx registers
+ */
+
+void ddb_set_pmr(u32 pmr, u32 type, u32 addr, u32 options)
+{
+ switch (type) {
+ case DDB_PCICMD_IACK: /* PCI Interrupt Acknowledge */
+ case DDB_PCICMD_IO: /* PCI I/O Space */
+ case DDB_PCICMD_MEM: /* PCI Memory Space */
+ case DDB_PCICMD_CFG: /* PCI Configuration Space */
+ break;
+ default:
+ panic("VR5701_set_pmr: invalid type %d", type);
+ }
+ ddb_out32(pmr, (type << 1) | (addr & 0xffe00000) | options);
+ ddb_out32(pmr + 4, 0);
+}
+
+void ddb_set_bar(u32 bar, u32 phys, int prefetchable)
+{
+ ddb_out32(bar, (phys & 0xffe00000) | (!!prefetchable << 3));
+ ddb_out32(bar + 4, 0);
+}
Index: linux-2.6.10/sound/oss/nec_vr5701_sg2.c
===================================================================
--- /dev/null
+++ linux-2.6.10/sound/oss/nec_vr5701_sg2.c
@@ -0,0 +1,1368 @@
+/*
+ * sound/oss/nec_vr5701_sg2.c
+ *
+ * A sound driver for NEC Electronics Corporation VR5701 SolutionGearII.
+ * It works with AC97 codec.
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include "nec_vr5701_sg2.h"
+
+static LIST_HEAD(devs);
+
+static u16 rdcodec(struct ac97_codec *codec, u8 addr)
+{
+ struct vr5701_ac97_state *s =
+ (struct vr5701_ac97_state *)codec->private_data;
+ unsigned long flags;
+ u32 result;
+
+ spin_lock_irqsave(&s->lock, flags);
+
+ /* wait until we can access codec registers */
+ while (inl(s->io + vr5701_CODEC_WR) & 0x80000000) ;
+
+ /* write the address and "read" command to codec */
+ addr = addr & 0x7f;
+ outl((addr << 16) | vr5701_CODEC_WR_RWC, s->io + vr5701_CODEC_WR);
+
+ /* get the return result */
+ udelay(100); /* workaround hardware bug */
+ while ((result = inl(s->io + vr5701_CODEC_RD)) &
+ (vr5701_CODEC_RD_RRDYA | vr5701_CODEC_RD_RRDYD)) {
+ /* we get either addr or data, or both */
+ if (result & vr5701_CODEC_RD_RRDYA) {
+ ASSERT(addr == ((result >> 16) & 0x7f));
+ }
+ if (result & vr5701_CODEC_RD_RRDYD) {
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&s->lock, flags);
+
+ return result & 0xffff;
+}
+
+static void wrcodec(struct ac97_codec *codec, u8 addr, u16 data)
+{
+ struct vr5701_ac97_state *s =
+ (struct vr5701_ac97_state *)codec->private_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&s->lock, flags);
+
+ /* wait until we can access codec registers */
+ while (inl(s->io + vr5701_CODEC_WR) & 0x80000000) ;
+
+ /* write the address and value to codec */
+ outl((addr << 16) | data, s->io + vr5701_CODEC_WR);
+
+ spin_unlock_irqrestore(&s->lock, flags);
+}
+
+static void waitcodec(struct ac97_codec *codec)
+{
+ struct vr5701_ac97_state *s =
+ (struct vr5701_ac97_state *)codec->private_data;
+
+ /* wait until we can access codec registers */
+ while (inl(s->io + vr5701_CODEC_WR) & 0x80000000) ;
+}
+
+static void vr5701_ac97_delay(int msec)
+{
+ unsigned long tmo;
+ signed long tmo2;
+
+ if (in_interrupt())
+ return;
+
+ tmo = jiffies + (msec * HZ) / 1000;
+ for (;;) {
+ tmo2 = tmo - jiffies;
+ if (tmo2 <= 0)
+ break;
+ schedule_timeout(tmo2);
+ }
+}
+
+static void set_adc_rate(struct vr5701_ac97_state *s, unsigned rate)
+{
+ wrcodec(s->codec, AC97_PCM_LR_ADC_RATE, rate);
+ s->adcRate = rate;
+}
+
+static void set_dac_rate(struct vr5701_ac97_state *s, unsigned rate)
+{
+ if (s->extended_status & AC97_EXTSTAT_VRA) {
+ wrcodec(s->codec, AC97_PCM_FRONT_DAC_RATE, rate);
+ s->dacRate = rdcodec(s->codec, AC97_PCM_FRONT_DAC_RATE);
+ }
+}
+
+static int start_dac(struct vr5701_ac97_state *s)
+{
+ struct dmabuf *db = &s->dma_dac;
+ unsigned long flags;
+ u32 dmaLength;
+ u32 temp;
+
+ spin_lock_irqsave(&s->lock, flags);
+
+ if (!db->stopped) {
+ spin_unlock_irqrestore(&s->lock, flags);
+ return -1;
+ }
+
+ /* we should have some data to do the DMA trasnfer */
+ if(db->count < db->fragSize){
+ spin_unlock_irqrestore(&s->lock, flags);
+ return -1;
+ }
+
+ /* clear pending fales interrupts */
+ outl(vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END,
+ s->io + vr5701_INT_CLR);
+
+ /* enable interrupts */
+ temp = inl(s->io + vr5701_INT_MASK);
+ temp |= vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END;
+ outl(temp, s->io + vr5701_INT_MASK);
+
+ /* setup dma base addr */
+ outl(db->lbufDma + db->nextOut, s->io + vr5701_DAC1_BADDR);
+ if (s->dacChannels == 1) {
+ outl(db->lbufDma + db->nextOut, s->io + vr5701_DAC2_BADDR);
+ } else {
+ outl(db->rbufDma + db->nextOut, s->io + vr5701_DAC2_BADDR);
+ }
+
+ /* set dma length, in the unit of 0x10 bytes */
+ dmaLength = db->fragSize >> 4;
+ outl(dmaLength, s->io + vr5701_DAC1L);
+ outl(dmaLength, s->io + vr5701_DAC2L);
+
+ /* activate dma */
+ outl(vr5701_DMA_ACTIVATION, s->io + vr5701_DAC1_CTRL);
+ outl(vr5701_DMA_ACTIVATION, s->io + vr5701_DAC2_CTRL);
+
+ /* enable dac slots - we should hear the music now! */
+ temp = inl(s->io + vr5701_CTRL);
+ temp |= (vr5701_CTRL_DAC1ENB | vr5701_CTRL_DAC2ENB);
+ outl(temp, s->io + vr5701_CTRL);
+
+ /* it is time to setup next dma transfer */
+ ASSERT(inl(s->io + vr5701_DAC1_CTRL) & vr5701_DMA_WIP);
+ ASSERT(inl(s->io + vr5701_DAC2_CTRL) & vr5701_DMA_WIP);
+
+ temp = db->nextOut + db->fragSize;
+ if (temp >= db->fragTotalSize) {
+ ASSERT(temp == db->fragTotalSize);
+ temp = 0;
+ }
+
+ outl(db->lbufDma + temp, s->io + vr5701_DAC1_BADDR);
+ if (s->dacChannels == 1) {
+ outl(db->lbufDma + temp, s->io + vr5701_DAC2_BADDR);
+ } else {
+ outl(db->rbufDma + temp, s->io + vr5701_DAC2_BADDR);
+ }
+
+ db->stopped = 0;
+
+#if defined(vr5701_AC97_VERBOSE_DEBUG)
+ outTicket = *(u16 *) (db->lbuf + db->nextOut);
+ if (db->count > db->fragSize) {
+ ASSERT((u16) (outTicket + 1) == *(u16 *) (db->lbuf + temp));
+ }
+#endif
+ spin_unlock_irqrestore(&s->lock, flags);
+ return 0;
+}
+
+static void start_adc(struct vr5701_ac97_state *s)
+{
+ struct dmabuf *db = &s->dma_adc;
+ unsigned long flags;
+ u32 dmaLength;
+ u32 temp;
+
+ spin_lock_irqsave(&s->lock, flags);
+
+ if (!db->stopped) {
+ spin_unlock_irqrestore(&s->lock, flags);
+ return;
+ }
+
+ /* we should at least have some free space in the buffer */
+ ASSERT(db->count < db->fragTotalSize - db->fragSize * 2);
+
+ /* clear pending ones */
+ outl(vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END,
+ s->io + vr5701_INT_CLR);
+
+ /* enable interrupts */
+ temp = inl(s->io + vr5701_INT_MASK);
+ temp |= vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END;
+ outl(temp, s->io + vr5701_INT_MASK);
+
+ /* setup dma base addr */
+ outl(db->lbufDma + db->nextIn, s->io + vr5701_ADC1_BADDR);
+ outl(db->rbufDma + db->nextIn, s->io + vr5701_ADC2_BADDR);
+
+ /* setup dma length */
+ dmaLength = db->fragSize >> 4;
+ outl(dmaLength, s->io + vr5701_ADC1L);
+ outl(dmaLength, s->io + vr5701_ADC2L);
+
+ /* activate dma */
+ outl(vr5701_DMA_ACTIVATION, s->io + vr5701_ADC1_CTRL);
+ outl(vr5701_DMA_ACTIVATION, s->io + vr5701_ADC2_CTRL);
+
+ /* enable adc slots */
+ temp = inl(s->io + vr5701_CTRL);
+ temp |= (vr5701_CTRL_ADC1ENB | vr5701_CTRL_ADC2ENB);
+ outl(temp, s->io + vr5701_CTRL);
+
+ /* it is time to setup next dma transfer */
+ temp = db->nextIn + db->fragSize;
+ if (temp >= db->fragTotalSize) {
+ ASSERT(temp == db->fragTotalSize);
+ temp = 0;
+ }
+ outl(db->lbufDma + temp, s->io + vr5701_ADC1_BADDR);
+ outl(db->rbufDma + temp, s->io + vr5701_ADC2_BADDR);
+
+ db->stopped = 0;
+
+ spin_unlock_irqrestore(&s->lock, flags);
+}
+
+/* return the total bytes that is copied */
+static inline int
+copy_dac_from_user(struct vr5701_ac97_state *s,
+ const char *buffer, size_t count, int avail)
+{
+ struct dmabuf *db = &s->dma_dac;
+ int copyCount = 0;
+ int copyFragCount = 0;
+ int totalCopyCount = 0;
+ int totalCopyFragCount = 0;
+ unsigned long flags;
+#if defined(vr5701_AC97_VERBOSE_DEBUG)
+ int i;
+#endif
+
+ /* adjust count to signel channel byte count */
+ count >>= s->dacChannels - 1;
+
+ /* we may have to "copy" twice as ring buffer wraps around */
+ for (; (avail > 0) && (count > 0);) {
+ /* determine max possible copy count for single channel */
+ copyCount = count;
+ if (copyCount > avail) {
+ copyCount = avail;
+ }
+ if (copyCount + db->nextIn > db->fragTotalSize) {
+ copyCount = db->fragTotalSize - db->nextIn;
+ ASSERT(copyCount > 0);
+ }
+
+ copyFragCount = copyCount;
+ ASSERT(copyFragCount >= copyCount);
+
+ /* we copy differently based on the number channels */
+ if (s->dacChannels == 1) {
+ if (copy_from_user(db->lbuf + db->nextIn,
+ buffer, copyCount))
+ return -1;
+ /* fill gaps with 0 */
+ memset(db->lbuf + db->nextIn + copyCount,
+ 0, copyFragCount - copyCount);
+ } else {
+ /* we have demux the stream into two separate ones */
+ if (copy_two_channel_dac_from_user
+ (s, buffer, copyCount))
+ return -1;
+ /* fill gaps with 0 */
+ memset(db->lbuf + db->nextIn + copyCount,
+ 0, copyFragCount - copyCount);
+ memset(db->rbuf + db->nextIn + copyCount,
+ 0, copyFragCount - copyCount);
+ }
+
+#if defined(vr5701_AC97_VERBOSE_DEBUG)
+ for (i = 0; i < copyFragCount; i += db->fragSize) {
+ *(u16 *) (db->lbuf + db->nextIn + i) = inTicket++;
+ }
+#endif
+
+ count -= copyCount;
+ totalCopyCount += copyCount;
+ avail -= copyFragCount;
+ totalCopyFragCount += copyFragCount;
+
+ buffer += copyCount << (s->dacChannels - 1);
+
+ db->nextIn += copyFragCount;
+ if (db->nextIn >= db->fragTotalSize) {
+ ASSERT(db->nextIn == db->fragTotalSize);
+ db->nextIn = 0;
+ }
+
+ ASSERT((count == 0) || (copyCount == copyFragCount));
+ }
+
+ spin_lock_irqsave(&s->lock, flags);
+ db->count += totalCopyFragCount;
+ if (db->stopped)
+ if(start_dac(s)){
+ spin_unlock_irqrestore(&s->lock, flags);
+ return -1;
+ }
+
+ /* nextIn should not be equal to nextOut unless we are full */
+ if(!(((db->count == db->fragTotalSize) &&
+ (db->nextIn == db->nextOut)) ||
+ ((db->count < db->fragTotalSize) &&
+ (db->nextIn != db->nextOut)))){
+ spin_unlock_irqrestore(&s->lock, flags);
+ return -1;
+ }
+ spin_unlock_irqrestore(&s->lock, flags);
+
+ return totalCopyCount << (s->dacChannels - 1);
+
+}
+
+static int prog_dmabuf(struct vr5701_ac97_state *s,
+ struct dmabuf *db, unsigned rate)
+{
+ int order;
+ unsigned bufsize;
+
+ if (!db->lbuf) {
+ ASSERT(!db->rbuf);
+
+ db->ready = 0;
+ for (order = DMABUF_DEFAULTORDER;
+ order >= DMABUF_MINORDER; order--) {
+ db->lbuf = pci_alloc_consistent(s->dev,
+ PAGE_SIZE << order,
+ &db->lbufDma);
+ db->rbuf = pci_alloc_consistent(s->dev,
+ PAGE_SIZE << order,
+ &db->rbufDma);
+ if (db->lbuf && db->rbuf)
+ break;
+ if (db->lbuf) {
+ ASSERT(!db->rbuf);
+ pci_free_consistent(s->dev,
+ PAGE_SIZE << order,
+ db->lbuf, db->lbufDma);
+ }
+ }
+ if (!db->lbuf) {
+ ASSERT(!db->rbuf);
+ return -ENOMEM;
+ }
+
+ db->bufOrder = order;
+ }
+
+ db->count = 0;
+ db->nextIn = db->nextOut = 0;
+
+ bufsize = PAGE_SIZE << db->bufOrder;
+ db->fragShift = ld2(rate * 2 / 100);
+ if (db->fragShift < 4)
+ db->fragShift = 4;
+
+ db->numFrag = bufsize >> db->fragShift;
+ while (db->numFrag < 4 && db->fragShift > 4) {
+ db->fragShift--;
+ db->numFrag = bufsize >> db->fragShift;
+ }
+ db->fragSize = 1 << db->fragShift;
+ db->fragTotalSize = db->numFrag << db->fragShift;
+ memset(db->lbuf, 0, db->fragTotalSize);
+ memset(db->rbuf, 0, db->fragTotalSize);
+
+ db->ready = 1;
+
+ return 0;
+}
+
+static irqreturn_t vr5701_ac97_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ struct vr5701_ac97_state *s = (struct vr5701_ac97_state *)dev_id;
+ u32 irqStatus;
+ u32 adcInterrupts, dacInterrupts;
+
+ spin_lock(&s->lock);
+
+ /* get irqStatus and clear the detected ones */
+ irqStatus = inl(s->io + vr5701_INT_STATUS);
+ outl(irqStatus, s->io + vr5701_INT_CLR);
+
+ /* let us see what we get */
+ dacInterrupts = vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END;
+ adcInterrupts = vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END;
+ if (irqStatus & dacInterrupts) {
+ /* we should get both interrupts, but just in case ... */
+ if (irqStatus & vr5701_INT_MASK_DAC1END) {
+ vr5701_ac97_dac_interrupt(s);
+ }
+ if ((irqStatus & dacInterrupts) != dacInterrupts) {
+ printk(KERN_WARNING
+ "vr5701_ac97 : dac interrupts not in sync!!!\n");
+ stop_dac(s);
+ start_dac(s);
+ }
+ } else if (irqStatus & adcInterrupts) {
+ /* we should get both interrupts, but just in case ... */
+ if (irqStatus & vr5701_INT_MASK_ADC1END) {
+ vr5701_ac97_adc_interrupt(s);
+ }
+ if ((irqStatus & adcInterrupts) != adcInterrupts) {
+ printk(KERN_WARNING
+ "vr5701_ac97 : adc interrupts not in sync!!!\n");
+ stop_adc(s);
+ start_adc(s);
+ }
+ }
+
+ spin_unlock(&s->lock);
+ return IRQ_HANDLED;
+}
+
+static int vr5701_ac97_open_mixdev(struct inode *inode, struct file *file)
+{
+ int minor = iminor(inode);
+ struct list_head *list;
+ struct vr5701_ac97_state *s;
+
+ for (list = devs.next;; list = list->next) {
+ if (list == &devs)
+ return -ENODEV;
+ s = list_entry(list, struct vr5701_ac97_state, devs);
+ if (s->codec->dev_mixer == minor)
+ break;
+ }
+ file->private_data = s;
+ return nonseekable_open(inode, file);
+}
+
+static int vr5701_ac97_release_mixdev(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd,
+ unsigned long arg)
+{
+ return codec->mixer_ioctl(codec, cmd, arg);
+}
+
+static int vr5701_ac97_ioctl_mixdev(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct vr5701_ac97_state *s =
+ (struct vr5701_ac97_state *)file->private_data;
+ struct ac97_codec *codec = s->codec;
+
+ return mixdev_ioctl(codec, cmd, arg);
+}
+
+static struct file_operations vr5701_ac97_mixer_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .ioctl = vr5701_ac97_ioctl_mixdev,
+ .open = vr5701_ac97_open_mixdev,
+ .release = vr5701_ac97_release_mixdev,
+};
+
+static int drain_dac(struct vr5701_ac97_state *s, int nonblock)
+{
+ unsigned long flags;
+ int count, tmo;
+
+ if (!s->dma_dac.ready)
+ return 0;
+
+ for (;;) {
+ spin_lock_irqsave(&s->lock, flags);
+ count = s->dma_dac.count;
+ spin_unlock_irqrestore(&s->lock, flags);
+ if (count <= 0)
+ break;
+ if (signal_pending(current))
+ break;
+ if (nonblock)
+ return -EBUSY;
+ tmo = 1000 * count / s->dacRate / 2;
+ vr5701_ac97_delay(tmo);
+ }
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ return 0;
+}
+
+static ssize_t
+vr5701_ac97_read(struct file *file, char *buffer, size_t count, loff_t * ppos)
+{
+ struct vr5701_ac97_state *s =
+ (struct vr5701_ac97_state *)file->private_data;
+ struct dmabuf *db = &s->dma_adc;
+ ssize_t ret = 0;
+ unsigned long flags;
+ int copyCount;
+ size_t avail;
+
+ if (!access_ok(VERIFY_WRITE, buffer, count))
+ return -EFAULT;
+
+ ASSERT(db->ready);
+
+ while (count > 0) {
+ do {
+ spin_lock_irqsave(&s->lock, flags);
+ if (db->stopped)
+ start_adc(s);
+ avail = db->count;
+ spin_unlock_irqrestore(&s->lock, flags);
+ if (avail <= 0) {
+ if (file->f_flags & O_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ return ret;
+ }
+ interruptible_sleep_on(&db->wait);
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ return ret;
+ }
+ }
+ } while (avail <= 0);
+
+ ASSERT((avail % db->fragSize) == 0);
+ copyCount = copy_adc_to_user(s, buffer, count, avail);
+ if (copyCount <= 0) {
+ if (!ret)
+ ret = -EFAULT;
+ return ret;
+ }
+
+ count -= copyCount;
+ buffer += copyCount;
+ ret += copyCount;
+ }
+
+ return ret;
+}
+
+static ssize_t vr5701_ac97_write(struct file *file, const char *buffer,
+ size_t count, loff_t * ppos)
+{
+ struct vr5701_ac97_state *s =
+ (struct vr5701_ac97_state *)file->private_data;
+ struct dmabuf *db = &s->dma_dac;
+ ssize_t ret;
+ unsigned long flags;
+ int copyCount, avail;
+
+ if (!access_ok(VERIFY_READ, buffer, count))
+ return -EFAULT;
+ ret = 0;
+
+ while (count > 0) {
+ do {
+ spin_lock_irqsave(&s->lock, flags);
+ avail = db->fragTotalSize - db->count;
+ spin_unlock_irqrestore(&s->lock, flags);
+ if (avail <= 0) {
+ if (file->f_flags & O_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ return ret;
+ }
+ interruptible_sleep_on(&db->wait);
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ return ret;
+ }
+ }
+ } while (avail <= 0);
+
+ copyCount = copy_dac_from_user(s, buffer, count, avail);
+ if (copyCount < 0) {
+ if (!ret)
+ ret = -EFAULT;
+ stop_dac(s);
+ synchronize_irq(s->irq);
+ s->dma_dac.count = 0;
+ s->dma_dac.nextIn = s->dma_dac.nextOut = 0;
+ return ret;
+ }
+
+ count -= copyCount;
+ buffer += copyCount;
+ ret += copyCount;
+ }
+
+ return ret;
+}
+
+/* No kernel lock - we have our own spinlock */
+static unsigned int vr5701_ac97_poll(struct file *file,
+ struct poll_table_struct *wait)
+{
+ struct vr5701_ac97_state *s =
+ (struct vr5701_ac97_state *)file->private_data;
+ unsigned long flags;
+ unsigned int mask = 0;
+
+ if (file->f_mode & FMODE_WRITE)
+ poll_wait(file, &s->dma_dac.wait, wait);
+ if (file->f_mode & FMODE_READ)
+ poll_wait(file, &s->dma_adc.wait, wait);
+ spin_lock_irqsave(&s->lock, flags);
+ if (file->f_mode & FMODE_READ) {
+ if (s->dma_adc.count >= (signed)s->dma_adc.fragSize)
+ mask |= POLLIN | POLLRDNORM;
+ }
+ if (file->f_mode & FMODE_WRITE) {
+ if ((signed)s->dma_dac.fragTotalSize >=
+ s->dma_dac.count + (signed)s->dma_dac.fragSize)
+ mask |= POLLOUT | POLLWRNORM;
+ }
+ spin_unlock_irqrestore(&s->lock, flags);
+ return mask;
+}
+
+#ifdef vr5701_AC97_DEBUG
+static struct ioctl_str_t {
+ unsigned int cmd;
+ const char *str;
+} ioctl_str[] = {
+ {
+ SNDCTL_DSP_RESET, "SNDCTL_DSP_RESET"}, {
+ SNDCTL_DSP_SYNC, "SNDCTL_DSP_SYNC"}, {
+ SNDCTL_DSP_SPEED, "SNDCTL_DSP_SPEED"}, {
+ SNDCTL_DSP_STEREO, "SNDCTL_DSP_STEREO"}, {
+ SNDCTL_DSP_GETBLKSIZE, "SNDCTL_DSP_GETBLKSIZE"}, {
+ SNDCTL_DSP_SETFMT, "SNDCTL_DSP_SETFMT"}, {
+ SNDCTL_DSP_SAMPLESIZE, "SNDCTL_DSP_SAMPLESIZE"}, {
+ SNDCTL_DSP_CHANNELS, "SNDCTL_DSP_CHANNELS"}, {
+ SOUND_PCM_WRITE_CHANNELS, "SOUND_PCM_WRITE_CHANNELS"}, {
+ SOUND_PCM_WRITE_FILTER, "SOUND_PCM_WRITE_FILTER"}, {
+ SNDCTL_DSP_POST, "SNDCTL_DSP_POST"}, {
+ SNDCTL_DSP_SUBDIVIDE, "SNDCTL_DSP_SUBDIVIDE"}, {
+ SNDCTL_DSP_SETFRAGMENT, "SNDCTL_DSP_SETFRAGMENT"}, {
+ SNDCTL_DSP_GETFMTS, "SNDCTL_DSP_GETFMTS"}, {
+ SNDCTL_DSP_GETOSPACE, "SNDCTL_DSP_GETOSPACE"}, {
+ SNDCTL_DSP_GETISPACE, "SNDCTL_DSP_GETISPACE"}, {
+ SNDCTL_DSP_NONBLOCK, "SNDCTL_DSP_NONBLOCK"}, {
+ SNDCTL_DSP_GETCAPS, "SNDCTL_DSP_GETCAPS"}, {
+ SNDCTL_DSP_GETTRIGGER, "SNDCTL_DSP_GETTRIGGER"}, {
+ SNDCTL_DSP_SETTRIGGER, "SNDCTL_DSP_SETTRIGGER"}, {
+ SNDCTL_DSP_GETIPTR, "SNDCTL_DSP_GETIPTR"}, {
+ SNDCTL_DSP_GETOPTR, "SNDCTL_DSP_GETOPTR"}, {
+ SNDCTL_DSP_MAPINBUF, "SNDCTL_DSP_MAPINBUF"}, {
+ SNDCTL_DSP_MAPOUTBUF, "SNDCTL_DSP_MAPOUTBUF"}, {
+ SNDCTL_DSP_SETSYNCRO, "SNDCTL_DSP_SETSYNCRO"}, {
+ SNDCTL_DSP_SETDUPLEX, "SNDCTL_DSP_SETDUPLEX"}, {
+ SNDCTL_DSP_GETODELAY, "SNDCTL_DSP_GETODELAY"}, {
+ SNDCTL_DSP_GETCHANNELMASK, "SNDCTL_DSP_GETCHANNELMASK"}, {
+ SNDCTL_DSP_BIND_CHANNEL, "SNDCTL_DSP_BIND_CHANNEL"}, {
+ OSS_GETVERSION, "OSS_GETVERSION"}, {
+ SOUND_PCM_READ_RATE, "SOUND_PCM_READ_RATE"}, {
+ SOUND_PCM_READ_CHANNELS, "SOUND_PCM_READ_CHANNELS"}, {
+ SOUND_PCM_READ_BITS, "SOUND_PCM_READ_BITS"}, {
+ SOUND_PCM_READ_FILTER, "SOUND_PCM_READ_FILTER"}
+};
+#endif
+
+static int vr5701_ac97_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct vr5701_ac97_state *s =
+ (struct vr5701_ac97_state *)file->private_data;
+ unsigned long flags;
+ audio_buf_info abinfo;
+ int count;
+ int val, ret;
+
+#ifdef vr5701_AC97_DEBUG
+ for (count = 0; count < sizeof(ioctl_str) / sizeof(ioctl_str[0]);
+ count++) {
+ if (ioctl_str[count].cmd == cmd)
+ break;
+ }
+ if (count < sizeof(ioctl_str) / sizeof(ioctl_str[0]))
+ printk(KERN_INFO PFX "ioctl %s\n", ioctl_str[count].str);
+ else
+ printk(KERN_INFO PFX "ioctl unknown, 0x%x\n", cmd);
+#endif
+
+ switch (cmd) {
+ case OSS_GETVERSION:
+ return put_user(SOUND_VERSION, (int *)arg);
+
+ case SNDCTL_DSP_SYNC:
+ if (file->f_mode & FMODE_WRITE)
+ return drain_dac(s, file->f_flags & O_NONBLOCK);
+ return 0;
+
+ case SNDCTL_DSP_SETDUPLEX:
+ return 0;
+
+ case SNDCTL_DSP_GETCAPS:
+ return put_user(DSP_CAP_DUPLEX, (int *)arg);
+
+ case SNDCTL_DSP_RESET:
+ if (file->f_mode & FMODE_WRITE) {
+ stop_dac(s);
+ synchronize_irq(s->irq);
+ s->dma_dac.count = 0;
+ s->dma_dac.nextIn = s->dma_dac.nextOut = 0;
+ }
+ if (file->f_mode & FMODE_READ) {
+ stop_adc(s);
+ synchronize_irq(s->irq);
+ s->dma_adc.count = 0;
+ s->dma_adc.nextIn = s->dma_adc.nextOut = 0;
+ }
+ return 0;
+
+ case SNDCTL_DSP_SPEED:
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
+ if (val >= 0) {
+ if (file->f_mode & FMODE_READ) {
+ stop_adc(s);
+ set_adc_rate(s, val);
+ if ((ret = prog_dmabuf_adc(s)))
+ return ret;
+ }
+ if (file->f_mode & FMODE_WRITE) {
+ stop_dac(s);
+ set_dac_rate(s, val);
+ if ((ret = prog_dmabuf_dac(s)))
+ return ret;
+ }
+ }
+ return put_user((file->f_mode & FMODE_READ) ?
+ s->adcRate : s->dacRate, (int *)arg);
+
+ case SNDCTL_DSP_STEREO:
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
+ if (file->f_mode & FMODE_READ) {
+ stop_adc(s);
+ if (val)
+ s->adcChannels = 2;
+ else
+ s->adcChannels = 1;
+ if ((ret = prog_dmabuf_adc(s)))
+ return ret;
+ }
+ if (file->f_mode & FMODE_WRITE) {
+ stop_dac(s);
+ if (val)
+ s->dacChannels = 2;
+ else
+ s->dacChannels = 1;
+ if ((ret = prog_dmabuf_dac(s)))
+ return ret;
+ }
+ return 0;
+
+ case SNDCTL_DSP_CHANNELS:
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
+ if (val != 0) {
+ if ((val != 1) && (val != 2))
+ val = 2;
+
+ if (file->f_mode & FMODE_READ) {
+ stop_adc(s);
+ s->dacChannels = val;
+ if ((ret = prog_dmabuf_adc(s)))
+ return ret;
+ }
+ if (file->f_mode & FMODE_WRITE) {
+ stop_dac(s);
+ s->dacChannels = val;
+ if ((ret = prog_dmabuf_dac(s)))
+ return ret;
+ }
+ }
+ return put_user(val, (int *)arg);
+
+ case SNDCTL_DSP_GETFMTS: /* Returns a mask */
+ return put_user(AFMT_S16_LE, (int *)arg);
+
+ case SNDCTL_DSP_SETFMT: /* Selects ONE fmt */
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
+ if (val != AFMT_QUERY) {
+ if (val != AFMT_S16_LE)
+ return -EINVAL;
+ if (file->f_mode & FMODE_READ) {
+ stop_adc(s);
+ if ((ret = prog_dmabuf_adc(s)))
+ return ret;
+ }
+ if (file->f_mode & FMODE_WRITE) {
+ stop_dac(s);
+ if ((ret = prog_dmabuf_dac(s)))
+ return ret;
+ }
+ } else {
+ val = AFMT_S16_LE;
+ }
+ return put_user(val, (int *)arg);
+
+ case SNDCTL_DSP_POST:
+ return 0;
+
+ case SNDCTL_DSP_GETTRIGGER:
+ case SNDCTL_DSP_SETTRIGGER:
+ /* NO trigger */
+ return -EINVAL;
+
+ case SNDCTL_DSP_GETOSPACE:
+ if (!(file->f_mode & FMODE_WRITE))
+ return -EINVAL;
+ abinfo.fragsize = s->dma_dac.fragSize << (s->dacChannels - 1);
+ spin_lock_irqsave(&s->lock, flags);
+ count = s->dma_dac.count;
+ spin_unlock_irqrestore(&s->lock, flags);
+ abinfo.bytes = (s->dma_dac.fragTotalSize - count) <<
+ (s->dacChannels - 1);
+ abinfo.fragstotal = s->dma_dac.numFrag;
+ abinfo.fragments = abinfo.bytes >> s->dma_dac.fragShift >>
+ (s->dacChannels - 1);
+ return copy_to_user((void *)arg, &abinfo,
+ sizeof(abinfo)) ? -EFAULT : 0;
+
+ case SNDCTL_DSP_GETISPACE:
+ if (!(file->f_mode & FMODE_READ))
+ return -EINVAL;
+ abinfo.fragsize = s->dma_adc.fragSize << (s->adcChannels - 1);
+ spin_lock_irqsave(&s->lock, flags);
+ count = s->dma_adc.count;
+ spin_unlock_irqrestore(&s->lock, flags);
+ if (count < 0)
+ count = 0;
+ abinfo.bytes = count << (s->adcChannels - 1);
+ abinfo.fragstotal = s->dma_adc.numFrag;
+ abinfo.fragments = (abinfo.bytes >> s->dma_adc.fragShift) >>
+ (s->adcChannels - 1);
+ return copy_to_user((void *)arg, &abinfo,
+ sizeof(abinfo)) ? -EFAULT : 0;
+
+ case SNDCTL_DSP_NONBLOCK:
+ file->f_flags |= O_NONBLOCK;
+ return 0;
+
+ case SNDCTL_DSP_GETODELAY:
+ if (!(file->f_mode & FMODE_WRITE))
+ return -EINVAL;
+ spin_lock_irqsave(&s->lock, flags);
+ count = s->dma_dac.count;
+ spin_unlock_irqrestore(&s->lock, flags);
+ return put_user(count, (int *)arg);
+
+ case SNDCTL_DSP_GETIPTR:
+ case SNDCTL_DSP_GETOPTR:
+ /* we cannot get DMA ptr */
+ return -EINVAL;
+
+ case SNDCTL_DSP_GETBLKSIZE:
+ if (file->f_mode & FMODE_WRITE)
+ return put_user(s->dma_dac.
+ fragSize << (s->dacChannels - 1),
+ (int *)arg);
+ else
+ return put_user(s->dma_adc.
+ fragSize << (s->adcChannels - 1),
+ (int *)arg);
+
+ case SNDCTL_DSP_SETFRAGMENT:
+ /* we ignore fragment size request */
+ return 0;
+
+ case SNDCTL_DSP_SUBDIVIDE:
+ /* what is this for? [jsun] */
+ return 0;
+
+ case SOUND_PCM_READ_RATE:
+ return put_user((file->f_mode & FMODE_READ) ?
+ s->adcRate : s->dacRate, (int *)arg);
+
+ case SOUND_PCM_READ_CHANNELS:
+ if (file->f_mode & FMODE_READ)
+ return put_user(s->adcChannels, (int *)arg);
+ else
+ return put_user(s->dacChannels ? 2 : 1, (int *)arg);
+
+ case SOUND_PCM_READ_BITS:
+ return put_user(16, (int *)arg);
+
+ case SOUND_PCM_WRITE_FILTER:
+ case SNDCTL_DSP_SETSYNCRO:
+ case SOUND_PCM_READ_FILTER:
+ return -EINVAL;
+ }
+
+ return mixdev_ioctl(s->codec, cmd, arg);
+}
+
+static int vr5701_ac97_open(struct inode *inode, struct file *file)
+{
+ int minor = iminor(inode);
+ DECLARE_WAITQUEUE(wait, current);
+ unsigned long flags;
+ struct list_head *list;
+ struct vr5701_ac97_state *s;
+ int ret = 0;
+
+ nonseekable_open(inode, file);
+ for (list = devs.next;; list = list->next) {
+ if (list == &devs)
+ return -ENODEV;
+ s = list_entry(list, struct vr5701_ac97_state, devs);
+ if (!((s->dev_audio ^ minor) & ~0xf))
+ break;
+ }
+ file->private_data = s;
+
+ /* wait for device to become free */
+ down(&s->open_sem);
+ while (s->open_mode & file->f_mode) {
+
+ if (file->f_flags & O_NONBLOCK) {
+ up(&s->open_sem);
+ return -EBUSY;
+ }
+ add_wait_queue(&s->open_wait, &wait);
+ __set_current_state(TASK_INTERRUPTIBLE);
+ up(&s->open_sem);
+ schedule();
+ remove_wait_queue(&s->open_wait, &wait);
+ set_current_state(TASK_RUNNING);
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ down(&s->open_sem);
+ }
+
+ spin_lock_irqsave(&s->lock, flags);
+
+ if (file->f_mode & FMODE_READ) {
+ /* set default settings */
+ set_adc_rate(s, 48000);
+ s->adcChannels = 2;
+
+ ret = prog_dmabuf_adc(s);
+ if (ret)
+ goto bailout;
+ }
+ if (file->f_mode & FMODE_WRITE) {
+ /* set default settings */
+ set_dac_rate(s, 48000);
+ s->dacChannels = 2;
+
+ ret = prog_dmabuf_dac(s);
+ if (ret)
+ goto bailout;
+ }
+
+ s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
+
+ bailout:
+ spin_unlock_irqrestore(&s->lock, flags);
+
+ up(&s->open_sem);
+ return ret;
+}
+
+static int vr5701_ac97_release(struct inode *inode, struct file *file)
+{
+ struct vr5701_ac97_state *s =
+ (struct vr5701_ac97_state *)file->private_data;
+
+ lock_kernel();
+ if (file->f_mode & FMODE_WRITE)
+ drain_dac(s, file->f_flags & O_NONBLOCK);
+ down(&s->open_sem);
+ if (file->f_mode & FMODE_WRITE) {
+ stop_dac(s);
+ dealloc_dmabuf(s, &s->dma_dac);
+ }
+ if (file->f_mode & FMODE_READ) {
+ stop_adc(s);
+ dealloc_dmabuf(s, &s->dma_adc);
+ }
+ s->open_mode &= (~file->f_mode) & (FMODE_READ | FMODE_WRITE);
+ up(&s->open_sem);
+ wake_up(&s->open_wait);
+ unlock_kernel();
+ return 0;
+}
+
+static struct file_operations vr5701_ac97_audio_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .read = vr5701_ac97_read,
+ .write = vr5701_ac97_write,
+ .poll = vr5701_ac97_poll,
+ .ioctl = vr5701_ac97_ioctl,
+ .open = vr5701_ac97_open,
+ .release = vr5701_ac97_release,
+};
+
+/*
+ * for debugging purposes, we'll create a proc device that dumps the
+ * CODEC chipstate
+ */
+
+#ifdef vr5701_AC97_DEBUG
+
+struct {
+ const char *regname;
+ unsigned regaddr;
+} vr5701_ac97_regs[] = {
+ {
+ "vr5701_INT_STATUS", vr5701_INT_STATUS}, {
+ "vr5701_CODEC_WR", vr5701_CODEC_WR}, {
+ "vr5701_CODEC_RD", vr5701_CODEC_RD}, {
+ "vr5701_CTRL", vr5701_CTRL}, {
+ "vr5701_ACLINK_CTRL", vr5701_ACLINK_CTRL}, {
+ "vr5701_INT_MASK", vr5701_INT_MASK}, {
+ "vr5701_DAC1_CTRL", vr5701_DAC1_CTRL}, {
+ "vr5701_DAC1L", vr5701_DAC1L}, {
+ "vr5701_DAC1_BADDR", vr5701_DAC1_BADDR}, {
+ "vr5701_DAC2_CTRL", vr5701_DAC2_CTRL}, {
+ "vr5701_DAC2L", vr5701_DAC2L}, {
+ "vr5701_DAC2_BADDR", vr5701_DAC2_BADDR}, {
+ "vr5701_DAC3_CTRL", vr5701_DAC3_CTRL}, {
+ "vr5701_DAC3L", vr5701_DAC3L}, {
+ "vr5701_DAC3_BADDR", vr5701_DAC3_BADDR}, {
+ "vr5701_ADC1_CTRL", vr5701_ADC1_CTRL}, {
+ "vr5701_ADC1L", vr5701_ADC1L}, {
+ "vr5701_ADC1_BADDR", vr5701_ADC1_BADDR}, {
+ "vr5701_ADC2_CTRL", vr5701_ADC2_CTRL}, {
+ "vr5701_ADC2L", vr5701_ADC2L}, {
+ "vr5701_ADC2_BADDR", vr5701_ADC2_BADDR}, {
+ "vr5701_ADC3_CTRL", vr5701_ADC3_CTRL}, {
+ "vr5701_ADC3L", vr5701_ADC3L}, {
+ "vr5701_ADC3_BADDR", vr5701_ADC3_BADDR}, {
+ NULL, 0x0}
+};
+
+static int proc_vr5701_ac97_dump(char *buf, char **start, off_t fpos,
+ int length, int *eof, void *data)
+{
+ struct vr5701_ac97_state *s;
+ int cnt, len = 0;
+
+ if (list_empty(&devs))
+ return 0;
+ s = list_entry(devs.next, struct vr5701_ac97_state, devs);
+
+ /* print out header */
+ len += sprintf(buf + len, "\n\t\tvr5701 Audio Debug\n\n");
+
+ len += sprintf(buf + len, "NEC Electronics Corporation VR5701 SolutionGearII Audio Controller registers\n");
+ len += sprintf(buf + len, "---------------------------------\n");
+ for (cnt = 0; vr5701_ac97_regs[cnt].regname != NULL; cnt++) {
+ len += sprintf(buf + len, "%-20s = %08x\n",
+ vr5701_ac97_regs[cnt].regname,
+ inl(s->io + vr5701_ac97_regs[cnt].regaddr));
+ }
+
+ /* print out driver state */
+ len += sprintf(buf + len, "NEC Electronics Corporation VR5701 SolutionGearII Audio driver states\n");
+ len += sprintf(buf + len, "---------------------------------\n");
+ len += sprintf(buf + len, "dacChannels = %d\n", s->dacChannels);
+ len += sprintf(buf + len, "adcChannels = %d\n", s->adcChannels);
+ len += sprintf(buf + len, "dacRate = %d\n", s->dacRate);
+ len += sprintf(buf + len, "adcRate = %d\n", s->adcRate);
+
+ len += sprintf(buf + len, "dma_dac is %s ready\n",
+ s->dma_dac.ready ? "" : "not");
+ if (s->dma_dac.ready) {
+ len += sprintf(buf + len, "dma_dac is %s stopped.\n",
+ s->dma_dac.stopped ? "" : "not");
+ len += sprintf(buf + len, "dma_dac.fragSize = %x\n",
+ s->dma_dac.fragSize);
+ len += sprintf(buf + len, "dma_dac.fragShift = %x\n",
+ s->dma_dac.fragShift);
+ len += sprintf(buf + len, "dma_dac.numFrag = %x\n",
+ s->dma_dac.numFrag);
+ len += sprintf(buf + len, "dma_dac.fragTotalSize = %x\n",
+ s->dma_dac.fragTotalSize);
+ len += sprintf(buf + len, "dma_dac.nextIn = %x\n",
+ s->dma_dac.nextIn);
+ len += sprintf(buf + len, "dma_dac.nextOut = %x\n",
+ s->dma_dac.nextOut);
+ len += sprintf(buf + len, "dma_dac.count = %x\n",
+ s->dma_dac.count);
+ }
+
+ len += sprintf(buf + len, "dma_adc is %s ready\n",
+ s->dma_adc.ready ? "" : "not");
+ if (s->dma_adc.ready) {
+ len += sprintf(buf + len, "dma_adc is %s stopped.\n",
+ s->dma_adc.stopped ? "" : "not");
+ len += sprintf(buf + len, "dma_adc.fragSize = %x\n",
+ s->dma_adc.fragSize);
+ len += sprintf(buf + len, "dma_adc.fragShift = %x\n",
+ s->dma_adc.fragShift);
+ len += sprintf(buf + len, "dma_adc.numFrag = %x\n",
+ s->dma_adc.numFrag);
+ len += sprintf(buf + len, "dma_adc.fragTotalSize = %x\n",
+ s->dma_adc.fragTotalSize);
+ len += sprintf(buf + len, "dma_adc.nextIn = %x\n",
+ s->dma_adc.nextIn);
+ len += sprintf(buf + len, "dma_adc.nextOut = %x\n",
+ s->dma_adc.nextOut);
+ len += sprintf(buf + len, "dma_adc.count = %x\n",
+ s->dma_adc.count);
+ }
+
+ /* print out CODEC state */
+ len += sprintf(buf + len, "\nAC97 CODEC registers\n");
+ len += sprintf(buf + len, "----------------------\n");
+ for (cnt = 0; cnt <= 0x7e; cnt = cnt + 2)
+ len += sprintf(buf + len, "reg %02x = %04x\n",
+ cnt, rdcodec(s->codec, cnt));
+
+ if (fpos >= len) {
+ *start = buf;
+ *eof = 1;
+ return 0;
+ }
+ *start = buf + fpos;
+ if ((len -= fpos) > length)
+ return length;
+ *eof = 1;
+ return len;
+
+}
+#endif /* vr5701_AC97_DEBUG */
+
+static unsigned int devindex;
+
+MODULE_AUTHOR("Sergey Podstavin");
+MODULE_DESCRIPTION("NEC Electronics Corporation VR5701 SolutionGearII audio (AC97) Driver");
+MODULE_LICENSE("GPL");
+
+static int __devinit vr5701_ac97_probe(struct pci_dev *pcidev,
+ const struct pci_device_id *pciid)
+{
+ struct vr5701_ac97_state *s;
+#ifdef vr5701_AC97_DEBUG
+ char proc_str[80];
+#endif
+
+ if (pcidev->irq == 0)
+ return -1;
+
+ if (!(s = kmalloc(sizeof(struct vr5701_ac97_state), GFP_KERNEL))) {
+ printk(KERN_ERR PFX "alloc of device struct failed\n");
+ return -1;
+ }
+ memset(s, 0, sizeof(struct vr5701_ac97_state));
+
+ init_waitqueue_head(&s->dma_adc.wait);
+ init_waitqueue_head(&s->dma_dac.wait);
+ init_waitqueue_head(&s->open_wait);
+ init_MUTEX(&s->open_sem);
+ spin_lock_init(&s->lock);
+
+ s->dev = pcidev;
+ s->io = pci_resource_start(pcidev, 0);
+ s->irq = pcidev->irq;
+
+ s->codec = ac97_alloc_codec();
+
+ s->codec->private_data = s;
+ s->codec->id = 0;
+ s->codec->codec_read = rdcodec;
+ s->codec->codec_write = wrcodec;
+ s->codec->codec_wait = waitcodec;
+
+ /* setting some other default values such as
+ * adcChannels, adcRate is done in open() so that
+ * no persistent state across file opens.
+ */
+
+ if (!request_region(s->io, pci_resource_len(pcidev, 0),
+ vr5701_AC97_MODULE_NAME)) {
+ printk(KERN_ERR PFX "io ports %#lx->%#lx in use\n",
+ s->io, s->io + pci_resource_len(pcidev, 0) - 1);
+ goto err_region;
+ }
+ if (request_irq(s->irq, vr5701_ac97_interrupt, SA_INTERRUPT,
+ vr5701_AC97_MODULE_NAME, s)) {
+ printk(KERN_ERR PFX "irq %u in use\n", s->irq);
+ goto err_irq;
+ }
+
+ printk(KERN_INFO PFX "IO at %#lx, IRQ %d\n", s->io, s->irq);
+
+ /* register devices */
+ if ((s->dev_audio =
+ register_sound_dsp(&vr5701_ac97_audio_fops, -1)) < 0)
+ goto err_dev1;
+ if ((s->codec->dev_mixer =
+ register_sound_mixer(&vr5701_ac97_mixer_fops, -1)) < 0)
+ goto err_dev2;
+
+#ifdef vr5701_AC97_DEBUG
+ /* initialize the debug proc device */
+ s->ps = create_proc_read_entry(vr5701_AC97_MODULE_NAME, 0, NULL,
+ proc_vr5701_ac97_dump, NULL);
+#endif /* vr5701_AC97_DEBUG */
+
+ /* enable pci io and bus mastering */
+ if (pci_enable_device(pcidev))
+ goto err_dev3;
+ pci_set_master(pcidev);
+
+ /* cold reset the AC97 */
+ outl(vr5701_ACLINK_CTRL_RST_ON | vr5701_ACLINK_CTRL_RST_TIME,
+ s->io + vr5701_ACLINK_CTRL);
+ while (inl(s->io + vr5701_ACLINK_CTRL) & vr5701_ACLINK_CTRL_RST_ON) ;
+
+ /* codec init */
+ if (!ac97_probe_codec(s->codec))
+ goto err_dev3;
+
+#ifdef vr5701_AC97_DEBUG
+ sprintf(proc_str, "driver/%s/%d/ac97",
+ vr5701_AC97_MODULE_NAME, s->codec->id);
+ s->ac97_ps = create_proc_read_entry(proc_str, 0, NULL,
+ ac97_read_proc, s->codec);
+ /* TODO : why this proc file does not show up? */
+#endif
+
+ /* Try to enable variable rate audio mode. */
+ wrcodec(s->codec, AC97_EXTENDED_STATUS,
+ rdcodec(s->codec, AC97_EXTENDED_STATUS) | AC97_EXTSTAT_VRA);
+ /* Did we enable it? */
+ if (rdcodec(s->codec, AC97_EXTENDED_STATUS) & AC97_EXTSTAT_VRA)
+ s->extended_status |= AC97_EXTSTAT_VRA;
+ else {
+ s->dacRate = 48000;
+ printk(KERN_INFO PFX "VRA mode not enabled; rate fixed at %d.",
+ s->dacRate);
+ }
+
+ /* let us get the default volumne louder */
+ wrcodec(s->codec, 0x2, 0x1010); /* master volume, middle */
+ wrcodec(s->codec, 0xc, 0x10); /* phone volume, middle */
+ wrcodec(s->codec, 0x10, 0x8000); /* line-in 2 line-out disable */
+ wrcodec(s->codec, 0x18, 0x0707); /* PCM out (line out) middle */
+
+ /* by default we select line in the input */
+ wrcodec(s->codec, 0xe, 0x10); /* misc volume, middle */
+ wrcodec(s->codec, 0x1a, 0x0000); /* default line is Line_mic */
+ /* wrcodec(s->codec, 0x1a, 0x0404); *//* default line is Line_in */
+ wrcodec(s->codec, 0x1c, 0x0f0f);
+ wrcodec(s->codec, 0x1e, 0x07);
+
+ /* enable the master interrupt but disable all others */
+ outl(vr5701_INT_MASK_NMASK, s->io + vr5701_INT_MASK);
+
+ /* store it in the driver field */
+ pci_set_drvdata(pcidev, s);
+ pcidev->dma_mask = 0xffffffff;
+ /* put it into driver list */
+ list_add_tail(&s->devs, &devs);
+ /* increment devindex */
+ if (devindex < NR_DEVICE - 1)
+ devindex++;
+ return 0;
+
+ err_dev3:
+ unregister_sound_mixer(s->codec->dev_mixer);
+ err_dev2:
+ unregister_sound_dsp(s->dev_audio);
+ err_dev1:
+ printk(KERN_ERR PFX "cannot register misc device\n");
+ free_irq(s->irq, s);
+
+ err_irq:
+ release_region(s->io, pci_resource_len(pcidev, 0));
+ err_region:
+ ac97_release_codec(s->codec);
+ kfree(s);
+ return -1;
+}
+
+static void __devexit vr5701_ac97_remove(struct pci_dev *dev)
+{
+ struct vr5701_ac97_state *s = pci_get_drvdata(dev);
+
+ if (!s)
+ return;
+ list_del(&s->devs);
+
+#ifdef vr5701_AC97_DEBUG
+ if (s->ps)
+ remove_proc_entry(vr5701_AC97_MODULE_NAME, NULL);
+#endif /* vr5701_AC97_DEBUG */
+
+ synchronize_irq();
+ free_irq(s->irq, s);
+ release_region(s->io, pci_resource_len(dev, 0));
+ unregister_sound_dsp(s->dev_audio);
+ unregister_sound_mixer(s->codec->dev_mixer);
+ ac97_release_codec(s->codec);
+ kfree(s);
+ pci_set_drvdata(dev, NULL);
+}
+
+static struct pci_device_id id_table[] = {
+ {PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_VRC5477_AC97,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, id_table);
+
+static struct pci_driver vr5701_ac97_driver = {
+ .name = vr5701_AC97_MODULE_NAME,
+ .id_table = id_table,
+ .probe = vr5701_ac97_probe,
+ .remove = __devexit_p(vr5701_ac97_remove)
+};
+
+static int __init init_vr5701_ac97(void)
+{
+ printk(KERN_INFO "NEC Electronics Corporation VR5701 SolutionGearII AC97 driver: time " __TIME__ " " __DATE__
+ " by Sergey Podstavin\n");
+ return pci_module_init(&vr5701_ac97_driver);
+}
+
+static void __exit cleanup_vr5701_ac97(void)
+{
+ printk(KERN_INFO PFX "unloading\n");
+ pci_unregister_driver(&vr5701_ac97_driver);
+}
+
+module_init(init_vr5701_ac97);
+module_exit(cleanup_vr5701_ac97);
Index: linux-2.6.10/sound/oss/nec_vr5701_sg2.h
===================================================================
--- /dev/null
+++ linux-2.6.10/sound/oss/nec_vr5701_sg2.h
@@ -0,0 +1,531 @@
+/*
+ * sound/oss/nec_vr5701_sg2.h
+ *
+ * A sound driver for NEC Electronics Corporation VR5701 SolutionGearII.
+ * It works with AC97 codec.
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/sound.h>
+#include <linux/slab.h>
+#include <linux/soundcard.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/bitops.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
+#include <linux/ac97_codec.h>
+#include <linux/interrupt.h>
+#include <asm/hardirq.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/uaccess.h>
+
+#define vr5701_INT_CLR 0x0
+#define vr5701_INT_STATUS 0x0
+#define vr5701_CODEC_WR 0x4
+#define vr5701_CODEC_RD 0x8
+#define vr5701_CTRL 0x18
+#define vr5701_ACLINK_CTRL 0x1c
+#define vr5701_INT_MASK 0x24
+
+#define vr5701_DAC1_CTRL 0x30
+#define vr5701_DAC1L 0x34
+#define vr5701_DAC1_BADDR 0x38
+#define vr5701_DAC2_CTRL 0x3c
+#define vr5701_DAC2L 0x40
+#define vr5701_DAC2_BADDR 0x44
+#define vr5701_DAC3_CTRL 0x48
+#define vr5701_DAC3L 0x4c
+#define vr5701_DAC3_BADDR 0x50
+
+#define vr5701_ADC1_CTRL 0x54
+#define vr5701_ADC1L 0x58
+#define vr5701_ADC1_BADDR 0x5c
+#define vr5701_ADC2_CTRL 0x60
+#define vr5701_ADC2L 0x64
+#define vr5701_ADC2_BADDR 0x68
+#define vr5701_ADC3_CTRL 0x6c
+#define vr5701_ADC3L 0x70
+#define vr5701_ADC3_BADDR 0x74
+
+#define vr5701_CODEC_WR_RWC (1 << 23)
+
+#define vr5701_CODEC_RD_RRDYA (1 << 31)
+#define vr5701_CODEC_RD_RRDYD (1 << 30)
+
+#define vr5701_ACLINK_CTRL_RST_ON (1 << 15)
+#define vr5701_ACLINK_CTRL_RST_TIME 0x7f
+#define vr5701_ACLINK_CTRL_SYNC_ON (1 << 30)
+#define vr5701_ACLINK_CTRL_CK_STOP_ON (1 << 31)
+
+#define vr5701_CTRL_DAC2ENB (1 << 15)
+#define vr5701_CTRL_ADC2ENB (1 << 14)
+#define vr5701_CTRL_DAC1ENB (1 << 13)
+#define vr5701_CTRL_ADC1ENB (1 << 12)
+
+#define vr5701_INT_MASK_NMASK (1 << 31)
+#define vr5701_INT_MASK_DAC1END (1 << 5)
+#define vr5701_INT_MASK_DAC2END (1 << 4)
+#define vr5701_INT_MASK_DAC3END (1 << 3)
+#define vr5701_INT_MASK_ADC1END (1 << 2)
+#define vr5701_INT_MASK_ADC2END (1 << 1)
+#define vr5701_INT_MASK_ADC3END (1 << 0)
+
+#define vr5701_DMA_ACTIVATION (1 << 31)
+#define vr5701_DMA_WIP (1 << 30)
+
+#define vr5701_AC97_MODULE_NAME "NEC_vr5701_audio"
+#define PFX vr5701_AC97_MODULE_NAME ": "
+#define WORK_BUF_SIZE 2048
+
+#define DMABUF_DEFAULTORDER (16-PAGE_SHIFT)
+#define DMABUF_MINORDER 1
+
+/* maximum number of devices; only used for command line params */
+#define NR_DEVICE 5
+/* -------------------debug macros -------------------------------------- */
+#undef vr5701_AC97_DEBUG
+
+#undef vr5701_AC97_VERBOSE_DEBUG
+
+#if defined(vr5701_AC97_VERBOSE_DEBUG)
+#define vr5701_AC97_DEBUG
+#endif
+
+#if defined(vr5701_AC97_DEBUG)
+#define ASSERT(x) if (!(x)) { \
+ panic("assertion failed at %s:%d: %s\n", __FILE__, __LINE__, #x); }
+#else
+#define ASSERT(x)
+#endif /* vr5701_AC97_DEBUG */
+
+static inline unsigned ld2(unsigned int x)
+{
+ unsigned r = 0;
+
+ if (x >= 0x10000) {
+ x >>= 16;
+ r += 16;
+ }
+ if (x >= 0x100) {
+ x >>= 8;
+ r += 8;
+ }
+ if (x >= 0x10) {
+ x >>= 4;
+ r += 4;
+ }
+ if (x >= 4) {
+ x >>= 2;
+ r += 2;
+ }
+ if (x >= 2)
+ r++;
+ return r;
+}
+
+#if defined(vr5701_AC97_VERBOSE_DEBUG)
+static u16 inTicket; /* check sync between intr & write */
+static u16 outTicket;
+#endif
+
+#undef OSS_DOCUMENTED_MIXER_SEMANTICS
+
+static const unsigned sample_shift[] = { 0, 1, 1, 2 };
+
+struct vr5701_ac97_state {
+ /* list of vr5701_ac97 devices */
+ struct list_head devs;
+
+ /* the corresponding pci_dev structure */
+ struct pci_dev *dev;
+
+ /* soundcore stuff */
+ int dev_audio;
+
+ /* hardware resources */
+ unsigned long io;
+ unsigned int irq;
+
+#ifdef vr5701_AC97_DEBUG
+ /* debug /proc entry */
+ struct proc_dir_entry *ps;
+ struct proc_dir_entry *ac97_ps;
+#endif /* vr5701_AC97_DEBUG */
+
+ struct ac97_codec *codec;
+
+ unsigned dacChannels, adcChannels;
+ unsigned short dacRate, adcRate;
+ unsigned short extended_status;
+
+ spinlock_t lock;
+ struct semaphore open_sem;
+ mode_t open_mode;
+ wait_queue_head_t open_wait;
+
+ struct dmabuf {
+ void *lbuf, *rbuf;
+ dma_addr_t lbufDma, rbufDma;
+ unsigned bufOrder;
+ unsigned numFrag;
+ unsigned fragShift;
+ unsigned fragSize; /* redundant */
+ unsigned fragTotalSize; /* = numFrag * fragSize(real) */
+ unsigned nextIn;
+ unsigned nextOut;
+ int count;
+ unsigned error; /* over/underrun */
+ wait_queue_head_t wait;
+ /* OSS stuff */
+ unsigned stopped:1;
+ unsigned ready:1;
+ } dma_dac, dma_adc;
+
+ struct {
+ u16 lchannel;
+ u16 rchannel;
+ } workBuf[WORK_BUF_SIZE / 4];
+};
+static inline void stop_dac(struct vr5701_ac97_state *s)
+{
+ struct dmabuf *db = &s->dma_dac;
+ unsigned long flags;
+ u32 temp;
+
+ spin_lock_irqsave(&s->lock, flags);
+
+ if (db->stopped) {
+ spin_unlock_irqrestore(&s->lock, flags);
+ return;
+ }
+
+ /* deactivate the dma */
+ outl(0, s->io + vr5701_DAC1_CTRL);
+ outl(0, s->io + vr5701_DAC2_CTRL);
+
+ /* wait for DAM completely stop */
+ while (inl(s->io + vr5701_DAC1_CTRL) & vr5701_DMA_WIP) ;
+ while (inl(s->io + vr5701_DAC2_CTRL) & vr5701_DMA_WIP) ;
+
+ /* disable dac slots in aclink */
+ temp = inl(s->io + vr5701_CTRL);
+ temp &= ~(vr5701_CTRL_DAC1ENB | vr5701_CTRL_DAC2ENB);
+ outl(temp, s->io + vr5701_CTRL);
+
+ /* disable interrupts */
+ temp = inl(s->io + vr5701_INT_MASK);
+ temp &= ~(vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END);
+ outl(temp, s->io + vr5701_INT_MASK);
+
+ /* clear pending ones */
+ outl(vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END,
+ s->io + vr5701_INT_CLR);
+
+ db->stopped = 1;
+
+ spin_unlock_irqrestore(&s->lock, flags);
+}
+
+static inline void stop_adc(struct vr5701_ac97_state *s)
+{
+ struct dmabuf *db = &s->dma_adc;
+ unsigned long flags;
+ u32 temp;
+
+ spin_lock_irqsave(&s->lock, flags);
+
+ if (db->stopped) {
+ spin_unlock_irqrestore(&s->lock, flags);
+ return;
+ }
+
+ /* deactivate the dma */
+ outl(0, s->io + vr5701_ADC1_CTRL);
+ outl(0, s->io + vr5701_ADC2_CTRL);
+
+ /* disable adc slots in aclink */
+ temp = inl(s->io + vr5701_CTRL);
+ temp &= ~(vr5701_CTRL_ADC1ENB | vr5701_CTRL_ADC2ENB);
+ outl(temp, s->io + vr5701_CTRL);
+
+ /* disable interrupts */
+ temp = inl(s->io + vr5701_INT_MASK);
+ temp &= ~(vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END);
+ outl(temp, s->io + vr5701_INT_MASK);
+
+ /* clear pending ones */
+ outl(vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END,
+ s->io + vr5701_INT_CLR);
+
+ db->stopped = 1;
+
+ spin_unlock_irqrestore(&s->lock, flags);
+}
+
+static inline void dealloc_dmabuf(struct vr5701_ac97_state *s,
+ struct dmabuf *db)
+{
+ if (db->lbuf) {
+ ASSERT(db->rbuf);
+ pci_free_consistent(s->dev, PAGE_SIZE << db->bufOrder,
+ db->lbuf, db->lbufDma);
+ pci_free_consistent(s->dev, PAGE_SIZE << db->bufOrder,
+ db->rbuf, db->rbufDma);
+ db->lbuf = db->rbuf = NULL;
+ }
+ db->nextIn = db->nextOut = 0;
+ db->ready = 0;
+}
+
+static inline int prog_dmabuf_adc(struct vr5701_ac97_state *s)
+{
+ stop_adc(s);
+ return prog_dmabuf(s, &s->dma_adc, s->adcRate);
+}
+
+static inline int prog_dmabuf_dac(struct vr5701_ac97_state *s)
+{
+ stop_dac(s);
+ return prog_dmabuf(s, &s->dma_dac, s->dacRate);
+}
+
+static inline void vr5701_ac97_adc_interrupt(struct vr5701_ac97_state *s)
+{
+ struct dmabuf *adc = &s->dma_adc;
+ unsigned temp;
+
+ /* we need two frags avaiable because one is already being used
+ * and the other will be used when next interrupt happens.
+ */
+ if (adc->count >= adc->fragTotalSize - adc->fragSize) {
+ stop_adc(s);
+ adc->error++;
+ printk(KERN_INFO PFX "adc overrun\n");
+ return;
+ }
+
+ /* set the base addr for next DMA transfer */
+ temp = adc->nextIn + 2 * adc->fragSize;
+ if (temp >= adc->fragTotalSize) {
+ ASSERT((temp == adc->fragTotalSize) ||
+ (temp == adc->fragTotalSize + adc->fragSize));
+ temp -= adc->fragTotalSize;
+ }
+ outl(adc->lbufDma + temp, s->io + vr5701_ADC1_BADDR);
+ outl(adc->rbufDma + temp, s->io + vr5701_ADC2_BADDR);
+
+ /* adjust nextIn */
+ adc->nextIn += adc->fragSize;
+ if (adc->nextIn >= adc->fragTotalSize) {
+ ASSERT(adc->nextIn == adc->fragTotalSize);
+ adc->nextIn = 0;
+ }
+
+ /* adjust count */
+ adc->count += adc->fragSize;
+
+ /* wake up anybody listening */
+ if (waitqueue_active(&adc->wait)) {
+ wake_up_interruptible(&adc->wait);
+ }
+}
+
+static inline void vr5701_ac97_dac_interrupt(struct vr5701_ac97_state *s)
+{
+ struct dmabuf *dac = &s->dma_dac;
+ unsigned temp;
+
+ /* let us set for next next DMA transfer */
+ temp = dac->nextOut + dac->fragSize * 2;
+ if (temp >= dac->fragTotalSize) {
+ ASSERT((temp == dac->fragTotalSize) ||
+ (temp == dac->fragTotalSize + dac->fragSize));
+ temp -= dac->fragTotalSize;
+ }
+ outl(dac->lbufDma + temp, s->io + vr5701_DAC1_BADDR);
+ if (s->dacChannels == 1) {
+ outl(dac->lbufDma + temp, s->io + vr5701_DAC2_BADDR);
+ } else {
+ outl(dac->rbufDma + temp, s->io + vr5701_DAC2_BADDR);
+ }
+
+#if defined(vr5701_AC97_VERBOSE_DEBUG)
+ if (*(u16 *) (dac->lbuf + dac->nextOut) != outTicket) {
+ printk(KERN_ERR "assert fail: - %d vs %d\n",
+ *(u16 *) (dac->lbuf + dac->nextOut), outTicket);
+ ASSERT(1 == 0);
+ }
+#endif
+
+ /* adjust nextOut pointer */
+ dac->nextOut += dac->fragSize;
+ if (dac->nextOut >= dac->fragTotalSize) {
+ ASSERT(dac->nextOut == dac->fragTotalSize);
+ dac->nextOut = 0;
+ }
+
+ /* adjust count */
+ dac->count -= dac->fragSize;
+ if (dac->count <= 0) {
+ /* buffer under run */
+ dac->count = 0;
+ dac->nextIn = dac->nextOut;
+ stop_dac(s);
+ }
+#if defined(vr5701_AC97_VERBOSE_DEBUG)
+ if (dac->count) {
+ outTicket++;
+ ASSERT(*(u16 *) (dac->lbuf + dac->nextOut) == outTicket);
+ }
+#endif
+
+ /* we cannot have both under run and someone is waiting on us */
+ ASSERT(!(waitqueue_active(&dac->wait) && (dac->count <= 0)));
+
+ /* wake up anybody listening */
+ if (waitqueue_active(&dac->wait))
+ wake_up_interruptible(&dac->wait);
+}
+
+static inline int
+copy_two_channel_adc_to_user(struct vr5701_ac97_state *s,
+ char *buffer, int copyCount)
+{
+ struct dmabuf *db = &s->dma_adc;
+ int bufStart = db->nextOut;
+ for (; copyCount > 0;) {
+ int i;
+ int count = copyCount;
+ if (count > WORK_BUF_SIZE / 2)
+ count = WORK_BUF_SIZE / 2;
+ for (i = 0; i < count / 2; i++) {
+ s->workBuf[i].lchannel =
+ *(u16 *) (db->lbuf + bufStart + i * 2);
+ s->workBuf[i].rchannel =
+ *(u16 *) (db->rbuf + bufStart + i * 2);
+ }
+ if (copy_to_user(buffer, s->workBuf, count * 2)) {
+ return -1;
+ }
+
+ copyCount -= count;
+ bufStart += count;
+ ASSERT(bufStart <= db->fragTotalSize);
+ buffer += count * 2;
+ }
+ return 0;
+}
+
+/* return the total bytes that is copied */
+static inline int
+copy_adc_to_user(struct vr5701_ac97_state *s,
+ char *buffer, size_t count, int avail)
+{
+ struct dmabuf *db = &s->dma_adc;
+ int copyCount = 0;
+ int copyFragCount = 0;
+ int totalCopyCount = 0;
+ int totalCopyFragCount = 0;
+ unsigned long flags;
+
+ /* adjust count to signel channel byte count */
+ count >>= s->adcChannels - 1;
+
+ /* we may have to "copy" twice as ring buffer wraps around */
+ for (; (avail > 0) && (count > 0);) {
+ /* determine max possible copy count for single channel */
+ copyCount = count;
+ if (copyCount > avail) {
+ copyCount = avail;
+ }
+ if (copyCount + db->nextOut > db->fragTotalSize) {
+ copyCount = db->fragTotalSize - db->nextOut;
+ ASSERT((copyCount % db->fragSize) == 0);
+ }
+
+ copyFragCount = (copyCount - 1) >> db->fragShift;
+ copyFragCount = (copyFragCount + 1) << db->fragShift;
+ ASSERT(copyFragCount >= copyCount);
+
+ /* we copy differently based on adc channels */
+ if (s->adcChannels == 1) {
+ if (copy_to_user(buffer,
+ db->lbuf + db->nextOut, copyCount))
+ return -1;
+ } else {
+ /* *sigh* we have to mix two streams into one */
+ if (copy_two_channel_adc_to_user(s, buffer, copyCount))
+ return -1;
+ }
+
+ count -= copyCount;
+ totalCopyCount += copyCount;
+ avail -= copyFragCount;
+ totalCopyFragCount += copyFragCount;
+
+ buffer += copyCount << (s->adcChannels - 1);
+
+ db->nextOut += copyFragCount;
+ if (db->nextOut >= db->fragTotalSize) {
+ ASSERT(db->nextOut == db->fragTotalSize);
+ db->nextOut = 0;
+ }
+
+ ASSERT((copyFragCount % db->fragSize) == 0);
+ ASSERT((count == 0) || (copyCount == copyFragCount));
+ }
+
+ spin_lock_irqsave(&s->lock, flags);
+ db->count -= totalCopyFragCount;
+ spin_unlock_irqrestore(&s->lock, flags);
+
+ return totalCopyCount << (s->adcChannels - 1);
+}
+
+static inline int
+copy_two_channel_dac_from_user(struct vr5701_ac97_state *s,
+ const char *buffer, int copyCount)
+{
+ struct dmabuf *db = &s->dma_dac;
+ int bufStart = db->nextIn;
+
+ ASSERT(db->ready);
+
+ for (; copyCount > 0;) {
+ int i;
+ int count = copyCount;
+ if (count > WORK_BUF_SIZE / 2)
+ count = WORK_BUF_SIZE / 2;
+ if (copy_from_user(s->workBuf, buffer, count * 2)) {
+ return -1;
+ }
+ for (i = 0; i < count / 2; i++) {
+ *(u16 *) (db->lbuf + bufStart + i * 2) =
+ s->workBuf[i].lchannel;
+ *(u16 *) (db->rbuf + bufStart + i * 2) =
+ s->workBuf[i].rchannel;
+ }
+
+ copyCount -= count;
+ bufStart += count;
+ ASSERT(bufStart <= db->fragTotalSize);
+ buffer += count * 2;
+ }
+ return 0;
+
+}
Index: linux-2.6.10/sound/oss/Makefile
===================================================================
--- linux-2.6.10.orig/sound/oss/Makefile
+++ linux-2.6.10/sound/oss/Makefile
@@ -67,6 +67,7 @@ endif
obj-$(CONFIG_SOUND_ES1370) += es1370.o
obj-$(CONFIG_SOUND_ES1371) += es1371.o ac97_codec.o
obj-$(CONFIG_SOUND_VRC5477) += nec_vrc5477.o ac97_codec.o
+obj-$(CONFIG_SOUND_VR5701) += nec_vr5701_sg2.o ac97_codec.o
obj-$(CONFIG_SOUND_AU1000) += au1000.o ac97_codec.o
obj-$(CONFIG_SOUND_AU1550_AC97) += au1550_ac97.o ac97_codec.o
obj-$(CONFIG_SOUND_ESSSOLO1) += esssolo1.o
Index: linux-2.6.10/arch/mips/configs/nec_vr5701_defconfig
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/configs/nec_vr5701_defconfig
@@ -0,0 +1,1250 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.10_dev
+# Thu Aug 4 14:29:56 2005
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SEMMNI=128
+CONFIG_SYSVIPC_SEMMSL=250
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_BOOT_FLIGHT_RECORDER is not set
+CONFIG_LOCKLESS=y
+CONFIG_BOOT_FLIGHT_BUFFERS=4
+CONFIG_BOOT_FLIGHT_SIZE=524288
+CONFIG_FLIGHT_PROC_BUFFERS=8
+CONFIG_FLIGHT_PROC_SIZE=8192
+CONFIG_NEWEV=y
+CONFIG_CSTM=y
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+CONFIG_TCUBE=y
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT_DESKTOP=y
+# CONFIG_PREEMPT_RT is not set
+CONFIG_PREEMPT=y
+# CONFIG_PREEMPT_SOFTIRQS is not set
+# CONFIG_PREEMPT_HARDIRQS is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_SPINLOCK_BKL is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_ASM_SEMAPHORES=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+CONFIG_CPU_R5500=y
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_ADVANCED=y
+CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_LLDSCD is not set
+# CONFIG_CPU_HAS_WB is not set
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_HIGH_RES_RESOLUTION=10000
+CONFIG_CPU_TIMER=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CONCAT=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+CONFIG_MTD_ROM=y
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x1C000000
+CONFIG_MTD_PHYSMAP_LEN=0x01a00000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_NEC_VR5701_SG2=y
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_CHR_DEV_OSST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_ADP94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_USE_POLICY_FWD=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_ADVANCED_ROUTER is not set
+# CONFIG_IPV6_MIP6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_IP6_NF_QUEUE is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+# CONFIG_IP6_NF_CONNTRACK is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_E100_NAPI is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_TSLIBDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_BLOCKER is not set
+CONFIG_GEN_RTC=y
+CONFIG_GEN_RTC_X=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+CONFIG_FB_SM=y
+# CONFIG_DISPLAY_640x480 is not set
+CONFIG_DISPLAY_1024x768=y
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_E1356 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_SEQUENCER=y
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# PCI devices
+#
+CONFIG_SND_AC97_CODEC=y
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_TRIDENT is not set
+CONFIG_SND_VR5701=y
+# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VX222 is not set
+
+#
+# ALSA MIPS devices
+#
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_USX2Y is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_MIDI is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_RW_DETECT=y
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB ATM/DSL drivers
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Synchronous Serial Interfaces (SSI)
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+CONFIG_JBD_DEBUG=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+CONFIG_JFS_FS=y
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_XFS_FS=m
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS_FS=y
+CONFIG_JFFS_FS_VERBOSE=0
+CONFIG_JFFS_PROC_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_NAND=y
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# CONFIG_CRAMFS_LINEAR is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_YAFFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_CODEPAGE_852=y
+CONFIG_NLS_CODEPAGE_855=y
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+CONFIG_NLS_ISO8859_3=y
+CONFIG_NLS_ISO8859_4=y
+CONFIG_NLS_ISO8859_5=y
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# MontaVista System tools
+#
+# CONFIG_ILATENCY is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_WAKEUP_TIMING is not set
+# CONFIG_CRITICAL_PREEMPT_TIMING is not set
+# CONFIG_CRITICAL_IRQSOFF_TIMING is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs rw "
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+
+#
+# Fast Real-Time Domain
+#
+
+#
+# Fast Real-Time Domain Advanced Options
+#
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
Index: linux-2.6.10/sound/pci/Makefile
===================================================================
--- linux-2.6.10.orig/sound/pci/Makefile
+++ linux-2.6.10/sound/pci/Makefile
@@ -57,4 +57,5 @@ obj-$(CONFIG_SND) += \
rme9652/ \
trident/ \
ymfpci/ \
+ vr5701/ \
vx222/
Index: linux-2.6.10/sound/pci/Kconfig
===================================================================
--- linux-2.6.10.orig/sound/pci/Kconfig
+++ linux-2.6.10/sound/pci/Kconfig
@@ -262,6 +262,16 @@ config SND_TRIDENT
To compile this driver as a module, choose M here: the module
will be called snd-trident.
+config SND_VR5701
+ tristate "NEC VR5701-SG2 Audio"
+ depends on SND
+ select SND_AC97_CODEC
+ help
+ Say Y here to include support for NEC VR5701-SG2 Audio.
+
+ To compile this driver as a module, choose M here: the module
+ will be called nec_vr5701_sg2.
+
config SND_YMFPCI
tristate "Yamaha YMF724/740/744/754"
depends on SND
Index: linux-2.6.10/sound/pci/vr5701/nec_vr5701_sg2.c
===================================================================
--- /dev/null
+++ linux-2.6.10/sound/pci/vr5701/nec_vr5701_sg2.c
@@ -0,0 +1,795 @@
+/*
+ * sound/pci/vr5701/nec_vr5701_sg2.c
+ *
+ * An ALSA sound driver for
+ * NEC Electronics Corporation VR5701 SolutionGearII.
+ * It works with AC97 codec.
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include "nec_vr5701_sg2.h"
+
+static unsigned short snd_vr5701_ac97_read(ac97_t *ac97,
+ unsigned short reg)
+{
+ vr5701_t *chip = ac97->private_data;
+ u32 the_register_value;
+
+ /* wait until we can access codec registers */
+ while (inl(chip->port + vr5701_CODEC_WR) & 0x80000000) ;
+
+ /* write the address and "read" command to codec */
+ reg = reg & 0x7f;
+ outl((reg << 16) | vr5701_CODEC_WR_RWC, chip->port + vr5701_CODEC_WR);
+
+ /* get the return result */
+ udelay(100); /* workaround hardware bug */
+ while ((the_register_value = inl(chip->port + vr5701_CODEC_RD)) &
+ (vr5701_CODEC_RD_RRDYA | vr5701_CODEC_RD_RRDYD)) {
+ /* we get either addr or data, or both */
+ if (the_register_value & vr5701_CODEC_RD_RRDYD) {
+ break;
+ }
+ }
+
+ return the_register_value & 0xffff;
+}
+
+static void snd_vr5701_ac97_write(ac97_t *ac97,
+ unsigned short reg, unsigned short val)
+{
+ vr5701_t *chip = ac97->private_data;
+
+ /* wait until we can access codec registers */
+ while (inl(chip->port + vr5701_CODEC_WR) & 0x80000000) ;
+
+ /* write the address and value to codec */
+ outl((reg << 16) | val, chip->port + vr5701_CODEC_WR);
+}
+
+static void snd_vr5701_ac97_reset(ac97_t *ac97)
+{
+ vr5701_t *chip = ac97->private_data;
+ outl(vr5701_ACLINK_CTRL_RST_ON | vr5701_ACLINK_CTRL_RST_TIME,
+ chip->port + vr5701_ACLINK_CTRL);
+ while (inl(chip->port + vr5701_ACLINK_CTRL) & vr5701_ACLINK_CTRL_RST_ON) ;
+ return;
+}
+
+static void snd_vr5701_ac97_wait(ac97_t *ac97)
+{
+ vr5701_t *chip = ac97->private_data;
+
+ /* wait until we can access codec registers */
+ while (inl(chip->port + vr5701_CODEC_WR) & 0x80000000) ;
+}
+
+static int snd_vr5701_ac97(vr5701_t *chip)
+{
+ ac97_bus_t *bus;
+ ac97_template_t ac97;
+ int err;
+ static ac97_bus_ops_t ops = {
+ .write = snd_vr5701_ac97_write,
+ .read = snd_vr5701_ac97_read,
+ .reset = snd_vr5701_ac97_reset,
+ .wait = snd_vr5701_ac97_wait,
+ };
+
+ if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus)) < 0)
+ return err;
+ memset(&ac97, 0, sizeof(ac97));
+ ac97.private_data = chip;
+ return snd_ac97_mixer(bus, &ac97, &chip->ac97);
+}
+
+/* open callback */
+static int snd_vr5701_playback_open(snd_pcm_substream_t *substream)
+{
+ vr5701_t *chip = snd_pcm_substream_chip(substream);
+ chip->substream[PLAYBACK] = substream;
+ substream->runtime->hw = snd_vr5701_playback_hw;
+ chip->next_playback = 0;
+
+ return (snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0);
+}
+
+
+/* open callback */
+static int snd_vr5701_capture_open(snd_pcm_substream_t *substream)
+{
+ vr5701_t *chip = snd_pcm_substream_chip(substream);
+ chip->substream[CAPTURE] = substream;
+ substream->runtime->hw = snd_vr5701_capture_hw;
+ chip->next_capture = 0;
+
+ return (snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0);
+}
+
+/* hw_params callback */
+static int snd_vr5701_pcm_hw_params(snd_pcm_substream_t *substream,
+ snd_pcm_hw_params_t * hw_params)
+{
+ return snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+}
+
+/* hw_free callback */
+static int snd_vr5701_pcm_hw_free(snd_pcm_substream_t *substream)
+{
+ return snd_pcm_lib_free_pages(substream);
+}
+
+/* playback prepare callback */
+static int snd_vr5701_pcm_prepare_playback(snd_pcm_substream_t *substream)
+{
+ vr5701_t *chip = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, runtime->rate);
+ return 0;
+}
+
+/* capture prepare callback */
+static int snd_vr5701_pcm_prepare_capture(snd_pcm_substream_t *substream)
+{
+ vr5701_t *chip = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ snd_ac97_set_rate(chip->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);
+ return 0;
+}
+
+static void vr5701_dma_stop_playback(snd_pcm_substream_t *substream)
+{
+ u32 temp;
+ vr5701_t *chip = snd_pcm_substream_chip(substream);
+ chip->next_playback = 0;
+
+ /* deactivate the dma */
+ outl(0, chip->port + vr5701_DAC1_CTRL);
+ outl(0, chip->port + vr5701_DAC2_CTRL);
+
+ /* wait for DMA completely stop */
+ while (inl(chip->port + vr5701_DAC1_CTRL) & vr5701_DMA_WIP);
+ while (inl(chip->port + vr5701_DAC2_CTRL) & vr5701_DMA_WIP);
+
+ /* disable dac slots in aclink */
+ temp = inl(chip->port + vr5701_CTRL);
+ temp &= ~(vr5701_CTRL_DAC1ENB | vr5701_CTRL_DAC2ENB);
+ outl(temp, chip->port + vr5701_CTRL);
+
+ /* disable interrupts */
+ temp = inl(chip->port + vr5701_INT_MASK);
+ temp &= ~(vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END);
+ outl(temp, chip->port + vr5701_INT_MASK);
+
+ /* clear pending ones */
+ outl(vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END,
+ chip->port + vr5701_INT_CLR);
+
+}
+
+/* close callback */
+static int snd_vr5701_playback_close(snd_pcm_substream_t *substream)
+{
+ vr5701_dma_stop_playback(substream);
+ return 0;
+}
+
+static void vr5701_dma_stop_capture(snd_pcm_substream_t *substream)
+{
+ u32 temp;
+ vr5701_t *chip = snd_pcm_substream_chip(substream);
+ chip->next_capture = 0;
+
+ /* deactivate the dma */
+ outl(0, chip->port + vr5701_ADC1_CTRL);
+ outl(0, chip->port + vr5701_ADC2_CTRL);
+
+ /* disable dac slots in aclink */
+ temp = inl(chip->port + vr5701_CTRL);
+ temp &= ~(vr5701_CTRL_ADC1ENB | vr5701_CTRL_ADC2ENB);
+ outl(temp, chip->port + vr5701_CTRL);
+
+ /* disable interrupts */
+ temp = inl(chip->port + vr5701_INT_MASK);
+ temp &= ~(vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END);
+ outl(temp, chip->port + vr5701_INT_MASK);
+
+ /* clear pending ones */
+ outl(vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END,
+ chip->port + vr5701_INT_CLR);
+}
+
+/* close callback */
+static int snd_vr5701_capture_close(snd_pcm_substream_t *substream)
+{
+ vr5701_dma_stop_capture(substream);
+ return 0;
+}
+
+static void vr5701_dma_start_playback(snd_pcm_substream_t *substream)
+{
+ u32 temp;
+ vr5701_t *chip = snd_pcm_substream_chip(substream);
+ unsigned long period_size;
+
+ /* clear pending fales interrupts */
+ outl(vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END,
+ chip->port + vr5701_INT_CLR);
+
+ /* enable interrupts */
+ temp = inl(chip->port + vr5701_INT_MASK);
+ temp |= vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END;
+ outl(temp, chip->port + vr5701_INT_MASK);
+
+ /* setup dma base addr */
+ if (substream->runtime->channels == 1) {
+ outl(substream->runtime->dma_addr + chip->next_playback,
+ chip->port + vr5701_DAC1_BADDR);
+ outl(substream->runtime->dma_addr + chip->next_playback,
+ chip->port + vr5701_DAC2_BADDR);
+ } else {
+ outl(substream->runtime->dma_addr + chip->next_playback,
+ chip->port + vr5701_DAC1_BADDR);
+ outl(substream->runtime->dma_addr + substream->runtime->dma_bytes/2
+ + chip->next_playback, chip->port + vr5701_DAC2_BADDR);
+ }
+
+ /* set dma length, in the unit of 0x10 bytes */
+ period_size = (frames_to_bytes(substream->runtime,
+ substream->runtime->period_size)) >> 4;
+ outl(period_size, chip->port + vr5701_DAC1L);
+ outl(period_size, chip->port + vr5701_DAC2L);
+
+ /* activate dma */
+ outl(vr5701_DMA_ACTIVATION, chip->port + vr5701_DAC1_CTRL);
+ outl(vr5701_DMA_ACTIVATION, chip->port + vr5701_DAC2_CTRL);
+
+ /* enable dac slots - we should hear the music now! */
+ temp = inl(chip->port + vr5701_CTRL);
+ temp |= (vr5701_CTRL_DAC1ENB | vr5701_CTRL_DAC2ENB);
+ outl(temp, chip->port + vr5701_CTRL);
+
+ /* it is time to setup next dma transfer */
+ temp = chip->next_playback + frames_to_bytes(substream->runtime,
+ substream->runtime->period_size);
+
+ if (substream->runtime->channels == 1) {
+ if (temp >= substream->runtime->dma_bytes) {
+ temp = 0;
+ }
+ outl(substream->runtime->dma_addr + temp,
+ chip->port + vr5701_DAC1_BADDR);
+ outl(substream->runtime->dma_addr + temp,
+ chip->port + vr5701_DAC2_BADDR);
+ } else {
+ if (temp >= substream->runtime->dma_bytes/2) {
+ temp = 0;
+ }
+ outl(substream->runtime->dma_addr + temp,
+ chip->port + vr5701_DAC1_BADDR);
+ outl(substream->runtime->dma_addr + substream->runtime->dma_bytes/2
+ + temp, chip->port + vr5701_DAC2_BADDR);
+ }
+ return ;
+}
+
+static void vr5701_dma_start_capture(snd_pcm_substream_t *substream)
+{
+ u32 temp;
+ vr5701_t *chip = snd_pcm_substream_chip(substream);
+ unsigned long period_size;
+
+ /* clear pending fales interrupts */
+ outl(vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END,
+ chip->port + vr5701_INT_CLR);
+
+ /* enable interrupts */
+ temp = inl(chip->port + vr5701_INT_MASK);
+ temp |= vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END;
+ outl(temp, chip->port + vr5701_INT_MASK);
+
+ /* setup dma base addr */
+ if (substream->runtime->channels == 1) {
+ outl(substream->runtime->dma_addr + chip->next_capture,
+ chip->port + vr5701_ADC1_BADDR);
+ } else {
+ outl(substream->runtime->dma_addr+ chip->next_capture,
+ chip->port + vr5701_ADC1_BADDR);
+ outl(substream->runtime->dma_addr + substream->runtime->dma_bytes/2
+ + chip->next_capture, chip->port + vr5701_ADC2_BADDR);
+ }
+
+ /* set dma length, in the unit of 0x10 bytes */
+ period_size = (frames_to_bytes(substream->runtime,
+ substream->runtime->period_size)) >> 4;
+ if (substream->runtime->channels == 1) {
+ outl(period_size, chip->port + vr5701_ADC1L);
+ } else {
+ outl(period_size, chip->port + vr5701_ADC1L);
+ outl(period_size, chip->port + vr5701_ADC2L);
+ }
+
+ /* activate dma */
+ if (substream->runtime->channels == 1) {
+ outl(vr5701_DMA_ACTIVATION, chip->port + vr5701_ADC1_CTRL);
+ } else {
+ outl(vr5701_DMA_ACTIVATION, chip->port + vr5701_ADC1_CTRL);
+ outl(vr5701_DMA_ACTIVATION, chip->port + vr5701_ADC2_CTRL);
+ }
+
+ /* enable adc slots */
+ temp = inl(chip->port + vr5701_CTRL);
+ temp |= (vr5701_CTRL_ADC1ENB | vr5701_CTRL_ADC2ENB);
+ outl(temp, chip->port + vr5701_CTRL);
+
+ /* it is time to setup next dma transfer */
+ temp = chip->next_capture + frames_to_bytes(substream->runtime,
+ substream->runtime->period_size);
+ if (substream->runtime->channels == 1) {
+ if (temp >= substream->runtime->dma_bytes) {
+ temp = 0;
+ }
+ outl(substream->runtime->dma_addr + temp,
+ chip->port + vr5701_ADC1_BADDR);
+ } else {
+ if (temp >= substream->runtime->dma_bytes/2) {
+ temp = 0;
+ }
+ outl(substream->runtime->dma_addr + temp,
+ chip->port + vr5701_ADC1_BADDR);
+ outl(substream->runtime->dma_addr + substream->runtime->dma_bytes/2
+ + temp, chip->port + vr5701_ADC2_BADDR);
+ }
+ return ;
+}
+
+/* trigger callback */
+static int snd_vr5701_pcm_trigger(snd_pcm_substream_t *substream,
+ int cmd)
+{
+ int err = 0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ if (substream->stream) {
+ vr5701_dma_start_capture(substream);
+ }
+ else {
+ vr5701_dma_start_playback(substream);
+ }
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ if (substream->stream)
+ vr5701_dma_stop_capture(substream);
+ else
+ vr5701_dma_stop_playback(substream);
+ break;
+ default:
+ err = -EINVAL;
+ printk(KERN_WARNING
+ "vr5701_ac97 : wrong trigger callback!!!\n");
+ break;
+ }
+ return err;
+}
+
+/* playback pointer callback */
+static snd_pcm_uframes_t
+snd_vr5701_pcm_pointer_playback(snd_pcm_substream_t *substream)
+{
+ vr5701_t *chip = snd_pcm_substream_chip(substream);
+ return bytes_to_frames(substream->runtime,
+ chip->next_playback);
+}
+
+/* capture pointer callback */
+static snd_pcm_uframes_t
+snd_vr5701_pcm_pointer_capture(snd_pcm_substream_t *substream)
+{
+ vr5701_t *chip = snd_pcm_substream_chip(substream);
+ return bytes_to_frames(substream->runtime,
+ chip->next_capture);
+}
+/* operators */
+static snd_pcm_ops_t snd_vr5701_playback_ops = {
+ .open = snd_vr5701_playback_open,
+ .close = snd_vr5701_playback_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_vr5701_pcm_hw_params,
+ .hw_free = snd_vr5701_pcm_hw_free,
+ .prepare = snd_vr5701_pcm_prepare_playback,
+ .trigger = snd_vr5701_pcm_trigger,
+ .pointer = snd_vr5701_pcm_pointer_playback,
+};
+
+/* operators */
+static snd_pcm_ops_t snd_vr5701_capture_ops = {
+ .open = snd_vr5701_capture_open,
+ .close = snd_vr5701_capture_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_vr5701_pcm_hw_params,
+ .hw_free = snd_vr5701_pcm_hw_free,
+ .prepare = snd_vr5701_pcm_prepare_capture,
+ .trigger = snd_vr5701_pcm_trigger,
+ .pointer = snd_vr5701_pcm_pointer_capture,
+};
+
+/* create a pcm device */
+static int __devinit snd_vr5701_new_pcm(vr5701_t *chip)
+{
+ snd_pcm_t *pcm;
+ int err;
+ if ((err = snd_pcm_new(chip->card, vr5701_AC97_MODULE_NAME, 0, 1, 1,
+ &pcm)) < 0)
+ return err;
+ pcm->private_data = chip;
+ strcpy(pcm->name, vr5701_AC97_MODULE_NAME);
+ chip->pcm = pcm;
+
+ /* set operators */
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ &snd_vr5701_playback_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ &snd_vr5701_capture_ops);
+
+ /* pre-allocation of buffers */
+ /* NOTE: this may fail */
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci), 64*1024, 64*1024);
+ return 0;
+}
+
+/* chip-specific destructor
+ */
+static int snd_vr5701_free(vr5701_t *chip)
+{
+ /* release the irq */
+ if (chip->irq >= 0)
+ free_irq(chip->irq, (void *)chip);
+
+ /* release the i/o ports & memory */
+ pci_release_regions(chip->pci);
+
+ /* disable the PCI entry */
+ pci_disable_device(chip->pci);
+
+ /* release the data */
+ kfree(chip);
+ return 0;
+}
+
+/* component-destructor
+ */
+static int snd_vr5701_dev_free(snd_device_t *device)
+{
+ vr5701_t *chip = device->device_data;
+ return snd_vr5701_free(chip);
+}
+static void vr5701_ac97_adc_interrupt(struct snd_vr5701 *chip)
+{
+ unsigned temp;
+
+ /* set the base addr for next DMA transfer */
+ temp = chip->next_capture + 2*(frames_to_bytes(chip->substream[CAPTURE]->runtime,
+ chip->substream[CAPTURE]->runtime->period_size));
+ if (chip->substream[CAPTURE]->runtime->channels == 1) {
+ if (temp >= chip->substream[CAPTURE]->runtime->dma_bytes) {
+ temp -= chip->substream[CAPTURE]->runtime->dma_bytes;
+ }
+ } else {
+ if (temp >= chip->substream[CAPTURE]->runtime->dma_bytes/2) {
+ temp -= chip->substream[CAPTURE]->runtime->dma_bytes/2;
+ }
+ }
+
+ if (chip->substream[CAPTURE]->runtime->channels == 1) {
+ outl(chip->substream[CAPTURE]->runtime->dma_addr
+ + temp, chip->port + vr5701_ADC1_BADDR);
+ } else {
+ outl(chip->substream[CAPTURE]->runtime->dma_addr
+ + temp, chip->port + vr5701_ADC1_BADDR);
+ outl(chip->substream[CAPTURE]->runtime->dma_addr
+ + chip->substream[CAPTURE]->runtime->dma_bytes/2+ temp,
+ chip->port + vr5701_ADC2_BADDR);
+ }
+
+ /* adjust next pointer */
+ chip->next_capture += frames_to_bytes(chip->substream[CAPTURE]->runtime,
+ chip->substream[CAPTURE]->runtime->period_size);
+ if (chip->substream[CAPTURE]->runtime->channels == 1) {
+ if (chip->next_capture >= chip->substream[CAPTURE]->runtime->dma_bytes){
+ chip->next_capture = 0;
+ }
+ } else {
+ if (chip->next_capture >= chip->substream[CAPTURE]->runtime->dma_bytes/2){
+ chip->next_capture = 0;
+ }
+ }
+}
+
+static void vr5701_ac97_dac_interrupt(struct snd_vr5701 *chip)
+{
+ unsigned temp;
+
+ /* let us set for next next DMA transfer */
+ temp = chip->next_playback + 2*(frames_to_bytes(chip->substream[PLAYBACK]->runtime,
+ chip->substream[PLAYBACK]->runtime->period_size));
+ if (chip->substream[PLAYBACK]->runtime->channels == 1) {
+ if (temp >= chip->substream[PLAYBACK]->runtime->dma_bytes) {
+ temp -= chip->substream[PLAYBACK]->runtime->dma_bytes;
+ }
+ } else {
+ if (temp >= chip->substream[PLAYBACK]->runtime->dma_bytes/2) {
+ temp -= chip->substream[PLAYBACK]->runtime->dma_bytes/2;
+ }
+ }
+
+ if (chip->substream[PLAYBACK]->runtime->channels == 1) {
+ outl(chip->substream[PLAYBACK]->runtime->dma_addr
+ + temp, chip->port + vr5701_DAC1_BADDR);
+ outl(chip->substream[PLAYBACK]->runtime->dma_addr
+ + temp, chip->port + vr5701_DAC2_BADDR);
+ } else {
+ outl(chip->substream[PLAYBACK]->runtime->dma_addr
+ + temp, chip->port + vr5701_DAC1_BADDR);
+ outl(chip->substream[PLAYBACK]->runtime->dma_addr
+ + chip->substream[PLAYBACK]->runtime->dma_bytes/2
+ + temp, chip->port + vr5701_DAC2_BADDR);
+ }
+
+ /* adjust next pointer */
+ chip->next_playback += frames_to_bytes(chip->substream[PLAYBACK]->runtime,
+ chip->substream[PLAYBACK]->runtime->period_size);
+ if (chip->substream[PLAYBACK]->runtime->channels == 1) {
+ if (chip->next_playback >= chip->substream[PLAYBACK]->runtime->dma_bytes){
+ chip->next_playback = 0;
+ }
+ } else {
+ if (chip->next_playback >= chip->substream[PLAYBACK]->runtime->dma_bytes/2){
+ chip->next_playback = 0;
+ }
+ }
+}
+static irqreturn_t snd_vr5701_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ vr5701_t *chip = dev_id;
+ u32 irqStatus;
+ u32 adcInterrupts, dacInterrupts;
+
+ /* get irqStatus and clear the detected ones */
+ irqStatus = inl(chip->port + vr5701_INT_STATUS);
+ outl(irqStatus, chip->port + vr5701_INT_CLR);
+
+ /* let us see what we get */
+ dacInterrupts = vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END;
+ adcInterrupts = vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END;
+ if (irqStatus & dacInterrupts) {
+ /* we should get both interrupts */
+ if (irqStatus & vr5701_INT_MASK_DAC1END) {
+ vr5701_ac97_dac_interrupt(chip);
+ }
+ if ((irqStatus & dacInterrupts) != dacInterrupts) {
+ printk(KERN_WARNING
+ "vr5701_ac97 : playback interrupts not in sync!!!\n");
+ vr5701_dma_stop_playback(chip->substream[PLAYBACK]);
+ vr5701_dma_start_playback(chip->substream[PLAYBACK]);
+ }
+ snd_pcm_period_elapsed(chip->substream[PLAYBACK]);
+ } else if (irqStatus & adcInterrupts) {
+ /* we should get both interrupts, but just in stereo case */
+ if (irqStatus & vr5701_INT_MASK_ADC1END) {
+ vr5701_ac97_adc_interrupt(chip);
+ }
+ if (((irqStatus & adcInterrupts) != adcInterrupts)
+ &&(chip->substream[CAPTURE]->runtime->channels == 2)) {
+ printk(KERN_WARNING
+ "vr5701_ac97 : capture interrupts not in sync!!!\n");
+ vr5701_dma_stop_capture(chip->substream[CAPTURE]);
+ vr5701_dma_start_capture(chip->substream[CAPTURE]);
+ }
+ snd_pcm_period_elapsed(chip->substream[CAPTURE]);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/* chip-specific constructor
+ */
+static int __devinit snd_vr5701_create(snd_card_t *card,
+ struct pci_dev *pci, vr5701_t **rchip)
+{
+ vr5701_t *chip;
+ int err;
+ static snd_device_ops_t ops = {
+ .dev_free = snd_vr5701_dev_free,
+ };
+
+ *rchip = NULL;
+
+ /* initialize the PCI entry */
+ if ((err = pci_enable_device(pci)) < 0)
+ return err;
+ pci_set_master(pci);
+
+ /* check PCI availability (28bit DMA) */
+ if (pci_set_dma_mask(pci, 0x0fffffff) < 0 ||
+ pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) {
+ printk(KERN_ERR "error to set 28bit mask DMA\n");
+ pci_disable_device(pci);
+ return -ENXIO;
+ }
+
+ /* allocate a chip-specific data with zero filled */
+ chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL) {
+ pci_disable_device(pci);
+ return -ENOMEM;
+ }
+
+ /* initialize the stuff */
+ chip->card = card;
+ chip->pci = pci;
+ chip->irq = -1;
+
+ /* so that snd_chip_free will work as intended */
+ chip->card->private_data = chip;
+
+ /* PCI resource allocation */
+ if ((err = pci_request_regions(pci, vr5701_AC97_MODULE_NAME)) < 0) {
+ kfree(chip);
+ pci_disable_device(pci);
+ return err;
+ }
+ chip->port = pci_resource_start(pci, 0);
+ if (request_irq(pci->irq, snd_vr5701_interrupt,
+ SA_INTERRUPT|SA_SHIRQ, vr5701_AC97_MODULE_NAME,
+ (void *)chip)) {
+ printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
+ snd_vr5701_free(chip);
+ return -EBUSY;
+ }
+ chip->irq = pci->irq;
+
+ if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
+ chip, &ops)) < 0) {
+ snd_vr5701_free(chip);
+ return err;
+ }
+
+ snd_card_set_dev(card, &pci->dev);
+
+ *rchip = chip;
+ return 0;
+}
+
+/* constructor */
+static int __devinit snd_vr5701_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
+{
+ static int dev;
+ snd_card_t *card;
+ vr5701_t *chip;
+ int err;
+
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+ if (!enable[dev]) {
+ dev++;
+ return -ENOENT;
+ }
+
+ card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+ if (card == NULL)
+ return -ENOMEM;
+
+ if ((err = snd_vr5701_create(card, pci, &chip)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+
+ strcpy(card->driver, vr5701_AC97_MODULE_NAME);
+ strcpy(card->shortname, "NEC Electronics Corporation ");
+ sprintf(card->longname, "%s at 0x%lx irq %i",
+ card->shortname, chip->port, chip->irq);
+
+ printk(KERN_INFO "IO at %#lx, IRQ %d\n", chip->port, chip->irq);
+
+ /* codec init */
+ if ((err = snd_vr5701_ac97(chip)) < 0)
+ return err;
+
+ snd_vr5701_ac97_reset(chip->ac97);
+
+ /* Try to enable variable rate audio mode. */
+ snd_vr5701_ac97_write(chip->ac97, AC97_EXTENDED_STATUS,
+ snd_vr5701_ac97_read(chip->ac97, AC97_EXTENDED_STATUS) | AC97_EI_VRA);
+
+ /* Did we enable it? */
+ if (!(snd_vr5701_ac97_read(chip->ac97, AC97_EXTENDED_STATUS) & AC97_EI_VRA))
+ printk(KERN_INFO "VRA mode not enabled; rate fixed at %d.",
+ 48000);
+
+ /* let us get the default volumne louder */
+ snd_vr5701_ac97_write(chip->ac97, 0x2, 0x1010); /* master volume, middle */
+ snd_vr5701_ac97_write(chip->ac97, 0xc, 0x10); /* phone volume, middle */
+ snd_vr5701_ac97_write(chip->ac97, 0x10, 0x8000);/* line-in 2 line-out disable */
+ snd_vr5701_ac97_write(chip->ac97, 0x18, 0x0707);/* PCM out (line out) middle */
+
+ /* by default we select line in the input */
+ snd_vr5701_ac97_write(chip->ac97, 0xe, 0x10); /* misc volume, middle */
+ snd_vr5701_ac97_write(chip->ac97, 0x1a, 0x0000);/* default line is Line_mic */
+ snd_vr5701_ac97_write(chip->ac97, 0x1c, 0x0f0f);
+ snd_vr5701_ac97_write(chip->ac97, 0x1e, 0x07);
+
+ /* enable the master interrupt but disable all others */
+ outl(vr5701_INT_MASK_NMASK, chip->port + vr5701_INT_MASK);
+
+ if ((err = snd_vr5701_new_pcm(chip)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+
+ if ((err = snd_card_register(card)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+
+ pci_set_drvdata(pci, card);
+ dev++;
+ return 0;
+}
+
+/* destructor */
+static void __devexit snd_vr5701_remove(struct pci_dev *pci)
+{
+ snd_card_free(pci_get_drvdata(pci));
+ pci_set_drvdata(pci, NULL);
+}
+
+/* PCI IDs */
+static struct pci_device_id snd_vr5701_ids[] = {
+ { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_VRC5477_AC97,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, snd_vr5701_ids);
+
+/* pci_driver definition */
+static struct pci_driver driver = {
+ .name = vr5701_AC97_MODULE_NAME,
+ .id_table = snd_vr5701_ids,
+ .probe = snd_vr5701_probe,
+ .remove = __devexit_p(snd_vr5701_remove),
+ SND_PCI_PM_CALLBACKS
+};
+
+/* initialization of the module */
+static int __init alsa_card_vr5701_init(void)
+{
+ printk(KERN_INFO "ALSA NEC Electronics Corporation VR5701 SolutionGearII AC97 driver: time "
+ __TIME__ " " __DATE__" by Sergey Podstavin\n");
+ return pci_register_driver(&driver);
+}
+
+/* clean up the module */
+static void __exit alsa_card_vr5701_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
+module_init(alsa_card_vr5701_init)
+module_exit(alsa_card_vr5701_exit)
+
+MODULE_AUTHOR("Sergey Podstavin");
+MODULE_DESCRIPTION("NEC Electronics Corporation VR5701 SolutionGearII audio (AC97) Driver");
+MODULE_LICENSE("GPL");
Index: linux-2.6.10/sound/pci/vr5701/nec_vr5701_sg2.h
===================================================================
--- /dev/null
+++ linux-2.6.10/sound/pci/vr5701/nec_vr5701_sg2.h
@@ -0,0 +1,155 @@
+/*
+ * sound/pci/vr5701/nec_vr5701_sg2.h
+ *
+ * An ALSA sound driver for
+ * NEC Electronics Corporation VR5701 SolutionGearII.
+ * It works with AC97 codec.
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/ac97_codec.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <sound/pcm_params.h>
+
+#define vr5701_INT_CLR 0x0
+#define vr5701_INT_STATUS 0x0
+#define vr5701_CODEC_WR 0x4
+#define vr5701_CODEC_RD 0x8
+#define vr5701_CTRL 0x18
+#define vr5701_ACLINK_CTRL 0x1c
+#define vr5701_INT_MASK 0x24
+
+#define vr5701_DAC1_CTRL 0x30
+#define vr5701_DAC1L 0x34
+#define vr5701_DAC1_BADDR 0x38
+#define vr5701_DAC2_CTRL 0x3c
+#define vr5701_DAC2L 0x40
+#define vr5701_DAC2_BADDR 0x44
+#define vr5701_DAC3_CTRL 0x48
+#define vr5701_DAC3L 0x4c
+#define vr5701_DAC3_BADDR 0x50
+
+#define vr5701_ADC1_CTRL 0x54
+#define vr5701_ADC1L 0x58
+#define vr5701_ADC1_BADDR 0x5c
+#define vr5701_ADC2_CTRL 0x60
+#define vr5701_ADC2L 0x64
+#define vr5701_ADC2_BADDR 0x68
+#define vr5701_ADC3_CTRL 0x6c
+#define vr5701_ADC3L 0x70
+#define vr5701_ADC3_BADDR 0x74
+
+#define vr5701_CODEC_WR_RWC (1 << 23)
+
+#define vr5701_CODEC_RD_RRDYA (1 << 31)
+#define vr5701_CODEC_RD_RRDYD (1 << 30)
+
+#define vr5701_ACLINK_CTRL_RST_ON (1 << 15)
+#define vr5701_ACLINK_CTRL_RST_TIME 0x7f
+#define vr5701_ACLINK_CTRL_SYNC_ON (1 << 30)
+#define vr5701_ACLINK_CTRL_CK_STOP_ON (1 << 31)
+
+#define vr5701_CTRL_DAC2ENB (1 << 15)
+#define vr5701_CTRL_ADC2ENB (1 << 14)
+#define vr5701_CTRL_DAC1ENB (1 << 13)
+#define vr5701_CTRL_ADC1ENB (1 << 12)
+
+#define vr5701_INT_MASK_NMASK (1 << 31)
+#define vr5701_INT_MASK_DAC1END (1 << 5)
+#define vr5701_INT_MASK_DAC2END (1 << 4)
+#define vr5701_INT_MASK_DAC3END (1 << 3)
+#define vr5701_INT_MASK_ADC1END (1 << 2)
+#define vr5701_INT_MASK_ADC2END (1 << 1)
+#define vr5701_INT_MASK_ADC3END (1 << 0)
+
+#define vr5701_DMA_ACTIVATION (1 << 31)
+#define vr5701_DMA_WIP (1 << 30)
+
+#define vr5701_AC97_MODULE_NAME "NEC_vr5701_audio"
+#define PLAYBACK 0
+#define CAPTURE 1
+
+/* module parameters */
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+/* definition of the chip-specific record */
+typedef struct snd_vr5701 vr5701_t;
+
+struct snd_vr5701 {
+ snd_card_t *card;
+ struct pci_dev *pci;
+ ac97_t *ac97;
+ unsigned long port;
+ int irq;
+ snd_pcm_t *pcm;
+ snd_pcm_substream_t * substream[2];
+ unsigned next_playback;
+ unsigned next_capture;
+};
+
+static unsigned int rates[] = {
+ 8000, 11025, 16000, 22050,
+ 32000, 44100, 48000,
+};
+
+static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
+ .count = ARRAY_SIZE(rates),
+ .list = rates,
+ .mask = 0,
+};
+
+/* hardware definition */
+static snd_pcm_hardware_t snd_vr5701_playback_hw = {
+ .info = ( SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_NONINTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = (128*1024),
+ .period_bytes_min = 32,
+ .period_bytes_max = (128*1024),
+ .periods_min = 1,
+ .periods_max = 1024,
+};
+
+/* hardware definition */
+static snd_pcm_hardware_t snd_vr5701_capture_hw = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = (128*1024),
+ .period_bytes_min = 32,
+ .period_bytes_max = (128*1024),
+ .periods_min = 1,
+ .periods_max = 1024,
+};
Index: linux-2.6.10/sound/pci/vr5701/Makefile
===================================================================
--- /dev/null
+++ linux-2.6.10/sound/pci/vr5701/Makefile
@@ -0,0 +1,16 @@
+#
+# sound/pci/vr5701/Makefile
+#
+# Makefile for ALSA
+#
+# Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+#
+# 2005 (c) MontaVista Software, Inc. This file is licensed under
+# the terms of the GNU General Public License version 2. This program
+# is licensed "as is" without any warranty of any kind, whether express
+# or implied.
+#
+
+snd-nec_vr5701_sg2-objs := nec_vr5701_sg2.o
+
+obj-$(CONFIG_SND_VR5701) += snd-nec_vr5701_sg2.o
Index: linux-2.6.10/mvl_patches/pro-0004.c
===================================================================
--- /dev/null
+++ linux-2.6.10/mvl_patches/pro-0004.c
@@ -0,0 +1,16 @@
+/*
+ * Author: MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/init.h>
+#include <linux/mvl_patch.h>
+
+static __init int regpatch(void)
+{
+ return mvl_register_patch(4);
+}
+module_init(regpatch);
Index: linux-2.6.10/include/linux/lsppatchlevel.h
===================================================================
--- linux-2.6.10.orig/include/linux/lsppatchlevel.h
+++ linux-2.6.10/include/linux/lsppatchlevel.h
@@ -6,4 +6,4 @@
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
-#define LSP_PATCH_LEVEL "3"
+#define LSP_PATCH_LEVEL "4"
^ permalink raw reply [flat|nested] 9+ messages in thread* NEC VR5701 support
@ 2006-02-23 15:38 Sergey Podstavin
0 siblings, 0 replies; 9+ messages in thread
From: Sergey Podstavin @ 2006-02-23 15:38 UTC (permalink / raw)
To: linux-mips
[-- Attachment #1: Type: text/plain, Size: 1 bytes --]
[-- Attachment #2: pro_mips_nec_vr5701_errata.patch --]
[-- Type: text/x-patch, Size: 2680 bytes --]
Source: MontaVista Software, Inc. Sergey Podstavin <spodstavin@ru.mvista.com>
MR: 17133
Type: Enhancement
Disposition: needs submitting to linuxmips-embedded mailing list
Signed-off-by: Sergey Podstavin <spodstavin@ru.mvista.com>
Description:
NEC Vr5701 workaround. Basically,it gives the following workaround:
Restriction no.1:
Please set the value 1 in DISCTIM field of the IPCI_CTRL-L
register of IPCIC (or the EPCI_CTRL-L register of EPCIC).
Restriction no.2:
Please clear SERREN bit of the PCICMD register of IDEC.
Restriction no.6:
Please clear PREFETCHABLE bit of the IP_BAR_MEM01 register
of IPCIC (or the EP_BAR_MEM01 register of EPCIC).
Index: linux-2.6.10/arch/mips/vr5701/vr5701_sg2/setup.c
===================================================================
--- linux-2.6.10.orig/arch/mips/vr5701/vr5701_sg2/setup.c
+++ linux-2.6.10/arch/mips/vr5701/vr5701_sg2/setup.c
@@ -98,7 +98,7 @@ static void __init vr5701_sg2_board_init
/* ------------ reset PCI bus and BARs ----------------- */
ddb_pci_reset_bus();
/* Ext. PCI memory space */
- ddb_out32(PCI_BAR_MEM01, 0x00000008);
+ ddb_out32(PCI_BAR_MEM01, 0x00000000); /* workaround - Restriction no.6 */
ddb_out8(PCI_MLTIM, 0x40);
ddb_out32(PCI_BAR_LCS0, 0xffffffff);
@@ -114,6 +114,8 @@ static void __init vr5701_sg2_board_init
ddb_out32(IPCI_BAR_LCS3, 0xffffffff);
ddb_out32(IPCI_BAR_IREG, 0xffffffff);
+ ddb_out32(IPCI_CTRLL, 0x01000000); /* workaround - Restriction no.1 */
+ ddb_out32(EPCI_CTRLL, 0x01000000); /* workaround - Restriction no.1 */
/*
* We use pci master register 0 for memory space / config space
* And we use register 1 for IO space.
Index: linux-2.6.10/drivers/ide/pci/nec_vr5701_sg2.c
===================================================================
--- linux-2.6.10.orig/drivers/ide/pci/nec_vr5701_sg2.c
+++ linux-2.6.10/drivers/ide/pci/nec_vr5701_sg2.c
@@ -184,6 +184,7 @@ static int __devinit nec_vr5701_init_one
return 1;
}
ide_setup_pci_device(dev, d);
+ pci_write_config_byte(dev, 0x52, 0x00); /* workaround - Restriction no.2 */
return 0;
}
Index: linux-2.6.10/include/asm-mips/vr5701/vr5701.h
===================================================================
--- linux-2.6.10.orig/include/asm-mips/vr5701/vr5701.h
+++ linux-2.6.10/include/asm-mips/vr5701/vr5701.h
@@ -40,6 +40,7 @@
#define LOCAL_CST0 0x400
#define LOCAL_CFG 0x440
/* EPCI registers */
+#define EPCI_CTRLL 0x600
#define EPCI_CTRLH 0x604
#define EPCI_INIT0 0x610
#define EPCI_INIT1 0x618
@@ -77,6 +78,7 @@
#define CSI1_INT 0xBC8
/* IPCI registers*/
+#define IPCI_CTRLL 0xE00
#define IPCI_CTRLH 0xE04
#define IPCI_INIT0 0xE10
#define IPCI_INIT1 0xE18
^ permalink raw reply [flat|nested] 9+ messages in thread* NEC VR5701 support
@ 2006-02-23 15:39 Sergey Podstavin
0 siblings, 0 replies; 9+ messages in thread
From: Sergey Podstavin @ 2006-02-23 15:39 UTC (permalink / raw)
To: linux-mips
[-- Attachment #1: Type: text/plain, Size: 1 bytes --]
[-- Attachment #2: pro_mips_nec_vr5701_ide_fix.patch --]
[-- Type: text/x-patch, Size: 3238 bytes --]
Source: MontaVista Software, Inc.
MR: 14884
Type: Defect Fix
Disposition: needs submitting to linuxmips-embedded mailing list
Signed-off-by: Aleskey Makarov <makarov@ru.mvista.com>
Description:
The address of IDE control register on this platform
is not standard. Also, an unnecessary check for pci
vendor/device/class was removed and
an unnamed constant assignment was fixed.
Index: linux-2.6.10/arch/mips/vr5701/tcube/setup.c
===================================================================
--- linux-2.6.10.orig/arch/mips/vr5701/tcube/setup.c
+++ linux-2.6.10/arch/mips/vr5701/tcube/setup.c
@@ -123,7 +123,7 @@ static void __init tcube_board_init(void
* IO_BASE in CPU physical address space.
*/
ddb_set_pmr(EPCI_INIT0, DDB_PCICMD_MEM, 0x10000000, DDB_PCI_ACCESS_32);
- ddb_set_pmr(EPCI_INIT1, DDB_PCICMD_IO, 0x00001000, DDB_PCI_ACCESS_32);
+ ddb_set_pmr(EPCI_INIT1, DDB_PCICMD_IO, 0x00000000, DDB_PCI_ACCESS_32);
ddb_set_pmr(IPCI_INIT0, DDB_PCICMD_MEM, 0x18800000, DDB_PCI_ACCESS_32);
ddb_set_pmr(IPCI_INIT1, DDB_PCICMD_IO, 0x01000000, DDB_PCI_ACCESS_32);
Index: linux-2.6.10/drivers/ide/pci/nec_vr5701_sg2.c
===================================================================
--- linux-2.6.10.orig/drivers/ide/pci/nec_vr5701_sg2.c
+++ linux-2.6.10/drivers/ide/pci/nec_vr5701_sg2.c
@@ -44,6 +44,13 @@ static void __init init_hwif_nec_vr5701(
hwif->mwdma_mask = 0x07;
hwif->swdma_mask = 0x07;
+ {
+ struct pci_dev * pci_dev = hwif->pci_dev;
+ hwif->io_ports[IDE_CONTROL_OFFSET]
+ = hwif->hw.io_ports[IDE_CONTROL_OFFSET]
+ = pci_resource_start(pci_dev, 1) + 0x06;
+ }
+
if (!noautodma)
hwif->autodma = 1;
hwif->drives[0].autodma = hwif->autodma;
@@ -65,15 +72,9 @@ static int __devinit nec_vr5701_init_one
ide_pci_device_t *d = &nec_vr5701_chipset;
u16 command;
- if (dev->vendor == PCI_VENDOR_ID_NEC &&
- dev->device == PCI_DEVICE_ID_NEC_USB_AND_IDE &&
- dev->class == 0x0c0310)
- return 1;
- udelay(100);
pci_enable_device(dev);
- *(volatile unsigned char *)0xb9001010 = 6;
- asm("sync");
- udelay(100);
+
+ outb(6, pci_resource_start(dev, 5));
pci_read_config_word(dev, PCI_COMMAND, &command);
if (!(command & PCI_COMMAND_IO)) {
Index: linux-2.6.10/include/linux/lsppatchlevel.h
===================================================================
--- linux-2.6.10.orig/include/linux/lsppatchlevel.h
+++ linux-2.6.10/include/linux/lsppatchlevel.h
@@ -6,4 +6,4 @@
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
-#define LSP_PATCH_LEVEL "6"
+#define LSP_PATCH_LEVEL "7"
Index: linux-2.6.10/mvl_patches/pro-0007.c
===================================================================
--- /dev/null
+++ linux-2.6.10/mvl_patches/pro-0007.c
@@ -0,0 +1,16 @@
+/*
+ * Author: MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/init.h>
+#include <linux/mvl_patch.h>
+
+static __init int regpatch(void)
+{
+ return mvl_register_patch(7);
+}
+module_init(regpatch);
^ permalink raw reply [flat|nested] 9+ messages in thread* NEC VR5701 support
@ 2006-02-23 15:39 Sergey Podstavin
0 siblings, 0 replies; 9+ messages in thread
From: Sergey Podstavin @ 2006-02-23 15:39 UTC (permalink / raw)
To: linux-mips
[-- Attachment #1: Type: text/plain, Size: 1 bytes --]
[-- Attachment #2: pro_mips_nec_vr5701_ide_udma_fix.patch --]
[-- Type: text/x-patch, Size: 4097 bytes --]
Source: MontaVista Software, Inc.
MR: 15910
Type: Defect Fix
Disposition: needs submitting to linuxmips-embedded mailing list
Signed-off-by: Aleskey Makarov <makarov@ru.mvista.com>
Description:
This patch adds the code that changes
dma mode of the IPCI IDE controller.
Index: linux-2.6.10/drivers/ide/pci/nec_vr5701_sg2.c
===================================================================
--- linux-2.6.10.orig/drivers/ide/pci/nec_vr5701_sg2.c
+++ linux-2.6.10/drivers/ide/pci/nec_vr5701_sg2.c
@@ -34,6 +34,105 @@ static unsigned int __init init_chipset_
return 0;
}
+static u8 nec_vr5701_ratemask(ide_drive_t * drive)
+{
+ u8 mode = 2;
+ if (!eighty_ninty_three(drive))
+ mode = min(mode, (u8)1);
+ return mode;
+}
+
+static void udma_set(ide_drive_t * drive, u16 udma_mode)
+{
+
+ ide_hwif_t * hwif = HWIF(drive);
+ struct pci_dev * dev = hwif->pci_dev;
+
+ u8 reg4b; /* udma control register */
+ u16 reg4c; /* udma timing register */
+
+ pci_read_config_word(dev, 0x4c, ®4c);
+ reg4c &= ~(7 << (drive->dn * 4));
+ reg4c |= udma_mode << (drive->dn * 4);
+ pci_write_config_word(dev, 0x4c, reg4c);
+
+ pci_read_config_byte(dev, 0x4b, ®4b);
+ reg4b |= 1 << drive->dn;
+ pci_write_config_byte(dev, 0x4b, reg4b);
+}
+
+static void udma_clean(ide_drive_t * drive)
+{
+
+ ide_hwif_t * hwif = HWIF(drive);
+ struct pci_dev * dev = hwif->pci_dev;
+
+ u8 reg4b; /* udma control register */
+
+ pci_read_config_byte(dev, 0x4b, ®4b);
+ reg4b &= ~(1 << drive->dn);
+ pci_write_config_byte(dev, 0x4b, reg4b);
+}
+
+static void dma_set(ide_drive_t * drive, u32 dma_mode)
+{
+
+ ide_hwif_t * hwif = HWIF(drive);
+ struct pci_dev * dev = hwif->pci_dev;
+
+ u32 reg44; /* dma timing register */
+
+ udma_clean(drive);
+
+ pci_read_config_dword(dev, 0x44, ®44);
+ reg44 &= ~(3 << (8 * drive->dn));
+ reg44 |= dma_mode << (8 * drive->dn);
+ pci_write_config_dword(dev, 0x44, reg44);
+}
+
+static int nec_vr5701_tune_chipset (ide_drive_t *drive, u8 xferspeed)
+{
+ u8 speed = ide_rate_filter(nec_vr5701_ratemask(drive), xferspeed);
+
+ switch(speed) {
+ case XFER_UDMA_4:
+ udma_set(drive, 4);
+ break;
+ case XFER_UDMA_3:
+ udma_set(drive, 3);
+ break;
+ case XFER_UDMA_2:
+ udma_set(drive, 2);
+ break;
+ case XFER_UDMA_1:
+ udma_set(drive, 1);
+ break;
+ case XFER_UDMA_0:
+ udma_set(drive, 0);
+ break;
+ case XFER_MW_DMA_2:
+ dma_set(drive, 2);
+ break;
+ case XFER_MW_DMA_1:
+ dma_set(drive, 1);
+ break;
+ case XFER_MW_DMA_0:
+ dma_set(drive, 0);
+ break;
+ case XFER_PIO_4:
+ case XFER_PIO_3:
+ case XFER_PIO_2:
+ case XFER_PIO_1:
+ case XFER_PIO_0:
+ udma_clean(drive);
+ break;
+ default:
+ return -1;
+ }
+
+ return (ide_config_drive_speed(drive, speed));
+}
+
static void __init init_hwif_nec_vr5701(ide_hwif_t * hwif)
{
if (!(hwif->dma_base))
@@ -44,6 +143,8 @@ static void __init init_hwif_nec_vr5701(
hwif->mwdma_mask = 0x07;
hwif->swdma_mask = 0x07;
+ hwif->speedproc = &nec_vr5701_tune_chipset;
+
{
struct pci_dev * pci_dev = hwif->pci_dev;
hwif->io_ports[IDE_CONTROL_OFFSET]
Index: linux-2.6.10/include/linux/lsppatchlevel.h
===================================================================
--- linux-2.6.10.orig/include/linux/lsppatchlevel.h
+++ linux-2.6.10/include/linux/lsppatchlevel.h
@@ -6,4 +6,4 @@
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
-#define LSP_PATCH_LEVEL "7"
+#define LSP_PATCH_LEVEL "8"
Index: linux-2.6.10/mvl_patches/pro-0008.c
===================================================================
--- /dev/null
+++ linux-2.6.10/mvl_patches/pro-0008.c
@@ -0,0 +1,16 @@
+/*
+ * Author: MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/init.h>
+#include <linux/mvl_patch.h>
+
+static __init int regpatch(void)
+{
+ return mvl_register_patch(8);
+}
+module_init(regpatch);
^ permalink raw reply [flat|nested] 9+ messages in thread* NEC VR5701 support
@ 2006-02-23 15:41 Sergey Podstavin
0 siblings, 0 replies; 9+ messages in thread
From: Sergey Podstavin @ 2006-02-23 15:41 UTC (permalink / raw)
To: linux-mips
[-- Attachment #1: Type: text/plain, Size: 1 bytes --]
[-- Attachment #2: pro_mips_nec_vr5701_removing_tcube.patch --]
[-- Type: text/x-patch, Size: 80063 bytes --]
Source: MontaVista Software, Inc. Sergey Podstavin <spodstavin@ru.mvista.com>
MR: 15475
Type: Defect Fix
Disposition: needs submitting to linuxmips-embedded mailing list
Signed-off-by: Sergey Podstavin <spodstavin@ru.mvista.com>
Description:
The Vendor asks to remove "teacube" and to change "teacube" to
"VR5701-SG2" respectively on all documents such as the name of Config,
directory, files, functions and etc.
Index: linux-2.6.10/arch/mips/Kconfig
===================================================================
--- linux-2.6.10.orig/arch/mips/Kconfig
+++ linux-2.6.10/arch/mips/Kconfig
@@ -449,7 +449,7 @@ config DDB5477_BUS_FREQUENCY
depends on DDB5477
default 0
-config TCUBE
+config VR5701_SG2
bool "Support for NEC Electronics Corporation VR5701 SolutionGearII"
select IRQ_CPU
select HW_HAS_PCI
Index: linux-2.6.10/arch/mips/Makefile
===================================================================
--- linux-2.6.10.orig/arch/mips/Makefile
+++ linux-2.6.10/arch/mips/Makefile
@@ -477,11 +477,11 @@ core-$(CONFIG_DDB5477) += arch/mips/ddb
load-$(CONFIG_DDB5477) += 0xffffffff80100000
#
-# NEC TCUBE
+# NEC VR5701-SG2
#
-core-$(CONFIG_TCUBE) += arch/mips/vr5701/common/
-core-$(CONFIG_TCUBE) += arch/mips/vr5701/tcube/
-load-$(CONFIG_TCUBE) += 0xffffffff80080000
+core-$(CONFIG_VR5701_SG2) += arch/mips/vr5701/common/
+core-$(CONFIG_VR5701_SG2) += arch/mips/vr5701/vr5701_sg2/
+load-$(CONFIG_VR5701_SG2) += 0xffffffff80080000
core-$(CONFIG_LASAT) += arch/mips/lasat/
cflags-$(CONFIG_LASAT) += -Iinclude/asm-mips/mach-lasat
Index: linux-2.6.10/arch/mips/configs/nec_vr5701_defconfig
===================================================================
--- linux-2.6.10.orig/arch/mips/configs/nec_vr5701_defconfig
+++ linux-2.6.10/arch/mips/configs/nec_vr5701_defconfig
@@ -90,7 +90,7 @@ CONFIG_KMOD=y
# CONFIG_DDB5074 is not set
# CONFIG_DDB5476 is not set
# CONFIG_DDB5477 is not set
-CONFIG_TCUBE=y
+CONFIG_VR5701_SG2=y
# CONFIG_NEC_OSPREY is not set
# CONFIG_SGI_IP22 is not set
# CONFIG_SOC_AU1X00 is not set
Index: linux-2.6.10/arch/mips/pci/Makefile
===================================================================
--- linux-2.6.10.orig/arch/mips/pci/Makefile
+++ linux-2.6.10/arch/mips/pci/Makefile
@@ -52,4 +52,4 @@ obj-$(CONFIG_TOSHIBA_JMR3927) += fixup-j
obj-$(CONFIG_TOSHIBA_RBTX4927) += fixup-rbtx4927.o ops-tx4927.o
obj-$(CONFIG_VICTOR_MPC30X) += fixup-mpc30x.o
obj-$(CONFIG_ZAO_CAPCELLA) += fixup-capcella.o
-obj-$(CONFIG_TCUBE) += pci-tcube.o ops-tcube.o
+obj-$(CONFIG_VR5701_SG2) += pci-vr5701_sg2.o ops-vr5701_sg2.o
Index: linux-2.6.10/arch/mips/pci/ops-tcube.c
===================================================================
--- linux-2.6.10.orig/arch/mips/pci/ops-tcube.c
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * arch/mips/pci/ops-tcube.c
- *
- * A config access for PCI controllers on NEC Electronics Corporation VR5701 SolutionGearII
- *
- * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <asm/addrspace.h>
-#include <asm/debug.h>
-#include <asm/tcube.h>
-
-/*
- * config_swap structure records what set of pdar/pmr are used
- * to access pci config space. It also provides a place hold the
- * original values for future restoring.
- */
-struct pci_config_swap {
- u32 pdar;
- u32 pmr;
- u32 config_base;
- u32 config_size;
- u32 pdar_backup;
- u32 pmr_backup;
-};
-
-/*
- * On VR5701-SG2, we have two sets of swap registers, for ext PCI and IOPCI.
- */
-struct pci_config_swap ext_pci_swap = {
- PADR_EPCIW0,
- EPCI_INIT0,
- 0x10000000,
- 0x08000000
-};
-struct pci_config_swap io_pci_swap = {
- PADR_IOPCIW0,
- IPCI_INIT0,
- 0x18800000,
- 0x00800000
-};
-
-/*
- * access config space
- */
-static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus, /* 0 means top level bus */
- u32 slot_num)
-{
- u32 pci_addr = 0;
- u32 pciinit_offset = 0;
- u32 virt_addr;
- u32 option;
-
- /* minimum pdar (window) size is 2MB */
- db_assert(swap->config_size >= (2 << 20));
- db_assert(slot_num < (1 << 5));
- db_assert(bus < (1 << 8));
-
- /* backup registers */
- swap->pdar_backup = ddb_in32(swap->pdar);
- swap->pmr_backup = ddb_in32(swap->pmr);
-
- /* set the pdar (pci window) register */
- ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32, /* 32 bit wide */
- 0, /* not on local memory bus */
- 0); /* not visible from PCI bus (N/A) */
-
- /*
- * calcuate the absolute pci config addr;
- * according to the spec, we start scanning from adr:11 (0x800)
- */
- if (bus == 0) {
- /* type 0 config */
- pci_addr = 0x800 << slot_num;
- } else {
- /* type 1 config */
- pci_addr = (bus << 16) | (slot_num << 11);
- }
-
- /*
- * if pci_addr is less than pci config window size, we set
- * pciinit_offset to 0 and adjust the virt_address.
- * Otherwise we will try to adjust pciinit_offset.
- */
- if (pci_addr < swap->config_size) {
- virt_addr = KSEG1ADDR(swap->config_base + pci_addr);
- pciinit_offset = 0;
- } else {
- db_assert((pci_addr & (swap->config_size - 1)) == 0);
- virt_addr = KSEG1ADDR(swap->config_base);
- pciinit_offset = pci_addr;
- }
-
- /* set the pmr register */
- option = DDB_PCI_ACCESS_32;
- if (bus != 0)
- option |= DDB_PCI_CFGTYPE1;
-
- ddb_out32(swap->pmr,
- (DDB_PCICMD_CFG << 1) | (pciinit_offset & 0xffe00000) |
- option);
- ddb_out32(swap->pmr + 4, 0);
-
- return virt_addr;
-}
-
-static inline void ddb_close_config_base(struct pci_config_swap *swap)
-{
- ddb_out32(swap->pdar, swap->pdar_backup);
- ddb_out32(swap->pmr, swap->pmr_backup);
-}
-
-static int read_config_dword(struct pci_config_swap *swap,
- struct pci_bus *bus, u32 devfn, u32 where,
- u32 * val)
-{
- u32 bus_num, slot_num, func_num;
- u32 base;
-
- db_assert((where & 3) == 0);
- db_assert(where < (1 << 8));
-
- /* check if the bus is top-level */
- if (bus->parent != NULL) {
- bus_num = bus->number;
- db_assert(bus_num != 0);
- } else {
- bus_num = 0;
- }
- slot_num = PCI_SLOT(devfn);
- func_num = PCI_FUNC(devfn);
- base = ddb_access_config_base(swap, bus_num, slot_num);
- *val = *(volatile u32 *)(base + (func_num << 8) + where);
- ddb_close_config_base(swap);
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int read_config_word(struct pci_config_swap *swap,
- struct pci_bus *bus, u32 devfn, u32 where,
- u16 * val)
-{
- int status;
- u32 result;
-
- db_assert((where & 1) == 0);
-
- status = read_config_dword(swap, bus, devfn, where & ~3, &result);
- if (where & 2)
- result >>= 16;
- *val = result & 0xffff;
- return status;
-}
-
-static int read_config_byte(struct pci_config_swap *swap,
- struct pci_bus *bus, u32 devfn, u32 where, u8 * val)
-{
- int status;
- u32 result;
-
- status = read_config_dword(swap, bus, devfn, where & ~3, &result);
- if (where & 1)
- result >>= 8;
- if (where & 2)
- result >>= 16;
- *val = result & 0xff;
-
- return status;
-}
-
-static int write_config_dword(struct pci_config_swap *swap,
- struct pci_bus *bus, u32 devfn, u32 where,
- u32 val)
-{
- u32 bus_num, slot_num, func_num;
- u32 base;
-
- db_assert((where & 3) == 0);
- db_assert(where < (1 << 8));
-
- /* check if the bus is top-level */
- if (bus->parent != NULL) {
- bus_num = bus->number;
- db_assert(bus_num != 0);
- } else {
- bus_num = 0;
- }
-
- slot_num = PCI_SLOT(devfn);
- func_num = PCI_FUNC(devfn);
- base = ddb_access_config_base(swap, bus_num, slot_num);
- *(volatile u32 *)(base + (func_num << 8) + where) = val;
- ddb_close_config_base(swap);
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int write_config_word(struct pci_config_swap *swap,
- struct pci_bus *bus, u32 devfn, u32 where, u16 val)
-{
- int status, shift = 0;
- u32 result;
-
- db_assert((where & 1) == 0);
-
- status = read_config_dword(swap, bus, devfn, where & ~3, &result);
- if (status != PCIBIOS_SUCCESSFUL)
- return status;
-
- if (where & 2)
- shift += 16;
- result &= ~(0xffff << shift);
- result |= val << shift;
- return write_config_dword(swap, bus, devfn, where & ~3, result);
-}
-
-static int write_config_byte(struct pci_config_swap *swap,
- struct pci_bus *bus, u32 devfn, u32 where, u8 val)
-{
- int status, shift = 0;
- u32 result;
-
- status = read_config_dword(swap, bus, devfn, where & ~3, &result);
- if (status != PCIBIOS_SUCCESSFUL)
- return status;
-
- if (where & 2)
- shift += 16;
- if (where & 1)
- shift += 8;
- result &= ~(0xff << shift);
- result |= val << shift;
- return write_config_dword(swap, bus, devfn, where & ~3, result);
-}
-
-#define MAKE_PCI_OPS(prefix, rw, pciswap, star) \
-static int prefix##_##rw##_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 star val) \
-{ \
- if (size == 1) \
- return rw##_config_byte(pciswap, bus, devfn, where, (u8 star)val); \
- else if (size == 2) \
- return rw##_config_word(pciswap, bus, devfn, where, (u16 star)val); \
- /* Size must be 4 */ \
- return rw##_config_dword(pciswap, bus, devfn, where, val); \
-}
-
-MAKE_PCI_OPS(extpci, read, &ext_pci_swap, *)
- MAKE_PCI_OPS(extpci, write, &ext_pci_swap,)
-
- MAKE_PCI_OPS(iopci, read, &io_pci_swap, *)
- MAKE_PCI_OPS(iopci, write, &io_pci_swap,)
-
-struct pci_ops VR5701_ext_pci_ops = {
- .read = extpci_read_config,
- .write = extpci_write_config
-};
-
-struct pci_ops VR5701_io_pci_ops = {
- .read = iopci_read_config,
- .write = iopci_write_config
-};
Index: linux-2.6.10/arch/mips/pci/ops-vr5701_sg2.c
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/pci/ops-vr5701_sg2.c
@@ -0,0 +1,267 @@
+/*
+ * arch/mips/pci/ops-vr5701_sg2.c
+ *
+ * A config access for PCI controllers on NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/addrspace.h>
+#include <asm/debug.h>
+#include <asm/vr5701/vr5701_sg2.h>
+
+/*
+ * config_swap structure records what set of pdar/pmr are used
+ * to access pci config space. It also provides a place hold the
+ * original values for future restoring.
+ */
+struct pci_config_swap {
+ u32 pdar;
+ u32 pmr;
+ u32 config_base;
+ u32 config_size;
+ u32 pdar_backup;
+ u32 pmr_backup;
+};
+
+/*
+ * On VR5701-SG2, we have two sets of swap registers, for ext PCI and IOPCI.
+ */
+struct pci_config_swap ext_pci_swap = {
+ PADR_EPCIW0,
+ EPCI_INIT0,
+ 0x10000000,
+ 0x08000000
+};
+struct pci_config_swap io_pci_swap = {
+ PADR_IOPCIW0,
+ IPCI_INIT0,
+ 0x18800000,
+ 0x00800000
+};
+
+/*
+ * access config space
+ */
+static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus, /* 0 means top level bus */
+ u32 slot_num)
+{
+ u32 pci_addr = 0;
+ u32 pciinit_offset = 0;
+ u32 virt_addr;
+ u32 option;
+
+ /* minimum pdar (window) size is 2MB */
+ db_assert(swap->config_size >= (2 << 20));
+ db_assert(slot_num < (1 << 5));
+ db_assert(bus < (1 << 8));
+
+ /* backup registers */
+ swap->pdar_backup = ddb_in32(swap->pdar);
+ swap->pmr_backup = ddb_in32(swap->pmr);
+
+ /* set the pdar (pci window) register */
+ ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32, /* 32 bit wide */
+ 0, /* not on local memory bus */
+ 0); /* not visible from PCI bus (N/A) */
+
+ /*
+ * calcuate the absolute pci config addr;
+ * according to the spec, we start scanning from adr:11 (0x800)
+ */
+ if (bus == 0) {
+ /* type 0 config */
+ pci_addr = 0x800 << slot_num;
+ } else {
+ /* type 1 config */
+ pci_addr = (bus << 16) | (slot_num << 11);
+ }
+
+ /*
+ * if pci_addr is less than pci config window size, we set
+ * pciinit_offset to 0 and adjust the virt_address.
+ * Otherwise we will try to adjust pciinit_offset.
+ */
+ if (pci_addr < swap->config_size) {
+ virt_addr = KSEG1ADDR(swap->config_base + pci_addr);
+ pciinit_offset = 0;
+ } else {
+ db_assert((pci_addr & (swap->config_size - 1)) == 0);
+ virt_addr = KSEG1ADDR(swap->config_base);
+ pciinit_offset = pci_addr;
+ }
+
+ /* set the pmr register */
+ option = DDB_PCI_ACCESS_32;
+ if (bus != 0)
+ option |= DDB_PCI_CFGTYPE1;
+
+ ddb_out32(swap->pmr,
+ (DDB_PCICMD_CFG << 1) | (pciinit_offset & 0xffe00000) |
+ option);
+ ddb_out32(swap->pmr + 4, 0);
+
+ return virt_addr;
+}
+
+static inline void ddb_close_config_base(struct pci_config_swap *swap)
+{
+ ddb_out32(swap->pdar, swap->pdar_backup);
+ ddb_out32(swap->pmr, swap->pmr_backup);
+}
+
+static int read_config_dword(struct pci_config_swap *swap,
+ struct pci_bus *bus, u32 devfn, u32 where,
+ u32 * val)
+{
+ u32 bus_num, slot_num, func_num;
+ u32 base;
+
+ db_assert((where & 3) == 0);
+ db_assert(where < (1 << 8));
+
+ /* check if the bus is top-level */
+ if (bus->parent != NULL) {
+ bus_num = bus->number;
+ db_assert(bus_num != 0);
+ } else {
+ bus_num = 0;
+ }
+ slot_num = PCI_SLOT(devfn);
+ func_num = PCI_FUNC(devfn);
+ base = ddb_access_config_base(swap, bus_num, slot_num);
+ *val = *(volatile u32 *)(base + (func_num << 8) + where);
+ ddb_close_config_base(swap);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int read_config_word(struct pci_config_swap *swap,
+ struct pci_bus *bus, u32 devfn, u32 where,
+ u16 * val)
+{
+ int status;
+ u32 result;
+
+ db_assert((where & 1) == 0);
+
+ status = read_config_dword(swap, bus, devfn, where & ~3, &result);
+ if (where & 2)
+ result >>= 16;
+ *val = result & 0xffff;
+ return status;
+}
+
+static int read_config_byte(struct pci_config_swap *swap,
+ struct pci_bus *bus, u32 devfn, u32 where, u8 * val)
+{
+ int status;
+ u32 result;
+
+ status = read_config_dword(swap, bus, devfn, where & ~3, &result);
+ if (where & 1)
+ result >>= 8;
+ if (where & 2)
+ result >>= 16;
+ *val = result & 0xff;
+
+ return status;
+}
+
+static int write_config_dword(struct pci_config_swap *swap,
+ struct pci_bus *bus, u32 devfn, u32 where,
+ u32 val)
+{
+ u32 bus_num, slot_num, func_num;
+ u32 base;
+
+ db_assert((where & 3) == 0);
+ db_assert(where < (1 << 8));
+
+ /* check if the bus is top-level */
+ if (bus->parent != NULL) {
+ bus_num = bus->number;
+ db_assert(bus_num != 0);
+ } else {
+ bus_num = 0;
+ }
+
+ slot_num = PCI_SLOT(devfn);
+ func_num = PCI_FUNC(devfn);
+ base = ddb_access_config_base(swap, bus_num, slot_num);
+ *(volatile u32 *)(base + (func_num << 8) + where) = val;
+ ddb_close_config_base(swap);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int write_config_word(struct pci_config_swap *swap,
+ struct pci_bus *bus, u32 devfn, u32 where, u16 val)
+{
+ int status, shift = 0;
+ u32 result;
+
+ db_assert((where & 1) == 0);
+
+ status = read_config_dword(swap, bus, devfn, where & ~3, &result);
+ if (status != PCIBIOS_SUCCESSFUL)
+ return status;
+
+ if (where & 2)
+ shift += 16;
+ result &= ~(0xffff << shift);
+ result |= val << shift;
+ return write_config_dword(swap, bus, devfn, where & ~3, result);
+}
+
+static int write_config_byte(struct pci_config_swap *swap,
+ struct pci_bus *bus, u32 devfn, u32 where, u8 val)
+{
+ int status, shift = 0;
+ u32 result;
+
+ status = read_config_dword(swap, bus, devfn, where & ~3, &result);
+ if (status != PCIBIOS_SUCCESSFUL)
+ return status;
+
+ if (where & 2)
+ shift += 16;
+ if (where & 1)
+ shift += 8;
+ result &= ~(0xff << shift);
+ result |= val << shift;
+ return write_config_dword(swap, bus, devfn, where & ~3, result);
+}
+
+#define MAKE_PCI_OPS(prefix, rw, pciswap, star) \
+static int prefix##_##rw##_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 star val) \
+{ \
+ if (size == 1) \
+ return rw##_config_byte(pciswap, bus, devfn, where, (u8 star)val); \
+ else if (size == 2) \
+ return rw##_config_word(pciswap, bus, devfn, where, (u16 star)val); \
+ /* Size must be 4 */ \
+ return rw##_config_dword(pciswap, bus, devfn, where, val); \
+}
+
+MAKE_PCI_OPS(extpci, read, &ext_pci_swap, *)
+ MAKE_PCI_OPS(extpci, write, &ext_pci_swap,)
+
+ MAKE_PCI_OPS(iopci, read, &io_pci_swap, *)
+ MAKE_PCI_OPS(iopci, write, &io_pci_swap,)
+
+struct pci_ops VR5701_ext_pci_ops = {
+ .read = extpci_read_config,
+ .write = extpci_write_config
+};
+
+struct pci_ops VR5701_io_pci_ops = {
+ .read = iopci_read_config,
+ .write = iopci_write_config
+};
Index: linux-2.6.10/arch/mips/pci/pci-tcube.c
===================================================================
--- linux-2.6.10.orig/arch/mips/pci/pci-tcube.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * arch/mips/pci/pci-tcube.c
- *
- * A code for PCI controllers on NEC Electronics Corporation VR5701 SolutionGearII
- *
- * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <asm/bootinfo.h>
-#include <asm/debug.h>
-#include <asm/byteorder.h>
-#include <asm/tcube.h>
-
-static struct resource extpci_io_resource = {
- "ext pci IO space",
- 0x00001000,
- 0x007FFFFF,
- IORESOURCE_IO
-};
-
-static struct resource extpci_mem_resource = {
- "ext pci memory space",
- 0x10000000,
- 0x17FFFFFF,
- IORESOURCE_MEM
-};
-
-static struct resource iopci_io_resource = {
- "io pci IO space",
- 0x01000000,
- 0x017FFFFF,
- IORESOURCE_IO
-};
-
-static struct resource iopci_mem_resource = {
- "io pci memory space",
- 0x18800000,
- 0x18FFFFFF,
- IORESOURCE_MEM
-};
-
-struct pci_controller VR5701_ext_controller = {
- .pci_ops = &VR5701_ext_pci_ops,
- .io_resource = &extpci_io_resource,
- .mem_resource = &extpci_mem_resource
-};
-
-struct pci_controller VR5701_io_controller = {
- .pci_ops = &VR5701_io_pci_ops,
- .io_resource = &iopci_io_resource,
- .mem_resource = &iopci_mem_resource
-};
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
- int slot_num;
- int k = 0;
-
- slot_num = PCI_SLOT(dev->devfn);
-
- if (dev->bus->number == 0) { /* EPCI */
- switch (slot_num) {
- case 24 - 11: /* INTD# */
- k = NUM_5701_IRQS + 3;
- break;
- case 25 - 11: /* INTC# */
- k = NUM_5701_IRQS + 2;
- break;
- case 26 - 11: /* INTB# */
- k = NUM_5701_IRQS + 1;
- break;
- case 27 - 11: /* INTA# */
- k = NUM_5701_IRQS + 0;
- break;
- }
- } else { /* IPCI */
- switch (slot_num) {
- case 29 - 11: /* INTC# */
- k = NUM_5701_IRQS + NUM_5701_EPCI_IRQ + 2;
- break;
- case 30 - 11: /* INTB# */
- k = NUM_5701_IRQS + NUM_5701_EPCI_IRQ + 1;
- break;
- case 31 - 11: /* INTA# */
- k = NUM_5701_IRQS + NUM_5701_EPCI_IRQ + 0;
- break;
- }
- }
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, k);
- dev->irq = k + 8;
- return dev->irq;
-}
-
-void ddb_pci_reset_bus(void)
-{
- u32 temp;
-
- temp = ddb_in32(EPCI_CTRLH);
- temp |= 0x80000000;
- ddb_out32(EPCI_CTRLH, temp);
- udelay(100);
- temp &= ~0xc0000000;
- ddb_out32(EPCI_CTRLH, temp);
-
- temp = ddb_in32(IPCI_CTRLH);
- temp |= 0x80000000;
- ddb_out32(IPCI_CTRLH, temp);
- udelay(100);
- temp &= ~0xc0000000;
- ddb_out32(IPCI_CTRLH, temp);
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
- return 0;
-}
Index: linux-2.6.10/arch/mips/pci/pci-vr5701_sg2.c
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/pci/pci-vr5701_sg2.c
@@ -0,0 +1,126 @@
+/*
+ * arch/mips/pci/pci-vr5701_sg2.c
+ *
+ * A code for PCI controllers on NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <asm/bootinfo.h>
+#include <asm/debug.h>
+#include <asm/byteorder.h>
+#include <asm/vr5701/vr5701_sg2.h>
+
+static struct resource extpci_io_resource = {
+ "ext pci IO space",
+ 0x00001000,
+ 0x007FFFFF,
+ IORESOURCE_IO
+};
+
+static struct resource extpci_mem_resource = {
+ "ext pci memory space",
+ 0x10000000,
+ 0x17FFFFFF,
+ IORESOURCE_MEM
+};
+
+static struct resource iopci_io_resource = {
+ "io pci IO space",
+ 0x01000000,
+ 0x017FFFFF,
+ IORESOURCE_IO
+};
+
+static struct resource iopci_mem_resource = {
+ "io pci memory space",
+ 0x18800000,
+ 0x18FFFFFF,
+ IORESOURCE_MEM
+};
+
+struct pci_controller VR5701_ext_controller = {
+ .pci_ops = &VR5701_ext_pci_ops,
+ .io_resource = &extpci_io_resource,
+ .mem_resource = &extpci_mem_resource
+};
+
+struct pci_controller VR5701_io_controller = {
+ .pci_ops = &VR5701_io_pci_ops,
+ .io_resource = &iopci_io_resource,
+ .mem_resource = &iopci_mem_resource
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ int slot_num;
+ int k = 0;
+
+ slot_num = PCI_SLOT(dev->devfn);
+
+ if (dev->bus->number == 0) { /* EPCI */
+ switch (slot_num) {
+ case 24 - 11: /* INTD# */
+ k = NUM_5701_IRQS + 3;
+ break;
+ case 25 - 11: /* INTC# */
+ k = NUM_5701_IRQS + 2;
+ break;
+ case 26 - 11: /* INTB# */
+ k = NUM_5701_IRQS + 1;
+ break;
+ case 27 - 11: /* INTA# */
+ k = NUM_5701_IRQS + 0;
+ break;
+ }
+ } else { /* IPCI */
+ switch (slot_num) {
+ case 29 - 11: /* INTC# */
+ k = NUM_5701_IRQS + NUM_5701_EPCI_IRQ + 2;
+ break;
+ case 30 - 11: /* INTB# */
+ k = NUM_5701_IRQS + NUM_5701_EPCI_IRQ + 1;
+ break;
+ case 31 - 11: /* INTA# */
+ k = NUM_5701_IRQS + NUM_5701_EPCI_IRQ + 0;
+ break;
+ }
+ }
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, k);
+ dev->irq = k + 8;
+ return dev->irq;
+}
+
+void ddb_pci_reset_bus(void)
+{
+ u32 temp;
+
+ temp = ddb_in32(EPCI_CTRLH);
+ temp |= 0x80000000;
+ ddb_out32(EPCI_CTRLH, temp);
+ udelay(100);
+ temp &= ~0xc0000000;
+ ddb_out32(EPCI_CTRLH, temp);
+
+ temp = ddb_in32(IPCI_CTRLH);
+ temp |= 0x80000000;
+ ddb_out32(IPCI_CTRLH, temp);
+ udelay(100);
+ temp &= ~0xc0000000;
+ ddb_out32(IPCI_CTRLH, temp);
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
Index: linux-2.6.10/arch/mips/vr5701/common/nec_vrxxxx.c
===================================================================
--- linux-2.6.10.orig/arch/mips/vr5701/common/nec_vrxxxx.c
+++ linux-2.6.10/arch/mips/vr5701/common/nec_vrxxxx.c
@@ -13,7 +13,7 @@
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <asm/tcube.h>
+#include <asm/vr5701/vr5701_sg2.h>
u32
ddb_calc_pdar(u32 phys, u32 size, int width, int on_memory_bus, int pci_visible)
Index: linux-2.6.10/arch/mips/vr5701/common/prom.c
===================================================================
--- linux-2.6.10.orig/arch/mips/vr5701/common/prom.c
+++ linux-2.6.10/arch/mips/vr5701/common/prom.c
@@ -18,7 +18,7 @@
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <asm/debug.h>
-#include <asm/tcube.h>
+#include <asm/vr5701/vr5701_sg2.h>
const char *get_system_type(void)
{
@@ -43,9 +43,9 @@ void __init prom_init(void)
strcat(arcs_cmdline, arg[i]);
strcat(arcs_cmdline, " ");
}
- mips_machgroup = MACH_GROUP_SHIMA;
- mips_machtype = MACH_SHIMA_TCUBE;
- add_memory_region(0, TCUBE_SDRAM_SIZE, BOOT_MEM_RAM);
+ mips_machgroup = MACH_GROUP_VR5701;
+ mips_machtype = MACH_VR5701_SG2;
+ add_memory_region(0, VR5701_SG2_SDRAM_SIZE, BOOT_MEM_RAM);
}
void __init prom_free_prom_memory(void)
Index: linux-2.6.10/arch/mips/vr5701/common/rtc_rx5c348.c
===================================================================
--- linux-2.6.10.orig/arch/mips/vr5701/common/rtc_rx5c348.c
+++ linux-2.6.10/arch/mips/vr5701/common/rtc_rx5c348.c
@@ -22,7 +22,7 @@
#include <asm/addrspace.h>
#include <asm/delay.h>
#include <asm/debug.h>
-#include <asm/tcube.h>
+#include <asm/vr5701/vr5701_sg2.h>
#undef DEBUG
#undef RTC_DELAY
Index: linux-2.6.10/arch/mips/vr5701/tcube/Makefile
===================================================================
--- linux-2.6.10.orig/arch/mips/vr5701/tcube/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for the NEC Electronics Corporation VR5701 SolutionGearII specific kernel interface routines
-# under Linux.
-#
-
-obj-y += setup.o irq.o int-handler.o irq_vr5701.o
-EXTRA_AFLAGS: = $(CFLAGS)
Index: linux-2.6.10/arch/mips/vr5701/tcube/int-handler.S
===================================================================
--- linux-2.6.10.orig/arch/mips/vr5701/tcube/int-handler.S
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * arch/mips/vr5701/tcube/int-handler.S
- *
- * First-level interrupt dispatcher for NEC Electronics Corporation VR5701 SolutionGearII
- *
- * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#include <linux/config.h>
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/tcube.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
- .align 5
- NESTED(tcube_handle_int, PT_SIZE, sp)
- SAVE_ALL
- CLI
- .set at
- .set noreorder
- mfc0 t0, CP0_CAUSE
- mfc0 t2, CP0_STATUS
-
- and t0, t2
-
- andi t1, t0, STATUSF_IP7 /* cpu timer */
- bnez t1, ll_cputimer_irq
- andi t1, t0, (STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6 )
- bnez t1, ll_tcube_irq
- andi t1, t0, STATUSF_IP0 /* software int 0 */
- bnez t1, ll_cpu_ip0
- andi t1, t0, STATUSF_IP1 /* software int 1 */
- bnez t1, ll_cpu_ip1
- nop
- .set reorder
-
- /* wrong alarm or masked ... */
- j spurious_interrupt
- nop
- END(tcube_handle_int)
-
- .align 5
-
-ll_tcube_irq:
- move a0, sp
- jal tcube_irq_dispatch
- j ret_from_irq
-
-ll_cputimer_irq:
- li a0, 7
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-
-ll_cpu_ip0:
- li a0, 0
- move a1, sp
- jal do_IRQ
- j ret_from_irq
-
-ll_cpu_ip1:
- li a0, 1
- move a1, sp
- jal do_IRQ
- j ret_from_irq
Index: linux-2.6.10/arch/mips/vr5701/tcube/irq.c
===================================================================
--- linux-2.6.10.orig/arch/mips/vr5701/tcube/irq.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * arch/mips/vr5701/tcube/irq.c
- *
- * The irq setup and misc routines for NEC Electronics Corporation VR5701 SolutionGearII
- *
- * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <asm/system.h>
-#include <asm/mipsregs.h>
-#include <asm/debug.h>
-#include <asm/tcube.h>
-/*
- * IRQ mapping
- *
- * 0-7: 8 CPU interrupts
- * 0 - software interrupt 0
- * 1 - software interrupt 1
- * 2 - most Vrc5477 interrupts are routed to this pin
- * 3 - (optional) some other interrupts routed to this pin for debugg
- * 4 - not used
- * 5 - not used
- * 6 - not used
- * 7 - cpu timer (used by default)
- *
- */
-
-void tcube_irq_setup(void)
-{
- pr_debug("NEC Electronics Corporation VR5701 SolutionGearII irq setup invoked.\n");
-
- /* by default, we disable all interrupts and route all vr5701
- * interrupts to pin 0 (irq 2) */
- ddb_out32(INT_ROUTE0, 0);
- ddb_out32(INT_ROUTE1, 0);
- ddb_out32(INT_ROUTE2, 0);
- ddb_out32(INT_ROUTE3, 0);
- ddb_out32(INT_MASK, 0);
- ddb_out32(INT_CLR, ~0x0);
-
- clear_c0_status(0xff00);
- set_c0_status(0x0400);
-
- ll_vr5701_irq_route(24, 1);
- ll_vr5701_irq_enable(24);
- ll_vr5701_irq_route(25, 1);
- ll_vr5701_irq_enable(25);
- ll_vr5701_irq_route(28, 1);
- ll_vr5701_irq_enable(28);
- ll_vr5701_irq_route(29, 1);
- ll_vr5701_irq_enable(29);
- ll_vr5701_irq_route(30, 1);
- ll_vr5701_irq_enable(30);
- ll_vr5701_irq_route(31, 1);
- ll_vr5701_irq_enable(31);
- set_c0_status(0x0800);
- set_except_vector(0, tcube_handle_int);
- /* init all controllers */
- mips_cpu_irq_init(0);
- vr5701_irq_init(8);
-}
-
-/*
- * the first level int-handler will jump here if it is a vr7701 irq
- */
-
-asmlinkage void tcube_irq_dispatch(struct pt_regs *regs)
-{
- u32 intStatus;
- u32 bitmask;
- u32 i;
- u32 intPCIStatus;
- if (ddb_in32(INT1_STAT) != 0) {
- printk(KERN_CRIT "NMI = %x\n", ddb_in32(NMI_STAT));
- printk(KERN_CRIT "INT0 = %x\n", ddb_in32(INT0_STAT));
- printk(KERN_CRIT "INT1 = %x\n", ddb_in32(INT1_STAT));
- printk(KERN_CRIT "INT2 = %x\n", ddb_in32(INT2_STAT));
- printk(KERN_CRIT "INT3 = %x\n", ddb_in32(INT3_STAT));
- printk(KERN_CRIT "INT4 = %x\n", ddb_in32(INT4_STAT));
- printk(KERN_CRIT "EPCI_ERR = %x\n", ddb_in32(EPCI_ERR));
- printk(KERN_CRIT "IPCI_ERR = %x\n", ddb_in32(IPCI_ERR));
-
- panic("error interrupt has happened.");
- }
-
- intStatus = ddb_in32(INT0_STAT);
-
- if (intStatus & 1 << 6)
- goto IRQ_EPCI;
-
- if (intStatus & 1 << 7)
- goto IRQ_IPCI;
-
- IRQ_OTHER:
- for (i = 0, bitmask = 1; i <= NUM_5701_IRQS; bitmask <<= 1, i++) {
- /* do we need to "and" with the int mask? */
- if (intStatus & bitmask) {
- do_IRQ(8 + i, regs);
- }
- }
- return;
-
- IRQ_EPCI:
- intStatus &= ~(1 << 6); /* unset Status flag */
- intPCIStatus = ddb_in32(EPCI_INTS);
- for (i = 0, bitmask = 1; i < NUM_5701_EPCI_IRQS; bitmask <<= 1, i++) {
- if (intPCIStatus & bitmask) {
- do_IRQ(8 + NUM_5701_IRQS + i, regs);
- }
- }
- if (!intStatus)
- return;
-
- IRQ_IPCI:
- intStatus &= ~(1 << 7);
- intPCIStatus = ddb_in32(IPCI_INTS);
- if (!intPCIStatus)
- goto IRQ_OTHER;
-
- for (i = 0, bitmask = 1; i < NUM_5701_IPCI_IRQS; bitmask <<= 1, i++) {
- if (intPCIStatus & bitmask) {
- do_IRQ(8 + NUM_5701_IRQS + NUM_5701_EPCI_IRQS + i,
- regs);
- }
- }
-
- if (!intStatus)
- return;
-
- goto IRQ_OTHER;
-}
-
-void __init arch_init_irq(void)
-{
- /* invoke board-specific irq setup */
- tcube_irq_setup();
-}
Index: linux-2.6.10/arch/mips/vr5701/tcube/irq_vr5701.c
===================================================================
--- linux-2.6.10.orig/arch/mips/vr5701/tcube/irq_vr5701.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * arch/mips/vr5701/tcube/irq_vr5701.c
- *
- * This file defines the irq handler for NEC Electronics Corporation VR5701 SolutionGearII
- *
- * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-/*
- * NEC Electronics Corporation VR5701 SolutionGearII defines 32 IRQs.
- *
- */
-#include <linux/interrupt.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-
-#include <asm/debug.h>
-#include <asm/tcube.h>
-
-static int vr5701_irq_base = -1;
-
-void ll_vr5701_irq_disable(int vr5701_irq, int ack);
-
-static void vr5701_irq_enable(unsigned int irq)
-{
- ll_vr5701_irq_enable(irq - vr5701_irq_base);
-}
-
-static void vr5701_irq_disable(unsigned int irq)
-{
- ll_vr5701_irq_disable(irq - vr5701_irq_base, 0);
-}
-
-static unsigned int vr5701_irq_startup(unsigned int irq)
-{
- vr5701_irq_enable(irq);
- return 0;
-}
-
-static void vr5701_irq_ack(unsigned int irq)
-{
- unsigned long flags;
- local_irq_save(flags);
-
- /* clear the interrupt bit for edge trigger */
- /* some irqs require the driver to clear the sources */
- if (irq < vr5701_irq_base + NUM_5701_IRQ) {
- ddb_out32(INT_CLR, 1 << (irq - vr5701_irq_base));
- }
- /* don't need for PCIs, for they are level triger */
-
- /* disable interrupt - some handler will re-enable the irq
- * and if the interrupt is leveled, we will have infinite loop
- */
- ll_vr5701_irq_disable(irq - vr5701_irq_base, 1);
- local_irq_restore(flags);
-}
-
-static void vr5701_irq_end(unsigned int irq)
-{
- unsigned long flags;
- local_irq_save(flags);
-
- if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
- ll_vr5701_irq_enable(irq - vr5701_irq_base);
- }
- local_irq_restore(flags);
-}
-
-struct hw_interrupt_type vr5701_irq_type = {
- "vr5701_irq",
- vr5701_irq_startup,
- vr5701_irq_disable,
- vr5701_irq_enable,
- vr5701_irq_disable,
- vr5701_irq_ack,
- vr5701_irq_end,
- NULL /* no affinity stuff for UP */
-};
-
-void vr5701_irq_init(u32 irq_base)
-{
- extern irq_desc_t irq_desc[];
- u32 i;
- vr5701_irq_base = irq_base;
- for (i = irq_base;
- i < irq_base + NUM_5701_IRQ + NUM_EPCI_IRQ + NUM_IPCI_IRQ; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = 0;
- irq_desc[i].depth = 1;
- irq_desc[i].handler = &vr5701_irq_type;
- }
-}
-
-int vr5701_irq_to_irq(int irq)
-{
- return irq + vr5701_irq_base;
-}
-
-void ll_vr5701_irq_route(int vr5701_irq, int ip)
-{
- u32 reg_value;
- u32 reg_bitmask;
- u32 reg_index;
-
- if (vr5701_irq >= NUM_5701_IRQ) {
- if (vr5701_irq >= NUM_5701_IRQ + NUM_EPCI_IRQ) {
- vr5701_irq = 7;
- } else {
- vr5701_irq = 6;
- }
- }
- reg_index = INT_ROUTE0 + vr5701_irq / 8 * 4;
- reg_value = ddb_in32(reg_index);
- reg_bitmask = 7 << (vr5701_irq % 8 * 4);
- reg_value &= ~reg_bitmask;
- reg_value |= ip << (vr5701_irq % 8 * 4);
- ddb_out32(reg_index, reg_value);
-}
-
-void ll_vr5701_irq_enable(int vr5701_irq)
-{
- u16 reg_value;
- u32 reg_bitmask;
- unsigned long flags;
-
- local_irq_save(flags);
- irq_desc[vr5701_irq_base + vr5701_irq].depth++;
-
- if (vr5701_irq >= NUM_5701_IRQ) {
- if (vr5701_irq >= NUM_5701_IRQ + NUM_EPCI_IRQ) {
- reg_value = ddb_in32(IPCI_INTM);
- reg_bitmask =
- 1 << (vr5701_irq - NUM_5701_IRQ - NUM_EPCI_IRQ);
- ddb_out32(IPCI_INTM, reg_value | reg_bitmask);
- vr5701_irq = 7;
- } else {
- reg_value = ddb_in32(EPCI_INTM);
- reg_bitmask = 1 << (vr5701_irq - NUM_5701_IRQ);
- ddb_out32(EPCI_INTM, reg_value | reg_bitmask);
- vr5701_irq = 6;
- }
- }
- reg_value = ddb_in32(INT_MASK);
- ddb_out32(INT_MASK, reg_value | (1 << vr5701_irq));
- local_irq_restore(flags);
-}
-
-void ll_vr5701_irq_disable(int vr5701_irq, int ack)
-{
- u16 reg_value;
- u32 udummy;
- u32 reg_bitmask;
- unsigned long flags;
-
- local_irq_save(flags);
- if (!ack) {
- irq_desc[vr5701_irq_base + vr5701_irq].depth--;
- if (irq_desc[vr5701_irq_base + vr5701_irq].depth) {
- local_irq_restore(flags);
- return;
- }
- }
-
- if (vr5701_irq >= NUM_5701_IRQ) {
- if (vr5701_irq >= NUM_5701_IRQ + NUM_EPCI_IRQ) {
- goto DISABLE_IRQ_IPCI;
- } else {
- goto DISABLE_IRQ_EPCI;
- }
- }
- reg_value = ddb_in32(INT_MASK);
- ddb_out32(INT_MASK, reg_value & ~(1 << vr5701_irq));
- udummy = ddb_in32(INT_MASK);
- local_irq_restore(flags);
- return;
-
- DISABLE_IRQ_IPCI:
- reg_value = ddb_in32(IPCI_INTM);
- reg_bitmask = 1 << (vr5701_irq - NUM_5701_IRQ - NUM_EPCI_IRQ);
- ddb_out32(IPCI_INTM, reg_value & ~reg_bitmask);
- local_irq_restore(flags);
- return;
-
- DISABLE_IRQ_EPCI:
- reg_value = ddb_in32(EPCI_INTM);
- reg_bitmask = 1 << (vr5701_irq - NUM_5701_IRQ);
- ddb_out32(EPCI_INTM, reg_value & ~reg_bitmask);
- local_irq_restore(flags);
-}
Index: linux-2.6.10/arch/mips/vr5701/tcube/setup.c
===================================================================
--- linux-2.6.10.orig/arch/mips/vr5701/tcube/setup.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * arch/mips/vr5701/tcube/setup.c
- *
- * Setup file for NEC Electronics Corporation VR5701 SolutionGearII
- *
- * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/kdev_t.h>
-#include <linux/types.h>
-#include <linux/console.h>
-#include <linux/sched.h>
-#include <linux/pci.h>
-#include <linux/fs.h> /* for ROOT_DEV */
-#include <linux/ioport.h>
-#include <linux/param.h> /* for HZ */
-#include <asm/bootinfo.h>
-#include <asm/addrspace.h>
-#include <asm/time.h>
-#include <asm/bcache.h>
-#include <asm/irq.h>
-#include <asm/reboot.h>
-#include <asm/gdb-stub.h>
-#include <asm/debug.h>
-#include <asm/tcube.h>
-
-static void tcube_machine_restart(char *command)
-{
- static void (*back_to_prom) (void) = (void (*)(void))0xbfc00000;
- back_to_prom();
-}
-
-static void tcube_machine_halt(void)
-{
- printk(KERN_CRIT "NEC Electronics Corporation VR5701 SolutionGearII halted.\n");
- while (1) ;
-}
-
-static void tcube_machine_power_off(void)
-{
- printk(KERN_CRIT "NEC Electronics Corporation VR5701 SolutionGearII halted. Please turn off the power.\n");
- while (1) ;
-}
-
-static void __init tcube_time_init(void)
-{
- mips_hpt_frequency = CPU_COUNTER_FREQUENCY;
-}
-
-static void __init tcube_timer_setup(struct irqaction *irq)
-{
- unsigned int count;
- irq->flags |= SA_NODELAY;
-
- /* we are using the cpu counter for timer interrupts */
- setup_irq(7, irq);
-
- /* to generate the first timer interrupt */
- count = read_c0_count();
- write_c0_compare(count + 10000);
-}
-
-#if defined(CONFIG_BLK_DEV_INITRD)
-extern unsigned long __rd_start, __rd_end, initrd_start, initrd_end;
-#endif
-
-static void chk_init_5701_reg(unsigned long addr, unsigned long data)
-{
- unsigned long a = ddb_in32(addr);
-
- if (a != data) {
- printk(KERN_INFO
- "Unexpected 5701 reg : addr = %08lX, expected = %08lX, read = %08lX\n",
- addr + VR5701_IO_BASE, data, a);
- }
-}
-
-static void __init tcube_board_init(void)
-{
- chk_init_5701_reg(0, 0x1e00008f);
- chk_init_5701_reg(PADR_SDRAM01, 0x000000a8);
- chk_init_5701_reg(PADR_LOCALCS0, 0x1f00004c);
- chk_init_5701_reg(LOCAL_CST0, 0x00088622);
- chk_init_5701_reg(LOCAL_CFG, 0x000f0000);
-
- /* setup PCI windows - window0 for MEM/config, window1 for IO */
- ddb_set_pdar(PADR_PCIW0, 0x10000000, 0x08000000, 32, 0, 1);
- ddb_set_pdar(PADR_PCIW1, 0x18000000, 0x00800000, 32, 0, 1);
- ddb_set_pdar(PADR_IOPCIW0, 0x18800000, 0x00800000, 32, 0, 1);
- ddb_set_pdar(PADR_IOPCIW1, 0x19000000, 0x00800000, 32, 0, 1);
- /* ------------ reset PCI bus and BARs ----------------- */
- ddb_pci_reset_bus();
- /* Ext. PCI memory space */
- ddb_out32(PCI_BAR_MEM01, 0x00000008);
- ddb_out8(PCI_MLTIM, 0x40);
-
- ddb_out32(PCI_BAR_LCS0, 0xffffffff);
- ddb_out32(PCI_BAR_LCS1, 0xffffffff);
- ddb_out32(PCI_BAR_LCS2, 0xffffffff);
- ddb_out32(PCI_BAR_LCS3, 0xffffffff);
- /* Int. PCI memory space */
- ddb_out8(IPCI_MLTIM, 0x40);
-
- ddb_out32(IPCI_BAR_LCS0, 0xffffffff);
- ddb_out32(IPCI_BAR_LCS1, 0xffffffff);
- ddb_out32(IPCI_BAR_LCS2, 0xffffffff);
- ddb_out32(IPCI_BAR_LCS3, 0xffffffff);
- ddb_out32(IPCI_BAR_IREG, 0xffffffff);
-
- /*
- * We use pci master register 0 for memory space / config space
- * And we use register 1 for IO space.
- * Note that for memory space, we bump up the pci base address
- * so that we have 1:1 mapping between PCI memory and cpu physical.
- * For PCI IO space, it starts from 0 in PCI IO space but with
- * IO_BASE in CPU physical address space.
- */
- ddb_set_pmr(EPCI_INIT0, DDB_PCICMD_MEM, 0x10000000, DDB_PCI_ACCESS_32);
- ddb_set_pmr(EPCI_INIT1, DDB_PCICMD_IO, 0x00000000, DDB_PCI_ACCESS_32);
- ddb_set_pmr(IPCI_INIT0, DDB_PCICMD_MEM, 0x18800000, DDB_PCI_ACCESS_32);
- ddb_set_pmr(IPCI_INIT1, DDB_PCICMD_IO, 0x01000000, DDB_PCI_ACCESS_32);
-
- /* PCI cross window should be set properly */
- ddb_set_pdar(PCI_BAR_IPCIW0, 0x18800000, 0x00800000, 32, 0, 1);
- ddb_set_pdar(PCI_BAR_IPCIW1, 0x19000000, 0x00800000, 32, 0, 1);
- ddb_set_pdar(IPCI_BAR_EPCIW0, 0x10000000, 0x08000000, 32, 0, 1);
- ddb_set_pdar(IPCI_BAR_EPCIW1, 0x18000000, 0x00800000, 32, 0, 1);
-
- /* setup GPIO */
- ddb_out32(GIU_DIR0, 0xf7ebffdf);
- ddb_out32(GIU_DIR1, 0x000007fa);
- ddb_out32(GIU_FUNCSEL0, 0xf1c07fff);
- ddb_out32(GIU_FUNCSEL1, 0x000007f0);
- chk_init_5701_reg(GIU_DIR0, 0xf7ebffdf);
- chk_init_5701_reg(GIU_DIR1, 0x000007fa);
- chk_init_5701_reg(GIU_FUNCSEL0, 0xf1c07fff);
- chk_init_5701_reg(GIU_FUNCSEL1, 0x000007f0);
-
- /* enable USB input buffers */
- ddb_out32(PIB_MISC, (ddb_in32(PIB_MISC) | 0x00000031));
-}
-
-int __init shima_tcube_setup(void)
-{
- set_io_port_base(0xB8000000);
-
- board_time_init = tcube_time_init;
- board_timer_setup = tcube_timer_setup;
-
- _machine_restart = tcube_machine_restart;
- _machine_halt = tcube_machine_halt;
- _machine_power_off = tcube_machine_power_off;
-
- /* setup resource limits */
- ioport_resource.end = 0x02000000;
- iomem_resource.end = 0xffffffff;
-
- /* Reboot on panic */
- panic_timeout = 30;
-
-#ifdef CONFIG_FB
- conswitchp = &dummy_con;
-#endif
-
- tcube_board_init();
-
-#if defined(CONFIG_BLK_DEV_INITRD)
- initrd_start = (unsigned long)&__rd_start;
- initrd_end = (unsigned long)&__rd_end;
-#endif
- register_pci_controller(&VR5701_ext_controller);
- register_pci_controller(&VR5701_io_controller);
- return 0;
-}
-
-void __init bus_error_init(void)
-{
- /* do nothing */
-}
-
-early_initcall(shima_tcube_setup);
Index: linux-2.6.10/arch/mips/vr5701/vr5701_sg2/Makefile
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/vr5701_sg2/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the NEC Electronics Corporation VR5701 SolutionGearII specific kernel interface routines
+# under Linux.
+#
+
+obj-y += setup.o irq.o int-handler.o irq_vr5701.o
+EXTRA_AFLAGS: = $(CFLAGS)
Index: linux-2.6.10/arch/mips/vr5701/vr5701_sg2/int-handler.S
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/vr5701_sg2/int-handler.S
@@ -0,0 +1,77 @@
+/*
+ * arch/mips/vr5701/vr5701_sg2/int-handler.S
+ *
+ * First-level interrupt dispatcher for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/config.h>
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/vr5701/vr5701_sg2.h>
+
+/*
+ * first level interrupt dispatcher for ocelot board -
+ * We check for the timer first, then check PCI ints A and D.
+ * Then check for serial IRQ and fall through.
+ */
+ .align 5
+ NESTED(vr5701_sg2_handle_int, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+ .set at
+ .set noreorder
+ mfc0 t0, CP0_CAUSE
+ mfc0 t2, CP0_STATUS
+
+ and t0, t2
+
+ andi t1, t0, STATUSF_IP7 /* cpu timer */
+ bnez t1, ll_cputimer_irq
+ andi t1, t0, (STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6 )
+ bnez t1, ll_vr5701_sg2_irq
+ andi t1, t0, STATUSF_IP0 /* software int 0 */
+ bnez t1, ll_cpu_ip0
+ andi t1, t0, STATUSF_IP1 /* software int 1 */
+ bnez t1, ll_cpu_ip1
+ nop
+ .set reorder
+
+ /* wrong alarm or masked ... */
+ j spurious_interrupt
+ nop
+ END(vr5701_sg2_handle_int)
+
+ .align 5
+
+ll_vr5701_sg2_irq:
+ move a0, sp
+ jal vr5701_sg2_irq_dispatch
+ j ret_from_irq
+
+ll_cputimer_irq:
+ li a0, 7
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+
+ll_cpu_ip0:
+ li a0, 0
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cpu_ip1:
+ li a0, 1
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
Index: linux-2.6.10/arch/mips/vr5701/vr5701_sg2/irq.c
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/vr5701_sg2/irq.c
@@ -0,0 +1,146 @@
+/*
+ * arch/mips/vr5701/vr5701_sg2/irq.c
+ *
+ * The irq setup and misc routines for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <asm/system.h>
+#include <asm/mipsregs.h>
+#include <asm/debug.h>
+#include <asm/vr5701/vr5701_sg2.h>
+/*
+ * IRQ mapping
+ *
+ * 0-7: 8 CPU interrupts
+ * 0 - software interrupt 0
+ * 1 - software interrupt 1
+ * 2 - most Vrc5477 interrupts are routed to this pin
+ * 3 - (optional) some other interrupts routed to this pin for debugg
+ * 4 - not used
+ * 5 - not used
+ * 6 - not used
+ * 7 - cpu timer (used by default)
+ *
+ */
+
+void vr5701_sg2_irq_setup(void)
+{
+ pr_debug("NEC Electronics Corporation VR5701 SolutionGearII irq setup invoked.\n");
+
+ /* by default, we disable all interrupts and route all vr5701
+ * interrupts to pin 0 (irq 2) */
+ ddb_out32(INT_ROUTE0, 0);
+ ddb_out32(INT_ROUTE1, 0);
+ ddb_out32(INT_ROUTE2, 0);
+ ddb_out32(INT_ROUTE3, 0);
+ ddb_out32(INT_MASK, 0);
+ ddb_out32(INT_CLR, ~0x0);
+
+ clear_c0_status(0xff00);
+ set_c0_status(0x0400);
+
+ ll_vr5701_irq_route(24, 1);
+ ll_vr5701_irq_enable(24);
+ ll_vr5701_irq_route(25, 1);
+ ll_vr5701_irq_enable(25);
+ ll_vr5701_irq_route(28, 1);
+ ll_vr5701_irq_enable(28);
+ ll_vr5701_irq_route(29, 1);
+ ll_vr5701_irq_enable(29);
+ ll_vr5701_irq_route(30, 1);
+ ll_vr5701_irq_enable(30);
+ ll_vr5701_irq_route(31, 1);
+ ll_vr5701_irq_enable(31);
+ set_c0_status(0x0800);
+ set_except_vector(0, vr5701_sg2_handle_int);
+ /* init all controllers */
+ mips_cpu_irq_init(0);
+ vr5701_irq_init(8);
+}
+
+/*
+ * the first level int-handler will jump here if it is a vr7701 irq
+ */
+
+asmlinkage void vr5701_sg2_irq_dispatch(struct pt_regs *regs)
+{
+ u32 intStatus;
+ u32 bitmask;
+ u32 i;
+ u32 intPCIStatus;
+ if (ddb_in32(INT1_STAT) != 0) {
+ printk(KERN_CRIT "NMI = %x\n", ddb_in32(NMI_STAT));
+ printk(KERN_CRIT "INT0 = %x\n", ddb_in32(INT0_STAT));
+ printk(KERN_CRIT "INT1 = %x\n", ddb_in32(INT1_STAT));
+ printk(KERN_CRIT "INT2 = %x\n", ddb_in32(INT2_STAT));
+ printk(KERN_CRIT "INT3 = %x\n", ddb_in32(INT3_STAT));
+ printk(KERN_CRIT "INT4 = %x\n", ddb_in32(INT4_STAT));
+ printk(KERN_CRIT "EPCI_ERR = %x\n", ddb_in32(EPCI_ERR));
+ printk(KERN_CRIT "IPCI_ERR = %x\n", ddb_in32(IPCI_ERR));
+
+ panic("error interrupt has happened.");
+ }
+
+ intStatus = ddb_in32(INT0_STAT);
+
+ if (intStatus & 1 << 6)
+ goto IRQ_EPCI;
+
+ if (intStatus & 1 << 7)
+ goto IRQ_IPCI;
+
+ IRQ_OTHER:
+ for (i = 0, bitmask = 1; i <= NUM_5701_IRQS; bitmask <<= 1, i++) {
+ /* do we need to "and" with the int mask? */
+ if (intStatus & bitmask) {
+ do_IRQ(8 + i, regs);
+ }
+ }
+ return;
+
+ IRQ_EPCI:
+ intStatus &= ~(1 << 6); /* unset Status flag */
+ intPCIStatus = ddb_in32(EPCI_INTS);
+ for (i = 0, bitmask = 1; i < NUM_5701_EPCI_IRQS; bitmask <<= 1, i++) {
+ if (intPCIStatus & bitmask) {
+ do_IRQ(8 + NUM_5701_IRQS + i, regs);
+ }
+ }
+ if (!intStatus)
+ return;
+
+ IRQ_IPCI:
+ intStatus &= ~(1 << 7);
+ intPCIStatus = ddb_in32(IPCI_INTS);
+ if (!intPCIStatus)
+ goto IRQ_OTHER;
+
+ for (i = 0, bitmask = 1; i < NUM_5701_IPCI_IRQS; bitmask <<= 1, i++) {
+ if (intPCIStatus & bitmask) {
+ do_IRQ(8 + NUM_5701_IRQS + NUM_5701_EPCI_IRQS + i,
+ regs);
+ }
+ }
+
+ if (!intStatus)
+ return;
+
+ goto IRQ_OTHER;
+}
+
+void __init arch_init_irq(void)
+{
+ /* invoke board-specific irq setup */
+ vr5701_sg2_irq_setup();
+}
Index: linux-2.6.10/arch/mips/vr5701/vr5701_sg2/irq_vr5701.c
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/vr5701_sg2/irq_vr5701.c
@@ -0,0 +1,194 @@
+/*
+ * arch/mips/vr5701/vr5701_sg2/irq_vr5701.c
+ *
+ * This file defines the irq handler for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+/*
+ * NEC Electronics Corporation VR5701 SolutionGearII defines 32 IRQs.
+ *
+ */
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+
+#include <asm/debug.h>
+#include <asm/vr5701/vr5701_sg2.h>
+
+static int vr5701_irq_base = -1;
+
+void ll_vr5701_irq_disable(int vr5701_irq, int ack);
+
+static void vr5701_irq_enable(unsigned int irq)
+{
+ ll_vr5701_irq_enable(irq - vr5701_irq_base);
+}
+
+static void vr5701_irq_disable(unsigned int irq)
+{
+ ll_vr5701_irq_disable(irq - vr5701_irq_base, 0);
+}
+
+static unsigned int vr5701_irq_startup(unsigned int irq)
+{
+ vr5701_irq_enable(irq);
+ return 0;
+}
+
+static void vr5701_irq_ack(unsigned int irq)
+{
+ unsigned long flags;
+ local_irq_save(flags);
+
+ /* clear the interrupt bit for edge trigger */
+ /* some irqs require the driver to clear the sources */
+ if (irq < vr5701_irq_base + NUM_5701_IRQ) {
+ ddb_out32(INT_CLR, 1 << (irq - vr5701_irq_base));
+ }
+ /* don't need for PCIs, for they are level triger */
+
+ /* disable interrupt - some handler will re-enable the irq
+ * and if the interrupt is leveled, we will have infinite loop
+ */
+ ll_vr5701_irq_disable(irq - vr5701_irq_base, 1);
+ local_irq_restore(flags);
+}
+
+static void vr5701_irq_end(unsigned int irq)
+{
+ unsigned long flags;
+ local_irq_save(flags);
+
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+ ll_vr5701_irq_enable(irq - vr5701_irq_base);
+ }
+ local_irq_restore(flags);
+}
+
+struct hw_interrupt_type vr5701_irq_type = {
+ "vr5701_irq",
+ vr5701_irq_startup,
+ vr5701_irq_disable,
+ vr5701_irq_enable,
+ vr5701_irq_disable,
+ vr5701_irq_ack,
+ vr5701_irq_end,
+ NULL /* no affinity stuff for UP */
+};
+
+void vr5701_irq_init(u32 irq_base)
+{
+ extern irq_desc_t irq_desc[];
+ u32 i;
+ vr5701_irq_base = irq_base;
+ for (i = irq_base;
+ i < irq_base + NUM_5701_IRQ + NUM_EPCI_IRQ + NUM_IPCI_IRQ; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &vr5701_irq_type;
+ }
+}
+
+int vr5701_irq_to_irq(int irq)
+{
+ return irq + vr5701_irq_base;
+}
+
+void ll_vr5701_irq_route(int vr5701_irq, int ip)
+{
+ u32 reg_value;
+ u32 reg_bitmask;
+ u32 reg_index;
+
+ if (vr5701_irq >= NUM_5701_IRQ) {
+ if (vr5701_irq >= NUM_5701_IRQ + NUM_EPCI_IRQ) {
+ vr5701_irq = 7;
+ } else {
+ vr5701_irq = 6;
+ }
+ }
+ reg_index = INT_ROUTE0 + vr5701_irq / 8 * 4;
+ reg_value = ddb_in32(reg_index);
+ reg_bitmask = 7 << (vr5701_irq % 8 * 4);
+ reg_value &= ~reg_bitmask;
+ reg_value |= ip << (vr5701_irq % 8 * 4);
+ ddb_out32(reg_index, reg_value);
+}
+
+void ll_vr5701_irq_enable(int vr5701_irq)
+{
+ u16 reg_value;
+ u32 reg_bitmask;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ irq_desc[vr5701_irq_base + vr5701_irq].depth++;
+
+ if (vr5701_irq >= NUM_5701_IRQ) {
+ if (vr5701_irq >= NUM_5701_IRQ + NUM_EPCI_IRQ) {
+ reg_value = ddb_in32(IPCI_INTM);
+ reg_bitmask =
+ 1 << (vr5701_irq - NUM_5701_IRQ - NUM_EPCI_IRQ);
+ ddb_out32(IPCI_INTM, reg_value | reg_bitmask);
+ vr5701_irq = 7;
+ } else {
+ reg_value = ddb_in32(EPCI_INTM);
+ reg_bitmask = 1 << (vr5701_irq - NUM_5701_IRQ);
+ ddb_out32(EPCI_INTM, reg_value | reg_bitmask);
+ vr5701_irq = 6;
+ }
+ }
+ reg_value = ddb_in32(INT_MASK);
+ ddb_out32(INT_MASK, reg_value | (1 << vr5701_irq));
+ local_irq_restore(flags);
+}
+
+void ll_vr5701_irq_disable(int vr5701_irq, int ack)
+{
+ u16 reg_value;
+ u32 udummy;
+ u32 reg_bitmask;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ if (!ack) {
+ irq_desc[vr5701_irq_base + vr5701_irq].depth--;
+ if (irq_desc[vr5701_irq_base + vr5701_irq].depth) {
+ local_irq_restore(flags);
+ return;
+ }
+ }
+
+ if (vr5701_irq >= NUM_5701_IRQ) {
+ if (vr5701_irq >= NUM_5701_IRQ + NUM_EPCI_IRQ) {
+ goto DISABLE_IRQ_IPCI;
+ } else {
+ goto DISABLE_IRQ_EPCI;
+ }
+ }
+ reg_value = ddb_in32(INT_MASK);
+ ddb_out32(INT_MASK, reg_value & ~(1 << vr5701_irq));
+ udummy = ddb_in32(INT_MASK);
+ local_irq_restore(flags);
+ return;
+
+ DISABLE_IRQ_IPCI:
+ reg_value = ddb_in32(IPCI_INTM);
+ reg_bitmask = 1 << (vr5701_irq - NUM_5701_IRQ - NUM_EPCI_IRQ);
+ ddb_out32(IPCI_INTM, reg_value & ~reg_bitmask);
+ local_irq_restore(flags);
+ return;
+
+ DISABLE_IRQ_EPCI:
+ reg_value = ddb_in32(EPCI_INTM);
+ reg_bitmask = 1 << (vr5701_irq - NUM_5701_IRQ);
+ ddb_out32(EPCI_INTM, reg_value & ~reg_bitmask);
+ local_irq_restore(flags);
+}
Index: linux-2.6.10/arch/mips/vr5701/vr5701_sg2/setup.c
===================================================================
--- /dev/null
+++ linux-2.6.10/arch/mips/vr5701/vr5701_sg2/setup.c
@@ -0,0 +1,188 @@
+/*
+ * arch/mips/vr5701/vr5701_sg2/setup.c
+ *
+ * Setup file for NEC Electronics Corporation VR5701 SolutionGearII
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/console.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/fs.h> /* for ROOT_DEV */
+#include <linux/ioport.h>
+#include <linux/param.h> /* for HZ */
+#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+#include <asm/time.h>
+#include <asm/bcache.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+#include <asm/gdb-stub.h>
+#include <asm/debug.h>
+#include <asm/vr5701/vr5701_sg2.h>
+
+static void vr5701_sg2_machine_restart(char *command)
+{
+ static void (*back_to_prom) (void) = (void (*)(void))0xbfc00000;
+ back_to_prom();
+}
+
+static void vr5701_sg2_machine_halt(void)
+{
+ printk(KERN_CRIT "NEC Electronics Corporation VR5701 SolutionGearII halted.\n");
+ while (1) ;
+}
+
+static void vr5701_sg2_machine_power_off(void)
+{
+ printk(KERN_CRIT "NEC Electronics Corporation VR5701 SolutionGearII halted. Please turn off the power.\n");
+ while (1) ;
+}
+
+static void __init vr5701_sg2_time_init(void)
+{
+ mips_hpt_frequency = CPU_COUNTER_FREQUENCY;
+}
+
+static void __init vr5701_sg2_timer_setup(struct irqaction *irq)
+{
+ unsigned int count;
+ irq->flags |= SA_NODELAY;
+
+ /* we are using the cpu counter for timer interrupts */
+ setup_irq(7, irq);
+
+ /* to generate the first timer interrupt */
+ count = read_c0_count();
+ write_c0_compare(count + 10000);
+}
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+extern unsigned long __rd_start, __rd_end, initrd_start, initrd_end;
+#endif
+
+static void chk_init_5701_reg(unsigned long addr, unsigned long data)
+{
+ unsigned long a = ddb_in32(addr);
+
+ if (a != data) {
+ printk(KERN_INFO
+ "Unexpected 5701 reg : addr = %08lX, expected = %08lX, read = %08lX\n",
+ addr + VR5701_IO_BASE, data, a);
+ }
+}
+
+static void __init vr5701_sg2_board_init(void)
+{
+ chk_init_5701_reg(0, 0x1e00008f);
+ chk_init_5701_reg(PADR_SDRAM01, 0x000000a8);
+ chk_init_5701_reg(PADR_LOCALCS0, 0x1f00004c);
+ chk_init_5701_reg(LOCAL_CST0, 0x00088622);
+ chk_init_5701_reg(LOCAL_CFG, 0x000f0000);
+
+ /* setup PCI windows - window0 for MEM/config, window1 for IO */
+ ddb_set_pdar(PADR_PCIW0, 0x10000000, 0x08000000, 32, 0, 1);
+ ddb_set_pdar(PADR_PCIW1, 0x18000000, 0x00800000, 32, 0, 1);
+ ddb_set_pdar(PADR_IOPCIW0, 0x18800000, 0x00800000, 32, 0, 1);
+ ddb_set_pdar(PADR_IOPCIW1, 0x19000000, 0x00800000, 32, 0, 1);
+ /* ------------ reset PCI bus and BARs ----------------- */
+ ddb_pci_reset_bus();
+ /* Ext. PCI memory space */
+ ddb_out32(PCI_BAR_MEM01, 0x00000008);
+ ddb_out8(PCI_MLTIM, 0x40);
+
+ ddb_out32(PCI_BAR_LCS0, 0xffffffff);
+ ddb_out32(PCI_BAR_LCS1, 0xffffffff);
+ ddb_out32(PCI_BAR_LCS2, 0xffffffff);
+ ddb_out32(PCI_BAR_LCS3, 0xffffffff);
+ /* Int. PCI memory space */
+ ddb_out8(IPCI_MLTIM, 0x40);
+
+ ddb_out32(IPCI_BAR_LCS0, 0xffffffff);
+ ddb_out32(IPCI_BAR_LCS1, 0xffffffff);
+ ddb_out32(IPCI_BAR_LCS2, 0xffffffff);
+ ddb_out32(IPCI_BAR_LCS3, 0xffffffff);
+ ddb_out32(IPCI_BAR_IREG, 0xffffffff);
+
+ /*
+ * We use pci master register 0 for memory space / config space
+ * And we use register 1 for IO space.
+ * Note that for memory space, we bump up the pci base address
+ * so that we have 1:1 mapping between PCI memory and cpu physical.
+ * For PCI IO space, it starts from 0 in PCI IO space but with
+ * IO_BASE in CPU physical address space.
+ */
+ ddb_set_pmr(EPCI_INIT0, DDB_PCICMD_MEM, 0x10000000, DDB_PCI_ACCESS_32);
+ ddb_set_pmr(EPCI_INIT1, DDB_PCICMD_IO, 0x00000000, DDB_PCI_ACCESS_32);
+ ddb_set_pmr(IPCI_INIT0, DDB_PCICMD_MEM, 0x18800000, DDB_PCI_ACCESS_32);
+ ddb_set_pmr(IPCI_INIT1, DDB_PCICMD_IO, 0x01000000, DDB_PCI_ACCESS_32);
+
+ /* PCI cross window should be set properly */
+ ddb_set_pdar(PCI_BAR_IPCIW0, 0x18800000, 0x00800000, 32, 0, 1);
+ ddb_set_pdar(PCI_BAR_IPCIW1, 0x19000000, 0x00800000, 32, 0, 1);
+ ddb_set_pdar(IPCI_BAR_EPCIW0, 0x10000000, 0x08000000, 32, 0, 1);
+ ddb_set_pdar(IPCI_BAR_EPCIW1, 0x18000000, 0x00800000, 32, 0, 1);
+
+ /* setup GPIO */
+ ddb_out32(GIU_DIR0, 0xf7ebffdf);
+ ddb_out32(GIU_DIR1, 0x000007fa);
+ ddb_out32(GIU_FUNCSEL0, 0xf1c07fff);
+ ddb_out32(GIU_FUNCSEL1, 0x000007f0);
+ chk_init_5701_reg(GIU_DIR0, 0xf7ebffdf);
+ chk_init_5701_reg(GIU_DIR1, 0x000007fa);
+ chk_init_5701_reg(GIU_FUNCSEL0, 0xf1c07fff);
+ chk_init_5701_reg(GIU_FUNCSEL1, 0x000007f0);
+
+ /* enable USB input buffers */
+ ddb_out32(PIB_MISC, (ddb_in32(PIB_MISC) | 0x00000031));
+}
+
+int __init vr5701_sg2_setup(void)
+{
+ set_io_port_base(0xB8000000);
+
+ board_time_init = vr5701_sg2_time_init;
+ board_timer_setup = vr5701_sg2_timer_setup;
+
+ _machine_restart = vr5701_sg2_machine_restart;
+ _machine_halt = vr5701_sg2_machine_halt;
+ _machine_power_off = vr5701_sg2_machine_power_off;
+
+ /* setup resource limits */
+ ioport_resource.end = 0x02000000;
+ iomem_resource.end = 0xffffffff;
+
+ /* Reboot on panic */
+ panic_timeout = 30;
+
+#ifdef CONFIG_FB
+ conswitchp = &dummy_con;
+#endif
+
+ vr5701_sg2_board_init();
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+ initrd_start = (unsigned long)&__rd_start;
+ initrd_end = (unsigned long)&__rd_end;
+#endif
+ register_pci_controller(&VR5701_ext_controller);
+ register_pci_controller(&VR5701_io_controller);
+ return 0;
+}
+
+void __init bus_error_init(void)
+{
+ /* do nothing */
+}
+
+early_initcall(vr5701_sg2_setup);
Index: linux-2.6.10/drivers/ide/Kconfig
===================================================================
--- linux-2.6.10.orig/drivers/ide/Kconfig
+++ linux-2.6.10/drivers/ide/Kconfig
@@ -838,7 +838,7 @@ config BLK_DEV_GAYLE
config BLK_DEV_NEC_VR5701_SG2
tristate "NEC Electronics Corporation VR5701 SolutionGearII IDE interface support"
- depends on TCUBE
+ depends on VR5701_SG2
help
This is the IDE driver for the NEC Electronics Corporation VR5701
SolutionGearII IDE interface.
Index: linux-2.6.10/include/asm-mips/bootinfo.h
===================================================================
--- linux-2.6.10.orig/include/asm-mips/bootinfo.h
+++ linux-2.6.10/include/asm-mips/bootinfo.h
@@ -214,10 +214,10 @@
#define MACH_TITAN_YOSEMITE 1 /* PMC-Sierra Yosemite */
/*
- * Valid machtype for group SHIMA
+ * Valid machtype for group VR5701
*/
-#define MACH_GROUP_SHIMA 24 /* SHIMAFUJI */
-#define MACH_SHIMA_TCUBE 0 /* SHIMAFUJI T-Cube(Vr5701) */
+#define MACH_GROUP_VR5701 24 /* VR5701 */
+#define MACH_VR5701_SG2 0 /* VR5701_SG2 */
#define CL_SIZE COMMAND_LINE_SIZE
Index: linux-2.6.10/include/asm-mips/serial.h
===================================================================
--- linux-2.6.10.orig/include/asm-mips/serial.h
+++ linux-2.6.10/include/asm-mips/serial.h
@@ -412,9 +412,9 @@
#define DDB5477_SERIAL_PORT_DEFNS
#endif
-#ifdef CONFIG_TCUBE
-#include <asm/tcube.h>
-#define TCUBE_SERIAL_PORT_DEFNS \
+#ifdef CONFIG_VR5701_SG2
+#include <asm/vr5701/vr5701_sg2.h>
+#define VR5701_SG2_SERIAL_PORT_DEFNS \
{ baud_base: BASE_BAUD, irq: 16, flags: STD_COM_FLAGS, \
iomem_base: (u8*)0xbe000a00, iomem_reg_shift: 3, \
io_type: SERIAL_IO_MEM},\
@@ -422,7 +422,7 @@
iomem_base: (u8*)0xbe000a40, iomem_reg_shift: 3, \
io_type: SERIAL_IO_MEM},
#else
-#define TCUBE_SERIAL_PORT_DEFNS
+#define VR5701_SG2_SERIAL_PORT_DEFNS
#endif
@@ -455,6 +455,6 @@
MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS \
TXX927_SERIAL_PORT_DEFNS \
AU1000_SERIAL_PORT_DEFNS \
- TCUBE_SERIAL_PORT_DEFNS
+ VR5701_SG2_SERIAL_PORT_DEFNS
#endif /* _ASM_SERIAL_H */
Index: linux-2.6.10/include/asm-mips/tcube.h
===================================================================
--- linux-2.6.10.orig/include/asm-mips/tcube.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * include/asm-mips/tcube.h
- *
- * Flash memory access on NEC Electronics Corporation VR5701 SolutionGearII board.
- *
- * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#ifndef __TCUBE_H
-#define __TCUBE_H
-
-#include <asm/vr5701.h>
-
-#define TCUBE_SDRAM_SIZE 0x10000000
-
-#ifndef __ASSEMBLY__
-#include <asm/delay.h>
-
-/*
- * PCI Master Registers
- */
-
-#define DDB_PCICMD_IACK 0 /* PCI Interrupt Acknowledge */
-#define DDB_PCICMD_IO 1 /* PCI I/O Space */
-#define DDB_PCICMD_MEM 3 /* PCI Memory Space */
-#define DDB_PCICMD_CFG 5 /* PCI Configuration Space */
-
-/*
- * additional options for pci init reg (no shifting needed)
- */
-#define DDB_PCI_CFGTYPE1 0x200 /* for pci init0/1 regs */
-#define DDB_PCI_ACCESS_32 0x10 /* for pci init0/1 regs */
-#define NUM_5701_IRQS 32
-#define NUM_5701_EPCI_IRQ 4
-
-/* A Real Time Clock interface for Linux on NEC Electronics Corporation VR5701 SolutionGearII */
-#define SET_32_BIT 0xffffffff
-#define CLR_32_BIT 0x00000000
-
-#define GPIO_3_INTR (0x1 << 3)
-#define GPIO_4_CE (0x1 << 4)
-#define GPIO_25_S1CLK (0x1 << 25)
-#define GPIO_26_S1DO (0x1 << 26)
-#define GPIO_27_S1DI (0x1 << 27)
-#define GPIO_CSI1_PIN (GPIO_25_S1CLK | GPIO_26_S1DO | GPIO_27_S1DI)
-
-#define CSIn_MODE_CKP (0x1 << 12)
-#define CSIn_MODE_DAP (0x1 << 11)
-#define CSIn_MODE_CKS_MASK (0x7 << 8)
-#define CSIn_MODE_CKS_833333MHZ (0x1 << 8)
-#define CSIn_MODE_CKS_416667MHZ (0x2 << 8)
-#define CSIn_MODE_CKS_208333MHZ (0x3 << 8)
-#define CSIn_MODE_CKS_104167MHZ (0x4 << 8)
-#define CSIn_MODE_CKS_052083MHZ (0x5 << 8)
-#define CSIn_MODE_CKS_0260417HZ (0x6 << 8) /* Default */
-#define CSIn_MODE_CSIE (0x1 << 7)
-#define CSIn_MODE_TRMD (0x1 << 6)
-#define CSIn_MODE_CCL_16 (0x1 << 5)
-#define CSIn_MODE_DIR_LSB (0x1 << 4)
-#define CSIn_MODE_AUTO (0x1 << 2)
-#define CSIn_MODE_CSOT (0x1 << 0)
-
-#define CSIn_INT_CSIEND (0x1 << 15)
-#define CSIn_INT_T_EMP (0x1 << 8)
-#define CSIn_INT_R_OVER (0x1 << 0)
-
-/* IRQs */
-#define ACTIVE_LOW 1
-#define ACTIVE_HIGH 0
-
-#define LEVEL_SENSE 2
-#define EDGE_TRIGGER 0
-
-#define NUM_5701_IRQS 32
-#define NUM_5701_EPCI_IRQS 4
-#define NUM_5701_IPCI_IRQS 8
-#define NUM_5701_IRQ 32
-#define NUM_EPCI_IRQ 4
-#define NUM_IPCI_IRQ 8
-
-#define INTA 0
-#define INTB 1
-#define INTC 2
-#define INTD 3
-#define INTE 4
-
-/* Timers */
-#define CPU_COUNTER_FREQUENCY 166666666
-
-#define ddb_sync io_sync
-#define ddb_out32(x,y) io_out32(x,y)
-#define ddb_out16(x,y) io_out16(x,y)
-#define ddb_out8(x,y) io_out8(x,y)
-#define ddb_in32(x) io_in32(x)
-#define ddb_in16(x) io_in16(x)
-#define ddb_in8(x) io_in8(x)
-
-static inline void io_sync(void)
-{
- asm("sync");
-}
-
-static inline void io_out32(u32 offset, u32 val)
-{
- *(volatile u32 *)(VR5701_IO_BASE + offset) = val;
- io_sync();
-}
-
-static inline u32 io_in32(u32 offset)
-{
- u32 val = *(volatile u32 *)(VR5701_IO_BASE + offset);
- io_sync();
- return val;
-}
-
-static inline void io_out16(u32 offset, u16 val)
-{
- *(volatile u16 *)(VR5701_IO_BASE + offset) = val;
- io_sync();
-}
-
-static inline u16 io_in16(u32 offset)
-{
- u16 val = *(volatile u16 *)(VR5701_IO_BASE + offset);
- io_sync();
- return val;
-}
-
-static inline void io_reset16(unsigned long adr,
- unsigned short val1,
- unsigned delay, unsigned short val2)
-{
- io_out16(adr, val1);
- __delay(delay);
- io_out16(adr, val2);
-}
-
-static inline void io_out8(u32 offset, u8 val)
-{
- *(volatile u8 *)(VR5701_IO_BASE + offset) = val;
- io_sync();
-}
-
-static inline u8 io_in8(u32 offset)
-{
- u8 val = *(volatile u8 *)(VR5701_IO_BASE + offset);
- io_sync();
- return val;
-}
-
-static inline void io_set16(u32 offset, u16 mask, u16 val)
-{
- u16 val0 = io_in16(offset);
- io_out16(offset, (val & mask) | (val0 & ~mask));
-}
-
-static inline void reg_set32(u32 offset, u32 mask, u32 val)
-{
- u32 val0 = io_in32(offset);
- io_out32(offset, (val & mask) | (val0 & ~mask));
-}
-
-static inline void csi1_reset(void)
-{
- /* CSI1 reset */
- reg_set32(CSI1_CNT, 0x00008000, SET_32_BIT); /* set CSIRST bit */
- __delay(100000);
- reg_set32(CSI1_CNT, 0x00008000, CLR_32_BIT); /* clear CSIRST bit */
- /* set clock phase */
- while (io_in32(CSI1_MODE) & 1) ;
- reg_set32(CSI1_MODE, CSIn_MODE_CSIE, CLR_32_BIT);
- reg_set32(CSI1_MODE, CSIn_MODE_CKP, SET_32_BIT);
- reg_set32(CSI1_MODE, CSIn_MODE_CKS_104167MHZ, SET_32_BIT);
- reg_set32(CSI1_MODE, CSIn_MODE_CSIE, SET_32_BIT);
- while (io_in32(CSI1_MODE) & CSIn_MODE_CSOT) ;
-}
-
-extern void ll_vr5701_irq_route(int vr5701_irq, int ip);
-extern void ll_vr5701_irq_enable(int vr5701_irq);
-extern void ddb_set_pdar(u32, u32, u32, int, int, int);
-extern void ddb_set_pmr(u32 pmr, u32 type, u32 addr, u32 options);
-extern void ddb_set_bar(u32 bar, u32 phys, int prefetchable);
-extern void ddb_pci_reset_bus(void);
-extern struct pci_ops VR5701_ext_pci_ops;
-extern struct pci_ops VR5701_io_pci_ops;
-extern struct pci_controller VR5701_ext_controller;
-extern struct pci_controller VR5701_io_controller;
-extern int shima_tcube_setup(void);
-extern void tcube_irq_init(u32 base);
-extern void mips_cpu_irq_init(u32 base);
-extern asmlinkage void tcube_handle_int(void);
-extern void vr5701_irq_init(u32 irq_base);
-extern int panic_timeout;
-
-#endif
-#endif
Index: linux-2.6.10/include/asm-mips/vr5701.h
===================================================================
--- linux-2.6.10.orig/include/asm-mips/vr5701.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * include/asm-mips/vr5701.h
- *
- * A header for NEC Electronics Corporation VR5701 SolutionGearII CPU
- *
- * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#ifndef __VR5701_H
-#define __VR5701_H
-
-#define VR5701_IO_BASE 0xbe000000
-
-/* PADR registers */
-#define PADR_SDRAM01 0x40
-#define PADR_LOCALCS0 0x80
-#define PADR_PCIW0 0xC0
-#define PADR_PCIW1 0xC8
-#define PADR_EPCIW0 0xC0
-#define PADR_IOPCIW0 0xE0
-#define PADR_IOPCIW1 0xE8
-/* INT registers */
-#define INT0_STAT 0x100
-#define INT1_STAT 0x108
-#define INT2_STAT 0x110
-#define INT3_STAT 0x118
-#define INT4_STAT 0x120
-#define NMI_STAT 0x130
-#define INT_CLR 0x140
-#define INT_MASK 0x150
-#define INT_ROUTE0 0x160
-#define INT_ROUTE1 0x168
-#define INT_ROUTE2 0x170
-#define INT_ROUTE3 0x178
-/* LOCAL registers */
-#define LOCAL_CST0 0x400
-#define LOCAL_CFG 0x440
-/* EPCI registers */
-#define EPCI_CTRLH 0x604
-#define EPCI_INIT0 0x610
-#define EPCI_INIT1 0x618
-#define EPCI_ERR 0x628
-#define EPCI_INTS 0x630
-#define EPCI_INTM 0x638
-/* PCI registers */
-#define PCI_MLTIM 0x70D
-#define PCI_BAR_MEM01 0x710
-#define PCI_BAR_LCS0 0x740
-#define PCI_BAR_LCS1 0x748
-#define PCI_BAR_LCS2 0x750
-#define PCI_BAR_LCS3 0x758
-#define PCI_BAR_IPCIW0 0x7A0
-#define PCI_BAR_IPCIW1 0x7A8
-#define PCI_BAR_IREG 0x7C0
-
-/* PIB registers*/
-#define PIB_RESET 0x800
-#define PIB_MISC 0x830
-
-/* GPIO registers*/
-#define GIU_PIO0 0x940
-#define GIU_DIR0 0x950
-#define GIU_DIR1 0x958
-#define GIU_FUNCSEL0 0x960
-#define GIU_FUNCSEL1 0x968
-
-/* CSI1 registers*/
-#define CSI1_MODE 0xB80
-#define CSI1_SIRB 0xB88
-#define CSI1_SOTB 0xB90
-#define CSI1_SOTBF 0xBA0
-#define CSI1_CNT 0xBC0
-#define CSI1_INT 0xBC8
-
-/* IPCI registers*/
-#define IPCI_CTRLH 0xE04
-#define IPCI_INIT0 0xE10
-#define IPCI_INIT1 0xE18
-#define IPCI_ERR 0xE28
-#define IPCI_INTS 0xE30
-#define IPCI_INTM 0xE38
-/* PCI registers */
-#define IPCI_MLTIM 0xF0D
-#define IPCI_BAR_LCS0 0xF40
-#define IPCI_BAR_LCS1 0xF48
-#define IPCI_BAR_LCS2 0xF50
-#define IPCI_BAR_LCS3 0xF58
-#define IPCI_BAR_EPCIW0 0xF80
-#define IPCI_BAR_EPCIW1 0xF88
-#define IPCI_BAR_IREG 0xFC0
-
-#endif /* __VR5701_H */
Index: linux-2.6.10/include/asm-mips/vr5701/vr5701.h
===================================================================
--- /dev/null
+++ linux-2.6.10/include/asm-mips/vr5701/vr5701.h
@@ -0,0 +1,96 @@
+/*
+ * include/asm-mips/vr5701/vr5701.h
+ *
+ * A header for NEC Electronics Corporation VR5701 SolutionGearII CPU
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __VR5701_H
+#define __VR5701_H
+
+#define VR5701_IO_BASE 0xbe000000
+
+/* PADR registers */
+#define PADR_SDRAM01 0x40
+#define PADR_LOCALCS0 0x80
+#define PADR_PCIW0 0xC0
+#define PADR_PCIW1 0xC8
+#define PADR_EPCIW0 0xC0
+#define PADR_IOPCIW0 0xE0
+#define PADR_IOPCIW1 0xE8
+/* INT registers */
+#define INT0_STAT 0x100
+#define INT1_STAT 0x108
+#define INT2_STAT 0x110
+#define INT3_STAT 0x118
+#define INT4_STAT 0x120
+#define NMI_STAT 0x130
+#define INT_CLR 0x140
+#define INT_MASK 0x150
+#define INT_ROUTE0 0x160
+#define INT_ROUTE1 0x168
+#define INT_ROUTE2 0x170
+#define INT_ROUTE3 0x178
+/* LOCAL registers */
+#define LOCAL_CST0 0x400
+#define LOCAL_CFG 0x440
+/* EPCI registers */
+#define EPCI_CTRLH 0x604
+#define EPCI_INIT0 0x610
+#define EPCI_INIT1 0x618
+#define EPCI_ERR 0x628
+#define EPCI_INTS 0x630
+#define EPCI_INTM 0x638
+/* PCI registers */
+#define PCI_MLTIM 0x70D
+#define PCI_BAR_MEM01 0x710
+#define PCI_BAR_LCS0 0x740
+#define PCI_BAR_LCS1 0x748
+#define PCI_BAR_LCS2 0x750
+#define PCI_BAR_LCS3 0x758
+#define PCI_BAR_IPCIW0 0x7A0
+#define PCI_BAR_IPCIW1 0x7A8
+#define PCI_BAR_IREG 0x7C0
+
+/* PIB registers*/
+#define PIB_RESET 0x800
+#define PIB_MISC 0x830
+
+/* GPIO registers*/
+#define GIU_PIO0 0x940
+#define GIU_DIR0 0x950
+#define GIU_DIR1 0x958
+#define GIU_FUNCSEL0 0x960
+#define GIU_FUNCSEL1 0x968
+
+/* CSI1 registers*/
+#define CSI1_MODE 0xB80
+#define CSI1_SIRB 0xB88
+#define CSI1_SOTB 0xB90
+#define CSI1_SOTBF 0xBA0
+#define CSI1_CNT 0xBC0
+#define CSI1_INT 0xBC8
+
+/* IPCI registers*/
+#define IPCI_CTRLH 0xE04
+#define IPCI_INIT0 0xE10
+#define IPCI_INIT1 0xE18
+#define IPCI_ERR 0xE28
+#define IPCI_INTS 0xE30
+#define IPCI_INTM 0xE38
+/* PCI registers */
+#define IPCI_MLTIM 0xF0D
+#define IPCI_BAR_LCS0 0xF40
+#define IPCI_BAR_LCS1 0xF48
+#define IPCI_BAR_LCS2 0xF50
+#define IPCI_BAR_LCS3 0xF58
+#define IPCI_BAR_EPCIW0 0xF80
+#define IPCI_BAR_EPCIW1 0xF88
+#define IPCI_BAR_IREG 0xFC0
+
+#endif /* __VR5701_H */
Index: linux-2.6.10/include/asm-mips/vr5701/vr5701_sg2.h
===================================================================
--- /dev/null
+++ linux-2.6.10/include/asm-mips/vr5701/vr5701_sg2.h
@@ -0,0 +1,200 @@
+/*
+ * include/asm-mips/vr5701/vr5701_sg2.h
+ *
+ * Flash memory access on NEC Electronics Corporation VR5701 SolutionGearII board.
+ *
+ * Author: Sergey Podstavin <spodstavin@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __VR5701_SG2_H
+#define __VR5701_SG2_H
+
+#include <asm/vr5701/vr5701.h>
+
+#define VR5701_SG2_SDRAM_SIZE 0x10000000
+
+#ifndef __ASSEMBLY__
+#include <asm/delay.h>
+
+/*
+ * PCI Master Registers
+ */
+
+#define DDB_PCICMD_IACK 0 /* PCI Interrupt Acknowledge */
+#define DDB_PCICMD_IO 1 /* PCI I/O Space */
+#define DDB_PCICMD_MEM 3 /* PCI Memory Space */
+#define DDB_PCICMD_CFG 5 /* PCI Configuration Space */
+
+/*
+ * additional options for pci init reg (no shifting needed)
+ */
+#define DDB_PCI_CFGTYPE1 0x200 /* for pci init0/1 regs */
+#define DDB_PCI_ACCESS_32 0x10 /* for pci init0/1 regs */
+#define NUM_5701_IRQS 32
+#define NUM_5701_EPCI_IRQ 4
+
+/* A Real Time Clock interface for Linux on NEC Electronics Corporation VR5701 SolutionGearII */
+#define SET_32_BIT 0xffffffff
+#define CLR_32_BIT 0x00000000
+
+#define GPIO_3_INTR (0x1 << 3)
+#define GPIO_4_CE (0x1 << 4)
+#define GPIO_25_S1CLK (0x1 << 25)
+#define GPIO_26_S1DO (0x1 << 26)
+#define GPIO_27_S1DI (0x1 << 27)
+#define GPIO_CSI1_PIN (GPIO_25_S1CLK | GPIO_26_S1DO | GPIO_27_S1DI)
+
+#define CSIn_MODE_CKP (0x1 << 12)
+#define CSIn_MODE_DAP (0x1 << 11)
+#define CSIn_MODE_CKS_MASK (0x7 << 8)
+#define CSIn_MODE_CKS_833333MHZ (0x1 << 8)
+#define CSIn_MODE_CKS_416667MHZ (0x2 << 8)
+#define CSIn_MODE_CKS_208333MHZ (0x3 << 8)
+#define CSIn_MODE_CKS_104167MHZ (0x4 << 8)
+#define CSIn_MODE_CKS_052083MHZ (0x5 << 8)
+#define CSIn_MODE_CKS_0260417HZ (0x6 << 8) /* Default */
+#define CSIn_MODE_CSIE (0x1 << 7)
+#define CSIn_MODE_TRMD (0x1 << 6)
+#define CSIn_MODE_CCL_16 (0x1 << 5)
+#define CSIn_MODE_DIR_LSB (0x1 << 4)
+#define CSIn_MODE_AUTO (0x1 << 2)
+#define CSIn_MODE_CSOT (0x1 << 0)
+
+#define CSIn_INT_CSIEND (0x1 << 15)
+#define CSIn_INT_T_EMP (0x1 << 8)
+#define CSIn_INT_R_OVER (0x1 << 0)
+
+/* IRQs */
+#define ACTIVE_LOW 1
+#define ACTIVE_HIGH 0
+
+#define LEVEL_SENSE 2
+#define EDGE_TRIGGER 0
+
+#define NUM_5701_IRQS 32
+#define NUM_5701_EPCI_IRQS 4
+#define NUM_5701_IPCI_IRQS 8
+#define NUM_5701_IRQ 32
+#define NUM_EPCI_IRQ 4
+#define NUM_IPCI_IRQ 8
+
+#define INTA 0
+#define INTB 1
+#define INTC 2
+#define INTD 3
+#define INTE 4
+
+/* Timers */
+#define CPU_COUNTER_FREQUENCY 166666666
+
+#define ddb_sync io_sync
+#define ddb_out32(x,y) io_out32(x,y)
+#define ddb_out16(x,y) io_out16(x,y)
+#define ddb_out8(x,y) io_out8(x,y)
+#define ddb_in32(x) io_in32(x)
+#define ddb_in16(x) io_in16(x)
+#define ddb_in8(x) io_in8(x)
+
+static inline void io_sync(void)
+{
+ asm("sync");
+}
+
+static inline void io_out32(u32 offset, u32 val)
+{
+ *(volatile u32 *)(VR5701_IO_BASE + offset) = val;
+ io_sync();
+}
+
+static inline u32 io_in32(u32 offset)
+{
+ u32 val = *(volatile u32 *)(VR5701_IO_BASE + offset);
+ io_sync();
+ return val;
+}
+
+static inline void io_out16(u32 offset, u16 val)
+{
+ *(volatile u16 *)(VR5701_IO_BASE + offset) = val;
+ io_sync();
+}
+
+static inline u16 io_in16(u32 offset)
+{
+ u16 val = *(volatile u16 *)(VR5701_IO_BASE + offset);
+ io_sync();
+ return val;
+}
+
+static inline void io_reset16(unsigned long adr,
+ unsigned short val1,
+ unsigned delay, unsigned short val2)
+{
+ io_out16(adr, val1);
+ __delay(delay);
+ io_out16(adr, val2);
+}
+
+static inline void io_out8(u32 offset, u8 val)
+{
+ *(volatile u8 *)(VR5701_IO_BASE + offset) = val;
+ io_sync();
+}
+
+static inline u8 io_in8(u32 offset)
+{
+ u8 val = *(volatile u8 *)(VR5701_IO_BASE + offset);
+ io_sync();
+ return val;
+}
+
+static inline void io_set16(u32 offset, u16 mask, u16 val)
+{
+ u16 val0 = io_in16(offset);
+ io_out16(offset, (val & mask) | (val0 & ~mask));
+}
+
+static inline void reg_set32(u32 offset, u32 mask, u32 val)
+{
+ u32 val0 = io_in32(offset);
+ io_out32(offset, (val & mask) | (val0 & ~mask));
+}
+
+static inline void csi1_reset(void)
+{
+ /* CSI1 reset */
+ reg_set32(CSI1_CNT, 0x00008000, SET_32_BIT); /* set CSIRST bit */
+ __delay(100000);
+ reg_set32(CSI1_CNT, 0x00008000, CLR_32_BIT); /* clear CSIRST bit */
+ /* set clock phase */
+ while (io_in32(CSI1_MODE) & 1) ;
+ reg_set32(CSI1_MODE, CSIn_MODE_CSIE, CLR_32_BIT);
+ reg_set32(CSI1_MODE, CSIn_MODE_CKP, SET_32_BIT);
+ reg_set32(CSI1_MODE, CSIn_MODE_CKS_104167MHZ, SET_32_BIT);
+ reg_set32(CSI1_MODE, CSIn_MODE_CSIE, SET_32_BIT);
+ while (io_in32(CSI1_MODE) & CSIn_MODE_CSOT) ;
+}
+
+extern void ll_vr5701_irq_route(int vr5701_irq, int ip);
+extern void ll_vr5701_irq_enable(int vr5701_irq);
+extern void ddb_set_pdar(u32, u32, u32, int, int, int);
+extern void ddb_set_pmr(u32 pmr, u32 type, u32 addr, u32 options);
+extern void ddb_set_bar(u32 bar, u32 phys, int prefetchable);
+extern void ddb_pci_reset_bus(void);
+extern struct pci_ops VR5701_ext_pci_ops;
+extern struct pci_ops VR5701_io_pci_ops;
+extern struct pci_controller VR5701_ext_controller;
+extern struct pci_controller VR5701_io_controller;
+extern int vr5701_sg2_setup(void);
+extern void vr5701_sg2_irq_init(u32 base);
+extern void mips_cpu_irq_init(u32 base);
+extern asmlinkage void vr5701_sg2_handle_int(void);
+extern void vr5701_irq_init(u32 irq_base);
+extern int panic_timeout;
+
+#endif
+#endif
Index: linux-2.6.10/include/linux/lsppatchlevel.h
===================================================================
--- linux-2.6.10.orig/include/linux/lsppatchlevel.h
+++ linux-2.6.10/include/linux/lsppatchlevel.h
@@ -6,4 +6,4 @@
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
-#define LSP_PATCH_LEVEL "9"
+#define LSP_PATCH_LEVEL "10"
Index: linux-2.6.10/mvl_patches/pro-0010.c
===================================================================
--- /dev/null
+++ linux-2.6.10/mvl_patches/pro-0010.c
@@ -0,0 +1,16 @@
+/*
+ * Author: MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/init.h>
+#include <linux/mvl_patch.h>
+
+static __init int regpatch(void)
+{
+ return mvl_register_patch(10);
+}
+module_init(regpatch);
Index: linux-2.6.10/sound/oss/Kconfig
===================================================================
--- linux-2.6.10.orig/sound/oss/Kconfig
+++ linux-2.6.10/sound/oss/Kconfig
@@ -235,7 +235,7 @@ config SOUND_VRC5477
config SOUND_VR5701
tristate "NEC Electronics Corporation VR5701 SolutionGearII AC97 sound"
- depends on SOUND_PRIME!=n && TCUBE && SOUND
+ depends on SOUND_PRIME!=n && VR5701_SG2 && SOUND
help
Say Y here to enable sound support for the NEC Electronics Corporation
VR5701 SolutionGearII AC97 sound. Works with the AC97 codec.
^ permalink raw reply [flat|nested] 9+ messages in thread* NEC VR5701 support
@ 2006-02-23 15:43 Sergey Podstavin
0 siblings, 0 replies; 9+ messages in thread
From: Sergey Podstavin @ 2006-02-23 15:43 UTC (permalink / raw)
To: linux-mips
[-- Attachment #1: Type: text/plain, Size: 1 bytes --]
[-- Attachment #2: pro_mips_nec_vr5701_serial_fix.patch --]
[-- Type: text/x-patch, Size: 2056 bytes --]
Source: MontaVista Software, Inc. Sergey Podstavin <spodstavin@ru.mvista.com>
MR: 14908
Type: Defect Fix
Disposition: needs submitting to linuxmips-embedded mailing list
Signed-off-by: Sergey Podstavin <spodstavin@ru.mvista.com>
Description:
A large file transfers with errors via UART on 115200 fix
Index: linux-2.6.10/arch/mips/vr5701/vr5701_sg2/irq.c
===================================================================
--- linux-2.6.10.orig/arch/mips/vr5701/vr5701_sg2/irq.c
+++ linux-2.6.10/arch/mips/vr5701/vr5701_sg2/irq.c
@@ -79,18 +79,6 @@ asmlinkage void vr5701_sg2_irq_dispatch(
u32 bitmask;
u32 i;
u32 intPCIStatus;
- if (ddb_in32(INT1_STAT) != 0) {
- printk(KERN_CRIT "NMI = %x\n", ddb_in32(NMI_STAT));
- printk(KERN_CRIT "INT0 = %x\n", ddb_in32(INT0_STAT));
- printk(KERN_CRIT "INT1 = %x\n", ddb_in32(INT1_STAT));
- printk(KERN_CRIT "INT2 = %x\n", ddb_in32(INT2_STAT));
- printk(KERN_CRIT "INT3 = %x\n", ddb_in32(INT3_STAT));
- printk(KERN_CRIT "INT4 = %x\n", ddb_in32(INT4_STAT));
- printk(KERN_CRIT "EPCI_ERR = %x\n", ddb_in32(EPCI_ERR));
- printk(KERN_CRIT "IPCI_ERR = %x\n", ddb_in32(IPCI_ERR));
-
- panic("error interrupt has happened.");
- }
intStatus = ddb_in32(INT0_STAT);
@@ -100,7 +88,6 @@ asmlinkage void vr5701_sg2_irq_dispatch(
if (intStatus & 1 << 7)
goto IRQ_IPCI;
- IRQ_OTHER:
for (i = 0, bitmask = 1; i <= NUM_5701_IRQS; bitmask <<= 1, i++) {
/* do we need to "and" with the int mask? */
if (intStatus & bitmask) {
@@ -117,26 +104,18 @@ asmlinkage void vr5701_sg2_irq_dispatch(
do_IRQ(8 + NUM_5701_IRQS + i, regs);
}
}
- if (!intStatus)
- return;
+ return;
IRQ_IPCI:
intStatus &= ~(1 << 7);
intPCIStatus = ddb_in32(IPCI_INTS);
- if (!intPCIStatus)
- goto IRQ_OTHER;
-
for (i = 0, bitmask = 1; i < NUM_5701_IPCI_IRQS; bitmask <<= 1, i++) {
if (intPCIStatus & bitmask) {
do_IRQ(8 + NUM_5701_IRQS + NUM_5701_EPCI_IRQS + i,
regs);
}
}
-
- if (!intStatus)
- return;
-
- goto IRQ_OTHER;
+ return;
}
void __init arch_init_irq(void)
^ permalink raw reply [flat|nested] 9+ messages in thread* NEC VR5701 support
@ 2006-02-23 15:43 Sergey Podstavin
0 siblings, 0 replies; 9+ messages in thread
From: Sergey Podstavin @ 2006-02-23 15:43 UTC (permalink / raw)
To: linux-mips
[-- Attachment #1: Type: text/plain, Size: 1 bytes --]
[-- Attachment #2: pro_mips_nec_vr5701_sound_fix.patch --]
[-- Type: text/x-patch, Size: 11689 bytes --]
Source: MontaVista Software, Inc.
MR: 14926
Type: Defect Fix
Disposition: needs submitting to linuxmips-embedded mailing list
Signed-off-by: Aleksey Makarov <makarov@ru.mvista.com>
Description:
Fixes bug with sound on 11025 and 22050 rates on NEC vr5701.
Index: linux-2.6.10/include/linux/lsppatchlevel.h
===================================================================
--- linux-2.6.10.orig/include/linux/lsppatchlevel.h
+++ linux-2.6.10/include/linux/lsppatchlevel.h
@@ -6,4 +6,4 @@
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
-#define LSP_PATCH_LEVEL "11"
+#define LSP_PATCH_LEVEL "12"
Index: linux-2.6.10/mvl_patches/pro-0012.c
===================================================================
--- /dev/null
+++ linux-2.6.10/mvl_patches/pro-0012.c
@@ -0,0 +1,16 @@
+/*
+ * Author: MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/init.h>
+#include <linux/mvl_patch.h>
+
+static __init int regpatch(void)
+{
+ return mvl_register_patch(12);
+}
+module_init(regpatch);
Index: linux-2.6.10/sound/pci/vr5701/nec_vr5701_sg2.c
===================================================================
--- linux-2.6.10.orig/sound/pci/vr5701/nec_vr5701_sg2.c
+++ linux-2.6.10/sound/pci/vr5701/nec_vr5701_sg2.c
@@ -89,6 +89,28 @@ static int snd_vr5701_ac97(vr5701_t *chi
return snd_ac97_mixer(bus, &ac97, &chip->ac97);
}
+static int set_constraints(snd_pcm_substream_t *substream)
+{
+ int err;
+
+ err = snd_pcm_hw_constraint_step(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 0x10);
+ if( err < 0 )
+ return err;
+
+ err = snd_pcm_hw_constraint_step(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 0x40);
+ if( err < 0 )
+ return err;
+
+ err = snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
+ if( err < 0 )
+ return err;
+
+ return 0;
+}
+
/* open callback */
static int snd_vr5701_playback_open(snd_pcm_substream_t *substream)
{
@@ -97,8 +119,7 @@ static int snd_vr5701_playback_open(snd_
substream->runtime->hw = snd_vr5701_playback_hw;
chip->next_playback = 0;
- return (snd_pcm_hw_constraint_list(substream->runtime, 0,
- SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0);
+ return set_constraints( substream );
}
@@ -110,8 +131,7 @@ static int snd_vr5701_capture_open(snd_p
substream->runtime->hw = snd_vr5701_capture_hw;
chip->next_capture = 0;
- return (snd_pcm_hw_constraint_list(substream->runtime, 0,
- SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0);
+ return set_constraints( substream );
}
/* hw_params callback */
@@ -215,6 +235,42 @@ static int snd_vr5701_capture_close(snd_
return 0;
}
+static inline void playback_next_position(snd_pcm_substream_t *substream, vr5701_t *chip)
+{
+ chip->next_playback = chip->next_playback ? 0 :
+ frames_to_bytes(substream->runtime, substream->runtime->period_size);
+}
+
+static inline void capture_next_position(snd_pcm_substream_t *substream, vr5701_t *chip)
+{
+ chip->next_capture = chip->next_capture ? 0 :
+ frames_to_bytes(substream->runtime, substream->runtime->period_size);
+}
+
+static inline void playback_setup_next(snd_pcm_substream_t *substream, vr5701_t *chip)
+{
+ u32 ch2_offset = (substream->runtime->channels == 1) ? 0 :
+ substream->runtime->dma_bytes/2;
+
+ outl(substream->runtime->dma_addr + chip->next_playback,
+ chip->port + vr5701_DAC1_BADDR);
+ outl(substream->runtime->dma_addr + chip->next_playback + ch2_offset,
+ chip->port + vr5701_DAC2_BADDR);
+}
+
+static inline void capture_setup_next(snd_pcm_substream_t *substream, vr5701_t *chip)
+{
+ if (substream->runtime->channels == 1) {
+ outl(substream->runtime->dma_addr + chip->next_capture,
+ chip->port + vr5701_ADC1_BADDR);
+ } else {
+ outl(substream->runtime->dma_addr+ chip->next_capture,
+ chip->port + vr5701_ADC1_BADDR);
+ outl(substream->runtime->dma_addr + substream->runtime->dma_bytes/2
+ + chip->next_capture, chip->port + vr5701_ADC2_BADDR);
+ }
+}
+
static void vr5701_dma_start_playback(snd_pcm_substream_t *substream)
{
u32 temp;
@@ -230,18 +286,7 @@ static void vr5701_dma_start_playback(sn
temp |= vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END;
outl(temp, chip->port + vr5701_INT_MASK);
- /* setup dma base addr */
- if (substream->runtime->channels == 1) {
- outl(substream->runtime->dma_addr + chip->next_playback,
- chip->port + vr5701_DAC1_BADDR);
- outl(substream->runtime->dma_addr + chip->next_playback,
- chip->port + vr5701_DAC2_BADDR);
- } else {
- outl(substream->runtime->dma_addr + chip->next_playback,
- chip->port + vr5701_DAC1_BADDR);
- outl(substream->runtime->dma_addr + substream->runtime->dma_bytes/2
- + chip->next_playback, chip->port + vr5701_DAC2_BADDR);
- }
+ playback_setup_next( substream, chip );
/* set dma length, in the unit of 0x10 bytes */
period_size = (frames_to_bytes(substream->runtime,
@@ -258,27 +303,10 @@ static void vr5701_dma_start_playback(sn
temp |= (vr5701_CTRL_DAC1ENB | vr5701_CTRL_DAC2ENB);
outl(temp, chip->port + vr5701_CTRL);
- /* it is time to setup next dma transfer */
- temp = chip->next_playback + frames_to_bytes(substream->runtime,
- substream->runtime->period_size);
+ playback_next_position( substream, chip );
+ playback_setup_next( substream, chip );
+ playback_next_position( substream, chip );
- if (substream->runtime->channels == 1) {
- if (temp >= substream->runtime->dma_bytes) {
- temp = 0;
- }
- outl(substream->runtime->dma_addr + temp,
- chip->port + vr5701_DAC1_BADDR);
- outl(substream->runtime->dma_addr + temp,
- chip->port + vr5701_DAC2_BADDR);
- } else {
- if (temp >= substream->runtime->dma_bytes/2) {
- temp = 0;
- }
- outl(substream->runtime->dma_addr + temp,
- chip->port + vr5701_DAC1_BADDR);
- outl(substream->runtime->dma_addr + substream->runtime->dma_bytes/2
- + temp, chip->port + vr5701_DAC2_BADDR);
- }
return ;
}
@@ -297,16 +325,7 @@ static void vr5701_dma_start_capture(snd
temp |= vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END;
outl(temp, chip->port + vr5701_INT_MASK);
- /* setup dma base addr */
- if (substream->runtime->channels == 1) {
- outl(substream->runtime->dma_addr + chip->next_capture,
- chip->port + vr5701_ADC1_BADDR);
- } else {
- outl(substream->runtime->dma_addr+ chip->next_capture,
- chip->port + vr5701_ADC1_BADDR);
- outl(substream->runtime->dma_addr + substream->runtime->dma_bytes/2
- + chip->next_capture, chip->port + vr5701_ADC2_BADDR);
- }
+ capture_setup_next( substream, chip );
/* set dma length, in the unit of 0x10 bytes */
period_size = (frames_to_bytes(substream->runtime,
@@ -331,24 +350,10 @@ static void vr5701_dma_start_capture(snd
temp |= (vr5701_CTRL_ADC1ENB | vr5701_CTRL_ADC2ENB);
outl(temp, chip->port + vr5701_CTRL);
- /* it is time to setup next dma transfer */
- temp = chip->next_capture + frames_to_bytes(substream->runtime,
- substream->runtime->period_size);
- if (substream->runtime->channels == 1) {
- if (temp >= substream->runtime->dma_bytes) {
- temp = 0;
- }
- outl(substream->runtime->dma_addr + temp,
- chip->port + vr5701_ADC1_BADDR);
- } else {
- if (temp >= substream->runtime->dma_bytes/2) {
- temp = 0;
- }
- outl(substream->runtime->dma_addr + temp,
- chip->port + vr5701_ADC1_BADDR);
- outl(substream->runtime->dma_addr + substream->runtime->dma_bytes/2
- + temp, chip->port + vr5701_ADC2_BADDR);
- }
+ capture_next_position( substream, chip );
+ capture_setup_next( substream, chip );
+ capture_next_position( substream, chip );
+
return ;
}
@@ -474,91 +479,20 @@ static int snd_vr5701_dev_free(snd_devic
vr5701_t *chip = device->device_data;
return snd_vr5701_free(chip);
}
-static void vr5701_ac97_adc_interrupt(struct snd_vr5701 *chip)
+static inline void vr5701_ac97_adc_interrupt(struct snd_vr5701 *chip)
{
- unsigned temp;
-
- /* set the base addr for next DMA transfer */
- temp = chip->next_capture + 2*(frames_to_bytes(chip->substream[CAPTURE]->runtime,
- chip->substream[CAPTURE]->runtime->period_size));
- if (chip->substream[CAPTURE]->runtime->channels == 1) {
- if (temp >= chip->substream[CAPTURE]->runtime->dma_bytes) {
- temp -= chip->substream[CAPTURE]->runtime->dma_bytes;
- }
- } else {
- if (temp >= chip->substream[CAPTURE]->runtime->dma_bytes/2) {
- temp -= chip->substream[CAPTURE]->runtime->dma_bytes/2;
- }
- }
-
- if (chip->substream[CAPTURE]->runtime->channels == 1) {
- outl(chip->substream[CAPTURE]->runtime->dma_addr
- + temp, chip->port + vr5701_ADC1_BADDR);
- } else {
- outl(chip->substream[CAPTURE]->runtime->dma_addr
- + temp, chip->port + vr5701_ADC1_BADDR);
- outl(chip->substream[CAPTURE]->runtime->dma_addr
- + chip->substream[CAPTURE]->runtime->dma_bytes/2+ temp,
- chip->port + vr5701_ADC2_BADDR);
- }
-
- /* adjust next pointer */
- chip->next_capture += frames_to_bytes(chip->substream[CAPTURE]->runtime,
- chip->substream[CAPTURE]->runtime->period_size);
- if (chip->substream[CAPTURE]->runtime->channels == 1) {
- if (chip->next_capture >= chip->substream[CAPTURE]->runtime->dma_bytes){
- chip->next_capture = 0;
- }
- } else {
- if (chip->next_capture >= chip->substream[CAPTURE]->runtime->dma_bytes/2){
- chip->next_capture = 0;
- }
- }
+ snd_pcm_substream_t * substream = chip->substream[CAPTURE];
+ capture_setup_next( substream, chip );
+ capture_next_position( substream, chip );
}
-static void vr5701_ac97_dac_interrupt(struct snd_vr5701 *chip)
+static inline void vr5701_ac97_dac_interrupt(struct snd_vr5701 *chip)
{
- unsigned temp;
-
- /* let us set for next next DMA transfer */
- temp = chip->next_playback + 2*(frames_to_bytes(chip->substream[PLAYBACK]->runtime,
- chip->substream[PLAYBACK]->runtime->period_size));
- if (chip->substream[PLAYBACK]->runtime->channels == 1) {
- if (temp >= chip->substream[PLAYBACK]->runtime->dma_bytes) {
- temp -= chip->substream[PLAYBACK]->runtime->dma_bytes;
- }
- } else {
- if (temp >= chip->substream[PLAYBACK]->runtime->dma_bytes/2) {
- temp -= chip->substream[PLAYBACK]->runtime->dma_bytes/2;
- }
- }
-
- if (chip->substream[PLAYBACK]->runtime->channels == 1) {
- outl(chip->substream[PLAYBACK]->runtime->dma_addr
- + temp, chip->port + vr5701_DAC1_BADDR);
- outl(chip->substream[PLAYBACK]->runtime->dma_addr
- + temp, chip->port + vr5701_DAC2_BADDR);
- } else {
- outl(chip->substream[PLAYBACK]->runtime->dma_addr
- + temp, chip->port + vr5701_DAC1_BADDR);
- outl(chip->substream[PLAYBACK]->runtime->dma_addr
- + chip->substream[PLAYBACK]->runtime->dma_bytes/2
- + temp, chip->port + vr5701_DAC2_BADDR);
- }
-
- /* adjust next pointer */
- chip->next_playback += frames_to_bytes(chip->substream[PLAYBACK]->runtime,
- chip->substream[PLAYBACK]->runtime->period_size);
- if (chip->substream[PLAYBACK]->runtime->channels == 1) {
- if (chip->next_playback >= chip->substream[PLAYBACK]->runtime->dma_bytes){
- chip->next_playback = 0;
- }
- } else {
- if (chip->next_playback >= chip->substream[PLAYBACK]->runtime->dma_bytes/2){
- chip->next_playback = 0;
- }
- }
+ snd_pcm_substream_t * substream = chip->substream[PLAYBACK];
+ playback_setup_next( substream, chip );
+ playback_next_position( substream, chip );
}
+
static irqreturn_t snd_vr5701_interrupt(int irq, void *dev_id,
struct pt_regs *regs)
{
^ permalink raw reply [flat|nested] 9+ messages in thread* NEC VR5701 support
@ 2006-02-23 15:44 Sergey Podstavin
0 siblings, 0 replies; 9+ messages in thread
From: Sergey Podstavin @ 2006-02-23 15:44 UTC (permalink / raw)
To: linux-mips
[-- Attachment #1: Type: text/plain, Size: 1 bytes --]
[-- Attachment #2: pro_mips_nec_vr5701_sound_recording_fix.patch --]
[-- Type: text/x-patch, Size: 1971 bytes --]
Source: MontaVista Software, Inc. Igor Goryachev <igoryachev@ru.mvista.com>
MR: 16114
Type: Defect Fix
Disposition: needs submitting to linuxmips-embedded mailing list
Signed-off-by: Igor Goryachev <igoryachev@ru.mvista.com>
Description:
Fixes bug with sound recording on NEC vr5701.
Index: linux-2.6.10/include/linux/lsppatchlevel.h
===================================================================
--- linux-2.6.10.orig/include/linux/lsppatchlevel.h
+++ linux-2.6.10/include/linux/lsppatchlevel.h
@@ -6,4 +6,4 @@
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
-#define LSP_PATCH_LEVEL "10"
+#define LSP_PATCH_LEVEL "11"
Index: linux-2.6.10/mvl_patches/pro-0011.c
===================================================================
--- /dev/null
+++ linux-2.6.10/mvl_patches/pro-0011.c
@@ -0,0 +1,16 @@
+/*
+ * Author: MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/init.h>
+#include <linux/mvl_patch.h>
+
+static __init int regpatch(void)
+{
+ return mvl_register_patch(11);
+}
+module_init(regpatch);
Index: linux-2.6.10/sound/pci/vr5701/nec_vr5701_sg2.h
===================================================================
--- linux-2.6.10.orig/sound/pci/vr5701/nec_vr5701_sg2.h
+++ linux-2.6.10/sound/pci/vr5701/nec_vr5701_sg2.h
@@ -138,7 +138,7 @@ static snd_pcm_hardware_t snd_vr5701_pla
/* hardware definition */
static snd_pcm_hardware_t snd_vr5701_capture_hw = {
.info = (SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_NONINTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
^ permalink raw reply [flat|nested] 9+ messages in thread* NEC VR5701 support
@ 2006-02-23 15:45 Sergey Podstavin
0 siblings, 0 replies; 9+ messages in thread
From: Sergey Podstavin @ 2006-02-23 15:45 UTC (permalink / raw)
To: linux-mips
[-- Attachment #1: Type: text/plain, Size: 1 bytes --]
[-- Attachment #2: pro_mips_nec_vr5701_usb_fix.patch --]
[-- Type: text/x-patch, Size: 2062 bytes --]
Source: MontaVista Software, Inc. Igor Goryachev <igoryachev@ru.mvista.com>
MR: 15905
Type: Defect Fix
Disposition: needs submitting to linuxmips-embedded mailing list
Signed-off-by: Igor Goryachev <igoryachev@ru.mvista.com>
Description:
Fixes USB host behaviour on NEC vr5701.
Index: linux-2.6.10/arch/mips/vr5701/tcube/setup.c
===================================================================
--- linux-2.6.10.orig/arch/mips/vr5701/tcube/setup.c
+++ linux-2.6.10/arch/mips/vr5701/tcube/setup.c
@@ -136,11 +136,11 @@ static void __init tcube_board_init(void
/* setup GPIO */
ddb_out32(GIU_DIR0, 0xf7ebffdf);
ddb_out32(GIU_DIR1, 0x000007fa);
- ddb_out32(GIU_FUNCSEL0, 0xf1c1ffff);
+ ddb_out32(GIU_FUNCSEL0, 0xf1c07fff);
ddb_out32(GIU_FUNCSEL1, 0x000007f0);
chk_init_5701_reg(GIU_DIR0, 0xf7ebffdf);
chk_init_5701_reg(GIU_DIR1, 0x000007fa);
- chk_init_5701_reg(GIU_FUNCSEL0, 0xf1c1ffff);
+ chk_init_5701_reg(GIU_FUNCSEL0, 0xf1c07fff);
chk_init_5701_reg(GIU_FUNCSEL1, 0x000007f0);
/* enable USB input buffers */
Index: linux-2.6.10/include/linux/lsppatchlevel.h
===================================================================
--- linux-2.6.10.orig/include/linux/lsppatchlevel.h
+++ linux-2.6.10/include/linux/lsppatchlevel.h
@@ -6,4 +6,4 @@
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
-#define LSP_PATCH_LEVEL "8"
+#define LSP_PATCH_LEVEL "9"
Index: linux-2.6.10/mvl_patches/pro-0009.c
===================================================================
--- /dev/null
+++ linux-2.6.10/mvl_patches/pro-0009.c
@@ -0,0 +1,16 @@
+/*
+ * Author: MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/init.h>
+#include <linux/mvl_patch.h>
+
+static __init int regpatch(void)
+{
+ return mvl_register_patch(9);
+}
+module_init(regpatch);
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2006-02-23 15:40 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-02-23 15:36 NEC VR5701 support Sergey Podstavin
-- strict thread matches above, loose matches on Subject: below --
2006-02-23 15:38 Sergey Podstavin
2006-02-23 15:39 Sergey Podstavin
2006-02-23 15:39 Sergey Podstavin
2006-02-23 15:41 Sergey Podstavin
2006-02-23 15:43 Sergey Podstavin
2006-02-23 15:43 Sergey Podstavin
2006-02-23 15:44 Sergey Podstavin
2006-02-23 15:45 Sergey Podstavin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox