mirror of https://gitee.com/openkylin/linux.git
Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm: (100 commits) ARM: Eliminate decompressor -Dstatic= PIC hack ARM: 5958/1: ARM: U300: fix inverted clk round rate ARM: 5956/1: misplaced parentheses ARM: 5955/1: ep93xx: move timer defines into core.c and document ARM: 5954/1: ep93xx: move gpio interrupt support to gpio.c ARM: 5953/1: ep93xx: fix broken build of clock.c ARM: 5952/1: ARM: MM: Add ARM_L1_CACHE_SHIFT_6 for handle inside each ARCH Kconfig ARM: 5949/1: NUC900 add gpio virtual memory map ARM: 5948/1: Enable timer0 to time4 clock support for nuc910 ARM: 5940/2: ARM: MMCI: remove custom DBG macro and printk ARM: make_coherent(): fix problems with highpte, part 2 MM: Pass a PTE pointer to update_mmu_cache() rather than the PTE itself ARM: 5945/1: ep93xx: include correct irq.h in core.c ARM: 5933/1: amba-pl011: support hardware flow control ARM: 5930/1: Add PKMAP area description to memory.txt. ARM: 5929/1: Add checks to detect overlap of memory regions. ARM: 5928/1: Change type of VMALLOC_END to unsigned long. ARM: 5927/1: Make delimiters of DMA area globally visibly. ARM: 5926/1: Add "Virtual kernel memory..." printout. ARM: 5920/1: OMAP4: Enable L2 Cache ... Fix up trivial conflict in arch/arm/mach-mx25/clock.c
This commit is contained in:
commit
ac0f6f927d
|
@ -59,7 +59,11 @@ PAGE_OFFSET high_memory-1 Kernel direct-mapped RAM region.
|
|||
This maps the platforms RAM, and typically
|
||||
maps all platform RAM in a 1:1 relationship.
|
||||
|
||||
TASK_SIZE PAGE_OFFSET-1 Kernel module space
|
||||
PKMAP_BASE PAGE_OFFSET-1 Permanent kernel mappings
|
||||
One way of mapping HIGHMEM pages into kernel
|
||||
space.
|
||||
|
||||
MODULES_VADDR MODULES_END-1 Kernel module space
|
||||
Kernel modules inserted via insmod are
|
||||
placed here using dynamic mappings.
|
||||
|
||||
|
|
|
@ -88,12 +88,12 @@ changes occur:
|
|||
This is used primarily during fault processing.
|
||||
|
||||
5) void update_mmu_cache(struct vm_area_struct *vma,
|
||||
unsigned long address, pte_t pte)
|
||||
unsigned long address, pte_t *ptep)
|
||||
|
||||
At the end of every page fault, this routine is invoked to
|
||||
tell the architecture specific code that a translation
|
||||
described by "pte" now exists at virtual address "address"
|
||||
for address space "vma->vm_mm", in the software page tables.
|
||||
now exists at virtual address "address" for address space
|
||||
"vma->vm_mm", in the software page tables.
|
||||
|
||||
A port may use this information in any way it so chooses.
|
||||
For example, it could use this event to pre-load TLB
|
||||
|
|
|
@ -329,7 +329,7 @@ extern pgd_t swapper_pg_dir[1024];
|
|||
* tables contain all the necessary information.
|
||||
*/
|
||||
extern inline void update_mmu_cache(struct vm_area_struct * vma,
|
||||
unsigned long address, pte_t pte)
|
||||
unsigned long address, pte_t *ptep)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ config ARM
|
|||
select HAVE_IDE
|
||||
select RTC_LIB
|
||||
select SYS_SUPPORTS_APM_EMULATION
|
||||
select GENERIC_ATOMIC64 if (!CPU_32v6K)
|
||||
select HAVE_OPROFILE
|
||||
select HAVE_ARCH_KGDB
|
||||
select HAVE_KPROBES if (!XIP_KERNEL)
|
||||
|
@ -20,6 +21,8 @@ config ARM
|
|||
select HAVE_GENERIC_DMA_COHERENT
|
||||
select HAVE_KERNEL_GZIP
|
||||
select HAVE_KERNEL_LZO
|
||||
select HAVE_PERF_EVENTS
|
||||
select PERF_USE_VMALLOC
|
||||
help
|
||||
The ARM series is a line of low-power-consumption RISC chip designs
|
||||
licensed by ARM Ltd and targeted at embedded applications and
|
||||
|
@ -52,6 +55,9 @@ config HAVE_TCM
|
|||
bool
|
||||
select GENERIC_ALLOCATOR
|
||||
|
||||
config HAVE_PROC_CPU
|
||||
bool
|
||||
|
||||
config NO_IOPORT
|
||||
bool
|
||||
|
||||
|
@ -161,6 +167,11 @@ config ARCH_MTD_XIP
|
|||
config GENERIC_HARDIRQS_NO__DO_IRQ
|
||||
def_bool y
|
||||
|
||||
config ARM_L1_CACHE_SHIFT_6
|
||||
bool
|
||||
help
|
||||
Setting ARM L1 cache line size to 64 Bytes.
|
||||
|
||||
if OPROFILE
|
||||
|
||||
config OPROFILE_ARMV6
|
||||
|
@ -550,10 +561,20 @@ config ARCH_W90X900
|
|||
<http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/
|
||||
ConsumerElectronicsIC/ARMMicrocontroller/ARMMicrocontroller>
|
||||
|
||||
config ARCH_NUC93X
|
||||
bool "Nuvoton NUC93X CPU"
|
||||
select CPU_ARM926T
|
||||
select HAVE_CLK
|
||||
select COMMON_CLKDEV
|
||||
help
|
||||
Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a
|
||||
low-power and high performance MPEG-4/JPEG multimedia controller chip.
|
||||
|
||||
config ARCH_PNX4008
|
||||
bool "Philips Nexperia PNX4008 Mobile"
|
||||
select CPU_ARM926T
|
||||
select HAVE_CLK
|
||||
select COMMON_CLKDEV
|
||||
help
|
||||
This enables support for Philips PNX4008 mobile platform.
|
||||
|
||||
|
@ -638,6 +659,7 @@ config ARCH_S5PC1XX
|
|||
select GENERIC_GPIO
|
||||
select HAVE_CLK
|
||||
select CPU_V7
|
||||
select ARM_L1_CACHE_SHIFT_6
|
||||
help
|
||||
Samsung S5PC1XX series based systems
|
||||
|
||||
|
@ -785,6 +807,8 @@ source "arch/arm/plat-nomadik/Kconfig"
|
|||
|
||||
source "arch/arm/mach-ns9xxx/Kconfig"
|
||||
|
||||
source "arch/arm/mach-nuc93x/Kconfig"
|
||||
|
||||
source "arch/arm/plat-omap/Kconfig"
|
||||
|
||||
source "arch/arm/mach-omap1/Kconfig"
|
||||
|
@ -867,6 +891,11 @@ config XSCALE_PMU
|
|||
depends on CPU_XSCALE && !XSCALE_PMU_TIMER
|
||||
default y
|
||||
|
||||
config CPU_HAS_PMU
|
||||
depends on CPU_V6 || CPU_V7 || XSCALE_PMU
|
||||
default y
|
||||
bool
|
||||
|
||||
if !MMU
|
||||
source "arch/arm/Kconfig-nommu"
|
||||
endif
|
||||
|
@ -921,6 +950,19 @@ config ARM_ERRATA_460075
|
|||
ACTLR register. Note that setting specific bits in the ACTLR register
|
||||
may not be available in non-secure mode.
|
||||
|
||||
config PL310_ERRATA_588369
|
||||
bool "Clean & Invalidate maintenance operations do not invalidate clean lines"
|
||||
depends on CACHE_L2X0 && ARCH_OMAP4
|
||||
help
|
||||
The PL310 L2 cache controller implements three types of Clean &
|
||||
Invalidate maintenance operations: by Physical Address
|
||||
(offset 0x7F0), by Index/Way (0x7F8) and by Way (0x7FC).
|
||||
They are architecturally defined to behave as the execution of a
|
||||
clean operation followed immediately by an invalidate operation,
|
||||
both performing to the same memory location. This functionality
|
||||
is not correctly implemented in PL310 as clean lines are not
|
||||
invalidated as a result of these operations. Note that this errata
|
||||
uses Texas Instrument's secure monitor api.
|
||||
endmenu
|
||||
|
||||
source "arch/arm/common/Kconfig"
|
||||
|
@ -1171,6 +1213,14 @@ config HIGHPTE
|
|||
depends on HIGHMEM
|
||||
depends on !OUTER_CACHE
|
||||
|
||||
config HW_PERF_EVENTS
|
||||
bool "Enable hardware performance counter support for perf events"
|
||||
depends on PERF_EVENTS && CPU_HAS_PMU && (CPU_V6 || CPU_V7)
|
||||
default y
|
||||
help
|
||||
Enable hardware performance counter support for perf events. If
|
||||
disabled, perf events will use software events only.
|
||||
|
||||
source "mm/Kconfig"
|
||||
|
||||
config LEDS
|
||||
|
@ -1230,6 +1280,7 @@ config ALIGNMENT_TRAP
|
|||
bool
|
||||
depends on CPU_CP15_MMU
|
||||
default y if !ARCH_EBSA110
|
||||
select HAVE_PROC_CPU if PROC_FS
|
||||
help
|
||||
ARM processors cannot fetch/store information which is not
|
||||
naturally aligned on the bus, i.e., a 4 byte fetch must start at an
|
||||
|
|
|
@ -171,6 +171,7 @@ machine-$(CONFIG_ARCH_U300) := u300
|
|||
machine-$(CONFIG_ARCH_U8500) := ux500
|
||||
machine-$(CONFIG_ARCH_VERSATILE) := versatile
|
||||
machine-$(CONFIG_ARCH_W90X900) := w90x900
|
||||
machine-$(CONFIG_ARCH_NUC93X) := nuc93x
|
||||
machine-$(CONFIG_FOOTBRIDGE) := footbridge
|
||||
|
||||
# Platform directory name. This list is sorted alphanumerically
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#
|
||||
|
||||
HEAD = head.o
|
||||
OBJS = misc.o
|
||||
OBJS = misc.o decompress.o
|
||||
FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c
|
||||
|
||||
#
|
||||
|
@ -106,10 +106,6 @@ lib1funcs = $(obj)/lib1funcs.o
|
|||
$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE
|
||||
$(call cmd,shipped)
|
||||
|
||||
# Don't allow any static data in misc.o, which
|
||||
# would otherwise mess up our GOT table
|
||||
CFLAGS_misc.o := -Dstatic=
|
||||
|
||||
$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
|
||||
$(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE
|
||||
$(call if_changed,ld)
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
#define _LINUX_STRING_H_
|
||||
|
||||
#include <linux/compiler.h> /* for inline */
|
||||
#include <linux/types.h> /* for size_t */
|
||||
#include <linux/stddef.h> /* for NULL */
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/string.h>
|
||||
|
||||
extern unsigned long free_mem_ptr;
|
||||
extern unsigned long free_mem_end_ptr;
|
||||
extern void error(char *);
|
||||
|
||||
#define STATIC static
|
||||
|
||||
#define ARCH_HAS_DECOMP_WDOG
|
||||
|
||||
/* Diagnostic functions */
|
||||
#ifdef DEBUG
|
||||
# define Assert(cond,msg) {if(!(cond)) error(msg);}
|
||||
# define Trace(x) fprintf x
|
||||
# define Tracev(x) {if (verbose) fprintf x ;}
|
||||
# define Tracevv(x) {if (verbose>1) fprintf x ;}
|
||||
# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
|
||||
# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
|
||||
#else
|
||||
# define Assert(cond,msg)
|
||||
# define Trace(x)
|
||||
# define Tracev(x)
|
||||
# define Tracevv(x)
|
||||
# define Tracec(c,x)
|
||||
# define Tracecv(c,x)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KERNEL_GZIP
|
||||
#include "../../../../lib/decompress_inflate.c"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KERNEL_LZO
|
||||
#include "../../../../lib/decompress_unlzo.c"
|
||||
#endif
|
||||
|
||||
void do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x))
|
||||
{
|
||||
decompress(input, len, NULL, NULL, output, NULL, error);
|
||||
}
|
|
@ -22,13 +22,13 @@
|
|||
#if defined(CONFIG_DEBUG_ICEDCC)
|
||||
|
||||
#ifdef CONFIG_CPU_V6
|
||||
.macro loadsp, rb
|
||||
.macro loadsp, rb, tmp
|
||||
.endm
|
||||
.macro writeb, ch, rb
|
||||
mcr p14, 0, \ch, c0, c5, 0
|
||||
.endm
|
||||
#elif defined(CONFIG_CPU_V7)
|
||||
.macro loadsp, rb
|
||||
.macro loadsp, rb, tmp
|
||||
.endm
|
||||
.macro writeb, ch, rb
|
||||
wait: mrc p14, 0, pc, c0, c1, 0
|
||||
|
@ -36,13 +36,13 @@ wait: mrc p14, 0, pc, c0, c1, 0
|
|||
mcr p14, 0, \ch, c0, c5, 0
|
||||
.endm
|
||||
#elif defined(CONFIG_CPU_XSCALE)
|
||||
.macro loadsp, rb
|
||||
.macro loadsp, rb, tmp
|
||||
.endm
|
||||
.macro writeb, ch, rb
|
||||
mcr p14, 0, \ch, c8, c0, 0
|
||||
.endm
|
||||
#else
|
||||
.macro loadsp, rb
|
||||
.macro loadsp, rb, tmp
|
||||
.endm
|
||||
.macro writeb, ch, rb
|
||||
mcr p14, 0, \ch, c1, c0, 0
|
||||
|
@ -58,7 +58,7 @@ wait: mrc p14, 0, pc, c0, c1, 0
|
|||
.endm
|
||||
|
||||
#if defined(CONFIG_ARCH_SA1100)
|
||||
.macro loadsp, rb
|
||||
.macro loadsp, rb, tmp
|
||||
mov \rb, #0x80000000 @ physical base address
|
||||
#ifdef CONFIG_DEBUG_LL_SER3
|
||||
add \rb, \rb, #0x00050000 @ Ser3
|
||||
|
@ -67,13 +67,13 @@ wait: mrc p14, 0, pc, c0, c1, 0
|
|||
#endif
|
||||
.endm
|
||||
#elif defined(CONFIG_ARCH_S3C2410)
|
||||
.macro loadsp, rb
|
||||
.macro loadsp, rb, tmp
|
||||
mov \rb, #0x50000000
|
||||
add \rb, \rb, #0x4000 * CONFIG_S3C_LOWLEVEL_UART_PORT
|
||||
.endm
|
||||
#else
|
||||
.macro loadsp, rb
|
||||
addruart \rb
|
||||
.macro loadsp, rb, tmp
|
||||
addruart \rb, \tmp
|
||||
.endm
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1025,7 +1025,7 @@ phex: adr r3, phexbuf
|
|||
strb r2, [r3, r1]
|
||||
b 1b
|
||||
|
||||
puts: loadsp r3
|
||||
puts: loadsp r3, r1
|
||||
1: ldrb r2, [r0], #1
|
||||
teq r2, #0
|
||||
moveq pc, lr
|
||||
|
@ -1042,7 +1042,7 @@ puts: loadsp r3
|
|||
putc:
|
||||
mov r2, r0
|
||||
mov r0, #0
|
||||
loadsp r3
|
||||
loadsp r3, r1
|
||||
b 2b
|
||||
|
||||
memdump: mov r12, r0
|
||||
|
|
|
@ -23,8 +23,8 @@ unsigned int __machine_arch_type;
|
|||
#include <linux/compiler.h> /* for inline */
|
||||
#include <linux/types.h> /* for size_t */
|
||||
#include <linux/stddef.h> /* for NULL */
|
||||
#include <asm/string.h>
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/string.h>
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
|
@ -117,57 +117,7 @@ static void putstr(const char *ptr)
|
|||
|
||||
#endif
|
||||
|
||||
#define __ptr_t void *
|
||||
|
||||
#define memzero(s,n) __memzero(s,n)
|
||||
|
||||
/*
|
||||
* Optimised C version of memzero for the ARM.
|
||||
*/
|
||||
void __memzero (__ptr_t s, size_t n)
|
||||
{
|
||||
union { void *vp; unsigned long *ulp; unsigned char *ucp; } u;
|
||||
int i;
|
||||
|
||||
u.vp = s;
|
||||
|
||||
for (i = n >> 5; i > 0; i--) {
|
||||
*u.ulp++ = 0;
|
||||
*u.ulp++ = 0;
|
||||
*u.ulp++ = 0;
|
||||
*u.ulp++ = 0;
|
||||
*u.ulp++ = 0;
|
||||
*u.ulp++ = 0;
|
||||
*u.ulp++ = 0;
|
||||
*u.ulp++ = 0;
|
||||
}
|
||||
|
||||
if (n & 1 << 4) {
|
||||
*u.ulp++ = 0;
|
||||
*u.ulp++ = 0;
|
||||
*u.ulp++ = 0;
|
||||
*u.ulp++ = 0;
|
||||
}
|
||||
|
||||
if (n & 1 << 3) {
|
||||
*u.ulp++ = 0;
|
||||
*u.ulp++ = 0;
|
||||
}
|
||||
|
||||
if (n & 1 << 2)
|
||||
*u.ulp++ = 0;
|
||||
|
||||
if (n & 1 << 1) {
|
||||
*u.ucp++ = 0;
|
||||
*u.ucp++ = 0;
|
||||
}
|
||||
|
||||
if (n & 1)
|
||||
*u.ucp++ = 0;
|
||||
}
|
||||
|
||||
static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
|
||||
size_t __n)
|
||||
void *memcpy(void *__dest, __const void *__src, size_t __n)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
|
||||
|
@ -204,59 +154,20 @@ static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
|
|||
/*
|
||||
* gzip delarations
|
||||
*/
|
||||
#define STATIC static
|
||||
|
||||
/* Diagnostic functions */
|
||||
#ifdef DEBUG
|
||||
# define Assert(cond,msg) {if(!(cond)) error(msg);}
|
||||
# define Trace(x) fprintf x
|
||||
# define Tracev(x) {if (verbose) fprintf x ;}
|
||||
# define Tracevv(x) {if (verbose>1) fprintf x ;}
|
||||
# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
|
||||
# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
|
||||
#else
|
||||
# define Assert(cond,msg)
|
||||
# define Trace(x)
|
||||
# define Tracev(x)
|
||||
# define Tracevv(x)
|
||||
# define Tracec(c,x)
|
||||
# define Tracecv(c,x)
|
||||
#endif
|
||||
|
||||
static void error(char *m);
|
||||
|
||||
extern char input_data[];
|
||||
extern char input_data_end[];
|
||||
|
||||
static unsigned char *output_data;
|
||||
static unsigned long output_ptr;
|
||||
unsigned char *output_data;
|
||||
unsigned long output_ptr;
|
||||
|
||||
static void error(char *m);
|
||||
|
||||
static void putstr(const char *);
|
||||
|
||||
static unsigned long free_mem_ptr;
|
||||
static unsigned long free_mem_end_ptr;
|
||||
|
||||
#ifdef STANDALONE_DEBUG
|
||||
#define NO_INFLATE_MALLOC
|
||||
#endif
|
||||
|
||||
#define ARCH_HAS_DECOMP_WDOG
|
||||
|
||||
#ifdef CONFIG_KERNEL_GZIP
|
||||
#include "../../../../lib/decompress_inflate.c"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KERNEL_LZO
|
||||
#include "../../../../lib/decompress_unlzo.c"
|
||||
#endif
|
||||
unsigned long free_mem_ptr;
|
||||
unsigned long free_mem_end_ptr;
|
||||
|
||||
#ifndef arch_error
|
||||
#define arch_error(x)
|
||||
#endif
|
||||
|
||||
static void error(char *x)
|
||||
void error(char *x)
|
||||
{
|
||||
arch_error(x);
|
||||
|
||||
|
@ -272,6 +183,8 @@ asmlinkage void __div0(void)
|
|||
error("Attempting division by 0!");
|
||||
}
|
||||
|
||||
extern void do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x));
|
||||
|
||||
#ifndef STANDALONE_DEBUG
|
||||
|
||||
unsigned long
|
||||
|
@ -292,8 +205,8 @@ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
|
|||
output_ptr = get_unaligned_le32(tmp);
|
||||
|
||||
putstr("Uncompressing Linux...");
|
||||
decompress(input_data, input_data_end - input_data,
|
||||
NULL, NULL, output_data, NULL, error);
|
||||
do_decompress(input_data, input_data_end - input_data,
|
||||
output_data, error);
|
||||
putstr(" done, booting the kernel.\n");
|
||||
return output_ptr;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,13 @@ SECTIONS
|
|||
/DISCARD/ : {
|
||||
*(.ARM.exidx*)
|
||||
*(.ARM.extab*)
|
||||
/*
|
||||
* Discard any r/w data - this produces a link error if we have any,
|
||||
* which is required for PIC decompression. Local data generates
|
||||
* GOTOFF relocations, which prevents it being relocated independently
|
||||
* of the text/got segments.
|
||||
*/
|
||||
*(.data)
|
||||
}
|
||||
|
||||
. = TEXT_START;
|
||||
|
@ -40,7 +47,6 @@ SECTIONS
|
|||
.got : { *(.got) }
|
||||
_got_end = .;
|
||||
.got.plt : { *(.got.plt) }
|
||||
.data : { *(.data) }
|
||||
_edata = .;
|
||||
|
||||
. = BSS_START;
|
||||
|
|
|
@ -99,6 +99,16 @@ void clkdev_add(struct clk_lookup *cl)
|
|||
}
|
||||
EXPORT_SYMBOL(clkdev_add);
|
||||
|
||||
void __init clkdev_add_table(struct clk_lookup *cl, size_t num)
|
||||
{
|
||||
mutex_lock(&clocks_mutex);
|
||||
while (num--) {
|
||||
list_add_tail(&cl->node, &clocks);
|
||||
cl++;
|
||||
}
|
||||
mutex_unlock(&clocks_mutex);
|
||||
}
|
||||
|
||||
#define MAX_DEV_ID 20
|
||||
#define MAX_CON_ID 16
|
||||
|
||||
|
|
|
@ -277,7 +277,7 @@ static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size,
|
|||
* We don't need to sync the DMA buffer since
|
||||
* it was allocated via the coherent allocators.
|
||||
*/
|
||||
dma_cache_maint(ptr, size, dir);
|
||||
__dma_single_cpu_to_dev(ptr, size, dir);
|
||||
}
|
||||
|
||||
return dma_addr;
|
||||
|
@ -315,6 +315,8 @@ static inline void unmap_single(struct device *dev, dma_addr_t dma_addr,
|
|||
__cpuc_flush_dcache_area(ptr, size);
|
||||
}
|
||||
free_safe_buffer(dev->archdata.dmabounce, buf);
|
||||
} else {
|
||||
__dma_single_dev_to_cpu(dma_to_virt(dev, dma_addr), size, dir);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
* 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/init.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/io.h>
|
||||
|
@ -28,48 +29,6 @@
|
|||
#include <asm/mach/irq.h>
|
||||
#include <asm/hardware/vic.h>
|
||||
|
||||
static void vic_ack_irq(unsigned int irq)
|
||||
{
|
||||
void __iomem *base = get_irq_chip_data(irq);
|
||||
irq &= 31;
|
||||
writel(1 << irq, base + VIC_INT_ENABLE_CLEAR);
|
||||
/* moreover, clear the soft-triggered, in case it was the reason */
|
||||
writel(1 << irq, base + VIC_INT_SOFT_CLEAR);
|
||||
}
|
||||
|
||||
static void vic_mask_irq(unsigned int irq)
|
||||
{
|
||||
void __iomem *base = get_irq_chip_data(irq);
|
||||
irq &= 31;
|
||||
writel(1 << irq, base + VIC_INT_ENABLE_CLEAR);
|
||||
}
|
||||
|
||||
static void vic_unmask_irq(unsigned int irq)
|
||||
{
|
||||
void __iomem *base = get_irq_chip_data(irq);
|
||||
irq &= 31;
|
||||
writel(1 << irq, base + VIC_INT_ENABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* vic_init2 - common initialisation code
|
||||
* @base: Base of the VIC.
|
||||
*
|
||||
* Common initialisation code for registeration
|
||||
* and resume.
|
||||
*/
|
||||
static void vic_init2(void __iomem *base)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
|
||||
writel(VIC_VECT_CNTL_ENABLE | i, reg);
|
||||
}
|
||||
|
||||
writel(32, base + VIC_PL190_DEF_VECT_ADDR);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PM)
|
||||
/**
|
||||
* struct vic_device - VIC PM device
|
||||
|
@ -99,13 +58,34 @@ struct vic_device {
|
|||
/* we cannot allocate memory when VICs are initially registered */
|
||||
static struct vic_device vic_devices[CONFIG_ARM_VIC_NR];
|
||||
|
||||
static int vic_id;
|
||||
|
||||
static inline struct vic_device *to_vic(struct sys_device *sys)
|
||||
{
|
||||
return container_of(sys, struct vic_device, sysdev);
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static int vic_id;
|
||||
/**
|
||||
* vic_init2 - common initialisation code
|
||||
* @base: Base of the VIC.
|
||||
*
|
||||
* Common initialisation code for registeration
|
||||
* and resume.
|
||||
*/
|
||||
static void vic_init2(void __iomem *base)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
|
||||
writel(VIC_VECT_CNTL_ENABLE | i, reg);
|
||||
}
|
||||
|
||||
writel(32, base + VIC_PL190_DEF_VECT_ADDR);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PM)
|
||||
static int vic_class_resume(struct sys_device *dev)
|
||||
{
|
||||
struct vic_device *vic = to_vic(dev);
|
||||
|
@ -158,31 +138,6 @@ struct sysdev_class vic_class = {
|
|||
.resume = vic_class_resume,
|
||||
};
|
||||
|
||||
/**
|
||||
* vic_pm_register - Register a VIC for later power management control
|
||||
* @base: The base address of the VIC.
|
||||
* @irq: The base IRQ for the VIC.
|
||||
* @resume_sources: bitmask of interrupts allowed for resume sources.
|
||||
*
|
||||
* Register the VIC with the system device tree so that it can be notified
|
||||
* of suspend and resume requests and ensure that the correct actions are
|
||||
* taken to re-instate the settings on resume.
|
||||
*/
|
||||
static void __init vic_pm_register(void __iomem *base, unsigned int irq, u32 resume_sources)
|
||||
{
|
||||
struct vic_device *v;
|
||||
|
||||
if (vic_id >= ARRAY_SIZE(vic_devices))
|
||||
printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__);
|
||||
else {
|
||||
v = &vic_devices[vic_id];
|
||||
v->base = base;
|
||||
v->resume_sources = resume_sources;
|
||||
v->irq = irq;
|
||||
vic_id++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* vic_pm_init - initicall to register VIC pm
|
||||
*
|
||||
|
@ -219,9 +174,60 @@ static int __init vic_pm_init(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
late_initcall(vic_pm_init);
|
||||
|
||||
/**
|
||||
* vic_pm_register - Register a VIC for later power management control
|
||||
* @base: The base address of the VIC.
|
||||
* @irq: The base IRQ for the VIC.
|
||||
* @resume_sources: bitmask of interrupts allowed for resume sources.
|
||||
*
|
||||
* Register the VIC with the system device tree so that it can be notified
|
||||
* of suspend and resume requests and ensure that the correct actions are
|
||||
* taken to re-instate the settings on resume.
|
||||
*/
|
||||
static void __init vic_pm_register(void __iomem *base, unsigned int irq, u32 resume_sources)
|
||||
{
|
||||
struct vic_device *v;
|
||||
|
||||
if (vic_id >= ARRAY_SIZE(vic_devices))
|
||||
printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__);
|
||||
else {
|
||||
v = &vic_devices[vic_id];
|
||||
v->base = base;
|
||||
v->resume_sources = resume_sources;
|
||||
v->irq = irq;
|
||||
vic_id++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
static inline void vic_pm_register(void __iomem *base, unsigned int irq, u32 arg1) { }
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static void vic_ack_irq(unsigned int irq)
|
||||
{
|
||||
void __iomem *base = get_irq_chip_data(irq);
|
||||
irq &= 31;
|
||||
writel(1 << irq, base + VIC_INT_ENABLE_CLEAR);
|
||||
/* moreover, clear the soft-triggered, in case it was the reason */
|
||||
writel(1 << irq, base + VIC_INT_SOFT_CLEAR);
|
||||
}
|
||||
|
||||
static void vic_mask_irq(unsigned int irq)
|
||||
{
|
||||
void __iomem *base = get_irq_chip_data(irq);
|
||||
irq &= 31;
|
||||
writel(1 << irq, base + VIC_INT_ENABLE_CLEAR);
|
||||
}
|
||||
|
||||
static void vic_unmask_irq(unsigned int irq)
|
||||
{
|
||||
void __iomem *base = get_irq_chip_data(irq);
|
||||
irq &= 31;
|
||||
writel(1 << irq, base + VIC_INT_ENABLE);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PM)
|
||||
static struct vic_device *vic_from_irq(unsigned int irq)
|
||||
{
|
||||
struct vic_device *v = vic_devices;
|
||||
|
@ -255,10 +261,7 @@ static int vic_set_wake(unsigned int irq, unsigned int on)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
static inline void vic_pm_register(void __iomem *base, unsigned int irq, u32 arg1) { }
|
||||
|
||||
#define vic_set_wake NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
|
@ -270,80 +273,6 @@ static struct irq_chip vic_chip = {
|
|||
.set_wake = vic_set_wake,
|
||||
};
|
||||
|
||||
/* The PL190 cell from ARM has been modified by ST, so handle both here */
|
||||
static void vik_init_st(void __iomem *base, unsigned int irq_start,
|
||||
u32 vic_sources);
|
||||
|
||||
/**
|
||||
* vic_init - initialise a vectored interrupt controller
|
||||
* @base: iomem base address
|
||||
* @irq_start: starting interrupt number, must be muliple of 32
|
||||
* @vic_sources: bitmask of interrupt sources to allow
|
||||
* @resume_sources: bitmask of interrupt sources to allow for resume
|
||||
*/
|
||||
void __init vic_init(void __iomem *base, unsigned int irq_start,
|
||||
u32 vic_sources, u32 resume_sources)
|
||||
{
|
||||
unsigned int i;
|
||||
u32 cellid = 0;
|
||||
enum amba_vendor vendor;
|
||||
|
||||
/* Identify which VIC cell this one is, by reading the ID */
|
||||
for (i = 0; i < 4; i++) {
|
||||
u32 addr = ((u32)base & PAGE_MASK) + 0xfe0 + (i * 4);
|
||||
cellid |= (readl(addr) & 0xff) << (8 * i);
|
||||
}
|
||||
vendor = (cellid >> 12) & 0xff;
|
||||
printk(KERN_INFO "VIC @%p: id 0x%08x, vendor 0x%02x\n",
|
||||
base, cellid, vendor);
|
||||
|
||||
switch(vendor) {
|
||||
case AMBA_VENDOR_ST:
|
||||
vik_init_st(base, irq_start, vic_sources);
|
||||
return;
|
||||
default:
|
||||
printk(KERN_WARNING "VIC: unknown vendor, continuing anyways\n");
|
||||
/* fall through */
|
||||
case AMBA_VENDOR_ARM:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Disable all interrupts initially. */
|
||||
|
||||
writel(0, base + VIC_INT_SELECT);
|
||||
writel(0, base + VIC_INT_ENABLE);
|
||||
writel(~0, base + VIC_INT_ENABLE_CLEAR);
|
||||
writel(0, base + VIC_IRQ_STATUS);
|
||||
writel(0, base + VIC_ITCR);
|
||||
writel(~0, base + VIC_INT_SOFT_CLEAR);
|
||||
|
||||
/*
|
||||
* Make sure we clear all existing interrupts
|
||||
*/
|
||||
writel(0, base + VIC_PL190_VECT_ADDR);
|
||||
for (i = 0; i < 19; i++) {
|
||||
unsigned int value;
|
||||
|
||||
value = readl(base + VIC_PL190_VECT_ADDR);
|
||||
writel(value, base + VIC_PL190_VECT_ADDR);
|
||||
}
|
||||
|
||||
vic_init2(base);
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (vic_sources & (1 << i)) {
|
||||
unsigned int irq = irq_start + i;
|
||||
|
||||
set_irq_chip(irq, &vic_chip);
|
||||
set_irq_chip_data(irq, base);
|
||||
set_irq_handler(irq, handle_level_irq);
|
||||
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
|
||||
}
|
||||
}
|
||||
|
||||
vic_pm_register(base, irq_start, resume_sources);
|
||||
}
|
||||
|
||||
/*
|
||||
* The PL190 cell from ARM has been modified by ST to handle 64 interrupts.
|
||||
* The original cell has 32 interrupts, while the modified one has 64,
|
||||
|
@ -351,7 +280,7 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,
|
|||
* the probe function is called twice, with base set to offset 000
|
||||
* and 020 within the page. We call this "second block".
|
||||
*/
|
||||
static void __init vik_init_st(void __iomem *base, unsigned int irq_start,
|
||||
static void __init vic_init_st(void __iomem *base, unsigned int irq_start,
|
||||
u32 vic_sources)
|
||||
{
|
||||
unsigned int i;
|
||||
|
@ -400,3 +329,73 @@ static void __init vik_init_st(void __iomem *base, unsigned int irq_start,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* vic_init - initialise a vectored interrupt controller
|
||||
* @base: iomem base address
|
||||
* @irq_start: starting interrupt number, must be muliple of 32
|
||||
* @vic_sources: bitmask of interrupt sources to allow
|
||||
* @resume_sources: bitmask of interrupt sources to allow for resume
|
||||
*/
|
||||
void __init vic_init(void __iomem *base, unsigned int irq_start,
|
||||
u32 vic_sources, u32 resume_sources)
|
||||
{
|
||||
unsigned int i;
|
||||
u32 cellid = 0;
|
||||
enum amba_vendor vendor;
|
||||
|
||||
/* Identify which VIC cell this one is, by reading the ID */
|
||||
for (i = 0; i < 4; i++) {
|
||||
u32 addr = ((u32)base & PAGE_MASK) + 0xfe0 + (i * 4);
|
||||
cellid |= (readl(addr) & 0xff) << (8 * i);
|
||||
}
|
||||
vendor = (cellid >> 12) & 0xff;
|
||||
printk(KERN_INFO "VIC @%p: id 0x%08x, vendor 0x%02x\n",
|
||||
base, cellid, vendor);
|
||||
|
||||
switch(vendor) {
|
||||
case AMBA_VENDOR_ST:
|
||||
vic_init_st(base, irq_start, vic_sources);
|
||||
return;
|
||||
default:
|
||||
printk(KERN_WARNING "VIC: unknown vendor, continuing anyways\n");
|
||||
/* fall through */
|
||||
case AMBA_VENDOR_ARM:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Disable all interrupts initially. */
|
||||
|
||||
writel(0, base + VIC_INT_SELECT);
|
||||
writel(0, base + VIC_INT_ENABLE);
|
||||
writel(~0, base + VIC_INT_ENABLE_CLEAR);
|
||||
writel(0, base + VIC_IRQ_STATUS);
|
||||
writel(0, base + VIC_ITCR);
|
||||
writel(~0, base + VIC_INT_SOFT_CLEAR);
|
||||
|
||||
/*
|
||||
* Make sure we clear all existing interrupts
|
||||
*/
|
||||
writel(0, base + VIC_PL190_VECT_ADDR);
|
||||
for (i = 0; i < 19; i++) {
|
||||
unsigned int value;
|
||||
|
||||
value = readl(base + VIC_PL190_VECT_ADDR);
|
||||
writel(value, base + VIC_PL190_VECT_ADDR);
|
||||
}
|
||||
|
||||
vic_init2(base);
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (vic_sources & (1 << i)) {
|
||||
unsigned int irq = irq_start + i;
|
||||
|
||||
set_irq_chip(irq, &vic_chip);
|
||||
set_irq_chip_data(irq, base);
|
||||
set_irq_handler(irq, handle_level_irq);
|
||||
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
|
||||
}
|
||||
}
|
||||
|
||||
vic_pm_register(base, irq_start, resume_sources);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -242,10 +242,13 @@ CONFIG_CPU_CP15_MMU=y
|
|||
# CONFIG_CPU_DCACHE_DISABLE is not set
|
||||
# CONFIG_CPU_BPREDICT_DISABLE is not set
|
||||
CONFIG_HAS_TLS_REG=y
|
||||
CONFIG_OUTER_CACHE=y
|
||||
CONFIG_CACHE_L2X0=y
|
||||
CONFIG_ARM_L1_CACHE_SHIFT=5
|
||||
# CONFIG_ARM_ERRATA_430973 is not set
|
||||
# CONFIG_ARM_ERRATA_458693 is not set
|
||||
# CONFIG_ARM_ERRATA_460075 is not set
|
||||
CONFIG_PL310_ERRATA_588369=y
|
||||
CONFIG_ARM_GIC=y
|
||||
|
||||
#
|
||||
|
|
|
@ -235,6 +235,234 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
|
|||
#define smp_mb__before_atomic_inc() smp_mb()
|
||||
#define smp_mb__after_atomic_inc() smp_mb()
|
||||
|
||||
#ifndef CONFIG_GENERIC_ATOMIC64
|
||||
typedef struct {
|
||||
u64 __aligned(8) counter;
|
||||
} atomic64_t;
|
||||
|
||||
#define ATOMIC64_INIT(i) { (i) }
|
||||
|
||||
static inline u64 atomic64_read(atomic64_t *v)
|
||||
{
|
||||
u64 result;
|
||||
|
||||
__asm__ __volatile__("@ atomic64_read\n"
|
||||
" ldrexd %0, %H0, [%1]"
|
||||
: "=&r" (result)
|
||||
: "r" (&v->counter)
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline void atomic64_set(atomic64_t *v, u64 i)
|
||||
{
|
||||
u64 tmp;
|
||||
|
||||
__asm__ __volatile__("@ atomic64_set\n"
|
||||
"1: ldrexd %0, %H0, [%1]\n"
|
||||
" strexd %0, %2, %H2, [%1]\n"
|
||||
" teq %0, #0\n"
|
||||
" bne 1b"
|
||||
: "=&r" (tmp)
|
||||
: "r" (&v->counter), "r" (i)
|
||||
: "cc");
|
||||
}
|
||||
|
||||
static inline void atomic64_add(u64 i, atomic64_t *v)
|
||||
{
|
||||
u64 result;
|
||||
unsigned long tmp;
|
||||
|
||||
__asm__ __volatile__("@ atomic64_add\n"
|
||||
"1: ldrexd %0, %H0, [%2]\n"
|
||||
" adds %0, %0, %3\n"
|
||||
" adc %H0, %H0, %H3\n"
|
||||
" strexd %1, %0, %H0, [%2]\n"
|
||||
" teq %1, #0\n"
|
||||
" bne 1b"
|
||||
: "=&r" (result), "=&r" (tmp)
|
||||
: "r" (&v->counter), "r" (i)
|
||||
: "cc");
|
||||
}
|
||||
|
||||
static inline u64 atomic64_add_return(u64 i, atomic64_t *v)
|
||||
{
|
||||
u64 result;
|
||||
unsigned long tmp;
|
||||
|
||||
smp_mb();
|
||||
|
||||
__asm__ __volatile__("@ atomic64_add_return\n"
|
||||
"1: ldrexd %0, %H0, [%2]\n"
|
||||
" adds %0, %0, %3\n"
|
||||
" adc %H0, %H0, %H3\n"
|
||||
" strexd %1, %0, %H0, [%2]\n"
|
||||
" teq %1, #0\n"
|
||||
" bne 1b"
|
||||
: "=&r" (result), "=&r" (tmp)
|
||||
: "r" (&v->counter), "r" (i)
|
||||
: "cc");
|
||||
|
||||
smp_mb();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline void atomic64_sub(u64 i, atomic64_t *v)
|
||||
{
|
||||
u64 result;
|
||||
unsigned long tmp;
|
||||
|
||||
__asm__ __volatile__("@ atomic64_sub\n"
|
||||
"1: ldrexd %0, %H0, [%2]\n"
|
||||
" subs %0, %0, %3\n"
|
||||
" sbc %H0, %H0, %H3\n"
|
||||
" strexd %1, %0, %H0, [%2]\n"
|
||||
" teq %1, #0\n"
|
||||
" bne 1b"
|
||||
: "=&r" (result), "=&r" (tmp)
|
||||
: "r" (&v->counter), "r" (i)
|
||||
: "cc");
|
||||
}
|
||||
|
||||
static inline u64 atomic64_sub_return(u64 i, atomic64_t *v)
|
||||
{
|
||||
u64 result;
|
||||
unsigned long tmp;
|
||||
|
||||
smp_mb();
|
||||
|
||||
__asm__ __volatile__("@ atomic64_sub_return\n"
|
||||
"1: ldrexd %0, %H0, [%2]\n"
|
||||
" subs %0, %0, %3\n"
|
||||
" sbc %H0, %H0, %H3\n"
|
||||
" strexd %1, %0, %H0, [%2]\n"
|
||||
" teq %1, #0\n"
|
||||
" bne 1b"
|
||||
: "=&r" (result), "=&r" (tmp)
|
||||
: "r" (&v->counter), "r" (i)
|
||||
: "cc");
|
||||
|
||||
smp_mb();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old, u64 new)
|
||||
{
|
||||
u64 oldval;
|
||||
unsigned long res;
|
||||
|
||||
smp_mb();
|
||||
|
||||
do {
|
||||
__asm__ __volatile__("@ atomic64_cmpxchg\n"
|
||||
"ldrexd %1, %H1, [%2]\n"
|
||||
"mov %0, #0\n"
|
||||
"teq %1, %3\n"
|
||||
"teqeq %H1, %H3\n"
|
||||
"strexdeq %0, %4, %H4, [%2]"
|
||||
: "=&r" (res), "=&r" (oldval)
|
||||
: "r" (&ptr->counter), "r" (old), "r" (new)
|
||||
: "cc");
|
||||
} while (res);
|
||||
|
||||
smp_mb();
|
||||
|
||||
return oldval;
|
||||
}
|
||||
|
||||
static inline u64 atomic64_xchg(atomic64_t *ptr, u64 new)
|
||||
{
|
||||
u64 result;
|
||||
unsigned long tmp;
|
||||
|
||||
smp_mb();
|
||||
|
||||
__asm__ __volatile__("@ atomic64_xchg\n"
|
||||
"1: ldrexd %0, %H0, [%2]\n"
|
||||
" strexd %1, %3, %H3, [%2]\n"
|
||||
" teq %1, #0\n"
|
||||
" bne 1b"
|
||||
: "=&r" (result), "=&r" (tmp)
|
||||
: "r" (&ptr->counter), "r" (new)
|
||||
: "cc");
|
||||
|
||||
smp_mb();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline u64 atomic64_dec_if_positive(atomic64_t *v)
|
||||
{
|
||||
u64 result;
|
||||
unsigned long tmp;
|
||||
|
||||
smp_mb();
|
||||
|
||||
__asm__ __volatile__("@ atomic64_dec_if_positive\n"
|
||||
"1: ldrexd %0, %H0, [%2]\n"
|
||||
" subs %0, %0, #1\n"
|
||||
" sbc %H0, %H0, #0\n"
|
||||
" teq %H0, #0\n"
|
||||
" bmi 2f\n"
|
||||
" strexd %1, %0, %H0, [%2]\n"
|
||||
" teq %1, #0\n"
|
||||
" bne 1b\n"
|
||||
"2:"
|
||||
: "=&r" (result), "=&r" (tmp)
|
||||
: "r" (&v->counter)
|
||||
: "cc");
|
||||
|
||||
smp_mb();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline int atomic64_add_unless(atomic64_t *v, u64 a, u64 u)
|
||||
{
|
||||
u64 val;
|
||||
unsigned long tmp;
|
||||
int ret = 1;
|
||||
|
||||
smp_mb();
|
||||
|
||||
__asm__ __volatile__("@ atomic64_add_unless\n"
|
||||
"1: ldrexd %0, %H0, [%3]\n"
|
||||
" teq %0, %4\n"
|
||||
" teqeq %H0, %H4\n"
|
||||
" moveq %1, #0\n"
|
||||
" beq 2f\n"
|
||||
" adds %0, %0, %5\n"
|
||||
" adc %H0, %H0, %H5\n"
|
||||
" strexd %2, %0, %H0, [%3]\n"
|
||||
" teq %2, #0\n"
|
||||
" bne 1b\n"
|
||||
"2:"
|
||||
: "=&r" (val), "=&r" (ret), "=&r" (tmp)
|
||||
: "r" (&v->counter), "r" (u), "r" (a)
|
||||
: "cc");
|
||||
|
||||
if (ret)
|
||||
smp_mb();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define atomic64_add_negative(a, v) (atomic64_add_return((a), (v)) < 0)
|
||||
#define atomic64_inc(v) atomic64_add(1LL, (v))
|
||||
#define atomic64_inc_return(v) atomic64_add_return(1LL, (v))
|
||||
#define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0)
|
||||
#define atomic64_sub_and_test(a, v) (atomic64_sub_return((a), (v)) == 0)
|
||||
#define atomic64_dec(v) atomic64_sub(1LL, (v))
|
||||
#define atomic64_dec_return(v) atomic64_sub_return(1LL, (v))
|
||||
#define atomic64_dec_and_test(v) (atomic64_dec_return((v)) == 0)
|
||||
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1LL, 0LL)
|
||||
|
||||
#else /* !CONFIG_GENERIC_ATOMIC64 */
|
||||
#include <asm-generic/atomic64.h>
|
||||
#endif
|
||||
#include <asm-generic/atomic-long.h>
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -197,21 +197,6 @@
|
|||
* DMA Cache Coherency
|
||||
* ===================
|
||||
*
|
||||
* dma_inv_range(start, end)
|
||||
*
|
||||
* Invalidate (discard) the specified virtual address range.
|
||||
* May not write back any entries. If 'start' or 'end'
|
||||
* are not cache line aligned, those lines must be written
|
||||
* back.
|
||||
* - start - virtual start address
|
||||
* - end - virtual end address
|
||||
*
|
||||
* dma_clean_range(start, end)
|
||||
*
|
||||
* Clean (write back) the specified virtual address range.
|
||||
* - start - virtual start address
|
||||
* - end - virtual end address
|
||||
*
|
||||
* dma_flush_range(start, end)
|
||||
*
|
||||
* Clean and invalidate the specified virtual address range.
|
||||
|
@ -228,8 +213,9 @@ struct cpu_cache_fns {
|
|||
void (*coherent_user_range)(unsigned long, unsigned long);
|
||||
void (*flush_kern_dcache_area)(void *, size_t);
|
||||
|
||||
void (*dma_inv_range)(const void *, const void *);
|
||||
void (*dma_clean_range)(const void *, const void *);
|
||||
void (*dma_map_area)(const void *, size_t, int);
|
||||
void (*dma_unmap_area)(const void *, size_t, int);
|
||||
|
||||
void (*dma_flush_range)(const void *, const void *);
|
||||
};
|
||||
|
||||
|
@ -259,8 +245,8 @@ extern struct cpu_cache_fns cpu_cache;
|
|||
* is visible to DMA, or data written by DMA to system memory is
|
||||
* visible to the CPU.
|
||||
*/
|
||||
#define dmac_inv_range cpu_cache.dma_inv_range
|
||||
#define dmac_clean_range cpu_cache.dma_clean_range
|
||||
#define dmac_map_area cpu_cache.dma_map_area
|
||||
#define dmac_unmap_area cpu_cache.dma_unmap_area
|
||||
#define dmac_flush_range cpu_cache.dma_flush_range
|
||||
|
||||
#else
|
||||
|
@ -285,12 +271,12 @@ extern void __cpuc_flush_dcache_area(void *, size_t);
|
|||
* is visible to DMA, or data written by DMA to system memory is
|
||||
* visible to the CPU.
|
||||
*/
|
||||
#define dmac_inv_range __glue(_CACHE,_dma_inv_range)
|
||||
#define dmac_clean_range __glue(_CACHE,_dma_clean_range)
|
||||
#define dmac_map_area __glue(_CACHE,_dma_map_area)
|
||||
#define dmac_unmap_area __glue(_CACHE,_dma_unmap_area)
|
||||
#define dmac_flush_range __glue(_CACHE,_dma_flush_range)
|
||||
|
||||
extern void dmac_inv_range(const void *, const void *);
|
||||
extern void dmac_clean_range(const void *, const void *);
|
||||
extern void dmac_map_area(const void *, size_t, int);
|
||||
extern void dmac_unmap_area(const void *, size_t, int);
|
||||
extern void dmac_flush_range(const void *, const void *);
|
||||
|
||||
#endif
|
||||
|
@ -331,12 +317,8 @@ static inline void outer_flush_range(unsigned long start, unsigned long end)
|
|||
* processes address space. Really, we want to allow our "user
|
||||
* space" model to handle this.
|
||||
*/
|
||||
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
|
||||
do { \
|
||||
memcpy(dst, src, len); \
|
||||
flush_ptrace_access(vma, page, vaddr, dst, len, 1);\
|
||||
} while (0)
|
||||
|
||||
extern void copy_to_user_page(struct vm_area_struct *, struct page *,
|
||||
unsigned long, void *, const void *, unsigned long);
|
||||
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
|
||||
do { \
|
||||
memcpy(dst, src, len); \
|
||||
|
@ -370,17 +352,6 @@ vivt_flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsig
|
|||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
vivt_flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
|
||||
unsigned long uaddr, void *kaddr,
|
||||
unsigned long len, int write)
|
||||
{
|
||||
if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) {
|
||||
unsigned long addr = (unsigned long)kaddr;
|
||||
__cpuc_coherent_kern_range(addr, addr + len);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_CPU_CACHE_VIPT
|
||||
#define flush_cache_mm(mm) \
|
||||
vivt_flush_cache_mm(mm)
|
||||
|
@ -388,15 +359,10 @@ vivt_flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
|
|||
vivt_flush_cache_range(vma,start,end)
|
||||
#define flush_cache_page(vma,addr,pfn) \
|
||||
vivt_flush_cache_page(vma,addr,pfn)
|
||||
#define flush_ptrace_access(vma,page,ua,ka,len,write) \
|
||||
vivt_flush_ptrace_access(vma,page,ua,ka,len,write)
|
||||
#else
|
||||
extern void flush_cache_mm(struct mm_struct *mm);
|
||||
extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
|
||||
extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn);
|
||||
extern void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
|
||||
unsigned long uaddr, void *kaddr,
|
||||
unsigned long len, int write);
|
||||
#endif
|
||||
|
||||
#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
|
||||
|
|
|
@ -27,4 +27,7 @@ struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
|
|||
void clkdev_add(struct clk_lookup *cl);
|
||||
void clkdev_drop(struct clk_lookup *cl);
|
||||
|
||||
void clkdev_add_table(struct clk_lookup *, size_t);
|
||||
int clk_add_alias(const char *, const char *, char *, struct device *);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -57,18 +57,58 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)
|
|||
#endif
|
||||
|
||||
/*
|
||||
* DMA-consistent mapping functions. These allocate/free a region of
|
||||
* uncached, unwrite-buffered mapped memory space for use with DMA
|
||||
* devices. This is the "generic" version. The PCI specific version
|
||||
* is in pci.h
|
||||
* The DMA API is built upon the notion of "buffer ownership". A buffer
|
||||
* is either exclusively owned by the CPU (and therefore may be accessed
|
||||
* by it) or exclusively owned by the DMA device. These helper functions
|
||||
* represent the transitions between these two ownership states.
|
||||
*
|
||||
* Note: Drivers should NOT use this function directly, as it will break
|
||||
* platforms with CONFIG_DMABOUNCE.
|
||||
* Use the driver DMA support - see dma-mapping.h (dma_sync_*)
|
||||
* Note, however, that on later ARMs, this notion does not work due to
|
||||
* speculative prefetches. We model our approach on the assumption that
|
||||
* the CPU does do speculative prefetches, which means we clean caches
|
||||
* before transfers and delay cache invalidation until transfer completion.
|
||||
*
|
||||
* Private support functions: these are not part of the API and are
|
||||
* liable to change. Drivers must not use these.
|
||||
*/
|
||||
extern void dma_cache_maint(const void *kaddr, size_t size, int rw);
|
||||
extern void dma_cache_maint_page(struct page *page, unsigned long offset,
|
||||
size_t size, int rw);
|
||||
static inline void __dma_single_cpu_to_dev(const void *kaddr, size_t size,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
extern void ___dma_single_cpu_to_dev(const void *, size_t,
|
||||
enum dma_data_direction);
|
||||
|
||||
if (!arch_is_coherent())
|
||||
___dma_single_cpu_to_dev(kaddr, size, dir);
|
||||
}
|
||||
|
||||
static inline void __dma_single_dev_to_cpu(const void *kaddr, size_t size,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
extern void ___dma_single_dev_to_cpu(const void *, size_t,
|
||||
enum dma_data_direction);
|
||||
|
||||
if (!arch_is_coherent())
|
||||
___dma_single_dev_to_cpu(kaddr, size, dir);
|
||||
}
|
||||
|
||||
static inline void __dma_page_cpu_to_dev(struct page *page, unsigned long off,
|
||||
size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
extern void ___dma_page_cpu_to_dev(struct page *, unsigned long,
|
||||
size_t, enum dma_data_direction);
|
||||
|
||||
if (!arch_is_coherent())
|
||||
___dma_page_cpu_to_dev(page, off, size, dir);
|
||||
}
|
||||
|
||||
static inline void __dma_page_dev_to_cpu(struct page *page, unsigned long off,
|
||||
size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
extern void ___dma_page_dev_to_cpu(struct page *, unsigned long,
|
||||
size_t, enum dma_data_direction);
|
||||
|
||||
if (!arch_is_coherent())
|
||||
___dma_page_dev_to_cpu(page, off, size, dir);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return whether the given device DMA address mask can be supported
|
||||
|
@ -304,8 +344,7 @@ static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
|
|||
{
|
||||
BUG_ON(!valid_dma_direction(dir));
|
||||
|
||||
if (!arch_is_coherent())
|
||||
dma_cache_maint(cpu_addr, size, dir);
|
||||
__dma_single_cpu_to_dev(cpu_addr, size, dir);
|
||||
|
||||
return virt_to_dma(dev, cpu_addr);
|
||||
}
|
||||
|
@ -329,8 +368,7 @@ static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
|
|||
{
|
||||
BUG_ON(!valid_dma_direction(dir));
|
||||
|
||||
if (!arch_is_coherent())
|
||||
dma_cache_maint_page(page, offset, size, dir);
|
||||
__dma_page_cpu_to_dev(page, offset, size, dir);
|
||||
|
||||
return page_to_dma(dev, page) + offset;
|
||||
}
|
||||
|
@ -352,7 +390,7 @@ static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
|
|||
static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,
|
||||
size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
/* nothing to do */
|
||||
__dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -372,7 +410,8 @@ static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,
|
|||
static inline void dma_unmap_page(struct device *dev, dma_addr_t handle,
|
||||
size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
/* nothing to do */
|
||||
__dma_page_dev_to_cpu(dma_to_page(dev, handle), handle & ~PAGE_MASK,
|
||||
size, dir);
|
||||
}
|
||||
#endif /* CONFIG_DMABOUNCE */
|
||||
|
||||
|
@ -400,7 +439,10 @@ static inline void dma_sync_single_range_for_cpu(struct device *dev,
|
|||
{
|
||||
BUG_ON(!valid_dma_direction(dir));
|
||||
|
||||
dmabounce_sync_for_cpu(dev, handle, offset, size, dir);
|
||||
if (!dmabounce_sync_for_cpu(dev, handle, offset, size, dir))
|
||||
return;
|
||||
|
||||
__dma_single_dev_to_cpu(dma_to_virt(dev, handle) + offset, size, dir);
|
||||
}
|
||||
|
||||
static inline void dma_sync_single_range_for_device(struct device *dev,
|
||||
|
@ -412,8 +454,7 @@ static inline void dma_sync_single_range_for_device(struct device *dev,
|
|||
if (!dmabounce_sync_for_device(dev, handle, offset, size, dir))
|
||||
return;
|
||||
|
||||
if (!arch_is_coherent())
|
||||
dma_cache_maint(dma_to_virt(dev, handle) + offset, size, dir);
|
||||
__dma_single_cpu_to_dev(dma_to_virt(dev, handle) + offset, size, dir);
|
||||
}
|
||||
|
||||
static inline void dma_sync_single_for_cpu(struct device *dev,
|
||||
|
|
|
@ -69,9 +69,16 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
|
|||
/*
|
||||
* __arm_ioremap takes CPU physical address.
|
||||
* __arm_ioremap_pfn takes a Page Frame Number and an offset into that page
|
||||
* The _caller variety takes a __builtin_return_address(0) value for
|
||||
* /proc/vmalloc to use - and should only be used in non-inline functions.
|
||||
*/
|
||||
extern void __iomem * __arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int);
|
||||
extern void __iomem * __arm_ioremap(unsigned long, size_t, unsigned int);
|
||||
extern void __iomem *__arm_ioremap_pfn_caller(unsigned long, unsigned long,
|
||||
size_t, unsigned int, void *);
|
||||
extern void __iomem *__arm_ioremap_caller(unsigned long, size_t, unsigned int,
|
||||
void *);
|
||||
|
||||
extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int);
|
||||
extern void __iomem *__arm_ioremap(unsigned long, size_t, unsigned int);
|
||||
extern void __iounmap(volatile void __iomem *addr);
|
||||
|
||||
/*
|
||||
|
|
|
@ -46,12 +46,4 @@ struct sys_timer {
|
|||
extern struct sys_timer *system_timer;
|
||||
extern void timer_tick(void);
|
||||
|
||||
/*
|
||||
* Kernel time keeping support.
|
||||
*/
|
||||
struct timespec;
|
||||
extern int (*set_rtc)(void);
|
||||
extern void save_time_delta(struct timespec *delta, struct timespec *rtc);
|
||||
extern void restore_time_delta(struct timespec *delta, struct timespec *rtc);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -76,6 +76,17 @@
|
|||
*/
|
||||
#define IOREMAP_MAX_ORDER 24
|
||||
|
||||
/*
|
||||
* Size of DMA-consistent memory region. Must be multiple of 2M,
|
||||
* between 2MB and 14MB inclusive.
|
||||
*/
|
||||
#ifndef CONSISTENT_DMA_SIZE
|
||||
#define CONSISTENT_DMA_SIZE SZ_2M
|
||||
#endif
|
||||
|
||||
#define CONSISTENT_END (0xffe00000UL)
|
||||
#define CONSISTENT_BASE (CONSISTENT_END - CONSISTENT_DMA_SIZE)
|
||||
|
||||
#else /* CONFIG_MMU */
|
||||
|
||||
/*
|
||||
|
@ -93,11 +104,11 @@
|
|||
#endif
|
||||
|
||||
#ifndef PHYS_OFFSET
|
||||
#define PHYS_OFFSET (CONFIG_DRAM_BASE)
|
||||
#define PHYS_OFFSET UL(CONFIG_DRAM_BASE)
|
||||
#endif
|
||||
|
||||
#ifndef END_MEM
|
||||
#define END_MEM (CONFIG_DRAM_BASE + CONFIG_DRAM_SIZE)
|
||||
#define END_MEM (UL(CONFIG_DRAM_BASE) + CONFIG_DRAM_SIZE)
|
||||
#endif
|
||||
|
||||
#ifndef PAGE_OFFSET
|
||||
|
@ -112,14 +123,6 @@
|
|||
|
||||
#endif /* !CONFIG_MMU */
|
||||
|
||||
/*
|
||||
* Size of DMA-consistent memory region. Must be multiple of 2M,
|
||||
* between 2MB and 14MB inclusive.
|
||||
*/
|
||||
#ifndef CONSISTENT_DMA_SIZE
|
||||
#define CONSISTENT_DMA_SIZE SZ_2M
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Physical vs virtual RAM address space conversion. These are
|
||||
* private definitions which should NOT be used outside memory.h
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
typedef struct {
|
||||
#ifdef CONFIG_CPU_HAS_ASID
|
||||
unsigned int id;
|
||||
spinlock_t id_lock;
|
||||
#endif
|
||||
unsigned int kvm_seq;
|
||||
} mm_context_t;
|
||||
|
|
|
@ -43,12 +43,23 @@ void __check_kvm_seq(struct mm_struct *mm);
|
|||
#define ASID_FIRST_VERSION (1 << ASID_BITS)
|
||||
|
||||
extern unsigned int cpu_last_asid;
|
||||
#ifdef CONFIG_SMP
|
||||
DECLARE_PER_CPU(struct mm_struct *, current_mm);
|
||||
#endif
|
||||
|
||||
void __init_new_context(struct task_struct *tsk, struct mm_struct *mm);
|
||||
void __new_context(struct mm_struct *mm);
|
||||
|
||||
static inline void check_context(struct mm_struct *mm)
|
||||
{
|
||||
/*
|
||||
* This code is executed with interrupts enabled. Therefore,
|
||||
* mm->context.id cannot be updated to the latest ASID version
|
||||
* on a different CPU (and condition below not triggered)
|
||||
* without first getting an IPI to reset the context. The
|
||||
* alternative is to take a read_lock on mm->context.id_lock
|
||||
* (after changing its type to rwlock_t).
|
||||
*/
|
||||
if (unlikely((mm->context.id ^ cpu_last_asid) >> ASID_BITS))
|
||||
__new_context(mm);
|
||||
|
||||
|
@ -108,6 +119,10 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
|||
__flush_icache_all();
|
||||
#endif
|
||||
if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next) {
|
||||
#ifdef CONFIG_SMP
|
||||
struct mm_struct **crt_mm = &per_cpu(current_mm, cpu);
|
||||
*crt_mm = next;
|
||||
#endif
|
||||
check_context(next);
|
||||
cpu_switch_mm(next->pgd, next);
|
||||
if (cache_is_vivt())
|
||||
|
|
|
@ -117,11 +117,12 @@
|
|||
#endif
|
||||
|
||||
struct page;
|
||||
struct vm_area_struct;
|
||||
|
||||
struct cpu_user_fns {
|
||||
void (*cpu_clear_user_highpage)(struct page *page, unsigned long vaddr);
|
||||
void (*cpu_copy_user_highpage)(struct page *to, struct page *from,
|
||||
unsigned long vaddr);
|
||||
unsigned long vaddr, struct vm_area_struct *vma);
|
||||
};
|
||||
|
||||
#ifdef MULTI_USER
|
||||
|
@ -137,7 +138,7 @@ extern struct cpu_user_fns cpu_user;
|
|||
|
||||
extern void __cpu_clear_user_highpage(struct page *page, unsigned long vaddr);
|
||||
extern void __cpu_copy_user_highpage(struct page *to, struct page *from,
|
||||
unsigned long vaddr);
|
||||
unsigned long vaddr, struct vm_area_struct *vma);
|
||||
#endif
|
||||
|
||||
#define clear_user_highpage(page,vaddr) \
|
||||
|
@ -145,7 +146,7 @@ extern void __cpu_copy_user_highpage(struct page *to, struct page *from,
|
|||
|
||||
#define __HAVE_ARCH_COPY_USER_HIGHPAGE
|
||||
#define copy_user_highpage(to,from,vaddr,vma) \
|
||||
__cpu_copy_user_highpage(to, from, vaddr)
|
||||
__cpu_copy_user_highpage(to, from, vaddr, vma)
|
||||
|
||||
#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
|
||||
extern void copy_page(void *to, const void *from);
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* linux/arch/arm/include/asm/perf_event.h
|
||||
*
|
||||
* Copyright (C) 2009 picoChip Designs Ltd, Jamie Iles
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ARM_PERF_EVENT_H__
|
||||
#define __ARM_PERF_EVENT_H__
|
||||
|
||||
/*
|
||||
* NOP: on *most* (read: all supported) ARM platforms, the performance
|
||||
* counter interrupts are regular interrupts and not an NMI. This
|
||||
* means that when we receive the interrupt we can call
|
||||
* perf_event_do_pending() that handles all of the work with
|
||||
* interrupts enabled.
|
||||
*/
|
||||
static inline void
|
||||
set_perf_event_pending(void)
|
||||
{
|
||||
}
|
||||
|
||||
/* ARM performance counters start from 1 (in the cp15 accesses) so use the
|
||||
* same indexes here for consistency. */
|
||||
#define PERF_EVENT_INDEX_OFFSET 1
|
||||
|
||||
#endif /* __ARM_PERF_EVENT_H__ */
|
|
@ -86,8 +86,8 @@ extern unsigned int kobjsize(const void *objp);
|
|||
* All 32bit addresses are effectively valid for vmalloc...
|
||||
* Sort of meaningless for non-VM targets.
|
||||
*/
|
||||
#define VMALLOC_START 0
|
||||
#define VMALLOC_END 0xffffffff
|
||||
#define VMALLOC_START 0UL
|
||||
#define VMALLOC_END 0xffffffffUL
|
||||
|
||||
#define FIRST_USER_ADDRESS (0)
|
||||
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* linux/arch/arm/include/asm/pmu.h
|
||||
*
|
||||
* Copyright (C) 2009 picoChip Designs Ltd, Jamie Iles
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ARM_PMU_H__
|
||||
#define __ARM_PMU_H__
|
||||
|
||||
#ifdef CONFIG_CPU_HAS_PMU
|
||||
|
||||
struct pmu_irqs {
|
||||
const int *irqs;
|
||||
int num_irqs;
|
||||
};
|
||||
|
||||
/**
|
||||
* reserve_pmu() - reserve the hardware performance counters
|
||||
*
|
||||
* Reserve the hardware performance counters in the system for exclusive use.
|
||||
* The 'struct pmu_irqs' for the system is returned on success, ERR_PTR()
|
||||
* encoded error on failure.
|
||||
*/
|
||||
extern const struct pmu_irqs *
|
||||
reserve_pmu(void);
|
||||
|
||||
/**
|
||||
* release_pmu() - Relinquish control of the performance counters
|
||||
*
|
||||
* Release the performance counters and allow someone else to use them.
|
||||
* Callers must have disabled the counters and released IRQs before calling
|
||||
* this. The 'struct pmu_irqs' returned from reserve_pmu() must be passed as
|
||||
* a cookie.
|
||||
*/
|
||||
extern int
|
||||
release_pmu(const struct pmu_irqs *irqs);
|
||||
|
||||
/**
|
||||
* init_pmu() - Initialise the PMU.
|
||||
*
|
||||
* Initialise the system ready for PMU enabling. This should typically set the
|
||||
* IRQ affinity and nothing else. The users (oprofile/perf events etc) will do
|
||||
* the actual hardware initialisation.
|
||||
*/
|
||||
extern int
|
||||
init_pmu(void);
|
||||
|
||||
#else /* CONFIG_CPU_HAS_PMU */
|
||||
|
||||
static inline const struct pmu_irqs *
|
||||
reserve_pmu(void)
|
||||
{
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static inline int
|
||||
release_pmu(const struct pmu_irqs *irqs)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int
|
||||
init_pmu(void)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_CPU_HAS_PMU */
|
||||
|
||||
#endif /* __ARM_PMU_H__ */
|
|
@ -223,18 +223,6 @@ extern struct meminfo meminfo;
|
|||
#define bank_phys_end(bank) ((bank)->start + (bank)->size)
|
||||
#define bank_phys_size(bank) (bank)->size
|
||||
|
||||
/*
|
||||
* Early command line parameters.
|
||||
*/
|
||||
struct early_params {
|
||||
const char *arg;
|
||||
void (*fn)(char **p);
|
||||
};
|
||||
|
||||
#define __early_param(name,fn) \
|
||||
static struct early_params __early_##fn __used \
|
||||
__attribute__((__section__(".early_param.init"))) = { name, fn }
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,4 +13,9 @@ static inline int tlb_ops_need_broadcast(void)
|
|||
return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 2;
|
||||
}
|
||||
|
||||
static inline int cache_ops_need_broadcast(void)
|
||||
{
|
||||
return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,6 +5,22 @@
|
|||
#error SMP not supported on pre-ARMv6 CPUs
|
||||
#endif
|
||||
|
||||
static inline void dsb_sev(void)
|
||||
{
|
||||
#if __LINUX_ARM_ARCH__ >= 7
|
||||
__asm__ __volatile__ (
|
||||
"dsb\n"
|
||||
"sev"
|
||||
);
|
||||
#elif defined(CONFIG_CPU_32v6K)
|
||||
__asm__ __volatile__ (
|
||||
"mcr p15, 0, %0, c7, c10, 4\n"
|
||||
"sev"
|
||||
: : "r" (0)
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* ARMv6 Spin-locking.
|
||||
*
|
||||
|
@ -69,13 +85,11 @@ static inline void arch_spin_unlock(arch_spinlock_t *lock)
|
|||
|
||||
__asm__ __volatile__(
|
||||
" str %1, [%0]\n"
|
||||
#ifdef CONFIG_CPU_32v6K
|
||||
" mcr p15, 0, %1, c7, c10, 4\n" /* DSB */
|
||||
" sev"
|
||||
#endif
|
||||
:
|
||||
: "r" (&lock->lock), "r" (0)
|
||||
: "cc");
|
||||
|
||||
dsb_sev();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -132,13 +146,11 @@ static inline void arch_write_unlock(arch_rwlock_t *rw)
|
|||
|
||||
__asm__ __volatile__(
|
||||
"str %1, [%0]\n"
|
||||
#ifdef CONFIG_CPU_32v6K
|
||||
" mcr p15, 0, %1, c7, c10, 4\n" /* DSB */
|
||||
" sev\n"
|
||||
#endif
|
||||
:
|
||||
: "r" (&rw->lock), "r" (0)
|
||||
: "cc");
|
||||
|
||||
dsb_sev();
|
||||
}
|
||||
|
||||
/* write_can_lock - would write_trylock() succeed? */
|
||||
|
@ -188,14 +200,12 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
|
|||
" strex %1, %0, [%2]\n"
|
||||
" teq %1, #0\n"
|
||||
" bne 1b"
|
||||
#ifdef CONFIG_CPU_32v6K
|
||||
"\n cmp %0, #0\n"
|
||||
" mcreq p15, 0, %0, c7, c10, 4\n"
|
||||
" seveq"
|
||||
#endif
|
||||
: "=&r" (tmp), "=&r" (tmp2)
|
||||
: "r" (&rw->lock)
|
||||
: "cc");
|
||||
|
||||
if (tmp == 0)
|
||||
dsb_sev();
|
||||
}
|
||||
|
||||
static inline int arch_read_trylock(arch_rwlock_t *rw)
|
||||
|
|
|
@ -73,8 +73,7 @@ extern unsigned int mem_fclk_21285;
|
|||
|
||||
struct pt_regs;
|
||||
|
||||
void die(const char *msg, struct pt_regs *regs, int err)
|
||||
__attribute__((noreturn));
|
||||
void die(const char *msg, struct pt_regs *regs, int err);
|
||||
|
||||
struct siginfo;
|
||||
void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info,
|
||||
|
|
|
@ -115,7 +115,8 @@ extern void iwmmxt_task_restore(struct thread_info *, void *);
|
|||
extern void iwmmxt_task_release(struct thread_info *);
|
||||
extern void iwmmxt_task_switch(struct thread_info *);
|
||||
|
||||
extern void vfp_sync_state(struct thread_info *thread);
|
||||
extern void vfp_sync_hwstate(struct thread_info *);
|
||||
extern void vfp_flush_hwstate(struct thread_info *);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -529,7 +529,8 @@ extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
|
|||
* cache entries for the kernels virtual memory range are written
|
||||
* back to the page.
|
||||
*/
|
||||
extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte);
|
||||
extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
|
||||
pte_t *ptep);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ obj-y := compat.o elf.o entry-armv.o entry-common.o irq.o \
|
|||
process.o ptrace.o return_address.o setup.o signal.o \
|
||||
sys_arm.o stacktrace.o time.o traps.o
|
||||
|
||||
obj-$(CONFIG_LEDS) += leds.o
|
||||
obj-$(CONFIG_OC_ETM) += etm.o
|
||||
|
||||
obj-$(CONFIG_ISA_DMA_API) += dma.o
|
||||
|
@ -46,6 +47,8 @@ obj-$(CONFIG_CPU_XSCALE) += xscale-cp0.o
|
|||
obj-$(CONFIG_CPU_XSC3) += xscale-cp0.o
|
||||
obj-$(CONFIG_CPU_MOHAWK) += xscale-cp0.o
|
||||
obj-$(CONFIG_IWMMXT) += iwmmxt.o
|
||||
obj-$(CONFIG_CPU_HAS_PMU) += pmu.o
|
||||
obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o
|
||||
AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt
|
||||
|
||||
ifneq ($(CONFIG_ARCH_EBSA110),y)
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
*/
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/memory.h>
|
||||
|
@ -112,5 +113,9 @@ int main(void)
|
|||
#ifdef MULTI_PABORT
|
||||
DEFINE(PROCESSOR_PABT_FUNC, offsetof(struct processor, _prefetch_abort));
|
||||
#endif
|
||||
BLANK();
|
||||
DEFINE(DMA_BIDIRECTIONAL, DMA_BIDIRECTIONAL);
|
||||
DEFINE(DMA_TO_DEVICE, DMA_TO_DEVICE);
|
||||
DEFINE(DMA_FROM_DEVICE, DMA_FROM_DEVICE);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
#if defined(CONFIG_CPU_V6)
|
||||
|
||||
.macro addruart, rx
|
||||
.macro addruart, rx, tmp
|
||||
.endm
|
||||
|
||||
.macro senduart, rd, rx
|
||||
|
@ -51,7 +51,7 @@
|
|||
|
||||
#elif defined(CONFIG_CPU_V7)
|
||||
|
||||
.macro addruart, rx
|
||||
.macro addruart, rx, tmp
|
||||
.endm
|
||||
|
||||
.macro senduart, rd, rx
|
||||
|
@ -71,7 +71,7 @@ wait: mrc p14, 0, pc, c0, c1, 0
|
|||
|
||||
#elif defined(CONFIG_CPU_XSCALE)
|
||||
|
||||
.macro addruart, rx
|
||||
.macro addruart, rx, tmp
|
||||
.endm
|
||||
|
||||
.macro senduart, rd, rx
|
||||
|
@ -98,7 +98,7 @@ wait: mrc p14, 0, pc, c0, c1, 0
|
|||
|
||||
#else
|
||||
|
||||
.macro addruart, rx
|
||||
.macro addruart, rx, tmp
|
||||
.endm
|
||||
|
||||
.macro senduart, rd, rx
|
||||
|
@ -164,7 +164,7 @@ ENDPROC(printhex2)
|
|||
.ltorg
|
||||
|
||||
ENTRY(printascii)
|
||||
addruart r3
|
||||
addruart r3, r1
|
||||
b 2f
|
||||
1: waituart r2, r3
|
||||
senduart r1, r3
|
||||
|
@ -180,7 +180,7 @@ ENTRY(printascii)
|
|||
ENDPROC(printascii)
|
||||
|
||||
ENTRY(printch)
|
||||
addruart r3
|
||||
addruart r3, r1
|
||||
mov r1, r0
|
||||
mov r0, #0
|
||||
b 1b
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* LED support code, ripped out of arch/arm/kernel/time.c
|
||||
*
|
||||
* Copyright (C) 1994-2001 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.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sysdev.h>
|
||||
|
||||
#include <asm/leds.h>
|
||||
|
||||
static void dummy_leds_event(led_event_t evt)
|
||||
{
|
||||
}
|
||||
|
||||
void (*leds_event)(led_event_t) = dummy_leds_event;
|
||||
|
||||
struct leds_evt_name {
|
||||
const char name[8];
|
||||
int on;
|
||||
int off;
|
||||
};
|
||||
|
||||
static const struct leds_evt_name evt_names[] = {
|
||||
{ "amber", led_amber_on, led_amber_off },
|
||||
{ "blue", led_blue_on, led_blue_off },
|
||||
{ "green", led_green_on, led_green_off },
|
||||
{ "red", led_red_on, led_red_off },
|
||||
};
|
||||
|
||||
static ssize_t leds_store(struct sys_device *dev,
|
||||
struct sysdev_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int ret = -EINVAL, len = strcspn(buf, " ");
|
||||
|
||||
if (len > 0 && buf[len] == '\0')
|
||||
len--;
|
||||
|
||||
if (strncmp(buf, "claim", len) == 0) {
|
||||
leds_event(led_claim);
|
||||
ret = size;
|
||||
} else if (strncmp(buf, "release", len) == 0) {
|
||||
leds_event(led_release);
|
||||
ret = size;
|
||||
} else {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(evt_names); i++) {
|
||||
if (strlen(evt_names[i].name) != len ||
|
||||
strncmp(buf, evt_names[i].name, len) != 0)
|
||||
continue;
|
||||
if (strncmp(buf+len, " on", 3) == 0) {
|
||||
leds_event(evt_names[i].on);
|
||||
ret = size;
|
||||
} else if (strncmp(buf+len, " off", 4) == 0) {
|
||||
leds_event(evt_names[i].off);
|
||||
ret = size;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static SYSDEV_ATTR(event, 0200, NULL, leds_store);
|
||||
|
||||
static int leds_suspend(struct sys_device *dev, pm_message_t state)
|
||||
{
|
||||
leds_event(led_stop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int leds_resume(struct sys_device *dev)
|
||||
{
|
||||
leds_event(led_start);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int leds_shutdown(struct sys_device *dev)
|
||||
{
|
||||
leds_event(led_halted);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysdev_class leds_sysclass = {
|
||||
.name = "leds",
|
||||
.shutdown = leds_shutdown,
|
||||
.suspend = leds_suspend,
|
||||
.resume = leds_resume,
|
||||
};
|
||||
|
||||
static struct sys_device leds_device = {
|
||||
.id = 0,
|
||||
.cls = &leds_sysclass,
|
||||
};
|
||||
|
||||
static int __init leds_init(void)
|
||||
{
|
||||
int ret;
|
||||
ret = sysdev_class_register(&leds_sysclass);
|
||||
if (ret == 0)
|
||||
ret = sysdev_register(&leds_device);
|
||||
if (ret == 0)
|
||||
ret = sysdev_create_file(&leds_device, &attr_event);
|
||||
return ret;
|
||||
}
|
||||
|
||||
device_initcall(leds_init);
|
||||
|
||||
EXPORT_SYMBOL(leds_event);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* linux/arch/arm/kernel/pmu.c
|
||||
*
|
||||
* Copyright (C) 2009 picoChip Designs Ltd, Jamie Iles
|
||||
*
|
||||
* 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/cpumask.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/pmu.h>
|
||||
|
||||
/*
|
||||
* Define the IRQs for the system. We could use something like a platform
|
||||
* device but that seems fairly heavyweight for this. Also, the performance
|
||||
* counters can't be removed or hotplugged.
|
||||
*
|
||||
* Ordering is important: init_pmu() will use the ordering to set the affinity
|
||||
* to the corresponding core. e.g. the first interrupt will go to cpu 0, the
|
||||
* second goes to cpu 1 etc.
|
||||
*/
|
||||
static const int irqs[] = {
|
||||
#if defined(CONFIG_ARCH_OMAP2)
|
||||
3,
|
||||
#elif defined(CONFIG_ARCH_BCMRING)
|
||||
IRQ_PMUIRQ,
|
||||
#elif defined(CONFIG_MACH_REALVIEW_EB)
|
||||
IRQ_EB11MP_PMU_CPU0,
|
||||
IRQ_EB11MP_PMU_CPU1,
|
||||
IRQ_EB11MP_PMU_CPU2,
|
||||
IRQ_EB11MP_PMU_CPU3,
|
||||
#elif defined(CONFIG_ARCH_OMAP3)
|
||||
INT_34XX_BENCH_MPU_EMUL,
|
||||
#elif defined(CONFIG_ARCH_IOP32X)
|
||||
IRQ_IOP32X_CORE_PMU,
|
||||
#elif defined(CONFIG_ARCH_IOP33X)
|
||||
IRQ_IOP33X_CORE_PMU,
|
||||
#elif defined(CONFIG_ARCH_PXA)
|
||||
IRQ_PMU,
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct pmu_irqs pmu_irqs = {
|
||||
.irqs = irqs,
|
||||
.num_irqs = ARRAY_SIZE(irqs),
|
||||
};
|
||||
|
||||
static volatile long pmu_lock;
|
||||
|
||||
const struct pmu_irqs *
|
||||
reserve_pmu(void)
|
||||
{
|
||||
return test_and_set_bit_lock(0, &pmu_lock) ? ERR_PTR(-EBUSY) :
|
||||
&pmu_irqs;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reserve_pmu);
|
||||
|
||||
int
|
||||
release_pmu(const struct pmu_irqs *irqs)
|
||||
{
|
||||
if (WARN_ON(irqs != &pmu_irqs))
|
||||
return -EINVAL;
|
||||
clear_bit_unlock(0, &pmu_lock);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(release_pmu);
|
||||
|
||||
static int
|
||||
set_irq_affinity(int irq,
|
||||
unsigned int cpu)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
int err = irq_set_affinity(irq, cpumask_of(cpu));
|
||||
if (err)
|
||||
pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",
|
||||
irq, cpu);
|
||||
return err;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
init_pmu(void)
|
||||
{
|
||||
int i, err = 0;
|
||||
|
||||
for (i = 0; i < pmu_irqs.num_irqs; ++i) {
|
||||
err = set_irq_affinity(pmu_irqs.irqs[i], i);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(init_pmu);
|
|
@ -499,10 +499,41 @@ static struct undef_hook thumb_break_hook = {
|
|||
.fn = break_trap,
|
||||
};
|
||||
|
||||
static int thumb2_break_trap(struct pt_regs *regs, unsigned int instr)
|
||||
{
|
||||
unsigned int instr2;
|
||||
void __user *pc;
|
||||
|
||||
/* Check the second half of the instruction. */
|
||||
pc = (void __user *)(instruction_pointer(regs) + 2);
|
||||
|
||||
if (processor_mode(regs) == SVC_MODE) {
|
||||
instr2 = *(u16 *) pc;
|
||||
} else {
|
||||
get_user(instr2, (u16 __user *)pc);
|
||||
}
|
||||
|
||||
if (instr2 == 0xa000) {
|
||||
ptrace_break(current, regs);
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static struct undef_hook thumb2_break_hook = {
|
||||
.instr_mask = 0xffff,
|
||||
.instr_val = 0xf7f0,
|
||||
.cpsr_mask = PSR_T_BIT,
|
||||
.cpsr_val = PSR_T_BIT,
|
||||
.fn = thumb2_break_trap,
|
||||
};
|
||||
|
||||
static int __init ptrace_break_init(void)
|
||||
{
|
||||
register_undef_hook(&arm_break_hook);
|
||||
register_undef_hook(&thumb_break_hook);
|
||||
register_undef_hook(&thumb2_break_hook);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -669,7 +700,7 @@ static int ptrace_getvfpregs(struct task_struct *tsk, void __user *data)
|
|||
union vfp_state *vfp = &thread->vfpstate;
|
||||
struct user_vfp __user *ufp = data;
|
||||
|
||||
vfp_sync_state(thread);
|
||||
vfp_sync_hwstate(thread);
|
||||
|
||||
/* copy the floating point registers */
|
||||
if (copy_to_user(&ufp->fpregs, &vfp->hard.fpregs,
|
||||
|
@ -692,7 +723,7 @@ static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data)
|
|||
union vfp_state *vfp = &thread->vfpstate;
|
||||
struct user_vfp __user *ufp = data;
|
||||
|
||||
vfp_sync_state(thread);
|
||||
vfp_sync_hwstate(thread);
|
||||
|
||||
/* copy the floating point registers */
|
||||
if (copy_from_user(&vfp->hard.fpregs, &ufp->fpregs,
|
||||
|
@ -703,6 +734,8 @@ static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data)
|
|||
if (get_user(vfp->hard.fpscr, &ufp->fpscr))
|
||||
return -EFAULT;
|
||||
|
||||
vfp_flush_hwstate(thread);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -712,26 +745,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
|||
int ret;
|
||||
|
||||
switch (request) {
|
||||
/*
|
||||
* read word at location "addr" in the child process.
|
||||
*/
|
||||
case PTRACE_PEEKTEXT:
|
||||
case PTRACE_PEEKDATA:
|
||||
ret = generic_ptrace_peekdata(child, addr, data);
|
||||
break;
|
||||
|
||||
case PTRACE_PEEKUSR:
|
||||
ret = ptrace_read_user(child, addr, (unsigned long __user *)data);
|
||||
break;
|
||||
|
||||
/*
|
||||
* write the word at location addr.
|
||||
*/
|
||||
case PTRACE_POKETEXT:
|
||||
case PTRACE_POKEDATA:
|
||||
ret = generic_ptrace_pokedata(child, addr, data);
|
||||
break;
|
||||
|
||||
case PTRACE_POKEUSR:
|
||||
ret = ptrace_write_user(child, addr, data);
|
||||
break;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/proc_fs.h>
|
||||
|
||||
#include <asm/unified.h>
|
||||
#include <asm/cpu.h>
|
||||
|
@ -118,7 +119,7 @@ EXPORT_SYMBOL(elf_platform);
|
|||
|
||||
static const char *cpu_name;
|
||||
static const char *machine_name;
|
||||
static char __initdata command_line[COMMAND_LINE_SIZE];
|
||||
static char __initdata cmd_line[COMMAND_LINE_SIZE];
|
||||
|
||||
static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
|
||||
static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
|
||||
|
@ -418,10 +419,11 @@ static int __init arm_add_memory(unsigned long start, unsigned long size)
|
|||
* Pick out the memory size. We look for mem=size@start,
|
||||
* where start and size are "size[KkMm]"
|
||||
*/
|
||||
static void __init early_mem(char **p)
|
||||
static int __init early_mem(char *p)
|
||||
{
|
||||
static int usermem __initdata = 0;
|
||||
unsigned long size, start;
|
||||
char *endp;
|
||||
|
||||
/*
|
||||
* If the user specifies memory size, we
|
||||
|
@ -434,52 +436,15 @@ static void __init early_mem(char **p)
|
|||
}
|
||||
|
||||
start = PHYS_OFFSET;
|
||||
size = memparse(*p, p);
|
||||
if (**p == '@')
|
||||
start = memparse(*p + 1, p);
|
||||
size = memparse(p, &endp);
|
||||
if (*endp == '@')
|
||||
start = memparse(endp + 1, NULL);
|
||||
|
||||
arm_add_memory(start, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
__early_param("mem=", early_mem);
|
||||
|
||||
/*
|
||||
* Initial parsing of the command line.
|
||||
*/
|
||||
static void __init parse_cmdline(char **cmdline_p, char *from)
|
||||
{
|
||||
char c = ' ', *to = command_line;
|
||||
int len = 0;
|
||||
|
||||
for (;;) {
|
||||
if (c == ' ') {
|
||||
extern struct early_params __early_begin, __early_end;
|
||||
struct early_params *p;
|
||||
|
||||
for (p = &__early_begin; p < &__early_end; p++) {
|
||||
int arglen = strlen(p->arg);
|
||||
|
||||
if (memcmp(from, p->arg, arglen) == 0) {
|
||||
if (to != command_line)
|
||||
to -= 1;
|
||||
from += arglen;
|
||||
p->fn(&from);
|
||||
|
||||
while (*from != ' ' && *from != '\0')
|
||||
from++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
c = *from++;
|
||||
if (!c)
|
||||
break;
|
||||
if (COMMAND_LINE_SIZE <= ++len)
|
||||
break;
|
||||
*to++ = c;
|
||||
}
|
||||
*to = '\0';
|
||||
*cmdline_p = command_line;
|
||||
}
|
||||
early_param("mem", early_mem);
|
||||
|
||||
static void __init
|
||||
setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
|
||||
|
@ -740,9 +705,15 @@ void __init setup_arch(char **cmdline_p)
|
|||
init_mm.end_data = (unsigned long) _edata;
|
||||
init_mm.brk = (unsigned long) _end;
|
||||
|
||||
memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
|
||||
boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
|
||||
parse_cmdline(cmdline_p, from);
|
||||
/* parse_early_param needs a boot_command_line */
|
||||
strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
|
||||
|
||||
/* populate cmd_line too for later use, preserving boot_command_line */
|
||||
strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
|
||||
*cmdline_p = cmd_line;
|
||||
|
||||
parse_early_param();
|
||||
|
||||
paging_init(mdesc);
|
||||
request_standard_resources(&meminfo, mdesc);
|
||||
|
||||
|
@ -783,9 +754,21 @@ static int __init topology_init(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
subsys_initcall(topology_init);
|
||||
|
||||
#ifdef CONFIG_HAVE_PROC_CPU
|
||||
static int __init proc_cpu_init(void)
|
||||
{
|
||||
struct proc_dir_entry *res;
|
||||
|
||||
res = proc_mkdir("cpu", NULL);
|
||||
if (!res)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
fs_initcall(proc_cpu_init);
|
||||
#endif
|
||||
|
||||
static const char *hwcap_str[] = {
|
||||
"swp",
|
||||
"half",
|
||||
|
|
|
@ -10,11 +10,6 @@
|
|||
*
|
||||
* This file contains the ARM-specific time handling details:
|
||||
* reading the RTC at bootup, etc...
|
||||
*
|
||||
* 1994-07-02 Alan Modra
|
||||
* fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
|
||||
* 1998-12-20 Updated NTP code according to technical memorandum Jan '96
|
||||
* "A Kernel Model for Precision Timekeeping" by Dave Mills
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
|
@ -77,11 +72,6 @@ unsigned long profile_pc(struct pt_regs *regs)
|
|||
EXPORT_SYMBOL(profile_pc);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* hook for setting the RTC's idea of the current time.
|
||||
*/
|
||||
int (*set_rtc)(void);
|
||||
|
||||
#ifndef CONFIG_GENERIC_TIME
|
||||
static unsigned long dummy_gettimeoffset(void)
|
||||
{
|
||||
|
@ -89,140 +79,6 @@ static unsigned long dummy_gettimeoffset(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
static unsigned long next_rtc_update;
|
||||
|
||||
/*
|
||||
* If we have an externally synchronized linux clock, then update
|
||||
* CMOS clock accordingly every ~11 minutes. set_rtc() has to be
|
||||
* called as close as possible to 500 ms before the new second
|
||||
* starts.
|
||||
*/
|
||||
static inline void do_set_rtc(void)
|
||||
{
|
||||
if (!ntp_synced() || set_rtc == NULL)
|
||||
return;
|
||||
|
||||
if (next_rtc_update &&
|
||||
time_before((unsigned long)xtime.tv_sec, next_rtc_update))
|
||||
return;
|
||||
|
||||
if (xtime.tv_nsec < 500000000 - ((unsigned) tick_nsec >> 1) &&
|
||||
xtime.tv_nsec >= 500000000 + ((unsigned) tick_nsec >> 1))
|
||||
return;
|
||||
|
||||
if (set_rtc())
|
||||
/*
|
||||
* rtc update failed. Try again in 60s
|
||||
*/
|
||||
next_rtc_update = xtime.tv_sec + 60;
|
||||
else
|
||||
next_rtc_update = xtime.tv_sec + 660;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LEDS
|
||||
|
||||
static void dummy_leds_event(led_event_t evt)
|
||||
{
|
||||
}
|
||||
|
||||
void (*leds_event)(led_event_t) = dummy_leds_event;
|
||||
|
||||
struct leds_evt_name {
|
||||
const char name[8];
|
||||
int on;
|
||||
int off;
|
||||
};
|
||||
|
||||
static const struct leds_evt_name evt_names[] = {
|
||||
{ "amber", led_amber_on, led_amber_off },
|
||||
{ "blue", led_blue_on, led_blue_off },
|
||||
{ "green", led_green_on, led_green_off },
|
||||
{ "red", led_red_on, led_red_off },
|
||||
};
|
||||
|
||||
static ssize_t leds_store(struct sys_device *dev,
|
||||
struct sysdev_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int ret = -EINVAL, len = strcspn(buf, " ");
|
||||
|
||||
if (len > 0 && buf[len] == '\0')
|
||||
len--;
|
||||
|
||||
if (strncmp(buf, "claim", len) == 0) {
|
||||
leds_event(led_claim);
|
||||
ret = size;
|
||||
} else if (strncmp(buf, "release", len) == 0) {
|
||||
leds_event(led_release);
|
||||
ret = size;
|
||||
} else {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(evt_names); i++) {
|
||||
if (strlen(evt_names[i].name) != len ||
|
||||
strncmp(buf, evt_names[i].name, len) != 0)
|
||||
continue;
|
||||
if (strncmp(buf+len, " on", 3) == 0) {
|
||||
leds_event(evt_names[i].on);
|
||||
ret = size;
|
||||
} else if (strncmp(buf+len, " off", 4) == 0) {
|
||||
leds_event(evt_names[i].off);
|
||||
ret = size;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static SYSDEV_ATTR(event, 0200, NULL, leds_store);
|
||||
|
||||
static int leds_suspend(struct sys_device *dev, pm_message_t state)
|
||||
{
|
||||
leds_event(led_stop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int leds_resume(struct sys_device *dev)
|
||||
{
|
||||
leds_event(led_start);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int leds_shutdown(struct sys_device *dev)
|
||||
{
|
||||
leds_event(led_halted);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysdev_class leds_sysclass = {
|
||||
.name = "leds",
|
||||
.shutdown = leds_shutdown,
|
||||
.suspend = leds_suspend,
|
||||
.resume = leds_resume,
|
||||
};
|
||||
|
||||
static struct sys_device leds_device = {
|
||||
.id = 0,
|
||||
.cls = &leds_sysclass,
|
||||
};
|
||||
|
||||
static int __init leds_init(void)
|
||||
{
|
||||
int ret;
|
||||
ret = sysdev_class_register(&leds_sysclass);
|
||||
if (ret == 0)
|
||||
ret = sysdev_register(&leds_device);
|
||||
if (ret == 0)
|
||||
ret = sysdev_create_file(&leds_device, &attr_event);
|
||||
return ret;
|
||||
}
|
||||
|
||||
device_initcall(leds_init);
|
||||
|
||||
EXPORT_SYMBOL(leds_event);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LEDS_TIMER
|
||||
static inline void do_leds(void)
|
||||
{
|
||||
|
@ -295,39 +151,6 @@ int do_settimeofday(struct timespec *tv)
|
|||
EXPORT_SYMBOL(do_settimeofday);
|
||||
#endif /* !CONFIG_GENERIC_TIME */
|
||||
|
||||
/**
|
||||
* save_time_delta - Save the offset between system time and RTC time
|
||||
* @delta: pointer to timespec to store delta
|
||||
* @rtc: pointer to timespec for current RTC time
|
||||
*
|
||||
* Return a delta between the system time and the RTC time, such
|
||||
* that system time can be restored later with restore_time_delta()
|
||||
*/
|
||||
void save_time_delta(struct timespec *delta, struct timespec *rtc)
|
||||
{
|
||||
set_normalized_timespec(delta,
|
||||
xtime.tv_sec - rtc->tv_sec,
|
||||
xtime.tv_nsec - rtc->tv_nsec);
|
||||
}
|
||||
EXPORT_SYMBOL(save_time_delta);
|
||||
|
||||
/**
|
||||
* restore_time_delta - Restore the current system time
|
||||
* @delta: delta returned by save_time_delta()
|
||||
* @rtc: pointer to timespec for current RTC time
|
||||
*/
|
||||
void restore_time_delta(struct timespec *delta, struct timespec *rtc)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
set_normalized_timespec(&ts,
|
||||
delta->tv_sec + rtc->tv_sec,
|
||||
delta->tv_nsec + rtc->tv_nsec);
|
||||
|
||||
do_settimeofday(&ts);
|
||||
}
|
||||
EXPORT_SYMBOL(restore_time_delta);
|
||||
|
||||
#ifndef CONFIG_GENERIC_CLOCKEVENTS
|
||||
/*
|
||||
* Kernel system timer support.
|
||||
|
@ -336,7 +159,6 @@ void timer_tick(void)
|
|||
{
|
||||
profile_tick(CPU_PROFILING);
|
||||
do_leds();
|
||||
do_set_rtc();
|
||||
write_seqlock(&xtime_lock);
|
||||
do_timer(1);
|
||||
write_sequnlock(&xtime_lock);
|
||||
|
|
|
@ -12,15 +12,17 @@
|
|||
* 'linux/arch/arm/lib/traps.S'. Mostly a debugging aid, but will probably
|
||||
* kill the offending process.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/personality.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/kdebug.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kexec.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
@ -224,14 +226,21 @@ void show_stack(struct task_struct *tsk, unsigned long *sp)
|
|||
#define S_SMP ""
|
||||
#endif
|
||||
|
||||
static void __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs)
|
||||
static int __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs)
|
||||
{
|
||||
struct task_struct *tsk = thread->task;
|
||||
static int die_counter;
|
||||
int ret;
|
||||
|
||||
printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n",
|
||||
str, err, ++die_counter);
|
||||
sysfs_printk_last_file();
|
||||
|
||||
/* trap and error numbers are mostly meaningless on ARM */
|
||||
ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV);
|
||||
if (ret == NOTIFY_STOP)
|
||||
return ret;
|
||||
|
||||
print_modules();
|
||||
__show_regs(regs);
|
||||
printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n",
|
||||
|
@ -243,6 +252,8 @@ static void __die(const char *str, int err, struct thread_info *thread, struct p
|
|||
dump_backtrace(regs, tsk);
|
||||
dump_instr(KERN_EMERG, regs);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEFINE_SPINLOCK(die_lock);
|
||||
|
@ -250,16 +261,21 @@ DEFINE_SPINLOCK(die_lock);
|
|||
/*
|
||||
* This function is protected against re-entrancy.
|
||||
*/
|
||||
NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
|
||||
void die(const char *str, struct pt_regs *regs, int err)
|
||||
{
|
||||
struct thread_info *thread = current_thread_info();
|
||||
int ret;
|
||||
|
||||
oops_enter();
|
||||
|
||||
spin_lock_irq(&die_lock);
|
||||
console_verbose();
|
||||
bust_spinlocks(1);
|
||||
__die(str, err, thread, regs);
|
||||
ret = __die(str, err, thread, regs);
|
||||
|
||||
if (regs && kexec_should_crash(thread->task))
|
||||
crash_kexec(regs);
|
||||
|
||||
bust_spinlocks(0);
|
||||
add_taint(TAINT_DIE);
|
||||
spin_unlock_irq(&die_lock);
|
||||
|
@ -267,11 +283,10 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
|
|||
|
||||
if (in_interrupt())
|
||||
panic("Fatal exception in interrupt");
|
||||
|
||||
if (panic_on_oops)
|
||||
panic("Fatal exception");
|
||||
|
||||
do_exit(SIGSEGV);
|
||||
if (ret != NOTIFY_STOP)
|
||||
do_exit(SIGSEGV);
|
||||
}
|
||||
|
||||
void arm_notify_die(const char *str, struct pt_regs *regs,
|
||||
|
|
|
@ -43,10 +43,6 @@ SECTIONS
|
|||
|
||||
INIT_SETUP(16)
|
||||
|
||||
__early_begin = .;
|
||||
*(.early_param.init)
|
||||
__early_end = .;
|
||||
|
||||
INIT_CALLS
|
||||
CON_INITCALL
|
||||
SECURITY_INITCALL
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
*/
|
||||
|
||||
#include "hardware.h"
|
||||
.macro addruart,rx
|
||||
.macro addruart, rx, tmp
|
||||
mrc p15, 0, \rx, c1, c0
|
||||
tst \rx, #1 @ MMU enabled?
|
||||
moveq \rx, #0x80000000 @ physical
|
||||
|
|
|
@ -89,6 +89,12 @@ config ARCH_AT91CAP9
|
|||
select GENERIC_CLOCKEVENTS
|
||||
select HAVE_FB_ATMEL
|
||||
|
||||
config ARCH_AT572D940HF
|
||||
bool "AT572D940HF"
|
||||
select CPU_ARM926T
|
||||
select GENERIC_TIME
|
||||
select GENERIC_CLOCKEVENTS
|
||||
|
||||
config ARCH_AT91X40
|
||||
bool "AT91x40"
|
||||
|
||||
|
@ -390,6 +396,23 @@ endif
|
|||
|
||||
# ----------------------------------------------------------
|
||||
|
||||
if ARCH_AT572D940HF
|
||||
|
||||
comment "AT572D940HF Board Type"
|
||||
|
||||
config MACH_AT572D940HFEB
|
||||
bool "AT572D940HF-EK"
|
||||
depends on ARCH_AT572D940HF
|
||||
select HAVE_AT91_DATAFLASH_CARD
|
||||
select HAVE_NAND_ATMEL_BUSWIDTH_16
|
||||
help
|
||||
Select this if you are using Atmel's AT572D940HF-EK evaluation kit.
|
||||
<http://www.atmel.com/products/diopsis/default.asp>
|
||||
|
||||
endif
|
||||
|
||||
# ----------------------------------------------------------
|
||||
|
||||
if ARCH_AT91X40
|
||||
|
||||
comment "AT91X40 Board Type"
|
||||
|
|
|
@ -19,6 +19,7 @@ obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devi
|
|||
obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o
|
||||
obj-$(CONFIG_ARCH_AT91SAM9G45) += at91sam9g45.o at91sam926x_time.o at91sam9g45_devices.o sam9_smc.o
|
||||
obj-$(CONFIG_ARCH_AT91CAP9) += at91cap9.o at91sam926x_time.o at91cap9_devices.o sam9_smc.o
|
||||
obj-$(CONFIG_ARCH_AT572D940HF) += at572d940hf.o at91sam926x_time.o at572d940hf_devices.o sam9_smc.o
|
||||
obj-$(CONFIG_ARCH_AT91X40) += at91x40.o at91x40_time.o
|
||||
|
||||
# AT91RM9200 board-specific support
|
||||
|
@ -69,6 +70,9 @@ obj-$(CONFIG_MACH_AT91SAM9G45EKES) += board-sam9m10g45ek.o
|
|||
# AT91CAP9 board-specific support
|
||||
obj-$(CONFIG_MACH_AT91CAP9ADK) += board-cap9adk.o
|
||||
|
||||
# AT572D940HF board-specific support
|
||||
obj-$(CONFIG_MACH_AT572D940HFEB) += board-at572d940hf_ek.o
|
||||
|
||||
# AT91X40 board-specific support
|
||||
obj-$(CONFIG_MACH_AT91EB01) += board-eb01.o
|
||||
|
||||
|
|
|
@ -0,0 +1,377 @@
|
|||
/*
|
||||
* arch/arm/mach-at91/at572d940hf.c
|
||||
*
|
||||
* Antonio R. Costa <costa.antonior@gmail.com>
|
||||
* Copyright (C) 2008 Atmel
|
||||
*
|
||||
* Copyright (C) 2005 SAN People
|
||||
*
|
||||
* 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/module.h>
|
||||
|
||||
#include <asm/mach/irq.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <mach/at572d940hf.h>
|
||||
#include <mach/at91_pmc.h>
|
||||
#include <mach/at91_rstc.h>
|
||||
|
||||
#include "generic.h"
|
||||
#include "clock.h"
|
||||
|
||||
static struct map_desc at572d940hf_io_desc[] __initdata = {
|
||||
{
|
||||
.virtual = AT91_VA_BASE_SYS,
|
||||
.pfn = __phys_to_pfn(AT91_BASE_SYS),
|
||||
.length = SZ_16K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = AT91_IO_VIRT_BASE - AT572D940HF_SRAM_SIZE,
|
||||
.pfn = __phys_to_pfn(AT572D940HF_SRAM_BASE),
|
||||
.length = AT572D940HF_SRAM_SIZE,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Clocks
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* The peripheral clocks.
|
||||
*/
|
||||
static struct clk pioA_clk = {
|
||||
.name = "pioA_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_PIOA,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk pioB_clk = {
|
||||
.name = "pioB_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_PIOB,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk pioC_clk = {
|
||||
.name = "pioC_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_PIOC,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk macb_clk = {
|
||||
.name = "macb_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_EMAC,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk usart0_clk = {
|
||||
.name = "usart0_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_US0,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk usart1_clk = {
|
||||
.name = "usart1_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_US1,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk usart2_clk = {
|
||||
.name = "usart2_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_US2,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk mmc_clk = {
|
||||
.name = "mci_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_MCI,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk udc_clk = {
|
||||
.name = "udc_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_UDP,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk twi0_clk = {
|
||||
.name = "twi0_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_TWI0,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk spi0_clk = {
|
||||
.name = "spi0_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_SPI0,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk spi1_clk = {
|
||||
.name = "spi1_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_SPI1,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk ssc0_clk = {
|
||||
.name = "ssc0_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_SSC0,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk ssc1_clk = {
|
||||
.name = "ssc1_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_SSC1,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk ssc2_clk = {
|
||||
.name = "ssc2_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_SSC2,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk tc0_clk = {
|
||||
.name = "tc0_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_TC0,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk tc1_clk = {
|
||||
.name = "tc1_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_TC1,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk tc2_clk = {
|
||||
.name = "tc2_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_TC2,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk ohci_clk = {
|
||||
.name = "ohci_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_UHP,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk ssc3_clk = {
|
||||
.name = "ssc3_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_SSC3,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk twi1_clk = {
|
||||
.name = "twi1_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_TWI1,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk can0_clk = {
|
||||
.name = "can0_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_CAN0,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk can1_clk = {
|
||||
.name = "can1_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_CAN1,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk mAgicV_clk = {
|
||||
.name = "mAgicV_clk",
|
||||
.pmc_mask = 1 << AT572D940HF_ID_MSIRQ0,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
|
||||
|
||||
static struct clk *periph_clocks[] __initdata = {
|
||||
&pioA_clk,
|
||||
&pioB_clk,
|
||||
&pioC_clk,
|
||||
&macb_clk,
|
||||
&usart0_clk,
|
||||
&usart1_clk,
|
||||
&usart2_clk,
|
||||
&mmc_clk,
|
||||
&udc_clk,
|
||||
&twi0_clk,
|
||||
&spi0_clk,
|
||||
&spi1_clk,
|
||||
&ssc0_clk,
|
||||
&ssc1_clk,
|
||||
&ssc2_clk,
|
||||
&tc0_clk,
|
||||
&tc1_clk,
|
||||
&tc2_clk,
|
||||
&ohci_clk,
|
||||
&ssc3_clk,
|
||||
&twi1_clk,
|
||||
&can0_clk,
|
||||
&can1_clk,
|
||||
&mAgicV_clk,
|
||||
/* irq0 .. irq2 */
|
||||
};
|
||||
|
||||
/*
|
||||
* The five programmable clocks.
|
||||
* You must configure pin multiplexing to bring these signals out.
|
||||
*/
|
||||
static struct clk pck0 = {
|
||||
.name = "pck0",
|
||||
.pmc_mask = AT91_PMC_PCK0,
|
||||
.type = CLK_TYPE_PROGRAMMABLE,
|
||||
.id = 0,
|
||||
};
|
||||
static struct clk pck1 = {
|
||||
.name = "pck1",
|
||||
.pmc_mask = AT91_PMC_PCK1,
|
||||
.type = CLK_TYPE_PROGRAMMABLE,
|
||||
.id = 1,
|
||||
};
|
||||
static struct clk pck2 = {
|
||||
.name = "pck2",
|
||||
.pmc_mask = AT91_PMC_PCK2,
|
||||
.type = CLK_TYPE_PROGRAMMABLE,
|
||||
.id = 2,
|
||||
};
|
||||
static struct clk pck3 = {
|
||||
.name = "pck3",
|
||||
.pmc_mask = AT91_PMC_PCK3,
|
||||
.type = CLK_TYPE_PROGRAMMABLE,
|
||||
.id = 3,
|
||||
};
|
||||
|
||||
static struct clk mAgicV_mem_clk = {
|
||||
.name = "mAgicV_mem_clk",
|
||||
.pmc_mask = AT91_PMC_PCK4,
|
||||
.type = CLK_TYPE_PROGRAMMABLE,
|
||||
.id = 4,
|
||||
};
|
||||
|
||||
/* HClocks */
|
||||
static struct clk hck0 = {
|
||||
.name = "hck0",
|
||||
.pmc_mask = AT91_PMC_HCK0,
|
||||
.type = CLK_TYPE_SYSTEM,
|
||||
.id = 0,
|
||||
};
|
||||
static struct clk hck1 = {
|
||||
.name = "hck1",
|
||||
.pmc_mask = AT91_PMC_HCK1,
|
||||
.type = CLK_TYPE_SYSTEM,
|
||||
.id = 1,
|
||||
};
|
||||
|
||||
static void __init at572d940hf_register_clocks(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
|
||||
clk_register(periph_clocks[i]);
|
||||
|
||||
clk_register(&pck0);
|
||||
clk_register(&pck1);
|
||||
clk_register(&pck2);
|
||||
clk_register(&pck3);
|
||||
clk_register(&mAgicV_mem_clk);
|
||||
|
||||
clk_register(&hck0);
|
||||
clk_register(&hck1);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* GPIO
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
static struct at91_gpio_bank at572d940hf_gpio[] = {
|
||||
{
|
||||
.id = AT572D940HF_ID_PIOA,
|
||||
.offset = AT91_PIOA,
|
||||
.clock = &pioA_clk,
|
||||
}, {
|
||||
.id = AT572D940HF_ID_PIOB,
|
||||
.offset = AT91_PIOB,
|
||||
.clock = &pioB_clk,
|
||||
}, {
|
||||
.id = AT572D940HF_ID_PIOC,
|
||||
.offset = AT91_PIOC,
|
||||
.clock = &pioC_clk,
|
||||
}
|
||||
};
|
||||
|
||||
static void at572d940hf_reset(void)
|
||||
{
|
||||
at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* AT572D940HF processor initialization
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
void __init at572d940hf_initialize(unsigned long main_clock)
|
||||
{
|
||||
/* Map peripherals */
|
||||
iotable_init(at572d940hf_io_desc, ARRAY_SIZE(at572d940hf_io_desc));
|
||||
|
||||
at91_arch_reset = at572d940hf_reset;
|
||||
at91_extern_irq = (1 << AT572D940HF_ID_IRQ0) | (1 << AT572D940HF_ID_IRQ1)
|
||||
| (1 << AT572D940HF_ID_IRQ2);
|
||||
|
||||
/* Init clock subsystem */
|
||||
at91_clock_init(main_clock);
|
||||
|
||||
/* Register the processor-specific clocks */
|
||||
at572d940hf_register_clocks();
|
||||
|
||||
/* Register GPIO subsystem */
|
||||
at91_gpio_init(at572d940hf_gpio, 3);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Interrupt initialization
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* The default interrupt priority levels (0 = lowest, 7 = highest).
|
||||
*/
|
||||
static unsigned int at572d940hf_default_irq_priority[NR_AIC_IRQS] __initdata = {
|
||||
7, /* Advanced Interrupt Controller */
|
||||
7, /* System Peripherals */
|
||||
0, /* Parallel IO Controller A */
|
||||
0, /* Parallel IO Controller B */
|
||||
0, /* Parallel IO Controller C */
|
||||
3, /* Ethernet */
|
||||
6, /* USART 0 */
|
||||
6, /* USART 1 */
|
||||
6, /* USART 2 */
|
||||
0, /* Multimedia Card Interface */
|
||||
4, /* USB Device Port */
|
||||
0, /* Two-Wire Interface 0 */
|
||||
6, /* Serial Peripheral Interface 0 */
|
||||
6, /* Serial Peripheral Interface 1 */
|
||||
5, /* Serial Synchronous Controller 0 */
|
||||
5, /* Serial Synchronous Controller 1 */
|
||||
5, /* Serial Synchronous Controller 2 */
|
||||
0, /* Timer Counter 0 */
|
||||
0, /* Timer Counter 1 */
|
||||
0, /* Timer Counter 2 */
|
||||
3, /* USB Host port */
|
||||
3, /* Serial Synchronous Controller 3 */
|
||||
0, /* Two-Wire Interface 1 */
|
||||
0, /* CAN Controller 0 */
|
||||
0, /* CAN Controller 1 */
|
||||
0, /* mAgicV HALT line */
|
||||
0, /* mAgicV SIRQ0 line */
|
||||
0, /* mAgicV exception line */
|
||||
0, /* mAgicV end of DMA line */
|
||||
0, /* Advanced Interrupt Controller */
|
||||
0, /* Advanced Interrupt Controller */
|
||||
0, /* Advanced Interrupt Controller */
|
||||
};
|
||||
|
||||
void __init at572d940hf_init_interrupts(unsigned int priority[NR_AIC_IRQS])
|
||||
{
|
||||
if (!priority)
|
||||
priority = at572d940hf_default_irq_priority;
|
||||
|
||||
/* Initialize the AIC interrupt controller */
|
||||
at91_aic_init(priority);
|
||||
|
||||
/* Enable GPIO interrupts */
|
||||
at91_gpio_irq_setup();
|
||||
}
|
||||
|
|
@ -0,0 +1,970 @@
|
|||
/*
|
||||
* arch/arm/mach-at91/at572d940hf_devices.c
|
||||
*
|
||||
* Copyright (C) 2008 Atmel Antonio R. Costa <costa.antonior@gmail.com>
|
||||
* Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
|
||||
* Copyright (C) 2005 David Brownell
|
||||
*
|
||||
* 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 <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <mach/board.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/at572d940hf.h>
|
||||
#include <mach/at572d940hf_matrix.h>
|
||||
#include <mach/at91sam9_smc.h>
|
||||
|
||||
#include "generic.h"
|
||||
#include "sam9_smc.h"
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* USB Host
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
|
||||
static u64 ohci_dmamask = DMA_BIT_MASK(32);
|
||||
static struct at91_usbh_data usbh_data;
|
||||
|
||||
static struct resource usbh_resources[] = {
|
||||
[0] = {
|
||||
.start = AT572D940HF_UHP_BASE,
|
||||
.end = AT572D940HF_UHP_BASE + SZ_1M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = AT572D940HF_ID_UHP,
|
||||
.end = AT572D940HF_ID_UHP,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device at572d940hf_usbh_device = {
|
||||
.name = "at91_ohci",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.dma_mask = &ohci_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = &usbh_data,
|
||||
},
|
||||
.resource = usbh_resources,
|
||||
.num_resources = ARRAY_SIZE(usbh_resources),
|
||||
};
|
||||
|
||||
void __init at91_add_device_usbh(struct at91_usbh_data *data)
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
usbh_data = *data;
|
||||
platform_device_register(&at572d940hf_usbh_device);
|
||||
|
||||
}
|
||||
#else
|
||||
void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
|
||||
#endif
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* USB Device (Gadget)
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_AT91
|
||||
static struct at91_udc_data udc_data;
|
||||
|
||||
static struct resource udc_resources[] = {
|
||||
[0] = {
|
||||
.start = AT572D940HF_BASE_UDP,
|
||||
.end = AT572D940HF_BASE_UDP + SZ_16K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = AT572D940HF_ID_UDP,
|
||||
.end = AT572D940HF_ID_UDP,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device at572d940hf_udc_device = {
|
||||
.name = "at91_udc",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &udc_data,
|
||||
},
|
||||
.resource = udc_resources,
|
||||
.num_resources = ARRAY_SIZE(udc_resources),
|
||||
};
|
||||
|
||||
void __init at91_add_device_udc(struct at91_udc_data *data)
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
if (data->vbus_pin) {
|
||||
at91_set_gpio_input(data->vbus_pin, 0);
|
||||
at91_set_deglitch(data->vbus_pin, 1);
|
||||
}
|
||||
|
||||
/* Pullup pin is handled internally */
|
||||
|
||||
udc_data = *data;
|
||||
platform_device_register(&at572d940hf_udc_device);
|
||||
}
|
||||
#else
|
||||
void __init at91_add_device_udc(struct at91_udc_data *data) {}
|
||||
#endif
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Ethernet
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
|
||||
static u64 eth_dmamask = DMA_BIT_MASK(32);
|
||||
static struct at91_eth_data eth_data;
|
||||
|
||||
static struct resource eth_resources[] = {
|
||||
[0] = {
|
||||
.start = AT572D940HF_BASE_EMAC,
|
||||
.end = AT572D940HF_BASE_EMAC + SZ_16K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = AT572D940HF_ID_EMAC,
|
||||
.end = AT572D940HF_ID_EMAC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device at572d940hf_eth_device = {
|
||||
.name = "macb",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.dma_mask = ð_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = ð_data,
|
||||
},
|
||||
.resource = eth_resources,
|
||||
.num_resources = ARRAY_SIZE(eth_resources),
|
||||
};
|
||||
|
||||
void __init at91_add_device_eth(struct at91_eth_data *data)
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
if (data->phy_irq_pin) {
|
||||
at91_set_gpio_input(data->phy_irq_pin, 0);
|
||||
at91_set_deglitch(data->phy_irq_pin, 1);
|
||||
}
|
||||
|
||||
/* Only RMII is supported */
|
||||
data->is_rmii = 1;
|
||||
|
||||
/* Pins used for RMII */
|
||||
at91_set_A_periph(AT91_PIN_PA16, 0); /* ETXCK_EREFCK */
|
||||
at91_set_A_periph(AT91_PIN_PA17, 0); /* ERXDV */
|
||||
at91_set_A_periph(AT91_PIN_PA18, 0); /* ERX0 */
|
||||
at91_set_A_periph(AT91_PIN_PA19, 0); /* ERX1 */
|
||||
at91_set_A_periph(AT91_PIN_PA20, 0); /* ERXER */
|
||||
at91_set_A_periph(AT91_PIN_PA23, 0); /* ETXEN */
|
||||
at91_set_A_periph(AT91_PIN_PA21, 0); /* ETX0 */
|
||||
at91_set_A_periph(AT91_PIN_PA22, 0); /* ETX1 */
|
||||
at91_set_A_periph(AT91_PIN_PA13, 0); /* EMDIO */
|
||||
at91_set_A_periph(AT91_PIN_PA14, 0); /* EMDC */
|
||||
|
||||
eth_data = *data;
|
||||
platform_device_register(&at572d940hf_eth_device);
|
||||
}
|
||||
#else
|
||||
void __init at91_add_device_eth(struct at91_eth_data *data) {}
|
||||
#endif
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* MMC / SD
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
|
||||
static u64 mmc_dmamask = DMA_BIT_MASK(32);
|
||||
static struct at91_mmc_data mmc_data;
|
||||
|
||||
static struct resource mmc_resources[] = {
|
||||
[0] = {
|
||||
.start = AT572D940HF_BASE_MCI,
|
||||
.end = AT572D940HF_BASE_MCI + SZ_16K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = AT572D940HF_ID_MCI,
|
||||
.end = AT572D940HF_ID_MCI,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device at572d940hf_mmc_device = {
|
||||
.name = "at91_mci",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.dma_mask = &mmc_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = &mmc_data,
|
||||
},
|
||||
.resource = mmc_resources,
|
||||
.num_resources = ARRAY_SIZE(mmc_resources),
|
||||
};
|
||||
|
||||
void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
/* input/irq */
|
||||
if (data->det_pin) {
|
||||
at91_set_gpio_input(data->det_pin, 1);
|
||||
at91_set_deglitch(data->det_pin, 1);
|
||||
}
|
||||
if (data->wp_pin)
|
||||
at91_set_gpio_input(data->wp_pin, 1);
|
||||
if (data->vcc_pin)
|
||||
at91_set_gpio_output(data->vcc_pin, 0);
|
||||
|
||||
/* CLK */
|
||||
at91_set_A_periph(AT91_PIN_PC22, 0);
|
||||
|
||||
/* CMD */
|
||||
at91_set_A_periph(AT91_PIN_PC23, 1);
|
||||
|
||||
/* DAT0, maybe DAT1..DAT3 */
|
||||
at91_set_A_periph(AT91_PIN_PC24, 1);
|
||||
if (data->wire4) {
|
||||
at91_set_A_periph(AT91_PIN_PC25, 1);
|
||||
at91_set_A_periph(AT91_PIN_PC26, 1);
|
||||
at91_set_A_periph(AT91_PIN_PC27, 1);
|
||||
}
|
||||
|
||||
mmc_data = *data;
|
||||
platform_device_register(&at572d940hf_mmc_device);
|
||||
}
|
||||
#else
|
||||
void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
|
||||
#endif
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* NAND / SmartMedia
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE)
|
||||
static struct atmel_nand_data nand_data;
|
||||
|
||||
#define NAND_BASE AT91_CHIPSELECT_3
|
||||
|
||||
static struct resource nand_resources[] = {
|
||||
{
|
||||
.start = NAND_BASE,
|
||||
.end = NAND_BASE + SZ_256M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device at572d940hf_nand_device = {
|
||||
.name = "atmel_nand",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &nand_data,
|
||||
},
|
||||
.resource = nand_resources,
|
||||
.num_resources = ARRAY_SIZE(nand_resources),
|
||||
};
|
||||
|
||||
void __init at91_add_device_nand(struct atmel_nand_data *data)
|
||||
{
|
||||
unsigned long csa;
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
csa = at91_sys_read(AT91_MATRIX_EBICSA);
|
||||
at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC_SMARTMEDIA);
|
||||
|
||||
/* enable pin */
|
||||
if (data->enable_pin)
|
||||
at91_set_gpio_output(data->enable_pin, 1);
|
||||
|
||||
/* ready/busy pin */
|
||||
if (data->rdy_pin)
|
||||
at91_set_gpio_input(data->rdy_pin, 1);
|
||||
|
||||
/* card detect pin */
|
||||
if (data->det_pin)
|
||||
at91_set_gpio_input(data->det_pin, 1);
|
||||
|
||||
at91_set_A_periph(AT91_PIN_PB28, 0); /* A[22] */
|
||||
at91_set_B_periph(AT91_PIN_PA28, 0); /* NANDOE */
|
||||
at91_set_B_periph(AT91_PIN_PA29, 0); /* NANDWE */
|
||||
|
||||
nand_data = *data;
|
||||
platform_device_register(&at572d940hf_nand_device);
|
||||
}
|
||||
|
||||
#else
|
||||
void __init at91_add_device_nand(struct atmel_nand_data *data) {}
|
||||
#endif
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* TWI (i2c)
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Prefer the GPIO code since the TWI controller isn't robust
|
||||
* (gets overruns and underruns under load) and can only issue
|
||||
* repeated STARTs in one scenario (the driver doesn't yet handle them).
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
|
||||
|
||||
static struct i2c_gpio_platform_data pdata = {
|
||||
.sda_pin = AT91_PIN_PC7,
|
||||
.sda_is_open_drain = 1,
|
||||
.scl_pin = AT91_PIN_PC8,
|
||||
.scl_is_open_drain = 1,
|
||||
.udelay = 2, /* ~100 kHz */
|
||||
};
|
||||
|
||||
static struct platform_device at572d940hf_twi_device {
|
||||
.name = "i2c-gpio",
|
||||
.id = -1,
|
||||
.dev.platform_data = &pdata,
|
||||
};
|
||||
|
||||
void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
|
||||
{
|
||||
at91_set_GPIO_periph(AT91_PIN_PC7, 1); /* TWD (SDA) */
|
||||
at91_set_multi_drive(AT91_PIN_PC7, 1);
|
||||
|
||||
at91_set_GPIO_periph(AT91_PIN_PA8, 1); /* TWCK (SCL) */
|
||||
at91_set_multi_drive(AT91_PIN_PC8, 1);
|
||||
|
||||
i2c_register_board_info(0, devices, nr_devices);
|
||||
platform_device_register(&at572d940hf_twi_device);
|
||||
}
|
||||
|
||||
#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
|
||||
|
||||
static struct resource twi0_resources[] = {
|
||||
[0] = {
|
||||
.start = AT572D940HF_BASE_TWI0,
|
||||
.end = AT572D940HF_BASE_TWI0 + SZ_16K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = AT572D940HF_ID_TWI0,
|
||||
.end = AT572D940HF_ID_TWI0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device at572d940hf_twi0_device = {
|
||||
.name = "at91_i2c",
|
||||
.id = 0,
|
||||
.resource = twi0_resources,
|
||||
.num_resources = ARRAY_SIZE(twi0_resources),
|
||||
};
|
||||
|
||||
static struct resource twi1_resources[] = {
|
||||
[0] = {
|
||||
.start = AT572D940HF_BASE_TWI1,
|
||||
.end = AT572D940HF_BASE_TWI1 + SZ_16K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = AT572D940HF_ID_TWI1,
|
||||
.end = AT572D940HF_ID_TWI1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device at572d940hf_twi1_device = {
|
||||
.name = "at91_i2c",
|
||||
.id = 1,
|
||||
.resource = twi1_resources,
|
||||
.num_resources = ARRAY_SIZE(twi1_resources),
|
||||
};
|
||||
|
||||
void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
|
||||
{
|
||||
/* pins used for TWI0 interface */
|
||||
at91_set_A_periph(AT91_PIN_PC7, 0); /* TWD */
|
||||
at91_set_multi_drive(AT91_PIN_PC7, 1);
|
||||
|
||||
at91_set_A_periph(AT91_PIN_PC8, 0); /* TWCK */
|
||||
at91_set_multi_drive(AT91_PIN_PC8, 1);
|
||||
|
||||
/* pins used for TWI1 interface */
|
||||
at91_set_A_periph(AT91_PIN_PC20, 0); /* TWD */
|
||||
at91_set_multi_drive(AT91_PIN_PC20, 1);
|
||||
|
||||
at91_set_A_periph(AT91_PIN_PC21, 0); /* TWCK */
|
||||
at91_set_multi_drive(AT91_PIN_PC21, 1);
|
||||
|
||||
i2c_register_board_info(0, devices, nr_devices);
|
||||
platform_device_register(&at572d940hf_twi0_device);
|
||||
platform_device_register(&at572d940hf_twi1_device);
|
||||
}
|
||||
#else
|
||||
void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) {}
|
||||
#endif
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* SPI
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
|
||||
static u64 spi_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
static struct resource spi0_resources[] = {
|
||||
[0] = {
|
||||
.start = AT572D940HF_BASE_SPI0,
|
||||
.end = AT572D940HF_BASE_SPI0 + SZ_16K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = AT572D940HF_ID_SPI0,
|
||||
.end = AT572D940HF_ID_SPI0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device at572d940hf_spi0_device = {
|
||||
.name = "atmel_spi",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &spi_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
},
|
||||
.resource = spi0_resources,
|
||||
.num_resources = ARRAY_SIZE(spi0_resources),
|
||||
};
|
||||
|
||||
static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 };
|
||||
|
||||
static struct resource spi1_resources[] = {
|
||||
[0] = {
|
||||
.start = AT572D940HF_BASE_SPI1,
|
||||
.end = AT572D940HF_BASE_SPI1 + SZ_16K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = AT572D940HF_ID_SPI1,
|
||||
.end = AT572D940HF_ID_SPI1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device at572d940hf_spi1_device = {
|
||||
.name = "atmel_spi",
|
||||
.id = 1,
|
||||
.dev = {
|
||||
.dma_mask = &spi_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
},
|
||||
.resource = spi1_resources,
|
||||
.num_resources = ARRAY_SIZE(spi1_resources),
|
||||
};
|
||||
|
||||
static const unsigned spi1_standard_cs[4] = { AT91_PIN_PC3, AT91_PIN_PC4, AT91_PIN_PC5, AT91_PIN_PC6 };
|
||||
|
||||
void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
|
||||
{
|
||||
int i;
|
||||
unsigned long cs_pin;
|
||||
short enable_spi0 = 0;
|
||||
short enable_spi1 = 0;
|
||||
|
||||
/* Choose SPI chip-selects */
|
||||
for (i = 0; i < nr_devices; i++) {
|
||||
if (devices[i].controller_data)
|
||||
cs_pin = (unsigned long) devices[i].controller_data;
|
||||
else if (devices[i].bus_num == 0)
|
||||
cs_pin = spi0_standard_cs[devices[i].chip_select];
|
||||
else
|
||||
cs_pin = spi1_standard_cs[devices[i].chip_select];
|
||||
|
||||
if (devices[i].bus_num == 0)
|
||||
enable_spi0 = 1;
|
||||
else
|
||||
enable_spi1 = 1;
|
||||
|
||||
/* enable chip-select pin */
|
||||
at91_set_gpio_output(cs_pin, 1);
|
||||
|
||||
/* pass chip-select pin to driver */
|
||||
devices[i].controller_data = (void *) cs_pin;
|
||||
}
|
||||
|
||||
spi_register_board_info(devices, nr_devices);
|
||||
|
||||
/* Configure SPI bus(es) */
|
||||
if (enable_spi0) {
|
||||
at91_set_A_periph(AT91_PIN_PA0, 0); /* SPI0_MISO */
|
||||
at91_set_A_periph(AT91_PIN_PA1, 0); /* SPI0_MOSI */
|
||||
at91_set_A_periph(AT91_PIN_PA2, 0); /* SPI0_SPCK */
|
||||
|
||||
at91_clock_associate("spi0_clk", &at572d940hf_spi0_device.dev, "spi_clk");
|
||||
platform_device_register(&at572d940hf_spi0_device);
|
||||
}
|
||||
if (enable_spi1) {
|
||||
at91_set_A_periph(AT91_PIN_PC0, 0); /* SPI1_MISO */
|
||||
at91_set_A_periph(AT91_PIN_PC1, 0); /* SPI1_MOSI */
|
||||
at91_set_A_periph(AT91_PIN_PC2, 0); /* SPI1_SPCK */
|
||||
|
||||
at91_clock_associate("spi1_clk", &at572d940hf_spi1_device.dev, "spi_clk");
|
||||
platform_device_register(&at572d940hf_spi1_device);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
|
||||
#endif
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Timer/Counter blocks
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#ifdef CONFIG_ATMEL_TCLIB
|
||||
|
||||
static struct resource tcb_resources[] = {
|
||||
[0] = {
|
||||
.start = AT572D940HF_BASE_TCB,
|
||||
.end = AT572D940HF_BASE_TCB + SZ_16K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = AT572D940HF_ID_TC0,
|
||||
.end = AT572D940HF_ID_TC0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
[2] = {
|
||||
.start = AT572D940HF_ID_TC1,
|
||||
.end = AT572D940HF_ID_TC1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
[3] = {
|
||||
.start = AT572D940HF_ID_TC2,
|
||||
.end = AT572D940HF_ID_TC2,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device at572d940hf_tcb_device = {
|
||||
.name = "atmel_tcb",
|
||||
.id = 0,
|
||||
.resource = tcb_resources,
|
||||
.num_resources = ARRAY_SIZE(tcb_resources),
|
||||
};
|
||||
|
||||
static void __init at91_add_device_tc(void)
|
||||
{
|
||||
/* this chip has a separate clock and irq for each TC channel */
|
||||
at91_clock_associate("tc0_clk", &at572d940hf_tcb_device.dev, "t0_clk");
|
||||
at91_clock_associate("tc1_clk", &at572d940hf_tcb_device.dev, "t1_clk");
|
||||
at91_clock_associate("tc2_clk", &at572d940hf_tcb_device.dev, "t2_clk");
|
||||
platform_device_register(&at572d940hf_tcb_device);
|
||||
}
|
||||
#else
|
||||
static void __init at91_add_device_tc(void) { }
|
||||
#endif
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* RTT
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
static struct resource rtt_resources[] = {
|
||||
{
|
||||
.start = AT91_BASE_SYS + AT91_RTT,
|
||||
.end = AT91_BASE_SYS + AT91_RTT + SZ_16 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device at572d940hf_rtt_device = {
|
||||
.name = "at91_rtt",
|
||||
.id = 0,
|
||||
.resource = rtt_resources,
|
||||
.num_resources = ARRAY_SIZE(rtt_resources),
|
||||
};
|
||||
|
||||
static void __init at91_add_device_rtt(void)
|
||||
{
|
||||
platform_device_register(&at572d940hf_rtt_device);
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Watchdog
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
|
||||
static struct platform_device at572d940hf_wdt_device = {
|
||||
.name = "at91_wdt",
|
||||
.id = -1,
|
||||
.num_resources = 0,
|
||||
};
|
||||
|
||||
static void __init at91_add_device_watchdog(void)
|
||||
{
|
||||
platform_device_register(&at572d940hf_wdt_device);
|
||||
}
|
||||
#else
|
||||
static void __init at91_add_device_watchdog(void) {}
|
||||
#endif
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* UART
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#if defined(CONFIG_SERIAL_ATMEL)
|
||||
static struct resource dbgu_resources[] = {
|
||||
[0] = {
|
||||
.start = AT91_VA_BASE_SYS + AT91_DBGU,
|
||||
.end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = AT91_ID_SYS,
|
||||
.end = AT91_ID_SYS,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct atmel_uart_data dbgu_data = {
|
||||
.use_dma_tx = 0,
|
||||
.use_dma_rx = 0, /* DBGU not capable of receive DMA */
|
||||
.regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
|
||||
};
|
||||
|
||||
static u64 dbgu_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
static struct platform_device at572d940hf_dbgu_device = {
|
||||
.name = "atmel_usart",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &dbgu_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = &dbgu_data,
|
||||
},
|
||||
.resource = dbgu_resources,
|
||||
.num_resources = ARRAY_SIZE(dbgu_resources),
|
||||
};
|
||||
|
||||
static inline void configure_dbgu_pins(void)
|
||||
{
|
||||
at91_set_A_periph(AT91_PIN_PC31, 1); /* DTXD */
|
||||
at91_set_A_periph(AT91_PIN_PC30, 0); /* DRXD */
|
||||
}
|
||||
|
||||
static struct resource uart0_resources[] = {
|
||||
[0] = {
|
||||
.start = AT572D940HF_BASE_US0,
|
||||
.end = AT572D940HF_BASE_US0 + SZ_16K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = AT572D940HF_ID_US0,
|
||||
.end = AT572D940HF_ID_US0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct atmel_uart_data uart0_data = {
|
||||
.use_dma_tx = 1,
|
||||
.use_dma_rx = 1,
|
||||
};
|
||||
|
||||
static u64 uart0_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
static struct platform_device at572d940hf_uart0_device = {
|
||||
.name = "atmel_usart",
|
||||
.id = 1,
|
||||
.dev = {
|
||||
.dma_mask = &uart0_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = &uart0_data,
|
||||
},
|
||||
.resource = uart0_resources,
|
||||
.num_resources = ARRAY_SIZE(uart0_resources),
|
||||
};
|
||||
|
||||
static inline void configure_usart0_pins(unsigned pins)
|
||||
{
|
||||
at91_set_A_periph(AT91_PIN_PA8, 1); /* TXD0 */
|
||||
at91_set_A_periph(AT91_PIN_PA7, 0); /* RXD0 */
|
||||
|
||||
if (pins & ATMEL_UART_RTS)
|
||||
at91_set_A_periph(AT91_PIN_PA10, 0); /* RTS0 */
|
||||
if (pins & ATMEL_UART_CTS)
|
||||
at91_set_A_periph(AT91_PIN_PA9, 0); /* CTS0 */
|
||||
}
|
||||
|
||||
static struct resource uart1_resources[] = {
|
||||
[0] = {
|
||||
.start = AT572D940HF_BASE_US1,
|
||||
.end = AT572D940HF_BASE_US1 + SZ_16K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = AT572D940HF_ID_US1,
|
||||
.end = AT572D940HF_ID_US1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct atmel_uart_data uart1_data = {
|
||||
.use_dma_tx = 1,
|
||||
.use_dma_rx = 1,
|
||||
};
|
||||
|
||||
static u64 uart1_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
static struct platform_device at572d940hf_uart1_device = {
|
||||
.name = "atmel_usart",
|
||||
.id = 2,
|
||||
.dev = {
|
||||
.dma_mask = &uart1_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = &uart1_data,
|
||||
},
|
||||
.resource = uart1_resources,
|
||||
.num_resources = ARRAY_SIZE(uart1_resources),
|
||||
};
|
||||
|
||||
static inline void configure_usart1_pins(unsigned pins)
|
||||
{
|
||||
at91_set_A_periph(AT91_PIN_PC10, 1); /* TXD1 */
|
||||
at91_set_A_periph(AT91_PIN_PC9 , 0); /* RXD1 */
|
||||
|
||||
if (pins & ATMEL_UART_RTS)
|
||||
at91_set_A_periph(AT91_PIN_PC12, 0); /* RTS1 */
|
||||
if (pins & ATMEL_UART_CTS)
|
||||
at91_set_A_periph(AT91_PIN_PC11, 0); /* CTS1 */
|
||||
}
|
||||
|
||||
static struct resource uart2_resources[] = {
|
||||
[0] = {
|
||||
.start = AT572D940HF_BASE_US2,
|
||||
.end = AT572D940HF_BASE_US2 + SZ_16K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = AT572D940HF_ID_US2,
|
||||
.end = AT572D940HF_ID_US2,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct atmel_uart_data uart2_data = {
|
||||
.use_dma_tx = 1,
|
||||
.use_dma_rx = 1,
|
||||
};
|
||||
|
||||
static u64 uart2_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
static struct platform_device at572d940hf_uart2_device = {
|
||||
.name = "atmel_usart",
|
||||
.id = 3,
|
||||
.dev = {
|
||||
.dma_mask = &uart2_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = &uart2_data,
|
||||
},
|
||||
.resource = uart2_resources,
|
||||
.num_resources = ARRAY_SIZE(uart2_resources),
|
||||
};
|
||||
|
||||
static inline void configure_usart2_pins(unsigned pins)
|
||||
{
|
||||
at91_set_A_periph(AT91_PIN_PC15, 1); /* TXD2 */
|
||||
at91_set_A_periph(AT91_PIN_PC14, 0); /* RXD2 */
|
||||
|
||||
if (pins & ATMEL_UART_RTS)
|
||||
at91_set_A_periph(AT91_PIN_PC17, 0); /* RTS2 */
|
||||
if (pins & ATMEL_UART_CTS)
|
||||
at91_set_A_periph(AT91_PIN_PC16, 0); /* CTS2 */
|
||||
}
|
||||
|
||||
static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
|
||||
struct platform_device *atmel_default_console_device; /* the serial console device */
|
||||
|
||||
void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
|
||||
switch (id) {
|
||||
case 0: /* DBGU */
|
||||
pdev = &at572d940hf_dbgu_device;
|
||||
configure_dbgu_pins();
|
||||
at91_clock_associate("mck", &pdev->dev, "usart");
|
||||
break;
|
||||
case AT572D940HF_ID_US0:
|
||||
pdev = &at572d940hf_uart0_device;
|
||||
configure_usart0_pins(pins);
|
||||
at91_clock_associate("usart0_clk", &pdev->dev, "usart");
|
||||
break;
|
||||
case AT572D940HF_ID_US1:
|
||||
pdev = &at572d940hf_uart1_device;
|
||||
configure_usart1_pins(pins);
|
||||
at91_clock_associate("usart1_clk", &pdev->dev, "usart");
|
||||
break;
|
||||
case AT572D940HF_ID_US2:
|
||||
pdev = &at572d940hf_uart2_device;
|
||||
configure_usart2_pins(pins);
|
||||
at91_clock_associate("usart2_clk", &pdev->dev, "usart");
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
pdev->id = portnr; /* update to mapped ID */
|
||||
|
||||
if (portnr < ATMEL_MAX_UART)
|
||||
at91_uarts[portnr] = pdev;
|
||||
}
|
||||
|
||||
void __init at91_set_serial_console(unsigned portnr)
|
||||
{
|
||||
if (portnr < ATMEL_MAX_UART)
|
||||
atmel_default_console_device = at91_uarts[portnr];
|
||||
}
|
||||
|
||||
void __init at91_add_device_serial(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ATMEL_MAX_UART; i++) {
|
||||
if (at91_uarts[i])
|
||||
platform_device_register(at91_uarts[i]);
|
||||
}
|
||||
|
||||
if (!atmel_default_console_device)
|
||||
printk(KERN_INFO "AT91: No default serial console defined.\n");
|
||||
}
|
||||
|
||||
#else
|
||||
void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
|
||||
void __init at91_set_serial_console(unsigned portnr) {}
|
||||
void __init at91_add_device_serial(void) {}
|
||||
#endif
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* mAgic
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#ifdef CONFIG_MAGICV
|
||||
static struct resource mAgic_resources[] = {
|
||||
{
|
||||
.start = AT91_MAGIC_PM_BASE,
|
||||
.end = AT91_MAGIC_PM_BASE + AT91_MAGIC_PM_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = AT91_MAGIC_DM_I_BASE,
|
||||
.end = AT91_MAGIC_DM_I_BASE + AT91_MAGIC_DM_I_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = AT91_MAGIC_DM_F_BASE,
|
||||
.end = AT91_MAGIC_DM_F_BASE + AT91_MAGIC_DM_F_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = AT91_MAGIC_DM_DB_BASE,
|
||||
.end = AT91_MAGIC_DM_DB_BASE + AT91_MAGIC_DM_DB_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = AT91_MAGIC_REGS_BASE,
|
||||
.end = AT91_MAGIC_REGS_BASE + AT91_MAGIC_REGS_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = AT91_MAGIC_EXTPAGE_BASE,
|
||||
.end = AT91_MAGIC_EXTPAGE_BASE + AT91_MAGIC_EXTPAGE_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = AT572D940HF_ID_MSIRQ0,
|
||||
.end = AT572D940HF_ID_MSIRQ0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AT572D940HF_ID_MHALT,
|
||||
.end = AT572D940HF_ID_MHALT,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AT572D940HF_ID_MEXC,
|
||||
.end = AT572D940HF_ID_MEXC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = AT572D940HF_ID_MEDMA,
|
||||
.end = AT572D940HF_ID_MEDMA,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device mAgic_device = {
|
||||
.name = "mAgic",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(mAgic_resources),
|
||||
.resource = mAgic_resources,
|
||||
};
|
||||
|
||||
void __init at91_add_device_mAgic(void)
|
||||
{
|
||||
platform_device_register(&mAgic_device);
|
||||
}
|
||||
#else
|
||||
void __init at91_add_device_mAgic(void) {}
|
||||
#endif
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* These devices are always present and don't need any board-specific
|
||||
* setup.
|
||||
*/
|
||||
static int __init at91_add_standard_devices(void)
|
||||
{
|
||||
at91_add_device_rtt();
|
||||
at91_add_device_watchdog();
|
||||
at91_add_device_tc();
|
||||
return 0;
|
||||
}
|
||||
|
||||
arch_initcall(at91_add_standard_devices);
|
|
@ -0,0 +1,328 @@
|
|||
/*
|
||||
* linux/arch/arm/mach-at91/board-at572d940hf_ek.c
|
||||
*
|
||||
* Copyright (C) 2008 Atmel Antonio R. Costa <costa.antonior@gmail.com>
|
||||
* Copyright (C) 2005 SAN People
|
||||
*
|
||||
* 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/spi/ds1305.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/mtd/physmap.h>
|
||||
|
||||
#include <mach/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 <mach/board.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/at91sam9_smc.h>
|
||||
|
||||
#include "sam9_smc.h"
|
||||
#include "generic.h"
|
||||
|
||||
|
||||
static void __init eb_map_io(void)
|
||||
{
|
||||
/* Initialize processor: 12.500 MHz crystal */
|
||||
at572d940hf_initialize(12000000);
|
||||
|
||||
/* DBGU on ttyS0. (Rx & Tx only) */
|
||||
at91_register_uart(0, 0, 0);
|
||||
|
||||
/* USART0 on ttyS1. (Rx & Tx only) */
|
||||
at91_register_uart(AT572D940HF_ID_US0, 1, 0);
|
||||
|
||||
/* USART1 on ttyS2. (Rx & Tx only) */
|
||||
at91_register_uart(AT572D940HF_ID_US1, 2, 0);
|
||||
|
||||
/* USART2 on ttyS3. (Tx & Rx only */
|
||||
at91_register_uart(AT572D940HF_ID_US2, 3, 0);
|
||||
|
||||
/* set serial console to ttyS0 (ie, DBGU) */
|
||||
at91_set_serial_console(0);
|
||||
}
|
||||
|
||||
static void __init eb_init_irq(void)
|
||||
{
|
||||
at572d940hf_init_interrupts(NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* USB Host Port
|
||||
*/
|
||||
static struct at91_usbh_data __initdata eb_usbh_data = {
|
||||
.ports = 2,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* USB Device Port
|
||||
*/
|
||||
static struct at91_udc_data __initdata eb_udc_data = {
|
||||
.vbus_pin = 0, /* no VBUS detection,UDC always on */
|
||||
.pullup_pin = 0, /* pull-up driven by UDC */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* MCI (SD/MMC)
|
||||
*/
|
||||
static struct at91_mmc_data __initdata eb_mmc_data = {
|
||||
.wire4 = 1,
|
||||
/* .det_pin = ... not connected */
|
||||
/* .wp_pin = ... not connected */
|
||||
/* .vcc_pin = ... not connected */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* MACB Ethernet device
|
||||
*/
|
||||
static struct at91_eth_data __initdata eb_eth_data = {
|
||||
.phy_irq_pin = AT91_PIN_PB25,
|
||||
.is_rmii = 1,
|
||||
};
|
||||
|
||||
/*
|
||||
* NOR flash
|
||||
*/
|
||||
|
||||
static struct mtd_partition eb_nor_partitions[] = {
|
||||
{
|
||||
.name = "Raw Environment",
|
||||
.offset = 0,
|
||||
.size = SZ_4M,
|
||||
.mask_flags = 0,
|
||||
},
|
||||
{
|
||||
.name = "OS FS",
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.size = 3 * SZ_1M,
|
||||
.mask_flags = 0,
|
||||
},
|
||||
{
|
||||
.name = "APP FS",
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.size = MTDPART_SIZ_FULL,
|
||||
.mask_flags = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static void nor_flash_set_vpp(struct map_info* mi, int i) {
|
||||
};
|
||||
|
||||
static struct physmap_flash_data nor_flash_data = {
|
||||
.width = 4,
|
||||
.parts = eb_nor_partitions,
|
||||
.nr_parts = ARRAY_SIZE(eb_nor_partitions),
|
||||
.set_vpp = nor_flash_set_vpp,
|
||||
};
|
||||
|
||||
static struct resource nor_flash_resources[] = {
|
||||
{
|
||||
.start = AT91_CHIPSELECT_0,
|
||||
.end = AT91_CHIPSELECT_0 + SZ_16M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device nor_flash = {
|
||||
.name = "physmap-flash",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &nor_flash_data,
|
||||
},
|
||||
.resource = nor_flash_resources,
|
||||
.num_resources = ARRAY_SIZE(nor_flash_resources),
|
||||
};
|
||||
|
||||
static struct sam9_smc_config __initdata eb_nor_smc_config = {
|
||||
.ncs_read_setup = 1,
|
||||
.nrd_setup = 1,
|
||||
.ncs_write_setup = 1,
|
||||
.nwe_setup = 1,
|
||||
|
||||
.ncs_read_pulse = 7,
|
||||
.nrd_pulse = 7,
|
||||
.ncs_write_pulse = 7,
|
||||
.nwe_pulse = 7,
|
||||
|
||||
.read_cycle = 9,
|
||||
.write_cycle = 9,
|
||||
|
||||
.mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_WRITE | AT91_SMC_DBW_32,
|
||||
.tdf_cycles = 1,
|
||||
};
|
||||
|
||||
static void __init eb_add_device_nor(void)
|
||||
{
|
||||
/* configure chip-select 0 (NOR) */
|
||||
sam9_smc_configure(0, &eb_nor_smc_config);
|
||||
platform_device_register(&nor_flash);
|
||||
}
|
||||
|
||||
/*
|
||||
* NAND flash
|
||||
*/
|
||||
static struct mtd_partition __initdata eb_nand_partition[] = {
|
||||
{
|
||||
.name = "Partition 1",
|
||||
.offset = 0,
|
||||
.size = SZ_16M,
|
||||
},
|
||||
{
|
||||
.name = "Partition 2",
|
||||
.offset = MTDPART_OFS_NXTBLK,
|
||||
.size = MTDPART_SIZ_FULL,
|
||||
}
|
||||
};
|
||||
|
||||
static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
|
||||
{
|
||||
*num_partitions = ARRAY_SIZE(eb_nand_partition);
|
||||
return eb_nand_partition;
|
||||
}
|
||||
|
||||
static struct atmel_nand_data __initdata eb_nand_data = {
|
||||
.ale = 22,
|
||||
.cle = 21,
|
||||
/* .det_pin = ... not connected */
|
||||
/* .rdy_pin = AT91_PIN_PC16, */
|
||||
.enable_pin = AT91_PIN_PA15,
|
||||
.partition_info = nand_partitions,
|
||||
#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
|
||||
.bus_width_16 = 1,
|
||||
#else
|
||||
.bus_width_16 = 0,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct sam9_smc_config __initdata eb_nand_smc_config = {
|
||||
.ncs_read_setup = 0,
|
||||
.nrd_setup = 0,
|
||||
.ncs_write_setup = 1,
|
||||
.nwe_setup = 1,
|
||||
|
||||
.ncs_read_pulse = 3,
|
||||
.nrd_pulse = 3,
|
||||
.ncs_write_pulse = 3,
|
||||
.nwe_pulse = 3,
|
||||
|
||||
.read_cycle = 5,
|
||||
.write_cycle = 5,
|
||||
|
||||
.mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
|
||||
.tdf_cycles = 12,
|
||||
};
|
||||
|
||||
static void __init eb_add_device_nand(void)
|
||||
{
|
||||
/* setup bus-width (8 or 16) */
|
||||
if (eb_nand_data.bus_width_16)
|
||||
eb_nand_smc_config.mode |= AT91_SMC_DBW_16;
|
||||
else
|
||||
eb_nand_smc_config.mode |= AT91_SMC_DBW_8;
|
||||
|
||||
/* configure chip-select 3 (NAND) */
|
||||
sam9_smc_configure(3, &eb_nand_smc_config);
|
||||
|
||||
at91_add_device_nand(&eb_nand_data);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SPI devices
|
||||
*/
|
||||
static struct resource rtc_resources[] = {
|
||||
[0] = {
|
||||
.start = AT572D940HF_ID_IRQ1,
|
||||
.end = AT572D940HF_ID_IRQ1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct ds1305_platform_data ds1306_data = {
|
||||
.is_ds1306 = true,
|
||||
.en_1hz = false,
|
||||
};
|
||||
|
||||
static struct spi_board_info eb_spi_devices[] = {
|
||||
{ /* RTC Dallas DS1306 */
|
||||
.modalias = "rtc-ds1305",
|
||||
.chip_select = 3,
|
||||
.mode = SPI_CS_HIGH | SPI_CPOL | SPI_CPHA,
|
||||
.max_speed_hz = 500000,
|
||||
.bus_num = 0,
|
||||
.irq = AT572D940HF_ID_IRQ1,
|
||||
.platform_data = (void *) &ds1306_data,
|
||||
},
|
||||
#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
|
||||
{ /* Dataflash card */
|
||||
.modalias = "mtd_dataflash",
|
||||
.chip_select = 0,
|
||||
.max_speed_hz = 15 * 1000 * 1000,
|
||||
.bus_num = 0,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
static void __init eb_board_init(void)
|
||||
{
|
||||
/* Serial */
|
||||
at91_add_device_serial();
|
||||
/* USB Host */
|
||||
at91_add_device_usbh(&eb_usbh_data);
|
||||
/* USB Device */
|
||||
at91_add_device_udc(&eb_udc_data);
|
||||
/* I2C */
|
||||
at91_add_device_i2c(NULL, 0);
|
||||
/* NOR */
|
||||
eb_add_device_nor();
|
||||
/* NAND */
|
||||
eb_add_device_nand();
|
||||
/* SPI */
|
||||
at91_add_device_spi(eb_spi_devices, ARRAY_SIZE(eb_spi_devices));
|
||||
/* MMC */
|
||||
at91_add_device_mmc(0, &eb_mmc_data);
|
||||
/* Ethernet */
|
||||
at91_add_device_eth(&eb_eth_data);
|
||||
/* mAgic */
|
||||
at91_add_device_mAgic();
|
||||
}
|
||||
|
||||
MACHINE_START(AT572D940HFEB, "Atmel AT91D940HF-EB")
|
||||
/* Maintainer: Atmel <costa.antonior@gmail.com> */
|
||||
.phys_io = AT91_BASE_SYS,
|
||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||
.timer = &at91sam926x_timer,
|
||||
.map_io = eb_map_io,
|
||||
.init_irq = eb_init_irq,
|
||||
.init_machine = eb_board_init,
|
||||
MACHINE_END
|
|
@ -29,6 +29,7 @@
|
|||
#include <mach/cpu.h>
|
||||
|
||||
#include "clock.h"
|
||||
#include "generic.h"
|
||||
|
||||
|
||||
/*
|
||||
|
@ -628,7 +629,7 @@ static void __init at91_pllb_usbfs_clock_init(unsigned long main_clock)
|
|||
at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP);
|
||||
} else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() ||
|
||||
cpu_is_at91sam9263() || cpu_is_at91sam9g20() ||
|
||||
cpu_is_at91sam9g10()) {
|
||||
cpu_is_at91sam9g10() || cpu_is_at572d940hf()) {
|
||||
uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
|
||||
udpck.pmc_mask = AT91SAM926x_PMC_UDP;
|
||||
} else if (cpu_is_at91cap9()) {
|
||||
|
@ -711,12 +712,13 @@ int __init at91_clock_init(unsigned long main_clock)
|
|||
/*
|
||||
* USB HS clock init
|
||||
*/
|
||||
if (cpu_has_utmi())
|
||||
if (cpu_has_utmi()) {
|
||||
/*
|
||||
* multiplier is hard-wired to 40
|
||||
* (obtain the USB High Speed 480 MHz when input is 12 MHz)
|
||||
*/
|
||||
utmi_clk.rate_hz = 40 * utmi_clk.parent->rate_hz;
|
||||
}
|
||||
|
||||
/*
|
||||
* USB FS clock init
|
||||
|
@ -746,7 +748,7 @@ int __init at91_clock_init(unsigned long main_clock)
|
|||
mck.rate_hz = (mckr & AT91_PMC_MDIV) == AT91SAM9_PMC_MDIV_3 ?
|
||||
freq / 3 : freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */
|
||||
} else {
|
||||
mck.rate_hz = freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */
|
||||
mck.rate_hz = freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */
|
||||
}
|
||||
|
||||
/* Register the PMC's standard clocks */
|
||||
|
|
|
@ -22,7 +22,7 @@ struct clk {
|
|||
struct clk *parent;
|
||||
u32 pmc_mask;
|
||||
void (*mode)(struct clk *, int);
|
||||
unsigned id:2; /* PCK0..3, or 32k/main/a/b */
|
||||
unsigned id:3; /* PCK0..4, or 32k/main/a/b */
|
||||
unsigned type; /* clock type */
|
||||
u16 users;
|
||||
};
|
||||
|
|
|
@ -17,6 +17,7 @@ extern void __init at91sam9rl_initialize(unsigned long main_clock);
|
|||
extern void __init at91sam9g45_initialize(unsigned long main_clock);
|
||||
extern void __init at91x40_initialize(unsigned long main_clock);
|
||||
extern void __init at91cap9_initialize(unsigned long main_clock);
|
||||
extern void __init at572d940hf_initialize(unsigned long main_clock);
|
||||
|
||||
/* Interrupts */
|
||||
extern void __init at91rm9200_init_interrupts(unsigned int priority[]);
|
||||
|
@ -27,6 +28,7 @@ extern void __init at91sam9rl_init_interrupts(unsigned int priority[]);
|
|||
extern void __init at91sam9g45_init_interrupts(unsigned int priority[]);
|
||||
extern void __init at91x40_init_interrupts(unsigned int priority[]);
|
||||
extern void __init at91cap9_init_interrupts(unsigned int priority[]);
|
||||
extern void __init at572d940hf_init_interrupts(unsigned int priority[]);
|
||||
extern void __init at91_aic_init(unsigned int priority[]);
|
||||
|
||||
/* Timer */
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* include/mach/at572d940hf.h
|
||||
*
|
||||
* Antonio R. Costa <costa.antonior@gmail.com>
|
||||
* Copyright (C) 2008 Atmel
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AT572D940HF_H
|
||||
#define AT572D940HF_H
|
||||
|
||||
/*
|
||||
* Peripheral identifiers/interrupts.
|
||||
*/
|
||||
#define AT91_ID_FIQ 0 /* Advanced Interrupt Controller (FIQ) */
|
||||
#define AT91_ID_SYS 1 /* System Peripherals */
|
||||
#define AT572D940HF_ID_PIOA 2 /* Parallel IO Controller A */
|
||||
#define AT572D940HF_ID_PIOB 3 /* Parallel IO Controller B */
|
||||
#define AT572D940HF_ID_PIOC 4 /* Parallel IO Controller C */
|
||||
#define AT572D940HF_ID_EMAC 5 /* MACB ethernet controller */
|
||||
#define AT572D940HF_ID_US0 6 /* USART 0 */
|
||||
#define AT572D940HF_ID_US1 7 /* USART 1 */
|
||||
#define AT572D940HF_ID_US2 8 /* USART 2 */
|
||||
#define AT572D940HF_ID_MCI 9 /* Multimedia Card Interface */
|
||||
#define AT572D940HF_ID_UDP 10 /* USB Device Port */
|
||||
#define AT572D940HF_ID_TWI0 11 /* Two-Wire Interface 0 */
|
||||
#define AT572D940HF_ID_SPI0 12 /* Serial Peripheral Interface 0 */
|
||||
#define AT572D940HF_ID_SPI1 13 /* Serial Peripheral Interface 1 */
|
||||
#define AT572D940HF_ID_SSC0 14 /* Serial Synchronous Controller 0 */
|
||||
#define AT572D940HF_ID_SSC1 15 /* Serial Synchronous Controller 1 */
|
||||
#define AT572D940HF_ID_SSC2 16 /* Serial Synchronous Controller 2 */
|
||||
#define AT572D940HF_ID_TC0 17 /* Timer Counter 0 */
|
||||
#define AT572D940HF_ID_TC1 18 /* Timer Counter 1 */
|
||||
#define AT572D940HF_ID_TC2 19 /* Timer Counter 2 */
|
||||
#define AT572D940HF_ID_UHP 20 /* USB Host port */
|
||||
#define AT572D940HF_ID_SSC3 21 /* Serial Synchronous Controller 3 */
|
||||
#define AT572D940HF_ID_TWI1 22 /* Two-Wire Interface 1 */
|
||||
#define AT572D940HF_ID_CAN0 23 /* CAN Controller 0 */
|
||||
#define AT572D940HF_ID_CAN1 24 /* CAN Controller 1 */
|
||||
#define AT572D940HF_ID_MHALT 25 /* mAgicV HALT line */
|
||||
#define AT572D940HF_ID_MSIRQ0 26 /* mAgicV SIRQ0 line */
|
||||
#define AT572D940HF_ID_MEXC 27 /* mAgicV exception line */
|
||||
#define AT572D940HF_ID_MEDMA 28 /* mAgicV end of DMA line */
|
||||
#define AT572D940HF_ID_IRQ0 29 /* External Interrupt Source (IRQ0) */
|
||||
#define AT572D940HF_ID_IRQ1 30 /* External Interrupt Source (IRQ1) */
|
||||
#define AT572D940HF_ID_IRQ2 31 /* External Interrupt Source (IRQ2) */
|
||||
|
||||
|
||||
/*
|
||||
* User Peripheral physical base addresses.
|
||||
*/
|
||||
#define AT572D940HF_BASE_TCB 0xfffa0000
|
||||
#define AT572D940HF_BASE_TC0 0xfffa0000
|
||||
#define AT572D940HF_BASE_TC1 0xfffa0040
|
||||
#define AT572D940HF_BASE_TC2 0xfffa0080
|
||||
#define AT572D940HF_BASE_UDP 0xfffa4000
|
||||
#define AT572D940HF_BASE_MCI 0xfffa8000
|
||||
#define AT572D940HF_BASE_TWI0 0xfffac000
|
||||
#define AT572D940HF_BASE_US0 0xfffb0000
|
||||
#define AT572D940HF_BASE_US1 0xfffb4000
|
||||
#define AT572D940HF_BASE_US2 0xfffb8000
|
||||
#define AT572D940HF_BASE_SSC0 0xfffbc000
|
||||
#define AT572D940HF_BASE_SSC1 0xfffc0000
|
||||
#define AT572D940HF_BASE_SSC2 0xfffc4000
|
||||
#define AT572D940HF_BASE_SPI0 0xfffc8000
|
||||
#define AT572D940HF_BASE_SPI1 0xfffcc000
|
||||
#define AT572D940HF_BASE_SSC3 0xfffd0000
|
||||
#define AT572D940HF_BASE_TWI1 0xfffd4000
|
||||
#define AT572D940HF_BASE_EMAC 0xfffd8000
|
||||
#define AT572D940HF_BASE_CAN0 0xfffdc000
|
||||
#define AT572D940HF_BASE_CAN1 0xfffe0000
|
||||
#define AT91_BASE_SYS 0xffffea00
|
||||
|
||||
|
||||
/*
|
||||
* System Peripherals (offset from AT91_BASE_SYS)
|
||||
*/
|
||||
#define AT91_SDRAMC (0xffffea00 - AT91_BASE_SYS)
|
||||
#define AT91_SMC (0xffffec00 - AT91_BASE_SYS)
|
||||
#define AT91_MATRIX (0xffffee00 - AT91_BASE_SYS)
|
||||
#define AT91_AIC (0xfffff000 - AT91_BASE_SYS)
|
||||
#define AT91_DBGU (0xfffff200 - AT91_BASE_SYS)
|
||||
#define AT91_PIOA (0xfffff400 - AT91_BASE_SYS)
|
||||
#define AT91_PIOB (0xfffff600 - AT91_BASE_SYS)
|
||||
#define AT91_PIOC (0xfffff800 - AT91_BASE_SYS)
|
||||
#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS)
|
||||
#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS)
|
||||
#define AT91_RTT (0xfffffd20 - AT91_BASE_SYS)
|
||||
#define AT91_PIT (0xfffffd30 - AT91_BASE_SYS)
|
||||
#define AT91_WDT (0xfffffd40 - AT91_BASE_SYS)
|
||||
|
||||
#define AT91_USART0 AT572D940HF_ID_US0
|
||||
#define AT91_USART1 AT572D940HF_ID_US1
|
||||
#define AT91_USART2 AT572D940HF_ID_US2
|
||||
|
||||
|
||||
/*
|
||||
* Internal Memory.
|
||||
*/
|
||||
#define AT572D940HF_SRAM_BASE 0x00300000 /* Internal SRAM base address */
|
||||
#define AT572D940HF_SRAM_SIZE (48 * SZ_1K) /* Internal SRAM size (48Kb) */
|
||||
|
||||
#define AT572D940HF_ROM_BASE 0x00400000 /* Internal ROM base address */
|
||||
#define AT572D940HF_ROM_SIZE SZ_32K /* Internal ROM size (32Kb) */
|
||||
|
||||
#define AT572D940HF_UHP_BASE 0x00500000 /* USB Host controller */
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* include/mach//at572d940hf_matrix.h
|
||||
*
|
||||
* Antonio R. Costa <costa.antonior@gmail.com>
|
||||
* Copyright (C) 2008 Atmel
|
||||
*
|
||||
* Copyright (C) 2005 SAN People
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef AT572D940HF_MATRIX_H
|
||||
#define AT572D940HF_MATRIX_H
|
||||
|
||||
#define AT91_MATRIX_MCFG0 (AT91_MATRIX + 0x00) /* Master Configuration Register 0 */
|
||||
#define AT91_MATRIX_MCFG1 (AT91_MATRIX + 0x04) /* Master Configuration Register 1 */
|
||||
#define AT91_MATRIX_MCFG2 (AT91_MATRIX + 0x08) /* Master Configuration Register 2 */
|
||||
#define AT91_MATRIX_MCFG3 (AT91_MATRIX + 0x0C) /* Master Configuration Register 3 */
|
||||
#define AT91_MATRIX_MCFG4 (AT91_MATRIX + 0x10) /* Master Configuration Register 4 */
|
||||
#define AT91_MATRIX_MCFG5 (AT91_MATRIX + 0x14) /* Master Configuration Register 5 */
|
||||
|
||||
#define AT91_MATRIX_ULBT (7 << 0) /* Undefined Length Burst Type */
|
||||
#define AT91_MATRIX_ULBT_INFINITE (0 << 0)
|
||||
#define AT91_MATRIX_ULBT_SINGLE (1 << 0)
|
||||
#define AT91_MATRIX_ULBT_FOUR (2 << 0)
|
||||
#define AT91_MATRIX_ULBT_EIGHT (3 << 0)
|
||||
#define AT91_MATRIX_ULBT_SIXTEEN (4 << 0)
|
||||
|
||||
#define AT91_MATRIX_SCFG0 (AT91_MATRIX + 0x40) /* Slave Configuration Register 0 */
|
||||
#define AT91_MATRIX_SCFG1 (AT91_MATRIX + 0x44) /* Slave Configuration Register 1 */
|
||||
#define AT91_MATRIX_SCFG2 (AT91_MATRIX + 0x48) /* Slave Configuration Register 2 */
|
||||
#define AT91_MATRIX_SCFG3 (AT91_MATRIX + 0x4C) /* Slave Configuration Register 3 */
|
||||
#define AT91_MATRIX_SCFG4 (AT91_MATRIX + 0x50) /* Slave Configuration Register 4 */
|
||||
#define AT91_MATRIX_SLOT_CYCLE (0xff << 0) /* Maximum Number of Allowed Cycles for a Burst */
|
||||
#define AT91_MATRIX_DEFMSTR_TYPE (3 << 16) /* Default Master Type */
|
||||
#define AT91_MATRIX_DEFMSTR_TYPE_NONE (0 << 16)
|
||||
#define AT91_MATRIX_DEFMSTR_TYPE_LAST (1 << 16)
|
||||
#define AT91_MATRIX_DEFMSTR_TYPE_FIXED (2 << 16)
|
||||
#define AT91_MATRIX_FIXED_DEFMSTR (0x7 << 18) /* Fixed Index of Default Master */
|
||||
#define AT91_MATRIX_ARBT (3 << 24) /* Arbitration Type */
|
||||
#define AT91_MATRIX_ARBT_ROUND_ROBIN (0 << 24)
|
||||
#define AT91_MATRIX_ARBT_FIXED_PRIORITY (1 << 24)
|
||||
|
||||
#define AT91_MATRIX_PRAS0 (AT91_MATRIX + 0x80) /* Priority Register A for Slave 0 */
|
||||
#define AT91_MATRIX_PRAS1 (AT91_MATRIX + 0x88) /* Priority Register A for Slave 1 */
|
||||
#define AT91_MATRIX_PRAS2 (AT91_MATRIX + 0x90) /* Priority Register A for Slave 2 */
|
||||
#define AT91_MATRIX_PRAS3 (AT91_MATRIX + 0x98) /* Priority Register A for Slave 3 */
|
||||
#define AT91_MATRIX_PRAS4 (AT91_MATRIX + 0xA0) /* Priority Register A for Slave 4 */
|
||||
|
||||
#define AT91_MATRIX_M0PR (3 << 0) /* Master 0 Priority */
|
||||
#define AT91_MATRIX_M1PR (3 << 4) /* Master 1 Priority */
|
||||
#define AT91_MATRIX_M2PR (3 << 8) /* Master 2 Priority */
|
||||
#define AT91_MATRIX_M3PR (3 << 12) /* Master 3 Priority */
|
||||
#define AT91_MATRIX_M4PR (3 << 16) /* Master 4 Priority */
|
||||
#define AT91_MATRIX_M5PR (3 << 20) /* Master 5 Priority */
|
||||
#define AT91_MATRIX_M6PR (3 << 24) /* Master 6 Priority */
|
||||
|
||||
#define AT91_MATRIX_MRCR (AT91_MATRIX + 0x100) /* Master Remap Control Register */
|
||||
#define AT91_MATRIX_RCB0 (1 << 0) /* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */
|
||||
#define AT91_MATRIX_RCB1 (1 << 1) /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
|
||||
|
||||
#define AT91_MATRIX_SFR0 (AT91_MATRIX + 0x110) /* Special Function Register 0 */
|
||||
#define AT91_MATRIX_SFR1 (AT91_MATRIX + 0x114) /* Special Function Register 1 */
|
||||
#define AT91_MATRIX_SFR2 (AT91_MATRIX + 0x118) /* Special Function Register 2 */
|
||||
#define AT91_MATRIX_SFR3 (AT91_MATRIX + 0x11C) /* Special Function Register 3 */
|
||||
#define AT91_MATRIX_SFR4 (AT91_MATRIX + 0x120) /* Special Function Register 4 */
|
||||
#define AT91_MATRIX_SFR5 (AT91_MATRIX + 0x124) /* Special Function Register 5 */
|
||||
#define AT91_MATRIX_SFR6 (AT91_MATRIX + 0x128) /* Special Function Register 6 */
|
||||
#define AT91_MATRIX_SFR7 (AT91_MATRIX + 0x12C) /* Special Function Register 7 */
|
||||
#define AT91_MATRIX_SFR8 (AT91_MATRIX + 0x130) /* Special Function Register 8 */
|
||||
#define AT91_MATRIX_SFR9 (AT91_MATRIX + 0x134) /* Special Function Register 9 */
|
||||
#define AT91_MATRIX_SFR10 (AT91_MATRIX + 0x138) /* Special Function Register 10 */
|
||||
#define AT91_MATRIX_SFR11 (AT91_MATRIX + 0x13C) /* Special Function Register 11 */
|
||||
#define AT91_MATRIX_SFR12 (AT91_MATRIX + 0x140) /* Special Function Register 12 */
|
||||
#define AT91_MATRIX_SFR13 (AT91_MATRIX + 0x144) /* Special Function Register 13 */
|
||||
#define AT91_MATRIX_SFR14 (AT91_MATRIX + 0x148) /* Special Function Register 14 */
|
||||
#define AT91_MATRIX_SFR15 (AT91_MATRIX + 0x14C) /* Special Function Register 15 */
|
||||
|
||||
|
||||
/*
|
||||
* The following registers / bits are not defined in the Datasheet (Revision A)
|
||||
*/
|
||||
|
||||
#define AT91_MATRIX_TCR (AT91_MATRIX + 0x100) /* TCM Configuration Register */
|
||||
#define AT91_MATRIX_ITCM_SIZE (0xf << 0) /* Size of ITCM enabled memory block */
|
||||
#define AT91_MATRIX_ITCM_0 (0 << 0)
|
||||
#define AT91_MATRIX_ITCM_16 (5 << 0)
|
||||
#define AT91_MATRIX_ITCM_32 (6 << 0)
|
||||
#define AT91_MATRIX_ITCM_64 (7 << 0)
|
||||
#define AT91_MATRIX_DTCM_SIZE (0xf << 4) /* Size of DTCM enabled memory block */
|
||||
#define AT91_MATRIX_DTCM_0 (0 << 4)
|
||||
#define AT91_MATRIX_DTCM_16 (5 << 4)
|
||||
#define AT91_MATRIX_DTCM_32 (6 << 4)
|
||||
#define AT91_MATRIX_DTCM_64 (7 << 4)
|
||||
|
||||
#define AT91_MATRIX_EBICSA (AT91_MATRIX + 0x11C) /* EBI Chip Select Assignment Register */
|
||||
#define AT91_MATRIX_CS1A (1 << 1) /* Chip Select 1 Assignment */
|
||||
#define AT91_MATRIX_CS1A_SMC (0 << 1)
|
||||
#define AT91_MATRIX_CS1A_SDRAMC (1 << 1)
|
||||
#define AT91_MATRIX_CS3A (1 << 3) /* Chip Select 3 Assignment */
|
||||
#define AT91_MATRIX_CS3A_SMC (0 << 3)
|
||||
#define AT91_MATRIX_CS3A_SMC_SMARTMEDIA (1 << 3)
|
||||
#define AT91_MATRIX_CS4A (1 << 4) /* Chip Select 4 Assignment */
|
||||
#define AT91_MATRIX_CS4A_SMC (0 << 4)
|
||||
#define AT91_MATRIX_CS4A_SMC_CF1 (1 << 4)
|
||||
#define AT91_MATRIX_CS5A (1 << 5) /* Chip Select 5 Assignment */
|
||||
#define AT91_MATRIX_CS5A_SMC (0 << 5)
|
||||
#define AT91_MATRIX_CS5A_SMC_CF2 (1 << 5)
|
||||
#define AT91_MATRIX_DBPUC (1 << 8) /* Data Bus Pull-up Configuration */
|
||||
|
||||
#endif
|
|
@ -32,6 +32,7 @@
|
|||
#define AT91_PMC_PCK1 (1 << 9) /* Programmable Clock 1 */
|
||||
#define AT91_PMC_PCK2 (1 << 10) /* Programmable Clock 2 */
|
||||
#define AT91_PMC_PCK3 (1 << 11) /* Programmable Clock 3 */
|
||||
#define AT91_PMC_PCK4 (1 << 12) /* Programmable Clock 4 [AT572D940HF only] */
|
||||
#define AT91_PMC_HCK0 (1 << 16) /* AHB Clock (USB host) [AT91SAM9261 only] */
|
||||
#define AT91_PMC_HCK1 (1 << 17) /* AHB Clock (LCD) [AT91SAM9261 only] */
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ struct at91_eth_data {
|
|||
extern void __init at91_add_device_eth(struct at91_eth_data *data);
|
||||
|
||||
#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9263) || defined(CONFIG_ARCH_AT91SAM9G20) || defined(CONFIG_ARCH_AT91CAP9) \
|
||||
|| defined(CONFIG_ARCH_AT91SAM9G45)
|
||||
|| defined(CONFIG_ARCH_AT91SAM9G45) || defined(CONFIG_ARCH_AT572D940HF)
|
||||
#define eth_platform_data at91_eth_data
|
||||
#endif
|
||||
|
||||
|
@ -205,6 +205,9 @@ extern void __init at91_init_leds(u8 cpu_led, u8 timer_led);
|
|||
extern void __init at91_gpio_leds(struct gpio_led *leds, int nr);
|
||||
extern void __init at91_pwm_leds(struct gpio_led *leds, int nr);
|
||||
|
||||
/* AT572D940HF DSP */
|
||||
extern void __init at91_add_device_mAgic(void);
|
||||
|
||||
/* FIXME: this needs a better location, but gets stuff building again */
|
||||
extern int at91_suspend_entering_slow_clock(void);
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
#define ARCH_ID_AT91SAM9XE256 0x329a93a0
|
||||
#define ARCH_ID_AT91SAM9XE512 0x329aa3a0
|
||||
|
||||
#define ARCH_ID_AT572D940HF 0x0e0303e0
|
||||
|
||||
#define ARCH_ID_AT91M40800 0x14080044
|
||||
#define ARCH_ID_AT91R40807 0x44080746
|
||||
#define ARCH_ID_AT91M40807 0x14080745
|
||||
|
@ -141,6 +143,12 @@ static inline unsigned long at91cap9_rev_identify(void)
|
|||
#define cpu_is_at91cap9_revC() (0)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_AT572D940HF
|
||||
#define cpu_is_at572d940hf() (at91_cpu_identify() == ARCH_ID_AT572D940HF)
|
||||
#else
|
||||
#define cpu_is_at572d940hf() (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Since this is ARM, we will never run on any AVR32 CPU. But these
|
||||
* definitions may reduce clutter in common drivers.
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include <mach/hardware.h>
|
||||
#include <mach/at91_dbgu.h>
|
||||
|
||||
.macro addruart,rx
|
||||
.macro addruart, rx, tmp
|
||||
mrc p15, 0, \rx, c1, c0
|
||||
tst \rx, #1 @ MMU enabled?
|
||||
ldreq \rx, =(AT91_BASE_SYS + AT91_DBGU) @ System peripherals (phys address)
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include <mach/at91cap9.h>
|
||||
#elif defined(CONFIG_ARCH_AT91X40)
|
||||
#include <mach/at91x40.h>
|
||||
#elif defined(CONFIG_ARCH_AT572D940HF)
|
||||
#include <mach/at572d940hf.h>
|
||||
#else
|
||||
#error "Unsupported AT91 processor"
|
||||
#endif
|
||||
|
|
|
@ -82,6 +82,11 @@
|
|||
#define AT91X40_MASTER_CLOCK 40000000
|
||||
#define CLOCK_TICK_RATE (AT91X40_MASTER_CLOCK)
|
||||
|
||||
#elif defined(CONFIG_ARCH_AT572D940HF)
|
||||
|
||||
#define AT572D940HF_MASTER_CLOCK 80000000
|
||||
#define CLOCK_TICK_RATE (AT572D940HF_MASTER_CLOCK/16)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -142,8 +142,7 @@ void __init bcmring_amba_init(void)
|
|||
|
||||
chipcHw_busInterfaceClockEnable(bus_clock);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lookups); i++)
|
||||
clkdev_add(&lookups[i]);
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
|
||||
struct amba_device *d = amba_devs[i];
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include <asm/hardware/clps7111.h>
|
||||
|
||||
.macro addruart,rx
|
||||
.macro addruart, rx, tmp
|
||||
mrc p15, 0, \rx, c1, c0
|
||||
tst \rx, #1 @ MMU enabled?
|
||||
moveq \rx, #CLPS7111_PHYS_BASE
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include <linux/serial_reg.h>
|
||||
#define UART_SHIFT 2
|
||||
|
||||
.macro addruart, rx
|
||||
.macro addruart, rx, tmp
|
||||
mrc p15, 0, \rx, c1, c0
|
||||
tst \rx, #1 @ MMU enabled?
|
||||
moveq \rx, #0x01000000 @ physical base address
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
/*
|
||||
* I/O mapping
|
||||
*/
|
||||
#define IO_PHYS 0x01c00000
|
||||
#define IO_PHYS 0x01c00000UL
|
||||
#define IO_OFFSET 0xfd000000 /* Virtual IO = 0xfec00000 */
|
||||
#define IO_SIZE 0x00400000
|
||||
#define IO_VIRT (IO_PHYS + IO_OFFSET)
|
||||
|
|
|
@ -24,7 +24,7 @@ void __iomem *davinci_ioremap(unsigned long p, size_t size, unsigned int type)
|
|||
if (BETWEEN(p, IO_PHYS, IO_SIZE))
|
||||
return XLATE(p, IO_PHYS, IO_VIRT);
|
||||
|
||||
return __arm_ioremap(p, size, type);
|
||||
return __arm_ioremap_caller(p, size, type, __builtin_return_address(0));
|
||||
}
|
||||
EXPORT_SYMBOL(davinci_ioremap);
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include <mach/bridge-regs.h>
|
||||
|
||||
.macro addruart,rx
|
||||
.macro addruart, rx, tmp
|
||||
mrc p15, 0, \rx, c1, c0
|
||||
tst \rx, #1 @ MMU enabled?
|
||||
ldreq \rx, =DOVE_SB_REGS_PHYS_BASE
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
* arch/arm/mach-dove/include/mach/vmalloc.h
|
||||
*/
|
||||
|
||||
#define VMALLOC_END 0xfd800000
|
||||
#define VMALLOC_END 0xfd800000UL
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
*
|
||||
**/
|
||||
|
||||
.macro addruart,rx
|
||||
.macro addruart, rx, tmp
|
||||
mov \rx, #0xf0000000
|
||||
orr \rx, \rx, #0x00000be0
|
||||
.endm
|
||||
|
|
|
@ -161,6 +161,20 @@ config MACH_MICRO9S
|
|||
Say 'Y' here if you want your kernel to support the
|
||||
Contec Micro9-Slim board.
|
||||
|
||||
config MACH_SIM_ONE
|
||||
bool "Support Simplemachines Sim.One board"
|
||||
depends on EP93XX_SDCE0_PHYS_OFFSET
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support the
|
||||
Simplemachines Sim.One board.
|
||||
|
||||
config MACH_SNAPPER_CL15
|
||||
bool "Support Bluewater Systems Snapper CL15 Module"
|
||||
depends on EP93XX_SDCE0_PHYS_OFFSET
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support the Bluewater
|
||||
Systems Snapper CL15 Module.
|
||||
|
||||
config MACH_TS72XX
|
||||
bool "Support Technologic Systems TS-72xx SBC"
|
||||
depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET
|
||||
|
|
|
@ -10,4 +10,6 @@ obj-$(CONFIG_MACH_ADSSPHERE) += adssphere.o
|
|||
obj-$(CONFIG_MACH_EDB93XX) += edb93xx.o
|
||||
obj-$(CONFIG_MACH_GESBC9312) += gesbc9312.o
|
||||
obj-$(CONFIG_MACH_MICRO9) += micro9.o
|
||||
obj-$(CONFIG_MACH_SIM_ONE) += simone.o
|
||||
obj-$(CONFIG_MACH_SNAPPER_CL15) += snappercl15.o
|
||||
obj-$(CONFIG_MACH_TS72XX) += ts72xx.o
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
* your option) any later version.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
|
@ -445,37 +447,39 @@ static void __init ep93xx_dma_clock_init(void)
|
|||
static int __init ep93xx_clock_init(void)
|
||||
{
|
||||
u32 value;
|
||||
int i;
|
||||
|
||||
value = __raw_readl(EP93XX_SYSCON_CLOCK_SET1);
|
||||
if (!(value & 0x00800000)) { /* PLL1 bypassed? */
|
||||
/* Determine the bootloader configured pll1 rate */
|
||||
value = __raw_readl(EP93XX_SYSCON_CLKSET1);
|
||||
if (!(value & EP93XX_SYSCON_CLKSET1_NBYP1))
|
||||
clk_pll1.rate = clk_xtali.rate;
|
||||
} else {
|
||||
else
|
||||
clk_pll1.rate = calc_pll_rate(value);
|
||||
}
|
||||
|
||||
/* Initialize the pll1 derived clocks */
|
||||
clk_f.rate = clk_pll1.rate / fclk_divisors[(value >> 25) & 0x7];
|
||||
clk_h.rate = clk_pll1.rate / hclk_divisors[(value >> 20) & 0x7];
|
||||
clk_p.rate = clk_h.rate / pclk_divisors[(value >> 18) & 0x3];
|
||||
ep93xx_dma_clock_init();
|
||||
|
||||
value = __raw_readl(EP93XX_SYSCON_CLOCK_SET2);
|
||||
if (!(value & 0x00080000)) { /* PLL2 bypassed? */
|
||||
/* Determine the bootloader configured pll2 rate */
|
||||
value = __raw_readl(EP93XX_SYSCON_CLKSET2);
|
||||
if (!(value & EP93XX_SYSCON_CLKSET2_NBYP2))
|
||||
clk_pll2.rate = clk_xtali.rate;
|
||||
} else if (value & 0x00040000) { /* PLL2 enabled? */
|
||||
else if (value & EP93XX_SYSCON_CLKSET2_PLL2_EN)
|
||||
clk_pll2.rate = calc_pll_rate(value);
|
||||
} else {
|
||||
else
|
||||
clk_pll2.rate = 0;
|
||||
}
|
||||
|
||||
/* Initialize the pll2 derived clocks */
|
||||
clk_usb_host.rate = clk_pll2.rate / (((value >> 28) & 0xf) + 1);
|
||||
|
||||
printk(KERN_INFO "ep93xx: PLL1 running at %ld MHz, PLL2 at %ld MHz\n",
|
||||
pr_info("PLL1 running at %ld MHz, PLL2 at %ld MHz\n",
|
||||
clk_pll1.rate / 1000000, clk_pll2.rate / 1000000);
|
||||
printk(KERN_INFO "ep93xx: FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n",
|
||||
pr_info("FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n",
|
||||
clk_f.rate / 1000000, clk_h.rate / 1000000,
|
||||
clk_p.rate / 1000000);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(clocks); i++)
|
||||
clkdev_add(&clocks[i]);
|
||||
clkdev_add_table(clocks, ARRAY_SIZE(clocks));
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(ep93xx_clock_init);
|
||||
|
|
|
@ -14,12 +14,15 @@
|
|||
* your option) any later version.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/timex.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/leds.h>
|
||||
|
@ -35,7 +38,6 @@
|
|||
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/mach/irq.h>
|
||||
|
||||
#include <asm/hardware/vic.h>
|
||||
|
||||
|
@ -82,13 +84,40 @@ void __init ep93xx_map_io(void)
|
|||
* to use this timer for something else. We also use timer 4 for keeping
|
||||
* track of lost jiffies.
|
||||
*/
|
||||
static unsigned int last_jiffy_time;
|
||||
#define EP93XX_TIMER_REG(x) (EP93XX_TIMER_BASE + (x))
|
||||
#define EP93XX_TIMER1_LOAD EP93XX_TIMER_REG(0x00)
|
||||
#define EP93XX_TIMER1_VALUE EP93XX_TIMER_REG(0x04)
|
||||
#define EP93XX_TIMER1_CONTROL EP93XX_TIMER_REG(0x08)
|
||||
#define EP93XX_TIMER123_CONTROL_ENABLE (1 << 7)
|
||||
#define EP93XX_TIMER123_CONTROL_MODE (1 << 6)
|
||||
#define EP93XX_TIMER123_CONTROL_CLKSEL (1 << 3)
|
||||
#define EP93XX_TIMER1_CLEAR EP93XX_TIMER_REG(0x0c)
|
||||
#define EP93XX_TIMER2_LOAD EP93XX_TIMER_REG(0x20)
|
||||
#define EP93XX_TIMER2_VALUE EP93XX_TIMER_REG(0x24)
|
||||
#define EP93XX_TIMER2_CONTROL EP93XX_TIMER_REG(0x28)
|
||||
#define EP93XX_TIMER2_CLEAR EP93XX_TIMER_REG(0x2c)
|
||||
#define EP93XX_TIMER4_VALUE_LOW EP93XX_TIMER_REG(0x60)
|
||||
#define EP93XX_TIMER4_VALUE_HIGH EP93XX_TIMER_REG(0x64)
|
||||
#define EP93XX_TIMER4_VALUE_HIGH_ENABLE (1 << 8)
|
||||
#define EP93XX_TIMER3_LOAD EP93XX_TIMER_REG(0x80)
|
||||
#define EP93XX_TIMER3_VALUE EP93XX_TIMER_REG(0x84)
|
||||
#define EP93XX_TIMER3_CONTROL EP93XX_TIMER_REG(0x88)
|
||||
#define EP93XX_TIMER3_CLEAR EP93XX_TIMER_REG(0x8c)
|
||||
|
||||
#define EP93XX_TIMER123_CLOCK 508469
|
||||
#define EP93XX_TIMER4_CLOCK 983040
|
||||
|
||||
#define TIMER1_RELOAD ((EP93XX_TIMER123_CLOCK / HZ) - 1)
|
||||
#define TIMER4_TICKS_PER_JIFFY DIV_ROUND_CLOSEST(CLOCK_TICK_RATE, HZ)
|
||||
|
||||
static unsigned int last_jiffy_time;
|
||||
|
||||
static irqreturn_t ep93xx_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
/* Writing any value clears the timer interrupt */
|
||||
__raw_writel(1, EP93XX_TIMER1_CLEAR);
|
||||
|
||||
/* Recover lost jiffies */
|
||||
while ((signed long)
|
||||
(__raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time)
|
||||
>= TIMER4_TICKS_PER_JIFFY) {
|
||||
|
@ -107,13 +136,18 @@ static struct irqaction ep93xx_timer_irq = {
|
|||
|
||||
static void __init ep93xx_timer_init(void)
|
||||
{
|
||||
u32 tmode = EP93XX_TIMER123_CONTROL_MODE |
|
||||
EP93XX_TIMER123_CONTROL_CLKSEL;
|
||||
|
||||
/* Enable periodic HZ timer. */
|
||||
__raw_writel(0x48, EP93XX_TIMER1_CONTROL);
|
||||
__raw_writel((508469 / HZ) - 1, EP93XX_TIMER1_LOAD);
|
||||
__raw_writel(0xc8, EP93XX_TIMER1_CONTROL);
|
||||
__raw_writel(tmode, EP93XX_TIMER1_CONTROL);
|
||||
__raw_writel(TIMER1_RELOAD, EP93XX_TIMER1_LOAD);
|
||||
__raw_writel(tmode | EP93XX_TIMER123_CONTROL_ENABLE,
|
||||
EP93XX_TIMER1_CONTROL);
|
||||
|
||||
/* Enable lost jiffy timer. */
|
||||
__raw_writel(0x100, EP93XX_TIMER4_VALUE_HIGH);
|
||||
__raw_writel(EP93XX_TIMER4_VALUE_HIGH_ENABLE,
|
||||
EP93XX_TIMER4_VALUE_HIGH);
|
||||
|
||||
setup_irq(IRQ_EP93XX_TIMER1, &ep93xx_timer_irq);
|
||||
}
|
||||
|
@ -134,238 +168,17 @@ struct sys_timer ep93xx_timer = {
|
|||
};
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* GPIO handling for EP93xx
|
||||
*************************************************************************/
|
||||
static unsigned char gpio_int_unmasked[3];
|
||||
static unsigned char gpio_int_enabled[3];
|
||||
static unsigned char gpio_int_type1[3];
|
||||
static unsigned char gpio_int_type2[3];
|
||||
static unsigned char gpio_int_debounce[3];
|
||||
|
||||
/* Port ordering is: A B F */
|
||||
static const u8 int_type1_register_offset[3] = { 0x90, 0xac, 0x4c };
|
||||
static const u8 int_type2_register_offset[3] = { 0x94, 0xb0, 0x50 };
|
||||
static const u8 eoi_register_offset[3] = { 0x98, 0xb4, 0x54 };
|
||||
static const u8 int_en_register_offset[3] = { 0x9c, 0xb8, 0x58 };
|
||||
static const u8 int_debounce_register_offset[3] = { 0xa8, 0xc4, 0x64 };
|
||||
|
||||
void ep93xx_gpio_update_int_params(unsigned port)
|
||||
{
|
||||
BUG_ON(port > 2);
|
||||
|
||||
__raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port]));
|
||||
|
||||
__raw_writeb(gpio_int_type2[port],
|
||||
EP93XX_GPIO_REG(int_type2_register_offset[port]));
|
||||
|
||||
__raw_writeb(gpio_int_type1[port],
|
||||
EP93XX_GPIO_REG(int_type1_register_offset[port]));
|
||||
|
||||
__raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port],
|
||||
EP93XX_GPIO_REG(int_en_register_offset[port]));
|
||||
}
|
||||
|
||||
void ep93xx_gpio_int_mask(unsigned line)
|
||||
{
|
||||
gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
|
||||
}
|
||||
|
||||
void ep93xx_gpio_int_debounce(unsigned int irq, int enable)
|
||||
{
|
||||
int line = irq_to_gpio(irq);
|
||||
int port = line >> 3;
|
||||
int port_mask = 1 << (line & 7);
|
||||
|
||||
if (enable)
|
||||
gpio_int_debounce[port] |= port_mask;
|
||||
else
|
||||
gpio_int_debounce[port] &= ~port_mask;
|
||||
|
||||
__raw_writeb(gpio_int_debounce[port],
|
||||
EP93XX_GPIO_REG(int_debounce_register_offset[port]));
|
||||
}
|
||||
EXPORT_SYMBOL(ep93xx_gpio_int_debounce);
|
||||
|
||||
/*************************************************************************
|
||||
* EP93xx IRQ handling
|
||||
*************************************************************************/
|
||||
static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
unsigned char status;
|
||||
int i;
|
||||
|
||||
status = __raw_readb(EP93XX_GPIO_A_INT_STATUS);
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (status & (1 << i)) {
|
||||
int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i;
|
||||
generic_handle_irq(gpio_irq);
|
||||
}
|
||||
}
|
||||
|
||||
status = __raw_readb(EP93XX_GPIO_B_INT_STATUS);
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (status & (1 << i)) {
|
||||
int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i;
|
||||
generic_handle_irq(gpio_irq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
/*
|
||||
* map discontiguous hw irq range to continous sw irq range:
|
||||
*
|
||||
* IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7})
|
||||
*/
|
||||
int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */
|
||||
int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx;
|
||||
|
||||
generic_handle_irq(gpio_irq);
|
||||
}
|
||||
|
||||
static void ep93xx_gpio_irq_ack(unsigned int irq)
|
||||
{
|
||||
int line = irq_to_gpio(irq);
|
||||
int port = line >> 3;
|
||||
int port_mask = 1 << (line & 7);
|
||||
|
||||
if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
|
||||
gpio_int_type2[port] ^= port_mask; /* switch edge direction */
|
||||
ep93xx_gpio_update_int_params(port);
|
||||
}
|
||||
|
||||
__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
|
||||
}
|
||||
|
||||
static void ep93xx_gpio_irq_mask_ack(unsigned int irq)
|
||||
{
|
||||
int line = irq_to_gpio(irq);
|
||||
int port = line >> 3;
|
||||
int port_mask = 1 << (line & 7);
|
||||
|
||||
if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
|
||||
gpio_int_type2[port] ^= port_mask; /* switch edge direction */
|
||||
|
||||
gpio_int_unmasked[port] &= ~port_mask;
|
||||
ep93xx_gpio_update_int_params(port);
|
||||
|
||||
__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
|
||||
}
|
||||
|
||||
static void ep93xx_gpio_irq_mask(unsigned int irq)
|
||||
{
|
||||
int line = irq_to_gpio(irq);
|
||||
int port = line >> 3;
|
||||
|
||||
gpio_int_unmasked[port] &= ~(1 << (line & 7));
|
||||
ep93xx_gpio_update_int_params(port);
|
||||
}
|
||||
|
||||
static void ep93xx_gpio_irq_unmask(unsigned int irq)
|
||||
{
|
||||
int line = irq_to_gpio(irq);
|
||||
int port = line >> 3;
|
||||
|
||||
gpio_int_unmasked[port] |= 1 << (line & 7);
|
||||
ep93xx_gpio_update_int_params(port);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* gpio_int_type1 controls whether the interrupt is level (0) or
|
||||
* edge (1) triggered, while gpio_int_type2 controls whether it
|
||||
* triggers on low/falling (0) or high/rising (1).
|
||||
*/
|
||||
static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
|
||||
{
|
||||
struct irq_desc *desc = irq_desc + irq;
|
||||
const int gpio = irq_to_gpio(irq);
|
||||
const int port = gpio >> 3;
|
||||
const int port_mask = 1 << (gpio & 7);
|
||||
|
||||
gpio_direction_input(gpio);
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
gpio_int_type1[port] |= port_mask;
|
||||
gpio_int_type2[port] |= port_mask;
|
||||
desc->handle_irq = handle_edge_irq;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
gpio_int_type1[port] |= port_mask;
|
||||
gpio_int_type2[port] &= ~port_mask;
|
||||
desc->handle_irq = handle_edge_irq;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
gpio_int_type1[port] &= ~port_mask;
|
||||
gpio_int_type2[port] |= port_mask;
|
||||
desc->handle_irq = handle_level_irq;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
gpio_int_type1[port] &= ~port_mask;
|
||||
gpio_int_type2[port] &= ~port_mask;
|
||||
desc->handle_irq = handle_level_irq;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
gpio_int_type1[port] |= port_mask;
|
||||
/* set initial polarity based on current input level */
|
||||
if (gpio_get_value(gpio))
|
||||
gpio_int_type2[port] &= ~port_mask; /* falling */
|
||||
else
|
||||
gpio_int_type2[port] |= port_mask; /* rising */
|
||||
desc->handle_irq = handle_edge_irq;
|
||||
break;
|
||||
default:
|
||||
pr_err("ep93xx: failed to set irq type %d for gpio %d\n",
|
||||
type, gpio);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gpio_int_enabled[port] |= port_mask;
|
||||
|
||||
desc->status &= ~IRQ_TYPE_SENSE_MASK;
|
||||
desc->status |= type & IRQ_TYPE_SENSE_MASK;
|
||||
|
||||
ep93xx_gpio_update_int_params(port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip ep93xx_gpio_irq_chip = {
|
||||
.name = "GPIO",
|
||||
.ack = ep93xx_gpio_irq_ack,
|
||||
.mask_ack = ep93xx_gpio_irq_mask_ack,
|
||||
.mask = ep93xx_gpio_irq_mask,
|
||||
.unmask = ep93xx_gpio_irq_unmask,
|
||||
.set_type = ep93xx_gpio_irq_type,
|
||||
};
|
||||
|
||||
extern void ep93xx_gpio_init_irq(void);
|
||||
|
||||
void __init ep93xx_init_irq(void)
|
||||
{
|
||||
int gpio_irq;
|
||||
|
||||
vic_init(EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0);
|
||||
vic_init(EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0);
|
||||
|
||||
for (gpio_irq = gpio_to_irq(0);
|
||||
gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
|
||||
set_irq_chip(gpio_irq, &ep93xx_gpio_irq_chip);
|
||||
set_irq_handler(gpio_irq, handle_level_irq);
|
||||
set_irq_flags(gpio_irq, IRQF_VALID);
|
||||
}
|
||||
|
||||
set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler);
|
||||
set_irq_chained_handler(IRQ_EP93XX_GPIO0MUX, ep93xx_gpio_f_irq_handler);
|
||||
set_irq_chained_handler(IRQ_EP93XX_GPIO1MUX, ep93xx_gpio_f_irq_handler);
|
||||
set_irq_chained_handler(IRQ_EP93XX_GPIO2MUX, ep93xx_gpio_f_irq_handler);
|
||||
set_irq_chained_handler(IRQ_EP93XX_GPIO3MUX, ep93xx_gpio_f_irq_handler);
|
||||
set_irq_chained_handler(IRQ_EP93XX_GPIO4MUX, ep93xx_gpio_f_irq_handler);
|
||||
set_irq_chained_handler(IRQ_EP93XX_GPIO5MUX, ep93xx_gpio_f_irq_handler);
|
||||
set_irq_chained_handler(IRQ_EP93XX_GPIO6MUX, ep93xx_gpio_f_irq_handler);
|
||||
set_irq_chained_handler(IRQ_EP93XX_GPIO7MUX, ep93xx_gpio_f_irq_handler);
|
||||
ep93xx_gpio_init_irq();
|
||||
}
|
||||
|
||||
|
||||
|
@ -572,9 +385,9 @@ void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
|
|||
* CMOS driver.
|
||||
*/
|
||||
if (data->sda_is_open_drain && data->sda_pin != EP93XX_GPIO_LINE_EEDAT)
|
||||
pr_warning("ep93xx: sda != EEDAT, open drain has no effect\n");
|
||||
pr_warning("sda != EEDAT, open drain has no effect\n");
|
||||
if (data->scl_is_open_drain && data->scl_pin != EP93XX_GPIO_LINE_EECLK)
|
||||
pr_warning("ep93xx: scl != EECLK, open drain has no effect\n");
|
||||
pr_warning("scl != EECLK, open drain has no effect\n");
|
||||
|
||||
__raw_writel((data->sda_is_open_drain << 1) |
|
||||
(data->scl_is_open_drain << 0),
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
* with this implementation.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
|
@ -173,7 +175,7 @@ static irqreturn_t m2p_irq(int irq, void *dev_id)
|
|||
|
||||
switch (m2p_channel_state(ch)) {
|
||||
case STATE_IDLE:
|
||||
pr_crit("m2p_irq: dma interrupt without a dma buffer\n");
|
||||
pr_crit("dma interrupt without a dma buffer\n");
|
||||
BUG();
|
||||
break;
|
||||
|
||||
|
@ -197,7 +199,7 @@ static irqreturn_t m2p_irq(int irq, void *dev_id)
|
|||
break;
|
||||
|
||||
case STATE_NEXT:
|
||||
pr_crit("m2p_irq: dma interrupt while next\n");
|
||||
pr_crit("dma interrupt while next\n");
|
||||
BUG();
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -118,12 +118,33 @@ static void __init edb93xx_register_i2c(void)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* EDB93xx pwm
|
||||
*************************************************************************/
|
||||
static void __init edb93xx_register_pwm(void)
|
||||
{
|
||||
if (machine_is_edb9301() ||
|
||||
machine_is_edb9302() || machine_is_edb9302a()) {
|
||||
/* EP9301 and EP9302 only have pwm.1 (EGPIO14) */
|
||||
ep93xx_register_pwm(0, 1);
|
||||
} else if (machine_is_edb9307() || machine_is_edb9307a()) {
|
||||
/* EP9307 only has pwm.0 (PWMOUT) */
|
||||
ep93xx_register_pwm(1, 0);
|
||||
} else {
|
||||
/* EP9312 and EP9315 have both */
|
||||
ep93xx_register_pwm(1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void __init edb93xx_init_machine(void)
|
||||
{
|
||||
ep93xx_init_devices();
|
||||
edb93xx_register_flash();
|
||||
ep93xx_register_eth(&edb93xx_eth_data, 1);
|
||||
edb93xx_register_i2c();
|
||||
edb93xx_register_pwm();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
@ -22,6 +24,235 @@
|
|||
|
||||
#include <mach/hardware.h>
|
||||
|
||||
/*************************************************************************
|
||||
* GPIO handling for EP93xx
|
||||
*************************************************************************/
|
||||
static unsigned char gpio_int_unmasked[3];
|
||||
static unsigned char gpio_int_enabled[3];
|
||||
static unsigned char gpio_int_type1[3];
|
||||
static unsigned char gpio_int_type2[3];
|
||||
static unsigned char gpio_int_debounce[3];
|
||||
|
||||
/* Port ordering is: A B F */
|
||||
static const u8 int_type1_register_offset[3] = { 0x90, 0xac, 0x4c };
|
||||
static const u8 int_type2_register_offset[3] = { 0x94, 0xb0, 0x50 };
|
||||
static const u8 eoi_register_offset[3] = { 0x98, 0xb4, 0x54 };
|
||||
static const u8 int_en_register_offset[3] = { 0x9c, 0xb8, 0x58 };
|
||||
static const u8 int_debounce_register_offset[3] = { 0xa8, 0xc4, 0x64 };
|
||||
|
||||
void ep93xx_gpio_update_int_params(unsigned port)
|
||||
{
|
||||
BUG_ON(port > 2);
|
||||
|
||||
__raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port]));
|
||||
|
||||
__raw_writeb(gpio_int_type2[port],
|
||||
EP93XX_GPIO_REG(int_type2_register_offset[port]));
|
||||
|
||||
__raw_writeb(gpio_int_type1[port],
|
||||
EP93XX_GPIO_REG(int_type1_register_offset[port]));
|
||||
|
||||
__raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port],
|
||||
EP93XX_GPIO_REG(int_en_register_offset[port]));
|
||||
}
|
||||
|
||||
void ep93xx_gpio_int_mask(unsigned line)
|
||||
{
|
||||
gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
|
||||
}
|
||||
|
||||
void ep93xx_gpio_int_debounce(unsigned int irq, int enable)
|
||||
{
|
||||
int line = irq_to_gpio(irq);
|
||||
int port = line >> 3;
|
||||
int port_mask = 1 << (line & 7);
|
||||
|
||||
if (enable)
|
||||
gpio_int_debounce[port] |= port_mask;
|
||||
else
|
||||
gpio_int_debounce[port] &= ~port_mask;
|
||||
|
||||
__raw_writeb(gpio_int_debounce[port],
|
||||
EP93XX_GPIO_REG(int_debounce_register_offset[port]));
|
||||
}
|
||||
EXPORT_SYMBOL(ep93xx_gpio_int_debounce);
|
||||
|
||||
static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
unsigned char status;
|
||||
int i;
|
||||
|
||||
status = __raw_readb(EP93XX_GPIO_A_INT_STATUS);
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (status & (1 << i)) {
|
||||
int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i;
|
||||
generic_handle_irq(gpio_irq);
|
||||
}
|
||||
}
|
||||
|
||||
status = __raw_readb(EP93XX_GPIO_B_INT_STATUS);
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (status & (1 << i)) {
|
||||
int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i;
|
||||
generic_handle_irq(gpio_irq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
/*
|
||||
* map discontiguous hw irq range to continous sw irq range:
|
||||
*
|
||||
* IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7})
|
||||
*/
|
||||
int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */
|
||||
int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx;
|
||||
|
||||
generic_handle_irq(gpio_irq);
|
||||
}
|
||||
|
||||
static void ep93xx_gpio_irq_ack(unsigned int irq)
|
||||
{
|
||||
int line = irq_to_gpio(irq);
|
||||
int port = line >> 3;
|
||||
int port_mask = 1 << (line & 7);
|
||||
|
||||
if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
|
||||
gpio_int_type2[port] ^= port_mask; /* switch edge direction */
|
||||
ep93xx_gpio_update_int_params(port);
|
||||
}
|
||||
|
||||
__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
|
||||
}
|
||||
|
||||
static void ep93xx_gpio_irq_mask_ack(unsigned int irq)
|
||||
{
|
||||
int line = irq_to_gpio(irq);
|
||||
int port = line >> 3;
|
||||
int port_mask = 1 << (line & 7);
|
||||
|
||||
if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
|
||||
gpio_int_type2[port] ^= port_mask; /* switch edge direction */
|
||||
|
||||
gpio_int_unmasked[port] &= ~port_mask;
|
||||
ep93xx_gpio_update_int_params(port);
|
||||
|
||||
__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
|
||||
}
|
||||
|
||||
static void ep93xx_gpio_irq_mask(unsigned int irq)
|
||||
{
|
||||
int line = irq_to_gpio(irq);
|
||||
int port = line >> 3;
|
||||
|
||||
gpio_int_unmasked[port] &= ~(1 << (line & 7));
|
||||
ep93xx_gpio_update_int_params(port);
|
||||
}
|
||||
|
||||
static void ep93xx_gpio_irq_unmask(unsigned int irq)
|
||||
{
|
||||
int line = irq_to_gpio(irq);
|
||||
int port = line >> 3;
|
||||
|
||||
gpio_int_unmasked[port] |= 1 << (line & 7);
|
||||
ep93xx_gpio_update_int_params(port);
|
||||
}
|
||||
|
||||
/*
|
||||
* gpio_int_type1 controls whether the interrupt is level (0) or
|
||||
* edge (1) triggered, while gpio_int_type2 controls whether it
|
||||
* triggers on low/falling (0) or high/rising (1).
|
||||
*/
|
||||
static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
|
||||
{
|
||||
struct irq_desc *desc = irq_desc + irq;
|
||||
const int gpio = irq_to_gpio(irq);
|
||||
const int port = gpio >> 3;
|
||||
const int port_mask = 1 << (gpio & 7);
|
||||
|
||||
gpio_direction_input(gpio);
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
gpio_int_type1[port] |= port_mask;
|
||||
gpio_int_type2[port] |= port_mask;
|
||||
desc->handle_irq = handle_edge_irq;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
gpio_int_type1[port] |= port_mask;
|
||||
gpio_int_type2[port] &= ~port_mask;
|
||||
desc->handle_irq = handle_edge_irq;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
gpio_int_type1[port] &= ~port_mask;
|
||||
gpio_int_type2[port] |= port_mask;
|
||||
desc->handle_irq = handle_level_irq;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
gpio_int_type1[port] &= ~port_mask;
|
||||
gpio_int_type2[port] &= ~port_mask;
|
||||
desc->handle_irq = handle_level_irq;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
gpio_int_type1[port] |= port_mask;
|
||||
/* set initial polarity based on current input level */
|
||||
if (gpio_get_value(gpio))
|
||||
gpio_int_type2[port] &= ~port_mask; /* falling */
|
||||
else
|
||||
gpio_int_type2[port] |= port_mask; /* rising */
|
||||
desc->handle_irq = handle_edge_irq;
|
||||
break;
|
||||
default:
|
||||
pr_err("failed to set irq type %d for gpio %d\n", type, gpio);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gpio_int_enabled[port] |= port_mask;
|
||||
|
||||
desc->status &= ~IRQ_TYPE_SENSE_MASK;
|
||||
desc->status |= type & IRQ_TYPE_SENSE_MASK;
|
||||
|
||||
ep93xx_gpio_update_int_params(port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip ep93xx_gpio_irq_chip = {
|
||||
.name = "GPIO",
|
||||
.ack = ep93xx_gpio_irq_ack,
|
||||
.mask_ack = ep93xx_gpio_irq_mask_ack,
|
||||
.mask = ep93xx_gpio_irq_mask,
|
||||
.unmask = ep93xx_gpio_irq_unmask,
|
||||
.set_type = ep93xx_gpio_irq_type,
|
||||
};
|
||||
|
||||
void __init ep93xx_gpio_init_irq(void)
|
||||
{
|
||||
int gpio_irq;
|
||||
|
||||
for (gpio_irq = gpio_to_irq(0);
|
||||
gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
|
||||
set_irq_chip(gpio_irq, &ep93xx_gpio_irq_chip);
|
||||
set_irq_handler(gpio_irq, handle_level_irq);
|
||||
set_irq_flags(gpio_irq, IRQF_VALID);
|
||||
}
|
||||
|
||||
set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler);
|
||||
set_irq_chained_handler(IRQ_EP93XX_GPIO0MUX, ep93xx_gpio_f_irq_handler);
|
||||
set_irq_chained_handler(IRQ_EP93XX_GPIO1MUX, ep93xx_gpio_f_irq_handler);
|
||||
set_irq_chained_handler(IRQ_EP93XX_GPIO2MUX, ep93xx_gpio_f_irq_handler);
|
||||
set_irq_chained_handler(IRQ_EP93XX_GPIO3MUX, ep93xx_gpio_f_irq_handler);
|
||||
set_irq_chained_handler(IRQ_EP93XX_GPIO4MUX, ep93xx_gpio_f_irq_handler);
|
||||
set_irq_chained_handler(IRQ_EP93XX_GPIO5MUX, ep93xx_gpio_f_irq_handler);
|
||||
set_irq_chained_handler(IRQ_EP93XX_GPIO6MUX, ep93xx_gpio_f_irq_handler);
|
||||
set_irq_chained_handler(IRQ_EP93XX_GPIO7MUX, ep93xx_gpio_f_irq_handler);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* gpiolib interface for EP93xx on-chip GPIOs
|
||||
*************************************************************************/
|
||||
struct ep93xx_gpio_chip {
|
||||
struct gpio_chip chip;
|
||||
|
||||
|
@ -31,10 +262,6 @@ struct ep93xx_gpio_chip {
|
|||
|
||||
#define to_ep93xx_gpio_chip(c) container_of(c, struct ep93xx_gpio_chip, chip)
|
||||
|
||||
/* From core.c */
|
||||
extern void ep93xx_gpio_int_mask(unsigned line);
|
||||
extern void ep93xx_gpio_update_int_params(unsigned port);
|
||||
|
||||
static int ep93xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
*/
|
||||
#include <mach/ep93xx-regs.h>
|
||||
|
||||
.macro addruart,rx
|
||||
.macro addruart, rx, tmp
|
||||
mrc p15, 0, \rx, c1, c0
|
||||
tst \rx, #1 @ MMU enabled?
|
||||
ldreq \rx, =EP93XX_APB_PHYS_BASE @ Physical base
|
||||
|
|
|
@ -92,21 +92,6 @@
|
|||
|
||||
/* APB peripherals */
|
||||
#define EP93XX_TIMER_BASE EP93XX_APB_IOMEM(0x00010000)
|
||||
#define EP93XX_TIMER_REG(x) (EP93XX_TIMER_BASE + (x))
|
||||
#define EP93XX_TIMER1_LOAD EP93XX_TIMER_REG(0x00)
|
||||
#define EP93XX_TIMER1_VALUE EP93XX_TIMER_REG(0x04)
|
||||
#define EP93XX_TIMER1_CONTROL EP93XX_TIMER_REG(0x08)
|
||||
#define EP93XX_TIMER1_CLEAR EP93XX_TIMER_REG(0x0c)
|
||||
#define EP93XX_TIMER2_LOAD EP93XX_TIMER_REG(0x20)
|
||||
#define EP93XX_TIMER2_VALUE EP93XX_TIMER_REG(0x24)
|
||||
#define EP93XX_TIMER2_CONTROL EP93XX_TIMER_REG(0x28)
|
||||
#define EP93XX_TIMER2_CLEAR EP93XX_TIMER_REG(0x2c)
|
||||
#define EP93XX_TIMER4_VALUE_LOW EP93XX_TIMER_REG(0x60)
|
||||
#define EP93XX_TIMER4_VALUE_HIGH EP93XX_TIMER_REG(0x64)
|
||||
#define EP93XX_TIMER3_LOAD EP93XX_TIMER_REG(0x80)
|
||||
#define EP93XX_TIMER3_VALUE EP93XX_TIMER_REG(0x84)
|
||||
#define EP93XX_TIMER3_CONTROL EP93XX_TIMER_REG(0x88)
|
||||
#define EP93XX_TIMER3_CLEAR EP93XX_TIMER_REG(0x8c)
|
||||
|
||||
#define EP93XX_I2S_BASE EP93XX_APB_IOMEM(0x00020000)
|
||||
|
||||
|
@ -167,8 +152,11 @@
|
|||
#define EP93XX_SYSCON_PWRCNT_DMA_M2P1 (1<<16)
|
||||
#define EP93XX_SYSCON_HALT EP93XX_SYSCON_REG(0x08)
|
||||
#define EP93XX_SYSCON_STANDBY EP93XX_SYSCON_REG(0x0c)
|
||||
#define EP93XX_SYSCON_CLOCK_SET1 EP93XX_SYSCON_REG(0x20)
|
||||
#define EP93XX_SYSCON_CLOCK_SET2 EP93XX_SYSCON_REG(0x24)
|
||||
#define EP93XX_SYSCON_CLKSET1 EP93XX_SYSCON_REG(0x20)
|
||||
#define EP93XX_SYSCON_CLKSET1_NBYP1 (1<<23)
|
||||
#define EP93XX_SYSCON_CLKSET2 EP93XX_SYSCON_REG(0x24)
|
||||
#define EP93XX_SYSCON_CLKSET2_NBYP2 (1<<19)
|
||||
#define EP93XX_SYSCON_CLKSET2_PLL2_EN (1<<18)
|
||||
#define EP93XX_SYSCON_DEVCFG EP93XX_SYSCON_REG(0x80)
|
||||
#define EP93XX_SYSCON_DEVCFG_SWRST (1<<31)
|
||||
#define EP93XX_SYSCON_DEVCFG_D1ONG (1<<30)
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
* arch/arm/mach-ep93xx/include/mach/vmalloc.h
|
||||
*/
|
||||
|
||||
#define VMALLOC_END 0xfe800000
|
||||
#define VMALLOC_END 0xfe800000UL
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* arch/arm/mach-ep93xx/simone.c
|
||||
* Simplemachines Sim.One support.
|
||||
*
|
||||
* Copyright (C) 2010 Ryan Mallon <ryan@bluewatersys.com>
|
||||
*
|
||||
* Based on the 2.6.24.7 support:
|
||||
* Copyright (C) 2009 Simplemachines
|
||||
* MMC support by Peter Ivanov <ivanovp@gmail.com>, 2007
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mtd/physmap.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-gpio.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/fb.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
static struct physmap_flash_data simone_flash_data = {
|
||||
.width = 2,
|
||||
};
|
||||
|
||||
static struct resource simone_flash_resource = {
|
||||
.start = EP93XX_CS6_PHYS_BASE,
|
||||
.end = EP93XX_CS6_PHYS_BASE + SZ_8M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
static struct platform_device simone_flash = {
|
||||
.name = "physmap-flash",
|
||||
.id = 0,
|
||||
.num_resources = 1,
|
||||
.resource = &simone_flash_resource,
|
||||
.dev = {
|
||||
.platform_data = &simone_flash_data,
|
||||
},
|
||||
};
|
||||
|
||||
static struct ep93xx_eth_data simone_eth_data = {
|
||||
.phy_id = 1,
|
||||
};
|
||||
|
||||
static struct ep93xxfb_mach_info simone_fb_info = {
|
||||
.num_modes = EP93XXFB_USE_MODEDB,
|
||||
.bpp = 16,
|
||||
.flags = EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING,
|
||||
};
|
||||
|
||||
static struct i2c_gpio_platform_data simone_i2c_gpio_data = {
|
||||
.sda_pin = EP93XX_GPIO_LINE_EEDAT,
|
||||
.sda_is_open_drain = 0,
|
||||
.scl_pin = EP93XX_GPIO_LINE_EECLK,
|
||||
.scl_is_open_drain = 0,
|
||||
.udelay = 0,
|
||||
.timeout = 0,
|
||||
};
|
||||
|
||||
static struct i2c_board_info __initdata simone_i2c_board_info[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("ds1337", 0x68),
|
||||
},
|
||||
};
|
||||
|
||||
static void __init simone_init_machine(void)
|
||||
{
|
||||
ep93xx_init_devices();
|
||||
|
||||
platform_device_register(&simone_flash);
|
||||
ep93xx_register_eth(&simone_eth_data, 1);
|
||||
ep93xx_register_fb(&simone_fb_info);
|
||||
ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info,
|
||||
ARRAY_SIZE(simone_i2c_board_info));
|
||||
}
|
||||
|
||||
MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board")
|
||||
/* Maintainer: Ryan Mallon <ryan@bluewatersys.com> */
|
||||
.phys_io = EP93XX_APB_PHYS_BASE,
|
||||
.io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
|
||||
.boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100,
|
||||
.map_io = ep93xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.timer = &ep93xx_timer,
|
||||
.init_machine = simone_init_machine,
|
||||
MACHINE_END
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* arch/arm/mach-ep93xx/snappercl15.c
|
||||
* Bluewater Systems Snapper CL15 system module
|
||||
*
|
||||
* Copyright (C) 2009 Bluewater Systems Ltd
|
||||
* Author: Ryan Mallon <ryan@bluewatersys.com>
|
||||
*
|
||||
* NAND code adapted from driver by:
|
||||
* Andre Renaud <andre@bluewatersys.com>
|
||||
* James R. McKaskill
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-gpio.h>
|
||||
#include <linux/fb.h>
|
||||
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/mtd/nand.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/fb.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
#define SNAPPERCL15_NAND_BASE (EP93XX_CS7_PHYS_BASE + SZ_16M)
|
||||
|
||||
#define SNAPPERCL15_NAND_WPN (1 << 8) /* Write protect (active low) */
|
||||
#define SNAPPERCL15_NAND_ALE (1 << 9) /* Address latch */
|
||||
#define SNAPPERCL15_NAND_CLE (1 << 10) /* Command latch */
|
||||
#define SNAPPERCL15_NAND_CEN (1 << 11) /* Chip enable (active low) */
|
||||
#define SNAPPERCL15_NAND_RDY (1 << 14) /* Device ready */
|
||||
|
||||
#define NAND_CTRL_ADDR(chip) (chip->IO_ADDR_W + 0x40)
|
||||
|
||||
static void snappercl15_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
|
||||
unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
static u16 nand_state = SNAPPERCL15_NAND_WPN;
|
||||
u16 set;
|
||||
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
set = SNAPPERCL15_NAND_CEN | SNAPPERCL15_NAND_WPN;
|
||||
|
||||
if (ctrl & NAND_NCE)
|
||||
set &= ~SNAPPERCL15_NAND_CEN;
|
||||
if (ctrl & NAND_CLE)
|
||||
set |= SNAPPERCL15_NAND_CLE;
|
||||
if (ctrl & NAND_ALE)
|
||||
set |= SNAPPERCL15_NAND_ALE;
|
||||
|
||||
nand_state &= ~(SNAPPERCL15_NAND_CEN |
|
||||
SNAPPERCL15_NAND_CLE |
|
||||
SNAPPERCL15_NAND_ALE);
|
||||
nand_state |= set;
|
||||
__raw_writew(nand_state, NAND_CTRL_ADDR(chip));
|
||||
}
|
||||
|
||||
if (cmd != NAND_CMD_NONE)
|
||||
__raw_writew((cmd & 0xff) | nand_state, chip->IO_ADDR_W);
|
||||
}
|
||||
|
||||
static int snappercl15_nand_dev_ready(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
|
||||
return !!(__raw_readw(NAND_CTRL_ADDR(chip)) & SNAPPERCL15_NAND_RDY);
|
||||
}
|
||||
|
||||
static const char *snappercl15_nand_part_probes[] = {"cmdlinepart", NULL};
|
||||
|
||||
static struct mtd_partition snappercl15_nand_parts[] = {
|
||||
{
|
||||
.name = "Kernel",
|
||||
.offset = 0,
|
||||
.size = SZ_2M,
|
||||
},
|
||||
{
|
||||
.name = "Filesystem",
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.size = MTDPART_SIZ_FULL,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_nand_data snappercl15_nand_data = {
|
||||
.chip = {
|
||||
.nr_chips = 1,
|
||||
.part_probe_types = snappercl15_nand_part_probes,
|
||||
.partitions = snappercl15_nand_parts,
|
||||
.nr_partitions = ARRAY_SIZE(snappercl15_nand_parts),
|
||||
.options = NAND_NO_AUTOINCR,
|
||||
.chip_delay = 25,
|
||||
},
|
||||
.ctrl = {
|
||||
.dev_ready = snappercl15_nand_dev_ready,
|
||||
.cmd_ctrl = snappercl15_nand_cmd_ctrl,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource snappercl15_nand_resource[] = {
|
||||
{
|
||||
.start = SNAPPERCL15_NAND_BASE,
|
||||
.end = SNAPPERCL15_NAND_BASE + SZ_4K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device snappercl15_nand_device = {
|
||||
.name = "gen_nand",
|
||||
.id = -1,
|
||||
.dev.platform_data = &snappercl15_nand_data,
|
||||
.resource = snappercl15_nand_resource,
|
||||
.num_resources = ARRAY_SIZE(snappercl15_nand_resource),
|
||||
};
|
||||
|
||||
static struct ep93xx_eth_data snappercl15_eth_data = {
|
||||
.phy_id = 1,
|
||||
};
|
||||
|
||||
static struct i2c_gpio_platform_data snappercl15_i2c_gpio_data = {
|
||||
.sda_pin = EP93XX_GPIO_LINE_EEDAT,
|
||||
.sda_is_open_drain = 0,
|
||||
.scl_pin = EP93XX_GPIO_LINE_EECLK,
|
||||
.scl_is_open_drain = 0,
|
||||
.udelay = 0,
|
||||
.timeout = 0,
|
||||
};
|
||||
|
||||
static struct i2c_board_info __initdata snappercl15_i2c_data[] = {
|
||||
{
|
||||
/* Audio codec */
|
||||
I2C_BOARD_INFO("tlv320aic23", 0x1a),
|
||||
},
|
||||
};
|
||||
|
||||
static struct ep93xxfb_mach_info snappercl15_fb_info = {
|
||||
.num_modes = EP93XXFB_USE_MODEDB,
|
||||
.bpp = 16,
|
||||
};
|
||||
|
||||
static void __init snappercl15_init_machine(void)
|
||||
{
|
||||
ep93xx_init_devices();
|
||||
ep93xx_register_eth(&snappercl15_eth_data, 1);
|
||||
ep93xx_register_i2c(&snappercl15_i2c_gpio_data, snappercl15_i2c_data,
|
||||
ARRAY_SIZE(snappercl15_i2c_data));
|
||||
ep93xx_register_fb(&snappercl15_fb_info);
|
||||
platform_device_register(&snappercl15_nand_device);
|
||||
}
|
||||
|
||||
MACHINE_START(SNAPPER_CL15, "Bluewater Systems Snapper CL15")
|
||||
/* Maintainer: Ryan Mallon <ryan@bluewatersys.com> */
|
||||
.phys_io = EP93XX_APB_PHYS_BASE,
|
||||
.io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
|
||||
.boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100,
|
||||
.map_io = ep93xx_map_io,
|
||||
.init_irq = ep93xx_init_irq,
|
||||
.timer = &ep93xx_timer,
|
||||
.init_machine = snappercl15_init_machine,
|
||||
MACHINE_END
|
|
@ -32,12 +32,13 @@ unsigned int mem_fclk_21285 = 50000000;
|
|||
|
||||
EXPORT_SYMBOL(mem_fclk_21285);
|
||||
|
||||
static void __init early_fclk(char **arg)
|
||||
static int __init early_fclk(char *arg)
|
||||
{
|
||||
mem_fclk_21285 = simple_strtoul(*arg, arg, 0);
|
||||
mem_fclk_21285 = simple_strtoul(arg, NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
__early_param("mem_fclk_21285=", early_fclk);
|
||||
early_param("mem_fclk_21285", early_fclk);
|
||||
|
||||
static int __init parse_tag_memclk(const struct tag *tag)
|
||||
{
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
#ifndef CONFIG_DEBUG_DC21285_PORT
|
||||
/* For NetWinder debugging */
|
||||
.macro addruart,rx
|
||||
.macro addruart, rx, tmp
|
||||
mrc p15, 0, \rx, c1, c0
|
||||
tst \rx, #1 @ MMU enabled?
|
||||
moveq \rx, #0x7c000000 @ physical
|
||||
|
@ -32,7 +32,7 @@
|
|||
.equ dc21285_high, ARMCSR_BASE & 0xff000000
|
||||
.equ dc21285_low, ARMCSR_BASE & 0x00ffffff
|
||||
|
||||
.macro addruart,rx
|
||||
.macro addruart, rx, tmp
|
||||
mrc p15, 0, \rx, c1, c0
|
||||
tst \rx, #1 @ MMU enabled?
|
||||
moveq \rx, #0x42000000
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
*/
|
||||
#include <mach/hardware.h>
|
||||
|
||||
.macro addruart,rx
|
||||
.macro addruart, rx, tmp
|
||||
mrc p15, 0, \rx, c1, c0
|
||||
tst \rx, #1 @ MMU enabled?
|
||||
ldreq \rx, =GEMINI_UART_BASE @ physical
|
||||
|
|
|
@ -7,4 +7,4 @@
|
|||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#define VMALLOC_END 0xF0000000
|
||||
#define VMALLOC_END 0xf0000000UL
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
.equ io_virt, IO_BASE
|
||||
.equ io_phys, IO_START
|
||||
|
||||
.macro addruart,rx
|
||||
.macro addruart, rx, tmp
|
||||
mrc p15, 0, \rx, c1, c0
|
||||
tst \rx, #1 @ MMU enabled?
|
||||
moveq \rx, #io_phys @ physical base address
|
||||
|
|
|
@ -144,8 +144,7 @@ static int __init integrator_init(void)
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lookups); i++)
|
||||
clkdev_add(&lookups[i]);
|
||||
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
|
||||
struct amba_device *d = amba_devs[i];
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
.macro addruart,rx
|
||||
.macro addruart, rx, tmp
|
||||
mrc p15, 0, \rx, c1, c0
|
||||
tst \rx, #1 @ MMU enabled?
|
||||
moveq \rx, #0x16000000 @ physical base address
|
||||
|
|
|
@ -558,9 +558,7 @@ static void __init intcp_init(void)
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cp_lookups); i++)
|
||||
clkdev_add(&cp_lookups[i]);
|
||||
|
||||
clkdev_add_table(cp_lookups, ARRAY_SIZE(cp_lookups));
|
||||
platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
.macro addruart, rx
|
||||
.macro addruart, rx, tmp
|
||||
mrc p15, 0, \rx, c1, c0
|
||||
tst \rx, #1 @ mmu enabled?
|
||||
moveq \rx, #0xff000000 @ physical
|
||||
|
|
|
@ -61,9 +61,9 @@ void * __iomem __iop13xx_ioremap(unsigned long cookie, size_t size,
|
|||
(cookie - IOP13XX_PCIE_LOWER_MEM_RA));
|
||||
break;
|
||||
case IOP13XX_PBI_LOWER_MEM_RA ... IOP13XX_PBI_UPPER_MEM_RA:
|
||||
retval = __arm_ioremap(IOP13XX_PBI_LOWER_MEM_PA +
|
||||
retval = __arm_ioremap_caller(IOP13XX_PBI_LOWER_MEM_PA +
|
||||
(cookie - IOP13XX_PBI_LOWER_MEM_RA),
|
||||
size, mtype);
|
||||
size, mtype, __builtin_return_address(0));
|
||||
break;
|
||||
case IOP13XX_PCIE_LOWER_IO_PA ... IOP13XX_PCIE_UPPER_IO_PA:
|
||||
retval = (void *) IOP13XX_PCIE_IO_PHYS_TO_VIRT(cookie);
|
||||
|
@ -75,7 +75,8 @@ void * __iomem __iop13xx_ioremap(unsigned long cookie, size_t size,
|
|||
retval = (void *) IOP13XX_PMMR_PHYS_TO_VIRT(cookie);
|
||||
break;
|
||||
default:
|
||||
retval = __arm_ioremap(cookie, size, mtype);
|
||||
retval = __arm_ioremap_caller(cookie, size, mtype,
|
||||
__builtin_return_address(0));
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
.macro addruart, rx
|
||||
.macro addruart, rx, tmp
|
||||
mov \rx, #0xfe000000 @ physical as well as virtual
|
||||
orr \rx, \rx, #0x00800000 @ location of the UART
|
||||
.endm
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
* arch/arm/mach-iop32x/include/mach/vmalloc.h
|
||||
*/
|
||||
|
||||
#define VMALLOC_END 0xfe000000
|
||||
#define VMALLOC_END 0xfe000000UL
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
.macro addruart, rx
|
||||
.macro addruart, rx, tmp
|
||||
mrc p15, 0, \rx, c1, c0
|
||||
tst \rx, #1 @ mmu enabled?
|
||||
moveq \rx, #0xff000000 @ physical
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
* arch/arm/mach-iop33x/include/mach/vmalloc.h
|
||||
*/
|
||||
|
||||
#define VMALLOC_END 0xfe000000
|
||||
#define VMALLOC_END 0xfe000000UL
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
.macro addruart,rx
|
||||
.macro addruart, rx, tmp
|
||||
mrc p15, 0, \rx, c1, c0
|
||||
tst \rx, #1 @ MMU enabled?
|
||||
moveq \rx, #0xc0000000 @ Physical base
|
||||
|
|
|
@ -17,4 +17,4 @@
|
|||
* The vmalloc() routines leaves a hole of 4kB between each vmalloced
|
||||
* area for the same reason. ;)
|
||||
*/
|
||||
#define VMALLOC_END 0xfb000000
|
||||
#define VMALLOC_END 0xfb000000UL
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*/
|
||||
#include <mach/ixp23xx.h>
|
||||
|
||||
.macro addruart,rx
|
||||
.macro addruart, rx, tmp
|
||||
mrc p15, 0, \rx, c1, c0
|
||||
tst \rx, #1 @ mmu enabled?
|
||||
ldreq \rx, =IXP23XX_PERIPHERAL_PHYS @ physical
|
||||
|
|
|
@ -7,4 +7,4 @@
|
|||
* specific static I/O.
|
||||
*/
|
||||
|
||||
#define VMALLOC_END (0xec000000)
|
||||
#define VMALLOC_END (0xec000000UL)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue