Merge ../linux-2.6

This commit is contained in:
Mauro Carvalho Chehab 2008-07-24 14:05:50 -03:00
commit 698158c799
291 changed files with 16312 additions and 3645 deletions

View File

@ -2034,6 +2034,9 @@ and is between 256 and 4096 characters. It is defined in the file
snd-ymfpci= [HW,ALSA]
softlockup_panic=
[KNL] Should the soft-lockup detector generate panics.
sonypi.*= [HW] Sony Programmable I/O Control Device driver
See Documentation/sonypi.txt

View File

@ -441,10 +441,7 @@ M: spyro@f2s.com
S: Maintained
ARM PRIMECELL MMCI PL180/1 DRIVER
P: Russell King
M: rmk@arm.linux.org.uk
L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
S: Maintained
S: Orphan
ARM/ADI ROADRUNNER MACHINE SUPPORT
P: Lennert Buytenhek
@ -483,11 +480,28 @@ M: kernel@wantstofly.org
L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
S: Maintained
ARM/COMPULAB CM-X270/EM-X270 MACHINE SUPPORT
P: Mike Rapoport
M: mike@compulab.co.il
L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
S: Maintained
ARM/CORGI MACHINE SUPPORT
P: Richard Purdie
M: rpurdie@rpsys.net
S: Maintained
ARM/EZX SMARTPHONES (A780, A910, A1200, E680, ROKR E2 and ROKR E6)
P: Daniel Ribeiro
M: drwyrm@gmail.com
P: Stefan Schmidt
M: stefan@openezx.org
P: Harald Welte
M: laforge@openezx.org
L: openezx-devel@lists.openezx.org (subscribers-only)
W: http://www.openezx.org/
S: Maintained
ARM/GLOMATION GESBC9312SX MACHINE SUPPORT
P: Lennert Buytenhek
M: kernel@wantstofly.org
@ -575,10 +589,18 @@ L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
S: Maintained
ARM/TOSA MACHINE SUPPORT
P: Dmitry Baryshkov
M: dbaryshkov@gmail.com
P: Dirk Opfer
M: dirk@opfer-online.de
S: Maintained
ARM/PALMTX SUPPORT
P: Marek Vasut
M: marek.vasut@gmail.com
W: http://hackndev.com
S: Maintained
ARM/PLEB SUPPORT
P: Peter Chubb
M: pleb@gelato.unsw.edu.au

View File

@ -12,6 +12,7 @@ config ARM
select RTC_LIB
select SYS_SUPPORTS_APM_EMULATION
select HAVE_OPROFILE
select HAVE_ARCH_KGDB
select HAVE_KPROBES if (!XIP_KERNEL)
select HAVE_KRETPROBES if (HAVE_KPROBES)
select HAVE_FTRACE if (!XIP_KERNEL)

View File

@ -627,7 +627,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
if (!sachip)
return -ENOMEM;
sachip->clk = clk_get(me, "GPIO27_CLK");
sachip->clk = clk_get(me, "SA1111_CLK");
if (!sachip->clk) {
ret = PTR_ERR(sachip->clk);
goto err_free;

File diff suppressed because it is too large Load Diff

View File

@ -28,6 +28,7 @@ obj-$(CONFIG_KPROBES) += kprobes.o kprobes-decode.o
obj-$(CONFIG_ATAGS_PROC) += atags.o
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
obj-$(CONFIG_ARM_THUMBEE) += thumbee.o
obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312

201
arch/arm/kernel/kgdb.c Normal file
View File

@ -0,0 +1,201 @@
/*
* arch/arm/kernel/kgdb.c
*
* ARM KGDB support
*
* Copyright (c) 2002-2004 MontaVista Software, Inc
* Copyright (c) 2008 Wind River Systems, Inc.
*
* Authors: George Davis <davis_g@mvista.com>
* Deepak Saxena <dsaxena@plexity.net>
*/
#include <linux/kgdb.h>
#include <asm/traps.h>
/* Make a local copy of the registers passed into the handler (bletch) */
void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs)
{
int regno;
/* Initialize all to zero. */
for (regno = 0; regno < GDB_MAX_REGS; regno++)
gdb_regs[regno] = 0;
gdb_regs[_R0] = kernel_regs->ARM_r0;
gdb_regs[_R1] = kernel_regs->ARM_r1;
gdb_regs[_R2] = kernel_regs->ARM_r2;
gdb_regs[_R3] = kernel_regs->ARM_r3;
gdb_regs[_R4] = kernel_regs->ARM_r4;
gdb_regs[_R5] = kernel_regs->ARM_r5;
gdb_regs[_R6] = kernel_regs->ARM_r6;
gdb_regs[_R7] = kernel_regs->ARM_r7;
gdb_regs[_R8] = kernel_regs->ARM_r8;
gdb_regs[_R9] = kernel_regs->ARM_r9;
gdb_regs[_R10] = kernel_regs->ARM_r10;
gdb_regs[_FP] = kernel_regs->ARM_fp;
gdb_regs[_IP] = kernel_regs->ARM_ip;
gdb_regs[_SPT] = kernel_regs->ARM_sp;
gdb_regs[_LR] = kernel_regs->ARM_lr;
gdb_regs[_PC] = kernel_regs->ARM_pc;
gdb_regs[_CPSR] = kernel_regs->ARM_cpsr;
}
/* Copy local gdb registers back to kgdb regs, for later copy to kernel */
void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs)
{
kernel_regs->ARM_r0 = gdb_regs[_R0];
kernel_regs->ARM_r1 = gdb_regs[_R1];
kernel_regs->ARM_r2 = gdb_regs[_R2];
kernel_regs->ARM_r3 = gdb_regs[_R3];
kernel_regs->ARM_r4 = gdb_regs[_R4];
kernel_regs->ARM_r5 = gdb_regs[_R5];
kernel_regs->ARM_r6 = gdb_regs[_R6];
kernel_regs->ARM_r7 = gdb_regs[_R7];
kernel_regs->ARM_r8 = gdb_regs[_R8];
kernel_regs->ARM_r9 = gdb_regs[_R9];
kernel_regs->ARM_r10 = gdb_regs[_R10];
kernel_regs->ARM_fp = gdb_regs[_FP];
kernel_regs->ARM_ip = gdb_regs[_IP];
kernel_regs->ARM_sp = gdb_regs[_SPT];
kernel_regs->ARM_lr = gdb_regs[_LR];
kernel_regs->ARM_pc = gdb_regs[_PC];
kernel_regs->ARM_cpsr = gdb_regs[_CPSR];
}
void
sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task)
{
struct pt_regs *thread_regs;
int regno;
/* Just making sure... */
if (task == NULL)
return;
/* Initialize to zero */
for (regno = 0; regno < GDB_MAX_REGS; regno++)
gdb_regs[regno] = 0;
/* Otherwise, we have only some registers from switch_to() */
thread_regs = task_pt_regs(task);
gdb_regs[_R0] = thread_regs->ARM_r0;
gdb_regs[_R1] = thread_regs->ARM_r1;
gdb_regs[_R2] = thread_regs->ARM_r2;
gdb_regs[_R3] = thread_regs->ARM_r3;
gdb_regs[_R4] = thread_regs->ARM_r4;
gdb_regs[_R5] = thread_regs->ARM_r5;
gdb_regs[_R6] = thread_regs->ARM_r6;
gdb_regs[_R7] = thread_regs->ARM_r7;
gdb_regs[_R8] = thread_regs->ARM_r8;
gdb_regs[_R9] = thread_regs->ARM_r9;
gdb_regs[_R10] = thread_regs->ARM_r10;
gdb_regs[_FP] = thread_regs->ARM_fp;
gdb_regs[_IP] = thread_regs->ARM_ip;
gdb_regs[_SPT] = thread_regs->ARM_sp;
gdb_regs[_LR] = thread_regs->ARM_lr;
gdb_regs[_PC] = thread_regs->ARM_pc;
gdb_regs[_CPSR] = thread_regs->ARM_cpsr;
}
static int compiled_break;
int kgdb_arch_handle_exception(int exception_vector, int signo,
int err_code, char *remcom_in_buffer,
char *remcom_out_buffer,
struct pt_regs *linux_regs)
{
unsigned long addr;
char *ptr;
switch (remcom_in_buffer[0]) {
case 'D':
case 'k':
case 'c':
kgdb_contthread = NULL;
/*
* Try to read optional parameter, pc unchanged if no parm.
* If this was a compiled breakpoint, we need to move
* to the next instruction or we will just breakpoint
* over and over again.
*/
ptr = &remcom_in_buffer[1];
if (kgdb_hex2long(&ptr, &addr))
linux_regs->ARM_pc = addr;
else if (compiled_break == 1)
linux_regs->ARM_pc += 4;
compiled_break = 0;
return 0;
}
return -1;
}
static int kgdb_brk_fn(struct pt_regs *regs, unsigned int instr)
{
kgdb_handle_exception(1, SIGTRAP, 0, regs);
return 0;
}
static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int instr)
{
compiled_break = 1;
kgdb_handle_exception(1, SIGTRAP, 0, regs);
return 0;
}
static struct undef_hook kgdb_brkpt_hook = {
.instr_mask = 0xffffffff,
.instr_val = KGDB_BREAKINST,
.fn = kgdb_brk_fn
};
static struct undef_hook kgdb_compiled_brkpt_hook = {
.instr_mask = 0xffffffff,
.instr_val = KGDB_COMPILED_BREAK,
.fn = kgdb_compiled_brk_fn
};
/**
* kgdb_arch_init - Perform any architecture specific initalization.
*
* This function will handle the initalization of any architecture
* specific callbacks.
*/
int kgdb_arch_init(void)
{
register_undef_hook(&kgdb_brkpt_hook);
register_undef_hook(&kgdb_compiled_brkpt_hook);
return 0;
}
/**
* kgdb_arch_exit - Perform any architecture specific uninitalization.
*
* This function will handle the uninitalization of any architecture
* specific callbacks, for dynamic registration and unregistration.
*/
void kgdb_arch_exit(void)
{
unregister_undef_hook(&kgdb_brkpt_hook);
unregister_undef_hook(&kgdb_compiled_brkpt_hook);
}
/*
* Register our undef instruction hooks with ARM undef core.
* We regsiter a hook specifically looking for the KGB break inst
* and we handle the normal undef case within the do_undefinstr
* handler.
*/
struct kgdb_arch arch_kgdb_ops = {
#ifndef __ARMEB__
.gdb_bpt_instr = {0xfe, 0xde, 0xff, 0xe7}
#else /* ! __ARMEB__ */
.gdb_bpt_instr = {0xe7, 0xff, 0xde, 0xfe}
#endif
};

View File

@ -36,6 +36,7 @@
#include <asm/mach/arch.h>
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
#include <asm/traps.h>
#include "compat.h"
#include "atags.h"
@ -853,6 +854,7 @@ void __init setup_arch(char **cmdline_p)
conswitchp = &dummy_con;
#endif
#endif
early_trap_init();
}

View File

