summaryrefslogtreecommitdiffstats
path: root/target/linux/realtek/files/arch/mips/rtl8196b
diff options
context:
space:
mode:
authorRoman Yeryomin <roman@advem.lv>2012-09-13 00:40:35 +0300
committerRoman Yeryomin <roman@advem.lv>2012-12-03 00:13:21 +0200
commit5deb3317cb51ac52de922bb55f8492624018906d (patch)
treec2fbe6346699d9bb0f2100490c3029519bb8fde8 /target/linux/realtek/files/arch/mips/rtl8196b
parent0239d37124f9184b478a42de8a7fa1bc85a6a6fe (diff)
Add realtek target files
Signed-off-by: Roman Yeryomin <roman@advem.lv>
Diffstat (limited to 'target/linux/realtek/files/arch/mips/rtl8196b')
-rw-r--r--target/linux/realtek/files/arch/mips/rtl8196b/Makefile9
-rw-r--r--target/linux/realtek/files/arch/mips/rtl8196b/int.c281
-rw-r--r--target/linux/realtek/files/arch/mips/rtl8196b/mem.c133
-rw-r--r--target/linux/realtek/files/arch/mips/rtl8196b/pci-rtl8196.c526
-rw-r--r--target/linux/realtek/files/arch/mips/rtl8196b/pci.h75
-rw-r--r--target/linux/realtek/files/arch/mips/rtl8196b/printf.c51
-rw-r--r--target/linux/realtek/files/arch/mips/rtl8196b/setup.c191
-rw-r--r--target/linux/realtek/files/arch/mips/rtl8196b/timer.c80
8 files changed, 1346 insertions, 0 deletions
diff --git a/target/linux/realtek/files/arch/mips/rtl8196b/Makefile b/target/linux/realtek/files/arch/mips/rtl8196b/Makefile
new file mode 100644
index 000000000..f7e8766ca
--- /dev/null
+++ b/target/linux/realtek/files/arch/mips/rtl8196b/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the RTL8652 specific parts of the kernel
+#
+DIR_RTLASIC = $(DIR_LINUX)/drivers/net/rtl819x/
+
+obj-y := setup.o printf.o int.o mem.o
+obj-$(CONFIG_PCI) += pci.o
+EXTRA_AFLAGS := $(CFLAGS)
+EXTRA_CFLAGS += -I$(DIR_RTLASIC)
diff --git a/target/linux/realtek/files/arch/mips/rtl8196b/int.c b/target/linux/realtek/files/arch/mips/rtl8196b/int.c
new file mode 100644
index 000000000..fd8699a23
--- /dev/null
+++ b/target/linux/realtek/files/arch/mips/rtl8196b/int.c
@@ -0,0 +1,281 @@
+#include <linux/config.h>
+#include <linux/irq.h>
+
+#include <asm/irq_cpu.h>
+#include <prom.h>
+#include <platform.h>
+#include <linux/hardirq.h>
+#if defined(CONFIG_RTL_819X)
+#include <common/rtl_types.h>
+#endif
+
+spinlock_t irq_lock = SPIN_LOCK_UNLOCKED;
+
+static void rtl8196_enable_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&irq_lock, flags);
+ REG32(GIMR) = REG32(GIMR) | (1 << irq);
+ spin_unlock_irqrestore(&irq_lock, flags);
+}
+
+static unsigned int rtl8196_startup_irq(unsigned int irq)
+{
+ rtl8196_enable_irq(irq);
+
+ return 0;
+}
+
+static void rtl8196_disable_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&irq_lock, flags);
+ REG32(GIMR) = REG32(GIMR) & (~(1 << irq));
+ spin_unlock_irqrestore(&irq_lock, flags);
+}
+
+static void rtl8196_end_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&irq_lock, flags);
+ REG32(GIMR) = REG32(GIMR) | (1 << irq);
+ spin_unlock_irqrestore(&irq_lock, flags);
+}
+
+#define rtl8196_shutdown_irq rtl8196_disable_irq
+#define rtl8196_mask_and_ack_irq rtl8196_disable_irq
+
+static struct irq_chip irq_type = {
+ .typename = "RTL8196",
+ .startup = rtl8196_startup_irq,
+ .shutdown = rtl8196_shutdown_irq,
+ .enable = rtl8196_enable_irq,
+ .disable = rtl8196_disable_irq,
+ .ack = rtl8196_mask_and_ack_irq,
+ .end = rtl8196_end_irq,
+ .mask = rtl8196_disable_irq,
+ .mask_ack = rtl8196_mask_and_ack_irq,
+ .unmask = rtl8196_enable_irq,
+};
+
+
+/*
+ * RTL8196b Interrupt Scheme (Subject to change)
+ *
+ * Source EXT_INT IRQ CPU INT
+ * -------- ------- ------ -------
+ * PCIB0TO 0 0 2
+ * PCIB1TO 1 1 2
+ * LBCTMOm0 2 2 2
+ * LBCTMOm1 3 3 2
+ * LBCTMOs 4 4 2
+ * TIMER0 8 8 7
+ * TIMER1 9 9 2
+ * USB 10 10 4
+ * UART0 12 12 3
+ * UART1 13 13 2
+ * PCI 14 14 5
+ * SWCORE 15 15 6
+ * GPIO_ABCD 16 16 2
+ * GPIO_EFGH 17 17 2
+ * HCI 18 18 2
+ * PCM 19 19 2
+ * CRYPTO 20 20 2
+ * GDMA 21 21 2
+ */
+
+void __init arch_init_irq(void)
+{
+ int i;
+
+ /* Initialize for IRQ: 0~31 */
+ for (i = 0; i < 32; i++) {
+ //irq_desc[i].chip = &irq_type;
+ set_irq_chip_and_handler(i, &irq_type, handle_level_irq);
+ }
+
+ /* Enable all interrupt mask of CPU */
+ write_c0_status(read_c0_status() | ST0_IM);
+
+ /* Set GIMR, IRR */
+ REG32(GIMR) = TC0_IE | UART0_IE |SW_IE ;
+
+ REG32(IRR0) = IRR0_SETTING;
+ REG32(IRR1) = IRR1_SETTING;
+ REG32(IRR2) = IRR2_SETTING;
+ REG32(IRR3) = IRR3_SETTING;
+}
+
+#define ST0_USED_IM (_ULCAST_(0xfc00)) /* interrupt 2/3/4/5/6/7 */
+#define ST0_REENTRY_IM (_ULCAST_(0xe000)) /* interrupt 5/6/7 */
+
+__IRAM_GEN asmlinkage void plat_irq_dispatch(void)
+{
+#if 0
+ unsigned int cpuint_ip;
+ unsigned int cpuint_mask;
+ unsigned int extint_ip;
+
+ cpuint_mask = read_c0_status() & ST0_IM;
+ cpuint_ip = read_c0_cause() & read_c0_status() & ST0_IM;
+
+#if 1
+ write_c0_status(read_c0_status()&(~ST0_IM));
+#else
+ write_c0_status((read_c0_status()&(~ST0_IM))|(cpuint_mask&(~(STATUSF_IP6|STATUSF_IP5))));
+#endif
+
+ do
+ {
+ if (cpuint_ip & CAUSEF_IP7)
+ {
+ /* Timer 0 */
+ do_IRQ(TC0_IRQ);
+ }
+ else if (cpuint_ip & CAUSEF_IP5)
+ {
+ /* PCIE */
+ do_IRQ(PCIE_IRQ);
+ }
+ if (cpuint_ip & CAUSEF_IP6)
+ {
+ /* switch core*/
+ do_IRQ(SWCORE_IRQ);
+
+ }
+ else if (cpuint_ip & CAUSEF_IP3)
+ {
+ /* pci */
+ do_IRQ(PCI_IRQ);
+ }
+ else if (cpuint_ip & CAUSEF_IP4)
+ {
+ /*USB*/
+ do_IRQ(USB_IRQ);
+ }
+ else if (cpuint_ip & CAUSEF_IP2)
+ {
+ /* For shared interrupts */
+ unsigned int extint_ip = REG32(GIMR) & REG32(GISR);
+
+ if (extint_ip & UART0_IP)
+ {
+ /* UART 0 */
+ do_IRQ(UART0_IRQ);
+ }
+ else if (extint_ip & TC1_IP)
+ {
+ do_IRQ(TC1_IRQ);
+ }
+#if 0
+ /* currently we do not use uart1 */
+ else if (extint_ip & UART1_IP)
+ {
+ do_IRQ(UART1_IRQ);
+ }
+#endif
+ else
+ {
+ prom_printf("Unknown Interrupt2:%x\n",extint_ip);
+ REG32(GISR) = extint_ip;
+ }
+ }
+
+ cpuint_ip = read_c0_cause() & (STATUSF_IP6|STATUSF_IP5|STATUSF_IP7);
+ } while(cpuint_ip);
+
+#if 0 /* patch for wds+wep hang up issue */
+ write_c0_status((read_c0_status()&(~ST0_IM))|(cpuint_mask));
+#else
+ write_c0_status((read_c0_status()|(ST0_IM)));
+#endif
+#else
+ unsigned int cpuint_ip;
+ unsigned int extint_ip;
+
+ cpuint_ip = read_c0_cause() & ST0_USED_IM;
+ write_c0_status(read_c0_status()&(~ST0_IM));
+
+#if 0
+ if ( ST0_REENTRY_IM & cpuint_ip )
+ {
+ do
+ {
+ if (cpuint_ip & CAUSEF_IP7)
+ {
+ /* Timer 0 */
+ do_IRQ(TC0_IRQ);
+ }
+ if (cpuint_ip & CAUSEF_IP6)
+ {
+ /* switch core*/
+ do_IRQ(SWCORE_IRQ);
+ }
+ if (cpuint_ip & CAUSEF_IP5)
+ {
+ /* PCIE */
+ do_IRQ(PCIE_IRQ);
+ }
+ cpuint_ip = read_c0_cause() & ST0_REENTRY_IM;
+ } while(cpuint_ip);
+ }
+#else
+ if (cpuint_ip & CAUSEF_IP6)
+ {
+ /* switch core*/
+ do_IRQ(SWCORE_IRQ);
+ }
+ else if (cpuint_ip & CAUSEF_IP5)
+ {
+ /* PCIE */
+ do_IRQ(PCIE_IRQ);
+ }
+ else if (cpuint_ip & CAUSEF_IP7)
+ {
+ /* Timer 0 */
+ do_IRQ(TC0_IRQ);
+ }
+#endif
+ else if(cpuint_ip & CAUSEF_IP3)
+ {
+ /* pci */
+ do_IRQ(PCI_IRQ);
+ }
+ else if (cpuint_ip & CAUSEF_IP4)
+ {
+ /*USB*/
+ do_IRQ(USB_IRQ);
+ }
+ else if (cpuint_ip & CAUSEF_IP2)
+ {
+ /* For shared interrupts */
+ extint_ip = REG32(GIMR) & REG32(GISR);
+
+ if (extint_ip & UART0_IP)
+ {
+ /* UART 0 */
+ do_IRQ(UART0_IRQ);
+ }
+#if 0
+ else if (extint_ip & TC1_IP)
+ {
+ do_IRQ(TC1_IRQ);
+ }
+ /* currently we do not use uart1 */
+ else if (extint_ip & UART1_IP)
+ {
+ do_IRQ(UART1_IRQ);
+ }
+ else
+ {
+ prom_printf("Unknown Interrupt2:%x\n",extint_ip);
+ REG32(GISR) = extint_ip;
+ }
+#endif
+ }
+ write_c0_status((read_c0_status()|(ST0_USED_IM)));
+#endif
+}
diff --git a/target/linux/realtek/files/arch/mips/rtl8196b/mem.c b/target/linux/realtek/files/arch/mips/rtl8196b/mem.c
new file mode 100644
index 000000000..98644d98b
--- /dev/null
+++ b/target/linux/realtek/files/arch/mips/rtl8196b/mem.c
@@ -0,0 +1,133 @@
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+
+#include <prom.h>
+#include <platform.h>
+
+#define DCR 0xb8001004
+
+void __init prom_meminit(void)
+{
+ //char *ptr;
+ unsigned int memsize;
+
+ memsize = 0x02000000; /* Default to 32MB */
+ /* Check the command line first for a memsize directive */
+ //ptr = strstr(arcs_cmdline, "mem=");
+#if 1
+ /*now: alway believe DRAM configuration register*/
+ {
+ unsigned int DCRvalue = 0;
+ unsigned int bus_width = 0, chip_sel = 0, row_cnt = 0, col_cnt = 0,bank_cnt = 0;
+
+ DCRvalue = ( (*(volatile unsigned int *)DCR));
+
+ /*bit 19,0:2 bank; 1: 4 bank*/
+ switch(DCRvalue & 0x080000)
+ {
+ case 0x0:
+ bank_cnt = 2;
+ break;
+ case 0x080000:
+ bank_cnt = 4;
+ break;
+ default:
+ bank_cnt = 0;
+ break;
+ }
+
+ /*bit 22~24: colomn count*/
+ switch(DCRvalue & 0x01C00000)
+ {
+ case 0x00000000:
+ col_cnt = 256;
+ break;
+ case 0x00400000:
+ col_cnt = 512;
+ break;
+ case 0x00800000:
+ col_cnt = 1024;
+ break;
+ case 0x00C00000:
+ col_cnt = 2048;
+ break;
+ case 0x01000000:
+ col_cnt = 4096;
+ break;
+ default:
+ printk("unknow colomn count(0x%x)\n",DCRvalue & 0x01C00000);
+ break;
+ }
+
+ /*bit 25~26: row count*/
+ switch(DCRvalue & 0x06000000)
+ {
+ case 0x00000000:
+ row_cnt = 2048;
+ break;
+ case 0x02000000:
+ row_cnt = 4096;
+ break;
+ case 0x04000000:
+ row_cnt = 8192;
+ break;
+ case 0x06000000:
+ row_cnt = 16384;
+ break;
+ }
+
+ /*bit 27: chip select*/
+ switch(DCRvalue & 0x08000000)
+ {
+ case 0x0:
+ chip_sel = 1;
+ break;
+ case 0x08000000:
+ chip_sel = 2;
+ break;
+ }
+
+ /*bit 28~29: bus width*/
+ switch(DCRvalue & 0x30000000)
+ {
+ case 0x0:
+ bus_width = 8;
+ break;
+ case 0x10000000:
+ bus_width = 16;
+ break;
+ case 0x20000000:
+ bus_width = 32;
+ break;
+ default:
+ printk("bus width is reseved!\n");
+ break;
+ }
+
+ /*total size(Byte)*/
+ memsize = (row_cnt * col_cnt *bank_cnt) * (bus_width >> 3) * chip_sel;
+
+ }
+#endif
+
+ /*
+ * call <add_memory_region> to register boot_mem_map
+ * add_memory_region(base, size, type);
+ * type: BOOT_MEM_RAM, BOOT_MEM_ROM_DATA or BOOT_MEM_RESERVED
+ */
+ add_memory_region(0, memsize, BOOT_MEM_RAM);
+}
+
+//unsigned long __init prom_free_prom_memory(void)
+void prom_free_prom_memory(void)
+{
+ //unsigned long freed = 0;
+
+ return;// freed;
+}
diff --git a/target/linux/realtek/files/arch/mips/rtl8196b/pci-rtl8196.c b/target/linux/realtek/files/arch/mips/rtl8196b/pci-rtl8196.c
new file mode 100644
index 000000000..fffd6d58f
--- /dev/null
+++ b/target/linux/realtek/files/arch/mips/rtl8196b/pci-rtl8196.c
@@ -0,0 +1,526 @@
+/*
+ * RTL8196B PCIE Host Controller Glue Driver
+ * Author: ghhuang@realtek.com.tw
+ *
+ * Notes:
+ * - Two host controllers available.
+ * - Each host direcly connects to one device
+ * - Supports PCI devices through PCIE-to-PCI bridges
+ * - If no PCI devices are connected to RC. Timeout monitor shall be
+ * enabled to prevent bus hanging.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <asm/mipsregs.h>
+
+#include <platform.h>
+
+
+#define PCI_8BIT_ACCESS 1
+#define PCI_16BIT_ACCESS 2
+#define PCI_32BIT_ACCESS 4
+#define PCI_ACCESS_READ 8
+#define PCI_ACCESS_WRITE 16
+
+#define MAX_NUM_DEV 4
+
+#define DEBUG_PRINTK 0
+
+
+static int pci0_bus_number = 0xff;
+static int pci1_bus_number = 0xff;
+
+
+static struct resource rtl8196b_pci0_io_resource = {
+ .name = "RTL8196B PCI0 IO",
+ .flags = IORESOURCE_IO,
+ .start = PADDR(PCIE0_D_IO),
+ .end = PADDR(PCIE0_D_IO + 0x1FFFFF)
+};
+
+static struct resource rtl8196b_pci0_mem_resource = {
+ .name = "RTL8196B PCI0 MEM",
+ .flags = IORESOURCE_MEM,
+ .start = PADDR(PCIE0_D_MEM),
+ .end = PADDR(PCIE0_D_MEM + 0xFFFFFF)
+};
+
+static struct resource rtl8196b_pci1_io_resource = {
+ .name = "RTL8196B PCI1 IO",
+ .flags = IORESOURCE_IO,
+ .start = PADDR(PCIE1_D_IO),
+ .end = PADDR(PCIE1_D_IO + 0x1FFFFFF)
+};
+
+static struct resource rtl8196b_pci1_mem_resource = {
+ .name = "RTL8196B PCI1 MEM",
+ .flags = IORESOURCE_MEM,
+ .start = PADDR(PCIE1_D_MEM),
+ .end = PADDR(PCIE1_D_MEM + 0xFFFFFF)
+};
+//#define PIN_208
+#define DEMO_8196
+static int rtl8196b_pci_reset(void)
+{
+ cli();
+ /* If PCI needs to be reset, put code here.
+ * Note:
+ * Software may need to do hot reset for a period of time, say ~100us.
+ * Here we put 2ms.
+ */
+#if 1
+#ifdef PIN_208
+WRITE_MEM32(0xb8000044, 0x358);//Disable PCIE EX-PLL
+#else
+//#ifdef DEMO_8196
+//WRITE_MEM32(0xb8000044, 0x358);//Disable PCIE EX-PLL
+//#else
+//Modified for PHY parameter for RD center 12292008
+WRITE_MEM32(0xb8000044, 0x9);//Enable PCIE IN-PLL
+//#endif
+#endif
+mdelay(100);
+WRITE_MEM32(0xb8000010, 0x00FFFFD6);//Active LX & PCIE Clock in 8196B system register
+mdelay(100);
+WRITE_MEM32(0xb800003C, 0x1);//PORT0 PCIE PHY MDIO Reset
+mdelay(100);
+WRITE_MEM32(0xb800003C, 0x3);//PORT0 PCIE PHY MDIO Reset
+mdelay(100);
+WRITE_MEM32(0xb8000040, 0x1);//PORT1 PCIE PHY MDIO Reset
+mdelay(100);
+WRITE_MEM32(0xb8000040, 0x3);//PORT1 PCIE PHY MDIO Reset
+mdelay(100);
+WRITE_MEM32(0xb8b01008, 0x1);// PCIE PHY Reset Close:Port 0
+mdelay(100);
+WRITE_MEM32(0xb8b01008, 0x81);// PCIE PHY Reset On:Port 0
+mdelay(100);
+#ifdef PIN_208
+WRITE_MEM32(0xb8b21008, 0x1);// PCIE PHY Reset Close:Port 1
+mdelay(100);
+WRITE_MEM32(0xb8b21008, 0x81);// PCIE PHY Reset On:Port 1
+mdelay(100);
+#endif
+#if 0//1//1// 1//def OUT_CYSTALL
+WRITE_MEM32(0xb8b01000, 0xcc011901);// PCIE Close Port 0
+mdelay(10);
+#ifdef PIN_208
+WRITE_MEM32(0xb8b21000, 0xcc011901);// PCIE Close Port 1
+mdelay(10);
+#endif
+#endif
+WRITE_MEM32(0xb8000010, 0x01FFFFD6);// PCIE PHY Reset On:Port 1
+mdelay(100);
+#endif
+ WRITE_MEM32(PCIE0_H_PWRCR, READ_MEM32(PCIE0_H_PWRCR) & 0xFFFFFF7F);
+#ifdef PIN_208
+ WRITE_MEM32(PCIE1_H_PWRCR, READ_MEM32(PCIE1_H_PWRCR) & 0xFFFFFF7F);
+#endif
+ mdelay(100);
+ WRITE_MEM32(PCIE0_H_PWRCR, READ_MEM32(PCIE0_H_PWRCR) | 0x00000080);
+#ifdef PIN_208
+ WRITE_MEM32(PCIE1_H_PWRCR, READ_MEM32(PCIE1_H_PWRCR) | 0x00000080);
+#endif
+ sti();
+ return 0;
+}
+
+
+static int rtl8196b_pcibios_config_access(unsigned char access_type,
+ unsigned int addr, unsigned int *data)
+{
+ /* Do 8bit/16bit/32bit access */
+ if (access_type & PCI_ACCESS_WRITE)
+ {
+ if (access_type & PCI_8BIT_ACCESS)
+ WRITE_MEM8(addr, *data);
+ else if (access_type & PCI_16BIT_ACCESS)
+ WRITE_MEM16(addr, *data);
+ else
+ WRITE_MEM32(addr, *data);
+ }
+ else if (access_type & PCI_ACCESS_READ)
+ {
+ if (access_type & PCI_8BIT_ACCESS)
+ *data = READ_MEM8(addr);
+ else if (access_type & PCI_16BIT_ACCESS)
+ *data = READ_MEM16(addr);
+ else
+ *data = READ_MEM32(addr);
+ }
+
+ /* If need to check for PCIE access timeout, put code here */
+ /* ... */
+
+ return 0;
+}
+
+
+
+/*
+ * RTL8196b supports config word read access for 8/16/32 bit
+ *
+ * FIXME: currently only utilize 32bit access
+ */
+static int rtl8196b_pcibios0_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, unsigned int *val)
+{
+ unsigned int data = 0;
+ unsigned int addr = 0;
+
+ if (pci0_bus_number == 0xff)
+ pci0_bus_number = bus->number;
+
+ #if DEBUG_PRINTK
+ printk("File: %s, Function: %s, Line: %d\n", __FILE__, __FUNCTION__, __LINE__);
+ printk("Bus: %d, Slot: %d, Func: %d, Where: %d, Size: %d\n", bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, size);
+ #endif
+
+ if (bus->number == pci0_bus_number)
+ {
+ /* PCIE host controller */
+ if (PCI_SLOT(devfn) == 0)
+ {
+ addr = PCIE0_H_CFG + where;
+
+ if (rtl8196b_pcibios_config_access(PCI_ACCESS_READ | PCI_32BIT_ACCESS, addr & ~(0x3), &data))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (size == 1)
+ *val = (data >> ((where & 3) << 3)) & 0xff;
+ else if (size == 2)
+ *val = (data >> ((where & 3) << 3)) & 0xffff;
+ else
+ *val = data;
+ }
+ else
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ else if (bus->number == (pci0_bus_number + 1))
+ {
+ /* PCIE devices directly connected */
+ if (PCI_SLOT(devfn) == 0)
+ {
+ addr = PCIE0_D_CFG0 + (PCI_FUNC(devfn) << 12) + where;
+
+ if (rtl8196b_pcibios_config_access(PCI_ACCESS_READ | size, addr, val))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ else
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ else
+ {
+ /* Devices connected through bridge */
+ if (PCI_SLOT(devfn) < MAX_NUM_DEV)
+ {
+ WRITE_MEM32(PCIE0_H_IPCFG, ((bus->number) << 8) | (PCI_SLOT(devfn) << 3) | PCI_FUNC(devfn));
+ addr = PCIE0_D_CFG1 + where;
+
+ if (rtl8196b_pcibios_config_access(PCI_ACCESS_READ | size, addr, val))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ else
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+ #if DEBUG_PRINTK
+ printk("File: %s, Function: %s, Line: %d\n", __FILE__, __FUNCTION__, __LINE__);
+ printk("Read Value: 0x%08X\n", *val);
+ #endif
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int rtl8196b_pcibios0_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, unsigned int val)
+{
+ unsigned int data = 0;
+ unsigned int addr = 0;
+
+ static int pci0_bus_number = 0xff;
+
+ if (pci0_bus_number == 0xff)
+ pci0_bus_number = bus->number;
+
+ #if DEBUG_PRINTK
+ printk("File: %s, Function: %s, Line: %d\n", __FILE__, __FUNCTION__, __LINE__);
+ printk("Bus: %d, Slot: %d, Func: %d, Where: %d, Size: %d\n", bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, size);
+ #endif
+
+ if (bus->number == pci0_bus_number)
+ {
+ /* PCIE host controller */
+ if (PCI_SLOT(devfn) == 0)
+ {
+ addr = PCIE0_H_CFG + where;
+
+ if (rtl8196b_pcibios_config_access(PCI_ACCESS_READ | PCI_32BIT_ACCESS, addr & ~(0x3), &data))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ 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));
+ else
+ data = val;
+
+ if (rtl8196b_pcibios_config_access(PCI_ACCESS_WRITE, addr, &data))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ else
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ else if (bus->number == (pci0_bus_number + 1))
+ {
+ /* PCIE devices directly connected */
+ if (PCI_SLOT(devfn) == 0)
+ {
+ addr = PCIE0_D_CFG0 + (PCI_FUNC(devfn) << 12) + where;
+
+ if (rtl8196b_pcibios_config_access(PCI_ACCESS_WRITE | size, addr, &val))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ else
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ else
+ {
+ /* Devices connected through bridge */
+ if (PCI_SLOT(devfn) < MAX_NUM_DEV)
+ {
+ WRITE_MEM32(PCIE0_H_IPCFG, ((bus->number) << 8) | (PCI_SLOT(devfn) << 3) | PCI_FUNC(devfn));
+ addr = PCIE0_D_CFG1 + where;
+
+ if (rtl8196b_pcibios_config_access(PCI_ACCESS_WRITE | size, addr, &val))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ else
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+/*
+ * RTL8196b supports config word read access for 8/16/32 bit
+ *
+ * FIXME: currently only utilize 32bit access
+ */
+static int rtl8196b_pcibios1_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, unsigned int *val)
+{
+ unsigned int data = 0;
+ unsigned int addr = 0;
+
+ if (pci1_bus_number == 0xff)
+ pci1_bus_number = bus->number;
+
+ #if DEBUG_PRINTK
+ printk("File: %s, Function: %s, Line: %d\n", __FILE__, __FUNCTION__, __LINE__);
+ printk("Bus: %d, Slot: %d, Func: %d, Where: %d, Size: %d\n", bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, size);
+ #endif
+
+ if (bus->number == pci1_bus_number)
+ {
+ /* PCIE host controller */
+ if (PCI_SLOT(devfn) == 0)
+ {
+ addr = PCIE1_H_CFG + where;
+
+ if (rtl8196b_pcibios_config_access(PCI_ACCESS_READ | PCI_32BIT_ACCESS, addr & ~(0x3), &data))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (size == 1)
+ *val = (data >> ((where & 3) << 3)) & 0xff;
+ else if (size == 2)
+ *val = (data >> ((where & 3) << 3)) & 0xffff;
+ else
+ *val = data;
+ }
+ else
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ else if (bus->number == (pci1_bus_number + 1))
+ {
+ /* PCIE devices directly connected */
+ if (PCI_SLOT(devfn) == 0)
+ {
+ addr = PCIE1_D_CFG0 + (PCI_FUNC(devfn) << 12) + where;
+
+ if (rtl8196b_pcibios_config_access(PCI_ACCESS_READ | size, addr, val))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ else
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ else
+ {
+ /* Devices connected through bridge */
+ if (PCI_SLOT(devfn) < MAX_NUM_DEV)
+ {
+ WRITE_MEM32(PCIE1_H_IPCFG, ((bus->number) << 8) | (PCI_SLOT(devfn) << 3) | PCI_FUNC(devfn));
+ addr = PCIE1_D_CFG1 + where;
+
+ if (rtl8196b_pcibios_config_access(PCI_ACCESS_READ | size, addr, val))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ else
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+ #if DEBUG_PRINTK
+ printk("File: %s, Function: %s, Line: %d\n", __FILE__, __FUNCTION__, __LINE__);
+ printk("Read Value: 0x%08X\n", *val);
+ #endif
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int rtl8196b_pcibios1_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, unsigned int val)
+{
+ unsigned int data = 0;
+ unsigned int addr = 0;
+
+ static int pci1_bus_number = 0xff;
+
+ if (pci1_bus_number == 0xff)
+ pci1_bus_number = bus->number;
+
+ #if DEBUG_PRINTK
+ printk("File: %s, Function: %s, Line: %d\n", __FILE__, __FUNCTION__, __LINE__);
+ printk("Bus: %d, Slot: %d, Func: %d, Where: %d, Size: %d\n", bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, size);
+ #endif
+
+
+ if (bus->number == pci1_bus_number)
+ {
+ /* PCIE host controller */
+ if (PCI_SLOT(devfn) == 0)
+ {
+ addr = PCIE1_H_CFG + where;
+
+ if (rtl8196b_pcibios_config_access(PCI_ACCESS_READ | PCI_32BIT_ACCESS, addr & ~(0x3), &data))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ 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));
+ else
+ data = val;
+
+ if (rtl8196b_pcibios_config_access(PCI_ACCESS_WRITE, addr, &data))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ else
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ else if (bus->number == (pci1_bus_number + 1))
+ {
+ /* PCIE devices directly connected */
+ if (PCI_SLOT(devfn) == 0)
+ {
+ addr = PCIE1_D_CFG0 + (PCI_FUNC(devfn) << 12) + where;
+
+ if (rtl8196b_pcibios_config_access(PCI_ACCESS_WRITE | size, addr, &val))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ else
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ else
+ {
+ /* Devices connected through bridge */
+ if (PCI_SLOT(devfn) < MAX_NUM_DEV)
+ {
+ WRITE_MEM32(PCIE1_H_IPCFG, ((bus->number) << 8) | (PCI_SLOT(devfn) << 3) | PCI_FUNC(devfn));
+ addr = PCIE1_D_CFG1 + where;
+
+ if (rtl8196b_pcibios_config_access(PCI_ACCESS_WRITE | size, addr, &val))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ else
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops rtl8196b_pci0_ops = {
+ .read = rtl8196b_pcibios0_read,
+ .write = rtl8196b_pcibios0_write
+};
+
+struct pci_ops rtl8196b_pci1_ops = {
+ .read = rtl8196b_pcibios1_read,
+ .write = rtl8196b_pcibios1_write
+};
+
+
+static struct pci_controller rtl8196b_pci0_controller = {
+ .pci_ops = &rtl8196b_pci0_ops,
+ .mem_resource = &rtl8196b_pci0_mem_resource,
+ .io_resource = &rtl8196b_pci0_io_resource,
+};
+
+static struct pci_controller rtl8196b_pci1_controller = {
+ .pci_ops = &rtl8196b_pci1_ops,
+ .mem_resource = &rtl8196b_pci1_mem_resource,
+ .io_resource = &rtl8196b_pci1_io_resource,
+};
+
+
+int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ #if DEBUG_PRINTK
+ printk("File: %s, Function: %s, Line: %d\n", __FILE__, __FUNCTION__, __LINE__);
+ printk("**Slot: %d\n", slot);
+ printk("**Pin: %d\n", pin);
+ printk("**Dev->BUS->Number: %d\n", dev->bus->number);
+ #endif
+
+ if (dev->bus->number < pci1_bus_number)
+ return PCIE_IRQ;
+ else
+ return PCIE2_IRQ;
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ #if DEBUG_PRINTK
+ printk("File: %s, Function: %s, Line: %d\n", __FILE__, __FUNCTION__, __LINE__);
+ #endif
+
+ return 0;
+}
+
+
+static __init int rtl8196b_pci_init(void)
+{
+ rtl8196b_pci_reset();
+
+ set_io_port_base(KSEG1);
+ ioport_resource.end = 0xFFFFFFFF;
+
+ #if DEBUG_PRINTK
+ printk("<<<<<Register 1st PCI Controller>>>>>\n");
+ printk("<<<<<Register 2nd PCI Controller>>>>>\n");
+ #endif
+
+ register_pci_controller(&rtl8196b_pci0_controller);
+#ifdef PIN_208
+ register_pci_controller(&rtl8196b_pci1_controller);
+#endif
+ return 0;
+}
+
+arch_initcall(rtl8196b_pci_init);
diff --git a/target/linux/realtek/files/arch/mips/rtl8196b/pci.h b/target/linux/realtek/files/arch/mips/rtl8196b/pci.h
new file mode 100644
index 000000000..1c8dca8b9
--- /dev/null
+++ b/target/linux/realtek/files/arch/mips/rtl8196b/pci.h
@@ -0,0 +1,75 @@
+#ifndef PCI_H
+#define PCI_H
+
+
+
+struct pci_slot_baseaddr_s {
+ u32 slotNum;
+ u32 addr;
+};
+
+#ifdef CONFIG_RTL865XC
+
+#define PCI_SLOT0_CONFIG_BASE 0xB8B40000
+#define PCI_SLOT1_CONFIG_BASE 0xB8B80000
+#define PCI_SLOT2_CONFIG_BASE 0xB8B10000
+#define PCI_SLOT3_CONFIG_BASE 0xB8B20000
+
+#define PCI_SLOT_MEM_BASE0 0xB9000000
+#define PCI_SLOT_IO_BASE0 0xB8C00000
+#define PCI_MEM_SPACE_SIZE0 0x01000000
+#define PCI_IO_SPACE_SIZE0 0x00200000
+
+#define PCI_SLOT_MEM_BASE1 0xBA000000
+#define PCI_SLOT_IO_BASE1 0xB8E00000
+#define PCI_MEM_SPACE_SIZE1 0x01000000
+#define PCI_IO_SPACE_SIZE1 0x00200000
+
+
+#else
+
+#define PCI_SLOT0_CONFIG_BASE 0xBBD40000
+#define PCI_SLOT1_CONFIG_BASE 0xBBD80000
+#define PCI_SLOT2_CONFIG_BASE 0xBBD10000
+#define PCI_SLOT3_CONFIG_BASE 0xBBD20000
+
+#define PCI_SLOT_MEM_BASE 0xBBF00000
+#define PCI_SLOT_IO_BASE 0xBBE00000
+#define PCI_MEM_SPACE_SIZE 0x00100000
+#define PCI_IO_SPACE_SIZE 0x00100000
+#endif
+
+
+//PCI configuration space
+#define PCI_CONFIG_VENDER_DEV 0x0000
+#define PCI_CONFIG_COMMAND 0x0004
+#define PCI_CONFIG_STATUS 0x0006
+#define PCI_CONFIG_CLASS_REVISION 0x0008
+#define PCI_CONFIG_CACHE 0x000c
+#define PCI_CONFIG_LATENCY 0x000d
+#define PCI_CONFIG_HEADER_TYPE 0x000e
+#define PCI_CONFIG_BASE0 0x0010
+#define PCI_CONFIG_BASE1 0x0014
+#define PCI_CONFIG_BASE2 0x0018
+#define PCI_CONFIG_BASE3 0x001c
+#define PCI_CONFIG_BASE4 0x0020
+#define PCI_CONFIG_BASE5 0x0024
+#define PCI_CONFIG_SUBSYSTEMVENDOR 0x002c
+#define PCI_CONFIG_INT_LINE 0x003c
+#define PCI_CONFIG_INT_PIN 0x003d
+#define PCI_CONFIG_MAXLAN 0x003f
+#define PCI_CONFIG_MINGNT 0x003e
+
+//PCI command register flag
+#define CMD_FAST_BACK_TO_BACK (1<<9)
+#define CMD_SERR (1<<8)
+#define CMD_STEP_CONTROL (1<<7)
+#define CMD_PARITY_ERROR_RESPONSE (1<<6)
+#define CMD_VGA_PALLETE_SNOOP (1<<5)
+#define CMD_WRITE_AND_INVALIDATE (1<<4)
+#define CMD_SPECIAL_CYCLE (1<<3)
+#define CMD_BUS_MASTER (1<<2)
+#define CMD_MEM_SPACE (1<<1)
+#define CMD_IO_SPACE (1<<0)
+
+#endif
diff --git a/target/linux/realtek/files/arch/mips/rtl8196b/printf.c b/target/linux/realtek/files/arch/mips/rtl8196b/printf.c
new file mode 100644
index 000000000..650f46d27
--- /dev/null
+++ b/target/linux/realtek/files/arch/mips/rtl8196b/printf.c
@@ -0,0 +1,51 @@
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include <prom.h>
+#include <platform.h>
+
+void __init prom_console_init(void)
+{
+ /* 8 bits, 1 stop bit, no parity. */
+ REG8(UART0_LCR) = CHAR_LEN_8 | ONE_STOP | PARITY_DISABLE;
+
+ /* Reset/Enable the FIFO */
+ REG8(UART0_FCR) = FCR_EN | RXRST | TXRST | CHAR_TRIGGER_14;
+
+ /* Disable All Interrupts */
+ REG8(UART0_IER) = 0x00000000;
+
+ /* Enable Divisor Latch */
+ REG8(UART0_LCR) |= DLAB;
+
+ /* Set Divisor */
+ REG8(UART0_DLL) = (SYSCLK / (BAUDRATE * 16) - 1) & 0x00FF;
+ REG8(UART0_DLM) = ((SYSCLK / (BAUDRATE * 16) - 1) & 0xFF00) >> 8;
+
+ /* Disable Divisor Latch */
+ REG8(UART0_LCR) &= (~DLAB);
+}
+
+int prom_putchar(char c)
+{
+ unsigned int busy_cnt = 0;
+
+ do
+ {
+ /* Prevent Hanging */
+ if (busy_cnt++ >= 30000)
+ {
+ /* Reset Tx FIFO */
+ REG8(UART0_FCR) = TXRST | CHAR_TRIGGER_14;
+ return 0;
+ }
+ } while ((REG8(UART0_LSR) & LSR_THRE) == TxCHAR_AVAIL);
+
+ /* Send Character */
+ REG8(UART0_THR) = c;
+
+ return 1;
+}
diff --git a/target/linux/realtek/files/arch/mips/rtl8196b/setup.c b/target/linux/realtek/files/arch/mips/rtl8196b/setup.c
new file mode 100644
index 000000000..7a2598495
--- /dev/null
+++ b/target/linux/realtek/files/arch/mips/rtl8196b/setup.c
@@ -0,0 +1,191 @@
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/serial.h>
+#include <asm/io.h>
+#include <asm/time.h>
+
+#include <prom.h>
+#include <platform.h>
+
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/percpu.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/notifier.h>
+#include <linux/thread_info.h>
+#include <linux/time.h>
+#include <linux/jiffies.h>
+#include <linux/posix-timers.h>
+#include <linux/cpu.h>
+#include <linux/syscalls.h>
+#include <linux/delay.h>
+
+#include <asm/uaccess.h>
+#include <asm/unistd.h>
+#include <asm/div64.h>
+#include <asm/timex.h>
+#include <asm/io.h>
+
+static void __init serial_init(void);
+#if 0
+static void __init rtl8652_time_init(void);
+static void rtl8652_timer_ack(void);
+
+/*
+ * Called from the timer interrupt handler to charge one tick to the current
+ * process. user_tick is 1 if the tick is user time, 0 for system.
+ */
+
+void local_timer_interrupt(int irq, void *dev_id)
+{
+// profile_tick(CPU_PROFILING);
+ account_process_tick(current, user_mode(get_irq_regs()));
+}
+/*
+ * High-level timer interrupt service routines. This function
+ * is set as irqaction->handler and is invoked through do_IRQ.
+ */
+
+irqreturn_t timer_interrupt(int irq, void *dev_id)
+{
+ write_seqlock(&xtime_lock);
+
+//Add for update flash check
+
+ rtl8652_timer_ack();
+
+ /*
+ * call the generic timer interrupt handling
+ */
+ do_timer(1);
+
+
+ write_sequnlock(&xtime_lock);
+
+ /*
+ * In UP mode, we call local_timer_interrupt() to do profiling
+ * and process accouting.
+ *
+ * In SMP mode, local_timer_interrupt() is invoked by appropriate
+ * low-level local timer interrupt handler.
+ */
+ local_timer_interrupt(irq, dev_id);
+
+ return IRQ_HANDLED;
+}
+#endif
+const char *get_system_type(void)
+{
+ return "RTL8652";
+}
+
+void __init prom_init(void)
+{
+ prom_console_init();
+ prom_meminit();
+}
+
+void __init plat_mem_setup(void)
+{
+ /* Platform Specific Setup */
+ /* define io/mem region */
+ ioport_resource.start = 0x18000000;
+ ioport_resource.end = 0x1fffffff;
+
+ iomem_resource.start = 0x18000000;
+ iomem_resource.end = 0x1fffffff;
+
+ serial_init();
+
+// board_time_init = rtl8652_time_init;
+// mips_timer_ack = rtl8652_timer_ack;
+}
+
+#if 0
+static void rtl8652_timer_ack(void)
+{
+ REG32(TCIR) |= TC0IP;
+}
+
+static void __init rtl8652_time_init(void)
+{
+
+}
+#endif
+
+extern int rtl_clockevent_init(int irq);
+//void __init plat_time_init(struct irqaction *irq)
+void __init plat_time_init(void)
+{
+ /* Setup Timer0 */
+
+ /* Clear Timer IP status */
+ if (REG32(TCIR) & TC0IP)
+ REG32(TCIR) |= TC0IP;
+
+ /* Here irq->handler is passed from outside */
+ // irq->handler = timer_interrupt;
+ //setup_irq(TC0_IRQ, irq);
+
+ REG32(TCCNR) = 0; /* disable timer before setting CDBR */
+ /* extend timer base to 4 times for wireless init process */
+#if 0
+ REG32(CDBR) = (DIVISOR) << DIVF_OFFSET;
+ REG32(TC0DATA) = (MHZ * (1000 / HZ)) << TCD_OFFSET;
+#else
+ REG32(CDBR)=(DIVISOR*4) << DIVF_OFFSET;
+ REG32(TC0DATA) = ((MHZ * 250) / HZ) << TCD_OFFSET;
+#endif
+
+ rtl_clockevent_init(TC0_IRQ);
+ /* enable timer */
+ REG32(TCCNR) = TC0EN | TC0MODE_TIMER;
+ REG32(TCIR) = TC0IE;
+ #ifdef CONFIG_RTL865X_WTDOG
+ *(volatile unsigned long *)(0xb800311C)=0x00600000;
+ #endif
+}
+
+extern int __init early_serial_setup(struct uart_port *port);
+static void __init serial_init(void)
+{
+#ifdef CONFIG_SERIAL_8250
+ struct uart_port s;
+
+ memset(&s, 0, sizeof(s));
+
+ s.line = 0;
+ s.type = PORT_16550A;
+ //s.membase = (unsigned char *) UART0_BASE;
+ s.mapbase = UART0_MAP_BASE;
+ s.membase = ioremap_nocache(s.mapbase, 0x20);
+ s.irq = UART0_IRQ;
+ //s.uartclk = SYSCLK - BAUDRATE * 24;
+ s.uartclk = 200000000;
+ //s.flags = UPF_SKIP_TEST | UPF_LOW_LATENCY | UPF_SPD_CUST;
+ s.flags = UPF_SKIP_TEST | UPF_LOW_LATENCY;
+ s.iotype = UPIO_MEM;
+ s.regshift = 2;
+ //s.fifosize = 1;
+ s.fifosize = 16;
+ // s.custom_divisor = SYSCLK / (BAUDRATE * 16) - 1;
+
+ /* Call early_serial_setup() here, to set up 8250 console driver */
+ if (early_serial_setup(&s) != 0) {
+ panic("Serial setup failed!\n");
+ }
+#endif
+}
diff --git a/target/linux/realtek/files/arch/mips/rtl8196b/timer.c b/target/linux/realtek/files/arch/mips/rtl8196b/timer.c
new file mode 100644
index 000000000..e8d58ebf8
--- /dev/null
+++ b/target/linux/realtek/files/arch/mips/rtl8196b/timer.c
@@ -0,0 +1,80 @@
+/*
+ * linux/arch/rlx/rlxocp/time.c
+ *
+ * Copyright (C) 1999 Harald Koerfgen
+ * Copyright (C) 2000 Pavel Machek (pavel@suse.cz)
+ * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Time handling functinos for Philips Nino.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/delay.h>
+
+#include <asm/time.h>
+#include <asm/rlxbsp.h>
+
+#include "bspchip.h"
+
+#ifdef CONFIG_RTL_TIMER_ADJUSTMENT
+#include <rtl_types.h>
+#include <rtl865xc_asicregs.h>
+
+void rtl865x_setupTimer1(void)
+{
+ WRITE_MEM32( TCCNR, READ_MEM32(TCCNR) & ~TC1EN );/* Disable timer1 */
+ WRITE_MEM32( TC1DATA, 0xffffff00);
+ WRITE_MEM32( TCCNR, ( READ_MEM32(TCCNR) | TC1EN ) | TC1MODE_TIMER );/* Enable timer1 - timer mode */
+ WRITE_MEM32( TCIR, READ_MEM32(TCIR) & ~TC1IE ); /* Disable timer1 interrupt */
+}
+#endif
+
+void inline bsp_timer_ack(void)
+{
+ REG32(BSP_TCIR) |= BSP_TC0IP;
+}
+
+void __init bsp_timer_init(void)
+{
+ unsigned int sys_clock_rate;
+
+ sys_clock_rate = BSP_SYS_CLK_RATE;
+
+ /* Clear Timer IP status */
+ if (REG32(BSP_TCIR) & BSP_TC0IP)
+ REG32(BSP_TCIR) |= BSP_TC0IP;
+
+ /* disable timer */
+ REG32(BSP_TCCNR) = 0; /* disable timer before setting CDBR */
+
+ /* initialize timer registers */
+ REG32(BSP_CDBR)=(BSP_DIVISOR) << BSP_DIVF_OFFSET;
+ REG32(BSP_TC0DATA) = (((sys_clock_rate/BSP_DIVISOR)/HZ)) << BSP_TCD_OFFSET;
+ // extend timer base to 4 times
+ //REG32(BSP_CDBR)=(BSP_DIVISOR*4) << BSP_DIVF_OFFSET;
+ //REG32(BSP_TC0DATA) = (((sys_clock_rate/(BSP_DIVISOR*4))/HZ)) << BSP_TCD_OFFSET;
+#ifdef CONFIG_RTL_TIMER_ADJUSTMENT
+ rtl865x_setupTimer1();
+#endif
+#if defined(CONFIG_RTK_WTDOG)
+ REG32(BSP_WDTCNR) = 0x00600000;
+#endif
+
+ /* hook up timer interrupt handler */
+ rlx_clockevent_init(BSP_TC0_IRQ);
+
+ /* enable timer */
+ REG32(BSP_TCCNR) = BSP_TC0EN | BSP_TC0MODE_TIMER;
+ REG32(BSP_TCIR) = BSP_TC0IE;
+}