Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus

* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus: (21 commits)
  [MIPS] Remove unused maltasmp.h.
  [MIPS] Remove unused saa9730_uart.h.
  [MIPS] Rename MIPS sys_pipe syscall entry point to something MIPS-specific.
  [MIPS] 32-bit compat: Delete unused sys_truncate64 and sys_ftruncate64.
  [MIPS] TXx9: Fix some sparse warnings
  [MIPS] TXx9: Add 64-bit support
  [MIPS] TXx9: Cleanups for 64-bit support
  [MIPS] Cobalt: Fix I/O port resource range
  [MIPS] don't leak setup_early_printk() in userspace header
  [MIPS] Remove include/asm-mips/mips-boards/sead{,int}.h
  [MIPS] Remove asm-mips/mips-boards/atlas{,int}.h
  [MIPS] mips/sgi-ip22/ip28-berr.c: fix the build
  [MIPS] TXx9: Miscellaneous build fixes
  [MIPS] Routerboard 532: Support for base system
  [MIPS] IP32: Use common SGI button driver
  [MIPS] IP22: Use common SGI button driver
  [MIPS] IP22, IP28: Fix merge bug
  [MIPS] Tinker with constraints in <asm/atomic.h> to fix build error.
  [MIPS] Add missing prototypes to asm/page.h
  [MIPS] Fix missing prototypes in asm/fpu.h
  ...