@ -707,6 +707,11 @@ void abort(void)
EXPORT_SYMBOL(abort);
void __init trap_init(void)
{
return;
}
void __init early_trap_init(void)
{
unsigned long vectors = CONFIG_VECTORS_BASE;
extern char __stubs_start[], __stubs_end[];

View File

@ -16,18 +16,24 @@ config CPU_PXA310
config CPU_PXA320
bool "PXA320 (codename Monahans-P)"
config CPU_PXA930
bool "PXA930 (codename Tavor-P)"
endmenu
endif
menu "Select target boards"
config ARCH_GUMSTIX
bool "Gumstix XScale boards"
help
Say Y here if you intend to run this kernel on a
Gumstix Full Function Minature Computer.
config MACH_GUMSTIX_F
bool "Basix, Connex, ws-200ax, ws-400ax systems"
depends on ARCH_GUMSTIX
select PXA25x
config ARCH_LUBBOCK
bool "Intel DBPXA250 Development Platform"
select PXA25x
@ -58,146 +64,6 @@ config PXA_SHARPSL
SL-C3000 (Spitz), SL-C3100 (Borzoi) or SL-C6000x (Tosa)
handheld computer.
config ARCH_PXA_ESERIES
bool "PXA based Toshiba e-series PDAs"
select PXA25x
config MACH_E330
bool "Toshiba e330"
default y
depends on ARCH_PXA_ESERIES
help
Say Y here if you intend to run this kernel on a Toshiba
e330 family PDA.
config MACH_E740
bool "Toshiba e740"
default y
depends on ARCH_PXA_ESERIES
help
Say Y here if you intend to run this kernel on a Toshiba
e740 family PDA.
config MACH_E750
bool "Toshiba e750"
default y
depends on ARCH_PXA_ESERIES
help
Say Y here if you intend to run this kernel on a Toshiba
e750 family PDA.
config MACH_E400
bool "Toshiba e400"
default y
depends on ARCH_PXA_ESERIES
help
Say Y here if you intend to run this kernel on a Toshiba
e400 family PDA.
config MACH_E800
bool "Toshiba e800"
default y
depends on ARCH_PXA_ESERIES
help
Say Y here if you intend to run this kernel on a Toshiba
e800 family PDA.
config MACH_TRIZEPS4
bool "Keith und Koep Trizeps4 DIMM-Module"
select PXA27x
config MACH_EM_X270
bool "CompuLab EM-x270 platform"
select PXA27x
config MACH_COLIBRI
bool "Toradex Colibri PX27x"
select PXA27x
config MACH_ZYLONITE
bool "PXA3xx Development Platform"
select PXA3xx
select HAVE_PWM
config MACH_LITTLETON
bool "PXA3xx Form Factor Platform (aka Littleton)"
select PXA3xx
select PXA_SSP
config MACH_ARMCORE
bool "CompuLab CM-X270 modules"
select PXA27x
select IWMMXT
config MACH_MAGICIAN
bool "Enable HTC Magician Support"
depends on ARCH_PXA
select PXA27x
select IWMMXT
config MACH_PCM027
bool "Phytec phyCORE-PXA270 CPU module (PCM-027)"
select PXA27x
select IWMMXT
endmenu
choice
prompt "Used baseboard"
depends on MACH_PCM027
config MACH_PCM990_BASEBOARD
bool "PHYTEC PCM-990 development board"
select HAVE_PWM
endchoice
choice
prompt "display on pcm990"
depends on MACH_PCM990_BASEBOARD
config PCM990_DISPLAY_SHARP
bool "sharp lq084v1dg21 stn display"
config PCM990_DISPLAY_NEC
bool "nec nl6448bc20_18d tft display"
config PCM990_DISPLAY_NONE
bool "no display"
endchoice
if ARCH_GUMSTIX
choice
prompt "Select target Gumstix board"
config MACH_GUMSTIX_F
bool "Basix, Connex, ws-200ax, ws-400ax systems"
select PXA25x
endchoice
endif
if MACH_TRIZEPS4
choice
prompt "Select base board for Trizeps 4 module"
config MACH_TRIZEPS4_CONXS
bool "ConXS Eval Board"
config MACH_TRIZEPS4_ANY
bool "another Board"
endchoice
endif
endmenu
config MACH_POODLE
bool "Enable Sharp SL-5600 (Poodle) Support"
depends on PXA_SHARPSL
@ -249,6 +115,186 @@ config MACH_TOSA
depends on PXA_SHARPSL
select PXA25x
config ARCH_PXA_ESERIES
bool "PXA based Toshiba e-series PDAs"
select PXA25x
config MACH_E330
bool "Toshiba e330"
default y
depends on ARCH_PXA_ESERIES
help
Say Y here if you intend to run this kernel on a Toshiba
e330 family PDA.
config MACH_E350
bool "Toshiba e350"
default y
depends on ARCH_PXA_ESERIES
help
Say Y here if you intend to run this kernel on a Toshiba
e350 family PDA.
config MACH_E740
bool "Toshiba e740"
default y
depends on ARCH_PXA_ESERIES
select FB_W100
help
Say Y here if you intend to run this kernel on a Toshiba
e740 family PDA.
config MACH_E750
bool "Toshiba e750"
default y
depends on ARCH_PXA_ESERIES
select FB_W100
help
Say Y here if you intend to run this kernel on a Toshiba
e750 family PDA.
config MACH_E400
bool "Toshiba e400"
default y
depends on ARCH_PXA_ESERIES
help
Say Y here if you intend to run this kernel on a Toshiba
e400 family PDA.
config MACH_E800
bool "Toshiba e800"
default y
depends on ARCH_PXA_ESERIES
select FB_W100
help
Say Y here if you intend to run this kernel on a Toshiba
e800 family PDA.
config MACH_TRIZEPS4
bool "Keith und Koep Trizeps4 DIMM-Module"
select PXA27x
config MACH_TRIZEPS4_CONXS
bool "ConXS Eval Board"
depends on MACH_TRIZEPS4
config MACH_EM_X270
bool "CompuLab EM-x270 platform"
select PXA27x
config MACH_COLIBRI
bool "Toradex Colibri PX27x"
select PXA27x
config MACH_ZYLONITE
bool "PXA3xx Development Platform (aka Zylonite)"
select PXA3xx
select HAVE_PWM
config MACH_LITTLETON
bool "PXA3xx Form Factor Platform (aka Littleton)"
select PXA3xx
select PXA_SSP
config MACH_TAVOREVB
bool "PXA930 Evaluation Board (aka TavorEVB)"
select PXA3xx
select PXA930
config MACH_SAAR
bool "PXA930 Handheld Platform (aka SAAR)"
select PXA3xx
select PXA930
config MACH_ARMCORE
bool "CompuLab CM-X270 modules"
select PXA27x
select IWMMXT
config MACH_MAGICIAN
bool "Enable HTC Magician Support"
select PXA27x
select IWMMXT
config MACH_PCM027
bool "Phytec phyCORE-PXA270 CPU module (PCM-027)"
select PXA27x
select IWMMXT
select PXA_SSP
config ARCH_PXA_PALM
bool "PXA based Palm PDAs"
select HAVE_PWM
config MACH_PALMTX
bool "Palm T|X"
default y
depends on ARCH_PXA_PALM
select PXA27x
select IWMMXT
help
Say Y here if you intend to run this kernel on a Palm T|X
handheld computer.
config MACH_PCM990_BASEBOARD
bool "PHYTEC PCM-990 development board"
select HAVE_PWM
depends on MACH_PCM027
choice
prompt "display on pcm990"
depends on MACH_PCM990_BASEBOARD
config PCM990_DISPLAY_SHARP
bool "sharp lq084v1dg21 stn display"
config PCM990_DISPLAY_NEC
bool "nec nl6448bc20_18d tft display"
config PCM990_DISPLAY_NONE
bool "no display"
endchoice
config PXA_EZX
bool "Motorola EZX Platform"
select PXA27x
select IWMMXT
select HAVE_PWM
config MACH_EZX_A780
bool "Motorola EZX A780"
default y
depends on PXA_EZX
config MACH_EZX_E680
bool "Motorola EZX E680"
default y
depends on PXA_EZX
config MACH_EZX_A1200
bool "Motorola EZX A1200"
default y
depends on PXA_EZX
config MACH_EZX_A910
bool "Motorola EZX A910"
default y
depends on PXA_EZX
config MACH_EZX_E6
bool "Motorola EZX E6"
default y
depends on PXA_EZX
config MACH_EZX_E2
bool "Motorola EZX E2"
default y
depends on PXA_EZX
endmenu
config PXA25x
bool
help
@ -288,4 +334,13 @@ config PXA_PWM
default BACKLIGHT_PWM
help
Enable support for PXA2xx/PXA3xx PWM controllers
config TOSA_BT
tristate "Control the state of built-in bluetooth chip on Sharp SL-6000"
depends on MACH_TOSA
select RFKILL
help
This is a simple driver that is able to control
the state of built in bluetooth chip on tosa.
endif

View File

@ -4,7 +4,7 @@
# Common support (must be linked before board specific support)
obj-y += clock.o devices.o generic.o irq.o dma.o \
time.o gpio.o
time.o gpio.o reset.o
obj-$(CONFIG_PM) += pm.o sleep.o standby.o
obj-$(CONFIG_CPU_FREQ) += cpu-pxa.o
@ -18,6 +18,7 @@ obj-$(CONFIG_PXA27x) += mfp-pxa2xx.o pxa2xx.o pxa27x.o
obj-$(CONFIG_PXA3xx) += mfp-pxa3xx.o pxa3xx.o smemc.o
obj-$(CONFIG_CPU_PXA300) += pxa300.o
obj-$(CONFIG_CPU_PXA320) += pxa320.o
obj-$(CONFIG_CPU_PXA930) += pxa930.o
# Specific board support
obj-$(CONFIG_ARCH_GUMSTIX) += gumstix.o
@ -36,7 +37,12 @@ obj-$(CONFIG_MACH_PCM990_BASEBOARD) += pcm990-baseboard.o
obj-$(CONFIG_MACH_TOSA) += tosa.o
obj-$(CONFIG_MACH_EM_X270) += em-x270.o
obj-$(CONFIG_MACH_MAGICIAN) += magician.o
obj-$(CONFIG_ARCH_PXA_ESERIES) += eseries.o
obj-$(CONFIG_ARCH_PXA_ESERIES) += eseries.o eseries_udc.o
obj-$(CONFIG_MACH_E740) += e740_lcd.o
obj-$(CONFIG_MACH_E750) += e750_lcd.o
obj-$(CONFIG_MACH_E400) += e400_lcd.o
obj-$(CONFIG_MACH_E800) += e800_lcd.o
obj-$(CONFIG_MACH_PALMTX) += palmtx.o
ifeq ($(CONFIG_MACH_ZYLONITE),y)
obj-y += zylonite.o
@ -44,8 +50,11 @@ ifeq ($(CONFIG_MACH_ZYLONITE),y)
obj-$(CONFIG_CPU_PXA320) += zylonite_pxa320.o
endif
obj-$(CONFIG_MACH_LITTLETON) += littleton.o
obj-$(CONFIG_MACH_TAVOREVB) += tavorevb.o
obj-$(CONFIG_MACH_SAAR) += saar.o
obj-$(CONFIG_MACH_ARMCORE) += cm-x270.o
obj-$(CONFIG_PXA_EZX) += ezx.o
# Support for blinky lights
led-y := leds.o
@ -59,3 +68,5 @@ obj-$(CONFIG_LEDS) += $(led-y)
ifeq ($(CONFIG_PCI),y)
obj-$(CONFIG_MACH_ARMCORE) += cm-x270-pci.o
endif
obj-$(CONFIG_TOSA_BT) += tosa-bt.o

View File

@ -101,21 +101,6 @@ unsigned long clk_get_rate(struct clk *clk)
EXPORT_SYMBOL(clk_get_rate);
static void clk_gpio27_enable(struct clk *clk)
{
pxa_gpio_mode(GPIO11_3_6MHz_MD);
}
static void clk_gpio27_disable(struct clk *clk)
{
}
static const struct clkops clk_gpio27_ops = {
.enable = clk_gpio27_enable,
.disable = clk_gpio27_disable,
};
void clk_cken_enable(struct clk *clk)
{
CKEN |= 1 << clk->cken;
@ -131,14 +116,6 @@ const struct clkops clk_cken_ops = {
.disable = clk_cken_disable,
};
static struct clk common_clks[] = {
{
.name = "GPIO27_CLK",
.ops = &clk_gpio27_ops,
.rate = 3686400,
},
};
void clks_register(struct clk *clks, size_t num)
{
int i;
@ -148,10 +125,3 @@ void clks_register(struct clk *clks, size_t num)
list_add(&clks[i].node, &clocks);
mutex_unlock(&clocks_mutex);
}
static int __init clk_init(void)
{
clks_register(common_clks, ARRAY_SIZE(common_clks));
return 0;
}
arch_initcall(clk_init);

View File

@ -47,9 +47,42 @@ struct clk {
.other = _other, \
}
#define INIT_CLK(_name, _ops, _rate, _delay, _dev) \
{ \
.name = _name, \
.dev = _dev, \
.ops = _ops, \
.rate = _rate, \
.delay = _delay, \
}
extern const struct clkops clk_cken_ops;
void clk_cken_enable(struct clk *clk);
void clk_cken_disable(struct clk *clk);
#ifdef CONFIG_PXA3xx
#define PXA3xx_CKEN(_name, _cken, _rate, _delay, _dev) \
{ \
.name = _name, \
.dev = _dev, \
.ops = &clk_pxa3xx_cken_ops, \
.rate = _rate, \
.cken = CKEN_##_cken, \
.delay = _delay, \
}
#define PXA3xx_CK(_name, _cken, _ops, _dev) \
{ \
.name = _name, \
.dev = _dev, \
.ops = _ops, \
.cken = CKEN_##_cken, \
}
extern const struct clkops clk_pxa3xx_cken_ops;
extern void clk_pxa3xx_cken_enable(struct clk *);
extern void clk_pxa3xx_cken_disable(struct clk *);
#endif
void clks_register(struct clk *clks, size_t num);

View File

@ -5,7 +5,7 @@
*
* Bits taken from various places.
*
* Copyright (C) 2007 Compulab, Ltd.
* Copyright (C) 2007, 2008 Compulab, Ltd.
* Mike Rapoport <mike@compulab.co.il>
*
* This program is free software; you can redistribute it and/or modify
@ -19,16 +19,16 @@
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <asm/mach/pci.h>
#include <asm/arch/cm-x270.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/pxa2xx-gpio.h>
#include <asm/mach-types.h>
#include <asm/hardware/it8152.h>
unsigned long it8152_base_address = CMX270_IT8152_VIRT;
unsigned long it8152_base_address;
static int cmx270_it8152_irq_gpio;
/*
* Only first 64MB of memory can be accessed via PCI.
@ -42,7 +42,7 @@ void __init cmx270_pci_adjust_zones(int node, unsigned long *zone_size,
unsigned int sz = SZ_64M >> PAGE_SHIFT;
if (machine_is_armcore()) {
pr_info("Adjusting zones for CM-x270\n");
pr_info("Adjusting zones for CM-X270\n");
/*
* Only adjust if > 64M on current system
@ -60,19 +60,20 @@ void __init cmx270_pci_adjust_zones(int node, unsigned long *zone_size,
static void cmx270_it8152_irq_demux(unsigned int irq, struct irq_desc *desc)
{
/* clear our parent irq */
GEDR(GPIO_IT8152_IRQ) = GPIO_bit(GPIO_IT8152_IRQ);
GEDR(cmx270_it8152_irq_gpio) = GPIO_bit(cmx270_it8152_irq_gpio);
it8152_irq_demux(irq, desc);
}
void __cmx270_pci_init_irq(void)
void __cmx270_pci_init_irq(int irq_gpio)
{
it8152_init_irq();
pxa_gpio_mode(IRQ_TO_GPIO(GPIO_IT8152_IRQ));
set_irq_type(IRQ_GPIO(GPIO_IT8152_IRQ), IRQT_RISING);
set_irq_chained_handler(IRQ_GPIO(GPIO_IT8152_IRQ),
cmx270_it8152_irq_demux);
cmx270_it8152_irq_gpio = irq_gpio;
set_irq_type(gpio_to_irq(irq_gpio), IRQT_RISING);
set_irq_chained_handler(gpio_to_irq(irq_gpio), cmx270_it8152_irq_demux);
}
#ifdef CONFIG_PM
@ -115,8 +116,8 @@ static int __init cmx270_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
/*
Here comes the ugly part. The routing is baseboard specific,
but defining a platform for each possible base of CM-x270 is
unrealistic. Here we keep mapping for ATXBase and SB-x270.
but defining a platform for each possible base of CM-X270 is
unrealistic. Here we keep mapping for ATXBase and SB-X270.
*/
/* ATXBASE PCI slot */
if (slot == 7)

View File

@ -1,13 +1,13 @@
extern void __cmx270_pci_init_irq(void);
extern void __cmx270_pci_init_irq(int irq_gpio);
extern void __cmx270_pci_suspend(void);
extern void __cmx270_pci_resume(void);
#ifdef CONFIG_PCI
#define cmx270_pci_init_irq __cmx270_pci_init_irq
#define cmx270_pci_suspend __cmx270_pci_suspend
#define cmx270_pci_resume __cmx270_pci_resume
#define cmx270_pci_init_irq(x) __cmx270_pci_init_irq(x)
#define cmx270_pci_suspend(x) __cmx270_pci_suspend(x)
#define cmx270_pci_resume(x) __cmx270_pci_resume(x)
#else
#define cmx270_pci_init_irq() do {} while (0)
#define cmx270_pci_suspend() do {} while (0)
#define cmx270_pci_resume() do {} while (0)
#define cmx270_pci_init_irq(x) do {} while (0)
#define cmx270_pci_suspend(x) do {} while (0)
#define cmx270_pci_resume(x) do {} while (0)
#endif

View File

@ -1,7 +1,7 @@
/*
* linux/arch/arm/mach-pxa/cm-x270.c
*
* Copyright (C) 2007 CompuLab, Ltd.
* Copyright (C) 2007, 2008 CompuLab, Ltd.
* Mike Rapoport <mike@compulab.co.il>
*
* This program is free software; you can redistribute it and/or modify
@ -9,44 +9,156 @@
* published by the Free Software Foundation.
*/
#include <linux/types.h>
#include <linux/pm.h>
#include <linux/fb.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <linux/sysdev.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/dm9000.h>
#include <linux/rtc-v3020.h>
#include <linux/serial_8250.h>
#include <video/mbxfb.h>
#include <linux/leds.h>
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
#include <asm/mach/map.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/pxa2xx-regs.h>
#include <asm/arch/pxa2xx-gpio.h>
#include <asm/arch/mfp-pxa27x.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/audio.h>
#include <asm/arch/pxafb.h>
#include <asm/arch/ohci.h>
#include <asm/arch/mmc.h>
#include <asm/arch/bitfield.h>
#include <asm/arch/cm-x270.h>
#include <asm/hardware/it8152.h>
#include "generic.h"
#include "cm-x270-pci.h"
/* virtual addresses for statically mapped regions */
#define CMX270_VIRT_BASE (0xe8000000)
#define CMX270_IT8152_VIRT (CMX270_VIRT_BASE)
#define RTC_PHYS_BASE (PXA_CS1_PHYS + (5 << 22))
#define DM9000_PHYS_BASE (PXA_CS1_PHYS + (6 << 22))
static struct resource cmx270_dm9k_resource[] = {
/* GPIO IRQ usage */
#define GPIO10_ETHIRQ (10)
#define GPIO22_IT8152_IRQ (22)
#define GPIO83_MMC_IRQ (83)
#define GPIO95_GFXIRQ (95)
#define CMX270_ETHIRQ IRQ_GPIO(GPIO10_ETHIRQ)
#define CMX270_IT8152_IRQ IRQ_GPIO(GPIO22_IT8152_IRQ)
#define CMX270_MMC_IRQ IRQ_GPIO(GPIO83_MMC_IRQ)
#define CMX270_GFXIRQ IRQ_GPIO(GPIO95_GFXIRQ)
/* MMC power enable */
#define GPIO105_MMC_POWER (105)
static unsigned long cmx270_pin_config[] = {
/* AC'97 */
GPIO28_AC97_BITCLK,
GPIO29_AC97_SDATA_IN_0,
GPIO30_AC97_SDATA_OUT,
GPIO31_AC97_SYNC,
GPIO98_AC97_SYSCLK,
GPIO113_AC97_nRESET,
/* BTUART */
GPIO42_BTUART_RXD,
GPIO43_BTUART_TXD,
GPIO44_BTUART_CTS,
GPIO45_BTUART_RTS,
/* STUART */
GPIO46_STUART_RXD,
GPIO47_STUART_TXD,
/* MCI controller */
GPIO32_MMC_CLK,
GPIO112_MMC_CMD,
GPIO92_MMC_DAT_0,
GPIO109_MMC_DAT_1,
GPIO110_MMC_DAT_2,
GPIO111_MMC_DAT_3,
/* LCD */
GPIO58_LCD_LDD_0,
GPIO59_LCD_LDD_1,
GPIO60_LCD_LDD_2,
GPIO61_LCD_LDD_3,
GPIO62_LCD_LDD_4,
GPIO63_LCD_LDD_5,
GPIO64_LCD_LDD_6,
GPIO65_LCD_LDD_7,
GPIO66_LCD_LDD_8,
GPIO67_LCD_LDD_9,
GPIO68_LCD_LDD_10,
GPIO69_LCD_LDD_11,
GPIO70_LCD_LDD_12,
GPIO71_LCD_LDD_13,
GPIO72_LCD_LDD_14,
GPIO73_LCD_LDD_15,
GPIO74_LCD_FCLK,
GPIO75_LCD_LCLK,
GPIO76_LCD_PCLK,
GPIO77_LCD_BIAS,
/* I2C */
GPIO117_I2C_SCL,
GPIO118_I2C_SDA,
/* SSP1 */
GPIO23_SSP1_SCLK,
GPIO24_SSP1_SFRM,
GPIO25_SSP1_TXD,
GPIO26_SSP1_RXD,
/* SSP2 */
GPIO19_SSP2_SCLK,
GPIO14_SSP2_SFRM,
GPIO87_SSP2_TXD,
GPIO88_SSP2_RXD,
/* PC Card */
GPIO48_nPOE,
GPIO49_nPWE,
GPIO50_nPIOR,
GPIO51_nPIOW,
GPIO85_nPCE_1,
GPIO54_nPCE_2,
GPIO55_nPREG,
GPIO56_nPWAIT,
GPIO57_nIOIS16,
/* SDRAM and local bus */
GPIO15_nCS_1,
GPIO78_nCS_2,
GPIO79_nCS_3,
GPIO80_nCS_4,
GPIO33_nCS_5,
GPIO49_nPWE,
GPIO18_RDY,
/* GPIO */
GPIO0_GPIO | WAKEUP_ON_EDGE_BOTH,
GPIO105_GPIO | MFP_LPM_DRIVE_HIGH, /* MMC/SD power */
GPIO53_GPIO, /* PC card reset */
/* NAND controls */
GPIO11_GPIO | MFP_LPM_DRIVE_HIGH, /* NAND CE# */
GPIO89_GPIO, /* NAND Ready/Busy */
/* interrupts */
GPIO10_GPIO, /* DM9000 interrupt */
GPIO83_GPIO, /* MMC card detect */
};
#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
static struct resource cmx270_dm9000_resource[] = {
[0] = {
.start = DM9000_PHYS_BASE,
.end = DM9000_PHYS_BASE + 4,
@ -64,31 +176,45 @@ static struct resource cmx270_dm9k_resource[] = {
}
};
/* for the moment we limit ourselves to 32bit IO until some
* better IO routines can be written and tested
*/
static struct dm9000_plat_data cmx270_dm9k_platdata = {
static struct dm9000_plat_data cmx270_dm9000_platdata = {
.flags = DM9000_PLATF_32BITONLY,
};
/* Ethernet device */
static struct platform_device cmx270_device_dm9k = {
static struct platform_device cmx270_dm9000_device = {
.name = "dm9000",
.id = 0,
.num_resources = ARRAY_SIZE(cmx270_dm9k_resource),
.resource = cmx270_dm9k_resource,
.num_resources = ARRAY_SIZE(cmx270_dm9000_resource),
.resource = cmx270_dm9000_resource,
.dev = {
.platform_data = &cmx270_dm9k_platdata,
.platform_data = &cmx270_dm9000_platdata,
}
};
/* touchscreen controller */
static void __init cmx270_init_dm9000(void)
{
platform_device_register(&cmx270_dm9000_device);
}
#else
static inline void cmx270_init_dm9000(void) {}
#endif
/* UCB1400 touchscreen controller */
#if defined(CONFIG_TOUCHSCREEN_UCB1400) || defined(CONFIG_TOUCHSCREEN_UCB1400_MODULE)
static struct platform_device cmx270_ts_device = {
.name = "ucb1400_ts",
.id = -1,
};
/* RTC */
static void __init cmx270_init_touchscreen(void)
{
platform_device_register(&cmx270_ts_device);
}
#else
static inline void cmx270_init_touchscreen(void) {}
#endif
/* V3020 RTC */
#if defined(CONFIG_RTC_DRV_V3020) || defined(CONFIG_RTC_DRV_V3020_MODULE)
static struct resource cmx270_v3020_resource[] = {
[0] = {
.start = RTC_PHYS_BASE,
@ -111,28 +237,67 @@ static struct platform_device cmx270_rtc_device = {
}
};
/*
* CM-X270 LEDs
*/
static struct platform_device cmx270_led_device = {
.name = "cm-x270-led",
.id = -1,
static void __init cmx270_init_rtc(void)
{
platform_device_register(&cmx270_rtc_device);
}
#else
static inline void cmx270_init_rtc(void) {}
#endif
/* CM-X270 LEDs */
#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
static struct gpio_led cmx270_leds[] = {
[0] = {
.name = "cm-x270:red",
.default_trigger = "nand-disk",
.gpio = 93,
.active_low = 1,
},
[1] = {
.name = "cm-x270:green",
.default_trigger = "heartbeat",
.gpio = 94,
.active_low = 1,
},
};
static struct gpio_led_platform_data cmx270_gpio_led_pdata = {
.num_leds = ARRAY_SIZE(cmx270_leds),
.leds = cmx270_leds,
};
static struct platform_device cmx270_led_device = {
.name = "leds-gpio",
.id = -1,
.dev = {
.platform_data = &cmx270_gpio_led_pdata,
},
};
static void __init cmx270_init_leds(void)
{
platform_device_register(&cmx270_led_device);
}
#else
static inline void cmx270_init_leds(void) {}
#endif
/* 2700G graphics */
#if defined(CONFIG_FB_MBX) || defined(CONFIG_FB_MBX_MODULE)
static u64 fb_dma_mask = ~(u64)0;
static struct resource cmx270_2700G_resource[] = {
/* frame buffer memory including ODFB and External SDRAM */
[0] = {
.start = MARATHON_PHYS,
.end = MARATHON_PHYS + 0x02000000,
.start = PXA_CS2_PHYS,
.end = PXA_CS2_PHYS + 0x01ffffff,
.flags = IORESOURCE_MEM,
},
/* Marathon registers */
[1] = {
.start = MARATHON_PHYS + 0x03fe0000,
.end = MARATHON_PHYS + 0x03ffffff,
.start = PXA_CS2_PHYS + 0x03fe0000,
.end = PXA_CS2_PHYS + 0x03ffffff,
.flags = IORESOURCE_MEM,
},
};
@ -200,43 +365,15 @@ static struct platform_device cmx270_2700G = {
.id = -1,
};
static u64 ata_dma_mask = ~(u64)0;
static struct platform_device cmx270_ata = {
.name = "pata_cm_x270",
.id = -1,
.dev = {
.dma_mask = &ata_dma_mask,
.coherent_dma_mask = 0xffffffff,
},
};
/* platform devices */
static struct platform_device *platform_devices[] __initdata = {
&cmx270_device_dm9k,
&cmx270_rtc_device,
&cmx270_2700G,
&cmx270_led_device,
&cmx270_ts_device,
&cmx270_ata,
};
/* Map PCI companion and IDE/General Purpose CS statically */
static struct map_desc cmx270_io_desc[] __initdata = {
[0] = { /* IDE/general purpose space */
.virtual = CMX270_IDE104_VIRT,
.pfn = __phys_to_pfn(CMX270_IDE104_PHYS),
.length = SZ_64M - SZ_8M,
.type = MT_DEVICE
},
[1] = { /* PCI bridge */
.virtual = CMX270_IT8152_VIRT,
.pfn = __phys_to_pfn(CMX270_IT8152_PHYS),
.length = SZ_64M,
.type = MT_DEVICE
},
};
static void __init cmx270_init_2700G(void)
{
platform_device_register(&cmx270_2700G);
}
#else
static inline void cmx270_init_2700G(void) {}
#endif
#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
/*
Display definitions
keep these for backwards compatibility, although symbolic names (as
@ -446,7 +583,16 @@ static int __init cmx270_set_display(char *str)
*/
__setup("monitor=", cmx270_set_display);
static void __init cmx270_init_display(void)
{
set_pxa_fb_info(cmx270_display);
}
#else
static inline void cmx270_init_display(void) {}
#endif
/* PXA27x OHCI controller setup */
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
static int cmx270_ohci_init(struct device *dev)
{
/* Set the Power Control Polarity Low */
@ -461,35 +607,37 @@ static struct pxaohci_platform_data cmx270_ohci_platform_data = {
.init = cmx270_ohci_init,
};
static void __init cmx270_init_ohci(void)
{
pxa_set_ohci_info(&cmx270_ohci_platform_data);
}
#else
static inline void cmx270_init_ohci(void) {}
#endif
#if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE)
static int cmx270_mci_init(struct device *dev,
irq_handler_t cmx270_detect_int,
void *data)
{
int err;
/*
* setup GPIO for PXA27x MMC controller
*/
pxa_gpio_mode(GPIO32_MMCCLK_MD);
pxa_gpio_mode(GPIO112_MMCCMD_MD);
pxa_gpio_mode(GPIO92_MMCDAT0_MD);
pxa_gpio_mode(GPIO109_MMCDAT1_MD);
pxa_gpio_mode(GPIO110_MMCDAT2_MD);
pxa_gpio_mode(GPIO111_MMCDAT3_MD);
err = gpio_request(GPIO105_MMC_POWER, "MMC/SD power");
if (err) {
dev_warn(dev, "power gpio unavailable\n");
return err;
}
/* SB-X270 uses GPIO105 as SD power enable */
pxa_gpio_mode(105 | GPIO_OUT);
/* card detect IRQ on GPIO 83 */
pxa_gpio_mode(IRQ_TO_GPIO(CMX270_MMC_IRQ));
gpio_direction_output(GPIO105_MMC_POWER, 0);
err = request_irq(CMX270_MMC_IRQ, cmx270_detect_int,
IRQF_DISABLED | IRQF_TRIGGER_FALLING,
"MMC card detect", data);
if (err)
printk(KERN_ERR "cmx270_mci_init: MMC/SD: can't"
" request MMC card detect IRQ\n");
if (err) {
gpio_free(GPIO105_MMC_POWER);
dev_err(dev, "cmx270_mci_init: MMC/SD: can't"
" request MMC card detect IRQ\n");
}
return err;
}
@ -499,17 +647,18 @@ static void cmx270_mci_setpower(struct device *dev, unsigned int vdd)
struct pxamci_platform_data *p_d = dev->platform_data;
if ((1 << vdd) & p_d->ocr_mask) {
printk(KERN_DEBUG "%s: on\n", __func__);
GPCR(105) = GPIO_bit(105);
dev_dbg(dev, "power on\n");
gpio_set_value(GPIO105_MMC_POWER, 0);
} else {
GPSR(105) = GPIO_bit(105);
printk(KERN_DEBUG "%s: off\n", __func__);
gpio_set_value(GPIO105_MMC_POWER, 1);
dev_dbg(dev, "power off\n");
}
}
static void cmx270_mci_exit(struct device *dev, void *data)
{
free_irq(CMX270_MMC_IRQ, data);
gpio_free(GPIO105_MMC_POWER);
}
static struct pxamci_platform_data cmx270_mci_platform_data = {
@ -519,6 +668,14 @@ static struct pxamci_platform_data cmx270_mci_platform_data = {
.exit = cmx270_mci_exit,
};
static void __init cmx270_init_mmc(void)
{
pxa_set_mci_info(&cmx270_mci_platform_data);
}
#else
static inline void cmx270_init_mmc(void) {}
#endif
#ifdef CONFIG_PM
static unsigned long sleep_save_msc[10];
@ -580,53 +737,63 @@ static int __init cmx270_pm_init(void)
static int __init cmx270_pm_init(void) { return 0; }
#endif
#if defined(CONFIG_SND_PXA2XX_AC97) || defined(CONFIG_SND_PXA2XX_AC97_MODULE)
static void __init cmx270_init_ac97(void)
{
pxa_set_ac97_info(NULL);
}
#else
static inline void cmx270_init_ac97(void) {}
#endif
static void __init cmx270_init(void)
{
cmx270_pm_init();
set_pxa_fb_info(cmx270_display);
pxa2xx_mfp_config(ARRAY_AND_SIZE(cmx270_pin_config));
/* register CM-X270 platform devices */
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
pxa_set_ac97_info(NULL);
/* set MCI and OHCI platform parameters */
pxa_set_mci_info(&cmx270_mci_platform_data);
pxa_set_ohci_info(&cmx270_ohci_platform_data);
/* This enables the STUART */
pxa_gpio_mode(GPIO46_STRXD_MD);
pxa_gpio_mode(GPIO47_STTXD_MD);
/* This enables the BTUART */
pxa_gpio_mode(GPIO42_BTRXD_MD);
pxa_gpio_mode(GPIO43_BTTXD_MD);
pxa_gpio_mode(GPIO44_BTCTS_MD);
pxa_gpio_mode(GPIO45_BTRTS_MD);
cmx270_init_dm9000();
cmx270_init_rtc();
cmx270_init_display();
cmx270_init_mmc();
cmx270_init_ohci();
cmx270_init_ac97();
cmx270_init_touchscreen();
cmx270_init_leds();
cmx270_init_2700G();
}
static void __init cmx270_init_irq(void)
{
pxa27x_init_irq();
cmx270_pci_init_irq();
/* Setup interrupt for dm9000 */
pxa_gpio_mode(IRQ_TO_GPIO(CMX270_ETHIRQ));
set_irq_type(CMX270_ETHIRQ, IRQT_RISING);
/* Setup interrupt for 2700G */
pxa_gpio_mode(IRQ_TO_GPIO(CMX270_GFXIRQ));
set_irq_type(CMX270_GFXIRQ, IRQT_FALLING);
cmx270_pci_init_irq(GPIO22_IT8152_IRQ);
}
#ifdef CONFIG_PCI
/* Map PCI companion statically */
static struct map_desc cmx270_io_desc[] __initdata = {
[0] = { /* PCI bridge */
.virtual = CMX270_IT8152_VIRT,
.pfn = __phys_to_pfn(PXA_CS4_PHYS),
.length = SZ_64M,
.type = MT_DEVICE
},
};
static void __init cmx270_map_io(void)
{
pxa_map_io();
iotable_init(cmx270_io_desc, ARRAY_SIZE(cmx270_io_desc));
}
it8152_base_address = CMX270_IT8152_VIRT;
}
#else
static void __init cmx270_map_io(void)
{
pxa_map_io();
}
#endif
MACHINE_START(ARMCORE, "Compulab CM-x270")
.boot_params = 0xa0000100,

View File

@ -465,6 +465,7 @@ static void corgi_irda_transceiver_mode(struct device *dev, int mode)
GPSR(CORGI_GPIO_IR_ON) = GPIO_bit(CORGI_GPIO_IR_ON);
else
GPCR(CORGI_GPIO_IR_ON) = GPIO_bit(CORGI_GPIO_IR_ON);
pxa2xx_transceiver_mode(dev, mode);
}
static struct pxaficp_platform_data corgi_ficp_platform_data = {

View File

@ -13,8 +13,10 @@
#include <asm/arch/mfp-pxa27x.h>
#include <asm/arch/ohci.h>
#include <asm/arch/pxa27x_keypad.h>
#include <asm/arch/pxa2xx_spi.h>
#include <asm/arch/camera.h>
#include <asm/arch/audio.h>
#include <asm/arch/pxa3xx_nand.h>
#include "devices.h"
#include "generic.h"
@ -830,4 +832,63 @@ void __init pxa3xx_set_mci3_info(struct pxamci_platform_data *info)
pxa_register_device(&pxa3xx_device_mci3, info);
}
static struct resource pxa3xx_resources_nand[] = {
[0] = {
.start = 0x43100000,
.end = 0x43100053,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_NAND,
.end = IRQ_NAND,
.flags = IORESOURCE_IRQ,
},
[2] = {
/* DRCMR for Data DMA */
.start = 97,
.end = 97,
.flags = IORESOURCE_DMA,
},
[3] = {
/* DRCMR for Command DMA */
.start = 99,
.end = 99,
.flags = IORESOURCE_DMA,
},
};
static u64 pxa3xx_nand_dma_mask = DMA_BIT_MASK(32);
struct platform_device pxa3xx_device_nand = {
.name = "pxa3xx-nand",
.id = -1,
.dev = {
.dma_mask = &pxa3xx_nand_dma_mask,
.coherent_dma_mask = DMA_BIT_MASK(32),
},
.num_resources = ARRAY_SIZE(pxa3xx_resources_nand),
.resource = pxa3xx_resources_nand,
};
void __init pxa3xx_set_nand_info(struct pxa3xx_nand_platform_data *info)
{
pxa_register_device(&pxa3xx_device_nand, info);
}
#endif /* CONFIG_PXA3xx */
/* pxa2xx-spi platform-device ID equals respective SSP platform-device ID + 1.
* See comment in arch/arm/mach-pxa/ssp.c::ssp_probe() */
void __init pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info)
{
struct platform_device *pd;
pd = platform_device_alloc("pxa2xx-spi", id);
if (pd == NULL) {
printk(KERN_ERR "pxa2xx-spi: failed to allocate device id %d\n",
id);
return;
}
pd->dev.platform_data = info;
platform_device_add(pd);
}

View File

@ -31,4 +31,6 @@ extern struct platform_device pxa25x_device_pwm1;
extern struct platform_device pxa27x_device_pwm0;
extern struct platform_device pxa27x_device_pwm1;
extern struct platform_device pxa3xx_device_nand;
void __init pxa_register_device(struct platform_device *dev, void *data);

View File

@ -0,0 +1,56 @@
/*
* e400_lcd.c
*
* (c) 2005 Ian Molton <spyro@f2s.com>
*
* 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/init.h>
#include <linux/module.h>
#include <asm/mach-types.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/pxafb.h>
static struct pxafb_mode_info e400_pxafb_mode_info = {
.pixclock = 140703,
.xres = 240,
.yres = 320,
.bpp = 16,
.hsync_len = 4,
.left_margin = 28,
.right_margin = 8,
.vsync_len = 3,
.upper_margin = 5,
.lower_margin = 6,
.sync = 0,
};
static struct pxafb_mach_info e400_pxafb_mach_info = {
.modes = &e400_pxafb_mode_info,
.num_modes = 1,
.lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
.lccr3 = 0,
.pxafb_backlight_power = NULL,
};
static int __init e400_lcd_init(void)
{
if (!machine_is_e400())
return -ENODEV;
set_pxa_fb_info(&e400_pxafb_mach_info);
return 0;
}
module_init(e400_lcd_init);
MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
MODULE_DESCRIPTION("e400 lcd driver");
MODULE_LICENSE("GPLv2");

View File

@ -0,0 +1,123 @@
/* e740_lcd.c
*
* This file contains the definitions for the LCD timings and functions
* to control the LCD power / frontlighting via the w100fb driver.
*
* (c) 2005 Ian Molton <spyro@f2s.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/module.h>
#include <linux/device.h>
#include <linux/fb.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <asm/mach-types.h>
#include <video/w100fb.h>
/*
**potential** shutdown routine - to be investigated
devmem2 0x0c010528 w 0xff3fff00
devmem2 0x0c010190 w 0x7FFF8000
devmem2 0x0c0101b0 w 0x00FF0000
devmem2 0x0c01008c w 0x00000000
devmem2 0x0c010080 w 0x000000bf
devmem2 0x0c010098 w 0x00000015
devmem2 0x0c010088 w 0x4b000204
devmem2 0x0c010098 w 0x0000001d
*/
static struct w100_gen_regs e740_lcd_regs = {
.lcd_format = 0x00008023,
.lcdd_cntl1 = 0x0f000000,
.lcdd_cntl2 = 0x0003ffff,
.genlcd_cntl1 = 0x00ffff03,
.genlcd_cntl2 = 0x003c0f03,
.genlcd_cntl3 = 0x000143aa,
};
static struct w100_mode e740_lcd_mode = {
.xres = 240,
.yres = 320,
.left_margin = 20,
.right_margin = 28,
.upper_margin = 9,
.lower_margin = 8,
.crtc_ss = 0x80140013,
.crtc_ls = 0x81150110,
.crtc_gs = 0x80050005,
.crtc_vpos_gs = 0x000a0009,
.crtc_rev = 0x0040010a,
.crtc_dclk = 0xa906000a,
.crtc_gclk = 0x80050108,
.crtc_goe = 0x80050108,
.pll_freq = 57,
.pixclk_divider = 4,
.pixclk_divider_rotated = 4,
.pixclk_src = CLK_SRC_XTAL,
.sysclk_divider = 1,
.sysclk_src = CLK_SRC_PLL,
.crtc_ps1_active = 0x41060010,
};
static struct w100_gpio_regs e740_w100_gpio_info = {
.init_data1 = 0x21002103,
.gpio_dir1 = 0xffffdeff,
.gpio_oe1 = 0x03c00643,
.init_data2 = 0x003f003f,
.gpio_dir2 = 0xffffffff,
.gpio_oe2 = 0x000000ff,
};
static struct w100fb_mach_info e740_fb_info = {
.modelist = &e740_lcd_mode,
.num_modes = 1,
.regs = &e740_lcd_regs,
.gpio = &e740_w100_gpio_info,
.xtal_freq = 14318000,
.xtal_dbl = 1,
};
static struct resource e740_fb_resources[] = {
[0] = {
.start = 0x0c000000,
.end = 0x0cffffff,
.flags = IORESOURCE_MEM,
},
};
/* ----------------------- device declarations -------------------------- */
static struct platform_device e740_fb_device = {
.name = "w100fb",
.id = -1,
.dev = {
.platform_data = &e740_fb_info,
},
.num_resources = ARRAY_SIZE(e740_fb_resources),
.resource = e740_fb_resources,
};
static int e740_lcd_init(void)
{
int ret;
if (!machine_is_e740())
return -ENODEV;
return platform_device_register(&e740_fb_device);
}
module_init(e740_lcd_init);
MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
MODULE_DESCRIPTION("e740 lcd driver");
MODULE_LICENSE("GPLv2");

View File

@ -0,0 +1,109 @@
/* e750_lcd.c
*
* This file contains the definitions for the LCD timings and functions
* to control the LCD power / frontlighting via the w100fb driver.
*
* (c) 2005 Ian Molton <spyro@f2s.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/module.h>
#include <linux/device.h>
#include <linux/fb.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <asm/mach-types.h>
#include <video/w100fb.h>
static struct w100_gen_regs e750_lcd_regs = {
.lcd_format = 0x00008003,
.lcdd_cntl1 = 0x00000000,
.lcdd_cntl2 = 0x0003ffff,
.genlcd_cntl1 = 0x00fff003,
.genlcd_cntl2 = 0x003c0f03,
.genlcd_cntl3 = 0x000143aa,
};
static struct w100_mode e750_lcd_mode = {
.xres = 240,
.yres = 320,
.left_margin = 21,
.right_margin = 22,
.upper_margin = 5,
.lower_margin = 4,
.crtc_ss = 0x80150014,
.crtc_ls = 0x8014000d,
.crtc_gs = 0xc1000005,
.crtc_vpos_gs = 0x00020147,
.crtc_rev = 0x0040010a,
.crtc_dclk = 0xa1700030,
.crtc_gclk = 0x80cc0015,
.crtc_goe = 0x80cc0015,
.crtc_ps1_active = 0x61060017,
.pll_freq = 57,
.pixclk_divider = 4,
.pixclk_divider_rotated = 4,
.pixclk_src = CLK_SRC_XTAL,
.sysclk_divider = 1,
.sysclk_src = CLK_SRC_PLL,
};
static struct w100_gpio_regs e750_w100_gpio_info = {
.init_data1 = 0x01192f1b,
.gpio_dir1 = 0xd5ffdeff,
.gpio_oe1 = 0x000020bf,
.init_data2 = 0x010f010f,
.gpio_dir2 = 0xffffffff,
.gpio_oe2 = 0x000001cf,
};
static struct w100fb_mach_info e750_fb_info = {
.modelist = &e750_lcd_mode,
.num_modes = 1,
.regs = &e750_lcd_regs,
.gpio = &e750_w100_gpio_info,
.xtal_freq = 14318000,
.xtal_dbl = 1,
};
static struct resource e750_fb_resources[] = {
[0] = {
.start = 0x0c000000,
.end = 0x0cffffff,
.flags = IORESOURCE_MEM,
},
};
/* ----------------------- device declarations -------------------------- */
static struct platform_device e750_fb_device = {
.name = "w100fb",
.id = -1,
.dev = {
.platform_data = &e750_fb_info,
},
.num_resources = ARRAY_SIZE(e750_fb_resources),
.resource = e750_fb_resources,
};
static int e750_lcd_init(void)
{
if (!machine_is_e750())
return -ENODEV;
return platform_device_register(&e750_fb_device);
}
module_init(e750_lcd_init);
MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
MODULE_DESCRIPTION("e750 lcd driver");
MODULE_LICENSE("GPLv2");

View File

@ -0,0 +1,159 @@
/* e800_lcd.c
*
* This file contains the definitions for the LCD timings and functions
* to control the LCD power / frontlighting via the w100fb driver.
*
* (c) 2005 Ian Molton <spyro@f2s.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/module.h>
#include <linux/device.h>
#include <linux/fb.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <asm/mach-types.h>
#include <video/w100fb.h>
static struct w100_gen_regs e800_lcd_regs = {
.lcd_format = 0x00008003,
.lcdd_cntl1 = 0x02a00000,
.lcdd_cntl2 = 0x0003ffff,
.genlcd_cntl1 = 0x000ff2a3,
.genlcd_cntl2 = 0x000002a3,
.genlcd_cntl3 = 0x000102aa,
};
static struct w100_mode e800_lcd_mode[2] = {
[0] = {
.xres = 480,
.yres = 640,
.left_margin = 52,
.right_margin = 148,
.upper_margin = 2,
.lower_margin = 6,
.crtc_ss = 0x80350034,
.crtc_ls = 0x802b0026,
.crtc_gs = 0x80160016,
.crtc_vpos_gs = 0x00020003,
.crtc_rev = 0x0040001d,
.crtc_dclk = 0xe0000000,
.crtc_gclk = 0x82a50049,
.crtc_goe = 0x80ee001c,
.crtc_ps1_active = 0x00000000,
.pll_freq = 128,
.pixclk_divider = 4,
.pixclk_divider_rotated = 6,
.pixclk_src = CLK_SRC_PLL,
.sysclk_divider = 0,
.sysclk_src = CLK_SRC_PLL,
},
[1] = {
.xres = 240,
.yres = 320,
.left_margin = 15,
.right_margin = 88,
.upper_margin = 0,
.lower_margin = 7,
.crtc_ss = 0xd010000f,
.crtc_ls = 0x80070003,
.crtc_gs = 0x80000000,
.crtc_vpos_gs = 0x01460147,
.crtc_rev = 0x00400003,
.crtc_dclk = 0xa1700030,
.crtc_gclk = 0x814b0008,
.crtc_goe = 0x80cc0015,
.crtc_ps1_active = 0x00000000,
.pll_freq = 100,
.pixclk_divider = 6, /* Wince uses 14 which gives a 7MHz pclk. */
.pixclk_divider_rotated = 6, /* we want a 14MHz one (much nicer to look at) */
.pixclk_src = CLK_SRC_PLL,
.sysclk_divider = 0,
.sysclk_src = CLK_SRC_PLL,
}
};
static struct w100_gpio_regs e800_w100_gpio_info = {
.init_data1 = 0xc13fc019,
.gpio_dir1 = 0x3e40df7f,
.gpio_oe1 = 0x003c3000,
.init_data2 = 0x00000000,
.gpio_dir2 = 0x00000000,
.gpio_oe2 = 0x00000000,
};
static struct w100_mem_info e800_w100_mem_info = {
.ext_cntl = 0x09640011,
.sdram_mode_reg = 0x00600021,
.ext_timing_cntl = 0x10001545,
.io_cntl = 0x7ddd7333,
.size = 0x1fffff,
};
static void e800_tg_change(struct w100fb_par *par)
{
unsigned long tmp;
tmp = w100fb_gpio_read(W100_GPIO_PORT_A);
if (par->mode->xres == 480)
tmp |= 0x100;
else
tmp &= ~0x100;
w100fb_gpio_write(W100_GPIO_PORT_A, tmp);
}
static struct w100_tg_info e800_tg_info = {
.change = e800_tg_change,
};
static struct w100fb_mach_info e800_fb_info = {
.modelist = e800_lcd_mode,
.num_modes = 2,
.regs = &e800_lcd_regs,
.gpio = &e800_w100_gpio_info,
.mem = &e800_w100_mem_info,
.tg = &e800_tg_info,
.xtal_freq = 16000000,
};
static struct resource e800_fb_resources[] = {
[0] = {
.start = 0x0c000000,
.end = 0x0cffffff,
.flags = IORESOURCE_MEM,
},
};
/* ----------------------- device declarations -------------------------- */
static struct platform_device e800_fb_device = {
.name = "w100fb",
.id = -1,
.dev = {
.platform_data = &e800_fb_info,
},
.num_resources = ARRAY_SIZE(e800_fb_resources),
.resource = e800_fb_resources,
};
static int e800_lcd_init(void)
{
if (!machine_is_e800())
return -ENODEV;
return platform_device_register(&e800_fb_device);
}
module_init(e800_lcd_init);
MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
MODULE_DESCRIPTION("e800 lcd driver");
MODULE_LICENSE("GPLv2");

View File

@ -1,7 +1,7 @@
/*
* Support for CompuLab EM-x270 platform
* Support for CompuLab EM-X270 platform
*
* Copyright (C) 2007 CompuLab, Ltd.
* Copyright (C) 2007, 2008 CompuLab, Ltd.
* Author: Mike Rapoport <mike@compulab.co.il>
*
* This program is free software; you can redistribute it and/or modify
@ -14,31 +14,159 @@
#include <linux/dm9000.h>
#include <linux/rtc-v3020.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/input.h>
#include <linux/gpio_keys.h>
#include <linux/gpio.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/arch/mfp-pxa27x.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/pxa2xx-gpio.h>
#include <asm/arch/pxa27x-udc.h>
#include <asm/arch/audio.h>
#include <asm/arch/pxafb.h>
#include <asm/arch/ohci.h>
#include <asm/arch/mmc.h>
#include <asm/arch/bitfield.h>
#include <asm/arch/pxa27x_keypad.h>
#include "generic.h"
/* GPIO IRQ usage */
#define EM_X270_MMC_PD (105)
#define EM_X270_ETHIRQ IRQ_GPIO(41)
#define EM_X270_MMC_IRQ IRQ_GPIO(13)
#define GPIO41_ETHIRQ (41)
#define GPIO13_MMC_CD (13)
#define EM_X270_ETHIRQ IRQ_GPIO(GPIO41_ETHIRQ)
#define EM_X270_MMC_CD IRQ_GPIO(GPIO13_MMC_CD)
static struct resource em_x270_dm9k_resource[] = {
/* NAND control GPIOs */
#define GPIO11_NAND_CS (11)
#define GPIO56_NAND_RB (56)
static unsigned long em_x270_pin_config[] = {
/* AC'97 */
GPIO28_AC97_BITCLK,
GPIO29_AC97_SDATA_IN_0,
GPIO30_AC97_SDATA_OUT,
GPIO31_AC97_SYNC,
GPIO98_AC97_SYSCLK,
GPIO113_AC97_nRESET,
/* BTUART */
GPIO42_BTUART_RXD,
GPIO43_BTUART_TXD,
GPIO44_BTUART_CTS,
GPIO45_BTUART_RTS,
/* STUART */
GPIO46_STUART_RXD,
GPIO47_STUART_TXD,
/* MCI controller */
GPIO32_MMC_CLK,
GPIO112_MMC_CMD,
GPIO92_MMC_DAT_0,
GPIO109_MMC_DAT_1,
GPIO110_MMC_DAT_2,
GPIO111_MMC_DAT_3,
/* LCD */
GPIO58_LCD_LDD_0,
GPIO59_LCD_LDD_1,
GPIO60_LCD_LDD_2,
GPIO61_LCD_LDD_3,
GPIO62_LCD_LDD_4,
GPIO63_LCD_LDD_5,
GPIO64_LCD_LDD_6,
GPIO65_LCD_LDD_7,
GPIO66_LCD_LDD_8,
GPIO67_LCD_LDD_9,
GPIO68_LCD_LDD_10,
GPIO69_LCD_LDD_11,
GPIO70_LCD_LDD_12,
GPIO71_LCD_LDD_13,
GPIO72_LCD_LDD_14,
GPIO73_LCD_LDD_15,
GPIO74_LCD_FCLK,
GPIO75_LCD_LCLK,
GPIO76_LCD_PCLK,
GPIO77_LCD_BIAS,
/* QCI */
GPIO84_CIF_FV,
GPIO25_CIF_LV,
GPIO53_CIF_MCLK,
GPIO54_CIF_PCLK,
GPIO81_CIF_DD_0,
GPIO55_CIF_DD_1,
GPIO51_CIF_DD_2,
GPIO50_CIF_DD_3,
GPIO52_CIF_DD_4,
GPIO48_CIF_DD_5,
GPIO17_CIF_DD_6,
GPIO12_CIF_DD_7,
/* I2C */
GPIO117_I2C_SCL,
GPIO118_I2C_SDA,
/* Keypad */
GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH,
GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH,
GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH,
GPIO34_KP_MKIN_3 | WAKEUP_ON_LEVEL_HIGH,
GPIO39_KP_MKIN_4 | WAKEUP_ON_LEVEL_HIGH,
GPIO99_KP_MKIN_5 | WAKEUP_ON_LEVEL_HIGH,
GPIO91_KP_MKIN_6 | WAKEUP_ON_LEVEL_HIGH,
GPIO36_KP_MKIN_7 | WAKEUP_ON_LEVEL_HIGH,
GPIO103_KP_MKOUT_0,
GPIO104_KP_MKOUT_1,
GPIO105_KP_MKOUT_2,
GPIO106_KP_MKOUT_3,
GPIO107_KP_MKOUT_4,
GPIO108_KP_MKOUT_5,
GPIO96_KP_MKOUT_6,
GPIO22_KP_MKOUT_7,
/* SSP1 */
GPIO26_SSP1_RXD,
GPIO23_SSP1_SCLK,
GPIO24_SSP1_SFRM,
GPIO57_SSP1_TXD,
/* SSP2 */
GPIO19_SSP2_SCLK,
GPIO14_SSP2_SFRM,
GPIO89_SSP2_TXD,
GPIO88_SSP2_RXD,
/* SDRAM and local bus */
GPIO15_nCS_1,
GPIO78_nCS_2,
GPIO79_nCS_3,
GPIO80_nCS_4,
GPIO49_nPWE,
GPIO18_RDY,
/* GPIO */
GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH,
/* power controls */
GPIO20_GPIO | MFP_LPM_DRIVE_LOW, /* GPRS_PWEN */
GPIO115_GPIO | MFP_LPM_DRIVE_LOW, /* WLAN_PWEN */
/* NAND controls */
GPIO11_GPIO | MFP_LPM_DRIVE_HIGH, /* NAND CE# */
GPIO56_GPIO, /* NAND Ready/Busy */
/* interrupts */
GPIO13_GPIO, /* MMC card detect */
GPIO41_GPIO, /* DM9000 interrupt */
};
#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
static struct resource em_x270_dm9000_resource[] = {
[0] = {
.start = PXA_CS2_PHYS,
.end = PXA_CS2_PHYS + 3,
@ -56,32 +184,30 @@ static struct resource em_x270_dm9k_resource[] = {
}
};
/* for the moment we limit ourselves to 32bit IO until some
* better IO routines can be written and tested
*/
static struct dm9000_plat_data em_x270_dm9k_platdata = {
static struct dm9000_plat_data em_x270_dm9000_platdata = {
.flags = DM9000_PLATF_32BITONLY,
};
/* Ethernet device */
static struct platform_device em_x270_dm9k = {
static struct platform_device em_x270_dm9000 = {
.name = "dm9000",
.id = 0,
.num_resources = ARRAY_SIZE(em_x270_dm9k_resource),
.resource = em_x270_dm9k_resource,
.num_resources = ARRAY_SIZE(em_x270_dm9000_resource),
.resource = em_x270_dm9000_resource,
.dev = {
.platform_data = &em_x270_dm9k_platdata,
.platform_data = &em_x270_dm9000_platdata,
}
};
/* WM9712 touchscreen controller. Hopefully the driver will make it to
* the mainstream sometime */
static struct platform_device em_x270_ts = {
.name = "wm97xx-ts",
.id = -1,
};
static void __init em_x270_init_dm9000(void)
{
platform_device_register(&em_x270_dm9000);
}
#else
static inline void em_x270_init_dm9000(void) {}
#endif
/* RTC */
/* V3020 RTC */
#if defined(CONFIG_RTC_DRV_V3020) || defined(CONFIG_RTC_DRV_V3020_MODULE)
static struct resource em_x270_v3020_resource[] = {
[0] = {
.start = PXA_CS4_PHYS,
@ -104,20 +230,26 @@ static struct platform_device em_x270_rtc = {
}
};
/* NAND flash */
#define GPIO_NAND_CS (11)
#define GPIO_NAND_RB (56)
static void __init em_x270_init_rtc(void)
{
platform_device_register(&em_x270_rtc);
}
#else
static inline void em_x270_init_rtc(void) {}
#endif
/* NAND flash */
#if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
static inline void nand_cs_on(void)
{
GPCR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS);
gpio_set_value(GPIO11_NAND_CS, 0);
}
static void nand_cs_off(void)
{
dsb();
GPSR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS);
gpio_set_value(GPIO11_NAND_CS, 1);
}
/* hardware specific access to control-lines */
@ -157,7 +289,7 @@ static int em_x270_nand_device_ready(struct mtd_info *mtd)
{
dsb();
return GPLR(GPIO_NAND_RB) & GPIO_bit(GPIO_NAND_RB);
return gpio_get_value(GPIO56_NAND_RB);
}
static struct mtd_partition em_x270_partition_info[] = {
@ -210,16 +342,35 @@ static struct platform_device em_x270_nand = {
}
};
/* platform devices */
static struct platform_device *platform_devices[] __initdata = {
&em_x270_dm9k,
&em_x270_ts,
&em_x270_rtc,
&em_x270_nand,
};
static void __init em_x270_init_nand(void)
{
int err;
err = gpio_request(GPIO11_NAND_CS, "NAND CS");
if (err) {
pr_warning("EM-X270: failed to request NAND CS gpio\n");
return;
}
gpio_direction_output(GPIO11_NAND_CS, 1);
err = gpio_request(GPIO56_NAND_RB, "NAND R/B");
if (err) {
pr_warning("EM-X270: failed to request NAND R/B gpio\n");
gpio_free(GPIO11_NAND_CS);
return;
}
gpio_direction_input(GPIO56_NAND_RB);
platform_device_register(&em_x270_nand);
}
#else
static inline void em_x270_init_nand(void) {}
#endif
/* PXA27x OHCI controller setup */
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
static int em_x270_ohci_init(struct device *dev)
{
/* Set the Power Control Polarity Low */
@ -237,27 +388,23 @@ static struct pxaohci_platform_data em_x270_ohci_platform_data = {
.init = em_x270_ohci_init,
};
static void __init em_x270_init_ohci(void)
{
pxa_set_ohci_info(&em_x270_ohci_platform_data);
}
#else
static inline void em_x270_init_ohci(void) {}
#endif
/* MCI controller setup */
#if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE)
static int em_x270_mci_init(struct device *dev,
irq_handler_t em_x270_detect_int,
void *data)
{
int err;
/* setup GPIO for PXA27x MMC controller */
pxa_gpio_mode(GPIO32_MMCCLK_MD);
pxa_gpio_mode(GPIO112_MMCCMD_MD);
pxa_gpio_mode(GPIO92_MMCDAT0_MD);
pxa_gpio_mode(GPIO109_MMCDAT1_MD);
pxa_gpio_mode(GPIO110_MMCDAT2_MD);
pxa_gpio_mode(GPIO111_MMCDAT3_MD);
/* EM-X270 uses GPIO13 as SD power enable */
pxa_gpio_mode(EM_X270_MMC_PD | GPIO_OUT);
err = request_irq(EM_X270_MMC_IRQ, em_x270_detect_int,
IRQF_DISABLED | IRQF_TRIGGER_FALLING,
"MMC card detect", data);
int err = request_irq(EM_X270_MMC_CD, em_x270_detect_int,
IRQF_DISABLED | IRQF_TRIGGER_FALLING,
"MMC card detect", data);
if (err) {
printk(KERN_ERR "%s: can't request MMC card detect IRQ: %d\n",
__func__, err);
@ -279,7 +426,8 @@ static void em_x270_mci_setpower(struct device *dev, unsigned int vdd)
static void em_x270_mci_exit(struct device *dev, void *data)
{
free_irq(EM_X270_MMC_IRQ, data);
int irq = gpio_to_irq(GPIO13_MMC_CD);
free_irq(irq, data);
}
static struct pxamci_platform_data em_x270_mci_platform_data = {
@ -289,7 +437,16 @@ static struct pxamci_platform_data em_x270_mci_platform_data = {
.exit = em_x270_mci_exit,
};
static void __init em_x270_init_mmc(void)
{
pxa_set_mci_info(&em_x270_mci_platform_data);
}
#else
static inline void em_x270_init_mmc(void) {}
#endif
/* LCD 480x640 */
#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
static struct pxafb_mode_info em_x270_lcd_mode = {
.pixclock = 50000,
.bpp = 16,
@ -307,40 +464,96 @@ static struct pxafb_mode_info em_x270_lcd_mode = {
static struct pxafb_mach_info em_x270_lcd = {
.modes = &em_x270_lcd_mode,
.num_modes = 1,
.cmap_inverse = 0,
.cmap_static = 0,
.lccr0 = LCCR0_PAS,
.lccr3 = LCCR3_PixClkDiv(0x01) | LCCR3_Acb(0xff),
.lcd_conn = LCD_COLOR_TFT_16BPP,
};
static void __init em_x270_init_lcd(void)
{
set_pxa_fb_info(&em_x270_lcd);
}
#else
static inline void em_x270_init_lcd(void) {}
#endif
#if defined(CONFIG_SND_PXA2XX_AC97) || defined(CONFIG_SND_PXA2XX_AC97_MODULE)
static void __init em_x270_init_ac97(void)
{
pxa_set_ac97_info(NULL);
}
#else
static inline void em_x270_init_ac97(void) {}
#endif
#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE)
static unsigned int em_x270_matrix_keys[] = {
KEY(0, 0, KEY_A), KEY(1, 0, KEY_UP), KEY(2, 1, KEY_B),
KEY(0, 2, KEY_LEFT), KEY(1, 1, KEY_ENTER), KEY(2, 0, KEY_RIGHT),
KEY(0, 1, KEY_C), KEY(1, 2, KEY_DOWN), KEY(2, 2, KEY_D),
};
struct pxa27x_keypad_platform_data em_x270_keypad_info = {
/* code map for the matrix keys */
.matrix_key_rows = 3,
.matrix_key_cols = 3,
.matrix_key_map = em_x270_matrix_keys,
.matrix_key_map_size = ARRAY_SIZE(em_x270_matrix_keys),
};
static void __init em_x270_init_keypad(void)
{
pxa_set_keypad_info(&em_x270_keypad_info);
}
#else
static inline void em_x270_init_keypad(void) {}
#endif
#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
static struct gpio_keys_button gpio_keys_button[] = {
[0] = {
.desc = "sleep/wakeup",
.code = KEY_SUSPEND,
.type = EV_PWR,
.gpio = 1,
.wakeup = 1,
},
};
static struct gpio_keys_platform_data em_x270_gpio_keys_data = {
.buttons = gpio_keys_button,
.nbuttons = 1,
};
static struct platform_device em_x270_gpio_keys = {
.name = "gpio-keys",
.id = -1,
.dev = {
.platform_data = &em_x270_gpio_keys_data,
},
};
static void __init em_x270_init_gpio_keys(void)
{
platform_device_register(&em_x270_gpio_keys);
}
#else
static inline void em_x270_init_gpio_keys(void) {}
#endif
static void __init em_x270_init(void)
{
/* setup LCD */
set_pxa_fb_info(&em_x270_lcd);
pxa2xx_mfp_config(ARRAY_AND_SIZE(em_x270_pin_config));
/* register EM-X270 platform devices */
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
pxa_set_ac97_info(NULL);
/* set MCI and OHCI platform parameters */
pxa_set_mci_info(&em_x270_mci_platform_data);
pxa_set_ohci_info(&em_x270_ohci_platform_data);
/* setup STUART GPIOs */
pxa_gpio_mode(GPIO46_STRXD_MD);
pxa_gpio_mode(GPIO47_STTXD_MD);
/* setup BTUART GPIOs */
pxa_gpio_mode(GPIO42_BTRXD_MD);
pxa_gpio_mode(GPIO43_BTTXD_MD);
pxa_gpio_mode(GPIO44_BTCTS_MD);
pxa_gpio_mode(GPIO45_BTRTS_MD);
/* Setup interrupt for dm9000 */
set_irq_type(EM_X270_ETHIRQ, IRQT_RISING);
em_x270_init_dm9000();
em_x270_init_rtc();
em_x270_init_nand();
em_x270_init_lcd();
em_x270_init_mmc();
em_x270_init_ohci();
em_x270_init_keypad();
em_x270_init_gpio_keys();
em_x270_init_ac97();
}
MACHINE_START(EM_X270, "Compulab EM-x270")
MACHINE_START(EM_X270, "Compulab EM-X270")
.boot_params = 0xa0000100,
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,

View File

@ -17,7 +17,7 @@
#include <asm/arch/hardware.h>
#include <asm/mach-types.h>
#include <generic.h>
#include "generic.h"
/* Only e800 has 128MB RAM */
static void __init eseries_fixup(struct machine_desc *desc,
@ -47,6 +47,19 @@ MACHINE_START(E330, "Toshiba e330")
MACHINE_END
#endif
#ifdef CONFIG_MACH_E350
MACHINE_START(E350, "Toshiba e350")
/* Maintainer: Ian Molton (spyro@f2s.com) */
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
.init_irq = pxa25x_init_irq,
.fixup = eseries_fixup,
.timer = &pxa_timer,
MACHINE_END
#endif
#ifdef CONFIG_MACH_E740
MACHINE_START(E740, "Toshiba e740")
/* Maintainer: Ian Molton (spyro@f2s.com) */

View File

@ -0,0 +1,57 @@
/*
* UDC functions for the Toshiba e-series PDAs
*
* Copyright (c) Ian Molton 2003
*
* This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <asm/arch/udc.h>
#include <asm/arch/eseries-gpio.h>
#include <asm/arch/hardware.h>
#include <asm/arch/pxa-regs.h>
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
#include <asm/mach/map.h>
#include <asm/domain.h>
/* local PXA generic code */
#include "generic.h"
static struct pxa2xx_udc_mach_info e7xx_udc_mach_info = {
.gpio_vbus = GPIO_E7XX_USB_DISC,
.gpio_pullup = GPIO_E7XX_USB_PULLUP,
.gpio_pullup_inverted = 1
};
static struct pxa2xx_udc_mach_info e800_udc_mach_info = {
.gpio_vbus = GPIO_E800_USB_DISC,
.gpio_pullup = GPIO_E800_USB_PULLUP,
.gpio_pullup_inverted = 1
};
static int __init eseries_udc_init(void)
{
if (machine_is_e330() || machine_is_e350() ||
machine_is_e740() || machine_is_e750() ||
machine_is_e400())
pxa_set_udc_info(&e7xx_udc_mach_info);
else if (machine_is_e800())
pxa_set_udc_info(&e800_udc_mach_info);
return 0;
}
module_init(eseries_udc_init);
MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
MODULE_DESCRIPTION("eseries UDC support");
MODULE_LICENSE("GPLv2");

220
arch/arm/mach-pxa/ezx.c Normal file
View File

@ -0,0 +1,220 @@
/*
* ezx.c - Common code for the EZX platform.
*
* Copyright (C) 2005-2006 Harald Welte <laforge@openezx.org>,
* 2007-2008 Daniel Ribeiro <drwyrm@gmail.com>,
* 2007-2008 Stefan Schmidt <stefan@datenfreihafen.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/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/pwm_backlight.h>
#include <asm/setup.h>
#include <asm/arch/pxafb.h>
#include <asm/arch/ohci.h>
#include <asm/arch/i2c.h>
#include <asm/arch/mfp-pxa27x.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/pxa2xx-regs.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include "devices.h"
#include "generic.h"
static struct platform_pwm_backlight_data ezx_backlight_data = {
.pwm_id = 0,
.max_brightness = 1023,
.dft_brightness = 1023,
.pwm_period_ns = 78770,
};
static struct platform_device ezx_backlight_device = {
.name = "pwm-backlight",
.dev = {
.parent = &pxa27x_device_pwm0.dev,
.platform_data = &ezx_backlight_data,
},
};
static struct pxafb_mode_info mode_ezx_old = {
.pixclock = 150000,
.xres = 240,
.yres = 320,
.bpp = 16,
.hsync_len = 10,
.left_margin = 20,
.right_margin = 10,
.vsync_len = 2,
.upper_margin = 3,
.lower_margin = 2,
.sync = 0,
};
static struct pxafb_mach_info ezx_fb_info_1 = {
.modes = &mode_ezx_old,
.num_modes = 1,
.lcd_conn = LCD_COLOR_TFT_16BPP,
};
static struct pxafb_mode_info mode_72r89803y01 = {
.pixclock = 192308,
.xres = 240,
.yres = 320,
.bpp = 32,
.depth = 18,
.hsync_len = 10,
.left_margin = 20,
.right_margin = 10,
.vsync_len = 2,
.upper_margin = 3,
.lower_margin = 2,
.sync = 0,
};
static struct pxafb_mach_info ezx_fb_info_2 = {
.modes = &mode_72r89803y01,
.num_modes = 1,
.lcd_conn = LCD_COLOR_TFT_18BPP,
};
static struct platform_device *devices[] __initdata = {
&ezx_backlight_device,
};
static unsigned long ezx_pin_config[] __initdata = {
/* PWM backlight */
GPIO16_PWM0_OUT,
/* BTUART */
GPIO42_BTUART_RXD,
GPIO43_BTUART_TXD,
GPIO44_BTUART_CTS,
GPIO45_BTUART_RTS,
/* STUART */
GPIO46_STUART_RXD,
GPIO47_STUART_TXD,
/* For A780 support (connected with Neptune GSM chip) */
GPIO30_USB_P3_2, /* ICL_TXENB */
GPIO31_USB_P3_6, /* ICL_VPOUT */
GPIO90_USB_P3_5, /* ICL_VPIN */
GPIO91_USB_P3_1, /* ICL_XRXD */
GPIO56_USB_P3_4, /* ICL_VMOUT */
GPIO113_USB_P3_3, /* /ICL_VMIN */
};
static void __init ezx_init(void)
{
pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config));
pxa_set_i2c_info(NULL);
if (machine_is_ezx_a780() || machine_is_ezx_e680())
set_pxa_fb_info(&ezx_fb_info_1);
else
set_pxa_fb_info(&ezx_fb_info_2);
platform_add_devices(devices, ARRAY_SIZE(devices));
}
static void __init ezx_fixup(struct machine_desc *desc, struct tag *tags,
char **cmdline, struct meminfo *mi)
{
/* We have two ram chips. First one with 32MB at 0xA0000000 and a second
* 16MB one at 0xAC000000
*/
mi->nr_banks = 2;
mi->bank[0].start = 0xa0000000;
mi->bank[0].node = 0;
mi->bank[0].size = (32*1024*1024);
mi->bank[1].start = 0xac000000;
mi->bank[1].node = 1;
mi->bank[1].size = (16*1024*1024);
}
#ifdef CONFIG_MACH_EZX_A780
MACHINE_START(EZX_A780, "Motorola EZX A780")
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = ezx_fixup,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
.init_machine = &ezx_init,
MACHINE_END
#endif
#ifdef CONFIG_MACH_EZX_E680
MACHINE_START(EZX_E680, "Motorola EZX E680")
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = ezx_fixup,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
.init_machine = &ezx_init,
MACHINE_END
#endif
#ifdef CONFIG_MACH_EZX_A1200
MACHINE_START(EZX_A1200, "Motorola EZX A1200")
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = ezx_fixup,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
.init_machine = &ezx_init,
MACHINE_END
#endif
#ifdef CONFIG_MACH_EZX_A910
MACHINE_START(EZX_A910, "Motorola EZX A910")
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = ezx_fixup,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
.init_machine = &ezx_init,
MACHINE_END
#endif
#ifdef CONFIG_MACH_EZX_E6
MACHINE_START(EZX_E6, "Motorola EZX E6")
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = ezx_fixup,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
.init_machine = &ezx_init,
MACHINE_END
#endif
#ifdef CONFIG_MACH_EZX_E2
MACHINE_START(EZX_E2, "Motorola EZX E2")
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = ezx_fixup,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
.init_machine = &ezx_init,
MACHINE_END
#endif

View File

@ -20,6 +20,7 @@
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/smc91x.h>
#include <asm/types.h>
#include <asm/setup.h>
@ -38,6 +39,7 @@
#include <asm/arch/pxafb.h>
#include <asm/arch/ssp.h>
#include <asm/arch/pxa27x_keypad.h>
#include <asm/arch/pxa3xx_nand.h>
#include <asm/arch/littleton.h>
#include "generic.h"
@ -101,18 +103,26 @@ static struct resource smc91x_resources[] = {
[1] = {
.start = IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO90)),
.end = IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO90)),
.flags = IORESOURCE_IRQ | IRQF_TRIGGER_FALLING,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
}
};
static struct smc91x_platdata littleton_smc91x_info = {
.flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT |
SMC91X_NOWAIT | SMC91X_USE_DMA,
};
static struct platform_device smc91x_device = {
.name = "smc91x",
.id = 0,
.num_resources = ARRAY_SIZE(smc91x_resources),
.resource = smc91x_resources,
.dev = {
.platform_data = &littleton_smc91x_info,
},
};
#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULES)
#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
/* use bit 30, 31 as the indicator of command parameter number */
#define CMD0(x) ((0x00000000) | ((x) << 9))
#define CMD1(x, x1) ((0x40000000) | ((x) << 9) | 0x100 | (x1))
@ -311,9 +321,9 @@ static void littleton_init_lcd(void)
}
#else
static inline void littleton_init_lcd(void) {};
#endif /* CONFIG_FB_PXA || CONFIG_FB_PXA_MODULES */
#endif /* CONFIG_FB_PXA || CONFIG_FB_PXA_MODULE */
#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULES)
#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE)
static unsigned int littleton_matrix_key_map[] = {
/* KEY(row, col, key_code) */
KEY(1, 3, KEY_0), KEY(0, 0, KEY_1), KEY(1, 0, KEY_2), KEY(2, 0, KEY_3),
@ -361,6 +371,57 @@ static void __init littleton_init_keypad(void)
static inline void littleton_init_keypad(void) {}
#endif
#if defined(CONFIG_MTD_NAND_PXA3xx) || defined(CONFIG_MTD_NAND_PXA3xx_MODULE)
static struct mtd_partition littleton_nand_partitions[] = {
[0] = {
.name = "Bootloader",
.offset = 0,
.size = 0x060000,
.mask_flags = MTD_WRITEABLE, /* force read-only */
},
[1] = {
.name = "Kernel",
.offset = 0x060000,
.size = 0x200000,
.mask_flags = MTD_WRITEABLE, /* force read-only */
},
[2] = {
.name = "Filesystem",
.offset = 0x0260000,
.size = 0x3000000, /* 48M - rootfs */
},
[3] = {
.name = "MassStorage",
.offset = 0x3260000,
.size = 0x3d40000,
},
[4] = {
.name = "BBT",
.offset = 0x6FA0000,
.size = 0x80000,
.mask_flags = MTD_WRITEABLE, /* force read-only */
},
/* NOTE: we reserve some blocks at the end of the NAND flash for
* bad block management, and the max number of relocation blocks
* differs on different platforms. Please take care with it when
* defining the partition table.
*/
};
static struct pxa3xx_nand_platform_data littleton_nand_info = {
.enable_arbiter = 1,
.parts = littleton_nand_partitions,
.nr_parts = ARRAY_SIZE(littleton_nand_partitions),
};
static void __init littleton_init_nand(void)
{
pxa3xx_set_nand_info(&littleton_nand_info);
}
#else
static inline void littleton_init_nand(void) {}
#endif /* CONFIG_MTD_NAND_PXA3xx || CONFIG_MTD_NAND_PXA3xx_MODULE */
static void __init littleton_init(void)
{
/* initialize MFP configurations */
@ -374,6 +435,7 @@ static void __init littleton_init(void)
littleton_init_lcd();
littleton_init_keypad();
littleton_init_nand();
}
MACHINE_START(LITTLETON, "Marvell Form Factor Development Platform (aka Littleton)")

View File

@ -21,6 +21,7 @@
#include <linux/interrupt.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/smc91x.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
@ -226,14 +227,6 @@ static struct pxa2xx_spi_master pxa_ssp_master_info = {
.num_chipselect = 0,
};
static struct platform_device pxa_ssp = {
.name = "pxa2xx-spi",
.id = 1,
.dev = {
.platform_data = &pxa_ssp_master_info,
},
};
static int lubbock_ads7846_pendown_state(void)
{
/* TS_BUSY is bit 8 in LUB_MISC_RD, but pendown is irq-only */
@ -292,11 +285,18 @@ static struct resource smc91x_resources[] = {
},
};
static struct smc91x_platdata lubbock_smc91x_info = {
.flags = SMC91X_USE_16BIT | SMC91X_NOWAIT | SMC91X_IO_SHIFT_2,
};
static struct platform_device smc91x_device = {
.name = "smc91x",
.id = -1,
.num_resources = ARRAY_SIZE(smc91x_resources),
.resource = smc91x_resources,
.dev = {
.platform_data = &lubbock_smc91x_info,
},
};
static struct resource flash_resources[] = {
@ -367,7 +367,6 @@ static struct platform_device *devices[] __initdata = {
&smc91x_device,
&lubbock_flash_device[0],
&lubbock_flash_device[1],
&pxa_ssp,
};
static struct pxafb_mode_info sharp_lm8v31_mode = {
@ -471,6 +470,7 @@ static void lubbock_irda_transceiver_mode(struct device *dev, int mode)
} else if (mode & IR_FIRMODE) {
LUB_MISC_WR |= 1 << 4;
}
pxa2xx_transceiver_mode(dev, mode);
local_irq_restore(flags);
}
@ -501,6 +501,7 @@ static void __init lubbock_init(void)
lubbock_flash_data[flashboot].name = "boot-rom";
(void) platform_add_devices(devices, ARRAY_SIZE(devices));
pxa2xx_set_spi_info(1, &pxa_ssp_master_info);
spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
}

View File

@ -17,17 +17,15 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/mfd/htc-egpio.h>
#include <linux/mfd/htc-pasic3.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/physmap.h>
#include <linux/pda_power.h>
#include <linux/pwm_backlight.h>
#include <asm/gpio.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@ -44,7 +42,7 @@
#include "devices.h"
#include "generic.h"
static unsigned long magician_pin_config[] = {
static unsigned long magician_pin_config[] __initdata = {
/* SDRAM and Static Memory I/O Signals */
GPIO20_nSDCS_2,
@ -134,6 +132,7 @@ static unsigned long magician_pin_config[] = {
static void magician_irda_transceiver_mode(struct device *dev, int mode)
{
gpio_set_value(GPIO83_MAGICIAN_nIR_EN, mode & IR_OFF);
pxa2xx_transceiver_mode(dev, mode);
}
static struct pxaficp_platform_data magician_ficp_info = {
@ -399,6 +398,7 @@ static struct platform_pwm_backlight_data backlight_data = {
static struct platform_device backlight = {
.name = "pwm-backlight",
.id = -1,
.dev = {
.parent = &pxa27x_device_pwm0.dev,
.platform_data = &backlight_data,
@ -511,6 +511,37 @@ static struct platform_device pasic3 = {
* External power
*/
static int power_supply_init(struct device *dev)
{
int ret;
ret = gpio_request(EGPIO_MAGICIAN_CABLE_STATE_AC, "CABLE_STATE_AC");
if (ret)
goto err_cs_ac;
ret = gpio_request(EGPIO_MAGICIAN_CABLE_STATE_USB, "CABLE_STATE_USB");
if (ret)
goto err_cs_usb;
ret = gpio_request(EGPIO_MAGICIAN_CHARGE_EN, "CHARGE_EN");
if (ret)
goto err_chg_en;
ret = gpio_request(GPIO30_MAGICIAN_nCHARGE_EN, "nCHARGE_EN");
if (!ret)
ret = gpio_direction_output(GPIO30_MAGICIAN_nCHARGE_EN, 0);
if (ret)
goto err_nchg_en;
return 0;
err_nchg_en:
gpio_free(EGPIO_MAGICIAN_CHARGE_EN);
err_chg_en:
gpio_free(EGPIO_MAGICIAN_CABLE_STATE_USB);
err_cs_usb:
gpio_free(EGPIO_MAGICIAN_CABLE_STATE_AC);
err_cs_ac:
return ret;
}
static int magician_is_ac_online(void)
{
return gpio_get_value(EGPIO_MAGICIAN_CABLE_STATE_AC);
@ -527,14 +558,24 @@ static void magician_set_charge(int flags)
gpio_set_value(EGPIO_MAGICIAN_CHARGE_EN, flags);
}
static void power_supply_exit(struct device *dev)
{
gpio_free(GPIO30_MAGICIAN_nCHARGE_EN);
gpio_free(EGPIO_MAGICIAN_CHARGE_EN);
gpio_free(EGPIO_MAGICIAN_CABLE_STATE_USB);
gpio_free(EGPIO_MAGICIAN_CABLE_STATE_AC);
}
static char *magician_supplicants[] = {
"ds2760-battery.0", "backup-battery"
};
static struct pda_power_pdata power_supply_info = {
.init = power_supply_init,
.is_ac_online = magician_is_ac_online,
.is_usb_online = magician_is_usb_online,
.set_charge = magician_set_charge,
.exit = power_supply_exit,
.supplied_to = magician_supplicants,
.num_supplicants = ARRAY_SIZE(magician_supplicants),
};

View File

@ -26,6 +26,7 @@
#include <linux/input.h>
#include <linux/gpio_keys.h>
#include <linux/pwm_backlight.h>
#include <linux/smc91x.h>
#include <asm/types.h>
#include <asm/setup.h>
@ -110,9 +111,9 @@ static unsigned long mainstone_pin_config[] = {
GPIO45_AC97_SYSCLK,
/* Keypad */
GPIO93_KP_DKIN_0 | WAKEUP_ON_LEVEL_HIGH,
GPIO94_KP_DKIN_1 | WAKEUP_ON_LEVEL_HIGH,
GPIO95_KP_DKIN_2 | WAKEUP_ON_LEVEL_HIGH,
GPIO93_KP_DKIN_0,
GPIO94_KP_DKIN_1,
GPIO95_KP_DKIN_2,
GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH,
GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH,
GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH,
@ -240,11 +241,19 @@ static struct resource smc91x_resources[] = {
}
};
static struct smc91x_platdata mainstone_smc91x_info = {
.flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT |
SMC91X_NOWAIT | SMC91X_USE_DMA,
};
static struct platform_device smc91x_device = {
.name = "smc91x",
.id = 0,
.num_resources = ARRAY_SIZE(smc91x_resources),
.resource = smc91x_resources,
.dev = {
.platform_data = &mainstone_smc91x_info,
},
};
static int mst_audio_startup(struct snd_pcm_substream *substream, void *priv)
@ -455,6 +464,7 @@ static void mainstone_irda_transceiver_mode(struct device *dev, int mode)
} else if (mode & IR_FIRMODE) {
MST_MSCWR1 |= MST_MSCWR1_IRDA_FIR;
}
pxa2xx_transceiver_mode(dev, mode);
if (mode & IR_OFF) {
MST_MSCWR1 = (MST_MSCWR1 & ~MST_MSCWR1_IRDA_MASK) | MST_MSCWR1_IRDA_OFF;
} else {
@ -513,7 +523,7 @@ static struct pxaohci_platform_data mainstone_ohci_platform_data = {
.init = mainstone_ohci_init,
};
#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULES)
#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE)
static unsigned int mainstone_matrix_keys[] = {
KEY(0, 0, KEY_A), KEY(1, 0, KEY_B), KEY(2, 0, KEY_C),
KEY(3, 0, KEY_D), KEY(4, 0, KEY_E), KEY(5, 0, KEY_F),

View File

@ -39,6 +39,28 @@ struct gpio_desc {
static struct gpio_desc gpio_desc[MFP_PIN_GPIO127 + 1];
static int __mfp_config_lpm(unsigned gpio, unsigned long lpm)
{
unsigned mask = GPIO_bit(gpio);
/* low power state */
switch (lpm) {
case MFP_LPM_DRIVE_HIGH:
PGSR(gpio) |= mask;
break;
case MFP_LPM_DRIVE_LOW:
PGSR(gpio) &= ~mask;
break;
case MFP_LPM_INPUT:
break;
default:
pr_warning("%s: invalid low power state for GPIO%d\n",
__func__, gpio);
return -EINVAL;
}
return 0;
}
static int __mfp_config_gpio(unsigned gpio, unsigned long c)
{
unsigned long gafr, mask = GPIO_bit(gpio);
@ -57,21 +79,8 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c)
else
GPDR(gpio) &= ~mask;
/* low power state */
switch (c & MFP_LPM_STATE_MASK) {
case MFP_LPM_DRIVE_HIGH:
PGSR(gpio) |= mask;
break;
case MFP_LPM_DRIVE_LOW:
PGSR(gpio) &= ~mask;
break;
case MFP_LPM_INPUT:
break;
default:
pr_warning("%s: invalid low power state for GPIO%d\n",
__func__, gpio);
if (__mfp_config_lpm(gpio, c & MFP_LPM_STATE_MASK))
return -EINVAL;
}
/* give early warning if MFP_LPM_CAN_WAKEUP is set on the
* configurations of those pins not able to wakeup
@ -91,6 +100,18 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c)
return 0;
}
static inline int __mfp_validate(int mfp)
{
int gpio = mfp_to_gpio(mfp);
if ((mfp > MFP_PIN_GPIO127) || !gpio_desc[gpio].valid) {
pr_warning("%s: GPIO%d is invalid pin\n", __func__, gpio);
return -1;
}
return gpio;
}
void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num)
{
unsigned long flags;
@ -99,13 +120,9 @@ void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num)
for (i = 0, c = mfp_cfgs; i < num; i++, c++) {
gpio = mfp_to_gpio(MFP_PIN(*c));
if (!gpio_desc[gpio].valid) {
pr_warning("%s: GPIO%d is invalid pin\n",
__func__, gpio);
gpio = __mfp_validate(MFP_PIN(*c));
if (gpio < 0)
continue;
}
local_irq_save(flags);
@ -116,6 +133,20 @@ void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num)
}
}
void pxa2xx_mfp_set_lpm(int mfp, unsigned long lpm)
{
unsigned long flags;
int gpio;
gpio = __mfp_validate(mfp);
if (gpio < 0)
return;
local_irq_save(flags);
__mfp_config_lpm(gpio, lpm);
local_irq_restore(flags);
}
int gpio_set_wake(unsigned int gpio, unsigned int on)
{
struct gpio_desc *d;

416
arch/arm/mach-pxa/palmtx.c Normal file
View File

@ -0,0 +1,416 @@
/*
* Hardware definitions for PalmTX
*
* Author: Marek Vasut <marek.vasut@gmail.com>
*
* Based on work of:
* Alex Osborne <ato@meshy.org>
* Cristiano P. <cristianop@users.sourceforge.net>
* Jan Herman <2hp@seznam.cz>
* Michal Hrusecky
*
* 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.
*
* (find more info at www.hackndev.com)
*
*/
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/pda_power.h>
#include <linux/pwm_backlight.h>
#include <linux/gpio.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/arch/audio.h>
#include <asm/arch/palmtx.h>
#include <asm/arch/mmc.h>
#include <asm/arch/pxafb.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/mfp-pxa27x.h>
#include <asm/arch/irda.h>
#include <asm/arch/pxa27x_keypad.h>
#include <asm/arch/udc.h>
#include "generic.h"
#include "devices.h"
/******************************************************************************
* Pin configuration
******************************************************************************/
static unsigned long palmtx_pin_config[] __initdata = {
/* MMC */
GPIO32_MMC_CLK,
GPIO92_MMC_DAT_0,
GPIO109_MMC_DAT_1,
GPIO110_MMC_DAT_2,
GPIO111_MMC_DAT_3,
GPIO112_MMC_CMD,
/* AC97 */
GPIO28_AC97_BITCLK,
GPIO29_AC97_SDATA_IN_0,
GPIO30_AC97_SDATA_OUT,
GPIO31_AC97_SYNC,
/* IrDA */
GPIO46_FICP_RXD,
GPIO47_FICP_TXD,
/* PWM */
GPIO16_PWM0_OUT,
/* USB */
GPIO13_GPIO,
/* PCMCIA */
GPIO48_nPOE,
GPIO49_nPWE,
GPIO50_nPIOR,
GPIO51_nPIOW,
GPIO85_nPCE_1,
GPIO54_nPCE_2,
GPIO79_PSKTSEL,
GPIO55_nPREG,
GPIO56_nPWAIT,
GPIO57_nIOIS16,
};
/******************************************************************************
* SD/MMC card controller
******************************************************************************/
static int palmtx_mci_init(struct device *dev, irq_handler_t palmtx_detect_int,
void *data)
{
int err = 0;
/* Setup an interrupt for detecting card insert/remove events */
err = request_irq(IRQ_GPIO_PALMTX_SD_DETECT_N, palmtx_detect_int,
IRQF_DISABLED | IRQF_SAMPLE_RANDOM |
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
"SD/MMC card detect", data);
if (err) {
printk(KERN_ERR "%s: cannot request SD/MMC card detect IRQ\n",
__func__);
return err;
}
err = gpio_request(GPIO_NR_PALMTX_SD_POWER, "SD_POWER");
if (err)
goto pwr_err;
err = gpio_request(GPIO_NR_PALMTX_SD_READONLY, "SD_READONLY");
if (err)
goto ro_err;
printk(KERN_DEBUG "%s: irq registered\n", __func__);
return 0;
ro_err:
gpio_free(GPIO_NR_PALMTX_SD_POWER);
pwr_err:
free_irq(IRQ_GPIO_PALMTX_SD_DETECT_N, data);
return err;
}
static void palmtx_mci_exit(struct device *dev, void *data)
{
gpio_free(GPIO_NR_PALMTX_SD_READONLY);
gpio_free(GPIO_NR_PALMTX_SD_POWER);
free_irq(IRQ_GPIO_PALMTX_SD_DETECT_N, data);
}
static void palmtx_mci_power(struct device *dev, unsigned int vdd)
{
struct pxamci_platform_data *p_d = dev->platform_data;
gpio_set_value(GPIO_NR_PALMTX_SD_POWER, p_d->ocr_mask & (1 << vdd));
}
static int palmtx_mci_get_ro(struct device *dev)
{
return gpio_get_value(GPIO_NR_PALMTX_SD_READONLY);
}
static struct pxamci_platform_data palmtx_mci_platform_data = {
.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
.setpower = palmtx_mci_power,
.get_ro = palmtx_mci_get_ro,
.init = palmtx_mci_init,
.exit = palmtx_mci_exit,
};
/******************************************************************************
* GPIO keyboard
******************************************************************************/
static unsigned int palmtx_matrix_keys[] = {
KEY(0, 0, KEY_POWER),
KEY(0, 1, KEY_F1),
KEY(0, 2, KEY_ENTER),
KEY(1, 0, KEY_F2),
KEY(1, 1, KEY_F3),
KEY(1, 2, KEY_F4),
KEY(2, 0, KEY_UP),
KEY(2, 2, KEY_DOWN),
KEY(3, 0, KEY_RIGHT),
KEY(3, 2, KEY_LEFT),
};
static struct pxa27x_keypad_platform_data palmtx_keypad_platform_data = {
.matrix_key_rows = 4,
.matrix_key_cols = 3,
.matrix_key_map = palmtx_matrix_keys,
.matrix_key_map_size = ARRAY_SIZE(palmtx_matrix_keys),
.debounce_interval = 30,
};
/******************************************************************************
* GPIO keys
******************************************************************************/
static struct gpio_keys_button palmtx_pxa_buttons[] = {
{KEY_F8, GPIO_NR_PALMTX_HOTSYNC_BUTTON_N, 1, "HotSync Button" },
};
static struct gpio_keys_platform_data palmtx_pxa_keys_data = {
.buttons = palmtx_pxa_buttons,
.nbuttons = ARRAY_SIZE(palmtx_pxa_buttons),
};
static struct platform_device palmtx_pxa_keys = {
.name = "gpio-keys",
.id = -1,
.dev = {
.platform_data = &palmtx_pxa_keys_data,
},
};
/******************************************************************************
* Backlight
******************************************************************************/
static int palmtx_backlight_init(struct device *dev)
{
int ret;
ret = gpio_request(GPIO_NR_PALMTX_BL_POWER, "BL POWER");
if (ret)
goto err;
ret = gpio_request(GPIO_NR_PALMTX_LCD_POWER, "LCD POWER");
if (ret)
goto err2;
return 0;
err2:
gpio_free(GPIO_NR_PALMTX_BL_POWER);
err:
return ret;
}
static int palmtx_backlight_notify(int brightness)
{
gpio_set_value(GPIO_NR_PALMTX_BL_POWER, brightness);
gpio_set_value(GPIO_NR_PALMTX_LCD_POWER, brightness);
return brightness;
}
static void palmtx_backlight_exit(struct device *dev)
{
gpio_free(GPIO_NR_PALMTX_BL_POWER);
gpio_free(GPIO_NR_PALMTX_LCD_POWER);
}
static struct platform_pwm_backlight_data palmtx_backlight_data = {
.pwm_id = 0,
.max_brightness = PALMTX_MAX_INTENSITY,
.dft_brightness = PALMTX_MAX_INTENSITY,
.pwm_period_ns = PALMTX_PERIOD_NS,
.init = palmtx_backlight_init,
.notify = palmtx_backlight_notify,
.exit = palmtx_backlight_exit,
};
static struct platform_device palmtx_backlight = {
.name = "pwm-backlight",
.dev = {
.parent = &pxa27x_device_pwm0.dev,
.platform_data = &palmtx_backlight_data,
},
};
/******************************************************************************
* IrDA
******************************************************************************/
static void palmtx_irda_transceiver_mode(struct device *dev, int mode)
{
gpio_set_value(GPIO_NR_PALMTX_IR_DISABLE, mode & IR_OFF);
pxa2xx_transceiver_mode(dev, mode);
}
static struct pxaficp_platform_data palmtx_ficp_platform_data = {
.transceiver_cap = IR_SIRMODE | IR_FIRMODE | IR_OFF,
.transceiver_mode = palmtx_irda_transceiver_mode,
};
/******************************************************************************
* UDC
******************************************************************************/
static void palmtx_udc_command(int cmd)
{
gpio_set_value(GPIO_NR_PALMTX_USB_POWER, !cmd);
udelay(50);
gpio_set_value(GPIO_NR_PALMTX_USB_PULLUP, !cmd);
}
static struct pxa2xx_udc_mach_info palmtx_udc_info __initdata = {
.gpio_vbus = GPIO_NR_PALMTX_USB_DETECT_N,
.gpio_vbus_inverted = 1,
.udc_command = palmtx_udc_command,
};
/******************************************************************************
* Power supply
******************************************************************************/
static int power_supply_init(struct device *dev)
{
int ret;
ret = gpio_request(GPIO_NR_PALMTX_POWER_DETECT, "CABLE_STATE_AC");
if (ret)
goto err_cs_ac;
ret = gpio_request(GPIO_NR_PALMTX_USB_DETECT_N, "CABLE_STATE_USB");
if (ret)
goto err_cs_usb;
return 0;
err_cs_usb:
gpio_free(GPIO_NR_PALMTX_POWER_DETECT);
err_cs_ac:
return ret;
}
static int palmtx_is_ac_online(void)
{
return gpio_get_value(GPIO_NR_PALMTX_POWER_DETECT);
}
static int palmtx_is_usb_online(void)
{
return !gpio_get_value(GPIO_NR_PALMTX_USB_DETECT_N);
}
static void power_supply_exit(struct device *dev)
{
gpio_free(GPIO_NR_PALMTX_USB_DETECT_N);
gpio_free(GPIO_NR_PALMTX_POWER_DETECT);
}
static char *palmtx_supplicants[] = {
"main-battery",
};
static struct pda_power_pdata power_supply_info = {
.init = power_supply_init,
.is_ac_online = palmtx_is_ac_online,
.is_usb_online = palmtx_is_usb_online,
.exit = power_supply_exit,
.supplied_to = palmtx_supplicants,
.num_supplicants = ARRAY_SIZE(palmtx_supplicants),
};
static struct platform_device power_supply = {
.name = "pda-power",
.id = -1,
.dev = {
.platform_data = &power_supply_info,
},
};
/******************************************************************************
* Framebuffer
******************************************************************************/
static struct pxafb_mode_info palmtx_lcd_modes[] = {
{
.pixclock = 57692,
.xres = 320,
.yres = 480,
.bpp = 16,
.left_margin = 32,
.right_margin = 1,
.upper_margin = 7,
.lower_margin = 1,
.hsync_len = 4,
.vsync_len = 1,
},
};
static struct pxafb_mach_info palmtx_lcd_screen = {
.modes = palmtx_lcd_modes,
.num_modes = ARRAY_SIZE(palmtx_lcd_modes),
.lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
};
/******************************************************************************
* Machine init
******************************************************************************/
static struct platform_device *devices[] __initdata = {
#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
&palmtx_pxa_keys,
#endif
&palmtx_backlight,
&power_supply,
};
static struct map_desc palmtx_io_desc[] __initdata = {
{
.virtual = PALMTX_PCMCIA_VIRT,
.pfn = __phys_to_pfn(PALMTX_PCMCIA_PHYS),
.length = PALMTX_PCMCIA_SIZE,
.type = MT_DEVICE
},
};
static void __init palmtx_map_io(void)
{
pxa_map_io();
iotable_init(palmtx_io_desc, ARRAY_SIZE(palmtx_io_desc));
}
static void __init palmtx_init(void)
{
pxa2xx_mfp_config(ARRAY_AND_SIZE(palmtx_pin_config));
set_pxa_fb_info(&palmtx_lcd_screen);
pxa_set_mci_info(&palmtx_mci_platform_data);
pxa_set_udc_info(&palmtx_udc_info);
pxa_set_ac97_info(NULL);
pxa_set_ficp_info(&palmtx_ficp_platform_data);
pxa_set_keypad_info(&palmtx_keypad_platform_data);
platform_add_devices(devices, ARRAY_SIZE(devices));
}
MACHINE_START(PALMTX, "Palm T|X")
.phys_io = PALMTX_PHYS_IO_START,
.io_pg_offst = io_p2v(0x40000000),
.boot_params = 0xa0000100,
.map_io = palmtx_map_io,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
.init_machine = palmtx_init
MACHINE_END

View File

@ -24,7 +24,9 @@
#include <linux/platform_device.h>
#include <linux/mtd/physmap.h>
#include <linux/spi/spi.h>
#include <linux/spi/max7301.h>
#include <linux/leds.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/arch/hardware.h>
@ -108,6 +110,32 @@ static struct platform_device smc91x_device = {
.resource = smc91x_resources,
};
/*
* SPI host and devices
*/
static struct pxa2xx_spi_master pxa_ssp_master_info = {
.num_chipselect = 1,
};
static struct max7301_platform_data max7301_info = {
.base = -1,
};
/* bus_num must match id in pxa2xx_set_spi_info() call */
static struct spi_board_info spi_board_info[] __initdata = {
{
.modalias = "max7301",
.platform_data = &max7301_info,
.max_speed_hz = 13000000,
.bus_num = 1,
.chip_select = 0,
.mode = SPI_MODE_0,
},
};
/*
* NOR flash
*/
static struct physmap_flash_data pcm027_flash_data = {
.width = 4,
};
@ -190,6 +218,9 @@ static void __init pcm027_init(void)
#ifdef CONFIG_MACH_PCM990_BASEBOARD
pcm990_baseboard_init();
#endif
pxa2xx_set_spi_info(1, &pxa_ssp_master_info);
spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
}
static void __init pcm027_map_io(void)

View File

@ -33,14 +33,30 @@
#include <asm/arch/camera.h>
#include <asm/mach/map.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/pxa2xx-gpio.h>
#include <asm/arch/audio.h>
#include <asm/arch/mmc.h>
#include <asm/arch/ohci.h>
#include <asm/arch/pcm990_baseboard.h>
#include <asm/arch/pxafb.h>
#include <asm/arch/mfp-pxa27x.h>
#include "devices.h"
#include "generic.h"
static unsigned long pcm990_pin_config[] __initdata = {
/* MMC */
GPIO32_MMC_CLK,
GPIO112_MMC_CMD,
GPIO92_MMC_DAT_0,
GPIO109_MMC_DAT_1,
GPIO110_MMC_DAT_2,
GPIO111_MMC_DAT_3,
/* USB */
GPIO88_USBH1_PWR,
GPIO89_USBH1_PEN,
/* PWM0 */
GPIO16_PWM0_OUT,
};
/*
* pcm990_lcd_power - control power supply to the LCD
@ -277,16 +293,6 @@ static int pcm990_mci_init(struct device *dev, irq_handler_t mci_detect_int,
{
int err;
/*
* enable GPIO for PXA27x MMC controller
*/
pxa_gpio_mode(GPIO32_MMCCLK_MD);
pxa_gpio_mode(GPIO112_MMCCMD_MD);
pxa_gpio_mode(GPIO92_MMCDAT0_MD);
pxa_gpio_mode(GPIO109_MMCDAT1_MD);
pxa_gpio_mode(GPIO110_MMCDAT2_MD);
pxa_gpio_mode(GPIO111_MMCDAT3_MD);
err = request_irq(PCM027_MMCDET_IRQ, mci_detect_int, IRQF_DISABLED,
"MMC card detect", data);
if (err)
@ -333,8 +339,6 @@ static struct pxamci_platform_data pcm990_mci_platform_data = {
*/
static int pcm990_ohci_init(struct device *dev)
{
pxa_gpio_mode(PCM990_USB_OVERCURRENT);
pxa_gpio_mode(PCM990_USB_PWR_EN);
/*
* disable USB port 2 and 3
* power sense is active low
@ -361,23 +365,27 @@ static struct pxaohci_platform_data pcm990_ohci_platform_data = {
* PXA27x Camera specific stuff
*/
#if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE)
static unsigned long pcm990_camera_pin_config[] = {
/* CIF */
GPIO98_CIF_DD_0,
GPIO105_CIF_DD_1,
GPIO104_CIF_DD_2,
GPIO103_CIF_DD_3,
GPIO95_CIF_DD_4,
GPIO94_CIF_DD_5,
GPIO93_CIF_DD_6,
GPIO108_CIF_DD_7,
GPIO107_CIF_DD_8,
GPIO106_CIF_DD_9,
GPIO42_CIF_MCLK,
GPIO45_CIF_PCLK,
GPIO43_CIF_FV,
GPIO44_CIF_LV,
};
static int pcm990_pxacamera_init(struct device *dev)
{
pxa_gpio_mode(GPIO98_CIF_DD_0_MD);
pxa_gpio_mode(GPIO105_CIF_DD_1_MD);
pxa_gpio_mode(GPIO104_CIF_DD_2_MD);
pxa_gpio_mode(GPIO103_CIF_DD_3_MD);
pxa_gpio_mode(GPIO95_CIF_DD_4_MD);
pxa_gpio_mode(GPIO94_CIF_DD_5_MD);
pxa_gpio_mode(GPIO93_CIF_DD_6_MD);
pxa_gpio_mode(GPIO108_CIF_DD_7_MD);
pxa_gpio_mode(GPIO107_CIF_DD_8_MD);
pxa_gpio_mode(GPIO106_CIF_DD_9_MD);
pxa_gpio_mode(GPIO42_CIF_MCLK_MD);
pxa_gpio_mode(GPIO45_CIF_PCLK_MD);
pxa_gpio_mode(GPIO43_CIF_FV_MD);
pxa_gpio_mode(GPIO44_CIF_LV_MD);
pxa2xx_mfp_config(ARRAY_AND_SIZE(pcm990_camera_pin_config));
return 0;
}
@ -449,8 +457,10 @@ static struct map_desc pcm990_io_desc[] __initdata = {
*/
void __init pcm990_baseboard_init(void)
{
pxa2xx_mfp_config(ARRAY_AND_SIZE(pcm990_pin_config));
/* register CPLD access */
iotable_init(pcm990_io_desc, ARRAY_SIZE(pcm990_io_desc));
iotable_init(ARRAY_AND_SIZE(pcm990_io_desc));
/* register CPLD's IRQ controller */
pcm990_init_irq();
@ -458,7 +468,6 @@ void __init pcm990_baseboard_init(void)
#ifndef CONFIG_PCM990_DISPLAY_NONE
set_pxa_fb_info(&pcm990_fbinfo);
#endif
pxa_gpio_mode(GPIO16_PWM0_MD);
platform_device_register(&pcm990_backlight_device);
/* MMC */
@ -473,9 +482,8 @@ void __init pcm990_baseboard_init(void)
#if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE)
pxa_set_camera_info(&pcm990_pxacamera_platform_data);
i2c_register_board_info(0, pcm990_i2c_devices,
ARRAY_SIZE(pcm990_i2c_devices));
i2c_register_board_info(0, ARRAY_AND_SIZE(pcm990_i2c_devices));
#endif
printk(KERN_INFO"PCM-990 Evaluation baseboard initialized\n");
printk(KERN_INFO "PCM-990 Evaluation baseboard initialized\n");
}

View File

@ -267,6 +267,7 @@ static void poodle_irda_transceiver_mode(struct device *dev, int mode)
} else {
GPCR(POODLE_GPIO_IR_ON) = GPIO_bit(POODLE_GPIO_IR_ON);
}
pxa2xx_transceiver_mode(dev, mode);
}
static struct pxaficp_platform_data poodle_ficp_platform_data = {

View File

@ -109,6 +109,52 @@ static const struct clkops clk_pxa25x_lcd_ops = {
.getrate = clk_pxa25x_lcd_getrate,
};
static unsigned long gpio12_config_32k[] = {
GPIO12_32KHz,
};
static unsigned long gpio12_config_gpio[] = {
GPIO12_GPIO,
};
static void clk_gpio12_enable(struct clk *clk)
{
pxa2xx_mfp_config(gpio12_config_32k, 1);
}
static void clk_gpio12_disable(struct clk *clk)
{
pxa2xx_mfp_config(gpio12_config_gpio, 1);
}
static const struct clkops clk_pxa25x_gpio12_ops = {
.enable = clk_gpio12_enable,
.disable = clk_gpio12_disable,
};
static unsigned long gpio11_config_3m6[] = {
GPIO11_3_6MHz,
};
static unsigned long gpio11_config_gpio[] = {
GPIO11_GPIO,
};
static void clk_gpio11_enable(struct clk *clk)
{
pxa2xx_mfp_config(gpio11_config_3m6, 1);
}
static void clk_gpio11_disable(struct clk *clk)
{
pxa2xx_mfp_config(gpio11_config_gpio, 1);
}
static const struct clkops clk_pxa25x_gpio11_ops = {
.enable = clk_gpio11_enable,
.disable = clk_gpio11_disable,
};
/*
* 3.6864MHz -> OST, GPIO, SSP, PWM, PLLs (95.842MHz, 147.456MHz)
* 95.842MHz -> MMC 19.169MHz, I2C 31.949MHz, FICP 47.923MHz, USB 47.923MHz
@ -128,6 +174,8 @@ static struct clk pxa25x_clks[] = {
INIT_CKEN("UARTCLK", BTUART, 14745600, 1, &pxa_device_btuart.dev),
INIT_CKEN("UARTCLK", STUART, 14745600, 1, NULL),
INIT_CKEN("UDCCLK", USB, 47923000, 5, &pxa25x_device_udc.dev),
INIT_CLK("GPIO11_CLK", &clk_pxa25x_gpio11_ops, 3686400, 0, NULL),
INIT_CLK("GPIO12_CLK", &clk_pxa25x_gpio12_ops, 32768, 0, NULL),
INIT_CKEN("MMCCLK", MMC, 19169000, 0, &pxa_device_mci.dev),
INIT_CKEN("I2CCLK", I2C, 31949000, 0, &pxa_device_i2c.dev),
@ -145,7 +193,10 @@ static struct clk pxa25x_clks[] = {
INIT_CKEN("FICPCLK", FICP, 47923000, 0, NULL),
};
static struct clk gpio7_clk = INIT_CKOTHER("GPIO7_CK", &pxa25x_clks[4], NULL);
static struct clk pxa2xx_clk_aliases[] = {
INIT_CKOTHER("GPIO7_CLK", &pxa25x_clks[4], NULL),
INIT_CKOTHER("SA1111_CLK", &pxa25x_clks[5], NULL),
};
#ifdef CONFIG_PM
@ -293,7 +344,7 @@ static int __init pxa25x_init(void)
int i, ret = 0;
/* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
if (cpu_is_pxa25x())
if (cpu_is_pxa255())
clks_register(&pxa25x_hwuart_clk, 1);
if (cpu_is_pxa21x() || cpu_is_pxa25x()) {
@ -317,10 +368,10 @@ static int __init pxa25x_init(void)
}
/* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
if (cpu_is_pxa25x())
if (cpu_is_pxa255())
ret = platform_device_register(&pxa_device_hwuart);
clks_register(&gpio7_clk, 1);
clks_register(pxa2xx_clk_aliases, ARRAY_SIZE(pxa2xx_clk_aliases));
return ret;
}

View File

@ -15,10 +15,16 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <asm/hardware.h>
#include <asm/arch/pxa3xx-regs.h>
#include <asm/arch/mfp-pxa300.h>
#include "generic.h"
#include "devices.h"
#include "clock.h"
static struct pxa3xx_mfp_addr_map pxa300_mfp_addr_map[] __initdata = {
MFP_ADDR_X(GPIO0, GPIO2, 0x00b4),
@ -79,15 +85,26 @@ static struct pxa3xx_mfp_addr_map pxa310_mfp_addr_map[] __initdata = {
MFP_ADDR_END,
};
static struct clk common_clks[] = {
PXA3xx_CKEN("NANDCLK", NAND, 156000000, 0, &pxa3xx_device_nand.dev),
};
static struct clk pxa310_clks[] = {
PXA3xx_CKEN("MMCCLK", MMC3, 19500000, 0, &pxa3xx_device_mci3.dev),
};
static int __init pxa300_init(void)
{
if (cpu_is_pxa300() || cpu_is_pxa310()) {
pxa3xx_init_mfp();
pxa3xx_mfp_init_addr(pxa300_mfp_addr_map);
clks_register(ARRAY_AND_SIZE(common_clks));
}
if (cpu_is_pxa310())
if (cpu_is_pxa310()) {
pxa3xx_mfp_init_addr(pxa310_mfp_addr_map);
clks_register(ARRAY_AND_SIZE(pxa310_clks));
}
return 0;
}

View File

@ -15,11 +15,17 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <asm/hardware.h>
#include <asm/arch/mfp.h>
#include <asm/arch/pxa3xx-regs.h>
#include <asm/arch/mfp-pxa320.h>
#include "generic.h"
#include "devices.h"
#include "clock.h"
static struct pxa3xx_mfp_addr_map pxa320_mfp_addr_map[] __initdata = {
MFP_ADDR_X(GPIO0, GPIO4, 0x0124),
@ -74,16 +80,17 @@ static struct pxa3xx_mfp_addr_map pxa320_mfp_addr_map[] __initdata = {
MFP_ADDR_END,
};
static void __init pxa320_init_mfp(void)
{
pxa3xx_init_mfp();
pxa3xx_mfp_init_addr(pxa320_mfp_addr_map);
}
static struct clk pxa320_clks[] = {
PXA3xx_CKEN("NANDCLK", NAND, 104000000, 0, &pxa3xx_device_nand.dev),
};
static int __init pxa320_init(void)
{
if (cpu_is_pxa320())
pxa320_init_mfp();
if (cpu_is_pxa320()) {
pxa3xx_init_mfp();
pxa3xx_mfp_init_addr(pxa320_mfp_addr_map);
clks_register(ARRAY_AND_SIZE(pxa320_clks));
}
return 0;
}

View File

@ -144,7 +144,7 @@ static unsigned long clk_pxa3xx_hsio_getrate(struct clk *clk)
return hsio_clk;
}
static void clk_pxa3xx_cken_enable(struct clk *clk)
void clk_pxa3xx_cken_enable(struct clk *clk)
{
unsigned long mask = 1ul << (clk->cken & 0x1f);
@ -154,7 +154,7 @@ static void clk_pxa3xx_cken_enable(struct clk *clk)
CKENB |= mask;
}
static void clk_pxa3xx_cken_disable(struct clk *clk)
void clk_pxa3xx_cken_disable(struct clk *clk)
{
unsigned long mask = 1ul << (clk->cken & 0x1f);
@ -164,7 +164,7 @@ static void clk_pxa3xx_cken_disable(struct clk *clk)
CKENB &= ~mask;
}
static const struct clkops clk_pxa3xx_cken_ops = {
const struct clkops clk_pxa3xx_cken_ops = {
.enable = clk_pxa3xx_cken_enable,
.disable = clk_pxa3xx_cken_disable,
};
@ -196,24 +196,6 @@ static const struct clkops clk_pout_ops = {
.disable = clk_pout_disable,
};
#define PXA3xx_CKEN(_name, _cken, _rate, _delay, _dev) \
{ \
.name = _name, \
.dev = _dev, \
.ops = &clk_pxa3xx_cken_ops, \
.rate = _rate, \
.cken = CKEN_##_cken, \
.delay = _delay, \
}
#define PXA3xx_CK(_name, _cken, _ops, _dev) \
{ \
.name = _name, \
.dev = _dev, \
.ops = _ops, \
.cken = CKEN_##_cken, \
}
static struct clk pxa3xx_clks[] = {
{
.name = "CLK_POUT",
@ -244,7 +226,6 @@ static struct clk pxa3xx_clks[] = {
PXA3xx_CKEN("MMCCLK", MMC1, 19500000, 0, &pxa_device_mci.dev),
PXA3xx_CKEN("MMCCLK", MMC2, 19500000, 0, &pxa3xx_device_mci2.dev),
PXA3xx_CKEN("MMCCLK", MMC3, 19500000, 0, &pxa3xx_device_mci3.dev),
};
#ifdef CONFIG_PM

190
arch/arm/mach-pxa/pxa930.c Normal file
View File

@ -0,0 +1,190 @@
/*
* linux/arch/arm/mach-pxa/pxa930.c
*
* Code specific to PXA930
*
* Copyright (C) 2007-2008 Marvell Internation Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <linux/dma-mapping.h>
#include <asm/hardware.h>
#include <asm/arch/mfp-pxa930.h>
static struct pxa3xx_mfp_addr_map pxa930_mfp_addr_map[] __initdata = {
MFP_ADDR(GPIO0, 0x02e0),
MFP_ADDR(GPIO1, 0x02dc),
MFP_ADDR(GPIO2, 0x02e8),
MFP_ADDR(GPIO3, 0x02d8),
MFP_ADDR(GPIO4, 0x02e4),
MFP_ADDR(GPIO5, 0x02ec),
MFP_ADDR(GPIO6, 0x02f8),
MFP_ADDR(GPIO7, 0x02fc),
MFP_ADDR(GPIO8, 0x0300),
MFP_ADDR(GPIO9, 0x02d4),
MFP_ADDR(GPIO10, 0x02f4),
MFP_ADDR(GPIO11, 0x02f0),
MFP_ADDR(GPIO12, 0x0304),
MFP_ADDR(GPIO13, 0x0310),
MFP_ADDR(GPIO14, 0x0308),
MFP_ADDR(GPIO15, 0x030c),
MFP_ADDR(GPIO16, 0x04e8),
MFP_ADDR(GPIO17, 0x04f4),
MFP_ADDR(GPIO18, 0x04f8),
MFP_ADDR(GPIO19, 0x04fc),
MFP_ADDR(GPIO20, 0x0518),
MFP_ADDR(GPIO21, 0x051c),
MFP_ADDR(GPIO22, 0x04ec),
MFP_ADDR(GPIO23, 0x0500),
MFP_ADDR(GPIO24, 0x04f0),
MFP_ADDR(GPIO25, 0x0504),
MFP_ADDR(GPIO26, 0x0510),
MFP_ADDR(GPIO27, 0x0514),
MFP_ADDR(GPIO28, 0x0520),
MFP_ADDR(GPIO29, 0x0600),
MFP_ADDR(GPIO30, 0x0618),
MFP_ADDR(GPIO31, 0x0610),
MFP_ADDR(GPIO32, 0x060c),
MFP_ADDR(GPIO33, 0x061c),
MFP_ADDR(GPIO34, 0x0620),
MFP_ADDR(GPIO35, 0x0628),
MFP_ADDR(GPIO36, 0x062c),
MFP_ADDR(GPIO37, 0x0630),
MFP_ADDR(GPIO38, 0x0634),
MFP_ADDR(GPIO39, 0x0638),
MFP_ADDR(GPIO40, 0x063c),
MFP_ADDR(GPIO41, 0x0614),
MFP_ADDR(GPIO42, 0x0624),
MFP_ADDR(GPIO43, 0x0608),
MFP_ADDR(GPIO44, 0x0604),
MFP_ADDR(GPIO45, 0x050c),
MFP_ADDR(GPIO46, 0x0508),
MFP_ADDR(GPIO47, 0x02bc),
MFP_ADDR(GPIO48, 0x02b4),
MFP_ADDR(GPIO49, 0x02b8),
MFP_ADDR(GPIO50, 0x02c8),
MFP_ADDR(GPIO51, 0x02c0),
MFP_ADDR(GPIO52, 0x02c4),
MFP_ADDR(GPIO53, 0x02d0),
MFP_ADDR(GPIO54, 0x02cc),
MFP_ADDR(GPIO55, 0x029c),
MFP_ADDR(GPIO56, 0x02a0),
MFP_ADDR(GPIO57, 0x0294),
MFP_ADDR(GPIO58, 0x0298),
MFP_ADDR(GPIO59, 0x02a4),
MFP_ADDR(GPIO60, 0x02a8),
MFP_ADDR(GPIO61, 0x02b0),
MFP_ADDR(GPIO62, 0x02ac),
MFP_ADDR(GPIO63, 0x0640),
MFP_ADDR(GPIO64, 0x065c),
MFP_ADDR(GPIO65, 0x0648),
MFP_ADDR(GPIO66, 0x0644),
MFP_ADDR(GPIO67, 0x0674),
MFP_ADDR(GPIO68, 0x0658),
MFP_ADDR(GPIO69, 0x0654),
MFP_ADDR(GPIO70, 0x0660),
MFP_ADDR(GPIO71, 0x0668),
MFP_ADDR(GPIO72, 0x0664),
MFP_ADDR(GPIO73, 0x0650),
MFP_ADDR(GPIO74, 0x066c),
MFP_ADDR(GPIO75, 0x064c),
MFP_ADDR(GPIO76, 0x0670),
MFP_ADDR(GPIO77, 0x0678),
MFP_ADDR(GPIO78, 0x067c),
MFP_ADDR(GPIO79, 0x0694),
MFP_ADDR(GPIO80, 0x069c),
MFP_ADDR(GPIO81, 0x06a0),
MFP_ADDR(GPIO82, 0x06a4),
MFP_ADDR(GPIO83, 0x0698),
MFP_ADDR(GPIO84, 0x06bc),
MFP_ADDR(GPIO85, 0x06b4),
MFP_ADDR(GPIO86, 0x06b0),
MFP_ADDR(GPIO87, 0x06c0),
MFP_ADDR(GPIO88, 0x06c4),
MFP_ADDR(GPIO89, 0x06ac),
MFP_ADDR(GPIO90, 0x0680),
MFP_ADDR(GPIO91, 0x0684),
MFP_ADDR(GPIO92, 0x0688),
MFP_ADDR(GPIO93, 0x0690),
MFP_ADDR(GPIO94, 0x068c),
MFP_ADDR(GPIO95, 0x06a8),
MFP_ADDR(GPIO96, 0x06b8),
MFP_ADDR(GPIO97, 0x0410),
MFP_ADDR(GPIO98, 0x0418),
MFP_ADDR(GPIO99, 0x041c),
MFP_ADDR(GPIO100, 0x0414),
MFP_ADDR(GPIO101, 0x0408),
MFP_ADDR(GPIO102, 0x0324),
MFP_ADDR(GPIO103, 0x040c),
MFP_ADDR(GPIO104, 0x0400),
MFP_ADDR(GPIO105, 0x0328),
MFP_ADDR(GPIO106, 0x0404),
MFP_ADDR(nXCVREN, 0x0204),
MFP_ADDR(DF_CLE_nOE, 0x020c),
MFP_ADDR(DF_nADV1_ALE, 0x0218),
MFP_ADDR(DF_SCLK_E, 0x0214),
MFP_ADDR(DF_SCLK_S, 0x0210),
MFP_ADDR(nBE0, 0x021c),
MFP_ADDR(nBE1, 0x0220),
MFP_ADDR(DF_nADV2_ALE, 0x0224),
MFP_ADDR(DF_INT_RnB, 0x0228),
MFP_ADDR(DF_nCS0, 0x022c),
MFP_ADDR(DF_nCS1, 0x0230),
MFP_ADDR(nLUA, 0x0254),
MFP_ADDR(nLLA, 0x0258),
MFP_ADDR(DF_nWE, 0x0234),
MFP_ADDR(DF_nRE_nOE, 0x0238),
MFP_ADDR(DF_ADDR0, 0x024c),
MFP_ADDR(DF_ADDR1, 0x0250),
MFP_ADDR(DF_ADDR2, 0x025c),
MFP_ADDR(DF_ADDR3, 0x0260),
MFP_ADDR(DF_IO0, 0x023c),
MFP_ADDR(DF_IO1, 0x0240),
MFP_ADDR(DF_IO2, 0x0244),
MFP_ADDR(DF_IO3, 0x0248),
MFP_ADDR(DF_IO4, 0x0264),
MFP_ADDR(DF_IO5, 0x0268),
MFP_ADDR(DF_IO6, 0x026c),
MFP_ADDR(DF_IO7, 0x0270),
MFP_ADDR(DF_IO8, 0x0274),
MFP_ADDR(DF_IO9, 0x0278),
MFP_ADDR(DF_IO10, 0x027c),
MFP_ADDR(DF_IO11, 0x0280),
MFP_ADDR(DF_IO12, 0x0284),
MFP_ADDR(DF_IO13, 0x0288),
MFP_ADDR(DF_IO14, 0x028c),
MFP_ADDR(DF_IO15, 0x0290),
MFP_ADDR(GSIM_UIO, 0x0314),
MFP_ADDR(GSIM_UCLK, 0x0318),
MFP_ADDR(GSIM_UDET, 0x031c),
MFP_ADDR(GSIM_nURST, 0x0320),
MFP_ADDR(PMIC_INT, 0x06c8),
MFP_ADDR(RDY, 0x0200),
MFP_ADDR_END,
};
static int __init pxa930_init(void)
{
if (cpu_is_pxa930()) {
pxa3xx_init_mfp();
pxa3xx_mfp_init_addr(pxa930_mfp_addr_map);
}
return 0;
}
core_initcall(pxa930_init);

96
arch/arm/mach-pxa/reset.c Normal file
View File

@ -0,0 +1,96 @@
/*
* 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/module.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <asm/io.h>
#include <asm/proc-fns.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/pxa2xx-regs.h>
static void do_hw_reset(void);
static int reset_gpio = -1;
int init_gpio_reset(int gpio)
{
int rc;
rc = gpio_request(gpio, "reset generator");
if (rc) {
printk(KERN_ERR "Can't request reset_gpio\n");
goto out;
}
rc = gpio_direction_input(gpio);
if (rc) {
printk(KERN_ERR "Can't configure reset_gpio for input\n");
gpio_free(gpio);
goto out;
}
out:
if (!rc)
reset_gpio = gpio;
return rc;
}
/*
* Trigger GPIO reset.
* This covers various types of logic connecting gpio pin
* to RESET pins (nRESET or GPIO_RESET):
*/
static void do_gpio_reset(void)
{
BUG_ON(reset_gpio == -1);
/* drive it low */
gpio_direction_output(reset_gpio, 0);
mdelay(2);
/* rising edge or drive high */
gpio_set_value(reset_gpio, 1);
mdelay(2);
/* falling edge */
gpio_set_value(reset_gpio, 0);
/* give it some time */
mdelay(10);
WARN_ON(1);
/* fallback */
do_hw_reset();
}
static void do_hw_reset(void)
{
/* Initialize the watchdog and let it fire */
OWER = OWER_WME;
OSSR = OSSR_M3;
OSMR3 = OSCR + 368640; /* ... in 100 ms */
}
void arch_reset(char mode)
{
if (cpu_is_pxa2xx())
RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
switch (mode) {
case 's':
/* Jump into ROM at address 0 */
cpu_reset(0);
break;
case 'h':
do_hw_reset();
break;
case 'g':
do_gpio_reset();
break;
}
}

84
arch/arm/mach-pxa/saar.c Normal file
View File

@ -0,0 +1,84 @@
/*
* linux/arch/arm/mach-pxa/saar.c
*
* Support for the Marvell PXA930 Handheld Platform (aka SAAR)
*
* Copyright (C) 2007-2008 Marvell International Ltd.
*
* 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
* publishhed by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/smc91x.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/hardware.h>
#include <asm/arch/pxa3xx-regs.h>
#include <asm/arch/mfp-pxa930.h>
#include "devices.h"
#include "generic.h"
/* SAAR MFP configurations */
static mfp_cfg_t saar_mfp_cfg[] __initdata = {
/* Ethernet */
DF_nCS1_nCS3,
GPIO97_GPIO,
};
#define SAAR_ETH_PHYS (0x14000000)
static struct resource smc91x_resources[] = {
[0] = {
.start = (SAAR_ETH_PHYS + 0x300),
.end = (SAAR_ETH_PHYS + 0xfffff),
.flags = IORESOURCE_MEM,
},
[1] = {
.start = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO97)),
.end = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO97)),
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
}
};
static struct smc91x_platdata saar_smc91x_info = {
.flags = SMC91X_USE_16BIT | SMC91X_NOWAIT | SMC91X_USE_DMA,
};
static struct platform_device smc91x_device = {
.name = "smc91x",
.id = 0,
.num_resources = ARRAY_SIZE(smc91x_resources),
.resource = smc91x_resources,
.dev = {
.platform_data = &saar_smc91x_info,
},
};
static void __init saar_init(void)
{
/* initialize MFP configurations */
pxa3xx_mfp_config(ARRAY_AND_SIZE(saar_mfp_cfg));
platform_device_register(&smc91x_device);
}
MACHINE_START(SAAR, "PXA930 Handheld Platform (aka SAAR)")
/* Maintainer: Eric Miao <eric.miao@marvell.com> */
.phys_io = 0x40000000,
.boot_params = 0xa0000100,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pxa_map_io,
.init_irq = pxa3xx_init_irq,
.timer = &pxa_timer,
.init_machine = saar_init,
MACHINE_END

View File

@ -38,6 +38,7 @@
#include <asm/arch/pxa-regs.h>
#include <asm/arch/pxa2xx-regs.h>
#include <asm/arch/pxa2xx-gpio.h>
#include <asm/arch/pxa27x-udc.h>
#include <asm/arch/irda.h>
#include <asm/arch/mmc.h>
#include <asm/arch/ohci.h>
@ -450,6 +451,7 @@ static void spitz_irda_transceiver_mode(struct device *dev, int mode)
set_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_IR_ON);
else
reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_IR_ON);
pxa2xx_transceiver_mode(dev, mode);
}
#ifdef CONFIG_MACH_AKITA
@ -459,6 +461,7 @@ static void akita_irda_transceiver_mode(struct device *dev, int mode)
akita_set_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_IR_ON);
else
akita_reset_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_IR_ON);
pxa2xx_transceiver_mode(dev, mode);
}
#endif
@ -529,11 +532,7 @@ static struct platform_device *devices[] __initdata = {
static void spitz_poweroff(void)
{
pxa_gpio_mode(SPITZ_GPIO_ON_RESET | GPIO_OUT);
GPSR(SPITZ_GPIO_ON_RESET) = GPIO_bit(SPITZ_GPIO_ON_RESET);
mdelay(1000);
arm_machine_restart('h');
arm_machine_restart('g');
}
static void spitz_restart(char mode)
@ -547,6 +546,7 @@ static void spitz_restart(char mode)
static void __init common_init(void)
{
init_gpio_reset(SPITZ_GPIO_ON_RESET);
pm_power_off = spitz_poweroff;
arm_pm_restart = spitz_restart;

View File

@ -14,13 +14,6 @@
* IO-based SSP applications and allows easy port setup for DMA access.
*
* Author: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
*
* Revision history:
* 22nd Aug 2003 Initial version.
* 20th Dec 2004 Added ssp_config for changing port config without
* closing the port.
* 4th Aug 2005 Added option to disable irq handler registration and
* cleaned up irq and clock detection.
*/
#include <linux/module.h>
@ -285,7 +278,7 @@ int ssp_init(struct ssp_dev *dev, u32 port, u32 init_flags)
goto out_region;
dev->irq = ssp->irq;
} else
dev->irq = 0;
dev->irq = NO_IRQ;
/* turn on SSP port clock */
clk_enable(ssp->clk);
@ -306,7 +299,8 @@ void ssp_exit(struct ssp_dev *dev)
struct ssp_device *ssp = dev->ssp;
ssp_disable(dev);
free_irq(dev->irq, dev);
if (dev->irq != NO_IRQ)
free_irq(dev->irq, dev);
clk_disable(ssp->clk);
ssp_free(ssp);
}
@ -360,6 +354,7 @@ static int __devinit ssp_probe(struct platform_device *pdev, int type)
dev_err(&pdev->dev, "failed to allocate memory");
return -ENOMEM;
}
ssp->pdev = pdev;
ssp->clk = clk_get(&pdev->dev, "SSPCLK");
if (IS_ERR(ssp->clk)) {

View File

@ -0,0 +1,84 @@
/*
* linux/arch/arm/mach-pxa/tavorevb.c
*
* Support for the Marvell PXA930 Evaluation Board
*
* Copyright (C) 2007-2008 Marvell International Ltd.
*
* 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
* publishhed by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/smc91x.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/hardware.h>
#include <asm/arch/pxa3xx-regs.h>
#include <asm/arch/mfp-pxa930.h>
#include "devices.h"
#include "generic.h"
/* Tavor EVB MFP configurations */
static mfp_cfg_t tavorevb_mfp_cfg[] __initdata = {
/* Ethernet */
DF_nCS1_nCS3,
GPIO47_GPIO,
};
#define TAVOREVB_ETH_PHYS (0x14000000)
static struct resource smc91x_resources[] = {
[0] = {
.start = (TAVOREVB_ETH_PHYS + 0x300),
.end = (TAVOREVB_ETH_PHYS + 0xfffff),
.flags = IORESOURCE_MEM,
},
[1] = {
.start = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO47)),
.end = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO47)),
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
}
};
static struct smc91x_platdata tavorevb_smc91x_info = {
.flags = SMC91X_USE_16BIT | SMC91X_NOWAIT | SMC91X_USE_DMA,
};
static struct platform_device smc91x_device = {
.name = "smc91x",
.id = 0,
.num_resources = ARRAY_SIZE(smc91x_resources),
.resource = smc91x_resources,
.dev = {
.platform_data = &tavorevb_smc91x_info,
},
};
static void __init tavorevb_init(void)
{
/* initialize MFP configurations */
pxa3xx_mfp_config(ARRAY_AND_SIZE(tavorevb_mfp_cfg));
platform_device_register(&smc91x_device);
}
MACHINE_START(TAVOREVB, "PXA930 Evaluation Board (aka TavorEVB)")
/* Maintainer: Eric Miao <eric.miao@marvell.com> */
.phys_io = 0x40000000,
.boot_params = 0xa0000100,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pxa_map_io,
.init_irq = pxa3xx_init_irq,
.timer = &pxa_timer,
.init_machine = tavorevb_init,
MACHINE_END

150
arch/arm/mach-pxa/tosa-bt.c Normal file
View File

@ -0,0 +1,150 @@
/*
* Bluetooth built-in chip control
*
* Copyright (c) 2008 Dmitry Baryshkov
*
* 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/module.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/rfkill.h>
#include <asm/arch/tosa_bt.h>
static void tosa_bt_on(struct tosa_bt_data *data)
{
gpio_set_value(data->gpio_reset, 0);
gpio_set_value(data->gpio_pwr, 1);
gpio_set_value(data->gpio_reset, 1);
mdelay(20);
gpio_set_value(data->gpio_reset, 0);
}
static void tosa_bt_off(struct tosa_bt_data *data)
{
gpio_set_value(data->gpio_reset, 1);
mdelay(10);
gpio_set_value(data->gpio_pwr, 0);
gpio_set_value(data->gpio_reset, 0);
}
static int tosa_bt_toggle_radio(void *data, enum rfkill_state state)
{
pr_info("BT_RADIO going: %s\n",
state == RFKILL_STATE_ON ? "on" : "off");
if (state == RFKILL_STATE_ON) {
pr_info("TOSA_BT: going ON\n");
tosa_bt_on(data);
} else {
pr_info("TOSA_BT: going OFF\n");
tosa_bt_off(data);
}
return 0;
}
static int tosa_bt_probe(struct platform_device *dev)
{
int rc;
struct rfkill *rfk;
struct tosa_bt_data *data = dev->dev.platform_data;
rc = gpio_request(data->gpio_reset, "Bluetooth reset");
if (rc)
goto err_reset;
rc = gpio_direction_output(data->gpio_reset, 0);
if (rc)
goto err_reset_dir;
rc = gpio_request(data->gpio_pwr, "Bluetooth power");
if (rc)
goto err_pwr;
rc = gpio_direction_output(data->gpio_pwr, 0);
if (rc)
goto err_pwr_dir;
rfk = rfkill_allocate(&dev->dev, RFKILL_TYPE_BLUETOOTH);
if (!rfk) {
rc = -ENOMEM;
goto err_rfk_alloc;
}
rfk->name = "tosa-bt";
rfk->toggle_radio = tosa_bt_toggle_radio;
rfk->data = data;
#ifdef CONFIG_RFKILL_LEDS
rfk->led_trigger.name = "tosa-bt";
#endif
rc = rfkill_register(rfk);
if (rc)
goto err_rfkill;
platform_set_drvdata(dev, rfk);
return 0;
err_rfkill:
if (rfk)
rfkill_free(rfk);
rfk = NULL;
err_rfk_alloc:
tosa_bt_off(data);
err_pwr_dir:
gpio_free(data->gpio_pwr);
err_pwr:
err_reset_dir:
gpio_free(data->gpio_reset);
err_reset:
return rc;
}
static int __devexit tosa_bt_remove(struct platform_device *dev)
{
struct tosa_bt_data *data = dev->dev.platform_data;
struct rfkill *rfk = platform_get_drvdata(dev);
platform_set_drvdata(dev, NULL);
if (rfk)
rfkill_unregister(rfk);
rfk = NULL;
tosa_bt_off(data);
gpio_free(data->gpio_pwr);
gpio_free(data->gpio_reset);
return 0;
}
static struct platform_driver tosa_bt_driver = {
.probe = tosa_bt_probe,
.remove = __devexit_p(tosa_bt_remove),
.driver = {
.name = "tosa-bt",
.owner = THIS_MODULE,
},
};
static int __init tosa_bt_init(void)
{
return platform_driver_register(&tosa_bt_driver);
}
static void __exit tosa_bt_exit(void)
{
platform_driver_unregister(&tosa_bt_driver);
}
module_init(tosa_bt_init);
module_exit(tosa_bt_exit);

View File

@ -18,30 +18,31 @@
#include <linux/major.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/mmc/host.h>
#include <linux/pm.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/mmc/host.h>
#include <linux/mfd/tc6393xb.h>
#include <linux/mfd/tmio.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/pm.h>
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/gpio.h>
#include <linux/pda_power.h>
#include <linux/rfkill.h>
#include <asm/setup.h>
#include <asm/memory.h>
#include <asm/mach-types.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/pxa2xx-regs.h>
#include <asm/arch/mfp-pxa25x.h>
#include <asm/arch/irda.h>
#include <asm/arch/i2c.h>
#include <asm/arch/mmc.h>
#include <asm/arch/udc.h>
#include <asm/arch/tosa_bt.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
#include <asm/arch/tosa.h>
#include <asm/hardware/scoop.h>
@ -86,7 +87,7 @@ static unsigned long tosa_pin_config[] = {
GPIO6_MMC_CLK,
GPIO8_MMC_CS0,
GPIO9_GPIO, /* Detect */
// GPIO10 nSD_INT
GPIO10_GPIO, /* nSD_INT */
/* CF */
GPIO13_GPIO, /* CD_IRQ */
@ -124,34 +125,34 @@ static unsigned long tosa_pin_config[] = {
GPIO44_BTUART_CTS,
GPIO45_BTUART_RTS,
/* IrDA */
GPIO46_STUART_RXD,
GPIO47_STUART_TXD,
/* Keybd */
GPIO58_GPIO,
GPIO59_GPIO,
GPIO60_GPIO,
GPIO61_GPIO,
GPIO62_GPIO,
GPIO63_GPIO,
GPIO64_GPIO,
GPIO65_GPIO,
GPIO66_GPIO,
GPIO67_GPIO,
GPIO68_GPIO,
GPIO69_GPIO,
GPIO70_GPIO,
GPIO71_GPIO,
GPIO72_GPIO,
GPIO73_GPIO,
GPIO74_GPIO,
GPIO75_GPIO,
GPIO58_GPIO | MFP_LPM_DRIVE_LOW,
GPIO59_GPIO | MFP_LPM_DRIVE_LOW,
GPIO60_GPIO | MFP_LPM_DRIVE_LOW,
GPIO61_GPIO | MFP_LPM_DRIVE_LOW,
GPIO62_GPIO | MFP_LPM_DRIVE_LOW,
GPIO63_GPIO | MFP_LPM_DRIVE_LOW,
GPIO64_GPIO | MFP_LPM_DRIVE_LOW,
GPIO65_GPIO | MFP_LPM_DRIVE_LOW,
GPIO66_GPIO | MFP_LPM_DRIVE_LOW,
GPIO67_GPIO | MFP_LPM_DRIVE_LOW,
GPIO68_GPIO | MFP_LPM_DRIVE_LOW,
GPIO69_GPIO | MFP_LPM_DRIVE_LOW,
GPIO70_GPIO | MFP_LPM_DRIVE_LOW,
GPIO71_GPIO | MFP_LPM_DRIVE_LOW,
GPIO72_GPIO | MFP_LPM_DRIVE_LOW,
GPIO73_GPIO | MFP_LPM_DRIVE_LOW,
GPIO74_GPIO | MFP_LPM_DRIVE_LOW,
GPIO75_GPIO | MFP_LPM_DRIVE_LOW,
/* SPI */
GPIO81_SSP2_CLK_OUT,
GPIO82_SSP2_FRM_OUT,
GPIO83_SSP2_TXD,
/* IrDA is managed in other way */
GPIO46_GPIO,
GPIO47_GPIO,
};
/*
@ -249,6 +250,15 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void
tosa_mci_platform_data.detect_delay = msecs_to_jiffies(250);
err = gpio_request(TOSA_GPIO_nSD_DETECT, "MMC/SD card detect");
if (err) {
printk(KERN_ERR "tosa_mci_init: can't request nSD_DETECT gpio\n");
goto err_gpio_detect;
}
err = gpio_direction_input(TOSA_GPIO_nSD_DETECT);
if (err)
goto err_gpio_detect_dir;
err = request_irq(TOSA_IRQ_GPIO_nSD_DETECT, tosa_detect_int,
IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"MMC/SD card detect", data);
@ -257,7 +267,7 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void
goto err_irq;
}
err = gpio_request(TOSA_GPIO_SD_WP, "sd_wp");
err = gpio_request(TOSA_GPIO_SD_WP, "SD Write Protect");
if (err) {
printk(KERN_ERR "tosa_mci_init: can't request SD_WP gpio\n");
goto err_gpio_wp;
@ -266,7 +276,7 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void
if (err)
goto err_gpio_wp_dir;
err = gpio_request(TOSA_GPIO_PWR_ON, "sd_pwr");
err = gpio_request(TOSA_GPIO_PWR_ON, "SD Power");
if (err) {
printk(KERN_ERR "tosa_mci_init: can't request SD_PWR gpio\n");
goto err_gpio_pwr;
@ -275,8 +285,20 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void
if (err)
goto err_gpio_pwr_dir;
err = gpio_request(TOSA_GPIO_nSD_INT, "SD Int");
if (err) {
printk(KERN_ERR "tosa_mci_init: can't request SD_PWR gpio\n");
goto err_gpio_int;
}
err = gpio_direction_input(TOSA_GPIO_nSD_INT);
if (err)
goto err_gpio_int_dir;
return 0;
err_gpio_int_dir:
gpio_free(TOSA_GPIO_nSD_INT);
err_gpio_int:
err_gpio_pwr_dir:
gpio_free(TOSA_GPIO_PWR_ON);
err_gpio_pwr:
@ -285,6 +307,9 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void
err_gpio_wp:
free_irq(TOSA_IRQ_GPIO_nSD_DETECT, data);
err_irq:
err_gpio_detect_dir:
gpio_free(TOSA_GPIO_nSD_DETECT);
err_gpio_detect:
return err;
}
@ -306,9 +331,11 @@ static int tosa_mci_get_ro(struct device *dev)
static void tosa_mci_exit(struct device *dev, void *data)
{
gpio_free(TOSA_GPIO_nSD_INT);
gpio_free(TOSA_GPIO_PWR_ON);
gpio_free(TOSA_GPIO_SD_WP);
free_irq(TOSA_IRQ_GPIO_nSD_DETECT, data);
gpio_free(TOSA_GPIO_nSD_DETECT);
}
static struct pxamci_platform_data tosa_mci_platform_data = {
@ -322,29 +349,55 @@ static struct pxamci_platform_data tosa_mci_platform_data = {
/*
* Irda
*/
static void tosa_irda_transceiver_mode(struct device *dev, int mode)
{
if (mode & IR_OFF) {
gpio_set_value(TOSA_GPIO_IR_POWERDWN, 0);
pxa2xx_transceiver_mode(dev, mode);
gpio_direction_output(TOSA_GPIO_IRDA_TX, 0);
} else {
pxa2xx_transceiver_mode(dev, mode);
gpio_set_value(TOSA_GPIO_IR_POWERDWN, 1);
}
}
static int tosa_irda_startup(struct device *dev)
{
int ret;
ret = gpio_request(TOSA_GPIO_IRDA_TX, "IrDA TX");
if (ret)
goto err_tx;
ret = gpio_direction_output(TOSA_GPIO_IRDA_TX, 0);
if (ret)
goto err_tx_dir;
ret = gpio_request(TOSA_GPIO_IR_POWERDWN, "IrDA powerdown");
if (ret)
return ret;
goto err_pwr;
ret = gpio_direction_output(TOSA_GPIO_IR_POWERDWN, 0);
if (ret)
gpio_free(TOSA_GPIO_IR_POWERDWN);
goto err_pwr_dir;
tosa_irda_transceiver_mode(dev, IR_SIRMODE | IR_OFF);
return 0;
err_pwr_dir:
gpio_free(TOSA_GPIO_IR_POWERDWN);
err_pwr:
err_tx_dir:
gpio_free(TOSA_GPIO_IRDA_TX);
err_tx:
return ret;
}
}
static void tosa_irda_shutdown(struct device *dev)
{
tosa_irda_transceiver_mode(dev, IR_SIRMODE | IR_OFF);
gpio_free(TOSA_GPIO_IR_POWERDWN);
}
static void tosa_irda_transceiver_mode(struct device *dev, int mode)
{
gpio_set_value(TOSA_GPIO_IR_POWERDWN, !(mode & IR_OFF));
gpio_free(TOSA_GPIO_IRDA_TX);
}
static struct pxaficp_platform_data tosa_ficp_platform_data = {
@ -354,6 +407,70 @@ static struct pxaficp_platform_data tosa_ficp_platform_data = {
.shutdown = tosa_irda_shutdown,
};
/*
* Tosa AC IN
*/
static int tosa_power_init(struct device *dev)
{
int ret = gpio_request(TOSA_GPIO_AC_IN, "ac in");
if (ret)
goto err_gpio_req;
ret = gpio_direction_input(TOSA_GPIO_AC_IN);
if (ret)
goto err_gpio_in;
return 0;
err_gpio_in:
gpio_free(TOSA_GPIO_AC_IN);
err_gpio_req:
return ret;
}
static void tosa_power_exit(struct device *dev)
{
gpio_free(TOSA_GPIO_AC_IN);
}
static int tosa_power_ac_online(void)
{
return gpio_get_value(TOSA_GPIO_AC_IN) == 0;
}
static char *tosa_ac_supplied_to[] = {
"main-battery",
"backup-battery",
"jacket-battery",
};
static struct pda_power_pdata tosa_power_data = {
.init = tosa_power_init,
.is_ac_online = tosa_power_ac_online,
.exit = tosa_power_exit,
.supplied_to = tosa_ac_supplied_to,
.num_supplicants = ARRAY_SIZE(tosa_ac_supplied_to),
};
static struct resource tosa_power_resource[] = {
{
.name = "ac",
.start = gpio_to_irq(TOSA_GPIO_AC_IN),
.end = gpio_to_irq(TOSA_GPIO_AC_IN),
.flags = IORESOURCE_IRQ |
IORESOURCE_IRQ_HIGHEDGE |
IORESOURCE_IRQ_LOWEDGE,
},
};
static struct platform_device tosa_power_device = {
.name = "pda-power",
.id = -1,
.dev.platform_data = &tosa_power_data,
.resource = tosa_power_resource,
.num_resources = ARRAY_SIZE(tosa_power_resource),
};
/*
* Tosa Keyboard
*/
@ -439,7 +556,7 @@ static struct gpio_led tosa_gpio_leds[] = {
},
{
.name = "tosa:blue:bluetooth",
.default_trigger = "none",
.default_trigger = "tosa-bt",
.gpio = TOSA_GPIO_BT_LED,
},
};
@ -457,21 +574,184 @@ static struct platform_device tosaled_device = {
},
};
/*
* Toshiba Mobile IO Controller
*/
static struct resource tc6393xb_resources[] = {
[0] = {
.start = TOSA_LCDC_PHYS,
.end = TOSA_LCDC_PHYS + 0x3ffffff,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = TOSA_IRQ_GPIO_TC6393XB_INT,
.end = TOSA_IRQ_GPIO_TC6393XB_INT,
.flags = IORESOURCE_IRQ,
},
};
static int tosa_tc6393xb_enable(struct platform_device *dev)
{
int rc;
rc = gpio_request(TOSA_GPIO_TC6393XB_REST_IN, "tc6393xb #pclr");
if (rc)
goto err_req_pclr;
rc = gpio_request(TOSA_GPIO_TC6393XB_SUSPEND, "tc6393xb #suspend");
if (rc)
goto err_req_suspend;
rc = gpio_request(TOSA_GPIO_TC6393XB_L3V_ON, "l3v");
if (rc)
goto err_req_l3v;
rc = gpio_direction_output(TOSA_GPIO_TC6393XB_L3V_ON, 0);
if (rc)
goto err_dir_l3v;
rc = gpio_direction_output(TOSA_GPIO_TC6393XB_SUSPEND, 0);
if (rc)
goto err_dir_suspend;
rc = gpio_direction_output(TOSA_GPIO_TC6393XB_REST_IN, 0);
if (rc)
goto err_dir_pclr;
mdelay(1);
gpio_set_value(TOSA_GPIO_TC6393XB_SUSPEND, 1);
mdelay(10);
gpio_set_value(TOSA_GPIO_TC6393XB_REST_IN, 1);
gpio_set_value(TOSA_GPIO_TC6393XB_L3V_ON, 1);
return 0;
err_dir_pclr:
err_dir_suspend:
err_dir_l3v:
gpio_free(TOSA_GPIO_TC6393XB_L3V_ON);
err_req_l3v:
gpio_free(TOSA_GPIO_TC6393XB_SUSPEND);
err_req_suspend:
gpio_free(TOSA_GPIO_TC6393XB_REST_IN);
err_req_pclr:
return rc;
}
static int tosa_tc6393xb_disable(struct platform_device *dev)
{
gpio_free(TOSA_GPIO_TC6393XB_L3V_ON);
gpio_free(TOSA_GPIO_TC6393XB_SUSPEND);
gpio_free(TOSA_GPIO_TC6393XB_REST_IN);
return 0;
}
static int tosa_tc6393xb_resume(struct platform_device *dev)
{
gpio_set_value(TOSA_GPIO_TC6393XB_SUSPEND, 1);
mdelay(10);
gpio_set_value(TOSA_GPIO_TC6393XB_L3V_ON, 1);
mdelay(10);
return 0;
}
static int tosa_tc6393xb_suspend(struct platform_device *dev)
{
gpio_set_value(TOSA_GPIO_TC6393XB_L3V_ON, 0);
gpio_set_value(TOSA_GPIO_TC6393XB_SUSPEND, 0);
return 0;
}
static struct mtd_partition tosa_nand_partition[] = {
{
.name = "smf",
.offset = 0,
.size = 7 * 1024 * 1024,
},
{
.name = "root",
.offset = MTDPART_OFS_APPEND,
.size = 28 * 1024 * 1024,
},
{
.name = "home",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL,
},
};
static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
static struct nand_bbt_descr tosa_tc6393xb_nand_bbt = {
.options = 0,
.offs = 4,
.len = 2,
.pattern = scan_ff_pattern
};
static struct tmio_nand_data tosa_tc6393xb_nand_config = {
.num_partitions = ARRAY_SIZE(tosa_nand_partition),
.partition = tosa_nand_partition,
.badblock_pattern = &tosa_tc6393xb_nand_bbt,
};
static struct tc6393xb_platform_data tosa_tc6393xb_setup = {
.scr_pll2cr = 0x0cc1,
.scr_gper = 0x3300,
.scr_gpo_dsr =
TOSA_TC6393XB_GPIO_BIT(TOSA_GPIO_CARD_VCC_ON),
.scr_gpo_doecr =
TOSA_TC6393XB_GPIO_BIT(TOSA_GPIO_CARD_VCC_ON),
.irq_base = IRQ_BOARD_START,
.gpio_base = TOSA_TC6393XB_GPIO_BASE,
.enable = tosa_tc6393xb_enable,
.disable = tosa_tc6393xb_disable,
.suspend = tosa_tc6393xb_suspend,
.resume = tosa_tc6393xb_resume,
.nand_data = &tosa_tc6393xb_nand_config,
};
static struct platform_device tc6393xb_device = {
.name = "tc6393xb",
.id = -1,
.dev = {
.platform_data = &tosa_tc6393xb_setup,
},
.num_resources = ARRAY_SIZE(tc6393xb_resources),
.resource = tc6393xb_resources,
};
static struct tosa_bt_data tosa_bt_data = {
.gpio_pwr = TOSA_GPIO_BT_PWR_EN,
.gpio_reset = TOSA_GPIO_BT_RESET,
};
static struct platform_device tosa_bt_device = {
.name = "tosa-bt",
.id = -1,
.dev.platform_data = &tosa_bt_data,
};
static struct platform_device *devices[] __initdata = {
&tosascoop_device,
&tosascoop_jc_device,
&tc6393xb_device,
&tosa_power_device,
&tosakbd_device,
&tosa_gpio_keys_device,
&tosaled_device,
&tosa_bt_device,
};
static void tosa_poweroff(void)
{
gpio_direction_output(TOSA_GPIO_ON_RESET, 0);
gpio_set_value(TOSA_GPIO_ON_RESET, 1);
mdelay(1000);
arm_machine_restart('h');
arm_machine_restart('g');
}
static void tosa_restart(char mode)
@ -485,10 +765,14 @@ static void tosa_restart(char mode)
static void __init tosa_init(void)
{
int dummy;
pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_config));
gpio_set_wake(MFP_PIN_GPIO1, 1);
/* We can't pass to gpio-keys since it will drop the Reset altfunc */
init_gpio_reset(TOSA_GPIO_ON_RESET);
pm_power_off = tosa_poweroff;
arm_pm_restart = tosa_restart;
@ -497,6 +781,10 @@ static void __init tosa_init(void)
/* enable batt_fault */
PMCR = 0x01;
dummy = gpiochip_reserve(TOSA_SCOOP_GPIO_BASE, 12);
dummy = gpiochip_reserve(TOSA_SCOOP_JC_GPIO_BASE, 12);
dummy = gpiochip_reserve(TOSA_TC6393XB_GPIO_BASE, 16);
pxa_set_mci_info(&tosa_mci_platform_data);
pxa_set_udc_info(&udc_info);
pxa_set_ficp_info(&tosa_ficp_platform_data);

