diff options
author | juhosg <juhosg@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-02-13 15:17:59 +0000 |
---|---|---|
committer | juhosg <juhosg@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-02-13 15:17:59 +0000 |
commit | 07c8d27309c0b6a734a012f7b6913a8e815f49eb (patch) | |
tree | 8b0dcffac18eab34d3c77f4f4f388faf65fdb093 /target/linux/ramips/files/arch/mips/ralink | |
parent | 9aa91c2c63264cab39919b63efbd5072bbbb9a45 (diff) |
ramips: add preliminary support for the RT3662/RT3883 SoCs
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@30495 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/ramips/files/arch/mips/ralink')
12 files changed, 993 insertions, 0 deletions
diff --git a/target/linux/ramips/files/arch/mips/ralink/Kconfig b/target/linux/ramips/files/arch/mips/ralink/Kconfig index 1bb6bc3ba..a7e7f21f9 100644 --- a/target/linux/ramips/files/arch/mips/ralink/Kconfig +++ b/target/linux/ramips/files/arch/mips/ralink/Kconfig @@ -14,10 +14,15 @@ choice bool "RT305x" select SOC_RT305X + config RALINK_RT3883 + bool "RT3883" + select SOC_RT3883 + endchoice source "arch/mips/ralink/rt288x/Kconfig" source "arch/mips/ralink/rt305x/Kconfig" +source "arch/mips/ralink/rt3883/Kconfig" config SOC_RT288X bool @@ -49,6 +54,22 @@ config SOC_RT305X select MIPS_MACHINE select USB_ARCH_HAS_HCD +config SOC_RT3883 + bool + select CEVT_R4K + select CSRC_R4K + select DMA_NONCOHERENT + select IRQ_CPU + select ARCH_REQUIRE_GPIOLIB + select SYS_HAS_CPU_MIPS32_R1 + select SYS_HAS_CPU_MIPS32_R2 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_HAS_EARLY_PRINTK + select MIPS_MACHINE + select USB_ARCH_HAS_OHCI + select USB_ARCH_HAS_EHCI + config RALINK_DEV_GPIO_BUTTONS def_bool n diff --git a/target/linux/ramips/files/arch/mips/ralink/Platform b/target/linux/ramips/files/arch/mips/ralink/Platform index 86871bda3..1b540492c 100644 --- a/target/linux/ramips/files/arch/mips/ralink/Platform +++ b/target/linux/ramips/files/arch/mips/ralink/Platform @@ -17,3 +17,10 @@ load-$(CONFIG_RALINK_RT288X) += 0xffffffff88000000 core-$(CONFIG_RALINK_RT305X) += arch/mips/ralink/rt305x/ cflags-$(CONFIG_RALINK_RT305X) += -I$(srctree)/arch/mips/include/asm/mach-ralink/rt305x load-$(CONFIG_RALINK_RT305X) += 0xffffffff80000000 + +# +# Ralink RT3883 +# +core-$(CONFIG_RALINK_RT3883) += arch/mips/ralink/rt3883/ +cflags-$(CONFIG_RALINK_RT3883) += -I$(srctree)/arch/mips/include/asm/mach-ralink/rt3883 +load-$(CONFIG_RALINK_RT3883) += 0xffffffff80000000 diff --git a/target/linux/ramips/files/arch/mips/ralink/rt3883/Kconfig b/target/linux/ramips/files/arch/mips/ralink/rt3883/Kconfig new file mode 100644 index 000000000..7b4579adb --- /dev/null +++ b/target/linux/ramips/files/arch/mips/ralink/rt3883/Kconfig @@ -0,0 +1,7 @@ +if RALINK_RT3883 + +menu "Ralink RT3662/RT3883 machine selection" + +endmenu + +endif diff --git a/target/linux/ramips/files/arch/mips/ralink/rt3883/Makefile b/target/linux/ramips/files/arch/mips/ralink/rt3883/Makefile new file mode 100644 index 000000000..f8098592b --- /dev/null +++ b/target/linux/ramips/files/arch/mips/ralink/rt3883/Makefile @@ -0,0 +1,12 @@ +# +# Makefile for the Ralink RT3662/RT3883 SoC specific parts of the kernel +# +# Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> +# +# 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. + +obj-y := irq.o setup.o devices.o rt3883.o clock.o + +obj-$(CONFIG_EARLY_PRINTK) += early_printk.o diff --git a/target/linux/ramips/files/arch/mips/ralink/rt3883/clock.c b/target/linux/ramips/files/arch/mips/ralink/rt3883/clock.c new file mode 100644 index 000000000..bf70259ca --- /dev/null +++ b/target/linux/ramips/files/arch/mips/ralink/rt3883/clock.c @@ -0,0 +1,103 @@ +/* + * Ralink RT3662/RT3883 clock API + * + * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/clk.h> + +#include <asm/mach-ralink/common.h> +#include <asm/mach-ralink/rt3883.h> +#include <asm/mach-ralink/rt3883_regs.h> +#include "common.h" + +struct clk { + unsigned long rate; +}; + +static struct clk rt3883_cpu_clk; +static struct clk rt3883_sys_clk; +static struct clk rt3883_wdt_clk; +static struct clk rt3883_uart_clk; + +void __init rt3883_clocks_init(void) +{ + u32 syscfg0; + u32 clksel; + u32 ddr2; + + syscfg0 = rt3883_sysc_rr(RT3883_SYSC_REG_SYSCFG0); + clksel = ((syscfg0 >> RT3883_SYSCFG0_CPUCLK_SHIFT) & + RT3883_SYSCFG0_CPUCLK_MASK); + ddr2 = syscfg0 & RT3883_SYSCFG0_DRAM_TYPE_DDR2; + + switch (clksel) { + case RT3883_SYSCFG0_CPUCLK_250: + rt3883_cpu_clk.rate = 250000000; + rt3883_sys_clk.rate = (ddr2) ? 125000000 : 83000000; + break; + case RT3883_SYSCFG0_CPUCLK_384: + rt3883_cpu_clk.rate = 384000000; + rt3883_sys_clk.rate = (ddr2) ? 128000000 : 96000000; + break; + case RT3883_SYSCFG0_CPUCLK_480: + rt3883_cpu_clk.rate = 480000000; + rt3883_sys_clk.rate = (ddr2) ? 160000000 : 120000000; + break; + case RT3883_SYSCFG0_CPUCLK_500: + rt3883_cpu_clk.rate = 500000000; + rt3883_sys_clk.rate = (ddr2) ? 166000000 : 125000000; + break; + } + + rt3883_wdt_clk.rate = rt3883_sys_clk.rate; + rt3883_uart_clk.rate = 40000000; +} + +struct clk *clk_get(struct device *dev, const char *id) +{ + if (!strcmp(id, "sys")) + return &rt3883_sys_clk; + + if (!strcmp(id, "cpu")) + return &rt3883_cpu_clk; + + if (!strcmp(id, "wdt")) + return &rt3883_wdt_clk; + + if (!strcmp(id, "uart")) + return &rt3883_uart_clk; + + return ERR_PTR(-ENOENT); +} +EXPORT_SYMBOL(clk_get); + +int clk_enable(struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + return clk->rate; +} +EXPORT_SYMBOL(clk_get_rate); + +void clk_put(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_put); diff --git a/target/linux/ramips/files/arch/mips/ralink/rt3883/common.h b/target/linux/ramips/files/arch/mips/ralink/rt3883/common.h new file mode 100644 index 000000000..a389dccce --- /dev/null +++ b/target/linux/ramips/files/arch/mips/ralink/rt3883/common.h @@ -0,0 +1,16 @@ +/* + * Ralink RT3662/RT3883 SoC common defines + * + * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#ifndef _RT3883_COMMON_H +#define _RT3883_COMMON_H + +void rt3883_clocks_init(void); + +#endif /* _RT3883_COMMON_H */
\ No newline at end of file diff --git a/target/linux/ramips/files/arch/mips/ralink/rt3883/devices.c b/target/linux/ramips/files/arch/mips/ralink/rt3883/devices.c new file mode 100644 index 000000000..058402a5a --- /dev/null +++ b/target/linux/ramips/files/arch/mips/ralink/rt3883/devices.c @@ -0,0 +1,385 @@ +/* + * Ralink RT3662/RT3883 SoC platform device registration + * + * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/physmap.h> +#include <linux/mtd/partitions.h> +#include <linux/dma-mapping.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/rt2x00_platform.h> + +#include <asm/addrspace.h> + +#include <asm/mach-ralink/rt3883.h> +#include <asm/mach-ralink/rt3883_regs.h> +#include <asm/mach-ralink/rt3883_ehci_platform.h> +#include <asm/mach-ralink/rt3883_ohci_platform.h> +#include <asm/mach-ralink/ramips_nand_platform.h> +#include "devices.h" + +#include <ramips_eth_platform.h> + +static struct resource rt3883_flash0_resources[] = { + { + .flags = IORESOURCE_MEM, + .start = RT3883_BOOT_BASE, + .end = RT3883_BOOT_BASE + RT3883_BOOT_SIZE - 1, + }, +}; + +struct physmap_flash_data rt3883_flash0_data; +static struct platform_device rt3883_flash0_device = { + .name = "physmap-flash", + .resource = rt3883_flash0_resources, + .num_resources = ARRAY_SIZE(rt3883_flash0_resources), + .dev = { + .platform_data = &rt3883_flash0_data, + }, +}; + +static struct resource rt3883_flash1_resources[] = { + { + .flags = IORESOURCE_MEM, + .start = RT3883_SRAM_BASE, + .end = RT3883_SRAM_BASE + RT3883_SRAM_SIZE - 1, + }, +}; + +struct physmap_flash_data rt3883_flash1_data; +static struct platform_device rt3883_flash1_device = { + .name = "physmap-flash", + .resource = rt3883_flash1_resources, + .num_resources = ARRAY_SIZE(rt3883_flash1_resources), + .dev = { + .platform_data = &rt3883_flash1_data, + }, +}; + +static int rt3883_flash_instance __initdata; +void __init rt3883_register_pflash(unsigned int id) +{ + struct platform_device *pdev; + struct physmap_flash_data *pdata; + void __iomem *fscc_base; + u32 t; + int reg; + + switch (id) { + case 0: + pdev = &rt3883_flash0_device; + reg = RT3883_FSCC_REG_FLASH_CFG0; + break; + case 1: + pdev = &rt3883_flash1_device; + reg = RT3883_FSCC_REG_FLASH_CFG1; + break; + default: + return; + } + + pdata = pdev->dev.platform_data; + + fscc_base = ioremap(RT3883_FSCC_BASE, RT3883_FSCC_SIZE); + if (!fscc_base) + panic("RT3883: ioremap failed for FSCC"); + + t = __raw_readl(fscc_base + reg); + iounmap(fscc_base); + + t = (t >> RT3883_FLASH_CFG_WIDTH_SHIFT) & RT3883_FLASH_CFG_WIDTH_MASK; + switch (t) { + case RT3883_FLASH_CFG_WIDTH_8BIT: + pdata->width = 1; + break; + case RT3883_FLASH_CFG_WIDTH_16BIT: + pdata->width = 2; + break; + case RT3883_FLASH_CFG_WIDTH_32BIT: + if (id == 1) { + pdata->width = 4; + break; + } + /* fallthrough */ + default: + pr_warn("RT3883: flash bank%d: invalid width detected\n", id); + return; + } + + pdev->id = rt3883_flash_instance; + + platform_device_register(pdev); + rt3883_flash_instance++; +} + +static atomic_t rt3883_usb_use_count = ATOMIC_INIT(0); + +static void rt3883_usb_host_start(void) +{ + u32 t; + + if (atomic_inc_return(&rt3883_usb_use_count) != 1) + return; + + t = rt3883_sysc_rr(RT3883_SYSC_REG_USB_PS); + +#if 0 + /* put the HOST controller into reset */ + t = rt3883_sysc_rr(RT3883_SYSC_REG_RSTCTRL); + t |= RT3883_RSTCTRL_UHST; + rt3883_sysc_wr(t, RT3883_SYSC_REG_RSTCTRL); +#endif + + /* enable clock for port0's and port1's phys */ + t = rt3883_sysc_rr(RT3883_SYSC_REG_CLKCFG1); + t = t | RT3883_CLKCFG1_UPHY0_CLK_EN | RT3883_CLKCFG1_UPHY1_CLK_EN; + rt3883_sysc_wr(t, RT3883_SYSC_REG_CLKCFG1); + mdelay(500); + + /* pull USBHOST and USBDEV out from reset */ + t = rt3883_sysc_rr(RT3883_SYSC_REG_RSTCTRL); + t &= ~(RT3883_RSTCTRL_UHST | RT3883_RSTCTRL_UDEV); + rt3883_sysc_wr(t, RT3883_SYSC_REG_RSTCTRL); + mdelay(500); + + /* enable host mode */ + t = rt3883_sysc_rr(RT3883_SYSC_REG_SYSCFG1); + t |= RT3883_SYSCFG1_USB0_HOST_MODE; + rt3883_sysc_wr(t, RT3883_SYSC_REG_SYSCFG1); + + t = rt3883_sysc_rr(RT3883_SYSC_REG_USB_PS); +} + +static void rt3883_usb_host_stop(void) +{ + u32 t; + + if (atomic_dec_return(&rt3883_usb_use_count) != 0) + return; + + /* put USBHOST and USBDEV into reset */ + t = rt3883_sysc_rr(RT3883_SYSC_REG_RSTCTRL); + t |= RT3883_RSTCTRL_UHST | RT3883_RSTCTRL_UDEV; + rt3883_sysc_wr(t, RT3883_SYSC_REG_RSTCTRL); + udelay(10000); + + /* disable clock for port0's and port1's phys*/ + t = rt3883_sysc_rr(RT3883_SYSC_REG_CLKCFG1); + t &= ~(RT3883_CLKCFG1_UPHY0_CLK_EN | RT3883_CLKCFG1_UPHY1_CLK_EN); + rt3883_sysc_wr(t, RT3883_SYSC_REG_CLKCFG1); + udelay(10000); +} + +static struct rt3883_ehci_platform_data rt3883_ehci_data = { + .start_hw = rt3883_usb_host_start, + .stop_hw = rt3883_usb_host_stop, +}; + +static struct resource rt3883_ehci_resources[] = { + { + .start = RT3883_EHCI_BASE, + .end = RT3883_EHCI_BASE + PAGE_SIZE - 1, + .flags = IORESOURCE_MEM, + }, { + .start = RT3883_INTC_IRQ_UHST, + .end = RT3883_INTC_IRQ_UHST, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 rt3883_ehci_dmamask = DMA_BIT_MASK(32); +static struct platform_device rt3883_ehci_device = { + .name = "rt3883-ehci", + .id = -1, + .resource = rt3883_ehci_resources, + .num_resources = ARRAY_SIZE(rt3883_ehci_resources), + .dev = { + .dma_mask = &rt3883_ehci_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &rt3883_ehci_data, + }, +}; + +static struct resource rt3883_ohci_resources[] = { + { + .start = RT3883_OHCI_BASE, + .end = RT3883_OHCI_BASE + PAGE_SIZE - 1, + .flags = IORESOURCE_MEM, + }, { + .start = RT3883_INTC_IRQ_UHST, + .end = RT3883_INTC_IRQ_UHST, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct rt3883_ohci_platform_data rt3883_ohci_data = { + .start_hw = rt3883_usb_host_start, + .stop_hw = rt3883_usb_host_stop, +}; + +static u64 rt3883_ohci_dmamask = DMA_BIT_MASK(32); +static struct platform_device rt3883_ohci_device = { + .name = "rt3883-ohci", + .id = -1, + .resource = rt3883_ohci_resources, + .num_resources = ARRAY_SIZE(rt3883_ohci_resources), + .dev = { + .dma_mask = &rt3883_ohci_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &rt3883_ohci_data, + }, +}; + +void __init rt3883_register_usbhost(void) +{ + platform_device_register(&rt3883_ehci_device); + platform_device_register(&rt3883_ohci_device); +} + +static void rt3883_fe_reset(void) +{ + u32 t; + + t = rt3883_sysc_rr(RT3883_SYSC_REG_RSTCTRL); + t |= RT3883_RSTCTRL_FE; + rt3883_sysc_wr(t , RT3883_SYSC_REG_RSTCTRL); + + t &= ~RT3883_RSTCTRL_FE; + rt3883_sysc_wr(t, RT3883_SYSC_REG_RSTCTRL); +} + +static struct resource rt3883_eth_resources[] = { + { + .start = RT3883_FE_BASE, + .end = RT3883_FE_BASE + PAGE_SIZE - 1, + .flags = IORESOURCE_MEM, + }, { + .start = RT3883_CPU_IRQ_FE, + .end = RT3883_CPU_IRQ_FE, + .flags = IORESOURCE_IRQ, + }, +}; + +struct ramips_eth_platform_data rt3883_eth_data = { + .mac = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }, + .reset_fe = rt3883_fe_reset, + .min_pkt_len = 64, +}; + +static struct platform_device rt3883_eth_device = { + .name = "ramips_eth", + .resource = rt3883_eth_resources, + .num_resources = ARRAY_SIZE(rt3883_eth_resources), + .dev = { + .platform_data = &rt3883_eth_data, + } +}; + +void __init rt3883_register_ethernet(void) +{ + struct clk *clk; + + clk = clk_get(NULL, "sys"); + if (IS_ERR(clk)) + panic("unable to get SYS clock, err=%ld", PTR_ERR(clk)); + + rt3883_eth_data.sys_freq = clk_get_rate(clk); + + platform_device_register(&rt3883_eth_device); +} + +static struct resource rt3883_wlan_resources[] = { + { + .start = RT3883_WLAN_BASE, + .end = RT3883_WLAN_BASE + 0x3FFFF, + .flags = IORESOURCE_MEM, + }, { + .start = RT3883_CPU_IRQ_WLAN, + .end = RT3883_CPU_IRQ_WLAN, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct rt2x00_platform_data rt3883_wlan_data = { + .eeprom_file_name = "rt3883.eeprom", +}; + +static struct platform_device rt3883_wlan_device = { + .name = "rt2800_wmac", + .resource = rt3883_wlan_resources, + .num_resources = ARRAY_SIZE(rt3883_wlan_resources), + .dev = { + .platform_data = &rt3883_wlan_data, + } +}; + +void __init rt3883_register_wlan(void) +{ + platform_device_register(&rt3883_wlan_device); +} + +static struct resource rt3883_wdt_resources[] = { + { + .start = RT3883_TIMER_BASE, + .end = RT3883_TIMER_BASE + RT3883_TIMER_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device rt3883_wdt_device = { + .name = "ramips-wdt", + .id = -1, + .resource = rt3883_wdt_resources, + .num_resources = ARRAY_SIZE(rt3883_wdt_resources), +}; + +void __init rt3883_register_wdt(bool enable_reset) +{ + if (enable_reset) { + u32 t; + + /* enable WDT reset output on GPIO 2 */ + t = rt3883_sysc_rr(RT3883_SYSC_REG_SYSCFG1); + t |= RT3883_SYSCFG1_GPIO2_AS_WDT_OUT; + rt3883_sysc_wr(t, RT3883_SYSC_REG_SYSCFG1); + } + + platform_device_register(&rt3883_wdt_device); +} + +static struct resource rt3883_nand_resources[] = { + { + .flags = IORESOURCE_MEM, + .start = RT3883_NANDC_BASE, + .end = RT3883_NANDC_BASE + RT3883_NANDC_SIZE - 1, + }, +}; + +static struct ramips_nand_platform_data rt3883_nand_data; + +static struct platform_device rt3883_nand_device = { + .name = RAMIPS_NAND_DRIVER_NAME, + .id = -1, + .resource = rt3883_nand_resources, + .num_resources = ARRAY_SIZE(rt3883_nand_resources), + .dev = { + .platform_data = &rt3883_nand_data, + }, +}; + +void __init rt3883_register_nand(struct mtd_partition *parts, int nr_parts) +{ + rt3883_nand_data.parts = parts; + rt3883_nand_data.nr_parts = nr_parts; + platform_device_register(&rt3883_nand_device); +} diff --git a/target/linux/ramips/files/arch/mips/ralink/rt3883/devices.h b/target/linux/ramips/files/arch/mips/ralink/rt3883/devices.h new file mode 100644 index 000000000..4b460e355 --- /dev/null +++ b/target/linux/ramips/files/arch/mips/ralink/rt3883/devices.h @@ -0,0 +1,29 @@ +/* + * Ralink RT3662/3883 SoC specific platform device definitions + * + * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#ifndef _RT3883_DEVICES_H +#define _RT3883_DEVICES_H + +struct physmap_flash_data; + +extern struct physmap_flash_data rt3883_flash0_data; +extern struct physmap_flash_data rt3883_flash1_data; +void rt3883_register_pflash(unsigned int id); + +struct mtd_partition; +void rt3883_register_nand(struct mtd_partition *parts, int nr_parts); + +extern struct ramips_eth_platform_data rt3883_eth_data; +void rt3883_register_ethernet(void); +void rt3883_register_usbhost(void); +void rt3883_register_wlan(void); +void rt3883_register_wdt(bool enable_reset); + +#endif /* _RT3883_DEVICES_H */ diff --git a/target/linux/ramips/files/arch/mips/ralink/rt3883/early_printk.c b/target/linux/ramips/files/arch/mips/ralink/rt3883/early_printk.c new file mode 100644 index 000000000..e3bf7ba33 --- /dev/null +++ b/target/linux/ramips/files/arch/mips/ralink/rt3883/early_printk.c @@ -0,0 +1,29 @@ +/* + * Ralink RT3662/RT3883 SoC early printk support + * + * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/io.h> +#include <linux/serial_reg.h> + +#include <asm/addrspace.h> + +#include <asm/mach-ralink/rt3883_regs.h> + +#define UART_READ(r) \ + __raw_readl((void __iomem *)(KSEG1ADDR(RT3883_UART1_BASE) + 4 * (r))) + +#define UART_WRITE(r, v) \ + __raw_writel((v), (void __iomem *)(KSEG1ADDR(RT3883_UART1_BASE) + 4 * (r))) + +void prom_putchar(unsigned char ch) +{ + while (((UART_READ(RT3883_UART_REG_LSR)) & UART_LSR_THRE) == 0); + UART_WRITE(RT3883_UART_REG_TX, ch); + while (((UART_READ(RT3883_UART_REG_LSR)) & UART_LSR_THRE) == 0); +} diff --git a/target/linux/ramips/files/arch/mips/ralink/rt3883/irq.c b/target/linux/ramips/files/arch/mips/ralink/rt3883/irq.c new file mode 100644 index 000000000..b561fd38c --- /dev/null +++ b/target/linux/ramips/files/arch/mips/ralink/rt3883/irq.c @@ -0,0 +1,84 @@ +/* + * Ralink RT3662/RT3883 SoC specific interrupt handling + * + * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/irq.h> + +#include <asm/irq_cpu.h> +#include <asm/mipsregs.h> + +#include <asm/mach-ralink/common.h> +#include <asm/mach-ralink/rt3883.h> +#include <asm/mach-ralink/rt3883_regs.h> + +static void rt3883_intc_irq_dispatch(void) +{ + u32 pending; + + pending = ramips_intc_get_status(); + + if (pending & RT3883_INTC_INT_TIMER0) + do_IRQ(RT3883_INTC_IRQ_TIMER0); + + else if (pending & RT3883_INTC_INT_TIMER1) + do_IRQ(RT3883_INTC_IRQ_TIMER1); + + else if (pending & RT3883_INTC_INT_UART0) + do_IRQ(RT3883_INTC_IRQ_UART0); + + else if (pending & RT3883_INTC_INT_UART1) + do_IRQ(RT3883_INTC_IRQ_UART1); + + else if (pending & RT3883_INTC_INT_PERFC) + do_IRQ(RT3883_INTC_IRQ_PERFC); + + else if (pending & RT3883_INTC_INT_UHST) + do_IRQ(RT3883_INTC_IRQ_UHST); + + /* TODO: handle PIO interrupts as well */ + + else + spurious_interrupt(); +} + +asmlinkage void plat_irq_dispatch(void) +{ + unsigned long pending; + + pending = read_c0_status() & read_c0_cause() & ST0_IM; + + if (pending & STATUSF_IP7) + do_IRQ(RT3883_CPU_IRQ_COUNTER); + + else if (pending & STATUSF_IP5) + do_IRQ(RT3883_CPU_IRQ_FE); + + else if (pending & STATUSF_IP6) + do_IRQ(RT3883_CPU_IRQ_WLAN); + + else if (pending & STATUSF_IP4) + do_IRQ(RT3883_CPU_IRQ_PCI); + + else if (pending & STATUSF_IP2) + rt3883_intc_irq_dispatch(); + + else + spurious_interrupt(); +} + +void __init arch_init_irq(void) +{ + mips_cpu_irq_init(); + ramips_intc_irq_init(RT3883_INTC_BASE, RT3883_CPU_IRQ_INTC, + RT3883_INTC_IRQ_BASE); + cp0_perfcount_irq = RT3883_INTC_IRQ_PERFC; +} diff --git a/target/linux/ramips/files/arch/mips/ralink/rt3883/rt3883.c b/target/linux/ramips/files/arch/mips/ralink/rt3883/rt3883.c new file mode 100644 index 000000000..6e75b390f --- /dev/null +++ b/target/linux/ramips/files/arch/mips/ralink/rt3883/rt3883.c @@ -0,0 +1,211 @@ +/* + * Ralink RT3662/RT3883 SoC specific setup + * + * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> + * + * Parts of this file are based on Ralink's 2.6.21 BSP + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> + +#include <asm/mach-ralink/common.h> +#include <asm/mach-ralink/ramips_gpio.h> +#include <asm/mach-ralink/rt3883.h> +#include <asm/mach-ralink/rt3883_regs.h> + +void __iomem * rt3883_sysc_base; +void __iomem * rt3883_memc_base; + +void __init rt3883_detect_sys_type(void) +{ + u32 n0; + u32 n1; + u32 id; + + n0 = rt3883_sysc_rr(RT3883_SYSC_REG_CHIPID0_3); + n1 = rt3883_sysc_rr(RT3883_SYSC_REG_CHIPID4_7); + id = rt3883_sysc_rr(RT3883_SYSC_REG_REVID); + + snprintf(ramips_sys_type, RAMIPS_SYS_TYPE_LEN, + "Ralink %c%c%c%c%c%c%c%c ver:%u eco:%u", + (char) (n0 & 0xff), (char) ((n0 >> 8) & 0xff), + (char) ((n0 >> 16) & 0xff), (char) ((n0 >> 24) & 0xff), + (char) (n1 & 0xff), (char) ((n1 >> 8) & 0xff), + (char) ((n1 >> 16) & 0xff), (char) ((n1 >> 24) & 0xff), + (id >> RT3883_REVID_VER_ID_SHIFT) & RT3883_REVID_VER_ID_MASK, + (id & RT3883_REVID_ECO_ID_MASK)); +} + +static struct ramips_gpio_chip rt3883_gpio_chips[] = { + { + .chip = { + .label = "RT3883-GPIO0", + .base = 0, + .ngpio = 24, + }, + .regs = { + [RAMIPS_GPIO_REG_INT] = 0x00, + [RAMIPS_GPIO_REG_EDGE] = 0x04, + [RAMIPS_GPIO_REG_RENA] = 0x08, + [RAMIPS_GPIO_REG_FENA] = 0x0c, + [RAMIPS_GPIO_REG_DATA] = 0x20, + [RAMIPS_GPIO_REG_DIR] = 0x24, + [RAMIPS_GPIO_REG_POL] = 0x28, + [RAMIPS_GPIO_REG_SET] = 0x2c, + [RAMIPS_GPIO_REG_RESET] = 0x30, + [RAMIPS_GPIO_REG_TOGGLE] = 0x34, + }, + .map_base = RT3883_PIO_BASE, + .map_size = RT3883_PIO_SIZE, + }, + { + .chip = { + .label = "RT3883-GPIO1", + .base = 24, + .ngpio = 16, + }, + .regs = { + [RAMIPS_GPIO_REG_INT] = 0x38, + [RAMIPS_GPIO_REG_EDGE] = 0x3c, + [RAMIPS_GPIO_REG_RENA] = 0x40, + [RAMIPS_GPIO_REG_FENA] = 0x44, + [RAMIPS_GPIO_REG_DATA] = 0x48, + [RAMIPS_GPIO_REG_DIR] = 0x4c, + [RAMIPS_GPIO_REG_POL] = 0x50, + [RAMIPS_GPIO_REG_SET] = 0x54, + [RAMIPS_GPIO_REG_RESET] = 0x58, + [RAMIPS_GPIO_REG_TOGGLE] = 0x5c, + }, + .map_base = RT3883_PIO_BASE, + .map_size = RT3883_PIO_SIZE, + }, + { + .chip = { + .label = "RT3883-GPIO2", + .base = 40, + .ngpio = 32, + }, + .regs = { + [RAMIPS_GPIO_REG_INT] = 0x60, + [RAMIPS_GPIO_REG_EDGE] = 0x64, + [RAMIPS_GPIO_REG_RENA] = 0x68, + [RAMIPS_GPIO_REG_FENA] = 0x6c, + [RAMIPS_GPIO_REG_DATA] = 0x70, + [RAMIPS_GPIO_REG_DIR] = 0x74, + [RAMIPS_GPIO_REG_POL] = 0x78, + [RAMIPS_GPIO_REG_SET] = 0x7c, + [RAMIPS_GPIO_REG_RESET] = 0x80, + [RAMIPS_GPIO_REG_TOGGLE] = 0x84, + }, + .map_base = RT3883_PIO_BASE, + .map_size = RT3883_PIO_SIZE, + }, + { + .chip = { + .label = "RT3883-GPIO3", + .base = 72, + .ngpio = 24, + }, + .regs = { + [RAMIPS_GPIO_REG_INT] = 0x88, + [RAMIPS_GPIO_REG_EDGE] = 0x8c, + [RAMIPS_GPIO_REG_RENA] = 0x90, + [RAMIPS_GPIO_REG_FENA] = 0x94, + [RAMIPS_GPIO_REG_DATA] = 0x98, + [RAMIPS_GPIO_REG_DIR] = 0x9c, + [RAMIPS_GPIO_REG_POL] = 0xa0, + [RAMIPS_GPIO_REG_SET] = 0xa4, + [RAMIPS_GPIO_REG_RESET] = 0xa8, + [RAMIPS_GPIO_REG_TOGGLE] = 0xac, + }, + .map_base = RT3883_PIO_BASE, + .map_size = RT3883_PIO_SIZE, + }, +}; + +static struct ramips_gpio_data rt3883_gpio_data = { + .chips = rt3883_gpio_chips, + .num_chips = ARRAY_SIZE(rt3883_gpio_chips), +}; + +static void rt3883_gpio_reserve(int first, int last) +{ + for (; first <= last; first++) + gpio_request(first, "reserved"); +} + +void __init rt3883_gpio_init(u32 mode) +{ + u32 t; + + rt3883_sysc_wr(mode, RT3883_SYSC_REG_GPIO_MODE); + + ramips_gpio_init(&rt3883_gpio_data); + if ((mode & RT3883_GPIO_MODE_I2C) == 0) + rt3883_gpio_reserve(RT3883_GPIO_I2C_SD, RT3883_GPIO_I2C_SCLK); + + if ((mode & RT3883_GPIO_MODE_SPI) == 0) + rt3883_gpio_reserve(RT3883_GPIO_SPI_CS0, RT3883_GPIO_SPI_CLK); + + t = mode >> RT3883_GPIO_MODE_UART0_SHIFT; + t &= RT3883_GPIO_MODE_UART0_MASK; + switch (t) { + case RT3883_GPIO_MODE_UARTF: + case RT3883_GPIO_MODE_PCM_UARTF: + case RT3883_GPIO_MODE_PCM_I2S: + case RT3883_GPIO_MODE_I2S_UARTF: + rt3883_gpio_reserve(RT3883_GPIO_7, RT3883_GPIO_14); + break; + case RT3883_GPIO_MODE_PCM_GPIO: + rt3883_gpio_reserve(RT3883_GPIO_11, RT3883_GPIO_14); + break; + case RT3883_GPIO_MODE_GPIO_UARTF: + case RT3883_GPIO_MODE_GPIO_I2S: + rt3883_gpio_reserve(RT3883_GPIO_7, RT3883_GPIO_10); + break; + } + + if ((mode & RT3883_GPIO_MODE_UART1) == 0) + rt3883_gpio_reserve(RT3883_GPIO_UART1_TXD, + RT3883_GPIO_UART1_RXD); + + if ((mode & RT3883_GPIO_MODE_JTAG) == 0) + rt3883_gpio_reserve(RT3883_GPIO_JTAG_TDO, + RT3883_GPIO_JTAG_TCLK); + + if ((mode & RT3883_GPIO_MODE_MDIO) == 0) + rt3883_gpio_reserve(RT3883_GPIO_MDIO_MDC, + RT3883_GPIO_MDIO_MDIO); + + if ((mode & RT3883_GPIO_MODE_GE1) == 0) + rt3883_gpio_reserve(RT3883_GPIO_GE1_TXD0, + RT3883_GPIO_GE1_RXCLK); + + if ((mode & RT3883_GPIO_MODE_GE2) == 0) + rt3883_gpio_reserve(RT3883_GPIO_GE2_TXD0, + RT3883_GPIO_GE2_RXCLK); + + t = mode >> RT3883_GPIO_MODE_PCI_SHIFT; + t &= RT3883_GPIO_MODE_PCI_MASK; + if (t != RT3883_GPIO_MODE_PCI_GPIO) + rt3883_gpio_reserve(RT3883_GPIO_PCI_AD0, + RT3883_GPIO_PCI_AD31); + + t = mode >> RT3883_GPIO_MODE_LNA_A_SHIFT; + t &= RT3883_GPIO_MODE_LNA_A_MASK; + if (t != RT3883_GPIO_MODE_LNA_A_GPIO) + rt3883_gpio_reserve(RT3883_GPIO_LNA_PE_A0, + RT3883_GPIO_LNA_PE_A2); + + t = mode >> RT3883_GPIO_MODE_LNA_G_SHIFT; + t &= RT3883_GPIO_MODE_LNA_G_MASK; + if (t != RT3883_GPIO_MODE_LNA_G_GPIO) + rt3883_gpio_reserve(RT3883_GPIO_LNA_PE_G0, + RT3883_GPIO_LNA_PE_G2); +} diff --git a/target/linux/ramips/files/arch/mips/ralink/rt3883/setup.c b/target/linux/ramips/files/arch/mips/ralink/rt3883/setup.c new file mode 100644 index 000000000..f4c7296fa --- /dev/null +++ b/target/linux/ramips/files/arch/mips/ralink/rt3883/setup.c @@ -0,0 +1,89 @@ +/* + * Ralink RT3662/RT3883 SoC specific setup + * + * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> + * + * Parts of this file are based on Ralink's 2.6.21 BSP + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/err.h> +#include <linux/clk.h> + +#include <asm/mips_machine.h> +#include <asm/reboot.h> +#include <asm/time.h> + +#include <asm/mach-ralink/common.h> +#include <asm/mach-ralink/rt3883.h> +#include <asm/mach-ralink/rt3883_regs.h> +#include "common.h" + +static void rt3883_restart(char *command) +{ + rt3883_sysc_wr(RT3883_RSTCTRL_SYS, RT3883_SYSC_REG_RSTCTRL); + while (1) + if (cpu_wait) + cpu_wait(); +} + +static void rt3883_halt(void) +{ + while (1) + if (cpu_wait) + cpu_wait(); +} + +unsigned int __cpuinit get_c0_compare_irq(void) +{ + return CP0_LEGACY_COMPARE_IRQ; +} + +void __init ramips_soc_setup(void) +{ + struct clk *clk; + + rt3883_sysc_base = ioremap_nocache(RT3883_SYSC_BASE, PAGE_SIZE); + rt3883_memc_base = ioremap_nocache(RT3883_MEMC_BASE, PAGE_SIZE); + + rt3883_detect_sys_type(); + rt3883_clocks_init(); + + clk = clk_get(NULL, "cpu"); + if (IS_ERR(clk)) + panic("unable to get CPU clock, err=%ld", PTR_ERR(clk)); + + printk(KERN_INFO "%s running at %lu.%02lu MHz\n", ramips_sys_type, + clk_get_rate(clk) / 1000000, + (clk_get_rate(clk) % 1000000) * 100 / 1000000); + + _machine_restart = rt3883_restart; + _machine_halt = rt3883_halt; + pm_power_off = rt3883_halt; + + clk = clk_get(NULL, "uart"); + if (IS_ERR(clk)) + panic("unable to get UART clock, err=%ld", PTR_ERR(clk)); + + ramips_early_serial_setup(0, RT3883_UART0_BASE, clk_get_rate(clk), + RT3883_INTC_IRQ_UART0); + ramips_early_serial_setup(1, RT3883_UART1_BASE, clk_get_rate(clk), + RT3883_INTC_IRQ_UART1); +} + +void __init plat_time_init(void) +{ + struct clk *clk; + + clk = clk_get(NULL, "cpu"); + if (IS_ERR(clk)) + panic("unable to get CPU clock, err=%ld", PTR_ERR(clk)); + + mips_hpt_frequency = clk_get_rate(clk) / 2; +} |