Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: ARM: fix lh7a40x build ARM: fix sa1100 build ARM: fix clps711x, footbridge, integrator, ixp2000, ixp2300 and s3c build bug ARM: VFP: fix vfp thread init bug and document vfp notifier entry conditions ARM: pxa: fix now incorrect reference of skt->irq by using skt->socket.pci_irq [ARM] pxa/zeus: default configuration for Arcom Zeus SBC. [ARM] pxa/zeus: make Viper pcmcia support more generic to support Zeus [ARM] pxa/zeus: basic support for Arcom Zeus SBC [ARM] pxa/em-x270: fix usb hub power up/reset sequence PCMCIA: fix pxa2xx_lubbock modular build error ARM: RealView: Fix typo in the RealView/PBX Kconfig entry ARM: Do not allow the probing of the local timer ARM: Add an earlyprintk debug console
This commit is contained in:
commit
af853e631d
@ -603,6 +603,7 @@ config ARCH_SA1100
|
||||
select ARCH_SPARSEMEM_ENABLE
|
||||
select ARCH_MTD_XIP
|
||||
select ARCH_HAS_CPUFREQ
|
||||
select CPU_FREQ
|
||||
select GENERIC_GPIO
|
||||
select GENERIC_TIME
|
||||
select GENERIC_CLOCKEVENTS
|
||||
@ -1359,13 +1360,9 @@ source "drivers/cpufreq/Kconfig"
|
||||
|
||||
config CPU_FREQ_SA1100
|
||||
bool
|
||||
depends on CPU_FREQ && (SA1100_H3100 || SA1100_H3600 || SA1100_LART || SA1100_PLEB || SA1100_BADGE4 || SA1100_HACKKIT)
|
||||
default y
|
||||
|
||||
config CPU_FREQ_SA1110
|
||||
bool
|
||||
depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3)
|
||||
default y
|
||||
|
||||
config CPU_FREQ_INTEGRATOR
|
||||
tristate "CPUfreq driver for ARM Integrator CPUs"
|
||||
|
@ -71,6 +71,14 @@ config DEBUG_LL
|
||||
in the kernel. This is helpful if you are debugging code that
|
||||
executes before the console is initialized.
|
||||
|
||||
config EARLY_PRINTK
|
||||
bool "Early printk"
|
||||
depends on DEBUG_LL
|
||||
help
|
||||
Say Y here if you want to have an early console using the
|
||||
kernel low-level debugging functions. Add earlyprintk to your
|
||||
kernel parameters to enable this console.
|
||||
|
||||
config DEBUG_ICEDCC
|
||||
bool "Kernel low-level debugging via EmbeddedICE DCC channel"
|
||||
depends on DEBUG_LL
|
||||
|
2032
arch/arm/configs/zeus_defconfig
Normal file
2032
arch/arm/configs/zeus_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
@ -54,5 +54,6 @@ endif
|
||||
|
||||
head-y := head$(MMUEXT).o
|
||||
obj-$(CONFIG_DEBUG_LL) += debug.o
|
||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
|
||||
extra-y := $(head-y) init_task.o vmlinux.lds
|
||||
|
57
arch/arm/kernel/early_printk.c
Normal file
57
arch/arm/kernel/early_printk.c
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* linux/arch/arm/kernel/early_printk.c
|
||||
*
|
||||
* Copyright (C) 2009 Sascha Hauer <s.hauer@pengutronix.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
extern void printch(int);
|
||||
|
||||
static void early_write(const char *s, unsigned n)
|
||||
{
|
||||
while (n-- > 0) {
|
||||
if (*s == '\n')
|
||||
printch('\r');
|
||||
printch(*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
static void early_console_write(struct console *con, const char *s, unsigned n)
|
||||
{
|
||||
early_write(s, n);
|
||||
}
|
||||
|
||||
static struct console early_console = {
|
||||
.name = "earlycon",
|
||||
.write = early_console_write,
|
||||
.flags = CON_PRINTBUFFER | CON_BOOT,
|
||||
.index = -1,
|
||||
};
|
||||
|
||||
asmlinkage void early_printk(const char *fmt, ...)
|
||||
{
|
||||
char buf[512];
|
||||
int n;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
n = vscnprintf(buf, sizeof(buf), fmt, ap);
|
||||
early_write(buf, n);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static int __init setup_early_printk(char *buf)
|
||||
{
|
||||
register_console(&early_console);
|
||||
return 0;
|
||||
}
|
||||
|
||||
early_param("earlyprintk", setup_early_printk);
|
@ -160,6 +160,7 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)
|
||||
|
||||
/* Make sure our local interrupt controller has this enabled */
|
||||
local_irq_save(flags);
|
||||
irq_to_desc(clk->irq)->status |= IRQ_NOPROBE;
|
||||
get_irq_chip(clk->irq)->unmask(clk->irq);
|
||||
local_irq_restore(flags);
|
||||
|
||||
|
@ -30,6 +30,8 @@
|
||||
|
||||
#define __virt_to_bus(x) ((x) - PAGE_OFFSET)
|
||||
#define __bus_to_virt(x) ((x) + PAGE_OFFSET)
|
||||
#define __pfn_to_bus(x) (__pfn_to_phys(x) - PHYS_OFFSET)
|
||||
#define __bus_to_pfn(x) __phys_to_pfn((x) + PHYS_OFFSET)
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -201,6 +201,11 @@ void __init footbridge_map_io(void)
|
||||
|
||||
#ifdef CONFIG_FOOTBRIDGE_ADDIN
|
||||
|
||||
static inline unsigned long fb_bus_sdram_offset(void)
|
||||
{
|
||||
return *CSR_PCISDRAMBASE & 0xfffffff0;
|
||||
}
|
||||
|
||||
/*
|
||||
* These two functions convert virtual addresses to PCI addresses and PCI
|
||||
* addresses to virtual addresses. Note that it is only legal to use these
|
||||
@ -210,14 +215,13 @@ unsigned long __virt_to_bus(unsigned long res)
|
||||
{
|
||||
WARN_ON(res < PAGE_OFFSET || res >= (unsigned long)high_memory);
|
||||
|
||||
return (res - PAGE_OFFSET) + (*CSR_PCISDRAMBASE & 0xfffffff0);
|
||||
return res + (fb_bus_sdram_offset() - PAGE_OFFSET);
|
||||
}
|
||||
EXPORT_SYMBOL(__virt_to_bus);
|
||||
|
||||
unsigned long __bus_to_virt(unsigned long res)
|
||||
{
|
||||
res -= (*CSR_PCISDRAMBASE & 0xfffffff0);
|
||||
res += PAGE_OFFSET;
|
||||
res = res - (fb_bus_sdram_offset() - PAGE_OFFSET);
|
||||
|
||||
WARN_ON(res < PAGE_OFFSET || res >= (unsigned long)high_memory);
|
||||
|
||||
@ -225,4 +229,16 @@ unsigned long __bus_to_virt(unsigned long res)
|
||||
}
|
||||
EXPORT_SYMBOL(__bus_to_virt);
|
||||
|
||||
unsigned long __pfn_to_bus(unsigned long pfn)
|
||||
{
|
||||
return __pfn_to_phys(pfn) + (fb_bus_sdram_offset() - PHYS_OFFSET));
|
||||
}
|
||||
EXPORT_SYMBOL(__pfn_to_bus);
|
||||
|
||||
unsigned long __bus_to_pfn(unsigned long bus)
|
||||
{
|
||||
return __phys_to_pfn(bus - (fb_bus_sdram_offset() - PHYS_OFFSET));
|
||||
}
|
||||
EXPORT_SYMBOL(__bus_to_pfn);
|
||||
|
||||
#endif
|
||||
|
@ -29,6 +29,8 @@
|
||||
#ifndef __ASSEMBLY__
|
||||
extern unsigned long __virt_to_bus(unsigned long);
|
||||
extern unsigned long __bus_to_virt(unsigned long);
|
||||
extern unsigned long __pfn_to_bus(unsigned long);
|
||||
extern unsigned long __bus_to_pfn(unsigned long);
|
||||
#endif
|
||||
#define __virt_to_bus __virt_to_bus
|
||||
#define __bus_to_virt __bus_to_virt
|
||||
@ -36,14 +38,15 @@ extern unsigned long __bus_to_virt(unsigned long);
|
||||
#elif defined(CONFIG_FOOTBRIDGE_HOST)
|
||||
|
||||
/*
|
||||
* The footbridge is programmed to expose the system RAM at the corresponding
|
||||
* address. So, if PAGE_OFFSET is 0xc0000000, RAM appears at 0xe0000000.
|
||||
* If 0x80000000, then its exposed at 0xa0000000 on the bus. etc.
|
||||
* The only requirement is that the RAM isn't placed at bus address 0 which
|
||||
* The footbridge is programmed to expose the system RAM at 0xe0000000.
|
||||
* The requirement is that the RAM isn't placed at bus address 0, which
|
||||
* would clash with VGA cards.
|
||||
*/
|
||||
#define __virt_to_bus(x) ((x) - 0xe0000000)
|
||||
#define __bus_to_virt(x) ((x) + 0xe0000000)
|
||||
#define BUS_OFFSET 0xe0000000
|
||||
#define __virt_to_bus(x) ((x) + (BUS_OFFSET - PAGE_OFFSET))
|
||||
#define __bus_to_virt(x) ((x) - (BUS_OFFSET - PAGE_OFFSET))
|
||||
#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - PHYS_OFFSET))
|
||||
#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - PHYS_OFFSET))
|
||||
|
||||
#else
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#define BUS_OFFSET UL(0x80000000)
|
||||
#define __virt_to_bus(x) ((x) - PAGE_OFFSET + BUS_OFFSET)
|
||||
#define __bus_to_virt(x) ((x) - BUS_OFFSET + PAGE_OFFSET)
|
||||
#define __pfn_to_bus(x) (((x) << PAGE_SHIFT) + BUS_OFFSET)
|
||||
#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - PHYS_OFFSET))
|
||||
#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - PHYS_OFFSET))
|
||||
|
||||
#endif
|
||||
|
@ -17,11 +17,15 @@
|
||||
|
||||
#include <mach/ixp2000-regs.h>
|
||||
|
||||
#define __virt_to_bus(v) \
|
||||
(((__virt_to_phys(v) - 0x0) + (*IXP2000_PCI_SDRAM_BAR & 0xfffffff0)))
|
||||
#define IXP2000_PCI_SDRAM_OFFSET (*IXP2000_PCI_SDRAM_BAR & 0xfffffff0)
|
||||
|
||||
#define __bus_to_virt(b) \
|
||||
__phys_to_virt((((b - (*IXP2000_PCI_SDRAM_BAR & 0xfffffff0)) + 0x0)))
|
||||
#define __phys_to_bus(x) ((x) + (IXP2000_PCI_SDRAM_OFFSET - PHYS_OFFSET))
|
||||
#define __bus_to_phys(x) ((x) - (IXP2000_PCI_SDRAM_OFFSET - PHYS_OFFSET))
|
||||
|
||||
#define __virt_to_bus(v) __phys_to_bus(__virt_to_phys(v))
|
||||
#define __bus_to_virt(b) __phys_to_virt(__bus_to_phys(b))
|
||||
#define __pfn_to_bus(p) __phys_to_bus(__pfn_to_phys(p))
|
||||
#define __bus_to_pfn(b) __phys_to_pfn(__bus_to_phys(b))
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -19,16 +19,15 @@
|
||||
*/
|
||||
#define PHYS_OFFSET (0x00000000)
|
||||
|
||||
#define __virt_to_bus(v) \
|
||||
({ unsigned int ret; \
|
||||
ret = ((__virt_to_phys(v) - 0x00000000) + \
|
||||
(*((volatile int *)IXP23XX_PCI_SDRAM_BAR) & 0xfffffff0)); \
|
||||
ret; })
|
||||
#define IXP23XX_PCI_SDRAM_OFFSET (*((volatile int *)IXP23XX_PCI_SDRAM_BAR) & 0xfffffff0))
|
||||
|
||||
#define __bus_to_virt(b) \
|
||||
({ unsigned int data; \
|
||||
data = *((volatile int *)IXP23XX_PCI_SDRAM_BAR); \
|
||||
__phys_to_virt((((b - (data & 0xfffffff0)) + 0x00000000))); })
|
||||
#define __phys_to_bus(x) ((x) + (IXP23XX_PCI_SDRAM_OFFSET - PHYS_OFFSET))
|
||||
#define __bus_to_phys(x) ((x) - (IXP23XX_PCI_SDRAM_OFFSET - PHYS_OFFSET))
|
||||
|
||||
#define __virt_to_bus(v) __phys_to_bus(__virt_to_phys(v))
|
||||
#define __bus_to_virt(b) __phys_to_virt(__bus_to_phys(b))
|
||||
#define __pfn_to_bus(p) __phys_to_bus(__pfn_to_phys(p))
|
||||
#define __bus_to_pfn(b) __phys_to_pfn(__bus_to_phys(b))
|
||||
|
||||
#define arch_is_coherent() 1
|
||||
|
||||
|
@ -7,8 +7,6 @@
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/cpufreq.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/clocks.h>
|
||||
#include <linux/err.h>
|
||||
@ -31,12 +29,6 @@ struct clk {
|
||||
#define HCLKDIV(c) (((c) >> 0) & 0x02)
|
||||
#define PCLKDIV(c) (((c) >> 16) & 0x03)
|
||||
|
||||
unsigned int cpufreq_get (unsigned int cpu) /* in kHz */
|
||||
{
|
||||
return fclkfreq_get ()/1000;
|
||||
}
|
||||
EXPORT_SYMBOL(cpufreq_get);
|
||||
|
||||
unsigned int fclkfreq_get (void)
|
||||
{
|
||||
unsigned int clkset = CSC_CLKSET;
|
||||
|
@ -63,6 +63,15 @@ config ARCH_VIPER
|
||||
select HAVE_PWM
|
||||
select PXA_HAVE_BOARD_IRQS
|
||||
select PXA_HAVE_ISA_IRQS
|
||||
select ARCOM_PCMCIA
|
||||
|
||||
config MACH_ARCOM_ZEUS
|
||||
bool "Arcom/Eurotech ZEUS SBC"
|
||||
select PXA27x
|
||||
select ISA
|
||||
select PXA_HAVE_BOARD_IRQS
|
||||
select PXA_HAVE_ISA_IRQS
|
||||
select ARCOM_PCMCIA
|
||||
|
||||
config MACH_BALLOON3
|
||||
bool "Balloon 3 board"
|
||||
@ -179,6 +188,11 @@ config MACH_TRIZEPS_ANY
|
||||
|
||||
endchoice
|
||||
|
||||
config ARCOM_PCMCIA
|
||||
bool
|
||||
help
|
||||
Generic option for Arcom Viper/Zeus PCMCIA
|
||||
|
||||
config TRIZEPS_PCMCIA
|
||||
bool
|
||||
help
|
||||
|
@ -38,6 +38,7 @@ obj-$(CONFIG_MACH_SAAR) += saar.o
|
||||
# 3rd Party Dev Platforms
|
||||
obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
|
||||
obj-$(CONFIG_ARCH_VIPER) += viper.o
|
||||
obj-$(CONFIG_MACH_ARCOM_ZEUS) += zeus.o
|
||||
obj-$(CONFIG_MACH_BALLOON3) += balloon3.o
|
||||
obj-$(CONFIG_MACH_CSB726) += csb726.o
|
||||
obj-$(CONFIG_CSB726_CSB701) += csb701.o
|
||||
|
@ -497,16 +497,15 @@ static int em_x270_usb_hub_init(void)
|
||||
goto err_free_vbus_gpio;
|
||||
|
||||
/* USB Hub power-on and reset */
|
||||
gpio_direction_output(usb_hub_reset, 0);
|
||||
gpio_direction_output(usb_hub_reset, 1);
|
||||
gpio_direction_output(GPIO9_USB_VBUS_EN, 0);
|
||||
regulator_enable(em_x270_usb_ldo);
|
||||
gpio_set_value(usb_hub_reset, 1);
|
||||
gpio_set_value(usb_hub_reset, 0);
|
||||
gpio_set_value(usb_hub_reset, 1);
|
||||
regulator_disable(em_x270_usb_ldo);
|
||||
regulator_enable(em_x270_usb_ldo);
|
||||
gpio_set_value(usb_hub_reset, 1);
|
||||
|
||||
/* enable VBUS */
|
||||
gpio_direction_output(GPIO9_USB_VBUS_EN, 1);
|
||||
gpio_set_value(usb_hub_reset, 0);
|
||||
gpio_set_value(GPIO9_USB_VBUS_EN, 1);
|
||||
|
||||
return 0;
|
||||
|
||||
|
11
arch/arm/mach-pxa/include/mach/arcom-pcmcia.h
Normal file
11
arch/arm/mach-pxa/include/mach/arcom-pcmcia.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef __ARCOM_PCMCIA_H
|
||||
#define __ARCOM_PCMCIA_H
|
||||
|
||||
struct arcom_pcmcia_pdata {
|
||||
int cd_gpio;
|
||||
int rdy_gpio;
|
||||
int pwr_gpio;
|
||||
void (*reset)(int state);
|
||||
};
|
||||
|
||||
#endif
|
@ -85,8 +85,6 @@
|
||||
/* Interrupt and Configuration Register (VIPER_ICR) */
|
||||
/* This is a write only register. Only CF_RST is used under Linux */
|
||||
|
||||
extern void viper_cf_rst(int state);
|
||||
|
||||
#define VIPER_ICR_RETRIG (1 << 0)
|
||||
#define VIPER_ICR_AUTO_CLR (1 << 1)
|
||||
#define VIPER_ICR_R_DIS (1 << 2)
|
||||
|
82
arch/arm/mach-pxa/include/mach/zeus.h
Normal file
82
arch/arm/mach-pxa/include/mach/zeus.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* arch/arm/mach-pxa/include/mach/zeus.h
|
||||
*
|
||||
* Author: David Vrabel
|
||||
* Created: Sept 28, 2005
|
||||
* Copyright: Arcom Control Systems Ltd.
|
||||
*
|
||||
* Maintained by: Marc Zyngier <maz@misterjones.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.
|
||||
*/
|
||||
|
||||
#ifndef _MACH_ZEUS_H
|
||||
#define _MACH_ZEUS_H
|
||||
|
||||
/* Physical addresses */
|
||||
#define ZEUS_FLASH_PHYS PXA_CS0_PHYS
|
||||
#define ZEUS_ETH0_PHYS PXA_CS1_PHYS
|
||||
#define ZEUS_ETH1_PHYS PXA_CS2_PHYS
|
||||
#define ZEUS_CPLD_PHYS (PXA_CS4_PHYS+0x2000000)
|
||||
#define ZEUS_SRAM_PHYS PXA_CS5_PHYS
|
||||
#define ZEUS_PC104IO_PHYS (0x30000000)
|
||||
|
||||
#define ZEUS_CPLD_VERSION_PHYS (ZEUS_CPLD_PHYS + 0x00000000)
|
||||
#define ZEUS_CPLD_ISA_IRQ_PHYS (ZEUS_CPLD_PHYS + 0x00800000)
|
||||
#define ZEUS_CPLD_CONTROL_PHYS (ZEUS_CPLD_PHYS + 0x01000000)
|
||||
#define ZEUS_CPLD_EXTWDOG_PHYS (ZEUS_CPLD_PHYS + 0x01800000)
|
||||
|
||||
/* GPIOs */
|
||||
#define ZEUS_AC97_GPIO 0
|
||||
#define ZEUS_WAKEUP_GPIO 1
|
||||
#define ZEUS_UARTA_GPIO 9
|
||||
#define ZEUS_UARTB_GPIO 10
|
||||
#define ZEUS_UARTC_GPIO 12
|
||||
#define ZEUS_UARTD_GPIO 11
|
||||
#define ZEUS_ETH0_GPIO 14
|
||||
#define ZEUS_ISA_GPIO 17
|
||||
#define ZEUS_BKLEN_GPIO 19
|
||||
#define ZEUS_USB2_PWREN_GPIO 22
|
||||
#define ZEUS_PTT_GPIO 27
|
||||
#define ZEUS_CF_CD_GPIO 35
|
||||
#define ZEUS_MMC_WP_GPIO 52
|
||||
#define ZEUS_MMC_CD_GPIO 53
|
||||
#define ZEUS_EXTGPIO_GPIO 91
|
||||
#define ZEUS_CF_PWEN_GPIO 97
|
||||
#define ZEUS_CF_RDY_GPIO 99
|
||||
#define ZEUS_LCD_EN_GPIO 101
|
||||
#define ZEUS_ETH1_GPIO 113
|
||||
#define ZEUS_CAN_GPIO 116
|
||||
|
||||
#define ZEUS_EXT0_GPIO_BASE 128
|
||||
#define ZEUS_EXT1_GPIO_BASE 160
|
||||
#define ZEUS_USER_GPIO_BASE 192
|
||||
|
||||
#define ZEUS_EXT0_GPIO(x) (ZEUS_EXT0_GPIO_BASE + (x))
|
||||
#define ZEUS_EXT1_GPIO(x) (ZEUS_EXT1_GPIO_BASE + (x))
|
||||
#define ZEUS_USER_GPIO(x) (ZEUS_USER_GPIO_BASE + (x))
|
||||
|
||||
/*
|
||||
* CPLD registers:
|
||||
* Only 4 registers, but spreaded over a 32MB address space.
|
||||
* Be gentle, and remap that over 32kB...
|
||||
*/
|
||||
|
||||
#define ZEUS_CPLD (0xf0000000)
|
||||
#define ZEUS_CPLD_VERSION (ZEUS_CPLD + 0x0000)
|
||||
#define ZEUS_CPLD_ISA_IRQ (ZEUS_CPLD + 0x1000)
|
||||
#define ZEUS_CPLD_CONTROL (ZEUS_CPLD + 0x2000)
|
||||
#define ZEUS_CPLD_EXTWDOG (ZEUS_CPLD + 0x3000)
|
||||
|
||||
/* CPLD register bits */
|
||||
#define ZEUS_CPLD_CONTROL_CF_RST 0x01
|
||||
|
||||
#define ZEUS_PC104IO (0xf1000000)
|
||||
|
||||
#define ZEUS_SRAM_SIZE (256 * 1024)
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include <mach/pxafb.h>
|
||||
#include <plat/i2c.h>
|
||||
#include <mach/regs-uart.h>
|
||||
#include <mach/arcom-pcmcia.h>
|
||||
#include <mach/viper.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
@ -76,14 +77,28 @@ static void viper_icr_clear_bit(unsigned int bit)
|
||||
}
|
||||
|
||||
/* This function is used from the pcmcia module to reset the CF */
|
||||
void viper_cf_rst(int state)
|
||||
static void viper_cf_reset(int state)
|
||||
{
|
||||
if (state)
|
||||
viper_icr_set_bit(VIPER_ICR_CF_RST);
|
||||
else
|
||||
viper_icr_clear_bit(VIPER_ICR_CF_RST);
|
||||
}
|
||||
EXPORT_SYMBOL(viper_cf_rst);
|
||||
|
||||
static struct arcom_pcmcia_pdata viper_pcmcia_info = {
|
||||
.cd_gpio = VIPER_CF_CD_GPIO,
|
||||
.rdy_gpio = VIPER_CF_RDY_GPIO,
|
||||
.pwr_gpio = VIPER_CF_POWER_GPIO,
|
||||
.reset = viper_cf_reset,
|
||||
};
|
||||
|
||||
static struct platform_device viper_pcmcia_device = {
|
||||
.name = "viper-pcmcia",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &viper_pcmcia_info,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* The CPLD version register was not present on VIPER boards prior to
|
||||
@ -685,6 +700,7 @@ static struct platform_device *viper_devs[] __initdata = {
|
||||
&viper_mtd_devices[0],
|
||||
&viper_mtd_devices[1],
|
||||
&viper_backlight_device,
|
||||
&viper_pcmcia_device,
|
||||
};
|
||||
|
||||
static mfp_cfg_t viper_pin_config[] __initdata = {
|
||||
|
820
arch/arm/mach-pxa/zeus.c
Normal file
820
arch/arm/mach-pxa/zeus.c
Normal file
@ -0,0 +1,820 @@
|
||||
/*
|
||||
* Support for the Arcom ZEUS.
|
||||
*
|
||||
* Copyright (C) 2006 Arcom Control Systems Ltd.
|
||||
*
|
||||
* Loosely based on Arcom's 2.6.16.28.
|
||||
* Maintained by Marc Zyngier <maz@misterjones.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/cpufreq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/dm9000.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/mtd/physmap.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c/pca953x.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include <plat/i2c.h>
|
||||
|
||||
#include <mach/pxa2xx-regs.h>
|
||||
#include <mach/regs-uart.h>
|
||||
#include <mach/ohci.h>
|
||||
#include <mach/mmc.h>
|
||||
#include <mach/pxa27x-udc.h>
|
||||
#include <mach/udc.h>
|
||||
#include <mach/pxafb.h>
|
||||
#include <mach/pxa2xx_spi.h>
|
||||
#include <mach/mfp-pxa27x.h>
|
||||
#include <mach/pm.h>
|
||||
#include <mach/audio.h>
|
||||
#include <mach/arcom-pcmcia.h>
|
||||
#include <mach/zeus.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
/*
|
||||
* Interrupt handling
|
||||
*/
|
||||
|
||||
static unsigned long zeus_irq_enabled_mask;
|
||||
static const int zeus_isa_irqs[] = { 3, 4, 5, 6, 7, 10, 11, 12, };
|
||||
static const int zeus_isa_irq_map[] = {
|
||||
0, /* ISA irq #0, invalid */
|
||||
0, /* ISA irq #1, invalid */
|
||||
0, /* ISA irq #2, invalid */
|
||||
1 << 0, /* ISA irq #3 */
|
||||
1 << 1, /* ISA irq #4 */
|
||||
1 << 2, /* ISA irq #5 */
|
||||
1 << 3, /* ISA irq #6 */
|
||||
1 << 4, /* ISA irq #7 */
|
||||
0, /* ISA irq #8, invalid */
|
||||
0, /* ISA irq #9, invalid */
|
||||
1 << 5, /* ISA irq #10 */
|
||||
1 << 6, /* ISA irq #11 */
|
||||
1 << 7, /* ISA irq #12 */
|
||||
};
|
||||
|
||||
static inline int zeus_irq_to_bitmask(unsigned int irq)
|
||||
{
|
||||
return zeus_isa_irq_map[irq - PXA_ISA_IRQ(0)];
|
||||
}
|
||||
|
||||
static inline int zeus_bit_to_irq(int bit)
|
||||
{
|
||||
return zeus_isa_irqs[bit] + PXA_ISA_IRQ(0);
|
||||
}
|
||||
|
||||
static void zeus_ack_irq(unsigned int irq)
|
||||
{
|
||||
__raw_writew(zeus_irq_to_bitmask(irq), ZEUS_CPLD_ISA_IRQ);
|
||||
}
|
||||
|
||||
static void zeus_mask_irq(unsigned int irq)
|
||||
{
|
||||
zeus_irq_enabled_mask &= ~(zeus_irq_to_bitmask(irq));
|
||||
}
|
||||
|
||||
static void zeus_unmask_irq(unsigned int irq)
|
||||
{
|
||||
zeus_irq_enabled_mask |= zeus_irq_to_bitmask(irq);
|
||||
}
|
||||
|
||||
static inline unsigned long zeus_irq_pending(void)
|
||||
{
|
||||
return __raw_readw(ZEUS_CPLD_ISA_IRQ) & zeus_irq_enabled_mask;
|
||||
}
|
||||
|
||||
static void zeus_irq_handler(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
unsigned long pending;
|
||||
|
||||
pending = zeus_irq_pending();
|
||||
do {
|
||||
/* we're in a chained irq handler,
|
||||
* so ack the interrupt by hand */
|
||||
desc->chip->ack(gpio_to_irq(ZEUS_ISA_GPIO));
|
||||
|
||||
if (likely(pending)) {
|
||||
irq = zeus_bit_to_irq(__ffs(pending));
|
||||
generic_handle_irq(irq);
|
||||
}
|
||||
pending = zeus_irq_pending();
|
||||
} while (pending);
|
||||
}
|
||||
|
||||
static struct irq_chip zeus_irq_chip = {
|
||||
.name = "ISA",
|
||||
.ack = zeus_ack_irq,
|
||||
.mask = zeus_mask_irq,
|
||||
.unmask = zeus_unmask_irq,
|
||||
};
|
||||
|
||||
static void __init zeus_init_irq(void)
|
||||
{
|
||||
int level;
|
||||
int isa_irq;
|
||||
|
||||
pxa27x_init_irq();
|
||||
|
||||
/* Peripheral IRQs. It would be nice to move those inside driver
|
||||
configuration, but it is not supported at the moment. */
|
||||
set_irq_type(gpio_to_irq(ZEUS_AC97_GPIO), IRQ_TYPE_EDGE_RISING);
|
||||
set_irq_type(gpio_to_irq(ZEUS_WAKEUP_GPIO), IRQ_TYPE_EDGE_RISING);
|
||||
set_irq_type(gpio_to_irq(ZEUS_PTT_GPIO), IRQ_TYPE_EDGE_RISING);
|
||||
set_irq_type(gpio_to_irq(ZEUS_EXTGPIO_GPIO), IRQ_TYPE_EDGE_FALLING);
|
||||
set_irq_type(gpio_to_irq(ZEUS_CAN_GPIO), IRQ_TYPE_EDGE_FALLING);
|
||||
|
||||
/* Setup ISA IRQs */
|
||||
for (level = 0; level < ARRAY_SIZE(zeus_isa_irqs); level++) {
|
||||
isa_irq = zeus_bit_to_irq(level);
|
||||
set_irq_chip(isa_irq, &zeus_irq_chip);
|
||||
set_irq_handler(isa_irq, handle_edge_irq);
|
||||
set_irq_flags(isa_irq, IRQF_VALID | IRQF_PROBE);
|
||||
}
|
||||
|
||||
set_irq_type(gpio_to_irq(ZEUS_ISA_GPIO), IRQ_TYPE_EDGE_RISING);
|
||||
set_irq_chained_handler(gpio_to_irq(ZEUS_ISA_GPIO), zeus_irq_handler);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Platform devices
|
||||
*/
|
||||
|
||||
/* Flash */
|
||||
static struct resource zeus_mtd_resources[] = {
|
||||
[0] = { /* NOR Flash (up to 64MB) */
|
||||
.start = ZEUS_FLASH_PHYS,
|
||||
.end = ZEUS_FLASH_PHYS + SZ_64M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = { /* SRAM */
|
||||
.start = ZEUS_SRAM_PHYS,
|
||||
.end = ZEUS_SRAM_PHYS + SZ_512K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct physmap_flash_data zeus_flash_data[] = {
|
||||
[0] = {
|
||||
.width = 2,
|
||||
.parts = NULL,
|
||||
.nr_parts = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device zeus_mtd_devices[] = {
|
||||
[0] = {
|
||||
.name = "physmap-flash",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &zeus_flash_data[0],
|
||||
},
|
||||
.resource = &zeus_mtd_resources[0],
|
||||
.num_resources = 1,
|
||||
},
|
||||
};
|
||||
|
||||
/* Serial */
|
||||
static struct resource zeus_serial_resources[] = {
|
||||
{
|
||||
.start = 0x10000000,
|
||||
.end = 0x1000000f,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = 0x10800000,
|
||||
.end = 0x1080000f,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = 0x11000000,
|
||||
.end = 0x1100000f,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = 0x40100000,
|
||||
.end = 0x4010001f,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = 0x40200000,
|
||||
.end = 0x4020001f,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = 0x40700000,
|
||||
.end = 0x4070001f,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct plat_serial8250_port serial_platform_data[] = {
|
||||
/* External UARTs */
|
||||
/* FIXME: Shared IRQs on COM1-COM4 will not work properly on v1i1 hardware. */
|
||||
{ /* COM1 */
|
||||
.mapbase = 0x10000000,
|
||||
.irq = gpio_to_irq(ZEUS_UARTA_GPIO),
|
||||
.irqflags = IRQF_TRIGGER_RISING,
|
||||
.uartclk = 14745600,
|
||||
.regshift = 1,
|
||||
.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
|
||||
.iotype = UPIO_MEM,
|
||||
},
|
||||
{ /* COM2 */
|
||||
.mapbase = 0x10800000,
|
||||
.irq = gpio_to_irq(ZEUS_UARTB_GPIO),
|
||||
.irqflags = IRQF_TRIGGER_RISING,
|
||||
.uartclk = 14745600,
|
||||
.regshift = 1,
|
||||
.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
|
||||
.iotype = UPIO_MEM,
|
||||
},
|
||||
{ /* COM3 */
|
||||
.mapbase = 0x11000000,
|
||||
.irq = gpio_to_irq(ZEUS_UARTC_GPIO),
|
||||
.irqflags = IRQF_TRIGGER_RISING,
|
||||
.uartclk = 14745600,
|
||||
.regshift = 1,
|
||||
.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
|
||||
.iotype = UPIO_MEM,
|
||||
},
|
||||
{ /* COM4 */
|
||||
.mapbase = 0x11800000,
|
||||
.irq = gpio_to_irq(ZEUS_UARTD_GPIO),
|
||||
.irqflags = IRQF_TRIGGER_RISING,
|
||||
.uartclk = 14745600,
|
||||
.regshift = 1,
|
||||
.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
|
||||
.iotype = UPIO_MEM,
|
||||
},
|
||||
/* Internal UARTs */
|
||||
{ /* FFUART */
|
||||
.membase = (void *)&FFUART,
|
||||
.mapbase = __PREG(FFUART),
|
||||
.irq = IRQ_FFUART,
|
||||
.uartclk = 921600 * 16,
|
||||
.regshift = 2,
|
||||
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
|
||||
.iotype = UPIO_MEM,
|
||||
},
|
||||
{ /* BTUART */
|
||||
.membase = (void *)&BTUART,
|
||||
.mapbase = __PREG(BTUART),
|
||||
.irq = IRQ_BTUART,
|
||||
.uartclk = 921600 * 16,
|
||||
.regshift = 2,
|
||||
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
|
||||
.iotype = UPIO_MEM,
|
||||
},
|
||||
{ /* STUART */
|
||||
.membase = (void *)&STUART,
|
||||
.mapbase = __PREG(STUART),
|
||||
.irq = IRQ_STUART,
|
||||
.uartclk = 921600 * 16,
|
||||
.regshift = 2,
|
||||
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
|
||||
.iotype = UPIO_MEM,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_device zeus_serial_device = {
|
||||
.name = "serial8250",
|
||||
.id = PLAT8250_DEV_PLATFORM,
|
||||
.dev = {
|
||||
.platform_data = serial_platform_data,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(zeus_serial_resources),
|
||||
.resource = zeus_serial_resources,
|
||||
};
|
||||
|
||||
/* Ethernet */
|
||||
static struct resource zeus_dm9k0_resource[] = {
|
||||
[0] = {
|
||||
.start = ZEUS_ETH0_PHYS,
|
||||
.end = ZEUS_ETH0_PHYS + 1,
|
||||
.flags = IORESOURCE_MEM
|
||||
},
|
||||
[1] = {
|
||||
.start = ZEUS_ETH0_PHYS + 2,
|
||||
.end = ZEUS_ETH0_PHYS + 3,
|
||||
.flags = IORESOURCE_MEM
|
||||
},
|
||||
[2] = {
|
||||
.start = gpio_to_irq(ZEUS_ETH0_GPIO),
|
||||
.end = gpio_to_irq(ZEUS_ETH0_GPIO),
|
||||
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource zeus_dm9k1_resource[] = {
|
||||
[0] = {
|
||||
.start = ZEUS_ETH1_PHYS,
|
||||
.end = ZEUS_ETH1_PHYS + 1,
|
||||
.flags = IORESOURCE_MEM
|
||||
},
|
||||
[1] = {
|
||||
.start = ZEUS_ETH1_PHYS + 2,
|
||||
.end = ZEUS_ETH1_PHYS + 3,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[2] = {
|
||||
.start = gpio_to_irq(ZEUS_ETH1_GPIO),
|
||||
.end = gpio_to_irq(ZEUS_ETH1_GPIO),
|
||||
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct dm9000_plat_data zeus_dm9k_platdata = {
|
||||
.flags = DM9000_PLATF_16BITONLY,
|
||||
};
|
||||
|
||||
static struct platform_device zeus_dm9k0_device = {
|
||||
.name = "dm9000",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(zeus_dm9k0_resource),
|
||||
.resource = zeus_dm9k0_resource,
|
||||
.dev = {
|
||||
.platform_data = &zeus_dm9k_platdata,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device zeus_dm9k1_device = {
|
||||
.name = "dm9000",
|
||||
.id = 1,
|
||||
.num_resources = ARRAY_SIZE(zeus_dm9k1_resource),
|
||||
.resource = zeus_dm9k1_resource,
|
||||
.dev = {
|
||||
.platform_data = &zeus_dm9k_platdata,
|
||||
}
|
||||
};
|
||||
|
||||
/* External SRAM */
|
||||
static struct resource zeus_sram_resource = {
|
||||
.start = ZEUS_SRAM_PHYS,
|
||||
.end = ZEUS_SRAM_PHYS + ZEUS_SRAM_SIZE * 2 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
static struct platform_device zeus_sram_device = {
|
||||
.name = "pxa2xx-8bit-sram",
|
||||
.id = 0,
|
||||
.num_resources = 1,
|
||||
.resource = &zeus_sram_resource,
|
||||
};
|
||||
|
||||
/* SPI interface on SSP3 */
|
||||
static struct pxa2xx_spi_master pxa2xx_spi_ssp3_master_info = {
|
||||
.num_chipselect = 1,
|
||||
.enable_dma = 1,
|
||||
};
|
||||
|
||||
static struct platform_device pxa2xx_spi_ssp3_device = {
|
||||
.name = "pxa2xx-spi",
|
||||
.id = 3,
|
||||
.dev = {
|
||||
.platform_data = &pxa2xx_spi_ssp3_master_info,
|
||||
},
|
||||
};
|
||||
|
||||
/* Leds */
|
||||
static struct gpio_led zeus_leds[] = {
|
||||
[0] = {
|
||||
.name = "zeus:yellow:1",
|
||||
.default_trigger = "heartbeat",
|
||||
.gpio = ZEUS_EXT0_GPIO(3),
|
||||
.active_low = 1,
|
||||
},
|
||||
[1] = {
|
||||
.name = "zeus:yellow:2",
|
||||
.default_trigger = "default-on",
|
||||
.gpio = ZEUS_EXT0_GPIO(4),
|
||||
.active_low = 1,
|
||||
},
|
||||
[2] = {
|
||||
.name = "zeus:yellow:3",
|
||||
.default_trigger = "default-on",
|
||||
.gpio = ZEUS_EXT0_GPIO(5),
|
||||
.active_low = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct gpio_led_platform_data zeus_leds_info = {
|
||||
.leds = zeus_leds,
|
||||
.num_leds = ARRAY_SIZE(zeus_leds),
|
||||
};
|
||||
|
||||
static struct platform_device zeus_leds_device = {
|
||||
.name = "leds-gpio",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &zeus_leds_info,
|
||||
},
|
||||
};
|
||||
|
||||
static void zeus_cf_reset(int state)
|
||||
{
|
||||
u16 cpld_state = __raw_readw(ZEUS_CPLD_CONTROL);
|
||||
|
||||
if (state)
|
||||
cpld_state |= ZEUS_CPLD_CONTROL_CF_RST;
|
||||
else
|
||||
cpld_state &= ~ZEUS_CPLD_CONTROL_CF_RST;
|
||||
|
||||
__raw_writew(cpld_state, ZEUS_CPLD_CONTROL);
|
||||
}
|
||||
|
||||
static struct arcom_pcmcia_pdata zeus_pcmcia_info = {
|
||||
.cd_gpio = ZEUS_CF_CD_GPIO,
|
||||
.rdy_gpio = ZEUS_CF_RDY_GPIO,
|
||||
.pwr_gpio = ZEUS_CF_PWEN_GPIO,
|
||||
.reset = zeus_cf_reset,
|
||||
};
|
||||
|
||||
static struct platform_device zeus_pcmcia_device = {
|
||||
.name = "zeus-pcmcia",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &zeus_pcmcia_info,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device *zeus_devices[] __initdata = {
|
||||
&zeus_serial_device,
|
||||
&zeus_mtd_devices[0],
|
||||
&zeus_dm9k0_device,
|
||||
&zeus_dm9k1_device,
|
||||
&zeus_sram_device,
|
||||
&pxa2xx_spi_ssp3_device,
|
||||
&zeus_leds_device,
|
||||
&zeus_pcmcia_device,
|
||||
};
|
||||
|
||||
/* AC'97 */
|
||||
static pxa2xx_audio_ops_t zeus_ac97_info = {
|
||||
.reset_gpio = 95,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* USB host
|
||||
*/
|
||||
|
||||
static int zeus_ohci_init(struct device *dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Switch on port 2. */
|
||||
if ((err = gpio_request(ZEUS_USB2_PWREN_GPIO, "USB2_PWREN"))) {
|
||||
dev_err(dev, "Can't request USB2_PWREN\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if ((err = gpio_direction_output(ZEUS_USB2_PWREN_GPIO, 1))) {
|
||||
gpio_free(ZEUS_USB2_PWREN_GPIO);
|
||||
dev_err(dev, "Can't enable USB2_PWREN\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Port 2 is shared between host and client interface. */
|
||||
UP2OCR = UP2OCR_HXOE | UP2OCR_HXS | UP2OCR_DMPDE | UP2OCR_DPPDE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void zeus_ohci_exit(struct device *dev)
|
||||
{
|
||||
/* Power-off port 2 */
|
||||
gpio_direction_output(ZEUS_USB2_PWREN_GPIO, 0);
|
||||
gpio_free(ZEUS_USB2_PWREN_GPIO);
|
||||
}
|
||||
|
||||
static struct pxaohci_platform_data zeus_ohci_platform_data = {
|
||||
.port_mode = PMM_NPS_MODE,
|
||||
.flags = ENABLE_PORT_ALL | POWER_CONTROL_LOW | POWER_SENSE_LOW,
|
||||
.init = zeus_ohci_init,
|
||||
.exit = zeus_ohci_exit,
|
||||
};
|
||||
|
||||
/*
|
||||
* Flat Panel
|
||||
*/
|
||||
|
||||
static void zeus_lcd_power(int on, struct fb_var_screeninfo *si)
|
||||
{
|
||||
gpio_set_value(ZEUS_LCD_EN_GPIO, on);
|
||||
}
|
||||
|
||||
static void zeus_backlight_power(int on)
|
||||
{
|
||||
gpio_set_value(ZEUS_BKLEN_GPIO, on);
|
||||
}
|
||||
|
||||
static int zeus_setup_fb_gpios(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
if ((err = gpio_request(ZEUS_LCD_EN_GPIO, "LCD_EN")))
|
||||
goto out_err;
|
||||
|
||||
if ((err = gpio_direction_output(ZEUS_LCD_EN_GPIO, 0)))
|
||||
goto out_err_lcd;
|
||||
|
||||
if ((err = gpio_request(ZEUS_BKLEN_GPIO, "BKLEN")))
|
||||
goto out_err_lcd;
|
||||
|
||||
if ((err = gpio_direction_output(ZEUS_BKLEN_GPIO, 0)))
|
||||
goto out_err_bkl;
|
||||
|
||||
return 0;
|
||||
|
||||
out_err_bkl:
|
||||
gpio_free(ZEUS_BKLEN_GPIO);
|
||||
out_err_lcd:
|
||||
gpio_free(ZEUS_LCD_EN_GPIO);
|
||||
out_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct pxafb_mode_info zeus_fb_mode_info[] = {
|
||||
{
|
||||
.pixclock = 39722,
|
||||
|
||||
.xres = 640,
|
||||
.yres = 480,
|
||||
|
||||
.bpp = 16,
|
||||
|
||||
.hsync_len = 63,
|
||||
.left_margin = 16,
|
||||
.right_margin = 81,
|
||||
|
||||
.vsync_len = 2,
|
||||
.upper_margin = 12,
|
||||
.lower_margin = 31,
|
||||
|
||||
.sync = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct pxafb_mach_info zeus_fb_info = {
|
||||
.modes = zeus_fb_mode_info,
|
||||
.num_modes = 1,
|
||||
.lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
|
||||
.pxafb_lcd_power = zeus_lcd_power,
|
||||
.pxafb_backlight_power = zeus_backlight_power,
|
||||
};
|
||||
|
||||
/*
|
||||
* MMC/SD Device
|
||||
*
|
||||
* The card detect interrupt isn't debounced so we delay it by 250ms
|
||||
* to give the card a chance to fully insert/eject.
|
||||
*/
|
||||
|
||||
static struct pxamci_platform_data zeus_mci_platform_data = {
|
||||
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
|
||||
.detect_delay = HZ/4,
|
||||
.gpio_card_detect = ZEUS_MMC_CD_GPIO,
|
||||
.gpio_card_ro = ZEUS_MMC_WP_GPIO,
|
||||
.gpio_card_ro_invert = 1,
|
||||
.gpio_power = -1
|
||||
};
|
||||
|
||||
/*
|
||||
* USB Device Controller
|
||||
*/
|
||||
static void zeus_udc_command(int cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
case PXA2XX_UDC_CMD_DISCONNECT:
|
||||
pr_info("zeus: disconnecting USB client\n");
|
||||
UP2OCR = UP2OCR_HXOE | UP2OCR_HXS | UP2OCR_DMPDE | UP2OCR_DPPDE;
|
||||
break;
|
||||
|
||||
case PXA2XX_UDC_CMD_CONNECT:
|
||||
pr_info("zeus: connecting USB client\n");
|
||||
UP2OCR = UP2OCR_HXOE | UP2OCR_DPPUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct pxa2xx_udc_mach_info zeus_udc_info = {
|
||||
.udc_command = zeus_udc_command,
|
||||
};
|
||||
|
||||
static void zeus_power_off(void)
|
||||
{
|
||||
local_irq_disable();
|
||||
pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP);
|
||||
}
|
||||
|
||||
int zeus_get_pcb_info(struct i2c_client *client, unsigned gpio,
|
||||
unsigned ngpio, void *context)
|
||||
{
|
||||
int i;
|
||||
u8 pcb_info = 0;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
int pcb_bit = gpio + i + 8;
|
||||
|
||||
if (gpio_request(pcb_bit, "pcb info")) {
|
||||
dev_err(&client->dev, "Can't request pcb info %d\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (gpio_direction_input(pcb_bit)) {
|
||||
dev_err(&client->dev, "Can't read pcb info %d\n", i);
|
||||
gpio_free(pcb_bit);
|
||||
continue;
|
||||
}
|
||||
|
||||
pcb_info |= !!gpio_get_value(pcb_bit) << i;
|
||||
|
||||
gpio_free(pcb_bit);
|
||||
}
|
||||
|
||||
dev_info(&client->dev, "Zeus PCB version %d issue %d\n",
|
||||
pcb_info >> 4, pcb_info & 0xf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pca953x_platform_data zeus_pca953x_pdata[] = {
|
||||
[0] = { .gpio_base = ZEUS_EXT0_GPIO_BASE, },
|
||||
[1] = {
|
||||
.gpio_base = ZEUS_EXT1_GPIO_BASE,
|
||||
.setup = zeus_get_pcb_info,
|
||||
},
|
||||
[2] = { .gpio_base = ZEUS_USER_GPIO_BASE, },
|
||||
};
|
||||
|
||||
static struct i2c_board_info __initdata zeus_i2c_devices[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("pca9535", 0x21),
|
||||
.platform_data = &zeus_pca953x_pdata[0],
|
||||
},
|
||||
{
|
||||
I2C_BOARD_INFO("pca9535", 0x22),
|
||||
.platform_data = &zeus_pca953x_pdata[1],
|
||||
},
|
||||
{
|
||||
I2C_BOARD_INFO("pca9535", 0x20),
|
||||
.platform_data = &zeus_pca953x_pdata[2],
|
||||
.irq = gpio_to_irq(ZEUS_EXTGPIO_GPIO),
|
||||
},
|
||||
{ I2C_BOARD_INFO("lm75a", 0x48) },
|
||||
{ I2C_BOARD_INFO("24c01", 0x50) },
|
||||
{ I2C_BOARD_INFO("isl1208", 0x6f) },
|
||||
};
|
||||
|
||||
static mfp_cfg_t zeus_pin_config[] __initdata = {
|
||||
GPIO15_nCS_1,
|
||||
GPIO78_nCS_2,
|
||||
GPIO80_nCS_4,
|
||||
GPIO33_nCS_5,
|
||||
|
||||
GPIO22_GPIO,
|
||||
GPIO32_MMC_CLK,
|
||||
GPIO92_MMC_DAT_0,
|
||||
GPIO109_MMC_DAT_1,
|
||||
GPIO110_MMC_DAT_2,
|
||||
GPIO111_MMC_DAT_3,
|
||||
GPIO112_MMC_CMD,
|
||||
|
||||
GPIO88_USBH1_PWR,
|
||||
GPIO89_USBH1_PEN,
|
||||
GPIO119_USBH2_PWR,
|
||||
GPIO120_USBH2_PEN,
|
||||
|
||||
GPIO86_LCD_LDD_16,
|
||||
GPIO87_LCD_LDD_17,
|
||||
|
||||
GPIO102_GPIO,
|
||||
GPIO104_CIF_DD_2,
|
||||
GPIO105_CIF_DD_1,
|
||||
|
||||
GPIO48_nPOE,
|
||||
GPIO49_nPWE,
|
||||
GPIO50_nPIOR,
|
||||
GPIO51_nPIOW,
|
||||
GPIO85_nPCE_1,
|
||||
GPIO54_nPCE_2,
|
||||
GPIO79_PSKTSEL,
|
||||
GPIO55_nPREG,
|
||||
GPIO56_nPWAIT,
|
||||
GPIO57_nIOIS16,
|
||||
GPIO36_GPIO, /* CF CD */
|
||||
GPIO97_GPIO, /* CF PWREN */
|
||||
GPIO99_GPIO, /* CF RDY */
|
||||
};
|
||||
|
||||
static void __init zeus_init(void)
|
||||
{
|
||||
u16 dm9000_msc = 0xe279;
|
||||
|
||||
system_rev = __raw_readw(ZEUS_CPLD_VERSION);
|
||||
pr_info("Zeus CPLD V%dI%d\n", (system_rev & 0xf0) >> 4, (system_rev & 0x0f));
|
||||
|
||||
/* Fix timings for dm9000s (CS1/CS2)*/
|
||||
MSC0 = (MSC0 & 0xffff) | (dm9000_msc << 16);
|
||||
MSC1 = (MSC1 & 0xffff0000) | dm9000_msc;
|
||||
|
||||
pm_power_off = zeus_power_off;
|
||||
|
||||
pxa2xx_mfp_config(ARRAY_AND_SIZE(zeus_pin_config));
|
||||
|
||||
platform_add_devices(zeus_devices, ARRAY_SIZE(zeus_devices));
|
||||
|
||||
pxa_set_ohci_info(&zeus_ohci_platform_data);
|
||||
|
||||
if (zeus_setup_fb_gpios())
|
||||
pr_err("Failed to setup fb gpios\n");
|
||||
else
|
||||
set_pxa_fb_info(&zeus_fb_info);
|
||||
|
||||
pxa_set_mci_info(&zeus_mci_platform_data);
|
||||
pxa_set_udc_info(&zeus_udc_info);
|
||||
pxa_set_ac97_info(&zeus_ac97_info);
|
||||
pxa_set_i2c_info(NULL);
|
||||
i2c_register_board_info(0, ARRAY_AND_SIZE(zeus_i2c_devices));
|
||||
}
|
||||
|
||||
static struct map_desc zeus_io_desc[] __initdata = {
|
||||
{
|
||||
.virtual = ZEUS_CPLD_VERSION,
|
||||
.pfn = __phys_to_pfn(ZEUS_CPLD_VERSION_PHYS),
|
||||
.length = 0x1000,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
{
|
||||
.virtual = ZEUS_CPLD_ISA_IRQ,
|
||||
.pfn = __phys_to_pfn(ZEUS_CPLD_ISA_IRQ_PHYS),
|
||||
.length = 0x1000,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
{
|
||||
.virtual = ZEUS_CPLD_CONTROL,
|
||||
.pfn = __phys_to_pfn(ZEUS_CPLD_CONTROL_PHYS),
|
||||
.length = 0x1000,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
{
|
||||
.virtual = ZEUS_CPLD_EXTWDOG,
|
||||
.pfn = __phys_to_pfn(ZEUS_CPLD_EXTWDOG_PHYS),
|
||||
.length = 0x1000,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
{
|
||||
.virtual = ZEUS_PC104IO,
|
||||
.pfn = __phys_to_pfn(ZEUS_PC104IO_PHYS),
|
||||
.length = 0x00800000,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
};
|
||||
|
||||
static void __init zeus_map_io(void)
|
||||
{
|
||||
pxa_map_io();
|
||||
|
||||
iotable_init(zeus_io_desc, ARRAY_SIZE(zeus_io_desc));
|
||||
|
||||
/* Clear PSPR to ensure a full restart on wake-up. */
|
||||
PMCR = PSPR = 0;
|
||||
|
||||
/* enable internal 32.768Khz oscillator (ignore OSCC_OOK) */
|
||||
OSCC |= OSCC_OON;
|
||||
|
||||
/* Some clock cycles later (from OSCC_ON), programme PCFR (OPDE...).
|
||||
* float chip selects and PCMCIA */
|
||||
PCFR = PCFR_OPDE | PCFR_DC_EN | PCFR_FS | PCFR_FP;
|
||||
}
|
||||
|
||||
MACHINE_START(ARCOM_ZEUS, "Arcom ZEUS")
|
||||
/* Maintainer: Marc Zyngier <maz@misterjones.org> */
|
||||
.phys_io = 0x40000000,
|
||||
.io_pg_offst = ((io_p2v(0x40000000) >> 18) & 0xfffc),
|
||||
.boot_params = 0xa0000100,
|
||||
.map_io = zeus_map_io,
|
||||
.init_irq = zeus_init_irq,
|
||||
.timer = &pxa_timer,
|
||||
.init_machine = zeus_init,
|
||||
MACHINE_END
|
||||
|
@ -70,7 +70,7 @@ config MACH_REALVIEW_PBX
|
||||
bool "Support RealView/PBX platform"
|
||||
select ARM_GIC
|
||||
select HAVE_PATA_PLATFORM
|
||||
select ARCH_SPARSEMEM_ENABLE if CPU_V7 && !HIGH_PHYS_OFFSET
|
||||
select ARCH_SPARSEMEM_ENABLE if CPU_V7 && !REALVIEW_HIGH_PHYS_OFFSET
|
||||
select ZONE_DMA if SPARSEMEM
|
||||
help
|
||||
Include support for the ARM(R) RealView PBX platform.
|
||||
|
@ -15,5 +15,7 @@
|
||||
|
||||
#define __virt_to_bus(x) __virt_to_phys(x)
|
||||
#define __bus_to_virt(x) __phys_to_virt(x)
|
||||
#define __pfn_to_bus(x) __pfn_to_phys(x)
|
||||
#define __bus_to_pfn(x) __phys_to_pfn(x)
|
||||
|
||||
#endif
|
||||
|
@ -4,6 +4,7 @@ menu "SA11x0 Implementations"
|
||||
|
||||
config SA1100_ASSABET
|
||||
bool "Assabet"
|
||||
select CPU_FREQ_SA1110
|
||||
help
|
||||
Say Y here if you are using the Intel(R) StrongARM(R) SA-1110
|
||||
Microprocessor Development Board (also known as the Assabet).
|
||||
@ -19,6 +20,7 @@ config ASSABET_NEPONSET
|
||||
|
||||
config SA1100_CERF
|
||||
bool "CerfBoard"
|
||||
select CPU_FREQ_SA1110
|
||||
help
|
||||
The Intrinsyc CerfBoard is based on the StrongARM 1110 (Discontinued).
|
||||
More information is available at:
|
||||
@ -45,6 +47,7 @@ endchoice
|
||||
|
||||
config SA1100_COLLIE
|
||||
bool "Sharp Zaurus SL5500"
|
||||
# FIXME: select CPU_FREQ_SA11x0
|
||||
select SHARP_LOCOMO
|
||||
select SHARP_SCOOP
|
||||
select SHARP_PARAM
|
||||
@ -54,6 +57,7 @@ config SA1100_COLLIE
|
||||
config SA1100_H3100
|
||||
bool "Compaq iPAQ H3100"
|
||||
select HTC_EGPIO
|
||||
select CPU_FREQ_SA1100
|
||||
help
|
||||
Say Y here if you intend to run this kernel on the Compaq iPAQ
|
||||
H3100 handheld computer. Information about this machine and the
|
||||
@ -64,6 +68,7 @@ config SA1100_H3100
|
||||
config SA1100_H3600
|
||||
bool "Compaq iPAQ H3600/H3700"
|
||||
select HTC_EGPIO
|
||||
select CPU_FREQ_SA1100
|
||||
help
|
||||
Say Y here if you intend to run this kernel on the Compaq iPAQ
|
||||
H3600 handheld computer. Information about this machine and the
|
||||
@ -74,6 +79,7 @@ config SA1100_H3600
|
||||
config SA1100_BADGE4
|
||||
bool "HP Labs BadgePAD 4"
|
||||
select SA1111
|
||||
select CPU_FREQ_SA1100
|
||||
help
|
||||
Say Y here if you want to build a kernel for the HP Laboratories
|
||||
BadgePAD 4.
|
||||
@ -81,6 +87,7 @@ config SA1100_BADGE4
|
||||
config SA1100_JORNADA720
|
||||
bool "HP Jornada 720"
|
||||
select SA1111
|
||||
# FIXME: select CPU_FREQ_SA11x0
|
||||
help
|
||||
Say Y here if you want to build a kernel for the HP Jornada 720
|
||||
handheld computer. See <http://www.hp.com/jornada/products/720>
|
||||
@ -98,12 +105,14 @@ config SA1100_JORNADA720_SSP
|
||||
|
||||
config SA1100_HACKKIT
|
||||
bool "HackKit Core CPU Board"
|
||||
select CPU_FREQ_SA1100
|
||||
help
|
||||
Say Y here to support the HackKit Core CPU Board
|
||||
<http://hackkit.eletztrick.de>;
|
||||
|
||||
config SA1100_LART
|
||||
bool "LART"
|
||||
select CPU_FREQ_SA1100
|
||||
help
|
||||
Say Y here if you are using the Linux Advanced Radio Terminal
|
||||
(also known as the LART). See <http://www.lartmaker.nl/> for
|
||||
@ -111,6 +120,7 @@ config SA1100_LART
|
||||
|
||||
config SA1100_PLEB
|
||||
bool "PLEB"
|
||||
select CPU_FREQ_SA1100
|
||||
help
|
||||
Say Y here if you are using version 1 of the Portable Linux
|
||||
Embedded Board (also known as PLEB).
|
||||
@ -119,6 +129,7 @@ config SA1100_PLEB
|
||||
|
||||
config SA1100_SHANNON
|
||||
bool "Shannon"
|
||||
select CPU_FREQ_SA1100
|
||||
help
|
||||
The Shannon (also known as a Tuxscreen, and also as a IS2630) was a
|
||||
limited edition webphone produced by Philips. The Shannon is a SA1100
|
||||
@ -127,6 +138,7 @@ config SA1100_SHANNON
|
||||
|
||||
config SA1100_SIMPAD
|
||||
bool "Simpad"
|
||||
select CPU_FREQ_SA1110
|
||||
help
|
||||
The SIEMENS webpad SIMpad is based on the StrongARM 1110. There
|
||||
are two different versions CL4 and SL4. CL4 has 32MB RAM and 16MB
|
||||
@ -145,3 +157,4 @@ config SA1100_SSP
|
||||
endmenu
|
||||
|
||||
endif
|
||||
|
||||
|
@ -58,7 +58,6 @@ static const unsigned short cclk_frequency_100khz[NR_FREQS] = {
|
||||
2802 /* 280.2 MHz */
|
||||
};
|
||||
|
||||
#if defined(CONFIG_CPU_FREQ_SA1100) || defined(CONFIG_CPU_FREQ_SA1110)
|
||||
/* rounds up(!) */
|
||||
unsigned int sa11x0_freq_to_ppcr(unsigned int khz)
|
||||
{
|
||||
@ -110,17 +109,6 @@ unsigned int sa11x0_getspeed(unsigned int cpu)
|
||||
return cclk_frequency_100khz[PPCR & 0xf] * 100;
|
||||
}
|
||||
|
||||
#else
|
||||
/*
|
||||
* We still need to provide this so building without cpufreq works.
|
||||
*/
|
||||
unsigned int cpufreq_get(unsigned int cpu)
|
||||
{
|
||||
return cclk_frequency_100khz[PPCR & 0xf] * 100;
|
||||
}
|
||||
EXPORT_SYMBOL(cpufreq_get);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is the SA11x0 sched_clock implementation. This has
|
||||
* a resolution of 271ns, and a maximum value of 32025597s (370 days).
|
||||
|
@ -38,16 +38,72 @@ union vfp_state *last_VFP_context[NR_CPUS];
|
||||
*/
|
||||
unsigned int VFP_arch;
|
||||
|
||||
/*
|
||||
* Per-thread VFP initialization.
|
||||
*/
|
||||
static void vfp_thread_flush(struct thread_info *thread)
|
||||
{
|
||||
union vfp_state *vfp = &thread->vfpstate;
|
||||
unsigned int cpu;
|
||||
|
||||
memset(vfp, 0, sizeof(union vfp_state));
|
||||
|
||||
vfp->hard.fpexc = FPEXC_EN;
|
||||
vfp->hard.fpscr = FPSCR_ROUND_NEAREST;
|
||||
|
||||
/*
|
||||
* Disable VFP to ensure we initialize it first. We must ensure
|
||||
* that the modification of last_VFP_context[] and hardware disable
|
||||
* are done for the same CPU and without preemption.
|
||||
*/
|
||||
cpu = get_cpu();
|
||||
if (last_VFP_context[cpu] == vfp)
|
||||
last_VFP_context[cpu] = NULL;
|
||||
fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
|
||||
put_cpu();
|
||||
}
|
||||
|
||||
static void vfp_thread_release(struct thread_info *thread)
|
||||
{
|
||||
/* release case: Per-thread VFP cleanup. */
|
||||
union vfp_state *vfp = &thread->vfpstate;
|
||||
unsigned int cpu = thread->cpu;
|
||||
|
||||
if (last_VFP_context[cpu] == vfp)
|
||||
last_VFP_context[cpu] = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* When this function is called with the following 'cmd's, the following
|
||||
* is true while this function is being run:
|
||||
* THREAD_NOFTIFY_SWTICH:
|
||||
* - the previously running thread will not be scheduled onto another CPU.
|
||||
* - the next thread to be run (v) will not be running on another CPU.
|
||||
* - thread->cpu is the local CPU number
|
||||
* - not preemptible as we're called in the middle of a thread switch
|
||||
* THREAD_NOTIFY_FLUSH:
|
||||
* - the thread (v) will be running on the local CPU, so
|
||||
* v === current_thread_info()
|
||||
* - thread->cpu is the local CPU number at the time it is accessed,
|
||||
* but may change at any time.
|
||||
* - we could be preempted if tree preempt rcu is enabled, so
|
||||
* it is unsafe to use thread->cpu.
|
||||
* THREAD_NOTIFY_RELEASE:
|
||||
* - the thread (v) will not be running on any CPU; it is a dead thread.
|
||||
* - thread->cpu will be the last CPU the thread ran on, which may not
|
||||
* be the current CPU.
|
||||
* - we could be preempted if tree preempt rcu is enabled.
|
||||
*/
|
||||
static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
|
||||
{
|
||||
struct thread_info *thread = v;
|
||||
union vfp_state *vfp;
|
||||
__u32 cpu = thread->cpu;
|
||||
|
||||
if (likely(cmd == THREAD_NOTIFY_SWITCH)) {
|
||||
u32 fpexc = fmrx(FPEXC);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
unsigned int cpu = thread->cpu;
|
||||
|
||||
/*
|
||||
* On SMP, if VFP is enabled, save the old state in
|
||||
* case the thread migrates to a different CPU. The
|
||||
@ -74,25 +130,10 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
vfp = &thread->vfpstate;
|
||||
if (cmd == THREAD_NOTIFY_FLUSH) {
|
||||
/*
|
||||
* Per-thread VFP initialisation.
|
||||
*/
|
||||
memset(vfp, 0, sizeof(union vfp_state));
|
||||
|
||||
vfp->hard.fpexc = FPEXC_EN;
|
||||
vfp->hard.fpscr = FPSCR_ROUND_NEAREST;
|
||||
|
||||
/*
|
||||
* Disable VFP to ensure we initialise it first.
|
||||
*/
|
||||
fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
|
||||
}
|
||||
|
||||
/* flush and release case: Per-thread VFP cleanup. */
|
||||
if (last_VFP_context[cpu] == vfp)
|
||||
last_VFP_context[cpu] = NULL;
|
||||
if (cmd == THREAD_NOTIFY_FLUSH)
|
||||
vfp_thread_flush(thread);
|
||||
else
|
||||
vfp_thread_release(thread);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
@ -208,7 +208,7 @@ config PCMCIA_PXA2XX
|
||||
depends on ARM && ARCH_PXA && PCMCIA
|
||||
depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \
|
||||
|| MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \
|
||||
|| ARCH_VIPER || ARCH_PXA_ESERIES || MACH_STARGATE2)
|
||||
|| ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2)
|
||||
select PCMCIA_SOC_COMMON
|
||||
help
|
||||
Say Y here to include support for the PXA2xx PCMCIA controller
|
||||
|
@ -67,7 +67,7 @@ pxa2xx-obj-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock_cs.o
|
||||
pxa2xx-obj-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o
|
||||
pxa2xx-obj-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o
|
||||
pxa2xx-obj-$(CONFIG_MACH_ARMCORE) += pxa2xx_cm_x2xx_cs.o
|
||||
pxa2xx-obj-$(CONFIG_ARCH_VIPER) += pxa2xx_viper.o
|
||||
pxa2xx-obj-$(CONFIG_ARCOM_PCMCIA) += pxa2xx_viper.o
|
||||
pxa2xx-obj-$(CONFIG_TRIZEPS_PCMCIA) += pxa2xx_trizeps4.o
|
||||
pxa2xx-obj-$(CONFIG_MACH_PALMTX) += pxa2xx_palmtx.o
|
||||
pxa2xx-obj-$(CONFIG_MACH_PALMTC) += pxa2xx_palmtc.o
|
||||
|
@ -214,7 +214,8 @@ static void pxa2xx_configure_sockets(struct device *dev)
|
||||
MECR |= MECR_CIT;
|
||||
|
||||
/* Set MECR:NOS (Number Of Sockets) */
|
||||
if ((ops->first + ops->nr) > 1 || machine_is_viper())
|
||||
if ((ops->first + ops->nr) > 1 ||
|
||||
machine_is_viper() || machine_is_arcom_zeus())
|
||||
MECR |= MECR_NOS;
|
||||
else
|
||||
MECR &= ~MECR_NOS;
|
||||
@ -252,6 +253,7 @@ int pxa2xx_drv_pcmcia_add_one(struct soc_pcmcia_socket *skt)
|
||||
|
||||
return soc_pcmcia_add_one(skt);
|
||||
}
|
||||
EXPORT_SYMBOL(pxa2xx_drv_pcmcia_add_one);
|
||||
|
||||
void pxa2xx_drv_pcmcia_ops(struct pcmcia_low_level *ops)
|
||||
{
|
||||
@ -261,19 +263,19 @@ void pxa2xx_drv_pcmcia_ops(struct pcmcia_low_level *ops)
|
||||
ops->frequency_change = pxa2xx_pcmcia_frequency_change;
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(pxa2xx_drv_pcmcia_ops);
|
||||
|
||||
int __pxa2xx_drv_pcmcia_probe(struct device *dev)
|
||||
static int pxa2xx_drv_pcmcia_probe(struct platform_device *dev)
|
||||
{
|
||||
int i, ret = 0;
|
||||
struct pcmcia_low_level *ops;
|
||||
struct skt_dev_info *sinfo;
|
||||
struct soc_pcmcia_socket *skt;
|
||||
|
||||
if (!dev || !dev->platform_data)
|
||||
ops = (struct pcmcia_low_level *)dev->dev.platform_data;
|
||||
if (!ops)
|
||||
return -ENODEV;
|
||||
|
||||
ops = (struct pcmcia_low_level *)dev->platform_data;
|
||||
|
||||
pxa2xx_drv_pcmcia_ops(ops);
|
||||
|
||||
sinfo = kzalloc(SKT_DEV_INFO_SIZE(ops->nr), GFP_KERNEL);
|
||||
@ -308,13 +310,6 @@ int __pxa2xx_drv_pcmcia_probe(struct device *dev)
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(__pxa2xx_drv_pcmcia_probe);
|
||||
|
||||
|
||||
static int pxa2xx_drv_pcmcia_probe(struct platform_device *dev)
|
||||
{
|
||||
return __pxa2xx_drv_pcmcia_probe(&dev->dev);
|
||||
}
|
||||
|
||||
static int pxa2xx_drv_pcmcia_remove(struct platform_device *dev)
|
||||
{
|
||||
|
@ -1,6 +1,3 @@
|
||||
/* temporary measure */
|
||||
extern int __pxa2xx_drv_pcmcia_probe(struct device *);
|
||||
|
||||
int pxa2xx_drv_pcmcia_add_one(struct soc_pcmcia_socket *skt);
|
||||
void pxa2xx_drv_pcmcia_ops(struct pcmcia_low_level *ops);
|
||||
|
||||
|
@ -67,7 +67,7 @@ static int palmtc_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
|
||||
if (ret)
|
||||
goto err7;
|
||||
|
||||
skt->irq = IRQ_GPIO(GPIO_NR_PALMTC_PCMCIA_READY);
|
||||
skt->socket.pci_irq = IRQ_GPIO(GPIO_NR_PALMTC_PCMCIA_READY);
|
||||
return 0;
|
||||
|
||||
err7:
|
||||
|
@ -40,7 +40,7 @@ static struct pcmcia_irqs irqs[] = {
|
||||
|
||||
static int sg2_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
|
||||
{
|
||||
skt->irq = IRQ_GPIO(SG2_S0_GPIO_READY);
|
||||
skt->socket.pci_irq = IRQ_GPIO(SG2_S0_GPIO_READY);
|
||||
return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
/*
|
||||
* VIPER PCMCIA support
|
||||
* Viper/Zeus PCMCIA support
|
||||
* Copyright 2004 Arcom Control Systems
|
||||
*
|
||||
* Maintained by Marc Zyngier <maz@misterjones.org>
|
||||
* <marc.zyngier@altran.com>
|
||||
*
|
||||
* Based on:
|
||||
* iPAQ h2200 PCMCIA support
|
||||
@ -26,37 +25,47 @@
|
||||
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <mach/viper.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <mach/arcom-pcmcia.h>
|
||||
|
||||
#include "soc_common.h"
|
||||
#include "pxa2xx_base.h"
|
||||
|
||||
static struct platform_device *arcom_pcmcia_dev;
|
||||
|
||||
static struct pcmcia_irqs irqs[] = {
|
||||
{ 0, gpio_to_irq(VIPER_CF_CD_GPIO), "PCMCIA_CD" }
|
||||
{
|
||||
.sock = 0,
|
||||
.str = "PCMCIA_CD",
|
||||
},
|
||||
};
|
||||
|
||||
static inline struct arcom_pcmcia_pdata *viper_get_pdata(void)
|
||||
{
|
||||
return arcom_pcmcia_dev->dev.platform_data;
|
||||
}
|
||||
|
||||
static int viper_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
|
||||
{
|
||||
struct arcom_pcmcia_pdata *pdata = viper_get_pdata();
|
||||
unsigned long flags;
|
||||
|
||||
skt->socket.pci_irq = gpio_to_irq(VIPER_CF_RDY_GPIO);
|
||||
skt->socket.pci_irq = gpio_to_irq(pdata->rdy_gpio);
|
||||
irqs[0].irq = gpio_to_irq(pdata->cd_gpio);
|
||||
|
||||
if (gpio_request(VIPER_CF_CD_GPIO, "CF detect"))
|
||||
if (gpio_request(pdata->cd_gpio, "CF detect"))
|
||||
goto err_request_cd;
|
||||
|
||||
if (gpio_request(VIPER_CF_RDY_GPIO, "CF ready"))
|
||||
if (gpio_request(pdata->rdy_gpio, "CF ready"))
|
||||
goto err_request_rdy;
|
||||
|
||||
if (gpio_request(VIPER_CF_POWER_GPIO, "CF power"))
|
||||
if (gpio_request(pdata->pwr_gpio, "CF power"))
|
||||
goto err_request_pwr;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
/* GPIO 82 is the CF power enable line. initially off */
|
||||
if (gpio_direction_output(VIPER_CF_POWER_GPIO, 0) ||
|
||||
gpio_direction_input(VIPER_CF_CD_GPIO) ||
|
||||
gpio_direction_input(VIPER_CF_RDY_GPIO)) {
|
||||
if (gpio_direction_output(pdata->pwr_gpio, 0) ||
|
||||
gpio_direction_input(pdata->cd_gpio) ||
|
||||
gpio_direction_input(pdata->rdy_gpio)) {
|
||||
local_irq_restore(flags);
|
||||
goto err_dir;
|
||||
}
|
||||
@ -66,13 +75,13 @@ static int viper_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
|
||||
return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
|
||||
|
||||
err_dir:
|
||||
gpio_free(VIPER_CF_POWER_GPIO);
|
||||
gpio_free(pdata->pwr_gpio);
|
||||
err_request_pwr:
|
||||
gpio_free(VIPER_CF_RDY_GPIO);
|
||||
gpio_free(pdata->rdy_gpio);
|
||||
err_request_rdy:
|
||||
gpio_free(VIPER_CF_CD_GPIO);
|
||||
gpio_free(pdata->cd_gpio);
|
||||
err_request_cd:
|
||||
printk(KERN_ERR "viper: Failed to setup PCMCIA GPIOs\n");
|
||||
dev_err(&arcom_pcmcia_dev->dev, "Failed to setup PCMCIA GPIOs\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -81,17 +90,21 @@ err_request_cd:
|
||||
*/
|
||||
static void viper_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
|
||||
{
|
||||
struct arcom_pcmcia_pdata *pdata = viper_get_pdata();
|
||||
|
||||
soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
|
||||
gpio_free(VIPER_CF_POWER_GPIO);
|
||||
gpio_free(VIPER_CF_RDY_GPIO);
|
||||
gpio_free(VIPER_CF_CD_GPIO);
|
||||
gpio_free(pdata->pwr_gpio);
|
||||
gpio_free(pdata->rdy_gpio);
|
||||
gpio_free(pdata->cd_gpio);
|
||||
}
|
||||
|
||||
static void viper_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
|
||||
struct pcmcia_state *state)
|
||||
{
|
||||
state->detect = gpio_get_value(VIPER_CF_CD_GPIO) ? 0 : 1;
|
||||
state->ready = gpio_get_value(VIPER_CF_RDY_GPIO) ? 1 : 0;
|
||||
struct arcom_pcmcia_pdata *pdata = viper_get_pdata();
|
||||
|
||||
state->detect = !gpio_get_value(pdata->cd_gpio);
|
||||
state->ready = !!gpio_get_value(pdata->rdy_gpio);
|
||||
state->bvd1 = 1;
|
||||
state->bvd2 = 1;
|
||||
state->wrprot = 0;
|
||||
@ -102,20 +115,21 @@ static void viper_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
|
||||
static int viper_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
|
||||
const socket_state_t *state)
|
||||
{
|
||||
struct arcom_pcmcia_pdata *pdata = viper_get_pdata();
|
||||
|
||||
/* Silently ignore Vpp, output enable, speaker enable. */
|
||||
viper_cf_rst(state->flags & SS_RESET);
|
||||
pdata->reset(state->flags & SS_RESET);
|
||||
|
||||
/* Apply socket voltage */
|
||||
switch (state->Vcc) {
|
||||
case 0:
|
||||
gpio_set_value(VIPER_CF_POWER_GPIO, 0);
|
||||
gpio_set_value(pdata->pwr_gpio, 0);
|
||||
break;
|
||||
case 33:
|
||||
gpio_set_value(VIPER_CF_POWER_GPIO, 1);
|
||||
gpio_set_value(pdata->pwr_gpio, 1);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "%s: Unsupported Vcc:%d\n",
|
||||
__func__, state->Vcc);
|
||||
dev_err(&arcom_pcmcia_dev->dev, "Unsupported Vcc:%d\n", state->Vcc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -130,7 +144,7 @@ static void viper_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
|
||||
{
|
||||
}
|
||||
|
||||
static struct pcmcia_low_level viper_pcmcia_ops __initdata = {
|
||||
static struct pcmcia_low_level viper_pcmcia_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.hw_init = viper_pcmcia_hw_init,
|
||||
.hw_shutdown = viper_pcmcia_hw_shutdown,
|
||||
@ -143,17 +157,25 @@ static struct pcmcia_low_level viper_pcmcia_ops __initdata = {
|
||||
|
||||
static struct platform_device *viper_pcmcia_device;
|
||||
|
||||
static int __init viper_pcmcia_init(void)
|
||||
static int viper_pcmcia_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!machine_is_viper())
|
||||
return -ENODEV;
|
||||
/* I can't imagine more than one device, but you never know... */
|
||||
if (arcom_pcmcia_dev)
|
||||
return -EEXIST;
|
||||
|
||||
if (!pdev->dev.platform_data)
|
||||
return -EINVAL;
|
||||
|
||||
viper_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
|
||||
if (!viper_pcmcia_device)
|
||||
return -ENOMEM;
|
||||
|
||||
arcom_pcmcia_dev = pdev;
|
||||
|
||||
viper_pcmcia_device->dev.parent = &pdev->dev;
|
||||
|
||||
ret = platform_device_add_data(viper_pcmcia_device,
|
||||
&viper_pcmcia_ops,
|
||||
sizeof(viper_pcmcia_ops));
|
||||
@ -161,18 +183,49 @@ static int __init viper_pcmcia_init(void)
|
||||
if (!ret)
|
||||
ret = platform_device_add(viper_pcmcia_device);
|
||||
|
||||
if (ret)
|
||||
if (ret) {
|
||||
platform_device_put(viper_pcmcia_device);
|
||||
arcom_pcmcia_dev = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit viper_pcmcia_exit(void)
|
||||
static int viper_pcmcia_remove(struct platform_device *pdev)
|
||||
{
|
||||
platform_device_unregister(viper_pcmcia_device);
|
||||
arcom_pcmcia_dev = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_device_id viper_pcmcia_id_table[] = {
|
||||
{ .name = "viper-pcmcia", },
|
||||
{ .name = "zeus-pcmcia", },
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_driver viper_pcmcia_driver = {
|
||||
.probe = viper_pcmcia_probe,
|
||||
.remove = viper_pcmcia_remove,
|
||||
.driver = {
|
||||
.name = "arcom-pcmcia",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.id_table = viper_pcmcia_id_table,
|
||||
};
|
||||
|
||||
static int __init viper_pcmcia_init(void)
|
||||
{
|
||||
return platform_driver_register(&viper_pcmcia_driver);
|
||||
}
|
||||
|
||||
static void __exit viper_pcmcia_exit(void)
|
||||
{
|
||||
return platform_driver_unregister(&viper_pcmcia_driver);
|
||||
}
|
||||
|
||||
module_init(viper_pcmcia_init);
|
||||
module_exit(viper_pcmcia_exit);
|
||||
|
||||
MODULE_DEVICE_TABLE(platform, viper_pcmcia_id_table);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
Loading…
Reference in New Issue
Block a user