Merge branches 'at91', 'imx', 'iop', 'ixp', 'ks8695', 'misc', 'ns9xxx', 'pxa' and 's3c' into devel

This commit is contained in:
Russell King 2007-07-22 17:09:17 +01:00 committed by Russell King
157 changed files with 5471 additions and 1149 deletions

View file

@ -457,7 +457,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

View file

@ -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"

View file

@ -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

View file

@ -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/

View file

@ -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

View file

@ -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

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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

View file

@ -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

View 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

View file

@ -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++) {

View file

@ -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;
}

View file

@ -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
View 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

View 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

View 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
View 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
View 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
View 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,
};

View file

@ -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

View file

@ -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));
}

View file

@ -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),

View file

@ -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,

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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
View 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

View file

@ -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,
};

View file

@ -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);

View file

@ -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;
}

View file

@ -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));
}

View file

@ -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

View file

@ -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
};

View file

@ -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

View file

@ -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

View file

@ -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>

View file

@ -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] = {

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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),
};

View file

@ -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
*

View file

@ -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

View file

@ -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>

View file

@ -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 }

View file

@ -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>

View file

@ -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>

View file

@ -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),
};

View file

@ -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.

View file

@ -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] = {

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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.

View file

@ -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

View file

@ -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, \

View file

@ -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>

View file

@ -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"

View file

@ -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

View 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);
}

View file

@ -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);

View file

@ -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

View file

@ -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)

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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
View 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

View 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
View 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
View 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.

View file

@ -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

View file

@ -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>

View file

@ -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>

View file

@ -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 */

View file

@ -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>

View file

@ -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 */

View file

@ -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!

View file

@ -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>

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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

View 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);

View file

@ -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

View file

@ -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"

View file

@ -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>

View file

@ -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[] = {

View file

@ -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;
}

View file

@ -23,15 +23,18 @@
#define OAKSCSI_PUBLIC_RELEASE 1
#define NCR5380_read(reg) oakscsi_read(_instance, reg)
#define NCR5380_write(reg, value) oakscsi_write(_instance, reg, value)
#define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata)
#define NCR5380_local_declare() void __iomem *_base
#define NCR5380_setup(host) _base = priv(host)->base
#define NCR5380_read(reg) readb(_base + ((reg) << 2))
#define NCR5380_write(reg, value) writeb(value, _base + ((reg) << 2))
#define NCR5380_intr oakscsi_intr
#define NCR5380_queue_command oakscsi_queue_command
#define NCR5380_proc_info oakscsi_proc_info
#define NCR5380_implementation_fields int port, ctrl
#define NCR5380_local_declare() struct Scsi_Host *_instance
#define NCR5380_setup(instance) _instance = instance
#define NCR5380_implementation_fields \
void __iomem *base
#define BOARD_NORMAL 0
#define BOARD_NCR53C400 1
@ -39,60 +42,62 @@
#include "../NCR5380.h"
#undef START_DMA_INITIATOR_RECEIVE_REG
#define START_DMA_INITIATOR_RECEIVE_REG (7 + 128)
#define START_DMA_INITIATOR_RECEIVE_REG (128 + 7)
const char * oakscsi_info (struct Scsi_Host *spnt)
{
return "";
}
#define STAT(p) inw(p + 144)
extern void inswb(int from, void *to, int len);
#define STAT ((128 + 16) << 2)
#define DATA ((128 + 8) << 2)
static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr,
int len)
{
int iobase = instance->io_port;
void __iomem *base = priv(instance)->base;
printk("writing %p len %d\n",addr, len);
if(!len) return -1;
while(1)
{
int status;
while(((status = STAT(iobase)) & 0x100)==0);
while (((status = readw(base + STAT)) & 0x100)==0);
}
}
static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr,
int len)
{
int iobase = instance->io_port;
void __iomem *base = priv(instance)->base;
printk("reading %p len %d\n", addr, len);
while(len > 0)
{
int status, timeout;
unsigned int status, timeout;
unsigned long b;
timeout = 0x01FFFFFF;
while(((status = STAT(iobase)) & 0x100)==0)
while (((status = readw(base + STAT)) & 0x100)==0)
{
timeout--;
if(status & 0x200 || !timeout)
{
printk("status = %08X\n",status);
printk("status = %08X\n", status);
return 1;
}
}
if(len >= 128)
{
inswb(iobase + 136, addr, 128);
readsw(base + DATA, addr, 128);
addr += 128;
len -= 128;
}
else
{
b = (unsigned long) inw(iobase + 136);
b = (unsigned long) readw(base + DATA);
*addr ++ = b;
len -= 1;
if(len)
@ -103,10 +108,8 @@ printk("reading %p len %d\n", addr, len);
return 0;
}
#define oakscsi_read(instance,reg) (inb((instance)->io_port + (reg)))
#define oakscsi_write(instance,reg,val) (outb((val), (instance)->io_port + (reg)))
#undef STAT
#undef DATA
#include "../NCR5380.c"
@ -132,18 +135,26 @@ oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
struct Scsi_Host *host;
int ret = -ENOMEM;
host = scsi_host_alloc(&oakscsi_template, sizeof(struct NCR5380_hostdata));
if (!host)
ret = ecard_request_resources(ec);
if (ret)
goto out;
host->io_port = ecard_address(ec, ECARD_MEMC, 0);
host = scsi_host_alloc(&oakscsi_template, sizeof(struct NCR5380_hostdata));
if (!host) {
ret = -ENOMEM;
goto release;
}
priv(host)->base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC),
ecard_resource_len(ec, ECARD_RES_MEMC));
if (!priv(host)->base) {
ret = -ENOMEM;
goto unreg;
}
host->irq = IRQ_NONE;
host->n_io_port = 255;
ret = -EBUSY;
if (!request_region (host->io_port, host->n_io_port, "Oak SCSI"))
goto unreg;
NCR5380_init(host, 0);
printk("scsi%d: at port 0x%08lx irqs disabled",
@ -156,15 +167,17 @@ oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
ret = scsi_add_host(host, &ec->dev);
if (ret)
goto out_release;
goto out_unmap;
scsi_scan_host(host);
goto out;
out_release:
release_region(host->io_port, host->n_io_port);
out_unmap:
iounmap(priv(host)->base);
unreg:
scsi_host_put(host);
release:
ecard_release_resources(ec);
out:
return ret;
}
@ -177,8 +190,9 @@ static void __devexit oakscsi_remove(struct expansion_card *ec)
scsi_remove_host(host);
NCR5380_exit(host);
release_region(host->io_port, host->n_io_port);
iounmap(priv(host)->base);
scsi_host_put(host);
ecard_release_resources(ec);
}
static const struct ecard_id oakscsi_cids[] = {

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