Commit af853e63 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 3f86ce72 fc773668
...@@ -603,6 +603,7 @@ config ARCH_SA1100 ...@@ -603,6 +603,7 @@ config ARCH_SA1100
select ARCH_SPARSEMEM_ENABLE select ARCH_SPARSEMEM_ENABLE
select ARCH_MTD_XIP select ARCH_MTD_XIP
select ARCH_HAS_CPUFREQ select ARCH_HAS_CPUFREQ
select CPU_FREQ
select GENERIC_GPIO select GENERIC_GPIO
select GENERIC_TIME select GENERIC_TIME
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
...@@ -1359,13 +1360,9 @@ source "drivers/cpufreq/Kconfig" ...@@ -1359,13 +1360,9 @@ source "drivers/cpufreq/Kconfig"
config CPU_FREQ_SA1100 config CPU_FREQ_SA1100
bool bool
depends on CPU_FREQ && (SA1100_H3100 || SA1100_H3600 || SA1100_LART || SA1100_PLEB || SA1100_BADGE4 || SA1100_HACKKIT)
default y
config CPU_FREQ_SA1110 config CPU_FREQ_SA1110
bool bool
depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3)
default y
config CPU_FREQ_INTEGRATOR config CPU_FREQ_INTEGRATOR
tristate "CPUfreq driver for ARM Integrator CPUs" tristate "CPUfreq driver for ARM Integrator CPUs"
......
...@@ -71,6 +71,14 @@ config DEBUG_LL ...@@ -71,6 +71,14 @@ config DEBUG_LL
in the kernel. This is helpful if you are debugging code that in the kernel. This is helpful if you are debugging code that
executes before the console is initialized. 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 config DEBUG_ICEDCC
bool "Kernel low-level debugging via EmbeddedICE DCC channel" bool "Kernel low-level debugging via EmbeddedICE DCC channel"
depends on DEBUG_LL depends on DEBUG_LL
......
This diff is collapsed.
...@@ -54,5 +54,6 @@ endif ...@@ -54,5 +54,6 @@ endif
head-y := head$(MMUEXT).o head-y := head$(MMUEXT).o
obj-$(CONFIG_DEBUG_LL) += debug.o obj-$(CONFIG_DEBUG_LL) += debug.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
extra-y := $(head-y) init_task.o vmlinux.lds extra-y := $(head-y) init_task.o vmlinux.lds
/*
* 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) ...@@ -160,6 +160,7 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)
/* Make sure our local interrupt controller has this enabled */ /* Make sure our local interrupt controller has this enabled */
local_irq_save(flags); local_irq_save(flags);
irq_to_desc(clk->irq)->status |= IRQ_NOPROBE;
get_irq_chip(clk->irq)->unmask(clk->irq); get_irq_chip(clk->irq)->unmask(clk->irq);
local_irq_restore(flags); local_irq_restore(flags);
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#define __virt_to_bus(x) ((x) - PAGE_OFFSET) #define __virt_to_bus(x) ((x) - PAGE_OFFSET)
#define __bus_to_virt(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 #endif
......
...@@ -201,6 +201,11 @@ void __init footbridge_map_io(void) ...@@ -201,6 +201,11 @@ void __init footbridge_map_io(void)
#ifdef CONFIG_FOOTBRIDGE_ADDIN #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 * These two functions convert virtual addresses to PCI addresses and PCI
* addresses to virtual addresses. Note that it is only legal to use these * 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) ...@@ -210,14 +215,13 @@ unsigned long __virt_to_bus(unsigned long res)
{ {
WARN_ON(res < PAGE_OFFSET || res >= (unsigned long)high_memory); 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); EXPORT_SYMBOL(__virt_to_bus);
unsigned long __bus_to_virt(unsigned long res) unsigned long __bus_to_virt(unsigned long res)
{ {
res -= (*CSR_PCISDRAMBASE & 0xfffffff0); res = res - (fb_bus_sdram_offset() - PAGE_OFFSET);
res += PAGE_OFFSET;
WARN_ON(res < PAGE_OFFSET || res >= (unsigned long)high_memory); WARN_ON(res < PAGE_OFFSET || res >= (unsigned long)high_memory);
...@@ -225,4 +229,16 @@ unsigned long __bus_to_virt(unsigned long res) ...@@ -225,4 +229,16 @@ unsigned long __bus_to_virt(unsigned long res)
} }
EXPORT_SYMBOL(__bus_to_virt); 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 #endif
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
extern unsigned long __virt_to_bus(unsigned long); extern unsigned long __virt_to_bus(unsigned long);
extern unsigned long __bus_to_virt(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 #endif
#define __virt_to_bus __virt_to_bus #define __virt_to_bus __virt_to_bus
#define __bus_to_virt __bus_to_virt #define __bus_to_virt __bus_to_virt
...@@ -36,14 +38,15 @@ extern unsigned long __bus_to_virt(unsigned long); ...@@ -36,14 +38,15 @@ extern unsigned long __bus_to_virt(unsigned long);
#elif defined(CONFIG_FOOTBRIDGE_HOST) #elif defined(CONFIG_FOOTBRIDGE_HOST)
/* /*
* The footbridge is programmed to expose the system RAM at the corresponding * The footbridge is programmed to expose the system RAM at 0xe0000000.
* address. So, if PAGE_OFFSET is 0xc0000000, RAM appears at 0xe0000000. * The requirement is that the RAM isn't placed at bus address 0, which
* 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
* would clash with VGA cards. * would clash with VGA cards.
*/ */
#define __virt_to_bus(x) ((x) - 0xe0000000) #define BUS_OFFSET 0xe0000000
#define __bus_to_virt(x) ((x) + 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 #else
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#define BUS_OFFSET UL(0x80000000) #define BUS_OFFSET UL(0x80000000)
#define __virt_to_bus(x) ((x) - PAGE_OFFSET + BUS_OFFSET) #define __virt_to_bus(x) ((x) - PAGE_OFFSET + BUS_OFFSET)
#define __bus_to_virt(x) ((x) - BUS_OFFSET + PAGE_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 #endif
...@@ -17,11 +17,15 @@ ...@@ -17,11 +17,15 @@
#include <mach/ixp2000-regs.h> #include <mach/ixp2000-regs.h>
#define __virt_to_bus(v) \ #define IXP2000_PCI_SDRAM_OFFSET (*IXP2000_PCI_SDRAM_BAR & 0xfffffff0)
(((__virt_to_phys(v) - 0x0) + (*IXP2000_PCI_SDRAM_BAR & 0xfffffff0)))
#define __bus_to_virt(b) \ #define __phys_to_bus(x) ((x) + (IXP2000_PCI_SDRAM_OFFSET - PHYS_OFFSET))
__phys_to_virt((((b - (*IXP2000_PCI_SDRAM_BAR & 0xfffffff0)) + 0x0))) #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 #endif
...@@ -19,16 +19,15 @@ ...@@ -19,16 +19,15 @@
*/ */
#define PHYS_OFFSET (0x00000000) #define PHYS_OFFSET (0x00000000)
#define __virt_to_bus(v) \ #define IXP23XX_PCI_SDRAM_OFFSET (*((volatile int *)IXP23XX_PCI_SDRAM_BAR) & 0xfffffff0))
({ unsigned int ret; \
ret = ((__virt_to_phys(v) - 0x00000000) + \ #define __phys_to_bus(x) ((x) + (IXP23XX_PCI_SDRAM_OFFSET - PHYS_OFFSET))
(*((volatile int *)IXP23XX_PCI_SDRAM_BAR) & 0xfffffff0)); \ #define __bus_to_phys(x) ((x) - (IXP23XX_PCI_SDRAM_OFFSET - PHYS_OFFSET))
ret; })
#define __virt_to_bus(v) __phys_to_bus(__virt_to_phys(v))
#define __bus_to_virt(b) \ #define __bus_to_virt(b) __phys_to_virt(__bus_to_phys(b))
({ unsigned int data; \ #define __pfn_to_bus(p) __phys_to_bus(__pfn_to_phys(p))
data = *((volatile int *)IXP23XX_PCI_SDRAM_BAR); \ #define __bus_to_pfn(b) __phys_to_pfn(__bus_to_phys(b))
__phys_to_virt((((b - (data & 0xfffffff0)) + 0x00000000))); })
#define arch_is_coherent() 1 #define arch_is_coherent() 1
......
...@@ -7,8 +7,6 @@ ...@@ -7,8 +7,6 @@
* version 2 as published by the Free Software Foundation. * version 2 as published by the Free Software Foundation.
* *
*/ */
#include <linux/cpufreq.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/clocks.h> #include <mach/clocks.h>
#include <linux/err.h> #include <linux/err.h>
...@@ -31,12 +29,6 @@ struct clk { ...@@ -31,12 +29,6 @@ struct clk {
#define HCLKDIV(c) (((c) >> 0) & 0x02) #define HCLKDIV(c) (((c) >> 0) & 0x02)
#define PCLKDIV(c) (((c) >> 16) & 0x03) #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 fclkfreq_get (void)
{ {
unsigned int clkset = CSC_CLKSET; unsigned int clkset = CSC_CLKSET;
......
...@@ -63,6 +63,15 @@ config ARCH_VIPER ...@@ -63,6 +63,15 @@ config ARCH_VIPER
select HAVE_PWM select HAVE_PWM
select PXA_HAVE_BOARD_IRQS select PXA_HAVE_BOARD_IRQS
select PXA_HAVE_ISA_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 config MACH_BALLOON3
bool "Balloon 3 board" bool "Balloon 3 board"
...@@ -179,6 +188,11 @@ config MACH_TRIZEPS_ANY ...@@ -179,6 +188,11 @@ config MACH_TRIZEPS_ANY
endchoice endchoice
config ARCOM_PCMCIA
bool
help
Generic option for Arcom Viper/Zeus PCMCIA
config TRIZEPS_PCMCIA config TRIZEPS_PCMCIA
bool bool
help help
......
...@@ -38,6 +38,7 @@ obj-$(CONFIG_MACH_SAAR) += saar.o ...@@ -38,6 +38,7 @@ obj-$(CONFIG_MACH_SAAR) += saar.o
# 3rd Party Dev Platforms # 3rd Party Dev Platforms
obj-$(CONFIG_ARCH_PXA_IDP) += idp.o obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
obj-$(CONFIG_ARCH_VIPER) += viper.o obj-$(CONFIG_ARCH_VIPER) += viper.o
obj-$(CONFIG_MACH_ARCOM_ZEUS) += zeus.o
obj-$(CONFIG_MACH_BALLOON3) += balloon3.o obj-$(CONFIG_MACH_BALLOON3) += balloon3.o
obj-$(CONFIG_MACH_CSB726) += csb726.o obj-$(CONFIG_MACH_CSB726) += csb726.o
obj-$(CONFIG_CSB726_CSB701) += csb701.o obj-$(CONFIG_CSB726_CSB701) += csb701.o
......
...@@ -497,16 +497,15 @@ static int em_x270_usb_hub_init(void) ...@@ -497,16 +497,15 @@ static int em_x270_usb_hub_init(void)
goto err_free_vbus_gpio; goto err_free_vbus_gpio;
/* USB Hub power-on and reset */ /* 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); 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, 0);
gpio_set_value(usb_hub_reset, 1);
regulator_disable(em_x270_usb_ldo); regulator_disable(em_x270_usb_ldo);
regulator_enable(em_x270_usb_ldo); regulator_enable(em_x270_usb_ldo);
gpio_set_value(usb_hub_reset, 1); gpio_set_value(usb_hub_reset, 0);
gpio_set_value(GPIO9_USB_VBUS_EN, 1);
/* enable VBUS */
gpio_direction_output(GPIO9_USB_VBUS_EN, 1);
return 0; return 0;
......
#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 @@ ...@@ -85,8 +85,6 @@
/* Interrupt and Configuration Register (VIPER_ICR) */ /* Interrupt and Configuration Register (VIPER_ICR) */
/* This is a write only register. Only CF_RST is used under Linux */ /* 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_RETRIG (1 << 0)
#define VIPER_ICR_AUTO_CLR (1 << 1) #define VIPER_ICR_AUTO_CLR (1 << 1)
#define VIPER_ICR_R_DIS (1 << 2) #define VIPER_ICR_R_DIS (1 << 2)
......
/*
* 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 @@ ...@@ -47,6 +47,7 @@
#include <mach/pxafb.h> #include <mach/pxafb.h>
#include <plat/i2c.h> #include <plat/i2c.h>
#include <mach/regs-uart.h> #include <mach/regs-uart.h>
#include <mach/arcom-pcmcia.h>
#include <mach/viper.h> #include <mach/viper.h>
#include <asm/setup.h> #include <asm/setup.h>
...@@ -76,14 +77,28 @@ static void viper_icr_clear_bit(unsigned int bit) ...@@ -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 */ /* 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) if (state)
viper_icr_set_bit(VIPER_ICR_CF_RST); viper_icr_set_bit(VIPER_ICR_CF_RST);
else else
viper_icr_clear_bit(VIPER_ICR_CF_RST); 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 * The CPLD version register was not present on VIPER boards prior to
...@@ -685,6 +700,7 @@ static struct platform_device *viper_devs[] __initdata = { ...@@ -685,6 +700,7 @@ static struct platform_device *viper_devs[] __initdata = {
&viper_mtd_devices[0], &viper_mtd_devices[0],
&viper_mtd_devices[1], &viper_mtd_devices[1],
&viper_backlight_device, &viper_backlight_device,
&viper_pcmcia_device,
}; };
static mfp_cfg_t viper_pin_config[] __initdata = { static mfp_cfg_t viper_pin_config[] __initdata = {
......
This diff is collapsed.
...@@ -70,7 +70,7 @@ config MACH_REALVIEW_PBX ...@@ -70,7 +70,7 @@ config MACH_REALVIEW_PBX
bool "Support RealView/PBX platform" bool "Support RealView/PBX platform"
select ARM_GIC select ARM_GIC
select HAVE_PATA_PLATFORM 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 select ZONE_DMA if SPARSEMEM
help help
Include support for the ARM(R) RealView PBX platform. Include support for the ARM(R) RealView PBX platform.
......
...@@ -15,5 +15,7 @@ ...@@ -15,5 +15,7 @@
#define __virt_to_bus(x) __virt_to_phys(x) #define __virt_to_bus(x) __virt_to_phys(x)
#define __bus_to_virt(x) __phys_to_virt(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 #endif
...@@ -4,6 +4,7 @@ menu "SA11x0 Implementations" ...@@ -4,6 +4,7 @@ menu "SA11x0 Implementations"
config SA1100_ASSABET config SA1100_ASSABET
bool "Assabet" bool "Assabet"
select CPU_FREQ_SA1110
help help
Say Y here if you are using the Intel(R) StrongARM(R) SA-1110 Say Y here if you are using the Intel(R) StrongARM(R) SA-1110
Microprocessor Development Board (also known as the Assabet). Microprocessor Development Board (also known as the Assabet).
...@@ -19,6 +20,7 @@ config ASSABET_NEPONSET ...@@ -19,6 +20,7 @@ config ASSABET_NEPONSET
config SA1100_CERF config SA1100_CERF
bool "CerfBoard" bool "CerfBoard"
select CPU_FREQ_SA1110
help help
The Intrinsyc CerfBoard is based on the StrongARM 1110 (Discontinued). The Intrinsyc CerfBoard is based on the StrongARM 1110 (Discontinued).
More information is available at: More information is available at:
...@@ -45,6 +47,7 @@ endchoice ...@@ -45,6 +47,7 @@ endchoice
config SA1100_COLLIE config SA1100_COLLIE
bool "Sharp Zaurus SL5500" bool "Sharp Zaurus SL5500"
# FIXME: select CPU_FREQ_SA11x0
select SHARP_LOCOMO select SHARP_LOCOMO
select SHARP_SCOOP select SHARP_SCOOP
select SHARP_PARAM select SHARP_PARAM
...@@ -54,6 +57,7 @@ config SA1100_COLLIE ...@@ -54,6 +57,7 @@ config SA1100_COLLIE
config SA1100_H3100 config SA1100_H3100
bool "Compaq iPAQ H3100" bool "Compaq iPAQ H3100"
select HTC_EGPIO select HTC_EGPIO
select CPU_FREQ_SA1100
help help
Say Y here if you intend to run this kernel on the Compaq iPAQ Say Y here if you intend to run this kernel on the Compaq iPAQ
H3100 handheld computer. Information about this machine and the H3100 handheld computer. Information about this machine and the
...@@ -64,6 +68,7 @@ config SA1100_H3100 ...@@ -64,6 +68,7 @@ config SA1100_H3100
config SA1100_H3600 config SA1100_H3600
bool "Compaq iPAQ H3600/H3700" bool "Compaq iPAQ H3600/H3700"
select HTC_EGPIO select HTC_EGPIO
select CPU_FREQ_SA1100
help help
Say Y here if you intend to run this kernel on the Compaq iPAQ Say Y here if you intend to run this kernel on the Compaq iPAQ
H3600 handheld computer. Information about this machine and the H3600 handheld computer. Information about this machine and the
...@@ -74,6 +79,7 @@ config SA1100_H3600 ...@@ -74,6 +79,7 @@ config SA1100_H3600
config SA1100_BADGE4 config SA1100_BADGE4
bool "HP Labs BadgePAD 4" bool "HP Labs BadgePAD 4"
select SA1111 select SA1111
select CPU_FREQ_SA1100
help help
Say Y here if you want to build a kernel for the HP Laboratories Say Y here if you want to build a kernel for the HP Laboratories
BadgePAD 4. BadgePAD 4.
...@@ -81,6 +87,7 @@ config SA1100_BADGE4 ...@@ -81,6 +87,7 @@ config SA1100_BADGE4
config SA1100_JORNADA720 config SA1100_JORNADA720
bool "HP Jornada 720" bool "HP Jornada 720"
select SA1111 select SA1111
# FIXME: select CPU_FREQ_SA11x0
help help
Say Y here if you want to build a kernel for the HP Jornada 720 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> handheld computer. See <http://www.hp.com/jornada/products/720>
...@@ -98,12 +105,14 @@ config SA1100_JORNADA720_SSP ...@@ -98,12 +105,14 @@ config SA1100_JORNADA720_SSP
config SA1100_HACKKIT config SA1100_HACKKIT
bool "HackKit Core CPU Board" bool "HackKit Core CPU Board"
select CPU_FREQ_SA1100
help help
Say Y here to support the HackKit Core CPU Board Say Y here to support the HackKit Core CPU Board
<http://hackkit.eletztrick.de>; <http://hackkit.eletztrick.de>;
config SA1100_LART config SA1100_LART
bool "LART" bool "LART"
select CPU_FREQ_SA1100
help help
Say Y here if you are using the Linux Advanced Radio Terminal Say Y here if you are using the Linux Advanced Radio Terminal
(also known as the LART). See <http://www.lartmaker.nl/> for (also known as the LART). See <http://www.lartmaker.nl/> for
...@@ -111,6 +120,7 @@ config SA1100_LART ...@@ -111,6 +120,7 @@ config SA1100_LART
config SA1100_PLEB config SA1100_PLEB
bool "PLEB" bool "PLEB"
select CPU_FREQ_SA1100
help help
Say Y here if you are using version 1 of the Portable Linux Say Y here if you are using version 1 of the Portable Linux
Embedded Board (also known as PLEB). Embedded Board (also known as PLEB).
...@@ -119,6 +129,7 @@ config SA1100_PLEB ...@@ -119,6 +129,7 @@ config SA1100_PLEB
config SA1100_SHANNON config SA1100_SHANNON
bool "Shannon" bool "Shannon"
select CPU_FREQ_SA1100
help help
The Shannon (also known as a Tuxscreen, and also as a IS2630) was a 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 limited edition webphone produced by Philips. The Shannon is a SA1100
...@@ -127,6 +138,7 @@ config SA1100_SHANNON ...@@ -127,6 +138,7 @@ config SA1100_SHANNON
config SA1100_SIMPAD config SA1100_SIMPAD
bool "Simpad" bool "Simpad"
select CPU_FREQ_SA1110
help help
The SIEMENS webpad SIMpad is based on the StrongARM 1110. There The SIEMENS webpad SIMpad is based on the StrongARM 1110. There
are two different versions CL4 and SL4. CL4 has 32MB RAM and 16MB are two different versions CL4 and SL4. CL4 has 32MB RAM and 16MB
...@@ -145,3 +157,4 @@ config SA1100_SSP ...@@ -145,3 +157,4 @@ config SA1100_SSP
endmenu endmenu
endif endif
...@@ -58,7 +58,6 @@ static const unsigned short cclk_frequency_100khz[NR_FREQS] = { ...@@ -58,7 +58,6 @@ static const unsigned short cclk_frequency_100khz[NR_FREQS] = {
2802 /* 280.2 MHz */ 2802 /* 280.2 MHz */
}; };
#if defined(CONFIG_CPU_FREQ_SA1100) || defined(CONFIG_CPU_FREQ_SA1110)
/* rounds up(!) */ /* rounds up(!) */
unsigned int sa11x0_freq_to_ppcr(unsigned int khz) unsigned int sa11x0_freq_to_ppcr(unsigned int khz)
{ {
...@@ -110,17 +109,6 @@ unsigned int sa11x0_getspeed(unsigned int cpu) ...@@ -110,17 +109,6 @@ unsigned int sa11x0_getspeed(unsigned int cpu)
return cclk_frequency_100khz[PPCR & 0xf] * 100; 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 * This is the SA11x0 sched_clock implementation. This has
* a resolution of 271ns, and a maximum value of 32025597s (370 days). * a resolution of 271ns, and a maximum value of 32025597s (370 days).
......
...@@ -38,16 +38,72 @@ union vfp_state *last_VFP_context[NR_CPUS]; ...@@ -38,16 +38,72 @@ union vfp_state *last_VFP_context[NR_CPUS];
*/ */
unsigned int VFP_arch; 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) static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
{ {
struct thread_info *thread = v; struct thread_info *thread = v;
union vfp_state *vfp;
__u32 cpu = thread->cpu;
if (likely(cmd == THREAD_NOTIFY_SWITCH)) { if (likely(cmd == THREAD_NOTIFY_SWITCH)) {
u32 fpexc = fmrx(FPEXC); u32 fpexc = fmrx(FPEXC);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
unsigned int cpu = thread->cpu;
/* /*
* On SMP, if VFP is enabled, save the old state in * On SMP, if VFP is enabled, save the old state in
* case the thread migrates to a different CPU. The * 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) ...@@ -74,25 +130,10 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
return NOTIFY_DONE; return NOTIFY_DONE;
} }
vfp = &thread->vfpstate; if (cmd == THREAD_NOTIFY_FLUSH)
if (cmd == THREAD_NOTIFY_FLUSH) { vfp_thread_flush(thread);
/* else
* Per-thread VFP initialisation. vfp_thread_release(thread);
*/
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;
return NOTIFY_DONE; return NOTIFY_DONE;
} }
......
...@@ -208,7 +208,7 @@ config PCMCIA_PXA2XX ...@@ -208,7 +208,7 @@ config PCMCIA_PXA2XX
depends on ARM && ARCH_PXA && PCMCIA depends on ARM && ARCH_PXA && PCMCIA
depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \ depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \
|| MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \ || 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 select PCMCIA_SOC_COMMON
help help
Say Y here to include support for the PXA2xx PCMCIA controller Say Y here to include support for the PXA2xx PCMCIA controller
......
...@@ -67,7 +67,7 @@ pxa2xx-obj-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock_cs.o ...@@ -67,7 +67,7 @@ pxa2xx-obj-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock_cs.o
pxa2xx-obj-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o pxa2xx-obj-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o
pxa2xx-obj-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o pxa2xx-obj-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o
pxa2xx-obj-$(CONFIG_MACH_ARMCORE) += pxa2xx_cm_x2xx_cs.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_TRIZEPS_PCMCIA) += pxa2xx_trizeps4.o
pxa2xx-obj-$(CONFIG_MACH_PALMTX) += pxa2xx_palmtx.o pxa2xx-obj-$(CONFIG_MACH_PALMTX) += pxa2xx_palmtx.o
pxa2xx-obj-$(CONFIG_MACH_PALMTC) += pxa2xx_palmtc.o pxa2xx-obj-$(CONFIG_MACH_PALMTC) += pxa2xx_palmtc.o
......
...@@ -214,7 +214,8 @@ static void pxa2xx_configure_sockets(struct device *dev) ...@@ -214,7 +214,8 @@ static void pxa2xx_configure_sockets(struct device *dev)
MECR |= MECR_CIT; MECR |= MECR_CIT;
/* Set MECR:NOS (Number Of Sockets) */ /* 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; MECR |= MECR_NOS;
else else
MECR &= ~MECR_NOS; MECR &= ~MECR_NOS;
...@@ -252,6 +253,7 @@ int pxa2xx_drv_pcmcia_add_one(struct soc_pcmcia_socket *skt) ...@@ -252,6 +253,7 @@ int pxa2xx_drv_pcmcia_add_one(struct soc_pcmcia_socket *skt)
return soc_pcmcia_add_one(skt); return soc_pcmcia_add_one(skt);
} }
EXPORT_SYMBOL(pxa2xx_drv_pcmcia_add_one);
void pxa2xx_drv_pcmcia_ops(struct pcmcia_low_level *ops) void pxa2xx_drv_pcmcia_ops(struct pcmcia_low_level *ops)
{ {
...@@ -261,19 +263,19 @@ 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; ops->frequency_change = pxa2xx_pcmcia_frequency_change;
#endif #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; int i, ret = 0;
struct pcmcia_low_level *ops; struct pcmcia_low_level *ops;
struct skt_dev_info *sinfo; struct skt_dev_info *sinfo;
struct soc_pcmcia_socket *skt; struct soc_pcmcia_socket *skt;
if (!dev || !dev->platform_data) ops = (struct pcmcia_low_level *)dev->dev.platform_data;
if (!ops)
return -ENODEV; return -ENODEV;
ops = (struct pcmcia_low_level *)dev->platform_data;
pxa2xx_drv_pcmcia_ops(ops); pxa2xx_drv_pcmcia_ops(ops);
sinfo = kzalloc(SKT_DEV_INFO_SIZE(ops->nr), GFP_KERNEL); sinfo = kzalloc(SKT_DEV_INFO_SIZE(ops->nr), GFP_KERNEL);
...@@ -308,13 +310,6 @@ int __pxa2xx_drv_pcmcia_probe(struct device *dev) ...@@ -308,13 +310,6 @@ int __pxa2xx_drv_pcmcia_probe(struct device *dev)
return ret; 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) static int pxa2xx_drv_pcmcia_remove(struct platform_device *dev)
{ {
......
/* temporary measure */
extern int __pxa2xx_drv_pcmcia_probe(struct device *);
int pxa2xx_drv_pcmcia_add_one(struct soc_pcmcia_socket *skt); int pxa2xx_drv_pcmcia_add_one(struct soc_pcmcia_socket *skt);
void pxa2xx_drv_pcmcia_ops(struct pcmcia_low_level *ops); 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) ...@@ -67,7 +67,7 @@ static int palmtc_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
if (ret) if (ret)
goto err7; goto err7;
skt->irq = IRQ_GPIO(GPIO_NR_PALMTC_PCMCIA_READY); skt->socket.pci_irq = IRQ_GPIO(GPIO_NR_PALMTC_PCMCIA_READY);
return 0; return 0;
err7: err7:
......
...@@ -40,7 +40,7 @@ static struct pcmcia_irqs irqs[] = { ...@@ -40,7 +40,7 @@ static struct pcmcia_irqs irqs[] = {
static int sg2_pcmcia_hw_init(struct soc_pcmcia_socket *skt) 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)); return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
} }
......
/* /*
* VIPER PCMCIA support * Viper/Zeus PCMCIA support
* Copyright 2004 Arcom Control Systems * Copyright 2004 Arcom Control Systems
* *
* Maintained by Marc Zyngier <maz@misterjones.org> * Maintained by Marc Zyngier <maz@misterjones.org>
* <marc.zyngier@altran.com>
* *
* Based on: * Based on:
* iPAQ h2200 PCMCIA support * iPAQ h2200 PCMCIA support
...@@ -26,37 +25,47 @@ ...@@ -26,37 +25,47 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <mach/viper.h> #include <mach/arcom-pcmcia.h>
#include <asm/mach-types.h>
#include "soc_common.h" #include "soc_common.h"
#include "pxa2xx_base.h" #include "pxa2xx_base.h"
static struct platform_device *arcom_pcmcia_dev;
static struct pcmcia_irqs irqs[] = { 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) static int viper_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{ {
struct arcom_pcmcia_pdata *pdata = viper_get_pdata();
unsigned long flags; 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; 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; 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; goto err_request_pwr;
local_irq_save(flags); local_irq_save(flags);
/* GPIO 82 is the CF power enable line. initially off */ if (gpio_direction_output(pdata->pwr_gpio, 0) ||
if (gpio_direction_output(VIPER_CF_POWER_GPIO, 0) || gpio_direction_input(pdata->cd_gpio) ||
gpio_direction_input(VIPER_CF_CD_GPIO) || gpio_direction_input(pdata->rdy_gpio)) {
gpio_direction_input(VIPER_CF_RDY_GPIO)) {
local_irq_restore(flags); local_irq_restore(flags);
goto err_dir; goto err_dir;
} }
...@@ -66,13 +75,13 @@ static int viper_pcmcia_hw_init(struct soc_pcmcia_socket *skt) ...@@ -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)); return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
err_dir: err_dir:
gpio_free(VIPER_CF_POWER_GPIO); gpio_free(pdata->pwr_gpio);
err_request_pwr: err_request_pwr:
gpio_free(VIPER_CF_RDY_GPIO); gpio_free(pdata->rdy_gpio);
err_request_rdy: err_request_rdy:
gpio_free(VIPER_CF_CD_GPIO); gpio_free(pdata->cd_gpio);
err_request_cd: 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; return -1;
} }
...@@ -81,17 +90,21 @@ static int viper_pcmcia_hw_init(struct soc_pcmcia_socket *skt) ...@@ -81,17 +90,21 @@ static int viper_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
*/ */
static void viper_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) 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)); soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
gpio_free(VIPER_CF_POWER_GPIO); gpio_free(pdata->pwr_gpio);
gpio_free(VIPER_CF_RDY_GPIO); gpio_free(pdata->rdy_gpio);
gpio_free(VIPER_CF_CD_GPIO); gpio_free(pdata->cd_gpio);
} }
static void viper_pcmcia_socket_state(struct soc_pcmcia_socket *skt, static void viper_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
struct pcmcia_state *state) struct pcmcia_state *state)
{ {
state->detect = gpio_get_value(VIPER_CF_CD_GPIO) ? 0 : 1; struct arcom_pcmcia_pdata *pdata = viper_get_pdata();
state->ready = gpio_get_value(VIPER_CF_RDY_GPIO) ? 1 : 0;
state->detect = !gpio_get_value(pdata->cd_gpio);
state->ready = !!gpio_get_value(pdata->rdy_gpio);
state->bvd1 = 1; state->bvd1 = 1;
state->bvd2 = 1; state->bvd2 = 1;
state->wrprot = 0; state->wrprot = 0;
...@@ -102,20 +115,21 @@ static void viper_pcmcia_socket_state(struct soc_pcmcia_socket *skt, ...@@ -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, static int viper_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
const socket_state_t *state) const socket_state_t *state)
{ {
struct arcom_pcmcia_pdata *pdata = viper_get_pdata();
/* Silently ignore Vpp, output enable, speaker enable. */ /* Silently ignore Vpp, output enable, speaker enable. */
viper_cf_rst(state->flags & SS_RESET); pdata->reset(state->flags & SS_RESET);
/* Apply socket voltage */ /* Apply socket voltage */
switch (state->Vcc) { switch (state->Vcc) {
case 0: case 0:
gpio_set_value(VIPER_CF_POWER_GPIO, 0); gpio_set_value(pdata->pwr_gpio, 0);
break; break;
case 33: case 33:
gpio_set_value(VIPER_CF_POWER_GPIO, 1); gpio_set_value(pdata->pwr_gpio, 1);
break; break;
default: default:
printk(KERN_ERR "%s: Unsupported Vcc:%d\n", dev_err(&arcom_pcmcia_dev->dev, "Unsupported Vcc:%d\n", state->Vcc);
__func__, state->Vcc);
return -1; return -1;
} }
...@@ -130,7 +144,7 @@ static void viper_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) ...@@ -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, .owner = THIS_MODULE,
.hw_init = viper_pcmcia_hw_init, .hw_init = viper_pcmcia_hw_init,
.hw_shutdown = viper_pcmcia_hw_shutdown, .hw_shutdown = viper_pcmcia_hw_shutdown,
...@@ -143,17 +157,25 @@ static struct pcmcia_low_level viper_pcmcia_ops __initdata = { ...@@ -143,17 +157,25 @@ static struct pcmcia_low_level viper_pcmcia_ops __initdata = {
static struct platform_device *viper_pcmcia_device; 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; int ret;
if (!machine_is_viper()) /* I can't imagine more than one device, but you never know... */
return -ENODEV; if (arcom_pcmcia_dev)
return -EEXIST;
if (!pdev->dev.platform_data)
return -EINVAL;
viper_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); viper_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
if (!viper_pcmcia_device) if (!viper_pcmcia_device)
return -ENOMEM; return -ENOMEM;
arcom_pcmcia_dev = pdev;
viper_pcmcia_device->dev.parent = &pdev->dev;
ret = platform_device_add_data(viper_pcmcia_device, ret = platform_device_add_data(viper_pcmcia_device,
&viper_pcmcia_ops, &viper_pcmcia_ops,
sizeof(viper_pcmcia_ops)); sizeof(viper_pcmcia_ops));
...@@ -161,18 +183,49 @@ static int __init viper_pcmcia_init(void) ...@@ -161,18 +183,49 @@ static int __init viper_pcmcia_init(void)
if (!ret) if (!ret)
ret = platform_device_add(viper_pcmcia_device); ret = platform_device_add(viper_pcmcia_device);
if (ret) if (ret) {
platform_device_put(viper_pcmcia_device); platform_device_put(viper_pcmcia_device);
arcom_pcmcia_dev = NULL;
}
return ret; return ret;
} }
static void __exit viper_pcmcia_exit(void) static int viper_pcmcia_remove(struct platform_device *pdev)
{ {
platform_device_unregister(viper_pcmcia_device); 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_init(viper_pcmcia_init);
module_exit(viper_pcmcia_exit); module_exit(viper_pcmcia_exit);
MODULE_DEVICE_TABLE(platform, viper_pcmcia_id_table);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment