提交 63a93699 编写于 作者: L Linus Torvalds

Merge branch 'remove' of master.kernel.org:/home/rmk/linux-2.6-arm

* 'remove' of master.kernel.org:/home/rmk/linux-2.6-arm:
  ARM: 6629/2: aaec2000: remove support for mach-aaec2000
  ARM: lh7a40x: remove unmaintained platform support

Fix up trivial conflicts in
 - arch/arm/mach-{aaec2000,lh7a40x}/include/mach/memory.h (removed)
 - drivers/usb/gadget/Kconfig (USB_[GADGET_]LH7A40X removed, others added)
README on the ADC/Touchscreen Controller
========================================
The LH79524 and LH7A404 include a built-in Analog to Digital
controller (ADC) that is used to process input from a touchscreen.
The driver only implements a four-wire touch panel protocol.
The touchscreen driver is maintenance free except for the pen-down or
touch threshold. Some resistive displays and board combinations may
require tuning of this threshold. The driver exposes some of its
internal state in the sys filesystem. If the kernel is configured
with it, CONFIG_SYSFS, and sysfs is mounted at /sys, there will be a
directory
/sys/devices/platform/adc-lh7.0
containing these files.
-r--r--r-- 1 root root 4096 Jan 1 00:00 samples
-rw-r--r-- 1 root root 4096 Jan 1 00:00 threshold
-r--r--r-- 1 root root 4096 Jan 1 00:00 threshold_range
The threshold is the current touch threshold. It defaults to 750 on
most targets.
# cat threshold
750
The threshold_range contains the range of valid values for the
threshold. Values outside of this range will be silently ignored.
# cat threshold_range
0 1023
To change the threshold, write a value to the threshold file.
# echo 500 > threshold
# cat threshold
500
The samples file contains the most recently sampled values from the
ADC. There are 12. Below are typical of the last sampled values when
the pen has been released. The first two and last two samples are for
detecting whether or not the pen is down. The third through sixth are
X coordinate samples. The seventh through tenth are Y coordinate
samples.
# cat samples
1023 1023 0 0 0 0 530 529 530 529 1023 1023
To determine a reasonable threshold, press on the touch panel with an
appropriate stylus and read the values from samples.
# cat samples
1023 676 92 103 101 102 855 919 922 922 1023 679
The first and eleventh samples are discarded. Thus, the important
values are the second and twelfth which are used to determine if the
pen is down. When both are below the threshold, the driver registers
that the pen is down. When either is above the threshold, it
registers then pen is up.
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 some 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 write access. The Sharp website has more information about
the effect this power-conserving feature has on peripheral
interfacing.
The solution is to follow every write access to the SMC chip with an
access to another memory region that will force the CPU to release the
chip select line. It is important to guarantee that this access
forces 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 write
operation.
SMC IO
BARRIER IO
Only this sequence is important. It does not matter that there is no
BARRIER IO before the access to the SMC chip because the AEN latch
only needs occurs after the SMC IO write cycle. The routines that
implement this work-around make an additional concession which is to
disable interrupts during the IO sequence. Other hardware devices
(the LogicPD CPLD) have registers in the same physical memory
region as the SMC chip. An interrupt might allow an access to one of
those registers while SMC IO is being performed.
You might be tempted to think that we have to 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. Choosing to access an undecoded memory region is not
desirable as there is no way to know how that chip select will be used
in the future.
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 the LCD Panels
========================
Configuration options for several LCD panels, available from Logic PD,
are included in the kernel source. This README will help you
understand the configuration data and give you some guidance for
adding support for other panels if you wish.
lcd-panels.h
------------
There is no way, at present, to detect which panel is attached to the
system at runtime. Thus the kernel configuration is static. The file
arch/arm/mach-ld7a40x/lcd-panels.h (or similar) defines all of the
panel specific parameters.
It should be possible for this data to be shared among several device
families. The current layout may be insufficiently general, but it is
amenable to improvement.
PIXEL_CLOCK
-----------
The panel data sheets will give a range of acceptable pixel clocks.
The fundamental LCDCLK input frequency is divided down by a PCD
constant in field '.tim2'. It may happen that it is impossible to set
the pixel clock within this range. A clock which is too slow will
tend to flicker. For the highest quality image, set the clock as high
as possible.
MARGINS
-------
These values may be difficult to glean from the panel data sheet. In
the case of the Sharp panels, the upper margin is explicitly called
out as a specific number of lines from the top of the frame. The
other values may not matter as much as the panels tend to
automatically center the image.
Sync Sense
----------
The sense of the hsync and vsync pulses may be called out in the data
sheet. On one panel, the sense of these pulses determine the height
of the visible region on the panel. Most of the Sharp panels use
negative sense sync pulses set by the TIM2_IHS and TIM2_IVS bits in
'.tim2'.
Pel Layout
----------
The Sharp color TFT panels are all configured for 16 bit direct color
modes. The amba-lcd driver sets the pel mode to 565 for 5 bits of
each red and blue and 6 bits of green.
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 SDRAM Controller for the LH7a40X
==============================================
The standard configuration for the SDRAM controller generates a sparse
memory array. The precise layout is determined by the SDRAM chips. A
default kernel configuration assembles the discontiguous memory
regions into separate memory nodes via the NUMA (Non-Uniform Memory
Architecture) facilities. In this default configuration, the kernel
is forgiving about the precise layout. As long as it is given an
accurate picture of available memory by the bootloader the kernel will
execute correctly.
The SDRC supports a mode where some of the chip select lines are
swapped in order to make SDRAM look like a synchronous ROM. Setting
this bit means that the RAM will present as a contiguous array. Some
programmers prefer this to the discontiguous layout. Be aware that
may be a penalty for this feature where some some configurations of
memory are significantly reduced; i.e. 64MiB of RAM appears as only 32
MiB.
There are a couple of configuration options to override the default
behavior. When the SROMLL bit is set and memory appears as a
contiguous array, there is no reason to support NUMA.
CONFIG_LH7A40X_CONTIGMEM disables NUMA support. When physical memory
is discontiguous, the memory tables are organized such that there are
two banks per nodes with a small gap between them. This layout wastes
some kernel memory for page tables representing non-existent memory.
CONFIG_LH7A40X_ONE_BANK_PER_NODE optimizes the node tables such that
there are no gaps. These options control the low level organization
of the memory management tables in ways that may prevent the kernel
from booting or may cause the kernel to allocated excessively large
page tables. Be warned. Only change these options if you know what
you are doing. The default behavior is a reasonable compromise that
will suit all users.
--
A typical 32MiB system with the default configuration options will
find physical memory managed as follows.
node 0: 0xc0000000 4MiB
0xc1000000 4MiB
node 1: 0xc4000000 4MiB
0xc5000000 4MiB
node 2: 0xc8000000 4MiB
0xc9000000 4MiB
node 3: 0xcc000000 4MiB
0xcd000000 4MiB
Setting CONFIG_LH7A40X_ONE_BANK_PER_NODE will put each bank into a
separate node.
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)
......@@ -227,15 +227,6 @@ choice
prompt "ARM system type"
default ARCH_VERSATILE
config ARCH_AAEC2000
bool "Agilent AAEC-2000 based"
select CPU_ARM920T
select ARM_AMBA
select HAVE_CLK
select ARCH_USES_GETTIMEOFFSET
help
This enables support for systems based on the Agilent AAEC-2000
config ARCH_INTEGRATOR
bool "ARM Ltd. Integrator family"
select ARM_AMBA
......@@ -811,17 +802,6 @@ config ARCH_TCC_926
help
Support for Telechips TCC ARM926-based systems.
config ARCH_LH7A40X
bool "Sharp LH7A40X"
select CPU_ARM922T
select ARCH_SPARSEMEM_ENABLE if !LH7A40X_CONTIGMEM
select ARCH_USES_GETTIMEOFFSET
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_U300
bool "ST-Ericsson U300 Series"
depends on MMU
......@@ -908,8 +888,6 @@ endchoice
# Kconfigs may be included either alphabetically (according to the
# plat- suffix) or along side the corresponding mach-* source.
#
source "arch/arm/mach-aaec2000/Kconfig"
source "arch/arm/mach-at91/Kconfig"
source "arch/arm/mach-bcmring/Kconfig"
......@@ -948,8 +926,6 @@ source "arch/arm/mach-kirkwood/Kconfig"
source "arch/arm/mach-ks8695/Kconfig"
source "arch/arm/mach-lh7a40x/Kconfig"
source "arch/arm/mach-loki/Kconfig"
source "arch/arm/mach-lpc32xx/Kconfig"
......
......@@ -131,7 +131,6 @@ endif
# Machine directory name. This list is sorted alphanumerically
# by CONFIG_* macro name.
machine-$(CONFIG_ARCH_AAEC2000) := aaec2000
machine-$(CONFIG_ARCH_AT91) := at91
machine-$(CONFIG_ARCH_BCMRING) := bcmring
machine-$(CONFIG_ARCH_CLPS711X) := clps711x
......@@ -151,7 +150,6 @@ machine-$(CONFIG_ARCH_IXP23XX) := ixp23xx
machine-$(CONFIG_ARCH_IXP4XX) := ixp4xx
machine-$(CONFIG_ARCH_KIRKWOOD) := kirkwood
machine-$(CONFIG_ARCH_KS8695) := ks8695
machine-$(CONFIG_ARCH_LH7A40X) := lh7a40x
machine-$(CONFIG_ARCH_LOKI) := loki
machine-$(CONFIG_ARCH_LPC32XX) := lpc32xx
machine-$(CONFIG_ARCH_MMP) := mmp
......
CONFIG_EXPERIMENTAL=y
# CONFIG_SWAP is not set
CONFIG_SYSVIPC=y
CONFIG_IKCONFIG=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_EXPERT=y
# CONFIG_HOTPLUG is not set
# CONFIG_EPOLL is not set
# CONFIG_IOSCHED_DEADLINE is not set
CONFIG_ARCH_LH7A40X=y
CONFIG_MACH_LPD7A400=y
CONFIG_PREEMPT=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_FPE_NWFPE=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_PNP_RARP=y
# CONFIG_IPV6 is not set
CONFIG_MTD=y
CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_PHYSMAP=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_IDE=y
CONFIG_SCSI=y
# CONFIG_SCSI_PROC_FS is not set
CONFIG_NETDEVICES=y
CONFIG_NET_ETHERNET=y
CONFIG_SMC91X=y
# CONFIG_INPUT_MOUSEDEV is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_TOUCHSCREEN=y
# CONFIG_SERIO is not set
CONFIG_SERIAL_LH7A40X=y
CONFIG_SERIAL_LH7A40X_CONSOLE=y
CONFIG_FB=y
# CONFIG_VGA_CONSOLE is not set
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_JFFS2_FS=y
CONFIG_CRAMFS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_USER=y
CONFIG_DEBUG_ERRORS=y
CONFIG_EXPERIMENTAL=y
# CONFIG_SWAP is not set
CONFIG_SYSVIPC=y
CONFIG_IKCONFIG=y
CONFIG_LOG_BUF_SHIFT=16
CONFIG_EXPERT=y
# CONFIG_HOTPLUG is not set
# CONFIG_EPOLL is not set
CONFIG_SLAB=y
# CONFIG_IOSCHED_DEADLINE is not set
CONFIG_ARCH_LH7A40X=y
CONFIG_MACH_LPD7A404=y
CONFIG_PREEMPT=y
CONFIG_DISCONTIGMEM_MANUAL=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_FPE_NWFPE=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_PNP_RARP=y
# CONFIG_IPV6 is not set
CONFIG_MTD=y
CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_PHYSMAP=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_IDE=y
CONFIG_SCSI=y
# CONFIG_SCSI_PROC_FS is not set
CONFIG_NETDEVICES=y
CONFIG_NET_ETHERNET=y
CONFIG_SMC91X=y
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_TOUCHSCREEN=y
# CONFIG_SERIO is not set
CONFIG_SERIAL_LH7A40X=y
CONFIG_SERIAL_LH7A40X_CONSOLE=y
CONFIG_FB=y
# CONFIG_VGA_CONSOLE is not set
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
CONFIG_USB=y
CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_STORAGE=y
CONFIG_USB_STORAGE_DEBUG=y
CONFIG_USB_STORAGE_DATAFAB=y
CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
CONFIG_INOTIFY=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_JFFS2_FS=y
CONFIG_CRAMFS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_USER=y
CONFIG_DEBUG_ERRORS=y
......@@ -192,11 +192,7 @@ static struct tagtable __tagtable_##fn __tag = { tag, fn }
/*
* Memory map description
*/
#ifdef CONFIG_ARCH_LH7A40X
# define NR_BANKS 16
#else
# define NR_BANKS 8
#endif
#define NR_BANKS 8
struct membank {
unsigned long start;
......
if ARCH_AAEC2000
menu "Agilent AAEC-2000 Implementations"
config MACH_AAED2000
bool "Agilent AAED-2000 Development Platform"
select CPU_ARM920T
endmenu
endif
#
# Makefile for the linux kernel.
#
# Common support (must be linked before board specific support)
obj-y += core.o
# Specific board support
obj-$(CONFIG_MACH_AAED2000) += aaed2000.o
/*
* linux/arch/arm/mach-aaec2000/aaed2000.c
*
* Support for the Agilent AAED-2000 Development Platform.
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* 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/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/major.h>
#include <linux/interrupt.h>
#include <asm/setup.h>
#include <asm/memory.h>
#include <asm/mach-types.h>
#include <mach/hardware.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
#include <mach/aaed2000.h>
#include "core.h"
static void aaed2000_clcd_disable(struct clcd_fb *fb)
{
AAED_EXT_GPIO &= ~AAED_EGPIO_LCD_PWR_EN;
}
static void aaed2000_clcd_enable(struct clcd_fb *fb)
{
AAED_EXT_GPIO |= AAED_EGPIO_LCD_PWR_EN;
}
struct aaec2000_clcd_info clcd_info = {
.enable = aaed2000_clcd_enable,
.disable = aaed2000_clcd_disable,
.panel = {
.mode = {
.name = "Sharp",
.refresh = 60,
.xres = 640,
.yres = 480,
.pixclock = 39721,
.left_margin = 20,
.right_margin = 44,
.upper_margin = 21,
.lower_margin = 34,
.hsync_len = 96,
.vsync_len = 2,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_IVS | TIM2_IHS,
.cntl = CNTL_LCDTFT,
.bpp = 16,
},
};
static void __init aaed2000_init_irq(void)
{
aaec2000_init_irq();
}
static void __init aaed2000_init(void)
{
aaec2000_set_clcd_plat_data(&clcd_info);
}
static struct map_desc aaed2000_io_desc[] __initdata = {
{
.virtual = EXT_GPIO_VBASE,
.pfn = __phys_to_pfn(EXT_GPIO_PBASE),
.length = EXT_GPIO_LENGTH,
.type = MT_DEVICE
},
};
static void __init aaed2000_map_io(void)
{
aaec2000_map_io();
iotable_init(aaed2000_io_desc, ARRAY_SIZE(aaed2000_io_desc));
}
MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform")
/* Maintainer: Nicolas Bellido Y Ortega */
.map_io = aaed2000_map_io,
.init_irq = aaed2000_init_irq,
.timer = &aaec2000_timer,
.init_machine = aaed2000_init,
MACHINE_END
/*
* linux/arch/arm/mach-aaec2000/core.c
*
* Code common to all AAEC-2000 machines
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* 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/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/timex.h>
#include <linux/signal.h>
#include <linux/clk.h>
#include <linux/gfp.h>
#include <mach/hardware.h>
#include <asm/irq.h>
#include <asm/sizes.h>
#include <asm/mach/flash.h>
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
#include <asm/mach/map.h>
#include "core.h"
/*
* Common I/O mapping:
*
* Static virtual address mappings are as follow:
*
* 0xf8000000-0xf8001ffff: Devices connected to APB bus
* 0xf8002000-0xf8003ffff: Devices connected to AHB bus
*
* Below 0xe8000000 is reserved for vm allocation.
*
* The machine specific code must provide the extra mapping beside the
* default mapping provided here.
*/
static struct map_desc standard_io_desc[] __initdata = {
{
.virtual = VIO_APB_BASE,
.pfn = __phys_to_pfn(PIO_APB_BASE),
.length = IO_APB_LENGTH,
.type = MT_DEVICE
}, {
.virtual = VIO_AHB_BASE,
.pfn = __phys_to_pfn(PIO_AHB_BASE),
.length = IO_AHB_LENGTH,
.type = MT_DEVICE
}
};
void __init aaec2000_map_io(void)
{
iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
}
/*
* Interrupt handling routines
*/
static void aaec2000_int_ack(struct irq_data *d)
{
IRQ_INTSR = 1 << d->irq;
}
static void aaec2000_int_mask(struct irq_data *d)
{
IRQ_INTENC |= (1 << d->irq);
}
static void aaec2000_int_unmask(struct irq_data *d)
{
IRQ_INTENS |= (1 << d->irq);
}
static struct irq_chip aaec2000_irq_chip = {
.irq_ack = aaec2000_int_ack,
.irq_mask = aaec2000_int_mask,
.irq_unmask = aaec2000_int_unmask,
};
void __init aaec2000_init_irq(void)
{
unsigned int i;
for (i = 0; i < NR_IRQS; i++) {
set_irq_handler(i, handle_level_irq);
set_irq_chip(i, &aaec2000_irq_chip);
set_irq_flags(i, IRQF_VALID);
}
/* Disable all interrupts */
IRQ_INTENC = 0xffffffff;
/* Clear any pending interrupts */
IRQ_INTSR = IRQ_INTSR;
}
/*
* Time keeping
*/
/* IRQs are disabled before entering here from do_gettimeofday() */
static unsigned long aaec2000_gettimeoffset(void)
{
unsigned long ticks_to_match, elapsed, usec;
/* Get ticks before next timer match */
ticks_to_match = TIMER1_LOAD - TIMER1_VAL;
/* We need elapsed ticks since last match */
elapsed = LATCH - ticks_to_match;
/* Now, convert them to usec */
usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
return usec;
}
/* We enter here with IRQs enabled */
static irqreturn_t
aaec2000_timer_interrupt(int irq, void *dev_id)
{
/* TODO: Check timer accuracy */
timer_tick();
TIMER1_CLEAR = 1;
return IRQ_HANDLED;
}
static struct irqaction aaec2000_timer_irq = {
.name = "AAEC-2000 Timer Tick",
.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
.handler = aaec2000_timer_interrupt,
};
static void __init aaec2000_timer_init(void)
{
/* Disable timer 1 */
TIMER1_CTRL = 0;
/* We have somehow to generate a 100Hz clock.
* We then use the 508KHz timer in periodic mode.
*/
TIMER1_LOAD = LATCH;
TIMER1_CLEAR = 1; /* Clear interrupt */
setup_irq(INT_TMR1_OFL, &aaec2000_timer_irq);
TIMER1_CTRL = TIMER_CTRL_ENABLE |
TIMER_CTRL_PERIODIC |
TIMER_CTRL_CLKSEL_508K;
}
struct sys_timer aaec2000_timer = {
.init = aaec2000_timer_init,
.offset = aaec2000_gettimeoffset,
};
static struct clcd_panel mach_clcd_panel;
static int aaec2000_clcd_setup(struct clcd_fb *fb)
{
dma_addr_t dma;
fb->panel = &mach_clcd_panel;
fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, SZ_1M,
&dma, GFP_KERNEL);
if (!fb->fb.screen_base) {
printk(KERN_ERR "CLCD: unable to map framebuffer\n");
return -ENOMEM;
}
fb->fb.fix.smem_start = dma;
fb->fb.fix.smem_len = SZ_1M;
return 0;
}
static int aaec2000_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
{
return dma_mmap_writecombine(&fb->dev->dev, vma,
fb->fb.screen_base,
fb->fb.fix.smem_start,
fb->fb.fix.smem_len);
}
static void aaec2000_clcd_remove(struct clcd_fb *fb)
{
dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
fb->fb.screen_base, fb->fb.fix.smem_start);
}
static struct clcd_board clcd_plat_data = {
.name = "AAEC-2000",
.check = clcdfb_check,
.decode = clcdfb_decode,
.setup = aaec2000_clcd_setup,
.mmap = aaec2000_clcd_mmap,
.remove = aaec2000_clcd_remove,
};
static struct amba_device clcd_device = {
.dev = {
.init_name = "mb:16",
.coherent_dma_mask = ~0,
.platform_data = &clcd_plat_data,
},
.res = {
.start = AAEC_CLCD_PHYS,
.end = AAEC_CLCD_PHYS + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
.irq = { INT_LCD, NO_IRQ },
.periphid = 0x41110,
};
static struct amba_device *amba_devs[] __initdata = {
&clcd_device,
};
void clk_disable(struct clk *clk)
{
}
int clk_set_rate(struct clk *clk, unsigned long rate)
{
return 0;
}
int clk_enable(struct clk *clk)
{
return 0;
}
struct clk *clk_get(struct device *dev, const char *id)
{
return dev && strcmp(dev_name(dev), "mb:16") == 0 ? NULL : ERR_PTR(-ENOENT);
}
void clk_put(struct clk *clk)
{
}
void __init aaec2000_set_clcd_plat_data(struct aaec2000_clcd_info *clcd)
{
clcd_plat_data.enable = clcd->enable;
clcd_plat_data.disable = clcd->disable;
memcpy(&mach_clcd_panel, &clcd->panel, sizeof(struct clcd_panel));
}
static struct flash_platform_data aaec2000_flash_data = {
.map_name = "cfi_probe",
.width = 4,
};
static struct resource aaec2000_flash_resource = {
.start = AAEC_FLASH_BASE,
.end = AAEC_FLASH_BASE + AAEC_FLASH_SIZE,
.flags = IORESOURCE_MEM,
};
static struct platform_device aaec2000_flash_device = {
.name = "armflash",
.id = 0,
.dev = {
.platform_data = &aaec2000_flash_data,
},
.num_resources = 1,
.resource = &aaec2000_flash_resource,
};
static int __init aaec2000_init(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
struct amba_device *d = amba_devs[i];
amba_device_register(d, &iomem_resource);
}
platform_device_register(&aaec2000_flash_device);
return 0;
};
arch_initcall(aaec2000_init);
/*
* linux/arch/arm/mach-aaec2000/core.h
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* 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/amba/bus.h>
#include <linux/amba/clcd.h>
struct sys_timer;
extern struct sys_timer aaec2000_timer;
extern void __init aaec2000_map_io(void);
extern void __init aaec2000_init_irq(void);
struct aaec2000_clcd_info {
struct clcd_panel panel;
void (*disable)(struct clcd_fb *);
void (*enable)(struct clcd_fb *);
};
extern void __init aaec2000_set_clcd_plat_data(struct aaec2000_clcd_info *);
/*
* arch/arm/mach-aaec2000/include/mach/aaec2000.h
*
* AAEC-2000 registers definition
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* 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_AAEC2000_H
#define __ASM_ARCH_AAEC2000_H
#ifndef __ASM_ARCH_HARDWARE_H
#error You must include hardware.h not this file
#endif /* __ASM_ARCH_HARDWARE_H */
/* Chip selects */
#define AAEC_CS0 0x00000000
#define AAEC_CS1 0x10000000
#define AAEC_CS2 0x20000000
#define AAEC_CS3 0x30000000
/* Flash */
#define AAEC_FLASH_BASE AAEC_CS0
#define AAEC_FLASH_SIZE SZ_64M
/* Interrupt controller */
#define IRQ_BASE __REG(0x80000500)
#define IRQ_INTSR __REG(0x80000500) /* Int Status Register */
#define IRQ_INTRSR __REG(0x80000504) /* Int Raw (unmasked) Status */
#define IRQ_INTENS __REG(0x80000508) /* Int Enable Set */
#define IRQ_INTENC __REG(0x8000050c) /* Int Enable Clear */
/* UART 1 */
#define UART1_BASE __REG(0x80000600)
#define UART1_DR __REG(0x80000600) /* Data/FIFO Register */
#define UART1_LCR __REG(0x80000604) /* Link Control Register */
#define UART1_BRCR __REG(0x80000608) /* Baud Rate Control Register */
#define UART1_CR __REG(0x8000060c) /* Control Register */
#define UART1_SR __REG(0x80000610) /* Status Register */
#define UART1_INT __REG(0x80000614) /* Interrupt Status Register */
#define UART1_INTM __REG(0x80000618) /* Interrupt Mask Register */
#define UART1_INTRES __REG(0x8000061c) /* Int Result (masked status) Register */
/* UART 2 */
#define UART2_BASE __REG(0x80000700)
#define UART2_DR __REG(0x80000700) /* Data/FIFO Register */
#define UART2_LCR __REG(0x80000704) /* Link Control Register */
#define UART2_BRCR __REG(0x80000708) /* Baud Rate Control Register */
#define UART2_CR __REG(0x8000070c) /* Control Register */
#define UART2_SR __REG(0x80000710) /* Status Register */
#define UART2_INT __REG(0x80000714) /* Interrupt Status Register */
#define UART2_INTM __REG(0x80000718) /* Interrupt Mask Register */
#define UART2_INTRES __REG(0x8000071c) /* Int Result (masked status) Register */
/* UART 3 */
#define UART3_BASE __REG(0x80000800)
#define UART3_DR __REG(0x80000800) /* Data/FIFO Register */
#define UART3_LCR __REG(0x80000804) /* Link Control Register */
#define UART3_BRCR __REG(0x80000808) /* Baud Rate Control Register */
#define UART3_CR __REG(0x8000080c) /* Control Register */
#define UART3_SR __REG(0x80000810) /* Status Register */
#define UART3_INT __REG(0x80000814) /* Interrupt Status Register */
#define UART3_INTM __REG(0x80000818) /* Interrupt Mask Register */
#define UART3_INTRES __REG(0x8000081c) /* Int Result (masked status) Register */
/* These are used in some places */
#define _UART1_BASE __PREG(UART1_BASE)
#define _UART2_BASE __PREG(UART2_BASE)
#define _UART3_BASE __PREG(UART3_BASE)
/* UART Registers Offsets */
#define UART_DR 0x00
#define UART_LCR 0x04
#define UART_BRCR 0x08
#define UART_CR 0x0c
#define UART_SR 0x10
#define UART_INT 0x14
#define UART_INTM 0x18
#define UART_INTRES 0x1c
/* UART_LCR Bitmask */
#define UART_LCR_BRK (1 << 0) /* Send Break */
#define UART_LCR_PEN (1 << 1) /* Parity Enable */
#define UART_LCR_EP (1 << 2) /* Even/Odd Parity */
#define UART_LCR_S2 (1 << 3) /* One/Two Stop bits */
#define UART_LCR_FIFO (1 << 4) /* FIFO Enable */
#define UART_LCR_WL5 (0 << 5) /* Word Length - 5 bits */
#define UART_LCR_WL6 (1 << 5) /* Word Length - 6 bits */
#define UART_LCR_WL7 (1 << 6) /* Word Length - 7 bits */
#define UART_LCR_WL8 (1 << 7) /* Word Length - 8 bits */
/* UART_CR Bitmask */
#define UART_CR_EN (1 << 0) /* UART Enable */
#define UART_CR_SIR (1 << 1) /* IrDA SIR Enable */
#define UART_CR_SIRLP (1 << 2) /* Low Power IrDA Enable */
#define UART_CR_RXP (1 << 3) /* Receive Pin Polarity */
#define UART_CR_TXP (1 << 4) /* Transmit Pin Polarity */
#define UART_CR_MXP (1 << 5) /* Modem Pin Polarity */
#define UART_CR_LOOP (1 << 6) /* Loopback Mode */
/* UART_SR Bitmask */
#define UART_SR_CTS (1 << 0) /* Clear To Send Status */
#define UART_SR_DSR (1 << 1) /* Data Set Ready Status */
#define UART_SR_DCD (1 << 2) /* Data Carrier Detect Status */
#define UART_SR_TxBSY (1 << 3) /* Transmitter Busy Status */
#define UART_SR_RxFE (1 << 4) /* Receive FIFO Empty Status */
#define UART_SR_TxFF (1 << 5) /* Transmit FIFO Full Status */
#define UART_SR_RxFF (1 << 6) /* Receive FIFO Full Status */
#define UART_SR_TxFE (1 << 7) /* Transmit FIFO Empty Status */
/* UART_INT Bitmask */
#define UART_INT_RIS (1 << 0) /* Rx Interrupt */
#define UART_INT_TIS (1 << 1) /* Tx Interrupt */
#define UART_INT_MIS (1 << 2) /* Modem Interrupt */
#define UART_INT_RTIS (1 << 3) /* Receive Timeout Interrupt */
/* Timer 1 */
#define TIMER1_BASE __REG(0x80000c00)
#define TIMER1_LOAD __REG(0x80000c00) /* Timer 1 Load Register */
#define TIMER1_VAL __REG(0x80000c04) /* Timer 1 Value Register */
#define TIMER1_CTRL __REG(0x80000c08) /* Timer 1 Control Register */
#define TIMER1_CLEAR __REG(0x80000c0c) /* Timer 1 Clear Register */
/* Timer 2 */
#define TIMER2_BASE __REG(0x80000d00)
#define TIMER2_LOAD __REG(0x80000d00) /* Timer 2 Load Register */
#define TIMER2_VAL __REG(0x80000d04) /* Timer 2 Value Register */
#define TIMER2_CTRL __REG(0x80000d08) /* Timer 2 Control Register */
#define TIMER2_CLEAR __REG(0x80000d0c) /* Timer 2 Clear Register */
/* Timer 3 */
#define TIMER3_BASE __REG(0x80000e00)
#define TIMER3_LOAD __REG(0x80000e00) /* Timer 3 Load Register */
#define TIMER3_VAL __REG(0x80000e04) /* Timer 3 Value Register */
#define TIMER3_CTRL __REG(0x80000e08) /* Timer 3 Control Register */
#define TIMER3_CLEAR __REG(0x80000e0c) /* Timer 3 Clear Register */
/* Timer Control register bits */
#define TIMER_CTRL_ENABLE (1 << 7) /* Enable (Start Timer) */
#define TIMER_CTRL_PERIODIC (1 << 6) /* Periodic Running Mode */
#define TIMER_CTRL_FREE_RUNNING (0 << 6) /* Normal Running Mode */
#define TIMER_CTRL_CLKSEL_508K (1 << 3) /* 508KHz Clock select (Timer 1, 2) */
#define TIMER_CTRL_CLKSEL_2K (0 << 3) /* 2KHz Clock Select (Timer 1, 2) */
/* Power and State Control */
#define POWER_BASE __REG(0x80000400)
#define POWER_PWRSR __REG(0x80000400) /* Power Status Register */
#define POWER_PWRCNT __REG(0x80000404) /* Power/Clock control */
#define POWER_HALT __REG(0x80000408) /* Power Idle Mode */
#define POWER_STDBY __REG(0x8000040c) /* Power Standby Mode */
#define POWER_BLEOI __REG(0x80000410) /* Battery Low End of Interrupt */
#define POWER_MCEOI __REG(0x80000414) /* Media Changed EoI */
#define POWER_TEOI __REG(0x80000418) /* Tick EoI */
#define POWER_STFCLR __REG(0x8000041c) /* NbFlg, RSTFlg, PFFlg, CLDFlg Clear */
#define POWER_CLKSET __REG(0x80000420) /* Clock Speed Control */
/* GPIO Registers */
#define AAEC_GPIO_PHYS 0x80000e00
#define AAEC_GPIO_PADR __REG(AAEC_GPIO_PHYS + 0x00)
#define AAEC_GPIO_PBDR __REG(AAEC_GPIO_PHYS + 0x04)
#define AAEC_GPIO_PCDR __REG(AAEC_GPIO_PHYS + 0x08)
#define AAEC_GPIO_PDDR __REG(AAEC_GPIO_PHYS + 0x0c)
#define AAEC_GPIO_PADDR __REG(AAEC_GPIO_PHYS + 0x10)
#define AAEC_GPIO_PBDDR __REG(AAEC_GPIO_PHYS + 0x14)
#define AAEC_GPIO_PCDDR __REG(AAEC_GPIO_PHYS + 0x18)
#define AAEC_GPIO_PDDDR __REG(AAEC_GPIO_PHYS + 0x1c)
#define AAEC_GPIO_PEDR __REG(AAEC_GPIO_PHYS + 0x20)
#define AAEC_GPIO_PEDDR __REG(AAEC_GPIO_PHYS + 0x24)
#define AAEC_GPIO_KSCAN __REG(AAEC_GPIO_PHYS + 0x28)
#define AAEC_GPIO_PINMUX __REG(AAEC_GPIO_PHYS + 0x2c)
#define AAEC_GPIO_PFDR __REG(AAEC_GPIO_PHYS + 0x30)
#define AAEC_GPIO_PFDDR __REG(AAEC_GPIO_PHYS + 0x34)
#define AAEC_GPIO_PGDR __REG(AAEC_GPIO_PHYS + 0x38)
#define AAEC_GPIO_PGDDR __REG(AAEC_GPIO_PHYS + 0x3c)
#define AAEC_GPIO_PHDR __REG(AAEC_GPIO_PHYS + 0x40)
#define AAEC_GPIO_PHDDR __REG(AAEC_GPIO_PHYS + 0x44)
#define AAEC_GPIO_RAZ __REG(AAEC_GPIO_PHYS + 0x48)
#define AAEC_GPIO_INTTYPE1 __REG(AAEC_GPIO_PHYS + 0x4c)
#define AAEC_GPIO_INTTYPE2 __REG(AAEC_GPIO_PHYS + 0x50)
#define AAEC_GPIO_FEOI __REG(AAEC_GPIO_PHYS + 0x54)
#define AAEC_GPIO_INTEN __REG(AAEC_GPIO_PHYS + 0x58)
#define AAEC_GPIO_INTSTATUS __REG(AAEC_GPIO_PHYS + 0x5c)
#define AAEC_GPIO_RAWINTSTATUS __REG(AAEC_GPIO_PHYS + 0x60)
#define AAEC_GPIO_DB __REG(AAEC_GPIO_PHYS + 0x64)
#define AAEC_GPIO_PAPINDR __REG(AAEC_GPIO_PHYS + 0x68)
#define AAEC_GPIO_PBPINDR __REG(AAEC_GPIO_PHYS + 0x6c)
#define AAEC_GPIO_PCPINDR __REG(AAEC_GPIO_PHYS + 0x70)
#define AAEC_GPIO_PDPINDR __REG(AAEC_GPIO_PHYS + 0x74)
#define AAEC_GPIO_PEPINDR __REG(AAEC_GPIO_PHYS + 0x78)
#define AAEC_GPIO_PFPINDR __REG(AAEC_GPIO_PHYS + 0x7c)
#define AAEC_GPIO_PGPINDR __REG(AAEC_GPIO_PHYS + 0x80)
#define AAEC_GPIO_PHPINDR __REG(AAEC_GPIO_PHYS + 0x84)
#define AAEC_GPIO_PINMUX_PE0CON (1 << 0)
#define AAEC_GPIO_PINMUX_PD0CON (1 << 1)
#define AAEC_GPIO_PINMUX_CODECON (1 << 2)
#define AAEC_GPIO_PINMUX_UART3CON (1 << 3)
/* LCD Controller */
#define AAEC_CLCD_PHYS 0x80003000
#endif /* __ARM_ARCH_AAEC2000_H */
/*
* arch/arm/mach-aaec2000/include/mach/aaed2000.h
*
* AAED-2000 specific bits definition
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* 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_AAED2000_H
#define __ASM_ARCH_AAED2000_H
/* External GPIOs. */
#define EXT_GPIO_PBASE AAEC_CS3
#define EXT_GPIO_VBASE 0xf8100000
#define EXT_GPIO_LENGTH 0x00001000
#define __ext_gpio_p2v(x) ((x) - EXT_GPIO_PBASE + EXT_GPIO_VBASE)
#define __ext_gpio_v2p(x) ((x) + EXT_GPIO_PBASE - EXT_GPIO_VBASE)
#define __EXT_GPIO_REG(x) (*((volatile u32 *)__ext_gpio_p2v(x)))
#define __EXT_GPIO_PREG(x) (__ext_gpio_v2p((u32)&(x)))
#define AAED_EXT_GPIO __EXT_GPIO_REG(EXT_GPIO_PBASE)
#define AAED_EGPIO_KBD_SCAN 0x00003fff /* Keyboard scan data */
#define AAED_EGPIO_PWR_INT 0x00008fff /* Smart battery charger interrupt */
#define AAED_EGPIO_SWITCHED 0x000f0000 /* DIP Switches */
#define AAED_EGPIO_USB_VBUS 0x00400000 /* USB Vbus sense */
#define AAED_EGPIO_LCD_PWR_EN 0x02000000 /* LCD and backlight PWR enable */
#define AAED_EGPIO_nLED0 0x20000000 /* LED 0 */
#define AAED_EGPIO_nLED1 0x20000000 /* LED 1 */
#define AAED_EGPIO_nLED2 0x20000000 /* LED 2 */
#endif /* __ARM_ARCH_AAED2000_H */
/* arch/arm/mach-aaec2000/include/mach/debug-macro.S
*
* Debugging macro include header
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* 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 "hardware.h"
.macro addruart, rp, rv
mov \rp, 0x00000800
orr \rv, \rp, #io_p2v(0x80000000) @ virtual
orr \rp, \rp, #0x80000000 @ physical
.endm
.macro senduart,rd,rx
str \rd, [\rx, #0]
.endm
.macro busyuart,rd,rx
1002: ldr \rd, [\rx, #0x10]
tst \rd, #(1 << 7)
beq 1002b
.endm
.macro waituart,rd,rx
#if 0
1001: ldr \rd, [\rx, #0x10]
tst \rd, #(1 << 5)
beq 1001b
#endif
.endm
/*
* arch/arm/mach-aaec2000/include/mach/entry-macro.S
*
* Low-level IRQ helper for aaec-2000 based platforms
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* 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 <mach/irqs.h>
.macro disable_fiq
.endm
.macro get_irqnr_preamble, base, tmp
.endm
.macro arch_ret_to_user, tmp1, tmp2
.endm
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
mov r4, #0xf8000000
add r4, r4, #0x00000500
mov \base, r4
ldr \irqstat, [\base, #0]
cmp \irqstat, #0
bne 1001f
ldr \irqnr, =NR_IRQS+1
b 1003f
1001: mov \irqnr, #0
1002: ands \tmp, \irqstat, #1
mov \irqstat, \irqstat, LSR #1
add \irqnr, \irqnr, #1
beq 1002b
sub \irqnr, \irqnr, #1
1003:
.endm
/*
* arch/arm/mach-aaec2000/include/mach/hardware.h
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* 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/sizes.h>
#include <mach/aaec2000.h>
/* The kernel is loaded at physical address 0xf8000000.
* We map the IO space a bit after
*/
#define PIO_APB_BASE 0x80000000
#define VIO_APB_BASE 0xf8000000
#define IO_APB_LENGTH 0x2000
#define PIO_AHB_BASE 0x80002000
#define VIO_AHB_BASE 0xf8002000
#define IO_AHB_LENGTH 0x2000
#define VIO_BASE VIO_APB_BASE
#define PIO_BASE PIO_APB_BASE
#define io_p2v(x) ( (x) - PIO_BASE + VIO_BASE )
#define io_v2p(x) ( (x) + PIO_BASE - VIO_BASE )
#ifndef __ASSEMBLY__
#include <asm/types.h>
/* FIXME: Is it needed to optimize this a la pxa ?? */
#define __REG(x) (*((volatile u32 *)io_p2v(x)))
#define __PREG(x) (io_v2p((u32)&(x)))
#else /* __ASSEMBLY__ */
#define __REG(x) io_p2v(x)
#define __PREG(x) io_v2p(x)
#endif
#include "aaec2000.h"
#endif /* __ASM_ARCH_HARDWARE_H */
/*
* arch/arm/mach-aaec2000/include/mach/io.h
*
* Copied from asm/arch/sa1100/io.h
*/
#ifndef __ASM_ARM_ARCH_IO_H
#define __ASM_ARM_ARCH_IO_H
#define IO_SPACE_LIMIT 0xffffffff
/*
* We don't actually have real ISA nor PCI buses, but there is so many
* drivers out there that might just work if we fake them...
*/
#define __io(a) __typesafe_io(a)
#define __mem_pci(a) (a)
#endif
/*
* arch/arm/mach-aaec2000/include/mach/irqs.h
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* 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_IRQS_H
#define __ASM_ARCH_IRQS_H
#define INT_GPIOF0_FIQ 0 /* External GPIO Port F O Fast Interrupt Input */
#define INT_BL_FIQ 1 /* Battery Low Fast Interrupt */
#define INT_WE_FIQ 2 /* Watchdog Expired Fast Interrupt */
#define INT_MV_FIQ 3 /* Media Changed Interrupt */
#define INT_SC 4 /* Sound Codec Interrupt */
#define INT_GPIO1 5 /* GPIO Port F Configurable Int 1 */
#define INT_GPIO2 6 /* GPIO Port F Configurable Int 2 */
#define INT_GPIO3 7 /* GPIO Port F Configurable Int 3 */
#define INT_TMR1_OFL 8 /* Timer 1 Overflow Interrupt */
#define INT_TMR2_OFL 9 /* Timer 2 Overflow Interrupt */
#define INT_RTC_CM 10 /* RTC Compare Match Interrupt */
#define INT_TICK 11 /* 64Hz Tick Interrupt */
#define INT_UART1 12 /* UART1 Interrupt */
#define INT_UART2 13 /* UART2 & Modem State Changed Interrupt */
#define INT_LCD 14 /* LCD Interrupt */
#define INT_SSI 15 /* SSI End of Transfer Interrupt */
#define INT_UART3 16 /* UART3 Interrupt */
#define INT_SCI 17 /* SCI Interrupt */
#define INT_AAC 18 /* Advanced Audio Codec Interrupt */
#define INT_MMC 19 /* MMC Interrupt */
#define INT_USB 20 /* USB Interrupt */
#define INT_DMA 21 /* DMA Interrupt */
#define INT_TMR3_UOFL 22 /* Timer 3 Underflow Interrupt */
#define INT_GPIO4 23 /* GPIO Port F Configurable Int 4 */
#define INT_GPIO5 24 /* GPIO Port F Configurable Int 4 */
#define INT_GPIO6 25 /* GPIO Port F Configurable Int 4 */
#define INT_GPIO7 26 /* GPIO Port F Configurable Int 4 */
#define INT_BMI 27 /* BMI Interrupt */
#define NR_IRQS (INT_BMI + 1)
#endif /* __ASM_ARCH_IRQS_H */
/*
* arch/arm/mach-aaec2000/include/mach/memory.h
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* 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 PLAT_PHYS_OFFSET UL(0xf0000000)
#endif /* __ASM_ARCH_MEMORY_H */
/*
* arch/arm/mach-aaed2000/include/mach/system.h
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* 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_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H
static inline void arch_idle(void)
{
cpu_do_idle();
}
static inline void arch_reset(char mode, const char *cmd)
{
cpu_reset(0);
}
#endif /* __ASM_ARCH_SYSTEM_H */
/*
* arch/arm/mach-aaec2000/include/mach/timex.h
*
* AAEC-2000 Architecture timex specification
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* 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_TIMEX_H
#define __ASM_ARCH_TIMEX_H
#define CLOCK_TICK_RATE 508000
#endif /* __ASM_ARCH_TIMEX_H */
/*
* arch/arm/mach-aaec2000/include/mach/uncompress.h
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* 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_UNCOMPRESS_H
#define __ASM_ARCH_UNCOMPRESS_H
#include "hardware.h"
#define UART(x) (*(volatile unsigned long *)(serial_port + (x)))
static void putc(int c)
{
unsigned long serial_port;
do {
serial_port = _UART3_BASE;
if (UART(UART_CR) & UART_CR_EN) break;
serial_port = _UART1_BASE;
if (UART(UART_CR) & UART_CR_EN) break;
serial_port = _UART2_BASE;
if (UART(UART_CR) & UART_CR_EN) break;
return;
} while (0);
/* wait for space in the UART's transmitter */
while ((UART(UART_SR) & UART_SR_TxFF))
barrier();
/* send the character out. */
UART(UART_DR) = c;
}
static inline void flush(void)
{
}
#define arch_decomp_setup()
#define arch_decomp_wdog()
#endif /* __ASM_ARCH_UNCOMPRESS_H */
/*
* arch/arm/mach-aaec2000/include/mach/vmalloc.h
*
* Copyright (c) 2005 Nicolas Bellido Y Ortega
*
* 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_VMALLOC_H
#define __ASM_ARCH_VMALLOC_H
#define VMALLOC_END 0xd0000000UL
#endif /* __ASM_ARCH_VMALLOC_H */
if ARCH_LH7A40X
menu "LH7A40X Implementations"
config MACH_KEV7A400
bool "KEV7A400"
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
surprised if you wanted this option.
config MACH_LPD7A400
bool "LPD7A400 Card Engine"
select ARCH_LH7A400
# select IDE_POLL
# select HAS_TOUCHSCREEN_ADS7843_LH7
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"
select ARCH_LH7A404
# select IDE_POLL
# select HAS_TOUCHSCREEN_ADC_LH7
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
config LPD7A40X_CPLD_SSP
bool
config LH7A40X_CONTIGMEM
bool "Disable NUMA/SparseMEM Support"
help
Say Y here if your bootloader sets the SROMLL bit(s) in
the SDRAM controller, organizing memory as a contiguous
array. This option will disable sparse memory support
and force the kernel to manage all memory in one node.
Setting this option incorrectly may prevent the kernel
from booting. It is OK to leave it N.
For more information, consult
<file:Documentation/arm/Sharp-LH/SDRAM>.
config LH7A40X_ONE_BANK_PER_NODE
bool "Optimize NUMA Node Tables for Size"
depends on !LH7A40X_CONTIGMEM
help
Say Y here to produce compact memory node tables. By
default pairs of adjacent physical RAM banks are managed
together in a single node, incurring some wasted overhead
in the node tables, however also maintaining compatibility
with systems where physical memory is truly contiguous.
Setting this option incorrectly may prevent the kernel from
booting. It is OK to leave it N.
For more information, consult
<file:Documentation/arm/Sharp-LH/SDRAM>.
endmenu
endif
#
# Makefile for the linux kernel.
#
# Object file lists.
obj-y := time.o clocks.o
obj-m :=
obj-n :=
obj- :=
obj-$(CONFIG_MACH_KEV7A400) += arch-kev7a400.o irq-lh7a400.o
obj-$(CONFIG_MACH_LPD7A400) += arch-lpd7a40x.o irq-lh7a400.o
obj-$(CONFIG_MACH_LPD7A404) += arch-lpd7a40x.o irq-lh7a404.o
obj-$(CONFIG_LPD7A40X_CPLD_SSP) += ssp-cpld.o
obj-$(CONFIG_FB_ARMCLCD) += clcd.o
zreladdr-y := 0xc0008000
params_phys-y := 0xc0000100
initrd_phys-y := 0xc4000000
/* 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 <linux/interrupt.h>
#include <mach/hardware.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/mach/map.h>
#include "common.h"
/* This function calls the board specific IRQ initialization function. */
static struct map_desc kev7a400_io_desc[] __initdata = {
{
.virtual = IO_VIRT,
.pfn = __phys_to_pfn(IO_PHYS),
.length = IO_SIZE,
.type = MT_DEVICE
}, {
.virtual = CPLD_VIRT,
.pfn = __phys_to_pfn(CPLD_PHYS),
.length = CPLD_SIZE,
.type = 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(struct irq_data *d)
{
CPLD_CL_INT = 1 << (d->irq - IRQ_KEV7A400_CPLD);
}
static void kev7a400_mask_cpld_irq(struct irq_data *d)
{
CPLD_IRQ_mask &= ~(1 << (d->irq - IRQ_KEV7A400_CPLD));
CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
}
static void kev7a400_unmask_cpld_irq(struct irq_data *d)
{
CPLD_IRQ_mask |= 1 << (d->irq - IRQ_KEV7A400_CPLD);
CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
}
static struct irq_chip kev7a400_cpld_chip = {
.name = "CPLD",
.irq_ack = kev7a400_ack_cpld_irq,
.irq_mask = kev7a400_mask_cpld_irq,
.irq_unmask = kev7a400_unmask_cpld_irq,
};
static void kev7a400_cpld_handler (unsigned int irq, struct irq_desc *desc)
{
u32 mask = CPLD_LATCHED_INTS;
irq = IRQ_KEV7A400_CPLD;
for (; mask; mask >>= 1, ++irq)
if (mask & 1)
generic_handle_irq(irq);
}
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, handle_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_params = 0xc0000100,
.map_io = kev7a400_map_io,
.init_irq = lh7a400_init_irq,
.timer = &lh7a40x_timer,
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/platform_device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <mach/hardware.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/mach/map.h>
#include "common.h"
#define CPLD_INT_NETHERNET (1<<0)
#define CPLD_INTMASK_ETHERNET (1<<2)
#if defined (CONFIG_MACH_LPD7A400)
# define CPLD_INT_NTOUCH (1<<1)
# define CPLD_INTMASK_TOUCH (1<<3)
# define CPLD_INT_PEN (1<<4)
# define CPLD_INTMASK_PEN (1<<4)
# define CPLD_INT_PIRQ (1<<4)
#endif
#define CPLD_INTMASK_CPLD (1<<7)
#define CPLD_INT_CPLD (1<<6)
#define CPLD_CONTROL_SWINT (1<<7) /* Disable all CPLD IRQs */
#define CPLD_CONTROL_OCMSK (1<<6) /* Mask USB1 connect IRQ */
#define CPLD_CONTROL_PDRV (1<<5) /* PCC_nDRV high */
#define CPLD_CONTROL_USB1C (1<<4) /* USB1 connect IRQ active */
#define CPLD_CONTROL_USB1P (1<<3) /* USB1 power disable */
#define CPLD_CONTROL_AWKP (1<<2) /* Auto-wakeup disabled */
#define CPLD_CONTROL_LCD_ENABLE (1<<1) /* LCD Vee enable */
#define CPLD_CONTROL_WRLAN_NENABLE (1<<0) /* SMC91x power disable */
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,
};
static struct resource lh7a40x_usbclient_resources[] = {
[0] = {
.start = USB_PHYS,
.end = (USB_PHYS + PAGE_SIZE),
.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",
.name = "lh7-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,
};
#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)
{
#if defined (CONFIG_MACH_LPD7A400)
CPLD_CONTROL |= 0
| CPLD_CONTROL_SWINT /* Disable software interrupt */
| CPLD_CONTROL_OCMSK; /* Mask USB1 connection IRQ */
CPLD_CONTROL &= ~(0
| CPLD_CONTROL_LCD_ENABLE /* Disable LCD */
| CPLD_CONTROL_WRLAN_NENABLE /* Enable SMC91x */
);
#endif
#if defined (CONFIG_MACH_LPD7A404)
CPLD_CONTROL &= ~(0
| CPLD_CONTROL_WRLAN_NENABLE /* Enable SMC91x */
);
#endif
platform_add_devices (lpd7a40x_devs, ARRAY_SIZE (lpd7a40x_devs));
#if defined (CONFIG_FB_ARMCLCD)
lh7a40x_clcd_init ();
#endif
}
static void lh7a40x_ack_cpld_irq(struct irq_data *d)
{
/* CPLD doesn't have ack capability, but some devices may */
#if defined (CPLD_INTMASK_TOUCH)
/* The touch control *must* mask the interrupt because the
* interrupt bit is read by the driver to determine if the pen
* is still down. */
if (d->irq == IRQ_TOUCH)
CPLD_INTERRUPTS |= CPLD_INTMASK_TOUCH;
#endif
}
static void lh7a40x_mask_cpld_irq(struct irq_data *d)
{
switch (d->irq) {
case IRQ_LPD7A40X_ETH_INT:
CPLD_INTERRUPTS |= CPLD_INTMASK_ETHERNET;
break;
#if defined (IRQ_TOUCH)
case IRQ_TOUCH:
CPLD_INTERRUPTS |= CPLD_INTMASK_TOUCH;
break;
#endif
}
}
static void lh7a40x_unmask_cpld_irq(struct irq_data *d)
{
switch (d->irq) {
case IRQ_LPD7A40X_ETH_INT:
CPLD_INTERRUPTS &= ~CPLD_INTMASK_ETHERNET;
break;
#if defined (IRQ_TOUCH)
case IRQ_TOUCH:
CPLD_INTERRUPTS &= ~CPLD_INTMASK_TOUCH;
break;
#endif
}
}
static struct irq_chip lpd7a40x_cpld_chip = {
.name = "CPLD",
.irq_ack = lh7a40x_ack_cpld_irq,
.irq_mask = lh7a40x_mask_cpld_irq,
.irq_unmask = lh7a40x_unmask_cpld_irq,
};
static void lpd7a40x_cpld_handler (unsigned int irq, struct irq_desc *desc)
{
unsigned int mask = CPLD_INTERRUPTS;
desc->irq_data.chip->irq_ack(&desc->irq_data);
if ((mask & (1<<0)) == 0) /* WLAN */
generic_handle_irq(IRQ_LPD7A40X_ETH_INT);
#if defined (IRQ_TOUCH)
if ((mask & (1<<1)) == 0) /* Touch */
generic_handle_irq(IRQ_TOUCH);
#endif
/* Level-triggered need this */
desc->irq_data.chip->irq_unmask(&desc->irq_data);
}
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; /* Coerce LPD7A404 to RevB */
#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 */
/* Disable all CPLD interrupts */
#if defined (CONFIG_MACH_LPD7A400)
CPLD_INTERRUPTS = CPLD_INTMASK_TOUCH | CPLD_INTMASK_PEN
| CPLD_INTMASK_ETHERNET;
/* *** FIXME: don't know why we need 7 and 4. 7 is way wrong
and 4 is uncefined. */
// (1<<7)|(1<<4)|(1<<3)|(1<<2);
#endif
#if defined (CONFIG_MACH_LPD7A404)
CPLD_INTERRUPTS = CPLD_INTMASK_ETHERNET;
/* *** FIXME: don't know why we need 6 and 5, neither is defined. */
// (1<<6)|(1<<5)|(1<<3);
#endif
GPIO_PFDD &= ~(1 << pinCPLD); /* Make input */
GPIO_INTTYPE1 &= ~(1 << pinCPLD); /* Level 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, handle_level_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 lpd7a40x_io_desc[] __initdata = {
{
.virtual = IO_VIRT,
.pfn = __phys_to_pfn(IO_PHYS),
.length = IO_SIZE,
.type = MT_DEVICE
},
{ /* Mapping added to work around chip select problems */
.virtual = IOBARRIER_VIRT,
.pfn = __phys_to_pfn(IOBARRIER_PHYS),
.length = IOBARRIER_SIZE,
.type = MT_DEVICE
},
{
.virtual = CF_VIRT,
.pfn = __phys_to_pfn(CF_PHYS),
.length = CF_SIZE,
.type = MT_DEVICE
},
{
.virtual = CPLD02_VIRT,
.pfn = __phys_to_pfn(CPLD02_PHYS),
.length = CPLD02_SIZE,
.type = MT_DEVICE
},
{
.virtual = CPLD06_VIRT,
.pfn = __phys_to_pfn(CPLD06_PHYS),
.length = CPLD06_SIZE,
.type = MT_DEVICE
},
{
.virtual = CPLD08_VIRT,
.pfn = __phys_to_pfn(CPLD08_PHYS),
.length = CPLD08_SIZE,
.type = MT_DEVICE
},
{
.virtual = CPLD08_VIRT,
.pfn = __phys_to_pfn(CPLD08_PHYS),
.length = CPLD08_SIZE,
.type = MT_DEVICE
},
{
.virtual = CPLD0A_VIRT,
.pfn = __phys_to_pfn(CPLD0A_PHYS),
.length = CPLD0A_SIZE,
.type = MT_DEVICE
},
{
.virtual = CPLD0C_VIRT,
.pfn = __phys_to_pfn(CPLD0C_PHYS),
.length = CPLD0C_SIZE,
.type = MT_DEVICE
},
{
.virtual = CPLD0E_VIRT,
.pfn = __phys_to_pfn(CPLD0E_PHYS),
.length = CPLD0E_SIZE,
.type = MT_DEVICE
},
{
.virtual = CPLD10_VIRT,
.pfn = __phys_to_pfn(CPLD10_PHYS),
.length = CPLD10_SIZE,
.type = MT_DEVICE
},
{
.virtual = CPLD12_VIRT,
.pfn = __phys_to_pfn(CPLD12_PHYS),
.length = CPLD12_SIZE,
.type = MT_DEVICE
},
{
.virtual = CPLD14_VIRT,
.pfn = __phys_to_pfn(CPLD14_PHYS),
.length = CPLD14_SIZE,
.type = MT_DEVICE
},
{
.virtual = CPLD16_VIRT,
.pfn = __phys_to_pfn(CPLD16_PHYS),
.length = CPLD16_SIZE,
.type = MT_DEVICE
},
{
.virtual = CPLD18_VIRT,
.pfn = __phys_to_pfn(CPLD18_PHYS),
.length = CPLD18_SIZE,
.type = MT_DEVICE
},
{
.virtual = CPLD1A_VIRT,
.pfn = __phys_to_pfn(CPLD1A_PHYS),
.length = CPLD1A_SIZE,
.type = MT_DEVICE
},
};
void __init
lpd7a40x_map_io(void)
{
iotable_init (lpd7a40x_io_desc, ARRAY_SIZE (lpd7a40x_io_desc));
}
#ifdef CONFIG_MACH_LPD7A400
MACHINE_START (LPD7A400, "Logic Product Development LPD7A400-10")
/* Maintainer: Marc Singer */
.boot_params = 0xc0000100,
.map_io = lpd7a40x_map_io,
.init_irq = lh7a400_init_irq,
.timer = &lh7a40x_timer,
.init_machine = lpd7a40x_init,
MACHINE_END
#endif
#ifdef CONFIG_MACH_LPD7A404
MACHINE_START (LPD7A404, "Logic Product Development LPD7A404-10")
/* Maintainer: Marc Singer */
.boot_params = 0xc0000100,
.map_io = lpd7a40x_map_io,
.init_irq = lh7a404_init_irq,
.timer = &lh7a40x_timer,
.init_machine = lpd7a40x_init,
MACHINE_END
#endif
/*
* arch/arm/mach-lh7a40x/clcd.c
*
* Copyright (C) 2004 Marc Singer
*
* 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/gfp.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/sysdev.h>
#include <linux/interrupt.h>
//#include <linux/module.h>
//#include <linux/time.h>
//#include <asm/mach/time.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/system.h>
#include <mach/hardware.h>
#include <linux/amba/bus.h>
#include <linux/amba/clcd.h>
#define HRTFTC_HRSETUP __REG(HRTFTC_PHYS + 0x00)
#define HRTFTC_HRCON __REG(HRTFTC_PHYS + 0x04)
#define HRTFTC_HRTIMING1 __REG(HRTFTC_PHYS + 0x08)
#define HRTFTC_HRTIMING2 __REG(HRTFTC_PHYS + 0x0c)
#define ALI_SETUP __REG(ALI_PHYS + 0x00)
#define ALI_CONTROL __REG(ALI_PHYS + 0x04)
#define ALI_TIMING1 __REG(ALI_PHYS + 0x08)
#define ALI_TIMING2 __REG(ALI_PHYS + 0x0c)
#include "lcd-panel.h"
static void lh7a40x_clcd_disable (struct clcd_fb *fb)
{
#if defined (CONFIG_MACH_LPD7A400)
CPLD_CONTROL &= ~(1<<1); /* Disable LCD Vee */
#endif
#if defined (CONFIG_MACH_LPD7A404)
GPIO_PCD &= ~(1<<3); /* Disable LCD Vee */
#endif
#if defined (CONFIG_ARCH_LH7A400)
HRTFTC_HRSETUP &= ~(1<<13); /* Disable HRTFT controller */
#endif
#if defined (CONFIG_ARCH_LH7A404)
ALI_SETUP &= ~(1<<13); /* Disable ALI */
#endif
}
static void lh7a40x_clcd_enable (struct clcd_fb *fb)
{
struct clcd_panel_extra* extra
= (struct clcd_panel_extra*) fb->board_data;
#if defined (CONFIG_MACH_LPD7A400)
CPLD_CONTROL |= (1<<1); /* Enable LCD Vee */
#endif
#if defined (CONFIG_MACH_LPD7A404)
GPIO_PCDD &= ~(1<<3); /* Enable LCD Vee */
GPIO_PCD |= (1<<3);
#endif
#if defined (CONFIG_ARCH_LH7A400)
if (extra) {
HRTFTC_HRSETUP
= (1 << 13)
| ((fb->fb.var.xres - 1) << 4)
| 0xc
| (extra->hrmode ? 1 : 0);
HRTFTC_HRCON
= ((extra->clsen ? 1 : 0) << 1)
| ((extra->spsen ? 1 : 0) << 0);
HRTFTC_HRTIMING1
= (extra->pcdel << 8)
| (extra->revdel << 4)
| (extra->lpdel << 0);
HRTFTC_HRTIMING2
= (extra->spldel << 9)
| (extra->pc2del << 0);
}
else
HRTFTC_HRSETUP
= (1 << 13)
| 0xc;
#endif
#if defined (CONFIG_ARCH_LH7A404)
if (extra) {
ALI_SETUP
= (1 << 13)
| ((fb->fb.var.xres - 1) << 4)
| 0xc
| (extra->hrmode ? 1 : 0);
ALI_CONTROL
= ((extra->clsen ? 1 : 0) << 1)
| ((extra->spsen ? 1 : 0) << 0);
ALI_TIMING1
= (extra->pcdel << 8)
| (extra->revdel << 4)
| (extra->lpdel << 0);
ALI_TIMING2
= (extra->spldel << 9)
| (extra->pc2del << 0);
}
else
ALI_SETUP
= (1 << 13)
| 0xc;
#endif
}
#define FRAMESIZE(s) (((s) + PAGE_SIZE - 1)&PAGE_MASK)
static int lh7a40x_clcd_setup (struct clcd_fb *fb)
{
dma_addr_t dma;
u32 len = FRAMESIZE (lcd_panel.mode.xres*lcd_panel.mode.yres
*(lcd_panel.bpp/8));
fb->panel = &lcd_panel;
/* Enforce the sync polarity defaults */
if (!(fb->panel->tim2 & TIM2_IHS))
fb->fb.var.sync |= FB_SYNC_HOR_HIGH_ACT;
if (!(fb->panel->tim2 & TIM2_IVS))
fb->fb.var.sync |= FB_SYNC_VERT_HIGH_ACT;
#if defined (HAS_LCD_PANEL_EXTRA)
fb->board_data = &lcd_panel_extra;
#endif
fb->fb.screen_base
= dma_alloc_writecombine (&fb->dev->dev, len,
&dma, GFP_KERNEL);
printk ("CLCD: LCD setup fb virt 0x%p phys 0x%p l %x io 0x%p \n",
fb->fb.screen_base, (void*) dma, len,
(void*) io_p2v (CLCDC_PHYS));
printk ("CLCD: pixclock %d\n", lcd_panel.mode.pixclock);
if (!fb->fb.screen_base) {
printk(KERN_ERR "CLCD: unable to map framebuffer\n");
return -ENOMEM;
}
#if defined (USE_RGB555)
fb->fb.var.green.length = 5; /* Panel uses RGB 5:5:5 */
#endif
fb->fb.fix.smem_start = dma;
fb->fb.fix.smem_len = len;
/* Drive PE4 high to prevent CPLD crash */
GPIO_PEDD |= (1<<4);
GPIO_PED |= (1<<4);
GPIO_PINMUX |= (1<<1) | (1<<0); /* LCDVD[15:4] */
// fb->fb.fbops->fb_check_var (&fb->fb.var, &fb->fb);
// fb->fb.fbops->fb_set_par (&fb->fb);
return 0;
}
static int lh7a40x_clcd_mmap (struct clcd_fb *fb, struct vm_area_struct *vma)
{
return dma_mmap_writecombine(&fb->dev->dev, vma,
fb->fb.screen_base,
fb->fb.fix.smem_start,
fb->fb.fix.smem_len);
}
static void lh7a40x_clcd_remove (struct clcd_fb *fb)
{
dma_free_writecombine (&fb->dev->dev, fb->fb.fix.smem_len,
fb->fb.screen_base, fb->fb.fix.smem_start);
}
static struct clcd_board clcd_platform_data = {
.name = "lh7a40x FB",
.check = clcdfb_check,
.decode = clcdfb_decode,
.enable = lh7a40x_clcd_enable,
.setup = lh7a40x_clcd_setup,
.mmap = lh7a40x_clcd_mmap,
.remove = lh7a40x_clcd_remove,
.disable = lh7a40x_clcd_disable,
};
#define IRQ_CLCDC (IRQ_LCDINTR)
#define AMBA_DEVICE(name,busid,base,plat,pid) \
static struct amba_device name##_device = { \
.dev = { \
.coherent_dma_mask = ~0, \
.init_name = busid, \
.platform_data = plat, \
}, \
.res = { \
.start = base##_PHYS, \
.end = (base##_PHYS) + (4*1024) - 1, \
.flags = IORESOURCE_MEM, \
}, \
.dma_mask = ~0, \
.irq = { IRQ_##base, }, \
/* .dma = base##_DMA,*/ \
.periphid = pid, \
}
AMBA_DEVICE(clcd, "cldc-lh7a40x", CLCDC, &clcd_platform_data, 0x41110);
static struct amba_device *amba_devs[] __initdata = {
&clcd_device,
};
void __init lh7a40x_clcd_init (void)
{
int i;
int result;
printk ("CLCD: registering amba devices\n");
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
struct amba_device *d = amba_devs[i];
result = amba_device_register(d, &iomem_resource);
printk (" %d -> %d\n", i ,result);
}
}
/* arch/arm/mach-lh7a40x/clocks.c
*
* Copyright (C) 2004 Marc Singer
*
* 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 <mach/hardware.h>
#include <mach/clocks.h>
#include <linux/err.h>
#include <linux/device.h>
#include <linux/string.h>
struct module;
struct clk {
struct list_head node;
unsigned long rate;
struct module *owner;
const char *name;
};
/* ----- */
#define MAINDIV1(c) (((c) >> 7) & 0x0f)
#define MAINDIV2(c) (((c) >> 11) & 0x1f)
#define PS(c) (((c) >> 18) & 0x03)
#define PREDIV(c) (((c) >> 2) & 0x1f)
#define HCLKDIV(c) (((c) >> 0) & 0x02)
#define PCLKDIV(c) (((c) >> 16) & 0x03)
unsigned int fclkfreq_get (void)
{
unsigned int clkset = CSC_CLKSET;
unsigned int gclk
= XTAL_IN
/ (1 << PS(clkset))
* (MAINDIV1(clkset) + 2)
/ (PREDIV(clkset) + 2)
* (MAINDIV2(clkset) + 2)
;
return gclk;
}
unsigned int hclkfreq_get (void)
{
unsigned int clkset = CSC_CLKSET;
unsigned int hclk = fclkfreq_get () / (HCLKDIV(clkset) + 1);
return hclk;
}
unsigned int pclkfreq_get (void)
{
unsigned int clkset = CSC_CLKSET;
int pclkdiv = PCLKDIV(clkset);
unsigned int pclk;
if (pclkdiv == 0x3)
pclkdiv = 0x2;
pclk = hclkfreq_get () / (1 << pclkdiv);
return pclk;
}
/* ----- */
struct clk *clk_get (struct device *dev, const char *id)
{
return dev && strcmp(dev_name(dev), "cldc-lh7a40x") == 0
? NULL : ERR_PTR(-ENOENT);
}
EXPORT_SYMBOL(clk_get);
void clk_put (struct clk *clk)
{
}
EXPORT_SYMBOL(clk_put);
int clk_enable (struct clk *clk)
{
return 0;
}
EXPORT_SYMBOL(clk_enable);
void clk_disable (struct clk *clk)
{
}
EXPORT_SYMBOL(clk_disable);
unsigned long clk_get_rate (struct clk *clk)
{
return 0;
}
EXPORT_SYMBOL(clk_get_rate);
long clk_round_rate (struct clk *clk, unsigned long rate)
{
return rate;
}
EXPORT_SYMBOL(clk_round_rate);
int clk_set_rate (struct clk *clk, unsigned long rate)
{
return -EIO;
}
EXPORT_SYMBOL(clk_set_rate);
/* arch/arm/mach-lh7a40x/common.h
*
* Copyright (C) 2004 Marc Singer
*
* 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.
*
*/
extern struct sys_timer lh7a40x_timer;
extern void lh7a400_init_irq (void);
extern void lh7a404_init_irq (void);
extern void lh7a40x_clcd_init (void);
extern void lh7a40x_init_board_irq (void);
/* arch/arm/mach-lh7a40x/include/mach/clocks.h
*
* Copyright (C) 2004 Marc Singer
*
* 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_CLOCKS_H
#define __ASM_ARCH_CLOCKS_H
unsigned int fclkfreq_get (void);
unsigned int hclkfreq_get (void);
unsigned int pclkfreq_get (void);
#endif /* _ASM_ARCH_CLOCKS_H */
/* arch/arm/mach-lh7a40x/include/mach/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
/* 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 0x10000000 /* Second bank, fastest timing */
# 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 CPLD0A_PHYS CPLDX_PHYS (0x0a)
# define CPLD0A_VIRT CPLDX_VIRT (0x0a)
# define CPLD0A_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 */
#define HCLK (99993600)
//#define HCLK (119808000)
#endif /* __ASM_ARCH_CONSTANTS_H */
/* arch/arm/mach-lh7a40x/include/mach/debug-macro.S
*
* Debugging macro include header
*
* Copyright (C) 1994-1999 Russell King
* Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
*
* 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 not known if this will be appropriate for every 40x
@ board.
.macro addruart, rp, rv
mov \rp, #0x00000700 @ offset from base
orr \rv, \rp, #0xf8000000 @ virtual base
orr \rp, \rp, #0x80000000 @ physical 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
/* arch/arm/mach-lh7a40x/include/mach/dma.h
*
* Copyright (C) 2005 Marc Singer
*
* 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.
*
*/
typedef enum {
DMA_M2M0 = 0,
DMA_M2M1 = 1,
DMA_M2P0 = 2, /* Tx */
DMA_M2P1 = 3, /* Rx */
DMA_M2P2 = 4, /* Tx */
DMA_M2P3 = 5, /* Rx */
DMA_M2P4 = 6, /* Tx - AC97 */
DMA_M2P5 = 7, /* Rx - AC97 */
DMA_M2P6 = 8, /* Tx */
DMA_M2P7 = 9, /* Rx */
} dma_device_t;
#define DMA_LENGTH_MAX ((64*1024) - 4) /* bytes */
#define DMAC_GCA __REG(DMAC_PHYS + 0x2b80)
#define DMAC_GIR __REG(DMAC_PHYS + 0x2bc0)
#define DMAC_GIR_MMI1 (1<<11)
#define DMAC_GIR_MMI0 (1<<10)
#define DMAC_GIR_MPI8 (1<<9)
#define DMAC_GIR_MPI9 (1<<8)
#define DMAC_GIR_MPI6 (1<<7)
#define DMAC_GIR_MPI7 (1<<6)
#define DMAC_GIR_MPI4 (1<<5)
#define DMAC_GIR_MPI5 (1<<4)
#define DMAC_GIR_MPI2 (1<<3)
#define DMAC_GIR_MPI3 (1<<2)
#define DMAC_GIR_MPI0 (1<<1)
#define DMAC_GIR_MPI1 (1<<0)
#define DMAC_M2P0 0x0000
#define DMAC_M2P1 0x0040
#define DMAC_M2P2 0x0080
#define DMAC_M2P3 0x00c0
#define DMAC_M2P4 0x0240
#define DMAC_M2P5 0x0200
#define DMAC_M2P6 0x02c0
#define DMAC_M2P7 0x0280
#define DMAC_M2P8 0x0340
#define DMAC_M2P9 0x0300
#define DMAC_M2M0 0x0100
#define DMAC_M2M1 0x0140
#define DMAC_P_PCONTROL(c) __REG(DMAC_PHYS + (c) + 0x00)
#define DMAC_P_PINTERRUPT(c) __REG(DMAC_PHYS + (c) + 0x04)
#define DMAC_P_PPALLOC(c) __REG(DMAC_PHYS + (c) + 0x08)
#define DMAC_P_PSTATUS(c) __REG(DMAC_PHYS + (c) + 0x0c)
#define DMAC_P_REMAIN(c) __REG(DMAC_PHYS + (c) + 0x14)
#define DMAC_P_MAXCNT0(c) __REG(DMAC_PHYS + (c) + 0x20)
#define DMAC_P_BASE0(c) __REG(DMAC_PHYS + (c) + 0x24)
#define DMAC_P_CURRENT0(c) __REG(DMAC_PHYS + (c) + 0x28)
#define DMAC_P_MAXCNT1(c) __REG(DMAC_PHYS + (c) + 0x30)
#define DMAC_P_BASE1(c) __REG(DMAC_PHYS + (c) + 0x34)
#define DMAC_P_CURRENT1(c) __REG(DMAC_PHYS + (c) + 0x38)
#define DMAC_PCONTROL_ENABLE (1<<4)
#define DMAC_PORT_USB 0
#define DMAC_PORT_SDMMC 1
#define DMAC_PORT_AC97_1 2
#define DMAC_PORT_AC97_2 3
#define DMAC_PORT_AC97_3 4
#define DMAC_PORT_UART1 6
#define DMAC_PORT_UART2 7
#define DMAC_PORT_UART3 8
#define DMAC_PSTATUS_CURRSTATE_SHIFT 4
#define DMAC_PSTATUS_CURRSTATE_MASK 0x3
#define DMAC_PSTATUS_NEXTBUF (1<<6)
#define DMAC_PSTATUS_STALLRINT (1<<0)
#define DMAC_INT_CHE (1<<3)
#define DMAC_INT_NFB (1<<1)
#define DMAC_INT_STALL (1<<0)
/*
* arch/arm/mach-lh7a40x/include/mach/entry-macro.S
*
* Low-level IRQ helper macros for LH7A40x platforms
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <mach/hardware.h>
#include <mach/irqs.h>
/* In order to allow there to be support for both of the processor
classes at the same time, we make a hack here that isn't very
pretty. At startup, the link pointed to with the
branch_irq_lh7a400 symbol is replaced with a NOP when the CPU is
detected as a lh7a404.
*** FIXME: we should clean this up so that there is only one
implementation for each CPU's design.
*/
#if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
.macro disable_fiq
.endm
.macro get_irqnr_preamble, base, tmp
.endm
.macro arch_ret_to_user, tmp1, tmp2
.endm
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
branch_irq_lh7a400: b 1000f
@ Implementation of the LH7A404 get_irqnr_and_base.
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
b 1009f
@ Implementation of the LH7A400 get_irqnr_and_base.
1000: 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
#elif defined (CONFIG_ARCH_LH7A400)
.macro disable_fiq
.endm
.macro get_irqnr_preamble, base, tmp
.endm
.macro arch_ret_to_user, tmp1, tmp2
.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
#elif defined(CONFIG_ARCH_LH7A404)
.macro disable_fiq
.endm
.macro get_irqnr_preamble, base, tmp
.endm
.macro arch_ret_to_user, tmp1, tmp2
.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
#endif
/* arch/arm/mach-lh7a40x/include/mach/hardware.h
*
* Copyright (C) 2004 Coastal Environmental Systems
*
* [ Substantially cribbed from arch/arm/mach-pxa/include/mach/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/sizes.h> /* Added for the sake of amba-clcd driver */
#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 contiguous 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)>>1]
# define __REG16(x) __REGP16(io_p2v(x))
typedef struct { volatile u8 offset[4096]; } __regbase8;
# define __REGP8(x) ((__regbase8 *)((x)&~4095))->offset[(x)&4095]
# 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
#define MASK_AND_SET(v,m,s) (v) = ((v)&~(m))|(s)
#include "registers.h"
#endif /* _ASM_ARCH_HARDWARE_H */
/* arch/arm/mach-lh7a40x/include/mach/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) __typesafe_io(a)
#define __mem_pci(a) (a)
#endif /* __ASM_ARCH_IO_H */
/* arch/arm/mach-lh7a40x/include/mach/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
#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 */
#define IRQ_USB IRQ_USBINTR /* USB device */
#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
#if defined (CONFIG_MACH_LPD7A400)
# define IRQ_TOUCH IRQ_LPD7A400_TS
#endif
#define NR_IRQS (NR_IRQ_CPU + NR_IRQ_BOARD)
#endif
/* arch/arm/mach-lh7a40x/include/mach/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.
*
*
* Refer to <file:Documentation/arm/Sharp-LH/SDRAM> for more information.
*
*/
#ifndef __ASM_ARCH_MEMORY_H
#define __ASM_ARCH_MEMORY_H
/*
* Physical DRAM offset.
*/
#define PLAT_PHYS_OFFSET UL(0xc0000000)
/*
* Sparsemem version of the above
*/
#define MAX_PHYSMEM_BITS 32
#define SECTION_SIZE_BITS 24
#endif
/* arch/arm/mach-lh7a40x/include/mach/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 <mach/constants.h>
#ifndef __ASM_ARCH_REGISTERS_H
#define __ASM_ARCH_REGISTERS_H
/* Physical register base addresses */
#define AC97C_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 HRTFTC_PHYS (0x80001000) /* High-res TFT Controller (LH7A400) */
#define ALI_PHYS (0x80001000) /* Advanced LCD Interface (LH7A404) */
#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 ADC_PHYS (0x80001300) /* A/D & Touchscreen Controller */
#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_PWRSR __REG(CSC_PHYS + 0x00) /* Reset register & ID */
#define CSC_PWRCNT __REG(CSC_PHYS + 0x04) /* Power control */
#define CSC_CLKSET __REG(CSC_PHYS + 0x20) /* Clock speed control */
#define CSC_USBDRESET __REG(CSC_PHYS + 0x4c) /* USB Device resets */
#define CSC_PWRCNT_USBH_EN (1<<28) /* USB Host power enable */
#define CSC_PWRCNT_DMAC_M2M1_EN (1<<27)
#define CSC_PWRCNT_DMAC_M2M0_EN (1<<26)
#define CSC_PWRCNT_DMAC_M2P8_EN (1<<25)
#define CSC_PWRCNT_DMAC_M2P9_EN (1<<24)
#define CSC_PWRCNT_DMAC_M2P6_EN (1<<23)
#define CSC_PWRCNT_DMAC_M2P7_EN (1<<22)
#define CSC_PWRCNT_DMAC_M2P4_EN (1<<21)
#define CSC_PWRCNT_DMAC_M2P5_EN (1<<20)
#define CSC_PWRCNT_DMAC_M2P2_EN (1<<19)
#define CSC_PWRCNT_DMAC_M2P3_EN (1<<18)
#define CSC_PWRCNT_DMAC_M2P0_EN (1<<17)
#define CSC_PWRCNT_DMAC_M2P1_EN (1<<16)
#define CSC_PWRSR_CHIPMAN_SHIFT (24)
#define CSC_PWRSR_CHIPMAN_MASK (0xff)
#define CSC_PWRSR_CHIPID_SHIFT (16)
#define CSC_PWRSR_CHIPID_MASK (0xff)
#define CSC_USBDRESET_APBRESETREG (1<<1)
#define CSC_USBDRESET_IORESETREG (1<<0)
/* 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 */
#define GPIO_PINMUX __REG(GPIO_PHYS + 0x2c)
#define GPIO_PADD __REG(GPIO_PHYS + 0x10)
#define GPIO_PAD __REG(GPIO_PHYS + 0x00)
#define GPIO_PCD __REG(GPIO_PHYS + 0x08)
#define GPIO_PCDD __REG(GPIO_PHYS + 0x18)
#define GPIO_PEDD __REG(GPIO_PHYS + 0x24)
#define GPIO_PED __REG(GPIO_PHYS + 0x20)
/* 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 __REG16(CPLD02_PHYS)
# define CPLD_SPI_DATA __REG16(CPLD06_PHYS)
# define CPLD_SPI_CONTROL __REG16(CPLD08_PHYS)
# define CPLD_SPI_EEPROM __REG16(CPLD0A_PHYS)
# define CPLD_INTERRUPTS __REG16(CPLD0C_PHYS) /* IRQ mask/status */
# define CPLD_BOOT_MODE __REG16(CPLD0E_PHYS)
# define CPLD_FLASH __REG16(CPLD10_PHYS)
# define CPLD_POWER_MGMT __REG16(CPLD12_PHYS)
# define CPLD_REVISION __REG16(CPLD14_PHYS)
# define CPLD_GPIO_EXT __REG16(CPLD16_PHYS)
# define CPLD_GPIO_DATA __REG16(CPLD18_PHYS)
# define CPLD_GPIO_DIR __REG16(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 */
/* ssp.h
written by Marc Singer
6 Dec 2004
Copyright (C) 2004 Marc Singer
-----------
DESCRIPTION
-----------
This SSP header is available throughout the kernel, for this
machine/architecture, because drivers that use it may be dispersed.
This file was cloned from the 7952x implementation. It would be
better to share them, but we're taking an easier approach for the
time being.
*/
#if !defined (__SSP_H__)
# define __SSP_H__
/* ----- Includes */
/* ----- Types */
struct ssp_driver {
int (*init) (void);
void (*exit) (void);
void (*acquire) (void);
void (*release) (void);
int (*configure) (int device, int mode, int speed,
int frame_size_write, int frame_size_read);
void (*chip_select) (int enable);
void (*set_callbacks) (void* handle,
irqreturn_t (*callback_tx)(void*),
irqreturn_t (*callback_rx)(void*));
void (*enable) (void);
void (*disable) (void);
// int (*save_state) (void*);
// void (*restore_state) (void*);
int (*read) (void);
int (*write) (u16 data);
int (*write_read) (u16 data);
void (*flush) (void);
void (*write_async) (void* pv, size_t cb);
size_t (*write_pos) (void);
};
/* These modes are only available on the LH79524 */
#define SSP_MODE_SPI (1)
#define SSP_MODE_SSI (2)
#define SSP_MODE_MICROWIRE (3)
#define SSP_MODE_I2S (4)
/* CPLD SPI devices */
#define DEVICE_EEPROM 0 /* Configuration eeprom */
#define DEVICE_MAC 1 /* MAC eeprom (LPD79524) */
#define DEVICE_CODEC 2 /* Audio codec */
#define DEVICE_TOUCH 3 /* Touch screen (LPD79520) */
/* ----- Globals */
/* ----- Prototypes */
//extern struct ssp_driver lh79520_i2s_driver;
extern struct ssp_driver lh7a400_cpld_ssp_driver;
#endif /* __SSP_H__ */
/* arch/arm/mach-lh7a40x/include/mach/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, const char *cmd)
{
cpu_reset (0);
}
/* arch/arm/mach-lh7a40x/include/mach/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 <mach/constants.h>
#define CLOCK_TICK_RATE (PLL_CLOCK/6/16)
/*
#define CLOCK_TICK_RATE 3686400
*/
/* arch/arm/mach-lh7a40x/include/mach/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 <mach/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(int ch)
{
while (UART_STATUS & nTxRdy)
barrier();
UART_DATA = ch;
}
static inline void flush(void)
{
}
/* NULL functions; we don't presently need them */
#define arch_decomp_setup()
#define arch_decomp_wdog()
/* arch/arm/mach-lh7a40x/include/mach/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.
*
*/
#define VMALLOC_END (0xe8000000UL)
/* 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>
#include "common.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
irq_chip lh7a400_cpld_chip = {
.name = "CPLD",
.ack = lh7a400_ack_cpld_irq,
.mask = lh7a400_mask_cpld_irq,
.unmask = lh7a400_unmask_cpld_irq,
};
static void
lh7a400_cpld_handler (unsigned int irq, struct irq_desc *desc)
{
u32 mask = CPLD_LATCHED_INTS;
irq = IRQ_KEV_7A400_CPLD;
for (; mask; mask >>= 1, ++irq) {
if (mask & 1)
desc[irq].handle (irq, desc);
}
}
/* 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, handle_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 <mach/hardware.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <mach/irqs.h>
#include "common.h"
/* CPU IRQ handling */
static void lh7a400_mask_irq(struct irq_data *d)
{
INTC_INTENC = (1 << d->irq);
}
static void lh7a400_unmask_irq(struct irq_data *d)
{
INTC_INTENS = (1 << d->irq);
}
static void lh7a400_ack_gpio_irq(struct irq_data *d)
{
GPIO_GPIOFEOI = (1 << IRQ_TO_GPIO (d->irq));
INTC_INTENC = (1 << d->irq);
}
static struct irq_chip lh7a400_internal_chip = {
.name = "MPU",
.irq_ack = lh7a400_mask_irq, /* Level triggering -> mask is ack */
.irq_mask = lh7a400_mask_irq,
.irq_unmask = lh7a400_unmask_irq,
};
static struct irq_chip lh7a400_gpio_chip = {
.name = "GPIO",
.irq_ack = lh7a400_ack_gpio_irq,
.irq_mask = lh7a400_mask_irq,
.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, handle_level_irq); /* OK default */
break;
default:
set_irq_chip (irq, &lh7a400_internal_chip);
set_irq_handler (irq, handle_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 <mach/hardware.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <mach/irqs.h>
#include "common.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, /* CPLD */
IRQ_DMAM2P4, IRQ_DMAM2P5, /* AC97 */
#endif
};
static unsigned char irq_pri_vic2[] = {
#if defined (USE_PRIORITIES)
IRQ_T3UI, /* Timer */
IRQ_GPIO7INTR, /* CPLD */
IRQ_UART1INTR, IRQ_UART2INTR, IRQ_UART3INTR,
IRQ_LCDINTR, /* LCD */
IRQ_TSCINTR, /* ADC/Touchscreen */
#endif
};
/* CPU IRQ handling */
static void lh7a404_vic1_mask_irq(struct irq_data *d)
{
VIC1_INTENCLR = (1 << d->irq);
}
static void lh7a404_vic1_unmask_irq(struct irq_data *d)
{
VIC1_INTEN = (1 << d->irq);
}
static void lh7a404_vic2_mask_irq(struct irq_data *d)
{
VIC2_INTENCLR = (1 << (d->irq - 32));
}
static void lh7a404_vic2_unmask_irq(struct irq_data *d)
{
VIC2_INTEN = (1 << (d->irq - 32));
}
static void lh7a404_vic1_ack_gpio_irq(struct irq_data *d)
{
GPIO_GPIOFEOI = (1 << IRQ_TO_GPIO (d->irq));
VIC1_INTENCLR = (1 << d->irq);
}
static void lh7a404_vic2_ack_gpio_irq(struct irq_data *d)
{
GPIO_GPIOFEOI = (1 << IRQ_TO_GPIO (d->irq));
VIC2_INTENCLR = (1 << d->irq);
}
static struct irq_chip lh7a404_vic1_chip = {
.name = "VIC1",
.irq_ack = lh7a404_vic1_mask_irq, /* Because level-triggered */
.irq_mask = lh7a404_vic1_mask_irq,
.irq_unmask = lh7a404_vic1_unmask_irq,
};
static struct irq_chip lh7a404_vic2_chip = {
.name = "VIC2",
.irq_ack = lh7a404_vic2_mask_irq, /* Because level-triggered */
.irq_mask = lh7a404_vic2_mask_irq,
.irq_unmask = lh7a404_vic2_unmask_irq,
};
static struct irq_chip lh7a404_gpio_vic1_chip = {
.name = "GPIO-VIC1",
.irq_ack = lh7a404_vic1_ack_gpio_irq,
.irq_mask = lh7a404_vic1_mask_irq,
.irq_unmask = lh7a404_vic1_unmask_irq,
};
static struct irq_chip lh7a404_gpio_vic2_chip = {
.name = "GPIO-VIC2",
.irq_ack = lh7a404_vic2_ack_gpio_irq,
.irq_mask = lh7a404_vic2_mask_irq,
.irq_unmask = lh7a404_vic2_unmask_irq,
};
/* IRQ initialization */
#if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
extern void* branch_irq_lh7a400;
#endif
void __init lh7a404_init_irq (void)
{
int irq;
#if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
#define NOP 0xe1a00000 /* mov r0, r0 */
branch_irq_lh7a400 = NOP;
#endif
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, handle_level_irq); /* OK default */
break;
default:
set_irq_chip (irq, irq < 32
? &lh7a404_vic1_chip
: &lh7a404_vic2_chip);
set_irq_handler (irq, handle_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 <mach/hardware.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <mach/irqs.h>
#include "common.h"
static void lh7a40x_ack_cpld_irq(struct irq_data *d)
{
/* CPLD doesn't have ack capability */
}
static void lh7a40x_mask_cpld_irq(struct irq_data *d)
{
switch (d->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(struct irq_data *d)
{
switch (d->irq) {
case IRQ_LPD7A40X_ETH_INT:
CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x4;
break;
case IRQ_LPD7A400_TS:
CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x8;
break;
}
}
static struct irq_chip lh7a40x_cpld_chip = {
.name = "CPLD",
.irq_ack = lh7a40x_ack_cpld_irq,
.irq_mask = lh7a40x_mask_cpld_irq,
.irq_unmask = lh7a40x_unmask_cpld_irq,
};
static void lh7a40x_cpld_handler (unsigned int irq, struct irq_desc *desc)
{
unsigned int mask = CPLD_INTERRUPTS;
desc->irq_data.chip->ack (irq);
if ((mask & 0x1) == 0) /* WLAN */
generic_handle_irq(IRQ_LPD7A40X_ETH_INT);
if ((mask & 0x2) == 0) /* Touch */
generic_handle_irq(IRQ_LPD7A400_TS);
desc->irq_data.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, handle_edge_irq);
set_irq_flags (irq, IRQF_VALID);
}
set_irq_chained_handler ((cpld_version == 0x28)
? IRQ_CPLD_V28
: IRQ_CPLD_V34,
lh7a40x_cpld_handler);
}
/* lcd-panel.h
written by Marc Singer
18 Jul 2005
Copyright (C) 2005 Marc Singer
-----------
DESCRIPTION
-----------
Only one panel may be defined at a time.
The pixel clock is calculated to be no greater than the target.
Each timing value is accompanied by a specification comment.
UNITS/MIN/TYP/MAX
Most of the units will be in clocks.
USE_RGB555
Define this macro to configure the AMBA LCD controller to use an
RGB555 encoding for the pels instead of the normal RGB565.
LPD9520, LPD79524, LPD7A400, LPD7A404-10, LPD7A404-11
These boards are best approximated by 555 for all panels. Some
can use an extra low-order bit of blue in bit 16 of the color
value, but we don't have a way to communicate this non-linear
mapping to the kernel.
*/
#if !defined (__LCD_PANEL_H__)
# define __LCD_PANEL_H__
#if defined (MACH_LPD79520)\
|| defined (MACH_LPD79524)\
|| defined (MACH_LPD7A400)\
|| defined (MACH_LPD7A404)
# define USE_RGB555
#endif
struct clcd_panel_extra {
unsigned int hrmode;
unsigned int clsen;
unsigned int spsen;
unsigned int pcdel;
unsigned int revdel;
unsigned int lpdel;
unsigned int spldel;
unsigned int pc2del;
};
#define NS_TO_CLOCK(ns,c) ((((ns)*((c)/1000) + (1000000 - 1))/1000000))
#define CLOCK_TO_DIV(e,c) (((c) + (e) - 1)/(e))
#if defined CONFIG_FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT
/* Logic Product Development LCD 3.5" QVGA HRTFT -10 */
/* Sharp PN LQ035Q7DB02 w/HRTFT controller chip */
#define PIX_CLOCK_TARGET (6800000)
#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER)
static struct clcd_panel lcd_panel = {
.mode = {
.name = "3.5in QVGA (LQ035Q7DB02)",
.xres = 240,
.yres = 320,
.pixclock = PIX_CLOCK,
.left_margin = 16,
.right_margin = 21,
.upper_margin = 8, // line/8/8/8
.lower_margin = 5,
.hsync_len = 61,
.vsync_len = NS_TO_CLOCK (60, PIX_CLOCK),
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_IPC | (PIX_CLOCK_DIVIDER - 2),
.cntl = CNTL_LCDTFT | CNTL_WATERMARK,
.bpp = 16,
};
#define HAS_LCD_PANEL_EXTRA
static struct clcd_panel_extra lcd_panel_extra = {
.hrmode = 1,
.clsen = 1,
.spsen = 1,
.pcdel = 8,
.revdel = 7,
.lpdel = 13,
.spldel = 77,
.pc2del = 208,
};
#endif
#if defined CONFIG_FB_ARMCLCD_SHARP_LQ057Q3DC02
/* Logic Product Development LCD 5.7" QVGA -10 */
/* Sharp PN LQ057Q3DC02 */
/* QVGA mode, V/Q=LOW */
/* From Sharp on 2006.1.3. I believe some of the values are incorrect
* based on the datasheet.
Timing0 TIMING1 TIMING2 CONTROL
0x140A0C4C 0x080504EF 0x013F380D 0x00000829
HBP= 20 VBP= 8 BCD= 0
HFP= 10 VFP= 5 CPL=319
HSW= 12 VSW= 1 IOE= 0
PPL= 19 LPP=239 IPC= 1
IHS= 1
IVS= 1
ACB= 0
CSEL= 0
PCD= 13
*/
/* The full horizontal cycle (Th) is clock/360/400/450. */
/* The full vertical cycle (Tv) is line/251/262/280. */
#define PIX_CLOCK_TARGET (6300000) /* -/6.3/7 MHz */
#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER)
static struct clcd_panel lcd_panel = {
.mode = {
.name = "5.7in QVGA (LQ057Q3DC02)",
.xres = 320,
.yres = 240,
.pixclock = PIX_CLOCK,
.left_margin = 11,
.right_margin = 400-11-320-2,
.upper_margin = 7, // line/7/7/7
.lower_margin = 262-7-240-2,
.hsync_len = 2, // clk/2/96/200
.vsync_len = 2, // line/2/-/34
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_IHS | TIM2_IVS
| (PIX_CLOCK_DIVIDER - 2),
.cntl = CNTL_LCDTFT | CNTL_WATERMARK,
.bpp = 16,
};
#endif
#if defined CONFIG_FB_ARMCLCD_SHARP_LQ64D343
/* Logic Product Development LCD 6.4" VGA -10 */
/* Sharp PN LQ64D343 */
/* The full horizontal cycle (Th) is clock/750/800/900. */
/* The full vertical cycle (Tv) is line/515/525/560. */
#define PIX_CLOCK_TARGET (28330000)
#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER)
static struct clcd_panel lcd_panel = {
.mode = {
.name = "6.4in QVGA (LQ64D343)",
.xres = 640,
.yres = 480,
.pixclock = PIX_CLOCK,
.left_margin = 32,
.right_margin = 800-32-640-96,
.upper_margin = 32, // line/34/34/34
.lower_margin = 540-32-480-2,
.hsync_len = 96, // clk/2/96/200
.vsync_len = 2, // line/2/-/34
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_IHS | TIM2_IVS
| (PIX_CLOCK_DIVIDER - 2),
.cntl = CNTL_LCDTFT | CNTL_WATERMARK,
.bpp = 16,
};
#endif
#if defined CONFIG_FB_ARMCLCD_SHARP_LQ10D368
/* Logic Product Development LCD 10.4" VGA -10 */
/* Sharp PN LQ10D368 */
#define PIX_CLOCK_TARGET (28330000)
#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER)
static struct clcd_panel lcd_panel = {
.mode = {
.name = "10.4in VGA (LQ10D368)",
.xres = 640,
.yres = 480,
.pixclock = PIX_CLOCK,
.left_margin = 21,
.right_margin = 15,
.upper_margin = 34,
.lower_margin = 5,
.hsync_len = 96,
.vsync_len = 16,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_IHS | TIM2_IVS
| (PIX_CLOCK_DIVIDER - 2),
.cntl = CNTL_LCDTFT | CNTL_WATERMARK,
.bpp = 16,
};
#endif
#if defined CONFIG_FB_ARMCLCD_SHARP_LQ121S1DG41
/* Logic Product Development LCD 12.1" SVGA -10 */
/* Sharp PN LQ121S1DG41, was LQ121S1DG31 */
/* Note that with a 99993900 Hz HCLK, it is not possible to hit the
* target clock frequency range of 35MHz to 42MHz. */
/* If the target pixel clock is substantially lower than the panel
* spec, this is done to prevent the LCD display from glitching when
* the CPU is under load. A pixel clock higher than 25MHz
* (empirically determined) will compete with the CPU for bus cycles
* for the Ethernet chip. However, even a pixel clock of 10MHz
* competes with Compact Flash interface during some operations
* (fdisk, e2fsck). And, at that speed the display may have a visible
* flicker. */
/* The full horizontal cycle (Th) is clock/832/1056/1395. */
#define PIX_CLOCK_TARGET (20000000)
#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER)
static struct clcd_panel lcd_panel = {
.mode = {
.name = "12.1in SVGA (LQ121S1DG41)",
.xres = 800,
.yres = 600,
.pixclock = PIX_CLOCK,
.left_margin = 89, // ns/5/-/(1/PIX_CLOCK)-10
.right_margin = 1056-800-89-128,
.upper_margin = 23, // line/23/23/23
.lower_margin = 44,
.hsync_len = 128, // clk/2/128/200
.vsync_len = 4, // line/2/4/6
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_IHS | TIM2_IVS
| (PIX_CLOCK_DIVIDER - 2),
.cntl = CNTL_LCDTFT | CNTL_WATERMARK,
.bpp = 16,
};
#endif
#if defined CONFIG_FB_ARMCLCD_HITACHI
/* Hitachi*/
/* Submitted by Michele Da Rold <michele.darold@ecsproject.com> */
#define PIX_CLOCK_TARGET (49000000)
#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER)
static struct clcd_panel lcd_panel = {
.mode = {
.name = "Hitachi 800x480",
.xres = 800,
.yres = 480,
.pixclock = PIX_CLOCK,
.left_margin = 88,
.right_margin = 40,
.upper_margin = 32,
.lower_margin = 11,
.hsync_len = 128,
.vsync_len = 2,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_IPC | TIM2_IHS | TIM2_IVS
| (PIX_CLOCK_DIVIDER - 2),
.cntl = CNTL_LCDTFT | CNTL_WATERMARK,
.bpp = 16,
};
#endif
#if defined CONFIG_FB_ARMCLCD_AUO_A070VW01_WIDE
/* AU Optotronics A070VW01 7.0 Wide Screen color Display*/
/* Submitted by Michele Da Rold <michele.darold@ecsproject.com> */
#define PIX_CLOCK_TARGET (10000000)
#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER)
static struct clcd_panel lcd_panel = {
.mode = {
.name = "7.0in Wide (A070VW01)",
.xres = 480,
.yres = 234,
.pixclock = PIX_CLOCK,
.left_margin = 30,
.right_margin = 25,
.upper_margin = 14,
.lower_margin = 12,
.hsync_len = 100,
.vsync_len = 1,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_IPC | TIM2_IHS | TIM2_IVS
| (PIX_CLOCK_DIVIDER - 2),
.cntl = CNTL_LCDTFT | CNTL_WATERMARK,
.bpp = 16,
};
#endif
#undef NS_TO_CLOCK
#undef CLOCK_TO_DIV
#endif /* __LCD_PANEL_H__ */
/* arch/arm/mach-lh7a40x/ssp-cpld.c
*
* Copyright (C) 2004,2005 Marc Singer
*
* 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.
*
* SSP/SPI driver for the CardEngine CPLD.
*
*/
/* NOTES
-----
o *** This driver is cribbed from the 7952x implementation.
Some comments may not apply.
o This driver contains sufficient logic to control either the
serial EEPROMs or the audio codec. It is included in the kernel
to support the codec. The EEPROMs are really the responsibility
of the boot loader and should probably be left alone.
o The code must be augmented to cope with multiple, simultaneous
clients.
o The audio codec writes to the codec chip whenever playback
starts.
o The touchscreen driver writes to the ads chip every time it
samples.
o The audio codec must write 16 bits, but the touch chip writes
are 8 bits long.
o We need to be able to keep these configurations separate while
simultaneously active.
*/
#include <linux/module.h>
#include <linux/kernel.h>
//#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
//#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <asm/irq.h>
#include <mach/hardware.h>
#include <mach/ssp.h>
//#define TALK
#if defined (TALK)
#define PRINTK(f...) printk (f)
#else
#define PRINTK(f...) do {} while (0)
#endif
#if defined (CONFIG_ARCH_LH7A400)
# define CPLD_SPID __REGP16(CPLD06_VIRT) /* SPI data */
# define CPLD_SPIC __REGP16(CPLD08_VIRT) /* SPI control */
# define CPLD_SPIC_CS_CODEC (1<<0)
# define CPLD_SPIC_CS_TOUCH (1<<1)
# define CPLD_SPIC_WRITE (0<<2)
# define CPLD_SPIC_READ (1<<2)
# define CPLD_SPIC_DONE (1<<3) /* r/o */
# define CPLD_SPIC_LOAD (1<<4)
# define CPLD_SPIC_START (1<<4)
# define CPLD_SPIC_LOADED (1<<5) /* r/o */
#endif
#define CPLD_SPI __REGP16(CPLD0A_VIRT) /* SPI operation */
#define CPLD_SPI_CS_EEPROM (1<<3)
#define CPLD_SPI_SCLK (1<<2)
#define CPLD_SPI_TX_SHIFT (1)
#define CPLD_SPI_TX (1<<CPLD_SPI_TX_SHIFT)
#define CPLD_SPI_RX_SHIFT (0)
#define CPLD_SPI_RX (1<<CPLD_SPI_RX_SHIFT)
/* *** FIXME: these timing values are substantially larger than the
*** chip requires. We may implement an nsleep () function. */
#define T_SKH 1 /* Clock time high (us) */
#define T_SKL 1 /* Clock time low (us) */
#define T_CS 1 /* Minimum chip select low time (us) */
#define T_CSS 1 /* Minimum chip select setup time (us) */
#define T_DIS 1 /* Data setup time (us) */
/* EEPROM SPI bits */
#define P_START (1<<9)
#define P_WRITE (1<<7)
#define P_READ (2<<7)
#define P_ERASE (3<<7)
#define P_EWDS (0<<7)
#define P_WRAL (0<<7)
#define P_ERAL (0<<7)
#define P_EWEN (0<<7)
#define P_A_EWDS (0<<5)
#define P_A_WRAL (1<<5)
#define P_A_ERAL (2<<5)
#define P_A_EWEN (3<<5)
struct ssp_configuration {
int device;
int mode;
int speed;
int frame_size_write;
int frame_size_read;
};
static struct ssp_configuration ssp_configuration;
static spinlock_t ssp_lock;
static void enable_cs (void)
{
switch (ssp_configuration.device) {
case DEVICE_EEPROM:
CPLD_SPI |= CPLD_SPI_CS_EEPROM;
break;
}
udelay (T_CSS);
}
static void disable_cs (void)
{
switch (ssp_configuration.device) {
case DEVICE_EEPROM:
CPLD_SPI &= ~CPLD_SPI_CS_EEPROM;
break;
}
udelay (T_CS);
}
static void pulse_clock (void)
{
CPLD_SPI |= CPLD_SPI_SCLK;
udelay (T_SKH);
CPLD_SPI &= ~CPLD_SPI_SCLK;
udelay (T_SKL);
}
/* execute_spi_command
sends an spi command to a device. It first sends cwrite bits from
v. If cread is greater than zero it will read cread bits
(discarding the leading 0 bit) and return them. If cread is less
than zero it will check for completetion status and return 0 on
success or -1 on timeout. If cread is zero it does nothing other
than sending the command.
On the LPD7A400, we can only read or write multiples of 8 bits on
the codec and the touch screen device. Here, we round up.
*/
static int execute_spi_command (int v, int cwrite, int cread)
{
unsigned long l = 0;
#if defined (CONFIG_MACH_LPD7A400)
/* The codec and touch devices cannot be bit-banged. Instead,
* the CPLD provides an eight-bit shift register and a crude
* interface. */
if ( ssp_configuration.device == DEVICE_CODEC
|| ssp_configuration.device == DEVICE_TOUCH) {
int select = 0;
PRINTK ("spi(%d %d.%d) 0x%04x",
ssp_configuration.device, cwrite, cread,
v);
#if defined (TALK)
if (ssp_configuration.device == DEVICE_CODEC)
PRINTK (" 0x%03x -> %2d", v & 0x1ff, (v >> 9) & 0x7f);
#endif
PRINTK ("\n");
if (ssp_configuration.device == DEVICE_CODEC)
select = CPLD_SPIC_CS_CODEC;
if (ssp_configuration.device == DEVICE_TOUCH)
select = CPLD_SPIC_CS_TOUCH;
if (cwrite) {
for (cwrite = (cwrite + 7)/8; cwrite-- > 0; ) {
CPLD_SPID = (v >> (8*cwrite)) & 0xff;
CPLD_SPIC = select | CPLD_SPIC_LOAD;
while (!(CPLD_SPIC & CPLD_SPIC_LOADED))
;
CPLD_SPIC = select;
while (!(CPLD_SPIC & CPLD_SPIC_DONE))
;
}
v = 0;
}
if (cread) {
mdelay (2); /* *** FIXME: required by ads7843? */
v = 0;
for (cread = (cread + 7)/8; cread-- > 0;) {
CPLD_SPID = 0;
CPLD_SPIC = select | CPLD_SPIC_READ
| CPLD_SPIC_START;
while (!(CPLD_SPIC & CPLD_SPIC_LOADED))
;
CPLD_SPIC = select | CPLD_SPIC_READ;
while (!(CPLD_SPIC & CPLD_SPIC_DONE))
;
v = (v << 8) | CPLD_SPID;
}
}
return v;
}
#endif
PRINTK ("spi(%d) 0x%04x -> 0x%x\r\n", ssp_configuration.device,
v & 0x1ff, (v >> 9) & 0x7f);
enable_cs ();
v <<= CPLD_SPI_TX_SHIFT; /* Correction for position of SPI_TX bit */
while (cwrite--) {
CPLD_SPI
= (CPLD_SPI & ~CPLD_SPI_TX)
| ((v >> cwrite) & CPLD_SPI_TX);
udelay (T_DIS);
pulse_clock ();
}
if (cread < 0) {
int delay = 10;
disable_cs ();
udelay (1);
enable_cs ();
l = -1;
do {
if (CPLD_SPI & CPLD_SPI_RX) {
l = 0;
break;
}
} while (udelay (1), --delay);
}
else
/* We pulse the clock before the data to skip the leading zero. */
while (cread-- > 0) {
pulse_clock ();
l = (l<<1)
| (((CPLD_SPI & CPLD_SPI_RX)
>> CPLD_SPI_RX_SHIFT) & 0x1);
}
disable_cs ();
return l;
}
static int ssp_init (void)
{
spin_lock_init (&ssp_lock);
memset (&ssp_configuration, 0, sizeof (ssp_configuration));
return 0;
}
/* ssp_chip_select
drops the chip select line for the CPLD shift-register controlled
devices. It doesn't enable chip
*/
static void ssp_chip_select (int enable)
{
#if defined (CONFIG_MACH_LPD7A400)
int select;
if (ssp_configuration.device == DEVICE_CODEC)
select = CPLD_SPIC_CS_CODEC;
else if (ssp_configuration.device == DEVICE_TOUCH)
select = CPLD_SPIC_CS_TOUCH;
else
return;
if (enable)
CPLD_SPIC = select;
else
CPLD_SPIC = 0;
#endif
}
static void ssp_acquire (void)
{
spin_lock (&ssp_lock);
}
static void ssp_release (void)
{
ssp_chip_select (0); /* just in case */
spin_unlock (&ssp_lock);
}
static int ssp_configure (int device, int mode, int speed,
int frame_size_write, int frame_size_read)
{
ssp_configuration.device = device;
ssp_configuration.mode = mode;
ssp_configuration.speed = speed;
ssp_configuration.frame_size_write = frame_size_write;
ssp_configuration.frame_size_read = frame_size_read;
return 0;
}
static int ssp_read (void)
{
return execute_spi_command (0, 0, ssp_configuration.frame_size_read);
}
static int ssp_write (u16 data)
{
execute_spi_command (data, ssp_configuration.frame_size_write, 0);
return 0;
}
static int ssp_write_read (u16 data)
{
return execute_spi_command (data, ssp_configuration.frame_size_write,
ssp_configuration.frame_size_read);
}
struct ssp_driver lh7a40x_cpld_ssp_driver = {
.init = ssp_init,
.acquire = ssp_acquire,
.release = ssp_release,
.configure = ssp_configure,
.chip_select = ssp_chip_select,
.read = ssp_read,
.write = ssp_write,
.write_read = ssp_write_read,
};
MODULE_AUTHOR("Marc Singer");
MODULE_DESCRIPTION("LPD7A40X CPLD SPI driver");
MODULE_LICENSE("GPL");
/*
* arch/arm/mach-lh7a40x/time.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/module.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/time.h>
#include <linux/io.h>
#include <mach/hardware.h>
#include <asm/irq.h>
#include <asm/leds.h>
#include <asm/mach/time.h>
#include "common.h"
#if HZ < 100
# define TIMER_CONTROL TIMER_CONTROL2
# define TIMER_LOAD TIMER_LOAD2
# define TIMER_CONSTANT (508469/HZ)
# define TIMER_MODE (TIMER_C_ENABLE | TIMER_C_PERIODIC | TIMER_C_508KHZ)
# define TIMER_EOI TIMER_EOI2
# define TIMER_IRQ IRQ_T2UI
#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)
{
TIMER_EOI = 0;
timer_tick();
return IRQ_HANDLED;
}
static struct irqaction lh7a40x_timer_irq = {
.name = "LHA740x Timer Tick",
.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
.handler = lh7a40x_timer_interrupt,
};
static void __init lh7a40x_timer_init (void)
{
/* Stop/disable all timers */
TIMER_CONTROL1 = 0;
TIMER_CONTROL2 = 0;
TIMER_CONTROL3 = 0;
setup_irq (TIMER_IRQ, &lh7a40x_timer_irq);
TIMER_LOAD = TIMER_CONSTANT;
TIMER_CONTROL = TIMER_MODE;
}
struct sys_timer lh7a40x_timer = {
.init = &lh7a40x_timer_init,
};
......@@ -206,68 +206,6 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#define RPC_LSA_DEFAULT RPC_LED_TX_RX
#define RPC_LSB_DEFAULT RPC_LED_100_10
#elif defined(CONFIG_MACH_LPD79520) || \
defined(CONFIG_MACH_LPD7A400) || \
defined(CONFIG_MACH_LPD7A404)
/* The LPD7X_IOBARRIER is necessary to overcome a mismatch between the
* way that the CPU handles chip selects and the way that the SMC chip
* expects the chip select to operate. Refer to
* Documentation/arm/Sharp-LH/IOBarrier for details. The read from
* IOBARRIER is a byte, in order that we read the least-common
* denominator. It would be wasteful to read 32 bits from an 8-bit
* accessible region.
*
* There is no explicit protection against interrupts intervening
* between the writew and the IOBARRIER. In SMC ISR there is a
* preamble that performs an IOBARRIER in the extremely unlikely event
* that the driver interrupts itself between a writew to the chip an
* the IOBARRIER that follows *and* the cache is large enough that the
* first off-chip access while handing the interrupt is to the SMC
* chip. Other devices in the same address space as the SMC chip must
* be aware of the potential for trouble and perform a similar
* IOBARRIER on entry to their ISR.
*/
#include <mach/constants.h> /* IOBARRIER_VIRT */
#define SMC_CAN_USE_8BIT 0
#define SMC_CAN_USE_16BIT 1
#define SMC_CAN_USE_32BIT 0
#define SMC_NOWAIT 0
#define LPD7X_IOBARRIER readb (IOBARRIER_VIRT)
#define SMC_inw(a,r)\
({ unsigned short v = readw ((void*) ((a) + (r))); LPD7X_IOBARRIER; v; })
#define SMC_outw(v,a,r) ({ writew ((v), (a) + (r)); LPD7X_IOBARRIER; })
#define SMC_insw LPD7_SMC_insw
static inline void LPD7_SMC_insw (unsigned char* a, int r,
unsigned char* p, int l)
{
unsigned short* ps = (unsigned short*) p;
while (l-- > 0) {
*ps++ = readw (a + r);
LPD7X_IOBARRIER;
}
}
#define SMC_outsw LPD7_SMC_outsw
static inline void LPD7_SMC_outsw (unsigned char* a, int r,
unsigned char* p, int l)
{
unsigned short* ps = (unsigned short*) p;
while (l-- > 0) {
writew (*ps++, a + r);
LPD7X_IOBARRIER;
}
}
#define SMC_INTERRUPT_PREAMBLE LPD7X_IOBARRIER
#define RPC_LSA_DEFAULT RPC_LED_TX_RX
#define RPC_LSB_DEFAULT RPC_LED_100_10
#elif defined(CONFIG_ARCH_VERSATILE)
#define SMC_CAN_USE_8BIT 1
......
此差异已折叠。
......@@ -54,7 +54,6 @@ obj-$(CONFIG_SERIAL_68328) += 68328serial.o
obj-$(CONFIG_SERIAL_68360) += 68360serial.o
obj-$(CONFIG_SERIAL_MCF) += mcf.o
obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o
obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o
obj-$(CONFIG_SERIAL_DZ) += dz.o
obj-$(CONFIG_SERIAL_ZS) += zs.o
obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o
......
此差异已折叠。
......@@ -31,7 +31,6 @@ config USB_ARCH_HAS_OHCI
# ARM:
default y if SA1111
default y if ARCH_OMAP
default y if ARCH_LH7A404
default y if ARCH_S3C2410
default y if PXA27x
default y if PXA3xx
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册