This commit is contained in:
Linus Torvalds
2008-07-20 21:14:00 -07:00
74 changed files with 5240 additions and 1192 deletions
+20 -2
View File
@@ -330,6 +330,7 @@ config SGI_IP22
select SGI_HAS_DS1286
select SGI_HAS_I8042
select SGI_HAS_INDYDOG
select SGI_HAS_HAL2
select SGI_HAS_SEEQ
select SGI_HAS_WD93
select SGI_HAS_ZILOG
@@ -386,7 +387,6 @@ config SGI_IP28
select SGI_HAS_I8042
select SGI_HAS_INDYDOG
select SGI_HAS_HAL2
select SGI_HAS_HAL2
select SGI_HAS_SEEQ
select SGI_HAS_WD93
select SGI_HAS_ZILOG
@@ -558,6 +558,24 @@ config MACH_TX39XX
config MACH_TX49XX
bool "Toshiba TX49 series based machines"
config MIKROTIK_RB532
bool "Mikrotik RB532 boards"
select CEVT_R4K
select CSRC_R4K
select DMA_NONCOHERENT
select GENERIC_HARDIRQS_NO__DO_IRQ
select HW_HAS_PCI
select IRQ_CPU
select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
select SWAP_IO_SPACE
select BOOT_RAW
select GENERIC_GPIO
help
Support the Mikrotik(tm) RouterBoard 532 series,
based on the IDT RC32434 SoC.
config WR_PPMC
bool "Wind River PPMC board"
select CEVT_R4K
@@ -899,7 +917,7 @@ config BOOT_ELF32
config MIPS_L1_CACHE_SHIFT
int
default "4" if MACH_DECSTATION
default "4" if MACH_DECSTATION || MIKROTIK_RB532
default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM
default "4" if PMC_MSP4200_EVAL
default "5"
+7
View File
@@ -559,6 +559,13 @@ load-$(CONFIG_MACH_TX49XX) += 0xffffffff80100000
#
core-$(CONFIG_TOSHIBA_JMR3927) += arch/mips/txx9/jmr3927/
#
# Routerboard 532 board
#
core-$(CONFIG_MIKROTIK_RB532) += arch/mips/rb532/
cflags-$(CONFIG_MIKROTIK_RB532) += -Iinclude/asm-mips/mach-rc32434
load-$(CONFIG_MIKROTIK_RB532) += 0xffffffff80101000
#
# Toshiba RBTX4927 board or
# Toshiba RBTX4937 board
+2 -2
View File
@@ -81,8 +81,8 @@ void __init plat_mem_setup(void)
set_io_port_base(CKSEG1ADDR(GT_DEF_PCI0_IO_BASE));
/* I/O port resource must include LCD/buttons */
ioport_resource.end = 0x0fffffff;
/* I/O port resource */
ioport_resource.end = 0x01ffffff;
/* These resources have been reserved by VIA SuperI/O chip. */
for (i = 0; i < ARRAY_SIZE(cobalt_reserved_resources); i++)
File diff suppressed because it is too large Load Diff
-17
View File
@@ -129,23 +129,6 @@ out:
return error;
}
asmlinkage int sys_truncate64(const char __user *path, unsigned int high,
unsigned int low)
{
if ((int)high < 0)
return -EINVAL;
return sys_truncate(path, ((long) high << 32) | low);
}
asmlinkage int sys_ftruncate64(unsigned int fd, unsigned int high,
unsigned int low)
{
if ((int)high < 0)
return -EINVAL;
return sys_ftruncate(fd, ((long) high << 32) | low);
}
/*
* sys_execve() executes a new program.
*/
+1 -1
View File
@@ -354,7 +354,7 @@ einval: li v0, -EINVAL
sys sys_mkdir 2
sys sys_rmdir 1 /* 4040 */
sys sys_dup 1
sys sys_pipe 0
sys sysm_pipe 0
sys sys_times 1
sys sys_ni_syscall 0
sys sys_brk 1 /* 4045 */
+1 -1
View File
@@ -219,7 +219,7 @@ sys_call_table:
PTR sys_readv
PTR sys_writev
PTR sys_access /* 5020 */
PTR sys_pipe
PTR sysm_pipe
PTR sys_select
PTR sys_sched_yield
PTR sys_mremap
+1 -1
View File
@@ -141,7 +141,7 @@ EXPORT(sysn32_call_table)
PTR compat_sys_readv
PTR compat_sys_writev
PTR sys_access /* 6020 */
PTR sys_pipe
PTR sysm_pipe
PTR compat_sys_select
PTR sys_sched_yield
PTR sys_mremap
+1 -1
View File
@@ -247,7 +247,7 @@ sys_call_table:
PTR sys_mkdir
PTR sys_rmdir /* 4040 */
PTR sys_dup
PTR sys_pipe
PTR sysm_pipe
PTR compat_sys_times
PTR sys_ni_syscall
PTR sys_brk /* 4045 */
+8 -1
View File
@@ -40,7 +40,14 @@
#include <asm/sysmips.h>
#include <asm/uaccess.h>
asmlinkage int sys_pipe(nabi_no_regargs volatile struct pt_regs regs)
/*
* For historic reasons the pipe(2) syscall on MIPS has an unusual calling
* convention. It returns results in registers $v0 / $v1 which means there
* is no need for it to do verify the validity of a userspace pointer
* argument. Historically that used to be expensive in Linux. These days
* the performance advantage is negligible.
*/
asmlinkage int sysm_pipe(nabi_no_regargs volatile struct pt_regs regs)
{
int fd[2];
int error, res;
+1
View File
@@ -24,6 +24,7 @@
#include <asm/signal.h>
#include <asm/uaccess.h>
#include <asm/fpu.h>
#include <asm/fpu_emulator.h>
#define SIGNALLING_NAN 0x7ff800007ff80000LL
+1
View File
@@ -49,3 +49,4 @@ obj-$(CONFIG_TOSHIBA_RBTX4938) += fixup-rbtx4938.o
obj-$(CONFIG_VICTOR_MPC30X) += fixup-mpc30x.o
obj-$(CONFIG_ZAO_CAPCELLA) += fixup-capcella.o
obj-$(CONFIG_WR_PPMC) += fixup-wrppmc.o
obj-$(CONFIG_MIKROTIK_RB532) += pci-rc32434.o ops-rc32434.o fixup-rc32434.o
+69
View File
@@ -0,0 +1,69 @@
/*
* 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/mach-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 __devinit 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;
}
static void rc32434_pci_early_fixup(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);
}
}
/*
* The fixup applies to both the IDT and VIA devices present on the board
*/
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, rc32434_pci_early_fixup);
/* Do platform specific device initialization at pci_enable_device() time */
int pcibios_plat_dev_init(struct pci_dev *dev)
{
return 0;
}
+207
View File
@@ -0,0 +1,207 @@
/*
* 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.
*/
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/pci.h>
#include <linux/types.h>
#include <asm/cpu.h>
#include <asm/mach-rc32434/rc32434.h>
#include <asm/mach-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;
/*
* Don't scan too far, else there will be errors with plugged in
* daughterboard (rb564).
*/
if (bus->number == 0 && PCI_SLOT(devfn) > 21)
return 0;
retry:
ret = config_access(PCI_ACCESS_READ, bus, devfn, where, val);
/*
* Certain devices react delayed at device scan time, this
* gives them time to settle
*/
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,
};
+221
View File
@@ -0,0 +1,221 @@
/*
* 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.
*/
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/mach-rc32434/rc32434.h>
#include <asm/mach-rc32434/pci.h>
#define PCI_ACCESS_READ 0
#define PCI_ACCESS_WRITE 1
/* define an unsigned array for the PCI registers */
static unsigned int korina_cnfg_regs[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 pci_config_addr;
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))) {
pr_err(KERN_ERR "PCI init error!!!\n");
/* Not in Host Mode, return ERROR */
return -1;
}
/* Enables the Idle Grant mode, Arbiter Parking */
pcicdata |= (PCI_CTL_IGM | PCI_CTL_EAP | PCI_CTL_EN);
rc32434_pci->pcic = pcicdata; /* Enable the PCI bus Interface */
/* Zero out the PCI status & PCI Status Mask */
for (;;) {
pcicdata = rc32434_pci->pcis;
if (!(pcicdata & PCI_STAT_RIP))
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].address = (unsigned int) (PCI_ADDR_START);
/* setup the PCI map address as same as the local address */
rc32434_pci->pcilba[0].mapping = (unsigned int) (PCI_ADDR_START);
/* Setup PCILBA1 as MEM */
rc32434_pci->pcilba[0].control =
(((SIZE_256MB & 0x1f) << PCI_LBAC_SIZE_BIT) | PCI_ENDIAN_FLAG);
dummyread = rc32434_pci->pcilba[0].control; /* flush the CPU write Buffers */
rc32434_pci->pcilba[1].address = 0x60000000;
rc32434_pci->pcilba[1].mapping = 0x60000000;
/* setup PCILBA2 as IO Window */
rc32434_pci->pcilba[1].control =
(((SIZE_256MB & 0x1f) << PCI_LBAC_SIZE_BIT) | PCI_ENDIAN_FLAG);
dummyread = rc32434_pci->pcilba[1].control; /* flush the CPU write Buffers */
rc32434_pci->pcilba[2].address = 0x18C00000;
rc32434_pci->pcilba[2].mapping = 0x18FFFFFF;
/* setup PCILBA2 as IO Window */
rc32434_pci->pcilba[2].control =
(((SIZE_4MB & 0x1f) << PCI_LBAC_SIZE_BIT) | PCI_ENDIAN_FLAG);
dummyread = rc32434_pci->pcilba[2].control; /* flush the CPU write Buffers */
/* Setup PCILBA3 as IO Window */
rc32434_pci->pcilba[3].address = 0x18800000;
rc32434_pci->pcilba[3].mapping = 0x18800000;
rc32434_pci->pcilba[3].control =
((((SIZE_1MB & 0x1ff) << PCI_LBAC_SIZE_BIT) | PCI_LBAC_MSI) |
PCI_ENDIAN_FLAG);
dummyread = rc32434_pci->pcilba[3].control; /* flush the CPU write Buffers */
pci_config_addr = (unsigned int) (0x80000004);
for (loopCount = 0; loopCount < 24; loopCount++) {
rc32434_pci->pcicfga = pci_config_addr;
dummyread = rc32434_pci->pcicfga;
rc32434_pci->pcicfgd = korina_cnfg_regs[loopCount];
dummyread = rc32434_pci->pcicfgd;
pci_config_addr += 4;
}
rc32434_pci->pcitc =
(unsigned int) ((PCITC_RTIMER_VAL & 0xff) << PCI_TC_RTIMER_BIT) |
((PCITC_DTIMER_VAL & 0xff) << PCI_TC_DTIMER_BIT);
pcicntlval = rc32434_pci->pcic;
pcicntlval &= ~PCI_CTL_TNR;
rc32434_pci->pcic = pcicntlval;
pcicntlval = rc32434_pci->pcic;
return 0;
}
static int __init rc32434_pci_init(void)
{
pr_info("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);
+1 -1
View File
@@ -204,7 +204,7 @@ static int pcibios_enable_resources(struct pci_dev *dev, int mask)
* If we set up a device for bus mastering, we need to check the latency
* timer as certain crappy BIOSes forget to set it properly.
*/
unsigned int pcibios_max_latency = 255;
static unsigned int pcibios_max_latency = 255;
void pcibios_set_master(struct pci_dev *dev)
{
+7
View File
@@ -0,0 +1,7 @@
#
# Makefile for the RB532 board specific parts of the kernel
#
obj-y += irq.o time.o setup.o serial.o prom.o gpio.o devices.o
EXTRA_CFLAGS += -Werror
+331
View File
@@ -0,0 +1,331 @@
/*
* 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/mach-rc32434/rc32434.h>
#include <asm/mach-rc32434/dma.h>
#include <asm/mach-rc32434/dma_v.h>
#include <asm/mach-rc32434/eth.h>
#include <asm/mach-rc32434/rb.h>
#include <asm/mach-rc32434/integ.h>
#include <asm/mach-rc32434/gpio.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_BASE_ADDR + 0 * DMA_CHAN_OFFSET)
#define ETH0_TX_DMA_ADDR (DMA0_BASE_ADDR + 1 * DMA_CHAN_OFFSET)
/* NAND definitions */
#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_BASE_ADDR,
.end = ETH0_BASE_ADDR + sizeof(struct eth_regs),
.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 = "pata-rb532-cf",
.dev.platform_data = &cf_slot0_data,
.resource = cf_slot0_res,
.num_resources = ARRAY_SIZE(cf_slot0_res),
};
/* Resources and device for NAND */
static int rb532_dev_ready(struct mtd_info *mtd)
{
return readl(IDT434_REG_BASE + GPIOD) & GPIO_RDY;
}
static void rb532_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;
set_latch_u5(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
}
};
static struct platform_nand_data rb532_nand_data = {
.ctrl.dev_ready = rb532_dev_ready,
.ctrl.cmd_ctrl = rb532_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 = &rb532_nand_data,
};
static struct mtd_partition rb532_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 rb532_led = {
.name = "rb532-led",
.id = 0,
};
static struct gpio_keys_button rb532_gpio_btn[] = {
{
.gpio = 1,
.code = BTN_0,
.desc = "S1",
.active_low = 1,
}
};
static struct gpio_keys_platform_data rb532_gpio_btn_data = {
.buttons = rb532_gpio_btn,
.nbuttons = ARRAY_SIZE(rb532_gpio_btn),
};
static struct platform_device rb532_button = {
.name = "gpio-keys",
.id = -1,
.dev = {
.platform_data = &rb532_gpio_btn_data,
}
};
static struct resource rb532_wdt_res[] = {
{
.name = "rb532_wdt_res",
.start = INTEG0_BASE_ADDR,
.end = INTEG0_BASE_ADDR + sizeof(struct integ),
.flags = IORESOURCE_MEM,
}
};
static struct platform_device rb532_wdt = {
.name = "rc32434_wdt",
.id = -1,
.resource = rb532_wdt_res,
.num_resources = ARRAY_SIZE(rb532_wdt_res),
};
static struct platform_device *rb532_devs[] = {
&korina_dev0,
&nand_slot0,
&cf_slot0,
&rb532_led,
&rb532_button,
&rb532_wdt
};
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 void __init rb532_nand_setup(void)
{
switch (mips_machtype) {
case MACH_MIKROTIK_RB532A:
set_latch_u5(LO_FOFF | LO_CEX,
LO_ULED | LO_ALE | LO_CLE | LO_WPX);
break;
default:
set_latch_u5(LO_WPX | LO_FOFF | LO_CEX,
LO_ULED | LO_ALE | LO_CLE);
break;
}
/* Setup NAND specific settings */
rb532_nand_data.chip.nr_chips = 1;
rb532_nand_data.chip.nr_partitions = ARRAY_SIZE(rb532_partition_info);
rb532_nand_data.chip.partitions = rb532_partition_info;
rb532_nand_data.chip.chip_delay = NAND_CHIP_DELAY;
rb532_nand_data.chip.options = NAND_NO_AUTOINCR;
}
static int __init plat_setup_devices(void)
{
/* Look for the CF card reader */
if (!readl(CFG_DC_DEV1 + CFG_DC_DEVMASK))
rb532_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 */
rb532_nand_setup();
return platform_add_devices(rb532_devs, ARRAY_SIZE(rb532_devs));
}
static int __init setup_kmac(char *s)
{
printk(KERN_INFO "korina mac = %s\n", s);
parse_mac_addr(s);
return 0;
}
__setup("kmac=", setup_kmac);
arch_initcall(plat_setup_devices);
+220
View File
@@ -0,0 +1,220 @@
/*
* 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/gpio.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/mach-rc32434/rb.h>
struct rb532_gpio_reg __iomem *rb532_gpio_reg0;
EXPORT_SYMBOL(rb532_gpio_reg0);
struct mpmc_device dev3;
static struct resource rb532_gpio_reg0_res[] = {
{
.name = "gpio_reg0",
.start = (u32)(IDT434_REG_BASE + GPIOBASE),
.end = (u32)(IDT434_REG_BASE + GPIOBASE + sizeof(struct rb532_gpio_reg)),
.flags = IORESOURCE_MEM,
}
};
static struct resource rb532_dev3_ctl_res[] = {
{
.name = "dev3_ctl",
.start = (u32)(IDT434_REG_BASE + DEV3BASE),
.end = (u32)(IDT434_REG_BASE + DEV3BASE + sizeof(struct dev_reg)),
.flags = IORESOURCE_MEM,
}
};
void set_434_reg(unsigned reg_offs, unsigned bit, unsigned len, unsigned val)
{
unsigned flags, data;
unsigned i = 0;
spin_lock_irqsave(&dev3.lock, flags);
data = *(volatile unsigned *) (IDT434_REG_BASE + reg_offs);
for (i = 0; i != len; ++i) {
if (val & (1 << i))
data |= (1 << (i + bit));
else
data &= ~(1 << (i + bit));
}
writel(data, (IDT434_REG_BASE + reg_offs));
spin_unlock_irqrestore(&dev3.lock, flags);
}
EXPORT_SYMBOL(set_434_reg);
unsigned get_434_reg(unsigned reg_offs)
{
return readl(IDT434_REG_BASE + reg_offs);
}
EXPORT_SYMBOL(get_434_reg);
void set_latch_u5(unsigned char or_mask, unsigned char nand_mask)
{
unsigned flags;
spin_lock_irqsave(&dev3.lock, flags);
dev3.state = (dev3.state | or_mask) & ~nand_mask;
writel(dev3.state, &dev3.base);
spin_unlock_irqrestore(&dev3.lock, flags);
}
EXPORT_SYMBOL(set_latch_u5);
unsigned char get_latch_u5(void)
{
return dev3.state;
}
EXPORT_SYMBOL(get_latch_u5);
int rb532_gpio_get_value(unsigned gpio)
{
return readl(&rb532_gpio_reg0->gpiod) & (1 << gpio);
}
EXPORT_SYMBOL(rb532_gpio_get_value);
void rb532_gpio_set_value(unsigned gpio, int value)
{
unsigned tmp;
tmp = readl(&rb532_gpio_reg0->gpiod) & ~(1 << gpio);
if (value)
tmp |= 1 << gpio;
writel(tmp, (void *)&rb532_gpio_reg0->gpiod);
}
EXPORT_SYMBOL(rb532_gpio_set_value);
int rb532_gpio_direction_input(unsigned gpio)
{
writel(readl(&rb532_gpio_reg0->gpiocfg) & ~(1 << gpio),
(void *)&rb532_gpio_reg0->gpiocfg);
return 0;
}
EXPORT_SYMBOL(rb532_gpio_direction_input);
int rb532_gpio_direction_output(unsigned gpio, int value)
{
gpio_set_value(gpio, value);
writel(readl(&rb532_gpio_reg0->gpiocfg) | (1 << gpio),
(void *)&rb532_gpio_reg0->gpiocfg);
return 0;
}
EXPORT_SYMBOL(rb532_gpio_direction_output);
void rb532_gpio_set_int_level(unsigned gpio, int value)
{
unsigned tmp;
tmp = readl(&rb532_gpio_reg0->gpioilevel) & ~(1 << gpio);
if (value)
tmp |= 1 << gpio;
writel(tmp, (void *)&rb532_gpio_reg0->gpioilevel);
}
EXPORT_SYMBOL(rb532_gpio_set_int_level);
int rb532_gpio_get_int_level(unsigned gpio)
{
return readl(&rb532_gpio_reg0->gpioilevel) & (1 << gpio);
}
EXPORT_SYMBOL(rb532_gpio_get_int_level);
void rb532_gpio_set_int_status(unsigned gpio, int value)
{
unsigned tmp;
tmp = readl(&rb532_gpio_reg0->gpioistat);
if (value)
tmp |= 1 << gpio;
writel(tmp, (void *)&rb532_gpio_reg0->gpioistat);
}
EXPORT_SYMBOL(rb532_gpio_set_int_status);
int rb532_gpio_get_int_status(unsigned gpio)
{
return readl(&rb532_gpio_reg0->gpioistat) & (1 << gpio);
}
EXPORT_SYMBOL(rb532_gpio_get_int_status);
void rb532_gpio_set_func(unsigned gpio, int value)
{
unsigned tmp;
tmp = readl(&rb532_gpio_reg0->gpiofunc);
if (value)
tmp |= 1 << gpio;
writel(tmp, (void *)&rb532_gpio_reg0->gpiofunc);
}
EXPORT_SYMBOL(rb532_gpio_set_func);
int rb532_gpio_get_func(unsigned gpio)
{
return readl(&rb532_gpio_reg0->gpiofunc) & (1 << gpio);
}
EXPORT_SYMBOL(rb532_gpio_get_func);
int __init rb532_gpio_init(void)
{
rb532_gpio_reg0 = ioremap_nocache(rb532_gpio_reg0_res[0].start,
rb532_gpio_reg0_res[0].end -
rb532_gpio_reg0_res[0].start);
if (!rb532_gpio_reg0) {
printk(KERN_ERR "rb532: cannot remap GPIO register 0\n");
return -ENXIO;
}
dev3.base = ioremap_nocache(rb532_dev3_ctl_res[0].start,
rb532_dev3_ctl_res[0].end -
rb532_dev3_ctl_res[0].start);
if (!dev3.base) {
printk(KERN_ERR "rb532: cannot remap device controller 3\n");
return -ENXIO;
}
return 0;
}
arch_initcall(rb532_gpio_init);
+209
View File
@@ -0,0 +1,209 @@
/*
* 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.
*
* Copyright 2002 MontaVista Software Inc.
* Author: MontaVista Software, Inc.
* stevel@mvista.com or source@mvista.com
*/
#include <linux/bitops.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/io.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/bootinfo.h>
#include <asm/time.h>
#include <asm/mipsregs.h>
#include <asm/system.h>
#include <asm/mach-rc32434/rc32434.h>
struct intr_group {
u32 mask; /* mask of valid bits in pending/mask registers */
volatile u32 *base_addr;
};
#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 struct intr_group intr_group[NUM_INTR_GROUPS] = {
{
.mask = 0x0000efff,
.base_addr = (u32 *) KSEG1ADDR(IC_GROUP0_PEND + 0 * IC_GROUP_OFFSET)},
{
.mask = 0x00001fff,
.base_addr = (u32 *) KSEG1ADDR(IC_GROUP0_PEND + 1 * IC_GROUP_OFFSET)},
{
.mask = 0x00000007,
.base_addr = (u32 *) KSEG1ADDR(IC_GROUP0_PEND + 2 * IC_GROUP_OFFSET)},
{
.mask = 0x0003ffff,
.base_addr = (u32 *) KSEG1ADDR(IC_GROUP0_PEND + 3 * IC_GROUP_OFFSET)},
{
.mask = 0xffffffff,
.base_addr = (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;
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 rb532_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 rb532_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 void rb532_mask_and_ack_irq(unsigned int irq_nr)
{
rb532_disable_irq(irq_nr);
ack_local_irq(group_to_ip(irq_to_group(irq_nr)));
}
static struct irq_chip rc32434_irq_type = {
.name = "RB532",
.ack = rb532_disable_irq,
.mask = rb532_disable_irq,
.mask_ack = rb532_mask_and_ack_irq,
.unmask = rb532_enable_irq,
};
void __init arch_init_irq(void)
{
int i;
pr_info("Initializing IRQ's: %d out of %d\n", RC32434_NR_IRQS, NR_IRQS);
for (i = 0; i < RC32434_NR_IRQS; i++)
set_irq_chip_and_handler(i, &rc32434_irq_type,
handle_level_irq);
}
/* 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) {
do_IRQ(7);
} else {
ip = (cp0_cause & 0x7c00);
if (ip) {
group = 21 + (fls(ip) - 32);
addr = intr_group[group].base_addr;
pend = READ_PEND(addr);
pend &= ~READ_MASK(addr); /* only unmasked interrupts */
pend = 39 + (fls(pend) - 32);
do_IRQ((group << 5) + pend);
}
}
}

Some files were not shown because too many files have changed in this diff Show More