forked from Minki/linux
Merge branches 'arm-mm', 'at91', 'clkevts', 'imx', 'iop', 'misc', 'netx', 'ns9xxx', 'omap', 'pxa', 'rpc', 's3c' and 'sa1100' into devel
This commit is contained in:
parent
3603ab2b62
93afa75230
075192ae80
ff4bfb2163
ad902cb9e2
1b11652286
fe7fdb80e9
13ea55b04e
fcf126d847
7053acbd78
5559bca8e6
d0fdb5a58e
d0a9d75b9c
commit
6f95416ebe
@ -62,7 +62,7 @@ static struct resource pxa_spi_nssp_resources[] = {
|
||||
|
||||
static struct pxa2xx_spi_master pxa_nssp_master_info = {
|
||||
.ssp_type = PXA25x_NSSP, /* Type of SSP */
|
||||
.clock_enable = CKEN9_NSSP, /* NSSP Peripheral clock */
|
||||
.clock_enable = CKEN_NSSP, /* NSSP Peripheral clock */
|
||||
.num_chipselect = 1, /* Matches the number of chips attached to NSSP */
|
||||
.enable_dma = 1, /* Enables NSSP DMA */
|
||||
};
|
||||
|
@ -29,6 +29,10 @@ config GENERIC_TIME
|
||||
bool
|
||||
default n
|
||||
|
||||
config GENERIC_CLOCKEVENTS
|
||||
bool
|
||||
default n
|
||||
|
||||
config MMU
|
||||
bool
|
||||
default y
|
||||
@ -67,6 +71,14 @@ config GENERIC_HARDIRQS
|
||||
bool
|
||||
default y
|
||||
|
||||
config STACKTRACE_SUPPORT
|
||||
bool
|
||||
default y
|
||||
|
||||
config LOCKDEP_SUPPORT
|
||||
bool
|
||||
default y
|
||||
|
||||
config TRACE_IRQFLAGS_SUPPORT
|
||||
bool
|
||||
default y
|
||||
@ -162,6 +174,8 @@ config ARCH_VERSATILE
|
||||
select ARM_AMBA
|
||||
select ARM_VIC
|
||||
select ICST307
|
||||
select GENERIC_TIME
|
||||
select GENERIC_CLOCKEVENTS
|
||||
help
|
||||
This enables support for ARM Ltd Versatile board.
|
||||
|
||||
@ -262,6 +276,7 @@ config ARCH_IXP4XX
|
||||
bool "IXP4xx-based"
|
||||
depends on MMU
|
||||
select GENERIC_TIME
|
||||
select GENERIC_CLOCKEVENTS
|
||||
help
|
||||
Support for Intel's IXP4XX (XScale) family of processors.
|
||||
|
||||
@ -363,6 +378,7 @@ config ARCH_LH7A40X
|
||||
config ARCH_OMAP
|
||||
bool "TI OMAP"
|
||||
select GENERIC_GPIO
|
||||
select GENERIC_TIME
|
||||
help
|
||||
Support for TI's OMAP platform (OMAP1 and OMAP2).
|
||||
|
||||
@ -513,6 +529,8 @@ endmenu
|
||||
|
||||
menu "Kernel Features"
|
||||
|
||||
source "kernel/time/Kconfig"
|
||||
|
||||
config SMP
|
||||
bool "Symmetric Multi-Processing (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL && REALVIEW_MPCORE
|
||||
@ -572,6 +590,7 @@ config PREEMPT
|
||||
|
||||
config NO_IDLE_HZ
|
||||
bool "Dynamic tick timer"
|
||||
depends on !GENERIC_CLOCKEVENTS
|
||||
help
|
||||
Select this option if you want to disable continuous timer ticks
|
||||
and have them programmed to occur as required. This option saves
|
||||
@ -669,6 +688,7 @@ config LEDS_TIMER
|
||||
bool "Timer LED" if (!ARCH_CDB89712 && !ARCH_OMAP) || \
|
||||
MACH_OMAP_H2 || MACH_OMAP_PERSEUS2
|
||||
depends on LEDS
|
||||
depends on !GENERIC_CLOCKEVENTS
|
||||
default y if ARCH_EBSA110
|
||||
help
|
||||
If you say Y here, one of the system LEDs (the green one on the
|
||||
|
@ -61,6 +61,12 @@
|
||||
cmp r7, r3
|
||||
beq 99f
|
||||
|
||||
@ picotux 200 : 963
|
||||
mov r3, #(MACH_TYPE_PICOTUX2XX & 0xff)
|
||||
orr r3, r3, #(MACH_TYPE_PICOTUX2XX & 0xff00)
|
||||
cmp r7, r3
|
||||
beq 99f
|
||||
|
||||
@ Ajeco 1ARM : 1075
|
||||
mov r3, #(MACH_TYPE_ONEARM & 0xff)
|
||||
orr r3, r3, #(MACH_TYPE_ONEARM & 0xff00)
|
||||
|
1386
arch/arm/configs/picotux200_defconfig
Normal file
1386
arch/arm/configs/picotux200_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
@ -7,8 +7,8 @@ AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
|
||||
# Object file lists.
|
||||
|
||||
obj-y := compat.o entry-armv.o entry-common.o irq.o \
|
||||
process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
|
||||
time.o traps.o
|
||||
process.o ptrace.o semaphore.o setup.o signal.o \
|
||||
sys_arm.o stacktrace.o time.o traps.o
|
||||
|
||||
obj-$(CONFIG_ISA_DMA_API) += dma.o
|
||||
obj-$(CONFIG_ARCH_ACORN) += ecard.o
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/kthread.h>
|
||||
|
||||
#include <asm/dma.h>
|
||||
#include <asm/ecard.h>
|
||||
@ -50,6 +51,8 @@
|
||||
#include <asm/mach/irq.h>
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
#include "ecard.h"
|
||||
|
||||
#ifndef CONFIG_ARCH_RPC
|
||||
#define HAVE_EXPMASK
|
||||
#endif
|
||||
@ -123,7 +126,7 @@ static void ecard_task_reset(struct ecard_request *req)
|
||||
|
||||
res = ec->slot_no == 8
|
||||
? &ec->resource[ECARD_RES_MEMC]
|
||||
: ec->type == ECARD_EASI
|
||||
: ec->easi
|
||||
? &ec->resource[ECARD_RES_EASI]
|
||||
: &ec->resource[ECARD_RES_IOCSYNC];
|
||||
|
||||
@ -178,7 +181,7 @@ static void ecard_task_readbytes(struct ecard_request *req)
|
||||
index += 1;
|
||||
}
|
||||
} else {
|
||||
unsigned long base = (ec->type == ECARD_EASI
|
||||
unsigned long base = (ec->easi
|
||||
? &ec->resource[ECARD_RES_EASI]
|
||||
: &ec->resource[ECARD_RES_IOCSYNC])->start;
|
||||
void __iomem *pbase = (void __iomem *)base;
|
||||
@ -263,8 +266,6 @@ static int ecard_init_mm(void)
|
||||
static int
|
||||
ecard_task(void * unused)
|
||||
{
|
||||
daemonize("kecardd");
|
||||
|
||||
/*
|
||||
* Allocate a mm. We're not a lazy-TLB kernel task since we need
|
||||
* to set page table entries where the user space would be. Note
|
||||
@ -727,7 +728,7 @@ static int ecard_prints(char *buffer, ecard_t *ec)
|
||||
char *start = buffer;
|
||||
|
||||
buffer += sprintf(buffer, " %d: %s ", ec->slot_no,
|
||||
ec->type == ECARD_EASI ? "EASI" : " ");
|
||||
ec->easi ? "EASI" : " ");
|
||||
|
||||
if (ec->cid.id == 0) {
|
||||
struct in_chunk_dir incd;
|
||||
@ -814,7 +815,7 @@ static struct expansion_card *__init ecard_alloc_card(int type, int slot)
|
||||
}
|
||||
|
||||
ec->slot_no = slot;
|
||||
ec->type = type;
|
||||
ec->easi = type == ECARD_EASI;
|
||||
ec->irq = NO_IRQ;
|
||||
ec->fiq = NO_IRQ;
|
||||
ec->dma = NO_DMA;
|
||||
@ -825,6 +826,7 @@ static struct expansion_card *__init ecard_alloc_card(int type, int slot)
|
||||
ec->dev.bus = &ecard_bus_type;
|
||||
ec->dev.dma_mask = &ec->dma_mask;
|
||||
ec->dma_mask = (u64)0xffffffff;
|
||||
ec->dev.coherent_dma_mask = ec->dma_mask;
|
||||
|
||||
if (slot < 4) {
|
||||
ec_set_resource(ec, ECARD_RES_MEMC,
|
||||
@ -907,7 +909,7 @@ static ssize_t ecard_show_device(struct device *dev, struct device_attribute *at
|
||||
static ssize_t ecard_show_type(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct expansion_card *ec = ECARD_DEV(dev);
|
||||
return sprintf(buf, "%s\n", ec->type == ECARD_EASI ? "EASI" : "IOC");
|
||||
return sprintf(buf, "%s\n", ec->easi ? "EASI" : "IOC");
|
||||
}
|
||||
|
||||
static struct device_attribute ecard_dev_attrs[] = {
|
||||
@ -1058,13 +1060,14 @@ ecard_probe(int slot, card_type_t type)
|
||||
*/
|
||||
static int __init ecard_init(void)
|
||||
{
|
||||
int slot, irqhw, ret;
|
||||
struct task_struct *task;
|
||||
int slot, irqhw;
|
||||
|
||||
ret = kernel_thread(ecard_task, NULL, CLONE_KERNEL);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "Ecard: unable to create kernel thread: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
task = kthread_run(ecard_task, NULL, "kecardd");
|
||||
if (IS_ERR(task)) {
|
||||
printk(KERN_ERR "Ecard: unable to create kernel thread: %ld\n",
|
||||
PTR_ERR(task));
|
||||
return PTR_ERR(task);
|
||||
}
|
||||
|
||||
printk("Probing expansion cards\n");
|
||||
|
56
arch/arm/kernel/ecard.h
Normal file
56
arch/arm/kernel/ecard.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* ecard.h
|
||||
*
|
||||
* Copyright 2007 Russell King
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Definitions internal to ecard.c - for it's use only!!
|
||||
*
|
||||
* External expansion card header as read from the card
|
||||
*/
|
||||
struct ex_ecid {
|
||||
unsigned char r_irq:1;
|
||||
unsigned char r_zero:1;
|
||||
unsigned char r_fiq:1;
|
||||
unsigned char r_id:4;
|
||||
unsigned char r_a:1;
|
||||
|
||||
unsigned char r_cd:1;
|
||||
unsigned char r_is:1;
|
||||
unsigned char r_w:2;
|
||||
unsigned char r_r1:4;
|
||||
|
||||
unsigned char r_r2:8;
|
||||
|
||||
unsigned char r_prod[2];
|
||||
|
||||
unsigned char r_manu[2];
|
||||
|
||||
unsigned char r_country;
|
||||
|
||||
unsigned char r_fiqmask;
|
||||
unsigned char r_fiqoff[3];
|
||||
|
||||
unsigned char r_irqmask;
|
||||
unsigned char r_irqoff[3];
|
||||
};
|
||||
|
||||
/*
|
||||
* Chunk directory entry as read from the card
|
||||
*/
|
||||
struct ex_chunk_dir {
|
||||
unsigned char r_id;
|
||||
unsigned char r_len[3];
|
||||
unsigned long r_start;
|
||||
union {
|
||||
char string[256];
|
||||
char data[1];
|
||||
} d;
|
||||
#define c_id(x) ((x)->r_id)
|
||||
#define c_len(x) ((x)->r_len[0]|((x)->r_len[1]<<8)|((x)->r_len[2]<<16))
|
||||
#define c_start(x) ((x)->r_start)
|
||||
};
|
@ -257,7 +257,9 @@ __create_page_tables:
|
||||
* Map some ram to cover our .data and .bss areas.
|
||||
*/
|
||||
orr r3, r7, #(KERNEL_RAM_PADDR & 0xff000000)
|
||||
.if (KERNEL_RAM_PADDR & 0x00f00000)
|
||||
orr r3, r3, #(KERNEL_RAM_PADDR & 0x00f00000)
|
||||
.endif
|
||||
add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> 18
|
||||
str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> 18]!
|
||||
ldr r6, =(_end - 1)
|
||||
@ -274,7 +276,9 @@ __create_page_tables:
|
||||
*/
|
||||
add r0, r4, #PAGE_OFFSET >> 18
|
||||
orr r6, r7, #(PHYS_OFFSET & 0xff000000)
|
||||
orr r6, r6, #(PHYS_OFFSET & 0x00e00000)
|
||||
.if (PHYS_OFFSET & 0x00f00000)
|
||||
orr r6, r6, #(PHYS_OFFSET & 0x00f00000)
|
||||
.endif
|
||||
str r6, [r0]
|
||||
|
||||
#ifdef CONFIG_DEBUG_LL
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/elfcore.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/tick.h>
|
||||
|
||||
#include <asm/leds.h>
|
||||
#include <asm/processor.h>
|
||||
@ -159,9 +160,11 @@ void cpu_idle(void)
|
||||
if (!idle)
|
||||
idle = default_idle;
|
||||
leds_event(led_idle_start);
|
||||
tick_nohz_stop_sched_tick();
|
||||
while (!need_resched())
|
||||
idle();
|
||||
leds_event(led_idle_end);
|
||||
tick_nohz_restart_sched_tick();
|
||||
preempt_enable_no_resched();
|
||||
schedule();
|
||||
preempt_disable();
|
||||
|
@ -779,8 +779,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
||||
break;
|
||||
|
||||
case PTRACE_SET_SYSCALL:
|
||||
task_thread_info(child)->syscall = data;
|
||||
ret = 0;
|
||||
child->ptrace_message = data;
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_CRUNCH
|
||||
@ -817,7 +817,7 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
|
||||
ip = regs->ARM_ip;
|
||||
regs->ARM_ip = why;
|
||||
|
||||
current->ptrace_message = scno;
|
||||
current_thread_info()->syscall = scno;
|
||||
|
||||
/* the 0x80 provides a way for the tracing parent to distinguish
|
||||
between a syscall stop and SIGTRAP delivery */
|
||||
@ -834,5 +834,5 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
|
||||
}
|
||||
regs->ARM_ip = ip;
|
||||
|
||||
return current->ptrace_message;
|
||||
return current_thread_info()->syscall;
|
||||
}
|
||||
|
73
arch/arm/kernel/stacktrace.c
Normal file
73
arch/arm/kernel/stacktrace.c
Normal file
@ -0,0 +1,73 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/stacktrace.h>
|
||||
|
||||
#include "stacktrace.h"
|
||||
|
||||
int walk_stackframe(unsigned long fp, unsigned long low, unsigned long high,
|
||||
int (*fn)(struct stackframe *, void *), void *data)
|
||||
{
|
||||
struct stackframe *frame;
|
||||
|
||||
do {
|
||||
/*
|
||||
* Check current frame pointer is within bounds
|
||||
*/
|
||||
if ((fp - 12) < low || fp + 4 >= high)
|
||||
break;
|
||||
|
||||
frame = (struct stackframe *)(fp - 12);
|
||||
|
||||
if (fn(frame, data))
|
||||
break;
|
||||
|
||||
/*
|
||||
* Update the low bound - the next frame must always
|
||||
* be at a higher address than the current frame.
|
||||
*/
|
||||
low = fp + 4;
|
||||
fp = frame->fp;
|
||||
} while (fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_STACKTRACE
|
||||
struct stack_trace_data {
|
||||
struct stack_trace *trace;
|
||||
unsigned int skip;
|
||||
};
|
||||
|
||||
static int save_trace(struct stackframe *frame, void *d)
|
||||
{
|
||||
struct stack_trace_data *data = d;
|
||||
struct stack_trace *trace = data->trace;
|
||||
|
||||
if (data->skip) {
|
||||
data->skip--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
trace->entries[trace->nr_entries++] = frame->lr;
|
||||
|
||||
return trace->nr_entries >= trace->max_entries;
|
||||
}
|
||||
|
||||
void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
|
||||
{
|
||||
struct stack_trace_data data;
|
||||
unsigned long fp, base;
|
||||
|
||||
data.trace = trace;
|
||||
data.skip = trace->skip;
|
||||
|
||||
if (task) {
|
||||
base = (unsigned long)task_stack_page(task);
|
||||
fp = 0; /* FIXME */
|
||||
} else {
|
||||
base = (unsigned long)task_stack_page(current);
|
||||
asm("mov %0, fp" : "=r" (fp));
|
||||
}
|
||||
|
||||
walk_stackframe(fp, base, base + THREAD_SIZE, save_trace, &data);
|
||||
}
|
||||
#endif
|
9
arch/arm/kernel/stacktrace.h
Normal file
9
arch/arm/kernel/stacktrace.h
Normal file
@ -0,0 +1,9 @@
|
||||
struct stackframe {
|
||||
unsigned long fp;
|
||||
unsigned long sp;
|
||||
unsigned long lr;
|
||||
unsigned long pc;
|
||||
};
|
||||
|
||||
int walk_stackframe(unsigned long fp, unsigned long low, unsigned long high,
|
||||
int (*fn)(struct stackframe *, void *), void *data);
|
@ -327,6 +327,7 @@ void restore_time_delta(struct timespec *delta, struct timespec *rtc)
|
||||
}
|
||||
EXPORT_SYMBOL(restore_time_delta);
|
||||
|
||||
#ifndef CONFIG_GENERIC_CLOCKEVENTS
|
||||
/*
|
||||
* Kernel system timer support.
|
||||
*/
|
||||
@ -340,8 +341,9 @@ void timer_tick(void)
|
||||
update_process_times(user_mode(get_irq_regs()));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#if defined(CONFIG_PM) && !defined(CONFIG_GENERIC_CLOCKEVENTS)
|
||||
static int timer_suspend(struct sys_device *dev, pm_message_t state)
|
||||
{
|
||||
struct sys_timer *timer = container_of(dev, struct sys_timer, dev);
|
||||
|
@ -286,6 +286,7 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
|
||||
struct undef_hook *hook;
|
||||
siginfo_t info;
|
||||
void __user *pc;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* According to the ARM ARM, PC is 2 or 4 bytes ahead,
|
||||
@ -304,7 +305,7 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
|
||||
get_user(instr, (u32 __user *)pc);
|
||||
}
|
||||
|
||||
spin_lock_irq(&undef_lock);
|
||||
spin_lock_irqsave(&undef_lock, flags);
|
||||
list_for_each_entry(hook, &undef_hook, node) {
|
||||
if ((instr & hook->instr_mask) == hook->instr_val &&
|
||||
(regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) {
|
||||
@ -314,7 +315,7 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock_irq(&undef_lock);
|
||||
spin_unlock_irqrestore(&undef_lock, flags);
|
||||
|
||||
#ifdef CONFIG_DEBUG_USER
|
||||
if (user_debug & UDBG_UNDEFINED) {
|
||||
|
@ -81,6 +81,13 @@ config MACH_KB9200
|
||||
Select this if you are using KwikByte's KB920x board.
|
||||
<http://kwikbyte.com/KB9202_description_new.htm>
|
||||
|
||||
config MACH_PICOTUX2XX
|
||||
bool "picotux 200"
|
||||
depends on ARCH_AT91RM9200
|
||||
help
|
||||
Select this if you are using a picotux 200.
|
||||
<http://www.picotux.com/>
|
||||
|
||||
config MACH_KAFA
|
||||
bool "Sperry-Sun KAFA board"
|
||||
depends on ARCH_AT91RM9200
|
||||
|
@ -25,6 +25,7 @@ obj-$(CONFIG_MACH_CARMEVA) += board-carmeva.o
|
||||
obj-$(CONFIG_MACH_KB9200) += board-kb9202.o
|
||||
obj-$(CONFIG_MACH_ATEB9200) += board-eb9200.o
|
||||
obj-$(CONFIG_MACH_KAFA) += board-kafa.o
|
||||
obj-$(CONFIG_MACH_PICOTUX2XX) += board-picotux200.o
|
||||
|
||||
# AT91SAM9260 board-specific support
|
||||
obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o
|
||||
|
@ -117,6 +117,21 @@ static struct clk pioD_clk = {
|
||||
.pmc_mask = 1 << AT91RM9200_ID_PIOD,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk ssc0_clk = {
|
||||
.name = "ssc0_clk",
|
||||
.pmc_mask = 1 << AT91RM9200_ID_SSC0,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk ssc1_clk = {
|
||||
.name = "ssc1_clk",
|
||||
.pmc_mask = 1 << AT91RM9200_ID_SSC1,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk ssc2_clk = {
|
||||
.name = "ssc2_clk",
|
||||
.pmc_mask = 1 << AT91RM9200_ID_SSC2,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk tc0_clk = {
|
||||
.name = "tc0_clk",
|
||||
.pmc_mask = 1 << AT91RM9200_ID_TC0,
|
||||
@ -161,7 +176,9 @@ static struct clk *periph_clocks[] __initdata = {
|
||||
&udc_clk,
|
||||
&twi_clk,
|
||||
&spi_clk,
|
||||
// ssc 0 .. ssc2
|
||||
&ssc0_clk,
|
||||
&ssc1_clk,
|
||||
&ssc2_clk,
|
||||
&tc0_clk,
|
||||
&tc1_clk,
|
||||
&tc2_clk,
|
||||
|
@ -119,6 +119,11 @@ static struct clk spi1_clk = {
|
||||
.pmc_mask = 1 << AT91SAM9260_ID_SPI1,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk ssc_clk = {
|
||||
.name = "ssc_clk",
|
||||
.pmc_mask = 1 << AT91SAM9260_ID_SSC,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk tc0_clk = {
|
||||
.name = "tc0_clk",
|
||||
.pmc_mask = 1 << AT91SAM9260_ID_TC0,
|
||||
@ -193,7 +198,7 @@ static struct clk *periph_clocks[] __initdata = {
|
||||
&twi_clk,
|
||||
&spi0_clk,
|
||||
&spi1_clk,
|
||||
// ssc
|
||||
&ssc_clk,
|
||||
&tc0_clk,
|
||||
&tc1_clk,
|
||||
&tc2_clk,
|
||||
|
@ -97,6 +97,21 @@ static struct clk spi1_clk = {
|
||||
.pmc_mask = 1 << AT91SAM9261_ID_SPI1,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk ssc0_clk = {
|
||||
.name = "ssc0_clk",
|
||||
.pmc_mask = 1 << AT91SAM9261_ID_SSC0,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk ssc1_clk = {
|
||||
.name = "ssc1_clk",
|
||||
.pmc_mask = 1 << AT91SAM9261_ID_SSC1,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk ssc2_clk = {
|
||||
.name = "ssc2_clk",
|
||||
.pmc_mask = 1 << AT91SAM9261_ID_SSC2,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk tc0_clk = {
|
||||
.name = "tc0_clk",
|
||||
.pmc_mask = 1 << AT91SAM9261_ID_TC0,
|
||||
@ -135,7 +150,9 @@ static struct clk *periph_clocks[] __initdata = {
|
||||
&twi_clk,
|
||||
&spi0_clk,
|
||||
&spi1_clk,
|
||||
// ssc 0 .. ssc2
|
||||
&ssc0_clk,
|
||||
&ssc1_clk,
|
||||
&ssc2_clk,
|
||||
&tc0_clk,
|
||||
&tc1_clk,
|
||||
&tc2_clk,
|
||||
|
@ -430,9 +430,9 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
|
||||
* LCD Controller
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#if defined(CONFIG_FB_AT91) || defined(CONFIG_FB_AT91_MODULE)
|
||||
#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
|
||||
static u64 lcdc_dmamask = 0xffffffffUL;
|
||||
static struct at91fb_info lcdc_data;
|
||||
static struct atmel_lcdfb_info lcdc_data;
|
||||
|
||||
static struct resource lcdc_resources[] = {
|
||||
[0] = {
|
||||
@ -455,7 +455,7 @@ static struct resource lcdc_resources[] = {
|
||||
};
|
||||
|
||||
static struct platform_device at91_lcdc_device = {
|
||||
.name = "at91-fb",
|
||||
.name = "atmel_lcdfb",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &lcdc_dmamask,
|
||||
@ -466,7 +466,7 @@ static struct platform_device at91_lcdc_device = {
|
||||
.num_resources = ARRAY_SIZE(lcdc_resources),
|
||||
};
|
||||
|
||||
void __init at91_add_device_lcdc(struct at91fb_info *data)
|
||||
void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
|
||||
{
|
||||
if (!data) {
|
||||
return;
|
||||
@ -499,7 +499,7 @@ void __init at91_add_device_lcdc(struct at91fb_info *data)
|
||||
platform_device_register(&at91_lcdc_device);
|
||||
}
|
||||
#else
|
||||
void __init at91_add_device_lcdc(struct at91fb_info *data) {}
|
||||
void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -87,6 +87,11 @@ static struct clk mmc1_clk = {
|
||||
.pmc_mask = 1 << AT91SAM9263_ID_MCI1,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk can_clk = {
|
||||
.name = "can_clk",
|
||||
.pmc_mask = 1 << AT91SAM9263_ID_CAN,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk twi_clk = {
|
||||
.name = "twi_clk",
|
||||
.pmc_mask = 1 << AT91SAM9263_ID_TWI,
|
||||
@ -102,16 +107,46 @@ static struct clk spi1_clk = {
|
||||
.pmc_mask = 1 << AT91SAM9263_ID_SPI1,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk ssc0_clk = {
|
||||
.name = "ssc0_clk",
|
||||
.pmc_mask = 1 << AT91SAM9263_ID_SSC0,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk ssc1_clk = {
|
||||
.name = "ssc1_clk",
|
||||
.pmc_mask = 1 << AT91SAM9263_ID_SSC1,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk ac97_clk = {
|
||||
.name = "ac97_clk",
|
||||
.pmc_mask = 1 << AT91SAM9263_ID_AC97C,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk tcb_clk = {
|
||||
.name = "tcb_clk",
|
||||
.pmc_mask = 1 << AT91SAM9263_ID_TCB,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk pwmc_clk = {
|
||||
.name = "pwmc_clk",
|
||||
.pmc_mask = 1 << AT91SAM9263_ID_PWMC,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk macb_clk = {
|
||||
.name = "macb_clk",
|
||||
.pmc_mask = 1 << AT91SAM9263_ID_EMAC,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk dma_clk = {
|
||||
.name = "dma_clk",
|
||||
.pmc_mask = 1 << AT91SAM9263_ID_DMA,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk twodge_clk = {
|
||||
.name = "2dge_clk",
|
||||
.pmc_mask = 1 << AT91SAM9263_ID_2DGE,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk udc_clk = {
|
||||
.name = "udc_clk",
|
||||
.pmc_mask = 1 << AT91SAM9263_ID_UDP,
|
||||
@ -142,20 +177,21 @@ static struct clk *periph_clocks[] __initdata = {
|
||||
&usart2_clk,
|
||||
&mmc0_clk,
|
||||
&mmc1_clk,
|
||||
// can
|
||||
&can_clk,
|
||||
&twi_clk,
|
||||
&spi0_clk,
|
||||
&spi1_clk,
|
||||
// ssc0 .. ssc1
|
||||
// ac97
|
||||
&ssc0_clk,
|
||||
&ssc1_clk,
|
||||
&ac97_clk,
|
||||
&tcb_clk,
|
||||
// pwmc
|
||||
&pwmc_clk,
|
||||
&macb_clk,
|
||||
// 2dge
|
||||
&twodge_clk,
|
||||
&udc_clk,
|
||||
&isi_clk,
|
||||
&lcdc_clk,
|
||||
// dma
|
||||
&dma_clk,
|
||||
&ohci_clk,
|
||||
// irq0 .. irq1
|
||||
};
|
||||
|
@ -572,6 +572,130 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
|
||||
#endif
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* AC97
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#if defined(CONFIG_SND_AT91_AC97) || defined(CONFIG_SND_AT91_AC97_MODULE)
|
||||
static u64 ac97_dmamask = 0xffffffffUL;
|
||||
static struct atmel_ac97_data ac97_data;
|
||||
|
||||
static struct resource ac97_resources[] = {
|
||||
[0] = {
|
||||
.start = AT91SAM9263_BASE_AC97C,
|
||||
.end = AT91SAM9263_BASE_AC97C + SZ_16K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = AT91SAM9263_ID_AC97C,
|
||||
.end = AT91SAM9263_ID_AC97C,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device at91sam9263_ac97_device = {
|
||||
.name = "ac97c",
|
||||
.id = 1,
|
||||
.dev = {
|
||||
.dma_mask = &ac97_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
.platform_data = &ac97_data,
|
||||
},
|
||||
.resource = ac97_resources,
|
||||
.num_resources = ARRAY_SIZE(ac97_resources),
|
||||
};
|
||||
|
||||
void __init at91_add_device_ac97(struct atmel_ac97_data *data)
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
at91_set_A_periph(AT91_PIN_PB0, 0); /* AC97FS */
|
||||
at91_set_A_periph(AT91_PIN_PB1, 0); /* AC97CK */
|
||||
at91_set_A_periph(AT91_PIN_PB2, 0); /* AC97TX */
|
||||
at91_set_A_periph(AT91_PIN_PB3, 0); /* AC97RX */
|
||||
|
||||
/* reset */
|
||||
if (data->reset_pin)
|
||||
at91_set_gpio_output(data->reset_pin, 0);
|
||||
|
||||
ac97_data = *ek_data;
|
||||
platform_device_register(&at91sam9263_ac97_device);
|
||||
}
|
||||
#else
|
||||
void __init at91_add_device_ac97(struct atmel_ac97_data *data) {}
|
||||
#endif
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* LCD Controller
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
|
||||
static u64 lcdc_dmamask = 0xffffffffUL;
|
||||
static struct atmel_lcdfb_info lcdc_data;
|
||||
|
||||
static struct resource lcdc_resources[] = {
|
||||
[0] = {
|
||||
.start = AT91SAM9263_LCDC_BASE,
|
||||
.end = AT91SAM9263_LCDC_BASE + SZ_4K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = AT91SAM9263_ID_LCDC,
|
||||
.end = AT91SAM9263_ID_LCDC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device at91_lcdc_device = {
|
||||
.name = "atmel_lcdfb",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &lcdc_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
.platform_data = &lcdc_data,
|
||||
},
|
||||
.resource = lcdc_resources,
|
||||
.num_resources = ARRAY_SIZE(lcdc_resources),
|
||||
};
|
||||
|
||||
void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
at91_set_A_periph(AT91_PIN_PC1, 0); /* LCDHSYNC */
|
||||
at91_set_A_periph(AT91_PIN_PC2, 0); /* LCDDOTCK */
|
||||
at91_set_A_periph(AT91_PIN_PC3, 0); /* LCDDEN */
|
||||
at91_set_B_periph(AT91_PIN_PB9, 0); /* LCDCC */
|
||||
at91_set_A_periph(AT91_PIN_PC6, 0); /* LCDD2 */
|
||||
at91_set_A_periph(AT91_PIN_PC7, 0); /* LCDD3 */
|
||||
at91_set_A_periph(AT91_PIN_PC8, 0); /* LCDD4 */
|
||||
at91_set_A_periph(AT91_PIN_PC9, 0); /* LCDD5 */
|
||||
at91_set_A_periph(AT91_PIN_PC10, 0); /* LCDD6 */
|
||||
at91_set_A_periph(AT91_PIN_PC11, 0); /* LCDD7 */
|
||||
at91_set_A_periph(AT91_PIN_PC14, 0); /* LCDD10 */
|
||||
at91_set_A_periph(AT91_PIN_PC15, 0); /* LCDD11 */
|
||||
at91_set_A_periph(AT91_PIN_PC16, 0); /* LCDD12 */
|
||||
at91_set_B_periph(AT91_PIN_PC12, 0); /* LCDD13 */
|
||||
at91_set_A_periph(AT91_PIN_PC18, 0); /* LCDD14 */
|
||||
at91_set_A_periph(AT91_PIN_PC19, 0); /* LCDD15 */
|
||||
at91_set_A_periph(AT91_PIN_PC22, 0); /* LCDD18 */
|
||||
at91_set_A_periph(AT91_PIN_PC23, 0); /* LCDD19 */
|
||||
at91_set_A_periph(AT91_PIN_PC24, 0); /* LCDD20 */
|
||||
at91_set_B_periph(AT91_PIN_PC17, 0); /* LCDD21 */
|
||||
at91_set_A_periph(AT91_PIN_PC26, 0); /* LCDD22 */
|
||||
at91_set_A_periph(AT91_PIN_PC27, 0); /* LCDD23 */
|
||||
|
||||
lcdc_data = *data;
|
||||
platform_device_register(&at91_lcdc_device);
|
||||
}
|
||||
#else
|
||||
void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
|
||||
#endif
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* LEDs
|
||||
* -------------------------------------------------------------------- */
|
||||
|
166
arch/arm/mach-at91/board-picotux200.c
Normal file
166
arch/arm/mach-at91/board-picotux200.c
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-at91/board-picotux200.c
|
||||
*
|
||||
* Copyright (C) 2005 SAN People
|
||||
* Copyright (C) 2007 Kleinhenz Elektronik GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/mtd/physmap.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/irq.h>
|
||||
|
||||
#include <asm/arch/board.h>
|
||||
#include <asm/arch/gpio.h>
|
||||
#include <asm/arch/at91rm9200_mc.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
|
||||
/*
|
||||
* Serial port configuration.
|
||||
* 0 .. 3 = USART0 .. USART3
|
||||
* 4 = DBGU
|
||||
*/
|
||||
static struct at91_uart_config __initdata picotux200_uart_config = {
|
||||
.console_tty = 0, /* ttyS0 */
|
||||
.nr_tty = 2,
|
||||
.tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */
|
||||
};
|
||||
|
||||
static void __init picotux200_map_io(void)
|
||||
{
|
||||
/* Initialize processor: 18.432 MHz crystal */
|
||||
at91rm9200_initialize(18432000, AT91RM9200_BGA);
|
||||
|
||||
/* Setup the serial ports and console */
|
||||
at91_init_serial(&picotux200_uart_config);
|
||||
}
|
||||
|
||||
static void __init picotux200_init_irq(void)
|
||||
{
|
||||
at91rm9200_init_interrupts(NULL);
|
||||
}
|
||||
|
||||
static struct at91_eth_data __initdata picotux200_eth_data = {
|
||||
.phy_irq_pin = AT91_PIN_PC4,
|
||||
.is_rmii = 1,
|
||||
};
|
||||
|
||||
static struct at91_usbh_data __initdata picotux200_usbh_data = {
|
||||
.ports = 1,
|
||||
};
|
||||
|
||||
// static struct at91_udc_data __initdata picotux200_udc_data = {
|
||||
// .vbus_pin = AT91_PIN_PD4,
|
||||
// .pullup_pin = AT91_PIN_PD5,
|
||||
// };
|
||||
|
||||
static struct at91_mmc_data __initdata picotux200_mmc_data = {
|
||||
.det_pin = AT91_PIN_PB27,
|
||||
.slot_b = 0,
|
||||
.wire4 = 1,
|
||||
.wp_pin = AT91_PIN_PA17,
|
||||
};
|
||||
|
||||
// static struct spi_board_info picotux200_spi_devices[] = {
|
||||
// { /* DataFlash chip */
|
||||
// .modalias = "mtd_dataflash",
|
||||
// .chip_select = 0,
|
||||
// .max_speed_hz = 15 * 1000 * 1000,
|
||||
// },
|
||||
// #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
|
||||
// { /* DataFlash card */
|
||||
// .modalias = "mtd_dataflash",
|
||||
// .chip_select = 3,
|
||||
// .max_speed_hz = 15 * 1000 * 1000,
|
||||
// },
|
||||
// #endif
|
||||
// };
|
||||
|
||||
#define PICOTUX200_FLASH_BASE AT91_CHIPSELECT_0
|
||||
#define PICOTUX200_FLASH_SIZE 0x400000
|
||||
|
||||
static struct physmap_flash_data picotux200_flash_data = {
|
||||
.width = 2,
|
||||
};
|
||||
|
||||
static struct resource picotux200_flash_resource = {
|
||||
.start = PICOTUX200_FLASH_BASE,
|
||||
.end = PICOTUX200_FLASH_BASE + PICOTUX200_FLASH_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
static struct platform_device picotux200_flash = {
|
||||
.name = "physmap-flash",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &picotux200_flash_data,
|
||||
},
|
||||
.resource = &picotux200_flash_resource,
|
||||
.num_resources = 1,
|
||||
};
|
||||
|
||||
static void __init picotux200_board_init(void)
|
||||
{
|
||||
/* Serial */
|
||||
at91_add_device_serial();
|
||||
/* Ethernet */
|
||||
at91_add_device_eth(&picotux200_eth_data);
|
||||
/* USB Host */
|
||||
at91_add_device_usbh(&picotux200_usbh_data);
|
||||
/* USB Device */
|
||||
// at91_add_device_udc(&picotux200_udc_data);
|
||||
// at91_set_multi_drive(picotux200_udc_data.pullup_pin, 1); /* pullup_pin is connected to reset */
|
||||
/* I2C */
|
||||
at91_add_device_i2c();
|
||||
/* SPI */
|
||||
// at91_add_device_spi(picotux200_spi_devices, ARRAY_SIZE(picotux200_spi_devices));
|
||||
#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
|
||||
/* DataFlash card */
|
||||
at91_set_gpio_output(AT91_PIN_PB22, 0);
|
||||
#else
|
||||
/* MMC */
|
||||
at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
|
||||
at91_add_device_mmc(0, &picotux200_mmc_data);
|
||||
#endif
|
||||
/* NOR Flash */
|
||||
platform_device_register(&picotux200_flash);
|
||||
}
|
||||
|
||||
MACHINE_START(PICOTUX2XX, "picotux 200")
|
||||
/* Maintainer: Kleinhenz Elektronik GmbH */
|
||||
.phys_io = AT91_BASE_SYS,
|
||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||
.timer = &at91rm9200_timer,
|
||||
.map_io = picotux200_map_io,
|
||||
.init_irq = picotux200_init_irq,
|
||||
.init_machine = picotux200_board_init,
|
||||
MACHINE_END
|
@ -104,9 +104,9 @@ static struct spi_board_info ek_spi_devices[] = {
|
||||
},
|
||||
#endif
|
||||
#endif
|
||||
#if defined(CONFIG_SND_AT73C213)
|
||||
#if defined(CONFIG_SND_AT73C213) || defined(CONFIG_SND_AT73C213_MODULE)
|
||||
{ /* AT73C213 DAC */
|
||||
.modalias = "snd_at73c213",
|
||||
.modalias = "at73c213",
|
||||
.chip_select = 0,
|
||||
.max_speed_hz = 10 * 1000 * 1000,
|
||||
.bus_num = 1,
|
||||
@ -118,7 +118,7 @@ static struct spi_board_info ek_spi_devices[] = {
|
||||
/*
|
||||
* MACB Ethernet device
|
||||
*/
|
||||
static struct __initdata at91_eth_data ek_macb_data = {
|
||||
static struct at91_eth_data __initdata ek_macb_data = {
|
||||
.phy_irq_pin = AT91_PIN_PA7,
|
||||
.is_rmii = 1,
|
||||
};
|
||||
@ -140,7 +140,7 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct mtd_partition *nand_partitions(int size, int *num_partitions)
|
||||
static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
|
||||
{
|
||||
*num_partitions = ARRAY_SIZE(ek_nand_partition);
|
||||
return ek_nand_partition;
|
||||
@ -188,6 +188,8 @@ static void __init ek_board_init(void)
|
||||
at91_add_device_eth(&ek_macb_data);
|
||||
/* MMC */
|
||||
at91_add_device_mmc(0, &ek_mmc_data);
|
||||
/* I2C */
|
||||
at91_add_device_i2c();
|
||||
}
|
||||
|
||||
MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/ads7846.h>
|
||||
#include <linux/dm9000.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
@ -194,6 +195,41 @@ static struct at91_nand_data __initdata ek_nand_data = {
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* ADS7846 Touchscreen
|
||||
*/
|
||||
#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
|
||||
|
||||
static int ads7843_pendown_state(void)
|
||||
{
|
||||
return !at91_get_gpio_value(AT91_PIN_PC2); /* Touchscreen PENIRQ */
|
||||
}
|
||||
|
||||
static struct ads7846_platform_data ads_info = {
|
||||
.model = 7843,
|
||||
.x_min = 150,
|
||||
.x_max = 3830,
|
||||
.y_min = 190,
|
||||
.y_max = 3830,
|
||||
.vref_delay_usecs = 100,
|
||||
.x_plate_ohms = 450,
|
||||
.y_plate_ohms = 250,
|
||||
.pressure_max = 15000,
|
||||
.debounce_max = 1,
|
||||
.debounce_rep = 0,
|
||||
.debounce_tol = (~0),
|
||||
.get_pendown_state = ads7843_pendown_state,
|
||||
};
|
||||
|
||||
static void __init ek_add_device_ts(void)
|
||||
{
|
||||
at91_set_B_periph(AT91_PIN_PC2, 1); /* External IRQ0, with pullup */
|
||||
at91_set_gpio_input(AT91_PIN_PA11, 1); /* Touchscreen BUSY signal */
|
||||
}
|
||||
#else
|
||||
static void __init ek_add_device_ts(void) {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SPI devices
|
||||
*/
|
||||
@ -204,6 +240,16 @@ static struct spi_board_info ek_spi_devices[] = {
|
||||
.max_speed_hz = 15 * 1000 * 1000,
|
||||
.bus_num = 0,
|
||||
},
|
||||
#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
|
||||
{
|
||||
.modalias = "ads7846",
|
||||
.chip_select = 2,
|
||||
.max_speed_hz = 125000 * 26, /* (max sample rate @ 3V) * (cmd + data + overhead) */
|
||||
.bus_num = 0,
|
||||
.platform_data = &ads_info,
|
||||
.irq = AT91SAM9261_ID_IRQ0,
|
||||
},
|
||||
#endif
|
||||
#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
|
||||
{ /* DataFlash card - jumper (J12) configurable to CS3 or CS0 */
|
||||
.modalias = "mtd_dataflash",
|
||||
@ -211,9 +257,9 @@ static struct spi_board_info ek_spi_devices[] = {
|
||||
.max_speed_hz = 15 * 1000 * 1000,
|
||||
.bus_num = 0,
|
||||
},
|
||||
#elif defined(CONFIG_SND_AT73C213)
|
||||
#elif defined(CONFIG_SND_AT73C213) || defined(CONFIG_SND_AT73C213_MODULE)
|
||||
{ /* AT73C213 DAC */
|
||||
.modalias = "snd_at73c213",
|
||||
.modalias = "at73c213",
|
||||
.chip_select = 3,
|
||||
.max_speed_hz = 10 * 1000 * 1000,
|
||||
.bus_num = 0,
|
||||
@ -241,6 +287,8 @@ static void __init ek_board_init(void)
|
||||
#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
|
||||
/* SPI */
|
||||
at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
|
||||
/* Touchscreen */
|
||||
ek_add_device_ts();
|
||||
#else
|
||||
/* MMC */
|
||||
at91_add_device_mmc(0, &ek_mmc_data);
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/ads7846.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/setup.h>
|
||||
@ -85,6 +86,40 @@ static struct at91_udc_data __initdata ek_udc_data = {
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* ADS7846 Touchscreen
|
||||
*/
|
||||
#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
|
||||
static int ads7843_pendown_state(void)
|
||||
{
|
||||
return !at91_get_gpio_value(AT91_PIN_PA15); /* Touchscreen PENIRQ */
|
||||
}
|
||||
|
||||
static struct ads7846_platform_data ads_info = {
|
||||
.model = 7843,
|
||||
.x_min = 150,
|
||||
.x_max = 3830,
|
||||
.y_min = 190,
|
||||
.y_max = 3830,
|
||||
.vref_delay_usecs = 100,
|
||||
.x_plate_ohms = 450,
|
||||
.y_plate_ohms = 250,
|
||||
.pressure_max = 15000,
|
||||
.debounce_max = 1,
|
||||
.debounce_rep = 0,
|
||||
.debounce_tol = (~0),
|
||||
.get_pendown_state = ads7843_pendown_state,
|
||||
};
|
||||
|
||||
static void __init ek_add_device_ts(void)
|
||||
{
|
||||
at91_set_B_periph(AT91_PIN_PA15, 1); /* External IRQ1, with pullup */
|
||||
at91_set_gpio_input(AT91_PIN_PA31, 1); /* Touchscreen BUSY signal */
|
||||
}
|
||||
#else
|
||||
static void __init ek_add_device_ts(void) {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SPI devices.
|
||||
*/
|
||||
@ -97,6 +132,16 @@ static struct spi_board_info ek_spi_devices[] = {
|
||||
.bus_num = 0,
|
||||
},
|
||||
#endif
|
||||
#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
|
||||
{
|
||||
.modalias = "ads7846",
|
||||
.chip_select = 3,
|
||||
.max_speed_hz = 125000 * 26, /* (max sample rate @ 3V) * (cmd + data + overhead) */
|
||||
.bus_num = 0,
|
||||
.platform_data = &ads_info,
|
||||
.irq = AT91SAM9263_ID_IRQ1,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@ -111,6 +156,14 @@ static struct at91_mmc_data __initdata ek_mmc_data = {
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* MACB Ethernet device
|
||||
*/
|
||||
static struct at91_eth_data __initdata ek_macb_data = {
|
||||
.is_rmii = 1,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* NAND flash
|
||||
*/
|
||||
@ -148,6 +201,14 @@ static struct at91_nand_data __initdata ek_nand_data = {
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* AC97
|
||||
*/
|
||||
static struct atmel_ac97_data ek_ac97_data = {
|
||||
.reset_pin = AT91_PIN_PA13,
|
||||
};
|
||||
|
||||
|
||||
static void __init ek_board_init(void)
|
||||
{
|
||||
/* Serial */
|
||||
@ -157,11 +218,20 @@ static void __init ek_board_init(void)
|
||||
/* USB Device */
|
||||
at91_add_device_udc(&ek_udc_data);
|
||||
/* SPI */
|
||||
at91_set_gpio_output(AT91_PIN_PE20, 1); /* select spi0 clock */
|
||||
at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
|
||||
/* Touchscreen */
|
||||
ek_add_device_ts();
|
||||
/* MMC */
|
||||
at91_add_device_mmc(1, &ek_mmc_data);
|
||||
/* Ethernet */
|
||||
at91_add_device_eth(&ek_macb_data);
|
||||
/* NAND */
|
||||
at91_add_device_nand(&ek_nand_data);
|
||||
/* I2C */
|
||||
at91_add_device_i2c();
|
||||
/* AC97 */
|
||||
at91_add_device_ac97(&ek_ac97_data);
|
||||
}
|
||||
|
||||
MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
|
||||
|
@ -27,6 +27,10 @@ struct clk {
|
||||
u32 enable_mask;
|
||||
};
|
||||
|
||||
static struct clk clk_uart = {
|
||||
.name = "UARTCLK",
|
||||
.rate = 14745600,
|
||||
};
|
||||
static struct clk clk_pll1 = {
|
||||
.name = "pll1",
|
||||
};
|
||||
@ -50,6 +54,7 @@ static struct clk clk_usb_host = {
|
||||
|
||||
|
||||
static struct clk *clocks[] = {
|
||||
&clk_uart,
|
||||
&clk_pll1,
|
||||
&clk_f,
|
||||
&clk_h,
|
||||
|
@ -7,5 +7,6 @@ obj-$(CONFIG_ARCH_IOP13XX) += setup.o
|
||||
obj-$(CONFIG_ARCH_IOP13XX) += irq.o
|
||||
obj-$(CONFIG_ARCH_IOP13XX) += pci.o
|
||||
obj-$(CONFIG_ARCH_IOP13XX) += io.o
|
||||
obj-$(CONFIG_ARCH_IOP13XX) += tpmi.o
|
||||
obj-$(CONFIG_MACH_IQ81340SC) += iq81340sc.o
|
||||
obj-$(CONFIG_MACH_IQ81340MC) += iq81340mc.o
|
||||
|
@ -75,11 +75,14 @@ static void __init iq81340mc_init(void)
|
||||
{
|
||||
iop13xx_platform_init();
|
||||
iq81340mc_pci_init();
|
||||
iop13xx_add_tpmi_devices();
|
||||
}
|
||||
|
||||
static void __init iq81340mc_timer_init(void)
|
||||
{
|
||||
iop_init_time(400000000);
|
||||
unsigned long bus_freq = iop13xx_core_freq() / iop13xx_xsi_bus_ratio();
|
||||
printk(KERN_DEBUG "%s: bus frequency: %lu\n", __FUNCTION__, bus_freq);
|
||||
iop_init_time(bus_freq);
|
||||
}
|
||||
|
||||
static struct sys_timer iq81340mc_timer = {
|
||||
|
@ -77,11 +77,14 @@ static void __init iq81340sc_init(void)
|
||||
{
|
||||
iop13xx_platform_init();
|
||||
iq81340sc_pci_init();
|
||||
iop13xx_add_tpmi_devices();
|
||||
}
|
||||
|
||||
static void __init iq81340sc_timer_init(void)
|
||||
{
|
||||
iop_init_time(400000000);
|
||||
unsigned long bus_freq = iop13xx_core_freq() / iop13xx_xsi_bus_ratio();
|
||||
printk(KERN_DEBUG "%s: bus frequency: %lu\n", __FUNCTION__, bus_freq);
|
||||
iop_init_time(bus_freq);
|
||||
}
|
||||
|
||||
static struct sys_timer iq81340sc_timer = {
|
||||
|
@ -1023,7 +1023,7 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
|
||||
<< IOP13XX_ATUX_PCIXSR_FUNC_NUM;
|
||||
__raw_writel(pcixsr, IOP13XX_ATUX_PCIXSR);
|
||||
|
||||
res[0].start = IOP13XX_PCIX_LOWER_IO_PA;
|
||||
res[0].start = IOP13XX_PCIX_LOWER_IO_PA + IOP13XX_PCIX_IO_BUS_OFFSET;
|
||||
res[0].end = IOP13XX_PCIX_UPPER_IO_PA;
|
||||
res[0].name = "IQ81340 ATUX PCI I/O Space";
|
||||
res[0].flags = IORESOURCE_IO;
|
||||
@ -1033,7 +1033,7 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
|
||||
res[1].name = "IQ81340 ATUX PCI Memory Space";
|
||||
res[1].flags = IORESOURCE_MEM;
|
||||
sys->mem_offset = IOP13XX_PCIX_MEM_OFFSET;
|
||||
sys->io_offset = IOP13XX_PCIX_IO_OFFSET;
|
||||
sys->io_offset = IOP13XX_PCIX_LOWER_IO_PA;
|
||||
break;
|
||||
case IOP13XX_INIT_ATU_ATUE:
|
||||
/* Note: the function number field in the PCSR is ro */
|
||||
@ -1044,7 +1044,7 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
|
||||
|
||||
__raw_writel(pcsr, IOP13XX_ATUE_PCSR);
|
||||
|
||||
res[0].start = IOP13XX_PCIE_LOWER_IO_PA;
|
||||
res[0].start = IOP13XX_PCIE_LOWER_IO_PA + IOP13XX_PCIE_IO_BUS_OFFSET;
|
||||
res[0].end = IOP13XX_PCIE_UPPER_IO_PA;
|
||||
res[0].name = "IQ81340 ATUE PCI I/O Space";
|
||||
res[0].flags = IORESOURCE_IO;
|
||||
@ -1054,7 +1054,7 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
|
||||
res[1].name = "IQ81340 ATUE PCI Memory Space";
|
||||
res[1].flags = IORESOURCE_MEM;
|
||||
sys->mem_offset = IOP13XX_PCIE_MEM_OFFSET;
|
||||
sys->io_offset = IOP13XX_PCIE_IO_OFFSET;
|
||||
sys->io_offset = IOP13XX_PCIE_LOWER_IO_PA;
|
||||
sys->map_irq = iop13xx_pcie_map_irq;
|
||||
break;
|
||||
default:
|
||||
|
@ -258,15 +258,11 @@ void __init iop13xx_platform_init(void)
|
||||
|
||||
if (init_uart == IOP13XX_INIT_UART_DEFAULT) {
|
||||
switch (iop13xx_dev_id()) {
|
||||
/* enable both uarts on iop341 and iop342 */
|
||||
/* enable both uarts on iop341 */
|
||||
case 0x3380:
|
||||
case 0x3384:
|
||||
case 0x3388:
|
||||
case 0x338c:
|
||||
case 0x3382:
|
||||
case 0x3386:
|
||||
case 0x338a:
|
||||
case 0x338e:
|
||||
init_uart |= IOP13XX_INIT_UART_0;
|
||||
init_uart |= IOP13XX_INIT_UART_1;
|
||||
break;
|
||||
|
234
arch/arm/mach-iop13xx/tpmi.c
Normal file
234
arch/arm/mach-iop13xx/tpmi.c
Normal file
@ -0,0 +1,234 @@
|
||||
/*
|
||||
* iop13xx tpmi device resources
|
||||
* Copyright (c) 2005-2006, Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place - Suite 330, Boston, MA 02111-1307 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/sizes.h>
|
||||
|
||||
/* assumes CONTROLLER_ONLY# is never asserted in the ESSR register */
|
||||
#define IOP13XX_TPMI_MMR(dev) IOP13XX_REG_ADDR32_PHYS(0x48000 + (dev << 12))
|
||||
#define IOP13XX_TPMI_MEM(dev) IOP13XX_REG_ADDR32_PHYS(0x60000 + (dev << 13))
|
||||
#define IOP13XX_TPMI_CTRL(dev) IOP13XX_REG_ADDR32_PHYS(0x50000 + (dev << 10))
|
||||
#define IOP13XX_TPMI_MMR_SIZE (SZ_4K - 1)
|
||||
#define IOP13XX_TPMI_MEM_SIZE (255)
|
||||
#define IOP13XX_TPMI_MEM_CTRL (SZ_1K - 1)
|
||||
#define IOP13XX_TPMI_RESOURCE_MMR 0
|
||||
#define IOP13XX_TPMI_RESOURCE_MEM 1
|
||||
#define IOP13XX_TPMI_RESOURCE_CTRL 2
|
||||
#define IOP13XX_TPMI_RESOURCE_IRQ 3
|
||||
|
||||
static struct resource iop13xx_tpmi_0_resources[] = {
|
||||
[IOP13XX_TPMI_RESOURCE_MMR] = {
|
||||
.start = IOP13XX_TPMI_MMR(4), /* tpmi0 starts at dev == 4 */
|
||||
.end = IOP13XX_TPMI_MMR(4) + IOP13XX_TPMI_MMR_SIZE,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[IOP13XX_TPMI_RESOURCE_MEM] = {
|
||||
.start = IOP13XX_TPMI_MEM(0),
|
||||
.end = IOP13XX_TPMI_MEM(0) + IOP13XX_TPMI_MEM_SIZE,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[IOP13XX_TPMI_RESOURCE_CTRL] = {
|
||||
.start = IOP13XX_TPMI_CTRL(0),
|
||||
.end = IOP13XX_TPMI_CTRL(0) + IOP13XX_TPMI_MEM_CTRL,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[IOP13XX_TPMI_RESOURCE_IRQ] = {
|
||||
.start = IRQ_IOP13XX_TPMI0_OUT,
|
||||
.end = IRQ_IOP13XX_TPMI0_OUT,
|
||||
.flags = IORESOURCE_IRQ
|
||||
}
|
||||
};
|
||||
|
||||
static struct resource iop13xx_tpmi_1_resources[] = {
|
||||
[IOP13XX_TPMI_RESOURCE_MMR] = {
|
||||
.start = IOP13XX_TPMI_MMR(1),
|
||||
.end = IOP13XX_TPMI_MMR(1) + IOP13XX_TPMI_MMR_SIZE,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[IOP13XX_TPMI_RESOURCE_MEM] = {
|
||||
.start = IOP13XX_TPMI_MEM(1),
|
||||
.end = IOP13XX_TPMI_MEM(1) + IOP13XX_TPMI_MEM_SIZE,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[IOP13XX_TPMI_RESOURCE_CTRL] = {
|
||||
.start = IOP13XX_TPMI_CTRL(1),
|
||||
.end = IOP13XX_TPMI_CTRL(1) + IOP13XX_TPMI_MEM_CTRL,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[IOP13XX_TPMI_RESOURCE_IRQ] = {
|
||||
.start = IRQ_IOP13XX_TPMI1_OUT,
|
||||
.end = IRQ_IOP13XX_TPMI1_OUT,
|
||||
.flags = IORESOURCE_IRQ
|
||||
}
|
||||
};
|
||||
|
||||
static struct resource iop13xx_tpmi_2_resources[] = {
|
||||
[IOP13XX_TPMI_RESOURCE_MMR] = {
|
||||
.start = IOP13XX_TPMI_MMR(2),
|
||||
.end = IOP13XX_TPMI_MMR(2) + IOP13XX_TPMI_MMR_SIZE,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[IOP13XX_TPMI_RESOURCE_MEM] = {
|
||||
.start = IOP13XX_TPMI_MEM(2),
|
||||
.end = IOP13XX_TPMI_MEM(2) + IOP13XX_TPMI_MEM_SIZE,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[IOP13XX_TPMI_RESOURCE_CTRL] = {
|
||||
.start = IOP13XX_TPMI_CTRL(2),
|
||||
.end = IOP13XX_TPMI_CTRL(2) + IOP13XX_TPMI_MEM_CTRL,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[IOP13XX_TPMI_RESOURCE_IRQ] = {
|
||||
.start = IRQ_IOP13XX_TPMI2_OUT,
|
||||
.end = IRQ_IOP13XX_TPMI2_OUT,
|
||||
.flags = IORESOURCE_IRQ
|
||||
}
|
||||
};
|
||||
|
||||
static struct resource iop13xx_tpmi_3_resources[] = {
|
||||
[IOP13XX_TPMI_RESOURCE_MMR] = {
|
||||
.start = IOP13XX_TPMI_MMR(3),
|
||||
.end = IOP13XX_TPMI_MMR(3) + IOP13XX_TPMI_MMR_SIZE,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[IOP13XX_TPMI_RESOURCE_MEM] = {
|
||||
.start = IOP13XX_TPMI_MEM(3),
|
||||
.end = IOP13XX_TPMI_MEM(3) + IOP13XX_TPMI_MEM_SIZE,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[IOP13XX_TPMI_RESOURCE_CTRL] = {
|
||||
.start = IOP13XX_TPMI_CTRL(3),
|
||||
.end = IOP13XX_TPMI_CTRL(3) + IOP13XX_TPMI_MEM_CTRL,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[IOP13XX_TPMI_RESOURCE_IRQ] = {
|
||||
.start = IRQ_IOP13XX_TPMI3_OUT,
|
||||
.end = IRQ_IOP13XX_TPMI3_OUT,
|
||||
.flags = IORESOURCE_IRQ
|
||||
}
|
||||
};
|
||||
|
||||
u64 iop13xx_tpmi_mask = DMA_64BIT_MASK;
|
||||
static struct platform_device iop13xx_tpmi_0_device = {
|
||||
.name = "iop-tpmi",
|
||||
.id = 0,
|
||||
.num_resources = 4,
|
||||
.resource = iop13xx_tpmi_0_resources,
|
||||
.dev = {
|
||||
.dma_mask = &iop13xx_tpmi_mask,
|
||||
.coherent_dma_mask = DMA_64BIT_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device iop13xx_tpmi_1_device = {
|
||||
.name = "iop-tpmi",
|
||||
.id = 1,
|
||||
.num_resources = 4,
|
||||
.resource = iop13xx_tpmi_1_resources,
|
||||
.dev = {
|
||||
.dma_mask = &iop13xx_tpmi_mask,
|
||||
.coherent_dma_mask = DMA_64BIT_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device iop13xx_tpmi_2_device = {
|
||||
.name = "iop-tpmi",
|
||||
.id = 2,
|
||||
.num_resources = 4,
|
||||
.resource = iop13xx_tpmi_2_resources,
|
||||
.dev = {
|
||||
.dma_mask = &iop13xx_tpmi_mask,
|
||||
.coherent_dma_mask = DMA_64BIT_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device iop13xx_tpmi_3_device = {
|
||||
.name = "iop-tpmi",
|
||||
.id = 3,
|
||||
.num_resources = 4,
|
||||
.resource = iop13xx_tpmi_3_resources,
|
||||
.dev = {
|
||||
.dma_mask = &iop13xx_tpmi_mask,
|
||||
.coherent_dma_mask = DMA_64BIT_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
__init void iop13xx_add_tpmi_devices(void)
|
||||
{
|
||||
unsigned short device_id;
|
||||
|
||||
/* tpmi's not present on iop341 or iop342 */
|
||||
if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX)
|
||||
/* ATUE must be present */
|
||||
device_id = __raw_readw(IOP13XX_ATUE_DID);
|
||||
else
|
||||
/* ATUX must be present */
|
||||
device_id = __raw_readw(IOP13XX_ATUX_DID);
|
||||
|
||||
switch (device_id) {
|
||||
/* iop34[1|2] 0-tpmi */
|
||||
case 0x3380:
|
||||
case 0x3384:
|
||||
case 0x3388:
|
||||
case 0x338c:
|
||||
case 0x3382:
|
||||
case 0x3386:
|
||||
case 0x338a:
|
||||
case 0x338e:
|
||||
return;
|
||||
/* iop348 1-tpmi */
|
||||
case 0x3310:
|
||||
case 0x3312:
|
||||
case 0x3314:
|
||||
case 0x3318:
|
||||
case 0x331a:
|
||||
case 0x331c:
|
||||
case 0x33c0:
|
||||
case 0x33c2:
|
||||
case 0x33c4:
|
||||
case 0x33c8:
|
||||
case 0x33ca:
|
||||
case 0x33cc:
|
||||
case 0x33b0:
|
||||
case 0x33b2:
|
||||
case 0x33b4:
|
||||
case 0x33b8:
|
||||
case 0x33ba:
|
||||
case 0x33bc:
|
||||
case 0x3320:
|
||||
case 0x3322:
|
||||
case 0x3324:
|
||||
case 0x3328:
|
||||
case 0x332a:
|
||||
case 0x332c:
|
||||
platform_device_register(&iop13xx_tpmi_0_device);
|
||||
return;
|
||||
default:
|
||||
platform_device_register(&iop13xx_tpmi_0_device);
|
||||
platform_device_register(&iop13xx_tpmi_1_device);
|
||||
platform_device_register(&iop13xx_tpmi_2_device);
|
||||
platform_device_register(&iop13xx_tpmi_3_device);
|
||||
return;
|
||||
}
|
||||
}
|
@ -34,6 +34,14 @@ config MACH_N2100
|
||||
Say Y here if you want to run your kernel on the Thecus n2100
|
||||
NAS appliance.
|
||||
|
||||
config IOP3XX_ATU
|
||||
bool "Enable the PCI Controller"
|
||||
default y
|
||||
help
|
||||
Say Y here if you want the IOP to initialize its PCI Controller.
|
||||
Say N if the IOP is an add in card, the host system owns the PCI
|
||||
bus in this case.
|
||||
|
||||
endmenu
|
||||
|
||||
endif
|
||||
|
@ -178,9 +178,10 @@ static struct hw_pci iq31244_pci __initdata = {
|
||||
|
||||
static int __init iq31244_pci_init(void)
|
||||
{
|
||||
if (is_ep80219())
|
||||
if (is_ep80219()) {
|
||||
if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE)
|
||||
pci_common_init(&ep80219_pci);
|
||||
else if (machine_is_iq31244()) {
|
||||
} else if (machine_is_iq31244()) {
|
||||
if (is_80219()) {
|
||||
printk("note: iq31244 board type has been selected\n");
|
||||
printk("note: to select ep80219 operation:\n");
|
||||
@ -189,6 +190,8 @@ static int __init iq31244_pci_init(void)
|
||||
printk("\t2/ update boot loader to pass"
|
||||
" the ep80219 id: %d\n", MACH_TYPE_EP80219);
|
||||
}
|
||||
|
||||
if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE)
|
||||
pci_common_init(&iq31244_pci);
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,8 @@ static struct hw_pci iq80321_pci __initdata = {
|
||||
|
||||
static int __init iq80321_pci_init(void)
|
||||
{
|
||||
if (machine_is_iq80321())
|
||||
if ((iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) &&
|
||||
machine_is_iq80321())
|
||||
pci_common_init(&iq80321_pci);
|
||||
|
||||
return 0;
|
||||
|
@ -16,6 +16,14 @@ config MACH_IQ80332
|
||||
Say Y here if you want to run your kernel on the Intel IQ80332
|
||||
evaluation kit for the IOP332 chipset.
|
||||
|
||||
config IOP3XX_ATU
|
||||
bool "Enable the PCI Controller"
|
||||
default y
|
||||
help
|
||||
Say Y here if you want the IOP to initialize its PCI Controller.
|
||||
Say N if the IOP is an add in card, the host system owns the PCI
|
||||
bus in this case.
|
||||
|
||||
endmenu
|
||||
|
||||
endif
|
||||
|
@ -96,7 +96,8 @@ static struct hw_pci iq80331_pci __initdata = {
|
||||
|
||||
static int __init iq80331_pci_init(void)
|
||||
{
|
||||
if (machine_is_iq80331())
|
||||
if ((iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) &&
|
||||
machine_is_iq80331())
|
||||
pci_common_init(&iq80331_pci);
|
||||
|
||||
return 0;
|
||||
|
@ -96,7 +96,8 @@ static struct hw_pci iq80332_pci __initdata = {
|
||||
|
||||
static int __init iq80332_pci_init(void)
|
||||
{
|
||||
if (machine_is_iq80332())
|
||||
if ((iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) &&
|
||||
machine_is_iq80332())
|
||||
pci_common_init(&iq80332_pci);
|
||||
|
||||
return 0;
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <linux/time.h>
|
||||
#include <linux/timex.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/clockchips.h>
|
||||
|
||||
#include <asm/arch/udc.h>
|
||||
#include <asm/hardware.h>
|
||||
@ -41,6 +42,8 @@
|
||||
#include <asm/mach/time.h>
|
||||
|
||||
static int __init ixp4xx_clocksource_init(void);
|
||||
static int __init ixp4xx_clockevent_init(void);
|
||||
static struct clock_event_device clockevent_ixp4xx;
|
||||
|
||||
/*************************************************************************
|
||||
* IXP4xx chipset I/O mapping
|
||||
@ -239,52 +242,40 @@ void __init ixp4xx_init_irq(void)
|
||||
* counter as a source of real clock ticks to account for missed jiffies.
|
||||
*************************************************************************/
|
||||
|
||||
static unsigned volatile last_jiffy_time;
|
||||
|
||||
#define CLOCK_TICKS_PER_USEC ((CLOCK_TICK_RATE + USEC_PER_SEC/2) / USEC_PER_SEC)
|
||||
|
||||
static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
write_seqlock(&xtime_lock);
|
||||
struct clock_event_device *evt = &clockevent_ixp4xx;
|
||||
|
||||
/* Clear Pending Interrupt by writing '1' to it */
|
||||
*IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND;
|
||||
|
||||
/*
|
||||
* Catch up with the real idea of time
|
||||
*/
|
||||
while ((signed long)(*IXP4XX_OSTS - last_jiffy_time) >= LATCH) {
|
||||
timer_tick();
|
||||
last_jiffy_time += LATCH;
|
||||
}
|
||||
|
||||
write_sequnlock(&xtime_lock);
|
||||
evt->event_handler(evt);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct irqaction ixp4xx_timer_irq = {
|
||||
.name = "IXP4xx Timer Tick",
|
||||
.name = "timer1",
|
||||
.flags = IRQF_DISABLED | IRQF_TIMER,
|
||||
.handler = ixp4xx_timer_interrupt,
|
||||
};
|
||||
|
||||
static void __init ixp4xx_timer_init(void)
|
||||
{
|
||||
/* Reset/disable counter */
|
||||
*IXP4XX_OSRT1 = 0;
|
||||
|
||||
/* Clear Pending Interrupt by writing '1' to it */
|
||||
*IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND;
|
||||
|
||||
/* Setup the Timer counter value */
|
||||
*IXP4XX_OSRT1 = (LATCH & ~IXP4XX_OST_RELOAD_MASK) | IXP4XX_OST_ENABLE;
|
||||
|
||||
/* Reset time-stamp counter */
|
||||
*IXP4XX_OSTS = 0;
|
||||
last_jiffy_time = 0;
|
||||
|
||||
/* Connect the interrupt handler and enable the interrupt */
|
||||
setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq);
|
||||
|
||||
ixp4xx_clocksource_init();
|
||||
ixp4xx_clockevent_init();
|
||||
}
|
||||
|
||||
struct sys_timer ixp4xx_timer = {
|
||||
@ -384,6 +375,9 @@ void __init ixp4xx_sys_init(void)
|
||||
ixp4xx_exp_bus_size >> 20);
|
||||
}
|
||||
|
||||
/*
|
||||
* clocksource
|
||||
*/
|
||||
cycle_t ixp4xx_get_cycles(void)
|
||||
{
|
||||
return *IXP4XX_OSTS;
|
||||
@ -408,3 +402,64 @@ static int __init ixp4xx_clocksource_init(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* clockevents
|
||||
*/
|
||||
static int ixp4xx_set_next_event(unsigned long evt,
|
||||
struct clock_event_device *unused)
|
||||
{
|
||||
unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK;
|
||||
|
||||
*IXP4XX_OSRT1 = (evt & ~IXP4XX_OST_RELOAD_MASK) | opts;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ixp4xx_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
unsigned long opts, osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK;
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
osrt = LATCH & ~IXP4XX_OST_RELOAD_MASK;
|
||||
opts = IXP4XX_OST_ENABLE;
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
/* period set by 'set next_event' */
|
||||
osrt = 0;
|
||||
opts = IXP4XX_OST_ENABLE | IXP4XX_OST_ONE_SHOT;
|
||||
break;
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
default:
|
||||
osrt = opts = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
*IXP4XX_OSRT1 = osrt | opts;
|
||||
}
|
||||
|
||||
static struct clock_event_device clockevent_ixp4xx = {
|
||||
.name = "ixp4xx timer1",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.rating = 200,
|
||||
.shift = 24,
|
||||
.set_mode = ixp4xx_set_mode,
|
||||
.set_next_event = ixp4xx_set_next_event,
|
||||
};
|
||||
|
||||
static int __init ixp4xx_clockevent_init(void)
|
||||
{
|
||||
clockevent_ixp4xx.mult = div_sc(FREQ, NSEC_PER_SEC,
|
||||
clockevent_ixp4xx.shift);
|
||||
clockevent_ixp4xx.max_delta_ns =
|
||||
clockevent_delta2ns(0xfffffffe, &clockevent_ixp4xx);
|
||||
clockevent_ixp4xx.min_delta_ns =
|
||||
clockevent_delta2ns(0xf, &clockevent_ixp4xx);
|
||||
clockevent_ixp4xx.cpumask = cpumask_of_cpu(0);
|
||||
|
||||
clockevents_register_device(&clockevent_ixp4xx);
|
||||
return 0;
|
||||
}
|
||||
|
@ -10,12 +10,23 @@ config MACH_CC9P9360DEV
|
||||
Say Y here if you are using the Digi ConnectCore 9P 9360
|
||||
on an A9M9750 Development Board.
|
||||
|
||||
config MACH_CC9P9360JS
|
||||
bool "ConnectCore 9P 9360 on a JSCC9P9360 Devboard"
|
||||
select PROCESSOR_NS9360
|
||||
select BOARD_JSCC9P9360
|
||||
help
|
||||
Say Y here if you are using the Digi ConnectCore 9P 9360
|
||||
on an JSCC9P9360 Development Board.
|
||||
|
||||
config PROCESSOR_NS9360
|
||||
bool
|
||||
|
||||
config BOARD_A9M9750DEV
|
||||
bool
|
||||
|
||||
config BOARD_JSCC9P9360
|
||||
bool
|
||||
|
||||
endmenu
|
||||
|
||||
endif
|
||||
|
@ -3,3 +3,4 @@ obj-y := irq.o time.o generic.o
|
||||
obj-$(CONFIG_MACH_CC9P9360DEV) += mach-cc9p9360dev.o
|
||||
|
||||
obj-$(CONFIG_BOARD_A9M9750DEV) += board-a9m9750dev.o
|
||||
obj-$(CONFIG_BOARD_JSCC9P9360) += board-jscc9p9360.o
|
||||
|
17
arch/arm/mach-ns9xxx/board-jscc9p9360.c
Normal file
17
arch/arm/mach-ns9xxx/board-jscc9p9360.c
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* arch/arm/mach-ns9xxx/board-jscc9p9360.c
|
||||
*
|
||||
* Copyright (C) 2006,2007 by Digi International Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
#include "board-jscc9p9360.h"
|
||||
|
||||
void __init board_jscc9p9360_init_machine(void)
|
||||
{
|
||||
/* TODO: reserve GPIOs for push buttons, etc pp */
|
||||
}
|
||||
|
13
arch/arm/mach-ns9xxx/board-jscc9p9360.h
Normal file
13
arch/arm/mach-ns9xxx/board-jscc9p9360.h
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* arch/arm/mach-ns9xxx/board-jscc9p9360.h
|
||||
*
|
||||
* Copyright (C) 2006 by Digi International Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
|
||||
void __init board_jscc9p9360_init_machine(void);
|
29
arch/arm/mach-ns9xxx/mach-cc9p9360js.c
Normal file
29
arch/arm/mach-ns9xxx/mach-cc9p9360js.c
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* arch/arm/mach-ns9xxx/mach-cc9p9360js.c
|
||||
*
|
||||
* Copyright (C) 2006 by Digi International Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include "board-jscc9p9360.h"
|
||||
#include "generic.h"
|
||||
|
||||
static void __init mach_cc9p9360js_init_machine(void)
|
||||
{
|
||||
ns9xxx_init_machine();
|
||||
board_jscc9p9360_init_machine();
|
||||
}
|
||||
|
||||
MACHINE_START(CC9P9360DEV, "Digi ConnectCore 9P 9360 on an JSCC9P9360 Devboard")
|
||||
.map_io = ns9xxx_map_io,
|
||||
.init_irq = ns9xxx_init_irq,
|
||||
.init_machine = mach_cc9p9360js_init_machine,
|
||||
.timer = &ns9xxx_timer,
|
||||
.boot_params = 0x100,
|
||||
MACHINE_END
|
@ -39,6 +39,10 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/clockchips.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/hardware.h>
|
||||
@ -48,13 +52,7 @@
|
||||
#include <asm/mach/irq.h>
|
||||
#include <asm/mach/time.h>
|
||||
|
||||
struct sys_timer omap_timer;
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------------
|
||||
* MPU timer
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
#define OMAP_MPU_TIMER_BASE OMAP_MPU_TIMER1_BASE
|
||||
#define OMAP_MPU_TIMER_OFFSET 0x100
|
||||
|
||||
@ -88,21 +86,6 @@ static inline unsigned long long cycles_2_ns(unsigned long long cyc)
|
||||
return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
|
||||
}
|
||||
|
||||
/*
|
||||
* MPU_TICKS_PER_SEC must be an even number, otherwise machinecycles_to_usecs
|
||||
* will break. On P2, the timer count rate is 6.5 MHz after programming PTV
|
||||
* with 0. This divides the 13MHz input by 2, and is undocumented.
|
||||
*/
|
||||
#if defined(CONFIG_MACH_OMAP_PERSEUS2) || defined(CONFIG_MACH_OMAP_FSAMPLE)
|
||||
/* REVISIT: This ifdef construct should be replaced by a query to clock
|
||||
* framework to see if timer base frequency is 12.0, 13.0 or 19.2 MHz.
|
||||
*/
|
||||
#define MPU_TICKS_PER_SEC (13000000 / 2)
|
||||
#else
|
||||
#define MPU_TICKS_PER_SEC (12000000 / 2)
|
||||
#endif
|
||||
|
||||
#define MPU_TIMER_TICK_PERIOD ((MPU_TICKS_PER_SEC / HZ) - 1)
|
||||
|
||||
typedef struct {
|
||||
u32 cntl; /* CNTL_TIMER, R/W */
|
||||
@ -120,98 +103,164 @@ static inline unsigned long omap_mpu_timer_read(int nr)
|
||||
return timer->read_tim;
|
||||
}
|
||||
|
||||
static inline void omap_mpu_timer_start(int nr, unsigned long load_val)
|
||||
static inline void omap_mpu_set_autoreset(int nr)
|
||||
{
|
||||
volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr);
|
||||
|
||||
timer->cntl = timer->cntl | MPU_TIMER_AR;
|
||||
}
|
||||
|
||||
static inline void omap_mpu_remove_autoreset(int nr)
|
||||
{
|
||||
volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr);
|
||||
|
||||
timer->cntl = timer->cntl & ~MPU_TIMER_AR;
|
||||
}
|
||||
|
||||
static inline void omap_mpu_timer_start(int nr, unsigned long load_val,
|
||||
int autoreset)
|
||||
{
|
||||
volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr);
|
||||
unsigned int timerflags = (MPU_TIMER_CLOCK_ENABLE | MPU_TIMER_ST);
|
||||
|
||||
if (autoreset) timerflags |= MPU_TIMER_AR;
|
||||
|
||||
timer->cntl = MPU_TIMER_CLOCK_ENABLE;
|
||||
udelay(1);
|
||||
timer->load_tim = load_val;
|
||||
udelay(1);
|
||||
timer->cntl = (MPU_TIMER_CLOCK_ENABLE | MPU_TIMER_AR | MPU_TIMER_ST);
|
||||
}
|
||||
|
||||
unsigned long omap_mpu_timer_ticks_to_usecs(unsigned long nr_ticks)
|
||||
{
|
||||
unsigned long long nsec;
|
||||
|
||||
nsec = cycles_2_ns((unsigned long long)nr_ticks);
|
||||
return (unsigned long)nsec / 1000;
|
||||
timer->cntl = timerflags;
|
||||
}
|
||||
|
||||
/*
|
||||
* Last processed system timer interrupt
|
||||
* ---------------------------------------------------------------------------
|
||||
* MPU timer 1 ... count down to zero, interrupt, reload
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
static unsigned long omap_mpu_timer_last = 0;
|
||||
|
||||
/*
|
||||
* Returns elapsed usecs since last system timer interrupt
|
||||
*/
|
||||
static unsigned long omap_mpu_timer_gettimeoffset(void)
|
||||
static int omap_mpu_set_next_event(unsigned long cycles,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
unsigned long now = 0 - omap_mpu_timer_read(0);
|
||||
unsigned long elapsed = now - omap_mpu_timer_last;
|
||||
|
||||
return omap_mpu_timer_ticks_to_usecs(elapsed);
|
||||
omap_mpu_timer_start(0, cycles, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Elapsed time between interrupts is calculated using timer0.
|
||||
* Latency during the interrupt is calculated using timer1.
|
||||
* Both timer0 and timer1 are counting at 6MHz (P2 6.5MHz).
|
||||
*/
|
||||
static irqreturn_t omap_mpu_timer_interrupt(int irq, void *dev_id)
|
||||
static void omap_mpu_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
unsigned long now, latency;
|
||||
|
||||
write_seqlock(&xtime_lock);
|
||||
now = 0 - omap_mpu_timer_read(0);
|
||||
latency = MPU_TICKS_PER_SEC / HZ - omap_mpu_timer_read(1);
|
||||
omap_mpu_timer_last = now - latency;
|
||||
timer_tick();
|
||||
write_sequnlock(&xtime_lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
omap_mpu_set_autoreset(0);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
omap_mpu_remove_autoreset(0);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct irqaction omap_mpu_timer_irq = {
|
||||
.name = "mpu timer",
|
||||
.flags = IRQF_DISABLED | IRQF_TIMER,
|
||||
.handler = omap_mpu_timer_interrupt,
|
||||
static struct clock_event_device clockevent_mpu_timer1 = {
|
||||
.name = "mpu_timer1",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC, CLOCK_EVT_FEAT_ONESHOT,
|
||||
.shift = 32,
|
||||
.set_next_event = omap_mpu_set_next_event,
|
||||
.set_mode = omap_mpu_set_mode,
|
||||
};
|
||||
|
||||
static unsigned long omap_mpu_timer1_overflows;
|
||||
static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
omap_mpu_timer1_overflows++;
|
||||
struct clock_event_device *evt = &clockevent_mpu_timer1;
|
||||
|
||||
evt->event_handler(evt);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct irqaction omap_mpu_timer1_irq = {
|
||||
.name = "mpu timer1 overflow",
|
||||
.flags = IRQF_DISABLED,
|
||||
.name = "mpu_timer1",
|
||||
.flags = IRQF_DISABLED | IRQF_TIMER,
|
||||
.handler = omap_mpu_timer1_interrupt,
|
||||
};
|
||||
|
||||
static __init void omap_init_mpu_timer(void)
|
||||
static __init void omap_init_mpu_timer(unsigned long rate)
|
||||
{
|
||||
set_cyc2ns_scale(MPU_TICKS_PER_SEC / 1000);
|
||||
omap_timer.offset = omap_mpu_timer_gettimeoffset;
|
||||
set_cyc2ns_scale(rate / 1000);
|
||||
|
||||
setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
|
||||
setup_irq(INT_TIMER2, &omap_mpu_timer_irq);
|
||||
omap_mpu_timer_start(0, 0xffffffff);
|
||||
omap_mpu_timer_start(1, MPU_TIMER_TICK_PERIOD);
|
||||
omap_mpu_timer_start(0, (rate / HZ) - 1, 1);
|
||||
|
||||
clockevent_mpu_timer1.mult = div_sc(rate, NSEC_PER_SEC,
|
||||
clockevent_mpu_timer1.shift);
|
||||
clockevent_mpu_timer1.max_delta_ns =
|
||||
clockevent_delta2ns(-1, &clockevent_mpu_timer1);
|
||||
clockevent_mpu_timer1.min_delta_ns =
|
||||
clockevent_delta2ns(1, &clockevent_mpu_timer1);
|
||||
|
||||
clockevent_mpu_timer1.cpumask = cpumask_of_cpu(0);
|
||||
clockevents_register_device(&clockevent_mpu_timer1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------------
|
||||
* MPU timer 2 ... free running 32-bit clock source and scheduler clock
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static unsigned long omap_mpu_timer2_overflows;
|
||||
|
||||
static irqreturn_t omap_mpu_timer2_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
omap_mpu_timer2_overflows++;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct irqaction omap_mpu_timer2_irq = {
|
||||
.name = "mpu_timer2",
|
||||
.flags = IRQF_DISABLED,
|
||||
.handler = omap_mpu_timer2_interrupt,
|
||||
};
|
||||
|
||||
static cycle_t mpu_read(void)
|
||||
{
|
||||
return ~omap_mpu_timer_read(1);
|
||||
}
|
||||
|
||||
static struct clocksource clocksource_mpu = {
|
||||
.name = "mpu_timer2",
|
||||
.rating = 300,
|
||||
.read = mpu_read,
|
||||
.mask = CLOCKSOURCE_MASK(32),
|
||||
.shift = 24,
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
};
|
||||
|
||||
static void __init omap_init_clocksource(unsigned long rate)
|
||||
{
|
||||
static char err[] __initdata = KERN_ERR
|
||||
"%s: can't register clocksource!\n";
|
||||
|
||||
clocksource_mpu.mult
|
||||
= clocksource_khz2mult(rate/1000, clocksource_mpu.shift);
|
||||
|
||||
setup_irq(INT_TIMER2, &omap_mpu_timer2_irq);
|
||||
omap_mpu_timer_start(1, ~0, 1);
|
||||
|
||||
if (clocksource_register(&clocksource_mpu))
|
||||
printk(err, clocksource_mpu.name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Scheduler clock - returns current time in nanosec units.
|
||||
*/
|
||||
unsigned long long sched_clock(void)
|
||||
{
|
||||
unsigned long ticks = 0 - omap_mpu_timer_read(0);
|
||||
unsigned long ticks = 0 - omap_mpu_timer_read(1);
|
||||
unsigned long long ticks64;
|
||||
|
||||
ticks64 = omap_mpu_timer1_overflows;
|
||||
ticks64 = omap_mpu_timer2_overflows;
|
||||
ticks64 <<= 32;
|
||||
ticks64 |= ticks;
|
||||
|
||||
@ -225,10 +274,21 @@ unsigned long long sched_clock(void)
|
||||
*/
|
||||
static void __init omap_timer_init(void)
|
||||
{
|
||||
omap_init_mpu_timer();
|
||||
struct clk *ck_ref = clk_get(NULL, "ck_ref");
|
||||
unsigned long rate;
|
||||
|
||||
BUG_ON(IS_ERR(ck_ref));
|
||||
|
||||
rate = clk_get_rate(ck_ref);
|
||||
clk_put(ck_ref);
|
||||
|
||||
/* PTV = 0 */
|
||||
rate /= 2;
|
||||
|
||||
omap_init_mpu_timer(rate);
|
||||
omap_init_clocksource(rate);
|
||||
}
|
||||
|
||||
struct sys_timer omap_timer = {
|
||||
.init = omap_timer_init,
|
||||
.offset = NULL, /* Initialized later */
|
||||
};
|
||||
|
@ -164,9 +164,9 @@ void pxa_set_cken(int clock, int enable)
|
||||
local_irq_save(flags);
|
||||
|
||||
if (enable)
|
||||
CKEN |= clock;
|
||||
CKEN |= (1 << clock);
|
||||
else
|
||||
CKEN &= ~clock;
|
||||
CKEN &= ~(1 << clock);
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
@ -38,11 +38,33 @@ static void pxa_unmask_low_irq(unsigned int irq)
|
||||
ICMR |= (1 << (irq + PXA_IRQ_SKIP));
|
||||
}
|
||||
|
||||
static int pxa_set_wake(unsigned int irq, unsigned int on)
|
||||
{
|
||||
u32 mask;
|
||||
|
||||
switch (irq) {
|
||||
case IRQ_RTCAlrm:
|
||||
mask = PWER_RTC;
|
||||
break;
|
||||
#ifdef CONFIG_PXA27x
|
||||
/* REVISIT can handle USBH1, USBH2, USB, MSL, USIM, ... */
|
||||
#endif
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if (on)
|
||||
PWER |= mask;
|
||||
else
|
||||
PWER &= ~mask;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip pxa_internal_chip_low = {
|
||||
.name = "SC",
|
||||
.ack = pxa_mask_low_irq,
|
||||
.mask = pxa_mask_low_irq,
|
||||
.unmask = pxa_unmask_low_irq,
|
||||
.set_wake = pxa_set_wake,
|
||||
};
|
||||
|
||||
#if PXA_INTERNAL_IRQS > 32
|
||||
@ -70,6 +92,26 @@ static struct irq_chip pxa_internal_chip_high = {
|
||||
|
||||
#endif
|
||||
|
||||
/* Note that if an input/irq line ever gets changed to an output during
|
||||
* suspend, the relevant PWER, PRER, and PFER bits should be cleared.
|
||||
*/
|
||||
#ifdef CONFIG_PXA27x
|
||||
|
||||
/* PXA27x: Various gpios can issue wakeup events. This logic only
|
||||
* handles the simple cases, not the WEMUX2 and WEMUX3 options
|
||||
*/
|
||||
#define PXA27x_GPIO_NOWAKE_MASK \
|
||||
((1 << 8) | (1 << 7) | (1 << 6) | (1 << 5) | (1 << 2))
|
||||
#define WAKEMASK(gpio) \
|
||||
(((gpio) <= 15) \
|
||||
? ((1 << (gpio)) & ~PXA27x_GPIO_NOWAKE_MASK) \
|
||||
: ((gpio == 35) ? (1 << 24) : 0))
|
||||
#else
|
||||
|
||||
/* pxa 210, 250, 255, 26x: gpios 0..15 can issue wakeups */
|
||||
#define WAKEMASK(gpio) (((gpio) <= 15) ? (1 << (gpio)) : 0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* PXA GPIO edge detection for IRQs:
|
||||
* IRQs are generated on Falling-Edge, Rising-Edge, or both.
|
||||
@ -83,9 +125,11 @@ static long GPIO_IRQ_mask[4];
|
||||
static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
|
||||
{
|
||||
int gpio, idx;
|
||||
u32 mask;
|
||||
|
||||
gpio = IRQ_TO_GPIO(irq);
|
||||
idx = gpio >> 5;
|
||||
mask = WAKEMASK(gpio);
|
||||
|
||||
if (type == IRQT_PROBE) {
|
||||
/* Don't mess with enabled GPIOs using preconfigured edges or
|
||||
@ -105,14 +149,20 @@ static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
|
||||
if (type & __IRQT_RISEDGE) {
|
||||
/* printk("rising "); */
|
||||
__set_bit (gpio, GPIO_IRQ_rising_edge);
|
||||
} else
|
||||
PRER |= mask;
|
||||
} else {
|
||||
__clear_bit (gpio, GPIO_IRQ_rising_edge);
|
||||
PRER &= ~mask;
|
||||
}
|
||||
|
||||
if (type & __IRQT_FALEDGE) {
|
||||
/* printk("falling "); */
|
||||
__set_bit (gpio, GPIO_IRQ_falling_edge);
|
||||
} else
|
||||
PFER |= mask;
|
||||
} else {
|
||||
__clear_bit (gpio, GPIO_IRQ_falling_edge);
|
||||
PFER &= ~mask;
|
||||
}
|
||||
|
||||
/* printk("edges\n"); */
|
||||
|
||||
@ -130,12 +180,29 @@ static void pxa_ack_low_gpio(unsigned int irq)
|
||||
GEDR0 = (1 << (irq - IRQ_GPIO0));
|
||||
}
|
||||
|
||||
static int pxa_set_gpio_wake(unsigned int irq, unsigned int on)
|
||||
{
|
||||
int gpio = IRQ_TO_GPIO(irq);
|
||||
u32 mask = WAKEMASK(gpio);
|
||||
|
||||
if (!mask)
|
||||
return -EINVAL;
|
||||
|
||||
if (on)
|
||||
PWER |= mask;
|
||||
else
|
||||
PWER &= ~mask;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct irq_chip pxa_low_gpio_chip = {
|
||||
.name = "GPIO-l",
|
||||
.ack = pxa_ack_low_gpio,
|
||||
.mask = pxa_mask_low_irq,
|
||||
.unmask = pxa_unmask_low_irq,
|
||||
.set_type = pxa_gpio_irq_type,
|
||||
.set_wake = pxa_set_gpio_wake,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -244,6 +311,7 @@ static struct irq_chip pxa_muxed_gpio_chip = {
|
||||
.mask = pxa_mask_muxed_gpio,
|
||||
.unmask = pxa_unmask_muxed_gpio,
|
||||
.set_type = pxa_gpio_irq_type,
|
||||
.set_wake = pxa_set_gpio_wake,
|
||||
};
|
||||
|
||||
|
||||
|
@ -234,7 +234,7 @@ static void lpd270_backlight_power(int on)
|
||||
{
|
||||
if (on) {
|
||||
pxa_gpio_mode(GPIO16_PWM0_MD);
|
||||
pxa_set_cken(CKEN0_PWM0, 1);
|
||||
pxa_set_cken(CKEN_PWM0, 1);
|
||||
PWM_CTRL0 = 0;
|
||||
PWM_PWDUTY0 = 0x3ff;
|
||||
PWM_PERVAL0 = 0x3ff;
|
||||
@ -242,7 +242,7 @@ static void lpd270_backlight_power(int on)
|
||||
PWM_CTRL0 = 0;
|
||||
PWM_PWDUTY0 = 0x0;
|
||||
PWM_PERVAL0 = 0x3FF;
|
||||
pxa_set_cken(CKEN0_PWM0, 0);
|
||||
pxa_set_cken(CKEN_PWM0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,7 +220,7 @@ static struct resource pxa_ssp_resources[] = {
|
||||
|
||||
static struct pxa2xx_spi_master pxa_ssp_master_info = {
|
||||
.ssp_type = PXA25x_SSP,
|
||||
.clock_enable = CKEN3_SSP,
|
||||
.clock_enable = CKEN_SSP,
|
||||
.num_chipselect = 0,
|
||||
};
|
||||
|
||||
|
@ -266,7 +266,7 @@ static void mainstone_backlight_power(int on)
|
||||
{
|
||||
if (on) {
|
||||
pxa_gpio_mode(GPIO16_PWM0_MD);
|
||||
pxa_set_cken(CKEN0_PWM0, 1);
|
||||
pxa_set_cken(CKEN_PWM0, 1);
|
||||
PWM_CTRL0 = 0;
|
||||
PWM_PWDUTY0 = 0x3ff;
|
||||
PWM_PERVAL0 = 0x3ff;
|
||||
@ -274,7 +274,7 @@ static void mainstone_backlight_power(int on)
|
||||
PWM_CTRL0 = 0;
|
||||
PWM_PWDUTY0 = 0x0;
|
||||
PWM_PERVAL0 = 0x3FF;
|
||||
pxa_set_cken(CKEN0_PWM0, 0);
|
||||
pxa_set_cken(CKEN_PWM0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,9 +140,9 @@ void pxa_cpu_pm_enter(suspend_state_t state)
|
||||
extern void pxa_cpu_resume(void);
|
||||
|
||||
if (state == PM_SUSPEND_STANDBY)
|
||||
CKEN = CKEN22_MEMC | CKEN9_OSTIMER | CKEN16_LCD |CKEN0_PWM0;
|
||||
CKEN = CKEN_MEMC | CKEN_OSTIMER | CKEN_LCD | CKEN_PWM0;
|
||||
else
|
||||
CKEN = CKEN22_MEMC | CKEN9_OSTIMER;
|
||||
CKEN = CKEN_MEMC | CKEN_OSTIMER;
|
||||
|
||||
/* ensure voltage-change sequencer not initiated, which hangs */
|
||||
PCFR &= ~PCFR_FVC;
|
||||
|
@ -52,13 +52,13 @@ struct ssp_info_ {
|
||||
*/
|
||||
static const struct ssp_info_ ssp_info[PXA_SSP_PORTS] = {
|
||||
#if defined (CONFIG_PXA27x)
|
||||
{IRQ_SSP, CKEN23_SSP1},
|
||||
{IRQ_SSP2, CKEN3_SSP2},
|
||||
{IRQ_SSP3, CKEN4_SSP3},
|
||||
{IRQ_SSP, CKEN_SSP1},
|
||||
{IRQ_SSP2, CKEN_SSP2},
|
||||
{IRQ_SSP3, CKEN_SSP3},
|
||||
#else
|
||||
{IRQ_SSP, CKEN3_SSP},
|
||||
{IRQ_NSSP, CKEN9_NSSP},
|
||||
{IRQ_ASSP, CKEN10_ASSP},
|
||||
{IRQ_SSP, CKEN_SSP},
|
||||
{IRQ_NSSP, CKEN_NSSP},
|
||||
{IRQ_ASSP, CKEN_ASSP},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/pata_platform.h>
|
||||
|
||||
#include <asm/elf.h>
|
||||
#include <asm/io.h>
|
||||
@ -159,11 +160,45 @@ static struct platform_device serial_device = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct pata_platform_info pata_platform_data = {
|
||||
.ioport_shift = 2,
|
||||
};
|
||||
|
||||
static struct resource pata_resources[] = {
|
||||
[0] = {
|
||||
.start = 0x030107c0,
|
||||
.end = 0x030107df,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = 0x03010fd8,
|
||||
.end = 0x03010fdb,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_HARDDISK,
|
||||
.end = IRQ_HARDDISK,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device pata_device = {
|
||||
.name = "pata_platform",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(pata_resources),
|
||||
.resource = pata_resources,
|
||||
.dev = {
|
||||
.platform_data = &pata_platform_data,
|
||||
.coherent_dma_mask = ~0, /* grumble */
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device *devs[] __initdata = {
|
||||
&iomd_device,
|
||||
&kbd_device,
|
||||
&serial_device,
|
||||
&acornfb_device,
|
||||
&pata_device,
|
||||
};
|
||||
|
||||
static int __init rpc_init(void)
|
||||
|
@ -160,17 +160,11 @@ static struct platform_device *amlm5900_devices[] __initdata = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct s3c24xx_board amlm5900_board __initdata = {
|
||||
.devices = amlm5900_devices,
|
||||
.devices_count = ARRAY_SIZE(amlm5900_devices)
|
||||
};
|
||||
|
||||
void __init amlm5900_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(amlm5900_iodesc, ARRAY_SIZE(amlm5900_iodesc));
|
||||
s3c24xx_init_clocks(0);
|
||||
s3c24xx_init_uarts(amlm5900_uartcfgs, ARRAY_SIZE(amlm5900_uartcfgs));
|
||||
s3c24xx_set_board(&amlm5900_board);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FB_S3C2410
|
||||
@ -247,6 +241,7 @@ static void __init amlm5900_init(void)
|
||||
#ifdef CONFIG_FB_S3C2410
|
||||
s3c24xx_fb_set_platdata(&amlm5900_lcd_info);
|
||||
#endif
|
||||
platform_add_devices(amlm5900_devices, ARRAY_SIZE(amlm5900_devices));
|
||||
}
|
||||
|
||||
MACHINE_START(AML_M5900, "AML_M5900")
|
||||
|
@ -464,13 +464,6 @@ static struct clk *bast_clocks[] = {
|
||||
&s3c24xx_uclk,
|
||||
};
|
||||
|
||||
static struct s3c24xx_board bast_board __initdata = {
|
||||
.devices = bast_devices,
|
||||
.devices_count = ARRAY_SIZE(bast_devices),
|
||||
.clocks = bast_clocks,
|
||||
.clocks_count = ARRAY_SIZE(bast_clocks),
|
||||
};
|
||||
|
||||
static void __init bast_map_io(void)
|
||||
{
|
||||
/* initialise the clocks */
|
||||
@ -486,19 +479,22 @@ static void __init bast_map_io(void)
|
||||
|
||||
s3c24xx_uclk.parent = &s3c24xx_clkout1;
|
||||
|
||||
s3c24xx_register_clocks(bast_clocks, ARRAY_SIZE(bast_clocks));
|
||||
|
||||
s3c_device_nand.dev.platform_data = &bast_nand_info;
|
||||
s3c_device_i2c.dev.platform_data = &bast_i2c_info;
|
||||
|
||||
s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
|
||||
s3c24xx_init_clocks(0);
|
||||
s3c24xx_init_uarts(bast_uartcfgs, ARRAY_SIZE(bast_uartcfgs));
|
||||
s3c24xx_set_board(&bast_board);
|
||||
|
||||
usb_simtec_init();
|
||||
}
|
||||
|
||||
static void __init bast_init(void)
|
||||
{
|
||||
s3c24xx_fb_set_platdata(&bast_lcd_info);
|
||||
platform_add_devices(bast_devices, ARRAY_SIZE(bast_devices));
|
||||
}
|
||||
|
||||
MACHINE_START(BAST, "Simtec-BAST")
|
||||
|
@ -129,7 +129,6 @@ static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = {
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set lcd on or off
|
||||
**/
|
||||
@ -188,17 +187,11 @@ static struct platform_device *h1940_devices[] __initdata = {
|
||||
&s3c_device_leds,
|
||||
};
|
||||
|
||||
static struct s3c24xx_board h1940_board __initdata = {
|
||||
.devices = h1940_devices,
|
||||
.devices_count = ARRAY_SIZE(h1940_devices)
|
||||
};
|
||||
|
||||
static void __init h1940_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc));
|
||||
s3c24xx_init_clocks(0);
|
||||
s3c24xx_init_uarts(h1940_uartcfgs, ARRAY_SIZE(h1940_uartcfgs));
|
||||
s3c24xx_set_board(&h1940_board);
|
||||
|
||||
/* setup PM */
|
||||
|
||||
@ -232,6 +225,8 @@ static void __init h1940_init(void)
|
||||
| (0x02 << S3C2410_PLLCON_PDIVSHIFT)
|
||||
| (0x03 << S3C2410_PLLCON_SDIVSHIFT);
|
||||
writel(tmp, S3C2410_UPLLCON);
|
||||
|
||||
platform_add_devices(h1940_devices, ARRAY_SIZE(h1940_devices));
|
||||
}
|
||||
|
||||
MACHINE_START(H1940, "IPAQ-H1940")
|
||||
|
@ -90,17 +90,11 @@ static struct s3c2410_platform_i2c n30_i2ccfg = {
|
||||
.max_freq = 10*1000,
|
||||
};
|
||||
|
||||
static struct s3c24xx_board n30_board __initdata = {
|
||||
.devices = n30_devices,
|
||||
.devices_count = ARRAY_SIZE(n30_devices)
|
||||
};
|
||||
|
||||
static void __init n30_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(n30_iodesc, ARRAY_SIZE(n30_iodesc));
|
||||
s3c24xx_init_clocks(0);
|
||||
s3c24xx_init_uarts(n30_uartcfgs, ARRAY_SIZE(n30_uartcfgs));
|
||||
s3c24xx_set_board(&n30_board);
|
||||
}
|
||||
|
||||
static void __init n30_init_irq(void)
|
||||
@ -120,6 +114,8 @@ static void __init n30_init(void)
|
||||
s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
|
||||
S3C2410_MISCCR_USBSUSPND0 |
|
||||
S3C2410_MISCCR_USBSUSPND1, 0x0);
|
||||
|
||||
platform_add_devices(n30_devices, ARRAY_SIZE(n30_devices));
|
||||
}
|
||||
|
||||
MACHINE_START(N30, "Acer-N30")
|
||||
|
@ -100,20 +100,17 @@ static struct platform_device *otom11_devices[] __initdata = {
|
||||
&otom_device_nor,
|
||||
};
|
||||
|
||||
static struct s3c24xx_board otom11_board __initdata = {
|
||||
.devices = otom11_devices,
|
||||
.devices_count = ARRAY_SIZE(otom11_devices)
|
||||
};
|
||||
|
||||
|
||||
static void __init otom11_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(otom11_iodesc, ARRAY_SIZE(otom11_iodesc));
|
||||
s3c24xx_init_clocks(0);
|
||||
s3c24xx_init_uarts(otom11_uartcfgs, ARRAY_SIZE(otom11_uartcfgs));
|
||||
s3c24xx_set_board(&otom11_board);
|
||||
}
|
||||
|
||||
static void __init otom11_init(void)
|
||||
{
|
||||
platform_add_devices(otom11_devices, ARRAY_SIZE(otom11_devices));
|
||||
}
|
||||
|
||||
MACHINE_START(OTOM, "Nex Vision - Otom 1.1")
|
||||
/* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
|
||||
@ -121,6 +118,7 @@ MACHINE_START(OTOM, "Nex Vision - Otom 1.1")
|
||||
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
|
||||
.boot_params = S3C2410_SDRAM_PA + 0x100,
|
||||
.map_io = otom11_map_io,
|
||||
.init_machine = otom11_init,
|
||||
.init_irq = s3c24xx_init_irq,
|
||||
.timer = &s3c24xx_timer,
|
||||
MACHINE_END
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/mmc/protocol.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/spi_bitbang.h>
|
||||
|
||||
@ -331,11 +330,6 @@ static struct platform_device *qt2410_devices[] __initdata = {
|
||||
&qt2410_led,
|
||||
};
|
||||
|
||||
static struct s3c24xx_board qt2410_board __initdata = {
|
||||
.devices = qt2410_devices,
|
||||
.devices_count = ARRAY_SIZE(qt2410_devices)
|
||||
};
|
||||
|
||||
static struct mtd_partition qt2410_nand_part[] = {
|
||||
[0] = {
|
||||
.name = "U-Boot",
|
||||
@ -405,7 +399,6 @@ static void __init qt2410_map_io(void)
|
||||
s3c24xx_init_io(qt2410_iodesc, ARRAY_SIZE(qt2410_iodesc));
|
||||
s3c24xx_init_clocks(12*1000*1000);
|
||||
s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
|
||||
s3c24xx_set_board(&qt2410_board);
|
||||
}
|
||||
|
||||
static void __init qt2410_machine_init(void)
|
||||
@ -432,6 +425,7 @@ static void __init qt2410_machine_init(void)
|
||||
|
||||
s3c2410_gpio_cfgpin(S3C2410_GPB5, S3C2410_GPIO_OUTPUT);
|
||||
|
||||
platform_add_devices(qt2410_devices, ARRAY_SIZE(qt2410_devices));
|
||||
s3c2410_pm_init();
|
||||
}
|
||||
|
||||
|
@ -94,17 +94,17 @@ static struct platform_device *smdk2410_devices[] __initdata = {
|
||||
&s3c_device_iis,
|
||||
};
|
||||
|
||||
static struct s3c24xx_board smdk2410_board __initdata = {
|
||||
.devices = smdk2410_devices,
|
||||
.devices_count = ARRAY_SIZE(smdk2410_devices)
|
||||
};
|
||||
|
||||
static void __init smdk2410_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc));
|
||||
s3c24xx_init_clocks(0);
|
||||
s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
|
||||
s3c24xx_set_board(&smdk2410_board);
|
||||
}
|
||||
|
||||
static void __init smdk2410_init(void)
|
||||
{
|
||||
platform_add_devices(smdk2410_devices, ARRAY_SIZE(smdk2410_devices));
|
||||
smdk_machine_init();
|
||||
}
|
||||
|
||||
MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
|
||||
@ -115,7 +115,7 @@ MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switc
|
||||
.boot_params = S3C2410_SDRAM_PA + 0x100,
|
||||
.map_io = smdk2410_map_io,
|
||||
.init_irq = s3c24xx_init_irq,
|
||||
.init_machine = smdk_machine_init,
|
||||
.init_machine = smdk2410_init,
|
||||
.timer = &s3c24xx_timer,
|
||||
MACHINE_END
|
||||
|
||||
|
@ -384,13 +384,6 @@ static struct clk *vr1000_clocks[] = {
|
||||
&s3c24xx_uclk,
|
||||
};
|
||||
|
||||
static struct s3c24xx_board vr1000_board __initdata = {
|
||||
.devices = vr1000_devices,
|
||||
.devices_count = ARRAY_SIZE(vr1000_devices),
|
||||
.clocks = vr1000_clocks,
|
||||
.clocks_count = ARRAY_SIZE(vr1000_clocks),
|
||||
};
|
||||
|
||||
static void vr1000_power_off(void)
|
||||
{
|
||||
s3c2410_gpio_cfgpin(S3C2410_GPB9, S3C2410_GPB9_OUTP);
|
||||
@ -412,15 +405,19 @@ static void __init vr1000_map_io(void)
|
||||
|
||||
s3c24xx_uclk.parent = &s3c24xx_clkout1;
|
||||
|
||||
s3c24xx_register_clocks(vr1000_clocks, ARRAY_SIZE(vr1000_clocks));
|
||||
|
||||
pm_power_off = vr1000_power_off;
|
||||
|
||||
s3c24xx_init_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc));
|
||||
s3c24xx_init_clocks(0);
|
||||
s3c24xx_init_uarts(vr1000_uartcfgs, ARRAY_SIZE(vr1000_uartcfgs));
|
||||
s3c24xx_set_board(&vr1000_board);
|
||||
usb_simtec_init();
|
||||
}
|
||||
|
||||
static void __init vr1000_init(void)
|
||||
{
|
||||
platform_add_devices(vr1000_devices, ARRAY_SIZE(vr1000_devices));
|
||||
}
|
||||
|
||||
MACHINE_START(VR1000, "Thorcom-VR1000")
|
||||
/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
|
||||
@ -428,6 +425,7 @@ MACHINE_START(VR1000, "Thorcom-VR1000")
|
||||
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
|
||||
.boot_params = S3C2410_SDRAM_PA + 0x100,
|
||||
.map_io = vr1000_map_io,
|
||||
.init_machine = vr1000_init,
|
||||
.init_irq = s3c24xx_init_irq,
|
||||
.timer = &s3c24xx_timer,
|
||||
MACHINE_END
|
||||
|
@ -47,6 +47,15 @@ config MACH_S3C2413
|
||||
machine_is_s3c2413() will work when MACH_SMDK2413 is
|
||||
selected
|
||||
|
||||
config MACH_SMDK2412
|
||||
bool "SMDK2412"
|
||||
select MACH_SMDK2413
|
||||
help
|
||||
Say Y here if you are using an SMDK2412
|
||||
|
||||
Note, this shares support with SMDK2413, so will automatically
|
||||
select MACH_SMDK2413.
|
||||
|
||||
config MACH_VSTMS
|
||||
bool "VMSTMS"
|
||||
select CPU_S3C2412
|
||||
|
@ -110,11 +110,6 @@ static struct platform_device *smdk2413_devices[] __initdata = {
|
||||
&s3c_device_usbgadget,
|
||||
};
|
||||
|
||||
static struct s3c24xx_board smdk2413_board __initdata = {
|
||||
.devices = smdk2413_devices,
|
||||
.devices_count = ARRAY_SIZE(smdk2413_devices)
|
||||
};
|
||||
|
||||
static void __init smdk2413_fixup(struct machine_desc *desc,
|
||||
struct tag *tags, char **cmdline,
|
||||
struct meminfo *mi)
|
||||
@ -132,7 +127,6 @@ static void __init smdk2413_map_io(void)
|
||||
s3c24xx_init_io(smdk2413_iodesc, ARRAY_SIZE(smdk2413_iodesc));
|
||||
s3c24xx_init_clocks(12000000);
|
||||
s3c24xx_init_uarts(smdk2413_uartcfgs, ARRAY_SIZE(smdk2413_uartcfgs));
|
||||
s3c24xx_set_board(&smdk2413_board);
|
||||
}
|
||||
|
||||
static void __init smdk2413_machine_init(void)
|
||||
@ -149,6 +143,7 @@ static void __init smdk2413_machine_init(void)
|
||||
|
||||
s3c24xx_udc_set_platdata(&smdk2413_udc_cfg);
|
||||
|
||||
platform_add_devices(smdk2413_devices, ARRAY_SIZE(smdk2413_devices));
|
||||
smdk_machine_init();
|
||||
}
|
||||
|
||||
|
@ -129,11 +129,6 @@ static struct platform_device *vstms_devices[] __initdata = {
|
||||
&s3c_device_nand,
|
||||
};
|
||||
|
||||
static struct s3c24xx_board vstms_board __initdata = {
|
||||
.devices = vstms_devices,
|
||||
.devices_count = ARRAY_SIZE(vstms_devices)
|
||||
};
|
||||
|
||||
static void __init vstms_fixup(struct machine_desc *desc,
|
||||
struct tag *tags, char **cmdline,
|
||||
struct meminfo *mi)
|
||||
@ -153,7 +148,11 @@ static void __init vstms_map_io(void)
|
||||
s3c24xx_init_io(vstms_iodesc, ARRAY_SIZE(vstms_iodesc));
|
||||
s3c24xx_init_clocks(12000000);
|
||||
s3c24xx_init_uarts(vstms_uartcfgs, ARRAY_SIZE(vstms_uartcfgs));
|
||||
s3c24xx_set_board(&vstms_board);
|
||||
}
|
||||
|
||||
static void __init vstms_init(void)
|
||||
{
|
||||
platform_add_devices(vstms_devices, ARRAY_SIZE(vstms_devices));
|
||||
}
|
||||
|
||||
MACHINE_START(VSTMS, "VSTMS")
|
||||
@ -163,6 +162,7 @@ MACHINE_START(VSTMS, "VSTMS")
|
||||
|
||||
.fixup = vstms_fixup,
|
||||
.init_irq = s3c24xx_init_irq,
|
||||
.init_machine = vstms_init,
|
||||
.map_io = vstms_map_io,
|
||||
.timer = &s3c24xx_timer,
|
||||
MACHINE_END
|
||||
|
@ -281,13 +281,6 @@ static struct clk *anubis_clocks[] = {
|
||||
&s3c24xx_uclk,
|
||||
};
|
||||
|
||||
static struct s3c24xx_board anubis_board __initdata = {
|
||||
.devices = anubis_devices,
|
||||
.devices_count = ARRAY_SIZE(anubis_devices),
|
||||
.clocks = anubis_clocks,
|
||||
.clocks_count = ARRAY_SIZE(anubis_clocks),
|
||||
};
|
||||
|
||||
static void __init anubis_map_io(void)
|
||||
{
|
||||
/* initialise the clocks */
|
||||
@ -303,23 +296,31 @@ static void __init anubis_map_io(void)
|
||||
|
||||
s3c24xx_uclk.parent = &s3c24xx_clkout1;
|
||||
|
||||
s3c24xx_register_clocks(anubis_clocks, ARRAY_SIZE(anubis_clocks));
|
||||
|
||||
s3c_device_nand.dev.platform_data = &anubis_nand_info;
|
||||
|
||||
s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc));
|
||||
s3c24xx_init_clocks(0);
|
||||
s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
|
||||
s3c24xx_set_board(&anubis_board);
|
||||
|
||||
/* ensure that the GPIO is setup */
|
||||
s3c2410_gpio_setpin(S3C2410_GPA0, 1);
|
||||
}
|
||||
|
||||
static void __init anubis_init(void)
|
||||
{
|
||||
platform_add_devices(anubis_devices, ARRAY_SIZE(anubis_devices));
|
||||
}
|
||||
|
||||
|
||||
MACHINE_START(ANUBIS, "Simtec-Anubis")
|
||||
/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
|
||||
.phys_io = S3C2410_PA_UART,
|
||||
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
|
||||
.boot_params = S3C2410_SDRAM_PA + 0x100,
|
||||
.map_io = anubis_map_io,
|
||||
.init_machine = anubis_init,
|
||||
.init_irq = s3c24xx_init_irq,
|
||||
.timer = &s3c24xx_timer,
|
||||
MACHINE_END
|
||||
|
@ -116,12 +116,6 @@ static struct platform_device *nexcoder_devices[] __initdata = {
|
||||
&nexcoder_device_nor,
|
||||
};
|
||||
|
||||
static struct s3c24xx_board nexcoder_board __initdata = {
|
||||
.devices = nexcoder_devices,
|
||||
.devices_count = ARRAY_SIZE(nexcoder_devices),
|
||||
};
|
||||
|
||||
|
||||
static void __init nexcoder_sensorboard_init(void)
|
||||
{
|
||||
// Initialize SCCB bus
|
||||
@ -142,10 +136,14 @@ static void __init nexcoder_map_io(void)
|
||||
s3c24xx_init_io(nexcoder_iodesc, ARRAY_SIZE(nexcoder_iodesc));
|
||||
s3c24xx_init_clocks(0);
|
||||
s3c24xx_init_uarts(nexcoder_uartcfgs, ARRAY_SIZE(nexcoder_uartcfgs));
|
||||
s3c24xx_set_board(&nexcoder_board);
|
||||
|
||||
nexcoder_sensorboard_init();
|
||||
}
|
||||
|
||||
static void __init nexcoder_init(void)
|
||||
{
|
||||
platform_add_devices(nexcoder_devices, ARRAY_SIZE(nexcoder_devices));
|
||||
};
|
||||
|
||||
MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440")
|
||||
/* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
|
||||
@ -153,6 +151,7 @@ MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440")
|
||||
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
|
||||
.boot_params = S3C2410_SDRAM_PA + 0x100,
|
||||
.map_io = nexcoder_map_io,
|
||||
.init_machine = nexcoder_init,
|
||||
.init_irq = s3c24xx_init_irq,
|
||||
.timer = &s3c24xx_timer,
|
||||
MACHINE_END
|
||||
|
@ -251,13 +251,6 @@ static struct clk *osiris_clocks[] = {
|
||||
&s3c24xx_uclk,
|
||||
};
|
||||
|
||||
static struct s3c24xx_board osiris_board __initdata = {
|
||||
.devices = osiris_devices,
|
||||
.devices_count = ARRAY_SIZE(osiris_devices),
|
||||
.clocks = osiris_clocks,
|
||||
.clocks_count = ARRAY_SIZE(osiris_clocks),
|
||||
};
|
||||
|
||||
static void __init osiris_map_io(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
@ -275,12 +268,13 @@ static void __init osiris_map_io(void)
|
||||
|
||||
s3c24xx_uclk.parent = &s3c24xx_clkout1;
|
||||
|
||||
s3c24xx_register_clocks(osiris_clocks, ARRAY_SIZE(osiris_clocks));
|
||||
|
||||
s3c_device_nand.dev.platform_data = &osiris_nand_info;
|
||||
|
||||
s3c24xx_init_io(osiris_iodesc, ARRAY_SIZE(osiris_iodesc));
|
||||
s3c24xx_init_clocks(0);
|
||||
s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs));
|
||||
s3c24xx_set_board(&osiris_board);
|
||||
|
||||
/* fix bus configuration (nBE settings wrong on ABLE pre v2.20) */
|
||||
|
||||
@ -292,12 +286,18 @@ static void __init osiris_map_io(void)
|
||||
s3c2410_gpio_setpin(S3C2410_GPA0, 1);
|
||||
}
|
||||
|
||||
static void __init osiris_init(void)
|
||||
{
|
||||
platform_add_devices(osiris_devices, ARRAY_SIZE(osiris_devices));
|
||||
};
|
||||
|
||||
MACHINE_START(OSIRIS, "Simtec-OSIRIS")
|
||||
/* Maintainer: Ben Dooks <ben@simtec.co.uk> */
|
||||
.phys_io = S3C2410_PA_UART,
|
||||
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
|
||||
.boot_params = S3C2410_SDRAM_PA + 0x100,
|
||||
.map_io = osiris_map_io,
|
||||
.init_machine = osiris_init,
|
||||
.init_irq = s3c24xx_init_irq,
|
||||
.timer = &s3c24xx_timer,
|
||||
MACHINE_END
|
||||
|
@ -202,11 +202,6 @@ static struct platform_device *rx3715_devices[] __initdata = {
|
||||
&s3c_device_nand,
|
||||
};
|
||||
|
||||
static struct s3c24xx_board rx3715_board __initdata = {
|
||||
.devices = rx3715_devices,
|
||||
.devices_count = ARRAY_SIZE(rx3715_devices)
|
||||
};
|
||||
|
||||
static void __init rx3715_map_io(void)
|
||||
{
|
||||
s3c_device_nand.dev.platform_data = &rx3715_nand_info;
|
||||
@ -214,7 +209,6 @@ static void __init rx3715_map_io(void)
|
||||
s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc));
|
||||
s3c24xx_init_clocks(16934000);
|
||||
s3c24xx_init_uarts(rx3715_uartcfgs, ARRAY_SIZE(rx3715_uartcfgs));
|
||||
s3c24xx_set_board(&rx3715_board);
|
||||
}
|
||||
|
||||
static void __init rx3715_init_irq(void)
|
||||
@ -230,9 +224,9 @@ static void __init rx3715_init_machine(void)
|
||||
s3c2410_pm_init();
|
||||
|
||||
s3c24xx_fb_set_platdata(&rx3715_lcdcfg);
|
||||
platform_add_devices(rx3715_devices, ARRAY_SIZE(rx3715_devices));
|
||||
}
|
||||
|
||||
|
||||
MACHINE_START(RX3715, "IPAQ-RX3715")
|
||||
/* Maintainer: Ben Dooks <ben@fluff.org> */
|
||||
.phys_io = S3C2410_PA_UART,
|
||||
|
@ -174,23 +174,18 @@ static struct platform_device *smdk2440_devices[] __initdata = {
|
||||
&s3c_device_iis,
|
||||
};
|
||||
|
||||
static struct s3c24xx_board smdk2440_board __initdata = {
|
||||
.devices = smdk2440_devices,
|
||||
.devices_count = ARRAY_SIZE(smdk2440_devices)
|
||||
};
|
||||
|
||||
static void __init smdk2440_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
|
||||
s3c24xx_init_clocks(16934400);
|
||||
s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
|
||||
s3c24xx_set_board(&smdk2440_board);
|
||||
}
|
||||
|
||||
static void __init smdk2440_machine_init(void)
|
||||
{
|
||||
s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);
|
||||
|
||||
platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));
|
||||
smdk_machine_init();
|
||||
}
|
||||
|
||||
|
@ -106,21 +106,16 @@ static struct platform_device *smdk2443_devices[] __initdata = {
|
||||
&s3c_device_i2c,
|
||||
};
|
||||
|
||||
static struct s3c24xx_board smdk2443_board __initdata = {
|
||||
.devices = smdk2443_devices,
|
||||
.devices_count = ARRAY_SIZE(smdk2443_devices)
|
||||
};
|
||||
|
||||
static void __init smdk2443_map_io(void)
|
||||
{
|
||||
s3c24xx_init_io(smdk2443_iodesc, ARRAY_SIZE(smdk2443_iodesc));
|
||||
s3c24xx_init_clocks(12000000);
|
||||
s3c24xx_init_uarts(smdk2443_uartcfgs, ARRAY_SIZE(smdk2443_uartcfgs));
|
||||
s3c24xx_set_board(&smdk2443_board);
|
||||
}
|
||||
|
||||
static void __init smdk2443_machine_init(void)
|
||||
{
|
||||
platform_add_devices(smdk2443_devices, ARRAY_SIZE(smdk2443_devices));
|
||||
smdk_machine_init();
|
||||
}
|
||||
|
||||
|
@ -9,14 +9,17 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/semaphore.h>
|
||||
|
||||
/*
|
||||
* Very simple clock implementation - we only have one clock to
|
||||
* deal with at the moment, so we only match using the "name".
|
||||
*/
|
||||
struct clk {
|
||||
struct list_head node;
|
||||
unsigned long rate;
|
||||
struct module *owner;
|
||||
const char *name;
|
||||
unsigned int enabled;
|
||||
void (*enable)(void);
|
||||
@ -24,21 +27,21 @@ struct clk {
|
||||
};
|
||||
|
||||
static LIST_HEAD(clocks);
|
||||
static DECLARE_MUTEX(clocks_sem);
|
||||
static DEFINE_MUTEX(clocks_mutex);
|
||||
static DEFINE_SPINLOCK(clocks_lock);
|
||||
|
||||
struct clk *clk_get(struct device *dev, const char *id)
|
||||
{
|
||||
struct clk *p, *clk = ERR_PTR(-ENOENT);
|
||||
|
||||
down(&clocks_sem);
|
||||
mutex_lock(&clocks_mutex);
|
||||
list_for_each_entry(p, &clocks, node) {
|
||||
if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
|
||||
if (strcmp(id, p->name) == 0) {
|
||||
clk = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
up(&clocks_sem);
|
||||
mutex_unlock(&clocks_mutex);
|
||||
|
||||
return clk;
|
||||
}
|
||||
@ -46,7 +49,6 @@ EXPORT_SYMBOL(clk_get);
|
||||
|
||||
void clk_put(struct clk *clk)
|
||||
{
|
||||
module_put(clk->owner);
|
||||
}
|
||||
EXPORT_SYMBOL(clk_put);
|
||||
|
||||
@ -109,18 +111,18 @@ static struct clk clk_gpio27 = {
|
||||
|
||||
int clk_register(struct clk *clk)
|
||||
{
|
||||
down(&clocks_sem);
|
||||
mutex_lock(&clocks_mutex);
|
||||
list_add(&clk->node, &clocks);
|
||||
up(&clocks_sem);
|
||||
mutex_unlock(&clocks_mutex);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_register);
|
||||
|
||||
void clk_unregister(struct clk *clk)
|
||||
{
|
||||
down(&clocks_sem);
|
||||
mutex_lock(&clocks_mutex);
|
||||
list_del(&clk->node);
|
||||
up(&clocks_sem);
|
||||
mutex_unlock(&clocks_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(clk_unregister);
|
||||
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/amba/clcd.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/clockchips.h>
|
||||
|
||||
#include <asm/cnt32_to_63.h>
|
||||
#include <asm/system.h>
|
||||
@ -828,59 +830,61 @@ void __init versatile_init(void)
|
||||
#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Returns number of ms since last clock interrupt. Note that interrupts
|
||||
* will have been disabled by do_gettimeoffset()
|
||||
*/
|
||||
static unsigned long versatile_gettimeoffset(void)
|
||||
static void timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *clk)
|
||||
{
|
||||
unsigned long ticks1, ticks2, status;
|
||||
unsigned long ctrl;
|
||||
|
||||
/*
|
||||
* Get the current number of ticks. Note that there is a race
|
||||
* condition between us reading the timer and checking for
|
||||
* an interrupt. We get around this by ensuring that the
|
||||
* counter has not reloaded between our two reads.
|
||||
*/
|
||||
ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
|
||||
do {
|
||||
ticks1 = ticks2;
|
||||
status = __raw_readl(VA_IC_BASE + VIC_RAW_STATUS);
|
||||
ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
|
||||
} while (ticks2 > ticks1);
|
||||
switch(mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
|
||||
|
||||
/*
|
||||
* Number of ticks since last interrupt.
|
||||
*/
|
||||
ticks1 = TIMER_RELOAD - ticks2;
|
||||
|
||||
/*
|
||||
* Interrupt pending? If so, we've reloaded once already.
|
||||
*
|
||||
* FIXME: Need to check this is effectively timer 0 that expires
|
||||
*/
|
||||
if (status & IRQMASK_TIMERINT0_1)
|
||||
ticks1 += TIMER_RELOAD;
|
||||
|
||||
/*
|
||||
* Convert the ticks to usecs
|
||||
*/
|
||||
return TICKS2USECS(ticks1);
|
||||
ctrl = TIMER_CTRL_PERIODIC;
|
||||
ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE | TIMER_CTRL_ENABLE;
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
/* period set, and timer enabled in 'next_event' hook */
|
||||
ctrl = TIMER_CTRL_ONESHOT;
|
||||
ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE;
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
default:
|
||||
ctrl = 0;
|
||||
}
|
||||
|
||||
writel(ctrl, TIMER0_VA_BASE + TIMER_CTRL);
|
||||
}
|
||||
|
||||
static int timer_set_next_event(unsigned long evt,
|
||||
struct clock_event_device *unused)
|
||||
{
|
||||
unsigned long ctrl = readl(TIMER0_VA_BASE + TIMER_CTRL);
|
||||
|
||||
writel(evt, TIMER0_VA_BASE + TIMER_LOAD);
|
||||
writel(ctrl | TIMER_CTRL_ENABLE, TIMER0_VA_BASE + TIMER_CTRL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clock_event_device timer0_clockevent = {
|
||||
.name = "timer0",
|
||||
.shift = 32,
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_mode = timer_set_mode,
|
||||
.set_next_event = timer_set_next_event,
|
||||
};
|
||||
|
||||
/*
|
||||
* IRQ handler for the timer
|
||||
*/
|
||||
static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
write_seqlock(&xtime_lock);
|
||||
struct clock_event_device *evt = &timer0_clockevent;
|
||||
|
||||
// ...clear the interrupt
|
||||
writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
|
||||
|
||||
timer_tick();
|
||||
|
||||
write_sequnlock(&xtime_lock);
|
||||
evt->event_handler(evt);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -891,6 +895,36 @@ static struct irqaction versatile_timer_irq = {
|
||||
.handler = versatile_timer_interrupt,
|
||||
};
|
||||
|
||||
static cycle_t versatile_get_cycles(void)
|
||||
{
|
||||
return ~readl(TIMER3_VA_BASE + TIMER_VALUE);
|
||||
}
|
||||
|
||||
static struct clocksource clocksource_versatile = {
|
||||
.name = "timer3",
|
||||
.rating = 200,
|
||||
.read = versatile_get_cycles,
|
||||
.mask = CLOCKSOURCE_MASK(32),
|
||||
.shift = 20,
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
};
|
||||
|
||||
static int __init versatile_clocksource_init(void)
|
||||
{
|
||||
/* setup timer3 as free-running clocksource */
|
||||
writel(0, TIMER3_VA_BASE + TIMER_CTRL);
|
||||
writel(0xffffffff, TIMER3_VA_BASE + TIMER_LOAD);
|
||||
writel(0xffffffff, TIMER3_VA_BASE + TIMER_VALUE);
|
||||
writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
|
||||
TIMER3_VA_BASE + TIMER_CTRL);
|
||||
|
||||
clocksource_versatile.mult =
|
||||
clocksource_khz2mult(1000, clocksource_versatile.shift);
|
||||
clocksource_register(&clocksource_versatile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up timer interrupt, and return the current time in seconds.
|
||||
*/
|
||||
@ -918,18 +952,25 @@ static void __init versatile_timer_init(void)
|
||||
writel(0, TIMER2_VA_BASE + TIMER_CTRL);
|
||||
writel(0, TIMER3_VA_BASE + TIMER_CTRL);
|
||||
|
||||
writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
|
||||
writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_VALUE);
|
||||
writel(TIMER_DIVISOR | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC |
|
||||
TIMER_CTRL_IE, TIMER0_VA_BASE + TIMER_CTRL);
|
||||
|
||||
/*
|
||||
* Make irqs happen for the system timer
|
||||
*/
|
||||
setup_irq(IRQ_TIMERINT0_1, &versatile_timer_irq);
|
||||
|
||||
versatile_clocksource_init();
|
||||
|
||||
timer0_clockevent.mult =
|
||||
div_sc(1000000, NSEC_PER_SEC, timer0_clockevent.shift);
|
||||
timer0_clockevent.max_delta_ns =
|
||||
clockevent_delta2ns(0xffffffff, &timer0_clockevent);
|
||||
timer0_clockevent.min_delta_ns =
|
||||
clockevent_delta2ns(0xf, &timer0_clockevent);
|
||||
|
||||
timer0_clockevent.cpumask = cpumask_of_cpu(0);
|
||||
clockevents_register_device(&timer0_clockevent);
|
||||
}
|
||||
|
||||
struct sys_timer versatile_timer = {
|
||||
.init = versatile_timer_init,
|
||||
.offset = versatile_gettimeoffset,
|
||||
};
|
||||
|
||||
|
@ -19,6 +19,19 @@
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include "../kernel/stacktrace.h"
|
||||
|
||||
static int report_trace(struct stackframe *frame, void *d)
|
||||
{
|
||||
unsigned int *depth = d;
|
||||
|
||||
if (*depth) {
|
||||
oprofile_add_trace(frame->lr);
|
||||
(*depth)--;
|
||||
}
|
||||
|
||||
return *depth == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The registers we're interested in are at the end of the variable
|
||||
@ -32,21 +45,6 @@ struct frame_tail {
|
||||
unsigned long lr;
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
#ifdef CONFIG_FRAME_POINTER
|
||||
static struct frame_tail* kernel_backtrace(struct frame_tail *tail)
|
||||
{
|
||||
oprofile_add_trace(tail->lr);
|
||||
|
||||
/* frame pointers should strictly progress back up the stack
|
||||
* (towards higher addresses) */
|
||||
if (tail >= tail->fp)
|
||||
return NULL;
|
||||
|
||||
return tail->fp-1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct frame_tail* user_backtrace(struct frame_tail *tail)
|
||||
{
|
||||
struct frame_tail buftail[2];
|
||||
@ -67,47 +65,14 @@ static struct frame_tail* user_backtrace(struct frame_tail *tail)
|
||||
return buftail[0].fp-1;
|
||||
}
|
||||
|
||||
/*
|
||||
* | | /\ Higher addresses
|
||||
* | |
|
||||
* --------------- stack base (address of current_thread_info)
|
||||
* | thread info |
|
||||
* . .
|
||||
* | stack |
|
||||
* --------------- saved regs->ARM_fp value if valid (frame_tail address)
|
||||
* . .
|
||||
* --------------- struct pt_regs stored on stack (struct pt_regs *)
|
||||
* | |
|
||||
* . .
|
||||
* | |
|
||||
* --------------- %esp
|
||||
* | |
|
||||
* | | \/ Lower addresses
|
||||
*
|
||||
* Thus, &pt_regs <-> stack base restricts the valid(ish) fp values
|
||||
*/
|
||||
static int valid_kernel_stack(struct frame_tail *tail, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long tailaddr = (unsigned long)tail;
|
||||
unsigned long stack = (unsigned long)regs;
|
||||
unsigned long stack_base = (stack & ~(THREAD_SIZE - 1)) + THREAD_SIZE;
|
||||
|
||||
return (tailaddr > stack) && (tailaddr < stack_base);
|
||||
}
|
||||
|
||||
void arm_backtrace(struct pt_regs * const regs, unsigned int depth)
|
||||
{
|
||||
struct frame_tail *tail;
|
||||
|
||||
tail = ((struct frame_tail *) regs->ARM_fp) - 1;
|
||||
struct frame_tail *tail = ((struct frame_tail *) regs->ARM_fp) - 1;
|
||||
|
||||
if (!user_mode(regs)) {
|
||||
|
||||
#ifdef CONFIG_FRAME_POINTER
|
||||
while (depth-- && tail && valid_kernel_stack(tail, regs)) {
|
||||
tail = kernel_backtrace(tail);
|
||||
}
|
||||
#endif
|
||||
unsigned long base = ((unsigned long)regs) & ~(THREAD_SIZE - 1);
|
||||
walk_stackframe(regs->ARM_fp, base, base + THREAD_SIZE,
|
||||
report_trace, &depth);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ static u32 iop3xx_cfg_address(struct pci_bus *bus, int devfn, int where)
|
||||
* This routine checks the status of the last configuration cycle. If an error
|
||||
* was detected it returns a 1, else it returns a 0. The errors being checked
|
||||
* are parity, master abort, target abort (master and target). These types of
|
||||
* errors occure during a config cycle where there is no device, like during
|
||||
* errors occur during a config cycle where there is no device, like during
|
||||
* the discovery stage.
|
||||
*/
|
||||
static int iop3xx_pci_status(void)
|
||||
@ -223,8 +223,111 @@ struct pci_bus *iop3xx_pci_scan_bus(int nr, struct pci_sys_data *sys)
|
||||
return pci_scan_bus(sys->busnr, &iop3xx_ops, sys);
|
||||
}
|
||||
|
||||
void __init iop3xx_atu_setup(void)
|
||||
{
|
||||
/* BAR 0 ( Disabled ) */
|
||||
*IOP3XX_IAUBAR0 = 0x0;
|
||||
*IOP3XX_IABAR0 = 0x0;
|
||||
*IOP3XX_IATVR0 = 0x0;
|
||||
*IOP3XX_IALR0 = 0x0;
|
||||
|
||||
/* BAR 1 ( Disabled ) */
|
||||
*IOP3XX_IAUBAR1 = 0x0;
|
||||
*IOP3XX_IABAR1 = 0x0;
|
||||
*IOP3XX_IALR1 = 0x0;
|
||||
|
||||
/* BAR 2 (1:1 mapping with Physical RAM) */
|
||||
/* Set limit and enable */
|
||||
*IOP3XX_IALR2 = ~((u32)IOP3XX_MAX_RAM_SIZE - 1) & ~0x1;
|
||||
*IOP3XX_IAUBAR2 = 0x0;
|
||||
|
||||
/* Align the inbound bar with the base of memory */
|
||||
*IOP3XX_IABAR2 = PHYS_OFFSET |
|
||||
PCI_BASE_ADDRESS_MEM_TYPE_64 |
|
||||
PCI_BASE_ADDRESS_MEM_PREFETCH;
|
||||
|
||||
*IOP3XX_IATVR2 = PHYS_OFFSET;
|
||||
|
||||
/* Outbound window 0 */
|
||||
*IOP3XX_OMWTVR0 = IOP3XX_PCI_LOWER_MEM_PA;
|
||||
*IOP3XX_OUMWTVR0 = 0;
|
||||
|
||||
/* Outbound window 1 */
|
||||
*IOP3XX_OMWTVR1 = IOP3XX_PCI_LOWER_MEM_PA + IOP3XX_PCI_MEM_WINDOW_SIZE;
|
||||
*IOP3XX_OUMWTVR1 = 0;
|
||||
|
||||
/* BAR 3 ( Disabled ) */
|
||||
*IOP3XX_IAUBAR3 = 0x0;
|
||||
*IOP3XX_IABAR3 = 0x0;
|
||||
*IOP3XX_IATVR3 = 0x0;
|
||||
*IOP3XX_IALR3 = 0x0;
|
||||
|
||||
/* Setup the I/O Bar
|
||||
*/
|
||||
*IOP3XX_OIOWTVR = IOP3XX_PCI_LOWER_IO_PA;;
|
||||
|
||||
/* Enable inbound and outbound cycles
|
||||
*/
|
||||
*IOP3XX_ATUCMD |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
|
||||
PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
|
||||
*IOP3XX_ATUCR |= IOP3XX_ATUCR_OUT_EN;
|
||||
}
|
||||
|
||||
void __init iop3xx_atu_disable(void)
|
||||
{
|
||||
*IOP3XX_ATUCMD = 0;
|
||||
*IOP3XX_ATUCR = 0;
|
||||
|
||||
/* wait for cycles to quiesce */
|
||||
while (*IOP3XX_PCSR & (IOP3XX_PCSR_OUT_Q_BUSY |
|
||||
IOP3XX_PCSR_IN_Q_BUSY))
|
||||
cpu_relax();
|
||||
|
||||
/* BAR 0 ( Disabled ) */
|
||||
*IOP3XX_IAUBAR0 = 0x0;
|
||||
*IOP3XX_IABAR0 = 0x0;
|
||||
*IOP3XX_IATVR0 = 0x0;
|
||||
*IOP3XX_IALR0 = 0x0;
|
||||
|
||||
/* BAR 1 ( Disabled ) */
|
||||
*IOP3XX_IAUBAR1 = 0x0;
|
||||
*IOP3XX_IABAR1 = 0x0;
|
||||
*IOP3XX_IALR1 = 0x0;
|
||||
|
||||
/* BAR 2 ( Disabled ) */
|
||||
*IOP3XX_IAUBAR2 = 0x0;
|
||||
*IOP3XX_IABAR2 = 0x0;
|
||||
*IOP3XX_IATVR2 = 0x0;
|
||||
*IOP3XX_IALR2 = 0x0;
|
||||
|
||||
/* BAR 3 ( Disabled ) */
|
||||
*IOP3XX_IAUBAR3 = 0x0;
|
||||
*IOP3XX_IABAR3 = 0x0;
|
||||
*IOP3XX_IATVR3 = 0x0;
|
||||
*IOP3XX_IALR3 = 0x0;
|
||||
|
||||
/* Clear the outbound windows */
|
||||
*IOP3XX_OIOWTVR = 0;
|
||||
|
||||
/* Outbound window 0 */
|
||||
*IOP3XX_OMWTVR0 = 0;
|
||||
*IOP3XX_OUMWTVR0 = 0;
|
||||
|
||||
/* Outbound window 1 */
|
||||
*IOP3XX_OMWTVR1 = 0;
|
||||
*IOP3XX_OUMWTVR1 = 0;
|
||||
}
|
||||
|
||||
/* Flag to determine whether the ATU is initialized and the PCI bus scanned */
|
||||
int init_atu;
|
||||
|
||||
void iop3xx_pci_preinit(void)
|
||||
{
|
||||
if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) {
|
||||
iop3xx_atu_disable();
|
||||
iop3xx_atu_setup();
|
||||
}
|
||||
|
||||
DBG("PCI: Intel 803xx PCI init code.\n");
|
||||
DBG("ATU: IOP3XX_ATUCMD=0x%04x\n", *IOP3XX_ATUCMD);
|
||||
DBG("ATU: IOP3XX_OMWTVR0=0x%04x, IOP3XX_OIOWTVR=0x%04x\n",
|
||||
@ -245,3 +348,38 @@ void iop3xx_pci_preinit(void)
|
||||
|
||||
hook_fault_code(16+6, iop3xx_pci_abort, SIGBUS, "imprecise external abort");
|
||||
}
|
||||
|
||||
/* allow init_atu to be user overridden */
|
||||
static int __init iop3xx_init_atu_setup(char *str)
|
||||
{
|
||||
init_atu = IOP3XX_INIT_ATU_DEFAULT;
|
||||
if (str) {
|
||||
while (*str != '\0') {
|
||||
switch (*str) {
|
||||
case 'y':
|
||||
case 'Y':
|
||||
init_atu = IOP3XX_INIT_ATU_ENABLE;
|
||||
break;
|
||||
case 'n':
|
||||
case 'N':
|
||||
init_atu = IOP3XX_INIT_ATU_DISABLE;
|
||||
break;
|
||||
case ',':
|
||||
case '=':
|
||||
break;
|
||||
default:
|
||||
printk(KERN_DEBUG "\"%s\" malformed at "
|
||||
"character: \'%c\'",
|
||||
__FUNCTION__,
|
||||
*str);
|
||||
*(str + 1) = '\0';
|
||||
}
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("iop3xx_init_atu", iop3xx_init_atu_setup);
|
||||
|
||||
|
@ -32,22 +32,22 @@ static unsigned long next_jiffy_time;
|
||||
|
||||
unsigned long iop_gettimeoffset(void)
|
||||
{
|
||||
unsigned long offset, temp1, temp2;
|
||||
unsigned long offset, temp;
|
||||
|
||||
/* enable cp6, if necessary, to avoid taking the overhead of an
|
||||
* undefined instruction trap
|
||||
*/
|
||||
asm volatile (
|
||||
"mrc p15, 0, %0, c15, c1, 0\n\t"
|
||||
"ands %1, %0, #(1 << 6)\n\t"
|
||||
"tst %0, #(1 << 6)\n\t"
|
||||
"orreq %0, %0, #(1 << 6)\n\t"
|
||||
"mcreq p15, 0, %0, c15, c1, 0\n\t"
|
||||
#ifdef CONFIG_XSCALE
|
||||
#ifdef CONFIG_CPU_XSCALE
|
||||
"mrceq p15, 0, %0, c15, c1, 0\n\t"
|
||||
"moveq %0, %0\n\t"
|
||||
"subeq pc, pc, #4\n\t"
|
||||
#endif
|
||||
: "=r"(temp1), "=r"(temp2) : : "cc");
|
||||
: "=r"(temp) : : "cc");
|
||||
|
||||
offset = next_jiffy_time - read_tcr1();
|
||||
|
||||
|
@ -11,6 +11,7 @@ choice
|
||||
|
||||
config ARCH_OMAP1
|
||||
bool "TI OMAP1"
|
||||
select GENERIC_CLOCKEVENTS
|
||||
|
||||
config ARCH_OMAP2
|
||||
bool "TI OMAP2"
|
||||
|
@ -156,3 +156,53 @@ static int __init omap_add_serial_console(void)
|
||||
return add_preferred_console("ttyS", line, opt);
|
||||
}
|
||||
console_initcall(omap_add_serial_console);
|
||||
|
||||
|
||||
/*
|
||||
* 32KHz clocksource ... always available, on pretty most chips except
|
||||
* OMAP 730 and 1510. Other timers could be used as clocksources, with
|
||||
* higher resolution in free-running counter modes (e.g. 12 MHz xtal),
|
||||
* but systems won't necessarily want to spend resources that way.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_ARCH_OMAP16XX)
|
||||
#define TIMER_32K_SYNCHRONIZED 0xfffbc410
|
||||
#elif defined(CONFIG_ARCH_OMAP24XX)
|
||||
#define TIMER_32K_SYNCHRONIZED 0x48004010
|
||||
#endif
|
||||
|
||||
#ifdef TIMER_32K_SYNCHRONIZED
|
||||
|
||||
#include <linux/clocksource.h>
|
||||
|
||||
static cycle_t omap_32k_read(void)
|
||||
{
|
||||
return omap_readl(TIMER_32K_SYNCHRONIZED);
|
||||
}
|
||||
|
||||
static struct clocksource clocksource_32k = {
|
||||
.name = "32k_counter",
|
||||
.rating = 250,
|
||||
.read = omap_32k_read,
|
||||
.mask = CLOCKSOURCE_MASK(32),
|
||||
.shift = 10,
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
};
|
||||
|
||||
static int __init omap_init_clocksource_32k(void)
|
||||
{
|
||||
static char err[] __initdata = KERN_ERR
|
||||
"%s: can't register clocksource!\n";
|
||||
|
||||
if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
|
||||
clocksource_32k.mult = clocksource_hz2mult(32768,
|
||||
clocksource_32k.shift);
|
||||
|
||||
if (clocksource_register(&clocksource_32k))
|
||||
printk(err, clocksource_32k.name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(omap_init_clocksource_32k);
|
||||
|
||||
#endif /* TIMER_32K_SYNCHRONIZED */
|
||||
|
@ -429,6 +429,10 @@ static inline void omap_init_rng(void) {}
|
||||
*/
|
||||
static int __init omap_init_devices(void)
|
||||
{
|
||||
/*
|
||||
* Need to enable relevant once for 2430 SDP
|
||||
*/
|
||||
#ifndef CONFIG_MACH_OMAP_2430SDP
|
||||
/* please keep these calls, and their implementations above,
|
||||
* in alphabetical order so they're easier to sort through.
|
||||
*/
|
||||
@ -438,7 +442,7 @@ static int __init omap_init_devices(void)
|
||||
omap_init_uwire();
|
||||
omap_init_wdt();
|
||||
omap_init_rng();
|
||||
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(omap_init_devices);
|
||||
|
@ -506,6 +506,8 @@ int omap_dm_timer_init(void)
|
||||
BUG_ON(dm_source_clocks[i] == NULL);
|
||||
}
|
||||
#endif
|
||||
if (cpu_is_omap243x())
|
||||
dm_timers[0].phys_base = 0x49018000;
|
||||
|
||||
for (i = 0; i < dm_timer_count; i++) {
|
||||
#ifdef CONFIG_ARCH_OMAP2
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -225,12 +225,17 @@ static void omap_mcbsp_dsp_free(void)
|
||||
#ifdef CONFIG_ARCH_OMAP2
|
||||
static void omap2_mcbsp2_mux_setup(void)
|
||||
{
|
||||
if (cpu_is_omap2420()) {
|
||||
omap_cfg_reg(Y15_24XX_MCBSP2_CLKX);
|
||||
omap_cfg_reg(R14_24XX_MCBSP2_FSX);
|
||||
omap_cfg_reg(W15_24XX_MCBSP2_DR);
|
||||
omap_cfg_reg(V15_24XX_MCBSP2_DX);
|
||||
omap_cfg_reg(V14_24XX_GPIO117);
|
||||
}
|
||||
/*
|
||||
* Need to add MUX settings for OMAP 2430 SDP
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -42,6 +42,8 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/clockchips.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/hardware.h>
|
||||
@ -80,13 +82,13 @@ struct sys_timer omap_timer;
|
||||
#define OMAP1_32K_TIMER_TVR 0x00
|
||||
#define OMAP1_32K_TIMER_TCR 0x04
|
||||
|
||||
#define OMAP_32K_TICKS_PER_HZ (32768 / HZ)
|
||||
#define OMAP_32K_TICKS_PER_SEC (32768)
|
||||
|
||||
/*
|
||||
* TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
|
||||
* so with HZ = 128, TVR = 255.
|
||||
*/
|
||||
#define OMAP_32K_TIMER_TICK_PERIOD ((32768 / HZ) - 1)
|
||||
#define OMAP_32K_TIMER_TICK_PERIOD ((OMAP_32K_TICKS_PER_SEC / HZ) - 1)
|
||||
|
||||
#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \
|
||||
(((nr_jiffies) * (clock_rate)) / HZ)
|
||||
@ -142,6 +144,28 @@ static inline void omap_32k_timer_ack_irq(void)
|
||||
|
||||
#endif
|
||||
|
||||
static void omap_32k_timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
omap_32k_timer_stop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct clock_event_device clockevent_32k_timer = {
|
||||
.name = "32k-timer",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC,
|
||||
.shift = 32,
|
||||
.set_mode = omap_32k_timer_set_mode,
|
||||
};
|
||||
|
||||
/*
|
||||
* The 32KHz synchronized timer is an additional timer on 16xx.
|
||||
* It is always running.
|
||||
@ -170,15 +194,6 @@ omap_32k_ticks_to_nsecs(unsigned long ticks_32k)
|
||||
|
||||
static unsigned long omap_32k_last_tick = 0;
|
||||
|
||||
/*
|
||||
* Returns elapsed usecs since last 32k timer interrupt
|
||||
*/
|
||||
static unsigned long omap_32k_timer_gettimeoffset(void)
|
||||
{
|
||||
unsigned long now = omap_32k_sync_timer_read();
|
||||
return omap_32k_ticks_to_usecs(now - omap_32k_last_tick);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns current time from boot in nsecs. It's OK for this to wrap
|
||||
* around for now, as it's just a relative time stamp.
|
||||
@ -188,95 +203,16 @@ unsigned long long sched_clock(void)
|
||||
return omap_32k_ticks_to_nsecs(omap_32k_sync_timer_read());
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer interrupt for 32KHz timer. When dynamic tick is enabled, this
|
||||
* function is also called from other interrupts to remove latency
|
||||
* issues with dynamic tick. In the dynamic tick case, we need to lock
|
||||
* with irqsave.
|
||||
*/
|
||||
static inline irqreturn_t _omap_32k_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
unsigned long now;
|
||||
|
||||
omap_32k_timer_ack_irq();
|
||||
now = omap_32k_sync_timer_read();
|
||||
|
||||
while ((signed long)(now - omap_32k_last_tick)
|
||||
>= OMAP_32K_TICKS_PER_HZ) {
|
||||
omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ;
|
||||
timer_tick();
|
||||
}
|
||||
|
||||
/* Restart timer so we don't drift off due to modulo or dynamic tick.
|
||||
* By default we program the next timer to be continuous to avoid
|
||||
* latencies during high system load. During dynamic tick operation the
|
||||
* continuous timer can be overridden from pm_idle to be longer.
|
||||
*/
|
||||
omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t omap_32k_timer_handler(int irq, void *dev_id)
|
||||
{
|
||||
return _omap_32k_timer_interrupt(irq, dev_id);
|
||||
}
|
||||
|
||||
static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct clock_event_device *evt = &clockevent_32k_timer;
|
||||
omap_32k_timer_ack_irq();
|
||||
|
||||
write_seqlock_irqsave(&xtime_lock, flags);
|
||||
_omap_32k_timer_interrupt(irq, dev_id);
|
||||
write_sequnlock_irqrestore(&xtime_lock, flags);
|
||||
evt->event_handler(evt);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NO_IDLE_HZ
|
||||
/*
|
||||
* Programs the next timer interrupt needed. Called when dynamic tick is
|
||||
* enabled, and to reprogram the ticks to skip from pm_idle. Note that
|
||||
* we can keep the timer continuous, and don't need to set it to run in
|
||||
* one-shot mode. This is because the timer will get reprogrammed again
|
||||
* after next interrupt.
|
||||
*/
|
||||
void omap_32k_timer_reprogram(unsigned long next_tick)
|
||||
{
|
||||
unsigned long ticks = JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1;
|
||||
unsigned long now = omap_32k_sync_timer_read();
|
||||
unsigned long idled = now - omap_32k_last_tick;
|
||||
|
||||
if (idled + 1 < ticks)
|
||||
ticks -= idled;
|
||||
else
|
||||
ticks = 1;
|
||||
omap_32k_timer_start(ticks);
|
||||
}
|
||||
|
||||
static struct irqaction omap_32k_timer_irq;
|
||||
extern struct timer_update_handler timer_update;
|
||||
|
||||
static int omap_32k_timer_enable_dyn_tick(void)
|
||||
{
|
||||
/* No need to reprogram timer, just use the next interrupt */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int omap_32k_timer_disable_dyn_tick(void)
|
||||
{
|
||||
omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dyn_tick_timer omap_dyn_tick_timer = {
|
||||
.enable = omap_32k_timer_enable_dyn_tick,
|
||||
.disable = omap_32k_timer_disable_dyn_tick,
|
||||
.reprogram = omap_32k_timer_reprogram,
|
||||
.handler = omap_32k_timer_handler,
|
||||
};
|
||||
#endif /* CONFIG_NO_IDLE_HZ */
|
||||
|
||||
static struct irqaction omap_32k_timer_irq = {
|
||||
.name = "32KHz timer",
|
||||
.flags = IRQF_DISABLED | IRQF_TIMER,
|
||||
@ -285,13 +221,8 @@ static struct irqaction omap_32k_timer_irq = {
|
||||
|
||||
static __init void omap_init_32k_timer(void)
|
||||
{
|
||||
#ifdef CONFIG_NO_IDLE_HZ
|
||||
omap_timer.dyn_tick = &omap_dyn_tick_timer;
|
||||
#endif
|
||||
|
||||
if (cpu_class_is_omap1())
|
||||
setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
|
||||
omap_timer.offset = omap_32k_timer_gettimeoffset;
|
||||
omap_32k_last_tick = omap_32k_sync_timer_read();
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP2
|
||||
@ -308,7 +239,16 @@ static __init void omap_init_32k_timer(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
|
||||
clockevent_32k_timer.mult = div_sc(OMAP_32K_TICKS_PER_SEC,
|
||||
NSEC_PER_SEC,
|
||||
clockevent_32k_timer.shift);
|
||||
clockevent_32k_timer.max_delta_ns =
|
||||
clockevent_delta2ns(0xfffffffe, &clockevent_32k_timer);
|
||||
clockevent_32k_timer.min_delta_ns =
|
||||
clockevent_delta2ns(1, &clockevent_32k_timer);
|
||||
|
||||
clockevent_32k_timer.cpumask = cpumask_of_cpu(0);
|
||||
clockevents_register_device(&clockevent_32k_timer);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -326,5 +266,4 @@ static void __init omap_timer_init(void)
|
||||
|
||||
struct sys_timer omap_timer = {
|
||||
.init = omap_timer_init,
|
||||
.offset = NULL, /* Initialized later */
|
||||
};
|
||||
|
@ -404,6 +404,18 @@ int s3c24xx_register_clock(struct clk *clk)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int s3c24xx_register_clocks(struct clk **clks, int nr_clks)
|
||||
{
|
||||
int fails = 0;
|
||||
|
||||
for (; nr_clks > 0; nr_clks--, clks++) {
|
||||
if (s3c24xx_register_clock(*clks) < 0)
|
||||
fails++;
|
||||
}
|
||||
|
||||
return fails;
|
||||
}
|
||||
|
||||
/* initalise all the clocks */
|
||||
|
||||
int __init s3c24xx_setup_clocks(unsigned long xtal,
|
||||
|
@ -181,24 +181,6 @@ s3c_lookup_cpu(unsigned long idcode)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* board information */
|
||||
|
||||
static struct s3c24xx_board *board;
|
||||
|
||||
void s3c24xx_set_board(struct s3c24xx_board *b)
|
||||
{
|
||||
int i;
|
||||
|
||||
board = b;
|
||||
|
||||
if (b->clocks_count != 0) {
|
||||
struct clk **ptr = b->clocks;
|
||||
|
||||
for (i = b->clocks_count; i > 0; i--, ptr++)
|
||||
s3c24xx_register_clock(*ptr);
|
||||
}
|
||||
}
|
||||
|
||||
/* cpu information */
|
||||
|
||||
static struct cpu_table *cpu;
|
||||
@ -342,26 +324,6 @@ static int __init s3c_arch_init(void)
|
||||
return ret;
|
||||
|
||||
ret = platform_add_devices(s3c24xx_uart_devs, nr_uarts);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if (board != NULL) {
|
||||
struct platform_device **ptr = board->devices;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < board->devices_count; i++, ptr++) {
|
||||
ret = platform_device_register(*ptr);
|
||||
|
||||
if (ret) {
|
||||
printk(KERN_ERR "s3c24xx: failed to add board device %s (%d) @%p\n", (*ptr)->name, ret, *ptr);
|
||||
}
|
||||
}
|
||||
|
||||
/* mask any error, we may not need all these board
|
||||
* devices */
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ static struct kmem_cache *dma_kmem;
|
||||
|
||||
static int dma_channels;
|
||||
|
||||
struct s3c24xx_dma_selection dma_sel;
|
||||
static struct s3c24xx_dma_selection dma_sel;
|
||||
|
||||
/* dma channel state information */
|
||||
struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
|
||||
@ -880,7 +880,7 @@ static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan)
|
||||
static void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan)
|
||||
{
|
||||
unsigned long tmp;
|
||||
unsigned int timeout = 0x10000;
|
||||
@ -957,8 +957,7 @@ static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
s3c2410_dma_started(struct s3c2410_dma_chan *chan)
|
||||
static int s3c2410_dma_started(struct s3c2410_dma_chan *chan)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
@ -1280,7 +1279,7 @@ static void s3c2410_dma_cache_ctor(void *p, struct kmem_cache *c, unsigned long
|
||||
|
||||
/* initialisation code */
|
||||
|
||||
int __init s3c24xx_dma_sysclass_init(void)
|
||||
static int __init s3c24xx_dma_sysclass_init(void)
|
||||
{
|
||||
int ret = sysdev_class_register(&dma_sysclass);
|
||||
|
||||
@ -1292,7 +1291,7 @@ int __init s3c24xx_dma_sysclass_init(void)
|
||||
|
||||
core_initcall(s3c24xx_dma_sysclass_init);
|
||||
|
||||
int __init s3c24xx_dma_sysdev_register(void)
|
||||
static int __init s3c24xx_dma_sysdev_register(void)
|
||||
{
|
||||
struct s3c2410_dma_chan *cp = s3c2410_chans;
|
||||
int channel, ret;
|
||||
@ -1396,7 +1395,7 @@ static struct s3c24xx_dma_order *dma_order;
|
||||
* channel
|
||||
*/
|
||||
|
||||
struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
|
||||
static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
|
||||
{
|
||||
struct s3c24xx_dma_order_ch *ord = NULL;
|
||||
struct s3c24xx_dma_map *ch_map;
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <asm/div64.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/vfp.h>
|
||||
|
||||
#include "vfpinstr.h"
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <asm/div64.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/vfp.h>
|
||||
|
||||
#include "vfpinstr.h"
|
||||
|
@ -545,13 +545,21 @@ config PATA_WINBOND_VLB
|
||||
|
||||
config PATA_PLATFORM
|
||||
tristate "Generic platform device PATA support"
|
||||
depends on EMBEDDED
|
||||
depends on EMBEDDED || ARCH_RPC
|
||||
help
|
||||
This option enables support for generic directly connected ATA
|
||||
devices commonly found on embedded systems.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config PATA_ICSIDE
|
||||
tristate "Acorn ICS PATA support"
|
||||
depends on ARM && ARCH_ACORN
|
||||
help
|
||||
On Acorn systems, say Y here if you wish to use the ICS PATA
|
||||
interface card. This is not required for ICS partition support.
|
||||
If you are unsure, say N to this.
|
||||
|
||||
config PATA_IXP4XX_CF
|
||||
tristate "IXP4XX Compact Flash support"
|
||||
depends on ARCH_IXP4XX
|
||||
|
@ -61,6 +61,7 @@ obj-$(CONFIG_PATA_TRIFLEX) += pata_triflex.o
|
||||
obj-$(CONFIG_PATA_IXP4XX_CF) += pata_ixp4xx_cf.o
|
||||
obj-$(CONFIG_PATA_SCC) += pata_scc.o
|
||||
obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o
|
||||
obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o
|
||||
# Should be last but one libata driver
|
||||
obj-$(CONFIG_ATA_GENERIC) += ata_generic.o
|
||||
# Should be last libata driver
|
||||
|
686
drivers/ata/pata_icside.c
Normal file
686
drivers/ata/pata_icside.c
Normal file
@ -0,0 +1,686 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <linux/ata.h>
|
||||
#include <linux/libata.h>
|
||||
|
||||
#include <asm/dma.h>
|
||||
#include <asm/ecard.h>
|
||||
|
||||
#define DRV_NAME "pata_icside"
|
||||
|
||||
#define ICS_IDENT_OFFSET 0x2280
|
||||
|
||||
#define ICS_ARCIN_V5_INTRSTAT 0x0000
|
||||
#define ICS_ARCIN_V5_INTROFFSET 0x0004
|
||||
|
||||
#define ICS_ARCIN_V6_INTROFFSET_1 0x2200
|
||||
#define ICS_ARCIN_V6_INTRSTAT_1 0x2290
|
||||
#define ICS_ARCIN_V6_INTROFFSET_2 0x3200
|
||||
#define ICS_ARCIN_V6_INTRSTAT_2 0x3290
|
||||
|
||||
struct portinfo {
|
||||
unsigned int dataoffset;
|
||||
unsigned int ctrloffset;
|
||||
unsigned int stepping;
|
||||
};
|
||||
|
||||
static const struct portinfo pata_icside_portinfo_v5 = {
|
||||
.dataoffset = 0x2800,
|
||||
.ctrloffset = 0x2b80,
|
||||
.stepping = 6,
|
||||
};
|
||||
|
||||
static const struct portinfo pata_icside_portinfo_v6_1 = {
|
||||
.dataoffset = 0x2000,
|
||||
.ctrloffset = 0x2380,
|
||||
.stepping = 6,
|
||||
};
|
||||
|
||||
static const struct portinfo pata_icside_portinfo_v6_2 = {
|
||||
.dataoffset = 0x3000,
|
||||
.ctrloffset = 0x3380,
|
||||
.stepping = 6,
|
||||
};
|
||||
|
||||
#define PATA_ICSIDE_MAX_SG 128
|
||||
|
||||
struct pata_icside_state {
|
||||
void __iomem *irq_port;
|
||||
void __iomem *ioc_base;
|
||||
unsigned int type;
|
||||
unsigned int dma;
|
||||
struct {
|
||||
u8 port_sel;
|
||||
u8 disabled;
|
||||
unsigned int speed[ATA_MAX_DEVICES];
|
||||
} port[2];
|
||||
struct scatterlist sg[PATA_ICSIDE_MAX_SG];
|
||||
};
|
||||
|
||||
#define ICS_TYPE_A3IN 0
|
||||
#define ICS_TYPE_A3USER 1
|
||||
#define ICS_TYPE_V6 3
|
||||
#define ICS_TYPE_V5 15
|
||||
#define ICS_TYPE_NOTYPE ((unsigned int)-1)
|
||||
|
||||
/* ---------------- Version 5 PCB Support Functions --------------------- */
|
||||
/* Prototype: pata_icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
|
||||
* Purpose : enable interrupts from card
|
||||
*/
|
||||
static void pata_icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
|
||||
{
|
||||
struct pata_icside_state *state = ec->irq_data;
|
||||
|
||||
writeb(0, state->irq_port + ICS_ARCIN_V5_INTROFFSET);
|
||||
}
|
||||
|
||||
/* Prototype: pata_icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
|
||||
* Purpose : disable interrupts from card
|
||||
*/
|
||||
static void pata_icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
|
||||
{
|
||||
struct pata_icside_state *state = ec->irq_data;
|
||||
|
||||
readb(state->irq_port + ICS_ARCIN_V5_INTROFFSET);
|
||||
}
|
||||
|
||||
static const expansioncard_ops_t pata_icside_ops_arcin_v5 = {
|
||||
.irqenable = pata_icside_irqenable_arcin_v5,
|
||||
.irqdisable = pata_icside_irqdisable_arcin_v5,
|
||||
};
|
||||
|
||||
|
||||
/* ---------------- Version 6 PCB Support Functions --------------------- */
|
||||
/* Prototype: pata_icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
|
||||
* Purpose : enable interrupts from card
|
||||
*/
|
||||
static void pata_icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
|
||||
{
|
||||
struct pata_icside_state *state = ec->irq_data;
|
||||
void __iomem *base = state->irq_port;
|
||||
|
||||
if (!state->port[0].disabled)
|
||||
writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
|
||||
if (!state->port[1].disabled)
|
||||
writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
|
||||
}
|
||||
|
||||
/* Prototype: pata_icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
|
||||
* Purpose : disable interrupts from card
|
||||
*/
|
||||
static void pata_icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
|
||||
{
|
||||
struct pata_icside_state *state = ec->irq_data;
|
||||
|
||||
readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
|
||||
readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
|
||||
}
|
||||
|
||||
/* Prototype: pata_icside_irqprobe(struct expansion_card *ec)
|
||||
* Purpose : detect an active interrupt from card
|
||||
*/
|
||||
static int pata_icside_irqpending_arcin_v6(struct expansion_card *ec)
|
||||
{
|
||||
struct pata_icside_state *state = ec->irq_data;
|
||||
|
||||
return readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 ||
|
||||
readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;
|
||||
}
|
||||
|
||||
static const expansioncard_ops_t pata_icside_ops_arcin_v6 = {
|
||||
.irqenable = pata_icside_irqenable_arcin_v6,
|
||||
.irqdisable = pata_icside_irqdisable_arcin_v6,
|
||||
.irqpending = pata_icside_irqpending_arcin_v6,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* SG-DMA support.
|
||||
*
|
||||
* Similar to the BM-DMA, but we use the RiscPCs IOMD DMA controllers.
|
||||
* There is only one DMA controller per card, which means that only
|
||||
* one drive can be accessed at one time. NOTE! We do not enforce that
|
||||
* here, but we rely on the main IDE driver spotting that both
|
||||
* interfaces use the same IRQ, which should guarantee this.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Configure the IOMD to give the appropriate timings for the transfer
|
||||
* mode being requested. We take the advice of the ATA standards, and
|
||||
* calculate the cycle time based on the transfer mode, and the EIDE
|
||||
* MW DMA specs that the drive provides in the IDENTIFY command.
|
||||
*
|
||||
* We have the following IOMD DMA modes to choose from:
|
||||
*
|
||||
* Type Active Recovery Cycle
|
||||
* A 250 (250) 312 (550) 562 (800)
|
||||
* B 187 (200) 250 (550) 437 (750)
|
||||
* C 125 (125) 125 (375) 250 (500)
|
||||
* D 62 (50) 125 (375) 187 (425)
|
||||
*
|
||||
* (figures in brackets are actual measured timings on DIOR/DIOW)
|
||||
*
|
||||
* However, we also need to take care of the read/write active and
|
||||
* recovery timings:
|
||||
*
|
||||
* Read Write
|
||||
* Mode Active -- Recovery -- Cycle IOMD type
|
||||
* MW0 215 50 215 480 A
|
||||
* MW1 80 50 50 150 C
|
||||
* MW2 70 25 25 120 C
|
||||
*/
|
||||
static void pata_icside_set_dmamode(struct ata_port *ap, struct ata_device *adev)
|
||||
{
|
||||
struct pata_icside_state *state = ap->host->private_data;
|
||||
struct ata_timing t;
|
||||
unsigned int cycle;
|
||||
char iomd_type;
|
||||
|
||||
/*
|
||||
* DMA is based on a 16MHz clock
|
||||
*/
|
||||
if (ata_timing_compute(adev, adev->dma_mode, &t, 1000, 1))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Choose the IOMD cycle timing which ensure that the interface
|
||||
* satisfies the measured active, recovery and cycle times.
|
||||
*/
|
||||
if (t.active <= 50 && t.recover <= 375 && t.cycle <= 425)
|
||||
iomd_type = 'D', cycle = 187;
|
||||
else if (t.active <= 125 && t.recover <= 375 && t.cycle <= 500)
|
||||
iomd_type = 'C', cycle = 250;
|
||||
else if (t.active <= 200 && t.recover <= 550 && t.cycle <= 750)
|
||||
iomd_type = 'B', cycle = 437;
|
||||
else
|
||||
iomd_type = 'A', cycle = 562;
|
||||
|
||||
ata_dev_printk(adev, KERN_INFO, "timings: act %dns rec %dns cyc %dns (%c)\n",
|
||||
t.active, t.recover, t.cycle, iomd_type);
|
||||
|
||||
state->port[ap->port_no].speed[adev->devno] = cycle;
|
||||
}
|
||||
|
||||
static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct ata_port *ap = qc->ap;
|
||||
struct pata_icside_state *state = ap->host->private_data;
|
||||
struct scatterlist *sg, *rsg = state->sg;
|
||||
unsigned int write = qc->tf.flags & ATA_TFLAG_WRITE;
|
||||
|
||||
/*
|
||||
* We are simplex; BUG if we try to fiddle with DMA
|
||||
* while it's active.
|
||||
*/
|
||||
BUG_ON(dma_channel_active(state->dma));
|
||||
|
||||
/*
|
||||
* Copy ATAs scattered sg list into a contiguous array of sg
|
||||
*/
|
||||
ata_for_each_sg(sg, qc) {
|
||||
memcpy(rsg, sg, sizeof(*sg));
|
||||
rsg++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Route the DMA signals to the correct interface
|
||||
*/
|
||||
writeb(state->port[ap->port_no].port_sel, state->ioc_base);
|
||||
|
||||
set_dma_speed(state->dma, state->port[ap->port_no].speed[qc->dev->devno]);
|
||||
set_dma_sg(state->dma, state->sg, rsg - state->sg);
|
||||
set_dma_mode(state->dma, write ? DMA_MODE_WRITE : DMA_MODE_READ);
|
||||
|
||||
/* issue r/w command */
|
||||
ap->ops->exec_command(ap, &qc->tf);
|
||||
}
|
||||
|
||||
static void pata_icside_bmdma_start(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct ata_port *ap = qc->ap;
|
||||
struct pata_icside_state *state = ap->host->private_data;
|
||||
|
||||
BUG_ON(dma_channel_active(state->dma));
|
||||
enable_dma(state->dma);
|
||||
}
|
||||
|
||||
static void pata_icside_bmdma_stop(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct ata_port *ap = qc->ap;
|
||||
struct pata_icside_state *state = ap->host->private_data;
|
||||
|
||||
disable_dma(state->dma);
|
||||
|
||||
/* see ata_bmdma_stop */
|
||||
ata_altstatus(ap);
|
||||
}
|
||||
|
||||
static u8 pata_icside_bmdma_status(struct ata_port *ap)
|
||||
{
|
||||
struct pata_icside_state *state = ap->host->private_data;
|
||||
void __iomem *irq_port;
|
||||
|
||||
irq_port = state->irq_port + (ap->port_no ? ICS_ARCIN_V6_INTRSTAT_2 :
|
||||
ICS_ARCIN_V6_INTRSTAT_1);
|
||||
|
||||
return readb(irq_port) & 1 ? ATA_DMA_INTR : 0;
|
||||
}
|
||||
|
||||
static int icside_dma_init(struct ata_probe_ent *ae, struct expansion_card *ec)
|
||||
{
|
||||
struct pata_icside_state *state = ae->private_data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ATA_MAX_DEVICES; i++) {
|
||||
state->port[0].speed[i] = 480;
|
||||
state->port[1].speed[i] = 480;
|
||||
}
|
||||
|
||||
if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) {
|
||||
state->dma = ec->dma;
|
||||
ae->mwdma_mask = 0x07; /* MW0..2 */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int pata_icside_port_start(struct ata_port *ap)
|
||||
{
|
||||
/* No PRD to alloc */
|
||||
return ata_pad_alloc(ap, ap->dev);
|
||||
}
|
||||
|
||||
static struct scsi_host_template pata_icside_sht = {
|
||||
.module = THIS_MODULE,
|
||||
.name = DRV_NAME,
|
||||
.ioctl = ata_scsi_ioctl,
|
||||
.queuecommand = ata_scsi_queuecmd,
|
||||
.can_queue = ATA_DEF_QUEUE,
|
||||
.this_id = ATA_SHT_THIS_ID,
|
||||
.sg_tablesize = PATA_ICSIDE_MAX_SG,
|
||||
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
|
||||
.emulated = ATA_SHT_EMULATED,
|
||||
.use_clustering = ATA_SHT_USE_CLUSTERING,
|
||||
.proc_name = DRV_NAME,
|
||||
.dma_boundary = ~0, /* no dma boundaries */
|
||||
.slave_configure = ata_scsi_slave_config,
|
||||
.slave_destroy = ata_scsi_slave_destroy,
|
||||
.bios_param = ata_std_bios_param,
|
||||
};
|
||||
|
||||
/* wish this was exported from libata-core */
|
||||
static void ata_dummy_noret(struct ata_port *port)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to shut down unused ports to prevent spurious interrupts.
|
||||
* FIXME: the libata core doesn't call this function for PATA interfaces.
|
||||
*/
|
||||
static void pata_icside_port_disable(struct ata_port *ap)
|
||||
{
|
||||
struct pata_icside_state *state = ap->host->private_data;
|
||||
|
||||
ata_port_printk(ap, KERN_ERR, "disabling icside port\n");
|
||||
|
||||
ata_port_disable(ap);
|
||||
|
||||
state->port[ap->port_no].disabled = 1;
|
||||
|
||||
if (state->type == ICS_TYPE_V6) {
|
||||
/*
|
||||
* Disable interrupts from this port, otherwise we
|
||||
* receive spurious interrupts from the floating
|
||||
* interrupt line.
|
||||
*/
|
||||
void __iomem *irq_port = state->irq_port +
|
||||
(ap->port_no ? ICS_ARCIN_V6_INTROFFSET_2 : ICS_ARCIN_V6_INTROFFSET_1);
|
||||
readb(irq_port);
|
||||
}
|
||||
}
|
||||
|
||||
static u8 pata_icside_irq_ack(struct ata_port *ap, unsigned int chk_drq)
|
||||
{
|
||||
unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
|
||||
u8 status;
|
||||
|
||||
status = ata_busy_wait(ap, bits, 1000);
|
||||
if (status & bits)
|
||||
if (ata_msg_err(ap))
|
||||
printk(KERN_ERR "abnormal status 0x%X\n", status);
|
||||
|
||||
if (ata_msg_intr(ap))
|
||||
printk(KERN_INFO "%s: irq ack: drv_stat 0x%X\n",
|
||||
__FUNCTION__, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static struct ata_port_operations pata_icside_port_ops = {
|
||||
.port_disable = pata_icside_port_disable,
|
||||
|
||||
.set_dmamode = pata_icside_set_dmamode,
|
||||
|
||||
.tf_load = ata_tf_load,
|
||||
.tf_read = ata_tf_read,
|
||||
.exec_command = ata_exec_command,
|
||||
.check_status = ata_check_status,
|
||||
.dev_select = ata_std_dev_select,
|
||||
|
||||
.bmdma_setup = pata_icside_bmdma_setup,
|
||||
.bmdma_start = pata_icside_bmdma_start,
|
||||
|
||||
.data_xfer = ata_data_xfer_noirq,
|
||||
|
||||
/* no need to build any PRD tables for DMA */
|
||||
.qc_prep = ata_noop_qc_prep,
|
||||
.qc_issue = ata_qc_issue_prot,
|
||||
|
||||
.freeze = ata_bmdma_freeze,
|
||||
.thaw = ata_bmdma_thaw,
|
||||
.error_handler = ata_bmdma_error_handler,
|
||||
.post_internal_cmd = pata_icside_bmdma_stop,
|
||||
|
||||
.irq_handler = ata_interrupt,
|
||||
.irq_clear = ata_dummy_noret,
|
||||
.irq_on = ata_irq_on,
|
||||
.irq_ack = pata_icside_irq_ack,
|
||||
|
||||
.port_start = pata_icside_port_start,
|
||||
|
||||
.bmdma_stop = pata_icside_bmdma_stop,
|
||||
.bmdma_status = pata_icside_bmdma_status,
|
||||
};
|
||||
|
||||
static void
|
||||
pata_icside_add_port(struct ata_probe_ent *ae, void __iomem *base,
|
||||
const struct portinfo *info)
|
||||
{
|
||||
struct ata_ioports *ioaddr = &ae->port[ae->n_ports++];
|
||||
void __iomem *cmd = base + info->dataoffset;
|
||||
|
||||
ioaddr->cmd_addr = cmd;
|
||||
ioaddr->data_addr = cmd + (ATA_REG_DATA << info->stepping);
|
||||
ioaddr->error_addr = cmd + (ATA_REG_ERR << info->stepping);
|
||||
ioaddr->feature_addr = cmd + (ATA_REG_FEATURE << info->stepping);
|
||||
ioaddr->nsect_addr = cmd + (ATA_REG_NSECT << info->stepping);
|
||||
ioaddr->lbal_addr = cmd + (ATA_REG_LBAL << info->stepping);
|
||||
ioaddr->lbam_addr = cmd + (ATA_REG_LBAM << info->stepping);
|
||||
ioaddr->lbah_addr = cmd + (ATA_REG_LBAH << info->stepping);
|
||||
ioaddr->device_addr = cmd + (ATA_REG_DEVICE << info->stepping);
|
||||
ioaddr->status_addr = cmd + (ATA_REG_STATUS << info->stepping);
|
||||
ioaddr->command_addr = cmd + (ATA_REG_CMD << info->stepping);
|
||||
|
||||
ioaddr->ctl_addr = base + info->ctrloffset;
|
||||
ioaddr->altstatus_addr = ioaddr->ctl_addr;
|
||||
}
|
||||
|
||||
static int __init
|
||||
pata_icside_register_v5(struct ata_probe_ent *ae, struct expansion_card *ec)
|
||||
{
|
||||
struct pata_icside_state *state = ae->private_data;
|
||||
void __iomem *base;
|
||||
|
||||
base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC),
|
||||
ecard_resource_len(ec, ECARD_RES_MEMC));
|
||||
if (!base)
|
||||
return -ENOMEM;
|
||||
|
||||
state->irq_port = base;
|
||||
|
||||
ec->irqaddr = base + ICS_ARCIN_V5_INTRSTAT;
|
||||
ec->irqmask = 1;
|
||||
ec->irq_data = state;
|
||||
ec->ops = &pata_icside_ops_arcin_v5;
|
||||
|
||||
/*
|
||||
* Be on the safe side - disable interrupts
|
||||
*/
|
||||
ec->ops->irqdisable(ec, ec->irq);
|
||||
|
||||
pata_icside_add_port(ae, base, &pata_icside_portinfo_v5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init
|
||||
pata_icside_register_v6(struct ata_probe_ent *ae, struct expansion_card *ec)
|
||||
{
|
||||
struct pata_icside_state *state = ae->private_data;
|
||||
void __iomem *ioc_base, *easi_base;
|
||||
unsigned int sel = 0;
|
||||
int ret;
|
||||
|
||||
ioc_base = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST),
|
||||
ecard_resource_len(ec, ECARD_RES_IOCFAST));
|
||||
if (!ioc_base) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
easi_base = ioc_base;
|
||||
|
||||
if (ecard_resource_flags(ec, ECARD_RES_EASI)) {
|
||||
easi_base = ioremap(ecard_resource_start(ec, ECARD_RES_EASI),
|
||||
ecard_resource_len(ec, ECARD_RES_EASI));
|
||||
if (!easi_base) {
|
||||
ret = -ENOMEM;
|
||||
goto unmap_slot;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable access to the EASI region.
|
||||
*/
|
||||
sel = 1 << 5;
|
||||
}
|
||||
|
||||
writeb(sel, ioc_base);
|
||||
|
||||
ec->irq_data = state;
|
||||
ec->ops = &pata_icside_ops_arcin_v6;
|
||||
|
||||
state->irq_port = easi_base;
|
||||
state->ioc_base = ioc_base;
|
||||
state->port[0].port_sel = sel;
|
||||
state->port[1].port_sel = sel | 1;
|
||||
|
||||
/*
|
||||
* Be on the safe side - disable interrupts
|
||||
*/
|
||||
ec->ops->irqdisable(ec, ec->irq);
|
||||
|
||||
/*
|
||||
* Find and register the interfaces.
|
||||
*/
|
||||
pata_icside_add_port(ae, easi_base, &pata_icside_portinfo_v6_1);
|
||||
pata_icside_add_port(ae, easi_base, &pata_icside_portinfo_v6_2);
|
||||
|
||||
/*
|
||||
* FIXME: work around libata's aversion to calling port_disable.
|
||||
* This permanently disables interrupts on port 0 - bad luck if
|
||||
* you have a drive on that port.
|
||||
*/
|
||||
state->port[0].disabled = 1;
|
||||
|
||||
return icside_dma_init(ae, ec);
|
||||
|
||||
unmap_slot:
|
||||
iounmap(ioc_base);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devinit
|
||||
pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id)
|
||||
{
|
||||
struct pata_icside_state *state;
|
||||
struct ata_probe_ent ae;
|
||||
void __iomem *idmem;
|
||||
int ret;
|
||||
|
||||
ret = ecard_request_resources(ec);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
state = kzalloc(sizeof(struct pata_icside_state), GFP_KERNEL);
|
||||
if (!state) {
|
||||
ret = -ENOMEM;
|
||||
goto release;
|
||||
}
|
||||
|
||||
state->type = ICS_TYPE_NOTYPE;
|
||||
state->dma = NO_DMA;
|
||||
|
||||
idmem = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST),
|
||||
ecard_resource_len(ec, ECARD_RES_IOCFAST));
|
||||
if (idmem) {
|
||||
unsigned int type;
|
||||
|
||||
type = readb(idmem + ICS_IDENT_OFFSET) & 1;
|
||||
type |= (readb(idmem + ICS_IDENT_OFFSET + 4) & 1) << 1;
|
||||
type |= (readb(idmem + ICS_IDENT_OFFSET + 8) & 1) << 2;
|
||||
type |= (readb(idmem + ICS_IDENT_OFFSET + 12) & 1) << 3;
|
||||
iounmap(idmem);
|
||||
|
||||
state->type = type;
|
||||
}
|
||||
|
||||
memset(&ae, 0, sizeof(ae));
|
||||
INIT_LIST_HEAD(&ae.node);
|
||||
ae.dev = &ec->dev;
|
||||
ae.port_ops = &pata_icside_port_ops;
|
||||
ae.sht = &pata_icside_sht;
|
||||
ae.pio_mask = 0x1f;
|
||||
ae.irq = ec->irq;
|
||||
ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
|
||||
ae._host_flags = ATA_HOST_SIMPLEX;
|
||||
ae.private_data = state;
|
||||
|
||||
switch (state->type) {
|
||||
case ICS_TYPE_A3IN:
|
||||
dev_warn(&ec->dev, "A3IN unsupported\n");
|
||||
ret = -ENODEV;
|
||||
break;
|
||||
|
||||
case ICS_TYPE_A3USER:
|
||||
dev_warn(&ec->dev, "A3USER unsupported\n");
|
||||
ret = -ENODEV;
|
||||
break;
|
||||
|
||||
case ICS_TYPE_V5:
|
||||
ret = pata_icside_register_v5(&ae, ec);
|
||||
break;
|
||||
|
||||
case ICS_TYPE_V6:
|
||||
ret = pata_icside_register_v6(&ae, ec);
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_warn(&ec->dev, "unknown interface type\n");
|
||||
ret = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
ret = ata_device_add(&ae) == 0 ? -ENODEV : 0;
|
||||
|
||||
if (ret == 0)
|
||||
goto out;
|
||||
|
||||
kfree(state);
|
||||
release:
|
||||
ecard_release_resources(ec);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void pata_icside_shutdown(struct expansion_card *ec)
|
||||
{
|
||||
struct ata_host *host = ecard_get_drvdata(ec);
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* Disable interrupts from this card. We need to do
|
||||
* this before disabling EASI since we may be accessing
|
||||
* this register via that region.
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
if (ec->ops)
|
||||
ec->ops->irqdisable(ec, ec->irq);
|
||||
local_irq_restore(flags);
|
||||
|
||||
/*
|
||||
* Reset the ROM pointer so that we can read the ROM
|
||||
* after a soft reboot. This also disables access to
|
||||
* the IDE taskfile via the EASI region.
|
||||
*/
|
||||
if (host) {
|
||||
struct pata_icside_state *state = host->private_data;
|
||||
if (state->ioc_base)
|
||||
writeb(0, state->ioc_base);
|
||||
}
|
||||
}
|
||||
|
||||
static void __devexit pata_icside_remove(struct expansion_card *ec)
|
||||
{
|
||||
struct ata_host *host = ecard_get_drvdata(ec);
|
||||
struct pata_icside_state *state = host->private_data;
|
||||
|
||||
ata_host_detach(host);
|
||||
|
||||
pata_icside_shutdown(ec);
|
||||
|
||||
/*
|
||||
* don't NULL out the drvdata - devres/libata wants it
|
||||
* to free the ata_host structure.
|
||||
*/
|
||||
ec->ops = NULL;
|
||||
ec->irq_data = NULL;
|
||||
|
||||
if (state->dma != NO_DMA)
|
||||
free_dma(state->dma);
|
||||
if (state->ioc_base)
|
||||
iounmap(state->ioc_base);
|
||||
if (state->ioc_base != state->irq_port)
|
||||
iounmap(state->irq_port);
|
||||
|
||||
kfree(state);
|
||||
ecard_release_resources(ec);
|
||||
}
|
||||
|
||||
static const struct ecard_id pata_icside_ids[] = {
|
||||
{ MANU_ICS, PROD_ICS_IDE },
|
||||
{ MANU_ICS2, PROD_ICS2_IDE },
|
||||
{ 0xffff, 0xffff }
|
||||
};
|
||||
|
||||
static struct ecard_driver pata_icside_driver = {
|
||||
.probe = pata_icside_probe,
|
||||
.remove = __devexit_p(pata_icside_remove),
|
||||
.shutdown = pata_icside_shutdown,
|
||||
.id_table = pata_icside_ids,
|
||||
.drv = {
|
||||
.name = DRV_NAME,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init pata_icside_init(void)
|
||||
{
|
||||
return ecard_register_driver(&pata_icside_driver);
|
||||
}
|
||||
|
||||
static void __exit pata_icside_exit(void)
|
||||
{
|
||||
ecard_remove_driver(&pata_icside_driver);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("ICS PATA driver");
|
||||
|
||||
module_init(pata_icside_init);
|
||||
module_exit(pata_icside_exit);
|
@ -839,9 +839,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
|
||||
{
|
||||
struct pxa_i2c *i2c = &i2c_pxa;
|
||||
struct resource *res;
|
||||
#ifdef CONFIG_I2C_PXA_SLAVE
|
||||
struct i2c_pxa_platform_data *plat = dev->dev.platform_data;
|
||||
#endif
|
||||
int ret;
|
||||
int irq;
|
||||
|
||||
@ -889,14 +887,14 @@ static int i2c_pxa_probe(struct platform_device *dev)
|
||||
pxa_gpio_mode(GPIO117_I2CSCL_MD);
|
||||
pxa_gpio_mode(GPIO118_I2CSDA_MD);
|
||||
#endif
|
||||
pxa_set_cken(CKEN14_I2C, 1);
|
||||
pxa_set_cken(CKEN_I2C, 1);
|
||||
break;
|
||||
#ifdef CONFIG_PXA27x
|
||||
case 1:
|
||||
local_irq_disable();
|
||||
PCFR |= PCFR_PI2CEN;
|
||||
local_irq_enable();
|
||||
pxa_set_cken(CKEN15_PWRI2C, 1);
|
||||
pxa_set_cken(CKEN_PWRI2C, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -911,6 +909,10 @@ static int i2c_pxa_probe(struct platform_device *dev)
|
||||
i2c->adap.algo_data = i2c;
|
||||
i2c->adap.dev.parent = &dev->dev;
|
||||
|
||||
if (plat) {
|
||||
i2c->adap.class = plat->class;
|
||||
}
|
||||
|
||||
ret = i2c_add_adapter(&i2c->adap);
|
||||
if (ret < 0) {
|
||||
printk(KERN_INFO "I2C: Failed to add bus\n");
|
||||
@ -933,11 +935,11 @@ eadapt:
|
||||
ereqirq:
|
||||
switch (dev->id) {
|
||||
case 0:
|
||||
pxa_set_cken(CKEN14_I2C, 0);
|
||||
pxa_set_cken(CKEN_I2C, 0);
|
||||
break;
|
||||
#ifdef CONFIG_PXA27x
|
||||
case 1:
|
||||
pxa_set_cken(CKEN15_PWRI2C, 0);
|
||||
pxa_set_cken(CKEN_PWRI2C, 0);
|
||||
local_irq_disable();
|
||||
PCFR &= ~PCFR_PI2CEN;
|
||||
local_irq_enable();
|
||||
@ -960,11 +962,11 @@ static int i2c_pxa_remove(struct platform_device *dev)
|
||||
free_irq(i2c->irq, i2c);
|
||||
switch (dev->id) {
|
||||
case 0:
|
||||
pxa_set_cken(CKEN14_I2C, 0);
|
||||
pxa_set_cken(CKEN_I2C, 0);
|
||||
break;
|
||||
#ifdef CONFIG_PXA27x
|
||||
case 1:
|
||||
pxa_set_cken(CKEN15_PWRI2C, 0);
|
||||
pxa_set_cken(CKEN_PWRI2C, 0);
|
||||
local_irq_disable();
|
||||
PCFR &= ~PCFR_PI2CEN;
|
||||
local_irq_enable();
|
||||
|
@ -369,14 +369,14 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||
if (CLOCKRATE / clk > ios->clock)
|
||||
clk <<= 1;
|
||||
host->clkrt = fls(clk) - 1;
|
||||
pxa_set_cken(CKEN12_MMC, 1);
|
||||
pxa_set_cken(CKEN_MMC, 1);
|
||||
|
||||
/*
|
||||
* we write clkrt on the next command
|
||||
*/
|
||||
} else {
|
||||
pxamci_stop_clock(host);
|
||||
pxa_set_cken(CKEN12_MMC, 0);
|
||||
pxa_set_cken(CKEN_MMC, 0);
|
||||
}
|
||||
|
||||
if (host->power_mode != ios->power_mode) {
|
||||
|
@ -134,7 +134,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
|
||||
DCSR(si->rxdma) &= ~DCSR_RUN;
|
||||
/* disable FICP */
|
||||
ICCR0 = 0;
|
||||
pxa_set_cken(CKEN13_FICP, 0);
|
||||
pxa_set_cken(CKEN_FICP, 0);
|
||||
|
||||
/* set board transceiver to SIR mode */
|
||||
si->pdata->transceiver_mode(si->dev, IR_SIRMODE);
|
||||
@ -144,7 +144,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
|
||||
pxa_gpio_mode(GPIO47_STTXD_MD);
|
||||
|
||||
/* enable the STUART clock */
|
||||
pxa_set_cken(CKEN5_STUART, 1);
|
||||
pxa_set_cken(CKEN_STUART, 1);
|
||||
}
|
||||
|
||||
/* disable STUART first */
|
||||
@ -169,7 +169,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
|
||||
/* disable STUART */
|
||||
STIER = 0;
|
||||
STISR = 0;
|
||||
pxa_set_cken(CKEN5_STUART, 0);
|
||||
pxa_set_cken(CKEN_STUART, 0);
|
||||
|
||||
/* disable FICP first */
|
||||
ICCR0 = 0;
|
||||
@ -182,7 +182,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
|
||||
pxa_gpio_mode(GPIO47_ICPTXD_MD);
|
||||
|
||||
/* enable the FICP clock */
|
||||
pxa_set_cken(CKEN13_FICP, 1);
|
||||
pxa_set_cken(CKEN_FICP, 1);
|
||||
|
||||
si->speed = speed;
|
||||
pxa_irda_fir_dma_rx_start(si);
|
||||
@ -593,7 +593,7 @@ static void pxa_irda_shutdown(struct pxa_irda *si)
|
||||
/* disable STUART SIR mode */
|
||||
STISR = 0;
|
||||
/* disable the STUART clock */
|
||||
pxa_set_cken(CKEN5_STUART, 0);
|
||||
pxa_set_cken(CKEN_STUART, 0);
|
||||
|
||||
/* disable DMA */
|
||||
DCSR(si->txdma) &= ~DCSR_RUN;
|
||||
@ -601,7 +601,7 @@ static void pxa_irda_shutdown(struct pxa_irda *si)
|
||||
/* disable FICP */
|
||||
ICCR0 = 0;
|
||||
/* disable the FICP clock */
|
||||
pxa_set_cken(CKEN13_FICP, 0);
|
||||
pxa_set_cken(CKEN_FICP, 0);
|
||||
|
||||
DRCMR17 = 0;
|
||||
DRCMR18 = 0;
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include <linux/serial.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/amba/serial.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
@ -70,6 +71,7 @@
|
||||
*/
|
||||
struct uart_amba_port {
|
||||
struct uart_port port;
|
||||
struct clk *clk;
|
||||
struct amba_device *dev;
|
||||
struct amba_pl010_data *data;
|
||||
unsigned int old_status;
|
||||
@ -77,73 +79,77 @@ struct uart_amba_port {
|
||||
|
||||
static void pl010_stop_tx(struct uart_port *port)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
unsigned int cr;
|
||||
|
||||
cr = readb(port->membase + UART010_CR);
|
||||
cr = readb(uap->port.membase + UART010_CR);
|
||||
cr &= ~UART010_CR_TIE;
|
||||
writel(cr, port->membase + UART010_CR);
|
||||
writel(cr, uap->port.membase + UART010_CR);
|
||||
}
|
||||
|
||||
static void pl010_start_tx(struct uart_port *port)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
unsigned int cr;
|
||||
|
||||
cr = readb(port->membase + UART010_CR);
|
||||
cr = readb(uap->port.membase + UART010_CR);
|
||||
cr |= UART010_CR_TIE;
|
||||
writel(cr, port->membase + UART010_CR);
|
||||
writel(cr, uap->port.membase + UART010_CR);
|
||||
}
|
||||
|
||||
static void pl010_stop_rx(struct uart_port *port)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
unsigned int cr;
|
||||
|
||||
cr = readb(port->membase + UART010_CR);
|
||||
cr = readb(uap->port.membase + UART010_CR);
|
||||
cr &= ~(UART010_CR_RIE | UART010_CR_RTIE);
|
||||
writel(cr, port->membase + UART010_CR);
|
||||
writel(cr, uap->port.membase + UART010_CR);
|
||||
}
|
||||
|
||||
static void pl010_enable_ms(struct uart_port *port)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
unsigned int cr;
|
||||
|
||||
cr = readb(port->membase + UART010_CR);
|
||||
cr = readb(uap->port.membase + UART010_CR);
|
||||
cr |= UART010_CR_MSIE;
|
||||
writel(cr, port->membase + UART010_CR);
|
||||
writel(cr, uap->port.membase + UART010_CR);
|
||||
}
|
||||
|
||||
static void pl010_rx_chars(struct uart_port *port)
|
||||
static void pl010_rx_chars(struct uart_amba_port *uap)
|
||||
{
|
||||
struct tty_struct *tty = port->info->tty;
|
||||
struct tty_struct *tty = uap->port.info->tty;
|
||||
unsigned int status, ch, flag, rsr, max_count = 256;
|
||||
|
||||
status = readb(port->membase + UART01x_FR);
|
||||
status = readb(uap->port.membase + UART01x_FR);
|
||||
while (UART_RX_DATA(status) && max_count--) {
|
||||
ch = readb(port->membase + UART01x_DR);
|
||||
ch = readb(uap->port.membase + UART01x_DR);
|
||||
flag = TTY_NORMAL;
|
||||
|
||||
port->icount.rx++;
|
||||
uap->port.icount.rx++;
|
||||
|
||||
/*
|
||||
* Note that the error handling code is
|
||||
* out of the main execution path
|
||||
*/
|
||||
rsr = readb(port->membase + UART01x_RSR) | UART_DUMMY_RSR_RX;
|
||||
rsr = readb(uap->port.membase + UART01x_RSR) | UART_DUMMY_RSR_RX;
|
||||
if (unlikely(rsr & UART01x_RSR_ANY)) {
|
||||
writel(0, port->membase + UART01x_ECR);
|
||||
writel(0, uap->port.membase + UART01x_ECR);
|
||||
|
||||
if (rsr & UART01x_RSR_BE) {
|
||||
rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE);
|
||||
port->icount.brk++;
|
||||
if (uart_handle_break(port))
|
||||
uap->port.icount.brk++;
|
||||
if (uart_handle_break(&uap->port))
|
||||
goto ignore_char;
|
||||
} else if (rsr & UART01x_RSR_PE)
|
||||
port->icount.parity++;
|
||||
uap->port.icount.parity++;
|
||||
else if (rsr & UART01x_RSR_FE)
|
||||
port->icount.frame++;
|
||||
uap->port.icount.frame++;
|
||||
if (rsr & UART01x_RSR_OE)
|
||||
port->icount.overrun++;
|
||||
uap->port.icount.overrun++;
|
||||
|
||||
rsr &= port->read_status_mask;
|
||||
rsr &= uap->port.read_status_mask;
|
||||
|
||||
if (rsr & UART01x_RSR_BE)
|
||||
flag = TTY_BREAK;
|
||||
@ -153,53 +159,52 @@ static void pl010_rx_chars(struct uart_port *port)
|
||||
flag = TTY_FRAME;
|
||||
}
|
||||
|
||||
if (uart_handle_sysrq_char(port, ch))
|
||||
if (uart_handle_sysrq_char(&uap->port, ch))
|
||||
goto ignore_char;
|
||||
|
||||
uart_insert_char(port, rsr, UART01x_RSR_OE, ch, flag);
|
||||
uart_insert_char(&uap->port, rsr, UART01x_RSR_OE, ch, flag);
|
||||
|
||||
ignore_char:
|
||||
status = readb(port->membase + UART01x_FR);
|
||||
status = readb(uap->port.membase + UART01x_FR);
|
||||
}
|
||||
tty_flip_buffer_push(tty);
|
||||
return;
|
||||
}
|
||||
|
||||
static void pl010_tx_chars(struct uart_port *port)
|
||||
static void pl010_tx_chars(struct uart_amba_port *uap)
|
||||
{
|
||||
struct circ_buf *xmit = &port->info->xmit;
|
||||
struct circ_buf *xmit = &uap->port.info->xmit;
|
||||
int count;
|
||||
|
||||
if (port->x_char) {
|
||||
writel(port->x_char, port->membase + UART01x_DR);
|
||||
port->icount.tx++;
|
||||
port->x_char = 0;
|
||||
if (uap->port.x_char) {
|
||||
writel(uap->port.x_char, uap->port.membase + UART01x_DR);
|
||||
uap->port.icount.tx++;
|
||||
uap->port.x_char = 0;
|
||||
return;
|
||||
}
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
|
||||
pl010_stop_tx(port);
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
|
||||
pl010_stop_tx(&uap->port);
|
||||
return;
|
||||
}
|
||||
|
||||
count = port->fifosize >> 1;
|
||||
count = uap->port.fifosize >> 1;
|
||||
do {
|
||||
writel(xmit->buf[xmit->tail], port->membase + UART01x_DR);
|
||||
writel(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
port->icount.tx++;
|
||||
uap->port.icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
} while (--count > 0);
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
uart_write_wakeup(&uap->port);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
pl010_stop_tx(port);
|
||||
pl010_stop_tx(&uap->port);
|
||||
}
|
||||
|
||||
static void pl010_modem_status(struct uart_port *port)
|
||||
static void pl010_modem_status(struct uart_amba_port *uap)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
unsigned int status, delta;
|
||||
|
||||
writel(0, uap->port.membase + UART010_ICR);
|
||||
@ -226,47 +231,50 @@ static void pl010_modem_status(struct uart_port *port)
|
||||
|
||||
static irqreturn_t pl010_int(int irq, void *dev_id)
|
||||
{
|
||||
struct uart_port *port = dev_id;
|
||||
struct uart_amba_port *uap = dev_id;
|
||||
unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
|
||||
int handled = 0;
|
||||
|
||||
spin_lock(&port->lock);
|
||||
spin_lock(&uap->port.lock);
|
||||
|
||||
status = readb(port->membase + UART010_IIR);
|
||||
status = readb(uap->port.membase + UART010_IIR);
|
||||
if (status) {
|
||||
do {
|
||||
if (status & (UART010_IIR_RTIS | UART010_IIR_RIS))
|
||||
pl010_rx_chars(port);
|
||||
pl010_rx_chars(uap);
|
||||
if (status & UART010_IIR_MIS)
|
||||
pl010_modem_status(port);
|
||||
pl010_modem_status(uap);
|
||||
if (status & UART010_IIR_TIS)
|
||||
pl010_tx_chars(port);
|
||||
pl010_tx_chars(uap);
|
||||
|
||||
if (pass_counter-- == 0)
|
||||
break;
|
||||
|
||||
status = readb(port->membase + UART010_IIR);
|
||||
status = readb(uap->port.membase + UART010_IIR);
|
||||
} while (status & (UART010_IIR_RTIS | UART010_IIR_RIS |
|
||||
UART010_IIR_TIS));
|
||||
handled = 1;
|
||||
}
|
||||
|
||||
spin_unlock(&port->lock);
|
||||
spin_unlock(&uap->port.lock);
|
||||
|
||||
return IRQ_RETVAL(handled);
|
||||
}
|
||||
|
||||
static unsigned int pl010_tx_empty(struct uart_port *port)
|
||||
{
|
||||
return readb(port->membase + UART01x_FR) & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT;
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
unsigned int status = readb(uap->port.membase + UART01x_FR);
|
||||
return status & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT;
|
||||
}
|
||||
|
||||
static unsigned int pl010_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
unsigned int result = 0;
|
||||
unsigned int status;
|
||||
|
||||
status = readb(port->membase + UART01x_FR);
|
||||
status = readb(uap->port.membase + UART01x_FR);
|
||||
if (status & UART01x_FR_DCD)
|
||||
result |= TIOCM_CAR;
|
||||
if (status & UART01x_FR_DSR)
|
||||
@ -287,17 +295,18 @@ static void pl010_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
|
||||
static void pl010_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
unsigned long flags;
|
||||
unsigned int lcr_h;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
lcr_h = readb(port->membase + UART010_LCRH);
|
||||
spin_lock_irqsave(&uap->port.lock, flags);
|
||||
lcr_h = readb(uap->port.membase + UART010_LCRH);
|
||||
if (break_state == -1)
|
||||
lcr_h |= UART01x_LCRH_BRK;
|
||||
else
|
||||
lcr_h &= ~UART01x_LCRH_BRK;
|
||||
writel(lcr_h, port->membase + UART010_LCRH);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
writel(lcr_h, uap->port.membase + UART010_LCRH);
|
||||
spin_unlock_irqrestore(&uap->port.lock, flags);
|
||||
}
|
||||
|
||||
static int pl010_startup(struct uart_port *port)
|
||||
@ -305,49 +314,71 @@ static int pl010_startup(struct uart_port *port)
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
int retval;
|
||||
|
||||
/*
|
||||
* Try to enable the clock producer.
|
||||
*/
|
||||
retval = clk_enable(uap->clk);
|
||||
if (retval)
|
||||
goto out;
|
||||
|
||||
uap->port.uartclk = clk_get_rate(uap->clk);
|
||||
|
||||
/*
|
||||
* Allocate the IRQ
|
||||
*/
|
||||
retval = request_irq(port->irq, pl010_int, 0, "uart-pl010", port);
|
||||
retval = request_irq(uap->port.irq, pl010_int, 0, "uart-pl010", uap);
|
||||
if (retval)
|
||||
return retval;
|
||||
goto clk_dis;
|
||||
|
||||
/*
|
||||
* initialise the old status of the modem signals
|
||||
*/
|
||||
uap->old_status = readb(port->membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
|
||||
uap->old_status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
|
||||
|
||||
/*
|
||||
* Finally, enable interrupts
|
||||
*/
|
||||
writel(UART01x_CR_UARTEN | UART010_CR_RIE | UART010_CR_RTIE,
|
||||
port->membase + UART010_CR);
|
||||
uap->port.membase + UART010_CR);
|
||||
|
||||
return 0;
|
||||
|
||||
clk_dis:
|
||||
clk_disable(uap->clk);
|
||||
out:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void pl010_shutdown(struct uart_port *port)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
|
||||
/*
|
||||
* Free the interrupt
|
||||
*/
|
||||
free_irq(port->irq, port);
|
||||
free_irq(uap->port.irq, uap);
|
||||
|
||||
/*
|
||||
* disable all interrupts, disable the port
|
||||
*/
|
||||
writel(0, port->membase + UART010_CR);
|
||||
writel(0, uap->port.membase + UART010_CR);
|
||||
|
||||
/* disable break condition and fifos */
|
||||
writel(readb(port->membase + UART010_LCRH) &
|
||||
writel(readb(uap->port.membase + UART010_LCRH) &
|
||||
~(UART01x_LCRH_BRK | UART01x_LCRH_FEN),
|
||||
port->membase + UART010_LCRH);
|
||||
uap->port.membase + UART010_LCRH);
|
||||
|
||||
/*
|
||||
* Shut down the clock producer
|
||||
*/
|
||||
clk_disable(uap->clk);
|
||||
}
|
||||
|
||||
static void
|
||||
pl010_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
struct ktermios *old)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
unsigned int lcr_h, old_cr;
|
||||
unsigned long flags;
|
||||
unsigned int baud, quot;
|
||||
@ -355,7 +386,7 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
/*
|
||||
* Ask the core to calculate the divisor for us.
|
||||
*/
|
||||
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
|
||||
baud = uart_get_baud_rate(port, termios, old, 0, uap->port.uartclk/16);
|
||||
quot = uart_get_divisor(port, baud);
|
||||
|
||||
switch (termios->c_cflag & CSIZE) {
|
||||
@ -379,66 +410,66 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
if (!(termios->c_cflag & PARODD))
|
||||
lcr_h |= UART01x_LCRH_EPS;
|
||||
}
|
||||
if (port->fifosize > 1)
|
||||
if (uap->port.fifosize > 1)
|
||||
lcr_h |= UART01x_LCRH_FEN;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
spin_lock_irqsave(&uap->port.lock, flags);
|
||||
|
||||
/*
|
||||
* Update the per-port timeout.
|
||||
*/
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
|
||||
port->read_status_mask = UART01x_RSR_OE;
|
||||
uap->port.read_status_mask = UART01x_RSR_OE;
|
||||
if (termios->c_iflag & INPCK)
|
||||
port->read_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
|
||||
uap->port.read_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
|
||||
if (termios->c_iflag & (BRKINT | PARMRK))
|
||||
port->read_status_mask |= UART01x_RSR_BE;
|
||||
uap->port.read_status_mask |= UART01x_RSR_BE;
|
||||
|
||||
/*
|
||||
* Characters to ignore
|
||||
*/
|
||||
port->ignore_status_mask = 0;
|
||||
uap->port.ignore_status_mask = 0;
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
port->ignore_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
|
||||
uap->port.ignore_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
|
||||
if (termios->c_iflag & IGNBRK) {
|
||||
port->ignore_status_mask |= UART01x_RSR_BE;
|
||||
uap->port.ignore_status_mask |= UART01x_RSR_BE;
|
||||
/*
|
||||
* If we're ignoring parity and break indicators,
|
||||
* ignore overruns too (for real raw support).
|
||||
*/
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
port->ignore_status_mask |= UART01x_RSR_OE;
|
||||
uap->port.ignore_status_mask |= UART01x_RSR_OE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ignore all characters if CREAD is not set.
|
||||
*/
|
||||
if ((termios->c_cflag & CREAD) == 0)
|
||||
port->ignore_status_mask |= UART_DUMMY_RSR_RX;
|
||||
uap->port.ignore_status_mask |= UART_DUMMY_RSR_RX;
|
||||
|
||||
/* first, disable everything */
|
||||
old_cr = readb(port->membase + UART010_CR) & ~UART010_CR_MSIE;
|
||||
old_cr = readb(uap->port.membase + UART010_CR) & ~UART010_CR_MSIE;
|
||||
|
||||
if (UART_ENABLE_MS(port, termios->c_cflag))
|
||||
old_cr |= UART010_CR_MSIE;
|
||||
|
||||
writel(0, port->membase + UART010_CR);
|
||||
writel(0, uap->port.membase + UART010_CR);
|
||||
|
||||
/* Set baud rate */
|
||||
quot -= 1;
|
||||
writel((quot & 0xf00) >> 8, port->membase + UART010_LCRM);
|
||||
writel(quot & 0xff, port->membase + UART010_LCRL);
|
||||
writel((quot & 0xf00) >> 8, uap->port.membase + UART010_LCRM);
|
||||
writel(quot & 0xff, uap->port.membase + UART010_LCRL);
|
||||
|
||||
/*
|
||||
* ----------v----------v----------v----------v-----
|
||||
* NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
|
||||
* ----------^----------^----------^----------^-----
|
||||
*/
|
||||
writel(lcr_h, port->membase + UART010_LCRH);
|
||||
writel(old_cr, port->membase + UART010_CR);
|
||||
writel(lcr_h, uap->port.membase + UART010_LCRH);
|
||||
writel(old_cr, uap->port.membase + UART010_CR);
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
spin_unlock_irqrestore(&uap->port.lock, flags);
|
||||
}
|
||||
|
||||
static const char *pl010_type(struct uart_port *port)
|
||||
@ -514,47 +545,52 @@ static struct uart_amba_port *amba_ports[UART_NR];
|
||||
|
||||
static void pl010_console_putchar(struct uart_port *port, int ch)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
unsigned int status;
|
||||
|
||||
do {
|
||||
status = readb(port->membase + UART01x_FR);
|
||||
status = readb(uap->port.membase + UART01x_FR);
|
||||
barrier();
|
||||
} while (!UART_TX_READY(status));
|
||||
writel(ch, port->membase + UART01x_DR);
|
||||
writel(ch, uap->port.membase + UART01x_DR);
|
||||
}
|
||||
|
||||
static void
|
||||
pl010_console_write(struct console *co, const char *s, unsigned int count)
|
||||
{
|
||||
struct uart_port *port = &amba_ports[co->index]->port;
|
||||
struct uart_amba_port *uap = amba_ports[co->index];
|
||||
unsigned int status, old_cr;
|
||||
|
||||
clk_enable(uap->clk);
|
||||
|
||||
/*
|
||||
* First save the CR then disable the interrupts
|
||||
*/
|
||||
old_cr = readb(port->membase + UART010_CR);
|
||||
writel(UART01x_CR_UARTEN, port->membase + UART010_CR);
|
||||
old_cr = readb(uap->port.membase + UART010_CR);
|
||||
writel(UART01x_CR_UARTEN, uap->port.membase + UART010_CR);
|
||||
|
||||
uart_console_write(port, s, count, pl010_console_putchar);
|
||||
uart_console_write(&uap->port, s, count, pl010_console_putchar);
|
||||
|
||||
/*
|
||||
* Finally, wait for transmitter to become empty
|
||||
* and restore the TCR
|
||||
*/
|
||||
do {
|
||||
status = readb(port->membase + UART01x_FR);
|
||||
status = readb(uap->port.membase + UART01x_FR);
|
||||
barrier();
|
||||
} while (status & UART01x_FR_BUSY);
|
||||
writel(old_cr, port->membase + UART010_CR);
|
||||
writel(old_cr, uap->port.membase + UART010_CR);
|
||||
|
||||
clk_disable(uap->clk);
|
||||
}
|
||||
|
||||
static void __init
|
||||
pl010_console_get_options(struct uart_port *port, int *baud,
|
||||
pl010_console_get_options(struct uart_amba_port *uap, int *baud,
|
||||
int *parity, int *bits)
|
||||
{
|
||||
if (readb(port->membase + UART010_CR) & UART01x_CR_UARTEN) {
|
||||
if (readb(uap->port.membase + UART010_CR) & UART01x_CR_UARTEN) {
|
||||
unsigned int lcr_h, quot;
|
||||
lcr_h = readb(port->membase + UART010_LCRH);
|
||||
lcr_h = readb(uap->port.membase + UART010_LCRH);
|
||||
|
||||
*parity = 'n';
|
||||
if (lcr_h & UART01x_LCRH_PEN) {
|
||||
@ -569,14 +605,15 @@ pl010_console_get_options(struct uart_port *port, int *baud,
|
||||
else
|
||||
*bits = 8;
|
||||
|
||||
quot = readb(port->membase + UART010_LCRL) | readb(port->membase + UART010_LCRM) << 8;
|
||||
*baud = port->uartclk / (16 * (quot + 1));
|
||||
quot = readb(uap->port.membase + UART010_LCRL) |
|
||||
readb(uap->port.membase + UART010_LCRM) << 8;
|
||||
*baud = uap->port.uartclk / (16 * (quot + 1));
|
||||
}
|
||||
}
|
||||
|
||||
static int __init pl010_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct uart_port *port;
|
||||
struct uart_amba_port *uap;
|
||||
int baud = 38400;
|
||||
int bits = 8;
|
||||
int parity = 'n';
|
||||
@ -589,16 +626,18 @@ static int __init pl010_console_setup(struct console *co, char *options)
|
||||
*/
|
||||
if (co->index >= UART_NR)
|
||||
co->index = 0;
|
||||
if (!amba_ports[co->index])
|
||||
uap = amba_ports[co->index];
|
||||
if (!uap)
|
||||
return -ENODEV;
|
||||
port = &amba_ports[co->index]->port;
|
||||
|
||||
uap->port.uartclk = clk_get_rate(uap->clk);
|
||||
|
||||
if (options)
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
else
|
||||
pl010_console_get_options(port, &baud, &parity, &bits);
|
||||
pl010_console_get_options(uap, &baud, &parity, &bits);
|
||||
|
||||
return uart_set_options(port, co, baud, parity, bits, flow);
|
||||
return uart_set_options(&uap->port, co, baud, parity, bits, flow);
|
||||
}
|
||||
|
||||
static struct uart_driver amba_reg;
|
||||
@ -629,7 +668,7 @@ static struct uart_driver amba_reg = {
|
||||
|
||||
static int pl010_probe(struct amba_device *dev, void *id)
|
||||
{
|
||||
struct uart_amba_port *port;
|
||||
struct uart_amba_port *uap;
|
||||
void __iomem *base;
|
||||
int i, ret;
|
||||
|
||||
@ -642,8 +681,8 @@ static int pl010_probe(struct amba_device *dev, void *id)
|
||||
goto out;
|
||||
}
|
||||
|
||||
port = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL);
|
||||
if (!port) {
|
||||
uap = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL);
|
||||
if (!uap) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
@ -654,51 +693,57 @@ static int pl010_probe(struct amba_device *dev, void *id)
|
||||
goto free;
|
||||
}
|
||||
|
||||
port->port.dev = &dev->dev;
|
||||
port->port.mapbase = dev->res.start;
|
||||
port->port.membase = base;
|
||||
port->port.iotype = UPIO_MEM;
|
||||
port->port.irq = dev->irq[0];
|
||||
port->port.uartclk = 14745600;
|
||||
port->port.fifosize = 16;
|
||||
port->port.ops = &amba_pl010_pops;
|
||||
port->port.flags = UPF_BOOT_AUTOCONF;
|
||||
port->port.line = i;
|
||||
port->dev = dev;
|
||||
port->data = dev->dev.platform_data;
|
||||
uap->clk = clk_get(&dev->dev, "UARTCLK");
|
||||
if (IS_ERR(uap->clk)) {
|
||||
ret = PTR_ERR(uap->clk);
|
||||
goto unmap;
|
||||
}
|
||||
|
||||
amba_ports[i] = port;
|
||||
uap->port.dev = &dev->dev;
|
||||
uap->port.mapbase = dev->res.start;
|
||||
uap->port.membase = base;
|
||||
uap->port.iotype = UPIO_MEM;
|
||||
uap->port.irq = dev->irq[0];
|
||||
uap->port.fifosize = 16;
|
||||
uap->port.ops = &amba_pl010_pops;
|
||||
uap->port.flags = UPF_BOOT_AUTOCONF;
|
||||
uap->port.line = i;
|
||||
uap->dev = dev;
|
||||
uap->data = dev->dev.platform_data;
|
||||
|
||||
amba_set_drvdata(dev, port);
|
||||
ret = uart_add_one_port(&amba_reg, &port->port);
|
||||
amba_ports[i] = uap;
|
||||
|
||||
amba_set_drvdata(dev, uap);
|
||||
ret = uart_add_one_port(&amba_reg, &uap->port);
|
||||
if (ret) {
|
||||
amba_set_drvdata(dev, NULL);
|
||||
amba_ports[i] = NULL;
|
||||
clk_put(uap->clk);
|
||||
unmap:
|
||||
iounmap(base);
|
||||
free:
|
||||
kfree(port);
|
||||
kfree(uap);
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pl010_remove(struct amba_device *dev)
|
||||
{
|
||||
struct uart_amba_port *port = amba_get_drvdata(dev);
|
||||
struct uart_amba_port *uap = amba_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
amba_set_drvdata(dev, NULL);
|
||||
|
||||
uart_remove_one_port(&amba_reg, &port->port);
|
||||
uart_remove_one_port(&amba_reg, &uap->port);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
|
||||
if (amba_ports[i] == port)
|
||||
if (amba_ports[i] == uap)
|
||||
amba_ports[i] = NULL;
|
||||
|
||||
iounmap(port->port.membase);
|
||||
kfree(port);
|
||||
|
||||
iounmap(uap->port.membase);
|
||||
clk_put(uap->clk);
|
||||
kfree(uap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -484,11 +484,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios * termios,
|
||||
unsigned long flags;
|
||||
unsigned int mode, imr, quot, baud;
|
||||
|
||||
/* Get current mode register */
|
||||
mode = UART_GET_MR(port) & ~(ATMEL_US_USCLKS | ATMEL_US_CHRL | ATMEL_US_NBSTOP | ATMEL_US_PAR);
|
||||
|
||||
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
|
||||
quot = uart_get_divisor(port, baud);
|
||||
|
||||
/* Get current mode register */
|
||||
mode = UART_GET_MR(port) & ~(ATMEL_US_CHRL | ATMEL_US_NBSTOP | ATMEL_US_PAR);
|
||||
if (quot > 65535) { /* BRGR is 16-bit, so switch to slower clock */
|
||||
quot /= 8;
|
||||
mode |= ATMEL_US_USCLKS_MCK_DIV8;
|
||||
}
|
||||
|
||||
/* byte size */
|
||||
switch (termios->c_cflag & CSIZE) {
|
||||
|
@ -46,6 +46,9 @@
|
||||
#define ATMEL_US_USMODE_ISO7816_T1 6
|
||||
#define ATMEL_US_USMODE_IRDA 8
|
||||
#define ATMEL_US_USCLKS (3 << 4) /* Clock Selection */
|
||||
#define ATMEL_US_USCLKS_MCK (0 << 4)
|
||||
#define ATMEL_US_USCLKS_MCK_DIV8 (1 << 4)
|
||||
#define ATMEL_US_USCLKS_SCK (3 << 4)
|
||||
#define ATMEL_US_CHRL (3 << 6) /* Character Length */
|
||||
#define ATMEL_US_CHRL_5 (0 << 6)
|
||||
#define ATMEL_US_CHRL_6 (1 << 6)
|
||||
|
@ -46,6 +46,122 @@
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/arch/imx-uart.h>
|
||||
|
||||
/* Register definitions */
|
||||
#define URXD0 0x0 /* Receiver Register */
|
||||
#define URTX0 0x40 /* Transmitter Register */
|
||||
#define UCR1 0x80 /* Control Register 1 */
|
||||
#define UCR2 0x84 /* Control Register 2 */
|
||||
#define UCR3 0x88 /* Control Register 3 */
|
||||
#define UCR4 0x8c /* Control Register 4 */
|
||||
#define UFCR 0x90 /* FIFO Control Register */
|
||||
#define USR1 0x94 /* Status Register 1 */
|
||||
#define USR2 0x98 /* Status Register 2 */
|
||||
#define UESC 0x9c /* Escape Character Register */
|
||||
#define UTIM 0xa0 /* Escape Timer Register */
|
||||
#define UBIR 0xa4 /* BRM Incremental Register */
|
||||
#define UBMR 0xa8 /* BRM Modulator Register */
|
||||
#define UBRC 0xac /* Baud Rate Count Register */
|
||||
#define BIPR1 0xb0 /* Incremental Preset Register 1 */
|
||||
#define BIPR2 0xb4 /* Incremental Preset Register 2 */
|
||||
#define BIPR3 0xb8 /* Incremental Preset Register 3 */
|
||||
#define BIPR4 0xbc /* Incremental Preset Register 4 */
|
||||
#define BMPR1 0xc0 /* BRM Modulator Register 1 */
|
||||
#define BMPR2 0xc4 /* BRM Modulator Register 2 */
|
||||
#define BMPR3 0xc8 /* BRM Modulator Register 3 */
|
||||
#define BMPR4 0xcc /* BRM Modulator Register 4 */
|
||||
#define UTS 0xd0 /* UART Test Register */
|
||||
|
||||
/* UART Control Register Bit Fields.*/
|
||||
#define URXD_CHARRDY (1<<15)
|
||||
#define URXD_ERR (1<<14)
|
||||
#define URXD_OVRRUN (1<<13)
|
||||
#define URXD_FRMERR (1<<12)
|
||||
#define URXD_BRK (1<<11)
|
||||
#define URXD_PRERR (1<<10)
|
||||
#define UCR1_ADEN (1<<15) /* Auto dectect interrupt */
|
||||
#define UCR1_ADBR (1<<14) /* Auto detect baud rate */
|
||||
#define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */
|
||||
#define UCR1_IDEN (1<<12) /* Idle condition interrupt */
|
||||
#define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */
|
||||
#define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */
|
||||
#define UCR1_IREN (1<<7) /* Infrared interface enable */
|
||||
#define UCR1_TXMPTYEN (1<<6) /* Transimitter empty interrupt enable */
|
||||
#define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */
|
||||
#define UCR1_SNDBRK (1<<4) /* Send break */
|
||||
#define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */
|
||||
#define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */
|
||||
#define UCR1_DOZE (1<<1) /* Doze */
|
||||
#define UCR1_UARTEN (1<<0) /* UART enabled */
|
||||
#define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */
|
||||
#define UCR2_IRTS (1<<14) /* Ignore RTS pin */
|
||||
#define UCR2_CTSC (1<<13) /* CTS pin control */
|
||||
#define UCR2_CTS (1<<12) /* Clear to send */
|
||||
#define UCR2_ESCEN (1<<11) /* Escape enable */
|
||||
#define UCR2_PREN (1<<8) /* Parity enable */
|
||||
#define UCR2_PROE (1<<7) /* Parity odd/even */
|
||||
#define UCR2_STPB (1<<6) /* Stop */
|
||||
#define UCR2_WS (1<<5) /* Word size */
|
||||
#define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */
|
||||
#define UCR2_TXEN (1<<2) /* Transmitter enabled */
|
||||
#define UCR2_RXEN (1<<1) /* Receiver enabled */
|
||||
#define UCR2_SRST (1<<0) /* SW reset */
|
||||
#define UCR3_DTREN (1<<13) /* DTR interrupt enable */
|
||||
#define UCR3_PARERREN (1<<12) /* Parity enable */
|
||||
#define UCR3_FRAERREN (1<<11) /* Frame error interrupt enable */
|
||||
#define UCR3_DSR (1<<10) /* Data set ready */
|
||||
#define UCR3_DCD (1<<9) /* Data carrier detect */
|
||||
#define UCR3_RI (1<<8) /* Ring indicator */
|
||||
#define UCR3_TIMEOUTEN (1<<7) /* Timeout interrupt enable */
|
||||
#define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */
|
||||
#define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */
|
||||
#define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */
|
||||
#define UCR3_REF25 (1<<3) /* Ref freq 25 MHz */
|
||||
#define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz */
|
||||
#define UCR3_INVT (1<<1) /* Inverted Infrared transmission */
|
||||
#define UCR3_BPEN (1<<0) /* Preset registers enable */
|
||||
#define UCR4_CTSTL_32 (32<<10) /* CTS trigger level (32 chars) */
|
||||
#define UCR4_INVR (1<<9) /* Inverted infrared reception */
|
||||
#define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */
|
||||
#define UCR4_WKEN (1<<7) /* Wake interrupt enable */
|
||||
#define UCR4_REF16 (1<<6) /* Ref freq 16 MHz */
|
||||
#define UCR4_IRSC (1<<5) /* IR special case */
|
||||
#define UCR4_TCEN (1<<3) /* Transmit complete interrupt enable */
|
||||
#define UCR4_BKEN (1<<2) /* Break condition interrupt enable */
|
||||
#define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */
|
||||
#define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */
|
||||
#define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */
|
||||
#define UFCR_RFDIV (7<<7) /* Reference freq divider mask */
|
||||
#define UFCR_TXTL_SHF 10 /* Transmitter trigger level shift */
|
||||
#define USR1_PARITYERR (1<<15) /* Parity error interrupt flag */
|
||||
#define USR1_RTSS (1<<14) /* RTS pin status */
|
||||
#define USR1_TRDY (1<<13) /* Transmitter ready interrupt/dma flag */
|
||||
#define USR1_RTSD (1<<12) /* RTS delta */
|
||||
#define USR1_ESCF (1<<11) /* Escape seq interrupt flag */
|
||||
#define USR1_FRAMERR (1<<10) /* Frame error interrupt flag */
|
||||
#define USR1_RRDY (1<<9) /* Receiver ready interrupt/dma flag */
|
||||
#define USR1_TIMEOUT (1<<7) /* Receive timeout interrupt status */
|
||||
#define USR1_RXDS (1<<6) /* Receiver idle interrupt flag */
|
||||
#define USR1_AIRINT (1<<5) /* Async IR wake interrupt flag */
|
||||
#define USR1_AWAKE (1<<4) /* Aysnc wake interrupt flag */
|
||||
#define USR2_ADET (1<<15) /* Auto baud rate detect complete */
|
||||
#define USR2_TXFE (1<<14) /* Transmit buffer FIFO empty */
|
||||
#define USR2_DTRF (1<<13) /* DTR edge interrupt flag */
|
||||
#define USR2_IDLE (1<<12) /* Idle condition */
|
||||
#define USR2_IRINT (1<<8) /* Serial infrared interrupt flag */
|
||||
#define USR2_WAKE (1<<7) /* Wake */
|
||||
#define USR2_RTSF (1<<4) /* RTS edge interrupt flag */
|
||||
#define USR2_TXDC (1<<3) /* Transmitter complete */
|
||||
#define USR2_BRCD (1<<2) /* Break condition */
|
||||
#define USR2_ORE (1<<1) /* Overrun error */
|
||||
#define USR2_RDR (1<<0) /* Recv data ready */
|
||||
#define UTS_FRCPERR (1<<13) /* Force parity error */
|
||||
#define UTS_LOOP (1<<12) /* Loop tx and rx */
|
||||
#define UTS_TXEMPTY (1<<6) /* TxFIFO empty */
|
||||
#define UTS_RXEMPTY (1<<5) /* RxFIFO empty */
|
||||
#define UTS_TXFULL (1<<4) /* TxFIFO full */
|
||||
#define UTS_RXFULL (1<<3) /* RxFIFO full */
|
||||
#define UTS_SOFTRST (1<<0) /* Software reset */
|
||||
|
||||
/* We've been assigned a range on the "Low-density serial ports" major */
|
||||
#define SERIAL_IMX_MAJOR 204
|
||||
#define MINOR_START 41
|
||||
@ -128,7 +244,10 @@ static void imx_timeout(unsigned long data)
|
||||
static void imx_stop_tx(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
UCR1((u32)sport->port.membase) &= ~UCR1_TXMPTYEN;
|
||||
unsigned long temp;
|
||||
|
||||
temp = readl(sport->port.membase + UCR1);
|
||||
writel(temp & ~UCR1_TXMPTYEN, sport->port.membase + UCR1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -137,7 +256,10 @@ static void imx_stop_tx(struct uart_port *port)
|
||||
static void imx_stop_rx(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
UCR2((u32)sport->port.membase) &= ~UCR2_RXEN;
|
||||
unsigned long temp;
|
||||
|
||||
temp = readl(sport->port.membase + UCR2);
|
||||
writel(temp &~ UCR2_RXEN, sport->port.membase + UCR2);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -154,10 +276,10 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
|
||||
{
|
||||
struct circ_buf *xmit = &sport->port.info->xmit;
|
||||
|
||||
while (!(UTS((u32)sport->port.membase) & UTS_TXFULL)) {
|
||||
while (!(readl(sport->port.membase + UTS) & UTS_TXFULL)) {
|
||||
/* send xmit->buf[xmit->tail]
|
||||
* out the port here */
|
||||
URTX0((u32)sport->port.membase) = xmit->buf[xmit->tail];
|
||||
writel(xmit->buf[xmit->tail], sport->port.membase + URTX0);
|
||||
xmit->tail = (xmit->tail + 1) &
|
||||
(UART_XMIT_SIZE - 1);
|
||||
sport->port.icount.tx++;
|
||||
@ -175,21 +297,24 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
|
||||
static void imx_start_tx(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
unsigned long temp;
|
||||
|
||||
UCR1((u32)sport->port.membase) |= UCR1_TXMPTYEN;
|
||||
temp = readl(sport->port.membase + UCR1);
|
||||
writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1);
|
||||
|
||||
if (readl(sport->port.membase + UTS) & UTS_TXEMPTY)
|
||||
imx_transmit_buffer(sport);
|
||||
}
|
||||
|
||||
static irqreturn_t imx_rtsint(int irq, void *dev_id)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)dev_id;
|
||||
unsigned int val = USR1((u32)sport->port.membase)&USR1_RTSS;
|
||||
unsigned int val = readl(sport->port.membase + USR1) & USR1_RTSS;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&sport->port.lock, flags);
|
||||
|
||||
USR1((u32)sport->port.membase) = USR1_RTSD;
|
||||
writel(USR1_RTSD, sport->port.membase + USR1);
|
||||
uart_handle_cts_change(&sport->port, !!val);
|
||||
wake_up_interruptible(&sport->port.info->delta_msr_wait);
|
||||
|
||||
@ -207,7 +332,7 @@ static irqreturn_t imx_txint(int irq, void *dev_id)
|
||||
if (sport->port.x_char)
|
||||
{
|
||||
/* Send next char */
|
||||
URTX0((u32)sport->port.membase) = sport->port.x_char;
|
||||
writel(sport->port.x_char, sport->port.membase + URTX0);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -231,17 +356,18 @@ static irqreturn_t imx_rxint(int irq, void *dev_id)
|
||||
struct imx_port *sport = dev_id;
|
||||
unsigned int rx,flg,ignored = 0;
|
||||
struct tty_struct *tty = sport->port.info->tty;
|
||||
unsigned long flags;
|
||||
unsigned long flags, temp;
|
||||
|
||||
rx = URXD0((u32)sport->port.membase);
|
||||
rx = readl(sport->port.membase + URXD0);
|
||||
spin_lock_irqsave(&sport->port.lock,flags);
|
||||
|
||||
do {
|
||||
flg = TTY_NORMAL;
|
||||
sport->port.icount.rx++;
|
||||
|
||||
if( USR2((u32)sport->port.membase) & USR2_BRCD ) {
|
||||
USR2((u32)sport->port.membase) |= USR2_BRCD;
|
||||
temp = readl(sport->port.membase + USR2);
|
||||
if( temp & USR2_BRCD ) {
|
||||
writel(temp | USR2_BRCD, sport->port.membase + USR2);
|
||||
if(uart_handle_break(&sport->port))
|
||||
goto ignore_char;
|
||||
}
|
||||
@ -257,7 +383,7 @@ static irqreturn_t imx_rxint(int irq, void *dev_id)
|
||||
tty_insert_flip_char(tty, rx, flg);
|
||||
|
||||
ignore_char:
|
||||
rx = URXD0((u32)sport->port.membase);
|
||||
rx = readl(sport->port.membase + URXD0);
|
||||
} while(rx & URXD_CHARRDY);
|
||||
|
||||
out:
|
||||
@ -301,7 +427,7 @@ static unsigned int imx_tx_empty(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
|
||||
return USR2((u32)sport->port.membase) & USR2_TXDC ? TIOCSER_TEMT : 0;
|
||||
return (readl(sport->port.membase + USR2) & USR2_TXDC) ? TIOCSER_TEMT : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -312,10 +438,10 @@ static unsigned int imx_get_mctrl(struct uart_port *port)
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
unsigned int tmp = TIOCM_DSR | TIOCM_CAR;
|
||||
|
||||
if (USR1((u32)sport->port.membase) & USR1_RTSS)
|
||||
if (readl(sport->port.membase + USR1) & USR1_RTSS)
|
||||
tmp |= TIOCM_CTS;
|
||||
|
||||
if (UCR2((u32)sport->port.membase) & UCR2_CTS)
|
||||
if (readl(sport->port.membase + UCR2) & UCR2_CTS)
|
||||
tmp |= TIOCM_RTS;
|
||||
|
||||
return tmp;
|
||||
@ -324,11 +450,14 @@ static unsigned int imx_get_mctrl(struct uart_port *port)
|
||||
static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
unsigned long temp;
|
||||
|
||||
temp = readl(sport->port.membase + UCR2) & ~UCR2_CTS;
|
||||
|
||||
if (mctrl & TIOCM_RTS)
|
||||
UCR2((u32)sport->port.membase) |= UCR2_CTS;
|
||||
else
|
||||
UCR2((u32)sport->port.membase) &= ~UCR2_CTS;
|
||||
temp |= UCR2_CTS;
|
||||
|
||||
writel(temp, sport->port.membase + UCR2);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -337,14 +466,16 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
static void imx_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
unsigned long flags;
|
||||
unsigned long flags, temp;
|
||||
|
||||
spin_lock_irqsave(&sport->port.lock, flags);
|
||||
|
||||
temp = readl(sport->port.membase + UCR1) & ~UCR1_SNDBRK;
|
||||
|
||||
if ( break_state != 0 )
|
||||
UCR1((u32)sport->port.membase) |= UCR1_SNDBRK;
|
||||
else
|
||||
UCR1((u32)sport->port.membase) &= ~UCR1_SNDBRK;
|
||||
temp |= UCR1_SNDBRK;
|
||||
|
||||
writel(temp, sport->port.membase + UCR1);
|
||||
|
||||
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||
}
|
||||
@ -373,7 +504,7 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
|
||||
|
||||
val |= UFCR_RFDIV & (ufcr_rfdiv << 7);
|
||||
|
||||
UFCR((u32)sport->port.membase) = val;
|
||||
writel(val, sport->port.membase + UFCR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -382,14 +513,15 @@ static int imx_startup(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
int retval;
|
||||
unsigned long flags;
|
||||
unsigned long flags, temp;
|
||||
|
||||
imx_setup_ufcr(sport, 0);
|
||||
|
||||
/* disable the DREN bit (Data Ready interrupt enable) before
|
||||
* requesting IRQs
|
||||
*/
|
||||
UCR4((u32)sport->port.membase) &= ~UCR4_DREN;
|
||||
temp = readl(sport->port.membase + UCR4);
|
||||
writel(temp & ~UCR4_DREN, sport->port.membase + UCR4);
|
||||
|
||||
/*
|
||||
* Allocate the IRQ
|
||||
@ -411,12 +543,16 @@ static int imx_startup(struct uart_port *port)
|
||||
/*
|
||||
* Finally, clear and enable interrupts
|
||||
*/
|
||||
writel(USR1_RTSD, sport->port.membase + USR1);
|
||||
|
||||
USR1((u32)sport->port.membase) = USR1_RTSD;
|
||||
UCR1((u32)sport->port.membase) |=
|
||||
(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
|
||||
temp = readl(sport->port.membase + UCR1);
|
||||
temp |= (UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
|
||||
writel(temp, sport->port.membase + UCR1);
|
||||
|
||||
temp = readl(sport->port.membase + UCR2);
|
||||
temp |= (UCR2_RXEN | UCR2_TXEN);
|
||||
writel(temp, sport->port.membase + UCR2);
|
||||
|
||||
UCR2((u32)sport->port.membase) |= (UCR2_RXEN | UCR2_TXEN);
|
||||
/*
|
||||
* Enable modem status interrupts
|
||||
*/
|
||||
@ -437,6 +573,7 @@ error_out1:
|
||||
static void imx_shutdown(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
unsigned long temp;
|
||||
|
||||
/*
|
||||
* Stop our timer.
|
||||
@ -454,8 +591,9 @@ static void imx_shutdown(struct uart_port *port)
|
||||
* Disable all interrupts, port and break condition.
|
||||
*/
|
||||
|
||||
UCR1((u32)sport->port.membase) &=
|
||||
~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
|
||||
temp = readl(sport->port.membase + UCR1);
|
||||
temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
|
||||
writel(temp, sport->port.membase + UCR1);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -548,18 +686,18 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
/*
|
||||
* disable interrupts and drain transmitter
|
||||
*/
|
||||
old_ucr1 = UCR1((u32)sport->port.membase);
|
||||
UCR1((u32)sport->port.membase) &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN);
|
||||
old_ucr1 = readl(sport->port.membase + UCR1);
|
||||
writel(old_ucr1 & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN),
|
||||
sport->port.membase + UCR1);
|
||||
|
||||
while ( !(USR2((u32)sport->port.membase) & USR2_TXDC))
|
||||
while ( !(readl(sport->port.membase + USR2) & USR2_TXDC))
|
||||
barrier();
|
||||
|
||||
/* then, disable everything */
|
||||
old_txrxen = UCR2((u32)sport->port.membase) & ( UCR2_TXEN | UCR2_RXEN );
|
||||
UCR2((u32)sport->port.membase) &= ~( UCR2_TXEN | UCR2_RXEN);
|
||||
|
||||
/* set the parity, stop bits and data size */
|
||||
UCR2((u32)sport->port.membase) = ucr2;
|
||||
old_txrxen = readl(sport->port.membase + UCR2);
|
||||
writel(old_txrxen & ~( UCR2_TXEN | UCR2_RXEN),
|
||||
sport->port.membase + UCR2);
|
||||
old_txrxen &= (UCR2_TXEN | UCR2_RXEN);
|
||||
|
||||
/* set the baud rate. We assume uartclk = 16 MHz
|
||||
*
|
||||
@ -567,11 +705,13 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
* --------- = --------
|
||||
* uartclk UBMR - 1
|
||||
*/
|
||||
UBIR((u32)sport->port.membase) = (baud / 100) - 1;
|
||||
UBMR((u32)sport->port.membase) = 10000 - 1;
|
||||
writel((baud / 100) - 1, sport->port.membase + UBIR);
|
||||
writel(10000 - 1, sport->port.membase + UBMR);
|
||||
|
||||
UCR1((u32)sport->port.membase) = old_ucr1;
|
||||
UCR2((u32)sport->port.membase) |= old_txrxen;
|
||||
writel(old_ucr1, sport->port.membase + UCR1);
|
||||
|
||||
/* set the parity, stop bits and data size */
|
||||
writel(ucr2 | old_txrxen, sport->port.membase + UCR2);
|
||||
|
||||
if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
|
||||
imx_enable_ms(&sport->port);
|
||||
@ -730,9 +870,11 @@ static void __init imx_init_ports(void)
|
||||
static void imx_console_putchar(struct uart_port *port, int ch)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
while ((UTS((u32)sport->port.membase) & UTS_TXFULL))
|
||||
|
||||
while (readl(sport->port.membase + UTS) & UTS_TXFULL)
|
||||
barrier();
|
||||
URTX0((u32)sport->port.membase) = ch;
|
||||
|
||||
writel(ch, sport->port.membase + URTX0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -747,13 +889,14 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
|
||||
/*
|
||||
* First, save UCR1/2 and then disable interrupts
|
||||
*/
|
||||
old_ucr1 = UCR1((u32)sport->port.membase);
|
||||
old_ucr2 = UCR2((u32)sport->port.membase);
|
||||
old_ucr1 = readl(sport->port.membase + UCR1);
|
||||
old_ucr2 = readl(sport->port.membase + UCR2);
|
||||
|
||||
UCR1((u32)sport->port.membase) =
|
||||
(old_ucr1 | UCR1_UARTCLKEN | UCR1_UARTEN)
|
||||
& ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN);
|
||||
UCR2((u32)sport->port.membase) = old_ucr2 | UCR2_TXEN;
|
||||
writel((old_ucr1 | UCR1_UARTCLKEN | UCR1_UARTEN) &
|
||||
~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN),
|
||||
sport->port.membase + UCR1);
|
||||
|
||||
writel(old_ucr2 | UCR2_TXEN, sport->port.membase + UCR2);
|
||||
|
||||
uart_console_write(&sport->port, s, count, imx_console_putchar);
|
||||
|
||||
@ -761,10 +904,10 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
|
||||
* Finally, wait for transmitter to become empty
|
||||
* and restore UCR1/2
|
||||
*/
|
||||
while (!(USR2((u32)sport->port.membase) & USR2_TXDC));
|
||||
while (!(readl(sport->port.membase + USR2) & USR2_TXDC));
|
||||
|
||||
UCR1((u32)sport->port.membase) = old_ucr1;
|
||||
UCR2((u32)sport->port.membase) = old_ucr2;
|
||||
writel(old_ucr1, sport->port.membase + UCR1);
|
||||
writel(old_ucr2, sport->port.membase + UCR2);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -776,13 +919,13 @@ imx_console_get_options(struct imx_port *sport, int *baud,
|
||||
int *parity, int *bits)
|
||||
{
|
||||
|
||||
if ( UCR1((u32)sport->port.membase) | UCR1_UARTEN ) {
|
||||
if ( readl(sport->port.membase + UCR1) | UCR1_UARTEN ) {
|
||||
/* ok, the port was enabled */
|
||||
unsigned int ucr2, ubir,ubmr, uartclk;
|
||||
unsigned int baud_raw;
|
||||
unsigned int ucfr_rfdiv;
|
||||
|
||||
ucr2 = UCR2((u32)sport->port.membase);
|
||||
ucr2 = readl(sport->port.membase + UCR2);
|
||||
|
||||
*parity = 'n';
|
||||
if (ucr2 & UCR2_PREN) {
|
||||
@ -797,11 +940,10 @@ imx_console_get_options(struct imx_port *sport, int *baud,
|
||||
else
|
||||
*bits = 7;
|
||||
|
||||
ubir = UBIR((u32)sport->port.membase) & 0xffff;
|
||||
ubmr = UBMR((u32)sport->port.membase) & 0xffff;
|
||||
ubir = readl(sport->port.membase + UBIR) & 0xffff;
|
||||
ubmr = readl(sport->port.membase + UBMR) & 0xffff;
|
||||
|
||||
|
||||
ucfr_rfdiv = (UFCR((u32)sport->port.membase) & UFCR_RFDIV) >> 7;
|
||||
ucfr_rfdiv = (readl(sport->port.membase + UFCR) & UFCR_RFDIV) >> 7;
|
||||
if (ucfr_rfdiv == 6)
|
||||
ucfr_rfdiv = 7;
|
||||
else
|
||||
|
@ -717,7 +717,7 @@ struct uart_ops serial_pxa_pops = {
|
||||
static struct uart_pxa_port serial_pxa_ports[] = {
|
||||
{ /* FFUART */
|
||||
.name = "FFUART",
|
||||
.cken = CKEN6_FFUART,
|
||||
.cken = CKEN_FFUART,
|
||||
.port = {
|
||||
.type = PORT_PXA,
|
||||
.iotype = UPIO_MEM,
|
||||
@ -731,7 +731,7 @@ static struct uart_pxa_port serial_pxa_ports[] = {
|
||||
},
|
||||
}, { /* BTUART */
|
||||
.name = "BTUART",
|
||||
.cken = CKEN7_BTUART,
|
||||
.cken = CKEN_BTUART,
|
||||
.port = {
|
||||
.type = PORT_PXA,
|
||||
.iotype = UPIO_MEM,
|
||||
@ -745,7 +745,7 @@ static struct uart_pxa_port serial_pxa_ports[] = {
|
||||
},
|
||||
}, { /* STUART */
|
||||
.name = "STUART",
|
||||
.cken = CKEN5_STUART,
|
||||
.cken = CKEN_STUART,
|
||||
.port = {
|
||||
.type = PORT_PXA,
|
||||
.iotype = UPIO_MEM,
|
||||
@ -759,7 +759,7 @@ static struct uart_pxa_port serial_pxa_ports[] = {
|
||||
},
|
||||
}, { /* HWUART */
|
||||
.name = "HWUART",
|
||||
.cken = CKEN4_HWUART,
|
||||
.cken = CKEN_HWUART,
|
||||
.port = {
|
||||
.type = PORT_PXA,
|
||||
.iotype = UPIO_MEM,
|
||||
|
@ -1497,7 +1497,7 @@ static void udc_disable(struct pxa2xx_udc *dev)
|
||||
|
||||
#ifdef CONFIG_ARCH_PXA
|
||||
/* Disable clock for USB device */
|
||||
pxa_set_cken(CKEN11_USB, 0);
|
||||
pxa_set_cken(CKEN_USB, 0);
|
||||
#endif
|
||||
|
||||
ep0_idle (dev);
|
||||
@ -1543,7 +1543,7 @@ static void udc_enable (struct pxa2xx_udc *dev)
|
||||
|
||||
#ifdef CONFIG_ARCH_PXA
|
||||
/* Enable clock for USB device */
|
||||
pxa_set_cken(CKEN11_USB, 1);
|
||||
pxa_set_cken(CKEN_USB, 1);
|
||||
udelay(5);
|
||||
#endif
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user