* [loongson-PATCH-v1 12/27] add basic loongson-2f support
[not found] <cover.1242855716.git.wuzhangjin@gmail.com>
@ 2009-05-20 22:05 ` wuzhangjin
2009-05-20 22:06 ` [loongson-PATCH-v1 13/27] add basic fuloong(2f) support wuzhangjin
` (3 subsequent siblings)
4 siblings, 0 replies; 20+ messages in thread
From: wuzhangjin @ 2009-05-20 22:05 UTC (permalink / raw)
To: linux-mips, Ralf Baechle, Andrew Morton
Cc: linux-kernel, Wu Zhangjin, Yan hua, Philippe Vachon, Zhang Le,
Zhang Fuxin, Arnaud Patard, loongson-dev, gnewsense-dev,
Nicholas Mc Guire, Liu Junliang, Erwan Lerale
From: Wu Zhangjin <wuzhangjin@gmail.com>
Loongson2F has built-in DDR2 and PCIX controller. The PCIX controller
have a similar programming interface with FPGA northbridge used in
Loongson2E.
so, the main difference between loongson-2e and loongson-2f is:
loongson-2f has an extra address windows configuration module, which can
be used to map CPU address space to DDR or PCI address space, or map the
PCI-DMA address space to DDR or LIO address space.
herein, the module and the operations are abstracted to loongson.h.
NOTE: this module is only available in 64bit kernel.
Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
arch/mips/Kconfig | 18 +++++
.../mips/include/asm/mach-loongson/dma-coherence.h | 4 +
arch/mips/include/asm/mach-loongson/loongson.h | 79 +++++++++++++++++++-
arch/mips/include/asm/mach-loongson/mem.h | 23 ++++++
arch/mips/include/asm/mach-loongson/pci.h | 30 +++++++-
arch/mips/loongson/common/init.c | 17 ++++
arch/mips/loongson/common/mem.c | 21 ++++-
arch/mips/loongson/common/pci.c | 14 +++-
8 files changed, 197 insertions(+), 9 deletions(-)
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index b5581d6..2aaa4d0 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1008,6 +1008,21 @@ config CPU_LOONGSON2E
The Loongson 2E processor implements the MIPS III instruction set
with many extensions.
+ It has an internal FPGA northbridge, which is compatiable to
+ bonito64.
+
+config CPU_LOONGSON2F
+ bool "Loongson 2F"
+ depends on SYS_HAS_CPU_LOONGSON2F
+ select CPU_LOONGSON2
+ help
+ The Loongson 2F processor implements the MIPS III instruction set
+ with many extensions.
+
+ Loongson2F have built-in DDR2 and PCIX controller. The PCIX controller
+ have a similar programming interface with FPGA northbridge used in
+ Loongson2E.
+
config CPU_MIPS32_R1
bool "MIPS32 Release 1"
depends on SYS_HAS_CPU_MIPS32_R1
@@ -1255,6 +1270,9 @@ config CPU_LOONGSON2
config SYS_HAS_CPU_LOONGSON2E
bool
+config SYS_HAS_CPU_LOONGSON2F
+ bool
+
config SYS_HAS_CPU_MIPS32_R1
bool
diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h b/arch/mips/include/asm/mach-loongson/dma-coherence.h
index f27d0f8..6ba8279 100644
--- a/arch/mips/include/asm/mach-loongson/dma-coherence.h
+++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h
@@ -27,7 +27,11 @@ static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
static inline unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
{
+#if defined(CONFIG_CPU_LOONGSON2F) & defined(CONFIG_64BIT)
+ return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr & 0x0fffffff);
+#else
return dma_addr & 0x7fffffff;
+#endif
}
static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
index 29c9730..8ddfbd3 100644
--- a/arch/mips/include/asm/mach-loongson/loongson.h
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
@@ -221,5 +221,82 @@ extern void mach_prepare_shutdown(void);
#define LOONGSON_PCIMAP_WIN(WIN, ADDR) \
((((ADDR)>>26) & LOONGSON_PCIMAP_PCIMAP_LO0) << ((WIN)*6))
-#endif /* __LOONGSON_H */
+/*
+ * address windows configuration module
+ *
+ * loongson2e do not have this module
+ */
+#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
+
+/* address window config module base address */
+#define LOONGSON_ADDRWINCFG_BASE 0x3ff00000ul
+#define LOONGSON_ADDRWINCFG_SIZE 0x180
+
+extern unsigned long _loongson_addrwincfg_base;
+#define LOONGSON_ADDRWINCFG(offset) \
+ (*(u64 *)(_loongson_addrwincfg_base + (offset)))
+
+#define CPU_WIN0_BASE LOONGSON_ADDRWINCFG(0x00)
+#define CPU_WIN1_BASE LOONGSON_ADDRWINCFG(0x08)
+#define CPU_WIN2_BASE LOONGSON_ADDRWINCFG(0x10)
+#define CPU_WIN3_BASE LOONGSON_ADDRWINCFG(0x18)
+
+#define CPU_WIN0_MASK LOONGSON_ADDRWINCFG(0x20)
+#define CPU_WIN1_MASK LOONGSON_ADDRWINCFG(0x28)
+#define CPU_WIN2_MASK LOONGSON_ADDRWINCFG(0x30)
+#define CPU_WIN3_MASK LOONGSON_ADDRWINCFG(0x38)
+
+#define CPU_WIN0_MMAP LOONGSON_ADDRWINCFG(0x40)
+#define CPU_WIN1_MMAP LOONGSON_ADDRWINCFG(0x48)
+#define CPU_WIN2_MMAP LOONGSON_ADDRWINCFG(0x50)
+#define CPU_WIN3_MMAP LOONGSON_ADDRWINCFG(0x58)
+
+#define PCIDMA_WIN0_BASE LOONGSON_ADDRWINCFG(0x60)
+#define PCIDMA_WIN1_BASE LOONGSON_ADDRWINCFG(0x68)
+#define PCIDMA_WIN2_BASE LOONGSON_ADDRWINCFG(0x70)
+#define PCIDMA_WIN3_BASE LOONGSON_ADDRWINCFG(0x78)
+
+#define PCIDMA_WIN0_MASK LOONGSON_ADDRWINCFG(0x80)
+#define PCIDMA_WIN1_MASK LOONGSON_ADDRWINCFG(0x88)
+#define PCIDMA_WIN2_MASK LOONGSON_ADDRWINCFG(0x90)
+#define PCIDMA_WIN3_MASK LOONGSON_ADDRWINCFG(0x98)
+
+#define PCIDMA_WIN0_MMAP LOONGSON_ADDRWINCFG(0xa0)
+#define PCIDMA_WIN1_MMAP LOONGSON_ADDRWINCFG(0xa8)
+#define PCIDMA_WIN2_MMAP LOONGSON_ADDRWINCFG(0xb0)
+#define PCIDMA_WIN3_MMAP LOONGSON_ADDRWINCFG(0xb8)
+
+#define ADDRWIN_WIN0 0
+#define ADDRWIN_WIN1 1
+#define ADDRWIN_WIN2 2
+#define ADDRWIN_WIN3 3
+
+#define ADDRWIN_MAP_DST_DDR 0
+#define ADDRWIN_MAP_DST_PCI 1
+#define ADDRWIN_MAP_DST_LIO 1
+
+/*
+ * s: CPU, PCIDMA
+ * d: DDR, PCI, LIO
+ * win: 0, 1, 2, 3
+ * src: map source
+ * dst: map destination
+ * size: ~mask + 1
+ */
+#define LOONGSON_ADDRWIN_CFG(s, d, w, src, dst, size) do {\
+ s##_WIN##w##_BASE = (src); \
+ s##_WIN##w##_MMAP = (src) | ADDRWIN_MAP_DST_##d; \
+ s##_WIN##w##_MASK = ~(size-1); \
+} while (0);
+
+#define LOONGSON_ADDRWIN_CPUTOPCI(win, src, dst, size) \
+ LOONGSON_ADDRWIN_CFG(CPU, PCI, win, src, dst, size)
+#define LOONGSON_ADDRWIN_CPUTODDR(win, src, dst, size) \
+ LOONGSON_ADDRWIN_CFG(CPU, DDR, win, src, dst, size)
+#define LOONGSON_ADDRWIN_PCITODDR(win, src, dst, size) \
+ LOONGSON_ADDRWIN_CFG(PCIDMA, DDR, win, src, dst, size)
+
+#endif /* ! CONFIG_CPU_LOONGSON2F && CONFIG_64BIT */
+
+#endif /* __LOONGSON_H */
diff --git a/arch/mips/include/asm/mach-loongson/mem.h b/arch/mips/include/asm/mach-loongson/mem.h
index ad01dc2..fb53be0 100644
--- a/arch/mips/include/asm/mach-loongson/mem.h
+++ b/arch/mips/include/asm/mach-loongson/mem.h
@@ -1,8 +1,31 @@
#ifndef __MEM_H
#define __MEM_H
+/*
+ * high memory space
+ *
+ * in loongson2e, starts from 512M
+ * in loongson2f, starts from 2G + 256M
+ */
+#ifdef CONFIG_CPU_LOONGSON2E
#define LOONGSON_HIGHMEM_START 0x20000000
+#else
+#define LOONGSON_HIGHMEM_START 0x90000000
+#endif
+
+/*
+ * the peripheral registers(MMIO):
+ *
+ * On the Lemote Loongson 2e system, reside between 0x1000:0000 and 0x2000:0000.
+ * On the Lemote Loongson 2f system, reside between 0x1000:0000 and 0x8000:0000.
+ */
+
#define LOONGSON_MMIO_MEM_START 0x10000000
+
+#ifdef CONFIG_CPU_LOONGSON2E
#define LOONGSON_MMIO_MEM_END 0x20000000
+#else
+#define LOONGSON_MMIO_MEM_END 0x80000000
+#endif
#endif /* !__MEM_H */
diff --git a/arch/mips/include/asm/mach-loongson/pci.h b/arch/mips/include/asm/mach-loongson/pci.h
index 8f02486..cdec41c 100644
--- a/arch/mips/include/asm/mach-loongson/pci.h
+++ b/arch/mips/include/asm/mach-loongson/pci.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2008 Zhang Le <r0bertz@gentoo.org>
+ * Copyright (c) 2009 Wu Zhangjin <wuzj@lemote.com>
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
@@ -24,8 +25,35 @@
extern struct pci_ops loongson_pci_ops;
+/* this is an offset from mips_io_port_base */
+#define LOONGSON_PCI_IO_START 0x00004000UL
+
+#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
+
+/*
+ * we use address window2 to map cpu address space to pci space
+ * window2: cpu [1G, 2G] -> pci [1G, 2G]
+ * why not use window 0 & 1? because they are used by cpu when booting.
+ * window0: cpu [0, 256M] -> ddr [0, 256M]
+ * window1: cpu [256M, 512M] -> pci [256M, 512M]
+ */
+
+/* the smallest LOONGSON_CPU_MEM_SRC can be 512M */
+#define LOONGSON_CPU_MEM_SRC 0x40000000ul /* 1G */
+#define LOONGSON_PCI_MEM_DST LOONGSON_CPU_MEM_SRC
+
+#define LOONGSON_PCI_MEM_START LOONGSON_PCI_MEM_DST
+#define LOONGSON_PCI_MEM_END (0x80000000ul-1) /* 2G */
+
+#define MMAP_CPUTOPCI_SIZE (LOONGSON_PCI_MEM_END - \
+ LOONGSON_PCI_MEM_START + 1)
+
+#else /* loongson2f/32bit & loongson2e */
+
#define LOONGSON_PCI_MEM_START 0x14000000UL
#define LOONGSON_PCI_MEM_END 0x1fffffffUL
-#define LOONGSON_PCI_IO_START 0x00004000UL
+
+#endif /* !(defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT))*/
+
#endif /* !_LOONGSON_PCI_H_ */
diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c
index 76e6fda..9bbd06f 100644
--- a/arch/mips/loongson/common/init.c
+++ b/arch/mips/loongson/common/init.c
@@ -22,6 +22,17 @@
#include <loongson.h>
+#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
+unsigned long _loongson_addrwincfg_base;
+
+/* Loongson CPU address windows config space base address */
+static inline void set_loongson_addrwincfg_base(unsigned long base)
+{
+ *(unsigned long *)&_loongson_addrwincfg_base = base;
+ barrier();
+}
+#endif
+
void __init prom_init(void)
{
/* init mach type, does we need to init it?? */
@@ -31,6 +42,12 @@ void __init prom_init(void)
set_io_port_base((unsigned long)
ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
+#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
+ set_loongson_addrwincfg_base((unsigned long)
+ ioremap(LOONGSON_ADDRWINCFG_BASE,
+ LOONGSON_ADDRWINCFG_SIZE));
+#endif
+
prom_init_cmdline();
prom_init_memory();
}
diff --git a/arch/mips/loongson/common/mem.c b/arch/mips/loongson/common/mem.c
index 17a7278..9e0b6e0 100644
--- a/arch/mips/loongson/common/mem.c
+++ b/arch/mips/loongson/common/mem.c
@@ -17,6 +17,23 @@ void __init prom_init_memory(void)
{
add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
#ifdef CONFIG_64BIT
+#ifdef CONFIG_CPU_LOONGSON2F
+ {
+ int bit;
+
+ bit = fls(memsize + highmemsize);
+ if (bit != ffs(memsize + highmemsize))
+ bit += 20;
+ else
+ bit = bit + 20 - 1;
+
+ /* set cpu window3 to map CPU to DDR: 2G -> 2G */
+ LOONGSON_ADDRWIN_CPUTODDR(ADDRWIN_WIN3, 0x80000000ul,
+ 0x80000000ul, (1 << bit));
+ mmiowb();
+ }
+#endif /* CONFIG_CPU_LOONGSON2F */
+
if (highmemsize > 0) {
add_memory_region(LOONGSON_HIGHMEM_START,
highmemsize << 20, BOOT_MEM_RAM);
@@ -30,10 +47,6 @@ int __uncached_access(struct file *file, unsigned long addr)
if (file->f_flags & O_SYNC)
return 1;
- /*
- * On the Lemote Loongson 2e system, the peripheral registers
- * reside between 0x1000:0000 and 0x2000:0000.
- */
return addr >= __pa(high_memory) ||
((addr >= LOONGSON_MMIO_MEM_START) && \
(addr < LOONGSON_MMIO_MEM_END));
diff --git a/arch/mips/loongson/common/pci.c b/arch/mips/loongson/common/pci.c
index e97c845..e8291c3 100644
--- a/arch/mips/loongson/common/pci.c
+++ b/arch/mips/loongson/common/pci.c
@@ -30,15 +30,15 @@
#include <pci.h>
static struct resource loongson_pci_mem_resource = {
- .name = "LOONGSON PCI MEM",
+ .name = "pci memory space",
.start = LOONGSON_PCI_MEM_START,
.end = LOONGSON_PCI_MEM_END,
.flags = IORESOURCE_MEM,
};
static struct resource loongson_pci_io_resource = {
- .name = "LOONGSON PCI IO MEM",
- .start = LOONGSON_PCI_IO_START,
+ .name = "pci io space",
+ .start = LOONGSON_PCI_IO_START, /* reserve regacy I/O space */
.end = IO_SPACE_LIMIT,
.flags = IORESOURCE_IO,
};
@@ -85,6 +85,14 @@ static void __init ict_pcimap(void)
/* can not change gnt to break pci transfer when device's gnt not
deassert for some broken device */
LOONGSON_PXARB_CFG = 0x00fe0105ul;
+
+#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
+ /*
+ * set cpu addr window2 to map CPU address space to PCI address space
+ */
+ LOONGSON_ADDRWIN_CPUTOPCI(ADDRWIN_WIN2, LOONGSON_CPU_MEM_SRC,
+ LOONGSON_PCI_MEM_DST, MMAP_CPUTOPCI_SIZE);
+#endif
}
static int __init pcibios_init(void)
--
1.6.2.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [loongson-PATCH-v1 13/27] add basic fuloong(2f) support
[not found] <cover.1242855716.git.wuzhangjin@gmail.com>
2009-05-20 22:05 ` [loongson-PATCH-v1 12/27] add basic loongson-2f support wuzhangjin
@ 2009-05-20 22:06 ` wuzhangjin
2009-05-20 22:08 ` [loongson-PATCH-v1 16/27] Add Siliconmotion 712 framebuffer driver wuzhangjin
` (2 subsequent siblings)
4 siblings, 0 replies; 20+ messages in thread
From: wuzhangjin @ 2009-05-20 22:06 UTC (permalink / raw)
To: linux-mips, Ralf Baechle, Andrew Morton
Cc: linux-kernel, Wu Zhangjin, Yan hua, Philippe Vachon, Zhang Le,
Zhang Fuxin, Arnaud Patard, loongson-dev, gnewsense-dev,
Nicholas Mc Guire, Liu Junliang, Erwan Lerale
From: Wu Zhangjin <wuzhangjin@gmail.com>
fuloong(2e) has an VIA686B south bridge, but fuloong(2f) has an AMD
CS5536 south bridge. so, we need to add basic cs5536 south bridge
support here.
there are several modules provided by cs5536, currently, only these
modules are used in fuloong(2f) mini PC: ide, acc(audio), ohci, isa, and
ehci. and these modules are general modules, which means should be
compiled in kernel by default, besides, there are several selective
modules: flash(nor and nand), otg, udc. the otg and udc modules are used
in the NAS machine made by Lemote(the source code support will be added
later, only a few differ from fuloong2f mini PC).
since the PCI operations are similiar between fuloong(2e) and
fuloong(2f),yeeloong(2f) and even similiar to gdium, herein, I just
rename ops-fuloong2e.c to ops-loongsgon2.c to share most of the source
code.
PS: the originl cs5536 support for fuloong2f is from the to-mips branch
of git://dev.lemote.com/linux_loongson.git, tons of source code have
been cleaned up. the most important change is using the linux-internal
pci_regs.h(include/linux/pci_regs.h) instead of the original pcireg.h
and dividing the huge cs5536_vsm.c to several small files, one file one
cs5536 module. at the same time, tons of souce code are tuned to be
understandable and some trashy souce code are removed away which will
archieve a higher performance. and also, the header files, cs5536.h and
cs5536_pci.h are cleaned up a lot.
Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
arch/mips/Makefile | 1 +
.../mips/include/asm/mach-loongson/cs5536/cs5536.h | 382 +++++++++++++++++
.../include/asm/mach-loongson/cs5536/cs5536_pci.h | 174 ++++++++
.../include/asm/mach-loongson/cs5536/cs5536_vsm.h | 59 +++
arch/mips/include/asm/mach-loongson/loongson.h | 2 +-
arch/mips/include/asm/mach-loongson/machine.h | 30 ++
arch/mips/loongson/Kconfig | 44 ++
arch/mips/loongson/Makefile | 6 +
arch/mips/loongson/common/Makefile | 6 +
arch/mips/loongson/common/bonito-irq.c | 5 +
arch/mips/loongson/common/cs5536/Makefile | 20 +
arch/mips/loongson/common/cs5536/cs5536_acc.c | 155 +++++++
arch/mips/loongson/common/cs5536/cs5536_ehci.c | 165 +++++++
arch/mips/loongson/common/cs5536/cs5536_flash.c | 450 ++++++++++++++++++++
arch/mips/loongson/common/cs5536/cs5536_ide.c | 193 +++++++++
arch/mips/loongson/common/cs5536/cs5536_isa.c | 376 ++++++++++++++++
arch/mips/loongson/common/cs5536/cs5536_ohci.c | 167 ++++++++
arch/mips/loongson/common/cs5536/cs5536_otg.c | 137 ++++++
arch/mips/loongson/common/cs5536/cs5536_pci.c | 126 ++++++
arch/mips/loongson/common/cs5536/cs5536_udc.c | 142 ++++++
arch/mips/loongson/fuloong-2f/Makefile | 5 +
arch/mips/loongson/fuloong-2f/irq.c | 53 +++
arch/mips/loongson/fuloong-2f/reset.c | 65 +++
arch/mips/pci/Makefile | 3 +-
arch/mips/pci/fixup-fuloong2f.c | 171 ++++++++
arch/mips/pci/ops-fuloong2e.c | 160 -------
arch/mips/pci/ops-loongson2.c | 213 +++++++++
27 files changed, 3148 insertions(+), 162 deletions(-)
create mode 100644 arch/mips/include/asm/mach-loongson/cs5536/cs5536.h
create mode 100644 arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h
create mode 100644 arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h
create mode 100644 arch/mips/loongson/common/cs5536/Makefile
create mode 100644 arch/mips/loongson/common/cs5536/cs5536_acc.c
create mode 100644 arch/mips/loongson/common/cs5536/cs5536_ehci.c
create mode 100644 arch/mips/loongson/common/cs5536/cs5536_flash.c
create mode 100644 arch/mips/loongson/common/cs5536/cs5536_ide.c
create mode 100644 arch/mips/loongson/common/cs5536/cs5536_isa.c
create mode 100644 arch/mips/loongson/common/cs5536/cs5536_ohci.c
create mode 100644 arch/mips/loongson/common/cs5536/cs5536_otg.c
create mode 100644 arch/mips/loongson/common/cs5536/cs5536_pci.c
create mode 100644 arch/mips/loongson/common/cs5536/cs5536_udc.c
create mode 100644 arch/mips/loongson/fuloong-2f/Makefile
create mode 100644 arch/mips/loongson/fuloong-2f/irq.c
create mode 100644 arch/mips/loongson/fuloong-2f/reset.c
create mode 100644 arch/mips/pci/fixup-fuloong2f.c
delete mode 100644 arch/mips/pci/ops-fuloong2e.c
create mode 100644 arch/mips/pci/ops-loongson2.c
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 6cbfc22..abf16c1 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -310,6 +310,7 @@ core-$(CONFIG_LOONGSON_SYSTEMS) +=arch/mips/loongson/
cflags-$(CONFIG_LOONGSON_SYSTEMS) += -I$(srctree)/arch/mips/include/asm/mach-loongson \
-mno-branch-likely
load-$(CONFIG_LEMOTE_FULOONG2E) +=0xffffffff80100000
+load-$(CONFIG_LEMOTE_FULOONG2F) +=0xffffffff80200000
#
# MIPS Malta board
diff --git a/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h b/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h
new file mode 100644
index 0000000..a9bbe1d
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h
@@ -0,0 +1,382 @@
+/*
+ * The header file of cs5536 sourth bridge.
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author : jlliu <liujl@lemote.com>
+ */
+
+#ifndef _CS5536_H
+#define _CS5536_H
+
+#include <linux/types.h>
+
+extern void _rdmsr(u32 msr, u32 *hi, u32 *lo);
+extern void _wrmsr(u32 msr, u32 hi, u32 lo);
+
+/*
+ * MSR module base
+ */
+#define CS5536_SB_MSR_BASE (0x00000000)
+#define CS5536_GLIU_MSR_BASE (0x10000000)
+#define CS5536_ILLEGAL_MSR_BASE (0x20000000)
+#define CS5536_USB_MSR_BASE (0x40000000)
+#define CS5536_IDE_MSR_BASE (0x60000000)
+#define CS5536_DIVIL_MSR_BASE (0x80000000)
+#define CS5536_ACC_MSR_BASE (0xa0000000)
+#define CS5536_UNUSED_MSR_BASE (0xc0000000)
+#define CS5536_GLCP_MSR_BASE (0xe0000000)
+
+#define SB_MSR_REG(offset) (CS5536_SB_MSR_BASE | (offset))
+#define GLIU_MSR_REG(offset) (CS5536_GLIU_MSR_BASE | (offset))
+#define ILLEGAL_MSR_REG(offset) (CS5536_ILLEGAL_MSR_BASE | (offset))
+#define USB_MSR_REG(offset) (CS5536_USB_MSR_BASE | (offset))
+#define IDE_MSR_REG(offset) (CS5536_IDE_MSR_BASE | (offset))
+#define DIVIL_MSR_REG(offset) (CS5536_DIVIL_MSR_BASE | (offset))
+#define ACC_MSR_REG(offset) (CS5536_ACC_MSR_BASE | (offset))
+#define UNUSED_MSR_REG(offset) (CS5536_UNUSED_MSR_BASE | (offset))
+#define GLCP_MSR_REG(offset) (CS5536_GLCP_MSR_BASE | (offset))
+
+/*
+ * BAR SPACE OF VIRTUAL PCI :
+ * range for pci probe use, length is the actual size.
+ */
+/* IO space for all DIVIL modules */
+#define CS5536_IRQ_RANGE 0xffffffe0 /* USERD FOR PCI PROBE */
+#define CS5536_IRQ_LENGTH 0x20 /* THE REGS ACTUAL LENGTH */
+#define CS5536_SMB_RANGE 0xfffffff8
+#define CS5536_SMB_LENGTH 0x08
+#define CS5536_GPIO_RANGE 0xffffff00
+#define CS5536_GPIO_LENGTH 0x100
+#define CS5536_MFGPT_RANGE 0xffffffc0
+#define CS5536_MFGPT_LENGTH 0x40
+#define CS5536_ACPI_RANGE 0xffffffe0
+#define CS5536_ACPI_LENGTH 0x20
+#define CS5536_PMS_RANGE 0xffffff80
+#define CS5536_PMS_LENGTH 0x80
+/* MEM space for 4KB nand flash; IO space for 16B nor flash. */
+#ifdef CS5536_NOR_FLASH
+#define CS5536_FLSH_LENGTH 0x10
+#define CS5536_FLSH_RANGE 0xfffffff0
+#else
+#define CS5536_FLSH_RANGE 0xfffff000
+#define CS5536_FLSH_LENGTH 0x1000
+#endif
+/* IO space for IDE */
+#define CS5536_IDE_RANGE 0xfffffff0
+#define CS5536_IDE_LENGTH 0x10
+/* IO space for ACC */
+#define CS5536_ACC_RANGE 0xffffff80
+#define CS5536_ACC_LENGTH 0x80
+/* MEM space for ALL USB modules */
+#define CS5536_OHCI_RANGE 0xfffff000
+#define CS5536_OHCI_LENGTH 0x1000
+#define CS5536_EHCI_RANGE 0xfffff000
+#define CS5536_EHCI_LENGTH 0x1000
+#define CS5536_UDC_RANGE 0xffffe000
+#define CS5536_UDC_LENGTH 0x2000
+#define CS5536_OTG_RANGE 0xfffff000
+#define CS5536_OTG_LENGTH 0x1000
+
+/*
+ * PCI MSR ACCESS
+ */
+#define PCI_MSR_CTRL 0xF0
+#define PCI_MSR_ADDR 0xF4
+#define PCI_MSR_DATA_LO 0xF8
+#define PCI_MSR_DATA_HI 0xFC
+
+/**************** MSR *****************************/
+
+/*
+ * GLIU STANDARD MSR
+ */
+#define GLIU_CAP 0x00
+#define GLIU_CONFIG 0x01
+#define GLIU_SMI 0x02
+#define GLIU_ERROR 0x03
+#define GLIU_PM 0x04
+#define GLIU_DIAG 0x05
+
+/*
+ * GLIU SPEC. MSR
+ */
+#define GLIU_P2D_BM0 0x20
+#define GLIU_P2D_BM1 0x21
+#define GLIU_P2D_BM2 0x22
+#define GLIU_P2D_BMK0 0x23
+#define GLIU_P2D_BMK1 0x24
+#define GLIU_P2D_BM3 0x25
+#define GLIU_P2D_BM4 0x26
+#define GLIU_COH 0x80
+#define GLIU_PAE 0x81
+#define GLIU_ARB 0x82
+#define GLIU_ASMI 0x83
+#define GLIU_AERR 0x84
+#define GLIU_DEBUG 0x85
+#define GLIU_PHY_CAP 0x86
+#define GLIU_NOUT_RESP 0x87
+#define GLIU_NOUT_WDATA 0x88
+#define GLIU_WHOAMI 0x8B
+#define GLIU_SLV_DIS 0x8C
+#define GLIU_IOD_BM0 0xE0
+#define GLIU_IOD_BM1 0xE1
+#define GLIU_IOD_BM2 0xE2
+#define GLIU_IOD_BM3 0xE3
+#define GLIU_IOD_BM4 0xE4
+#define GLIU_IOD_BM5 0xE5
+#define GLIU_IOD_BM6 0xE6
+#define GLIU_IOD_BM7 0xE7
+#define GLIU_IOD_BM8 0xE8
+#define GLIU_IOD_BM9 0xE9
+#define GLIU_IOD_SC0 0xEA
+#define GLIU_IOD_SC1 0xEB
+#define GLIU_IOD_SC2 0xEC
+#define GLIU_IOD_SC3 0xED
+#define GLIU_IOD_SC4 0xEE
+#define GLIU_IOD_SC5 0xEF
+#define GLIU_IOD_SC6 0xF0
+#define GLIU_IOD_SC7 0xF1
+
+/*
+ * SB STANDARD
+ */
+#define SB_CAP 0x00
+#define SB_CONFIG 0x01
+#define SB_SMI 0x02
+#define SB_ERROR 0x03
+#define SB_MAR_ERR_EN 0x00000001
+#define SB_TAR_ERR_EN 0x00000002
+#define SB_RSVD_BIT1 0x00000004
+#define SB_EXCEP_ERR_EN 0x00000008
+#define SB_SYSE_ERR_EN 0x00000010
+#define SB_PARE_ERR_EN 0x00000020
+#define SB_TAS_ERR_EN 0x00000040
+#define SB_MAR_ERR_FLAG 0x00010000
+#define SB_TAR_ERR_FLAG 0x00020000
+#define SB_RSVD_BIT2 0x00040000
+#define SB_EXCEP_ERR_FLAG 0x00080000
+#define SB_SYSE_ERR_FLAG 0x00100000
+#define SB_PARE_ERR_FLAG 0x00200000
+#define SB_TAS_ERR_FLAG 0x00400000
+#define SB_PM 0x04
+#define SB_DIAG 0x05
+
+/*
+ * SB SPEC.
+ */
+#define SB_CTRL 0x10
+#define SB_R0 0x20
+#define SB_R1 0x21
+#define SB_R2 0x22
+#define SB_R3 0x23
+#define SB_R4 0x24
+#define SB_R5 0x25
+#define SB_R6 0x26
+#define SB_R7 0x27
+#define SB_R8 0x28
+#define SB_R9 0x29
+#define SB_R10 0x2A
+#define SB_R11 0x2B
+#define SB_R12 0x2C
+#define SB_R13 0x2D
+#define SB_R14 0x2E
+#define SB_R15 0x2F
+
+/*
+ * GLCP STANDARD
+ */
+#define GLCP_CAP 0x00
+#define GLCP_CONFIG 0x01
+#define GLCP_SMI 0x02
+#define GLCP_ERROR 0x03
+#define GLCP_PM 0x04
+#define GLCP_DIAG 0x05
+
+/*
+ * GLCP SPEC.
+ */
+#define GLCP_CLK_DIS_DELAY 0x08
+#define GLCP_PM_CLK_DISABLE 0x09
+#define GLCP_GLB_PM 0x0B
+#define GLCP_DBG_OUT 0x0C
+#define GLCP_RSVD1 0x0D
+#define GLCP_SOFT_COM 0x0E
+#define SOFT_BAR_SMB_FLAG 0x00000001
+#define SOFT_BAR_GPIO_FLAG 0x00000002
+#define SOFT_BAR_MFGPT_FLAG 0x00000004
+#define SOFT_BAR_IRQ_FLAG 0x00000008
+#define SOFT_BAR_PMS_FLAG 0x00000010
+#define SOFT_BAR_ACPI_FLAG 0x00000020
+#define SOFT_BAR_FLSH0_FLAG 0x00000040
+#define SOFT_BAR_FLSH1_FLAG 0x00000080
+#define SOFT_BAR_FLSH2_FLAG 0x00000100
+#define SOFT_BAR_FLSH3_FLAG 0x00000200
+#define SOFT_BAR_IDE_FLAG 0x00000400
+#define SOFT_BAR_ACC_FLAG 0x00000800
+#define SOFT_BAR_OHCI_FLAG 0x00001000
+#define SOFT_BAR_EHCI_FLAG 0x00002000
+#define SOFT_BAR_UDC_FLAG 0x00004000
+#define SOFT_BAR_OTG_FLAG 0x00008000
+#define GLCP_RSVD2 0x0F
+#define GLCP_CLK_OFF 0x10
+#define GLCP_CLK_ACTIVE 0x11
+#define GLCP_CLK_DISABLE 0x12
+#define GLCP_CLK4ACK 0x13
+#define GLCP_SYS_RST 0x14
+#define GLCP_RSVD3 0x15
+#define GLCP_DBG_CLK_CTRL 0x16
+#define GLCP_CHIP_REV_ID 0x17
+
+/*
+ * DIVIL STANDARD
+ */
+#define DIVIL_CAP 0x00
+#define DIVIL_CONFIG 0x01
+#define DIVIL_SMI 0x02
+#define DIVIL_ERROR 0x03
+#define DIVIL_PM 0x04
+#define DIVIL_DIAG 0x05
+
+/*
+ * DIVIL SPEC.
+ */
+#define DIVIL_LBAR_IRQ 0x08
+#define DIVIL_LBAR_KEL 0x09
+#define DIVIL_LBAR_SMB 0x0B
+#define DIVIL_LBAR_GPIO 0x0C
+#define DIVIL_LBAR_MFGPT 0x0D
+#define DIVIL_LBAR_ACPI 0x0E
+#define DIVIL_LBAR_PMS 0x0F
+#define DIVIL_LBAR_FLSH0 0x10
+#define DIVIL_LBAR_FLSH1 0x11
+#define DIVIL_LBAR_FLSH2 0x12
+#define DIVIL_LBAR_FLSH3 0x13
+#define DIVIL_LEG_IO 0x14
+#define DIVIL_BALL_OPTS 0x15
+#define DIVIL_SOFT_IRQ 0x16
+#define DIVIL_SOFT_RESET 0x17
+/* NOR FLASH */
+#define NORF_CTRL 0x18
+#define NORF_T01 0x19
+#define NORF_T23 0x1A
+/* NAND FLASH */
+#define NANDF_DATA 0x1B
+#define NANDF_CTRL 0x1C
+#define NANDF_RSVD 0x1D
+/* KEL Keyboard Emulation Logic */
+#define KEL_CTRL 0x1F
+/* PIC */
+#define PIC_YSEL_LOW 0x20
+#define PIC_YSEL_LOW_USB_SHIFT 8
+#define PIC_YSEL_LOW_ACC_SHIFT 16
+#define PIC_YSEL_LOW_FLASH_SHIFT 24
+#define PIC_YSEL_HIGH 0x21
+#define PIC_ZSEL_LOW 0x22
+#define PIC_ZSEL_HIGH 0x23
+#define PIC_IRQM_PRIM 0x24
+#define PIC_IRQM_LPC 0x25
+#define PIC_XIRR_STS_LOW 0x26
+#define PIC_XIRR_STS_HIGH 0x27
+#define PCI_SHDW 0x34
+/* MFGPT */
+#define MFGPT_IRQ 0x28
+#define MFGPT_NR 0x29
+#define MFGPT_RSVD 0x2A
+#define MFGPT_SETUP 0x2B
+/* FLOPPY */
+#define FLPY_3F2_SHDW 0x30
+#define FLPY_3F7_SHDW 0x31
+#define FLPY_372_SHDW 0x32
+#define FLPY_377_SHDW 0x33
+/* PIT */
+#define PIT_SHDW 0x36
+#define PIT_CNTRL 0x37
+/* UART */
+#define UART1_MOD 0x38
+#define UART1_DONG 0x39
+#define UART1_CONF 0x3A
+#define UART1_RSVD 0x3B
+#define UART2_MOD 0x3C
+#define UART2_DONG 0x3D
+#define UART2_CONF 0x3E
+#define UART2_RSVD 0x3F
+/* DMA */
+#define DIVIL_AC_DMA 0x1E
+#define DMA_MAP 0x40
+#define DMA_SHDW_CH0 0x41
+#define DMA_SHDW_CH1 0x42
+#define DMA_SHDW_CH2 0x43
+#define DMA_SHDW_CH3 0x44
+#define DMA_SHDW_CH4 0x45
+#define DMA_SHDW_CH5 0x46
+#define DMA_SHDW_CH6 0x47
+#define DMA_SHDW_CH7 0x48
+#define DMA_MSK_SHDW 0x49
+/* LPC */
+#define LPC_EADDR 0x4C
+#define LPC_ESTAT 0x4D
+#define LPC_SIRQ 0x4E
+#define LPC_RSVD 0x4F
+/* PMC */
+#define PMC_LTMR 0x50
+#define PMC_RSVD 0x51
+/* RTC */
+#define RTC_RAM_LOCK 0x54
+#define RTC_DOMA_OFFSET 0x55
+#define RTC_MONA_OFFSET 0x56
+#define RTC_CEN_OFFSET 0x57
+
+/*
+ * IDE STANDARD
+ */
+#define IDE_CAP 0x00
+#define IDE_CONFIG 0x01
+#define IDE_SMI 0x02
+#define IDE_ERROR 0x03
+#define IDE_PM 0x04
+#define IDE_DIAG 0x05
+
+/*
+ * IDE SPEC.
+ */
+#define IDE_IO_BAR 0x08
+#define IDE_CFG 0x10
+#define IDE_DTC 0x12
+#define IDE_CAST 0x13
+#define IDE_ETC 0x14
+#define IDE_INTERNAL_PM 0x15
+
+/*
+ * ACC STANDARD
+ */
+#define ACC_CAP 0x00
+#define ACC_CONFIG 0x01
+#define ACC_SMI 0x02
+#define ACC_ERROR 0x03
+#define ACC_PM 0x04
+#define ACC_DIAG 0x05
+
+/*
+ * USB STANDARD
+ */
+#define USB_CAP 0x00
+#define USB_CONFIG 0x01
+#define USB_SMI 0x02
+#define USB_ERROR 0x03
+#define USB_PM 0x04
+#define USB_DIAG 0x05
+
+/*
+ * USB SPEC.
+ */
+#define USB_OHCI 0x08
+#define USB_EHCI 0x09
+#define USB_UDC 0x0A
+#define USB_OTG 0x0B
+
+/****************** NATIVE ***************************/
+/* GPIO : I/O SPACE; REG : 32BITS */
+#define GPIOL_OUT_VAL 0x00
+#define GPIOL_OUT_EN 0x04
+
+#endif /* _CS5536_H */
diff --git a/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h b/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h
new file mode 100644
index 0000000..34d37ed
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h
@@ -0,0 +1,174 @@
+/*
+ * the definition file of cs5536 Virtual Support Module(VSM).
+ * pci configuration space can be accessed through the VSM, so
+ * there is no need of the MSR read/write now, except the spec.
+ * MSR registers which are not implemented yet.
+ *
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author : jlliu, liujl@lemote.com
+ */
+
+#ifndef _CS5536_PCI_H
+#define _CS5536_PCI_H
+
+#include <linux/types.h>
+#include <linux/pci_regs.h>
+
+extern void cs5536_pci_conf_write4(int function, int reg, u32 value);
+extern u32 cs5536_pci_conf_read4(int function, int reg);
+
+#define CS5536_FLASH_INTR 6
+#define CS5536_ACC_INTR 9
+#define CS5536_IDE_INTR 14
+#define CS5536_USB_INTR 11
+#define CS5536_UART1_INTR 4
+#define CS5536_UART2_INTR 3
+
+/************** PCI BUS DEVICE FUNCTION ***************/
+
+/*
+ * PCI bus device function
+ */
+#define PCI_BUS_CS5536 0
+#define PCI_IDSEL_CS5536 14
+
+/********** STANDARD PCI-2.2 EXPANSION ****************/
+
+/*
+ * PCI configuration space
+ * we have to virtualize the PCI configure space head, so we should
+ * define the necessary IDs and some others.
+ */
+
+/* CONFIG of PCI VENDOR ID*/
+#define CFG_PCI_VENDOR_ID(mod_dev_id, sys_vendor_id) \
+ (((mod_dev_id) << 16) | (sys_vendor_id))
+
+/* VENDOR ID */
+#define CS5536_VENDOR_ID 0x1022
+
+/* DEVICE ID */
+#define CS5536_ISA_DEVICE_ID 0x2090
+#define CS5536_FLASH_DEVICE_ID 0x2091
+#define CS5536_IDE_DEVICE_ID 0x209a
+#define CS5536_ACC_DEVICE_ID 0x2093
+#define CS5536_OHCI_DEVICE_ID 0x2094
+#define CS5536_EHCI_DEVICE_ID 0x2095
+#define CS5536_UDC_DEVICE_ID 0x2096
+#define CS5536_OTG_DEVICE_ID 0x2097
+
+/* CLASS CODE : CLASS SUB-CLASS INTERFACE */
+#define CS5536_ISA_CLASS_CODE 0x060100
+#define CS5536_FLASH_CLASS_CODE 0x050100
+#define CS5536_IDE_CLASS_CODE 0x010180
+#define CS5536_ACC_CLASS_CODE 0x040100
+#define CS5536_OHCI_CLASS_CODE 0x0C0310
+#define CS5536_EHCI_CLASS_CODE 0x0C0320
+#define CS5536_UDC_CLASS_CODE 0x0C03FE
+#define CS5536_OTG_CLASS_CODE 0x0C0380
+
+/* BHLC : BIST HEADER-TYPE LATENCY-TIMER CACHE-LINE-SIZE */
+
+#define CFG_PCI_CACHE_LINE_SIZE(header_type, latency_timer) \
+ ((PCI_NONE_BIST << 24) | ((header_type) << 16) \
+ | ((latency_timer) << 8) | PCI_NORMAL_CACHE_LINE_SIZE);
+
+#define PCI_NONE_BIST 0x00 /* RO not implemented yet. */
+#define PCI_BRIDGE_HEADER_TYPE 0x80 /* RO */
+#define PCI_NORMAL_HEADER_TYPE 0x00
+#define PCI_NORMAL_LATENCY_TIMER 0x00
+#define PCI_NORMAL_CACHE_LINE_SIZE 0x08 /* RW */
+
+/* BAR */
+#define PCI_BAR0_REG 0x10
+#define PCI_BAR1_REG 0x14
+#define PCI_BAR2_REG 0x18
+#define PCI_BAR3_REG 0x1c
+#define PCI_BAR4_REG 0x20
+#define PCI_BAR5_REG 0x24
+#define PCI_BAR_COUNT 6
+#define PCI_BAR_RANGE_MASK 0xFFFFFFFF
+
+/* CARDBUS CIS POINTER */
+#define PCI_CARDBUS_CIS_POINTER 0x00000000
+
+/* SUBSYSTEM VENDOR ID */
+#define CS5536_SUB_VENDOR_ID CS5536_VENDOR_ID
+
+/* SUBSYSTEM ID */
+#define CS5536_ISA_SUB_ID CS5536_ISA_DEVICE_ID
+#define CS5536_FLASH_SUB_ID CS5536_FLASH_DEVICE_ID
+#define CS5536_IDE_SUB_ID CS5536_IDE_DEVICE_ID
+#define CS5536_ACC_SUB_ID CS5536_ACC_DEVICE_ID
+#define CS5536_OHCI_SUB_ID CS5536_OHCI_DEVICE_ID
+#define CS5536_EHCI_SUB_ID CS5536_EHCI_DEVICE_ID
+#define CS5536_UDC_SUB_ID CS5536_UDC_DEVICE_ID
+#define CS5536_OTG_SUB_ID CS5536_OTG_DEVICE_ID
+
+/* EXPANSION ROM BAR */
+#define PCI_EXPANSION_ROM_BAR 0x00000000
+
+/* CAPABILITIES POINTER */
+#define PCI_CAPLIST_POINTER 0x00000000
+#define PCI_CAPLIST_USB_POINTER 0x40
+/* INTERRUPT */
+
+#define CFG_PCI_INTERRUPT_LINE(pin, mod_intr) \
+ ((PCI_MAX_LATENCY << 24) | (PCI_MIN_GRANT << 16) | \
+ ((pin) << 8) | (mod_intr))
+
+#define PCI_MAX_LATENCY 0x40
+#define PCI_MIN_GRANT 0x00
+#define PCI_DEFAULT_PIN 0x01
+
+/*********** EXPANSION PCI REG ************************/
+
+/*
+ * ISA EXPANSION
+ */
+#define PCI_UART1_INT_REG 0x50
+#define PCI_UART2_INT_REG 0x54
+#define PCI_ISA_FIXUP_REG 0x58
+
+/*
+ * FLASH EXPANSION
+ */
+#define PCI_FLASH_INT_REG 0x50
+#define PCI_NOR_FLASH_CTRL_REG 0x40
+#define PCI_NOR_FLASH_T01_REG 0x44
+#define PCI_NOR_FLASH_T23_REG 0x48
+#define PCI_NAND_FLASH_TDATA_REG 0x60
+#define PCI_NAND_FLASH_TCTRL_REG 0x64
+#define PCI_NAND_FLASH_RSVD_REG 0x68
+#define PCI_FLASH_SELECT_REG 0x70
+
+/*
+ * IDE EXPANSION
+ */
+#define PCI_IDE_CFG_REG 0x40
+#define CS5536_IDE_FLASH_SIGNATURE 0xDEADBEEF
+#define PCI_IDE_DTC_REG 0x48
+#define PCI_IDE_CAST_REG 0x4C
+#define PCI_IDE_ETC_REG 0x50
+#define PCI_IDE_PM_REG 0x54
+#define PCI_IDE_INT_REG 0x60
+
+/*
+ * ACC EXPANSION
+ */
+#define PCI_ACC_INT_REG 0x50
+
+/*
+ * OHCI EXPANSION : INTTERUPT IS IMPLEMENTED BY THE OHCI
+ */
+#define PCI_OHCI_PM_REG 0x40
+#define PCI_OHCI_INT_REG 0x50
+
+/*
+ * EHCI EXPANSION
+ */
+#define PCI_EHCI_LEGSMIEN_REG 0x50
+#define PCI_EHCI_LEGSMISTS_REG 0x54
+#define PCI_EHCI_FLADJ_REG 0x60
+
+#endif /* _CS5536_PCI_H_ */
diff --git a/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h b/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h
new file mode 100644
index 0000000..41e7136
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h
@@ -0,0 +1,59 @@
+/*
+ * the Virtual Support Module(VSM) read/write interfaces
+ *
+ * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Author: Wu Zhangjin <wuzj@lemote.com>
+ */
+
+#ifndef _CS5536_VSM_H
+#define _CS5536_VSM_H
+
+#include <linux/types.h>
+
+#define DECLARE_CS5536_MODULE(name) \
+extern void pci_##name##_write_reg(int reg, u32 value); \
+extern u32 pci_##name##_read_reg(int reg);
+
+#define DEFINE_CS5536_MODULE(name) \
+void pci_##name##_write_reg(int reg, u32 value)\
+{ \
+ return; \
+} \
+u32 pci_##name##_read_reg(int reg) \
+{ \
+ return 0xffffffff; \
+} \
+
+/* core modules of cs5536 */
+
+/* ide module */
+DECLARE_CS5536_MODULE(ide)
+/* acc module */
+DECLARE_CS5536_MODULE(acc)
+/* ohci module */
+DECLARE_CS5536_MODULE(ohci)
+/* isa module */
+DECLARE_CS5536_MODULE(isa)
+/* ehci module */
+DECLARE_CS5536_MODULE(ehci)
+
+/* selective modules of cs5536 */
+/* flash(nor or nand flash) module */
+#ifdef CONFIG_CS5536_FLASH
+ DECLARE_CS5536_MODULE(flash)
+#else
+ DEFINE_CS5536_MODULE(flash)
+#endif
+/* otg module */
+#ifdef CONFIG_CS5536_OTG
+ DECLARE_CS5536_MODULE(otg)
+#else
+ DEFINE_CS5536_MODULE(otg)
+#endif
+/* udc module */
+#ifdef CONFIG_CS5536_UDC
+ DECLARE_CS5536_MODULE(udc)
+#else
+ DEFINE_CS5536_MODULE(udc)
+#endif
+#endif /* _CS5536_VSM_H */
diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
index 8ddfbd3..aaa2948 100644
--- a/arch/mips/include/asm/mach-loongson/loongson.h
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
@@ -287,7 +287,7 @@ extern unsigned long _loongson_addrwincfg_base;
s##_WIN##w##_BASE = (src); \
s##_WIN##w##_MMAP = (src) | ADDRWIN_MAP_DST_##d; \
s##_WIN##w##_MASK = ~(size-1); \
-} while (0);
+} while (0)
#define LOONGSON_ADDRWIN_CPUTOPCI(win, src, dst, size) \
LOONGSON_ADDRWIN_CFG(CPU, PCI, win, src, dst, size)
diff --git a/arch/mips/include/asm/mach-loongson/machine.h b/arch/mips/include/asm/mach-loongson/machine.h
index 5f2cd3a..bb3dd37 100644
--- a/arch/mips/include/asm/mach-loongson/machine.h
+++ b/arch/mips/include/asm/mach-loongson/machine.h
@@ -13,6 +13,8 @@
#ifndef __MACHINE_H
#define __MACHINE_H
+#ifdef CONFIG_LEMOTE_FULOONG2E
+
#define MACH_NAME "lemote-fuloong(2e)"
#define LOONGSON_UART_BASE 0x1fd003f8
@@ -23,5 +25,33 @@
#define LOONGSON_TIMER_IRQ (MIPS_CPU_IRQ_BASE + 7)
#define LOONGSON_DMATIMEOUT_IRQ (LOONGSON_IRQ_BASE + 10)
+#else /* CONFIG_LEMOTE_FULOONG2F */
+
+#define MACH_NAME "lemote-fuloong(2f)"
+
+#define LOONGSON_UART_BASE 0x1fd002f8
+
+#define LOONGSON_TIMER_IRQ (MIPS_CPU_IRQ_BASE + 7) /* cpu timer */
+#define LOONGSON_PERFCNT_IRQ (MIPS_CPU_IRQ_BASE + 6) /* cpu perf counter */
+#define LOONGSON_NORTH_BRIDGE_IRQ (MIPS_CPU_IRQ_BASE + 6) /* bonito */
+#define LOONGSON_UART_IRQ (MIPS_CPU_IRQ_BASE + 3) /* cpu serial port */
+#define LOONGSON_SOUTH_BRIDGE_IRQ (MIPS_CPU_IRQ_BASE + 2) /* i8259 */
+
+#define LOONGSON_INT_BIT_GPIO1 (1 << 1)
+#define LOONGSON_INT_BIT_GPIO2 (1 << 2)
+#define LOONGSON_INT_BIT_GPIO3 (1 << 3)
+#define LOONGSON_INT_BIT_PCI_INTA (1 << 4)
+#define LOONGSON_INT_BIT_PCI_INTB (1 << 5)
+#define LOONGSON_INT_BIT_PCI_INTC (1 << 6)
+#define LOONGSON_INT_BIT_PCI_INTD (1 << 7)
+#define LOONGSON_INT_BIT_PCI_PERR (1 << 8)
+#define LOONGSON_INT_BIT_PCI_SERR (1 << 9)
+#define LOONGSON_INT_BIT_DDR (1 << 10)
+#define LOONGSON_INT_BIT_INT0 (1 << 11)
+#define LOONGSON_INT_BIT_INT1 (1 << 12)
+#define LOONGSON_INT_BIT_INT2 (1 << 13)
+#define LOONGSON_INT_BIT_INT3 (1 << 14)
+
+#endif
#endif /* ! __MACHINE_H */
diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
index 5874bf6..2bfda6e 100644
--- a/arch/mips/loongson/Kconfig
+++ b/arch/mips/loongson/Kconfig
@@ -28,4 +28,48 @@ config LEMOTE_FULOONG2E
Lemote Fulong mini-PC board based on the Chinese Loongson-2E CPU and
an FPGA northbridge
+config LEMOTE_FULOONG2F
+ bool "Lemote Fuloong(2f) mini-PC"
+ select ARCH_SPARSEMEM_ENABLE
+ select CEVT_R4K
+ select CSRC_R4K
+ select SYS_HAS_CPU_LOONGSON2F
+ select DMA_NONCOHERENT
+ select BOOT_ELF32
+ select BOARD_SCACHE
+ select HW_HAS_PCI
+ select I8259
+ select ISA
+ select IRQ_CPU
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+ select SYS_SUPPORTS_HIGHMEM
+ select SYS_HAS_EARLY_PRINTK
+ select GENERIC_HARDIRQS_NO__DO_IRQ
+ select GENERIC_ISA_DMA_SUPPORT_BROKEN
+ select CPU_HAS_WB
+ select CS5536
+ help
+ Lemote Fulong mini-PC board based on the Chinese Loongson-2F CPU
+
endchoice
+
+config CS5536
+ bool
+
+config CS5536_FLASH
+ bool
+ depends on CS5536
+
+config CS5536_NOR_FLASH
+ bool
+ depends on CS5536_FLASH
+
+config CS5536_OTG
+ bool
+ depends on CS5536
+
+config CS5536_UDC
+ bool
+ depends on CS5536
diff --git a/arch/mips/loongson/Makefile b/arch/mips/loongson/Makefile
index cc9f1c8..e9b8a81 100644
--- a/arch/mips/loongson/Makefile
+++ b/arch/mips/loongson/Makefile
@@ -9,3 +9,9 @@ obj-$(CONFIG_LOONGSON_SYSTEMS) += common/
#
obj-$(CONFIG_LEMOTE_FULOONG2E) += fuloong-2e/
+
+#
+# Lemote Fuloong mini-PC (Loongson 2F-based)
+#
+
+obj-$(CONFIG_LEMOTE_FULOONG2F) += fuloong-2f/
diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile
index 79b2736..71a4ea7 100644
--- a/arch/mips/loongson/common/Makefile
+++ b/arch/mips/loongson/common/Makefile
@@ -17,4 +17,10 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
#
obj-$(CONFIG_RTC_DRV_CMOS) += rtc.o
+#
+# Enable CS5536 Virtual Support Module(VSM) for virtulize the PCI configure
+# space
+#
+obj-$(CONFIG_CS5536) += cs5536/
+
EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/loongson/common/bonito-irq.c b/arch/mips/loongson/common/bonito-irq.c
index 1f43447..940c1f0 100644
--- a/arch/mips/loongson/common/bonito-irq.c
+++ b/arch/mips/loongson/common/bonito-irq.c
@@ -53,10 +53,13 @@ static struct irq_chip bonito_irq_type = {
.unmask = bonito_irq_enable,
};
+/* there is no need to handle dma timeout in loongson-2f based machines */
+#ifdef CONFIG_CPU_LOONGSON2E
static struct irqaction dma_timeout_irqaction = {
.handler = no_action,
.name = "dma_timeout",
};
+#endif
void bonito_irq_init(void)
{
@@ -65,5 +68,7 @@ void bonito_irq_init(void)
for (i = LOONGSON_IRQ_BASE; i < LOONGSON_IRQ_BASE + 32; i++)
set_irq_chip_and_handler(i, &bonito_irq_type, handle_level_irq);
+#ifdef CONFIG_CPU_LOONGSON2E
setup_irq(LOONGSON_DMATIMEOUT_IRQ, &dma_timeout_irqaction);
+#endif
}
diff --git a/arch/mips/loongson/common/cs5536/Makefile b/arch/mips/loongson/common/cs5536/Makefile
new file mode 100644
index 0000000..09bc177
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/Makefile
@@ -0,0 +1,20 @@
+#
+# Makefile for CS5536 support.
+#
+
+#
+# core modules
+#
+obj-$(CONFIG_CS5536) += cs5536_pci.o cs5536_ide.o cs5536_acc.o cs5536_ohci.o \
+ cs5536_isa.o cs5536_ehci.o
+#
+# selective modules
+#
+# add a CS5536_[MODULE] to your board in arch/mips/loongson/Kconfig
+#
+obj-$(CONFIG_CS5536_FLASH) += cs5536_flash.o
+obj-$(CONFIG_CS5536_NOR_FLASH) += cs5536_flash.o
+obj-$(CONFIG_CS5536_OTG) += cs5536_otg.o
+obj-$(CONFIG_CS5536_UDC) += cs5536_udc.o
+
+EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/loongson/common/cs5536/cs5536_acc.c b/arch/mips/loongson/common/cs5536/cs5536_acc.c
new file mode 100644
index 0000000..487f4a6
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_acc.c
@@ -0,0 +1,155 @@
+/*
+ * the ACC Virtual Support Module of AMD CS5536
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author : jlliu, liujl@lemote.com
+ *
+ * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * 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 <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+/*
+ * acc_write: acc write transfering
+ */
+
+void pci_acc_write_reg(int reg, u32 value)
+{
+ u32 hi = 0, lo = value;
+
+ switch (reg) {
+ case PCI_COMMAND:
+ _rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo);
+ if (value & PCI_COMMAND_MASTER)
+ lo |= (0x03 << 8);
+ else
+ lo &= ~(0x03 << 8);
+ _wrmsr(GLIU_MSR_REG(GLIU_PAE), hi, lo);
+ break;
+ case PCI_STATUS:
+ if (value & PCI_STATUS_PARITY) {
+ _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+ if (lo & SB_PARE_ERR_FLAG) {
+ lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG;
+ _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+ }
+ }
+ break;
+ case PCI_BAR0_REG:
+ if (value == PCI_BAR_RANGE_MASK) {
+ _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+ lo |= SOFT_BAR_ACC_FLAG;
+ _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+ } else if (value & 0x01) {
+ value &= 0xfffffffc;
+ hi = 0xA0000000 | ((value & 0x000ff000) >> 12);
+ lo = 0x000fff80 | ((value & 0x00000fff) << 20);
+ _wrmsr(GLIU_MSR_REG(GLIU_IOD_BM1), hi, lo);
+ }
+ break;
+ case PCI_ACC_INT_REG:
+ _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo);
+ /* disable all the usb interrupt in PIC */
+ lo &= ~(0xf << PIC_YSEL_LOW_ACC_SHIFT);
+ if (value) /* enable all the acc interrupt in PIC */
+ lo |= (CS5536_ACC_INTR << PIC_YSEL_LOW_ACC_SHIFT);
+ _wrmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), hi, lo);
+ break;
+ default:
+ break;
+ }
+
+ return;
+}
+
+/*
+ * acc_read: acc read transfering
+ */
+
+u32 pci_acc_read_reg(int reg)
+{
+ u32 hi, lo;
+ u32 conf_data = 0;
+
+ switch (reg) {
+ case PCI_VENDOR_ID:
+ conf_data =
+ CFG_PCI_VENDOR_ID(CS5536_ACC_DEVICE_ID, CS5536_VENDOR_ID);
+ break;
+ case PCI_COMMAND:
+ _rdmsr(GLIU_MSR_REG(GLIU_IOD_BM1), &hi, &lo);
+ if (((lo & 0xfff00000) || (hi & 0x000000ff))
+ && ((hi & 0xf0000000) == 0xa0000000))
+ conf_data |= PCI_COMMAND_IO;
+ _rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo);
+ if ((lo & 0x300) == 0x300)
+ conf_data |= PCI_COMMAND_MASTER;
+ break;
+ case PCI_STATUS:
+ conf_data |= PCI_STATUS_66MHZ;
+ conf_data |= PCI_STATUS_FAST_BACK;
+ _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+ if (lo & SB_PARE_ERR_FLAG)
+ conf_data |= PCI_STATUS_PARITY;
+ conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
+ break;
+ case PCI_CLASS_REVISION:
+ _rdmsr(ACC_MSR_REG(ACC_CAP), &hi, &lo);
+ conf_data = lo & 0x000000ff;
+ conf_data |= (CS5536_ACC_CLASS_CODE << 8);
+ break;
+ case PCI_CACHE_LINE_SIZE:
+ conf_data =
+ CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE,
+ PCI_NORMAL_LATENCY_TIMER);
+ break;
+ case PCI_BAR0_REG:
+ _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+ if (lo & SOFT_BAR_ACC_FLAG) {
+ conf_data = CS5536_ACC_RANGE |
+ PCI_BASE_ADDRESS_SPACE_IO;
+ lo &= ~SOFT_BAR_ACC_FLAG;
+ _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+ } else {
+ _rdmsr(GLIU_MSR_REG(GLIU_IOD_BM1), &hi, &lo);
+ conf_data = (hi & 0x000000ff) << 12;
+ conf_data |= (lo & 0xfff00000) >> 20;
+ conf_data |= 0x01;
+ conf_data &= ~0x02;
+ }
+ break;
+ case PCI_BAR1_REG:
+ case PCI_BAR2_REG:
+ case PCI_BAR3_REG:
+ case PCI_BAR4_REG:
+ case PCI_BAR5_REG:
+ break;
+ case PCI_CARDBUS_CIS:
+ conf_data = PCI_CARDBUS_CIS_POINTER;
+ break;
+ case PCI_SUBSYSTEM_VENDOR_ID:
+ conf_data =
+ CFG_PCI_VENDOR_ID(CS5536_ACC_SUB_ID, CS5536_SUB_VENDOR_ID);
+ break;
+ case PCI_ROM_ADDRESS:
+ conf_data = PCI_EXPANSION_ROM_BAR;
+ break;
+ case PCI_CAPABILITY_LIST:
+ conf_data = PCI_CAPLIST_USB_POINTER;
+ break;
+ case PCI_INTERRUPT_LINE:
+ conf_data = CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_ACC_INTR);
+ break;
+ default:
+ break;
+ }
+
+ return conf_data;
+}
diff --git a/arch/mips/loongson/common/cs5536/cs5536_ehci.c b/arch/mips/loongson/common/cs5536/cs5536_ehci.c
new file mode 100644
index 0000000..9c262fd
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_ehci.c
@@ -0,0 +1,165 @@
+/*
+ * the EHCI Virtual Support Module of AMD CS5536
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author : jlliu, liujl@lemote.com
+ *
+ * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * 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 <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+void pci_ehci_write_reg(int reg, u32 value)
+{
+ u32 hi = 0, lo = value;
+
+ switch (reg) {
+ case PCI_COMMAND:
+ _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+ if (value & PCI_COMMAND_MASTER)
+ hi |= PCI_COMMAND_MASTER;
+ else
+ hi &= ~PCI_COMMAND_MASTER;
+
+ if (value & PCI_COMMAND_MEMORY)
+ hi |= PCI_COMMAND_MEMORY;
+ else
+ hi &= ~PCI_COMMAND_MEMORY;
+ _wrmsr(USB_MSR_REG(USB_EHCI), hi, lo);
+ break;
+ case PCI_STATUS:
+ if (value & PCI_STATUS_PARITY) {
+ _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+ if (lo & SB_PARE_ERR_FLAG) {
+ lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG;
+ _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+ }
+ }
+ break;
+ case PCI_BAR0_REG:
+ if (value == PCI_BAR_RANGE_MASK) {
+ _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+ lo |= SOFT_BAR_EHCI_FLAG;
+ _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+ } else if ((value & 0x01) == 0x00) {
+ _wrmsr(USB_MSR_REG(USB_EHCI), hi, lo);
+
+ value &= 0xfffffff0;
+ hi = 0x40000000 | ((value & 0xff000000) >> 24);
+ lo = 0x000fffff | ((value & 0x00fff000) << 8);
+ _wrmsr(GLIU_MSR_REG(GLIU_P2D_BM4), hi, lo);
+ }
+ break;
+ case PCI_EHCI_LEGSMIEN_REG:
+ _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+ hi &= 0x003f0000;
+ hi |= (value & 0x3f) << 16;
+ _wrmsr(USB_MSR_REG(USB_EHCI), hi, lo);
+ break;
+ case PCI_EHCI_FLADJ_REG:
+ _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+ hi &= ~0x00003f00;
+ hi |= value & 0x00003f00;
+ _wrmsr(USB_MSR_REG(USB_EHCI), hi, lo);
+ break;
+ default:
+ break;
+ }
+
+ return;
+}
+
+u32 pci_ehci_read_reg(int reg)
+{
+ u32 conf_data = 0;
+ u32 hi, lo;
+
+ switch (reg) {
+ case PCI_VENDOR_ID:
+ conf_data =
+ CFG_PCI_VENDOR_ID(CS5536_EHCI_DEVICE_ID, CS5536_VENDOR_ID);
+ break;
+ case PCI_COMMAND:
+ _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+ if (hi & PCI_COMMAND_MASTER)
+ conf_data |= PCI_COMMAND_MASTER;
+ if (hi & PCI_COMMAND_MEMORY)
+ conf_data |= PCI_COMMAND_MEMORY;
+ break;
+ case PCI_STATUS:
+ conf_data |= PCI_STATUS_66MHZ;
+ conf_data |= PCI_STATUS_FAST_BACK;
+ _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+ if (lo & SB_PARE_ERR_FLAG)
+ conf_data |= PCI_STATUS_PARITY;
+ conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
+ break;
+ case PCI_CLASS_REVISION:
+ _rdmsr(USB_MSR_REG(USB_CAP), &hi, &lo);
+ conf_data = lo & 0x000000ff;
+ conf_data |= (CS5536_EHCI_CLASS_CODE << 8);
+ break;
+ case PCI_CACHE_LINE_SIZE:
+ conf_data =
+ CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE,
+ PCI_NORMAL_LATENCY_TIMER);
+ break;
+ case PCI_BAR0_REG:
+ _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+ if (lo & SOFT_BAR_EHCI_FLAG) {
+ conf_data = CS5536_EHCI_RANGE |
+ PCI_BASE_ADDRESS_SPACE_MEMORY;
+ lo &= ~SOFT_BAR_EHCI_FLAG;
+ _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+ } else {
+ _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+ conf_data = lo & 0xfffff000;
+ }
+ break;
+ case PCI_BAR1_REG:
+ case PCI_BAR2_REG:
+ case PCI_BAR3_REG:
+ case PCI_BAR4_REG:
+ case PCI_BAR5_REG:
+ break;
+ case PCI_CARDBUS_CIS:
+ conf_data = PCI_CARDBUS_CIS_POINTER;
+ break;
+ case PCI_SUBSYSTEM_VENDOR_ID:
+ conf_data =
+ CFG_PCI_VENDOR_ID(CS5536_EHCI_SUB_ID, CS5536_SUB_VENDOR_ID);
+ break;
+ case PCI_ROM_ADDRESS:
+ conf_data = PCI_EXPANSION_ROM_BAR;
+ break;
+ case PCI_CAPABILITY_LIST:
+ conf_data = PCI_CAPLIST_USB_POINTER;
+ break;
+ case PCI_INTERRUPT_LINE:
+ conf_data = CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_USB_INTR);
+ break;
+ case PCI_EHCI_LEGSMIEN_REG:
+ _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+ conf_data = (hi & 0x003f0000) >> 16;
+ break;
+ case PCI_EHCI_LEGSMISTS_REG:
+ _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+ conf_data = (hi & 0x3f000000) >> 24;
+ break;
+ case PCI_EHCI_FLADJ_REG:
+ _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+ conf_data = hi & 0x00003f00;
+ break;
+ default:
+ break;
+ }
+
+ return conf_data;
+}
diff --git a/arch/mips/loongson/common/cs5536/cs5536_flash.c b/arch/mips/loongson/common/cs5536/cs5536_flash.c
new file mode 100644
index 0000000..88226c8
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_flash.c
@@ -0,0 +1,450 @@
+/*
+ * the FLASH Virtual Support Module of AMD CS5536
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author : jlliu, liujl@lemote.com
+ *
+ * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * 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 <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+/*
+ * enable the region of flashs(NOR or NAND)
+ *
+ * the same as the DIVIL other modules above, two groups of regs should be
+ * modified here to control the region. DIVIL flash LBAR and the
+ * RCONFx(6~9 reserved).
+ */
+static void flash_lbar_enable(void)
+{
+ u32 hi, lo;
+ int offset;
+
+ for (offset = DIVIL_LBAR_FLSH0; offset <= DIVIL_LBAR_FLSH3; offset++) {
+ _rdmsr(DIVIL_MSR_REG(offset), &hi, &lo);
+ hi |= 0x1;
+ _wrmsr(DIVIL_MSR_REG(offset), hi, lo);
+ }
+
+ for (offset = SB_R6; offset <= SB_R9; offset++) {
+ _rdmsr(SB_MSR_REG(offset), &hi, &lo);
+ lo |= 0x1;
+ _wrmsr(SB_MSR_REG(offset), hi, lo);
+ }
+
+ return;
+}
+
+/*
+ * disable the region of flashs(NOR or NAND)
+ */
+static void flash_lbar_disable(void)
+{
+ u32 hi, lo;
+ int offset;
+
+ for (offset = DIVIL_LBAR_FLSH0; offset <= DIVIL_LBAR_FLSH3; offset++) {
+ _rdmsr(DIVIL_MSR_REG(offset), &hi, &lo);
+ hi &= ~0x01;
+ _wrmsr(DIVIL_MSR_REG(offset), hi, lo);
+ }
+ for (offset = SB_R6; offset <= SB_R9; offset++) {
+ _rdmsr(SB_MSR_REG(offset), &hi, &lo);
+ lo &= ~0x01;
+ _wrmsr(SB_MSR_REG(offset), hi, lo);
+ }
+
+ return;
+}
+
+#ifndef CONFIG_CS5536_NOR_FLASH /* for nand flash */
+
+void pci_flash_write_bar(int n, u32 value)
+{
+ u32 hi = 0, lo = value;
+
+ if (value == PCI_BAR_RANGE_MASK) {
+ /* make the flag for reading the bar length. */
+ _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+ lo |= (SOFT_BAR_FLSH0_FLAG << n);
+ _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+ } else if ((value & 0x01) == 0x00) {
+ /* mem space nand flash native reg base addr */
+ hi = 0xfffff007;
+ lo &= CS5536_FLSH_RANGE;
+ _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH0 + n), hi, lo);
+
+ /* RCONFx is 4KB in units for mem space. */
+ hi = ((value & 0xfffff000) << 12) |
+ ((CS5536_FLSH_LENGTH & 0xfffff000) - (1 << 12)) | 0x00;
+ lo = ((value & 0xfffff000) << 12) | 0x01;
+ _wrmsr(SB_MSR_REG(SB_R6 + n), hi, lo);
+ }
+ return;
+}
+
+void pci_flash_write_reg(int reg, u32 value)
+{
+ u32 hi = 0, lo = value;
+
+ switch (reg) {
+ case PCI_COMMAND:
+ if (value & PCI_COMMAND_MEMORY)
+ flash_lbar_enable();
+ else
+ flash_lbar_disable();
+ break;
+ case PCI_STATUS:
+ if (value & PCI_STATUS_PARITY) {
+ _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+ if (lo & SB_PARE_ERR_FLAG) {
+ lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG;
+ _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+ }
+ }
+ break;
+ case PCI_BAR0_REG:
+ pci_flash_write_bar(0, value);
+ break;
+ case PCI_BAR1_REG:
+ pci_flash_write_bar(1, value);
+ break;
+ case PCI_BAR2_REG:
+ pci_flash_write_bar(2, value);
+ break;
+ case PCI_BAR3_REG:
+ pci_flash_write_bar(3, value);
+ break;
+ case PCI_FLASH_INT_REG:
+ _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo);
+ /* disable all the flash interrupt in PIC */
+ lo &= ~(0xf << PIC_YSEL_LOW_FLASH_SHIFT);
+ if (value) /* enable all the flash interrupt in PIC */
+ lo |= (CS5536_FLASH_INTR << PIC_YSEL_LOW_FLASH_SHIFT);
+ _wrmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), hi, lo);
+ break;
+ case PCI_NAND_FLASH_TDATA_REG:
+ _wrmsr(DIVIL_MSR_REG(NANDF_DATA), hi, lo);
+ break;
+ case PCI_NAND_FLASH_TCTRL_REG:
+ lo &= 0x00000fff;
+ _wrmsr(DIVIL_MSR_REG(NANDF_CTRL), hi, lo);
+ break;
+ case PCI_NAND_FLASH_RSVD_REG:
+ _wrmsr(DIVIL_MSR_REG(NANDF_RSVD), hi, lo);
+ break;
+ case PCI_FLASH_SELECT_REG:
+ if (value == CS5536_IDE_FLASH_SIGNATURE) {
+ _rdmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), &hi, &lo);
+ lo &= ~0x01;
+ _wrmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), hi, lo);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return;
+}
+
+u32 pci_flash_read_bar(int n)
+{
+ u32 hi, lo;
+ u32 conf_data = 0;
+
+ _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+ if (lo & (SOFT_BAR_FLSH0_FLAG << n)) {
+ conf_data = CS5536_FLSH_RANGE | PCI_BASE_ADDRESS_SPACE_MEMORY;
+ lo &= ~(SOFT_BAR_FLSH0_FLAG << n);
+ _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+ } else {
+ _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH0 + n), &hi, &lo);
+ conf_data = lo;
+ conf_data &= ~0x0f;
+ }
+
+ return conf_data;
+}
+
+u32 pci_flash_read_reg(int reg)
+{
+ u32 conf_data = 0;
+ u32 hi, lo;
+
+ switch (reg) {
+ case PCI_VENDOR_ID:
+ conf_data =
+ CFG_PCI_VENDOR_ID(CS5536_FLASH_DEVICE_ID, CS5536_VENDOR_ID);
+ break;
+ case PCI_COMMAND:
+ /* we just read one lbar for returning. */
+ _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH0), &hi, &lo);
+ if (hi & 0x1)
+ conf_data |= PCI_COMMAND_MEMORY;
+ break;
+ case PCI_STATUS:
+ conf_data |= PCI_STATUS_66MHZ;
+ conf_data |= PCI_STATUS_FAST_BACK;
+ _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+ if (lo & SB_PARE_ERR_FLAG)
+ conf_data |= PCI_STATUS_PARITY;
+ conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
+ break;
+ case PCI_CLASS_REVISION:
+ _rdmsr(DIVIL_MSR_REG(DIVIL_CAP), &hi, &lo);
+ conf_data = lo & 0x000000ff;
+ conf_data |= (CS5536_FLASH_CLASS_CODE << 8);
+ break;
+ case PCI_CACHE_LINE_SIZE:
+ conf_data =
+ CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE,
+ PCI_NORMAL_LATENCY_TIMER);
+ break;
+ case PCI_BAR0_REG:
+ return pci_flash_read_bar(0);
+ break;
+ case PCI_BAR1_REG:
+ return pci_flash_read_bar(1);
+ break;
+ case PCI_BAR2_REG:
+ return pci_flash_read_bar(2);
+ break;
+ case PCI_BAR3_REG:
+ return pci_flash_read_bar(3);
+ break;
+ case PCI_CARDBUS_CIS:
+ conf_data = PCI_CARDBUS_CIS_POINTER;
+ break;
+ case PCI_SUBSYSTEM_VENDOR_ID:
+ conf_data =
+ CFG_PCI_VENDOR_ID(CS5536_FLASH_SUB_ID,
+ CS5536_SUB_VENDOR_ID);
+ break;
+ case PCI_ROM_ADDRESS:
+ conf_data = PCI_EXPANSION_ROM_BAR;
+ break;
+ case PCI_CAPABILITY_LIST:
+ conf_data = PCI_CAPLIST_POINTER;
+ break;
+ case PCI_INTERRUPT_LINE:
+ conf_data = CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_FLASH_INTR);
+ break;
+ case PCI_NAND_FLASH_TDATA_REG:
+ _rdmsr(DIVIL_MSR_REG(NANDF_DATA), &hi, &lo);
+ conf_data = lo;
+ break;
+ case PCI_NAND_FLASH_TCTRL_REG:
+ _rdmsr(DIVIL_MSR_REG(NANDF_CTRL), &hi, &lo);
+ conf_data = lo & 0x00000fff;
+ break;
+ case PCI_NAND_FLASH_RSVD_REG:
+ _rdmsr(DIVIL_MSR_REG(NANDF_RSVD), &hi, &lo);
+ conf_data = lo;
+ break;
+ case PCI_FLASH_SELECT_REG:
+ _rdmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), &hi, &lo);
+ conf_data = lo & 0x01;
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+#else /* CONFIG_CS5536_NOR_FLASH */
+
+void pci_flash_write_bar(int n, u32 value)
+{
+ u32 hi = 0, lo = value;
+
+ if (value == PCI_BAR_RANGE_MASK) {
+ _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+ lo |= (SOFT_BAR_FLSH0_FLAG << n);
+ _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+ } else if (value & 0x01) {
+ /* IO space of 16bytes nor flash */
+ hi = 0x0000fff1;
+ lo &= CS5536_FLSH_RANGE;
+ _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH0 + n), hi, lo);
+
+ /* RCONFx used for 16bytes reserved. */
+ hi = ((value & 0x000ffffc) << 12) | ((CS5536_FLSH_LENGTH - 4)
+ << 12) | 0x01;
+ lo = ((value & 0x000ffffc) << 12) | 0x01;
+ _wrmsr(SB_MSR_REG(SB_R6 + n), hi, lo);
+ }
+ return;
+}
+
+void pci_flash_write_reg(int reg, u32 value)
+{
+ u32 hi = 0, lo = value;
+
+ switch (reg) {
+ case PCI_COMMAND:
+ if (value & PCI_COMMAND_IO)
+ flash_lbar_enable();
+ else
+ flash_lbar_disable();
+ break;
+ case PCI_STATUS:
+ if (value & PCI_STATUS_PARITY) {
+ _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+ if (lo & SB_PARE_ERR_FLAG) {
+ lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG;
+ _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+ }
+ }
+ break;
+ case PCI_BAR0_REG:
+ pci_flash_write_bar(0, value);
+ break;
+ case PCI_BAR1_REG:
+ pci_flash_write_bar(1, value);
+ break;
+ case PCI_BAR2_REG:
+ pci_flash_write_bar(2, value);
+ break;
+ case PCI_BAR3_REG:
+ pci_flash_write_bar(3, value);
+ break;
+ case PCI_FLASH_INT_REG:
+ _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo);
+ /* disable all the flash interrupt in PIC */
+ lo &= ~(0xf << PIC_YSEL_LOW_FLASH_SHIFT);
+ if (value) /* enable all the flash interrupt in PIC */
+ lo |= (CS5536_FLASH_INTR << PIC_YSEL_LOW_FLASH_SHIFT);
+ _wrmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), hi, lo);
+ break;
+ case PCI_NOR_FLASH_CTRL_REG:
+ lo &= 0x000000ff;
+ _wrmsr(DIVIL_MSR_REG(NORF_CTRL), hi, lo);
+ break;
+ case PCI_NOR_FLASH_T01_REG:
+ _wrmsr(DIVIL_MSR_REG(NORF_T01), hi, lo);
+ break;
+ case PCI_NOR_FLASH_T23_REG:
+ _wrmsr(DIVIL_MSR_REG(NORF_T23), hi, lo);
+ break;
+ case PCI_FLASH_SELECT_REG:
+ if (value == CS5536_IDE_FLASH_SIGNATURE) {
+ _rdmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), &hi, &lo);
+ lo &= ~0x01;
+ _wrmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), hi, lo);
+ }
+ break;
+ default:
+ break;
+ }
+ return;
+}
+
+u32 pci_flash_read_bar(int n)
+{
+ u32 hi, lo;
+ u32 conf_data = 0;
+
+ _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+ if (lo & (SOFT_BAR_FLSH0_FLAG << n)) {
+ conf_data = CS5536_FLSH_RANGE | PCI_BASE_ADDRESS_SPACE_IO;
+ lo &= ~(SOFT_BAR_FLSH0_FLAG << n);
+ _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+ } else {
+ _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH0 + n), &hi, &lo);
+ conf_data = lo & 0x0000ffff;
+ conf_data |= 0x01;
+ conf_data &= ~0x02;
+ }
+
+ return conf_data;
+}
+
+u32 pci_flash_read_reg(int reg)
+{
+ u32 conf_data = 0;
+ u32 hi, lo;
+
+ switch (reg) {
+ case PCI_VENDOR_ID:
+ conf_data =
+ CFG_PCI_VENDOR_ID(CS5536_FLASH_DEVICE_ID, CS5536_VENDOR_ID);
+ break;
+ case PCI_COMMAND:
+ /* we just check one flash bar for returning. */
+ _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_FLSH0), &hi, &lo);
+ if (hi & PCI_COMMAND_IO)
+ conf_data |= PCI_COMMAND_IO;
+ break;
+ case PCI_STATUS:
+ conf_data |= PCI_STATUS_66MHZ;
+ conf_data |= PCI_STATUS_FAST_BACK;
+ _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+ if (lo & SB_PARE_ERR_FLAG)
+ conf_data |= PCI_STATUS_PARITY;
+ conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
+ break;
+ case PCI_CLASS_REVISION:
+ _rdmsr(DIVIL_MSR_REG(DIVIL_CAP), &hi, &lo);
+ conf_data = lo & 0x000000ff;
+ conf_data |= (CS5536_FLASH_CLASS_CODE << 8);
+ break;
+ case PCI_CACHE_LINE_SIZE:
+ conf_data =
+ CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE,
+ PCI_NORMAL_LATENCY_TIMER);
+ break;
+ case PCI_BAR0_REG:
+ return pci_flash_read_bar(0);
+ break;
+ case PCI_BAR1_REG:
+ return pci_flash_read_bar(1);
+ break;
+ case PCI_BAR2_REG:
+ return pci_flash_read_bar(2);
+ break;
+ case PCI_BAR3_REG:
+ return pci_flash_read_bar(3);
+ break;
+ case PCI_CARDBUS_CIS:
+ conf_data = PCI_CARDBUS_CIS_POINTER;
+ break;
+ case PCI_SUBSYSTEM_VENDOR_ID:
+ conf_data =
+ CFG_PCI_VENDOR_ID(CS5536_FLASH_SUB_ID,
+ CS5536_SUB_VENDOR_ID);
+ break;
+ case PCI_ROM_ADDRESS:
+ conf_data = PCI_EXPANSION_ROM_BAR;
+ break;
+ case PCI_CAPABILITY_LIST:
+ conf_data = PCI_CAPLIST_POINTER;
+ break;
+ case PCI_INTERRUPT_LINE:
+ conf_data = CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_FLASH_INTR);
+ break;
+ case PCI_NOR_FLASH_CTRL_REG:
+ _rdmsr(DIVIL_MSR_REG(NORF_CTRL), &hi, &lo);
+ conf_data = lo & 0x000000ff;
+ break;
+ case PCI_NOR_FLASH_T01_REG:
+ _rdmsr(DIVIL_MSR_REG(NORF_T01), &hi, &lo);
+ conf_data = lo;
+ break;
+ case PCI_NOR_FLASH_T23_REG:
+ _rdmsr(DIVIL_MSR_REG(NORF_T23), &hi, &lo);
+ conf_data = lo;
+ break;
+ default:
+ break;
+ }
+ return conf_data;
+}
+#endif /* CONFIG_CS5536_NOR_FLASH */
diff --git a/arch/mips/loongson/common/cs5536/cs5536_ide.c b/arch/mips/loongson/common/cs5536/cs5536_ide.c
new file mode 100644
index 0000000..fa605cd
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_ide.c
@@ -0,0 +1,193 @@
+/*
+ * the IDE Virtual Support Module of AMD CS5536
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author : jlliu, liujl@lemote.com
+ *
+ * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * 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 <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+/*
+ * ide_write : ide write transfering
+ */
+void pci_ide_write_reg(int reg, u32 value)
+{
+ u32 hi = 0, lo = value;
+
+ switch (reg) {
+ case PCI_COMMAND:
+ _rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo);
+ if (value & PCI_COMMAND_MASTER)
+ lo |= (0x03 << 4);
+ else
+ lo &= ~(0x03 << 4);
+ _wrmsr(GLIU_MSR_REG(GLIU_PAE), hi, lo);
+ break;
+ case PCI_STATUS:
+ if (value & PCI_STATUS_PARITY) {
+ _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+ if (lo & SB_PARE_ERR_FLAG) {
+ lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG;
+ _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+ }
+ }
+ break;
+ case PCI_CACHE_LINE_SIZE:
+ value &= 0x0000ff00;
+ _rdmsr(SB_MSR_REG(SB_CTRL), &hi, &lo);
+ hi &= 0xffffff00;
+ hi |= (value >> 8);
+ _wrmsr(SB_MSR_REG(SB_CTRL), hi, lo);
+ break;
+ case PCI_BAR4_REG:
+ if (value == PCI_BAR_RANGE_MASK) {
+ _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+ lo |= SOFT_BAR_IDE_FLAG;
+ _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+ } else if (value & 0x01) {
+ lo = (value & 0xfffffff0) | 0x1;
+ _wrmsr(IDE_MSR_REG(IDE_IO_BAR), hi, lo);
+
+ value &= 0xfffffffc;
+ hi = 0x60000000 | ((value & 0x000ff000) >> 12);
+ lo = 0x000ffff0 | ((value & 0x00000fff) << 20);
+ _wrmsr(GLIU_MSR_REG(GLIU_IOD_BM2), hi, lo);
+ }
+ break;
+ case PCI_IDE_CFG_REG:
+ if (value == CS5536_IDE_FLASH_SIGNATURE) {
+ _rdmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), &hi, &lo);
+ lo |= 0x01;
+ _wrmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), hi, lo);
+ } else
+ _wrmsr(IDE_MSR_REG(IDE_CFG), hi, lo);
+ break;
+ case PCI_IDE_DTC_REG:
+ _wrmsr(IDE_MSR_REG(IDE_DTC), hi, lo);
+ break;
+ case PCI_IDE_CAST_REG:
+ _wrmsr(IDE_MSR_REG(IDE_CAST), hi, lo);
+ break;
+ case PCI_IDE_ETC_REG:
+ _wrmsr(IDE_MSR_REG(IDE_ETC), hi, lo);
+ break;
+ case PCI_IDE_PM_REG:
+ _wrmsr(IDE_MSR_REG(IDE_INTERNAL_PM), hi, lo);
+ break;
+ default:
+ break;
+ }
+
+ return;
+}
+
+/*
+ * ide_read : ide read tranfering.
+ */
+u32 pci_ide_read_reg(int reg)
+{
+ u32 conf_data = 0;
+ u32 hi, lo;
+
+ switch (reg) {
+ case PCI_VENDOR_ID:
+ conf_data =
+ CFG_PCI_VENDOR_ID(CS5536_IDE_DEVICE_ID, CS5536_VENDOR_ID);
+ break;
+ case PCI_COMMAND:
+ _rdmsr(IDE_MSR_REG(IDE_IO_BAR), &hi, &lo);
+ if (lo & 0xfffffff0)
+ conf_data |= PCI_COMMAND_IO;
+ _rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo);
+ if ((lo & 0x30) == 0x30)
+ conf_data |= PCI_COMMAND_MASTER;
+ break;
+ case PCI_STATUS:
+ conf_data |= PCI_STATUS_66MHZ;
+ conf_data |= PCI_STATUS_FAST_BACK;
+ _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+ if (lo & SB_PARE_ERR_FLAG)
+ conf_data |= PCI_STATUS_PARITY;
+ conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
+ break;
+ case PCI_CLASS_REVISION:
+ _rdmsr(IDE_MSR_REG(IDE_CAP), &hi, &lo);
+ conf_data = lo & 0x000000ff;
+ conf_data |= (CS5536_IDE_CLASS_CODE << 8);
+ break;
+ case PCI_CACHE_LINE_SIZE:
+ _rdmsr(SB_MSR_REG(SB_CTRL), &hi, &lo);
+ hi &= 0x000000f8;
+ conf_data = CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE, hi);
+ break;
+ case PCI_BAR0_REG:
+ case PCI_BAR1_REG:
+ case PCI_BAR2_REG:
+ case PCI_BAR3_REG:
+ break;
+ case PCI_BAR4_REG:
+ _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+ if (lo & SOFT_BAR_IDE_FLAG) {
+ conf_data = CS5536_IDE_RANGE |
+ PCI_BASE_ADDRESS_SPACE_IO;
+ lo &= ~SOFT_BAR_IDE_FLAG;
+ _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+ } else {
+ _rdmsr(IDE_MSR_REG(IDE_IO_BAR), &hi, &lo);
+ conf_data = lo & 0xfffffff0;
+ conf_data |= 0x01;
+ conf_data &= ~0x02;
+ }
+ break;
+ case PCI_BAR5_REG:
+ break;
+ case PCI_CARDBUS_CIS:
+ conf_data = PCI_CARDBUS_CIS_POINTER;
+ break;
+ case PCI_SUBSYSTEM_VENDOR_ID:
+ conf_data =
+ CFG_PCI_VENDOR_ID(CS5536_IDE_SUB_ID, CS5536_SUB_VENDOR_ID);
+ break;
+ case PCI_ROM_ADDRESS:
+ conf_data = PCI_EXPANSION_ROM_BAR;
+ break;
+ case PCI_CAPABILITY_LIST:
+ conf_data = PCI_CAPLIST_POINTER;
+ break;
+ case PCI_INTERRUPT_LINE:
+ conf_data = CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_IDE_INTR);
+ break;
+ case PCI_IDE_CFG_REG:
+ _rdmsr(IDE_MSR_REG(IDE_CFG), &hi, &lo);
+ conf_data = lo;
+ break;
+ case PCI_IDE_DTC_REG:
+ _rdmsr(IDE_MSR_REG(IDE_DTC), &hi, &lo);
+ conf_data = lo;
+ break;
+ case PCI_IDE_CAST_REG:
+ _rdmsr(IDE_MSR_REG(IDE_CAST), &hi, &lo);
+ conf_data = lo;
+ break;
+ case PCI_IDE_ETC_REG:
+ _rdmsr(IDE_MSR_REG(IDE_ETC), &hi, &lo);
+ conf_data = lo;
+ case PCI_IDE_PM_REG:
+ _rdmsr(IDE_MSR_REG(IDE_INTERNAL_PM), &hi, &lo);
+ conf_data = lo;
+ break;
+ default:
+ break;
+ }
+
+ return conf_data;
+}
diff --git a/arch/mips/loongson/common/cs5536/cs5536_isa.c b/arch/mips/loongson/common/cs5536/cs5536_isa.c
new file mode 100644
index 0000000..507cd4f
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_isa.c
@@ -0,0 +1,376 @@
+/*
+ * the ISA Virtual Support Module of AMD CS5536
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author : jlliu, liujl@lemote.com
+ *
+ * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * 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 <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+/* common variables for PCI_ISA_READ/WRITE_BAR */
+static const u32 divil_msr_reg[6] = {
+ DIVIL_MSR_REG(DIVIL_LBAR_SMB), DIVIL_MSR_REG(DIVIL_LBAR_GPIO),
+ DIVIL_MSR_REG(DIVIL_LBAR_MFGPT), DIVIL_MSR_REG(DIVIL_LBAR_IRQ),
+ DIVIL_MSR_REG(DIVIL_LBAR_PMS), DIVIL_MSR_REG(DIVIL_LBAR_ACPI),
+};
+
+static const u32 soft_bar_flag[6] = {
+ SOFT_BAR_SMB_FLAG, SOFT_BAR_GPIO_FLAG, SOFT_BAR_MFGPT_FLAG,
+ SOFT_BAR_IRQ_FLAG, SOFT_BAR_PMS_FLAG, SOFT_BAR_ACPI_FLAG,
+};
+
+static const u32 sb_msr_reg[6] = {
+ SB_MSR_REG(SB_R0), SB_MSR_REG(SB_R1), SB_MSR_REG(SB_R2),
+ SB_MSR_REG(SB_R3), SB_MSR_REG(SB_R4), SB_MSR_REG(SB_R5),
+};
+
+static const u32 bar_space_range[6] = {
+ CS5536_SMB_RANGE, CS5536_GPIO_RANGE, CS5536_MFGPT_RANGE,
+ CS5536_IRQ_RANGE, CS5536_PMS_RANGE, CS5536_ACPI_RANGE,
+};
+
+static const int bar_space_len[6] = {
+ CS5536_SMB_LENGTH, CS5536_GPIO_LENGTH, CS5536_MFGPT_LENGTH,
+ CS5536_IRQ_LENGTH, CS5536_PMS_LENGTH, CS5536_ACPI_LENGTH,
+};
+
+/*
+ * enable the divil module bar space.
+ *
+ * For all the DIVIL module LBAR, you should control the DIVIL LBAR reg
+ * and the RCONFx(0~5) reg to use the modules.
+ */
+static void divil_lbar_enable(void)
+{
+ u32 hi, lo;
+ int offset;
+
+ /*
+ * The DIVIL IRQ is not used yet. and make the RCONF0 reserved.
+ */
+
+ for (offset = DIVIL_LBAR_SMB; offset <= DIVIL_LBAR_PMS; offset++) {
+ _rdmsr(DIVIL_MSR_REG(offset), &hi, &lo);
+ hi |= 0x01;
+ _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), hi, lo);
+ }
+ return;
+}
+
+/*
+ * disable the divil module bar space.
+ */
+static void divil_lbar_disable(void)
+{
+ u32 hi, lo;
+ int offset;
+
+ for (offset = DIVIL_LBAR_SMB; offset <= DIVIL_LBAR_PMS; offset++) {
+ _rdmsr(DIVIL_MSR_REG(offset), &hi, &lo);
+ hi &= ~0x01;
+ _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), hi, lo);
+ }
+ return;
+}
+
+/*
+ * BAR write: write value to the n BAR
+ */
+
+void pci_isa_write_bar(int n, u32 value)
+{
+ u32 hi = 0, lo = value;
+
+ if (value == PCI_BAR_RANGE_MASK) {
+ _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+ lo |= soft_bar_flag[n];
+ _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+ } else if (value & 0x01) {
+ /* NATIVE reg */
+ hi = 0x0000f001;
+ lo &= bar_space_range[n];
+ _wrmsr(divil_msr_reg[n], hi, lo);
+
+ /* RCONFx is 4bytes in units for I/O space */
+ hi = ((value & 0x000ffffc) << 12) |
+ ((bar_space_len[n] - 4) << 12) | 0x01;
+ lo = ((value & 0x000ffffc) << 12) | 0x01;
+ _wrmsr(sb_msr_reg[n], hi, lo);
+ }
+
+ return;
+}
+
+/*
+ * BAR read: read the n BAR
+ */
+
+u32 pci_isa_read_bar(int n)
+{
+ u32 conf_data = 0;
+ u32 hi, lo;
+
+ _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+ if (lo & soft_bar_flag[n]) {
+ conf_data = bar_space_range[n] | PCI_BASE_ADDRESS_SPACE_IO;
+ lo &= ~soft_bar_flag[n];
+ _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+ } else {
+ _rdmsr(divil_msr_reg[n], &hi, &lo);
+ conf_data = lo & bar_space_range[n];
+ conf_data |= 0x01;
+ conf_data &= ~0x02;
+ }
+ return conf_data;
+}
+
+/*
+ * isa_write : isa write transfering.
+ * WE assume that the ISA is not the BUS MASTER.!!!
+ */
+/* FAST BACK TO BACK '1' for BUS MASTER '0' for BUS SALVE */
+/* COMMAND :
+ * bit0 : IO SPACE ENABLE
+ * bit1 : MEMORY SPACE ENABLE(ignore)
+ * bit2 : BUS MASTER ENABLE(ignore)
+ * bit3 : SPECIAL CYCLE(ignore)? default is ignored.
+ * bit4 : MEMORY WRITE and INVALIDATE(ignore)
+ * bit5 : VGA PALETTE(ignore)
+ * bit6 : PARITY ERROR(ignore)? : default is ignored.
+ * bit7 : WAIT CYCLE CONTROL(ignore)
+ * bit8 : SYSTEM ERROR(ignore)
+ * bit9 : FAST BACK TO BACK(ignore)
+ * bit10-bit15 : RESERVED
+ * STATUS :
+ * bit0-bit3 : RESERVED
+ * bit4 : CAPABILITY LIST(ignore)
+ * bit5 : 66MHZ CAPABLE
+ * bit6 : RESERVED
+ * bit7 : FAST BACK TO BACK(ignore)
+ * bit8 : DATA PARITY ERROR DETECED(ignore)
+ * bit9-bit10 : DEVSEL TIMING(ALL MEDIUM)
+ * bit11: SIGNALED TARGET ABORT
+ * bit12: RECEIVED TARGET ABORT
+ * bit13: RECEIVED MASTER ABORT
+ * bit14: SIGNALED SYSTEM ERROR
+ * bit15: DETECTED PARITY ERROR
+ */
+
+void pci_isa_write_reg(int reg, u32 value)
+{
+ u32 hi = 0, lo = value;
+ u32 temp;
+
+ switch (reg) {
+ case PCI_COMMAND:
+ if (value & PCI_COMMAND_IO)
+ divil_lbar_enable();
+ else
+ divil_lbar_disable();
+ break;
+ case PCI_STATUS:
+ _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+ temp = lo & 0x0000ffff;
+ if ((value & PCI_STATUS_SIG_TARGET_ABORT) &&
+ (lo & SB_TAS_ERR_EN))
+ temp |= SB_TAS_ERR_FLAG;
+
+ if ((value & PCI_STATUS_REC_TARGET_ABORT) &&
+ (lo & SB_TAR_ERR_EN))
+ temp |= SB_TAR_ERR_FLAG;
+
+ if ((value & PCI_STATUS_REC_MASTER_ABORT)
+ && (lo & SB_MAR_ERR_EN))
+ temp |= SB_MAR_ERR_FLAG;
+
+ if ((value & PCI_STATUS_DETECTED_PARITY)
+ && (lo & SB_PARE_ERR_EN))
+ temp |= SB_PARE_ERR_FLAG;
+
+ lo = temp;
+ _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+ break;
+ case PCI_CACHE_LINE_SIZE:
+ value &= 0x0000ff00;
+ _rdmsr(SB_MSR_REG(SB_CTRL), &hi, &lo);
+ hi &= 0xffffff00;
+ hi |= (value >> 8);
+ _wrmsr(SB_MSR_REG(SB_CTRL), hi, lo);
+ break;
+ case PCI_BAR0_REG:
+ pci_isa_write_bar(0, value);
+ break;
+ case PCI_BAR1_REG:
+ pci_isa_write_bar(1, value);
+ break;
+ case PCI_BAR2_REG:
+ pci_isa_write_bar(2, value);
+ break;
+ case PCI_BAR3_REG:
+ pci_isa_write_bar(3, value);
+ break;
+ case PCI_BAR4_REG:
+ pci_isa_write_bar(4, value);
+ break;
+ case PCI_BAR5_REG:
+ pci_isa_write_bar(5, value);
+ break;
+ case PCI_UART1_INT_REG:
+ _rdmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), &hi, &lo);
+ /* disable uart1 interrupt in PIC */
+ lo &= ~(0xf << 24);
+ if (value) /* enable uart1 interrupt in PIC */
+ lo |= (CS5536_UART1_INTR << 24);
+ _wrmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), hi, lo);
+ break;
+ case PCI_UART2_INT_REG:
+ _rdmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), &hi, &lo);
+ /* disable uart2 interrupt in PIC */
+ lo &= ~(0xf << 28);
+ if (value) /* enable uart2 interrupt in PIC */
+ lo |= (CS5536_UART2_INTR << 28);
+ _wrmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), hi, lo);
+ break;
+ case PCI_ISA_FIXUP_REG:
+ if (value) {
+ /* enable the TARGET ABORT/MASTER ABORT etc. */
+ _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+ lo |= 0x00000063;
+ _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+ }
+
+ default:
+ /* ALL OTHER PCI CONFIG SPACE HEADER IS NOT IMPLEMENTED. */
+ break;
+ }
+
+ return;
+}
+
+/*
+ * isa_read : isa read transfering.
+ * we assume that the ISA is not the BUS MASTER.
+ */
+
+ /* COMMAND :
+ * bit0 : IO SPACE ENABLE
+ * bit1 : MEMORY SPACE ENABLE(ignore)
+ * bit2 : BUS MASTER ENABLE(ignore)
+ * bit3 : SPECIAL CYCLE(ignore)? default is ignored.
+ * bit4 : MEMORY WRITE and INVALIDATE(ignore)
+ * bit5 : VGA PALETTE(ignore)
+ * bit6 : PARITY ERROR(ignore)? : default is ignored.
+ * bit7 : WAIT CYCLE CONTROL(ignore)
+ * bit8 : SYSTEM ERROR(ignore)
+ * bit9 : FAST BACK TO BACK(ignore)
+ * bit10-bit15 : RESERVED
+ * STATUS :
+ * bit0-bit3 : RESERVED
+ * bit4 : CAPABILITY LIST(ignore)
+ * bit5 : 66MHZ CAPABLE
+ * bit6 : RESERVED
+ * bit7 : FAST BACK TO BACK(ignore)
+ * bit8 : DATA PARITY ERROR DETECED(ignore)?
+ * bit9-bit10 : DEVSEL TIMING(ALL MEDIUM)
+ * bit11: SIGNALED TARGET ABORT
+ * bit12: RECEIVED TARGET ABORT
+ * bit13: RECEIVED MASTER ABORT
+ * bit14: SIGNALED SYSTEM ERROR
+ * bit15: DETECTED PARITY ERROR(?)
+ */
+
+u32 pci_isa_read_reg(int reg)
+{
+ u32 conf_data = 0;
+ u32 hi, lo;
+
+ switch (reg) {
+ case PCI_VENDOR_ID:
+ conf_data =
+ CFG_PCI_VENDOR_ID(CS5536_ISA_DEVICE_ID, CS5536_VENDOR_ID);
+ break;
+ case PCI_COMMAND:
+ /* we just check the first LBAR for the IO enable bit, */
+ /* maybe we should changed later. */
+ _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), &hi, &lo);
+ if (hi & 0x01)
+ conf_data |= PCI_COMMAND_IO;
+ break;
+ case PCI_STATUS:
+ conf_data |= PCI_STATUS_66MHZ;
+ conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
+ conf_data |= PCI_STATUS_FAST_BACK;
+
+ _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+ if (lo & SB_TAS_ERR_FLAG)
+ conf_data |= PCI_STATUS_SIG_TARGET_ABORT;
+ if (lo & SB_TAR_ERR_FLAG)
+ conf_data |= PCI_STATUS_REC_TARGET_ABORT;
+ if (lo & SB_MAR_ERR_FLAG)
+ conf_data |= PCI_STATUS_REC_MASTER_ABORT;
+ if (lo & SB_PARE_ERR_FLAG)
+ conf_data |= PCI_STATUS_DETECTED_PARITY;
+ break;
+ case PCI_CLASS_REVISION:
+ _rdmsr(GLCP_MSR_REG(GLCP_CHIP_REV_ID), &hi, &lo);
+ conf_data = lo & 0x000000ff;
+ conf_data |= (CS5536_ISA_CLASS_CODE << 8);
+ break;
+ case PCI_CACHE_LINE_SIZE:
+ _rdmsr(SB_MSR_REG(SB_CTRL), &hi, &lo);
+ hi &= 0x000000f8;
+ conf_data = CFG_PCI_CACHE_LINE_SIZE(PCI_BRIDGE_HEADER_TYPE, hi);
+ break;
+ /*
+ * we only use the LBAR of DIVIL, no RCONF used.
+ * all of them are IO space.
+ */
+ case PCI_BAR0_REG:
+ return pci_isa_read_bar(0);
+ break;
+ case PCI_BAR1_REG:
+ return pci_isa_read_bar(1);
+ break;
+ case PCI_BAR2_REG:
+ return pci_isa_read_bar(2);
+ break;
+ case PCI_BAR3_REG:
+ break;
+ case PCI_BAR4_REG:
+ return pci_isa_read_bar(4);
+ break;
+ case PCI_BAR5_REG:
+ return pci_isa_read_bar(5);
+ break;
+ case PCI_CARDBUS_CIS:
+ conf_data = PCI_CARDBUS_CIS_POINTER;
+ break;
+ case PCI_SUBSYSTEM_VENDOR_ID:
+ conf_data =
+ CFG_PCI_VENDOR_ID(CS5536_ISA_SUB_ID, CS5536_SUB_VENDOR_ID);
+ break;
+ case PCI_ROM_ADDRESS:
+ conf_data = PCI_EXPANSION_ROM_BAR;
+ break;
+ case PCI_CAPABILITY_LIST:
+ conf_data = PCI_CAPLIST_POINTER;
+ break;
+ case PCI_INTERRUPT_LINE:
+ /* no interrupt used here */
+ conf_data = CFG_PCI_INTERRUPT_LINE(0x00, 0x00);
+ break;
+ default:
+ break;
+ }
+
+ return conf_data;
+}
diff --git a/arch/mips/loongson/common/cs5536/cs5536_ohci.c b/arch/mips/loongson/common/cs5536/cs5536_ohci.c
new file mode 100644
index 0000000..71146b3
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_ohci.c
@@ -0,0 +1,167 @@
+/*
+ * the OHCI Virtual Support Module of AMD CS5536
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author : jlliu, liujl@lemote.com
+ *
+ * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * 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 <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+/*
+ * ohci_write : ohci write transfering.
+ */
+void pci_ohci_write_reg(int reg, u32 value)
+{
+ u32 hi = 0, lo = value;
+
+ switch (reg) {
+ case PCI_COMMAND:
+ _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo);
+ if (value & PCI_COMMAND_MASTER)
+ hi |= PCI_COMMAND_MASTER;
+ else
+ hi &= ~PCI_COMMAND_MASTER;
+
+ if (value & PCI_COMMAND_MEMORY)
+ hi |= PCI_COMMAND_MEMORY;
+ else
+ hi &= ~PCI_COMMAND_MEMORY;
+ _wrmsr(USB_MSR_REG(USB_OHCI), hi, lo);
+ break;
+ case PCI_STATUS:
+ if (value & PCI_STATUS_PARITY) {
+ _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+ if (lo & SB_PARE_ERR_FLAG) {
+ lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG;
+ _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+ }
+ }
+ break;
+ case PCI_BAR0_REG:
+ if (value == PCI_BAR_RANGE_MASK) {
+ _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+ lo |= SOFT_BAR_OHCI_FLAG;
+ _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+ } else if ((value & 0x01) == 0x00) {
+ _wrmsr(USB_MSR_REG(USB_OHCI), hi, lo);
+
+ value &= 0xfffffff0;
+ hi = 0x40000000 | ((value & 0xff000000) >> 24);
+ lo = 0x000fffff | ((value & 0x00fff000) << 8);
+ _wrmsr(GLIU_MSR_REG(GLIU_P2D_BM3), hi, lo);
+ }
+ break;
+ case PCI_INTERRUPT_LINE:
+ value &= 0x000000ff;
+ break;
+ case PCI_OHCI_PM_REG:
+ break;
+ case PCI_OHCI_INT_REG:
+ _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo);
+ lo &= ~(0xf << PIC_YSEL_LOW_USB_SHIFT);
+ if (value) /* enable all the usb interrupt in PIC */
+ lo |= (CS5536_USB_INTR << PIC_YSEL_LOW_USB_SHIFT);
+ _wrmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), hi, lo);
+ break;
+ default:
+ break;
+ }
+
+ return;
+}
+
+/*
+ * ohci_read : ohci read transfering.
+ */
+u32 pci_ohci_read_reg(int reg)
+{
+ u32 conf_data = 0;
+ u32 hi, lo;
+
+ switch (reg) {
+ case PCI_VENDOR_ID:
+ conf_data =
+ CFG_PCI_VENDOR_ID(CS5536_OHCI_DEVICE_ID, CS5536_VENDOR_ID);
+ break;
+ case PCI_COMMAND:
+ _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo);
+ if (hi & PCI_COMMAND_MASTER)
+ conf_data |= PCI_COMMAND_MASTER;
+ if (hi & PCI_COMMAND_MEMORY)
+ conf_data |= PCI_COMMAND_MEMORY;
+ break;
+ case PCI_STATUS:
+ conf_data |= PCI_STATUS_66MHZ;
+ conf_data |= PCI_STATUS_FAST_BACK;
+ _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+ if (lo & SB_PARE_ERR_FLAG)
+ conf_data |= PCI_STATUS_PARITY;
+ conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
+ break;
+ case PCI_CLASS_REVISION:
+ _rdmsr(USB_MSR_REG(USB_CAP), &hi, &lo);
+ conf_data = lo & 0x000000ff;
+ conf_data |= (CS5536_OHCI_CLASS_CODE << 8);
+ break;
+ case PCI_CACHE_LINE_SIZE:
+ conf_data =
+ CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE,
+ PCI_NORMAL_LATENCY_TIMER);
+ break;
+ case PCI_BAR0_REG:
+ _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+ if (lo & SOFT_BAR_OHCI_FLAG) {
+ conf_data = CS5536_OHCI_RANGE |
+ PCI_BASE_ADDRESS_SPACE_MEMORY;
+ lo &= ~SOFT_BAR_OHCI_FLAG;
+ _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+ } else {
+ _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo);
+ conf_data = lo & 0xffffff00;
+ conf_data &= ~0x0000000f; /* 32bit mem */
+ }
+ break;
+ case PCI_BAR1_REG:
+ case PCI_BAR2_REG:
+ case PCI_BAR3_REG:
+ case PCI_BAR4_REG:
+ case PCI_BAR5_REG:
+ break;
+ case PCI_CARDBUS_CIS:
+ conf_data = PCI_CARDBUS_CIS_POINTER;
+ break;
+ case PCI_SUBSYSTEM_VENDOR_ID:
+ conf_data =
+ CFG_PCI_VENDOR_ID(CS5536_OHCI_SUB_ID, CS5536_SUB_VENDOR_ID);
+ break;
+ case PCI_ROM_ADDRESS:
+ conf_data = PCI_EXPANSION_ROM_BAR;
+ break;
+ case PCI_CAPABILITY_LIST:
+ conf_data = PCI_CAPLIST_USB_POINTER;
+ break;
+ case PCI_INTERRUPT_LINE:
+ conf_data = CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_USB_INTR);
+ break;
+ case PCI_OHCI_PM_REG:
+ break;
+ case PCI_OHCI_INT_REG:
+ _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo);
+ if ((lo & 0x00000f00) == CS5536_USB_INTR)
+ conf_data = 1;
+ break;
+ default:
+ break;
+ }
+
+ return conf_data;
+}
diff --git a/arch/mips/loongson/common/cs5536/cs5536_otg.c b/arch/mips/loongson/common/cs5536/cs5536_otg.c
new file mode 100644
index 0000000..363aa88
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_otg.c
@@ -0,0 +1,137 @@
+/*
+ * the OTG Virtual Support Module of AMD CS5536
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author : jlliu, liujl@lemote.com
+ *
+ * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * 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 <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+void pci_otg_write_reg(int reg, u32 value)
+{
+ u32 hi = 0, lo = value;
+
+ switch (reg) {
+ case PCI_COMMAND:
+ _rdmsr(USB_MSR_REG(USB_OTG), &hi, &lo);
+ if (value & PCI_COMMAND_MEMORY)
+ hi |= PCI_COMMAND_MEMORY;
+ else
+ hi &= ~PCI_COMMAND_MEMORY;
+ _wrmsr(USB_MSR_REG(USB_OTG), hi, lo);
+ break;
+ case PCI_STATUS:
+ if (value & PCI_STATUS_PARITY) {
+ _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+ if (lo & SB_PARE_ERR_FLAG) {
+ lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG;
+ _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+ }
+ }
+ break;
+ case PCI_BAR0_REG:
+ if (value == PCI_BAR_RANGE_MASK) {
+ _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+ lo |= SOFT_BAR_OTG_FLAG;
+ _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+ } else if ((value & 0x01) == 0x00) {
+ _rdmsr(USB_MSR_REG(USB_OTG), &hi, &lo);
+ lo &= 0xffffff00;
+ _wrmsr(USB_MSR_REG(USB_OTG), hi, lo);
+
+ value &= 0xfffffff0;
+ hi = 0x40000000 | ((value & 0xff000000) >> 24);
+ lo = 0x000fffff | ((value & 0x00fff000) << 8);
+ _wrmsr(GLIU_MSR_REG(GLIU_P2D_BM1), hi, lo);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return;
+}
+
+u32 pci_otg_read_reg(int reg)
+{
+ u32 conf_data = 0;
+ u32 hi, lo;
+
+ switch (reg) {
+ case PCI_VENDOR_ID:
+ conf_data =
+ CFG_PCI_VENDOR_ID(CS5536_OTG_DEVICE_ID, CS5536_VENDOR_ID);
+ break;
+ case PCI_COMMAND:
+ _rdmsr(USB_MSR_REG(USB_OTG), &hi, &lo);
+ if (hi & PCI_COMMAND_MEMORY)
+ conf_data |= PCI_COMMAND_MEMORY;
+ break;
+ case PCI_STATUS:
+ conf_data |= PCI_STATUS_66MHZ;
+ conf_data |= PCI_STATUS_FAST_BACK;
+ _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+ if (lo & SB_PARE_ERR_FLAG)
+ conf_data |= PCI_STATUS_PARITY;
+ conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
+ break;
+ case PCI_CLASS_REVISION:
+ _rdmsr(USB_MSR_REG(USB_CAP), &hi, &lo);
+ conf_data = lo & 0x000000ff;
+ conf_data |= (CS5536_OTG_CLASS_CODE << 8);
+ break;
+ case PCI_CACHE_LINE_SIZE:
+ conf_data =
+ CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE,
+ PCI_NORMAL_LATENCY_TIMER);
+ break;
+ case PCI_BAR0_REG:
+ _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+ if (lo & SOFT_BAR_OTG_FLAG) {
+ conf_data = CS5536_OTG_RANGE |
+ PCI_BASE_ADDRESS_SPACE_MEMORY;
+ lo &= ~SOFT_BAR_OTG_FLAG;
+ _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+ } else {
+ _rdmsr(USB_MSR_REG(USB_OTG), &hi, &lo);
+ conf_data = lo & 0xffffff00;
+ conf_data &= ~0x0000000f;
+ }
+ break;
+ case PCI_BAR1_REG:
+ case PCI_BAR2_REG:
+ case PCI_BAR3_REG:
+ case PCI_BAR4_REG:
+ case PCI_BAR5_REG:
+ break;
+ case PCI_CARDBUS_CIS:
+ conf_data = PCI_CARDBUS_CIS_POINTER;
+ break;
+ case PCI_SUBSYSTEM_VENDOR_ID:
+ conf_data =
+ CFG_PCI_VENDOR_ID(CS5536_OTG_SUB_ID, CS5536_SUB_VENDOR_ID);
+ break;
+ case PCI_ROM_ADDRESS:
+ conf_data = PCI_EXPANSION_ROM_BAR;
+ break;
+ case PCI_CAPABILITY_LIST:
+ conf_data = PCI_CAPLIST_USB_POINTER;
+ break;
+ case PCI_INTERRUPT_LINE:
+ conf_data = CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_USB_INTR);
+ break;
+ default:
+ break;
+ }
+
+ return conf_data;
+}
diff --git a/arch/mips/loongson/common/cs5536/cs5536_pci.c b/arch/mips/loongson/common/cs5536/cs5536_pci.c
new file mode 100644
index 0000000..977d77e
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_pci.c
@@ -0,0 +1,126 @@
+/*
+ * read/write operation to the PCI config space of CS5536
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author : jlliu, liujl@lemote.com
+ *
+ * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * 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.
+ *
+ * the Virtual Support Module(VSM) for virtulizing the PCI
+ * configure space are defined in cs5536_modulename.c respectively,
+ * so you can select modules which have been used in his/her board.
+ * to archive this, you just need to add a "select CS5536_[MODULE]"
+ * option in your board in arch/mips/loongson/Kconfig
+ *
+ * after this virtulizing, user can access the PCI configure space
+ * directly as a normal multi-function PCI device which following
+ * the PCI-2.2 spec.
+ */
+
+#include <linux/types.h>
+#include <cs5536/cs5536_vsm.h>
+
+enum {
+ CS5536_FUNC_START = -1,
+ CS5536_ISA_FUNC,
+ CS5536_FLASH_FUNC,
+ CS5536_IDE_FUNC,
+ CS5536_ACC_FUNC,
+ CS5536_OHCI_FUNC,
+ CS5536_EHCI_FUNC,
+ CS5536_UDC_FUNC,
+ CS5536_OTG_FUNC,
+ CS5536_FUNC_END,
+};
+
+/*
+ * write to PCI config space and transfer it to MSR write.
+ */
+void cs5536_pci_conf_write4(int function, int reg, u32 value)
+{
+ if ((function <= CS5536_FUNC_START) || (function >= CS5536_FUNC_END))
+ return;
+ if ((reg < 0) || (reg > 0x100) || ((reg & 0x03) != 0))
+ return;
+
+ switch (function) {
+ case CS5536_ISA_FUNC:
+ pci_isa_write_reg(reg, value);
+ break;
+ case CS5536_FLASH_FUNC:
+ pci_flash_write_reg(reg, value);
+ break;
+ case CS5536_IDE_FUNC:
+ pci_ide_write_reg(reg, value);
+ break;
+ case CS5536_ACC_FUNC:
+ pci_acc_write_reg(reg, value);
+ break;
+ case CS5536_OHCI_FUNC:
+ pci_ohci_write_reg(reg, value);
+ break;
+ case CS5536_EHCI_FUNC:
+ pci_ehci_write_reg(reg, value);
+ break;
+ case CS5536_UDC_FUNC:
+ pci_udc_write_reg(reg, value);
+ break;
+ case CS5536_OTG_FUNC:
+ pci_otg_write_reg(reg, value);
+ break;
+ default:
+ break;
+ }
+ return;
+}
+
+/*
+ * read PCI config space and transfer it to MSR access.
+ */
+u32 cs5536_pci_conf_read4(int function, int reg)
+{
+ u32 data = 0;
+
+ if ((function <= CS5536_FUNC_START) || (function >= CS5536_FUNC_END))
+ return 0;
+ if ((reg < 0) || ((reg & 0x03) != 0))
+ return 0;
+ if (reg > 0x100)
+ return 0xffffffff;
+
+ switch (function) {
+ case CS5536_ISA_FUNC:
+ data = pci_isa_read_reg(reg);
+ break;
+ case CS5536_FLASH_FUNC:
+ data = pci_flash_read_reg(reg);
+ break;
+ case CS5536_IDE_FUNC:
+ data = pci_ide_read_reg(reg);
+ break;
+ case CS5536_ACC_FUNC:
+ data = pci_acc_read_reg(reg);
+ break;
+ case CS5536_OHCI_FUNC:
+ data = pci_ohci_read_reg(reg);
+ break;
+ case CS5536_EHCI_FUNC:
+ data = pci_ehci_read_reg(reg);
+ break;
+ case CS5536_UDC_FUNC:
+ data = pci_udc_read_reg(reg);
+ break;
+ case CS5536_OTG_FUNC:
+ data = pci_otg_read_reg(reg);
+ break;
+ default:
+ break;
+ }
+ return data;
+}
diff --git a/arch/mips/loongson/common/cs5536/cs5536_udc.c b/arch/mips/loongson/common/cs5536/cs5536_udc.c
new file mode 100644
index 0000000..2050aac
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_udc.c
@@ -0,0 +1,142 @@
+/*
+ * the UDC Virtual Support Module of AMD CS5536
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author : jlliu, liujl@lemote.com
+ *
+ * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * 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 <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+void pci_udc_write_reg(int reg, u32 value)
+{
+ u32 hi = 0, lo = value;
+
+ switch (reg) {
+ case PCI_COMMAND:
+ _rdmsr(USB_MSR_REG(USB_UDC), &hi, &lo);
+ if (value & PCI_COMMAND_MASTER)
+ hi |= PCI_COMMAND_MASTER;
+ else
+ hi &= ~PCI_COMMAND_MASTER;
+
+ if (value & PCI_COMMAND_MEMORY)
+ hi |= PCI_COMMAND_MEMORY;
+ else
+ hi &= ~PCI_COMMAND_MEMORY;
+ _wrmsr(USB_MSR_REG(USB_UDC), hi, lo);
+ break;
+ case PCI_STATUS:
+ if (value & PCI_STATUS_PARITY) {
+ _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+ if (lo & SB_PARE_ERR_FLAG) {
+ lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG;
+ _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+ }
+ }
+ break;
+ case PCI_BAR0_REG:
+ if (value == PCI_BAR_RANGE_MASK) {
+ _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+ lo |= SOFT_BAR_UDC_FLAG;
+ _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+ } else if ((value & 0x01) == 0x00) {
+ _wrmsr(USB_MSR_REG(USB_UDC), hi, lo);
+
+ value &= 0xfffffff0;
+ hi = 0x40000000 | ((value & 0xff000000) >> 24);
+ lo = 0x000fffff | ((value & 0x00fff000) << 8);
+ _wrmsr(GLIU_MSR_REG(GLIU_P2D_BM0), hi, lo);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return;
+}
+
+u32 pci_udc_read_reg(int reg)
+{
+ u32 conf_data = 0;
+ u32 hi, lo;
+
+ switch (reg) {
+ case PCI_VENDOR_ID:
+ conf_data =
+ CFG_PCI_VENDOR_ID(CS5536_UDC_DEVICE_ID, CS5536_VENDOR_ID);
+ break;
+ case PCI_COMMAND:
+ _rdmsr(USB_MSR_REG(USB_UDC), &hi, &lo);
+ if (hi & PCI_COMMAND_MASTER)
+ conf_data |= PCI_COMMAND_MASTER;
+ if (hi & PCI_COMMAND_MEMORY)
+ conf_data |= PCI_COMMAND_MEMORY;
+ break;
+ case PCI_STATUS:
+ conf_data |= PCI_STATUS_66MHZ;
+ conf_data |= PCI_STATUS_FAST_BACK;
+ _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+ if (lo & SB_PARE_ERR_FLAG)
+ conf_data |= PCI_STATUS_PARITY;
+ conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
+ break;
+ case PCI_CLASS_REVISION:
+ _rdmsr(USB_MSR_REG(USB_CAP), &hi, &lo);
+ conf_data = lo & 0x000000ff;
+ conf_data |= (CS5536_UDC_CLASS_CODE << 8);
+ break;
+ case PCI_CACHE_LINE_SIZE:
+ conf_data =
+ CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE,
+ PCI_NORMAL_LATENCY_TIMER);
+ break;
+ case PCI_BAR0_REG:
+ _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+ if (lo & SOFT_BAR_UDC_FLAG) {
+ conf_data = CS5536_UDC_RANGE |
+ PCI_BASE_ADDRESS_SPACE_MEMORY;
+ lo &= ~SOFT_BAR_UDC_FLAG;
+ _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+ } else {
+ _rdmsr(USB_MSR_REG(USB_UDC), &hi, &lo);
+ conf_data = lo & 0xfffff000;
+ conf_data &= ~0x0000000f; /* 32bit mem */
+ }
+ break;
+ case PCI_BAR1_REG:
+ case PCI_BAR2_REG:
+ case PCI_BAR3_REG:
+ case PCI_BAR4_REG:
+ case PCI_BAR5_REG:
+ break;
+ case PCI_CARDBUS_CIS:
+ conf_data = PCI_CARDBUS_CIS_POINTER;
+ break;
+ case PCI_SUBSYSTEM_VENDOR_ID:
+ conf_data =
+ CFG_PCI_VENDOR_ID(CS5536_UDC_SUB_ID, CS5536_SUB_VENDOR_ID);
+ break;
+ case PCI_ROM_ADDRESS:
+ conf_data = PCI_EXPANSION_ROM_BAR;
+ break;
+ case PCI_CAPABILITY_LIST:
+ conf_data = PCI_CAPLIST_USB_POINTER;
+ break;
+ case PCI_INTERRUPT_LINE:
+ conf_data = CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_USB_INTR);
+ break;
+ default:
+ break;
+ }
+
+ return conf_data;
+}
diff --git a/arch/mips/loongson/fuloong-2f/Makefile b/arch/mips/loongson/fuloong-2f/Makefile
new file mode 100644
index 0000000..010b86c
--- /dev/null
+++ b/arch/mips/loongson/fuloong-2f/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for fuloong-2f
+#
+
+obj-y += irq.o reset.o
diff --git a/arch/mips/loongson/fuloong-2f/irq.c b/arch/mips/loongson/fuloong-2f/irq.c
new file mode 100644
index 0000000..571aeb3
--- /dev/null
+++ b/arch/mips/loongson/fuloong-2f/irq.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ * 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/interrupt.h>
+
+#include <loongson.h>
+#include <machine.h>
+
+inline int mach_i8259_irq(void)
+{
+ int irq, isr, imr;
+
+ irq = -1;
+
+ if ((LOONGSON_INTISR & LOONGSON_INTEN) & LOONGSON_INT_BIT_INT0) {
+ imr = inb(0x21) | (inb(0xa1) << 8);
+ isr = inb(0x20) | (inb(0xa0) << 8);
+ isr &= ~0x4; /* irq2 for cascade */
+ isr &= ~imr;
+ irq = ffs(isr) - 1;
+ }
+
+ return irq;
+}
+
+inline void mach_irq_dispatch(unsigned int pending)
+{
+ if (pending & CAUSEF_IP7)
+ do_IRQ(LOONGSON_TIMER_IRQ);
+ else if (pending & CAUSEF_IP6) { /* North Bridge, Perf counter */
+ do_IRQ(LOONGSON_PERFCNT_IRQ);
+ bonito_irqdispatch();
+ } else if (pending & CAUSEF_IP3) /* CPU UART */
+ do_IRQ(LOONGSON_UART_IRQ);
+ else if (pending & CAUSEF_IP2) /* South Bridge */
+ i8259_irqdispatch();
+ else
+ spurious_interrupt();
+}
+
+void __init set_irq_trigger_mode(void)
+{
+ /* setup cs5536 as high level trigger */
+ LOONGSON_INTPOL = LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1;
+ LOONGSON_INTEDGE &= ~(LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1);
+}
diff --git a/arch/mips/loongson/fuloong-2f/reset.c b/arch/mips/loongson/fuloong-2f/reset.c
new file mode 100644
index 0000000..0261c17
--- /dev/null
+++ b/arch/mips/loongson/fuloong-2f/reset.c
@@ -0,0 +1,65 @@
+/* Board-specific reboot/shutdown routines
+ *
+ * Copyright (c) 2009 Philippe Vachon <philippe@cowpig.ca>
+ *
+ * Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * 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/io.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+
+#include <loongson.h>
+
+/* cs5536 is the south bridge used by fuloong2f mini PC */
+#include <cs5536/cs5536.h>
+
+void mach_prepare_reboot(void)
+{
+ /*
+ * reset cpu to full speed, this is needed when enabling cpu frequency
+ * scalling
+ */
+ LOONGSON_CHIPCFG0 |= 0x7;
+
+ /* send a reset signal to south bridge.
+ *
+ * NOTE: if enable "Power Management" in kernel, rtl8169 will not reset
+ * normally with this reset operation and it will not work in PMON, but
+ * you can type halt command and then reboot, seems the hardware reset
+ * logic not work normally.
+ */
+ {
+ u32 hi, lo;
+ _rdmsr(DIVIL_MSR_REG(DIVIL_SOFT_RESET), &hi, &lo);
+ lo |= 0x00000001;
+ _wrmsr(DIVIL_MSR_REG(DIVIL_SOFT_RESET), hi, lo);
+ }
+}
+
+void mach_prepare_shutdown(void)
+{
+ u32 hi, lo, val;
+ phys_addr_t gpio_base;
+
+ _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_GPIO), &hi, &lo);
+
+ gpio_base = mips_io_port_base | (lo & 0xff00);
+
+ /* make cs5536 gpio13 output enable */
+ val = (readl((u32 *) (gpio_base + GPIOL_OUT_EN)) & ~(1 << (16 + 13)))
+ | (1 << 13);
+ writel(val, (u32 *) (gpio_base + GPIOL_OUT_EN));
+ mmiowb();
+ /* make cs5536 gpio13 output low level voltage. */
+ val = (readl((u32 *) (gpio_base + GPIOL_OUT_VAL)) & ~(1 << (13)))
+ | (1 << (16 + 13));
+ writel(val, (u32 *) (gpio_base + GPIOL_OUT_VAL));
+ mmiowb();
+}
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index a0cc238..b96ed14 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -26,7 +26,8 @@ obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o
obj-$(CONFIG_SOC_AU1500) += fixup-au1000.o ops-au1000.o
obj-$(CONFIG_SOC_AU1550) += fixup-au1000.o ops-au1000.o
obj-$(CONFIG_SOC_PNX8550) += fixup-pnx8550.o ops-pnx8550.o
-obj-$(CONFIG_LEMOTE_FULOONG2E) += fixup-fuloong2e.o ops-fuloong2e.o
+obj-$(CONFIG_LEMOTE_FULOONG2E) += fixup-fuloong2e.o ops-loongson2.o
+obj-$(CONFIG_LEMOTE_FULOONG2F) += fixup-fuloong2f.o ops-loongson2.o
obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o
obj-$(CONFIG_PMC_MSP7120_GW) += fixup-pmcmsp.o ops-pmcmsp.o
obj-$(CONFIG_PMC_MSP7120_EVAL) += fixup-pmcmsp.o ops-pmcmsp.o
diff --git a/arch/mips/pci/fixup-fuloong2f.c b/arch/mips/pci/fixup-fuloong2f.c
new file mode 100644
index 0000000..99fd2c8
--- /dev/null
+++ b/arch/mips/pci/fixup-fuloong2f.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2008 Lemote Technology
+ * Copyright (C) 2004 ICT CAS
+ * Author: Li xiaoyu, lixy@ict.ac.cn
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ * 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/init.h>
+#include <linux/pci.h>
+
+#include <loongson.h>
+#include <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+/* PCI interrupt pins
+ *
+ * These should not be changed, or you should consider loongson2f interrupt
+ * register and your pci card dispatch
+ */
+
+#define PCIA 4
+#define PCIB 5
+#define PCIC 6
+#define PCID 7
+
+/* all the pci device has the PCIA pin, check the datasheet. */
+static char irq_tab[][5] __initdata = {
+ /* INTA INTB INTC INTD */
+ {0, 0, 0, 0, 0}, /* 11: Unused */
+ {0, 0, 0, 0, 0}, /* 12: Unused */
+ {0, 0, 0, 0, 0}, /* 13: Unused */
+ {0, 0, 0, 0, 0}, /* 14: Unused */
+ {0, 0, 0, 0, 0}, /* 15: Unused */
+ {0, 0, 0, 0, 0}, /* 16: Unused */
+ {0, PCIA, 0, 0, 0}, /* 17: RTL8110-0 */
+ {0, PCIB, 0, 0, 0}, /* 18: RTL8110-1 */
+ {0, PCIC, 0, 0, 0}, /* 19: SiI3114 */
+ {0, PCID, 0, 0, 0}, /* 20: 3-ports nec usb */
+ {0, PCIA, PCIB, PCIC, PCID}, /* 21: PCI-SLOT */
+ {0, 0, 0, 0, 0}, /* 22: Unused */
+ {0, 0, 0, 0, 0}, /* 23: Unused */
+ {0, 0, 0, 0, 0}, /* 24: Unused */
+ {0, 0, 0, 0, 0}, /* 25: Unused */
+ {0, 0, 0, 0, 0}, /* 26: Unused */
+ {0, 0, 0, 0, 0}, /* 27: Unused */
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ int virq;
+
+ if ((PCI_SLOT(dev->devfn) != PCI_IDSEL_CS5536)
+ && (PCI_SLOT(dev->devfn) < 32)) {
+ virq = irq_tab[slot][pin];
+ printk(KERN_INFO "slot: %d, pin: %d, irq: %d\n", slot, pin,
+ virq + LOONGSON_IRQ_BASE);
+ if (virq != 0)
+ return LOONGSON_IRQ_BASE + virq;
+ else
+ return 0;
+ } else if (PCI_SLOT(dev->devfn) == PCI_IDSEL_CS5536) { /* cs5536 */
+ switch (PCI_FUNC(dev->devfn)) {
+ case 2:
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
+ CS5536_IDE_INTR);
+ return 14; /* for IDE */
+ case 3:
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
+ CS5536_ACC_INTR);
+ return 9; /* for AUDIO */
+ case 4: /* for OHCI */
+ case 5: /* for EHCI */
+ case 6: /* for UDC */
+ case 7: /* for OTG */
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
+ CS5536_USB_INTR);
+ return 11;
+ }
+ return dev->irq;
+ } else {
+ printk(KERN_INFO " strange pci slot number.\n");
+ return 0;
+ }
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
+
+/* CS5536 SPEC. fixup */
+static void __init loongson_cs5536_isa_fixup(struct pci_dev *pdev)
+{
+ /* the uart1 and uart2 interrupt in PIC is enabled as default */
+ pci_write_config_dword(pdev, PCI_UART1_INT_REG, 1);
+ pci_write_config_dword(pdev, PCI_UART2_INT_REG, 1);
+ return;
+}
+
+static void __init loongson_cs5536_ide_fixup(struct pci_dev *pdev)
+{
+ /* setting the mutex pin as IDE function */
+ pci_write_config_dword(pdev, PCI_IDE_CFG_REG,
+ CS5536_IDE_FLASH_SIGNATURE);
+ return;
+}
+
+static void __init loongson_cs5536_acc_fixup(struct pci_dev *pdev)
+{
+ u8 val;
+
+ /* enable the AUDIO interrupt in PIC */
+ pci_write_config_dword(pdev, PCI_ACC_INT_REG, 1);
+
+#if 1
+ pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &val);
+ printk(KERN_INFO "cs5536 acc latency 0x%x\n", val);
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xc0);
+#endif
+ return;
+}
+
+static void __init loongson_cs5536_ohci_fixup(struct pci_dev *pdev)
+{
+ /* enable the OHCI interrupt in PIC */
+ /* THE OHCI, EHCI, UDC, OTG are shared with interrupt in PIC */
+ pci_write_config_dword(pdev, PCI_OHCI_INT_REG, 1);
+ return;
+}
+
+static void __init loongson_cs5536_ehci_fixup(struct pci_dev *pdev)
+{
+ u32 hi, lo;
+
+ /* Serial short detect enable */
+ _rdmsr(USB_MSR_REG(USB_CONFIG), &hi, &lo);
+ _wrmsr(USB_MSR_REG(USB_CONFIG), (1 << 1) | (1 << 2) | (1 << 3), lo);
+
+ /* setting the USB2.0 micro frame length */
+ pci_write_config_dword(pdev, PCI_EHCI_FLADJ_REG, 0x2000);
+ return;
+}
+
+static void __init loongson_nec_fixup(struct pci_dev *pdev)
+{
+ unsigned int val;
+
+ pci_read_config_dword(pdev, 0xe0, &val);
+ /* Only 2 port be used */
+ pci_write_config_dword(pdev, 0xe0, (val & ~3) | 0x2);
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA,
+ loongson_cs5536_isa_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_OHC,
+ loongson_cs5536_ohci_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_EHC,
+ loongson_cs5536_ehci_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO,
+ loongson_cs5536_acc_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE,
+ loongson_cs5536_ide_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
+ loongson_nec_fixup);
diff --git a/arch/mips/pci/ops-fuloong2e.c b/arch/mips/pci/ops-fuloong2e.c
deleted file mode 100644
index 6bb7919..0000000
--- a/arch/mips/pci/ops-fuloong2e.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 1999, 2000, 2004 MIPS Technologies, Inc.
- * All rights reserved.
- * Authors: Carsten Langgaard <carstenl@mips.com>
- * Maciej W. Rozycki <macro@mips.com>
- *
- * 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.
- *
- * MIPS boards specific PCI support.
- */
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <loongson.h>
-
-#define PCI_ACCESS_READ 0
-#define PCI_ACCESS_WRITE 1
-
-#define CFG_SPACE_REG(offset) \
- (void *)CKSEG1ADDR(LOONGSON_PCICFG_BASE | (offset))
-#define ID_SEL_BEGIN 11
-#define MAX_DEV_NUM (31 - ID_SEL_BEGIN)
-
-
-static int loongson_pcibios_config_access(unsigned char access_type,
- struct pci_bus *bus,
- unsigned int devfn, int where,
- u32 *data)
-{
- u32 busnum = bus->number;
- u32 addr, type;
- u32 dummy;
- void *addrp;
- int device = PCI_SLOT(devfn);
- int function = PCI_FUNC(devfn);
- int reg = where & ~3;
-
- if (busnum == 0) {
- /* Type 0 configuration for onboard PCI bus */
- if (device > MAX_DEV_NUM)
- return -1;
-
- addr = (1 << (device + ID_SEL_BEGIN)) | (function << 8) | reg;
- type = 0;
- } else {
- /* Type 1 configuration for offboard PCI bus */
- addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
- type = 0x10000;
- }
-
- /* Clear aborts */
- LOONGSON_PCICMD |= LOONGSON_PCICMD_MABORT_CLR | \
- LOONGSON_PCICMD_MTABORT_CLR;
-
- LOONGSON_PCIMAP_CFG = (addr >> 16) | type;
-
- /* Flush Bonito register block */
- dummy = LOONGSON_PCIMAP_CFG;
- mmiowb();
-
- addrp = CFG_SPACE_REG(addr & 0xffff);
- if (access_type == PCI_ACCESS_WRITE)
- writel(cpu_to_le32(*data), addrp);
- else
- *data = le32_to_cpu(readl(addrp));
-
- /* Detect Master/Target abort */
- if (LOONGSON_PCICMD & (LOONGSON_PCICMD_MABORT_CLR |
- LOONGSON_PCICMD_MTABORT_CLR)) {
- /* Error occurred */
-
- /* Clear bits */
- LOONGSON_PCICMD |= (LOONGSON_PCICMD_MABORT_CLR |
- LOONGSON_PCICMD_MTABORT_CLR);
-
- return -1;
- }
-
- return 0;
-
-}
-
-
-/*
- * We can't address 8 and 16 bit words directly. Instead we have to
- * read/write a 32bit word and mask/modify the data we actually want.
- */
-static int loongson_pcibios_read(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 *val)
-{
- u32 data = 0;
-
- if ((size == 2) && (where & 1))
- return PCIBIOS_BAD_REGISTER_NUMBER;
- else if ((size == 4) && (where & 3))
- return PCIBIOS_BAD_REGISTER_NUMBER;
-
- if (loongson_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
- &data))
- return -1;
-
- if (size == 1)
- *val = (data >> ((where & 3) << 3)) & 0xff;
- else if (size == 2)
- *val = (data >> ((where & 3) << 3)) & 0xffff;
- else
- *val = data;
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int loongson_pcibios_write(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 val)
-{
- u32 data = 0;
-
- if ((size == 2) && (where & 1))
- return PCIBIOS_BAD_REGISTER_NUMBER;
- else if ((size == 4) && (where & 3))
- return PCIBIOS_BAD_REGISTER_NUMBER;
-
- if (size == 4)
- data = val;
- else {
- if (loongson_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
- where, &data))
- return -1;
-
- if (size == 1)
- data = (data & ~(0xff << ((where & 3) << 3))) |
- (val << ((where & 3) << 3));
- else if (size == 2)
- data = (data & ~(0xffff << ((where & 3) << 3))) |
- (val << ((where & 3) << 3));
- }
-
- if (loongson_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where,
- &data))
- return -1;
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-struct pci_ops loongson_pci_ops = {
- .read = loongson_pcibios_read,
- .write = loongson_pcibios_write
-};
diff --git a/arch/mips/pci/ops-loongson2.c b/arch/mips/pci/ops-loongson2.c
new file mode 100644
index 0000000..08d705e
--- /dev/null
+++ b/arch/mips/pci/ops-loongson2.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 1999, 2000, 2004 MIPS Technologies, Inc.
+ * All rights reserved.
+ * Authors: Carsten Langgaard <carstenl@mips.com>
+ * Maciej W. Rozycki <macro@mips.com>
+ *
+ * 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.
+ *
+ * MIPS boards specific PCI support.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <loongson.h>
+
+#ifdef CONFIG_CS5536
+#include <cs5536/cs5536_pci.h>
+#include <cs5536/cs5536.h>
+#endif
+
+#define PCI_ACCESS_READ 0
+#define PCI_ACCESS_WRITE 1
+
+#define CFG_SPACE_REG(offset) \
+ (void *)CKSEG1ADDR(LOONGSON_PCICFG_BASE | (offset))
+#define ID_SEL_BEGIN 11
+#define MAX_DEV_NUM (31 - ID_SEL_BEGIN)
+
+
+static int loongson_pcibios_config_access(unsigned char access_type,
+ struct pci_bus *bus,
+ unsigned int devfn, int where,
+ u32 *data)
+{
+ u32 busnum = bus->number;
+ u32 addr, type;
+ u32 dummy;
+ void *addrp;
+ int device = PCI_SLOT(devfn);
+ int function = PCI_FUNC(devfn);
+ int reg = where & ~3;
+
+ if (busnum == 0) {
+ /* board-specific part,currently,only fuloong2f,yeeloong2f
+ * use CS5536, fuloong2e use via686b, gdium has no
+ * south bridge
+ */
+#ifdef CONFIG_CS5536
+ /* cs5536_pci_conf_read4/write4() will call _rdmsr/_wrmsr()
+ * to access the regsters 0xf4,0xf8,0xfc, which is bigger than
+ * 0xf0, so, it will not go this branch, but the others. so,
+ * no calling dead loop here.
+ */
+ if ((PCI_IDSEL_CS5536 == device) && (reg < 0xF0)) {
+ switch (access_type) {
+ case PCI_ACCESS_READ:
+ *data = cs5536_pci_conf_read4(function, reg);
+ break;
+ case PCI_ACCESS_WRITE:
+ cs5536_pci_conf_write4(function, reg, *data);
+ break;
+ }
+ return 0;
+ }
+#endif
+ /* Type 0 configuration for onboard PCI bus */
+ if (device > MAX_DEV_NUM)
+ return -1;
+
+ addr = (1 << (device + ID_SEL_BEGIN)) | (function << 8) | reg;
+ type = 0;
+ } else {
+ /* Type 1 configuration for offboard PCI bus */
+ addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
+ type = 0x10000;
+ }
+
+ /* Clear aborts */
+ LOONGSON_PCICMD |= LOONGSON_PCICMD_MABORT_CLR | \
+ LOONGSON_PCICMD_MTABORT_CLR;
+
+ LOONGSON_PCIMAP_CFG = (addr >> 16) | type;
+
+ /* Flush Bonito register block */
+ dummy = LOONGSON_PCIMAP_CFG;
+ mmiowb();
+
+ addrp = CFG_SPACE_REG(addr & 0xffff);
+ if (access_type == PCI_ACCESS_WRITE)
+ writel(cpu_to_le32(*data), addrp);
+ else
+ *data = le32_to_cpu(readl(addrp));
+
+ /* Detect Master/Target abort */
+ if (LOONGSON_PCICMD & (LOONGSON_PCICMD_MABORT_CLR |
+ LOONGSON_PCICMD_MTABORT_CLR)) {
+ /* Error occurred */
+
+ /* Clear bits */
+ LOONGSON_PCICMD |= (LOONGSON_PCICMD_MABORT_CLR |
+ LOONGSON_PCICMD_MTABORT_CLR);
+
+ return -1;
+ }
+
+ return 0;
+
+}
+
+
+/*
+ * We can't address 8 and 16 bit words directly. Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static int loongson_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 *val)
+{
+ u32 data = 0;
+
+ if ((size == 2) && (where & 1))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ else if ((size == 4) && (where & 3))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ if (loongson_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
+ &data))
+ return -1;
+
+ if (size == 1)
+ *val = (data >> ((where & 3) << 3)) & 0xff;
+ else if (size == 2)
+ *val = (data >> ((where & 3) << 3)) & 0xffff;
+ else
+ *val = data;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int loongson_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+ u32 data = 0;
+
+ if ((size == 2) && (where & 1))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ else if ((size == 4) && (where & 3))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ if (size == 4)
+ data = val;
+ else {
+ if (loongson_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+ where, &data))
+ return -1;
+
+ if (size == 1)
+ data = (data & ~(0xff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ else if (size == 2)
+ data = (data & ~(0xffff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ }
+
+ if (loongson_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where,
+ &data))
+ return -1;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops loongson_pci_ops = {
+ .read = loongson_pcibios_read,
+ .write = loongson_pcibios_write
+};
+
+#ifdef CONFIG_CS5536
+void _rdmsr(u32 msr, u32 *hi, u32 *lo)
+{
+ struct pci_bus bus = {
+ .number = PCI_BUS_CS5536
+ };
+ u32 devfn = PCI_DEVFN(PCI_IDSEL_CS5536, 0);
+ loongson_pcibios_write(&bus, devfn, PCI_MSR_ADDR, 4, msr);
+ loongson_pcibios_read(&bus, devfn, PCI_MSR_DATA_LO, 4, lo);
+ loongson_pcibios_read(&bus, devfn, PCI_MSR_DATA_HI, 4, hi);
+}
+EXPORT_SYMBOL(_rdmsr);
+
+void _wrmsr(u32 msr, u32 hi, u32 lo)
+{
+ struct pci_bus bus = {
+ .number = PCI_BUS_CS5536
+ };
+ u32 devfn = PCI_DEVFN(PCI_IDSEL_CS5536, 0);
+ loongson_pcibios_write(&bus, devfn, PCI_MSR_ADDR, 4, msr);
+ loongson_pcibios_write(&bus, devfn, PCI_MSR_DATA_LO, 4, lo);
+ loongson_pcibios_write(&bus, devfn, PCI_MSR_DATA_HI, 4, hi);
+}
+EXPORT_SYMBOL(_wrmsr);
+#endif
--
1.6.2.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [loongson-PATCH-v1 16/27] Add Siliconmotion 712 framebuffer driver
[not found] <cover.1242855716.git.wuzhangjin@gmail.com>
2009-05-20 22:05 ` [loongson-PATCH-v1 12/27] add basic loongson-2f support wuzhangjin
2009-05-20 22:06 ` [loongson-PATCH-v1 13/27] add basic fuloong(2f) support wuzhangjin
@ 2009-05-20 22:08 ` wuzhangjin
2009-05-29 13:29 ` Simon Braunschmidt
2009-05-20 22:12 ` [loongson-PATCH-v1 24/27] fixup for FUJITSU disk wuzhangjin
2009-05-20 22:14 ` [loongson-PATCH-v1 27/27] add gcc 4.4 support for MIPS and loongson wuzhangjin
4 siblings, 1 reply; 20+ messages in thread
From: wuzhangjin @ 2009-05-20 22:08 UTC (permalink / raw)
To: linux-mips, Ralf Baechle, Andrew Morton
Cc: linux-kernel, Wu Zhangjin, Yan hua, Philippe Vachon, Zhang Le,
Zhang Fuxin, Arnaud Patard, loongson-dev, gnewsense-dev,
Nicholas Mc Guire, Liu Junliang, Erwan Lerale
From: Wu Zhangjin <wuzhangjin@gmail.com>
yeeloong(2f) laptop has a SMI video card, need this driver.
this source code is originally from
http://dev.lemote.com/code/linux_loongson
tons of warnings have been fixed, the main warning is:
warning: left shift count >= width of type
have been fixed via the following modification:
drivers/video/smi/smtc2d.h:
#define _F_MASK(f) ((((1 << _F_SIZE(f)) - 1) << _F_START(f))
#define _F_MASK(f) (((1ULL << _F_SIZE(f)) - 1) << _F_START(f))
besides, the coding style is changed to follow the kernel style, and two
non-used header files are removed: sm501hw.h, sm7xxhw.h.
Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
drivers/video/Kconfig | 23 +
drivers/video/Makefile | 1 +
drivers/video/smi/Makefile | 8 +
drivers/video/smi/smtc2d.c | 979 +++++++++++++++++++++++++++++++++++++
drivers/video/smi/smtc2d.h | 530 ++++++++++++++++++++
drivers/video/smi/smtcfb.c | 1141 ++++++++++++++++++++++++++++++++++++++++++++
drivers/video/smi/smtcfb.h | 793 ++++++++++++++++++++++++++++++
7 files changed, 3475 insertions(+), 0 deletions(-)
create mode 100644 drivers/video/smi/Makefile
create mode 100644 drivers/video/smi/smtc2d.c
create mode 100644 drivers/video/smi/smtc2d.h
create mode 100644 drivers/video/smi/smtcfb.c
create mode 100644 drivers/video/smi/smtcfb.h
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index fb19803..ded6807 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1943,6 +1943,29 @@ config FB_S3C2410_DEBUG
Turn on debugging messages. Note that you can set/unset at run time
through sysfs
+config FB_SILICONMOTION
+ bool "Silicon Motion Display Support"
+ depends on FB
+ help
+ Frame Buffer driver for the Silicon Motion serial graphic card.
+
+config FB_SM7XX
+ bool "Silicon Motion SM7XX Frame Buffer Support"
+ depends on FB_SILICONMOTION
+ depends on FB
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ Frame Buffer driver for the Silicon Motion SM7XX serial graphic card.
+
+config FB_SM7XX_ACCEL
+ bool "Siliconmotion Acceleration functions (EXPERIMENTAL)"
+ depends on FB_SM7XX && EXPERIMENTAL
+ help
+ This will compile the Trident frame buffer device with
+ acceleration functions.
+
config FB_SM501
tristate "Silicon Motion SM501 framebuffer support"
depends on FB && MFD_SM501
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 2a998ca..452479f 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -71,6 +71,7 @@ obj-$(CONFIG_FB_P9100) += p9100.o sbuslib.o
obj-$(CONFIG_FB_TCX) += tcx.o sbuslib.o
obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o
obj-$(CONFIG_FB_SGIVW) += sgivwfb.o
+obj-$(CONFIG_FB_SILICONMOTION) += smi/
obj-$(CONFIG_FB_ACORN) += acornfb.o
obj-$(CONFIG_FB_ATARI) += atafb.o c2p_iplan2.o atafb_mfb.o \
atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o
diff --git a/drivers/video/smi/Makefile b/drivers/video/smi/Makefile
new file mode 100644
index 0000000..0058148
--- /dev/null
+++ b/drivers/video/smi/Makefile
@@ -0,0 +1,8 @@
+obj-y += smi.o
+
+smi-y := $(DRIVER_OBJS)
+
+smi-y += smtcfb.o
+
+EXTRA_CFLAGS += -Werror
+
diff --git a/drivers/video/smi/smtc2d.c b/drivers/video/smi/smtc2d.c
new file mode 100644
index 0000000..2a9c3bd
--- /dev/null
+++ b/drivers/video/smi/smtc2d.c
@@ -0,0 +1,979 @@
+/*
+ * smtc2d.c -- Silicon Motion SM501 and SM7xx 2D drawing engine functions.
+ *
+ * Copyright (C) 2006 Silicon Motion Technology Corp.
+ * Author: Boyod boyod.yang@siliconmotion.com.cn
+ *
+ * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Version 0.10.26192.21.01
+ * - Add PowerPC support
+ * - Add 2D support for Lynx -
+ * Verified on 2.6.19.2
+ * Boyod.yang <boyod.yang@siliconmotion.com.cn>
+ */
+
+unsigned char smtc_de_busy;
+
+void SMTC_write2Dreg(unsigned long nOffset, unsigned long nData)
+{
+ writel(nData, smtc_2DBaseAddress + nOffset);
+}
+
+unsigned long SMTC_read2Dreg(unsigned long nOffset)
+{
+ return readl(smtc_2DBaseAddress + nOffset);
+}
+
+void SMTC_write2Ddataport(unsigned long nOffset, unsigned long nData)
+{
+ writel(nData, smtc_2Ddataport + nOffset);
+}
+
+/**********************************************************************
+ *
+ * deInit
+ *
+ * Purpose
+ * Drawing engine initialization.
+ *
+ **********************************************************************/
+
+void deInit(unsigned int nModeWidth, unsigned int nModeHeight,
+ unsigned int bpp)
+{
+ /* Get current power configuration. */
+ unsigned char clock;
+ clock = smtc_seqr(0x21);
+
+ /* initialize global 'mutex lock' variable */
+ smtc_de_busy = 0;
+
+ /* Enable 2D Drawing Engine */
+ smtc_seqw(0x21, clock & 0xF8);
+
+ SMTC_write2Dreg(DE_CLIP_TL,
+ FIELD_VALUE(0, DE_CLIP_TL, TOP, 0) |
+ FIELD_SET(0, DE_CLIP_TL, STATUS, DISABLE) |
+ FIELD_SET(0, DE_CLIP_TL, INHIBIT, OUTSIDE) |
+ FIELD_VALUE(0, DE_CLIP_TL, LEFT, 0));
+
+ if (bpp >= 24) {
+ SMTC_write2Dreg(DE_PITCH,
+ FIELD_VALUE(0, DE_PITCH, DESTINATION,
+ nModeWidth * 3) | FIELD_VALUE(0,
+ DE_PITCH,
+ SOURCE,
+ nModeWidth
+ * 3));
+ } else {
+ SMTC_write2Dreg(DE_PITCH,
+ FIELD_VALUE(0, DE_PITCH, DESTINATION,
+ nModeWidth) | FIELD_VALUE(0,
+ DE_PITCH,
+ SOURCE,
+ nModeWidth));
+ }
+
+ SMTC_write2Dreg(DE_WINDOW_WIDTH,
+ FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+ nModeWidth) | FIELD_VALUE(0,
+ DE_WINDOW_WIDTH,
+ SOURCE,
+ nModeWidth));
+
+ switch (bpp) {
+ case 8:
+ SMTC_write2Dreg(DE_STRETCH_FORMAT,
+ FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY,
+ NORMAL) | FIELD_VALUE(0,
+ DE_STRETCH_FORMAT,
+ PATTERN_Y,
+ 0) |
+ FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X,
+ 0) | FIELD_SET(0, DE_STRETCH_FORMAT,
+ PIXEL_FORMAT,
+ 8) | FIELD_SET(0,
+ DE_STRETCH_FORMAT,
+ ADDRESSING,
+ XY) |
+ FIELD_VALUE(0, DE_STRETCH_FORMAT,
+ SOURCE_HEIGHT, 3));
+ break;
+ case 24:
+ SMTC_write2Dreg(DE_STRETCH_FORMAT,
+ FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY,
+ NORMAL) | FIELD_VALUE(0,
+ DE_STRETCH_FORMAT,
+ PATTERN_Y,
+ 0) |
+ FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X,
+ 0) | FIELD_SET(0, DE_STRETCH_FORMAT,
+ PIXEL_FORMAT,
+ 24) | FIELD_SET(0,
+ DE_STRETCH_FORMAT,
+ ADDRESSING,
+ XY) |
+ FIELD_VALUE(0, DE_STRETCH_FORMAT,
+ SOURCE_HEIGHT, 3));
+ break;
+ case 16:
+ default:
+ SMTC_write2Dreg(DE_STRETCH_FORMAT,
+ FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY,
+ NORMAL) | FIELD_VALUE(0,
+ DE_STRETCH_FORMAT,
+ PATTERN_Y,
+ 0) |
+ FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X,
+ 0) | FIELD_SET(0, DE_STRETCH_FORMAT,
+ PIXEL_FORMAT,
+ 16) | FIELD_SET(0,
+ DE_STRETCH_FORMAT,
+ ADDRESSING,
+ XY) |
+ FIELD_VALUE(0, DE_STRETCH_FORMAT,
+ SOURCE_HEIGHT, 3));
+ break;
+ }
+
+ SMTC_write2Dreg(DE_MASKS,
+ FIELD_VALUE(0, DE_MASKS, BYTE_MASK, 0xFFFF) |
+ FIELD_VALUE(0, DE_MASKS, BIT_MASK, 0xFFFF));
+ SMTC_write2Dreg(DE_COLOR_COMPARE_MASK,
+ FIELD_VALUE(0, DE_COLOR_COMPARE_MASK, MASKS, \
+ 0xFFFFFF));
+ SMTC_write2Dreg(DE_COLOR_COMPARE,
+ FIELD_VALUE(0, DE_COLOR_COMPARE, COLOR, 0xFFFFFF));
+}
+
+void deVerticalLine(unsigned long dst_base,
+ unsigned long dst_pitch,
+ unsigned long nX,
+ unsigned long nY,
+ unsigned long dst_height, unsigned long nColor)
+{
+ deWaitForNotBusy();
+
+ SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
+ FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS,
+ dst_base));
+
+ SMTC_write2Dreg(DE_PITCH,
+ FIELD_VALUE(0, DE_PITCH, DESTINATION, dst_pitch) |
+ FIELD_VALUE(0, DE_PITCH, SOURCE, dst_pitch));
+
+ SMTC_write2Dreg(DE_WINDOW_WIDTH,
+ FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+ dst_pitch) | FIELD_VALUE(0, DE_WINDOW_WIDTH,
+ SOURCE,
+ dst_pitch));
+
+ SMTC_write2Dreg(DE_FOREGROUND,
+ FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
+
+ SMTC_write2Dreg(DE_DESTINATION,
+ FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+ FIELD_VALUE(0, DE_DESTINATION, X, nX) |
+ FIELD_VALUE(0, DE_DESTINATION, Y, nY));
+
+ SMTC_write2Dreg(DE_DIMENSION,
+ FIELD_VALUE(0, DE_DIMENSION, X, 1) |
+ FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height));
+
+ SMTC_write2Dreg(DE_CONTROL,
+ FIELD_SET(0, DE_CONTROL, STATUS, START) |
+ FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) |
+ FIELD_SET(0, DE_CONTROL, MAJOR, Y) |
+ FIELD_SET(0, DE_CONTROL, STEP_X, NEGATIVE) |
+ FIELD_SET(0, DE_CONTROL, STEP_Y, POSITIVE) |
+ FIELD_SET(0, DE_CONTROL, LAST_PIXEL, OFF) |
+ FIELD_SET(0, DE_CONTROL, COMMAND, SHORT_STROKE) |
+ FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
+ FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C));
+
+ smtc_de_busy = 1;
+}
+
+void deHorizontalLine(unsigned long dst_base,
+ unsigned long dst_pitch,
+ unsigned long nX,
+ unsigned long nY,
+ unsigned long dst_width, unsigned long nColor)
+{
+ deWaitForNotBusy();
+
+ SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
+ FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS,
+ dst_base));
+
+ SMTC_write2Dreg(DE_PITCH,
+ FIELD_VALUE(0, DE_PITCH, DESTINATION, dst_pitch) |
+ FIELD_VALUE(0, DE_PITCH, SOURCE, dst_pitch));
+
+ SMTC_write2Dreg(DE_WINDOW_WIDTH,
+ FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+ dst_pitch) | FIELD_VALUE(0, DE_WINDOW_WIDTH,
+ SOURCE,
+ dst_pitch));
+ SMTC_write2Dreg(DE_FOREGROUND,
+ FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
+ SMTC_write2Dreg(DE_DESTINATION,
+ FIELD_SET(0, DE_DESTINATION, WRAP,
+ DISABLE) | FIELD_VALUE(0, DE_DESTINATION, X,
+ nX) | FIELD_VALUE(0,
+ DE_DESTINATION,
+ Y,
+ nY));
+ SMTC_write2Dreg(DE_DIMENSION,
+ FIELD_VALUE(0, DE_DIMENSION, X,
+ dst_width) | FIELD_VALUE(0, DE_DIMENSION,
+ Y_ET, 1));
+ SMTC_write2Dreg(DE_CONTROL,
+ FIELD_SET(0, DE_CONTROL, STATUS, START) | FIELD_SET(0,
+ DE_CONTROL,
+ DIRECTION,
+ RIGHT_TO_LEFT)
+ | FIELD_SET(0, DE_CONTROL, MAJOR, X) | FIELD_SET(0,
+ DE_CONTROL,
+ STEP_X,
+ POSITIVE)
+ | FIELD_SET(0, DE_CONTROL, STEP_Y,
+ NEGATIVE) | FIELD_SET(0, DE_CONTROL,
+ LAST_PIXEL,
+ OFF) | FIELD_SET(0,
+ DE_CONTROL,
+ COMMAND,
+ SHORT_STROKE)
+ | FIELD_SET(0, DE_CONTROL, ROP_SELECT,
+ ROP2) | FIELD_VALUE(0, DE_CONTROL, ROP,
+ 0x0C));
+
+ smtc_de_busy = 1;
+}
+
+void deLine(unsigned long dst_base,
+ unsigned long dst_pitch,
+ unsigned long nX1,
+ unsigned long nY1,
+ unsigned long nX2, unsigned long nY2, unsigned long nColor)
+{
+ unsigned long nCommand =
+ FIELD_SET(0, DE_CONTROL, STATUS, START) |
+ FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) |
+ FIELD_SET(0, DE_CONTROL, MAJOR, X) |
+ FIELD_SET(0, DE_CONTROL, STEP_X, POSITIVE) |
+ FIELD_SET(0, DE_CONTROL, STEP_Y, POSITIVE) |
+ FIELD_SET(0, DE_CONTROL, LAST_PIXEL, OFF) |
+ FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
+ FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C);
+ unsigned long DeltaX;
+ unsigned long DeltaY;
+
+ /* Calculate delta X */
+ if (nX1 <= nX2)
+ DeltaX = nX2 - nX1;
+ else {
+ DeltaX = nX1 - nX2;
+ nCommand = FIELD_SET(nCommand, DE_CONTROL, STEP_X, NEGATIVE);
+ }
+
+ /* Calculate delta Y */
+ if (nY1 <= nY2)
+ DeltaY = nY2 - nY1;
+ else {
+ DeltaY = nY1 - nY2;
+ nCommand = FIELD_SET(nCommand, DE_CONTROL, STEP_Y, NEGATIVE);
+ }
+
+ /* Determine the major axis */
+ if (DeltaX < DeltaY)
+ nCommand = FIELD_SET(nCommand, DE_CONTROL, MAJOR, Y);
+
+ /* Vertical line? */
+ if (nX1 == nX2)
+ deVerticalLine(dst_base, dst_pitch, nX1, nY1, DeltaY, nColor);
+
+ /* Horizontal line? */
+ else if (nY1 == nY2)
+ deHorizontalLine(dst_base, dst_pitch, nX1, nY1, \
+ DeltaX, nColor);
+
+ /* Diagonal line? */
+ else if (DeltaX == DeltaY) {
+ deWaitForNotBusy();
+
+ SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
+ FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE,
+ ADDRESS, dst_base));
+
+ SMTC_write2Dreg(DE_PITCH,
+ FIELD_VALUE(0, DE_PITCH, DESTINATION,
+ dst_pitch) | FIELD_VALUE(0,
+ DE_PITCH,
+ SOURCE,
+ dst_pitch));
+
+ SMTC_write2Dreg(DE_WINDOW_WIDTH,
+ FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+ dst_pitch) | FIELD_VALUE(0,
+ DE_WINDOW_WIDTH,
+ SOURCE,
+ dst_pitch));
+
+ SMTC_write2Dreg(DE_FOREGROUND,
+ FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
+
+ SMTC_write2Dreg(DE_DESTINATION,
+ FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+ FIELD_VALUE(0, DE_DESTINATION, X, 1) |
+ FIELD_VALUE(0, DE_DESTINATION, Y, nY1));
+
+ SMTC_write2Dreg(DE_DIMENSION,
+ FIELD_VALUE(0, DE_DIMENSION, X, 1) |
+ FIELD_VALUE(0, DE_DIMENSION, Y_ET, DeltaX));
+
+ SMTC_write2Dreg(DE_CONTROL,
+ FIELD_SET(nCommand, DE_CONTROL, COMMAND,
+ SHORT_STROKE));
+ }
+
+ /* Generic line */
+ else {
+ unsigned int k1, k2, et, w;
+ if (DeltaX < DeltaY) {
+ k1 = 2 * DeltaX;
+ et = k1 - DeltaY;
+ k2 = et - DeltaY;
+ w = DeltaY + 1;
+ } else {
+ k1 = 2 * DeltaY;
+ et = k1 - DeltaX;
+ k2 = et - DeltaX;
+ w = DeltaX + 1;
+ }
+
+ deWaitForNotBusy();
+
+ SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
+ FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE,
+ ADDRESS, dst_base));
+
+ SMTC_write2Dreg(DE_PITCH,
+ FIELD_VALUE(0, DE_PITCH, DESTINATION,
+ dst_pitch) | FIELD_VALUE(0,
+ DE_PITCH,
+ SOURCE,
+ dst_pitch));
+
+ SMTC_write2Dreg(DE_WINDOW_WIDTH,
+ FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+ dst_pitch) | FIELD_VALUE(0,
+ DE_WINDOW_WIDTH,
+ SOURCE,
+ dst_pitch));
+
+ SMTC_write2Dreg(DE_FOREGROUND,
+ FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
+
+ SMTC_write2Dreg(DE_SOURCE,
+ FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
+ FIELD_VALUE(0, DE_SOURCE, X_K1, k1) |
+ FIELD_VALUE(0, DE_SOURCE, Y_K2, k2));
+
+ SMTC_write2Dreg(DE_DESTINATION,
+ FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+ FIELD_VALUE(0, DE_DESTINATION, X, nX1) |
+ FIELD_VALUE(0, DE_DESTINATION, Y, nY1));
+
+ SMTC_write2Dreg(DE_DIMENSION,
+ FIELD_VALUE(0, DE_DIMENSION, X, w) |
+ FIELD_VALUE(0, DE_DIMENSION, Y_ET, et));
+
+ SMTC_write2Dreg(DE_CONTROL,
+ FIELD_SET(nCommand, DE_CONTROL, COMMAND,
+ LINE_DRAW));
+ }
+
+ smtc_de_busy = 1;
+}
+
+void deFillRect(unsigned long dst_base,
+ unsigned long dst_pitch,
+ unsigned long dst_X,
+ unsigned long dst_Y,
+ unsigned long dst_width,
+ unsigned long dst_height, unsigned long nColor)
+{
+ deWaitForNotBusy();
+
+ SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
+ FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS,
+ dst_base));
+
+ if (dst_pitch) {
+ SMTC_write2Dreg(DE_PITCH,
+ FIELD_VALUE(0, DE_PITCH, DESTINATION,
+ dst_pitch) | FIELD_VALUE(0,
+ DE_PITCH,
+ SOURCE,
+ dst_pitch));
+
+ SMTC_write2Dreg(DE_WINDOW_WIDTH,
+ FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+ dst_pitch) | FIELD_VALUE(0,
+ DE_WINDOW_WIDTH,
+ SOURCE,
+ dst_pitch));
+ }
+
+ SMTC_write2Dreg(DE_FOREGROUND,
+ FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
+
+ SMTC_write2Dreg(DE_DESTINATION,
+ FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+ FIELD_VALUE(0, DE_DESTINATION, X, dst_X) |
+ FIELD_VALUE(0, DE_DESTINATION, Y, dst_Y));
+
+ SMTC_write2Dreg(DE_DIMENSION,
+ FIELD_VALUE(0, DE_DIMENSION, X, dst_width) |
+ FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height));
+
+ SMTC_write2Dreg(DE_CONTROL,
+ FIELD_SET(0, DE_CONTROL, STATUS, START) |
+ FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) |
+ FIELD_SET(0, DE_CONTROL, LAST_PIXEL, OFF) |
+ FIELD_SET(0, DE_CONTROL, COMMAND, RECTANGLE_FILL) |
+ FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
+ FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C));
+
+ smtc_de_busy = 1;
+}
+
+/**********************************************************************
+ *
+ * deRotatePattern
+ *
+ * Purpose
+ * Rotate the given pattern if necessary
+ *
+ * Parameters
+ * [in]
+ * pPattern - Pointer to DE_SURFACE structure containing
+ * pattern attributes
+ * patternX - X position (0-7) of pattern origin
+ * patternY - Y position (0-7) of pattern origin
+ *
+ * [out]
+ * pattern_dstaddr - Pointer to pre-allocated buffer containing
+ * rotated pattern
+ *
+ **********************************************************************/
+void deRotatePattern(unsigned char *pattern_dstaddr,
+ unsigned long pattern_src_addr,
+ unsigned long pattern_BPP,
+ unsigned long pattern_stride, int patternX, int patternY)
+{
+ unsigned int i;
+ unsigned long pattern[PATTERN_WIDTH * PATTERN_HEIGHT];
+ unsigned int x, y;
+ unsigned char *pjPatByte;
+
+ if (pattern_dstaddr != NULL) {
+ deWaitForNotBusy();
+
+ if (patternX || patternY) {
+ /* Rotate pattern */
+ pjPatByte = (unsigned char *)pattern;
+
+ switch (pattern_BPP) {
+ case 8:
+ {
+ for (y = 0; y < 8; y++) {
+ unsigned char *pjBuffer =
+ pattern_dstaddr +
+ ((patternY + y) & 7) * 8;
+ for (x = 0; x < 8; x++) {
+ pjBuffer[(patternX +
+ x) & 7] =
+ pjPatByte[x];
+ }
+ pjPatByte += pattern_stride;
+ }
+ break;
+ }
+
+ case 16:
+ {
+ for (y = 0; y < 8; y++) {
+ unsigned short *pjBuffer =
+ (unsigned short *)
+ pattern_dstaddr +
+ ((patternY + y) & 7) * 8;
+ for (x = 0; x < 8; x++) {
+ pjBuffer[(patternX +
+ x) & 7] =
+ ((unsigned short *)
+ pjPatByte)[x];
+ }
+ pjPatByte += pattern_stride;
+ }
+ break;
+ }
+
+ case 32:
+ {
+ for (y = 0; y < 8; y++) {
+ unsigned long *pjBuffer =
+ (unsigned long *)
+ pattern_dstaddr +
+ ((patternY + y) & 7) * 8;
+ for (x = 0; x < 8; x++) {
+ pjBuffer[(patternX +
+ x) & 7] =
+ ((unsigned long *)
+ pjPatByte)[x];
+ }
+ pjPatByte += pattern_stride;
+ }
+ break;
+ }
+ }
+ } else {
+ /*Don't rotate,just copy pattern into pattern_dstaddr*/
+ for (i = 0; i < (pattern_BPP * 2); i++) {
+ ((unsigned long *)pattern_dstaddr)[i] =
+ pattern[i];
+ }
+ }
+
+ }
+}
+
+/**********************************************************************
+ *
+ * deCopy
+ *
+ * Purpose
+ * Copy a rectangular area of the source surface to a destination surface
+ *
+ * Remarks
+ * Source bitmap must have the same color depth (BPP) as the destination
+ * bitmap.
+ *
+**********************************************************************/
+void deCopy(unsigned long dst_base,
+ unsigned long dst_pitch,
+ unsigned long dst_BPP,
+ unsigned long dst_X,
+ unsigned long dst_Y,
+ unsigned long dst_width,
+ unsigned long dst_height,
+ unsigned long src_base,
+ unsigned long src_pitch,
+ unsigned long src_X,
+ unsigned long src_Y, pTransparent pTransp, unsigned char nROP2)
+{
+ unsigned long nDirection = 0;
+ unsigned long nTransparent = 0;
+ /* Direction of ROP2 operation:
+ * 1 = Left to Right,
+ * (-1) = Right to Left
+ */
+ unsigned long opSign = 1;
+ /* xWidth is in pixels */
+ unsigned long xWidth = 192 / (dst_BPP / 8);
+ unsigned long de_ctrl = 0;
+
+ deWaitForNotBusy();
+
+ SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
+ FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS,
+ dst_base));
+
+ SMTC_write2Dreg(DE_WINDOW_SOURCE_BASE,
+ FIELD_VALUE(0, DE_WINDOW_SOURCE_BASE, ADDRESS,
+ src_base));
+
+ if (dst_pitch && src_pitch) {
+ SMTC_write2Dreg(DE_PITCH,
+ FIELD_VALUE(0, DE_PITCH, DESTINATION,
+ dst_pitch) | FIELD_VALUE(0,
+ DE_PITCH,
+ SOURCE,
+ src_pitch));
+
+ SMTC_write2Dreg(DE_WINDOW_WIDTH,
+ FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+ dst_pitch) | FIELD_VALUE(0,
+ DE_WINDOW_WIDTH,
+ SOURCE,
+ src_pitch));
+ }
+
+ /* Set transparent bits if necessary */
+ if (pTransp != NULL) {
+ nTransparent =
+ pTransp->match | pTransp->select | pTransp->control;
+
+ /* Set color compare register */
+ SMTC_write2Dreg(DE_COLOR_COMPARE,
+ FIELD_VALUE(0, DE_COLOR_COMPARE, COLOR,
+ pTransp->color));
+ }
+
+ /* Determine direction of operation */
+ if (src_Y < dst_Y) {
+ /* +----------+
+ |S |
+ | +----------+
+ | | | |
+ | | | |
+ +---|------+ |
+ | D |
+ +----------+ */
+
+ nDirection = BOTTOM_TO_TOP;
+ } else if (src_Y > dst_Y) {
+ /* +----------+
+ |D |
+ | +----------+
+ | | | |
+ | | | |
+ +---|------+ |
+ | S |
+ +----------+ */
+
+ nDirection = TOP_TO_BOTTOM;
+ } else {
+ /* src_Y == dst_Y */
+
+ if (src_X <= dst_X) {
+ /* +------+---+------+
+ |S | | D|
+ | | | |
+ | | | |
+ | | | |
+ +------+---+------+ */
+
+ nDirection = RIGHT_TO_LEFT;
+ } else {
+ /* src_X > dst_X */
+
+ /* +------+---+------+
+ |D | | S|
+ | | | |
+ | | | |
+ | | | |
+ +------+---+------+ */
+
+ nDirection = LEFT_TO_RIGHT;
+ }
+ }
+
+ if ((nDirection == BOTTOM_TO_TOP) || (nDirection == RIGHT_TO_LEFT)) {
+ src_X += dst_width - 1;
+ src_Y += dst_height - 1;
+ dst_X += dst_width - 1;
+ dst_Y += dst_height - 1;
+ opSign = (-1);
+ }
+
+ if (dst_BPP >= 24) {
+ src_X *= 3;
+ src_Y *= 3;
+ dst_X *= 3;
+ dst_Y *= 3;
+ dst_width *= 3;
+ if ((nDirection == BOTTOM_TO_TOP)
+ || (nDirection == RIGHT_TO_LEFT)) {
+ src_X += 2;
+ dst_X += 2;
+ }
+ }
+
+ /* Workaround for 192 byte hw bug */
+ if ((nROP2 != 0x0C) && ((dst_width * (dst_BPP / 8)) >= 192)) {
+ /*
+ * Perform the ROP2 operation in chunks of (xWidth *
+ * dst_height)
+ */
+ while (1) {
+ deWaitForNotBusy();
+
+ SMTC_write2Dreg(DE_SOURCE,
+ FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
+ FIELD_VALUE(0, DE_SOURCE, X_K1, src_X) |
+ FIELD_VALUE(0, DE_SOURCE, Y_K2, src_Y));
+
+ SMTC_write2Dreg(DE_DESTINATION,
+ FIELD_SET(0, DE_DESTINATION, WRAP,
+ DISABLE) | FIELD_VALUE(0,
+ DE_DESTINATION,
+ X,
+ dst_X)
+ | FIELD_VALUE(0, DE_DESTINATION, Y,
+ dst_Y));
+
+ SMTC_write2Dreg(DE_DIMENSION,
+ FIELD_VALUE(0, DE_DIMENSION, X,
+ xWidth) | FIELD_VALUE(0,
+ DE_DIMENSION,
+ Y_ET,
+ dst_height));
+
+ de_ctrl =
+ FIELD_VALUE(0, DE_CONTROL, ROP,
+ nROP2) | nTransparent | FIELD_SET(0,
+ DE_CONTROL,
+ ROP_SELECT,
+ ROP2)
+ | FIELD_SET(0, DE_CONTROL, COMMAND,
+ BITBLT) | ((nDirection ==
+ 1) ? FIELD_SET(0,
+ DE_CONTROL,
+ DIRECTION,
+ RIGHT_TO_LEFT)
+ : FIELD_SET(0, DE_CONTROL,
+ DIRECTION,
+ LEFT_TO_RIGHT)) |
+ FIELD_SET(0, DE_CONTROL, STATUS, START);
+
+ SMTC_write2Dreg(DE_CONTROL, de_ctrl);
+
+ src_X += (opSign * xWidth);
+ dst_X += (opSign * xWidth);
+ dst_width -= xWidth;
+
+ if (dst_width <= 0) {
+ /* ROP2 operation is complete */
+ break;
+ }
+
+ if (xWidth > dst_width)
+ xWidth = dst_width;
+ }
+ } else {
+ deWaitForNotBusy();
+ SMTC_write2Dreg(DE_SOURCE,
+ FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
+ FIELD_VALUE(0, DE_SOURCE, X_K1, src_X) |
+ FIELD_VALUE(0, DE_SOURCE, Y_K2, src_Y));
+
+ SMTC_write2Dreg(DE_DESTINATION,
+ FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+ FIELD_VALUE(0, DE_DESTINATION, X, dst_X) |
+ FIELD_VALUE(0, DE_DESTINATION, Y, dst_Y));
+
+ SMTC_write2Dreg(DE_DIMENSION,
+ FIELD_VALUE(0, DE_DIMENSION, X, dst_width) |
+ FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height));
+
+ de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, nROP2) |
+ nTransparent |
+ FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
+ FIELD_SET(0, DE_CONTROL, COMMAND, BITBLT) |
+ ((nDirection == 1) ? FIELD_SET(0, DE_CONTROL, DIRECTION,
+ RIGHT_TO_LEFT)
+ : FIELD_SET(0, DE_CONTROL, DIRECTION,
+ LEFT_TO_RIGHT)) | FIELD_SET(0, DE_CONTROL,
+ STATUS, START);
+ SMTC_write2Dreg(DE_CONTROL, de_ctrl);
+ }
+
+ smtc_de_busy = 1;
+}
+
+/*
+ * This function sets the pixel format that will apply to the 2D Engine.
+ */
+void deSetPixelFormat(unsigned long bpp)
+{
+ unsigned long de_format;
+
+ de_format = SMTC_read2Dreg(DE_STRETCH_FORMAT);
+
+ switch (bpp) {
+ case 8:
+ de_format =
+ FIELD_SET(de_format, DE_STRETCH_FORMAT, PIXEL_FORMAT, 8);
+ break;
+ default:
+ case 16:
+ de_format =
+ FIELD_SET(de_format, DE_STRETCH_FORMAT, PIXEL_FORMAT, 16);
+ break;
+ case 32:
+ de_format =
+ FIELD_SET(de_format, DE_STRETCH_FORMAT, PIXEL_FORMAT, 32);
+ break;
+ }
+
+ SMTC_write2Dreg(DE_STRETCH_FORMAT, de_format);
+}
+
+/*
+ * System memory to Video memory monochrome expansion.
+ *
+ * Source is monochrome image in system memory. This function expands the
+ * monochrome data to color image in video memory.
+ */
+
+long deSystemMem2VideoMemMonoBlt(const char *pSrcbuf,
+ long srcDelta,
+ unsigned long startBit,
+ unsigned long dBase,
+ unsigned long dPitch,
+ unsigned long bpp,
+ unsigned long dx, unsigned long dy,
+ unsigned long width, unsigned long height,
+ unsigned long fColor,
+ unsigned long bColor,
+ unsigned long rop2) {
+ unsigned long bytePerPixel;
+ unsigned long ulBytesPerScan;
+ unsigned long ul4BytesPerScan;
+ unsigned long ulBytesRemain;
+ unsigned long de_ctrl = 0;
+ unsigned char ajRemain[4];
+ long i, j;
+
+ bytePerPixel = bpp / 8;
+
+ /* Just make sure the start bit is within legal range */
+ startBit &= 7;
+
+ ulBytesPerScan = (width + startBit + 7) / 8;
+ ul4BytesPerScan = ulBytesPerScan & ~3;
+ ulBytesRemain = ulBytesPerScan & 3;
+
+ if (smtc_de_busy)
+ deWaitForNotBusy();
+
+ /*
+ * 2D Source Base. Use 0 for HOST Blt.
+ */
+
+ SMTC_write2Dreg(DE_WINDOW_SOURCE_BASE, 0);
+
+ /*
+ * 2D Destination Base.
+ *
+ * It is an address offset (128 bit aligned) from the beginning of
+ * frame buffer.
+ */
+
+ SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE, dBase);
+
+ if (dPitch) {
+
+ /*
+ * Program pitch (distance between the 1st points of two
+ * adjacent lines).
+ *
+ * Note that input pitch is BYTE value, but the 2D Pitch
+ * register uses pixel values. Need Byte to pixel convertion.
+ */
+
+ SMTC_write2Dreg(DE_PITCH,
+ FIELD_VALUE(0, DE_PITCH, DESTINATION,
+ dPitch /
+ bytePerPixel) | FIELD_VALUE(0,
+ DE_PITCH,
+ SOURCE,
+ dPitch /
+ bytePerPixel));
+
+ /* Screen Window width in Pixels.
+ *
+ * 2D engine uses this value to calculate the linear address in
+ * frame buffer for a given point.
+ */
+
+ SMTC_write2Dreg(DE_WINDOW_WIDTH,
+ FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
+ (dPitch /
+ bytePerPixel)) | FIELD_VALUE(0,
+ DE_WINDOW_WIDTH,
+ SOURCE,
+ (dPitch
+ /
+ bytePerPixel)));
+ }
+ /* Note: For 2D Source in Host Write, only X_K1 field is needed, and
+ * Y_K2 field is not used. For mono bitmap, use startBit for X_K1.
+ */
+
+ SMTC_write2Dreg(DE_SOURCE,
+ FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
+ FIELD_VALUE(0, DE_SOURCE, X_K1, startBit) |
+ FIELD_VALUE(0, DE_SOURCE, Y_K2, 0));
+
+ SMTC_write2Dreg(DE_DESTINATION,
+ FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+ FIELD_VALUE(0, DE_DESTINATION, X, dx) |
+ FIELD_VALUE(0, DE_DESTINATION, Y, dy));
+
+ SMTC_write2Dreg(DE_DIMENSION,
+ FIELD_VALUE(0, DE_DIMENSION, X, width) |
+ FIELD_VALUE(0, DE_DIMENSION, Y_ET, height));
+
+ SMTC_write2Dreg(DE_FOREGROUND, fColor);
+ SMTC_write2Dreg(DE_BACKGROUND, bColor);
+
+ if (bpp)
+ deSetPixelFormat(bpp);
+ /* Set the pixel format of the destination */
+
+ de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, rop2) |
+ FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
+ FIELD_SET(0, DE_CONTROL, COMMAND, HOST_WRITE) |
+ FIELD_SET(0, DE_CONTROL, HOST, MONO) |
+ FIELD_SET(0, DE_CONTROL, STATUS, START);
+
+ SMTC_write2Dreg(DE_CONTROL, de_ctrl | deGetTransparency());
+
+ /* Write MONO data (line by line) to 2D Engine data port */
+ for (i = 0; i < height; i++) {
+ /* For each line, send the data in chunks of 4 bytes */
+ for (j = 0; j < (ul4BytesPerScan / 4); j++)
+ SMTC_write2Ddataport(0,
+ *(unsigned long *)(pSrcbuf +
+ (j * 4)));
+
+ if (ulBytesRemain) {
+ memcpy(ajRemain, pSrcbuf + ul4BytesPerScan,
+ ulBytesRemain);
+ SMTC_write2Ddataport(0, *(unsigned long *)ajRemain);
+ }
+
+ pSrcbuf += srcDelta;
+ }
+ smtc_de_busy = 1;
+
+ return 0;
+}
+
+/*
+ * This function gets the transparency status from DE_CONTROL register.
+ * It returns a double word with the transparent fields properly set,
+ * while other fields are 0.
+ */
+unsigned long deGetTransparency(void)
+{
+ unsigned long de_ctrl;
+
+ de_ctrl = SMTC_read2Dreg(DE_CONTROL);
+
+ de_ctrl &=
+ FIELD_MASK(DE_CONTROL_TRANSPARENCY_MATCH) |
+ FIELD_MASK(DE_CONTROL_TRANSPARENCY_SELECT) |
+ FIELD_MASK(DE_CONTROL_TRANSPARENCY);
+
+ return de_ctrl;
+}
diff --git a/drivers/video/smi/smtc2d.h b/drivers/video/smi/smtc2d.h
new file mode 100644
index 0000000..3cd640c
--- /dev/null
+++ b/drivers/video/smi/smtc2d.h
@@ -0,0 +1,530 @@
+/*
+ * smtc2d.h -- Silicon Motion SM501 and SM7xx 2D drawing engine functions.
+ *
+ * Copyright (C) 2006 Silicon Motion Technology Corp.
+ * Author: Ge Wang, gewang@siliconmotion.com
+ *
+ * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* Internal macros */
+
+#define _F_START(f) (0 ? f)
+#define _F_END(f) (1 ? f)
+#define _F_SIZE(f) (1 + _F_END(f) - _F_START(f))
+#define _F_MASK(f) (((1ULL << _F_SIZE(f)) - 1) << _F_START(f))
+#define _F_NORMALIZE(v, f) (((v) & _F_MASK(f)) >> _F_START(f))
+#define _F_DENORMALIZE(v, f) (((v) << _F_START(f)) & _F_MASK(f))
+
+/* Global macros */
+
+#define FIELD_GET(x, reg, field) \
+( \
+ _F_NORMALIZE((x), reg ## _ ## field) \
+)
+
+#define FIELD_SET(x, reg, field, value) \
+( \
+ (x & ~_F_MASK(reg ## _ ## field)) \
+ | _F_DENORMALIZE(reg ## _ ## field ## _ ## value, reg ## _ ## field) \
+)
+
+#define FIELD_VALUE(x, reg, field, value) \
+( \
+ (x & ~_F_MASK(reg ## _ ## field)) \
+ | _F_DENORMALIZE(value, reg ## _ ## field) \
+)
+
+#define FIELD_CLEAR(reg, field) \
+( \
+ ~_F_MASK(reg ## _ ## field) \
+)
+
+/* Field Macros */
+
+#define FIELD_START(field) (0 ? field)
+#define FIELD_END(field) (1 ? field)
+#define FIELD_SIZE(field) \
+ (1 + FIELD_END(field) - FIELD_START(field))
+
+#define FIELD_MASK(field) \
+ (((1 << (FIELD_SIZE(field)-1)) \
+ | ((1 << (FIELD_SIZE(field)-1)) - 1)) \
+ << FIELD_START(field))
+
+#define FIELD_NORMALIZE(reg, field) \
+ (((reg) & FIELD_MASK(field)) >> FIELD_START(field))
+
+#define FIELD_DENORMALIZE(field, value) \
+ (((value) << FIELD_START(field)) & FIELD_MASK(field))
+
+#define FIELD_INIT(reg, field, value) \
+ FIELD_DENORMALIZE(reg ## _ ## field, \
+ reg ## _ ## field ## _ ## value)
+
+#define FIELD_INIT_VAL(reg, field, value) \
+ (FIELD_DENORMALIZE(reg ## _ ## field, value))
+
+#define FIELD_VAL_SET(x, r, f, v) ({ \
+ x = (x & ~FIELD_MASK(r ## _ ## f)) \
+ | FIELD_DENORMALIZE(r ## _ ## f, r ## _ ## f ## _ ## v) \
+})
+
+#define RGB(r, g, b) ((unsigned long)(((r) << 16) | ((g) << 8) | (b)))
+
+/* Transparent info definition */
+typedef struct {
+ unsigned long match; /* Matching pixel is OPAQUE/TRANSPARENT */
+ unsigned long select; /* Transparency controlled by SRC/DST */
+ unsigned long control; /* ENABLE/DISABLE transparency */
+ unsigned long color; /* Transparent color */
+} Transparent, *pTransparent;
+
+#define PIXEL_DEPTH_1_BP 0 /* 1 bit per pixel */
+#define PIXEL_DEPTH_8_BPP 1 /* 8 bits per pixel */
+#define PIXEL_DEPTH_16_BPP 2 /* 16 bits per pixel */
+#define PIXEL_DEPTH_32_BPP 3 /* 32 bits per pixel */
+#define PIXEL_DEPTH_YUV422 8 /* 16 bits per pixel YUV422 */
+#define PIXEL_DEPTH_YUV420 9 /* 16 bits per pixel YUV420 */
+
+#define PATTERN_WIDTH 8
+#define PATTERN_HEIGHT 8
+
+#define TOP_TO_BOTTOM 0
+#define BOTTOM_TO_TOP 1
+#define RIGHT_TO_LEFT BOTTOM_TO_TOP
+#define LEFT_TO_RIGHT TOP_TO_BOTTOM
+
+/* Constants used in Transparent structure */
+#define MATCH_OPAQUE 0x00000000
+#define MATCH_TRANSPARENT 0x00000400
+#define SOURCE 0x00000000
+#define DESTINATION 0x00000200
+
+/* 2D registers. */
+
+#define DE_SOURCE 0x000000
+#define DE_SOURCE_WRAP 31 : 31
+#define DE_SOURCE_WRAP_DISABLE 0
+#define DE_SOURCE_WRAP_ENABLE 1
+#define DE_SOURCE_X_K1 29 : 16
+#define DE_SOURCE_Y_K2 15 : 0
+
+#define DE_DESTINATION 0x000004
+#define DE_DESTINATION_WRAP 31 : 31
+#define DE_DESTINATION_WRAP_DISABLE 0
+#define DE_DESTINATION_WRAP_ENABLE 1
+#define DE_DESTINATION_X 28 : 16
+#define DE_DESTINATION_Y 15 : 0
+
+#define DE_DIMENSION 0x000008
+#define DE_DIMENSION_X 28 : 16
+#define DE_DIMENSION_Y_ET 15 : 0
+
+#define DE_CONTROL 0x00000C
+#define DE_CONTROL_STATUS 31 : 31
+#define DE_CONTROL_STATUS_STOP 0
+#define DE_CONTROL_STATUS_START 1
+#define DE_CONTROL_PATTERN 30 : 30
+#define DE_CONTROL_PATTERN_MONO 0
+#define DE_CONTROL_PATTERN_COLOR 1
+#define DE_CONTROL_UPDATE_DESTINATION_X 29 : 29
+#define DE_CONTROL_UPDATE_DESTINATION_X_DISABLE 0
+#define DE_CONTROL_UPDATE_DESTINATION_X_ENABLE 1
+#define DE_CONTROL_QUICK_START 28 : 28
+#define DE_CONTROL_QUICK_START_DISABLE 0
+#define DE_CONTROL_QUICK_START_ENABLE 1
+#define DE_CONTROL_DIRECTION 27 : 27
+#define DE_CONTROL_DIRECTION_LEFT_TO_RIGHT 0
+#define DE_CONTROL_DIRECTION_RIGHT_TO_LEFT 1
+#define DE_CONTROL_MAJOR 26 : 26
+#define DE_CONTROL_MAJOR_X 0
+#define DE_CONTROL_MAJOR_Y 1
+#define DE_CONTROL_STEP_X 25 : 25
+#define DE_CONTROL_STEP_X_POSITIVE 1
+#define DE_CONTROL_STEP_X_NEGATIVE 0
+#define DE_CONTROL_STEP_Y 24 : 24
+#define DE_CONTROL_STEP_Y_POSITIVE 1
+#define DE_CONTROL_STEP_Y_NEGATIVE 0
+#define DE_CONTROL_STRETCH 23 : 23
+#define DE_CONTROL_STRETCH_DISABLE 0
+#define DE_CONTROL_STRETCH_ENABLE 1
+#define DE_CONTROL_HOST 22 : 22
+#define DE_CONTROL_HOST_COLOR 0
+#define DE_CONTROL_HOST_MONO 1
+#define DE_CONTROL_LAST_PIXEL 21 : 21
+#define DE_CONTROL_LAST_PIXEL_OFF 0
+#define DE_CONTROL_LAST_PIXEL_ON 1
+#define DE_CONTROL_COMMAND 20 : 16
+#define DE_CONTROL_COMMAND_BITBLT 0
+#define DE_CONTROL_COMMAND_RECTANGLE_FILL 1
+#define DE_CONTROL_COMMAND_DE_TILE 2
+#define DE_CONTROL_COMMAND_TRAPEZOID_FILL 3
+#define DE_CONTROL_COMMAND_ALPHA_BLEND 4
+#define DE_CONTROL_COMMAND_RLE_STRIP 5
+#define DE_CONTROL_COMMAND_SHORT_STROKE 6
+#define DE_CONTROL_COMMAND_LINE_DRAW 7
+#define DE_CONTROL_COMMAND_HOST_WRITE 8
+#define DE_CONTROL_COMMAND_HOST_READ 9
+#define DE_CONTROL_COMMAND_HOST_WRITE_BOTTOM_UP 10
+#define DE_CONTROL_COMMAND_ROTATE 11
+#define DE_CONTROL_COMMAND_FONT 12
+#define DE_CONTROL_COMMAND_TEXTURE_LOAD 15
+#define DE_CONTROL_ROP_SELECT 15 : 15
+#define DE_CONTROL_ROP_SELECT_ROP3 0
+#define DE_CONTROL_ROP_SELECT_ROP2 1
+#define DE_CONTROL_ROP2_SOURCE 14 : 14
+#define DE_CONTROL_ROP2_SOURCE_BITMAP 0
+#define DE_CONTROL_ROP2_SOURCE_PATTERN 1
+#define DE_CONTROL_MONO_DATA 13 : 12
+#define DE_CONTROL_MONO_DATA_NOT_PACKED 0
+#define DE_CONTROL_MONO_DATA_8_PACKED 1
+#define DE_CONTROL_MONO_DATA_16_PACKED 2
+#define DE_CONTROL_MONO_DATA_32_PACKED 3
+#define DE_CONTROL_REPEAT_ROTATE 11 : 11
+#define DE_CONTROL_REPEAT_ROTATE_DISABLE 0
+#define DE_CONTROL_REPEAT_ROTATE_ENABLE 1
+#define DE_CONTROL_TRANSPARENCY_MATCH 10 : 10
+#define DE_CONTROL_TRANSPARENCY_MATCH_OPAQUE 0
+#define DE_CONTROL_TRANSPARENCY_MATCH_TRANSPARENT 1
+#define DE_CONTROL_TRANSPARENCY_SELECT 9 : 9
+#define DE_CONTROL_TRANSPARENCY_SELECT_SOURCE 0
+#define DE_CONTROL_TRANSPARENCY_SELECT_DESTINATION 1
+#define DE_CONTROL_TRANSPARENCY 8 : 8
+#define DE_CONTROL_TRANSPARENCY_DISABLE 0
+#define DE_CONTROL_TRANSPARENCY_ENABLE 1
+#define DE_CONTROL_ROP 7 : 0
+
+/* Pseudo fields. */
+
+#define DE_CONTROL_SHORT_STROKE_DIR 27 : 24
+#define DE_CONTROL_SHORT_STROKE_DIR_225 0
+#define DE_CONTROL_SHORT_STROKE_DIR_135 1
+#define DE_CONTROL_SHORT_STROKE_DIR_315 2
+#define DE_CONTROL_SHORT_STROKE_DIR_45 3
+#define DE_CONTROL_SHORT_STROKE_DIR_270 4
+#define DE_CONTROL_SHORT_STROKE_DIR_90 5
+#define DE_CONTROL_SHORT_STROKE_DIR_180 8
+#define DE_CONTROL_SHORT_STROKE_DIR_0 10
+#define DE_CONTROL_ROTATION 25 : 24
+#define DE_CONTROL_ROTATION_0 0
+#define DE_CONTROL_ROTATION_270 1
+#define DE_CONTROL_ROTATION_90 2
+#define DE_CONTROL_ROTATION_180 3
+
+#define DE_PITCH 0x000010
+#define DE_PITCH_DESTINATION 28 : 16
+#define DE_PITCH_SOURCE 12 : 0
+
+#define DE_FOREGROUND 0x000014
+#define DE_FOREGROUND_COLOR 31 : 0
+
+#define DE_BACKGROUND 0x000018
+#define DE_BACKGROUND_COLOR 31 : 0
+
+#define DE_STRETCH_FORMAT 0x00001C
+#define DE_STRETCH_FORMAT_PATTERN_XY 30 : 30
+#define DE_STRETCH_FORMAT_PATTERN_XY_NORMAL 0
+#define DE_STRETCH_FORMAT_PATTERN_XY_OVERWRITE 1
+#define DE_STRETCH_FORMAT_PATTERN_Y 29 : 27
+#define DE_STRETCH_FORMAT_PATTERN_X 25 : 23
+#define DE_STRETCH_FORMAT_PIXEL_FORMAT 21 : 20
+#define DE_STRETCH_FORMAT_PIXEL_FORMAT_8 0
+#define DE_STRETCH_FORMAT_PIXEL_FORMAT_16 1
+#define DE_STRETCH_FORMAT_PIXEL_FORMAT_24 3
+#define DE_STRETCH_FORMAT_PIXEL_FORMAT_32 2
+#define DE_STRETCH_FORMAT_ADDRESSING 19 : 16
+#define DE_STRETCH_FORMAT_ADDRESSING_XY 0
+#define DE_STRETCH_FORMAT_ADDRESSING_LINEAR 15
+#define DE_STRETCH_FORMAT_SOURCE_HEIGHT 11 : 0
+
+#define DE_COLOR_COMPARE 0x000020
+#define DE_COLOR_COMPARE_COLOR 23 : 0
+
+#define DE_COLOR_COMPARE_MASK 0x000024
+#define DE_COLOR_COMPARE_MASK_MASKS 23 : 0
+
+#define DE_MASKS 0x000028
+#define DE_MASKS_BYTE_MASK 31 : 16
+#define DE_MASKS_BIT_MASK 15 : 0
+
+#define DE_CLIP_TL 0x00002C
+#define DE_CLIP_TL_TOP 31 : 16
+#define DE_CLIP_TL_STATUS 13 : 13
+#define DE_CLIP_TL_STATUS_DISABLE 0
+#define DE_CLIP_TL_STATUS_ENABLE 1
+#define DE_CLIP_TL_INHIBIT 12 : 12
+#define DE_CLIP_TL_INHIBIT_OUTSIDE 0
+#define DE_CLIP_TL_INHIBIT_INSIDE 1
+#define DE_CLIP_TL_LEFT 11 : 0
+
+#define DE_CLIP_BR 0x000030
+#define DE_CLIP_BR_BOTTOM 31 : 16
+#define DE_CLIP_BR_RIGHT 12 : 0
+
+#define DE_MONO_PATTERN_LOW 0x000034
+#define DE_MONO_PATTERN_LOW_PATTERN 31 : 0
+
+#define DE_MONO_PATTERN_HIGH 0x000038
+#define DE_MONO_PATTERN_HIGH_PATTERN 31 : 0
+
+#define DE_WINDOW_WIDTH 0x00003C
+#define DE_WINDOW_WIDTH_DESTINATION 28 : 16
+#define DE_WINDOW_WIDTH_SOURCE 12 : 0
+
+#define DE_WINDOW_SOURCE_BASE 0x000040
+#define DE_WINDOW_SOURCE_BASE_EXT 27 : 27
+#define DE_WINDOW_SOURCE_BASE_EXT_LOCAL 0
+#define DE_WINDOW_SOURCE_BASE_EXT_EXTERNAL 1
+#define DE_WINDOW_SOURCE_BASE_CS 26 : 26
+#define DE_WINDOW_SOURCE_BASE_CS_0 0
+#define DE_WINDOW_SOURCE_BASE_CS_1 1
+#define DE_WINDOW_SOURCE_BASE_ADDRESS 25 : 0
+
+#define DE_WINDOW_DESTINATION_BASE 0x000044
+#define DE_WINDOW_DESTINATION_BASE_EXT 27 : 27
+#define DE_WINDOW_DESTINATION_BASE_EXT_LOCAL 0
+#define DE_WINDOW_DESTINATION_BASE_EXT_EXTERNAL 1
+#define DE_WINDOW_DESTINATION_BASE_CS 26 : 26
+#define DE_WINDOW_DESTINATION_BASE_CS_0 0
+#define DE_WINDOW_DESTINATION_BASE_CS_1 1
+#define DE_WINDOW_DESTINATION_BASE_ADDRESS 25 : 0
+
+#define DE_ALPHA 0x000048
+#define DE_ALPHA_VALUE 7 : 0
+
+#define DE_WRAP 0x00004C
+#define DE_WRAP_X 31 : 16
+#define DE_WRAP_Y 15 : 0
+
+#define DE_STATUS 0x000050
+#define DE_STATUS_CSC 1 : 1
+#define DE_STATUS_CSC_CLEAR 0
+#define DE_STATUS_CSC_NOT_ACTIVE 0
+#define DE_STATUS_CSC_ACTIVE 1
+#define DE_STATUS_2D 0 : 0
+#define DE_STATUS_2D_CLEAR 0
+#define DE_STATUS_2D_NOT_ACTIVE 0
+#define DE_STATUS_2D_ACTIVE 1
+
+/* Color Space Conversion registers. */
+
+#define CSC_Y_SOURCE_BASE 0x0000C8
+#define CSC_Y_SOURCE_BASE_EXT 27 : 27
+#define CSC_Y_SOURCE_BASE_EXT_LOCAL 0
+#define CSC_Y_SOURCE_BASE_EXT_EXTERNAL 1
+#define CSC_Y_SOURCE_BASE_CS 26 : 26
+#define CSC_Y_SOURCE_BASE_CS_0 0
+#define CSC_Y_SOURCE_BASE_CS_1 1
+#define CSC_Y_SOURCE_BASE_ADDRESS 25 : 0
+
+#define CSC_CONSTANTS 0x0000CC
+#define CSC_CONSTANTS_Y 31 : 24
+#define CSC_CONSTANTS_R 23 : 16
+#define CSC_CONSTANTS_G 15 : 8
+#define CSC_CONSTANTS_B 7 : 0
+
+#define CSC_Y_SOURCE_X 0x0000D0
+#define CSC_Y_SOURCE_X_INTEGER 26 : 16
+#define CSC_Y_SOURCE_X_FRACTION 15 : 3
+
+#define CSC_Y_SOURCE_Y 0x0000D4
+#define CSC_Y_SOURCE_Y_INTEGER 27 : 16
+#define CSC_Y_SOURCE_Y_FRACTION 15 : 3
+
+#define CSC_U_SOURCE_BASE 0x0000D8
+#define CSC_U_SOURCE_BASE_EXT 27 : 27
+#define CSC_U_SOURCE_BASE_EXT_LOCAL 0
+#define CSC_U_SOURCE_BASE_EXT_EXTERNAL 1
+#define CSC_U_SOURCE_BASE_CS 26 : 26
+#define CSC_U_SOURCE_BASE_CS_0 0
+#define CSC_U_SOURCE_BASE_CS_1 1
+#define CSC_U_SOURCE_BASE_ADDRESS 25 : 0
+
+#define CSC_V_SOURCE_BASE 0x0000DC
+#define CSC_V_SOURCE_BASE_EXT 27 : 27
+#define CSC_V_SOURCE_BASE_EXT_LOCAL 0
+#define CSC_V_SOURCE_BASE_EXT_EXTERNAL 1
+#define CSC_V_SOURCE_BASE_CS 26 : 26
+#define CSC_V_SOURCE_BASE_CS_0 0
+#define CSC_V_SOURCE_BASE_CS_1 1
+#define CSC_V_SOURCE_BASE_ADDRESS 25 : 0
+
+#define CSC_SOURCE_DIMENSION 0x0000E0
+#define CSC_SOURCE_DIMENSION_X 31 : 16
+#define CSC_SOURCE_DIMENSION_Y 15 : 0
+
+#define CSC_SOURCE_PITCH 0x0000E4
+#define CSC_SOURCE_PITCH_Y 31 : 16
+#define CSC_SOURCE_PITCH_UV 15 : 0
+
+#define CSC_DESTINATION 0x0000E8
+#define CSC_DESTINATION_WRAP 31 : 31
+#define CSC_DESTINATION_WRAP_DISABLE 0
+#define CSC_DESTINATION_WRAP_ENABLE 1
+#define CSC_DESTINATION_X 27 : 16
+#define CSC_DESTINATION_Y 11 : 0
+
+#define CSC_DESTINATION_DIMENSION 0x0000EC
+#define CSC_DESTINATION_DIMENSION_X 31 : 16
+#define CSC_DESTINATION_DIMENSION_Y 15 : 0
+
+#define CSC_DESTINATION_PITCH 0x0000F0
+#define CSC_DESTINATION_PITCH_X 31 : 16
+#define CSC_DESTINATION_PITCH_Y 15 : 0
+
+#define CSC_SCALE_FACTOR 0x0000F4
+#define CSC_SCALE_FACTOR_HORIZONTAL 31 : 16
+#define CSC_SCALE_FACTOR_VERTICAL 15 : 0
+
+#define CSC_DESTINATION_BASE 0x0000F8
+#define CSC_DESTINATION_BASE_EXT 27 : 27
+#define CSC_DESTINATION_BASE_EXT_LOCAL 0
+#define CSC_DESTINATION_BASE_EXT_EXTERNAL 1
+#define CSC_DESTINATION_BASE_CS 26 : 26
+#define CSC_DESTINATION_BASE_CS_0 0
+#define CSC_DESTINATION_BASE_CS_1 1
+#define CSC_DESTINATION_BASE_ADDRESS 25 : 0
+
+#define CSC_CONTROL 0x0000FC
+#define CSC_CONTROL_STATUS 31 : 31
+#define CSC_CONTROL_STATUS_STOP 0
+#define CSC_CONTROL_STATUS_START 1
+#define CSC_CONTROL_SOURCE_FORMAT 30 : 28
+#define CSC_CONTROL_SOURCE_FORMAT_YUV422 0
+#define CSC_CONTROL_SOURCE_FORMAT_YUV420I 1
+#define CSC_CONTROL_SOURCE_FORMAT_YUV420 2
+#define CSC_CONTROL_SOURCE_FORMAT_YVU9 3
+#define CSC_CONTROL_SOURCE_FORMAT_IYU1 4
+#define CSC_CONTROL_SOURCE_FORMAT_IYU2 5
+#define CSC_CONTROL_SOURCE_FORMAT_RGB565 6
+#define CSC_CONTROL_SOURCE_FORMAT_RGB8888 7
+#define CSC_CONTROL_DESTINATION_FORMAT 27 : 26
+#define CSC_CONTROL_DESTINATION_FORMAT_RGB565 0
+#define CSC_CONTROL_DESTINATION_FORMAT_RGB8888 1
+#define CSC_CONTROL_HORIZONTAL_FILTER 25 : 25
+#define CSC_CONTROL_HORIZONTAL_FILTER_DISABLE 0
+#define CSC_CONTROL_HORIZONTAL_FILTER_ENABLE 1
+#define CSC_CONTROL_VERTICAL_FILTER 24 : 24
+#define CSC_CONTROL_VERTICAL_FILTER_DISABLE 0
+#define CSC_CONTROL_VERTICAL_FILTER_ENABLE 1
+#define CSC_CONTROL_BYTE_ORDER 23 : 23
+#define CSC_CONTROL_BYTE_ORDER_YUYV 0
+#define CSC_CONTROL_BYTE_ORDER_UYVY 1
+
+#define DE_DATA_PORT_501 0x110000
+#define DE_DATA_PORT_712 0x400000
+#define DE_DATA_PORT_722 0x6000
+
+/* point to virtual Memory Map IO starting address */
+extern char *smtc_RegBaseAddress;
+/* point to virtual video memory starting address */
+extern char *smtc_VRAMBaseAddress;
+extern unsigned char smtc_de_busy;
+
+extern unsigned long memRead32(unsigned long nOffset);
+extern void memWrite32(unsigned long nOffset, unsigned long nData);
+extern unsigned long SMTC_read2Dreg(unsigned long nOffset);
+
+/* 2D functions */
+extern void deInit(unsigned int nModeWidth, unsigned int nModeHeight,
+ unsigned int bpp);
+
+extern void deWaitForNotBusy(void);
+
+extern void deVerticalLine(unsigned long dst_base,
+ unsigned long dst_pitch,
+ unsigned long nX,
+ unsigned long nY,
+ unsigned long dst_height,
+ unsigned long nColor);
+
+extern void deHorizontalLine(unsigned long dst_base,
+ unsigned long dst_pitch,
+ unsigned long nX,
+ unsigned long nY,
+ unsigned long dst_width,
+ unsigned long nColor);
+
+extern void deLine(unsigned long dst_base,
+ unsigned long dst_pitch,
+ unsigned long nX1,
+ unsigned long nY1,
+ unsigned long nX2,
+ unsigned long nY2,
+ unsigned long nColor);
+
+extern void deFillRect(unsigned long dst_base,
+ unsigned long dst_pitch,
+ unsigned long dst_X,
+ unsigned long dst_Y,
+ unsigned long dst_width,
+ unsigned long dst_height,
+ unsigned long nColor);
+
+extern void deRotatePattern(unsigned char *pattern_dstaddr,
+ unsigned long pattern_src_addr,
+ unsigned long pattern_BPP,
+ unsigned long pattern_stride,
+ int patternX,
+ int patternY);
+
+extern void deCopy(unsigned long dst_base,
+ unsigned long dst_pitch,
+ unsigned long dst_BPP,
+ unsigned long dst_X,
+ unsigned long dst_Y,
+ unsigned long dst_width,
+ unsigned long dst_height,
+ unsigned long src_base,
+ unsigned long src_pitch,
+ unsigned long src_X,
+ unsigned long src_Y,
+ pTransparent pTransp,
+ unsigned char nROP2);
+
+/*
+ * System memory to Video memory monochrome expansion.
+ *
+ * Source is monochrome image in system memory. This function expands the
+ * monochrome data to color image in video memory.
+ *
+ * @pSrcbuf: pointer to start of source buffer in system memory
+ * @srcDelta: Pitch value (in bytes) of the source buffer, +ive means top
+ * down and -ive mean button up
+ * @startBit: Mono data can start at any bit in a byte, this value should
+ * be 0 to 7
+ * @dBase: Address of destination : offset in frame buffer
+ * @dPitch: Pitch value of destination surface in BYTE
+ * @bpp: Color depth of destination surface
+ * @dx, dy: Starting coordinate of destination surface
+ * @width, height: width and height of rectange in pixel value
+ * @fColor,bColor: Foreground, Background color (corresponding to a 1, 0 in
+ * the monochrome data)
+ * @rop2: ROP value
+ */
+
+extern long deSystemMem2VideoMemMonoBlt(
+ const char *pSrcbuf,
+ long srcDelta,
+ unsigned long startBit,
+ unsigned long dBase,
+ unsigned long dPitch,
+ unsigned long bpp,
+ unsigned long dx, unsigned long dy,
+ unsigned long width, unsigned long height,
+ unsigned long fColor,
+ unsigned long bColor,
+ unsigned long rop2);
+
+extern unsigned long deGetTransparency(void);
+extern void deSetPixelFormat(unsigned long bpp);
diff --git a/drivers/video/smi/smtcfb.c b/drivers/video/smi/smtcfb.c
new file mode 100644
index 0000000..33ce878
--- /dev/null
+++ b/drivers/video/smi/smtcfb.c
@@ -0,0 +1,1141 @@
+/*
+ * smtcfb.c -- Silicon Motion SM501 and SM7xx frame buffer device
+ *
+ * Copyright (C) 2006 Silicon Motion Technology Corp.
+ * Authors: Ge Wang, gewang@siliconmotion.com
+ * Boyod boyod.yang@siliconmotion.com.cn
+ *
+ * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Version 0.10.26192.21.01
+ * - Add PowerPC/Big endian support
+ * - Add 2D support for Lynx
+ * - Verified on2.6.19.2 Boyod.yang <boyod.yang@siliconmotion.com.cn>
+ *
+ * Version 0.09.2621.00.01
+ * - Only support Linux Kernel's version 2.6.21.
+ * Boyod.yang <boyod.yang@siliconmotion.com.cn>
+ *
+ * Version 0.09
+ * - Only support Linux Kernel's version 2.6.12.
+ * Boyod.yang <boyod.yang@siliconmotion.com.cn>
+ */
+
+#ifndef __KERNEL__
+#define __KERNEL__
+#endif
+
+#include <linux/io.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/uaccess.h>
+#include <linux/screen_info.h>
+
+#ifdef CONFIG_PM
+#include <linux/pm.h>
+#endif
+
+#include "smtcfb.h"
+#include "smtc2d.h"
+
+#ifdef DEBUG
+#define smdbg(format, arg...) printk(KERN_DEBUG format , ## arg)
+#else
+#define smdbg(format, arg...)
+#endif
+
+#ifdef __BIG_ENDIAN
+struct screen_info screen_info;
+#endif
+
+/*
+* Private structure
+*/
+struct smtcfb_info {
+ /*
+ * The following is a pointer to be passed into the
+ * functions below. The modules outside the main
+ * voyager.c driver have no knowledge as to what
+ * is within this structure.
+ */
+ struct fb_info fb;
+ struct display_switch *dispsw;
+ struct pci_dev *dev;
+ signed int currcon;
+
+ struct {
+ u8 red, green, blue;
+ } palette[NR_RGB];
+
+ u_int palette_size;
+};
+
+struct par_info {
+ /*
+ * Hardware
+ */
+ u16 chipID;
+ unsigned char __iomem *m_pMMIO;
+ char __iomem *m_pLFB;
+ char *m_pDPR;
+ char *m_pVPR;
+ char *m_pCPR;
+
+ u_int width;
+ u_int height;
+ u_int hz;
+ u_long BaseAddressInVRAM;
+ u8 chipRevID;
+};
+
+#ifdef __BIG_ENDIAN
+struct vesa_mode_table {
+ char mode_index[6];
+ u16 lfb_width;
+ u16 lfb_height;
+ u16 lfb_depth;
+};
+
+static struct vesa_mode_table vesa_mode[] = {
+ {"0x301", 640, 480, 8},
+ {"0x303", 800, 600, 8},
+ {"0x305", 1024, 768, 8},
+ {"0x307", 1280, 1024, 8},
+
+ {"0x311", 640, 480, 16},
+ {"0x314", 800, 600, 16},
+ {"0x317", 1024, 768, 16},
+ {"0x31A", 1280, 1024, 16},
+
+ {"0x312", 640, 480, 24},
+ {"0x315", 800, 600, 24},
+ {"0x318", 1024, 768, 24},
+ {"0x31B", 1280, 1024, 24},
+
+};
+#endif
+
+char __iomem *smtc_RegBaseAddress; /* Memory Map IO starting address */
+char __iomem *smtc_VRAMBaseAddress; /* video memory starting address */
+
+char *smtc_2DBaseAddress; /* 2D engine starting address */
+char *smtc_2Ddataport; /* 2D data port offset */
+short smtc_2Dacceleration;
+
+static u32 colreg[17];
+static struct par_info hw; /* hardware information */
+
+#if defined(CONFIG_FB_SM7XX_DUALHEAD)
+
+static u32 colreg2[17];
+/* hardware information for second display (CRT) */
+static struct par_info hw2;
+/* fb_info for second display (CRT) */
+struct smtcfb_info smtcfb_info2;
+
+#endif /* CONFIG_FB_SM501_DUALHEAD */
+
+u16 smtc_ChipIDs[] = {
+ 0x710,
+ 0x712,
+ 0x720
+};
+
+int sm712be_flag;
+
+#define numSMTCchipIDs (sizeof(smtc_ChipIDs) / sizeof(u16))
+
+void deWaitForNotBusy(void)
+{
+ unsigned long i = 0x1000000;
+ while (i--) {
+ if ((smtc_seqr(0x16) & 0x18) == 0x10)
+ break;
+ }
+ smtc_de_busy = 0;
+}
+
+static void sm712_set_timing(struct smtcfb_info *sfb,
+ struct par_info *ppar_info)
+{
+ int i = 0, j = 0;
+ u32 m_nScreenStride;
+
+ smdbg("\nppar_info->width = %d ppar_info->height = %d"
+ "sfb->fb.var.bits_per_pixel = %d ppar_info->hz = %d\n",
+ ppar_info->width, ppar_info->height,
+ sfb->fb.var.bits_per_pixel, ppar_info->hz);
+
+ for (j = 0; j < numVGAModes; j++) {
+ if (VGAMode[j].mmSizeX == ppar_info->width &&
+ VGAMode[j].mmSizeY == ppar_info->height &&
+ VGAMode[j].bpp == sfb->fb.var.bits_per_pixel &&
+ VGAMode[j].hz == ppar_info->hz) {
+
+ smdbg("\nVGAMode[j].mmSizeX = %d VGAMode[j].mmSizeY ="
+ "%d VGAMode[j].bpp = %d"
+ "VGAMode[j].hz=%d\n",
+ VGAMode[j].mmSizeX, VGAMode[j].mmSizeY,
+ VGAMode[j].bpp, VGAMode[j].hz);
+
+ smdbg("VGAMode index=%d\n", j);
+
+ smtc_mmiowb(0x0, 0x3c6);
+
+ smtc_seqw(0, 0x1);
+
+ smtc_mmiowb(VGAMode[j].Init_MISC, 0x3c2);
+
+ /* init SEQ register SR00 - SR04 */
+ for (i = 0; i < SIZE_SR00_SR04; i++)
+ smtc_seqw(i, VGAMode[j].Init_SR00_SR04[i]);
+
+ /* init SEQ register SR10 - SR24 */
+ for (i = 0; i < SIZE_SR10_SR24; i++)
+ smtc_seqw(i + 0x10,
+ VGAMode[j].Init_SR10_SR24[i]);
+
+ /* init SEQ register SR30 - SR75 */
+ for (i = 0; i < SIZE_SR30_SR75; i++)
+ if (((i + 0x30) != 0x62) \
+ && ((i + 0x30) != 0x6a) \
+ && ((i + 0x30) != 0x6b))
+ smtc_seqw(i + 0x30,
+ VGAMode[j].Init_SR30_SR75[i]);
+
+ /* init SEQ register SR80 - SR93 */
+ for (i = 0; i < SIZE_SR80_SR93; i++)
+ smtc_seqw(i + 0x80,
+ VGAMode[j].Init_SR80_SR93[i]);
+
+ /* init SEQ register SRA0 - SRAF */
+ for (i = 0; i < SIZE_SRA0_SRAF; i++)
+ smtc_seqw(i + 0xa0,
+ VGAMode[j].Init_SRA0_SRAF[i]);
+
+ /* init Graphic register GR00 - GR08 */
+ for (i = 0; i < SIZE_GR00_GR08; i++)
+ smtc_grphw(i, VGAMode[j].Init_GR00_GR08[i]);
+
+ /* init Attribute register AR00 - AR14 */
+ for (i = 0; i < SIZE_AR00_AR14; i++)
+ smtc_attrw(i, VGAMode[j].Init_AR00_AR14[i]);
+
+ /* init CRTC register CR00 - CR18 */
+ for (i = 0; i < SIZE_CR00_CR18; i++)
+ smtc_crtcw(i, VGAMode[j].Init_CR00_CR18[i]);
+
+ /* init CRTC register CR30 - CR4D */
+ for (i = 0; i < SIZE_CR30_CR4D; i++)
+ smtc_crtcw(i + 0x30,
+ VGAMode[j].Init_CR30_CR4D[i]);
+
+ /* init CRTC register CR90 - CRA7 */
+ for (i = 0; i < SIZE_CR90_CRA7; i++)
+ smtc_crtcw(i + 0x90,
+ VGAMode[j].Init_CR90_CRA7[i]);
+ }
+ }
+ smtc_mmiowb(0x67, 0x3c2);
+
+ /* set VPR registers */
+ writel(0x0, ppar_info->m_pVPR + 0x0C);
+ writel(0x0, ppar_info->m_pVPR + 0x40);
+
+ /* set data width */
+ m_nScreenStride =
+ (ppar_info->width * sfb->fb.var.bits_per_pixel) / 64;
+ switch (sfb->fb.var.bits_per_pixel) {
+ case 8:
+ writel(0x0, ppar_info->m_pVPR + 0x0);
+ break;
+ case 16:
+ writel(0x00020000, ppar_info->m_pVPR + 0x0);
+ break;
+ case 24:
+ writel(0x00040000, ppar_info->m_pVPR + 0x0);
+ break;
+ case 32:
+ writel(0x00030000, ppar_info->m_pVPR + 0x0);
+ break;
+ }
+ writel((u32) (((m_nScreenStride + 2) << 16) | m_nScreenStride),
+ ppar_info->m_pVPR + 0x10);
+
+}
+
+static void sm712_setpalette(int regno, unsigned red, unsigned green,
+ unsigned blue, struct fb_info *info)
+{
+ struct par_info *cur_par = (struct par_info *)info->par;
+
+ if (cur_par->BaseAddressInVRAM)
+ /*
+ * second display palette for dual head. Enable CRT RAM, 6-bit
+ * RAM
+ */
+ smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x20);
+ else
+ /* primary display palette. Enable LCD RAM only, 6-bit RAM */
+ smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x10);
+ smtc_mmiowb(regno, dac_reg);
+ smtc_mmiowb(red >> 10, dac_val);
+ smtc_mmiowb(green >> 10, dac_val);
+ smtc_mmiowb(blue >> 10, dac_val);
+}
+
+static void smtc_set_timing(struct smtcfb_info *sfb, struct par_info
+ *ppar_info)
+{
+ switch (ppar_info->chipID) {
+ case 0x710:
+ case 0x712:
+ case 0x720:
+ sm712_set_timing(sfb, ppar_info);
+ break;
+ }
+}
+
+static struct fb_var_screeninfo smtcfb_var = {
+ .xres = 1024,
+ .yres = 600,
+ .xres_virtual = 1024,
+ .yres_virtual = 600,
+ .bits_per_pixel = 16,
+ .red = {16, 8, 0},
+ .green = {8, 8, 0},
+ .blue = {0, 8, 0},
+ .activate = FB_ACTIVATE_NOW,
+ .height = -1,
+ .width = -1,
+ .vmode = FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo smtcfb_fix = {
+ .id = "sm712fb",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
+ .line_length = 800 * 3,
+ .accel = FB_ACCEL_SMI_LYNX,
+};
+
+/* chan_to_field
+ *
+ * convert a colour value into a field position
+ *
+ * from pxafb.c
+ */
+
+static inline unsigned int chan_to_field(unsigned int chan,
+ struct fb_bitfield *bf)
+{
+ chan &= 0xffff;
+ chan >>= 16 - bf->length;
+ return chan << bf->offset;
+}
+
+static int smtc_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned trans, struct fb_info *info)
+{
+ struct smtcfb_info *sfb = (struct smtcfb_info *)info;
+ u32 val;
+
+ if (regno > 255)
+ return 1;
+
+ switch (sfb->fb.fix.visual) {
+ case FB_VISUAL_DIRECTCOLOR:
+ case FB_VISUAL_TRUECOLOR:
+ /*
+ * 16/32 bit true-colour, use pseuo-palette for 16 base color
+ */
+ if (regno < 16) {
+ if (sfb->fb.var.bits_per_pixel == 16) {
+ u32 *pal = sfb->fb.pseudo_palette;
+ val = chan_to_field(red, &sfb->fb.var.red);
+ val |= chan_to_field(green, \
+ &sfb->fb.var.green);
+ val |= chan_to_field(blue, &sfb->fb.var.blue);
+#ifdef __BIG_ENDIAN
+ pal[regno] =
+ ((red & 0xf800) >> 8) |
+ ((green & 0xe000) >> 13) |
+ ((green & 0x1c00) << 3) |
+ ((blue & 0xf800) >> 3);
+#else
+ pal[regno] = val;
+#endif
+ } else {
+ u32 *pal = sfb->fb.pseudo_palette;
+ val = chan_to_field(red, &sfb->fb.var.red);
+ val |= chan_to_field(green, \
+ &sfb->fb.var.green);
+ val |= chan_to_field(blue, &sfb->fb.var.blue);
+#ifdef __BIG_ENDIAN
+ val =
+ (val & 0xff00ff00 >> 8) |
+ (val & 0x00ff00ff << 8);
+#endif
+ pal[regno] = val;
+ }
+ }
+ break;
+
+ case FB_VISUAL_PSEUDOCOLOR:
+ /* color depth 8 bit */
+ sm712_setpalette(regno, red, green, blue, info);
+ break;
+
+ default:
+ return 1; /* unknown type */
+ }
+
+ return 0;
+
+}
+
+#ifdef __BIG_ENDIAN
+static ssize_t
+smtcfb_read(struct file *file, char __user * buf, size_t count, loff_t * ppos)
+{
+ unsigned long p = *ppos;
+
+ struct inode *inode = file->f_dentry->d_inode;
+ int fbidx = iminor(inode);
+ struct fb_info *info = registered_fb[fbidx];
+
+ u32 *buffer, *dst;
+ u32 __iomem *src;
+ int c, i, cnt = 0, err = 0;
+ unsigned long total_size;
+
+ if (!info || !info->screen_base)
+ return -ENODEV;
+
+ if (info->state != FBINFO_STATE_RUNNING)
+ return -EPERM;
+
+ total_size = info->screen_size;
+
+ if (total_size == 0)
+ total_size = info->fix.smem_len;
+
+ if (p >= total_size)
+ return 0;
+
+ if (count >= total_size)
+ count = total_size;
+
+ if (count + p > total_size)
+ count = total_size - p;
+
+ buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ src = (u32 __iomem *) (info->screen_base + p);
+
+ if (info->fbops->fb_sync)
+ info->fbops->fb_sync(info);
+
+ while (count) {
+ c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+ dst = buffer;
+ for (i = c >> 2; i--;) {
+ *dst = fb_readl(src++);
+ *dst =
+ (*dst & 0xff00ff00 >> 8) |
+ (*dst & 0x00ff00ff << 8);
+ dst++;
+ }
+ if (c & 3) {
+ u8 *dst8 = (u8 *) dst;
+ u8 __iomem *src8 = (u8 __iomem *) src;
+
+ for (i = c & 3; i--;) {
+ if (i & 1) {
+ *dst8++ = fb_readb(++src8);
+ } else {
+ *dst8++ = fb_readb(--src8);
+ src8 += 2;
+ }
+ }
+ src = (u32 __iomem *) src8;
+ }
+
+ if (copy_to_user(buf, buffer, c)) {
+ err = -EFAULT;
+ break;
+ }
+ *ppos += c;
+ buf += c;
+ cnt += c;
+ count -= c;
+ }
+
+ kfree(buffer);
+
+ return (err) ? err : cnt;
+}
+
+static ssize_t
+smtcfb_write(struct file *file, const char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ unsigned long p = *ppos;
+ struct inode *inode = file->f_dentry->d_inode;
+ int fbidx = iminor(inode);
+ struct fb_info *info = registered_fb[fbidx];
+ u32 *buffer, *src;
+ u32 __iomem *dst;
+ int c, i, cnt = 0, err = 0;
+ unsigned long total_size;
+
+ if (!info || !info->screen_base)
+ return -ENODEV;
+
+ if (info->state != FBINFO_STATE_RUNNING)
+ return -EPERM;
+
+ total_size = info->screen_size;
+
+ if (total_size == 0)
+ total_size = info->fix.smem_len;
+
+ if (p > total_size)
+ return -EFBIG;
+
+ if (count > total_size) {
+ err = -EFBIG;
+ count = total_size;
+ }
+
+ if (count + p > total_size) {
+ if (!err)
+ err = -ENOSPC;
+
+ count = total_size - p;
+ }
+
+ buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ dst = (u32 __iomem *) (info->screen_base + p);
+
+ if (info->fbops->fb_sync)
+ info->fbops->fb_sync(info);
+
+ while (count) {
+ c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+ src = buffer;
+
+ if (copy_from_user(src, buf, c)) {
+ err = -EFAULT;
+ break;
+ }
+
+ for (i = c >> 2; i--;) {
+ fb_writel((*src & 0xff00ff00 >> 8) |
+ (*src & 0x00ff00ff << 8), dst++);
+ src++;
+ }
+ if (c & 3) {
+ u8 *src8 = (u8 *) src;
+ u8 __iomem *dst8 = (u8 __iomem *) dst;
+
+ for (i = c & 3; i--;) {
+ if (i & 1) {
+ fb_writeb(*src8++, ++dst8);
+ } else {
+ fb_writeb(*src8++, --dst8);
+ dst8 += 2;
+ }
+ }
+ dst = (u32 __iomem *) dst8;
+ }
+
+ *ppos += c;
+ buf += c;
+ cnt += c;
+ count -= c;
+ }
+
+ kfree(buffer);
+
+ return (cnt) ? cnt : err;
+}
+#endif /* ! __BIG_ENDIAN */
+
+#include "smtc2d.c"
+
+void smtcfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+ struct par_info *p = (struct par_info *)info->par;
+
+ if (smtc_2Dacceleration) {
+ if (!area->width || !area->height)
+ return;
+
+ deCopy(p->BaseAddressInVRAM, 0, info->var.bits_per_pixel,
+ area->dx, area->dy, area->width, area->height,
+ p->BaseAddressInVRAM, 0, area->sx, area->sy, 0, 0xC);
+
+ } else
+ cfb_copyarea(info, area);
+}
+
+void smtcfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+ struct par_info *p = (struct par_info *)info->par;
+
+ if (smtc_2Dacceleration) {
+ if (!rect->width || !rect->height)
+ return;
+ if (info->var.bits_per_pixel >= 24)
+ deFillRect(p->BaseAddressInVRAM, 0, rect->dx * 3,
+ rect->dy * 3, rect->width * 3, rect->height,
+ rect->color);
+ else
+ deFillRect(p->BaseAddressInVRAM, 0, rect->dx, rect->dy,
+ rect->width, rect->height, rect->color);
+ } else
+ cfb_fillrect(info, rect);
+}
+
+void smtcfb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+ struct par_info *p = (struct par_info *)info->par;
+ u32 bg_col = 0, fg_col = 0;
+
+ if ((smtc_2Dacceleration) && (image->depth == 1)) {
+ if (smtc_de_busy)
+ deWaitForNotBusy();
+
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ bg_col = image->bg_color;
+ fg_col = image->fg_color;
+ break;
+ case 16:
+ bg_col =
+ ((u32 *) (info->pseudo_palette))[image->bg_color];
+ fg_col =
+ ((u32 *) (info->pseudo_palette))[image->fg_color];
+ break;
+ case 32:
+ bg_col =
+ ((u32 *) (info->pseudo_palette))[image->bg_color];
+ fg_col =
+ ((u32 *) (info->pseudo_palette))[image->fg_color];
+ break;
+ }
+
+ deSystemMem2VideoMemMonoBlt(
+ image->data,
+ image->width / 8,
+ 0,
+ p->BaseAddressInVRAM,
+ 0,
+ 0,
+ image->dx, image->dy,
+ image->width, image->height,
+ fg_col, bg_col,
+ 0x0C);
+
+ } else
+ cfb_imageblit(info, image);
+}
+
+static struct fb_ops smtcfb_ops = {
+ .owner = THIS_MODULE,
+ .fb_setcolreg = smtc_setcolreg,
+ .fb_fillrect = smtcfb_fillrect,
+ .fb_imageblit = smtcfb_imageblit,
+ .fb_copyarea = smtcfb_copyarea,
+#ifdef __BIG_ENDIAN
+ .fb_read = smtcfb_read,
+ .fb_write = smtcfb_write,
+#endif
+
+};
+
+void smtcfb_setmode(struct smtcfb_info *sfb)
+{
+ switch (sfb->fb.var.bits_per_pixel) {
+ case 32:
+ sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
+ sfb->fb.fix.line_length = sfb->fb.var.xres * 4;
+ sfb->fb.var.red.length = 8;
+ sfb->fb.var.green.length = 8;
+ sfb->fb.var.blue.length = 8;
+ sfb->fb.var.red.offset = 16;
+ sfb->fb.var.green.offset = 8;
+ sfb->fb.var.blue.offset = 0;
+
+ break;
+ case 8:
+ sfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ sfb->fb.fix.line_length = sfb->fb.var.xres;
+ sfb->fb.var.red.offset = 5;
+ sfb->fb.var.red.length = 3;
+ sfb->fb.var.green.offset = 2;
+ sfb->fb.var.green.length = 3;
+ sfb->fb.var.blue.offset = 0;
+ sfb->fb.var.blue.length = 2;
+ break;
+ case 24:
+ sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
+ sfb->fb.fix.line_length = sfb->fb.var.xres * 3;
+ sfb->fb.var.red.length = 8;
+ sfb->fb.var.green.length = 8;
+ sfb->fb.var.blue.length = 8;
+
+ sfb->fb.var.red.offset = 16;
+ sfb->fb.var.green.offset = 8;
+ sfb->fb.var.blue.offset = 0;
+
+ break;
+ case 16:
+ default:
+ sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
+ sfb->fb.fix.line_length = sfb->fb.var.xres * 2;
+
+ sfb->fb.var.red.length = 5;
+ sfb->fb.var.green.length = 6;
+ sfb->fb.var.blue.length = 5;
+
+ sfb->fb.var.red.offset = 11;
+ sfb->fb.var.green.offset = 5;
+ sfb->fb.var.blue.offset = 0;
+
+ break;
+ }
+
+ hw.width = sfb->fb.var.xres;
+ hw.height = sfb->fb.var.yres;
+ hw.hz = 60;
+ smtc_set_timing(sfb, &hw);
+ if (smtc_2Dacceleration) {
+ printk("2D acceleration enabled!\n");
+ /* Init smtc drawing engine */
+ deInit(sfb->fb.var.xres, sfb->fb.var.yres,
+ sfb->fb.var.bits_per_pixel);
+ }
+}
+
+#if defined(CONFIG_FB_SM7XX_DUALHEAD)
+void smtc_head2_init(struct smtcfb_info *sfb)
+{
+ smtcfb_info2 = *sfb;
+ smtcfb_info2.fb.pseudo_palette = &colreg2;
+ smtcfb_info2.fb.par = &hw2;
+ sprintf(smtcfb_info2.fb.fix.id, "sm%Xfb2", hw.chipID);
+ hw2.chipID = hw.chipID;
+ hw2.chipRevID = hw.chipRevID;
+ hw2.width = smtcfb_info2.fb.var.xres;
+ hw2.height = smtcfb_info2.fb.var.yres;
+ hw2.hz = 60;
+ hw2.m_pMMIO = smtc_RegBaseAddress;
+
+ /*hard code 2nd head starting from half VRAM size postion */
+ hw2.BaseAddressInVRAM = smtcfb_info2.fb.fix.smem_len / 2;
+
+ hw2.m_pLFB = smtc_VRAMBaseAddress + hw2.BaseAddressInVRAM;
+ smtcfb_info2.fb.screen_base = hw2.m_pLFB;
+
+ writel(hw2.BaseAddressInVRAM >> 3, hw2.m_pVPR + 0x10);
+}
+#endif
+
+/*
+ * Alloc struct smtcfb_info and assign the default value
+ */
+static struct smtcfb_info *__devinit smtc_alloc_fb_info(struct pci_dev *dev,
+ char *name)
+{
+ struct smtcfb_info *sfb;
+
+ sfb = kmalloc(sizeof(struct smtcfb_info), GFP_KERNEL);
+
+ if (!sfb)
+ return NULL;
+
+ memset(sfb, 0, sizeof(struct smtcfb_info));
+
+ sfb->currcon = -1;
+ sfb->dev = dev;
+
+ /*** Init sfb->fb with default value ***/
+ sfb->fb.flags = FBINFO_FLAG_DEFAULT;
+ sfb->fb.fbops = &smtcfb_ops;
+ sfb->fb.var = smtcfb_var;
+ sfb->fb.fix = smtcfb_fix;
+
+ strcpy(sfb->fb.fix.id, name);
+
+ sfb->fb.fix.type = FB_TYPE_PACKED_PIXELS;
+ sfb->fb.fix.type_aux = 0;
+ sfb->fb.fix.xpanstep = 0;
+ sfb->fb.fix.ypanstep = 0;
+ sfb->fb.fix.ywrapstep = 0;
+ sfb->fb.fix.accel = FB_ACCEL_SMI_LYNX;
+
+ sfb->fb.var.nonstd = 0;
+ sfb->fb.var.activate = FB_ACTIVATE_NOW;
+ sfb->fb.var.height = -1;
+ sfb->fb.var.width = -1;
+ /* text mode acceleration */
+ sfb->fb.var.accel_flags = FB_ACCELF_TEXT;
+ sfb->fb.var.vmode = FB_VMODE_NONINTERLACED;
+ sfb->fb.par = &hw;
+ sfb->fb.pseudo_palette = colreg;
+
+ return sfb;
+}
+
+/*
+ * Unmap in the memory mapped IO registers
+ */
+
+static void __devinit smtc_unmap_mmio(struct smtcfb_info *sfb)
+{
+ if (sfb && smtc_RegBaseAddress)
+ smtc_RegBaseAddress = NULL;
+}
+
+/*
+ * Map in the screen memory
+ */
+
+static int __devinit smtc_map_smem(struct smtcfb_info *sfb,
+ struct pci_dev *dev, u_long smem_len)
+{
+ if (sfb->fb.var.bits_per_pixel == 32) {
+#ifdef __BIG_ENDIAN
+ sfb->fb.fix.smem_start = pci_resource_start(dev, 0)
+ + 0x800000;
+#else
+ sfb->fb.fix.smem_start = pci_resource_start(dev, 0);
+#endif
+ } else {
+ sfb->fb.fix.smem_start = pci_resource_start(dev, 0);
+ }
+
+ sfb->fb.fix.smem_len = smem_len;
+
+ sfb->fb.screen_base = smtc_VRAMBaseAddress;
+
+ if (!sfb->fb.screen_base) {
+ printk(KERN_INFO "%s: unable to map screen memory\n",
+ sfb->fb.fix.id);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+/*
+ * Unmap in the screen memory
+ *
+ */
+static void __devinit smtc_unmap_smem(struct smtcfb_info *sfb)
+{
+ if (sfb && sfb->fb.screen_base) {
+ iounmap(sfb->fb.screen_base);
+ sfb->fb.screen_base = NULL;
+ }
+}
+
+/*
+ * We need to wake up the LynxEM+, and make sure its in linear memory mode.
+ */
+static inline void __devinit sm7xx_init_hw(void)
+{
+ outb_p(0x18, 0x3c4);
+ outb_p(0x11, 0x3c5);
+}
+
+static void __devinit smtc_free_fb_info(struct smtcfb_info *sfb)
+{
+ if (sfb) {
+ fb_alloc_cmap(&sfb->fb.cmap, 0, 0);
+ kfree(sfb);
+ }
+}
+
+static int __init smtcfb_init(void)
+{
+ struct smtcfb_info *sfb;
+ u_long smem_size = 0x00800000; /* default 8MB */
+ char name[16];
+ int err, i = 0;
+ unsigned long pFramebufferPhysical;
+ struct pci_dev *pdev = NULL;
+
+ printk(KERN_INFO
+ "Silicon Motion display driver " SMTC_LINUX_FB_VERSION "\n");
+
+ /* init the global variable */
+ smtc_2Dacceleration = 0; /* default no 2D acceleration */
+
+ do {
+ pdev = pci_get_device(0x126f, smtc_ChipIDs[i], pdev);
+ if (pdev == NULL) {
+ i++;
+ } else {
+ hw.chipID = smtc_ChipIDs[i];
+ break;
+ }
+ } while (i < numSMTCchipIDs);
+
+ err = pci_enable_device(pdev); /* enable SMTC chip */
+
+ if (err)
+ return err;
+
+ err = -ENOMEM;
+
+ sprintf(name, "sm%Xfb", hw.chipID);
+
+ sfb = smtc_alloc_fb_info(pdev, name);
+
+ if (!sfb)
+ goto failed;
+
+ sm7xx_init_hw();
+
+ /*get mode parameter from screen_info */
+ if (screen_info.lfb_width != 0) {
+ sfb->fb.var.xres = screen_info.lfb_width;
+ sfb->fb.var.yres = screen_info.lfb_height;
+ sfb->fb.var.bits_per_pixel = screen_info.lfb_depth;
+ } else {
+ /* default resolution 1024x600 16bit mode */
+ sfb->fb.var.xres = SCREEN_X_RES;
+ sfb->fb.var.yres = SCREEN_Y_RES;
+ sfb->fb.var.bits_per_pixel = SCREEN_BPP;
+ }
+
+ smdbg("\nsfb->fb.var.bits_per_pixel = %d sm712be_flag = %d\n",
+ sfb->fb.var.bits_per_pixel, sm712be_flag);
+#ifdef __BIG_ENDIAN
+ if (sm712be_flag == 1 && sfb->fb.var.bits_per_pixel == 24)
+ sfb->fb.var.bits_per_pixel = (screen_info.lfb_depth = 32);
+#endif
+ /* Map address and memory detection */
+ pFramebufferPhysical = pci_resource_start(pdev, 0);
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &hw.chipRevID);
+
+ switch (hw.chipID) {
+ case 0x710:
+ case 0x712:
+ sfb->fb.fix.mmio_start = pFramebufferPhysical + 0x00400000;
+ sfb->fb.fix.mmio_len = 0x00400000;
+ smem_size = SM712_VIDEOMEMORYSIZE;
+#ifdef __BIG_ENDIAN
+ hw.m_pLFB = (smtc_VRAMBaseAddress =
+ ioremap(pFramebufferPhysical, 0x00c00000));
+#else
+ hw.m_pLFB = (smtc_VRAMBaseAddress =
+ ioremap(pFramebufferPhysical, 0x00800000));
+#endif
+ hw.m_pMMIO = (smtc_RegBaseAddress =
+ smtc_VRAMBaseAddress + 0x00700000);
+ smtc_2DBaseAddress = (hw.m_pDPR =
+ smtc_VRAMBaseAddress + 0x00408000);
+ smtc_2Ddataport = smtc_VRAMBaseAddress + DE_DATA_PORT_712;
+ hw.m_pVPR = hw.m_pLFB + 0x0040c000;
+ if (sfb->fb.var.bits_per_pixel == 32) {
+#ifdef __BIG_ENDIAN
+ smtc_VRAMBaseAddress += 0x800000;
+ hw.m_pLFB += 0x800000;
+ printk(KERN_INFO
+ "\nsmtc_VRAMBaseAddress=0x%X hw.m_pLFB=0x%X\n",
+ smtc_VRAMBaseAddress, hw.m_pLFB);
+#endif
+ }
+ if (!smtc_RegBaseAddress) {
+
+ printk(KERN_INFO
+ "%s: unable to map memory mapped IO\n",
+ sfb->fb.fix.id);
+
+ return -ENOMEM;
+ }
+
+ /* set MCLK = 14.31818 * (0x16 / 0x2) */
+ smtc_seqw(0x6a, 0x16);
+ smtc_seqw(0x6b, 0x02);
+ smtc_seqw(0x62, 0x3e);
+ /* enable PCI burst */
+ smtc_seqw(0x17, 0x20);
+ /* enabel word swap */
+ if (sfb->fb.var.bits_per_pixel == 32) {
+#ifdef __BIG_ENDIAN
+ smtc_seqw(0x17, 0x30);
+#endif
+ }
+#ifdef CONFIG_FB_SM7XX_ACCEL
+ smtc_2Dacceleration = 1;
+#endif
+
+ break;
+
+ case 0x720:
+ sfb->fb.fix.mmio_start = pFramebufferPhysical;
+ sfb->fb.fix.mmio_len = 0x00200000;
+ smem_size = SM722_VIDEOMEMORYSIZE;
+ smtc_2DBaseAddress = (hw.m_pDPR =
+ ioremap(pFramebufferPhysical, 0x00a00000));
+ hw.m_pLFB = (smtc_VRAMBaseAddress =
+ smtc_2DBaseAddress + 0x00200000);
+ hw.m_pMMIO = (smtc_RegBaseAddress =
+ smtc_2DBaseAddress + 0x000c0000);
+ smtc_2Ddataport = smtc_2DBaseAddress + DE_DATA_PORT_722;
+ hw.m_pVPR = smtc_2DBaseAddress + 0x800;
+
+ smtc_seqw(0x62, 0xff);
+ smtc_seqw(0x6a, 0x0d);
+ smtc_seqw(0x6b, 0x02);
+ smtc_2Dacceleration = 0;
+ break;
+ default:
+ printk(KERN_INFO
+ "No valid Silicon Motion display chip was detected!\n");
+
+ smtc_free_fb_info(sfb);
+ return err;
+ }
+
+ /* can support 32 bpp */
+ if (15 == sfb->fb.var.bits_per_pixel)
+ sfb->fb.var.bits_per_pixel = 16;
+
+ sfb->fb.var.xres_virtual = sfb->fb.var.xres;
+
+ sfb->fb.var.yres_virtual = sfb->fb.var.yres;
+ err = smtc_map_smem(sfb, pdev, smem_size);
+ if (err)
+ goto failed;
+
+ smtcfb_setmode(sfb);
+ /* Primary display starting from 0 postion */
+ hw.BaseAddressInVRAM = 0;
+ sfb->fb.par = &hw;
+
+ err = register_framebuffer(&sfb->fb);
+ if (err < 0)
+ goto failed;
+
+ printk(KERN_INFO "Silicon Motion SM%X Rev%X primary display mode"
+ "%dx%d-%d Init Complete.\n", hw.chipID, hw.chipRevID,
+ sfb->fb.var.xres, sfb->fb.var.yres,
+ sfb->fb.var.bits_per_pixel);
+
+#if defined(CONFIG_FB_SM7XX_DUALHEAD)
+ smtc_head2_init(sfb);
+ err = register_framebuffer(&smtcfb_info2.fb);
+
+ /* if second head display fails, also fails the primary display */
+ if (err < 0) {
+ printk(KERN_INFO
+ "Silicon Motion, Inc. second head init fail\n");
+ goto failed;
+ }
+
+ printk(KERN_INFO "Silicon Motion SM%X Rev%X secondary display mode"
+ "%dx%d-%d Init Complete.\n", hw.chipID, hw.chipRevID,
+ hw2.width, hw2.height,
+ smtcfb_info2.fb.var.bits_per_pixel);
+#endif
+
+ return 0;
+
+ failed:
+ printk(KERN_INFO "Silicon Motion, Inc. primary display init fail\n");
+
+ smtc_unmap_smem(sfb);
+ smtc_unmap_mmio(sfb);
+ smtc_free_fb_info(sfb);
+
+ return err;
+}
+
+static void __exit smtcfb_exit(void)
+{
+}
+
+module_init(smtcfb_init);
+module_exit(smtcfb_exit);
+
+/*
+ * sm712be_setup - process command line options
+ * @options: string of options
+ * Returns zero.
+ *
+ */
+static int __init sm712be_setup(char *options)
+{
+ int retval = 0;
+ sm712be_flag = 0;
+ if (!options || !*options) {
+ retval = 1;
+ smdbg("\n No sm712be parameter\n", __LINE__);
+ }
+ if (!retval && strstr(options, "enable"))
+ sm712be_flag = 1;
+ smdbg("\nsm712be_setup = %s sm712be_flag = %d\n", options,
+ sm712be_flag);
+ return 1;
+}
+
+__setup("sm712be=", sm712be_setup);
+
+#ifdef __BIG_ENDIAN
+/*
+ * sm712vga_setup - process command line options, get vga parameter
+ * @options: string of options
+ * Returns zero.
+ *
+ */
+static int __init sm712vga_setup(char *options)
+{
+ int retval = 0;
+ int index;
+ sm712be_flag = 0;
+
+ if (!options || !*options) {
+ retval = 1;
+ smdbg("\n No vga parameter\n", __LINE__);
+ }
+
+ screen_info.lfb_width = 0;
+ screen_info.lfb_height = 0;
+ screen_info.lfb_depth = 0;
+
+ for (index = 0;
+ index < (sizeof(vesa_mode) / sizeof(struct vesa_mode_table));
+ index++) {
+ if (strstr(options, vesa_mode[index].mode_index)) {
+ screen_info.lfb_width = vesa_mode[index].lfb_width;
+ screen_info.lfb_height = vesa_mode[index].lfb_height;
+ screen_info.lfb_depth = vesa_mode[index].lfb_depth;
+ }
+ }
+ smdbg("\nsm712vga_setup = %s\n", options);
+ return 1;
+}
+
+__setup("vga=", sm712vga_setup);
+#endif
+
+MODULE_AUTHOR("Siliconmotion ");
+MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/smi/smtcfb.h b/drivers/video/smi/smtcfb.h
new file mode 100644
index 0000000..6b8ed8a
--- /dev/null
+++ b/drivers/video/smi/smtcfb.h
@@ -0,0 +1,793 @@
+/*
+ * smtcfb.h -- Silicon Motion SM501 and SM7xx frame buffer device
+ *
+ * Copyright (C) 2006 Silicon Motion Technology Corp.
+ * Authors: Ge Wang, gewang@siliconmotion.com
+ * Boyod boyod.yang@siliconmotion.com.cn
+ *
+ * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#define SMTC_LINUX_FB_VERSION "version 0.11.2619.21.01 July 27, 2008"
+
+#define NR_PALETTE 256
+#define NR_RGB 2
+
+#define FB_ACCEL_SMI_LYNX 88
+
+#ifdef __BIG_ENDIAN
+#define PC_VGA 0
+#else
+#define PC_VGA 1
+#endif
+
+#define SCREEN_X_RES 1024
+#define SCREEN_Y_RES 600
+#define SCREEN_BPP 16
+
+#ifndef FIELD_OFFSET
+#define FIELD_OFSFET(type, field) \
+ ((unsigned long) (PUCHAR) & (((type *)0)->field))
+#endif
+
+/*Assume SM712 graphics chip has 4MB VRAM */
+#define SM712_VIDEOMEMORYSIZE 0x00400000
+/*Assume SM722 graphics chip has 8MB VRAM */
+#define SM722_VIDEOMEMORYSIZE 0x00800000
+
+#define dac_reg (0x3c8)
+#define dac_val (0x3c9)
+
+extern char *smtc_RegBaseAddress;
+#define smtc_mmiowb(dat, reg) writeb(dat, smtc_RegBaseAddress + reg)
+#define smtc_mmioww(dat, reg) writew(dat, smtc_RegBaseAddress + reg)
+#define smtc_mmiowl(dat, reg) writel(dat, smtc_RegBaseAddress + reg)
+
+#define smtc_mmiorb(reg) readb(smtc_RegBaseAddress + reg)
+#define smtc_mmiorw(reg) readw(smtc_RegBaseAddress + reg)
+#define smtc_mmiorl(reg) readl(smtc_RegBaseAddress + reg)
+
+#define SIZE_SR00_SR04 (0x04 - 0x00 + 1)
+#define SIZE_SR10_SR24 (0x24 - 0x10 + 1)
+#define SIZE_SR30_SR75 (0x75 - 0x30 + 1)
+#define SIZE_SR80_SR93 (0x93 - 0x80 + 1)
+#define SIZE_SRA0_SRAF (0xAF - 0xA0 + 1)
+#define SIZE_GR00_GR08 (0x08 - 0x00 + 1)
+#define SIZE_AR00_AR14 (0x14 - 0x00 + 1)
+#define SIZE_CR00_CR18 (0x18 - 0x00 + 1)
+#define SIZE_CR30_CR4D (0x4D - 0x30 + 1)
+#define SIZE_CR90_CRA7 (0xA7 - 0x90 + 1)
+#define SIZE_VPR (0x6C + 1)
+#define SIZE_DPR (0x44 + 1)
+
+static inline void smtc_crtcw(int reg, int val)
+{
+ smtc_mmiowb(reg, 0x3d4);
+ smtc_mmiowb(val, 0x3d5);
+}
+
+static inline unsigned int smtc_crtcr(int reg)
+{
+ smtc_mmiowb(reg, 0x3d4);
+ return smtc_mmiorb(0x3d5);
+}
+
+static inline void smtc_grphw(int reg, int val)
+{
+ smtc_mmiowb(reg, 0x3ce);
+ smtc_mmiowb(val, 0x3cf);
+}
+
+static inline unsigned int smtc_grphr(int reg)
+{
+ smtc_mmiowb(reg, 0x3ce);
+ return smtc_mmiorb(0x3cf);
+}
+
+static inline void smtc_attrw(int reg, int val)
+{
+ smtc_mmiorb(0x3da);
+ smtc_mmiowb(reg, 0x3c0);
+ smtc_mmiorb(0x3c1);
+ smtc_mmiowb(val, 0x3c0);
+}
+
+static inline void smtc_seqw(int reg, int val)
+{
+ smtc_mmiowb(reg, 0x3c4);
+ smtc_mmiowb(val, 0x3c5);
+}
+
+static inline unsigned int smtc_seqr(int reg)
+{
+ smtc_mmiowb(reg, 0x3c4);
+ return smtc_mmiorb(0x3c5);
+}
+
+/* The next structure holds all information relevant for a specific video mode.
+ */
+
+struct ModeInit {
+ int mmSizeX;
+ int mmSizeY;
+ int bpp;
+ int hz;
+ unsigned char Init_MISC;
+ unsigned char Init_SR00_SR04[SIZE_SR00_SR04];
+ unsigned char Init_SR10_SR24[SIZE_SR10_SR24];
+ unsigned char Init_SR30_SR75[SIZE_SR30_SR75];
+ unsigned char Init_SR80_SR93[SIZE_SR80_SR93];
+ unsigned char Init_SRA0_SRAF[SIZE_SRA0_SRAF];
+ unsigned char Init_GR00_GR08[SIZE_GR00_GR08];
+ unsigned char Init_AR00_AR14[SIZE_AR00_AR14];
+ unsigned char Init_CR00_CR18[SIZE_CR00_CR18];
+ unsigned char Init_CR30_CR4D[SIZE_CR30_CR4D];
+ unsigned char Init_CR90_CRA7[SIZE_CR90_CRA7];
+};
+
+/**********************************************************************
+ SM712 Mode table.
+ **********************************************************************/
+struct ModeInit VGAMode[] = {
+ {
+ /* mode#0: 640 x 480 16Bpp 60Hz */
+ 640, 480, 16, 60,
+ /* Init_MISC */
+ 0xE3,
+ { /* Init_SR0_SR4 */
+ 0x03, 0x01, 0x0F, 0x00, 0x0E,
+ },
+ { /* Init_SR10_SR24 */
+ 0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
+ 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xC4, 0x30, 0x02, 0x01, 0x01,
+ },
+ { /* Init_SR30_SR75 */
+ 0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
+ 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
+ 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+ 0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
+ 0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
+ 0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
+ 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+ 0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
+ 0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
+ },
+ { /* Init_SR80_SR93 */
+ 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
+ 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
+ 0x00, 0x00, 0x00, 0x00,
+ },
+ { /* Init_SRA0_SRAF */
+ 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+ 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
+ },
+ { /* Init_GR00_GR08 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+ 0xFF,
+ },
+ { /* Init_AR00_AR14 */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x41, 0x00, 0x0F, 0x00, 0x00,
+ },
+ { /* Init_CR00_CR18 */
+ 0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
+ 0xFF,
+ },
+ { /* Init_CR30_CR4D */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
+ 0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
+ 0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
+ },
+ { /* Init_CR90_CRA7 */
+ 0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
+ 0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
+ 0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
+ },
+ },
+ {
+ /* mode#1: 640 x 480 24Bpp 60Hz */
+ 640, 480, 24, 60,
+ /* Init_MISC */
+ 0xE3,
+ { /* Init_SR0_SR4 */
+ 0x03, 0x01, 0x0F, 0x00, 0x0E,
+ },
+ { /* Init_SR10_SR24 */
+ 0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
+ 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xC4, 0x30, 0x02, 0x01, 0x01,
+ },
+ { /* Init_SR30_SR75 */
+ 0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
+ 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
+ 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+ 0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
+ 0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
+ 0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
+ 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+ 0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
+ 0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
+ },
+ { /* Init_SR80_SR93 */
+ 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
+ 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
+ 0x00, 0x00, 0x00, 0x00,
+ },
+ { /* Init_SRA0_SRAF */
+ 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+ 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
+ },
+ { /* Init_GR00_GR08 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+ 0xFF,
+ },
+ { /* Init_AR00_AR14 */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x41, 0x00, 0x0F, 0x00, 0x00,
+ },
+ { /* Init_CR00_CR18 */
+ 0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
+ 0xFF,
+ },
+ { /* Init_CR30_CR4D */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
+ 0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
+ 0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
+ },
+ { /* Init_CR90_CRA7 */
+ 0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
+ 0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
+ 0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
+ },
+ },
+ {
+ /* mode#0: 640 x 480 32Bpp 60Hz */
+ 640, 480, 32, 60,
+ /* Init_MISC */
+ 0xE3,
+ { /* Init_SR0_SR4 */
+ 0x03, 0x01, 0x0F, 0x00, 0x0E,
+ },
+ { /* Init_SR10_SR24 */
+ 0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
+ 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xC4, 0x30, 0x02, 0x01, 0x01,
+ },
+ { /* Init_SR30_SR75 */
+ 0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
+ 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
+ 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+ 0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
+ 0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
+ 0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
+ 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+ 0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
+ 0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
+ },
+ { /* Init_SR80_SR93 */
+ 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
+ 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
+ 0x00, 0x00, 0x00, 0x00,
+ },
+ { /* Init_SRA0_SRAF */
+ 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+ 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
+ },
+ { /* Init_GR00_GR08 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+ 0xFF,
+ },
+ { /* Init_AR00_AR14 */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x41, 0x00, 0x0F, 0x00, 0x00,
+ },
+ { /* Init_CR00_CR18 */
+ 0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
+ 0xFF,
+ },
+ { /* Init_CR30_CR4D */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
+ 0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
+ 0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
+ },
+ { /* Init_CR90_CRA7 */
+ 0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
+ 0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
+ 0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
+ },
+ },
+
+ { /* mode#2: 800 x 600 16Bpp 60Hz */
+ 800, 600, 16, 60,
+ /* Init_MISC */
+ 0x2B,
+ { /* Init_SR0_SR4 */
+ 0x03, 0x01, 0x0F, 0x03, 0x0E,
+ },
+ { /* Init_SR10_SR24 */
+ 0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
+ 0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xC4, 0x30, 0x02, 0x01, 0x01,
+ },
+ { /* Init_SR30_SR75 */
+ 0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
+ 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
+ 0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
+ 0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
+ 0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
+ 0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
+ 0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+ 0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
+ 0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
+ },
+ { /* Init_SR80_SR93 */
+ 0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
+ 0x00, 0x00, 0x00, 0x00,
+ },
+ { /* Init_SRA0_SRAF */
+ 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+ 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
+ },
+ { /* Init_GR00_GR08 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+ 0xFF,
+ },
+ { /* Init_AR00_AR14 */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x41, 0x00, 0x0F, 0x00, 0x00,
+ },
+ { /* Init_CR00_CR18 */
+ 0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
+ 0xFF,
+ },
+ { /* Init_CR30_CR4D */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
+ 0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
+ 0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
+ },
+ { /* Init_CR90_CRA7 */
+ 0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
+ 0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
+ 0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
+ },
+ },
+ { /* mode#3: 800 x 600 24Bpp 60Hz */
+ 800, 600, 24, 60,
+ 0x2B,
+ { /* Init_SR0_SR4 */
+ 0x03, 0x01, 0x0F, 0x03, 0x0E,
+ },
+ { /* Init_SR10_SR24 */
+ 0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
+ 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xC4, 0x30, 0x02, 0x01, 0x01,
+ },
+ { /* Init_SR30_SR75 */
+ 0x36, 0x03, 0x20, 0x09, 0xC0, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x03, 0xFF,
+ 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+ 0x20, 0x0C, 0x44, 0x20, 0x00, 0x36, 0x36, 0x36,
+ 0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
+ 0x04, 0x55, 0x59, 0x36, 0x36, 0x00, 0x00, 0x36,
+ 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+ 0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
+ 0x02, 0x45, 0x30, 0x30, 0x40, 0x20,
+ },
+ { /* Init_SR80_SR93 */
+ 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x36,
+ 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x36, 0x36,
+ 0x00, 0x00, 0x00, 0x00,
+ },
+ { /* Init_SRA0_SRAF */
+ 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+ 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
+ },
+ { /* Init_GR00_GR08 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+ 0xFF,
+ },
+ { /* Init_AR00_AR14 */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x41, 0x00, 0x0F, 0x00, 0x00,
+ },
+ { /* Init_CR00_CR18 */
+ 0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
+ 0xFF,
+ },
+ { /* Init_CR30_CR4D */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
+ 0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
+ 0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
+ },
+ { /* Init_CR90_CRA7 */
+ 0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
+ 0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
+ 0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
+ },
+ },
+ { /* mode#7: 800 x 600 32Bpp 60Hz */
+ 800, 600, 32, 60,
+ /* Init_MISC */
+ 0x2B,
+ { /* Init_SR0_SR4 */
+ 0x03, 0x01, 0x0F, 0x03, 0x0E,
+ },
+ { /* Init_SR10_SR24 */
+ 0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
+ 0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xC4, 0x30, 0x02, 0x01, 0x01,
+ },
+ { /* Init_SR30_SR75 */
+ 0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
+ 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
+ 0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
+ 0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
+ 0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
+ 0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
+ 0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+ 0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
+ 0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
+ },
+ { /* Init_SR80_SR93 */
+ 0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
+ 0x00, 0x00, 0x00, 0x00,
+ },
+ { /* Init_SRA0_SRAF */
+ 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
+ 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
+ },
+ { /* Init_GR00_GR08 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+ 0xFF,
+ },
+ { /* Init_AR00_AR14 */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x41, 0x00, 0x0F, 0x00, 0x00,
+ },
+ { /* Init_CR00_CR18 */
+ 0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
+ 0xFF,
+ },
+ { /* Init_CR30_CR4D */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
+ 0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
+ 0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
+ },
+ { /* Init_CR90_CRA7 */
+ 0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
+ 0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
+ 0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
+ },
+ },
+ /* We use 1024x768 table to light 1024x600 panel for lemote */
+ { /* mode#4: 1024 x 600 16Bpp 60Hz */
+ 1024, 600, 16, 60,
+ /* Init_MISC */
+ 0xEB,
+ { /* Init_SR0_SR4 */
+ 0x03, 0x01, 0x0F, 0x00, 0x0E,
+ },
+ { /* Init_SR10_SR24 */
+ 0xC8, 0x40, 0x14, 0x60, 0x00, 0x0A, 0x17, 0x20,
+ 0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xC4, 0x30, 0x02, 0x00, 0x01,
+ },
+ { /* Init_SR30_SR75 */
+ 0x22, 0x03, 0x24, 0x09, 0xC0, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x03, 0xFF,
+ 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+ 0x20, 0x0C, 0x44, 0x20, 0x00, 0x22, 0x22, 0x22,
+ 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
+ 0x00, 0x60, 0x59, 0x22, 0x22, 0x00, 0x00, 0x22,
+ 0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+ 0x50, 0x03, 0x16, 0x02, 0x0D, 0x82, 0x09, 0x02,
+ 0x04, 0x45, 0x3F, 0x30, 0x40, 0x20,
+ },
+ { /* Init_SR80_SR93 */
+ 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
+ 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
+ 0x00, 0x00, 0x00, 0x00,
+ },
+ { /* Init_SRA0_SRAF */
+ 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
+ 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
+ },
+ { /* Init_GR00_GR08 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+ 0xFF,
+ },
+ { /* Init_AR00_AR14 */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x41, 0x00, 0x0F, 0x00, 0x00,
+ },
+ { /* Init_CR00_CR18 */
+ 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
+ 0xFF,
+ },
+ { /* Init_CR30_CR4D */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
+ 0xA3, 0x7F, 0x00, 0x82, 0x0b, 0x6f, 0x57, 0x00,
+ 0x5c, 0x0f, 0xE0, 0xe0, 0x7F, 0x57,
+ },
+ { /* Init_CR90_CRA7 */
+ 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
+ 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
+ },
+ },
+ { /* mode#5: 1024 x 768 24Bpp 60Hz */
+ 1024, 768, 24, 60,
+ /* Init_MISC */
+ 0xEB,
+ { /* Init_SR0_SR4 */
+ 0x03, 0x01, 0x0F, 0x03, 0x0E,
+ },
+ { /* Init_SR10_SR24 */
+ 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
+ 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xC4, 0x30, 0x02, 0x01, 0x01,
+ },
+ { /* Init_SR30_SR75 */
+ 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
+ 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
+ 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+ 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
+ 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
+ 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
+ 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+ 0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
+ 0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
+ },
+ { /* Init_SR80_SR93 */
+ 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
+ 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
+ 0x00, 0x00, 0x00, 0x00,
+ },
+ { /* Init_SRA0_SRAF */
+ 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
+ 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
+ },
+ { /* Init_GR00_GR08 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+ 0xFF,
+ },
+ { /* Init_AR00_AR14 */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x41, 0x00, 0x0F, 0x00, 0x00,
+ },
+ { /* Init_CR00_CR18 */
+ 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
+ 0xFF,
+ },
+ { /* Init_CR30_CR4D */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
+ 0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
+ 0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
+ },
+ { /* Init_CR90_CRA7 */
+ 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
+ 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
+ },
+ },
+ { /* mode#4: 1024 x 768 32Bpp 60Hz */
+ 1024, 768, 32, 60,
+ /* Init_MISC */
+ 0xEB,
+ { /* Init_SR0_SR4 */
+ 0x03, 0x01, 0x0F, 0x03, 0x0E,
+ },
+ { /* Init_SR10_SR24 */
+ 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
+ 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xC4, 0x32, 0x02, 0x01, 0x01,
+ },
+ { /* Init_SR30_SR75 */
+ 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
+ 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
+ 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+ 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
+ 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
+ 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
+ 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+ 0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
+ 0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
+ },
+ { /* Init_SR80_SR93 */
+ 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
+ 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
+ 0x00, 0x00, 0x00, 0x00,
+ },
+ { /* Init_SRA0_SRAF */
+ 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
+ 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
+ },
+ { /* Init_GR00_GR08 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+ 0xFF,
+ },
+ { /* Init_AR00_AR14 */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x41, 0x00, 0x0F, 0x00, 0x00,
+ },
+ { /* Init_CR00_CR18 */
+ 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
+ 0xFF,
+ },
+ { /* Init_CR30_CR4D */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
+ 0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
+ 0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
+ },
+ { /* Init_CR90_CRA7 */
+ 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
+ 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
+ },
+ },
+ { /* mode#6: 320 x 240 16Bpp 60Hz */
+ 320, 240, 16, 60,
+ /* Init_MISC */
+ 0xEB,
+ { /* Init_SR0_SR4 */
+ 0x03, 0x01, 0x0F, 0x03, 0x0E,
+ },
+ { /* Init_SR10_SR24 */
+ 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
+ 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xC4, 0x32, 0x02, 0x01, 0x01,
+ },
+ { /* Init_SR30_SR75 */
+ 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
+ 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
+ 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+ 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
+ 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
+ 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
+ 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+ 0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
+ 0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
+ },
+ { /* Init_SR80_SR93 */
+ 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
+ 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
+ 0x00, 0x00, 0x00, 0x00,
+ },
+ { /* Init_SRA0_SRAF */
+ 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
+ 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
+ },
+ { /* Init_GR00_GR08 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+ 0xFF,
+ },
+ { /* Init_AR00_AR14 */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x41, 0x00, 0x0F, 0x00, 0x00,
+ },
+ { /* Init_CR00_CR18 */
+ 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
+ 0xFF,
+ },
+ { /* Init_CR30_CR4D */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
+ 0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
+ 0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
+ 0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
+ },
+ { /* Init_CR90_CRA7 */
+ 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
+ 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
+ },
+ },
+
+ { /* mode#8: 320 x 240 32Bpp 60Hz */
+ 320, 240, 32, 60,
+ /* Init_MISC */
+ 0xEB,
+ { /* Init_SR0_SR4 */
+ 0x03, 0x01, 0x0F, 0x03, 0x0E,
+ },
+ { /* Init_SR10_SR24 */
+ 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
+ 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xC4, 0x32, 0x02, 0x01, 0x01,
+ },
+ { /* Init_SR30_SR75 */
+ 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
+ 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
+ 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
+ 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
+ 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
+ 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
+ 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
+ 0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
+ 0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
+ },
+ { /* Init_SR80_SR93 */
+ 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
+ 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
+ 0x00, 0x00, 0x00, 0x00,
+ },
+ { /* Init_SRA0_SRAF */
+ 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
+ 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
+ },
+ { /* Init_GR00_GR08 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+ 0xFF,
+ },
+ { /* Init_AR00_AR14 */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x41, 0x00, 0x0F, 0x00, 0x00,
+ },
+ { /* Init_CR00_CR18 */
+ 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
+ 0xFF,
+ },
+ { /* Init_CR30_CR4D */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
+ 0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
+ 0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
+ 0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
+ },
+ { /* Init_CR90_CRA7 */
+ 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
+ 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
+ },
+ },
+};
+
+#define numVGAModes (sizeof(VGAMode) / sizeof(struct ModeInit))
--
1.6.2.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [loongson-PATCH-v1 24/27] fixup for FUJITSU disk
[not found] <cover.1242855716.git.wuzhangjin@gmail.com>
` (2 preceding siblings ...)
2009-05-20 22:08 ` [loongson-PATCH-v1 16/27] Add Siliconmotion 712 framebuffer driver wuzhangjin
@ 2009-05-20 22:12 ` wuzhangjin
2009-05-22 18:32 ` Bartlomiej Zolnierkiewicz
2009-05-20 22:14 ` [loongson-PATCH-v1 27/27] add gcc 4.4 support for MIPS and loongson wuzhangjin
4 siblings, 1 reply; 20+ messages in thread
From: wuzhangjin @ 2009-05-20 22:12 UTC (permalink / raw)
To: linux-mips, Ralf Baechle
Cc: IDE/ATA development list, Linux Kernel, linux-scsi, Wu Zhangjin,
Yan hua, Philippe Vachon, Zhang Le, Zhang Fuxin, Arnaud Patard,
loongson-dev, gnewsense-dev, Nicholas Mc Guire, Liu Junliang,
Erwan Lerale
From: Wu Zhangjin <wuzhangjin@gmail.com>
This is originally from the to-mips branch from
http://dev.lemote.com/code/linux_loongson
Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
drivers/ide/amd74xx.c | 19 +++++++++++++++++++
1 files changed, 19 insertions(+), 0 deletions(-)
diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c
index 77267c8..8f488b8 100644
--- a/drivers/ide/amd74xx.c
+++ b/drivers/ide/amd74xx.c
@@ -23,6 +23,11 @@
#define DRV_NAME "amd74xx"
+static const char *am74xx_quirk_drives[] = {
+ "FUJITSU MHZ2160BH G2",
+ NULL
+};
+
enum {
AMD_IDE_CONFIG = 0x41,
AMD_CABLE_DETECT = 0x42,
@@ -112,6 +117,19 @@ static void amd_set_pio_mode(ide_drive_t *drive, const u8 pio)
amd_set_drive(drive, XFER_PIO_0 + pio);
}
+static void amd_quirkproc(ide_drive_t *drive)
+{
+ const char **list, *m = (char *)&drive->id[ATA_ID_PROD];
+
+ for (list = am74xx_quirk_drives; *list != NULL; list++)
+ if (strstr(m, *list) != NULL) {
+ drive->quirk_list = 2;
+ return;
+ }
+
+ drive->quirk_list = 0;
+}
+
static void amd7409_cable_detect(struct pci_dev *dev)
{
/* no host side cable detection */
@@ -194,6 +212,7 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
static const struct ide_port_ops amd_port_ops = {
.set_pio_mode = amd_set_pio_mode,
.set_dma_mode = amd_set_drive,
+ .quirkproc = amd_quirkproc,
.cable_detect = amd_cable_detect,
};
--
1.6.2.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [loongson-PATCH-v1 27/27] add gcc 4.4 support for MIPS and loongson
[not found] <cover.1242855716.git.wuzhangjin@gmail.com>
` (3 preceding siblings ...)
2009-05-20 22:12 ` [loongson-PATCH-v1 24/27] fixup for FUJITSU disk wuzhangjin
@ 2009-05-20 22:14 ` wuzhangjin
4 siblings, 0 replies; 20+ messages in thread
From: wuzhangjin @ 2009-05-20 22:14 UTC (permalink / raw)
To: linux-mips, Ralf Baechle
Cc: Linux Kernel, Wu Zhangjin, Yan hua, Philippe Vachon, Zhang Le,
Zhang Fuxin, Arnaud Patard, loongson-dev, gnewsense-dev,
Nicholas Mc Guire, Liu Junliang, Erwan Lerale
From: Wu Zhangjin <wuzhangjin@gmail.com>
the gcc 4.4 support for MIPS mostly refer to this PATCH:
http://www.nabble.com/-PATCH--MIPS:-Handle-removal-of-%27h%27-constraint-in-GCC-4.4-td22192768.html
but have been tuned a little.
because only gcc 4.4 have loongson-specific support, so, we need to
choose the suitable -march argument for gcc <= 4.3 and gcc >= 4.4, and
we also need to consider use -march=loongson2e and -march=loongson2f for
loongson2e and loongson2f respectively. this is handled by adding two
new kernel options: CPU_LOONGSON2E and CPU_LOONGSON2F(thanks for the
solutin provided by ZhangLe).
I have tested it on FuLoong(2f) in 32bit and 64bit with gcc-4.4 and
gcc-4.3. so, basically, it works.
Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
arch/mips/Makefile | 9 +++++-
arch/mips/include/asm/compiler.h | 10 ++++++
arch/mips/include/asm/delay.h | 58 +++++++++++++++++++++++++------------
arch/mips/include/asm/div64.h | 24 +++++++++++++--
4 files changed, 77 insertions(+), 24 deletions(-)
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 8bde363..f679731 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -119,7 +119,14 @@ cflags-$(CONFIG_CPU_R4300) += -march=r4300 -Wa,--trap
cflags-$(CONFIG_CPU_VR41XX) += -march=r4100 -Wa,--trap
cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap
cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap
-cflags-$(CONFIG_CPU_LOONGSON2) += -march=r4600 -Wa,--trap
+
+# only gcc >= 4.4 have the loongson-specific support
+cflags-$(CONFIG_CPU_LOONGSON2) += -Wa,--trap
+cflags-$(CONFIG_CPU_LOONGSON2E) += $(shell if [ $(call cc-version) -lt 0440 ] ; then \
+ echo $(call cc-option,-march=r4600); else echo $(call cc-option,-march=loongson2e); fi ;)
+cflags-$(CONFIG_CPU_LOONGSON2F) += $(shell if [ $(call cc-version) -lt 0440 ] ; then \
+ echo $(call cc-option,-march=r4600); else echo $(call cc-option,-march=loongson2f); fi ;)
+
cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
-Wa,-mips32 -Wa,--trap
cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
diff --git a/arch/mips/include/asm/compiler.h b/arch/mips/include/asm/compiler.h
index 71f5c5c..95256a8 100644
--- a/arch/mips/include/asm/compiler.h
+++ b/arch/mips/include/asm/compiler.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2004, 2007 Maciej W. Rozycki
+ * Copyright (C) 2009 Wu Zhangjin, wuzj@lemote.com
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -16,4 +17,13 @@
#define GCC_REG_ACCUM "accum"
#endif
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
+#define GCC_NO_H_CONSTRAINT
+#ifdef CONFIG_64BIT
+typedef unsigned int uintx_t __attribute__((mode(TI)));
+#else
+typedef u64 uintx_t;
+#endif
+#endif
+
#endif /* _ASM_COMPILER_H */
diff --git a/arch/mips/include/asm/delay.h b/arch/mips/include/asm/delay.h
index b0bccd2..00d7969 100644
--- a/arch/mips/include/asm/delay.h
+++ b/arch/mips/include/asm/delay.h
@@ -7,6 +7,7 @@
* Copyright (C) 1995 - 2000, 01, 03 by Ralf Baechle
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
* Copyright (C) 2007 Maciej W. Rozycki
+ * Copyright (C) 2009 Wu Zhangjin, wuzj@lemote.com
*/
#ifndef _ASM_DELAY_H
#define _ASM_DELAY_H
@@ -48,6 +49,43 @@ static inline void __delay(unsigned long loops)
: "0" (loops), "r" (1));
}
+/*
+ * convert usecs to loops
+ *
+ * handle removal of 'h' constraint in GCC 4.4
+ */
+
+#ifndef GCC_NO_H_CONSTRAINT /* gcc <= 4.3 */
+static inline unsigned long __usecs_to_loops(unsigned long usecs,
+ unsigned long lpj)
+{
+ unsigned long hi, lo;
+
+ if (sizeof(long) == 4)
+ __asm__("multu\t%2, %3"
+ : "=h" (usecs), "=l" (lo)
+ : "r" (usecs), "r" (lpj)
+ : GCC_REG_ACCUM);
+ else if (sizeof(long) == 8 && !R4000_WAR)
+ __asm__("dmultu\t%2, %3"
+ : "=h" (usecs), "=l" (lo)
+ : "r" (usecs), "r" (lpj)
+ : GCC_REG_ACCUM);
+ else if (sizeof(long) == 8 && R4000_WAR)
+ __asm__("dmultu\t%3, %4\n\tmfhi\t%0"
+ : "=r" (usecs), "=h" (hi), "=l" (lo)
+ : "r" (usecs), "r" (lpj)
+ : GCC_REG_ACCUM);
+
+ return usecs;
+}
+#else /* GCC_NO_H_CONSTRAINT, gcc >= 4.4 */
+static inline unsigned long __usecs_to_loops(unsigned long usecs,
+ unsigned long lpj)
+{
+ return ((uintx_t)usecs * lpj) >> BITS_PER_LONG;
+}
+#endif
/*
* Division by multiplication: you don't have to worry about
@@ -62,8 +100,6 @@ static inline void __delay(unsigned long loops)
static inline void __udelay(unsigned long usecs, unsigned long lpj)
{
- unsigned long hi, lo;
-
/*
* The rates of 128 is rounded wrongly by the catchall case
* for 64-bit. Excessive precission? Probably ...
@@ -77,23 +113,7 @@ static inline void __udelay(unsigned long usecs, unsigned long lpj)
0x80000000ULL) >> 32);
#endif
- if (sizeof(long) == 4)
- __asm__("multu\t%2, %3"
- : "=h" (usecs), "=l" (lo)
- : "r" (usecs), "r" (lpj)
- : GCC_REG_ACCUM);
- else if (sizeof(long) == 8 && !R4000_WAR)
- __asm__("dmultu\t%2, %3"
- : "=h" (usecs), "=l" (lo)
- : "r" (usecs), "r" (lpj)
- : GCC_REG_ACCUM);
- else if (sizeof(long) == 8 && R4000_WAR)
- __asm__("dmultu\t%3, %4\n\tmfhi\t%0"
- : "=r" (usecs), "=h" (hi), "=l" (lo)
- : "r" (usecs), "r" (lpj)
- : GCC_REG_ACCUM);
-
- __delay(usecs);
+ __delay(__usecs_to_loops(usecs, lpj));
}
#define __udelay_val cpu_data[raw_smp_processor_id()].udelay_val
diff --git a/arch/mips/include/asm/div64.h b/arch/mips/include/asm/div64.h
index d1d6991..6efc268 100644
--- a/arch/mips/include/asm/div64.h
+++ b/arch/mips/include/asm/div64.h
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2000, 2004 Maciej W. Rozycki
* Copyright (C) 2003, 07 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2009 Wu Zhangjin (wuzj@lemote.com)
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -56,6 +57,24 @@
(res) = __quot32; \
__mod32; })
+/*
+ * __do_divu -- unsigned interger dividing
+ *
+ * handle removal of 'h' constraint in GCC 4.4
+ */
+#ifndef GCC_NO_H_CONSTRAINT /* gcc <= 4.3*/
+#define __do_divu() ({ \
+ __asm__("divu $0, %z2, %z3" \
+ : "=h" (__upper), "=l" (__high) \
+ : "Jr" (__high), "Jr" (__base) \
+ : GCC_REG_ACCUM); })
+
+#else /* gcc >= 4.4 */
+#define __do_divu() ({ \
+ __upper = (uintx_t)__high % __base; \
+ __high = (uintx_t)__high / __base; })
+#endif
+
#define do_div(n, base) ({ \
unsigned long long __quot; \
unsigned long __mod; \
@@ -70,10 +89,7 @@
__upper = __high; \
\
if (__high) \
- __asm__("divu $0, %z2, %z3" \
- : "=h" (__upper), "=l" (__high) \
- : "Jr" (__high), "Jr" (__base) \
- : GCC_REG_ACCUM); \
+ __do_divu();\
\
__mod = do_div64_32(__low, __upper, __low, __base); \
\
--
1.6.2.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [loongson-PATCH-v1 24/27] fixup for FUJITSU disk
2009-05-20 22:12 ` [loongson-PATCH-v1 24/27] fixup for FUJITSU disk wuzhangjin
@ 2009-05-22 18:32 ` Bartlomiej Zolnierkiewicz
2009-05-23 7:11 ` yanh
0 siblings, 1 reply; 20+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2009-05-22 18:32 UTC (permalink / raw)
To: wuzhangjin
Cc: linux-mips, Ralf Baechle, IDE/ATA development list, Linux Kernel,
linux-scsi, Yan hua, Philippe Vachon, Zhang Le, Zhang Fuxin,
Arnaud Patard, loongson-dev, gnewsense-dev, Nicholas Mc Guire,
Liu Junliang, Erwan Lerale
On Thursday 21 May 2009 00:12:46 wuzhangjin@gmail.com wrote:
> From: Wu Zhangjin <wuzhangjin@gmail.com>
>
> This is originally from the to-mips branch from
> http://dev.lemote.com/code/linux_loongson
Sadly, the patch description lacks all the important information.
What is the original problem that this fixup tries to address?
Is it limited to amd74xx controllers?
[ We are generalizing quirk_drives handling currently... ]
> Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
> ---
> drivers/ide/amd74xx.c | 19 +++++++++++++++++++
> 1 files changed, 19 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c
> index 77267c8..8f488b8 100644
> --- a/drivers/ide/amd74xx.c
> +++ b/drivers/ide/amd74xx.c
> @@ -23,6 +23,11 @@
>
> #define DRV_NAME "amd74xx"
>
> +static const char *am74xx_quirk_drives[] = {
> + "FUJITSU MHZ2160BH G2",
> + NULL
> +};
> +
> enum {
> AMD_IDE_CONFIG = 0x41,
> AMD_CABLE_DETECT = 0x42,
> @@ -112,6 +117,19 @@ static void amd_set_pio_mode(ide_drive_t *drive, const u8 pio)
> amd_set_drive(drive, XFER_PIO_0 + pio);
> }
>
> +static void amd_quirkproc(ide_drive_t *drive)
> +{
> + const char **list, *m = (char *)&drive->id[ATA_ID_PROD];
> +
> + for (list = am74xx_quirk_drives; *list != NULL; list++)
> + if (strstr(m, *list) != NULL) {
> + drive->quirk_list = 2;
> + return;
> + }
> +
> + drive->quirk_list = 0;
> +}
> +
> static void amd7409_cable_detect(struct pci_dev *dev)
> {
> /* no host side cable detection */
> @@ -194,6 +212,7 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
> static const struct ide_port_ops amd_port_ops = {
> .set_pio_mode = amd_set_pio_mode,
> .set_dma_mode = amd_set_drive,
> + .quirkproc = amd_quirkproc,
> .cable_detect = amd_cable_detect,
> };
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [loongson-PATCH-v1 24/27] fixup for FUJITSU disk
2009-05-22 18:32 ` Bartlomiej Zolnierkiewicz
@ 2009-05-23 7:11 ` yanh
2009-05-23 11:47 ` Bartlomiej Zolnierkiewicz
0 siblings, 1 reply; 20+ messages in thread
From: yanh @ 2009-05-23 7:11 UTC (permalink / raw)
To: Bartlomiej Zolnierkiewicz
Cc: wuzhangjin, linux-mips, Ralf Baechle, IDE/ATA development list,
Linux Kernel, linux-scsi, Philippe Vachon, Zhang Le, Zhang Fuxin,
Arnaud Patard, loongson-dev, gnewsense-dev, Nicholas Mc Guire,
Liu Junliang, Erwan Lerale
在 2009-05-22五的 20:32 +0200,Bartlomiej Zolnierkiewicz写道:
> On Thursday 21 May 2009 00:12:46 wuzhangjin@gmail.com wrote:
> > From: Wu Zhangjin <wuzhangjin@gmail.com>
> >
> > This is originally from the to-mips branch from
> > http://dev.lemote.com/code/linux_loongson
>
> Sadly, the patch description lacks all the important information.
>
> What is the original problem that this fixup tries to address?
>
> Is it limited to amd74xx controllers?
In loongson2f yeeloong machines, the ide controller is AMD cs5536, or
say amd74xx, and the hard drives is Fujistu.
While debuging the hard disk suspned and resume, the ide irq can not be
cleared. I guess this is a fake interrupt, hence the clear irq action
can not be finished.
This patch is to fix this issue. Maybe other controller and drives also
have this issue, but I am not sure.
Thanks for your reply.
>
> [ We are generalizing quirk_drives handling currently... ]
>
> > Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
> > ---
> > drivers/ide/amd74xx.c | 19 +++++++++++++++++++
> > 1 files changed, 19 insertions(+), 0 deletions(-)
> >
> > diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c
> > index 77267c8..8f488b8 100644
> > --- a/drivers/ide/amd74xx.c
> > +++ b/drivers/ide/amd74xx.c
> > @@ -23,6 +23,11 @@
> >
> > #define DRV_NAME "amd74xx"
> >
> > +static const char *am74xx_quirk_drives[] = {
> > + "FUJITSU MHZ2160BH G2",
> > + NULL
> > +};
> > +
> > enum {
> > AMD_IDE_CONFIG = 0x41,
> > AMD_CABLE_DETECT = 0x42,
> > @@ -112,6 +117,19 @@ static void amd_set_pio_mode(ide_drive_t *drive, const u8 pio)
> > amd_set_drive(drive, XFER_PIO_0 + pio);
> > }
> >
> > +static void amd_quirkproc(ide_drive_t *drive)
> > +{
> > + const char **list, *m = (char *)&drive->id[ATA_ID_PROD];
> > +
> > + for (list = am74xx_quirk_drives; *list != NULL; list++)
> > + if (strstr(m, *list) != NULL) {
> > + drive->quirk_list = 2;
> > + return;
> > + }
> > +
> > + drive->quirk_list = 0;
> > +}
> > +
> > static void amd7409_cable_detect(struct pci_dev *dev)
> > {
> > /* no host side cable detection */
> > @@ -194,6 +212,7 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
> > static const struct ide_port_ops amd_port_ops = {
> > .set_pio_mode = amd_set_pio_mode,
> > .set_dma_mode = amd_set_drive,
> > + .quirkproc = amd_quirkproc,
> > .cable_detect = amd_cable_detect,
> > };
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [loongson-PATCH-v1 24/27] fixup for FUJITSU disk
2009-05-23 7:11 ` yanh
@ 2009-05-23 11:47 ` Bartlomiej Zolnierkiewicz
2009-05-25 5:45 ` yanh
0 siblings, 1 reply; 20+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2009-05-23 11:47 UTC (permalink / raw)
To: yanh
Cc: wuzhangjin, linux-mips, Ralf Baechle, IDE/ATA development list,
Linux Kernel, linux-scsi, Philippe Vachon, Zhang Le, Zhang Fuxin,
Arnaud Patard, loongson-dev, gnewsense-dev, Nicholas Mc Guire,
Liu Junliang, Erwan Lerale
On Saturday 23 May 2009 09:11:42 yanh wrote:
> 在 2009-05-22五的 20:32 +0200,Bartlomiej Zolnierkiewicz写道:
> > On Thursday 21 May 2009 00:12:46 wuzhangjin@gmail.com wrote:
> > > From: Wu Zhangjin <wuzhangjin@gmail.com>
> > >
> > > This is originally from the to-mips branch from
> > > http://dev.lemote.com/code/linux_loongson
> >
> > Sadly, the patch description lacks all the important information.
> >
> > What is the original problem that this fixup tries to address?
> >
> > Is it limited to amd74xx controllers?
>
> In loongson2f yeeloong machines, the ide controller is AMD cs5536, or
> say amd74xx, and the hard drives is Fujistu.
Then it should use the new & shiny :) native cs5536 IDE host driver
instead of legacy support in amd74xx...
> While debuging the hard disk suspned and resume, the ide irq can not be
> cleared. I guess this is a fake interrupt, hence the clear irq action
> can not be finished.
AFAICS the only change that the fixup would cause for suspend/resume paths
is the one in ide_config_drive_speed() which is called during resume to set
transfer mode on the drive:
tp_ops->write_devctl(hwif, ATA_NIEN | ATA_DEVCTL_OBS);
memset(&tf, 0, sizeof(tf));
tf.feature = SETFEATURES_XFER;
tf.nsect = speed;
tp_ops->tf_load(drive, &tf, IDE_VALID_FEATURE | IDE_VALID_NSECT);
tp_ops->exec_command(hwif, ATA_CMD_SET_FEATURES);
--->
if (drive->quirk_list == 2)
tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS);
--->
error = __ide_wait_stat(drive, drive->ready_stat,
ATA_BUSY | ATA_DRQ | ATA_ERR,
WAIT_CMD, &stat);
Please tell me I if understand the issue correctly: if the above quirk is
not executed we end up with spurious IRQs, right?
> This patch is to fix this issue. Maybe other controller and drives also
> have this issue, but I am not sure.
Probably moving it to a generic quirk_drives list later will be useful...
Anyway this fixup needs to be ported to / verified with cs5536 first.
Thanks.
Bart
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [loongson-PATCH-v1 24/27] fixup for FUJITSU disk
2009-05-23 11:47 ` Bartlomiej Zolnierkiewicz
@ 2009-05-25 5:45 ` yanh
2009-05-25 7:35 ` 胡洪兵
0 siblings, 1 reply; 20+ messages in thread
From: yanh @ 2009-05-25 5:45 UTC (permalink / raw)
To: Bartlomiej Zolnierkiewicz
Cc: wuzhangjin, linux-mips, Ralf Baechle, IDE/ATA development list,
Linux Kernel, linux-scsi, Philippe Vachon, Zhang Le, Zhang Fuxin,
Arnaud Patard, loongson-dev, gnewsense-dev, Nicholas Mc Guire,
Liu Junliang, Erwan Lerale
在 2009-05-23六的 13:47 +0200,Bartlomiej Zolnierkiewicz写道:
> On Saturday 23 May 2009 09:11:42 yanh wrote:
> > 在 2009-05-22五的 20:32 +0200,Bartlomiej Zolnierkiewicz写道:
> > > On Thursday 21 May 2009 00:12:46 wuzhangjin@gmail.com wrote:
> > > > From: Wu Zhangjin <wuzhangjin@gmail.com>
> > > >
> > > > This is originally from the to-mips branch from
> > > > http://dev.lemote.com/code/linux_loongson
> > >
> > > Sadly, the patch description lacks all the important information.
> > >
> > > What is the original problem that this fixup tries to address?
> > >
> > > Is it limited to amd74xx controllers?
> >
> > In loongson2f yeeloong machines, the ide controller is AMD cs5536, or
> > say amd74xx, and the hard drives is Fujistu.
>
> Then it should use the new & shiny :) native cs5536 IDE host driver
> instead of legacy support in amd74xx...
>
> > While debuging the hard disk suspned and resume, the ide irq can not be
> > cleared. I guess this is a fake interrupt, hence the clear irq action
> > can not be finished.
>
> AFAICS the only change that the fixup would cause for suspend/resume paths
> is the one in ide_config_drive_speed() which is called during resume to set
> transfer mode on the drive:
>
> tp_ops->write_devctl(hwif, ATA_NIEN | ATA_DEVCTL_OBS);
>
> memset(&tf, 0, sizeof(tf));
> tf.feature = SETFEATURES_XFER;
> tf.nsect = speed;
>
> tp_ops->tf_load(drive, &tf, IDE_VALID_FEATURE | IDE_VALID_NSECT);
>
> tp_ops->exec_command(hwif, ATA_CMD_SET_FEATURES);
> --->
> if (drive->quirk_list == 2)
> tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS);
> --->
> error = __ide_wait_stat(drive, drive->ready_stat,
> ATA_BUSY | ATA_DRQ | ATA_ERR,
> WAIT_CMD, &stat);
>
> Please tell me I if understand the issue correctly: if the above quirk is
> not executed we end up with spurious IRQs, right?
right.
>
> > This patch is to fix this issue. Maybe other controller and drives also
> > have this issue, but I am not sure.
>
> Probably moving it to a generic quirk_drives list later will be useful...
>
> Anyway this fixup needs to be ported to / verified with cs5536 first.
the cs5536 pata driver have some geode platform dependent codes. We can
just ignore it, but the performance is poor(using hdparm to test it),
which only get 22+ MB/s. we find it only use udma2. However if using
amd74xx driver, it can set udma5, and the speed can reach to 50+ MB/s.
we will test whether this driver is working well without this patch.
Anyway, thanks your advice.
>
> Thanks.
> Bart
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [loongson-PATCH-v1 24/27] fixup for FUJITSU disk
2009-05-25 5:45 ` yanh
@ 2009-05-25 7:35 ` 胡洪兵
2009-05-25 14:56 ` Bartlomiej Zolnierkiewicz
0 siblings, 1 reply; 20+ messages in thread
From: 胡洪兵 @ 2009-05-25 7:35 UTC (permalink / raw)
To: yanh
Cc: Bartlomiej Zolnierkiewicz, wuzhangjin, linux-mips, Ralf Baechle,
IDE/ATA development list, Linux Kernel, linux-scsi,
Philippe Vachon, Zhang Le, Zhang Fuxin, Arnaud Patard,
loongson-dev, gnewsense-dev, Nicholas Mc Guire, Liu Junliang,
Erwan Lerale
yanh 写道:
> 在 2009-05-23六的 13:47 +0200,Bartlomiej Zolnierkiewicz写道:
>
>> On Saturday 23 May 2009 09:11:42 yanh wrote:
>>
>>> 在 2009-05-22五的 20:32 +0200,Bartlomiej Zolnierkiewicz写道:
>>>
>>>> On Thursday 21 May 2009 00:12:46 wuzhangjin@gmail.com wrote:
>>>>
>>>>> From: Wu Zhangjin <wuzhangjin@gmail.com>
>>>>>
>>>>> This is originally from the to-mips branch from
>>>>> http://dev.lemote.com/code/linux_loongson
>>>>>
>>>> Sadly, the patch description lacks all the important information.
>>>>
>>>> What is the original problem that this fixup tries to address?
>>>>
>>>> Is it limited to amd74xx controllers?
>>>>
>>> In loongson2f yeeloong machines, the ide controller is AMD cs5536, or
>>> say amd74xx, and the hard drives is Fujistu.
>>>
>> Then it should use the new & shiny :) native cs5536 IDE host driver
>> instead of legacy support in amd74xx...
>>
>>
>>> While debuging the hard disk suspned and resume, the ide irq can not be
>>> cleared. I guess this is a fake interrupt, hence the clear irq action
>>> can not be finished.
>>>
>> AFAICS the only change that the fixup would cause for suspend/resume paths
>> is the one in ide_config_drive_speed() which is called during resume to set
>> transfer mode on the drive:
>>
>> tp_ops->write_devctl(hwif, ATA_NIEN | ATA_DEVCTL_OBS);
>>
>> memset(&tf, 0, sizeof(tf));
>> tf.feature = SETFEATURES_XFER;
>> tf.nsect = speed;
>>
>> tp_ops->tf_load(drive, &tf, IDE_VALID_FEATURE | IDE_VALID_NSECT);
>>
>> tp_ops->exec_command(hwif, ATA_CMD_SET_FEATURES);
>> --->
>> if (drive->quirk_list == 2)
>> tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS);
>>
>
>
>> --->
>> error = __ide_wait_stat(drive, drive->ready_stat,
>> ATA_BUSY | ATA_DRQ | ATA_ERR,
>> WAIT_CMD, &stat);
>>
>> Please tell me I if understand the issue correctly: if the above quirk is
>> not executed we end up with spurious IRQs, right?
>>
> right.
>
>>> This patch is to fix this issue. Maybe other controller and drives also
>>> have this issue, but I am not sure.
>>>
>> Probably moving it to a generic quirk_drives list later will be useful...
>>
>> Anyway this fixup needs to be ported to / verified with cs5536 first.
>>
> the cs5536 pata driver have some geode platform dependent codes. We can
> just ignore it, but the performance is poor(using hdparm to test it),
> which only get 22+ MB/s. we find it only use udma2. However if using
> amd74xx driver, it can set udma5, and the speed can reach to 50+ MB/s.
>
> we will test whether this driver is working well without this patch.
>
> Anyway, thanks your advice.
>
Use the driver drivers/ata/pata_cs5536.c, unfortunately it also have the
same issue.
>> Thanks.
>> Bart
>>
>>
>
>
>
>
--
---------------------------------------------------------
Hongbing,Hu (Software Department)
Tel: 0512-52308631
E-mail: huhb@lemote.com
MSN: [huhb04@gmail.com]
JiangSu Lemote Corp. Ltd.
MengLan, Yushan, Changshu, JiangSu Province, China
---------------------------------------------------------
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [loongson-PATCH-v1 24/27] fixup for FUJITSU disk
2009-05-25 7:35 ` 胡洪兵
@ 2009-05-25 14:56 ` Bartlomiej Zolnierkiewicz
2009-05-25 19:05 ` Sergei Shtylyov
0 siblings, 1 reply; 20+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2009-05-25 14:56 UTC (permalink / raw)
To: 胡洪兵
Cc: yanh, wuzhangjin, linux-mips, Ralf Baechle,
IDE/ATA development list, Linux Kernel, linux-scsi,
Philippe Vachon, Zhang Le, Zhang Fuxin, Arnaud Patard,
loongson-dev, gnewsense-dev, Nicholas Mc Guire, Liu Junliang,
Erwan Lerale
On Monday 25 May 2009 09:35:48 胡洪兵 wrote:
> yanh 写道:
[...]
> > the cs5536 pata driver have some geode platform dependent codes. We can
> > just ignore it, but the performance is poor(using hdparm to test it),
> > which only get 22+ MB/s. we find it only use udma2. However if using
> > amd74xx driver, it can set udma5, and the speed can reach to 50+ MB/s.
> >
> > we will test whether this driver is working well without this patch.
> >
> > Anyway, thanks your advice.
> >
> Use the driver drivers/ata/pata_cs5536.c, unfortunately it also have the
> same issue.
Both drivers (pata_cs5536 & cs5536) should handle UDMA5.
Could you please explain the issue with platform specific code a bit more?
Is it related to a cable detection by any chance?
Thanks.
Bart
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [loongson-PATCH-v1 24/27] fixup for FUJITSU disk
2009-05-25 14:56 ` Bartlomiej Zolnierkiewicz
@ 2009-05-25 19:05 ` Sergei Shtylyov
2009-05-25 19:10 ` Martin K. Petersen
0 siblings, 1 reply; 20+ messages in thread
From: Sergei Shtylyov @ 2009-05-25 19:05 UTC (permalink / raw)
To: Bartlomiej Zolnierkiewicz
Cc: 胡洪兵,
yanh, wuzhangjin, linux-mips, Ralf Baechle,
IDE/ATA development list, Linux Kernel, linux-scsi,
Philippe Vachon, Zhang Le, Zhang Fuxin, Arnaud Patard,
loongson-dev, gnewsense-dev, Nicholas Mc Guire, Liu Junliang,
Erwan Lerale
Bartlomiej Zolnierkiewicz wrote:
>>yanh 写道:
> [...]
>>>the cs5536 pata driver have some geode platform dependent codes. We can
>>>just ignore it, but the performance is poor(using hdparm to test it),
>>>which only get 22+ MB/s. we find it only use udma2. However if using
>>>amd74xx driver, it can set udma5, and the speed can reach to 50+ MB/s.
>>>we will test whether this driver is working well without this patch.
>>>Anyway, thanks your advice.
>>Use the driver drivers/ata/pata_cs5536.c, unfortunately it also have the
>>same issue.
> Both drivers (pata_cs5536 & cs5536) should handle UDMA5.
> Could you please explain the issue with platform specific code a bit more?
> Is it related to a cable detection by any chance?
I guess it's rdmsr()/wrmsr()...
> Thanks.
> Bart
MBR, Sergei
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [loongson-PATCH-v1 24/27] fixup for FUJITSU disk
2009-05-25 19:05 ` Sergei Shtylyov
@ 2009-05-25 19:10 ` Martin K. Petersen
2009-05-25 19:17 ` Sergei Shtylyov
2009-05-26 1:21 ` yanh
0 siblings, 2 replies; 20+ messages in thread
From: Martin K. Petersen @ 2009-05-25 19:10 UTC (permalink / raw)
To: Sergei Shtylyov
Cc: Bartlomiej Zolnierkiewicz, 胡洪兵,
yanh, wuzhangjin, linux-mips, Ralf Baechle,
IDE/ATA development list, Linux Kernel, linux-scsi,
Philippe Vachon, Zhang Le, Zhang Fuxin, Arnaud Patard,
loongson-dev, gnewsense-dev, Nicholas Mc Guire, Liu Junliang,
Erwan Lerale
>>>>> "Sergei" == Sergei Shtylyov <sshtylyov@ru.mvista.com> writes:
>> Could you please explain the issue with platform specific code a bit
>> more?
>> Is it related to a cable detection by any chance?
Sergei> I guess it's rdmsr()/wrmsr()...
Those are only used when the driver is explicitly loaded with
use_msr=1. The default is to use PCI config space/VSA.
In any case I have yet to see a CS5536 system whose BIOS sets the cable
detection bit. If that's the problem I guess we could add a quirk flag
to override the (lack of) BIOS setting.
--
Martin K. Petersen Oracle Linux Engineering
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [loongson-PATCH-v1 24/27] fixup for FUJITSU disk
2009-05-25 19:10 ` Martin K. Petersen
@ 2009-05-25 19:17 ` Sergei Shtylyov
2009-05-26 1:21 ` yanh
1 sibling, 0 replies; 20+ messages in thread
From: Sergei Shtylyov @ 2009-05-25 19:17 UTC (permalink / raw)
To: Martin K. Petersen
Cc: Bartlomiej Zolnierkiewicz, 胡洪兵,
yanh, wuzhangjin, linux-mips, Ralf Baechle,
IDE/ATA development list, Linux Kernel, linux-scsi,
Philippe Vachon, Zhang Le, Zhang Fuxin, Arnaud Patard,
loongson-dev, gnewsense-dev, Nicholas Mc Guire, Liu Junliang,
Erwan Lerale
Hello.
Martin K. Petersen wrote:
>>>Could you please explain the issue with platform specific code a bit
>>>more?
>>>Is it related to a cable detection by any chance?
> Sergei> I guess it's rdmsr()/wrmsr()...
> Those are only used when the driver is explicitly loaded with
> use_msr=1. The default is to use PCI config space/VSA.
But you need them defined for the driver to build...
MBR, Sergei
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [loongson-PATCH-v1 24/27] fixup for FUJITSU disk
2009-05-25 19:10 ` Martin K. Petersen
2009-05-25 19:17 ` Sergei Shtylyov
@ 2009-05-26 1:21 ` yanh
2009-05-26 7:56 ` Alan Cox
1 sibling, 1 reply; 20+ messages in thread
From: yanh @ 2009-05-26 1:21 UTC (permalink / raw)
To: Martin K. Petersen
Cc: Sergei Shtylyov, Bartlomiej Zolnierkiewicz,
胡洪兵,
wuzhangjin, linux-mips, Ralf Baechle, IDE/ATA development list,
Linux Kernel, linux-scsi, Philippe Vachon, Zhang Le, Zhang Fuxin,
Arnaud Patard, loongson-dev, gnewsense-dev, Nicholas Mc Guire,
Liu Junliang, Erwan Lerale
在 2009-05-25一的 15:10 -0400,Martin K. Petersen写道:
> >>>>> "Sergei" == Sergei Shtylyov <sshtylyov@ru.mvista.com> writes:
>
> >> Could you please explain the issue with platform specific code a bit
> >> more?
>
> >> Is it related to a cable detection by any chance?
>
> Sergei> I guess it's rdmsr()/wrmsr()...
currently, we just commented out the rdmsr/wrmsr.
and we use pci VSA to access it.
>
> Those are only used when the driver is explicitly loaded with
> use_msr=1. The default is to use PCI config space/VSA.
>
> In any case I have yet to see a CS5536 system whose BIOS sets the cable
> detection bit. If that's the problem I guess we could add a quirk flag
> to override the (lack of) BIOS setting.
>
This may be the cause that udma5 cannot be set.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [loongson-PATCH-v1 24/27] fixup for FUJITSU disk
2009-05-26 1:21 ` yanh
@ 2009-05-26 7:56 ` Alan Cox
2009-05-26 14:39 ` yanh
0 siblings, 1 reply; 20+ messages in thread
From: Alan Cox @ 2009-05-26 7:56 UTC (permalink / raw)
To: yanh
Cc: Martin K. Petersen, Sergei Shtylyov, Bartlomiej Zolnierkiewicz,
胡洪兵,
wuzhangjin, linux-mips, Ralf Baechle, IDE/ATA development list,
Linux Kernel, linux-scsi, Philippe Vachon, Zhang Le, Zhang Fuxin,
Arnaud Patard, loongson-dev, gnewsense-dev, Nicholas Mc Guire,
Liu Junliang, Erwan Lerale
> > In any case I have yet to see a CS5536 system whose BIOS sets the cable
> > detection bit. If that's the problem I guess we could add a quirk flag
> > to override the (lack of) BIOS setting.
> >
> This may be the cause that udma5 cannot be set.
If the system doesn't have working BIOS cable detect as per the
documentation for the chip then just return the "unknown" cable type and
libata will do device side cable detect.
Alan
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [loongson-PATCH-v1 24/27] fixup for FUJITSU disk
2009-05-26 7:56 ` Alan Cox
@ 2009-05-26 14:39 ` yanh
0 siblings, 0 replies; 20+ messages in thread
From: yanh @ 2009-05-26 14:39 UTC (permalink / raw)
To: Alan Cox
Cc: Martin K. Petersen, Sergei Shtylyov, Bartlomiej Zolnierkiewicz,
胡洪兵,
wuzhangjin, linux-mips, Ralf Baechle, IDE/ATA development list,
Linux Kernel, linux-scsi, Philippe Vachon, Zhang Le, Zhang Fuxin,
Arnaud Patard, loongson-dev, gnewsense-dev, Nicholas Mc Guire,
Liu Junliang, Erwan Lerale
在 2009-05-26二的 08:56 +0100,Alan Cox写道:
> > > In any case I have yet to see a CS5536 system whose BIOS sets the cable
> > > detection bit. If that's the problem I guess we could add a quirk flag
> > > to override the (lack of) BIOS setting.
> > >
> > This may be the cause that udma5 cannot be set.
>
>
> If the system doesn't have working BIOS cable detect as per the
> documentation for the chip then just return the "unknown" cable type and
> libata will do device side cable detect.
After force cable type as 80 wire, udma5 can be set OK now.
after some raw test, the legacy and native driver have no obvious
difference in performance.
Remain issue: this native driver still have suspend/resume issue.
>
> Alan
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [loongson-PATCH-v1 16/27] Add Siliconmotion 712 framebuffer driver
2009-05-20 22:08 ` [loongson-PATCH-v1 16/27] Add Siliconmotion 712 framebuffer driver wuzhangjin
@ 2009-05-29 13:29 ` Simon Braunschmidt
2009-05-29 19:51 ` Wu Zhangjin
2009-06-01 7:41 ` Wu Zhangjin
0 siblings, 2 replies; 20+ messages in thread
From: Simon Braunschmidt @ 2009-05-29 13:29 UTC (permalink / raw)
To: wuzhangjin; +Cc: linux-mips, linux-kernel
Hi Wu Zhangjin
I applied your patch cleanly and run it on a i486SX (little endian)
embedded computing board.
This provides a huge performance benefit compared to vesa framebuffer,
so thanks a lot for the contribution.
I tested it in both the library-accelerated (cfb...) and hardware
accelerated codepaths, with no problems. Tested with qt-embedded 4.5.1.
As i have seen lots of functionality are guarded by
#ifdef __BIG_ENDIAN
Is there a way to setup a different mode than 1024x600 on
kernel-commandline or from userspace, e.g. with fbset?
What I currently do is
picking appropriate values form the table VGAMode in smtcfb.h and
hardcoding them.
I tried 800x600x16bit@60hz, which worked also, but 1024x768x24bit@60hz
left me with a corrupted display output (distored colors, missing
regions), i did not check further wheter it also crashed.
I dont know wheter i am subscribed and this will make it through to lkml
and linux-mips, feel free to cite me if you want.
Also if you want you may add my
Tested-by: Simon Braunschmidt <sbraun@emlix.com>
see also attached a patch for the debug messages
From addec9a5a27512621c538a2f799e31e07720cb9c Mon Sep 17 00:00:00 2001
From: Simon Braunschmidt <sbraun@emlix.com>
Date: Fri, 29 May 2009 15:03:51 +0200
Subject: [PATCH] [video] fix debug messages in smtcfb
when defining #DEBUG
---
drivers/video/smi/smtcfb.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/video/smi/smtcfb.c b/drivers/video/smi/smtcfb.c
index 33ce878..ebc6371 100644
--- a/drivers/video/smi/smtcfb.c
+++ b/drivers/video/smi/smtcfb.c
@@ -44,6 +44,8 @@
#include "smtcfb.h"
#include "smtc2d.h"
+#define DEBUG
+
#ifdef DEBUG
#define smdbg(format, arg...) printk(KERN_DEBUG format , ## arg)
#else
@@ -1087,7 +1089,7 @@ static int __init sm712be_setup(char *options)
sm712be_flag = 0;
if (!options || !*options) {
retval = 1;
- smdbg("\n No sm712be parameter\n", __LINE__);
+ smdbg("\n No sm712be parameter\n");
}
if (!retval && strstr(options, "enable"))
sm712be_flag = 1;
@@ -1113,7 +1115,7 @@ static int __init sm712vga_setup(char *options)
if (!options || !*options) {
retval = 1;
- smdbg("\n No vga parameter\n", __LINE__);
+ smdbg("\n No vga parameter\n");
}
screen_info.lfb_width = 0;
--
1.6.3.rc0.1.gf800
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [loongson-PATCH-v1 16/27] Add Siliconmotion 712 framebuffer driver
2009-05-29 13:29 ` Simon Braunschmidt
@ 2009-05-29 19:51 ` Wu Zhangjin
2009-06-01 7:41 ` Wu Zhangjin
1 sibling, 0 replies; 20+ messages in thread
From: Wu Zhangjin @ 2009-05-29 19:51 UTC (permalink / raw)
To: Simon Braunschmidt, boyod.yang, gewang; +Cc: linux-mips, linux-kernel
Hi,
On Fri, 2009-05-29 at 15:29 +0200, Simon Braunschmidt wrote:
> Hi Wu Zhangjin
>
> I applied your patch cleanly and run it on a i486SX (little endian)
> embedded computing board.
thanks very much for testing it in a non-mips platform!
> This provides a huge performance benefit compared to vesa framebuffer,
> so thanks a lot for the contribution.
>
the thanks should goes to the original authors from Silicon Motion
Technology Corp. including Ge Wang and Boyod.Yang. I just cleaned it up.
> I tested it in both the library-accelerated (cfb...) and hardware
> accelerated codepaths, with no problems. Tested with qt-embedded 4.5.1.
>
> As i have seen lots of functionality are guarded by
> #ifdef __BIG_ENDIAN
>
> Is there a way to setup a different mode than 1024x600 on
> kernel-commandline or from userspace, e.g. with fbset?
>
seems we can change it in userspace, i have changed it to 800X480 in a
7inch yeeloong2f laptop in the "control center" of KDE desktop.
or perhaps you can configure it in the Xorg.conf directly.
> What I currently do is
> picking appropriate values form the table VGAMode in smtcfb.h and
> hardcoding them.
>
> I tried 800x600x16bit@60hz, which worked also, but 1024x768x24bit@60hz
> left me with a corrupted display output (distored colors, missing
> regions), i did not check further wheter it also crashed.
>
I will try to check it, but in reality, I'm not familiar with it, so
maybe very hard and slow to check it. I will forward this E-mail to the
original authors, hope they can give some help.
> I dont know wheter i am subscribed and this will make it through to lkml
> and linux-mips, feel free to cite me if you want.
>
> Also if you want you may add my
>
> Tested-by: Simon Braunschmidt <sbraun@emlix.com>
>
added.
>
> see also attached a patch for the debug messages
>
>
Applied.
thanks!
Wu Zhangjin
>
> From addec9a5a27512621c538a2f799e31e07720cb9c Mon Sep 17 00:00:00 2001
> From: Simon Braunschmidt <sbraun@emlix.com>
> Date: Fri, 29 May 2009 15:03:51 +0200
> Subject: [PATCH] [video] fix debug messages in smtcfb
>
> when defining #DEBUG
> ---
> drivers/video/smi/smtcfb.c | 6 ++++--
> 1 files changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/video/smi/smtcfb.c b/drivers/video/smi/smtcfb.c
> index 33ce878..ebc6371 100644
> --- a/drivers/video/smi/smtcfb.c
> +++ b/drivers/video/smi/smtcfb.c
> @@ -44,6 +44,8 @@
> #include "smtcfb.h"
> #include "smtc2d.h"
>
> +#define DEBUG
> +
> #ifdef DEBUG
> #define smdbg(format, arg...) printk(KERN_DEBUG format , ## arg)
> #else
> @@ -1087,7 +1089,7 @@ static int __init sm712be_setup(char *options)
> sm712be_flag = 0;
> if (!options || !*options) {
> retval = 1;
> - smdbg("\n No sm712be parameter\n", __LINE__);
> + smdbg("\n No sm712be parameter\n");
> }
> if (!retval && strstr(options, "enable"))
> sm712be_flag = 1;
> @@ -1113,7 +1115,7 @@ static int __init sm712vga_setup(char *options)
>
> if (!options || !*options) {
> retval = 1;
> - smdbg("\n No vga parameter\n", __LINE__);
> + smdbg("\n No vga parameter\n");
> }
>
> screen_info.lfb_width = 0;
> --
> 1.6.3.rc0.1.gf800
>
>
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [loongson-PATCH-v1 16/27] Add Siliconmotion 712 framebuffer driver
2009-05-29 13:29 ` Simon Braunschmidt
2009-05-29 19:51 ` Wu Zhangjin
@ 2009-06-01 7:41 ` Wu Zhangjin
1 sibling, 0 replies; 20+ messages in thread
From: Wu Zhangjin @ 2009-06-01 7:41 UTC (permalink / raw)
To: Simon Braunschmidt; +Cc: linux-mips, linux-kernel
hi,
> As i have seen lots of functionality are guarded by
> #ifdef __BIG_ENDIAN
>
> Is there a way to setup a different mode than 1024x600 on
> kernel-commandline or from userspace, e.g. with fbset?
>
I just removed some of #ifdef __BIG_ENDIAN ... #endif, and tuned the
vesa_mode values, now, we can pass it in kernel-commandline like this:
vga=1024x600x24
the latest SMI video driver patch with this modification will be sent
out later, but you can get this one if you need it immediately:
>From 34e4afa8b64f794e4fef0dd622ef576dbfecc851 Mon Sep 17 00:00:00 2001
From: Wu Zhangjin <wuzj@lemote.com>
Date: Mon, 1 Jun 2009 15:31:26 +0800
Subject: [PATCH] enable the vga command line in SMI video driver
there is no need to define a screen_info again so remove it, because it
is defined in arch/mips/kernel/setup.c and not relative to big endian or
little endian, and here I think its better use something like
1024x600x24 than 0x318, so replace all of the magic numbers to an
understandable one.
Signed-off-by: Wu Zhangjin <wuzj@lemote.com>
---
drivers/video/smi/smtcfb.c | 42
++++++++++++++++++------------------------
1 files changed, 18 insertions(+), 24 deletions(-)
diff --git a/drivers/video/smi/smtcfb.c b/drivers/video/smi/smtcfb.c
index ebc6371..4fe940b 100644
--- a/drivers/video/smi/smtcfb.c
+++ b/drivers/video/smi/smtcfb.c
@@ -52,10 +52,6 @@
#define smdbg(format, arg...)
#endif
-#ifdef __BIG_ENDIAN
-struct screen_info screen_info;
-#endif
-
/*
* Private structure
*/
@@ -96,32 +92,32 @@ struct par_info {
u8 chipRevID;
};
-#ifdef __BIG_ENDIAN
struct vesa_mode_table {
- char mode_index[6];
+ char mode_index[15];
u16 lfb_width;
u16 lfb_height;
u16 lfb_depth;
};
static struct vesa_mode_table vesa_mode[] = {
- {"0x301", 640, 480, 8},
- {"0x303", 800, 600, 8},
- {"0x305", 1024, 768, 8},
- {"0x307", 1280, 1024, 8},
-
- {"0x311", 640, 480, 16},
- {"0x314", 800, 600, 16},
- {"0x317", 1024, 768, 16},
- {"0x31A", 1280, 1024, 16},
-
- {"0x312", 640, 480, 24},
- {"0x315", 800, 600, 24},
- {"0x318", 1024, 768, 24},
- {"0x31B", 1280, 1024, 24},
-
+ {"640x480x8", 640, 480, 8},
+ {"800x480x8", 800, 480, 8},
+ {"800x600x8", 800, 600, 8},
+ {"1024x768x8", 1024, 768, 8},
+ {"1280x1024x8", 1280, 1024, 8},
+
+ {"640x480x16", 640, 480, 16},
+ {"800x480x16", 800, 480, 16},
+ {"800x600x16", 800, 600, 16},
+ {"1024x768x16", 1024, 768, 16},
+ {"1280x1024x16", 1280, 1024, 16},
+
+ {"640x480x24", 640, 480, 24},
+ {"800x480x24", 800, 480, 24},
+ {"800x600x24", 800, 600, 24},
+ {"1024x768x24", 1024, 768, 24},
+ {"1280x1024x24", 1280, 1024, 24},
};
-#endif
char __iomem *smtc_RegBaseAddress; /* Memory Map IO starting address */
char __iomem *smtc_VRAMBaseAddress; /* video memory starting address */
@@ -1100,7 +1096,6 @@ static int __init sm712be_setup(char *options)
__setup("sm712be=", sm712be_setup);
-#ifdef __BIG_ENDIAN
/*
* sm712vga_setup - process command line options, get vga parameter
* @options: string of options
@@ -1136,7 +1131,6 @@ static int __init sm712vga_setup(char *options)
}
__setup("vga=", sm712vga_setup);
-#endif
MODULE_AUTHOR("Siliconmotion ");
MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards");
--
1.6.0.4
with the support of this patch, the users of 7inch yeeloong and 8.9inch
yeeloong can use the same kernel(not totally, the shutdown logic is a
little different, a patch is also ready for it).
there is only a need to add such kernel command line for 7inch yeeloong:
vga=800x480x24
> What I currently do is
> picking appropriate values form the table VGAMode in smtcfb.h and
> hardcoding them.
>
> I tried 800x600x16bit@60hz, which worked also, but 1024x768x24bit@60hz
> left me with a corrupted display output (distored colors, missing
> regions), i did not check further wheter it also crashed.
>
no all of the Vesa mode is suitable to your screen, you should choose
one for you, for example, only 800x480 is suitable to yeeloong 7inch
screen, but the 8.9 inch yeeloong, need 1024x600.
best regards,
Wu Zhangjin
^ permalink raw reply related [flat|nested] 20+ messages in thread
end of thread, other threads:[~2009-06-01 7:41 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <cover.1242855716.git.wuzhangjin@gmail.com>
2009-05-20 22:05 ` [loongson-PATCH-v1 12/27] add basic loongson-2f support wuzhangjin
2009-05-20 22:06 ` [loongson-PATCH-v1 13/27] add basic fuloong(2f) support wuzhangjin
2009-05-20 22:08 ` [loongson-PATCH-v1 16/27] Add Siliconmotion 712 framebuffer driver wuzhangjin
2009-05-29 13:29 ` Simon Braunschmidt
2009-05-29 19:51 ` Wu Zhangjin
2009-06-01 7:41 ` Wu Zhangjin
2009-05-20 22:12 ` [loongson-PATCH-v1 24/27] fixup for FUJITSU disk wuzhangjin
2009-05-22 18:32 ` Bartlomiej Zolnierkiewicz
2009-05-23 7:11 ` yanh
2009-05-23 11:47 ` Bartlomiej Zolnierkiewicz
2009-05-25 5:45 ` yanh
2009-05-25 7:35 ` 胡洪兵
2009-05-25 14:56 ` Bartlomiej Zolnierkiewicz
2009-05-25 19:05 ` Sergei Shtylyov
2009-05-25 19:10 ` Martin K. Petersen
2009-05-25 19:17 ` Sergei Shtylyov
2009-05-26 1:21 ` yanh
2009-05-26 7:56 ` Alan Cox
2009-05-26 14:39 ` yanh
2009-05-20 22:14 ` [loongson-PATCH-v1 27/27] add gcc 4.4 support for MIPS and loongson wuzhangjin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).