1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2025-04-21 12:27:27 +03:00

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
This commit is contained in:
florian
2008-07-15 17:17:04 +00:00
parent 69f7e26c1a
commit 42c88ed264
40 changed files with 6692 additions and 0 deletions

View File

@@ -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;
}

View File

@@ -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,
};

View File

@@ -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);

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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";
}

View File

@@ -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);
}