mirror of
https://github.com/joel16/android_kernel_sony_msm8994_rework.git
synced 2024-12-28 06:54:55 +00:00
Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (60 commits) [ARM] 4524/1: S3C: Move register out of include/asm-arm/arch-s3c2410 [ARM] 4523/1: S3C: Remove FIFO_MAX from uncompression headers [ARM] 4522/1: S3C: split include/asm-arm/arch/memory.h [ARM] 4521/2: S3C: Reorganise VA mapping headers [ARM] 4520/1: S3C: Remove old VA values from static map [ARM] 4519/1: S3C: split S3C2400 values out of S3C24XX map.h [ARM] 4518/1: S3C: Rename watchdog configuration options [ARM] 4517/1: S3C: Fix debug macros for ARM926 output [ARM] 4516/1: S3C: Fix uncompressor serial output for ARM926 [ARM] 4515/1: S3C: Move uncompress code to plat-s3c [ARM] 4514/1: S3C: Rename DEBUG_S3C2410_PORT and DEBUG_S3C_UART [ARM] 4513/1: S3C: Rename CONFIG_S3C2410_LOWLEVEL_UART_PORT [ARM] 4512/1: S3C: rename the debug macros for per-cpu updates [ARM] 4511/1: S3C: updated LLSERIAL Kconfig defines for CPU support [ARM] 4510/1: S3C: split debug-macro support into plat-s3c [ARM] 4509/1: S3C: Create initial arch/arm/plat-s3c [ARM] 4508/1: S3C: Move items to include/asm-arm/plat-s3c [ARM] 4461/1: MXC platform and i.MX31ADS core support [ARM] 4507/1: pxa2xx clock_event_device [ARM] 4497/1: Only allow safe cache configurations on ARMv6 and later ...
This commit is contained in:
commit
7578634990
@ -463,7 +463,7 @@ S: Maintained
|
||||
|
||||
ARM/HP JORNADA 7XX MACHINE SUPPORT
|
||||
P: Kristoffer Ericson
|
||||
M: kristoffer_e1@hotmail.com
|
||||
M: kristoffer.ericson@gmail.com
|
||||
W: www.jlime.com
|
||||
S: Maintained
|
||||
|
||||
|
@ -324,6 +324,12 @@ config ARCH_NS9XXX
|
||||
|
||||
<http://www.digi.com/products/microprocessors/index.jsp>
|
||||
|
||||
config ARCH_MXC
|
||||
bool "Freescale MXC/iMX-based"
|
||||
select ARCH_MTD_XIP
|
||||
help
|
||||
Support for Freescale MXC/iMX-based family of processors
|
||||
|
||||
config ARCH_PNX4008
|
||||
bool "Philips Nexperia PNX4008 Mobile"
|
||||
help
|
||||
@ -432,6 +438,7 @@ source "arch/arm/mach-omap1/Kconfig"
|
||||
source "arch/arm/mach-omap2/Kconfig"
|
||||
|
||||
source "arch/arm/plat-s3c24xx/Kconfig"
|
||||
source "arch/arm/plat-s3c/Kconfig"
|
||||
|
||||
if ARCH_S3C2410
|
||||
source "arch/arm/mach-s3c2400/Kconfig"
|
||||
@ -456,6 +463,8 @@ source "arch/arm/mach-realview/Kconfig"
|
||||
|
||||
source "arch/arm/mach-at91/Kconfig"
|
||||
|
||||
source "arch/arm/plat-mxc/Kconfig"
|
||||
|
||||
source "arch/arm/mach-netx/Kconfig"
|
||||
|
||||
source "arch/arm/mach-ns9xxx/Kconfig"
|
||||
|
@ -82,24 +82,24 @@ config DEBUG_CLPS711X_UART2
|
||||
output to the second serial port on these devices. Saying N will
|
||||
cause the debug messages to appear on the first serial port.
|
||||
|
||||
config DEBUG_S3C2410_PORT
|
||||
depends on DEBUG_LL && ARCH_S3C2410
|
||||
bool "Kernel low-level debugging messages via S3C2410 UART"
|
||||
config DEBUG_S3C_PORT
|
||||
depends on DEBUG_LL && PLAT_S3C
|
||||
bool "Kernel low-level debugging messages via S3C UART"
|
||||
help
|
||||
Say Y here if you want debug print routines to go to one of the
|
||||
S3C2410 internal UARTs. The chosen UART must have been configured
|
||||
S3C internal UARTs. The chosen UART must have been configured
|
||||
before it is used.
|
||||
|
||||
config DEBUG_S3C2410_UART
|
||||
depends on ARCH_S3C2410
|
||||
int "S3C2410 UART to use for low-level debug"
|
||||
config DEBUG_S3C_UART
|
||||
depends on PLAT_S3C
|
||||
int "S3C UART to use for low-level debug"
|
||||
default "0"
|
||||
help
|
||||
Choice for UART for kernel low-level using S3C2410 UARTS,
|
||||
Choice for UART for kernel low-level using S3C UARTS,
|
||||
should be between zero and two. The port must have been
|
||||
initialised by the boot-loader before use.
|
||||
|
||||
The uncompressor code port configuration is now handled
|
||||
by CONFIG_S3C2410_LOWLEVEL_UART_PORT.
|
||||
by CONFIG_S3C_LOWLEVEL_UART_PORT.
|
||||
|
||||
endmenu
|
||||
|
@ -137,6 +137,8 @@ endif
|
||||
textofs-$(CONFIG_ARCH_NS9XXX) := 0x00108000
|
||||
machine-$(CONFIG_ARCH_DAVINCI) := davinci
|
||||
machine-$(CONFIG_ARCH_KS8695) := ks8695
|
||||
incdir-$(CONFIG_ARCH_MXC) := mxc
|
||||
machine-$(CONFIG_ARCH_MX3) := mx3
|
||||
|
||||
ifeq ($(CONFIG_ARCH_EBSA110),y)
|
||||
# This is what happens if you forget the IOCS16 line.
|
||||
@ -183,6 +185,7 @@ core-$(CONFIG_VFP) += arch/arm/vfp/
|
||||
core-$(CONFIG_PLAT_IOP) += arch/arm/plat-iop/
|
||||
core-$(CONFIG_ARCH_OMAP) += arch/arm/plat-omap/
|
||||
core-$(CONFIG_PLAT_S3C24XX) += arch/arm/plat-s3c24xx/
|
||||
core-$(CONFIG_ARCH_MXC) += arch/arm/plat-mxc/
|
||||
|
||||
drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/
|
||||
drivers-$(CONFIG_ARCH_CLPS7500) += drivers/acorn/char/
|
||||
|
@ -91,4 +91,12 @@ zinstall: $(obj)/zImage
|
||||
$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
|
||||
$(obj)/zImage System.map "$(INSTALL_PATH)"
|
||||
|
||||
zi:
|
||||
$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
|
||||
$(obj)/zImage System.map "$(INSTALL_PATH)"
|
||||
|
||||
i:
|
||||
$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
|
||||
$(obj)/Image System.map "$(INSTALL_PATH)"
|
||||
|
||||
subdir- := bootp compressed
|
||||
|
@ -73,7 +73,7 @@ SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
|
||||
|
||||
targets := vmlinux vmlinux.lds piggy.gz piggy.o font.o font.c \
|
||||
head.o misc.o $(OBJS)
|
||||
EXTRA_CFLAGS := -fpic
|
||||
EXTRA_CFLAGS := -fpic -fno-builtin
|
||||
EXTRA_AFLAGS :=
|
||||
|
||||
# Supply ZRELADDR, INITRD_PHYS and PARAMS_PHYS to the decompressor via
|
||||
|
@ -55,7 +55,7 @@
|
||||
#elif defined(CONFIG_ARCH_S3C2410)
|
||||
.macro loadsp, rb
|
||||
mov \rb, #0x50000000
|
||||
add \rb, \rb, #0x4000 * CONFIG_S3C2410_LOWLEVEL_UART_PORT
|
||||
add \rb, \rb, #0x4000 * CONFIG_S3C_LOWLEVEL_UART_PORT
|
||||
.endm
|
||||
#else
|
||||
.macro loadsp, rb
|
||||
|
1265
arch/arm/configs/em_x270_defconfig
Normal file
1265
arch/arm/configs/em_x270_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
@ -138,11 +138,11 @@ CONFIG_ARCH_S3C2410=y
|
||||
CONFIG_PLAT_S3C24XX=y
|
||||
CONFIG_CPU_S3C244X=y
|
||||
CONFIG_PM_SIMTEC=y
|
||||
# CONFIG_S3C2410_BOOT_WATCHDOG is not set
|
||||
# CONFIG_S3C2410_BOOT_ERROR_RESET is not set
|
||||
# CONFIG_S3C_BOOT_WATCHDOG is not set
|
||||
# CONFIG_S3C_BOOT_ERROR_RESET is not set
|
||||
# CONFIG_S3C2410_PM_DEBUG is not set
|
||||
# CONFIG_S3C2410_PM_CHECK is not set
|
||||
CONFIG_S3C2410_LOWLEVEL_UART_PORT=0
|
||||
CONFIG_S3C_LOWLEVEL_UART_PORT=0
|
||||
CONFIG_S3C2410_DMA=y
|
||||
# CONFIG_S3C2410_DMA_DEBUG is not set
|
||||
CONFIG_MACH_SMDK=y
|
||||
@ -1392,8 +1392,8 @@ CONFIG_DEBUG_USER=y
|
||||
# CONFIG_DEBUG_ERRORS is not set
|
||||
CONFIG_DEBUG_LL=y
|
||||
# CONFIG_DEBUG_ICEDCC is not set
|
||||
CONFIG_DEBUG_S3C2410_PORT=y
|
||||
CONFIG_DEBUG_S3C2410_UART=0
|
||||
CONFIG_DEBUG_S3C_PORT=y
|
||||
CONFIG_DEBUG_S3C_UART=0
|
||||
|
||||
#
|
||||
# Security options
|
||||
|
@ -477,7 +477,7 @@ void __init at91_add_device_i2c(void) {}
|
||||
* SPI
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#if defined(CONFIG_SPI_AT91) || defined(CONFIG_SPI_AT91_MODULE) || defined(CONFIG_AT91_SPI) || defined(CONFIG_AT91_SPI_MODULE)
|
||||
#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
|
||||
static u64 spi_dmamask = 0xffffffffUL;
|
||||
|
||||
static struct resource spi_resources[] = {
|
||||
@ -494,7 +494,7 @@ static struct resource spi_resources[] = {
|
||||
};
|
||||
|
||||
static struct platform_device at91rm9200_spi_device = {
|
||||
.name = "at91_spi",
|
||||
.name = "atmel_spi",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &spi_dmamask,
|
||||
@ -522,18 +522,14 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
|
||||
else
|
||||
cs_pin = spi_standard_cs[devices[i].chip_select];
|
||||
|
||||
#ifdef CONFIG_SPI_AT91_MANUAL_CS
|
||||
/* enable chip-select pin */
|
||||
at91_set_gpio_output(cs_pin, 1);
|
||||
#else
|
||||
at91_set_A_periph(cs_pin, 0);
|
||||
#endif
|
||||
|
||||
/* pass chip-select pin to driver */
|
||||
devices[i].controller_data = (void *) cs_pin;
|
||||
}
|
||||
|
||||
spi_register_board_info(devices, nr_devices);
|
||||
at91_clock_associate("spi_clk", &at91rm9200_spi_device.dev, "spi");
|
||||
platform_device_register(&at91rm9200_spi_device);
|
||||
}
|
||||
#else
|
||||
|
@ -42,6 +42,13 @@ config IOP3XX_ATU
|
||||
Say N if the IOP is an add in card, the host system owns the PCI
|
||||
bus in this case.
|
||||
|
||||
config MACH_EM7210
|
||||
bool "Enable support for the Lanner EM7210"
|
||||
help
|
||||
Say Y here if you want to run your kernel on the Lanner EM7210
|
||||
board. Say also Y here if you have a SS4000e Baxter Creek NAS
|
||||
appliance."
|
||||
|
||||
endmenu
|
||||
|
||||
endif
|
||||
|
@ -11,3 +11,4 @@ obj-$(CONFIG_MACH_GLANTANK) += glantank.o
|
||||
obj-$(CONFIG_ARCH_IQ80321) += iq80321.o
|
||||
obj-$(CONFIG_ARCH_IQ31244) += iq31244.o
|
||||
obj-$(CONFIG_MACH_N2100) += n2100.o
|
||||
obj-$(CONFIG_MACH_EM7210) += em7210.o
|
||||
|
215
arch/arm/mach-iop32x/em7210.c
Normal file
215
arch/arm/mach-iop32x/em7210.c
Normal file
@ -0,0 +1,215 @@
|
||||
/*
|
||||
* arch/arm/mach-iop32x/em7210.c
|
||||
*
|
||||
* Board support code for the Lanner EM7210 platforms.
|
||||
*
|
||||
* Based on arch/arm/mach-iop32x/iq31244.c file.
|
||||
*
|
||||
* Copyright (C) 2007 Arnaud Patard <arnaud.patard@rtp-net.org>
|
||||
*
|
||||
* 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/mm.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/mtd/physmap.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/pci.h>
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/arch/time.h>
|
||||
|
||||
static void __init em7210_timer_init(void)
|
||||
{
|
||||
/* http://www.kwaak.net/fotos/fotos-nas/slide_24.html */
|
||||
/* 33.333 MHz crystal. */
|
||||
iop_init_time(200000000);
|
||||
}
|
||||
|
||||
static struct sys_timer em7210_timer = {
|
||||
.init = em7210_timer_init,
|
||||
.offset = iop_gettimeoffset,
|
||||
};
|
||||
|
||||
/*
|
||||
* EM7210 RTC
|
||||
*/
|
||||
static struct i2c_board_info __initdata em7210_i2c_devices[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("rtc-rs5c372", 0x32),
|
||||
.type = "rs5c372a",
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* EM7210 I/O
|
||||
*/
|
||||
static struct map_desc em7210_io_desc[] __initdata = {
|
||||
{ /* on-board devices */
|
||||
.virtual = IQ31244_UART,
|
||||
.pfn = __phys_to_pfn(IQ31244_UART),
|
||||
.length = 0x00100000,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
};
|
||||
|
||||
void __init em7210_map_io(void)
|
||||
{
|
||||
iop3xx_map_io();
|
||||
iotable_init(em7210_io_desc, ARRAY_SIZE(em7210_io_desc));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* EM7210 PCI
|
||||
*/
|
||||
#define INTA IRQ_IOP32X_XINT0
|
||||
#define INTB IRQ_IOP32X_XINT1
|
||||
#define INTC IRQ_IOP32X_XINT2
|
||||
#define INTD IRQ_IOP32X_XINT3
|
||||
|
||||
static int __init
|
||||
em7210_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
|
||||
{
|
||||
static int pci_irq_table[][4] = {
|
||||
/*
|
||||
* PCI IDSEL/INTPIN->INTLINE
|
||||
* A B C D
|
||||
*/
|
||||
{INTB, INTB, INTB, INTB}, /* console / uart */
|
||||
{INTA, INTA, INTA, INTA}, /* 1st 82541 */
|
||||
{INTD, INTD, INTD, INTD}, /* 2nd 82541 */
|
||||
{INTC, INTC, INTC, INTC}, /* GD31244 */
|
||||
{INTD, INTA, INTA, INTA}, /* mini-PCI */
|
||||
{INTD, INTC, INTA, INTA}, /* NEC USB */
|
||||
};
|
||||
|
||||
if (pin < 1 || pin > 4)
|
||||
return -1;
|
||||
|
||||
return pci_irq_table[slot % 6][pin - 1];
|
||||
}
|
||||
|
||||
static struct hw_pci em7210_pci __initdata = {
|
||||
.swizzle = pci_std_swizzle,
|
||||
.nr_controllers = 1,
|
||||
.setup = iop3xx_pci_setup,
|
||||
.preinit = iop3xx_pci_preinit,
|
||||
.scan = iop3xx_pci_scan_bus,
|
||||
.map_irq = em7210_pci_map_irq,
|
||||
};
|
||||
|
||||
static int __init em7210_pci_init(void)
|
||||
{
|
||||
if (machine_is_em7210())
|
||||
pci_common_init(&em7210_pci);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
subsys_initcall(em7210_pci_init);
|
||||
|
||||
|
||||
/*
|
||||
* EM7210 Flash
|
||||
*/
|
||||
static struct physmap_flash_data em7210_flash_data = {
|
||||
.width = 2,
|
||||
};
|
||||
|
||||
static struct resource em7210_flash_resource = {
|
||||
.start = 0xf0000000,
|
||||
.end = 0xf1ffffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
static struct platform_device em7210_flash_device = {
|
||||
.name = "physmap-flash",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &em7210_flash_data,
|
||||
},
|
||||
.num_resources = 1,
|
||||
.resource = &em7210_flash_resource,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* EM7210 UART
|
||||
* The physical address of the serial port is 0xfe800000,
|
||||
* so it can be used for physical and virtual address.
|
||||
*/
|
||||
static struct plat_serial8250_port em7210_serial_port[] = {
|
||||
{
|
||||
.mapbase = IQ31244_UART,
|
||||
.membase = (char *)IQ31244_UART,
|
||||
.irq = IRQ_IOP32X_XINT1,
|
||||
.flags = UPF_SKIP_TEST,
|
||||
.iotype = UPIO_MEM,
|
||||
.regshift = 0,
|
||||
.uartclk = 1843200,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct resource em7210_uart_resource = {
|
||||
.start = IQ31244_UART,
|
||||
.end = IQ31244_UART + 7,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
static struct platform_device em7210_serial_device = {
|
||||
.name = "serial8250",
|
||||
.id = PLAT8250_DEV_PLATFORM,
|
||||
.dev = {
|
||||
.platform_data = em7210_serial_port,
|
||||
},
|
||||
.num_resources = 1,
|
||||
.resource = &em7210_uart_resource,
|
||||
};
|
||||
|
||||
void em7210_power_off(void)
|
||||
{
|
||||
*IOP3XX_GPOE &= 0xfe;
|
||||
*IOP3XX_GPOD |= 0x01;
|
||||
}
|
||||
|
||||
static void __init em7210_init_machine(void)
|
||||
{
|
||||
platform_device_register(&em7210_serial_device);
|
||||
platform_device_register(&iop3xx_i2c0_device);
|
||||
platform_device_register(&iop3xx_i2c1_device);
|
||||
platform_device_register(&em7210_flash_device);
|
||||
platform_device_register(&iop3xx_dma_0_channel);
|
||||
platform_device_register(&iop3xx_dma_1_channel);
|
||||
|
||||
i2c_register_board_info(0, em7210_i2c_devices,
|
||||
ARRAY_SIZE(em7210_i2c_devices));
|
||||
|
||||
|
||||
pm_power_off = em7210_power_off;
|
||||
}
|
||||
|
||||
MACHINE_START(EM7210, "Lanner EM7210")
|
||||
.phys_io = IQ31244_UART,
|
||||
.io_pg_offst = ((IQ31244_UART) >> 18) & 0xfffc,
|
||||
.boot_params = 0xa0000100,
|
||||
.map_io = em7210_map_io,
|
||||
.init_irq = iop32x_init_irq,
|
||||
.timer = &em7210_timer,
|
||||
.init_machine = em7210_init_machine,
|
||||
MACHINE_END
|
@ -63,7 +63,8 @@ void __init iop32x_init_irq(void)
|
||||
if (machine_is_glantank() ||
|
||||
machine_is_iq80321() ||
|
||||
machine_is_iq31244() ||
|
||||
machine_is_n2100())
|
||||
machine_is_n2100() ||
|
||||
machine_is_em7210())
|
||||
*IOP3XX_PCIIRSR = 0x0f;
|
||||
|
||||
for (i = 0; i < NR_IRQS; i++) {
|
||||
|
@ -188,7 +188,7 @@ static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type)
|
||||
*int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
|
||||
|
||||
/* Configure the line as an input */
|
||||
gpio_line_config(line, IXP4XX_GPIO_IN);
|
||||
gpio_line_config(irq2gpio[irq], IXP4XX_GPIO_IN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/sysdev.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
|
12
arch/arm/mach-mx3/Kconfig
Normal file
12
arch/arm/mach-mx3/Kconfig
Normal file
@ -0,0 +1,12 @@
|
||||
menu "MX3 Options"
|
||||
depends on ARCH_MX3
|
||||
|
||||
config MACH_MX31ADS
|
||||
bool "Support MX31ADS platforms"
|
||||
default y
|
||||
help
|
||||
Include support for MX31ADS platform. This includes specific
|
||||
configurations for the board and its peripherals.
|
||||
|
||||
endmenu
|
||||
|
8
arch/arm/mach-mx3/Makefile
Normal file
8
arch/arm/mach-mx3/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
#
|
||||
# Makefile for the linux kernel.
|
||||
#
|
||||
|
||||
# Object file lists.
|
||||
|
||||
obj-y := mm.o time.o
|
||||
obj-$(CONFIG_MACH_MX31ADS) += mx31ads.o
|
3
arch/arm/mach-mx3/Makefile.boot
Normal file
3
arch/arm/mach-mx3/Makefile.boot
Normal file
@ -0,0 +1,3 @@
|
||||
zreladdr-y := 0x80008000
|
||||
params_phys-y := 0x80000100
|
||||
initrd_phys-y := 0x80800000
|
64
arch/arm/mach-mx3/mm.c
Normal file
64
arch/arm/mach-mx3/mm.c
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 1999,2000 Arm Limited
|
||||
* Copyright (C) 2000 Deep Blue Solutions Ltd
|
||||
* Copyright (C) 2002 Shane Nay (shane@minirl.com)
|
||||
* Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||
* - add MX31 specific definitions
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/mm.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/arch/common.h>
|
||||
|
||||
/*!
|
||||
* @file mm.c
|
||||
*
|
||||
* @brief This file creates static virtual to physical mappings, common to all MX3 boards.
|
||||
*
|
||||
* @ingroup Memory
|
||||
*/
|
||||
|
||||
/*!
|
||||
* This table defines static virtual address mappings for I/O regions.
|
||||
* These are the mappings common across all MX3 boards.
|
||||
*/
|
||||
static struct map_desc mxc_io_desc[] __initdata = {
|
||||
{
|
||||
.virtual = X_MEMC_BASE_ADDR_VIRT,
|
||||
.pfn = __phys_to_pfn(X_MEMC_BASE_ADDR),
|
||||
.length = X_MEMC_SIZE,
|
||||
.type = MT_DEVICE
|
||||
}, {
|
||||
.virtual = AVIC_BASE_ADDR_VIRT,
|
||||
.pfn = __phys_to_pfn(AVIC_BASE_ADDR),
|
||||
.length = AVIC_SIZE,
|
||||
.type = MT_NONSHARED_DEVICE
|
||||
},
|
||||
};
|
||||
|
||||
/*!
|
||||
* This function initializes the memory map. It is called during the
|
||||
* system startup to create static physical to virtual memory mappings
|
||||
* for the IO modules.
|
||||
*/
|
||||
void __init mxc_map_io(void)
|
||||
{
|
||||
iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
|
||||
}
|
142
arch/arm/mach-mx3/mx31ads.c
Normal file
142
arch/arm/mach-mx3/mx31ads.c
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (C) 2000 Deep Blue Solutions Ltd
|
||||
* Copyright (C) 2002 Shane Nay (shane@minirl.com)
|
||||
* Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/serial_8250.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/memory.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/arch/common.h>
|
||||
|
||||
/*!
|
||||
* @file mx31ads.c
|
||||
*
|
||||
* @brief This file contains the board-specific initialization routines.
|
||||
*
|
||||
* @ingroup System
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
|
||||
/*!
|
||||
* The serial port definition structure.
|
||||
*/
|
||||
static struct plat_serial8250_port serial_platform_data[] = {
|
||||
{
|
||||
.membase = (void *)(PBC_BASE_ADDRESS + PBC_SC16C652_UARTA),
|
||||
.mapbase = (unsigned long)(CS4_BASE_ADDR + PBC_SC16C652_UARTA),
|
||||
.irq = EXPIO_INT_XUART_INTA,
|
||||
.uartclk = 14745600,
|
||||
.regshift = 0,
|
||||
.iotype = UPIO_MEM,
|
||||
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ,
|
||||
}, {
|
||||
.membase = (void *)(PBC_BASE_ADDRESS + PBC_SC16C652_UARTB),
|
||||
.mapbase = (unsigned long)(CS4_BASE_ADDR + PBC_SC16C652_UARTB),
|
||||
.irq = EXPIO_INT_XUART_INTB,
|
||||
.uartclk = 14745600,
|
||||
.regshift = 0,
|
||||
.iotype = UPIO_MEM,
|
||||
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_device serial_device = {
|
||||
.name = "serial8250",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = serial_platform_data,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init mxc_init_extuart(void)
|
||||
{
|
||||
return platform_device_register(&serial_device);
|
||||
}
|
||||
#else
|
||||
static inline int mxc_init_extuart(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* This structure defines static mappings for the i.MX31ADS board.
|
||||
*/
|
||||
static struct map_desc mx31ads_io_desc[] __initdata = {
|
||||
{
|
||||
.virtual = AIPS1_BASE_ADDR_VIRT,
|
||||
.pfn = __phys_to_pfn(AIPS1_BASE_ADDR),
|
||||
.length = AIPS1_SIZE,
|
||||
.type = MT_NONSHARED_DEVICE
|
||||
}, {
|
||||
.virtual = SPBA0_BASE_ADDR_VIRT,
|
||||
.pfn = __phys_to_pfn(SPBA0_BASE_ADDR),
|
||||
.length = SPBA0_SIZE,
|
||||
.type = MT_NONSHARED_DEVICE
|
||||
}, {
|
||||
.virtual = AIPS2_BASE_ADDR_VIRT,
|
||||
.pfn = __phys_to_pfn(AIPS2_BASE_ADDR),
|
||||
.length = AIPS2_SIZE,
|
||||
.type = MT_NONSHARED_DEVICE
|
||||
}, {
|
||||
.virtual = CS4_BASE_ADDR_VIRT,
|
||||
.pfn = __phys_to_pfn(CS4_BASE_ADDR),
|
||||
.length = CS4_SIZE / 2,
|
||||
.type = MT_DEVICE
|
||||
},
|
||||
};
|
||||
|
||||
/*!
|
||||
* Set up static virtual mappings.
|
||||
*/
|
||||
void __init mx31ads_map_io(void)
|
||||
{
|
||||
mxc_map_io();
|
||||
iotable_init(mx31ads_io_desc, ARRAY_SIZE(mx31ads_io_desc));
|
||||
}
|
||||
|
||||
/*!
|
||||
* Board specific initialization.
|
||||
*/
|
||||
static void __init mxc_board_init(void)
|
||||
{
|
||||
mxc_init_extuart();
|
||||
}
|
||||
|
||||
/*
|
||||
* The following uses standard kernel macros defined in arch.h in order to
|
||||
* initialize __mach_desc_MX31ADS data structure.
|
||||
*/
|
||||
MACHINE_START(MX31ADS, "Freescale MX31ADS")
|
||||
/* Maintainer: Freescale Semiconductor, Inc. */
|
||||
.phys_io = AIPS1_BASE_ADDR,
|
||||
.io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
|
||||
.boot_params = PHYS_OFFSET + 0x100,
|
||||
.map_io = mx31ads_map_io,
|
||||
.init_irq = mxc_init_irq,
|
||||
.init_machine = mxc_board_init,
|
||||
.timer = &mxc_timer,
|
||||
MACHINE_END
|
152
arch/arm/mach-mx3/time.c
Normal file
152
arch/arm/mach-mx3/time.c
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* System Timer Interrupt reconfigured to run in free-run mode.
|
||||
* Author: Vitaly Wool
|
||||
* Copyright 2004 MontaVista Software Inc.
|
||||
* Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @file time.c
|
||||
* @brief This file contains OS tick and wdog timer implementations.
|
||||
*
|
||||
* This file contains OS tick and wdog timer implementations.
|
||||
*
|
||||
* @ingroup Timers
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/common.h>
|
||||
|
||||
/*!
|
||||
* This is the timer interrupt service routine to do required tasks.
|
||||
* It also services the WDOG timer at the frequency of twice per WDOG
|
||||
* timeout value. For example, if the WDOG's timeout value is 4 (2
|
||||
* seconds since the WDOG runs at 0.5Hz), it will be serviced once
|
||||
* every 2/2=1 second.
|
||||
*
|
||||
* @param irq GPT interrupt source number (not used)
|
||||
* @param dev_id this parameter is not used
|
||||
* @return always returns \b IRQ_HANDLED as defined in
|
||||
* include/linux/interrupt.h.
|
||||
*/
|
||||
static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
unsigned int next_match;
|
||||
|
||||
write_seqlock(&xtime_lock);
|
||||
|
||||
if (__raw_readl(MXC_GPT_GPTSR) & GPTSR_OF1) {
|
||||
do {
|
||||
timer_tick();
|
||||
next_match = __raw_readl(MXC_GPT_GPTOCR1) + LATCH;
|
||||
__raw_writel(GPTSR_OF1, MXC_GPT_GPTSR);
|
||||
__raw_writel(next_match, MXC_GPT_GPTOCR1);
|
||||
} while ((signed long)(next_match -
|
||||
__raw_readl(MXC_GPT_GPTCNT)) <= 0);
|
||||
}
|
||||
|
||||
write_sequnlock(&xtime_lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*!
|
||||
* This function is used to obtain the number of microseconds since the last
|
||||
* timer interrupt. Note that interrupts is disabled by do_gettimeofday().
|
||||
*
|
||||
* @return the number of microseconds since the last timer interrupt.
|
||||
*/
|
||||
static unsigned long mxc_gettimeoffset(void)
|
||||
{
|
||||
unsigned long ticks_to_match, elapsed, usec, tick_usec, i;
|
||||
|
||||
/* Get ticks before next timer match */
|
||||
ticks_to_match =
|
||||
__raw_readl(MXC_GPT_GPTOCR1) - __raw_readl(MXC_GPT_GPTCNT);
|
||||
|
||||
/* We need elapsed ticks since last match */
|
||||
elapsed = LATCH - ticks_to_match;
|
||||
|
||||
/* Now convert them to usec */
|
||||
/* Insure no overflow when calculating the usec below */
|
||||
for (i = 1, tick_usec = tick_nsec / 1000;; i *= 2) {
|
||||
tick_usec /= i;
|
||||
if ((0xFFFFFFFF / tick_usec) > elapsed)
|
||||
break;
|
||||
}
|
||||
usec = (unsigned long)(elapsed * tick_usec) / (LATCH / i);
|
||||
|
||||
return usec;
|
||||
}
|
||||
|
||||
/*!
|
||||
* The OS tick timer interrupt structure.
|
||||
*/
|
||||
static struct irqaction timer_irq = {
|
||||
.name = "MXC Timer Tick",
|
||||
.flags = IRQF_DISABLED | IRQF_TIMER,
|
||||
.handler = mxc_timer_interrupt
|
||||
};
|
||||
|
||||
/*!
|
||||
* This function is used to initialize the GPT to produce an interrupt
|
||||
* based on HZ. It is called by start_kernel() during system startup.
|
||||
*/
|
||||
void __init mxc_init_time(void)
|
||||
{
|
||||
u32 reg, v;
|
||||
reg = __raw_readl(MXC_GPT_GPTCR);
|
||||
reg &= ~GPTCR_ENABLE;
|
||||
__raw_writel(reg, MXC_GPT_GPTCR);
|
||||
reg |= GPTCR_SWR;
|
||||
__raw_writel(reg, MXC_GPT_GPTCR);
|
||||
|
||||
while ((__raw_readl(MXC_GPT_GPTCR) & GPTCR_SWR) != 0)
|
||||
cpu_relax();
|
||||
|
||||
reg = GPTCR_FRR | GPTCR_CLKSRC_HIGHFREQ;
|
||||
__raw_writel(reg, MXC_GPT_GPTCR);
|
||||
|
||||
/* TODO: get timer rate from clk driver */
|
||||
v = 66500000;
|
||||
|
||||
__raw_writel((v / CLOCK_TICK_RATE) - 1, MXC_GPT_GPTPR);
|
||||
|
||||
if ((v % CLOCK_TICK_RATE) != 0) {
|
||||
pr_info("\nWARNING: Can't generate CLOCK_TICK_RATE at %d Hz\n",
|
||||
CLOCK_TICK_RATE);
|
||||
}
|
||||
pr_info("Actual CLOCK_TICK_RATE is %d Hz\n",
|
||||
v / ((__raw_readl(MXC_GPT_GPTPR) & 0xFFF) + 1));
|
||||
|
||||
reg = __raw_readl(MXC_GPT_GPTCNT);
|
||||
reg += LATCH;
|
||||
__raw_writel(reg, MXC_GPT_GPTOCR1);
|
||||
|
||||
setup_irq(MXC_INT_GPT, &timer_irq);
|
||||
|
||||
reg = __raw_readl(MXC_GPT_GPTCR);
|
||||
reg =
|
||||
GPTCR_FRR | GPTCR_CLKSRC_HIGHFREQ | GPTCR_STOPEN | GPTCR_DOZEN |
|
||||
GPTCR_WAITEN | GPTCR_ENMOD | GPTCR_ENABLE;
|
||||
__raw_writel(reg, MXC_GPT_GPTCR);
|
||||
|
||||
__raw_writel(GPTIR_OF1IE, MXC_GPT_GPTIR);
|
||||
}
|
||||
|
||||
struct sys_timer mxc_timer = {
|
||||
.init = mxc_init_time,
|
||||
.offset = mxc_gettimeoffset,
|
||||
};
|
@ -1,6 +1,7 @@
|
||||
obj-y := irq.o time.o generic.o
|
||||
|
||||
obj-$(CONFIG_MACH_CC9P9360DEV) += mach-cc9p9360dev.o
|
||||
obj-$(CONFIG_MACH_CC9P9360JS) += mach-cc9p9360js.o
|
||||
|
||||
obj-$(CONFIG_BOARD_A9M9750DEV) += board-a9m9750dev.o
|
||||
obj-$(CONFIG_BOARD_JSCC9P9360) += board-jscc9p9360.o
|
||||
|
@ -77,7 +77,7 @@ static void a9m9750dev_fpga_demux_handler(unsigned int irq,
|
||||
|
||||
desc = irq_desc + FPGA_IRQ(irqno);
|
||||
|
||||
desc_handle_irq(irqno, desc);
|
||||
desc_handle_irq(FPGA_IRQ(irqno), desc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,7 +91,7 @@ void __init board_a9m9750dev_init_irq(void)
|
||||
* use GPIO 11, because GPIO 32 is used for the LCD
|
||||
*/
|
||||
/* XXX: proper GPIO handling */
|
||||
BBU_GC(2) &= ~0x2000;
|
||||
BBU_GCONFb1(1) &= ~0x2000;
|
||||
|
||||
for (i = FPGA_IRQ(0); i <= FPGA_IRQ(7); ++i) {
|
||||
set_irq_chip(i, &a9m9750dev_fpga_chip);
|
||||
@ -178,7 +178,7 @@ void __init board_a9m9750dev_init_machine(void)
|
||||
|
||||
/* setup static CS0: memory configuration */
|
||||
reg = MEM_SMC(0);
|
||||
REGSET(reg, MEM_SMC, WSMC, OFF);
|
||||
REGSET(reg, MEM_SMC, PSMC, OFF);
|
||||
REGSET(reg, MEM_SMC, BSMC, OFF);
|
||||
REGSET(reg, MEM_SMC, EW, OFF);
|
||||
REGSET(reg, MEM_SMC, PB, 1);
|
||||
@ -196,4 +196,3 @@ void __init board_a9m9750dev_init_machine(void)
|
||||
platform_add_devices(board_a9m9750dev_devices,
|
||||
ARRAY_SIZE(board_a9m9750dev_devices));
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include <asm/arch-ns9xxx/regs-mem.h>
|
||||
#include <asm/arch-ns9xxx/board.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
static struct map_desc standard_io_desc[] __initdata = {
|
||||
{ /* BBus */
|
||||
.virtual = io_p2v(0x90000000),
|
||||
|
@ -21,6 +21,15 @@ static void ns9xxx_ack_irq_timer(unsigned int irq)
|
||||
{
|
||||
u32 tc = SYS_TC(irq - IRQ_TIMER0);
|
||||
|
||||
/*
|
||||
* If the timer is programmed to halt on terminal count, the
|
||||
* timer must be disabled before clearing the interrupt.
|
||||
*/
|
||||
if (REGGET(tc, SYS_TCx, REN) == 0) {
|
||||
REGSET(tc, SYS_TCx, TEN, DIS);
|
||||
SYS_TC(irq - IRQ_TIMER0) = tc;
|
||||
}
|
||||
|
||||
REGSET(tc, SYS_TCx, INTC, SET);
|
||||
SYS_TC(irq - IRQ_TIMER0) = tc;
|
||||
|
||||
@ -28,7 +37,7 @@ static void ns9xxx_ack_irq_timer(unsigned int irq)
|
||||
SYS_TC(irq - IRQ_TIMER0) = tc;
|
||||
}
|
||||
|
||||
void (*ns9xxx_ack_irq_functions[NR_IRQS])(unsigned int) = {
|
||||
static void (*ns9xxx_ack_irq_functions[NR_IRQS])(unsigned int) = {
|
||||
[IRQ_TIMER0] = ns9xxx_ack_irq_timer,
|
||||
[IRQ_TIMER1] = ns9xxx_ack_irq_timer,
|
||||
[IRQ_TIMER2] = ns9xxx_ack_irq_timer,
|
||||
|
@ -20,7 +20,7 @@ static void __init mach_cc9p9360js_init_machine(void)
|
||||
board_jscc9p9360_init_machine();
|
||||
}
|
||||
|
||||
MACHINE_START(CC9P9360DEV, "Digi ConnectCore 9P 9360 on an JSCC9P9360 Devboard")
|
||||
MACHINE_START(CC9P9360JS, "Digi ConnectCore 9P 9360 on an JSCC9P9360 Devboard")
|
||||
.map_io = ns9xxx_map_io,
|
||||
.init_irq = ns9xxx_init_irq,
|
||||
.init_machine = mach_cc9p9360js_init_machine,
|
||||
|
@ -37,6 +37,10 @@ config MACH_TRIZEPS4
|
||||
bool "Keith und Koep Trizeps4 DIMM-Module"
|
||||
select PXA27x
|
||||
|
||||
config MACH_EM_X270
|
||||
bool "CompuLab EM-x270 platform"
|
||||
select PXA27x
|
||||
|
||||
endchoice
|
||||
|
||||
if PXA_SHARPSL
|
||||
|
@ -18,6 +18,7 @@ obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o sp
|
||||
obj-$(CONFIG_MACH_AKITA) += akita-ioexp.o
|
||||
obj-$(CONFIG_MACH_POODLE) += poodle.o corgi_ssp.o
|
||||
obj-$(CONFIG_MACH_TOSA) += tosa.o
|
||||
obj-$(CONFIG_MACH_EM_X270) += em-x270.o
|
||||
|
||||
# Support for blinky lights
|
||||
led-y := leds.o
|
||||
|
@ -1,11 +1,11 @@
|
||||
extern struct platform_device pxamci_device;
|
||||
extern struct platform_device pxaudc_device;
|
||||
extern struct platform_device pxafb_device;
|
||||
extern struct platform_device ffuart_device;
|
||||
extern struct platform_device btuart_device;
|
||||
extern struct platform_device stuart_device;
|
||||
extern struct platform_device hwuart_device;
|
||||
extern struct platform_device pxai2c_device;
|
||||
extern struct platform_device pxai2s_device;
|
||||
extern struct platform_device pxaficp_device;
|
||||
extern struct platform_device pxartc_device;
|
||||
extern struct platform_device pxa_device_mci;
|
||||
extern struct platform_device pxa_device_udc;
|
||||
extern struct platform_device pxa_device_fb;
|
||||
extern struct platform_device pxa_device_ffuart;
|
||||
extern struct platform_device pxa_device_btuart;
|
||||
extern struct platform_device pxa_device_stuart;
|
||||
extern struct platform_device pxa_device_hwuart;
|
||||
extern struct platform_device pxa_device_i2c;
|
||||
extern struct platform_device pxa_device_i2s;
|
||||
extern struct platform_device pxa_device_ficp;
|
||||
extern struct platform_device pxa_device_rtc;
|
||||
|
354
arch/arm/mach-pxa/em-x270.c
Normal file
354
arch/arm/mach-pxa/em-x270.c
Normal file
@ -0,0 +1,354 @@
|
||||
/*
|
||||
* Support for CompuLab EM-x270 platform
|
||||
*
|
||||
* Copyright (C) 2007 CompuLab, Ltd.
|
||||
* Author: Mike Rapoport <mike@compulab.co.il>
|
||||
*
|
||||
* 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/irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <linux/dm9000.h>
|
||||
#include <linux/rtc-v3020.h>
|
||||
|
||||
#include <linux/mtd/nand.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
#include <asm/arch/pxa-regs.h>
|
||||
#include <asm/arch/pxafb.h>
|
||||
#include <asm/arch/ohci.h>
|
||||
#include <asm/arch/mmc.h>
|
||||
#include <asm/arch/bitfield.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
/* GPIO IRQ usage */
|
||||
#define EM_X270_MMC_PD (105)
|
||||
#define EM_X270_ETHIRQ IRQ_GPIO(41)
|
||||
#define EM_X270_MMC_IRQ IRQ_GPIO(13)
|
||||
|
||||
static struct resource em_x270_dm9k_resource[] = {
|
||||
[0] = {
|
||||
.start = PXA_CS2_PHYS,
|
||||
.end = PXA_CS2_PHYS + 3,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = PXA_CS2_PHYS + 8,
|
||||
.end = PXA_CS2_PHYS + 8 + 0x3f,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[2] = {
|
||||
.start = EM_X270_ETHIRQ,
|
||||
.end = EM_X270_ETHIRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
||||
/* for the moment we limit ourselves to 32bit IO until some
|
||||
* better IO routines can be written and tested
|
||||
*/
|
||||
static struct dm9000_plat_data em_x270_dm9k_platdata = {
|
||||
.flags = DM9000_PLATF_32BITONLY,
|
||||
};
|
||||
|
||||
/* Ethernet device */
|
||||
static struct platform_device em_x270_dm9k = {
|
||||
.name = "dm9000",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(em_x270_dm9k_resource),
|
||||
.resource = em_x270_dm9k_resource,
|
||||
.dev = {
|
||||
.platform_data = &em_x270_dm9k_platdata,
|
||||
}
|
||||
};
|
||||
|
||||
/* audio device */
|
||||
static struct platform_device em_x270_audio = {
|
||||
.name = "pxa2xx-ac97",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
/* WM9712 touchscreen controller. Hopefully the driver will make it to
|
||||
* the mainstream sometime */
|
||||
static struct platform_device em_x270_ts = {
|
||||
.name = "wm97xx-ts",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
/* RTC */
|
||||
static struct resource em_x270_v3020_resource[] = {
|
||||
[0] = {
|
||||
.start = PXA_CS4_PHYS,
|
||||
.end = PXA_CS4_PHYS + 3,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct v3020_platform_data em_x270_v3020_platdata = {
|
||||
.leftshift = 0,
|
||||
};
|
||||
|
||||
static struct platform_device em_x270_rtc = {
|
||||
.name = "v3020",
|
||||
.num_resources = ARRAY_SIZE(em_x270_v3020_resource),
|
||||
.resource = em_x270_v3020_resource,
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &em_x270_v3020_platdata,
|
||||
}
|
||||
};
|
||||
|
||||
/* NAND flash */
|
||||
#define GPIO_NAND_CS (11)
|
||||
#define GPIO_NAND_RB (56)
|
||||
|
||||
static inline void nand_cs_on(void)
|
||||
{
|
||||
GPCR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS);
|
||||
}
|
||||
|
||||
static void nand_cs_off(void)
|
||||
{
|
||||
dsb();
|
||||
|
||||
GPSR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS);
|
||||
}
|
||||
|
||||
/* hardware specific access to control-lines */
|
||||
static void em_x270_nand_cmd_ctl(struct mtd_info *mtd, int dat,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
unsigned long nandaddr = (unsigned long)this->IO_ADDR_W;
|
||||
|
||||
dsb();
|
||||
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
if (ctrl & NAND_ALE)
|
||||
nandaddr |= (1 << 3);
|
||||
else
|
||||
nandaddr &= ~(1 << 3);
|
||||
if (ctrl & NAND_CLE)
|
||||
nandaddr |= (1 << 2);
|
||||
else
|
||||
nandaddr &= ~(1 << 2);
|
||||
if (ctrl & NAND_NCE)
|
||||
nand_cs_on();
|
||||
else
|
||||
nand_cs_off();
|
||||
}
|
||||
|
||||
dsb();
|
||||
this->IO_ADDR_W = (void __iomem *)nandaddr;
|
||||
if (dat != NAND_CMD_NONE)
|
||||
writel(dat, this->IO_ADDR_W);
|
||||
|
||||
dsb();
|
||||
}
|
||||
|
||||
/* read device ready pin */
|
||||
static int em_x270_nand_device_ready(struct mtd_info *mtd)
|
||||
{
|
||||
dsb();
|
||||
|
||||
return GPLR(GPIO_NAND_RB) & GPIO_bit(GPIO_NAND_RB);
|
||||
}
|
||||
|
||||
static struct mtd_partition em_x270_partition_info[] = {
|
||||
[0] = {
|
||||
.name = "em_x270-0",
|
||||
.offset = 0,
|
||||
.size = SZ_4M,
|
||||
},
|
||||
[1] = {
|
||||
.name = "em_x270-1",
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.size = MTDPART_SIZ_FULL
|
||||
},
|
||||
};
|
||||
|
||||
static const char *em_x270_part_probes[] = { "cmdlinepart", NULL };
|
||||
|
||||
struct platform_nand_data em_x270_nand_platdata = {
|
||||
.chip = {
|
||||
.nr_chips = 1,
|
||||
.chip_offset = 0,
|
||||
.nr_partitions = ARRAY_SIZE(em_x270_partition_info),
|
||||
.partitions = em_x270_partition_info,
|
||||
.chip_delay = 20,
|
||||
.part_probe_types = em_x270_part_probes,
|
||||
},
|
||||
.ctrl = {
|
||||
.hwcontrol = 0,
|
||||
.dev_ready = em_x270_nand_device_ready,
|
||||
.select_chip = 0,
|
||||
.cmd_ctrl = em_x270_nand_cmd_ctl,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource em_x270_nand_resource[] = {
|
||||
[0] = {
|
||||
.start = PXA_CS1_PHYS,
|
||||
.end = PXA_CS1_PHYS + 12,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device em_x270_nand = {
|
||||
.name = "gen_nand",
|
||||
.num_resources = ARRAY_SIZE(em_x270_nand_resource),
|
||||
.resource = em_x270_nand_resource,
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &em_x270_nand_platdata,
|
||||
}
|
||||
};
|
||||
|
||||
/* platform devices */
|
||||
static struct platform_device *platform_devices[] __initdata = {
|
||||
&em_x270_dm9k,
|
||||
&em_x270_audio,
|
||||
&em_x270_ts,
|
||||
&em_x270_rtc,
|
||||
&em_x270_nand,
|
||||
};
|
||||
|
||||
|
||||
/* PXA27x OHCI controller setup */
|
||||
static int em_x270_ohci_init(struct device *dev)
|
||||
{
|
||||
/* Set the Power Control Polarity Low */
|
||||
UHCHR = (UHCHR | UHCHR_PCPL) &
|
||||
~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSE);
|
||||
|
||||
/* enable port 2 transiever */
|
||||
UP2OCR = UP2OCR_HXS | UP2OCR_HXOE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pxaohci_platform_data em_x270_ohci_platform_data = {
|
||||
.port_mode = PMM_PERPORT_MODE,
|
||||
.init = em_x270_ohci_init,
|
||||
};
|
||||
|
||||
|
||||
static int em_x270_mci_init(struct device *dev,
|
||||
irq_handler_t em_x270_detect_int,
|
||||
void *data)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* setup GPIO for PXA27x MMC controller */
|
||||
pxa_gpio_mode(GPIO32_MMCCLK_MD);
|
||||
pxa_gpio_mode(GPIO112_MMCCMD_MD);
|
||||
pxa_gpio_mode(GPIO92_MMCDAT0_MD);
|
||||
pxa_gpio_mode(GPIO109_MMCDAT1_MD);
|
||||
pxa_gpio_mode(GPIO110_MMCDAT2_MD);
|
||||
pxa_gpio_mode(GPIO111_MMCDAT3_MD);
|
||||
|
||||
/* EM-X270 uses GPIO13 as SD power enable */
|
||||
pxa_gpio_mode(EM_X270_MMC_PD | GPIO_OUT);
|
||||
|
||||
err = request_irq(EM_X270_MMC_IRQ, em_x270_detect_int,
|
||||
IRQF_DISABLED | IRQF_TRIGGER_FALLING,
|
||||
"MMC card detect", data);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: can't request MMC card detect IRQ: %d\n",
|
||||
__FUNCTION__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void em_x270_mci_setpower(struct device *dev, unsigned int vdd)
|
||||
{
|
||||
/*
|
||||
FIXME: current hardware implementation does not allow to
|
||||
enable/disable MMC power. This will be fixed in next HW releases,
|
||||
and we'll need to add implmentation here.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
static void em_x270_mci_exit(struct device *dev, void *data)
|
||||
{
|
||||
free_irq(EM_X270_MMC_IRQ, data);
|
||||
}
|
||||
|
||||
static struct pxamci_platform_data em_x270_mci_platform_data = {
|
||||
.ocr_mask = MMC_VDD_28_29|MMC_VDD_29_30|MMC_VDD_30_31,
|
||||
.init = em_x270_mci_init,
|
||||
.setpower = em_x270_mci_setpower,
|
||||
.exit = em_x270_mci_exit,
|
||||
};
|
||||
|
||||
/* LCD 480x640 */
|
||||
static struct pxafb_mode_info em_x270_lcd_mode = {
|
||||
.pixclock = 50000,
|
||||
.bpp = 16,
|
||||
.xres = 480,
|
||||
.yres = 640,
|
||||
.hsync_len = 8,
|
||||
.vsync_len = 2,
|
||||
.left_margin = 8,
|
||||
.upper_margin = 0,
|
||||
.right_margin = 24,
|
||||
.lower_margin = 4,
|
||||
.cmap_greyscale = 0,
|
||||
};
|
||||
|
||||
static struct pxafb_mach_info em_x270_lcd = {
|
||||
.modes = &em_x270_lcd_mode,
|
||||
.num_modes = 1,
|
||||
.cmap_inverse = 0,
|
||||
.cmap_static = 0,
|
||||
.lccr0 = LCCR0_PAS,
|
||||
.lccr3 = LCCR3_PixClkDiv(0x01) | LCCR3_Acb(0xff),
|
||||
};
|
||||
|
||||
static void __init em_x270_init(void)
|
||||
{
|
||||
/* setup LCD */
|
||||
set_pxa_fb_info(&em_x270_lcd);
|
||||
|
||||
/* register EM-X270 platform devices */
|
||||
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
|
||||
|
||||
/* set MCI and OHCI platform parameters */
|
||||
pxa_set_mci_info(&em_x270_mci_platform_data);
|
||||
pxa_set_ohci_info(&em_x270_ohci_platform_data);
|
||||
|
||||
/* setup STUART GPIOs */
|
||||
pxa_gpio_mode(GPIO46_STRXD_MD);
|
||||
pxa_gpio_mode(GPIO47_STTXD_MD);
|
||||
|
||||
/* setup BTUART GPIOs */
|
||||
pxa_gpio_mode(GPIO42_BTRXD_MD);
|
||||
pxa_gpio_mode(GPIO43_BTTXD_MD);
|
||||
pxa_gpio_mode(GPIO44_BTCTS_MD);
|
||||
pxa_gpio_mode(GPIO45_BTRTS_MD);
|
||||
|
||||
/* Setup interrupt for dm9000 */
|
||||
set_irq_type(EM_X270_ETHIRQ, IRQT_RISING);
|
||||
}
|
||||
|
||||
MACHINE_START(EM_X270, "Compulab EM-x270")
|
||||
.boot_params = 0xa0000100,
|
||||
.phys_io = 0x40000000,
|
||||
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
|
||||
.map_io = pxa_map_io,
|
||||
.init_irq = pxa27x_init_irq,
|
||||
.timer = &pxa_timer,
|
||||
.init_machine = em_x270_init,
|
||||
MACHINE_END
|
@ -243,7 +243,7 @@ static struct resource pxamci_resources[] = {
|
||||
|
||||
static u64 pxamci_dmamask = 0xffffffffUL;
|
||||
|
||||
struct platform_device pxamci_device = {
|
||||
struct platform_device pxa_device_mci = {
|
||||
.name = "pxa2xx-mci",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
@ -256,7 +256,7 @@ struct platform_device pxamci_device = {
|
||||
|
||||
void __init pxa_set_mci_info(struct pxamci_platform_data *info)
|
||||
{
|
||||
pxamci_device.dev.platform_data = info;
|
||||
pxa_device_mci.dev.platform_data = info;
|
||||
}
|
||||
|
||||
|
||||
@ -282,7 +282,7 @@ static struct resource pxa2xx_udc_resources[] = {
|
||||
|
||||
static u64 udc_dma_mask = ~(u32)0;
|
||||
|
||||
struct platform_device pxaudc_device = {
|
||||
struct platform_device pxa_device_udc = {
|
||||
.name = "pxa2xx-udc",
|
||||
.id = -1,
|
||||
.resource = pxa2xx_udc_resources,
|
||||
@ -308,7 +308,7 @@ static struct resource pxafb_resources[] = {
|
||||
|
||||
static u64 fb_dma_mask = ~(u64)0;
|
||||
|
||||
struct platform_device pxafb_device = {
|
||||
struct platform_device pxa_device_fb = {
|
||||
.name = "pxa2xx-fb",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
@ -321,27 +321,27 @@ struct platform_device pxafb_device = {
|
||||
|
||||
void __init set_pxa_fb_info(struct pxafb_mach_info *info)
|
||||
{
|
||||
pxafb_device.dev.platform_data = info;
|
||||
pxa_device_fb.dev.platform_data = info;
|
||||
}
|
||||
|
||||
void __init set_pxa_fb_parent(struct device *parent_dev)
|
||||
{
|
||||
pxafb_device.dev.parent = parent_dev;
|
||||
pxa_device_fb.dev.parent = parent_dev;
|
||||
}
|
||||
|
||||
struct platform_device ffuart_device = {
|
||||
struct platform_device pxa_device_ffuart= {
|
||||
.name = "pxa2xx-uart",
|
||||
.id = 0,
|
||||
};
|
||||
struct platform_device btuart_device = {
|
||||
struct platform_device pxa_device_btuart = {
|
||||
.name = "pxa2xx-uart",
|
||||
.id = 1,
|
||||
};
|
||||
struct platform_device stuart_device = {
|
||||
struct platform_device pxa_device_stuart = {
|
||||
.name = "pxa2xx-uart",
|
||||
.id = 2,
|
||||
};
|
||||
struct platform_device hwuart_device = {
|
||||
struct platform_device pxa_device_hwuart = {
|
||||
.name = "pxa2xx-uart",
|
||||
.id = 3,
|
||||
};
|
||||
@ -358,7 +358,7 @@ static struct resource pxai2c_resources[] = {
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device pxai2c_device = {
|
||||
struct platform_device pxa_device_i2c = {
|
||||
.name = "pxa2xx-i2c",
|
||||
.id = 0,
|
||||
.resource = pxai2c_resources,
|
||||
@ -367,7 +367,7 @@ struct platform_device pxai2c_device = {
|
||||
|
||||
void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info)
|
||||
{
|
||||
pxai2c_device.dev.platform_data = info;
|
||||
pxa_device_i2c.dev.platform_data = info;
|
||||
}
|
||||
|
||||
static struct resource pxai2s_resources[] = {
|
||||
@ -382,7 +382,7 @@ static struct resource pxai2s_resources[] = {
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device pxai2s_device = {
|
||||
struct platform_device pxa_device_i2s = {
|
||||
.name = "pxa2xx-i2s",
|
||||
.id = -1,
|
||||
.resource = pxai2s_resources,
|
||||
@ -391,7 +391,7 @@ struct platform_device pxai2s_device = {
|
||||
|
||||
static u64 pxaficp_dmamask = ~(u32)0;
|
||||
|
||||
struct platform_device pxaficp_device = {
|
||||
struct platform_device pxa_device_ficp = {
|
||||
.name = "pxa2xx-ir",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
@ -402,10 +402,10 @@ struct platform_device pxaficp_device = {
|
||||
|
||||
void __init pxa_set_ficp_info(struct pxaficp_platform_data *info)
|
||||
{
|
||||
pxaficp_device.dev.platform_data = info;
|
||||
pxa_device_ficp.dev.platform_data = info;
|
||||
}
|
||||
|
||||
struct platform_device pxartc_device = {
|
||||
struct platform_device pxa_device_rtc = {
|
||||
.name = "sa1100-rtc",
|
||||
.id = -1,
|
||||
};
|
||||
|
@ -24,61 +24,13 @@
|
||||
#include <asm/arch/lubbock.h>
|
||||
#include <asm/mach/time.h>
|
||||
|
||||
|
||||
/*
|
||||
* Debug macros
|
||||
*/
|
||||
#undef DEBUG
|
||||
|
||||
#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
|
||||
#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
|
||||
|
||||
#define RESTORE_GPLEVEL(n) do { \
|
||||
GPSR##n = sleep_save[SLEEP_SAVE_GPLR##n]; \
|
||||
GPCR##n = ~sleep_save[SLEEP_SAVE_GPLR##n]; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* List of global PXA peripheral registers to preserve.
|
||||
* More ones like CP and general purpose register values are preserved
|
||||
* with the stack pointer in sleep.S.
|
||||
*/
|
||||
enum { SLEEP_SAVE_START = 0,
|
||||
|
||||
SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2, SLEEP_SAVE_GPLR3,
|
||||
SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2, SLEEP_SAVE_GPDR3,
|
||||
SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2, SLEEP_SAVE_GRER3,
|
||||
SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2, SLEEP_SAVE_GFER3,
|
||||
SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3,
|
||||
|
||||
SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U,
|
||||
SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U,
|
||||
SLEEP_SAVE_GAFR2_L, SLEEP_SAVE_GAFR2_U,
|
||||
SLEEP_SAVE_GAFR3_L, SLEEP_SAVE_GAFR3_U,
|
||||
|
||||
SLEEP_SAVE_PSTR,
|
||||
|
||||
SLEEP_SAVE_ICMR,
|
||||
SLEEP_SAVE_CKEN,
|
||||
|
||||
#ifdef CONFIG_PXA27x
|
||||
SLEEP_SAVE_MDREFR,
|
||||
SLEEP_SAVE_PWER, SLEEP_SAVE_PCFR, SLEEP_SAVE_PRER,
|
||||
SLEEP_SAVE_PFER, SLEEP_SAVE_PKWR,
|
||||
#endif
|
||||
|
||||
SLEEP_SAVE_CKSUM,
|
||||
|
||||
SLEEP_SAVE_SIZE
|
||||
};
|
||||
|
||||
struct pxa_cpu_pm_fns *pxa_cpu_pm_fns;
|
||||
static unsigned long *sleep_save;
|
||||
|
||||
int pxa_pm_enter(suspend_state_t state)
|
||||
{
|
||||
unsigned long sleep_save[SLEEP_SAVE_SIZE];
|
||||
unsigned long checksum = 0;
|
||||
unsigned long sleep_save_checksum = 0, checksum = 0;
|
||||
int i;
|
||||
extern void pxa_cpu_pm_enter(suspend_state_t state);
|
||||
|
||||
#ifdef CONFIG_IWMMXT
|
||||
/* force any iWMMXt context to ram **/
|
||||
@ -86,100 +38,35 @@ int pxa_pm_enter(suspend_state_t state)
|
||||
iwmmxt_task_disable(NULL);
|
||||
#endif
|
||||
|
||||
SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2);
|
||||
SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2);
|
||||
SAVE(GRER0); SAVE(GRER1); SAVE(GRER2);
|
||||
SAVE(GFER0); SAVE(GFER1); SAVE(GFER2);
|
||||
SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2);
|
||||
|
||||
SAVE(GAFR0_L); SAVE(GAFR0_U);
|
||||
SAVE(GAFR1_L); SAVE(GAFR1_U);
|
||||
SAVE(GAFR2_L); SAVE(GAFR2_U);
|
||||
|
||||
#ifdef CONFIG_PXA27x
|
||||
SAVE(MDREFR);
|
||||
SAVE(GPLR3); SAVE(GPDR3); SAVE(GRER3); SAVE(GFER3); SAVE(PGSR3);
|
||||
SAVE(GAFR3_L); SAVE(GAFR3_U);
|
||||
SAVE(PWER); SAVE(PCFR); SAVE(PRER);
|
||||
SAVE(PFER); SAVE(PKWR);
|
||||
#endif
|
||||
|
||||
SAVE(ICMR);
|
||||
ICMR = 0;
|
||||
|
||||
SAVE(CKEN);
|
||||
SAVE(PSTR);
|
||||
|
||||
/* Note: wake up source are set up in each machine specific files */
|
||||
|
||||
/* clear GPIO transition detect bits */
|
||||
GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2;
|
||||
#ifdef CONFIG_PXA27x
|
||||
GEDR3 = GEDR3;
|
||||
#endif
|
||||
pxa_cpu_pm_fns->save(sleep_save);
|
||||
|
||||
/* Clear sleep reset status */
|
||||
RCSR = RCSR_SMR;
|
||||
|
||||
/* before sleeping, calculate and save a checksum */
|
||||
for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++)
|
||||
checksum += sleep_save[i];
|
||||
sleep_save[SLEEP_SAVE_CKSUM] = checksum;
|
||||
for (i = 0; i < pxa_cpu_pm_fns->save_size - 1; i++)
|
||||
sleep_save_checksum += sleep_save[i];
|
||||
|
||||
/* *** go zzz *** */
|
||||
pxa_cpu_pm_enter(state);
|
||||
|
||||
pxa_cpu_pm_fns->enter(state);
|
||||
cpu_init();
|
||||
|
||||
/* after sleeping, validate the checksum */
|
||||
checksum = 0;
|
||||
for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++)
|
||||
for (i = 0; i < pxa_cpu_pm_fns->save_size - 1; i++)
|
||||
checksum += sleep_save[i];
|
||||
|
||||
/* if invalid, display message and wait for a hardware reset */
|
||||
if (checksum != sleep_save[SLEEP_SAVE_CKSUM]) {
|
||||
if (checksum != sleep_save_checksum) {
|
||||
#ifdef CONFIG_ARCH_LUBBOCK
|
||||
LUB_HEXLED = 0xbadbadc5;
|
||||
#endif
|
||||
while (1)
|
||||
pxa_cpu_pm_enter(state);
|
||||
pxa_cpu_pm_fns->enter(state);
|
||||
}
|
||||
|
||||
/* ensure not to come back here if it wasn't intended */
|
||||
PSPR = 0;
|
||||
pxa_cpu_pm_fns->restore(sleep_save);
|
||||
|
||||
/* restore registers */
|
||||
RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); RESTORE_GPLEVEL(2);
|
||||
RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2);
|
||||
RESTORE(GAFR0_L); RESTORE(GAFR0_U);
|
||||
RESTORE(GAFR1_L); RESTORE(GAFR1_U);
|
||||
RESTORE(GAFR2_L); RESTORE(GAFR2_U);
|
||||
RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2);
|
||||
RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2);
|
||||
RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2);
|
||||
|
||||
#ifdef CONFIG_PXA27x
|
||||
RESTORE(MDREFR);
|
||||
RESTORE_GPLEVEL(3); RESTORE(GPDR3);
|
||||
RESTORE(GAFR3_L); RESTORE(GAFR3_U);
|
||||
RESTORE(GRER3); RESTORE(GFER3); RESTORE(PGSR3);
|
||||
RESTORE(PWER); RESTORE(PCFR); RESTORE(PRER);
|
||||
RESTORE(PFER); RESTORE(PKWR);
|
||||
#endif
|
||||
|
||||
PSSR = PSSR_RDH | PSSR_PH;
|
||||
|
||||
RESTORE(CKEN);
|
||||
|
||||
ICLR = 0;
|
||||
ICCR = 1;
|
||||
RESTORE(ICMR);
|
||||
|
||||
RESTORE(PSTR);
|
||||
|
||||
#ifdef DEBUG
|
||||
printk(KERN_DEBUG "*** made it back from resume\n");
|
||||
#endif
|
||||
pr_debug("*** made it back from resume\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -190,3 +77,35 @@ unsigned long sleep_phys_sp(void *sp)
|
||||
{
|
||||
return virt_to_phys(sp);
|
||||
}
|
||||
|
||||
static int pxa_pm_valid(suspend_state_t state)
|
||||
{
|
||||
if (pxa_cpu_pm_fns)
|
||||
return pxa_cpu_pm_fns->valid(state);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct pm_ops pxa_pm_ops = {
|
||||
.valid = pxa_pm_valid,
|
||||
.enter = pxa_pm_enter,
|
||||
};
|
||||
|
||||
static int __init pxa_pm_init(void)
|
||||
{
|
||||
if (!pxa_cpu_pm_fns) {
|
||||
printk(KERN_ERR "no valid pxa_cpu_pm_fns defined\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sleep_save = kmalloc(pxa_cpu_pm_fns->save_size, GFP_KERNEL);
|
||||
if (!sleep_save) {
|
||||
printk(KERN_ERR "failed to alloc memory for pm save\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pm_set_ops(&pxa_pm_ops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
device_initcall(pxa_pm_init);
|
||||
|
@ -110,26 +110,99 @@ EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
void pxa_cpu_pm_enter(suspend_state_t state)
|
||||
{
|
||||
extern void pxa_cpu_suspend(unsigned int);
|
||||
extern void pxa_cpu_resume(void);
|
||||
#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
|
||||
#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
|
||||
|
||||
#define RESTORE_GPLEVEL(n) do { \
|
||||
GPSR##n = sleep_save[SLEEP_SAVE_GPLR##n]; \
|
||||
GPCR##n = ~sleep_save[SLEEP_SAVE_GPLR##n]; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* List of global PXA peripheral registers to preserve.
|
||||
* More ones like CP and general purpose register values are preserved
|
||||
* with the stack pointer in sleep.S.
|
||||
*/
|
||||
enum { SLEEP_SAVE_START = 0,
|
||||
|
||||
SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2,
|
||||
SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2,
|
||||
SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2,
|
||||
SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2,
|
||||
SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2,
|
||||
|
||||
SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U,
|
||||
SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U,
|
||||
SLEEP_SAVE_GAFR2_L, SLEEP_SAVE_GAFR2_U,
|
||||
|
||||
SLEEP_SAVE_PSTR,
|
||||
|
||||
SLEEP_SAVE_ICMR,
|
||||
SLEEP_SAVE_CKEN,
|
||||
|
||||
SLEEP_SAVE_SIZE
|
||||
};
|
||||
|
||||
|
||||
static void pxa25x_cpu_pm_save(unsigned long *sleep_save)
|
||||
{
|
||||
SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2);
|
||||
SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2);
|
||||
SAVE(GRER0); SAVE(GRER1); SAVE(GRER2);
|
||||
SAVE(GFER0); SAVE(GFER1); SAVE(GFER2);
|
||||
SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2);
|
||||
|
||||
SAVE(GAFR0_L); SAVE(GAFR0_U);
|
||||
SAVE(GAFR1_L); SAVE(GAFR1_U);
|
||||
SAVE(GAFR2_L); SAVE(GAFR2_U);
|
||||
|
||||
SAVE(ICMR);
|
||||
SAVE(CKEN);
|
||||
SAVE(PSTR);
|
||||
}
|
||||
|
||||
static void pxa25x_cpu_pm_restore(unsigned long *sleep_save)
|
||||
{
|
||||
/* restore registers */
|
||||
RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); RESTORE_GPLEVEL(2);
|
||||
RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2);
|
||||
RESTORE(GAFR0_L); RESTORE(GAFR0_U);
|
||||
RESTORE(GAFR1_L); RESTORE(GAFR1_U);
|
||||
RESTORE(GAFR2_L); RESTORE(GAFR2_U);
|
||||
RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2);
|
||||
RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2);
|
||||
RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2);
|
||||
|
||||
RESTORE(CKEN);
|
||||
RESTORE(ICMR);
|
||||
RESTORE(PSTR);
|
||||
}
|
||||
|
||||
static void pxa25x_cpu_pm_enter(suspend_state_t state)
|
||||
{
|
||||
CKEN = 0;
|
||||
|
||||
switch (state) {
|
||||
case PM_SUSPEND_MEM:
|
||||
/* set resume return address */
|
||||
PSPR = virt_to_phys(pxa_cpu_resume);
|
||||
pxa_cpu_suspend(PWRMODE_SLEEP);
|
||||
pxa25x_cpu_suspend(PWRMODE_SLEEP);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct pm_ops pxa25x_pm_ops = {
|
||||
.enter = pxa_pm_enter,
|
||||
static struct pxa_cpu_pm_fns pxa25x_cpu_pm_fns = {
|
||||
.save_size = SLEEP_SAVE_SIZE,
|
||||
.valid = pm_valid_only_mem,
|
||||
.save = pxa25x_cpu_pm_save,
|
||||
.restore = pxa25x_cpu_pm_restore,
|
||||
.enter = pxa25x_cpu_pm_enter,
|
||||
};
|
||||
|
||||
static void __init pxa25x_init_pm(void)
|
||||
{
|
||||
pxa_cpu_pm_fns = &pxa25x_cpu_pm_fns;
|
||||
}
|
||||
#endif
|
||||
|
||||
void __init pxa25x_init_irq(void)
|
||||
@ -139,16 +212,16 @@ void __init pxa25x_init_irq(void)
|
||||
}
|
||||
|
||||
static struct platform_device *pxa25x_devices[] __initdata = {
|
||||
&pxamci_device,
|
||||
&pxaudc_device,
|
||||
&pxafb_device,
|
||||
&ffuart_device,
|
||||
&btuart_device,
|
||||
&stuart_device,
|
||||
&pxai2c_device,
|
||||
&pxai2s_device,
|
||||
&pxaficp_device,
|
||||
&pxartc_device,
|
||||
&pxa_device_mci,
|
||||
&pxa_device_udc,
|
||||
&pxa_device_fb,
|
||||
&pxa_device_ffuart,
|
||||
&pxa_device_btuart,
|
||||
&pxa_device_stuart,
|
||||
&pxa_device_i2c,
|
||||
&pxa_device_i2s,
|
||||
&pxa_device_ficp,
|
||||
&pxa_device_rtc,
|
||||
};
|
||||
|
||||
static int __init pxa25x_init(void)
|
||||
@ -159,14 +232,14 @@ static int __init pxa25x_init(void)
|
||||
if ((ret = pxa_init_dma(16)))
|
||||
return ret;
|
||||
#ifdef CONFIG_PM
|
||||
pm_set_ops(&pxa25x_pm_ops);
|
||||
pxa25x_init_pm();
|
||||
#endif
|
||||
ret = platform_add_devices(pxa25x_devices,
|
||||
ARRAY_SIZE(pxa25x_devices));
|
||||
}
|
||||
/* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
|
||||
if (cpu_is_pxa25x())
|
||||
ret = platform_device_register(&hwuart_device);
|
||||
ret = platform_device_register(&pxa_device_hwuart);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -126,14 +126,107 @@ EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
void pxa_cpu_pm_enter(suspend_state_t state)
|
||||
#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
|
||||
#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
|
||||
|
||||
#define RESTORE_GPLEVEL(n) do { \
|
||||
GPSR##n = sleep_save[SLEEP_SAVE_GPLR##n]; \
|
||||
GPCR##n = ~sleep_save[SLEEP_SAVE_GPLR##n]; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* List of global PXA peripheral registers to preserve.
|
||||
* More ones like CP and general purpose register values are preserved
|
||||
* with the stack pointer in sleep.S.
|
||||
*/
|
||||
enum { SLEEP_SAVE_START = 0,
|
||||
|
||||
SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2, SLEEP_SAVE_GPLR3,
|
||||
SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2, SLEEP_SAVE_GPDR3,
|
||||
SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2, SLEEP_SAVE_GRER3,
|
||||
SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2, SLEEP_SAVE_GFER3,
|
||||
SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3,
|
||||
|
||||
SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U,
|
||||
SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U,
|
||||
SLEEP_SAVE_GAFR2_L, SLEEP_SAVE_GAFR2_U,
|
||||
SLEEP_SAVE_GAFR3_L, SLEEP_SAVE_GAFR3_U,
|
||||
|
||||
SLEEP_SAVE_PSTR,
|
||||
|
||||
SLEEP_SAVE_ICMR,
|
||||
SLEEP_SAVE_CKEN,
|
||||
|
||||
SLEEP_SAVE_MDREFR,
|
||||
SLEEP_SAVE_PWER, SLEEP_SAVE_PCFR, SLEEP_SAVE_PRER,
|
||||
SLEEP_SAVE_PFER, SLEEP_SAVE_PKWR,
|
||||
|
||||
SLEEP_SAVE_SIZE
|
||||
};
|
||||
|
||||
void pxa27x_cpu_pm_save(unsigned long *sleep_save)
|
||||
{
|
||||
SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2); SAVE(GPLR3);
|
||||
SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2); SAVE(GPDR3);
|
||||
SAVE(GRER0); SAVE(GRER1); SAVE(GRER2); SAVE(GRER3);
|
||||
SAVE(GFER0); SAVE(GFER1); SAVE(GFER2); SAVE(GFER3);
|
||||
SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2); SAVE(PGSR3);
|
||||
|
||||
SAVE(GAFR0_L); SAVE(GAFR0_U);
|
||||
SAVE(GAFR1_L); SAVE(GAFR1_U);
|
||||
SAVE(GAFR2_L); SAVE(GAFR2_U);
|
||||
SAVE(GAFR3_L); SAVE(GAFR3_U);
|
||||
|
||||
SAVE(MDREFR);
|
||||
SAVE(PWER); SAVE(PCFR); SAVE(PRER);
|
||||
SAVE(PFER); SAVE(PKWR);
|
||||
|
||||
SAVE(ICMR); ICMR = 0;
|
||||
SAVE(CKEN);
|
||||
SAVE(PSTR);
|
||||
|
||||
/* Clear GPIO transition detect bits */
|
||||
GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2; GEDR3 = GEDR3;
|
||||
}
|
||||
|
||||
void pxa27x_cpu_pm_restore(unsigned long *sleep_save)
|
||||
{
|
||||
/* ensure not to come back here if it wasn't intended */
|
||||
PSPR = 0;
|
||||
|
||||
/* restore registers */
|
||||
RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1);
|
||||
RESTORE_GPLEVEL(2); RESTORE_GPLEVEL(3);
|
||||
RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2); RESTORE(GPDR3);
|
||||
RESTORE(GAFR0_L); RESTORE(GAFR0_U);
|
||||
RESTORE(GAFR1_L); RESTORE(GAFR1_U);
|
||||
RESTORE(GAFR2_L); RESTORE(GAFR2_U);
|
||||
RESTORE(GAFR3_L); RESTORE(GAFR3_U);
|
||||
RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2); RESTORE(GRER3);
|
||||
RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2); RESTORE(GFER3);
|
||||
RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2); RESTORE(PGSR3);
|
||||
|
||||
RESTORE(MDREFR);
|
||||
RESTORE(PWER); RESTORE(PCFR); RESTORE(PRER);
|
||||
RESTORE(PFER); RESTORE(PKWR);
|
||||
|
||||
PSSR = PSSR_RDH | PSSR_PH;
|
||||
|
||||
RESTORE(CKEN);
|
||||
|
||||
ICLR = 0;
|
||||
ICCR = 1;
|
||||
RESTORE(ICMR);
|
||||
RESTORE(PSTR);
|
||||
}
|
||||
|
||||
void pxa27x_cpu_pm_enter(suspend_state_t state)
|
||||
{
|
||||
extern void pxa_cpu_standby(void);
|
||||
extern void pxa_cpu_suspend(unsigned int);
|
||||
extern void pxa_cpu_resume(void);
|
||||
|
||||
if (state == PM_SUSPEND_STANDBY)
|
||||
CKEN = (1 << CKEN_MEMC) | (1 << CKEN_OSTIMER) | (1 << CKEN_LCD) | (1 << CKEN_PWM0);
|
||||
CKEN = (1 << CKEN_MEMC) | (1 << CKEN_OSTIMER) |
|
||||
(1 << CKEN_LCD) | (1 << CKEN_PWM0);
|
||||
else
|
||||
CKEN = (1 << CKEN_MEMC) | (1 << CKEN_OSTIMER);
|
||||
|
||||
@ -150,20 +243,28 @@ void pxa_cpu_pm_enter(suspend_state_t state)
|
||||
case PM_SUSPEND_MEM:
|
||||
/* set resume return address */
|
||||
PSPR = virt_to_phys(pxa_cpu_resume);
|
||||
pxa_cpu_suspend(PWRMODE_SLEEP);
|
||||
pxa27x_cpu_suspend(PWRMODE_SLEEP);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int pxa27x_pm_valid(suspend_state_t state)
|
||||
static int pxa27x_cpu_pm_valid(suspend_state_t state)
|
||||
{
|
||||
return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY;
|
||||
}
|
||||
|
||||
static struct pm_ops pxa27x_pm_ops = {
|
||||
.enter = pxa_pm_enter,
|
||||
.valid = pxa27x_pm_valid,
|
||||
static struct pxa_cpu_pm_fns pxa27x_cpu_pm_fns = {
|
||||
.save_size = SLEEP_SAVE_SIZE,
|
||||
.save = pxa27x_cpu_pm_save,
|
||||
.restore = pxa27x_cpu_pm_restore,
|
||||
.valid = pxa27x_cpu_pm_valid,
|
||||
.enter = pxa27x_cpu_pm_enter,
|
||||
};
|
||||
|
||||
static void __init pxa27x_init_pm(void)
|
||||
{
|
||||
pxa_cpu_pm_fns = &pxa27x_cpu_pm_fns;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -185,7 +286,7 @@ static struct resource pxa27x_ohci_resources[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device pxaohci_device = {
|
||||
static struct platform_device pxa27x_device_ohci = {
|
||||
.name = "pxa27x-ohci",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
@ -198,7 +299,7 @@ static struct platform_device pxaohci_device = {
|
||||
|
||||
void __init pxa_set_ohci_info(struct pxaohci_platform_data *info)
|
||||
{
|
||||
pxaohci_device.dev.platform_data = info;
|
||||
pxa27x_device_ohci.dev.platform_data = info;
|
||||
}
|
||||
|
||||
static struct resource i2c_power_resources[] = {
|
||||
@ -213,7 +314,7 @@ static struct resource i2c_power_resources[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device pxai2c_power_device = {
|
||||
static struct platform_device pxa27x_device_i2c_power = {
|
||||
.name = "pxa2xx-i2c",
|
||||
.id = 1,
|
||||
.resource = i2c_power_resources,
|
||||
@ -221,18 +322,18 @@ static struct platform_device pxai2c_power_device = {
|
||||
};
|
||||
|
||||
static struct platform_device *devices[] __initdata = {
|
||||
&pxamci_device,
|
||||
&pxaudc_device,
|
||||
&pxafb_device,
|
||||
&ffuart_device,
|
||||
&btuart_device,
|
||||
&stuart_device,
|
||||
&pxai2c_device,
|
||||
&pxai2c_power_device,
|
||||
&pxai2s_device,
|
||||
&pxaficp_device,
|
||||
&pxartc_device,
|
||||
&pxaohci_device,
|
||||
&pxa_device_mci,
|
||||
&pxa_device_udc,
|
||||
&pxa_device_fb,
|
||||
&pxa_device_ffuart,
|
||||
&pxa_device_btuart,
|
||||
&pxa_device_stuart,
|
||||
&pxa_device_i2c,
|
||||
&pxa_device_i2s,
|
||||
&pxa_device_ficp,
|
||||
&pxa_device_rtc,
|
||||
&pxa27x_device_i2c_power,
|
||||
&pxa27x_device_ohci,
|
||||
};
|
||||
|
||||
void __init pxa27x_init_irq(void)
|
||||
@ -249,7 +350,7 @@ static int __init pxa27x_init(void)
|
||||
if ((ret = pxa_init_dma(32)))
|
||||
return ret;
|
||||
#ifdef CONFIG_PM
|
||||
pm_set_ops(&pxa27x_pm_ops);
|
||||
pxa27x_init_pm();
|
||||
#endif
|
||||
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
}
|
||||
|
@ -17,28 +17,12 @@
|
||||
|
||||
#include <asm/arch/pxa-regs.h>
|
||||
|
||||
#ifdef CONFIG_PXA27x // workaround for Errata 50
|
||||
#define MDREFR_KDIV 0x200a4000 // all banks
|
||||
#define CCCR_SLEEP 0x00000107 // L=7 2N=2 A=0 PPDIS=0 CPDIS=0
|
||||
#endif
|
||||
|
||||
.text
|
||||
|
||||
/*
|
||||
* pxa_cpu_suspend()
|
||||
*
|
||||
* Forces CPU into sleep state.
|
||||
*
|
||||
* r0 = value for PWRMODE M field for desired sleep state
|
||||
*/
|
||||
|
||||
ENTRY(pxa_cpu_suspend)
|
||||
|
||||
#ifndef CONFIG_IWMMXT
|
||||
mra r2, r3, acc0
|
||||
#endif
|
||||
stmfd sp!, {r2 - r12, lr} @ save registers on stack
|
||||
|
||||
pxa_cpu_save_cp:
|
||||
@ get coprocessor registers
|
||||
mrc p14, 0, r3, c6, c0, 0 @ clock configuration, for turbo mode
|
||||
mrc p15, 0, r4, c15, c1, 0 @ CP access reg
|
||||
@ -54,12 +38,36 @@ ENTRY(pxa_cpu_suspend)
|
||||
mov r10, sp
|
||||
stmfd sp!, {r3 - r10}
|
||||
|
||||
mov r5, r0 @ save sleep mode
|
||||
mov pc, lr
|
||||
|
||||
pxa_cpu_save_sp:
|
||||
@ preserve phys address of stack
|
||||
mov r0, sp
|
||||
mov r2, lr
|
||||
bl sleep_phys_sp
|
||||
ldr r1, =sleep_save_sp
|
||||
str r0, [r1]
|
||||
mov pc, r2
|
||||
|
||||
/*
|
||||
* pxa27x_cpu_suspend()
|
||||
*
|
||||
* Forces CPU into sleep state.
|
||||
*
|
||||
* r0 = value for PWRMODE M field for desired sleep state
|
||||
*/
|
||||
|
||||
ENTRY(pxa27x_cpu_suspend)
|
||||
|
||||
#ifndef CONFIG_IWMMXT
|
||||
mra r2, r3, acc0
|
||||
#endif
|
||||
stmfd sp!, {r2 - r12, lr} @ save registers on stack
|
||||
|
||||
bl pxa_cpu_save_cp
|
||||
|
||||
mov r5, r0 @ save sleep mode
|
||||
bl pxa_cpu_save_sp
|
||||
|
||||
@ clean data cache
|
||||
bl xscale_flush_kern_cache_all
|
||||
@ -80,13 +88,55 @@ ENTRY(pxa_cpu_suspend)
|
||||
@ enable SDRAM self-refresh mode
|
||||
orr r5, r5, #MDREFR_SLFRSH
|
||||
|
||||
#ifdef CONFIG_PXA27x
|
||||
@ set SDCLKx divide-by-2 bits (this is part of a workaround for Errata 50)
|
||||
ldr r6, =MDREFR_KDIV
|
||||
orr r5, r5, r6
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PXA25x
|
||||
@ Intel PXA270 Specification Update notes problems sleeping
|
||||
@ with core operating above 91 MHz
|
||||
@ (see Errata 50, ...processor does not exit from sleep...)
|
||||
|
||||
ldr r6, =CCCR
|
||||
ldr r8, [r6] @ keep original value for resume
|
||||
|
||||
ldr r7, =CCCR_SLEEP @ prepare CCCR sleep value
|
||||
mov r0, #0x2 @ prepare value for CLKCFG
|
||||
|
||||
@ align execution to a cache line
|
||||
b pxa_cpu_do_suspend
|
||||
|
||||
/*
|
||||
* pxa27x_cpu_suspend()
|
||||
*
|
||||
* Forces CPU into sleep state.
|
||||
*
|
||||
* r0 = value for PWRMODE M field for desired sleep state
|
||||
*/
|
||||
|
||||
ENTRY(pxa25x_cpu_suspend)
|
||||
stmfd sp!, {r2 - r12, lr} @ save registers on stack
|
||||
|
||||
bl pxa_cpu_save_cp
|
||||
|
||||
mov r5, r0 @ save sleep mode
|
||||
bl pxa_cpu_save_sp
|
||||
|
||||
@ clean data cache
|
||||
bl xscale_flush_kern_cache_all
|
||||
|
||||
@ prepare value for sleep mode
|
||||
mov r1, r5 @ sleep mode
|
||||
|
||||
@ prepare pointer to physical address 0 (virtual mapping in generic.c)
|
||||
mov r2, #UNCACHED_PHYS_0
|
||||
|
||||
@ prepare SDRAM refresh settings
|
||||
ldr r4, =MDREFR
|
||||
ldr r5, [r4]
|
||||
|
||||
@ enable SDRAM self-refresh mode
|
||||
orr r5, r5, #MDREFR_SLFRSH
|
||||
|
||||
@ Intel PXA255 Specification Update notes problems
|
||||
@ about suspending with PXBus operating above 133MHz
|
||||
@ (see Errata 31, GPIO output signals, ... unpredictable in sleep
|
||||
@ -118,30 +168,15 @@ ENTRY(pxa_cpu_suspend)
|
||||
mov r0, #0
|
||||
mcr p14, 0, r0, c6, c0, 0
|
||||
orr r0, r0, #2 @ initiate change bit
|
||||
#endif
|
||||
#ifdef CONFIG_PXA27x
|
||||
@ Intel PXA270 Specification Update notes problems sleeping
|
||||
@ with core operating above 91 MHz
|
||||
@ (see Errata 50, ...processor does not exit from sleep...)
|
||||
|
||||
ldr r6, =CCCR
|
||||
ldr r8, [r6] @ keep original value for resume
|
||||
|
||||
ldr r7, =CCCR_SLEEP @ prepare CCCR sleep value
|
||||
mov r0, #0x2 @ prepare value for CLKCFG
|
||||
#endif
|
||||
|
||||
@ align execution to a cache line
|
||||
b 1f
|
||||
b pxa_cpu_do_suspend
|
||||
|
||||
.ltorg
|
||||
.align 5
|
||||
1:
|
||||
pxa_cpu_do_suspend:
|
||||
|
||||
@ All needed values are now in registers.
|
||||
@ These last instructions should be in cache
|
||||
|
||||
#if defined(CONFIG_PXA25x) || defined(CONFIG_PXA27x)
|
||||
@ initiate the frequency change...
|
||||
str r7, [r6]
|
||||
mcr p14, 0, r0, c6, c0, 0
|
||||
@ -155,7 +190,6 @@ ENTRY(pxa_cpu_suspend)
|
||||
mov r0, #42
|
||||
10: subs r0, r0, #1
|
||||
bne 10b
|
||||
#endif
|
||||
|
||||
@ Do not reorder...
|
||||
@ Intel PXA270 Specification Update notes problems performing
|
||||
|
@ -1,9 +1,11 @@
|
||||
/*
|
||||
* arch/arm/mach-pxa/time.c
|
||||
*
|
||||
* Author: Nicolas Pitre
|
||||
* Created: Jun 15, 2001
|
||||
* Copyright: MontaVista Software Inc.
|
||||
* PXA clocksource, clockevents, and OST interrupt handlers.
|
||||
* Copyright (c) 2007 by Bill Gatliff <bgat@billgatliff.com>.
|
||||
*
|
||||
* Derived from Nicolas Pitre's PXA timer handler Copyright (c) 2001
|
||||
* by MontaVista Software, Inc. (Nico, your code rocks!)
|
||||
*
|
||||
* 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
|
||||
@ -12,164 +14,160 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/clockchips.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/leds.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mach/irq.h>
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/arch/pxa-regs.h>
|
||||
|
||||
|
||||
static int pxa_set_rtc(void)
|
||||
{
|
||||
unsigned long current_time = xtime.tv_sec;
|
||||
|
||||
if (RTSR & RTSR_ALE) {
|
||||
/* make sure not to forward the clock over an alarm */
|
||||
unsigned long alarm = RTAR;
|
||||
if (current_time >= alarm && alarm >= RCNR)
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
RCNR = current_time;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NO_IDLE_HZ
|
||||
static unsigned long initial_match;
|
||||
static int match_posponed;
|
||||
#endif
|
||||
|
||||
static irqreturn_t
|
||||
pxa_timer_interrupt(int irq, void *dev_id)
|
||||
pxa_ost0_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
int next_match;
|
||||
struct clock_event_device *c = dev_id;
|
||||
|
||||
write_seqlock(&xtime_lock);
|
||||
|
||||
#ifdef CONFIG_NO_IDLE_HZ
|
||||
if (match_posponed) {
|
||||
match_posponed = 0;
|
||||
OSMR0 = initial_match;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Loop until we get ahead of the free running timer.
|
||||
* This ensures an exact clock tick count and time accuracy.
|
||||
* Since IRQs are disabled at this point, coherence between
|
||||
* lost_ticks(updated in do_timer()) and the match reg value is
|
||||
* ensured, hence we can use do_gettimeofday() from interrupt
|
||||
* handlers.
|
||||
*
|
||||
* HACK ALERT: it seems that the PXA timer regs aren't updated right
|
||||
* away in all cases when a write occurs. We therefore compare with
|
||||
* 8 instead of 0 in the while() condition below to avoid missing a
|
||||
* match if OSCR has already reached the next OSMR value.
|
||||
* Experience has shown that up to 6 ticks are needed to work around
|
||||
* this problem, but let's use 8 to be conservative. Note that this
|
||||
* affect things only when the timer IRQ has been delayed by nearly
|
||||
* exactly one tick period which should be a pretty rare event.
|
||||
if (c->mode == CLOCK_EVT_MODE_ONESHOT) {
|
||||
/* Disarm the compare/match, signal the event. */
|
||||
OIER &= ~OIER_E0;
|
||||
c->event_handler(c);
|
||||
} else if (c->mode == CLOCK_EVT_MODE_PERIODIC) {
|
||||
/* Call the event handler as many times as necessary
|
||||
* to recover missed events, if any (if we update
|
||||
* OSMR0 and OSCR0 is still ahead of us, we've missed
|
||||
* the event). As we're dealing with that, re-arm the
|
||||
* compare/match for the next event.
|
||||
*
|
||||
* HACK ALERT:
|
||||
*
|
||||
* There's a latency between the instruction that
|
||||
* writes to OSMR0 and the actual commit to the
|
||||
* physical hardware, because the CPU doesn't (have
|
||||
* to) run at bus speed, there's a write buffer
|
||||
* between the CPU and the bus, etc. etc. So if the
|
||||
* target OSCR0 is "very close", to the OSMR0 load
|
||||
* value, the update to OSMR0 might not get to the
|
||||
* hardware in time and we'll miss that interrupt.
|
||||
*
|
||||
* To be safe, if the new OSMR0 is "very close" to the
|
||||
* target OSCR0 value, we call the event_handler as
|
||||
* though the event actually happened. According to
|
||||
* Nico's comment in the previous version of this
|
||||
* code, experience has shown that 6 OSCR ticks is
|
||||
* "very close" but he went with 8. We will use 16,
|
||||
* based on the results of testing on PXA270.
|
||||
*
|
||||
* To be doubly sure, we also tell clkevt via
|
||||
* clockevents_register_device() not to ask for
|
||||
* anything that might put us "very close".
|
||||
*/
|
||||
#define MIN_OSCR_DELTA 16
|
||||
do {
|
||||
timer_tick();
|
||||
OSSR = OSSR_M0; /* Clear match on timer 0 */
|
||||
OSSR = OSSR_M0;
|
||||
next_match = (OSMR0 += LATCH);
|
||||
} while( (signed long)(next_match - OSCR) <= 8 );
|
||||
|
||||
write_sequnlock(&xtime_lock);
|
||||
c->event_handler(c);
|
||||
} while (((signed long)(next_match - OSCR) <= MIN_OSCR_DELTA)
|
||||
&& (c->mode == CLOCK_EVT_MODE_PERIODIC));
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct irqaction pxa_timer_irq = {
|
||||
.name = "PXA Timer Tick",
|
||||
.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
|
||||
.handler = pxa_timer_interrupt,
|
||||
static int
|
||||
pxa_osmr0_set_next_event(unsigned long delta, struct clock_event_device *dev)
|
||||
{
|
||||
unsigned long irqflags;
|
||||
|
||||
raw_local_irq_save(irqflags);
|
||||
OSMR0 = OSCR + delta;
|
||||
OSSR = OSSR_M0;
|
||||
OIER |= OIER_E0;
|
||||
raw_local_irq_restore(irqflags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
|
||||
{
|
||||
unsigned long irqflags;
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
raw_local_irq_save(irqflags);
|
||||
OSMR0 = OSCR + LATCH;
|
||||
OSSR = OSSR_M0;
|
||||
OIER |= OIER_E0;
|
||||
raw_local_irq_restore(irqflags);
|
||||
break;
|
||||
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
raw_local_irq_save(irqflags);
|
||||
OIER &= ~OIER_E0;
|
||||
raw_local_irq_restore(irqflags);
|
||||
break;
|
||||
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
/* initializing, released, or preparing for suspend */
|
||||
raw_local_irq_save(irqflags);
|
||||
OIER &= ~OIER_E0;
|
||||
raw_local_irq_restore(irqflags);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct clock_event_device ckevt_pxa_osmr0 = {
|
||||
.name = "osmr0",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.shift = 32,
|
||||
.rating = 200,
|
||||
.cpumask = CPU_MASK_CPU0,
|
||||
.set_next_event = pxa_osmr0_set_next_event,
|
||||
.set_mode = pxa_osmr0_set_mode,
|
||||
};
|
||||
|
||||
static cycle_t pxa_get_cycles(void)
|
||||
static cycle_t pxa_read_oscr(void)
|
||||
{
|
||||
return OSCR;
|
||||
}
|
||||
|
||||
static struct clocksource clocksource_pxa = {
|
||||
.name = "pxa_timer",
|
||||
static struct clocksource cksrc_pxa_oscr0 = {
|
||||
.name = "oscr0",
|
||||
.rating = 200,
|
||||
.read = pxa_get_cycles,
|
||||
.read = pxa_read_oscr,
|
||||
.mask = CLOCKSOURCE_MASK(32),
|
||||
.shift = 20,
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
};
|
||||
|
||||
static struct irqaction pxa_ost0_irq = {
|
||||
.name = "ost0",
|
||||
.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
|
||||
.handler = pxa_ost0_interrupt,
|
||||
.dev_id = &ckevt_pxa_osmr0,
|
||||
};
|
||||
|
||||
static void __init pxa_timer_init(void)
|
||||
{
|
||||
struct timespec tv;
|
||||
unsigned long flags;
|
||||
OIER = 0;
|
||||
OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3;
|
||||
|
||||
set_rtc = pxa_set_rtc;
|
||||
ckevt_pxa_osmr0.mult =
|
||||
div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt_pxa_osmr0.shift);
|
||||
ckevt_pxa_osmr0.max_delta_ns =
|
||||
clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0);
|
||||
ckevt_pxa_osmr0.min_delta_ns =
|
||||
clockevent_delta2ns(MIN_OSCR_DELTA, &ckevt_pxa_osmr0) + 1;
|
||||
|
||||
OIER = 0; /* disable any timer interrupts */
|
||||
OSSR = 0xf; /* clear status on all timers */
|
||||
setup_irq(IRQ_OST0, &pxa_timer_irq);
|
||||
local_irq_save(flags);
|
||||
OIER = OIER_E0; /* enable match on timer 0 to cause interrupts */
|
||||
OSMR0 = OSCR + LATCH; /* set initial match */
|
||||
local_irq_restore(flags);
|
||||
cksrc_pxa_oscr0.mult =
|
||||
clocksource_hz2mult(CLOCK_TICK_RATE, cksrc_pxa_oscr0.shift);
|
||||
|
||||
/*
|
||||
* OSCR runs continuously on PXA and is not written to,
|
||||
* so we can use it as clock source directly.
|
||||
*/
|
||||
clocksource_pxa.mult =
|
||||
clocksource_hz2mult(CLOCK_TICK_RATE, clocksource_pxa.shift);
|
||||
clocksource_register(&clocksource_pxa);
|
||||
setup_irq(IRQ_OST0, &pxa_ost0_irq);
|
||||
|
||||
clocksource_register(&cksrc_pxa_oscr0);
|
||||
clockevents_register_device(&ckevt_pxa_osmr0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NO_IDLE_HZ
|
||||
static int pxa_dyn_tick_enable_disable(void)
|
||||
{
|
||||
/* nothing to do */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pxa_dyn_tick_reprogram(unsigned long ticks)
|
||||
{
|
||||
if (ticks > 1) {
|
||||
initial_match = OSMR0;
|
||||
OSMR0 = initial_match + ticks * LATCH;
|
||||
match_posponed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
pxa_dyn_tick_handler(int irq, void *dev_id)
|
||||
{
|
||||
if (match_posponed) {
|
||||
match_posponed = 0;
|
||||
OSMR0 = initial_match;
|
||||
if ( (signed long)(initial_match - OSCR) <= 8 )
|
||||
return pxa_timer_interrupt(irq, dev_id);
|
||||
}
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static struct dyn_tick_timer pxa_dyn_tick = {
|
||||
.enable = pxa_dyn_tick_enable_disable,
|
||||
.disable = pxa_dyn_tick_enable_disable,
|
||||
.reprogram = pxa_dyn_tick_reprogram,
|
||||
.handler = pxa_dyn_tick_handler,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static unsigned long osmr[4], oier;
|
||||
|
||||
@ -191,7 +189,10 @@ static void pxa_timer_resume(void)
|
||||
OIER = oier;
|
||||
|
||||
/*
|
||||
* OSMR0 is the system timer: make sure OSCR is sufficiently behind
|
||||
* OSCR0 is the system timer, which has to increase
|
||||
* monotonically until it rolls over in hardware. The value
|
||||
* (OSMR0 - LATCH) is OSCR0 at the most recent system tick,
|
||||
* which is a handy value to restore to OSCR0.
|
||||
*/
|
||||
OSCR = OSMR0 - LATCH;
|
||||
}
|
||||
@ -204,7 +205,4 @@ struct sys_timer pxa_timer = {
|
||||
.init = pxa_timer_init,
|
||||
.suspend = pxa_timer_suspend,
|
||||
.resume = pxa_timer_resume,
|
||||
#ifdef CONFIG_NO_IDLE_HZ
|
||||
.dyn_tick = &pxa_dyn_tick,
|
||||
#endif
|
||||
};
|
||||
|
@ -87,7 +87,7 @@ static void __init rpc_map_io(void)
|
||||
/*
|
||||
* Turn off floppy.
|
||||
*/
|
||||
outb(0xc, 0x3f2);
|
||||
writeb(0xc, PCIO_BASE + (0x3f2 << 2));
|
||||
|
||||
/*
|
||||
* RiscPC can't handle half-word loads and stores
|
||||
|
@ -9,6 +9,7 @@ config CPU_S3C2410
|
||||
depends on ARCH_S3C2410
|
||||
select S3C2410_CLOCK
|
||||
select S3C2410_GPIO
|
||||
select CPU_LLSERIAL_S3C2410
|
||||
select S3C2410_PM if PM
|
||||
help
|
||||
Support for S3C2410 and S3C2410A family from the S3C24XX line
|
||||
|
@ -37,7 +37,7 @@
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-clock.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
|
||||
|
@ -23,14 +23,14 @@
|
||||
#include <asm/plat-s3c24xx/cpu.h>
|
||||
#include <asm/plat-s3c24xx/dma.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-ac97.h>
|
||||
#include <asm/plat-s3c/regs-ac97.h>
|
||||
#include <asm/arch/regs-mem.h>
|
||||
#include <asm/arch/regs-lcd.h>
|
||||
#include <asm/arch/regs-sdi.h>
|
||||
#include <asm/arch/regs-iis.h>
|
||||
#include <asm/arch/regs-spi.h>
|
||||
#include <asm/plat-s3c24xx/regs-iis.h>
|
||||
#include <asm/plat-s3c24xx/regs-spi.h>
|
||||
|
||||
static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
|
||||
[DMACH_XD0] = {
|
||||
|
@ -48,7 +48,7 @@
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/arch/fb.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-lcd.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
|
||||
|
@ -36,13 +36,13 @@
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
//#include <asm/debug-ll.h>
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-mem.h>
|
||||
#include <asm/arch/regs-lcd.h>
|
||||
|
||||
#include <asm/arch/nand.h>
|
||||
#include <asm/arch/iic.h>
|
||||
#include <asm/plat-s3c/nand.h>
|
||||
#include <asm/plat-s3c/iic.h>
|
||||
#include <asm/arch/fb.h>
|
||||
|
||||
#include <linux/mtd/mtd.h>
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-lcd.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-clock.h>
|
||||
@ -38,7 +38,7 @@
|
||||
#include <asm/arch/h1940.h>
|
||||
#include <asm/arch/h1940-latch.h>
|
||||
#include <asm/arch/fb.h>
|
||||
#include <asm/arch/udc.h>
|
||||
#include <asm/plat-s3c24xx/udc.h>
|
||||
|
||||
#include <asm/plat-s3c24xx/clock.h>
|
||||
#include <asm/plat-s3c24xx/devs.h>
|
||||
|
@ -33,9 +33,9 @@
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/iic.h>
|
||||
#include <asm/plat-s3c/iic.h>
|
||||
|
||||
#include <asm/plat-s3c24xx/s3c2410.h>
|
||||
#include <asm/plat-s3c24xx/clock.h>
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
|
||||
#include <asm/plat-s3c24xx/s3c2410.h>
|
||||
|
@ -49,10 +49,10 @@
|
||||
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/leds-gpio.h>
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/fb.h>
|
||||
#include <asm/arch/nand.h>
|
||||
#include <asm/arch/udc.h>
|
||||
#include <asm/plat-s3c/nand.h>
|
||||
#include <asm/plat-s3c24xx/udc.h>
|
||||
#include <asm/arch/spi.h>
|
||||
#include <asm/arch/spi-gpio.h>
|
||||
|
||||
|
@ -47,7 +47,7 @@
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
|
||||
#include <asm/plat-s3c24xx/devs.h>
|
||||
#include <asm/plat-s3c24xx/cpu.h>
|
||||
|
@ -39,7 +39,7 @@
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/leds-gpio.h>
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <asm/arch/regs-clock.h>
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
|
||||
#include <asm/plat-s3c24xx/s3c2410.h>
|
||||
#include <asm/plat-s3c24xx/cpu.h>
|
||||
@ -40,7 +40,6 @@
|
||||
|
||||
static struct map_desc s3c2410_iodesc[] __initdata = {
|
||||
IODESC_ENT(CLKPWR),
|
||||
IODESC_ENT(LCD),
|
||||
IODESC_ENT(TIMER),
|
||||
IODESC_ENT(WATCHDOG),
|
||||
};
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-clock.h>
|
||||
#include <asm/arch/regs-mem.h>
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
|
||||
/* s3c2410_cpu_suspend
|
||||
*
|
||||
|
@ -7,6 +7,7 @@
|
||||
config CPU_S3C2412
|
||||
bool
|
||||
depends on ARCH_S3C2410
|
||||
select CPU_LLSERIAL_S3C2440
|
||||
select S3C2412_PM if PM
|
||||
select S3C2412_DMA if S3C2410_DMA
|
||||
help
|
||||
|
@ -37,7 +37,7 @@
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-clock.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
|
||||
|
@ -24,14 +24,14 @@
|
||||
#include <asm/plat-s3c24xx/dma.h>
|
||||
#include <asm/plat-s3c24xx/cpu.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-ac97.h>
|
||||
#include <asm/plat-s3c/regs-ac97.h>
|
||||
#include <asm/arch/regs-mem.h>
|
||||
#include <asm/arch/regs-lcd.h>
|
||||
#include <asm/arch/regs-sdi.h>
|
||||
#include <asm/arch/regs-iis.h>
|
||||
#include <asm/arch/regs-spi.h>
|
||||
#include <asm/plat-s3c24xx/regs-iis.h>
|
||||
#include <asm/plat-s3c24xx/regs-spi.h>
|
||||
|
||||
#define MAP(x) { (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID }
|
||||
|
||||
|
@ -32,12 +32,12 @@
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
//#include <asm/debug-ll.h>
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-lcd.h>
|
||||
|
||||
#include <asm/arch/idle.h>
|
||||
#include <asm/arch/udc.h>
|
||||
#include <asm/plat-s3c24xx/udc.h>
|
||||
#include <asm/arch/fb.h>
|
||||
|
||||
#include <asm/plat-s3c24xx/s3c2410.h>
|
||||
|
@ -33,14 +33,14 @@
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-lcd.h>
|
||||
|
||||
#include <asm/arch/idle.h>
|
||||
#include <asm/arch/fb.h>
|
||||
|
||||
#include <asm/arch/nand.h>
|
||||
#include <asm/plat-s3c/nand.h>
|
||||
|
||||
#include <asm/plat-s3c24xx/s3c2410.h>
|
||||
#include <asm/plat-s3c24xx/s3c2412.h>
|
||||
|
@ -34,12 +34,12 @@
|
||||
#include <asm/arch/idle.h>
|
||||
|
||||
#include <asm/arch/regs-clock.h>
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-power.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-gpioj.h>
|
||||
#include <asm/arch/regs-dsc.h>
|
||||
#include <asm/arch/regs-spi.h>
|
||||
#include <asm/plat-s3c24xx/regs-spi.h>
|
||||
#include <asm/arch/regs-s3c2412.h>
|
||||
|
||||
#include <asm/plat-s3c24xx/s3c2412.h>
|
||||
@ -63,7 +63,6 @@ static inline void s3c2412_init_gpio2(void)
|
||||
|
||||
static struct map_desc s3c2412_iodesc[] __initdata = {
|
||||
IODESC_ENT(CLKPWR),
|
||||
IODESC_ENT(LCD),
|
||||
IODESC_ENT(TIMER),
|
||||
IODESC_ENT(WATCHDOG),
|
||||
};
|
||||
|
@ -12,6 +12,7 @@ config CPU_S3C2440
|
||||
select S3C2410_GPIO
|
||||
select S3C2440_DMA if S3C2410_DMA
|
||||
select CPU_S3C244X
|
||||
select CPU_LLSERIAL_S3C2440
|
||||
help
|
||||
Support for S3C2440 Samsung Mobile CPU based systems.
|
||||
|
||||
|
@ -23,14 +23,14 @@
|
||||
#include <asm/plat-s3c24xx/dma.h>
|
||||
#include <asm/plat-s3c24xx/cpu.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-ac97.h>
|
||||
#include <asm/plat-s3c/regs-ac97.h>
|
||||
#include <asm/arch/regs-mem.h>
|
||||
#include <asm/arch/regs-lcd.h>
|
||||
#include <asm/arch/regs-sdi.h>
|
||||
#include <asm/arch/regs-iis.h>
|
||||
#include <asm/arch/regs-spi.h>
|
||||
#include <asm/plat-s3c24xx/regs-iis.h>
|
||||
#include <asm/plat-s3c24xx/regs-spi.h>
|
||||
|
||||
static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = {
|
||||
[DMACH_XD0] = {
|
||||
|
@ -34,11 +34,11 @@
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-mem.h>
|
||||
#include <asm/arch/regs-lcd.h>
|
||||
#include <asm/arch/nand.h>
|
||||
#include <asm/plat-s3c/nand.h>
|
||||
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/nand.h>
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
//#include <asm/debug-ll.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
|
||||
#include <asm/plat-s3c24xx/s3c2410.h>
|
||||
#include <asm/plat-s3c24xx/s3c2440.h>
|
||||
|
@ -31,11 +31,11 @@
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-mem.h>
|
||||
#include <asm/arch/regs-lcd.h>
|
||||
#include <asm/arch/nand.h>
|
||||
#include <asm/plat-s3c/nand.h>
|
||||
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/nand.h>
|
||||
|
@ -38,12 +38,12 @@
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-lcd.h>
|
||||
|
||||
#include <asm/arch/h1940.h>
|
||||
#include <asm/arch/nand.h>
|
||||
#include <asm/plat-s3c/nand.h>
|
||||
#include <asm/arch/fb.h>
|
||||
|
||||
#include <asm/plat-s3c24xx/clock.h>
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-lcd.h>
|
||||
|
||||
|
@ -11,6 +11,7 @@ config CPU_S3C2442
|
||||
select S3C2410_GPIO
|
||||
select S3C2410_PM if PM
|
||||
select CPU_S3C244X
|
||||
select CPU_LLSERIAL_S3C2440
|
||||
help
|
||||
Support for S3C2442 Samsung Mobile CPU based systems.
|
||||
|
||||
|
@ -8,6 +8,7 @@ config CPU_S3C2443
|
||||
bool
|
||||
depends on ARCH_S3C2410
|
||||
select S3C2443_DMA if S3C2410_DMA
|
||||
select CPU_LLSERIAL_S3C2440
|
||||
help
|
||||
Support for the S3C2443 SoC from the S3C24XX line
|
||||
|
||||
|
@ -24,14 +24,14 @@
|
||||
#include <asm/plat-s3c24xx/dma.h>
|
||||
#include <asm/plat-s3c24xx/cpu.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-ac97.h>
|
||||
#include <asm/plat-s3c/regs-ac97.h>
|
||||
#include <asm/arch/regs-mem.h>
|
||||
#include <asm/arch/regs-lcd.h>
|
||||
#include <asm/arch/regs-sdi.h>
|
||||
#include <asm/arch/regs-iis.h>
|
||||
#include <asm/arch/regs-spi.h>
|
||||
#include <asm/plat-s3c24xx/regs-iis.h>
|
||||
#include <asm/plat-s3c24xx/regs-spi.h>
|
||||
|
||||
#define MAP(x) { \
|
||||
[0] = (x) | DMA_CH_VALID, \
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-lcd.h>
|
||||
|
||||
|
@ -101,6 +101,16 @@ config SA1100_JORNADA720
|
||||
handheld computer. See <http://www.hp.com/jornada/products/720>
|
||||
for details.
|
||||
|
||||
config SA1100_JORNADA720_SSP
|
||||
bool "HP Jornada 720 Extended SSP driver"
|
||||
select SA1100_SSP
|
||||
depends on SA1100_JORNADA720
|
||||
help
|
||||
Say Y here if you have a HP Jornada 7xx handheld computer and you
|
||||
want to access devices connected to the MCU. Those include the
|
||||
keyboard, touchscreen, backlight and battery. This driver also activates
|
||||
the generic SSP which it extends.
|
||||
|
||||
config SA1100_HACKKIT
|
||||
bool "HackKit Core CPU Board"
|
||||
help
|
||||
@ -145,8 +155,7 @@ config SA1100_SSP
|
||||
help
|
||||
Say Y here to enable support for the generic PIO SSP driver.
|
||||
This isn't for audio support, but for attached sensors and
|
||||
other devices, eg for BadgePAD 4 sensor support, or Jornada
|
||||
720 touchscreen support.
|
||||
other devices, eg for BadgePAD 4 sensor support.
|
||||
|
||||
config H3600_SLEEVE
|
||||
tristate "Compaq iPAQ Handheld sleeve support"
|
||||
|
@ -31,6 +31,7 @@ obj-$(CONFIG_SA1100_HACKKIT) += hackkit.o
|
||||
led-$(CONFIG_SA1100_HACKKIT) += leds-hackkit.o
|
||||
|
||||
obj-$(CONFIG_SA1100_JORNADA720) += jornada720.o
|
||||
obj-$(CONFIG_SA1100_JORNADA720_SSP) += jornada720_ssp.o
|
||||
|
||||
obj-$(CONFIG_SA1100_LART) += lart.o
|
||||
led-$(CONFIG_SA1100_LART) += leds-lart.o
|
||||
@ -51,3 +52,4 @@ obj-$(CONFIG_LEDS) += $(led-y)
|
||||
# Miscelaneous functions
|
||||
obj-$(CONFIG_PM) += pm.o sleep.o
|
||||
obj-$(CONFIG_SA1100_SSP) += ssp.o
|
||||
|
||||
|
201
arch/arm/mach-sa1100/jornada720_ssp.c
Normal file
201
arch/arm/mach-sa1100/jornada720_ssp.c
Normal file
@ -0,0 +1,201 @@
|
||||
/**
|
||||
* arch/arm/mac-sa1100/jornada720_ssp.c
|
||||
*
|
||||
* Copyright (C) 2006/2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com>
|
||||
* Copyright (C) 2006 Filip Zyzniewski <filip.zyzniewski@tefnet.pl>
|
||||
*
|
||||
* 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 driver for the HP Jornada 710/720/728
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/hardware/ssp.h>
|
||||
#include <asm/arch/jornada720.h>
|
||||
|
||||
static DEFINE_SPINLOCK(jornada_ssp_lock);
|
||||
static unsigned long jornada_ssp_flags;
|
||||
|
||||
/**
|
||||
* jornada_ssp_reverse - reverses input byte
|
||||
*
|
||||
* we need to reverse all data we recieve from the mcu due to its physical location
|
||||
* returns : 01110111 -> 11101110
|
||||
*/
|
||||
u8 inline jornada_ssp_reverse(u8 byte)
|
||||
{
|
||||
return
|
||||
((0x80 & byte) >> 7) |
|
||||
((0x40 & byte) >> 5) |
|
||||
((0x20 & byte) >> 3) |
|
||||
((0x10 & byte) >> 1) |
|
||||
((0x08 & byte) << 1) |
|
||||
((0x04 & byte) << 3) |
|
||||
((0x02 & byte) << 5) |
|
||||
((0x01 & byte) << 7);
|
||||
};
|
||||
EXPORT_SYMBOL(jornada_ssp_reverse);
|
||||
|
||||
/**
|
||||
* jornada_ssp_byte - waits for ready ssp bus and sends byte
|
||||
*
|
||||
* waits for fifo buffer to clear and then transmits, if it doesn't then we will
|
||||
* timeout after <timeout> rounds. Needs mcu running before its called.
|
||||
*
|
||||
* returns : %mcu output on success
|
||||
* : %-ETIMEOUT on timeout
|
||||
*/
|
||||
int jornada_ssp_byte(u8 byte)
|
||||
{
|
||||
int timeout = 400000;
|
||||
u16 ret;
|
||||
|
||||
while ((GPLR & GPIO_GPIO10)) {
|
||||
if (!--timeout) {
|
||||
printk(KERN_WARNING "SSP: timeout while waiting for transmit\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
ret = jornada_ssp_reverse(byte) << 8;
|
||||
|
||||
ssp_write_word(ret);
|
||||
ssp_read_word(&ret);
|
||||
|
||||
return jornada_ssp_reverse(ret);
|
||||
};
|
||||
EXPORT_SYMBOL(jornada_ssp_byte);
|
||||
|
||||
/**
|
||||
* jornada_ssp_inout - decide if input is command or trading byte
|
||||
*
|
||||
* returns : (jornada_ssp_byte(byte)) on success
|
||||
* : %-ETIMEOUT on timeout failure
|
||||
*/
|
||||
int jornada_ssp_inout(u8 byte)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
/* true means command byte */
|
||||
if (byte != TXDUMMY) {
|
||||
ret = jornada_ssp_byte(byte);
|
||||
/* Proper return to commands is TxDummy */
|
||||
if (ret != TXDUMMY) {
|
||||
for (i = 0; i < 256; i++)/* flushing bus */
|
||||
if (jornada_ssp_byte(TXDUMMY) == -1)
|
||||
break;
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
} else /* Exchange TxDummy for data */
|
||||
ret = jornada_ssp_byte(TXDUMMY);
|
||||
|
||||
return ret;
|
||||
};
|
||||
EXPORT_SYMBOL(jornada_ssp_inout);
|
||||
|
||||
/**
|
||||
* jornada_ssp_start - enable mcu
|
||||
*
|
||||
*/
|
||||
int jornada_ssp_start()
|
||||
{
|
||||
spin_lock_irqsave(&jornada_ssp_lock, jornada_ssp_flags);
|
||||
GPCR = GPIO_GPIO25;
|
||||
udelay(50);
|
||||
return 0;
|
||||
};
|
||||
EXPORT_SYMBOL(jornada_ssp_start);
|
||||
|
||||
/**
|
||||
* jornada_ssp_end - disable mcu and turn off lock
|
||||
*
|
||||
*/
|
||||
int jornada_ssp_end()
|
||||
{
|
||||
GPSR = GPIO_GPIO25;
|
||||
spin_unlock_irqrestore(&jornada_ssp_lock, jornada_ssp_flags);
|
||||
return 0;
|
||||
};
|
||||
EXPORT_SYMBOL(jornada_ssp_end);
|
||||
|
||||
static int __init jornada_ssp_probe(struct platform_device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
GPSR = GPIO_GPIO25;
|
||||
|
||||
ret = ssp_init();
|
||||
|
||||
/* worked fine, lets not bother with anything else */
|
||||
if (!ret) {
|
||||
printk(KERN_INFO "SSP: device initialized with irq\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
printk(KERN_WARNING "SSP: initialization failed, trying non-irq solution \n");
|
||||
|
||||
/* init of Serial 4 port */
|
||||
Ser4MCCR0 = 0;
|
||||
Ser4SSCR0 = 0x0387;
|
||||
Ser4SSCR1 = 0x18;
|
||||
|
||||
/* clear out any left over data */
|
||||
ssp_flush();
|
||||
|
||||
/* enable MCU */
|
||||
jornada_ssp_start();
|
||||
|
||||
/* see if return value makes sense */
|
||||
ret = jornada_ssp_inout(GETBRIGHTNESS);
|
||||
|
||||
/* seems like it worked, just feed it with TxDummy to get rid of data */
|
||||
if (ret == TxDummy)
|
||||
jornada_ssp_inout(TXDUMMY);
|
||||
|
||||
jornada_ssp_end();
|
||||
|
||||
/* failed, lets just kill everything */
|
||||
if (ret == -ETIMEDOUT) {
|
||||
printk(KERN_WARNING "SSP: attempts failed, bailing\n");
|
||||
ssp_exit();
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* all fine */
|
||||
printk(KERN_INFO "SSP: device initialized\n");
|
||||
return 0;
|
||||
};
|
||||
|
||||
static int jornada_ssp_remove(struct platform_device *dev)
|
||||
{
|
||||
/* Note that this doesnt actually remove the driver, since theres nothing to remove
|
||||
* It just makes sure everything is turned off */
|
||||
GPSR = GPIO_GPIO25;
|
||||
ssp_exit();
|
||||
return 0;
|
||||
};
|
||||
|
||||
struct platform_driver jornadassp_driver = {
|
||||
.probe = jornada_ssp_probe,
|
||||
.remove = jornada_ssp_remove,
|
||||
.driver = {
|
||||
.name = "jornada_ssp",
|
||||
},
|
||||
};
|
||||
|
||||
static int __init jornada_ssp_init(void)
|
||||
{
|
||||
return platform_driver_register(&jornadassp_driver);
|
||||
}
|
@ -292,6 +292,8 @@ static struct platform_device *devices[] __initdata = {
|
||||
&smc91x_device,
|
||||
};
|
||||
|
||||
extern void sa1110_mb_disable(void);
|
||||
|
||||
static int __init neponset_init(void)
|
||||
{
|
||||
platform_driver_register(&neponset_device_driver);
|
||||
|
@ -345,13 +345,14 @@ config CPU_XSC3
|
||||
# ARMv6
|
||||
config CPU_V6
|
||||
bool "Support ARM V6 processor"
|
||||
depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB || ARCH_OMAP2
|
||||
depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB || ARCH_OMAP2 || ARCH_MX3
|
||||
default y if ARCH_MX3
|
||||
select CPU_32v6
|
||||
select CPU_ABRT_EV6
|
||||
select CPU_CACHE_V6
|
||||
select CPU_CACHE_VIPT
|
||||
select CPU_CP15_MMU
|
||||
select CPU_HAS_ASID
|
||||
select CPU_HAS_ASID if MMU
|
||||
select CPU_COPY_V6 if MMU
|
||||
select CPU_TLB_V6 if MMU
|
||||
|
||||
@ -359,7 +360,7 @@ config CPU_V6
|
||||
config CPU_32v6K
|
||||
bool "Support ARM V6K processor extensions" if !SMP
|
||||
depends on CPU_V6
|
||||
default y if SMP
|
||||
default y if SMP && !ARCH_MX3
|
||||
help
|
||||
Say Y here if your ARMv6 processor supports the 'K' extension.
|
||||
This enables the kernel to use some instructions not present
|
||||
@ -377,7 +378,7 @@ config CPU_V7
|
||||
select CPU_CACHE_V7
|
||||
select CPU_CACHE_VIPT
|
||||
select CPU_CP15_MMU
|
||||
select CPU_HAS_ASID
|
||||
select CPU_HAS_ASID if MMU
|
||||
select CPU_COPY_V6 if MMU
|
||||
select CPU_TLB_V7 if MMU
|
||||
|
||||
@ -405,6 +406,7 @@ config CPU_32v5
|
||||
|
||||
config CPU_32v6
|
||||
bool
|
||||
select TLS_REG_EMUL if !CPU_32v6K && !MMU
|
||||
|
||||
config CPU_32v7
|
||||
bool
|
||||
@ -598,7 +600,7 @@ config CPU_DCACHE_SIZE
|
||||
|
||||
config CPU_DCACHE_WRITETHROUGH
|
||||
bool "Force write through D-cache"
|
||||
depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_V6) && !CPU_DCACHE_DISABLE
|
||||
depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020) && !CPU_DCACHE_DISABLE
|
||||
default y if CPU_ARM925T
|
||||
help
|
||||
Say Y here to use the data cache in writethrough mode. Unless you
|
||||
@ -611,12 +613,6 @@ config CPU_CACHE_ROUND_ROBIN
|
||||
Say Y here to use the predictable round-robin cache replacement
|
||||
policy. Unless you specifically require this or are unsure, say N.
|
||||
|
||||
config CPU_L2CACHE_DISABLE
|
||||
bool "Disable level 2 cache"
|
||||
depends on CPU_V7
|
||||
help
|
||||
Say Y here to disable the level 2 cache. If unsure, say N.
|
||||
|
||||
config CPU_BPREDICT_DISABLE
|
||||
bool "Disable branch prediction"
|
||||
depends on CPU_ARM1020 || CPU_V6 || CPU_XSC3 || CPU_V7
|
||||
|
@ -17,6 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/io.h>
|
||||
@ -25,14 +26,19 @@
|
||||
#define CACHE_LINE_SIZE 32
|
||||
|
||||
static void __iomem *l2x0_base;
|
||||
static DEFINE_SPINLOCK(l2x0_lock);
|
||||
|
||||
static inline void sync_writel(unsigned long val, unsigned long reg,
|
||||
unsigned long complete_mask)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&l2x0_lock, flags);
|
||||
writel(val, l2x0_base + reg);
|
||||
/* wait for the operation to complete */
|
||||
while (readl(l2x0_base + reg) & complete_mask)
|
||||
;
|
||||
spin_unlock_irqrestore(&l2x0_lock, flags);
|
||||
}
|
||||
|
||||
static inline void cache_sync(void)
|
||||
|
@ -114,6 +114,10 @@ static void __init early_cachepolicy(char **p)
|
||||
}
|
||||
if (i == ARRAY_SIZE(cache_policies))
|
||||
printk(KERN_ERR "ERROR: unknown or unsupported cache policy\n");
|
||||
if (cpu_architecture() >= CPU_ARCH_ARMv6) {
|
||||
printk(KERN_WARNING "Only cachepolicy=writeback supported on ARMv6 and later\n");
|
||||
cachepolicy = CPOLICY_WRITEBACK;
|
||||
}
|
||||
flush_cache_all();
|
||||
set_cr(cr_alignment);
|
||||
}
|
||||
@ -252,13 +256,15 @@ static void __init build_mem_type_table(void)
|
||||
int cpu_arch = cpu_architecture();
|
||||
int i;
|
||||
|
||||
if (cpu_arch < CPU_ARCH_ARMv6) {
|
||||
#if defined(CONFIG_CPU_DCACHE_DISABLE)
|
||||
if (cachepolicy > CPOLICY_BUFFERED)
|
||||
cachepolicy = CPOLICY_BUFFERED;
|
||||
if (cachepolicy > CPOLICY_BUFFERED)
|
||||
cachepolicy = CPOLICY_BUFFERED;
|
||||
#elif defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
|
||||
if (cachepolicy > CPOLICY_WRITETHROUGH)
|
||||
cachepolicy = CPOLICY_WRITETHROUGH;
|
||||
if (cachepolicy > CPOLICY_WRITETHROUGH)
|
||||
cachepolicy = CPOLICY_WRITETHROUGH;
|
||||
#endif
|
||||
}
|
||||
if (cpu_arch < CPU_ARCH_ARMv5) {
|
||||
if (cachepolicy >= CPOLICY_WRITEALLOC)
|
||||
cachepolicy = CPOLICY_WRITEBACK;
|
||||
|
@ -31,12 +31,14 @@ EXPORT_SYMBOL(__cpuc_coherent_kern_range);
|
||||
EXPORT_SYMBOL(cpu_cache);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
#ifndef MULTI_USER
|
||||
EXPORT_SYMBOL(__cpu_clear_user_page);
|
||||
EXPORT_SYMBOL(__cpu_copy_user_page);
|
||||
#else
|
||||
EXPORT_SYMBOL(cpu_user);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* No module should need to touch the TLB (and currently
|
||||
|
@ -77,6 +77,7 @@ ENTRY(cpu_v7_dcache_clean_area)
|
||||
* - we are not using split page tables
|
||||
*/
|
||||
ENTRY(cpu_v7_switch_mm)
|
||||
#ifdef CONFIG_MMU
|
||||
mov r2, #0
|
||||
ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id
|
||||
orr r0, r0, #TTB_RGN_OC_WB @ mark PTWs outer cacheable, WB
|
||||
@ -86,6 +87,7 @@ ENTRY(cpu_v7_switch_mm)
|
||||
isb
|
||||
mcr p15, 0, r1, c13, c0, 1 @ set context ID
|
||||
isb
|
||||
#endif
|
||||
mov pc, lr
|
||||
|
||||
/*
|
||||
@ -109,6 +111,7 @@ ENTRY(cpu_v7_switch_mm)
|
||||
* 1111 0 1 1 r/w r/w
|
||||
*/
|
||||
ENTRY(cpu_v7_set_pte_ext)
|
||||
#ifdef CONFIG_MMU
|
||||
str r1, [r0], #-2048 @ linux version
|
||||
|
||||
bic r3, r1, #0x000003f0
|
||||
@ -136,6 +139,7 @@ ENTRY(cpu_v7_set_pte_ext)
|
||||
|
||||
str r3, [r0]
|
||||
mcr p15, 0, r0, c7, c10, 1 @ flush_pte
|
||||
#endif
|
||||
mov pc, lr
|
||||
|
||||
cpu_v7_name:
|
||||
@ -169,6 +173,7 @@ __v7_setup:
|
||||
mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate
|
||||
#endif
|
||||
dsb
|
||||
#ifdef CONFIG_MMU
|
||||
mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs
|
||||
mcr p15, 0, r10, c2, c0, 2 @ TTB control register
|
||||
orr r4, r4, #TTB_RGN_OC_WB @ mark PTWs outer cacheable, WB
|
||||
@ -176,21 +181,12 @@ __v7_setup:
|
||||
mcr p15, 0, r4, c2, c0, 1 @ load TTB1
|
||||
mov r10, #0x1f @ domains 0, 1 = manager
|
||||
mcr p15, 0, r10, c3, c0, 0 @ load domain access register
|
||||
#ifndef CONFIG_CPU_L2CACHE_DISABLE
|
||||
@ L2 cache configuration in the L2 aux control register
|
||||
mrc p15, 1, r10, c9, c0, 2
|
||||
bic r10, r10, #(1 << 16) @ L2 outer cache
|
||||
mcr p15, 1, r10, c9, c0, 2
|
||||
@ L2 cache is enabled in the aux control register
|
||||
mrc p15, 0, r10, c1, c0, 1
|
||||
orr r10, r10, #2
|
||||
mcr p15, 0, r10, c1, c0, 1
|
||||
#endif
|
||||
mrc p15, 0, r0, c1, c0, 0 @ read control register
|
||||
ldr r10, cr1_clear @ get mask for bits to clear
|
||||
bic r0, r0, r10 @ clear bits them
|
||||
ldr r10, cr1_set @ get mask for bits to set
|
||||
orr r0, r0, r10 @ set them
|
||||
adr r5, v7_crval
|
||||
ldmia r5, {r5, r6}
|
||||
mrc p15, 0, r0, c1, c0, 0 @ read control register
|
||||
bic r0, r0, r5 @ clear bits them
|
||||
orr r0, r0, r6 @ set them
|
||||
mov pc, lr @ return to head.S:__ret
|
||||
|
||||
/*
|
||||
@ -199,12 +195,9 @@ __v7_setup:
|
||||
* rrrr rrrx xxx0 0101 xxxx xxxx x111 xxxx < forced
|
||||
* 0 110 0011 1.00 .111 1101 < we want
|
||||
*/
|
||||
.type cr1_clear, #object
|
||||
.type cr1_set, #object
|
||||
cr1_clear:
|
||||
.word 0x0120c302
|
||||
cr1_set:
|
||||
.word 0x00c0387d
|
||||
.type v7_crval, #object
|
||||
v7_crval:
|
||||
crval clear=0x0120c302, mmuset=0x00c0387d, ucset=0x00c0187c
|
||||
|
||||
__v7_setup_stack:
|
||||
.space 4 * 11 @ 11 registers
|
||||
|
@ -78,6 +78,13 @@ static struct irqaction iop_timer_irq = {
|
||||
.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
|
||||
};
|
||||
|
||||
static unsigned long iop_tick_rate;
|
||||
unsigned long get_iop_tick_rate(void)
|
||||
{
|
||||
return iop_tick_rate;
|
||||
}
|
||||
EXPORT_SYMBOL(get_iop_tick_rate);
|
||||
|
||||
void __init iop_init_time(unsigned long tick_rate)
|
||||
{
|
||||
u32 timer_ctl;
|
||||
@ -85,6 +92,7 @@ void __init iop_init_time(unsigned long tick_rate)
|
||||
ticks_per_jiffy = (tick_rate + HZ/2) / HZ;
|
||||
ticks_per_usec = tick_rate / 1000000;
|
||||
next_jiffy_time = 0xffffffff;
|
||||
iop_tick_rate = tick_rate;
|
||||
|
||||
timer_ctl = IOP_TMR_EN | IOP_TMR_PRIVILEGED |
|
||||
IOP_TMR_RELOAD | IOP_TMR_RATIO_1_1;
|
||||
|
20
arch/arm/plat-mxc/Kconfig
Normal file
20
arch/arm/plat-mxc/Kconfig
Normal file
@ -0,0 +1,20 @@
|
||||
if ARCH_MXC
|
||||
|
||||
menu "Freescale MXC Implementations"
|
||||
|
||||
choice
|
||||
prompt "MXC/iMX System Type"
|
||||
default 0
|
||||
|
||||
config ARCH_MX3
|
||||
bool "MX3-based"
|
||||
help
|
||||
This enables support for systems based on the Freescale i.MX3 family
|
||||
|
||||
endchoice
|
||||
|
||||
source "arch/arm/mach-mx3/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
endif
|
10
arch/arm/plat-mxc/Makefile
Normal file
10
arch/arm/plat-mxc/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
#
|
||||
# Makefile for the linux kernel.
|
||||
#
|
||||
|
||||
# Common support
|
||||
obj-y := irq.o
|
||||
|
||||
obj-m :=
|
||||
obj-n :=
|
||||
obj- :=
|
83
arch/arm/plat-mxc/irq.c
Normal file
83
arch/arm/plat-mxc/irq.c
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mach/irq.h>
|
||||
#include <asm/arch/common.h>
|
||||
|
||||
/*!
|
||||
* Disable interrupt number "irq" in the AVIC
|
||||
*
|
||||
* @param irq interrupt source number
|
||||
*/
|
||||
static void mxc_mask_irq(unsigned int irq)
|
||||
{
|
||||
__raw_writel(irq, AVIC_INTDISNUM);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Enable interrupt number "irq" in the AVIC
|
||||
*
|
||||
* @param irq interrupt source number
|
||||
*/
|
||||
static void mxc_unmask_irq(unsigned int irq)
|
||||
{
|
||||
__raw_writel(irq, AVIC_INTENNUM);
|
||||
}
|
||||
|
||||
static struct irq_chip mxc_avic_chip = {
|
||||
.mask_ack = mxc_mask_irq,
|
||||
.mask = mxc_mask_irq,
|
||||
.unmask = mxc_unmask_irq,
|
||||
};
|
||||
|
||||
/*!
|
||||
* This function initializes the AVIC hardware and disables all the
|
||||
* interrupts. It registers the interrupt enable and disable functions
|
||||
* to the kernel for each interrupt source.
|
||||
*/
|
||||
void __init mxc_init_irq(void)
|
||||
{
|
||||
int i;
|
||||
u32 reg;
|
||||
|
||||
/* put the AVIC into the reset value with
|
||||
* all interrupts disabled
|
||||
*/
|
||||
__raw_writel(0, AVIC_INTCNTL);
|
||||
__raw_writel(0x1f, AVIC_NIMASK);
|
||||
|
||||
/* disable all interrupts */
|
||||
__raw_writel(0, AVIC_INTENABLEH);
|
||||
__raw_writel(0, AVIC_INTENABLEL);
|
||||
|
||||
/* all IRQ no FIQ */
|
||||
__raw_writel(0, AVIC_INTTYPEH);
|
||||
__raw_writel(0, AVIC_INTTYPEL);
|
||||
for (i = 0; i < MXC_MAX_INT_LINES; i++) {
|
||||
set_irq_chip(i, &mxc_avic_chip);
|
||||
set_irq_handler(i, handle_level_irq);
|
||||
set_irq_flags(i, IRQF_VALID);
|
||||
}
|
||||
|
||||
/* Set WDOG2's interrupt the highest priority level (bit 28-31) */
|
||||
reg = __raw_readl(AVIC_NIPRIORITY6);
|
||||
reg |= (0xF << 28);
|
||||
__raw_writel(reg, AVIC_NIPRIORITY6);
|
||||
|
||||
printk(KERN_INFO "MXC IRQ initialized\n");
|
||||
}
|
104
arch/arm/plat-s3c/Kconfig
Normal file
104
arch/arm/plat-s3c/Kconfig
Normal file
@ -0,0 +1,104 @@
|
||||
# arch/arm/plat-s3c/Kconfig
|
||||
#
|
||||
# Copyright 2007 Simtec Electronics
|
||||
#
|
||||
# Licensed under GPLv2
|
||||
|
||||
config PLAT_S3C
|
||||
bool
|
||||
depends on ARCH_S3C2410
|
||||
default y if ARCH_S3C2410
|
||||
select NO_IOPORT
|
||||
help
|
||||
Base platform code for any Samsung S3C device
|
||||
|
||||
# low-level serial option nodes
|
||||
|
||||
config CPU_LLSERIAL_S3C2410_ONLY
|
||||
bool
|
||||
depends on ARCH_S3C2410
|
||||
default y if CPU_LLSERIAL_S3C2410 && !CPU_LLSERIAL_S3C2440
|
||||
|
||||
config CPU_LLSERIAL_S3C2440_ONLY
|
||||
bool
|
||||
depends on ARCH_S3C2410
|
||||
default y if CPU_LLSERIAL_S3C2440 && !CPU_LLSERIAL_S3C2410
|
||||
|
||||
config CPU_LLSERIAL_S3C2410
|
||||
bool
|
||||
depends on ARCH_S3C2410
|
||||
help
|
||||
Selected if there is an S3C2410 (or register compatible) serial
|
||||
low-level implementation needed
|
||||
|
||||
config CPU_LLSERIAL_S3C2440
|
||||
bool
|
||||
depends on ARCH_S3C2410
|
||||
help
|
||||
Selected if there is an S3C2440 (or register compatible) serial
|
||||
low-level implementation needed
|
||||
|
||||
# boot configurations
|
||||
|
||||
comment "Boot options"
|
||||
|
||||
config S3C_BOOT_WATCHDOG
|
||||
bool "S3C Initialisation watchdog"
|
||||
depends on PLAT_S3C && S3C2410_WATCHDOG
|
||||
help
|
||||
Say y to enable the watchdog during the kernel decompression
|
||||
stage. If the kernel fails to uncompress, then the watchdog
|
||||
will trigger a reset and the system should restart.
|
||||
|
||||
config S3C_BOOT_ERROR_RESET
|
||||
bool "S3C Reboot on decompression error"
|
||||
depends on PLAT_S3C
|
||||
help
|
||||
Say y here to use the watchdog to reset the system if the
|
||||
kernel decompressor detects an error during decompression.
|
||||
|
||||
comment "Power management"
|
||||
|
||||
config S3C2410_PM_DEBUG
|
||||
bool "S3C2410 PM Suspend debug"
|
||||
depends on PLAT_S3C && PM
|
||||
help
|
||||
Say Y here if you want verbose debugging from the PM Suspend and
|
||||
Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
|
||||
for more information.
|
||||
|
||||
config S3C2410_PM_CHECK
|
||||
bool "S3C2410 PM Suspend Memory CRC"
|
||||
depends on PLAT_S3C && PM && CRC32
|
||||
help
|
||||
Enable the PM code's memory area checksum over sleep. This option
|
||||
will generate CRCs of all blocks of memory, and store them before
|
||||
going to sleep. The blocks are then checked on resume for any
|
||||
errors.
|
||||
|
||||
Note, this can take several seconds depending on memory size
|
||||
and CPU speed.
|
||||
|
||||
See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
|
||||
|
||||
config S3C2410_PM_CHECK_CHUNKSIZE
|
||||
int "S3C2410 PM Suspend CRC Chunksize (KiB)"
|
||||
depends on PLAT_S3C && PM && S3C2410_PM_CHECK
|
||||
default 64
|
||||
help
|
||||
Set the chunksize in Kilobytes of the CRC for checking memory
|
||||
corruption over suspend and resume. A smaller value will mean that
|
||||
the CRC data block will take more memory, but wil identify any
|
||||
faults with better precision.
|
||||
|
||||
See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
|
||||
|
||||
config S3C_LOWLEVEL_UART_PORT
|
||||
int "S3C UART to use for low-level messages"
|
||||
depends on PLAT_S3C
|
||||
default 0
|
||||
help
|
||||
Choice of which UART port to use for the low-level messages,
|
||||
such as the `Uncompressing...` at start time. The value of
|
||||
this configuration should be between zero and two. The port
|
||||
must have been initialised by the boot-loader before use.
|
@ -10,7 +10,7 @@ config PLAT_S3C24XX
|
||||
default y if ARCH_S3C2410
|
||||
select NO_IOPORT
|
||||
help
|
||||
Base platform code for any Samsung S3C device
|
||||
Base platform code for any Samsung S3C24XX device
|
||||
|
||||
if PLAT_S3C24XX
|
||||
|
||||
@ -26,64 +26,6 @@ config PM_SIMTEC
|
||||
Common power management code for systems that are
|
||||
compatible with the Simtec style of power management
|
||||
|
||||
config S3C2410_BOOT_WATCHDOG
|
||||
bool "S3C2410 Initialisation watchdog"
|
||||
depends on ARCH_S3C2410 && S3C2410_WATCHDOG
|
||||
help
|
||||
Say y to enable the watchdog during the kernel decompression
|
||||
stage. If the kernel fails to uncompress, then the watchdog
|
||||
will trigger a reset and the system should restart.
|
||||
|
||||
config S3C2410_BOOT_ERROR_RESET
|
||||
bool "S3C2410 Reboot on decompression error"
|
||||
depends on ARCH_S3C2410
|
||||
help
|
||||
Say y here to use the watchdog to reset the system if the
|
||||
kernel decompressor detects an error during decompression.
|
||||
|
||||
config S3C2410_PM_DEBUG
|
||||
bool "S3C2410 PM Suspend debug"
|
||||
depends on ARCH_S3C2410 && PM
|
||||
help
|
||||
Say Y here if you want verbose debugging from the PM Suspend and
|
||||
Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
|
||||
for more information.
|
||||
|
||||
config S3C2410_PM_CHECK
|
||||
bool "S3C2410 PM Suspend Memory CRC"
|
||||
depends on ARCH_S3C2410 && PM && CRC32
|
||||
help
|
||||
Enable the PM code's memory area checksum over sleep. This option
|
||||
will generate CRCs of all blocks of memory, and store them before
|
||||
going to sleep. The blocks are then checked on resume for any
|
||||
errors.
|
||||
|
||||
Note, this can take several seconds depending on memory size
|
||||
and CPU speed.
|
||||
|
||||
See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
|
||||
|
||||
config S3C2410_PM_CHECK_CHUNKSIZE
|
||||
int "S3C2410 PM Suspend CRC Chunksize (KiB)"
|
||||
depends on ARCH_S3C2410 && PM && S3C2410_PM_CHECK
|
||||
default 64
|
||||
help
|
||||
Set the chunksize in Kilobytes of the CRC for checking memory
|
||||
corruption over suspend and resume. A smaller value will mean that
|
||||
the CRC data block will take more memory, but wil identify any
|
||||
faults with better precision.
|
||||
|
||||
See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
|
||||
|
||||
config S3C2410_LOWLEVEL_UART_PORT
|
||||
int "S3C2410 UART to use for low-level messages"
|
||||
default 0
|
||||
help
|
||||
Choice of which UART port to use for the low-level messages,
|
||||
such as the `Uncompressing...` at start time. The value of
|
||||
this configuration should be between zero and two. The port
|
||||
must have been initialised by the boot-loader before use.
|
||||
|
||||
config S3C2410_DMA
|
||||
bool "S3C2410 DMA support"
|
||||
depends on ARCH_S3C2410
|
||||
|
@ -38,7 +38,7 @@
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/leds-gpio.h>
|
||||
|
||||
#include <asm/arch/nand.h>
|
||||
#include <asm/plat-s3c/nand.h>
|
||||
|
||||
#include <asm/plat-s3c24xx/common-smdk.h>
|
||||
#include <asm/plat-s3c24xx/devs.h>
|
||||
|
@ -38,7 +38,7 @@
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
|
||||
#include <asm/plat-s3c24xx/cpu.h>
|
||||
#include <asm/plat-s3c24xx/devs.h>
|
||||
|
@ -28,12 +28,12 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/arch/udc.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/plat-s3c24xx/udc.h>
|
||||
|
||||
#include <asm/plat-s3c24xx/devs.h>
|
||||
#include <asm/plat-s3c24xx/cpu.h>
|
||||
#include <asm/arch/regs-spi.h>
|
||||
#include <asm/plat-s3c24xx/regs-spi.h>
|
||||
|
||||
/* Serial port registrations */
|
||||
|
||||
|
@ -40,7 +40,7 @@
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-clock.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-mem.h>
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <asm/arch/regs-clock.h>
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-gpioj.h>
|
||||
#include <asm/arch/regs-dsc.h>
|
||||
@ -47,7 +47,6 @@ static struct map_desc s3c244x_iodesc[] __initdata = {
|
||||
IODESC_ENT(CLKPWR),
|
||||
IODESC_ENT(TIMER),
|
||||
IODESC_ENT(WATCHDOG),
|
||||
IODESC_ENT(LCD),
|
||||
};
|
||||
|
||||
/* uart initialisation */
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-clock.h>
|
||||
#include <asm/arch/regs-mem.h>
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/plat-s3c/regs-serial.h>
|
||||
|
||||
/* CONFIG_DEBUG_RESUME is dangerous if your bootloader does not
|
||||
* reset the UART configuration, only enable if you really need this!
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/arch/map.h>
|
||||
#include <asm/arch/regs-timer.h>
|
||||
#include <asm/plat-s3c/regs-timer.h>
|
||||
#include <asm/arch/regs-irq.h>
|
||||
#include <asm/mach/time.h>
|
||||
|
||||
|
@ -74,14 +74,14 @@ vfp_support_entry:
|
||||
|
||||
VFPFMRX r1, FPEXC @ Is the VFP enabled?
|
||||
DBGSTR1 "fpexc %08x", r1
|
||||
tst r1, #FPEXC_ENABLE
|
||||
tst r1, #FPEXC_EN
|
||||
bne look_for_VFP_exceptions @ VFP is already enabled
|
||||
|
||||
DBGSTR1 "enable %x", r10
|
||||
ldr r3, last_VFP_context_address
|
||||
orr r1, r1, #FPEXC_ENABLE @ user FPEXC has the enable bit set
|
||||
orr r1, r1, #FPEXC_EN @ user FPEXC has the enable bit set
|
||||
ldr r4, [r3, r11, lsl #2] @ last_VFP_context pointer
|
||||
bic r5, r1, #FPEXC_EXCEPTION @ make sure exceptions are disabled
|
||||
bic r5, r1, #FPEXC_EX @ make sure exceptions are disabled
|
||||
cmp r4, r10
|
||||
beq check_for_exception @ we are returning to the same
|
||||
@ process, so the registers are
|
||||
@ -124,7 +124,7 @@ no_old_VFP_process:
|
||||
VFPFMXR FPSCR, r5 @ restore status
|
||||
|
||||
check_for_exception:
|
||||
tst r1, #FPEXC_EXCEPTION
|
||||
tst r1, #FPEXC_EX
|
||||
bne process_exception @ might as well handle the pending
|
||||
@ exception before retrying branch
|
||||
@ out before setting an FPEXC that
|
||||
@ -136,10 +136,10 @@ check_for_exception:
|
||||
|
||||
|
||||
look_for_VFP_exceptions:
|
||||
tst r1, #FPEXC_EXCEPTION
|
||||
tst r1, #FPEXC_EX
|
||||
bne process_exception
|
||||
VFPFMRX r5, FPSCR
|
||||
tst r5, #FPSCR_IXE @ IXE doesn't set FPEXC_EXCEPTION !
|
||||
tst r5, #FPSCR_IXE @ IXE doesn't set FPEXC_EX !
|
||||
bne process_exception
|
||||
|
||||
@ Fall into hand on to next handler - appropriate coproc instr
|
||||
|
@ -53,7 +53,7 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
|
||||
* case the thread migrates to a different CPU. The
|
||||
* restoring is done lazily.
|
||||
*/
|
||||
if ((fpexc & FPEXC_ENABLE) && last_VFP_context[cpu]) {
|
||||
if ((fpexc & FPEXC_EN) && last_VFP_context[cpu]) {
|
||||
vfp_save_state(last_VFP_context[cpu], fpexc);
|
||||
last_VFP_context[cpu]->hard.cpu = cpu;
|
||||
}
|
||||
@ -70,7 +70,7 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
|
||||
* Always disable VFP so we can lazily save/restore the
|
||||
* old state.
|
||||
*/
|
||||
fmxr(FPEXC, fpexc & ~FPEXC_ENABLE);
|
||||
fmxr(FPEXC, fpexc & ~FPEXC_EN);
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
@ -81,13 +81,13 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
|
||||
*/
|
||||
memset(vfp, 0, sizeof(union vfp_state));
|
||||
|
||||
vfp->hard.fpexc = FPEXC_ENABLE;
|
||||
vfp->hard.fpexc = FPEXC_EN;
|
||||
vfp->hard.fpscr = FPSCR_ROUND_NEAREST;
|
||||
|
||||
/*
|
||||
* Disable VFP to ensure we initialise it first.
|
||||
*/
|
||||
fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
|
||||
fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
|
||||
}
|
||||
|
||||
/* flush and release case: Per-thread VFP cleanup. */
|
||||
@ -229,7 +229,7 @@ void VFP9_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
|
||||
/*
|
||||
* Enable access to the VFP so we can handle the bounce.
|
||||
*/
|
||||
fmxr(FPEXC, fpexc & ~(FPEXC_EXCEPTION|FPEXC_INV|FPEXC_UFC|FPEXC_IOC));
|
||||
fmxr(FPEXC, fpexc & ~(FPEXC_EX|FPEXC_INV|FPEXC_UFC|FPEXC_IOC));
|
||||
|
||||
orig_fpscr = fpscr = fmrx(FPSCR);
|
||||
|
||||
@ -248,7 +248,7 @@ void VFP9_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
|
||||
/*
|
||||
* Modify fpscr to indicate the number of iterations remaining
|
||||
*/
|
||||
if (fpexc & FPEXC_EXCEPTION) {
|
||||
if (fpexc & FPEXC_EX) {
|
||||
u32 len;
|
||||
|
||||
len = fpexc + (1 << FPEXC_LENGTH_BIT);
|
||||
|
@ -187,6 +187,22 @@ config PNX4008_WATCHDOG
|
||||
|
||||
Say N if you are unsure.
|
||||
|
||||
config IOP_WATCHDOG
|
||||
tristate "IOP Watchdog"
|
||||
depends on WATCHDOG && PLAT_IOP
|
||||
select WATCHDOG_NOWAYOUT if (ARCH_IOP32X || ARCH_IOP33X)
|
||||
help
|
||||
Say Y here if to include support for the watchdog timer
|
||||
in the Intel IOP3XX & IOP13XX I/O Processors. This driver can
|
||||
be built as a module by choosing M. The module will
|
||||
be called iop_wdt.
|
||||
|
||||
Note: The IOP13XX watchdog does an Internal Bus Reset which will
|
||||
affect both cores and the peripherals of the IOP. The ATU-X
|
||||
and/or ATUe configuration registers will remain intact, but if
|
||||
operating as an Root Complex and/or Central Resource, the PCI-X
|
||||
and/or PCIe busses will also be reset. THIS IS A VERY BIG HAMMER.
|
||||
|
||||
# AVR32 Architecture
|
||||
|
||||
config AT32AP700X_WDT
|
||||
|
@ -35,6 +35,7 @@ obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
|
||||
obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
|
||||
obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o
|
||||
obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o
|
||||
obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o
|
||||
|
||||
# AVR32 Architecture
|
||||
obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
|
||||
|
262
drivers/char/watchdog/iop_wdt.c
Normal file
262
drivers/char/watchdog/iop_wdt.c
Normal file
@ -0,0 +1,262 @@
|
||||
/*
|
||||
* drivers/char/watchdog/iop_wdt.c
|
||||
*
|
||||
* WDT driver for Intel I/O Processors
|
||||
* Copyright (C) 2005, Intel Corporation.
|
||||
*
|
||||
* Based on ixp4xx driver, Copyright 2004 (c) MontaVista, Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place - Suite 330, Boston, MA 02111-1307 USA.
|
||||
*
|
||||
* Curt E Bruns <curt.e.bruns@intel.com>
|
||||
* Peter Milne <peter.milne@d-tacq.com>
|
||||
* Dan Williams <dan.j.williams@intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/watchdog.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/hardware.h>
|
||||
|
||||
static int nowayout = WATCHDOG_NOWAYOUT;
|
||||
static unsigned long wdt_status;
|
||||
static unsigned long boot_status;
|
||||
|
||||
#define WDT_IN_USE 0
|
||||
#define WDT_OK_TO_CLOSE 1
|
||||
#define WDT_ENABLED 2
|
||||
|
||||
static unsigned long iop_watchdog_timeout(void)
|
||||
{
|
||||
return (0xffffffffUL / get_iop_tick_rate());
|
||||
}
|
||||
|
||||
/**
|
||||
* wdt_supports_disable - determine if we are accessing a iop13xx watchdog
|
||||
* or iop3xx by whether it has a disable command
|
||||
*/
|
||||
static int wdt_supports_disable(void)
|
||||
{
|
||||
int can_disable;
|
||||
|
||||
if (IOP_WDTCR_EN_ARM != IOP_WDTCR_DIS_ARM)
|
||||
can_disable = 1;
|
||||
else
|
||||
can_disable = 0;
|
||||
|
||||
return can_disable;
|
||||
}
|
||||
|
||||
static void wdt_enable(void)
|
||||
{
|
||||
/* Arm and enable the Timer to starting counting down from 0xFFFF.FFFF
|
||||
* Takes approx. 10.7s to timeout
|
||||
*/
|
||||
write_wdtcr(IOP_WDTCR_EN_ARM);
|
||||
write_wdtcr(IOP_WDTCR_EN);
|
||||
}
|
||||
|
||||
/* returns 0 if the timer was successfully disabled */
|
||||
static int wdt_disable(void)
|
||||
{
|
||||
/* Stop Counting */
|
||||
if (wdt_supports_disable()) {
|
||||
write_wdtcr(IOP_WDTCR_DIS_ARM);
|
||||
write_wdtcr(IOP_WDTCR_DIS);
|
||||
clear_bit(WDT_ENABLED, &wdt_status);
|
||||
printk(KERN_INFO "WATCHDOG: Disabled\n");
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int iop_wdt_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
if (test_and_set_bit(WDT_IN_USE, &wdt_status))
|
||||
return -EBUSY;
|
||||
|
||||
clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
|
||||
|
||||
wdt_enable();
|
||||
|
||||
set_bit(WDT_ENABLED, &wdt_status);
|
||||
|
||||
return nonseekable_open(inode, file);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
iop_wdt_write(struct file *file, const char *data, size_t len,
|
||||
loff_t *ppos)
|
||||
{
|
||||
if (len) {
|
||||
if (!nowayout) {
|
||||
size_t i;
|
||||
|
||||
clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
|
||||
|
||||
for (i = 0; i != len; i++) {
|
||||
char c;
|
||||
|
||||
if (get_user(c, data + i))
|
||||
return -EFAULT;
|
||||
if (c == 'V')
|
||||
set_bit(WDT_OK_TO_CLOSE, &wdt_status);
|
||||
}
|
||||
}
|
||||
wdt_enable();
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static struct watchdog_info ident = {
|
||||
.options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
|
||||
.identity = "iop watchdog",
|
||||
};
|
||||
|
||||
static int
|
||||
iop_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
int options;
|
||||
int ret = -ENOTTY;
|
||||
|
||||
switch (cmd) {
|
||||
case WDIOC_GETSUPPORT:
|
||||
if (copy_to_user
|
||||
((struct watchdog_info *)arg, &ident, sizeof ident))
|
||||
ret = -EFAULT;
|
||||
else
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case WDIOC_GETSTATUS:
|
||||
ret = put_user(0, (int *)arg);
|
||||
break;
|
||||
|
||||
case WDIOC_GETBOOTSTATUS:
|
||||
ret = put_user(boot_status, (int *)arg);
|
||||
break;
|
||||
|
||||
case WDIOC_GETTIMEOUT:
|
||||
ret = put_user(iop_watchdog_timeout(), (int *)arg);
|
||||
break;
|
||||
|
||||
case WDIOC_KEEPALIVE:
|
||||
wdt_enable();
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case WDIOC_SETOPTIONS:
|
||||
if (get_user(options, (int *)arg))
|
||||
return -EFAULT;
|
||||
|
||||
if (options & WDIOS_DISABLECARD) {
|
||||
if (!nowayout) {
|
||||
if (wdt_disable() == 0) {
|
||||
set_bit(WDT_OK_TO_CLOSE, &wdt_status);
|
||||
ret = 0;
|
||||
} else
|
||||
ret = -ENXIO;
|
||||
} else
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (options & WDIOS_ENABLECARD) {
|
||||
wdt_enable();
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iop_wdt_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
int state = 1;
|
||||
if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
|
||||
if (test_bit(WDT_ENABLED, &wdt_status))
|
||||
state = wdt_disable();
|
||||
|
||||
/* if the timer is not disbaled reload and notify that we are still
|
||||
* going down
|
||||
*/
|
||||
if (state != 0) {
|
||||
wdt_enable();
|
||||
printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
|
||||
"reset in %lu seconds\n", iop_watchdog_timeout());
|
||||
}
|
||||
|
||||
clear_bit(WDT_IN_USE, &wdt_status);
|
||||
clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations iop_wdt_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.write = iop_wdt_write,
|
||||
.ioctl = iop_wdt_ioctl,
|
||||
.open = iop_wdt_open,
|
||||
.release = iop_wdt_release,
|
||||
};
|
||||
|
||||
static struct miscdevice iop_wdt_miscdev = {
|
||||
.minor = WATCHDOG_MINOR,
|
||||
.name = "watchdog",
|
||||
.fops = &iop_wdt_fops,
|
||||
};
|
||||
|
||||
static int __init iop_wdt_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = misc_register(&iop_wdt_miscdev);
|
||||
if (ret == 0)
|
||||
printk("iop watchdog timer: timeout %lu sec\n",
|
||||
iop_watchdog_timeout());
|
||||
|
||||
/* check if the reset was caused by the watchdog timer */
|
||||
boot_status = (read_rcsr() & IOP_RCSR_WDT) ? WDIOF_CARDRESET : 0;
|
||||
|
||||
/* Configure Watchdog Timeout to cause an Internal Bus (IB) Reset
|
||||
* NOTE: An IB Reset will Reset both cores in the IOP342
|
||||
*/
|
||||
write_wdtsr(IOP13XX_WDTCR_IB_RESET);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit iop_wdt_exit(void)
|
||||
{
|
||||
misc_deregister(&iop_wdt_miscdev);
|
||||
}
|
||||
|
||||
module_init(iop_wdt_init);
|
||||
module_exit(iop_wdt_exit);
|
||||
|
||||
module_param(nowayout, int, 0);
|
||||
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
|
||||
|
||||
MODULE_AUTHOR("Curt E Bruns <curt.e.bruns@intel.com>");
|
||||
MODULE_DESCRIPTION("iop watchdog timer driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
|
@ -36,7 +36,6 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/slab.h>
|
||||
@ -75,7 +74,7 @@ static void ether1_timeout(struct net_device *dev);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static char version[] __initdata = "ether1 ethernet driver (c) 2000 Russell King v1.07\n";
|
||||
static char version[] __devinitdata = "ether1 ethernet driver (c) 2000 Russell King v1.07\n";
|
||||
|
||||
#define BUS_16 16
|
||||
#define BUS_8 8
|
||||
|
@ -51,7 +51,6 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/slab.h>
|
||||
@ -69,7 +68,7 @@
|
||||
#include <asm/ecard.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
static char version[] __initdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n";
|
||||
static char version[] __devinitdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n";
|
||||
|
||||
#include "ether3.h"
|
||||
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
#define CUMANASCSI_PUBLIC_RELEASE 1
|
||||
|
||||
#define NCR5380_implementation_fields int port, ctrl
|
||||
#define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata)
|
||||
#define NCR5380_local_declare() struct Scsi_Host *_instance
|
||||
#define NCR5380_setup(instance) _instance = instance
|
||||
#define NCR5380_read(reg) cumanascsi_read(_instance, reg)
|
||||
@ -33,6 +33,11 @@
|
||||
#define NCR5380_queue_command cumanascsi_queue_command
|
||||
#define NCR5380_proc_info cumanascsi_proc_info
|
||||
|
||||
#define NCR5380_implementation_fields \
|
||||
unsigned ctrl; \
|
||||
void __iomem *base; \
|
||||
void __iomem *dma
|
||||
|
||||
#define BOARD_NORMAL 0
|
||||
#define BOARD_NCR53C400 1
|
||||
|
||||
@ -47,193 +52,163 @@ const char *cumanascsi_info(struct Scsi_Host *spnt)
|
||||
return "";
|
||||
}
|
||||
|
||||
#ifdef NOT_EFFICIENT
|
||||
#define CTRL(p,v) outb(*ctrl = (v), (p) - 577)
|
||||
#define STAT(p) inb((p)+1)
|
||||
#define IN(p) inb((p))
|
||||
#define OUT(v,p) outb((v), (p))
|
||||
#else
|
||||
#define CTRL(p,v) (p[-2308] = (*ctrl = (v)))
|
||||
#define STAT(p) (p[4])
|
||||
#define IN(p) (*(p))
|
||||
#define IN2(p) ((unsigned short)(*(volatile unsigned long *)(p)))
|
||||
#define OUT(v,p) (*(p) = (v))
|
||||
#define OUT2(v,p) (*((volatile unsigned long *)(p)) = (v))
|
||||
#endif
|
||||
#define L(v) (((v)<<16)|((v) & 0x0000ffff))
|
||||
#define H(v) (((v)>>16)|((v) & 0xffff0000))
|
||||
#define CTRL 0x16fc
|
||||
#define STAT 0x2004
|
||||
#define L(v) (((v)<<16)|((v) & 0x0000ffff))
|
||||
#define H(v) (((v)>>16)|((v) & 0xffff0000))
|
||||
|
||||
static inline int
|
||||
NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr, int len)
|
||||
NCR5380_pwrite(struct Scsi_Host *host, unsigned char *addr, int len)
|
||||
{
|
||||
int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
|
||||
int oldctrl = *ctrl;
|
||||
unsigned long *laddr;
|
||||
#ifdef NOT_EFFICIENT
|
||||
int iobase = instance->io_port;
|
||||
int dma_io = iobase & ~(0x3C0000>>2);
|
||||
#else
|
||||
volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port);
|
||||
volatile unsigned char *dma_io = (unsigned char *)((int)iobase & ~0x3C0000);
|
||||
#endif
|
||||
void __iomem *dma = priv(host)->dma + 0x2000;
|
||||
|
||||
if(!len) return 0;
|
||||
|
||||
CTRL(iobase, 0x02);
|
||||
writeb(0x02, priv(host)->base + CTRL);
|
||||
laddr = (unsigned long *)addr;
|
||||
while(len >= 32)
|
||||
{
|
||||
int status;
|
||||
unsigned int status;
|
||||
unsigned long v;
|
||||
status = STAT(iobase);
|
||||
status = readb(priv(host)->base + STAT);
|
||||
if(status & 0x80)
|
||||
goto end;
|
||||
if(!(status & 0x40))
|
||||
continue;
|
||||
v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
|
||||
v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
|
||||
v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
|
||||
v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
|
||||
v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
|
||||
v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
|
||||
v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
|
||||
v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
|
||||
v=*laddr++; writew(L(v), dma); writew(H(v), dma);
|
||||
v=*laddr++; writew(L(v), dma); writew(H(v), dma);
|
||||
v=*laddr++; writew(L(v), dma); writew(H(v), dma);
|
||||
v=*laddr++; writew(L(v), dma); writew(H(v), dma);
|
||||
v=*laddr++; writew(L(v), dma); writew(H(v), dma);
|
||||
v=*laddr++; writew(L(v), dma); writew(H(v), dma);
|
||||
v=*laddr++; writew(L(v), dma); writew(H(v), dma);
|
||||
v=*laddr++; writew(L(v), dma); writew(H(v), dma);
|
||||
len -= 32;
|
||||
if(len == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
addr = (unsigned char *)laddr;
|
||||
CTRL(iobase, 0x12);
|
||||
writeb(0x12, priv(host)->base + CTRL);
|
||||
|
||||
while(len > 0)
|
||||
{
|
||||
int status;
|
||||
status = STAT(iobase);
|
||||
unsigned int status;
|
||||
status = readb(priv(host)->base + STAT);
|
||||
if(status & 0x80)
|
||||
goto end;
|
||||
if(status & 0x40)
|
||||
{
|
||||
OUT(*addr++, dma_io);
|
||||
writeb(*addr++, dma);
|
||||
if(--len == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
status = STAT(iobase);
|
||||
status = readb(priv(host)->base + STAT);
|
||||
if(status & 0x80)
|
||||
goto end;
|
||||
if(status & 0x40)
|
||||
{
|
||||
OUT(*addr++, dma_io);
|
||||
writeb(*addr++, dma);
|
||||
if(--len == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
end:
|
||||
CTRL(iobase, oldctrl|0x40);
|
||||
writeb(priv(host)->ctrl | 0x40, priv(host)->base + CTRL);
|
||||
return len;
|
||||
}
|
||||
|
||||
static inline int
|
||||
NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr, int len)
|
||||
NCR5380_pread(struct Scsi_Host *host, unsigned char *addr, int len)
|
||||
{
|
||||
int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
|
||||
int oldctrl = *ctrl;
|
||||
unsigned long *laddr;
|
||||
#ifdef NOT_EFFICIENT
|
||||
int iobase = instance->io_port;
|
||||
int dma_io = iobase & ~(0x3C0000>>2);
|
||||
#else
|
||||
volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port);
|
||||
volatile unsigned char *dma_io = (unsigned char *)((int)iobase & ~0x3C0000);
|
||||
#endif
|
||||
void __iomem *dma = priv(host)->dma + 0x2000;
|
||||
|
||||
if(!len) return 0;
|
||||
|
||||
CTRL(iobase, 0x00);
|
||||
writeb(0x00, priv(host)->base + CTRL);
|
||||
laddr = (unsigned long *)addr;
|
||||
while(len >= 32)
|
||||
{
|
||||
int status;
|
||||
status = STAT(iobase);
|
||||
unsigned int status;
|
||||
status = readb(priv(host)->base + STAT);
|
||||
if(status & 0x80)
|
||||
goto end;
|
||||
if(!(status & 0x40))
|
||||
continue;
|
||||
*laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
|
||||
*laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
|
||||
*laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
|
||||
*laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
|
||||
*laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
|
||||
*laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
|
||||
*laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
|
||||
*laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
|
||||
*laddr++ = readw(dma) | (readw(dma) << 16);
|
||||
*laddr++ = readw(dma) | (readw(dma) << 16);
|
||||
*laddr++ = readw(dma) | (readw(dma) << 16);
|
||||
*laddr++ = readw(dma) | (readw(dma) << 16);
|
||||
*laddr++ = readw(dma) | (readw(dma) << 16);
|
||||
*laddr++ = readw(dma) | (readw(dma) << 16);
|
||||
*laddr++ = readw(dma) | (readw(dma) << 16);
|
||||
*laddr++ = readw(dma) | (readw(dma) << 16);
|
||||
len -= 32;
|
||||
if(len == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
addr = (unsigned char *)laddr;
|
||||
CTRL(iobase, 0x10);
|
||||
writeb(0x10, priv(host)->base + CTRL);
|
||||
|
||||
while(len > 0)
|
||||
{
|
||||
int status;
|
||||
status = STAT(iobase);
|
||||
unsigned int status;
|
||||
status = readb(priv(host)->base + STAT);
|
||||
if(status & 0x80)
|
||||
goto end;
|
||||
if(status & 0x40)
|
||||
{
|
||||
*addr++ = IN(dma_io);
|
||||
*addr++ = readb(dma);
|
||||
if(--len == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
status = STAT(iobase);
|
||||
status = readb(priv(host)->base + STAT);
|
||||
if(status & 0x80)
|
||||
goto end;
|
||||
if(status & 0x40)
|
||||
{
|
||||
*addr++ = IN(dma_io);
|
||||
*addr++ = readb(dma);
|
||||
if(--len == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
end:
|
||||
CTRL(iobase, oldctrl|0x40);
|
||||
writeb(priv(host)->ctrl | 0x40, priv(host)->base + CTRL);
|
||||
return len;
|
||||
}
|
||||
|
||||
#undef STAT
|
||||
#undef CTRL
|
||||
#undef IN
|
||||
#undef OUT
|
||||
|
||||
#define CTRL(p,v) outb(*ctrl = (v), (p) - 577)
|
||||
|
||||
static char cumanascsi_read(struct Scsi_Host *instance, int reg)
|
||||
static unsigned char cumanascsi_read(struct Scsi_Host *host, unsigned int reg)
|
||||
{
|
||||
unsigned int iobase = instance->io_port;
|
||||
int i;
|
||||
int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
|
||||
void __iomem *base = priv(host)->base;
|
||||
unsigned char val;
|
||||
|
||||
CTRL(iobase, 0);
|
||||
i = inb(iobase + 64 + reg);
|
||||
CTRL(iobase, 0x40);
|
||||
writeb(0, base + CTRL);
|
||||
|
||||
return i;
|
||||
val = readb(base + 0x2100 + (reg << 2));
|
||||
|
||||
priv(host)->ctrl = 0x40;
|
||||
writeb(0x40, base + CTRL);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void cumanascsi_write(struct Scsi_Host *instance, int reg, int value)
|
||||
static void cumanascsi_write(struct Scsi_Host *host, unsigned int reg, unsigned int value)
|
||||
{
|
||||
int iobase = instance->io_port;
|
||||
int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
|
||||
void __iomem *base = priv(host)->base;
|
||||
|
||||
CTRL(iobase, 0);
|
||||
outb(value, iobase + 64 + reg);
|
||||
CTRL(iobase, 0x40);
|
||||
writeb(0, base + CTRL);
|
||||
|
||||
writeb(value, base + 0x2100 + (reg << 2));
|
||||
|
||||
priv(host)->ctrl = 0x40;
|
||||
writeb(0x40, base + CTRL);
|
||||
}
|
||||
|
||||
#undef CTRL
|
||||
|
||||
#include "../NCR5380.c"
|
||||
|
||||
static struct scsi_host_template cumanascsi_template = {
|
||||
@ -256,32 +231,46 @@ static int __devinit
|
||||
cumanascsi1_probe(struct expansion_card *ec, const struct ecard_id *id)
|
||||
{
|
||||
struct Scsi_Host *host;
|
||||
int ret = -ENOMEM;
|
||||
int ret;
|
||||
|
||||
host = scsi_host_alloc(&cumanascsi_template, sizeof(struct NCR5380_hostdata));
|
||||
if (!host)
|
||||
ret = ecard_request_resources(ec);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
host->io_port = ecard_address(ec, ECARD_IOC, ECARD_SLOW) + 0x800;
|
||||
host = scsi_host_alloc(&cumanascsi_template, sizeof(struct NCR5380_hostdata));
|
||||
if (!host) {
|
||||
ret = -ENOMEM;
|
||||
goto out_release;
|
||||
}
|
||||
|
||||
priv(host)->base = ioremap(ecard_resource_start(ec, ECARD_RES_IOCSLOW),
|
||||
ecard_resource_len(ec, ECARD_RES_IOCSLOW));
|
||||
priv(host)->dma = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC),
|
||||
ecard_resource_len(ec, ECARD_RES_MEMC));
|
||||
if (!priv(host)->base || !priv(host)->dma) {
|
||||
ret = -ENOMEM;
|
||||
goto out_unmap;
|
||||
}
|
||||
|
||||
host->irq = ec->irq;
|
||||
|
||||
NCR5380_init(host, 0);
|
||||
|
||||
priv(host)->ctrl = 0;
|
||||
writeb(0, priv(host)->base + CTRL);
|
||||
|
||||
host->n_io_port = 255;
|
||||
if (!(request_region(host->io_port, host->n_io_port, "CumanaSCSI-1"))) {
|
||||
ret = -EBUSY;
|
||||
goto out_free;
|
||||
goto out_unmap;
|
||||
}
|
||||
|
||||
((struct NCR5380_hostdata *)host->hostdata)->ctrl = 0;
|
||||
outb(0x00, host->io_port - 577);
|
||||
|
||||
ret = request_irq(host->irq, cumanascsi_intr, IRQF_DISABLED,
|
||||
"CumanaSCSI-1", host);
|
||||
if (ret) {
|
||||
printk("scsi%d: IRQ%d not free: %d\n",
|
||||
host->host_no, host->irq, ret);
|
||||
goto out_release;
|
||||
goto out_unmap;
|
||||
}
|
||||
|
||||
printk("scsi%d: at port 0x%08lx irq %d",
|
||||
@ -301,10 +290,12 @@ cumanascsi1_probe(struct expansion_card *ec, const struct ecard_id *id)
|
||||
|
||||
out_free_irq:
|
||||
free_irq(host->irq, host);
|
||||
out_release:
|
||||
release_region(host->io_port, host->n_io_port);
|
||||
out_free:
|
||||
out_unmap:
|
||||
iounmap(priv(host)->base);
|
||||
iounmap(priv(host)->dma);
|
||||
scsi_host_put(host);
|
||||
out_release:
|
||||
ecard_release_resources(ec);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@ -318,8 +309,10 @@ static void __devexit cumanascsi1_remove(struct expansion_card *ec)
|
||||
scsi_remove_host(host);
|
||||
free_irq(host->irq, host);
|
||||
NCR5380_exit(host);
|
||||
release_region(host->io_port, host->n_io_port);
|
||||
iounmap(priv(host)->base);
|
||||
iounmap(priv(host)->dma);
|
||||
scsi_host_put(host);
|
||||
ecard_release_resources(ec);
|
||||
}
|
||||
|
||||
static const struct ecard_id cumanascsi1_cids[] = {
|
||||
|
@ -34,35 +34,25 @@
|
||||
#include "../scsi.h"
|
||||
#include <scsi/scsi_host.h>
|
||||
|
||||
#define NCR5380_implementation_fields int port, ctrl
|
||||
#define NCR5380_local_declare() struct Scsi_Host *_instance
|
||||
#define NCR5380_setup(instance) _instance = instance
|
||||
#define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata)
|
||||
|
||||
#define NCR5380_read(reg) ecoscsi_read(_instance, reg)
|
||||
#define NCR5380_write(reg, value) ecoscsi_write(_instance, reg, value)
|
||||
#define NCR5380_local_declare() void __iomem *_base
|
||||
#define NCR5380_setup(host) _base = priv(host)->base
|
||||
|
||||
#define NCR5380_read(reg) ({ writeb(reg | 8, _base); readb(_base + 4); })
|
||||
#define NCR5380_write(reg, value) ({ writeb(reg | 8, _base); writeb(value, _base + 4); })
|
||||
|
||||
#define NCR5380_intr ecoscsi_intr
|
||||
#define NCR5380_queue_command ecoscsi_queue_command
|
||||
#define NCR5380_proc_info ecoscsi_proc_info
|
||||
|
||||
#define NCR5380_implementation_fields \
|
||||
void __iomem *base
|
||||
|
||||
#include "../NCR5380.h"
|
||||
|
||||
#define ECOSCSI_PUBLIC_RELEASE 1
|
||||
|
||||
static char ecoscsi_read(struct Scsi_Host *instance, int reg)
|
||||
{
|
||||
int iobase = instance->io_port;
|
||||
outb(reg | 8, iobase);
|
||||
return inb(iobase + 1);
|
||||
}
|
||||
|
||||
static void ecoscsi_write(struct Scsi_Host *instance, int reg, int value)
|
||||
{
|
||||
int iobase = instance->io_port;
|
||||
outb(reg | 8, iobase);
|
||||
outb(value, iobase + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function : ecoscsi_setup(char *str, int *ints)
|
||||
*
|
||||
@ -82,73 +72,6 @@ const char * ecoscsi_info (struct Scsi_Host *spnt)
|
||||
return "";
|
||||
}
|
||||
|
||||
#if 0
|
||||
#define STAT(p) inw(p + 144)
|
||||
|
||||
static inline int NCR5380_pwrite(struct Scsi_Host *host, unsigned char *addr,
|
||||
int len)
|
||||
{
|
||||
int iobase = host->io_port;
|
||||
printk("writing %p len %d\n",addr, len);
|
||||
if(!len) return -1;
|
||||
|
||||
while(1)
|
||||
{
|
||||
int status;
|
||||
while(((status = STAT(iobase)) & 0x100)==0);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int NCR5380_pread(struct Scsi_Host *host, unsigned char *addr,
|
||||
int len)
|
||||
{
|
||||
int iobase = host->io_port;
|
||||
int iobase2= host->io_port + 0x100;
|
||||
unsigned char *start = addr;
|
||||
int s;
|
||||
printk("reading %p len %d\n",addr, len);
|
||||
outb(inb(iobase + 128), iobase + 135);
|
||||
while(len > 0)
|
||||
{
|
||||
int status,b,i, timeout;
|
||||
timeout = 0x07FFFFFF;
|
||||
while(((status = STAT(iobase)) & 0x100)==0)
|
||||
{
|
||||
timeout--;
|
||||
if(status & 0x200 || !timeout)
|
||||
{
|
||||
printk("status = %p\n",status);
|
||||
outb(0, iobase + 135);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if(len >= 128)
|
||||
{
|
||||
for(i=0; i<64; i++)
|
||||
{
|
||||
b = inw(iobase + 136);
|
||||
*addr++ = b;
|
||||
*addr++ = b>>8;
|
||||
}
|
||||
len -= 128;
|
||||
}
|
||||
else
|
||||
{
|
||||
b = inw(iobase + 136);
|
||||
*addr ++ = b;
|
||||
len -= 1;
|
||||
if(len)
|
||||
*addr ++ = b>>8;
|
||||
len -= 1;
|
||||
}
|
||||
}
|
||||
outb(0, iobase + 135);
|
||||
printk("first bytes = %02X %02X %02X %20X %02X %02X %02X\n",*start, start[1], start[2], start[3], start[4], start[5], start[6]);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
#undef STAT
|
||||
|
||||
#define BOARD_NORMAL 0
|
||||
#define BOARD_NCR53C400 1
|
||||
|
||||
@ -173,26 +96,37 @@ static struct Scsi_Host *host;
|
||||
|
||||
static int __init ecoscsi_init(void)
|
||||
{
|
||||
void __iomem *_base;
|
||||
int ret;
|
||||
|
||||
if (!request_mem_region(0x33a0000, 4096, "ecoscsi")) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
_base = ioremap(0x33a0000, 4096);
|
||||
if (!_base) {
|
||||
ret = -ENOMEM;
|
||||
goto out_release;
|
||||
}
|
||||
|
||||
NCR5380_write(MODE_REG, 0x20); /* Is it really SCSI? */
|
||||
if (NCR5380_read(MODE_REG) != 0x20) /* Write to a reg. */
|
||||
goto out_unmap;
|
||||
|
||||
NCR5380_write(MODE_REG, 0x00); /* it back. */
|
||||
if (NCR5380_read(MODE_REG) != 0x00)
|
||||
goto out_unmap;
|
||||
|
||||
host = scsi_host_alloc(tpnt, sizeof(struct NCR5380_hostdata));
|
||||
if (!host)
|
||||
return 0;
|
||||
if (!host) {
|
||||
ret = -ENOMEM;
|
||||
goto out_unmap;
|
||||
}
|
||||
|
||||
host->io_port = 0x80ce8000;
|
||||
host->n_io_port = 144;
|
||||
priv(host)->base = _base;
|
||||
host->irq = IRQ_NONE;
|
||||
|
||||
if (!(request_region(host->io_port, host->n_io_port, "ecoscsi")) )
|
||||
goto unregister_scsi;
|
||||
|
||||
ecoscsi_write(host, MODE_REG, 0x20); /* Is it really SCSI? */
|
||||
if (ecoscsi_read(host, MODE_REG) != 0x20) /* Write to a reg. */
|
||||
goto release_reg;
|
||||
|
||||
ecoscsi_write(host, MODE_REG, 0x00 ); /* it back. */
|
||||
if (ecoscsi_read(host, MODE_REG) != 0x00)
|
||||
goto release_reg;
|
||||
|
||||
NCR5380_init(host, 0);
|
||||
|
||||
printk("scsi%d: at port 0x%08lx irqs disabled", host->host_no, host->io_port);
|
||||
@ -206,24 +140,20 @@ static int __init ecoscsi_init(void)
|
||||
scsi_scan_host(host);
|
||||
return 0;
|
||||
|
||||
release_reg:
|
||||
release_region(host->io_port, host->n_io_port);
|
||||
unregister_scsi:
|
||||
scsi_host_put(host);
|
||||
return -ENODEV;
|
||||
out_unmap:
|
||||
iounmap(_base);
|
||||
out_release:
|
||||
release_mem_region(0x33a0000, 4096);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit ecoscsi_exit(void)
|
||||
{
|
||||
scsi_remove_host(host);
|
||||
|
||||
if (shpnt->irq != IRQ_NONE)
|
||||
free_irq(shpnt->irq, NULL);
|
||||
NCR5380_exit(host);
|
||||
if (shpnt->io_port)
|
||||
release_region(shpnt->io_port, shpnt->n_io_port);
|
||||
|
||||
scsi_host_put(host);
|
||||
release_mem_region(0x33a0000, 4096);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user