Commit 1d89057b authored by Russell King's avatar Russell King

Merge flint.arm.linux.org.uk:/usr/src/bk/linux-2.6-sharp

into flint.arm.linux.org.uk:/usr/src/bk/linux-2.6-rmk
parents a263e250 f42083cc
README on the Compact Flash for Card Engines
============================================
There are three challenges in supporting the CF interface of the Card
Engines. First, every IO operation must be followed with IO to
another memory region. Second, the slot is wired for one-to-one
address mapping *and* it is wired for 16 bit access only. Second, the
interrupt request line from the CF device isn't wired.
The IOBARRIER issue is covered in README.IOBARRIER. This isn't an
onerous problem. Enough said here.
The addressing issue is solved in the
arch/arm/mach-lh7a40x/ide-lpd7a40x.c file with some awkward
work-arounds. We implement a special SELECT_DRIVE routine that is
called before the IDE driver performs its own SELECT_DRIVE. Our code
recognizes that the SELECT register cannot be modified without also
writing a command. It send an IDLE_IMMEDIATE command on selecting a
drive. The function also prevents drive select to the slave drive
since there can be only one. The awkward part is that the IDE driver,
even though we have a select procedure, also attempts to change the
drive by writing directly the SELECT register. This attempt is
explicitly blocked by the OUTB function--not pretty, but effective.
The lack of interrupts is a more serious problem. Even though the CF
card is fast when compared to a normal IDE device, we don't know that
the CF is really flash. A user could use one of the very small hard
drives being shipped with a CF interface. The IDE code includes a
check for interfaces that lack an IRQ. In these cases, submitting a
command to the IDE controller is followed by a call to poll for
completion. If the device isn't immediately ready, it schedules a
timer to poll again later.
README on the IOBARRIER for CardEngine IO
=========================================
Due to an unfortunate oversight when the Card Engines were designed,
the signals that control access to some peripherals, most notably the
SMC91C9111 ethernet controller, are not properly handled.
The symptom is that back to back IO with the peripheral returns
unreliable data. With the SMC chip, you'll see errors about the bank
register being 'screwed'.
The cause is that the AEN signal to the SMC chip does not transition
for every memory access. It is driven through the CPLD from the CS7
line of the CPU's static memory controller which is optimized to
eliminate unnecessary transitions. Yet, the SMC requires a transition
for every access. The Sharp website has more information on the
effect of this power conservation feature on peripheral interfacing.
The solution is to follow every access to the SMC chip with an access
to another memory region that will force the CPU to release the chip
select line. Note that it is important to guarantee that the access
will force the CPU off-chip. We map a page of SDRAM as if it were an
uncacheable IO device and read from it after every SMC IO operation.
SMC IO
BARRIER IO
You might be tempted to believe that we must access another device
attached to the static memory controller, but the empirical evidence
indicates that this is not so. Mapping 0x00000000 (flash) and
0xc0000000 (SDRAM) appear to have the same effect. Using SDRAM seems
to be faster.
README on Implementing Linux for Sharp's KEV7a400
=================================================
This product has been discontinued by Sharp. For the time being, the
partially implemented code remains in the kernel. At some point in
the future, either the code will be finished or it will be removed
completely. This depends primarily on how many of the development
boards are in the field.
README on Implementing Linux for the Logic PD LPD7A400-10
=========================================================
- CPLD memory mapping
The board designers chose to use high address lines for controlling
access to the CPLD registers. It turns out to be a big waste
because we're using an MMU and must map IO space into virtual
memory. The result is that we have to make a mapping for every
register.
- Serial Console
It may be OK not to use the serial console option if the user passes
the console device name to the kernel. This deserves some exploration.
README on Implementing Linux for the Logic PD LPD7A40X-10
=========================================================
- CPLD memory mapping
The board designers chose to use high address lines for controlling
access to the CPLD registers. It turns out to be a big waste
because we're using an MMU and must map IO space into virtual
memory. The result is that we have to make a mapping for every
register.
- Serial Console
It may be OK not to use the serial console option if the user passes
the console device name to the kernel. This deserves some exploration.
README on the Vectored Interrupt Controller of the LH7A404
==========================================================
The 404 revision of the LH7A40X series comes with two vectored
interrupts controllers. While the kernel does use some of the
features of these devices, it is far from the purpose for which they
were designed.
When this README was written, the implementation of the VICs was in
flux. It is possible that some details, especially with priorities,
will change.
The VIC support code is inspired by routines written by Sharp.
Priority Control
----------------
The significant reason for using the VIC's vectoring is to control
interrupt priorities. There are two tables in
arch/arm/mach-lh7a40x/irq-lh7a404.c that look something like this.
static unsigned char irq_pri_vic1[] = { IRQ_GPIO3INTR, };
static unsigned char irq_pri_vic2[] = {
IRQ_T3UI, IRQ_GPIO7INTR,
IRQ_UART1INTR, IRQ_UART2INTR, IRQ_UART3INTR, };
The initialization code reads these tables and inserts a vector
address and enable for each indicated IRQ. Vectored interrupts have
higher priority than non-vectored interrupts. So, on VIC1,
IRQ_GPIO3INTR will be served before any other non-FIQ interrupt. Due
to the way that the vectoring works, IRQ_T3UI is the next highest
priority followed by the other vectored interrupts on VIC2. After
that, the non-vectored interrupts are scanned in VIC1 then in VIC2.
ISR
---
The interrupt service routine macro get_irqnr() in
arch/arm/kernel/entry-armv.S scans the VICs for the next active
interrupt. The vectoring makes this code somewhat larger than it was
before using vectoring (refer to the LH7A400 implementation). In the
case where an interrupt is vectored, the implementation will tend to
be faster than the non-vectored version. However, the worst-case path
is longer.
It is worth noting that at present, there is no need to read
VIC2_VECTADDR because the register appears to be shared between the
controllers. The code is written such that if this changes, it ought
to still work properly.
Vector Addresses
----------------
The proper use of the vectoring hardware would jump to the ISR
specified by the vectoring address. Linux isn't structured to take
advantage of this feature, though it might be possible to change
things to support it.
In this implementation, the vectoring address is used to speed the
search for the active IRQ. The address is coded such that the lowest
6 bits store the IRQ number for vectored interrupts. These numbers
correspond to the bits in the interrupt status registers. IRQ zero is
the lowest interrupt bit in VIC1. IRQ 32 is the lowest interrupt bit
in VIC2. Because zero is a valid IRQ number and because we cannot
detect whether or not there is a valid vectoring address if that
address is zero, the eigth bit (0x100) is set for vectored interrupts.
The address for IRQ 0x18 (VIC2) is 0x118. Only the ninth bit is set
for the default handler on VIC1 and only the tenth bit is set for the
default handler on VIC2.
In other words.
0x000 - no active interrupt
0x1ii - vectored interrupt 0xii
0x2xx - unvectored interrupt on VIC1 (xx is don't care)
0x4xx - unvectored interrupt on VIC2 (xx is don't care)
......@@ -145,6 +145,14 @@ config ARCH_S3C2410
config ARCH_OMAP
bool "TI OMAP"
config ARCH_LH7A40X
bool "Sharp LH7A40X"
help
Say Y here for systems based on one of the Sharp LH7A40X
System on a Chip processors. These CPUs include an ARM922T
core with a wide array of integrated devices for
hand-held and low-power applications.
config ARCH_VERSATILE_PB
bool "Versatile PB"
help
......@@ -170,6 +178,8 @@ source "arch/arm/mach-omap/Kconfig"
source "arch/arm/mach-s3c2410/Kconfig"
source "arch/arm/mach-lh7a40x/Kconfig"
# Definitions to make life easier
config ARCH_ACORN
bool
......@@ -231,7 +241,7 @@ menu "General setup"
# Select various configuration options depending on the machine type
config DISCONTIGMEM
bool
depends on ARCH_EDB7211 || ARCH_SA1100
depends on ARCH_EDB7211 || ARCH_SA1100 || ARCH_LH7A40X
default y
help
Say Y to upport efficient handling of discontiguous physical memory,
......@@ -293,7 +303,7 @@ config ISA_DMA
config FIQ
bool
depends on ARCH_ACORN || ARCH_L7200
depends on ARCH_ACORN || ARCH_L7200 || ARCH_LH7A400
default y
# Compressed boot loader in ROM. Yes, we really want to ask about
......
......@@ -94,6 +94,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET) := 0xc0008000
machine-$(CONFIG_ARCH_ADIFCC) := adifcc
machine-$(CONFIG_ARCH_OMAP) := omap
machine-$(CONFIG_ARCH_S3C2410) := s3c2410
machine-$(CONFIG_ARCH_LH7A40X) := lh7a40x
machine-$(CONFIG_ARCH_VERSATILE_PB) := versatile
TEXTADDR := $(textaddr-y)
......
......@@ -54,6 +54,9 @@ params_phys-$(CONFIG_ARCH_ADIFCC) := 0xc0000100
zreladdr-$(CONFIG_ARCH_OMAP) := 0x10008000
params_phys-$(CONFIG_ARCH_OMAP) := 0x10000100
initrd_phys-$(CONFIG_ARCH_OMAP) := 0x10800000
zreladdr-$(CONFIG_ARCH_LH7A40X) := 0xc0008000
params_phys-$(CONFIG_ARCH_LH7A40X) := 0xc0000100
initrd_phys-$(CONFIG_ARCH_LH7A40X) := 0xc4000000
zreladdr-$(CONFIG_ARCH_S3C2410) := 0x30008000
params_phys-$(CONFIG_ARCH_S3C2410) := 0x30000100
zreladdr-$(CONFIG_ARCH_VERSATILE_PB) := 0x00008000
......
......@@ -73,6 +73,13 @@
.macro writeb, rb
str \rb, [r3, #0x14] @ UTDR
.endm
#elif defined(CONFIG_ARCH_LH7A40X)
.macro loadsp, rb
ldr \rb, =0x80000700 @ UART2 UARTBASE
.endm
.macro writeb, rb
strb \rb, [r3, #0]
.endm
#else
#error no serial architecture defined
#endif
......
This diff is collapsed.
This diff is collapsed.
......@@ -550,6 +550,33 @@
1002: @ exit busyuart
.endm
#elif defined(CONFIG_ARCH_LH7A40X)
@ It isn't known if this will be appropriate for every 40x
@ board.
.macro addruart,rx
mrc p15, 0, \rx, c1, c0
tst \rx, #1 @ MMU enabled?
ldr \rx, =0x80000700 @ physical base address
orrne \rx, \rx, #0xf8000000 @ virtual base
.endm
.macro senduart,rd,rx
strb \rd, [\rx] @ DATA
.endm
.macro busyuart,rd,rx @ spin while busy
1001: ldr \rd, [\rx, #0x10] @ STATUS
tst \rd, #1 << 3 @ BUSY (TX FIFO not empty)
bne 1001b @ yes, spin
.endm
.macro waituart,rd,rx @ wait for Tx FIFO room
1001: ldrb \rd, [\rx, #0x10] @ STATUS
tst \rd, #1 << 5 @ TXFF (TX FIFO full)
bne 1001b @ yes, spin
.endm
#elif defined(CONFIG_ARCH_VERSATILE_PB)
......
......@@ -789,6 +789,67 @@ ENTRY(soft_irq_mask)
.macro irq_prio_table
.endm
#elif defined(CONFIG_ARCH_LH7A400)
# if defined (CONFIG_ARCH_LH7A404)
# error "LH7A400 and LH7A404 are mutually exclusive"
# endif
.macro disable_fiq
.endm
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
mov \irqnr, #0
mov \base, #io_p2v(0x80000000) @ APB registers
ldr \irqstat, [\base, #0x500] @ PIC INTSR
1001: movs \irqstat, \irqstat, lsr #1 @ Shift into carry
bcs 1008f @ Bit set; irq found
add \irqnr, \irqnr, #1
bne 1001b @ Until no bits
b 1009f @ Nothing? Hmm.
1008: movs \irqstat, #1 @ Force !Z
1009:
.endm
.macro irq_prio_table
.endm
#elif defined(CONFIG_ARCH_LH7A404)
.macro disable_fiq
.endm
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
mov \irqnr, #0 @ VIC1 irq base
mov \base, #io_p2v(0x80000000) @ APB registers
add \base, \base, #0x8000
ldr \tmp, [\base, #0x0030] @ VIC1_VECTADDR
tst \tmp, #VA_VECTORED @ Direct vectored
bne 1002f
tst \tmp, #VA_VIC1DEFAULT @ Default vectored VIC1
ldrne \irqstat, [\base, #0] @ VIC1_IRQSTATUS
bne 1001f
add \base, \base, #(0xa000 - 0x8000)
ldr \tmp, [\base, #0x0030] @ VIC2_VECTADDR
tst \tmp, #VA_VECTORED @ Direct vectored
bne 1002f
ldr \irqstat, [\base, #0] @ VIC2_IRQSTATUS
mov \irqnr, #32 @ VIC2 irq base
1001: movs \irqstat, \irqstat, lsr #1 @ Shift into carry
bcs 1008f @ Bit set; irq found
add \irqnr, \irqnr, #1
bne 1001b @ Until no bits
b 1009f @ Nothing? Hmm.
1002: and \irqnr, \tmp, #0x3f @ Mask for valid bits
1008: movs \irqstat, #1 @ Force !Z
str \tmp, [\base, #0x0030] @ Clear vector
1009:
.endm
.macro irq_prio_table
.endm
#else
#error Unknown architecture
#endif
......
menu "LH7A40X Implementations"
config MACH_KEV7A400
bool "KEV7A400"
depends on ARCH_LH7A40X
select ARCH_LH7A400
help
Say Y here if you are using the Sharp KEV7A400 development
board. This hardware is discontinued, so I'd be very
suprised if you wanted this option.
config MACH_LPD7A400
bool "LPD7A400 Card Engine"
depends on ARCH_LH7A40X
select ARCH_LH7A400
select IDE_POLL
help
Say Y here if you are using Logic Product Development's
LPD7A400 CardEngine. For the time being, the LPD7A400 and
LPD7A404 options are mutually exclusive.
config MACH_LPD7A404
bool "LPD7A404 Card Engine"
depends on ARCH_LH7A40X
select ARCH_LH7A404
select IDE_POLL
help
Say Y here if you are using Logic Product Development's
LPD7A404 CardEngine. For the time being, the LPD7A400 and
LPD7A404 options are mutually exclusive.
config ARCH_LH7A400
bool
config ARCH_LH7A404
bool
endmenu
#
# Makefile for the linux kernel.
#
# Object file lists.
obj-y := fiq.o
# generic.o
obj-$(CONFIG_MACH_KEV7A400) += arch-kev7a400.o irq-lh7a400.o
obj-$(CONFIG_MACH_LPD7A400) += arch-lpd7a40x.o ide-lpd7a40x.o irq-lh7a400.o
obj-$(CONFIG_MACH_LPD7A404) += arch-lpd7a40x.o ide-lpd7a40x.o irq-lh7a404.o
obj-m :=
obj-n :=
obj- :=
/* arch/arm/mach-lh7a40x/arch-kev7a400.c
*
* Copyright (C) 2004 Logic Product Development
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
#include <linux/tty.h>
#include <linux/init.h>
#include <linux/device.h>
#include <asm/hardware.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/hardware.h> /* io_p2v() */
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/mach/map.h>
#include <linux/interrupt.h>
/* This function calls the board specific IRQ initialization function. */
extern void lh7a400_init_irq (void);
static struct map_desc kev7a400_io_desc[] __initdata = {
{ IO_VIRT, IO_PHYS, IO_SIZE, MT_DEVICE },
{ CPLD_VIRT, CPLD_PHYS, CPLD_SIZE, MT_DEVICE },
};
void __init kev7a400_map_io(void)
{
iotable_init (kev7a400_io_desc, ARRAY_SIZE (kev7a400_io_desc));
}
static u16 CPLD_IRQ_mask; /* Mask for CPLD IRQs, 1 == unmasked */
static void kev7a400_ack_cpld_irq (u32 irq)
{
CPLD_CL_INT = 1 << (irq - IRQ_KEV7A400_CPLD);
}
static void kev7a400_mask_cpld_irq (u32 irq)
{
CPLD_IRQ_mask &= ~(1 << (irq - IRQ_KEV7A400_CPLD));
CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
}
static void kev7a400_unmask_cpld_irq (u32 irq)
{
CPLD_IRQ_mask |= 1 << (irq - IRQ_KEV7A400_CPLD);
CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
}
static struct irqchip kev7a400_cpld_chip = {
.ack = kev7a400_ack_cpld_irq,
.mask = kev7a400_mask_cpld_irq,
.unmask = kev7a400_unmask_cpld_irq,
};
static void kev7a400_cpld_handler (unsigned int irq, struct irqdesc *desc,
struct pt_regs *regs)
{
u32 mask = CPLD_LATCHED_INTS;
irq = IRQ_KEV7A400_CPLD;
for (; mask; mask >>= 1, ++irq) {
if (mask & 1)
desc[irq].handle (irq, desc, regs);
}
}
void __init lh7a40x_init_board_irq (void)
{
int irq;
for (irq = IRQ_KEV7A400_CPLD;
irq < IRQ_KEV7A400_CPLD + NR_IRQ_BOARD; ++irq) {
set_irq_chip (irq, &kev7a400_cpld_chip);
set_irq_handler (irq, do_edge_IRQ);
set_irq_flags (irq, IRQF_VALID);
}
set_irq_chained_handler (IRQ_CPLD, kev7a400_cpld_handler);
/* Clear all CPLD interrupts */
CPLD_CL_INT = 0xff; /* CPLD_INTR_MMC_CD | CPLD_INTR_ETH_INT; */
GPIO_GPIOINTEN = 0; /* Disable all GPIO interrupts */
barrier();
#if 0
GPIO_INTTYPE1
= (GPIO_INTR_PCC1_CD | GPIO_INTR_PCC1_CD); /* Edge trig. */
GPIO_INTTYPE2 = 0; /* Falling edge & low-level */
GPIO_GPIOFEOI = 0xff; /* Clear all GPIO interrupts */
GPIO_GPIOINTEN = 0xff; /* Enable all GPIO interrupts */
init_FIQ();
#endif
}
MACHINE_START (KEV7A400, "Sharp KEV7a400")
MAINTAINER ("Marc Singer")
BOOT_MEM (0xc0000000, 0x80000000, io_p2v (0x80000000))
BOOT_PARAMS (0xc0000100)
MAPIO (kev7a400_map_io)
INITIRQ (lh7a400_init_irq)
MACHINE_END
/* arch/arm/mach-lh7a40x/arch-lpd7a40x.c
*
* Copyright (C) 2004 Logic Product Development
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
#include <linux/tty.h>
#include <linux/init.h>
#include <linux/device.h>
#include <asm/hardware.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/hardware.h> /* io_p2v() */
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/mach/map.h>
#include <linux/interrupt.h>
static struct resource smc91x_resources[] = {
[0] = {
.start = CPLD00_PHYS,
.end = CPLD00_PHYS + CPLD00_SIZE - 1, /* Only needs 16B */
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_LPD7A40X_ETH_INT,
.end = IRQ_LPD7A40X_ETH_INT,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device smc91x_device = {
.name = "smc91x",
.id = 0,
.num_resources = ARRAY_SIZE(smc91x_resources),
.resource = smc91x_resources,
};
#if 0
static struct resource lh7a40x_usbclient_resources[] = {
[0] = {
.start = USB_PHYS,
.end = (USB_PHYS + 0xFF),
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_USB,
.end = IRQ_USB,
.flags = IORESOURCE_IRQ,
},
};
static u64 lh7a40x_usbclient_dma_mask = 0xffffffffUL;
static struct platform_device lh7a40x_usbclient_device = {
.name = "lh7a40x-udc",
.id = 0,
.dev = {
.dma_mask = &lh7a40x_usbclient_dma_mask,
.coherent_dma_mask = 0xffffffffUL,
},
.num_resources = ARRAY_SIZE (lh7a40x_usbclient_resources),
.resource = lh7a40x_usbclient_resources,
};
#endif
#if defined (CONFIG_ARCH_LH7A404)
static struct resource lh7a404_usbhost_resources [] = {
[0] = {
.start = USBH_PHYS,
.end = (USBH_PHYS + 0xFF),
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_USHINTR,
.end = IRQ_USHINTR,
.flags = IORESOURCE_IRQ,
},
};
static u64 lh7a404_usbhost_dma_mask = 0xffffffffUL;
static struct platform_device lh7a404_usbhost_device = {
.name = "lh7a404-ohci",
.id = 0,
.dev = {
.dma_mask = &lh7a404_usbhost_dma_mask,
.coherent_dma_mask = 0xffffffffUL,
},
.num_resources = ARRAY_SIZE (lh7a404_usbhost_resources),
.resource = lh7a404_usbhost_resources,
};
#endif
static struct platform_device *lpd7a40x_devs[] __initdata = {
&smc91x_device,
/* &lh7a40x_usbclient_device, */
#if defined (CONFIG_ARCH_LH7A404)
&lh7a404_usbhost_device,
#endif
};
extern void lpd7a400_map_io (void);
static void __init lpd7a40x_init (void)
{
CPLD_CONTROL = 0x0; /* Enable LAN (Disable LCD) */
platform_add_devices (lpd7a40x_devs, ARRAY_SIZE (lpd7a40x_devs));
}
static void lh7a40x_ack_cpld_irq (u32 irq)
{
/* CPLD doesn't have ack capability */
}
static void lh7a40x_mask_cpld_irq (u32 irq)
{
switch (irq) {
case IRQ_LPD7A40X_ETH_INT:
CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x4;
break;
case IRQ_LPD7A400_TS:
CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x8;
break;
}
}
static void lh7a40x_unmask_cpld_irq (u32 irq)
{
switch (irq) {
case IRQ_LPD7A40X_ETH_INT:
CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x4;
break;
case IRQ_LPD7A400_TS:
CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x8;
break;
}
}
static struct irqchip lpd7a40x_cpld_chip = {
.ack = lh7a40x_ack_cpld_irq,
.mask = lh7a40x_mask_cpld_irq,
.unmask = lh7a40x_unmask_cpld_irq,
};
#define IRQ_DISPATCH(irq) irq_desc[irq].handle ((irq), &irq_desc[irq], regs)
static void lpd7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc,
struct pt_regs *regs)
{
unsigned int mask = CPLD_INTERRUPTS;
desc->chip->ack (irq);
if ((mask & 0x1) == 0) /* WLAN */
IRQ_DISPATCH (IRQ_LPD7A40X_ETH_INT);
if ((mask & 0x2) == 0) /* Touch */
IRQ_DISPATCH (IRQ_LPD7A400_TS);
desc->chip->unmask (irq); /* Level-triggered need this */
}
void __init lh7a40x_init_board_irq (void)
{
int irq;
/* Rev A (v2.8): PF0, PF1, PF2, and PF3 are available IRQs.
PF7 supports the CPLD.
Rev B (v3.4): PF0, PF1, and PF2 are available IRQs.
PF3 supports the CPLD.
(Some) LPD7A404 prerelease boards report a version
number of 0x16, but we force an override since the
hardware is of the newer variety.
*/
unsigned char cpld_version = CPLD_REVISION;
int pinCPLD = (cpld_version == 0x28) ? 7 : 3;
#if defined CONFIG_MACH_LPD7A404
cpld_version = 0x34; /* Override, for now */
#endif
/* First, configure user controlled GPIOF interrupts */
GPIO_PFDD &= ~0x0f; /* PF0-3 are inputs */
GPIO_INTTYPE1 &= ~0x0f; /* PF0-3 are level triggered */
GPIO_INTTYPE2 &= ~0x0f; /* PF0-3 are active low */
barrier ();
GPIO_GPIOFINTEN |= 0x0f; /* Enable PF0, PF1, PF2, and PF3 IRQs */
/* Then, configure CPLD interrupt */
CPLD_INTERRUPTS = 0x0c; /* Disable all CPLD interrupts */
GPIO_PFDD &= ~(1 << pinCPLD); /* Make input */
GPIO_INTTYPE1 |= (1 << pinCPLD); /* Edge triggered */
GPIO_INTTYPE2 &= ~(1 << pinCPLD); /* Active low */
barrier ();
GPIO_GPIOFINTEN |= (1 << pinCPLD); /* Enable */
/* Cascade CPLD interrupts */
for (irq = IRQ_BOARD_START;
irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) {
set_irq_chip (irq, &lpd7a40x_cpld_chip);
set_irq_handler (irq, do_edge_IRQ);
set_irq_flags (irq, IRQF_VALID);
}
set_irq_chained_handler ((cpld_version == 0x28)
? IRQ_CPLD_V28
: IRQ_CPLD_V34,
lpd7a40x_cpld_handler);
}
static struct map_desc lpd7a400_io_desc[] __initdata = {
{ IO_VIRT, IO_PHYS, IO_SIZE, MT_DEVICE },
/* Mapping added to work around chip select problems */
{ IOBARRIER_VIRT, IOBARRIER_PHYS, IOBARRIER_SIZE, MT_DEVICE },
{ CF_VIRT, CF_PHYS, CF_SIZE, MT_DEVICE },
/* This mapping is redundant since the smc driver performs another. */
/* { CPLD00_VIRT, CPLD00_PHYS, CPLD00_SIZE, MT_DEVICE }, */
{ CPLD02_VIRT, CPLD02_PHYS, CPLD02_SIZE, MT_DEVICE },
{ CPLD06_VIRT, CPLD06_PHYS, CPLD06_SIZE, MT_DEVICE },
{ CPLD08_VIRT, CPLD08_PHYS, CPLD08_SIZE, MT_DEVICE },
{ CPLD0C_VIRT, CPLD0C_PHYS, CPLD0C_SIZE, MT_DEVICE },
{ CPLD0E_VIRT, CPLD0E_PHYS, CPLD0E_SIZE, MT_DEVICE },
{ CPLD10_VIRT, CPLD10_PHYS, CPLD10_SIZE, MT_DEVICE },
{ CPLD12_VIRT, CPLD12_PHYS, CPLD12_SIZE, MT_DEVICE },
{ CPLD14_VIRT, CPLD14_PHYS, CPLD14_SIZE, MT_DEVICE },
{ CPLD16_VIRT, CPLD16_PHYS, CPLD16_SIZE, MT_DEVICE },
{ CPLD18_VIRT, CPLD18_PHYS, CPLD18_SIZE, MT_DEVICE },
{ CPLD1A_VIRT, CPLD1A_PHYS, CPLD1A_SIZE, MT_DEVICE },
};
void __init
lpd7a400_map_io(void)
{
iotable_init (lpd7a400_io_desc, ARRAY_SIZE (lpd7a400_io_desc));
/* Fixup (improve) Static Memory Controller settings */
SMC_BCR0 = 0x200039af; /* Boot Flash */
SMC_BCR6 = 0x1000fbe0; /* CPLD */
SMC_BCR7 = 0x1000b2c2; /* Compact Flash */
}
#ifdef CONFIG_MACH_LPD7A400
extern void lh7a400_init_irq (void);
MACHINE_START (LPD7A400, "Logic Product Development LPD7A400-10")
MAINTAINER ("Marc Singer")
BOOT_MEM (0xc0000000, 0x80000000, io_p2v (0x80000000))
BOOT_PARAMS (0xc0000100)
MAPIO (lpd7a400_map_io)
INITIRQ (lh7a400_init_irq)
INIT_MACHINE (lpd7a40x_init)
MACHINE_END
#endif
#ifdef CONFIG_MACH_LPD7A404
extern void lh7a404_init_irq (void);
MACHINE_START (LPD7A404, "Logic Product Development LPD7A404-10")
MAINTAINER ("Marc Singer")
BOOT_MEM (0xc0000000, 0x80000000, io_p2v (0x80000000))
BOOT_PARAMS (0xc0000100)
MAPIO (lpd7a400_map_io)
INITIRQ (lh7a404_init_irq)
INIT_MACHINE (lpd7a40x_init)
MACHINE_END
#endif
/*
* linux/arch/arm/lib/lh7a400-fiqhandler.S
* Copyright (C) 2002, Lineo, Inc.
* based on linux/arch/arm/lib/floppydma.S, which is
* Copyright (C) 1995, 1996 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
.text
.global fiqhandler_end
@ register usage:
@ r8 &interrupt controller registers
@ r9 &gpio registers
@ r11 work
@ r12 work
ENTRY(fiqhandler)
@ read the status register to find out which FIQ this is
ldr r12, [r8] @ intc->status
and r12, r12, #0xf @ only interested in low-order 4 bits
@ translate FIQ 0:3 to IRQ 23:26
@ disable this FIQ and enable the corresponding IRQ
str r12, [r8, #0xc] @ disable this FIQ
mov r12, r12, lsl #23 @ get the corresopnding IRQ bit
str r12, [r8, #0x8] @ enable that IRQ
subs pc, lr, #4
fiqhandler_end:
/* arch/arm/mach-lh7a40x/ide-lpd7a40x.c
*
* Copyright (C) 2004 Logic Product Development
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
#include <linux/config.h>
#include <linux/ide.h>
#include <asm/io.h>
#define IOBARRIER_READ readl (IOBARRIER_VIRT)
static u8 lpd7a40x_ide_inb (unsigned long port)
{
u16 v = (u16) readw (port & ~0x1);
IOBARRIER_READ;
if (port & 0x1)
v >>= 8;
return v & 0xff;
}
static u16 lpd7a40x_ide_inw (unsigned long port)
{
u16 v = (u16) readw (port);
IOBARRIER_READ;
return v;
}
static void lpd7a40x_ide_insw (unsigned long port, void *addr, u32 count)
{
while (count--) {
*((u16*) addr)++ = (u16) readw (port);
IOBARRIER_READ;
}
}
static u32 lpd7a40x_ide_inl (unsigned long port)
{
u32 v = (u16) readw (port);
IOBARRIER_READ;
v |= (u16) readw (port + 2);
IOBARRIER_READ;
return v;
}
static void lpd7a40x_ide_insl (unsigned long port, void *addr, u32 count)
{
while (count--) {
*((u16*) addr)++ = (u16) readw (port);
IOBARRIER_READ;
*((u16*) addr)++ = (u16) readw (port + 2);
IOBARRIER_READ;
}
}
/* lpd7a40x_ide_outb -- this function is complicated by the fact that
* the user wants to be able to do byte IO and the hardware cannot.
* In order to write the high byte, we need to write a short. So, we
* read before writing in order to maintain the register values that
* shouldn't change. This isn't a good idea for the data IO registers
* since reading from them will not return the current value. We
* expect that this function handles the control register adequately.
*/
static void lpd7a40x_ide_outb (u8 valueUser, unsigned long port)
{
/* Block writes to SELECT register. Draconian, but the only
* way to cope with this hardware configuration without
* modifying the SELECT_DRIVE call in the ide driver. */
if ((port & 0xf) == 0x6)
return;
if (port & 0x1) { /* Perform read before write. Only
* the COMMAND register needs
* this. */
u16 value = (u16) readw (port & ~0x1);
IOBARRIER_READ;
value = (value & 0x00ff) | (valueUser << 8);
writew (value, port & ~0x1);
IOBARRIER_READ;
}
else { /* Allow low-byte writes which seem to
* be OK. */
writeb (valueUser, port);
IOBARRIER_READ;
}
}
static void lpd7a40x_ide_outbsync (ide_drive_t *drive, u8 value,
unsigned long port)
{
lpd7a40x_ide_outb (value, port);
}
static void lpd7a40x_ide_outw (u16 value, unsigned long port)
{
writew (value, port);
IOBARRIER_READ;
}
static void lpd7a40x_ide_outsw (unsigned long port, void *addr, u32 count)
{
while (count-- > 0) {
writew (*((u16*) addr)++, port);
IOBARRIER_READ;
}
}
static void lpd7a40x_ide_outl (u32 value, unsigned long port)
{
writel (value, port);
IOBARRIER_READ;
}
static void lpd7a40x_ide_outsl (unsigned long port, void *addr, u32 count)
{
while (count-- > 0) {
writel (*((u32*) addr)++, port);
IOBARRIER_READ;
}
}
void lpd7a40x_SELECT_DRIVE (ide_drive_t *drive)
{
unsigned jifStart = jiffies;
#define WAIT_TIME (30*HZ/1000)
/* Check for readiness. */
while ((HWIF(drive)->INB(IDE_STATUS_REG) & 0x40) == 0)
if (jifStart <= jiffies + WAIT_TIME)
return;
/* Only allow one drive.
For more information, see Documentation/arm/Sharp-LH/ */
if (drive->select.all & (1<<4))
return;
/* OUTW so that the IDLE_IMMEDIATE (and not NOP) command is sent. */
HWIF(drive)->OUTW(drive->select.all | 0xe100, IDE_SELECT_REG);
}
void lpd7a40x_hwif_ioops (ide_hwif_t *hwif)
{
hwif->mmio = 2; /* Just for show */
hwif->irq = IDE_NO_IRQ; /* Stop this probing */
hwif->OUTB = lpd7a40x_ide_outb;
hwif->OUTBSYNC = lpd7a40x_ide_outbsync;
hwif->OUTW = lpd7a40x_ide_outw;
hwif->OUTL = lpd7a40x_ide_outl;
hwif->OUTSW = lpd7a40x_ide_outsw;
hwif->OUTSL = lpd7a40x_ide_outsl;
hwif->INB = lpd7a40x_ide_inb;
hwif->INW = lpd7a40x_ide_inw;
hwif->INL = lpd7a40x_ide_inl;
hwif->INSW = lpd7a40x_ide_insw;
hwif->INSL = lpd7a40x_ide_insl;
hwif->selectproc = lpd7a40x_SELECT_DRIVE;
}
/* arch/arm/mach-lh7a40x/irq-kev7a400.c
*
* Copyright (C) 2004 Coastal Environmental Systems
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
#include <linux/interrupt.h>
#include <linux/init.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/mach/hardware.h>
#include <asm/mach/irqs.h>
/* KEV7a400 CPLD IRQ handling */
static u16 CPLD_IRQ_mask; /* Mask for CPLD IRQs, 1 == unmasked */
static void
lh7a400_ack_cpld_irq (u32 irq)
{
CPLD_CL_INT = 1 << (irq - IRQ_KEV7A400_CPLD);
}
static void
lh7a400_mask_cpld_irq (u32 irq)
{
CPLD_IRQ_mask &= ~(1 << (irq - IRQ_KEV7A400_CPLD));
CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
}
static void
lh7a400_unmask_cpld_irq (u32 irq)
{
CPLD_IRQ_mask |= 1 << (irq - IRQ_KEV7A400_CPLD);
CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
}
static struct
irqchip lh7a400_cpld_chip = {
.ack = lh7a400_ack_cpld_irq,
.mask = lh7a400_mask_cpld_irq,
.unmask = lh7a400_unmask_cpld_irq,
};
static void
lh7a400_cpld_handler (unsigned int irq, struct irqdesc *desc,
struct pt_regs *regs)
{
u32 mask = CPLD_LATCHED_INTS;
irq = IRQ_KEV_7A400_CPLD;
for (; mask; mask >>= 1, ++irq) {
if (mask & 1)
desc[irq].handle (irq, desc, regs);
}
}
/* IRQ initialization */
void __init
lh7a400_init_board_irq (void)
{
int irq;
for (irq = IRQ_KEV7A400_CPLD;
irq < IRQ_KEV7A400_CPLD + NR_IRQ_KEV7A400_CPLD; ++irq) {
set_irq_chip (irq, &lh7a400_cpld_chip);
set_irq_handler (irq, do_edge_IRQ);
set_irq_flags (irq, IRQF_VALID);
}
set_irq_chained_handler (IRQ_CPLD, kev7a400_cpld_handler);
/* Clear all CPLD interrupts */
CPLD_CL_INT = 0xff; /* CPLD_INTR_MMC_CD | CPLD_INTR_ETH_INT; */
/* *** FIXME CF enabled in ide-probe.c */
GPIO_GPIOINTEN = 0; /* Disable all GPIO interrupts */
barrier();
GPIO_INTTYPE1
= (GPIO_INTR_PCC1_CD | GPIO_INTR_PCC1_CD); /* Edge trig. */
GPIO_INTTYPE2 = 0; /* Falling edge & low-level */
GPIO_GPIOFEOI = 0xff; /* Clear all GPIO interrupts */
GPIO_GPIOINTEN = 0xff; /* Enable all GPIO interrupts */
init_FIQ();
}
/* arch/arm/mach-lh7a40x/irq-lh7a400.c
*
* Copyright (C) 2004 Coastal Environmental Systems
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/arch/irq.h>
#include <asm/arch/irqs.h>
/* CPU IRQ handling */
static void lh7a400_mask_irq (u32 irq)
{
INTC_INTENC = (1 << irq);
}
static void lh7a400_unmask_irq (u32 irq)
{
INTC_INTENS = (1 << irq);
}
static void lh7a400_ack_gpio_irq (u32 irq)
{
GPIO_GPIOFEOI = (1 << IRQ_TO_GPIO (irq));
INTC_INTENC = (1 << irq);
}
static struct irqchip lh7a400_internal_chip = {
.ack = lh7a400_mask_irq, /* Level triggering -> mask is ack */
.mask = lh7a400_mask_irq,
.unmask = lh7a400_unmask_irq,
};
static struct irqchip lh7a400_gpio_chip = {
.ack = lh7a400_ack_gpio_irq,
.mask = lh7a400_mask_irq,
.unmask = lh7a400_unmask_irq,
};
/* IRQ initialization */
void __init lh7a400_init_irq (void)
{
int irq;
INTC_INTENC = 0xffffffff; /* Disable all interrupts */
GPIO_GPIOFINTEN = 0x00; /* Disable all GPIOF interrupts */
barrier ();
for (irq = 0; irq < NR_IRQS; ++irq) {
switch (irq) {
case IRQ_GPIO0INTR:
case IRQ_GPIO1INTR:
case IRQ_GPIO2INTR:
case IRQ_GPIO3INTR:
case IRQ_GPIO4INTR:
case IRQ_GPIO5INTR:
case IRQ_GPIO6INTR:
case IRQ_GPIO7INTR:
set_irq_chip (irq, &lh7a400_gpio_chip);
set_irq_handler (irq, do_level_IRQ); /* OK default */
break;
default:
set_irq_chip (irq, &lh7a400_internal_chip);
set_irq_handler (irq, do_level_IRQ);
}
set_irq_flags (irq, IRQF_VALID);
}
lh7a40x_init_board_irq ();
/* *** FIXME: the LH7a400 does use FIQ interrupts in some cases. For
the time being, these are not initialized. */
/* init_FIQ(); */
}
/* arch/arm/mach-lh7a40x/irq-lh7a404.c
*
* Copyright (C) 2004 Logic Product Development
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/arch/irq.h>
#include <asm/arch/irqs.h>
#define USE_PRIORITIES
/* See Documentation/arm/Sharp-LH/VectoredInterruptController for more
* information on using the vectored interrupt controller's
* prioritizing feature. */
static unsigned char irq_pri_vic1[] = {
#if defined (USE_PRIORITIES)
IRQ_GPIO3INTR,
#endif
};
static unsigned char irq_pri_vic2[] = {
#if defined (USE_PRIORITIES)
IRQ_T3UI, IRQ_GPIO7INTR,
IRQ_UART1INTR, IRQ_UART2INTR, IRQ_UART3INTR,
#endif
};
/* CPU IRQ handling */
static void lh7a404_vic1_mask_irq (u32 irq)
{
VIC1_INTENCLR = (1 << irq);
}
static void lh7a404_vic1_unmask_irq (u32 irq)
{
VIC1_INTEN = (1 << irq);
}
static void lh7a404_vic2_mask_irq (u32 irq)
{
VIC2_INTENCLR = (1 << (irq - 32));
}
static void lh7a404_vic2_unmask_irq (u32 irq)
{
VIC2_INTEN = (1 << (irq - 32));
}
static void lh7a404_vic1_ack_gpio_irq (u32 irq)
{
GPIO_GPIOFEOI = (1 << IRQ_TO_GPIO (irq));
VIC1_INTENCLR = (1 << irq);
}
static void lh7a404_vic2_ack_gpio_irq (u32 irq)
{
GPIO_GPIOFEOI = (1 << IRQ_TO_GPIO (irq));
VIC2_INTENCLR = (1 << irq);
}
static struct irqchip lh7a404_vic1_chip = {
.ack = lh7a404_vic1_mask_irq, /* Because level-triggered */
.mask = lh7a404_vic1_mask_irq,
.unmask = lh7a404_vic1_unmask_irq,
};
static struct irqchip lh7a404_vic2_chip = {
.ack = lh7a404_vic2_mask_irq, /* Because level-triggered */
.mask = lh7a404_vic2_mask_irq,
.unmask = lh7a404_vic2_unmask_irq,
};
static struct irqchip lh7a404_gpio_vic1_chip = {
.ack = lh7a404_vic1_ack_gpio_irq,
.mask = lh7a404_vic1_mask_irq,
.unmask = lh7a404_vic1_unmask_irq,
};
static struct irqchip lh7a404_gpio_vic2_chip = {
.ack = lh7a404_vic2_ack_gpio_irq,
.mask = lh7a404_vic2_mask_irq,
.unmask = lh7a404_vic2_unmask_irq,
};
/* IRQ initialization */
void __init lh7a404_init_irq (void)
{
int irq;
VIC1_INTENCLR = 0xffffffff;
VIC2_INTENCLR = 0xffffffff;
VIC1_INTSEL = 0; /* All IRQs */
VIC2_INTSEL = 0; /* All IRQs */
VIC1_NVADDR = VA_VIC1DEFAULT;
VIC2_NVADDR = VA_VIC2DEFAULT;
VIC1_VECTADDR = 0;
VIC2_VECTADDR = 0;
GPIO_GPIOFINTEN = 0x00; /* Disable all GPIOF interrupts */
barrier ();
/* Install prioritized interrupts, if there are any. */
/* The | 0x20*/
for (irq = 0; irq < 16; ++irq) {
(&VIC1_VAD0)[irq]
= (irq < ARRAY_SIZE (irq_pri_vic1))
? (irq_pri_vic1[irq] | VA_VECTORED) : 0;
(&VIC1_VECTCNTL0)[irq]
= (irq < ARRAY_SIZE (irq_pri_vic1))
? (irq_pri_vic1[irq] | VIC_CNTL_ENABLE) : 0;
(&VIC2_VAD0)[irq]
= (irq < ARRAY_SIZE (irq_pri_vic2))
? (irq_pri_vic2[irq] | VA_VECTORED) : 0;
(&VIC2_VECTCNTL0)[irq]
= (irq < ARRAY_SIZE (irq_pri_vic2))
? (irq_pri_vic2[irq] | VIC_CNTL_ENABLE) : 0;
}
for (irq = 0; irq < NR_IRQS; ++irq) {
switch (irq) {
case IRQ_GPIO0INTR:
case IRQ_GPIO1INTR:
case IRQ_GPIO2INTR:
case IRQ_GPIO3INTR:
case IRQ_GPIO4INTR:
case IRQ_GPIO5INTR:
case IRQ_GPIO6INTR:
case IRQ_GPIO7INTR:
set_irq_chip (irq, irq < 32
? &lh7a404_gpio_vic1_chip
: &lh7a404_gpio_vic2_chip);
set_irq_handler (irq, do_level_IRQ); /* OK default */
break;
default:
set_irq_chip (irq, irq < 32
? &lh7a404_vic1_chip
: &lh7a404_vic2_chip);
set_irq_handler (irq, do_level_IRQ);
}
set_irq_flags (irq, IRQF_VALID);
}
lh7a40x_init_board_irq ();
}
/* arch/arm/mach-lh7a40x/irq-lpd7a40x.c
*
* Copyright (C) 2004 Coastal Environmental Systems
* Copyright (C) 2004 Logic Product Development
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/arch/irqs.h>
static void lh7a40x_ack_cpld_irq (u32 irq)
{
/* CPLD doesn't have ack capability */
}
static void lh7a40x_mask_cpld_irq (u32 irq)
{
switch (irq) {
case IRQ_LPD7A40X_ETH_INT:
CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x4;
break;
case IRQ_LPD7A400_TS:
CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x8;
break;
}
}
static void lh7a40x_unmask_cpld_irq (u32 irq)
{
switch (irq) {
case IRQ_LPD7A40X_ETH_INT:
CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x4;
break;
case IRQ_LPD7A400_TS:
CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x8;
break;
}
}
static struct irqchip lh7a40x_cpld_chip = {
.ack = lh7a40x_ack_cpld_irq,
.mask = lh7a40x_mask_cpld_irq,
.unmask = lh7a40x_unmask_cpld_irq,
};
#define IRQ_DISPATCH(irq) irq_desc[irq].handle ((irq), &irq_desc[irq], regs)
static void lh7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc,
struct pt_regs *regs)
{
unsigned int mask = CPLD_INTERRUPTS;
desc->chip->ack (irq);
if ((mask & 0x1) == 0) /* WLAN */
IRQ_DISPATCH (IRQ_LPD7A40X_ETH_INT);
if ((mask & 0x2) == 0) /* Touch */
IRQ_DISPATCH (IRQ_LPD7A400_TS);
desc->chip->unmask (irq); /* Level-triggered need this */
}
/* IRQ initialization */
void __init lh7a40x_init_board_irq (void)
{
int irq;
/* Rev A (v2.8): PF0, PF1, PF2, and PF3 are available IRQs.
PF7 supports the CPLD.
Rev B (v3.4): PF0, PF1, and PF2 are available IRQs.
PF3 supports the CPLD.
(Some) LPD7A404 prerelease boards report a version
number of 0x16, but we force an override since the
hardware is of the newer variety.
*/
unsigned char cpld_version = CPLD_REVISION;
int pinCPLD;
#if defined CONFIG_MACH_LPD7A404
cpld_version = 0x34; /* Override, for now */
#endif
pinCPLD = (cpld_version == 0x28) ? 7 : 3;
/* First, configure user controlled GPIOF interrupts */
GPIO_PFDD &= ~0x0f; /* PF0-3 are inputs */
GPIO_INTTYPE1 &= ~0x0f; /* PF0-3 are level triggered */
GPIO_INTTYPE2 &= ~0x0f; /* PF0-3 are active low */
barrier ();
GPIO_GPIOFINTEN |= 0x0f; /* Enable PF0, PF1, PF2, and PF3 IRQs */
/* Then, configure CPLD interrupt */
CPLD_INTERRUPTS = 0x0c; /* Disable all CPLD interrupts */
GPIO_PFDD &= ~(1 << pinCPLD); /* Make input */
GPIO_INTTYPE1 |= (1 << pinCPLD); /* Edge triggered */
GPIO_INTTYPE2 &= ~(1 << pinCPLD); /* Active low */
barrier ();
GPIO_GPIOFINTEN |= (1 << pinCPLD); /* Enable */
/* Cascade CPLD interrupts */
for (irq = IRQ_BOARD_START;
irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) {
set_irq_chip (irq, &lh7a40x_cpld_chip);
set_irq_handler (irq, do_edge_IRQ);
set_irq_flags (irq, IRQF_VALID);
}
set_irq_chained_handler ((cpld_version == 0x28)
? IRQ_CPLD_V28
: IRQ_CPLD_V34,
lh7a40x_cpld_handler);
}
......@@ -79,7 +79,7 @@ config CPU_ARM920T
# ARM922T
config CPU_ARM922T
bool
depends on ARCH_CAMELOT
depends on ARCH_CAMELOT || ARCH_LH7A40X
default y
select CPU_32v4
select CPU_ABRT_EV4T
......
......@@ -15,8 +15,8 @@
#include <linux/init.h>
#include <linux/bootmem.h>
#if MAX_NUMNODES != 4
#error Fix Me Please
#if MAX_NUMNODES != 4 && MAX_NUMNODES != 16
# error Fix Me Please
#endif
/*
......@@ -29,8 +29,21 @@ pg_data_t discontig_node_data[MAX_NUMNODES] = {
{ .bdata = &node_bootmem_data[0] },
{ .bdata = &node_bootmem_data[1] },
{ .bdata = &node_bootmem_data[2] },
{ .bdata = &node_bootmem_data[3] }
{ .bdata = &node_bootmem_data[3] },
#if MAX_NUMNODES == 16
{ .bdata = &node_bootmem_data[4] },
{ .bdata = &node_bootmem_data[5] },
{ .bdata = &node_bootmem_data[6] },
{ .bdata = &node_bootmem_data[7] },
{ .bdata = &node_bootmem_data[8] },
{ .bdata = &node_bootmem_data[9] },
{ .bdata = &node_bootmem_data[10] },
{ .bdata = &node_bootmem_data[11] },
{ .bdata = &node_bootmem_data[12] },
{ .bdata = &node_bootmem_data[13] },
{ .bdata = &node_bootmem_data[14] },
{ .bdata = &node_bootmem_data[15] },
#endif
};
EXPORT_SYMBOL(discontig_node_data);
/* include/asm-arm/arch-lh7a40x/constants.h
*
* Copyright (C) 2004 Coastal Environmental Systems
* Copyright (C) 2004 Logic Product Development
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
#ifndef __ASM_ARCH_CONSTANTS_H
#define __ASM_ARCH_CONSTANTS_H
#include <linux/config.h>
/* Addressing constants */
/* SoC CPU IO addressing */
#define IO_PHYS (0x80000000)
#define IO_VIRT (0xf8000000)
#define IO_SIZE (0x0000B000)
#ifdef CONFIG_MACH_KEV7A400
# define CPLD_PHYS (0x20000000)
# define CPLD_VIRT (0xf2000000)
# define CPLD_SIZE PAGE_SIZE
#endif
#if defined (CONFIG_MACH_LPD7A400) || defined (CONFIG_MACH_LPD7A404)
# define IOBARRIER_PHYS 0xc0000000 /* Start of SDRAM */
/*# define IOBARRIER_PHYS 0x00000000 */ /* Start of flash */
# define IOBARRIER_VIRT 0xf0000000
# define IOBARRIER_SIZE PAGE_SIZE
# define CF_PHYS 0x60200000
# define CF_VIRT 0xf6020000
# define CF_SIZE (8*1024)
/* The IO mappings for the LPD CPLD are, unfortunately, sparse. */
# define CPLDX_PHYS(x) (0x70000000 | ((x) << 20))
# define CPLDX_VIRT(x) (0xf7000000 | ((x) << 16))
# define CPLD00_PHYS CPLDX_PHYS (0x00) /* Wired LAN */
# define CPLD00_VIRT CPLDX_VIRT (0x00)
# define CPLD00_SIZE PAGE_SIZE
# define CPLD02_PHYS CPLDX_PHYS (0x02)
# define CPLD02_VIRT CPLDX_VIRT (0x02)
# define CPLD02_SIZE PAGE_SIZE
# define CPLD06_PHYS CPLDX_PHYS (0x06)
# define CPLD06_VIRT CPLDX_VIRT (0x06)
# define CPLD06_SIZE PAGE_SIZE
# define CPLD08_PHYS CPLDX_PHYS (0x08)
# define CPLD08_VIRT CPLDX_VIRT (0x08)
# define CPLD08_SIZE PAGE_SIZE
# define CPLD0C_PHYS CPLDX_PHYS (0x0c)
# define CPLD0C_VIRT CPLDX_VIRT (0x0c)
# define CPLD0C_SIZE PAGE_SIZE
# define CPLD0E_PHYS CPLDX_PHYS (0x0e)
# define CPLD0E_VIRT CPLDX_VIRT (0x0e)
# define CPLD0E_SIZE PAGE_SIZE
# define CPLD10_PHYS CPLDX_PHYS (0x10)
# define CPLD10_VIRT CPLDX_VIRT (0x10)
# define CPLD10_SIZE PAGE_SIZE
# define CPLD12_PHYS CPLDX_PHYS (0x12)
# define CPLD12_VIRT CPLDX_VIRT (0x12)
# define CPLD12_SIZE PAGE_SIZE
# define CPLD14_PHYS CPLDX_PHYS (0x14)
# define CPLD14_VIRT CPLDX_VIRT (0x14)
# define CPLD14_SIZE PAGE_SIZE
# define CPLD16_PHYS CPLDX_PHYS (0x16)
# define CPLD16_VIRT CPLDX_VIRT (0x16)
# define CPLD16_SIZE PAGE_SIZE
# define CPLD18_PHYS CPLDX_PHYS (0x18)
# define CPLD18_VIRT CPLDX_VIRT (0x18)
# define CPLD18_SIZE PAGE_SIZE
# define CPLD1A_PHYS CPLDX_PHYS (0x1a)
# define CPLD1A_VIRT CPLDX_VIRT (0x1a)
# define CPLD1A_SIZE PAGE_SIZE
#endif
/* Timing constants */
#define XTAL_IN 14745600 /* 14.7456 MHz crystal */
#define PLL_CLOCK (XTAL_IN * 21) /* 309 MHz PLL clock */
#define MAX_HCLK_KHZ 100000 /* HCLK max limit ~100MHz */
#endif /* __ASM_ARCH_CONSTANTS_H */
/* include/asm-arm/arch-lh7a40x/dma.h
*
* Copyright (C) 2003 Coastal Environmental Systems
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
#ifndef __ASM_ARCH_DMA_H
#define __ASM_ARCH_DMA_H
#define MAX_DMA_ADDRESS 0xffffffff
#define MAX_DMA_CHANNELS 0 /* All DMA is internal to CPU */
#endif /* _ASM_ARCH_DMA_H */
/* include/asm-arm/arch-lh7a40x/hardware.h
*
* Copyright (C) 2004 Coastal Environmental Systems
*
* [ Substantially cribbed from include/asm-arm/arch-pxa/hardware.h ]
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
#ifndef __ASM_ARCH_HARDWARE_H
#define __ASM_ARCH_HARDWARE_H
#include <asm/mach-types.h>
#define io_p2v(x) (0xf0000000 | (((x) & 0xfff00000) >> 4) | ((x) & 0x0000ffff))
#define io_v2p(x) ( (((x) & 0x0fff0000) << 4) | ((x) & 0x0000ffff))
#ifdef __ASSEMBLY__
# define __REG(x) io_p2v(x)
# define __PREG(x) io_v2p(x)
#else
# if 0
# define __REG(x) (*((volatile u32 *)io_p2v(x)))
# else
/*
* This __REG() version gives the same results as the one above, except
* that we are fooling gcc somehow so it generates far better and smaller
* assembly code for access to contigous registers. It's a shame that gcc
* doesn't guess this by itself.
*/
#include <asm/types.h>
typedef struct { volatile u32 offset[4096]; } __regbase;
# define __REGP(x) ((__regbase *)((x)&~4095))->offset[((x)&4095)>>2]
# define __REG(x) __REGP(io_p2v(x))
typedef struct { volatile u16 offset[4096]; } __regbase16;
# define __REGP16(x) ((__regbase16 *)((x)&~4095))->offset[((x)&4095)>>2]
# define __REG16(x) __REGP16(io_p2v(x))
typedef struct { volatile u8 offset[4096]; } __regbase8;
# define __REGP8(x) ((__regbase8 *)((x)&~4095))->offset[((x)&4095)>>2]
# define __REG8(x) __REGP8(io_p2v(x))
#endif
/* Let's kick gcc's ass again... */
# define __REG2(x,y) \
( __builtin_constant_p(y) ? (__REG((x) + (y))) \
: (*(volatile u32 *)((u32)&__REG(x) + (y))) )
# define __PREG(x) (io_v2p((u32)&(x)))
#endif
#include "registers.h"
#endif /* _ASM_ARCH_HARDWARE_H */
/* include/asm-arm/arch-lh7a40x/ide.h
*
* Copyright (C) 2004 Logic Product Development
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
#ifndef __ASM_ARCH_IDE_H
#define __ASM_ARCH_IDE_H
#if defined (CONFIG_MACH_LPD7A400) || defined (CONFIG_MACH_LPD7A404)
/* This implementation of ide.h only applies to the LPD CardEngines.
* Thankfully, there is less to do for the KEV.
*/
#include <linux/config.h>
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/arch/registers.h>
#define IDE_REG_LINE (1<<12) /* A12 drives !REG */
#define IDE_ALT_LINE (1<<11) /* Unused A11 allows non-overlapping regions */
#define IDE_CONTROLREG_OFFSET (0xe)
void lpd7a40x_hwif_ioops (struct hwif_s* hwif);
static __inline__ void ide_init_hwif_ports (hw_regs_t *hw, int data_port,
int ctrl_port, int *irq)
{
ide_ioreg_t reg;
int i;
int regincr = 1;
memset (hw, 0, sizeof (*hw));
reg = (ide_ioreg_t) data_port;
for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
hw->io_ports[i] = reg;
reg += regincr;
}
hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
if (irq)
*irq = IDE_NO_IRQ;
}
static __inline__ void ide_init_default_hwifs (void)
{
hw_regs_t hw;
struct hwif_s* hwif;
ide_init_hwif_ports (&hw,
CF_VIRT + IDE_REG_LINE,
CF_VIRT + IDE_REG_LINE + IDE_ALT_LINE
+ IDE_CONTROLREG_OFFSET,
NULL);
ide_register_hw (&hw, &hwif);
lpd7a40x_hwif_ioops (hwif); /* Override IO routines */
}
#else
static __inline__ void ide_init_hwif_ports (hw_regs_t *hw, int data_port,
int ctrl_port, int *irq) {}
static __inline__ void ide_init_default_hwifs (void) {}
#endif
#endif
/* include/asm-arm/arch-lh7a40x/io.h
*
* Copyright (C) 2004 Coastal Environmental Systems
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
#ifndef __ASM_ARCH_IO_H
#define __ASM_ARCH_IO_H
#define IO_SPACE_LIMIT 0xffffffff
/* No ISA or PCI bus on this machine. */
#define __io(a) (a)
#define __mem_pci(a) ((unsigned long)(a))
#define __mem_isa(a) ((unsigned long)(a))
#endif /* __ASM_ARCH_IO_H */
/* include/asm-arm/arch-lh7a40x/irq.h
*
* Copyright (C) 2004 Logic Product Development
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
void __init lh7a40x_init_board_irq (void);
/* include/asm-arm/arch-lh7a40x/irqs.h
*
* Copyright (C) 2004 Coastal Environmental Systems
* Copyright (C) 2004 Logic Product Development
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
/* It is to be seen whether or not we can build a kernel for more than
* one board. For the time being, these macros assume that we cannot.
* Thus, it is OK to ifdef machine/board specific IRQ assignments.
*/
#ifndef __ASM_ARCH_IRQS_H
#define __ASM_ARCH_IRQS_H
#include <linux/config.h>
#define FIQ_START 80
#if defined (CONFIG_ARCH_LH7A400)
/* FIQs */
# define IRQ_GPIO0FIQ 0 /* GPIO External FIQ Interrupt on F0 */
# define IRQ_BLINT 1 /* Battery Low */
# define IRQ_WEINT 2 /* Watchdog Timer, WDT overflow */
# define IRQ_MCINT 3 /* Media Change, MEDCHG pin rising */
/* IRQs */
# define IRQ_CSINT 4 /* Audio Codec (ACI) */
# define IRQ_GPIO1INTR 5 /* GPIO External IRQ Interrupt on F1 */
# define IRQ_GPIO2INTR 6 /* GPIO External IRQ Interrupt on F2 */
# define IRQ_GPIO3INTR 7 /* GPIO External IRQ Interrupt on F3 */
# define IRQ_T1UI 8 /* Timer 1 underflow */
# define IRQ_T2UI 9 /* Timer 2 underflow */
# define IRQ_RTCMI 10
# define IRQ_TINTR 11 /* Clock State Controller 64 Hz tick (CSC) */
# define IRQ_UART1INTR 12
# define IRQ_UART2INTR 13
# define IRQ_LCDINTR 14
# define IRQ_SSIEOT 15 /* Synchronous Serial Interface (SSI) */
# define IRQ_UART3INTR 16
# define IRQ_SCIINTR 17 /* Smart Card Interface (SCI) */
# define IRQ_AACINTR 18 /* Advanced Audio Codec (AAC) */
# define IRQ_MMCINTR 19 /* Multimedia Card (MMC) */
# define IRQ_USBINTR 20
# define IRQ_DMAINTR 21
# define IRQ_T3UI 22 /* Timer 3 underflow */
# define IRQ_GPIO4INTR 23 /* GPIO External IRQ Interrupt on F4 */
# define IRQ_GPIO5INTR 24 /* GPIO External IRQ Interrupt on F5 */
# define IRQ_GPIO6INTR 25 /* GPIO External IRQ Interrupt on F6 */
# define IRQ_GPIO7INTR 26 /* GPIO External IRQ Interrupt on F7 */
# define IRQ_BMIINTR 27 /* Battery Monitor Interface (BMI) */
# define NR_IRQ_CPU 28 /* IRQs directly recognized by CPU */
/* Given IRQ, return GPIO interrupt number 0-7 */
# define IRQ_TO_GPIO(i) ((i) \
- (((i) > IRQ_GPIO3INTR) ? IRQ_GPIO4INTR - IRQ_GPIO3INTR - 1 : 0)\
- (((i) > IRQ_GPIO0INTR) ? IRQ_GPIO1INTR - IRQ_GPIO0INTR - 1 : 0))
#endif
#if defined (CONFIG_ARCH_LH7A404)
# define IRQ_BROWN 0 /* Brownout */
# define IRQ_WDTINTR 1 /* Watchdog Timer */
# define IRQ_COMMRX 2 /* ARM Comm Rx for Debug */
# define IRQ_COMMTX 3 /* ARM Comm Tx for Debug */
# define IRQ_T1UI 4 /* Timer 1 underflow */
# define IRQ_T2UI 5 /* Timer 2 underflow */
# define IRQ_CSINT 6 /* Codec Interrupt (shared by AAC on 404) */
# define IRQ_DMAM2P0 7 /* -- DMA Memory to Peripheral */
# define IRQ_DMAM2P1 8
# define IRQ_DMAM2P2 9
# define IRQ_DMAM2P3 10
# define IRQ_DMAM2P4 11
# define IRQ_DMAM2P5 12
# define IRQ_DMAM2P6 13
# define IRQ_DMAM2P7 14
# define IRQ_DMAM2P8 15
# define IRQ_DMAM2P9 16
# define IRQ_DMAM2M0 17 /* -- DMA Memory to Memory */
# define IRQ_DMAM2M1 18
# define IRQ_GPIO0INTR 19 /* -- GPIOF Interrupt */
# define IRQ_GPIO1INTR 20
# define IRQ_GPIO2INTR 21
# define IRQ_GPIO3INTR 22
# define IRQ_SOFT_V1_23 23 /* -- Unassigned */
# define IRQ_SOFT_V1_24 24
# define IRQ_SOFT_V1_25 25
# define IRQ_SOFT_V1_26 26
# define IRQ_SOFT_V1_27 27
# define IRQ_SOFT_V1_28 28
# define IRQ_SOFT_V1_29 29
# define IRQ_SOFT_V1_30 30
# define IRQ_SOFT_V1_31 31
# define IRQ_BLINT 32 /* Battery Low */
# define IRQ_BMIINTR 33 /* Battery Monitor */
# define IRQ_MCINTR 34 /* Media Change */
# define IRQ_TINTR 35 /* 64Hz Tick */
# define IRQ_WEINT 36 /* Watchdog Expired */
# define IRQ_RTCMI 37 /* Real-time Clock Match */
# define IRQ_UART1INTR 38 /* UART1 Interrupt (including error) */
# define IRQ_UART1ERR 39 /* UART1 Error */
# define IRQ_UART2INTR 40 /* UART2 Interrupt (including error) */
# define IRQ_UART2ERR 41 /* UART2 Error */
# define IRQ_UART3INTR 42 /* UART3 Interrupt (including error) */
# define IRQ_UART3ERR 43 /* UART3 Error */
# define IRQ_SCIINTR 44 /* Smart Card */
# define IRQ_TSCINTR 45 /* Touchscreen */
# define IRQ_KMIINTR 46 /* Keyboard/Mouse (PS/2) */
# define IRQ_GPIO4INTR 47 /* -- GPIOF Interrupt */
# define IRQ_GPIO5INTR 48
# define IRQ_GPIO6INTR 49
# define IRQ_GPIO7INTR 50
# define IRQ_T3UI 51 /* Timer 3 underflow */
# define IRQ_LCDINTR 52 /* LCD Controller */
# define IRQ_SSPINTR 53 /* Synchronous Serial Port */
# define IRQ_SDINTR 54 /* Secure Digital Port (MMC) */
# define IRQ_USBINTR 55 /* USB Device Port */
# define IRQ_USHINTR 56 /* USB Host Port */
# define IRQ_SOFT_V2_25 57 /* -- Unassigned */
# define IRQ_SOFT_V2_26 58
# define IRQ_SOFT_V2_27 59
# define IRQ_SOFT_V2_28 60
# define IRQ_SOFT_V2_29 61
# define IRQ_SOFT_V2_30 62
# define IRQ_SOFT_V2_31 63
# define NR_IRQ_CPU 64 /* IRQs directly recognized by CPU */
/* Given IRQ, return GPIO interrupt number 0-7 */
# define IRQ_TO_GPIO(i) ((i) \
- (((i) > IRQ_GPIO3INTR) ? IRQ_GPIO4INTR - IRQ_GPIO3INTR - 1 : 0)\
- IRQ_GPIO0INTR)
/* Vector Address constants */
# define VA_VECTORED 0x100 /* Set for vectored interrupt */
# define VA_VIC1DEFAULT 0x200 /* Set as default VECTADDR for VIC1 */
# define VA_VIC2DEFAULT 0x400 /* Set as default VECTADDR for VIC2 */
#endif
/* IRQ aliases */
#if !defined (IRQ_GPIO0INTR)
# define IRQ_GPIO0INTR IRQ_GPIO0FIQ
#endif
#define IRQ_TICK IRQ_TINTR
#define IRQ_PCC1_RDY IRQ_GPIO6INTR /* PCCard 1 ready */
#define IRQ_PCC2_RDY IRQ_GPIO7INTR /* PCCard 2 ready */
#ifdef CONFIG_MACH_KEV7A400
# define IRQ_TS IRQ_GPIOFIQ /* Touchscreen */
# define IRQ_CPLD IRQ_GPIO1INTR /* CPLD cascade */
# define IRQ_PCC1_CD IRQ_GPIO_F2 /* PCCard 1 card detect */
# define IRQ_PCC2_CD IRQ_GPIO_F3 /* PCCard 2 card detect */
#endif
#if defined (CONFIG_MACH_LPD7A400) || defined (CONFIG_MACH_LPD7A404)
# define IRQ_CPLD_V28 IRQ_GPIO7INTR /* CPLD cascade through GPIO_PF7 */
# define IRQ_CPLD_V34 IRQ_GPIO3INTR /* CPLD cascade through GPIO_PF3 */
#endif
/* System specific IRQs */
#define IRQ_BOARD_START NR_IRQ_CPU
#ifdef CONFIG_MACH_KEV7A400
# define IRQ_KEV7A400_CPLD IRQ_BOARD_START
# define NR_IRQ_BOARD 5
# define IRQ_KEV7A400_MMC_CD IRQ_KEV7A400_CPLD + 0 /* MMC Card Detect */
# define IRQ_KEV7A400_RI2 IRQ_KEV7A400_CPLD + 1 /* Ring Indicator 2 */
# define IRQ_KEV7A400_IDE_CF IRQ_KEV7A400_CPLD + 2 /* Compact Flash (?) */
# define IRQ_KEV7A400_ETH_INT IRQ_KEV7A400_CPLD + 3 /* Ethernet chip */
# define IRQ_KEV7A400_INT IRQ_KEV7A400_CPLD + 4
#endif
#if defined (CONFIG_MACH_LPD7A400) || defined (CONFIG_MACH_LPD7A404)
# define IRQ_LPD7A40X_CPLD IRQ_BOARD_START
# define NR_IRQ_BOARD 2
# define IRQ_LPD7A40X_ETH_INT IRQ_LPD7A40X_CPLD + 0 /* Ethernet chip */
# define IRQ_LPD7A400_TS IRQ_LPD7A40X_CPLD + 1 /* Touch screen */
#endif
#define NR_IRQS (NR_IRQ_CPU + NR_IRQ_BOARD)
#endif
/* include/asm-arm/arch-lh7a40x/memory.h
*
* Copyright (C) 2004 Coastal Environmental Systems
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
#ifndef __ASM_ARCH_MEMORY_H
#define __ASM_ARCH_MEMORY_H
#define BANKS_PER_NODE 1 /* Define as either 1 or 2 */
/*
* Task size: 3GB
*/
#define TASK_SIZE (0xbf000000UL) /* 0xc0000000? */
#define TASK_SIZE_26 (0x04000000UL)
/*
* This decides where the kernel will search for a free chunk of vm
* space during mmap's.
*/
#define TASK_UNMAPPED_BASE (0x40000000)
/*
* Page offset: 3GB
*/
#define PAGE_OFFSET (0xc0000000UL)
/*
* Physical DRAM offset.
*/
#define PHYS_OFFSET (0xc0000000UL)
/*
* physical vs virtual ram conversion
*/
#define __virt_to_phys__is_a_macro
#define __phys_to_virt__is_a_macro
#define __virt_to_phys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET)
#define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET)
/*
* Virtual view <-> DMA view memory address translations
* virt_to_bus: Used to translate the virtual address to an
* address suitable to be passed to set_dma_addr
* bus_to_virt: Used to convert an address for DMA operations
* to an address that the kernel can use.
*/
#define __virt_to_bus__is_a_macro
#define __bus_to_virt__is_a_macro
#define __virt_to_bus(x) __virt_to_phys(x)
#define __bus_to_virt(x) __phys_to_virt(x)
#ifdef CONFIG_DISCONTIGMEM
/*
* Because of the wide memory address space between physical RAM
* banks, it's convenient to use Linux's NUMA support to represent our
* memory map. Assuming all memory nodes have equal access
* characteristics, we then have a generic discontiguous memory setup.
*
* Of course, all this isn't mandatory for implementations with only
* one used memory bank. For those, simply undefine
* CONFIG_DISCONTIGMEM. However, keep in mind that a featurefull
* system will need more than 4MiB of RAM.
*
* The contiguous memory blocks are small enough that it pays to
* aggregate two banks into one node. Setting BANKS_PER_NODE to 2
* puts pairs of banks into a node.
*
* A typical layout would start like this:
*
* node 0: 0xc0000000
* 0xc1000000
* node 1: 0xc4000000
* 0xc5000000
* node 2: 0xc8000000
* 0xc9000000
*
* The proximity of the pairs of blocks makes it feasible to combine them.
*
*/
/*
* Given a kernel address, find the home node of the underlying memory.
*/
#if BANKS_PER_NODE==1
#define KVADDR_TO_NID(addr) \
( ((((unsigned long) (addr) - PAGE_OFFSET) >> 24) & 1)\
| ((((unsigned long) (addr) - PAGE_OFFSET) >> 25) & ~1))
#else /* 2 banks per node */
#define KVADDR_TO_NID(addr) \
((unsigned long) (addr) - PAGE_OFFSET) >> 26)
#endif
/*
* Given a page frame number, convert it to a node id.
*/
#if BANKS_PER_NODE==1
#define PFN_TO_NID(pfn) \
(((((pfn) - PHYS_PFN_OFFSET) >> (24 - PAGE_SHIFT)) & 1)\
| ((((pfn) - PHYS_PFN_OFFSET) >> (25 - PAGE_SHIFT)) & ~1))
#else /* 2 banks per node */
#define PFN_TO_NID(addr) \
(((pfn) - PHYS_PFN_OFFSET) >> (26 - PAGE_SHIFT))
#endif
/*
* Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
* and return the mem_map of that node.
*/
#define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID(kaddr))
/*
* Given a page frame number, find the owning node of the memory
* and return the mem_map of that node.
*/
#define PFN_TO_MAPBASE(pfn) NODE_MEM_MAP(PFN_TO_NID(pfn))
/*
* Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory
* and returns the index corresponding to the appropriate page in the
* node's mem_map.
*/
#if BANKS_PER_NODE==1
#define LOCAL_MAP_NR(addr) \
(((unsigned long)(addr) & 0x003fffff) >> PAGE_SHIFT)
#else /* 2 banks per node */
#define LOCAL_MAP_NR(addr) \
(((unsigned long)(addr) & 0x01ffffff) >> PAGE_SHIFT)
#endif
#else
#define PFN_TO_NID(addr) (0)
#endif
#endif
/* include/asm-arm/arch-lh7a40x/param.h
*
* Copyright (C) 2004 Coastal Environmental Systems
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
/* include/asm-arm/arch-lh7a40x/registers.h
*
* Copyright (C) 2004 Coastal Environmental Systems
* Copyright (C) 2004 Logic Product Development
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
#include <linux/config.h>
#include <asm/arch/constants.h>
#ifndef __ASM_ARCH_REGISTERS_H
#define __ASM_ARCH_REGISTERS_H
/* Physical register base addresses */
#define AC97_PHYS (0x80000000) /* AC97 Controller */
#define MMC_PHYS (0x80000100) /* Multimedia Card Controller */
#define USB_PHYS (0x80000200) /* USB Client */
#define SCI_PHYS (0x80000300) /* Secure Card Interface */
#define CSC_PHYS (0x80000400) /* Clock/State Controller */
#define INTC_PHYS (0x80000500) /* Interrupt Controller */
#define UART1_PHYS (0x80000600) /* UART1 Controller */
#define SIR_PHYS (0x80000600) /* IR Controller, same are UART1 */
#define UART2_PHYS (0x80000700) /* UART2 Controller */
#define UART3_PHYS (0x80000800) /* UART3 Controller */
#define DCDC_PHYS (0x80000900) /* DC to DC Controller */
#define ACI_PHYS (0x80000a00) /* Audio Codec Interface */
#define SSP_PHYS (0x80000b00) /* Synchronous ... */
#define TIMER_PHYS (0x80000c00) /* Timer Controller */
#define RTC_PHYS (0x80000d00) /* Real-time Clock */
#define GPIO_PHYS (0x80000e00) /* General Purpose IO */
#define BMI_PHYS (0x80000f00) /* Battery Monitor Interface */
#define WDT_PHYS (0x80001400) /* Watchdog Timer */
#define SMC_PHYS (0x80002000) /* Static Memory Controller */
#define SDRC_PHYS (0x80002400) /* SDRAM Controller */
#define DMAC_PHYS (0x80002800) /* DMA Controller */
#define CLCDC_PHYS (0x80003000) /* Color LCD Controller */
/* Physical registers of the LH7A404 */
#define VIC1_PHYS (0x80008000) /* Vectored Interrupt Controller 1 */
#define USBH_PHYS (0x80009000) /* USB OHCI host controller */
#define VIC2_PHYS (0x8000a000) /* Vectored Interrupt Controller 2 */
/*#define KBD_PHYS (0x80000e00) */
/*#define LCDICP_PHYS (0x80001000) */
/* Clock/State Controller register */
#define CSC_PWRCNT __REG(CSC_PHYS + 0x04) /* Power control */
#define CSC_PWRCNT_USBH_EN (1<<28) /* USB Host power enable */
/* Interrupt Controller registers */
#define INTC_INTSR __REG(INTC_PHYS + 0x00) /* Status */
#define INTC_INTRSR __REG(INTC_PHYS + 0x04) /* Raw Status */
#define INTC_INTENS __REG(INTC_PHYS + 0x08) /* Enable Set */
#define INTC_INTENC __REG(INTC_PHYS + 0x0c) /* Enable Clear */
/* Vectored Interrupted Controller registers */
#define VIC1_IRQSTATUS __REG(VIC1_PHYS + 0x00)
#define VIC1_FIQSTATUS __REG(VIC1_PHYS + 0x04)
#define VIC1_RAWINTR __REG(VIC1_PHYS + 0x08)
#define VIC1_INTSEL __REG(VIC1_PHYS + 0x0c)
#define VIC1_INTEN __REG(VIC1_PHYS + 0x10)
#define VIC1_INTENCLR __REG(VIC1_PHYS + 0x14)
#define VIC1_SOFTINT __REG(VIC1_PHYS + 0x18)
#define VIC1_SOFTINTCLR __REG(VIC1_PHYS + 0x1c)
#define VIC1_PROTECT __REG(VIC1_PHYS + 0x20)
#define VIC1_VECTADDR __REG(VIC1_PHYS + 0x30)
#define VIC1_NVADDR __REG(VIC1_PHYS + 0x34)
#define VIC1_VAD0 __REG(VIC1_PHYS + 0x100)
#define VIC1_VECTCNTL0 __REG(VIC1_PHYS + 0x200)
#define VIC2_IRQSTATUS __REG(VIC2_PHYS + 0x00)
#define VIC2_FIQSTATUS __REG(VIC2_PHYS + 0x04)
#define VIC2_RAWINTR __REG(VIC2_PHYS + 0x08)
#define VIC2_INTSEL __REG(VIC2_PHYS + 0x0c)
#define VIC2_INTEN __REG(VIC2_PHYS + 0x10)
#define VIC2_INTENCLR __REG(VIC2_PHYS + 0x14)
#define VIC2_SOFTINT __REG(VIC2_PHYS + 0x18)
#define VIC2_SOFTINTCLR __REG(VIC2_PHYS + 0x1c)
#define VIC2_PROTECT __REG(VIC2_PHYS + 0x20)
#define VIC2_VECTADDR __REG(VIC2_PHYS + 0x30)
#define VIC2_NVADDR __REG(VIC2_PHYS + 0x34)
#define VIC2_VAD0 __REG(VIC2_PHYS + 0x100)
#define VIC2_VECTCNTL0 __REG(VIC2_PHYS + 0x200)
#define VIC_CNTL_ENABLE (0x20)
/* USB Host registers (Open HCI compatible) */
#define USBH_CMDSTATUS __REG(USBH_PHYS + 0x08)
/* GPIO registers */
#define GPIO_INTTYPE1 __REG(GPIO_PHYS + 0x4c) /* Interrupt Type 1 (Edge) */
#define GPIO_INTTYPE2 __REG(GPIO_PHYS + 0x50) /* Interrupt Type 2 */
#define GPIO_GPIOFEOI __REG(GPIO_PHYS + 0x54) /* GPIO End-of-Interrupt */
#define GPIO_GPIOINTEN __REG(GPIO_PHYS + 0x58) /* GPIO Interrupt Enable */
#define GPIO_INTSTATUS __REG(GPIO_PHYS + 0x5c) /* GPIO Interrupt Status */
/* Static Memory Controller registers */
#define SMC_BCR0 __REG(SMC_PHYS + 0x00) /* Bank 0 Configuration */
#define SMC_BCR1 __REG(SMC_PHYS + 0x04) /* Bank 1 Configuration */
#define SMC_BCR2 __REG(SMC_PHYS + 0x08) /* Bank 2 Configuration */
#define SMC_BCR3 __REG(SMC_PHYS + 0x0C) /* Bank 3 Configuration */
#define SMC_BCR6 __REG(SMC_PHYS + 0x18) /* Bank 6 Configuration */
#define SMC_BCR7 __REG(SMC_PHYS + 0x1c) /* Bank 7 Configuration */
#ifdef CONFIG_MACH_KEV7A400
# define CPLD_RD_OPT_DIP_SW __REG16(CPLD_PHYS + 0x00) /* Read Option SW */
# define CPLD_WR_IO_BRD_CTL __REG16(CPLD_PHYS + 0x00) /* Write Control */
# define CPLD_RD_PB_KEYS __REG16(CPLD_PHYS + 0x02) /* Read Btn Keys */
# define CPLD_LATCHED_INTS __REG16(CPLD_PHYS + 0x04) /* Read INTR stat. */
# define CPLD_CL_INT __REG16(CPLD_PHYS + 0x04) /* Clear INTR stat */
# define CPLD_BOOT_MMC_STATUS __REG16(CPLD_PHYS + 0x06) /* R/O */
# define CPLD_RD_KPD_ROW_SENSE __REG16(CPLD_PHYS + 0x08)
# define CPLD_WR_PB_INT_MASK __REG16(CPLD_PHYS + 0x08)
# define CPLD_RD_BRD_DISP_SW __REG16(CPLD_PHYS + 0x0a)
# define CPLD_WR_EXT_INT_MASK __REG16(CPLD_PHYS + 0x0a)
# define CPLD_LCD_PWR_CNTL __REG16(CPLD_PHYS + 0x0c)
# define CPLD_SEVEN_SEG __REG16(CPLD_PHYS + 0x0e) /* 7 seg. LED mask */
#endif
#if defined (CONFIG_MACH_LPD7A400) || defined (CONFIG_MACH_LPD7A404)
# define CPLD_CONTROL __REG8(CPLD02_PHYS)
# define CPLD_SPI_DATA __REG8(CPLD06_PHYS)
# define CPLD_SPI_CONTROL __REG8(CPLD08_PHYS)
# define CPLD_SPI_EEPROM __REG8(CPLD0A_PHYS)
# define CPLD_INTERRUPTS __REG8(CPLD0C_PHYS) /* IRQ mask/status */
# define CPLD_BOOT_MODE __REG8(CPLD0E_PHYS)
# define CPLD_FLASH __REG8(CPLD10_PHYS)
# define CPLD_POWER_MGMT __REG8(CPLD12_PHYS)
# define CPLD_REVISION __REG8(CPLD14_PHYS)
# define CPLD_GPIO_EXT __REG8(CPLD16_PHYS)
# define CPLD_GPIO_DATA __REG8(CPLD18_PHYS)
# define CPLD_GPIO_DIR __REG8(CPLD1A_PHYS)
#endif
/* Timer registers */
#define TIMER_LOAD1 __REG(TIMER_PHYS + 0x00) /* Timer 1 initial value */
#define TIMER_VALUE1 __REG(TIMER_PHYS + 0x04) /* Timer 1 current value */
#define TIMER_CONTROL1 __REG(TIMER_PHYS + 0x08) /* Timer 1 control word */
#define TIMER_EOI1 __REG(TIMER_PHYS + 0x0c) /* Timer 1 interrupt clear */
#define TIMER_LOAD2 __REG(TIMER_PHYS + 0x20) /* Timer 2 initial value */
#define TIMER_VALUE2 __REG(TIMER_PHYS + 0x24) /* Timer 2 current value */
#define TIMER_CONTROL2 __REG(TIMER_PHYS + 0x28) /* Timer 2 control word */
#define TIMER_EOI2 __REG(TIMER_PHYS + 0x2c) /* Timer 2 interrupt clear */
#define TIMER_BUZZCON __REG(TIMER_PHYS + 0x40) /* Buzzer configuration */
#define TIMER_LOAD3 __REG(TIMER_PHYS + 0x80) /* Timer 3 initial value */
#define TIMER_VALUE3 __REG(TIMER_PHYS + 0x84) /* Timer 3 current value */
#define TIMER_CONTROL3 __REG(TIMER_PHYS + 0x88) /* Timer 3 control word */
#define TIMER_EOI3 __REG(TIMER_PHYS + 0x8c) /* Timer 3 interrupt clear */
#define TIMER_C_ENABLE (1<<7)
#define TIMER_C_PERIODIC (1<<6)
#define TIMER_C_FREERUNNING (0)
#define TIMER_C_2KHZ (0x00) /* 1.986 kHz */
#define TIMER_C_508KHZ (0x08)
/* GPIO registers */
#define GPIO_PFDD __REG(GPIO_PHYS + 0x34) /* PF direction */
#define GPIO_INTTYPE1 __REG(GPIO_PHYS + 0x4c) /* IRQ edge or lvl */
#define GPIO_INTTYPE2 __REG(GPIO_PHYS + 0x50) /* IRQ activ hi/lo */
#define GPIO_GPIOFEOI __REG(GPIO_PHYS + 0x54) /* GPIOF end of IRQ */
#define GPIO_GPIOFINTEN __REG(GPIO_PHYS + 0x58) /* GPIOF IRQ enable */
#define GPIO_INTSTATUS __REG(GPIO_PHYS + 0x5c) /* GPIOF IRQ latch */
#define GPIO_RAWINTSTATUS __REG(GPIO_PHYS + 0x60) /* GPIOF IRQ raw */
#endif /* _ASM_ARCH_REGISTERS_H */
/* include/asm-arm/arch-lh7a40x/serial.h
*
* Copyright (C) 2004 Coastal Environmental Systems
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
#ifndef __ASM_ARCH_SERIAL_H
#define __ASM_ARCH_SERIAL_H
#include <asm/arch/registers.h>
#define UART_R_DATA (0x00)
#define UART_R_FCON (0x04)
#define UART_R_BRCON (0x08)
#define UART_R_CON (0x0c)
#define UART_R_STATUS (0x10)
#define UART_R_RAWISR (0x14)
#define UART_R_INTEN (0x18)
#define UART_R_ISR (0x1c)
#endif /* _ASM_ARCH_SERIAL_H */
/* include/asm-arm/arch-lh7a40x/system.h
*
* Copyright (C) 2004 Coastal Environmental Systems
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
static inline void arch_idle(void)
{
cpu_do_idle ();
}
static inline void arch_reset(char mode)
{
cpu_reset (0);
}
/* include/asm-arm/arch-lh7a40x/time.h
*
* Copyright (C) 2004 Logic Product Development
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
#if HZ < 100
# define TIMER_CONTROL TIMER_CONTROL1
# define TIMER_LOAD TIMER_LOAD1
# define TIMER_CONSTANT (508469/HZ)
# define TIMER_MODE (TIMER_C_ENABLE | TIMER_C_PERIODIC | TIMER_C_508KHZ)
# define TIMER_EOI TIMER_EOI1
# define TIMER_IRQ IRQ_T1UI
#else
# define TIMER_CONTROL TIMER_CONTROL3
# define TIMER_LOAD TIMER_LOAD3
# define TIMER_CONSTANT (3686400/HZ)
# define TIMER_MODE (TIMER_C_ENABLE | TIMER_C_PERIODIC)
# define TIMER_EOI TIMER_EOI3
# define TIMER_IRQ IRQ_T3UI
#endif
static irqreturn_t
lh7a40x_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
TIMER_EOI = 0;
do_profile (regs);
do_leds();
do_set_rtc();
do_timer (regs);
return IRQ_HANDLED;
}
void __init time_init(void)
{
/* Stop/disable all timers */
TIMER_CONTROL1 = 0;
TIMER_CONTROL2 = 0;
TIMER_CONTROL3 = 0;
timer_irq.handler = lh7a40x_timer_interrupt;
timer_irq.flags |= SA_INTERRUPT;
setup_irq (TIMER_IRQ, &timer_irq);
TIMER_LOAD = TIMER_CONSTANT;
TIMER_CONTROL = TIMER_MODE;
}
/* include/asm-arm/arch-lh7a40x/timex.h
*
* Copyright (C) 2004 Coastal Environmental Systems
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
#include <asm/arch/constants.h>
#define CLOCK_TICK_RATE (PLL_CLOCK/6/16)
/*
#define CLOCK_TICK_RATE 3686400
#define CLOCK_TICK_FACTOR 80
*/
/* include/asm-arm/arch-lh7a40x/uncompress.h
*
* Copyright (C) 2004 Coastal Environmental Systems
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
#include <asm/arch/registers.h>
#ifndef UART_R_DATA
# define UART_R_DATA (0x00)
#endif
#ifndef UART_R_STATUS
# define UART_R_STATUS (0x10)
#endif
#define nTxRdy (0x20) /* Not TxReady (literally Tx FIFO full) */
/* Access UART with physical addresses before MMU is setup */
#define UART_STATUS (*(volatile unsigned long*) (UART2_PHYS + UART_R_STATUS))
#define UART_DATA (*(volatile unsigned long*) (UART2_PHYS + UART_R_DATA))
static __inline__ void putc (char ch)
{
while (UART_STATUS & nTxRdy)
;
UART_DATA = ch;
}
static void puts (const char* sz)
{
for (; *sz; ++sz) {
putc (*sz);
if (*sz == '\n')
putc ('\r');
}
}
/* NULL functions; we don't presently need them */
#define arch_decomp_setup()
#define arch_decomp_wdog()
/* include/asm-arm/arch-lh7a40x/vmalloc.h
*
* Copyright (C) 2004 Coastal Environmental Systems
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
/*
* Just any arbitrary offset to the start of the vmalloc VM area: the
* current 8MB value just means that there will be a 8MB "hole" after
* the physical memory until the kernel virtual memory starts. That
* means that any out-of-bounds memory accesses will hopefully be
* caught. The vmalloc() routines leaves a hole of 4kB (one page)
* between each vmalloced area for the same reason. ;)
*/
#define VMALLOC_OFFSET (8*1024*1024)
#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
#define VMALLOC_END (0xe8000000)
......@@ -10,7 +10,10 @@
#ifndef __ASM_ARM_NUMNODES_H
#define __ASM_ARM_NUMNODES_H
/* Max 4 Nodes */
#define NODES_SHIFT 2
#ifdef CONFIG_ARCH_LH7A40X
# define NODES_SHIFT 4 /* Max 16 nodes for the Sharp CPUs */
#else
# define NODES_SHIFT 2 /* Normally, Max 4 Nodes */
#endif
#endif
......@@ -188,7 +188,11 @@ static struct tagtable __tagtable_##fn __tag = { tag, fn }
/*
* Memory map description
*/
#define NR_BANKS 8
#ifdef CONFIG_ARCH_LH7A40X
# define NR_BANKS 16
#else
# define NR_BANKS 8
#endif
struct meminfo {
int nr_banks;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment