mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2025-04-21 12:27:27 +03:00
yet another patchset - 2.6.27
it's basically also provided by ingenic and nativly based on 2.6.27, adjusted to fit into the OpenWrt-environment
This commit is contained in:
11
target/linux/xburst/files-2.6.27/Changelog
Normal file
11
target/linux/xburst/files-2.6.27/Changelog
Normal file
@@ -0,0 +1,11 @@
|
||||
2009.04.30
|
||||
* Fix a bug in using gpio keys when pressing two keys at the same time.
|
||||
Updated file:
|
||||
drivers/input/keyboard/gpio_keys.c
|
||||
<lhhuang@ingenic.cn>
|
||||
|
||||
2009.04.28
|
||||
* Support detecting the power of battery.
|
||||
Add File:
|
||||
drivers/power/jz_battery.c
|
||||
<lhhuang@ingenic.cn>
|
||||
@@ -0,0 +1,42 @@
|
||||
#
|
||||
# linux/arch/mips/boot/compressed/Makefile
|
||||
#
|
||||
# create a compressed zImage from the original vmlinux
|
||||
#
|
||||
|
||||
targets := zImage vmlinuz vmlinux.bin.gz head.o misc.o piggy.o dummy.o
|
||||
|
||||
OBJS := $(obj)/head.o $(obj)/misc.o
|
||||
|
||||
LD_ARGS := -T $(obj)/ld.script -Ttext 0x80600000 -Bstatic
|
||||
OBJCOPY_ARGS := -O elf32-tradlittlemips
|
||||
|
||||
ENTRY := $(obj)/../tools/entry
|
||||
FILESIZE := $(obj)/../tools/filesize
|
||||
|
||||
drop-sections = .reginfo .mdebug .comment .note .pdr .options .MIPS.options
|
||||
strip-flags = $(addprefix --remove-section=,$(drop-sections))
|
||||
|
||||
|
||||
$(obj)/vmlinux.bin.gz: vmlinux
|
||||
rm -f $(obj)/vmlinux.bin.gz
|
||||
$(OBJCOPY) -O binary $(strip-flags) vmlinux $(obj)/vmlinux.bin
|
||||
gzip -v9f $(obj)/vmlinux.bin
|
||||
|
||||
$(obj)/head.o: $(obj)/head.S $(obj)/vmlinux.bin.gz vmlinux
|
||||
$(CC) $(KBUILD_AFLAGS) \
|
||||
-DIMAGESIZE=$(shell sh $(FILESIZE) $(obj)/vmlinux.bin.gz) \
|
||||
-DKERNEL_ENTRY=$(shell sh $(ENTRY) $(NM) vmlinux ) \
|
||||
-DLOADADDR=$(loadaddr) \
|
||||
-c -o $(obj)/head.o $<
|
||||
|
||||
$(obj)/vmlinuz: $(OBJS) $(obj)/ld.script $(obj)/vmlinux.bin.gz $(obj)/dummy.o
|
||||
$(OBJCOPY) \
|
||||
--add-section=.image=$(obj)/vmlinux.bin.gz \
|
||||
--set-section-flags=.image=contents,alloc,load,readonly,data \
|
||||
$(obj)/dummy.o $(obj)/piggy.o
|
||||
$(LD) $(LD_ARGS) -o $@ $(OBJS) $(obj)/piggy.o
|
||||
$(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab -R .stabstr -R .initrd -R .sysmap
|
||||
|
||||
zImage: $(obj)/vmlinuz
|
||||
$(OBJCOPY) -O binary $(obj)/vmlinuz $(obj)/zImage
|
||||
@@ -0,0 +1,4 @@
|
||||
int main(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* linux/arch/mips/boot/compressed/head.S
|
||||
*
|
||||
* Copyright (C) 2005-2008 Ingenic Semiconductor Inc.
|
||||
*/
|
||||
|
||||
#include <asm/asm.h>
|
||||
#include <asm/cacheops.h>
|
||||
#include <asm/cachectl.h>
|
||||
#include <asm/regdef.h>
|
||||
|
||||
#define IndexInvalidate_I 0x00
|
||||
#define IndexWriteBack_D 0x01
|
||||
|
||||
.set noreorder
|
||||
LEAF(startup)
|
||||
startup:
|
||||
move s0, a0 /* Save the boot loader transfered args */
|
||||
move s1, a1
|
||||
move s2, a2
|
||||
move s3, a3
|
||||
|
||||
la a0, _edata
|
||||
la a1, _end
|
||||
1: sw zero, 0(a0) /* Clear BSS section */
|
||||
bne a1, a0, 1b
|
||||
addu a0, 4
|
||||
|
||||
la sp, (.stack + 8192)
|
||||
|
||||
la a0, __image_begin
|
||||
la a1, IMAGESIZE
|
||||
la a2, LOADADDR
|
||||
la ra, 1f
|
||||
la k0, decompress_kernel
|
||||
jr k0
|
||||
nop
|
||||
1:
|
||||
|
||||
move a0, s0
|
||||
move a1, s1
|
||||
move a2, s2
|
||||
move a3, s3
|
||||
li k0, KERNEL_ENTRY
|
||||
jr k0
|
||||
nop
|
||||
2:
|
||||
b 32
|
||||
END(startup)
|
||||
|
||||
|
||||
LEAF(flushcaches)
|
||||
la t0, 1f
|
||||
la t1, 0xa0000000
|
||||
or t0, t0, t1
|
||||
jr t0
|
||||
nop
|
||||
1:
|
||||
li k0, 0x80000000 # start address
|
||||
li k1, 0x80004000 # end address (16KB I-Cache)
|
||||
subu k1, 128
|
||||
|
||||
2:
|
||||
.set mips3
|
||||
cache IndexWriteBack_D, 0(k0)
|
||||
cache IndexWriteBack_D, 32(k0)
|
||||
cache IndexWriteBack_D, 64(k0)
|
||||
cache IndexWriteBack_D, 96(k0)
|
||||
cache IndexInvalidate_I, 0(k0)
|
||||
cache IndexInvalidate_I, 32(k0)
|
||||
cache IndexInvalidate_I, 64(k0)
|
||||
cache IndexInvalidate_I, 96(k0)
|
||||
.set mips0
|
||||
|
||||
bne k0, k1, 2b
|
||||
addu k0, k0, 128
|
||||
la t0, 3f
|
||||
jr t0
|
||||
nop
|
||||
3:
|
||||
jr ra
|
||||
nop
|
||||
END(flushcaches)
|
||||
|
||||
.comm .stack,4096*2,4
|
||||
@@ -0,0 +1,151 @@
|
||||
OUTPUT_ARCH(mips)
|
||||
ENTRY(startup)
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
|
||||
.init : { *(.init) } =0
|
||||
.text :
|
||||
{
|
||||
_ftext = . ;
|
||||
*(.text)
|
||||
*(.rodata)
|
||||
*(.rodata1)
|
||||
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||
*(.gnu.warning)
|
||||
} =0
|
||||
.kstrtab : { *(.kstrtab) }
|
||||
|
||||
. = ALIGN(16); /* Exception table */
|
||||
__start___ex_table = .;
|
||||
__ex_table : { *(__ex_table) }
|
||||
__stop___ex_table = .;
|
||||
|
||||
__start___dbe_table = .; /* Exception table for data bus errors */
|
||||
__dbe_table : { *(__dbe_table) }
|
||||
__stop___dbe_table = .;
|
||||
|
||||
__start___ksymtab = .; /* Kernel symbol table */
|
||||
__ksymtab : { *(__ksymtab) }
|
||||
__stop___ksymtab = .;
|
||||
|
||||
_etext = .;
|
||||
|
||||
. = ALIGN(8192);
|
||||
.data.init_task : { *(.data.init_task) }
|
||||
|
||||
/* Startup code */
|
||||
. = ALIGN(4096);
|
||||
__init_begin = .;
|
||||
.text.init : { *(.text.init) }
|
||||
.data.init : { *(.data.init) }
|
||||
. = ALIGN(16);
|
||||
__setup_start = .;
|
||||
.setup.init : { *(.setup.init) }
|
||||
__setup_end = .;
|
||||
__initcall_start = .;
|
||||
.initcall.init : { *(.initcall.init) }
|
||||
__initcall_end = .;
|
||||
. = ALIGN(4096); /* Align double page for init_task_union */
|
||||
__init_end = .;
|
||||
|
||||
. = ALIGN(4096);
|
||||
.data.page_aligned : { *(.data.idt) }
|
||||
|
||||
. = ALIGN(32);
|
||||
.data.cacheline_aligned : { *(.data.cacheline_aligned) }
|
||||
|
||||
.fini : { *(.fini) } =0
|
||||
.reginfo : { *(.reginfo) }
|
||||
/* Adjust the address for the data segment. We want to adjust up to
|
||||
the same address within the page on the next page up. It would
|
||||
be more correct to do this:
|
||||
. = .;
|
||||
The current expression does not correctly handle the case of a
|
||||
text segment ending precisely at the end of a page; it causes the
|
||||
data segment to skip a page. The above expression does not have
|
||||
this problem, but it will currently (2/95) cause BFD to allocate
|
||||
a single segment, combining both text and data, for this case.
|
||||
This will prevent the text segment from being shared among
|
||||
multiple executions of the program; I think that is more
|
||||
important than losing a page of the virtual address space (note
|
||||
that no actual memory is lost; the page which is skipped can not
|
||||
be referenced). */
|
||||
. = .;
|
||||
.data :
|
||||
{
|
||||
_fdata = . ;
|
||||
*(.data)
|
||||
|
||||
/* Put the compressed image here, so bss is on the end. */
|
||||
__image_begin = .;
|
||||
*(.image)
|
||||
__image_end = .;
|
||||
/* Align the initial ramdisk image (INITRD) on page boundaries. */
|
||||
. = ALIGN(4096);
|
||||
__ramdisk_begin = .;
|
||||
*(.initrd)
|
||||
__ramdisk_end = .;
|
||||
. = ALIGN(4096);
|
||||
|
||||
CONSTRUCTORS
|
||||
}
|
||||
.data1 : { *(.data1) }
|
||||
_gp = . + 0x8000;
|
||||
.lit8 : { *(.lit8) }
|
||||
.lit4 : { *(.lit4) }
|
||||
.ctors : { *(.ctors) }
|
||||
.dtors : { *(.dtors) }
|
||||
.got : { *(.got.plt) *(.got) }
|
||||
.dynamic : { *(.dynamic) }
|
||||
/* We want the small data sections together, so single-instruction offsets
|
||||
can access them all, and initialized data all before uninitialized, so
|
||||
we can shorten the on-disk segment size. */
|
||||
.sdata : { *(.sdata) }
|
||||
. = ALIGN(4);
|
||||
_edata = .;
|
||||
PROVIDE (edata = .);
|
||||
|
||||
__bss_start = .;
|
||||
_fbss = .;
|
||||
.sbss : { *(.sbss) *(.scommon) }
|
||||
.bss :
|
||||
{
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
_end = . ;
|
||||
PROVIDE (end = .);
|
||||
}
|
||||
|
||||
/* Sections to be discarded */
|
||||
/DISCARD/ :
|
||||
{
|
||||
*(.text.exit)
|
||||
*(.data.exit)
|
||||
*(.exitcall.exit)
|
||||
}
|
||||
|
||||
/* This is the MIPS specific mdebug section. */
|
||||
.mdebug : { *(.mdebug) }
|
||||
/* These are needed for ELF backends which have not yet been
|
||||
converted to the new style linker. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
/* DWARF debug sections.
|
||||
Symbols in the .debug DWARF section are relative to the beginning of the
|
||||
section so we begin .debug at 0. It's not clear yet what needs to happen
|
||||
for the others. */
|
||||
.debug 0 : { *(.debug) }
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
.line 0 : { *(.line) }
|
||||
/* These must appear regardless of . */
|
||||
.gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
|
||||
.gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
|
||||
.comment : { *(.comment) }
|
||||
.note : { *(.note) }
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* linux/arch/mips/boot/compressed/misc.c
|
||||
*
|
||||
* This is a collection of several routines from gzip-1.0.3
|
||||
* adapted for Linux.
|
||||
*
|
||||
* malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
|
||||
*
|
||||
* Adapted for JZSOC by Peter Wei, 2008
|
||||
*
|
||||
*/
|
||||
|
||||
#define size_t int
|
||||
#define NULL 0
|
||||
|
||||
/*
|
||||
* gzip declarations
|
||||
*/
|
||||
|
||||
#define OF(args) args
|
||||
#define STATIC static
|
||||
|
||||
#undef memset
|
||||
#undef memcpy
|
||||
#define memzero(s, n) memset ((s), 0, (n))
|
||||
|
||||
typedef unsigned char uch;
|
||||
typedef unsigned short ush;
|
||||
typedef unsigned long ulg;
|
||||
|
||||
#define WSIZE 0x8000 /* Window size must be at least 32k, */
|
||||
/* and a power of two */
|
||||
|
||||
static uch *inbuf; /* input buffer */
|
||||
static uch window[WSIZE]; /* Sliding window buffer */
|
||||
|
||||
static unsigned insize = 0; /* valid bytes in inbuf */
|
||||
static unsigned inptr = 0; /* index of next byte to be processed in inbuf */
|
||||
static unsigned outcnt = 0; /* bytes in output buffer */
|
||||
|
||||
/* gzip flag byte */
|
||||
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
|
||||
#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
|
||||
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
|
||||
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
|
||||
#define COMMENT 0x10 /* bit 4 set: file comment present */
|
||||
#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
|
||||
#define RESERVED 0xC0 /* bit 6,7: reserved */
|
||||
|
||||
#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
|
||||
|
||||
/* 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 int fill_inbuf(void);
|
||||
static void flush_window(void);
|
||||
static void error(char *m);
|
||||
static void gzip_mark(void **);
|
||||
static void gzip_release(void **);
|
||||
|
||||
void* memset(void* s, int c, size_t n);
|
||||
void* memcpy(void* __dest, __const void* __src, size_t __n);
|
||||
|
||||
extern void flushcaches(void); /* defined in head.S */
|
||||
|
||||
char *input_data;
|
||||
int input_len;
|
||||
|
||||
static long bytes_out = 0;
|
||||
static uch *output_data;
|
||||
static unsigned long output_ptr = 0;
|
||||
|
||||
|
||||
static void *malloc(int size);
|
||||
static void free(void *where);
|
||||
static void error(char *m);
|
||||
static void gzip_mark(void **);
|
||||
static void gzip_release(void **);
|
||||
|
||||
static void puts(const char *str)
|
||||
{
|
||||
}
|
||||
|
||||
extern unsigned char _end[];
|
||||
static unsigned long free_mem_ptr;
|
||||
static unsigned long free_mem_end_ptr;
|
||||
|
||||
#define HEAP_SIZE 0x10000
|
||||
|
||||
#include "../../../../lib/inflate.c"
|
||||
|
||||
static void *malloc(int size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
if (size <0) error("Malloc error\n");
|
||||
if (free_mem_ptr == 0) error("Memory error\n");
|
||||
|
||||
free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
|
||||
|
||||
p = (void *)free_mem_ptr;
|
||||
free_mem_ptr += size;
|
||||
|
||||
if (free_mem_ptr >= free_mem_end_ptr)
|
||||
error("\nOut of memory\n");
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static void free(void *where)
|
||||
{ /* Don't care */
|
||||
}
|
||||
|
||||
static void gzip_mark(void **ptr)
|
||||
{
|
||||
*ptr = (void *) free_mem_ptr;
|
||||
}
|
||||
|
||||
static void gzip_release(void **ptr)
|
||||
{
|
||||
free_mem_ptr = (long) *ptr;
|
||||
}
|
||||
|
||||
void* memset(void* s, int c, size_t n)
|
||||
{
|
||||
int i;
|
||||
char *ss = (char*)s;
|
||||
|
||||
for (i=0;i<n;i++) ss[i] = c;
|
||||
return s;
|
||||
}
|
||||
|
||||
void* memcpy(void* __dest, __const void* __src, size_t __n)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
|
||||
|
||||
for (i = __n >> 3; i > 0; i--) {
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
}
|
||||
|
||||
if (__n & 1 << 2) {
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
}
|
||||
|
||||
if (__n & 1 << 1) {
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
}
|
||||
|
||||
if (__n & 1)
|
||||
*d++ = *s++;
|
||||
|
||||
return __dest;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Fill the input buffer. This is called only when the buffer is empty
|
||||
* and at least one byte is really needed.
|
||||
*/
|
||||
static int fill_inbuf(void)
|
||||
{
|
||||
if (insize != 0) {
|
||||
error("ran out of input data\n");
|
||||
}
|
||||
|
||||
inbuf = input_data;
|
||||
insize = input_len;
|
||||
inptr = 1;
|
||||
return inbuf[0];
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Write the output window window[0..outcnt-1] and update crc and bytes_out.
|
||||
* (Used for the decompressed data only.)
|
||||
*/
|
||||
static void flush_window(void)
|
||||
{
|
||||
ulg c = crc; /* temporary variable */
|
||||
unsigned n;
|
||||
uch *in, *out, ch;
|
||||
|
||||
in = window;
|
||||
out = &output_data[output_ptr];
|
||||
for (n = 0; n < outcnt; n++) {
|
||||
ch = *out++ = *in++;
|
||||
c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
|
||||
}
|
||||
crc = c;
|
||||
bytes_out += (ulg)outcnt;
|
||||
output_ptr += (ulg)outcnt;
|
||||
outcnt = 0;
|
||||
}
|
||||
|
||||
static void error(char *x)
|
||||
{
|
||||
puts("\n\n");
|
||||
puts(x);
|
||||
puts("\n\n -- System halted");
|
||||
|
||||
while(1); /* Halt */
|
||||
}
|
||||
|
||||
void decompress_kernel(unsigned int imageaddr, unsigned int imagesize, unsigned int loadaddr)
|
||||
{
|
||||
input_data = (char *)imageaddr;
|
||||
input_len = imagesize;
|
||||
output_ptr = 0;
|
||||
output_data = (uch *)loadaddr;
|
||||
free_mem_ptr = (unsigned long)_end;
|
||||
free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
|
||||
|
||||
makecrc();
|
||||
puts("Uncompressing Linux...");
|
||||
gunzip();
|
||||
flushcaches();
|
||||
puts("Ok, booting the kernel.");
|
||||
}
|
||||
12
target/linux/xburst/files-2.6.27/arch/mips/boot/tools/entry
Normal file
12
target/linux/xburst/files-2.6.27/arch/mips/boot/tools/entry
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
|
||||
# grab the kernel_entry address from the vmlinux elf image
|
||||
entry=`$1 $2 | grep kernel_entry`
|
||||
|
||||
fs=`echo $entry | grep ffffffff` # check toolchain output
|
||||
|
||||
if [ -n "$fs" ]; then
|
||||
echo "0x"`$1 $2 | grep kernel_entry | cut -c9- | awk '{print $1}'`
|
||||
else
|
||||
echo "0x"`$1 $2 | grep kernel_entry | cut -c1- | awk '{print $1}'`
|
||||
fi
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
HOSTNAME=`uname`
|
||||
if [ "$HOSTNAME" = "Linux" ]; then
|
||||
echo `ls -l $1 | awk '{print $5}'`
|
||||
else
|
||||
echo `ls -l $1 | awk '{print $6}'`
|
||||
fi
|
||||
1348
target/linux/xburst/files-2.6.27/arch/mips/configs/apus_defconfig
Normal file
1348
target/linux/xburst/files-2.6.27/arch/mips/configs/apus_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
1183
target/linux/xburst/files-2.6.27/arch/mips/configs/cetus_defconfig
Normal file
1183
target/linux/xburst/files-2.6.27/arch/mips/configs/cetus_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
1281
target/linux/xburst/files-2.6.27/arch/mips/configs/dipper_defconfig
Normal file
1281
target/linux/xburst/files-2.6.27/arch/mips/configs/dipper_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,892 @@
|
||||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.27
|
||||
# Fri Aug 7 10:22:22 2009
|
||||
#
|
||||
CONFIG_MIPS=y
|
||||
|
||||
#
|
||||
# Machine selection
|
||||
#
|
||||
# CONFIG_JZ4730_PMP is not set
|
||||
# CONFIG_JZ4740_PAVO is not set
|
||||
# CONFIG_JZ4740_LEO is not set
|
||||
# CONFIG_JZ4740_LYRA is not set
|
||||
# CONFIG_JZ4725_DIPPER is not set
|
||||
# CONFIG_JZ4720_VIRGO is not set
|
||||
# CONFIG_JZ4750_FUWA is not set
|
||||
# CONFIG_JZ4750_APUS is not set
|
||||
# CONFIG_JZ4750D_CETUS is not set
|
||||
CONFIG_JZ4760_F4760=y
|
||||
# CONFIG_MACH_ALCHEMY is not set
|
||||
# CONFIG_BASLER_EXCITE is not set
|
||||
# CONFIG_BCM47XX is not set
|
||||
# CONFIG_MIPS_COBALT is not set
|
||||
# CONFIG_MACH_DECSTATION is not set
|
||||
# CONFIG_MACH_JAZZ is not set
|
||||
# CONFIG_LASAT is not set
|
||||
# CONFIG_LEMOTE_FULONG is not set
|
||||
# CONFIG_MIPS_MALTA is not set
|
||||
# CONFIG_MIPS_SIM is not set
|
||||
# CONFIG_MARKEINS is not set
|
||||
# CONFIG_MACH_VR41XX is not set
|
||||
# CONFIG_PNX8550_JBS is not set
|
||||
# CONFIG_PNX8550_STB810 is not set
|
||||
# CONFIG_PMC_MSP is not set
|
||||
# CONFIG_PMC_YOSEMITE is not set
|
||||
# CONFIG_SGI_IP22 is not set
|
||||
# CONFIG_SGI_IP27 is not set
|
||||
# CONFIG_SGI_IP28 is not set
|
||||
# CONFIG_SGI_IP32 is not set
|
||||
# CONFIG_SIBYTE_CRHINE is not set
|
||||
# CONFIG_SIBYTE_CARMEL is not set
|
||||
# CONFIG_SIBYTE_CRHONE is not set
|
||||
# CONFIG_SIBYTE_RHONE is not set
|
||||
# CONFIG_SIBYTE_SWARM is not set
|
||||
# CONFIG_SIBYTE_LITTLESUR is not set
|
||||
# CONFIG_SIBYTE_SENTOSA is not set
|
||||
# CONFIG_SIBYTE_BIGSUR is not set
|
||||
# CONFIG_SNI_RM is not set
|
||||
# CONFIG_MACH_TX39XX is not set
|
||||
# CONFIG_MACH_TX49XX is not set
|
||||
# CONFIG_MIKROTIK_RB532 is not set
|
||||
# CONFIG_WR_PPMC is not set
|
||||
CONFIG_SOC_JZ4760=y
|
||||
CONFIG_JZ_FPGA=y
|
||||
CONFIG_JZSOC=y
|
||||
CONFIG_JZRISC=y
|
||||
CONFIG_RWSEM_GENERIC_SPINLOCK=y
|
||||
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
|
||||
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
|
||||
CONFIG_ARCH_SUPPORTS_OPROFILE=y
|
||||
CONFIG_GENERIC_FIND_NEXT_BIT=y
|
||||
CONFIG_GENERIC_HWEIGHT=y
|
||||
CONFIG_GENERIC_CALIBRATE_DELAY=y
|
||||
CONFIG_GENERIC_CLOCKEVENTS=y
|
||||
CONFIG_GENERIC_TIME=y
|
||||
CONFIG_GENERIC_CMOS_UPDATE=y
|
||||
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
|
||||
# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
|
||||
CONFIG_DMA_NONCOHERENT=y
|
||||
CONFIG_DMA_NEED_PCI_MAP_STATE=y
|
||||
# CONFIG_HOTPLUG_CPU is not set
|
||||
# CONFIG_NO_IOPORT is not set
|
||||
# CONFIG_CPU_BIG_ENDIAN is not set
|
||||
CONFIG_CPU_LITTLE_ENDIAN=y
|
||||
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
|
||||
CONFIG_MIPS_L1_CACHE_SHIFT=5
|
||||
|
||||
#
|
||||
# CPU selection
|
||||
#
|
||||
# CONFIG_CPU_LOONGSON2 is not set
|
||||
CONFIG_CPU_MIPS32_R1=y
|
||||
# CONFIG_CPU_MIPS32_R2 is not set
|
||||
# CONFIG_CPU_MIPS64_R1 is not set
|
||||
# CONFIG_CPU_MIPS64_R2 is not set
|
||||
# CONFIG_CPU_R3000 is not set
|
||||
# CONFIG_CPU_TX39XX is not set
|
||||
# CONFIG_CPU_VR41XX is not set
|
||||
# CONFIG_CPU_R4300 is not set
|
||||
# CONFIG_CPU_R4X00 is not set
|
||||
# CONFIG_CPU_TX49XX is not set
|
||||
# CONFIG_CPU_R5000 is not set
|
||||
# CONFIG_CPU_R5432 is not set
|
||||
# CONFIG_CPU_R6000 is not set
|
||||
# CONFIG_CPU_NEVADA is not set
|
||||
# CONFIG_CPU_R8000 is not set
|
||||
# CONFIG_CPU_R10000 is not set
|
||||
# CONFIG_CPU_RM7000 is not set
|
||||
# CONFIG_CPU_RM9000 is not set
|
||||
# CONFIG_CPU_SB1 is not set
|
||||
CONFIG_SYS_HAS_CPU_MIPS32_R1=y
|
||||
CONFIG_CPU_MIPS32=y
|
||||
CONFIG_CPU_MIPSR1=y
|
||||
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
|
||||
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
|
||||
|
||||
#
|
||||
# Kernel type
|
||||
#
|
||||
CONFIG_32BIT=y
|
||||
# CONFIG_64BIT is not set
|
||||
CONFIG_PAGE_SIZE_4KB=y
|
||||
# CONFIG_PAGE_SIZE_8KB is not set
|
||||
# CONFIG_PAGE_SIZE_16KB is not set
|
||||
# CONFIG_PAGE_SIZE_64KB is not set
|
||||
CONFIG_CPU_HAS_PREFETCH=y
|
||||
CONFIG_MIPS_MT_DISABLED=y
|
||||
# CONFIG_MIPS_MT_SMP is not set
|
||||
# CONFIG_MIPS_MT_SMTC is not set
|
||||
CONFIG_CPU_HAS_LLSC=y
|
||||
CONFIG_CPU_HAS_SYNC=y
|
||||
CONFIG_GENERIC_HARDIRQS=y
|
||||
CONFIG_GENERIC_IRQ_PROBE=y
|
||||
CONFIG_CPU_SUPPORTS_HIGHMEM=y
|
||||
CONFIG_ARCH_FLATMEM_ENABLE=y
|
||||
CONFIG_ARCH_POPULATES_NODE_MAP=y
|
||||
CONFIG_SELECT_MEMORY_MODEL=y
|
||||
CONFIG_FLATMEM_MANUAL=y
|
||||
# CONFIG_DISCONTIGMEM_MANUAL is not set
|
||||
# CONFIG_SPARSEMEM_MANUAL is not set
|
||||
CONFIG_FLATMEM=y
|
||||
CONFIG_FLAT_NODE_MEM_MAP=y
|
||||
# CONFIG_SPARSEMEM_STATIC is not set
|
||||
# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
|
||||
CONFIG_PAGEFLAGS_EXTENDED=y
|
||||
CONFIG_SPLIT_PTLOCK_CPUS=4
|
||||
# CONFIG_RESOURCES_64BIT is not set
|
||||
CONFIG_ZONE_DMA_FLAG=0
|
||||
CONFIG_VIRT_TO_BUS=y
|
||||
# CONFIG_TICK_ONESHOT is not set
|
||||
# CONFIG_NO_HZ is not set
|
||||
# CONFIG_HIGH_RES_TIMERS is not set
|
||||
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
|
||||
CONFIG_FORCE_MAX_ZONEORDER=13
|
||||
# CONFIG_HZ_48 is not set
|
||||
CONFIG_HZ_100=y
|
||||
# CONFIG_HZ_128 is not set
|
||||
# CONFIG_HZ_250 is not set
|
||||
# CONFIG_HZ_256 is not set
|
||||
# CONFIG_HZ_1000 is not set
|
||||
# CONFIG_HZ_1024 is not set
|
||||
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
|
||||
CONFIG_HZ=100
|
||||
# CONFIG_PREEMPT_NONE is not set
|
||||
# CONFIG_PREEMPT_VOLUNTARY is not set
|
||||
CONFIG_PREEMPT=y
|
||||
# CONFIG_PREEMPT_RCU is not set
|
||||
# CONFIG_KEXEC is not set
|
||||
CONFIG_SECCOMP=y
|
||||
CONFIG_LOCKDEP_SUPPORT=y
|
||||
CONFIG_STACKTRACE_SUPPORT=y
|
||||
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
|
||||
|
||||
#
|
||||
# General setup
|
||||
#
|
||||
CONFIG_EXPERIMENTAL=y
|
||||
CONFIG_BROKEN_ON_SMP=y
|
||||
CONFIG_LOCK_KERNEL=y
|
||||
CONFIG_INIT_ENV_ARG_LIMIT=32
|
||||
CONFIG_LOCALVERSION=""
|
||||
CONFIG_LOCALVERSION_AUTO=y
|
||||
CONFIG_SWAP=y
|
||||
CONFIG_SYSVIPC=y
|
||||
CONFIG_SYSVIPC_SYSCTL=y
|
||||
# CONFIG_POSIX_MQUEUE is not set
|
||||
# CONFIG_BSD_PROCESS_ACCT is not set
|
||||
# CONFIG_TASKSTATS is not set
|
||||
# CONFIG_AUDIT is not set
|
||||
# CONFIG_IKCONFIG is not set
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
# CONFIG_CGROUPS is not set
|
||||
# CONFIG_GROUP_SCHED is not set
|
||||
CONFIG_SYSFS_DEPRECATED=y
|
||||
CONFIG_SYSFS_DEPRECATED_V2=y
|
||||
CONFIG_RELAY=y
|
||||
# CONFIG_NAMESPACES is not set
|
||||
# CONFIG_BLK_DEV_INITRD is not set
|
||||
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
||||
CONFIG_SYSCTL=y
|
||||
CONFIG_PANIC_TIMEOUT=0
|
||||
CONFIG_EMBEDDED=y
|
||||
CONFIG_SYSCTL_SYSCALL=y
|
||||
CONFIG_KALLSYMS=y
|
||||
# CONFIG_KALLSYMS_EXTRA_PASS is not set
|
||||
CONFIG_HOTPLUG=y
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_BUG=y
|
||||
CONFIG_ELF_CORE=y
|
||||
CONFIG_PCSPKR_PLATFORM=y
|
||||
CONFIG_COMPAT_BRK=y
|
||||
CONFIG_BASE_FULL=y
|
||||
CONFIG_FUTEX=y
|
||||
CONFIG_ANON_INODES=y
|
||||
CONFIG_EPOLL=y
|
||||
CONFIG_SIGNALFD=y
|
||||
CONFIG_TIMERFD=y
|
||||
CONFIG_EVENTFD=y
|
||||
CONFIG_SHMEM=y
|
||||
CONFIG_ASHMEM=y
|
||||
CONFIG_VM_EVENT_COUNTERS=y
|
||||
CONFIG_SLAB=y
|
||||
# CONFIG_SLUB is not set
|
||||
# CONFIG_SLOB is not set
|
||||
# CONFIG_PROFILING is not set
|
||||
# CONFIG_MARKERS is not set
|
||||
CONFIG_HAVE_OPROFILE=y
|
||||
# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
|
||||
# CONFIG_HAVE_IOREMAP_PROT is not set
|
||||
# CONFIG_HAVE_KPROBES is not set
|
||||
# CONFIG_HAVE_KRETPROBES is not set
|
||||
# CONFIG_HAVE_ARCH_TRACEHOOK is not set
|
||||
# CONFIG_HAVE_DMA_ATTRS is not set
|
||||
# CONFIG_USE_GENERIC_SMP_HELPERS is not set
|
||||
# CONFIG_HAVE_CLK is not set
|
||||
CONFIG_PROC_PAGE_MONITOR=y
|
||||
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
|
||||
CONFIG_SLABINFO=y
|
||||
CONFIG_RT_MUTEXES=y
|
||||
# CONFIG_TINY_SHMEM is not set
|
||||
CONFIG_BASE_SMALL=0
|
||||
CONFIG_MODULES=y
|
||||
# CONFIG_MODULE_FORCE_LOAD is not set
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
# CONFIG_MODULE_FORCE_UNLOAD is not set
|
||||
CONFIG_MODVERSIONS=y
|
||||
CONFIG_MODULE_SRCVERSION_ALL=y
|
||||
CONFIG_KMOD=y
|
||||
CONFIG_BLOCK=y
|
||||
# CONFIG_LBD is not set
|
||||
# CONFIG_BLK_DEV_IO_TRACE is not set
|
||||
# CONFIG_LSF is not set
|
||||
# CONFIG_BLK_DEV_BSG is not set
|
||||
# CONFIG_BLK_DEV_INTEGRITY is not set
|
||||
|
||||
#
|
||||
# IO Schedulers
|
||||
#
|
||||
CONFIG_IOSCHED_NOOP=y
|
||||
CONFIG_IOSCHED_AS=y
|
||||
CONFIG_IOSCHED_DEADLINE=y
|
||||
CONFIG_IOSCHED_CFQ=y
|
||||
CONFIG_DEFAULT_AS=y
|
||||
# CONFIG_DEFAULT_DEADLINE is not set
|
||||
# CONFIG_DEFAULT_CFQ is not set
|
||||
# CONFIG_DEFAULT_NOOP is not set
|
||||
CONFIG_DEFAULT_IOSCHED="anticipatory"
|
||||
CONFIG_CLASSIC_RCU=y
|
||||
|
||||
#
|
||||
# Bus options (PCI, PCMCIA, EISA, ISA, TC)
|
||||
#
|
||||
# CONFIG_ARCH_SUPPORTS_MSI is not set
|
||||
CONFIG_MMU=y
|
||||
# CONFIG_PCCARD is not set
|
||||
|
||||
#
|
||||
# Executable file formats
|
||||
#
|
||||
CONFIG_BINFMT_ELF=y
|
||||
# CONFIG_BINFMT_MISC is not set
|
||||
CONFIG_TRAD_SIGNALS=y
|
||||
|
||||
#
|
||||
# CPU Frequency scaling
|
||||
#
|
||||
# CONFIG_CPU_FREQ_JZ is not set
|
||||
|
||||
#
|
||||
# Power management options
|
||||
#
|
||||
CONFIG_ARCH_SUSPEND_POSSIBLE=y
|
||||
# CONFIG_PM is not set
|
||||
CONFIG_NET=y
|
||||
|
||||
#
|
||||
# Networking options
|
||||
#
|
||||
CONFIG_PACKET=y
|
||||
# CONFIG_PACKET_MMAP is not set
|
||||
CONFIG_UNIX=y
|
||||
# CONFIG_NET_KEY is not set
|
||||
CONFIG_INET=y
|
||||
CONFIG_IP_MULTICAST=y
|
||||
# CONFIG_IP_ADVANCED_ROUTER is not set
|
||||
CONFIG_IP_FIB_HASH=y
|
||||
CONFIG_IP_PNP=y
|
||||
CONFIG_IP_PNP_DHCP=y
|
||||
CONFIG_IP_PNP_BOOTP=y
|
||||
# CONFIG_IP_PNP_RARP is not set
|
||||
# CONFIG_NET_IPIP is not set
|
||||
# CONFIG_NET_IPGRE is not set
|
||||
# CONFIG_IP_MROUTE is not set
|
||||
# CONFIG_ARPD is not set
|
||||
# CONFIG_SYN_COOKIES is not set
|
||||
# CONFIG_INET_AH is not set
|
||||
# CONFIG_INET_ESP is not set
|
||||
# CONFIG_INET_IPCOMP is not set
|
||||
# CONFIG_INET_XFRM_TUNNEL is not set
|
||||
# CONFIG_INET_TUNNEL is not set
|
||||
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
|
||||
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
|
||||
# CONFIG_INET_XFRM_MODE_BEET is not set
|
||||
# CONFIG_INET_LRO is not set
|
||||
CONFIG_INET_DIAG=m
|
||||
CONFIG_INET_TCP_DIAG=m
|
||||
# CONFIG_TCP_CONG_ADVANCED is not set
|
||||
CONFIG_TCP_CONG_CUBIC=y
|
||||
CONFIG_DEFAULT_TCP_CONG="cubic"
|
||||
# CONFIG_TCP_MD5SIG is not set
|
||||
# CONFIG_IPV6 is not set
|
||||
CONFIG_ANDROID_PARANOID_NETWORK=y
|
||||
# CONFIG_NETWORK_SECMARK is not set
|
||||
# CONFIG_NETFILTER is not set
|
||||
# CONFIG_IP_DCCP is not set
|
||||
# CONFIG_IP_SCTP is not set
|
||||
# CONFIG_TIPC is not set
|
||||
# CONFIG_ATM is not set
|
||||
# CONFIG_BRIDGE is not set
|
||||
# CONFIG_VLAN_8021Q is not set
|
||||
# CONFIG_DECNET is not set
|
||||
# CONFIG_LLC2 is not set
|
||||
# CONFIG_IPX is not set
|
||||
# CONFIG_ATALK is not set
|
||||
# CONFIG_X25 is not set
|
||||
# CONFIG_LAPB is not set
|
||||
# CONFIG_ECONET is not set
|
||||
# CONFIG_WAN_ROUTER is not set
|
||||
# CONFIG_NET_SCHED is not set
|
||||
|
||||
#
|
||||
# Network testing
|
||||
#
|
||||
# CONFIG_NET_PKTGEN is not set
|
||||
# CONFIG_HAMRADIO is not set
|
||||
# CONFIG_CAN is not set
|
||||
# CONFIG_IRDA is not set
|
||||
# CONFIG_BT is not set
|
||||
# CONFIG_AF_RXRPC is not set
|
||||
|
||||
#
|
||||
# Wireless
|
||||
#
|
||||
# CONFIG_CFG80211 is not set
|
||||
# CONFIG_WIRELESS_EXT is not set
|
||||
# CONFIG_MAC80211 is not set
|
||||
# CONFIG_IEEE80211 is not set
|
||||
# CONFIG_RFKILL is not set
|
||||
# CONFIG_NET_9P is not set
|
||||
|
||||
#
|
||||
# Device Drivers
|
||||
#
|
||||
|
||||
#
|
||||
# Generic Driver Options
|
||||
#
|
||||
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
|
||||
CONFIG_STANDALONE=y
|
||||
CONFIG_PREVENT_FIRMWARE_BUILD=y
|
||||
# CONFIG_FW_LOADER is not set
|
||||
# CONFIG_SYS_HYPERVISOR is not set
|
||||
# CONFIG_CONNECTOR is not set
|
||||
# CONFIG_MTD is not set
|
||||
# CONFIG_PARPORT is not set
|
||||
CONFIG_BLK_DEV=y
|
||||
# CONFIG_BLK_DEV_COW_COMMON is not set
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
|
||||
# CONFIG_BLK_DEV_NBD is not set
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_COUNT=16
|
||||
CONFIG_BLK_DEV_RAM_SIZE=4096
|
||||
# CONFIG_BLK_DEV_XIP is not set
|
||||
# CONFIG_CDROM_PKTCDVD is not set
|
||||
# CONFIG_ATA_OVER_ETH is not set
|
||||
# CONFIG_BLK_DEV_HD is not set
|
||||
# CONFIG_MISC_DEVICES is not set
|
||||
CONFIG_HAVE_IDE=y
|
||||
# CONFIG_IDE is not set
|
||||
|
||||
#
|
||||
# SCSI device support
|
||||
#
|
||||
# CONFIG_RAID_ATTRS is not set
|
||||
# CONFIG_SCSI is not set
|
||||
# CONFIG_SCSI_DMA is not set
|
||||
# CONFIG_SCSI_NETLINK is not set
|
||||
# CONFIG_ATA is not set
|
||||
# CONFIG_MD is not set
|
||||
CONFIG_NETDEVICES=y
|
||||
# CONFIG_DUMMY is not set
|
||||
# CONFIG_BONDING is not set
|
||||
# CONFIG_MACVLAN is not set
|
||||
# CONFIG_EQUALIZER is not set
|
||||
# CONFIG_TUN is not set
|
||||
# CONFIG_VETH is not set
|
||||
CONFIG_PHYLIB=y
|
||||
|
||||
#
|
||||
# MII PHY device drivers
|
||||
#
|
||||
# CONFIG_MARVELL_PHY is not set
|
||||
# CONFIG_DAVICOM_PHY is not set
|
||||
# CONFIG_QSEMI_PHY is not set
|
||||
# CONFIG_LXT_PHY is not set
|
||||
# CONFIG_CICADA_PHY is not set
|
||||
# CONFIG_VITESSE_PHY is not set
|
||||
# CONFIG_SMSC_PHY is not set
|
||||
# CONFIG_BROADCOM_PHY is not set
|
||||
# CONFIG_ICPLUS_PHY is not set
|
||||
# CONFIG_REALTEK_PHY is not set
|
||||
# CONFIG_FIXED_PHY is not set
|
||||
# CONFIG_MDIO_BITBANG is not set
|
||||
CONFIG_NET_ETHERNET=y
|
||||
CONFIG_MII=y
|
||||
# CONFIG_JZ_ETH is not set
|
||||
CONFIG_JZ4760_ETH=y
|
||||
# CONFIG_AX88796 is not set
|
||||
# CONFIG_DM9000 is not set
|
||||
# CONFIG_IBM_NEW_EMAC_ZMII is not set
|
||||
# CONFIG_IBM_NEW_EMAC_RGMII is not set
|
||||
# CONFIG_IBM_NEW_EMAC_TAH is not set
|
||||
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
|
||||
# CONFIG_B44 is not set
|
||||
# CONFIG_NETDEV_1000 is not set
|
||||
# CONFIG_NETDEV_10000 is not set
|
||||
|
||||
#
|
||||
# Wireless LAN
|
||||
#
|
||||
# CONFIG_WLAN_PRE80211 is not set
|
||||
# CONFIG_WLAN_80211 is not set
|
||||
# CONFIG_IWLWIFI_LEDS is not set
|
||||
# CONFIG_WAN is not set
|
||||
# CONFIG_PPP is not set
|
||||
# CONFIG_SLIP is not set
|
||||
# CONFIG_NETCONSOLE is not set
|
||||
# CONFIG_NETPOLL is not set
|
||||
# CONFIG_NET_POLL_CONTROLLER is not set
|
||||
# CONFIG_ISDN is not set
|
||||
# CONFIG_PHONE is not set
|
||||
|
||||
#
|
||||
# Input device support
|
||||
#
|
||||
CONFIG_INPUT=y
|
||||
# CONFIG_INPUT_FF_MEMLESS is not set
|
||||
# CONFIG_INPUT_POLLDEV is not set
|
||||
|
||||
#
|
||||
# Userland interfaces
|
||||
#
|
||||
# CONFIG_INPUT_MOUSEDEV is not set
|
||||
# CONFIG_INPUT_JOYDEV is not set
|
||||
CONFIG_INPUT_EVDEV=y
|
||||
# CONFIG_INPUT_EVBUG is not set
|
||||
# CONFIG_INPUT_KEYRESET is not set
|
||||
|
||||
#
|
||||
# Input Device Drivers
|
||||
#
|
||||
CONFIG_INPUT_KEYBOARD=y
|
||||
# CONFIG_KEYBOARD_ATKBD is not set
|
||||
# CONFIG_KEYBOARD_SUNKBD is not set
|
||||
# CONFIG_KEYBOARD_LKKBD is not set
|
||||
# CONFIG_KEYBOARD_XTKBD is not set
|
||||
# CONFIG_KEYBOARD_NEWTON is not set
|
||||
# CONFIG_KEYBOARD_STOWAWAY is not set
|
||||
# CONFIG_KEYBOARD_JZ_GPIO is not set
|
||||
# CONFIG_KEYBOARD_JZ is not set
|
||||
# CONFIG_KEYBOARD_JZ_5x5 is not set
|
||||
# CONFIG_INPUT_MOUSE is not set
|
||||
# CONFIG_INPUT_JOYSTICK is not set
|
||||
# CONFIG_INPUT_TABLET is not set
|
||||
CONFIG_INPUT_TOUCHSCREEN=y
|
||||
# CONFIG_TOUCHSCREEN_FUJITSU is not set
|
||||
# CONFIG_TOUCHSCREEN_GUNZE is not set
|
||||
# CONFIG_TOUCHSCREEN_ELO is not set
|
||||
# CONFIG_TOUCHSCREEN_MTOUCH is not set
|
||||
# CONFIG_TOUCHSCREEN_INEXIO is not set
|
||||
# CONFIG_TOUCHSCREEN_JZ is not set
|
||||
# CONFIG_TOUCHSCREEN_MK712 is not set
|
||||
# CONFIG_TOUCHSCREEN_PENMOUNT is not set
|
||||
# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
|
||||
# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
|
||||
# CONFIG_TOUCHSCREEN_UCB1400 is not set
|
||||
# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
|
||||
# CONFIG_INPUT_MISC is not set
|
||||
|
||||
#
|
||||
# Hardware I/O ports
|
||||
#
|
||||
CONFIG_SERIO=y
|
||||
# CONFIG_SERIO_I8042 is not set
|
||||
CONFIG_SERIO_SERPORT=y
|
||||
# CONFIG_SERIO_LIBPS2 is not set
|
||||
# CONFIG_SERIO_RAW is not set
|
||||
# CONFIG_GAMEPORT is not set
|
||||
|
||||
#
|
||||
# Character devices
|
||||
#
|
||||
CONFIG_VT=y
|
||||
CONFIG_CONSOLE_TRANSLATIONS=y
|
||||
CONFIG_VT_CONSOLE=y
|
||||
CONFIG_HW_CONSOLE=y
|
||||
CONFIG_VT_HW_CONSOLE_BINDING=y
|
||||
CONFIG_DEVMEM=y
|
||||
CONFIG_DEVKMEM=y
|
||||
# CONFIG_SERIAL_NONSTANDARD is not set
|
||||
|
||||
#
|
||||
# Serial drivers
|
||||
#
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_NR_UARTS=4
|
||||
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
|
||||
# CONFIG_SERIAL_8250_EXTENDED is not set
|
||||
|
||||
#
|
||||
# Non-8250 serial port support
|
||||
#
|
||||
CONFIG_SERIAL_CORE=y
|
||||
CONFIG_SERIAL_CORE_CONSOLE=y
|
||||
CONFIG_UNIX98_PTYS=y
|
||||
CONFIG_LEGACY_PTYS=y
|
||||
CONFIG_LEGACY_PTY_COUNT=2
|
||||
# CONFIG_IPMI_HANDLER is not set
|
||||
# CONFIG_HW_RANDOM is not set
|
||||
# CONFIG_R3964 is not set
|
||||
# CONFIG_RAW_DRIVER is not set
|
||||
# CONFIG_TCG_TPM is not set
|
||||
# CONFIG_I2C is not set
|
||||
# CONFIG_SPI is not set
|
||||
# CONFIG_W1 is not set
|
||||
# CONFIG_POWER_SUPPLY is not set
|
||||
# CONFIG_HWMON is not set
|
||||
# CONFIG_THERMAL is not set
|
||||
# CONFIG_THERMAL_HWMON is not set
|
||||
# CONFIG_WATCHDOG is not set
|
||||
|
||||
#
|
||||
# Sonics Silicon Backplane
|
||||
#
|
||||
CONFIG_SSB_POSSIBLE=y
|
||||
# CONFIG_SSB is not set
|
||||
|
||||
#
|
||||
# Multifunction device drivers
|
||||
#
|
||||
# CONFIG_MFD_CORE is not set
|
||||
# CONFIG_MFD_SM501 is not set
|
||||
# CONFIG_HTC_PASIC3 is not set
|
||||
# CONFIG_MFD_TMIO is not set
|
||||
|
||||
#
|
||||
# Multimedia devices
|
||||
#
|
||||
|
||||
#
|
||||
# Multimedia core support
|
||||
#
|
||||
# CONFIG_VIDEO_DEV is not set
|
||||
# CONFIG_DVB_CORE is not set
|
||||
# CONFIG_VIDEO_MEDIA is not set
|
||||
|
||||
#
|
||||
# Multimedia drivers
|
||||
#
|
||||
# CONFIG_DAB is not set
|
||||
|
||||
#
|
||||
# Graphics support
|
||||
#
|
||||
# CONFIG_VGASTATE is not set
|
||||
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
|
||||
# CONFIG_FB is not set
|
||||
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
|
||||
|
||||
#
|
||||
# Display device support
|
||||
#
|
||||
# CONFIG_DISPLAY_SUPPORT is not set
|
||||
|
||||
#
|
||||
# Console display driver support
|
||||
#
|
||||
# CONFIG_VGA_CONSOLE is not set
|
||||
CONFIG_DUMMY_CONSOLE=y
|
||||
# CONFIG_SOUND is not set
|
||||
# CONFIG_HID_SUPPORT is not set
|
||||
# CONFIG_USB_SUPPORT is not set
|
||||
# CONFIG_MMC is not set
|
||||
# CONFIG_MEMSTICK is not set
|
||||
# CONFIG_NEW_LEDS is not set
|
||||
# CONFIG_SWITCH is not set
|
||||
# CONFIG_ACCESSIBILITY is not set
|
||||
CONFIG_RTC_LIB=y
|
||||
# CONFIG_RTC_CLASS is not set
|
||||
# CONFIG_DMADEVICES is not set
|
||||
# CONFIG_UIO is not set
|
||||
|
||||
#
|
||||
# File systems
|
||||
#
|
||||
CONFIG_EXT2_FS=y
|
||||
CONFIG_EXT2_FS_XATTR=y
|
||||
# CONFIG_EXT2_FS_POSIX_ACL is not set
|
||||
# CONFIG_EXT2_FS_SECURITY is not set
|
||||
# CONFIG_EXT2_FS_XIP is not set
|
||||
# CONFIG_EXT3_FS is not set
|
||||
# CONFIG_EXT4DEV_FS is not set
|
||||
CONFIG_FS_MBCACHE=y
|
||||
# CONFIG_REISERFS_FS is not set
|
||||
# CONFIG_JFS_FS is not set
|
||||
CONFIG_FS_POSIX_ACL=y
|
||||
# CONFIG_XFS_FS is not set
|
||||
# CONFIG_OCFS2_FS is not set
|
||||
CONFIG_DNOTIFY=y
|
||||
CONFIG_INOTIFY=y
|
||||
CONFIG_INOTIFY_USER=y
|
||||
# CONFIG_QUOTA is not set
|
||||
# CONFIG_AUTOFS_FS is not set
|
||||
# CONFIG_AUTOFS4_FS is not set
|
||||
# CONFIG_FUSE_FS is not set
|
||||
|
||||
#
|
||||
# CD-ROM/DVD Filesystems
|
||||
#
|
||||
# CONFIG_ISO9660_FS is not set
|
||||
# CONFIG_UDF_FS is not set
|
||||
|
||||
#
|
||||
# DOS/FAT/NT Filesystems
|
||||
#
|
||||
CONFIG_FAT_FS=y
|
||||
CONFIG_MSDOS_FS=y
|
||||
CONFIG_VFAT_FS=y
|
||||
CONFIG_FAT_DEFAULT_CODEPAGE=437
|
||||
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
|
||||
# CONFIG_NTFS_FS is not set
|
||||
|
||||
#
|
||||
# Pseudo filesystems
|
||||
#
|
||||
CONFIG_PROC_FS=y
|
||||
CONFIG_PROC_KCORE=y
|
||||
CONFIG_PROC_SYSCTL=y
|
||||
CONFIG_SYSFS=y
|
||||
CONFIG_TMPFS=y
|
||||
# CONFIG_TMPFS_POSIX_ACL is not set
|
||||
# CONFIG_HUGETLB_PAGE is not set
|
||||
# CONFIG_CONFIGFS_FS is not set
|
||||
|
||||
#
|
||||
# Miscellaneous filesystems
|
||||
#
|
||||
# CONFIG_ADFS_FS is not set
|
||||
# CONFIG_AFFS_FS is not set
|
||||
# CONFIG_HFS_FS is not set
|
||||
# CONFIG_HFSPLUS_FS is not set
|
||||
# CONFIG_BEFS_FS is not set
|
||||
# CONFIG_BFS_FS is not set
|
||||
# CONFIG_EFS_FS is not set
|
||||
# CONFIG_CRAMFS is not set
|
||||
# CONFIG_VXFS_FS is not set
|
||||
CONFIG_MINIX_FS=y
|
||||
# CONFIG_OMFS_FS is not set
|
||||
# CONFIG_HPFS_FS is not set
|
||||
# CONFIG_QNX4FS_FS is not set
|
||||
# CONFIG_ROMFS_FS is not set
|
||||
# CONFIG_SYSV_FS is not set
|
||||
# CONFIG_UFS_FS is not set
|
||||
CONFIG_NETWORK_FILESYSTEMS=y
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3=y
|
||||
CONFIG_NFS_V3_ACL=y
|
||||
CONFIG_NFS_V4=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
# CONFIG_NFSD is not set
|
||||
CONFIG_LOCKD=y
|
||||
CONFIG_LOCKD_V4=y
|
||||
CONFIG_NFS_ACL_SUPPORT=y
|
||||
CONFIG_NFS_COMMON=y
|
||||
CONFIG_SUNRPC=y
|
||||
CONFIG_SUNRPC_GSS=y
|
||||
CONFIG_RPCSEC_GSS_KRB5=y
|
||||
# CONFIG_RPCSEC_GSS_SPKM3 is not set
|
||||
# CONFIG_SMB_FS is not set
|
||||
# CONFIG_CIFS is not set
|
||||
# CONFIG_NCP_FS is not set
|
||||
# CONFIG_CODA_FS is not set
|
||||
# CONFIG_AFS_FS is not set
|
||||
|
||||
#
|
||||
# Partition Types
|
||||
#
|
||||
CONFIG_PARTITION_ADVANCED=y
|
||||
# CONFIG_ACORN_PARTITION is not set
|
||||
# CONFIG_OSF_PARTITION is not set
|
||||
# CONFIG_AMIGA_PARTITION is not set
|
||||
# CONFIG_ATARI_PARTITION is not set
|
||||
# CONFIG_MAC_PARTITION is not set
|
||||
CONFIG_MSDOS_PARTITION=y
|
||||
# CONFIG_BSD_DISKLABEL is not set
|
||||
# CONFIG_MINIX_SUBPARTITION is not set
|
||||
# CONFIG_SOLARIS_X86_PARTITION is not set
|
||||
# CONFIG_UNIXWARE_DISKLABEL is not set
|
||||
# CONFIG_LDM_PARTITION is not set
|
||||
# CONFIG_SGI_PARTITION is not set
|
||||
# CONFIG_ULTRIX_PARTITION is not set
|
||||
# CONFIG_SUN_PARTITION is not set
|
||||
# CONFIG_KARMA_PARTITION is not set
|
||||
# CONFIG_EFI_PARTITION is not set
|
||||
# CONFIG_SYSV68_PARTITION is not set
|
||||
CONFIG_NLS=y
|
||||
CONFIG_NLS_DEFAULT="iso8859-1"
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
# CONFIG_NLS_CODEPAGE_737 is not set
|
||||
# CONFIG_NLS_CODEPAGE_775 is not set
|
||||
# CONFIG_NLS_CODEPAGE_850 is not set
|
||||
# CONFIG_NLS_CODEPAGE_852 is not set
|
||||
# CONFIG_NLS_CODEPAGE_855 is not set
|
||||
# CONFIG_NLS_CODEPAGE_857 is not set
|
||||
# CONFIG_NLS_CODEPAGE_860 is not set
|
||||
# CONFIG_NLS_CODEPAGE_861 is not set
|
||||
# CONFIG_NLS_CODEPAGE_862 is not set
|
||||
# CONFIG_NLS_CODEPAGE_863 is not set
|
||||
# CONFIG_NLS_CODEPAGE_864 is not set
|
||||
# CONFIG_NLS_CODEPAGE_865 is not set
|
||||
# CONFIG_NLS_CODEPAGE_866 is not set
|
||||
# CONFIG_NLS_CODEPAGE_869 is not set
|
||||
CONFIG_NLS_CODEPAGE_936=y
|
||||
# CONFIG_NLS_CODEPAGE_950 is not set
|
||||
# CONFIG_NLS_CODEPAGE_932 is not set
|
||||
# CONFIG_NLS_CODEPAGE_949 is not set
|
||||
# CONFIG_NLS_CODEPAGE_874 is not set
|
||||
# CONFIG_NLS_ISO8859_8 is not set
|
||||
# CONFIG_NLS_CODEPAGE_1250 is not set
|
||||
# CONFIG_NLS_CODEPAGE_1251 is not set
|
||||
CONFIG_NLS_ASCII=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
# CONFIG_NLS_ISO8859_2 is not set
|
||||
# CONFIG_NLS_ISO8859_3 is not set
|
||||
# CONFIG_NLS_ISO8859_4 is not set
|
||||
# CONFIG_NLS_ISO8859_5 is not set
|
||||
# CONFIG_NLS_ISO8859_6 is not set
|
||||
# CONFIG_NLS_ISO8859_7 is not set
|
||||
# CONFIG_NLS_ISO8859_9 is not set
|
||||
# CONFIG_NLS_ISO8859_13 is not set
|
||||
# CONFIG_NLS_ISO8859_14 is not set
|
||||
# CONFIG_NLS_ISO8859_15 is not set
|
||||
# CONFIG_NLS_KOI8_R is not set
|
||||
# CONFIG_NLS_KOI8_U is not set
|
||||
# CONFIG_NLS_UTF8 is not set
|
||||
# CONFIG_DLM is not set
|
||||
|
||||
#
|
||||
# Kernel hacking
|
||||
#
|
||||
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
|
||||
# CONFIG_PRINTK_TIME is not set
|
||||
CONFIG_ENABLE_WARN_DEPRECATED=y
|
||||
CONFIG_ENABLE_MUST_CHECK=y
|
||||
CONFIG_FRAME_WARN=1024
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
# CONFIG_UNUSED_SYMBOLS is not set
|
||||
# CONFIG_DEBUG_FS is not set
|
||||
# CONFIG_HEADERS_CHECK is not set
|
||||
# CONFIG_DEBUG_KERNEL is not set
|
||||
# CONFIG_DEBUG_MEMORY_INIT is not set
|
||||
# CONFIG_SYSCTL_SYSCALL_CHECK is not set
|
||||
# CONFIG_SAMPLES is not set
|
||||
CONFIG_HAVE_ARCH_KGDB=y
|
||||
CONFIG_CMDLINE=""
|
||||
|
||||
#
|
||||
# Security options
|
||||
#
|
||||
# CONFIG_KEYS is not set
|
||||
# CONFIG_SECURITY is not set
|
||||
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
|
||||
CONFIG_CRYPTO=y
|
||||
|
||||
#
|
||||
# Crypto core or helper
|
||||
#
|
||||
CONFIG_CRYPTO_ALGAPI=y
|
||||
CONFIG_CRYPTO_BLKCIPHER=y
|
||||
CONFIG_CRYPTO_MANAGER=y
|
||||
# CONFIG_CRYPTO_GF128MUL is not set
|
||||
# CONFIG_CRYPTO_NULL is not set
|
||||
# CONFIG_CRYPTO_CRYPTD is not set
|
||||
# CONFIG_CRYPTO_AUTHENC is not set
|
||||
# CONFIG_CRYPTO_TEST is not set
|
||||
|
||||
#
|
||||
# Authenticated Encryption with Associated Data
|
||||
#
|
||||
# CONFIG_CRYPTO_CCM is not set
|
||||
# CONFIG_CRYPTO_GCM is not set
|
||||
# CONFIG_CRYPTO_SEQIV is not set
|
||||
|
||||
#
|
||||
# Block modes
|
||||
#
|
||||
CONFIG_CRYPTO_CBC=y
|
||||
# CONFIG_CRYPTO_CTR is not set
|
||||
# CONFIG_CRYPTO_CTS is not set
|
||||
# CONFIG_CRYPTO_ECB is not set
|
||||
# CONFIG_CRYPTO_LRW is not set
|
||||
# CONFIG_CRYPTO_PCBC is not set
|
||||
# CONFIG_CRYPTO_XTS is not set
|
||||
|
||||
#
|
||||
# Hash modes
|
||||
#
|
||||
# CONFIG_CRYPTO_HMAC is not set
|
||||
# CONFIG_CRYPTO_XCBC is not set
|
||||
|
||||
#
|
||||
# Digest
|
||||
#
|
||||
# CONFIG_CRYPTO_CRC32C is not set
|
||||
# CONFIG_CRYPTO_MD4 is not set
|
||||
CONFIG_CRYPTO_MD5=y
|
||||
# CONFIG_CRYPTO_MICHAEL_MIC is not set
|
||||
# CONFIG_CRYPTO_RMD128 is not set
|
||||
# CONFIG_CRYPTO_RMD160 is not set
|
||||
# CONFIG_CRYPTO_RMD256 is not set
|
||||
# CONFIG_CRYPTO_RMD320 is not set
|
||||
# CONFIG_CRYPTO_SHA1 is not set
|
||||
# CONFIG_CRYPTO_SHA256 is not set
|
||||
# CONFIG_CRYPTO_SHA512 is not set
|
||||
# CONFIG_CRYPTO_TGR192 is not set
|
||||
# CONFIG_CRYPTO_WP512 is not set
|
||||
|
||||
#
|
||||
# Ciphers
|
||||
#
|
||||
# CONFIG_CRYPTO_AES is not set
|
||||
# CONFIG_CRYPTO_ANUBIS is not set
|
||||
# CONFIG_CRYPTO_ARC4 is not set
|
||||
# CONFIG_CRYPTO_BLOWFISH is not set
|
||||
# CONFIG_CRYPTO_CAMELLIA is not set
|
||||
# CONFIG_CRYPTO_CAST5 is not set
|
||||
# CONFIG_CRYPTO_CAST6 is not set
|
||||
CONFIG_CRYPTO_DES=y
|
||||
# CONFIG_CRYPTO_FCRYPT is not set
|
||||
# CONFIG_CRYPTO_KHAZAD is not set
|
||||
# CONFIG_CRYPTO_SALSA20 is not set
|
||||
# CONFIG_CRYPTO_SEED is not set
|
||||
# CONFIG_CRYPTO_SERPENT is not set
|
||||
# CONFIG_CRYPTO_TEA is not set
|
||||
# CONFIG_CRYPTO_TWOFISH is not set
|
||||
|
||||
#
|
||||
# Compression
|
||||
#
|
||||
# CONFIG_CRYPTO_DEFLATE is not set
|
||||
# CONFIG_CRYPTO_LZO is not set
|
||||
CONFIG_CRYPTO_HW=y
|
||||
|
||||
#
|
||||
# Library routines
|
||||
#
|
||||
CONFIG_BITREVERSE=y
|
||||
# CONFIG_GENERIC_FIND_FIRST_BIT is not set
|
||||
# CONFIG_CRC_CCITT is not set
|
||||
# CONFIG_CRC16 is not set
|
||||
# CONFIG_CRC_T10DIF is not set
|
||||
# CONFIG_CRC_ITU_T is not set
|
||||
CONFIG_CRC32=y
|
||||
# CONFIG_CRC7 is not set
|
||||
# CONFIG_LIBCRC32C is not set
|
||||
CONFIG_PLIST=y
|
||||
CONFIG_HAS_IOMEM=y
|
||||
CONFIG_HAS_IOPORT=y
|
||||
CONFIG_HAS_DMA=y
|
||||
@@ -0,0 +1,928 @@
|
||||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.24.3
|
||||
# Fri Jul 4 19:20:22 2008
|
||||
#
|
||||
CONFIG_MIPS=y
|
||||
|
||||
#
|
||||
# Machine selection
|
||||
#
|
||||
# CONFIG_JZ4730_PMP is not set
|
||||
# CONFIG_JZ4740_PAVO is not set
|
||||
# CONFIG_JZ4740_LEO is not set
|
||||
# CONFIG_JZ4740_LYRA is not set
|
||||
# CONFIG_JZ4725_DIPPER is not set
|
||||
# CONFIG_JZ4720_VIRGO is not set
|
||||
CONFIG_JZ4750_FUWA=y
|
||||
# CONFIG_MACH_ALCHEMY is not set
|
||||
# CONFIG_BASLER_EXCITE is not set
|
||||
# CONFIG_BCM47XX is not set
|
||||
# CONFIG_MIPS_COBALT is not set
|
||||
# CONFIG_MACH_DECSTATION is not set
|
||||
# CONFIG_MACH_JAZZ is not set
|
||||
# CONFIG_LASAT is not set
|
||||
# CONFIG_LEMOTE_FULONG is not set
|
||||
# CONFIG_MIPS_ATLAS is not set
|
||||
# CONFIG_MIPS_MALTA is not set
|
||||
# CONFIG_MIPS_SEAD is not set
|
||||
# CONFIG_MIPS_SIM is not set
|
||||
# CONFIG_MARKEINS is not set
|
||||
# CONFIG_MACH_VR41XX is not set
|
||||
# CONFIG_PNX8550_JBS is not set
|
||||
# CONFIG_PNX8550_STB810 is not set
|
||||
# CONFIG_PMC_MSP is not set
|
||||
# CONFIG_PMC_YOSEMITE is not set
|
||||
# CONFIG_QEMU is not set
|
||||
# CONFIG_SGI_IP22 is not set
|
||||
# CONFIG_SGI_IP27 is not set
|
||||
# CONFIG_SGI_IP32 is not set
|
||||
# CONFIG_SIBYTE_CRHINE is not set
|
||||
# CONFIG_SIBYTE_CARMEL is not set
|
||||
# CONFIG_SIBYTE_CRHONE is not set
|
||||
# CONFIG_SIBYTE_RHONE is not set
|
||||
# CONFIG_SIBYTE_SWARM is not set
|
||||
# CONFIG_SIBYTE_LITTLESUR is not set
|
||||
# CONFIG_SIBYTE_SENTOSA is not set
|
||||
# CONFIG_SIBYTE_PTSWARM is not set
|
||||
# CONFIG_SIBYTE_BIGSUR is not set
|
||||
# CONFIG_SNI_RM is not set
|
||||
# CONFIG_TOSHIBA_JMR3927 is not set
|
||||
# CONFIG_TOSHIBA_RBTX4927 is not set
|
||||
# CONFIG_TOSHIBA_RBTX4938 is not set
|
||||
# CONFIG_WR_PPMC is not set
|
||||
CONFIG_SOC_JZ4750=y
|
||||
CONFIG_JZ_FPGA=y
|
||||
CONFIG_JZSOC=y
|
||||
CONFIG_JZRISC=y
|
||||
CONFIG_RWSEM_GENERIC_SPINLOCK=y
|
||||
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
|
||||
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
|
||||
CONFIG_ARCH_SUPPORTS_OPROFILE=y
|
||||
CONFIG_GENERIC_FIND_NEXT_BIT=y
|
||||
CONFIG_GENERIC_HWEIGHT=y
|
||||
CONFIG_GENERIC_CALIBRATE_DELAY=y
|
||||
CONFIG_GENERIC_CLOCKEVENTS=y
|
||||
CONFIG_GENERIC_TIME=y
|
||||
CONFIG_GENERIC_CMOS_UPDATE=y
|
||||
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
|
||||
# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
|
||||
CONFIG_DMA_NONCOHERENT=y
|
||||
CONFIG_DMA_NEED_PCI_MAP_STATE=y
|
||||
# CONFIG_HOTPLUG_CPU is not set
|
||||
# CONFIG_NO_IOPORT is not set
|
||||
# CONFIG_CPU_BIG_ENDIAN is not set
|
||||
CONFIG_CPU_LITTLE_ENDIAN=y
|
||||
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
|
||||
CONFIG_MIPS_L1_CACHE_SHIFT=5
|
||||
|
||||
#
|
||||
# CPU selection
|
||||
#
|
||||
# CONFIG_CPU_LOONGSON2 is not set
|
||||
CONFIG_CPU_MIPS32_R1=y
|
||||
# CONFIG_CPU_MIPS32_R2 is not set
|
||||
# CONFIG_CPU_MIPS64_R1 is not set
|
||||
# CONFIG_CPU_MIPS64_R2 is not set
|
||||
# CONFIG_CPU_R3000 is not set
|
||||
# CONFIG_CPU_TX39XX is not set
|
||||
# CONFIG_CPU_VR41XX is not set
|
||||
# CONFIG_CPU_R4300 is not set
|
||||
# CONFIG_CPU_R4X00 is not set
|
||||
# CONFIG_CPU_TX49XX is not set
|
||||
# CONFIG_CPU_R5000 is not set
|
||||
# CONFIG_CPU_R5432 is not set
|
||||
# CONFIG_CPU_R6000 is not set
|
||||
# CONFIG_CPU_NEVADA is not set
|
||||
# CONFIG_CPU_R8000 is not set
|
||||
# CONFIG_CPU_R10000 is not set
|
||||
# CONFIG_CPU_RM7000 is not set
|
||||
# CONFIG_CPU_RM9000 is not set
|
||||
# CONFIG_CPU_SB1 is not set
|
||||
CONFIG_SYS_HAS_CPU_MIPS32_R1=y
|
||||
CONFIG_CPU_MIPS32=y
|
||||
CONFIG_CPU_MIPSR1=y
|
||||
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
|
||||
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
|
||||
|
||||
#
|
||||
# Kernel type
|
||||
#
|
||||
CONFIG_32BIT=y
|
||||
# CONFIG_64BIT is not set
|
||||
CONFIG_PAGE_SIZE_4KB=y
|
||||
# CONFIG_PAGE_SIZE_8KB is not set
|
||||
# CONFIG_PAGE_SIZE_16KB is not set
|
||||
# CONFIG_PAGE_SIZE_64KB is not set
|
||||
CONFIG_CPU_HAS_PREFETCH=y
|
||||
CONFIG_MIPS_MT_DISABLED=y
|
||||
# CONFIG_MIPS_MT_SMP is not set
|
||||
# CONFIG_MIPS_MT_SMTC is not set
|
||||
CONFIG_CPU_HAS_LLSC=y
|
||||
CONFIG_CPU_HAS_SYNC=y
|
||||
CONFIG_GENERIC_HARDIRQS=y
|
||||
CONFIG_GENERIC_IRQ_PROBE=y
|
||||
CONFIG_CPU_SUPPORTS_HIGHMEM=y
|
||||
CONFIG_ARCH_FLATMEM_ENABLE=y
|
||||
CONFIG_ARCH_POPULATES_NODE_MAP=y
|
||||
CONFIG_SELECT_MEMORY_MODEL=y
|
||||
CONFIG_FLATMEM_MANUAL=y
|
||||
# CONFIG_DISCONTIGMEM_MANUAL is not set
|
||||
# CONFIG_SPARSEMEM_MANUAL is not set
|
||||
CONFIG_FLATMEM=y
|
||||
CONFIG_FLAT_NODE_MEM_MAP=y
|
||||
# CONFIG_SPARSEMEM_STATIC is not set
|
||||
# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
|
||||
CONFIG_SPLIT_PTLOCK_CPUS=4
|
||||
# CONFIG_RESOURCES_64BIT is not set
|
||||
CONFIG_ZONE_DMA_FLAG=0
|
||||
CONFIG_VIRT_TO_BUS=y
|
||||
# CONFIG_TICK_ONESHOT is not set
|
||||
# CONFIG_NO_HZ is not set
|
||||
# CONFIG_HIGH_RES_TIMERS is not set
|
||||
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
|
||||
# CONFIG_HZ_48 is not set
|
||||
CONFIG_HZ_100=y
|
||||
# CONFIG_HZ_128 is not set
|
||||
# CONFIG_HZ_250 is not set
|
||||
# CONFIG_HZ_256 is not set
|
||||
# CONFIG_HZ_1000 is not set
|
||||
# CONFIG_HZ_1024 is not set
|
||||
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
|
||||
CONFIG_HZ=100
|
||||
# CONFIG_PREEMPT_NONE is not set
|
||||
# CONFIG_PREEMPT_VOLUNTARY is not set
|
||||
CONFIG_PREEMPT=y
|
||||
CONFIG_PREEMPT_BKL=y
|
||||
# CONFIG_KEXEC is not set
|
||||
CONFIG_SECCOMP=y
|
||||
CONFIG_LOCKDEP_SUPPORT=y
|
||||
CONFIG_STACKTRACE_SUPPORT=y
|
||||
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
|
||||
|
||||
#
|
||||
# General setup
|
||||
#
|
||||
CONFIG_EXPERIMENTAL=y
|
||||
CONFIG_BROKEN_ON_SMP=y
|
||||
CONFIG_LOCK_KERNEL=y
|
||||
CONFIG_INIT_ENV_ARG_LIMIT=32
|
||||
CONFIG_LOCALVERSION=""
|
||||
CONFIG_LOCALVERSION_AUTO=y
|
||||
CONFIG_SWAP=y
|
||||
CONFIG_SYSVIPC=y
|
||||
CONFIG_SYSVIPC_SYSCTL=y
|
||||
# CONFIG_POSIX_MQUEUE is not set
|
||||
# CONFIG_BSD_PROCESS_ACCT is not set
|
||||
# CONFIG_TASKSTATS is not set
|
||||
# CONFIG_USER_NS is not set
|
||||
# CONFIG_PID_NS is not set
|
||||
# CONFIG_AUDIT is not set
|
||||
# CONFIG_IKCONFIG is not set
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
# CONFIG_CGROUPS is not set
|
||||
CONFIG_FAIR_GROUP_SCHED=y
|
||||
CONFIG_FAIR_USER_SCHED=y
|
||||
# CONFIG_FAIR_CGROUP_SCHED is not set
|
||||
CONFIG_SYSFS_DEPRECATED=y
|
||||
CONFIG_RELAY=y
|
||||
# CONFIG_BLK_DEV_INITRD is not set
|
||||
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
||||
CONFIG_SYSCTL=y
|
||||
CONFIG_EMBEDDED=y
|
||||
CONFIG_SYSCTL_SYSCALL=y
|
||||
CONFIG_KALLSYMS=y
|
||||
# CONFIG_KALLSYMS_EXTRA_PASS is not set
|
||||
CONFIG_HOTPLUG=y
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_BUG=y
|
||||
CONFIG_ELF_CORE=y
|
||||
CONFIG_BASE_FULL=y
|
||||
CONFIG_FUTEX=y
|
||||
CONFIG_ANON_INODES=y
|
||||
CONFIG_EPOLL=y
|
||||
CONFIG_SIGNALFD=y
|
||||
CONFIG_EVENTFD=y
|
||||
CONFIG_SHMEM=y
|
||||
CONFIG_VM_EVENT_COUNTERS=y
|
||||
CONFIG_SLAB=y
|
||||
# CONFIG_SLUB is not set
|
||||
# CONFIG_SLOB is not set
|
||||
CONFIG_SLABINFO=y
|
||||
CONFIG_RT_MUTEXES=y
|
||||
# CONFIG_TINY_SHMEM is not set
|
||||
CONFIG_BASE_SMALL=0
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
# CONFIG_MODULE_FORCE_UNLOAD is not set
|
||||
CONFIG_MODVERSIONS=y
|
||||
CONFIG_MODULE_SRCVERSION_ALL=y
|
||||
CONFIG_KMOD=y
|
||||
CONFIG_BLOCK=y
|
||||
# CONFIG_LBD is not set
|
||||
# CONFIG_BLK_DEV_IO_TRACE is not set
|
||||
# CONFIG_LSF is not set
|
||||
# CONFIG_BLK_DEV_BSG is not set
|
||||
|
||||
#
|
||||
# IO Schedulers
|
||||
#
|
||||
CONFIG_IOSCHED_NOOP=y
|
||||
CONFIG_IOSCHED_AS=y
|
||||
CONFIG_IOSCHED_DEADLINE=y
|
||||
CONFIG_IOSCHED_CFQ=y
|
||||
CONFIG_DEFAULT_AS=y
|
||||
# CONFIG_DEFAULT_DEADLINE is not set
|
||||
# CONFIG_DEFAULT_CFQ is not set
|
||||
# CONFIG_DEFAULT_NOOP is not set
|
||||
CONFIG_DEFAULT_IOSCHED="anticipatory"
|
||||
|
||||
#
|
||||
# Bus options (PCI, PCMCIA, EISA, ISA, TC)
|
||||
#
|
||||
# CONFIG_ARCH_SUPPORTS_MSI is not set
|
||||
CONFIG_MMU=y
|
||||
# CONFIG_PCCARD is not set
|
||||
|
||||
#
|
||||
# Executable file formats
|
||||
#
|
||||
CONFIG_BINFMT_ELF=y
|
||||
# CONFIG_BINFMT_MISC is not set
|
||||
CONFIG_TRAD_SIGNALS=y
|
||||
|
||||
#
|
||||
# CPU Frequency scaling
|
||||
#
|
||||
# CONFIG_CPU_FREQ_JZ is not set
|
||||
|
||||
#
|
||||
# Power management options
|
||||
#
|
||||
# CONFIG_PM is not set
|
||||
CONFIG_SUSPEND_UP_POSSIBLE=y
|
||||
|
||||
#
|
||||
# Networking
|
||||
#
|
||||
CONFIG_NET=y
|
||||
|
||||
#
|
||||
# Networking options
|
||||
#
|
||||
CONFIG_PACKET=y
|
||||
# CONFIG_PACKET_MMAP is not set
|
||||
CONFIG_UNIX=y
|
||||
# CONFIG_NET_KEY is not set
|
||||
CONFIG_INET=y
|
||||
# CONFIG_IP_MULTICAST is not set
|
||||
# CONFIG_IP_ADVANCED_ROUTER is not set
|
||||
CONFIG_IP_FIB_HASH=y
|
||||
CONFIG_IP_PNP=y
|
||||
CONFIG_IP_PNP_DHCP=y
|
||||
CONFIG_IP_PNP_BOOTP=y
|
||||
# CONFIG_IP_PNP_RARP is not set
|
||||
# CONFIG_NET_IPIP is not set
|
||||
# CONFIG_NET_IPGRE is not set
|
||||
# CONFIG_ARPD is not set
|
||||
# CONFIG_SYN_COOKIES is not set
|
||||
# CONFIG_INET_AH is not set
|
||||
# CONFIG_INET_ESP is not set
|
||||
# CONFIG_INET_IPCOMP is not set
|
||||
# CONFIG_INET_XFRM_TUNNEL is not set
|
||||
# CONFIG_INET_TUNNEL is not set
|
||||
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
|
||||
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
|
||||
# CONFIG_INET_XFRM_MODE_BEET is not set
|
||||
# CONFIG_INET_LRO is not set
|
||||
CONFIG_INET_DIAG=m
|
||||
CONFIG_INET_TCP_DIAG=m
|
||||
# CONFIG_TCP_CONG_ADVANCED is not set
|
||||
CONFIG_TCP_CONG_CUBIC=y
|
||||
CONFIG_DEFAULT_TCP_CONG="cubic"
|
||||
# CONFIG_TCP_MD5SIG is not set
|
||||
# CONFIG_IPV6 is not set
|
||||
# CONFIG_INET6_XFRM_TUNNEL is not set
|
||||
# CONFIG_INET6_TUNNEL is not set
|
||||
# CONFIG_NETWORK_SECMARK is not set
|
||||
# CONFIG_NETFILTER is not set
|
||||
# CONFIG_IP_DCCP is not set
|
||||
# CONFIG_IP_SCTP is not set
|
||||
# CONFIG_TIPC is not set
|
||||
# CONFIG_ATM is not set
|
||||
# CONFIG_BRIDGE is not set
|
||||
# CONFIG_VLAN_8021Q is not set
|
||||
# CONFIG_DECNET is not set
|
||||
# CONFIG_LLC2 is not set
|
||||
# CONFIG_IPX is not set
|
||||
# CONFIG_ATALK is not set
|
||||
# CONFIG_X25 is not set
|
||||
# CONFIG_LAPB is not set
|
||||
# CONFIG_ECONET is not set
|
||||
# CONFIG_WAN_ROUTER is not set
|
||||
# CONFIG_NET_SCHED is not set
|
||||
|
||||
#
|
||||
# Network testing
|
||||
#
|
||||
# CONFIG_NET_PKTGEN is not set
|
||||
# CONFIG_HAMRADIO is not set
|
||||
# CONFIG_IRDA is not set
|
||||
# CONFIG_BT is not set
|
||||
# CONFIG_AF_RXRPC is not set
|
||||
|
||||
#
|
||||
# Wireless
|
||||
#
|
||||
# CONFIG_CFG80211 is not set
|
||||
# CONFIG_WIRELESS_EXT is not set
|
||||
# CONFIG_MAC80211 is not set
|
||||
# CONFIG_IEEE80211 is not set
|
||||
# CONFIG_RFKILL is not set
|
||||
# CONFIG_NET_9P is not set
|
||||
|
||||
#
|
||||
# Device Drivers
|
||||
#
|
||||
|
||||
#
|
||||
# Generic Driver Options
|
||||
#
|
||||
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
|
||||
CONFIG_STANDALONE=y
|
||||
CONFIG_PREVENT_FIRMWARE_BUILD=y
|
||||
# CONFIG_FW_LOADER is not set
|
||||
# CONFIG_SYS_HYPERVISOR is not set
|
||||
# CONFIG_CONNECTOR is not set
|
||||
CONFIG_MTD=y
|
||||
# CONFIG_MTD_DEBUG is not set
|
||||
# CONFIG_MTD_CONCAT is not set
|
||||
CONFIG_MTD_PARTITIONS=y
|
||||
# CONFIG_MTD_REDBOOT_PARTS is not set
|
||||
# CONFIG_MTD_CMDLINE_PARTS is not set
|
||||
|
||||
#
|
||||
# User Modules And Translation Layers
|
||||
#
|
||||
CONFIG_MTD_CHAR=y
|
||||
CONFIG_MTD_BLKDEVS=y
|
||||
CONFIG_MTD_BLOCK=y
|
||||
# CONFIG_FTL is not set
|
||||
# CONFIG_NFTL is not set
|
||||
# CONFIG_INFTL is not set
|
||||
# CONFIG_RFD_FTL is not set
|
||||
# CONFIG_SSFDC is not set
|
||||
# CONFIG_MTD_OOPS is not set
|
||||
|
||||
#
|
||||
# RAM/ROM/Flash chip drivers
|
||||
#
|
||||
# CONFIG_MTD_CFI is not set
|
||||
# CONFIG_MTD_JEDECPROBE is not set
|
||||
CONFIG_MTD_MAP_BANK_WIDTH_1=y
|
||||
CONFIG_MTD_MAP_BANK_WIDTH_2=y
|
||||
CONFIG_MTD_MAP_BANK_WIDTH_4=y
|
||||
# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
|
||||
# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
|
||||
# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
|
||||
CONFIG_MTD_CFI_I1=y
|
||||
CONFIG_MTD_CFI_I2=y
|
||||
# CONFIG_MTD_CFI_I4 is not set
|
||||
# CONFIG_MTD_CFI_I8 is not set
|
||||
# CONFIG_MTD_RAM is not set
|
||||
# CONFIG_MTD_ROM is not set
|
||||
# CONFIG_MTD_ABSENT is not set
|
||||
|
||||
#
|
||||
# Mapping drivers for chip access
|
||||
#
|
||||
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
|
||||
# CONFIG_MTD_PLATRAM is not set
|
||||
|
||||
#
|
||||
# Self-contained MTD device drivers
|
||||
#
|
||||
# CONFIG_MTD_SLRAM is not set
|
||||
# CONFIG_MTD_PHRAM is not set
|
||||
# CONFIG_MTD_MTDRAM is not set
|
||||
# CONFIG_MTD_BLOCK2MTD is not set
|
||||
|
||||
#
|
||||
# Disk-On-Chip Device Drivers
|
||||
#
|
||||
# CONFIG_MTD_DOC2000 is not set
|
||||
# CONFIG_MTD_DOC2001 is not set
|
||||
# CONFIG_MTD_DOC2001PLUS is not set
|
||||
CONFIG_MTD_NAND=y
|
||||
# CONFIG_MTD_NAND_VERIFY_WRITE is not set
|
||||
# CONFIG_MTD_NAND_ECC_SMC is not set
|
||||
# CONFIG_MTD_NAND_MUSEUM_IDS is not set
|
||||
CONFIG_MTD_NAND_IDS=y
|
||||
# CONFIG_MTD_NAND_DISKONCHIP is not set
|
||||
# CONFIG_MTD_NAND_NANDSIM is not set
|
||||
# CONFIG_MTD_NAND_PLATFORM is not set
|
||||
CONFIG_MTD_NAND_JZ4750=y
|
||||
# CONFIG_MTD_HW_HM_ECC is not set
|
||||
# CONFIG_MTD_SW_HM_ECC is not set
|
||||
# CONFIG_MTD_HW_RS_ECC is not set
|
||||
CONFIG_MTD_HW_BCH_ECC=y
|
||||
CONFIG_MTD_NAND_DMA=y
|
||||
# CONFIG_MTD_NAND_NO_DMA is not set
|
||||
CONFIG_MTD_HW_BCH_4BIT=y
|
||||
# CONFIG_MTD_HW_BCH_8BIT is not set
|
||||
# CONFIG_MTD_MTDBLOCK_WRITE_VERIFY_ENABLE is not set
|
||||
CONFIG_MTD_OOB_COPIES=0
|
||||
CONFIG_MTD_BADBLOCK_FLAG_PAGE=127
|
||||
# CONFIG_MTD_ONENAND is not set
|
||||
|
||||
#
|
||||
# UBI - Unsorted block images
|
||||
#
|
||||
# CONFIG_MTD_UBI is not set
|
||||
# CONFIG_MTD_UBI_BLKDEVS is not set
|
||||
# CONFIG_PARPORT is not set
|
||||
# CONFIG_PNP is not set
|
||||
CONFIG_BLK_DEV=y
|
||||
# CONFIG_BLK_DEV_COW_COMMON is not set
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
|
||||
# CONFIG_BLK_DEV_NBD is not set
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_COUNT=16
|
||||
CONFIG_BLK_DEV_RAM_SIZE=4096
|
||||
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
|
||||
# CONFIG_CDROM_PKTCDVD is not set
|
||||
# CONFIG_ATA_OVER_ETH is not set
|
||||
CONFIG_MISC_DEVICES=y
|
||||
# CONFIG_EEPROM_93CX6 is not set
|
||||
# CONFIG_IDE is not set
|
||||
|
||||
#
|
||||
# SCSI device support
|
||||
#
|
||||
# CONFIG_RAID_ATTRS is not set
|
||||
# CONFIG_SCSI is not set
|
||||
# CONFIG_SCSI_DMA is not set
|
||||
# CONFIG_SCSI_NETLINK is not set
|
||||
# CONFIG_ATA is not set
|
||||
# CONFIG_MD is not set
|
||||
CONFIG_NETDEVICES=y
|
||||
# CONFIG_NETDEVICES_MULTIQUEUE is not set
|
||||
# CONFIG_DUMMY is not set
|
||||
# CONFIG_BONDING is not set
|
||||
# CONFIG_MACVLAN is not set
|
||||
# CONFIG_EQUALIZER is not set
|
||||
# CONFIG_TUN is not set
|
||||
# CONFIG_VETH is not set
|
||||
CONFIG_PHYLIB=y
|
||||
|
||||
#
|
||||
# MII PHY device drivers
|
||||
#
|
||||
# CONFIG_MARVELL_PHY is not set
|
||||
# CONFIG_DAVICOM_PHY is not set
|
||||
# CONFIG_QSEMI_PHY is not set
|
||||
# CONFIG_LXT_PHY is not set
|
||||
# CONFIG_CICADA_PHY is not set
|
||||
# CONFIG_VITESSE_PHY is not set
|
||||
# CONFIG_SMSC_PHY is not set
|
||||
# CONFIG_BROADCOM_PHY is not set
|
||||
# CONFIG_ICPLUS_PHY is not set
|
||||
# CONFIG_FIXED_PHY is not set
|
||||
# CONFIG_MDIO_BITBANG is not set
|
||||
CONFIG_NET_ETHERNET=y
|
||||
CONFIG_MII=y
|
||||
CONFIG_JZ_ETH=y
|
||||
# CONFIG_AX88796 is not set
|
||||
# CONFIG_DM9000 is not set
|
||||
# CONFIG_IBM_NEW_EMAC_ZMII is not set
|
||||
# CONFIG_IBM_NEW_EMAC_RGMII is not set
|
||||
# CONFIG_IBM_NEW_EMAC_TAH is not set
|
||||
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
|
||||
# CONFIG_B44 is not set
|
||||
CONFIG_NETDEV_1000=y
|
||||
CONFIG_NETDEV_10000=y
|
||||
|
||||
#
|
||||
# Wireless LAN
|
||||
#
|
||||
# CONFIG_WLAN_PRE80211 is not set
|
||||
# CONFIG_WLAN_80211 is not set
|
||||
# CONFIG_WAN is not set
|
||||
# CONFIG_PPP is not set
|
||||
# CONFIG_SLIP is not set
|
||||
# CONFIG_SHAPER is not set
|
||||
# CONFIG_NETCONSOLE is not set
|
||||
# CONFIG_NETPOLL is not set
|
||||
# CONFIG_NET_POLL_CONTROLLER is not set
|
||||
# CONFIG_ISDN is not set
|
||||
# CONFIG_PHONE is not set
|
||||
|
||||
#
|
||||
# Input device support
|
||||
#
|
||||
CONFIG_INPUT=y
|
||||
# CONFIG_INPUT_FF_MEMLESS is not set
|
||||
# CONFIG_INPUT_POLLDEV is not set
|
||||
|
||||
#
|
||||
# Userland interfaces
|
||||
#
|
||||
# CONFIG_INPUT_MOUSEDEV is not set
|
||||
# CONFIG_INPUT_JOYDEV is not set
|
||||
# CONFIG_INPUT_EVDEV is not set
|
||||
# CONFIG_INPUT_EVBUG is not set
|
||||
|
||||
#
|
||||
# Input Device Drivers
|
||||
#
|
||||
# CONFIG_INPUT_KEYBOARD is not set
|
||||
# CONFIG_INPUT_MOUSE is not set
|
||||
# CONFIG_INPUT_JOYSTICK is not set
|
||||
# CONFIG_INPUT_TABLET is not set
|
||||
# CONFIG_INPUT_TOUCHSCREEN is not set
|
||||
# CONFIG_INPUT_MISC is not set
|
||||
|
||||
#
|
||||
# Hardware I/O ports
|
||||
#
|
||||
CONFIG_SERIO=y
|
||||
# CONFIG_SERIO_I8042 is not set
|
||||
CONFIG_SERIO_SERPORT=y
|
||||
# CONFIG_SERIO_LIBPS2 is not set
|
||||
# CONFIG_SERIO_RAW is not set
|
||||
# CONFIG_GAMEPORT is not set
|
||||
|
||||
#
|
||||
# Character devices
|
||||
#
|
||||
CONFIG_VT=y
|
||||
CONFIG_VT_CONSOLE=y
|
||||
CONFIG_HW_CONSOLE=y
|
||||
CONFIG_VT_HW_CONSOLE_BINDING=y
|
||||
# CONFIG_SERIAL_NONSTANDARD is not set
|
||||
|
||||
#
|
||||
# Serial drivers
|
||||
#
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_NR_UARTS=4
|
||||
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
|
||||
# CONFIG_SERIAL_8250_EXTENDED is not set
|
||||
|
||||
#
|
||||
# Non-8250 serial port support
|
||||
#
|
||||
CONFIG_SERIAL_CORE=y
|
||||
CONFIG_SERIAL_CORE_CONSOLE=y
|
||||
CONFIG_UNIX98_PTYS=y
|
||||
CONFIG_LEGACY_PTYS=y
|
||||
CONFIG_LEGACY_PTY_COUNT=2
|
||||
# CONFIG_IPMI_HANDLER is not set
|
||||
# CONFIG_HW_RANDOM is not set
|
||||
# CONFIG_RTC is not set
|
||||
# CONFIG_RTC_PCF8563 is not set
|
||||
# CONFIG_RTC_JZ is not set
|
||||
# CONFIG_R3964 is not set
|
||||
# CONFIG_RAW_DRIVER is not set
|
||||
# CONFIG_TCG_TPM is not set
|
||||
|
||||
#
|
||||
# JZSOC char device support
|
||||
#
|
||||
# CONFIG_JZCHAR is not set
|
||||
# CONFIG_I2C is not set
|
||||
|
||||
#
|
||||
# SPI support
|
||||
#
|
||||
# CONFIG_SPI is not set
|
||||
# CONFIG_SPI_MASTER is not set
|
||||
# CONFIG_W1 is not set
|
||||
# CONFIG_POWER_SUPPLY is not set
|
||||
# CONFIG_HWMON is not set
|
||||
# CONFIG_WATCHDOG is not set
|
||||
|
||||
#
|
||||
# Sonics Silicon Backplane
|
||||
#
|
||||
CONFIG_SSB_POSSIBLE=y
|
||||
# CONFIG_SSB is not set
|
||||
|
||||
#
|
||||
# Multifunction device drivers
|
||||
#
|
||||
# CONFIG_MFD_SM501 is not set
|
||||
|
||||
#
|
||||
# Multimedia devices
|
||||
#
|
||||
# CONFIG_VIDEO_DEV is not set
|
||||
# CONFIG_DVB_CORE is not set
|
||||
# CONFIG_DAB is not set
|
||||
|
||||
#
|
||||
# Graphics support
|
||||
#
|
||||
# CONFIG_VGASTATE is not set
|
||||
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
|
||||
# CONFIG_FB is not set
|
||||
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
|
||||
|
||||
#
|
||||
# Display device support
|
||||
#
|
||||
# CONFIG_DISPLAY_SUPPORT is not set
|
||||
|
||||
#
|
||||
# Console display driver support
|
||||
#
|
||||
# CONFIG_VGA_CONSOLE is not set
|
||||
CONFIG_DUMMY_CONSOLE=y
|
||||
|
||||
#
|
||||
# Sound
|
||||
#
|
||||
# CONFIG_SOUND is not set
|
||||
CONFIG_HID_SUPPORT=y
|
||||
CONFIG_HID=y
|
||||
# CONFIG_HID_DEBUG is not set
|
||||
# CONFIG_HIDRAW is not set
|
||||
CONFIG_USB_SUPPORT=y
|
||||
CONFIG_USB_ARCH_HAS_HCD=y
|
||||
CONFIG_USB_ARCH_HAS_OHCI=y
|
||||
# CONFIG_USB_ARCH_HAS_EHCI is not set
|
||||
# CONFIG_USB is not set
|
||||
|
||||
#
|
||||
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
|
||||
#
|
||||
|
||||
#
|
||||
# USB Gadget Support
|
||||
#
|
||||
# CONFIG_USB_GADGET is not set
|
||||
# CONFIG_MMC is not set
|
||||
# CONFIG_NEW_LEDS is not set
|
||||
CONFIG_RTC_LIB=y
|
||||
# CONFIG_RTC_CLASS is not set
|
||||
|
||||
#
|
||||
# Userspace I/O
|
||||
#
|
||||
# CONFIG_UIO is not set
|
||||
|
||||
#
|
||||
# File systems
|
||||
#
|
||||
CONFIG_EXT2_FS=y
|
||||
CONFIG_EXT2_FS_XATTR=y
|
||||
# CONFIG_EXT2_FS_POSIX_ACL is not set
|
||||
# CONFIG_EXT2_FS_SECURITY is not set
|
||||
# CONFIG_EXT2_FS_XIP is not set
|
||||
# CONFIG_EXT3_FS is not set
|
||||
# CONFIG_EXT4DEV_FS is not set
|
||||
CONFIG_FS_MBCACHE=y
|
||||
# CONFIG_REISERFS_FS is not set
|
||||
# CONFIG_JFS_FS is not set
|
||||
CONFIG_FS_POSIX_ACL=y
|
||||
# CONFIG_XFS_FS is not set
|
||||
# CONFIG_GFS2_FS is not set
|
||||
# CONFIG_OCFS2_FS is not set
|
||||
CONFIG_MINIX_FS=y
|
||||
# CONFIG_ROMFS_FS is not set
|
||||
CONFIG_INOTIFY=y
|
||||
CONFIG_INOTIFY_USER=y
|
||||
# CONFIG_QUOTA is not set
|
||||
CONFIG_DNOTIFY=y
|
||||
# CONFIG_AUTOFS_FS is not set
|
||||
# CONFIG_AUTOFS4_FS is not set
|
||||
# CONFIG_FUSE_FS is not set
|
||||
|
||||
#
|
||||
# CD-ROM/DVD Filesystems
|
||||
#
|
||||
# CONFIG_ISO9660_FS is not set
|
||||
# CONFIG_UDF_FS is not set
|
||||
|
||||
#
|
||||
# DOS/FAT/NT Filesystems
|
||||
#
|
||||
CONFIG_FAT_FS=y
|
||||
CONFIG_MSDOS_FS=y
|
||||
CONFIG_VFAT_FS=y
|
||||
CONFIG_FAT_DEFAULT_CODEPAGE=437
|
||||
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
|
||||
# CONFIG_NTFS_FS is not set
|
||||
|
||||
#
|
||||
# Pseudo filesystems
|
||||
#
|
||||
CONFIG_PROC_FS=y
|
||||
CONFIG_PROC_KCORE=y
|
||||
CONFIG_PROC_SYSCTL=y
|
||||
CONFIG_SYSFS=y
|
||||
CONFIG_TMPFS=y
|
||||
# CONFIG_TMPFS_POSIX_ACL is not set
|
||||
# CONFIG_HUGETLB_PAGE is not set
|
||||
# CONFIG_CONFIGFS_FS is not set
|
||||
|
||||
#
|
||||
# Miscellaneous filesystems
|
||||
#
|
||||
# CONFIG_ADFS_FS is not set
|
||||
# CONFIG_AFFS_FS is not set
|
||||
# CONFIG_HFS_FS is not set
|
||||
# CONFIG_HFSPLUS_FS is not set
|
||||
# CONFIG_BEFS_FS is not set
|
||||
# CONFIG_BFS_FS is not set
|
||||
# CONFIG_EFS_FS is not set
|
||||
# CONFIG_JFFS2_FS is not set
|
||||
# CONFIG_CRAMFS is not set
|
||||
# CONFIG_VXFS_FS is not set
|
||||
# CONFIG_HPFS_FS is not set
|
||||
# CONFIG_QNX4FS_FS is not set
|
||||
# CONFIG_SYSV_FS is not set
|
||||
# CONFIG_UFS_FS is not set
|
||||
CONFIG_NETWORK_FILESYSTEMS=y
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3=y
|
||||
CONFIG_NFS_V3_ACL=y
|
||||
CONFIG_NFS_V4=y
|
||||
CONFIG_NFS_DIRECTIO=y
|
||||
# CONFIG_NFSD is not set
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_LOCKD=y
|
||||
CONFIG_LOCKD_V4=y
|
||||
CONFIG_NFS_ACL_SUPPORT=y
|
||||
CONFIG_NFS_COMMON=y
|
||||
CONFIG_SUNRPC=y
|
||||
CONFIG_SUNRPC_GSS=y
|
||||
# CONFIG_SUNRPC_BIND34 is not set
|
||||
CONFIG_RPCSEC_GSS_KRB5=y
|
||||
# CONFIG_RPCSEC_GSS_SPKM3 is not set
|
||||
# CONFIG_SMB_FS is not set
|
||||
# CONFIG_CIFS is not set
|
||||
# CONFIG_NCP_FS is not set
|
||||
# CONFIG_CODA_FS is not set
|
||||
# CONFIG_AFS_FS is not set
|
||||
|
||||
#
|
||||
# Partition Types
|
||||
#
|
||||
CONFIG_PARTITION_ADVANCED=y
|
||||
# CONFIG_ACORN_PARTITION is not set
|
||||
# CONFIG_OSF_PARTITION is not set
|
||||
# CONFIG_AMIGA_PARTITION is not set
|
||||
# CONFIG_ATARI_PARTITION is not set
|
||||
# CONFIG_MAC_PARTITION is not set
|
||||
CONFIG_MSDOS_PARTITION=y
|
||||
# CONFIG_BSD_DISKLABEL is not set
|
||||
# CONFIG_MINIX_SUBPARTITION is not set
|
||||
# CONFIG_SOLARIS_X86_PARTITION is not set
|
||||
# CONFIG_UNIXWARE_DISKLABEL is not set
|
||||
# CONFIG_LDM_PARTITION is not set
|
||||
# CONFIG_SGI_PARTITION is not set
|
||||
# CONFIG_ULTRIX_PARTITION is not set
|
||||
# CONFIG_SUN_PARTITION is not set
|
||||
# CONFIG_KARMA_PARTITION is not set
|
||||
# CONFIG_EFI_PARTITION is not set
|
||||
# CONFIG_SYSV68_PARTITION is not set
|
||||
CONFIG_NLS=y
|
||||
CONFIG_NLS_DEFAULT="iso8859-1"
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
# CONFIG_NLS_CODEPAGE_737 is not set
|
||||
# CONFIG_NLS_CODEPAGE_775 is not set
|
||||
# CONFIG_NLS_CODEPAGE_850 is not set
|
||||
# CONFIG_NLS_CODEPAGE_852 is not set
|
||||
# CONFIG_NLS_CODEPAGE_855 is not set
|
||||
# CONFIG_NLS_CODEPAGE_857 is not set
|
||||
# CONFIG_NLS_CODEPAGE_860 is not set
|
||||
# CONFIG_NLS_CODEPAGE_861 is not set
|
||||
# CONFIG_NLS_CODEPAGE_862 is not set
|
||||
# CONFIG_NLS_CODEPAGE_863 is not set
|
||||
# CONFIG_NLS_CODEPAGE_864 is not set
|
||||
# CONFIG_NLS_CODEPAGE_865 is not set
|
||||
# CONFIG_NLS_CODEPAGE_866 is not set
|
||||
# CONFIG_NLS_CODEPAGE_869 is not set
|
||||
CONFIG_NLS_CODEPAGE_936=y
|
||||
# CONFIG_NLS_CODEPAGE_950 is not set
|
||||
# CONFIG_NLS_CODEPAGE_932 is not set
|
||||
# CONFIG_NLS_CODEPAGE_949 is not set
|
||||
# CONFIG_NLS_CODEPAGE_874 is not set
|
||||
# CONFIG_NLS_ISO8859_8 is not set
|
||||
# CONFIG_NLS_CODEPAGE_1250 is not set
|
||||
# CONFIG_NLS_CODEPAGE_1251 is not set
|
||||
CONFIG_NLS_ASCII=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
# CONFIG_NLS_ISO8859_2 is not set
|
||||
# CONFIG_NLS_ISO8859_3 is not set
|
||||
# CONFIG_NLS_ISO8859_4 is not set
|
||||
# CONFIG_NLS_ISO8859_5 is not set
|
||||
# CONFIG_NLS_ISO8859_6 is not set
|
||||
# CONFIG_NLS_ISO8859_7 is not set
|
||||
# CONFIG_NLS_ISO8859_9 is not set
|
||||
# CONFIG_NLS_ISO8859_13 is not set
|
||||
# CONFIG_NLS_ISO8859_14 is not set
|
||||
# CONFIG_NLS_ISO8859_15 is not set
|
||||
# CONFIG_NLS_KOI8_R is not set
|
||||
# CONFIG_NLS_KOI8_U is not set
|
||||
# CONFIG_NLS_UTF8 is not set
|
||||
# CONFIG_DLM is not set
|
||||
|
||||
#
|
||||
# Yaffs2 Filesystems
|
||||
#
|
||||
CONFIG_YAFFS_FS=y
|
||||
CONFIG_YAFFS_YAFFS1=y
|
||||
# CONFIG_YAFFS_DOES_ECC is not set
|
||||
CONFIG_YAFFS_YAFFS2=y
|
||||
CONFIG_YAFFS_AUTO_YAFFS2=y
|
||||
# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
|
||||
# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
|
||||
CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK=y
|
||||
CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
|
||||
CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
|
||||
CONFIG_INSTRUMENTATION=y
|
||||
# CONFIG_PROFILING is not set
|
||||
# CONFIG_MARKERS is not set
|
||||
|
||||
#
|
||||
# Kernel hacking
|
||||
#
|
||||
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
|
||||
# CONFIG_PRINTK_TIME is not set
|
||||
CONFIG_ENABLE_WARN_DEPRECATED=y
|
||||
CONFIG_ENABLE_MUST_CHECK=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
# CONFIG_UNUSED_SYMBOLS is not set
|
||||
# CONFIG_DEBUG_FS is not set
|
||||
# CONFIG_HEADERS_CHECK is not set
|
||||
# CONFIG_DEBUG_KERNEL is not set
|
||||
# CONFIG_SAMPLES is not set
|
||||
CONFIG_CMDLINE=""
|
||||
|
||||
#
|
||||
# Security options
|
||||
#
|
||||
# CONFIG_KEYS is not set
|
||||
# CONFIG_SECURITY is not set
|
||||
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
|
||||
CONFIG_CRYPTO=y
|
||||
CONFIG_CRYPTO_ALGAPI=y
|
||||
CONFIG_CRYPTO_BLKCIPHER=y
|
||||
CONFIG_CRYPTO_MANAGER=y
|
||||
# CONFIG_CRYPTO_HMAC is not set
|
||||
# CONFIG_CRYPTO_XCBC is not set
|
||||
# CONFIG_CRYPTO_NULL is not set
|
||||
# CONFIG_CRYPTO_MD4 is not set
|
||||
CONFIG_CRYPTO_MD5=y
|
||||
# CONFIG_CRYPTO_SHA1 is not set
|
||||
# CONFIG_CRYPTO_SHA256 is not set
|
||||
# CONFIG_CRYPTO_SHA512 is not set
|
||||
# CONFIG_CRYPTO_WP512 is not set
|
||||
# CONFIG_CRYPTO_TGR192 is not set
|
||||
# CONFIG_CRYPTO_GF128MUL is not set
|
||||
# CONFIG_CRYPTO_ECB is not set
|
||||
CONFIG_CRYPTO_CBC=y
|
||||
# CONFIG_CRYPTO_PCBC is not set
|
||||
# CONFIG_CRYPTO_LRW is not set
|
||||
# CONFIG_CRYPTO_XTS is not set
|
||||
# CONFIG_CRYPTO_CRYPTD is not set
|
||||
CONFIG_CRYPTO_DES=y
|
||||
# CONFIG_CRYPTO_FCRYPT is not set
|
||||
# CONFIG_CRYPTO_BLOWFISH is not set
|
||||
# CONFIG_CRYPTO_TWOFISH is not set
|
||||
# CONFIG_CRYPTO_SERPENT is not set
|
||||
# CONFIG_CRYPTO_AES is not set
|
||||
# CONFIG_CRYPTO_CAST5 is not set
|
||||
# CONFIG_CRYPTO_CAST6 is not set
|
||||
# CONFIG_CRYPTO_TEA is not set
|
||||
# CONFIG_CRYPTO_ARC4 is not set
|
||||
# CONFIG_CRYPTO_KHAZAD is not set
|
||||
# CONFIG_CRYPTO_ANUBIS is not set
|
||||
# CONFIG_CRYPTO_SEED is not set
|
||||
# CONFIG_CRYPTO_DEFLATE is not set
|
||||
# CONFIG_CRYPTO_MICHAEL_MIC is not set
|
||||
# CONFIG_CRYPTO_CRC32C is not set
|
||||
# CONFIG_CRYPTO_CAMELLIA is not set
|
||||
# CONFIG_CRYPTO_TEST is not set
|
||||
# CONFIG_CRYPTO_AUTHENC is not set
|
||||
# CONFIG_CRYPTO_LZO is not set
|
||||
CONFIG_CRYPTO_HW=y
|
||||
|
||||
#
|
||||
# Library routines
|
||||
#
|
||||
CONFIG_BITREVERSE=y
|
||||
# CONFIG_CRC_CCITT is not set
|
||||
# CONFIG_CRC16 is not set
|
||||
# CONFIG_CRC_ITU_T is not set
|
||||
CONFIG_CRC32=y
|
||||
# CONFIG_CRC7 is not set
|
||||
# CONFIG_LIBCRC32C is not set
|
||||
CONFIG_PLIST=y
|
||||
CONFIG_HAS_IOMEM=y
|
||||
CONFIG_HAS_IOPORT=y
|
||||
CONFIG_HAS_DMA=y
|
||||
1256
target/linux/xburst/files-2.6.27/arch/mips/configs/leo_defconfig
Normal file
1256
target/linux/xburst/files-2.6.27/arch/mips/configs/leo_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,981 @@
|
||||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.24.3
|
||||
# Thu Jun 12 13:53:57 2008
|
||||
#
|
||||
CONFIG_MIPS=y
|
||||
|
||||
#
|
||||
# Machine selection
|
||||
#
|
||||
# CONFIG_JZ4730_PMP is not set
|
||||
# CONFIG_JZ4740_PAVO is not set
|
||||
# CONFIG_JZ4740_LEO is not set
|
||||
CONFIG_JZ4740_LYRA=y
|
||||
# CONFIG_JZ4725_DIPPER is not set
|
||||
# CONFIG_JZ4720_VIRGO is not set
|
||||
# CONFIG_JZ4750_FUWA is not set
|
||||
# CONFIG_MACH_ALCHEMY is not set
|
||||
# CONFIG_BASLER_EXCITE is not set
|
||||
# CONFIG_BCM47XX is not set
|
||||
# CONFIG_MIPS_COBALT is not set
|
||||
# CONFIG_MACH_DECSTATION is not set
|
||||
# CONFIG_MACH_JAZZ is not set
|
||||
# CONFIG_LASAT is not set
|
||||
# CONFIG_LEMOTE_FULONG is not set
|
||||
# CONFIG_MIPS_ATLAS is not set
|
||||
# CONFIG_MIPS_MALTA is not set
|
||||
# CONFIG_MIPS_SEAD is not set
|
||||
# CONFIG_MIPS_SIM is not set
|
||||
# CONFIG_MARKEINS is not set
|
||||
# CONFIG_MACH_VR41XX is not set
|
||||
# CONFIG_PNX8550_JBS is not set
|
||||
# CONFIG_PNX8550_STB810 is not set
|
||||
# CONFIG_PMC_MSP is not set
|
||||
# CONFIG_PMC_YOSEMITE is not set
|
||||
# CONFIG_QEMU is not set
|
||||
# CONFIG_SGI_IP22 is not set
|
||||
# CONFIG_SGI_IP27 is not set
|
||||
# CONFIG_SGI_IP32 is not set
|
||||
# CONFIG_SIBYTE_CRHINE is not set
|
||||
# CONFIG_SIBYTE_CARMEL is not set
|
||||
# CONFIG_SIBYTE_CRHONE is not set
|
||||
# CONFIG_SIBYTE_RHONE is not set
|
||||
# CONFIG_SIBYTE_SWARM is not set
|
||||
# CONFIG_SIBYTE_LITTLESUR is not set
|
||||
# CONFIG_SIBYTE_SENTOSA is not set
|
||||
# CONFIG_SIBYTE_PTSWARM is not set
|
||||
# CONFIG_SIBYTE_BIGSUR is not set
|
||||
# CONFIG_SNI_RM is not set
|
||||
# CONFIG_TOSHIBA_JMR3927 is not set
|
||||
# CONFIG_TOSHIBA_RBTX4927 is not set
|
||||
# CONFIG_TOSHIBA_RBTX4938 is not set
|
||||
# CONFIG_WR_PPMC is not set
|
||||
CONFIG_SOC_JZ4740=y
|
||||
CONFIG_JZSOC=y
|
||||
CONFIG_JZRISC=y
|
||||
CONFIG_RWSEM_GENERIC_SPINLOCK=y
|
||||
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
|
||||
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
|
||||
CONFIG_ARCH_SUPPORTS_OPROFILE=y
|
||||
CONFIG_GENERIC_FIND_NEXT_BIT=y
|
||||
CONFIG_GENERIC_HWEIGHT=y
|
||||
CONFIG_GENERIC_CALIBRATE_DELAY=y
|
||||
CONFIG_GENERIC_CLOCKEVENTS=y
|
||||
CONFIG_GENERIC_TIME=y
|
||||
CONFIG_GENERIC_CMOS_UPDATE=y
|
||||
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
|
||||
# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
|
||||
CONFIG_DMA_NONCOHERENT=y
|
||||
CONFIG_DMA_NEED_PCI_MAP_STATE=y
|
||||
# CONFIG_HOTPLUG_CPU is not set
|
||||
# CONFIG_NO_IOPORT is not set
|
||||
# CONFIG_CPU_BIG_ENDIAN is not set
|
||||
CONFIG_CPU_LITTLE_ENDIAN=y
|
||||
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
|
||||
CONFIG_MIPS_L1_CACHE_SHIFT=5
|
||||
|
||||
#
|
||||
# CPU selection
|
||||
#
|
||||
# CONFIG_CPU_LOONGSON2 is not set
|
||||
CONFIG_CPU_MIPS32_R1=y
|
||||
# CONFIG_CPU_MIPS32_R2 is not set
|
||||
# CONFIG_CPU_MIPS64_R1 is not set
|
||||
# CONFIG_CPU_MIPS64_R2 is not set
|
||||
# CONFIG_CPU_R3000 is not set
|
||||
# CONFIG_CPU_TX39XX is not set
|
||||
# CONFIG_CPU_VR41XX is not set
|
||||
# CONFIG_CPU_R4300 is not set
|
||||
# CONFIG_CPU_R4X00 is not set
|
||||
# CONFIG_CPU_TX49XX is not set
|
||||
# CONFIG_CPU_R5000 is not set
|
||||
# CONFIG_CPU_R5432 is not set
|
||||
# CONFIG_CPU_R6000 is not set
|
||||
# CONFIG_CPU_NEVADA is not set
|
||||
# CONFIG_CPU_R8000 is not set
|
||||
# CONFIG_CPU_R10000 is not set
|
||||
# CONFIG_CPU_RM7000 is not set
|
||||
# CONFIG_CPU_RM9000 is not set
|
||||
# CONFIG_CPU_SB1 is not set
|
||||
CONFIG_SYS_HAS_CPU_MIPS32_R1=y
|
||||
CONFIG_CPU_MIPS32=y
|
||||
CONFIG_CPU_MIPSR1=y
|
||||
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
|
||||
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
|
||||
|
||||
#
|
||||
# Kernel type
|
||||
#
|
||||
CONFIG_32BIT=y
|
||||
# CONFIG_64BIT is not set
|
||||
CONFIG_PAGE_SIZE_4KB=y
|
||||
# CONFIG_PAGE_SIZE_8KB is not set
|
||||
# CONFIG_PAGE_SIZE_16KB is not set
|
||||
# CONFIG_PAGE_SIZE_64KB is not set
|
||||
CONFIG_CPU_HAS_PREFETCH=y
|
||||
CONFIG_MIPS_MT_DISABLED=y
|
||||
# CONFIG_MIPS_MT_SMP is not set
|
||||
# CONFIG_MIPS_MT_SMTC is not set
|
||||
CONFIG_CPU_HAS_LLSC=y
|
||||
CONFIG_CPU_HAS_SYNC=y
|
||||
CONFIG_GENERIC_HARDIRQS=y
|
||||
CONFIG_GENERIC_IRQ_PROBE=y
|
||||
CONFIG_CPU_SUPPORTS_HIGHMEM=y
|
||||
CONFIG_ARCH_FLATMEM_ENABLE=y
|
||||
CONFIG_ARCH_POPULATES_NODE_MAP=y
|
||||
CONFIG_SELECT_MEMORY_MODEL=y
|
||||
CONFIG_FLATMEM_MANUAL=y
|
||||
# CONFIG_DISCONTIGMEM_MANUAL is not set
|
||||
# CONFIG_SPARSEMEM_MANUAL is not set
|
||||
CONFIG_FLATMEM=y
|
||||
CONFIG_FLAT_NODE_MEM_MAP=y
|
||||
# CONFIG_SPARSEMEM_STATIC is not set
|
||||
# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
|
||||
CONFIG_SPLIT_PTLOCK_CPUS=4
|
||||
# CONFIG_RESOURCES_64BIT is not set
|
||||
CONFIG_ZONE_DMA_FLAG=0
|
||||
CONFIG_VIRT_TO_BUS=y
|
||||
# CONFIG_TICK_ONESHOT is not set
|
||||
# CONFIG_NO_HZ is not set
|
||||
# CONFIG_HIGH_RES_TIMERS is not set
|
||||
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
|
||||
# CONFIG_HZ_48 is not set
|
||||
CONFIG_HZ_100=y
|
||||
# CONFIG_HZ_128 is not set
|
||||
# CONFIG_HZ_250 is not set
|
||||
# CONFIG_HZ_256 is not set
|
||||
# CONFIG_HZ_1000 is not set
|
||||
# CONFIG_HZ_1024 is not set
|
||||
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
|
||||
CONFIG_HZ=100
|
||||
# CONFIG_PREEMPT_NONE is not set
|
||||
# CONFIG_PREEMPT_VOLUNTARY is not set
|
||||
CONFIG_PREEMPT=y
|
||||
CONFIG_PREEMPT_BKL=y
|
||||
# CONFIG_KEXEC is not set
|
||||
CONFIG_SECCOMP=y
|
||||
CONFIG_LOCKDEP_SUPPORT=y
|
||||
CONFIG_STACKTRACE_SUPPORT=y
|
||||
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
|
||||
|
||||
#
|
||||
# General setup
|
||||
#
|
||||
CONFIG_EXPERIMENTAL=y
|
||||
CONFIG_BROKEN_ON_SMP=y
|
||||
CONFIG_LOCK_KERNEL=y
|
||||
CONFIG_INIT_ENV_ARG_LIMIT=32
|
||||
CONFIG_LOCALVERSION=""
|
||||
CONFIG_LOCALVERSION_AUTO=y
|
||||
CONFIG_SWAP=y
|
||||
CONFIG_SYSVIPC=y
|
||||
CONFIG_SYSVIPC_SYSCTL=y
|
||||
# CONFIG_BSD_PROCESS_ACCT is not set
|
||||
# CONFIG_USER_NS is not set
|
||||
# CONFIG_PID_NS is not set
|
||||
# CONFIG_IKCONFIG is not set
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
# CONFIG_CGROUPS is not set
|
||||
CONFIG_FAIR_GROUP_SCHED=y
|
||||
CONFIG_FAIR_USER_SCHED=y
|
||||
# CONFIG_FAIR_CGROUP_SCHED is not set
|
||||
CONFIG_SYSFS_DEPRECATED=y
|
||||
CONFIG_RELAY=y
|
||||
# CONFIG_BLK_DEV_INITRD is not set
|
||||
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
||||
CONFIG_SYSCTL=y
|
||||
CONFIG_EMBEDDED=y
|
||||
CONFIG_SYSCTL_SYSCALL=y
|
||||
CONFIG_KALLSYMS=y
|
||||
CONFIG_KALLSYMS_ALL=y
|
||||
# CONFIG_KALLSYMS_EXTRA_PASS is not set
|
||||
CONFIG_HOTPLUG=y
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_BUG=y
|
||||
CONFIG_ELF_CORE=y
|
||||
CONFIG_BASE_FULL=y
|
||||
CONFIG_FUTEX=y
|
||||
CONFIG_ANON_INODES=y
|
||||
CONFIG_EPOLL=y
|
||||
CONFIG_SIGNALFD=y
|
||||
CONFIG_EVENTFD=y
|
||||
CONFIG_SHMEM=y
|
||||
CONFIG_VM_EVENT_COUNTERS=y
|
||||
CONFIG_SLAB=y
|
||||
# CONFIG_SLUB is not set
|
||||
# CONFIG_SLOB is not set
|
||||
CONFIG_SLABINFO=y
|
||||
CONFIG_RT_MUTEXES=y
|
||||
# CONFIG_TINY_SHMEM is not set
|
||||
CONFIG_BASE_SMALL=0
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
# CONFIG_MODULE_FORCE_UNLOAD is not set
|
||||
CONFIG_MODVERSIONS=y
|
||||
CONFIG_MODULE_SRCVERSION_ALL=y
|
||||
CONFIG_KMOD=y
|
||||
CONFIG_BLOCK=y
|
||||
# CONFIG_LBD is not set
|
||||
# CONFIG_BLK_DEV_IO_TRACE is not set
|
||||
# CONFIG_LSF is not set
|
||||
# CONFIG_BLK_DEV_BSG is not set
|
||||
|
||||
#
|
||||
# IO Schedulers
|
||||
#
|
||||
CONFIG_IOSCHED_NOOP=y
|
||||
CONFIG_IOSCHED_AS=y
|
||||
CONFIG_IOSCHED_DEADLINE=y
|
||||
CONFIG_IOSCHED_CFQ=y
|
||||
CONFIG_DEFAULT_AS=y
|
||||
# CONFIG_DEFAULT_DEADLINE is not set
|
||||
# CONFIG_DEFAULT_CFQ is not set
|
||||
# CONFIG_DEFAULT_NOOP is not set
|
||||
CONFIG_DEFAULT_IOSCHED="anticipatory"
|
||||
|
||||
#
|
||||
# Bus options (PCI, PCMCIA, EISA, ISA, TC)
|
||||
#
|
||||
# CONFIG_ARCH_SUPPORTS_MSI is not set
|
||||
CONFIG_MMU=y
|
||||
# CONFIG_PCCARD is not set
|
||||
|
||||
#
|
||||
# Executable file formats
|
||||
#
|
||||
CONFIG_BINFMT_ELF=y
|
||||
# CONFIG_BINFMT_MISC is not set
|
||||
CONFIG_TRAD_SIGNALS=y
|
||||
|
||||
#
|
||||
# CPU Frequency scaling
|
||||
#
|
||||
CONFIG_CPU_FREQ_JZ=y
|
||||
CONFIG_CPU_FREQ=y
|
||||
CONFIG_CPU_FREQ_TABLE=y
|
||||
# CONFIG_CPU_FREQ_DEBUG is not set
|
||||
CONFIG_CPU_FREQ_STAT=y
|
||||
# CONFIG_CPU_FREQ_STAT_DETAILS is not set
|
||||
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
|
||||
CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
|
||||
# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
|
||||
# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
|
||||
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
|
||||
# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
|
||||
CONFIG_CPU_FREQ_GOV_USERSPACE=y
|
||||
# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
|
||||
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
|
||||
|
||||
#
|
||||
# Power management options
|
||||
#
|
||||
CONFIG_PM=y
|
||||
CONFIG_PM_LEGACY=y
|
||||
# CONFIG_PM_DEBUG is not set
|
||||
CONFIG_PM_SLEEP=y
|
||||
CONFIG_SUSPEND_UP_POSSIBLE=y
|
||||
CONFIG_SUSPEND=y
|
||||
|
||||
#
|
||||
# Networking
|
||||
#
|
||||
# CONFIG_NET is not set
|
||||
|
||||
#
|
||||
# Device Drivers
|
||||
#
|
||||
|
||||
#
|
||||
# Generic Driver Options
|
||||
#
|
||||
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
|
||||
CONFIG_STANDALONE=y
|
||||
CONFIG_PREVENT_FIRMWARE_BUILD=y
|
||||
# CONFIG_FW_LOADER is not set
|
||||
# CONFIG_SYS_HYPERVISOR is not set
|
||||
CONFIG_MTD=y
|
||||
# CONFIG_MTD_DEBUG is not set
|
||||
CONFIG_MTD_CONCAT=y
|
||||
CONFIG_MTD_PARTITIONS=y
|
||||
# CONFIG_MTD_REDBOOT_PARTS is not set
|
||||
# CONFIG_MTD_CMDLINE_PARTS is not set
|
||||
|
||||
#
|
||||
# User Modules And Translation Layers
|
||||
#
|
||||
CONFIG_MTD_CHAR=y
|
||||
CONFIG_MTD_BLKDEVS=y
|
||||
CONFIG_MTD_BLOCK=y
|
||||
# CONFIG_FTL is not set
|
||||
# CONFIG_NFTL is not set
|
||||
# CONFIG_INFTL is not set
|
||||
# CONFIG_RFD_FTL is not set
|
||||
# CONFIG_SSFDC is not set
|
||||
# CONFIG_MTD_OOPS is not set
|
||||
|
||||
#
|
||||
# RAM/ROM/Flash chip drivers
|
||||
#
|
||||
# CONFIG_MTD_CFI is not set
|
||||
# CONFIG_MTD_JEDECPROBE is not set
|
||||
CONFIG_MTD_MAP_BANK_WIDTH_1=y
|
||||
CONFIG_MTD_MAP_BANK_WIDTH_2=y
|
||||
CONFIG_MTD_MAP_BANK_WIDTH_4=y
|
||||
# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
|
||||
# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
|
||||
# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
|
||||
CONFIG_MTD_CFI_I1=y
|
||||
CONFIG_MTD_CFI_I2=y
|
||||
# CONFIG_MTD_CFI_I4 is not set
|
||||
# CONFIG_MTD_CFI_I8 is not set
|
||||
# CONFIG_MTD_RAM is not set
|
||||
# CONFIG_MTD_ROM is not set
|
||||
# CONFIG_MTD_ABSENT is not set
|
||||
|
||||
#
|
||||
# Mapping drivers for chip access
|
||||
#
|
||||
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
|
||||
# CONFIG_MTD_PLATRAM is not set
|
||||
|
||||
#
|
||||
# Self-contained MTD device drivers
|
||||
#
|
||||
# CONFIG_MTD_SLRAM is not set
|
||||
# CONFIG_MTD_PHRAM is not set
|
||||
# CONFIG_MTD_MTDRAM is not set
|
||||
CONFIG_MTD_BLOCK2MTD=y
|
||||
|
||||
#
|
||||
# Disk-On-Chip Device Drivers
|
||||
#
|
||||
# CONFIG_MTD_DOC2000 is not set
|
||||
# CONFIG_MTD_DOC2001 is not set
|
||||
# CONFIG_MTD_DOC2001PLUS is not set
|
||||
CONFIG_MTD_NAND=y
|
||||
# CONFIG_MTD_NAND_VERIFY_WRITE is not set
|
||||
# CONFIG_MTD_NAND_ECC_SMC is not set
|
||||
# CONFIG_MTD_NAND_MUSEUM_IDS is not set
|
||||
CONFIG_MTD_NAND_IDS=y
|
||||
# CONFIG_MTD_NAND_DISKONCHIP is not set
|
||||
# CONFIG_MTD_NAND_NANDSIM is not set
|
||||
# CONFIG_MTD_NAND_PLATFORM is not set
|
||||
CONFIG_MTD_NAND_JZ4740=y
|
||||
# CONFIG_MTD_HW_HM_ECC is not set
|
||||
# CONFIG_MTD_SW_HM_ECC is not set
|
||||
CONFIG_MTD_HW_RS_ECC=y
|
||||
# CONFIG_MTD_MTDBLOCK_WRITE_VERIFY_ENABLE is not set
|
||||
CONFIG_MTD_OOB_COPIES=3
|
||||
CONFIG_MTD_BADBLOCK_FLAG_PAGE=127
|
||||
# CONFIG_MTD_ONENAND is not set
|
||||
|
||||
#
|
||||
# UBI - Unsorted block images
|
||||
#
|
||||
CONFIG_MTD_UBI=m
|
||||
CONFIG_MTD_UBI_WL_THRESHOLD=4096
|
||||
CONFIG_MTD_UBI_BEB_RESERVE=1
|
||||
CONFIG_MTD_UBI_GLUEBI=y
|
||||
|
||||
#
|
||||
# UBI debugging options
|
||||
#
|
||||
# CONFIG_MTD_UBI_DEBUG is not set
|
||||
# CONFIG_MTD_UBI_BLKDEVS is not set
|
||||
# CONFIG_PARPORT is not set
|
||||
# CONFIG_PNP is not set
|
||||
CONFIG_BLK_DEV=y
|
||||
# CONFIG_BLK_DEV_COW_COMMON is not set
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_COUNT=16
|
||||
CONFIG_BLK_DEV_RAM_SIZE=4096
|
||||
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
|
||||
# CONFIG_CDROM_PKTCDVD is not set
|
||||
CONFIG_MISC_DEVICES=y
|
||||
# CONFIG_EEPROM_93CX6 is not set
|
||||
# CONFIG_IDE is not set
|
||||
|
||||
#
|
||||
# SCSI device support
|
||||
#
|
||||
# CONFIG_RAID_ATTRS is not set
|
||||
CONFIG_SCSI=y
|
||||
CONFIG_SCSI_DMA=y
|
||||
# CONFIG_SCSI_TGT is not set
|
||||
# CONFIG_SCSI_NETLINK is not set
|
||||
CONFIG_SCSI_PROC_FS=y
|
||||
|
||||
#
|
||||
# SCSI support type (disk, tape, CD-ROM)
|
||||
#
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
# CONFIG_CHR_DEV_ST is not set
|
||||
# CONFIG_CHR_DEV_OSST is not set
|
||||
# CONFIG_BLK_DEV_SR is not set
|
||||
# CONFIG_CHR_DEV_SG is not set
|
||||
# CONFIG_CHR_DEV_SCH is not set
|
||||
|
||||
#
|
||||
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
|
||||
#
|
||||
# CONFIG_SCSI_MULTI_LUN is not set
|
||||
# CONFIG_SCSI_CONSTANTS is not set
|
||||
# CONFIG_SCSI_LOGGING is not set
|
||||
# CONFIG_SCSI_SCAN_ASYNC is not set
|
||||
CONFIG_SCSI_WAIT_SCAN=m
|
||||
|
||||
#
|
||||
# SCSI Transports
|
||||
#
|
||||
# CONFIG_SCSI_SPI_ATTRS is not set
|
||||
# CONFIG_SCSI_FC_ATTRS is not set
|
||||
# CONFIG_SCSI_SAS_LIBSAS is not set
|
||||
# CONFIG_SCSI_SRP_ATTRS is not set
|
||||
CONFIG_SCSI_LOWLEVEL=y
|
||||
# CONFIG_SCSI_DEBUG is not set
|
||||
# CONFIG_ATA is not set
|
||||
# CONFIG_MD is not set
|
||||
# CONFIG_PHONE is not set
|
||||
|
||||
#
|
||||
# Input device support
|
||||
#
|
||||
CONFIG_INPUT=y
|
||||
# CONFIG_INPUT_FF_MEMLESS is not set
|
||||
# CONFIG_INPUT_POLLDEV is not set
|
||||
|
||||
#
|
||||
# Userland interfaces
|
||||
#
|
||||
CONFIG_INPUT_MOUSEDEV=y
|
||||
CONFIG_INPUT_MOUSEDEV_PSAUX=y
|
||||
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
|
||||
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
|
||||
# CONFIG_INPUT_JOYDEV is not set
|
||||
CONFIG_INPUT_EVDEV=y
|
||||
# CONFIG_INPUT_EVBUG is not set
|
||||
|
||||
#
|
||||
# Input Device Drivers
|
||||
#
|
||||
# CONFIG_INPUT_KEYBOARD is not set
|
||||
# CONFIG_INPUT_MOUSE is not set
|
||||
# CONFIG_INPUT_JOYSTICK is not set
|
||||
# CONFIG_INPUT_TABLET is not set
|
||||
# CONFIG_INPUT_TOUCHSCREEN is not set
|
||||
# CONFIG_INPUT_MISC is not set
|
||||
|
||||
#
|
||||
# Hardware I/O ports
|
||||
#
|
||||
CONFIG_SERIO=y
|
||||
# CONFIG_SERIO_I8042 is not set
|
||||
CONFIG_SERIO_SERPORT=y
|
||||
# CONFIG_SERIO_LIBPS2 is not set
|
||||
# CONFIG_SERIO_RAW is not set
|
||||
# CONFIG_GAMEPORT is not set
|
||||
|
||||
#
|
||||
# Character devices
|
||||
#
|
||||
CONFIG_VT=y
|
||||
CONFIG_VT_CONSOLE=y
|
||||
CONFIG_HW_CONSOLE=y
|
||||
CONFIG_VT_HW_CONSOLE_BINDING=y
|
||||
# CONFIG_SERIAL_NONSTANDARD is not set
|
||||
|
||||
#
|
||||
# Serial drivers
|
||||
#
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_NR_UARTS=4
|
||||
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
|
||||
# CONFIG_SERIAL_8250_EXTENDED is not set
|
||||
|
||||
#
|
||||
# Non-8250 serial port support
|
||||
#
|
||||
CONFIG_SERIAL_CORE=y
|
||||
CONFIG_SERIAL_CORE_CONSOLE=y
|
||||
CONFIG_UNIX98_PTYS=y
|
||||
CONFIG_LEGACY_PTYS=y
|
||||
CONFIG_LEGACY_PTY_COUNT=256
|
||||
# CONFIG_IPMI_HANDLER is not set
|
||||
# CONFIG_HW_RANDOM is not set
|
||||
# CONFIG_RTC is not set
|
||||
# CONFIG_RTC_PCF8563 is not set
|
||||
CONFIG_RTC_JZ=y
|
||||
# CONFIG_R3964 is not set
|
||||
# CONFIG_RAW_DRIVER is not set
|
||||
# CONFIG_TCG_TPM is not set
|
||||
|
||||
#
|
||||
# JZSOC char device support
|
||||
#
|
||||
CONFIG_JZCHAR=y
|
||||
# CONFIG_JZ_CIM is not set
|
||||
CONFIG_JZ_TPANEL_ATA2508=y
|
||||
# CONFIG_JZ_TPANEL is not set
|
||||
CONFIG_JZ_UDC_HOTPLUG=y
|
||||
CONFIG_JZ_POWEROFF=y
|
||||
# CONFIG_JZ_OW is not set
|
||||
# CONFIG_I2C is not set
|
||||
|
||||
#
|
||||
# SPI support
|
||||
#
|
||||
# CONFIG_SPI is not set
|
||||
# CONFIG_SPI_MASTER is not set
|
||||
# CONFIG_W1 is not set
|
||||
# CONFIG_POWER_SUPPLY is not set
|
||||
# CONFIG_HWMON is not set
|
||||
CONFIG_WATCHDOG=y
|
||||
# CONFIG_WATCHDOG_NOWAYOUT is not set
|
||||
|
||||
#
|
||||
# Watchdog Device Drivers
|
||||
#
|
||||
CONFIG_JZ_WDT=y
|
||||
# CONFIG_SOFT_WATCHDOG is not set
|
||||
|
||||
#
|
||||
# Sonics Silicon Backplane
|
||||
#
|
||||
CONFIG_SSB_POSSIBLE=y
|
||||
# CONFIG_SSB is not set
|
||||
|
||||
#
|
||||
# Multifunction device drivers
|
||||
#
|
||||
# CONFIG_MFD_SM501 is not set
|
||||
|
||||
#
|
||||
# Multimedia devices
|
||||
#
|
||||
# CONFIG_VIDEO_DEV is not set
|
||||
# CONFIG_DAB is not set
|
||||
|
||||
#
|
||||
# Graphics support
|
||||
#
|
||||
# CONFIG_VGASTATE is not set
|
||||
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
|
||||
CONFIG_FB=y
|
||||
# CONFIG_FIRMWARE_EDID is not set
|
||||
# CONFIG_FB_DDC is not set
|
||||
CONFIG_FB_CFB_FILLRECT=y
|
||||
CONFIG_FB_CFB_COPYAREA=y
|
||||
CONFIG_FB_CFB_IMAGEBLIT=y
|
||||
# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
|
||||
# CONFIG_FB_SYS_FILLRECT is not set
|
||||
# CONFIG_FB_SYS_COPYAREA is not set
|
||||
# CONFIG_FB_SYS_IMAGEBLIT is not set
|
||||
# CONFIG_FB_SYS_FOPS is not set
|
||||
CONFIG_FB_DEFERRED_IO=y
|
||||
# CONFIG_FB_SVGALIB is not set
|
||||
# CONFIG_FB_MACMODES is not set
|
||||
# CONFIG_FB_BACKLIGHT is not set
|
||||
# CONFIG_FB_MODE_HELPERS is not set
|
||||
# CONFIG_FB_TILEBLITTING is not set
|
||||
|
||||
#
|
||||
# Frame buffer hardware drivers
|
||||
#
|
||||
CONFIG_FB_JZSOC=y
|
||||
# CONFIG_FB_JZ4740_SLCD is not set
|
||||
CONFIG_FB_JZLCD_4730_4740=y
|
||||
CONFIG_JZLCD_FRAMEBUFFER_MAX=1
|
||||
# CONFIG_JZLCD_FRAMEBUFFER_ROTATE_SUPPORT is not set
|
||||
# CONFIG_JZLCD_SHARP_LQ035Q7 is not set
|
||||
# CONFIG_JZLCD_SAMSUNG_LTS350Q1 is not set
|
||||
# CONFIG_JZLCD_SAMSUNG_LTV350QVF04 is not set
|
||||
# CONFIG_JZLCD_SAMSUNG_LTP400WQF01 is not set
|
||||
# CONFIG_JZLCD_SAMSUNG_LTP400WQF02 is not set
|
||||
CONFIG_JZLCD_AUO_A030FL01_V1=y
|
||||
# CONFIG_JZLCD_TRULY_TFTG320240DTSW is not set
|
||||
# CONFIG_JZLCD_TRULY_TFTG320240DTSW_SERIAL is not set
|
||||
# CONFIG_JZLCD_TRULY_TFTG240320UTSW_63W_E is not set
|
||||
# CONFIG_JZLCD_FOXCONN_PT035TN01 is not set
|
||||
# CONFIG_JZLCD_INNOLUX_PT035TN01_SERIAL is not set
|
||||
# CONFIG_JZLCD_TOSHIBA_LTM084P363 is not set
|
||||
# CONFIG_JZLCD_HYNIX_HT10X21 is not set
|
||||
# CONFIG_JZLCD_INNOLUX_AT080TN42 is not set
|
||||
# CONFIG_JZLCD_CSTN_800x600 is not set
|
||||
# CONFIG_JZLCD_CSTN_320x240 is not set
|
||||
# CONFIG_JZLCD_MSTN_480x320 is not set
|
||||
# CONFIG_JZLCD_MSTN_320x240 is not set
|
||||
# CONFIG_JZLCD_MSTN_240x128 is not set
|
||||
# CONFIG_FB_S1D13XXX is not set
|
||||
# CONFIG_FB_VIRTUAL is not set
|
||||
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
|
||||
|
||||
#
|
||||
# Display device support
|
||||
#
|
||||
# CONFIG_DISPLAY_SUPPORT is not set
|
||||
|
||||
#
|
||||
# Console display driver support
|
||||
#
|
||||
# CONFIG_VGA_CONSOLE is not set
|
||||
CONFIG_DUMMY_CONSOLE=y
|
||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||
# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
|
||||
# CONFIG_FRAMEBUFFER_CONSOLE_CURSOR_FLASH is not set
|
||||
# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
|
||||
CONFIG_FONTS=y
|
||||
CONFIG_FONT_8x8=y
|
||||
CONFIG_FONT_8x16=y
|
||||
# CONFIG_FONT_6x11 is not set
|
||||
# CONFIG_FONT_7x14 is not set
|
||||
# CONFIG_FONT_PEARL_8x8 is not set
|
||||
# CONFIG_FONT_ACORN_8x8 is not set
|
||||
# CONFIG_FONT_MINI_4x6 is not set
|
||||
# CONFIG_FONT_SUN8x16 is not set
|
||||
# CONFIG_FONT_SUN12x22 is not set
|
||||
# CONFIG_FONT_10x18 is not set
|
||||
CONFIG_LOGO=y
|
||||
CONFIG_LOGO_LINUX_MONO=y
|
||||
CONFIG_LOGO_LINUX_VGA16=y
|
||||
CONFIG_LOGO_LINUX_CLUT224=y
|
||||
|
||||
#
|
||||
# Sound
|
||||
#
|
||||
CONFIG_SOUND=y
|
||||
|
||||
#
|
||||
# Advanced Linux Sound Architecture
|
||||
#
|
||||
# CONFIG_SND is not set
|
||||
|
||||
#
|
||||
# Open Sound System
|
||||
#
|
||||
CONFIG_SOUND_PRIME=y
|
||||
CONFIG_OSS_OBSOLETE=y
|
||||
# CONFIG_SOUND_JZ_AC97 is not set
|
||||
CONFIG_SOUND_JZ_I2S=y
|
||||
# CONFIG_SOUND_JZ_PCM is not set
|
||||
# CONFIG_I2S_AK4642EN is not set
|
||||
CONFIG_I2S_ICODEC=y
|
||||
# CONFIG_SOUND_MSNDCLAS is not set
|
||||
# CONFIG_SOUND_MSNDPIN is not set
|
||||
CONFIG_HID_SUPPORT=y
|
||||
CONFIG_HID=y
|
||||
# CONFIG_HID_DEBUG is not set
|
||||
# CONFIG_HIDRAW is not set
|
||||
CONFIG_USB_SUPPORT=y
|
||||
CONFIG_USB_ARCH_HAS_HCD=y
|
||||
CONFIG_USB_ARCH_HAS_OHCI=y
|
||||
# CONFIG_USB_ARCH_HAS_EHCI is not set
|
||||
# CONFIG_USB is not set
|
||||
|
||||
#
|
||||
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
|
||||
#
|
||||
|
||||
#
|
||||
# USB Gadget Support
|
||||
#
|
||||
CONFIG_USB_GADGET=m
|
||||
CONFIG_USB_GADGET_DEBUG_FILES=y
|
||||
# CONFIG_USB_GADGET_DEBUG_FS is not set
|
||||
CONFIG_USB_GADGET_SELECTED=y
|
||||
CONFIG_USB_GADGET_JZ4740=y
|
||||
CONFIG_USB_JZ4740=m
|
||||
# CONFIG_USB_GADGET_JZ4730 is not set
|
||||
# CONFIG_USB_GADGET_AMD5536UDC is not set
|
||||
# CONFIG_USB_GADGET_ATMEL_USBA is not set
|
||||
# CONFIG_USB_GADGET_FSL_USB2 is not set
|
||||
# CONFIG_USB_GADGET_NET2280 is not set
|
||||
# CONFIG_USB_GADGET_PXA2XX is not set
|
||||
# CONFIG_USB_GADGET_M66592 is not set
|
||||
# CONFIG_USB_GADGET_GOKU is not set
|
||||
# CONFIG_USB_GADGET_LH7A40X is not set
|
||||
# CONFIG_USB_GADGET_OMAP is not set
|
||||
# CONFIG_USB_GADGET_S3C2410 is not set
|
||||
# CONFIG_USB_GADGET_AT91 is not set
|
||||
# CONFIG_USB_GADGET_DUMMY_HCD is not set
|
||||
CONFIG_USB_GADGET_DUALSPEED=y
|
||||
# CONFIG_USB_ZERO is not set
|
||||
# CONFIG_USB_ETH is not set
|
||||
# CONFIG_USB_GADGETFS is not set
|
||||
CONFIG_USB_FILE_STORAGE=m
|
||||
# CONFIG_USB_FILE_STORAGE_TEST is not set
|
||||
CONFIG_USB_G_SERIAL=m
|
||||
# CONFIG_USB_MIDI_GADGET is not set
|
||||
CONFIG_MMC=y
|
||||
# CONFIG_MMC_DEBUG is not set
|
||||
# CONFIG_MMC_UNSAFE_RESUME is not set
|
||||
|
||||
#
|
||||
# MMC/SD Card Drivers
|
||||
#
|
||||
CONFIG_MMC_BLOCK=y
|
||||
CONFIG_MMC_BLOCK_BOUNCE=y
|
||||
# CONFIG_SDIO_UART is not set
|
||||
|
||||
#
|
||||
# MMC/SD Host Controller Drivers
|
||||
#
|
||||
# CONFIG_MMC_JZ is not set
|
||||
# CONFIG_NEW_LEDS is not set
|
||||
CONFIG_RTC_LIB=y
|
||||
# CONFIG_RTC_CLASS is not set
|
||||
|
||||
#
|
||||
# Userspace I/O
|
||||
#
|
||||
# CONFIG_UIO is not set
|
||||
|
||||
#
|
||||
# File systems
|
||||
#
|
||||
CONFIG_EXT2_FS=y
|
||||
CONFIG_EXT2_FS_XATTR=y
|
||||
# CONFIG_EXT2_FS_POSIX_ACL is not set
|
||||
# CONFIG_EXT2_FS_SECURITY is not set
|
||||
# CONFIG_EXT2_FS_XIP is not set
|
||||
CONFIG_EXT3_FS=y
|
||||
CONFIG_EXT3_FS_XATTR=y
|
||||
# CONFIG_EXT3_FS_POSIX_ACL is not set
|
||||
# CONFIG_EXT3_FS_SECURITY is not set
|
||||
# CONFIG_EXT4DEV_FS is not set
|
||||
CONFIG_JBD=y
|
||||
# CONFIG_JBD_DEBUG is not set
|
||||
CONFIG_FS_MBCACHE=y
|
||||
# CONFIG_REISERFS_FS is not set
|
||||
# CONFIG_JFS_FS is not set
|
||||
# CONFIG_FS_POSIX_ACL is not set
|
||||
# CONFIG_XFS_FS is not set
|
||||
# CONFIG_GFS2_FS is not set
|
||||
CONFIG_MINIX_FS=y
|
||||
# CONFIG_ROMFS_FS is not set
|
||||
CONFIG_INOTIFY=y
|
||||
CONFIG_INOTIFY_USER=y
|
||||
# CONFIG_QUOTA is not set
|
||||
CONFIG_DNOTIFY=y
|
||||
# CONFIG_AUTOFS_FS is not set
|
||||
# CONFIG_AUTOFS4_FS is not set
|
||||
# CONFIG_FUSE_FS is not set
|
||||
|
||||
#
|
||||
# CD-ROM/DVD Filesystems
|
||||
#
|
||||
# CONFIG_ISO9660_FS is not set
|
||||
# CONFIG_UDF_FS is not set
|
||||
|
||||
#
|
||||
# DOS/FAT/NT Filesystems
|
||||
#
|
||||
CONFIG_FAT_FS=y
|
||||
CONFIG_MSDOS_FS=y
|
||||
CONFIG_VFAT_FS=y
|
||||
CONFIG_FAT_DEFAULT_CODEPAGE=437
|
||||
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
|
||||
# CONFIG_NTFS_FS is not set
|
||||
|
||||
#
|
||||
# Pseudo filesystems
|
||||
#
|
||||
CONFIG_PROC_FS=y
|
||||
CONFIG_PROC_KCORE=y
|
||||
CONFIG_PROC_SYSCTL=y
|
||||
CONFIG_SYSFS=y
|
||||
CONFIG_TMPFS=y
|
||||
# CONFIG_TMPFS_POSIX_ACL is not set
|
||||
# CONFIG_HUGETLB_PAGE is not set
|
||||
# CONFIG_CONFIGFS_FS is not set
|
||||
|
||||
#
|
||||
# Miscellaneous filesystems
|
||||
#
|
||||
# CONFIG_ADFS_FS is not set
|
||||
# CONFIG_AFFS_FS is not set
|
||||
# CONFIG_HFS_FS is not set
|
||||
# CONFIG_HFSPLUS_FS is not set
|
||||
# CONFIG_BEFS_FS is not set
|
||||
# CONFIG_BFS_FS is not set
|
||||
# CONFIG_EFS_FS is not set
|
||||
# CONFIG_JFFS2_FS is not set
|
||||
CONFIG_UBIFS_FS=m
|
||||
# CONFIG_UBIFS_FS_XATTR is not set
|
||||
# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
|
||||
CONFIG_UBIFS_FS_LZO=y
|
||||
CONFIG_UBIFS_FS_ZLIB=y
|
||||
CONFIG_UBIFS_FS_DEBUG=y
|
||||
CONFIG_UBIFS_FS_DEBUG_MSG_LVL=0
|
||||
# CONFIG_UBIFS_FS_DEBUG_CHKS is not set
|
||||
# CONFIG_CRAMFS is not set
|
||||
# CONFIG_VXFS_FS is not set
|
||||
# CONFIG_HPFS_FS is not set
|
||||
# CONFIG_QNX4FS_FS is not set
|
||||
# CONFIG_SYSV_FS is not set
|
||||
# CONFIG_UFS_FS is not set
|
||||
|
||||
#
|
||||
# Partition Types
|
||||
#
|
||||
CONFIG_PARTITION_ADVANCED=y
|
||||
# CONFIG_ACORN_PARTITION is not set
|
||||
# CONFIG_OSF_PARTITION is not set
|
||||
# CONFIG_AMIGA_PARTITION is not set
|
||||
# CONFIG_ATARI_PARTITION is not set
|
||||
# CONFIG_MAC_PARTITION is not set
|
||||
CONFIG_MSDOS_PARTITION=y
|
||||
# CONFIG_BSD_DISKLABEL is not set
|
||||
# CONFIG_MINIX_SUBPARTITION is not set
|
||||
# CONFIG_SOLARIS_X86_PARTITION is not set
|
||||
# CONFIG_UNIXWARE_DISKLABEL is not set
|
||||
# CONFIG_LDM_PARTITION is not set
|
||||
# CONFIG_SGI_PARTITION is not set
|
||||
# CONFIG_ULTRIX_PARTITION is not set
|
||||
# CONFIG_SUN_PARTITION is not set
|
||||
# CONFIG_KARMA_PARTITION is not set
|
||||
# CONFIG_EFI_PARTITION is not set
|
||||
# CONFIG_SYSV68_PARTITION is not set
|
||||
CONFIG_NLS=y
|
||||
CONFIG_NLS_DEFAULT="iso8859-1"
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
# CONFIG_NLS_CODEPAGE_737 is not set
|
||||
# CONFIG_NLS_CODEPAGE_775 is not set
|
||||
# CONFIG_NLS_CODEPAGE_850 is not set
|
||||
# CONFIG_NLS_CODEPAGE_852 is not set
|
||||
# CONFIG_NLS_CODEPAGE_855 is not set
|
||||
# CONFIG_NLS_CODEPAGE_857 is not set
|
||||
# CONFIG_NLS_CODEPAGE_860 is not set
|
||||
# CONFIG_NLS_CODEPAGE_861 is not set
|
||||
# CONFIG_NLS_CODEPAGE_862 is not set
|
||||
# CONFIG_NLS_CODEPAGE_863 is not set
|
||||
# CONFIG_NLS_CODEPAGE_864 is not set
|
||||
# CONFIG_NLS_CODEPAGE_865 is not set
|
||||
# CONFIG_NLS_CODEPAGE_866 is not set
|
||||
# CONFIG_NLS_CODEPAGE_869 is not set
|
||||
CONFIG_NLS_CODEPAGE_936=y
|
||||
# CONFIG_NLS_CODEPAGE_950 is not set
|
||||
# CONFIG_NLS_CODEPAGE_932 is not set
|
||||
# CONFIG_NLS_CODEPAGE_949 is not set
|
||||
# CONFIG_NLS_CODEPAGE_874 is not set
|
||||
# CONFIG_NLS_ISO8859_8 is not set
|
||||
# CONFIG_NLS_CODEPAGE_1250 is not set
|
||||
# CONFIG_NLS_CODEPAGE_1251 is not set
|
||||
CONFIG_NLS_ASCII=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
# CONFIG_NLS_ISO8859_2 is not set
|
||||
# CONFIG_NLS_ISO8859_3 is not set
|
||||
# CONFIG_NLS_ISO8859_4 is not set
|
||||
# CONFIG_NLS_ISO8859_5 is not set
|
||||
# CONFIG_NLS_ISO8859_6 is not set
|
||||
# CONFIG_NLS_ISO8859_7 is not set
|
||||
# CONFIG_NLS_ISO8859_9 is not set
|
||||
# CONFIG_NLS_ISO8859_13 is not set
|
||||
# CONFIG_NLS_ISO8859_14 is not set
|
||||
# CONFIG_NLS_ISO8859_15 is not set
|
||||
# CONFIG_NLS_KOI8_R is not set
|
||||
# CONFIG_NLS_KOI8_U is not set
|
||||
# CONFIG_NLS_UTF8 is not set
|
||||
|
||||
#
|
||||
# Yaffs2 Filesystems
|
||||
#
|
||||
CONFIG_YAFFS_FS=y
|
||||
CONFIG_YAFFS_YAFFS1=y
|
||||
# CONFIG_YAFFS_DOES_ECC is not set
|
||||
CONFIG_YAFFS_YAFFS2=y
|
||||
CONFIG_YAFFS_AUTO_YAFFS2=y
|
||||
# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
|
||||
# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
|
||||
CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK=y
|
||||
CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
|
||||
CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
|
||||
CONFIG_INSTRUMENTATION=y
|
||||
# CONFIG_PROFILING is not set
|
||||
# CONFIG_MARKERS is not set
|
||||
|
||||
#
|
||||
# Kernel hacking
|
||||
#
|
||||
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
|
||||
# CONFIG_PRINTK_TIME is not set
|
||||
CONFIG_ENABLE_WARN_DEPRECATED=y
|
||||
CONFIG_ENABLE_MUST_CHECK=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
# CONFIG_UNUSED_SYMBOLS is not set
|
||||
CONFIG_DEBUG_FS=y
|
||||
# CONFIG_HEADERS_CHECK is not set
|
||||
# CONFIG_DEBUG_KERNEL is not set
|
||||
# CONFIG_SAMPLES is not set
|
||||
CONFIG_CMDLINE=""
|
||||
|
||||
#
|
||||
# Security options
|
||||
#
|
||||
# CONFIG_KEYS is not set
|
||||
# CONFIG_SECURITY is not set
|
||||
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
|
||||
CONFIG_CRYPTO=y
|
||||
CONFIG_CRYPTO_ALGAPI=y
|
||||
CONFIG_CRYPTO_BLKCIPHER=y
|
||||
CONFIG_CRYPTO_MANAGER=y
|
||||
# CONFIG_CRYPTO_HMAC is not set
|
||||
# CONFIG_CRYPTO_XCBC is not set
|
||||
# CONFIG_CRYPTO_NULL is not set
|
||||
# CONFIG_CRYPTO_MD4 is not set
|
||||
CONFIG_CRYPTO_MD5=y
|
||||
# CONFIG_CRYPTO_SHA1 is not set
|
||||
# CONFIG_CRYPTO_SHA256 is not set
|
||||
# CONFIG_CRYPTO_SHA512 is not set
|
||||
# CONFIG_CRYPTO_WP512 is not set
|
||||
# CONFIG_CRYPTO_TGR192 is not set
|
||||
# CONFIG_CRYPTO_GF128MUL is not set
|
||||
# CONFIG_CRYPTO_ECB is not set
|
||||
CONFIG_CRYPTO_CBC=y
|
||||
# CONFIG_CRYPTO_PCBC is not set
|
||||
# CONFIG_CRYPTO_LRW is not set
|
||||
# CONFIG_CRYPTO_XTS is not set
|
||||
# CONFIG_CRYPTO_CRYPTD is not set
|
||||
CONFIG_CRYPTO_DES=y
|
||||
# CONFIG_CRYPTO_FCRYPT is not set
|
||||
# CONFIG_CRYPTO_BLOWFISH is not set
|
||||
# CONFIG_CRYPTO_TWOFISH is not set
|
||||
# CONFIG_CRYPTO_SERPENT is not set
|
||||
# CONFIG_CRYPTO_AES is not set
|
||||
# CONFIG_CRYPTO_CAST5 is not set
|
||||
# CONFIG_CRYPTO_CAST6 is not set
|
||||
# CONFIG_CRYPTO_TEA is not set
|
||||
# CONFIG_CRYPTO_ARC4 is not set
|
||||
# CONFIG_CRYPTO_KHAZAD is not set
|
||||
# CONFIG_CRYPTO_ANUBIS is not set
|
||||
# CONFIG_CRYPTO_SEED is not set
|
||||
CONFIG_CRYPTO_DEFLATE=m
|
||||
# CONFIG_CRYPTO_MICHAEL_MIC is not set
|
||||
# CONFIG_CRYPTO_CRC32C is not set
|
||||
# CONFIG_CRYPTO_CAMELLIA is not set
|
||||
# CONFIG_CRYPTO_TEST is not set
|
||||
# CONFIG_CRYPTO_AUTHENC is not set
|
||||
CONFIG_CRYPTO_LZO=m
|
||||
CONFIG_CRYPTO_HW=y
|
||||
|
||||
#
|
||||
# Library routines
|
||||
#
|
||||
CONFIG_BITREVERSE=y
|
||||
# CONFIG_CRC_CCITT is not set
|
||||
CONFIG_CRC16=m
|
||||
# CONFIG_CRC_ITU_T is not set
|
||||
CONFIG_CRC32=y
|
||||
# CONFIG_CRC7 is not set
|
||||
# CONFIG_LIBCRC32C is not set
|
||||
CONFIG_ZLIB_INFLATE=m
|
||||
CONFIG_ZLIB_DEFLATE=m
|
||||
CONFIG_LZO_COMPRESS=m
|
||||
CONFIG_LZO_DECOMPRESS=m
|
||||
CONFIG_PLIST=y
|
||||
CONFIG_HAS_IOMEM=y
|
||||
CONFIG_HAS_IOPORT=y
|
||||
CONFIG_HAS_DMA=y
|
||||
1329
target/linux/xburst/files-2.6.27/arch/mips/configs/pavo_defconfig
Normal file
1329
target/linux/xburst/files-2.6.27/arch/mips/configs/pavo_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
1212
target/linux/xburst/files-2.6.27/arch/mips/configs/pmp_defconfig
Normal file
1212
target/linux/xburst/files-2.6.27/arch/mips/configs/pmp_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
1281
target/linux/xburst/files-2.6.27/arch/mips/configs/virgo_defconfig
Normal file
1281
target/linux/xburst/files-2.6.27/arch/mips/configs/virgo_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
22
target/linux/xburst/files-2.6.27/arch/mips/jz4730/Makefile
Normal file
22
target/linux/xburst/files-2.6.27/arch/mips/jz4730/Makefile
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Makefile for the Ingenic JZ4730.
|
||||
#
|
||||
|
||||
# Object file lists.
|
||||
|
||||
obj-y += prom.o irq.o time.o reset.o setup.o dma.o \
|
||||
platform.o i2c.o
|
||||
|
||||
obj-$(CONFIG_PROC_FS) += proc.o
|
||||
|
||||
# board specific support
|
||||
|
||||
obj-$(CONFIG_JZ4730_PMP) += board-pmp.o
|
||||
|
||||
# CPU Frequency scaling support
|
||||
|
||||
obj-$(CONFIG_CPU_FREQ_JZ) +=cpufreq.o
|
||||
|
||||
# PM support
|
||||
|
||||
obj-$(CONFIG_PM_LEGACY) +=pm.o sleep.o
|
||||
109
target/linux/xburst/files-2.6.27/arch/mips/jz4730/board-pmp.c
Normal file
109
target/linux/xburst/files-2.6.27/arch/mips/jz4730/board-pmp.c
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4730/board-pmp.c
|
||||
*
|
||||
* JZ4730 PMP board setup routines.
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/reboot.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
extern void (*jz_timer_callback)(void);
|
||||
|
||||
static void dancing(void)
|
||||
{
|
||||
static unsigned int count = 0;
|
||||
|
||||
count ++;
|
||||
count &= 1;
|
||||
if (count)
|
||||
__gpio_set_pin(GPIO_LED_EN);
|
||||
else
|
||||
__gpio_clear_pin(GPIO_LED_EN);
|
||||
}
|
||||
|
||||
static void pmp_timer_ack(void)
|
||||
{
|
||||
static unsigned int count = 0;
|
||||
count ++;
|
||||
if (count % 100 == 0) {
|
||||
count = 0;
|
||||
dancing();
|
||||
}
|
||||
}
|
||||
|
||||
static void __init board_cpm_setup(void)
|
||||
{
|
||||
__cpm_start_all();
|
||||
}
|
||||
|
||||
static void __init board_gpio_setup(void)
|
||||
{
|
||||
/*
|
||||
* Most of the gpios have been setup in the bootloader.
|
||||
*/
|
||||
|
||||
__harb_usb0_uhc();
|
||||
__gpio_as_dma();
|
||||
__gpio_as_eth();
|
||||
__gpio_as_usb();
|
||||
__gpio_as_lcd_master();
|
||||
#if defined(CONFIG_I2S_AK4642EN)
|
||||
__gpio_as_scc1();
|
||||
#endif
|
||||
#if defined(CONFIG_I2S_TSC2301) || defined(CONFIG_I2S_TLC320AIC23)
|
||||
__gpio_as_ssi();
|
||||
#endif
|
||||
//__gpio_as_ac97();
|
||||
#if defined(CONFIG_I2S_TSC2301) || defined(CONFIG_I2S_TLC320AIC23) || defined(CONFIG_I2S_CS42L51)
|
||||
__gpio_as_i2s_slave();
|
||||
#endif
|
||||
__gpio_as_cim();
|
||||
__gpio_as_msc();
|
||||
|
||||
__gpio_as_output(GPIO_LED_EN);
|
||||
__gpio_set_pin(GPIO_LED_EN);
|
||||
|
||||
__gpio_as_output(GPIO_DISP_OFF_N);
|
||||
__gpio_set_pin(GPIO_DISP_OFF_N);
|
||||
__gpio_as_output(GPIO_PWM0);
|
||||
__gpio_set_pin(GPIO_PWM0);
|
||||
|
||||
__gpio_as_input(GPIO_RTC_IRQ);
|
||||
__gpio_as_output(GPIO_USB_CLK_EN);
|
||||
__gpio_set_pin(GPIO_USB_CLK_EN);
|
||||
|
||||
__gpio_as_input(GPIO_CHARG_STAT);
|
||||
__gpio_disable_pull(GPIO_CHARG_STAT);
|
||||
|
||||
__gpio_as_input(GPIO_UDC_HOTPLUG);
|
||||
__gpio_disable_pull(GPIO_UDC_HOTPLUG);
|
||||
__gpio_disable_pull(54); /* fixed ic bug, the pull of gpio pin 86 is as pin 54 */
|
||||
}
|
||||
|
||||
void __init jz_board_setup(void)
|
||||
{
|
||||
printk("JZ4730 PMP board setup\n");
|
||||
|
||||
board_cpm_setup();
|
||||
board_gpio_setup();
|
||||
|
||||
jz_timer_callback = pmp_timer_ack;
|
||||
}
|
||||
596
target/linux/xburst/files-2.6.27/arch/mips/jz4730/cpufreq.c
Normal file
596
target/linux/xburst/files-2.6.27/arch/mips/jz4730/cpufreq.c
Normal file
@@ -0,0 +1,596 @@
|
||||
|
||||
/*
|
||||
* linux/arch/mips/jz4730/cpufreq.c
|
||||
*
|
||||
* cpufreq driver for JZ4730
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <lhhuang@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <linux/cpufreq.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
|
||||
"cpufreq-jz4730", msg)
|
||||
|
||||
#undef CHANGE_PLL
|
||||
|
||||
#define PLL_UNCHANGED 0
|
||||
#define PLL_GOES_UP 1
|
||||
#define PLL_GOES_DOWN 2
|
||||
|
||||
#define PLL_WAIT_500NS (500*(__cpm_get_iclk()/1000000000))
|
||||
|
||||
/* Saved the boot-time parameters */
|
||||
static struct {
|
||||
/* SDRAM parameters */
|
||||
unsigned int mclk; /* memory clock, KHz */
|
||||
unsigned int tras; /* RAS pulse width, cycles of mclk */
|
||||
unsigned int rcd; /* RAS to CAS Delay, cycles of mclk */
|
||||
unsigned int tpc; /* RAS Precharge time, cycles of mclk */
|
||||
unsigned int trwl; /* Write Precharge Time, cycles of mclk */
|
||||
unsigned int trc; /* RAS Cycle Time, cycles of mclk */
|
||||
unsigned int rtcor; /* Refresh Time Constant */
|
||||
unsigned int sdram_initialized;
|
||||
|
||||
/* LCD parameters */
|
||||
unsigned int lcd_clk; /* LCD clock, Hz */
|
||||
unsigned int lcdpix_clk; /* LCD Pixel clock, Hz */
|
||||
unsigned int lcd_clks_initialized;
|
||||
} boot_config;
|
||||
|
||||
struct jz4730_freq_percpu_info {
|
||||
struct cpufreq_frequency_table table[7];
|
||||
};
|
||||
|
||||
static struct jz4730_freq_percpu_info jz4730_freq_table;
|
||||
|
||||
/*
|
||||
* This contains the registers value for an operating point.
|
||||
* If only part of a register needs to change then there is
|
||||
* a mask value for that register.
|
||||
* When going to a new operating point the current register
|
||||
* value is ANDed with the ~mask and ORed with the new value.
|
||||
*/
|
||||
struct dpm_regs {
|
||||
u32 cfcr; /* Clock Freq Control Register */
|
||||
u32 cfcr_mask; /* Clock Freq Control Register mask */
|
||||
u32 cfcr2; /* Clock Freq Control Register 2 */
|
||||
u32 cfcr2_mask; /* Clock Freq Control Register 2 mask */
|
||||
u32 plcr1; /* PLL1 Control Register */
|
||||
u32 plcr1_mask; /* PLL1 Control Register mask */
|
||||
u32 pll_up_flag; /* New PLL freq is higher than current or not */
|
||||
};
|
||||
|
||||
extern jz_clocks_t jz_clocks;
|
||||
|
||||
static void jz_update_clocks(void)
|
||||
{
|
||||
/* Next clocks must be updated if we have changed
|
||||
* the PLL or divisors.
|
||||
*/
|
||||
jz_clocks.iclk = __cpm_get_iclk();
|
||||
jz_clocks.sclk = __cpm_get_sclk();
|
||||
jz_clocks.mclk = __cpm_get_mclk();
|
||||
jz_clocks.pclk = __cpm_get_pclk();
|
||||
jz_clocks.lcdclk = __cpm_get_lcdclk();
|
||||
jz_clocks.pixclk = __cpm_get_pixclk();
|
||||
}
|
||||
|
||||
static void
|
||||
jz_init_boot_config(void)
|
||||
{
|
||||
if (!boot_config.lcd_clks_initialized) {
|
||||
/* the first time to scale pll */
|
||||
boot_config.lcd_clk = __cpm_get_lcdclk();
|
||||
boot_config.lcdpix_clk = __cpm_get_pixclk();
|
||||
boot_config.lcd_clks_initialized = 1;
|
||||
}
|
||||
|
||||
if (!boot_config.sdram_initialized) {
|
||||
/* the first time to scale frequencies */
|
||||
unsigned int dmcr, rtcor;
|
||||
unsigned int tras, rcd, tpc, trwl, trc;
|
||||
|
||||
dmcr = REG_EMC_DMCR;
|
||||
rtcor = REG_EMC_RTCOR;
|
||||
|
||||
tras = (dmcr >> 13) & 0x7;
|
||||
rcd = (dmcr >> 11) & 0x3;
|
||||
tpc = (dmcr >> 8) & 0x7;
|
||||
trwl = (dmcr >> 5) & 0x3;
|
||||
trc = (dmcr >> 2) & 0x7;
|
||||
|
||||
boot_config.mclk = __cpm_get_mclk() / 1000;
|
||||
boot_config.tras = tras + 4;
|
||||
boot_config.rcd = rcd + 1;
|
||||
boot_config.tpc = tpc + 1;
|
||||
boot_config.trwl = trwl + 1;
|
||||
boot_config.trc = trc * 2 + 1;
|
||||
boot_config.rtcor = rtcor;
|
||||
|
||||
boot_config.sdram_initialized = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void jz_update_dram_rtcor(unsigned int new_mclk)
|
||||
{
|
||||
unsigned int rtcor;
|
||||
|
||||
new_mclk /= 1000;
|
||||
rtcor = boot_config.rtcor * new_mclk / boot_config.mclk;
|
||||
rtcor--;
|
||||
|
||||
if (rtcor < 1) rtcor = 1;
|
||||
if (rtcor > 255) rtcor = 255;
|
||||
|
||||
REG_EMC_RTCOR = rtcor;
|
||||
REG_EMC_RTCNT = rtcor;
|
||||
}
|
||||
|
||||
static void jz_update_dram_dmcr(unsigned int new_mclk)
|
||||
{
|
||||
unsigned int dmcr;
|
||||
unsigned int tras, rcd, tpc, trwl, trc;
|
||||
unsigned int valid_time, new_time; /* ns */
|
||||
|
||||
new_mclk /= 1000;
|
||||
tras = boot_config.tras * new_mclk / boot_config.mclk;
|
||||
rcd = boot_config.rcd * new_mclk / boot_config.mclk;
|
||||
tpc = boot_config.tpc * new_mclk / boot_config.mclk;
|
||||
trwl = boot_config.trwl * new_mclk / boot_config.mclk;
|
||||
trc = boot_config.trc * new_mclk / boot_config.mclk;
|
||||
|
||||
/* Validation checking */
|
||||
valid_time = (boot_config.tras * 1000000) / boot_config.mclk;
|
||||
new_time = (tras * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) tras += 1;
|
||||
|
||||
valid_time = (boot_config.rcd * 1000000) / boot_config.mclk;
|
||||
new_time = (rcd * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) rcd += 1;
|
||||
|
||||
valid_time = (boot_config.tpc * 1000000) / boot_config.mclk;
|
||||
new_time = (tpc * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) tpc += 1;
|
||||
|
||||
valid_time = (boot_config.trwl * 1000000) / boot_config.mclk;
|
||||
new_time = (trwl * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) trwl += 1;
|
||||
|
||||
valid_time = (boot_config.trc * 1000000) / boot_config.mclk;
|
||||
new_time = (trc * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) trc += 2;
|
||||
|
||||
tras = (tras < 4) ? 4: tras;
|
||||
tras = (tras > 11) ? 11: tras;
|
||||
tras -= 4;
|
||||
|
||||
rcd = (rcd < 1) ? 1: rcd;
|
||||
rcd = (rcd > 4) ? 4: rcd;
|
||||
rcd -= 1;
|
||||
|
||||
tpc = (tpc < 1) ? 1: tpc;
|
||||
tpc = (tpc > 8) ? 8: tpc;
|
||||
tpc -= 1;
|
||||
|
||||
trwl = (trwl < 1) ? 1: trwl;
|
||||
trwl = (trwl > 4) ? 4: trwl;
|
||||
trwl -= 1;
|
||||
|
||||
trc = (trc < 1) ? 1: trc;
|
||||
trc = (trc > 15) ? 15: trc;
|
||||
trc /= 2;
|
||||
|
||||
dmcr = REG_EMC_DMCR;
|
||||
|
||||
dmcr &= ~(EMC_DMCR_TRAS_MASK | EMC_DMCR_RCD_MASK | EMC_DMCR_TPC_MASK | EMC_DMCR_TRWL_MASK | EMC_DMCR_TRC_MASK);
|
||||
dmcr |= ((tras << EMC_DMCR_TRAS_BIT) | (rcd << EMC_DMCR_RCD_BIT) | (tpc << EMC_DMCR_TPC_BIT) | (trwl << EMC_DMCR_TRWL_BIT) | (trc << EMC_DMCR_TRC_BIT));
|
||||
|
||||
REG_EMC_DMCR = dmcr;
|
||||
}
|
||||
|
||||
static void jz_update_dram_prev(unsigned int cur_mclk, unsigned int new_mclk)
|
||||
{
|
||||
/* No risk, no fun: run with interrupts on! */
|
||||
if (new_mclk > cur_mclk) {
|
||||
/* We're going FASTER, so first update TRAS, RCD, TPC, TRWL
|
||||
* and TRC of DMCR before changing the frequency.
|
||||
*/
|
||||
jz_update_dram_dmcr(new_mclk);
|
||||
} else {
|
||||
/* We're going SLOWER: first update RTCOR value
|
||||
* before changing the frequency.
|
||||
*/
|
||||
jz_update_dram_rtcor(new_mclk);
|
||||
}
|
||||
}
|
||||
|
||||
static void jz_update_dram_post(unsigned int cur_mclk, unsigned int new_mclk)
|
||||
{
|
||||
/* No risk, no fun: run with interrupts on! */
|
||||
if (new_mclk > cur_mclk) {
|
||||
/* We're going FASTER, so update RTCOR
|
||||
* after changing the frequency
|
||||
*/
|
||||
jz_update_dram_rtcor(new_mclk);
|
||||
} else {
|
||||
/* We're going SLOWER: so update TRAS, RCD, TPC, TRWL
|
||||
* and TRC of DMCR after changing the frequency.
|
||||
*/
|
||||
jz_update_dram_dmcr(new_mclk);
|
||||
}
|
||||
}
|
||||
|
||||
static void jz_scale_divisors(struct dpm_regs *regs)
|
||||
{
|
||||
unsigned int cfcr;
|
||||
unsigned int cur_mclk, new_mclk;
|
||||
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
|
||||
unsigned int tmp = 0, wait = PLL_WAIT_500NS;
|
||||
|
||||
cfcr = REG_CPM_CFCR;
|
||||
cfcr &= ~((unsigned long)regs->cfcr_mask);
|
||||
cfcr |= regs->cfcr;
|
||||
cfcr |= CPM_CFCR_UPE; /* update immediately */
|
||||
|
||||
cur_mclk = __cpm_get_mclk();
|
||||
new_mclk = __cpm_get_pllout() / div[(cfcr & CPM_CFCR_MFR_MASK) >> CPM_CFCR_MFR_BIT];
|
||||
|
||||
/* Update some DRAM parameters before changing frequency */
|
||||
jz_update_dram_prev(cur_mclk, new_mclk);
|
||||
|
||||
/* update register to change the clocks.
|
||||
* align this code to a cache line.
|
||||
*/
|
||||
__asm__ __volatile__(
|
||||
".set noreorder\n\t"
|
||||
".align 5\n"
|
||||
"sw %1,0(%0)\n\t"
|
||||
"li %3,0\n\t"
|
||||
"1:\n\t"
|
||||
"bne %3,%2,1b\n\t"
|
||||
"addi %3, 1\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
".set reorder\n\t"
|
||||
:
|
||||
: "r" (CPM_CFCR), "r" (cfcr), "r" (wait), "r" (tmp));
|
||||
|
||||
/* Update some other DRAM parameters after changing frequency */
|
||||
jz_update_dram_post(cur_mclk, new_mclk);
|
||||
}
|
||||
|
||||
#ifdef CHANGE_PLL
|
||||
/* Maintain the LCD clock and pixel clock */
|
||||
static void jz_scale_lcd_divisors(struct dpm_regs *regs)
|
||||
{
|
||||
unsigned int new_pll, new_lcd_div, new_lcdpix_div;
|
||||
unsigned int cfcr;
|
||||
unsigned int tmp = 0, wait = PLL_WAIT_500NS;
|
||||
|
||||
if (!boot_config.lcd_clks_initialized) return;
|
||||
|
||||
new_pll = __cpm_get_pllout();
|
||||
new_lcd_div = new_pll / boot_config.lcd_clk;
|
||||
new_lcdpix_div = new_pll / boot_config.lcdpix_clk;
|
||||
|
||||
if (new_lcd_div < 1)
|
||||
new_lcd_div = 1;
|
||||
if (new_lcd_div > 16)
|
||||
new_lcd_div = 16;
|
||||
|
||||
if (new_lcdpix_div < 1)
|
||||
new_lcdpix_div = 1;
|
||||
if (new_lcdpix_div > 512)
|
||||
new_lcdpix_div = 512;
|
||||
|
||||
REG_CPM_CFCR2 = new_lcdpix_div - 1;
|
||||
|
||||
cfcr = REG_CPM_CFCR;
|
||||
cfcr &= ~CPM_CFCR_LFR_MASK;
|
||||
cfcr |= ((new_lcd_div - 1) << CPM_CFCR_LFR_BIT);
|
||||
cfcr |= CPM_CFCR_UPE; /* update immediately */
|
||||
|
||||
/* update register to change the clocks.
|
||||
* align this code to a cache line.
|
||||
*/
|
||||
__asm__ __volatile__(
|
||||
".set noreorder\n\t"
|
||||
".align 5\n"
|
||||
"sw %1,0(%0)\n\t"
|
||||
"li %3,0\n\t"
|
||||
"1:\n\t"
|
||||
"bne %3,%2,1b\n\t"
|
||||
"addi %3, 1\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
".set reorder\n\t"
|
||||
:
|
||||
: "r" (CPM_CFCR), "r" (cfcr), "r" (wait), "r" (tmp));
|
||||
}
|
||||
|
||||
static void jz_scale_pll(struct dpm_regs *regs)
|
||||
{
|
||||
unsigned int plcr1;
|
||||
unsigned int cur_mclk, new_mclk, new_pll;
|
||||
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
|
||||
int od[] = {1, 2, 2, 4};
|
||||
|
||||
plcr1 = REG_CPM_PLCR1;
|
||||
plcr1 &= ~(regs->plcr1_mask | CPM_PLCR1_PLL1S | CPM_PLCR1_PLL1EN | CPM_PLCR1_PLL1ST_MASK);
|
||||
regs->plcr1 &= ~CPM_PLCR1_PLL1EN;
|
||||
plcr1 |= (regs->plcr1 | 0xff);
|
||||
|
||||
/* Update some DRAM parameters before changing frequency */
|
||||
new_pll = JZ_EXTAL * ((plcr1>>23)+2) / ((((plcr1>>18)&0x1f)+2) * od[(plcr1>>16)&0x03]);
|
||||
cur_mclk = __cpm_get_mclk();
|
||||
new_mclk = new_pll / div[(REG_CPM_CFCR>>16) & 0xf];
|
||||
|
||||
/*
|
||||
* Update some SDRAM parameters
|
||||
*/
|
||||
jz_update_dram_prev(cur_mclk, new_mclk);
|
||||
|
||||
/*
|
||||
* Update PLL, align code to cache line.
|
||||
*/
|
||||
plcr1 |= CPM_PLCR1_PLL1EN;
|
||||
__asm__ __volatile__(
|
||||
".set noreorder\n\t"
|
||||
".align 5\n"
|
||||
"sw %1,0(%0)\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
".set reorder\n\t"
|
||||
:
|
||||
: "r" (CPM_PLCR1), "r" (plcr1));
|
||||
|
||||
/* Update some other DRAM parameters after changing frequency */
|
||||
jz_update_dram_post(cur_mclk, new_mclk);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void jz4730_transition(struct dpm_regs *regs)
|
||||
{
|
||||
/*
|
||||
* Get and save some boot-time conditions.
|
||||
*/
|
||||
jz_init_boot_config();
|
||||
|
||||
#ifdef CHANGE_PLL
|
||||
/*
|
||||
* Disable LCD before scaling pll.
|
||||
* LCD and LCD pixel clocks should not be changed even if the PLL
|
||||
* output frequency has been changed.
|
||||
*/
|
||||
REG_LCD_CTRL &= ~LCD_CTRL_ENA;
|
||||
#endif
|
||||
/*
|
||||
* Stop module clocks before scaling PLL
|
||||
*/
|
||||
__cpm_stop_eth();
|
||||
__cpm_stop_aic_pclk();
|
||||
__cpm_stop_aic_bitclk();
|
||||
|
||||
/* ... add more as necessary */
|
||||
|
||||
if (regs->pll_up_flag == PLL_GOES_UP) {
|
||||
/* the pll frequency is going up, so change dividors first */
|
||||
jz_scale_divisors(regs);
|
||||
#ifdef CHANGE_PLL
|
||||
jz_scale_pll(regs);
|
||||
#endif
|
||||
}
|
||||
else if (regs->pll_up_flag == PLL_GOES_DOWN) {
|
||||
/* the pll frequency is going down, so change pll first */
|
||||
#ifdef CHANGE_PLL
|
||||
jz_scale_pll(regs);
|
||||
#endif
|
||||
jz_scale_divisors(regs);
|
||||
}
|
||||
else {
|
||||
/* the pll frequency is unchanged, so change divisors only */
|
||||
jz_scale_divisors(regs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Restart module clocks before scaling PLL
|
||||
*/
|
||||
__cpm_start_eth();
|
||||
__cpm_start_aic_pclk();
|
||||
__cpm_start_aic_bitclk();
|
||||
|
||||
/* ... add more as necessary */
|
||||
|
||||
#ifdef CHANGE_PLL
|
||||
/* Scale the LCD divisors after scaling pll */
|
||||
if (regs->pll_up_flag != PLL_UNCHANGED) {
|
||||
jz_scale_lcd_divisors(regs);
|
||||
}
|
||||
|
||||
/* Enable LCD controller */
|
||||
REG_LCD_CTRL &= ~LCD_CTRL_DIS;
|
||||
REG_LCD_CTRL |= LCD_CTRL_ENA;
|
||||
#endif
|
||||
|
||||
/* Update system clocks */
|
||||
jz_update_clocks();
|
||||
}
|
||||
|
||||
extern unsigned int idle_times;
|
||||
static unsigned int jz4730_freq_get(unsigned int cpu)
|
||||
{
|
||||
return (__cpm_get_iclk() / 1000);
|
||||
}
|
||||
|
||||
static unsigned int index_to_divisor(unsigned int index, struct dpm_regs *regs)
|
||||
{
|
||||
int n2FR[33] = {
|
||||
0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0,
|
||||
7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
|
||||
9
|
||||
};
|
||||
int div[4] = {1, 2, 2, 2}; /* divisors of I:S:P:M */
|
||||
unsigned int div_of_cclk, new_freq, i;
|
||||
|
||||
regs->pll_up_flag = PLL_UNCHANGED;
|
||||
regs->cfcr_mask = CPM_CFCR_IFR_MASK | CPM_CFCR_SFR_MASK | CPM_CFCR_PFR_MASK | CPM_CFCR_MFR_MASK;
|
||||
|
||||
new_freq = jz4730_freq_table.table[index].frequency;
|
||||
|
||||
do {
|
||||
div_of_cclk = __cpm_get_pllout() / (1000 * new_freq);
|
||||
} while (div_of_cclk==0);
|
||||
|
||||
if(div_of_cclk == 1 || div_of_cclk == 2 || div_of_cclk == 4) {
|
||||
for(i = 1; i<4; i++) {
|
||||
div[i] = 3;
|
||||
}
|
||||
} else {
|
||||
for(i = 1; i<4; i++) {
|
||||
div[i] = 2;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i<4; i++) {
|
||||
div[i] *= div_of_cclk;
|
||||
}
|
||||
|
||||
dprintk("divisors of I:S:P:M = %d:%d:%d:%d\n", div[0], div[1], div[2], div[3]);
|
||||
|
||||
regs->cfcr = (n2FR[div[0]] << CPM_CFCR_IFR_BIT) |
|
||||
(n2FR[div[1]] << CPM_CFCR_SFR_BIT) |
|
||||
(n2FR[div[2]] << CPM_CFCR_PFR_BIT) |
|
||||
(n2FR[div[3]] << CPM_CFCR_MFR_BIT);
|
||||
|
||||
return div_of_cclk;
|
||||
}
|
||||
|
||||
static void jz4730_set_cpu_divider_index(unsigned int cpu, unsigned int index)
|
||||
{
|
||||
unsigned long divisor, old_divisor;
|
||||
struct cpufreq_freqs freqs;
|
||||
struct dpm_regs regs;
|
||||
|
||||
old_divisor = __cpm_get_pllout() / __cpm_get_iclk();
|
||||
divisor = index_to_divisor(index, ®s);
|
||||
|
||||
freqs.old = __cpm_get_iclk() / 1000;
|
||||
freqs.new = __cpm_get_pllout() / (1000 * divisor);
|
||||
freqs.cpu = cpu;
|
||||
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
|
||||
if (old_divisor != divisor)
|
||||
jz4730_transition(®s);
|
||||
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
}
|
||||
|
||||
static int jz4730_freq_target(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation)
|
||||
{
|
||||
unsigned int new_index = 0;
|
||||
|
||||
if (cpufreq_frequency_table_target(policy,
|
||||
&jz4730_freq_table.table[0],
|
||||
target_freq, relation, &new_index))
|
||||
return -EINVAL;
|
||||
|
||||
jz4730_set_cpu_divider_index(policy->cpu, new_index);
|
||||
|
||||
dprintk("new frequency is %d KHz (REG_CPM_CFCR:0x%x)\n", __cpm_get_iclk() / 1000, REG_CPM_CFCR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jz4730_freq_verify(struct cpufreq_policy *policy)
|
||||
{
|
||||
return cpufreq_frequency_table_verify(policy,
|
||||
&jz4730_freq_table.table[0]);
|
||||
}
|
||||
|
||||
static int __init jz4730_cpufreq_driver_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
|
||||
struct cpufreq_frequency_table *table = &jz4730_freq_table.table[0];
|
||||
unsigned int MAX_FREQ;
|
||||
|
||||
dprintk(KERN_INFO "Jz4730 cpufreq driver\n");
|
||||
|
||||
if (policy->cpu != 0)
|
||||
return -EINVAL;
|
||||
|
||||
policy->cur = MAX_FREQ = __cpm_get_iclk() / 1000; /* in kHz. Current and max frequency is determined by u-boot */
|
||||
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
|
||||
|
||||
policy->cpuinfo.min_freq = MAX_FREQ/8;
|
||||
policy->cpuinfo.max_freq = MAX_FREQ;
|
||||
policy->cpuinfo.transition_latency = 100000; /* in 10^(-9) s = nanoseconds */
|
||||
|
||||
table[0].index = 0;
|
||||
table[0].frequency = MAX_FREQ/8;
|
||||
table[1].index = 1;
|
||||
table[1].frequency = MAX_FREQ/6;
|
||||
table[2].index = 2;
|
||||
table[2].frequency = MAX_FREQ/4;
|
||||
table[3].index = 3;
|
||||
table[3].frequency = MAX_FREQ/3;
|
||||
table[4].index = 4;
|
||||
table[4].frequency = MAX_FREQ/2;
|
||||
table[5].index = 5;
|
||||
table[5].frequency = MAX_FREQ;
|
||||
table[6].index = 6;
|
||||
table[6].frequency = CPUFREQ_TABLE_END;
|
||||
|
||||
return cpufreq_frequency_table_cpuinfo(policy, table);
|
||||
}
|
||||
|
||||
static struct cpufreq_driver cpufreq_jz4730_driver = {
|
||||
// .flags = CPUFREQ_STICKY,
|
||||
.init = jz4730_cpufreq_driver_init,
|
||||
.verify = jz4730_freq_verify,
|
||||
.target = jz4730_freq_target,
|
||||
.get = jz4730_freq_get,
|
||||
.name = "jz4730",
|
||||
};
|
||||
|
||||
static int __init jz4730_cpufreq_init(void)
|
||||
{
|
||||
return cpufreq_register_driver(&cpufreq_jz4730_driver);
|
||||
}
|
||||
|
||||
static void __exit jz4730_cpufreq_exit(void)
|
||||
{
|
||||
cpufreq_unregister_driver(&cpufreq_jz4730_driver);
|
||||
}
|
||||
|
||||
module_init(jz4730_cpufreq_init);
|
||||
module_exit(jz4730_cpufreq_exit);
|
||||
|
||||
MODULE_AUTHOR("Regen <lhhuang@ingenic.cn>");
|
||||
MODULE_DESCRIPTION("cpufreq driver for Jz4730");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
509
target/linux/xburst/files-2.6.27/arch/mips/jz4730/dma.c
Normal file
509
target/linux/xburst/files-2.6.27/arch/mips/jz4730/dma.c
Normal file
@@ -0,0 +1,509 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4730/dma.c
|
||||
*
|
||||
* JZ4730 DMA PC-like APIs.
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/soundcard.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/*
|
||||
* A note on resource allocation:
|
||||
*
|
||||
* All drivers needing DMA channels, should allocate and release them
|
||||
* through the public routines `jz_request_dma()' and `jz_free_dma()'.
|
||||
*
|
||||
* In order to avoid problems, all processes should allocate resources in
|
||||
* the same sequence and release them in the reverse order.
|
||||
*
|
||||
* So, when allocating DMAs and IRQs, first allocate the DMA, then the IRQ.
|
||||
* When releasing them, first release the IRQ, then release the DMA. The
|
||||
* main reason for this order is that, if you are requesting the DMA buffer
|
||||
* done interrupt, you won't know the irq number until the DMA channel is
|
||||
* returned from jz_request_dma().
|
||||
*/
|
||||
|
||||
struct jz_dma_chan jz_dma_table[NUM_DMA] = {
|
||||
{dev_id:-1,},
|
||||
{dev_id:-1,},
|
||||
{dev_id:-1,},
|
||||
{dev_id:-1,},
|
||||
{dev_id:-1,},
|
||||
{dev_id:-1,},
|
||||
};
|
||||
|
||||
|
||||
// Device FIFO addresses and default DMA modes
|
||||
static const struct {
|
||||
unsigned int fifo_addr;
|
||||
unsigned int dma_mode;
|
||||
unsigned int dma_source;
|
||||
} dma_dev_table[NUM_DMA_DEV] = {
|
||||
{CPHYSADDR(UART0_BASE), DMA_8bit_TX_CONF|DMA_MODE_WRITE, DMAC_DRSR_RS_UART0OUT},
|
||||
{CPHYSADDR(UART0_BASE), DMA_8bit_RX_CONF|DMA_MODE_READ, DMAC_DRSR_RS_UART0IN},
|
||||
{CPHYSADDR(UART1_BASE), DMA_8bit_TX_CONF|DMA_MODE_WRITE, DMAC_DRSR_RS_UART1OUT},
|
||||
{CPHYSADDR(UART1_BASE), DMA_8bit_RX_CONF|DMA_MODE_READ, DMAC_DRSR_RS_UART1IN},
|
||||
{CPHYSADDR(UART2_BASE), DMA_8bit_TX_CONF|DMA_MODE_WRITE, DMAC_DRSR_RS_UART2OUT},
|
||||
{CPHYSADDR(UART2_BASE), DMA_8bit_RX_CONF|DMA_MODE_READ, DMAC_DRSR_RS_UART2IN},
|
||||
{CPHYSADDR(UART3_BASE), DMA_8bit_TX_CONF|DMA_MODE_WRITE, DMAC_DRSR_RS_UART3OUT},
|
||||
{CPHYSADDR(UART3_BASE), DMA_8bit_RX_CONF|DMA_MODE_READ, DMAC_DRSR_RS_UART3IN},
|
||||
{CPHYSADDR(SSI_DR), DMA_32bit_TX_CONF|DMA_MODE_WRITE, DMAC_DRSR_RS_SSIOUT},
|
||||
{CPHYSADDR(SSI_DR), DMA_32bit_RX_CONF|DMA_MODE_READ, DMAC_DRSR_RS_SSIIN},
|
||||
{CPHYSADDR(MSC_TXFIFO), DMA_32bit_TX_CONF|DMA_MODE_WRITE, DMAC_DRSR_RS_MSCOUT},
|
||||
{CPHYSADDR(MSC_RXFIFO), DMA_32bit_RX_CONF|DMA_MODE_READ, DMAC_DRSR_RS_MSCIN},
|
||||
{CPHYSADDR(AIC_DR), DMA_32bit_TX_CONF|DMA_MODE_WRITE, DMAC_DRSR_RS_AICOUT},
|
||||
{CPHYSADDR(AIC_DR), DMA_32bit_RX_CONF|DMA_MODE_READ, DMAC_DRSR_RS_AICIN},
|
||||
{0, DMA_AUTOINIT, 0},
|
||||
};
|
||||
|
||||
|
||||
int jz_dma_read_proc(char *buf, char **start, off_t fpos,
|
||||
int length, int *eof, void *data)
|
||||
{
|
||||
int i, len = 0;
|
||||
struct jz_dma_chan *chan;
|
||||
|
||||
for (i = 0; i < NUM_DMA; i++) {
|
||||
if ((chan = get_dma_chan(i)) != NULL) {
|
||||
len += sprintf(buf + len, "%2d: %s\n",
|
||||
i, chan->dev_str);
|
||||
}
|
||||
}
|
||||
|
||||
if (fpos >= len) {
|
||||
*start = buf;
|
||||
*eof = 1;
|
||||
return 0;
|
||||
}
|
||||
*start = buf + fpos;
|
||||
if ((len -= fpos) > length)
|
||||
return length;
|
||||
*eof = 1;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
void dump_jz_dma_channel(unsigned int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan;
|
||||
|
||||
if (dmanr > NUM_DMA)
|
||||
return;
|
||||
chan = &jz_dma_table[dmanr];
|
||||
|
||||
printk(KERN_INFO "DMA%d Register Dump:\n", dmanr);
|
||||
printk(KERN_INFO " DMACR= 0x%08x\n", REG_DMAC_DMACR);
|
||||
printk(KERN_INFO " DSAR = 0x%08x\n", REG_DMAC_DSAR(dmanr));
|
||||
printk(KERN_INFO " DDAR = 0x%08x\n", REG_DMAC_DDAR(dmanr));
|
||||
printk(KERN_INFO " DTCR = 0x%08x\n", REG_DMAC_DTCR(dmanr));
|
||||
printk(KERN_INFO " DRSR = 0x%08x\n", REG_DMAC_DRSR(dmanr));
|
||||
printk(KERN_INFO " DCCSR = 0x%08x\n", REG_DMAC_DCCSR(dmanr));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* jz_request_dma - dynamically allcate an idle DMA channel to return
|
||||
* @dev_id: the specified dma device id or DMA_ID_RAW_REQ
|
||||
* @dev_str: the specified dma device string name
|
||||
* @irqhandler: the irq handler, or NULL
|
||||
* @irqflags: the irq handler flags
|
||||
* @irq_dev_id: the irq handler device id for shared irq
|
||||
*
|
||||
* Finds a free channel, and binds the requested device to it.
|
||||
* Returns the allocated channel number, or negative on error.
|
||||
* Requests the DMA done IRQ if irqhandler != NULL.
|
||||
*
|
||||
*/
|
||||
int jz_request_dma(int dev_id, const char *dev_str,
|
||||
irqreturn_t (*irqhandler)(int, void *),
|
||||
unsigned long irqflags,
|
||||
void *irq_dev_id)
|
||||
{
|
||||
struct jz_dma_chan *chan;
|
||||
int i, ret;
|
||||
|
||||
if (dev_id < 0 || dev_id >= NUM_DMA_DEV)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < NUM_DMA; i++) {
|
||||
if (jz_dma_table[i].dev_id < 0)
|
||||
break;
|
||||
}
|
||||
if (i == NUM_DMA)
|
||||
return -ENODEV;
|
||||
|
||||
chan = &jz_dma_table[i];
|
||||
|
||||
if (irqhandler) {
|
||||
chan->irq = IRQ_DMA_0 + i; // see intc.h
|
||||
chan->irq_dev = irq_dev_id;
|
||||
if ((ret = request_irq(chan->irq, irqhandler, irqflags,
|
||||
dev_str, chan->irq_dev))) {
|
||||
chan->irq = 0;
|
||||
chan->irq_dev = NULL;
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
chan->irq = 0;
|
||||
chan->irq_dev = NULL;
|
||||
}
|
||||
|
||||
// fill it in
|
||||
chan->io = i;
|
||||
chan->dev_id = dev_id;
|
||||
chan->dev_str = dev_str;
|
||||
chan->fifo_addr = dma_dev_table[dev_id].fifo_addr;
|
||||
chan->mode = dma_dev_table[dev_id].dma_mode;
|
||||
chan->source = dma_dev_table[dev_id].dma_source;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void jz_free_dma(unsigned int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
if (!chan) {
|
||||
printk("Trying to free DMA%d\n", dmanr);
|
||||
return;
|
||||
}
|
||||
|
||||
disable_dma(dmanr);
|
||||
if (chan->irq)
|
||||
free_irq(chan->irq, chan->irq_dev);
|
||||
|
||||
chan->irq = 0;
|
||||
chan->irq_dev = NULL;
|
||||
chan->dev_id = -1;
|
||||
}
|
||||
|
||||
void jz_set_dma_dest_width(int dmanr, int nbit)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
if (!chan)
|
||||
return;
|
||||
chan->mode &= ~DMAC_DCCSR_DWDH_MASK;
|
||||
switch (nbit) {
|
||||
case 8:
|
||||
chan->mode |= DMAC_DCCSR_DWDH_8;
|
||||
break;
|
||||
case 16:
|
||||
chan->mode |= DMAC_DCCSR_DWDH_16;
|
||||
break;
|
||||
case 32:
|
||||
chan->mode |= DMAC_DCCSR_DWDH_32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void jz_set_dma_src_width(int dmanr, int nbit)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
if (!chan)
|
||||
return;
|
||||
chan->mode &= ~DMAC_DCCSR_SWDH_MASK;
|
||||
switch (nbit) {
|
||||
case 8:
|
||||
chan->mode |= DMAC_DCCSR_SWDH_8;
|
||||
break;
|
||||
case 16:
|
||||
chan->mode |= DMAC_DCCSR_SWDH_16;
|
||||
break;
|
||||
case 32:
|
||||
chan->mode |= DMAC_DCCSR_SWDH_32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void jz_set_dma_block_size(int dmanr, int nbyte)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
if (!chan)
|
||||
return;
|
||||
chan->mode &= ~DMAC_DCCSR_DS_MASK;
|
||||
switch (nbyte) {
|
||||
case 1:
|
||||
chan->mode |= DMAC_DCCSR_DS_8b;
|
||||
break;
|
||||
case 2:
|
||||
chan->mode |= DMAC_DCCSR_DS_16b;
|
||||
break;
|
||||
case 4:
|
||||
chan->mode |= DMAC_DCCSR_DS_32b;
|
||||
break;
|
||||
case 16:
|
||||
chan->mode |= DMAC_DCCSR_DS_16B;
|
||||
break;
|
||||
case 32:
|
||||
chan->mode |= DMAC_DCCSR_DS_32B;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* jz_set_dma_mode - do the raw settings for the specified DMA channel
|
||||
* @dmanr: the specified DMA channel
|
||||
* @mode: dma operate mode, DMA_MODE_READ or DMA_MODE_WRITE
|
||||
* @dma_mode: dma raw mode
|
||||
* @dma_source: dma raw request source
|
||||
* @fifo_addr: dma raw device fifo address
|
||||
*
|
||||
* Ensure call jz_request_dma(DMA_ID_RAW_REQ, ...) first, then call
|
||||
* jz_set_dma_mode() rather than set_dma_mode() if you work with
|
||||
* and external request dma device.
|
||||
*
|
||||
* NOTE: Don not dynamically allocate dma channel if one external request
|
||||
* dma device will occupy this channel.
|
||||
*/
|
||||
int jz_set_dma_mode(unsigned int dmanr, unsigned int mode,
|
||||
unsigned int dma_mode, unsigned int dma_source,
|
||||
unsigned int fifo_addr)
|
||||
{
|
||||
int dev_id, i;
|
||||
struct jz_dma_chan *chan;
|
||||
|
||||
if (dmanr > NUM_DMA)
|
||||
return -ENODEV;
|
||||
for (i = 0; i < NUM_DMA; i++) {
|
||||
if (jz_dma_table[i].dev_id < 0)
|
||||
break;
|
||||
}
|
||||
if (i == NUM_DMA)
|
||||
return -ENODEV;
|
||||
|
||||
chan = &jz_dma_table[dmanr];
|
||||
dev_id = chan->dev_id;
|
||||
if (dev_id > 0) {
|
||||
printk(KERN_DEBUG "%s sets the allocated DMA channel %d!\n",
|
||||
__FUNCTION__, dmanr);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* clone it from the dynamically allocated. */
|
||||
if (i != dmanr) {
|
||||
chan->irq = jz_dma_table[i].irq;
|
||||
chan->irq_dev = jz_dma_table[i].irq_dev;
|
||||
chan->dev_str = jz_dma_table[i].dev_str;
|
||||
jz_dma_table[i].irq = 0;
|
||||
jz_dma_table[i].irq_dev = NULL;
|
||||
jz_dma_table[i].dev_id = -1;
|
||||
}
|
||||
chan->dev_id = DMA_ID_RAW_SET;
|
||||
chan->io = dmanr;
|
||||
chan->fifo_addr = fifo_addr;
|
||||
chan->mode = dma_mode;
|
||||
chan->source = dma_source;
|
||||
|
||||
set_dma_mode(dmanr, dma_mode);
|
||||
|
||||
return dmanr;
|
||||
}
|
||||
|
||||
void enable_dma(unsigned int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
REG_DMAC_DCCSR(chan->io) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TC | DMAC_DCCSR_AR);
|
||||
__dmac_enable_channel(dmanr);
|
||||
if (chan->irq)
|
||||
__dmac_channel_enable_irq(dmanr);
|
||||
}
|
||||
|
||||
#define DMA_DISABLE_POLL 0x5000
|
||||
|
||||
void disable_dma(unsigned int dmanr)
|
||||
{
|
||||
int i;
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
if (!chan)
|
||||
return;
|
||||
if (!__dmac_channel_enabled(dmanr))
|
||||
return;
|
||||
|
||||
for (i = 0; i < DMA_DISABLE_POLL; i++)
|
||||
if (__dmac_channel_transmit_end_detected(dmanr))
|
||||
break;
|
||||
#if 0
|
||||
if (i == DMA_DISABLE_POLL)
|
||||
printk(KERN_INFO "disable_dma: poll expired!\n");
|
||||
#endif
|
||||
|
||||
__dmac_disable_channel(dmanr);
|
||||
if (chan->irq)
|
||||
__dmac_channel_disable_irq(dmanr);
|
||||
}
|
||||
|
||||
/* note: DMA_MODE_MASK is simulated by sw, DCCSR_MODE_MASK mask hw bits */
|
||||
void set_dma_mode(unsigned int dmanr, unsigned int mode)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
if (!chan)
|
||||
return;
|
||||
mode &= ~(DMAC_DCCSR_TC | DMAC_DCCSR_AR);
|
||||
chan->mode |= mode & ~(DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM | DMAC_DCCSR_DAM);
|
||||
mode &= DMA_MODE_MASK;
|
||||
if (mode == DMA_MODE_READ) {
|
||||
chan->mode |= DMAC_DCCSR_DAM;
|
||||
chan->mode &= ~DMAC_DCCSR_SAM;
|
||||
} else if (mode == DMA_MODE_WRITE) {
|
||||
chan->mode |= DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM;
|
||||
chan->mode &= ~DMAC_DCCSR_DAM;
|
||||
} else {
|
||||
printk(KERN_DEBUG "set_dma_mode() support DMA_MODE_READ or DMA_MODE_WRITE!\n");
|
||||
}
|
||||
REG_DMAC_DCCSR(chan->io) = chan->mode & ~DMA_MODE_MASK;
|
||||
REG_DMAC_DRSR(chan->io) = chan->source;
|
||||
}
|
||||
|
||||
void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
switch (audio_fmt) {
|
||||
case AFMT_U8:
|
||||
/* SNDRV_PCM_FORMAT_S8 burst mode : 32BIT */
|
||||
break;
|
||||
case AFMT_S16_LE:
|
||||
/* SNDRV_PCM_FORMAT_S16_LE burst mode : 16BYTE */
|
||||
if (mode == DMA_MODE_READ) {
|
||||
mode &= ~(DMAC_DCCSR_TC | DMAC_DCCSR_AR);
|
||||
chan->mode = DMA_AIC_32_16BYTE_RX_CMD | DMA_MODE_READ;
|
||||
chan->mode |= mode & ~(DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM | DMAC_DCCSR_DAM);
|
||||
mode &= DMA_MODE_MASK;
|
||||
chan->mode |= DMAC_DCCSR_DAM;
|
||||
chan->mode &= ~DMAC_DCCSR_SAM;
|
||||
} else if (mode == DMA_MODE_WRITE) {
|
||||
mode &= ~(DMAC_DCCSR_TC | DMAC_DCCSR_AR);
|
||||
chan->mode = DMA_AIC_32_16BYTE_TX_CMD | DMA_MODE_WRITE;
|
||||
chan->mode |= mode & ~(DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM |DMAC_DCCSR_DAM);
|
||||
mode &= DMA_MODE_MASK;
|
||||
chan->mode |= DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM;
|
||||
chan->mode &= ~DMAC_DCCSR_DAM;
|
||||
} else
|
||||
printk("jz_set_oss_dma() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n");
|
||||
|
||||
REG_DMAC_DCCSR(chan->io) = chan->mode & ~DMA_MODE_MASK;
|
||||
REG_DMAC_DRSR(chan->io) = chan->source;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
switch (audio_fmt) {
|
||||
case 8:
|
||||
/* SNDRV_PCM_FORMAT_S8 burst mode : 32BIT */
|
||||
break;
|
||||
case 16:
|
||||
/* SNDRV_PCM_FORMAT_S16_LE burst mode : 16BYTE */
|
||||
if (mode == DMA_MODE_READ) {
|
||||
mode &= ~(DMAC_DCCSR_TC | DMAC_DCCSR_AR);
|
||||
chan->mode = DMA_AIC_16BYTE_RX_CMD | DMA_MODE_READ;
|
||||
chan->mode |= mode & ~(DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM | DMAC_DCCSR_DAM);
|
||||
mode &= DMA_MODE_MASK;
|
||||
chan->mode |= DMAC_DCCSR_DAM;
|
||||
chan->mode &= ~DMAC_DCCSR_SAM;
|
||||
} else if (mode == DMA_MODE_WRITE) {
|
||||
mode &= ~(DMAC_DCCSR_TC | DMAC_DCCSR_AR);
|
||||
chan->mode = DMA_AIC_16BYTE_TX_CMD | DMA_MODE_WRITE;
|
||||
chan->mode |= mode & ~(DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM | DMAC_DCCSR_DAM);
|
||||
mode &= DMA_MODE_MASK;
|
||||
chan->mode |= DMAC_DCCSR_SAM | DMAC_DCCSR_EACKM;
|
||||
chan->mode &= ~DMAC_DCCSR_DAM;
|
||||
} else
|
||||
printk("jz_set_alsa_dma() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n");
|
||||
|
||||
REG_DMAC_DCCSR(chan->io) = chan->mode & ~DMA_MODE_MASK;
|
||||
REG_DMAC_DRSR(chan->io) = chan->source;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void set_dma_addr(unsigned int dmanr, unsigned int a)
|
||||
{
|
||||
unsigned int mode;
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
if (!chan)
|
||||
return;
|
||||
mode = chan->mode & DMA_MODE_MASK;
|
||||
if (mode == DMA_MODE_READ) {
|
||||
REG_DMAC_DSAR(chan->io) = chan->fifo_addr;
|
||||
REG_DMAC_DDAR(chan->io) = a;
|
||||
} else if (mode == DMA_MODE_WRITE) {
|
||||
REG_DMAC_DSAR(chan->io) = a;
|
||||
REG_DMAC_DDAR(chan->io) = chan->fifo_addr;
|
||||
} else
|
||||
printk(KERN_DEBUG "Driver should call set_dma_mode() ahead set_dma_addr()!\n");
|
||||
}
|
||||
|
||||
void set_dma_count(unsigned int dmanr, unsigned int count)
|
||||
{
|
||||
unsigned int mode;
|
||||
int dma_ds[] = {4, 1, 2, 16, 32};
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
if (!chan)
|
||||
return;
|
||||
mode = (chan->mode & DMAC_DCCSR_DS_MASK) >> DMAC_DCCSR_DS_BIT;
|
||||
count = count / dma_ds[mode];
|
||||
REG_DMAC_DTCR(chan->io) = count;
|
||||
}
|
||||
|
||||
int get_dma_residue(unsigned int dmanr)
|
||||
{
|
||||
int count;
|
||||
unsigned int mode;
|
||||
int dma_ds[] = {4, 1, 2, 16, 32};
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
if (!chan)
|
||||
return 0;
|
||||
|
||||
mode = (chan->mode & DMAC_DCCSR_DS_MASK) >> DMAC_DCCSR_DS_BIT;
|
||||
count = REG_DMAC_DTCR(chan->io);
|
||||
count = count * dma_ds[mode];
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(jz_dma_table);
|
||||
EXPORT_SYMBOL(jz_request_dma);
|
||||
EXPORT_SYMBOL(jz_free_dma);
|
||||
EXPORT_SYMBOL(jz_set_dma_src_width);
|
||||
EXPORT_SYMBOL(jz_set_dma_dest_width);
|
||||
EXPORT_SYMBOL(jz_set_dma_block_size);
|
||||
EXPORT_SYMBOL(jz_set_dma_mode);
|
||||
EXPORT_SYMBOL(set_dma_mode);
|
||||
EXPORT_SYMBOL(jz_set_oss_dma);
|
||||
EXPORT_SYMBOL(jz_set_alsa_dma);
|
||||
EXPORT_SYMBOL(set_dma_addr);
|
||||
EXPORT_SYMBOL(set_dma_count);
|
||||
EXPORT_SYMBOL(get_dma_residue);
|
||||
EXPORT_SYMBOL(enable_dma);
|
||||
EXPORT_SYMBOL(disable_dma);
|
||||
EXPORT_SYMBOL(dump_jz_dma_channel);
|
||||
214
target/linux/xburst/files-2.6.27/arch/mips/jz4730/i2c.c
Normal file
214
target/linux/xburst/files-2.6.27/arch/mips/jz4730/i2c.c
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4730/i2c.c
|
||||
*
|
||||
* JZ4730 I2C APIs.
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* 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/types.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/addrspace.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/* I2C protocol */
|
||||
#define I2C_READ 1
|
||||
#define I2C_WRITE 0
|
||||
|
||||
#define TIMEOUT 1000
|
||||
|
||||
/*
|
||||
* I2C bus protocol basic routines
|
||||
*/
|
||||
static int i2c_put_data(unsigned char data)
|
||||
{
|
||||
unsigned int timeout = TIMEOUT * 10;
|
||||
|
||||
__i2c_write(data);
|
||||
__i2c_set_drf();
|
||||
while (__i2c_check_drf() != 0);
|
||||
while (!__i2c_transmit_ended());
|
||||
while (!__i2c_received_ack() && timeout)
|
||||
timeout--;
|
||||
|
||||
if (timeout)
|
||||
return 0;
|
||||
else
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int i2c_get_data(unsigned char *data, int ack)
|
||||
{
|
||||
int timeout = TIMEOUT*10;
|
||||
|
||||
if (!ack)
|
||||
__i2c_send_nack();
|
||||
else
|
||||
__i2c_send_ack();
|
||||
|
||||
while (__i2c_check_drf() == 0 && timeout)
|
||||
timeout--;
|
||||
|
||||
if (timeout) {
|
||||
if (!ack)
|
||||
__i2c_send_stop();
|
||||
*data = __i2c_read();
|
||||
__i2c_clear_drf();
|
||||
return 0;
|
||||
} else
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/*
|
||||
* I2C interface
|
||||
*/
|
||||
void i2c_open(void)
|
||||
{
|
||||
__i2c_set_clk(jz_clocks.devclk, 10000); /* default 10 KHz */
|
||||
__i2c_enable();
|
||||
}
|
||||
|
||||
void i2c_close(void)
|
||||
{
|
||||
udelay(300); /* wait for STOP goes over. */
|
||||
__i2c_disable();
|
||||
}
|
||||
|
||||
void i2c_setclk(unsigned int i2cclk)
|
||||
{
|
||||
__i2c_set_clk(jz_clocks.devclk, i2cclk);
|
||||
}
|
||||
|
||||
int i2c_lseek(unsigned char device, unsigned char offset)
|
||||
{
|
||||
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
|
||||
goto device_err;
|
||||
if (i2c_put_data(offset) < 0)
|
||||
goto address_err;
|
||||
return 0;
|
||||
device_err:
|
||||
printk(KERN_DEBUG "No I2C device (0x%02x) installed.\n", device);
|
||||
__i2c_send_stop();
|
||||
return -ENODEV;
|
||||
address_err:
|
||||
printk(KERN_DEBUG "No I2C device (0x%02x) response.\n", device);
|
||||
__i2c_send_stop();
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
int i2c_read(unsigned char device, unsigned char *buf,
|
||||
unsigned char address, int count)
|
||||
{
|
||||
int cnt = count;
|
||||
int timeout = 5;
|
||||
|
||||
L_try_again:
|
||||
|
||||
if (timeout < 0)
|
||||
goto L_timeout;
|
||||
|
||||
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
|
||||
goto device_werr;
|
||||
if (i2c_put_data(address) < 0)
|
||||
goto address_err;
|
||||
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_READ ) < 0)
|
||||
goto device_rerr;
|
||||
__i2c_send_ack(); /* Master sends ACK for continue reading */
|
||||
while (cnt) {
|
||||
if (cnt == 1) {
|
||||
if (i2c_get_data(buf, 0) < 0)
|
||||
break;
|
||||
} else {
|
||||
if (i2c_get_data(buf, 1) < 0)
|
||||
break;
|
||||
}
|
||||
cnt--;
|
||||
buf++;
|
||||
}
|
||||
|
||||
__i2c_send_stop();
|
||||
return count - cnt;
|
||||
device_rerr:
|
||||
device_werr:
|
||||
address_err:
|
||||
timeout --;
|
||||
__i2c_send_stop();
|
||||
goto L_try_again;
|
||||
|
||||
L_timeout:
|
||||
__i2c_send_stop();
|
||||
printk("Read I2C device 0x%2x failed.\n", device);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int i2c_write(unsigned char device, unsigned char *buf,
|
||||
unsigned char address, int count)
|
||||
{
|
||||
int cnt = count;
|
||||
int cnt_in_pg;
|
||||
int timeout = 5;
|
||||
unsigned char *tmpbuf;
|
||||
unsigned char tmpaddr;
|
||||
|
||||
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
|
||||
|
||||
W_try_again:
|
||||
if (timeout < 0)
|
||||
goto W_timeout;
|
||||
|
||||
cnt = count;
|
||||
tmpbuf = (unsigned char *)buf;
|
||||
tmpaddr = address;
|
||||
|
||||
start_write_page:
|
||||
cnt_in_pg = 0;
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
|
||||
goto device_err;
|
||||
if (i2c_put_data(tmpaddr) < 0)
|
||||
goto address_err;
|
||||
while (cnt) {
|
||||
if (++cnt_in_pg > 8) {
|
||||
__i2c_send_stop();
|
||||
mdelay(1);
|
||||
tmpaddr += 8;
|
||||
goto start_write_page;
|
||||
}
|
||||
if (i2c_put_data(*tmpbuf) < 0)
|
||||
break;
|
||||
cnt--;
|
||||
tmpbuf++;
|
||||
}
|
||||
__i2c_send_stop();
|
||||
return count - cnt;
|
||||
device_err:
|
||||
address_err:
|
||||
timeout--;
|
||||
__i2c_send_stop();
|
||||
goto W_try_again;
|
||||
|
||||
W_timeout:
|
||||
printk(KERN_DEBUG "Write I2C device 0x%2x failed.\n", device);
|
||||
__i2c_send_stop();
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(i2c_open);
|
||||
EXPORT_SYMBOL(i2c_close);
|
||||
EXPORT_SYMBOL(i2c_setclk);
|
||||
EXPORT_SYMBOL(i2c_read);
|
||||
EXPORT_SYMBOL(i2c_write);
|
||||
266
target/linux/xburst/files-2.6.27/arch/mips/jz4730/irq.c
Normal file
266
target/linux/xburst/files-2.6.27/arch/mips/jz4730/irq.c
Normal file
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4730/irq.c
|
||||
*
|
||||
* JZ4730 interrupt routines.
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* 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/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/timex.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/*
|
||||
* INTC irq type
|
||||
*/
|
||||
|
||||
static void enable_intc_irq(unsigned int irq)
|
||||
{
|
||||
__intc_unmask_irq(irq);
|
||||
}
|
||||
|
||||
static void disable_intc_irq(unsigned int irq)
|
||||
{
|
||||
__intc_mask_irq(irq);
|
||||
}
|
||||
|
||||
static void mask_and_ack_intc_irq(unsigned int irq)
|
||||
{
|
||||
__intc_mask_irq(irq);
|
||||
__intc_ack_irq(irq);
|
||||
}
|
||||
|
||||
static void end_intc_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
|
||||
enable_intc_irq(irq);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int startup_intc_irq(unsigned int irq)
|
||||
{
|
||||
enable_intc_irq(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void shutdown_intc_irq(unsigned int irq)
|
||||
{
|
||||
disable_intc_irq(irq);
|
||||
}
|
||||
|
||||
static struct irq_chip intc_irq_type = {
|
||||
.typename = "INTC",
|
||||
.startup = startup_intc_irq,
|
||||
.shutdown = shutdown_intc_irq,
|
||||
.enable = enable_intc_irq,
|
||||
.disable = disable_intc_irq,
|
||||
.ack = mask_and_ack_intc_irq,
|
||||
.end = end_intc_irq,
|
||||
};
|
||||
|
||||
/*
|
||||
* GPIO irq type
|
||||
*/
|
||||
|
||||
static void enable_gpio_irq(unsigned int irq)
|
||||
{
|
||||
unsigned int intc_irq;
|
||||
|
||||
if (irq < (IRQ_GPIO_0 + 32)) {
|
||||
intc_irq = IRQ_GPIO0;
|
||||
}
|
||||
else if (irq < (IRQ_GPIO_0 + 64)) {
|
||||
intc_irq = IRQ_GPIO1;
|
||||
}
|
||||
else if (irq < (IRQ_GPIO_0 + 96)) {
|
||||
intc_irq = IRQ_GPIO2;
|
||||
}
|
||||
else {
|
||||
intc_irq = IRQ_GPIO3;
|
||||
}
|
||||
|
||||
enable_intc_irq(intc_irq);
|
||||
__gpio_unmask_irq(irq - IRQ_GPIO_0);
|
||||
}
|
||||
|
||||
static void disable_gpio_irq(unsigned int irq)
|
||||
{
|
||||
__gpio_mask_irq(irq - IRQ_GPIO_0);
|
||||
}
|
||||
|
||||
static void mask_and_ack_gpio_irq(unsigned int irq)
|
||||
{
|
||||
__gpio_mask_irq(irq - IRQ_GPIO_0);
|
||||
__gpio_ack_irq(irq - IRQ_GPIO_0);
|
||||
}
|
||||
|
||||
static void end_gpio_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
|
||||
enable_gpio_irq(irq);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int startup_gpio_irq(unsigned int irq)
|
||||
{
|
||||
enable_gpio_irq(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void shutdown_gpio_irq(unsigned int irq)
|
||||
{
|
||||
disable_gpio_irq(irq);
|
||||
}
|
||||
|
||||
static struct irq_chip gpio_irq_type = {
|
||||
.typename = "GPIO",
|
||||
.startup = startup_gpio_irq,
|
||||
.shutdown = shutdown_gpio_irq,
|
||||
.enable = enable_gpio_irq,
|
||||
.disable = disable_gpio_irq,
|
||||
.ack = mask_and_ack_gpio_irq,
|
||||
.end = end_gpio_irq,
|
||||
};
|
||||
|
||||
/*
|
||||
* DMA irq type
|
||||
*/
|
||||
|
||||
static void enable_dma_irq(unsigned int irq)
|
||||
{
|
||||
__intc_unmask_irq(IRQ_DMAC);
|
||||
__dmac_channel_enable_irq(irq - IRQ_DMA_0);
|
||||
}
|
||||
|
||||
static void disable_dma_irq(unsigned int irq)
|
||||
{
|
||||
__dmac_channel_disable_irq(irq - IRQ_DMA_0);
|
||||
}
|
||||
|
||||
static void mask_and_ack_dma_irq(unsigned int irq)
|
||||
{
|
||||
__intc_ack_irq(IRQ_DMAC);
|
||||
__dmac_channel_disable_irq(irq - IRQ_DMA_0);
|
||||
}
|
||||
|
||||
static void end_dma_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
|
||||
enable_dma_irq(irq);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int startup_dma_irq(unsigned int irq)
|
||||
{
|
||||
enable_dma_irq(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void shutdown_dma_irq(unsigned int irq)
|
||||
{
|
||||
disable_dma_irq(irq);
|
||||
}
|
||||
|
||||
static struct irq_chip dma_irq_type = {
|
||||
.typename = "DMA",
|
||||
.startup = startup_dma_irq,
|
||||
.shutdown = shutdown_dma_irq,
|
||||
.enable = enable_dma_irq,
|
||||
.disable = disable_dma_irq,
|
||||
.ack = mask_and_ack_dma_irq,
|
||||
.end = end_dma_irq,
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void __init arch_init_irq(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
clear_c0_status(0xff04); /* clear ERL */
|
||||
set_c0_status(0x0400); /* set IP2 */
|
||||
|
||||
/* Set up INTC irq
|
||||
*/
|
||||
for (i = 0; i < 32; i++) {
|
||||
disable_intc_irq(i);
|
||||
irq_desc[i].chip = &intc_irq_type;
|
||||
}
|
||||
|
||||
/* Set up DMAC irq
|
||||
*/
|
||||
for (i = 0; i < NUM_DMA; i++) {
|
||||
disable_dma_irq(IRQ_DMA_0 + i);
|
||||
irq_desc[IRQ_DMA_0 + i].chip = &dma_irq_type;
|
||||
}
|
||||
|
||||
/* Set up GPIO irq
|
||||
*/
|
||||
for (i = 0; i < NUM_GPIO; i++) {
|
||||
disable_gpio_irq(IRQ_GPIO_0 + i);
|
||||
irq_desc[IRQ_GPIO_0 + i].chip = &gpio_irq_type;
|
||||
}
|
||||
}
|
||||
|
||||
static int plat_real_irq(int irq)
|
||||
{
|
||||
switch (irq) {
|
||||
case IRQ_GPIO0:
|
||||
irq = __gpio_group_irq(0) + IRQ_GPIO_0;
|
||||
break;
|
||||
case IRQ_GPIO1:
|
||||
irq = __gpio_group_irq(1) + IRQ_GPIO_0 + 32;
|
||||
break;
|
||||
case IRQ_GPIO2:
|
||||
irq = __gpio_group_irq(2) + IRQ_GPIO_0 + 64;
|
||||
break;
|
||||
case IRQ_GPIO3:
|
||||
irq = __gpio_group_irq(3) + IRQ_GPIO_0 + 96;
|
||||
break;
|
||||
case IRQ_DMAC:
|
||||
irq = __dmac_get_irq() + IRQ_DMA_0;
|
||||
break;
|
||||
}
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
asmlinkage void plat_irq_dispatch(void)
|
||||
{
|
||||
int irq = 0;
|
||||
static unsigned long intc_ipr = 0;
|
||||
|
||||
intc_ipr |= REG_INTC_IPR;
|
||||
|
||||
if (!intc_ipr) return;
|
||||
|
||||
irq = ffs(intc_ipr) - 1;
|
||||
intc_ipr &= ~(1<<irq);
|
||||
|
||||
irq = plat_real_irq(irq);
|
||||
|
||||
do_IRQ(irq);
|
||||
}
|
||||
140
target/linux/xburst/files-2.6.27/arch/mips/jz4730/platform.c
Normal file
140
target/linux/xburst/files-2.6.27/arch/mips/jz4730/platform.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Platform device support for Jz4730 SoC.
|
||||
*
|
||||
* Copyright 2007, Peter <jlwei@ingenic.cn>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/resource.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/* OHCI (USB full speed host controller) */
|
||||
static struct resource jz_usb_ohci_resources[] = {
|
||||
[0] = {
|
||||
.start = CPHYSADDR(UHC_BASE), // phys addr for ioremap
|
||||
.end = CPHYSADDR(UHC_BASE) + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_UHC,
|
||||
.end = IRQ_UHC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
/* The dmamask must be set for OHCI to work */
|
||||
static u64 ohci_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device jz_usb_ohci_device = {
|
||||
.name = "jz-ohci",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &ohci_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz_usb_ohci_resources),
|
||||
.resource = jz_usb_ohci_resources,
|
||||
};
|
||||
|
||||
/*** LCD controller ***/
|
||||
static struct resource jz_lcd_resources[] = {
|
||||
[0] = {
|
||||
.start = CPHYSADDR(LCD_BASE),
|
||||
.end = CPHYSADDR(LCD_BASE) + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_LCD,
|
||||
.end = IRQ_LCD,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
||||
static u64 jz_lcd_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device jz_lcd_device = {
|
||||
.name = "jz-lcd",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &jz_lcd_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz_lcd_resources),
|
||||
.resource = jz_lcd_resources,
|
||||
};
|
||||
|
||||
/* UDC (USB gadget controller) */
|
||||
static struct resource jz_usb_gdt_resources[] = {
|
||||
[0] = {
|
||||
.start = CPHYSADDR(UDC_BASE),
|
||||
.end = CPHYSADDR(UDC_BASE) + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_UDC,
|
||||
.end = IRQ_UDC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static u64 udc_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device jz_usb_gdt_device = {
|
||||
.name = "jz-udc",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &udc_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz_usb_gdt_resources),
|
||||
.resource = jz_usb_gdt_resources,
|
||||
};
|
||||
|
||||
/** MMC/SD controller **/
|
||||
static struct resource jz_mmc_resources[] = {
|
||||
[0] = {
|
||||
.start = CPHYSADDR(MSC_BASE),
|
||||
.end = CPHYSADDR(MSC_BASE) + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_MSC,
|
||||
.end = IRQ_MSC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
||||
static u64 jz_mmc_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device jz_mmc_device = {
|
||||
.name = "jz-mmc",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &jz_mmc_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz_mmc_resources),
|
||||
.resource = jz_mmc_resources,
|
||||
};
|
||||
|
||||
/* All */
|
||||
static struct platform_device *jz_platform_devices[] __initdata = {
|
||||
&jz_usb_ohci_device,
|
||||
&jz_lcd_device,
|
||||
&jz_usb_gdt_device,
|
||||
&jz_mmc_device,
|
||||
};
|
||||
|
||||
static int __init jz_platform_init(void)
|
||||
{
|
||||
return platform_add_devices(jz_platform_devices, ARRAY_SIZE(jz_platform_devices));
|
||||
}
|
||||
|
||||
arch_initcall(jz_platform_init);
|
||||
1098
target/linux/xburst/files-2.6.27/arch/mips/jz4730/pm.c
Normal file
1098
target/linux/xburst/files-2.6.27/arch/mips/jz4730/pm.c
Normal file
File diff suppressed because it is too large
Load Diff
292
target/linux/xburst/files-2.6.27/arch/mips/jz4730/proc.c
Normal file
292
target/linux/xburst/files-2.6.27/arch/mips/jz4730/proc.c
Normal file
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4730/proc.c
|
||||
*
|
||||
* /proc/jz/ procfs for on-chip peripherals.
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* 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/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/proc_fs.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
struct proc_dir_entry *proc_jz_root;
|
||||
|
||||
/*
|
||||
* EMC Module
|
||||
*/
|
||||
static int emc_read_proc (char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
len += sprintf (page+len, "BCR: 0x%08x\n", REG_EMC_BCR);
|
||||
len += sprintf (page+len, "SMCR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SMCR0, REG_EMC_SMCR1, REG_EMC_SMCR2, REG_EMC_SMCR3, REG_EMC_SMCR4, REG_EMC_SMCR5);
|
||||
len += sprintf (page+len, "SACR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SACR0, REG_EMC_SACR1, REG_EMC_SACR2, REG_EMC_SACR3, REG_EMC_SACR4, REG_EMC_SACR5);
|
||||
len += sprintf (page+len, "DMCR: 0x%08x\n", REG_EMC_DMCR);
|
||||
len += sprintf (page+len, "RTCSR: 0x%04x\n", REG_EMC_RTCSR);
|
||||
len += sprintf (page+len, "RTCOR: 0x%04x\n", REG_EMC_RTCOR);
|
||||
len += sprintf (page+len, "DMAR(0-1): 0x%08x 0x%08x\n", REG_EMC_DMAR1, REG_EMC_DMAR2);
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Power Manager Module
|
||||
*/
|
||||
static int pmc_read_proc (char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
unsigned long lpcr = REG_CPM_LPCR;
|
||||
unsigned long mscr = REG_CPM_MSCR;
|
||||
|
||||
len += sprintf (page+len, "LPCR : 0x%08lx\n", lpcr);
|
||||
len += sprintf (page+len, "Low Power Mode : %s\n",
|
||||
((lpcr & CPM_LPCR_LPM_MASK) == (CPM_LPCR_LPM_IDLE)) ?
|
||||
"idle" : (((lpcr & CPM_LPCR_LPM_MASK) == (CPM_LPCR_LPM_SLEEP)) ? "sleep" : "hibernate"));
|
||||
len += sprintf (page+len, "Doze Mode : %s\n",
|
||||
(lpcr & CPM_LPCR_DOZE) ? "on" : "off");
|
||||
if (lpcr & CPM_LPCR_DOZE)
|
||||
len += sprintf (page+len, " duty : %d\n", (int)((lpcr & CPM_LPCR_DUTY_MASK) >> CPM_LPCR_DUTY_BIT));
|
||||
len += sprintf (page+len, "CKO1 : %s\n",
|
||||
(REG_CPM_CFCR & CPM_CFCR_CKOEN1) ? "enable" : "disable");
|
||||
len += sprintf (page+len, "UART0 : %s\n",
|
||||
(mscr & CPM_MSCR_MSTP_UART0) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "UART1 : %s\n",
|
||||
(mscr & CPM_MSCR_MSTP_UART1) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "UART2 : %s\n",
|
||||
(mscr & CPM_MSCR_MSTP_UART2) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "UART3 : %s\n",
|
||||
(mscr & CPM_MSCR_MSTP_UART3) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "OST : %s\n",
|
||||
(mscr & CPM_MSCR_MSTP_OST) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "DMAC : %s\n",
|
||||
(mscr & CPM_MSCR_MSTP_DMAC) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "ETH : %s\n",
|
||||
(mscr & CPM_MSCR_MSTP_ETH) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "UHC/UDC : %s\n",
|
||||
(mscr & CPM_MSCR_MSTP_UHC) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "PWM0 : %s\n",
|
||||
(mscr & CPM_MSCR_MSTP_PWM0) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "PWM1 : %s\n",
|
||||
(mscr & CPM_MSCR_MSTP_PWM1) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "I2C : %s\n",
|
||||
(mscr & CPM_MSCR_MSTP_I2C) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "SSI : %s\n",
|
||||
(mscr & CPM_MSCR_MSTP_SSI) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "SCC : %s\n",
|
||||
(mscr & CPM_MSCR_MSTP_SCC) ? "stopped" : "running");
|
||||
return len;
|
||||
}
|
||||
|
||||
static int pmc_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data)
|
||||
{
|
||||
REG_CPM_MSCR = simple_strtoul(buffer, 0, 16);
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clock Generation Module
|
||||
*/
|
||||
static int cgm_read_proc (char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
unsigned int cfcr = REG_CPM_CFCR;
|
||||
unsigned int plcr1 = REG_CPM_PLCR1;
|
||||
unsigned int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
|
||||
unsigned int od[4] = {1, 2, 2, 4};
|
||||
|
||||
|
||||
len += sprintf (page+len, "PLCR1 : 0x%08x\n", plcr1);
|
||||
len += sprintf (page+len, "CFCR : 0x%08x\n", cfcr);
|
||||
len += sprintf (page+len, "PLL : %s\n",
|
||||
(plcr1 & CPM_PLCR1_PLL1EN) ? "ON" : "OFF");
|
||||
len += sprintf (page+len, "NF:NR:NO : %d:%d:%d\n",
|
||||
__cpm_plcr1_fd() + 2,
|
||||
__cpm_plcr1_rd() + 2,
|
||||
od[__cpm_plcr1_od()]
|
||||
);
|
||||
len += sprintf (page+len, "I:S:M:P : %d:%d:%d:%d\n",
|
||||
div[(cfcr & CPM_CFCR_IFR_MASK) >> CPM_CFCR_IFR_BIT],
|
||||
div[(cfcr & CPM_CFCR_SFR_MASK) >> CPM_CFCR_SFR_BIT],
|
||||
div[(cfcr & CPM_CFCR_MFR_MASK) >> CPM_CFCR_MFR_BIT],
|
||||
div[(cfcr & CPM_CFCR_PFR_MASK) >> CPM_CFCR_PFR_BIT]
|
||||
);
|
||||
len += sprintf (page+len, "PLL Freq : %d MHz\n", __cpm_get_pllout()/1000000);
|
||||
len += sprintf (page+len, "ICLK : %d MHz\n", __cpm_get_iclk()/1000000);
|
||||
len += sprintf (page+len, "SCLK : %d MHz\n", __cpm_get_sclk()/1000000);
|
||||
len += sprintf (page+len, "MCLK : %d MHz\n", __cpm_get_mclk()/1000000);
|
||||
len += sprintf (page+len, "PCLK : %d MHz\n", __cpm_get_pclk()/1000000);
|
||||
len += sprintf (page+len, "DEVCLK : %d MHz\n", __cpm_get_devclk()/1000000);
|
||||
len += sprintf (page+len, "RTCCLK : %d KHz\n", __cpm_get_rtcclk()/1000);
|
||||
len += sprintf (page+len, "USBCLK : %d MHz\n", __cpm_get_usbclk()/1000000);
|
||||
#if defined(CONFIG_FB_JZ)
|
||||
len += sprintf (page+len, "LCDCLK : %d MHz\n", __cpm_get_lcdclk()/1000000);
|
||||
len += sprintf (page+len, "PIXCLK : %d MHz\n", __cpm_get_pixclk()/1000000);
|
||||
#endif
|
||||
return len;
|
||||
}
|
||||
|
||||
static int cgm_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
|
||||
{
|
||||
REG_CPM_CFCR = simple_strtoul(buffer, 0, 16);
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* WDT
|
||||
*/
|
||||
static int wdt_read_proc (char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
len += sprintf (page+len, "WDT_WTCSR : 0x%08x\n", REG_WDT_WTCSR);
|
||||
len += sprintf (page+len, "WDT_WTCNT : 0x%08x\n", REG_WDT_WTCNT);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int wdt_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
|
||||
{
|
||||
unsigned long cnt = simple_strtoul(buffer, 0, 16);
|
||||
|
||||
REG_WDT_WTCNT = cnt;
|
||||
REG_WDT_WTCSR = WDT_WTCSR_START;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* PWM
|
||||
*/
|
||||
|
||||
static int proc_jz_pwm_read_byte(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
return sprintf (page, "0x%02x\n", REG8(data));
|
||||
}
|
||||
|
||||
static int proc_jz_pwm_read_word(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
return sprintf (page, "0x%04x\n", REG16(data));
|
||||
}
|
||||
|
||||
static int proc_jz_pwm_write_byte(struct file *file, const char *buffer, unsigned long count, void *data)
|
||||
{
|
||||
REG8(data) = simple_strtoul(buffer, 0, 16);
|
||||
return count;
|
||||
}
|
||||
|
||||
static int proc_jz_pwm_write_word(struct file *file, const char *buffer, unsigned long count, void *data)
|
||||
{
|
||||
REG16(data) = simple_strtoul(buffer, 0, 16);
|
||||
return count;
|
||||
}
|
||||
|
||||
#define PWM_NUM 2
|
||||
|
||||
static int jz_pwm_proc_init(void)
|
||||
{
|
||||
struct proc_dir_entry *proc_jz_pwm, *res;
|
||||
char name[16];
|
||||
unsigned char i;
|
||||
|
||||
for (i = 0; i < PWM_NUM; i++) {
|
||||
sprintf(name, "pwm%d", i);
|
||||
proc_jz_pwm = proc_mkdir(name, proc_jz_root);
|
||||
res = create_proc_entry("control", 0600, proc_jz_pwm);
|
||||
if ( res) {
|
||||
res->read_proc = proc_jz_pwm_read_byte;
|
||||
res->write_proc = proc_jz_pwm_write_byte;
|
||||
if (i)
|
||||
res->data = (void * )PWM_CTR(1);
|
||||
else
|
||||
res->data = (void * )PWM_CTR(0);
|
||||
}
|
||||
res = create_proc_entry("period", 0600, proc_jz_pwm);
|
||||
if ( res) {
|
||||
res->read_proc = proc_jz_pwm_read_word;
|
||||
res->write_proc = proc_jz_pwm_write_word;
|
||||
if (i)
|
||||
res->data = (void *)PWM_PER(1);
|
||||
else
|
||||
res->data = (void *)PWM_PER(0);
|
||||
}
|
||||
res = create_proc_entry("duty", 0600, proc_jz_pwm);
|
||||
if ( res) {
|
||||
res->read_proc = proc_jz_pwm_read_word;
|
||||
res->write_proc = proc_jz_pwm_write_word;
|
||||
if (i)
|
||||
res->data = (void * )PWM_DUT(1);
|
||||
else
|
||||
res->data = (void * )PWM_DUT(0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* /proc/jz/xxx entry
|
||||
*
|
||||
*/
|
||||
static int __init jz_proc_init(void)
|
||||
{
|
||||
struct proc_dir_entry *entry;
|
||||
|
||||
/* create /proc/jz */
|
||||
proc_jz_root = proc_mkdir("jz", 0);
|
||||
|
||||
/* create /proc/jz/emc */
|
||||
entry = create_proc_entry("emc", 0644, proc_jz_root);
|
||||
if (entry) {
|
||||
entry->read_proc = emc_read_proc;
|
||||
entry->write_proc = NULL;
|
||||
entry->data = NULL;
|
||||
}
|
||||
|
||||
/* create /proc/jz/pmc */
|
||||
entry = create_proc_entry("pmc", 0644, proc_jz_root);
|
||||
if (entry) {
|
||||
entry->read_proc = pmc_read_proc;
|
||||
entry->write_proc = pmc_write_proc;
|
||||
entry->data = NULL;
|
||||
}
|
||||
|
||||
/* create /proc/jz/cgm */
|
||||
entry = create_proc_entry("cgm", 0644, proc_jz_root);
|
||||
if (entry) {
|
||||
entry->read_proc = cgm_read_proc;
|
||||
entry->write_proc = cgm_write_proc;
|
||||
entry->data = NULL;
|
||||
}
|
||||
|
||||
/* create /proc/jz/wdt */
|
||||
entry = create_proc_entry("wdt", 0644, proc_jz_root);
|
||||
if (entry) {
|
||||
entry->read_proc = wdt_read_proc;
|
||||
entry->write_proc = wdt_write_proc;
|
||||
entry->data = NULL;
|
||||
}
|
||||
|
||||
/* PWM */
|
||||
jz_pwm_proc_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__initcall(jz_proc_init);
|
||||
198
target/linux/xburst/files-2.6.27/arch/mips/jz4730/prom.c
Normal file
198
target/linux/xburst/files-2.6.27/arch/mips/jz4730/prom.c
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
*
|
||||
* BRIEF MODULE DESCRIPTION
|
||||
* PROM library initialisation code, supports YAMON and U-Boot.
|
||||
*
|
||||
* Copyright 2000, 2001, 2006 MontaVista Software Inc.
|
||||
* Author: MontaVista Software, Inc.
|
||||
* ppopov@mvista.com or source@mvista.com
|
||||
*
|
||||
* This file was derived from Carsten Langgaard's
|
||||
* arch/mips/mips-boards/xx files.
|
||||
*
|
||||
* Carsten Langgaard, carstenl@mips.com
|
||||
* Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
|
||||
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* 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.,
|
||||
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/* #define DEBUG_CMDLINE */
|
||||
|
||||
int prom_argc;
|
||||
char **prom_argv, **prom_envp;
|
||||
|
||||
char * prom_getcmdline(void)
|
||||
{
|
||||
return &(arcs_cmdline[0]);
|
||||
}
|
||||
|
||||
void prom_init_cmdline(void)
|
||||
{
|
||||
char *cp;
|
||||
int actr;
|
||||
|
||||
actr = 1; /* Always ignore argv[0] */
|
||||
|
||||
cp = &(arcs_cmdline[0]);
|
||||
while(actr < prom_argc) {
|
||||
strcpy(cp, prom_argv[actr]);
|
||||
cp += strlen(prom_argv[actr]);
|
||||
*cp++ = ' ';
|
||||
actr++;
|
||||
}
|
||||
if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
|
||||
--cp;
|
||||
if (prom_argc > 1)
|
||||
*cp = '\0';
|
||||
|
||||
}
|
||||
|
||||
|
||||
char *prom_getenv(char *envname)
|
||||
{
|
||||
#if 0
|
||||
/*
|
||||
* Return a pointer to the given environment variable.
|
||||
* YAMON uses "name", "value" pairs, while U-Boot uses "name=value".
|
||||
*/
|
||||
|
||||
char **env = prom_envp;
|
||||
int i = strlen(envname);
|
||||
int yamon = (*env && strchr(*env, '=') == NULL);
|
||||
|
||||
while (*env) {
|
||||
if (yamon) {
|
||||
if (strcmp(envname, *env++) == 0)
|
||||
return *env;
|
||||
} else {
|
||||
if (strncmp(envname, *env, i) == 0 && (*env)[i] == '=')
|
||||
return *env + i + 1;
|
||||
}
|
||||
env++;
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline unsigned char str2hexnum(unsigned char c)
|
||||
{
|
||||
if(c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
if(c >= 'a' && c <= 'f')
|
||||
return c - 'a' + 10;
|
||||
if(c >= 'A' && c <= 'F')
|
||||
return c - 'A' + 10;
|
||||
return 0; /* foo */
|
||||
}
|
||||
|
||||
inline void str2eaddr(unsigned char *ea, unsigned char *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 6; i++) {
|
||||
unsigned char num;
|
||||
|
||||
if((*str == '.') || (*str == ':'))
|
||||
str++;
|
||||
num = str2hexnum(*str++) << 4;
|
||||
num |= (str2hexnum(*str++));
|
||||
ea[i] = num;
|
||||
}
|
||||
}
|
||||
|
||||
int get_ethernet_addr(char *ethernet_addr)
|
||||
{
|
||||
char *ethaddr_str;
|
||||
|
||||
ethaddr_str = prom_getenv("ethaddr");
|
||||
if (!ethaddr_str) {
|
||||
printk("ethaddr not set in boot prom\n");
|
||||
return -1;
|
||||
}
|
||||
str2eaddr(ethernet_addr, ethaddr_str);
|
||||
|
||||
#if 0
|
||||
{
|
||||
int i;
|
||||
|
||||
printk("get_ethernet_addr: ");
|
||||
for (i=0; i<5; i++)
|
||||
printk("%02x:", (unsigned char)*(ethernet_addr+i));
|
||||
printk("%02x\n", *(ethernet_addr+i));
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init prom_free_prom_memory(void)
|
||||
{
|
||||
}
|
||||
|
||||
void __init prom_init(void)
|
||||
{
|
||||
unsigned char *memsize_str;
|
||||
unsigned long memsize;
|
||||
|
||||
prom_argc = (int) fw_arg0;
|
||||
prom_argv = (char **) fw_arg1;
|
||||
prom_envp = (char **) fw_arg2;
|
||||
|
||||
mips_machtype = MACH_INGENIC_JZ4730;
|
||||
|
||||
prom_init_cmdline();
|
||||
memsize_str = prom_getenv("memsize");
|
||||
if (!memsize_str) {
|
||||
memsize = 0x04000000;
|
||||
} else {
|
||||
memsize = simple_strtol(memsize_str, NULL, 0);
|
||||
}
|
||||
add_memory_region(0, memsize, BOOT_MEM_RAM);
|
||||
}
|
||||
|
||||
/* used by early printk */
|
||||
void prom_putchar(char c)
|
||||
{
|
||||
volatile u8 *uart_lsr = (volatile u8 *)(UART3_BASE + OFF_LSR);
|
||||
volatile u8 *uart_tdr = (volatile u8 *)(UART3_BASE + OFF_TDR);
|
||||
|
||||
/* Wait for fifo to shift out some bytes */
|
||||
while ( !((*uart_lsr & (UARTLSR_TDRQ | UARTLSR_TEMT)) == 0x60) );
|
||||
|
||||
*uart_tdr = (u8)c;
|
||||
}
|
||||
|
||||
const char *get_system_type(void)
|
||||
{
|
||||
return "JZ4730";
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(prom_getcmdline);
|
||||
EXPORT_SYMBOL(get_ethernet_addr);
|
||||
EXPORT_SYMBOL(str2eaddr);
|
||||
40
target/linux/xburst/files-2.6.27/arch/mips/jz4730/reset.c
Normal file
40
target/linux/xburst/files-2.6.27/arch/mips/jz4730/reset.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4730/reset.c
|
||||
*
|
||||
* JZ4730 reset routines.
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* 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/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/reboot.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
void jz_restart(char *command)
|
||||
{
|
||||
__wdt_set_count(0xffffffff-32); /* reset after 1/1024 s */
|
||||
__wdt_start();
|
||||
while (1);
|
||||
}
|
||||
|
||||
void jz_halt(void)
|
||||
{
|
||||
__wdt_set_count(0xffffffff-32); /* reset after 1/1024 s */
|
||||
__wdt_start();
|
||||
while (1);
|
||||
}
|
||||
|
||||
void jz_power_off(void)
|
||||
{
|
||||
jz_halt();
|
||||
}
|
||||
182
target/linux/xburst/files-2.6.27/arch/mips/jz4730/setup.c
Normal file
182
target/linux/xburst/files-2.6.27/arch/mips/jz4730/setup.c
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4730/setup.c
|
||||
*
|
||||
* JZ4730 CPU common setup routines.
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_8250.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/reboot.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
#ifdef CONFIG_PC_KEYB
|
||||
#include <asm/keyboard.h>
|
||||
#endif
|
||||
|
||||
jz_clocks_t jz_clocks;
|
||||
|
||||
extern char * __init prom_getcmdline(void);
|
||||
extern void __init jz_board_setup(void);
|
||||
extern void jz_restart(char *);
|
||||
extern void jz_halt(void);
|
||||
extern void jz_power_off(void);
|
||||
extern void jz_time_init(void);
|
||||
|
||||
static void __init sysclocks_setup(void)
|
||||
{
|
||||
#ifndef CONFIG_JZ4730_URANUS
|
||||
jz_clocks.iclk = __cpm_get_iclk();
|
||||
jz_clocks.sclk = __cpm_get_sclk();
|
||||
jz_clocks.mclk = __cpm_get_mclk();
|
||||
jz_clocks.pclk = __cpm_get_pclk();
|
||||
jz_clocks.devclk = __cpm_get_devclk();
|
||||
jz_clocks.rtcclk = __cpm_get_rtcclk();
|
||||
jz_clocks.uartclk = __cpm_get_uartclk();
|
||||
jz_clocks.lcdclk = __cpm_get_lcdclk();
|
||||
jz_clocks.pixclk = __cpm_get_pixclk();
|
||||
jz_clocks.usbclk = __cpm_get_usbclk();
|
||||
jz_clocks.i2sclk = __cpm_get_i2sclk();
|
||||
jz_clocks.mscclk = __cpm_get_mscclk();
|
||||
#else /* URANUS FPGA */
|
||||
|
||||
#define FPGACLK 8000000
|
||||
|
||||
jz_clocks.iclk = FPGACLK;
|
||||
jz_clocks.sclk = FPGACLK;
|
||||
jz_clocks.mclk = FPGACLK;
|
||||
jz_clocks.devclk = FPGACLK;
|
||||
jz_clocks.rtcclk = FPGACLK;
|
||||
jz_clocks.uartclk = FPGACLK;
|
||||
jz_clocks.pixclk = FPGACLK;
|
||||
jz_clocks.lcdclk = FPGACLK;
|
||||
jz_clocks.usbclk = FPGACLK;
|
||||
jz_clocks.i2sclk = FPGACLK;
|
||||
jz_clocks.mscclk = FPGACLK;
|
||||
#endif
|
||||
|
||||
printk("CPU clock: %dMHz, System clock: %dMHz, Memory clock: %dMHz, Peripheral clock: %dMHz\n",
|
||||
(jz_clocks.iclk + 500000) / 1000000,
|
||||
(jz_clocks.sclk + 500000) / 1000000,
|
||||
(jz_clocks.mclk + 500000) / 1000000,
|
||||
(jz_clocks.pclk + 500000) / 1000000);
|
||||
}
|
||||
|
||||
static void __init soc_cpm_setup(void)
|
||||
{
|
||||
__cpm_idle_mode();
|
||||
__cpm_enable_cko1();
|
||||
__cpm_start_all();
|
||||
|
||||
/* get system clocks */
|
||||
sysclocks_setup();
|
||||
}
|
||||
|
||||
static void __init soc_harb_setup(void)
|
||||
{
|
||||
// __harb_set_priority(0x00); /* CIM>LCD>DMA>ETH>PCI>USB>CBB */
|
||||
// __harb_set_priority(0x03); /* LCD>CIM>DMA>ETH>PCI>USB>CBB */
|
||||
__harb_set_priority(0x08); /* DMAC>LCD>CIM>ETH>USB>CIM */
|
||||
// __harb_set_priority(0x0a); /* ETH>LCD>CIM>DMA>PCI>USB>CBB */
|
||||
}
|
||||
|
||||
static void __init soc_emc_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void __init soc_dmac_setup(void)
|
||||
{
|
||||
__dmac_enable_all_channels();
|
||||
}
|
||||
|
||||
static void __init jz_soc_setup(void)
|
||||
{
|
||||
soc_cpm_setup();
|
||||
soc_harb_setup();
|
||||
soc_emc_setup();
|
||||
soc_dmac_setup();
|
||||
}
|
||||
|
||||
static void __init jz_serial_setup(void)
|
||||
{
|
||||
#ifdef CONFIG_SERIAL_8250
|
||||
struct uart_port s;
|
||||
|
||||
memset(&s, 0, sizeof(s));
|
||||
|
||||
s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
|
||||
s.iotype = UPIO_MEM;
|
||||
s.regshift = 2;
|
||||
s.uartclk = jz_clocks.uartclk;
|
||||
|
||||
s.line = 0;
|
||||
s.membase = (u8 *)UART0_BASE;
|
||||
s.irq = IRQ_UART0;
|
||||
if (early_serial_setup(&s) != 0) {
|
||||
printk(KERN_ERR "Serial ttyS0 setup failed!\n");
|
||||
}
|
||||
|
||||
s.line = 1;
|
||||
s.membase = (u8 *)UART1_BASE;
|
||||
s.irq = IRQ_UART1;
|
||||
if (early_serial_setup(&s) != 0) {
|
||||
printk(KERN_ERR "Serial ttyS1 setup failed!\n");
|
||||
}
|
||||
|
||||
s.line = 2;
|
||||
s.membase = (u8 *)UART2_BASE;
|
||||
s.irq = IRQ_UART2;
|
||||
if (early_serial_setup(&s) != 0) {
|
||||
printk(KERN_ERR "Serial ttyS2 setup failed!\n");
|
||||
}
|
||||
|
||||
s.line = 3;
|
||||
s.membase = (u8 *)UART3_BASE;
|
||||
s.irq = IRQ_UART3;
|
||||
if (early_serial_setup(&s) != 0) {
|
||||
printk(KERN_ERR "Serial ttyS3 setup failed!\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void __init plat_mem_setup(void)
|
||||
{
|
||||
char *argptr;
|
||||
|
||||
argptr = prom_getcmdline();
|
||||
|
||||
/* IO/MEM resources. */
|
||||
set_io_port_base(0);
|
||||
ioport_resource.start = 0x00000000;
|
||||
ioport_resource.end = 0xffffffff;
|
||||
iomem_resource.start = 0x00000000;
|
||||
iomem_resource.end = 0xffffffff;
|
||||
|
||||
_machine_restart = jz_restart;
|
||||
_machine_halt = jz_halt;
|
||||
pm_power_off = jz_power_off;
|
||||
|
||||
jz_soc_setup(); /* soc specific setup */
|
||||
jz_serial_setup(); /* serial port setup */
|
||||
jz_board_setup(); /* board specific setup */
|
||||
}
|
||||
307
target/linux/xburst/files-2.6.27/arch/mips/jz4730/sleep.S
Normal file
307
target/linux/xburst/files-2.6.27/arch/mips/jz4730/sleep.S
Normal file
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4730/sleep.S
|
||||
*
|
||||
* jz4730 Assembler Sleep/WakeUp Management Routines
|
||||
*
|
||||
* Copyright (C) 2005 Ingenic Semiconductor
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* 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 <asm/regdef.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/mach-jz4730/regs.h>
|
||||
|
||||
.text
|
||||
.set noreorder
|
||||
.set noat
|
||||
|
||||
.extern jz_flush_cache_all
|
||||
|
||||
/*
|
||||
* jz_cpu_suspend()
|
||||
*
|
||||
* Forces CPU into hibernate mode
|
||||
*/
|
||||
|
||||
.globl jz_cpu_suspend
|
||||
jz_cpu_suspend:
|
||||
|
||||
/* save hi, lo and general registers except k0($26) and k1($27) (total 32) */
|
||||
move k0, sp
|
||||
addiu k0, k0, -(32*4)
|
||||
mfhi k1
|
||||
sw $0, 0(k0)
|
||||
sw $1, 4(k0)
|
||||
sw k1, 120(k0) /* hi */
|
||||
mflo k1
|
||||
sw $2, 8(k0)
|
||||
sw $3, 12(k0)
|
||||
sw k1, 124(k0) /* lo */
|
||||
sw $4, 16(k0)
|
||||
sw $5, 20(k0)
|
||||
sw $6, 24(k0)
|
||||
sw $7, 28(k0)
|
||||
sw $8, 32(k0)
|
||||
sw $9, 36(k0)
|
||||
sw $10, 40(k0)
|
||||
sw $11, 44(k0)
|
||||
sw $12, 48(k0)
|
||||
sw $13, 52(k0)
|
||||
sw $14, 56(k0)
|
||||
sw $15, 60(k0)
|
||||
sw $16, 64(k0)
|
||||
sw $17, 68(k0)
|
||||
sw $18, 72(k0)
|
||||
sw $19, 76(k0)
|
||||
sw $20, 80(k0)
|
||||
sw $21, 84(k0)
|
||||
sw $22, 88(k0)
|
||||
sw $23, 92(k0)
|
||||
sw $24, 96(k0)
|
||||
sw $25, 100(k0)
|
||||
sw $28, 104(k0)
|
||||
sw $29, 108(k0) /* saved sp */
|
||||
sw $30, 112(k0)
|
||||
sw $31, 116(k0) /* saved ra */
|
||||
move sp, k0
|
||||
|
||||
/* save CP0 registers and sp (total 26) */
|
||||
move k0, sp
|
||||
addiu k0, k0, -(26*4)
|
||||
|
||||
mfc0 $1, CP0_INDEX
|
||||
mfc0 $2, CP0_RANDOM
|
||||
mfc0 $3, CP0_ENTRYLO0
|
||||
mfc0 $4, CP0_ENTRYLO1
|
||||
mfc0 $5, CP0_CONTEXT
|
||||
mfc0 $6, CP0_PAGEMASK
|
||||
mfc0 $7, CP0_WIRED
|
||||
mfc0 $8, CP0_BADVADDR
|
||||
mfc0 $9, CP0_ENTRYHI
|
||||
mfc0 $10, CP0_STATUS
|
||||
/* mfc0 $11, $12, 1*/ /* IntCtl */
|
||||
mfc0 $12, CP0_CAUSE
|
||||
mfc0 $13, CP0_EPC
|
||||
/* mfc0 $14, $15, 1*/ /* EBase */
|
||||
mfc0 $15, CP0_CONFIG
|
||||
/* mfc0 $16, CP0_CONFIG, 7*/ /* Config 7 */
|
||||
mfc0 $17, CP0_LLADDR
|
||||
mfc0 $18, CP0_WATCHLO
|
||||
mfc0 $19, CP0_WATCHHI
|
||||
mfc0 $20, CP0_DEBUG
|
||||
mfc0 $21, CP0_DEPC
|
||||
mfc0 $22, CP0_ECC
|
||||
mfc0 $23, CP0_TAGLO
|
||||
mfc0 $24, CP0_ERROREPC
|
||||
mfc0 $25, CP0_DESAVE
|
||||
|
||||
sw $1, 0(k0)
|
||||
sw $2, 4(k0)
|
||||
sw $3, 8(k0)
|
||||
sw $4, 12(k0)
|
||||
sw $5, 16(k0)
|
||||
sw $6, 20(k0)
|
||||
sw $7, 24(k0)
|
||||
sw $8, 28(k0)
|
||||
sw $9, 32(k0)
|
||||
sw $10, 36(k0)
|
||||
sw $11, 40(k0)
|
||||
sw $12, 44(k0)
|
||||
sw $13, 48(k0)
|
||||
sw $14, 52(k0)
|
||||
sw $15, 56(k0)
|
||||
sw $16, 60(k0)
|
||||
sw $17, 64(k0)
|
||||
sw $18, 68(k0)
|
||||
sw $19, 72(k0)
|
||||
sw $20, 76(k0)
|
||||
sw $21, 80(k0)
|
||||
sw $22, 84(k0)
|
||||
sw $23, 88(k0)
|
||||
sw $24, 92(k0)
|
||||
sw $25, 96(k0)
|
||||
sw $29, 100(k0) /* saved sp */
|
||||
move sp, k0
|
||||
|
||||
/* preserve virtual address of stack */
|
||||
la k0, suspend_save_sp
|
||||
sw sp, 0(k0)
|
||||
|
||||
/* flush caches and write buffers */
|
||||
jal jz_flush_cache_all
|
||||
nop
|
||||
|
||||
/* set new sdram refresh constant */
|
||||
li t0, 1
|
||||
la t1, EMC_RTCOR
|
||||
sh t0, 0(t1)
|
||||
|
||||
/* disable PLL */
|
||||
la t0, CPM_PLCR1
|
||||
sw $0, 0(t0)
|
||||
|
||||
/* put CPU to hibernate mode */
|
||||
la t0, CPM_LPCR
|
||||
lw t1, 0(t0)
|
||||
li t2, ~CPM_LPCR_LPM_MASK
|
||||
and t1, t2
|
||||
ori t1, CPM_LPCR_LPM_HIBERNATE
|
||||
|
||||
.align 5
|
||||
/* align execution to a cache line */
|
||||
j 1f
|
||||
|
||||
.align 5
|
||||
1:
|
||||
/* all needed values are now in registers.
|
||||
* These last instructions should be in cache
|
||||
*/
|
||||
nop
|
||||
nop
|
||||
|
||||
/* set hibernate mode */
|
||||
sw t1, 0(t0)
|
||||
nop
|
||||
|
||||
/* enter hibernate mode */
|
||||
.set mips3
|
||||
wait
|
||||
nop
|
||||
.set mips2
|
||||
|
||||
2: j 2b /* loop waiting for suspended */
|
||||
nop
|
||||
|
||||
/*
|
||||
* jz_cpu_resume()
|
||||
*
|
||||
* entry point from bootloader into kernel during resume
|
||||
*/
|
||||
|
||||
.align 5
|
||||
.globl jz_cpu_resume
|
||||
jz_cpu_resume:
|
||||
/* clear SCR.HGP */
|
||||
la t0, CPM_SCR
|
||||
lw t1, 0(t0)
|
||||
li t2, ~CPM_SCR_HGP
|
||||
and t1, t2
|
||||
sw t1, 0(t0)
|
||||
|
||||
/* restore LPCR.LPM to IDLE mode */
|
||||
la t0, CPM_LPCR
|
||||
lw t1, 0(t0)
|
||||
li t2, ~CPM_LPCR_LPM_MASK
|
||||
and t1, t2
|
||||
ori t1, CPM_LPCR_LPM_IDLE
|
||||
sw t1, 0(t0)
|
||||
|
||||
/* restore saved sp */
|
||||
la t0, suspend_save_sp
|
||||
lw sp, 0(t0)
|
||||
|
||||
/* restore CP0 registers */
|
||||
move k0, sp
|
||||
lw $1, 0(k0)
|
||||
lw $2, 4(k0)
|
||||
lw $3, 8(k0)
|
||||
lw $4, 12(k0)
|
||||
lw $5, 16(k0)
|
||||
lw $6, 20(k0)
|
||||
lw $7, 24(k0)
|
||||
lw $8, 28(k0)
|
||||
lw $9, 32(k0)
|
||||
lw $10, 36(k0)
|
||||
lw $11, 40(k0)
|
||||
lw $12, 44(k0)
|
||||
lw $13, 48(k0)
|
||||
lw $14, 52(k0)
|
||||
lw $15, 56(k0)
|
||||
lw $16, 60(k0)
|
||||
lw $17, 64(k0)
|
||||
lw $18, 68(k0)
|
||||
lw $19, 72(k0)
|
||||
lw $20, 76(k0)
|
||||
lw $21, 80(k0)
|
||||
lw $22, 84(k0)
|
||||
lw $23, 88(k0)
|
||||
lw $24, 92(k0)
|
||||
lw $25, 96(k0)
|
||||
lw $29, 100(k0) /* saved sp */
|
||||
|
||||
mtc0 $1, CP0_INDEX
|
||||
mtc0 $2, CP0_RANDOM
|
||||
mtc0 $3, CP0_ENTRYLO0
|
||||
mtc0 $4, CP0_ENTRYLO1
|
||||
mtc0 $5, CP0_CONTEXT
|
||||
mtc0 $6, CP0_PAGEMASK
|
||||
mtc0 $7, CP0_WIRED
|
||||
mtc0 $8, CP0_BADVADDR
|
||||
mtc0 $9, CP0_ENTRYHI
|
||||
mtc0 $10, CP0_STATUS
|
||||
/* mtc0 $11, $12, 1*/ /* IntCtl */
|
||||
mtc0 $12, CP0_CAUSE
|
||||
mtc0 $13, CP0_EPC
|
||||
/* mtc0 $14, $15, 1*/ /* EBase */
|
||||
mtc0 $15, CP0_CONFIG
|
||||
/* mtc0 $16, CP0_CONFIG, 7*/ /* Config 7 */
|
||||
mtc0 $17, CP0_LLADDR
|
||||
mtc0 $18, CP0_WATCHLO
|
||||
mtc0 $19, CP0_WATCHHI
|
||||
mtc0 $20, CP0_DEBUG
|
||||
mtc0 $21, CP0_DEPC
|
||||
mtc0 $22, CP0_ECC
|
||||
mtc0 $23, CP0_TAGLO
|
||||
mtc0 $24, CP0_ERROREPC
|
||||
mtc0 $25, CP0_DESAVE
|
||||
|
||||
/* restore general registers */
|
||||
move k0, sp
|
||||
lw k1, 120(k0) /* hi */
|
||||
lw $0, 0(k0)
|
||||
lw $1, 4(k0)
|
||||
mthi k1
|
||||
lw k1, 124(k0) /* lo */
|
||||
lw $2, 8(k0)
|
||||
lw $3, 12(k0)
|
||||
mtlo k1
|
||||
lw $4, 16(k0)
|
||||
lw $5, 20(k0)
|
||||
lw $6, 24(k0)
|
||||
lw $7, 28(k0)
|
||||
lw $8, 32(k0)
|
||||
lw $9, 36(k0)
|
||||
lw $10, 40(k0)
|
||||
lw $11, 44(k0)
|
||||
lw $12, 48(k0)
|
||||
lw $13, 52(k0)
|
||||
lw $14, 56(k0)
|
||||
lw $15, 60(k0)
|
||||
lw $16, 64(k0)
|
||||
lw $17, 68(k0)
|
||||
lw $18, 72(k0)
|
||||
lw $19, 76(k0)
|
||||
lw $20, 80(k0)
|
||||
lw $21, 84(k0)
|
||||
lw $22, 88(k0)
|
||||
lw $23, 92(k0)
|
||||
lw $24, 96(k0)
|
||||
lw $25, 100(k0)
|
||||
lw $28, 104(k0)
|
||||
lw $29, 108(k0) /* saved sp */
|
||||
lw $30, 112(k0)
|
||||
lw $31, 116(k0) /* saved ra */
|
||||
|
||||
/* return to caller */
|
||||
jr ra
|
||||
nop
|
||||
|
||||
suspend_save_sp:
|
||||
.word 0 /* preserve sp here */
|
||||
|
||||
.set reorder
|
||||
129
target/linux/xburst/files-2.6.27/arch/mips/jz4730/time.c
Normal file
129
target/linux/xburst/files-2.6.27/arch/mips/jz4730/time.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4730/time.c
|
||||
*
|
||||
* Setting up the clock on the JZ4730 boards.
|
||||
*
|
||||
* Copyright (c) 2006-2008 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* 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/types.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/clockchips.h>
|
||||
|
||||
#include <asm/time.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
#define JZ_TIMER_CHAN 0
|
||||
#define JZ_TIMER_IRQ IRQ_OST0
|
||||
#define JZ_TIMER_CLOCK JZ_EXTAL
|
||||
|
||||
static unsigned int timer_latch;
|
||||
|
||||
void (*jz_timer_callback)(void);
|
||||
|
||||
static void jz_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
break;
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct clock_event_device jz_clockevent_device = {
|
||||
.name = "jz-timer",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC,
|
||||
|
||||
/* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */
|
||||
|
||||
.rating = 300,
|
||||
.irq = JZ_TIMER_IRQ,
|
||||
.set_mode = jz_set_mode,
|
||||
};
|
||||
|
||||
static irqreturn_t jz_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct clock_event_device *cd = dev_id;
|
||||
|
||||
__ost_clear_uf(JZ_TIMER_CHAN); /* ACK timer */
|
||||
|
||||
if (jz_timer_callback)
|
||||
jz_timer_callback();
|
||||
|
||||
cd->event_handler(cd);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct irqaction jz_irqaction = {
|
||||
.handler = jz_timer_interrupt,
|
||||
.flags = IRQF_DISABLED | IRQF_PERCPU,
|
||||
.name = "jz-timer",
|
||||
};
|
||||
|
||||
cycle_t jz_get_cycles(void)
|
||||
{
|
||||
unsigned int jz_timer_cnt;
|
||||
#if 0 /* clock source use pll, read directly */
|
||||
jz_timer_cnt = timer_latch - REG_OST_TCNT(JZ_TIMER_CHAN);
|
||||
#else /* clock source use RTCClock or Extall Clock, wait read ready */
|
||||
jz_timer_cnt = REG_OST_TCNT(JZ_TIMER_CHAN); /* dummy read */
|
||||
while ( __ost_is_busy(JZ_TIMER_CHAN) ) ; /* wait read ready */
|
||||
jz_timer_cnt = timer_latch - REG_OST_TCRB(JZ_TIMER_CHAN);
|
||||
#endif
|
||||
|
||||
/* convert jiffes to jz timer cycles */
|
||||
return (cycle_t)( jiffies*((JZ_TIMER_CLOCK)/HZ) + jz_timer_cnt);
|
||||
}
|
||||
|
||||
static struct clocksource clocksource_jz = {
|
||||
.name = "jz_clocksource",
|
||||
.rating = 300,
|
||||
.read = jz_get_cycles,
|
||||
.mask = 0xFFFFFFFF,
|
||||
.shift = 10, /* control clocksource.mult's accuracy */
|
||||
.flags = CLOCK_SOURCE_WATCHDOG,
|
||||
};
|
||||
|
||||
static int __init jz_clocksource_init(void)
|
||||
{
|
||||
clocksource_jz.mult = clocksource_hz2mult(JZ_TIMER_CLOCK, clocksource_jz.shift);
|
||||
clocksource_register(&clocksource_jz);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init jz_timer_setup(void)
|
||||
{
|
||||
struct clock_event_device *cd = &jz_clockevent_device;
|
||||
struct irqaction *action = &jz_irqaction;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
jz_clocksource_init();
|
||||
cd->cpumask = cpumask_of_cpu(cpu);
|
||||
clockevents_register_device(cd);
|
||||
action->dev_id = cd;
|
||||
setup_irq(JZ_TIMER_IRQ, &jz_irqaction);
|
||||
}
|
||||
|
||||
void __init plat_time_init(void)
|
||||
{
|
||||
/* Init timer, timer clock soure use extal clock */
|
||||
timer_latch = (JZ_TIMER_CLOCK + (HZ>>1)) / HZ;
|
||||
__ost_set_mode(JZ_TIMER_CHAN, OST_TCSR_UIE | OST_TCSR_CKS_EXTAL);
|
||||
__ost_set_reload(JZ_TIMER_CHAN, timer_latch);
|
||||
__ost_set_count(JZ_TIMER_CHAN, timer_latch);
|
||||
__ost_enable_channel(JZ_TIMER_CHAN);
|
||||
|
||||
jz_timer_setup();
|
||||
}
|
||||
26
target/linux/xburst/files-2.6.27/arch/mips/jz4740/Makefile
Normal file
26
target/linux/xburst/files-2.6.27/arch/mips/jz4740/Makefile
Normal file
@@ -0,0 +1,26 @@
|
||||
#
|
||||
# Makefile for the Ingenic JZ4740.
|
||||
#
|
||||
|
||||
# Object file lists.
|
||||
|
||||
obj-y += prom.o irq.o time.o reset.o setup.o dma.o \
|
||||
platform.o i2c.o
|
||||
|
||||
obj-$(CONFIG_PROC_FS) += proc.o
|
||||
|
||||
# board specific support
|
||||
|
||||
obj-$(CONFIG_JZ4740_PAVO) += board-pavo.o
|
||||
obj-$(CONFIG_JZ4740_LEO) += board-leo.o
|
||||
obj-$(CONFIG_JZ4740_LYRA) += board-lyra.o
|
||||
obj-$(CONFIG_JZ4725_DIPPER) += board-dipper.o
|
||||
obj-$(CONFIG_JZ4720_VIRGO) += board-virgo.o
|
||||
|
||||
# PM support
|
||||
|
||||
obj-$(CONFIG_PM) +=pm.o
|
||||
|
||||
# CPU Frequency scaling support
|
||||
|
||||
obj-$(CONFIG_CPU_FREQ_JZ) +=cpufreq.o
|
||||
117
target/linux/xburst/files-2.6.27/arch/mips/jz4740/board-dipper.c
Normal file
117
target/linux/xburst/files-2.6.27/arch/mips/jz4740/board-dipper.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4740/board-dipper.c
|
||||
*
|
||||
* JZ4725 Dipper board setup routines.
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <lhhuang@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/reboot.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
extern void (*jz_timer_callback)(void);
|
||||
|
||||
#if 0
|
||||
static void dancing(void)
|
||||
{
|
||||
static unsigned int count = 0;
|
||||
|
||||
count ++;
|
||||
count &= 1;
|
||||
|
||||
if (count)
|
||||
__gpio_set_pin(GPIO_LED_EN);
|
||||
else
|
||||
__gpio_clear_pin(GPIO_LED_EN);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void dipper_timer_callback(void)
|
||||
{
|
||||
static unsigned long count = 0;
|
||||
|
||||
if ((++count) % 50 == 0) {
|
||||
// dancing();
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init board_cpm_setup(void)
|
||||
{
|
||||
/* Stop unused module clocks here.
|
||||
* We have started all module clocks at arch/mips/jz4740/setup.c.
|
||||
*/
|
||||
}
|
||||
|
||||
static void __init board_gpio_setup(void)
|
||||
{
|
||||
/*
|
||||
* Most of the GPIO pins should have been initialized by the boot-loader
|
||||
*/
|
||||
|
||||
/*
|
||||
* Initialize MSC pins
|
||||
*/
|
||||
__gpio_as_msc();
|
||||
|
||||
/*
|
||||
* Initialize Smart LCD pins
|
||||
*/
|
||||
// __gpio_as_slcd_18bit();
|
||||
|
||||
/*
|
||||
* Initialize SSI pins
|
||||
*/
|
||||
__gpio_as_ssi();
|
||||
|
||||
/*
|
||||
* Initialize I2C pins
|
||||
*/
|
||||
__gpio_as_i2c();
|
||||
|
||||
/*
|
||||
* Initialize Other pins
|
||||
*/
|
||||
__gpio_as_output(GPIO_SD_VCC_EN_N);
|
||||
__gpio_clear_pin(GPIO_SD_VCC_EN_N);
|
||||
|
||||
__gpio_as_input(GPIO_SD_CD_N);
|
||||
__gpio_disable_pull(GPIO_SD_CD_N);
|
||||
|
||||
__gpio_as_input(GPIO_SD_WP);
|
||||
__gpio_disable_pull(GPIO_SD_WP);
|
||||
|
||||
__gpio_as_input(GPIO_DC_DETE_N);
|
||||
__gpio_as_input(GPIO_CHARG_STAT_N);
|
||||
__gpio_as_input(GPIO_USB_DETE);
|
||||
|
||||
__gpio_as_output(GPIO_DISP_OFF_N);
|
||||
|
||||
// __gpio_as_output(GPIO_LED_EN);
|
||||
}
|
||||
|
||||
void __init jz_board_setup(void)
|
||||
{
|
||||
printk("JZ4725 DIPPER board setup\n");
|
||||
|
||||
board_cpm_setup();
|
||||
board_gpio_setup();
|
||||
|
||||
jz_timer_callback = dipper_timer_callback;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4740/board-leo.c
|
||||
*
|
||||
* JZ4740 LEO board setup routines.
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <lhhuang@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/reboot.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
extern void (*jz_timer_callback)(void);
|
||||
|
||||
static void dancing(void)
|
||||
{
|
||||
static unsigned char slash[] = "\\|/-";
|
||||
static volatile unsigned char *p = (unsigned char *)0xb6000016;
|
||||
static unsigned int count = 0;
|
||||
*p = slash[count++];
|
||||
count &= 3;
|
||||
}
|
||||
|
||||
static void leo_timer_callback(void)
|
||||
{
|
||||
static unsigned long count = 0;
|
||||
|
||||
if ((++count) % 10 == 0) {
|
||||
dancing();
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init board_cpm_setup(void)
|
||||
{
|
||||
/* Stop unused module clocks here.
|
||||
* We have started all module clocks at arch/mips/jz4740/setup.c.
|
||||
*/
|
||||
}
|
||||
|
||||
static void __init board_gpio_setup(void)
|
||||
{
|
||||
/* All GPIO pins should have been initialized by the boot-loader */
|
||||
}
|
||||
|
||||
void __init jz_board_setup(void)
|
||||
{
|
||||
board_cpm_setup();
|
||||
board_gpio_setup();
|
||||
printk(" BOARD SETUP");
|
||||
jz_timer_callback = leo_timer_callback;
|
||||
}
|
||||
114
target/linux/xburst/files-2.6.27/arch/mips/jz4740/board-lyra.c
Normal file
114
target/linux/xburst/files-2.6.27/arch/mips/jz4740/board-lyra.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4740/board-lyra.c
|
||||
*
|
||||
* JZ4740 LYRA board setup routines.
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <lhhuang@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/reboot.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
extern void (*jz_timer_callback)(void);
|
||||
|
||||
static void dancing(void)
|
||||
{
|
||||
static unsigned int count = 0;
|
||||
|
||||
count ++;
|
||||
count &= 1;
|
||||
if (count)
|
||||
__gpio_set_pin(GPIO_LED_EN);
|
||||
else
|
||||
__gpio_clear_pin(GPIO_LED_EN);
|
||||
}
|
||||
|
||||
static void lyra_timer_callback(void)
|
||||
{
|
||||
static unsigned long count = 0;
|
||||
|
||||
if ((++count) % 50 == 0) {
|
||||
dancing();
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init board_cpm_setup(void)
|
||||
{
|
||||
/* Stop unused module clocks here.
|
||||
* We have started all module clocks at arch/mips/jz4740/setup.c.
|
||||
*/
|
||||
}
|
||||
|
||||
static void __init board_gpio_setup(void)
|
||||
{
|
||||
/*
|
||||
* Most of the GPIO pins should have been initialized by the boot-loader
|
||||
*/
|
||||
|
||||
/*
|
||||
* Initialize MSC pins
|
||||
*/
|
||||
__gpio_as_msc();
|
||||
|
||||
/*
|
||||
* Initialize LCD pins
|
||||
*/
|
||||
__gpio_as_lcd_18bit();
|
||||
|
||||
/*
|
||||
* Initialize SSI pins
|
||||
*/
|
||||
__gpio_as_ssi();
|
||||
|
||||
/*
|
||||
* Initialize I2C pins
|
||||
*/
|
||||
__gpio_as_i2c();
|
||||
|
||||
/*
|
||||
* Initialize Other pins
|
||||
*/
|
||||
__gpio_as_output(GPIO_SD_VCC_EN_N);
|
||||
__gpio_clear_pin(GPIO_SD_VCC_EN_N);
|
||||
|
||||
__gpio_as_input(GPIO_SD_CD_N);
|
||||
__gpio_disable_pull(GPIO_SD_CD_N);
|
||||
|
||||
__gpio_as_input(GPIO_SD_WP);
|
||||
__gpio_disable_pull(GPIO_SD_WP);
|
||||
|
||||
__gpio_as_input(GPIO_DC_DETE_N);
|
||||
__gpio_as_input(GPIO_CHARG_STAT_N);
|
||||
__gpio_as_input(GPIO_USB_DETE);
|
||||
|
||||
__gpio_as_output(GPIO_DISP_OFF_N);
|
||||
|
||||
__gpio_as_output(GPIO_LED_EN);
|
||||
}
|
||||
|
||||
void __init jz_board_setup(void)
|
||||
{
|
||||
printk("JZ4740 LYRA board setup\n");
|
||||
|
||||
board_cpm_setup();
|
||||
board_gpio_setup();
|
||||
|
||||
jz_timer_callback = lyra_timer_callback;
|
||||
}
|
||||
114
target/linux/xburst/files-2.6.27/arch/mips/jz4740/board-pavo.c
Normal file
114
target/linux/xburst/files-2.6.27/arch/mips/jz4740/board-pavo.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4740/board-pavo.c
|
||||
*
|
||||
* JZ4740 PAVO board setup routines.
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <lhhuang@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/reboot.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
extern void (*jz_timer_callback)(void);
|
||||
|
||||
static void dancing(void)
|
||||
{
|
||||
static unsigned int count = 0;
|
||||
|
||||
count ++;
|
||||
count &= 1;
|
||||
if (count)
|
||||
__gpio_set_pin(GPIO_LED_EN);
|
||||
else
|
||||
__gpio_clear_pin(GPIO_LED_EN);
|
||||
}
|
||||
|
||||
static void pavo_timer_callback(void)
|
||||
{
|
||||
static unsigned long count = 0;
|
||||
|
||||
if ((++count) % 50 == 0) {
|
||||
dancing();
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init board_cpm_setup(void)
|
||||
{
|
||||
/* Stop unused module clocks here.
|
||||
* We have started all module clocks at arch/mips/jz4740/setup.c.
|
||||
*/
|
||||
}
|
||||
|
||||
static void __init board_gpio_setup(void)
|
||||
{
|
||||
/*
|
||||
* Most of the GPIO pins should have been initialized by the boot-loader
|
||||
*/
|
||||
|
||||
/*
|
||||
* Initialize MSC pins
|
||||
*/
|
||||
__gpio_as_msc();
|
||||
|
||||
/*
|
||||
* Initialize LCD pins
|
||||
*/
|
||||
__gpio_as_lcd_18bit();
|
||||
|
||||
/*
|
||||
* Initialize SSI pins
|
||||
*/
|
||||
__gpio_as_ssi();
|
||||
|
||||
/*
|
||||
* Initialize I2C pins
|
||||
*/
|
||||
__gpio_as_i2c();
|
||||
|
||||
/*
|
||||
* Initialize Other pins
|
||||
*/
|
||||
__gpio_as_output(GPIO_SD_VCC_EN_N);
|
||||
__gpio_clear_pin(GPIO_SD_VCC_EN_N);
|
||||
|
||||
__gpio_as_input(GPIO_SD_CD_N);
|
||||
__gpio_disable_pull(GPIO_SD_CD_N);
|
||||
|
||||
__gpio_as_input(GPIO_SD_WP);
|
||||
__gpio_disable_pull(GPIO_SD_WP);
|
||||
|
||||
__gpio_as_input(GPIO_DC_DETE_N);
|
||||
__gpio_as_input(GPIO_CHARG_STAT_N);
|
||||
__gpio_as_input(GPIO_USB_DETE);
|
||||
|
||||
__gpio_as_output(GPIO_DISP_OFF_N);
|
||||
|
||||
__gpio_as_output(GPIO_LED_EN);
|
||||
}
|
||||
|
||||
void __init jz_board_setup(void)
|
||||
{
|
||||
printk("JZ4740 PAVO board setup\n");
|
||||
|
||||
board_cpm_setup();
|
||||
board_gpio_setup();
|
||||
|
||||
jz_timer_callback = pavo_timer_callback;
|
||||
}
|
||||
114
target/linux/xburst/files-2.6.27/arch/mips/jz4740/board-virgo.c
Normal file
114
target/linux/xburst/files-2.6.27/arch/mips/jz4740/board-virgo.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4740/board-virgo.c
|
||||
*
|
||||
* JZ4720 VIRGO board setup routines.
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <lhhuang@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/reboot.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
extern void (*jz_timer_callback)(void);
|
||||
|
||||
static void dancing(void)
|
||||
{
|
||||
static unsigned int count = 0;
|
||||
|
||||
count ++;
|
||||
count &= 1;
|
||||
if (count)
|
||||
__gpio_set_pin(GPIO_LED_EN);
|
||||
else
|
||||
__gpio_clear_pin(GPIO_LED_EN);
|
||||
}
|
||||
|
||||
static void virgo_timer_callback(void)
|
||||
{
|
||||
static unsigned long count = 0;
|
||||
|
||||
if ((++count) % 50 == 0) {
|
||||
dancing();
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init board_cpm_setup(void)
|
||||
{
|
||||
/* Stop unused module clocks here.
|
||||
* We have started all module clocks at arch/mips/jz4740/setup.c.
|
||||
*/
|
||||
}
|
||||
|
||||
static void __init board_gpio_setup(void)
|
||||
{
|
||||
/*
|
||||
* Most of the GPIO pins should have been initialized by the boot-loader
|
||||
*/
|
||||
|
||||
/*
|
||||
* Initialize MSC pins
|
||||
*/
|
||||
__gpio_as_msc();
|
||||
|
||||
/*
|
||||
* Initialize LCD pins
|
||||
*/
|
||||
// __gpio_as_lcd_18bit();
|
||||
|
||||
/*
|
||||
* Initialize SSI pins
|
||||
*/
|
||||
__gpio_as_ssi();
|
||||
|
||||
/*
|
||||
* Initialize I2C pins
|
||||
*/
|
||||
__gpio_as_i2c();
|
||||
|
||||
/*
|
||||
* Initialize Other pins
|
||||
*/
|
||||
__gpio_as_output(GPIO_SD_VCC_EN_N);
|
||||
__gpio_clear_pin(GPIO_SD_VCC_EN_N);
|
||||
|
||||
__gpio_as_input(GPIO_SD_CD_N);
|
||||
__gpio_disable_pull(GPIO_SD_CD_N);
|
||||
|
||||
// __gpio_as_input(GPIO_SD_WP);
|
||||
// __gpio_disable_pull(GPIO_SD_WP);
|
||||
|
||||
__gpio_as_input(GPIO_DC_DETE_N);
|
||||
// __gpio_as_input(GPIO_CHARG_STAT_N);
|
||||
__gpio_as_input(GPIO_USB_DETE);
|
||||
|
||||
__gpio_as_output(GPIO_DISP_OFF_N);
|
||||
|
||||
// __gpio_as_output(GPIO_LED_EN);
|
||||
}
|
||||
|
||||
void __init jz_board_setup(void)
|
||||
{
|
||||
printk("JZ4720 VIRGO board setup\n");
|
||||
|
||||
board_cpm_setup();
|
||||
board_gpio_setup();
|
||||
|
||||
jz_timer_callback = virgo_timer_callback;
|
||||
}
|
||||
602
target/linux/xburst/files-2.6.27/arch/mips/jz4740/cpufreq.c
Normal file
602
target/linux/xburst/files-2.6.27/arch/mips/jz4740/cpufreq.c
Normal file
@@ -0,0 +1,602 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4740/cpufreq.c
|
||||
*
|
||||
* cpufreq driver for JZ4740
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <lhhuang@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <linux/cpufreq.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
|
||||
"cpufreq-jz4740", msg)
|
||||
|
||||
#undef CHANGE_PLL
|
||||
|
||||
#define PLL_UNCHANGED 0
|
||||
#define PLL_GOES_UP 1
|
||||
#define PLL_GOES_DOWN 2
|
||||
|
||||
#define PLL_WAIT_500NS (500*(__cpm_get_cclk()/1000000000))
|
||||
|
||||
/* Saved the boot-time parameters */
|
||||
static struct {
|
||||
/* SDRAM parameters */
|
||||
unsigned int mclk; /* memory clock, KHz */
|
||||
unsigned int tras; /* RAS pulse width, cycles of mclk */
|
||||
unsigned int rcd; /* RAS to CAS Delay, cycles of mclk */
|
||||
unsigned int tpc; /* RAS Precharge time, cycles of mclk */
|
||||
unsigned int trwl; /* Write Precharge Time, cycles of mclk */
|
||||
unsigned int trc; /* RAS Cycle Time, cycles of mclk */
|
||||
unsigned int rtcor; /* Refresh Time Constant */
|
||||
unsigned int sdram_initialized;
|
||||
|
||||
/* LCD parameters */
|
||||
unsigned int lcd_clk; /* LCD clock, Hz */
|
||||
unsigned int lcdpix_clk; /* LCD Pixel clock, Hz */
|
||||
unsigned int lcd_clks_initialized;
|
||||
} boot_config;
|
||||
|
||||
struct jz4740_freq_percpu_info {
|
||||
struct cpufreq_frequency_table table[7];
|
||||
};
|
||||
|
||||
static struct jz4740_freq_percpu_info jz4740_freq_table;
|
||||
|
||||
/*
|
||||
* This contains the registers value for an operating point.
|
||||
* If only part of a register needs to change then there is
|
||||
* a mask value for that register.
|
||||
* When going to a new operating point the current register
|
||||
* value is ANDed with the ~mask and ORed with the new value.
|
||||
*/
|
||||
struct dpm_regs {
|
||||
u32 cpccr; /* Clock Freq Control Register */
|
||||
u32 cpccr_mask; /* Clock Freq Control Register mask */
|
||||
u32 cppcr; /* PLL1 Control Register */
|
||||
u32 cppcr_mask; /* PLL1 Control Register mask */
|
||||
u32 pll_up_flag; /* New PLL freq is higher than current or not */
|
||||
};
|
||||
|
||||
extern jz_clocks_t jz_clocks;
|
||||
|
||||
static void jz_update_clocks(void)
|
||||
{
|
||||
/* Next clocks must be updated if we have changed
|
||||
* the PLL or divisors.
|
||||
*/
|
||||
jz_clocks.cclk = __cpm_get_cclk();
|
||||
jz_clocks.hclk = __cpm_get_hclk();
|
||||
jz_clocks.mclk = __cpm_get_mclk();
|
||||
jz_clocks.pclk = __cpm_get_pclk();
|
||||
jz_clocks.lcdclk = __cpm_get_lcdclk();
|
||||
jz_clocks.pixclk = __cpm_get_pixclk();
|
||||
jz_clocks.i2sclk = __cpm_get_i2sclk();
|
||||
jz_clocks.usbclk = __cpm_get_usbclk();
|
||||
jz_clocks.mscclk = __cpm_get_mscclk();
|
||||
}
|
||||
|
||||
static void
|
||||
jz_init_boot_config(void)
|
||||
{
|
||||
if (!boot_config.lcd_clks_initialized) {
|
||||
/* the first time to scale pll */
|
||||
boot_config.lcd_clk = __cpm_get_lcdclk();
|
||||
boot_config.lcdpix_clk = __cpm_get_pixclk();
|
||||
boot_config.lcd_clks_initialized = 1;
|
||||
}
|
||||
|
||||
if (!boot_config.sdram_initialized) {
|
||||
/* the first time to scale frequencies */
|
||||
unsigned int dmcr, rtcor;
|
||||
unsigned int tras, rcd, tpc, trwl, trc;
|
||||
|
||||
dmcr = REG_EMC_DMCR;
|
||||
rtcor = REG_EMC_RTCOR;
|
||||
|
||||
tras = (dmcr >> 13) & 0x7;
|
||||
rcd = (dmcr >> 11) & 0x3;
|
||||
tpc = (dmcr >> 8) & 0x7;
|
||||
trwl = (dmcr >> 5) & 0x3;
|
||||
trc = (dmcr >> 2) & 0x7;
|
||||
|
||||
boot_config.mclk = __cpm_get_mclk() / 1000;
|
||||
boot_config.tras = tras + 4;
|
||||
boot_config.rcd = rcd + 1;
|
||||
boot_config.tpc = tpc + 1;
|
||||
boot_config.trwl = trwl + 1;
|
||||
boot_config.trc = trc * 2 + 1;
|
||||
boot_config.rtcor = rtcor;
|
||||
|
||||
boot_config.sdram_initialized = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void jz_update_dram_rtcor(unsigned int new_mclk)
|
||||
{
|
||||
unsigned int rtcor;
|
||||
|
||||
new_mclk /= 1000;
|
||||
rtcor = boot_config.rtcor * new_mclk / boot_config.mclk;
|
||||
rtcor--;
|
||||
|
||||
if (rtcor < 1) rtcor = 1;
|
||||
if (rtcor > 255) rtcor = 255;
|
||||
|
||||
REG_EMC_RTCOR = rtcor;
|
||||
REG_EMC_RTCNT = rtcor;
|
||||
}
|
||||
|
||||
static void jz_update_dram_dmcr(unsigned int new_mclk)
|
||||
{
|
||||
unsigned int dmcr;
|
||||
unsigned int tras, rcd, tpc, trwl, trc;
|
||||
unsigned int valid_time, new_time; /* ns */
|
||||
|
||||
new_mclk /= 1000;
|
||||
tras = boot_config.tras * new_mclk / boot_config.mclk;
|
||||
rcd = boot_config.rcd * new_mclk / boot_config.mclk;
|
||||
tpc = boot_config.tpc * new_mclk / boot_config.mclk;
|
||||
trwl = boot_config.trwl * new_mclk / boot_config.mclk;
|
||||
trc = boot_config.trc * new_mclk / boot_config.mclk;
|
||||
|
||||
/* Validation checking */
|
||||
valid_time = (boot_config.tras * 1000000) / boot_config.mclk;
|
||||
new_time = (tras * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) tras += 1;
|
||||
|
||||
valid_time = (boot_config.rcd * 1000000) / boot_config.mclk;
|
||||
new_time = (rcd * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) rcd += 1;
|
||||
|
||||
valid_time = (boot_config.tpc * 1000000) / boot_config.mclk;
|
||||
new_time = (tpc * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) tpc += 1;
|
||||
|
||||
valid_time = (boot_config.trwl * 1000000) / boot_config.mclk;
|
||||
new_time = (trwl * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) trwl += 1;
|
||||
|
||||
valid_time = (boot_config.trc * 1000000) / boot_config.mclk;
|
||||
new_time = (trc * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) trc += 2;
|
||||
|
||||
tras = (tras < 4) ? 4: tras;
|
||||
tras = (tras > 11) ? 11: tras;
|
||||
tras -= 4;
|
||||
|
||||
rcd = (rcd < 1) ? 1: rcd;
|
||||
rcd = (rcd > 4) ? 4: rcd;
|
||||
rcd -= 1;
|
||||
|
||||
tpc = (tpc < 1) ? 1: tpc;
|
||||
tpc = (tpc > 8) ? 8: tpc;
|
||||
tpc -= 1;
|
||||
|
||||
trwl = (trwl < 1) ? 1: trwl;
|
||||
trwl = (trwl > 4) ? 4: trwl;
|
||||
trwl -= 1;
|
||||
|
||||
trc = (trc < 1) ? 1: trc;
|
||||
trc = (trc > 15) ? 15: trc;
|
||||
trc /= 2;
|
||||
|
||||
dmcr = REG_EMC_DMCR;
|
||||
|
||||
dmcr &= ~(EMC_DMCR_TRAS_MASK | EMC_DMCR_RCD_MASK | EMC_DMCR_TPC_MASK | EMC_DMCR_TRWL_MASK | EMC_DMCR_TRC_MASK);
|
||||
dmcr |= ((tras << EMC_DMCR_TRAS_BIT) | (rcd << EMC_DMCR_RCD_BIT) | (tpc << EMC_DMCR_TPC_BIT) | (trwl << EMC_DMCR_TRWL_BIT) | (trc << EMC_DMCR_TRC_BIT));
|
||||
|
||||
REG_EMC_DMCR = dmcr;
|
||||
}
|
||||
|
||||
static void jz_update_dram_prev(unsigned int cur_mclk, unsigned int new_mclk)
|
||||
{
|
||||
/* No risk, no fun: run with interrupts on! */
|
||||
if (new_mclk > cur_mclk) {
|
||||
/* We're going FASTER, so first update TRAS, RCD, TPC, TRWL
|
||||
* and TRC of DMCR before changing the frequency.
|
||||
*/
|
||||
jz_update_dram_dmcr(new_mclk);
|
||||
} else {
|
||||
/* We're going SLOWER: first update RTCOR value
|
||||
* before changing the frequency.
|
||||
*/
|
||||
jz_update_dram_rtcor(new_mclk);
|
||||
}
|
||||
}
|
||||
|
||||
static void jz_update_dram_post(unsigned int cur_mclk, unsigned int new_mclk)
|
||||
{
|
||||
/* No risk, no fun: run with interrupts on! */
|
||||
if (new_mclk > cur_mclk) {
|
||||
/* We're going FASTER, so update RTCOR
|
||||
* after changing the frequency
|
||||
*/
|
||||
jz_update_dram_rtcor(new_mclk);
|
||||
} else {
|
||||
/* We're going SLOWER: so update TRAS, RCD, TPC, TRWL
|
||||
* and TRC of DMCR after changing the frequency.
|
||||
*/
|
||||
jz_update_dram_dmcr(new_mclk);
|
||||
}
|
||||
}
|
||||
|
||||
static void jz_scale_divisors(struct dpm_regs *regs)
|
||||
{
|
||||
unsigned int cpccr;
|
||||
unsigned int cur_mclk, new_mclk;
|
||||
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
|
||||
unsigned int tmp = 0, wait = PLL_WAIT_500NS;
|
||||
|
||||
cpccr = REG_CPM_CPCCR;
|
||||
cpccr &= ~((unsigned long)regs->cpccr_mask);
|
||||
cpccr |= regs->cpccr;
|
||||
cpccr |= CPM_CPCCR_CE; /* update immediately */
|
||||
|
||||
cur_mclk = __cpm_get_mclk();
|
||||
new_mclk = __cpm_get_pllout() / div[(cpccr & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT];
|
||||
|
||||
/* Update some DRAM parameters before changing frequency */
|
||||
jz_update_dram_prev(cur_mclk, new_mclk);
|
||||
|
||||
/* update register to change the clocks.
|
||||
* align this code to a cache line.
|
||||
*/
|
||||
__asm__ __volatile__(
|
||||
".set noreorder\n\t"
|
||||
".align 5\n"
|
||||
"sw %1,0(%0)\n\t"
|
||||
"li %3,0\n\t"
|
||||
"1:\n\t"
|
||||
"bne %3,%2,1b\n\t"
|
||||
"addi %3, 1\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
".set reorder\n\t"
|
||||
:
|
||||
: "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp));
|
||||
|
||||
/* Update some other DRAM parameters after changing frequency */
|
||||
jz_update_dram_post(cur_mclk, new_mclk);
|
||||
}
|
||||
|
||||
#ifdef CHANGE_PLL
|
||||
/* Maintain the LCD clock and pixel clock */
|
||||
static void jz_scale_lcd_divisors(struct dpm_regs *regs)
|
||||
{
|
||||
unsigned int new_pll, new_lcd_div, new_lcdpix_div;
|
||||
unsigned int cpccr;
|
||||
unsigned int tmp = 0, wait = PLL_WAIT_500NS;
|
||||
|
||||
if (!boot_config.lcd_clks_initialized) return;
|
||||
|
||||
new_pll = __cpm_get_pllout();
|
||||
new_lcd_div = new_pll / boot_config.lcd_clk;
|
||||
new_lcdpix_div = new_pll / boot_config.lcdpix_clk;
|
||||
|
||||
if (new_lcd_div < 1)
|
||||
new_lcd_div = 1;
|
||||
if (new_lcd_div > 16)
|
||||
new_lcd_div = 16;
|
||||
|
||||
if (new_lcdpix_div < 1)
|
||||
new_lcdpix_div = 1;
|
||||
if (new_lcdpix_div > 512)
|
||||
new_lcdpix_div = 512;
|
||||
|
||||
// REG_CPM_CPCCR2 = new_lcdpix_div - 1;
|
||||
|
||||
cpccr = REG_CPM_CPCCR;
|
||||
cpccr &= ~CPM_CPCCR_LDIV_MASK;
|
||||
cpccr |= ((new_lcd_div - 1) << CPM_CPCCR_LDIV_BIT);
|
||||
cpccr |= CPM_CPCCR_CE; /* update immediately */
|
||||
|
||||
/* update register to change the clocks.
|
||||
* align this code to a cache line.
|
||||
*/
|
||||
__asm__ __volatile__(
|
||||
".set noreorder\n\t"
|
||||
".align 5\n"
|
||||
"sw %1,0(%0)\n\t"
|
||||
"li %3,0\n\t"
|
||||
"1:\n\t"
|
||||
"bne %3,%2,1b\n\t"
|
||||
"addi %3, 1\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
".set reorder\n\t"
|
||||
:
|
||||
: "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp));
|
||||
}
|
||||
|
||||
static void jz_scale_pll(struct dpm_regs *regs)
|
||||
{
|
||||
unsigned int cppcr;
|
||||
unsigned int cur_mclk, new_mclk, new_pll;
|
||||
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
|
||||
int od[] = {1, 2, 2, 4};
|
||||
|
||||
cppcr = REG_CPM_CPPCR;
|
||||
cppcr &= ~(regs->cppcr_mask | CPM_CPPCR_PLLS | CPM_CPPCR_PLLEN | CPM_CPPCR_PLLST_MASK);
|
||||
regs->cppcr &= ~CPM_CPPCR_PLLEN;
|
||||
cppcr |= (regs->cppcr | 0xff);
|
||||
|
||||
/* Update some DRAM parameters before changing frequency */
|
||||
new_pll = JZ_EXTAL * ((cppcr>>23)+2) / ((((cppcr>>18)&0x1f)+2) * od[(cppcr>>16)&0x03]);
|
||||
cur_mclk = __cpm_get_mclk();
|
||||
new_mclk = new_pll / div[(REG_CPM_CPCCR>>CPM_CPCCR_MDIV_BIT) & 0xf];
|
||||
|
||||
/*
|
||||
* Update some SDRAM parameters
|
||||
*/
|
||||
jz_update_dram_prev(cur_mclk, new_mclk);
|
||||
|
||||
/*
|
||||
* Update PLL, align code to cache line.
|
||||
*/
|
||||
cppcr |= CPM_CPPCR_PLLEN;
|
||||
__asm__ __volatile__(
|
||||
".set noreorder\n\t"
|
||||
".align 5\n"
|
||||
"sw %1,0(%0)\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
".set reorder\n\t"
|
||||
:
|
||||
: "r" (CPM_CPPCR), "r" (cppcr));
|
||||
|
||||
/* Update some other DRAM parameters after changing frequency */
|
||||
jz_update_dram_post(cur_mclk, new_mclk);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void jz4740_transition(struct dpm_regs *regs)
|
||||
{
|
||||
/*
|
||||
* Get and save some boot-time conditions.
|
||||
*/
|
||||
jz_init_boot_config();
|
||||
|
||||
#ifdef CHANGE_PLL
|
||||
/*
|
||||
* Disable LCD before scaling pll.
|
||||
* LCD and LCD pixel clocks should not be changed even if the PLL
|
||||
* output frequency has been changed.
|
||||
*/
|
||||
REG_LCD_CTRL &= ~LCD_CTRL_ENA;
|
||||
|
||||
/*
|
||||
* Stop module clocks before scaling PLL
|
||||
*/
|
||||
__cpm_stop_eth();
|
||||
__cpm_stop_aic(1);
|
||||
__cpm_stop_aic(2);
|
||||
#endif
|
||||
|
||||
/* ... add more as necessary */
|
||||
|
||||
if (regs->pll_up_flag == PLL_GOES_UP) {
|
||||
/* the pll frequency is going up, so change dividors first */
|
||||
jz_scale_divisors(regs);
|
||||
#ifdef CHANGE_PLL
|
||||
jz_scale_pll(regs);
|
||||
#endif
|
||||
}
|
||||
else if (regs->pll_up_flag == PLL_GOES_DOWN) {
|
||||
/* the pll frequency is going down, so change pll first */
|
||||
#ifdef CHANGE_PLL
|
||||
jz_scale_pll(regs);
|
||||
#endif
|
||||
jz_scale_divisors(regs);
|
||||
}
|
||||
else {
|
||||
/* the pll frequency is unchanged, so change divisors only */
|
||||
jz_scale_divisors(regs);
|
||||
}
|
||||
|
||||
#ifdef CHANGE_PLL
|
||||
/*
|
||||
* Restart module clocks before scaling PLL
|
||||
*/
|
||||
__cpm_start_eth();
|
||||
__cpm_start_aic(1);
|
||||
__cpm_start_aic(2);
|
||||
|
||||
/* ... add more as necessary */
|
||||
|
||||
/* Scale the LCD divisors after scaling pll */
|
||||
if (regs->pll_up_flag != PLL_UNCHANGED) {
|
||||
jz_scale_lcd_divisors(regs);
|
||||
}
|
||||
|
||||
/* Enable LCD controller */
|
||||
REG_LCD_CTRL &= ~LCD_CTRL_DIS;
|
||||
REG_LCD_CTRL |= LCD_CTRL_ENA;
|
||||
#endif
|
||||
|
||||
/* Update system clocks */
|
||||
jz_update_clocks();
|
||||
}
|
||||
|
||||
extern unsigned int idle_times;
|
||||
static unsigned int jz4740_freq_get(unsigned int cpu)
|
||||
{
|
||||
return (__cpm_get_cclk() / 1000);
|
||||
}
|
||||
|
||||
static unsigned int index_to_divisor(unsigned int index, struct dpm_regs *regs)
|
||||
{
|
||||
int n2FR[33] = {
|
||||
0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0,
|
||||
7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
|
||||
9
|
||||
};
|
||||
int div[4] = {1, 2, 2, 2}; /* divisors of I:S:P:M */
|
||||
unsigned int div_of_cclk, new_freq, i;
|
||||
|
||||
regs->pll_up_flag = PLL_UNCHANGED;
|
||||
regs->cpccr_mask = CPM_CPCCR_CDIV_MASK | CPM_CPCCR_HDIV_MASK | CPM_CPCCR_PDIV_MASK | CPM_CPCCR_MDIV_MASK;
|
||||
|
||||
new_freq = jz4740_freq_table.table[index].frequency;
|
||||
|
||||
do {
|
||||
div_of_cclk = __cpm_get_pllout() / (1000 * new_freq);
|
||||
} while (div_of_cclk==0);
|
||||
|
||||
if(div_of_cclk == 1 || div_of_cclk == 2 || div_of_cclk == 4) {
|
||||
for(i = 1; i<4; i++) {
|
||||
div[i] = 3;
|
||||
}
|
||||
} else {
|
||||
for(i = 1; i<4; i++) {
|
||||
div[i] = 2;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i<4; i++) {
|
||||
div[i] *= div_of_cclk;
|
||||
}
|
||||
|
||||
dprintk("divisors of I:S:P:M = %d:%d:%d:%d\n", div[0], div[1], div[2], div[3]);
|
||||
|
||||
regs->cpccr =
|
||||
(n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) |
|
||||
(n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) |
|
||||
(n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) |
|
||||
(n2FR[div[3]] << CPM_CPCCR_MDIV_BIT);
|
||||
|
||||
return div_of_cclk;
|
||||
}
|
||||
|
||||
static void jz4740_set_cpu_divider_index(unsigned int cpu, unsigned int index)
|
||||
{
|
||||
unsigned long divisor, old_divisor;
|
||||
struct cpufreq_freqs freqs;
|
||||
struct dpm_regs regs;
|
||||
|
||||
old_divisor = __cpm_get_pllout() / __cpm_get_cclk();
|
||||
divisor = index_to_divisor(index, ®s);
|
||||
|
||||
freqs.old = __cpm_get_cclk() / 1000;
|
||||
freqs.new = __cpm_get_pllout() / (1000 * divisor);
|
||||
freqs.cpu = cpu;
|
||||
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
|
||||
if (old_divisor != divisor)
|
||||
jz4740_transition(®s);
|
||||
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
}
|
||||
|
||||
static int jz4740_freq_target(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation)
|
||||
{
|
||||
unsigned int new_index = 0;
|
||||
|
||||
if (cpufreq_frequency_table_target(policy,
|
||||
&jz4740_freq_table.table[0],
|
||||
target_freq, relation, &new_index))
|
||||
return -EINVAL;
|
||||
|
||||
jz4740_set_cpu_divider_index(policy->cpu, new_index);
|
||||
|
||||
dprintk("new frequency is %d KHz (REG_CPM_CPCCR:0x%x)\n", __cpm_get_cclk() / 1000, REG_CPM_CPCCR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jz4740_freq_verify(struct cpufreq_policy *policy)
|
||||
{
|
||||
return cpufreq_frequency_table_verify(policy,
|
||||
&jz4740_freq_table.table[0]);
|
||||
}
|
||||
|
||||
static int __init jz4740_cpufreq_driver_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
|
||||
struct cpufreq_frequency_table *table = &jz4740_freq_table.table[0];
|
||||
unsigned int MAX_FREQ;
|
||||
|
||||
dprintk(KERN_INFO "Jz4740 cpufreq driver\n");
|
||||
|
||||
if (policy->cpu != 0)
|
||||
return -EINVAL;
|
||||
|
||||
policy->cur = MAX_FREQ = __cpm_get_cclk() / 1000; /* in kHz. Current and max frequency is determined by u-boot */
|
||||
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
|
||||
|
||||
policy->cpuinfo.min_freq = MAX_FREQ/8;
|
||||
policy->cpuinfo.max_freq = MAX_FREQ;
|
||||
policy->cpuinfo.transition_latency = 100000; /* in 10^(-9) s = nanoseconds */
|
||||
|
||||
table[0].index = 0;
|
||||
table[0].frequency = MAX_FREQ/8;
|
||||
table[1].index = 1;
|
||||
table[1].frequency = MAX_FREQ/6;
|
||||
table[2].index = 2;
|
||||
table[2].frequency = MAX_FREQ/4;
|
||||
table[3].index = 3;
|
||||
table[3].frequency = MAX_FREQ/3;
|
||||
table[4].index = 4;
|
||||
table[4].frequency = MAX_FREQ/2;
|
||||
table[5].index = 5;
|
||||
table[5].frequency = MAX_FREQ;
|
||||
table[6].index = 6;
|
||||
table[6].frequency = CPUFREQ_TABLE_END;
|
||||
|
||||
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
|
||||
cpufreq_frequency_table_get_attr(table, policy->cpu); /* for showing /sys/devices/system/cpu/cpuX/cpufreq/stats/ */
|
||||
#endif
|
||||
|
||||
return cpufreq_frequency_table_cpuinfo(policy, table);
|
||||
}
|
||||
|
||||
static struct cpufreq_driver cpufreq_jz4740_driver = {
|
||||
// .flags = CPUFREQ_STICKY,
|
||||
.init = jz4740_cpufreq_driver_init,
|
||||
.verify = jz4740_freq_verify,
|
||||
.target = jz4740_freq_target,
|
||||
.get = jz4740_freq_get,
|
||||
.name = "jz4740",
|
||||
};
|
||||
|
||||
static int __init jz4740_cpufreq_init(void)
|
||||
{
|
||||
return cpufreq_register_driver(&cpufreq_jz4740_driver);
|
||||
}
|
||||
|
||||
static void __exit jz4740_cpufreq_exit(void)
|
||||
{
|
||||
cpufreq_unregister_driver(&cpufreq_jz4740_driver);
|
||||
}
|
||||
|
||||
module_init(jz4740_cpufreq_init);
|
||||
module_exit(jz4740_cpufreq_exit);
|
||||
|
||||
MODULE_AUTHOR("Regen <lhhuang@ingenic.cn>");
|
||||
MODULE_DESCRIPTION("cpufreq driver for Jz4740");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
768
target/linux/xburst/files-2.6.27/arch/mips/jz4740/dma.c
Normal file
768
target/linux/xburst/files-2.6.27/arch/mips/jz4740/dma.c
Normal file
@@ -0,0 +1,768 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4740/dma.c
|
||||
*
|
||||
* Support functions for the JZ4740 internal DMA channels.
|
||||
* No-descriptor transfer only.
|
||||
* Descriptor transfer should also call jz_request_dma() to get a free
|
||||
* channel and call jz_free_dma() to free the channel. And driver should
|
||||
* build the DMA descriptor and setup the DMA channel by itself.
|
||||
*
|
||||
* Copyright (C) 2006 Ingenic Semiconductor Inc.
|
||||
*
|
||||
* 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/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/soundcard.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/*
|
||||
* A note on resource allocation:
|
||||
*
|
||||
* All drivers needing DMA channels, should allocate and release them
|
||||
* through the public routines `jz_request_dma()' and `jz_free_dma()'.
|
||||
*
|
||||
* In order to avoid problems, all processes should allocate resources in
|
||||
* the same sequence and release them in the reverse order.
|
||||
*
|
||||
* So, when allocating DMAs and IRQs, first allocate the DMA, then the IRQ.
|
||||
* When releasing them, first release the IRQ, then release the DMA. The
|
||||
* main reason for this order is that, if you are requesting the DMA buffer
|
||||
* done interrupt, you won't know the irq number until the DMA channel is
|
||||
* returned from jz_request_dma().
|
||||
*/
|
||||
|
||||
struct jz_dma_chan jz_dma_table[MAX_DMA_NUM] = {
|
||||
{dev_id:-1,},
|
||||
{dev_id:-1,},
|
||||
{dev_id:-1,},
|
||||
{dev_id:-1,},
|
||||
{dev_id:-1,},
|
||||
{dev_id:-1,},
|
||||
};
|
||||
|
||||
// Device FIFO addresses and default DMA modes
|
||||
static const struct {
|
||||
unsigned int fifo_addr;
|
||||
unsigned int dma_mode;
|
||||
unsigned int dma_source;
|
||||
} dma_dev_table[DMA_ID_MAX] = {
|
||||
{CPHYSADDR(UART0_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART0OUT},
|
||||
{CPHYSADDR(UART0_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART0IN},
|
||||
{CPHYSADDR(SSI_DR), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_SSIOUT},
|
||||
{CPHYSADDR(SSI_DR), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SSIIN},
|
||||
{CPHYSADDR(AIC_DR), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_AICOUT},
|
||||
{CPHYSADDR(AIC_DR), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_AICIN},
|
||||
{CPHYSADDR(MSC_TXFIFO), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_MSCOUT},
|
||||
{CPHYSADDR(MSC_RXFIFO), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_MSCIN},
|
||||
{0, DMA_AUTOINIT, DMAC_DRSR_RS_TCU},
|
||||
{0, DMA_AUTOINIT, DMAC_DRSR_RS_AUTO},
|
||||
{},
|
||||
};
|
||||
|
||||
|
||||
int jz_dma_read_proc(char *buf, char **start, off_t fpos,
|
||||
int length, int *eof, void *data)
|
||||
{
|
||||
int i, len = 0;
|
||||
struct jz_dma_chan *chan;
|
||||
|
||||
for (i = 0; i < MAX_DMA_NUM; i++) {
|
||||
if ((chan = get_dma_chan(i)) != NULL) {
|
||||
len += sprintf(buf + len, "%2d: %s\n",
|
||||
i, chan->dev_str);
|
||||
}
|
||||
}
|
||||
|
||||
if (fpos >= len) {
|
||||
*start = buf;
|
||||
*eof = 1;
|
||||
return 0;
|
||||
}
|
||||
*start = buf + fpos;
|
||||
if ((len -= fpos) > length)
|
||||
return length;
|
||||
*eof = 1;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
void dump_jz_dma_channel(unsigned int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan;
|
||||
|
||||
if (dmanr > MAX_DMA_NUM)
|
||||
return;
|
||||
chan = &jz_dma_table[dmanr];
|
||||
|
||||
printk("DMA%d Registers:\n", dmanr);
|
||||
printk(" DMACR = 0x%08x\n", REG_DMAC_DMACR);
|
||||
printk(" DSAR = 0x%08x\n", REG_DMAC_DSAR(dmanr));
|
||||
printk(" DTAR = 0x%08x\n", REG_DMAC_DTAR(dmanr));
|
||||
printk(" DTCR = 0x%08x\n", REG_DMAC_DTCR(dmanr));
|
||||
printk(" DRSR = 0x%08x\n", REG_DMAC_DRSR(dmanr));
|
||||
printk(" DCCSR = 0x%08x\n", REG_DMAC_DCCSR(dmanr));
|
||||
printk(" DCMD = 0x%08x\n", REG_DMAC_DCMD(dmanr));
|
||||
printk(" DDA = 0x%08x\n", REG_DMAC_DDA(dmanr));
|
||||
printk(" DMADBR = 0x%08x\n", REG_DMAC_DMADBR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* jz_request_dma - dynamically allcate an idle DMA channel to return
|
||||
* @dev_id: the specified dma device id or DMA_ID_RAW_SET
|
||||
* @dev_str: the specified dma device string name
|
||||
* @irqhandler: the irq handler, or NULL
|
||||
* @irqflags: the irq handler flags
|
||||
* @irq_dev_id: the irq handler device id for shared irq
|
||||
*
|
||||
* Finds a free channel, and binds the requested device to it.
|
||||
* Returns the allocated channel number, or negative on error.
|
||||
* Requests the DMA done IRQ if irqhandler != NULL.
|
||||
*
|
||||
*/
|
||||
/*int jz_request_dma(int dev_id, const char *dev_str,
|
||||
void (*irqhandler)(int, void *, struct pt_regs *),
|
||||
unsigned long irqflags,
|
||||
void *irq_dev_id)
|
||||
*/
|
||||
|
||||
int jz_request_dma(int dev_id, const char *dev_str,
|
||||
irqreturn_t (*irqhandler)(int, void *),
|
||||
unsigned long irqflags,
|
||||
void *irq_dev_id)
|
||||
{
|
||||
struct jz_dma_chan *chan;
|
||||
int i, ret;
|
||||
|
||||
if (dev_id < 0 || dev_id >= DMA_ID_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < MAX_DMA_NUM; i++) {
|
||||
if (jz_dma_table[i].dev_id < 0)
|
||||
break;
|
||||
}
|
||||
if (i == MAX_DMA_NUM) /* no free channel */
|
||||
return -ENODEV;
|
||||
|
||||
/* we got a free channel */
|
||||
chan = &jz_dma_table[i];
|
||||
|
||||
if (irqhandler) {
|
||||
chan->irq = IRQ_DMA_0 + i; // allocate irq number
|
||||
chan->irq_dev = irq_dev_id;
|
||||
if ((ret = request_irq(chan->irq, irqhandler, irqflags,
|
||||
dev_str, chan->irq_dev))) {
|
||||
chan->irq = -1;
|
||||
chan->irq_dev = NULL;
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
chan->irq = -1;
|
||||
chan->irq_dev = NULL;
|
||||
}
|
||||
|
||||
// fill it in
|
||||
chan->io = i;
|
||||
chan->dev_id = dev_id;
|
||||
chan->dev_str = dev_str;
|
||||
chan->fifo_addr = dma_dev_table[dev_id].fifo_addr;
|
||||
chan->mode = dma_dev_table[dev_id].dma_mode;
|
||||
chan->source = dma_dev_table[dev_id].dma_source;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void jz_free_dma(unsigned int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan) {
|
||||
printk("Trying to free DMA%d\n", dmanr);
|
||||
return;
|
||||
}
|
||||
|
||||
disable_dma(dmanr);
|
||||
if (chan->irq)
|
||||
free_irq(chan->irq, chan->irq_dev);
|
||||
|
||||
chan->irq = -1;
|
||||
chan->irq_dev = NULL;
|
||||
chan->dev_id = -1;
|
||||
}
|
||||
|
||||
void jz_set_dma_dest_width(int dmanr, int nbit)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
chan->mode &= ~DMAC_DCMD_DWDH_MASK;
|
||||
switch (nbit) {
|
||||
case 8:
|
||||
chan->mode |= DMAC_DCMD_DWDH_8;
|
||||
break;
|
||||
case 16:
|
||||
chan->mode |= DMAC_DCMD_DWDH_16;
|
||||
break;
|
||||
case 32:
|
||||
chan->mode |= DMAC_DCMD_DWDH_32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void jz_set_dma_src_width(int dmanr, int nbit)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
chan->mode &= ~DMAC_DCMD_SWDH_MASK;
|
||||
switch (nbit) {
|
||||
case 8:
|
||||
chan->mode |= DMAC_DCMD_SWDH_8;
|
||||
break;
|
||||
case 16:
|
||||
chan->mode |= DMAC_DCMD_SWDH_16;
|
||||
break;
|
||||
case 32:
|
||||
chan->mode |= DMAC_DCMD_SWDH_32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void jz_set_dma_block_size(int dmanr, int nbyte)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
chan->mode &= ~DMAC_DCMD_DS_MASK;
|
||||
switch (nbyte) {
|
||||
case 1:
|
||||
chan->mode |= DMAC_DCMD_DS_8BIT;
|
||||
break;
|
||||
case 2:
|
||||
chan->mode |= DMAC_DCMD_DS_16BIT;
|
||||
break;
|
||||
case 4:
|
||||
chan->mode |= DMAC_DCMD_DS_32BIT;
|
||||
break;
|
||||
case 16:
|
||||
chan->mode |= DMAC_DCMD_DS_16BYTE;
|
||||
break;
|
||||
case 32:
|
||||
chan->mode |= DMAC_DCMD_DS_32BYTE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int jz_get_dma_command(int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
return chan->mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* jz_set_dma_mode - do the raw settings for the specified DMA channel
|
||||
* @dmanr: the specified DMA channel
|
||||
* @mode: dma operate mode, DMA_MODE_READ or DMA_MODE_WRITE
|
||||
* @dma_mode: dma raw mode
|
||||
* @dma_source: dma raw request source
|
||||
* @fifo_addr: dma raw device fifo address
|
||||
*
|
||||
* Ensure call jz_request_dma(DMA_ID_RAW_SET, ...) first, then call
|
||||
* jz_set_dma_mode() rather than set_dma_mode() if you work with
|
||||
* and external request dma device.
|
||||
*
|
||||
* NOTE: Don not dynamically allocate dma channel if one external request
|
||||
* dma device will occupy this channel.
|
||||
*/
|
||||
int jz_set_dma_mode(unsigned int dmanr, unsigned int mode,
|
||||
unsigned int dma_mode, unsigned int dma_source,
|
||||
unsigned int fifo_addr)
|
||||
{
|
||||
int dev_id, i;
|
||||
struct jz_dma_chan *chan;
|
||||
|
||||
if (dmanr > MAX_DMA_NUM)
|
||||
return -ENODEV;
|
||||
for (i = 0; i < MAX_DMA_NUM; i++) {
|
||||
if (jz_dma_table[i].dev_id < 0)
|
||||
break;
|
||||
}
|
||||
if (i == MAX_DMA_NUM)
|
||||
return -ENODEV;
|
||||
|
||||
chan = &jz_dma_table[dmanr];
|
||||
dev_id = chan->dev_id;
|
||||
if (dev_id > 0) {
|
||||
printk(KERN_DEBUG "%s sets the allocated DMA channel %d!\n",
|
||||
__FUNCTION__, dmanr);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* clone it from the dynamically allocated. */
|
||||
if (i != dmanr) {
|
||||
chan->irq = jz_dma_table[i].irq;
|
||||
chan->irq_dev = jz_dma_table[i].irq_dev;
|
||||
chan->dev_str = jz_dma_table[i].dev_str;
|
||||
jz_dma_table[i].irq = 0;
|
||||
jz_dma_table[i].irq_dev = NULL;
|
||||
jz_dma_table[i].dev_id = -1;
|
||||
}
|
||||
chan->dev_id = DMA_ID_RAW_SET;
|
||||
chan->io = dmanr;
|
||||
chan->fifo_addr = fifo_addr;
|
||||
chan->mode = dma_mode;
|
||||
chan->source = dma_source;
|
||||
|
||||
set_dma_mode(dmanr, dma_mode);
|
||||
|
||||
return dmanr;
|
||||
}
|
||||
|
||||
void enable_dma(unsigned int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
REG_DMAC_DCCSR(dmanr) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR);
|
||||
REG_DMAC_DCCSR(dmanr) |= DMAC_DCCSR_NDES; /* No-descriptor transfer */
|
||||
__dmac_enable_channel(dmanr);
|
||||
if (chan->irq)
|
||||
__dmac_channel_enable_irq(dmanr);
|
||||
}
|
||||
|
||||
#define DMA_DISABLE_POLL 0x10000
|
||||
|
||||
void disable_dma(unsigned int dmanr)
|
||||
{
|
||||
int i;
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
if (!__dmac_channel_enabled(dmanr))
|
||||
return;
|
||||
|
||||
for (i = 0; i < DMA_DISABLE_POLL; i++)
|
||||
if (__dmac_channel_transmit_end_detected(dmanr))
|
||||
break;
|
||||
#if 0
|
||||
if (i == DMA_DISABLE_POLL)
|
||||
printk(KERN_INFO "disable_dma: poll expired!\n");
|
||||
#endif
|
||||
|
||||
__dmac_disable_channel(dmanr);
|
||||
if (chan->irq)
|
||||
__dmac_channel_disable_irq(dmanr);
|
||||
}
|
||||
|
||||
/* Note: DMA_MODE_MASK is simulated by sw */
|
||||
void set_dma_mode(unsigned int dmanr, unsigned int mode)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI);
|
||||
mode &= DMA_MODE_MASK;
|
||||
if (mode == DMA_MODE_READ) {
|
||||
chan->mode |= DMAC_DCMD_DAI;
|
||||
chan->mode &= ~DMAC_DCMD_SAI;
|
||||
} else if (mode == DMA_MODE_WRITE) {
|
||||
chan->mode |= DMAC_DCMD_SAI;
|
||||
chan->mode &= ~DMAC_DCMD_DAI;
|
||||
} else {
|
||||
printk(KERN_DEBUG "set_dma_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n");
|
||||
}
|
||||
REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK;
|
||||
REG_DMAC_DRSR(chan->io) = chan->source;
|
||||
}
|
||||
|
||||
void set_dma_addr(unsigned int dmanr, unsigned int phyaddr)
|
||||
{
|
||||
unsigned int mode;
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
mode = chan->mode & DMA_MODE_MASK;
|
||||
if (mode == DMA_MODE_READ) {
|
||||
REG_DMAC_DSAR(chan->io) = chan->fifo_addr;
|
||||
REG_DMAC_DTAR(chan->io) = phyaddr;
|
||||
} else if (mode == DMA_MODE_WRITE) {
|
||||
REG_DMAC_DSAR(chan->io) = phyaddr;
|
||||
REG_DMAC_DTAR(chan->io) = chan->fifo_addr;
|
||||
} else
|
||||
printk(KERN_DEBUG "Driver should call set_dma_mode() ahead set_dma_addr()!\n");
|
||||
}
|
||||
|
||||
void set_dma_count(unsigned int dmanr, unsigned int bytecnt)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
int dma_ds[] = {4, 1, 2, 16, 32};
|
||||
unsigned int ds;
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT;
|
||||
REG_DMAC_DTCR(chan->io) = bytecnt / dma_ds[ds]; // transfer count
|
||||
}
|
||||
|
||||
unsigned int get_dma_residue(unsigned int dmanr)
|
||||
{
|
||||
unsigned int count, ds;
|
||||
int dma_ds[] = {4, 1, 2, 16, 32};
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
if (!chan)
|
||||
return 0;
|
||||
|
||||
ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT;
|
||||
count = REG_DMAC_DTCR(chan->io);
|
||||
count = count * dma_ds[ds];
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
switch (audio_fmt) {
|
||||
case AFMT_U8:
|
||||
/* burst mode : 32BIT */
|
||||
break;
|
||||
case AFMT_S16_LE:
|
||||
/* burst mode : 16BYTE */
|
||||
if (mode == DMA_MODE_READ) {
|
||||
chan->mode = DMA_AIC_32_16BYTE_RX_CMD | DMA_MODE_READ;
|
||||
chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI);
|
||||
mode &= DMA_MODE_MASK;
|
||||
chan->mode |= DMAC_DCMD_DAI;
|
||||
chan->mode &= ~DMAC_DCMD_SAI;
|
||||
} else if (mode == DMA_MODE_WRITE) {
|
||||
chan->mode = DMA_AIC_32_16BYTE_TX_CMD | DMA_MODE_WRITE;
|
||||
chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI);
|
||||
mode &= DMA_MODE_MASK;
|
||||
chan->mode |= DMAC_DCMD_SAI;
|
||||
chan->mode &= ~DMAC_DCMD_DAI;
|
||||
} else
|
||||
printk("oss_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n");
|
||||
|
||||
REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK;
|
||||
REG_DMAC_DRSR(chan->io) = chan->source;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
switch (audio_fmt) {
|
||||
case 8:
|
||||
/* SNDRV_PCM_FORMAT_S8 burst mode : 32BIT */
|
||||
break;
|
||||
case 16:
|
||||
/* SNDRV_PCM_FORMAT_S16_LE burst mode : 16BYTE */
|
||||
if (mode == DMA_MODE_READ) {
|
||||
chan->mode = DMA_AIC_16BYTE_RX_CMD | DMA_MODE_READ;
|
||||
chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI);
|
||||
mode &= DMA_MODE_MASK;
|
||||
chan->mode |= DMAC_DCMD_DAI;
|
||||
chan->mode &= ~DMAC_DCMD_SAI;
|
||||
} else if (mode == DMA_MODE_WRITE) {
|
||||
chan->mode = DMA_AIC_16BYTE_TX_CMD | DMA_MODE_WRITE;
|
||||
chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI);
|
||||
mode &= DMA_MODE_MASK;
|
||||
chan->mode |= DMAC_DCMD_SAI;
|
||||
chan->mode &= ~DMAC_DCMD_DAI;
|
||||
} else
|
||||
printk("alsa_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n");
|
||||
|
||||
REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK;
|
||||
REG_DMAC_DRSR(chan->io) = chan->source;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#undef JZ4740_DMAC_TEST_ENABLE
|
||||
|
||||
#ifdef JZ4740_DMAC_TEST_ENABLE
|
||||
|
||||
/*
|
||||
* DMA test: external address <--> external address
|
||||
*/
|
||||
#define TEST_DMA_SIZE 16*1024
|
||||
|
||||
static jz_dma_desc *dma_desc;
|
||||
|
||||
static int dma_chan;
|
||||
static dma_addr_t dma_desc_phys_addr;
|
||||
static unsigned int dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr;
|
||||
|
||||
static int dma_check_result(void *src, void *dst, int size)
|
||||
{
|
||||
unsigned int addr1, addr2, i, err = 0;
|
||||
|
||||
addr1 = (unsigned int)src;
|
||||
addr2 = (unsigned int)dst;
|
||||
|
||||
for (i = 0; i < size; i += 4) {
|
||||
if (*(volatile unsigned int *)addr1 != *(volatile unsigned int *)addr2) {
|
||||
err++;
|
||||
printk("wrong data at 0x%08x: src 0x%08x dst 0x%08x\n", addr2, *(volatile unsigned int *)addr1, *(volatile unsigned int *)addr2);
|
||||
}
|
||||
addr1 += 4;
|
||||
addr2 += 4;
|
||||
}
|
||||
printk("check DMA result err=%d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void jz4740_dma_irq(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
printk("jz4740_dma_irq %d\n", irq);
|
||||
|
||||
REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */
|
||||
|
||||
if (__dmac_channel_transmit_halt_detected(dma_chan)) {
|
||||
printk("DMA HALT\n");
|
||||
__dmac_channel_clear_transmit_halt(dma_chan);
|
||||
}
|
||||
|
||||
if (__dmac_channel_address_error_detected(dma_chan)) {
|
||||
printk("DMA ADDR ERROR\n");
|
||||
__dmac_channel_clear_address_error(dma_chan);
|
||||
}
|
||||
|
||||
if (__dmac_channel_descriptor_invalid_detected(dma_chan)) {
|
||||
printk("DMA DESC INVALID\n");
|
||||
__dmac_channel_clear_descriptor_invalid(dma_chan);
|
||||
}
|
||||
|
||||
if (__dmac_channel_count_terminated_detected(dma_chan)) {
|
||||
printk("DMA CT\n");
|
||||
__dmac_channel_clear_count_terminated(dma_chan);
|
||||
}
|
||||
|
||||
if (__dmac_channel_transmit_end_detected(dma_chan)) {
|
||||
printk("DMA TT\n");
|
||||
__dmac_channel_clear_transmit_end(dma_chan);
|
||||
dump_jz_dma_channel(dma_chan);
|
||||
dma_check_result((void *)dma_src_addr, (void *)dma_dst_addr, TEST_DMA_SIZE);
|
||||
}
|
||||
|
||||
/* free buffers */
|
||||
printk("free DMA buffers\n");
|
||||
free_pages(dma_src_addr, 2);
|
||||
free_pages(dma_dst_addr, 2);
|
||||
|
||||
if (dma_desc)
|
||||
free_pages((unsigned int)dma_desc, 0);
|
||||
|
||||
/* free dma */
|
||||
jz_free_dma(dma_chan);
|
||||
}
|
||||
|
||||
void dma_nodesc_test(void)
|
||||
{
|
||||
unsigned int addr, i;
|
||||
|
||||
printk("dma_nodesc_test\n");
|
||||
|
||||
/* Request DMA channel and setup irq handler */
|
||||
dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4740_dma_irq,
|
||||
SA_INTERRUPT, NULL);
|
||||
if (dma_chan < 0) {
|
||||
printk("Setup irq failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printk("Requested DMA channel = %d\n", dma_chan);
|
||||
|
||||
/* Allocate DMA buffers */
|
||||
dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */
|
||||
dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */
|
||||
|
||||
dma_src_phys_addr = CPHYSADDR(dma_src_addr);
|
||||
dma_dst_phys_addr = CPHYSADDR(dma_dst_addr);
|
||||
|
||||
printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n",
|
||||
dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr);
|
||||
|
||||
/* Prepare data for source buffer */
|
||||
addr = (unsigned int)dma_src_addr;
|
||||
for (i = 0; i < TEST_DMA_SIZE; i += 4) {
|
||||
*(volatile unsigned int *)addr = addr;
|
||||
addr += 4;
|
||||
}
|
||||
dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE);
|
||||
|
||||
/* Init target buffer */
|
||||
memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE);
|
||||
dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE);
|
||||
|
||||
/* Init DMA module */
|
||||
printk("Starting DMA\n");
|
||||
REG_DMAC_DMACR = 0;
|
||||
REG_DMAC_DCCSR(dma_chan) = 0;
|
||||
REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO;
|
||||
REG_DMAC_DSAR(dma_chan) = dma_src_phys_addr;
|
||||
REG_DMAC_DTAR(dma_chan) = dma_dst_phys_addr;
|
||||
REG_DMAC_DTCR(dma_chan) = 512;
|
||||
REG_DMAC_DCMD(dma_chan) = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TIE;
|
||||
REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_NDES | DMAC_DCCSR_EN;
|
||||
REG_DMAC_DMACR = DMAC_DMACR_DMAE; /* global DMA enable bit */
|
||||
|
||||
printk("DMA started. IMR=%08x\n", REG_INTC_IMR);
|
||||
}
|
||||
|
||||
void dma_desc_test(void)
|
||||
{
|
||||
unsigned int next, addr, i;
|
||||
static jz_dma_desc *desc;
|
||||
|
||||
printk("dma_desc_test\n");
|
||||
|
||||
/* Request DMA channel and setup irq handler */
|
||||
dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4740_dma_irq,
|
||||
SA_INTERRUPT, NULL);
|
||||
if (dma_chan < 0) {
|
||||
printk("Setup irq failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printk("Requested DMA channel = %d\n", dma_chan);
|
||||
|
||||
/* Allocate DMA buffers */
|
||||
dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */
|
||||
dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */
|
||||
|
||||
dma_src_phys_addr = CPHYSADDR(dma_src_addr);
|
||||
dma_dst_phys_addr = CPHYSADDR(dma_dst_addr);
|
||||
|
||||
printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n",
|
||||
dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr);
|
||||
|
||||
/* Prepare data for source buffer */
|
||||
addr = (unsigned int)dma_src_addr;
|
||||
for (i = 0; i < TEST_DMA_SIZE; i += 4) {
|
||||
*(volatile unsigned int *)addr = addr;
|
||||
addr += 4;
|
||||
}
|
||||
dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE);
|
||||
|
||||
/* Init target buffer */
|
||||
memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE);
|
||||
dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE);
|
||||
|
||||
/* Allocate DMA descriptors */
|
||||
dma_desc = (jz_dma_desc *)__get_free_pages(GFP_KERNEL, 0);
|
||||
dma_desc_phys_addr = CPHYSADDR((unsigned long)dma_desc);
|
||||
|
||||
printk("DMA descriptor address: 0x%08x 0x%08x\n", (u32)dma_desc, dma_desc_phys_addr);
|
||||
|
||||
/* Setup DMA descriptors */
|
||||
desc = dma_desc;
|
||||
next = (dma_desc_phys_addr + (sizeof(jz_dma_desc))) >> 4;
|
||||
|
||||
desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TM | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK;
|
||||
desc->dsadr = dma_src_phys_addr; /* DMA source address */
|
||||
desc->dtadr = dma_dst_phys_addr; /* DMA target address */
|
||||
desc->ddadr = (next << 24) + 128; /* size: 128*32 bytes = 4096 bytes */
|
||||
|
||||
desc++;
|
||||
next = (dma_desc_phys_addr + 2*(sizeof(jz_dma_desc))) >> 4;
|
||||
|
||||
desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK;
|
||||
desc->dsadr = dma_src_phys_addr + 4096; /* DMA source address */
|
||||
desc->dtadr = dma_dst_phys_addr + 4096; /* DMA target address */
|
||||
desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */
|
||||
|
||||
desc++;
|
||||
next = (dma_desc_phys_addr + 3*(sizeof(jz_dma_desc))) >> 4;
|
||||
|
||||
desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK;
|
||||
desc->dsadr = dma_src_phys_addr + 8192; /* DMA source address */
|
||||
desc->dtadr = dma_dst_phys_addr + 8192; /* DMA target address */
|
||||
desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */
|
||||
|
||||
desc++;
|
||||
next = (dma_desc_phys_addr + 4*(sizeof(jz_dma_desc))) >> 4;
|
||||
|
||||
desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE;
|
||||
desc->dsadr = dma_src_phys_addr + 12*1024; /* DMA source address */
|
||||
desc->dtadr = dma_dst_phys_addr + 12*1024; /* DMA target address */
|
||||
desc->ddadr = (next << 24) + 1024; /* size: 1024*4 bytes = 4096 bytes */
|
||||
|
||||
dma_cache_wback((unsigned long)dma_desc, 4*(sizeof(jz_dma_desc)));
|
||||
|
||||
/* Setup DMA descriptor address */
|
||||
REG_DMAC_DDA(dma_chan) = dma_desc_phys_addr;
|
||||
|
||||
/* Setup request source */
|
||||
REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO;
|
||||
|
||||
/* Setup DMA channel control/status register */
|
||||
REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_EN; /* descriptor transfer, clear status, start channel */
|
||||
|
||||
/* Enable DMA */
|
||||
REG_DMAC_DMACR = DMAC_DMACR_DMAE;
|
||||
|
||||
/* DMA doorbell set -- start DMA now ... */
|
||||
REG_DMAC_DMADBSR = 1 << dma_chan;
|
||||
|
||||
printk("DMA started. IMR=%08x\n", REG_INTC_IMR);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//EXPORT_SYMBOL_NOVERS(jz_dma_table);
|
||||
EXPORT_SYMBOL(jz_dma_table);
|
||||
EXPORT_SYMBOL(jz_request_dma);
|
||||
EXPORT_SYMBOL(jz_free_dma);
|
||||
EXPORT_SYMBOL(jz_set_dma_src_width);
|
||||
EXPORT_SYMBOL(jz_set_dma_dest_width);
|
||||
EXPORT_SYMBOL(jz_set_dma_block_size);
|
||||
EXPORT_SYMBOL(jz_set_dma_mode);
|
||||
EXPORT_SYMBOL(set_dma_mode);
|
||||
EXPORT_SYMBOL(jz_set_oss_dma);
|
||||
EXPORT_SYMBOL(jz_set_alsa_dma);
|
||||
EXPORT_SYMBOL(set_dma_addr);
|
||||
EXPORT_SYMBOL(set_dma_count);
|
||||
EXPORT_SYMBOL(get_dma_residue);
|
||||
EXPORT_SYMBOL(enable_dma);
|
||||
EXPORT_SYMBOL(disable_dma);
|
||||
EXPORT_SYMBOL(dump_jz_dma_channel);
|
||||
273
target/linux/xburst/files-2.6.27/arch/mips/jz4740/i2c.c
Normal file
273
target/linux/xburst/files-2.6.27/arch/mips/jz4740/i2c.c
Normal file
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4740/i2c.c
|
||||
*
|
||||
* Jz4740 I2C routines.
|
||||
*
|
||||
* Copyright (C) 2005,2006 Ingenic Semiconductor Inc.
|
||||
* Author: <lhhuang@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can distribute it and/or modify it
|
||||
* under the terms of the GNU General Public License (Version 2) as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/addrspace.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/* I2C protocol */
|
||||
#define I2C_READ 1
|
||||
#define I2C_WRITE 0
|
||||
|
||||
#define TIMEOUT 1000
|
||||
|
||||
/*
|
||||
* I2C bus protocol basic routines
|
||||
*/
|
||||
static int i2c_put_data(unsigned char data)
|
||||
{
|
||||
unsigned int timeout = TIMEOUT*10;
|
||||
|
||||
__i2c_write(data);
|
||||
__i2c_set_drf();
|
||||
while (__i2c_check_drf() != 0);
|
||||
while (!__i2c_transmit_ended());
|
||||
while (!__i2c_received_ack() && timeout)
|
||||
timeout--;
|
||||
|
||||
if (timeout)
|
||||
return 0;
|
||||
else
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_JZ_TPANEL_ATA2508
|
||||
static int i2c_put_data_nack(unsigned char data)
|
||||
{
|
||||
unsigned int timeout = TIMEOUT*10;
|
||||
|
||||
__i2c_write(data);
|
||||
__i2c_set_drf();
|
||||
while (__i2c_check_drf() != 0);
|
||||
while (!__i2c_transmit_ended());
|
||||
while (timeout--);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int i2c_get_data(unsigned char *data, int ack)
|
||||
{
|
||||
int timeout = TIMEOUT*10;
|
||||
|
||||
if (!ack)
|
||||
__i2c_send_nack();
|
||||
else
|
||||
__i2c_send_ack();
|
||||
|
||||
while (__i2c_check_drf() == 0 && timeout)
|
||||
timeout--;
|
||||
|
||||
if (timeout) {
|
||||
if (!ack)
|
||||
__i2c_send_stop();
|
||||
*data = __i2c_read();
|
||||
__i2c_clear_drf();
|
||||
return 0;
|
||||
} else
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/*
|
||||
* I2C interface
|
||||
*/
|
||||
void i2c_open(void)
|
||||
{
|
||||
__i2c_set_clk(jz_clocks.extalclk, 10000); /* default 10 KHz */
|
||||
__i2c_enable();
|
||||
}
|
||||
|
||||
void i2c_close(void)
|
||||
{
|
||||
udelay(300); /* wait for STOP goes over. */
|
||||
__i2c_disable();
|
||||
}
|
||||
|
||||
void i2c_setclk(unsigned int i2cclk)
|
||||
{
|
||||
__i2c_set_clk(jz_clocks.extalclk, i2cclk);
|
||||
}
|
||||
|
||||
int i2c_lseek(unsigned char device, unsigned char offset)
|
||||
{
|
||||
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
|
||||
goto device_err;
|
||||
if (i2c_put_data(offset) < 0)
|
||||
goto address_err;
|
||||
return 0;
|
||||
device_err:
|
||||
printk(KERN_DEBUG "No I2C device (0x%02x) installed.\n", device);
|
||||
__i2c_send_stop();
|
||||
return -ENODEV;
|
||||
address_err:
|
||||
printk(KERN_DEBUG "No I2C device (0x%02x) response.\n", device);
|
||||
__i2c_send_stop();
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
int i2c_read(unsigned char device, unsigned char *buf,
|
||||
unsigned char address, int count)
|
||||
{
|
||||
int cnt = count;
|
||||
int timeout = 5;
|
||||
|
||||
L_try_again:
|
||||
|
||||
if (timeout < 0)
|
||||
goto L_timeout;
|
||||
|
||||
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
|
||||
goto device_werr;
|
||||
if (i2c_put_data(address) < 0)
|
||||
goto address_err;
|
||||
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_READ ) < 0)
|
||||
goto device_rerr;
|
||||
__i2c_send_ack(); /* Master sends ACK for continue reading */
|
||||
while (cnt) {
|
||||
if (cnt == 1) {
|
||||
if (i2c_get_data(buf, 0) < 0)
|
||||
break;
|
||||
} else {
|
||||
if (i2c_get_data(buf, 1) < 0)
|
||||
break;
|
||||
}
|
||||
cnt--;
|
||||
buf++;
|
||||
}
|
||||
|
||||
__i2c_send_stop();
|
||||
return count - cnt;
|
||||
device_rerr:
|
||||
device_werr:
|
||||
address_err:
|
||||
timeout --;
|
||||
__i2c_send_stop();
|
||||
goto L_try_again;
|
||||
|
||||
L_timeout:
|
||||
__i2c_send_stop();
|
||||
printk("Read I2C device 0x%2x failed.\n", device);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int i2c_write(unsigned char device, unsigned char *buf,
|
||||
unsigned char address, int count)
|
||||
{
|
||||
int cnt = count;
|
||||
int cnt_in_pg;
|
||||
int timeout = 5;
|
||||
unsigned char *tmpbuf;
|
||||
unsigned char tmpaddr;
|
||||
|
||||
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
|
||||
|
||||
W_try_again:
|
||||
if (timeout < 0)
|
||||
goto W_timeout;
|
||||
|
||||
cnt = count;
|
||||
tmpbuf = (unsigned char *)buf;
|
||||
tmpaddr = address;
|
||||
|
||||
start_write_page:
|
||||
cnt_in_pg = 0;
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
|
||||
goto device_err;
|
||||
#ifdef CONFIG_JZ_TPANEL_ATA2508
|
||||
if (address == 0xff) {
|
||||
if (i2c_put_data_nack(tmpaddr) < 0)
|
||||
goto address_err;
|
||||
while (cnt) {
|
||||
if (++cnt_in_pg > 8) {
|
||||
__i2c_send_stop();
|
||||
mdelay(1);
|
||||
tmpaddr += 8;
|
||||
goto start_write_page;
|
||||
}
|
||||
if (i2c_put_data_nack(*tmpbuf) < 0)
|
||||
break;
|
||||
cnt--;
|
||||
tmpbuf++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if (i2c_put_data(tmpaddr) < 0)
|
||||
goto address_err;
|
||||
while (cnt) {
|
||||
if (++cnt_in_pg > 8) {
|
||||
__i2c_send_stop();
|
||||
mdelay(1);
|
||||
tmpaddr += 8;
|
||||
goto start_write_page;
|
||||
}
|
||||
if (i2c_put_data(*tmpbuf) < 0)
|
||||
break;
|
||||
cnt--;
|
||||
tmpbuf++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (i2c_put_data(tmpaddr) < 0)
|
||||
goto address_err;
|
||||
while (cnt) {
|
||||
if (++cnt_in_pg > 8) {
|
||||
__i2c_send_stop();
|
||||
mdelay(1);
|
||||
tmpaddr += 8;
|
||||
goto start_write_page;
|
||||
}
|
||||
if (i2c_put_data(*tmpbuf) < 0)
|
||||
break;
|
||||
cnt--;
|
||||
tmpbuf++;
|
||||
}
|
||||
#endif
|
||||
__i2c_send_stop();
|
||||
return count - cnt;
|
||||
device_err:
|
||||
address_err:
|
||||
timeout--;
|
||||
__i2c_send_stop();
|
||||
goto W_try_again;
|
||||
|
||||
W_timeout:
|
||||
printk(KERN_DEBUG "Write I2C device 0x%2x failed.\n", device);
|
||||
__i2c_send_stop();
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(i2c_open);
|
||||
EXPORT_SYMBOL(i2c_close);
|
||||
EXPORT_SYMBOL(i2c_setclk);
|
||||
EXPORT_SYMBOL(i2c_read);
|
||||
EXPORT_SYMBOL(i2c_write);
|
||||
265
target/linux/xburst/files-2.6.27/arch/mips/jz4740/irq.c
Normal file
265
target/linux/xburst/files-2.6.27/arch/mips/jz4740/irq.c
Normal file
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4740/irq.c
|
||||
*
|
||||
* JZ4740 interrupt routines.
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <lhhuang@ingenic.cn>
|
||||
*
|
||||
* 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/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/timex.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/*
|
||||
* INTC irq type
|
||||
*/
|
||||
|
||||
static void enable_intc_irq(unsigned int irq)
|
||||
{
|
||||
__intc_unmask_irq(irq);
|
||||
}
|
||||
|
||||
static void disable_intc_irq(unsigned int irq)
|
||||
{
|
||||
__intc_mask_irq(irq);
|
||||
}
|
||||
|
||||
static void mask_and_ack_intc_irq(unsigned int irq)
|
||||
{
|
||||
__intc_mask_irq(irq);
|
||||
__intc_ack_irq(irq);
|
||||
}
|
||||
|
||||
static void end_intc_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
|
||||
enable_intc_irq(irq);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int startup_intc_irq(unsigned int irq)
|
||||
{
|
||||
enable_intc_irq(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void shutdown_intc_irq(unsigned int irq)
|
||||
{
|
||||
disable_intc_irq(irq);
|
||||
}
|
||||
|
||||
static struct irq_chip intc_irq_type = {
|
||||
.typename = "INTC",
|
||||
.startup = startup_intc_irq,
|
||||
.shutdown = shutdown_intc_irq,
|
||||
.enable = enable_intc_irq,
|
||||
.disable = disable_intc_irq,
|
||||
.ack = mask_and_ack_intc_irq,
|
||||
.end = end_intc_irq,
|
||||
};
|
||||
|
||||
/*
|
||||
* GPIO irq type
|
||||
*/
|
||||
|
||||
static void enable_gpio_irq(unsigned int irq)
|
||||
{
|
||||
unsigned int intc_irq;
|
||||
|
||||
if (irq < (IRQ_GPIO_0 + 32)) {
|
||||
intc_irq = IRQ_GPIO0;
|
||||
}
|
||||
else if (irq < (IRQ_GPIO_0 + 64)) {
|
||||
intc_irq = IRQ_GPIO1;
|
||||
}
|
||||
else if (irq < (IRQ_GPIO_0 + 96)) {
|
||||
intc_irq = IRQ_GPIO2;
|
||||
}
|
||||
else {
|
||||
intc_irq = IRQ_GPIO3;
|
||||
}
|
||||
|
||||
enable_intc_irq(intc_irq);
|
||||
__gpio_unmask_irq(irq - IRQ_GPIO_0);
|
||||
}
|
||||
|
||||
static void disable_gpio_irq(unsigned int irq)
|
||||
{
|
||||
__gpio_mask_irq(irq - IRQ_GPIO_0);
|
||||
}
|
||||
|
||||
static void mask_and_ack_gpio_irq(unsigned int irq)
|
||||
{
|
||||
__gpio_mask_irq(irq - IRQ_GPIO_0);
|
||||
__gpio_ack_irq(irq - IRQ_GPIO_0);
|
||||
}
|
||||
|
||||
static void end_gpio_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
|
||||
enable_gpio_irq(irq);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int startup_gpio_irq(unsigned int irq)
|
||||
{
|
||||
enable_gpio_irq(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void shutdown_gpio_irq(unsigned int irq)
|
||||
{
|
||||
disable_gpio_irq(irq);
|
||||
}
|
||||
|
||||
static struct irq_chip gpio_irq_type = {
|
||||
.typename = "GPIO",
|
||||
.startup = startup_gpio_irq,
|
||||
.shutdown = shutdown_gpio_irq,
|
||||
.enable = enable_gpio_irq,
|
||||
.disable = disable_gpio_irq,
|
||||
.ack = mask_and_ack_gpio_irq,
|
||||
.end = end_gpio_irq,
|
||||
};
|
||||
|
||||
/*
|
||||
* DMA irq type
|
||||
*/
|
||||
|
||||
static void enable_dma_irq(unsigned int irq)
|
||||
{
|
||||
__intc_unmask_irq(IRQ_DMAC);
|
||||
__dmac_channel_enable_irq(irq - IRQ_DMA_0);
|
||||
}
|
||||
|
||||
static void disable_dma_irq(unsigned int irq)
|
||||
{
|
||||
__dmac_channel_disable_irq(irq - IRQ_DMA_0);
|
||||
}
|
||||
|
||||
static void mask_and_ack_dma_irq(unsigned int irq)
|
||||
{
|
||||
__intc_ack_irq(IRQ_DMAC);
|
||||
__dmac_channel_disable_irq(irq - IRQ_DMA_0);
|
||||
}
|
||||
|
||||
static void end_dma_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
|
||||
enable_dma_irq(irq);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int startup_dma_irq(unsigned int irq)
|
||||
{
|
||||
enable_dma_irq(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void shutdown_dma_irq(unsigned int irq)
|
||||
{
|
||||
disable_dma_irq(irq);
|
||||
}
|
||||
|
||||
static struct irq_chip dma_irq_type = {
|
||||
.typename = "DMA",
|
||||
.startup = startup_dma_irq,
|
||||
.shutdown = shutdown_dma_irq,
|
||||
.enable = enable_dma_irq,
|
||||
.disable = disable_dma_irq,
|
||||
.ack = mask_and_ack_dma_irq,
|
||||
.end = end_dma_irq,
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void __init arch_init_irq(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
clear_c0_status(0xff04); /* clear ERL */
|
||||
set_c0_status(0x0400); /* set IP2 */
|
||||
|
||||
/* Set up INTC irq
|
||||
*/
|
||||
for (i = 0; i < 32; i++) {
|
||||
disable_intc_irq(i);
|
||||
irq_desc[i].chip = &intc_irq_type;
|
||||
}
|
||||
|
||||
/* Set up DMAC irq
|
||||
*/
|
||||
for (i = 0; i < NUM_DMA; i++) {
|
||||
disable_dma_irq(IRQ_DMA_0 + i);
|
||||
irq_desc[IRQ_DMA_0 + i].chip = &dma_irq_type;
|
||||
}
|
||||
|
||||
/* Set up GPIO irq
|
||||
*/
|
||||
for (i = 0; i < NUM_GPIO; i++) {
|
||||
disable_gpio_irq(IRQ_GPIO_0 + i);
|
||||
irq_desc[IRQ_GPIO_0 + i].chip = &gpio_irq_type;
|
||||
}
|
||||
}
|
||||
|
||||
static int plat_real_irq(int irq)
|
||||
{
|
||||
switch (irq) {
|
||||
case IRQ_GPIO0:
|
||||
irq = __gpio_group_irq(0) + IRQ_GPIO_0;
|
||||
break;
|
||||
case IRQ_GPIO1:
|
||||
irq = __gpio_group_irq(1) + IRQ_GPIO_0 + 32;
|
||||
break;
|
||||
case IRQ_GPIO2:
|
||||
irq = __gpio_group_irq(2) + IRQ_GPIO_0 + 64;
|
||||
break;
|
||||
case IRQ_GPIO3:
|
||||
irq = __gpio_group_irq(3) + IRQ_GPIO_0 + 96;
|
||||
break;
|
||||
case IRQ_DMAC:
|
||||
irq = __dmac_get_irq() + IRQ_DMA_0;
|
||||
break;
|
||||
}
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
asmlinkage void plat_irq_dispatch(void)
|
||||
{
|
||||
int irq = 0;
|
||||
static unsigned long intc_ipr = 0;
|
||||
|
||||
intc_ipr |= REG_INTC_IPR;
|
||||
|
||||
if (!intc_ipr) return;
|
||||
|
||||
irq = ffs(intc_ipr) - 1;
|
||||
intc_ipr &= ~(1<<irq);
|
||||
|
||||
irq = plat_real_irq(irq);
|
||||
do_IRQ(irq);
|
||||
}
|
||||
169
target/linux/xburst/files-2.6.27/arch/mips/jz4740/platform.c
Normal file
169
target/linux/xburst/files-2.6.27/arch/mips/jz4740/platform.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Platform device support for Jz4740 SoC.
|
||||
*
|
||||
* Copyright 2007, <yliu@ingenic.cn>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/resource.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/* OHCI (USB full speed host controller) */
|
||||
static struct resource jz_usb_ohci_resources[] = {
|
||||
[0] = {
|
||||
.start = CPHYSADDR(UHC_BASE), // phys addr for ioremap
|
||||
.end = CPHYSADDR(UHC_BASE) + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_UHC,
|
||||
.end = IRQ_UHC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
/* The dmamask must be set for OHCI to work */
|
||||
static u64 ohci_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device jz_usb_ohci_device = {
|
||||
.name = "jz-ohci",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &ohci_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz_usb_ohci_resources),
|
||||
.resource = jz_usb_ohci_resources,
|
||||
};
|
||||
|
||||
/*** LCD controller ***/
|
||||
static struct resource jz_lcd_resources[] = {
|
||||
[0] = {
|
||||
.start = CPHYSADDR(LCD_BASE),
|
||||
.end = CPHYSADDR(LCD_BASE) + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_LCD,
|
||||
.end = IRQ_LCD,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
||||
static u64 jz_lcd_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device jz_lcd_device = {
|
||||
.name = "jz-lcd",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &jz_lcd_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz_lcd_resources),
|
||||
.resource = jz_lcd_resources,
|
||||
};
|
||||
|
||||
/* UDC (USB gadget controller) */
|
||||
static struct resource jz_usb_gdt_resources[] = {
|
||||
[0] = {
|
||||
.start = CPHYSADDR(UDC_BASE),
|
||||
.end = CPHYSADDR(UDC_BASE) + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_UDC,
|
||||
.end = IRQ_UDC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static u64 udc_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device jz_usb_gdt_device = {
|
||||
.name = "jz-udc",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &udc_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz_usb_gdt_resources),
|
||||
.resource = jz_usb_gdt_resources,
|
||||
};
|
||||
|
||||
/** MMC/SD controller **/
|
||||
static struct resource jz_mmc_resources[] = {
|
||||
[0] = {
|
||||
.start = CPHYSADDR(MSC_BASE),
|
||||
.end = CPHYSADDR(MSC_BASE) + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_MSC,
|
||||
.end = IRQ_MSC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
||||
static u64 jz_mmc_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device jz_mmc_device = {
|
||||
.name = "jz-mmc",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &jz_mmc_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz_mmc_resources),
|
||||
.resource = jz_mmc_resources,
|
||||
};
|
||||
|
||||
/** I2C controller **/
|
||||
static struct resource jz_i2c_resources[] = {
|
||||
[0] = {
|
||||
.start = CPHYSADDR(I2C_BASE),
|
||||
.end = CPHYSADDR(I2C_BASE) + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_I2C,
|
||||
.end = IRQ_I2C,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
||||
static u64 jz_i2c_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device jz_i2c_device = {
|
||||
.name = "jz_i2c",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &jz_i2c_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz_i2c_resources),
|
||||
.resource = jz_i2c_resources,
|
||||
};
|
||||
|
||||
/* All */
|
||||
static struct platform_device *jz_platform_devices[] __initdata = {
|
||||
&jz_usb_ohci_device,
|
||||
&jz_lcd_device,
|
||||
&jz_usb_gdt_device,
|
||||
&jz_mmc_device,
|
||||
&jz_i2c_device,
|
||||
};
|
||||
|
||||
static int __init jz_platform_init(void)
|
||||
{
|
||||
return platform_add_devices(jz_platform_devices, ARRAY_SIZE(jz_platform_devices));
|
||||
}
|
||||
|
||||
arch_initcall(jz_platform_init);
|
||||
410
target/linux/xburst/files-2.6.27/arch/mips/jz4740/pm.c
Normal file
410
target/linux/xburst/files-2.6.27/arch/mips/jz4740/pm.c
Normal file
@@ -0,0 +1,410 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4740/common/pm.c
|
||||
*
|
||||
* JZ4740 Power Management Routines
|
||||
*
|
||||
* Copyright (C) 2006 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can distribute it and/or modify it
|
||||
* under the terms of the GNU General Public License (Version 2) as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <asm/cacheops.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
#undef DEBUG
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
#define dprintk(x...) printk(x)
|
||||
#else
|
||||
#define dprintk(x...)
|
||||
#endif
|
||||
|
||||
#define GPIO_WAKEUP 125 /* set SW7(GPIO 125) as WAKEUP key */
|
||||
|
||||
/*
|
||||
* __gpio_as_sleep set all pins to pull-disable, and set all pins as input
|
||||
* except sdram, nand flash pins and the pins which can be used as CS1_N
|
||||
* to CS4_N for chip select.
|
||||
*/
|
||||
#define __gpio_as_sleep() \
|
||||
do { \
|
||||
REG_GPIO_PXFUNC(1) = ~0x9ff9ffff; \
|
||||
REG_GPIO_PXSELC(1) = ~0x9ff9ffff; \
|
||||
REG_GPIO_PXDIRC(1) = ~0x9ff9ffff; \
|
||||
REG_GPIO_PXPES(1) = 0xffffffff; \
|
||||
REG_GPIO_PXFUNC(2) = ~0x37000000; \
|
||||
REG_GPIO_PXSELC(2) = ~0x37000000; \
|
||||
REG_GPIO_PXDIRC(2) = ~0x37000000; \
|
||||
REG_GPIO_PXPES(2) = 0xffffffff; \
|
||||
REG_GPIO_PXFUNC(3) = 0xffffffff; \
|
||||
REG_GPIO_PXSELC(3) = 0xffffffff; \
|
||||
REG_GPIO_PXDIRC(3) = 0xffffffff; \
|
||||
REG_GPIO_PXPES(3) = 0xffffffff; \
|
||||
} while (0)
|
||||
|
||||
static int jz_pm_do_hibernate(void)
|
||||
{
|
||||
|
||||
/* Mask all interrupts */
|
||||
REG_INTC_IMSR = 0xffffffff;
|
||||
|
||||
/*
|
||||
* RTC Wakeup or 1Hz interrupt can be enabled or disabled
|
||||
* through RTC driver's ioctl (linux/driver/char/rtc_jz.c).
|
||||
*/
|
||||
|
||||
/* Set minimum wakeup_n pin low-level assertion time for wakeup: 100ms */
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
REG_RTC_HWFCR = (100 << RTC_HWFCR_BIT);
|
||||
|
||||
/* Set reset pin low-level assertion time after wakeup: must > 60ms */
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
REG_RTC_HRCR = (60 << RTC_HRCR_BIT); /* 60 ms */
|
||||
|
||||
/* Scratch pad register to be reserved */
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
REG_RTC_HSPR = 0x12345678;
|
||||
|
||||
/* clear wakeup status register */
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
REG_RTC_HWRSR = 0x0;
|
||||
|
||||
/* Put CPU to power down mode */
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
REG_RTC_HCR = RTC_HCR_PD;
|
||||
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
while(1);
|
||||
|
||||
/* We can't get here */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* NOTES:
|
||||
* 1: Pins that are floated (NC) should be set as input and pull-enable.
|
||||
* 2: Pins that are pull-up or pull-down by outside should be set as input
|
||||
* and pull-disable.
|
||||
* 3: Pins that are connected to a chip except sdram and nand flash
|
||||
* should be set as input and pull-disable, too.
|
||||
*/
|
||||
static void jz_board_do_sleep(unsigned long *ptr)
|
||||
{
|
||||
unsigned char i;
|
||||
|
||||
/* Print messages of GPIO registers for debug */
|
||||
for(i=0;i<4;i++) {
|
||||
dprintk("run dat:%x pin:%x fun:%x sel:%x dir:%x pull:%x msk:%x trg:%x\n", \
|
||||
REG_GPIO_PXDAT(i),REG_GPIO_PXPIN(i),REG_GPIO_PXFUN(i),REG_GPIO_PXSEL(i), \
|
||||
REG_GPIO_PXDIR(i),REG_GPIO_PXPE(i),REG_GPIO_PXIM(i),REG_GPIO_PXTRG(i));
|
||||
}
|
||||
|
||||
/* Save GPIO registers */
|
||||
for(i = 1; i < 4; i++) {
|
||||
*ptr++ = REG_GPIO_PXFUN(i);
|
||||
*ptr++ = REG_GPIO_PXSEL(i);
|
||||
*ptr++ = REG_GPIO_PXDIR(i);
|
||||
*ptr++ = REG_GPIO_PXPE(i);
|
||||
*ptr++ = REG_GPIO_PXIM(i);
|
||||
*ptr++ = REG_GPIO_PXDAT(i);
|
||||
*ptr++ = REG_GPIO_PXTRG(i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set all pins to pull-disable, and set all pins as input except
|
||||
* sdram, nand flash pins and the pins which can be used as CS1_N
|
||||
* to CS4_N for chip select.
|
||||
*/
|
||||
__gpio_as_sleep();
|
||||
|
||||
/*
|
||||
* Set proper status for GPB25 to GPB28 which can be used as CS1_N to CS4_N.
|
||||
* Keep the pins' function used for chip select(CS) here according to your
|
||||
* system to avoid chip select crashing with sdram when resuming from sleep mode.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_JZ4740_PAVO)
|
||||
/* GPB25/CS1_N is used as chip select for nand flash, shouldn't be change. */
|
||||
|
||||
/* GPB26/CS2_N is connected to nand flash, needn't be changed. */
|
||||
|
||||
/* GPB27/CS3_N is used as EXT_INT for CS8900 on debug board, it should be set as input.*/
|
||||
__gpio_as_input(32+27);
|
||||
|
||||
/* GPB28/CS4_N is used as cs8900's chip select, shouldn't be changed. */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Enable pull for NC pins here according to your system
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_JZ4740_PAVO)
|
||||
/* GPB30-27 <-> J1: WE_N RD_N CS4_N EXT_INT */
|
||||
for(i=27;i<31;i++) {
|
||||
__gpio_enable_pull(32+i);
|
||||
}
|
||||
|
||||
/* GPC27<-> WAIT_N */
|
||||
__gpio_enable_pull(32*2+27);
|
||||
|
||||
/* GPD16<->SD_WP; GPD13-10<->MSC_D0-3; GPD9<->MSC_CMD; GPD8<->MSC_CLK */
|
||||
__gpio_enable_pull(32*3+16);
|
||||
for(i=8;i<14;i++) {
|
||||
__gpio_enable_pull(32*3+i);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If you must set some GPIOs as output to high level or low level,
|
||||
* you can set them here, using:
|
||||
* __gpio_as_output(n);
|
||||
* __gpio_set_pin(n); or __gpio_clear_pin(n);
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_JZ4740_PAVO)
|
||||
/* GPD16 which is used as AMPEN_N should be set to high to disable audio amplifier */
|
||||
__gpio_set_pin(32*3+4);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Keep uart0 function for printing debug message */
|
||||
__gpio_as_uart0();
|
||||
|
||||
/* Print messages of GPIO registers for debug */
|
||||
for(i=0;i<4;i++) {
|
||||
dprintk("sleep dat:%x pin:%x fun:%x sel:%x dir:%x pull:%x msk:%x trg:%x\n", \
|
||||
REG_GPIO_PXDAT(i),REG_GPIO_PXPIN(i),REG_GPIO_PXFUN(i),REG_GPIO_PXSEL(i), \
|
||||
REG_GPIO_PXDIR(i),REG_GPIO_PXPE(i),REG_GPIO_PXIM(i),REG_GPIO_PXTRG(i));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void jz_board_do_resume(unsigned long *ptr)
|
||||
{
|
||||
unsigned char i;
|
||||
|
||||
/* Restore GPIO registers */
|
||||
for(i = 1; i < 4; i++) {
|
||||
REG_GPIO_PXFUNS(i) = *ptr;
|
||||
REG_GPIO_PXFUNC(i) = ~(*ptr++);
|
||||
|
||||
REG_GPIO_PXSELS(i) = *ptr;
|
||||
REG_GPIO_PXSELC(i) = ~(*ptr++);
|
||||
|
||||
REG_GPIO_PXDIRS(i) = *ptr;
|
||||
REG_GPIO_PXDIRC(i) = ~(*ptr++);
|
||||
|
||||
REG_GPIO_PXPES(i) = *ptr;
|
||||
REG_GPIO_PXPEC(i) = ~(*ptr++);
|
||||
|
||||
REG_GPIO_PXIMS(i)=*ptr;
|
||||
REG_GPIO_PXIMC(i)=~(*ptr++);
|
||||
|
||||
REG_GPIO_PXDATS(i)=*ptr;
|
||||
REG_GPIO_PXDATC(i)=~(*ptr++);
|
||||
|
||||
REG_GPIO_PXTRGS(i)=*ptr;
|
||||
REG_GPIO_PXTRGC(i)=~(*ptr++);
|
||||
}
|
||||
|
||||
/* Print messages of GPIO registers for debug */
|
||||
for(i=0;i<4;i++) {
|
||||
dprintk("resume dat:%x pin:%x fun:%x sel:%x dir:%x pull:%x msk:%x trg:%x\n", \
|
||||
REG_GPIO_PXDAT(i),REG_GPIO_PXPIN(i),REG_GPIO_PXFUN(i),REG_GPIO_PXSEL(i), \
|
||||
REG_GPIO_PXDIR(i),REG_GPIO_PXPE(i),REG_GPIO_PXIM(i),REG_GPIO_PXTRG(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int jz_pm_do_sleep(void)
|
||||
{
|
||||
unsigned long delta;
|
||||
unsigned long nfcsr = REG_EMC_NFCSR;
|
||||
unsigned long scr = REG_CPM_SCR;
|
||||
unsigned long imr = REG_INTC_IMR;
|
||||
unsigned long sadc = REG_SADC_ENA;
|
||||
unsigned long sleep_gpio_save[7*3];
|
||||
|
||||
/* Preserve current time */
|
||||
delta = xtime.tv_sec - REG_RTC_RSR;
|
||||
|
||||
/* Disable nand flash */
|
||||
REG_EMC_NFCSR = ~0xff;
|
||||
|
||||
/* stop sadc */
|
||||
REG_SADC_ENA &= ~0x7;
|
||||
while((REG_SADC_ENA & 0x7) != 0);
|
||||
udelay(100);
|
||||
|
||||
/*stop udc and usb*/
|
||||
REG_CPM_SCR &= ~( 1<<6 | 1<<7);
|
||||
REG_CPM_SCR |= 0<<6 | 1<<7;
|
||||
|
||||
/* Sleep on-board modules */
|
||||
jz_board_do_sleep(sleep_gpio_save);
|
||||
|
||||
/* Mask all interrupts */
|
||||
REG_INTC_IMSR = 0xffffffff;
|
||||
|
||||
/* Just allow following interrupts to wakeup the system.
|
||||
* Note: modify this according to your system.
|
||||
*/
|
||||
|
||||
/* enable RTC alarm */
|
||||
__intc_unmask_irq(IRQ_RTC);
|
||||
#if 0
|
||||
/* make system wake up after n seconds by RTC alarm */
|
||||
unsigned int v, n;
|
||||
n = 10;
|
||||
while (!__rtc_write_ready());
|
||||
__rtc_enable_alarm();
|
||||
while (!__rtc_write_ready());
|
||||
__rtc_enable_alarm_irq();
|
||||
while (!__rtc_write_ready());
|
||||
v = __rtc_get_second();
|
||||
while (!__rtc_write_ready());
|
||||
__rtc_set_alarm_second(v+n);
|
||||
#endif
|
||||
|
||||
/* WAKEUP key */
|
||||
__gpio_as_irq_rise_edge(GPIO_WAKEUP);
|
||||
__gpio_unmask_irq(GPIO_WAKEUP);
|
||||
__intc_unmask_irq(IRQ_GPIO3); /* IRQ_GPIOn depends on GPIO_WAKEUP */
|
||||
|
||||
/* Enter SLEEP mode */
|
||||
REG_CPM_LCR &= ~CPM_LCR_LPM_MASK;
|
||||
REG_CPM_LCR |= CPM_LCR_LPM_SLEEP;
|
||||
__asm__(".set\tmips3\n\t"
|
||||
"wait\n\t"
|
||||
".set\tmips0");
|
||||
|
||||
/* Restore to IDLE mode */
|
||||
REG_CPM_LCR &= ~CPM_LCR_LPM_MASK;
|
||||
REG_CPM_LCR |= CPM_LCR_LPM_IDLE;
|
||||
|
||||
/* Restore nand flash control register */
|
||||
REG_EMC_NFCSR = nfcsr;
|
||||
|
||||
/* Restore interrupts */
|
||||
REG_INTC_IMSR = imr;
|
||||
REG_INTC_IMCR = ~imr;
|
||||
|
||||
/* Restore sadc */
|
||||
REG_SADC_ENA = sadc;
|
||||
|
||||
/* Resume on-board modules */
|
||||
jz_board_do_resume(sleep_gpio_save);
|
||||
|
||||
/* Restore sleep control register */
|
||||
REG_CPM_SCR = scr;
|
||||
|
||||
/* Restore current time */
|
||||
xtime.tv_sec = REG_RTC_RSR + delta;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Put CPU to HIBERNATE mode */
|
||||
int jz_pm_hibernate(void)
|
||||
{
|
||||
printk("Put CPU into hibernate mode.\n");
|
||||
return jz_pm_do_hibernate();
|
||||
}
|
||||
|
||||
#ifndef CONFIG_JZ_POWEROFF
|
||||
static irqreturn_t pm_irq_handler (int irq, void *dev_id)
|
||||
{
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Put CPU to SLEEP mode */
|
||||
int jz_pm_sleep(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
#ifndef CONFIG_JZ_POWEROFF
|
||||
if ((retval = request_irq (IRQ_GPIO_0 + GPIO_WAKEUP, pm_irq_handler, IRQF_DISABLED,
|
||||
"PM", NULL))) {
|
||||
printk ("PM could not get IRQ for GPIO_WAKEUP\n");
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
printk("Put CPU into sleep mode.\n");
|
||||
retval = jz_pm_do_sleep();
|
||||
|
||||
#ifndef CONFIG_JZ_POWEROFF
|
||||
free_irq (IRQ_GPIO_0 + GPIO_WAKEUP, NULL);
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* valid states, only support standby(sleep) and mem(hibernate)
|
||||
*/
|
||||
static int jz_pm_valid(suspend_state_t state)
|
||||
{
|
||||
switch (state) {
|
||||
case PM_SUSPEND_STANDBY:
|
||||
case PM_SUSPEND_MEM:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Jz CPU enter save power mode
|
||||
*/
|
||||
static int jz_pm_enter(suspend_state_t state)
|
||||
{
|
||||
if (state == PM_SUSPEND_STANDBY)
|
||||
jz_pm_sleep();
|
||||
else
|
||||
jz_pm_hibernate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct platform_suspend_ops jz_pm_ops = {
|
||||
.valid = jz_pm_valid,
|
||||
.enter = jz_pm_enter,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Initialize power interface
|
||||
*/
|
||||
int __init jz_pm_init(void)
|
||||
{
|
||||
printk("Power Management for JZ\n");
|
||||
|
||||
suspend_set_ops(&jz_pm_ops);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
//module_init(jz_pm_init);
|
||||
|
||||
873
target/linux/xburst/files-2.6.27/arch/mips/jz4740/proc.c
Normal file
873
target/linux/xburst/files-2.6.27/arch/mips/jz4740/proc.c
Normal file
@@ -0,0 +1,873 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4740/proc.c
|
||||
*
|
||||
* /proc/jz/ procfs for jz4740 on-chip modules.
|
||||
*
|
||||
* Copyright (C) 2006 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can distribute it and/or modify it
|
||||
* under the terms of the GNU General Public License (Version 2) as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/page-flags.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
//#define DEBUG 1
|
||||
#undef DEBUG
|
||||
|
||||
|
||||
struct proc_dir_entry *proc_jz_root;
|
||||
|
||||
|
||||
/*
|
||||
* EMC Modules
|
||||
*/
|
||||
static int emc_read_proc (char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
len += sprintf (page+len, "SMCR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SMCR0, REG_EMC_SMCR1, REG_EMC_SMCR2, REG_EMC_SMCR3, REG_EMC_SMCR4);
|
||||
len += sprintf (page+len, "SACR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SACR0, REG_EMC_SACR1, REG_EMC_SACR2, REG_EMC_SACR3, REG_EMC_SACR4);
|
||||
len += sprintf (page+len, "DMCR: 0x%08x\n", REG_EMC_DMCR);
|
||||
len += sprintf (page+len, "RTCSR: 0x%04x\n", REG_EMC_RTCSR);
|
||||
len += sprintf (page+len, "RTCOR: 0x%04x\n", REG_EMC_RTCOR);
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Power Manager Module
|
||||
*/
|
||||
static int pmc_read_proc (char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
unsigned long lcr = REG_CPM_LCR;
|
||||
unsigned long clkgr = REG_CPM_CLKGR;
|
||||
|
||||
len += sprintf (page+len, "Low Power Mode : %s\n",
|
||||
((lcr & CPM_LCR_LPM_MASK) == (CPM_LCR_LPM_IDLE)) ?
|
||||
"IDLE" : (((lcr & CPM_LCR_LPM_MASK) == (CPM_LCR_LPM_SLEEP)) ?
|
||||
"SLEEP" : "HIBERNATE"));
|
||||
len += sprintf (page+len, "Doze Mode : %s\n",
|
||||
(lcr & CPM_LCR_DOZE_ON) ? "on" : "off");
|
||||
if (lcr & CPM_LCR_DOZE_ON)
|
||||
len += sprintf (page+len, " duty : %d\n", (int)((lcr & CPM_LCR_DOZE_DUTY_MASK) >> CPM_LCR_DOZE_DUTY_BIT));
|
||||
len += sprintf (page+len, "IPU : %s\n",
|
||||
(clkgr & CPM_CLKGR_IPU) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "DMAC : %s\n",
|
||||
(clkgr & CPM_CLKGR_DMAC) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "UHC : %s\n",
|
||||
(clkgr & CPM_CLKGR_UHC) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "UDC : %s\n",
|
||||
(clkgr & CPM_CLKGR_UDC) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "LCD : %s\n",
|
||||
(clkgr & CPM_CLKGR_LCD) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "CIM : %s\n",
|
||||
(clkgr & CPM_CLKGR_CIM) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "SADC : %s\n",
|
||||
(clkgr & CPM_CLKGR_SADC) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "MSC : %s\n",
|
||||
(clkgr & CPM_CLKGR_MSC) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "AIC1 : %s\n",
|
||||
(clkgr & CPM_CLKGR_AIC1) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "AIC2 : %s\n",
|
||||
(clkgr & CPM_CLKGR_AIC2) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "SSI : %s\n",
|
||||
(clkgr & CPM_CLKGR_SSI) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "I2C : %s\n",
|
||||
(clkgr & CPM_CLKGR_I2C) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "RTC : %s\n",
|
||||
(clkgr & CPM_CLKGR_RTC) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "TCU : %s\n",
|
||||
(clkgr & CPM_CLKGR_TCU) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "UART1 : %s\n",
|
||||
(clkgr & CPM_CLKGR_UART1) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "UART0 : %s\n",
|
||||
(clkgr & CPM_CLKGR_UART0) ? "stopped" : "running");
|
||||
return len;
|
||||
}
|
||||
|
||||
static int pmc_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
|
||||
{
|
||||
REG_CPM_CLKGR = simple_strtoul(buffer, 0, 16);
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clock Generation Module
|
||||
*/
|
||||
#define TO_MHZ(x) (x/1000000),(x%1000000)/10000
|
||||
#define TO_KHZ(x) (x/1000),(x%1000)/10
|
||||
|
||||
static int cgm_read_proc (char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
unsigned int cppcr = REG_CPM_CPPCR; /* PLL Control Register */
|
||||
unsigned int cpccr = REG_CPM_CPCCR; /* Clock Control Register */
|
||||
unsigned int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
|
||||
unsigned int od[4] = {1, 2, 2, 4};
|
||||
|
||||
len += sprintf (page+len, "CPPCR : 0x%08x\n", cppcr);
|
||||
len += sprintf (page+len, "CPCCR : 0x%08x\n", cpccr);
|
||||
len += sprintf (page+len, "PLL : %s\n",
|
||||
(cppcr & CPM_CPPCR_PLLEN) ? "ON" : "OFF");
|
||||
len += sprintf (page+len, "m:n:o : %d:%d:%d\n",
|
||||
__cpm_get_pllm() + 2,
|
||||
__cpm_get_plln() + 2,
|
||||
od[__cpm_get_pllod()]
|
||||
);
|
||||
len += sprintf (page+len, "C:H:M:P : %d:%d:%d:%d\n",
|
||||
div[__cpm_get_cdiv()],
|
||||
div[__cpm_get_hdiv()],
|
||||
div[__cpm_get_mdiv()],
|
||||
div[__cpm_get_pdiv()]
|
||||
);
|
||||
len += sprintf (page+len, "PLL Freq : %3d.%02d MHz\n", TO_MHZ(__cpm_get_pllout()));
|
||||
len += sprintf (page+len, "CCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_cclk()));
|
||||
len += sprintf (page+len, "HCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_hclk()));
|
||||
len += sprintf (page+len, "MCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mclk()));
|
||||
len += sprintf (page+len, "PCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_pclk()));
|
||||
len += sprintf (page+len, "LCDCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_lcdclk()));
|
||||
len += sprintf (page+len, "PIXCLK : %3d.%02d KHz\n", TO_KHZ(__cpm_get_pixclk()));
|
||||
len += sprintf (page+len, "I2SCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_i2sclk()));
|
||||
len += sprintf (page+len, "USBCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_usbclk()));
|
||||
len += sprintf (page+len, "MSCCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mscclk()));
|
||||
len += sprintf (page+len, "EXTALCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_extalclk()));
|
||||
len += sprintf (page+len, "RTCCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_rtcclk()));
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int cgm_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
|
||||
{
|
||||
REG_CPM_CPCCR = simple_strtoul(buffer, 0, 16);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/* USAGE:
|
||||
* echo n > /proc/jz/ipu // n = [1,...,9], alloc mem, 2^n pages.
|
||||
* echo FF > /proc/jz/ipu // 255, free all buffer
|
||||
* echo xxxx > /proc/jz/ipu // free buffer which addr is xxxx
|
||||
* echo llll > /proc/jz/ipu // add_wired_entry(l,l,l,l)
|
||||
* echo 0 > /proc/jz/ipu // debug, print ipu_buf
|
||||
* od -X /proc/jz/ipu // read mem addr
|
||||
*/
|
||||
|
||||
typedef struct _ipu_buf {
|
||||
unsigned int addr; /* phys addr */
|
||||
unsigned int page_shift;
|
||||
} ipu_buf_t;
|
||||
|
||||
#define IPU_BUF_MAX 4 /* 4 buffers */
|
||||
|
||||
static struct _ipu_buf ipu_buf[IPU_BUF_MAX];
|
||||
static int ipu_buf_cnt = 0;
|
||||
static unsigned char g_asid=0;
|
||||
|
||||
extern void local_flush_tlb_all(void);
|
||||
|
||||
/* CP0 hazard avoidance. */
|
||||
#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \
|
||||
"nop; nop; nop; nop; nop; nop;\n\t" \
|
||||
".set reorder\n\t")
|
||||
void show_tlb(void)
|
||||
{
|
||||
#define ASID_MASK 0xFF
|
||||
|
||||
unsigned long flags;
|
||||
unsigned int old_ctx;
|
||||
unsigned int entry;
|
||||
unsigned int entrylo0, entrylo1, entryhi;
|
||||
unsigned int pagemask;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
/* Save old context */
|
||||
old_ctx = (read_c0_entryhi() & 0xff);
|
||||
|
||||
printk("TLB content:\n");
|
||||
entry = 0;
|
||||
while(entry < 32) {
|
||||
write_c0_index(entry);
|
||||
BARRIER;
|
||||
tlb_read();
|
||||
BARRIER;
|
||||
entryhi = read_c0_entryhi();
|
||||
entrylo0 = read_c0_entrylo0();
|
||||
entrylo1 = read_c0_entrylo1();
|
||||
pagemask = read_c0_pagemask();
|
||||
printk("%02d: ASID=%02d%s VA=0x%08x ", entry, entryhi & ASID_MASK, (entrylo0 & entrylo1 & 1) ? "(G)" : " ", entryhi & ~ASID_MASK);
|
||||
printk("PA0=0x%08x C0=%x %s%s%s\n", (entrylo0>>6)<<12, (entrylo0>>3) & 7, (entrylo0 & 4) ? "Dirty " : "", (entrylo0 & 2) ? "Valid " : "Invalid ", (entrylo0 & 1) ? "Global" : "");
|
||||
printk("\t\t\t PA1=0x%08x C1=%x %s%s%s\n", (entrylo1>>6)<<12, (entrylo1>>3) & 7, (entrylo1 & 4) ? "Dirty " : "", (entrylo1 & 2) ? "Valid " : "Invalid ", (entrylo1 & 1) ? "Global" : "");
|
||||
|
||||
printk("\t\tpagemask=0x%08x", pagemask);
|
||||
printk("\tentryhi=0x%08x\n", entryhi);
|
||||
printk("\t\tentrylo0=0x%08x", entrylo0);
|
||||
printk("\tentrylo1=0x%08x\n", entrylo1);
|
||||
|
||||
entry++;
|
||||
}
|
||||
BARRIER;
|
||||
write_c0_entryhi(old_ctx);
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void ipu_add_wired_entry(unsigned long pid,
|
||||
unsigned long entrylo0, unsigned long entrylo1,
|
||||
unsigned long entryhi, unsigned long pagemask)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long wired;
|
||||
unsigned long old_pagemask;
|
||||
unsigned long old_ctx;
|
||||
struct task_struct *g, *p;
|
||||
|
||||
/* We will lock an 4MB page size entry to map the 4MB reserved IPU memory */
|
||||
wired = read_c0_wired();
|
||||
if (wired) return;
|
||||
|
||||
do_each_thread(g, p) {
|
||||
if (p->pid == pid )
|
||||
g_asid = p->mm->context[0];
|
||||
} while_each_thread(g, p);
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
entrylo0 = entrylo0 >> 6; /* PFN */
|
||||
entrylo0 |= 0x6 | (0 << 3); /* Write-through cacheable, dirty, valid */
|
||||
|
||||
/* Save old context and create impossible VPN2 value */
|
||||
old_ctx = read_c0_entryhi() & 0xff;
|
||||
old_pagemask = read_c0_pagemask();
|
||||
write_c0_wired(wired + 1);
|
||||
write_c0_index(wired);
|
||||
BARRIER;
|
||||
entryhi &= ~0xff; /* new add, 20070906 */
|
||||
entryhi |= g_asid; /* new add, 20070906 */
|
||||
// entryhi |= old_ctx; /* new add, 20070906 */
|
||||
write_c0_pagemask(pagemask);
|
||||
write_c0_entryhi(entryhi);
|
||||
write_c0_entrylo0(entrylo0);
|
||||
write_c0_entrylo1(entrylo1);
|
||||
BARRIER;
|
||||
tlb_write_indexed();
|
||||
BARRIER;
|
||||
|
||||
write_c0_entryhi(old_ctx);
|
||||
BARRIER;
|
||||
write_c0_pagemask(old_pagemask);
|
||||
local_flush_tlb_all();
|
||||
local_irq_restore(flags);
|
||||
#if defined(DEBUG)
|
||||
printk("\nold_ctx=%03d\n", old_ctx);
|
||||
|
||||
show_tlb();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ipu_del_wired_entry( void )
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long wired;
|
||||
|
||||
/* Free all lock entry */
|
||||
local_irq_save(flags);
|
||||
wired = read_c0_wired();
|
||||
if (wired)
|
||||
write_c0_wired(0);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static inline void ipu_buf_get( unsigned int page_shift )
|
||||
{
|
||||
unsigned char * virt_addr;
|
||||
int i;
|
||||
for ( i=0; i< IPU_BUF_MAX; ++i ) {
|
||||
if ( ipu_buf[i].addr == 0 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( (ipu_buf_cnt = i) == IPU_BUF_MAX ) {
|
||||
printk("Error, no free ipu buffer.\n");
|
||||
return ;
|
||||
}
|
||||
|
||||
virt_addr = (unsigned char *)__get_free_pages(GFP_KERNEL, page_shift);
|
||||
|
||||
if ( virt_addr ) {
|
||||
ipu_buf[ipu_buf_cnt].addr = (unsigned int)virt_to_phys((void *)virt_addr);
|
||||
ipu_buf[ipu_buf_cnt].page_shift = page_shift;
|
||||
|
||||
for (i = 0; i < (1<<page_shift); i++) {
|
||||
SetPageReserved(virt_to_page(virt_addr));
|
||||
virt_addr += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
printk("get memory Failed.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ipu_buf_free( unsigned int phys_addr )
|
||||
{
|
||||
unsigned char * virt_addr, *addr;
|
||||
int cnt, i;
|
||||
|
||||
if ( phys_addr == 0 )
|
||||
return ;
|
||||
|
||||
for ( cnt=0; cnt<IPU_BUF_MAX; ++cnt )
|
||||
if ( phys_addr == ipu_buf[cnt].addr )
|
||||
break;
|
||||
|
||||
if ( cnt == IPU_BUF_MAX ) { /* addr not in the ipu buffers */
|
||||
printk("Invalid addr:0x%08x\n", (unsigned int)phys_addr);
|
||||
}
|
||||
|
||||
virt_addr = (unsigned char *)phys_to_virt(ipu_buf[cnt].addr);
|
||||
addr = virt_addr;
|
||||
for (i = 0; i < (1<<ipu_buf[cnt].page_shift); i++) {
|
||||
ClearPageReserved(virt_to_page(addr));
|
||||
addr += PAGE_SIZE;
|
||||
}
|
||||
|
||||
if ( cnt == 0 )
|
||||
ipu_del_wired_entry();
|
||||
|
||||
free_pages((unsigned long )virt_addr, ipu_buf[cnt].page_shift);
|
||||
|
||||
ipu_buf[cnt].addr = 0;
|
||||
ipu_buf[cnt].page_shift = 0;
|
||||
}
|
||||
|
||||
static int ipu_read_proc (char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
/* read as binary */
|
||||
unsigned int * pint;
|
||||
pint = (unsigned int *) (page+len);
|
||||
|
||||
if ( ipu_buf_cnt >= IPU_BUF_MAX ) { /* failed alloc mem, rturn 0 */
|
||||
printk("no free buffer.\n");
|
||||
*pint = 0;
|
||||
}
|
||||
else
|
||||
*pint = (unsigned int )ipu_buf[ipu_buf_cnt].addr; /* phys addr */
|
||||
len += sizeof(unsigned int);
|
||||
|
||||
#if defined(DEBUG)
|
||||
show_tlb();
|
||||
#endif
|
||||
return len;
|
||||
|
||||
}
|
||||
|
||||
static int ipu_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
|
||||
{
|
||||
unsigned int val ;
|
||||
int cnt,i;
|
||||
char buf[12];
|
||||
unsigned long pid, entrylo0, entrylo1, entryhi, pagemask;
|
||||
#if defined(DEBUG)
|
||||
printk("ipu write count=%u\n", count);
|
||||
#endif
|
||||
if (count == (8*5+1)) {
|
||||
for (i=0;i<12;i++) buf[i]=0;
|
||||
strncpy(buf, buffer+8*0, 8);
|
||||
pid = simple_strtoul(buf, 0, 16);
|
||||
for (i=0;i<12;i++) buf[i]=0;
|
||||
strncpy(buf, buffer+8*1, 8);
|
||||
entrylo0 = simple_strtoul(buf, 0, 16);
|
||||
for (i=0;i<12;i++) buf[i]=0;
|
||||
strncpy(buf, buffer+8*2, 8);
|
||||
entrylo1 = simple_strtoul(buf, 0, 16);
|
||||
for (i=0;i<12;i++) buf[i]=0;
|
||||
strncpy(buf, buffer+8*3, 8);
|
||||
entryhi = simple_strtoul(buf, 0, 16);
|
||||
for (i=0;i<12;i++) buf[i]=0;
|
||||
strncpy(buf, buffer+8*4, 8);
|
||||
pagemask = simple_strtoul(buf, 0, 16);
|
||||
|
||||
#if defined(DEBUG)
|
||||
printk("pid=0x%08x, entrylo0=0x%08x, entrylo1=0x%08x, entryhi=0x%08x, pagemask=0x%08x\n",
|
||||
pid, entrylo0, entrylo1, entryhi, pagemask);
|
||||
#endif
|
||||
ipu_add_wired_entry( pid, entrylo0, entrylo1, entryhi, pagemask);
|
||||
return 41;
|
||||
} else if ( count <= 8+1 ) {
|
||||
for (i=0;i<12;i++) buf[i]=0;
|
||||
strncpy(buf, buffer, 8);
|
||||
val = simple_strtoul(buf, 0, 16);
|
||||
} else if (count == 44) {
|
||||
for (i = 0; i < 12; i++)
|
||||
buf[i] = 0;
|
||||
strncpy(buf, buffer, 10);
|
||||
pid = simple_strtoul(buf, 0, 16);
|
||||
for (i = 0; i < 12; i++)
|
||||
buf[i] = 0;
|
||||
strncpy(buf, buffer + 11, 10);
|
||||
entryhi = simple_strtoul(buf, 0, 16);//vaddr
|
||||
for (i = 0; i < 12; i++)
|
||||
buf[i] = 0;
|
||||
strncpy(buf, buffer + 22, 10);
|
||||
entrylo0 = simple_strtoul(buf, 0, 16);//paddr
|
||||
for (i = 0; i < 12; i++)
|
||||
buf[i] = 0;
|
||||
strncpy(buf, buffer + 33, 10);
|
||||
pagemask = simple_strtoul(buf, 0, 16);
|
||||
pagemask = 0x3ff << 13; /* Fixed to 4MB page size */
|
||||
ipu_add_wired_entry(pid, entrylo0, 0, entryhi, pagemask);
|
||||
return 44;
|
||||
} else {
|
||||
printk("ipu write count error, count=%d\n.", (unsigned int)count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* val: 1-9, page_shift, val>= 10: ipu_buf.addr */
|
||||
if ( val == 0 ) { /* debug, print ipu_buf info */
|
||||
for ( cnt=0; cnt<IPU_BUF_MAX; ++cnt)
|
||||
printk("ipu_buf[%d]: addr=0x%08x, page_shift=%d\n",
|
||||
cnt, ipu_buf[cnt].addr, ipu_buf[cnt].page_shift );
|
||||
#if defined(DEBUG)
|
||||
show_tlb();
|
||||
#endif
|
||||
}
|
||||
else if ( 0< val && val < 10 ) {
|
||||
ipu_buf_get(val);
|
||||
}
|
||||
else if ( val == 0xff ) { /* 255: free all ipu_buf */
|
||||
for ( cnt=0; cnt<IPU_BUF_MAX; ++cnt ) {
|
||||
ipu_buf_free(ipu_buf[cnt].addr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ipu_buf_free(val);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* UDC hotplug
|
||||
*/
|
||||
#ifdef CONFIG_JZ_UDC_HOTPLUG
|
||||
extern int jz_udc_active; /* defined in drivers/char/jzchar/jz_udc_hotplug.c */
|
||||
#endif
|
||||
|
||||
#ifndef GPIO_UDC_HOTPLUG
|
||||
#define GPIO_UDC_HOTPLUG 86
|
||||
#endif
|
||||
|
||||
static int udc_read_proc(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
if (__gpio_get_pin(GPIO_UDC_HOTPLUG)) {
|
||||
|
||||
#ifdef CONFIG_JZ_UDC_HOTPLUG
|
||||
|
||||
/* Cable has connected, wait for disconnection. */
|
||||
__gpio_as_irq_fall_edge(GPIO_UDC_HOTPLUG);
|
||||
|
||||
if (jz_udc_active)
|
||||
len += sprintf (page+len, "CONNECT_CABLE\n");
|
||||
else
|
||||
len += sprintf (page+len, "CONNECT_POWER\n");
|
||||
#else
|
||||
len += sprintf (page+len, "CONNECT\n");
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
|
||||
#ifdef CONFIG_JZ_UDC_HOTPLUG
|
||||
/* Cable has disconnected, wait for connection. */
|
||||
__gpio_as_irq_rise_edge(GPIO_UDC_HOTPLUG);
|
||||
#endif
|
||||
|
||||
len += sprintf (page+len, "REMOVE\n");
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* MMC/SD hotplug
|
||||
*/
|
||||
|
||||
#ifndef MSC_HOTPLUG_PIN
|
||||
#define MSC_HOTPLUG_PIN 90
|
||||
#endif
|
||||
|
||||
static int mmc_read_proc (char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
#if defined(CONFIG_JZ4740_LYRA)
|
||||
if (!(__gpio_get_pin(MSC_HOTPLUG_PIN)))
|
||||
#else
|
||||
if (__gpio_get_pin(MSC_HOTPLUG_PIN))
|
||||
#endif
|
||||
len += sprintf (page+len, "REMOVE\n");
|
||||
else
|
||||
len += sprintf (page+len, "INSERT\n");
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* IPU memory management (used by mplayer and other apps)
|
||||
*
|
||||
* We reserved 4MB memory for IPU
|
||||
* The memory base address is jz_ipu_framebuf
|
||||
*/
|
||||
|
||||
/* Usage:
|
||||
*
|
||||
* echo n > /proc/jz/imem // n = [0,...,10], allocate memory, 2^n pages
|
||||
* echo xxxxxxxx > /proc/jz/imem // free buffer which addr is xxxxxxxx
|
||||
* echo FF > /proc/jz/ipu // FF, free all buffers
|
||||
* od -X /proc/jz/imem // return the allocated buffer address and the max order of free buffer
|
||||
*/
|
||||
|
||||
//#define DEBUG_IMEM 1
|
||||
|
||||
#define IMEM_MAX_ORDER 10 /* max 2^10 * 4096 = 4MB */
|
||||
|
||||
static unsigned int jz_imem_base; /* physical base address of ipu memory */
|
||||
|
||||
static unsigned int allocated_phys_addr = 0;
|
||||
|
||||
/*
|
||||
* Allocated buffer list
|
||||
*/
|
||||
typedef struct imem_list {
|
||||
unsigned int phys_start; /* physical start addr */
|
||||
unsigned int phys_end; /* physical end addr */
|
||||
struct imem_list *next;
|
||||
} imem_list_t;
|
||||
|
||||
static struct imem_list *imem_list_head = NULL; /* up sorted by phys_start */
|
||||
|
||||
#ifdef DEBUG_IMEM
|
||||
static void dump_imem_list(void)
|
||||
{
|
||||
struct imem_list *imem;
|
||||
|
||||
printk("*** dump_imem_list 0x%x ***\n", (u32)imem_list_head);
|
||||
imem = imem_list_head;
|
||||
while (imem) {
|
||||
printk("imem=0x%x phys_start=0x%x phys_end=0x%x next=0x%x\n", (u32)imem, imem->phys_start, imem->phys_end, (u32)imem->next);
|
||||
imem = imem->next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* allocate 2^order pages inside the 4MB memory */
|
||||
static int imem_alloc(unsigned int order)
|
||||
{
|
||||
int alloc_ok = 0;
|
||||
unsigned int start, end;
|
||||
unsigned int size = (1 << order) * PAGE_SIZE;
|
||||
struct imem_list *imem, *imemn, *imemp;
|
||||
|
||||
allocated_phys_addr = 0;
|
||||
|
||||
start = jz_imem_base;
|
||||
end = start + (1 << IMEM_MAX_ORDER) * PAGE_SIZE;
|
||||
|
||||
imem = imem_list_head;
|
||||
while (imem) {
|
||||
if ((imem->phys_start - start) >= size) {
|
||||
/* we got a valid address range */
|
||||
alloc_ok = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
start = imem->phys_end + 1;
|
||||
imem = imem->next;
|
||||
}
|
||||
|
||||
if (!alloc_ok) {
|
||||
if ((end - start) >= size)
|
||||
alloc_ok = 1;
|
||||
}
|
||||
|
||||
if (alloc_ok) {
|
||||
end = start + size - 1;
|
||||
allocated_phys_addr = start;
|
||||
|
||||
/* add to imem_list, up sorted by phys_start */
|
||||
imemn = kmalloc(sizeof(struct imem_list), GFP_KERNEL);
|
||||
if (!imemn) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
imemn->phys_start = start;
|
||||
imemn->phys_end = end;
|
||||
imemn->next = NULL;
|
||||
|
||||
if (!imem_list_head)
|
||||
imem_list_head = imemn;
|
||||
else {
|
||||
imem = imemp = imem_list_head;
|
||||
while (imem) {
|
||||
if (start < imem->phys_start) {
|
||||
break;
|
||||
}
|
||||
|
||||
imemp = imem;
|
||||
imem = imem->next;
|
||||
}
|
||||
|
||||
if (imem == imem_list_head) {
|
||||
imem_list_head = imemn;
|
||||
imemn->next = imem;
|
||||
}
|
||||
else {
|
||||
imemn->next = imemp->next;
|
||||
imemp->next = imemn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_IMEM
|
||||
dump_imem_list();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void imem_free(unsigned int phys_addr)
|
||||
{
|
||||
struct imem_list *imem, *imemp;
|
||||
|
||||
imem = imemp = imem_list_head;
|
||||
while (imem) {
|
||||
if (phys_addr == imem->phys_start) {
|
||||
if (imem == imem_list_head) {
|
||||
imem_list_head = imem->next;
|
||||
}
|
||||
else {
|
||||
imemp->next = imem->next;
|
||||
}
|
||||
|
||||
kfree(imem);
|
||||
break;
|
||||
}
|
||||
|
||||
imemp = imem;
|
||||
imem = imem->next;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_IMEM
|
||||
dump_imem_list();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void imem_free_all(void)
|
||||
{
|
||||
struct imem_list *imem;
|
||||
|
||||
imem = imem_list_head;
|
||||
while (imem) {
|
||||
kfree(imem);
|
||||
imem = imem->next;
|
||||
}
|
||||
|
||||
imem_list_head = NULL;
|
||||
|
||||
allocated_phys_addr = 0;
|
||||
|
||||
#ifdef DEBUG_IMEM
|
||||
dump_imem_list();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the allocated buffer address and the max order of free buffer
|
||||
*/
|
||||
static int imem_read_proc(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
unsigned int start_addr, end_addr, max_order, max_size;
|
||||
struct imem_list *imem;
|
||||
|
||||
unsigned int *tmp = (unsigned int *)(page + len);
|
||||
|
||||
start_addr = jz_imem_base;
|
||||
end_addr = start_addr + (1 << IMEM_MAX_ORDER) * PAGE_SIZE;
|
||||
|
||||
if (!imem_list_head)
|
||||
max_size = end_addr - start_addr;
|
||||
else {
|
||||
max_size = 0;
|
||||
imem = imem_list_head;
|
||||
while (imem) {
|
||||
if (max_size < (imem->phys_start - start_addr))
|
||||
max_size = imem->phys_start - start_addr;
|
||||
|
||||
start_addr = imem->phys_end + 1;
|
||||
imem = imem->next;
|
||||
}
|
||||
|
||||
if (max_size < (end_addr - start_addr))
|
||||
max_size = end_addr - start_addr;
|
||||
}
|
||||
|
||||
if (max_size > 0) {
|
||||
max_order = get_order(max_size);
|
||||
if (((1 << max_order) * PAGE_SIZE) > max_size)
|
||||
max_order--;
|
||||
}
|
||||
else {
|
||||
max_order = 0xffffffff; /* No any free buffer */
|
||||
}
|
||||
|
||||
*tmp++ = allocated_phys_addr; /* address allocated by 'echo n > /proc/jz/imem' */
|
||||
*tmp = max_order; /* max order of current free buffers */
|
||||
|
||||
len += 2 * sizeof(unsigned int);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int imem_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
val = simple_strtoul(buffer, 0, 16);
|
||||
|
||||
if (val == 0xff) {
|
||||
/* free all memory */
|
||||
imem_free_all();
|
||||
ipu_del_wired_entry();
|
||||
}
|
||||
else if ((val >= 0) && (val <= IMEM_MAX_ORDER)) {
|
||||
/* allocate 2^val pages */
|
||||
imem_alloc(val);
|
||||
}
|
||||
else {
|
||||
/* free buffer which phys_addr is val */
|
||||
imem_free(val);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* /proc/jz/xxx entry
|
||||
*
|
||||
*/
|
||||
static int __init jz_proc_init(void)
|
||||
{
|
||||
struct proc_dir_entry *res;
|
||||
unsigned int virt_addr, i;
|
||||
|
||||
proc_jz_root = proc_mkdir("jz", 0);
|
||||
|
||||
/* External Memory Controller */
|
||||
res = create_proc_entry("emc", 0644, proc_jz_root);
|
||||
if (res) {
|
||||
res->read_proc = emc_read_proc;
|
||||
res->write_proc = NULL;
|
||||
res->data = NULL;
|
||||
}
|
||||
|
||||
/* Power Management Controller */
|
||||
res = create_proc_entry("pmc", 0644, proc_jz_root);
|
||||
if (res) {
|
||||
res->read_proc = pmc_read_proc;
|
||||
res->write_proc = pmc_write_proc;
|
||||
res->data = NULL;
|
||||
}
|
||||
|
||||
/* Clock Generation Module */
|
||||
res = create_proc_entry("cgm", 0644, proc_jz_root);
|
||||
if (res) {
|
||||
res->read_proc = cgm_read_proc;
|
||||
res->write_proc = cgm_write_proc;
|
||||
res->data = NULL;
|
||||
}
|
||||
|
||||
/* Image process unit */
|
||||
res = create_proc_entry("ipu", 0644, proc_jz_root);
|
||||
if (res) {
|
||||
res->read_proc = ipu_read_proc;
|
||||
res->write_proc = ipu_write_proc;
|
||||
res->data = NULL;
|
||||
}
|
||||
|
||||
/* udc hotplug */
|
||||
res = create_proc_entry("udc", 0644, proc_jz_root);
|
||||
if (res) {
|
||||
res->read_proc = udc_read_proc;
|
||||
res->write_proc = NULL;
|
||||
res->data = NULL;
|
||||
}
|
||||
|
||||
/* mmc hotplug */
|
||||
res = create_proc_entry("mmc", 0644, proc_jz_root);
|
||||
if (res) {
|
||||
res->read_proc = mmc_read_proc;
|
||||
res->write_proc = NULL;
|
||||
res->data = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reserve a 4MB memory for IPU on JZ4740.
|
||||
*/
|
||||
jz_imem_base = (unsigned int)__get_free_pages(GFP_KERNEL, IMEM_MAX_ORDER);
|
||||
if (jz_imem_base) {
|
||||
/* imem (IPU memory management) */
|
||||
res = create_proc_entry("imem", 0644, proc_jz_root);
|
||||
if (res) {
|
||||
res->read_proc = imem_read_proc;
|
||||
res->write_proc = imem_write_proc;
|
||||
res->data = NULL;
|
||||
}
|
||||
|
||||
/* Set page reserved */
|
||||
virt_addr = jz_imem_base;
|
||||
for (i = 0; i < (1 << IMEM_MAX_ORDER); i++) {
|
||||
SetPageReserved(virt_to_page((void *)virt_addr));
|
||||
virt_addr += PAGE_SIZE;
|
||||
}
|
||||
|
||||
/* Convert to physical address */
|
||||
jz_imem_base = virt_to_phys((void *)jz_imem_base);
|
||||
|
||||
printk("Total %dMB memory at 0x%x was reserved for IPU\n",
|
||||
(unsigned int)((1 << IMEM_MAX_ORDER) * PAGE_SIZE)/1000000, jz_imem_base);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__initcall(jz_proc_init);
|
||||
198
target/linux/xburst/files-2.6.27/arch/mips/jz4740/prom.c
Normal file
198
target/linux/xburst/files-2.6.27/arch/mips/jz4740/prom.c
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
*
|
||||
* BRIEF MODULE DESCRIPTION
|
||||
* PROM library initialisation code, supports YAMON and U-Boot.
|
||||
*
|
||||
* Copyright 2000, 2001, 2006 MontaVista Software Inc.
|
||||
* Author: MontaVista Software, Inc.
|
||||
* ppopov@mvista.com or source@mvista.com
|
||||
*
|
||||
* This file was derived from Carsten Langgaard's
|
||||
* arch/mips/mips-boards/xx files.
|
||||
*
|
||||
* Carsten Langgaard, carstenl@mips.com
|
||||
* Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
|
||||
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* 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.,
|
||||
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/* #define DEBUG_CMDLINE */
|
||||
|
||||
int prom_argc;
|
||||
char **prom_argv, **prom_envp;
|
||||
|
||||
char * prom_getcmdline(void)
|
||||
{
|
||||
return &(arcs_cmdline[0]);
|
||||
}
|
||||
|
||||
void prom_init_cmdline(void)
|
||||
{
|
||||
char *cp;
|
||||
int actr;
|
||||
|
||||
actr = 1; /* Always ignore argv[0] */
|
||||
|
||||
cp = &(arcs_cmdline[0]);
|
||||
while(actr < prom_argc) {
|
||||
strcpy(cp, prom_argv[actr]);
|
||||
cp += strlen(prom_argv[actr]);
|
||||
*cp++ = ' ';
|
||||
actr++;
|
||||
}
|
||||
if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
|
||||
--cp;
|
||||
if (prom_argc > 1)
|
||||
*cp = '\0';
|
||||
|
||||
}
|
||||
|
||||
|
||||
char *prom_getenv(char *envname)
|
||||
{
|
||||
#if 0
|
||||
/*
|
||||
* Return a pointer to the given environment variable.
|
||||
* YAMON uses "name", "value" pairs, while U-Boot uses "name=value".
|
||||
*/
|
||||
|
||||
char **env = prom_envp;
|
||||
int i = strlen(envname);
|
||||
int yamon = (*env && strchr(*env, '=') == NULL);
|
||||
|
||||
while (*env) {
|
||||
if (yamon) {
|
||||
if (strcmp(envname, *env++) == 0)
|
||||
return *env;
|
||||
} else {
|
||||
if (strncmp(envname, *env, i) == 0 && (*env)[i] == '=')
|
||||
return *env + i + 1;
|
||||
}
|
||||
env++;
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline unsigned char str2hexnum(unsigned char c)
|
||||
{
|
||||
if(c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
if(c >= 'a' && c <= 'f')
|
||||
return c - 'a' + 10;
|
||||
if(c >= 'A' && c <= 'F')
|
||||
return c - 'A' + 10;
|
||||
return 0; /* foo */
|
||||
}
|
||||
|
||||
inline void str2eaddr(unsigned char *ea, unsigned char *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 6; i++) {
|
||||
unsigned char num;
|
||||
|
||||
if((*str == '.') || (*str == ':'))
|
||||
str++;
|
||||
num = str2hexnum(*str++) << 4;
|
||||
num |= (str2hexnum(*str++));
|
||||
ea[i] = num;
|
||||
}
|
||||
}
|
||||
|
||||
int get_ethernet_addr(char *ethernet_addr)
|
||||
{
|
||||
char *ethaddr_str;
|
||||
|
||||
ethaddr_str = prom_getenv("ethaddr");
|
||||
if (!ethaddr_str) {
|
||||
printk("ethaddr not set in boot prom\n");
|
||||
return -1;
|
||||
}
|
||||
str2eaddr(ethernet_addr, ethaddr_str);
|
||||
|
||||
#if 0
|
||||
{
|
||||
int i;
|
||||
|
||||
printk("get_ethernet_addr: ");
|
||||
for (i=0; i<5; i++)
|
||||
printk("%02x:", (unsigned char)*(ethernet_addr+i));
|
||||
printk("%02x\n", *(ethernet_addr+i));
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init prom_free_prom_memory(void)
|
||||
{
|
||||
}
|
||||
|
||||
void __init prom_init(void)
|
||||
{
|
||||
unsigned char *memsize_str;
|
||||
unsigned long memsize;
|
||||
|
||||
prom_argc = (int) fw_arg0;
|
||||
prom_argv = (char **) fw_arg1;
|
||||
prom_envp = (char **) fw_arg2;
|
||||
|
||||
mips_machtype = MACH_INGENIC_JZ4740;
|
||||
|
||||
prom_init_cmdline();
|
||||
memsize_str = prom_getenv("memsize");
|
||||
if (!memsize_str) {
|
||||
memsize = 0x04000000;
|
||||
} else {
|
||||
memsize = simple_strtol(memsize_str, NULL, 0);
|
||||
}
|
||||
add_memory_region(0, memsize, BOOT_MEM_RAM);
|
||||
}
|
||||
|
||||
/* used by early printk */
|
||||
void prom_putchar(char c)
|
||||
{
|
||||
volatile u8 *uart_lsr = (volatile u8 *)(UART0_BASE + OFF_LSR);
|
||||
volatile u8 *uart_tdr = (volatile u8 *)(UART0_BASE + OFF_TDR);
|
||||
|
||||
/* Wait for fifo to shift out some bytes */
|
||||
while ( !((*uart_lsr & (UARTLSR_TDRQ | UARTLSR_TEMT)) == 0x60) );
|
||||
|
||||
*uart_tdr = (u8)c;
|
||||
}
|
||||
|
||||
const char *get_system_type(void)
|
||||
{
|
||||
return "JZ4740";
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(prom_getcmdline);
|
||||
EXPORT_SYMBOL(get_ethernet_addr);
|
||||
EXPORT_SYMBOL(str2eaddr);
|
||||
46
target/linux/xburst/files-2.6.27/arch/mips/jz4740/reset.c
Normal file
46
target/linux/xburst/files-2.6.27/arch/mips/jz4740/reset.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4740/reset.c
|
||||
*
|
||||
* JZ4740 reset routines.
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <yliu@ingenic.cn>
|
||||
*
|
||||
* 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/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/reboot.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
void jz_restart(char *command)
|
||||
{
|
||||
printk("Restarting after 4 ms\n");
|
||||
REG_WDT_TCSR = WDT_TCSR_PRESCALE4 | WDT_TCSR_EXT_EN;
|
||||
REG_WDT_TCNT = 0;
|
||||
REG_WDT_TDR = JZ_EXTAL/1000; /* reset after 4ms */
|
||||
REG_TCU_TSCR = TCU_TSSR_WDTSC; /* enable wdt clock */
|
||||
REG_WDT_TCER = WDT_TCER_TCEN; /* wdt start */
|
||||
while (1);
|
||||
}
|
||||
|
||||
void jz_halt(void)
|
||||
{
|
||||
printk(KERN_NOTICE "\n** You can safely turn off the power\n");
|
||||
|
||||
while (1)
|
||||
__asm__(".set\tmips3\n\t"
|
||||
"wait\n\t"
|
||||
".set\tmips0");
|
||||
}
|
||||
|
||||
void jz_power_off(void)
|
||||
{
|
||||
jz_halt();
|
||||
}
|
||||
188
target/linux/xburst/files-2.6.27/arch/mips/jz4740/setup.c
Normal file
188
target/linux/xburst/files-2.6.27/arch/mips/jz4740/setup.c
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4740/common/setup.c
|
||||
*
|
||||
* JZ4740 common setup routines.
|
||||
*
|
||||
* Copyright (C) 2006 Ingenic Semiconductor Inc.
|
||||
*
|
||||
* This program is free software; you can distribute it and/or modify it
|
||||
* under the terms of the GNU General Public License (Version 2) as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_8250.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/reboot.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#include <asm/suspend.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PC_KEYB
|
||||
#include <asm/keyboard.h>
|
||||
#endif
|
||||
|
||||
jz_clocks_t jz_clocks;
|
||||
|
||||
extern char * __init prom_getcmdline(void);
|
||||
extern void __init jz_board_setup(void);
|
||||
extern void jz_restart(char *);
|
||||
extern void jz_halt(void);
|
||||
extern void jz_power_off(void);
|
||||
extern void jz_time_init(void);
|
||||
|
||||
static void __init sysclocks_setup(void)
|
||||
{
|
||||
#ifndef CONFIG_MIPS_JZ_EMURUS /* FPGA */
|
||||
jz_clocks.cclk = __cpm_get_cclk();
|
||||
jz_clocks.hclk = __cpm_get_hclk();
|
||||
jz_clocks.pclk = __cpm_get_pclk();
|
||||
jz_clocks.mclk = __cpm_get_mclk();
|
||||
jz_clocks.lcdclk = __cpm_get_lcdclk();
|
||||
jz_clocks.pixclk = __cpm_get_pixclk();
|
||||
jz_clocks.i2sclk = __cpm_get_i2sclk();
|
||||
jz_clocks.usbclk = __cpm_get_usbclk();
|
||||
jz_clocks.mscclk = __cpm_get_mscclk();
|
||||
jz_clocks.extalclk = __cpm_get_extalclk();
|
||||
jz_clocks.rtcclk = __cpm_get_rtcclk();
|
||||
#else
|
||||
|
||||
#define FPGACLK 8000000
|
||||
|
||||
jz_clocks.cclk = FPGACLK;
|
||||
jz_clocks.hclk = FPGACLK;
|
||||
jz_clocks.pclk = FPGACLK;
|
||||
jz_clocks.mclk = FPGACLK;
|
||||
jz_clocks.lcdclk = FPGACLK;
|
||||
jz_clocks.pixclk = FPGACLK;
|
||||
jz_clocks.i2sclk = FPGACLK;
|
||||
jz_clocks.usbclk = FPGACLK;
|
||||
jz_clocks.mscclk = FPGACLK;
|
||||
jz_clocks.extalclk = FPGACLK;
|
||||
jz_clocks.rtcclk = FPGACLK;
|
||||
#endif
|
||||
|
||||
printk("CPU clock: %dMHz, System clock: %dMHz, Peripheral clock: %dMHz, Memory clock: %dMHz\n",
|
||||
(jz_clocks.cclk + 500000) / 1000000,
|
||||
(jz_clocks.hclk + 500000) / 1000000,
|
||||
(jz_clocks.pclk + 500000) / 1000000,
|
||||
(jz_clocks.mclk + 500000) / 1000000);
|
||||
}
|
||||
|
||||
static void __init soc_cpm_setup(void)
|
||||
{
|
||||
/* Start all module clocks
|
||||
*/
|
||||
__cpm_start_all();
|
||||
|
||||
/* Enable CKO to external memory */
|
||||
__cpm_enable_cko();
|
||||
|
||||
/* CPU enters IDLE mode when executing 'wait' instruction */
|
||||
__cpm_idle_mode();
|
||||
|
||||
/* Setup system clocks */
|
||||
sysclocks_setup();
|
||||
}
|
||||
|
||||
static void __init soc_harb_setup(void)
|
||||
{
|
||||
// __harb_set_priority(0x00); /* CIM>LCD>DMA>ETH>PCI>USB>CBB */
|
||||
// __harb_set_priority(0x03); /* LCD>CIM>DMA>ETH>PCI>USB>CBB */
|
||||
// __harb_set_priority(0x0a); /* ETH>LCD>CIM>DMA>PCI>USB>CBB */
|
||||
}
|
||||
|
||||
static void __init soc_emc_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void __init soc_dmac_setup(void)
|
||||
{
|
||||
__dmac_enable_module();
|
||||
}
|
||||
|
||||
static void __init jz_soc_setup(void)
|
||||
{
|
||||
soc_cpm_setup();
|
||||
soc_harb_setup();
|
||||
soc_emc_setup();
|
||||
soc_dmac_setup();
|
||||
}
|
||||
|
||||
static void __init jz_serial_setup(void)
|
||||
{
|
||||
#ifdef CONFIG_SERIAL_8250
|
||||
struct uart_port s;
|
||||
REG8(UART0_FCR) |= UARTFCR_UUE; /* enable UART module */
|
||||
memset(&s, 0, sizeof(s));
|
||||
s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
|
||||
s.iotype = SERIAL_IO_MEM;
|
||||
s.regshift = 2;
|
||||
s.uartclk = jz_clocks.extalclk ;
|
||||
|
||||
s.line = 0;
|
||||
s.membase = (u8 *)UART0_BASE;
|
||||
s.irq = IRQ_UART0;
|
||||
if (early_serial_setup(&s) != 0) {
|
||||
printk(KERN_ERR "Serial ttyS0 setup failed!\n");
|
||||
}
|
||||
|
||||
s.line = 1;
|
||||
s.membase = (u8 *)UART1_BASE;
|
||||
s.irq = IRQ_UART1;
|
||||
if (early_serial_setup(&s) != 0) {
|
||||
printk(KERN_ERR "Serial ttyS1 setup failed!\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void __init plat_mem_setup(void)
|
||||
{
|
||||
char *argptr;
|
||||
|
||||
argptr = prom_getcmdline();
|
||||
|
||||
/* IO/MEM resources. Which will be the addtion value in `inX' and
|
||||
* `outX' macros defined in asm/io.h */
|
||||
set_io_port_base(0);
|
||||
ioport_resource.start = 0x00000000;
|
||||
ioport_resource.end = 0xffffffff;
|
||||
iomem_resource.start = 0x00000000;
|
||||
iomem_resource.end = 0xffffffff;
|
||||
|
||||
_machine_restart = jz_restart;
|
||||
_machine_halt = jz_halt;
|
||||
pm_power_off = jz_power_off;
|
||||
#ifdef CONFIG_PM
|
||||
jz_pm_init();
|
||||
#endif
|
||||
jz_soc_setup();
|
||||
jz_serial_setup();
|
||||
jz_board_setup();
|
||||
}
|
||||
|
||||
159
target/linux/xburst/files-2.6.27/arch/mips/jz4740/time.c
Normal file
159
target/linux/xburst/files-2.6.27/arch/mips/jz4740/time.c
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4740/time.c
|
||||
*
|
||||
* Setting up the clock on the JZ4740 boards.
|
||||
*
|
||||
* Copyright (C) 2008 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can distribute it and/or modify it
|
||||
* under the terms of the GNU General Public License (Version 2) as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/clockchips.h>
|
||||
|
||||
#include <asm/time.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/* This is for machines which generate the exact clock. */
|
||||
|
||||
#define JZ_TIMER_CHAN 0
|
||||
#define JZ_TIMER_IRQ IRQ_TCU0
|
||||
|
||||
#define JZ_TIMER_CLOCK (JZ_EXTAL>>4) /* Jz timer clock frequency */
|
||||
|
||||
static struct clocksource clocksource_jz; /* Jz clock source */
|
||||
static struct clock_event_device jz_clockevent_device; /* Jz clock event */
|
||||
|
||||
void (*jz_timer_callback)(void);
|
||||
|
||||
static irqreturn_t jz_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct clock_event_device *cd = dev_id;
|
||||
|
||||
REG_TCU_TFCR = 1 << JZ_TIMER_CHAN; /* ACK timer */
|
||||
|
||||
if (jz_timer_callback)
|
||||
jz_timer_callback();
|
||||
|
||||
cd->event_handler(cd);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct irqaction jz_irqaction = {
|
||||
.handler = jz_timer_interrupt,
|
||||
.flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER,
|
||||
.name = "jz-timerirq",
|
||||
};
|
||||
|
||||
|
||||
cycle_t jz_get_cycles(void)
|
||||
{
|
||||
/* convert jiffes to jz timer cycles */
|
||||
return (cycle_t)( jiffies*((JZ_TIMER_CLOCK)/HZ) + REG_TCU_TCNT(JZ_TIMER_CHAN));
|
||||
}
|
||||
|
||||
static struct clocksource clocksource_jz = {
|
||||
.name = "jz_clocksource",
|
||||
.rating = 300,
|
||||
.read = jz_get_cycles,
|
||||
.mask = 0xFFFF,
|
||||
.shift = 10,
|
||||
.flags = CLOCK_SOURCE_WATCHDOG,
|
||||
};
|
||||
|
||||
static int __init jz_clocksource_init(void)
|
||||
{
|
||||
clocksource_jz.mult = clocksource_hz2mult(JZ_TIMER_CLOCK, clocksource_jz.shift);
|
||||
clocksource_register(&clocksource_jz);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jz_set_next_event(unsigned long evt,
|
||||
struct clock_event_device *unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void jz_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
break;
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct clock_event_device jz_clockevent_device = {
|
||||
.name = "jz-clockenvent",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC,
|
||||
// .features = CLOCK_EVT_FEAT_ONESHOT, /* Jz4740 not support dynamic clock now */
|
||||
|
||||
/* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */
|
||||
.mult = 1,
|
||||
.rating = 300,
|
||||
.irq = JZ_TIMER_IRQ,
|
||||
.set_mode = jz_set_mode,
|
||||
.set_next_event = jz_set_next_event,
|
||||
};
|
||||
|
||||
static void __init jz_clockevent_init(void)
|
||||
{
|
||||
struct clock_event_device *cd = &jz_clockevent_device;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
cd->cpumask = cpumask_of_cpu(cpu);
|
||||
clockevents_register_device(cd);
|
||||
}
|
||||
|
||||
static void __init jz_timer_setup(void)
|
||||
{
|
||||
jz_clocksource_init(); /* init jz clock source */
|
||||
jz_clockevent_init(); /* init jz clock event */
|
||||
|
||||
/*
|
||||
* Make irqs happen for the system timer
|
||||
*/
|
||||
jz_irqaction.dev_id = &jz_clockevent_device;
|
||||
setup_irq(JZ_TIMER_IRQ, &jz_irqaction);
|
||||
}
|
||||
|
||||
|
||||
void __init plat_time_init(void)
|
||||
{
|
||||
unsigned int latch;
|
||||
/* Init timer */
|
||||
latch = ( JZ_TIMER_CLOCK + (HZ>>1)) / HZ;
|
||||
|
||||
REG_TCU_TCSR(JZ_TIMER_CHAN) = TCU_TCSR_PRESCALE16 | TCU_TCSR_EXT_EN;
|
||||
REG_TCU_TCNT(JZ_TIMER_CHAN) = 0;
|
||||
REG_TCU_TDHR(JZ_TIMER_CHAN) = 0;
|
||||
REG_TCU_TDFR(JZ_TIMER_CHAN) = latch;
|
||||
|
||||
REG_TCU_TMSR = (1 << (JZ_TIMER_CHAN + 16)); /* mask half irq */
|
||||
REG_TCU_TMCR = (1 << JZ_TIMER_CHAN); /* unmask full irq */
|
||||
REG_TCU_TSCR = (1 << JZ_TIMER_CHAN); /* enable timer clock */
|
||||
REG_TCU_TESR = (1 << JZ_TIMER_CHAN); /* start counting up */
|
||||
|
||||
jz_timer_setup();
|
||||
}
|
||||
23
target/linux/xburst/files-2.6.27/arch/mips/jz4750/Makefile
Normal file
23
target/linux/xburst/files-2.6.27/arch/mips/jz4750/Makefile
Normal file
@@ -0,0 +1,23 @@
|
||||
#
|
||||
# Makefile for the Ingenic JZ4750.
|
||||
#
|
||||
|
||||
# Object file lists.
|
||||
|
||||
obj-y += prom.o irq.o time.o reset.o setup.o dma.o \
|
||||
platform.o i2c.o
|
||||
|
||||
obj-$(CONFIG_PROC_FS) += proc.o
|
||||
|
||||
# board specific support
|
||||
|
||||
obj-$(CONFIG_JZ4750_FUWA) += board-fuwa.o
|
||||
obj-$(CONFIG_JZ4750_APUS) += board-apus.o
|
||||
|
||||
# PM support
|
||||
|
||||
obj-$(CONFIG_PM) +=pm.o
|
||||
|
||||
# CPU Frequency scaling support
|
||||
|
||||
obj-$(CONFIG_CPU_FREQ_JZ) +=cpufreq.o
|
||||
303
target/linux/xburst/files-2.6.27/arch/mips/jz4750/board-apus.c
Normal file
303
target/linux/xburst/files-2.6.27/arch/mips/jz4750/board-apus.c
Normal file
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4750/board-apus.c
|
||||
*
|
||||
* JZ4750 APUS board setup routines.
|
||||
*
|
||||
* Copyright (c) 2006-2008 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/reboot.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
/*********************************************************************************
|
||||
* Power management routines
|
||||
********************************************************************************/
|
||||
|
||||
/*
|
||||
* __gpio_as_sleep set all pins to pull-disable, and set all pins as input
|
||||
* except sdram and the pins which can be used as CS1_N to CS4_N for chip select.
|
||||
*/
|
||||
#define __gpio_as_sleep() \
|
||||
do { \
|
||||
REG_GPIO_PXFUNC(1) = ~0x03ff7fff; \
|
||||
REG_GPIO_PXSELC(1) = ~0x03ff7fff; \
|
||||
REG_GPIO_PXDIRC(1) = ~0x03ff7fff; \
|
||||
REG_GPIO_PXPES(1) = ~0x03ff7fff; \
|
||||
REG_GPIO_PXFUNC(2) = ~0x01e00000; \
|
||||
REG_GPIO_PXSELC(2) = ~0x01e00000; \
|
||||
REG_GPIO_PXDIRC(2) = ~0x01e00000; \
|
||||
REG_GPIO_PXPES(2) = ~0x01e00000; \
|
||||
REG_GPIO_PXFUNC(3) = 0xffffffff; \
|
||||
REG_GPIO_PXSELC(3) = 0xffffffff; \
|
||||
REG_GPIO_PXDIRC(3) = 0xffffffff; \
|
||||
REG_GPIO_PXPES(3) = 0xffffffff; \
|
||||
REG_GPIO_PXFUNC(4) = 0xffffffff; \
|
||||
REG_GPIO_PXSELC(4) = 0xffffffff; \
|
||||
REG_GPIO_PXDIRC(4) = 0xffffffff; \
|
||||
REG_GPIO_PXPES(4) = 0xffffffff; \
|
||||
REG_GPIO_PXFUNC(5) = 0xffffffff; \
|
||||
REG_GPIO_PXSELC(5) = 0xffffffff; \
|
||||
REG_GPIO_PXDIRC(5) = 0xffffffff; \
|
||||
REG_GPIO_PXPES(5) = 0xffffffff; \
|
||||
} while (0)
|
||||
|
||||
extern void (*jz_timer_callback)(void);
|
||||
|
||||
struct wakeup_key_s {
|
||||
int gpio; /* gpio pin number */
|
||||
int active_low; /* the key interrupt pin is low voltage
|
||||
or fall edge acitve */
|
||||
};
|
||||
|
||||
/* add wakeup keys here */
|
||||
static struct wakeup_key_s wakeup_key[] = {
|
||||
{
|
||||
.gpio = GPIO_CALL,
|
||||
.active_low = ACTIVE_LOW_CALL,
|
||||
},
|
||||
{
|
||||
.gpio = GPIO_HOME,
|
||||
.active_low = ACTIVE_LOW_HOME,
|
||||
},
|
||||
{
|
||||
.gpio = GPIO_BACK,
|
||||
.active_low = ACTIVE_LOW_BACK,
|
||||
},
|
||||
{
|
||||
.gpio = GPIO_MENU,
|
||||
.active_low = ACTIVE_LOW_MENU,
|
||||
},
|
||||
{
|
||||
.gpio = GPIO_ENDCALL,
|
||||
.active_low = ACTIVE_LOW_ENDCALL,
|
||||
},
|
||||
{
|
||||
.gpio = GPIO_ADKEY_INT,
|
||||
.active_low = ACTIVE_LOW_ADKEY,
|
||||
},
|
||||
};
|
||||
|
||||
static void wakeup_key_setup(void)
|
||||
{
|
||||
int i;
|
||||
int num = sizeof(wakeup_key) / sizeof(wakeup_key[0]);
|
||||
|
||||
for(i = 0; i < num; i++) {
|
||||
#if 0
|
||||
if(wakeup_key[i].active_low)
|
||||
__gpio_as_irq_fall_edge(wakeup_key[i].gpio);
|
||||
else
|
||||
__gpio_as_irq_rise_edge(wakeup_key[i].gpio);
|
||||
#endif
|
||||
__gpio_ack_irq(wakeup_key[i].gpio);
|
||||
__gpio_unmask_irq(wakeup_key[i].gpio);
|
||||
__intc_unmask_irq(IRQ_GPIO0 - (wakeup_key[i].gpio/32)); /* unmask IRQ_GPIOn */
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTES:
|
||||
* 1: Pins that are floated (NC) should be set as input and pull-enable.
|
||||
* 2: Pins that are pull-up or pull-down by outside should be set as input
|
||||
* and pull-disable.
|
||||
* 3: Pins that are connected to a chip except sdram and nand flash
|
||||
* should be set as input and pull-disable, too.
|
||||
*/
|
||||
void jz_board_do_sleep(unsigned long *ptr)
|
||||
{
|
||||
unsigned char i;
|
||||
#ifdef DEBUG
|
||||
__intc_unmask_irq(IRQ_UART3);
|
||||
/* Print messages of GPIO registers for debug */
|
||||
for(i=0;i<GPIO_PORT_NUM;i++) {
|
||||
printk("run dat:%x pin:%x fun:%x sel:%x dir:%x pull:%x msk:%x trg:%x\n", \
|
||||
REG_GPIO_PXDAT(i),REG_GPIO_PXPIN(i),REG_GPIO_PXFUN(i),REG_GPIO_PXSEL(i), \
|
||||
REG_GPIO_PXDIR(i),REG_GPIO_PXPE(i),REG_GPIO_PXIM(i),REG_GPIO_PXTRG(i));
|
||||
}
|
||||
#endif
|
||||
/* Save GPIO registers */
|
||||
for(i = 1; i < GPIO_PORT_NUM; i++) {
|
||||
*ptr++ = REG_GPIO_PXFUN(i);
|
||||
*ptr++ = REG_GPIO_PXSEL(i);
|
||||
*ptr++ = REG_GPIO_PXDIR(i);
|
||||
*ptr++ = REG_GPIO_PXPE(i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mask the ethernet irq
|
||||
*/
|
||||
__gpio_mask_irq(GPIO_NET_INT);
|
||||
|
||||
/*
|
||||
* Set all pins to pull-disable, and set all pins as input except
|
||||
* sdram and the pins which can be used as CS1_N to CS4_N for chip select.
|
||||
*/
|
||||
// __gpio_as_sleep();
|
||||
|
||||
/*
|
||||
* Set proper status for GPC21 to GPC24 which can be used as CS1_N to CS4_N.
|
||||
* Keep the pins' function used for chip select(CS) here according to your
|
||||
* system to avoid chip select crashing with sdram when resuming from sleep mode.
|
||||
*/
|
||||
|
||||
/* GPB25/CS1_N is used as chip select for nand flash, shouldn't be change. */
|
||||
|
||||
/* GPB26/CS2_N is connected to nand flash, needn't be changed. */
|
||||
|
||||
/* GPB28/CS3_N is used as cs8900's chip select, shouldn't be changed. */
|
||||
|
||||
/* GPB27/CS4_N is used as NOR's chip select, shouldn't be changed. */
|
||||
|
||||
/*
|
||||
* Enable pull for NC pins here according to your system
|
||||
*/
|
||||
|
||||
/*
|
||||
* If you must set some GPIOs as output to high level or low level,
|
||||
* you can set them here, using:
|
||||
* __gpio_as_output(n);
|
||||
* __gpio_set_pin(n); or __gpio_clear_pin(n);
|
||||
*/
|
||||
|
||||
/* AMPEN_N should be set to high to disable audio amplifier */
|
||||
__gpio_as_output(GPIO_AMPEN_N);
|
||||
__gpio_set_pin(GPIO_AMPEN_N);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Keep uart function for printing debug message */
|
||||
__gpio_as_uart0();
|
||||
__gpio_as_uart1();
|
||||
__gpio_as_uart2();
|
||||
__gpio_as_uart3();
|
||||
|
||||
|
||||
/* Print messages of GPIO registers for debug */
|
||||
for(i=0;i<GPIO_PORT_NUM;i++) {
|
||||
printk("sleep dat:%x pin:%x fun:%x sel:%x dir:%x pull:%x msk:%x trg:%x\n", \
|
||||
REG_GPIO_PXDAT(i),REG_GPIO_PXPIN(i),REG_GPIO_PXFUN(i),REG_GPIO_PXSEL(i), \
|
||||
REG_GPIO_PXDIR(i),REG_GPIO_PXPE(i),REG_GPIO_PXIM(i),REG_GPIO_PXTRG(i));
|
||||
}
|
||||
__intc_mask_irq(IRQ_UART3);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Just allow following interrupts to wakeup the system.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_RTC_CLASS
|
||||
/* enable RTC alarm */
|
||||
__intc_unmask_irq(IRQ_RTC);
|
||||
#if 0
|
||||
/* make system wake up after n seconds by RTC alarm */
|
||||
unsigned int v, n;
|
||||
n = 10;
|
||||
while (!__rtc_write_ready());
|
||||
__rtc_enable_alarm();
|
||||
while (!__rtc_write_ready());
|
||||
__rtc_enable_alarm_irq();
|
||||
while (!__rtc_write_ready());
|
||||
v = __rtc_get_second();
|
||||
while (!__rtc_write_ready());
|
||||
__rtc_set_alarm_second(v+n);
|
||||
#endif
|
||||
#endif
|
||||
/* setup wakeup keys before sleeping */
|
||||
wakeup_key_setup();
|
||||
}
|
||||
|
||||
void jz_board_do_resume(unsigned long *ptr)
|
||||
{
|
||||
unsigned char i;
|
||||
|
||||
/* Restore GPIO registers */
|
||||
for(i = 1; i < GPIO_PORT_NUM; i++) {
|
||||
REG_GPIO_PXFUNS(i) = *ptr;
|
||||
REG_GPIO_PXFUNC(i) = ~(*ptr++);
|
||||
|
||||
REG_GPIO_PXSELS(i) = *ptr;
|
||||
REG_GPIO_PXSELC(i) = ~(*ptr++);
|
||||
|
||||
REG_GPIO_PXDIRS(i) = *ptr;
|
||||
REG_GPIO_PXDIRC(i) = ~(*ptr++);
|
||||
|
||||
REG_GPIO_PXPES(i) = *ptr;
|
||||
REG_GPIO_PXPEC(i) = ~(*ptr++);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
/* Print messages of GPIO registers for debug */
|
||||
for(i=0;i<GPIO_PORT_NUM;i++) {
|
||||
printk("resume dat:%x pin:%x fun:%x sel:%x dir:%x pull:%x msk:%x trg:%x\n", \
|
||||
REG_GPIO_PXDAT(i),REG_GPIO_PXPIN(i),REG_GPIO_PXFUN(i),REG_GPIO_PXSEL(i), \
|
||||
REG_GPIO_PXDIR(i),REG_GPIO_PXPE(i),REG_GPIO_PXIM(i),REG_GPIO_PXTRG(i));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*********************************************************************************
|
||||
* Basic setup routines
|
||||
********************************************************************************/
|
||||
|
||||
#if 0
|
||||
static inline void dancing(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void apus_timer_callback(void)
|
||||
{
|
||||
static unsigned long count = 0;
|
||||
|
||||
if ((++count) % 50 == 0) {
|
||||
dancing();
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void __init board_cpm_setup(void)
|
||||
{
|
||||
/* Stop unused module clocks here.
|
||||
* We have started all module clocks at arch/mips/jz4750/setup.c.
|
||||
*/
|
||||
}
|
||||
|
||||
static void __init board_gpio_setup(void)
|
||||
{
|
||||
__lcd_close_backlight();
|
||||
__gpio_as_pcm();
|
||||
}
|
||||
|
||||
void __init jz_board_setup(void)
|
||||
{
|
||||
printk("JZ4750 APUS board setup\n");
|
||||
|
||||
board_cpm_setup();
|
||||
board_gpio_setup();
|
||||
|
||||
jz_timer_callback = NULL;/* apus_timer_callback; */
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by arch/mips/kernel/proc.c when 'cat /proc/cpuinfo'.
|
||||
* Android requires the 'Hardware:' field in cpuinfo to setup the init.%hardware%.rc.
|
||||
*/
|
||||
const char *get_board_type(void)
|
||||
{
|
||||
return "apus";
|
||||
}
|
||||
114
target/linux/xburst/files-2.6.27/arch/mips/jz4750/board-fuwa.c
Normal file
114
target/linux/xburst/files-2.6.27/arch/mips/jz4750/board-fuwa.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4750/board-fuwa.c
|
||||
*
|
||||
* JZ4750 FUWA board setup routines.
|
||||
*
|
||||
* Copyright (c) 2006-2008 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/reboot.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
extern void (*jz_timer_callback)(void);
|
||||
|
||||
static void dancing(void)
|
||||
{
|
||||
static unsigned char slash[] = "\\|/-";
|
||||
// static volatile unsigned char *p = (unsigned char *)0xb6000058;
|
||||
static volatile unsigned char *p = (unsigned char *)0xb6000016;
|
||||
static unsigned int count = 0;
|
||||
*p = slash[count++];
|
||||
count &= 3;
|
||||
}
|
||||
|
||||
static void fuwa_timer_callback(void)
|
||||
{
|
||||
static unsigned long count = 0;
|
||||
|
||||
if ((++count) % 50 == 0) {
|
||||
dancing();
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init board_cpm_setup(void)
|
||||
{
|
||||
/* Stop unused module clocks here.
|
||||
* We have started all module clocks at arch/mips/jz4750/setup.c.
|
||||
*/
|
||||
}
|
||||
|
||||
static void __init board_gpio_setup(void)
|
||||
{
|
||||
/*
|
||||
* Initialize SDRAM pins
|
||||
*/
|
||||
|
||||
/* PORT A: D0 ~ D31 */
|
||||
REG_GPIO_PXFUNS(0) = 0xffffffff;
|
||||
REG_GPIO_PXSELC(0) = 0xffffffff;
|
||||
|
||||
/* PORT B: A0 ~ A16, DCS#, RAS#, CAS#, CKE#, RDWE#, CKO#, WE0# */
|
||||
REG_GPIO_PXFUNS(1) = 0x81f9ffff;
|
||||
REG_GPIO_PXSELC(1) = 0x81f9ffff;
|
||||
|
||||
/* PORT C: WE1#, WE2#, WE3# */
|
||||
REG_GPIO_PXFUNS(2) = 0x07000000;
|
||||
REG_GPIO_PXSELC(2) = 0x07000000;
|
||||
|
||||
|
||||
/*
|
||||
* Initialize UART0 pins
|
||||
*/
|
||||
|
||||
/* PORT D: TXD/RXD */
|
||||
REG_GPIO_PXFUNS(3) = 0x06000000;
|
||||
REG_GPIO_PXSELS(3) = 0x06000000;
|
||||
|
||||
|
||||
/*
|
||||
* Initialize LED pins
|
||||
*/
|
||||
__gpio_as_lcd_18bit();
|
||||
|
||||
/* CS2# */
|
||||
REG_GPIO_PXFUNS(1) = 0x04000000;
|
||||
REG_GPIO_PXSELC(1) = 0x04000000;
|
||||
|
||||
__gpio_as_pcm();
|
||||
}
|
||||
|
||||
void __init jz_board_setup(void)
|
||||
{
|
||||
printk("JZ4750 FUWA board setup\n");
|
||||
|
||||
board_cpm_setup();
|
||||
board_gpio_setup();
|
||||
|
||||
jz_timer_callback = fuwa_timer_callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by arch/mips/kernel/proc.c when 'cat /proc/cpuinfo'.
|
||||
* Android requires the 'Hardware:' field in cpuinfo to setup the init.%hardware%.rc.
|
||||
*/
|
||||
const char *get_board_type(void)
|
||||
{
|
||||
return "fuwa";
|
||||
}
|
||||
601
target/linux/xburst/files-2.6.27/arch/mips/jz4750/cpufreq.c
Normal file
601
target/linux/xburst/files-2.6.27/arch/mips/jz4750/cpufreq.c
Normal file
@@ -0,0 +1,601 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4750/cpufreq.c
|
||||
*
|
||||
* cpufreq driver for JZ4750
|
||||
*
|
||||
* Copyright (c) 2006-2008 Ingenic Semiconductor Inc.
|
||||
* Author: <lhhuang@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <linux/cpufreq.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
|
||||
"cpufreq-jz4750", msg)
|
||||
|
||||
#undef CHANGE_PLL
|
||||
|
||||
#define PLL_UNCHANGED 0
|
||||
#define PLL_GOES_UP 1
|
||||
#define PLL_GOES_DOWN 2
|
||||
|
||||
#define PLL_WAIT_500NS (500*(__cpm_get_cclk()/1000000000))
|
||||
|
||||
/* Saved the boot-time parameters */
|
||||
static struct {
|
||||
/* SDRAM parameters */
|
||||
unsigned int mclk; /* memory clock, KHz */
|
||||
unsigned int tras; /* RAS pulse width, cycles of mclk */
|
||||
unsigned int rcd; /* RAS to CAS Delay, cycles of mclk */
|
||||
unsigned int tpc; /* RAS Precharge time, cycles of mclk */
|
||||
unsigned int trwl; /* Write Precharge Time, cycles of mclk */
|
||||
unsigned int trc; /* RAS Cycle Time, cycles of mclk */
|
||||
unsigned int rtcor; /* Refresh Time Constant */
|
||||
unsigned int sdram_initialized;
|
||||
|
||||
/* LCD parameters */
|
||||
unsigned int lcd_clk; /* LCD clock, Hz */
|
||||
unsigned int lcdpix_clk; /* LCD Pixel clock, Hz */
|
||||
unsigned int lcd_clks_initialized;
|
||||
} boot_config;
|
||||
|
||||
struct jz4750_freq_percpu_info {
|
||||
struct cpufreq_frequency_table table[7];
|
||||
};
|
||||
|
||||
static struct jz4750_freq_percpu_info jz4750_freq_table;
|
||||
|
||||
/*
|
||||
* This contains the registers value for an operating point.
|
||||
* If only part of a register needs to change then there is
|
||||
* a mask value for that register.
|
||||
* When going to a new operating point the current register
|
||||
* value is ANDed with the ~mask and ORed with the new value.
|
||||
*/
|
||||
struct dpm_regs {
|
||||
u32 cpccr; /* Clock Freq Control Register */
|
||||
u32 cpccr_mask; /* Clock Freq Control Register mask */
|
||||
u32 cppcr; /* PLL1 Control Register */
|
||||
u32 cppcr_mask; /* PLL1 Control Register mask */
|
||||
u32 pll_up_flag; /* New PLL freq is higher than current or not */
|
||||
};
|
||||
|
||||
extern jz_clocks_t jz_clocks;
|
||||
|
||||
static void jz_update_clocks(void)
|
||||
{
|
||||
/* Next clocks must be updated if we have changed
|
||||
* the PLL or divisors.
|
||||
*/
|
||||
jz_clocks.cclk = __cpm_get_cclk();
|
||||
jz_clocks.hclk = __cpm_get_hclk();
|
||||
jz_clocks.mclk = __cpm_get_mclk();
|
||||
jz_clocks.pclk = __cpm_get_pclk();
|
||||
jz_clocks.lcdclk = __cpm_get_lcdclk();
|
||||
jz_clocks.pixclk = __cpm_get_pixclk();
|
||||
jz_clocks.i2sclk = __cpm_get_i2sclk();
|
||||
jz_clocks.usbclk = __cpm_get_usbclk();
|
||||
jz_clocks.mscclk = __cpm_get_mscclk(0);
|
||||
}
|
||||
|
||||
static void
|
||||
jz_init_boot_config(void)
|
||||
{
|
||||
if (!boot_config.lcd_clks_initialized) {
|
||||
/* the first time to scale pll */
|
||||
boot_config.lcd_clk = __cpm_get_lcdclk();
|
||||
boot_config.lcdpix_clk = __cpm_get_pixclk();
|
||||
boot_config.lcd_clks_initialized = 1;
|
||||
}
|
||||
|
||||
if (!boot_config.sdram_initialized) {
|
||||
/* the first time to scale frequencies */
|
||||
unsigned int dmcr, rtcor;
|
||||
unsigned int tras, rcd, tpc, trwl, trc;
|
||||
|
||||
dmcr = REG_EMC_DMCR;
|
||||
rtcor = REG_EMC_RTCOR;
|
||||
|
||||
tras = (dmcr >> 13) & 0x7;
|
||||
rcd = (dmcr >> 11) & 0x3;
|
||||
tpc = (dmcr >> 8) & 0x7;
|
||||
trwl = (dmcr >> 5) & 0x3;
|
||||
trc = (dmcr >> 2) & 0x7;
|
||||
|
||||
boot_config.mclk = __cpm_get_mclk() / 1000;
|
||||
boot_config.tras = tras + 4;
|
||||
boot_config.rcd = rcd + 1;
|
||||
boot_config.tpc = tpc + 1;
|
||||
boot_config.trwl = trwl + 1;
|
||||
boot_config.trc = trc * 2 + 1;
|
||||
boot_config.rtcor = rtcor;
|
||||
|
||||
boot_config.sdram_initialized = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void jz_update_dram_rtcor(unsigned int new_mclk)
|
||||
{
|
||||
unsigned int rtcor;
|
||||
|
||||
new_mclk /= 1000;
|
||||
rtcor = boot_config.rtcor * new_mclk / boot_config.mclk;
|
||||
rtcor--;
|
||||
|
||||
if (rtcor < 1) rtcor = 1;
|
||||
if (rtcor > 255) rtcor = 255;
|
||||
|
||||
REG_EMC_RTCOR = rtcor;
|
||||
REG_EMC_RTCNT = rtcor;
|
||||
}
|
||||
|
||||
static void jz_update_dram_dmcr(unsigned int new_mclk)
|
||||
{
|
||||
unsigned int dmcr;
|
||||
unsigned int tras, rcd, tpc, trwl, trc;
|
||||
unsigned int valid_time, new_time; /* ns */
|
||||
|
||||
new_mclk /= 1000;
|
||||
tras = boot_config.tras * new_mclk / boot_config.mclk;
|
||||
rcd = boot_config.rcd * new_mclk / boot_config.mclk;
|
||||
tpc = boot_config.tpc * new_mclk / boot_config.mclk;
|
||||
trwl = boot_config.trwl * new_mclk / boot_config.mclk;
|
||||
trc = boot_config.trc * new_mclk / boot_config.mclk;
|
||||
|
||||
/* Validation checking */
|
||||
valid_time = (boot_config.tras * 1000000) / boot_config.mclk;
|
||||
new_time = (tras * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) tras += 1;
|
||||
|
||||
valid_time = (boot_config.rcd * 1000000) / boot_config.mclk;
|
||||
new_time = (rcd * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) rcd += 1;
|
||||
|
||||
valid_time = (boot_config.tpc * 1000000) / boot_config.mclk;
|
||||
new_time = (tpc * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) tpc += 1;
|
||||
|
||||
valid_time = (boot_config.trwl * 1000000) / boot_config.mclk;
|
||||
new_time = (trwl * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) trwl += 1;
|
||||
|
||||
valid_time = (boot_config.trc * 1000000) / boot_config.mclk;
|
||||
new_time = (trc * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) trc += 2;
|
||||
|
||||
tras = (tras < 4) ? 4: tras;
|
||||
tras = (tras > 11) ? 11: tras;
|
||||
tras -= 4;
|
||||
|
||||
rcd = (rcd < 1) ? 1: rcd;
|
||||
rcd = (rcd > 4) ? 4: rcd;
|
||||
rcd -= 1;
|
||||
|
||||
tpc = (tpc < 1) ? 1: tpc;
|
||||
tpc = (tpc > 8) ? 8: tpc;
|
||||
tpc -= 1;
|
||||
|
||||
trwl = (trwl < 1) ? 1: trwl;
|
||||
trwl = (trwl > 4) ? 4: trwl;
|
||||
trwl -= 1;
|
||||
|
||||
trc = (trc < 1) ? 1: trc;
|
||||
trc = (trc > 15) ? 15: trc;
|
||||
trc /= 2;
|
||||
|
||||
dmcr = REG_EMC_DMCR;
|
||||
|
||||
dmcr &= ~(EMC_DMCR_TRAS_MASK | EMC_DMCR_RCD_MASK | EMC_DMCR_TPC_MASK | EMC_DMCR_TRWL_MASK | EMC_DMCR_TRC_MASK);
|
||||
dmcr |= ((tras << EMC_DMCR_TRAS_BIT) | (rcd << EMC_DMCR_RCD_BIT) | (tpc << EMC_DMCR_TPC_BIT) | (trwl << EMC_DMCR_TRWL_BIT) | (trc << EMC_DMCR_TRC_BIT));
|
||||
|
||||
REG_EMC_DMCR = dmcr;
|
||||
}
|
||||
|
||||
static void jz_update_dram_prev(unsigned int cur_mclk, unsigned int new_mclk)
|
||||
{
|
||||
/* No risk, no fun: run with interrupts on! */
|
||||
if (new_mclk > cur_mclk) {
|
||||
/* We're going FASTER, so first update TRAS, RCD, TPC, TRWL
|
||||
* and TRC of DMCR before changing the frequency.
|
||||
*/
|
||||
jz_update_dram_dmcr(new_mclk);
|
||||
} else {
|
||||
/* We're going SLOWER: first update RTCOR value
|
||||
* before changing the frequency.
|
||||
*/
|
||||
jz_update_dram_rtcor(new_mclk);
|
||||
}
|
||||
}
|
||||
|
||||
static void jz_update_dram_post(unsigned int cur_mclk, unsigned int new_mclk)
|
||||
{
|
||||
/* No risk, no fun: run with interrupts on! */
|
||||
if (new_mclk > cur_mclk) {
|
||||
/* We're going FASTER, so update RTCOR
|
||||
* after changing the frequency
|
||||
*/
|
||||
jz_update_dram_rtcor(new_mclk);
|
||||
} else {
|
||||
/* We're going SLOWER: so update TRAS, RCD, TPC, TRWL
|
||||
* and TRC of DMCR after changing the frequency.
|
||||
*/
|
||||
jz_update_dram_dmcr(new_mclk);
|
||||
}
|
||||
}
|
||||
|
||||
static void jz_scale_divisors(struct dpm_regs *regs)
|
||||
{
|
||||
unsigned int cpccr;
|
||||
unsigned int cur_mclk, new_mclk;
|
||||
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
|
||||
unsigned int tmp = 0, wait = PLL_WAIT_500NS;
|
||||
|
||||
cpccr = REG_CPM_CPCCR;
|
||||
cpccr &= ~((unsigned long)regs->cpccr_mask);
|
||||
cpccr |= regs->cpccr;
|
||||
cpccr |= CPM_CPCCR_CE; /* update immediately */
|
||||
|
||||
cur_mclk = __cpm_get_mclk();
|
||||
new_mclk = __cpm_get_pllout() / div[(cpccr & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT];
|
||||
|
||||
/* Update some DRAM parameters before changing frequency */
|
||||
jz_update_dram_prev(cur_mclk, new_mclk);
|
||||
|
||||
/* update register to change the clocks.
|
||||
* align this code to a cache line.
|
||||
*/
|
||||
__asm__ __volatile__(
|
||||
".set noreorder\n\t"
|
||||
".align 5\n"
|
||||
"sw %1,0(%0)\n\t"
|
||||
"li %3,0\n\t"
|
||||
"1:\n\t"
|
||||
"bne %3,%2,1b\n\t"
|
||||
"addi %3, 1\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
".set reorder\n\t"
|
||||
:
|
||||
: "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp));
|
||||
|
||||
/* Update some other DRAM parameters after changing frequency */
|
||||
jz_update_dram_post(cur_mclk, new_mclk);
|
||||
}
|
||||
|
||||
#ifdef CHANGE_PLL
|
||||
/* Maintain the LCD clock and pixel clock */
|
||||
static void jz_scale_lcd_divisors(struct dpm_regs *regs)
|
||||
{
|
||||
unsigned int new_pll, new_lcd_div, new_lcdpix_div;
|
||||
unsigned int cpccr;
|
||||
unsigned int tmp = 0, wait = PLL_WAIT_500NS;
|
||||
|
||||
if (!boot_config.lcd_clks_initialized) return;
|
||||
|
||||
new_pll = __cpm_get_pllout();
|
||||
new_lcd_div = new_pll / boot_config.lcd_clk;
|
||||
new_lcdpix_div = new_pll / boot_config.lcdpix_clk;
|
||||
|
||||
if (new_lcd_div < 1)
|
||||
new_lcd_div = 1;
|
||||
if (new_lcd_div > 16)
|
||||
new_lcd_div = 16;
|
||||
|
||||
if (new_lcdpix_div < 1)
|
||||
new_lcdpix_div = 1;
|
||||
if (new_lcdpix_div > 512)
|
||||
new_lcdpix_div = 512;
|
||||
|
||||
// REG_CPM_CPCCR2 = new_lcdpix_div - 1;
|
||||
|
||||
cpccr = REG_CPM_CPCCR;
|
||||
cpccr &= ~CPM_CPCCR_LDIV_MASK;
|
||||
cpccr |= ((new_lcd_div - 1) << CPM_CPCCR_LDIV_BIT);
|
||||
cpccr |= CPM_CPCCR_CE; /* update immediately */
|
||||
|
||||
/* update register to change the clocks.
|
||||
* align this code to a cache line.
|
||||
*/
|
||||
__asm__ __volatile__(
|
||||
".set noreorder\n\t"
|
||||
".align 5\n"
|
||||
"sw %1,0(%0)\n\t"
|
||||
"li %3,0\n\t"
|
||||
"1:\n\t"
|
||||
"bne %3,%2,1b\n\t"
|
||||
"addi %3, 1\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
".set reorder\n\t"
|
||||
:
|
||||
: "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp));
|
||||
}
|
||||
|
||||
static void jz_scale_pll(struct dpm_regs *regs)
|
||||
{
|
||||
unsigned int cppcr;
|
||||
unsigned int cur_mclk, new_mclk, new_pll;
|
||||
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
|
||||
int od[] = {1, 2, 2, 4};
|
||||
|
||||
cppcr = REG_CPM_CPPCR;
|
||||
cppcr &= ~(regs->cppcr_mask | CPM_CPPCR_PLLS | CPM_CPPCR_PLLEN | CPM_CPPCR_PLLST_MASK);
|
||||
regs->cppcr &= ~CPM_CPPCR_PLLEN;
|
||||
cppcr |= (regs->cppcr | 0xff);
|
||||
|
||||
/* Update some DRAM parameters before changing frequency */
|
||||
new_pll = JZ_EXTAL * ((cppcr>>23)+2) / ((((cppcr>>18)&0x1f)+2) * od[(cppcr>>16)&0x03]);
|
||||
cur_mclk = __cpm_get_mclk();
|
||||
new_mclk = new_pll / div[(REG_CPM_CPCCR>>16) & 0xf];
|
||||
|
||||
/*
|
||||
* Update some SDRAM parameters
|
||||
*/
|
||||
jz_update_dram_prev(cur_mclk, new_mclk);
|
||||
|
||||
/*
|
||||
* Update PLL, align code to cache line.
|
||||
*/
|
||||
cppcr |= CPM_CPPCR_PLLEN;
|
||||
__asm__ __volatile__(
|
||||
".set noreorder\n\t"
|
||||
".align 5\n"
|
||||
"sw %1,0(%0)\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
".set reorder\n\t"
|
||||
:
|
||||
: "r" (CPM_CPPCR), "r" (cppcr));
|
||||
|
||||
/* Update some other DRAM parameters after changing frequency */
|
||||
jz_update_dram_post(cur_mclk, new_mclk);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void jz4750_transition(struct dpm_regs *regs)
|
||||
{
|
||||
/*
|
||||
* Get and save some boot-time conditions.
|
||||
*/
|
||||
jz_init_boot_config();
|
||||
|
||||
#ifdef CHANGE_PLL
|
||||
/*
|
||||
* Disable LCD before scaling pll.
|
||||
* LCD and LCD pixel clocks should not be changed even if the PLL
|
||||
* output frequency has been changed.
|
||||
*/
|
||||
REG_LCD_CTRL &= ~LCD_CTRL_ENA;
|
||||
|
||||
/*
|
||||
* Stop module clocks before scaling PLL
|
||||
*/
|
||||
__cpm_stop_eth();
|
||||
__cpm_stop_aic(1);
|
||||
__cpm_stop_aic(2);
|
||||
#endif
|
||||
|
||||
/* ... add more as necessary */
|
||||
|
||||
if (regs->pll_up_flag == PLL_GOES_UP) {
|
||||
/* the pll frequency is going up, so change dividors first */
|
||||
jz_scale_divisors(regs);
|
||||
#ifdef CHANGE_PLL
|
||||
jz_scale_pll(regs);
|
||||
#endif
|
||||
}
|
||||
else if (regs->pll_up_flag == PLL_GOES_DOWN) {
|
||||
/* the pll frequency is going down, so change pll first */
|
||||
#ifdef CHANGE_PLL
|
||||
jz_scale_pll(regs);
|
||||
#endif
|
||||
jz_scale_divisors(regs);
|
||||
}
|
||||
else {
|
||||
/* the pll frequency is unchanged, so change divisors only */
|
||||
jz_scale_divisors(regs);
|
||||
}
|
||||
|
||||
#ifdef CHANGE_PLL
|
||||
/*
|
||||
* Restart module clocks before scaling PLL
|
||||
*/
|
||||
__cpm_start_eth();
|
||||
__cpm_start_aic(1);
|
||||
__cpm_start_aic(2);
|
||||
|
||||
/* ... add more as necessary */
|
||||
|
||||
/* Scale the LCD divisors after scaling pll */
|
||||
if (regs->pll_up_flag != PLL_UNCHANGED) {
|
||||
jz_scale_lcd_divisors(regs);
|
||||
}
|
||||
|
||||
/* Enable LCD controller */
|
||||
REG_LCD_CTRL &= ~LCD_CTRL_DIS;
|
||||
REG_LCD_CTRL |= LCD_CTRL_ENA;
|
||||
#endif
|
||||
|
||||
/* Update system clocks */
|
||||
jz_update_clocks();
|
||||
}
|
||||
|
||||
extern unsigned int idle_times;
|
||||
static unsigned int jz4750_freq_get(unsigned int cpu)
|
||||
{
|
||||
return (__cpm_get_cclk() / 1000);
|
||||
}
|
||||
|
||||
static unsigned int index_to_divisor(unsigned int index, struct dpm_regs *regs)
|
||||
{
|
||||
int n2FR[33] = {
|
||||
0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0,
|
||||
7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
|
||||
9
|
||||
};
|
||||
int div[4] = {1, 2, 2, 2}; /* divisors of I:S:P:M */
|
||||
unsigned int div_of_cclk, new_freq, i;
|
||||
|
||||
regs->pll_up_flag = PLL_UNCHANGED;
|
||||
regs->cpccr_mask = CPM_CPCCR_CDIV_MASK | CPM_CPCCR_HDIV_MASK | CPM_CPCCR_PDIV_MASK | CPM_CPCCR_MDIV_MASK;
|
||||
|
||||
new_freq = jz4750_freq_table.table[index].frequency;
|
||||
|
||||
do {
|
||||
div_of_cclk = __cpm_get_pllout() / (1000 * new_freq);
|
||||
} while (div_of_cclk==0);
|
||||
|
||||
if(div_of_cclk == 1 || div_of_cclk == 2 || div_of_cclk == 4) {
|
||||
for(i = 1; i<4; i++) {
|
||||
div[i] = 3;
|
||||
}
|
||||
} else {
|
||||
for(i = 1; i<4; i++) {
|
||||
div[i] = 2;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i<4; i++) {
|
||||
div[i] *= div_of_cclk;
|
||||
}
|
||||
|
||||
dprintk("divisors of I:S:P:M = %d:%d:%d:%d\n", div[0], div[1], div[2], div[3]);
|
||||
|
||||
regs->cpccr =
|
||||
(n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) |
|
||||
(n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) |
|
||||
(n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) |
|
||||
(n2FR[div[3]] << CPM_CPCCR_MDIV_BIT);
|
||||
|
||||
return div_of_cclk;
|
||||
}
|
||||
|
||||
static void jz4750_set_cpu_divider_index(unsigned int cpu, unsigned int index)
|
||||
{
|
||||
unsigned long divisor, old_divisor;
|
||||
struct cpufreq_freqs freqs;
|
||||
struct dpm_regs regs;
|
||||
|
||||
old_divisor = __cpm_get_pllout() / __cpm_get_cclk();
|
||||
divisor = index_to_divisor(index, ®s);
|
||||
|
||||
freqs.old = __cpm_get_cclk() / 1000;
|
||||
freqs.new = __cpm_get_pllout() / (1000 * divisor);
|
||||
freqs.cpu = cpu;
|
||||
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
|
||||
if (old_divisor != divisor)
|
||||
jz4750_transition(®s);
|
||||
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
}
|
||||
|
||||
static int jz4750_freq_target(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation)
|
||||
{
|
||||
unsigned int new_index = 0;
|
||||
|
||||
if (cpufreq_frequency_table_target(policy,
|
||||
&jz4750_freq_table.table[0],
|
||||
target_freq, relation, &new_index))
|
||||
return -EINVAL;
|
||||
|
||||
jz4750_set_cpu_divider_index(policy->cpu, new_index);
|
||||
|
||||
dprintk("new frequency is %d KHz (REG_CPM_CPCCR:0x%x)\n", __cpm_get_cclk() / 1000, REG_CPM_CPCCR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jz4750_freq_verify(struct cpufreq_policy *policy)
|
||||
{
|
||||
return cpufreq_frequency_table_verify(policy,
|
||||
&jz4750_freq_table.table[0]);
|
||||
}
|
||||
|
||||
static int __init jz4750_cpufreq_driver_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
|
||||
struct cpufreq_frequency_table *table = &jz4750_freq_table.table[0];
|
||||
unsigned int MAX_FREQ;
|
||||
|
||||
dprintk(KERN_INFO "Jz4750 cpufreq driver\n");
|
||||
|
||||
if (policy->cpu != 0)
|
||||
return -EINVAL;
|
||||
|
||||
policy->cur = MAX_FREQ = __cpm_get_cclk() / 1000; /* in kHz. Current and max frequency is determined by u-boot */
|
||||
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
|
||||
|
||||
policy->cpuinfo.min_freq = MAX_FREQ/8;
|
||||
policy->cpuinfo.max_freq = MAX_FREQ;
|
||||
policy->cpuinfo.transition_latency = 100000; /* in 10^(-9) s = nanoseconds */
|
||||
|
||||
table[0].index = 0;
|
||||
table[0].frequency = MAX_FREQ/8;
|
||||
table[1].index = 1;
|
||||
table[1].frequency = MAX_FREQ/6;
|
||||
table[2].index = 2;
|
||||
table[2].frequency = MAX_FREQ/4;
|
||||
table[3].index = 3;
|
||||
table[3].frequency = MAX_FREQ/3;
|
||||
table[4].index = 4;
|
||||
table[4].frequency = MAX_FREQ/2;
|
||||
table[5].index = 5;
|
||||
table[5].frequency = MAX_FREQ;
|
||||
table[6].index = 6;
|
||||
table[6].frequency = CPUFREQ_TABLE_END;
|
||||
|
||||
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
|
||||
cpufreq_frequency_table_get_attr(table, policy->cpu); /* for showing /sys/devices/system/cpu/cpuX/cpufreq/stats/ */
|
||||
#endif
|
||||
|
||||
return cpufreq_frequency_table_cpuinfo(policy, table);
|
||||
}
|
||||
|
||||
static struct cpufreq_driver cpufreq_jz4750_driver = {
|
||||
// .flags = CPUFREQ_STICKY,
|
||||
.init = jz4750_cpufreq_driver_init,
|
||||
.verify = jz4750_freq_verify,
|
||||
.target = jz4750_freq_target,
|
||||
.get = jz4750_freq_get,
|
||||
.name = "jz4750",
|
||||
};
|
||||
|
||||
static int __init jz4750_cpufreq_init(void)
|
||||
{
|
||||
return cpufreq_register_driver(&cpufreq_jz4750_driver);
|
||||
}
|
||||
|
||||
static void __exit jz4750_cpufreq_exit(void)
|
||||
{
|
||||
cpufreq_unregister_driver(&cpufreq_jz4750_driver);
|
||||
}
|
||||
|
||||
module_init(jz4750_cpufreq_init);
|
||||
module_exit(jz4750_cpufreq_exit);
|
||||
|
||||
MODULE_AUTHOR("Regen <lhhuang@ingenic.cn>");
|
||||
MODULE_DESCRIPTION("cpufreq driver for Jz4750");
|
||||
MODULE_LICENSE("GPL");
|
||||
836
target/linux/xburst/files-2.6.27/arch/mips/jz4750/dma.c
Normal file
836
target/linux/xburst/files-2.6.27/arch/mips/jz4750/dma.c
Normal file
@@ -0,0 +1,836 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4750/dma.c
|
||||
*
|
||||
* Support functions for the JZ4750 internal DMA channels.
|
||||
* No-descriptor transfer only.
|
||||
* Descriptor transfer should also call jz_request_dma() to get a free
|
||||
* channel and call jz_free_dma() to free the channel. And driver should
|
||||
* build the DMA descriptor and setup the DMA channel by itself.
|
||||
*
|
||||
* Copyright (C) 2006 - 2008 Ingenic Semiconductor Inc.
|
||||
*
|
||||
* 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/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/soundcard.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/*
|
||||
* A note on resource allocation:
|
||||
*
|
||||
* All drivers needing DMA channels, should allocate and release them
|
||||
* through the public routines `jz_request_dma()' and `jz_free_dma()'.
|
||||
*
|
||||
* In order to avoid problems, all processes should allocate resources in
|
||||
* the same sequence and release them in the reverse order.
|
||||
*
|
||||
* So, when allocating DMAs and IRQs, first allocate the DMA, then the IRQ.
|
||||
* When releasing them, first release the IRQ, then release the DMA. The
|
||||
* main reason for this order is that, if you are requesting the DMA buffer
|
||||
* done interrupt, you won't know the irq number until the DMA channel is
|
||||
* returned from jz_request_dma().
|
||||
*/
|
||||
|
||||
struct jz_dma_chan jz_dma_table[MAX_DMA_NUM] = {
|
||||
{dev_id:DMA_ID_BCH_ENC,}, /* DMAC0 channel 0, reserved for BCH */
|
||||
{dev_id:-1,}, /* DMAC0 channel 1 */
|
||||
{dev_id:-1,}, /* DMAC0 channel 2 */
|
||||
{dev_id:-1,}, /* DMAC0 channel 3 */
|
||||
{dev_id:-1,}, /* DMAC0 channel 4 */
|
||||
{dev_id:-1,}, /* DMAC0 channel 5 */
|
||||
{dev_id:-1,}, /* DMAC1 channel 0 */
|
||||
{dev_id:-1,}, /* DMAC1 channel 1 */
|
||||
{dev_id:-1,}, /* DMAC1 channel 2 */
|
||||
{dev_id:-1,}, /* DMAC1 channel 3 */
|
||||
{dev_id:-1,}, /* DMAC1 channel 4 */
|
||||
{dev_id:-1,}, /* DMAC1 channel 5 */
|
||||
};
|
||||
|
||||
// Device FIFO addresses and default DMA modes
|
||||
static const struct {
|
||||
unsigned int fifo_addr;
|
||||
unsigned int dma_mode;
|
||||
unsigned int dma_source;
|
||||
} dma_dev_table[DMA_ID_MAX] = {
|
||||
{0, DMA_AUTOINIT, DMAC_DRSR_RS_EXT}, /* External request with DREQn */
|
||||
{0x18000000, DMA_AUTOINIT, DMAC_DRSR_RS_NAND}, /* NAND request */
|
||||
{CPHYSADDR(BCH_DR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_BCH_ENC},
|
||||
{CPHYSADDR(BCH_DR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_BCH_DEC},
|
||||
{0, DMA_AUTOINIT, DMAC_DRSR_RS_AUTO},
|
||||
// {CPHYSADDR(TSSI_FIFO), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_TSSIIN},
|
||||
{CPHYSADDR(UART3_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART3OUT},
|
||||
{CPHYSADDR(UART3_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART3IN},
|
||||
{CPHYSADDR(UART2_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART2OUT},
|
||||
{CPHYSADDR(UART2_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART2IN},
|
||||
{CPHYSADDR(UART1_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART1OUT},
|
||||
{CPHYSADDR(UART1_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART1IN},
|
||||
{CPHYSADDR(UART0_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART0OUT},
|
||||
{CPHYSADDR(UART0_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART0IN},
|
||||
{CPHYSADDR(SSI_DR(0)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_SSI0OUT},
|
||||
{CPHYSADDR(SSI_DR(0)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SSI0IN},
|
||||
{CPHYSADDR(AIC_DR), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_AICOUT},
|
||||
{CPHYSADDR(AIC_DR), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_AICIN},
|
||||
{CPHYSADDR(MSC_TXFIFO(0)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_MSC0OUT},
|
||||
{CPHYSADDR(MSC_RXFIFO(0)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_MSC0IN},
|
||||
{0, DMA_AUTOINIT, DMAC_DRSR_RS_TCU},
|
||||
{SADC_TSDAT, DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SADC},/* Touch Screen Data Register */
|
||||
{CPHYSADDR(MSC_TXFIFO(1)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_MSC1OUT}, /* SSC1 TX */
|
||||
{CPHYSADDR(MSC_RXFIFO(1)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_MSC1IN}, /* SSC1 RX */
|
||||
{CPHYSADDR(SSI_DR(1)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_SSI1OUT},
|
||||
{CPHYSADDR(SSI_DR(1)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SSI1IN},
|
||||
{CPHYSADDR(PCM_DP), DMA_16BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_PMOUT},
|
||||
{CPHYSADDR(PCM_DP), DMA_16BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_PMIN},
|
||||
{},
|
||||
};
|
||||
|
||||
|
||||
int jz_dma_read_proc(char *buf, char **start, off_t fpos,
|
||||
int length, int *eof, void *data)
|
||||
{
|
||||
int i, len = 0;
|
||||
struct jz_dma_chan *chan;
|
||||
|
||||
for (i = 0; i < MAX_DMA_NUM; i++) {
|
||||
if ((chan = get_dma_chan(i)) != NULL) {
|
||||
len += sprintf(buf + len, "%2d: %s\n",
|
||||
i, chan->dev_str);
|
||||
}
|
||||
}
|
||||
|
||||
if (fpos >= len) {
|
||||
*start = buf;
|
||||
*eof = 1;
|
||||
return 0;
|
||||
}
|
||||
*start = buf + fpos;
|
||||
if ((len -= fpos) > length)
|
||||
return length;
|
||||
*eof = 1;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
void dump_jz_dma_channel(unsigned int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan;
|
||||
|
||||
if (dmanr > MAX_DMA_NUM)
|
||||
return;
|
||||
chan = &jz_dma_table[dmanr];
|
||||
|
||||
printk("DMA%d Registers:\n", dmanr);
|
||||
printk(" DMACR = 0x%08x\n", REG_DMAC_DMACR(chan->io/HALF_DMA_NUM));
|
||||
printk(" DSAR = 0x%08x\n", REG_DMAC_DSAR(dmanr));
|
||||
printk(" DTAR = 0x%08x\n", REG_DMAC_DTAR(dmanr));
|
||||
printk(" DTCR = 0x%08x\n", REG_DMAC_DTCR(dmanr));
|
||||
printk(" DRSR = 0x%08x\n", REG_DMAC_DRSR(dmanr));
|
||||
printk(" DCCSR = 0x%08x\n", REG_DMAC_DCCSR(dmanr));
|
||||
printk(" DCMD = 0x%08x\n", REG_DMAC_DCMD(dmanr));
|
||||
printk(" DDA = 0x%08x\n", REG_DMAC_DDA(dmanr));
|
||||
printk(" DMADBR = 0x%08x\n", REG_DMAC_DMADBR(chan->io/HALF_DMA_NUM));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* jz_request_dma - dynamically allcate an idle DMA channel to return
|
||||
* @dev_id: the specified dma device id or DMA_ID_RAW_SET
|
||||
* @dev_str: the specified dma device string name
|
||||
* @irqhandler: the irq handler, or NULL
|
||||
* @irqflags: the irq handler flags
|
||||
* @irq_dev_id: the irq handler device id for shared irq
|
||||
*
|
||||
* Finds a free channel, and binds the requested device to it.
|
||||
* Returns the allocated channel number, or negative on error.
|
||||
* Requests the DMA done IRQ if irqhandler != NULL.
|
||||
*
|
||||
*/
|
||||
/*int jz_request_dma(int dev_id, const char *dev_str,
|
||||
void (*irqhandler)(int, void *, struct pt_regs *),
|
||||
unsigned long irqflags,
|
||||
void *irq_dev_id)
|
||||
*/
|
||||
|
||||
int jz_request_dma(int dev_id, const char *dev_str,
|
||||
irqreturn_t (*irqhandler)(int, void *),
|
||||
unsigned long irqflags,
|
||||
void *irq_dev_id)
|
||||
{
|
||||
struct jz_dma_chan *chan;
|
||||
int i, ret, chan0;
|
||||
|
||||
if (dev_id < 0 || dev_id >= DMA_ID_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
/* Because of a bug in DMA controller of jz4750, which causes auto
|
||||
request and device request can't be allocated in a same DMA
|
||||
controller, all device requests should be put in the second DMA
|
||||
controller
|
||||
*/
|
||||
if (dev_id > DMA_ID_AUTO)
|
||||
chan0 = 6;
|
||||
else
|
||||
chan0 = 0;
|
||||
|
||||
for (i = chan0; i < MAX_DMA_NUM; i++) {
|
||||
if (jz_dma_table[i].dev_id < 0)
|
||||
break;
|
||||
}
|
||||
if (i == MAX_DMA_NUM) /* no free channel */
|
||||
return -ENODEV;
|
||||
|
||||
/* we got a free channel */
|
||||
chan = &jz_dma_table[i];
|
||||
|
||||
if (irqhandler) {
|
||||
chan->irq = IRQ_DMA_0 + i; // allocate irq number
|
||||
chan->irq_dev = irq_dev_id;
|
||||
if ((ret = request_irq(chan->irq, irqhandler, irqflags,
|
||||
dev_str, chan->irq_dev))) {
|
||||
chan->irq = -1;
|
||||
chan->irq_dev = NULL;
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
chan->irq = -1;
|
||||
chan->irq_dev = NULL;
|
||||
}
|
||||
|
||||
// fill it in
|
||||
chan->io = i;
|
||||
chan->dev_id = dev_id;
|
||||
chan->dev_str = dev_str;
|
||||
chan->fifo_addr = dma_dev_table[dev_id].fifo_addr;
|
||||
chan->mode = dma_dev_table[dev_id].dma_mode;
|
||||
chan->source = dma_dev_table[dev_id].dma_source;
|
||||
|
||||
if (i < 6)
|
||||
REG_DMAC_DMACKE(0) = 1 << i;
|
||||
else
|
||||
REG_DMAC_DMACKE(1) = 1 << (i - 6);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void jz_free_dma(unsigned int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan) {
|
||||
printk("Trying to free DMA%d\n", dmanr);
|
||||
return;
|
||||
}
|
||||
|
||||
disable_dma(dmanr);
|
||||
if (chan->irq)
|
||||
free_irq(chan->irq, chan->irq_dev);
|
||||
|
||||
chan->irq = -1;
|
||||
chan->irq_dev = NULL;
|
||||
chan->dev_id = -1;
|
||||
}
|
||||
|
||||
void jz_set_dma_dest_width(int dmanr, int nbit)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
chan->mode &= ~DMAC_DCMD_DWDH_MASK;
|
||||
switch (nbit) {
|
||||
case 8:
|
||||
chan->mode |= DMAC_DCMD_DWDH_8;
|
||||
break;
|
||||
case 16:
|
||||
chan->mode |= DMAC_DCMD_DWDH_16;
|
||||
break;
|
||||
case 32:
|
||||
chan->mode |= DMAC_DCMD_DWDH_32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void jz_set_dma_src_width(int dmanr, int nbit)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
chan->mode &= ~DMAC_DCMD_SWDH_MASK;
|
||||
switch (nbit) {
|
||||
case 8:
|
||||
chan->mode |= DMAC_DCMD_SWDH_8;
|
||||
break;
|
||||
case 16:
|
||||
chan->mode |= DMAC_DCMD_SWDH_16;
|
||||
break;
|
||||
case 32:
|
||||
chan->mode |= DMAC_DCMD_SWDH_32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void jz_set_dma_block_size(int dmanr, int nbyte)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
chan->mode &= ~DMAC_DCMD_DS_MASK;
|
||||
switch (nbyte) {
|
||||
case 1:
|
||||
chan->mode |= DMAC_DCMD_DS_8BIT;
|
||||
break;
|
||||
case 2:
|
||||
chan->mode |= DMAC_DCMD_DS_16BIT;
|
||||
break;
|
||||
case 4:
|
||||
chan->mode |= DMAC_DCMD_DS_32BIT;
|
||||
break;
|
||||
case 16:
|
||||
chan->mode |= DMAC_DCMD_DS_16BYTE;
|
||||
break;
|
||||
case 32:
|
||||
chan->mode |= DMAC_DCMD_DS_32BYTE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int jz_get_dma_command(int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
return chan->mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* jz_set_dma_mode - do the raw settings for the specified DMA channel
|
||||
* @dmanr: the specified DMA channel
|
||||
* @mode: dma operate mode, DMA_MODE_READ or DMA_MODE_WRITE
|
||||
* @dma_mode: dma raw mode
|
||||
* @dma_source: dma raw request source
|
||||
* @fifo_addr: dma raw device fifo address
|
||||
*
|
||||
* Ensure call jz_request_dma(DMA_ID_RAW_SET, ...) first, then call
|
||||
* jz_set_dma_mode() rather than set_dma_mode() if you work with
|
||||
* and external request dma device.
|
||||
*
|
||||
* NOTE: Don not dynamically allocate dma channel if one external request
|
||||
* dma device will occupy this channel.
|
||||
*/
|
||||
int jz_set_dma_mode(unsigned int dmanr, unsigned int mode,
|
||||
unsigned int dma_mode, unsigned int dma_source,
|
||||
unsigned int fifo_addr)
|
||||
{
|
||||
int dev_id, i;
|
||||
struct jz_dma_chan *chan;
|
||||
|
||||
if (dmanr > MAX_DMA_NUM)
|
||||
return -ENODEV;
|
||||
for (i = 0; i < MAX_DMA_NUM; i++) {
|
||||
if (jz_dma_table[i].dev_id < 0)
|
||||
break;
|
||||
}
|
||||
if (i == MAX_DMA_NUM)
|
||||
return -ENODEV;
|
||||
|
||||
chan = &jz_dma_table[dmanr];
|
||||
dev_id = chan->dev_id;
|
||||
if (dev_id > 0) {
|
||||
printk(KERN_DEBUG "%s sets the allocated DMA channel %d!\n",
|
||||
__FUNCTION__, dmanr);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* clone it from the dynamically allocated. */
|
||||
if (i != dmanr) {
|
||||
chan->irq = jz_dma_table[i].irq;
|
||||
chan->irq_dev = jz_dma_table[i].irq_dev;
|
||||
chan->dev_str = jz_dma_table[i].dev_str;
|
||||
jz_dma_table[i].irq = 0;
|
||||
jz_dma_table[i].irq_dev = NULL;
|
||||
jz_dma_table[i].dev_id = -1;
|
||||
}
|
||||
chan->dev_id = DMA_ID_RAW_SET;
|
||||
chan->io = dmanr;
|
||||
chan->fifo_addr = fifo_addr;
|
||||
chan->mode = dma_mode;
|
||||
chan->source = dma_source;
|
||||
|
||||
set_dma_mode(dmanr, dma_mode);
|
||||
|
||||
return dmanr;
|
||||
}
|
||||
|
||||
void enable_dma(unsigned int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
REG_DMAC_DCCSR(dmanr) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR);
|
||||
REG_DMAC_DCCSR(dmanr) |= DMAC_DCCSR_NDES; /* No-descriptor transfer */
|
||||
__dmac_enable_channel(dmanr);
|
||||
if (chan->irq)
|
||||
__dmac_channel_enable_irq(dmanr);
|
||||
}
|
||||
|
||||
#define DMA_DISABLE_POLL 0x10000
|
||||
|
||||
void disable_dma(unsigned int dmanr)
|
||||
{
|
||||
int i;
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
if (!__dmac_channel_enabled(dmanr))
|
||||
return;
|
||||
|
||||
for (i = 0; i < DMA_DISABLE_POLL; i++)
|
||||
if (__dmac_channel_transmit_end_detected(dmanr))
|
||||
break;
|
||||
#if 0
|
||||
if (i == DMA_DISABLE_POLL)
|
||||
printk(KERN_INFO "disable_dma: poll expired!\n");
|
||||
#endif
|
||||
|
||||
__dmac_disable_channel(dmanr);
|
||||
if (chan->irq)
|
||||
__dmac_channel_disable_irq(dmanr);
|
||||
}
|
||||
|
||||
/* Note: DMA_MODE_MASK is simulated by sw */
|
||||
void set_dma_mode(unsigned int dmanr, unsigned int mode)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI);
|
||||
mode &= DMA_MODE_MASK;
|
||||
if (mode == DMA_MODE_READ) {
|
||||
chan->mode |= DMAC_DCMD_DAI;
|
||||
chan->mode &= ~DMAC_DCMD_SAI;
|
||||
} else if (mode == DMA_MODE_WRITE) {
|
||||
chan->mode |= DMAC_DCMD_SAI;
|
||||
chan->mode &= ~DMAC_DCMD_DAI;
|
||||
} else {
|
||||
printk(KERN_DEBUG "set_dma_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n");
|
||||
}
|
||||
REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK;
|
||||
REG_DMAC_DRSR(chan->io) = chan->source;
|
||||
}
|
||||
|
||||
void set_dma_addr(unsigned int dmanr, unsigned int phyaddr)
|
||||
{
|
||||
unsigned int mode;
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
mode = chan->mode & DMA_MODE_MASK;
|
||||
if (mode == DMA_MODE_READ) {
|
||||
REG_DMAC_DSAR(chan->io) = chan->fifo_addr;
|
||||
REG_DMAC_DTAR(chan->io) = phyaddr;
|
||||
} else if (mode == DMA_MODE_WRITE) {
|
||||
REG_DMAC_DSAR(chan->io) = phyaddr;
|
||||
REG_DMAC_DTAR(chan->io) = chan->fifo_addr;
|
||||
} else
|
||||
printk(KERN_DEBUG "Driver should call set_dma_mode() ahead set_dma_addr()!\n");
|
||||
}
|
||||
|
||||
void set_dma_count(unsigned int dmanr, unsigned int bytecnt)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
int dma_ds[] = {4, 1, 2, 16, 32};
|
||||
unsigned int ds;
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT;
|
||||
REG_DMAC_DTCR(chan->io) = bytecnt / dma_ds[ds]; // transfer count
|
||||
}
|
||||
|
||||
unsigned int get_dma_residue(unsigned int dmanr)
|
||||
{
|
||||
unsigned int count, ds;
|
||||
int dma_ds[] = {4, 1, 2, 16, 32};
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
if (!chan)
|
||||
return 0;
|
||||
|
||||
ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT;
|
||||
count = REG_DMAC_DTCR(chan->io);
|
||||
count = count * dma_ds[ds];
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
switch (audio_fmt) {
|
||||
case AFMT_U8:
|
||||
/* burst mode : 32BIT */
|
||||
break;
|
||||
case AFMT_S16_LE:
|
||||
/* burst mode : 16BYTE */
|
||||
if (mode == DMA_MODE_READ) {
|
||||
chan->mode = DMA_AIC_32_16BYTE_RX_CMD | DMA_MODE_READ;
|
||||
chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI);
|
||||
mode &= DMA_MODE_MASK;
|
||||
chan->mode |= DMAC_DCMD_DAI;
|
||||
chan->mode &= ~DMAC_DCMD_SAI;
|
||||
} else if (mode == DMA_MODE_WRITE) {
|
||||
chan->mode = DMA_AIC_32_16BYTE_TX_CMD | DMA_MODE_WRITE;
|
||||
//chan->mode = DMA_AIC_16BYTE_TX_CMD | DMA_MODE_WRITE;
|
||||
chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI);
|
||||
mode &= DMA_MODE_MASK;
|
||||
chan->mode |= DMAC_DCMD_SAI;
|
||||
chan->mode &= ~DMAC_DCMD_DAI;
|
||||
} else
|
||||
printk("oss_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n");
|
||||
|
||||
REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK;
|
||||
REG_DMAC_DRSR(chan->io) = chan->source;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
switch (audio_fmt) {
|
||||
case 8:
|
||||
/* SNDRV_PCM_FORMAT_S8 burst mode : 32BIT */
|
||||
break;
|
||||
case 16:
|
||||
/* SNDRV_PCM_FORMAT_S16_LE burst mode : 16BYTE */
|
||||
if (mode == DMA_MODE_READ) {
|
||||
chan->mode = DMA_AIC_16BYTE_RX_CMD | DMA_MODE_READ;
|
||||
chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI);
|
||||
mode &= DMA_MODE_MASK;
|
||||
chan->mode |= DMAC_DCMD_DAI;
|
||||
chan->mode &= ~DMAC_DCMD_SAI;
|
||||
} else if (mode == DMA_MODE_WRITE) {
|
||||
chan->mode = DMA_AIC_16BYTE_TX_CMD | DMA_MODE_WRITE;
|
||||
chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI);
|
||||
mode &= DMA_MODE_MASK;
|
||||
chan->mode |= DMAC_DCMD_SAI;
|
||||
chan->mode &= ~DMAC_DCMD_DAI;
|
||||
} else
|
||||
printk("alsa_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n");
|
||||
|
||||
REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK;
|
||||
REG_DMAC_DRSR(chan->io) = chan->source;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//#define JZ4750_DMAC_TEST_ENABLE
|
||||
#undef JZ4750_DMAC_TEST_ENABLE
|
||||
|
||||
#ifdef JZ4750_DMAC_TEST_ENABLE
|
||||
|
||||
/*
|
||||
* DMA test: external address <--> external address
|
||||
*/
|
||||
#define TEST_DMA_SIZE 16*1024
|
||||
|
||||
static jz_dma_desc *dma_desc;
|
||||
|
||||
static int dma_chan;
|
||||
static dma_addr_t dma_desc_phys_addr;
|
||||
static unsigned int dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr;
|
||||
|
||||
static int dma_check_result(void *src, void *dst, int size)
|
||||
{
|
||||
unsigned int addr1, addr2, i, err = 0;
|
||||
|
||||
addr1 = (unsigned int)src;
|
||||
addr2 = (unsigned int)dst;
|
||||
|
||||
for (i = 0; i < size; i += 4) {
|
||||
if (*(volatile unsigned int *)addr1 != *(volatile unsigned int *)addr2) {
|
||||
err++;
|
||||
printk("wrong data at 0x%08x: src 0x%08x dst 0x%08x\n", addr2, *(volatile unsigned int *)addr1, *(volatile unsigned int *)addr2);
|
||||
}
|
||||
addr1 += 4;
|
||||
addr2 += 4;
|
||||
}
|
||||
printk("check DMA result err=%d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
static irqreturn_t jz4750_dma_irq(int irq, void *dev_id)
|
||||
{
|
||||
printk("jz4750_dma_irq %d\n", irq);
|
||||
|
||||
|
||||
if (__dmac_channel_transmit_halt_detected(dma_chan)) {
|
||||
printk("DMA HALT\n");
|
||||
REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */
|
||||
__dmac_channel_clear_transmit_halt(dma_chan);
|
||||
}
|
||||
|
||||
if (__dmac_channel_address_error_detected(dma_chan)) {
|
||||
printk("DMA ADDR ERROR\n");
|
||||
REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */
|
||||
REG_DMAC_DSAR(dma_chan) = 0; /* clear source address register */
|
||||
REG_DMAC_DTAR(dma_chan) = 0; /* clear target address register */
|
||||
__dmac_channel_clear_address_error(dma_chan);
|
||||
}
|
||||
|
||||
if (__dmac_channel_descriptor_invalid_detected(dma_chan)) {
|
||||
REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */
|
||||
printk("DMA DESC INVALID\n");
|
||||
__dmac_channel_clear_descriptor_invalid(dma_chan);
|
||||
}
|
||||
|
||||
if (__dmac_channel_count_terminated_detected(dma_chan)) {
|
||||
printk("DMA CT\n");
|
||||
__dmac_channel_clear_count_terminated(dma_chan);
|
||||
}
|
||||
|
||||
if (__dmac_channel_transmit_end_detected(dma_chan)) {
|
||||
REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */
|
||||
printk("DMA TT\n");
|
||||
__dmac_channel_clear_transmit_end(dma_chan);
|
||||
dump_jz_dma_channel(dma_chan);
|
||||
dma_check_result((void *)dma_src_addr, (void *)dma_dst_addr, TEST_DMA_SIZE);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
void dma_nodesc_test(void)
|
||||
{
|
||||
unsigned int addr, i;
|
||||
|
||||
printk("dma_nodesc_test\n");
|
||||
|
||||
/* Request DMA channel and setup irq handler */
|
||||
dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4750_dma_irq,
|
||||
IRQF_DISABLED, NULL);
|
||||
if (dma_chan < 0) {
|
||||
printk("Setup irq failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printk("Requested DMA channel = %d\n", dma_chan);
|
||||
|
||||
/* Allocate DMA buffers */
|
||||
dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */
|
||||
dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */
|
||||
|
||||
dma_src_phys_addr = CPHYSADDR(dma_src_addr);
|
||||
dma_dst_phys_addr = CPHYSADDR(dma_dst_addr);
|
||||
|
||||
printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n",
|
||||
dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr);
|
||||
|
||||
/* Prepare data for source buffer */
|
||||
addr = (unsigned int)dma_src_addr;
|
||||
for (i = 0; i < TEST_DMA_SIZE; i += 4) {
|
||||
*(volatile unsigned int *)addr = addr;
|
||||
addr += 4;
|
||||
}
|
||||
dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE);
|
||||
|
||||
/* Init target buffer */
|
||||
memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE);
|
||||
dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE);
|
||||
|
||||
/* Init DMA module */
|
||||
printk("Starting DMA\n");
|
||||
REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = 0;
|
||||
REG_DMAC_DCCSR(dma_chan) = 0;
|
||||
REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO;
|
||||
REG_DMAC_DSAR(dma_chan) = dma_src_phys_addr;
|
||||
REG_DMAC_DTAR(dma_chan) = dma_dst_phys_addr;
|
||||
REG_DMAC_DTCR(dma_chan) = 512;
|
||||
REG_DMAC_DCMD(dma_chan) = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TIE;
|
||||
REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_NDES | DMAC_DCCSR_EN;
|
||||
REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = DMAC_DMACR_DMAE; /* global DMA enable bit */
|
||||
|
||||
printk("DMA started. IMR=%08x\n", REG_INTC_IMR);
|
||||
|
||||
/* wait a long time, ensure transfer end */
|
||||
printk("wait 3s...\n");
|
||||
mdelay(3000); /* wait 3s */
|
||||
|
||||
REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */
|
||||
/* free buffers */
|
||||
printk("free DMA buffers\n");
|
||||
free_pages(dma_src_addr, 2);
|
||||
free_pages(dma_dst_addr, 2);
|
||||
|
||||
if (dma_desc)
|
||||
free_pages((unsigned int)dma_desc, 0);
|
||||
|
||||
/* free dma */
|
||||
jz_free_dma(dma_chan);
|
||||
}
|
||||
|
||||
void dma_desc_test(void)
|
||||
{
|
||||
unsigned int next, addr, i;
|
||||
static jz_dma_desc *desc;
|
||||
|
||||
printk("dma_desc_test\n");
|
||||
|
||||
/* Request DMA channel and setup irq handler */
|
||||
dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4750_dma_irq,
|
||||
IRQF_DISABLED, NULL);
|
||||
if (dma_chan < 0) {
|
||||
printk("Setup irq failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printk("Requested DMA channel = %d\n", dma_chan);
|
||||
|
||||
/* Allocate DMA buffers */
|
||||
dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */
|
||||
dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */
|
||||
|
||||
dma_src_phys_addr = CPHYSADDR(dma_src_addr);
|
||||
dma_dst_phys_addr = CPHYSADDR(dma_dst_addr);
|
||||
|
||||
printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n",
|
||||
dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr);
|
||||
|
||||
/* Prepare data for source buffer */
|
||||
addr = (unsigned int)dma_src_addr;
|
||||
for (i = 0; i < TEST_DMA_SIZE; i += 4) {
|
||||
*(volatile unsigned int *)addr = addr;
|
||||
addr += 4;
|
||||
}
|
||||
dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE);
|
||||
|
||||
/* Init target buffer */
|
||||
memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE);
|
||||
dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE);
|
||||
|
||||
/* Allocate DMA descriptors */
|
||||
dma_desc = (jz_dma_desc *)__get_free_pages(GFP_KERNEL, 0);
|
||||
dma_desc_phys_addr = CPHYSADDR((unsigned long)dma_desc);
|
||||
|
||||
printk("DMA descriptor address: 0x%08x 0x%08x\n", (u32)dma_desc, dma_desc_phys_addr);
|
||||
|
||||
/* Setup DMA descriptors */
|
||||
desc = dma_desc;
|
||||
next = (dma_desc_phys_addr + (sizeof(jz_dma_desc))) >> 4;
|
||||
|
||||
desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK;
|
||||
desc->dsadr = dma_src_phys_addr; /* DMA source address */
|
||||
desc->dtadr = dma_dst_phys_addr; /* DMA target address */
|
||||
desc->ddadr = (next << 24) + 128; /* size: 128*32 bytes = 4096 bytes */
|
||||
|
||||
desc++;
|
||||
next = (dma_desc_phys_addr + 2*(sizeof(jz_dma_desc))) >> 4;
|
||||
|
||||
desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK;
|
||||
desc->dsadr = dma_src_phys_addr + 4096; /* DMA source address */
|
||||
desc->dtadr = dma_dst_phys_addr + 4096; /* DMA target address */
|
||||
desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */
|
||||
|
||||
desc++;
|
||||
next = (dma_desc_phys_addr + 3*(sizeof(jz_dma_desc))) >> 4;
|
||||
|
||||
desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK;
|
||||
desc->dsadr = dma_src_phys_addr + 8192; /* DMA source address */
|
||||
desc->dtadr = dma_dst_phys_addr + 8192; /* DMA target address */
|
||||
desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */
|
||||
|
||||
desc++;
|
||||
next = (dma_desc_phys_addr + 4*(sizeof(jz_dma_desc))) >> 4;
|
||||
|
||||
desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE;
|
||||
desc->dsadr = dma_src_phys_addr + 12*1024; /* DMA source address */
|
||||
desc->dtadr = dma_dst_phys_addr + 12*1024; /* DMA target address */
|
||||
desc->ddadr = (next << 24) + 1024; /* size: 1024*4 bytes = 4096 bytes */
|
||||
|
||||
dma_cache_wback((unsigned long)dma_desc, 4*(sizeof(jz_dma_desc)));
|
||||
|
||||
/* Setup DMA descriptor address */
|
||||
REG_DMAC_DDA(dma_chan) = dma_desc_phys_addr;
|
||||
|
||||
/* Setup request source */
|
||||
REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO;
|
||||
|
||||
/* Setup DMA channel control/status register */
|
||||
REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_EN; /* descriptor transfer, clear status, start channel */
|
||||
|
||||
/* Enable DMA */
|
||||
REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = DMAC_DMACR_DMAE;
|
||||
|
||||
/* DMA doorbell set -- start DMA now ... */
|
||||
REG_DMAC_DMADBSR(dma_chan/HALF_DMA_NUM) = 1 << dma_chan;
|
||||
|
||||
printk("DMA started. IMR=%08x\n", REG_INTC_IMR);
|
||||
/* wait a long time, ensure transfer end */
|
||||
printk("wait 3s...\n");
|
||||
mdelay(3000); /* wait 3s */
|
||||
|
||||
REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */
|
||||
/* free buffers */
|
||||
printk("free DMA buffers\n");
|
||||
free_pages(dma_src_addr, 2);
|
||||
free_pages(dma_dst_addr, 2);
|
||||
|
||||
if (dma_desc)
|
||||
free_pages((unsigned int)dma_desc, 0);
|
||||
|
||||
/* free dma */
|
||||
jz_free_dma(dma_chan);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//EXPORT_SYMBOL_NOVERS(jz_dma_table);
|
||||
EXPORT_SYMBOL(jz_dma_table);
|
||||
EXPORT_SYMBOL(jz_request_dma);
|
||||
EXPORT_SYMBOL(jz_free_dma);
|
||||
EXPORT_SYMBOL(jz_set_dma_src_width);
|
||||
EXPORT_SYMBOL(jz_set_dma_dest_width);
|
||||
EXPORT_SYMBOL(jz_set_dma_block_size);
|
||||
EXPORT_SYMBOL(jz_set_dma_mode);
|
||||
EXPORT_SYMBOL(set_dma_mode);
|
||||
EXPORT_SYMBOL(jz_set_oss_dma);
|
||||
EXPORT_SYMBOL(jz_set_alsa_dma);
|
||||
EXPORT_SYMBOL(set_dma_addr);
|
||||
EXPORT_SYMBOL(set_dma_count);
|
||||
EXPORT_SYMBOL(get_dma_residue);
|
||||
EXPORT_SYMBOL(enable_dma);
|
||||
EXPORT_SYMBOL(disable_dma);
|
||||
EXPORT_SYMBOL(dump_jz_dma_channel);
|
||||
386
target/linux/xburst/files-2.6.27/arch/mips/jz4750/i2c.c
Normal file
386
target/linux/xburst/files-2.6.27/arch/mips/jz4750/i2c.c
Normal file
@@ -0,0 +1,386 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4750/i2c.c
|
||||
*
|
||||
* Jz4750 I2C routines.
|
||||
*
|
||||
* Copyright (C) 2005,2006 Ingenic Semiconductor Inc.
|
||||
* Author: <lhhuang@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can distribute it and/or modify it
|
||||
* under the terms of the GNU General Public License (Version 2) as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/addrspace.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/* I2C protocol */
|
||||
#define I2C_READ 1
|
||||
#define I2C_WRITE 0
|
||||
|
||||
#define TIMEOUT 1000
|
||||
|
||||
/*
|
||||
* I2C bus protocol basic routines
|
||||
*/
|
||||
static int i2c_put_data(unsigned char data)
|
||||
{
|
||||
unsigned int timeout = TIMEOUT*10;
|
||||
|
||||
__i2c_write(data);
|
||||
__i2c_set_drf();
|
||||
while (__i2c_check_drf() != 0);
|
||||
while (!__i2c_transmit_ended());
|
||||
while (!__i2c_received_ack() && timeout)
|
||||
timeout--;
|
||||
|
||||
if (timeout)
|
||||
return 0;
|
||||
else
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int i2c_put_data_nack(unsigned char data)
|
||||
{
|
||||
unsigned int timeout = TIMEOUT*10;
|
||||
|
||||
__i2c_write(data);
|
||||
__i2c_set_drf();
|
||||
while (__i2c_check_drf() != 0);
|
||||
while (!__i2c_transmit_ended());
|
||||
while (timeout--);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2c_get_data(unsigned char *data, int ack)
|
||||
{
|
||||
int timeout = TIMEOUT*10;
|
||||
|
||||
if (!ack)
|
||||
__i2c_send_nack();
|
||||
else
|
||||
__i2c_send_ack();
|
||||
|
||||
while (__i2c_check_drf() == 0 && timeout)
|
||||
timeout--;
|
||||
|
||||
if (timeout) {
|
||||
if (!ack)
|
||||
__i2c_send_stop();
|
||||
*data = __i2c_read();
|
||||
__i2c_clear_drf();
|
||||
return 0;
|
||||
} else
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/*
|
||||
* I2C interface
|
||||
*/
|
||||
void i2c_open(void)
|
||||
{
|
||||
__i2c_set_clk(jz_clocks.extalclk, 10000); /* default 10 KHz */
|
||||
__i2c_enable();
|
||||
}
|
||||
|
||||
void i2c_close(void)
|
||||
{
|
||||
udelay(300); /* wait for STOP goes over. */
|
||||
__i2c_disable();
|
||||
}
|
||||
|
||||
void i2c_setclk(unsigned int i2cclk)
|
||||
{
|
||||
__i2c_set_clk(jz_clocks.extalclk, i2cclk);
|
||||
}
|
||||
|
||||
int i2c_lseek(unsigned char device, unsigned char offset)
|
||||
{
|
||||
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
|
||||
goto device_err;
|
||||
if (i2c_put_data(offset) < 0)
|
||||
goto address_err;
|
||||
return 0;
|
||||
device_err:
|
||||
printk(KERN_DEBUG "No I2C device (0x%02x) installed.\n", device);
|
||||
__i2c_send_stop();
|
||||
return -ENODEV;
|
||||
address_err:
|
||||
printk(KERN_DEBUG "No I2C device (0x%02x) response.\n", device);
|
||||
__i2c_send_stop();
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
int i2c_read(unsigned char device, unsigned char *buf,
|
||||
unsigned char address, int count)
|
||||
{
|
||||
int cnt = count;
|
||||
int timeout = 5;
|
||||
|
||||
L_try_again:
|
||||
|
||||
if (timeout < 0)
|
||||
goto L_timeout;
|
||||
|
||||
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
|
||||
goto device_werr;
|
||||
if (i2c_put_data(address) < 0)
|
||||
goto address_err;
|
||||
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_READ ) < 0)
|
||||
goto device_rerr;
|
||||
__i2c_send_ack(); /* Master sends ACK for continue reading */
|
||||
while (cnt) {
|
||||
if (cnt == 1) {
|
||||
if (i2c_get_data(buf, 0) < 0)
|
||||
break;
|
||||
} else {
|
||||
if (i2c_get_data(buf, 1) < 0)
|
||||
break;
|
||||
}
|
||||
cnt--;
|
||||
buf++;
|
||||
}
|
||||
|
||||
__i2c_send_stop();
|
||||
return count - cnt;
|
||||
device_rerr:
|
||||
device_werr:
|
||||
address_err:
|
||||
timeout --;
|
||||
__i2c_send_stop();
|
||||
goto L_try_again;
|
||||
|
||||
L_timeout:
|
||||
__i2c_send_stop();
|
||||
printk("Read I2C device 0x%2x failed.\n", device);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int i2c_write(unsigned char device, unsigned char *buf,
|
||||
unsigned char address, int count)
|
||||
{
|
||||
int cnt = count;
|
||||
int cnt_in_pg;
|
||||
int timeout = 5;
|
||||
unsigned char *tmpbuf;
|
||||
unsigned char tmpaddr;
|
||||
|
||||
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
|
||||
|
||||
W_try_again:
|
||||
if (timeout < 0)
|
||||
goto W_timeout;
|
||||
|
||||
cnt = count;
|
||||
tmpbuf = (unsigned char *)buf;
|
||||
tmpaddr = address;
|
||||
|
||||
start_write_page:
|
||||
cnt_in_pg = 0;
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
|
||||
goto device_err;
|
||||
#ifdef CONFIG_JZ_TPANEL_ATA2508
|
||||
if (address == 0xff) {
|
||||
if (i2c_put_data_nack(tmpaddr) < 0)
|
||||
goto address_err;
|
||||
while (cnt) {
|
||||
if (++cnt_in_pg > 8) {
|
||||
__i2c_send_stop();
|
||||
mdelay(1);
|
||||
tmpaddr += 8;
|
||||
goto start_write_page;
|
||||
}
|
||||
if (i2c_put_data_nack(*tmpbuf) < 0)
|
||||
break;
|
||||
cnt--;
|
||||
tmpbuf++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if (i2c_put_data(tmpaddr) < 0)
|
||||
goto address_err;
|
||||
while (cnt) {
|
||||
if (++cnt_in_pg > 8) {
|
||||
__i2c_send_stop();
|
||||
mdelay(1);
|
||||
tmpaddr += 8;
|
||||
goto start_write_page;
|
||||
}
|
||||
if (i2c_put_data(*tmpbuf) < 0)
|
||||
break;
|
||||
cnt--;
|
||||
tmpbuf++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (i2c_put_data(tmpaddr) < 0)
|
||||
goto address_err;
|
||||
while (cnt) {
|
||||
if (++cnt_in_pg > 8) {
|
||||
__i2c_send_stop();
|
||||
mdelay(1);
|
||||
tmpaddr += 8;
|
||||
goto start_write_page;
|
||||
}
|
||||
if (i2c_put_data(*tmpbuf) < 0)
|
||||
break;
|
||||
cnt--;
|
||||
tmpbuf++;
|
||||
}
|
||||
#endif
|
||||
__i2c_send_stop();
|
||||
return count - cnt;
|
||||
device_err:
|
||||
address_err:
|
||||
timeout--;
|
||||
__i2c_send_stop();
|
||||
goto W_try_again;
|
||||
|
||||
W_timeout:
|
||||
printk(KERN_DEBUG "Write I2C device 0x%2x failed.\n", device);
|
||||
__i2c_send_stop();
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int i2c_read_16(unsigned char device, unsigned char *buf,
|
||||
unsigned short address, int count)
|
||||
{
|
||||
int cnt = count;
|
||||
int timeout = 5;
|
||||
unsigned char tmpaddrh, tmpaddrl;
|
||||
|
||||
tmpaddrh = (unsigned char)((address >> 8) & 0xff);
|
||||
tmpaddrl = (unsigned char)(address & 0xff);
|
||||
|
||||
L_try_again:
|
||||
|
||||
if (timeout < 0)
|
||||
goto L_timeout;
|
||||
|
||||
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
|
||||
goto device_werr;
|
||||
if (i2c_put_data_nack(tmpaddrh) < 0)
|
||||
goto address_err;
|
||||
if (i2c_put_data(tmpaddrl) < 0)
|
||||
goto address_err;
|
||||
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_READ ) < 0)
|
||||
goto device_rerr;
|
||||
__i2c_send_ack(); /* Master sends ACK for continue reading */
|
||||
while (cnt) {
|
||||
if (cnt == 1) {
|
||||
if (i2c_get_data(buf, 0) < 0)
|
||||
break;
|
||||
} else {
|
||||
if (i2c_get_data(buf, 1) < 0)
|
||||
break;
|
||||
}
|
||||
cnt--;
|
||||
buf++;
|
||||
}
|
||||
|
||||
__i2c_send_stop();
|
||||
return count - cnt;
|
||||
device_rerr:
|
||||
device_werr:
|
||||
address_err:
|
||||
timeout --;
|
||||
__i2c_send_stop();
|
||||
goto L_try_again;
|
||||
|
||||
L_timeout:
|
||||
__i2c_send_stop();
|
||||
printk("Read I2C device 0x%2x failed.\n", device);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int i2c_write_16(unsigned char device, unsigned char *buf,
|
||||
unsigned short address, int count)
|
||||
{
|
||||
int cnt = count;
|
||||
int cnt_in_pg;
|
||||
int timeout = 5;
|
||||
unsigned char *tmpbuf;
|
||||
unsigned char tmpaddrh, tmpaddrl;
|
||||
|
||||
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
|
||||
|
||||
W_try_again:
|
||||
if (timeout < 0)
|
||||
goto W_timeout;
|
||||
|
||||
cnt = count;
|
||||
tmpbuf = (unsigned char *)buf;
|
||||
tmpaddrh = (unsigned char)((address >> 8) & 0xff);
|
||||
tmpaddrl = (unsigned char)(address & 0xff);
|
||||
|
||||
start_write_page:
|
||||
cnt_in_pg = 0;
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
|
||||
goto device_err;
|
||||
if (i2c_put_data_nack(tmpaddrh) < 0)
|
||||
goto address_err;
|
||||
if (i2c_put_data(tmpaddrl) < 0)
|
||||
goto address_err;
|
||||
while (cnt) {
|
||||
if (++cnt_in_pg > 8) {
|
||||
__i2c_send_stop();
|
||||
mdelay(1);
|
||||
tmpaddrh += 8;
|
||||
goto start_write_page;
|
||||
}
|
||||
if (i2c_put_data(*tmpbuf) < 0)
|
||||
break;
|
||||
cnt--;
|
||||
tmpbuf++;
|
||||
}
|
||||
|
||||
__i2c_send_stop();
|
||||
return count - cnt;
|
||||
device_err:
|
||||
printk("1:Write I2C device 0x%2x failed.\n", device);
|
||||
address_err:
|
||||
printk("2:Write I2C address 0x%2x failed.\n", address);
|
||||
timeout--;
|
||||
__i2c_send_stop();
|
||||
goto W_try_again;
|
||||
|
||||
W_timeout:
|
||||
printk("3:Write I2C device 0x%2x failed.\n", device);
|
||||
__i2c_send_stop();
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(i2c_open);
|
||||
EXPORT_SYMBOL(i2c_close);
|
||||
EXPORT_SYMBOL(i2c_setclk);
|
||||
EXPORT_SYMBOL(i2c_read);
|
||||
EXPORT_SYMBOL(i2c_write);
|
||||
EXPORT_SYMBOL(i2c_read_16);
|
||||
EXPORT_SYMBOL(i2c_write_16);
|
||||
299
target/linux/xburst/files-2.6.27/arch/mips/jz4750/irq.c
Normal file
299
target/linux/xburst/files-2.6.27/arch/mips/jz4750/irq.c
Normal file
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4750/irq.c
|
||||
*
|
||||
* JZ4750 interrupt routines.
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <lhhuang@ingenic.cn>
|
||||
*
|
||||
* 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/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/timex.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/*
|
||||
* INTC irq type
|
||||
*/
|
||||
|
||||
static void enable_intc_irq(unsigned int irq)
|
||||
{
|
||||
__intc_unmask_irq(irq);
|
||||
}
|
||||
|
||||
static void disable_intc_irq(unsigned int irq)
|
||||
{
|
||||
__intc_mask_irq(irq);
|
||||
}
|
||||
|
||||
static void mask_and_ack_intc_irq(unsigned int irq)
|
||||
{
|
||||
__intc_mask_irq(irq);
|
||||
__intc_ack_irq(irq);
|
||||
}
|
||||
|
||||
static void end_intc_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
|
||||
enable_intc_irq(irq);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int startup_intc_irq(unsigned int irq)
|
||||
{
|
||||
enable_intc_irq(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void shutdown_intc_irq(unsigned int irq)
|
||||
{
|
||||
disable_intc_irq(irq);
|
||||
}
|
||||
|
||||
static struct irq_chip intc_irq_type = {
|
||||
.typename = "INTC",
|
||||
.startup = startup_intc_irq,
|
||||
.shutdown = shutdown_intc_irq,
|
||||
.enable = enable_intc_irq,
|
||||
.disable = disable_intc_irq,
|
||||
.ack = mask_and_ack_intc_irq,
|
||||
.end = end_intc_irq,
|
||||
};
|
||||
|
||||
/*
|
||||
* GPIO irq type
|
||||
*/
|
||||
|
||||
static void enable_gpio_irq(unsigned int irq)
|
||||
{
|
||||
unsigned int intc_irq;
|
||||
|
||||
if (irq < (IRQ_GPIO_0 + 32)) {
|
||||
intc_irq = IRQ_GPIO0;
|
||||
}
|
||||
else if (irq < (IRQ_GPIO_0 + 64)) {
|
||||
intc_irq = IRQ_GPIO1;
|
||||
}
|
||||
else if (irq < (IRQ_GPIO_0 + 96)) {
|
||||
intc_irq = IRQ_GPIO2;
|
||||
}
|
||||
else if (irq < (IRQ_GPIO_0 + 128)) {
|
||||
intc_irq = IRQ_GPIO3;
|
||||
}
|
||||
else if (irq < (IRQ_GPIO_0 + 160)) {
|
||||
intc_irq = IRQ_GPIO4;
|
||||
}
|
||||
else {
|
||||
intc_irq = IRQ_GPIO5;
|
||||
}
|
||||
|
||||
enable_intc_irq(intc_irq);
|
||||
__gpio_unmask_irq(irq - IRQ_GPIO_0);
|
||||
}
|
||||
|
||||
static void disable_gpio_irq(unsigned int irq)
|
||||
{
|
||||
__gpio_mask_irq(irq - IRQ_GPIO_0);
|
||||
}
|
||||
|
||||
static void mask_and_ack_gpio_irq(unsigned int irq)
|
||||
{
|
||||
__gpio_mask_irq(irq - IRQ_GPIO_0);
|
||||
__gpio_ack_irq(irq - IRQ_GPIO_0);
|
||||
}
|
||||
|
||||
static void end_gpio_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
|
||||
enable_gpio_irq(irq);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int startup_gpio_irq(unsigned int irq)
|
||||
{
|
||||
enable_gpio_irq(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void shutdown_gpio_irq(unsigned int irq)
|
||||
{
|
||||
disable_gpio_irq(irq);
|
||||
}
|
||||
|
||||
static struct irq_chip gpio_irq_type = {
|
||||
.typename = "GPIO",
|
||||
.startup = startup_gpio_irq,
|
||||
.shutdown = shutdown_gpio_irq,
|
||||
.enable = enable_gpio_irq,
|
||||
.disable = disable_gpio_irq,
|
||||
.ack = mask_and_ack_gpio_irq,
|
||||
.end = end_gpio_irq,
|
||||
};
|
||||
|
||||
/*
|
||||
* DMA irq type
|
||||
*/
|
||||
|
||||
static void enable_dma_irq(unsigned int irq)
|
||||
{
|
||||
unsigned int intc_irq;
|
||||
|
||||
if ( irq < (IRQ_DMA_0 + HALF_DMA_NUM) ) /* DMAC Group 0 irq */
|
||||
intc_irq = IRQ_DMAC0;
|
||||
else if ( irq < (IRQ_DMA_0 + MAX_DMA_NUM) ) /* DMAC Group 1 irq */
|
||||
intc_irq = IRQ_DMAC1;
|
||||
else {
|
||||
printk("%s, unexpected dma irq #%d\n", __FILE__, irq);
|
||||
return;
|
||||
}
|
||||
__intc_unmask_irq(intc_irq);
|
||||
__dmac_channel_enable_irq(irq - IRQ_DMA_0);
|
||||
}
|
||||
|
||||
static void disable_dma_irq(unsigned int irq)
|
||||
{
|
||||
__dmac_channel_disable_irq(irq - IRQ_DMA_0);
|
||||
}
|
||||
|
||||
static void mask_and_ack_dma_irq(unsigned int irq)
|
||||
{
|
||||
unsigned int intc_irq;
|
||||
|
||||
if ( irq < (IRQ_DMA_0 + HALF_DMA_NUM) ) /* DMAC Group 0 irq */
|
||||
intc_irq = IRQ_DMAC0;
|
||||
else if ( irq < (IRQ_DMA_0 + MAX_DMA_NUM) ) /* DMAC Group 1 irq */
|
||||
intc_irq = IRQ_DMAC1;
|
||||
else {
|
||||
printk("%s, unexpected dma irq #%d\n", __FILE__, irq);
|
||||
return ;
|
||||
}
|
||||
__intc_ack_irq(intc_irq);
|
||||
__dmac_channel_ack_irq(irq-IRQ_DMA_0); /* needed?? add 20080506, Wolfgang */
|
||||
__dmac_channel_disable_irq(irq - IRQ_DMA_0);
|
||||
}
|
||||
|
||||
static void end_dma_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
|
||||
enable_dma_irq(irq);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int startup_dma_irq(unsigned int irq)
|
||||
{
|
||||
enable_dma_irq(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void shutdown_dma_irq(unsigned int irq)
|
||||
{
|
||||
disable_dma_irq(irq);
|
||||
}
|
||||
|
||||
static struct irq_chip dma_irq_type = {
|
||||
.typename = "DMA",
|
||||
.startup = startup_dma_irq,
|
||||
.shutdown = shutdown_dma_irq,
|
||||
.enable = enable_dma_irq,
|
||||
.disable = disable_dma_irq,
|
||||
.ack = mask_and_ack_dma_irq,
|
||||
.end = end_dma_irq,
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void __init arch_init_irq(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
clear_c0_status(0xff04); /* clear ERL */
|
||||
set_c0_status(0x0400); /* set IP2 */
|
||||
|
||||
/* Set up INTC irq
|
||||
*/
|
||||
for (i = 0; i < 32; i++) {
|
||||
disable_intc_irq(i);
|
||||
irq_desc[i].chip = &intc_irq_type;
|
||||
}
|
||||
|
||||
/* Set up DMAC irq
|
||||
*/
|
||||
for (i = 0; i < NUM_DMA; i++) {
|
||||
disable_dma_irq(IRQ_DMA_0 + i);
|
||||
irq_desc[IRQ_DMA_0 + i].chip = &dma_irq_type;
|
||||
}
|
||||
|
||||
/* Set up GPIO irq
|
||||
*/
|
||||
for (i = 0; i < NUM_GPIO; i++) {
|
||||
disable_gpio_irq(IRQ_GPIO_0 + i);
|
||||
irq_desc[IRQ_GPIO_0 + i].chip = &gpio_irq_type;
|
||||
}
|
||||
}
|
||||
|
||||
static int plat_real_irq(int irq)
|
||||
{
|
||||
switch (irq) {
|
||||
case IRQ_GPIO0:
|
||||
irq = __gpio_group_irq(0) + IRQ_GPIO_0;
|
||||
break;
|
||||
case IRQ_GPIO1:
|
||||
irq = __gpio_group_irq(1) + IRQ_GPIO_0 + 32;
|
||||
break;
|
||||
case IRQ_GPIO2:
|
||||
irq = __gpio_group_irq(2) + IRQ_GPIO_0 + 64;
|
||||
break;
|
||||
case IRQ_GPIO3:
|
||||
irq = __gpio_group_irq(3) + IRQ_GPIO_0 + 96;
|
||||
break;
|
||||
case IRQ_GPIO4:
|
||||
irq = __gpio_group_irq(4) + IRQ_GPIO_0 + 128;
|
||||
break;
|
||||
case IRQ_GPIO5:
|
||||
irq = __gpio_group_irq(5) + IRQ_GPIO_0 + 160;
|
||||
break;
|
||||
case IRQ_DMAC0:
|
||||
case IRQ_DMAC1:
|
||||
irq = __dmac_get_irq() + IRQ_DMA_0;
|
||||
break;
|
||||
}
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
asmlinkage void plat_irq_dispatch(void)
|
||||
{
|
||||
int irq = 0;
|
||||
static unsigned long intc_ipr = 0;
|
||||
|
||||
intc_ipr |= REG_INTC_IPR;
|
||||
|
||||
if (!intc_ipr) return;
|
||||
|
||||
irq = ffs(intc_ipr) - 1;
|
||||
intc_ipr &= ~(1<<irq);
|
||||
|
||||
irq = plat_real_irq(irq);
|
||||
do_IRQ(irq);
|
||||
}
|
||||
147
target/linux/xburst/files-2.6.27/arch/mips/jz4750/platform.c
Normal file
147
target/linux/xburst/files-2.6.27/arch/mips/jz4750/platform.c
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Platform device support for Jz4740 SoC.
|
||||
*
|
||||
* Copyright 2007, <yliu@ingenic.cn>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/resource.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/* OHCI (USB full speed host controller) */
|
||||
static struct resource jz_usb_ohci_resources[] = {
|
||||
[0] = {
|
||||
.start = CPHYSADDR(UHC_BASE), // phys addr for ioremap
|
||||
.end = CPHYSADDR(UHC_BASE) + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_UHC,
|
||||
.end = IRQ_UHC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
/* The dmamask must be set for OHCI to work */
|
||||
static u64 ohci_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device jz_usb_ohci_device = {
|
||||
.name = "jz-ohci",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &ohci_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz_usb_ohci_resources),
|
||||
.resource = jz_usb_ohci_resources,
|
||||
};
|
||||
|
||||
/*** LCD controller ***/
|
||||
static struct resource jz_lcd_resources[] = {
|
||||
[0] = {
|
||||
.start = CPHYSADDR(LCD_BASE),
|
||||
.end = CPHYSADDR(LCD_BASE) + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_LCD,
|
||||
.end = IRQ_LCD,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
||||
static u64 jz_lcd_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device jz_lcd_device = {
|
||||
.name = "jz-lcd",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &jz_lcd_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz_lcd_resources),
|
||||
.resource = jz_lcd_resources,
|
||||
};
|
||||
|
||||
/* UDC (USB gadget controller) */
|
||||
static struct resource jz_usb_gdt_resources[] = {
|
||||
[0] = {
|
||||
.start = CPHYSADDR(UDC_BASE),
|
||||
.end = CPHYSADDR(UDC_BASE) + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_UDC,
|
||||
.end = IRQ_UDC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static u64 udc_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device jz_usb_gdt_device = {
|
||||
.name = "jz-udc",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &udc_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz_usb_gdt_resources),
|
||||
.resource = jz_usb_gdt_resources,
|
||||
};
|
||||
|
||||
/** MMC/SD controller **/
|
||||
static struct resource jz_mmc_resources[] = {
|
||||
[0] = {
|
||||
.start = CPHYSADDR(MSC_BASE),
|
||||
.end = CPHYSADDR(MSC_BASE) + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_MSC0,
|
||||
.end = IRQ_MSC0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
||||
static u64 jz_mmc_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device jz_mmc_device = {
|
||||
.name = "jz-mmc",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &jz_mmc_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz_mmc_resources),
|
||||
.resource = jz_mmc_resources,
|
||||
};
|
||||
|
||||
struct platform_device jz4750_rtc_device = {
|
||||
.name = "jz4750-rtc",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
/* All */
|
||||
static struct platform_device *jz_platform_devices[] __initdata = {
|
||||
&jz_usb_ohci_device,
|
||||
&jz_lcd_device,
|
||||
&jz_usb_gdt_device,
|
||||
&jz_mmc_device,
|
||||
&jz4750_rtc_device,
|
||||
};
|
||||
|
||||
static int __init jz_platform_init(void)
|
||||
{
|
||||
return platform_add_devices(jz_platform_devices, ARRAY_SIZE(jz_platform_devices));
|
||||
}
|
||||
|
||||
arch_initcall(jz_platform_init);
|
||||
203
target/linux/xburst/files-2.6.27/arch/mips/jz4750/pm.c
Normal file
203
target/linux/xburst/files-2.6.27/arch/mips/jz4750/pm.c
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4750/common/pm.c
|
||||
*
|
||||
* JZ4750 Power Management Routines
|
||||
*
|
||||
* Copyright (C) 2006 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can distribute it and/or modify it
|
||||
* under the terms of the GNU General Public License (Version 2) as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <asm/cacheops.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
extern void jz_board_do_sleep(unsigned long *ptr);
|
||||
extern void jz_board_do_resume(unsigned long *ptr);
|
||||
|
||||
static void jz_pm_do_hibernate(void)
|
||||
{
|
||||
printk("Put CPU into hibernate mode.\n");
|
||||
|
||||
/* Mask all interrupts */
|
||||
REG_INTC_IMSR = 0xffffffff;
|
||||
|
||||
/*
|
||||
* RTC Wakeup or 1Hz interrupt can be enabled or disabled
|
||||
* through RTC driver's ioctl (linux/driver/char/rtc_jz.c).
|
||||
*/
|
||||
|
||||
/* Set minimum wakeup_n pin low-level assertion time for wakeup: 100ms */
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
REG_RTC_HWFCR = (100 << RTC_HWFCR_BIT);
|
||||
|
||||
/* Set reset pin low-level assertion time after wakeup: must > 60ms */
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
REG_RTC_HRCR = (60 << RTC_HRCR_BIT); /* 60 ms */
|
||||
|
||||
/* Scratch pad register to be reserved */
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
REG_RTC_HSPR = 0x12345678;
|
||||
|
||||
/* clear wakeup status register */
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
REG_RTC_HWRSR = 0x0;
|
||||
|
||||
/* Put CPU to power down mode */
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
REG_RTC_HCR = RTC_HCR_PD;
|
||||
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
while(1);
|
||||
|
||||
/* We can't get here */
|
||||
}
|
||||
|
||||
static int jz_pm_do_sleep(void)
|
||||
{
|
||||
unsigned long delta;
|
||||
unsigned long nfcsr = REG_EMC_NFCSR;
|
||||
unsigned long opcr = REG_CPM_OPCR;
|
||||
unsigned long imr = REG_INTC_IMR;
|
||||
unsigned long sadc = REG_SADC_ENA;
|
||||
unsigned long sleep_gpio_save[4*(GPIO_PORT_NUM-1)];
|
||||
|
||||
printk("Put CPU into sleep mode.\n");
|
||||
|
||||
/* Preserve current time */
|
||||
delta = xtime.tv_sec - REG_RTC_RSR;
|
||||
|
||||
/* Disable nand flash */
|
||||
REG_EMC_NFCSR = ~0xff;
|
||||
|
||||
/* stop sadc */
|
||||
REG_SADC_ENA &= ~0x7;
|
||||
while((REG_SADC_ENA & 0x7) != 0);
|
||||
udelay(100);
|
||||
|
||||
/*stop udc and usb*/
|
||||
__cpm_suspend_uhcphy();
|
||||
__cpm_suspend_udcphy();
|
||||
|
||||
/* Mask all interrupts */
|
||||
REG_INTC_IMSR = 0xffffffff;
|
||||
|
||||
/* Sleep on-board modules and setup wake event */
|
||||
jz_board_do_sleep(sleep_gpio_save);
|
||||
|
||||
/* disable externel clock Oscillator in sleep mode */
|
||||
__cpm_disable_osc_in_sleep();
|
||||
/* select 32K crystal as RTC clock in sleep mode */
|
||||
__cpm_select_rtcclk_rtc();
|
||||
|
||||
/* Enter SLEEP mode */
|
||||
REG_CPM_LCR &= ~CPM_LCR_LPM_MASK;
|
||||
REG_CPM_LCR |= CPM_LCR_LPM_SLEEP;
|
||||
__asm__(".set\tmips3\n\t"
|
||||
"wait\n\t"
|
||||
".set\tmips0");
|
||||
|
||||
/* Restore to IDLE mode */
|
||||
REG_CPM_LCR &= ~CPM_LCR_LPM_MASK;
|
||||
REG_CPM_LCR |= CPM_LCR_LPM_IDLE;
|
||||
|
||||
/* Restore nand flash control register */
|
||||
REG_EMC_NFCSR = nfcsr;
|
||||
|
||||
/* Restore interrupts */
|
||||
REG_INTC_IMSR = imr;
|
||||
REG_INTC_IMCR = ~imr;
|
||||
|
||||
/* Restore sadc */
|
||||
REG_SADC_ENA = sadc;
|
||||
|
||||
/* Resume on-board modules */
|
||||
jz_board_do_resume(sleep_gpio_save);
|
||||
|
||||
/* Restore Oscillator and Power Control Register */
|
||||
REG_CPM_OPCR = opcr;
|
||||
|
||||
/* Restore current time */
|
||||
xtime.tv_sec = REG_RTC_RSR + delta;
|
||||
|
||||
printk("Resume CPU from sleep mode.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Put CPU to HIBERNATE mode
|
||||
*----------------------------------------------------------------------------
|
||||
* Power Management sleep sysctl interface
|
||||
*
|
||||
* Write "mem" to /sys/power/state invokes this function
|
||||
* which initiates a poweroff.
|
||||
*/
|
||||
void jz_pm_hibernate(void)
|
||||
{
|
||||
jz_pm_do_hibernate();
|
||||
}
|
||||
|
||||
/* Put CPU to SLEEP mode
|
||||
*----------------------------------------------------------------------------
|
||||
* Power Management sleep sysctl interface
|
||||
*
|
||||
* Write "standby" to /sys/power/state invokes this function
|
||||
* which initiates a sleep.
|
||||
*/
|
||||
|
||||
int jz_pm_sleep(void)
|
||||
{
|
||||
return jz_pm_do_sleep();
|
||||
}
|
||||
|
||||
/*
|
||||
* valid states, only support standby(sleep) and mem(hibernate)
|
||||
*/
|
||||
static int jz4750_pm_valid(suspend_state_t state)
|
||||
{
|
||||
return state == PM_SUSPEND_MEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Jz CPU enter save power mode
|
||||
*/
|
||||
static int jz4750_pm_enter(suspend_state_t state)
|
||||
{
|
||||
return jz_pm_do_sleep();
|
||||
}
|
||||
|
||||
static struct platform_suspend_ops jz4750_pm_ops = {
|
||||
.valid = jz4750_pm_valid,
|
||||
.enter = jz4750_pm_enter,
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize power interface
|
||||
*/
|
||||
int __init jz_pm_init(void)
|
||||
{
|
||||
printk("JZ4750 Power Management\n");
|
||||
|
||||
suspend_set_ops(&jz4750_pm_ops);
|
||||
return 0;
|
||||
}
|
||||
1058
target/linux/xburst/files-2.6.27/arch/mips/jz4750/proc.c
Normal file
1058
target/linux/xburst/files-2.6.27/arch/mips/jz4750/proc.c
Normal file
File diff suppressed because it is too large
Load Diff
198
target/linux/xburst/files-2.6.27/arch/mips/jz4750/prom.c
Normal file
198
target/linux/xburst/files-2.6.27/arch/mips/jz4750/prom.c
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
*
|
||||
* BRIEF MODULE DESCRIPTION
|
||||
* PROM library initialisation code, supports YAMON and U-Boot.
|
||||
*
|
||||
* Copyright 2000, 2001, 2006 MontaVista Software Inc.
|
||||
* Author: MontaVista Software, Inc.
|
||||
* ppopov@mvista.com or source@mvista.com
|
||||
*
|
||||
* This file was derived from Carsten Langgaard's
|
||||
* arch/mips/mips-boards/xx files.
|
||||
*
|
||||
* Carsten Langgaard, carstenl@mips.com
|
||||
* Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
|
||||
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* 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.,
|
||||
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/* #define DEBUG_CMDLINE */
|
||||
|
||||
int prom_argc;
|
||||
char **prom_argv, **prom_envp;
|
||||
|
||||
char * prom_getcmdline(void)
|
||||
{
|
||||
return &(arcs_cmdline[0]);
|
||||
}
|
||||
|
||||
void prom_init_cmdline(void)
|
||||
{
|
||||
char *cp;
|
||||
int actr;
|
||||
|
||||
actr = 1; /* Always ignore argv[0] */
|
||||
|
||||
cp = &(arcs_cmdline[0]);
|
||||
while(actr < prom_argc) {
|
||||
strcpy(cp, prom_argv[actr]);
|
||||
cp += strlen(prom_argv[actr]);
|
||||
*cp++ = ' ';
|
||||
actr++;
|
||||
}
|
||||
if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
|
||||
--cp;
|
||||
if (prom_argc > 1)
|
||||
*cp = '\0';
|
||||
|
||||
}
|
||||
|
||||
|
||||
char *prom_getenv(char *envname)
|
||||
{
|
||||
#if 0
|
||||
/*
|
||||
* Return a pointer to the given environment variable.
|
||||
* YAMON uses "name", "value" pairs, while U-Boot uses "name=value".
|
||||
*/
|
||||
|
||||
char **env = prom_envp;
|
||||
int i = strlen(envname);
|
||||
int yamon = (*env && strchr(*env, '=') == NULL);
|
||||
|
||||
while (*env) {
|
||||
if (yamon) {
|
||||
if (strcmp(envname, *env++) == 0)
|
||||
return *env;
|
||||
} else {
|
||||
if (strncmp(envname, *env, i) == 0 && (*env)[i] == '=')
|
||||
return *env + i + 1;
|
||||
}
|
||||
env++;
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline unsigned char str2hexnum(unsigned char c)
|
||||
{
|
||||
if(c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
if(c >= 'a' && c <= 'f')
|
||||
return c - 'a' + 10;
|
||||
if(c >= 'A' && c <= 'F')
|
||||
return c - 'A' + 10;
|
||||
return 0; /* foo */
|
||||
}
|
||||
|
||||
inline void str2eaddr(unsigned char *ea, unsigned char *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 6; i++) {
|
||||
unsigned char num;
|
||||
|
||||
if((*str == '.') || (*str == ':'))
|
||||
str++;
|
||||
num = str2hexnum(*str++) << 4;
|
||||
num |= (str2hexnum(*str++));
|
||||
ea[i] = num;
|
||||
}
|
||||
}
|
||||
|
||||
int get_ethernet_addr(char *ethernet_addr)
|
||||
{
|
||||
char *ethaddr_str;
|
||||
|
||||
ethaddr_str = prom_getenv("ethaddr");
|
||||
if (!ethaddr_str) {
|
||||
printk("ethaddr not set in boot prom\n");
|
||||
return -1;
|
||||
}
|
||||
str2eaddr(ethernet_addr, ethaddr_str);
|
||||
|
||||
#if 0
|
||||
{
|
||||
int i;
|
||||
|
||||
printk("get_ethernet_addr: ");
|
||||
for (i=0; i<5; i++)
|
||||
printk("%02x:", (unsigned char)*(ethernet_addr+i));
|
||||
printk("%02x\n", *(ethernet_addr+i));
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init prom_free_prom_memory(void)
|
||||
{
|
||||
}
|
||||
|
||||
void __init prom_init(void)
|
||||
{
|
||||
unsigned char *memsize_str;
|
||||
unsigned long memsize;
|
||||
|
||||
prom_argc = (int) fw_arg0;
|
||||
prom_argv = (char **) fw_arg1;
|
||||
prom_envp = (char **) fw_arg2;
|
||||
|
||||
mips_machtype = MACH_INGENIC_JZ4750;
|
||||
|
||||
prom_init_cmdline();
|
||||
memsize_str = prom_getenv("memsize");
|
||||
if (!memsize_str) {
|
||||
memsize = 0x04000000;
|
||||
} else {
|
||||
memsize = simple_strtol(memsize_str, NULL, 0);
|
||||
}
|
||||
add_memory_region(0, memsize, BOOT_MEM_RAM);
|
||||
}
|
||||
|
||||
/* used by early printk */
|
||||
void prom_putchar(char c)
|
||||
{
|
||||
volatile u8 *uart_lsr = (volatile u8 *)(UART0_BASE + OFF_LSR);
|
||||
volatile u8 *uart_tdr = (volatile u8 *)(UART0_BASE + OFF_TDR);
|
||||
|
||||
/* Wait for fifo to shift out some bytes */
|
||||
while ( !((*uart_lsr & (UARTLSR_TDRQ | UARTLSR_TEMT)) == 0x60) );
|
||||
|
||||
*uart_tdr = (u8)c;
|
||||
}
|
||||
|
||||
const char *get_system_type(void)
|
||||
{
|
||||
return "JZ4750";
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(prom_getcmdline);
|
||||
EXPORT_SYMBOL(get_ethernet_addr);
|
||||
EXPORT_SYMBOL(str2eaddr);
|
||||
46
target/linux/xburst/files-2.6.27/arch/mips/jz4750/reset.c
Normal file
46
target/linux/xburst/files-2.6.27/arch/mips/jz4750/reset.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4750/reset.c
|
||||
*
|
||||
* JZ4750 reset routines.
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <yliu@ingenic.cn>
|
||||
*
|
||||
* 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/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/reboot.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
void jz_restart(char *command)
|
||||
{
|
||||
printk("Restarting after 4 ms\n");
|
||||
REG_WDT_TCSR = WDT_TCSR_PRESCALE4 | WDT_TCSR_EXT_EN;
|
||||
REG_WDT_TCNT = 0;
|
||||
REG_WDT_TDR = JZ_EXTAL/1000; /* reset after 4ms */
|
||||
REG_TCU_TSCR = TCU_TSCR_WDTSC; /* enable wdt clock */
|
||||
REG_WDT_TCER = WDT_TCER_TCEN; /* wdt start */
|
||||
while (1);
|
||||
}
|
||||
|
||||
void jz_halt(void)
|
||||
{
|
||||
printk(KERN_NOTICE "\n** You can safely turn off the power\n");
|
||||
|
||||
while (1)
|
||||
__asm__(".set\tmips3\n\t"
|
||||
"wait\n\t"
|
||||
".set\tmips0");
|
||||
}
|
||||
|
||||
void jz_power_off(void)
|
||||
{
|
||||
jz_halt();
|
||||
}
|
||||
206
target/linux/xburst/files-2.6.27/arch/mips/jz4750/setup.c
Normal file
206
target/linux/xburst/files-2.6.27/arch/mips/jz4750/setup.c
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4750/common/setup.c
|
||||
*
|
||||
* JZ4750 common setup routines.
|
||||
*
|
||||
* Copyright (C) 2006 Ingenic Semiconductor Inc.
|
||||
*
|
||||
* This program is free software; you can distribute it and/or modify it
|
||||
* under the terms of the GNU General Public License (Version 2) as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_8250.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/reboot.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#include <asm/suspend.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PC_KEYB
|
||||
#include <asm/keyboard.h>
|
||||
#endif
|
||||
|
||||
jz_clocks_t jz_clocks;
|
||||
|
||||
extern char * __init prom_getcmdline(void);
|
||||
extern void __init jz_board_setup(void);
|
||||
extern void jz_restart(char *);
|
||||
extern void jz_halt(void);
|
||||
extern void jz_power_off(void);
|
||||
extern void jz_pm_hibernate(void);
|
||||
extern void jz_time_init(void);
|
||||
|
||||
static void __init sysclocks_setup(void)
|
||||
{
|
||||
#ifndef CONFIG_MIPS_JZ_EMURUS /* FPGA */
|
||||
jz_clocks.cclk = __cpm_get_cclk();
|
||||
jz_clocks.hclk = __cpm_get_hclk();
|
||||
jz_clocks.pclk = __cpm_get_pclk();
|
||||
jz_clocks.mclk = __cpm_get_mclk();
|
||||
jz_clocks.lcdclk = __cpm_get_lcdclk();
|
||||
jz_clocks.pixclk = __cpm_get_pixclk();
|
||||
jz_clocks.i2sclk = __cpm_get_i2sclk();
|
||||
jz_clocks.usbclk = __cpm_get_usbclk();
|
||||
jz_clocks.mscclk = __cpm_get_mscclk(0);
|
||||
jz_clocks.extalclk = __cpm_get_extalclk();
|
||||
jz_clocks.rtcclk = __cpm_get_rtcclk();
|
||||
#else
|
||||
|
||||
#define FPGACLK 8000000
|
||||
|
||||
jz_clocks.cclk = FPGACLK;
|
||||
jz_clocks.hclk = FPGACLK;
|
||||
jz_clocks.pclk = FPGACLK;
|
||||
jz_clocks.mclk = FPGACLK;
|
||||
jz_clocks.lcdclk = FPGACLK;
|
||||
jz_clocks.pixclk = FPGACLK;
|
||||
jz_clocks.i2sclk = FPGACLK;
|
||||
jz_clocks.usbclk = FPGACLK;
|
||||
jz_clocks.mscclk = FPGACLK;
|
||||
jz_clocks.extalclk = FPGACLK;
|
||||
jz_clocks.rtcclk = FPGACLK;
|
||||
#endif
|
||||
|
||||
printk("CPU clock: %dMHz, System clock: %dMHz, Peripheral clock: %dMHz, Memory clock: %dMHz\n",
|
||||
(jz_clocks.cclk + 500000) / 1000000,
|
||||
(jz_clocks.hclk + 500000) / 1000000,
|
||||
(jz_clocks.pclk + 500000) / 1000000,
|
||||
(jz_clocks.mclk + 500000) / 1000000);
|
||||
}
|
||||
|
||||
static void __init soc_cpm_setup(void)
|
||||
{
|
||||
/* Start all module clocks
|
||||
*/
|
||||
__cpm_start_all();
|
||||
|
||||
/* Enable CKO to external memory */
|
||||
__cpm_enable_cko();
|
||||
|
||||
/* CPU enters IDLE mode when executing 'wait' instruction */
|
||||
__cpm_idle_mode();
|
||||
|
||||
/* Setup system clocks */
|
||||
sysclocks_setup();
|
||||
}
|
||||
|
||||
static void __init soc_harb_setup(void)
|
||||
{
|
||||
// __harb_set_priority(0x00); /* CIM>LCD>DMA>ETH>PCI>USB>CBB */
|
||||
// __harb_set_priority(0x03); /* LCD>CIM>DMA>ETH>PCI>USB>CBB */
|
||||
// __harb_set_priority(0x0a); /* ETH>LCD>CIM>DMA>PCI>USB>CBB */
|
||||
}
|
||||
|
||||
static void __init soc_emc_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void __init soc_dmac_setup(void)
|
||||
{
|
||||
__dmac_enable_module(0);
|
||||
__dmac_enable_module(1);
|
||||
}
|
||||
|
||||
static void __init jz_soc_setup(void)
|
||||
{
|
||||
soc_cpm_setup();
|
||||
soc_harb_setup();
|
||||
soc_emc_setup();
|
||||
soc_dmac_setup();
|
||||
}
|
||||
|
||||
static void __init jz_serial_setup(void)
|
||||
{
|
||||
#ifdef CONFIG_SERIAL_8250
|
||||
struct uart_port s;
|
||||
REG8(UART0_FCR) |= UARTFCR_UUE; /* enable UART module */
|
||||
memset(&s, 0, sizeof(s));
|
||||
s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
|
||||
s.iotype = SERIAL_IO_MEM;
|
||||
s.regshift = 2;
|
||||
s.uartclk = jz_clocks.extalclk ;
|
||||
|
||||
s.line = 0;
|
||||
s.membase = (u8 *)UART0_BASE;
|
||||
s.irq = IRQ_UART0;
|
||||
if (early_serial_setup(&s) != 0) {
|
||||
printk(KERN_ERR "Serial ttyS0 setup failed!\n");
|
||||
}
|
||||
|
||||
s.line = 1;
|
||||
s.membase = (u8 *)UART1_BASE;
|
||||
s.irq = IRQ_UART1;
|
||||
if (early_serial_setup(&s) != 0) {
|
||||
printk(KERN_ERR "Serial ttyS1 setup failed!\n");
|
||||
}
|
||||
|
||||
s.line = 2;
|
||||
s.membase = (u8 *)UART2_BASE;
|
||||
s.irq = IRQ_UART2;
|
||||
if (early_serial_setup(&s) != 0) {
|
||||
printk(KERN_ERR "Serial ttyS2 setup failed!\n");
|
||||
}
|
||||
|
||||
s.line = 3;
|
||||
s.membase = (u8 *)UART3_BASE;
|
||||
s.irq = IRQ_UART3;
|
||||
if (early_serial_setup(&s) != 0) {
|
||||
printk(KERN_ERR "Serial ttyS3 setup failed!\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void __init plat_mem_setup(void)
|
||||
{
|
||||
char *argptr;
|
||||
|
||||
argptr = prom_getcmdline();
|
||||
|
||||
/* IO/MEM resources. Which will be the addtion value in `inX' and
|
||||
* `outX' macros defined in asm/io.h */
|
||||
set_io_port_base(0);
|
||||
ioport_resource.start = 0x00000000;
|
||||
ioport_resource.end = 0xffffffff;
|
||||
iomem_resource.start = 0x00000000;
|
||||
iomem_resource.end = 0xffffffff;
|
||||
|
||||
_machine_restart = jz_restart;
|
||||
_machine_halt = jz_halt;
|
||||
pm_power_off = jz_pm_hibernate;
|
||||
|
||||
jz_soc_setup();
|
||||
jz_serial_setup();
|
||||
jz_board_setup();
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
jz_pm_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
157
target/linux/xburst/files-2.6.27/arch/mips/jz4750/time.c
Normal file
157
target/linux/xburst/files-2.6.27/arch/mips/jz4750/time.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4750/time.c
|
||||
*
|
||||
* Setting up the clock on the JZ4750 boards.
|
||||
*
|
||||
* Copyright (C) 2008 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can distribute it and/or modify it
|
||||
* under the terms of the GNU General Public License (Version 2) as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/clockchips.h>
|
||||
|
||||
#include <asm/time.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/* This is for machines which generate the exact clock. */
|
||||
|
||||
#define JZ_TIMER_IRQ IRQ_TCU0
|
||||
|
||||
#define JZ_TIMER_CLOCK (JZ_EXTAL>>4) /* Jz timer clock frequency */
|
||||
|
||||
static struct clocksource clocksource_jz; /* Jz clock source */
|
||||
static struct clock_event_device jz_clockevent_device; /* Jz clock event */
|
||||
|
||||
void (*jz_timer_callback)(void);
|
||||
|
||||
static irqreturn_t jz_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct clock_event_device *cd = dev_id;
|
||||
|
||||
REG_TCU_TFCR = TCU_TFCR_OSTFCL; /* ACK timer */
|
||||
|
||||
if (jz_timer_callback)
|
||||
jz_timer_callback();
|
||||
|
||||
cd->event_handler(cd);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct irqaction jz_irqaction = {
|
||||
.handler = jz_timer_interrupt,
|
||||
.flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER,
|
||||
.name = "jz-timerirq",
|
||||
};
|
||||
|
||||
|
||||
cycle_t jz_get_cycles(void)
|
||||
{
|
||||
/* convert jiffes to jz timer cycles */
|
||||
return (cycle_t)( jiffies*((JZ_TIMER_CLOCK)/HZ) + REG_TCU_OSTCNT);
|
||||
}
|
||||
|
||||
static struct clocksource clocksource_jz = {
|
||||
.name = "jz_clocksource",
|
||||
.rating = 300,
|
||||
.read = jz_get_cycles,
|
||||
.mask = 0xFFFFFFFF,
|
||||
.shift = 10,
|
||||
.flags = CLOCK_SOURCE_WATCHDOG,
|
||||
};
|
||||
|
||||
static int __init jz_clocksource_init(void)
|
||||
{
|
||||
clocksource_jz.mult = clocksource_hz2mult(JZ_TIMER_CLOCK, clocksource_jz.shift);
|
||||
clocksource_register(&clocksource_jz);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jz_set_next_event(unsigned long evt,
|
||||
struct clock_event_device *unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void jz_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
break;
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct clock_event_device jz_clockevent_device = {
|
||||
.name = "jz-clockenvent",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC,
|
||||
// .features = CLOCK_EVT_FEAT_ONESHOT, /* Jz4740 not support dynamic clock now */
|
||||
|
||||
/* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */
|
||||
.mult = 1,
|
||||
.rating = 300,
|
||||
.irq = JZ_TIMER_IRQ,
|
||||
.set_mode = jz_set_mode,
|
||||
.set_next_event = jz_set_next_event,
|
||||
};
|
||||
|
||||
static void __init jz_clockevent_init(void)
|
||||
{
|
||||
struct clock_event_device *cd = &jz_clockevent_device;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
cd->cpumask = cpumask_of_cpu(cpu);
|
||||
clockevents_register_device(cd);
|
||||
}
|
||||
|
||||
static void __init jz_timer_setup(void)
|
||||
{
|
||||
jz_clocksource_init(); /* init jz clock source */
|
||||
jz_clockevent_init(); /* init jz clock event */
|
||||
|
||||
/*
|
||||
* Make irqs happen for the system timer
|
||||
*/
|
||||
jz_irqaction.dev_id = &jz_clockevent_device;
|
||||
setup_irq(JZ_TIMER_IRQ, &jz_irqaction);
|
||||
}
|
||||
|
||||
|
||||
void __init plat_time_init(void)
|
||||
{
|
||||
unsigned int latch;
|
||||
|
||||
/* Init timer */
|
||||
latch = (JZ_TIMER_CLOCK + (HZ>>1)) / HZ;
|
||||
|
||||
REG_TCU_OSTCSR = TCU_OSTCSR_PRESCALE16 | TCU_OSTCSR_EXT_EN;
|
||||
REG_TCU_OSTCNT = 0;
|
||||
REG_TCU_OSTDR = latch;
|
||||
|
||||
REG_TCU_TMCR = TCU_TMCR_OSTMCL; /* unmask match irq */
|
||||
REG_TCU_TSCR = TCU_TSCR_OSTSC; /* enable timer clock */
|
||||
REG_TCU_TESR = TCU_TESR_OSTST; /* start counting up */
|
||||
|
||||
jz_timer_setup();
|
||||
}
|
||||
23
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/Makefile
Normal file
23
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/Makefile
Normal file
@@ -0,0 +1,23 @@
|
||||
#
|
||||
# Makefile for the Ingenic JZ4750D.
|
||||
#
|
||||
|
||||
# Object file lists.
|
||||
|
||||
obj-y += prom.o irq.o time.o reset.o setup.o dma.o \
|
||||
platform.o i2c.o
|
||||
|
||||
obj-$(CONFIG_PROC_FS) += proc.o
|
||||
|
||||
# board specific support
|
||||
|
||||
obj-$(CONFIG_JZ4750D_FUWA1) += board-fuwa1.o
|
||||
obj-$(CONFIG_JZ4750D_CETUS) += board-cetus.o
|
||||
|
||||
# PM support
|
||||
|
||||
obj-$(CONFIG_PM) +=pm.o
|
||||
|
||||
# CPU Frequency scaling support
|
||||
|
||||
obj-$(CONFIG_CPU_FREQ_JZ) +=cpufreq.o
|
||||
301
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/board-cetus.c
Executable file
301
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/board-cetus.c
Executable file
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4750d/board-cetus.c
|
||||
*
|
||||
* JZ4750D CETUS board setup routines.
|
||||
*
|
||||
* Copyright (c) 2006-2008 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/reboot.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/*********************************************************************************
|
||||
* Power management routines
|
||||
********************************************************************************/
|
||||
|
||||
/*
|
||||
* __gpio_as_sleep set all pins to pull-disable, and set all pins as input
|
||||
* except sdram and the pins which can be used as CS1_N to CS4_N for chip select.
|
||||
*/
|
||||
#define __gpio_as_sleep() \
|
||||
do { \
|
||||
REG_GPIO_PXFUNC(1) = ~0x03ff7fff; \
|
||||
REG_GPIO_PXSELC(1) = ~0x03ff7fff; \
|
||||
REG_GPIO_PXDIRC(1) = ~0x03ff7fff; \
|
||||
REG_GPIO_PXPES(1) = ~0x03ff7fff; \
|
||||
REG_GPIO_PXFUNC(2) = ~0x01e00000; \
|
||||
REG_GPIO_PXSELC(2) = ~0x01e00000; \
|
||||
REG_GPIO_PXDIRC(2) = ~0x01e00000; \
|
||||
REG_GPIO_PXPES(2) = ~0x01e00000; \
|
||||
REG_GPIO_PXFUNC(3) = 0xffffffff; \
|
||||
REG_GPIO_PXSELC(3) = 0xffffffff; \
|
||||
REG_GPIO_PXDIRC(3) = 0xffffffff; \
|
||||
REG_GPIO_PXPES(3) = 0xffffffff; \
|
||||
REG_GPIO_PXFUNC(4) = 0xffffffff; \
|
||||
REG_GPIO_PXSELC(4) = 0xffffffff; \
|
||||
REG_GPIO_PXDIRC(4) = 0xffffffff; \
|
||||
REG_GPIO_PXPES(4) = 0xffffffff; \
|
||||
REG_GPIO_PXFUNC(5) = 0xffffffff; \
|
||||
REG_GPIO_PXSELC(5) = 0xffffffff; \
|
||||
REG_GPIO_PXDIRC(5) = 0xffffffff; \
|
||||
REG_GPIO_PXPES(5) = 0xffffffff; \
|
||||
} while (0)
|
||||
|
||||
extern void (*jz_timer_callback)(void);
|
||||
|
||||
struct wakeup_key_s {
|
||||
int gpio; /* gpio pin number */
|
||||
int active_low; /* the key interrupt pin is low voltage
|
||||
or fall edge acitve */
|
||||
};
|
||||
|
||||
/* add wakeup keys here */
|
||||
static struct wakeup_key_s wakeup_key[] = {
|
||||
{
|
||||
.gpio = GPIO_CALL,
|
||||
.active_low = ACTIVE_LOW_CALL,
|
||||
},
|
||||
{
|
||||
.gpio = GPIO_HOME,
|
||||
.active_low = ACTIVE_LOW_HOME,
|
||||
},
|
||||
{
|
||||
.gpio = GPIO_BACK,
|
||||
.active_low = ACTIVE_LOW_BACK,
|
||||
},
|
||||
{
|
||||
.gpio = GPIO_MENU,
|
||||
.active_low = ACTIVE_LOW_MENU,
|
||||
},
|
||||
{
|
||||
.gpio = GPIO_ENDCALL,
|
||||
.active_low = ACTIVE_LOW_ENDCALL,
|
||||
},
|
||||
{
|
||||
.gpio = GPIO_ADKEY_INT,
|
||||
.active_low = ACTIVE_LOW_ADKEY,
|
||||
},
|
||||
};
|
||||
|
||||
static void wakeup_key_setup(void)
|
||||
{
|
||||
int i;
|
||||
int num = sizeof(wakeup_key) / sizeof(wakeup_key[0]);
|
||||
|
||||
for(i = 0; i < num; i++) {
|
||||
#if 0
|
||||
if(wakeup_key[i].active_low)
|
||||
__gpio_as_irq_fall_edge(wakeup_key[i].gpio);
|
||||
else
|
||||
__gpio_as_irq_rise_edge(wakeup_key[i].gpio);
|
||||
#endif
|
||||
__gpio_ack_irq(wakeup_key[i].gpio);
|
||||
__gpio_unmask_irq(wakeup_key[i].gpio);
|
||||
__intc_unmask_irq(IRQ_GPIO0 - (wakeup_key[i].gpio/32)); /* unmask IRQ_GPIOn */
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTES:
|
||||
* 1: Pins that are floated (NC) should be set as input and pull-enable.
|
||||
* 2: Pins that are pull-up or pull-down by outside should be set as input
|
||||
* and pull-disable.
|
||||
* 3: Pins that are connected to a chip except sdram and nand flash
|
||||
* should be set as input and pull-disable, too.
|
||||
*/
|
||||
void jz_board_do_sleep(unsigned long *ptr)
|
||||
{
|
||||
unsigned char i;
|
||||
#ifdef DEBUG
|
||||
__intc_unmask_irq(IRQ_UART3);
|
||||
/* Print messages of GPIO registers for debug */
|
||||
for(i=0;i<GPIO_PORT_NUM;i++) {
|
||||
printk("run dat:%x pin:%x fun:%x sel:%x dir:%x pull:%x msk:%x trg:%x\n", \
|
||||
REG_GPIO_PXDAT(i),REG_GPIO_PXPIN(i),REG_GPIO_PXFUN(i),REG_GPIO_PXSEL(i), \
|
||||
REG_GPIO_PXDIR(i),REG_GPIO_PXPE(i),REG_GPIO_PXIM(i),REG_GPIO_PXTRG(i));
|
||||
}
|
||||
#endif
|
||||
/* Save GPIO registers */
|
||||
for(i = 1; i < GPIO_PORT_NUM; i++) {
|
||||
*ptr++ = REG_GPIO_PXFUN(i);
|
||||
*ptr++ = REG_GPIO_PXSEL(i);
|
||||
*ptr++ = REG_GPIO_PXDIR(i);
|
||||
*ptr++ = REG_GPIO_PXPE(i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mask the ethernet irq
|
||||
*/
|
||||
// __gpio_mask_irq(GPIO_NET_INT);
|
||||
|
||||
/*
|
||||
* Set all pins to pull-disable, and set all pins as input except
|
||||
* sdram and the pins which can be used as CS1_N to CS4_N for chip select.
|
||||
*/
|
||||
// __gpio_as_sleep();
|
||||
|
||||
/*
|
||||
* Set proper status for GPC21 to GPC24 which can be used as CS1_N to CS4_N.
|
||||
* Keep the pins' function used for chip select(CS) here according to your
|
||||
* system to avoid chip select crashing with sdram when resuming from sleep mode.
|
||||
*/
|
||||
|
||||
/* GPB25/CS1_N is used as chip select for nand flash, shouldn't be change. */
|
||||
|
||||
/* GPB26/CS2_N is connected to nand flash, needn't be changed. */
|
||||
|
||||
/* GPB28/CS3_N is used as cs8900's chip select, shouldn't be changed. */
|
||||
|
||||
/* GPB27/CS4_N is used as NOR's chip select, shouldn't be changed. */
|
||||
|
||||
/*
|
||||
* Enable pull for NC pins here according to your system
|
||||
*/
|
||||
|
||||
/*
|
||||
* If you must set some GPIOs as output to high level or low level,
|
||||
* you can set them here, using:
|
||||
* __gpio_as_output(n);
|
||||
* __gpio_set_pin(n); or __gpio_clear_pin(n);
|
||||
*/
|
||||
|
||||
/* AMPEN_N should be set to high to disable audio amplifier */
|
||||
__gpio_as_output(GPIO_AMPEN_N);
|
||||
__gpio_set_pin(GPIO_AMPEN_N);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Keep uart function for printing debug message */
|
||||
__gpio_as_uart0();
|
||||
__gpio_as_uart1();
|
||||
|
||||
/* Print messages of GPIO registers for debug */
|
||||
for(i=0;i<GPIO_PORT_NUM;i++) {
|
||||
printk("sleep dat:%x pin:%x fun:%x sel:%x dir:%x pull:%x msk:%x trg:%x\n", \
|
||||
REG_GPIO_PXDAT(i),REG_GPIO_PXPIN(i),REG_GPIO_PXFUN(i),REG_GPIO_PXSEL(i), \
|
||||
REG_GPIO_PXDIR(i),REG_GPIO_PXPE(i),REG_GPIO_PXIM(i),REG_GPIO_PXTRG(i));
|
||||
}
|
||||
__intc_mask_irq(IRQ_UART1);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Just allow following interrupts to wakeup the system.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_RTC_CLASS
|
||||
/* enable RTC alarm */
|
||||
__intc_unmask_irq(IRQ_RTC);
|
||||
#if 0
|
||||
/* make system wake up after n seconds by RTC alarm */
|
||||
unsigned int v, n;
|
||||
n = 10;
|
||||
while (!__rtc_write_ready());
|
||||
__rtc_enable_alarm();
|
||||
while (!__rtc_write_ready());
|
||||
__rtc_enable_alarm_irq();
|
||||
while (!__rtc_write_ready());
|
||||
v = __rtc_get_second();
|
||||
while (!__rtc_write_ready());
|
||||
__rtc_set_alarm_second(v+n);
|
||||
#endif
|
||||
#endif
|
||||
/* setup wakeup keys before sleeping */
|
||||
wakeup_key_setup();
|
||||
}
|
||||
|
||||
void jz_board_do_resume(unsigned long *ptr)
|
||||
{
|
||||
unsigned char i;
|
||||
|
||||
/* Restore GPIO registers */
|
||||
for(i = 1; i < GPIO_PORT_NUM; i++) {
|
||||
REG_GPIO_PXFUNS(i) = *ptr;
|
||||
REG_GPIO_PXFUNC(i) = ~(*ptr++);
|
||||
|
||||
REG_GPIO_PXSELS(i) = *ptr;
|
||||
REG_GPIO_PXSELC(i) = ~(*ptr++);
|
||||
|
||||
REG_GPIO_PXDIRS(i) = *ptr;
|
||||
REG_GPIO_PXDIRC(i) = ~(*ptr++);
|
||||
|
||||
REG_GPIO_PXPES(i) = *ptr;
|
||||
REG_GPIO_PXPEC(i) = ~(*ptr++);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
/* Print messages of GPIO registers for debug */
|
||||
for(i=0;i<GPIO_PORT_NUM;i++) {
|
||||
printk("resume dat:%x pin:%x fun:%x sel:%x dir:%x pull:%x msk:%x trg:%x\n", \
|
||||
REG_GPIO_PXDAT(i),REG_GPIO_PXPIN(i),REG_GPIO_PXFUN(i),REG_GPIO_PXSEL(i), \
|
||||
REG_GPIO_PXDIR(i),REG_GPIO_PXPE(i),REG_GPIO_PXIM(i),REG_GPIO_PXTRG(i));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void dancing(void)
|
||||
{
|
||||
static unsigned char slash[] = "\\|/-";
|
||||
// static volatile unsigned char *p = (unsigned char *)0xb6000058;
|
||||
static volatile unsigned char *p = (unsigned char *)0xb6000016;
|
||||
static unsigned int count = 0;
|
||||
*p = slash[count++];
|
||||
count &= 3;
|
||||
}
|
||||
|
||||
static void cetus_timer_callback(void)
|
||||
{
|
||||
static unsigned long count = 0;
|
||||
|
||||
if ((++count) % 50 == 0) {
|
||||
dancing();
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
static void __init board_cpm_setup(void)
|
||||
{
|
||||
/* Stop unused module clocks here.
|
||||
* We have started all module clocks at arch/mips/jz4750d/setup.c.
|
||||
*/
|
||||
}
|
||||
|
||||
static void __init board_gpio_setup(void)
|
||||
{
|
||||
/*
|
||||
* Initialize SDRAM pins
|
||||
*/
|
||||
__lcd_close_backlight();
|
||||
}
|
||||
|
||||
void __init jz_board_setup(void)
|
||||
{
|
||||
printk("JZ4750D CETUS board setup\n");
|
||||
|
||||
board_cpm_setup();
|
||||
board_gpio_setup();
|
||||
|
||||
jz_timer_callback = NULL;//cetus_timer_callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by arch/mips/kernel/proc.c when 'cat /proc/cpuinfo'.
|
||||
* Android requires the 'Hardware:' field in cpuinfo to setup the init.%hardware%.rc.
|
||||
*/
|
||||
const char *get_board_type(void)
|
||||
{
|
||||
return "cetus";
|
||||
}
|
||||
81
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/board-fuwa1.c
Executable file
81
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/board-fuwa1.c
Executable file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4750d/board-fuwa1.c
|
||||
*
|
||||
* JZ4750D FUWA1 board setup routines.
|
||||
*
|
||||
* Copyright (c) 2006-2008 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/reboot.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
extern void (*jz_timer_callback)(void);
|
||||
|
||||
static void dancing(void)
|
||||
{
|
||||
static unsigned char slash[] = "\\|/-";
|
||||
// static volatile unsigned char *p = (unsigned char *)0xb6000058;
|
||||
static volatile unsigned char *p = (unsigned char *)0xb6000016;
|
||||
static unsigned int count = 0;
|
||||
*p = slash[count++];
|
||||
count &= 3;
|
||||
}
|
||||
|
||||
static void fuwa1_timer_callback(void)
|
||||
{
|
||||
static unsigned long count = 0;
|
||||
|
||||
if ((++count) % 50 == 0) {
|
||||
dancing();
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init board_cpm_setup(void)
|
||||
{
|
||||
/* Stop unused module clocks here.
|
||||
* We have started all module clocks at arch/mips/jz4750d/setup.c.
|
||||
*/
|
||||
}
|
||||
|
||||
static void __init board_gpio_setup(void)
|
||||
{
|
||||
/*
|
||||
* Initialize SDRAM pins
|
||||
*/
|
||||
}
|
||||
|
||||
void __init jz_board_setup(void)
|
||||
{
|
||||
printk("JZ4750D FUWA1 board setup\n");
|
||||
|
||||
board_cpm_setup();
|
||||
board_gpio_setup();
|
||||
|
||||
jz_timer_callback = fuwa1_timer_callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by arch/mips/kernel/proc.c when 'cat /proc/cpuinfo'.
|
||||
* Android requires the 'Hardware:' field in cpuinfo to setup the init.%hardware%.rc.
|
||||
*/
|
||||
const char *get_board_type(void)
|
||||
{
|
||||
return "fuwa1";
|
||||
}
|
||||
600
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/cpufreq.c
Executable file
600
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/cpufreq.c
Executable file
@@ -0,0 +1,600 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4750d/cpufreq.c
|
||||
*
|
||||
* cpufreq driver for JZ4750D
|
||||
*
|
||||
* Copyright (c) 2006-2008 Ingenic Semiconductor Inc.
|
||||
* Author: <lhhuang@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <linux/cpufreq.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
|
||||
"cpufreq-jz4750d", msg)
|
||||
|
||||
#undef CHANGE_PLL
|
||||
|
||||
#define PLL_UNCHANGED 0
|
||||
#define PLL_GOES_UP 1
|
||||
#define PLL_GOES_DOWN 2
|
||||
|
||||
#define PLL_WAIT_500NS (500*(__cpm_get_cclk()/1000000000))
|
||||
|
||||
/* Saved the boot-time parameters */
|
||||
static struct {
|
||||
/* SDRAM parameters */
|
||||
unsigned int mclk; /* memory clock, KHz */
|
||||
unsigned int tras; /* RAS pulse width, cycles of mclk */
|
||||
unsigned int rcd; /* RAS to CAS Delay, cycles of mclk */
|
||||
unsigned int tpc; /* RAS Precharge time, cycles of mclk */
|
||||
unsigned int trwl; /* Write Precharge Time, cycles of mclk */
|
||||
unsigned int trc; /* RAS Cycle Time, cycles of mclk */
|
||||
unsigned int rtcor; /* Refresh Time Constant */
|
||||
unsigned int sdram_initialized;
|
||||
|
||||
/* LCD parameters */
|
||||
unsigned int ah1_clk; /* LCD clock, Hz */
|
||||
unsigned int lcdpix_clk; /* LCD Pixel clock, Hz */
|
||||
unsigned int lcd_clks_initialized;
|
||||
} boot_config;
|
||||
|
||||
struct jz4750d_freq_percpu_info {
|
||||
struct cpufreq_frequency_table table[7];
|
||||
};
|
||||
|
||||
static struct jz4750d_freq_percpu_info jz4750d_freq_table;
|
||||
|
||||
/*
|
||||
* This contains the registers value for an operating point.
|
||||
* If only part of a register needs to change then there is
|
||||
* a mask value for that register.
|
||||
* When going to a new operating point the current register
|
||||
* value is ANDed with the ~mask and ORed with the new value.
|
||||
*/
|
||||
struct dpm_regs {
|
||||
u32 cpccr; /* Clock Freq Control Register */
|
||||
u32 cpccr_mask; /* Clock Freq Control Register mask */
|
||||
u32 cppcr; /* PLL1 Control Register */
|
||||
u32 cppcr_mask; /* PLL1 Control Register mask */
|
||||
u32 pll_up_flag; /* New PLL freq is higher than current or not */
|
||||
};
|
||||
|
||||
extern jz_clocks_t jz_clocks;
|
||||
|
||||
static void jz_update_clocks(void)
|
||||
{
|
||||
/* Next clocks must be updated if we have changed
|
||||
* the PLL or divisors.
|
||||
*/
|
||||
jz_clocks.cclk = __cpm_get_cclk();
|
||||
jz_clocks.hclk = __cpm_get_hclk();
|
||||
jz_clocks.mclk = __cpm_get_mclk();
|
||||
jz_clocks.pclk = __cpm_get_pclk();
|
||||
jz_clocks.h1clk = __cpm_get_h1clk();
|
||||
jz_clocks.pixclk = __cpm_get_pixclk();
|
||||
jz_clocks.i2sclk = __cpm_get_i2sclk();
|
||||
jz_clocks.usbclk = __cpm_get_usbclk();
|
||||
jz_clocks.mscclk = __cpm_get_mscclk(0);
|
||||
}
|
||||
|
||||
static void
|
||||
jz_init_boot_config(void)
|
||||
{
|
||||
if (!boot_config.lcd_clks_initialized) {
|
||||
/* the first time to scale pll */
|
||||
boot_config.lcdpix_clk = __cpm_get_pixclk();
|
||||
boot_config.lcd_clks_initialized = 1;
|
||||
}
|
||||
|
||||
if (!boot_config.sdram_initialized) {
|
||||
/* the first time to scale frequencies */
|
||||
unsigned int dmcr, rtcor;
|
||||
unsigned int tras, rcd, tpc, trwl, trc;
|
||||
|
||||
dmcr = REG_EMC_DMCR;
|
||||
rtcor = REG_EMC_RTCOR;
|
||||
|
||||
tras = (dmcr >> 13) & 0x7;
|
||||
rcd = (dmcr >> 11) & 0x3;
|
||||
tpc = (dmcr >> 8) & 0x7;
|
||||
trwl = (dmcr >> 5) & 0x3;
|
||||
trc = (dmcr >> 2) & 0x7;
|
||||
|
||||
boot_config.mclk = __cpm_get_mclk() / 1000;
|
||||
boot_config.tras = tras + 4;
|
||||
boot_config.rcd = rcd + 1;
|
||||
boot_config.tpc = tpc + 1;
|
||||
boot_config.trwl = trwl + 1;
|
||||
boot_config.trc = trc * 2 + 1;
|
||||
boot_config.rtcor = rtcor;
|
||||
|
||||
boot_config.sdram_initialized = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void jz_update_dram_rtcor(unsigned int new_mclk)
|
||||
{
|
||||
unsigned int rtcor;
|
||||
|
||||
new_mclk /= 1000;
|
||||
rtcor = boot_config.rtcor * new_mclk / boot_config.mclk;
|
||||
rtcor--;
|
||||
|
||||
if (rtcor < 1) rtcor = 1;
|
||||
if (rtcor > 255) rtcor = 255;
|
||||
|
||||
REG_EMC_RTCOR = rtcor;
|
||||
REG_EMC_RTCNT = rtcor;
|
||||
}
|
||||
|
||||
static void jz_update_dram_dmcr(unsigned int new_mclk)
|
||||
{
|
||||
unsigned int dmcr;
|
||||
unsigned int tras, rcd, tpc, trwl, trc;
|
||||
unsigned int valid_time, new_time; /* ns */
|
||||
|
||||
new_mclk /= 1000;
|
||||
tras = boot_config.tras * new_mclk / boot_config.mclk;
|
||||
rcd = boot_config.rcd * new_mclk / boot_config.mclk;
|
||||
tpc = boot_config.tpc * new_mclk / boot_config.mclk;
|
||||
trwl = boot_config.trwl * new_mclk / boot_config.mclk;
|
||||
trc = boot_config.trc * new_mclk / boot_config.mclk;
|
||||
|
||||
/* Validation checking */
|
||||
valid_time = (boot_config.tras * 1000000) / boot_config.mclk;
|
||||
new_time = (tras * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) tras += 1;
|
||||
|
||||
valid_time = (boot_config.rcd * 1000000) / boot_config.mclk;
|
||||
new_time = (rcd * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) rcd += 1;
|
||||
|
||||
valid_time = (boot_config.tpc * 1000000) / boot_config.mclk;
|
||||
new_time = (tpc * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) tpc += 1;
|
||||
|
||||
valid_time = (boot_config.trwl * 1000000) / boot_config.mclk;
|
||||
new_time = (trwl * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) trwl += 1;
|
||||
|
||||
valid_time = (boot_config.trc * 1000000) / boot_config.mclk;
|
||||
new_time = (trc * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) trc += 2;
|
||||
|
||||
tras = (tras < 4) ? 4: tras;
|
||||
tras = (tras > 11) ? 11: tras;
|
||||
tras -= 4;
|
||||
|
||||
rcd = (rcd < 1) ? 1: rcd;
|
||||
rcd = (rcd > 4) ? 4: rcd;
|
||||
rcd -= 1;
|
||||
|
||||
tpc = (tpc < 1) ? 1: tpc;
|
||||
tpc = (tpc > 8) ? 8: tpc;
|
||||
tpc -= 1;
|
||||
|
||||
trwl = (trwl < 1) ? 1: trwl;
|
||||
trwl = (trwl > 4) ? 4: trwl;
|
||||
trwl -= 1;
|
||||
|
||||
trc = (trc < 1) ? 1: trc;
|
||||
trc = (trc > 15) ? 15: trc;
|
||||
trc /= 2;
|
||||
|
||||
dmcr = REG_EMC_DMCR;
|
||||
|
||||
dmcr &= ~(EMC_DMCR_TRAS_MASK | EMC_DMCR_RCD_MASK | EMC_DMCR_TPC_MASK | EMC_DMCR_TRWL_MASK | EMC_DMCR_TRC_MASK);
|
||||
dmcr |= ((tras << EMC_DMCR_TRAS_BIT) | (rcd << EMC_DMCR_RCD_BIT) | (tpc << EMC_DMCR_TPC_BIT) | (trwl << EMC_DMCR_TRWL_BIT) | (trc << EMC_DMCR_TRC_BIT));
|
||||
|
||||
REG_EMC_DMCR = dmcr;
|
||||
}
|
||||
|
||||
static void jz_update_dram_prev(unsigned int cur_mclk, unsigned int new_mclk)
|
||||
{
|
||||
/* No risk, no fun: run with interrupts on! */
|
||||
if (new_mclk > cur_mclk) {
|
||||
/* We're going FASTER, so first update TRAS, RCD, TPC, TRWL
|
||||
* and TRC of DMCR before changing the frequency.
|
||||
*/
|
||||
jz_update_dram_dmcr(new_mclk);
|
||||
} else {
|
||||
/* We're going SLOWER: first update RTCOR value
|
||||
* before changing the frequency.
|
||||
*/
|
||||
jz_update_dram_rtcor(new_mclk);
|
||||
}
|
||||
}
|
||||
|
||||
static void jz_update_dram_post(unsigned int cur_mclk, unsigned int new_mclk)
|
||||
{
|
||||
/* No risk, no fun: run with interrupts on! */
|
||||
if (new_mclk > cur_mclk) {
|
||||
/* We're going FASTER, so update RTCOR
|
||||
* after changing the frequency
|
||||
*/
|
||||
jz_update_dram_rtcor(new_mclk);
|
||||
} else {
|
||||
/* We're going SLOWER: so update TRAS, RCD, TPC, TRWL
|
||||
* and TRC of DMCR after changing the frequency.
|
||||
*/
|
||||
jz_update_dram_dmcr(new_mclk);
|
||||
}
|
||||
}
|
||||
|
||||
static void jz_scale_divisors(struct dpm_regs *regs)
|
||||
{
|
||||
unsigned int cpccr;
|
||||
unsigned int cur_mclk, new_mclk;
|
||||
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
|
||||
unsigned int tmp = 0, wait = PLL_WAIT_500NS;
|
||||
|
||||
cpccr = REG_CPM_CPCCR;
|
||||
cpccr &= ~((unsigned long)regs->cpccr_mask);
|
||||
cpccr |= regs->cpccr;
|
||||
cpccr |= CPM_CPCCR_CE; /* update immediately */
|
||||
|
||||
cur_mclk = __cpm_get_mclk();
|
||||
new_mclk = __cpm_get_pllout() / div[(cpccr & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT];
|
||||
|
||||
/* Update some DRAM parameters before changing frequency */
|
||||
jz_update_dram_prev(cur_mclk, new_mclk);
|
||||
|
||||
/* update register to change the clocks.
|
||||
* align this code to a cache line.
|
||||
*/
|
||||
__asm__ __volatile__(
|
||||
".set noreorder\n\t"
|
||||
".align 5\n"
|
||||
"sw %1,0(%0)\n\t"
|
||||
"li %3,0\n\t"
|
||||
"1:\n\t"
|
||||
"bne %3,%2,1b\n\t"
|
||||
"addi %3, 1\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
".set reorder\n\t"
|
||||
:
|
||||
: "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp));
|
||||
|
||||
/* Update some other DRAM parameters after changing frequency */
|
||||
jz_update_dram_post(cur_mclk, new_mclk);
|
||||
}
|
||||
|
||||
#ifdef CHANGE_PLL
|
||||
/* Maintain the LCD clock and pixel clock */
|
||||
static void jz_scale_lcd_divisors(struct dpm_regs *regs)
|
||||
{
|
||||
unsigned int new_pll, new_lcd_div, new_lcdpix_div;
|
||||
unsigned int cpccr;
|
||||
unsigned int tmp = 0, wait = PLL_WAIT_500NS;
|
||||
|
||||
if (!boot_config.lcd_clks_initialized) return;
|
||||
|
||||
new_pll = __cpm_get_pllout();
|
||||
new_lcd_div = new_pll / boot_config.lcd_clk;
|
||||
new_lcdpix_div = new_pll / boot_config.lcdpix_clk;
|
||||
|
||||
if (new_lcd_div < 1)
|
||||
new_lcd_div = 1;
|
||||
if (new_lcd_div > 16)
|
||||
new_lcd_div = 16;
|
||||
|
||||
if (new_lcdpix_div < 1)
|
||||
new_lcdpix_div = 1;
|
||||
if (new_lcdpix_div > 512)
|
||||
new_lcdpix_div = 512;
|
||||
|
||||
// REG_CPM_CPCCR2 = new_lcdpix_div - 1;
|
||||
|
||||
cpccr = REG_CPM_CPCCR;
|
||||
cpccr &= ~CPM_CPCCR_LDIV_MASK;
|
||||
cpccr |= ((new_lcd_div - 1) << CPM_CPCCR_LDIV_BIT);
|
||||
cpccr |= CPM_CPCCR_CE; /* update immediately */
|
||||
|
||||
/* update register to change the clocks.
|
||||
* align this code to a cache line.
|
||||
*/
|
||||
__asm__ __volatile__(
|
||||
".set noreorder\n\t"
|
||||
".align 5\n"
|
||||
"sw %1,0(%0)\n\t"
|
||||
"li %3,0\n\t"
|
||||
"1:\n\t"
|
||||
"bne %3,%2,1b\n\t"
|
||||
"addi %3, 1\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
".set reorder\n\t"
|
||||
:
|
||||
: "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp));
|
||||
}
|
||||
|
||||
static void jz_scale_pll(struct dpm_regs *regs)
|
||||
{
|
||||
unsigned int cppcr;
|
||||
unsigned int cur_mclk, new_mclk, new_pll;
|
||||
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
|
||||
int od[] = {1, 2, 2, 4};
|
||||
|
||||
cppcr = REG_CPM_CPPCR;
|
||||
cppcr &= ~(regs->cppcr_mask | CPM_CPPCR_PLLS | CPM_CPPCR_PLLEN | CPM_CPPCR_PLLST_MASK);
|
||||
regs->cppcr &= ~CPM_CPPCR_PLLEN;
|
||||
cppcr |= (regs->cppcr | 0xff);
|
||||
|
||||
/* Update some DRAM parameters before changing frequency */
|
||||
new_pll = JZ_EXTAL * ((cppcr>>23)+2) / ((((cppcr>>18)&0x1f)+2) * od[(cppcr>>16)&0x03]);
|
||||
cur_mclk = __cpm_get_mclk();
|
||||
new_mclk = new_pll / div[(REG_CPM_CPCCR>>16) & 0xf];
|
||||
|
||||
/*
|
||||
* Update some SDRAM parameters
|
||||
*/
|
||||
jz_update_dram_prev(cur_mclk, new_mclk);
|
||||
|
||||
/*
|
||||
* Update PLL, align code to cache line.
|
||||
*/
|
||||
cppcr |= CPM_CPPCR_PLLEN;
|
||||
__asm__ __volatile__(
|
||||
".set noreorder\n\t"
|
||||
".align 5\n"
|
||||
"sw %1,0(%0)\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
".set reorder\n\t"
|
||||
:
|
||||
: "r" (CPM_CPPCR), "r" (cppcr));
|
||||
|
||||
/* Update some other DRAM parameters after changing frequency */
|
||||
jz_update_dram_post(cur_mclk, new_mclk);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void jz4750d_transition(struct dpm_regs *regs)
|
||||
{
|
||||
/*
|
||||
* Get and save some boot-time conditions.
|
||||
*/
|
||||
jz_init_boot_config();
|
||||
|
||||
#ifdef CHANGE_PLL
|
||||
/*
|
||||
* Disable LCD before scaling pll.
|
||||
* LCD and LCD pixel clocks should not be changed even if the PLL
|
||||
* output frequency has been changed.
|
||||
*/
|
||||
REG_LCD_CTRL &= ~LCD_CTRL_ENA;
|
||||
|
||||
/*
|
||||
* Stop module clocks before scaling PLL
|
||||
*/
|
||||
__cpm_stop_eth();
|
||||
__cpm_stop_aic(1);
|
||||
__cpm_stop_aic(2);
|
||||
#endif
|
||||
|
||||
/* ... add more as necessary */
|
||||
|
||||
if (regs->pll_up_flag == PLL_GOES_UP) {
|
||||
/* the pll frequency is going up, so change dividors first */
|
||||
jz_scale_divisors(regs);
|
||||
#ifdef CHANGE_PLL
|
||||
jz_scale_pll(regs);
|
||||
#endif
|
||||
}
|
||||
else if (regs->pll_up_flag == PLL_GOES_DOWN) {
|
||||
/* the pll frequency is going down, so change pll first */
|
||||
#ifdef CHANGE_PLL
|
||||
jz_scale_pll(regs);
|
||||
#endif
|
||||
jz_scale_divisors(regs);
|
||||
}
|
||||
else {
|
||||
/* the pll frequency is unchanged, so change divisors only */
|
||||
jz_scale_divisors(regs);
|
||||
}
|
||||
|
||||
#ifdef CHANGE_PLL
|
||||
/*
|
||||
* Restart module clocks before scaling PLL
|
||||
*/
|
||||
__cpm_start_eth();
|
||||
__cpm_start_aic(1);
|
||||
__cpm_start_aic(2);
|
||||
|
||||
/* ... add more as necessary */
|
||||
|
||||
/* Scale the LCD divisors after scaling pll */
|
||||
if (regs->pll_up_flag != PLL_UNCHANGED) {
|
||||
jz_scale_lcd_divisors(regs);
|
||||
}
|
||||
|
||||
/* Enable LCD controller */
|
||||
REG_LCD_CTRL &= ~LCD_CTRL_DIS;
|
||||
REG_LCD_CTRL |= LCD_CTRL_ENA;
|
||||
#endif
|
||||
|
||||
/* Update system clocks */
|
||||
jz_update_clocks();
|
||||
}
|
||||
|
||||
extern unsigned int idle_times;
|
||||
static unsigned int jz4750d_freq_get(unsigned int cpu)
|
||||
{
|
||||
return (__cpm_get_cclk() / 1000);
|
||||
}
|
||||
|
||||
static unsigned int index_to_divisor(unsigned int index, struct dpm_regs *regs)
|
||||
{
|
||||
int n2FR[33] = {
|
||||
0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0,
|
||||
7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
|
||||
9
|
||||
};
|
||||
int div[4] = {1, 2, 2, 2}; /* divisors of I:S:P:M */
|
||||
unsigned int div_of_cclk, new_freq, i;
|
||||
|
||||
regs->pll_up_flag = PLL_UNCHANGED;
|
||||
regs->cpccr_mask = CPM_CPCCR_CDIV_MASK | CPM_CPCCR_HDIV_MASK | CPM_CPCCR_PDIV_MASK | CPM_CPCCR_MDIV_MASK;
|
||||
|
||||
new_freq = jz4750d_freq_table.table[index].frequency;
|
||||
|
||||
do {
|
||||
div_of_cclk = __cpm_get_pllout() / (1000 * new_freq);
|
||||
} while (div_of_cclk==0);
|
||||
|
||||
if(div_of_cclk == 1 || div_of_cclk == 2 || div_of_cclk == 4) {
|
||||
for(i = 1; i<4; i++) {
|
||||
div[i] = 3;
|
||||
}
|
||||
} else {
|
||||
for(i = 1; i<4; i++) {
|
||||
div[i] = 2;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i<4; i++) {
|
||||
div[i] *= div_of_cclk;
|
||||
}
|
||||
|
||||
dprintk("divisors of I:S:P:M = %d:%d:%d:%d\n", div[0], div[1], div[2], div[3]);
|
||||
|
||||
regs->cpccr =
|
||||
(n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) |
|
||||
(n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) |
|
||||
(n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) |
|
||||
(n2FR[div[3]] << CPM_CPCCR_MDIV_BIT);
|
||||
|
||||
return div_of_cclk;
|
||||
}
|
||||
|
||||
static void jz4750d_set_cpu_divider_index(unsigned int cpu, unsigned int index)
|
||||
{
|
||||
unsigned long divisor, old_divisor;
|
||||
struct cpufreq_freqs freqs;
|
||||
struct dpm_regs regs;
|
||||
|
||||
old_divisor = __cpm_get_pllout() / __cpm_get_cclk();
|
||||
divisor = index_to_divisor(index, ®s);
|
||||
|
||||
freqs.old = __cpm_get_cclk() / 1000;
|
||||
freqs.new = __cpm_get_pllout() / (1000 * divisor);
|
||||
freqs.cpu = cpu;
|
||||
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
|
||||
if (old_divisor != divisor)
|
||||
jz4750d_transition(®s);
|
||||
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
}
|
||||
|
||||
static int jz4750d_freq_target(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation)
|
||||
{
|
||||
unsigned int new_index = 0;
|
||||
|
||||
if (cpufreq_frequency_table_target(policy,
|
||||
&jz4750d_freq_table.table[0],
|
||||
target_freq, relation, &new_index))
|
||||
return -EINVAL;
|
||||
|
||||
jz4750d_set_cpu_divider_index(policy->cpu, new_index);
|
||||
|
||||
dprintk("new frequency is %d KHz (REG_CPM_CPCCR:0x%x)\n", __cpm_get_cclk() / 1000, REG_CPM_CPCCR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jz4750d_freq_verify(struct cpufreq_policy *policy)
|
||||
{
|
||||
return cpufreq_frequency_table_verify(policy,
|
||||
&jz4750d_freq_table.table[0]);
|
||||
}
|
||||
|
||||
static int __init jz4750d_cpufreq_driver_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
|
||||
struct cpufreq_frequency_table *table = &jz4750d_freq_table.table[0];
|
||||
unsigned int MAX_FREQ;
|
||||
|
||||
dprintk(KERN_INFO "Jz4750d cpufreq driver\n");
|
||||
|
||||
if (policy->cpu != 0)
|
||||
return -EINVAL;
|
||||
|
||||
policy->cur = MAX_FREQ = __cpm_get_cclk() / 1000; /* in kHz. Current and max frequency is determined by u-boot */
|
||||
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
|
||||
|
||||
policy->cpuinfo.min_freq = MAX_FREQ/8;
|
||||
policy->cpuinfo.max_freq = MAX_FREQ;
|
||||
policy->cpuinfo.transition_latency = 100000; /* in 10^(-9) s = nanoseconds */
|
||||
|
||||
table[0].index = 0;
|
||||
table[0].frequency = MAX_FREQ/8;
|
||||
table[1].index = 1;
|
||||
table[1].frequency = MAX_FREQ/6;
|
||||
table[2].index = 2;
|
||||
table[2].frequency = MAX_FREQ/4;
|
||||
table[3].index = 3;
|
||||
table[3].frequency = MAX_FREQ/3;
|
||||
table[4].index = 4;
|
||||
table[4].frequency = MAX_FREQ/2;
|
||||
table[5].index = 5;
|
||||
table[5].frequency = MAX_FREQ;
|
||||
table[6].index = 6;
|
||||
table[6].frequency = CPUFREQ_TABLE_END;
|
||||
|
||||
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
|
||||
cpufreq_frequency_table_get_attr(table, policy->cpu); /* for showing /sys/devices/system/cpu/cpuX/cpufreq/stats/ */
|
||||
#endif
|
||||
|
||||
return cpufreq_frequency_table_cpuinfo(policy, table);
|
||||
}
|
||||
|
||||
static struct cpufreq_driver cpufreq_jz4750d_driver = {
|
||||
// .flags = CPUFREQ_STICKY,
|
||||
.init = jz4750d_cpufreq_driver_init,
|
||||
.verify = jz4750d_freq_verify,
|
||||
.target = jz4750d_freq_target,
|
||||
.get = jz4750d_freq_get,
|
||||
.name = "jz4750d",
|
||||
};
|
||||
|
||||
static int __init jz4750d_cpufreq_init(void)
|
||||
{
|
||||
return cpufreq_register_driver(&cpufreq_jz4750d_driver);
|
||||
}
|
||||
|
||||
static void __exit jz4750d_cpufreq_exit(void)
|
||||
{
|
||||
cpufreq_unregister_driver(&cpufreq_jz4750d_driver);
|
||||
}
|
||||
|
||||
module_init(jz4750d_cpufreq_init);
|
||||
module_exit(jz4750d_cpufreq_exit);
|
||||
|
||||
MODULE_AUTHOR("Regen <lhhuang@ingenic.cn>");
|
||||
MODULE_DESCRIPTION("cpufreq driver for Jz4750d");
|
||||
MODULE_LICENSE("GPL");
|
||||
822
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/dma.c
Executable file
822
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/dma.c
Executable file
@@ -0,0 +1,822 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4750d/dma.c
|
||||
*
|
||||
* Support functions for the JZ4750D internal DMA channels.
|
||||
* No-descriptor transfer only.
|
||||
* Descriptor transfer should also call jz_request_dma() to get a free
|
||||
* channel and call jz_free_dma() to free the channel. And driver should
|
||||
* build the DMA descriptor and setup the DMA channel by itself.
|
||||
*
|
||||
* Copyright (C) 2006 - 2008 Ingenic Semiconductor Inc.
|
||||
*
|
||||
* 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/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/soundcard.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/*
|
||||
* A note on resource allocation:
|
||||
*
|
||||
* All drivers needing DMA channels, should allocate and release them
|
||||
* through the public routines `jz_request_dma()' and `jz_free_dma()'.
|
||||
*
|
||||
* In order to avoid problems, all processes should allocate resources in
|
||||
* the same sequence and release them in the reverse order.
|
||||
*
|
||||
* So, when allocating DMAs and IRQs, first allocate the DMA, then the IRQ.
|
||||
* When releasing them, first release the IRQ, then release the DMA. The
|
||||
* main reason for this order is that, if you are requesting the DMA buffer
|
||||
* done interrupt, you won't know the irq number until the DMA channel is
|
||||
* returned from jz_request_dma().
|
||||
*/
|
||||
|
||||
struct jz_dma_chan jz_dma_table[MAX_DMA_NUM] = {
|
||||
{dev_id:DMA_ID_BCH_ENC,}, /* DMAC0 channel 0, reserved for BCH */
|
||||
{dev_id:-1,}, /* DMAC0 channel 1 */
|
||||
{dev_id:-1,}, /* DMAC0 channel 2 */
|
||||
{dev_id:-1,}, /* DMAC0 channel 3 */
|
||||
{dev_id:-1,}, /* DMAC1 channel 0 */
|
||||
{dev_id:-1,}, /* DMAC1 channel 1 */
|
||||
{dev_id:-1,}, /* DMAC1 channel 2 */
|
||||
{dev_id:-1,}, /* DMAC1 channel 3 */
|
||||
};
|
||||
|
||||
// Device FIFO addresses and default DMA modes
|
||||
static const struct {
|
||||
unsigned int fifo_addr;
|
||||
unsigned int dma_mode;
|
||||
unsigned int dma_source;
|
||||
} dma_dev_table[DMA_ID_MAX] = {
|
||||
{0, DMA_AUTOINIT, DMAC_DRSR_RS_EXT}, /* External request with DREQn */
|
||||
{0x18000000, DMA_AUTOINIT, DMAC_DRSR_RS_NAND}, /* NAND request */
|
||||
{CPHYSADDR(BCH_DR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_BCH_ENC},
|
||||
{CPHYSADDR(BCH_DR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_BCH_DEC},
|
||||
{0, DMA_AUTOINIT, DMAC_DRSR_RS_AUTO},
|
||||
// {CPHYSADDR(TSSI_FIFO), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_TSSIIN},
|
||||
{CPHYSADDR(UART3_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART3OUT},
|
||||
{CPHYSADDR(UART3_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART3IN},
|
||||
{CPHYSADDR(UART2_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART2OUT},
|
||||
{CPHYSADDR(UART2_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART2IN},
|
||||
{CPHYSADDR(UART1_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART1OUT},
|
||||
{CPHYSADDR(UART1_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART1IN},
|
||||
{CPHYSADDR(UART0_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART0OUT},
|
||||
{CPHYSADDR(UART0_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART0IN},
|
||||
{CPHYSADDR(SSI_DR(0)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_SSI0OUT},
|
||||
{CPHYSADDR(SSI_DR(0)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SSI0IN},
|
||||
{CPHYSADDR(AIC_DR), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_AICOUT},
|
||||
{CPHYSADDR(AIC_DR), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_AICIN},
|
||||
{CPHYSADDR(MSC_TXFIFO(0)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_MSC0OUT},
|
||||
{CPHYSADDR(MSC_RXFIFO(0)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_MSC0IN},
|
||||
{0, DMA_AUTOINIT, DMAC_DRSR_RS_TCU},
|
||||
{SADC_TSDAT, DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SADC},/* Touch Screen Data Register */
|
||||
{CPHYSADDR(MSC_TXFIFO(1)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_MSC1OUT}, /* SSC1 TX */
|
||||
{CPHYSADDR(MSC_RXFIFO(1)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_MSC1IN}, /* SSC1 RX */
|
||||
{CPHYSADDR(SSI_DR(1)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_SSI1OUT},
|
||||
{CPHYSADDR(SSI_DR(1)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SSI1IN},
|
||||
{CPHYSADDR(PCM_DP), DMA_16BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_PMOUT},
|
||||
{CPHYSADDR(PCM_DP), DMA_16BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_PMIN},
|
||||
{},
|
||||
};
|
||||
|
||||
|
||||
int jz_dma_read_proc(char *buf, char **start, off_t fpos,
|
||||
int length, int *eof, void *data)
|
||||
{
|
||||
int i, len = 0;
|
||||
struct jz_dma_chan *chan;
|
||||
|
||||
for (i = 0; i < MAX_DMA_NUM; i++) {
|
||||
if ((chan = get_dma_chan(i)) != NULL) {
|
||||
len += sprintf(buf + len, "%2d: %s\n",
|
||||
i, chan->dev_str);
|
||||
}
|
||||
}
|
||||
|
||||
if (fpos >= len) {
|
||||
*start = buf;
|
||||
*eof = 1;
|
||||
return 0;
|
||||
}
|
||||
*start = buf + fpos;
|
||||
if ((len -= fpos) > length)
|
||||
return length;
|
||||
*eof = 1;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
void dump_jz_dma_channel(unsigned int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan;
|
||||
|
||||
if (dmanr > MAX_DMA_NUM)
|
||||
return;
|
||||
chan = &jz_dma_table[dmanr];
|
||||
|
||||
printk("DMA%d Registers:\n", dmanr);
|
||||
printk(" DMACR = 0x%08x\n", REG_DMAC_DMACR(chan->io/HALF_DMA_NUM));
|
||||
printk(" DSAR = 0x%08x\n", REG_DMAC_DSAR(dmanr));
|
||||
printk(" DTAR = 0x%08x\n", REG_DMAC_DTAR(dmanr));
|
||||
printk(" DTCR = 0x%08x\n", REG_DMAC_DTCR(dmanr));
|
||||
printk(" DRSR = 0x%08x\n", REG_DMAC_DRSR(dmanr));
|
||||
printk(" DCCSR = 0x%08x\n", REG_DMAC_DCCSR(dmanr));
|
||||
printk(" DCMD = 0x%08x\n", REG_DMAC_DCMD(dmanr));
|
||||
printk(" DDA = 0x%08x\n", REG_DMAC_DDA(dmanr));
|
||||
printk(" DMADBR = 0x%08x\n", REG_DMAC_DMADBR(chan->io/HALF_DMA_NUM));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* jz_request_dma - dynamically allcate an idle DMA channel to return
|
||||
* @dev_id: the specified dma device id or DMA_ID_RAW_SET
|
||||
* @dev_str: the specified dma device string name
|
||||
* @irqhandler: the irq handler, or NULL
|
||||
* @irqflags: the irq handler flags
|
||||
* @irq_dev_id: the irq handler device id for shared irq
|
||||
*
|
||||
* Finds a free channel, and binds the requested device to it.
|
||||
* Returns the allocated channel number, or negative on error.
|
||||
* Requests the DMA done IRQ if irqhandler != NULL.
|
||||
*
|
||||
*/
|
||||
/*int jz_request_dma(int dev_id, const char *dev_str,
|
||||
void (*irqhandler)(int, void *, struct pt_regs *),
|
||||
unsigned long irqflags,
|
||||
void *irq_dev_id)
|
||||
*/
|
||||
|
||||
int jz_request_dma(int dev_id, const char *dev_str,
|
||||
irqreturn_t (*irqhandler)(int, void *),
|
||||
unsigned long irqflags,
|
||||
void *irq_dev_id)
|
||||
{
|
||||
struct jz_dma_chan *chan;
|
||||
int i, ret;
|
||||
|
||||
if (dev_id < 0 || dev_id >= DMA_ID_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < MAX_DMA_NUM; i++) {
|
||||
if (jz_dma_table[i].dev_id < 0)
|
||||
break;
|
||||
}
|
||||
if (i == MAX_DMA_NUM) /* no free channel */
|
||||
return -ENODEV;
|
||||
|
||||
/* we got a free channel */
|
||||
chan = &jz_dma_table[i];
|
||||
|
||||
if (irqhandler) {
|
||||
chan->irq = IRQ_DMA_0 + i; // allocate irq number
|
||||
chan->irq_dev = irq_dev_id;
|
||||
if ((ret = request_irq(chan->irq, irqhandler, irqflags,
|
||||
dev_str, chan->irq_dev))) {
|
||||
chan->irq = -1;
|
||||
chan->irq_dev = NULL;
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
chan->irq = -1;
|
||||
chan->irq_dev = NULL;
|
||||
}
|
||||
|
||||
// fill it in
|
||||
chan->io = i;
|
||||
chan->dev_id = dev_id;
|
||||
chan->dev_str = dev_str;
|
||||
chan->fifo_addr = dma_dev_table[dev_id].fifo_addr;
|
||||
chan->mode = dma_dev_table[dev_id].dma_mode;
|
||||
chan->source = dma_dev_table[dev_id].dma_source;
|
||||
|
||||
if (i < HALF_DMA_NUM)
|
||||
REG_DMAC_DMACKE(0) = 1 << i;
|
||||
else
|
||||
REG_DMAC_DMACKE(1) = 1 << (i - HALF_DMA_NUM);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void jz_free_dma(unsigned int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan) {
|
||||
printk("Trying to free DMA%d\n", dmanr);
|
||||
return;
|
||||
}
|
||||
|
||||
disable_dma(dmanr);
|
||||
if (chan->irq)
|
||||
free_irq(chan->irq, chan->irq_dev);
|
||||
|
||||
chan->irq = -1;
|
||||
chan->irq_dev = NULL;
|
||||
chan->dev_id = -1;
|
||||
}
|
||||
|
||||
void jz_set_dma_dest_width(int dmanr, int nbit)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
chan->mode &= ~DMAC_DCMD_DWDH_MASK;
|
||||
switch (nbit) {
|
||||
case 8:
|
||||
chan->mode |= DMAC_DCMD_DWDH_8;
|
||||
break;
|
||||
case 16:
|
||||
chan->mode |= DMAC_DCMD_DWDH_16;
|
||||
break;
|
||||
case 32:
|
||||
chan->mode |= DMAC_DCMD_DWDH_32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void jz_set_dma_src_width(int dmanr, int nbit)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
chan->mode &= ~DMAC_DCMD_SWDH_MASK;
|
||||
switch (nbit) {
|
||||
case 8:
|
||||
chan->mode |= DMAC_DCMD_SWDH_8;
|
||||
break;
|
||||
case 16:
|
||||
chan->mode |= DMAC_DCMD_SWDH_16;
|
||||
break;
|
||||
case 32:
|
||||
chan->mode |= DMAC_DCMD_SWDH_32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void jz_set_dma_block_size(int dmanr, int nbyte)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
chan->mode &= ~DMAC_DCMD_DS_MASK;
|
||||
switch (nbyte) {
|
||||
case 1:
|
||||
chan->mode |= DMAC_DCMD_DS_8BIT;
|
||||
break;
|
||||
case 2:
|
||||
chan->mode |= DMAC_DCMD_DS_16BIT;
|
||||
break;
|
||||
case 4:
|
||||
chan->mode |= DMAC_DCMD_DS_32BIT;
|
||||
break;
|
||||
case 16:
|
||||
chan->mode |= DMAC_DCMD_DS_16BYTE;
|
||||
break;
|
||||
case 32:
|
||||
chan->mode |= DMAC_DCMD_DS_32BYTE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int jz_get_dma_command(int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
return chan->mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* jz_set_dma_mode - do the raw settings for the specified DMA channel
|
||||
* @dmanr: the specified DMA channel
|
||||
* @mode: dma operate mode, DMA_MODE_READ or DMA_MODE_WRITE
|
||||
* @dma_mode: dma raw mode
|
||||
* @dma_source: dma raw request source
|
||||
* @fifo_addr: dma raw device fifo address
|
||||
*
|
||||
* Ensure call jz_request_dma(DMA_ID_RAW_SET, ...) first, then call
|
||||
* jz_set_dma_mode() rather than set_dma_mode() if you work with
|
||||
* and external request dma device.
|
||||
*
|
||||
* NOTE: Don not dynamically allocate dma channel if one external request
|
||||
* dma device will occupy this channel.
|
||||
*/
|
||||
int jz_set_dma_mode(unsigned int dmanr, unsigned int mode,
|
||||
unsigned int dma_mode, unsigned int dma_source,
|
||||
unsigned int fifo_addr)
|
||||
{
|
||||
int dev_id, i;
|
||||
struct jz_dma_chan *chan;
|
||||
|
||||
if (dmanr > MAX_DMA_NUM)
|
||||
return -ENODEV;
|
||||
for (i = 0; i < MAX_DMA_NUM; i++) {
|
||||
if (jz_dma_table[i].dev_id < 0)
|
||||
break;
|
||||
}
|
||||
if (i == MAX_DMA_NUM)
|
||||
return -ENODEV;
|
||||
|
||||
chan = &jz_dma_table[dmanr];
|
||||
dev_id = chan->dev_id;
|
||||
if (dev_id > 0) {
|
||||
printk(KERN_DEBUG "%s sets the allocated DMA channel %d!\n",
|
||||
__FUNCTION__, dmanr);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* clone it from the dynamically allocated. */
|
||||
if (i != dmanr) {
|
||||
chan->irq = jz_dma_table[i].irq;
|
||||
chan->irq_dev = jz_dma_table[i].irq_dev;
|
||||
chan->dev_str = jz_dma_table[i].dev_str;
|
||||
jz_dma_table[i].irq = 0;
|
||||
jz_dma_table[i].irq_dev = NULL;
|
||||
jz_dma_table[i].dev_id = -1;
|
||||
}
|
||||
chan->dev_id = DMA_ID_RAW_SET;
|
||||
chan->io = dmanr;
|
||||
chan->fifo_addr = fifo_addr;
|
||||
chan->mode = dma_mode;
|
||||
chan->source = dma_source;
|
||||
|
||||
set_dma_mode(dmanr, dma_mode);
|
||||
|
||||
return dmanr;
|
||||
}
|
||||
|
||||
void enable_dma(unsigned int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
REG_DMAC_DCCSR(dmanr) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR);
|
||||
REG_DMAC_DCCSR(dmanr) |= DMAC_DCCSR_NDES; /* No-descriptor transfer */
|
||||
__dmac_enable_channel(dmanr);
|
||||
if (chan->irq)
|
||||
__dmac_channel_enable_irq(dmanr);
|
||||
}
|
||||
|
||||
#define DMA_DISABLE_POLL 0x10000
|
||||
|
||||
void disable_dma(unsigned int dmanr)
|
||||
{
|
||||
int i;
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
if (!__dmac_channel_enabled(dmanr))
|
||||
return;
|
||||
|
||||
for (i = 0; i < DMA_DISABLE_POLL; i++)
|
||||
if (__dmac_channel_transmit_end_detected(dmanr))
|
||||
break;
|
||||
#if 0
|
||||
if (i == DMA_DISABLE_POLL)
|
||||
printk(KERN_INFO "disable_dma: poll expired!\n");
|
||||
#endif
|
||||
|
||||
__dmac_disable_channel(dmanr);
|
||||
if (chan->irq)
|
||||
__dmac_channel_disable_irq(dmanr);
|
||||
}
|
||||
|
||||
/* Note: DMA_MODE_MASK is simulated by sw */
|
||||
void set_dma_mode(unsigned int dmanr, unsigned int mode)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI);
|
||||
mode &= DMA_MODE_MASK;
|
||||
if (mode == DMA_MODE_READ) {
|
||||
chan->mode |= DMAC_DCMD_DAI;
|
||||
chan->mode &= ~DMAC_DCMD_SAI;
|
||||
} else if (mode == DMA_MODE_WRITE) {
|
||||
chan->mode |= DMAC_DCMD_SAI;
|
||||
chan->mode &= ~DMAC_DCMD_DAI;
|
||||
} else {
|
||||
printk(KERN_DEBUG "set_dma_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n");
|
||||
}
|
||||
REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK;
|
||||
REG_DMAC_DRSR(chan->io) = chan->source;
|
||||
}
|
||||
|
||||
void set_dma_addr(unsigned int dmanr, unsigned int phyaddr)
|
||||
{
|
||||
unsigned int mode;
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
mode = chan->mode & DMA_MODE_MASK;
|
||||
if (mode == DMA_MODE_READ) {
|
||||
REG_DMAC_DSAR(chan->io) = chan->fifo_addr;
|
||||
REG_DMAC_DTAR(chan->io) = phyaddr;
|
||||
} else if (mode == DMA_MODE_WRITE) {
|
||||
REG_DMAC_DSAR(chan->io) = phyaddr;
|
||||
REG_DMAC_DTAR(chan->io) = chan->fifo_addr;
|
||||
} else
|
||||
printk(KERN_DEBUG "Driver should call set_dma_mode() ahead set_dma_addr()!\n");
|
||||
}
|
||||
|
||||
void set_dma_count(unsigned int dmanr, unsigned int bytecnt)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
int dma_ds[] = {4, 1, 2, 16, 32};
|
||||
unsigned int ds;
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT;
|
||||
REG_DMAC_DTCR(chan->io) = bytecnt / dma_ds[ds]; // transfer count
|
||||
}
|
||||
|
||||
unsigned int get_dma_residue(unsigned int dmanr)
|
||||
{
|
||||
unsigned int count, ds;
|
||||
int dma_ds[] = {4, 1, 2, 16, 32};
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
if (!chan)
|
||||
return 0;
|
||||
|
||||
ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT;
|
||||
count = REG_DMAC_DTCR(chan->io);
|
||||
count = count * dma_ds[ds];
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
switch (audio_fmt) {
|
||||
case AFMT_U8:
|
||||
/* burst mode : 32BIT */
|
||||
break;
|
||||
case AFMT_S16_LE:
|
||||
/* burst mode : 16BYTE */
|
||||
if (mode == DMA_MODE_READ) {
|
||||
chan->mode = DMA_AIC_32_16BYTE_RX_CMD | DMA_MODE_READ;
|
||||
chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI);
|
||||
mode &= DMA_MODE_MASK;
|
||||
chan->mode |= DMAC_DCMD_DAI;
|
||||
chan->mode &= ~DMAC_DCMD_SAI;
|
||||
} else if (mode == DMA_MODE_WRITE) {
|
||||
chan->mode = DMA_AIC_32_16BYTE_TX_CMD | DMA_MODE_WRITE;
|
||||
//chan->mode = DMA_AIC_16BYTE_TX_CMD | DMA_MODE_WRITE;
|
||||
chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI);
|
||||
mode &= DMA_MODE_MASK;
|
||||
chan->mode |= DMAC_DCMD_SAI;
|
||||
chan->mode &= ~DMAC_DCMD_DAI;
|
||||
} else
|
||||
printk("oss_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n");
|
||||
|
||||
REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK;
|
||||
REG_DMAC_DRSR(chan->io) = chan->source;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
switch (audio_fmt) {
|
||||
case 8:
|
||||
/* SNDRV_PCM_FORMAT_S8 burst mode : 32BIT */
|
||||
break;
|
||||
case 16:
|
||||
/* SNDRV_PCM_FORMAT_S16_LE burst mode : 16BYTE */
|
||||
if (mode == DMA_MODE_READ) {
|
||||
chan->mode = DMA_AIC_16BYTE_RX_CMD | DMA_MODE_READ;
|
||||
chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI);
|
||||
mode &= DMA_MODE_MASK;
|
||||
chan->mode |= DMAC_DCMD_DAI;
|
||||
chan->mode &= ~DMAC_DCMD_SAI;
|
||||
} else if (mode == DMA_MODE_WRITE) {
|
||||
chan->mode = DMA_AIC_16BYTE_TX_CMD | DMA_MODE_WRITE;
|
||||
chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI);
|
||||
mode &= DMA_MODE_MASK;
|
||||
chan->mode |= DMAC_DCMD_SAI;
|
||||
chan->mode &= ~DMAC_DCMD_DAI;
|
||||
} else
|
||||
printk("alsa_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n");
|
||||
|
||||
REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK;
|
||||
REG_DMAC_DRSR(chan->io) = chan->source;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//#define JZ4750D_DMAC_TEST_ENABLE
|
||||
#undef JZ4750D_DMAC_TEST_ENABLE
|
||||
|
||||
#ifdef JZ4750D_DMAC_TEST_ENABLE
|
||||
|
||||
/*
|
||||
* DMA test: external address <--> external address
|
||||
*/
|
||||
#define TEST_DMA_SIZE 16*1024
|
||||
|
||||
static jz_dma_desc *dma_desc;
|
||||
|
||||
static int dma_chan;
|
||||
static dma_addr_t dma_desc_phys_addr;
|
||||
static unsigned int dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr;
|
||||
|
||||
static int dma_check_result(void *src, void *dst, int size)
|
||||
{
|
||||
unsigned int addr1, addr2, i, err = 0;
|
||||
|
||||
addr1 = (unsigned int)src;
|
||||
addr2 = (unsigned int)dst;
|
||||
|
||||
for (i = 0; i < size; i += 4) {
|
||||
if (*(volatile unsigned int *)addr1 != *(volatile unsigned int *)addr2) {
|
||||
err++;
|
||||
printk("wrong data at 0x%08x: src 0x%08x dst 0x%08x\n", addr2, *(volatile unsigned int *)addr1, *(volatile unsigned int *)addr2);
|
||||
}
|
||||
addr1 += 4;
|
||||
addr2 += 4;
|
||||
}
|
||||
printk("check DMA result err=%d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
static irqreturn_t jz4750d_dma_irq(int irq, void *dev_id)
|
||||
{
|
||||
printk("jz4750d_dma_irq %d\n", irq);
|
||||
|
||||
|
||||
if (__dmac_channel_transmit_halt_detected(dma_chan)) {
|
||||
printk("DMA HALT\n");
|
||||
REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */
|
||||
__dmac_channel_clear_transmit_halt(dma_chan);
|
||||
}
|
||||
|
||||
if (__dmac_channel_address_error_detected(dma_chan)) {
|
||||
printk("DMA ADDR ERROR\n");
|
||||
REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */
|
||||
REG_DMAC_DSAR(dma_chan) = 0; /* clear source address register */
|
||||
REG_DMAC_DTAR(dma_chan) = 0; /* clear target address register */
|
||||
__dmac_channel_clear_address_error(dma_chan);
|
||||
}
|
||||
|
||||
if (__dmac_channel_descriptor_invalid_detected(dma_chan)) {
|
||||
REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */
|
||||
printk("DMA DESC INVALID\n");
|
||||
__dmac_channel_clear_descriptor_invalid(dma_chan);
|
||||
}
|
||||
|
||||
if (__dmac_channel_count_terminated_detected(dma_chan)) {
|
||||
printk("DMA CT\n");
|
||||
__dmac_channel_clear_count_terminated(dma_chan);
|
||||
}
|
||||
|
||||
if (__dmac_channel_transmit_end_detected(dma_chan)) {
|
||||
REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */
|
||||
printk("DMA TT\n");
|
||||
__dmac_channel_clear_transmit_end(dma_chan);
|
||||
dump_jz_dma_channel(dma_chan);
|
||||
dma_check_result((void *)dma_src_addr, (void *)dma_dst_addr, TEST_DMA_SIZE);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
void dma_nodesc_test(void)
|
||||
{
|
||||
unsigned int addr, i;
|
||||
|
||||
printk("dma_nodesc_test\n");
|
||||
|
||||
/* Request DMA channel and setup irq handler */
|
||||
dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4750d_dma_irq,
|
||||
IRQF_DISABLED, NULL);
|
||||
if (dma_chan < 0) {
|
||||
printk("Setup irq failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printk("Requested DMA channel = %d\n", dma_chan);
|
||||
|
||||
/* Allocate DMA buffers */
|
||||
dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */
|
||||
dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */
|
||||
|
||||
dma_src_phys_addr = CPHYSADDR(dma_src_addr);
|
||||
dma_dst_phys_addr = CPHYSADDR(dma_dst_addr);
|
||||
|
||||
printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n",
|
||||
dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr);
|
||||
|
||||
/* Prepare data for source buffer */
|
||||
addr = (unsigned int)dma_src_addr;
|
||||
for (i = 0; i < TEST_DMA_SIZE; i += 4) {
|
||||
*(volatile unsigned int *)addr = addr;
|
||||
addr += 4;
|
||||
}
|
||||
dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE);
|
||||
|
||||
/* Init target buffer */
|
||||
memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE);
|
||||
dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE);
|
||||
|
||||
/* Init DMA module */
|
||||
printk("Starting DMA\n");
|
||||
REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = 0;
|
||||
REG_DMAC_DCCSR(dma_chan) = 0;
|
||||
REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO;
|
||||
REG_DMAC_DSAR(dma_chan) = dma_src_phys_addr;
|
||||
REG_DMAC_DTAR(dma_chan) = dma_dst_phys_addr;
|
||||
REG_DMAC_DTCR(dma_chan) = 512;
|
||||
REG_DMAC_DCMD(dma_chan) = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TIE;
|
||||
REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_NDES | DMAC_DCCSR_EN;
|
||||
REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = DMAC_DMACR_DMAE; /* global DMA enable bit */
|
||||
|
||||
printk("DMA started. IMR=%08x\n", REG_INTC_IMR);
|
||||
|
||||
/* wait a long time, ensure transfer end */
|
||||
printk("wait 3s...\n");
|
||||
mdelay(3000); /* wait 3s */
|
||||
|
||||
REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */
|
||||
/* free buffers */
|
||||
printk("free DMA buffers\n");
|
||||
free_pages(dma_src_addr, 2);
|
||||
free_pages(dma_dst_addr, 2);
|
||||
|
||||
if (dma_desc)
|
||||
free_pages((unsigned int)dma_desc, 0);
|
||||
|
||||
/* free dma */
|
||||
jz_free_dma(dma_chan);
|
||||
}
|
||||
|
||||
void dma_desc_test(void)
|
||||
{
|
||||
unsigned int next, addr, i;
|
||||
static jz_dma_desc *desc;
|
||||
|
||||
printk("dma_desc_test\n");
|
||||
|
||||
/* Request DMA channel and setup irq handler */
|
||||
dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4750d_dma_irq,
|
||||
IRQF_DISABLED, NULL);
|
||||
if (dma_chan < 0) {
|
||||
printk("Setup irq failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printk("Requested DMA channel = %d\n", dma_chan);
|
||||
|
||||
/* Allocate DMA buffers */
|
||||
dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */
|
||||
dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */
|
||||
|
||||
dma_src_phys_addr = CPHYSADDR(dma_src_addr);
|
||||
dma_dst_phys_addr = CPHYSADDR(dma_dst_addr);
|
||||
|
||||
printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n",
|
||||
dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr);
|
||||
|
||||
/* Prepare data for source buffer */
|
||||
addr = (unsigned int)dma_src_addr;
|
||||
for (i = 0; i < TEST_DMA_SIZE; i += 4) {
|
||||
*(volatile unsigned int *)addr = addr;
|
||||
addr += 4;
|
||||
}
|
||||
dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE);
|
||||
|
||||
/* Init target buffer */
|
||||
memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE);
|
||||
dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE);
|
||||
|
||||
/* Allocate DMA descriptors */
|
||||
dma_desc = (jz_dma_desc *)__get_free_pages(GFP_KERNEL, 0);
|
||||
dma_desc_phys_addr = CPHYSADDR((unsigned long)dma_desc);
|
||||
|
||||
printk("DMA descriptor address: 0x%08x 0x%08x\n", (u32)dma_desc, dma_desc_phys_addr);
|
||||
|
||||
/* Setup DMA descriptors */
|
||||
desc = dma_desc;
|
||||
next = (dma_desc_phys_addr + (sizeof(jz_dma_desc))) >> 4;
|
||||
|
||||
desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK;
|
||||
desc->dsadr = dma_src_phys_addr; /* DMA source address */
|
||||
desc->dtadr = dma_dst_phys_addr; /* DMA target address */
|
||||
desc->ddadr = (next << 24) + 128; /* size: 128*32 bytes = 4096 bytes */
|
||||
|
||||
desc++;
|
||||
next = (dma_desc_phys_addr + 2*(sizeof(jz_dma_desc))) >> 4;
|
||||
|
||||
desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK;
|
||||
desc->dsadr = dma_src_phys_addr + 4096; /* DMA source address */
|
||||
desc->dtadr = dma_dst_phys_addr + 4096; /* DMA target address */
|
||||
desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */
|
||||
|
||||
desc++;
|
||||
next = (dma_desc_phys_addr + 3*(sizeof(jz_dma_desc))) >> 4;
|
||||
|
||||
desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK;
|
||||
desc->dsadr = dma_src_phys_addr + 8192; /* DMA source address */
|
||||
desc->dtadr = dma_dst_phys_addr + 8192; /* DMA target address */
|
||||
desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */
|
||||
|
||||
desc++;
|
||||
next = (dma_desc_phys_addr + 4*(sizeof(jz_dma_desc))) >> 4;
|
||||
|
||||
desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE;
|
||||
desc->dsadr = dma_src_phys_addr + 12*1024; /* DMA source address */
|
||||
desc->dtadr = dma_dst_phys_addr + 12*1024; /* DMA target address */
|
||||
desc->ddadr = (next << 24) + 1024; /* size: 1024*4 bytes = 4096 bytes */
|
||||
|
||||
dma_cache_wback((unsigned long)dma_desc, 4*(sizeof(jz_dma_desc)));
|
||||
|
||||
/* Setup DMA descriptor address */
|
||||
REG_DMAC_DDA(dma_chan) = dma_desc_phys_addr;
|
||||
|
||||
/* Setup request source */
|
||||
REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO;
|
||||
|
||||
/* Setup DMA channel control/status register */
|
||||
REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_EN; /* descriptor transfer, clear status, start channel */
|
||||
|
||||
/* Enable DMA */
|
||||
REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = DMAC_DMACR_DMAE;
|
||||
|
||||
/* DMA doorbell set -- start DMA now ... */
|
||||
REG_DMAC_DMADBSR(dma_chan/HALF_DMA_NUM) = 1 << dma_chan;
|
||||
|
||||
printk("DMA started. IMR=%08x\n", REG_INTC_IMR);
|
||||
/* wait a long time, ensure transfer end */
|
||||
printk("wait 3s...\n");
|
||||
mdelay(3000); /* wait 3s */
|
||||
|
||||
REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */
|
||||
/* free buffers */
|
||||
printk("free DMA buffers\n");
|
||||
free_pages(dma_src_addr, 2);
|
||||
free_pages(dma_dst_addr, 2);
|
||||
|
||||
if (dma_desc)
|
||||
free_pages((unsigned int)dma_desc, 0);
|
||||
|
||||
/* free dma */
|
||||
jz_free_dma(dma_chan);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//EXPORT_SYMBOL_NOVERS(jz_dma_table);
|
||||
EXPORT_SYMBOL(jz_dma_table);
|
||||
EXPORT_SYMBOL(jz_request_dma);
|
||||
EXPORT_SYMBOL(jz_free_dma);
|
||||
EXPORT_SYMBOL(jz_set_dma_src_width);
|
||||
EXPORT_SYMBOL(jz_set_dma_dest_width);
|
||||
EXPORT_SYMBOL(jz_set_dma_block_size);
|
||||
EXPORT_SYMBOL(jz_set_dma_mode);
|
||||
EXPORT_SYMBOL(set_dma_mode);
|
||||
EXPORT_SYMBOL(jz_set_oss_dma);
|
||||
EXPORT_SYMBOL(jz_set_alsa_dma);
|
||||
EXPORT_SYMBOL(set_dma_addr);
|
||||
EXPORT_SYMBOL(set_dma_count);
|
||||
EXPORT_SYMBOL(get_dma_residue);
|
||||
EXPORT_SYMBOL(enable_dma);
|
||||
EXPORT_SYMBOL(disable_dma);
|
||||
EXPORT_SYMBOL(dump_jz_dma_channel);
|
||||
385
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/i2c.c
Executable file
385
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/i2c.c
Executable file
@@ -0,0 +1,385 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4750d/i2c.c
|
||||
*
|
||||
* Jz4750D I2C routines.
|
||||
*
|
||||
* Copyright (C) 2005,2006 Ingenic Semiconductor Inc.
|
||||
* Author: <lhhuang@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can distribute it and/or modify it
|
||||
* under the terms of the GNU General Public License (Version 2) as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/addrspace.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/* I2C protocol */
|
||||
#define I2C_READ 1
|
||||
#define I2C_WRITE 0
|
||||
|
||||
#define TIMEOUT 1000
|
||||
|
||||
/*
|
||||
* I2C bus protocol basic routines
|
||||
*/
|
||||
static int i2c_put_data(unsigned char data)
|
||||
{
|
||||
unsigned int timeout = TIMEOUT*10;
|
||||
|
||||
__i2c_write(data);
|
||||
__i2c_set_drf();
|
||||
while (__i2c_check_drf() != 0);
|
||||
while (!__i2c_transmit_ended());
|
||||
while (!__i2c_received_ack() && timeout)
|
||||
timeout--;
|
||||
|
||||
if (timeout)
|
||||
return 0;
|
||||
else
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int i2c_put_data_nack(unsigned char data)
|
||||
{
|
||||
unsigned int timeout = TIMEOUT*10;
|
||||
|
||||
__i2c_write(data);
|
||||
__i2c_set_drf();
|
||||
while (__i2c_check_drf() != 0);
|
||||
while (!__i2c_transmit_ended());
|
||||
while (timeout--);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2c_get_data(unsigned char *data, int ack)
|
||||
{
|
||||
int timeout = TIMEOUT*10;
|
||||
|
||||
if (!ack)
|
||||
__i2c_send_nack();
|
||||
else
|
||||
__i2c_send_ack();
|
||||
|
||||
while (__i2c_check_drf() == 0 && timeout)
|
||||
timeout--;
|
||||
|
||||
if (timeout) {
|
||||
if (!ack)
|
||||
__i2c_send_stop();
|
||||
*data = __i2c_read();
|
||||
__i2c_clear_drf();
|
||||
return 0;
|
||||
} else
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/*
|
||||
* I2C interface
|
||||
*/
|
||||
void i2c_open(void)
|
||||
{
|
||||
__i2c_set_clk(jz_clocks.extalclk, 10000); /* default 10 KHz */
|
||||
__i2c_enable();
|
||||
}
|
||||
|
||||
void i2c_close(void)
|
||||
{
|
||||
udelay(300); /* wait for STOP goes over. */
|
||||
__i2c_disable();
|
||||
}
|
||||
|
||||
void i2c_setclk(unsigned int i2cclk)
|
||||
{
|
||||
__i2c_set_clk(jz_clocks.extalclk, i2cclk);
|
||||
}
|
||||
|
||||
int i2c_lseek(unsigned char device, unsigned char offset)
|
||||
{
|
||||
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
|
||||
goto device_err;
|
||||
if (i2c_put_data(offset) < 0)
|
||||
goto address_err;
|
||||
return 0;
|
||||
device_err:
|
||||
printk(KERN_DEBUG "No I2C device (0x%02x) installed.\n", device);
|
||||
__i2c_send_stop();
|
||||
return -ENODEV;
|
||||
address_err:
|
||||
printk(KERN_DEBUG "No I2C device (0x%02x) response.\n", device);
|
||||
__i2c_send_stop();
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
int i2c_read(unsigned char device, unsigned char *buf,
|
||||
unsigned char address, int count)
|
||||
{
|
||||
int cnt = count;
|
||||
int timeout = 5;
|
||||
|
||||
L_try_again:
|
||||
|
||||
if (timeout < 0)
|
||||
goto L_timeout;
|
||||
|
||||
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
|
||||
goto device_werr;
|
||||
if (i2c_put_data(address) < 0)
|
||||
goto address_err;
|
||||
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_READ ) < 0)
|
||||
goto device_rerr;
|
||||
__i2c_send_ack(); /* Master sends ACK for continue reading */
|
||||
while (cnt) {
|
||||
if (cnt == 1) {
|
||||
if (i2c_get_data(buf, 0) < 0)
|
||||
break;
|
||||
} else {
|
||||
if (i2c_get_data(buf, 1) < 0)
|
||||
break;
|
||||
}
|
||||
cnt--;
|
||||
buf++;
|
||||
}
|
||||
|
||||
__i2c_send_stop();
|
||||
return count - cnt;
|
||||
device_rerr:
|
||||
device_werr:
|
||||
address_err:
|
||||
timeout --;
|
||||
__i2c_send_stop();
|
||||
goto L_try_again;
|
||||
|
||||
L_timeout:
|
||||
__i2c_send_stop();
|
||||
printk("Read I2C device 0x%2x failed.\n", device);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int i2c_write(unsigned char device, unsigned char *buf,
|
||||
unsigned char address, int count)
|
||||
{
|
||||
int cnt = count;
|
||||
int cnt_in_pg;
|
||||
int timeout = 5;
|
||||
unsigned char *tmpbuf;
|
||||
unsigned char tmpaddr;
|
||||
|
||||
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
|
||||
|
||||
W_try_again:
|
||||
if (timeout < 0)
|
||||
goto W_timeout;
|
||||
|
||||
cnt = count;
|
||||
tmpbuf = (unsigned char *)buf;
|
||||
tmpaddr = address;
|
||||
|
||||
start_write_page:
|
||||
cnt_in_pg = 0;
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
|
||||
goto device_err;
|
||||
#ifdef CONFIG_JZ_TPANEL_ATA2508
|
||||
if (address == 0xff) {
|
||||
if (i2c_put_data_nack(tmpaddr) < 0)
|
||||
goto address_err;
|
||||
while (cnt) {
|
||||
if (++cnt_in_pg > 8) {
|
||||
__i2c_send_stop();
|
||||
mdelay(1);
|
||||
tmpaddr += 8;
|
||||
goto start_write_page;
|
||||
}
|
||||
if (i2c_put_data_nack(*tmpbuf) < 0)
|
||||
break;
|
||||
cnt--;
|
||||
tmpbuf++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if (i2c_put_data(tmpaddr) < 0)
|
||||
goto address_err;
|
||||
while (cnt) {
|
||||
if (++cnt_in_pg > 8) {
|
||||
__i2c_send_stop();
|
||||
mdelay(1);
|
||||
tmpaddr += 8;
|
||||
goto start_write_page;
|
||||
}
|
||||
if (i2c_put_data(*tmpbuf) < 0)
|
||||
break;
|
||||
cnt--;
|
||||
tmpbuf++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (i2c_put_data(tmpaddr) < 0)
|
||||
goto address_err;
|
||||
while (cnt) {
|
||||
if (++cnt_in_pg > 8) {
|
||||
__i2c_send_stop();
|
||||
mdelay(1);
|
||||
tmpaddr += 8;
|
||||
goto start_write_page;
|
||||
}
|
||||
if (i2c_put_data(*tmpbuf) < 0)
|
||||
break;
|
||||
cnt--;
|
||||
tmpbuf++;
|
||||
}
|
||||
#endif
|
||||
__i2c_send_stop();
|
||||
return count - cnt;
|
||||
device_err:
|
||||
address_err:
|
||||
timeout--;
|
||||
__i2c_send_stop();
|
||||
goto W_try_again;
|
||||
|
||||
W_timeout:
|
||||
printk(KERN_DEBUG "Write I2C device 0x%2x failed.\n", device);
|
||||
__i2c_send_stop();
|
||||
return -ENODEV;
|
||||
}
|
||||
int i2c_read_16(unsigned char device, unsigned char *buf,
|
||||
unsigned short address, int count)
|
||||
{
|
||||
int cnt = count;
|
||||
int timeout = 5;
|
||||
unsigned char tmpaddrh, tmpaddrl;
|
||||
|
||||
tmpaddrh = (unsigned char)((address >> 8) & 0xff);
|
||||
tmpaddrl = (unsigned char)(address & 0xff);
|
||||
|
||||
L_try_again:
|
||||
|
||||
if (timeout < 0)
|
||||
goto L_timeout;
|
||||
|
||||
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
|
||||
goto device_werr;
|
||||
if (i2c_put_data_nack(tmpaddrh) < 0)
|
||||
goto address_err;
|
||||
if (i2c_put_data(tmpaddrl) < 0)
|
||||
goto address_err;
|
||||
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_READ ) < 0)
|
||||
goto device_rerr;
|
||||
__i2c_send_ack(); /* Master sends ACK for continue reading */
|
||||
while (cnt) {
|
||||
if (cnt == 1) {
|
||||
if (i2c_get_data(buf, 0) < 0)
|
||||
break;
|
||||
} else {
|
||||
if (i2c_get_data(buf, 1) < 0)
|
||||
break;
|
||||
}
|
||||
cnt--;
|
||||
buf++;
|
||||
}
|
||||
|
||||
__i2c_send_stop();
|
||||
return count - cnt;
|
||||
device_rerr:
|
||||
device_werr:
|
||||
address_err:
|
||||
timeout --;
|
||||
__i2c_send_stop();
|
||||
goto L_try_again;
|
||||
|
||||
L_timeout:
|
||||
__i2c_send_stop();
|
||||
printk("Read I2C device 0x%2x failed.\n", device);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int i2c_write_16(unsigned char device, unsigned char *buf,
|
||||
unsigned short address, int count)
|
||||
{
|
||||
int cnt = count;
|
||||
int cnt_in_pg;
|
||||
int timeout = 5;
|
||||
unsigned char *tmpbuf;
|
||||
unsigned char tmpaddrh, tmpaddrl;
|
||||
|
||||
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
|
||||
|
||||
W_try_again:
|
||||
if (timeout < 0)
|
||||
goto W_timeout;
|
||||
|
||||
cnt = count;
|
||||
tmpbuf = (unsigned char *)buf;
|
||||
tmpaddrh = (unsigned char)((address >> 8) & 0xff);
|
||||
tmpaddrl = (unsigned char)(address & 0xff);
|
||||
|
||||
start_write_page:
|
||||
cnt_in_pg = 0;
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
|
||||
goto device_err;
|
||||
if (i2c_put_data_nack(tmpaddrh) < 0)
|
||||
goto address_err;
|
||||
if (i2c_put_data(tmpaddrl) < 0)
|
||||
goto address_err;
|
||||
while (cnt) {
|
||||
if (++cnt_in_pg > 8) {
|
||||
__i2c_send_stop();
|
||||
mdelay(1);
|
||||
tmpaddrh += 8;
|
||||
goto start_write_page;
|
||||
}
|
||||
if (i2c_put_data(*tmpbuf) < 0)
|
||||
break;
|
||||
cnt--;
|
||||
tmpbuf++;
|
||||
}
|
||||
|
||||
__i2c_send_stop();
|
||||
return count - cnt;
|
||||
device_err:
|
||||
printk("1:Write I2C device 0x%2x failed.\n", device);
|
||||
address_err:
|
||||
printk("2:Write I2C address 0x%2x failed.\n", address);
|
||||
timeout--;
|
||||
__i2c_send_stop();
|
||||
goto W_try_again;
|
||||
|
||||
W_timeout:
|
||||
printk("3:Write I2C device 0x%2x failed.\n", device);
|
||||
__i2c_send_stop();
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(i2c_open);
|
||||
EXPORT_SYMBOL(i2c_close);
|
||||
EXPORT_SYMBOL(i2c_setclk);
|
||||
EXPORT_SYMBOL(i2c_read);
|
||||
EXPORT_SYMBOL(i2c_write);
|
||||
EXPORT_SYMBOL(i2c_read_16);
|
||||
EXPORT_SYMBOL(i2c_write_16);
|
||||
299
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/irq.c
Executable file
299
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/irq.c
Executable file
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4750d/irq.c
|
||||
*
|
||||
* JZ4750D interrupt routines.
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <lhhuang@ingenic.cn>
|
||||
*
|
||||
* 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/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/timex.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/*
|
||||
* INTC irq type
|
||||
*/
|
||||
|
||||
static void enable_intc_irq(unsigned int irq)
|
||||
{
|
||||
__intc_unmask_irq(irq);
|
||||
}
|
||||
|
||||
static void disable_intc_irq(unsigned int irq)
|
||||
{
|
||||
__intc_mask_irq(irq);
|
||||
}
|
||||
|
||||
static void mask_and_ack_intc_irq(unsigned int irq)
|
||||
{
|
||||
__intc_mask_irq(irq);
|
||||
__intc_ack_irq(irq);
|
||||
}
|
||||
|
||||
static void end_intc_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
|
||||
enable_intc_irq(irq);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int startup_intc_irq(unsigned int irq)
|
||||
{
|
||||
enable_intc_irq(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void shutdown_intc_irq(unsigned int irq)
|
||||
{
|
||||
disable_intc_irq(irq);
|
||||
}
|
||||
|
||||
static struct irq_chip intc_irq_type = {
|
||||
.typename = "INTC",
|
||||
.startup = startup_intc_irq,
|
||||
.shutdown = shutdown_intc_irq,
|
||||
.enable = enable_intc_irq,
|
||||
.disable = disable_intc_irq,
|
||||
.ack = mask_and_ack_intc_irq,
|
||||
.end = end_intc_irq,
|
||||
};
|
||||
|
||||
/*
|
||||
* GPIO irq type
|
||||
*/
|
||||
|
||||
static void enable_gpio_irq(unsigned int irq)
|
||||
{
|
||||
unsigned int intc_irq;
|
||||
|
||||
if (irq < (IRQ_GPIO_0 + 32)) {
|
||||
intc_irq = IRQ_GPIO0;
|
||||
}
|
||||
else if (irq < (IRQ_GPIO_0 + 64)) {
|
||||
intc_irq = IRQ_GPIO1;
|
||||
}
|
||||
else if (irq < (IRQ_GPIO_0 + 96)) {
|
||||
intc_irq = IRQ_GPIO2;
|
||||
}
|
||||
else if (irq < (IRQ_GPIO_0 + 128)) {
|
||||
intc_irq = IRQ_GPIO3;
|
||||
}
|
||||
else if (irq < (IRQ_GPIO_0 + 160)) {
|
||||
intc_irq = IRQ_GPIO4;
|
||||
}
|
||||
else {
|
||||
intc_irq = IRQ_GPIO5;
|
||||
}
|
||||
|
||||
enable_intc_irq(intc_irq);
|
||||
__gpio_unmask_irq(irq - IRQ_GPIO_0);
|
||||
}
|
||||
|
||||
static void disable_gpio_irq(unsigned int irq)
|
||||
{
|
||||
__gpio_mask_irq(irq - IRQ_GPIO_0);
|
||||
}
|
||||
|
||||
static void mask_and_ack_gpio_irq(unsigned int irq)
|
||||
{
|
||||
__gpio_mask_irq(irq - IRQ_GPIO_0);
|
||||
__gpio_ack_irq(irq - IRQ_GPIO_0);
|
||||
}
|
||||
|
||||
static void end_gpio_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
|
||||
enable_gpio_irq(irq);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int startup_gpio_irq(unsigned int irq)
|
||||
{
|
||||
enable_gpio_irq(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void shutdown_gpio_irq(unsigned int irq)
|
||||
{
|
||||
disable_gpio_irq(irq);
|
||||
}
|
||||
|
||||
static struct irq_chip gpio_irq_type = {
|
||||
.typename = "GPIO",
|
||||
.startup = startup_gpio_irq,
|
||||
.shutdown = shutdown_gpio_irq,
|
||||
.enable = enable_gpio_irq,
|
||||
.disable = disable_gpio_irq,
|
||||
.ack = mask_and_ack_gpio_irq,
|
||||
.end = end_gpio_irq,
|
||||
};
|
||||
|
||||
/*
|
||||
* DMA irq type
|
||||
*/
|
||||
|
||||
static void enable_dma_irq(unsigned int irq)
|
||||
{
|
||||
unsigned int intc_irq;
|
||||
|
||||
if ( irq < (IRQ_DMA_0 + HALF_DMA_NUM) ) /* DMAC Group 0 irq */
|
||||
intc_irq = IRQ_DMAC0;
|
||||
else if ( irq < (IRQ_DMA_0 + MAX_DMA_NUM) ) /* DMAC Group 1 irq */
|
||||
intc_irq = IRQ_DMAC1;
|
||||
else {
|
||||
printk("%s, unexpected dma irq #%d\n", __FILE__, irq);
|
||||
return;
|
||||
}
|
||||
__intc_unmask_irq(intc_irq);
|
||||
__dmac_channel_enable_irq(irq - IRQ_DMA_0);
|
||||
}
|
||||
|
||||
static void disable_dma_irq(unsigned int irq)
|
||||
{
|
||||
__dmac_channel_disable_irq(irq - IRQ_DMA_0);
|
||||
}
|
||||
|
||||
static void mask_and_ack_dma_irq(unsigned int irq)
|
||||
{
|
||||
unsigned int intc_irq;
|
||||
|
||||
if ( irq < (IRQ_DMA_0 + HALF_DMA_NUM) ) /* DMAC Group 0 irq */
|
||||
intc_irq = IRQ_DMAC0;
|
||||
else if ( irq < (IRQ_DMA_0 + MAX_DMA_NUM) ) /* DMAC Group 1 irq */
|
||||
intc_irq = IRQ_DMAC1;
|
||||
else {
|
||||
printk("%s, unexpected dma irq #%d\n", __FILE__, irq);
|
||||
return ;
|
||||
}
|
||||
__intc_ack_irq(intc_irq);
|
||||
__dmac_channel_ack_irq(irq-IRQ_DMA_0); /* needed?? add 20080506, Wolfgang */
|
||||
__dmac_channel_disable_irq(irq - IRQ_DMA_0);
|
||||
}
|
||||
|
||||
static void end_dma_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
|
||||
enable_dma_irq(irq);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int startup_dma_irq(unsigned int irq)
|
||||
{
|
||||
enable_dma_irq(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void shutdown_dma_irq(unsigned int irq)
|
||||
{
|
||||
disable_dma_irq(irq);
|
||||
}
|
||||
|
||||
static struct irq_chip dma_irq_type = {
|
||||
.typename = "DMA",
|
||||
.startup = startup_dma_irq,
|
||||
.shutdown = shutdown_dma_irq,
|
||||
.enable = enable_dma_irq,
|
||||
.disable = disable_dma_irq,
|
||||
.ack = mask_and_ack_dma_irq,
|
||||
.end = end_dma_irq,
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void __init arch_init_irq(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
clear_c0_status(0xff04); /* clear ERL */
|
||||
set_c0_status(0x0400); /* set IP2 */
|
||||
|
||||
/* Set up INTC irq
|
||||
*/
|
||||
for (i = 0; i < 32; i++) {
|
||||
disable_intc_irq(i);
|
||||
irq_desc[i].chip = &intc_irq_type;
|
||||
}
|
||||
|
||||
/* Set up DMAC irq
|
||||
*/
|
||||
for (i = 0; i < NUM_DMA; i++) {
|
||||
disable_dma_irq(IRQ_DMA_0 + i);
|
||||
irq_desc[IRQ_DMA_0 + i].chip = &dma_irq_type;
|
||||
}
|
||||
|
||||
/* Set up GPIO irq
|
||||
*/
|
||||
for (i = 0; i < NUM_GPIO; i++) {
|
||||
disable_gpio_irq(IRQ_GPIO_0 + i);
|
||||
irq_desc[IRQ_GPIO_0 + i].chip = &gpio_irq_type;
|
||||
}
|
||||
}
|
||||
|
||||
static int plat_real_irq(int irq)
|
||||
{
|
||||
switch (irq) {
|
||||
case IRQ_GPIO0:
|
||||
irq = __gpio_group_irq(0) + IRQ_GPIO_0;
|
||||
break;
|
||||
case IRQ_GPIO1:
|
||||
irq = __gpio_group_irq(1) + IRQ_GPIO_0 + 32;
|
||||
break;
|
||||
case IRQ_GPIO2:
|
||||
irq = __gpio_group_irq(2) + IRQ_GPIO_0 + 64;
|
||||
break;
|
||||
case IRQ_GPIO3:
|
||||
irq = __gpio_group_irq(3) + IRQ_GPIO_0 + 96;
|
||||
break;
|
||||
case IRQ_GPIO4:
|
||||
irq = __gpio_group_irq(4) + IRQ_GPIO_0 + 128;
|
||||
break;
|
||||
case IRQ_GPIO5:
|
||||
irq = __gpio_group_irq(5) + IRQ_GPIO_0 + 160;
|
||||
break;
|
||||
case IRQ_DMAC0:
|
||||
case IRQ_DMAC1:
|
||||
irq = __dmac_get_irq() + IRQ_DMA_0;
|
||||
break;
|
||||
}
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
asmlinkage void plat_irq_dispatch(void)
|
||||
{
|
||||
int irq = 0;
|
||||
static unsigned long intc_ipr = 0;
|
||||
|
||||
intc_ipr |= REG_INTC_IPR;
|
||||
|
||||
if (!intc_ipr) return;
|
||||
|
||||
irq = ffs(intc_ipr) - 1;
|
||||
intc_ipr &= ~(1<<irq);
|
||||
|
||||
irq = plat_real_irq(irq);
|
||||
do_IRQ(irq);
|
||||
}
|
||||
147
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/platform.c
Executable file
147
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/platform.c
Executable file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Platform device support for Jz4740 SoC.
|
||||
*
|
||||
* Copyright 2007, <yliu@ingenic.cn>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/resource.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
#if 0
|
||||
/* OHCI (USB full speed host controller) */
|
||||
static struct resource jz_usb_ohci_resources[] = {
|
||||
[0] = {
|
||||
.start = CPHYSADDR(UHC_BASE), // phys addr for ioremap
|
||||
.end = CPHYSADDR(UHC_BASE) + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_UHC,
|
||||
.end = IRQ_UHC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
/* The dmamask must be set for OHCI to work */
|
||||
static u64 ohci_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device jz_usb_ohci_device = {
|
||||
.name = "jz-ohci",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &ohci_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz_usb_ohci_resources),
|
||||
.resource = jz_usb_ohci_resources,
|
||||
};
|
||||
#endif
|
||||
/*** LCD controller ***/
|
||||
static struct resource jz_lcd_resources[] = {
|
||||
[0] = {
|
||||
.start = CPHYSADDR(LCD_BASE),
|
||||
.end = CPHYSADDR(LCD_BASE) + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_LCD,
|
||||
.end = IRQ_LCD,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
||||
static u64 jz_lcd_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device jz_lcd_device = {
|
||||
.name = "jz-lcd",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &jz_lcd_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz_lcd_resources),
|
||||
.resource = jz_lcd_resources,
|
||||
};
|
||||
|
||||
/* UDC (USB gadget controller) */
|
||||
static struct resource jz_usb_gdt_resources[] = {
|
||||
[0] = {
|
||||
.start = CPHYSADDR(UDC_BASE),
|
||||
.end = CPHYSADDR(UDC_BASE) + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_UDC,
|
||||
.end = IRQ_UDC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static u64 udc_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device jz_usb_gdt_device = {
|
||||
.name = "jz-udc",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &udc_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz_usb_gdt_resources),
|
||||
.resource = jz_usb_gdt_resources,
|
||||
};
|
||||
|
||||
/** MMC/SD controller **/
|
||||
static struct resource jz_mmc_resources[] = {
|
||||
[0] = {
|
||||
.start = CPHYSADDR(MSC_BASE),
|
||||
.end = CPHYSADDR(MSC_BASE) + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_MSC0,
|
||||
.end = IRQ_MSC0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
||||
static u64 jz_mmc_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device jz_mmc_device = {
|
||||
.name = "jz-mmc",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &jz_mmc_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz_mmc_resources),
|
||||
.resource = jz_mmc_resources,
|
||||
};
|
||||
|
||||
struct platform_device jz4750_rtc_device = {
|
||||
.name = "jz4750-rtc",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
/* All */
|
||||
static struct platform_device *jz_platform_devices[] __initdata = {
|
||||
// &jz_usb_ohci_device,
|
||||
&jz_lcd_device,
|
||||
&jz_usb_gdt_device,
|
||||
&jz_mmc_device,
|
||||
&jz4750_rtc_device,
|
||||
};
|
||||
|
||||
static int __init jz_platform_init(void)
|
||||
{
|
||||
return platform_add_devices(jz_platform_devices, ARRAY_SIZE(jz_platform_devices));
|
||||
}
|
||||
|
||||
arch_initcall(jz_platform_init);
|
||||
201
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/pm.c
Executable file
201
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/pm.c
Executable file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4750d/pm.c
|
||||
*
|
||||
* JZ4750D Power Management Routines
|
||||
*
|
||||
* Copyright (C) 2006 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can distribute it and/or modify it
|
||||
* under the terms of the GNU General Public License (Version 2) as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <asm/cacheops.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
#undef DEBUG
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
#define dprintk(x...) printk(x)
|
||||
#else
|
||||
#define dprintk(x...)
|
||||
#endif
|
||||
|
||||
extern void jz_board_do_sleep(unsigned long *ptr);
|
||||
extern void jz_board_do_resume(unsigned long *ptr);
|
||||
|
||||
|
||||
static void jz_pm_do_hibernate(void)
|
||||
{
|
||||
printk("Put CPU into hibernate mode.\n");
|
||||
|
||||
/* Mask all interrupts */
|
||||
REG_INTC_IMSR = 0xffffffff;
|
||||
|
||||
/*
|
||||
* RTC Wakeup or 1Hz interrupt can be enabled or disabled
|
||||
* through RTC driver's ioctl (linux/driver/char/rtc_jz.c).
|
||||
*/
|
||||
|
||||
/* Set minimum wakeup_n pin low-level assertion time for wakeup: 100ms */
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
REG_RTC_HWFCR = (100 << RTC_HWFCR_BIT);
|
||||
|
||||
/* Set reset pin low-level assertion time after wakeup: must > 60ms */
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
REG_RTC_HRCR = (60 << RTC_HRCR_BIT); /* 60 ms */
|
||||
|
||||
/* Scratch pad register to be reserved */
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
REG_RTC_HSPR = 0x12345678;
|
||||
|
||||
/* clear wakeup status register */
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
REG_RTC_HWRSR = 0x0;
|
||||
|
||||
/* Put CPU to power down mode */
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
REG_RTC_HCR = RTC_HCR_PD;
|
||||
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
while(1);
|
||||
|
||||
}
|
||||
|
||||
static int jz_pm_do_sleep(void)
|
||||
{
|
||||
unsigned long delta;
|
||||
unsigned long nfcsr = REG_EMC_NFCSR;
|
||||
unsigned long opcr = REG_CPM_OPCR;
|
||||
unsigned long imr = REG_INTC_IMR;
|
||||
unsigned long sadc = REG_SADC_ENA;
|
||||
unsigned long sleep_gpio_save[4*(GPIO_PORT_NUM-1)];
|
||||
|
||||
printk("Put CPU into sleep mode.\n");
|
||||
|
||||
/* Preserve current time */
|
||||
delta = xtime.tv_sec - REG_RTC_RSR;
|
||||
|
||||
/* Disable nand flash */
|
||||
REG_EMC_NFCSR = ~0xff;
|
||||
|
||||
/* stop sadc */
|
||||
REG_SADC_ENA &= ~0x7;
|
||||
while((REG_SADC_ENA & 0x7) != 0);
|
||||
udelay(100);
|
||||
|
||||
/*stop udc and usb*/
|
||||
__cpm_suspend_uhcphy();
|
||||
__cpm_suspend_udcphy();
|
||||
|
||||
/* Mask all interrupts */
|
||||
REG_INTC_IMSR = 0xffffffff;
|
||||
|
||||
/* Sleep on-board modules and setup wake event */
|
||||
jz_board_do_sleep(sleep_gpio_save);
|
||||
|
||||
/* disable externel clock Oscillator in sleep mode */
|
||||
__cpm_disable_osc_in_sleep();
|
||||
/* select 32K crystal as RTC clock in sleep mode */
|
||||
__cpm_select_rtcclk_rtc();
|
||||
|
||||
/* Enter SLEEP mode */
|
||||
REG_CPM_LCR &= ~CPM_LCR_LPM_MASK;
|
||||
REG_CPM_LCR |= CPM_LCR_LPM_SLEEP;
|
||||
__asm__(".set\tmips3\n\t"
|
||||
"wait\n\t"
|
||||
".set\tmips0");
|
||||
|
||||
/* Restore to IDLE mode */
|
||||
REG_CPM_LCR &= ~CPM_LCR_LPM_MASK;
|
||||
REG_CPM_LCR |= CPM_LCR_LPM_IDLE;
|
||||
|
||||
/* Restore nand flash control register */
|
||||
REG_EMC_NFCSR = nfcsr;
|
||||
|
||||
/* Restore interrupts */
|
||||
REG_INTC_IMSR = imr;
|
||||
REG_INTC_IMCR = ~imr;
|
||||
|
||||
/* Restore sadc */
|
||||
REG_SADC_ENA = sadc;
|
||||
|
||||
/* Resume on-board modules */
|
||||
jz_board_do_resume(sleep_gpio_save);
|
||||
|
||||
/* Restore Oscillator and Power Control Register */
|
||||
REG_CPM_OPCR = opcr;
|
||||
|
||||
/* Restore current time */
|
||||
xtime.tv_sec = REG_RTC_RSR + delta;
|
||||
|
||||
printk("Resume CPU from sleep mode.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Put CPU to HIBERNATE mode */
|
||||
void jz_pm_hibernate(void)
|
||||
{
|
||||
jz_pm_do_hibernate();
|
||||
}
|
||||
|
||||
|
||||
/* Put CPU to SLEEP mode */
|
||||
int jz_pm_sleep(void)
|
||||
{
|
||||
return jz_pm_do_sleep();
|
||||
}
|
||||
|
||||
/*
|
||||
* valid states, only support standby(sleep) and mem(hibernate)
|
||||
*/
|
||||
static int jz4750_pm_valid(suspend_state_t state)
|
||||
{
|
||||
return state == PM_SUSPEND_MEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Jz CPU enter save power mode
|
||||
*/
|
||||
static int jz4750_pm_enter(suspend_state_t state)
|
||||
{
|
||||
return jz_pm_do_sleep();
|
||||
}
|
||||
|
||||
static struct platform_suspend_ops jz4750_pm_ops = {
|
||||
.valid = jz4750_pm_valid,
|
||||
.enter = jz4750_pm_enter,
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize power interface
|
||||
*/
|
||||
int __init jz_pm_init(void)
|
||||
{
|
||||
printk("Power Management for JZ\n");
|
||||
|
||||
suspend_set_ops(&jz4750_pm_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
1056
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/proc.c
Executable file
1056
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/proc.c
Executable file
File diff suppressed because it is too large
Load Diff
198
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/prom.c
Executable file
198
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/prom.c
Executable file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
*
|
||||
* BRIEF MODULE DESCRIPTION
|
||||
* PROM library initialisation code, supports YAMON and U-Boot.
|
||||
*
|
||||
* Copyright 2000, 2001, 2006 MontaVista Software Inc.
|
||||
* Author: MontaVista Software, Inc.
|
||||
* ppopov@mvista.com or source@mvista.com
|
||||
*
|
||||
* This file was derived from Carsten Langgaard's
|
||||
* arch/mips/mips-boards/xx files.
|
||||
*
|
||||
* Carsten Langgaard, carstenl@mips.com
|
||||
* Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
|
||||
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* 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.,
|
||||
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/* #define DEBUG_CMDLINE */
|
||||
|
||||
int prom_argc;
|
||||
char **prom_argv, **prom_envp;
|
||||
|
||||
char * prom_getcmdline(void)
|
||||
{
|
||||
return &(arcs_cmdline[0]);
|
||||
}
|
||||
|
||||
void prom_init_cmdline(void)
|
||||
{
|
||||
char *cp;
|
||||
int actr;
|
||||
|
||||
actr = 1; /* Always ignore argv[0] */
|
||||
|
||||
cp = &(arcs_cmdline[0]);
|
||||
while(actr < prom_argc) {
|
||||
strcpy(cp, prom_argv[actr]);
|
||||
cp += strlen(prom_argv[actr]);
|
||||
*cp++ = ' ';
|
||||
actr++;
|
||||
}
|
||||
if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
|
||||
--cp;
|
||||
if (prom_argc > 1)
|
||||
*cp = '\0';
|
||||
|
||||
}
|
||||
|
||||
|
||||
char *prom_getenv(char *envname)
|
||||
{
|
||||
#if 0
|
||||
/*
|
||||
* Return a pointer to the given environment variable.
|
||||
* YAMON uses "name", "value" pairs, while U-Boot uses "name=value".
|
||||
*/
|
||||
|
||||
char **env = prom_envp;
|
||||
int i = strlen(envname);
|
||||
int yamon = (*env && strchr(*env, '=') == NULL);
|
||||
|
||||
while (*env) {
|
||||
if (yamon) {
|
||||
if (strcmp(envname, *env++) == 0)
|
||||
return *env;
|
||||
} else {
|
||||
if (strncmp(envname, *env, i) == 0 && (*env)[i] == '=')
|
||||
return *env + i + 1;
|
||||
}
|
||||
env++;
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline unsigned char str2hexnum(unsigned char c)
|
||||
{
|
||||
if(c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
if(c >= 'a' && c <= 'f')
|
||||
return c - 'a' + 10;
|
||||
if(c >= 'A' && c <= 'F')
|
||||
return c - 'A' + 10;
|
||||
return 0; /* foo */
|
||||
}
|
||||
|
||||
inline void str2eaddr(unsigned char *ea, unsigned char *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 6; i++) {
|
||||
unsigned char num;
|
||||
|
||||
if((*str == '.') || (*str == ':'))
|
||||
str++;
|
||||
num = str2hexnum(*str++) << 4;
|
||||
num |= (str2hexnum(*str++));
|
||||
ea[i] = num;
|
||||
}
|
||||
}
|
||||
|
||||
int get_ethernet_addr(char *ethernet_addr)
|
||||
{
|
||||
char *ethaddr_str;
|
||||
|
||||
ethaddr_str = prom_getenv("ethaddr");
|
||||
if (!ethaddr_str) {
|
||||
printk("ethaddr not set in boot prom\n");
|
||||
return -1;
|
||||
}
|
||||
str2eaddr(ethernet_addr, ethaddr_str);
|
||||
|
||||
#if 0
|
||||
{
|
||||
int i;
|
||||
|
||||
printk("get_ethernet_addr: ");
|
||||
for (i=0; i<5; i++)
|
||||
printk("%02x:", (unsigned char)*(ethernet_addr+i));
|
||||
printk("%02x\n", *(ethernet_addr+i));
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init prom_free_prom_memory(void)
|
||||
{
|
||||
}
|
||||
|
||||
void __init prom_init(void)
|
||||
{
|
||||
unsigned char *memsize_str;
|
||||
unsigned long memsize;
|
||||
|
||||
prom_argc = (int) fw_arg0;
|
||||
prom_argv = (char **) fw_arg1;
|
||||
prom_envp = (char **) fw_arg2;
|
||||
|
||||
mips_machtype = MACH_INGENIC_JZ4750D;
|
||||
|
||||
prom_init_cmdline();
|
||||
memsize_str = prom_getenv("memsize");
|
||||
if (!memsize_str) {
|
||||
memsize = 0x04000000;
|
||||
} else {
|
||||
memsize = simple_strtol(memsize_str, NULL, 0);
|
||||
}
|
||||
add_memory_region(0, memsize, BOOT_MEM_RAM);
|
||||
}
|
||||
|
||||
/* used by early printk */
|
||||
void prom_putchar(char c)
|
||||
{
|
||||
volatile u8 *uart_lsr = (volatile u8 *)(UART1_BASE + OFF_LSR);
|
||||
volatile u8 *uart_tdr = (volatile u8 *)(UART1_BASE + OFF_TDR);
|
||||
|
||||
/* Wait for fifo to shift out some bytes */
|
||||
while ( !((*uart_lsr & (UARTLSR_TDRQ | UARTLSR_TEMT)) == 0x60) );
|
||||
|
||||
*uart_tdr = (u8)c;
|
||||
}
|
||||
|
||||
const char *get_system_type(void)
|
||||
{
|
||||
return "JZ4750D";
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(prom_getcmdline);
|
||||
EXPORT_SYMBOL(get_ethernet_addr);
|
||||
EXPORT_SYMBOL(str2eaddr);
|
||||
46
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/reset.c
Executable file
46
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/reset.c
Executable file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4750/reset.c
|
||||
*
|
||||
* JZ4750 reset routines.
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <yliu@ingenic.cn>
|
||||
*
|
||||
* 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/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/reboot.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
void jz_restart(char *command)
|
||||
{
|
||||
printk("Restarting after 4 ms\n");
|
||||
REG_WDT_TCSR = WDT_TCSR_PRESCALE4 | WDT_TCSR_EXT_EN;
|
||||
REG_WDT_TCNT = 0;
|
||||
REG_WDT_TDR = JZ_EXTAL/1000; /* reset after 4ms */
|
||||
REG_TCU_TSCR = TCU_TSCR_WDTSC; /* enable wdt clock */
|
||||
REG_WDT_TCER = WDT_TCER_TCEN; /* wdt start */
|
||||
while (1);
|
||||
}
|
||||
|
||||
void jz_halt(void)
|
||||
{
|
||||
printk(KERN_NOTICE "\n** You can safely turn off the power\n");
|
||||
|
||||
while (1)
|
||||
__asm__(".set\tmips3\n\t"
|
||||
"wait\n\t"
|
||||
".set\tmips0");
|
||||
}
|
||||
|
||||
void jz_power_off(void)
|
||||
{
|
||||
jz_halt();
|
||||
}
|
||||
207
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/setup.c
Executable file
207
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/setup.c
Executable file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4750d/common/setup.c
|
||||
*
|
||||
* JZ4750D common setup routines.
|
||||
*
|
||||
* Copyright (C) 2006 Ingenic Semiconductor Inc.
|
||||
*
|
||||
* This program is free software; you can distribute it and/or modify it
|
||||
* under the terms of the GNU General Public License (Version 2) as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_8250.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/reboot.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#include <asm/suspend.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PC_KEYB
|
||||
#include <asm/keyboard.h>
|
||||
#endif
|
||||
|
||||
jz_clocks_t jz_clocks;
|
||||
|
||||
extern char * __init prom_getcmdline(void);
|
||||
extern void __init jz_board_setup(void);
|
||||
extern void jz_restart(char *);
|
||||
extern void jz_halt(void);
|
||||
extern void jz_power_off(void);
|
||||
extern void jz_time_init(void);
|
||||
extern void jz_pm_hibernate(void);
|
||||
|
||||
static void __init sysclocks_setup(void)
|
||||
{
|
||||
#ifndef CONFIG_MIPS_JZ_EMURUS /* FPGA */
|
||||
jz_clocks.cclk = __cpm_get_cclk();
|
||||
jz_clocks.hclk = __cpm_get_hclk();
|
||||
jz_clocks.pclk = __cpm_get_pclk();
|
||||
jz_clocks.mclk = __cpm_get_mclk();
|
||||
jz_clocks.h1clk = __cpm_get_h1clk();
|
||||
jz_clocks.pixclk = __cpm_get_pixclk();
|
||||
jz_clocks.i2sclk = __cpm_get_i2sclk();
|
||||
jz_clocks.usbclk = __cpm_get_usbclk();
|
||||
jz_clocks.mscclk = __cpm_get_mscclk(0);
|
||||
jz_clocks.extalclk = __cpm_get_extalclk();
|
||||
jz_clocks.rtcclk = __cpm_get_rtcclk();
|
||||
#else
|
||||
|
||||
#define FPGACLK 8000000
|
||||
|
||||
jz_clocks.cclk = FPGACLK;
|
||||
jz_clocks.hclk = FPGACLK;
|
||||
jz_clocks.pclk = FPGACLK;
|
||||
jz_clocks.mclk = FPGACLK;
|
||||
jz_clocks.h1clk = FPGACLK;
|
||||
jz_clocks.pixclk = FPGACLK;
|
||||
jz_clocks.i2sclk = FPGACLK;
|
||||
jz_clocks.usbclk = FPGACLK;
|
||||
jz_clocks.mscclk = FPGACLK;
|
||||
jz_clocks.extalclk = FPGACLK;
|
||||
jz_clocks.rtcclk = FPGACLK;
|
||||
#endif
|
||||
|
||||
printk("CPU clock: %dMHz, System clock: %dMHz, Peripheral clock: %dMHz, Memory clock: %dMHz\n",
|
||||
(jz_clocks.cclk + 500000) / 1000000,
|
||||
(jz_clocks.hclk + 500000) / 1000000,
|
||||
(jz_clocks.pclk + 500000) / 1000000,
|
||||
(jz_clocks.mclk + 500000) / 1000000);
|
||||
}
|
||||
|
||||
static void __init soc_cpm_setup(void)
|
||||
{
|
||||
/* Start all module clocks
|
||||
*/
|
||||
__cpm_start_all();
|
||||
|
||||
/* Enable CKO to external memory */
|
||||
__cpm_enable_cko();
|
||||
|
||||
/* CPU enters IDLE mode when executing 'wait' instruction */
|
||||
__cpm_idle_mode();
|
||||
|
||||
/* Setup system clocks */
|
||||
sysclocks_setup();
|
||||
}
|
||||
|
||||
static void __init soc_harb_setup(void)
|
||||
{
|
||||
// __harb_set_priority(0x00); /* CIM>LCD>DMA>ETH>PCI>USB>CBB */
|
||||
// __harb_set_priority(0x03); /* LCD>CIM>DMA>ETH>PCI>USB>CBB */
|
||||
// __harb_set_priority(0x0a); /* ETH>LCD>CIM>DMA>PCI>USB>CBB */
|
||||
}
|
||||
|
||||
static void __init soc_emc_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void __init soc_dmac_setup(void)
|
||||
{
|
||||
__dmac_enable_module(0);
|
||||
__dmac_enable_module(1);
|
||||
}
|
||||
|
||||
static void __init jz_soc_setup(void)
|
||||
{
|
||||
soc_cpm_setup();
|
||||
soc_harb_setup();
|
||||
soc_emc_setup();
|
||||
soc_dmac_setup();
|
||||
}
|
||||
|
||||
static void __init jz_serial_setup(void)
|
||||
{
|
||||
#ifdef CONFIG_SERIAL_8250
|
||||
struct uart_port s;
|
||||
REG8(UART0_FCR) |= UARTFCR_UUE; /* enable UART module */
|
||||
memset(&s, 0, sizeof(s));
|
||||
s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
|
||||
s.iotype = SERIAL_IO_MEM;
|
||||
s.regshift = 2;
|
||||
s.uartclk = jz_clocks.extalclk ;
|
||||
|
||||
s.line = 0;
|
||||
s.membase = (u8 *)UART0_BASE;
|
||||
s.irq = IRQ_UART0;
|
||||
if (early_serial_setup(&s) != 0) {
|
||||
printk(KERN_ERR "Serial ttyS0 setup failed!\n");
|
||||
}
|
||||
|
||||
s.line = 1;
|
||||
s.membase = (u8 *)UART1_BASE;
|
||||
s.irq = IRQ_UART1;
|
||||
if (early_serial_setup(&s) != 0) {
|
||||
printk(KERN_ERR "Serial ttyS1 setup failed!\n");
|
||||
}
|
||||
|
||||
s.line = 2;
|
||||
s.membase = (u8 *)UART2_BASE;
|
||||
s.irq = IRQ_UART2;
|
||||
|
||||
if (early_serial_setup(&s) != 0) {
|
||||
printk(KERN_ERR "Serial ttyS2 setup failed!\n");
|
||||
}
|
||||
/*
|
||||
s.line = 3;
|
||||
s.membase = (u8 *)UART3_BASE;
|
||||
s.irq = IRQ_UART3;
|
||||
if (early_serial_setup(&s) != 0) {
|
||||
printk(KERN_ERR "Serial ttyS3 setup failed!\n");
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
|
||||
void __init plat_mem_setup(void)
|
||||
{
|
||||
char *argptr;
|
||||
|
||||
argptr = prom_getcmdline();
|
||||
|
||||
/* IO/MEM resources. Which will be the addtion value in `inX' and
|
||||
* `outX' macros defined in asm/io.h */
|
||||
set_io_port_base(0);
|
||||
ioport_resource.start = 0x00000000;
|
||||
ioport_resource.end = 0xffffffff;
|
||||
iomem_resource.start = 0x00000000;
|
||||
iomem_resource.end = 0xffffffff;
|
||||
|
||||
_machine_restart = jz_restart;
|
||||
_machine_halt = jz_halt;
|
||||
pm_power_off = jz_pm_hibernate;
|
||||
|
||||
jz_soc_setup();
|
||||
jz_serial_setup();
|
||||
jz_board_setup();
|
||||
#ifdef CONFIG_PM
|
||||
jz_pm_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
157
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/time.c
Executable file
157
target/linux/xburst/files-2.6.27/arch/mips/jz4750d/time.c
Executable file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4750d/time.c
|
||||
*
|
||||
* Setting up the clock on the JZ4750D boards.
|
||||
*
|
||||
* Copyright (C) 2008 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can distribute it and/or modify it
|
||||
* under the terms of the GNU General Public License (Version 2) as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/clockchips.h>
|
||||
|
||||
#include <asm/time.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/* This is for machines which generate the exact clock. */
|
||||
|
||||
#define JZ_TIMER_IRQ IRQ_TCU0
|
||||
|
||||
#define JZ_TIMER_CLOCK (JZ_EXTAL>>4) /* Jz timer clock frequency */
|
||||
|
||||
static struct clocksource clocksource_jz; /* Jz clock source */
|
||||
static struct clock_event_device jz_clockevent_device; /* Jz clock event */
|
||||
|
||||
void (*jz_timer_callback)(void);
|
||||
|
||||
static irqreturn_t jz_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct clock_event_device *cd = dev_id;
|
||||
|
||||
REG_TCU_TFCR = TCU_TFCR_OSTFCL; /* ACK timer */
|
||||
|
||||
if (jz_timer_callback)
|
||||
jz_timer_callback();
|
||||
|
||||
cd->event_handler(cd);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct irqaction jz_irqaction = {
|
||||
.handler = jz_timer_interrupt,
|
||||
.flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER,
|
||||
.name = "jz-timerirq",
|
||||
};
|
||||
|
||||
|
||||
cycle_t jz_get_cycles(void)
|
||||
{
|
||||
/* convert jiffes to jz timer cycles */
|
||||
return (cycle_t)( jiffies*((JZ_TIMER_CLOCK)/HZ) + REG_TCU_OSTCNT);
|
||||
}
|
||||
|
||||
static struct clocksource clocksource_jz = {
|
||||
.name = "jz_clocksource",
|
||||
.rating = 300,
|
||||
.read = jz_get_cycles,
|
||||
.mask = 0xFFFFFFFF,
|
||||
.shift = 10,
|
||||
.flags = CLOCK_SOURCE_WATCHDOG,
|
||||
};
|
||||
|
||||
static int __init jz_clocksource_init(void)
|
||||
{
|
||||
clocksource_jz.mult = clocksource_hz2mult(JZ_TIMER_CLOCK, clocksource_jz.shift);
|
||||
clocksource_register(&clocksource_jz);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jz_set_next_event(unsigned long evt,
|
||||
struct clock_event_device *unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void jz_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
break;
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct clock_event_device jz_clockevent_device = {
|
||||
.name = "jz-clockenvent",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC,
|
||||
// .features = CLOCK_EVT_FEAT_ONESHOT, /* Jz4740 not support dynamic clock now */
|
||||
|
||||
/* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */
|
||||
.mult = 1,
|
||||
.rating = 300,
|
||||
.irq = JZ_TIMER_IRQ,
|
||||
.set_mode = jz_set_mode,
|
||||
.set_next_event = jz_set_next_event,
|
||||
};
|
||||
|
||||
static void __init jz_clockevent_init(void)
|
||||
{
|
||||
struct clock_event_device *cd = &jz_clockevent_device;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
cd->cpumask = cpumask_of_cpu(cpu);
|
||||
clockevents_register_device(cd);
|
||||
}
|
||||
|
||||
static void __init jz_timer_setup(void)
|
||||
{
|
||||
jz_clocksource_init(); /* init jz clock source */
|
||||
jz_clockevent_init(); /* init jz clock event */
|
||||
|
||||
/*
|
||||
* Make irqs happen for the system timer
|
||||
*/
|
||||
jz_irqaction.dev_id = &jz_clockevent_device;
|
||||
setup_irq(JZ_TIMER_IRQ, &jz_irqaction);
|
||||
}
|
||||
|
||||
|
||||
void __init plat_time_init(void)
|
||||
{
|
||||
unsigned int latch;
|
||||
|
||||
/* Init timer */
|
||||
latch = (JZ_TIMER_CLOCK + (HZ>>1)) / HZ;
|
||||
|
||||
REG_TCU_OSTCSR = TCU_OSTCSR_PRESCALE16 | TCU_OSTCSR_EXT_EN;
|
||||
REG_TCU_OSTCNT = 0;
|
||||
REG_TCU_OSTDR = latch;
|
||||
|
||||
REG_TCU_TMCR = TCU_TMCR_OSTMCL; /* unmask match irq */
|
||||
REG_TCU_TSCR = TCU_TSCR_OSTSC; /* enable timer clock */
|
||||
REG_TCU_TESR = TCU_TESR_OSTST; /* start counting up */
|
||||
|
||||
jz_timer_setup();
|
||||
}
|
||||
22
target/linux/xburst/files-2.6.27/arch/mips/jz4760/Makefile
Normal file
22
target/linux/xburst/files-2.6.27/arch/mips/jz4760/Makefile
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Makefile for the Ingenic JZ4760.
|
||||
#
|
||||
|
||||
# Object file lists.
|
||||
|
||||
obj-y += prom.o irq.o time.o reset.o setup.o dma.o \
|
||||
platform.o i2c.o
|
||||
|
||||
obj-$(CONFIG_PROC_FS) += proc.o
|
||||
|
||||
# board specific support
|
||||
|
||||
obj-$(CONFIG_JZ4760_F4760) += board-f4760.o
|
||||
|
||||
# PM support
|
||||
|
||||
obj-$(CONFIG_PM_LEGACY) +=pm.o
|
||||
|
||||
# CPU Frequency scaling support
|
||||
|
||||
obj-$(CONFIG_CPU_FREQ_JZ) +=cpufreq.o
|
||||
81
target/linux/xburst/files-2.6.27/arch/mips/jz4760/board-f4760.c
Executable file
81
target/linux/xburst/files-2.6.27/arch/mips/jz4760/board-f4760.c
Executable file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4760/board-f4760.c
|
||||
*
|
||||
* JZ4760 F4760 board setup routines.
|
||||
*
|
||||
* Copyright (c) 2006-2008 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/reboot.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
extern void (*jz_timer_callback)(void);
|
||||
|
||||
static void dancing(void)
|
||||
{
|
||||
static unsigned char slash[] = "\\|/-";
|
||||
// static volatile unsigned char *p = (unsigned char *)0xb6000058;
|
||||
static volatile unsigned char *p = (unsigned char *)0xb6000016;
|
||||
static unsigned int count = 0;
|
||||
*p = slash[count++];
|
||||
count &= 3;
|
||||
}
|
||||
|
||||
static void f4760_timer_callback(void)
|
||||
{
|
||||
static unsigned long count = 0;
|
||||
|
||||
if ((++count) % 50 == 0) {
|
||||
dancing();
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init board_cpm_setup(void)
|
||||
{
|
||||
/* Stop unused module clocks here.
|
||||
* We have started all module clocks at arch/mips/jz4760/setup.c.
|
||||
*/
|
||||
}
|
||||
|
||||
static void __init board_gpio_setup(void)
|
||||
{
|
||||
/*
|
||||
* Initialize SDRAM pins
|
||||
*/
|
||||
}
|
||||
|
||||
void __init jz_board_setup(void)
|
||||
{
|
||||
printk("JZ4760 F4760 board setup\n");
|
||||
// jz_restart(NULL);
|
||||
board_cpm_setup();
|
||||
board_gpio_setup();
|
||||
|
||||
jz_timer_callback = f4760_timer_callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by arch/mips/kernel/proc.c when 'cat /proc/cpuinfo'.
|
||||
* Android requires the 'Hardware:' field in cpuinfo to setup the init.%hardware%.rc.
|
||||
*/
|
||||
const char *get_board_type(void)
|
||||
{
|
||||
return "f4760";
|
||||
}
|
||||
598
target/linux/xburst/files-2.6.27/arch/mips/jz4760/cpufreq.c
Executable file
598
target/linux/xburst/files-2.6.27/arch/mips/jz4760/cpufreq.c
Executable file
@@ -0,0 +1,598 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4760/cpufreq.c
|
||||
*
|
||||
* cpufreq driver for JZ4760
|
||||
*
|
||||
* Copyright (c) 2006-2008 Ingenic Semiconductor Inc.
|
||||
* Author: <lhhuang@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <linux/cpufreq.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
|
||||
"cpufreq-jz4760", msg)
|
||||
|
||||
#undef CHANGE_PLL
|
||||
|
||||
#define PLL_UNCHANGED 0
|
||||
#define PLL_GOES_UP 1
|
||||
#define PLL_GOES_DOWN 2
|
||||
|
||||
#define PLL_WAIT_500NS (500*(__cpm_get_cclk()/1000000000))
|
||||
|
||||
/* Saved the boot-time parameters */
|
||||
static struct {
|
||||
/* SDRAM parameters */
|
||||
unsigned int mclk; /* memory clock, KHz */
|
||||
unsigned int tras; /* RAS pulse width, cycles of mclk */
|
||||
unsigned int rcd; /* RAS to CAS Delay, cycles of mclk */
|
||||
unsigned int tpc; /* RAS Precharge time, cycles of mclk */
|
||||
unsigned int trwl; /* Write Precharge Time, cycles of mclk */
|
||||
unsigned int trc; /* RAS Cycle Time, cycles of mclk */
|
||||
unsigned int rtcor; /* Refresh Time Constant */
|
||||
unsigned int sdram_initialized;
|
||||
|
||||
/* LCD parameters */
|
||||
unsigned int lcdpix_clk; /* LCD Pixel clock, Hz */
|
||||
unsigned int lcd_clks_initialized;
|
||||
} boot_config;
|
||||
|
||||
struct jz4760_freq_percpu_info {
|
||||
struct cpufreq_frequency_table table[7];
|
||||
};
|
||||
|
||||
static struct jz4760_freq_percpu_info jz4760_freq_table;
|
||||
|
||||
/*
|
||||
* This contains the registers value for an operating point.
|
||||
* If only part of a register needs to change then there is
|
||||
* a mask value for that register.
|
||||
* When going to a new operating point the current register
|
||||
* value is ANDed with the ~mask and ORed with the new value.
|
||||
*/
|
||||
struct dpm_regs {
|
||||
u32 cpccr; /* Clock Freq Control Register */
|
||||
u32 cpccr_mask; /* Clock Freq Control Register mask */
|
||||
u32 cppcr; /* PLL1 Control Register */
|
||||
u32 cppcr_mask; /* PLL1 Control Register mask */
|
||||
u32 pll_up_flag; /* New PLL freq is higher than current or not */
|
||||
};
|
||||
|
||||
extern jz_clocks_t jz_clocks;
|
||||
|
||||
static void jz_update_clocks(void)
|
||||
{
|
||||
/* Next clocks must be updated if we have changed
|
||||
* the PLL or divisors.
|
||||
*/
|
||||
jz_clocks.cclk = __cpm_get_cclk();
|
||||
jz_clocks.hclk = __cpm_get_hclk();
|
||||
jz_clocks.mclk = __cpm_get_mclk();
|
||||
jz_clocks.pclk = __cpm_get_pclk();
|
||||
jz_clocks.pixclk = __cpm_get_pixclk();
|
||||
jz_clocks.i2sclk = __cpm_get_i2sclk();
|
||||
jz_clocks.usbclk = __cpm_get_usbclk();
|
||||
jz_clocks.mscclk = __cpm_get_mscclk(0);
|
||||
}
|
||||
|
||||
static void
|
||||
jz_init_boot_config(void)
|
||||
{
|
||||
if (!boot_config.lcd_clks_initialized) {
|
||||
/* the first time to scale pll */
|
||||
boot_config.lcdpix_clk = __cpm_get_pixclk();
|
||||
boot_config.lcd_clks_initialized = 1;
|
||||
}
|
||||
|
||||
if (!boot_config.sdram_initialized) {
|
||||
/* the first time to scale frequencies */
|
||||
unsigned int dmcr, rtcor;
|
||||
unsigned int tras, rcd, tpc, trwl, trc;
|
||||
|
||||
dmcr = REG_EMC_DMCR;
|
||||
rtcor = REG_EMC_RTCOR;
|
||||
|
||||
tras = (dmcr >> 13) & 0x7;
|
||||
rcd = (dmcr >> 11) & 0x3;
|
||||
tpc = (dmcr >> 8) & 0x7;
|
||||
trwl = (dmcr >> 5) & 0x3;
|
||||
trc = (dmcr >> 2) & 0x7;
|
||||
|
||||
boot_config.mclk = __cpm_get_mclk() / 1000;
|
||||
boot_config.tras = tras + 4;
|
||||
boot_config.rcd = rcd + 1;
|
||||
boot_config.tpc = tpc + 1;
|
||||
boot_config.trwl = trwl + 1;
|
||||
boot_config.trc = trc * 2 + 1;
|
||||
boot_config.rtcor = rtcor;
|
||||
|
||||
boot_config.sdram_initialized = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void jz_update_dram_rtcor(unsigned int new_mclk)
|
||||
{
|
||||
unsigned int rtcor;
|
||||
|
||||
new_mclk /= 1000;
|
||||
rtcor = boot_config.rtcor * new_mclk / boot_config.mclk;
|
||||
rtcor--;
|
||||
|
||||
if (rtcor < 1) rtcor = 1;
|
||||
if (rtcor > 255) rtcor = 255;
|
||||
|
||||
REG_EMC_RTCOR = rtcor;
|
||||
REG_EMC_RTCNT = rtcor;
|
||||
}
|
||||
|
||||
static void jz_update_dram_dmcr(unsigned int new_mclk)
|
||||
{
|
||||
unsigned int dmcr;
|
||||
unsigned int tras, rcd, tpc, trwl, trc;
|
||||
unsigned int valid_time, new_time; /* ns */
|
||||
|
||||
new_mclk /= 1000;
|
||||
tras = boot_config.tras * new_mclk / boot_config.mclk;
|
||||
rcd = boot_config.rcd * new_mclk / boot_config.mclk;
|
||||
tpc = boot_config.tpc * new_mclk / boot_config.mclk;
|
||||
trwl = boot_config.trwl * new_mclk / boot_config.mclk;
|
||||
trc = boot_config.trc * new_mclk / boot_config.mclk;
|
||||
|
||||
/* Validation checking */
|
||||
valid_time = (boot_config.tras * 1000000) / boot_config.mclk;
|
||||
new_time = (tras * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) tras += 1;
|
||||
|
||||
valid_time = (boot_config.rcd * 1000000) / boot_config.mclk;
|
||||
new_time = (rcd * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) rcd += 1;
|
||||
|
||||
valid_time = (boot_config.tpc * 1000000) / boot_config.mclk;
|
||||
new_time = (tpc * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) tpc += 1;
|
||||
|
||||
valid_time = (boot_config.trwl * 1000000) / boot_config.mclk;
|
||||
new_time = (trwl * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) trwl += 1;
|
||||
|
||||
valid_time = (boot_config.trc * 1000000) / boot_config.mclk;
|
||||
new_time = (trc * 1000000) / new_mclk;
|
||||
if (new_time < valid_time) trc += 2;
|
||||
|
||||
tras = (tras < 4) ? 4: tras;
|
||||
tras = (tras > 11) ? 11: tras;
|
||||
tras -= 4;
|
||||
|
||||
rcd = (rcd < 1) ? 1: rcd;
|
||||
rcd = (rcd > 4) ? 4: rcd;
|
||||
rcd -= 1;
|
||||
|
||||
tpc = (tpc < 1) ? 1: tpc;
|
||||
tpc = (tpc > 8) ? 8: tpc;
|
||||
tpc -= 1;
|
||||
|
||||
trwl = (trwl < 1) ? 1: trwl;
|
||||
trwl = (trwl > 4) ? 4: trwl;
|
||||
trwl -= 1;
|
||||
|
||||
trc = (trc < 1) ? 1: trc;
|
||||
trc = (trc > 15) ? 15: trc;
|
||||
trc /= 2;
|
||||
|
||||
dmcr = REG_EMC_DMCR;
|
||||
|
||||
dmcr &= ~(EMC_DMCR_TRAS_MASK | EMC_DMCR_RCD_MASK | EMC_DMCR_TPC_MASK | EMC_DMCR_TRWL_MASK | EMC_DMCR_TRC_MASK);
|
||||
dmcr |= ((tras << EMC_DMCR_TRAS_BIT) | (rcd << EMC_DMCR_RCD_BIT) | (tpc << EMC_DMCR_TPC_BIT) | (trwl << EMC_DMCR_TRWL_BIT) | (trc << EMC_DMCR_TRC_BIT));
|
||||
|
||||
REG_EMC_DMCR = dmcr;
|
||||
}
|
||||
|
||||
static void jz_update_dram_prev(unsigned int cur_mclk, unsigned int new_mclk)
|
||||
{
|
||||
/* No risk, no fun: run with interrupts on! */
|
||||
if (new_mclk > cur_mclk) {
|
||||
/* We're going FASTER, so first update TRAS, RCD, TPC, TRWL
|
||||
* and TRC of DMCR before changing the frequency.
|
||||
*/
|
||||
jz_update_dram_dmcr(new_mclk);
|
||||
} else {
|
||||
/* We're going SLOWER: first update RTCOR value
|
||||
* before changing the frequency.
|
||||
*/
|
||||
jz_update_dram_rtcor(new_mclk);
|
||||
}
|
||||
}
|
||||
|
||||
static void jz_update_dram_post(unsigned int cur_mclk, unsigned int new_mclk)
|
||||
{
|
||||
/* No risk, no fun: run with interrupts on! */
|
||||
if (new_mclk > cur_mclk) {
|
||||
/* We're going FASTER, so update RTCOR
|
||||
* after changing the frequency
|
||||
*/
|
||||
jz_update_dram_rtcor(new_mclk);
|
||||
} else {
|
||||
/* We're going SLOWER: so update TRAS, RCD, TPC, TRWL
|
||||
* and TRC of DMCR after changing the frequency.
|
||||
*/
|
||||
jz_update_dram_dmcr(new_mclk);
|
||||
}
|
||||
}
|
||||
|
||||
static void jz_scale_divisors(struct dpm_regs *regs)
|
||||
{
|
||||
unsigned int cpccr;
|
||||
unsigned int cur_mclk, new_mclk;
|
||||
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
|
||||
unsigned int tmp = 0, wait = PLL_WAIT_500NS;
|
||||
|
||||
cpccr = REG_CPM_CPCCR;
|
||||
cpccr &= ~((unsigned long)regs->cpccr_mask);
|
||||
cpccr |= regs->cpccr;
|
||||
cpccr |= CPM_CPCCR_CE; /* update immediately */
|
||||
|
||||
cur_mclk = __cpm_get_mclk();
|
||||
new_mclk = __cpm_get_pllout() / div[(cpccr & CPM_CPCCR_MDIV_MASK) >> CPM_CPCCR_MDIV_BIT];
|
||||
|
||||
/* Update some DRAM parameters before changing frequency */
|
||||
jz_update_dram_prev(cur_mclk, new_mclk);
|
||||
|
||||
/* update register to change the clocks.
|
||||
* align this code to a cache line.
|
||||
*/
|
||||
__asm__ __volatile__(
|
||||
".set noreorder\n\t"
|
||||
".align 5\n"
|
||||
"sw %1,0(%0)\n\t"
|
||||
"li %3,0\n\t"
|
||||
"1:\n\t"
|
||||
"bne %3,%2,1b\n\t"
|
||||
"addi %3, 1\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
".set reorder\n\t"
|
||||
:
|
||||
: "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp));
|
||||
|
||||
/* Update some other DRAM parameters after changing frequency */
|
||||
jz_update_dram_post(cur_mclk, new_mclk);
|
||||
}
|
||||
|
||||
#ifdef CHANGE_PLL
|
||||
/* Maintain the LCD clock and pixel clock */
|
||||
static void jz_scale_lcd_divisors(struct dpm_regs *regs)
|
||||
{
|
||||
unsigned int new_pll, new_lcd_div, new_lcdpix_div;
|
||||
unsigned int cpccr;
|
||||
unsigned int tmp = 0, wait = PLL_WAIT_500NS;
|
||||
|
||||
if (!boot_config.lcd_clks_initialized) return;
|
||||
|
||||
new_pll = __cpm_get_pllout();
|
||||
new_lcd_div = new_pll / boot_config.lcd_clk;
|
||||
new_lcdpix_div = new_pll / boot_config.lcdpix_clk;
|
||||
|
||||
if (new_lcd_div < 1)
|
||||
new_lcd_div = 1;
|
||||
if (new_lcd_div > 16)
|
||||
new_lcd_div = 16;
|
||||
|
||||
if (new_lcdpix_div < 1)
|
||||
new_lcdpix_div = 1;
|
||||
if (new_lcdpix_div > 512)
|
||||
new_lcdpix_div = 512;
|
||||
|
||||
// REG_CPM_CPCCR2 = new_lcdpix_div - 1;
|
||||
|
||||
cpccr = REG_CPM_CPCCR;
|
||||
cpccr &= ~CPM_CPCCR_LDIV_MASK;
|
||||
cpccr |= ((new_lcd_div - 1) << CPM_CPCCR_LDIV_BIT);
|
||||
cpccr |= CPM_CPCCR_CE; /* update immediately */
|
||||
|
||||
/* update register to change the clocks.
|
||||
* align this code to a cache line.
|
||||
*/
|
||||
__asm__ __volatile__(
|
||||
".set noreorder\n\t"
|
||||
".align 5\n"
|
||||
"sw %1,0(%0)\n\t"
|
||||
"li %3,0\n\t"
|
||||
"1:\n\t"
|
||||
"bne %3,%2,1b\n\t"
|
||||
"addi %3, 1\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
".set reorder\n\t"
|
||||
:
|
||||
: "r" (CPM_CPCCR), "r" (cpccr), "r" (wait), "r" (tmp));
|
||||
}
|
||||
|
||||
static void jz_scale_pll(struct dpm_regs *regs)
|
||||
{
|
||||
unsigned int cppcr;
|
||||
unsigned int cur_mclk, new_mclk, new_pll;
|
||||
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
|
||||
int od[] = {1, 2, 2, 4};
|
||||
|
||||
cppcr = REG_CPM_CPPCR;
|
||||
cppcr &= ~(regs->cppcr_mask | CPM_CPPCR_PLLS | CPM_CPPCR_PLLEN | CPM_CPPCR_PLLST_MASK);
|
||||
regs->cppcr &= ~CPM_CPPCR_PLLEN;
|
||||
cppcr |= (regs->cppcr | 0xff);
|
||||
|
||||
/* Update some DRAM parameters before changing frequency */
|
||||
new_pll = JZ_EXTAL * ((cppcr>>23)+2) / ((((cppcr>>18)&0x1f)+2) * od[(cppcr>>16)&0x03]);
|
||||
cur_mclk = __cpm_get_mclk();
|
||||
new_mclk = new_pll / div[(REG_CPM_CPCCR>>16) & 0xf];
|
||||
|
||||
/*
|
||||
* Update some SDRAM parameters
|
||||
*/
|
||||
jz_update_dram_prev(cur_mclk, new_mclk);
|
||||
|
||||
/*
|
||||
* Update PLL, align code to cache line.
|
||||
*/
|
||||
cppcr |= CPM_CPPCR_PLLEN;
|
||||
__asm__ __volatile__(
|
||||
".set noreorder\n\t"
|
||||
".align 5\n"
|
||||
"sw %1,0(%0)\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
".set reorder\n\t"
|
||||
:
|
||||
: "r" (CPM_CPPCR), "r" (cppcr));
|
||||
|
||||
/* Update some other DRAM parameters after changing frequency */
|
||||
jz_update_dram_post(cur_mclk, new_mclk);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void jz4760_transition(struct dpm_regs *regs)
|
||||
{
|
||||
/*
|
||||
* Get and save some boot-time conditions.
|
||||
*/
|
||||
jz_init_boot_config();
|
||||
|
||||
#ifdef CHANGE_PLL
|
||||
/*
|
||||
* Disable LCD before scaling pll.
|
||||
* LCD and LCD pixel clocks should not be changed even if the PLL
|
||||
* output frequency has been changed.
|
||||
*/
|
||||
REG_LCD_CTRL &= ~LCD_CTRL_ENA;
|
||||
|
||||
/*
|
||||
* Stop module clocks before scaling PLL
|
||||
*/
|
||||
__cpm_stop_eth();
|
||||
__cpm_stop_aic(1);
|
||||
__cpm_stop_aic(2);
|
||||
#endif
|
||||
|
||||
/* ... add more as necessary */
|
||||
|
||||
if (regs->pll_up_flag == PLL_GOES_UP) {
|
||||
/* the pll frequency is going up, so change dividors first */
|
||||
jz_scale_divisors(regs);
|
||||
#ifdef CHANGE_PLL
|
||||
jz_scale_pll(regs);
|
||||
#endif
|
||||
}
|
||||
else if (regs->pll_up_flag == PLL_GOES_DOWN) {
|
||||
/* the pll frequency is going down, so change pll first */
|
||||
#ifdef CHANGE_PLL
|
||||
jz_scale_pll(regs);
|
||||
#endif
|
||||
jz_scale_divisors(regs);
|
||||
}
|
||||
else {
|
||||
/* the pll frequency is unchanged, so change divisors only */
|
||||
jz_scale_divisors(regs);
|
||||
}
|
||||
|
||||
#ifdef CHANGE_PLL
|
||||
/*
|
||||
* Restart module clocks before scaling PLL
|
||||
*/
|
||||
__cpm_start_eth();
|
||||
__cpm_start_aic(1);
|
||||
__cpm_start_aic(2);
|
||||
|
||||
/* ... add more as necessary */
|
||||
|
||||
/* Scale the LCD divisors after scaling pll */
|
||||
if (regs->pll_up_flag != PLL_UNCHANGED) {
|
||||
jz_scale_lcd_divisors(regs);
|
||||
}
|
||||
|
||||
/* Enable LCD controller */
|
||||
REG_LCD_CTRL &= ~LCD_CTRL_DIS;
|
||||
REG_LCD_CTRL |= LCD_CTRL_ENA;
|
||||
#endif
|
||||
|
||||
/* Update system clocks */
|
||||
jz_update_clocks();
|
||||
}
|
||||
|
||||
extern unsigned int idle_times;
|
||||
static unsigned int jz4760_freq_get(unsigned int cpu)
|
||||
{
|
||||
return (__cpm_get_cclk() / 1000);
|
||||
}
|
||||
|
||||
static unsigned int index_to_divisor(unsigned int index, struct dpm_regs *regs)
|
||||
{
|
||||
int n2FR[33] = {
|
||||
0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0,
|
||||
7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
|
||||
9
|
||||
};
|
||||
int div[4] = {1, 2, 2, 2}; /* divisors of I:S:P:M */
|
||||
unsigned int div_of_cclk, new_freq, i;
|
||||
|
||||
regs->pll_up_flag = PLL_UNCHANGED;
|
||||
regs->cpccr_mask = CPM_CPCCR_CDIV_MASK | CPM_CPCCR_HDIV_MASK | CPM_CPCCR_PDIV_MASK | CPM_CPCCR_MDIV_MASK;
|
||||
|
||||
new_freq = jz4760_freq_table.table[index].frequency;
|
||||
|
||||
do {
|
||||
div_of_cclk = __cpm_get_pllout() / (1000 * new_freq);
|
||||
} while (div_of_cclk==0);
|
||||
|
||||
if(div_of_cclk == 1 || div_of_cclk == 2 || div_of_cclk == 4) {
|
||||
for(i = 1; i<4; i++) {
|
||||
div[i] = 3;
|
||||
}
|
||||
} else {
|
||||
for(i = 1; i<4; i++) {
|
||||
div[i] = 2;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i<4; i++) {
|
||||
div[i] *= div_of_cclk;
|
||||
}
|
||||
|
||||
dprintk("divisors of I:S:P:M = %d:%d:%d:%d\n", div[0], div[1], div[2], div[3]);
|
||||
|
||||
regs->cpccr =
|
||||
(n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) |
|
||||
(n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) |
|
||||
(n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) |
|
||||
(n2FR[div[3]] << CPM_CPCCR_MDIV_BIT);
|
||||
|
||||
return div_of_cclk;
|
||||
}
|
||||
|
||||
static void jz4760_set_cpu_divider_index(unsigned int cpu, unsigned int index)
|
||||
{
|
||||
unsigned long divisor, old_divisor;
|
||||
struct cpufreq_freqs freqs;
|
||||
struct dpm_regs regs;
|
||||
|
||||
old_divisor = __cpm_get_pllout() / __cpm_get_cclk();
|
||||
divisor = index_to_divisor(index, ®s);
|
||||
|
||||
freqs.old = __cpm_get_cclk() / 1000;
|
||||
freqs.new = __cpm_get_pllout() / (1000 * divisor);
|
||||
freqs.cpu = cpu;
|
||||
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
|
||||
if (old_divisor != divisor)
|
||||
jz4760_transition(®s);
|
||||
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
}
|
||||
|
||||
static int jz4760_freq_target(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation)
|
||||
{
|
||||
unsigned int new_index = 0;
|
||||
|
||||
if (cpufreq_frequency_table_target(policy,
|
||||
&jz4760_freq_table.table[0],
|
||||
target_freq, relation, &new_index))
|
||||
return -EINVAL;
|
||||
|
||||
jz4760_set_cpu_divider_index(policy->cpu, new_index);
|
||||
|
||||
dprintk("new frequency is %d KHz (REG_CPM_CPCCR:0x%x)\n", __cpm_get_cclk() / 1000, REG_CPM_CPCCR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jz4760_freq_verify(struct cpufreq_policy *policy)
|
||||
{
|
||||
return cpufreq_frequency_table_verify(policy,
|
||||
&jz4760_freq_table.table[0]);
|
||||
}
|
||||
|
||||
static int __init jz4760_cpufreq_driver_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
|
||||
struct cpufreq_frequency_table *table = &jz4760_freq_table.table[0];
|
||||
unsigned int MAX_FREQ;
|
||||
|
||||
dprintk(KERN_INFO "Jz4760 cpufreq driver\n");
|
||||
|
||||
if (policy->cpu != 0)
|
||||
return -EINVAL;
|
||||
|
||||
policy->cur = MAX_FREQ = __cpm_get_cclk() / 1000; /* in kHz. Current and max frequency is determined by u-boot */
|
||||
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
|
||||
|
||||
policy->cpuinfo.min_freq = MAX_FREQ/8;
|
||||
policy->cpuinfo.max_freq = MAX_FREQ;
|
||||
policy->cpuinfo.transition_latency = 100000; /* in 10^(-9) s = nanoseconds */
|
||||
|
||||
table[0].index = 0;
|
||||
table[0].frequency = MAX_FREQ/8;
|
||||
table[1].index = 1;
|
||||
table[1].frequency = MAX_FREQ/6;
|
||||
table[2].index = 2;
|
||||
table[2].frequency = MAX_FREQ/4;
|
||||
table[3].index = 3;
|
||||
table[3].frequency = MAX_FREQ/3;
|
||||
table[4].index = 4;
|
||||
table[4].frequency = MAX_FREQ/2;
|
||||
table[5].index = 5;
|
||||
table[5].frequency = MAX_FREQ;
|
||||
table[6].index = 6;
|
||||
table[6].frequency = CPUFREQ_TABLE_END;
|
||||
|
||||
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
|
||||
cpufreq_frequency_table_get_attr(table, policy->cpu); /* for showing /sys/devices/system/cpu/cpuX/cpufreq/stats/ */
|
||||
#endif
|
||||
|
||||
return cpufreq_frequency_table_cpuinfo(policy, table);
|
||||
}
|
||||
|
||||
static struct cpufreq_driver cpufreq_jz4760_driver = {
|
||||
// .flags = CPUFREQ_STICKY,
|
||||
.init = jz4760_cpufreq_driver_init,
|
||||
.verify = jz4760_freq_verify,
|
||||
.target = jz4760_freq_target,
|
||||
.get = jz4760_freq_get,
|
||||
.name = "jz4760",
|
||||
};
|
||||
|
||||
static int __init jz4760_cpufreq_init(void)
|
||||
{
|
||||
return cpufreq_register_driver(&cpufreq_jz4760_driver);
|
||||
}
|
||||
|
||||
static void __exit jz4760_cpufreq_exit(void)
|
||||
{
|
||||
cpufreq_unregister_driver(&cpufreq_jz4760_driver);
|
||||
}
|
||||
|
||||
module_init(jz4760_cpufreq_init);
|
||||
module_exit(jz4760_cpufreq_exit);
|
||||
|
||||
MODULE_AUTHOR("Regen <lhhuang@ingenic.cn>");
|
||||
MODULE_DESCRIPTION("cpufreq driver for Jz4760");
|
||||
MODULE_LICENSE("GPL");
|
||||
822
target/linux/xburst/files-2.6.27/arch/mips/jz4760/dma.c
Executable file
822
target/linux/xburst/files-2.6.27/arch/mips/jz4760/dma.c
Executable file
@@ -0,0 +1,822 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4760/dma.c
|
||||
*
|
||||
* Support functions for the JZ4760 internal DMA channels.
|
||||
* No-descriptor transfer only.
|
||||
* Descriptor transfer should also call jz_request_dma() to get a free
|
||||
* channel and call jz_free_dma() to free the channel. And driver should
|
||||
* build the DMA descriptor and setup the DMA channel by itself.
|
||||
*
|
||||
* Copyright (C) 2006 - 2008 Ingenic Semiconductor Inc.
|
||||
*
|
||||
* 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/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/soundcard.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/*
|
||||
* A note on resource allocation:
|
||||
*
|
||||
* All drivers needing DMA channels, should allocate and release them
|
||||
* through the public routines `jz_request_dma()' and `jz_free_dma()'.
|
||||
*
|
||||
* In order to avoid problems, all processes should allocate resources in
|
||||
* the same sequence and release them in the reverse order.
|
||||
*
|
||||
* So, when allocating DMAs and IRQs, first allocate the DMA, then the IRQ.
|
||||
* When releasing them, first release the IRQ, then release the DMA. The
|
||||
* main reason for this order is that, if you are requesting the DMA buffer
|
||||
* done interrupt, you won't know the irq number until the DMA channel is
|
||||
* returned from jz_request_dma().
|
||||
*/
|
||||
|
||||
struct jz_dma_chan jz_dma_table[MAX_DMA_NUM] = {
|
||||
{dev_id:DMA_ID_BCH_ENC,}, /* DMAC0 channel 0, reserved for BCH */
|
||||
{dev_id:-1,}, /* DMAC0 channel 1 */
|
||||
{dev_id:-1,}, /* DMAC0 channel 2 */
|
||||
{dev_id:-1,}, /* DMAC0 channel 3 */
|
||||
{dev_id:-1,}, /* DMAC1 channel 0 */
|
||||
{dev_id:-1,}, /* DMAC1 channel 1 */
|
||||
{dev_id:-1,}, /* DMAC1 channel 2 */
|
||||
{dev_id:-1,}, /* DMAC1 channel 3 */
|
||||
};
|
||||
|
||||
// Device FIFO addresses and default DMA modes
|
||||
static const struct {
|
||||
unsigned int fifo_addr;
|
||||
unsigned int dma_mode;
|
||||
unsigned int dma_source;
|
||||
} dma_dev_table[DMA_ID_MAX] = {
|
||||
{0, DMA_AUTOINIT, DMAC_DRSR_RS_EXT}, /* External request with DREQn */
|
||||
{0x18000000, DMA_AUTOINIT, DMAC_DRSR_RS_NAND}, /* NAND request */
|
||||
{CPHYSADDR(BCH_DR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_BCH_ENC},
|
||||
{CPHYSADDR(BCH_DR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_BCH_DEC},
|
||||
{0, DMA_AUTOINIT, DMAC_DRSR_RS_AUTO},
|
||||
// {CPHYSADDR(TSSI_FIFO), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_TSSIIN},
|
||||
{CPHYSADDR(UART3_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART3OUT},
|
||||
{CPHYSADDR(UART3_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART3IN},
|
||||
{CPHYSADDR(UART2_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART2OUT},
|
||||
{CPHYSADDR(UART2_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART2IN},
|
||||
{CPHYSADDR(UART1_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART1OUT},
|
||||
{CPHYSADDR(UART1_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART1IN},
|
||||
{CPHYSADDR(UART0_TDR), DMA_8BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_UART0OUT},
|
||||
{CPHYSADDR(UART0_RDR), DMA_8BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_UART0IN},
|
||||
{CPHYSADDR(SSI_DR(0)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_SSI0OUT},
|
||||
{CPHYSADDR(SSI_DR(0)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SSI0IN},
|
||||
{CPHYSADDR(AIC_DR), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_AICOUT},
|
||||
{CPHYSADDR(AIC_DR), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_AICIN},
|
||||
{CPHYSADDR(MSC_TXFIFO(0)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_MSC0OUT},
|
||||
{CPHYSADDR(MSC_RXFIFO(0)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_MSC0IN},
|
||||
{0, DMA_AUTOINIT, DMAC_DRSR_RS_TCU},
|
||||
{SADC_TSDAT, DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SADC},/* Touch Screen Data Register */
|
||||
{CPHYSADDR(MSC_TXFIFO(1)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_MSC1OUT}, /* SSC1 TX */
|
||||
{CPHYSADDR(MSC_RXFIFO(1)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_MSC1IN}, /* SSC1 RX */
|
||||
{CPHYSADDR(SSI_DR(1)), DMA_32BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_SSI1OUT},
|
||||
{CPHYSADDR(SSI_DR(1)), DMA_32BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_SSI1IN},
|
||||
// {CPHYSADDR(PCM_DP), DMA_16BIT_TX_CMD | DMA_MODE_WRITE, DMAC_DRSR_RS_PMOUT},
|
||||
// {CPHYSADDR(PCM_DP), DMA_16BIT_RX_CMD | DMA_MODE_READ, DMAC_DRSR_RS_PMIN},
|
||||
{},
|
||||
};
|
||||
|
||||
|
||||
int jz_dma_read_proc(char *buf, char **start, off_t fpos,
|
||||
int length, int *eof, void *data)
|
||||
{
|
||||
int i, len = 0;
|
||||
struct jz_dma_chan *chan;
|
||||
|
||||
for (i = 0; i < MAX_DMA_NUM; i++) {
|
||||
if ((chan = get_dma_chan(i)) != NULL) {
|
||||
len += sprintf(buf + len, "%2d: %s\n",
|
||||
i, chan->dev_str);
|
||||
}
|
||||
}
|
||||
|
||||
if (fpos >= len) {
|
||||
*start = buf;
|
||||
*eof = 1;
|
||||
return 0;
|
||||
}
|
||||
*start = buf + fpos;
|
||||
if ((len -= fpos) > length)
|
||||
return length;
|
||||
*eof = 1;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
void dump_jz_dma_channel(unsigned int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan;
|
||||
|
||||
if (dmanr > MAX_DMA_NUM)
|
||||
return;
|
||||
chan = &jz_dma_table[dmanr];
|
||||
|
||||
printk("DMA%d Registers:\n", dmanr);
|
||||
printk(" DMACR = 0x%08x\n", REG_DMAC_DMACR(chan->io/HALF_DMA_NUM));
|
||||
printk(" DSAR = 0x%08x\n", REG_DMAC_DSAR(dmanr));
|
||||
printk(" DTAR = 0x%08x\n", REG_DMAC_DTAR(dmanr));
|
||||
printk(" DTCR = 0x%08x\n", REG_DMAC_DTCR(dmanr));
|
||||
printk(" DRSR = 0x%08x\n", REG_DMAC_DRSR(dmanr));
|
||||
printk(" DCCSR = 0x%08x\n", REG_DMAC_DCCSR(dmanr));
|
||||
printk(" DCMD = 0x%08x\n", REG_DMAC_DCMD(dmanr));
|
||||
printk(" DDA = 0x%08x\n", REG_DMAC_DDA(dmanr));
|
||||
printk(" DMADBR = 0x%08x\n", REG_DMAC_DMADBR(chan->io/HALF_DMA_NUM));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* jz_request_dma - dynamically allcate an idle DMA channel to return
|
||||
* @dev_id: the specified dma device id or DMA_ID_RAW_SET
|
||||
* @dev_str: the specified dma device string name
|
||||
* @irqhandler: the irq handler, or NULL
|
||||
* @irqflags: the irq handler flags
|
||||
* @irq_dev_id: the irq handler device id for shared irq
|
||||
*
|
||||
* Finds a free channel, and binds the requested device to it.
|
||||
* Returns the allocated channel number, or negative on error.
|
||||
* Requests the DMA done IRQ if irqhandler != NULL.
|
||||
*
|
||||
*/
|
||||
/*int jz_request_dma(int dev_id, const char *dev_str,
|
||||
void (*irqhandler)(int, void *, struct pt_regs *),
|
||||
unsigned long irqflags,
|
||||
void *irq_dev_id)
|
||||
*/
|
||||
|
||||
int jz_request_dma(int dev_id, const char *dev_str,
|
||||
irqreturn_t (*irqhandler)(int, void *),
|
||||
unsigned long irqflags,
|
||||
void *irq_dev_id)
|
||||
{
|
||||
struct jz_dma_chan *chan;
|
||||
int i, ret;
|
||||
|
||||
if (dev_id < 0 || dev_id >= DMA_ID_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < MAX_DMA_NUM; i++) {
|
||||
if (jz_dma_table[i].dev_id < 0)
|
||||
break;
|
||||
}
|
||||
if (i == MAX_DMA_NUM) /* no free channel */
|
||||
return -ENODEV;
|
||||
|
||||
/* we got a free channel */
|
||||
chan = &jz_dma_table[i];
|
||||
|
||||
if (irqhandler) {
|
||||
chan->irq = IRQ_DMA_0 + i; // allocate irq number
|
||||
chan->irq_dev = irq_dev_id;
|
||||
if ((ret = request_irq(chan->irq, irqhandler, irqflags,
|
||||
dev_str, chan->irq_dev))) {
|
||||
chan->irq = -1;
|
||||
chan->irq_dev = NULL;
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
chan->irq = -1;
|
||||
chan->irq_dev = NULL;
|
||||
}
|
||||
|
||||
// fill it in
|
||||
chan->io = i;
|
||||
chan->dev_id = dev_id;
|
||||
chan->dev_str = dev_str;
|
||||
chan->fifo_addr = dma_dev_table[dev_id].fifo_addr;
|
||||
chan->mode = dma_dev_table[dev_id].dma_mode;
|
||||
chan->source = dma_dev_table[dev_id].dma_source;
|
||||
|
||||
if (i < HALF_DMA_NUM)
|
||||
REG_DMAC_DMACKE(0) = 1 << i;
|
||||
else
|
||||
REG_DMAC_DMACKE(1) = 1 << (i - HALF_DMA_NUM);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void jz_free_dma(unsigned int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan) {
|
||||
printk("Trying to free DMA%d\n", dmanr);
|
||||
return;
|
||||
}
|
||||
|
||||
disable_dma(dmanr);
|
||||
if (chan->irq)
|
||||
free_irq(chan->irq, chan->irq_dev);
|
||||
|
||||
chan->irq = -1;
|
||||
chan->irq_dev = NULL;
|
||||
chan->dev_id = -1;
|
||||
}
|
||||
|
||||
void jz_set_dma_dest_width(int dmanr, int nbit)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
chan->mode &= ~DMAC_DCMD_DWDH_MASK;
|
||||
switch (nbit) {
|
||||
case 8:
|
||||
chan->mode |= DMAC_DCMD_DWDH_8;
|
||||
break;
|
||||
case 16:
|
||||
chan->mode |= DMAC_DCMD_DWDH_16;
|
||||
break;
|
||||
case 32:
|
||||
chan->mode |= DMAC_DCMD_DWDH_32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void jz_set_dma_src_width(int dmanr, int nbit)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
chan->mode &= ~DMAC_DCMD_SWDH_MASK;
|
||||
switch (nbit) {
|
||||
case 8:
|
||||
chan->mode |= DMAC_DCMD_SWDH_8;
|
||||
break;
|
||||
case 16:
|
||||
chan->mode |= DMAC_DCMD_SWDH_16;
|
||||
break;
|
||||
case 32:
|
||||
chan->mode |= DMAC_DCMD_SWDH_32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void jz_set_dma_block_size(int dmanr, int nbyte)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
chan->mode &= ~DMAC_DCMD_DS_MASK;
|
||||
switch (nbyte) {
|
||||
case 1:
|
||||
chan->mode |= DMAC_DCMD_DS_8BIT;
|
||||
break;
|
||||
case 2:
|
||||
chan->mode |= DMAC_DCMD_DS_16BIT;
|
||||
break;
|
||||
case 4:
|
||||
chan->mode |= DMAC_DCMD_DS_32BIT;
|
||||
break;
|
||||
case 16:
|
||||
chan->mode |= DMAC_DCMD_DS_16BYTE;
|
||||
break;
|
||||
case 32:
|
||||
chan->mode |= DMAC_DCMD_DS_32BYTE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int jz_get_dma_command(int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
return chan->mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* jz_set_dma_mode - do the raw settings for the specified DMA channel
|
||||
* @dmanr: the specified DMA channel
|
||||
* @mode: dma operate mode, DMA_MODE_READ or DMA_MODE_WRITE
|
||||
* @dma_mode: dma raw mode
|
||||
* @dma_source: dma raw request source
|
||||
* @fifo_addr: dma raw device fifo address
|
||||
*
|
||||
* Ensure call jz_request_dma(DMA_ID_RAW_SET, ...) first, then call
|
||||
* jz_set_dma_mode() rather than set_dma_mode() if you work with
|
||||
* and external request dma device.
|
||||
*
|
||||
* NOTE: Don not dynamically allocate dma channel if one external request
|
||||
* dma device will occupy this channel.
|
||||
*/
|
||||
int jz_set_dma_mode(unsigned int dmanr, unsigned int mode,
|
||||
unsigned int dma_mode, unsigned int dma_source,
|
||||
unsigned int fifo_addr)
|
||||
{
|
||||
int dev_id, i;
|
||||
struct jz_dma_chan *chan;
|
||||
|
||||
if (dmanr > MAX_DMA_NUM)
|
||||
return -ENODEV;
|
||||
for (i = 0; i < MAX_DMA_NUM; i++) {
|
||||
if (jz_dma_table[i].dev_id < 0)
|
||||
break;
|
||||
}
|
||||
if (i == MAX_DMA_NUM)
|
||||
return -ENODEV;
|
||||
|
||||
chan = &jz_dma_table[dmanr];
|
||||
dev_id = chan->dev_id;
|
||||
if (dev_id > 0) {
|
||||
printk(KERN_DEBUG "%s sets the allocated DMA channel %d!\n",
|
||||
__FUNCTION__, dmanr);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* clone it from the dynamically allocated. */
|
||||
if (i != dmanr) {
|
||||
chan->irq = jz_dma_table[i].irq;
|
||||
chan->irq_dev = jz_dma_table[i].irq_dev;
|
||||
chan->dev_str = jz_dma_table[i].dev_str;
|
||||
jz_dma_table[i].irq = 0;
|
||||
jz_dma_table[i].irq_dev = NULL;
|
||||
jz_dma_table[i].dev_id = -1;
|
||||
}
|
||||
chan->dev_id = DMA_ID_RAW_SET;
|
||||
chan->io = dmanr;
|
||||
chan->fifo_addr = fifo_addr;
|
||||
chan->mode = dma_mode;
|
||||
chan->source = dma_source;
|
||||
|
||||
set_dma_mode(dmanr, dma_mode);
|
||||
|
||||
return dmanr;
|
||||
}
|
||||
|
||||
void enable_dma(unsigned int dmanr)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
REG_DMAC_DCCSR(dmanr) &= ~(DMAC_DCCSR_HLT | DMAC_DCCSR_TT | DMAC_DCCSR_AR);
|
||||
REG_DMAC_DCCSR(dmanr) |= DMAC_DCCSR_NDES; /* No-descriptor transfer */
|
||||
__dmac_enable_channel(dmanr);
|
||||
if (chan->irq)
|
||||
__dmac_channel_enable_irq(dmanr);
|
||||
}
|
||||
|
||||
#define DMA_DISABLE_POLL 0x10000
|
||||
|
||||
void disable_dma(unsigned int dmanr)
|
||||
{
|
||||
int i;
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
if (!__dmac_channel_enabled(dmanr))
|
||||
return;
|
||||
|
||||
for (i = 0; i < DMA_DISABLE_POLL; i++)
|
||||
if (__dmac_channel_transmit_end_detected(dmanr))
|
||||
break;
|
||||
#if 0
|
||||
if (i == DMA_DISABLE_POLL)
|
||||
printk(KERN_INFO "disable_dma: poll expired!\n");
|
||||
#endif
|
||||
|
||||
__dmac_disable_channel(dmanr);
|
||||
if (chan->irq)
|
||||
__dmac_channel_disable_irq(dmanr);
|
||||
}
|
||||
|
||||
/* Note: DMA_MODE_MASK is simulated by sw */
|
||||
void set_dma_mode(unsigned int dmanr, unsigned int mode)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI);
|
||||
mode &= DMA_MODE_MASK;
|
||||
if (mode == DMA_MODE_READ) {
|
||||
chan->mode |= DMAC_DCMD_DAI;
|
||||
chan->mode &= ~DMAC_DCMD_SAI;
|
||||
} else if (mode == DMA_MODE_WRITE) {
|
||||
chan->mode |= DMAC_DCMD_SAI;
|
||||
chan->mode &= ~DMAC_DCMD_DAI;
|
||||
} else {
|
||||
printk(KERN_DEBUG "set_dma_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n");
|
||||
}
|
||||
REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK;
|
||||
REG_DMAC_DRSR(chan->io) = chan->source;
|
||||
}
|
||||
|
||||
void set_dma_addr(unsigned int dmanr, unsigned int phyaddr)
|
||||
{
|
||||
unsigned int mode;
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
mode = chan->mode & DMA_MODE_MASK;
|
||||
if (mode == DMA_MODE_READ) {
|
||||
REG_DMAC_DSAR(chan->io) = chan->fifo_addr;
|
||||
REG_DMAC_DTAR(chan->io) = phyaddr;
|
||||
} else if (mode == DMA_MODE_WRITE) {
|
||||
REG_DMAC_DSAR(chan->io) = phyaddr;
|
||||
REG_DMAC_DTAR(chan->io) = chan->fifo_addr;
|
||||
} else
|
||||
printk(KERN_DEBUG "Driver should call set_dma_mode() ahead set_dma_addr()!\n");
|
||||
}
|
||||
|
||||
void set_dma_count(unsigned int dmanr, unsigned int bytecnt)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
int dma_ds[] = {4, 1, 2, 16, 32};
|
||||
unsigned int ds;
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT;
|
||||
REG_DMAC_DTCR(chan->io) = bytecnt / dma_ds[ds]; // transfer count
|
||||
}
|
||||
|
||||
unsigned int get_dma_residue(unsigned int dmanr)
|
||||
{
|
||||
unsigned int count, ds;
|
||||
int dma_ds[] = {4, 1, 2, 16, 32};
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
if (!chan)
|
||||
return 0;
|
||||
|
||||
ds = (chan->mode & DMAC_DCMD_DS_MASK) >> DMAC_DCMD_DS_BIT;
|
||||
count = REG_DMAC_DTCR(chan->io);
|
||||
count = count * dma_ds[ds];
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void jz_set_oss_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
switch (audio_fmt) {
|
||||
case AFMT_U8:
|
||||
/* burst mode : 32BIT */
|
||||
break;
|
||||
case AFMT_S16_LE:
|
||||
/* burst mode : 16BYTE */
|
||||
if (mode == DMA_MODE_READ) {
|
||||
chan->mode = DMA_AIC_32_16BYTE_RX_CMD | DMA_MODE_READ;
|
||||
chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI);
|
||||
mode &= DMA_MODE_MASK;
|
||||
chan->mode |= DMAC_DCMD_DAI;
|
||||
chan->mode &= ~DMAC_DCMD_SAI;
|
||||
} else if (mode == DMA_MODE_WRITE) {
|
||||
chan->mode = DMA_AIC_32_16BYTE_TX_CMD | DMA_MODE_WRITE;
|
||||
//chan->mode = DMA_AIC_16BYTE_TX_CMD | DMA_MODE_WRITE;
|
||||
chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI);
|
||||
mode &= DMA_MODE_MASK;
|
||||
chan->mode |= DMAC_DCMD_SAI;
|
||||
chan->mode &= ~DMAC_DCMD_DAI;
|
||||
} else
|
||||
printk("oss_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n");
|
||||
|
||||
REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK;
|
||||
REG_DMAC_DRSR(chan->io) = chan->source;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void jz_set_alsa_dma(unsigned int dmanr, unsigned int mode, unsigned int audio_fmt)
|
||||
{
|
||||
struct jz_dma_chan *chan = get_dma_chan(dmanr);
|
||||
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
switch (audio_fmt) {
|
||||
case 8:
|
||||
/* SNDRV_PCM_FORMAT_S8 burst mode : 32BIT */
|
||||
break;
|
||||
case 16:
|
||||
/* SNDRV_PCM_FORMAT_S16_LE burst mode : 16BYTE */
|
||||
if (mode == DMA_MODE_READ) {
|
||||
chan->mode = DMA_AIC_16BYTE_RX_CMD | DMA_MODE_READ;
|
||||
chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI);
|
||||
mode &= DMA_MODE_MASK;
|
||||
chan->mode |= DMAC_DCMD_DAI;
|
||||
chan->mode &= ~DMAC_DCMD_SAI;
|
||||
} else if (mode == DMA_MODE_WRITE) {
|
||||
chan->mode = DMA_AIC_16BYTE_TX_CMD | DMA_MODE_WRITE;
|
||||
chan->mode |= mode & ~(DMAC_DCMD_SAI | DMAC_DCMD_DAI);
|
||||
mode &= DMA_MODE_MASK;
|
||||
chan->mode |= DMAC_DCMD_SAI;
|
||||
chan->mode &= ~DMAC_DCMD_DAI;
|
||||
} else
|
||||
printk("alsa_dma_burst_mode() just supports DMA_MODE_READ or DMA_MODE_WRITE!\n");
|
||||
|
||||
REG_DMAC_DCMD(chan->io) = chan->mode & ~DMA_MODE_MASK;
|
||||
REG_DMAC_DRSR(chan->io) = chan->source;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//#define JZ4760_DMAC_TEST_ENABLE
|
||||
#undef JZ4760_DMAC_TEST_ENABLE
|
||||
|
||||
#ifdef JZ4760_DMAC_TEST_ENABLE
|
||||
|
||||
/*
|
||||
* DMA test: external address <--> external address
|
||||
*/
|
||||
#define TEST_DMA_SIZE 16*1024
|
||||
|
||||
static jz_dma_desc *dma_desc;
|
||||
|
||||
static int dma_chan;
|
||||
static dma_addr_t dma_desc_phys_addr;
|
||||
static unsigned int dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr;
|
||||
|
||||
static int dma_check_result(void *src, void *dst, int size)
|
||||
{
|
||||
unsigned int addr1, addr2, i, err = 0;
|
||||
|
||||
addr1 = (unsigned int)src;
|
||||
addr2 = (unsigned int)dst;
|
||||
|
||||
for (i = 0; i < size; i += 4) {
|
||||
if (*(volatile unsigned int *)addr1 != *(volatile unsigned int *)addr2) {
|
||||
err++;
|
||||
printk("wrong data at 0x%08x: src 0x%08x dst 0x%08x\n", addr2, *(volatile unsigned int *)addr1, *(volatile unsigned int *)addr2);
|
||||
}
|
||||
addr1 += 4;
|
||||
addr2 += 4;
|
||||
}
|
||||
printk("check DMA result err=%d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
static irqreturn_t jz4760_dma_irq(int irq, void *dev_id)
|
||||
{
|
||||
printk("jz4760_dma_irq %d\n", irq);
|
||||
|
||||
|
||||
if (__dmac_channel_transmit_halt_detected(dma_chan)) {
|
||||
printk("DMA HALT\n");
|
||||
REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */
|
||||
__dmac_channel_clear_transmit_halt(dma_chan);
|
||||
}
|
||||
|
||||
if (__dmac_channel_address_error_detected(dma_chan)) {
|
||||
printk("DMA ADDR ERROR\n");
|
||||
REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */
|
||||
REG_DMAC_DSAR(dma_chan) = 0; /* clear source address register */
|
||||
REG_DMAC_DTAR(dma_chan) = 0; /* clear target address register */
|
||||
__dmac_channel_clear_address_error(dma_chan);
|
||||
}
|
||||
|
||||
if (__dmac_channel_descriptor_invalid_detected(dma_chan)) {
|
||||
REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */
|
||||
printk("DMA DESC INVALID\n");
|
||||
__dmac_channel_clear_descriptor_invalid(dma_chan);
|
||||
}
|
||||
|
||||
if (__dmac_channel_count_terminated_detected(dma_chan)) {
|
||||
printk("DMA CT\n");
|
||||
__dmac_channel_clear_count_terminated(dma_chan);
|
||||
}
|
||||
|
||||
if (__dmac_channel_transmit_end_detected(dma_chan)) {
|
||||
REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */
|
||||
printk("DMA TT\n");
|
||||
__dmac_channel_clear_transmit_end(dma_chan);
|
||||
dump_jz_dma_channel(dma_chan);
|
||||
dma_check_result((void *)dma_src_addr, (void *)dma_dst_addr, TEST_DMA_SIZE);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
void dma_nodesc_test(void)
|
||||
{
|
||||
unsigned int addr, i;
|
||||
|
||||
printk("dma_nodesc_test\n");
|
||||
|
||||
/* Request DMA channel and setup irq handler */
|
||||
dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4760_dma_irq,
|
||||
IRQF_DISABLED, NULL);
|
||||
if (dma_chan < 0) {
|
||||
printk("Setup irq failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printk("Requested DMA channel = %d\n", dma_chan);
|
||||
|
||||
/* Allocate DMA buffers */
|
||||
dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */
|
||||
dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */
|
||||
|
||||
dma_src_phys_addr = CPHYSADDR(dma_src_addr);
|
||||
dma_dst_phys_addr = CPHYSADDR(dma_dst_addr);
|
||||
|
||||
printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n",
|
||||
dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr);
|
||||
|
||||
/* Prepare data for source buffer */
|
||||
addr = (unsigned int)dma_src_addr;
|
||||
for (i = 0; i < TEST_DMA_SIZE; i += 4) {
|
||||
*(volatile unsigned int *)addr = addr;
|
||||
addr += 4;
|
||||
}
|
||||
dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE);
|
||||
|
||||
/* Init target buffer */
|
||||
memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE);
|
||||
dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE);
|
||||
|
||||
/* Init DMA module */
|
||||
printk("Starting DMA\n");
|
||||
REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = 0;
|
||||
REG_DMAC_DCCSR(dma_chan) = 0;
|
||||
REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO;
|
||||
REG_DMAC_DSAR(dma_chan) = dma_src_phys_addr;
|
||||
REG_DMAC_DTAR(dma_chan) = dma_dst_phys_addr;
|
||||
REG_DMAC_DTCR(dma_chan) = 512;
|
||||
REG_DMAC_DCMD(dma_chan) = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_TIE;
|
||||
REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_NDES | DMAC_DCCSR_EN;
|
||||
REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = DMAC_DMACR_DMAE; /* global DMA enable bit */
|
||||
|
||||
printk("DMA started. IMR=%08x\n", REG_INTC_IMR);
|
||||
|
||||
/* wait a long time, ensure transfer end */
|
||||
printk("wait 3s...\n");
|
||||
mdelay(3000); /* wait 3s */
|
||||
|
||||
REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */
|
||||
/* free buffers */
|
||||
printk("free DMA buffers\n");
|
||||
free_pages(dma_src_addr, 2);
|
||||
free_pages(dma_dst_addr, 2);
|
||||
|
||||
if (dma_desc)
|
||||
free_pages((unsigned int)dma_desc, 0);
|
||||
|
||||
/* free dma */
|
||||
jz_free_dma(dma_chan);
|
||||
}
|
||||
|
||||
void dma_desc_test(void)
|
||||
{
|
||||
unsigned int next, addr, i;
|
||||
static jz_dma_desc *desc;
|
||||
|
||||
printk("dma_desc_test\n");
|
||||
|
||||
/* Request DMA channel and setup irq handler */
|
||||
dma_chan = jz_request_dma(DMA_ID_AUTO, "auto", jz4760_dma_irq,
|
||||
IRQF_DISABLED, NULL);
|
||||
if (dma_chan < 0) {
|
||||
printk("Setup irq failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printk("Requested DMA channel = %d\n", dma_chan);
|
||||
|
||||
/* Allocate DMA buffers */
|
||||
dma_src_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */
|
||||
dma_dst_addr = __get_free_pages(GFP_KERNEL, 2); /* 16KB */
|
||||
|
||||
dma_src_phys_addr = CPHYSADDR(dma_src_addr);
|
||||
dma_dst_phys_addr = CPHYSADDR(dma_dst_addr);
|
||||
|
||||
printk("Buffer addresses: 0x%08x 0x%08x 0x%08x 0x%08x\n",
|
||||
dma_src_addr, dma_src_phys_addr, dma_dst_addr, dma_dst_phys_addr);
|
||||
|
||||
/* Prepare data for source buffer */
|
||||
addr = (unsigned int)dma_src_addr;
|
||||
for (i = 0; i < TEST_DMA_SIZE; i += 4) {
|
||||
*(volatile unsigned int *)addr = addr;
|
||||
addr += 4;
|
||||
}
|
||||
dma_cache_wback((unsigned long)dma_src_addr, TEST_DMA_SIZE);
|
||||
|
||||
/* Init target buffer */
|
||||
memset((void *)dma_dst_addr, 0, TEST_DMA_SIZE);
|
||||
dma_cache_wback((unsigned long)dma_dst_addr, TEST_DMA_SIZE);
|
||||
|
||||
/* Allocate DMA descriptors */
|
||||
dma_desc = (jz_dma_desc *)__get_free_pages(GFP_KERNEL, 0);
|
||||
dma_desc_phys_addr = CPHYSADDR((unsigned long)dma_desc);
|
||||
|
||||
printk("DMA descriptor address: 0x%08x 0x%08x\n", (u32)dma_desc, dma_desc_phys_addr);
|
||||
|
||||
/* Setup DMA descriptors */
|
||||
desc = dma_desc;
|
||||
next = (dma_desc_phys_addr + (sizeof(jz_dma_desc))) >> 4;
|
||||
|
||||
desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK;
|
||||
desc->dsadr = dma_src_phys_addr; /* DMA source address */
|
||||
desc->dtadr = dma_dst_phys_addr; /* DMA target address */
|
||||
desc->ddadr = (next << 24) + 128; /* size: 128*32 bytes = 4096 bytes */
|
||||
|
||||
desc++;
|
||||
next = (dma_desc_phys_addr + 2*(sizeof(jz_dma_desc))) >> 4;
|
||||
|
||||
desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK;
|
||||
desc->dsadr = dma_src_phys_addr + 4096; /* DMA source address */
|
||||
desc->dtadr = dma_dst_phys_addr + 4096; /* DMA target address */
|
||||
desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */
|
||||
|
||||
desc++;
|
||||
next = (dma_desc_phys_addr + 3*(sizeof(jz_dma_desc))) >> 4;
|
||||
|
||||
desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE | DMAC_DCMD_LINK;
|
||||
desc->dsadr = dma_src_phys_addr + 8192; /* DMA source address */
|
||||
desc->dtadr = dma_dst_phys_addr + 8192; /* DMA target address */
|
||||
desc->ddadr = (next << 24) + 256; /* size: 256*16 bytes = 4096 bytes */
|
||||
|
||||
desc++;
|
||||
next = (dma_desc_phys_addr + 4*(sizeof(jz_dma_desc))) >> 4;
|
||||
|
||||
desc->dcmd = DMAC_DCMD_SAI | DMAC_DCMD_DAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_DES_V | DMAC_DCMD_DES_VM | DMAC_DCMD_DES_VIE | DMAC_DCMD_TIE;
|
||||
desc->dsadr = dma_src_phys_addr + 12*1024; /* DMA source address */
|
||||
desc->dtadr = dma_dst_phys_addr + 12*1024; /* DMA target address */
|
||||
desc->ddadr = (next << 24) + 1024; /* size: 1024*4 bytes = 4096 bytes */
|
||||
|
||||
dma_cache_wback((unsigned long)dma_desc, 4*(sizeof(jz_dma_desc)));
|
||||
|
||||
/* Setup DMA descriptor address */
|
||||
REG_DMAC_DDA(dma_chan) = dma_desc_phys_addr;
|
||||
|
||||
/* Setup request source */
|
||||
REG_DMAC_DRSR(dma_chan) = DMAC_DRSR_RS_AUTO;
|
||||
|
||||
/* Setup DMA channel control/status register */
|
||||
REG_DMAC_DCCSR(dma_chan) = DMAC_DCCSR_EN; /* descriptor transfer, clear status, start channel */
|
||||
|
||||
/* Enable DMA */
|
||||
REG_DMAC_DMACR(dma_chan/HALF_DMA_NUM) = DMAC_DMACR_DMAE;
|
||||
|
||||
/* DMA doorbell set -- start DMA now ... */
|
||||
REG_DMAC_DMADBSR(dma_chan/HALF_DMA_NUM) = 1 << dma_chan;
|
||||
|
||||
printk("DMA started. IMR=%08x\n", REG_INTC_IMR);
|
||||
/* wait a long time, ensure transfer end */
|
||||
printk("wait 3s...\n");
|
||||
mdelay(3000); /* wait 3s */
|
||||
|
||||
REG_DMAC_DCCSR(dma_chan) &= ~DMAC_DCCSR_EN; /* disable DMA */
|
||||
/* free buffers */
|
||||
printk("free DMA buffers\n");
|
||||
free_pages(dma_src_addr, 2);
|
||||
free_pages(dma_dst_addr, 2);
|
||||
|
||||
if (dma_desc)
|
||||
free_pages((unsigned int)dma_desc, 0);
|
||||
|
||||
/* free dma */
|
||||
jz_free_dma(dma_chan);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//EXPORT_SYMBOL_NOVERS(jz_dma_table);
|
||||
EXPORT_SYMBOL(jz_dma_table);
|
||||
EXPORT_SYMBOL(jz_request_dma);
|
||||
EXPORT_SYMBOL(jz_free_dma);
|
||||
EXPORT_SYMBOL(jz_set_dma_src_width);
|
||||
EXPORT_SYMBOL(jz_set_dma_dest_width);
|
||||
EXPORT_SYMBOL(jz_set_dma_block_size);
|
||||
EXPORT_SYMBOL(jz_set_dma_mode);
|
||||
EXPORT_SYMBOL(set_dma_mode);
|
||||
EXPORT_SYMBOL(jz_set_oss_dma);
|
||||
EXPORT_SYMBOL(jz_set_alsa_dma);
|
||||
EXPORT_SYMBOL(set_dma_addr);
|
||||
EXPORT_SYMBOL(set_dma_count);
|
||||
EXPORT_SYMBOL(get_dma_residue);
|
||||
EXPORT_SYMBOL(enable_dma);
|
||||
EXPORT_SYMBOL(disable_dma);
|
||||
EXPORT_SYMBOL(dump_jz_dma_channel);
|
||||
273
target/linux/xburst/files-2.6.27/arch/mips/jz4760/i2c.c
Executable file
273
target/linux/xburst/files-2.6.27/arch/mips/jz4760/i2c.c
Executable file
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4760/i2c.c
|
||||
*
|
||||
* Jz4760 I2C routines.
|
||||
*
|
||||
* Copyright (C) 2005,2006 Ingenic Semiconductor Inc.
|
||||
* Author: <lhhuang@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can distribute it and/or modify it
|
||||
* under the terms of the GNU General Public License (Version 2) as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/addrspace.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/* I2C protocol */
|
||||
#define I2C_READ 1
|
||||
#define I2C_WRITE 0
|
||||
|
||||
#define TIMEOUT 1000
|
||||
|
||||
/*
|
||||
* I2C bus protocol basic routines
|
||||
*/
|
||||
static int i2c_put_data(unsigned char data)
|
||||
{
|
||||
unsigned int timeout = TIMEOUT*10;
|
||||
|
||||
__i2c_write(data);
|
||||
__i2c_set_drf();
|
||||
while (__i2c_check_drf() != 0);
|
||||
while (!__i2c_transmit_ended());
|
||||
while (!__i2c_received_ack() && timeout)
|
||||
timeout--;
|
||||
|
||||
if (timeout)
|
||||
return 0;
|
||||
else
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_JZ_TPANEL_ATA2508
|
||||
static int i2c_put_data_nack(unsigned char data)
|
||||
{
|
||||
unsigned int timeout = TIMEOUT*10;
|
||||
|
||||
__i2c_write(data);
|
||||
__i2c_set_drf();
|
||||
while (__i2c_check_drf() != 0);
|
||||
while (!__i2c_transmit_ended());
|
||||
while (timeout--);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int i2c_get_data(unsigned char *data, int ack)
|
||||
{
|
||||
int timeout = TIMEOUT*10;
|
||||
|
||||
if (!ack)
|
||||
__i2c_send_nack();
|
||||
else
|
||||
__i2c_send_ack();
|
||||
|
||||
while (__i2c_check_drf() == 0 && timeout)
|
||||
timeout--;
|
||||
|
||||
if (timeout) {
|
||||
if (!ack)
|
||||
__i2c_send_stop();
|
||||
*data = __i2c_read();
|
||||
__i2c_clear_drf();
|
||||
return 0;
|
||||
} else
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/*
|
||||
* I2C interface
|
||||
*/
|
||||
void i2c_open(void)
|
||||
{
|
||||
__i2c_set_clk(jz_clocks.extalclk, 10000); /* default 10 KHz */
|
||||
__i2c_enable();
|
||||
}
|
||||
|
||||
void i2c_close(void)
|
||||
{
|
||||
udelay(300); /* wait for STOP goes over. */
|
||||
__i2c_disable();
|
||||
}
|
||||
|
||||
void i2c_setclk(unsigned int i2cclk)
|
||||
{
|
||||
__i2c_set_clk(jz_clocks.extalclk, i2cclk);
|
||||
}
|
||||
|
||||
int i2c_lseek(unsigned char device, unsigned char offset)
|
||||
{
|
||||
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
|
||||
goto device_err;
|
||||
if (i2c_put_data(offset) < 0)
|
||||
goto address_err;
|
||||
return 0;
|
||||
device_err:
|
||||
printk(KERN_DEBUG "No I2C device (0x%02x) installed.\n", device);
|
||||
__i2c_send_stop();
|
||||
return -ENODEV;
|
||||
address_err:
|
||||
printk(KERN_DEBUG "No I2C device (0x%02x) response.\n", device);
|
||||
__i2c_send_stop();
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
int i2c_read(unsigned char device, unsigned char *buf,
|
||||
unsigned char address, int count)
|
||||
{
|
||||
int cnt = count;
|
||||
int timeout = 5;
|
||||
|
||||
L_try_again:
|
||||
|
||||
if (timeout < 0)
|
||||
goto L_timeout;
|
||||
|
||||
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
|
||||
goto device_werr;
|
||||
if (i2c_put_data(address) < 0)
|
||||
goto address_err;
|
||||
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_READ ) < 0)
|
||||
goto device_rerr;
|
||||
__i2c_send_ack(); /* Master sends ACK for continue reading */
|
||||
while (cnt) {
|
||||
if (cnt == 1) {
|
||||
if (i2c_get_data(buf, 0) < 0)
|
||||
break;
|
||||
} else {
|
||||
if (i2c_get_data(buf, 1) < 0)
|
||||
break;
|
||||
}
|
||||
cnt--;
|
||||
buf++;
|
||||
}
|
||||
|
||||
__i2c_send_stop();
|
||||
return count - cnt;
|
||||
device_rerr:
|
||||
device_werr:
|
||||
address_err:
|
||||
timeout --;
|
||||
__i2c_send_stop();
|
||||
goto L_try_again;
|
||||
|
||||
L_timeout:
|
||||
__i2c_send_stop();
|
||||
printk("Read I2C device 0x%2x failed.\n", device);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int i2c_write(unsigned char device, unsigned char *buf,
|
||||
unsigned char address, int count)
|
||||
{
|
||||
int cnt = count;
|
||||
int cnt_in_pg;
|
||||
int timeout = 5;
|
||||
unsigned char *tmpbuf;
|
||||
unsigned char tmpaddr;
|
||||
|
||||
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
|
||||
|
||||
W_try_again:
|
||||
if (timeout < 0)
|
||||
goto W_timeout;
|
||||
|
||||
cnt = count;
|
||||
tmpbuf = (unsigned char *)buf;
|
||||
tmpaddr = address;
|
||||
|
||||
start_write_page:
|
||||
cnt_in_pg = 0;
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
|
||||
goto device_err;
|
||||
#ifdef CONFIG_JZ_TPANEL_ATA2508
|
||||
if (address == 0xff) {
|
||||
if (i2c_put_data_nack(tmpaddr) < 0)
|
||||
goto address_err;
|
||||
while (cnt) {
|
||||
if (++cnt_in_pg > 8) {
|
||||
__i2c_send_stop();
|
||||
mdelay(1);
|
||||
tmpaddr += 8;
|
||||
goto start_write_page;
|
||||
}
|
||||
if (i2c_put_data_nack(*tmpbuf) < 0)
|
||||
break;
|
||||
cnt--;
|
||||
tmpbuf++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if (i2c_put_data(tmpaddr) < 0)
|
||||
goto address_err;
|
||||
while (cnt) {
|
||||
if (++cnt_in_pg > 8) {
|
||||
__i2c_send_stop();
|
||||
mdelay(1);
|
||||
tmpaddr += 8;
|
||||
goto start_write_page;
|
||||
}
|
||||
if (i2c_put_data(*tmpbuf) < 0)
|
||||
break;
|
||||
cnt--;
|
||||
tmpbuf++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (i2c_put_data(tmpaddr) < 0)
|
||||
goto address_err;
|
||||
while (cnt) {
|
||||
if (++cnt_in_pg > 8) {
|
||||
__i2c_send_stop();
|
||||
mdelay(1);
|
||||
tmpaddr += 8;
|
||||
goto start_write_page;
|
||||
}
|
||||
if (i2c_put_data(*tmpbuf) < 0)
|
||||
break;
|
||||
cnt--;
|
||||
tmpbuf++;
|
||||
}
|
||||
#endif
|
||||
__i2c_send_stop();
|
||||
return count - cnt;
|
||||
device_err:
|
||||
address_err:
|
||||
timeout--;
|
||||
__i2c_send_stop();
|
||||
goto W_try_again;
|
||||
|
||||
W_timeout:
|
||||
printk(KERN_DEBUG "Write I2C device 0x%2x failed.\n", device);
|
||||
__i2c_send_stop();
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(i2c_open);
|
||||
EXPORT_SYMBOL(i2c_close);
|
||||
EXPORT_SYMBOL(i2c_setclk);
|
||||
EXPORT_SYMBOL(i2c_read);
|
||||
EXPORT_SYMBOL(i2c_write);
|
||||
299
target/linux/xburst/files-2.6.27/arch/mips/jz4760/irq.c
Executable file
299
target/linux/xburst/files-2.6.27/arch/mips/jz4760/irq.c
Executable file
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4760/irq.c
|
||||
*
|
||||
* JZ4760 interrupt routines.
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <lhhuang@ingenic.cn>
|
||||
*
|
||||
* 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/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/timex.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/*
|
||||
* INTC irq type
|
||||
*/
|
||||
|
||||
static void enable_intc_irq(unsigned int irq)
|
||||
{
|
||||
__intc_unmask_irq(irq);
|
||||
}
|
||||
|
||||
static void disable_intc_irq(unsigned int irq)
|
||||
{
|
||||
__intc_mask_irq(irq);
|
||||
}
|
||||
|
||||
static void mask_and_ack_intc_irq(unsigned int irq)
|
||||
{
|
||||
__intc_mask_irq(irq);
|
||||
__intc_ack_irq(irq);
|
||||
}
|
||||
|
||||
static void end_intc_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
|
||||
enable_intc_irq(irq);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int startup_intc_irq(unsigned int irq)
|
||||
{
|
||||
enable_intc_irq(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void shutdown_intc_irq(unsigned int irq)
|
||||
{
|
||||
disable_intc_irq(irq);
|
||||
}
|
||||
|
||||
static struct irq_chip intc_irq_type = {
|
||||
.typename = "INTC",
|
||||
.startup = startup_intc_irq,
|
||||
.shutdown = shutdown_intc_irq,
|
||||
.enable = enable_intc_irq,
|
||||
.disable = disable_intc_irq,
|
||||
.ack = mask_and_ack_intc_irq,
|
||||
.end = end_intc_irq,
|
||||
};
|
||||
|
||||
/*
|
||||
* GPIO irq type
|
||||
*/
|
||||
|
||||
static void enable_gpio_irq(unsigned int irq)
|
||||
{
|
||||
unsigned int intc_irq;
|
||||
|
||||
if (irq < (IRQ_GPIO_0 + 32)) {
|
||||
intc_irq = IRQ_GPIO0;
|
||||
}
|
||||
else if (irq < (IRQ_GPIO_0 + 64)) {
|
||||
intc_irq = IRQ_GPIO1;
|
||||
}
|
||||
else if (irq < (IRQ_GPIO_0 + 96)) {
|
||||
intc_irq = IRQ_GPIO2;
|
||||
}
|
||||
else if (irq < (IRQ_GPIO_0 + 128)) {
|
||||
intc_irq = IRQ_GPIO3;
|
||||
}
|
||||
else if (irq < (IRQ_GPIO_0 + 160)) {
|
||||
intc_irq = IRQ_GPIO4;
|
||||
}
|
||||
else {
|
||||
intc_irq = IRQ_GPIO5;
|
||||
}
|
||||
|
||||
enable_intc_irq(intc_irq);
|
||||
__gpio_unmask_irq(irq - IRQ_GPIO_0);
|
||||
}
|
||||
|
||||
static void disable_gpio_irq(unsigned int irq)
|
||||
{
|
||||
__gpio_mask_irq(irq - IRQ_GPIO_0);
|
||||
}
|
||||
|
||||
static void mask_and_ack_gpio_irq(unsigned int irq)
|
||||
{
|
||||
__gpio_mask_irq(irq - IRQ_GPIO_0);
|
||||
__gpio_ack_irq(irq - IRQ_GPIO_0);
|
||||
}
|
||||
|
||||
static void end_gpio_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
|
||||
enable_gpio_irq(irq);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int startup_gpio_irq(unsigned int irq)
|
||||
{
|
||||
enable_gpio_irq(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void shutdown_gpio_irq(unsigned int irq)
|
||||
{
|
||||
disable_gpio_irq(irq);
|
||||
}
|
||||
|
||||
static struct irq_chip gpio_irq_type = {
|
||||
.typename = "GPIO",
|
||||
.startup = startup_gpio_irq,
|
||||
.shutdown = shutdown_gpio_irq,
|
||||
.enable = enable_gpio_irq,
|
||||
.disable = disable_gpio_irq,
|
||||
.ack = mask_and_ack_gpio_irq,
|
||||
.end = end_gpio_irq,
|
||||
};
|
||||
|
||||
/*
|
||||
* DMA irq type
|
||||
*/
|
||||
|
||||
static void enable_dma_irq(unsigned int irq)
|
||||
{
|
||||
unsigned int intc_irq;
|
||||
|
||||
if ( irq < (IRQ_DMA_0 + HALF_DMA_NUM) ) /* DMAC Group 0 irq */
|
||||
intc_irq = IRQ_DMAC0;
|
||||
else if ( irq < (IRQ_DMA_0 + MAX_DMA_NUM) ) /* DMAC Group 1 irq */
|
||||
intc_irq = IRQ_DMAC1;
|
||||
else {
|
||||
printk("%s, unexpected dma irq #%d\n", __FILE__, irq);
|
||||
return;
|
||||
}
|
||||
__intc_unmask_irq(intc_irq);
|
||||
__dmac_channel_enable_irq(irq - IRQ_DMA_0);
|
||||
}
|
||||
|
||||
static void disable_dma_irq(unsigned int irq)
|
||||
{
|
||||
__dmac_channel_disable_irq(irq - IRQ_DMA_0);
|
||||
}
|
||||
|
||||
static void mask_and_ack_dma_irq(unsigned int irq)
|
||||
{
|
||||
unsigned int intc_irq;
|
||||
|
||||
if ( irq < (IRQ_DMA_0 + HALF_DMA_NUM) ) /* DMAC Group 0 irq */
|
||||
intc_irq = IRQ_DMAC0;
|
||||
else if ( irq < (IRQ_DMA_0 + MAX_DMA_NUM) ) /* DMAC Group 1 irq */
|
||||
intc_irq = IRQ_DMAC1;
|
||||
else {
|
||||
printk("%s, unexpected dma irq #%d\n", __FILE__, irq);
|
||||
return ;
|
||||
}
|
||||
__intc_ack_irq(intc_irq);
|
||||
__dmac_channel_ack_irq(irq-IRQ_DMA_0); /* needed?? add 20080506, Wolfgang */
|
||||
__dmac_channel_disable_irq(irq - IRQ_DMA_0);
|
||||
}
|
||||
|
||||
static void end_dma_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
|
||||
enable_dma_irq(irq);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int startup_dma_irq(unsigned int irq)
|
||||
{
|
||||
enable_dma_irq(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void shutdown_dma_irq(unsigned int irq)
|
||||
{
|
||||
disable_dma_irq(irq);
|
||||
}
|
||||
|
||||
static struct irq_chip dma_irq_type = {
|
||||
.typename = "DMA",
|
||||
.startup = startup_dma_irq,
|
||||
.shutdown = shutdown_dma_irq,
|
||||
.enable = enable_dma_irq,
|
||||
.disable = disable_dma_irq,
|
||||
.ack = mask_and_ack_dma_irq,
|
||||
.end = end_dma_irq,
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void __init arch_init_irq(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
clear_c0_status(0xff04); /* clear ERL */
|
||||
set_c0_status(0x0400); /* set IP2 */
|
||||
|
||||
/* Set up INTC irq
|
||||
*/
|
||||
for (i = 0; i < 32; i++) {
|
||||
disable_intc_irq(i);
|
||||
irq_desc[i].chip = &intc_irq_type;
|
||||
}
|
||||
|
||||
/* Set up DMAC irq
|
||||
*/
|
||||
for (i = 0; i < NUM_DMA; i++) {
|
||||
disable_dma_irq(IRQ_DMA_0 + i);
|
||||
irq_desc[IRQ_DMA_0 + i].chip = &dma_irq_type;
|
||||
}
|
||||
|
||||
/* Set up GPIO irq
|
||||
*/
|
||||
for (i = 0; i < NUM_GPIO; i++) {
|
||||
disable_gpio_irq(IRQ_GPIO_0 + i);
|
||||
irq_desc[IRQ_GPIO_0 + i].chip = &gpio_irq_type;
|
||||
}
|
||||
}
|
||||
|
||||
static int plat_real_irq(int irq)
|
||||
{
|
||||
switch (irq) {
|
||||
case IRQ_GPIO0:
|
||||
irq = __gpio_group_irq(0) + IRQ_GPIO_0;
|
||||
break;
|
||||
case IRQ_GPIO1:
|
||||
irq = __gpio_group_irq(1) + IRQ_GPIO_0 + 32;
|
||||
break;
|
||||
case IRQ_GPIO2:
|
||||
irq = __gpio_group_irq(2) + IRQ_GPIO_0 + 64;
|
||||
break;
|
||||
case IRQ_GPIO3:
|
||||
irq = __gpio_group_irq(3) + IRQ_GPIO_0 + 96;
|
||||
break;
|
||||
case IRQ_GPIO4:
|
||||
irq = __gpio_group_irq(4) + IRQ_GPIO_0 + 128;
|
||||
break;
|
||||
case IRQ_GPIO5:
|
||||
irq = __gpio_group_irq(5) + IRQ_GPIO_0 + 160;
|
||||
break;
|
||||
case IRQ_DMAC0:
|
||||
case IRQ_DMAC1:
|
||||
irq = __dmac_get_irq() + IRQ_DMA_0;
|
||||
break;
|
||||
}
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
asmlinkage void plat_irq_dispatch(void)
|
||||
{
|
||||
int irq = 0;
|
||||
static unsigned long intc_ipr = 0;
|
||||
|
||||
intc_ipr |= REG_INTC_IPR;
|
||||
|
||||
if (!intc_ipr) return;
|
||||
|
||||
irq = ffs(intc_ipr) - 1;
|
||||
intc_ipr &= ~(1<<irq);
|
||||
|
||||
irq = plat_real_irq(irq);
|
||||
do_IRQ(irq);
|
||||
}
|
||||
166
target/linux/xburst/files-2.6.27/arch/mips/jz4760/platform.c
Executable file
166
target/linux/xburst/files-2.6.27/arch/mips/jz4760/platform.c
Executable file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Platform device support for Jz4760 SoC.
|
||||
*
|
||||
* Copyright 2007, <yliu@ingenic.cn>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/resource.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
#include <linux/usb/musb.h>
|
||||
|
||||
#if 0
|
||||
/* OHCI (USB full speed host controller) */
|
||||
static struct resource jz_usb_ohci_resources[] = {
|
||||
[0] = {
|
||||
.start = CPHYSADDR(UHC_BASE), // phys addr for ioremap
|
||||
.end = CPHYSADDR(UHC_BASE) + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_UHC,
|
||||
.end = IRQ_UHC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
/* The dmamask must be set for OHCI to work */
|
||||
static u64 ohci_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device jz_usb_ohci_device = {
|
||||
.name = "jz-ohci",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &ohci_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz_usb_ohci_resources),
|
||||
.resource = jz_usb_ohci_resources,
|
||||
};
|
||||
#endif
|
||||
|
||||
/*** LCD controller ***/
|
||||
static struct resource jz_lcd_resources[] = {
|
||||
[0] = {
|
||||
.start = CPHYSADDR(LCD_BASE),
|
||||
.end = CPHYSADDR(LCD_BASE) + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_LCD,
|
||||
.end = IRQ_LCD,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
||||
static u64 jz_lcd_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device jz_lcd_device = {
|
||||
.name = "jz-lcd",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &jz_lcd_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz_lcd_resources),
|
||||
.resource = jz_lcd_resources,
|
||||
};
|
||||
|
||||
/* USB OTG Controller */
|
||||
static struct musb_hdrc_config jz_usb_otg_config = {
|
||||
.multipoint = 0,
|
||||
.dyn_fifo = 0,
|
||||
.soft_con = 1,
|
||||
.dma = 1,
|
||||
.num_eps = 5,
|
||||
.dma_channels = 5,
|
||||
};
|
||||
|
||||
static struct musb_hdrc_platform_data jz_usb_otg_platform_data = {
|
||||
#if defined(CONFIG_USB_MUSB_OTG)
|
||||
.mode = MUSB_OTG,
|
||||
#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
|
||||
.mode = MUSB_HOST,
|
||||
#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
|
||||
.mode = MUSB_PERIPHERAL,
|
||||
#endif
|
||||
.config = &jz_usb_otg_config,
|
||||
};
|
||||
|
||||
static struct resource jz_usb_otg_resources[] = {
|
||||
[0] = {
|
||||
.start = CPHYSADDR(UDC_BASE),
|
||||
.end = CPHYSADDR(UDC_BASE) + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_OTG,
|
||||
.end = IRQ_OTG,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static u64 usb_otg_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device jz_usb_otg_device = {
|
||||
.name = "musb_hdrc",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &usb_otg_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
.platform_data = &jz_usb_otg_platform_data,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz_usb_otg_resources),
|
||||
.resource = jz_usb_otg_resources,
|
||||
};
|
||||
|
||||
/** MMC/SD controller **/
|
||||
static struct resource jz_mmc_resources[] = {
|
||||
[0] = {
|
||||
.start = CPHYSADDR(MSC0_BASE),
|
||||
.end = CPHYSADDR(MSC0_BASE) + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_MSC0,
|
||||
.end = IRQ_MSC0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
||||
static u64 jz_mmc_dmamask = ~(u32)0;
|
||||
|
||||
static struct platform_device jz_mmc_device = {
|
||||
.name = "jz-mmc",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &jz_mmc_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz_mmc_resources),
|
||||
.resource = jz_mmc_resources,
|
||||
};
|
||||
|
||||
/* All */
|
||||
static struct platform_device *jz_platform_devices[] __initdata = {
|
||||
// &jz_usb_ohci_device,
|
||||
&jz_usb_otg_device,
|
||||
&jz_lcd_device,
|
||||
&jz_mmc_device,
|
||||
};
|
||||
|
||||
static int __init jz_platform_init(void)
|
||||
{
|
||||
return platform_add_devices(jz_platform_devices, ARRAY_SIZE(jz_platform_devices));
|
||||
}
|
||||
|
||||
arch_initcall(jz_platform_init);
|
||||
461
target/linux/xburst/files-2.6.27/arch/mips/jz4760/pm.c
Executable file
461
target/linux/xburst/files-2.6.27/arch/mips/jz4760/pm.c
Executable file
@@ -0,0 +1,461 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4760/common/pm.c
|
||||
*
|
||||
* JZ4760 Power Management Routines
|
||||
*
|
||||
* Copyright (C) 2006 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can distribute it and/or modify it
|
||||
* under the terms of the GNU General Public License (Version 2) as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/pm_legacy.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/sysctl.h>
|
||||
|
||||
#include <asm/cacheops.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
#undef DEBUG
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
#define dprintk(x...) printk(x)
|
||||
#else
|
||||
#define dprintk(x...)
|
||||
#endif
|
||||
|
||||
#define GPIO_PORT_NUM 6
|
||||
|
||||
/*
|
||||
* __gpio_as_sleep set all pins to pull-disable, and set all pins as input
|
||||
* except sdram and the pins which can be used as CS1_N to CS4_N for chip select.
|
||||
*/
|
||||
#define __gpio_as_sleep() \
|
||||
do { \
|
||||
REG_GPIO_PXFUNC(1) = ~0x03ff7fff; \
|
||||
REG_GPIO_PXSELC(1) = ~0x03ff7fff; \
|
||||
REG_GPIO_PXDIRC(1) = ~0x03ff7fff; \
|
||||
REG_GPIO_PXPES(1) = 0xffffffff; \
|
||||
REG_GPIO_PXFUNC(2) = ~0x01e00000; \
|
||||
REG_GPIO_PXSELC(2) = ~0x01e00000; \
|
||||
REG_GPIO_PXDIRC(2) = ~0x01e00000; \
|
||||
REG_GPIO_PXPES(2) = 0xffffffff; \
|
||||
REG_GPIO_PXFUNC(3) = 0xffffffff; \
|
||||
REG_GPIO_PXSELC(3) = 0xffffffff; \
|
||||
REG_GPIO_PXDIRC(3) = 0xffffffff; \
|
||||
REG_GPIO_PXPES(3) = 0xffffffff; \
|
||||
REG_GPIO_PXFUNC(4) = 0xffffffff; \
|
||||
REG_GPIO_PXSELC(4) = 0xffffffff; \
|
||||
REG_GPIO_PXDIRC(4) = 0xffffffff; \
|
||||
REG_GPIO_PXPES(4) = 0xffffffff; \
|
||||
REG_GPIO_PXFUNC(5) = 0xffffffff; \
|
||||
REG_GPIO_PXSELC(5) = 0xffffffff; \
|
||||
REG_GPIO_PXDIRC(5) = 0xffffffff; \
|
||||
REG_GPIO_PXPES(5) = 0xffffffff; \
|
||||
} while (0)
|
||||
|
||||
static int jz_pm_do_hibernate(void)
|
||||
{
|
||||
printk("Put CPU into hibernate mode.\n");
|
||||
|
||||
/* Mask all interrupts */
|
||||
REG_INTC_IMSR = 0xffffffff;
|
||||
|
||||
/*
|
||||
* RTC Wakeup or 1Hz interrupt can be enabled or disabled
|
||||
* through RTC driver's ioctl (linux/driver/char/rtc_jz.c).
|
||||
*/
|
||||
|
||||
/* Set minimum wakeup_n pin low-level assertion time for wakeup: 100ms */
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
REG_RTC_HWFCR = (100 << RTC_HWFCR_BIT);
|
||||
|
||||
/* Set reset pin low-level assertion time after wakeup: must > 60ms */
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
REG_RTC_HRCR = (60 << RTC_HRCR_BIT); /* 60 ms */
|
||||
|
||||
/* Scratch pad register to be reserved */
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
REG_RTC_HSPR = 0x12345678;
|
||||
|
||||
/* clear wakeup status register */
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
REG_RTC_HWRSR = 0x0;
|
||||
|
||||
/* Put CPU to power down mode */
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
REG_RTC_HCR = RTC_HCR_PD;
|
||||
|
||||
while (!(REG_RTC_RCR & RTC_RCR_WRDY));
|
||||
while(1);
|
||||
|
||||
/* We can't get here */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* NOTES:
|
||||
* 1: Pins that are floated (NC) should be set as input and pull-enable.
|
||||
* 2: Pins that are pull-up or pull-down by outside should be set as input
|
||||
* and pull-disable.
|
||||
* 3: Pins that are connected to a chip except sdram and nand flash
|
||||
* should be set as input and pull-disable, too.
|
||||
*/
|
||||
static void jz_board_do_sleep(unsigned long *ptr)
|
||||
{
|
||||
unsigned char i;
|
||||
|
||||
/* Print messages of GPIO registers for debug */
|
||||
for(i=0;i<GPIO_PORT_NUM;i++) {
|
||||
dprintk("run dat:%x pin:%x fun:%x sel:%x dir:%x pull:%x msk:%x trg:%x\n", \
|
||||
REG_GPIO_PXDAT(i),REG_GPIO_PXPIN(i),REG_GPIO_PXFUN(i),REG_GPIO_PXSEL(i), \
|
||||
REG_GPIO_PXDIR(i),REG_GPIO_PXPE(i),REG_GPIO_PXIM(i),REG_GPIO_PXTRG(i));
|
||||
}
|
||||
|
||||
/* Save GPIO registers */
|
||||
for(i = 1; i < GPIO_PORT_NUM; i++) {
|
||||
*ptr++ = REG_GPIO_PXFUN(i);
|
||||
*ptr++ = REG_GPIO_PXSEL(i);
|
||||
*ptr++ = REG_GPIO_PXDIR(i);
|
||||
*ptr++ = REG_GPIO_PXPE(i);
|
||||
*ptr++ = REG_GPIO_PXIM(i);
|
||||
*ptr++ = REG_GPIO_PXDAT(i);
|
||||
*ptr++ = REG_GPIO_PXTRG(i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set all pins to pull-disable, and set all pins as input except
|
||||
* sdram and the pins which can be used as CS1_N to CS4_N for chip select.
|
||||
*/
|
||||
__gpio_as_sleep();
|
||||
|
||||
/*
|
||||
* Set proper status for GPC21 to GPC24 which can be used as CS1_N to CS4_N.
|
||||
* Keep the pins' function used for chip select(CS) here according to your
|
||||
* system to avoid chip select crashing with sdram when resuming from sleep mode.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_JZ4760_APUS)
|
||||
/* GPB25/CS1_N is used as chip select for nand flash, shouldn't be change. */
|
||||
|
||||
/* GPB26/CS2_N is connected to nand flash, needn't be changed. */
|
||||
|
||||
/* GPB28/CS3_N is used as cs8900's chip select, shouldn't be changed. */
|
||||
|
||||
/* GPB27/CS4_N is used as NOR's chip select, shouldn't be changed. */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Enable pull for NC pins here according to your system
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_JZ4760_APUS)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If you must set some GPIOs as output to high level or low level,
|
||||
* you can set them here, using:
|
||||
* __gpio_as_output(n);
|
||||
* __gpio_set_pin(n); or __gpio_clear_pin(n);
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_JZ4760_APUS)
|
||||
/* GPC7 which is used as AMPEN_N should be set to high to disable audio amplifier */
|
||||
__gpio_as_output(32*2+7);
|
||||
__gpio_set_pin(32*2+7);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Keep uart function for printing debug message */
|
||||
__gpio_as_uart0();
|
||||
__gpio_as_uart1();
|
||||
__gpio_as_uart2();
|
||||
__gpio_as_uart3();
|
||||
|
||||
/* Print messages of GPIO registers for debug */
|
||||
for(i=0;i<GPIO_PORT_NUM;i++) {
|
||||
dprintk("sleep dat:%x pin:%x fun:%x sel:%x dir:%x pull:%x msk:%x trg:%x\n", \
|
||||
REG_GPIO_PXDAT(i),REG_GPIO_PXPIN(i),REG_GPIO_PXFUN(i),REG_GPIO_PXSEL(i), \
|
||||
REG_GPIO_PXDIR(i),REG_GPIO_PXPE(i),REG_GPIO_PXIM(i),REG_GPIO_PXTRG(i));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void jz_board_do_resume(unsigned long *ptr)
|
||||
{
|
||||
unsigned char i;
|
||||
|
||||
/* Restore GPIO registers */
|
||||
for(i = 1; i < GPIO_PORT_NUM; i++) {
|
||||
REG_GPIO_PXFUNS(i) = *ptr;
|
||||
REG_GPIO_PXFUNC(i) = ~(*ptr++);
|
||||
|
||||
REG_GPIO_PXSELS(i) = *ptr;
|
||||
REG_GPIO_PXSELC(i) = ~(*ptr++);
|
||||
|
||||
REG_GPIO_PXDIRS(i) = *ptr;
|
||||
REG_GPIO_PXDIRC(i) = ~(*ptr++);
|
||||
|
||||
REG_GPIO_PXPES(i) = *ptr;
|
||||
REG_GPIO_PXPEC(i) = ~(*ptr++);
|
||||
|
||||
REG_GPIO_PXIMS(i)=*ptr;
|
||||
REG_GPIO_PXIMC(i)=~(*ptr++);
|
||||
|
||||
REG_GPIO_PXDATS(i)=*ptr;
|
||||
REG_GPIO_PXDATC(i)=~(*ptr++);
|
||||
|
||||
REG_GPIO_PXTRGS(i)=*ptr;
|
||||
REG_GPIO_PXTRGC(i)=~(*ptr++);
|
||||
}
|
||||
|
||||
/* Print messages of GPIO registers for debug */
|
||||
for(i=0;i<GPIO_PORT_NUM;i++) {
|
||||
dprintk("resume dat:%x pin:%x fun:%x sel:%x dir:%x pull:%x msk:%x trg:%x\n", \
|
||||
REG_GPIO_PXDAT(i),REG_GPIO_PXPIN(i),REG_GPIO_PXFUN(i),REG_GPIO_PXSEL(i), \
|
||||
REG_GPIO_PXDIR(i),REG_GPIO_PXPE(i),REG_GPIO_PXIM(i),REG_GPIO_PXTRG(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int jz_pm_do_sleep(void)
|
||||
{
|
||||
unsigned long delta;
|
||||
unsigned long nfcsr = REG_EMC_NFCSR;
|
||||
unsigned long opcr = REG_CPM_OPCR;
|
||||
unsigned long imr = REG_INTC_IMR;
|
||||
unsigned long sadc = REG_SADC_ENA;
|
||||
unsigned long sleep_gpio_save[7*(GPIO_PORT_NUM-1)];
|
||||
|
||||
printk("Put CPU into sleep mode.\n");
|
||||
|
||||
/* Preserve current time */
|
||||
delta = xtime.tv_sec - REG_RTC_RSR;
|
||||
|
||||
/* Disable nand flash */
|
||||
REG_EMC_NFCSR = ~0xff;
|
||||
|
||||
/* stop sadc */
|
||||
REG_SADC_ENA &= ~0x7;
|
||||
while((REG_SADC_ENA & 0x7) != 0);
|
||||
udelay(100);
|
||||
|
||||
/*stop udc and usb*/
|
||||
__cpm_suspend_uhcphy();
|
||||
__cpm_suspend_udcphy();
|
||||
|
||||
/* Sleep on-board modules */
|
||||
jz_board_do_sleep(sleep_gpio_save);
|
||||
|
||||
/* Mask all interrupts */
|
||||
REG_INTC_IMSR = 0xffffffff;
|
||||
|
||||
/* Just allow following interrupts to wakeup the system.
|
||||
* Note: modify this according to your system.
|
||||
*/
|
||||
|
||||
/* enable RTC alarm */
|
||||
__intc_unmask_irq(IRQ_RTC);
|
||||
#if 0
|
||||
/* make system wake up after n seconds by RTC alarm */
|
||||
unsigned int v, n;
|
||||
n = 10;
|
||||
while (!__rtc_write_ready());
|
||||
__rtc_enable_alarm();
|
||||
while (!__rtc_write_ready());
|
||||
__rtc_enable_alarm_irq();
|
||||
while (!__rtc_write_ready());
|
||||
v = __rtc_get_second();
|
||||
while (!__rtc_write_ready());
|
||||
__rtc_set_alarm_second(v+n);
|
||||
#endif
|
||||
|
||||
/* WAKEUP key */
|
||||
__gpio_as_irq_rise_edge(GPIO_WAKEUP);
|
||||
__gpio_unmask_irq(GPIO_WAKEUP);
|
||||
__intc_unmask_irq(IRQ_GPIO0 - (GPIO_WAKEUP/32)); /* unmask IRQ_GPIOn depends on GPIO_WAKEUP */
|
||||
|
||||
/* disable externel clock Oscillator in sleep mode */
|
||||
__cpm_disable_osc_in_sleep();
|
||||
/* select 32K crystal as RTC clock in sleep mode */
|
||||
__cpm_select_rtcclk_rtc();
|
||||
|
||||
/* Enter SLEEP mode */
|
||||
REG_CPM_LCR &= ~CPM_LCR_LPM_MASK;
|
||||
REG_CPM_LCR |= CPM_LCR_LPM_SLEEP;
|
||||
__asm__(".set\tmips3\n\t"
|
||||
"wait\n\t"
|
||||
".set\tmips0");
|
||||
|
||||
/* Restore to IDLE mode */
|
||||
REG_CPM_LCR &= ~CPM_LCR_LPM_MASK;
|
||||
REG_CPM_LCR |= CPM_LCR_LPM_IDLE;
|
||||
|
||||
/* Restore nand flash control register */
|
||||
REG_EMC_NFCSR = nfcsr;
|
||||
|
||||
/* Restore interrupts */
|
||||
REG_INTC_IMSR = imr;
|
||||
REG_INTC_IMCR = ~imr;
|
||||
|
||||
/* Restore sadc */
|
||||
REG_SADC_ENA = sadc;
|
||||
|
||||
/* Resume on-board modules */
|
||||
jz_board_do_resume(sleep_gpio_save);
|
||||
|
||||
/* Restore Oscillator and Power Control Register */
|
||||
REG_CPM_OPCR = opcr;
|
||||
|
||||
/* Restore current time */
|
||||
xtime.tv_sec = REG_RTC_RSR + delta;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Put CPU to HIBERNATE mode */
|
||||
int jz_pm_hibernate(void)
|
||||
{
|
||||
return jz_pm_do_hibernate();
|
||||
}
|
||||
|
||||
#ifndef CONFIG_JZ_POWEROFF
|
||||
static irqreturn_t pm_irq_handler (int irq, void *dev_id)
|
||||
{
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Put CPU to SLEEP mode */
|
||||
int jz_pm_sleep(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
#ifndef CONFIG_JZ_POWEROFF
|
||||
if ((retval = request_irq (IRQ_GPIO_0 + GPIO_WAKEUP, pm_irq_handler, IRQF_DISABLED,
|
||||
"PM", NULL))) {
|
||||
printk ("PM could not get IRQ for GPIO_WAKEUP\n");
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
pm_send_all(PM_SUSPEND, (void *)3);
|
||||
retval = jz_pm_do_sleep();
|
||||
pm_send_all(PM_RESUME, (void *)0);
|
||||
|
||||
#ifndef CONFIG_JZ_POWEROFF
|
||||
free_irq (IRQ_GPIO_0 + GPIO_WAKEUP, NULL);
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Deprecated ,was used by dpm */
|
||||
void jz_pm_idle(void)
|
||||
{
|
||||
local_irq_disable();
|
||||
if (!need_resched()) {
|
||||
local_irq_enable();
|
||||
cpu_wait();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
|
||||
/*
|
||||
* Use a temporary sysctl number. Horrid, but will be cleaned up in 2.6
|
||||
* when all the PM interfaces exist nicely.
|
||||
*/
|
||||
#define CTL_PM_SUSPEND 1
|
||||
#define CTL_PM_HIBERNATE 2
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Power Management sleep sysctl proc interface
|
||||
*
|
||||
* A write to /proc/sys/pm/suspend invokes this function
|
||||
* which initiates a sleep.
|
||||
*--------------------------------------------------------------------------*/
|
||||
static int sysctl_jz_pm_sleep(void)
|
||||
{
|
||||
return jz_pm_sleep();
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Power Management sleep sysctl proc interface
|
||||
*
|
||||
* A write to /proc/sys/pm/hibernate invokes this function
|
||||
* which initiates a poweroff.
|
||||
*--------------------------------------------------------------------------*/
|
||||
static int sysctl_jz_pm_hibernate(void)
|
||||
{
|
||||
return jz_pm_hibernate();
|
||||
}
|
||||
|
||||
static struct ctl_table pm_table[] =
|
||||
{
|
||||
{
|
||||
.ctl_name = CTL_UNNUMBERED,
|
||||
.procname = "suspend",
|
||||
.data = NULL,
|
||||
.maxlen = 0,
|
||||
.mode = 0600,
|
||||
.proc_handler = &sysctl_jz_pm_sleep,
|
||||
},
|
||||
{
|
||||
.ctl_name = CTL_UNNUMBERED,
|
||||
.procname = "hibernate",
|
||||
.data = NULL,
|
||||
.maxlen = 0,
|
||||
.mode = 0600,
|
||||
.proc_handler = &sysctl_jz_pm_hibernate,
|
||||
},
|
||||
{ .ctl_name = 0}
|
||||
};
|
||||
|
||||
static struct ctl_table pm_dir_table[] =
|
||||
{
|
||||
{
|
||||
.ctl_name = CTL_UNNUMBERED,
|
||||
.procname = "pm",
|
||||
.mode = 0555,
|
||||
.child = pm_table,
|
||||
},
|
||||
{ .ctl_name = 0}
|
||||
};
|
||||
|
||||
#endif /* CONFIG_SYSCTL */
|
||||
|
||||
/*
|
||||
* Initialize power interface
|
||||
*/
|
||||
static int __init jz_pm_init(void)
|
||||
{
|
||||
printk("Power Management for JZ\n");
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
register_sysctl_table(pm_dir_table);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(jz_pm_init);
|
||||
885
target/linux/xburst/files-2.6.27/arch/mips/jz4760/proc.c
Executable file
885
target/linux/xburst/files-2.6.27/arch/mips/jz4760/proc.c
Executable file
@@ -0,0 +1,885 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4760/proc.c
|
||||
*
|
||||
* /proc/jz/ procfs for jz4760 on-chip modules.
|
||||
*
|
||||
* Copyright (C) 2006 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can distribute it and/or modify it
|
||||
* under the terms of the GNU General Public License (Version 2) as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/page-flags.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
//#define DEBUG 1
|
||||
#undef DEBUG
|
||||
|
||||
|
||||
struct proc_dir_entry *proc_jz_root;
|
||||
|
||||
|
||||
/*
|
||||
* EMC Modules
|
||||
*/
|
||||
static int emc_read_proc (char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
len += sprintf (page+len, "SMCR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SMCR0, REG_EMC_SMCR1, REG_EMC_SMCR2, REG_EMC_SMCR3, REG_EMC_SMCR4);
|
||||
len += sprintf (page+len, "SACR(0-5): 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", REG_EMC_SACR0, REG_EMC_SACR1, REG_EMC_SACR2, REG_EMC_SACR3, REG_EMC_SACR4);
|
||||
len += sprintf (page+len, "DMCR: 0x%08x\n", REG_EMC_DMCR);
|
||||
len += sprintf (page+len, "RTCSR: 0x%04x\n", REG_EMC_RTCSR);
|
||||
len += sprintf (page+len, "RTCOR: 0x%04x\n", REG_EMC_RTCOR);
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Power Manager Module
|
||||
*/
|
||||
static int pmc_read_proc (char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
unsigned long lcr = REG_CPM_LCR;
|
||||
unsigned long clkgr = REG_CPM_CLKGR;
|
||||
|
||||
len += sprintf (page+len, "Low Power Mode : %s\n",
|
||||
((lcr & CPM_LCR_LPM_MASK) == (CPM_LCR_LPM_IDLE)) ?
|
||||
"IDLE" : (((lcr & CPM_LCR_LPM_MASK) == (CPM_LCR_LPM_SLEEP)) ?
|
||||
"SLEEP" : "HIBERNATE"));
|
||||
len += sprintf (page+len, "Doze Mode : %s\n",
|
||||
(lcr & CPM_LCR_DOZE_ON) ? "on" : "off");
|
||||
if (lcr & CPM_LCR_DOZE_ON)
|
||||
len += sprintf (page+len, " duty : %d\n", (int)((lcr & CPM_LCR_DOZE_DUTY_MASK) >> CPM_LCR_DOZE_DUTY_BIT));
|
||||
len += sprintf (page+len, "AUX_CPU : %s\n",
|
||||
(clkgr & CPM_CLKGR_AUX_CPU) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "AHB1 : %s\n",
|
||||
(clkgr & CPM_CLKGR_AHB1) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "IDCT : %s\n",
|
||||
(clkgr & CPM_CLKGR_IDCT) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "DB : %s\n",
|
||||
(clkgr & CPM_CLKGR_DB) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "ME : %s\n",
|
||||
(clkgr & CPM_CLKGR_ME) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "MC : %s\n",
|
||||
(clkgr & CPM_CLKGR_MC) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "TVE : %s\n",
|
||||
(clkgr & CPM_CLKGR_TVE) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "TSSI : %s\n",
|
||||
(clkgr & CPM_CLKGR_TSSI) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "IPU : %s\n",
|
||||
(clkgr & CPM_CLKGR_IPU) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "DMAC : %s\n",
|
||||
(clkgr & CPM_CLKGR_DMAC) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "UDC : %s\n",
|
||||
(clkgr & CPM_CLKGR_UDC) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "LCD : %s\n",
|
||||
(clkgr & CPM_CLKGR_LCD) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "CIM : %s\n",
|
||||
(clkgr & CPM_CLKGR_CIM) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "SADC : %s\n",
|
||||
(clkgr & CPM_CLKGR_SADC) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "MSC0 : %s\n",
|
||||
(clkgr & CPM_CLKGR_MSC0) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "MSC1 : %s\n",
|
||||
(clkgr & CPM_CLKGR_MSC1) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "SSI : %s\n",
|
||||
(clkgr & CPM_CLKGR_SSI) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "I2C : %s\n",
|
||||
(clkgr & CPM_CLKGR_I2C) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "RTC : %s\n",
|
||||
(clkgr & CPM_CLKGR_RTC) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "TCU : %s\n",
|
||||
(clkgr & CPM_CLKGR_TCU) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "UART1 : %s\n",
|
||||
(clkgr & CPM_CLKGR_UART1) ? "stopped" : "running");
|
||||
len += sprintf (page+len, "UART0 : %s\n",
|
||||
(clkgr & CPM_CLKGR_UART0) ? "stopped" : "running");
|
||||
return len;
|
||||
}
|
||||
|
||||
static int pmc_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
|
||||
{
|
||||
REG_CPM_CLKGR = simple_strtoul(buffer, 0, 16);
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clock Generation Module
|
||||
*/
|
||||
#define TO_MHZ(x) (x/1000000),(x%1000000)/10000
|
||||
#define TO_KHZ(x) (x/1000),(x%1000)/10
|
||||
|
||||
static int cgm_read_proc (char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
unsigned int cppcr = REG_CPM_CPPCR; /* PLL Control Register */
|
||||
unsigned int cpccr = REG_CPM_CPCCR; /* Clock Control Register */
|
||||
unsigned int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
|
||||
unsigned int od[4] = {1, 2, 2, 4};
|
||||
|
||||
len += sprintf (page+len, "CPPCR : 0x%08x\n", cppcr);
|
||||
len += sprintf (page+len, "CPCCR : 0x%08x\n", cpccr);
|
||||
len += sprintf (page+len, "PLL : %s\n",
|
||||
(cppcr & CPM_CPPCR_PLLEN) ? "ON" : "OFF");
|
||||
len += sprintf (page+len, "m:n:o : %d:%d:%d\n",
|
||||
__cpm_get_pllm() + 2,
|
||||
__cpm_get_plln() + 2,
|
||||
od[__cpm_get_pllod()]
|
||||
);
|
||||
len += sprintf (page+len, "C:H:M:P : %d:%d:%d:%d\n",
|
||||
div[__cpm_get_cdiv()],
|
||||
div[__cpm_get_hdiv()],
|
||||
div[__cpm_get_mdiv()],
|
||||
div[__cpm_get_pdiv()]
|
||||
);
|
||||
len += sprintf (page+len, "PLL Freq : %3d.%02d MHz\n", TO_MHZ(__cpm_get_pllout()));
|
||||
len += sprintf (page+len, "CCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_cclk()));
|
||||
len += sprintf (page+len, "H0CLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_h0clk()));
|
||||
len += sprintf (page+len, "MCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mclk()));
|
||||
len += sprintf (page+len, "PCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_pclk()));
|
||||
len += sprintf (page+len, "H1CLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_h1clk()));
|
||||
len += sprintf (page+len, "PIXCLK : %3d.%02d KHz\n", TO_KHZ(__cpm_get_pixclk()));
|
||||
len += sprintf (page+len, "I2SCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_i2sclk()));
|
||||
len += sprintf (page+len, "USBCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_usbclk()));
|
||||
len += sprintf (page+len, "MSC0CLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mscclk(0)));
|
||||
len += sprintf (page+len, "MSC1CLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_mscclk(1)));
|
||||
len += sprintf (page+len, "EXTALCLK0 : %3d.%02d MHz\n", TO_MHZ(__cpm_get_extalclk0()));
|
||||
len += sprintf (page+len, "EXTALCLK(by CPM): %3d.%02d MHz\n", TO_MHZ(__cpm_get_extalclk()));
|
||||
len += sprintf (page+len, "RTCCLK : %3d.%02d MHz\n", TO_MHZ(__cpm_get_rtcclk()));
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int cgm_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
|
||||
{
|
||||
REG_CPM_CPCCR = simple_strtoul(buffer, 0, 16);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/* USAGE:
|
||||
* echo n > /proc/jz/ipu // n = [1,...,9], alloc mem, 2^n pages.
|
||||
* echo FF > /proc/jz/ipu // 255, free all buffer
|
||||
* echo xxxx > /proc/jz/ipu // free buffer which addr is xxxx
|
||||
* echo llll > /proc/jz/ipu // add_wired_entry(l,l,l,l)
|
||||
* echo 0 > /proc/jz/ipu // debug, print ipu_buf
|
||||
* od -X /proc/jz/ipu // read mem addr
|
||||
*/
|
||||
|
||||
typedef struct _ipu_buf {
|
||||
unsigned int addr; /* phys addr */
|
||||
unsigned int page_shift;
|
||||
} ipu_buf_t;
|
||||
|
||||
#define IPU_BUF_MAX 4 /* 4 buffers */
|
||||
|
||||
static struct _ipu_buf ipu_buf[IPU_BUF_MAX];
|
||||
static int ipu_buf_cnt = 0;
|
||||
static unsigned char g_asid=0;
|
||||
|
||||
extern void local_flush_tlb_all(void);
|
||||
|
||||
/* CP0 hazard avoidance. */
|
||||
#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \
|
||||
"nop; nop; nop; nop; nop; nop;\n\t" \
|
||||
".set reorder\n\t")
|
||||
void show_tlb(void)
|
||||
{
|
||||
#define ASID_MASK 0xFF
|
||||
|
||||
unsigned long flags;
|
||||
unsigned int old_ctx;
|
||||
unsigned int entry;
|
||||
unsigned int entrylo0, entrylo1, entryhi;
|
||||
unsigned int pagemask;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
/* Save old context */
|
||||
old_ctx = (read_c0_entryhi() & 0xff);
|
||||
|
||||
printk("TLB content:\n");
|
||||
entry = 0;
|
||||
while(entry < 32) {
|
||||
write_c0_index(entry);
|
||||
BARRIER;
|
||||
tlb_read();
|
||||
BARRIER;
|
||||
entryhi = read_c0_entryhi();
|
||||
entrylo0 = read_c0_entrylo0();
|
||||
entrylo1 = read_c0_entrylo1();
|
||||
pagemask = read_c0_pagemask();
|
||||
printk("%02d: ASID=%02d%s VA=0x%08x ", entry, entryhi & ASID_MASK, (entrylo0 & entrylo1 & 1) ? "(G)" : " ", entryhi & ~ASID_MASK);
|
||||
printk("PA0=0x%08x C0=%x %s%s%s\n", (entrylo0>>6)<<12, (entrylo0>>3) & 7, (entrylo0 & 4) ? "Dirty " : "", (entrylo0 & 2) ? "Valid " : "Invalid ", (entrylo0 & 1) ? "Global" : "");
|
||||
printk("\t\t\t PA1=0x%08x C1=%x %s%s%s\n", (entrylo1>>6)<<12, (entrylo1>>3) & 7, (entrylo1 & 4) ? "Dirty " : "", (entrylo1 & 2) ? "Valid " : "Invalid ", (entrylo1 & 1) ? "Global" : "");
|
||||
|
||||
printk("\t\tpagemask=0x%08x", pagemask);
|
||||
printk("\tentryhi=0x%08x\n", entryhi);
|
||||
printk("\t\tentrylo0=0x%08x", entrylo0);
|
||||
printk("\tentrylo1=0x%08x\n", entrylo1);
|
||||
|
||||
entry++;
|
||||
}
|
||||
BARRIER;
|
||||
write_c0_entryhi(old_ctx);
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void ipu_add_wired_entry(unsigned long pid,
|
||||
unsigned long entrylo0, unsigned long entrylo1,
|
||||
unsigned long entryhi, unsigned long pagemask)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long wired;
|
||||
unsigned long old_pagemask;
|
||||
unsigned long old_ctx;
|
||||
struct task_struct *g, *p;
|
||||
|
||||
/* We will lock an 4MB page size entry to map the 4MB reserved IPU memory */
|
||||
wired = read_c0_wired();
|
||||
if (wired) return;
|
||||
|
||||
do_each_thread(g, p) {
|
||||
if (p->pid == pid )
|
||||
g_asid = p->mm->context[0];
|
||||
} while_each_thread(g, p);
|
||||
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
entrylo0 = entrylo0 >> 6; /* PFN */
|
||||
entrylo0 |= 0x6 | (0 << 3); /* Write-through cacheable, dirty, valid */
|
||||
|
||||
/* Save old context and create impossible VPN2 value */
|
||||
old_ctx = read_c0_entryhi() & 0xff;
|
||||
old_pagemask = read_c0_pagemask();
|
||||
wired = read_c0_wired();
|
||||
write_c0_wired(wired + 1);
|
||||
write_c0_index(wired);
|
||||
BARRIER;
|
||||
entryhi &= ~0xff; /* new add, 20070906 */
|
||||
entryhi |= g_asid; /* new add, 20070906 */
|
||||
// entryhi |= old_ctx; /* new add, 20070906 */
|
||||
write_c0_pagemask(pagemask);
|
||||
write_c0_entryhi(entryhi);
|
||||
write_c0_entrylo0(entrylo0);
|
||||
write_c0_entrylo1(entrylo1);
|
||||
BARRIER;
|
||||
tlb_write_indexed();
|
||||
BARRIER;
|
||||
|
||||
write_c0_entryhi(old_ctx);
|
||||
BARRIER;
|
||||
write_c0_pagemask(old_pagemask);
|
||||
local_flush_tlb_all();
|
||||
local_irq_restore(flags);
|
||||
#if defined(DEBUG)
|
||||
printk("\nold_ctx=%03d\n", old_ctx);
|
||||
|
||||
show_tlb();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ipu_del_wired_entry( void )
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long wired;
|
||||
|
||||
local_irq_save(flags);
|
||||
wired = read_c0_wired();
|
||||
if ( wired > 0 ) {
|
||||
write_c0_wired(wired - 1);
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static inline void ipu_buf_get( unsigned int page_shift )
|
||||
{
|
||||
unsigned char * virt_addr;
|
||||
int i;
|
||||
for ( i=0; i< IPU_BUF_MAX; ++i ) {
|
||||
if ( ipu_buf[i].addr == 0 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( (ipu_buf_cnt = i) == IPU_BUF_MAX ) {
|
||||
printk("Error, no free ipu buffer.\n");
|
||||
return ;
|
||||
}
|
||||
|
||||
virt_addr = (unsigned char *)__get_free_pages(GFP_KERNEL, page_shift);
|
||||
|
||||
if ( virt_addr ) {
|
||||
ipu_buf[ipu_buf_cnt].addr = (unsigned int)virt_to_phys((void *)virt_addr);
|
||||
ipu_buf[ipu_buf_cnt].page_shift = page_shift;
|
||||
|
||||
for (i = 0; i < (1<<page_shift); i++) {
|
||||
SetPageReserved(virt_to_page(virt_addr));
|
||||
virt_addr += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
printk("get memory Failed.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ipu_buf_free( unsigned int phys_addr )
|
||||
{
|
||||
unsigned char * virt_addr, *addr;
|
||||
int cnt, i;
|
||||
|
||||
if ( phys_addr == 0 )
|
||||
return ;
|
||||
|
||||
for ( cnt=0; cnt<IPU_BUF_MAX; ++cnt )
|
||||
if ( phys_addr == ipu_buf[cnt].addr )
|
||||
break;
|
||||
|
||||
if ( cnt == IPU_BUF_MAX ) { /* addr not in the ipu buffers */
|
||||
printk("Invalid addr:0x%08x\n", (unsigned int)phys_addr);
|
||||
}
|
||||
|
||||
virt_addr = (unsigned char *)phys_to_virt(ipu_buf[cnt].addr);
|
||||
addr = virt_addr;
|
||||
for (i = 0; i < (1<<ipu_buf[cnt].page_shift); i++) {
|
||||
ClearPageReserved(virt_to_page(addr));
|
||||
addr += PAGE_SIZE;
|
||||
}
|
||||
|
||||
if ( cnt == 0 )
|
||||
ipu_del_wired_entry();
|
||||
|
||||
free_pages((unsigned long )virt_addr, ipu_buf[cnt].page_shift);
|
||||
|
||||
ipu_buf[cnt].addr = 0;
|
||||
ipu_buf[cnt].page_shift = 0;
|
||||
}
|
||||
|
||||
static int ipu_read_proc (char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
/* read as binary */
|
||||
unsigned int * pint;
|
||||
pint = (unsigned int *) (page+len);
|
||||
|
||||
if ( ipu_buf_cnt >= IPU_BUF_MAX ) { /* failed alloc mem, rturn 0 */
|
||||
printk("no free buffer.\n");
|
||||
*pint = 0;
|
||||
}
|
||||
else
|
||||
*pint = (unsigned int )ipu_buf[ipu_buf_cnt].addr; /* phys addr */
|
||||
len += sizeof(unsigned int);
|
||||
|
||||
#if defined(DEBUG)
|
||||
show_tlb();
|
||||
#endif
|
||||
return len;
|
||||
|
||||
}
|
||||
|
||||
static int ipu_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
|
||||
{
|
||||
unsigned int val ;
|
||||
int cnt,i;
|
||||
char buf[12];
|
||||
unsigned long pid, entrylo0, entrylo1, entryhi, pagemask;
|
||||
#if defined(DEBUG)
|
||||
printk("ipu write count=%u\n", count);
|
||||
#endif
|
||||
if (count == (8*5+1)) {
|
||||
for (i=0;i<12;i++) buf[i]=0;
|
||||
strncpy(buf, buffer+8*0, 8);
|
||||
pid = simple_strtoul(buf, 0, 16);
|
||||
for (i=0;i<12;i++) buf[i]=0;
|
||||
strncpy(buf, buffer+8*1, 8);
|
||||
entrylo0 = simple_strtoul(buf, 0, 16);
|
||||
for (i=0;i<12;i++) buf[i]=0;
|
||||
strncpy(buf, buffer+8*2, 8);
|
||||
entrylo1 = simple_strtoul(buf, 0, 16);
|
||||
for (i=0;i<12;i++) buf[i]=0;
|
||||
strncpy(buf, buffer+8*3, 8);
|
||||
entryhi = simple_strtoul(buf, 0, 16);
|
||||
for (i=0;i<12;i++) buf[i]=0;
|
||||
strncpy(buf, buffer+8*4, 8);
|
||||
pagemask = simple_strtoul(buf, 0, 16);
|
||||
|
||||
#if defined(DEBUG)
|
||||
printk("pid=0x%08x, entrylo0=0x%08x, entrylo1=0x%08x, entryhi=0x%08x, pagemask=0x%08x\n",
|
||||
pid, entrylo0, entrylo1, entryhi, pagemask);
|
||||
#endif
|
||||
ipu_add_wired_entry( pid, entrylo0, entrylo1, entryhi, pagemask);
|
||||
return 41;
|
||||
}
|
||||
else if ( count <= 8+1 ) {
|
||||
for (i=0;i<12;i++) buf[i]=0;
|
||||
strncpy(buf, buffer, 8);
|
||||
val = simple_strtoul(buf, 0, 16);
|
||||
} else if (count == 44) {
|
||||
for (i = 0; i < 12; i++)
|
||||
buf[i] = 0;
|
||||
strncpy(buf, buffer, 10);
|
||||
pid = simple_strtoul(buf, 0, 16);
|
||||
for (i = 0; i < 12; i++)
|
||||
buf[i] = 0;
|
||||
strncpy(buf, buffer + 11, 10);
|
||||
entryhi = simple_strtoul(buf, 0, 16);//vaddr
|
||||
for (i = 0; i < 12; i++)
|
||||
buf[i] = 0;
|
||||
strncpy(buf, buffer + 22, 10);
|
||||
entrylo0 = simple_strtoul(buf, 0, 16);//paddr
|
||||
for (i = 0; i < 12; i++)
|
||||
buf[i] = 0;
|
||||
strncpy(buf, buffer + 33, 10);
|
||||
pagemask = simple_strtoul(buf, 0, 16);
|
||||
pagemask = 0x3ff << 13; /* Fixed to 4MB page size */
|
||||
ipu_add_wired_entry(pid, entrylo0, 0, entryhi, pagemask);
|
||||
return 44;
|
||||
} else {
|
||||
printk("ipu write count error, count=%d\n.", (unsigned int)count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* val: 1-9, page_shift, val>= 10: ipu_buf.addr */
|
||||
if ( val == 0 ) { /* debug, print ipu_buf info */
|
||||
for ( cnt=0; cnt<IPU_BUF_MAX; ++cnt)
|
||||
printk("ipu_buf[%d]: addr=0x%08x, page_shift=%d\n",
|
||||
cnt, ipu_buf[cnt].addr, ipu_buf[cnt].page_shift );
|
||||
#if defined(DEBUG)
|
||||
show_tlb();
|
||||
#endif
|
||||
}
|
||||
else if ( 0< val && val < 10 ) {
|
||||
ipu_buf_get(val);
|
||||
}
|
||||
else if ( val == 0xff ) { /* 255: free all ipu_buf */
|
||||
for ( cnt=0; cnt<IPU_BUF_MAX; ++cnt ) {
|
||||
ipu_buf_free(ipu_buf[cnt].addr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ipu_buf_free(val);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* UDC hotplug
|
||||
*/
|
||||
#ifdef CONFIG_JZ_UDC_HOTPLUG
|
||||
extern int jz_udc_active; /* defined in drivers/char/jzchar/jz_udc_hotplug.c */
|
||||
#endif
|
||||
|
||||
#ifndef GPIO_UDC_HOTPLUG
|
||||
#define GPIO_UDC_HOTPLUG 86
|
||||
#endif
|
||||
|
||||
static int udc_read_proc(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
if (__gpio_get_pin(GPIO_UDC_HOTPLUG)) {
|
||||
|
||||
#ifdef CONFIG_JZ_UDC_HOTPLUG
|
||||
|
||||
/* Cable has connected, wait for disconnection. */
|
||||
__gpio_as_irq_fall_edge(GPIO_UDC_HOTPLUG);
|
||||
|
||||
if (jz_udc_active)
|
||||
len += sprintf (page+len, "CONNECT_CABLE\n");
|
||||
else
|
||||
len += sprintf (page+len, "CONNECT_POWER\n");
|
||||
#else
|
||||
len += sprintf (page+len, "CONNECT\n");
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
|
||||
#ifdef CONFIG_JZ_UDC_HOTPLUG
|
||||
/* Cable has disconnected, wait for connection. */
|
||||
__gpio_as_irq_rise_edge(GPIO_UDC_HOTPLUG);
|
||||
#endif
|
||||
|
||||
len += sprintf (page+len, "REMOVE\n");
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* MMC/SD hotplug
|
||||
*/
|
||||
|
||||
#ifndef MSC_HOTPLUG_PIN
|
||||
#define MSC_HOTPLUG_PIN 90
|
||||
#endif
|
||||
|
||||
static int mmc_read_proc (char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
if (__gpio_get_pin(MSC_HOTPLUG_PIN))
|
||||
len += sprintf (page+len, "REMOVE\n");
|
||||
else
|
||||
len += sprintf (page+len, "INSERT\n");
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* IPU memory management (used by mplayer and other apps)
|
||||
*
|
||||
* We reserved 4MB memory for IPU
|
||||
* The memory base address is jz_ipu_framebuf
|
||||
*/
|
||||
|
||||
/* Usage:
|
||||
*
|
||||
* echo n > /proc/jz/imem // n = [0,...,10], allocate memory, 2^n pages
|
||||
* echo xxxxxxxx > /proc/jz/imem // free buffer which addr is xxxxxxxx
|
||||
* echo FF > /proc/jz/ipu // FF, free all buffers
|
||||
* od -X /proc/jz/imem // return the allocated buffer address and the max order of free buffer
|
||||
*/
|
||||
|
||||
//#define DEBUG_IMEM 1
|
||||
|
||||
#define IMEM_MAX_ORDER 10 /* max 2^10 * 4096 = 4MB */
|
||||
|
||||
static unsigned int jz_imem_base; /* physical base address of ipu memory */
|
||||
|
||||
static unsigned int allocated_phys_addr = 0;
|
||||
|
||||
/*
|
||||
* Allocated buffer list
|
||||
*/
|
||||
typedef struct imem_list {
|
||||
unsigned int phys_start; /* physical start addr */
|
||||
unsigned int phys_end; /* physical end addr */
|
||||
struct imem_list *next;
|
||||
} imem_list_t;
|
||||
|
||||
static struct imem_list *imem_list_head = NULL; /* up sorted by phys_start */
|
||||
|
||||
#ifdef DEBUG_IMEM
|
||||
static void dump_imem_list(void)
|
||||
{
|
||||
struct imem_list *imem;
|
||||
|
||||
printk("*** dump_imem_list 0x%x ***\n", (u32)imem_list_head);
|
||||
imem = imem_list_head;
|
||||
while (imem) {
|
||||
printk("imem=0x%x phys_start=0x%x phys_end=0x%x next=0x%x\n", (u32)imem, imem->phys_start, imem->phys_end, (u32)imem->next);
|
||||
imem = imem->next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* allocate 2^order pages inside the 4MB memory */
|
||||
static int imem_alloc(unsigned int order)
|
||||
{
|
||||
int alloc_ok = 0;
|
||||
unsigned int start, end;
|
||||
unsigned int size = (1 << order) * PAGE_SIZE;
|
||||
struct imem_list *imem, *imemn, *imemp;
|
||||
|
||||
allocated_phys_addr = 0;
|
||||
|
||||
start = jz_imem_base;
|
||||
end = start + (1 << IMEM_MAX_ORDER) * PAGE_SIZE;
|
||||
|
||||
imem = imem_list_head;
|
||||
while (imem) {
|
||||
if ((imem->phys_start - start) >= size) {
|
||||
/* we got a valid address range */
|
||||
alloc_ok = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
start = imem->phys_end + 1;
|
||||
imem = imem->next;
|
||||
}
|
||||
|
||||
if (!alloc_ok) {
|
||||
if ((end - start) >= size)
|
||||
alloc_ok = 1;
|
||||
}
|
||||
|
||||
if (alloc_ok) {
|
||||
end = start + size - 1;
|
||||
allocated_phys_addr = start;
|
||||
|
||||
/* add to imem_list, up sorted by phys_start */
|
||||
imemn = kmalloc(sizeof(struct imem_list), GFP_KERNEL);
|
||||
if (!imemn) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
imemn->phys_start = start;
|
||||
imemn->phys_end = end;
|
||||
imemn->next = NULL;
|
||||
|
||||
if (!imem_list_head)
|
||||
imem_list_head = imemn;
|
||||
else {
|
||||
imem = imemp = imem_list_head;
|
||||
while (imem) {
|
||||
if (start < imem->phys_start) {
|
||||
break;
|
||||
}
|
||||
|
||||
imemp = imem;
|
||||
imem = imem->next;
|
||||
}
|
||||
|
||||
if (imem == imem_list_head) {
|
||||
imem_list_head = imemn;
|
||||
imemn->next = imem;
|
||||
}
|
||||
else {
|
||||
imemn->next = imemp->next;
|
||||
imemp->next = imemn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_IMEM
|
||||
dump_imem_list();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void imem_free(unsigned int phys_addr)
|
||||
{
|
||||
struct imem_list *imem, *imemp;
|
||||
|
||||
imem = imemp = imem_list_head;
|
||||
while (imem) {
|
||||
if (phys_addr == imem->phys_start) {
|
||||
if (imem == imem_list_head) {
|
||||
imem_list_head = imem->next;
|
||||
}
|
||||
else {
|
||||
imemp->next = imem->next;
|
||||
}
|
||||
|
||||
kfree(imem);
|
||||
break;
|
||||
}
|
||||
|
||||
imemp = imem;
|
||||
imem = imem->next;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_IMEM
|
||||
dump_imem_list();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void imem_free_all(void)
|
||||
{
|
||||
struct imem_list *imem;
|
||||
|
||||
imem = imem_list_head;
|
||||
while (imem) {
|
||||
kfree(imem);
|
||||
imem = imem->next;
|
||||
}
|
||||
|
||||
imem_list_head = NULL;
|
||||
|
||||
allocated_phys_addr = 0;
|
||||
|
||||
#ifdef DEBUG_IMEM
|
||||
dump_imem_list();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the allocated buffer address and the max order of free buffer
|
||||
*/
|
||||
static int imem_read_proc(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
unsigned int start_addr, end_addr, max_order, max_size;
|
||||
struct imem_list *imem;
|
||||
|
||||
unsigned int *tmp = (unsigned int *)(page + len);
|
||||
|
||||
start_addr = jz_imem_base;
|
||||
end_addr = start_addr + (1 << IMEM_MAX_ORDER) * PAGE_SIZE;
|
||||
|
||||
if (!imem_list_head)
|
||||
max_size = end_addr - start_addr;
|
||||
else {
|
||||
max_size = 0;
|
||||
imem = imem_list_head;
|
||||
while (imem) {
|
||||
if (max_size < (imem->phys_start - start_addr))
|
||||
max_size = imem->phys_start - start_addr;
|
||||
|
||||
start_addr = imem->phys_end + 1;
|
||||
imem = imem->next;
|
||||
}
|
||||
|
||||
if (max_size < (end_addr - start_addr))
|
||||
max_size = end_addr - start_addr;
|
||||
}
|
||||
|
||||
if (max_size > 0) {
|
||||
max_order = get_order(max_size);
|
||||
if (((1 << max_order) * PAGE_SIZE) > max_size)
|
||||
max_order--;
|
||||
}
|
||||
else {
|
||||
max_order = 0xffffffff; /* No any free buffer */
|
||||
}
|
||||
|
||||
*tmp++ = allocated_phys_addr; /* address allocated by 'echo n > /proc/jz/imem' */
|
||||
*tmp = max_order; /* max order of current free buffers */
|
||||
|
||||
len += 2 * sizeof(unsigned int);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int imem_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
val = simple_strtoul(buffer, 0, 16);
|
||||
|
||||
if (val == 0xff) {
|
||||
/* free all memory */
|
||||
imem_free_all();
|
||||
}
|
||||
else if ((val >= 0) && (val <= IMEM_MAX_ORDER)) {
|
||||
/* allocate 2^val pages */
|
||||
imem_alloc(val);
|
||||
}
|
||||
else {
|
||||
/* free buffer which phys_addr is val */
|
||||
imem_free(val);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* /proc/jz/xxx entry
|
||||
*
|
||||
*/
|
||||
static int __init jz_proc_init(void)
|
||||
{
|
||||
struct proc_dir_entry *res;
|
||||
unsigned int virt_addr, i;
|
||||
|
||||
proc_jz_root = proc_mkdir("jz", 0);
|
||||
|
||||
/* External Memory Controller */
|
||||
res = create_proc_entry("emc", 0644, proc_jz_root);
|
||||
if (res) {
|
||||
res->read_proc = emc_read_proc;
|
||||
res->write_proc = NULL;
|
||||
res->data = NULL;
|
||||
}
|
||||
|
||||
/* Power Management Controller */
|
||||
res = create_proc_entry("pmc", 0644, proc_jz_root);
|
||||
if (res) {
|
||||
res->read_proc = pmc_read_proc;
|
||||
res->write_proc = pmc_write_proc;
|
||||
res->data = NULL;
|
||||
}
|
||||
|
||||
/* Clock Generation Module */
|
||||
res = create_proc_entry("cgm", 0644, proc_jz_root);
|
||||
if (res) {
|
||||
res->read_proc = cgm_read_proc;
|
||||
res->write_proc = cgm_write_proc;
|
||||
res->data = NULL;
|
||||
}
|
||||
|
||||
/* Image process unit */
|
||||
res = create_proc_entry("ipu", 0644, proc_jz_root);
|
||||
if (res) {
|
||||
res->read_proc = ipu_read_proc;
|
||||
res->write_proc = ipu_write_proc;
|
||||
res->data = NULL;
|
||||
}
|
||||
|
||||
/* udc hotplug */
|
||||
res = create_proc_entry("udc", 0644, proc_jz_root);
|
||||
if (res) {
|
||||
res->read_proc = udc_read_proc;
|
||||
res->write_proc = NULL;
|
||||
res->data = NULL;
|
||||
}
|
||||
|
||||
/* mmc hotplug */
|
||||
res = create_proc_entry("mmc", 0644, proc_jz_root);
|
||||
if (res) {
|
||||
res->read_proc = mmc_read_proc;
|
||||
res->write_proc = NULL;
|
||||
res->data = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reserve a 4MB memory for IPU on JZ4760.
|
||||
*/
|
||||
jz_imem_base = (unsigned int)__get_free_pages(GFP_KERNEL, IMEM_MAX_ORDER);
|
||||
if (jz_imem_base) {
|
||||
/* imem (IPU memory management) */
|
||||
res = create_proc_entry("imem", 0644, proc_jz_root);
|
||||
if (res) {
|
||||
res->read_proc = imem_read_proc;
|
||||
res->write_proc = imem_write_proc;
|
||||
res->data = NULL;
|
||||
}
|
||||
|
||||
/* Set page reserved */
|
||||
virt_addr = jz_imem_base;
|
||||
for (i = 0; i < (1 << IMEM_MAX_ORDER); i++) {
|
||||
SetPageReserved(virt_to_page((void *)virt_addr));
|
||||
virt_addr += PAGE_SIZE;
|
||||
}
|
||||
|
||||
/* Convert to physical address */
|
||||
jz_imem_base = virt_to_phys((void *)jz_imem_base);
|
||||
|
||||
printk("Total %dMB memory at 0x%x was reserved for IPU\n",
|
||||
(unsigned int)((1 << IMEM_MAX_ORDER) * PAGE_SIZE)/1000000, jz_imem_base);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__initcall(jz_proc_init);
|
||||
198
target/linux/xburst/files-2.6.27/arch/mips/jz4760/prom.c
Executable file
198
target/linux/xburst/files-2.6.27/arch/mips/jz4760/prom.c
Executable file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
*
|
||||
* BRIEF MODULE DESCRIPTION
|
||||
* PROM library initialisation code, supports YAMON and U-Boot.
|
||||
*
|
||||
* Copyright 2000, 2001, 2006 MontaVista Software Inc.
|
||||
* Author: MontaVista Software, Inc.
|
||||
* ppopov@mvista.com or source@mvista.com
|
||||
*
|
||||
* This file was derived from Carsten Langgaard's
|
||||
* arch/mips/mips-boards/xx files.
|
||||
*
|
||||
* Carsten Langgaard, carstenl@mips.com
|
||||
* Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
|
||||
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* 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.,
|
||||
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/* #define DEBUG_CMDLINE */
|
||||
|
||||
int prom_argc;
|
||||
char **prom_argv, **prom_envp;
|
||||
|
||||
char * prom_getcmdline(void)
|
||||
{
|
||||
return &(arcs_cmdline[0]);
|
||||
}
|
||||
|
||||
void prom_init_cmdline(void)
|
||||
{
|
||||
char *cp;
|
||||
int actr;
|
||||
|
||||
actr = 1; /* Always ignore argv[0] */
|
||||
|
||||
cp = &(arcs_cmdline[0]);
|
||||
while(actr < prom_argc) {
|
||||
strcpy(cp, prom_argv[actr]);
|
||||
cp += strlen(prom_argv[actr]);
|
||||
*cp++ = ' ';
|
||||
actr++;
|
||||
}
|
||||
if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
|
||||
--cp;
|
||||
if (prom_argc > 1)
|
||||
*cp = '\0';
|
||||
|
||||
}
|
||||
|
||||
|
||||
char *prom_getenv(char *envname)
|
||||
{
|
||||
#if 0
|
||||
/*
|
||||
* Return a pointer to the given environment variable.
|
||||
* YAMON uses "name", "value" pairs, while U-Boot uses "name=value".
|
||||
*/
|
||||
|
||||
char **env = prom_envp;
|
||||
int i = strlen(envname);
|
||||
int yamon = (*env && strchr(*env, '=') == NULL);
|
||||
|
||||
while (*env) {
|
||||
if (yamon) {
|
||||
if (strcmp(envname, *env++) == 0)
|
||||
return *env;
|
||||
} else {
|
||||
if (strncmp(envname, *env, i) == 0 && (*env)[i] == '=')
|
||||
return *env + i + 1;
|
||||
}
|
||||
env++;
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline unsigned char str2hexnum(unsigned char c)
|
||||
{
|
||||
if(c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
if(c >= 'a' && c <= 'f')
|
||||
return c - 'a' + 10;
|
||||
if(c >= 'A' && c <= 'F')
|
||||
return c - 'A' + 10;
|
||||
return 0; /* foo */
|
||||
}
|
||||
|
||||
inline void str2eaddr(unsigned char *ea, unsigned char *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 6; i++) {
|
||||
unsigned char num;
|
||||
|
||||
if((*str == '.') || (*str == ':'))
|
||||
str++;
|
||||
num = str2hexnum(*str++) << 4;
|
||||
num |= (str2hexnum(*str++));
|
||||
ea[i] = num;
|
||||
}
|
||||
}
|
||||
|
||||
int get_ethernet_addr(char *ethernet_addr)
|
||||
{
|
||||
char *ethaddr_str;
|
||||
|
||||
ethaddr_str = prom_getenv("ethaddr");
|
||||
if (!ethaddr_str) {
|
||||
printk("ethaddr not set in boot prom\n");
|
||||
return -1;
|
||||
}
|
||||
str2eaddr(ethernet_addr, ethaddr_str);
|
||||
|
||||
#if 0
|
||||
{
|
||||
int i;
|
||||
|
||||
printk("get_ethernet_addr: ");
|
||||
for (i=0; i<5; i++)
|
||||
printk("%02x:", (unsigned char)*(ethernet_addr+i));
|
||||
printk("%02x\n", *(ethernet_addr+i));
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init prom_free_prom_memory(void)
|
||||
{
|
||||
}
|
||||
|
||||
void __init prom_init(void)
|
||||
{
|
||||
unsigned char *memsize_str;
|
||||
unsigned long memsize;
|
||||
|
||||
prom_argc = (int) fw_arg0;
|
||||
prom_argv = (char **) fw_arg1;
|
||||
prom_envp = (char **) fw_arg2;
|
||||
|
||||
mips_machtype = MACH_INGENIC_JZ4760;
|
||||
|
||||
prom_init_cmdline();
|
||||
memsize_str = prom_getenv("memsize");
|
||||
if (!memsize_str) {
|
||||
memsize = 0x04000000;
|
||||
} else {
|
||||
memsize = simple_strtol(memsize_str, NULL, 0);
|
||||
}
|
||||
add_memory_region(0, memsize, BOOT_MEM_RAM);
|
||||
}
|
||||
|
||||
/* used by early printk */
|
||||
void prom_putchar(char c)
|
||||
{
|
||||
volatile u8 *uart_lsr = (volatile u8 *)(UART1_BASE + OFF_LSR);
|
||||
volatile u8 *uart_tdr = (volatile u8 *)(UART1_BASE + OFF_TDR);
|
||||
|
||||
/* Wait for fifo to shift out some bytes */
|
||||
while ( !((*uart_lsr & (UARTLSR_TDRQ | UARTLSR_TEMT)) == 0x60) );
|
||||
|
||||
*uart_tdr = (u8)c;
|
||||
}
|
||||
|
||||
const char *get_system_type(void)
|
||||
{
|
||||
return "JZ4760";
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(prom_getcmdline);
|
||||
EXPORT_SYMBOL(get_ethernet_addr);
|
||||
EXPORT_SYMBOL(str2eaddr);
|
||||
46
target/linux/xburst/files-2.6.27/arch/mips/jz4760/reset.c
Executable file
46
target/linux/xburst/files-2.6.27/arch/mips/jz4760/reset.c
Executable file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4760/reset.c
|
||||
*
|
||||
* JZ4760 reset routines.
|
||||
*
|
||||
* Copyright (c) 2006-2007 Ingenic Semiconductor Inc.
|
||||
* Author: <yliu@ingenic.cn>
|
||||
*
|
||||
* 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/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/reboot.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
void jz_restart(char *command)
|
||||
{
|
||||
printk("Restarting after 4 ms\n");
|
||||
REG_WDT_TCSR = WDT_TCSR_PRESCALE4 | WDT_TCSR_EXT_EN;
|
||||
REG_WDT_TCNT = 0;
|
||||
REG_WDT_TDR = JZ_EXTAL/1000; /* reset after 4ms */
|
||||
REG_TCU_TSCR = TCU_TSCR_WDTSC; /* enable wdt clock */
|
||||
REG_WDT_TCER = WDT_TCER_TCEN; /* wdt start */
|
||||
while (1);
|
||||
}
|
||||
|
||||
void jz_halt(void)
|
||||
{
|
||||
printk(KERN_NOTICE "\n** You can safely turn off the power\n");
|
||||
|
||||
while (1)
|
||||
__asm__(".set\tmips3\n\t"
|
||||
"wait\n\t"
|
||||
".set\tmips0");
|
||||
}
|
||||
|
||||
void jz_power_off(void)
|
||||
{
|
||||
jz_halt();
|
||||
}
|
||||
199
target/linux/xburst/files-2.6.27/arch/mips/jz4760/setup.c
Executable file
199
target/linux/xburst/files-2.6.27/arch/mips/jz4760/setup.c
Executable file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4760/common/setup.c
|
||||
*
|
||||
* JZ4760 common setup routines.
|
||||
*
|
||||
* Copyright (C) 2006 Ingenic Semiconductor Inc.
|
||||
*
|
||||
* This program is free software; you can distribute it and/or modify it
|
||||
* under the terms of the GNU General Public License (Version 2) as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_8250.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/reboot.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
#ifdef CONFIG_PC_KEYB
|
||||
#include <asm/keyboard.h>
|
||||
#endif
|
||||
|
||||
jz_clocks_t jz_clocks;
|
||||
|
||||
extern char * __init prom_getcmdline(void);
|
||||
extern void __init jz_board_setup(void);
|
||||
extern void jz_restart(char *);
|
||||
extern void jz_halt(void);
|
||||
extern void jz_power_off(void);
|
||||
extern void jz_time_init(void);
|
||||
|
||||
static void __init sysclocks_setup(void)
|
||||
{
|
||||
#ifndef CONFIG_MIPS_JZ_EMURUS /* FPGA */
|
||||
jz_clocks.cclk = __cpm_get_cclk();
|
||||
jz_clocks.hclk = __cpm_get_h0clk();
|
||||
jz_clocks.pclk = __cpm_get_pclk();
|
||||
jz_clocks.mclk = __cpm_get_mclk();
|
||||
jz_clocks.h1clk = __cpm_get_h1clk();
|
||||
jz_clocks.pixclk = __cpm_get_pixclk();
|
||||
jz_clocks.i2sclk = __cpm_get_i2sclk();
|
||||
jz_clocks.usbclk = __cpm_get_usbclk();
|
||||
jz_clocks.mscclk = __cpm_get_mscclk(0);
|
||||
jz_clocks.extalclk = __cpm_get_extalclk();
|
||||
jz_clocks.rtcclk = __cpm_get_rtcclk();
|
||||
#else
|
||||
|
||||
#define FPGACLK 8000000
|
||||
|
||||
jz_clocks.cclk = FPGACLK;
|
||||
jz_clocks.hclk = FPGACLK;
|
||||
jz_clocks.pclk = FPGACLK;
|
||||
jz_clocks.mclk = FPGACLK;
|
||||
jz_clocks.h1clk = FPGACLK;
|
||||
jz_clocks.pixclk = FPGACLK;
|
||||
jz_clocks.i2sclk = FPGACLK;
|
||||
jz_clocks.usbclk = FPGACLK;
|
||||
jz_clocks.mscclk = FPGACLK;
|
||||
jz_clocks.extalclk = FPGACLK;
|
||||
jz_clocks.rtcclk = FPGACLK;
|
||||
#endif
|
||||
|
||||
printk("CPU clock: %dMHz, System clock: %dMHz, Peripheral clock: %dMHz, Memory clock: %dMHz\n",
|
||||
(jz_clocks.cclk + 500000) / 1000000,
|
||||
(jz_clocks.hclk + 500000) / 1000000,
|
||||
(jz_clocks.pclk + 500000) / 1000000,
|
||||
(jz_clocks.mclk + 500000) / 1000000);
|
||||
}
|
||||
|
||||
static void __init soc_cpm_setup(void)
|
||||
{
|
||||
/* Start all module clocks
|
||||
*/
|
||||
__cpm_start_all();
|
||||
|
||||
/* Enable CKO to external memory */
|
||||
__cpm_enable_cko();
|
||||
|
||||
/* CPU enters IDLE mode when executing 'wait' instruction */
|
||||
__cpm_idle_mode();
|
||||
|
||||
/* Setup system clocks */
|
||||
sysclocks_setup();
|
||||
}
|
||||
|
||||
static void __init soc_harb_setup(void)
|
||||
{
|
||||
// __harb_set_priority(0x00); /* CIM>LCD>DMA>ETH>PCI>USB>CBB */
|
||||
// __harb_set_priority(0x03); /* LCD>CIM>DMA>ETH>PCI>USB>CBB */
|
||||
// __harb_set_priority(0x0a); /* ETH>LCD>CIM>DMA>PCI>USB>CBB */
|
||||
}
|
||||
|
||||
static void __init soc_emc_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void __init soc_dmac_setup(void)
|
||||
{
|
||||
__dmac_enable_module(0);
|
||||
__dmac_enable_module(1);
|
||||
}
|
||||
|
||||
static void __init jz_soc_setup(void)
|
||||
{
|
||||
soc_cpm_setup();
|
||||
soc_harb_setup();
|
||||
soc_emc_setup();
|
||||
soc_dmac_setup();
|
||||
}
|
||||
|
||||
static void __init jz_serial_setup(void)
|
||||
{
|
||||
#ifdef CONFIG_SERIAL_8250
|
||||
struct uart_port s;
|
||||
REG8(UART0_FCR) |= UARTFCR_UUE; /* enable UART module */
|
||||
memset(&s, 0, sizeof(s));
|
||||
s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
|
||||
s.iotype = SERIAL_IO_MEM;
|
||||
s.regshift = 2;
|
||||
s.uartclk = jz_clocks.extalclk ;
|
||||
|
||||
s.line = 0;
|
||||
s.membase = (u8 *)UART0_BASE;
|
||||
s.irq = IRQ_UART0;
|
||||
if (early_serial_setup(&s) != 0) {
|
||||
printk(KERN_ERR "Serial ttyS0 setup failed!\n");
|
||||
}
|
||||
|
||||
s.line = 1;
|
||||
s.membase = (u8 *)UART1_BASE;
|
||||
s.irq = IRQ_UART1;
|
||||
if (early_serial_setup(&s) != 0) {
|
||||
printk(KERN_ERR "Serial ttyS1 setup failed!\n");
|
||||
}
|
||||
|
||||
s.line = 2;
|
||||
s.membase = (u8 *)UART2_BASE;
|
||||
s.irq = IRQ_UART2;
|
||||
|
||||
if (early_serial_setup(&s) != 0) {
|
||||
printk(KERN_ERR "Serial ttyS2 setup failed!\n");
|
||||
}
|
||||
/*
|
||||
s.line = 3;
|
||||
s.membase = (u8 *)UART3_BASE;
|
||||
s.irq = IRQ_UART3;
|
||||
if (early_serial_setup(&s) != 0) {
|
||||
printk(KERN_ERR "Serial ttyS3 setup failed!\n");
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
|
||||
void __init plat_mem_setup(void)
|
||||
{
|
||||
char *argptr;
|
||||
|
||||
argptr = prom_getcmdline();
|
||||
|
||||
/* IO/MEM resources. Which will be the addtion value in `inX' and
|
||||
* `outX' macros defined in asm/io.h */
|
||||
set_io_port_base(0);
|
||||
ioport_resource.start = 0x00000000;
|
||||
ioport_resource.end = 0xffffffff;
|
||||
iomem_resource.start = 0x00000000;
|
||||
iomem_resource.end = 0xffffffff;
|
||||
|
||||
_machine_restart = jz_restart;
|
||||
_machine_halt = jz_halt;
|
||||
pm_power_off = jz_power_off;
|
||||
|
||||
jz_soc_setup();
|
||||
jz_serial_setup();
|
||||
jz_board_setup();
|
||||
}
|
||||
|
||||
156
target/linux/xburst/files-2.6.27/arch/mips/jz4760/time.c
Executable file
156
target/linux/xburst/files-2.6.27/arch/mips/jz4760/time.c
Executable file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* linux/arch/mips/jz4760/time.c
|
||||
*
|
||||
* Setting up the clock on the JZ4760 boards.
|
||||
*
|
||||
* Copyright (C) 2008 Ingenic Semiconductor Inc.
|
||||
* Author: <jlwei@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can distribute it and/or modify it
|
||||
* under the terms of the GNU General Public License (Version 2) as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/clockchips.h>
|
||||
|
||||
#include <asm/time.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
/* This is for machines which generate the exact clock. */
|
||||
|
||||
#define JZ_TIMER_IRQ IRQ_TCU0
|
||||
|
||||
#define JZ_TIMER_CLOCK (JZ_EXTAL>>4) /* Jz timer clock frequency */
|
||||
|
||||
static struct clocksource clocksource_jz; /* Jz clock source */
|
||||
static struct clock_event_device jz_clockevent_device; /* Jz clock event */
|
||||
|
||||
void (*jz_timer_callback)(void);
|
||||
|
||||
static irqreturn_t jz_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct clock_event_device *cd = dev_id;
|
||||
|
||||
REG_TCU_TFCR = TCU_TFCR_OSTFCL; /* ACK timer */
|
||||
|
||||
if (jz_timer_callback)
|
||||
jz_timer_callback();
|
||||
|
||||
cd->event_handler(cd);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct irqaction jz_irqaction = {
|
||||
.handler = jz_timer_interrupt,
|
||||
.flags = IRQF_DISABLED | IRQF_PERCPU | IRQF_TIMER,
|
||||
.name = "jz-timerirq",
|
||||
};
|
||||
|
||||
|
||||
cycle_t jz_get_cycles(void)
|
||||
{
|
||||
/* convert jiffes to jz timer cycles */
|
||||
return (cycle_t)( jiffies*((JZ_TIMER_CLOCK)/HZ) + REG_TCU_OSTCNT);
|
||||
}
|
||||
|
||||
static struct clocksource clocksource_jz = {
|
||||
.name = "jz_clocksource",
|
||||
.rating = 300,
|
||||
.read = jz_get_cycles,
|
||||
.mask = 0xFFFFFFFF,
|
||||
.shift = 10,
|
||||
.flags = CLOCK_SOURCE_WATCHDOG,
|
||||
};
|
||||
|
||||
static int __init jz_clocksource_init(void)
|
||||
{
|
||||
clocksource_jz.mult = clocksource_hz2mult(JZ_TIMER_CLOCK, clocksource_jz.shift);
|
||||
clocksource_register(&clocksource_jz);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jz_set_next_event(unsigned long evt,
|
||||
struct clock_event_device *unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void jz_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
break;
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct clock_event_device jz_clockevent_device = {
|
||||
.name = "jz-clockenvent",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC,
|
||||
// .features = CLOCK_EVT_FEAT_ONESHOT, /* Jz4740 not support dynamic clock now */
|
||||
|
||||
/* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */
|
||||
.rating = 300,
|
||||
.irq = JZ_TIMER_IRQ,
|
||||
.set_mode = jz_set_mode,
|
||||
.set_next_event = jz_set_next_event,
|
||||
};
|
||||
|
||||
static void __init jz_clockevent_init(void)
|
||||
{
|
||||
struct clock_event_device *cd = &jz_clockevent_device;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
cd->cpumask = cpumask_of_cpu(cpu);
|
||||
clockevents_register_device(cd);
|
||||
}
|
||||
|
||||
static void __init jz_timer_setup(void)
|
||||
{
|
||||
jz_clocksource_init(); /* init jz clock source */
|
||||
jz_clockevent_init(); /* init jz clock event */
|
||||
|
||||
/*
|
||||
* Make irqs happen for the system timer
|
||||
*/
|
||||
jz_irqaction.dev_id = &jz_clockevent_device;
|
||||
setup_irq(JZ_TIMER_IRQ, &jz_irqaction);
|
||||
}
|
||||
|
||||
|
||||
void __init plat_time_init(void)
|
||||
{
|
||||
unsigned int latch;
|
||||
|
||||
/* Init timer */
|
||||
latch = (JZ_TIMER_CLOCK + (HZ>>1)) / HZ;
|
||||
|
||||
REG_TCU_OSTCSR = TCU_OSTCSR_PRESCALE16 | TCU_OSTCSR_EXT_EN;
|
||||
REG_TCU_OSTCNT = 0;
|
||||
REG_TCU_OSTDR = latch;
|
||||
|
||||
REG_TCU_TMCR = TCU_TMCR_OSTMCL; /* unmask match irq */
|
||||
REG_TCU_TSCR = TCU_TSCR_OSTSC; /* enable timer clock */
|
||||
REG_TCU_TESR = TCU_TESR_OSTST; /* start counting up */
|
||||
|
||||
jz_timer_setup();
|
||||
}
|
||||
330
target/linux/xburst/files-2.6.27/drivers/i2c/busses/i2c-jz47xx.c
Normal file
330
target/linux/xburst/files-2.6.27/drivers/i2c/busses/i2c-jz47xx.c
Normal file
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* i2c_jz47xx.c
|
||||
* I2C adapter for the INGENIC I2C bus access.
|
||||
*
|
||||
* Copyright (C) 2006 - 2008 Ingenic Semiconductor Inc.
|
||||
* Author: <cwjia@ingenic.cn>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-id.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <asm/addrspace.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
#include "i2c-jz47xx.h"
|
||||
|
||||
/* I2C protocol */
|
||||
#define I2C_READ 1
|
||||
#define I2C_WRITE 0
|
||||
|
||||
#define TIMEOUT 1000
|
||||
unsigned short sub_addr = 0;
|
||||
int addr_val = 0;
|
||||
struct jz_i2c {
|
||||
spinlock_t lock;
|
||||
wait_queue_head_t wait;
|
||||
struct i2c_msg *msg;
|
||||
unsigned int msg_num;
|
||||
unsigned int slave_addr;
|
||||
struct i2c_adapter adap;
|
||||
struct clk *clk;
|
||||
};
|
||||
|
||||
/*
|
||||
* I2C bus protocol basic routines
|
||||
*/
|
||||
static int i2c_put_data(unsigned char data)
|
||||
{
|
||||
unsigned int timeout = TIMEOUT*10;
|
||||
|
||||
__i2c_write(data);
|
||||
__i2c_set_drf();
|
||||
while (__i2c_check_drf() != 0);
|
||||
while (!__i2c_transmit_ended());
|
||||
while (!__i2c_received_ack() && timeout)
|
||||
timeout--;
|
||||
|
||||
if (timeout)
|
||||
return 0;
|
||||
else
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int i2c_get_data(unsigned char *data, int ack)
|
||||
{
|
||||
int timeout = TIMEOUT*10;
|
||||
|
||||
if (!ack)
|
||||
__i2c_send_nack();
|
||||
else
|
||||
__i2c_send_ack();
|
||||
|
||||
while (__i2c_check_drf() == 0 && timeout)
|
||||
timeout--;
|
||||
|
||||
if (timeout) {
|
||||
if (!ack)
|
||||
__i2c_send_stop();
|
||||
*data = __i2c_read();
|
||||
__i2c_clear_drf();
|
||||
return 0;
|
||||
} else
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/*
|
||||
* I2C interface
|
||||
*/
|
||||
void i2c_jz_setclk(unsigned int i2cclk)
|
||||
{
|
||||
__i2c_set_clk(jz_clocks.extalclk, i2cclk);
|
||||
}
|
||||
|
||||
static int xfer_read(unsigned char device, struct i2c_adapter *adap, unsigned char *buf, int length)
|
||||
{
|
||||
int cnt = length;
|
||||
int timeout = 5;
|
||||
|
||||
device = (0xa << 3) | ((sub_addr & 0x0700) >> 8);
|
||||
sub_addr = sub_addr & 0xff;
|
||||
|
||||
L_try_again:
|
||||
|
||||
if (timeout < 0)
|
||||
goto L_timeout;
|
||||
|
||||
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
|
||||
|
||||
if (addr_val) {
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
|
||||
goto device_werr;
|
||||
if (i2c_put_data(sub_addr) < 0)
|
||||
goto address_err;
|
||||
}
|
||||
__i2c_send_start();
|
||||
|
||||
if (i2c_put_data((device << 1) | I2C_READ ) < 0)
|
||||
goto device_rerr;
|
||||
|
||||
__i2c_send_ack(); /* Master sends ACK for continue reading */
|
||||
__i2c_send_start();
|
||||
|
||||
while (cnt) {
|
||||
if (cnt == 1) {
|
||||
if (i2c_get_data(buf, 0) < 0)
|
||||
break;
|
||||
} else {
|
||||
if (i2c_get_data(buf, 1) < 0)
|
||||
break;
|
||||
}
|
||||
cnt--;
|
||||
buf++;
|
||||
}
|
||||
addr_val = 0;
|
||||
return length - cnt;
|
||||
device_rerr:
|
||||
device_werr:
|
||||
address_err:
|
||||
timeout --;
|
||||
__i2c_send_stop();
|
||||
goto L_try_again;
|
||||
|
||||
L_timeout:
|
||||
__i2c_send_stop();
|
||||
printk("Read I2C device 0x%2x failed.\n", device);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int xfer_write(unsigned char device, struct i2c_adapter *adap, unsigned char *buf, int length)
|
||||
{
|
||||
int cnt = length;
|
||||
int cnt_in_pg;
|
||||
int timeout = 5;
|
||||
unsigned char *tmpbuf;
|
||||
unsigned char tmpaddr;
|
||||
|
||||
device = (0xa << 3) | ((sub_addr & 0x0700) >> 8);
|
||||
sub_addr = sub_addr & 0xff;
|
||||
|
||||
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
|
||||
|
||||
W_try_again:
|
||||
if (timeout < 0)
|
||||
goto W_timeout;
|
||||
|
||||
cnt = length;
|
||||
tmpbuf = (unsigned char *)buf;
|
||||
tmpaddr = device;
|
||||
start_write_page:
|
||||
cnt_in_pg = 0;
|
||||
__i2c_send_start();
|
||||
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
|
||||
goto device_err;
|
||||
if (addr_val) {
|
||||
if (i2c_put_data(sub_addr) < 0)
|
||||
goto address_err;
|
||||
}
|
||||
while (cnt) {
|
||||
if (++cnt_in_pg > 8) {
|
||||
__i2c_send_stop();
|
||||
mdelay(1);
|
||||
sub_addr += 8;
|
||||
goto start_write_page;
|
||||
}
|
||||
if (i2c_put_data(*tmpbuf) < 0)
|
||||
break;
|
||||
cnt--;
|
||||
tmpbuf++;
|
||||
}
|
||||
__i2c_send_stop();
|
||||
addr_val = 0;
|
||||
return length - cnt;
|
||||
device_err:
|
||||
address_err:
|
||||
timeout--;
|
||||
__i2c_send_stop();
|
||||
goto W_try_again;
|
||||
|
||||
W_timeout:
|
||||
printk(KERN_DEBUG "Write I2C device 0x%2x failed.\n", device);
|
||||
__i2c_send_stop();
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int i2c_jz_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg, int num)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
dev_dbg(&adap->dev, "jz47xx_xfer: processing %d messages:\n", num);
|
||||
for (i = 0; i < num; i++) {
|
||||
dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i,
|
||||
pmsg->flags & I2C_M_RD ? "read" : "writ",
|
||||
pmsg->len, pmsg->len > 1 ? "s" : "",
|
||||
pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr);
|
||||
if (pmsg->len && pmsg->buf) { /* sanity check */
|
||||
if (pmsg->flags & I2C_M_RD)
|
||||
ret = xfer_read(pmsg->addr, adap, pmsg->buf, pmsg->len);
|
||||
else
|
||||
ret = xfer_write(pmsg->addr, adap, pmsg->buf, pmsg->len);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
/* Wait until transfer is finished */
|
||||
}
|
||||
dev_dbg(&adap->dev, "transfer complete\n");
|
||||
pmsg++; /* next message */
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static u32 i2c_jz_functionality(struct i2c_adapter *adap)
|
||||
{
|
||||
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
|
||||
}
|
||||
|
||||
static const struct i2c_algorithm i2c_jz_algorithm = {
|
||||
.master_xfer = i2c_jz_xfer,
|
||||
.functionality = i2c_jz_functionality,
|
||||
};
|
||||
|
||||
static int i2c_jz_probe(struct platform_device *dev)
|
||||
{
|
||||
struct jz_i2c *i2c;
|
||||
struct i2c_jz_platform_data *plat = dev->dev.platform_data;
|
||||
int ret;
|
||||
|
||||
__i2c_set_clk(jz_clocks.extalclk, 10000); /* default 10 KHz */
|
||||
__i2c_enable();
|
||||
|
||||
i2c = kzalloc(sizeof(struct jz_i2c), GFP_KERNEL);
|
||||
if (!i2c) {
|
||||
printk("There is no enough memory\n");
|
||||
ret = -ENOMEM;
|
||||
goto emalloc;
|
||||
}
|
||||
|
||||
i2c->adap.owner = THIS_MODULE;
|
||||
i2c->adap.algo = &i2c_jz_algorithm;
|
||||
i2c->adap.retries = 5;
|
||||
spin_lock_init(&i2c->lock);
|
||||
init_waitqueue_head(&i2c->wait);
|
||||
sprintf(i2c->adap.name, "jz_i2c-i2c.%u", dev->id);
|
||||
i2c->adap.algo_data = i2c;
|
||||
i2c->adap.dev.parent = &dev->dev;
|
||||
|
||||
if (plat) {
|
||||
i2c->adap.class = plat->class;
|
||||
}
|
||||
|
||||
/*
|
||||
* If "dev->id" is negative we consider it as zero.
|
||||
* The reason to do so is to avoid sysfs names that only make
|
||||
* sense when there are multiple adapters.
|
||||
*/
|
||||
i2c->adap.nr = dev->id != -1 ? dev->id : 0;
|
||||
/* ret = i2c_add_adapter(&i2c->adap); */
|
||||
ret = i2c_add_numbered_adapter(&i2c->adap);
|
||||
if (ret < 0) {
|
||||
printk(KERN_INFO "I2C: Failed to add bus\n");
|
||||
goto eadapt;
|
||||
}
|
||||
|
||||
platform_set_drvdata(dev, i2c);
|
||||
dev_info(&dev->dev, "JZ47xx i2c bus driver.\n");
|
||||
return 0;
|
||||
eadapt:
|
||||
__i2c_disable();
|
||||
emalloc:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int i2c_jz_remove(struct platform_device *dev)
|
||||
{
|
||||
struct i2c_adapter *adapter = platform_get_drvdata(dev);
|
||||
int rc;
|
||||
|
||||
rc = i2c_del_adapter(adapter);
|
||||
platform_set_drvdata(dev, NULL);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct platform_driver i2c_jz_driver = {
|
||||
.probe = i2c_jz_probe,
|
||||
.remove = i2c_jz_remove,
|
||||
.driver = {
|
||||
.name = "jz_i2c",
|
||||
},
|
||||
};
|
||||
|
||||
static int __init i2c_adap_jz_init(void)
|
||||
{
|
||||
return platform_driver_register(&i2c_jz_driver);
|
||||
}
|
||||
|
||||
static void __exit i2c_adap_jz_exit(void)
|
||||
{
|
||||
return platform_driver_unregister(&i2c_jz_driver);
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(i2c_adap_jz_init);
|
||||
module_exit(i2c_adap_jz_exit);
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* i2c_jz47xx.h
|
||||
*
|
||||
* 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 _I2C_JZ_H_
|
||||
#define _I2C_JZ_H_
|
||||
|
||||
struct i2c_slave_client;
|
||||
|
||||
struct i2c_jz_platform_data {
|
||||
unsigned int slave_addr;
|
||||
struct i2c_slave_client *slave;
|
||||
unsigned int class;
|
||||
};
|
||||
|
||||
extern void jz_set_i2c_info(struct i2c_jz_platform_data *info);
|
||||
#endif
|
||||
413
target/linux/xburst/files-2.6.27/drivers/input/keyboard/jz_gpio_keypad.c
Executable file
413
target/linux/xburst/files-2.6.27/drivers/input/keyboard/jz_gpio_keypad.c
Executable file
@@ -0,0 +1,413 @@
|
||||
/*
|
||||
* linux/drivers/input/keyboard/jz_gpio_keys.c
|
||||
*
|
||||
* Keypad driver based on GPIO pins for Jz4750 APUS board.
|
||||
*
|
||||
* User applications can access to this device via /dev/input/eventX.
|
||||
*
|
||||
* Copyright (c) 2005 - 2009 Ingenic Semiconductor Inc.
|
||||
*
|
||||
* Author: Richard <cjfeng@ingenic.cn>
|
||||
* Regen <lhhuang@ingenic.cn>
|
||||
*
|
||||
* 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/version.h>
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/gpio_keys.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
#undef DEBUG
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
#define dprintk(x...) printk(x)
|
||||
#else
|
||||
#define dprintk(x...)
|
||||
#endif
|
||||
|
||||
/* Device name */
|
||||
#ifdef CONFIG_JZ4750_APUS
|
||||
#define DEV_NAME "apus-keypad"
|
||||
#else
|
||||
#ifdef CONFIG_JZ4750D_CETUS
|
||||
#define DEV_NAME "cetus-keypad"
|
||||
#else
|
||||
#define DEV_NAME "jz-keypad"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Key codes */
|
||||
#define ANDROID_MENU KEY_MENU
|
||||
#define ANDROID_CALL KEY_SEND
|
||||
#define ANDROID_HOME KEY_HOME
|
||||
#define ANDROID_ENDCALL KEY_END
|
||||
#define ANDROID_BACK KEY_BACK
|
||||
|
||||
/* Timer interval */
|
||||
#define SCAN_INTERVAL 5
|
||||
|
||||
/*
|
||||
* GPIO Buttons
|
||||
*/
|
||||
static struct gpio_keys_button board_buttons[] = {
|
||||
#if 0
|
||||
{
|
||||
.gpio = GPIO_WAKEUP,
|
||||
.code = KEY_1,
|
||||
.desc = "Button 0",
|
||||
.active_low = 1,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.gpio = GPIO_CALL,
|
||||
.code = ANDROID_CALL,
|
||||
.desc = "Button 1",
|
||||
.active_low = ACTIVE_LOW_CALL,
|
||||
},
|
||||
{
|
||||
.gpio = GPIO_HOME,
|
||||
.code = ANDROID_HOME,
|
||||
.desc = "Button 2",
|
||||
.active_low = ACTIVE_LOW_HOME,
|
||||
},
|
||||
{
|
||||
.gpio = GPIO_BACK,
|
||||
.code = ANDROID_BACK,
|
||||
.desc = "Button 3",
|
||||
.active_low = ACTIVE_LOW_BACK,
|
||||
},
|
||||
{
|
||||
.gpio = GPIO_MENU,
|
||||
.code = ANDROID_MENU,
|
||||
.desc = "Button 4",
|
||||
.active_low = ACTIVE_LOW_MENU,
|
||||
},
|
||||
{
|
||||
.gpio = GPIO_ENDCALL,
|
||||
.code = ANDROID_ENDCALL,
|
||||
.desc = "Button 5",
|
||||
.active_low = ACTIVE_LOW_ENDCALL,
|
||||
},
|
||||
#if 0
|
||||
{
|
||||
.gpio = GPIO_SW7,
|
||||
.code = KEY_7,
|
||||
.desc = "Button 6",
|
||||
.active_low = 1,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct timer_list button_timer;
|
||||
static int button_no;
|
||||
|
||||
static struct gpio_keys_platform_data board_button_data = {
|
||||
.buttons = board_buttons,
|
||||
.nbuttons = ARRAY_SIZE(board_buttons),
|
||||
};
|
||||
|
||||
static struct platform_device board_button_device = {
|
||||
.name = DEV_NAME,
|
||||
.id = -1,
|
||||
.num_resources = 0,
|
||||
.dev = {
|
||||
.platform_data = &board_button_data,
|
||||
}
|
||||
};
|
||||
|
||||
static void enable_gpio_irqs(struct gpio_keys_platform_data *pdata)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pdata->nbuttons; i++) {
|
||||
struct gpio_keys_button *button = &pdata->buttons[i];
|
||||
|
||||
if (button->active_low)
|
||||
__gpio_as_irq_fall_edge(button->gpio);
|
||||
else
|
||||
__gpio_as_irq_rise_edge(button->gpio);
|
||||
}
|
||||
}
|
||||
|
||||
static void button_timer_callback(unsigned long data)
|
||||
{
|
||||
int gpio = board_buttons[button_no].gpio;
|
||||
int code = board_buttons[button_no].code;
|
||||
int active_low = board_buttons[button_no].active_low;
|
||||
struct platform_device *pdev = (struct platform_device *)data;
|
||||
struct input_dev *input = platform_get_drvdata(pdev);
|
||||
int state;
|
||||
static int button_pressed = 0;
|
||||
|
||||
state = __gpio_get_pin(gpio);
|
||||
|
||||
if (active_low) {
|
||||
if (state == 0) {
|
||||
/* button pressed */
|
||||
button_pressed = 1;
|
||||
input_report_key(input, code, 1);
|
||||
input_sync(input);
|
||||
mod_timer(&button_timer, jiffies + SCAN_INTERVAL);
|
||||
dprintk("gpio %d down, code:%d \n", gpio, code);
|
||||
} else {
|
||||
/* button released */
|
||||
if (button_pressed) {
|
||||
input_report_key(input, code, 0);
|
||||
input_sync(input);
|
||||
button_pressed = 0;
|
||||
dprintk("gpio %d up, code:%d \n", gpio, code);
|
||||
}
|
||||
__gpio_as_irq_fall_edge(gpio);
|
||||
}
|
||||
} else {
|
||||
if (state == 1) {
|
||||
/* button pressed */
|
||||
button_pressed = 1;
|
||||
input_report_key(input, code, 1);
|
||||
input_sync(input);
|
||||
mod_timer(&button_timer, jiffies + SCAN_INTERVAL);
|
||||
dprintk("gpio %d down code:%d \n", gpio, code);
|
||||
} else {
|
||||
/* button released */
|
||||
if (button_pressed) {
|
||||
input_report_key(input, code, 0);
|
||||
input_sync(input);
|
||||
dprintk("gpio %d up code:%d \n", gpio, code);
|
||||
}
|
||||
__gpio_as_irq_rise_edge(gpio);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t jz_gpio_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
int i;
|
||||
struct platform_device *pdev = dev_id;
|
||||
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
|
||||
|
||||
dprintk("--irq of gpio:%d\n", irq - IRQ_GPIO_0);
|
||||
|
||||
__gpio_ack_irq(irq - IRQ_GPIO_0); /* clear flag */
|
||||
|
||||
if (!timer_pending(&button_timer)) {
|
||||
for (i = 0; i < pdata->nbuttons; i++) {
|
||||
struct gpio_keys_button *button = &pdata->buttons[i];
|
||||
int gpio = button->gpio;
|
||||
|
||||
if (irq == (gpio + IRQ_GPIO_0) ) {
|
||||
/* start timer */
|
||||
__gpio_as_input(gpio);
|
||||
button_no = i;
|
||||
mod_timer(&button_timer, jiffies + SCAN_INTERVAL);
|
||||
dprintk("--mod_timer for gpio:%d\n", gpio);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int __devinit gpio_keys_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct input_dev *input;
|
||||
int i, error;
|
||||
int wakeup = 0;
|
||||
|
||||
input = input_allocate_device();
|
||||
if (!input)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, input);
|
||||
|
||||
input->name = pdev->name;
|
||||
input->dev.parent = &pdev->dev;
|
||||
|
||||
input->id.bustype = BUS_HOST;
|
||||
input->id.vendor = 0x0001;
|
||||
input->id.product = 0x0001;
|
||||
input->id.version = 0x0100;
|
||||
|
||||
input->evbit[0] = BIT(EV_KEY) | BIT(EV_SYN);
|
||||
|
||||
set_bit(ANDROID_MENU, input->keybit);
|
||||
set_bit(ANDROID_HOME, input->keybit);
|
||||
set_bit(ANDROID_CALL, input->keybit);
|
||||
set_bit(ANDROID_BACK, input->keybit);
|
||||
set_bit(ANDROID_ENDCALL, input->keybit);
|
||||
|
||||
for (i = 0; i < pdata->nbuttons; i++) {
|
||||
struct gpio_keys_button *button = &pdata->buttons[i];
|
||||
int irq;
|
||||
unsigned int type = button->type ?: EV_KEY;
|
||||
|
||||
irq = IRQ_GPIO_0 + button->gpio;
|
||||
if (irq < 0) {
|
||||
error = irq;
|
||||
pr_err("%s: Unable to get irq number"
|
||||
" for GPIO %d, error %d\n", DEV_NAME,
|
||||
button->gpio, error);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
error = request_irq(irq, jz_gpio_interrupt,
|
||||
IRQF_SAMPLE_RANDOM | IRQF_DISABLED,
|
||||
button->desc ? button->desc : "gpio_keys",
|
||||
pdev);
|
||||
if (error) {
|
||||
pr_err("%s: Unable to claim irq %d; error %d\n",
|
||||
DEV_NAME, irq, error);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (button->wakeup)
|
||||
wakeup = 1;
|
||||
|
||||
input_set_capability(input, type, button->code);
|
||||
}
|
||||
|
||||
/* Enable all GPIO irqs */
|
||||
enable_gpio_irqs(pdata);
|
||||
|
||||
/* Init timer */
|
||||
init_timer(&button_timer);
|
||||
button_timer.data = (unsigned long)&board_button_device;
|
||||
button_timer.function = button_timer_callback;
|
||||
|
||||
error = input_register_device(input);
|
||||
if (error) {
|
||||
pr_err("%s: Unable to register input device, "
|
||||
"error: %d\n", DEV_NAME, error);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
device_init_wakeup(&pdev->dev, wakeup);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
while (--i >= 0) {
|
||||
free_irq(pdata->buttons[i].gpio + IRQ_GPIO_0 , pdev);
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
input_free_device(input);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int __devexit gpio_keys_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct input_dev *input = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
device_init_wakeup(&pdev->dev, 0);
|
||||
|
||||
for (i = 0; i < pdata->nbuttons; i++) {
|
||||
int irq = pdata->buttons[i].gpio + IRQ_GPIO_0;
|
||||
free_irq(irq, pdev);
|
||||
}
|
||||
|
||||
input_unregister_device(input);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int gpio_keys_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
#if 0
|
||||
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
|
||||
int i;
|
||||
|
||||
if (device_may_wakeup(&pdev->dev)) {
|
||||
for (i = 0; i < pdata->nbuttons; i++) {
|
||||
struct gpio_keys_button *button = &pdata->buttons[i];
|
||||
if (button->wakeup) {
|
||||
int irq = button->gpio + IRQ_GPIO_0;
|
||||
enable_irq_wake(irq);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_keys_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
|
||||
#if 0
|
||||
int i;
|
||||
|
||||
if (device_may_wakeup(&pdev->dev)) {
|
||||
for (i = 0; i < pdata->nbuttons; i++) {
|
||||
struct gpio_keys_button *button = &pdata->buttons[i];
|
||||
if (button->wakeup) {
|
||||
int irq = button->gpio + IRQ_GPIO_0;
|
||||
disable_irq_wake(irq);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Enable all GPIO irqs */
|
||||
enable_gpio_irqs(pdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define gpio_keys_suspend NULL
|
||||
#define gpio_keys_resume NULL
|
||||
#endif
|
||||
|
||||
static struct platform_driver gpio_keys_device_driver = {
|
||||
.probe = gpio_keys_probe,
|
||||
.remove = __devexit_p(gpio_keys_remove),
|
||||
.suspend = gpio_keys_suspend,
|
||||
.resume = gpio_keys_resume,
|
||||
.driver = {
|
||||
.name = DEV_NAME,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init gpio_keys_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
platform_device_register(&board_button_device);
|
||||
ret = platform_driver_register(&gpio_keys_device_driver);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit gpio_keys_exit(void)
|
||||
{
|
||||
platform_device_unregister(&board_button_device);
|
||||
platform_driver_unregister(&gpio_keys_device_driver);
|
||||
}
|
||||
|
||||
module_init(gpio_keys_init);
|
||||
module_exit(gpio_keys_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Regen Huang <lhhuang@ingenic.cn>");
|
||||
MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs");
|
||||
357
target/linux/xburst/files-2.6.27/drivers/input/keyboard/jz_keypad.c
Executable file
357
target/linux/xburst/files-2.6.27/drivers/input/keyboard/jz_keypad.c
Executable file
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* linux/drivers/input/keyboard/jz_keypad.c
|
||||
*
|
||||
* JZ Keypad Driver
|
||||
*
|
||||
* Copyright (c) 2005 - 2008 Ingenic Semiconductor Inc.
|
||||
*
|
||||
* Author: Richard <cjfeng@ingenic.cn>
|
||||
*
|
||||
* 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/version.h>
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/gpio_keys.h>
|
||||
|
||||
#include <asm/gpio.h>
|
||||
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
#define KB_ROWS 3
|
||||
#define KB_COLS 3
|
||||
|
||||
#define SCAN_INTERVAL (10)
|
||||
|
||||
static unsigned short col[KB_COLS] = {85,87,91};
|
||||
static unsigned short row[KB_ROWS] = {60,61,62};
|
||||
static unsigned short s0[KB_COLS];
|
||||
static unsigned short s1[KB_COLS]={7,7,7};
|
||||
static unsigned short precol,prerow;
|
||||
|
||||
static const unsigned int jz_kbd_keycode[KB_COLS * KB_ROWS] = {
|
||||
KEY_1, KEY_4, KEY_7,
|
||||
KEY_2, KEY_5, 0,
|
||||
KEY_3, KEY_6, 0,
|
||||
};
|
||||
|
||||
struct jz_kbd {
|
||||
unsigned int keycode[ARRAY_SIZE(jz_kbd_keycode)];
|
||||
struct input_dev *input;
|
||||
char phys[32];
|
||||
|
||||
spinlock_t lock;
|
||||
struct timer_list timer;
|
||||
|
||||
unsigned int suspended;
|
||||
unsigned long suspend_jiffies;
|
||||
};
|
||||
|
||||
static struct jz_kbd g_jz_kbd;
|
||||
|
||||
static inline void jz_scan_kbd(unsigned short *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
for (i = 0; i < KB_COLS; i++) {
|
||||
|
||||
__gpio_as_input(85); /* row */
|
||||
__gpio_as_input(87); /* row */
|
||||
__gpio_as_input(91); /* row */
|
||||
|
||||
__gpio_as_input(60); /* col */
|
||||
__gpio_as_input(61); /* col */
|
||||
__gpio_as_input(62); /* col */
|
||||
|
||||
__gpio_clear_pin(col[i]);
|
||||
__gpio_as_output(col[i]);
|
||||
|
||||
udelay(1000);
|
||||
s[i]=(__gpio_get_pin(60) << 0) | (__gpio_get_pin(61) << 1) |
|
||||
(__gpio_get_pin(62) << 2);
|
||||
}
|
||||
}
|
||||
|
||||
static void jz_kbd_scankeyboard(struct jz_kbd *kbd_data)
|
||||
{
|
||||
unsigned int row,col;
|
||||
unsigned long flags;
|
||||
unsigned int num_pressed;
|
||||
|
||||
if (kbd_data->suspended)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&kbd_data->lock, flags);
|
||||
|
||||
num_pressed = 0;
|
||||
jz_scan_kbd(s0);
|
||||
|
||||
/* look for key if pressed down on not, col & row */
|
||||
if (s0[0] == 7 && s0[1] == 7 && s0[2] == 7) {
|
||||
if (s1[0] != 7 || s1[1] != 7 || s1[2] != 7) {
|
||||
/* up */
|
||||
input_report_key(kbd_data->input, kbd_data->keycode[prerow * KB_COLS + precol], 0);
|
||||
input_sync(kbd_data->input);
|
||||
}
|
||||
precol = prerow = -1;
|
||||
s1[0] = s1[1] = s1[2] = 7;
|
||||
spin_unlock_irqrestore(&kbd_data->lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
if (s0[0] == 6 && s0[1] == 7 && s0[2] == 7) {
|
||||
row = 0;//K7
|
||||
col = 2;
|
||||
goto find_row_col;
|
||||
}
|
||||
if (s0[0] == 7 && s0[1] == 3 && s0[2] == 7) {
|
||||
row = 2;//k6
|
||||
col = 1;
|
||||
goto find_row_col;
|
||||
}
|
||||
if (s0[0] == 7 && s0[1] == 5 && s0[2] == 7) {
|
||||
row = 1;//k5
|
||||
col = 1;
|
||||
goto find_row_col;
|
||||
}
|
||||
if (s0[0] == 7 && s0[1] == 6 && s0[2] == 7) {
|
||||
row = 0;//k4
|
||||
col = 1;
|
||||
goto find_row_col;
|
||||
}
|
||||
if (s0[0] == 7 && s0[1] == 7 && s0[2] == 3) {
|
||||
row = 2;//k3
|
||||
col = 0;
|
||||
goto find_row_col;
|
||||
}
|
||||
if (s0[0] == 7 && s0[1] == 7 && s0[2] == 5) {
|
||||
row = 1;//k2
|
||||
col = 0;
|
||||
goto find_row_col;
|
||||
}
|
||||
if (s0[0] == 7 && s0[1] == 7 && s0[2] == 6) {
|
||||
row = 0;//k1
|
||||
col = 0;
|
||||
goto find_row_col;
|
||||
}
|
||||
/* 2 or 3 buttons are pressed */
|
||||
s0[0] = s0[1] = s0[2] = 7;
|
||||
s1[0] = s1[1] = s1[2] = 7;
|
||||
prerow = precol = -1;
|
||||
spin_unlock_irqrestore(&kbd_data->lock, flags);
|
||||
return;
|
||||
find_row_col:
|
||||
if (s1[0] == 7 && s1[1] == 7 && s1[2] == 7) {
|
||||
/* down */
|
||||
input_report_key(kbd_data->input, kbd_data->keycode[row * KB_COLS + col], 1);
|
||||
input_sync(kbd_data->input);
|
||||
s1[0] = s0[0];
|
||||
s1[1] = s0[1];
|
||||
s1[2] = s0[2];
|
||||
|
||||
precol = col;
|
||||
prerow = row;
|
||||
spin_unlock_irqrestore(&kbd_data->lock, flags);
|
||||
return;
|
||||
}
|
||||
if (s1[0] != 7 || s1[1] != 7 || s1[2] != 7) {
|
||||
/* is the same as the preview key */
|
||||
if (s0[0] == s1[0] && s0[1] == s1[1] && s0[2] == s1[2]) {
|
||||
input_report_key(kbd_data->input, kbd_data->keycode[row * KB_COLS + col], 1);
|
||||
input_sync(kbd_data->input);
|
||||
s1[0] = s0[0];
|
||||
s1[1] = s0[1];
|
||||
s1[2] = s0[2];
|
||||
|
||||
precol = col;
|
||||
prerow = row;
|
||||
spin_unlock_irqrestore(&kbd_data->lock, flags);
|
||||
return;
|
||||
} else {
|
||||
/* the preview key is up and other key is down */
|
||||
if (s0[0] != s1[0] || s0[1] != s1[1] || s0[2] != s1[2]) {
|
||||
input_report_key(kbd_data->input, kbd_data->keycode[prerow * KB_COLS + precol], 0);
|
||||
input_sync(kbd_data->input);
|
||||
input_report_key(kbd_data->input, kbd_data->keycode[row * KB_COLS + col], 1);
|
||||
input_sync(kbd_data->input);
|
||||
s1[0] = s0[0];
|
||||
s1[1] = s0[1];
|
||||
s1[2] = s0[2];
|
||||
precol = col;
|
||||
prerow = row;
|
||||
spin_unlock_irqrestore(&kbd_data->lock, flags);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void jz_kbd_timer_callback(unsigned long data)
|
||||
{
|
||||
jz_kbd_scankeyboard(&g_jz_kbd);
|
||||
mod_timer(&g_jz_kbd.timer, jiffies + SCAN_INTERVAL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int jz_kbd_suspend(struct platform_device *dev, pm_message_t state)
|
||||
{
|
||||
struct jz_kbd *jz_kbd = platform_get_drvdata(dev);
|
||||
jz_kbd->suspended = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jz_kbd_resume(struct platform_device *dev)
|
||||
{
|
||||
struct jz_kbd *jz_kbd = platform_get_drvdata(dev);
|
||||
|
||||
jz_kbd->suspend_jiffies = jiffies;
|
||||
jz_kbd->suspended = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define jz_kbd_suspend NULL
|
||||
#define jz_kbd_resume NULL
|
||||
#endif
|
||||
|
||||
static int __init jz_kbd_probe(struct platform_device *dev)
|
||||
{
|
||||
struct input_dev *input_dev;
|
||||
int i, error;
|
||||
|
||||
input_dev = input_allocate_device();
|
||||
if (!input_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(dev, &g_jz_kbd);
|
||||
|
||||
strcpy(g_jz_kbd.phys, "input/kbd0");
|
||||
|
||||
spin_lock_init(&g_jz_kbd.lock);
|
||||
|
||||
g_jz_kbd.suspend_jiffies = jiffies;
|
||||
g_jz_kbd.input = input_dev;
|
||||
|
||||
input_dev->private = &g_jz_kbd;
|
||||
input_dev->name = "JZ Keypad";
|
||||
input_dev->phys = g_jz_kbd.phys;
|
||||
input_dev->cdev.dev = &dev->dev;
|
||||
|
||||
input_dev->id.bustype = BUS_PARPORT;
|
||||
input_dev->id.vendor = 0x0001;
|
||||
input_dev->id.product = 0x0001;
|
||||
input_dev->id.version = 0x0100;
|
||||
|
||||
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_SYN);
|
||||
input_dev->keycode = g_jz_kbd.keycode; /* keycode array address */
|
||||
input_dev->keycodesize = sizeof(unsigned int);
|
||||
input_dev->keycodemax = ARRAY_SIZE(jz_kbd_keycode);
|
||||
|
||||
memcpy(g_jz_kbd.keycode, jz_kbd_keycode, sizeof(g_jz_kbd.keycode));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(jz_kbd_keycode); i++)
|
||||
set_bit(g_jz_kbd.keycode[i], input_dev->keybit);
|
||||
|
||||
//clear_bit(0, input_dev->keybit);
|
||||
|
||||
__gpio_as_input(85);
|
||||
__gpio_as_input(87);
|
||||
__gpio_as_input(91);
|
||||
|
||||
#if 0
|
||||
__gpio_as_input(60);
|
||||
__gpio_as_input(61);
|
||||
__gpio_as_input(62);
|
||||
#endif
|
||||
|
||||
/* Init Keyboard rescan timer */
|
||||
init_timer(&g_jz_kbd.timer);
|
||||
g_jz_kbd.timer.function = jz_kbd_timer_callback;
|
||||
g_jz_kbd.timer.data = (unsigned long)&g_jz_kbd;
|
||||
mod_timer(&g_jz_kbd.timer, jiffies + SCAN_INTERVAL);
|
||||
|
||||
error = input_register_device(input_dev);
|
||||
if (error) {
|
||||
pr_err("gpio-keys: Unable to register input device, "
|
||||
"error: %d\n", error);
|
||||
}
|
||||
printk("input: JZ Keypad Registered\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jz_kbd_remove(struct platform_device *dev)
|
||||
{
|
||||
struct jz_kbd *jz_kbd = platform_get_drvdata(dev);
|
||||
|
||||
del_timer_sync(&jz_kbd->timer);
|
||||
|
||||
__gpio_as_input(85);
|
||||
__gpio_as_input(87);
|
||||
__gpio_as_input(91);
|
||||
|
||||
/* These pins is conficting with cs8900a's CS RD WE pins on JZ4740-PAVO board */
|
||||
__gpio_as_input(60);
|
||||
__gpio_as_input(61);
|
||||
__gpio_as_input(62);
|
||||
|
||||
input_unregister_device(jz_kbd->input);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver jz_kbd_driver = {
|
||||
.probe = jz_kbd_probe,
|
||||
.remove = jz_kbd_remove,
|
||||
.suspend = jz_kbd_suspend,
|
||||
.resume = jz_kbd_resume,
|
||||
.driver = {
|
||||
.name = "jz-keypad",
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Jz Keyboard Device
|
||||
*/
|
||||
static struct platform_device jzkbd_device = {
|
||||
.name = "jz-keypad",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static int __init jz_kbd_init(void)
|
||||
{
|
||||
platform_device_register(&jzkbd_device);
|
||||
return platform_driver_register(&jz_kbd_driver);
|
||||
}
|
||||
|
||||
static void __exit jz_kbd_exit(void)
|
||||
{
|
||||
platform_device_unregister(&jzkbd_device);
|
||||
platform_driver_unregister(&jz_kbd_driver);
|
||||
}
|
||||
|
||||
module_init(jz_kbd_init);
|
||||
module_exit(jz_kbd_exit);
|
||||
|
||||
MODULE_AUTHOR("Richard");
|
||||
MODULE_DESCRIPTION("JZ keypad driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* JZ Keypad ( 5 x 5 ) Driver
|
||||
*
|
||||
* Copyright (c) 2005 - 2008 Ingenic Semiconductor Inc.
|
||||
*
|
||||
* Author: Jason <xwang@ingenic.cn> 20090210
|
||||
*
|
||||
* 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/version.h>
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/delay.h>
|
||||
//#include <linux/platform_device.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/gpio_keys.h>
|
||||
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
#define KB_ROWS 5
|
||||
#define KB_COLS 5
|
||||
#define KB_COUNT 25
|
||||
|
||||
|
||||
#define JZ_KEY_PRESSED 0x01
|
||||
#define JZ_KEY_RELEASED 0x00
|
||||
|
||||
#define SCAN_INTERVAL 10 /* jiffies */
|
||||
|
||||
#define ROW_KEYBIT_MASK 0xFFE0
|
||||
|
||||
#define SET_GPIOS_AS_INPUT() \
|
||||
do { \
|
||||
unsigned short i; \
|
||||
\
|
||||
for (i = 0; i < KB_ROWS; i++) { \
|
||||
__gpio_as_input(jz_row_gpios[i]); \
|
||||
__gpio_as_input(jz_col_gpios[i]); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define GET_ROW_GPIO_PINS() \
|
||||
({ \
|
||||
unsigned short _pins = 0, i; \
|
||||
for (i = 0; \
|
||||
i < KB_ROWS; \
|
||||
_pins |= __gpio_get_pin(jz_row_gpios[i]) << i, i++) \
|
||||
; \
|
||||
_pins; \
|
||||
})
|
||||
|
||||
#define CHECK_IF_KEY_PRESSED(s) \
|
||||
({ \
|
||||
unsigned short i; \
|
||||
for (i = 0; i < KB_COLS && s[i] == 0x1F ; i++) \
|
||||
; \
|
||||
i != KB_ROWS; \
|
||||
})
|
||||
|
||||
#define CLEAN_SCAN_RESULT(s) \
|
||||
do { \
|
||||
unsigned short i; \
|
||||
for (i = 0; i < KB_COLS; s[i++] = 0x1F) \
|
||||
; \
|
||||
} while (0)
|
||||
|
||||
|
||||
static const unsigned short jz_col_gpios[KB_ROWS] = {76, 75, 74, 73, 72};
|
||||
static const unsigned short jz_row_gpios[KB_COLS] = {181, 182, 79, 78, 77};
|
||||
|
||||
static const unsigned int jz_kbd_keycode[KB_ROWS * KB_COLS] = {
|
||||
KEY_A, KEY_B, KEY_C, KEY_D, KEY_E,
|
||||
KEY_F, KEY_G, KEY_H, KEY_I, KEY_J,
|
||||
KEY_K, KEY_L, KEY_M, KEY_N, KEY_O,
|
||||
KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T,
|
||||
KEY_LEFTSHIFT, KEY_LEFTCTRL, KEY_LEFTALT, KEY_BACKSPACE, KEY_ENTER
|
||||
};
|
||||
|
||||
static unsigned short jz_kbd_status[KB_ROWS * KB_COLS] = {0};
|
||||
|
||||
struct jz_kbd {
|
||||
unsigned int keycode[ARRAY_SIZE(jz_kbd_keycode)];
|
||||
struct input_dev *input;
|
||||
char phys[32];
|
||||
|
||||
spinlock_t lock;
|
||||
struct timer_list timer;
|
||||
|
||||
unsigned int suspended;
|
||||
unsigned long suspend_jiffies;
|
||||
};
|
||||
static struct jz_kbd g_jz_kbd;
|
||||
|
||||
/* An element shows the scan result of a whole row. LSB --> column 0 */
|
||||
static unsigned short scan_result[KB_ROWS];
|
||||
|
||||
/**
|
||||
* Scan keypad by reading GPIO pins.
|
||||
*/
|
||||
static inline void jz_do_scan(unsigned short *s)
|
||||
{
|
||||
unsigned short i;
|
||||
|
||||
if (!s)
|
||||
return ;
|
||||
|
||||
for (i = 0; i < KB_COLS; i++) {
|
||||
|
||||
SET_GPIOS_AS_INPUT();
|
||||
__gpio_clear_pin(jz_col_gpios[i]);
|
||||
__gpio_as_output(jz_col_gpios[i]);
|
||||
|
||||
udelay(1000);
|
||||
|
||||
s[i] = GET_ROW_GPIO_PINS();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call scan function and handle 'GPIO event'(like key down, key up),
|
||||
* and report it to upper layer of input subsystem ... if necessary
|
||||
*/
|
||||
static void jz_kbd_scan(struct jz_kbd *kbd_data)
|
||||
{
|
||||
unsigned short row, col;
|
||||
unsigned long flags;
|
||||
|
||||
if (kbd_data->suspended)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&kbd_data->lock, flags);
|
||||
|
||||
jz_do_scan(scan_result);
|
||||
|
||||
/* handle gpio event */
|
||||
for (row = 0; row < KB_ROWS; row++) {
|
||||
for (col = 0; col < KB_COLS; col++) {
|
||||
|
||||
if ( !(scan_result[row] & 0x01) ) {
|
||||
/* oh! a key pressed ... may be it is not news ...*/
|
||||
input_report_key(kbd_data->input, kbd_data->keycode[row * KB_COLS + col], 1);
|
||||
input_sync(kbd_data->input);
|
||||
jz_kbd_status[row * KB_ROWS + col] = JZ_KEY_PRESSED;
|
||||
|
||||
} else {
|
||||
/* if the key has been pressed ... release it */
|
||||
if (jz_kbd_status[row * KB_ROWS + col]) {
|
||||
input_report_key(kbd_data->input, kbd_data->keycode[row * KB_COLS + col], 0);
|
||||
input_sync(kbd_data->input);
|
||||
jz_kbd_status[row * KB_ROWS + col] = JZ_KEY_RELEASED;
|
||||
}
|
||||
}
|
||||
|
||||
scan_result[row] >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&kbd_data->lock, flags);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void jz_kbd_timer_callback(unsigned long data)
|
||||
{
|
||||
jz_kbd_scan(&g_jz_kbd);
|
||||
mod_timer(&g_jz_kbd.timer, jiffies + SCAN_INTERVAL);
|
||||
}
|
||||
|
||||
static int __init jz_kbd_init(void)
|
||||
{
|
||||
struct input_dev *input_dev;
|
||||
int i, error;
|
||||
|
||||
input_dev = input_allocate_device();
|
||||
if (!input_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
strcpy(g_jz_kbd.phys, "input/kbd0");
|
||||
|
||||
spin_lock_init(&g_jz_kbd.lock);
|
||||
|
||||
g_jz_kbd.suspend_jiffies = jiffies;
|
||||
g_jz_kbd.input = input_dev;
|
||||
|
||||
input_dev->name = "JZ 5x5 Keypad";
|
||||
input_dev->phys = g_jz_kbd.phys;
|
||||
input_dev->id.bustype = BUS_PARPORT;
|
||||
input_dev->id.vendor = 0x0001;
|
||||
input_dev->id.product = 0x0001;
|
||||
input_dev->id.version = 0x0100;
|
||||
|
||||
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_SYN);
|
||||
input_dev->keycode = g_jz_kbd.keycode;
|
||||
input_dev->keycodesize = sizeof(unsigned int);
|
||||
input_dev->keycodemax = ARRAY_SIZE(jz_kbd_keycode);
|
||||
|
||||
memcpy(g_jz_kbd.keycode, jz_kbd_keycode, sizeof(g_jz_kbd.keycode));
|
||||
|
||||
for ( i = 0; i < ARRAY_SIZE(jz_kbd_keycode); i++)
|
||||
set_bit(g_jz_kbd.keycode[i], input_dev->keybit);
|
||||
|
||||
init_timer(&g_jz_kbd.timer);
|
||||
g_jz_kbd.timer.function = jz_kbd_timer_callback;
|
||||
g_jz_kbd.timer.data = (unsigned long)&g_jz_kbd;
|
||||
mod_timer(&g_jz_kbd.timer, jiffies + SCAN_INTERVAL);
|
||||
|
||||
input_set_drvdata(input_dev, &g_jz_kbd);
|
||||
error = input_register_device(input_dev);
|
||||
if (error) {
|
||||
pr_err("gpio-keys: Unable to register input device, "
|
||||
"error: %d\n", error);
|
||||
}
|
||||
printk("input: JZ 5x5 Keypad Registered.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit jz_kbd_exit(void)
|
||||
{
|
||||
del_timer_sync(&g_jz_kbd.timer);
|
||||
|
||||
SET_GPIOS_AS_INPUT();
|
||||
|
||||
input_unregister_device(g_jz_kbd.input);
|
||||
}
|
||||
|
||||
module_init(jz_kbd_init);
|
||||
module_exit(jz_kbd_exit);
|
||||
|
||||
MODULE_AUTHOR("Jason <xwang@ingenic.cn>");
|
||||
MODULE_DESCRIPTION("JZ 5x5 keypad driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1,789 @@
|
||||
/*
|
||||
* JZ Touch Screen Driver
|
||||
*
|
||||
* Copyright (c) 2005 - 2009 Ingenic Semiconductor Inc.
|
||||
*
|
||||
* Author: Jason <xwang@ingenic.cn> 20090219
|
||||
* Regen <lhhuang@ingenic.cn> 20090324 add adkey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/freezer.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/jzsoc.h>
|
||||
|
||||
#define TS_NAME "jz-ts"
|
||||
|
||||
#define KEY_SCAN_INTERVAL 5
|
||||
#define TS_SCAN_INTERVAL 0
|
||||
|
||||
/* from qwerty.kl of android */
|
||||
#define DPAD_CENTER 232
|
||||
#define DPAD_DOWN 108
|
||||
#define DPAD_UP 103
|
||||
#define DPAD_LEFT 105
|
||||
#define DPAD_RIGHT 106
|
||||
|
||||
/* TS event status */
|
||||
#define PENUP 0x00
|
||||
#define PENDOWN 0x01
|
||||
|
||||
/* Sample times in one sample process */
|
||||
#define SAMPLE_TIMES 3
|
||||
|
||||
/* Min pressure value. If less than it, filt the point.
|
||||
* Mask it if it is not useful for you
|
||||
*/
|
||||
//#define MIN_PRESSURE 0x100
|
||||
|
||||
/* Max delta x distance between current point and last point. */
|
||||
#define MAX_DELTA_X_OF_2_POINTS 200
|
||||
/* Max delta x distance between current point and last point. */
|
||||
#define MAX_DELTA_Y_OF_2_POINTS 120
|
||||
|
||||
/* Max delta between points in one sample process
|
||||
* Verify method :
|
||||
* (diff value / min value) * 100 <= MAX_DELTA_OF_SAMPLING
|
||||
*/
|
||||
#define MAX_DELTA_OF_SAMPLING 20
|
||||
|
||||
#define DIFF(a,b) (((a)>(b))?((a)-(b)):((b)-(a)))
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* TS deriver
|
||||
*/
|
||||
struct jz_ts_t {
|
||||
int pendown_irq; // IRQ of pendown interrupt
|
||||
int pen_is_down; // 1 = pen is down, 0 = pen is up
|
||||
int irq_enabled;
|
||||
struct timer_list acq_timer; // Timer for triggering acquisitions
|
||||
#ifdef CONFIG_JZ_ADKEY
|
||||
struct timer_list key_timer; // for adkey
|
||||
int active_low; // for adkey's interrupt pin
|
||||
#endif
|
||||
wait_queue_head_t wait; // read wait queue
|
||||
spinlock_t lock;
|
||||
|
||||
/* Following 4 members use to pass arguments from u-boot to tell us the ts data.
|
||||
* But in Android we do not use them.
|
||||
*/
|
||||
/*
|
||||
int minx, miny, maxx, maxy;
|
||||
*/
|
||||
int first_read;
|
||||
|
||||
char phys[32];
|
||||
struct input_dev *input_dev;
|
||||
};
|
||||
|
||||
/*
|
||||
* TS Event type
|
||||
*/
|
||||
struct ts_event {
|
||||
u16 status;
|
||||
u16 x;
|
||||
u16 y;
|
||||
u16 pressure;
|
||||
u16 pad;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_JZ_ADKEY
|
||||
struct ad_keys_button {
|
||||
int code; /* input event code */
|
||||
int val; /* the ad value of the key */
|
||||
int fuzz; /* the error(+-fuzz) allowed of the ad value of the key */
|
||||
};
|
||||
static struct ad_keys_button ad_buttons[] = {
|
||||
{
|
||||
.code = DPAD_LEFT,
|
||||
.val = DPAD_LEFT_LEVEL,
|
||||
.fuzz = 40,
|
||||
},
|
||||
{
|
||||
.code = DPAD_DOWN,
|
||||
.val = DPAD_DOWN_LEVEL,
|
||||
.fuzz = 40,
|
||||
},
|
||||
{
|
||||
.code = DPAD_UP,
|
||||
.val = DPAD_UP_LEVEL,
|
||||
.fuzz = 40,
|
||||
},
|
||||
{
|
||||
.code = DPAD_CENTER,
|
||||
.val = DPAD_CENTER_LEVEL,
|
||||
.fuzz = 40,
|
||||
},
|
||||
{
|
||||
.code = DPAD_RIGHT,
|
||||
.val = DPAD_RIGHT_LEVEL,
|
||||
.fuzz = 40,
|
||||
},
|
||||
};
|
||||
#define KEY_NUM (sizeof(ad_buttons) / sizeof(struct ad_keys_button))
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
/* SAR ADC OPS */
|
||||
/************************************************************************/
|
||||
|
||||
typedef struct datasource {
|
||||
u16 xbuf;
|
||||
u16 ybuf;
|
||||
u16 zbuf;
|
||||
}datasource_t;
|
||||
|
||||
static datasource_t data_s;
|
||||
static unsigned int p;
|
||||
|
||||
static DECLARE_WAIT_QUEUE_HEAD (sadc_wait_queue);
|
||||
|
||||
static int first_time = 0;
|
||||
//static unsigned long last_x, last_y, last_p;
|
||||
static unsigned int old_x, old_y;
|
||||
|
||||
extern unsigned int (*codec_read_battery)(void);
|
||||
#if 0
|
||||
static void reg_debug(void)
|
||||
{
|
||||
printk("\t####CTRL####################################################\n");
|
||||
printk("\tPEND %s, ", REG_SADC_CTRL & SADC_CTRL_PENDM ? "masked" : "enabled");
|
||||
printk("PENU %s, ", REG_SADC_CTRL & SADC_CTRL_PENUM ? "masked" : "enabled");
|
||||
printk("TSRDY %s\n", REG_SADC_CTRL & SADC_CTRL_TSRDYM ? "masked" : "enabled");
|
||||
printk("\t----STATE---------------------------------------------------\n");
|
||||
printk("\tIRQ actived: %s, %s, %s\n",
|
||||
REG_SADC_STATE & SADC_STATE_PEND ? "pen down" : " ",
|
||||
REG_SADC_STATE & SADC_STATE_PENU ? "pen up " : " ",
|
||||
REG_SADC_STATE & SADC_STATE_TSRDY ? "sample " : " ");
|
||||
printk("\t############################################################\n");
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* set adc clock to 24MHz/div. A/D works at freq between 500KHz to 8MHz.
|
||||
*/
|
||||
static void sadc_init_clock(int div)
|
||||
{
|
||||
if (div < 2) div = 2;
|
||||
if (div > 23) div = 23;
|
||||
#if defined(CONFIG_SOC_JZ4740)
|
||||
REG_SADC_CFG &= ~SADC_CFG_CLKDIV_MASK;
|
||||
REG_SADC_CFG |= (div - 1) << SADC_CFG_CLKDIV_BIT;
|
||||
#endif
|
||||
#if defined(CONFIG_SOC_JZ4750) || defined(CONFIG_SOC_JZ4750D)
|
||||
REG_SADC_ADCLK &= ~SADC_ADCLK_CLKDIV_MASK;
|
||||
REG_SADC_ADCLK |= (div - 1) << SADC_ADCLK_CLKDIV_BIT;
|
||||
REG_SADC_ADCLK &= ~SADC_ADCLK_CLKDIV_BIT;
|
||||
REG_SADC_ADCLK |= 39 << SADC_ADCLK_CLKDIV_10_BIT; /* if div ==3,here is 39 */
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void sadc_start_sadcin(void)
|
||||
{
|
||||
REG_SADC_ENA |= SADC_ENA_SADCINEN;
|
||||
}
|
||||
|
||||
static void sadc_start_pbat(void)
|
||||
{
|
||||
if (CFG_PBAT_DIV == 1)
|
||||
REG_SADC_CFG |= SADC_CFG_PBAT_HIGH; /* full baterry voltage >= 2.5V */
|
||||
else
|
||||
REG_SADC_CFG |= SADC_CFG_PBAT_LOW; /* full baterry voltage < 2.5V */
|
||||
REG_SADC_ENA |= SADC_ENA_PBATEN; /* Enable pbat adc */
|
||||
}
|
||||
|
||||
static inline void ts_enable_pendown_irq(void)
|
||||
{
|
||||
REG_SADC_CTRL &= ~SADC_CTRL_PENDM;
|
||||
}
|
||||
|
||||
static inline void ts_enable_penup_irq(void)
|
||||
{
|
||||
REG_SADC_CTRL &= ~SADC_CTRL_PENUM;
|
||||
}
|
||||
|
||||
static inline void ts_disable_pendown_irq(void)
|
||||
{
|
||||
REG_SADC_CTRL |= SADC_CTRL_PENDM;
|
||||
}
|
||||
|
||||
static inline void ts_disable_penup_irq(void)
|
||||
{
|
||||
REG_SADC_CTRL |= SADC_CTRL_PENUM;
|
||||
}
|
||||
|
||||
static inline void sadc_enable_ts(void)
|
||||
{
|
||||
REG_SADC_ENA |= SADC_ENA_TSEN;
|
||||
}
|
||||
|
||||
static inline void sadc_disable_ts(void)
|
||||
{
|
||||
REG_SADC_ENA &= ~SADC_ENA_TSEN;
|
||||
}
|
||||
|
||||
static inline void sadc_start_ts(void)
|
||||
{
|
||||
REG_SADC_SAMETIME = 10; /* about 0.1 ms,you can change it */
|
||||
REG_SADC_WAITTIME = 2; /* about 0.02 ms,you can change it */
|
||||
|
||||
REG_SADC_CFG &= ~(SADC_CFG_TS_DMA | SADC_CFG_XYZ_MASK | SADC_CFG_SNUM_MASK);
|
||||
REG_SADC_CFG |= (SADC_CFG_EXIN | SADC_CFG_XYZ | SADC_CFG_SNUM_3);
|
||||
|
||||
REG_SADC_CTRL |= (SADC_CTRL_TSRDYM | SADC_CTRL_PBATRDYM | SADC_CTRL_PENUM |SADC_CTRL_SRDYM);
|
||||
|
||||
ts_enable_pendown_irq();
|
||||
|
||||
sadc_enable_ts();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the battery voltage
|
||||
*/
|
||||
unsigned int jz_read_battery(void)
|
||||
{
|
||||
unsigned int v;
|
||||
unsigned int timeout = 0x3fff;
|
||||
u16 pbat;
|
||||
|
||||
if(!(REG_SADC_STATE & SADC_STATE_PBATRDY) ==1)
|
||||
sadc_start_pbat();
|
||||
|
||||
while(!(REG_SADC_STATE & SADC_STATE_PBATRDY) && --timeout)
|
||||
;
|
||||
|
||||
pbat = REG_SADC_BATDAT;
|
||||
v = pbat & 0x0fff;
|
||||
REG_SADC_STATE = SADC_STATE_PBATRDY;
|
||||
return v;
|
||||
}
|
||||
|
||||
#define TSMAXX 3920
|
||||
#define TSMAXY 3700
|
||||
#define TSMINX 150
|
||||
#define TSMINY 270
|
||||
|
||||
#define SCREEN_MAXX 479
|
||||
#define SCREEN_MAXY 271
|
||||
|
||||
static unsigned long transform_to_screen_x(struct jz_ts_t *ts, unsigned long x )
|
||||
{
|
||||
/* Now we don't need u-boot to tell us the ts data. */
|
||||
/*
|
||||
if (ts->minx)
|
||||
{
|
||||
if (x < ts->minx) x = ts->minx;
|
||||
if (x > ts->maxx) x = ts->maxx;
|
||||
|
||||
return (x - ts->minx) * SCREEN_MAXX / (ts->maxx - ts->minx);
|
||||
}
|
||||
else
|
||||
{
|
||||
*/
|
||||
if (x < TSMINX) x = TSMINX;
|
||||
if (x > TSMAXX) x = TSMAXX;
|
||||
|
||||
return (x - TSMINX) * SCREEN_MAXX / (TSMAXX - TSMINX);
|
||||
/*
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
static unsigned long transform_to_screen_y(struct jz_ts_t *ts, unsigned long y)
|
||||
{
|
||||
/* Now we don't need u-boot to tell us the ts data. */
|
||||
/*
|
||||
if (ts->miny)
|
||||
{
|
||||
if (y < ts->miny) y = ts->miny;
|
||||
if (y > ts->maxy) y = ts->maxy;
|
||||
|
||||
return (ts->maxy - y) * SCREEN_MAXY / (ts->maxy - ts->miny);
|
||||
}
|
||||
else
|
||||
{
|
||||
*/
|
||||
if (y < TSMINY) y = TSMINY;
|
||||
if (y > TSMAXY) y = TSMAXY;
|
||||
|
||||
return (TSMAXY - y) * SCREEN_MAXY / (TSMAXY - TSMINY);
|
||||
/*
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
static inline void ts_data_ready(void)
|
||||
{
|
||||
REG_SADC_CTRL |= SADC_CTRL_TSRDYM;
|
||||
}
|
||||
|
||||
static int adc_read(struct jz_ts_t *ts)
|
||||
{
|
||||
struct datasource *ds = &data_s;
|
||||
u32 xybuf,z;
|
||||
|
||||
while (!(REG_SADC_STATE & SADC_STATE_TSRDY)) {
|
||||
REG_SADC_CTRL &= ~SADC_CTRL_TSRDYM;
|
||||
}
|
||||
|
||||
xybuf = REG_SADC_TSDAT;
|
||||
ds->xbuf = (xybuf>>16) & 0x0fff;
|
||||
ds->ybuf = (xybuf)& 0x0fff;
|
||||
z = REG_SADC_TSDAT;
|
||||
ds->zbuf = z& 0x0fff;
|
||||
REG_SADC_STATE &= ~SADC_STATE_TSRDY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Acquire raw pen coodinate data and compute touch screen
|
||||
* pressure resistance. Hold spinlock when calling.
|
||||
*/
|
||||
int adc_acquire_event(struct jz_ts_t *ts, struct ts_event *event)
|
||||
{
|
||||
unsigned int x_raw[SAMPLE_TIMES], y_raw[SAMPLE_TIMES], p_raw[SAMPLE_TIMES];
|
||||
int i;
|
||||
unsigned int avl_x, avl_y, avl_p, diff_x, diff_y;
|
||||
struct datasource *ds = &data_s;
|
||||
avl_x = avl_y = avl_p = 0;
|
||||
|
||||
for (i = 0; i < SAMPLE_TIMES; i++) {
|
||||
if (adc_read(ts)) {
|
||||
goto _INVALID_POINT;
|
||||
}
|
||||
|
||||
x_raw[i] = ds->ybuf;
|
||||
y_raw[i] = ds->xbuf;
|
||||
p_raw[i] = ds->zbuf;
|
||||
|
||||
#ifdef MIN_PRESSURE
|
||||
if (p_raw[i] < MIN_PRESSURE) {
|
||||
goto _INVALID_POINT;
|
||||
}
|
||||
#endif
|
||||
avl_x += x_raw[i];
|
||||
avl_y += y_raw[i];
|
||||
avl_p += p_raw[i];
|
||||
#if 0
|
||||
printk("x_raw = %u , y_raw = %u , z_raw = %u\n",x_raw[i],y_raw[i],p_raw[i]);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
avl_x /= SAMPLE_TIMES;
|
||||
avl_y /= SAMPLE_TIMES;
|
||||
avl_p /= SAMPLE_TIMES;
|
||||
|
||||
/* Verify delta data. */
|
||||
for (i = 1; i < SAMPLE_TIMES; i++)
|
||||
{
|
||||
if ( ((DIFF(x_raw[i],x_raw[i-1]) / MIN(x_raw[i],x_raw[i-1])) * 100) > MAX_DELTA_OF_SAMPLING )
|
||||
goto _INVALID_POINT;
|
||||
|
||||
if ( ((DIFF(y_raw[i],y_raw[i-1]) / MIN(y_raw[i],y_raw[i-1])) * 100) > MAX_DELTA_OF_SAMPLING )
|
||||
goto _INVALID_POINT;
|
||||
|
||||
if ( ((DIFF(p_raw[i],p_raw[i-1]) / MIN(p_raw[i],p_raw[i-1])) * 100) > MAX_DELTA_OF_SAMPLING )
|
||||
goto _INVALID_POINT;
|
||||
}
|
||||
|
||||
/* Compare with last point. */
|
||||
if (ts->first_read) {
|
||||
ts->first_read = 0;
|
||||
old_x = avl_x;
|
||||
old_y = avl_y;
|
||||
}
|
||||
|
||||
diff_x = DIFF(old_x, avl_x);
|
||||
diff_y = DIFF(old_y, avl_y);
|
||||
|
||||
if (diff_x >= MAX_DELTA_X_OF_2_POINTS || diff_y >= MAX_DELTA_Y_OF_2_POINTS)
|
||||
goto _INVALID_POINT;
|
||||
|
||||
old_x = avl_x;
|
||||
old_y = avl_y;
|
||||
|
||||
|
||||
/* Android need it ... transform the raw value to screen coordinate. */
|
||||
event->x = transform_to_screen_x(ts, avl_x);
|
||||
event->y = transform_to_screen_y(ts, avl_y);
|
||||
|
||||
event->pressure = (u16)avl_p;
|
||||
event->status = PENDOWN;
|
||||
|
||||
return 1;
|
||||
|
||||
_INVALID_POINT:
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Interrupt handler
|
||||
*/
|
||||
void ts_irq_callback(void)
|
||||
{
|
||||
u32 state;
|
||||
|
||||
state = REG_SADC_STATE;
|
||||
if (!(REG_SADC_CTRL&SADC_CTRL_PENDM)&&(REG_SADC_STATE & SADC_STATE_PEND)) {
|
||||
REG_SADC_STATE = SADC_STATE_PEND;
|
||||
REG_SADC_STATE = SADC_STATE_PENU;
|
||||
REG_SADC_CTRL |= SADC_CTRL_PENDM;
|
||||
REG_SADC_CTRL &= ~SADC_CTRL_PENUM;
|
||||
p = 1;
|
||||
}
|
||||
|
||||
if (!(REG_SADC_CTRL&SADC_CTRL_PENUM)&&(REG_SADC_STATE & SADC_STATE_PENU)) {
|
||||
REG_SADC_STATE = SADC_STATE_PENU;
|
||||
REG_SADC_CTRL |= SADC_CTRL_PENUM;
|
||||
REG_SADC_CTRL &= ~SADC_CTRL_PENDM;
|
||||
p = 0;
|
||||
}
|
||||
|
||||
first_time = 1; // first time to acquire sample
|
||||
}
|
||||
|
||||
static inline int PenIsDown(void)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_JZ_ADKEY
|
||||
/**
|
||||
* Read the battery voltage
|
||||
*/
|
||||
static unsigned int read_sadcin(void)
|
||||
{
|
||||
unsigned int v;
|
||||
unsigned int timeout = 0x3ff;
|
||||
u16 val;
|
||||
|
||||
if(!(REG_SADC_STATE & SADC_STATE_SRDY))
|
||||
sadc_start_sadcin();
|
||||
|
||||
while(!(REG_SADC_STATE & SADC_STATE_SRDY) && --timeout)
|
||||
;
|
||||
|
||||
val = REG_SADC_SADDAT;
|
||||
v = val & 0x0fff;
|
||||
REG_SADC_STATE = SADC_STATE_SRDY;
|
||||
return v;
|
||||
}
|
||||
|
||||
static unsigned int key_scan(int ad_val)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i<KEY_NUM; i++) {
|
||||
if((ad_buttons[i].val + ad_buttons[i].fuzz >= ad_val) &&
|
||||
(ad_val >=ad_buttons[i].val - ad_buttons[i].fuzz)) {
|
||||
return ad_buttons[i].code;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void key_timer_callback(unsigned long data)
|
||||
{
|
||||
struct jz_ts_t *ts = (struct jz_ts_t *)data;
|
||||
int state;
|
||||
int active_low = ts->active_low;
|
||||
int ad_val, code;
|
||||
static int old_code;
|
||||
|
||||
spin_lock(&ts->lock);
|
||||
|
||||
state = __gpio_get_pin(GPIO_ADKEY_INT);
|
||||
ad_val = read_sadcin();
|
||||
|
||||
if (active_low) {
|
||||
if (state == 0) {
|
||||
/* press down */
|
||||
code = key_scan(ad_val);
|
||||
old_code = code;
|
||||
input_report_key(ts->input_dev, code, 1);
|
||||
input_sync(ts->input_dev);
|
||||
mod_timer(&ts->key_timer, jiffies + KEY_SCAN_INTERVAL);
|
||||
} else {
|
||||
/* up */
|
||||
input_report_key(ts->input_dev, old_code, 0);
|
||||
input_sync(ts->input_dev);
|
||||
udelay(1000);
|
||||
__gpio_as_irq_fall_edge(GPIO_ADKEY_INT);
|
||||
}
|
||||
} else {
|
||||
if (state == 1) {
|
||||
/* press down */
|
||||
code = key_scan(ad_val);
|
||||
old_code = code;
|
||||
input_report_key(ts->input_dev, code, 1);
|
||||
input_sync(ts->input_dev);
|
||||
mod_timer(&ts->key_timer, jiffies + KEY_SCAN_INTERVAL);
|
||||
} else {
|
||||
/* up */
|
||||
input_report_key(ts->input_dev, old_code, 0);
|
||||
input_sync(ts->input_dev);
|
||||
udelay(1000);
|
||||
__gpio_as_irq_rise_edge(GPIO_ADKEY_INT);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock(&ts->lock);
|
||||
}
|
||||
|
||||
static irqreturn_t key_interrupt(int irq, void * dev_id)
|
||||
{
|
||||
struct jz_ts_t *ts = dev_id;
|
||||
|
||||
spin_lock(&ts->lock);
|
||||
|
||||
__gpio_ack_irq(GPIO_ADKEY_INT);
|
||||
__gpio_as_input(GPIO_ADKEY_INT);
|
||||
sadc_start_sadcin();
|
||||
mod_timer(&ts->key_timer, jiffies + KEY_SCAN_INTERVAL);
|
||||
|
||||
spin_unlock(&ts->lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
/* Touch Screen module */
|
||||
/************************************************************************/
|
||||
|
||||
static int pen_is_down = 0;
|
||||
|
||||
static irqreturn_t pendown_interrupt(int irq, void * dev_id)
|
||||
{
|
||||
struct jz_ts_t *ts = dev_id;
|
||||
|
||||
spin_lock_irq(&ts->lock);
|
||||
|
||||
if (ts->irq_enabled)
|
||||
ts->irq_enabled = 0;
|
||||
else
|
||||
ts->irq_enabled = 1;
|
||||
|
||||
|
||||
if (pen_is_down)
|
||||
pen_is_down = 0;
|
||||
else
|
||||
pen_is_down = 1;
|
||||
|
||||
/* callback routine to clear irq status */
|
||||
ts_irq_callback();
|
||||
|
||||
if ( (pen_is_down == 0)){
|
||||
del_timer(&ts->acq_timer);
|
||||
ts->first_read = 0;
|
||||
input_report_abs(ts->input_dev, ABS_PRESSURE, 0);
|
||||
/* Android need it ... */
|
||||
input_report_key(ts->input_dev, BTN_TOUCH, 0);
|
||||
input_sync(ts->input_dev);
|
||||
|
||||
} else { // pen_is_down == 1
|
||||
|
||||
ts->acq_timer.expires = jiffies + TS_SCAN_INTERVAL;
|
||||
del_timer(&ts->acq_timer);
|
||||
ts->first_read = 1;
|
||||
add_timer(&ts->acq_timer);
|
||||
}
|
||||
|
||||
spin_unlock_irq(&ts->lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Raw X,Y,pressure acquisition timer function. It gets scheduled
|
||||
* only while pen is down. Its duration between calls is the polling
|
||||
* rate.
|
||||
*/
|
||||
static void
|
||||
jz_acq_timer(unsigned long data)
|
||||
{
|
||||
struct jz_ts_t *ts = (struct jz_ts_t *)data;
|
||||
struct ts_event event;
|
||||
int pen_was_down = ts->pen_is_down;
|
||||
|
||||
spin_lock_irq(&ts->lock);
|
||||
|
||||
if (PenIsDown()) {
|
||||
|
||||
ts->pen_is_down = 1;
|
||||
|
||||
if (adc_acquire_event(ts, &event)) {// check event is valid or not?
|
||||
input_report_abs(ts->input_dev, ABS_X, event.x);
|
||||
input_report_abs(ts->input_dev, ABS_Y, event.y);
|
||||
input_report_abs(ts->input_dev, ABS_PRESSURE, event.pressure);
|
||||
/* Android need it ... */
|
||||
input_report_key(ts->input_dev, BTN_TOUCH, 1);
|
||||
|
||||
input_sync(ts->input_dev);
|
||||
}
|
||||
|
||||
// schedule next acquire
|
||||
ts->acq_timer.expires = jiffies + TS_SCAN_INTERVAL;
|
||||
del_timer(&ts->acq_timer);
|
||||
add_timer(&ts->acq_timer);
|
||||
} else {
|
||||
|
||||
if (!ts->irq_enabled) {
|
||||
ts->irq_enabled = 1;
|
||||
}
|
||||
ts->pen_is_down = 0;
|
||||
if (pen_was_down) {
|
||||
input_report_abs(ts->input_dev, ABS_PRESSURE, 0);
|
||||
/* Android need it ... */
|
||||
input_report_key(ts->input_dev, BTN_TOUCH, 0);
|
||||
|
||||
input_sync(ts->input_dev);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irq(&ts->lock);
|
||||
}
|
||||
|
||||
static struct jz_ts_t *jz_ts;
|
||||
static int __init jz_ts_init(void)
|
||||
{
|
||||
struct input_dev *input_dev;
|
||||
struct jz_ts_t *ts;
|
||||
int error;
|
||||
|
||||
ts = jz_ts = kzalloc(sizeof(struct jz_ts_t), GFP_KERNEL);
|
||||
input_dev = input_allocate_device();
|
||||
if (!ts || !input_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
input_dev->name = "qwerty"; /* Set to 'qwerty' to load /system/usr/keychars/qwerty.kcm.bin by Android */
|
||||
input_dev->phys = ts->phys;
|
||||
|
||||
/*
|
||||
old:
|
||||
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
|
||||
input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
|
||||
*/
|
||||
|
||||
/* For Android */
|
||||
set_bit(EV_ABS, input_dev->evbit);
|
||||
set_bit(ABS_X, input_dev->absbit);
|
||||
set_bit(ABS_Y, input_dev->absbit);
|
||||
set_bit(ABS_PRESSURE, input_dev->absbit);
|
||||
set_bit(EV_KEY, input_dev->evbit);
|
||||
set_bit(BTN_TOUCH, input_dev->keybit);
|
||||
|
||||
#ifdef CONFIG_JZ_ADKEY
|
||||
set_bit(DPAD_CENTER, input_dev->keybit);
|
||||
set_bit(DPAD_DOWN, input_dev->keybit);
|
||||
set_bit(DPAD_UP, input_dev->keybit);
|
||||
set_bit(DPAD_LEFT, input_dev->keybit);
|
||||
set_bit(DPAD_RIGHT, input_dev->keybit);
|
||||
#endif
|
||||
input_set_abs_params(input_dev, ABS_X, 0, SCREEN_MAXX, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_Y, 0, SCREEN_MAXY, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0);
|
||||
input_set_drvdata(input_dev, ts);
|
||||
error = input_register_device(input_dev);
|
||||
|
||||
strcpy(ts->phys, "input/ts0");
|
||||
spin_lock_init(&ts->lock);
|
||||
|
||||
ts->input_dev = input_dev;
|
||||
|
||||
// Init ts acquisition timer function
|
||||
init_timer(&ts->acq_timer);
|
||||
ts->acq_timer.function = jz_acq_timer;
|
||||
ts->acq_timer.data = (unsigned long)ts;
|
||||
ts->irq_enabled = 1;
|
||||
|
||||
if (error) {
|
||||
printk("Input device register failed !\n");
|
||||
goto err_free_dev;
|
||||
}
|
||||
|
||||
sadc_init_clock(6);
|
||||
ts_disable_pendown_irq();
|
||||
ts_disable_penup_irq();
|
||||
|
||||
error = request_irq(IRQ_SADC, pendown_interrupt, IRQF_DISABLED, TS_NAME, ts);
|
||||
if (error) {
|
||||
pr_err("unable to get PenDown IRQ %d", IRQ_SADC);
|
||||
goto err_free_irq;
|
||||
}
|
||||
#ifdef CONFIG_JZ_ADKEY
|
||||
// Init key acquisition timer function
|
||||
init_timer(&ts->key_timer);
|
||||
ts->key_timer.function = key_timer_callback;
|
||||
ts->key_timer.data = (unsigned long)ts;
|
||||
ts->active_low = ACTIVE_LOW_ADKEY;
|
||||
|
||||
error = request_irq(IRQ_GPIO_0 + GPIO_ADKEY_INT, key_interrupt, IRQF_DISABLED, TS_NAME, ts);
|
||||
if (error) {
|
||||
pr_err("unable to get AD KEY IRQ %d", IRQ_GPIO_0 + GPIO_ADKEY_INT);
|
||||
goto err_free_irq;
|
||||
}
|
||||
|
||||
__gpio_disable_pull(GPIO_ADKEY_INT);
|
||||
if(ts->active_low)
|
||||
__gpio_as_irq_fall_edge(GPIO_ADKEY_INT);
|
||||
else
|
||||
__gpio_as_irq_rise_edge(GPIO_ADKEY_INT);
|
||||
|
||||
#endif
|
||||
sadc_start_ts();
|
||||
|
||||
printk("input: JZ Touch Screen registered.\n");
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_irq:
|
||||
free_irq(IRQ_SADC, ts);
|
||||
#ifdef CONFIG_JZ_ADKEY
|
||||
free_irq(IRQ_GPIO_0 + GPIO_ADKEY_INT, ts);
|
||||
#endif
|
||||
err_free_dev:
|
||||
input_free_device(ts->input_dev);
|
||||
kfree(ts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit jz_ts_exit(void)
|
||||
{
|
||||
free_irq(IRQ_SADC, jz_ts);
|
||||
input_unregister_device(jz_ts->input_dev);
|
||||
|
||||
ts_disable_pendown_irq();
|
||||
ts_disable_penup_irq();
|
||||
|
||||
sadc_disable_ts();
|
||||
}
|
||||
|
||||
module_init(jz_ts_init);
|
||||
module_exit(jz_ts_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("JZ TouchScreen Driver");
|
||||
MODULE_AUTHOR("Jason <xwang@ingenic.com>");
|
||||
748
target/linux/xburst/files-2.6.27/drivers/misc/jz_cim.c
Normal file
748
target/linux/xburst/files-2.6.27/drivers/misc/jz_cim.c
Normal file
@@ -0,0 +1,748 @@
|
||||
/*
|
||||
* linux/drivers/misc/tcsm.c
|
||||
*
|
||||
* Virtual device driver with tricky appoach to manage TCSM
|
||||
*
|
||||
* Copyright (C) 2006 Ingenic Semiconductor Inc.
|
||||
*
|
||||
* 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/errno.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/wakelock.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/mipsmtregs.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/jzsoc.h>
|
||||
#include "jz_cim.h"
|
||||
#include "jz_sensor.h"
|
||||
|
||||
|
||||
MODULE_AUTHOR("Lemon Liu<zyliu@ingenic.cn>");
|
||||
MODULE_DESCRIPTION("Ingenic Camera driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
//#define CIM_DEBUG
|
||||
#undef CIM_DEBUG
|
||||
#ifdef CIM_DEBUG
|
||||
#define dprintk(x...) printk(x)
|
||||
#else
|
||||
#define dprintk(x...)
|
||||
#endif
|
||||
|
||||
#define CIM_NAME "cim"
|
||||
|
||||
|
||||
/*
|
||||
* CIM DMA descriptor
|
||||
*/
|
||||
struct cim_desc {
|
||||
u32 nextdesc; /* Physical address of next desc */
|
||||
u32 framebuf; /* Physical address of frame buffer */
|
||||
u32 frameid; /* Frame ID */
|
||||
u32 dmacmd; /* DMA command */
|
||||
};
|
||||
|
||||
/*
|
||||
* CIM device structure
|
||||
*/
|
||||
|
||||
struct cim_device {
|
||||
cim_config_t cim_cfg;
|
||||
preview_param_t view_par;
|
||||
picture_param_t pic_par;
|
||||
unsigned char *mem_base;
|
||||
unsigned char *frm_buf; /*current trans buffer pointer*/
|
||||
unsigned char *jpeg_buf; /* buf for jpeg data */
|
||||
unsigned int mem_size;
|
||||
wait_queue_head_t wait_queue;
|
||||
};
|
||||
|
||||
static struct cim_device jz_cim_info = {
|
||||
#ifdef CONFIG_OV3640
|
||||
.cim_cfg = {
|
||||
.cfg = CIM_CFG_PACK_4 | CIM_CFG_DSM_GCM | CIM_CFG_VSP | CIM_CFG_PCP
|
||||
| CIM_CFG_BYPASS | CIM_CFG_DMA_BURST_INCR8 | CIM_CTRL_FAST_MODE,
|
||||
.ctrl = CIM_CTRL_FRC_1 | CIM_CTRL_RXF_TRIG_4,
|
||||
.mclk = 24000000,
|
||||
},
|
||||
#elif defined(CONFIG_OV2640)
|
||||
.cim_cfg = {
|
||||
.cfg = CIM_CFG_PACK_4 | CIM_CFG_DSM_GCM | CIM_CFG_VSP | CIM_CFG_BYPASS,
|
||||
|
||||
.ctrl = CIM_CTRL_FRC_1 | CIM_CTRL_RXF_TRIG_4,
|
||||
.mclk = 24000000,
|
||||
},
|
||||
#elif defined(CONFIG_OV9650)
|
||||
.cim_cfg = {
|
||||
.cfg = CIM_CFG_PACK_4 | CIM_CFG_DSM_GCM | CIM_CFG_VSP | CIM_CFG_BYPASS,
|
||||
|
||||
.ctrl = CIM_CTRL_FRC_1 | CIM_CTRL_RXF_TRIG_4,
|
||||
.mclk = 24000000,
|
||||
},
|
||||
#else /* CONFIG-SENSOR*/
|
||||
#error "Define Sensor first..."
|
||||
#endif
|
||||
.view_par = {320, 240, 16, "yuv422"},
|
||||
.pic_par = {640, 480, 16, "yuv422",},
|
||||
};
|
||||
|
||||
static int cim_inited = 0;
|
||||
static int jpeg_reading_flag;
|
||||
static int cim_tran_buf_id; /*cim dma current transfer buffer ID*/
|
||||
static int data_ready_buf_id; /*data ready for yuv convert buffer ID*/
|
||||
static struct cim_desc cim_frame_desc[CIM_BUF_NUM] __attribute__ ((aligned (16)));
|
||||
static struct cim_desc cim_jpeg_desc __attribute__ ((aligned (16)));
|
||||
static struct cim_desc cim_test_jpeg_desc __attribute__ ((aligned (16)));
|
||||
|
||||
|
||||
static struct cim_device *jz_cim = &jz_cim_info;
|
||||
|
||||
/*==========================================================================
|
||||
* CIM Module operations
|
||||
*========================================================================*/
|
||||
|
||||
/*
|
||||
* Init CIM module
|
||||
*/
|
||||
static void cim_print_regs(void)
|
||||
{
|
||||
printk("REG_CIM_CFG \t= \t0x%08x\n", REG_CIM_CFG);
|
||||
printk("REG_CIM_CTRL \t= \t0x%08x\n", REG_CIM_CTRL);
|
||||
printk("REG_CIM_STATE \t= \t0x%08x\n", REG_CIM_STATE);
|
||||
printk("REG_CIM_IID \t= \t0x%08x\n", REG_CIM_IID);
|
||||
printk("REG_CIM_DA \t= \t0x%08x\n", REG_CIM_DA);
|
||||
printk("REG_CIM_FA \t= \t0x%08x\n", REG_CIM_FA);
|
||||
printk("REG_CIM_FID \t= \t0x%08x\n", REG_CIM_FID);
|
||||
printk("REG_CIM_CMD \t= \t0x%08x\n", REG_CIM_CMD);
|
||||
printk("REG_CIM_SIZE \t= \t0x%08x\n", REG_CIM_SIZE);
|
||||
printk("REG_CIM_OFFSET \t= \t0x%08x\n", REG_CIM_OFFSET);
|
||||
}
|
||||
|
||||
static void cim_config(cim_config_t *c)
|
||||
{
|
||||
REG_CIM_CFG = c->cfg;
|
||||
REG_CIM_CTRL = c->ctrl;
|
||||
REG_CIM_SIZE = c->size;
|
||||
REG_CIM_OFFSET = c->offs;
|
||||
|
||||
#ifndef CIM_EXTCLK
|
||||
/* Set the master clock output, If use pll clock, enable it */
|
||||
__cim_set_master_clk(__cpm_get_hclk(), c->mclk);
|
||||
#endif
|
||||
|
||||
/* Enable sof, eof and stop interrupts*/
|
||||
__cim_enable_eof_intr();
|
||||
|
||||
// __cim_enable_stop_intr();
|
||||
#if defined(CONFIG_SOC_JZ4750)
|
||||
__cim_enable_rxfifo_overflow_intr();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* CIM start/stop operations
|
||||
*/
|
||||
#if 0
|
||||
static int cim_start_dma(void)
|
||||
{
|
||||
|
||||
if (start_inited == 0) {
|
||||
__cim_disable();
|
||||
__cim_set_da(virt_to_phys(jz_cim->frame_desc));
|
||||
__cim_clear_state(); // clear state register
|
||||
__cim_reset_rxfifo(); // resetting rxfifo
|
||||
__cim_unreset_rxfifo();
|
||||
start_inited = 1;
|
||||
__cim_enable_dma(); // enable dma
|
||||
__cim_enable();
|
||||
}
|
||||
interruptible_sleep_on(&jz_cim->wait_queue);
|
||||
frm_buf = (unsigned char *)cim_frame_desc[data_ready_buf_id].framebuf;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline static int get_ready_buf_id(void)
|
||||
{
|
||||
interruptible_sleep_on(&jz_cim->wait_queue);
|
||||
return data_ready_buf_id;
|
||||
}
|
||||
|
||||
inline void cim_start(void)
|
||||
{
|
||||
dprintk("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__);
|
||||
cim_tran_buf_id = 0;
|
||||
data_ready_buf_id = 0;
|
||||
__cim_disable();
|
||||
__cim_set_da(virt_to_phys(&cim_frame_desc[cim_tran_buf_id]));
|
||||
__cim_clear_state(); // clear state register
|
||||
__cim_reset_rxfifo(); // resetting rxfifo
|
||||
__cim_unreset_rxfifo();
|
||||
__cim_enable_dma(); // enable dma
|
||||
__cim_enable();
|
||||
}
|
||||
inline static void cim_stop(void)
|
||||
{
|
||||
__cim_disable();
|
||||
__cim_disable_dma();
|
||||
__cim_clear_state();
|
||||
}
|
||||
static int cim_device_init(void)
|
||||
{
|
||||
cim_config(&jz_cim->cim_cfg);
|
||||
__sensor_gpio_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cim_snapshot(int mode)
|
||||
{
|
||||
int i;
|
||||
dprintk("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__);
|
||||
jpeg_reading_flag = 1;
|
||||
for(i = 0; i < INVALID_PIC_BUF; i++) {
|
||||
__cim_disable();
|
||||
__cim_set_da(virt_to_phys((&cim_test_jpeg_desc)));
|
||||
__cim_clear_state(); // clear state register
|
||||
__cim_reset_rxfifo(); // resetting rxfifo
|
||||
__cim_unreset_rxfifo();
|
||||
__cim_enable_dma(); // enable dma
|
||||
__cim_enable();
|
||||
interruptible_sleep_on(&jz_cim->wait_queue);
|
||||
}
|
||||
__cim_disable();
|
||||
__cim_set_da(virt_to_phys(&cim_jpeg_desc));
|
||||
__cim_clear_state(); // clear state register
|
||||
__cim_reset_rxfifo(); // resetting rxfifo
|
||||
__cim_unreset_rxfifo();
|
||||
__cim_enable_dma(); // enable dma
|
||||
__cim_enable();
|
||||
interruptible_sleep_on(&jz_cim->wait_queue);
|
||||
jpeg_reading_flag = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*==========================================================================
|
||||
* Framebuffer allocation and destroy
|
||||
*========================================================================*/
|
||||
static struct cim_desc *init_cim_desc_list(void * base)
|
||||
{
|
||||
int i;
|
||||
unsigned char *p_buf;
|
||||
struct cim_desc *p_desc;
|
||||
struct cim_desc *desc_list_head __attribute__ ((aligned (16)));
|
||||
struct cim_desc *desc_list_tail __attribute__ ((aligned (16)));
|
||||
|
||||
|
||||
int frmsize = (((jz_cim->view_par.width * jz_cim->view_par.height
|
||||
* jz_cim->view_par.bpp + 7) >> 3) + 3) >> 2; /* word aligned */
|
||||
|
||||
desc_list_head = desc_list_tail = NULL;
|
||||
|
||||
for (i = 0; i < CIM_BUF_NUM; i++) {
|
||||
p_desc = &cim_frame_desc[i];
|
||||
p_buf = (void*)((((unsigned int)base + (MAX_PRE_SIZE * i)) >> 3) << 3);
|
||||
|
||||
if (desc_list_head == NULL) {
|
||||
dprintk("Page_list_head\n");
|
||||
desc_list_head = p_desc;
|
||||
} else
|
||||
desc_list_tail->nextdesc = virt_to_phys(p_desc);
|
||||
|
||||
jz_cim->view_par.framebuf[i] = virt_to_phys(p_buf);
|
||||
desc_list_tail = p_desc;
|
||||
desc_list_tail->framebuf = virt_to_phys(p_buf);
|
||||
dprintk("framebuf addr is 0x%08x\n", (u32)desc_list_tail->framebuf);
|
||||
dprintk("frame_desc addr is 0x%08x\n",(u32)virt_to_phys(desc_list_tail));
|
||||
desc_list_tail->frameid = i;
|
||||
desc_list_tail->dmacmd = frmsize;
|
||||
#if defined(CONFIG_SOC_JZ4750)
|
||||
desc_list_tail->dmacmd |= CIM_CMD_EOFINT;
|
||||
#else
|
||||
desc_list_tail->dmacmd |= (CIM_CMD_EOFINT | CIM_CMD_OFRCV);
|
||||
#endif
|
||||
dprintk("framedesc\t= 0x%08x\n",(unsigned int)virt_to_phys(desc_list_tail));
|
||||
dprintk("framebuf \t= 0x%08x\n", (unsigned int)desc_list_tail->framebuf);
|
||||
dprintk("frameid \t= 0x%08x\n", (unsigned int)desc_list_tail->frameid);
|
||||
dprintk("dmacmd \t= 0x%08x\n", (unsigned int)desc_list_tail->dmacmd);
|
||||
dprintk("the desc_list_tail->dmacmd is 0x%08x\n", desc_list_tail->dmacmd);
|
||||
}
|
||||
desc_list_tail->nextdesc = virt_to_phys(desc_list_head);
|
||||
|
||||
for (i = 0; i < CIM_BUF_NUM; i++)
|
||||
dma_cache_wback((unsigned long)(&cim_frame_desc[i]), sizeof(struct cim_desc));
|
||||
|
||||
/* prepare the jpeg descriptor */
|
||||
|
||||
p_buf = (void*)((((unsigned int)base + (MAX_PRE_SIZE * CIM_BUF_NUM)) >> 3) << 3);
|
||||
|
||||
cim_test_jpeg_desc.framebuf = (unsigned int)virt_to_phys(p_buf);
|
||||
cim_test_jpeg_desc.nextdesc = (unsigned int)virt_to_phys(NULL);
|
||||
cim_test_jpeg_desc.frameid = 0xf0;
|
||||
cim_test_jpeg_desc.dmacmd = (4 >> 2) | CIM_CMD_EOFINT | CIM_CMD_STOP;
|
||||
dma_cache_wback_inv((unsigned long)&cim_test_jpeg_desc, sizeof(struct cim_desc));
|
||||
|
||||
jz_cim->pic_par.framebuf[0] = virt_to_phys(p_buf);
|
||||
cim_jpeg_desc.framebuf = (unsigned int)virt_to_phys(p_buf);
|
||||
cim_jpeg_desc.nextdesc = (unsigned int)virt_to_phys(NULL);
|
||||
cim_jpeg_desc.frameid = 0xff;
|
||||
|
||||
frmsize = (((jz_cim->pic_par.width * jz_cim->pic_par.height
|
||||
* 16) >> 3) + 3) >> 2; /* word aligned */
|
||||
if (strcmp(jz_cim->pic_par.format, "jpeg") == 0) {
|
||||
if (frmsize > (MAX_PICTURE_SIZE >> 2))
|
||||
cim_jpeg_desc.dmacmd = (MAX_PICTURE_SIZE >> 2);
|
||||
else
|
||||
cim_jpeg_desc.dmacmd = frmsize;
|
||||
}
|
||||
else/* if ((strcmp(jz_cim->pic_par.format, "yuv422") == 0) ||
|
||||
(strcmp(jz_cim->pic_par.format, "rgb565") == 0)) */
|
||||
cim_jpeg_desc.dmacmd = frmsize;
|
||||
cim_jpeg_desc.frameid = 0xff;
|
||||
|
||||
cim_jpeg_desc.dmacmd |= (CIM_CMD_EOFINT | CIM_CMD_STOP);
|
||||
dma_cache_wback_inv((unsigned long)&cim_jpeg_desc, sizeof(struct cim_desc));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cim_fb_alloc(void)
|
||||
{
|
||||
#ifndef USE_DEFAULT_MEM
|
||||
int page_order;
|
||||
#endif
|
||||
/* Alloc max preview frame for chang preview size */
|
||||
/* Total memsize = preview size + picture size */
|
||||
jz_cim->mem_size = MAX_PRE_SIZE * CIM_BUF_NUM + MAX_PICTURE_SIZE;
|
||||
|
||||
#ifndef USE_DEFAULT_MEM
|
||||
|
||||
/* If no default memory, Alloc memory here */
|
||||
page_order = get_order(jz_cim->mem_size);
|
||||
jz_cim->mem_base = (unsigned char *)__get_free_pages(GFP_KERNEL, page_order);
|
||||
if (jz_cim->mem_base == NULL)
|
||||
return -ENOMEM;
|
||||
#endif
|
||||
|
||||
/* Descriptor list for cim DMA */
|
||||
init_cim_desc_list(jz_cim->mem_base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cim_fb_destroy(void)
|
||||
{
|
||||
#if 0
|
||||
int pages;
|
||||
struct cim_desc *jz_frame_desc, *p_desc;
|
||||
__cim_disable_dma();
|
||||
__cim_disable();
|
||||
|
||||
dprintk("jz_cim->frame_desc = %x\n", (u32)jz_cim->frame_desc);
|
||||
if (jz_cim->frame_desc == NULL) {
|
||||
printk("Original memory is NULL\n");
|
||||
return;
|
||||
}
|
||||
jz_frame_desc = jz_cim->frame_desc;
|
||||
// dprintk("framebuf = %x,thisdesc = %x,frame_size= %d\n", (u32) jz_frame_desc->framebuf, (unsigned int)jz_frame_desc, (jz_frame_desc->dmacmd & 0xffffff) * 4);
|
||||
p_desc = (struct cim_desc *)phys_to_virt(jz_frame_desc->nextdesc);
|
||||
pages = jz_frame_desc->pagenum;
|
||||
dprintk("page_order = %d\n", pages);
|
||||
free_pages((unsigned long)phys_to_virt(jz_frame_desc->framebuf), pages);
|
||||
kfree(jz_frame_desc);
|
||||
jz_frame_desc = p_desc;
|
||||
jz_cim->frame_desc = NULL;
|
||||
start_init = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*==========================================================================
|
||||
* Interrupt handler
|
||||
*========================================================================*/
|
||||
|
||||
static irqreturn_t cim_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
u32 state = REG_CIM_STATE;
|
||||
/* dprintk("REG_CIM_STATE = %x\n", REG_CIM_STATE);
|
||||
dprintk("IRQ:REG_CIM_CTRL = %x\n", REG_CIM_CTRL);
|
||||
dprintk("REG_CIM_IID \t= \t0x%08x\n", REG_CIM_IID);
|
||||
dprintk("REG_CIM_FID \t= \t0x%08x\n", REG_CIM_FID);
|
||||
*/
|
||||
|
||||
if (state & CIM_STATE_DMA_EOF) {
|
||||
if (jpeg_reading_flag != 1) {
|
||||
data_ready_buf_id = REG_CIM_IID;
|
||||
cim_tran_buf_id = REG_CIM_FID;
|
||||
wake_up_interruptible(&jz_cim->wait_queue);
|
||||
// printk("preview sleep \n");
|
||||
REG_CIM_STATE &= ~CIM_STATE_DMA_EOF;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
else {
|
||||
cim_stop();
|
||||
printk("wake_up_interruptible\n");
|
||||
wake_up_interruptible(&jz_cim->wait_queue);
|
||||
REG_CIM_STATE = 0;
|
||||
}
|
||||
}
|
||||
#if defined(CONFIG_SOC_JZ4750)
|
||||
if (state & CIM_STATE_RXF_OF) {
|
||||
printk("OverFlow interrupt!\n");
|
||||
__cim_disable();
|
||||
REG_CIM_STATE = 0;
|
||||
__cim_reset_rxfifo(); // resetting rxfifo
|
||||
__cim_unreset_rxfifo();
|
||||
__cim_enable_dma(); // enable dma
|
||||
__cim_enable();
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
#endif
|
||||
/* clear status flags*/
|
||||
REG_CIM_STATE = 0;
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*==========================================================================
|
||||
* File operations
|
||||
*========================================================================*/
|
||||
|
||||
static int cim_open(struct inode *inode, struct file *filp);
|
||||
static int cim_release(struct inode *inode, struct file *filp);
|
||||
static ssize_t cim_read(struct file *filp, char *buf, size_t size, loff_t *l);
|
||||
static ssize_t cim_write(struct file *filp, const char *buf, size_t size, loff_t *l);
|
||||
static int cim_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
|
||||
static int cim_mmap(struct file *file, struct vm_area_struct *vma);
|
||||
|
||||
static struct file_operations cim_fops =
|
||||
{
|
||||
open: cim_open,
|
||||
release: cim_release,
|
||||
read: cim_read,
|
||||
write: cim_write,
|
||||
ioctl: cim_ioctl,
|
||||
mmap: cim_mmap,
|
||||
|
||||
};
|
||||
|
||||
static int cim_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
if (cim_inited == 0) {
|
||||
cim_device_init();
|
||||
}
|
||||
/* allocate frame buffers */
|
||||
cim_inited = 1;
|
||||
dprintk("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__);
|
||||
try_module_get(THIS_MODULE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cim_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
dprintk("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__);
|
||||
cim_fb_destroy();
|
||||
cim_stop();
|
||||
|
||||
module_put(THIS_MODULE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t cim_read(struct file *filp, char *buf, size_t size, loff_t *l)
|
||||
{
|
||||
unsigned long off = *l;
|
||||
if ((size + off) > jz_cim->mem_size)
|
||||
size = jz_cim->mem_size;
|
||||
memcpy(buf, jz_cim->mem_base + off, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t cim_write(struct file *filp, const char *buf, size_t size, loff_t *l)
|
||||
{
|
||||
printk("cim error: write is not implemented\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**************************
|
||||
* IOCTL Handlers *
|
||||
**************************/
|
||||
|
||||
/*
|
||||
* If use default mem, app need trans a mem_base to cim though "IOCTL_SET_MEM".(only once)
|
||||
* Else driver will alloc memory by itself. See cim_fb_alloc() for detail.
|
||||
*
|
||||
* Then "IOCTL_SET_CIM_CONFIG" and "IOCTL_SET_PREVIEW_PARAM" will be call to set preview parametes.
|
||||
* Now, call IOCTL_START_CIM to start data tranfer.
|
||||
* When Take a picture,
|
||||
*
|
||||
*/
|
||||
static int cim_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
void __user *argp = (void __user *)arg;
|
||||
switch (cmd) {
|
||||
case IOCTL_SET_I2C_ADDR:
|
||||
if (copy_from_user(&i2c_addr, (void *)arg, 4))
|
||||
return -EFAULT;
|
||||
break;
|
||||
case IOCTL_SET_I2C_CLK:
|
||||
if (copy_from_user(&i2c_clk, (void *)arg, 4))
|
||||
return -EFAULT;
|
||||
break;
|
||||
case IOCTL_WRITE_I2C_REG:
|
||||
{
|
||||
unsigned char regval[2];
|
||||
|
||||
if (copy_from_user(regval, (void *)arg, 2))
|
||||
return -EFAULT;
|
||||
|
||||
sensor_write_reg(regval[0], regval[1]);
|
||||
break;
|
||||
}
|
||||
case IOCTL_READ_I2C_REG:
|
||||
{
|
||||
unsigned char reg, val;
|
||||
|
||||
if (copy_from_user(®, (void *)arg, 1))
|
||||
return -EFAULT;
|
||||
|
||||
val = sensor_read_reg(reg);
|
||||
|
||||
if (copy_to_user((void *)(arg + 1), &val, 1))
|
||||
return -EFAULT;
|
||||
break;
|
||||
}
|
||||
case IOCTL_WRITE_I2C_REG16:
|
||||
{
|
||||
unsigned short regval[2];
|
||||
|
||||
if (copy_from_user(regval, (void *)arg, 4))
|
||||
return -EFAULT;
|
||||
|
||||
sensor_write_reg16(regval[0], (unsigned char)regval[1]);
|
||||
break;
|
||||
}
|
||||
case IOCTL_READ_I2C_REG16:
|
||||
{
|
||||
unsigned short reg, val;
|
||||
|
||||
if (copy_from_user(®, (void *)arg, 2))
|
||||
return -EFAULT;
|
||||
|
||||
val = sensor_read_reg16(reg);
|
||||
|
||||
if (copy_to_user((void *)(arg + 1), &val, 2))
|
||||
return -EFAULT;
|
||||
break;
|
||||
}
|
||||
#ifdef USE_DEFAULT_MEM
|
||||
case IOCTL_SET_MEM:
|
||||
jz_cim->mem_base = (unsigned char *)arg;
|
||||
cim_fb_alloc();
|
||||
break;
|
||||
#endif
|
||||
case IOCTL_START_CIM:
|
||||
cim_start();
|
||||
break;
|
||||
case IOCTL_STOP_CIM:
|
||||
cim_stop();
|
||||
return 0;
|
||||
case IOCTL_GET_CIM_CONFIG:
|
||||
dprintk("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__);
|
||||
return copy_to_user((void *)argp, (void *)&jz_cim->cim_cfg,
|
||||
sizeof(cim_config_t)) ? -EFAULT : 0;
|
||||
break;
|
||||
|
||||
case IOCTL_SET_CIM_CONFIG:
|
||||
if (copy_from_user((void *)&jz_cim->cim_cfg, (void *)arg,
|
||||
sizeof(cim_config_t)))
|
||||
return -EFAULT;
|
||||
cim_config(&jz_cim->cim_cfg);
|
||||
break;
|
||||
case IOCTL_GET_PREVIEW_PARAM:
|
||||
dprintk("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__);
|
||||
return copy_to_user(argp, &jz_cim->view_par, sizeof(preview_param_t)) ? -EFAULT : 0;
|
||||
break;
|
||||
case IOCTL_SET_PREVIEW_PARAM:
|
||||
{
|
||||
int i, framesize, wpf; /* words per frame */
|
||||
preview_param_t p;
|
||||
|
||||
|
||||
if (copy_from_user((void *)&p, (void *)arg, sizeof(preview_param_t)))
|
||||
return -EFAULT;
|
||||
|
||||
framesize = (p.width * p.height * p.bpp + 7) >> 3;
|
||||
if (framesize > MAX_PRE_SIZE){
|
||||
printk("ERROR! Preview size is too large!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
jz_cim->view_par.width = p.width;
|
||||
jz_cim->view_par.height = p.height;
|
||||
jz_cim->view_par.bpp = p.bpp;
|
||||
wpf = (framesize +3) >> 2 ;
|
||||
for (i = 0; i < CIM_BUF_NUM; i++) {
|
||||
cim_frame_desc[i].dmacmd &= ~CIM_CMD_LEN_MASK;
|
||||
cim_frame_desc[i].dmacmd |= wpf;
|
||||
dma_cache_wback((unsigned long)(&cim_frame_desc[i]), sizeof(struct cim_desc));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IOCTL_GET_PICTURE_PARAM:
|
||||
return copy_to_user(argp, &jz_cim->pic_par, sizeof(picture_param_t)) ? -EFAULT : 0;
|
||||
break;
|
||||
case IOCTL_SET_PICTURE_PARAM:
|
||||
{
|
||||
int framesize, wpf; /* words per frame */
|
||||
picture_param_t p;
|
||||
|
||||
if (copy_from_user((void *)&p, (void *)arg, sizeof(picture_param_t)))
|
||||
return -EFAULT;
|
||||
framesize = (p.width * p.height * 16 + 7) >> 3;
|
||||
jz_cim->pic_par.width = p.width;
|
||||
jz_cim->pic_par.height = p.height;
|
||||
wpf = (framesize + 3) >> 2 ;
|
||||
cim_jpeg_desc.dmacmd &= ~CIM_CMD_LEN_MASK;
|
||||
cim_jpeg_desc.dmacmd |= wpf;
|
||||
dma_cache_wback((unsigned long)(&cim_jpeg_desc), sizeof(struct cim_desc));
|
||||
break;
|
||||
}
|
||||
case IOCTL_PRINT_REGS:
|
||||
cim_print_regs();
|
||||
break;
|
||||
|
||||
case IOCTL_TAKE_PICTURE:
|
||||
cim_snapshot(0);
|
||||
break;
|
||||
case IOCTL_GET_CURRENT_BUF_ID:
|
||||
{
|
||||
int id;
|
||||
id = get_ready_buf_id();
|
||||
return copy_to_user(argp, &id, 4) ? -EFAULT : 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printk("Not supported command: 0x%x\n", cmd);
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use mmap /dev/fb can only get a non-cacheable Virtual Address. */
|
||||
static int cim_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
{
|
||||
unsigned long start;
|
||||
unsigned long off;
|
||||
u32 len;
|
||||
|
||||
dprintk("%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__);
|
||||
off = vma->vm_pgoff << PAGE_SHIFT;
|
||||
|
||||
/* frame buffer memory */
|
||||
start = virt_to_phys(jz_cim->mem_base);
|
||||
len = PAGE_ALIGN((start & ~PAGE_MASK) + ((unsigned long)jz_cim->mem_size));
|
||||
start &= PAGE_MASK;
|
||||
|
||||
if ((vma->vm_end - vma->vm_start + off) > len) {
|
||||
printk("Error: vma is larger than memory length\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
off += start;
|
||||
|
||||
vma->vm_pgoff = off >> PAGE_SHIFT;
|
||||
vma->vm_flags |= VM_IO;
|
||||
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); /* Uncacheable */
|
||||
|
||||
#if defined(CONFIG_MIPS32)
|
||||
pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK;
|
||||
pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED; /* Uncacheable */
|
||||
#endif
|
||||
|
||||
if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
|
||||
vma->vm_end - vma->vm_start,
|
||||
vma->vm_page_prot)) {
|
||||
return -EAGAIN;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static struct miscdevice cim_dev = {
|
||||
CIM_MINOR,
|
||||
"cim",
|
||||
&cim_fops
|
||||
};
|
||||
|
||||
/*
|
||||
* Module init and exit
|
||||
*/
|
||||
|
||||
static int __init cim_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* GPIO init for cim pins and i2c SDA & SCL */
|
||||
__gpio_as_cim();
|
||||
__gpio_as_i2c();
|
||||
|
||||
/* waitqueue */
|
||||
init_waitqueue_head(&jz_cim->wait_queue);
|
||||
|
||||
#ifndef USE_DEFAULT_MEM
|
||||
/* Alloc memory for cim DMA*/
|
||||
|
||||
printk("Alloc memory for cim DMA\n");
|
||||
ret = cim_fb_alloc();
|
||||
if (ret) {
|
||||
printk("No mem: Alloc memory for cim DMA\n");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
/* request interrupt for cim */
|
||||
if ((ret = request_irq(IRQ_CIM, cim_irq_handler, IRQF_DISABLED, CIM_NAME, jz_cim))) {
|
||||
printk(KERN_ERR "request_irq return error, ret=%d\n", ret);
|
||||
cim_fb_destroy();
|
||||
printk(KERN_ERR "CIM could not get IRQ\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Register as a misc device */
|
||||
ret = misc_register(&cim_dev);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
printk("Virtual Driver of JZ CIM registered\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit cim_exit(void)
|
||||
{
|
||||
misc_deregister(&cim_dev);
|
||||
}
|
||||
|
||||
module_init(cim_init);
|
||||
module_exit(cim_exit);
|
||||
104
target/linux/xburst/files-2.6.27/drivers/misc/jz_cim.h
Normal file
104
target/linux/xburst/files-2.6.27/drivers/misc/jz_cim.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* linux/drivers/misc/jz_cim.h -- Ingenic Jz4750 On-Chip CIM driver
|
||||
*
|
||||
* Copyright (C) 2005-2008, Ingenic Semiconductor Inc.
|
||||
*
|
||||
* 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 __JZ_CIM_H__
|
||||
#define __JZ_CIM_H__
|
||||
|
||||
/* use ext clock as mclk */
|
||||
#define CIM_EXTCLK 24000000
|
||||
|
||||
|
||||
/* If use default 16M mem, enable it*/
|
||||
//#define USE_DEFAULT_MEM
|
||||
|
||||
/* Camera Preview buffer number */
|
||||
#define CIM_BUF_NUM 3
|
||||
#define INVALID_PIC_BUF 0
|
||||
|
||||
//#define IMEM_MAX_ORDER 12 /* max 2^12 * 4096 = 16MB */
|
||||
|
||||
/*
|
||||
* Define the Max Image Size CIM Support
|
||||
*/
|
||||
#define MAX_IMAGE_WIDTH 4096
|
||||
#define MAX_IMAGE_HEIGHT 4096
|
||||
#define MAX_PRE_WIDTH 640
|
||||
#define MAX_PRE_HEIGHT 480
|
||||
#define MAX_IMAGE_BPP 16
|
||||
#define MAX_PRE_SIZE (MAX_PRE_WIDTH * MAX_PRE_HEIGHT * MAX_IMAGE_BPP >> 3)
|
||||
#define MAX_FRAME_SIZE (MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT * MAX_IMAGE_BPP >> 3)
|
||||
|
||||
/*
|
||||
* IOCTL_XXX commands
|
||||
*/
|
||||
#define IOCTL_SET_I2C_ADDR 0x0
|
||||
#define IOCTL_SET_I2C_CLK 0x1
|
||||
#define IOCTL_WRITE_I2C_REG 0x2
|
||||
#define IOCTL_READ_I2C_REG 0x3
|
||||
#define IOCTL_WRITE_I2C_REG16 0x4
|
||||
#define IOCTL_READ_I2C_REG16 0x5
|
||||
#define IOCTL_SET_MEM 0x6
|
||||
#define IOCTL_START_CIM 0x7 // arg type: void
|
||||
#define IOCTL_STOP_CIM 0x8 // arg type: void
|
||||
#define IOCTL_GET_PREVIEW_PARAM 0x9 // arg type: preview param *
|
||||
#define IOCTL_SET_PREVIEW_PARAM 0xA // arg type: preview param *
|
||||
#define IOCTL_GET_PICTURE_PARAM 0xB // arg type: img_param_t *
|
||||
#define IOCTL_SET_PICTURE_PARAM 0xC // arg type: img_param_t *
|
||||
#define IOCTL_GET_CIM_CONFIG 0xD // arg type: cim_config_t *
|
||||
#define IOCTL_SET_CIM_CONFIG 0xE // arg type: cim_config_t *
|
||||
#define IOCTL_PRINT_REGS 0xF // NULL
|
||||
#define IOCTL_TAKE_PICTURE 0x10
|
||||
#define IOCTL_GET_CURRENT_BUF_ID 0x11
|
||||
|
||||
/* gpio init */
|
||||
#if defined(CONFIG_JZ4750_APUS) || defined(CONFIG_JZ4750D_FUWA1) /* board pavo */
|
||||
#define GPIO_CAMERA_RST (32*4+8) /* CIM_MCLK as reset */
|
||||
#else
|
||||
#error "driver/misc/jz_cim.h, please define camera for your board."
|
||||
#endif
|
||||
|
||||
|
||||
/* preview-format=rgb565|yuv422 */
|
||||
typedef struct{
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int bpp;
|
||||
char format[20];
|
||||
unsigned int framebuf[CIM_BUF_NUM];
|
||||
} preview_param_t;
|
||||
|
||||
/* picture-format=yuv422|jpeg */
|
||||
typedef struct{
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int bpp;
|
||||
// const char *format;
|
||||
char format[20];
|
||||
unsigned int framebuf[CIM_BUF_NUM];
|
||||
} picture_param_t;
|
||||
|
||||
typedef struct{
|
||||
unsigned int cfg;
|
||||
unsigned int ctrl;
|
||||
unsigned int mclk;
|
||||
unsigned int size;
|
||||
unsigned int offs;
|
||||
} cim_config_t;
|
||||
|
||||
|
||||
struct jz_camera_device_platform_data {
|
||||
int gpio_reset;
|
||||
void (*config_gpio_on) (void);
|
||||
void (*config_gpio_off)(void);
|
||||
};
|
||||
|
||||
|
||||
#endif /*__JZ_CIM_H__*/
|
||||
92
target/linux/xburst/files-2.6.27/drivers/misc/jz_sensor.c
Normal file
92
target/linux/xburst/files-2.6.27/drivers/misc/jz_sensor.c
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* linux/drivers/misc/jz_sensor.c
|
||||
*
|
||||
* Virtual device driver with tricky appoach to manage TCSM
|
||||
*
|
||||
* Copyright (C) 2006 Ingenic Semiconductor Inc.
|
||||
*
|
||||
* 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/errno.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/wakelock.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/mipsmtregs.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/jzsoc.h>
|
||||
#include "jz_cim.h"
|
||||
#include "jz_sensor.h"
|
||||
|
||||
unsigned int i2c_addr = 0x60;
|
||||
unsigned int i2c_clk = 100000;
|
||||
|
||||
/* I2C ops to init senser */
|
||||
void sensor_write_reg(unsigned char reg, unsigned char val)
|
||||
{
|
||||
i2c_open();
|
||||
i2c_setclk(i2c_clk);
|
||||
i2c_write((i2c_addr >> 1), &val, reg, 1);
|
||||
i2c_close();
|
||||
}
|
||||
|
||||
int sensor_write_reg16(unsigned short reg, unsigned char val)
|
||||
{
|
||||
int ret;
|
||||
i2c_open();
|
||||
i2c_setclk(i2c_clk);
|
||||
ret = i2c_write_16(i2c_addr >> 1, &val, reg, 1);
|
||||
i2c_close();
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned char sensor_read_reg(unsigned char reg)
|
||||
{
|
||||
unsigned char val;
|
||||
|
||||
i2c_open();
|
||||
i2c_setclk(i2c_clk);
|
||||
i2c_read((i2c_addr >> 1), &val, reg, 1);
|
||||
i2c_close();
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get sensor register through i2c bus
|
||||
*/
|
||||
|
||||
unsigned char sensor_read_reg16(unsigned short reg)
|
||||
{
|
||||
unsigned char val;
|
||||
i2c_open();
|
||||
i2c_setclk(i2c_clk);
|
||||
i2c_read_16(i2c_addr >> 1, &val, reg, 1);
|
||||
i2c_close();
|
||||
return val;
|
||||
}
|
||||
|
||||
94
target/linux/xburst/files-2.6.27/drivers/misc/jz_sensor.h
Normal file
94
target/linux/xburst/files-2.6.27/drivers/misc/jz_sensor.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* linux/drivers/misc/jz_cim.h -- Ingenic Jz4750 On-Chip CIM driver
|
||||
*
|
||||
* Copyright (C) 2005-2008, Ingenic Semiconductor Inc.
|
||||
*
|
||||
* 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 __JZ_SENSOR_H__
|
||||
#define __JZ_SENSOR_H__
|
||||
|
||||
#include "jz_cim.h"
|
||||
|
||||
|
||||
#define IN_YUV422 1 /*Sensor output YUV422*/
|
||||
|
||||
/*
|
||||
* Define the Max Image Size Sensor Support, Should less than CIM MAX
|
||||
*/
|
||||
#if defined(CONFIG_OV3640)
|
||||
#define MAX_SENSOR_WIDTH 2048
|
||||
#define MAX_SENSOR_HEIGHT 1536
|
||||
#define MAX_SENSOR_BPP 16
|
||||
#define SENSOR_PRE_WIDTH 320
|
||||
#define SENSOR_PRE_HEIGHT 240
|
||||
#elif defined(CONFIG_OV2640)
|
||||
#define MAX_SENSOR_WIDTH 1600
|
||||
#define MAX_SENSOR_HEIGHT 1200
|
||||
#define MAX_SENSOR_BPP 16
|
||||
#define SENSOR_PRE_WIDTH 320
|
||||
#define SENSOR_PRE_HEIGHT 240
|
||||
#elif defined(CONFIG_OV9650)
|
||||
#define MAX_SENSOR_WIDTH 1280
|
||||
#define MAX_SENSOR_HEIGHT 1024
|
||||
#define MAX_SENSOR_BPP 16
|
||||
#define SENSOR_PRE_WIDTH 320
|
||||
#define SENSOR_PRE_HEIGHT 240
|
||||
#else
|
||||
#define MAX_SENSOR_WIDTH 1280
|
||||
#define MAX_SENSOR_HEIGHT 1024
|
||||
#define MAX_SENSOR_BPP 16
|
||||
#define SENSOR_PRE_WIDTH 320
|
||||
#define SENSOR_PRE_HEIGHT 240
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_OV3640) || defined(CONFIG_OV2640)
|
||||
//#define JPEG_OUTPUT_SUPPORT
|
||||
#endif
|
||||
|
||||
#if defined(JPEG_OUTPUT_SUPPORT)
|
||||
#define MAX_PICTURE_SIZE (6*1024*1024) /* for 2048*1536*2 */
|
||||
#else
|
||||
#define MAX_PICTURE_SIZE (MAX_SENSOR_WIDTH * MAX_SENSOR_HEIGHT * MAX_IMAGE_BPP >> 3)
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(CONFIG_OV9650) || defined(CONFIG_OV2640)
|
||||
#define __sensor_gpio_init() \
|
||||
do {\
|
||||
__gpio_as_output(GPIO_CAMERA_RST); \
|
||||
__gpio_set_pin(GPIO_CAMERA_RST); \
|
||||
mdelay(50); \
|
||||
__gpio_clear_pin(GPIO_CAMERA_RST);\
|
||||
} while(0)
|
||||
#elif defined(CONFIG_OV3640)
|
||||
#define __sensor_gpio_init() \
|
||||
do {\
|
||||
__gpio_as_output(GPIO_CAMERA_RST); \
|
||||
__gpio_clear_pin(GPIO_CAMERA_RST);\
|
||||
mdelay(50); \
|
||||
__gpio_set_pin(GPIO_CAMERA_RST); \
|
||||
} while(0)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
extern unsigned int i2c_addr;
|
||||
extern unsigned int i2c_clk;
|
||||
|
||||
/* I2C APP */
|
||||
|
||||
extern int i2c_write_16(unsigned char device, unsigned char *buf, unsigned short address, int count);
|
||||
extern int i2c_read_16(unsigned char device, unsigned char *buf, unsigned short address, int count);
|
||||
|
||||
|
||||
extern void sensor_write_reg(unsigned char reg, unsigned char val);
|
||||
extern int sensor_write_reg16(unsigned short reg, unsigned char val);
|
||||
extern unsigned char sensor_read_reg(unsigned char reg);
|
||||
extern unsigned char sensor_read_reg16(unsigned short reg);
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user