summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-10-12 14:37:49 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2009-10-12 14:37:49 -0700
commit589bf8d52b5bbb580962438ad9403ec6853bc12b (patch)
treeb11aaf7c0e6dfc207db237381bfc11739dffa809
parente3c6f15fecee5aaa2dd1d0b83b17d09b64997e31 (diff)
parent787b2faadc4356b6c2c71feb42fb944fece9a12f (diff)
downloadlinux-589bf8d52b5bbb580962438ad9403ec6853bc12b.tar.gz
linux-589bf8d52b5bbb580962438ad9403ec6853bc12b.tar.bz2
linux-589bf8d52b5bbb580962438ad9403ec6853bc12b.zip
Merge master.kernel.org:/home/rmk/linux-2.6-arm
* master.kernel.org:/home/rmk/linux-2.6-arm: (24 commits) ARM: force dcache flush if dcache_dirty bit set [ARM] pxa: workaround errata #37 by not using half turbo switching [ARM] pxamci: fix printing gpio numbers in pxamci_probe [ARM] pxa/csb726: adjust duplicate structure field initialization ARM: Add kmap_atomic type debugging ARM: boolean bit testing ARM: update die() output ARM: Dump code/mem oops lines with the appropriate log level ARM: Dump memory and backtrace as one printk per line ARM: 5756/1: ep93xx: introduce clk parent ARM: 5754/1: ep93xx: update i2c support ARM: 5753/1: ep93xx: remove old EP93XX_GPIO_* defines ARM: 5729/1: ep93xx: define EP93XX_*_PHYS_BASE with macros ARM: 5751/1: ep93xx/micro9: Add Micro9-Slim ARM: 5750/1: ep93xx/micro9: Update platform code ARM: 5749/1: ep93xx/micro9: Update maintainer ARM: 5752/1: SA1100: fix building of h3100 ARM: 5748/1: bcmring: fix build warning messages ARM: 5747/1: Fix the start_pg value in free_memmap() ARM: 5746/1: Handle possible translation errors in ARMv6/v7 coherent_user_range ...
-rw-r--r--MAINTAINERS5
-rw-r--r--arch/arm/include/asm/bitops.h6
-rw-r--r--arch/arm/kernel/traps.c76
-rw-r--r--arch/arm/mach-bcmring/core.c4
-rw-r--r--arch/arm/mach-bcmring/include/mach/system.h2
-rw-r--r--arch/arm/mach-ep93xx/Kconfig44
-rw-r--r--arch/arm/mach-ep93xx/Makefile.boot9
-rw-r--r--arch/arm/mach-ep93xx/clock.c166
-rw-r--r--arch/arm/mach-ep93xx/core.c31
-rw-r--r--arch/arm/mach-ep93xx/edb93xx.c31
-rw-r--r--arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h42
-rw-r--r--arch/arm/mach-ep93xx/include/mach/gpio.h16
-rw-r--r--arch/arm/mach-ep93xx/include/mach/memory.h6
-rw-r--r--arch/arm/mach-ep93xx/include/mach/platform.h4
-rw-r--r--arch/arm/mach-ep93xx/micro9.c132
-rw-r--r--arch/arm/mach-pxa/cpufreq-pxa2xx.c2
-rw-r--r--arch/arm/mach-pxa/csb726.c2
-rw-r--r--arch/arm/mach-sa1100/Makefile1
-rw-r--r--arch/arm/mm/cache-v6.S20
-rw-r--r--arch/arm/mm/cache-v7.S19
-rw-r--r--arch/arm/mm/fault-armv.c9
-rw-r--r--arch/arm/mm/fault.c5
-rw-r--r--arch/arm/mm/highmem.c2
-rw-r--r--arch/arm/mm/init.c2
-rw-r--r--drivers/mmc/host/pxamci.c4
-rw-r--r--drivers/spi/amba-pl022.c2
26 files changed, 426 insertions, 216 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 69e31aab1308..ff968842ce56 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -577,6 +577,11 @@ M: Mike Rapoport <mike@compulab.co.il>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
+ARM/CONTEC MICRO9 MACHINE SUPPORT
+M: Hubert Feurstein <hubert.feurstein@contec.at>
+S: Maintained
+F: arch/arm/mach-ep93xx/micro9.c
+
ARM/CORGI MACHINE SUPPORT
M: Richard Purdie <rpurdie@rpsys.net>
S: Maintained
diff --git a/arch/arm/include/asm/bitops.h b/arch/arm/include/asm/bitops.h
index 63a481fbbed4..338ff19ae447 100644
--- a/arch/arm/include/asm/bitops.h
+++ b/arch/arm/include/asm/bitops.h
@@ -84,7 +84,7 @@ ____atomic_test_and_set_bit(unsigned int bit, volatile unsigned long *p)
*p = res | mask;
raw_local_irq_restore(flags);
- return res & mask;
+ return (res & mask) != 0;
}
static inline int
@@ -101,7 +101,7 @@ ____atomic_test_and_clear_bit(unsigned int bit, volatile unsigned long *p)
*p = res & ~mask;
raw_local_irq_restore(flags);
- return res & mask;
+ return (res & mask) != 0;
}
static inline int
@@ -118,7 +118,7 @@ ____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p)
*p = res ^ mask;
raw_local_irq_restore(flags);
- return res & mask;
+ return (res & mask) != 0;
}
#include <asm-generic/bitops/non-atomic.h>
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 467b69ed1021..f838f36eb702 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -45,21 +45,21 @@ static int __init user_debug_setup(char *str)
__setup("user_debug=", user_debug_setup);
#endif
-static void dump_mem(const char *str, unsigned long bottom, unsigned long top);
+static void dump_mem(const char *, const char *, unsigned long, unsigned long);
void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame)
{
#ifdef CONFIG_KALLSYMS
- printk("[<%08lx>] ", where);
- print_symbol("(%s) ", where);
- printk("from [<%08lx>] ", from);
- print_symbol("(%s)\n", from);
+ char sym1[KSYM_SYMBOL_LEN], sym2[KSYM_SYMBOL_LEN];
+ sprint_symbol(sym1, where);
+ sprint_symbol(sym2, from);
+ printk("[<%08lx>] (%s) from [<%08lx>] (%s)\n", where, sym1, from, sym2);
#else
printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from);
#endif
if (in_exception_text(where))
- dump_mem("Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs));
+ dump_mem("", "Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs));
}
#ifndef CONFIG_ARM_UNWIND
@@ -81,9 +81,10 @@ static int verify_stack(unsigned long sp)
/*
* Dump out the contents of some memory nicely...
*/
-static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
+static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
+ unsigned long top)
{
- unsigned long p = bottom & ~31;
+ unsigned long first;
mm_segment_t fs;
int i;
@@ -95,33 +96,37 @@ static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
fs = get_fs();
set_fs(KERNEL_DS);
- printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
+ printk("%s%s(0x%08lx to 0x%08lx)\n", lvl, str, bottom, top);
- for (p = bottom & ~31; p < top;) {
- printk("%04lx: ", p & 0xffff);
+ for (first = bottom & ~31; first < top; first += 32) {
+ unsigned long p;
+ char str[sizeof(" 12345678") * 8 + 1];
- for (i = 0; i < 8; i++, p += 4) {
- unsigned int val;
+ memset(str, ' ', sizeof(str));
+ str[sizeof(str) - 1] = '\0';
- if (p < bottom || p >= top)
- printk(" ");
- else {
- __get_user(val, (unsigned long *)p);
- printk("%08x ", val);
+ for (p = first, i = 0; i < 8 && p < top; i++, p += 4) {
+ if (p >= bottom && p < top) {
+ unsigned long val;
+ if (__get_user(val, (unsigned long *)p) == 0)
+ sprintf(str + i * 9, " %08lx", val);
+ else
+ sprintf(str + i * 9, " ????????");
}
}
- printk ("\n");
+ printk("%s%04lx:%s\n", lvl, first & 0xffff, str);
}
set_fs(fs);
}
-static void dump_instr(struct pt_regs *regs)
+static void dump_instr(const char *lvl, struct pt_regs *regs)
{
unsigned long addr = instruction_pointer(regs);
const int thumb = thumb_mode(regs);
const int width = thumb ? 4 : 8;
mm_segment_t fs;
+ char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str;
int i;
/*
@@ -132,7 +137,6 @@ static void dump_instr(struct pt_regs *regs)
fs = get_fs();
set_fs(KERNEL_DS);
- printk("Code: ");
for (i = -4; i < 1; i++) {
unsigned int val, bad;
@@ -142,13 +146,14 @@ static void dump_instr(struct pt_regs *regs)
bad = __get_user(val, &((u32 *)addr)[i]);
if (!bad)
- printk(i == 0 ? "(%0*x) " : "%0*x ", width, val);
+ p += sprintf(p, i == 0 ? "(%0*x) " : "%0*x ",
+ width, val);
else {
- printk("bad PC value.");
+ p += sprintf(p, "bad PC value");
break;
}
}
- printk("\n");
+ printk("%sCode: %s\n", lvl, str);
set_fs(fs);
}
@@ -224,18 +229,19 @@ static void __die(const char *str, int err, struct thread_info *thread, struct p
struct task_struct *tsk = thread->task;
static int die_counter;
- printk("Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n",
+ printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n",
str, err, ++die_counter);
+ sysfs_printk_last_file();
print_modules();
__show_regs(regs);
- printk("Process %s (pid: %d, stack limit = 0x%p)\n",
- tsk->comm, task_pid_nr(tsk), thread + 1);
+ printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n",
+ TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1);
if (!user_mode(regs) || in_interrupt()) {
- dump_mem("Stack: ", regs->ARM_sp,
+ dump_mem(KERN_EMERG, "Stack: ", regs->ARM_sp,
THREAD_SIZE + (unsigned long)task_stack_page(tsk));
dump_backtrace(regs, tsk);
- dump_instr(regs);
+ dump_instr(KERN_EMERG, regs);
}
}
@@ -250,13 +256,14 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
oops_enter();
- console_verbose();
spin_lock_irq(&die_lock);
+ console_verbose();
bust_spinlocks(1);
__die(str, err, thread, regs);
bust_spinlocks(0);
add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock);
+ oops_exit();
if (in_interrupt())
panic("Fatal exception in interrupt");
@@ -264,7 +271,6 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
if (panic_on_oops)
panic("Fatal exception");
- oops_exit();
do_exit(SIGSEGV);
}
@@ -349,7 +355,7 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
if (user_debug & UDBG_UNDEFINED) {
printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n",
current->comm, task_pid_nr(current), pc);
- dump_instr(regs);
+ dump_instr(KERN_INFO, regs);
}
#endif
@@ -400,7 +406,7 @@ static int bad_syscall(int n, struct pt_regs *regs)
if (user_debug & UDBG_SYSCALL) {
printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n",
task_pid_nr(current), current->comm, n);
- dump_instr(regs);
+ dump_instr(KERN_ERR, regs);
}
#endif
@@ -579,7 +585,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
if (user_debug & UDBG_SYSCALL) {
printk("[%d] %s: arm syscall %d\n",
task_pid_nr(current), current->comm, no);
- dump_instr(regs);
+ dump_instr("", regs);
if (user_mode(regs)) {
__show_regs(regs);
c_backtrace(regs->ARM_fp, processor_mode(regs));
@@ -656,7 +662,7 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
if (user_debug & UDBG_BADABORT) {
printk(KERN_ERR "[%d] %s: bad data abort: code %d instr 0x%08lx\n",
task_pid_nr(current), current->comm, code, instr);
- dump_instr(regs);
+ dump_instr(KERN_ERR, regs);
show_pte(current->mm, addr);
}
#endif
diff --git a/arch/arm/mach-bcmring/core.c b/arch/arm/mach-bcmring/core.c
index 4b4f69251b31..e590bbe0a7b4 100644
--- a/arch/arm/mach-bcmring/core.c
+++ b/arch/arm/mach-bcmring/core.c
@@ -271,12 +271,12 @@ static struct irqaction bcmring_timer_irq = {
.handler = bcmring_timer_interrupt,
};
-static cycle_t bcmring_get_cycles_timer1(void)
+static cycle_t bcmring_get_cycles_timer1(struct clocksource *cs)
{
return ~readl(TIMER1_VA_BASE + TIMER_VALUE);
}
-static cycle_t bcmring_get_cycles_timer3(void)
+static cycle_t bcmring_get_cycles_timer3(struct clocksource *cs)
{
return ~readl(TIMER3_VA_BASE + TIMER_VALUE);
}
diff --git a/arch/arm/mach-bcmring/include/mach/system.h b/arch/arm/mach-bcmring/include/mach/system.h
index cdbf93c694a6..38b37060d426 100644
--- a/arch/arm/mach-bcmring/include/mach/system.h
+++ b/arch/arm/mach-bcmring/include/mach/system.h
@@ -29,7 +29,7 @@ static inline void arch_idle(void)
cpu_do_idle();
}
-static inline void arch_reset(char mode, char *cmd)
+static inline void arch_reset(char mode, const char *cmd)
{
printk("arch_reset:%c %x\n", mode, bcmring_arch_warm_reboot);
diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
index d7291c682a64..9167c3d2a5ed 100644
--- a/arch/arm/mach-ep93xx/Kconfig
+++ b/arch/arm/mach-ep93xx/Kconfig
@@ -17,13 +17,31 @@ config EP93XX_SDCE3_SYNC_PHYS_OFFSET
bool "0x00000000 - SDCE3/SyncBoot"
help
Select this option if you want support for EP93xx boards with the
- first SDRAM bank at 0x00000000
+ first SDRAM bank at 0x00000000.
config EP93XX_SDCE0_PHYS_OFFSET
bool "0xc0000000 - SDCEO"
help
Select this option if you want support for EP93xx boards with the
- first SDRAM bank at 0xc0000000
+ first SDRAM bank at 0xc0000000.
+
+config EP93XX_SDCE1_PHYS_OFFSET
+ bool "0xd0000000 - SDCE1"
+ help
+ Select this option if you want support for EP93xx boards with the
+ first SDRAM bank at 0xd0000000.
+
+config EP93XX_SDCE2_PHYS_OFFSET
+ bool "0xe0000000 - SDCE2"
+ help
+ Select this option if you want support for EP93xx boards with the
+ first SDRAM bank at 0xe0000000.
+
+config EP93XX_SDCE3_ASYNC_PHYS_OFFSET
+ bool "0xf0000000 - SDCE3/AsyncBoot"
+ help
+ Select this option if you want support for EP93xx boards with the
+ first SDRAM bank at 0xf0000000.
endchoice
@@ -112,28 +130,36 @@ config MACH_MICRO9
bool
config MACH_MICRO9H
- bool "Support Contec Hypercontrol Micro9-H"
+ bool "Support Contec Micro9-High"
depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
select MACH_MICRO9
help
Say 'Y' here if you want your kernel to support the
- Contec Hypercontrol Micro9-H board.
+ Contec Micro9-High board.
config MACH_MICRO9M
- bool "Support Contec Hypercontrol Micro9-M"
- depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
+ bool "Support Contec Micro9-Mid"
+ depends on EP93XX_SDCE3_ASYNC_PHYS_OFFSET
select MACH_MICRO9
help
Say 'Y' here if you want your kernel to support the
- Contec Hypercontrol Micro9-M board.
+ Contec Micro9-Mid board.
config MACH_MICRO9L
- bool "Support Contec Hypercontrol Micro9-L"
+ bool "Support Contec Micro9-Lite"
depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
select MACH_MICRO9
help
Say 'Y' here if you want your kernel to support the
- Contec Hypercontrol Micro9-L board.
+ Contec Micro9-Lite board.
+
+config MACH_MICRO9S
+ bool "Support Contec Micro9-Slim"
+ depends on EP93XX_SDCE3_ASYNC_PHYS_OFFSET
+ select MACH_MICRO9
+ help
+ Say 'Y' here if you want your kernel to support the
+ Contec Micro9-Slim board.
config MACH_TS72XX
bool "Support Technologic Systems TS-72xx SBC"
diff --git a/arch/arm/mach-ep93xx/Makefile.boot b/arch/arm/mach-ep93xx/Makefile.boot
index 27a085a8f12a..0ad33f15c622 100644
--- a/arch/arm/mach-ep93xx/Makefile.boot
+++ b/arch/arm/mach-ep93xx/Makefile.boot
@@ -3,3 +3,12 @@ params_phys-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET) := 0x00000100
zreladdr-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET) := 0xc0008000
params_phys-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET) := 0xc0000100
+
+ zreladdr-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET) := 0xd0008000
+params_phys-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET) := 0xd0000100
+
+ zreladdr-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET) := 0xe0008000
+params_phys-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET) := 0xe0000100
+
+ zreladdr-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET) := 0xf0008000
+params_phys-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET) := 0xf0000100
diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c
index dda19cd76194..1d0f9d8aff2e 100644
--- a/arch/arm/mach-ep93xx/clock.c
+++ b/arch/arm/mach-ep93xx/clock.c
@@ -16,13 +16,16 @@
#include <linux/module.h>
#include <linux/string.h>
#include <linux/io.h>
+#include <linux/spinlock.h>
+
+#include <mach/hardware.h>
#include <asm/clkdev.h>
#include <asm/div64.h>
-#include <mach/hardware.h>
struct clk {
+ struct clk *parent;
unsigned long rate;
int users;
int sw_locked;
@@ -39,40 +42,60 @@ static unsigned long get_uart_rate(struct clk *clk);
static int set_keytchclk_rate(struct clk *clk, unsigned long rate);
static int set_div_rate(struct clk *clk, unsigned long rate);
+
+static struct clk clk_xtali = {
+ .rate = EP93XX_EXT_CLK_RATE,
+};
static struct clk clk_uart1 = {
+ .parent = &clk_xtali,
.sw_locked = 1,
.enable_reg = EP93XX_SYSCON_DEVCFG,
.enable_mask = EP93XX_SYSCON_DEVCFG_U1EN,
.get_rate = get_uart_rate,
};
static struct clk clk_uart2 = {
+ .parent = &clk_xtali,
.sw_locked = 1,
.enable_reg = EP93XX_SYSCON_DEVCFG,
.enable_mask = EP93XX_SYSCON_DEVCFG_U2EN,
.get_rate = get_uart_rate,
};
static struct clk clk_uart3 = {
+ .parent = &clk_xtali,
.sw_locked = 1,
.enable_reg = EP93XX_SYSCON_DEVCFG,
.enable_mask = EP93XX_SYSCON_DEVCFG_U3EN,
.get_rate = get_uart_rate,
};
-static struct clk clk_pll1;
-static struct clk clk_f;
-static struct clk clk_h;
-static struct clk clk_p;
-static struct clk clk_pll2;
+static struct clk clk_pll1 = {
+ .parent = &clk_xtali,
+};
+static struct clk clk_f = {
+ .parent = &clk_pll1,
+};
+static struct clk clk_h = {
+ .parent = &clk_pll1,
+};
+static struct clk clk_p = {
+ .parent = &clk_pll1,
+};
+static struct clk clk_pll2 = {
+ .parent = &clk_xtali,
+};
static struct clk clk_usb_host = {
+ .parent = &clk_pll2,
.enable_reg = EP93XX_SYSCON_PWRCNT,
.enable_mask = EP93XX_SYSCON_PWRCNT_USH_EN,
};
static struct clk clk_keypad = {
+ .parent = &clk_xtali,
.sw_locked = 1,
.enable_reg = EP93XX_SYSCON_KEYTCHCLKDIV,
.enable_mask = EP93XX_SYSCON_KEYTCHCLKDIV_KEN,
.set_rate = set_keytchclk_rate,
};
static struct clk clk_pwm = {
+ .parent = &clk_xtali,
.rate = EP93XX_EXT_CLK_RATE,
};
@@ -85,50 +108,62 @@ static struct clk clk_video = {
/* DMA Clocks */
static struct clk clk_m2p0 = {
+ .parent = &clk_h,
.enable_reg = EP93XX_SYSCON_PWRCNT,
.enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P0,
};
static struct clk clk_m2p1 = {
+ .parent = &clk_h,
.enable_reg = EP93XX_SYSCON_PWRCNT,
.enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P1,
};
static struct clk clk_m2p2 = {
+ .parent = &clk_h,
.enable_reg = EP93XX_SYSCON_PWRCNT,
.enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P2,
};
static struct clk clk_m2p3 = {
+ .parent = &clk_h,
.enable_reg = EP93XX_SYSCON_PWRCNT,
.enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P3,
};
static struct clk clk_m2p4 = {
+ .parent = &clk_h,
.enable_reg = EP93XX_SYSCON_PWRCNT,
.enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P4,
};
static struct clk clk_m2p5 = {
+ .parent = &clk_h,
.enable_reg = EP93XX_SYSCON_PWRCNT,
.enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P5,
};
static struct clk clk_m2p6 = {
+ .parent = &clk_h,
.enable_reg = EP93XX_SYSCON_PWRCNT,
.enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P6,
};
static struct clk clk_m2p7 = {
+ .parent = &clk_h,
.enable_reg = EP93XX_SYSCON_PWRCNT,
.enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P7,
};
static struct clk clk_m2p8 = {
+ .parent = &clk_h,
.enable_reg = EP93XX_SYSCON_PWRCNT,
.enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P8,
};
static struct clk clk_m2p9 = {
+ .parent = &clk_h,
.enable_reg = EP93XX_SYSCON_PWRCNT,
.enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P9,
};
static struct clk clk_m2m0 = {
+ .parent = &clk_h,
.enable_reg = EP93XX_SYSCON_PWRCNT,
.enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2M0,
};
static struct clk clk_m2m1 = {
+ .parent = &clk_h,
.enable_reg = EP93XX_SYSCON_PWRCNT,
.enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2M1,
};
@@ -137,6 +172,7 @@ static struct clk clk_m2m1 = {
{ .dev_id = dev, .con_id = con, .clk = ck }
static struct clk_lookup clocks[] = {
+ INIT_CK(NULL, "xtali", &clk_xtali),
INIT_CK("apb:uart1", NULL, &clk_uart1),
INIT_CK("apb:uart2", NULL, &clk_uart2),
INIT_CK("apb:uart3", NULL, &clk_uart3),
@@ -163,48 +199,84 @@ static struct clk_lookup clocks[] = {
INIT_CK(NULL, "m2m1", &clk_m2m1),
};
+static DEFINE_SPINLOCK(clk_lock);
+
+static void __clk_enable(struct clk *clk)
+{
+ if (!clk->users++) {
+ if (clk->parent)
+ __clk_enable(clk->parent);
+
+ if (clk->enable_reg) {
+ u32 v;
+
+ v = __raw_readl(clk->enable_reg);
+ v |= clk->enable_mask;
+ if (clk->sw_locked)
+ ep93xx_syscon_swlocked_write(v, clk->enable_reg);
+ else
+ __raw_writel(v, clk->enable_reg);
+ }
+ }
+}
int clk_enable(struct clk *clk)
{
- if (!clk->users++ && clk->enable_reg) {
- u32 value;
+ unsigned long flags;
- value = __raw_readl(clk->enable_reg);
- value |= clk->enable_mask;
- if (clk->sw_locked)
- ep93xx_syscon_swlocked_write(value, clk->enable_reg);
- else
- __raw_writel(value, clk->enable_reg);
- }
+ if (!clk)
+ return -EINVAL;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ __clk_enable(clk);
+ spin_unlock_irqrestore(&clk_lock, flags);
return 0;
}
EXPORT_SYMBOL(clk_enable);
-void clk_disable(struct clk *clk)
+static void __clk_disable(struct clk *clk)
{
- if (!--clk->users && clk->enable_reg) {
- u32 value;
+ if (!--clk->users) {
+ if (clk->enable_reg) {
+ u32 v;
+
+ v = __raw_readl(clk->enable_reg);
+ v &= ~clk->enable_mask;
+ if (clk->sw_locked)
+ ep93xx_syscon_swlocked_write(v, clk->enable_reg);
+ else
+ __raw_writel(v, clk->enable_reg);
+ }
- value = __raw_readl(clk->enable_reg);
- value &= ~clk->enable_mask;
- if (clk->sw_locked)
- ep93xx_syscon_swlocked_write(value, clk->enable_reg);
- else
- __raw_writel(value, clk->enable_reg);
+ if (clk->parent)
+ __clk_disable(clk->parent);
}
}
+
+void clk_disable(struct clk *clk)
+{
+ unsigned long flags;
+
+ if (!clk)
+ return;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ __clk_disable(clk);
+ spin_unlock_irqrestore(&clk_lock, flags);
+}
EXPORT_SYMBOL(clk_disable);
static unsigned long get_uart_rate(struct clk *clk)
{
+ unsigned long rate = clk_get_rate(clk->parent);
u32 value;
value = __raw_readl(EP93XX_SYSCON_PWRCNT);
if (value & EP93XX_SYSCON_PWRCNT_UARTBAUD)
- return EP93XX_EXT_CLK_RATE;
+ return rate;
else
- return EP93XX_EXT_CLK_RATE / 2;
+ return rate / 2;
}
unsigned long clk_get_rate(struct clk *clk)
@@ -244,16 +316,16 @@ static int set_keytchclk_rate(struct clk *clk, unsigned long rate)
return 0;
}
-static unsigned long calc_clk_div(unsigned long rate, int *psel, int *esel,
- int *pdiv, int *div)
+static int calc_clk_div(struct clk *clk, unsigned long rate,
+ int *psel, int *esel, int *pdiv, int *div)
{
- unsigned long max_rate, best_rate = 0,
- actual_rate = 0, mclk_rate = 0, rate_err = -1;
+ struct clk *mclk;
+ unsigned long max_rate, actual_rate, mclk_rate, rate_err = -1;
int i, found = 0, __div = 0, __pdiv = 0;
/* Don't exceed the maximum rate */
max_rate = max(max(clk_pll1.rate / 4, clk_pll2.rate / 4),
- (unsigned long)EP93XX_EXT_CLK_RATE / 4);
+ clk_xtali.rate / 4);
rate = min(rate, max_rate);
/*
@@ -267,11 +339,12 @@ static unsigned long calc_clk_div(unsigned long rate, int *psel, int *esel,
*/
for (i = 0; i < 3; i++) {
if (i == 0)
- mclk_rate = EP93XX_EXT_CLK_RATE * 2;
+ mclk = &clk_xtali;
else if (i == 1)
- mclk_rate = clk_pll1.rate * 2;
- else if (i == 2)
- mclk_rate = clk_pll2.rate * 2;
+ mclk = &clk_pll1;
+ else
+ mclk = &clk_pll2;
+ mclk_rate = mclk->rate * 2;
/* Try each predivider value */
for (__pdiv = 4; __pdiv <= 6; __pdiv++) {
@@ -286,7 +359,8 @@ static unsigned long calc_clk_div(unsigned long rate, int *psel, int *esel,
*div = __div;
*psel = (i == 2);
*esel = (i != 0);
- best_rate = actual_rate;
+ clk->parent = mclk;
+ clk->rate = actual_rate;
rate_err = abs(actual_rate - rate);
found = 1;
}
@@ -294,21 +368,19 @@ static unsigned long calc_clk_div(unsigned long rate, int *psel, int *esel,
}
if (!found)
- return 0;
+ return -EINVAL;
- return best_rate;
+ return 0;
}
static int set_div_rate(struct clk *clk, unsigned long rate)
{
- unsigned long actual_rate;
- int psel = 0, esel = 0, pdiv = 0, div = 0;
+ int err, psel = 0, esel = 0, pdiv = 0, div = 0;
u32 val;
- actual_rate = calc_clk_div(rate, &psel, &esel, &pdiv, &div);
- if (actual_rate == 0)
- return -EINVAL;
- clk->rate = actual_rate;
+ err = calc_clk_div(clk, rate, &psel, &esel, &pdiv, &div);
+ if (err)
+ return err;
/* Clear the esel, psel, pdiv and div bits */
val = __raw_readl(clk->enable_reg);
@@ -344,7 +416,7 @@ static unsigned long calc_pll_rate(u32 config_word)
unsigned long long rate;
int i;
- rate = EP93XX_EXT_CLK_RATE;
+ rate = clk_xtali.rate;
rate *= ((config_word >> 11) & 0x1f) + 1; /* X1FBD */
rate *= ((config_word >> 5) & 0x3f) + 1; /* X2FBD */
do_div(rate, (config_word & 0x1f) + 1); /* X2IPD */
@@ -377,7 +449,7 @@ static int __init ep93xx_clock_init(void)
value = __raw_readl(EP93XX_SYSCON_CLOCK_SET1);
if (!(value & 0x00800000)) { /* PLL1 bypassed? */
- clk_pll1.rate = EP93XX_EXT_CLK_RATE;
+ clk_pll1.rate = clk_xtali.rate;
} else {
clk_pll1.rate = calc_pll_rate(value);
}
@@ -388,7 +460,7 @@ static int __init ep93xx_clock_init(void)
value = __raw_readl(EP93XX_SYSCON_CLOCK_SET2);
if (!(value & 0x00080000)) { /* PLL2 bypassed? */
- clk_pll2.rate = EP93XX_EXT_CLK_RATE;
+ clk_pll2.rate = clk_xtali.rate;
} else if (value & 0x00040000) { /* PLL2 enabled? */
clk_pll2.rate = calc_pll_rate(value);
} else {
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index f7ebed942f66..f95dc160c34b 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -550,13 +550,11 @@ void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr)
platform_device_register(&ep93xx_eth_device);
}
-static struct i2c_gpio_platform_data ep93xx_i2c_data = {
- .sda_pin = EP93XX_GPIO_LINE_EEDAT,
- .sda_is_open_drain = 0,
- .scl_pin = EP93XX_GPIO_LINE_EECLK,
- .scl_is_open_drain = 0,
- .udelay = 2,
-};
+
+/*************************************************************************
+ * EP93xx i2c peripheral handling
+ *************************************************************************/
+static struct i2c_gpio_platform_data ep93xx_i2c_data;
static struct platform_device ep93xx_i2c_device = {
.name = "i2c-gpio",
@@ -564,8 +562,25 @@ static struct platform_device ep93xx_i2c_device = {
.dev.platform_data = &ep93xx_i2c_data,
};
-void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num)
+void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
+ struct i2c_board_info *devices, int num)
{
+ /*
+ * Set the EEPROM interface pin drive type control.
+ * Defines the driver type for the EECLK and EEDAT pins as either
+ * open drain, which will require an external pull-up, or a normal
+ * CMOS driver.
+ */
+ if (data->sda_is_open_drain && data->sda_pin != EP93XX_GPIO_LINE_EEDAT)
+ pr_warning("ep93xx: sda != EEDAT, open drain has no effect\n");
+ if (data->scl_is_open_drain && data->scl_pin != EP93XX_GPIO_LINE_EECLK)
+ pr_warning("ep93xx: scl != EECLK, open drain has no effect\n");
+
+ __raw_writel((data->sda_is_open_drain << 1) |
+ (data->scl_is_open_drain << 0),
+ EP93XX_GPIO_EEDRIVE);
+
+ ep93xx_i2c_data = *data;
i2c_register_board_info(0, devices, num);
platform_device_register(&ep93xx_i2c_device);
}
diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c
index 73145ae5d3fa..ca71cf1a72a0 100644
--- a/arch/arm/mach-ep93xx/edb93xx.c
+++ b/arch/arm/mach-ep93xx/edb93xx.c
@@ -27,8 +27,10 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/i2c.h>
#include <linux/mtd/physmap.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
#include <mach/hardware.h>
@@ -76,13 +78,26 @@ static struct ep93xx_eth_data edb93xx_eth_data = {
.phy_id = 1,
};
-static struct i2c_board_info __initdata edb93xxa_i2c_data[] = {
+
+/*************************************************************************
+ * EDB93xx i2c peripheral handling
+ *************************************************************************/
+static struct i2c_gpio_platform_data edb93xx_i2c_gpio_data = {
+ .sda_pin = EP93XX_GPIO_LINE_EEDAT,
+ .sda_is_open_drain = 0,
+ .scl_pin = EP93XX_GPIO_LINE_EECLK,
+ .scl_is_open_drain = 0,
+ .udelay = 0, /* default to 100 kHz */
+ .timeout = 0, /* default to 100 ms */
+};
+
+static struct i2c_board_info __initdata edb93xxa_i2c_board_info