From 5deb3317cb51ac52de922bb55f8492624018906d Mon Sep 17 00:00:00 2001 From: Roman Yeryomin Date: Thu, 13 Sep 2012 00:40:35 +0300 Subject: Add realtek target files Signed-off-by: Roman Yeryomin --- .../realtek/files/arch/mips/rtl8196c/Makefile | 9 + .../linux/realtek/files/arch/mips/rtl8196c/int.c | 262 ++++++++++ .../linux/realtek/files/arch/mips/rtl8196c/mem.c | 133 ++++++ .../realtek/files/arch/mips/rtl8196c/pci-rtl8196.c | 526 +++++++++++++++++++++ .../linux/realtek/files/arch/mips/rtl8196c/pci.h | 75 +++ .../realtek/files/arch/mips/rtl8196c/printf.c | 51 ++ .../linux/realtek/files/arch/mips/rtl8196c/setup.c | 191 ++++++++ .../linux/realtek/files/arch/mips/rtl8196c/timer.c | 80 ++++ 8 files changed, 1327 insertions(+) create mode 100644 target/linux/realtek/files/arch/mips/rtl8196c/Makefile create mode 100644 target/linux/realtek/files/arch/mips/rtl8196c/int.c create mode 100644 target/linux/realtek/files/arch/mips/rtl8196c/mem.c create mode 100644 target/linux/realtek/files/arch/mips/rtl8196c/pci-rtl8196.c create mode 100644 target/linux/realtek/files/arch/mips/rtl8196c/pci.h create mode 100644 target/linux/realtek/files/arch/mips/rtl8196c/printf.c create mode 100644 target/linux/realtek/files/arch/mips/rtl8196c/setup.c create mode 100644 target/linux/realtek/files/arch/mips/rtl8196c/timer.c (limited to 'target/linux/realtek/files/arch/mips/rtl8196c') diff --git a/target/linux/realtek/files/arch/mips/rtl8196c/Makefile b/target/linux/realtek/files/arch/mips/rtl8196c/Makefile new file mode 100644 index 000000000..f7e8766ca --- /dev/null +++ b/target/linux/realtek/files/arch/mips/rtl8196c/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/rtl8196c/int.c b/target/linux/realtek/files/arch/mips/rtl8196c/int.c new file mode 100644 index 000000000..4d00494dc --- /dev/null +++ b/target/linux/realtek/files/arch/mips/rtl8196c/int.c @@ -0,0 +1,262 @@ +#include +#include + +#include +#include +#include +#include + +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 ; + + 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 */ + +#define __IRAM_GEN __attribute__ ((section(".iram-gen"))) + +__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 ( 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_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/rtl8196c/mem.c b/target/linux/realtek/files/arch/mips/rtl8196c/mem.c new file mode 100644 index 000000000..98644d98b --- /dev/null +++ b/target/linux/realtek/files/arch/mips/rtl8196c/mem.c @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#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 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/rtl8196c/pci-rtl8196.c b/target/linux/realtek/files/arch/mips/rtl8196c/pci-rtl8196.c new file mode 100644 index 000000000..fffd6d58f --- /dev/null +++ b/target/linux/realtek/files/arch/mips/rtl8196c/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 +#include +#include +#include +#include + +#include + +#include + + +#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("<<<<>>>>\n"); + printk("<<<<>>>>\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/rtl8196c/pci.h b/target/linux/realtek/files/arch/mips/rtl8196c/pci.h new file mode 100644 index 000000000..1c8dca8b9 --- /dev/null +++ b/target/linux/realtek/files/arch/mips/rtl8196c/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/rtl8196c/printf.c b/target/linux/realtek/files/arch/mips/rtl8196c/printf.c new file mode 100644 index 000000000..650f46d27 --- /dev/null +++ b/target/linux/realtek/files/arch/mips/rtl8196c/printf.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include + +#include +#include + +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/rtl8196c/setup.c b/target/linux/realtek/files/arch/mips/rtl8196c/setup.c new file mode 100644 index 000000000..7a2598495 --- /dev/null +++ b/target/linux/realtek/files/arch/mips/rtl8196c/setup.c @@ -0,0 +1,191 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +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/rtl8196c/timer.c b/target/linux/realtek/files/arch/mips/rtl8196c/timer.c new file mode 100644 index 000000000..e8d58ebf8 --- /dev/null +++ b/target/linux/realtek/files/arch/mips/rtl8196c/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "bspchip.h" + +#ifdef CONFIG_RTL_TIMER_ADJUSTMENT +#include +#include + +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; +} -- cgit v1.2.3