View File

@ -254,6 +254,7 @@ static void board_irda_mode(struct device *dev, int mode)
/* Fast mode */
trizeps_conxs_ircr |= ConXS_IRCR_MODE;
}
pxa2xx_transceiver_mode(dev, mode);
if (mode & IR_OFF) {
trizeps_conxs_ircr |= ConXS_IRCR_SD;
} else {

View File

@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/pwm_backlight.h>
#include <linux/smc91x.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@ -29,6 +30,7 @@
#include <asm/arch/zylonite.h>
#include <asm/arch/mmc.h>
#include <asm/arch/pxa27x_keypad.h>
#include <asm/arch/pxa3xx_nand.h>
#include "devices.h"
#include "generic.h"
@ -37,6 +39,8 @@
struct platform_mmc_slot zylonite_mmc_slot[MAX_SLOTS];
int gpio_eth_irq;
int gpio_debug_led1;
int gpio_debug_led2;
int wm9713_irq;
@ -56,13 +60,57 @@ static struct resource smc91x_resources[] = {
}
};
static struct smc91x_platdata zylonite_smc91x_info = {
.flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT |
SMC91X_NOWAIT | SMC91X_USE_DMA,
};
static struct platform_device smc91x_device = {
.name = "smc91x",
.id = 0,
.num_resources = ARRAY_SIZE(smc91x_resources),
.resource = smc91x_resources,
.dev = {
.platform_data = &zylonite_smc91x_info,
},
};
#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
static struct gpio_led zylonite_debug_leds[] = {
[0] = {
.name = "zylonite:yellow:1",
.default_trigger = "heartbeat",
},
[1] = {
.name = "zylonite:yellow:2",
.default_trigger = "default-on",
},
};
static struct gpio_led_platform_data zylonite_debug_leds_info = {
.leds = zylonite_debug_leds,
.num_leds = ARRAY_SIZE(zylonite_debug_leds),
};
static struct platform_device zylonite_device_leds = {
.name = "leds-gpio",
.id = -1,
.dev = {
.platform_data = &zylonite_debug_leds_info,
}
};
static void __init zylonite_init_leds(void)
{
zylonite_debug_leds[0].gpio = gpio_debug_led1;
zylonite_debug_leds[1].gpio = gpio_debug_led2;
platform_device_register(&zylonite_device_leds);
}
#else
static inline void zylonite_init_leds(void) {}
#endif
#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
static struct platform_pwm_backlight_data zylonite_backlight_data = {
.pwm_id = 3,
@ -259,7 +307,7 @@ static void __init zylonite_init_mmc(void)
static inline void zylonite_init_mmc(void) {}
#endif
#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULES)
#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE)
static unsigned int zylonite_matrix_key_map[] = {
/* KEY(row, col, key_code) */
KEY(0, 0, KEY_A), KEY(0, 1, KEY_B), KEY(0, 2, KEY_C), KEY(0, 5, KEY_D),
@ -324,6 +372,57 @@ static void __init zylonite_init_keypad(void)
static inline void zylonite_init_keypad(void) {}
#endif
#if defined(CONFIG_MTD_NAND_PXA3xx) || defined(CONFIG_MTD_NAND_PXA3xx_MODULE)
static struct mtd_partition zylonite_nand_partitions[] = {
[0] = {
.name = "Bootloader",
.offset = 0,
.size = 0x060000,
.mask_flags = MTD_WRITEABLE, /* force read-only */
},
[1] = {
.name = "Kernel",
.offset = 0x060000,
.size = 0x200000,
.mask_flags = MTD_WRITEABLE, /* force read-only */
},
[2] = {
.name = "Filesystem",
.offset = 0x0260000,
.size = 0x3000000, /* 48M - rootfs */
},
[3] = {
.name = "MassStorage",
.offset = 0x3260000,
.size = 0x3d40000,
},
[4] = {
.name = "BBT",
.offset = 0x6FA0000,
.size = 0x80000,
.mask_flags = MTD_WRITEABLE, /* force read-only */
},
/* NOTE: we reserve some blocks at the end of the NAND flash for
* bad block management, and the max number of relocation blocks
* differs on different platforms. Please take care with it when
* defining the partition table.
*/
};
static struct pxa3xx_nand_platform_data zylonite_nand_info = {
.enable_arbiter = 1,
.parts = zylonite_nand_partitions,
.nr_parts = ARRAY_SIZE(zylonite_nand_partitions),
};
static void __init zylonite_init_nand(void)
{
pxa3xx_set_nand_info(&zylonite_nand_info);
}
#else
static inline void zylonite_init_nand(void) {}
#endif /* CONFIG_MTD_NAND_PXA3xx || CONFIG_MTD_NAND_PXA3xx_MODULE */
static void __init zylonite_init(void)
{
/* board-processor specific initialization */
@ -342,6 +441,8 @@ static void __init zylonite_init(void)
zylonite_init_lcd();
zylonite_init_mmc();
zylonite_init_keypad();
zylonite_init_nand();
zylonite_init_leds();
}
MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")

View File

@ -16,9 +16,12 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/i2c/pca953x.h>
#include <asm/gpio.h>
#include <asm/arch/mfp-pxa300.h>
#include <asm/arch/i2c.h>
#include <asm/arch/zylonite.h>
#include "generic.h"
@ -109,6 +112,10 @@ static mfp_cfg_t common_mfp_cfg[] __initdata = {
GPIO12_MMC2_DAT3,
GPIO13_MMC2_CLK,
GPIO14_MMC2_CMD,
/* Standard I2C */
GPIO21_I2C_SCL,
GPIO22_I2C_SDA,
};
static mfp_cfg_t pxa300_mfp_cfg[] __initdata = {
@ -192,6 +199,39 @@ static void __init zylonite_detect_lcd_panel(void)
pxa3xx_mfp_write(lcd_detect_pins[i], mfpr_save[i]);
}
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static struct pca953x_platform_data gpio_exp[] = {
[0] = {
.gpio_base = 128,
},
[1] = {
.gpio_base = 144,
},
};
struct i2c_board_info zylonite_i2c_board_info[] = {
{
.type = "pca9539",
.addr = 0x74,
.platform_data = &gpio_exp[0],
.irq = IRQ_GPIO(18),
}, {
.type = "pca9539",
.addr = 0x75,
.platform_data = &gpio_exp[1],
.irq = IRQ_GPIO(19),
},
};
static void __init zylonite_init_i2c(void)
{
pxa_set_i2c_info(NULL);
i2c_register_board_info(0, ARRAY_AND_SIZE(zylonite_i2c_board_info));
}
#else
static inline void zylonite_init_i2c(void) {}
#endif
void __init zylonite_pxa300_init(void)
{
if (cpu_is_pxa300() || cpu_is_pxa310()) {
@ -207,6 +247,8 @@ void __init zylonite_pxa300_init(void)
/* WM9713 IRQ */
wm9713_irq = mfp_to_gpio(MFP_PIN_GPIO26);
zylonite_init_i2c();
}
if (cpu_is_pxa300()) {
@ -222,4 +264,8 @@ void __init zylonite_pxa300_init(void)
zylonite_mmc_slot[2].gpio_cd = EXT_GPIO(30);
zylonite_mmc_slot[2].gpio_wp = EXT_GPIO(31);
}
/* GPIOs for Debug LEDs */
gpio_debug_led1 = EXT_GPIO(25);
gpio_debug_led2 = EXT_GPIO(26);
}

View File

@ -116,6 +116,10 @@ static mfp_cfg_t mfp_cfg[] __initdata = {
GPIO27_MMC2_DAT3,
GPIO28_MMC2_CLK,
GPIO29_MMC2_CMD,
/* Debug LEDs */
GPIO1_2_GPIO | MFP_LPM_DRIVE_HIGH,
GPIO4_2_GPIO | MFP_LPM_DRIVE_HIGH,
};
#define NUM_LCD_DETECT_PINS 7
@ -189,6 +193,8 @@ void __init zylonite_pxa320_init(void)
/* GPIO pin assignment */
gpio_eth_irq = mfp_to_gpio(MFP_PIN_GPIO9);
gpio_debug_led1 = mfp_to_gpio(MFP_PIN_GPIO1_2);
gpio_debug_led2 = mfp_to_gpio(MFP_PIN_GPIO4_2);
/* MMC card detect & write protect for controller 0 */
zylonite_mmc_slot[0].gpio_cd = mfp_to_gpio(MFP_PIN_GPIO1);

View File

@ -103,7 +103,7 @@ static void clk_gpio27_disable(void)
}
static struct clk clk_gpio27 = {
.name = "GPIO27_CLK",
.name = "SA1111_CLK",
.rate = 3686400,
.enable = clk_gpio27_enable,
.disable = clk_gpio27_disable,

View File

@ -76,3 +76,5 @@ obj-$(CONFIG_CPU_V7) += proc-v7.o
obj-$(CONFIG_CACHE_FEROCEON_L2) += cache-feroceon-l2.o
obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o
obj-$(CONFIG_CACHE_XSC3L2) += cache-xsc3l2.o

View File

@ -12,7 +12,7 @@
#
# http://www.arm.linux.org.uk/developer/machines/?action=new
#
# Last update: Mon Jul 7 16:25:39 2008
# Last update: Sun Jul 13 12:04:05 2008
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
@ -1812,3 +1812,11 @@ jade MACH_JADE JADE 1821
ks8695_softplc MACH_KS8695_SOFTPLC KS8695_SOFTPLC 1822
gprisc4 MACH_GPRISC4 GPRISC4 1823
stamp9260 MACH_STAMP9260 STAMP9260 1824
smdk6430 MACH_SMDK6430 SMDK6430 1825
smdkc100 MACH_SMDKC100 SMDKC100 1826
tavorevb MACH_TAVOREVB TAVOREVB 1827
saar MACH_SAAR SAAR 1828
deister_eyecam MACH_DEISTER_EYECAM DEISTER_EYECAM 1829
at91sam9m10ek MACH_AT91SAM9M10EK AT91SAM9M10EK 1830
linkstation_produo MACH_LINKSTATION_PRODUO LINKSTATION_PRODUO 1831
hit_b0 MACH_HIT_B0 HIT_B0 1832

View File

@ -7,6 +7,7 @@
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dw_dmac.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@ -594,6 +595,17 @@ static void __init genclk_init_parent(struct clk *clk)
clk->parent = parent;
}
static struct dw_dma_platform_data dw_dmac0_data = {
.nr_channels = 3,
};
static struct resource dw_dmac0_resource[] = {
PBMEM(0xff200000),
IRQ(2),
};
DEFINE_DEV_DATA(dw_dmac, 0);
DEV_CLK(hclk, dw_dmac0, hsb, 10);
/* --------------------------------------------------------------------
* System peripherals
* -------------------------------------------------------------------- */
@ -708,17 +720,6 @@ static struct clk pico_clk = {
.users = 1,
};
static struct resource dmaca0_resource[] = {
{
.start = 0xff200000,
.end = 0xff20ffff,
.flags = IORESOURCE_MEM,
},
IRQ(2),
};
DEFINE_DEV(dmaca, 0);
DEV_CLK(hclk, dmaca0, hsb, 10);
/* --------------------------------------------------------------------
* HMATRIX
* -------------------------------------------------------------------- */
@ -831,7 +832,7 @@ void __init at32_add_system_devices(void)
platform_device_register(&at32_eic0_device);
platform_device_register(&smc0_device);
platform_device_register(&pdc_device);
platform_device_register(&dmaca0_device);
platform_device_register(&dw_dmac0_device);
platform_device_register(&at32_tcb0_device);
platform_device_register(&at32_tcb1_device);
@ -2032,7 +2033,7 @@ struct clk *at32_clock_list[] = {
&smc0_mck,
&pdc_hclk,
&pdc_pclk,
&dmaca0_hclk,
&dw_dmac0_hclk,
&pico_clk,
&pio0_mck,
&pio1_mck,

View File

@ -112,6 +112,7 @@ config PPC
select HAVE_FTRACE
select HAVE_IDE
select HAVE_KPROBES
select HAVE_ARCH_KGDB
select HAVE_KRETPROBES
select HAVE_LMB
select HAVE_DMA_ATTRS if PPC64

View File

@ -41,22 +41,6 @@ config HCALL_STATS
This option will add a small amount of overhead to all hypervisor
calls.
config DEBUGGER
bool "Enable debugger hooks"
depends on DEBUG_KERNEL
help
Include in-kernel hooks for kernel debuggers. Unless you are
intending to debug the kernel, say N here.
config KGDB
bool "Include kgdb kernel debugger"
depends on DEBUGGER && (BROKEN || PPC_GEN550 || 4xx)
select DEBUG_INFO
help
Include in-kernel hooks for kgdb, the Linux kernel source level
debugger. See <http://kgdb.sourceforge.net/> for more information.
Unless you are intending to debug the kernel, say N here.
config CODE_PATCHING_SELFTEST
bool "Run self-tests of the code-patching code."
depends on DEBUG_KERNEL
@ -67,36 +51,9 @@ config FTR_FIXUP_SELFTEST
depends on DEBUG_KERNEL
default n
choice
prompt "Serial Port"
depends on KGDB
default KGDB_TTYS1
config KGDB_TTYS0
bool "ttyS0"
config KGDB_TTYS1
bool "ttyS1"
config KGDB_TTYS2
bool "ttyS2"
config KGDB_TTYS3
bool "ttyS3"
endchoice
config KGDB_CONSOLE
bool "Enable serial console thru kgdb port"
depends on KGDB && 8xx || CPM2
help
If you enable this, all serial console messages will be sent
over the gdb stub.
If unsure, say N.
config XMON
bool "Include xmon kernel debugger"
depends on DEBUGGER
depends on DEBUG_KERNEL
help
Include in-kernel hooks for the xmon kernel monitor/debugger.
Unless you are intending to debug the kernel, say N here.
@ -126,6 +83,11 @@ config XMON_DISASSEMBLY
to say Y here, unless you're building for a memory-constrained
system.
config DEBUGGER
bool
depends on KGDB || XMON
default y
config IRQSTACKS
bool "Use separate kernel stacks when processing interrupts"
help

View File

@ -74,6 +74,7 @@ obj-y += time.o prom.o traps.o setup-common.o \
misc_$(CONFIG_WORD_SIZE).o
obj-$(CONFIG_PPC32) += entry_32.o setup_32.o
obj-$(CONFIG_PPC64) += dma_64.o iommu.o
obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o
obj-$(CONFIG_MODULES) += ppc_ksyms.o
obj-$(CONFIG_BOOTX_TEXT) += btext.o

410
arch/powerpc/kernel/kgdb.c Normal file
View File

@ -0,0 +1,410 @@
/*
* PowerPC backend to the KGDB stub.
*
* 1998 (c) Michael AK Tesch (tesch@cs.wisc.edu)
* Copyright (C) 2003 Timesys Corporation.
* Copyright (C) 2004-2006 MontaVista Software, Inc.
* PPC64 Mods (C) 2005 Frank Rowand (frowand@mvista.com)
* PPC32 support restored by Vitaly Wool <vwool@ru.mvista.com> and
* Sergei Shtylyov <sshtylyov@ru.mvista.com>
* Copyright (C) 2007-2008 Wind River Systems, Inc.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program as licensed "as is" without any warranty of any
* kind, whether express or implied.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/kgdb.h>
#include <linux/smp.h>
#include <linux/signal.h>
#include <linux/ptrace.h>
#include <asm/current.h>
#include <asm/processor.h>
#include <asm/machdep.h>
/*
* This table contains the mapping between PowerPC hardware trap types, and
* signals, which are primarily what GDB understands. GDB and the kernel
* don't always agree on values, so we use constants taken from gdb-6.2.
*/
static struct hard_trap_info
{
unsigned int tt; /* Trap type code for powerpc */
unsigned char signo; /* Signal that we map this trap into */
} hard_trap_info[] = {
{ 0x0100, 0x02 /* SIGINT */ }, /* system reset */
{ 0x0200, 0x0b /* SIGSEGV */ }, /* machine check */
{ 0x0300, 0x0b /* SIGSEGV */ }, /* data access */
{ 0x0400, 0x0b /* SIGSEGV */ }, /* instruction access */
{ 0x0500, 0x02 /* SIGINT */ }, /* external interrupt */
{ 0x0600, 0x0a /* SIGBUS */ }, /* alignment */
{ 0x0700, 0x05 /* SIGTRAP */ }, /* program check */
{ 0x0800, 0x08 /* SIGFPE */ }, /* fp unavailable */
{ 0x0900, 0x0e /* SIGALRM */ }, /* decrementer */
{ 0x0c00, 0x14 /* SIGCHLD */ }, /* system call */
#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
{ 0x2002, 0x05 /* SIGTRAP */ }, /* debug */
#if defined(CONFIG_FSL_BOOKE)
{ 0x2010, 0x08 /* SIGFPE */ }, /* spe unavailable */
{ 0x2020, 0x08 /* SIGFPE */ }, /* spe unavailable */
{ 0x2030, 0x08 /* SIGFPE */ }, /* spe fp data */
{ 0x2040, 0x08 /* SIGFPE */ }, /* spe fp data */
{ 0x2050, 0x08 /* SIGFPE */ }, /* spe fp round */
{ 0x2060, 0x0e /* SIGILL */ }, /* performace monitor */
{ 0x2900, 0x08 /* SIGFPE */ }, /* apu unavailable */
{ 0x3100, 0x0e /* SIGALRM */ }, /* fixed interval timer */
{ 0x3200, 0x02 /* SIGINT */ }, /* watchdog */
#else /* ! CONFIG_FSL_BOOKE */
{ 0x1000, 0x0e /* SIGALRM */ }, /* prog interval timer */
{ 0x1010, 0x0e /* SIGALRM */ }, /* fixed interval timer */
{ 0x1020, 0x02 /* SIGINT */ }, /* watchdog */
{ 0x2010, 0x08 /* SIGFPE */ }, /* fp unavailable */
{ 0x2020, 0x08 /* SIGFPE */ }, /* ap unavailable */
#endif
#else /* ! (defined(CONFIG_40x) || defined(CONFIG_BOOKE)) */
{ 0x0d00, 0x05 /* SIGTRAP */ }, /* single-step */
#if defined(CONFIG_8xx)
{ 0x1000, 0x04 /* SIGILL */ }, /* software emulation */
#else /* ! CONFIG_8xx */
{ 0x0f00, 0x04 /* SIGILL */ }, /* performance monitor */
{ 0x0f20, 0x08 /* SIGFPE */ }, /* altivec unavailable */
{ 0x1300, 0x05 /* SIGTRAP */ }, /* instruction address break */
#if defined(CONFIG_PPC64)
{ 0x1200, 0x05 /* SIGILL */ }, /* system error */
{ 0x1500, 0x04 /* SIGILL */ }, /* soft patch */
{ 0x1600, 0x04 /* SIGILL */ }, /* maintenance */
{ 0x1700, 0x08 /* SIGFPE */ }, /* altivec assist */
{ 0x1800, 0x04 /* SIGILL */ }, /* thermal */
#else /* ! CONFIG_PPC64 */
{ 0x1400, 0x02 /* SIGINT */ }, /* SMI */
{ 0x1600, 0x08 /* SIGFPE */ }, /* altivec assist */
{ 0x1700, 0x04 /* SIGILL */ }, /* TAU */
{ 0x2000, 0x05 /* SIGTRAP */ }, /* run mode */
#endif
#endif
#endif
{ 0x0000, 0x00 } /* Must be last */
};
static int computeSignal(unsigned int tt)
{
struct hard_trap_info *ht;
for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
if (ht->tt == tt)
return ht->signo;
return SIGHUP; /* default for things we don't know about */
}
static int kgdb_call_nmi_hook(struct pt_regs *regs)
{
kgdb_nmicallback(raw_smp_processor_id(), regs);
return 0;
}
#ifdef CONFIG_SMP
void kgdb_roundup_cpus(unsigned long flags)
{
smp_send_debugger_break(MSG_ALL_BUT_SELF);
}
#endif
/* KGDB functions to use existing PowerPC64 hooks. */
static int kgdb_debugger(struct pt_regs *regs)
{
return kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
}
static int kgdb_handle_breakpoint(struct pt_regs *regs)
{
if (user_mode(regs))
return 0;
if (kgdb_handle_exception(0, SIGTRAP, 0, regs) != 0)
return 0;
if (*(u32 *) (regs->nip) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr))
regs->nip += 4;
return 1;
}
static int kgdb_singlestep(struct pt_regs *regs)
{
struct thread_info *thread_info, *exception_thread_info;
if (user_mode(regs))
return 0;
/*
* On Book E and perhaps other processsors, singlestep is handled on
* the critical exception stack. This causes current_thread_info()
* to fail, since it it locates the thread_info by masking off
* the low bits of the current stack pointer. We work around
* this issue by copying the thread_info from the kernel stack
* before calling kgdb_handle_exception, and copying it back
* afterwards. On most processors the copy is avoided since
* exception_thread_info == thread_info.
*/
thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1));
exception_thread_info = current_thread_info();
if (thread_info != exception_thread_info)
memcpy(exception_thread_info, thread_info, sizeof *thread_info);
kgdb_handle_exception(0, SIGTRAP, 0, regs);
if (thread_info != exception_thread_info)
memcpy(thread_info, exception_thread_info, sizeof *thread_info);
return 1;
}
static int kgdb_iabr_match(struct pt_regs *regs)
{
if (user_mode(regs))
return 0;
if (kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs) != 0)
return 0;
return 1;
}
static int kgdb_dabr_match(struct pt_regs *regs)
{
if (user_mode(regs))
return 0;
if (kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs) != 0)
return 0;
return 1;
}
#define PACK64(ptr, src) do { *(ptr++) = (src); } while (0)
#define PACK32(ptr, src) do { \
u32 *ptr32; \
ptr32 = (u32 *)ptr; \
*(ptr32++) = (src); \
ptr = (unsigned long *)ptr32; \
} while (0)
void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
{
unsigned long *ptr = gdb_regs;
int reg;
memset(gdb_regs, 0, NUMREGBYTES);
for (reg = 0; reg < 32; reg++)
PACK64(ptr, regs->gpr[reg]);
#ifdef CONFIG_FSL_BOOKE
#ifdef CONFIG_SPE
for (reg = 0; reg < 32; reg++)
PACK64(ptr, current->thread.evr[reg]);
#else
ptr += 32;
#endif
#else
/* fp registers not used by kernel, leave zero */
ptr += 32 * 8 / sizeof(long);
#endif
PACK64(ptr, regs->nip);
PACK64(ptr, regs->msr);
PACK32(ptr, regs->ccr);
PACK64(ptr, regs->link);
PACK64(ptr, regs->ctr);
PACK32(ptr, regs->xer);
BUG_ON((unsigned long)ptr >
(unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
}
void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
{
struct pt_regs *regs = (struct pt_regs *)(p->thread.ksp +
STACK_FRAME_OVERHEAD);
unsigned long *ptr = gdb_regs;
int reg;
memset(gdb_regs, 0, NUMREGBYTES);
/* Regs GPR0-2 */
for (reg = 0; reg < 3; reg++)
PACK64(ptr, regs->gpr[reg]);
/* Regs GPR3-13 are caller saved, not in regs->gpr[] */
ptr += 11;
/* Regs GPR14-31 */
for (reg = 14; reg < 32; reg++)
PACK64(ptr, regs->gpr[reg]);
#ifdef CONFIG_FSL_BOOKE
#ifdef CONFIG_SPE
for (reg = 0; reg < 32; reg++)
PACK64(ptr, p->thread.evr[reg]);
#else
ptr += 32;
#endif
#else
/* fp registers not used by kernel, leave zero */
ptr += 32 * 8 / sizeof(long);
#endif
PACK64(ptr, regs->nip);
PACK64(ptr, regs->msr);
PACK32(ptr, regs->ccr);
PACK64(ptr, regs->link);
PACK64(ptr, regs->ctr);
PACK32(ptr, regs->xer);
BUG_ON((unsigned long)ptr >
(unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
}
#define UNPACK64(dest, ptr) do { dest = *(ptr++); } while (0)
#define UNPACK32(dest, ptr) do { \
u32 *ptr32; \
ptr32 = (u32 *)ptr; \
dest = *(ptr32++); \
ptr = (unsigned long *)ptr32; \
} while (0)
void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
{
unsigned long *ptr = gdb_regs;
int reg;
#ifdef CONFIG_SPE
union {
u32 v32[2];
u64 v64;
} acc;
#endif
for (reg = 0; reg < 32; reg++)
UNPACK64(regs->gpr[reg], ptr);
#ifdef CONFIG_FSL_BOOKE
#ifdef CONFIG_SPE
for (reg = 0; reg < 32; reg++)
UNPACK64(current->thread.evr[reg], ptr);
#else
ptr += 32;
#endif
#else
/* fp registers not used by kernel, leave zero */
ptr += 32 * 8 / sizeof(int);
#endif
UNPACK64(regs->nip, ptr);
UNPACK64(regs->msr, ptr);
UNPACK32(regs->ccr, ptr);
UNPACK64(regs->link, ptr);
UNPACK64(regs->ctr, ptr);
UNPACK32(regs->xer, ptr);
BUG_ON((unsigned long)ptr >
(unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
}
/*
* This function does PowerPC specific procesing for interfacing to gdb.
*/
int kgdb_arch_handle_exception(int vector, int signo, int err_code,
char *remcom_in_buffer, char *remcom_out_buffer,
struct pt_regs *linux_regs)
{
char *ptr = &remcom_in_buffer[1];
unsigned long addr;
switch (remcom_in_buffer[0]) {
/*
* sAA..AA Step one instruction from AA..AA
* This will return an error to gdb ..
*/
case 's':
case 'c':
/* handle the optional parameter */
if (kgdb_hex2long(&ptr, &addr))
linux_regs->nip = addr;
atomic_set(&kgdb_cpu_doing_single_step, -1);
/* set the trace bit if we're stepping */
if (remcom_in_buffer[0] == 's') {
#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
mtspr(SPRN_DBCR0,
mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
linux_regs->msr |= MSR_DE;
#else
linux_regs->msr |= MSR_SE;
#endif
kgdb_single_step = 1;
if (kgdb_contthread)
atomic_set(&kgdb_cpu_doing_single_step,
raw_smp_processor_id());
}
return 0;
}
return -1;
}
/*
* Global data
*/
struct kgdb_arch arch_kgdb_ops = {
.gdb_bpt_instr = {0x7d, 0x82, 0x10, 0x08},
};
static int kgdb_not_implemented(struct pt_regs *regs)
{
return 0;
}
static void *old__debugger_ipi;
static void *old__debugger;
static void *old__debugger_bpt;
static void *old__debugger_sstep;
static void *old__debugger_iabr_match;
static void *old__debugger_dabr_match;
static void *old__debugger_fault_handler;
int kgdb_arch_init(void)
{
old__debugger_ipi = __debugger_ipi;
old__debugger = __debugger;
old__debugger_bpt = __debugger_bpt;
old__debugger_sstep = __debugger_sstep;
old__debugger_iabr_match = __debugger_iabr_match;
old__debugger_dabr_match = __debugger_dabr_match;
old__debugger_fault_handler = __debugger_fault_handler;
__debugger_ipi = kgdb_call_nmi_hook;
__debugger = kgdb_debugger;
__debugger_bpt = kgdb_handle_breakpoint;
__debugger_sstep = kgdb_singlestep;
__debugger_iabr_match = kgdb_iabr_match;
__debugger_dabr_match = kgdb_dabr_match;
__debugger_fault_handler = kgdb_not_implemented;
return 0;
}
void kgdb_arch_exit(void)
{
__debugger_ipi = old__debugger_ipi;
__debugger = old__debugger;
__debugger_bpt = old__debugger_bpt;
__debugger_sstep = old__debugger_sstep;
__debugger_iabr_match = old__debugger_iabr_match;
__debugger_dabr_match = old__debugger_dabr_match;
__debugger_fault_handler = old__debugger_fault_handler;
}

View File

@ -43,10 +43,6 @@
#define DBG(fmt...)
#if defined CONFIG_KGDB
#include <asm/kgdb.h>
#endif
extern void bootx_init(unsigned long r4, unsigned long phys);
int boot_cpuid;
@ -302,18 +298,6 @@ void __init setup_arch(char **cmdline_p)
xmon_setup();
#if defined(CONFIG_KGDB)
if (ppc_md.kgdb_map_scc)
ppc_md.kgdb_map_scc();
set_debug_traps();
if (strstr(cmd_line, "gdb")) {
if (ppc_md.progress)
ppc_md.progress("setup_arch: kgdb breakpoint", 0x4000);
printk("kgdb breakpoint activated\n");
breakpoint();
}
#endif
/*
* Set cache line size based on type of cpu as a default.
* Systems with OF can look in the properties on the cpu node(s)

View File

@ -97,8 +97,6 @@ extern struct machdep_calls pmac_md;
int sccdbg;
#endif
extern void zs_kgdb_hook(int tty_num);
sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;
EXPORT_SYMBOL(sys_ctrler);
@ -329,10 +327,6 @@ static void __init pmac_setup_arch(void)
l2cr_init();
#endif /* CONFIG_PPC32 */
#ifdef CONFIG_KGDB
zs_kgdb_hook(0);
#endif
find_via_cuda();
find_via_pmu();
smu_init();

View File

@ -30,7 +30,6 @@
static struct smc91x_platdata smc91x_info = {
.flags = SMC91X_USE_16BIT,
.irq_flags = IRQF_TRIGGER_HIGH,
};
static struct resource smc91x_eth_resources[] = {
@ -42,7 +41,7 @@ static struct resource smc91x_eth_resources[] = {
},
[1] = {
.start = 32, /* IRQ0 */
.flags = IORESOURCE_IRQ,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
},
};

View File

@ -45,12 +45,20 @@ typedef void (*exitcall_t)(void);
# define __section(S) __attribute__ ((__section__(#S)))
#endif
#if __GNUC__ == 3
#if __GNUC_MINOR__ >= 3
# define __used __attribute__((__used__))
#else
# define __used __attribute__((__unused__))
#endif
#else
#if __GNUC__ == 4
# define __used __attribute__((__used__))
#endif
#endif
#else
#include <linux/compiler.h>
#endif

View File

@ -15,6 +15,16 @@
#include <asm/irqflags.h>
#include <linux/linkage.h>
/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
#include <linux/elf-em.h>
#define AUDIT_ARCH_I386 (EM_386|__AUDIT_ARCH_LE)
#define __AUDIT_ARCH_LE 0x40000000
#ifndef CONFIG_AUDITSYSCALL
#define sysexit_audit int_ret_from_sys_call
#define sysretl_audit int_ret_from_sys_call
#endif
#define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8)
.macro IA32_ARG_FIXUP noebp=0
@ -148,13 +158,15 @@ ENTRY(ia32_sysenter_target)
ja ia32_badsys
sysenter_do_call:
IA32_ARG_FIXUP 1
sysenter_dispatch:
call *ia32_sys_call_table(,%rax,8)
movq %rax,RAX-ARGOFFSET(%rsp)
GET_THREAD_INFO(%r10)
DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF
testl $_TIF_ALLWORK_MASK,TI_flags(%r10)
jnz int_ret_from_sys_call
jnz sysexit_audit
sysexit_from_sys_call:
andl $~TS_COMPAT,TI_status(%r10)
/* clear IF, that popfq doesn't enable interrupts early */
andl $~0x200,EFLAGS-R11(%rsp)
@ -170,9 +182,63 @@ sysenter_do_call:
TRACE_IRQS_ON
ENABLE_INTERRUPTS_SYSEXIT32
sysenter_tracesys:
#ifdef CONFIG_AUDITSYSCALL
.macro auditsys_entry_common
movl %esi,%r9d /* 6th arg: 4th syscall arg */
movl %edx,%r8d /* 5th arg: 3rd syscall arg */
/* (already in %ecx) 4th arg: 2nd syscall arg */
movl %ebx,%edx /* 3rd arg: 1st syscall arg */
movl %eax,%esi /* 2nd arg: syscall number */
movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */
call audit_syscall_entry
movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */
cmpl $(IA32_NR_syscalls-1),%eax
ja ia32_badsys
movl %ebx,%edi /* reload 1st syscall arg */
movl RCX-ARGOFFSET(%rsp),%esi /* reload 2nd syscall arg */
movl RDX-ARGOFFSET(%rsp),%edx /* reload 3rd syscall arg */
movl RSI-ARGOFFSET(%rsp),%ecx /* reload 4th syscall arg */
movl RDI-ARGOFFSET(%rsp),%r8d /* reload 5th syscall arg */
.endm
.macro auditsys_exit exit
testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10)
jnz int_ret_from_sys_call
TRACE_IRQS_ON
sti
movl %eax,%esi /* second arg, syscall return value */
cmpl $0,%eax /* is it < 0? */
setl %al /* 1 if so, 0 if not */
movzbl %al,%edi /* zero-extend that into %edi */
inc %edi /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
call audit_syscall_exit
GET_THREAD_INFO(%r10)
movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall return value */
movl RBP-ARGOFFSET(%rsp),%ebp /* reload user register value */
movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
cli
TRACE_IRQS_OFF
testl %edi,TI_flags(%r10)
jnz int_with_check
jmp \exit
.endm
sysenter_auditsys:
CFI_RESTORE_STATE
auditsys_entry_common
movl %ebp,%r9d /* reload 6th syscall arg */
jmp sysenter_dispatch
sysexit_audit:
auditsys_exit sysexit_from_sys_call
#endif
sysenter_tracesys:
xchgl %r9d,%ebp
#ifdef CONFIG_AUDITSYSCALL
testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10)
jz sysenter_auditsys
#endif
SAVE_REST
CLEAR_RREGS
movq %r9,R9(%rsp)
@ -252,13 +318,15 @@ cstar_do_call:
cmpl $IA32_NR_syscalls-1,%eax
ja ia32_badsys
IA32_ARG_FIXUP 1
cstar_dispatch:
call *ia32_sys_call_table(,%rax,8)
movq %rax,RAX-ARGOFFSET(%rsp)
GET_THREAD_INFO(%r10)
DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF
testl $_TIF_ALLWORK_MASK,TI_flags(%r10)
jnz int_ret_from_sys_call
jnz sysretl_audit
sysretl_from_sys_call:
andl $~TS_COMPAT,TI_status(%r10)
RESTORE_ARGS 1,-ARG_SKIP,1,1,1
movl RIP-ARGOFFSET(%rsp),%ecx
@ -270,8 +338,23 @@ cstar_do_call:
CFI_RESTORE rsp
USERGS_SYSRET32
cstar_tracesys:
#ifdef CONFIG_AUDITSYSCALL
cstar_auditsys:
CFI_RESTORE_STATE
movl %r9d,R9-ARGOFFSET(%rsp) /* register to be clobbered by call */
auditsys_entry_common
movl R9-ARGOFFSET(%rsp),%r9d /* reload 6th syscall arg */
jmp cstar_dispatch
sysretl_audit:
auditsys_exit sysretl_from_sys_call
#endif
cstar_tracesys:
#ifdef CONFIG_AUDITSYSCALL
testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10)
jz cstar_auditsys
#endif
xchgl %r9d,%ebp
SAVE_REST
CLEAR_RREGS

View File

@ -73,6 +73,7 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu,
struct cpuinfo_x86 *c = &cpu_data(cpu);
cpumask_t saved_mask;
cpumask_of_cpu_ptr(new_mask, cpu);
int retval;
unsigned int eax, ebx, ecx, edx;
unsigned int edx_part;
@ -91,7 +92,7 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu,
/* Make sure we are running on right CPU */
saved_mask = current->cpus_allowed;
retval = set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
retval = set_cpus_allowed_ptr(current, new_mask);
if (retval)
return -1;

View File

@ -200,10 +200,12 @@ static void drv_read(struct drv_cmd *cmd)
static void drv_write(struct drv_cmd *cmd)
{
cpumask_t saved_mask = current->cpus_allowed;
cpumask_of_cpu_ptr_declare(cpu_mask);
unsigned int i;
for_each_cpu_mask(i, cmd->mask) {
set_cpus_allowed_ptr(current, &cpumask_of_cpu(i));
for_each_cpu_mask_nr(i, cmd->mask) {
cpumask_of_cpu_ptr_next(cpu_mask, i);
set_cpus_allowed_ptr(current, cpu_mask);
do_drv_write(cmd);
}
@ -267,11 +269,12 @@ static unsigned int get_measured_perf(unsigned int cpu)
} aperf_cur, mperf_cur;
cpumask_t saved_mask;
cpumask_of_cpu_ptr(cpu_mask, cpu);
unsigned int perf_percent;
unsigned int retval;
saved_mask = current->cpus_allowed;
set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
set_cpus_allowed_ptr(current, cpu_mask);
if (get_cpu() != cpu) {
/* We were not able to run on requested processor */
put_cpu();
@ -337,6 +340,7 @@ static unsigned int get_measured_perf(unsigned int cpu)
static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
{
cpumask_of_cpu_ptr(cpu_mask, cpu);
struct acpi_cpufreq_data *data = per_cpu(drv_data, cpu);
unsigned int freq;
unsigned int cached_freq;
@ -349,7 +353,7 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
}
cached_freq = data->freq_table[data->acpi_data->state].frequency;
freq = extract_freq(get_cur_val(&cpumask_of_cpu(cpu)), data);
freq = extract_freq(get_cur_val(cpu_mask), data);
if (freq != cached_freq) {
/*
* The dreaded BIOS frequency change behind our back.
@ -451,7 +455,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
freqs.old = perf->states[perf->state].core_frequency * 1000;
freqs.new = data->freq_table[next_state].frequency;
for_each_cpu_mask(i, cmd.mask) {
for_each_cpu_mask_nr(i, cmd.mask) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
}
@ -466,7 +470,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
}
}
for_each_cpu_mask(i, cmd.mask) {
for_each_cpu_mask_nr(i, cmd.mask) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}

View File

@ -122,7 +122,7 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy,
return 0;
/* notifiers */
for_each_cpu_mask(i, policy->cpus) {
for_each_cpu_mask_nr(i, policy->cpus) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
}
@ -130,11 +130,11 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy,
/* run on each logical CPU, see section 13.15.3 of IA32 Intel Architecture Software
* Developer's Manual, Volume 3
*/
for_each_cpu_mask(i, policy->cpus)
for_each_cpu_mask_nr(i, policy->cpus)
cpufreq_p4_setdc(i, p4clockmod_table[newstate].index);
/* notifiers */
for_each_cpu_mask(i, policy->cpus) {
for_each_cpu_mask_nr(i, policy->cpus) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}

View File

@ -479,11 +479,12 @@ static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvi
static int check_supported_cpu(unsigned int cpu)
{
cpumask_t oldmask;
cpumask_of_cpu_ptr(cpu_mask, cpu);
u32 eax, ebx, ecx, edx;
unsigned int rc = 0;
oldmask = current->cpus_allowed;
set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
set_cpus_allowed_ptr(current, cpu_mask);
if (smp_processor_id() != cpu) {
printk(KERN_ERR PFX "limiting to cpu %u failed\n", cpu);
@ -966,7 +967,7 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data, unsigned i
freqs.old = find_khz_freq_from_fid(data->currfid);
freqs.new = find_khz_freq_from_fid(fid);
for_each_cpu_mask(i, *(data->available_cores)) {
for_each_cpu_mask_nr(i, *(data->available_cores)) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
}
@ -974,7 +975,7 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data, unsigned i
res = transition_fid_vid(data, fid, vid);
freqs.new = find_khz_freq_from_fid(data->currfid);
for_each_cpu_mask(i, *(data->available_cores)) {
for_each_cpu_mask_nr(i, *(data->available_cores)) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
@ -997,7 +998,7 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned i
freqs.old = find_khz_freq_from_pstate(data->powernow_table, data->currpstate);
freqs.new = find_khz_freq_from_pstate(data->powernow_table, pstate);
for_each_cpu_mask(i, *(data->available_cores)) {
for_each_cpu_mask_nr(i, *(data->available_cores)) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
}
@ -1005,7 +1006,7 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned i
res = transition_pstate(data, pstate);
freqs.new = find_khz_freq_from_pstate(data->powernow_table, pstate);
for_each_cpu_mask(i, *(data->available_cores)) {
for_each_cpu_mask_nr(i, *(data->available_cores)) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
@ -1016,6 +1017,7 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned i
static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsigned relation)
{
cpumask_t oldmask;
cpumask_of_cpu_ptr(cpu_mask, pol->cpu);
struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
u32 checkfid;
u32 checkvid;
@ -1030,7 +1032,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
/* only run on specific CPU from here on */
oldmask = current->cpus_allowed;
set_cpus_allowed_ptr(current, &cpumask_of_cpu(pol->cpu));
set_cpus_allowed_ptr(current, cpu_mask);
if (smp_processor_id() != pol->cpu) {
printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
@ -1105,6 +1107,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
{
struct powernow_k8_data *data;
cpumask_t oldmask;
cpumask_of_cpu_ptr_declare(newmask);
int rc;
if (!cpu_online(pol->cpu))
@ -1156,7 +1159,8 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
/* only run on specific CPU from here on */
oldmask = current->cpus_allowed;
set_cpus_allowed_ptr(current, &cpumask_of_cpu(pol->cpu));
cpumask_of_cpu_ptr_next(newmask, pol->cpu);
set_cpus_allowed_ptr(current, newmask);
if (smp_processor_id() != pol->cpu) {
printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
@ -1178,7 +1182,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
set_cpus_allowed_ptr(current, &oldmask);
if (cpu_family == CPU_HW_PSTATE)
pol->cpus = cpumask_of_cpu(pol->cpu);
pol->cpus = *newmask;
else
pol->cpus = per_cpu(cpu_core_map, pol->cpu);
data->available_cores = &(pol->cpus);
@ -1244,6 +1248,7 @@ static unsigned int powernowk8_get (unsigned int cpu)
{
struct powernow_k8_data *data;
cpumask_t oldmask = current->cpus_allowed;
cpumask_of_cpu_ptr(newmask, cpu);
unsigned int khz = 0;
unsigned int first;
@ -1253,7 +1258,7 @@ static unsigned int powernowk8_get (unsigned int cpu)
if (!data)
return -EINVAL;
set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
set_cpus_allowed_ptr(current, newmask);
if (smp_processor_id() != cpu) {
printk(KERN_ERR PFX
"limiting to CPU %d failed in powernowk8_get\n", cpu);

View File

@ -28,7 +28,8 @@
#define PFX "speedstep-centrino: "
#define MAINTAINER "cpufreq@lists.linux.org.uk"
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-centrino", msg)
#define dprintk(msg...) \
cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-centrino", msg)
#define INTEL_MSR_RANGE (0xffff)
@ -66,11 +67,12 @@ struct cpu_model
struct cpufreq_frequency_table *op_points; /* clock/voltage pairs */
};
static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x);
static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c,
const struct cpu_id *x);
/* Operating points for current CPU */
static struct cpu_model *centrino_model[NR_CPUS];
static const struct cpu_id *centrino_cpu[NR_CPUS];
static DEFINE_PER_CPU(struct cpu_model *, centrino_model);
static DEFINE_PER_CPU(const struct cpu_id *, centrino_cpu);
static struct cpufreq_driver centrino_driver;
@ -255,7 +257,7 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
return -ENOENT;
}
centrino_model[policy->cpu] = model;
per_cpu(centrino_model, policy->cpu) = model;
dprintk("found \"%s\": max frequency: %dkHz\n",
model->model_name, model->max_freq);
@ -264,10 +266,14 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
}
#else
static inline int centrino_cpu_init_table(struct cpufreq_policy *policy) { return -ENODEV; }
static inline int centrino_cpu_init_table(struct cpufreq_policy *policy)
{
return -ENODEV;
}
#endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE */
static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x)
static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c,
const struct cpu_id *x)
{
if ((c->x86 == x->x86) &&
(c->x86_model == x->x86_model) &&
@ -286,23 +292,28 @@ static unsigned extract_clock(unsigned msr, unsigned int cpu, int failsafe)
* for centrino, as some DSDTs are buggy.
* Ideally, this can be done using the acpi_data structure.
*/
if ((centrino_cpu[cpu] == &cpu_ids[CPU_BANIAS]) ||
(centrino_cpu[cpu] == &cpu_ids[CPU_DOTHAN_A1]) ||
(centrino_cpu[cpu] == &cpu_ids[CPU_DOTHAN_B0])) {
if ((per_cpu(centrino_cpu, cpu) == &cpu_ids[CPU_BANIAS]) ||
(per_cpu(centrino_cpu, cpu) == &cpu_ids[CPU_DOTHAN_A1]) ||
(per_cpu(centrino_cpu, cpu) == &cpu_ids[CPU_DOTHAN_B0])) {
msr = (msr >> 8) & 0xff;
return msr * 100000;
}
if ((!centrino_model[cpu]) || (!centrino_model[cpu]->op_points))
if ((!per_cpu(centrino_model, cpu)) ||
(!per_cpu(centrino_model, cpu)->op_points))
return 0;
msr &= 0xffff;
for (i=0;centrino_model[cpu]->op_points[i].frequency != CPUFREQ_TABLE_END; i++) {
if (msr == centrino_model[cpu]->op_points[i].index)
return centrino_model[cpu]->op_points[i].frequency;
for (i = 0;
per_cpu(centrino_model, cpu)->op_points[i].frequency
!= CPUFREQ_TABLE_END;
i++) {
if (msr == per_cpu(centrino_model, cpu)->op_points[i].index)
return per_cpu(centrino_model, cpu)->
op_points[i].frequency;
}
if (failsafe)
return centrino_model[cpu]->op_points[i-1].frequency;
return per_cpu(centrino_model, cpu)->op_points[i-1].frequency;
else
return 0;
}
@ -313,9 +324,10 @@ static unsigned int get_cur_freq(unsigned int cpu)
unsigned l, h;
unsigned clock_freq;
cpumask_t saved_mask;
cpumask_of_cpu_ptr(new_mask, cpu);
saved_mask = current->cpus_allowed;
set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
set_cpus_allowed_ptr(current, new_mask);
if (smp_processor_id() != cpu)
return 0;
@ -347,7 +359,8 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
int i;
/* Only Intel makes Enhanced Speedstep-capable CPUs */
if (cpu->x86_vendor != X86_VENDOR_INTEL || !cpu_has(cpu, X86_FEATURE_EST))
if (cpu->x86_vendor != X86_VENDOR_INTEL ||
!cpu_has(cpu, X86_FEATURE_EST))
return -ENODEV;
if (cpu_has(cpu, X86_FEATURE_CONSTANT_TSC))
@ -361,9 +374,9 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
break;
if (i != N_IDS)
centrino_cpu[policy->cpu] = &cpu_ids[i];
per_cpu(centrino_cpu, policy->cpu) = &cpu_ids[i];
if (!centrino_cpu[policy->cpu]) {
if (!per_cpu(centrino_cpu, policy->cpu)) {
dprintk("found unsupported CPU with "
"Enhanced SpeedStep: send /proc/cpuinfo to "
MAINTAINER "\n");
@ -386,23 +399,26 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
/* check to see if it stuck */
rdmsr(MSR_IA32_MISC_ENABLE, l, h);
if (!(l & (1<<16))) {
printk(KERN_INFO PFX "couldn't enable Enhanced SpeedStep\n");
printk(KERN_INFO PFX
"couldn't enable Enhanced SpeedStep\n");
return -ENODEV;
}
}
freq = get_cur_freq(policy->cpu);
policy->cpuinfo.transition_latency = 10000; /* 10uS transition latency */
policy->cpuinfo.transition_latency = 10000;
/* 10uS transition latency */
policy->cur = freq;
dprintk("centrino_cpu_init: cur=%dkHz\n", policy->cur);
ret = cpufreq_frequency_table_cpuinfo(policy, centrino_model[policy->cpu]->op_points);
ret = cpufreq_frequency_table_cpuinfo(policy,
per_cpu(centrino_model, policy->cpu)->op_points);
if (ret)
return (ret);
cpufreq_frequency_table_get_attr(centrino_model[policy->cpu]->op_points, policy->cpu);
cpufreq_frequency_table_get_attr(
per_cpu(centrino_model, policy->cpu)->op_points, policy->cpu);
return 0;
}
@ -411,12 +427,12 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy)
{
unsigned int cpu = policy->cpu;
if (!centrino_model[cpu])
if (!per_cpu(centrino_model, cpu))
return -ENODEV;
cpufreq_frequency_table_put_attr(cpu);
centrino_model[cpu] = NULL;
per_cpu(centrino_model, cpu) = NULL;
return 0;
}
@ -430,17 +446,26 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy)
*/
static int centrino_verify (struct cpufreq_policy *policy)
{
return cpufreq_frequency_table_verify(policy, centrino_model[policy->cpu]->op_points);
return cpufreq_frequency_table_verify(policy,
per_cpu(centrino_model, policy->cpu)->op_points);
}
/**
* centrino_setpolicy - set a new CPUFreq policy
* @policy: new policy
* @target_freq: the target frequency
* @relation: how that frequency relates to achieved frequency (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H)
* @relation: how that frequency relates to achieved frequency
* (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H)
*
* Sets a new CPUFreq policy.
*/
struct allmasks {
cpumask_t online_policy_cpus;
cpumask_t saved_mask;
cpumask_t set_mask;
cpumask_t covered_cpus;
};
static int centrino_target (struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
@ -448,48 +473,55 @@ static int centrino_target (struct cpufreq_policy *policy,
unsigned int newstate = 0;
unsigned int msr, oldmsr = 0, h = 0, cpu = policy->cpu;
struct cpufreq_freqs freqs;
cpumask_t online_policy_cpus;
cpumask_t saved_mask;
cpumask_t set_mask;
cpumask_t covered_cpus;
int retval = 0;
unsigned int j, k, first_cpu, tmp;
CPUMASK_ALLOC(allmasks);
CPUMASK_PTR(online_policy_cpus, allmasks);
CPUMASK_PTR(saved_mask, allmasks);
CPUMASK_PTR(set_mask, allmasks);
CPUMASK_PTR(covered_cpus, allmasks);
if (unlikely(centrino_model[cpu] == NULL))
return -ENODEV;
if (unlikely(allmasks == NULL))
return -ENOMEM;
if (unlikely(per_cpu(centrino_model, cpu) == NULL)) {
retval = -ENODEV;
goto out;
}
if (unlikely(cpufreq_frequency_table_target(policy,
centrino_model[cpu]->op_points,
per_cpu(centrino_model, cpu)->op_points,
target_freq,
relation,
&newstate))) {
return -EINVAL;
retval = -EINVAL;
goto out;
}
#ifdef CONFIG_HOTPLUG_CPU
/* cpufreq holds the hotplug lock, so we are safe from here on */
cpus_and(online_policy_cpus, cpu_online_map, policy->cpus);
cpus_and(*online_policy_cpus, cpu_online_map, policy->cpus);
#else
online_policy_cpus = policy->cpus;
*online_policy_cpus = policy->cpus;
#endif
saved_mask = current->cpus_allowed;
*saved_mask = current->cpus_allowed;
first_cpu = 1;
cpus_clear(covered_cpus);
for_each_cpu_mask(j, online_policy_cpus) {
cpus_clear(*covered_cpus);
for_each_cpu_mask_nr(j, *online_policy_cpus) {
/*
* Support for SMP systems.
* Make sure we are running on CPU that wants to change freq
*/
cpus_clear(set_mask);
cpus_clear(*set_mask);
if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
cpus_or(set_mask, set_mask, online_policy_cpus);
cpus_or(*set_mask, *set_mask, *online_policy_cpus);
else
cpu_set(j, set_mask);
cpu_set(j, *set_mask);
set_cpus_allowed_ptr(current, &set_mask);
set_cpus_allowed_ptr(current, set_mask);
preempt_disable();
if (unlikely(!cpu_isset(smp_processor_id(), set_mask))) {
if (unlikely(!cpu_isset(smp_processor_id(), *set_mask))) {
dprintk("couldn't limit to CPUs in this domain\n");
retval = -EAGAIN;
if (first_cpu) {
@ -500,7 +532,7 @@ static int centrino_target (struct cpufreq_policy *policy,
break;
}
msr = centrino_model[cpu]->op_points[newstate].index;
msr = per_cpu(centrino_model, cpu)->op_points[newstate].index;
if (first_cpu) {
rdmsr(MSR_IA32_PERF_CTL, oldmsr, h);
@ -517,7 +549,7 @@ static int centrino_target (struct cpufreq_policy *policy,
dprintk("target=%dkHz old=%d new=%d msr=%04x\n",
target_freq, freqs.old, freqs.new, msr);
for_each_cpu_mask(k, online_policy_cpus) {
for_each_cpu_mask_nr(k, *online_policy_cpus) {
freqs.cpu = k;
cpufreq_notify_transition(&freqs,
CPUFREQ_PRECHANGE);
@ -536,11 +568,11 @@ static int centrino_target (struct cpufreq_policy *policy,
break;
}
cpu_set(j, covered_cpus);
cpu_set(j, *covered_cpus);
preempt_enable();
}
for_each_cpu_mask(k, online_policy_cpus) {
for_each_cpu_mask_nr(k, *online_policy_cpus) {
freqs.cpu = k;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
@ -553,10 +585,12 @@ static int centrino_target (struct cpufreq_policy *policy,
* Best effort undo..
*/
if (!cpus_empty(covered_cpus)) {
for_each_cpu_mask(j, covered_cpus) {
set_cpus_allowed_ptr(current,
&cpumask_of_cpu(j));
if (!cpus_empty(*covered_cpus)) {
cpumask_of_cpu_ptr_declare(new_mask);
for_each_cpu_mask_nr(j, *covered_cpus) {
cpumask_of_cpu_ptr_next(new_mask, j);
set_cpus_allowed_ptr(current, new_mask);
wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
}
}
@ -564,19 +598,22 @@ static int centrino_target (struct cpufreq_policy *policy,
tmp = freqs.new;
freqs.new = freqs.old;
freqs.old = tmp;
for_each_cpu_mask(j, online_policy_cpus) {
for_each_cpu_mask_nr(j, *online_policy_cpus) {
freqs.cpu = j;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
}
set_cpus_allowed_ptr(current, &saved_mask);
return 0;
set_cpus_allowed_ptr(current, saved_mask);
retval = 0;
goto out;
migrate_end:
preempt_enable();
set_cpus_allowed_ptr(current, &saved_mask);
return 0;
set_cpus_allowed_ptr(current, saved_mask);
out:
CPUMASK_FREE(allmasks);
return retval;
}
static struct freq_attr* centrino_attr[] = {

View File

@ -244,7 +244,8 @@ static unsigned int _speedstep_get(const cpumask_t *cpus)
static unsigned int speedstep_get(unsigned int cpu)
{
return _speedstep_get(&cpumask_of_cpu(cpu));
cpumask_of_cpu_ptr(newmask, cpu);
return _speedstep_get(newmask);
}
/**
@ -279,7 +280,7 @@ static int speedstep_target (struct cpufreq_policy *policy,
cpus_allowed = current->cpus_allowed;
for_each_cpu_mask(i, policy->cpus) {
for_each_cpu_mask_nr(i, policy->cpus) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
}
@ -292,7 +293,7 @@ static int speedstep_target (struct cpufreq_policy *policy,
/* allow to be run on all CPUs */
set_cpus_allowed_ptr(current, &cpus_allowed);
for_each_cpu_mask(i, policy->cpus) {
for_each_cpu_mask_nr(i, policy->cpus) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}

View File

@ -489,7 +489,7 @@ static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index)
int sibling;
this_leaf = CPUID4_INFO_IDX(cpu, index);
for_each_cpu_mask(sibling, this_leaf->shared_cpu_map) {
for_each_cpu_mask_nr(sibling, this_leaf->shared_cpu_map) {
sibling_leaf = CPUID4_INFO_IDX(sibling, index);
cpu_clear(cpu, sibling_leaf->shared_cpu_map);
}
@ -516,6 +516,7 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu)
unsigned long j;
int retval;
cpumask_t oldmask;
cpumask_of_cpu_ptr(newmask, cpu);
if (num_cache_leaves == 0)
return -ENOENT;
@ -526,7 +527,7 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu)
return -ENOMEM;
oldmask = current->cpus_allowed;
retval = set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
retval = set_cpus_allowed_ptr(current, newmask);
if (retval)
goto out;

View File

@ -580,7 +580,7 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize,
char __user *buf = ubuf;
int i, err;
cpu_tsc = kmalloc(NR_CPUS * sizeof(long), GFP_KERNEL);
cpu_tsc = kmalloc(nr_cpu_ids * sizeof(long), GFP_KERNEL);
if (!cpu_tsc)
return -ENOMEM;

View File

@ -527,7 +527,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
if (err)
goto out_free;
for_each_cpu_mask(i, b->cpus) {
for_each_cpu_mask_nr(i, b->cpus) {
if (i == cpu)
continue;
@ -617,7 +617,7 @@ static void threshold_remove_bank(unsigned int cpu, int bank)
#endif
/* remove all sibling symlinks before unregistering */
for_each_cpu_mask(i, b->cpus) {
for_each_cpu_mask_nr(i, b->cpus) {
if (i == cpu)
continue;

View File

@ -160,7 +160,7 @@ static void *c_start(struct seq_file *m, loff_t *pos)
{
if (*pos == 0) /* just in case, cpu 0 is not the first */
*pos = first_cpu(cpu_online_map);
if ((*pos) < NR_CPUS && cpu_online(*pos))
if ((*pos) < nr_cpu_ids && cpu_online(*pos))
return &cpu_data(*pos);
return NULL;
}

View File

@ -54,6 +54,16 @@
#include <asm/ftrace.h>
#include <asm/irq_vectors.h>
/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
#include <linux/elf-em.h>
#define AUDIT_ARCH_I386 (EM_386|__AUDIT_ARCH_LE)
#define __AUDIT_ARCH_LE 0x40000000
#ifndef CONFIG_AUDITSYSCALL
#define sysenter_audit syscall_trace_entry
#define sysexit_audit syscall_exit_work
#endif
/*
* We use macros for low-level operations which need to be overridden
* for paravirtualization. The following will never clobber any registers:
@ -333,7 +343,8 @@ sysenter_past_esp:
/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
jnz syscall_trace_entry
jnz sysenter_audit
sysenter_do_call:
cmpl $(nr_syscalls), %eax
jae syscall_badsys
call *sys_call_table(,%eax,4)
@ -343,7 +354,8 @@ sysenter_past_esp:
TRACE_IRQS_OFF
movl TI_flags(%ebp), %ecx
testw $_TIF_ALLWORK_MASK, %cx
jne syscall_exit_work
jne sysexit_audit
sysenter_exit:
/* if something modifies registers it must also disable sysexit */
movl PT_EIP(%esp), %edx
movl PT_OLDESP(%esp), %ecx
@ -351,6 +363,45 @@ sysenter_past_esp:
TRACE_IRQS_ON
1: mov PT_FS(%esp), %fs
ENABLE_INTERRUPTS_SYSEXIT
#ifdef CONFIG_AUDITSYSCALL
sysenter_audit:
testw $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
jnz syscall_trace_entry
addl $4,%esp
CFI_ADJUST_CFA_OFFSET -4
/* %esi already in 8(%esp) 6th arg: 4th syscall arg */
/* %edx already in 4(%esp) 5th arg: 3rd syscall arg */
/* %ecx already in 0(%esp) 4th arg: 2nd syscall arg */
movl %ebx,%ecx /* 3rd arg: 1st syscall arg */
movl %eax,%edx /* 2nd arg: syscall number */
movl $AUDIT_ARCH_I386,%eax /* 1st arg: audit arch */
call audit_syscall_entry
pushl %ebx
CFI_ADJUST_CFA_OFFSET 4
movl PT_EAX(%esp),%eax /* reload syscall number */
jmp sysenter_do_call
sysexit_audit:
testw $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %cx
jne syscall_exit_work
TRACE_IRQS_ON
ENABLE_INTERRUPTS(CLBR_ANY)
movl %eax,%edx /* second arg, syscall return value */
cmpl $0,%eax /* is it < 0? */
setl %al /* 1 if so, 0 if not */
movzbl %al,%eax /* zero-extend that */
inc %eax /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
call audit_syscall_exit
DISABLE_INTERRUPTS(CLBR_ANY)
TRACE_IRQS_OFF
movl TI_flags(%ebp), %ecx
testw $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %cx
jne syscall_exit_work
movl PT_EAX(%esp),%eax /* reload syscall return value */
jmp sysenter_exit
#endif
CFI_ENDPROC
.pushsection .fixup,"ax"
2: movl $0,PT_FS(%esp)

View File

@ -53,6 +53,12 @@
#include <asm/paravirt.h>
#include <asm/ftrace.h>
/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
#include <linux/elf-em.h>
#define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
#define __AUDIT_ARCH_64BIT 0x80000000
#define __AUDIT_ARCH_LE 0x40000000
.code64
#ifdef CONFIG_FTRACE
@ -351,6 +357,7 @@ ENTRY(system_call_after_swapgs)
GET_THREAD_INFO(%rcx)
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%rcx)
jnz tracesys
system_call_fastpath:
cmpq $__NR_syscall_max,%rax
ja badsys
movq %r10,%rcx
@ -402,16 +409,16 @@ sysret_careful:
sysret_signal:
TRACE_IRQS_ON
ENABLE_INTERRUPTS(CLBR_NONE)
testl $_TIF_DO_NOTIFY_MASK,%edx
jz 1f
/* Really a signal */
#ifdef CONFIG_AUDITSYSCALL
bt $TIF_SYSCALL_AUDIT,%edx
jc sysret_audit
#endif
/* edx: work flags (arg3) */
leaq do_notify_resume(%rip),%rax
leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
xorl %esi,%esi # oldset -> arg2
call ptregscall_common
1: movl $_TIF_WORK_MASK,%edi
movl $_TIF_WORK_MASK,%edi
/* Use IRET because user could have changed frame. This
works because ptregscall_common has called FIXUP_TOP_OF_STACK. */
DISABLE_INTERRUPTS(CLBR_NONE)
@ -422,8 +429,45 @@ badsys:
movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
jmp ret_from_sys_call
#ifdef CONFIG_AUDITSYSCALL
/*
* Fast path for syscall audit without full syscall trace.
* We just call audit_syscall_entry() directly, and then
* jump back to the normal fast path.
*/
auditsys:
movq %r10,%r9 /* 6th arg: 4th syscall arg */
movq %rdx,%r8 /* 5th arg: 3rd syscall arg */
movq %rsi,%rcx /* 4th arg: 2nd syscall arg */
movq %rdi,%rdx /* 3rd arg: 1st syscall arg */
movq %rax,%rsi /* 2nd arg: syscall number */
movl $AUDIT_ARCH_X86_64,%edi /* 1st arg: audit arch */
call audit_syscall_entry
LOAD_ARGS 0 /* reload call-clobbered registers */
jmp system_call_fastpath
/*
* Return fast path for syscall audit. Call audit_syscall_exit()
* directly and then jump back to the fast path with TIF_SYSCALL_AUDIT
* masked off.
*/
sysret_audit:
movq %rax,%rsi /* second arg, syscall return value */
cmpq $0,%rax /* is it < 0? */
setl %al /* 1 if so, 0 if not */
movzbl %al,%edi /* zero-extend that into %edi */
inc %edi /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
call audit_syscall_exit
movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
jmp sysret_check
#endif /* CONFIG_AUDITSYSCALL */
/* Do syscall tracing */
tracesys:
#ifdef CONFIG_AUDITSYSCALL
testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%rcx)
jz auditsys
#endif
SAVE_REST
movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
FIXUP_TOP_OF_STACK %rdi
@ -448,6 +492,7 @@ tracesys:
* Has correct top of stack, but partial stack frame.
*/
.globl int_ret_from_sys_call
.globl int_with_check
int_ret_from_sys_call:
DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF

View File

@ -168,7 +168,7 @@ static unsigned int physflat_cpu_mask_to_apicid(cpumask_t cpumask)
* May as well be the first.
*/
cpu = first_cpu(cpumask);
if ((unsigned)cpu < NR_CPUS)
if ((unsigned)cpu < nr_cpu_ids)
return per_cpu(x86_cpu_to_apicid, cpu);
else
return BAD_APICID;

View File

@ -98,7 +98,7 @@ static void uv_send_IPI_mask(cpumask_t mask, int vector)
{
unsigned int cpu;
for (cpu = 0; cpu < NR_CPUS; ++cpu)
for_each_possible_cpu(cpu)
if (cpu_isset(cpu, mask))
uv_send_IPI_one(cpu, vector);
}
@ -132,7 +132,7 @@ static unsigned int uv_cpu_mask_to_apicid(cpumask_t cpumask)
* May as well be the first.
*/
cpu = first_cpu(cpumask);
if ((unsigned)cpu < NR_CPUS)
if ((unsigned)cpu < nr_cpu_ids)
return per_cpu(x86_cpu_to_apicid, cpu);
else
return BAD_APICID;

View File

@ -732,7 +732,7 @@ static int __assign_irq_vector(int irq, cpumask_t mask)
return 0;
}
for_each_cpu_mask(cpu, mask) {
for_each_cpu_mask_nr(cpu, mask) {
cpumask_t domain, new_mask;
int new_cpu;
int vector, offset;
@ -753,7 +753,7 @@ static int __assign_irq_vector(int irq, cpumask_t mask)
continue;
if (vector == IA32_SYSCALL_VECTOR)
goto next;
for_each_cpu_mask(new_cpu, new_mask)
for_each_cpu_mask_nr(new_cpu, new_mask)
if (per_cpu(vector_irq, new_cpu)[vector] != -1)
goto next;
/* Found one! */
@ -763,7 +763,7 @@ static int __assign_irq_vector(int irq, cpumask_t mask)
cfg->move_in_progress = 1;
cfg->old_domain = cfg->domain;
}
for_each_cpu_mask(new_cpu, new_mask)
for_each_cpu_mask_nr(new_cpu, new_mask)
per_cpu(vector_irq, new_cpu)[vector] = irq;
cfg->vector = vector;
cfg->domain = domain;
@ -795,7 +795,7 @@ static void __clear_irq_vector(int irq)
vector = cfg->vector;
cpus_and(mask, cfg->domain, cpu_online_map);
for_each_cpu_mask(cpu, mask)
for_each_cpu_mask_nr(cpu, mask)
per_cpu(vector_irq, cpu)[vector] = -1;
cfg->vector = 0;
@ -1373,12 +1373,10 @@ static unsigned int startup_ioapic_irq(unsigned int irq)
static int ioapic_retrigger_irq(unsigned int irq)
{
struct irq_cfg *cfg = &irq_cfg[irq];
cpumask_t mask;
unsigned long flags;
spin_lock_irqsave(&vector_lock, flags);
mask = cpumask_of_cpu(first_cpu(cfg->domain));
send_IPI_mask(mask, cfg->vector);
send_IPI_mask(cpumask_of_cpu(first_cpu(cfg->domain)), cfg->vector);
spin_unlock_irqrestore(&vector_lock, flags);
return 1;

View File

@ -62,12 +62,12 @@ static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
if (reload) {
#ifdef CONFIG_SMP
cpumask_t mask;
cpumask_of_cpu_ptr_declare(mask);
preempt_disable();
load_LDT(pc);
mask = cpumask_of_cpu(smp_processor_id());
if (!cpus_equal(current->mm->cpu_vm_mask, mask))
cpumask_of_cpu_ptr_next(mask, smp_processor_id());
if (!cpus_equal(current->mm->cpu_vm_mask, *mask))
smp_call_function(flush_ldt, current->mm, 1);
preempt_enable();
#else

View File

@ -388,6 +388,7 @@ static int do_microcode_update (void)
void *new_mc = NULL;
int cpu;
cpumask_t old;
cpumask_of_cpu_ptr_declare(newmask);
old = current->cpus_allowed;
@ -404,7 +405,8 @@ static int do_microcode_update (void)
if (!uci->valid)
continue;
set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
cpumask_of_cpu_ptr_next(newmask, cpu);
set_cpus_allowed_ptr(current, newmask);
error = get_maching_microcode(new_mc, cpu);
if (error < 0)
goto out;
@ -574,6 +576,7 @@ static int apply_microcode_check_cpu(int cpu)
struct cpuinfo_x86 *c = &cpu_data(cpu);
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
cpumask_t old;
cpumask_of_cpu_ptr(newmask, cpu);
unsigned int val[2];
int err = 0;
@ -582,7 +585,7 @@ static int apply_microcode_check_cpu(int cpu)
return 0;
old = current->cpus_allowed;
set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
set_cpus_allowed_ptr(current, newmask);
/* Check if the microcode we have in memory matches the CPU */
if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
@ -620,11 +623,12 @@ static int apply_microcode_check_cpu(int cpu)
static void microcode_init_cpu(int cpu, int resume)
{
cpumask_t old;
cpumask_of_cpu_ptr(newmask, cpu);
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
old = current->cpus_allowed;
set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
set_cpus_allowed_ptr(current, newmask);
mutex_lock(&microcode_mutex);
collect_cpu_info(cpu);
if (uci->valid && system_state == SYSTEM_RUNNING && !resume)
@ -658,11 +662,12 @@ static ssize_t reload_store(struct sys_device *dev,
return -EINVAL;
if (val == 1) {
cpumask_t old;
cpumask_of_cpu_ptr(newmask, cpu);
old = current->cpus_allowed;
get_online_cpus();
set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
set_cpus_allowed_ptr(current, newmask);
mutex_lock(&microcode_mutex);
if (uci->valid)

View File

@ -411,24 +411,28 @@ void native_machine_shutdown(void)
{
/* Stop the cpus and apics */
#ifdef CONFIG_SMP
int reboot_cpu_id;
/* The boot cpu is always logical cpu 0 */
reboot_cpu_id = 0;
int reboot_cpu_id = 0;
cpumask_of_cpu_ptr(newmask, reboot_cpu_id);
#ifdef CONFIG_X86_32
/* See if there has been given a command line override */
if ((reboot_cpu != -1) && (reboot_cpu < NR_CPUS) &&
cpu_online(reboot_cpu))
cpu_online(reboot_cpu)) {
reboot_cpu_id = reboot_cpu;
cpumask_of_cpu_ptr_next(newmask, reboot_cpu_id);
}
#endif
/* Make certain the cpu I'm about to reboot on is online */
if (!cpu_online(reboot_cpu_id))
if (!cpu_online(reboot_cpu_id)) {
reboot_cpu_id = smp_processor_id();
cpumask_of_cpu_ptr_next(newmask, reboot_cpu_id);
}
/* Make certain I only run on the appropriate processor */
set_cpus_allowed_ptr(current, &cpumask_of_cpu(reboot_cpu_id));
set_cpus_allowed_ptr(current, newmask);
/* O.K Now that I'm on the appropriate processor,
* stop all of the others.

View File

@ -661,8 +661,5 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs);
if (thread_info_flags & _TIF_HRTICK_RESCHED)
hrtick_resched();
clear_thread_flag(TIF_IRET);
}

View File

@ -496,9 +496,6 @@ void do_notify_resume(struct pt_regs *regs, void *unused,
/* deal with pending signal delivery */
if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs);
if (thread_info_flags & _TIF_HRTICK_RESCHED)
hrtick_resched();
}
void signal_fault(struct pt_regs *regs, void __user *frame, char *where)

View File

@ -438,7 +438,7 @@ void __cpuinit set_cpu_sibling_map(int cpu)
cpu_set(cpu, cpu_sibling_setup_map);
if (smp_num_siblings > 1) {
for_each_cpu_mask(i, cpu_sibling_setup_map) {
for_each_cpu_mask_nr(i, cpu_sibling_setup_map) {
if (c->phys_proc_id == cpu_data(i).phys_proc_id &&
c->cpu_core_id == cpu_data(i).cpu_core_id) {
cpu_set(i, per_cpu(cpu_sibling_map, cpu));
@ -461,7 +461,7 @@ void __cpuinit set_cpu_sibling_map(int cpu)
return;
}
for_each_cpu_mask(i, cpu_sibling_setup_map) {
for_each_cpu_mask_nr(i, cpu_sibling_setup_map) {
if (per_cpu(cpu_llc_id, cpu) != BAD_APICID &&
per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) {
cpu_set(i, c->llc_shared_map);
@ -1219,7 +1219,7 @@ static void remove_siblinginfo(int cpu)
int sibling;
struct cpuinfo_x86 *c = &cpu_data(cpu);
for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) {
for_each_cpu_mask_nr(sibling, per_cpu(cpu_core_map, cpu)) {
cpu_clear(cpu, per_cpu(cpu_core_map, sibling));
/*/
* last thread sibling in this cpu core going down
@ -1228,7 +1228,7 @@ static void remove_siblinginfo(int cpu)
cpu_data(sibling).booted_cores--;
}
for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu))
for_each_cpu_mask_nr(sibling, per_cpu(cpu_sibling_map, cpu))
cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling));
cpus_clear(per_cpu(cpu_sibling_map, cpu));
cpus_clear(per_cpu(cpu_core_map, cpu));

View File

@ -367,7 +367,7 @@ static void xen_send_IPI_mask(cpumask_t mask, enum ipi_vector vector)
cpus_and(mask, mask, cpu_online_map);
for_each_cpu_mask(cpu, mask)
for_each_cpu_mask_nr(cpu, mask)
xen_send_IPI_one(cpu, vector);
}
@ -378,7 +378,7 @@ static void xen_smp_send_call_function_ipi(cpumask_t mask)
xen_send_IPI_mask(mask, XEN_CALL_FUNCTION_VECTOR);
/* Make sure other vcpus get a chance to run if they need to. */
for_each_cpu_mask(cpu, mask) {
for_each_cpu_mask_nr(cpu, mask) {
if (xen_vcpu_stolen(cpu)) {
HYPERVISOR_sched_op(SCHEDOP_yield, 0);
break;

View File

@ -73,15 +73,7 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
pr_debug("%s: (sync) len: %zu\n", __func__, len);
/* wait for any prerequisite operations */
if (depend_tx) {
/* if ack is already set then we cannot be sure
* we are referring to the correct operation
*/
BUG_ON(async_tx_test_ack(depend_tx));
if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
panic("%s: DMA_ERROR waiting for depend_tx\n",
__func__);
}
async_tx_quiesce(&depend_tx);
dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset;
src_buf = kmap_atomic(src, KM_USER1) + src_offset;
@ -91,7 +83,7 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
kunmap_atomic(dest_buf, KM_USER0);
kunmap_atomic(src_buf, KM_USER1);
async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
async_tx_sync_epilog(cb_fn, cb_param);
}
return tx;

View File

@ -72,19 +72,11 @@ async_memset(struct page *dest, int val, unsigned int offset,
dest_buf = (void *) (((char *) page_address(dest)) + offset);
/* wait for any prerequisite operations */
if (depend_tx) {
/* if ack is already set then we cannot be sure
* we are referring to the correct operation
*/
BUG_ON(depend_tx->ack);
if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
panic("%s: DMA_ERROR waiting for depend_tx\n",
__func__);
}
async_tx_quiesce(&depend_tx);
memset(dest_buf, val, len);
async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
async_tx_sync_epilog(cb_fn, cb_param);
}
return tx;

View File

@ -295,7 +295,7 @@ dma_channel_add_remove(struct dma_client *client,
case DMA_RESOURCE_REMOVED:
found = 0;
spin_lock_irqsave(&async_tx_lock, flags);
list_for_each_entry_rcu(ref, &async_tx_master_list, node)
list_for_each_entry(ref, &async_tx_master_list, node)
if (ref->chan == chan) {
/* permit backing devices to go away */
dma_chan_put(ref->chan);
@ -608,23 +608,34 @@ async_trigger_callback(enum async_tx_flags flags,
pr_debug("%s: (sync)\n", __func__);
/* wait for any prerequisite operations */
if (depend_tx) {
/* if ack is already set then we cannot be sure
* we are referring to the correct operation
*/
BUG_ON(async_tx_test_ack(depend_tx));
if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
panic("%s: DMA_ERROR waiting for depend_tx\n",
__func__);
}
async_tx_quiesce(&depend_tx);
async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
async_tx_sync_epilog(cb_fn, cb_param);
}
return tx;
}
EXPORT_SYMBOL_GPL(async_trigger_callback);
/**
* async_tx_quiesce - ensure tx is complete and freeable upon return
* @tx - transaction to quiesce
*/
void async_tx_quiesce(struct dma_async_tx_descriptor **tx)
{
if (*tx) {
/* if ack is already set then we cannot be sure
* we are referring to the correct operation
*/
BUG_ON(async_tx_test_ack(*tx));
if (dma_wait_for_async_tx(*tx) == DMA_ERROR)
panic("DMA_ERROR waiting for transaction\n");
async_tx_ack(*tx);
*tx = NULL;
}
}
EXPORT_SYMBOL_GPL(async_tx_quiesce);
module_init(async_tx_init);
module_exit(async_tx_exit);

View File

@ -35,74 +35,121 @@
* when CONFIG_DMA_ENGINE=n
*/
static __always_inline struct dma_async_tx_descriptor *
do_async_xor(struct dma_device *device,
struct dma_chan *chan, struct page *dest, struct page **src_list,
unsigned int offset, unsigned int src_cnt, size_t len,
enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
dma_async_tx_callback cb_fn, void *cb_param)
do_async_xor(struct dma_chan *chan, struct page *dest, struct page **src_list,
unsigned int offset, int src_cnt, size_t len,
enum async_tx_flags flags,
struct dma_async_tx_descriptor *depend_tx,
dma_async_tx_callback cb_fn, void *cb_param)
{
dma_addr_t dma_dest;
struct dma_device *dma = chan->device;
dma_addr_t *dma_src = (dma_addr_t *) src_list;
struct dma_async_tx_descriptor *tx;
struct dma_async_tx_descriptor *tx = NULL;
int src_off = 0;
int i;
unsigned long dma_prep_flags = cb_fn ? DMA_PREP_INTERRUPT : 0;
pr_debug("%s: len: %zu\n", __func__, len);
dma_dest = dma_map_page(device->dev, dest, offset, len,
DMA_FROM_DEVICE);
dma_async_tx_callback _cb_fn;
void *_cb_param;
enum async_tx_flags async_flags;
enum dma_ctrl_flags dma_flags;
int xor_src_cnt;
dma_addr_t dma_dest;
dma_dest = dma_map_page(dma->dev, dest, offset, len, DMA_FROM_DEVICE);
for (i = 0; i < src_cnt; i++)
dma_src[i] = dma_map_page(device->dev, src_list[i], offset,
dma_src[i] = dma_map_page(dma->dev, src_list[i], offset,
len, DMA_TO_DEVICE);
/* Since we have clobbered the src_list we are committed
* to doing this asynchronously. Drivers force forward progress
* in case they can not provide a descriptor
*/
tx = device->device_prep_dma_xor(chan, dma_dest, dma_src, src_cnt, len,
dma_prep_flags);
if (!tx) {
if (depend_tx)
dma_wait_for_async_tx(depend_tx);
while (src_cnt) {
async_flags = flags;
dma_flags = 0;
xor_src_cnt = min(src_cnt, dma->max_xor);
/* if we are submitting additional xors, leave the chain open,
* clear the callback parameters, and leave the destination
* buffer mapped
*/
if (src_cnt > xor_src_cnt) {
async_flags &= ~ASYNC_TX_ACK;
dma_flags = DMA_COMPL_SKIP_DEST_UNMAP;
_cb_fn = NULL;
_cb_param = NULL;
} else {
_cb_fn = cb_fn;
_cb_param = cb_param;
}
if (_cb_fn)
dma_flags |= DMA_PREP_INTERRUPT;
while (!tx)
tx = device->device_prep_dma_xor(chan, dma_dest,
dma_src, src_cnt, len,
dma_prep_flags);
/* Since we have clobbered the src_list we are committed
* to doing this asynchronously. Drivers force forward progress
* in case they can not provide a descriptor
*/
tx = dma->device_prep_dma_xor(chan, dma_dest, &dma_src[src_off],
xor_src_cnt, len, dma_flags);
if (unlikely(!tx))
async_tx_quiesce(&depend_tx);
/* spin wait for the preceeding transactions to complete */
while (unlikely(!tx)) {
dma_async_issue_pending(chan);
tx = dma->device_prep_dma_xor(chan, dma_dest,
&dma_src[src_off],
xor_src_cnt, len,
dma_flags);
}
async_tx_submit(chan, tx, async_flags, depend_tx, _cb_fn,
_cb_param);
depend_tx = tx;
flags |= ASYNC_TX_DEP_ACK;
if (src_cnt > xor_src_cnt) {
/* drop completed sources */
src_cnt -= xor_src_cnt;
src_off += xor_src_cnt;
/* use the intermediate result a source */
dma_src[--src_off] = dma_dest;
src_cnt++;
} else
break;
}
async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
return tx;
}
static void
do_sync_xor(struct page *dest, struct page **src_list, unsigned int offset,
unsigned int src_cnt, size_t len, enum async_tx_flags flags,
struct dma_async_tx_descriptor *depend_tx,
dma_async_tx_callback cb_fn, void *cb_param)
int src_cnt, size_t len, enum async_tx_flags flags,
dma_async_tx_callback cb_fn, void *cb_param)
{
void *_dest;
int i;
pr_debug("%s: len: %zu\n", __func__, len);
int xor_src_cnt;
int src_off = 0;
void *dest_buf;
void **srcs = (void **) src_list;
/* reuse the 'src_list' array to convert to buffer pointers */
for (i = 0; i < src_cnt; i++)
src_list[i] = (struct page *)
(page_address(src_list[i]) + offset);
srcs[i] = page_address(src_list[i]) + offset;
/* set destination address */
_dest = page_address(dest) + offset;
dest_buf = page_address(dest) + offset;
if (flags & ASYNC_TX_XOR_ZERO_DST)
memset(_dest, 0, len);
memset(dest_buf, 0, len);
xor_blocks(src_cnt, len, _dest,
(void **) src_list);
while (src_cnt > 0) {
/* process up to 'MAX_XOR_BLOCKS' sources */
xor_src_cnt = min(src_cnt, MAX_XOR_BLOCKS);
xor_blocks(xor_src_cnt, len, dest_buf, &srcs[src_off]);
async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
/* drop completed sources */
src_cnt -= xor_src_cnt;
src_off += xor_src_cnt;
}
async_tx_sync_epilog(cb_fn, cb_param);
}
/**
@ -132,106 +179,34 @@ async_xor(struct page *dest, struct page **src_list, unsigned int offset,
struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_XOR,
&dest, 1, src_list,
src_cnt, len);
struct dma_device *device = chan ? chan->device : NULL;
struct dma_async_tx_descriptor *tx = NULL;
dma_async_tx_callback _cb_fn;
void *_cb_param;
unsigned long local_flags;
int xor_src_cnt;
int i = 0, src_off = 0;
BUG_ON(src_cnt <= 1);
while (src_cnt) {
local_flags = flags;
if (device) { /* run the xor asynchronously */
xor_src_cnt = min(src_cnt, device->max_xor);
/* if we are submitting additional xors
* only set the callback on the last transaction
*/
if (src_cnt > xor_src_cnt) {
local_flags &= ~ASYNC_TX_ACK;
_cb_fn = NULL;
_cb_param = NULL;
} else {
_cb_fn = cb_fn;
_cb_param = cb_param;
}
if (chan) {
/* run the xor asynchronously */
pr_debug("%s (async): len: %zu\n", __func__, len);
tx = do_async_xor(device, chan, dest,
&src_list[src_off], offset,
xor_src_cnt, len, local_flags,
depend_tx, _cb_fn, _cb_param);
} else { /* run the xor synchronously */
/* in the sync case the dest is an implied source
* (assumes the dest is at the src_off index)
*/
if (flags & ASYNC_TX_XOR_DROP_DST) {
src_cnt--;
src_off++;
}
return do_async_xor(chan, dest, src_list, offset, src_cnt, len,
flags, depend_tx, cb_fn, cb_param);
} else {
/* run the xor synchronously */
pr_debug("%s (sync): len: %zu\n", __func__, len);
/* process up to 'MAX_XOR_BLOCKS' sources */
xor_src_cnt = min(src_cnt, MAX_XOR_BLOCKS);
/* if we are submitting additional xors
* only set the callback on the last transaction
*/
if (src_cnt > xor_src_cnt) {
local_flags &= ~ASYNC_TX_ACK;
_cb_fn = NULL;
_cb_param = NULL;
} else {
_cb_fn = cb_fn;
_cb_param = cb_param;
}
/* wait for any prerequisite operations */
if (depend_tx) {
/* if ack is already set then we cannot be sure
* we are referring to the correct operation
*/
BUG_ON(async_tx_test_ack(depend_tx));
if (dma_wait_for_async_tx(depend_tx) ==
DMA_ERROR)
panic("%s: DMA_ERROR waiting for "
"depend_tx\n",
__func__);
}
do_sync_xor(dest, &src_list[src_off], offset,
xor_src_cnt, len, local_flags, depend_tx,
_cb_fn, _cb_param);
/* in the sync case the dest is an implied source
* (assumes the dest is the first source)
*/
if (flags & ASYNC_TX_XOR_DROP_DST) {
src_cnt--;
src_list++;
}
/* the previous tx is hidden from the client,
* so ack it
*/
if (i && depend_tx)
async_tx_ack(depend_tx);
/* wait for any prerequisite operations */
async_tx_quiesce(&depend_tx);
depend_tx = tx;
do_sync_xor(dest, src_list, offset, src_cnt, len,
flags, cb_fn, cb_param);
if (src_cnt > xor_src_cnt) {
/* drop completed sources */
src_cnt -= xor_src_cnt;
src_off += xor_src_cnt;
/* unconditionally preserve the destination */
flags &= ~ASYNC_TX_XOR_ZERO_DST;
/* use the intermediate result a source, but remember
* it's dropped, because it's implied, in the sync case
*/
src_list[--src_off] = dest;
src_cnt++;
flags |= ASYNC_TX_XOR_DROP_DST;
} else
src_cnt = 0;
i++;
return NULL;
}
return tx;
}
EXPORT_SYMBOL_GPL(async_xor);
@ -285,11 +260,11 @@ async_xor_zero_sum(struct page *dest, struct page **src_list,
tx = device->device_prep_dma_zero_sum(chan, dma_src, src_cnt,
len, result,
dma_prep_flags);
if (!tx) {
if (depend_tx)
dma_wait_for_async_tx(depend_tx);
if (unlikely(!tx)) {
async_tx_quiesce(&depend_tx);
while (!tx)
dma_async_issue_pending(chan);
tx = device->device_prep_dma_zero_sum(chan,
dma_src, src_cnt, len, result,
dma_prep_flags);
@ -307,18 +282,11 @@ async_xor_zero_sum(struct page *dest, struct page **src_list,
tx = async_xor(dest, src_list, offset, src_cnt, len, xor_flags,
depend_tx, NULL, NULL);
if (tx) {
if (dma_wait_for_async_tx(tx) == DMA_ERROR)
panic("%s: DMA_ERROR waiting for tx\n",
__func__);
async_tx_ack(tx);
}
async_tx_quiesce(&tx);
*result = page_is_zero(dest, offset, len) ? 0 : 1;
tx = NULL;
async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
async_tx_sync_epilog(cb_fn, cb_param);
}
return tx;

View File

@ -827,6 +827,7 @@ static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr)
static int acpi_processor_get_throttling(struct acpi_processor *pr)
{
cpumask_t saved_mask;
cpumask_of_cpu_ptr_declare(new_mask);
int ret;
if (!pr)
@ -838,7 +839,8 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr)
* Migrate task to the cpu pointed by pr.
*/
saved_mask = current->cpus_allowed;
set_cpus_allowed_ptr(current, &cpumask_of_cpu(pr->id));
cpumask_of_cpu_ptr_next(new_mask, pr->id);
set_cpus_allowed_ptr(current, new_mask);
ret = pr->throttling.acpi_processor_get_throttling(pr);
/* restore the previous state */
set_cpus_allowed_ptr(current, &saved_mask);
@ -987,6 +989,7 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
{
cpumask_t saved_mask;
cpumask_of_cpu_ptr_declare(new_mask);
int ret = 0;
unsigned int i;
struct acpi_processor *match_pr;
@ -1013,7 +1016,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
* affected cpu in order to get one proper T-state.
* The notifier event is THROTTLING_PRECHANGE.
*/
for_each_cpu_mask(i, online_throttling_cpus) {
for_each_cpu_mask_nr(i, online_throttling_cpus) {
t_state.cpu = i;
acpi_processor_throttling_notifier(THROTTLING_PRECHANGE,
&t_state);
@ -1025,7 +1028,8 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
* it can be called only for the cpu pointed by pr.
*/
if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
set_cpus_allowed_ptr(current, &cpumask_of_cpu(pr->id));
cpumask_of_cpu_ptr_next(new_mask, pr->id);
set_cpus_allowed_ptr(current, new_mask);
ret = p_throttling->acpi_processor_set_throttling(pr,
t_state.target_state);
} else {
@ -1034,7 +1038,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
* it is necessary to set T-state for every affected
* cpus.
*/
for_each_cpu_mask(i, online_throttling_cpus) {
for_each_cpu_mask_nr(i, online_throttling_cpus) {
match_pr = per_cpu(processors, i);
/*
* If the pointer is invalid, we will report the
@ -1056,7 +1060,8 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
continue;
}
t_state.cpu = i;
set_cpus_allowed_ptr(current, &cpumask_of_cpu(i));
cpumask_of_cpu_ptr_next(new_mask, i);
set_cpus_allowed_ptr(current, new_mask);
ret = match_pr->throttling.
acpi_processor_set_throttling(
match_pr, t_state.target_state);
@ -1068,7 +1073,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
* affected cpu to update the T-states.
* The notifier event is THROTTLING_POSTCHANGE
*/
for_each_cpu_mask(i, online_throttling_cpus) {
for_each_cpu_mask_nr(i, online_throttling_cpus) {
t_state.cpu = i;
acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE,
&t_state);

View File

@ -121,14 +121,14 @@ static ssize_t print_cpus_##type(struct sysdev_class *class, char *buf) \
{ \
return print_cpus_map(buf, &cpu_##type##_map); \
} \
struct sysdev_class_attribute attr_##type##_map = \
static struct sysdev_class_attribute attr_##type##_map = \
_SYSDEV_CLASS_ATTR(type, 0444, print_cpus_##type, NULL)
print_cpus_func(online);
print_cpus_func(possible);
print_cpus_func(present);
struct sysdev_class_attribute *cpu_state_attr[] = {
static struct sysdev_class_attribute *cpu_state_attr[] = {
&attr_online_map,
&attr_possible_map,
&attr_present_map,

View File

@ -107,7 +107,6 @@
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/uaccess.h>

View File

@ -915,7 +915,7 @@ static void tty_reset_termios(struct tty_struct *tty)
* do_tty_hangup - actual handler for hangup events
* @work: tty device
*
k * This can be called by the "eventd" kernel thread. That is process
* This can be called by the "eventd" kernel thread. That is process
* synchronous but doesn't hold any locks, so we need to make sure we
* have the appropriate locks for what we're doing.
*

View File

@ -589,7 +589,7 @@ static ssize_t show_cpus(cpumask_t mask, char *buf)
ssize_t i = 0;
unsigned int cpu;
for_each_cpu_mask(cpu, mask) {
for_each_cpu_mask_nr(cpu, mask) {
if (i)
i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), " ");
i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), "%u", cpu);
@ -835,7 +835,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
}
#endif
for_each_cpu_mask(j, policy->cpus) {
for_each_cpu_mask_nr(j, policy->cpus) {
if (cpu == j)
continue;
@ -898,14 +898,14 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
}
spin_lock_irqsave(&cpufreq_driver_lock, flags);
for_each_cpu_mask(j, policy->cpus) {
for_each_cpu_mask_nr(j, policy->cpus) {
per_cpu(cpufreq_cpu_data, j) = policy;
per_cpu(policy_cpu, j) = policy->cpu;
}
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
/* symlink affected CPUs */
for_each_cpu_mask(j, policy->cpus) {
for_each_cpu_mask_nr(j, policy->cpus) {
if (j == cpu)
continue;
if (!cpu_online(j))
@ -945,7 +945,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
err_out_unregister:
spin_lock_irqsave(&cpufreq_driver_lock, flags);
for_each_cpu_mask(j, policy->cpus)
for_each_cpu_mask_nr(j, policy->cpus)
per_cpu(cpufreq_cpu_data, j) = NULL;
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
@ -1028,7 +1028,7 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
* the sysfs links afterwards.
*/
if (unlikely(cpus_weight(data->cpus) > 1)) {
for_each_cpu_mask(j, data->cpus) {
for_each_cpu_mask_nr(j, data->cpus) {
if (j == cpu)
continue;
per_cpu(cpufreq_cpu_data, j) = NULL;
@ -1038,7 +1038,7 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
if (unlikely(cpus_weight(data->cpus) > 1)) {
for_each_cpu_mask(j, data->cpus) {
for_each_cpu_mask_nr(j, data->cpus) {
if (j == cpu)
continue;
dprintk("removing link for cpu %u\n", j);

View File

@ -497,7 +497,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
return rc;
}
for_each_cpu_mask(j, policy->cpus) {
for_each_cpu_mask_nr(j, policy->cpus) {
struct cpu_dbs_info_s *j_dbs_info;
j_dbs_info = &per_cpu(cpu_dbs_info, j);
j_dbs_info->cur_policy = policy;

View File

@ -367,7 +367,7 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
/* Get Idle Time */
idle_ticks = UINT_MAX;
for_each_cpu_mask(j, policy->cpus) {
for_each_cpu_mask_nr(j, policy->cpus) {
cputime64_t total_idle_ticks;
unsigned int tmp_idle_ticks;
struct cpu_dbs_info_s *j_dbs_info;
@ -521,7 +521,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
return rc;
}
for_each_cpu_mask(j, policy->cpus) {
for_each_cpu_mask_nr(j, policy->cpus) {
struct cpu_dbs_info_s *j_dbs_info;
j_dbs_info = &per_cpu(cpu_dbs_info, j);
j_dbs_info->cur_policy = policy;

View File

@ -30,16 +30,18 @@
/**
* A few values needed by the userspace governor
*/
static unsigned int cpu_max_freq[NR_CPUS];
static unsigned int cpu_min_freq[NR_CPUS];
static unsigned int cpu_cur_freq[NR_CPUS]; /* current CPU freq */
static unsigned int cpu_set_freq[NR_CPUS]; /* CPU freq desired by userspace */
static unsigned int cpu_is_managed[NR_CPUS];
static DEFINE_PER_CPU(unsigned int, cpu_max_freq);
static DEFINE_PER_CPU(unsigned int, cpu_min_freq);
static DEFINE_PER_CPU(unsigned int, cpu_cur_freq); /* current CPU freq */
static DEFINE_PER_CPU(unsigned int, cpu_set_freq); /* CPU freq desired by
userspace */
static DEFINE_PER_CPU(unsigned int, cpu_is_managed);
static DEFINE_MUTEX (userspace_mutex);
static int cpus_using_userspace_governor;
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "userspace", msg)
#define dprintk(msg...) \
cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "userspace", msg)
/* keep track of frequency transitions */
static int
@ -48,12 +50,12 @@ userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
{
struct cpufreq_freqs *freq = data;
if (!cpu_is_managed[freq->cpu])
if (!per_cpu(cpu_is_managed, freq->cpu))
return 0;
dprintk("saving cpu_cur_freq of cpu %u to be %u kHz\n",
freq->cpu, freq->new);
cpu_cur_freq[freq->cpu] = freq->new;
per_cpu(cpu_cur_freq, freq->cpu) = freq->new;
return 0;
}
@ -77,15 +79,15 @@ static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq)
dprintk("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq);
mutex_lock(&userspace_mutex);
if (!cpu_is_managed[policy->cpu])
if (!per_cpu(cpu_is_managed, policy->cpu))
goto err;
cpu_set_freq[policy->cpu] = freq;
per_cpu(cpu_set_freq, policy->cpu) = freq;
if (freq < cpu_min_freq[policy->cpu])
freq = cpu_min_freq[policy->cpu];
if (freq > cpu_max_freq[policy->cpu])
freq = cpu_max_freq[policy->cpu];
if (freq < per_cpu(cpu_min_freq, policy->cpu))
freq = per_cpu(cpu_min_freq, policy->cpu);
if (freq > per_cpu(cpu_max_freq, policy->cpu))
freq = per_cpu(cpu_max_freq, policy->cpu);
/*
* We're safe from concurrent calls to ->target() here
@ -104,7 +106,7 @@ static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq)
static ssize_t show_speed(struct cpufreq_policy *policy, char *buf)
{
return sprintf(buf, "%u\n", cpu_cur_freq[policy->cpu]);
return sprintf(buf, "%u\n", per_cpu(cpu_cur_freq, policy->cpu));
}
static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
@ -127,12 +129,17 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
}
cpus_using_userspace_governor++;
cpu_is_managed[cpu] = 1;
cpu_min_freq[cpu] = policy->min;
cpu_max_freq[cpu] = policy->max;
cpu_cur_freq[cpu] = policy->cur;
cpu_set_freq[cpu] = policy->cur;
dprintk("managing cpu %u started (%u - %u kHz, currently %u kHz)\n", cpu, cpu_min_freq[cpu], cpu_max_freq[cpu], cpu_cur_freq[cpu]);
per_cpu(cpu_is_managed, cpu) = 1;
per_cpu(cpu_min_freq, cpu) = policy->min;
per_cpu(cpu_max_freq, cpu) = policy->max;
per_cpu(cpu_cur_freq, cpu) = policy->cur;
per_cpu(cpu_set_freq, cpu) = policy->cur;
dprintk("managing cpu %u started "
"(%u - %u kHz, currently %u kHz)\n",
cpu,
per_cpu(cpu_min_freq, cpu),
per_cpu(cpu_max_freq, cpu),
per_cpu(cpu_cur_freq, cpu));
mutex_unlock(&userspace_mutex);
break;
@ -145,34 +152,34 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
CPUFREQ_TRANSITION_NOTIFIER);
}
cpu_is_managed[cpu] = 0;
cpu_min_freq[cpu] = 0;
cpu_max_freq[cpu] = 0;
cpu_set_freq[cpu] = 0;
per_cpu(cpu_is_managed, cpu) = 0;
per_cpu(cpu_min_freq, cpu) = 0;
per_cpu(cpu_max_freq, cpu) = 0;
per_cpu(cpu_set_freq, cpu) = 0;
dprintk("managing cpu %u stopped\n", cpu);
mutex_unlock(&userspace_mutex);
break;
case CPUFREQ_GOV_LIMITS:
mutex_lock(&userspace_mutex);
dprintk("limit event for cpu %u: %u - %u kHz,"
dprintk("limit event for cpu %u: %u - %u kHz, "
"currently %u kHz, last set to %u kHz\n",
cpu, policy->min, policy->max,
cpu_cur_freq[cpu], cpu_set_freq[cpu]);
if (policy->max < cpu_set_freq[cpu]) {
per_cpu(cpu_cur_freq, cpu),
per_cpu(cpu_set_freq, cpu));
if (policy->max < per_cpu(cpu_set_freq, cpu)) {
__cpufreq_driver_target(policy, policy->max,
CPUFREQ_RELATION_H);
}
else if (policy->min > cpu_set_freq[cpu]) {
} else if (policy->min > per_cpu(cpu_set_freq, cpu)) {
__cpufreq_driver_target(policy, policy->min,
CPUFREQ_RELATION_L);
}
else {
__cpufreq_driver_target(policy, cpu_set_freq[cpu],
} else {
__cpufreq_driver_target(policy,
per_cpu(cpu_set_freq, cpu),
CPUFREQ_RELATION_L);
}
cpu_min_freq[cpu] = policy->min;
cpu_max_freq[cpu] = policy->max;
cpu_cur_freq[cpu] = policy->cur;
per_cpu(cpu_min_freq, cpu) = policy->min;
per_cpu(cpu_max_freq, cpu) = policy->max;
per_cpu(cpu_cur_freq, cpu) = policy->cur;
mutex_unlock(&userspace_mutex);
break;
}

View File

@ -28,13 +28,29 @@
#include <linux/device.h>
#include <linux/dca.h>
MODULE_LICENSE("GPL");
#define DCA_VERSION "1.4"
/* For now we're assuming a single, global, DCA provider for the system. */
MODULE_VERSION(DCA_VERSION);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Intel Corporation");
static DEFINE_SPINLOCK(dca_lock);
static struct dca_provider *global_dca = NULL;
static LIST_HEAD(dca_providers);
static struct dca_provider *dca_find_provider_by_dev(struct device *dev)
{
struct dca_provider *dca, *ret = NULL;
list_for_each_entry(dca, &dca_providers, node) {
if ((!dev) || (dca->ops->dev_managed(dca, dev))) {
ret = dca;
break;
}
}
return ret;
}
/**
* dca_add_requester - add a dca client to the list
@ -42,25 +58,39 @@ static struct dca_provider *global_dca = NULL;
*/
int dca_add_requester(struct device *dev)
{
int err, slot;
struct dca_provider *dca;
int err, slot = -ENODEV;
if (!global_dca)
return -ENODEV;
if (!dev)
return -EFAULT;
spin_lock(&dca_lock);
slot = global_dca->ops->add_requester(global_dca, dev);
spin_unlock(&dca_lock);
if (slot < 0)
return slot;
err = dca_sysfs_add_req(global_dca, dev, slot);
/* check if the requester has not been added already */
dca = dca_find_provider_by_dev(dev);
if (dca) {
spin_unlock(&dca_lock);
return -EEXIST;
}
list_for_each_entry(dca, &dca_providers, node) {
slot = dca->ops->add_requester(dca, dev);
if (slot >= 0)
break;
}
if (slot < 0) {
spin_unlock(&dca_lock);
return slot;
}
err = dca_sysfs_add_req(dca, dev, slot);
if (err) {
spin_lock(&dca_lock);
global_dca->ops->remove_requester(global_dca, dev);
dca->ops->remove_requester(dca, dev);
spin_unlock(&dca_lock);
return err;
}
spin_unlock(&dca_lock);
return 0;
}
EXPORT_SYMBOL_GPL(dca_add_requester);
@ -71,30 +101,78 @@ EXPORT_SYMBOL_GPL(dca_add_requester);
*/
int dca_remove_requester(struct device *dev)
{
struct dca_provider *dca;
int slot;
if (!global_dca)
return -ENODEV;
if (!dev)
return -EFAULT;
spin_lock(&dca_lock);
slot = global_dca->ops->remove_requester(global_dca, dev);
spin_unlock(&dca_lock);
if (slot < 0)
dca = dca_find_provider_by_dev(dev);
if (!dca) {
spin_unlock(&dca_lock);
return -ENODEV;
}
slot = dca->ops->remove_requester(dca, dev);
if (slot < 0) {
spin_unlock(&dca_lock);
return slot;
}
dca_sysfs_remove_req(global_dca, slot);
dca_sysfs_remove_req(dca, slot);
spin_unlock(&dca_lock);
return 0;
}
EXPORT_SYMBOL_GPL(dca_remove_requester);
/**
* dca_get_tag - return the dca tag for the given cpu
* dca_common_get_tag - return the dca tag (serves both new and old api)
* @dev - the device that wants dca service
* @cpu - the cpuid as returned by get_cpu()
*/
u8 dca_common_get_tag(struct device *dev, int cpu)
{
struct dca_provider *dca;
u8 tag;
spin_lock(&dca_lock);
dca = dca_find_provider_by_dev(dev);
if (!dca) {
spin_unlock(&dca_lock);
return -ENODEV;
}
tag = dca->ops->get_tag(dca, dev, cpu);
spin_unlock(&dca_lock);
return tag;
}
/**
* dca3_get_tag - return the dca tag to the requester device
* for the given cpu (new api)
* @dev - the device that wants dca service
* @cpu - the cpuid as returned by get_cpu()
*/
u8 dca3_get_tag(struct device *dev, int cpu)
{
if (!dev)
return -EFAULT;
return dca_common_get_tag(dev, cpu);
}
EXPORT_SYMBOL_GPL(dca3_get_tag);
/**
* dca_get_tag - return the dca tag for the given cpu (old api)
* @cpu - the cpuid as returned by get_cpu()
*/
u8 dca_get_tag(int cpu)
{
if (!global_dca)
return -ENODEV;
return global_dca->ops->get_tag(global_dca, cpu);
struct device *dev = NULL;
return dca_common_get_tag(dev, cpu);
}
EXPORT_SYMBOL_GPL(dca_get_tag);
@ -140,12 +218,10 @@ int register_dca_provider(struct dca_provider *dca, struct device *dev)
{
int err;
if (global_dca)
return -EEXIST;
err = dca_sysfs_add_provider(dca, dev);
if (err)
return err;
global_dca = dca;
list_add(&dca->node, &dca_providers);
blocking_notifier_call_chain(&dca_provider_chain,
DCA_PROVIDER_ADD, NULL);
return 0;
@ -158,11 +234,9 @@ EXPORT_SYMBOL_GPL(register_dca_provider);
*/
void unregister_dca_provider(struct dca_provider *dca)
{
if (!global_dca)
return;
blocking_notifier_call_chain(&dca_provider_chain,
DCA_PROVIDER_REMOVE, NULL);
global_dca = NULL;
list_del(&dca->node);
dca_sysfs_remove_provider(dca);
}
EXPORT_SYMBOL_GPL(unregister_dca_provider);
@ -187,6 +261,7 @@ EXPORT_SYMBOL_GPL(dca_unregister_notify);
static int __init dca_init(void)
{
printk(KERN_ERR "dca service started, version %s\n", DCA_VERSION);
return dca_sysfs_init();
}

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