Commit b404fc90 authored by Anton Altaparmakov's avatar Anton Altaparmakov

Merge cantab.net:/home/src/bklinux-2.6

into cantab.net:/home/src/ntfs-2.6
parents e2b48faa 3dc567d8
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)
VERSION = 2 VERSION = 2
PATCHLEVEL = 6 PATCHLEVEL = 6
SUBLEVEL = 6 SUBLEVEL = 6
EXTRAVERSION =-rc3 EXTRAVERSION =
NAME=Zonked Quokka NAME=Zonked Quokka
# *DOCUMENTATION* # *DOCUMENTATION*
......
...@@ -145,6 +145,14 @@ config ARCH_S3C2410 ...@@ -145,6 +145,14 @@ config ARCH_S3C2410
config ARCH_OMAP config ARCH_OMAP
bool "TI 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 config ARCH_VERSATILE_PB
bool "Versatile PB" bool "Versatile PB"
help help
...@@ -170,6 +178,8 @@ source "arch/arm/mach-omap/Kconfig" ...@@ -170,6 +178,8 @@ source "arch/arm/mach-omap/Kconfig"
source "arch/arm/mach-s3c2410/Kconfig" source "arch/arm/mach-s3c2410/Kconfig"
source "arch/arm/mach-lh7a40x/Kconfig"
# Definitions to make life easier # Definitions to make life easier
config ARCH_ACORN config ARCH_ACORN
bool bool
...@@ -231,7 +241,7 @@ menu "General setup" ...@@ -231,7 +241,7 @@ menu "General setup"
# Select various configuration options depending on the machine type # Select various configuration options depending on the machine type
config DISCONTIGMEM config DISCONTIGMEM
bool bool
depends on ARCH_EDB7211 || ARCH_SA1100 depends on ARCH_EDB7211 || ARCH_SA1100 || ARCH_LH7A40X
default y default y
help help
Say Y to upport efficient handling of discontiguous physical memory, Say Y to upport efficient handling of discontiguous physical memory,
...@@ -293,7 +303,7 @@ config ISA_DMA ...@@ -293,7 +303,7 @@ config ISA_DMA
config FIQ config FIQ
bool bool
depends on ARCH_ACORN || ARCH_L7200 depends on ARCH_ACORN || ARCH_L7200 || ARCH_LH7A400
default y default y
# Compressed boot loader in ROM. Yes, we really want to ask about # Compressed boot loader in ROM. Yes, we really want to ask about
......
...@@ -94,6 +94,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET) := 0xc0008000 ...@@ -94,6 +94,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET) := 0xc0008000
machine-$(CONFIG_ARCH_ADIFCC) := adifcc machine-$(CONFIG_ARCH_ADIFCC) := adifcc
machine-$(CONFIG_ARCH_OMAP) := omap machine-$(CONFIG_ARCH_OMAP) := omap
machine-$(CONFIG_ARCH_S3C2410) := s3c2410 machine-$(CONFIG_ARCH_S3C2410) := s3c2410
machine-$(CONFIG_ARCH_LH7A40X) := lh7a40x
machine-$(CONFIG_ARCH_VERSATILE_PB) := versatile machine-$(CONFIG_ARCH_VERSATILE_PB) := versatile
TEXTADDR := $(textaddr-y) TEXTADDR := $(textaddr-y)
......
...@@ -54,6 +54,9 @@ params_phys-$(CONFIG_ARCH_ADIFCC) := 0xc0000100 ...@@ -54,6 +54,9 @@ params_phys-$(CONFIG_ARCH_ADIFCC) := 0xc0000100
zreladdr-$(CONFIG_ARCH_OMAP) := 0x10008000 zreladdr-$(CONFIG_ARCH_OMAP) := 0x10008000
params_phys-$(CONFIG_ARCH_OMAP) := 0x10000100 params_phys-$(CONFIG_ARCH_OMAP) := 0x10000100
initrd_phys-$(CONFIG_ARCH_OMAP) := 0x10800000 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 zreladdr-$(CONFIG_ARCH_S3C2410) := 0x30008000
params_phys-$(CONFIG_ARCH_S3C2410) := 0x30000100 params_phys-$(CONFIG_ARCH_S3C2410) := 0x30000100
zreladdr-$(CONFIG_ARCH_VERSATILE_PB) := 0x00008000 zreladdr-$(CONFIG_ARCH_VERSATILE_PB) := 0x00008000
......
...@@ -73,6 +73,13 @@ ...@@ -73,6 +73,13 @@
.macro writeb, rb .macro writeb, rb
str \rb, [r3, #0x14] @ UTDR str \rb, [r3, #0x14] @ UTDR
.endm .endm
#elif defined(CONFIG_ARCH_LH7A40X)
.macro loadsp, rb
ldr \rb, =0x80000700 @ UART2 UARTBASE
.endm
.macro writeb, rb
strb \rb, [r3, #0]
.endm
#else #else
#error no serial architecture defined #error no serial architecture defined
#endif #endif
......
This diff is collapsed.
This diff is collapsed.
...@@ -550,6 +550,33 @@ ...@@ -550,6 +550,33 @@
1002: @ exit busyuart 1002: @ exit busyuart
.endm .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) #elif defined(CONFIG_ARCH_VERSATILE_PB)
......
...@@ -789,6 +789,67 @@ ENTRY(soft_irq_mask) ...@@ -789,6 +789,67 @@ ENTRY(soft_irq_mask)
.macro irq_prio_table .macro irq_prio_table
.endm .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 #else
#error Unknown architecture #error Unknown architecture
#endif #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);
}
menu "TI OMAP Implementations" menu "TI OMAP Implementations"
choice comment "OMAP Core Type"
prompt "OMAP Core Type"
config ARCH_OMAP730
depends on ARCH_OMAP depends on ARCH_OMAP
default ARCH_OMAP1510 bool "OMAP730 Based System"
select CPU_ARM926T
config ARCH_OMAP1510 config ARCH_OMAP1510
bool "OMAP-1510 Based System" depends on ARCH_OMAP
default y
bool "OMAP1510 Based System"
select CPU_ARM925T select CPU_ARM925T
select CPU_DCACHE_WRITETHROUGH select CPU_DCACHE_WRITETHROUGH
config ARCH_OMAP1610 config ARCH_OMAP1610
bool "OMAP-1610 Based System" depends on ARCH_OMAP
bool "OMAP1610 Based System"
select CPU_ARM926T select CPU_ARM926T
endchoice config ARCH_OMAP5912
choice
prompt "OMAP Board Type"
depends on ARCH_OMAP depends on ARCH_OMAP
default MACH_OMAP_INNOVATOR bool "OMAP5912 Based System"
select CPU_ARM926T
comment "OMAP Board Type"
config MACH_OMAP_INNOVATOR config MACH_OMAP_INNOVATOR
bool "TI Innovator" bool "TI Innovator"
default y
depends on ARCH_OMAP1510 || ARCH_OMAP1610 depends on ARCH_OMAP1510 || ARCH_OMAP1610
help help
TI OMAP 1510 or 1610 Innovator board support. Say Y here if you TI OMAP 1510 or 1610 Innovator board support. Say Y here if you
have such a board. have such a board.
config MACH_OMAP_H2
bool "TI H2 Support"
depends on ARCH_OMAP1610
select MACH_OMAP_INNOVATOR
help
TI OMAP 1610 H2 board support. Say Y here if you have such
a board.
config MACH_OMAP_H3
bool "TI H3 Support"
depends on ARCH_OMAP1610
help
TI OMAP 1610 H3 board support. Say Y here if you have such
a board.
config MACH_OMAP_H4
bool "TI H4 Support"
depends on ARCH_OMAP1610
help
TI OMAP 1610 H4 board support. Say Y here if you have such
a board.
config MACH_OMAP_OSK
bool "TI OSK Support"
depends on ARCH_OMAP5912
help
TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here
if you have such a board.
config MACH_OMAP_PERSEUS2
bool "TI Perseus2"
depends on ARCH_OMAP730
select LEDS
select LEDS_TIMER
select LEDS_CPU
help
Support for TI OMAP 730 Perseus2 board. Say Y here if you have such
a board.
config MACH_OMAP_GENERIC config MACH_OMAP_GENERIC
bool "Generic OMAP board" bool "Generic OMAP board"
depends on ARCH_OMAP1510 || ARCH_OMAP1610 depends on ARCH_OMAP1510 || ARCH_OMAP1610
...@@ -38,16 +83,15 @@ config MACH_OMAP_GENERIC ...@@ -38,16 +83,15 @@ config MACH_OMAP_GENERIC
custom OMAP boards. Say Y here if you have a custom custom OMAP boards. Say Y here if you have a custom
board. board.
endchoice
comment "OMAP Feature Selections" comment "OMAP Feature Selections"
config MACH_OMAP_H2 #config OMAP_BOOT_TAG
bool "TI H2 Support" # bool "OMAP bootloader information passing"
depends on ARCH_OMAP1610 && MACH_OMAP_INNOVATOR # depends on ARCH_OMAP
help # default n
TI OMAP 1610 H2 board support. Say Y here if you have such # help
a board. # Say Y, if you have a bootloader which passes information
# about your board and its peripheral configuration.
config OMAP_MUX config OMAP_MUX
bool "OMAP multiplexing support" bool "OMAP multiplexing support"
...@@ -67,6 +111,22 @@ config OMAP_MUX_DEBUG ...@@ -67,6 +111,22 @@ config OMAP_MUX_DEBUG
This is useful if you want to find out the correct values of the This is useful if you want to find out the correct values of the
multiplexing registers. multiplexing registers.
choice
prompt "Low-level debug console UART"
depends on ARCH_OMAP
default OMAP_LL_DEBUG_UART1
config OMAP_LL_DEBUG_UART1
bool "UART1"
config OMAP_LL_DEBUG_UART2
bool "UART2"
config OMAP_LL_DEBUG_UART3
bool "UART3"
endchoice
config OMAP_ARM_195MHZ config OMAP_ARM_195MHZ
bool "OMAP ARM 195 MHz CPU" bool "OMAP ARM 195 MHz CPU"
depends on ARCH_OMAP730 depends on ARCH_OMAP730
...@@ -75,7 +135,7 @@ config OMAP_ARM_195MHZ ...@@ -75,7 +135,7 @@ config OMAP_ARM_195MHZ
config OMAP_ARM_192MHZ config OMAP_ARM_192MHZ
bool "OMAP ARM 192 MHz CPU" bool "OMAP ARM 192 MHz CPU"
depends on ARCH_OMAP1610 depends on ARCH_OMAP1610 || ARCH_OMAP5912
help help
Enable 192MHz clock for OMAP CPU. If unsure, say N. Enable 192MHz clock for OMAP CPU. If unsure, say N.
...@@ -87,7 +147,7 @@ config OMAP_ARM_182MHZ ...@@ -87,7 +147,7 @@ config OMAP_ARM_182MHZ
config OMAP_ARM_168MHZ config OMAP_ARM_168MHZ
bool "OMAP ARM 168 MHz CPU" bool "OMAP ARM 168 MHz CPU"
depends on ARCH_OMAP1510 || ARCH_OMAP1610 || ARCH_OMAP730 depends on ARCH_OMAP1510 || ARCH_OMAP1610 || ARCH_OMAP730 || ARCH_OMAP5912
help help
Enable 168MHz clock for OMAP CPU. If unsure, say N. Enable 168MHz clock for OMAP CPU. If unsure, say N.
......
...@@ -9,28 +9,28 @@ obj-n := ...@@ -9,28 +9,28 @@ obj-n :=
obj- := obj- :=
led-y := leds.o led-y := leds.o
# OCPI interconnect support for 1610
ifeq ($(CONFIG_ARCH_OMAP1610),y)
obj-y += ocpi.o
ifeq ($(CONFIG_OMAP_INNOVATOR),y)
obj-y += innovator1610.o
endif
endif
ifeq ($(CONFIG_ARCH_OMAP1510),y)
ifeq ($(CONFIG_OMAP_INNOVATOR),y)
obj-y += innovator1510.o fpga.o
endif
endif
# Specific board support # Specific board support
obj-$(CONFIG_MACH_OMAP_GENERIC) += omap-generic.o obj-$(CONFIG_MACH_OMAP_INNOVATOR) += board-innovator.o
obj-$(CONFIG_MACH_OMAP_PERSEUS2) += omap-perseus2.o obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
obj-$(CONFIG_MACH_OMAP_PERSEUS2) += board-perseus2.o
obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o
# OCPI interconnect support for 1610 and 5912
obj-$(CONFIG_ARCH_OMAP1610) += ocpi.o
obj-$(CONFIG_ARCH_OMAP5912) += ocpi.o
# LEDs support # LEDs support
led-$(CONFIG_OMAP_INNOVATOR) += leds-innovator.o led-$(CONFIG_MACH_OMAP_INNOVATOR) += leds-innovator.o
led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-perseus2.o led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-perseus2.o
obj-$(CONFIG_LEDS) += $(led-y) obj-$(CONFIG_LEDS) += $(led-y)
# Power Management
obj-$(CONFIG_PM) += pm.o sleep.o
ifeq ($(CONFIG_ARCH_OMAP1510),y)
# Innovator-1510 FPGA
obj-$(CONFIG_MACH_OMAP_INNOVATOR) += fpga.o
endif
# kgdb support # kgdb support
obj-$(CONFIG_KGDB_SERIAL) += kgdb-serial.o obj-$(CONFIG_KGDB_SERIAL) += kgdb-serial.o
/*
* linux/arch/arm/mach-omap/board-generic.c
*
* Modified from board-innovator1510.c
*
* Code for generic OMAP board. Should work on many OMAP systems where
* the device drivers take care of all the necessary hardware initialization.
* Do not put any board specific code to this file; create a new machine
* type if you need custom low-level initializations.
*
* 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/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <asm/hardware.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/arch/clocks.h>
#include <asm/arch/gpio.h>
#include <asm/arch/mux.h>
#include "common.h"
static void __init omap_generic_init_irq(void)
{
omap_init_irq();
}
/*
* Muxes the serial ports on
*/
static void __init omap_early_serial_init(void)
{
omap_cfg_reg(UART1_TX);
omap_cfg_reg(UART1_RTS);
omap_cfg_reg(UART2_TX);
omap_cfg_reg(UART2_RTS);
omap_cfg_reg(UART3_TX);
omap_cfg_reg(UART3_RX);
}
static void __init omap_generic_init(void)
{
/*
* Make sure the serial ports are muxed on at this point.
* You have to mux them off in device drivers later on
* if not needed.
*/
if (cpu_is_omap1510()) {
omap_early_serial_init();
}
}
static void __init omap_generic_map_io(void)
{
omap_map_io();
}
MACHINE_START(OMAP_GENERIC, "Generic OMAP-1510/1610")
MAINTAINER("Tony Lindgren <tony@atomide.com>")
BOOT_MEM(0x10000000, 0xe0000000, 0xe0000000)
BOOT_PARAMS(0x10000100)
MAPIO(omap_generic_map_io)
INITIRQ(omap_generic_init_irq)
INIT_MACHINE(omap_generic_init)
MACHINE_END
/*
* linux/arch/arm/mach-omap/board-innovator.c
*
* Board specific inits for OMAP-1510 and OMAP-1610 Innovator
*
* Copyright (C) 2001 RidgeRun, Inc.
* Author: Greg Lonnon <glonnon@ridgerun.com>
*
* Copyright (C) 2002 MontaVista Software, Inc.
*
* Separated FPGA interrupts from innovator1510.c and cleaned up for 2.6
* Copyright (C) 2004 Nokia Corporation by Tony Lindrgen <tony@atomide.com>
*
* 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/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <asm/hardware.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/arch/clocks.h>
#include <asm/arch/gpio.h>
#include <asm/arch/fpga.h>
#include "common.h"
#ifdef CONFIG_ARCH_OMAP1510
extern int omap_gpio_init(void);
/* Only FPGA needs to be mapped here. All others are done with ioremap */
static struct map_desc innovator1510_io_desc[] __initdata = {
{ OMAP1510P1_FPGA_BASE, OMAP1510P1_FPGA_START, OMAP1510P1_FPGA_SIZE,
MT_DEVICE },
};
static struct resource innovator1510_smc91x_resources[] = {
[0] = {
.start = OMAP1510P1_FPGA_ETHR_START, /* Physical */
.end = OMAP1510P1_FPGA_ETHR_START + 16,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = INT_ETHER,
.end = INT_ETHER,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device innovator1510_smc91x_device = {
.name = "smc91x",
.id = 0,
.num_resources = ARRAY_SIZE(innovator1510_smc91x_resources),
.resource = innovator1510_smc91x_resources,
};
static struct platform_device *innovator1510_devices[] __initdata = {
&innovator1510_smc91x_device,
};
#endif /* CONFIG_ARCH_OMAP1510 */
#ifdef CONFIG_ARCH_OMAP1610
static struct map_desc innovator1610_io_desc[] __initdata = {
{ OMAP1610_ETHR_BASE, OMAP1610_ETHR_START, OMAP1610_ETHR_SIZE,MT_DEVICE },
{ OMAP1610_NOR_FLASH_BASE, OMAP1610_NOR_FLASH_START, OMAP1610_NOR_FLASH_SIZE,
MT_DEVICE },
};
static struct resource innovator1610_smc91x_resources[] = {
[0] = {
.start = OMAP1610_ETHR_START, /* Physical */
.end = OMAP1610_ETHR_START + SZ_4K,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 0, /* Really GPIO 0 */
.end = 0,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device innovator1610_smc91x_device = {
.name = "smc91x",
.id = 0,
.num_resources = ARRAY_SIZE(innovator1610_smc91x_resources),
.resource = innovator1610_smc91x_resources,
};
static struct platform_device *innovator1610_devices[] __initdata = {
&innovator1610_smc91x_device,
};
#endif /* CONFIG_ARCH_OMAP1610 */
void innovator_init_irq(void)
{
omap_init_irq();
#ifdef CONFIG_ARCH_OMAP1510
if (cpu_is_omap1510()) {
omap_gpio_init();
fpga_init_irq();
}
#endif
}
static void __init innovator_init(void)
{
#ifdef CONFIG_ARCH_OMAP1510
if (cpu_is_omap1510()) {
platform_add_devices(innovator1510_devices, ARRAY_SIZE(innovator1510_devices));
}
#endif
#ifdef CONFIG_ARCH_OMAP1610
if (cpu_is_omap1610()) {
platform_add_devices(innovator1610_devices, ARRAY_SIZE(innovator1610_devices));
}
#endif
}
static void __init innovator_map_io(void)
{
omap_map_io();
#ifdef CONFIG_ARCH_OMAP1510
if (cpu_is_omap1510()) {
iotable_init(innovator1510_io_desc, ARRAY_SIZE(innovator1510_io_desc));
/* Dump the Innovator FPGA rev early - useful info for support. */
printk("Innovator FPGA Rev %d.%d Board Rev %d\n",
fpga_read(OMAP1510P1_FPGA_REV_HIGH),
fpga_read(OMAP1510P1_FPGA_REV_LOW),
fpga_read(OMAP1510P1_FPGA_BOARD_REV));
}
#endif
#ifdef CONFIG_ARCH_OMAP1610
if (cpu_is_omap1610()) {
iotable_init(innovator1610_io_desc, ARRAY_SIZE(innovator1610_io_desc));
}
#endif
}
MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
MAINTAINER("MontaVista Software, Inc.")
BOOT_MEM(0x10000000, 0xe0000000, 0xe0000000)
BOOT_PARAMS(0x10000100)
MAPIO(innovator_map_io)
INITIRQ(innovator_init_irq)
INIT_MACHINE(innovator_init)
MACHINE_END
/*
* linux/arch/arm/mach-omap/board-osk.c
*
* Board specific init for OMAP5912 OSK
*
* Written by Dirk Behme <dirk.behme@de.bosch.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/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <asm/hardware.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/arch/clocks.h>
#include <asm/arch/gpio.h>
#include <asm/arch/fpga.h>
#include "common.h"
static struct map_desc osk5912_io_desc[] __initdata = {
{ OMAP_OSK_ETHR_BASE, OMAP_OSK_ETHR_START, OMAP_OSK_ETHR_SIZE,MT_DEVICE },
{ OMAP_OSK_NOR_FLASH_BASE, OMAP_OSK_NOR_FLASH_START, OMAP_OSK_NOR_FLASH_SIZE,
MT_DEVICE },
};
static struct resource osk5912_smc91x_resources[] = {
[0] = {
.start = OMAP_OSK_ETHR_START, /* Physical */
.end = OMAP_OSK_ETHR_START + SZ_4K,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 0, /* Really GPIO 0 */
.end = 0,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device osk5912_smc91x_device = {
.name = "smc91x",
.id = 0,
.num_resources = ARRAY_SIZE(osk5912_smc91x_resources),
.resource = osk5912_smc91x_resources,
};
static struct platform_device *osk5912_devices[] __initdata = {
&osk5912_smc91x_device,
};
void osk_init_irq(void)
{
omap_init_irq();
}
static void __init osk_init(void)
{
platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices));
}
static void __init osk_map_io(void)
{
omap_map_io();
iotable_init(osk5912_io_desc, ARRAY_SIZE(osk5912_io_desc));
}
MACHINE_START(OMAP_OSK, "TI-OSK")
MAINTAINER("Dirk Behme <dirk.behme@de.bosch.com>")
BOOT_MEM(0x10000000, 0xe0000000, 0xe0000000)
BOOT_PARAMS(0x10000100)
MAPIO(osk_map_io)
INITIRQ(osk_init_irq)
INIT_MACHINE(osk_init)
MACHINE_END
/*
* linux/arch/arm/mach-omap/board-perseus2.c
*
* Modified from board-generic.c
*
* 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/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <asm/hardware.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/arch/clocks.h>
#include <asm/arch/gpio.h>
#include <asm/arch/mux.h>
#include "common.h"
void omap_perseus2_init_irq(void)
{
omap_init_irq();
}
static struct resource smc91x_resources[] = {
[0] = {
.start = OMAP730_FPGA_ETHR_START, /* Physical */
.end = OMAP730_FPGA_ETHR_START + SZ_4K,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 0,
.end = 0,
.flags = INT_ETHER,
},
};
static struct platform_device smc91x_device = {
.name = "smc91x",
.id = 0,
.num_resources = ARRAY_SIZE(smc91x_resources),
.resource = smc91x_resources,
};
static struct platform_device *devices[] __initdata = {
&smc91x_device,
};
static void __init omap_perseus2_init(void)
{
(void) platform_add_devices(devices, ARRAY_SIZE(devices));
}
/* Only FPGA needs to be mapped here. All others are done with ioremap */
static struct map_desc omap_perseus2_io_desc[] __initdata = {
{OMAP730_FPGA_BASE, OMAP730_FPGA_START, OMAP730_FPGA_SIZE,
MT_DEVICE},
};
static void __init omap_perseus2_map_io(void)
{
omap_map_io();
iotable_init(omap_perseus2_io_desc,
ARRAY_SIZE(omap_perseus2_io_desc));
/* Early, board-dependent init */
/*
* Hold GSM Reset until needed
*/
omap_writew(omap_readw(OMAP730_DSP_M_CTL) & ~1, OMAP730_DSP_M_CTL);
/*
* UARTs -> done automagically by 8250 driver
*/
/*
* CSx timings, GPIO Mux ... setup
*/
/* Flash: CS0 timings setup */
omap_writel(0x0000fff3, OMAP730_FLASH_CFG_0);
omap_writel(0x00000088, OMAP730_FLASH_ACFG_0);
/*
* Ethernet support trough the debug board
* CS1 timings setup
*/
omap_writel(0x0000fff3, OMAP730_FLASH_CFG_1);
omap_writel(0x00000000, OMAP730_FLASH_ACFG_1);
/*
* Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
* It is used as the Ethernet controller interrupt
*/
omap_writel(omap_readl(OMAP730_IO_CONF_9) & 0x1FFFFFFF, OMAP730_IO_CONF_9);
}
MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
MAINTAINER("Kevin Hilman <k-hilman@ti.com>")
BOOT_MEM(0x10000000, 0xe0000000, 0xe0000000)
BOOT_PARAMS(0x10000100)
MAPIO(omap_perseus2_map_io)
INITIRQ(omap_perseus2_init_irq)
INIT_MACHINE(omap_perseus2_init)
MACHINE_END
...@@ -93,6 +93,8 @@ static struct bus_type omap_bus_types[OMAP_NR_BUSES] = { ...@@ -93,6 +93,8 @@ static struct bus_type omap_bus_types[OMAP_NR_BUSES] = {
*/ */
inline int dmadev_uses_omap_lbus(struct device * dev) inline int dmadev_uses_omap_lbus(struct device * dev)
{ {
if (dev == NULL || !cpu_is_omap1510())
return 0;
return dev->bus == &omap_bus_types[OMAP_BUS_LBUS] ? 1 : 0; return dev->bus == &omap_bus_types[OMAP_BUS_LBUS] ? 1 : 0;
} }
...@@ -184,6 +186,9 @@ int omap_device_register(struct omap_dev *odev) ...@@ -184,6 +186,9 @@ int omap_device_register(struct omap_dev *odev)
if (odev->dma_mask) if (odev->dma_mask)
odev->dev.dma_mask = odev->dma_mask; odev->dev.dma_mask = odev->dma_mask;
if (odev->coherent_dma_mask)
odev->dev.coherent_dma_mask = odev->coherent_dma_mask;
snprintf(odev->dev.bus_id, BUS_ID_SIZE, "%s%u", snprintf(odev->dev.bus_id, BUS_ID_SIZE, "%s%u",
odev->name, odev->devid); odev->name, odev->devid);
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/arch/clocks.h> #include <asm/arch/clocks.h>
#include <asm/arch/board.h>
/* Input clock in MHz */ /* Input clock in MHz */
static unsigned int source_clock = 12; static unsigned int source_clock = 12;
...@@ -49,10 +50,10 @@ typedef struct { ...@@ -49,10 +50,10 @@ typedef struct {
char *name; char *name;
__u8 flags; __u8 flags;
ck_t parent; ck_t parent;
volatile __u16 *rate_reg; /* Clock rate register */ unsigned long rate_reg; /* Clock rate register */
volatile __u16 *enbl_reg; /* Enable register */ unsigned long enbl_reg; /* Enable register */
volatile __u16 *idle_reg; /* Idle register */ unsigned long idle_reg; /* Idle register */
volatile __u16 *slct_reg; /* Select register */ unsigned long slct_reg; /* Select register */
__s8 rate_shift; /* Clock rate bit shift */ __s8 rate_shift; /* Clock rate bit shift */
__s8 enbl_shift; /* Clock enable bit shift */ __s8 enbl_shift; /* Clock enable bit shift */
__s8 idle_shift; /* Clock idle bit shift */ __s8 idle_shift; /* Clock idle bit shift */
...@@ -245,7 +246,7 @@ int ...@@ -245,7 +246,7 @@ int
ck_set_input(ck_t ck, ck_t input) ck_set_input(ck_t ck, ck_t input)
{ {
int ret = 0, shift; int ret = 0, shift;
volatile __u16 *reg; unsigned short reg;
unsigned long flags; unsigned long flags;
if (!CK_IN_RANGE(ck) || !CK_CAN_SWITCH(ck)) { if (!CK_IN_RANGE(ck) || !CK_CAN_SWITCH(ck)) {
...@@ -253,15 +254,17 @@ ck_set_input(ck_t ck, ck_t input) ...@@ -253,15 +254,17 @@ ck_set_input(ck_t ck, ck_t input)
goto exit; goto exit;
} }
reg = CK_SELECT_REG(ck); reg = omap_readw(CK_SELECT_REG(ck));
shift = CK_SELECT_SHIFT(ck); shift = CK_SELECT_SHIFT(ck);
spin_lock_irqsave(&clock_lock, flags); spin_lock_irqsave(&clock_lock, flags);
if (input == OMAP_CLKIN) { if (input == OMAP_CLKIN) {
*((volatile __u16 *) reg) &= ~(1 << shift); reg &= ~(1 << shift);
omap_writew(reg, CK_SELECT_REG(ck));
goto exit; goto exit;
} else if (input == CK_PARENT(ck)) { } else if (input == CK_PARENT(ck)) {
*((volatile __u16 *) reg) |= (1 << shift); reg |= (1 << shift);
omap_writew(reg, CK_SELECT_REG(ck));
goto exit; goto exit;
} }
...@@ -285,11 +288,11 @@ ck_get_input(ck_t ck, ck_t * input) ...@@ -285,11 +288,11 @@ ck_get_input(ck_t ck, ck_t * input)
spin_lock_irqsave(&clock_lock, flags); spin_lock_irqsave(&clock_lock, flags);
if (CK_CAN_SWITCH(ck)) { if (CK_CAN_SWITCH(ck)) {
int shift; int shift;
volatile __u16 *reg; unsigned short reg;
reg = CK_SELECT_REG(ck); reg = omap_readw(CK_SELECT_REG(ck));
shift = CK_SELECT_SHIFT(ck); shift = CK_SELECT_SHIFT(ck);
if (*reg & (1 << shift)) { if (reg & (1 << shift)) {
*input = CK_PARENT(ck); *input = CK_PARENT(ck);
goto exit; goto exit;
} }
...@@ -305,7 +308,7 @@ ck_get_input(ck_t ck, ck_t * input) ...@@ -305,7 +308,7 @@ ck_get_input(ck_t ck, ck_t * input)
static int static int
__ck_set_pll_rate(ck_t ck, int rate) __ck_set_pll_rate(ck_t ck, int rate)
{ {
volatile __u16 *pll; unsigned short pll;
unsigned long flags; unsigned long flags;
if ((rate < 0) || (rate > CK_MAX_PLL_FREQ)) if ((rate < 0) || (rate > CK_MAX_PLL_FREQ))
...@@ -322,13 +325,16 @@ __ck_set_pll_rate(ck_t ck, int rate) ...@@ -322,13 +325,16 @@ __ck_set_pll_rate(ck_t ck, int rate)
} }
spin_lock_irqsave(&clock_lock, flags); spin_lock_irqsave(&clock_lock, flags);
pll = (volatile __u16 *) CK_RATE_REG(ck); pll = omap_readw(CK_RATE_REG(ck));
/* Clear the rate bits */ /* Clear the rate bits */
*pll &= ~(0x1f << 5); pll &= ~(0x1f << 5);
/* Set the rate bits */ /* Set the rate bits */
*pll |= (ck_lookup_table[rate - 1] << 5); pll |= (ck_lookup_table[rate - 1] << 5);
omap_writew(pll, CK_RATE_REG(ck));
spin_unlock_irqrestore(&clock_lock, flags); spin_unlock_irqrestore(&clock_lock, flags);
return 0; return 0;
...@@ -338,7 +344,7 @@ static int ...@@ -338,7 +344,7 @@ static int
__ck_set_clkm_rate(ck_t ck, int rate) __ck_set_clkm_rate(ck_t ck, int rate)
{ {
int shift, prate, div, ret; int shift, prate, div, ret;
volatile __u16 *reg; unsigned short reg;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&clock_lock, flags); spin_lock_irqsave(&clock_lock, flags);
...@@ -390,10 +396,11 @@ __ck_set_clkm_rate(ck_t ck, int rate) ...@@ -390,10 +396,11 @@ __ck_set_clkm_rate(ck_t ck, int rate)
* At last, we can set the divisor. Clear the old rate bits and * At last, we can set the divisor. Clear the old rate bits and
* set the new ones. * set the new ones.
*/ */
reg = (volatile __u16 *) CK_RATE_REG(ck); reg = omap_readw(CK_RATE_REG(ck));
shift = CK_RATE_SHIFT(ck); shift = CK_RATE_SHIFT(ck);
*reg &= ~(3 << shift); reg &= ~(3 << shift);
*reg |= (div << shift); reg |= (div << shift);
omap_writew(reg, CK_RATE_REG(ck));
/* And return the new (actual, after rounding down) rate. */ /* And return the new (actual, after rounding down) rate. */
ret = prate; ret = prate;
...@@ -432,7 +439,7 @@ __ck_get_pll_rate(ck_t ck) ...@@ -432,7 +439,7 @@ __ck_get_pll_rate(ck_t ck)
{ {
int m, d; int m, d;
__u16 pll = *((volatile __u16 *) CK_RATE_REG(ck)); unsigned short pll = omap_readw(CK_RATE_REG(ck));
m = (pll & (0x1f << 7)) >> 7; m = (pll & (0x1f << 7)) >> 7;
m = m ? m : 1; m = m ? m : 1;
...@@ -448,7 +455,7 @@ __ck_get_clkm_rate(ck_t ck) ...@@ -448,7 +455,7 @@ __ck_get_clkm_rate(ck_t ck)
static int bits2div[] = { 1, 2, 4, 8 }; static int bits2div[] = { 1, 2, 4, 8 };
int in, bits, reg, shift; int in, bits, reg, shift;
reg = *(CK_RATE_REG(ck)); reg = omap_readw(CK_RATE_REG(ck));
shift = CK_RATE_SHIFT(ck); shift = CK_RATE_SHIFT(ck);
in = ck_get_rate(CK_PARENT(ck)); in = ck_get_rate(CK_PARENT(ck));
...@@ -520,7 +527,7 @@ ck_get_rate(ck_t ck) ...@@ -520,7 +527,7 @@ ck_get_rate(ck_t ck)
int int
ck_enable(ck_t ck) ck_enable(ck_t ck)
{ {
volatile __u16 *reg; unsigned short reg;
int ret = -EINVAL, shift; int ret = -EINVAL, shift;
unsigned long flags; unsigned long flags;
...@@ -537,9 +544,10 @@ ck_enable(ck_t ck) ...@@ -537,9 +544,10 @@ ck_enable(ck_t ck)
goto exit; goto exit;
spin_lock_irqsave(&clock_lock, flags); spin_lock_irqsave(&clock_lock, flags);
reg = CK_ENABLE_REG(ck); reg = omap_readw(CK_ENABLE_REG(ck));
shift = CK_ENABLE_SHIFT(ck); shift = CK_ENABLE_SHIFT(ck);
*reg |= (1 << shift); reg |= (1 << shift);
omap_writew(reg, CK_ENABLE_REG(ck));
spin_unlock_irqrestore(&clock_lock, flags); spin_unlock_irqrestore(&clock_lock, flags);
exit: exit:
...@@ -549,7 +557,7 @@ ck_enable(ck_t ck) ...@@ -549,7 +557,7 @@ ck_enable(ck_t ck)
int int
ck_disable(ck_t ck) ck_disable(ck_t ck)
{ {
volatile __u16 *reg; unsigned short reg;
int ret = -EINVAL, shift; int ret = -EINVAL, shift;
unsigned long flags; unsigned long flags;
...@@ -568,9 +576,10 @@ ck_disable(ck_t ck) ...@@ -568,9 +576,10 @@ ck_disable(ck_t ck)
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&clock_lock, flags); spin_lock_irqsave(&clock_lock, flags);
reg = CK_ENABLE_REG(ck); reg = omap_readw(CK_ENABLE_REG(ck));
shift = CK_ENABLE_SHIFT(ck); shift = CK_ENABLE_SHIFT(ck);
*reg &= ~(1 << shift); reg &= ~(1 << shift);
omap_writew(reg, CK_ENABLE_REG(ck));
spin_unlock_irqrestore(&clock_lock, flags); spin_unlock_irqrestore(&clock_lock, flags);
exit: exit:
...@@ -606,54 +615,71 @@ __ck_make_lookup_table(void) ...@@ -606,54 +615,71 @@ __ck_make_lookup_table(void)
int __init int __init
init_ck(void) init_ck(void)
{ {
const struct omap_clock_info *info;
int crystal_type = 0; /* Default 12 MHz */
__ck_make_lookup_table(); __ck_make_lookup_table();
info = omap_get_per_info(OMAP_TAG_CLOCK, struct omap_clock_info);
if (info != NULL) {
if (!cpu_is_omap1510())
crystal_type = info->system_clock_type;
}
/* We want to be in syncronous scalable mode */ /* We want to be in syncronous scalable mode */
*ARM_SYSST = 0x1000; omap_writew(0x1000, ARM_SYSST);
#if defined(CONFIG_OMAP_ARM_30MHZ) #if defined(CONFIG_OMAP_ARM_30MHZ)
*ARM_CKCTL = 0x1555; omap_writew(0x1555, ARM_CKCTL);
*DPLL_CTL_REG = 0x2290; omap_writew(0x2290, DPLL_CTL_REG);
#elif defined(CONFIG_OMAP_ARM_60MHZ) #elif defined(CONFIG_OMAP_ARM_60MHZ)
*ARM_CKCTL = 0x1005; omap_writew(0x1005, ARM_CKCTL);
*DPLL_CTL_REG = 0x2290; omap_writew(0x2290, DPLL_CTL_REG);
#elif defined(CONFIG_OMAP_ARM_96MHZ) #elif defined(CONFIG_OMAP_ARM_96MHZ)
*ARM_CKCTL = 0x1005; omap_writew(0x1005, ARM_CKCTL);
*DPLL_CTL_REG = 0x2410; omap_writew(0x2410, DPLL_CTL_REG);
#elif defined(CONFIG_OMAP_ARM_120MHZ) #elif defined(CONFIG_OMAP_ARM_120MHZ)
*ARM_CKCTL = 0x110a; omap_writew(0x110a, ARM_CKCTL);
*DPLL_CTL_REG = 0x2510; omap_writew(0x2510, DPLL_CTL_REG);
#elif defined(CONFIG_OMAP_ARM_168MHZ) #elif defined(CONFIG_OMAP_ARM_168MHZ)
*ARM_CKCTL = 0x110f; omap_writew(0x110f, ARM_CKCTL);
*DPLL_CTL_REG = 0x2710; omap_writew(0x2710, DPLL_CTL_REG);
#elif defined(CONFIG_OMAP_ARM_182MHZ) && defined(CONFIG_ARCH_OMAP730) #elif defined(CONFIG_OMAP_ARM_182MHZ) && defined(CONFIG_ARCH_OMAP730)
*ARM_CKCTL = 0x250E; omap_writew(0x250E, ARM_CKCTL);
*DPLL_CTL_REG = 0x2713; omap_writew(0x2710, DPLL_CTL_REG);
#elif defined(CONFIG_OMAP_ARM_192MHZ) && defined(CONFIG_ARCH_OMAP1610) #elif defined(CONFIG_OMAP_ARM_192MHZ) && (defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912))
*ARM_CKCTL = 0x110f; omap_writew(0x150f, ARM_CKCTL);
if (crystal_type == 2) { if (crystal_type == 2) {
source_clock = 13; /* MHz */ source_clock = 13; /* MHz */
*DPLL_CTL_REG = 0x2510; omap_writew(0x2510, DPLL_CTL_REG);
} else } else
*DPLL_CTL_REG = 0x2810; omap_writew(0x2810, DPLL_CTL_REG);
#elif defined(CONFIG_OMAP_ARM_195MHZ) && defined(CONFIG_ARCH_OMAP730) #elif defined(CONFIG_OMAP_ARM_195MHZ) && defined(CONFIG_ARCH_OMAP730)
*ARM_CKCTL = 0x250E; omap_writew(0x250E, ARM_CKCTL);
*DPLL_CTL_REG = 0x2793; omap_writew(0x2790, DPLL_CTL_REG);
#else #else
#error "OMAP MHZ not set, please run make xconfig" #error "OMAP MHZ not set, please run make xconfig"
#endif #endif
#ifdef CONFIG_MACH_OMAP_PERSEUS2
/* Select slicer output as OMAP input clock */
omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL_REG) & ~0x1, OMAP730_PCC_UPLD_CTRL_REG);
#endif
/* Turn off some other junk the bootloader might have turned on */ /* Turn off some other junk the bootloader might have turned on */
*ARM_CKCTL &= 0x0fff; /* Turn off DSP, ARM_INTHCK, ARM_TIMXO */
*ARM_RSTCT1 = 0; /* Put DSP/MPUI into reset until needed */ /* Turn off DSP, ARM_INTHCK, ARM_TIMXO */
*ARM_RSTCT2 = 1; omap_writew(omap_readw(ARM_CKCTL) & 0x0fff, ARM_CKCTL);
*ARM_IDLECT1 = 0x400;
/* Put DSP/MPUI into reset until needed */
omap_writew(0, ARM_RSTCT1);
omap_writew(1, ARM_RSTCT2);
omap_writew(0x400, ARM_IDLECT1);
/* /*
* According to OMAP5910 Erratum SYS_DMA_1, bit DMACK_REQ (bit 8) * According to OMAP5910 Erratum SYS_DMA_1, bit DMACK_REQ (bit 8)
* of the ARM_IDLECT2 register must be set to zero. The power-on * of the ARM_IDLECT2 register must be set to zero. The power-on
* default value of this bit is one. * default value of this bit is one.
*/ */
*ARM_IDLECT2 = 0x0000; /* Turn LCD clock off also */ omap_writew(0x0000, ARM_IDLECT2); /* Turn LCD clock off also */
/* /*
* Only enable those clocks we will need, let the drivers * Only enable those clocks we will need, let the drivers
......
...@@ -13,29 +13,60 @@ ...@@ -13,29 +13,60 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/console.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <asm/arch/clocks.h> #include <asm/arch/clocks.h>
#include <asm/arch/board.h>
#include <asm/io.h> #include <asm/io.h>
#include "common.h"
/* /*
* Common OMAP I/O mapping * ----------------------------------------------------------------------------
* OMAP I/O mapping
* *
* The machine specific code may provide the extra mapping besides the * The machine specific code may provide the extra mapping besides the
* default mapping provided here. * default mapping provided here.
* ----------------------------------------------------------------------------
*/ */
static struct map_desc standard_io_desc[] __initdata = { static struct map_desc omap_io_desc[] __initdata = {
{ IO_BASE, IO_START, IO_SIZE, MT_DEVICE }, { IO_VIRT, IO_PHYS, IO_SIZE, MT_DEVICE },
{ OMAP_DSP_BASE, OMAP_DSP_START, OMAP_DSP_SIZE, MT_DEVICE }, };
{ OMAP_DSPREG_BASE, OMAP_DSPREG_START, OMAP_DSPREG_SIZE, MT_DEVICE },
{ OMAP_SRAM_BASE, OMAP_SRAM_START, OMAP_SRAM_SIZE, MT_DEVICE } #ifdef CONFIG_ARCH_OMAP730
static struct map_desc omap730_io_desc[] __initdata = {
{ OMAP730_DSP_BASE, OMAP730_DSP_START, OMAP730_DSP_SIZE, MT_DEVICE },
{ OMAP730_DSPREG_BASE, OMAP730_DSPREG_START, OMAP730_DSPREG_SIZE, MT_DEVICE },
{ OMAP730_SRAM_BASE, OMAP730_SRAM_START, OMAP730_SRAM_SIZE, MT_DEVICE }
}; };
#endif
#ifdef CONFIG_ARCH_OMAP1510
static struct map_desc omap1510_io_desc[] __initdata = {
{ OMAP1510_DSP_BASE, OMAP1510_DSP_START, OMAP1510_DSP_SIZE, MT_DEVICE },
{ OMAP1510_DSPREG_BASE, OMAP1510_DSPREG_START, OMAP1510_DSPREG_SIZE, MT_DEVICE },
{ OMAP1510_SRAM_BASE, OMAP1510_SRAM_START, OMAP1510_SRAM_SIZE, MT_DEVICE }
};
#endif
#ifdef CONFIG_ARCH_OMAP1610
static struct map_desc omap1610_io_desc[] __initdata = {
{ OMAP1610_DSP_BASE, OMAP1610_DSP_START, OMAP1610_DSP_SIZE, MT_DEVICE },
{ OMAP1610_DSPREG_BASE, OMAP1610_DSPREG_START, OMAP1610_DSPREG_SIZE, MT_DEVICE },
{ OMAP1610_SRAM_BASE, OMAP1610_SRAM_START, OMAP1610_SRAM_SIZE, MT_DEVICE }
};
#endif
#ifdef CONFIG_ARCH_OMAP5912
static struct map_desc omap5912_io_desc[] __initdata = {
{ OMAP5912_DSP_BASE, OMAP5912_DSP_START, OMAP5912_DSP_SIZE, MT_DEVICE },
{ OMAP5912_DSPREG_BASE, OMAP5912_DSPREG_START, OMAP5912_DSPREG_SIZE, MT_DEVICE },
{ OMAP5912_SRAM_BASE, OMAP5912_SRAM_START, OMAP5912_SRAM_SIZE, MT_DEVICE }
};
#endif
static int initialized = 0; static int initialized = 0;
...@@ -43,13 +74,36 @@ static void __init _omap_map_io(void) ...@@ -43,13 +74,36 @@ static void __init _omap_map_io(void)
{ {
initialized = 1; initialized = 1;
iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc)); /* We have to initialize the IO space mapping before we can run
* cpu_is_omapxxx() macros. */
iotable_init(omap_io_desc, ARRAY_SIZE(omap_io_desc));
#ifdef CONFIG_ARCH_OMAP730
if (cpu_is_omap730()) {
iotable_init(omap730_io_desc, ARRAY_SIZE(omap730_io_desc));
}
#endif
#ifdef CONFIG_ARCH_OMAP1510
if (cpu_is_omap1510()) {
iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
}
#endif
#ifdef CONFIG_ARCH_OMAP1610
if (cpu_is_omap1610()) {
iotable_init(omap1610_io_desc, ARRAY_SIZE(omap1610_io_desc));
}
#endif
#ifdef CONFIG_ARCH_OMAP5912
if (cpu_is_omap5912()) {
iotable_init(omap5912_io_desc, ARRAY_SIZE(omap5912_io_desc));
}
#endif
/* REVISIT: Refer to OMAP5910 Errata, Advisory SYS_1: "Timeout Abort /* REVISIT: Refer to OMAP5910 Errata, Advisory SYS_1: "Timeout Abort
* on a Posted Write in the TIPB Bridge". * on a Posted Write in the TIPB Bridge".
*/ */
__raw_writew(0x0, MPU_PUBLIC_TIPB_CNTL_REG); omap_writew(0x0, MPU_PUBLIC_TIPB_CNTL_REG);
__raw_writew(0x0, MPU_PRIVATE_TIPB_CNTL_REG); omap_writew(0x0, MPU_PRIVATE_TIPB_CNTL_REG);
/* Must init clocks early to assure that timer interrupt works /* Must init clocks early to assure that timer interrupt works
*/ */
...@@ -65,5 +119,55 @@ void omap_map_io(void) ...@@ -65,5 +119,55 @@ void omap_map_io(void)
_omap_map_io(); _omap_map_io();
} }
EXPORT_SYMBOL(omap_map_io); extern int omap_bootloader_tag_len;
extern u8 omap_bootloader_tag[];
const void *__omap_get_per_info(u16 tag, size_t len)
{
struct omap_board_info_entry *info = NULL;
#ifdef CONFIG_OMAP_BOOT_TAG
if (omap_bootloader_tag_len > 4)
info = (struct omap_board_info_entry *) omap_bootloader_tag;
while (info != NULL) {
u8 *next;
if (info->tag == tag)
break;
next = (u8 *) info + sizeof(*info) + info->len;
if (next >= omap_bootloader_tag + omap_bootloader_tag_len)
info = NULL;
else
info = (struct omap_board_info_entry *) next;
}
#endif
if (info == NULL)
return NULL;
if (info->len != len) {
printk(KERN_ERR "OMAP per_info: Length mismatch with tag %x (want %d, got %d)\n",
tag, len, info->len);
return NULL;
}
return info->data;
}
EXPORT_SYMBOL(__omap_get_per_info);
static int __init omap_add_serial_console(void)
{
const struct omap_uart_info *info;
info = omap_get_per_info(OMAP_TAG_UART, struct omap_uart_info);
if (info != NULL && info->console_uart) {
static char speed[11], *opt = NULL;
if (info->console_speed) {
snprintf(speed, sizeof(speed), "%u", info->console_speed);
opt = speed;
}
return add_preferred_console("ttyS", info->console_uart - 1, opt);
}
return 0;
}
console_initcall(omap_add_serial_console);
/* /*
* linux/arch/arm/mach-omap/common.h * linux/arch/arm/mach-omap/common.h
*
* Header for code common to all OMAP machines.
*
* 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.
*/ */
#ifndef __ARCH_ARM_MACH_OMAP_COMMON_H
#define __ARCH_ARM_MACH_OMAP_COMMON_H
extern void omap_map_io(void); extern void omap_map_io(void);
#endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */
This diff is collapsed.
/* /*
* linux/arch/arm/mach-omap/fpga.c * linux/arch/arm/mach-omap/fpga.c
* *
* Interrupt handler for OMAP-1510 FPGA * Interrupt handler for OMAP-1510 Innovator FPGA
* *
* Copyright (C) 2001 RidgeRun, Inc. * Copyright (C) 2001 RidgeRun, Inc.
* Author: Greg Lonnon <glonnon@ridgerun.com> * Author: Greg Lonnon <glonnon@ridgerun.com>
......
This diff is collapsed.
This diff is collapsed.
/*
* linux/arch/arm/mach-omap/irq.h
*
* OMAP specific interrupt bank definitions
*
* Copyright (C) 2004 Nokia Corporation
* Written by Tony Lindgren <tony@atomide.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.
*/
#define OMAP_IRQ_TYPE710 1
#define OMAP_IRQ_TYPE730 2
#define OMAP_IRQ_TYPE1510 3
#define OMAP_IRQ_TYPE1610 4
#define OMAP_IRQ_TYPE1710 5
#define MAX_NR_IRQ_BANKS 4
#define BANK_NR_IRQS 32
struct omap_irq_desc {
unsigned int cpu_type;
unsigned int start_irq;
unsigned long level_map;
unsigned long base_reg;
unsigned long mask_reg;
unsigned long ack_reg;
struct irqchip *handler;
};
struct omap_irq_bank {
unsigned int start_irq;
unsigned long level_map;
unsigned long base_reg;
unsigned long mask_reg;
unsigned long ack_reg;
struct irqchip *handler;
};
static void omap_offset_ack_irq(unsigned int irq);
static void omap_offset_mask_irq(unsigned int irq);
static void omap_offset_unmask_irq(unsigned int irq);
static void omap_offset_mask_ack_irq(unsigned int irq);
/* NOTE: These will not work if irq bank offset != 0x100 */
#define IRQ_TO_BANK(irq) (irq >> 5)
#define IRQ_BIT(irq) (irq & 0x1f)
#define BANK_OFFSET(bank) ((bank - 1) * 0x100)
static struct irqchip omap_offset_irq = {
.ack = omap_offset_mask_ack_irq,
.mask = omap_offset_mask_irq,
.unmask = omap_offset_unmask_irq,
};
/*
* OMAP-730 interrupt banks
*/
static struct omap_irq_desc omap730_bank0_irqs __initdata = {
.cpu_type = OMAP_IRQ_TYPE730,
.start_irq = 0,
.level_map = 0xb3f8e22f,
.base_reg = OMAP_IH1_BASE,
.mask_reg = OMAP_IH1_BASE + IRQ_MIR,
.ack_reg = OMAP_IH1_BASE + IRQ_CONTROL_REG,
.handler = &omap_offset_irq, /* IH2 regs at 0x100 offsets */
};
static struct omap_irq_desc omap730_bank1_irqs __initdata = {
.cpu_type = OMAP_IRQ_TYPE730,
.start_irq = 32,
.level_map = 0xfdb9c1f2,
.base_reg = OMAP_IH2_BASE,
.mask_reg = OMAP_IH2_BASE + IRQ_MIR,
.ack_reg = OMAP_IH2_BASE + IRQ_CONTROL_REG,
.handler = &omap_offset_irq, /* IH2 regs at 0x100 offsets */
};
static struct omap_irq_desc omap730_bank2_irqs __initdata = {
.cpu_type = OMAP_IRQ_TYPE730,
.start_irq = 64,
.level_map = 0x800040f3,
.base_reg = OMAP_IH2_BASE + 0x100,
.mask_reg = OMAP_IH2_BASE + 0x100 + IRQ_MIR,
.ack_reg = OMAP_IH2_BASE + IRQ_CONTROL_REG, /* Not replicated */
.handler = &omap_offset_irq, /* IH2 regs at 0x100 offsets */
};
/*
* OMAP-1510 interrupt banks
*/
static struct omap_irq_desc omap1510_bank0_irqs __initdata = {
.cpu_type = OMAP_IRQ_TYPE1510,
.start_irq = 0,
.level_map = 0xb3febfff,
.base_reg = OMAP_IH1_BASE,
.mask_reg = OMAP_IH1_BASE + IRQ_MIR,
.ack_reg = OMAP_IH1_BASE + IRQ_CONTROL_REG,
.handler = &omap_offset_irq, /* IH2 regs at 0x100 offsets */
};
static struct omap_irq_desc omap1510_bank1_irqs __initdata = {
.cpu_type = OMAP_IRQ_TYPE1510,
.start_irq = 32,
.level_map = 0xffbfffed,
.base_reg = OMAP_IH2_BASE,
.mask_reg = OMAP_IH2_BASE + IRQ_MIR,
.ack_reg = OMAP_IH2_BASE + IRQ_CONTROL_REG,
.handler = &omap_offset_irq, /* IH2 regs at 0x100 offsets */
};
/*
* OMAP-1610 interrupt banks
*/
static struct omap_irq_desc omap1610_bank0_irqs __initdata = {
.cpu_type = OMAP_IRQ_TYPE1610,
.start_irq = 0,
.level_map = 0xb3fefe8f,
.base_reg = OMAP_IH1_BASE,
.mask_reg = OMAP_IH1_BASE + IRQ_MIR,
.ack_reg = OMAP_IH1_BASE + IRQ_CONTROL_REG,
.handler = &omap_offset_irq, /* IH2 regs at 0x100 offsets */
};
static struct omap_irq_desc omap1610_bank1_irqs __initdata = {
.cpu_type = OMAP_IRQ_TYPE1610,
.start_irq = 32,
.level_map = 0xfffff7ff,
.base_reg = OMAP_IH2_BASE,
.mask_reg = OMAP_IH2_BASE + IRQ_MIR,
.ack_reg = OMAP_IH2_BASE + IRQ_CONTROL_REG,
.handler = &omap_offset_irq, /* IH2 regs at 0x100 offsets */
};
static struct omap_irq_desc omap1610_bank2_irqs __initdata = {
.cpu_type = OMAP_IRQ_TYPE1610,
.start_irq = 64,
.level_map = 0xffffffff,
.base_reg = OMAP_IH2_BASE + 0x100,
.mask_reg = OMAP_IH2_BASE + 0x100 + IRQ_MIR,
.ack_reg = OMAP_IH2_BASE + IRQ_CONTROL_REG, /* Not replicated */
.handler = &omap_offset_irq, /* IH2 regs at 0x100 offsets */
};
static struct omap_irq_desc omap1610_bank3_irqs __initdata = {
.cpu_type = OMAP_IRQ_TYPE1610,
.start_irq = 96,
.level_map = 0xffffffff,
.base_reg = OMAP_IH2_BASE + 0x200,
.mask_reg = OMAP_IH2_BASE + 0x200 + IRQ_MIR,
.ack_reg = OMAP_IH2_BASE + IRQ_CONTROL_REG, /* Not replicated */
.handler = &omap_offset_irq, /* IH2 regs at 0x100 offsets */
};
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/leds.h> #include <asm/leds.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/arch/omap-perseus2.h>
#include "leds.h" #include "leds.h"
...@@ -97,7 +96,7 @@ void perseus2_leds_event(led_event_t evt) ...@@ -97,7 +96,7 @@ void perseus2_leds_event(led_event_t evt)
/* /*
* Actually burn the LEDs * Actually burn the LEDs
*/ */
__raw_writew(~hw_led_state & 0xffff, OMAP730_FPGA_LEDS); omap_writew(~hw_led_state & 0xffff, OMAP730_FPGA_LEDS);
local_irq_restore(flags); local_irq_restore(flags);
} }
...@@ -13,9 +13,13 @@ ...@@ -13,9 +13,13 @@
static int __init static int __init
omap1510_leds_init(void) omap1510_leds_init(void)
{ {
if (machine_is_innovator()) if (machine_is_omap_innovator())
leds_event = innovator_leds_event; leds_event = innovator_leds_event;
else if (machine_is_omap_perseus2()) {
leds_event = perseus2_leds_event;
}
leds_event(led_start); leds_event(led_start);
return 0; return 0;
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -79,7 +79,7 @@ config CPU_ARM920T ...@@ -79,7 +79,7 @@ config CPU_ARM920T
# ARM922T # ARM922T
config CPU_ARM922T config CPU_ARM922T
bool bool
depends on ARCH_CAMELOT depends on ARCH_CAMELOT || ARCH_LH7A40X
default y default y
select CPU_32v4 select CPU_32v4
select CPU_ABRT_EV4T select CPU_ABRT_EV4T
...@@ -115,7 +115,7 @@ config CPU_ARM925T ...@@ -115,7 +115,7 @@ config CPU_ARM925T
# ARM926T # ARM926T
config CPU_ARM926T config CPU_ARM926T
bool "Support ARM926T processor" if ARCH_INTEGRATOR bool "Support ARM926T processor" if ARCH_INTEGRATOR
depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || ARCH_OMAP1610 depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || ARCH_OMAP730 || ARCH_OMAP1610 || ARCH_OMAP5912
default y if ARCH_VERSATILE_PB default y if ARCH_VERSATILE_PB
select CPU_32v5 select CPU_32v5
select CPU_ABRT_EV5TJ select CPU_ABRT_EV5TJ
......
This diff is collapsed.
This diff is collapsed.
...@@ -618,6 +618,7 @@ EXPORT_SYMBOL(pci_dma_supported); ...@@ -618,6 +618,7 @@ EXPORT_SYMBOL(pci_dma_supported);
EXPORT_SYMBOL(no_iommu); EXPORT_SYMBOL(no_iommu);
EXPORT_SYMBOL(force_iommu); EXPORT_SYMBOL(force_iommu);
EXPORT_SYMBOL(bad_dma_address); EXPORT_SYMBOL(bad_dma_address);
EXPORT_SYMBOL(iommu_merge);
static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size) static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size)
{ {
......
...@@ -5,6 +5,10 @@ ...@@ -5,6 +5,10 @@
#include <asm/proto.h> #include <asm/proto.h>
int iommu_merge = 0; int iommu_merge = 0;
EXPORT_SYMBOL(iommu_merge);
dma_addr_t bad_dma_address;
EXPORT_SYMBOL(bad_dma_address);
/* /*
* Dummy IO MMU functions * Dummy IO MMU functions
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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