diff options
| author | florian <florian@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2008-07-15 17:17:04 +0000 | 
|---|---|---|
| committer | florian <florian@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2008-07-15 17:17:04 +0000 | 
| commit | 42c88ed264e86b3e8287f85e2099bc2ca7c5f51d (patch) | |
| tree | 03c3dac161ce721fd65cb2f2d967eda861999b74 /target/linux/rb532/files-2.6.23/arch | |
| parent | 69f7e26c1a2390ae345cfa94dadcc59a3fb118f7 (diff) | |
Move files and patches to files-2.6.23 and patches-2.6.23
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@11843 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/rb532/files-2.6.23/arch')
11 files changed, 1742 insertions, 0 deletions
diff --git a/target/linux/rb532/files-2.6.23/arch/mips/pci/fixup-rb500.c b/target/linux/rb532/files-2.6.23/arch/mips/pci/fixup-rb500.c new file mode 100644 index 000000000..76c465fea --- /dev/null +++ b/target/linux/rb532/files-2.6.23/arch/mips/pci/fixup-rb500.c @@ -0,0 +1,51 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + *         	stevel@mvista.com or source@mvista.com + * + *  This program is free software; you can redistribute  it and/or modify it + *  under  the terms of  the GNU General  Public License as published by the + *  Free Software Foundation;  either version 2 of the  License, or (at your + *  option) any later version. + * + *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED + *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN + *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT, + *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF + *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT + *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *  You should have received a copy of the  GNU General Public License along + *  with this program; if not, write  to the Free Software Foundation, Inc., + *  675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/kernel.h> +#include <linux/init.h> + +#include <asm/pci.h> +#include <asm/io.h> + +#include <asm/rc32434/rc32434.h> + +static int __devinitdata irq_map[2][12] = { +	{ 0, 0, 2, 3, 2, 3, 0, 0, 0, 0, 0, 1 }, +	{ 0, 0, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3 } +}; + +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ +	int irq = 0; + +	if (dev->bus->number < 2 && PCI_SLOT(dev->devfn) < 12) { +		irq = irq_map[dev->bus->number][PCI_SLOT(dev->devfn)]; +	} +	return irq + GROUP4_IRQ_BASE + 4; +} + diff --git a/target/linux/rb532/files-2.6.23/arch/mips/pci/ops-rc32434.c b/target/linux/rb532/files-2.6.23/arch/mips/pci/ops-rc32434.c new file mode 100644 index 000000000..b90ab1d12 --- /dev/null +++ b/target/linux/rb532/files-2.6.23/arch/mips/pci/ops-rc32434.c @@ -0,0 +1,218 @@ +/************************************************************************** + * + *  BRIEF MODULE DESCRIPTION + *     pci_ops for IDT EB434 board + * + *  Copyright 2004 IDT Inc. (rischelp@idt.com) + *  Copyright 2006 Felix Fietkau <nbd@openwrt.org> + *          + *  This program is free software; you can redistribute  it and/or modify it + *  under  the terms of  the GNU General  Public License as published by the + *  Free Software Foundation;  either version 2 of the  License, or (at your + *  option) any later version. + * + *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED + *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN + *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT, + *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF + *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT + *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *  You should have received a copy of the  GNU General Public License along + *  with this program; if not, write  to the Free Software Foundation, Inc., + *  675 Mass Ave, Cambridge, MA 02139, USA. + * + * + ************************************************************************** + * May 2004 rkt, neb + * + * Initial Release + * + *  + * + ************************************************************************** + */ + +#include <linux/autoconf.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/types.h> +#include <linux/delay.h> + +#include <asm/cpu.h> +#include <asm/io.h> + +#include <asm/rc32434/rc32434.h> +#include <asm/rc32434/pci.h>  + +#define PCI_ACCESS_READ  0 +#define PCI_ACCESS_WRITE 1 + + +#define PCI_CFG_SET(bus,slot,func,off) \ +	(rc32434_pci->pcicfga = (0x80000000 | \ +				((bus) << 16) | ((slot)<<11) | \ +				((func)<<8) | (off))) + +static inline int config_access(unsigned char access_type, struct pci_bus *bus, +                         unsigned int devfn, unsigned char where, +                         u32 * data) +{  +	unsigned int slot = PCI_SLOT(devfn); +	u8 func = PCI_FUNC(devfn); +	 +	/* Setup address */ +	PCI_CFG_SET(bus->number, slot, func, where); +	rc32434_sync(); +	 +	if (access_type == PCI_ACCESS_WRITE) +		rc32434_pci->pcicfgd = *data; +	else +		*data = rc32434_pci->pcicfgd; +	 +	rc32434_sync(); +	 +	return 0; +} + + +/* + * We can't address 8 and 16 bit words directly.  Instead we have to + * read/write a 32bit word and mask/modify the data we actually want. + */ +static int read_config_byte(struct pci_bus *bus, unsigned int devfn, +                            int where, u8 * val) +{ +	u32 data; +	int ret; +	 +	ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data); +	*val = (data >> ((where & 3) << 3)) & 0xff; +	return ret; +} + +static int read_config_word(struct pci_bus *bus, unsigned int devfn, +                            int where, u16 * val) +{ +	u32 data; +	int ret; +	 +	ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data); +	*val = (data >> ((where & 3) << 3)) & 0xffff; +	return ret; +} + +static int read_config_dword(struct pci_bus *bus, unsigned int devfn, +                             int where, u32 * val) +{ +	int ret; +	int delay = 1; + +	if (bus->number == 0 && PCI_SLOT(devfn) > 21) +		return 0; + +retry: +	ret = config_access(PCI_ACCESS_READ, bus, devfn, where, val); +	 +	/* PCI scan: check for invalid values, device may not have +	 * finished initializing */ + +	if (where == PCI_VENDOR_ID) { +		if (ret == 0xffffffff || ret == 0x00000000 || +			ret == 0x0000ffff || ret == 0xffff0000) { + +			if (delay > 4) +				return 0; + +			delay *= 2; +			msleep(delay); +			goto retry; +		} +	} +	 +	return ret; +} + +static int +write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, +                  u8 val) +{ +	u32 data = 0; +	 +	if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) +		return -1; +	 +	data = (data & ~(0xff << ((where & 3) << 3))) | +		(val << ((where & 3) << 3)); +	 +	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data)) +		return -1; +	 +	return PCIBIOS_SUCCESSFUL; +} + + +static int +write_config_word(struct pci_bus *bus, unsigned int devfn, int where, +                  u16 val) +{ +	u32 data = 0; +	 +	if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) +		return -1; +	 +	data = (data & ~(0xffff << ((where & 3) << 3))) | +		(val << ((where & 3) << 3)); +	 +	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data)) +		return -1; +	 +	 +	return PCIBIOS_SUCCESSFUL; +} + + +static int  +write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, +                   u32 val) +{ +	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &val)) +		return -1; +	 +	return PCIBIOS_SUCCESSFUL; +} + +static int pci_config_read(struct pci_bus *bus, unsigned int devfn, +			   int where, int size, u32 * val) +{ +	switch (size) { +	case 1:  +		return read_config_byte(bus, devfn, where, (u8 *) val); +	case 2:  +		return read_config_word(bus, devfn, where, (u16 *) val); +	default: +		return read_config_dword(bus, devfn, where, val); +	} +} + +static int pci_config_write(struct pci_bus *bus, unsigned int devfn, +			    int where, int size, u32 val) +{ +	switch (size) { +	case 1:  +		return write_config_byte(bus, devfn, where, (u8) val); +	case 2:  +		return write_config_word(bus, devfn, where, (u16) val); +	default: +		return write_config_dword(bus, devfn, where, val); +	} +} + +struct pci_ops rc32434_pci_ops = { +	.read =  pci_config_read, +	.write = pci_config_write, +}; diff --git a/target/linux/rb532/files-2.6.23/arch/mips/pci/pci-rc32434.c b/target/linux/rb532/files-2.6.23/arch/mips/pci/pci-rc32434.c new file mode 100644 index 000000000..9ae596c22 --- /dev/null +++ b/target/linux/rb532/files-2.6.23/arch/mips/pci/pci-rc32434.c @@ -0,0 +1,236 @@ +/************************************************************************** + * + *  BRIEF MODULE DESCRIPTION + *     PCI initialization for IDT EB434 board + * + *  Copyright 2004 IDT Inc. (rischelp@idt.com) + * + *  This program is free software; you can redistribute  it and/or modify it + *  under  the terms of  the GNU General  Public License as published by the + *  Free Software Foundation;  either version 2 of the  License, or (at your + *  option) any later version. + * + *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED + *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN + *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT, + *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF + *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT + *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *  You should have received a copy of the  GNU General Public License along + *  with this program; if not, write  to the Free Software Foundation, Inc., + *  675 Mass Ave, Cambridge, MA 02139, USA. + * + * + ************************************************************************** + * May 2004 rkt, neb + * + * Initial Release + * + * + * + ************************************************************************** + */ + +#include <linux/autoconf.h> +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/kernel.h> +#include <linux/init.h> + +#include <asm/rc32434/rc32434.h> +#include <asm/rc32434/pci.h> + +#define PCI_ACCESS_READ  0 +#define PCI_ACCESS_WRITE 1 + +/* define an unsigned array for the PCI registers */ +unsigned int korinaCnfgRegs[25] = { +	KORINA_CNFG1,	 KORINA_CNFG2,  KORINA_CNFG3,  KORINA_CNFG4, +	KORINA_CNFG5,	 KORINA_CNFG6,  KORINA_CNFG7,  KORINA_CNFG8, +	KORINA_CNFG9,	 KORINA_CNFG10, KORINA_CNFG11, KORINA_CNFG12, +	KORINA_CNFG13, KORINA_CNFG14, KORINA_CNFG15, KORINA_CNFG16, +	KORINA_CNFG17, KORINA_CNFG18, KORINA_CNFG19, KORINA_CNFG20, +	KORINA_CNFG21, KORINA_CNFG22, KORINA_CNFG23, KORINA_CNFG24 +}; +static struct resource rc32434_res_pci_mem1; +static struct resource rc32434_res_pci_mem2; + +static struct resource rc32434_res_pci_mem1 = { +	.name = "PCI MEM1", +	.start = 0x50000000, +	.end = 0x5FFFFFFF, +	.flags = IORESOURCE_MEM, +	.parent = &rc32434_res_pci_mem1, +	.sibling = NULL, +	.child = &rc32434_res_pci_mem2 +}; + +static struct resource rc32434_res_pci_mem2 = { +	.name = "PCI Mem2", +	.start = 0x60000000, +	.end = 0x6FFFFFFF, +	.flags = IORESOURCE_MEM, +	.parent = &rc32434_res_pci_mem1, +	.sibling = NULL, +	.child = NULL +}; + +static struct resource rc32434_res_pci_io1 = { +	.name = "PCI I/O1", +	.start = 0x18800000, +	.end = 0x188FFFFF, +	.flags = IORESOURCE_IO, +}; + +extern struct pci_ops rc32434_pci_ops; + +#define PCI_MEM1_START	PCI_ADDR_START +#define PCI_MEM1_END	PCI_ADDR_START + CPUTOPCI_MEM_WIN - 1 +#define PCI_MEM2_START	PCI_ADDR_START + CPUTOPCI_MEM_WIN +#define PCI_MEM2_END	PCI_ADDR_START + ( 2* CPUTOPCI_MEM_WIN)  - 1 +#define PCI_IO1_START	PCI_ADDR_START + (2 * CPUTOPCI_MEM_WIN) +#define PCI_IO1_END 	PCI_ADDR_START + (2* CPUTOPCI_MEM_WIN) + CPUTOPCI_IO_WIN -1 +#define PCI_IO2_START	PCI_ADDR_START + (2 * CPUTOPCI_MEM_WIN) + CPUTOPCI_IO_WIN +#define PCI_IO2_END 	PCI_ADDR_START + (2* CPUTOPCI_MEM_WIN) + (2 * CPUTOPCI_IO_WIN) -1 + + +struct pci_controller rc32434_controller2; + +struct pci_controller rc32434_controller = { +	.pci_ops 	= &rc32434_pci_ops, +	.mem_resource 	= &rc32434_res_pci_mem1, +	.io_resource 	= &rc32434_res_pci_io1, +	.mem_offset     = 0, +	.io_offset      = 0, + +}; + +#ifdef __MIPSEB__ +#define PCI_ENDIAN_FLAG PCILBAC_sb_m +#else +#define PCI_ENDIAN_FLAG 0 +#endif + +static int __init rc32434_pcibridge_init(void) +{ +	unsigned int pcicValue, pcicData = 0; +	unsigned int dummyRead, pciCntlVal; +	int loopCount; +	unsigned int pciConfigAddr; + +	pcicValue = rc32434_pci->pcic; +	pcicValue = (pcicValue >> PCIM_SHFT) & PCIM_BIT_LEN; +	if (!((pcicValue == PCIM_H_EA) || +		 (pcicValue == PCIM_H_IA_FIX) || +		(pcicValue == PCIM_H_IA_RR))) { +		printk("PCI init error!!!\n"); +		/* Not in Host Mode, return ERROR */ +		return -1; +	} +	/* Enables the Idle Grant mode, Arbiter Parking */ +	pcicData |=(PCIC_igm_m|PCIC_eap_m|PCIC_en_m); +	rc32434_pci->pcic = pcicData; /* Enable the PCI bus Interface */ +	/* Zero out the PCI status & PCI Status Mask */ +	for(;;) +	{ +	   pcicData = rc32434_pci->pcis; +	   if (!(pcicData & PCIS_rip_m)) +		    break; +	} + +	rc32434_pci->pcis = 0; +	rc32434_pci->pcism = 0xFFFFFFFF; +	/* Zero out the PCI decoupled registers */ +	rc32434_pci->pcidac=0; /* disable PCI decoupled accesses at initialization */ +	rc32434_pci->pcidas=0; /* clear the status */ +	rc32434_pci->pcidasm=0x0000007F; /* Mask all the interrupts */ +	/* Mask PCI Messaging Interrupts */ +	rc32434_pci_msg->pciiic = 0; +	rc32434_pci_msg->pciiim = 0xFFFFFFFF; +	rc32434_pci_msg->pciioic = 0; +	rc32434_pci_msg->pciioim = 0; + + +	/* Setup PCILB0 as Memory Window */ +	rc32434_pci->pcilba[0].a = (unsigned int) (PCI_ADDR_START); + +	/* setup the PCI map address as same as the local address */ + +	rc32434_pci->pcilba[0].m = (unsigned int) (PCI_ADDR_START); + + +	/* Setup PCILBA1 as MEM */ +	rc32434_pci->pcilba[0].c = ( ((SIZE_256MB & 0x1f) << PCILBAC_size_b) | PCI_ENDIAN_FLAG); +	dummyRead = rc32434_pci->pcilba[0].c; /* flush the CPU write Buffers */ +	rc32434_pci->pcilba[1].a = 0x60000000; +	rc32434_pci->pcilba[1].m = 0x60000000; + +	/* setup PCILBA2 as IO Window*/ +	rc32434_pci->pcilba[1].c = (((SIZE_256MB & 0x1f) << PCILBAC_size_b )| PCI_ENDIAN_FLAG); +	dummyRead = rc32434_pci->pcilba[1].c; /* flush the CPU write Buffers */ +	rc32434_pci->pcilba[2].a = 0x18C00000; +	rc32434_pci->pcilba[2].m = 0x18FFFFFF; + +	/* setup PCILBA2 as IO Window*/ +	rc32434_pci->pcilba[2].c = (((SIZE_4MB & 0x1f) << PCILBAC_size_b) | PCI_ENDIAN_FLAG ); +	dummyRead = rc32434_pci->pcilba[2].c; /* flush the CPU write Buffers */ + +	/* Setup PCILBA3 as IO Window */ +	rc32434_pci->pcilba[3].a = 0x18800000; +	rc32434_pci->pcilba[3].m = 0x18800000; +	rc32434_pci->pcilba[3].c = ( (((SIZE_1MB & 0x1ff) << PCILBAC_size_b) | PCILBAC_msi_m) | PCI_ENDIAN_FLAG); +	dummyRead = rc32434_pci->pcilba[3].c; /* flush the CPU write Buffers */ + +	pciConfigAddr=(unsigned int)(0x80000004); +	for(loopCount=0;loopCount<24;loopCount++){ +		rc32434_pci->pcicfga=pciConfigAddr; +		dummyRead=rc32434_pci->pcicfga; +		rc32434_pci->pcicfgd = korinaCnfgRegs[loopCount]; +		dummyRead=rc32434_pci->pcicfgd; +		pciConfigAddr += 4; +	} +	rc32434_pci->pcitc = (unsigned int)((PCITC_RTIMER_VAL&0xff) << PCITC_rtimer_b) +		| ((PCITC_DTIMER_VAL&0xff) << PCITC_dtimer_b); + +	pciCntlVal=rc32434_pci->pcic; +	pciCntlVal &=~(PCIC_tnr_m); +	rc32434_pci->pcic = pciCntlVal; +	pciCntlVal=rc32434_pci->pcic; +	return 0; +} + +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ +	if (PCI_SLOT(dev->devfn) == 6 && dev->bus->number == 0) { +		/* disable prefetched memory range */ +		pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT, 0); +		pci_write_config_word(dev, PCI_PREF_MEMORY_BASE, 0x10); + +		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 4); +	} +	return 0; +} + +static int __init rc32434_pci_init(void) +{ +	printk("PCI: Initializing PCI\n"); + +	ioport_resource.start = rc32434_res_pci_io1.start; +	ioport_resource.end = rc32434_res_pci_io1.end; + +	rc32434_pcibridge_init(); + +	register_pci_controller(&rc32434_controller); +	rc32434_sync(); + +	return 0; +} + +arch_initcall(rc32434_pci_init); + diff --git a/target/linux/rb532/files-2.6.23/arch/mips/rb500/Makefile b/target/linux/rb532/files-2.6.23/arch/mips/rb500/Makefile new file mode 100644 index 000000000..d3ae3d912 --- /dev/null +++ b/target/linux/rb532/files-2.6.23/arch/mips/rb500/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the RB500 board specific parts of the kernel +# + +obj-y	 += irq.o time.o setup.o serial.o prom.o gpio.o devices.o diff --git a/target/linux/rb532/files-2.6.23/arch/mips/rb500/devices.c b/target/linux/rb532/files-2.6.23/arch/mips/rb500/devices.c new file mode 100644 index 000000000..6372737de --- /dev/null +++ b/target/linux/rb532/files-2.6.23/arch/mips/rb500/devices.c @@ -0,0 +1,338 @@ +/* + *  RouterBoard 500 Platform devices + * + *  Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> + *  Copyright (C) 2007 Florian Fainelli <florian@openwrt.org> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + *  GNU General Public License for more details. + */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/ctype.h> +#include <linux/string.h> +#include <linux/platform_device.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> +#include <linux/gpio_keys.h> +#include <linux/input.h> + +#include <asm/bootinfo.h> + +#include <asm/rc32434/rc32434.h> +#include <asm/rc32434/dma.h> +#include <asm/rc32434/dma_v.h> +#include <asm/rc32434/eth.h> +#include <asm/rc32434/rb.h> + +#define ETH0_DMA_RX_IRQ   	GROUP1_IRQ_BASE + 0 +#define ETH0_DMA_TX_IRQ   	GROUP1_IRQ_BASE + 1 +#define ETH0_RX_OVR_IRQ   	GROUP3_IRQ_BASE + 9 +#define ETH0_TX_UND_IRQ   	GROUP3_IRQ_BASE + 10 + +#define ETH0_RX_DMA_ADDR  (DMA0_PhysicalAddress + 0*DMA_CHAN_OFFSET) +#define ETH0_TX_DMA_ADDR  (DMA0_PhysicalAddress + 1*DMA_CHAN_OFFSET) + +/* NAND definitions */ +#define MEM32(x) *((volatile unsigned *) (x)) + +#define GPIO_RDY (1 << 0x08) +#define GPIO_WPX (1 << 0x09) +#define GPIO_ALE (1 << 0x0a) +#define GPIO_CLE (1 << 0x0b) + +extern char* board_type; + +static struct resource korina_dev0_res[] = { +	{ +		.name = "korina_regs", +		.start = ETH0_PhysicalAddress, +		.end = ETH0_PhysicalAddress + sizeof(ETH_t), +		.flags = IORESOURCE_MEM, +	 }, { +		.name = "korina_rx", +		.start = ETH0_DMA_RX_IRQ, +		.end = ETH0_DMA_RX_IRQ, +		.flags = IORESOURCE_IRQ +	}, { +		.name = "korina_tx", +		.start = ETH0_DMA_TX_IRQ, +		.end = ETH0_DMA_TX_IRQ, +		.flags = IORESOURCE_IRQ +	}, { +		.name = "korina_ovr", +		.start = ETH0_RX_OVR_IRQ, +		.end = ETH0_RX_OVR_IRQ, +		.flags = IORESOURCE_IRQ +	}, { +		.name = "korina_und", +		.start = ETH0_TX_UND_IRQ, +		.end = ETH0_TX_UND_IRQ, +		.flags = IORESOURCE_IRQ +	}, { +		.name = "korina_dma_rx", +		.start = ETH0_RX_DMA_ADDR, +		.end = ETH0_RX_DMA_ADDR + DMA_CHAN_OFFSET - 1, +		.flags = IORESOURCE_MEM, +	 }, { +		.name = "korina_dma_tx", +		.start = ETH0_TX_DMA_ADDR, +		.end = ETH0_TX_DMA_ADDR + DMA_CHAN_OFFSET - 1, +		.flags = IORESOURCE_MEM, +	 } +}; + +static struct korina_device korina_dev0_data = { +	.name = "korina0", +	.mac = {0xde, 0xca, 0xff, 0xc0, 0xff, 0xee} +}; + +static struct platform_device korina_dev0 = { +	.id = 0, +	.name = "korina", +	.dev.platform_data = &korina_dev0_data, +	.resource = korina_dev0_res, +	.num_resources = ARRAY_SIZE(korina_dev0_res), +}; + +#define CF_GPIO_NUM 13 + +static struct resource cf_slot0_res[] = { +	{ +		.name = "cf_membase", +		.flags = IORESOURCE_MEM +	}, { +		.name = "cf_irq", +		.start = (8 + 4 * 32 + CF_GPIO_NUM),	/* 149 */ +		.end = (8 + 4 * 32 + CF_GPIO_NUM), +		.flags = IORESOURCE_IRQ +	} +}; + +static struct cf_device cf_slot0_data = { +	.gpio_pin = 13 +}; + +static struct platform_device cf_slot0 = { +	.id = 0, +	.name = "rb500-cf", +	.dev.platform_data = &cf_slot0_data, +	.resource = cf_slot0_res, +	.num_resources = ARRAY_SIZE(cf_slot0_res), +}; + +/* Resources and device for NAND.  There is no data needed and no irqs, so just define the memory used. */ + +/* + * We need to use the OLD Yaffs-1 OOB layout, otherwise the RB bootloader + * will not be able to find the kernel that we load.  So set the oobinfo + * when creating the partitions + */ +static struct nand_ecclayout rb500_nand_ecclayout = { +	.eccbytes	= 6, +	.eccpos		= { 8, 9, 10, 13, 14, 15 }, +	.oobavail	= 9, +	.oobfree	= { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } } +}; + +int rb500_dev_ready(struct mtd_info *mtd) +{ +        return MEM32(IDT434_REG_BASE + GPIOD) & GPIO_RDY; +} + +void rb500_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{ +        struct nand_chip *chip = mtd->priv; +        unsigned char orbits, nandbits; + +        if (ctrl & NAND_CTRL_CHANGE) { + +                orbits = (ctrl & NAND_CLE) << 1; +                orbits |= (ctrl & NAND_ALE) >> 1; + +                nandbits = (~ctrl & NAND_CLE) << 1; +                nandbits |= (~ctrl & NAND_ALE) >> 1; + +                changeLatchU5(orbits, nandbits); +        } +        if (cmd != NAND_CMD_NONE) +                writeb(cmd, chip->IO_ADDR_W); +} + +static struct resource nand_slot0_res[] = { +	[0] = { +		.name = "nand_membase", +		.flags = IORESOURCE_MEM +	} +}; + +struct platform_nand_data rb500_nand_data = { +	.ctrl.dev_ready = rb500_dev_ready, +	.ctrl.cmd_ctrl	= rb500_cmd_ctrl, +}; + +static struct platform_device nand_slot0 = { +	.name = "gen_nand", +	.id = -1, +	.resource = nand_slot0_res, +	.num_resources = ARRAY_SIZE(nand_slot0_res), +	.dev.platform_data = &rb500_nand_data, +}; + +static struct mtd_partition rb500_partition_info[] = { +	{ +		.name = "Routerboard NAND boot", +		.offset = 0, +		.size = 4 * 1024 * 1024, +	}, { +		.name = "rootfs", +		.offset = MTDPART_OFS_NXTBLK, +		.size = MTDPART_SIZ_FULL, +	} +}; + +static struct platform_device rb500_led = { +	.name = "rb500-led", +	.id = 0, +}; + +static struct gpio_keys_button rb500_gpio_btn[] = { +	{ +		.gpio = 1, +		.code = BTN_0, +		.desc = "S1", +		.active_low = 1, +	} +}; + +static struct gpio_keys_platform_data rb500_gpio_btn_data = { +	.buttons = rb500_gpio_btn, +	.nbuttons = ARRAY_SIZE(rb500_gpio_btn), +}; + +static struct platform_device rb500_button = { +	.name 	= "gpio-keys", +	.id	= -1, +	.dev	= { +		.platform_data = &rb500_gpio_btn_data, +	} +}; + +static struct platform_device *rb500_devs[] = { +	&korina_dev0, +	&nand_slot0, +	&cf_slot0, +	&rb500_led, +	&rb500_button +}; + +static void __init parse_mac_addr(char *macstr) +{ +	int i, j; +	unsigned char result, value; + +	for (i = 0; i < 6; i++) { +		result = 0; + +		if (i != 5 && *(macstr + 2) != ':') +			return; + +		for (j = 0; j < 2; j++) { +			if (isxdigit(*macstr) +			    && (value = +				isdigit(*macstr) ? *macstr - +				'0' : toupper(*macstr) - 'A' + 10) < 16) { +				result = result * 16 + value; +				macstr++; +			} else +				return; +		} + +		macstr++; +		korina_dev0_data.mac[i] = result; +	} +} + + +/* DEVICE CONTROLLER 1 */ +#define CFG_DC_DEV1 (void*)0xb8010010 +#define CFG_DC_DEV2 (void*)0xb8010020 +#define CFG_DC_DEVBASE    0x0 +#define CFG_DC_DEVMASK    0x4 +#define CFG_DC_DEVC       0x8 +#define CFG_DC_DEVTC      0xC + +/* NAND definitions */ +#define NAND_CHIP_DELAY	25 + +static int rb500_nand_fixup(struct mtd_info *mtd) +{ +	struct nand_chip *chip = mtd->priv; + +	if (mtd->writesize == 512) +		chip->ecc.layout = &rb500_nand_ecclayout; + +	return 0; +} + +static void __init rb500_nand_setup(void) +{ +	switch (mips_machtype) { +	case MACH_MIKROTIK_RB532A: +		changeLatchU5(LO_FOFF | LO_CEX, LO_ULED | LO_ALE | LO_CLE | LO_WPX); +		break; +	default: +		changeLatchU5(LO_WPX | LO_FOFF | LO_CEX, LO_ULED | LO_ALE | LO_CLE); +		break; +	} + +	/* Setup NAND specific settings */ +	rb500_nand_data.chip.nr_chips = 1; +	rb500_nand_data.chip.nr_partitions = ARRAY_SIZE(rb500_partition_info); +	rb500_nand_data.chip.partitions = rb500_partition_info; +	rb500_nand_data.chip.chip_delay = NAND_CHIP_DELAY; +	rb500_nand_data.chip.options = NAND_NO_AUTOINCR; + +	rb500_nand_data.chip.chip_fixup = &rb500_nand_fixup; +} + + +static int __init plat_setup_devices(void) +{ +	/* Look for the CF card reader */ +	if (!readl(CFG_DC_DEV1 + CFG_DC_DEVMASK)) +		rb500_devs[1] = NULL; +	else { +		cf_slot0_res[0].start = +		    readl(CFG_DC_DEV1 + CFG_DC_DEVBASE); +		cf_slot0_res[0].end = cf_slot0_res[0].start + 0x1000; +	} + +	/* Read the NAND resources from the device controller */ +	nand_slot0_res[0].start = readl(CFG_DC_DEV2 + CFG_DC_DEVBASE); +	nand_slot0_res[0].end = nand_slot0_res[0].start + 0x1000; + +	/* Initialise the NAND device */ +	rb500_nand_setup(); + +	return platform_add_devices(rb500_devs, ARRAY_SIZE(rb500_devs)); +} + +static int __init setup_kmac(char *s) +{ +	printk("korina mac = %s\n", s); +	parse_mac_addr(s); +	return 0; +} + +__setup("kmac=", setup_kmac); + +arch_initcall(plat_setup_devices); diff --git a/target/linux/rb532/files-2.6.23/arch/mips/rb500/gpio.c b/target/linux/rb532/files-2.6.23/arch/mips/rb500/gpio.c new file mode 100644 index 000000000..6c92a8fe5 --- /dev/null +++ b/target/linux/rb532/files-2.6.23/arch/mips/rb500/gpio.c @@ -0,0 +1,198 @@ +/* + *  Miscellaneous functions for IDT EB434 board + * + *  Copyright 2004 IDT Inc. (rischelp@idt.com) + *  Copyright 2006 Phil Sutter <n0-1@freewrt.org> + *  Copyright 2007 Florian Fainelli <florian@openwrt.org> + * + *  This program is free software; you can redistribute  it and/or modify it + *  under  the terms of  the GNU General  Public License as published by the + *  Free Software Foundation;  either version 2 of the  License, or (at your + *  option) any later version. + * + *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED + *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN + *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT, + *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF + *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT + *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *  You should have received a copy of the  GNU General Public License along + *  with this program; if not, write  to the Free Software Foundation, Inc., + *  675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/spinlock.h> +#include <linux/io.h> +#include <linux/platform_device.h> + +#include <asm/addrspace.h> +#include <asm/gpio.h> + +#include <asm/rc32434/rb.h> + +#define GPIO_BADDR  0x18050000 + +static volatile unsigned char *devCtl3Base; +static unsigned char latchU5State; +static spinlock_t clu5Lock = SPIN_LOCK_UNLOCKED; + +struct rb500_gpio_reg __iomem *rb500_gpio_reg0; +EXPORT_SYMBOL(rb500_gpio_reg0); + +static struct resource rb500_gpio_reg0_res[] = { +	{ +		.name 	= "gpio_reg0", +		.start 	= GPIO_BADDR, +		.end 	= GPIO_BADDR + sizeof(struct rb500_gpio_reg), +		.flags 	= IORESOURCE_MEM, +	} +}; + +void set434Reg(unsigned regOffs, unsigned bit, unsigned len, unsigned val) +{ +	unsigned flags, data; +	unsigned i = 0; + +	spin_lock_irqsave(&clu5Lock, flags); +	data = *(volatile unsigned *) (IDT434_REG_BASE + regOffs); +	for (i = 0; i != len; ++i) { +		if (val & (1 << i)) +			data |= (1 << (i + bit)); +		else +			data &= ~(1 << (i + bit)); +	} +	*(volatile unsigned *) (IDT434_REG_BASE + regOffs) = data; +	spin_unlock_irqrestore(&clu5Lock, flags); +} +EXPORT_SYMBOL(set434Reg); + +void changeLatchU5(unsigned char orMask, unsigned char nandMask) +{ +	unsigned flags; + +	spin_lock_irqsave(&clu5Lock, flags); +	latchU5State = (latchU5State | orMask) & ~nandMask; +	if (!devCtl3Base) +		devCtl3Base = (volatile unsigned char *) +		    KSEG1ADDR(*(volatile unsigned *) +			      KSEG1ADDR(0x18010030)); +	*devCtl3Base = latchU5State; +	spin_unlock_irqrestore(&clu5Lock, flags); +} +EXPORT_SYMBOL(changeLatchU5); + +unsigned char getLatchU5State(void) +{ +	return latchU5State; +} +EXPORT_SYMBOL(getLatchU5State); + +int rb500_gpio_get_value(unsigned gpio) +{ +	return readl(&rb500_gpio_reg0->gpiod) & (1 << gpio); +} +EXPORT_SYMBOL(rb500_gpio_get_value); + +void rb500_gpio_set_value(unsigned gpio, int value) +{ +	unsigned tmp; + +	tmp = readl(&rb500_gpio_reg0->gpiod) & ~(1 << gpio); +	if (value) +		tmp |= 1 << gpio; + +	writel(tmp, (void *)&rb500_gpio_reg0->gpiod); +} +EXPORT_SYMBOL(rb500_gpio_set_value); + +int rb500_gpio_direction_input(unsigned gpio) +{ +	writel(readl(&rb500_gpio_reg0->gpiocfg) & ~(1 << gpio), (void *)&rb500_gpio_reg0->gpiocfg); + +	return 0; +} +EXPORT_SYMBOL(rb500_gpio_direction_input); + +int rb500_gpio_direction_output(unsigned gpio, int value) +{ +	gpio_set_value(gpio, value); +	writel(readl(&rb500_gpio_reg0->gpiocfg) | (1 << gpio), (void *)&rb500_gpio_reg0->gpiocfg); + +	return 0; +} +EXPORT_SYMBOL(rb500_gpio_direction_output); + +void rb500_gpio_set_int_level(unsigned gpio, int value) +{ +	unsigned tmp; + +	tmp = readl(&rb500_gpio_reg0->gpioilevel) & ~(1 << gpio); +	if (value) +		tmp |= 1 << gpio; +	writel(tmp, (void *)&rb500_gpio_reg0->gpioilevel); +} +EXPORT_SYMBOL(rb500_gpio_set_int_level); + +int rb500_gpio_get_int_level(unsigned gpio) +{ +	return readl(&rb500_gpio_reg0->gpioilevel) & (1 << gpio); +} +EXPORT_SYMBOL(rb500_gpio_get_int_level); + +void rb500_gpio_set_int_status(unsigned gpio, int value) +{ +	unsigned tmp; + +	tmp = readl(&rb500_gpio_reg0->gpioistat); +	if (value) +		tmp |= 1 << gpio; +	writel(tmp, (void *)&rb500_gpio_reg0->gpioistat); +} +EXPORT_SYMBOL(rb500_gpio_set_int_status); + +int rb500_gpio_get_int_status(unsigned gpio) +{ +	return readl(&rb500_gpio_reg0->gpioistat) & (1 << gpio); +} +EXPORT_SYMBOL(rb500_gpio_get_int_status); + +void rb500_gpio_set_func(unsigned gpio, int value) +{ +        unsigned tmp; + +        tmp = readl(&rb500_gpio_reg0->gpiofunc); +        if (value) +                tmp |= 1 << gpio; +        writel(tmp, (void *)&rb500_gpio_reg0->gpiofunc); +} +EXPORT_SYMBOL(rb500_gpio_set_func); + +int rb500_gpio_get_func(unsigned gpio) +{ +        return readl(&rb500_gpio_reg0->gpiofunc) & (1 << gpio); +} +EXPORT_SYMBOL(rb500_gpio_get_func); + +int __init rb500_gpio_init(void) +{ +	rb500_gpio_reg0 = ioremap_nocache(rb500_gpio_reg0_res[0].start, +				rb500_gpio_reg0_res[0].end - +				rb500_gpio_reg0_res[0].start); + +	if (!rb500_gpio_reg0) { +		printk(KERN_ERR "rb500: cannot remap GPIO register 0\n"); +		return -ENXIO; +	} + +	return 0; +} +arch_initcall(rb500_gpio_init); diff --git a/target/linux/rb532/files-2.6.23/arch/mips/rb500/irq.c b/target/linux/rb532/files-2.6.23/arch/mips/rb500/irq.c new file mode 100644 index 000000000..5a4d349d4 --- /dev/null +++ b/target/linux/rb532/files-2.6.23/arch/mips/rb500/irq.c @@ -0,0 +1,265 @@ +/* + * BRIEF MODULE DESCRIPTION + *	RC32434 interrupt routines. + * + * Copyright 2002 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + *		stevel@mvista.com or source@mvista.com + * + *  This program is free software; you can redistribute	 it and/or modify it + *  under  the terms of	 the GNU General  Public License as published by the + *  Free Software Foundation;  either version 2 of the	License, or (at your + *  option) any later version. + * + *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED + *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN + *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT, + *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF + *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT + *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *  You should have received a copy of the  GNU General Public License along + *  with this program; if not, write  to the Free Software Foundation, Inc., + *  675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel_stat.h> +#include <linux/module.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/timex.h> +#include <linux/slab.h> +#include <linux/random.h> +#include <linux/delay.h> + +#include <asm/bitops.h> +#include <asm/bootinfo.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/time.h> +#include <asm/mipsregs.h> +#include <asm/system.h> +#include <asm/rc32434/rc32434.h> +#include <asm/rc32434/gpio.h> + +extern void set_debug_traps(void); +extern irq_cpustat_t irq_stat [NR_CPUS]; +unsigned int local_bh_count[NR_CPUS]; +unsigned int local_irq_count[NR_CPUS]; + +static unsigned int startup_irq(unsigned int irq); +static void rb500_end_irq(unsigned int irq_nr); +static void mask_and_ack_irq(unsigned int irq_nr); +static void rb500_enable_irq(unsigned int irq_nr); +static void rb500_disable_irq(unsigned int irq_nr); + +extern void __init init_generic_irq(void); +extern struct rb500_gpio_reg __iomem *rb500_gpio_reg0; + +typedef struct { +  u32 mask;       /* mask of valid bits in pending/mask registers */ +  volatile u32 *base_addr; +} intr_group_t; + +#define RC32434_NR_IRQS  (GROUP4_IRQ_BASE + 32) + +#if (NR_IRQS < RC32434_NR_IRQS) +#error Too little irqs defined. Did you override <asm/irq.h> ? +#endif + +static const intr_group_t intr_group[NUM_INTR_GROUPS] = { +  { 0x0000efff, (u32 *)KSEG1ADDR(IC_GROUP0_PEND + 0 * IC_GROUP_OFFSET) }, +  { 0x00001fff, (u32 *)KSEG1ADDR(IC_GROUP0_PEND + 1 * IC_GROUP_OFFSET) }, +  { 0x00000007, (u32 *)KSEG1ADDR(IC_GROUP0_PEND + 2 * IC_GROUP_OFFSET) }, +  { 0x0003ffff, (u32 *)KSEG1ADDR(IC_GROUP0_PEND + 3 * IC_GROUP_OFFSET) }, +  { 0xffffffff, (u32 *)KSEG1ADDR(IC_GROUP0_PEND + 4 * IC_GROUP_OFFSET) } +}; + +#define READ_PEND(base) (*(base)) +#define READ_MASK(base) (*(base + 2)) +#define WRITE_MASK(base, val) (*(base + 2) = (val)) + +static inline int irq_to_group(unsigned int irq_nr) +{ +  return ((irq_nr - GROUP0_IRQ_BASE) >> 5); +} + +static inline int group_to_ip(unsigned int group) +{ +  return group + 2; +} + +static inline void enable_local_irq(unsigned int ip) +{ +  int ipnum = 0x100 << ip; +  clear_c0_cause(ipnum); +  set_c0_status(ipnum); +} + +static inline void disable_local_irq(unsigned int ip) +{ +  int ipnum = 0x100 << ip; +  clear_c0_status(ipnum); +} + +static inline void ack_local_irq(unsigned int ip) +{ +  int ipnum = 0x100 << ip; +  clear_c0_cause(ipnum); +} + +static void rb500_enable_irq(unsigned int irq_nr) +{ +  int           ip = irq_nr - GROUP0_IRQ_BASE; +  unsigned int  group, intr_bit; +  volatile unsigned int  *addr; +   +   +  if (ip < 0) +    enable_local_irq(irq_nr); +  else { +    group = ip >> 5; +  +    ip &= (1<<5)-1; +    intr_bit = 1 << ip; +  +    enable_local_irq(group_to_ip(group)); +     +    addr = intr_group[group].base_addr; +    WRITE_MASK(addr, READ_MASK(addr) & ~intr_bit); +  } +} + +static void rb500_disable_irq(unsigned int irq_nr) +{ +  int           ip = irq_nr - GROUP0_IRQ_BASE; +  unsigned int  group, intr_bit, mask; +  volatile unsigned int  *addr; +   +  if (ip < 0) { +	disable_local_irq(irq_nr); +    }else{ +    group = ip >> 5; +     +    ip &= (1<<5) -1; +    intr_bit = 1 << ip; +    addr = intr_group[group].base_addr; +    mask = READ_MASK(addr); +    mask |= intr_bit; +    WRITE_MASK(addr,mask); +    +    /* +     * if there are no more interrupts enabled in this +     * group, disable corresponding IP +     */ +    if (mask == intr_group[group].mask) +      disable_local_irq(group_to_ip(group)); +  } +} + +static unsigned int startup_irq(unsigned int irq_nr) +{ +  rb500_enable_irq(irq_nr); +  return 0;  +} + +static void shutdown_irq(unsigned int irq_nr) +{ +  rb500_disable_irq(irq_nr); +  return; +} + +static void mask_and_ack_irq(unsigned int irq_nr) +{ +  rb500_disable_irq(irq_nr); +  ack_local_irq(group_to_ip(irq_to_group(irq_nr))); +} + +static void rb500_end_irq(unsigned int irq_nr) +{ + +  int ip = irq_nr - GROUP0_IRQ_BASE; +  unsigned int intr_bit, group; +  volatile unsigned int *addr; + +	if ((irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { +		printk("warning: end_irq %d did not enable (%x)\n",  +			irq_nr, irq_desc[irq_nr].status); +		return; +	} +	 +	if (ip < 0) { +		enable_local_irq(irq_nr); +	} else { +		group = ip >> 5; +	 +		ip &= (1 << 5) - 1; +		intr_bit = 1 << ip; +	 +		if (irq_nr >= GROUP4_IRQ_BASE && irq_nr <= (GROUP4_IRQ_BASE + 13)) { +			rb500_gpio_reg0->gpioistat = rb500_gpio_reg0->gpioistat & ~intr_bit; +		} +	 +		enable_local_irq(group_to_ip(group)); +	 +		addr = intr_group[group].base_addr; +		WRITE_MASK(addr, READ_MASK(addr) & ~intr_bit); +	} +} + +static struct hw_interrupt_type rc32434_irq_type = { +  .typename = "RB500", +  .startup = startup_irq, +  .shutdown = shutdown_irq, +  .enable = rb500_enable_irq, +  .disable = rb500_disable_irq, +  .ack = mask_and_ack_irq, +  .end = rb500_end_irq, +}; + + +void __init arch_init_irq(void) +{ +	int i; + +	printk("Initializing IRQ's: %d out of %d\n", RC32434_NR_IRQS, NR_IRQS); +	memset(irq_desc, 0, sizeof(irq_desc)); +   +	for (i = 0; i < RC32434_NR_IRQS; i++) { +		irq_desc[i].status = IRQ_DISABLED; +		irq_desc[i].action = NULL; +		irq_desc[i].depth = 1; +		irq_desc[i].chip = &rc32434_irq_type; +		spin_lock_init(&irq_desc[i].lock); +	} +} + +/* Main Interrupt dispatcher */ +asmlinkage void plat_irq_dispatch(void) +{ +	unsigned int ip, pend, group; +	volatile unsigned int *addr; +	unsigned int cp0_cause = read_c0_cause() & read_c0_status(); + +	if (cp0_cause & CAUSEF_IP7) { +		ll_timer_interrupt(7); +	} else if ((ip = (cp0_cause & 0x7c00))) { +		group = 21 - rc32434_clz(ip); + +		addr = intr_group[group].base_addr; + +		pend = READ_PEND(addr); +		pend &= ~READ_MASK(addr); // only unmasked interrupts +		pend = 39 - rc32434_clz(pend); +		do_IRQ((group << 5) + pend); +	} +} diff --git a/target/linux/rb532/files-2.6.23/arch/mips/rb500/prom.c b/target/linux/rb532/files-2.6.23/arch/mips/rb500/prom.c new file mode 100644 index 000000000..b10172fb5 --- /dev/null +++ b/target/linux/rb532/files-2.6.23/arch/mips/rb500/prom.c @@ -0,0 +1,178 @@ +/* +* prom.c +********************************************************************** +* P . Sadik Oct 10, 2003 +* +* Started change log +* idt_cpu_freq is make a kernel configuration parameter +* idt_cpu_freq is exported so that other modules can use it. +* Code cleanup +********************************************************************** +* P. Sadik Oct 20, 2003 +* +* Removed NVRAM code from here, since they are already available under +* nvram directory. +* Added serial port initialisation. +********************************************************************** +********************************************************************** +* P. Sadik Oct 30, 2003 +* +* Added reset_cons_port +********************************************************************** + +  P.Christeas, 2005-2006 +  Port to 2.6, add 2.6 cmdline parsing + +*/ + +#include <linux/autoconf.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/console.h> +#include <asm/bootinfo.h> +#include <linux/bootmem.h> +#include <linux/ioport.h> +#include <linux/blkdev.h> +#include <asm/rc32434/ddr.h> + +#define PROM_ENTRY(x)   (0xbfc00000+((x)*8)) +extern void __init setup_serial_port(void); + +unsigned int idt_cpu_freq = 132000000; +EXPORT_SYMBOL(idt_cpu_freq); +unsigned int gpio_bootup_state = 0; +EXPORT_SYMBOL(gpio_bootup_state); + +char mips_mac_address[18] = "08:00:06:05:40:01"; +EXPORT_SYMBOL(mips_mac_address); + +/* what to append to cmdline when button is [not] pressed */ +#define GPIO_INIT_NOBUTTON "" +#define GPIO_INIT_BUTTON   " 2" + +#ifdef CONFIG_MIKROTIK_RB500 +unsigned soft_reboot = 0; +EXPORT_SYMBOL(soft_reboot); +#endif + +#define SR_NMI			0x00180000      /* NMI */ +#define SERIAL_SPEED_ENTRY	0x00000001 + +#ifdef CONFIG_REMOTE_DEBUG +extern int remote_debug; +#endif + +#define FREQ_TAG   "HZ=" +#define GPIO_TAG   "gpio=" +#define KMAC_TAG   "kmac=" +#define MEM_TAG	   "mem=" +#define BOARD_TAG  "board=" +#define IGNORE_CMDLINE_MEM 1 +#define DEBUG_DDR + +#define BOARD_RB532	"500" +#define BOARD_RB532A	"500r5" + +void parse_soft_settings(unsigned *ptr, unsigned size); +void parse_hard_settings(unsigned *ptr, unsigned size); + +void __init prom_setup_cmdline(void); + +void __init prom_init(void) +{ +	DDR_t ddr = (DDR_t) DDR_VirtualAddress; /* define the pointer to the DDR registers */ +	phys_t memsize = 0-ddr->ddrmask; + +	/* this should be the very first message, even before serial is properly initialized */ +	prom_setup_cmdline(); +	setup_serial_port(); + +	mips_machgroup = MACH_GROUP_MIKROTIK; +	soft_reboot = read_c0_status() & SR_NMI; +	pm_power_off = NULL; + +	/* +	 * give all RAM to boot allocator, +	 * except for the first 0x400 and the last 0x200 bytes +	 */ +	add_memory_region(ddr->ddrbase + 0x400, memsize - 0x600, BOOT_MEM_RAM); +} + +void __init prom_free_prom_memory(void) +{ +	/* No prom memory to free */ +} + +static inline int match_tag(char *arg, const char *tag) +{ +	return (strncmp(arg, tag, strlen(tag)) == 0); +} + +static inline unsigned long tag2ul(char *arg, const char *tag) +{ +	char *num = arg+strlen(tag); +	return simple_strtoul(num, 0, 10); +} + +extern char _image_cmdline; +void __init prom_setup_cmdline(void){ +	char cmd_line[CL_SIZE]; +	char *cp; +	int prom_argc; +	char **prom_argv, **prom_envp; +	int i; + +	prom_argc = fw_arg0; +	prom_argv = (char **) fw_arg1; +	prom_envp = (char **) fw_arg2; + +	cp=cmd_line; +		/* Note: it is common that parameters start at argv[1] and not argv[0], +		however, our elf loader starts at [0] */ +	for(i=0;i<prom_argc;i++){ +		if (match_tag(prom_argv[i], FREQ_TAG)) { +			idt_cpu_freq = tag2ul(prom_argv[i], FREQ_TAG); +			continue; +		} +#ifdef IGNORE_CMDLINE_MEM +		/* parses out the "mem=xx" arg */ +		if (match_tag(prom_argv[i], MEM_TAG)) { +			continue; +		} +#endif +		if (i>0) *(cp++) = ' '; +		if (match_tag(prom_argv[i], BOARD_TAG)) { +			char *board = prom_argv[i] + strlen(BOARD_TAG); +			if (match_tag(board, BOARD_RB532A)) +				mips_machtype = MACH_MIKROTIK_RB532A; +			else +				mips_machtype = MACH_MIKROTIK_RB532; +		} + +		if (match_tag(prom_argv[i], GPIO_TAG)) { +			gpio_bootup_state = tag2ul(prom_argv[i], GPIO_TAG); +		} +		strcpy(cp,prom_argv[i]); +		cp+=strlen(prom_argv[i]); +	} +	*(cp++) = ' '; +	strcpy(cp,(&_image_cmdline + 8)); +	cp += strlen(&_image_cmdline); + +	i=strlen(arcs_cmdline); +	if (i>0){ +		*(cp++) = ' '; +		strcpy(cp,arcs_cmdline); +		cp+=strlen(arcs_cmdline); +	} +	if (gpio_bootup_state&0x02) +		strcpy(cp,GPIO_INIT_NOBUTTON); +	else +		strcpy(cp,GPIO_INIT_BUTTON); +	cmd_line[CL_SIZE-1] = '\0'; + +	strcpy(arcs_cmdline,cmd_line); +} + diff --git a/target/linux/rb532/files-2.6.23/arch/mips/rb500/serial.c b/target/linux/rb532/files-2.6.23/arch/mips/rb500/serial.c new file mode 100644 index 000000000..25a03e010 --- /dev/null +++ b/target/linux/rb532/files-2.6.23/arch/mips/rb500/serial.c @@ -0,0 +1,78 @@ +/************************************************************************** + * + *  BRIEF MODULE DESCRIPTION + *     Serial port initialisation. + * + *  Copyright 2004 IDT Inc. (rischelp@idt.com) + *          + *  This program is free software; you can redistribute  it and/or modify it + *  under  the terms of  the GNU General  Public License as published by the + *  Free Software Foundation;  either version 2 of the  License, or (at your + *  option) any later version. + * + *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED + *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN + *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT, + *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF + *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT + *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *  You should have received a copy of the  GNU General Public License along + *  with this program; if not, write  to the Free Software Foundation, Inc., + *  675 Mass Ave, Cambridge, MA 02139, USA. + * + * + ************************************************************************** + * May 2004 rkt, neb + * + * Initial Release + * + *  + * + ************************************************************************** + */ + + +#include <linux/autoconf.h> +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/pci.h> +#include <linux/interrupt.h> +#include <linux/tty.h> +#include <linux/serial.h> +#include <linux/serial_core.h> +#include <linux/serial_8250.h> + +#include <asm/time.h> +#include <asm/cpu.h> +#include <asm/bootinfo.h> +#include <asm/irq.h> +#include <asm/serial.h> +#include <asm/rc32434/rc32434.h> + +extern unsigned int idt_cpu_freq; + +static struct uart_port serial_req = { +	.type = PORT_16550A, +	.line = 0, +	.irq = RC32434_UART0_IRQ, +	//.flags = STD_COM_FLAGS, +	.iotype = UPIO_MEM, +	.membase = (char *) KSEG1ADDR(RC32434_UART0_BASE), +//	.fifosize = 14 +	.regshift = 2 +}; + +int __init setup_serial_port(void) +{ +	serial_req.uartclk = idt_cpu_freq; + +	if (early_serial_setup(&serial_req)) +		return -ENODEV; +	 +	return(0); +} diff --git a/target/linux/rb532/files-2.6.23/arch/mips/rb500/setup.c b/target/linux/rb532/files-2.6.23/arch/mips/rb500/setup.c new file mode 100644 index 000000000..2fda0e2ab --- /dev/null +++ b/target/linux/rb532/files-2.6.23/arch/mips/rb500/setup.c @@ -0,0 +1,81 @@ +/* + * setup.c - boot time setup code + */ + +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/irq.h> +#include <linux/ioport.h> +#include <linux/pm.h> +#include <asm/bootinfo.h> +#include <asm/mipsregs.h> +#include <asm/pgtable.h> +#include <asm/reboot.h> +#include <asm/addrspace.h>     /* for KSEG1ADDR() */ +#include <asm/time.h> +#include <asm/io.h> +#include <asm/rc32434/rc32434.h> +#include <asm/rc32434/pci.h> + +#ifdef CONFIG_PCI +extern void rc32434_time_init(void); +extern int __init rc32434_pcibridge_init(void); +#endif + +#define epldMask ((volatile unsigned char *)0xB900000d) + +static void rb_machine_restart(char *command) +{ +	/* just jump to the reset vector */ +	* (volatile unsigned *) KSEG1ADDR(0x18008000) = 0x80000001; +	((void (*)(void))KSEG1ADDR(0x1FC00000u))(); +} + +static void rb_machine_halt(void) +{ +	for(;;) continue; +} + +#ifdef CONFIG_CPU_HAS_WB +void (*__wbflush) (void); + +static void rb_write_buffer_flush(void) +{ +	__asm__ __volatile__ +	    ("sync\n\t" "nop\n\t" "loop: bc0f loop\n\t" "nop\n\t"); +} +#endif + +void __init plat_mem_setup(void) +{ +	unsigned int pciCntlVal; + +	board_time_init = rc32434_time_init; + +#ifdef CONFIG_CPU_HAS_WB +	__wbflush = rb_write_buffer_flush; +#endif +	_machine_restart = rb_machine_restart; +	_machine_halt = rb_machine_halt; +	/*_machine_power_off = rb_machine_power_halt;*/ +	pm_power_off = rb_machine_halt; + +	set_io_port_base(KSEG1); + +	pciCntlVal=rc32434_pci->pcic; +	pciCntlVal &= 0xFFFFFF7; +	rc32434_pci->pcic = pciCntlVal; + +#ifdef CONFIG_PCI +	/* Enable PCI interrupts in EPLD Mask register */ +	*epldMask = 0x0; +	*(epldMask + 1) = 0x0; +#endif +	write_c0_wired(0); +} + +const char *get_system_type(void) +{ +	return "MIPS RB500"; +} diff --git a/target/linux/rb532/files-2.6.23/arch/mips/rb500/time.c b/target/linux/rb532/files-2.6.23/arch/mips/rb500/time.c new file mode 100644 index 000000000..13320a6ca --- /dev/null +++ b/target/linux/rb532/files-2.6.23/arch/mips/rb500/time.c @@ -0,0 +1,94 @@ +/* +**************************************************************************** +* Carsten Langgaard, carstenl@mips.com +* Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved. +* +*************************************************************************** +* +*  This program is free software; you can distribute it and/or modify it +*  under the terms of the GNU General Public License (Version 2) as +*  published by the Free Software Foundation. +* +*  This program is distributed in the hope it will be useful, but WITHOUT +*  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +*  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License +*  for more details. +* +*  You should have received a copy of the GNU General Public License along +*  with this program; if not, write to the Free Software Foundation, Inc., +*  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +* +**************************************************************************** +* +* Setting up the clock on the MIPS boards. +* +**************************************************************************** +* P. Sadik Oct 10, 2003 +* +* Started change log. +* mips_counter_frequency is now calculated at run time, based on idt_cpu_freq. +* Code cleanup +**************************************************************************** +*/ + +#include <linux/autoconf.h> +#include <linux/init.h> +#include <linux/kernel_stat.h> +#include <linux/sched.h> +#include <linux/spinlock.h> +#include <linux/mc146818rtc.h> +#include <linux/irq.h> +#include <linux/timex.h> + +#include <asm/irq_cpu.h> +#include <asm/mipsregs.h> +#include <asm/ptrace.h> +#include <asm/debug.h> +#include <asm/rc32434/rc32434.h> + +static unsigned long r4k_offset; /* Amount to incr compare reg each time */ +static unsigned long r4k_cur;    /* What counter should be at next timer irq */ +extern unsigned int mips_hpt_frequency; +extern unsigned int idt_cpu_freq; + +/*  + * Figure out the r4k offset, the amount to increment the compare + * register for each time tick. There is no RTC available. + * + * The RC32434 counts at half the CPU *core* speed. + */ +static unsigned long __init cal_r4koff(void) +{ +	mips_hpt_frequency = idt_cpu_freq * IDT_CLOCK_MULT / 2; +	return (mips_hpt_frequency / HZ); +} + + +void __init rc32434_time_init(void) +{ +	unsigned int est_freq, flags; + +	local_irq_save(flags); + +	printk("calculating r4koff... "); +	r4k_offset = cal_r4koff(); +	printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); + +	est_freq = 2*r4k_offset*HZ;	 +	est_freq += 5000;	/* round */ +	est_freq -= est_freq%10000; +	printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,  +	       (est_freq%1000000)*100/1000000); +	local_irq_restore(flags); +} + +void __init plat_timer_setup(struct irqaction *irq) +{ +	/* we are using the cpu counter for timer interrupts */ +	setup_irq(MIPS_CPU_TIMER_IRQ, irq); + +	/* to generate the first timer interrupt */ +	r4k_cur = (read_c0_count() + r4k_offset); +	write_c0_compare(r4k_cur); +} +  | 
