1
0
Fork 0

Merge branches 'fixes-for-linus', 'generic', 'cavium', 'module.h-fixes', 'next/ath79' and 'next/lantiq' into mips-for-linux-next

hifive-unleashed-5.1
Ralf Baechle 2012-05-26 19:55:48 +01:00
129 changed files with 4496 additions and 2371 deletions

View File

@ -0,0 +1,38 @@
Lantiq SoC External Bus memory mapped GPIO controller
By attaching hardware latches to the EBU it is possible to create output
only gpios. This driver configures a special memory address, which when
written to outputs 16 bit to the latches.
The node describing the memory mapped GPIOs needs to be a child of the node
describing the "lantiq,localbus".
Required properties:
- compatible : Should be "lantiq,gpio-mm-lantiq"
- reg : Address and length of the register set for the device
- #gpio-cells : Should be two. The first cell is the pin number and
the second cell is used to specify optional parameters (currently
unused).
- gpio-controller : Marks the device node as a gpio controller.
Optional properties:
- lantiq,shadow : The default value that we shall assume as already set on the
shift register cascade.
Example:
localbus@0 {
#address-cells = <2>;
#size-cells = <1>;
ranges = <0 0 0x0 0x3ffffff /* addrsel0 */
1 0 0x4000000 0x4000010>; /* addsel1 */
compatible = "lantiq,localbus", "simple-bus";
gpio_mm0: gpio@4000000 {
compatible = "lantiq,gpio-mm";
reg = <1 0x0 0x10>;
gpio-controller;
#gpio-cells = <2>;
lantiq,shadow = <0x77f>
};
}

View File

@ -0,0 +1,42 @@
Lantiq SoC Serial To Parallel (STP) GPIO controller
The Serial To Parallel (STP) is found on MIPS based Lantiq socs. It is a
peripheral controller used to drive external shift register cascades. At most
3 groups of 8 bits can be driven. The hardware is able to allow the DSL modem
to drive the 2 LSBs of the cascade automatically.
Required properties:
- compatible : Should be "lantiq,gpio-stp-xway"
- reg : Address and length of the register set for the device
- #gpio-cells : Should be two. The first cell is the pin number and
the second cell is used to specify optional parameters (currently
unused).
- gpio-controller : Marks the device node as a gpio controller.
Optional properties:
- lantiq,shadow : The default value that we shall assume as already set on the
shift register cascade.
- lantiq,groups : Set the 3 bit mask to select which of the 3 groups are enabled
in the shift register cascade.
- lantiq,dsl : The dsl core can control the 2 LSBs of the gpio cascade. This 2 bit
property can enable this feature.
- lantiq,phy1 : The gphy1 core can control 3 bits of the gpio cascade.
- lantiq,phy2 : The gphy2 core can control 3 bits of the gpio cascade.
- lantiq,rising : use rising instead of falling edge for the shift register
Example:
gpio1: stp@E100BB0 {
compatible = "lantiq,gpio-stp-xway";
reg = <0xE100BB0 0x40>;
#gpio-cells = <2>;
gpio-controller;
lantiq,shadow = <0xffff>;
lantiq,groups = <0x7>;
lantiq,dsl = <0x3>;
lantiq,phy1 = <0x7>;
lantiq,phy2 = <0x7>;
/* lantiq,rising; */
};

View File

@ -228,8 +228,9 @@ config LANTIQ
select ARCH_REQUIRE_GPIOLIB
select SWAP_IO_SPACE
select BOOT_RAW
select HAVE_CLK
select MIPS_MACHINE
select HAVE_MACH_CLKDEV
select CLKDEV_LOOKUP
select USE_OF
config LASAT
bool "LASAT Networks platforms"

View File

@ -22,6 +22,7 @@
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/leds.h>

View File

@ -26,6 +26,18 @@ config ATH79_MACH_AP81
Say 'Y' here if you want your kernel to support the
Atheros AP81 reference board.
config ATH79_MACH_DB120
bool "Atheros DB120 reference board"
select SOC_AR934X
select ATH79_DEV_GPIO_BUTTONS
select ATH79_DEV_LEDS_GPIO
select ATH79_DEV_SPI
select ATH79_DEV_USB
select ATH79_DEV_WMAC
help
Say 'Y' here if you want your kernel to support the
Atheros DB120 reference board.
config ATH79_MACH_PB44
bool "Atheros PB44 reference board"
select SOC_AR71XX
@ -52,12 +64,14 @@ endmenu
config SOC_AR71XX
select USB_ARCH_HAS_EHCI
select USB_ARCH_HAS_OHCI
select HW_HAS_PCI
def_bool n
config SOC_AR724X
select USB_ARCH_HAS_EHCI
select USB_ARCH_HAS_OHCI
select HW_HAS_PCI
select PCI_AR724X if PCI
def_bool n
config SOC_AR913X
@ -68,6 +82,15 @@ config SOC_AR933X
select USB_ARCH_HAS_EHCI
def_bool n
config SOC_AR934X
select USB_ARCH_HAS_EHCI
select HW_HAS_PCI
select PCI_AR724X if PCI
def_bool n
config PCI_AR724X
def_bool n
config ATH79_DEV_GPIO_BUTTONS
def_bool n
@ -81,7 +104,7 @@ config ATH79_DEV_USB
def_bool n
config ATH79_DEV_WMAC
depends on (SOC_AR913X || SOC_AR933X)
depends on (SOC_AR913X || SOC_AR933X || SOC_AR934X)
def_bool n
endif

View File

@ -11,6 +11,7 @@
obj-y := prom.o setup.o irq.o common.o clock.o gpio.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_PCI) += pci.o
#
# Devices
@ -27,5 +28,6 @@ obj-$(CONFIG_ATH79_DEV_WMAC) += dev-wmac.o
#
obj-$(CONFIG_ATH79_MACH_AP121) += mach-ap121.o
obj-$(CONFIG_ATH79_MACH_AP81) += mach-ap81.o
obj-$(CONFIG_ATH79_MACH_DB120) += mach-db120.o
obj-$(CONFIG_ATH79_MACH_PB44) += mach-pb44.o
obj-$(CONFIG_ATH79_MACH_UBNT_XM) += mach-ubnt-xm.o

View File

@ -1,8 +1,11 @@
/*
* Atheros AR71XX/AR724X/AR913X common routines
*
* Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
* Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
*
* Parts of this file are based on Atheros' 2.6.15/2.6.31 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.
@ -163,6 +166,82 @@ static void __init ar933x_clocks_init(void)
ath79_uart_clk.rate = ath79_ref_clk.rate;
}
static void __init ar934x_clocks_init(void)
{
u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv;
u32 cpu_pll, ddr_pll;
u32 bootstrap;
bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP);
if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40)
ath79_ref_clk.rate = 40 * 1000 * 1000;
else
ath79_ref_clk.rate = 25 * 1000 * 1000;
pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG);
out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
AR934X_PLL_CPU_CONFIG_OUTDIV_MASK;
ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
AR934X_PLL_CPU_CONFIG_REFDIV_MASK;
nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) &
AR934X_PLL_CPU_CONFIG_NINT_MASK;
frac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) &
AR934X_PLL_CPU_CONFIG_NFRAC_MASK;
cpu_pll = nint * ath79_ref_clk.rate / ref_div;
cpu_pll += frac * ath79_ref_clk.rate / (ref_div * (2 << 6));
cpu_pll /= (1 << out_div);
pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG);
out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
AR934X_PLL_DDR_CONFIG_OUTDIV_MASK;
ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
AR934X_PLL_DDR_CONFIG_REFDIV_MASK;
nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) &
AR934X_PLL_DDR_CONFIG_NINT_MASK;
frac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) &
AR934X_PLL_DDR_CONFIG_NFRAC_MASK;
ddr_pll = nint * ath79_ref_clk.rate / ref_div;
ddr_pll += frac * ath79_ref_clk.rate / (ref_div * (2 << 10));
ddr_pll /= (1 << out_div);
clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG);
postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT) &
AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK;
if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS)
ath79_cpu_clk.rate = ath79_ref_clk.rate;
else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL)
ath79_cpu_clk.rate = cpu_pll / (postdiv + 1);
else
ath79_cpu_clk.rate = ddr_pll / (postdiv + 1);
postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT) &
AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK;
if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS)
ath79_ddr_clk.rate = ath79_ref_clk.rate;
else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL)
ath79_ddr_clk.rate = ddr_pll / (postdiv + 1);
else
ath79_ddr_clk.rate = cpu_pll / (postdiv + 1);
postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT) &
AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK;
if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS)
ath79_ahb_clk.rate = ath79_ref_clk.rate;
else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL)
ath79_ahb_clk.rate = ddr_pll / (postdiv + 1);
else
ath79_ahb_clk.rate = cpu_pll / (postdiv + 1);
ath79_wdt_clk.rate = ath79_ref_clk.rate;
ath79_uart_clk.rate = ath79_ref_clk.rate;
}
void __init ath79_clocks_init(void)
{
if (soc_is_ar71xx())
@ -173,6 +252,8 @@ void __init ath79_clocks_init(void)
ar913x_clocks_init();
else if (soc_is_ar933x())
ar933x_clocks_init();
else if (soc_is_ar934x())
ar934x_clocks_init();
else
BUG();

View File

@ -1,9 +1,12 @@
/*
* Atheros AR71XX/AR724X/AR913X common routines
*
* Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
* Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
*
* Parts of this file are based on Atheros' 2.6.15/2.6.31 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.
@ -67,6 +70,8 @@ void ath79_device_reset_set(u32 mask)
reg = AR913X_RESET_REG_RESET_MODULE;
else if (soc_is_ar933x())
reg = AR933X_RESET_REG_RESET_MODULE;
else if (soc_is_ar934x())
reg = AR934X_RESET_REG_RESET_MODULE;
else
BUG();
@ -91,6 +96,8 @@ void ath79_device_reset_clear(u32 mask)
reg = AR913X_RESET_REG_RESET_MODULE;
else if (soc_is_ar933x())
reg = AR933X_RESET_REG_RESET_MODULE;
else if (soc_is_ar934x())
reg = AR934X_RESET_REG_RESET_MODULE;
else
BUG();

View File

@ -89,7 +89,8 @@ void __init ath79_register_uart(void)
if (soc_is_ar71xx() ||
soc_is_ar724x() ||
soc_is_ar913x()) {
soc_is_ar913x() ||
soc_is_ar934x()) {
ath79_uart_data[0].uartclk = clk_get_rate(clk);
platform_device_register(&ath79_uart_device);
} else if (soc_is_ar933x()) {

View File

@ -25,12 +25,10 @@ void __init ath79_register_gpio_keys_polled(int id,
struct gpio_keys_button *p;
int err;
p = kmalloc(nbuttons * sizeof(*p), GFP_KERNEL);
p = kmemdup(buttons, nbuttons * sizeof(*p), GFP_KERNEL);
if (!p)
return;
memcpy(p, buttons, nbuttons * sizeof(*p));
pdev = platform_device_alloc("gpio-keys-polled", id);
if (!pdev)
goto err_free_buttons;

View File

@ -24,12 +24,10 @@ void __init ath79_register_leds_gpio(int id,
struct gpio_led *p;
int err;
p = kmalloc(num_leds * sizeof(*p), GFP_KERNEL);
p = kmemdup(leds, num_leds * sizeof(*p), GFP_KERNEL);
if (!p)
return;
memcpy(p, leds, num_leds * sizeof(*p));
pdev = platform_device_alloc("leds-gpio", id);
if (!pdev)
goto err_free_leds;

View File

@ -1,9 +1,12 @@
/*
* Atheros AR913X/AR933X SoC built-in WMAC device support
*
* Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
* Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
*
* Parts of this file are based on Atheros 2.6.15/2.6.31 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.
@ -26,8 +29,7 @@ static struct resource ath79_wmac_resources[] = {
/* .start and .end fields are filled dynamically */
.flags = IORESOURCE_MEM,
}, {
.start = ATH79_CPU_IRQ_IP2,
.end = ATH79_CPU_IRQ_IP2,
/* .start and .end fields are filled dynamically */
.flags = IORESOURCE_IRQ,
},
};
@ -53,6 +55,8 @@ static void __init ar913x_wmac_setup(void)
ath79_wmac_resources[0].start = AR913X_WMAC_BASE;
ath79_wmac_resources[0].end = AR913X_WMAC_BASE + AR913X_WMAC_SIZE - 1;
ath79_wmac_resources[1].start = ATH79_CPU_IRQ_IP2;
ath79_wmac_resources[1].end = ATH79_CPU_IRQ_IP2;
}
@ -79,6 +83,8 @@ static void __init ar933x_wmac_setup(void)
ath79_wmac_resources[0].start = AR933X_WMAC_BASE;
ath79_wmac_resources[0].end = AR933X_WMAC_BASE + AR933X_WMAC_SIZE - 1;
ath79_wmac_resources[1].start = ATH79_CPU_IRQ_IP2;
ath79_wmac_resources[1].end = ATH79_CPU_IRQ_IP2;
t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP);
if (t & AR933X_BOOTSTRAP_REF_CLK_40)
@ -92,12 +98,32 @@ static void __init ar933x_wmac_setup(void)
ath79_wmac_data.external_reset = ar933x_wmac_reset;
}
static void ar934x_wmac_setup(void)
{
u32 t;
ath79_wmac_device.name = "ar934x_wmac";
ath79_wmac_resources[0].start = AR934X_WMAC_BASE;
ath79_wmac_resources[0].end = AR934X_WMAC_BASE + AR934X_WMAC_SIZE - 1;
ath79_wmac_resources[1].start = ATH79_IP2_IRQ(1);
ath79_wmac_resources[1].start = ATH79_IP2_IRQ(1);
t = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP);
if (t & AR934X_BOOTSTRAP_REF_CLK_40)
ath79_wmac_data.is_clk_25mhz = false;
else
ath79_wmac_data.is_clk_25mhz = true;
}
void __init ath79_register_wmac(u8 *cal_data)
{
if (soc_is_ar913x())
ar913x_wmac_setup();
else if (soc_is_ar933x())
ar933x_wmac_setup();
else if (soc_is_ar934x())
ar934x_wmac_setup();
else
BUG();

View File

@ -71,6 +71,9 @@ static void prom_putchar_init(void)
case REV_ID_MAJOR_AR7241:
case REV_ID_MAJOR_AR7242:
case REV_ID_MAJOR_AR913X:
case REV_ID_MAJOR_AR9341:
case REV_ID_MAJOR_AR9342:
case REV_ID_MAJOR_AR9344:
_prom_putchar = prom_putchar_ar71xx;
break;

View File

@ -1,9 +1,12 @@
/*
* Atheros AR71XX/AR724X/AR913X GPIO API support
*
* Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
* Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
*
* Parts of this file are based on Atheros' 2.6.15/2.6.31 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.
@ -89,6 +92,42 @@ static int ath79_gpio_direction_output(struct gpio_chip *chip,
return 0;
}
static int ar934x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
void __iomem *base = ath79_gpio_base;
unsigned long flags;
spin_lock_irqsave(&ath79_gpio_lock, flags);
__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
base + AR71XX_GPIO_REG_OE);
spin_unlock_irqrestore(&ath79_gpio_lock, flags);
return 0;
}
static int ar934x_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
int value)
{
void __iomem *base = ath79_gpio_base;
unsigned long flags;
spin_lock_irqsave(&ath79_gpio_lock, flags);
if (value)
__raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
else
__raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
base + AR71XX_GPIO_REG_OE);
spin_unlock_irqrestore(&ath79_gpio_lock, flags);
return 0;
}
static struct gpio_chip ath79_gpio_chip = {
.label = "ath79",
.get = ath79_gpio_get_value,
@ -155,11 +194,17 @@ void __init ath79_gpio_init(void)
ath79_gpio_count = AR913X_GPIO_COUNT;
else if (soc_is_ar933x())
ath79_gpio_count = AR933X_GPIO_COUNT;
else if (soc_is_ar934x())
ath79_gpio_count = AR934X_GPIO_COUNT;
else
BUG();
ath79_gpio_base = ioremap_nocache(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE);
ath79_gpio_chip.ngpio = ath79_gpio_count;
if (soc_is_ar934x()) {
ath79_gpio_chip.direction_input = ar934x_gpio_direction_input;
ath79_gpio_chip.direction_output = ar934x_gpio_direction_output;
}
err = gpiochip_add(&ath79_gpio_chip);
if (err)

View File

@ -1,10 +1,11 @@
/*
* Atheros AR71xx/AR724x/AR913x specific interrupt handling
*
* Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
* Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
*
* Parts of this file are based on Atheros' 2.6.15 BSP
* Parts of this file are based on Atheros' 2.6.15/2.6.31 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
@ -23,8 +24,8 @@
#include <asm/mach-ath79/ar71xx_regs.h>
#include "common.h"
static unsigned int ath79_ip2_flush_reg;
static unsigned int ath79_ip3_flush_reg;
static void (*ath79_ip2_handler)(void);
static void (*ath79_ip3_handler)(void);
static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc)
{
@ -129,7 +130,7 @@ static void __init ath79_misc_irq_init(void)
if (soc_is_ar71xx() || soc_is_ar913x())
ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask;
else if (soc_is_ar724x() || soc_is_ar933x())
else if (soc_is_ar724x() || soc_is_ar933x() || soc_is_ar934x())
ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack;
else
BUG();
@ -143,6 +144,39 @@ static void __init ath79_misc_irq_init(void)
irq_set_chained_handler(ATH79_CPU_IRQ_MISC, ath79_misc_irq_handler);
}
static void ar934x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc)
{
u32 status;
disable_irq_nosync(irq);
status = ath79_reset_rr(AR934X_RESET_REG_PCIE_WMAC_INT_STATUS);
if (status & AR934X_PCIE_WMAC_INT_PCIE_ALL) {
ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_PCIE);
generic_handle_irq(ATH79_IP2_IRQ(0));
} else if (status & AR934X_PCIE_WMAC_INT_WMAC_ALL) {
ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_WMAC);
generic_handle_irq(ATH79_IP2_IRQ(1));
} else {
spurious_interrupt();
}
enable_irq(irq);
}
static void ar934x_ip2_irq_init(void)
{
int i;
for (i = ATH79_IP2_IRQ_BASE;
i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++)
irq_set_chip_and_handler(i, &dummy_irq_chip,
handle_level_irq);
irq_set_chained_handler(ATH79_CPU_IRQ_IP2, ar934x_ip2_irq_dispatch);
}
asmlinkage void plat_irq_dispatch(void)
{
unsigned long pending;
@ -152,10 +186,8 @@ asmlinkage void plat_irq_dispatch(void)
if (pending & STATUSF_IP7)
do_IRQ(ATH79_CPU_IRQ_TIMER);
else if (pending & STATUSF_IP2) {
ath79_ddr_wb_flush(ath79_ip2_flush_reg);
do_IRQ(ATH79_CPU_IRQ_IP2);
}
else if (pending & STATUSF_IP2)
ath79_ip2_handler();
else if (pending & STATUSF_IP4)
do_IRQ(ATH79_CPU_IRQ_GE0);
@ -163,10 +195,8 @@ asmlinkage void plat_irq_dispatch(void)
else if (pending & STATUSF_IP5)
do_IRQ(ATH79_CPU_IRQ_GE1);
else if (pending & STATUSF_IP3) {
ath79_ddr_wb_flush(ath79_ip3_flush_reg);
do_IRQ(ATH79_CPU_IRQ_USB);
}
else if (pending & STATUSF_IP3)
ath79_ip3_handler();
else if (pending & STATUSF_IP6)
do_IRQ(ATH79_CPU_IRQ_MISC);
@ -175,24 +205,97 @@ asmlinkage void plat_irq_dispatch(void)
spurious_interrupt();
}
/*
* The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for
* these devices typically allocate coherent DMA memory, however the
* DMA controller may still have some unsynchronized data in the FIFO.
* Issue a flush in the handlers to ensure that the driver sees
* the update.
*/
static void ar71xx_ip2_handler(void)
{
ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_PCI);
do_IRQ(ATH79_CPU_IRQ_IP2);
}
static void ar724x_ip2_handler(void)
{
ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_PCIE);
do_IRQ(ATH79_CPU_IRQ_IP2);
}
static void ar913x_ip2_handler(void)
{
ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_WMAC);
do_IRQ(ATH79_CPU_IRQ_IP2);
}
static void ar933x_ip2_handler(void)
{
ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_WMAC);
do_IRQ(ATH79_CPU_IRQ_IP2);
}
static void ar934x_ip2_handler(void)
{
do_IRQ(ATH79_CPU_IRQ_IP2);
}
static void ar71xx_ip3_handler(void)
{
ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_USB);
do_IRQ(ATH79_CPU_IRQ_USB);
}
static void ar724x_ip3_handler(void)
{
ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_USB);
do_IRQ(ATH79_CPU_IRQ_USB);
}
static void ar913x_ip3_handler(void)
{
ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_USB);
do_IRQ(ATH79_CPU_IRQ_USB);
}
static void ar933x_ip3_handler(void)
{
ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_USB);
do_IRQ(ATH79_CPU_IRQ_USB);
}
static void ar934x_ip3_handler(void)
{
ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_USB);
do_IRQ(ATH79_CPU_IRQ_USB);
}
void __init arch_init_irq(void)
{
if (soc_is_ar71xx()) {
ath79_ip2_flush_reg = AR71XX_DDR_REG_FLUSH_PCI;
ath79_ip3_flush_reg = AR71XX_DDR_REG_FLUSH_USB;
ath79_ip2_handler = ar71xx_ip2_handler;
ath79_ip3_handler = ar71xx_ip3_handler;
} else if (soc_is_ar724x()) {
ath79_ip2_flush_reg = AR724X_DDR_REG_FLUSH_PCIE;
ath79_ip3_flush_reg = AR724X_DDR_REG_FLUSH_USB;
ath79_ip2_handler = ar724x_ip2_handler;
ath79_ip3_handler = ar724x_ip3_handler;
} else if (soc_is_ar913x()) {
ath79_ip2_flush_reg = AR913X_DDR_REG_FLUSH_WMAC;
ath79_ip3_flush_reg = AR913X_DDR_REG_FLUSH_USB;
ath79_ip2_handler = ar913x_ip2_handler;
ath79_ip3_handler = ar913x_ip3_handler;
} else if (soc_is_ar933x()) {
ath79_ip2_flush_reg = AR933X_DDR_REG_FLUSH_WMAC;
ath79_ip3_flush_reg = AR933X_DDR_REG_FLUSH_USB;
} else
ath79_ip2_handler = ar933x_ip2_handler;
ath79_ip3_handler = ar933x_ip3_handler;
} else if (soc_is_ar934x()) {
ath79_ip2_handler = ar934x_ip2_handler;
ath79_ip3_handler = ar934x_ip3_handler;
} else {
BUG();
}
cp0_perfcount_irq = ATH79_MISC_IRQ_PERFC;
mips_cpu_irq_init();
ath79_misc_irq_init();
if (soc_is_ar934x())
ar934x_ip2_irq_init();
}

View File

@ -0,0 +1,134 @@
/*
* Atheros DB120 reference board support
*
* Copyright (c) 2011 Qualcomm Atheros
* Copyright (c) 2011 Gabor Juhos <juhosg@openwrt.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include <linux/pci.h>
#include <linux/ath9k_platform.h>
#include "machtypes.h"
#include "dev-gpio-buttons.h"
#include "dev-leds-gpio.h"
#include "dev-spi.h"
#include "dev-wmac.h"
#include "pci.h"
#define DB120_GPIO_LED_WLAN_5G 12
#define DB120_GPIO_LED_WLAN_2G 13
#define DB120_GPIO_LED_STATUS 14
#define DB120_GPIO_LED_WPS 15
#define DB120_GPIO_BTN_WPS 16
#define DB120_KEYS_POLL_INTERVAL 20 /* msecs */
#define DB120_KEYS_DEBOUNCE_INTERVAL (3 * DB120_KEYS_POLL_INTERVAL)
#define DB120_WMAC_CALDATA_OFFSET 0x1000
#define DB120_PCIE_CALDATA_OFFSET 0x5000
static struct gpio_led db120_leds_gpio[] __initdata = {
{
.name = "db120:green:status",
.gpio = DB120_GPIO_LED_STATUS,
.active_low = 1,
},
{
.name = "db120:green:wps",
.gpio = DB120_GPIO_LED_WPS,
.active_low = 1,
},
{
.name = "db120:green:wlan-5g",
.gpio = DB120_GPIO_LED_WLAN_5G,
.active_low = 1,
},
{
.name = "db120:green:wlan-2g",
.gpio = DB120_GPIO_LED_WLAN_2G,
.active_low = 1,
},
};
static struct gpio_keys_button db120_gpio_keys[] __initdata = {
{
.desc = "WPS button",
.type = EV_KEY,
.code = KEY_WPS_BUTTON,
.debounce_interval = DB120_KEYS_DEBOUNCE_INTERVAL,
.gpio = DB120_GPIO_BTN_WPS,
.active_low = 1,
},
};
static struct spi_board_info db120_spi_info[] = {
{
.bus_num = 0,
.chip_select = 0,
.max_speed_hz = 25000000,
.modalias = "s25sl064a",
}
};
static struct ath79_spi_platform_data db120_spi_data = {
.bus_num = 0,
.num_chipselect = 1,
};
#ifdef CONFIG_PCI
static struct ath9k_platform_data db120_ath9k_data;
static int db120_pci_plat_dev_init(struct pci_dev *dev)
{
switch (PCI_SLOT(dev->devfn)) {
case 0:
dev->dev.platform_data = &db120_ath9k_data;
break;
}
return 0;
}
static void __init db120_pci_init(u8 *eeprom)
{
memcpy(db120_ath9k_data.eeprom_data, eeprom,
sizeof(db120_ath9k_data.eeprom_data));
ath79_pci_set_plat_dev_init(db120_pci_plat_dev_init);
ath79_register_pci();
}
#else
static inline void db120_pci_init(void) {}
#endif /* CONFIG_PCI */
static void __init db120_setup(void)
{
u8 *art = (u8 *) KSEG1ADDR(0x1fff0000);
ath79_register_leds_gpio(-1, ARRAY_SIZE(db120_leds_gpio),
db120_leds_gpio);
ath79_register_gpio_keys_polled(-1, DB120_KEYS_POLL_INTERVAL,
ARRAY_SIZE(db120_gpio_keys),
db120_gpio_keys);
ath79_register_spi(&db120_spi_data, db120_spi_info,
ARRAY_SIZE(db120_spi_info));
ath79_register_wmac(art + DB120_WMAC_CALDATA_OFFSET);
db120_pci_init(art + DB120_PCIE_CALDATA_OFFSET);
}
MIPS_MACHINE(ATH79_MACH_DB120, "DB120", "Atheros DB120 reference board",
db120_setup);

View File

@ -19,6 +19,7 @@
#include "dev-leds-gpio.h"
#include "dev-spi.h"
#include "dev-usb.h"
#include "pci.h"
#define PB44_GPIO_I2C_SCL 0
#define PB44_GPIO_I2C_SDA 1
@ -114,6 +115,7 @@ static void __init pb44_init(void)
ath79_register_spi(&pb44_spi_data, pb44_spi_info,
ARRAY_SIZE(pb44_spi_info));
ath79_register_usb();
ath79_register_pci();
}
MIPS_MACHINE(ATH79_MACH_PB44, "PB44", "Atheros PB44 reference board",

View File

@ -12,16 +12,15 @@
#include <linux/init.h>
#include <linux/pci.h>
#ifdef CONFIG_PCI
#include <linux/ath9k_platform.h>
#include <asm/mach-ath79/pci-ath724x.h>
#endif /* CONFIG_PCI */
#include <asm/mach-ath79/irq.h>
#include "machtypes.h"
#include "dev-gpio-buttons.h"
#include "dev-leds-gpio.h"
#include "dev-spi.h"
#include "pci.h"
#define UBNT_XM_GPIO_LED_L1 0
#define UBNT_XM_GPIO_LED_L2 1
@ -33,7 +32,6 @@
#define UBNT_XM_KEYS_POLL_INTERVAL 20
#define UBNT_XM_KEYS_DEBOUNCE_INTERVAL (3 * UBNT_XM_KEYS_POLL_INTERVAL)
#define UBNT_XM_PCI_IRQ 48
#define UBNT_XM_EEPROM_ADDR (u8 *) KSEG1ADDR(0x1fff1000)
static struct gpio_led ubnt_xm_leds_gpio[] __initdata = {
@ -84,12 +82,27 @@ static struct ath79_spi_platform_data ubnt_xm_spi_data = {
#ifdef CONFIG_PCI
static struct ath9k_platform_data ubnt_xm_eeprom_data;
static struct ath724x_pci_data ubnt_xm_pci_data[] = {
{
.irq = UBNT_XM_PCI_IRQ,
.pdata = &ubnt_xm_eeprom_data,
},
};
static int ubnt_xm_pci_plat_dev_init(struct pci_dev *dev)
{
switch (PCI_SLOT(dev->devfn)) {
case 0:
dev->dev.platform_data = &ubnt_xm_eeprom_data;
break;
}
return 0;
}
static void __init ubnt_xm_pci_init(void)
{
memcpy(ubnt_xm_eeprom_data.eeprom_data, UBNT_XM_EEPROM_ADDR,
sizeof(ubnt_xm_eeprom_data.eeprom_data));
ath79_pci_set_plat_dev_init(ubnt_xm_pci_plat_dev_init);
ath79_register_pci();
}
#else
static inline void ubnt_xm_pci_init(void) {}
#endif /* CONFIG_PCI */
static void __init ubnt_xm_init(void)
@ -104,13 +117,7 @@ static void __init ubnt_xm_init(void)
ath79_register_spi(&ubnt_xm_spi_data, ubnt_xm_spi_info,
ARRAY_SIZE(ubnt_xm_spi_info));
#ifdef CONFIG_PCI
memcpy(ubnt_xm_eeprom_data.eeprom_data, UBNT_XM_EEPROM_ADDR,
sizeof(ubnt_xm_eeprom_data.eeprom_data));
ath724x_pci_add_data(ubnt_xm_pci_data, ARRAY_SIZE(ubnt_xm_pci_data));
#endif /* CONFIG_PCI */
ubnt_xm_pci_init();
}
MIPS_MACHINE(ATH79_MACH_UBNT_XM,

View File

@ -18,6 +18,7 @@ enum ath79_mach_type {
ATH79_MACH_GENERIC = 0,
ATH79_MACH_AP121, /* Atheros AP121 reference board */
ATH79_MACH_AP81, /* Atheros AP81 reference board */
ATH79_MACH_DB120, /* Atheros DB120 reference board */
ATH79_MACH_PB44, /* Atheros PB44 reference board */
ATH79_MACH_UBNT_XM, /* Ubiquiti Networks XM board rev 1.0 */
};

View File

@ -0,0 +1,130 @@
/*
* Atheros AR71XX/AR724X specific PCI setup code
*
* Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
* Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
*
* Parts of this file are based on Atheros' 2.6.15 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/init.h>
#include <linux/pci.h>
#include <asm/mach-ath79/ar71xx_regs.h>
#include <asm/mach-ath79/ath79.h>
#include <asm/mach-ath79/irq.h>
#include <asm/mach-ath79/pci.h>
#include "pci.h"
static int (*ath79_pci_plat_dev_init)(struct pci_dev *dev);
static const struct ath79_pci_irq *ath79_pci_irq_map __initdata;
static unsigned ath79_pci_nr_irqs __initdata;
static const struct ath79_pci_irq ar71xx_pci_irq_map[] __initconst = {
{
.slot = 17,
.pin = 1,
.irq = ATH79_PCI_IRQ(0),
}, {
.slot = 18,
.pin = 1,
.irq = ATH79_PCI_IRQ(1),
}, {
.slot = 19,
.pin = 1,
.irq = ATH79_PCI_IRQ(2),
}
};
static const struct ath79_pci_irq ar724x_pci_irq_map[] __initconst = {
{
.slot = 0,
.pin = 1,
.irq = ATH79_PCI_IRQ(0),
}
};
int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)
{
int irq = -1;
int i;
if (ath79_pci_nr_irqs == 0 ||
ath79_pci_irq_map == NULL) {
if (soc_is_ar71xx()) {
ath79_pci_irq_map = ar71xx_pci_irq_map;
ath79_pci_nr_irqs = ARRAY_SIZE(ar71xx_pci_irq_map);
} else if (soc_is_ar724x() ||
soc_is_ar9342() ||
soc_is_ar9344()) {
ath79_pci_irq_map = ar724x_pci_irq_map;
ath79_pci_nr_irqs = ARRAY_SIZE(ar724x_pci_irq_map);
} else {
pr_crit("pci %s: invalid irq map\n",
pci_name((struct pci_dev *) dev));
return irq;
}
}
for (i = 0; i < ath79_pci_nr_irqs; i++) {
const struct ath79_pci_irq *entry;
entry = &ath79_pci_irq_map[i];
if (entry->slot == slot && entry->pin == pin) {
irq = entry->irq;
break;
}
}
if (irq < 0)
pr_crit("pci %s: no irq found for pin %u\n",
pci_name((struct pci_dev *) dev), pin);
else
pr_info("pci %s: using irq %d for pin %u\n",
pci_name((struct pci_dev *) dev), irq, pin);
return irq;
}
int pcibios_plat_dev_init(struct pci_dev *dev)
{
if (ath79_pci_plat_dev_init)
return ath79_pci_plat_dev_init(dev);
return 0;
}
void __init ath79_pci_set_irq_map(unsigned nr_irqs,
const struct ath79_pci_irq *map)
{
ath79_pci_nr_irqs = nr_irqs;
ath79_pci_irq_map = map;
}
void __init ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *dev))
{
ath79_pci_plat_dev_init = func;
}
int __init ath79_register_pci(void)
{
if (soc_is_ar71xx())
return ar71xx_pcibios_init();
if (soc_is_ar724x())
return ar724x_pcibios_init(ATH79_CPU_IRQ_IP2);
if (soc_is_ar9342() || soc_is_ar9344()) {
u32 bootstrap;
bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP);
if (bootstrap & AR934X_BOOTSTRAP_PCIE_RC)
return ar724x_pcibios_init(ATH79_IP2_IRQ(0));
}
return -ENODEV;
}

View File

@ -0,0 +1,34 @@
/*
* Atheros AR71XX/AR724X PCI support
*
* Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
* Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2008 Imre Kaloz <kaloz@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 _ATH79_PCI_H
#define _ATH79_PCI_H
struct ath79_pci_irq {
u8 slot;
u8 pin;
int irq;
};
#ifdef CONFIG_PCI
void ath79_pci_set_irq_map(unsigned nr_irqs, const struct ath79_pci_irq *map);
void ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *dev));
int ath79_register_pci(void);
#else
static inline void
ath79_pci_set_irq_map(unsigned nr_irqs, const struct ath79_pci_irq *map) {}
static inline void
ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *)) {}
static inline int ath79_register_pci(void) { return 0; }
#endif
#endif /* _ATH79_PCI_H */

View File

@ -1,10 +1,11 @@
/*
* Atheros AR71XX/AR724X/AR913X specific setup
*
* Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
* Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
*
* Parts of this file are based on Atheros' 2.6.15 BSP
* Parts of this file are based on Atheros' 2.6.15/2.6.31 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
@ -116,18 +117,6 @@ static void __init ath79_detect_sys_type(void)
rev = id & AR724X_REV_ID_REVISION_MASK;
break;
case REV_ID_MAJOR_AR9330:
ath79_soc = ATH79_SOC_AR9330;
chip = "9330";
rev = id & AR933X_REV_ID_REVISION_MASK;
break;
case REV_ID_MAJOR_AR9331:
ath79_soc = ATH79_SOC_AR9331;
chip = "9331";
rev = id & AR933X_REV_ID_REVISION_MASK;
break;
case REV_ID_MAJOR_AR913X:
minor = id & AR913X_REV_ID_MINOR_MASK;
rev = id >> AR913X_REV_ID_REVISION_SHIFT;
@ -145,6 +134,36 @@ static void __init ath79_detect_sys_type(void)
}
break;
case REV_ID_MAJOR_AR9330:
ath79_soc = ATH79_SOC_AR9330;
chip = "9330";
rev = id & AR933X_REV_ID_REVISION_MASK;
break;
case REV_ID_MAJOR_AR9331:
ath79_soc = ATH79_SOC_AR9331;
chip = "9331";
rev = id & AR933X_REV_ID_REVISION_MASK;
break;
case REV_ID_MAJOR_AR9341:
ath79_soc = ATH79_SOC_AR9341;
chip = "9341";
rev = id & AR934X_REV_ID_REVISION_MASK;
break;
case REV_ID_MAJOR_AR9342:
ath79_soc = ATH79_SOC_AR9342;
chip = "9342";
rev = id & AR934X_REV_ID_REVISION_MASK;
break;
case REV_ID_MAJOR_AR9344:
ath79_soc = ATH79_SOC_AR9344;
chip = "9344";
rev = id & AR934X_REV_ID_REVISION_MASK;
break;
default:
panic("ath79: unknown SoC, id:0x%08x", id);
}

View File

@ -1,3 +1 @@
obj-$(CONFIG_BOARD_BCM963XX) += board_bcm963xx.o
ccflags-y := -Werror

View File

@ -9,6 +9,7 @@
#include <linux/init.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/serial.h>

View File

@ -257,8 +257,6 @@ DEFINE_PER_CPU(int, cpu_state);
extern void fixup_irqs(void);
static DEFINE_SPINLOCK(smp_reserve_lock);
static int octeon_cpu_disable(void)
{
unsigned int cpu = smp_processor_id();
@ -266,8 +264,6 @@ static int octeon_cpu_disable(void)
if (cpu == 0)
return -EBUSY;
spin_lock(&smp_reserve_lock);
set_cpu_online(cpu, false);
cpu_clear(cpu, cpu_callin_map);
local_irq_disable();
@ -277,8 +273,6 @@ static int octeon_cpu_disable(void)
flush_cache_all();
local_flush_tlb_all();
spin_unlock(&smp_reserve_lock);
return 0;
}

View File

@ -8,5 +8,3 @@ lib-y += cmdline.o env.o file.o identify.o init.o \
lib-$(CONFIG_ARC_MEMORY) += memory.o
lib-$(CONFIG_ARC_CONSOLE) += arc_con.o
lib-$(CONFIG_ARC_PROMLIB) += promlib.o
ccflags-y := -Werror

View File

@ -0,0 +1,25 @@
/*
* based on arch/arm/include/asm/clkdev.h
*
* Copyright (C) 2008 Russell King.
*
* 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.
*
* Helper for the clk API to assist looking up a struct clk.
*/
#ifndef __ASM_CLKDEV_H
#define __ASM_CLKDEV_H
#include <linux/slab.h>
#define __clk_get(clk) ({ 1; })
#define __clk_put(clk) do { } while (0)
static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
{
return kzalloc(size, GFP_KERNEL);
}
#endif

View File

@ -1,10 +1,11 @@
/*
* Atheros AR71XX/AR724X/AR913X SoC register definitions
*
* Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
* Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
*
* Parts of this file are based on Atheros' 2.6.15 BSP
* Parts of this file are based on Atheros' 2.6.15/2.6.31 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
@ -60,6 +61,9 @@
#define AR933X_EHCI_BASE 0x1b000000
#define AR933X_EHCI_SIZE 0x1000
#define AR934X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000)
#define AR934X_WMAC_SIZE 0x20000
/*
* DDR_CTRL block
*/
@ -91,6 +95,12 @@
#define AR933X_DDR_REG_FLUSH_USB 0x84
#define AR933X_DDR_REG_FLUSH_WMAC 0x88
#define AR934X_DDR_REG_FLUSH_GE0 0x9c
#define AR934X_DDR_REG_FLUSH_GE1 0xa0
#define AR934X_DDR_REG_FLUSH_USB 0xa4
#define AR934X_DDR_REG_FLUSH_PCIE 0xa8
#define AR934X_DDR_REG_FLUSH_WMAC 0xac
/*
* PLL block
*/
@ -150,6 +160,41 @@
#define AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT 15
#define AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK 0x7
#define AR934X_PLL_CPU_CONFIG_REG 0x00
#define AR934X_PLL_DDR_CONFIG_REG 0x04
#define AR934X_PLL_CPU_DDR_CLK_CTRL_REG 0x08
#define AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT 0
#define AR934X_PLL_CPU_CONFIG_NFRAC_MASK 0x3f
#define AR934X_PLL_CPU_CONFIG_NINT_SHIFT 6
#define AR934X_PLL_CPU_CONFIG_NINT_MASK 0x3f
#define AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT 12
#define AR934X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f
#define AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19
#define AR934X_PLL_CPU_CONFIG_OUTDIV_MASK 0x3
#define AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT 0
#define AR934X_PLL_DDR_CONFIG_NFRAC_MASK 0x3ff
#define AR934X_PLL_DDR_CONFIG_NINT_SHIFT 10
#define AR934X_PLL_DDR_CONFIG_NINT_MASK 0x3f
#define AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT 16
#define AR934X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f
#define AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23
#define AR934X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7
#define AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS BIT(2)
#define AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS BIT(3)
#define AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS BIT(4)
#define AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT 5
#define AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK 0x1f
#define AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT 10
#define AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK 0x1f
#define AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT 15
#define AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK 0x1f
#define AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL BIT(20)
#define AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL BIT(21)
#define AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24)
/*
* USB_CONFIG block
*/
@ -185,6 +230,10 @@
#define AR933X_RESET_REG_RESET_MODULE 0x1c
#define AR933X_RESET_REG_BOOTSTRAP 0xac
#define AR934X_RESET_REG_RESET_MODULE 0x1c
#define AR934X_RESET_REG_BOOTSTRAP 0xb0
#define AR934X_RESET_REG_PCIE_WMAC_INT_STATUS 0xac
#define MISC_INT_ETHSW BIT(12)
#define MISC_INT_TIMER4 BIT(10)
#define MISC_INT_TIMER3 BIT(9)
@ -241,6 +290,40 @@
#define AR933X_BOOTSTRAP_REF_CLK_40 BIT(0)
#define AR934X_BOOTSTRAP_SW_OPTION8 BIT(23)
#define AR934X_BOOTSTRAP_SW_OPTION7 BIT(22)
#define AR934X_BOOTSTRAP_SW_OPTION6 BIT(21)
#define AR934X_BOOTSTRAP_SW_OPTION5 BIT(20)
#define AR934X_BOOTSTRAP_SW_OPTION4 BIT(19)
#define AR934X_BOOTSTRAP_SW_OPTION3 BIT(18)
#define AR934X_BOOTSTRAP_SW_OPTION2 BIT(17)
#define AR934X_BOOTSTRAP_SW_OPTION1 BIT(16)
#define AR934X_BOOTSTRAP_USB_MODE_DEVICE BIT(7)
#define AR934X_BOOTSTRAP_PCIE_RC BIT(6)
#define AR934X_BOOTSTRAP_EJTAG_MODE BIT(5)
#define AR934X_BOOTSTRAP_REF_CLK_40 BIT(4)
#define AR934X_BOOTSTRAP_BOOT_FROM_SPI BIT(2)
#define AR934X_BOOTSTRAP_SDRAM_DISABLED BIT(1)
#define AR934X_BOOTSTRAP_DDR1 BIT(0)
#define AR934X_PCIE_WMAC_INT_WMAC_MISC BIT(0)
#define AR934X_PCIE_WMAC_INT_WMAC_TX BIT(1)
#define AR934X_PCIE_WMAC_INT_WMAC_RXLP BIT(2)
#define AR934X_PCIE_WMAC_INT_WMAC_RXHP BIT(3)
#define AR934X_PCIE_WMAC_INT_PCIE_RC BIT(4)
#define AR934X_PCIE_WMAC_INT_PCIE_RC0 BIT(5)
#define AR934X_PCIE_WMAC_INT_PCIE_RC1 BIT(6)
#define AR934X_PCIE_WMAC_INT_PCIE_RC2 BIT(7)
#define AR934X_PCIE_WMAC_INT_PCIE_RC3 BIT(8)
#define AR934X_PCIE_WMAC_INT_WMAC_ALL \
(AR934X_PCIE_WMAC_INT_WMAC_MISC | AR934X_PCIE_WMAC_INT_WMAC_TX | \
AR934X_PCIE_WMAC_INT_WMAC_RXLP | AR934X_PCIE_WMAC_INT_WMAC_RXHP)
#define AR934X_PCIE_WMAC_INT_PCIE_ALL \
(AR934X_PCIE_WMAC_INT_PCIE_RC | AR934X_PCIE_WMAC_INT_PCIE_RC0 | \
AR934X_PCIE_WMAC_INT_PCIE_RC1 | AR934X_PCIE_WMAC_INT_PCIE_RC2 | \
AR934X_PCIE_WMAC_INT_PCIE_RC3)
#define REV_ID_MAJOR_MASK 0xfff0
#define REV_ID_MAJOR_AR71XX 0x00a0
#define REV_ID_MAJOR_AR913X 0x00b0
@ -249,6 +332,9 @@
#define REV_ID_MAJOR_AR7242 0x1100
#define REV_ID_MAJOR_AR9330 0x0110
#define REV_ID_MAJOR_AR9331 0x1110
#define REV_ID_MAJOR_AR9341 0x0120
#define REV_ID_MAJOR_AR9342 0x1120
#define REV_ID_MAJOR_AR9344 0x2120
#define AR71XX_REV_ID_MINOR_MASK 0x3
#define AR71XX_REV_ID_MINOR_AR7130 0x0
@ -267,6 +353,8 @@
#define AR724X_REV_ID_REVISION_MASK 0x3
#define AR934X_REV_ID_REVISION_MASK 0xf
/*
* SPI block
*/
@ -308,5 +396,6 @@
#define AR724X_GPIO_COUNT 18
#define AR913X_GPIO_COUNT 22
#define AR933X_GPIO_COUNT 30
#define AR934X_GPIO_COUNT 23
#endif /* __ASM_MACH_AR71XX_REGS_H */

View File

@ -29,6 +29,9 @@ enum ath79_soc_type {
ATH79_SOC_AR9132,
ATH79_SOC_AR9330,
ATH79_SOC_AR9331,
ATH79_SOC_AR9341,
ATH79_SOC_AR9342,
ATH79_SOC_AR9344,
};
extern enum ath79_soc_type ath79_soc;
@ -75,6 +78,26 @@ static inline int soc_is_ar933x(void)
ath79_soc == ATH79_SOC_AR9331);
}
static inline int soc_is_ar9341(void)
{
return (ath79_soc == ATH79_SOC_AR9341);
}
static inline int soc_is_ar9342(void)
{
return (ath79_soc == ATH79_SOC_AR9342);
}
static inline int soc_is_ar9344(void)
{
return (ath79_soc == ATH79_SOC_AR9344);
}
static inline int soc_is_ar934x(void)
{
return soc_is_ar9341() || soc_is_ar9342() || soc_is_ar9344();
}
extern void __iomem *ath79_ddr_base;
extern void __iomem *ath79_pll_base;
extern void __iomem *ath79_reset_base;

View File

@ -10,11 +10,19 @@
#define __ASM_MACH_ATH79_IRQ_H
#define MIPS_CPU_IRQ_BASE 0
#define NR_IRQS 40
#define NR_IRQS 48
#define ATH79_MISC_IRQ_BASE 8
#define ATH79_MISC_IRQ_COUNT 32
#define ATH79_PCI_IRQ_BASE (ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT)
#define ATH79_PCI_IRQ_COUNT 6
#define ATH79_PCI_IRQ(_x) (ATH79_PCI_IRQ_BASE + (_x))
#define ATH79_IP2_IRQ_BASE (ATH79_PCI_IRQ_BASE + ATH79_PCI_IRQ_COUNT)
#define ATH79_IP2_IRQ_COUNT 2
#define ATH79_IP2_IRQ(_x) (ATH79_IP2_IRQ_BASE + (_x))
#define ATH79_CPU_IRQ_IP2 (MIPS_CPU_IRQ_BASE + 2)
#define ATH79_CPU_IRQ_USB (MIPS_CPU_IRQ_BASE + 3)
#define ATH79_CPU_IRQ_GE0 (MIPS_CPU_IRQ_BASE + 4)

View File

@ -1,21 +0,0 @@
/*
* Atheros 724x PCI support
*
* Copyright (C) 2011 René Bolldorf <xsecute@googlemail.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.
*/
#ifndef __ASM_MACH_ATH79_PCI_ATH724X_H
#define __ASM_MACH_ATH79_PCI_ATH724X_H
struct ath724x_pci_data {
int irq;
void *pdata;
};
void ath724x_pci_add_data(struct ath724x_pci_data *data, int size);
#endif /* __ASM_MACH_ATH79_PCI_ATH724X_H */

View File

@ -0,0 +1,28 @@
/*
* Atheros AR71XX/AR724X PCI support
*
* Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
* Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2008 Imre Kaloz <kaloz@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 __ASM_MACH_ATH79_PCI_H
#define __ASM_MACH_ATH79_PCI_H
#if defined(CONFIG_PCI) && defined(CONFIG_SOC_AR71XX)
int ar71xx_pcibios_init(void);
#else
static inline int ar71xx_pcibios_init(void) { return 0; }
#endif
#if defined(CONFIG_PCI_AR724X)
int ar724x_pcibios_init(int irq);
#else
static inline int ar724x_pcibios_init(int irq) { return 0; }
#endif
#endif /* __ASM_MACH_ATH79_PCI_H */

View File

@ -0,0 +1,23 @@
/*
* 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.
*
* Copyright (C) 2010 Thomas Langer <thomas.langer@lantiq.com>
*/
#ifndef _FALCON_IRQ__
#define _FALCON_IRQ__
#define INT_NUM_IRQ0 8
#define INT_NUM_IM0_IRL0 (INT_NUM_IRQ0 + 0)
#define INT_NUM_IM1_IRL0 (INT_NUM_IM0_IRL0 + 32)
#define INT_NUM_IM2_IRL0 (INT_NUM_IM1_IRL0 + 32)
#define INT_NUM_IM3_IRL0 (INT_NUM_IM2_IRL0 + 32)
#define INT_NUM_IM4_IRL0 (INT_NUM_IM3_IRL0 + 32)
#define INT_NUM_EXTRA_START (INT_NUM_IM4_IRL0 + 32)
#define INT_NUM_IM_OFFSET (INT_NUM_IM1_IRL0 - INT_NUM_IM0_IRL0)
#define MIPS_CPU_TIMER_IRQ 7
#endif /* _FALCON_IRQ__ */

View File

@ -0,0 +1,18 @@
/*
* 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.
*
* Copyright (C) 2011 Thomas Langer <thomas.langer@lantiq.com>
*/
#ifndef __FALCON_IRQ_H
#define __FALCON_IRQ_H
#include <falcon_irq.h>
#define NR_IRQS 328
#include_next <irq.h>
#endif

View File

@ -0,0 +1,67 @@
/*
* 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.
*
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
*/
#ifndef _LTQ_FALCON_H__
#define _LTQ_FALCON_H__
#ifdef CONFIG_SOC_FALCON
#include <linux/pinctrl/pinctrl.h>
#include <lantiq.h>
/* Chip IDs */
#define SOC_ID_FALCON 0x01B8
/* SoC Types */
#define SOC_TYPE_FALCON 0x01
/*
* during early_printk no ioremap possible at this early stage
* lets use KSEG1 instead
*/
#define LTQ_ASC0_BASE_ADDR 0x1E100C00
#define LTQ_EARLY_ASC KSEG1ADDR(LTQ_ASC0_BASE_ADDR)
/* WDT */
#define LTQ_RST_CAUSE_WDTRST 0x0002
/* CHIP ID */
#define LTQ_STATUS_BASE_ADDR 0x1E802000
#define FALCON_CHIPID ((u32 *)(KSEG1 + LTQ_STATUS_BASE_ADDR + 0x0c))
#define FALCON_CHIPTYPE ((u32 *)(KSEG1 + LTQ_STATUS_BASE_ADDR + 0x38))
#define FALCON_CHIPCONF ((u32 *)(KSEG1 + LTQ_STATUS_BASE_ADDR + 0x40))
/* SYSCTL - start/stop/restart/configure/... different parts of the Soc */
#define SYSCTL_SYS1 0
#define SYSCTL_SYSETH 1
#define SYSCTL_SYSGPE 2
/* BOOT_SEL - find what boot media we have */
#define BS_FLASH 0x1
#define BS_SPI 0x4
/* global register ranges */
extern __iomem void *ltq_ebu_membase;
extern __iomem void *ltq_sys1_membase;
#define ltq_ebu_w32(x, y) ltq_w32((x), ltq_ebu_membase + (y))
#define ltq_ebu_r32(x) ltq_r32(ltq_ebu_membase + (x))
#define ltq_sys1_w32(x, y) ltq_w32((x), ltq_sys1_membase + (y))
#define ltq_sys1_r32(x) ltq_r32(ltq_sys1_membase + (x))
#define ltq_sys1_w32_mask(clear, set, reg) \
ltq_sys1_w32((ltq_sys1_r32(reg) & ~(clear)) | (set), reg)
/*
* to keep the irq code generic we need to define this to 0 as falcon
* has no EIU/EBU
*/
#define LTQ_EBU_PCC_ISTAT 0
#endif /* CONFIG_SOC_FALCON */
#endif /* _LTQ_XWAY_H__ */

View File

@ -0,0 +1,16 @@
#ifndef __ASM_MIPS_MACH_LANTIQ_GPIO_H
#define __ASM_MIPS_MACH_LANTIQ_GPIO_H
static inline int gpio_to_irq(unsigned int gpio)
{
return -1;
}
#define gpio_get_value __gpio_get_value
#define gpio_set_value __gpio_set_value
#define gpio_cansleep __gpio_cansleep
#include <asm-generic/gpio.h>
#endif

View File

@ -9,6 +9,8 @@
#define _LANTIQ_H__
#include <linux/irq.h>
#include <linux/device.h>
#include <linux/clk.h>
/* generic reg access functions */
#define ltq_r32(reg) __raw_readl(reg)
@ -21,25 +23,9 @@
/* register access macros for EBU and CGU */
#define ltq_ebu_w32(x, y) ltq_w32((x), ltq_ebu_membase + (y))
#define ltq_ebu_r32(x) ltq_r32(ltq_ebu_membase + (x))
#define ltq_cgu_w32(x, y) ltq_w32((x), ltq_cgu_membase + (y))
#define ltq_cgu_r32(x) ltq_r32(ltq_cgu_membase + (x))
#define ltq_ebu_w32_mask(x, y, z) \
ltq_w32_mask(x, y, ltq_ebu_membase + (z))
extern __iomem void *ltq_ebu_membase;
extern __iomem void *ltq_cgu_membase;
extern unsigned int ltq_get_cpu_ver(void);
extern unsigned int ltq_get_soc_type(void);
/* clock speeds */
#define CLOCK_60M 60000000
#define CLOCK_83M 83333333
#define CLOCK_111M 111111111
#define CLOCK_133M 133333333
#define CLOCK_167M 166666667
#define CLOCK_200M 200000000
#define CLOCK_266M 266666666
#define CLOCK_333M 333333333
#define CLOCK_400M 400000000
/* spinlock all ebu i/o */
extern spinlock_t ebu_lock;
@ -49,15 +35,21 @@ extern void ltq_disable_irq(struct irq_data *data);
extern void ltq_mask_and_ack_irq(struct irq_data *data);
extern void ltq_enable_irq(struct irq_data *data);
/* clock handling */
extern int clk_activate(struct clk *clk);
extern void clk_deactivate(struct clk *clk);
extern struct clk *clk_get_cpu(void);
extern struct clk *clk_get_fpi(void);
extern struct clk *clk_get_io(void);
/* find out what bootsource we have */
extern unsigned char ltq_boot_select(void);
/* find out what caused the last cpu reset */
extern int ltq_reset_cause(void);
#define LTQ_RST_CAUSE_WDTRST 0x20
#define IOPORT_RESOURCE_START 0x10000000
#define IOPORT_RESOURCE_END 0xffffffff
#define IOMEM_RESOURCE_START 0x10000000
#define IOMEM_RESOURCE_END 0xffffffff
#define LTQ_FLASH_START 0x10000000
#define LTQ_FLASH_MAX 0x04000000
#endif

View File

@ -9,41 +9,8 @@
#ifndef _LANTIQ_PLATFORM_H__
#define _LANTIQ_PLATFORM_H__
#include <linux/mtd/partitions.h>
#include <linux/socket.h>
/* struct used to pass info to the pci core */
enum {
PCI_CLOCK_INT = 0,
PCI_CLOCK_EXT
};
#define PCI_EXIN0 0x0001
#define PCI_EXIN1 0x0002
#define PCI_EXIN2 0x0004
#define PCI_EXIN3 0x0008
#define PCI_EXIN4 0x0010
#define PCI_EXIN5 0x0020
#define PCI_EXIN_MAX 6
#define PCI_GNT1 0x0040
#define PCI_GNT2 0x0080
#define PCI_GNT3 0x0100
#define PCI_GNT4 0x0200
#define PCI_REQ1 0x0400
#define PCI_REQ2 0x0800
#define PCI_REQ3 0x1000
#define PCI_REQ4 0x2000
#define PCI_REQ_SHIFT 10
#define PCI_REQ_MASK 0xf
struct ltq_pci_data {
int clock;
int gpio;
int irq[16];
};
/* struct used to pass info to network drivers */
struct ltq_eth_data {
struct sockaddr mac;

View File

@ -17,50 +17,8 @@
#define INT_NUM_IM4_IRL0 (INT_NUM_IRQ0 + 128)
#define INT_NUM_IM_OFFSET (INT_NUM_IM1_IRL0 - INT_NUM_IM0_IRL0)
#define LTQ_ASC_TIR(x) (INT_NUM_IM3_IRL0 + (x * 8))
#define LTQ_ASC_RIR(x) (INT_NUM_IM3_IRL0 + (x * 8) + 1)
#define LTQ_ASC_EIR(x) (INT_NUM_IM3_IRL0 + (x * 8) + 2)
#define LTQ_ASC_ASE_TIR INT_NUM_IM2_IRL0
#define LTQ_ASC_ASE_RIR (INT_NUM_IM2_IRL0 + 2)
#define LTQ_ASC_ASE_EIR (INT_NUM_IM2_IRL0 + 3)
#define LTQ_SSC_TIR (INT_NUM_IM0_IRL0 + 15)
#define LTQ_SSC_RIR (INT_NUM_IM0_IRL0 + 14)
#define LTQ_SSC_EIR (INT_NUM_IM0_IRL0 + 16)
#define LTQ_MEI_DYING_GASP_INT (INT_NUM_IM1_IRL0 + 21)
#define LTQ_MEI_INT (INT_NUM_IM1_IRL0 + 23)
#define LTQ_TIMER6_INT (INT_NUM_IM1_IRL0 + 23)
#define LTQ_USB_INT (INT_NUM_IM1_IRL0 + 22)
#define LTQ_USB_OC_INT (INT_NUM_IM4_IRL0 + 23)
#define MIPS_CPU_TIMER_IRQ 7
#define LTQ_DMA_CH0_INT (INT_NUM_IM2_IRL0)
#define LTQ_DMA_CH1_INT (INT_NUM_IM2_IRL0 + 1)
#define LTQ_DMA_CH2_INT (INT_NUM_IM2_IRL0 + 2)
#define LTQ_DMA_CH3_INT (INT_NUM_IM2_IRL0 + 3)
#define LTQ_DMA_CH4_INT (INT_NUM_IM2_IRL0 + 4)
#define LTQ_DMA_CH5_INT (INT_NUM_IM2_IRL0 + 5)
#define LTQ_DMA_CH6_INT (INT_NUM_IM2_IRL0 + 6)
#define LTQ_DMA_CH7_INT (INT_NUM_IM2_IRL0 + 7)
#define LTQ_DMA_CH8_INT (INT_NUM_IM2_IRL0 + 8)
#define LTQ_DMA_CH9_INT (INT_NUM_IM2_IRL0 + 9)
#define LTQ_DMA_CH10_INT (INT_NUM_IM2_IRL0 + 10)
#define LTQ_DMA_CH11_INT (INT_NUM_IM2_IRL0 + 11)
#define LTQ_DMA_CH12_INT (INT_NUM_IM2_IRL0 + 25)
#define LTQ_DMA_CH13_INT (INT_NUM_IM2_IRL0 + 26)
#define LTQ_DMA_CH14_INT (INT_NUM_IM2_IRL0 + 27)
#define LTQ_DMA_CH15_INT (INT_NUM_IM2_IRL0 + 28)
#define LTQ_DMA_CH16_INT (INT_NUM_IM2_IRL0 + 29)
#define LTQ_DMA_CH17_INT (INT_NUM_IM2_IRL0 + 30)
#define LTQ_DMA_CH18_INT (INT_NUM_IM2_IRL0 + 16)
#define LTQ_DMA_CH19_INT (INT_NUM_IM2_IRL0 + 21)
#define LTQ_PPE_MBOX_INT (INT_NUM_IM2_IRL0 + 24)
#define INT_NUM_IM4_IRL14 (INT_NUM_IM4_IRL0 + 14)
#define MIPS_CPU_TIMER_IRQ 7
#endif

View File

@ -17,38 +17,56 @@
#define SOC_ID_DANUBE1 0x129
#define SOC_ID_DANUBE2 0x12B
#define SOC_ID_TWINPASS 0x12D
#define SOC_ID_AMAZON_SE 0x152
#define SOC_ID_AMAZON_SE_1 0x152 /* 50601 */
#define SOC_ID_AMAZON_SE_2 0x153 /* 50600 */
#define SOC_ID_ARX188 0x16C
#define SOC_ID_ARX168 0x16D
#define SOC_ID_ARX168_1 0x16D
#define SOC_ID_ARX168_2 0x16E
#define SOC_ID_ARX182 0x16F
#define SOC_ID_GRX188 0x170
#define SOC_ID_GRX168 0x171
/* SoC Types */
#define SOC_ID_VRX288 0x1C0 /* v1.1 */
#define SOC_ID_VRX282 0x1C1 /* v1.1 */
#define SOC_ID_VRX268 0x1C2 /* v1.1 */
#define SOC_ID_GRX268 0x1C8 /* v1.1 */
#define SOC_ID_GRX288 0x1C9 /* v1.1 */
#define SOC_ID_VRX288_2 0x00B /* v1.2 */
#define SOC_ID_VRX268_2 0x00C /* v1.2 */
#define SOC_ID_GRX288_2 0x00D /* v1.2 */
#define SOC_ID_GRX282_2 0x00E /* v1.2 */
/* SoC Types */
#define SOC_TYPE_DANUBE 0x01
#define SOC_TYPE_TWINPASS 0x02
#define SOC_TYPE_AR9 0x03
#define SOC_TYPE_VR9 0x04
#define SOC_TYPE_AMAZON_SE 0x05
#define SOC_TYPE_VR9 0x04 /* v1.1 */
#define SOC_TYPE_VR9_2 0x05 /* v1.2 */
#define SOC_TYPE_AMAZON_SE 0x06
/* ASC0/1 - serial port */
#define LTQ_ASC0_BASE_ADDR 0x1E100400
/* BOOT_SEL - find what boot media we have */
#define BS_EXT_ROM 0x0
#define BS_FLASH 0x1
#define BS_MII0 0x2
#define BS_PCI 0x3
#define BS_UART1 0x4
#define BS_SPI 0x5
#define BS_NAND 0x6
#define BS_RMII0 0x7
/* helpers used to access the cgu */
#define ltq_cgu_w32(x, y) ltq_w32((x), ltq_cgu_membase + (y))
#define ltq_cgu_r32(x) ltq_r32(ltq_cgu_membase + (x))
extern __iomem void *ltq_cgu_membase;
/*
* during early_printk no ioremap is possible
* lets use KSEG1 instead
*/
#define LTQ_ASC1_BASE_ADDR 0x1E100C00
#define LTQ_ASC_SIZE 0x400
/* RCU - reset control unit */
#define LTQ_RCU_BASE_ADDR 0x1F203000
#define LTQ_RCU_SIZE 0x1000
/* GPTU - general purpose timer unit */
#define LTQ_GPTU_BASE_ADDR 0x18000300
#define LTQ_GPTU_SIZE 0x100
#define LTQ_EARLY_ASC KSEG1ADDR(LTQ_ASC1_BASE_ADDR)
/* EBU - external bus unit */
#define LTQ_EBU_GPIO_START 0x14000000
#define LTQ_EBU_GPIO_SIZE 0x1000
#define LTQ_EBU_BASE_ADDR 0x1E105300
#define LTQ_EBU_SIZE 0x100
#define LTQ_EBU_BUSCON0 0x0060
#define LTQ_EBU_PCC_CON 0x0090
#define LTQ_EBU_PCC_IEN 0x00A4
@ -57,85 +75,17 @@
#define LTQ_EBU_ADDRSEL1 0x0024
#define EBU_WRDIS 0x80000000
/* CGU - clock generation unit */
#define LTQ_CGU_BASE_ADDR 0x1F103000
#define LTQ_CGU_SIZE 0x1000
/* ICU - interrupt control unit */
#define LTQ_ICU_BASE_ADDR 0x1F880200
#define LTQ_ICU_SIZE 0x100
/* EIU - external interrupt unit */
#define LTQ_EIU_BASE_ADDR 0x1F101000
#define LTQ_EIU_SIZE 0x1000
/* PMU - power management unit */
#define LTQ_PMU_BASE_ADDR 0x1F102000
#define LTQ_PMU_SIZE 0x1000
#define PMU_DMA 0x0020
#define PMU_USB 0x8041
#define PMU_LED 0x0800
#define PMU_GPT 0x1000
#define PMU_PPE 0x2000
#define PMU_FPI 0x4000
#define PMU_SWITCH 0x10000000
/* ETOP - ethernet */
#define LTQ_ETOP_BASE_ADDR 0x1E180000
#define LTQ_ETOP_SIZE 0x40000
/* DMA */
#define LTQ_DMA_BASE_ADDR 0x1E104100
#define LTQ_DMA_SIZE 0x800
/* PCI */
#define PCI_CR_BASE_ADDR 0x1E105400
#define PCI_CR_SIZE 0x400
/* WDT */
#define LTQ_WDT_BASE_ADDR 0x1F8803F0
#define LTQ_WDT_SIZE 0x10
/* STP - serial to parallel conversion unit */
#define LTQ_STP_BASE_ADDR 0x1E100BB0
#define LTQ_STP_SIZE 0x40
/* GPIO */
#define LTQ_GPIO0_BASE_ADDR 0x1E100B10
#define LTQ_GPIO1_BASE_ADDR 0x1E100B40
#define LTQ_GPIO2_BASE_ADDR 0x1E100B70
#define LTQ_GPIO_SIZE 0x30
/* SSC */
#define LTQ_SSC_BASE_ADDR 0x1e100800
#define LTQ_SSC_SIZE 0x100
/* MEI - dsl core */
#define LTQ_MEI_BASE_ADDR 0x1E116000
/* DEU - data encryption unit */
#define LTQ_DEU_BASE_ADDR 0x1E103100
#define LTQ_RST_CAUSE_WDTRST 0x20
/* MPS - multi processor unit (voice) */
#define LTQ_MPS_BASE_ADDR (KSEG1 + 0x1F107000)
#define LTQ_MPS_CHIPID ((u32 *)(LTQ_MPS_BASE_ADDR + 0x0344))
/* request a non-gpio and set the PIO config */
extern int ltq_gpio_request(unsigned int pin, unsigned int alt0,
unsigned int alt1, unsigned int dir, const char *name);
#define PMU_PPE BIT(13)
extern void ltq_pmu_enable(unsigned int module);
extern void ltq_pmu_disable(unsigned int module);
static inline int ltq_is_ar9(void)
{
return (ltq_get_soc_type() == SOC_TYPE_AR9);
}
static inline int ltq_is_vr9(void)
{
return (ltq_get_soc_type() == SOC_TYPE_VR9);
}
#endif /* CONFIG_SOC_TYPE_XWAY */
#endif /* _LTQ_XWAY_H__ */

View File

@ -93,8 +93,4 @@ extern void mips_pcibios_init(void);
#define mips_pcibios_init() do { } while (0)
#endif
#ifdef CONFIG_KGDB
extern void kgdb_config(void);
#endif
#endif /* __ASM_MIPS_BOARDS_GENERIC_H */

View File

@ -2,6 +2,7 @@
#define _ASM_MODULE_H
#include <linux/list.h>
#include <linux/elf.h>
#include <asm/uaccess.h>
struct mod_arch_specific {

View File

@ -17,6 +17,7 @@
*/
#include <linux/ioport.h>
#include <linux/of.h>
/*
* Each pci channel is a top-level PCI bus seem by CPU. A machine with
@ -26,6 +27,7 @@
struct pci_controller {
struct pci_controller *next;
struct pci_bus *bus;
struct device_node *of_node;
struct pci_ops *pci_ops;
struct resource *mem_resource;
@ -142,4 +144,8 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
extern char * (*pcibios_plat_setup)(char *str);
/* this function parses memory ranges from a device node */
extern void __devinit pci_load_of_ranges(struct pci_controller *hose,
struct device_node *node);
#endif /* _ASM_PCI_H */

View File

@ -12,6 +12,9 @@
#define __ASM_PROM_H
#ifdef CONFIG_OF
#include <linux/bug.h>
#include <linux/io.h>
#include <linux/types.h>
#include <asm/bootinfo.h>
extern int early_init_dt_scan_memory_arch(unsigned long node,
@ -21,6 +24,29 @@ extern int reserve_mem_mach(unsigned long addr, unsigned long size);
extern void free_mem_mach(unsigned long addr, unsigned long size);
extern void device_tree_init(void);
static inline unsigned long pci_address_to_pio(phys_addr_t address)
{
/*
* The ioport address can be directly used by inX() / outX()
*/
BUG_ON(address > IO_SPACE_LIMIT);
return (unsigned long) address;
}
#define pci_address_to_pio pci_address_to_pio
struct boot_param_header;
extern void __dt_setup_arch(struct boot_param_header *bph);
#define dt_setup_arch(sym) \
({ \
extern struct boot_param_header __dtb_##sym##_begin; \
\
__dt_setup_arch(&__dtb_##sym##_begin); \
})
#else /* CONFIG_OF */
static inline void device_tree_init(void) { }
#endif /* CONFIG_OF */

View File

@ -14,7 +14,8 @@ extern void *set_vi_handler(int n, vi_handler_t addr);
extern void *set_except_vector(int n, void *addr);
extern unsigned long ebase;
extern void per_cpu_trap_init(void);
extern void per_cpu_trap_init(bool);
extern void cpu_cache_init(void);
#endif /* __KERNEL__ */

View File

@ -60,7 +60,7 @@ struct termio {
};
#ifdef __KERNEL__
#include <linux/module.h>
#include <asm/uaccess.h>
/*
* intr=^C quit=^\ erase=del kill=^U

View File

@ -25,6 +25,7 @@ extern void (*board_nmi_handler_setup)(void);
extern void (*board_ejtag_handler_setup)(void);
extern void (*board_bind_eic_interrupt)(int irq, int regset);
extern void (*board_ebase_setup)(void);
extern void (*board_cache_error_setup)(void);
extern int register_nmi_notifier(struct notifier_block *nb);

View File

@ -11,7 +11,7 @@
#include <linux/types.h>
#ifdef CONFIG_EXPORT_UASM
#include <linux/module.h>
#include <linux/export.h>
#define __uasminit
#define __uasminitdata
#define UASM_EXPORT_SYMBOL(sym) EXPORT_SYMBOL(sym)

View File

@ -16,5 +16,3 @@ obj-$(CONFIG_JZ4740_QI_LB60) += board-qi_lb60.o
# PM support
obj-$(CONFIG_PM) += pm.o
ccflags-y := -Werror -Wall

View File

@ -340,7 +340,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "R2000";
c->isa_level = MIPS_CPU_ISA_I;
c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
MIPS_CPU_NOFPUEX;
MIPS_CPU_NOFPUEX;
if (__cpu_has_fpu())
c->options |= MIPS_CPU_FPU;
c->tlbsize = 64;
@ -361,7 +361,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
}
c->isa_level = MIPS_CPU_ISA_I;
c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
MIPS_CPU_NOFPUEX;
MIPS_CPU_NOFPUEX;
if (__cpu_has_fpu())
c->options |= MIPS_CPU_FPU;
c->tlbsize = 64;
@ -387,8 +387,8 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
c->isa_level = MIPS_CPU_ISA_III;
c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_WATCH | MIPS_CPU_VCE |
MIPS_CPU_LLSC;
MIPS_CPU_WATCH | MIPS_CPU_VCE |
MIPS_CPU_LLSC;
c->tlbsize = 48;
break;
case PRID_IMP_VR41XX:
@ -434,7 +434,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "R4300";
c->isa_level = MIPS_CPU_ISA_III;
c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_LLSC;
MIPS_CPU_LLSC;
c->tlbsize = 32;
break;
case PRID_IMP_R4600:
@ -446,7 +446,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
c->tlbsize = 48;
break;
#if 0
case PRID_IMP_R4650:
case PRID_IMP_R4650:
/*
* This processor doesn't have an MMU, so it's not
* "real easy" to run Linux on it. It is left purely
@ -455,9 +455,9 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
*/
c->cputype = CPU_R4650;
__cpu_name[cpu] = "R4650";
c->isa_level = MIPS_CPU_ISA_III;
c->isa_level = MIPS_CPU_ISA_III;
c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC;
c->tlbsize = 48;
c->tlbsize = 48;
break;
#endif
case PRID_IMP_TX39:
@ -488,7 +488,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "R4700";
c->isa_level = MIPS_CPU_ISA_III;
c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_LLSC;
MIPS_CPU_LLSC;
c->tlbsize = 48;
break;
case PRID_IMP_TX49:
@ -505,7 +505,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "R5000";
c->isa_level = MIPS_CPU_ISA_IV;
c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_LLSC;
MIPS_CPU_LLSC;
c->tlbsize = 48;
break;
case PRID_IMP_R5432:
@ -513,7 +513,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "R5432";
c->isa_level = MIPS_CPU_ISA_IV;
c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_WATCH | MIPS_CPU_LLSC;
MIPS_CPU_WATCH | MIPS_CPU_LLSC;
c->tlbsize = 48;
break;
case PRID_IMP_R5500:
@ -521,7 +521,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "R5500";
c->isa_level = MIPS_CPU_ISA_IV;
c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_WATCH | MIPS_CPU_LLSC;
MIPS_CPU_WATCH | MIPS_CPU_LLSC;
c->tlbsize = 48;
break;
case PRID_IMP_NEVADA:
@ -529,7 +529,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "Nevada";
c->isa_level = MIPS_CPU_ISA_IV;
c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_DIVEC | MIPS_CPU_LLSC;
MIPS_CPU_DIVEC | MIPS_CPU_LLSC;
c->tlbsize = 48;
break;
case PRID_IMP_R6000:
@ -537,7 +537,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "R6000";
c->isa_level = MIPS_CPU_ISA_II;
c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
MIPS_CPU_LLSC;
MIPS_CPU_LLSC;
c->tlbsize = 32;
break;
case PRID_IMP_R6000A:
@ -545,7 +545,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "R6000A";
c->isa_level = MIPS_CPU_ISA_II;
c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
MIPS_CPU_LLSC;
MIPS_CPU_LLSC;
c->tlbsize = 32;
break;
case PRID_IMP_RM7000:
@ -553,7 +553,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "RM7000";
c->isa_level = MIPS_CPU_ISA_IV;
c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_LLSC;
MIPS_CPU_LLSC;
/*
* Undocumented RM7000: Bit 29 in the info register of
* the RM7000 v2.0 indicates if the TLB has 48 or 64
@ -569,7 +569,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "RM9000";
c->isa_level = MIPS_CPU_ISA_IV;
c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_LLSC;
MIPS_CPU_LLSC;
/*
* Bit 29 in the info register of the RM9000
* indicates if the TLB has 48 or 64 entries.
@ -584,8 +584,8 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "RM8000";
c->isa_level = MIPS_CPU_ISA_IV;
c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_LLSC;
MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_LLSC;
c->tlbsize = 384; /* has weird TLB: 3-way x 128 */
break;
case PRID_IMP_R10000:
@ -593,9 +593,9 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "R10000";
c->isa_level = MIPS_CPU_ISA_IV;
c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
MIPS_CPU_LLSC;
MIPS_CPU_LLSC;
c->tlbsize = 64;
break;
case PRID_IMP_R12000:
@ -603,9 +603,9 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "R12000";
c->isa_level = MIPS_CPU_ISA_IV;
c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
MIPS_CPU_LLSC;
MIPS_CPU_LLSC;
c->tlbsize = 64;
break;
case PRID_IMP_R14000:
@ -613,9 +613,9 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "R14000";
c->isa_level = MIPS_CPU_ISA_IV;
c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_FPU | MIPS_CPU_32FPR |
MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
MIPS_CPU_LLSC;
MIPS_CPU_LLSC;
c->tlbsize = 64;
break;
case PRID_IMP_LOONGSON2:
@ -739,7 +739,7 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
if (config3 & MIPS_CONF3_VEIC)
c->options |= MIPS_CPU_VEIC;
if (config3 & MIPS_CONF3_MT)
c->ases |= MIPS_ASE_MIPSMT;
c->ases |= MIPS_ASE_MIPSMT;
if (config3 & MIPS_CONF3_ULRI)
c->options |= MIPS_CPU_ULRI;
@ -767,7 +767,7 @@ static void __cpuinit decode_configs(struct cpuinfo_mips *c)
/* MIPS32 or MIPS64 compliant CPU. */
c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER |
MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK;
MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK;
c->scache.flags = MIPS_CACHE_NOT_PRESENT;

View File

@ -1532,7 +1532,8 @@ init_hw_perf_events(void)
irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR;
} else {
#endif
if (cp0_perfcount_irq >= 0)
if ((cp0_perfcount_irq >= 0) &&
(cp0_compare_irq != cp0_perfcount_irq))
irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
else
irq = -1;

View File

@ -41,27 +41,27 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "processor\t\t: %ld\n", n);
sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n",
cpu_data[n].options & MIPS_CPU_FPU ? " FPU V%d.%d" : "");
cpu_data[n].options & MIPS_CPU_FPU ? " FPU V%d.%d" : "");
seq_printf(m, fmt, __cpu_name[n],
(version >> 4) & 0x0f, version & 0x0f,
(fp_vers >> 4) & 0x0f, fp_vers & 0x0f);
(version >> 4) & 0x0f, version & 0x0f,
(fp_vers >> 4) & 0x0f, fp_vers & 0x0f);
seq_printf(m, "BogoMIPS\t\t: %u.%02u\n",
cpu_data[n].udelay_val / (500000/HZ),
(cpu_data[n].udelay_val / (5000/HZ)) % 100);
cpu_data[n].udelay_val / (500000/HZ),
(cpu_data[n].udelay_val / (5000/HZ)) % 100);
seq_printf(m, "wait instruction\t: %s\n", cpu_wait ? "yes" : "no");
seq_printf(m, "microsecond timers\t: %s\n",
cpu_has_counter ? "yes" : "no");
cpu_has_counter ? "yes" : "no");
seq_printf(m, "tlb_entries\t\t: %d\n", cpu_data[n].tlbsize);
seq_printf(m, "extra interrupt vector\t: %s\n",
cpu_has_divec ? "yes" : "no");
cpu_has_divec ? "yes" : "no");
seq_printf(m, "hardware watchpoint\t: %s",
cpu_has_watch ? "yes, " : "no\n");
cpu_has_watch ? "yes, " : "no\n");
if (cpu_has_watch) {
seq_printf(m, "count: %d, address/irw mask: [",
cpu_data[n].watch_reg_count);
cpu_data[n].watch_reg_count);
for (i = 0; i < cpu_data[n].watch_reg_count; i++)
seq_printf(m, "%s0x%04x", i ? ", " : "" ,
cpu_data[n].watch_reg_masks[i]);
cpu_data[n].watch_reg_masks[i]);
seq_printf(m, "]\n");
}
seq_printf(m, "ASEs implemented\t:%s%s%s%s%s%s\n",
@ -73,13 +73,13 @@ static int show_cpuinfo(struct seq_file *m, void *v)
cpu_has_mipsmt ? " mt" : ""
);
seq_printf(m, "shadow register sets\t: %d\n",
cpu_data[n].srsets);
cpu_data[n].srsets);
seq_printf(m, "kscratch registers\t: %d\n",
hweight8(cpu_data[n].kscratch_mask));
hweight8(cpu_data[n].kscratch_mask));
seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core);
sprintf(fmt, "VCE%%c exceptions\t\t: %s\n",
cpu_has_vce ? "%u" : "not available");
cpu_has_vce ? "%u" : "not available");
seq_printf(m, fmt, 'D', vced_count);
seq_printf(m, fmt, 'I', vcei_count);
seq_printf(m, "\n");

View File

@ -95,3 +95,16 @@ void __init device_tree_init(void)
/* free the space reserved for the dt blob */
free_mem_mach(base, size);
}
void __init __dt_setup_arch(struct boot_param_header *bph)
{
if (be32_to_cpu(bph->magic) != OF_DT_HEADER) {
pr_err("DTB has bad magic, ignoring builtin OF DTB\n");
return;
}
initial_boot_params = bph;
early_init_devtree(initial_boot_params);
}

View File

@ -605,6 +605,8 @@ void __init setup_arch(char **cmdline_p)
resource_init();
plat_smp_setup();
cpu_cache_init();
}
unsigned long kernelsp[NR_CPUS];

View File

@ -106,7 +106,7 @@ asmlinkage __cpuinit void start_secondary(void)
#endif /* CONFIG_MIPS_MT_SMTC */
cpu_probe();
cpu_report();
per_cpu_trap_init();
per_cpu_trap_init(false);
mips_clockevent_init();
mp_ops->init_secondary();

View File

@ -15,6 +15,7 @@
#include <linux/compiler.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/smp.h>
@ -91,7 +92,7 @@ void (*board_nmi_handler_setup)(void);
void (*board_ejtag_handler_setup)(void);
void (*board_bind_eic_interrupt)(int irq, int regset);
void (*board_ebase_setup)(void);
void __cpuinitdata(*board_cache_error_setup)(void);
static void show_raw_backtrace(unsigned long reg29)
{
@ -1490,7 +1491,6 @@ void *set_vi_handler(int n, vi_handler_t addr)
return set_vi_srs_handler(n, addr, 0);
}
extern void cpu_cache_init(void);
extern void tlb_init(void);
extern void flush_tlb_handlers(void);
@ -1517,7 +1517,7 @@ static int __init ulri_disable(char *s)
}
__setup("noulri", ulri_disable);
void __cpuinit per_cpu_trap_init(void)
void __cpuinit per_cpu_trap_init(bool is_boot_cpu)
{
unsigned int cpu = smp_processor_id();
unsigned int status_set = ST0_CU0;
@ -1616,7 +1616,9 @@ void __cpuinit per_cpu_trap_init(void)
#ifdef CONFIG_MIPS_MT_SMTC
if (bootTC) {
#endif /* CONFIG_MIPS_MT_SMTC */
cpu_cache_init();
/* Boot CPU's cache setup in setup_arch(). */
if (!is_boot_cpu)
cpu_cache_init();
tlb_init();
#ifdef CONFIG_MIPS_MT_SMTC
} else if (!secondaryTC) {
@ -1632,7 +1634,7 @@ void __cpuinit per_cpu_trap_init(void)
}
/* Install CPU exception handler */
void __init set_handler(unsigned long offset, void *addr, unsigned long size)
void __cpuinit set_handler(unsigned long offset, void *addr, unsigned long size)
{
memcpy((void *)(ebase + offset), addr, size);
local_flush_icache_range(ebase + offset, ebase + offset + size);
@ -1693,7 +1695,7 @@ void __init trap_init(void)
if (board_ebase_setup)
board_ebase_setup();
per_cpu_trap_init();
per_cpu_trap_init(true);
/*
* Copy the generic exception handlers to their final destination.
@ -1797,6 +1799,9 @@ void __init trap_init(void)
set_except_vector(26, handle_dsp);
if (board_cache_error_setup)
board_cache_error_setup();
if (cpu_has_vce)
/* Special exception: R4[04]00 uses also the divec space. */
memcpy((void *)(ebase + 0x180), &except_vec3_r4000, 0x100);

View File

@ -16,8 +16,22 @@ config SOC_XWAY
bool "XWAY"
select SOC_TYPE_XWAY
select HW_HAS_PCI
config SOC_FALCON
bool "FALCON"
endchoice
source "arch/mips/lantiq/xway/Kconfig"
choice
prompt "Devicetree"
config DT_EASY50712
bool "Easy50712"
depends on SOC_XWAY
endchoice
config PCI_LANTIQ
bool "PCI Support"
depends on SOC_XWAY && PCI
endif

View File

@ -4,8 +4,11 @@
# under the terms of the GNU General Public License version 2 as published
# by the Free Software Foundation.
obj-y := irq.o setup.o clk.o prom.o devices.o
obj-y := irq.o clk.o prom.o
obj-y += dts/
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_SOC_TYPE_XWAY) += xway/
obj-$(CONFIG_SOC_FALCON) += falcon/

View File

@ -6,3 +6,4 @@ platform-$(CONFIG_LANTIQ) += lantiq/
cflags-$(CONFIG_LANTIQ) += -I$(srctree)/arch/mips/include/asm/mach-lantiq
load-$(CONFIG_LANTIQ) = 0xffffffff80002000
cflags-$(CONFIG_SOC_TYPE_XWAY) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/xway
cflags-$(CONFIG_SOC_FALCON) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/falcon

View File

@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/err.h>
#include <linux/list.h>
@ -22,44 +23,32 @@
#include <lantiq_soc.h>
#include "clk.h"
struct clk {
const char *name;
unsigned long rate;
unsigned long (*get_rate) (void);
};
static struct clk *cpu_clk;
static int cpu_clk_cnt;
#include "prom.h"
/* lantiq socs have 3 static clocks */
static struct clk cpu_clk_generic[] = {
{
.name = "cpu",
.get_rate = ltq_get_cpu_hz,
}, {
.name = "fpi",
.get_rate = ltq_get_fpi_hz,
}, {
.name = "io",
.get_rate = ltq_get_io_region_clock,
},
};
static struct clk cpu_clk_generic[3];
static struct resource ltq_cgu_resource = {
.name = "cgu",
.start = LTQ_CGU_BASE_ADDR,
.end = LTQ_CGU_BASE_ADDR + LTQ_CGU_SIZE - 1,
.flags = IORESOURCE_MEM,
};
/* remapped clock register range */
void __iomem *ltq_cgu_membase;
void clk_init(void)
void clkdev_add_static(unsigned long cpu, unsigned long fpi, unsigned long io)
{
cpu_clk = cpu_clk_generic;
cpu_clk_cnt = ARRAY_SIZE(cpu_clk_generic);
cpu_clk_generic[0].rate = cpu;
cpu_clk_generic[1].rate = fpi;
cpu_clk_generic[2].rate = io;
}
struct clk *clk_get_cpu(void)
{
return &cpu_clk_generic[0];
}
struct clk *clk_get_fpi(void)
{
return &cpu_clk_generic[1];
}
EXPORT_SYMBOL_GPL(clk_get_fpi);
struct clk *clk_get_io(void)
{
return &cpu_clk_generic[2];
}
static inline int clk_good(struct clk *clk)
@ -82,38 +71,71 @@ unsigned long clk_get_rate(struct clk *clk)
}
EXPORT_SYMBOL(clk_get_rate);
struct clk *clk_get(struct device *dev, const char *id)
int clk_set_rate(struct clk *clk, unsigned long rate)
{
int i;
if (unlikely(!clk_good(clk)))
return 0;
if (clk->rates && *clk->rates) {
unsigned long *r = clk->rates;
for (i = 0; i < cpu_clk_cnt; i++)
if (!strcmp(id, cpu_clk[i].name))
return &cpu_clk[i];
BUG();
return ERR_PTR(-ENOENT);
while (*r && (*r != rate))
r++;
if (!*r) {
pr_err("clk %s.%s: trying to set invalid rate %ld\n",
clk->cl.dev_id, clk->cl.con_id, rate);
return -1;
}
}
clk->rate = rate;
return 0;
}
EXPORT_SYMBOL(clk_get);
void clk_put(struct clk *clk)
{
/* not used */
}
EXPORT_SYMBOL(clk_put);
EXPORT_SYMBOL(clk_set_rate);
int clk_enable(struct clk *clk)
{
/* not used */
return 0;
if (unlikely(!clk_good(clk)))
return -1;
if (clk->enable)
return clk->enable(clk);
return -1;
}
EXPORT_SYMBOL(clk_enable);
void clk_disable(struct clk *clk)
{
/* not used */
if (unlikely(!clk_good(clk)))
return;
if (clk->disable)
clk->disable(clk);
}
EXPORT_SYMBOL(clk_disable);
static inline u32 ltq_get_counter_resolution(void)
int clk_activate(struct clk *clk)
{
if (unlikely(!clk_good(clk)))
return -1;
if (clk->activate)
return clk->activate(clk);
return -1;
}
EXPORT_SYMBOL(clk_activate);
void clk_deactivate(struct clk *clk)
{
if (unlikely(!clk_good(clk)))
return;
if (clk->deactivate)
clk->deactivate(clk);
}
EXPORT_SYMBOL(clk_deactivate);
static inline u32 get_counter_resolution(void)
{
u32 res;
@ -133,21 +155,11 @@ void __init plat_time_init(void)
{
struct clk *clk;
if (insert_resource(&iomem_resource, &ltq_cgu_resource) < 0)
panic("Failed to insert cgu memory");
ltq_soc_init();
if (request_mem_region(ltq_cgu_resource.start,
resource_size(&ltq_cgu_resource), "cgu") < 0)
panic("Failed to request cgu memory");
ltq_cgu_membase = ioremap_nocache(ltq_cgu_resource.start,
resource_size(&ltq_cgu_resource));
if (!ltq_cgu_membase) {
pr_err("Failed to remap cgu memory\n");
unreachable();
}
clk = clk_get(0, "cpu");
mips_hpt_frequency = clk_get_rate(clk) / ltq_get_counter_resolution();
clk = clk_get_cpu();
mips_hpt_frequency = clk_get_rate(clk) / get_counter_resolution();
write_c0_compare(read_c0_count());
pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
clk_put(clk);
}

View File

@ -9,10 +9,70 @@
#ifndef _LTQ_CLK_H__
#define _LTQ_CLK_H__
extern void clk_init(void);
#include <linux/clkdev.h>
extern unsigned long ltq_get_cpu_hz(void);
extern unsigned long ltq_get_fpi_hz(void);
extern unsigned long ltq_get_io_region_clock(void);
/* clock speeds */
#define CLOCK_33M 33333333
#define CLOCK_60M 60000000
#define CLOCK_62_5M 62500000
#define CLOCK_83M 83333333
#define CLOCK_83_5M 83500000
#define CLOCK_98_304M 98304000
#define CLOCK_100M 100000000
#define CLOCK_111M 111111111
#define CLOCK_125M 125000000
#define CLOCK_133M 133333333
#define CLOCK_150M 150000000
#define CLOCK_166M 166666666
#define CLOCK_167M 166666667
#define CLOCK_196_608M 196608000
#define CLOCK_200M 200000000
#define CLOCK_250M 250000000
#define CLOCK_266M 266666666
#define CLOCK_300M 300000000
#define CLOCK_333M 333333333
#define CLOCK_393M 393215332
#define CLOCK_400M 400000000
#define CLOCK_500M 500000000
#define CLOCK_600M 600000000
/* clock out speeds */
#define CLOCK_32_768K 32768
#define CLOCK_1_536M 1536000
#define CLOCK_2_5M 2500000
#define CLOCK_12M 12000000
#define CLOCK_24M 24000000
#define CLOCK_25M 25000000
#define CLOCK_30M 30000000
#define CLOCK_40M 40000000
#define CLOCK_48M 48000000
#define CLOCK_50M 50000000
#define CLOCK_60M 60000000
struct clk {
struct clk_lookup cl;
unsigned long rate;
unsigned long *rates;
unsigned int module;
unsigned int bits;
unsigned long (*get_rate) (void);
int (*enable) (struct clk *clk);
void (*disable) (struct clk *clk);
int (*activate) (struct clk *clk);
void (*deactivate) (struct clk *clk);
void (*reboot) (struct clk *clk);
};
extern void clkdev_add_static(unsigned long cpu, unsigned long fpi,
unsigned long io);
extern unsigned long ltq_danube_cpu_hz(void);
extern unsigned long ltq_danube_fpi_hz(void);
extern unsigned long ltq_ar9_cpu_hz(void);
extern unsigned long ltq_ar9_fpi_hz(void);
extern unsigned long ltq_vr9_cpu_hz(void);
extern unsigned long ltq_vr9_fpi_hz(void);
#endif

View File

@ -1,120 +0,0 @@
/*
* 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.
*
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
*/
#include <linux/init.h>
#include <linux/export.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/reboot.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/etherdevice.h>
#include <linux/time.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <asm/bootinfo.h>
#include <asm/irq.h>
#include <lantiq_soc.h>
#include "devices.h"
/* nor flash */
static struct resource ltq_nor_resource = {
.name = "nor",
.start = LTQ_FLASH_START,
.end = LTQ_FLASH_START + LTQ_FLASH_MAX - 1,
.flags = IORESOURCE_MEM,
};
static struct platform_device ltq_nor = {
.name = "ltq_nor",
.resource = &ltq_nor_resource,
.num_resources = 1,
};
void __init ltq_register_nor(struct physmap_flash_data *data)
{
ltq_nor.dev.platform_data = data;
platform_device_register(&ltq_nor);
}
/* watchdog */
static struct resource ltq_wdt_resource = {
.name = "watchdog",
.start = LTQ_WDT_BASE_ADDR,
.end = LTQ_WDT_BASE_ADDR + LTQ_WDT_SIZE - 1,
.flags = IORESOURCE_MEM,
};
void __init ltq_register_wdt(void)
{
platform_device_register_simple("ltq_wdt", 0, &ltq_wdt_resource, 1);
}
/* asc ports */
static struct resource ltq_asc0_resources[] = {
{
.name = "asc0",
.start = LTQ_ASC0_BASE_ADDR,
.end = LTQ_ASC0_BASE_ADDR + LTQ_ASC_SIZE - 1,
.flags = IORESOURCE_MEM,
},
IRQ_RES(tx, LTQ_ASC_TIR(0)),
IRQ_RES(rx, LTQ_ASC_RIR(0)),
IRQ_RES(err, LTQ_ASC_EIR(0)),
};
static struct resource ltq_asc1_resources[] = {
{
.name = "asc1",
.start = LTQ_ASC1_BASE_ADDR,
.end = LTQ_ASC1_BASE_ADDR + LTQ_ASC_SIZE - 1,
.flags = IORESOURCE_MEM,
},
IRQ_RES(tx, LTQ_ASC_TIR(1)),
IRQ_RES(rx, LTQ_ASC_RIR(1)),
IRQ_RES(err, LTQ_ASC_EIR(1)),
};
void __init ltq_register_asc(int port)
{
switch (port) {
case 0:
platform_device_register_simple("ltq_asc", 0,
ltq_asc0_resources, ARRAY_SIZE(ltq_asc0_resources));
break;
case 1:
platform_device_register_simple("ltq_asc", 1,
ltq_asc1_resources, ARRAY_SIZE(ltq_asc1_resources));
break;
default:
break;
}
}
#ifdef CONFIG_PCI
/* pci */
static struct platform_device ltq_pci = {
.name = "ltq_pci",
.num_resources = 0,
};
void __init ltq_register_pci(struct ltq_pci_data *data)
{
ltq_pci.dev.platform_data = data;
platform_device_register(&ltq_pci);
}
#else
void __init ltq_register_pci(struct ltq_pci_data *data)
{
pr_err("kernel is compiled without PCI support\n");
}
#endif

View File

@ -1,23 +0,0 @@
/*
* 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.
*
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
*/
#ifndef _LTQ_DEVICES_H__
#define _LTQ_DEVICES_H__
#include <lantiq_platform.h>
#include <linux/mtd/physmap.h>
#define IRQ_RES(resname, irq) \
{.name = #resname, .start = (irq), .flags = IORESOURCE_IRQ}
extern void ltq_register_nor(struct physmap_flash_data *data);
extern void ltq_register_wdt(void);
extern void ltq_register_asc(int port);
extern void ltq_register_pci(struct ltq_pci_data *data);
#endif

View File

@ -0,0 +1,4 @@
obj-$(CONFIG_DT_EASY50712) := easy50712.dtb.o
$(obj)/%.dtb: $(obj)/%.dts
$(call if_changed,dtc)

View File

@ -0,0 +1,105 @@
/ {
#address-cells = <1>;
#size-cells = <1>;
compatible = "lantiq,xway", "lantiq,danube";
cpus {
cpu@0 {
compatible = "mips,mips24Kc";
};
};
biu@1F800000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "lantiq,biu", "simple-bus";
reg = <0x1F800000 0x800000>;
ranges = <0x0 0x1F800000 0x7FFFFF>;
icu0: icu@80200 {
#interrupt-cells = <1>;
interrupt-controller;
compatible = "lantiq,icu";
reg = <0x80200 0x120>;
};
watchdog@803F0 {
compatible = "lantiq,wdt";
reg = <0x803F0 0x10>;
};
};
sram@1F000000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "lantiq,sram";
reg = <0x1F000000 0x800000>;
ranges = <0x0 0x1F000000 0x7FFFFF>;
eiu0: eiu@101000 {
#interrupt-cells = <1>;
interrupt-controller;
interrupt-parent;
compatible = "lantiq,eiu-xway";
reg = <0x101000 0x1000>;
};
pmu0: pmu@102000 {
compatible = "lantiq,pmu-xway";
reg = <0x102000 0x1000>;
};
cgu0: cgu@103000 {
compatible = "lantiq,cgu-xway";
reg = <0x103000 0x1000>;
#clock-cells = <1>;
};
rcu0: rcu@203000 {
compatible = "lantiq,rcu-xway";
reg = <0x203000 0x1000>;
};
};
fpi@10000000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "lantiq,fpi", "simple-bus";
ranges = <0x0 0x10000000 0xEEFFFFF>;
reg = <0x10000000 0xEF00000>;
gptu@E100A00 {
compatible = "lantiq,gptu-xway";
reg = <0xE100A00 0x100>;
};
serial@E100C00 {
compatible = "lantiq,asc";
reg = <0xE100C00 0x400>;
interrupt-parent = <&icu0>;
interrupts = <112 113 114>;
};
dma0: dma@E104100 {
compatible = "lantiq,dma-xway";
reg = <0xE104100 0x800>;
};
ebu0: ebu@E105300 {
compatible = "lantiq,ebu-xway";
reg = <0xE105300 0x100>;
};
pci0: pci@E105400 {
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
compatible = "lantiq,pci-xway";
bus-range = <0x0 0x0>;
ranges = <0x2000000 0 0x8000000 0x8000000 0 0x2000000 /* pci memory */
0x1000000 0 0x00000000 0xAE00000 0 0x200000>; /* io space */
reg = <0x7000000 0x8000 /* config space */
0xE105400 0x400>; /* pci bridge */
};
};
};

View File

@ -0,0 +1,113 @@
/dts-v1/;
/include/ "danube.dtsi"
/ {
chosen {
bootargs = "console=ttyLTQ0,115200 init=/etc/preinit";
};
memory@0 {
reg = <0x0 0x2000000>;
};
fpi@10000000 {
#address-cells = <1>;
#size-cells = <1>;
localbus@0 {
#address-cells = <2>;
#size-cells = <1>;
ranges = <0 0 0x0 0x3ffffff /* addrsel0 */
1 0 0x4000000 0x4000010>; /* addsel1 */
compatible = "lantiq,localbus", "simple-bus";
nor-boot@0 {
compatible = "lantiq,nor";
bank-width = <2>;
reg = <0 0x0 0x2000000>;
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "uboot";
reg = <0x00000 0x10000>; /* 64 KB */
};
partition@10000 {
label = "uboot_env";
reg = <0x10000 0x10000>; /* 64 KB */
};
partition@20000 {
label = "linux";
reg = <0x20000 0x3d0000>;
};
partition@400000 {
label = "rootfs";
reg = <0x400000 0x400000>;
};
};
};
gpio: pinmux@E100B10 {
compatible = "lantiq,pinctrl-xway";
pinctrl-names = "default";
pinctrl-0 = <&state_default>;
#gpio-cells = <2>;
gpio-controller;
reg = <0xE100B10 0xA0>;
state_default: pinmux {
stp {
lantiq,groups = "stp";
lantiq,function = "stp";
};
exin {
lantiq,groups = "exin1";
lantiq,function = "exin";
};
pci {
lantiq,groups = "gnt1";
lantiq,function = "pci";
};
conf_out {
lantiq,pins = "io4", "io5", "io6"; /* stp */
lantiq,open-drain;
lantiq,pull = <0>;
};
};
};
etop@E180000 {
compatible = "lantiq,etop-xway";
reg = <0xE180000 0x40000>;
interrupt-parent = <&icu0>;
interrupts = <73 78>;
phy-mode = "rmii";
mac-address = [ 00 11 22 33 44 55 ];
};
stp0: stp@E100BB0 {
#gpio-cells = <2>;
compatible = "lantiq,gpio-stp-xway";
gpio-controller;
reg = <0xE100BB0 0x40>;
lantiq,shadow = <0xfff>;
lantiq,groups = <0x3>;
};
pci@E105400 {
lantiq,bus-clock = <33333333>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
0x7000 0 0 1 &icu0 29 1 // slot 14, irq 29
>;
gpios-reset = <&gpio 21 0>;
req-mask = <0x1>; /* GNT1 */
};
};
};

View File

@ -6,17 +6,16 @@
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
*/
#include <linux/init.h>
#include <linux/cpu.h>
#include <lantiq.h>
#include <lantiq_soc.h>
/* no ioremap possible at this early stage, lets use KSEG1 instead */
#define LTQ_ASC_BASE KSEG1ADDR(LTQ_ASC1_BASE_ADDR)
#define ASC_BUF 1024
#define LTQ_ASC_FSTAT ((u32 *)(LTQ_ASC_BASE + 0x0048))
#define LTQ_ASC_TBUF ((u32 *)(LTQ_ASC_BASE + 0x0020))
#define LTQ_ASC_FSTAT ((u32 *)(LTQ_EARLY_ASC + 0x0048))
#ifdef __BIG_ENDIAN
#define LTQ_ASC_TBUF ((u32 *)(LTQ_EARLY_ASC + 0x0020 + 3))
#else
#define LTQ_ASC_TBUF ((u32 *)(LTQ_EARLY_ASC + 0x0020))
#endif
#define TXMASK 0x3F00
#define TXOFFSET 8
@ -27,7 +26,7 @@ void prom_putchar(char c)
local_irq_save(flags);
do { } while ((ltq_r32(LTQ_ASC_FSTAT) & TXMASK) >> TXOFFSET);
if (c == '\n')
ltq_w32('\r', LTQ_ASC_TBUF);
ltq_w32(c, LTQ_ASC_TBUF);
ltq_w8('\r', LTQ_ASC_TBUF);
ltq_w8(c, LTQ_ASC_TBUF);
local_irq_restore(flags);
}

View File

@ -0,0 +1 @@
obj-y := prom.o reset.o sysctrl.o

View File

@ -0,0 +1,87 @@
/*
* 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.
*
* Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com>
* Copyright (C) 2012 John Crispin <blogic@openwrt.org>
*/
#include <linux/kernel.h>
#include <asm/io.h>
#include <lantiq_soc.h>
#include "../prom.h"
#define SOC_FALCON "Falcon"
#define SOC_FALCON_D "Falcon-D"
#define SOC_FALCON_V "Falcon-V"
#define SOC_FALCON_M "Falcon-M"
#define COMP_FALCON "lantiq,falcon"
#define PART_SHIFT 12
#define PART_MASK 0x0FFFF000
#define REV_SHIFT 28
#define REV_MASK 0xF0000000
#define SREV_SHIFT 22
#define SREV_MASK 0x03C00000
#define TYPE_SHIFT 26
#define TYPE_MASK 0x3C000000
/* reset, nmi and ejtag exception vectors */
#define BOOT_REG_BASE (KSEG1 | 0x1F200000)
#define BOOT_RVEC (BOOT_REG_BASE | 0x00)
#define BOOT_NVEC (BOOT_REG_BASE | 0x04)
#define BOOT_EVEC (BOOT_REG_BASE | 0x08)
void __init ltq_soc_nmi_setup(void)
{
extern void (*nmi_handler)(void);
ltq_w32((unsigned long)&nmi_handler, (void *)BOOT_NVEC);
}
void __init ltq_soc_ejtag_setup(void)
{
extern void (*ejtag_debug_handler)(void);
ltq_w32((unsigned long)&ejtag_debug_handler, (void *)BOOT_EVEC);
}
void __init ltq_soc_detect(struct ltq_soc_info *i)
{
u32 type;
i->partnum = (ltq_r32(FALCON_CHIPID) & PART_MASK) >> PART_SHIFT;
i->rev = (ltq_r32(FALCON_CHIPID) & REV_MASK) >> REV_SHIFT;
i->srev = ((ltq_r32(FALCON_CHIPCONF) & SREV_MASK) >> SREV_SHIFT);
i->compatible = COMP_FALCON;
i->type = SOC_TYPE_FALCON;
sprintf(i->rev_type, "%c%d%d", (i->srev & 0x4) ? ('B') : ('A'),
i->rev & 0x7, (i->srev & 0x3) + 1);
switch (i->partnum) {
case SOC_ID_FALCON:
type = (ltq_r32(FALCON_CHIPTYPE) & TYPE_MASK) >> TYPE_SHIFT;
switch (type) {
case 0:
i->name = SOC_FALCON_D;
break;
case 1:
i->name = SOC_FALCON_V;
break;
case 2:
i->name = SOC_FALCON_M;
break;
default:
i->name = SOC_FALCON;
break;
}
break;
default:
unreachable();
break;
}
}

View File

@ -0,0 +1,90 @@
/*
* 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.
*
* Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com>
* Copyright (C) 2012 John Crispin <blogic@openwrt.org>
*/
#include <linux/init.h>
#include <linux/io.h>
#include <linux/pm.h>
#include <asm/reboot.h>
#include <linux/export.h>
#include <lantiq_soc.h>
/* CPU0 Reset Source Register */
#define SYS1_CPU0RS 0x0040
/* reset cause mask */
#define CPU0RS_MASK 0x0003
/* CPU0 Boot Mode Register */
#define SYS1_BM 0x00a0
/* boot mode mask */
#define BM_MASK 0x0005
/* allow platform code to find out what surce we booted from */
unsigned char ltq_boot_select(void)
{
return ltq_sys1_r32(SYS1_BM) & BM_MASK;
}
/* allow the watchdog driver to find out what the boot reason was */
int ltq_reset_cause(void)
{
return ltq_sys1_r32(SYS1_CPU0RS) & CPU0RS_MASK;
}
EXPORT_SYMBOL_GPL(ltq_reset_cause);
#define BOOT_REG_BASE (KSEG1 | 0x1F200000)
#define BOOT_PW1_REG (BOOT_REG_BASE | 0x20)
#define BOOT_PW2_REG (BOOT_REG_BASE | 0x24)
#define BOOT_PW1 0x4C545100
#define BOOT_PW2 0x0051544C
#define WDT_REG_BASE (KSEG1 | 0x1F8803F0)
#define WDT_PW1 0x00BE0000
#define WDT_PW2 0x00DC0000
static void machine_restart(char *command)
{
local_irq_disable();
/* reboot magic */
ltq_w32(BOOT_PW1, (void *)BOOT_PW1_REG); /* 'LTQ\0' */
ltq_w32(BOOT_PW2, (void *)BOOT_PW2_REG); /* '\0QTL' */
ltq_w32(0, (void *)BOOT_REG_BASE); /* reset Bootreg RVEC */
/* watchdog magic */
ltq_w32(WDT_PW1, (void *)WDT_REG_BASE);
ltq_w32(WDT_PW2 |
(0x3 << 26) | /* PWL */
(0x2 << 24) | /* CLKDIV */
(0x1 << 31) | /* enable */
(1), /* reload */
(void *)WDT_REG_BASE);
unreachable();
}
static void machine_halt(void)
{
local_irq_disable();
unreachable();
}
static void machine_power_off(void)
{
local_irq_disable();
unreachable();
}
static int __init mips_reboot_setup(void)
{
_machine_restart = machine_restart;
_machine_halt = machine_halt;
pm_power_off = machine_power_off;
return 0;
}
arch_initcall(mips_reboot_setup);

View File

@ -0,0 +1,260 @@
/*
* 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.
*
* Copyright (C) 2011 Thomas Langer <thomas.langer@lantiq.com>
* Copyright (C) 2011 John Crispin <blogic@openwrt.org>
*/
#include <linux/ioport.h>
#include <linux/export.h>
#include <linux/clkdev.h>
#include <linux/of_address.h>
#include <asm/delay.h>
#include <lantiq_soc.h>
#include "../clk.h"
/* infrastructure control register */
#define SYS1_INFRAC 0x00bc
/* Configuration fuses for drivers and pll */
#define STATUS_CONFIG 0x0040
/* GPE frequency selection */
#define GPPC_OFFSET 24
#define GPEFREQ_MASK 0x00000C0
#define GPEFREQ_OFFSET 10
/* Clock status register */
#define SYSCTL_CLKS 0x0000
/* Clock enable register */
#define SYSCTL_CLKEN 0x0004
/* Clock clear register */
#define SYSCTL_CLKCLR 0x0008
/* Activation Status Register */
#define SYSCTL_ACTS 0x0020
/* Activation Register */
#define SYSCTL_ACT 0x0024
/* Deactivation Register */
#define SYSCTL_DEACT 0x0028
/* reboot Register */
#define SYSCTL_RBT 0x002c
/* CPU0 Clock Control Register */
#define SYS1_CPU0CC 0x0040
/* HRST_OUT_N Control Register */
#define SYS1_HRSTOUTC 0x00c0
/* clock divider bit */
#define CPU0CC_CPUDIV 0x0001
/* Activation Status Register */
#define ACTS_ASC1_ACT 0x00000800
#define ACTS_I2C_ACT 0x00004000
#define ACTS_P0 0x00010000
#define ACTS_P1 0x00010000
#define ACTS_P2 0x00020000
#define ACTS_P3 0x00020000
#define ACTS_P4 0x00040000
#define ACTS_PADCTRL0 0x00100000
#define ACTS_PADCTRL1 0x00100000
#define ACTS_PADCTRL2 0x00200000
#define ACTS_PADCTRL3 0x00200000
#define ACTS_PADCTRL4 0x00400000
#define sysctl_w32(m, x, y) ltq_w32((x), sysctl_membase[m] + (y))
#define sysctl_r32(m, x) ltq_r32(sysctl_membase[m] + (x))
#define sysctl_w32_mask(m, clear, set, reg) \
sysctl_w32(m, (sysctl_r32(m, reg) & ~(clear)) | (set), reg)
#define status_w32(x, y) ltq_w32((x), status_membase + (y))
#define status_r32(x) ltq_r32(status_membase + (x))
static void __iomem *sysctl_membase[3], *status_membase;
void __iomem *ltq_sys1_membase, *ltq_ebu_membase;
void falcon_trigger_hrst(int level)
{
sysctl_w32(SYSCTL_SYS1, level & 1, SYS1_HRSTOUTC);
}
static inline void sysctl_wait(struct clk *clk,
unsigned int test, unsigned int reg)
{
int err = 1000000;
do {} while (--err && ((sysctl_r32(clk->module, reg)
& clk->bits) != test));
if (!err)
pr_err("module de/activation failed %d %08X %08X %08X\n",
clk->module, clk->bits, test,
sysctl_r32(clk->module, reg) & clk->bits);
}
static int sysctl_activate(struct clk *clk)
{
sysctl_w32(clk->module, clk->bits, SYSCTL_CLKEN);
sysctl_w32(clk->module, clk->bits, SYSCTL_ACT);
sysctl_wait(clk, clk->bits, SYSCTL_ACTS);
return 0;
}
static void sysctl_deactivate(struct clk *clk)
{
sysctl_w32(clk->module, clk->bits, SYSCTL_CLKCLR);
sysctl_w32(clk->module, clk->bits, SYSCTL_DEACT);
sysctl_wait(clk, 0, SYSCTL_ACTS);
}
static int sysctl_clken(struct clk *clk)
{
sysctl_w32(clk->module, clk->bits, SYSCTL_CLKEN);
sysctl_wait(clk, clk->bits, SYSCTL_CLKS);
return 0;
}
static void sysctl_clkdis(struct clk *clk)
{
sysctl_w32(clk->module, clk->bits, SYSCTL_CLKCLR);
sysctl_wait(clk, 0, SYSCTL_CLKS);
}
static void sysctl_reboot(struct clk *clk)
{
unsigned int act;
unsigned int bits;
act = sysctl_r32(clk->module, SYSCTL_ACT);
bits = ~act & clk->bits;
if (bits != 0) {
sysctl_w32(clk->module, bits, SYSCTL_CLKEN);
sysctl_w32(clk->module, bits, SYSCTL_ACT);
sysctl_wait(clk, bits, SYSCTL_ACTS);
}
sysctl_w32(clk->module, act & clk->bits, SYSCTL_RBT);
sysctl_wait(clk, clk->bits, SYSCTL_ACTS);
}
/* enable the ONU core */
static void falcon_gpe_enable(void)
{
unsigned int freq;
unsigned int status;
/* if if the clock is already enabled */
status = sysctl_r32(SYSCTL_SYS1, SYS1_INFRAC);
if (status & (1 << (GPPC_OFFSET + 1)))
return;
if (status_r32(STATUS_CONFIG) == 0)
freq = 1; /* use 625MHz on unfused chip */
else
freq = (status_r32(STATUS_CONFIG) &
GPEFREQ_MASK) >>
GPEFREQ_OFFSET;
/* apply new frequency */
sysctl_w32_mask(SYSCTL_SYS1, 7 << (GPPC_OFFSET + 1),
freq << (GPPC_OFFSET + 2) , SYS1_INFRAC);
udelay(1);
/* enable new frequency */
sysctl_w32_mask(SYSCTL_SYS1, 0, 1 << (GPPC_OFFSET + 1), SYS1_INFRAC);
udelay(1);
}
static inline void clkdev_add_sys(const char *dev, unsigned int module,
unsigned int bits)
{
struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
clk->cl.dev_id = dev;
clk->cl.con_id = NULL;
clk->cl.clk = clk;
clk->module = module;
clk->activate = sysctl_activate;
clk->deactivate = sysctl_deactivate;
clk->enable = sysctl_clken;
clk->disable = sysctl_clkdis;
clk->reboot = sysctl_reboot;
clkdev_add(&clk->cl);
}
void __init ltq_soc_init(void)
{
struct device_node *np_status =
of_find_compatible_node(NULL, NULL, "lantiq,status-falcon");
struct device_node *np_ebu =
of_find_compatible_node(NULL, NULL, "lantiq,ebu-falcon");
struct device_node *np_sys1 =
of_find_compatible_node(NULL, NULL, "lantiq,sys1-falcon");
struct device_node *np_syseth =
of_find_compatible_node(NULL, NULL, "lantiq,syseth-falcon");
struct device_node *np_sysgpe =
of_find_compatible_node(NULL, NULL, "lantiq,sysgpe-falcon");
struct resource res_status, res_ebu, res_sys[3];
int i;
/* check if all the core register ranges are available */
if (!np_status || !np_ebu || !np_sys1 || !np_syseth || !np_sysgpe)
panic("Failed to load core nodes from devicetree");
if (of_address_to_resource(np_status, 0, &res_status) ||
of_address_to_resource(np_ebu, 0, &res_ebu) ||
of_address_to_resource(np_sys1, 0, &res_sys[0]) ||
of_address_to_resource(np_syseth, 0, &res_sys[1]) ||
of_address_to_resource(np_sysgpe, 0, &res_sys[2]))
panic("Failed to get core resources");
if ((request_mem_region(res_status.start, resource_size(&res_status),
res_status.name) < 0) ||
(request_mem_region(res_ebu.start, resource_size(&res_ebu),
res_ebu.name) < 0) ||
(request_mem_region(res_sys[0].start,
resource_size(&res_sys[0]),
res_sys[0].name) < 0) ||
(request_mem_region(res_sys[1].start,
resource_size(&res_sys[1]),
res_sys[1].name) < 0) ||
(request_mem_region(res_sys[2].start,
resource_size(&res_sys[2]),
res_sys[2].name) < 0))
pr_err("Failed to request core reources");
status_membase = ioremap_nocache(res_status.start,
resource_size(&res_status));
ltq_ebu_membase = ioremap_nocache(res_ebu.start,
resource_size(&res_ebu));
if (!status_membase || !ltq_ebu_membase)
panic("Failed to remap core resources");
for (i = 0; i < 3; i++) {
sysctl_membase[i] = ioremap_nocache(res_sys[i].start,
resource_size(&res_sys[i]));
if (!sysctl_membase[i])
panic("Failed to remap sysctrl resources");
}
ltq_sys1_membase = sysctl_membase[0];
falcon_gpe_enable();
/* get our 3 static rates for cpu, fpi and io clocks */
if (ltq_sys1_r32(SYS1_CPU0CC) & CPU0CC_CPUDIV)
clkdev_add_static(CLOCK_200M, CLOCK_100M, CLOCK_200M);
else
clkdev_add_static(CLOCK_400M, CLOCK_100M, CLOCK_200M);
/* add our clock domains */
clkdev_add_sys("1d810000.gpio", SYSCTL_SYSETH, ACTS_P0);
clkdev_add_sys("1d810100.gpio", SYSCTL_SYSETH, ACTS_P2);
clkdev_add_sys("1e800100.gpio", SYSCTL_SYS1, ACTS_P1);
clkdev_add_sys("1e800200.gpio", SYSCTL_SYS1, ACTS_P3);
clkdev_add_sys("1e800300.gpio", SYSCTL_SYS1, ACTS_P4);
clkdev_add_sys("1db01000.pad", SYSCTL_SYSETH, ACTS_PADCTRL0);
clkdev_add_sys("1db02000.pad", SYSCTL_SYSETH, ACTS_PADCTRL2);
clkdev_add_sys("1e800400.pad", SYSCTL_SYS1, ACTS_PADCTRL1);
clkdev_add_sys("1e800500.pad", SYSCTL_SYS1, ACTS_PADCTRL3);
clkdev_add_sys("1e800600.pad", SYSCTL_SYS1, ACTS_PADCTRL4);
clkdev_add_sys("1e100C00.serial", SYSCTL_SYS1, ACTS_ASC1_ACT);
clkdev_add_sys("1e200000.i2c", SYSCTL_SYS1, ACTS_I2C_ACT);
}

View File

@ -9,6 +9,11 @@
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/irqdomain.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <asm/bootinfo.h>
#include <asm/irq_cpu.h>
@ -16,7 +21,7 @@
#include <lantiq_soc.h>
#include <irq.h>
/* register definitions */
/* register definitions - internal irqs */
#define LTQ_ICU_IM0_ISR 0x0000
#define LTQ_ICU_IM0_IER 0x0008
#define LTQ_ICU_IM0_IOSR 0x0010
@ -25,6 +30,7 @@
#define LTQ_ICU_IM1_ISR 0x0028
#define LTQ_ICU_OFFSET (LTQ_ICU_IM1_ISR - LTQ_ICU_IM0_ISR)
/* register definitions - external irqs */
#define LTQ_EIU_EXIN_C 0x0000
#define LTQ_EIU_EXIN_INIC 0x0004
#define LTQ_EIU_EXIN_INEN 0x000C
@ -37,10 +43,14 @@
#define LTQ_EIU_IR4 (INT_NUM_IM1_IRL0 + 1)
#define LTQ_EIU_IR5 (INT_NUM_IM1_IRL0 + 2)
#define LTQ_EIU_IR6 (INT_NUM_IM2_IRL0 + 30)
#define XWAY_EXIN_COUNT 3
#define MAX_EIU 6
/* irqs generated by device attached to the EBU need to be acked in
/* the performance counter */
#define LTQ_PERF_IRQ (INT_NUM_IM4_IRL0 + 31)
/*
* irqs generated by devices attached to the EBU need to be acked in
* a special manner
*/
#define LTQ_ICU_EBU_IRQ 22
@ -51,6 +61,17 @@
#define ltq_eiu_w32(x, y) ltq_w32((x), ltq_eiu_membase + (y))
#define ltq_eiu_r32(x) ltq_r32(ltq_eiu_membase + (x))
/* our 2 ipi interrupts for VSMP */
#define MIPS_CPU_IPI_RESCHED_IRQ 0
#define MIPS_CPU_IPI_CALL_IRQ 1
/* we have a cascade of 8 irqs */
#define MIPS_CPU_IRQ_CASCADE 8
#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
int gic_present;
#endif
static unsigned short ltq_eiu_irq[MAX_EIU] = {
LTQ_EIU_IR0,
LTQ_EIU_IR1,
@ -60,64 +81,51 @@ static unsigned short ltq_eiu_irq[MAX_EIU] = {
LTQ_EIU_IR5,
};
static struct resource ltq_icu_resource = {
.name = "icu",
.start = LTQ_ICU_BASE_ADDR,
.end = LTQ_ICU_BASE_ADDR + LTQ_ICU_SIZE - 1,
.flags = IORESOURCE_MEM,
};
static struct resource ltq_eiu_resource = {
.name = "eiu",
.start = LTQ_EIU_BASE_ADDR,
.end = LTQ_EIU_BASE_ADDR + LTQ_ICU_SIZE - 1,
.flags = IORESOURCE_MEM,
};
static int exin_avail;
static void __iomem *ltq_icu_membase;
static void __iomem *ltq_eiu_membase;
void ltq_disable_irq(struct irq_data *d)
{
u32 ier = LTQ_ICU_IM0_IER;
int irq_nr = d->irq - INT_NUM_IRQ0;
int offset = d->hwirq - MIPS_CPU_IRQ_CASCADE;
ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
irq_nr %= INT_NUM_IM_OFFSET;
ltq_icu_w32(ltq_icu_r32(ier) & ~(1 << irq_nr), ier);
ier += LTQ_ICU_OFFSET * (offset / INT_NUM_IM_OFFSET);
offset %= INT_NUM_IM_OFFSET;
ltq_icu_w32(ltq_icu_r32(ier) & ~BIT(offset), ier);
}
void ltq_mask_and_ack_irq(struct irq_data *d)
{
u32 ier = LTQ_ICU_IM0_IER;
u32 isr = LTQ_ICU_IM0_ISR;
int irq_nr = d->irq - INT_NUM_IRQ0;
int offset = d->hwirq - MIPS_CPU_IRQ_CASCADE;
ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
isr += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
irq_nr %= INT_NUM_IM_OFFSET;
ltq_icu_w32(ltq_icu_r32(ier) & ~(1 << irq_nr), ier);
ltq_icu_w32((1 << irq_nr), isr);
ier += LTQ_ICU_OFFSET * (offset / INT_NUM_IM_OFFSET);
isr += LTQ_ICU_OFFSET * (offset / INT_NUM_IM_OFFSET);
offset %= INT_NUM_IM_OFFSET;
ltq_icu_w32(ltq_icu_r32(ier) & ~BIT(offset), ier);
ltq_icu_w32(BIT(offset), isr);
}
static void ltq_ack_irq(struct irq_data *d)
{
u32 isr = LTQ_ICU_IM0_ISR;
int irq_nr = d->irq - INT_NUM_IRQ0;
int offset = d->hwirq - MIPS_CPU_IRQ_CASCADE;
isr += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
irq_nr %= INT_NUM_IM_OFFSET;
ltq_icu_w32((1 << irq_nr), isr);
isr += LTQ_ICU_OFFSET * (offset / INT_NUM_IM_OFFSET);
offset %= INT_NUM_IM_OFFSET;
ltq_icu_w32(BIT(offset), isr);
}
void ltq_enable_irq(struct irq_data *d)
{
u32 ier = LTQ_ICU_IM0_IER;
int irq_nr = d->irq - INT_NUM_IRQ0;
int offset = d->hwirq - MIPS_CPU_IRQ_CASCADE;
ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
irq_nr %= INT_NUM_IM_OFFSET;
ltq_icu_w32(ltq_icu_r32(ier) | (1 << irq_nr), ier);
ier += LTQ_ICU_OFFSET * (offset / INT_NUM_IM_OFFSET);
offset %= INT_NUM_IM_OFFSET;
ltq_icu_w32(ltq_icu_r32(ier) | BIT(offset), ier);
}
static unsigned int ltq_startup_eiu_irq(struct irq_data *d)
@ -126,15 +134,15 @@ static unsigned int ltq_startup_eiu_irq(struct irq_data *d)
ltq_enable_irq(d);
for (i = 0; i < MAX_EIU; i++) {
if (d->irq == ltq_eiu_irq[i]) {
if (d->hwirq == ltq_eiu_irq[i]) {
/* low level - we should really handle set_type */
ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_C) |
(0x6 << (i * 4)), LTQ_EIU_EXIN_C);
/* clear all pending */
ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INIC) & ~(1 << i),
ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INIC) & ~BIT(i),
LTQ_EIU_EXIN_INIC);
/* enable */
ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) | (1 << i),
ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) | BIT(i),
LTQ_EIU_EXIN_INEN);
break;
}
@ -149,9 +157,9 @@ static void ltq_shutdown_eiu_irq(struct irq_data *d)
ltq_disable_irq(d);
for (i = 0; i < MAX_EIU; i++) {
if (d->irq == ltq_eiu_irq[i]) {
if (d->hwirq == ltq_eiu_irq[i]) {
/* disable */
ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) & ~(1 << i),
ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) & ~BIT(i),
LTQ_EIU_EXIN_INEN);
break;
}
@ -188,14 +196,15 @@ static void ltq_hw_irqdispatch(int module)
if (irq == 0)
return;
/* silicon bug causes only the msb set to 1 to be valid. all
/*
* silicon bug causes only the msb set to 1 to be valid. all
* other bits might be bogus
*/
irq = __fls(irq);
do_IRQ((int)irq + INT_NUM_IM0_IRL0 + (INT_NUM_IM_OFFSET * module));
do_IRQ((int)irq + MIPS_CPU_IRQ_CASCADE + (INT_NUM_IM_OFFSET * module));
/* if this is a EBU irq, we need to ack it or get a deadlock */
if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0))
if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0) && LTQ_EBU_PCC_ISTAT)
ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_ISTAT) | 0x10,
LTQ_EBU_PCC_ISTAT);
}
@ -216,6 +225,47 @@ static void ltq_hw5_irqdispatch(void)
do_IRQ(MIPS_CPU_TIMER_IRQ);
}
#ifdef CONFIG_MIPS_MT_SMP
void __init arch_init_ipiirq(int irq, struct irqaction *action)
{
setup_irq(irq, action);
irq_set_handler(irq, handle_percpu_irq);
}
static void ltq_sw0_irqdispatch(void)
{
do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ);
}
static void ltq_sw1_irqdispatch(void)
{
do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ);
}
static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
{
scheduler_ipi();
return IRQ_HANDLED;
}
static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
{
smp_call_function_interrupt();
return IRQ_HANDLED;
}
static struct irqaction irq_resched = {
.handler = ipi_resched_interrupt,
.flags = IRQF_PERCPU,
.name = "IPI_resched"
};
static struct irqaction irq_call = {
.handler = ipi_call_interrupt,
.flags = IRQF_PERCPU,
.name = "IPI_call"
};
#endif
asmlinkage void plat_irq_dispatch(void)
{
unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
@ -238,45 +288,75 @@ out:
return;
}
static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
{
struct irq_chip *chip = &ltq_irq_type;
int i;
for (i = 0; i < exin_avail; i++)
if (hw == ltq_eiu_irq[i])
chip = &ltq_eiu_type;
irq_set_chip_and_handler(hw, chip, handle_level_irq);
return 0;
}
static const struct irq_domain_ops irq_domain_ops = {
.xlate = irq_domain_xlate_onetwocell,
.map = icu_map,
};
static struct irqaction cascade = {
.handler = no_action,
.name = "cascade",
};
void __init arch_init_irq(void)
int __init icu_of_init(struct device_node *node, struct device_node *parent)
{
struct device_node *eiu_node;
struct resource res;
int i;
if (insert_resource(&iomem_resource, &ltq_icu_resource) < 0)
panic("Failed to insert icu memory");
if (of_address_to_resource(node, 0, &res))
panic("Failed to get icu memory range");
if (request_mem_region(ltq_icu_resource.start,
resource_size(&ltq_icu_resource), "icu") < 0)
panic("Failed to request icu memory");
if (request_mem_region(res.start, resource_size(&res), res.name) < 0)
pr_err("Failed to request icu memory");
ltq_icu_membase = ioremap_nocache(ltq_icu_resource.start,
resource_size(&ltq_icu_resource));
ltq_icu_membase = ioremap_nocache(res.start, resource_size(&res));
if (!ltq_icu_membase)
panic("Failed to remap icu memory");
if (insert_resource(&iomem_resource, &ltq_eiu_resource) < 0)
panic("Failed to insert eiu memory");
/* the external interrupts are optional and xway only */
eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu");
if (eiu_node && of_address_to_resource(eiu_node, 0, &res)) {
/* find out how many external irq sources we have */
const __be32 *count = of_get_property(node,
"lantiq,count", NULL);
if (request_mem_region(ltq_eiu_resource.start,
resource_size(&ltq_eiu_resource), "eiu") < 0)
panic("Failed to request eiu memory");
if (count)
exin_avail = *count;
if (exin_avail > MAX_EIU)
exin_avail = MAX_EIU;
ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start,
resource_size(&ltq_eiu_resource));
if (!ltq_eiu_membase)
panic("Failed to remap eiu memory");
if (request_mem_region(res.start, resource_size(&res),
res.name) < 0)
pr_err("Failed to request eiu memory");
/* make sure all irqs are turned off by default */
for (i = 0; i < 5; i++)
ltq_eiu_membase = ioremap_nocache(res.start,
resource_size(&res));
if (!ltq_eiu_membase)
panic("Failed to remap eiu memory");
}
/* turn off all irqs by default */
for (i = 0; i < 5; i++) {
/* make sure all irqs are turned off by default */
ltq_icu_w32(0, LTQ_ICU_IM0_IER + (i * LTQ_ICU_OFFSET));
/* clear all possibly pending interrupts */
ltq_icu_w32(~0, LTQ_ICU_IM0_ISR + (i * LTQ_ICU_OFFSET));
/* clear all possibly pending interrupts */
ltq_icu_w32(~0, LTQ_ICU_IM0_ISR + (i * LTQ_ICU_OFFSET));
}
mips_cpu_irq_init();
@ -293,20 +373,19 @@ void __init arch_init_irq(void)
set_vi_handler(7, ltq_hw5_irqdispatch);
}
for (i = INT_NUM_IRQ0;
i <= (INT_NUM_IRQ0 + (5 * INT_NUM_IM_OFFSET)); i++)
if ((i == LTQ_EIU_IR0) || (i == LTQ_EIU_IR1) ||
(i == LTQ_EIU_IR2))
irq_set_chip_and_handler(i, &ltq_eiu_type,
handle_level_irq);
/* EIU3-5 only exist on ar9 and vr9 */
else if (((i == LTQ_EIU_IR3) || (i == LTQ_EIU_IR4) ||
(i == LTQ_EIU_IR5)) && (ltq_is_ar9() || ltq_is_vr9()))
irq_set_chip_and_handler(i, &ltq_eiu_type,
handle_level_irq);
else
irq_set_chip_and_handler(i, &ltq_irq_type,
handle_level_irq);
irq_domain_add_linear(node, 6 * INT_NUM_IM_OFFSET,
&irq_domain_ops, 0);
#if defined(CONFIG_MIPS_MT_SMP)
if (cpu_has_vint) {
pr_info("Setting up IPI vectored interrupts\n");
set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ltq_sw0_irqdispatch);
set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ltq_sw1_irqdispatch);
}
arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ,
&irq_resched);
arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ, &irq_call);
#endif
#if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC)
set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 |
@ -315,9 +394,23 @@ void __init arch_init_irq(void)
set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ0 | IE_IRQ1 |
IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
#endif
/* tell oprofile which irq to use */
cp0_perfcount_irq = LTQ_PERF_IRQ;
return 0;
}
unsigned int __cpuinit get_c0_compare_int(void)
{
return CP0_LEGACY_COMPARE_IRQ;
}
static struct of_device_id __initdata of_irq_ids[] = {
{ .compatible = "lantiq,icu", .data = icu_of_init },
{},
};
void __init arch_init_irq(void)
{
of_irq_init(of_irq_ids);
}

View File

@ -1,20 +0,0 @@
/*
* 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.
*
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
*/
#ifndef _LANTIQ_MACH_H__
#define _LANTIQ_MACH_H__
#include <asm/mips_machine.h>
enum lantiq_mach_type {
LTQ_MACH_GENERIC = 0,
LTQ_MACH_EASY50712, /* Danube evaluation board */
LTQ_MACH_EASY50601, /* Amazon SE evaluation board */
};
#endif

View File

@ -8,6 +8,7 @@
#include <linux/export.h>
#include <linux/clk.h>
#include <linux/of_platform.h>
#include <asm/bootinfo.h>
#include <asm/time.h>
@ -16,20 +17,16 @@
#include "prom.h"
#include "clk.h"
/* access to the ebu needs to be locked between different drivers */
DEFINE_SPINLOCK(ebu_lock);
EXPORT_SYMBOL_GPL(ebu_lock);
/*
* this struct is filled by the soc specific detection code and holds
* information about the specific soc type, revision and name
*/
static struct ltq_soc_info soc_info;
unsigned int ltq_get_cpu_ver(void)
{
return soc_info.rev;
}
EXPORT_SYMBOL(ltq_get_cpu_ver);
unsigned int ltq_get_soc_type(void)
{
return soc_info.type;
}
EXPORT_SYMBOL(ltq_get_soc_type);
const char *get_system_type(void)
{
return soc_info.sys_type;
@ -45,27 +42,62 @@ static void __init prom_init_cmdline(void)
char **argv = (char **) KSEG1ADDR(fw_arg1);
int i;
for (i = 0; i < argc; i++) {
char *p = (char *) KSEG1ADDR(argv[i]);
arcs_cmdline[0] = '\0';
if (p && *p) {
for (i = 0; i < argc; i++) {
char *p = (char *) KSEG1ADDR(argv[i]);
if (CPHYSADDR(p) && *p) {
strlcat(arcs_cmdline, p, sizeof(arcs_cmdline));
strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
}
}
}
void __init plat_mem_setup(void)
{
ioport_resource.start = IOPORT_RESOURCE_START;
ioport_resource.end = IOPORT_RESOURCE_END;
iomem_resource.start = IOMEM_RESOURCE_START;
iomem_resource.end = IOMEM_RESOURCE_END;
set_io_port_base((unsigned long) KSEG1);
/*
* Load the builtin devicetree. This causes the chosen node to be
* parsed resulting in our memory appearing
*/
__dt_setup_arch(&__dtb_start);
}
void __init prom_init(void)
{
struct clk *clk;
/* call the soc specific detetcion code and get it to fill soc_info */
ltq_soc_detect(&soc_info);
clk_init();
clk = clk_get(0, "cpu");
snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev1.%d",
soc_info.name, soc_info.rev);
clk_put(clk);
snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev %s",
soc_info.name, soc_info.rev_type);
soc_info.sys_type[LTQ_SYS_TYPE_LEN - 1] = '\0';
pr_info("SoC: %s\n", soc_info.sys_type);
prom_init_cmdline();
#if defined(CONFIG_MIPS_MT_SMP)
if (register_vsmp_smp_ops())
panic("failed to register_vsmp_smp_ops()");
#endif
}
int __init plat_of_setup(void)
{
static struct of_device_id of_ids[3];
if (!of_have_populated_dt())
panic("device tree not present");
strncpy(of_ids[0].compatible, soc_info.compatible,
sizeof(of_ids[0].compatible));
strncpy(of_ids[1].compatible, "simple-bus",
sizeof(of_ids[1].compatible));
return of_platform_bus_probe(NULL, of_ids, NULL);
}
arch_initcall(plat_of_setup);

View File

@ -10,16 +10,22 @@
#define _LTQ_PROM_H__
#define LTQ_SYS_TYPE_LEN 0x100
#define LTQ_SYS_REV_LEN 0x10
struct ltq_soc_info {
unsigned char *name;
unsigned int rev;
unsigned char rev_type[LTQ_SYS_REV_LEN];
unsigned int srev;
unsigned int partnum;
unsigned int type;
unsigned char sys_type[LTQ_SYS_TYPE_LEN];
unsigned char *compatible;
};
extern void ltq_soc_detect(struct ltq_soc_info *i);
extern void ltq_soc_setup(void);
extern void ltq_soc_init(void);
extern struct boot_param_header __dtb_start;
#endif

View File

@ -1,66 +0,0 @@
/*
* 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.
*
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
*/
#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <asm/bootinfo.h>
#include <lantiq_soc.h>
#include "machtypes.h"
#include "devices.h"
#include "prom.h"
void __init plat_mem_setup(void)
{
/* assume 16M as default incase uboot fails to pass proper ramsize */
unsigned long memsize = 16;
char **envp = (char **) KSEG1ADDR(fw_arg2);
ioport_resource.start = IOPORT_RESOURCE_START;
ioport_resource.end = IOPORT_RESOURCE_END;
iomem_resource.start = IOMEM_RESOURCE_START;
iomem_resource.end = IOMEM_RESOURCE_END;
set_io_port_base((unsigned long) KSEG1);
while (*envp) {
char *e = (char *)KSEG1ADDR(*envp);
if (!strncmp(e, "memsize=", 8)) {
e += 8;
if (strict_strtoul(e, 0, &memsize))
pr_warn("bad memsize specified\n");
}
envp++;
}
memsize *= 1024 * 1024;
add_memory_region(0x00000000, memsize, BOOT_MEM_RAM);
}
static int __init
lantiq_setup(void)
{
ltq_soc_setup();
mips_machine_setup();
return 0;
}
arch_initcall(lantiq_setup);
static void __init
lantiq_generic_init(void)
{
/* Nothing to do */
}
MIPS_MACHINE(LTQ_MACH_GENERIC,
"Generic",
"Generic Lantiq based board",
lantiq_generic_init);

View File

@ -1,23 +0,0 @@
if SOC_XWAY
menu "MIPS Machine"
config LANTIQ_MACH_EASY50712
bool "Easy50712 - Danube"
default y
endmenu
endif
if SOC_AMAZON_SE
menu "MIPS Machine"
config LANTIQ_MACH_EASY50601
bool "Easy50601 - Amazon SE"
default y
endmenu
endif

View File

@ -1,7 +1 @@
obj-y := pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o
obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o setup-xway.o
obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o setup-ase.o
obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
obj-y := prom.o sysctrl.o clk.o reset.o gpio.o dma.o

View File

@ -1,48 +0,0 @@
/*
* 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.
*
* Copyright (C) 2011 John Crispin <blogic@openwrt.org>
*/
#include <linux/io.h>
#include <linux/export.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <asm/time.h>
#include <asm/irq.h>
#include <asm/div64.h>
#include <lantiq_soc.h>
/* cgu registers */
#define LTQ_CGU_SYS 0x0010
unsigned int ltq_get_io_region_clock(void)
{
return CLOCK_133M;
}
EXPORT_SYMBOL(ltq_get_io_region_clock);
unsigned int ltq_get_fpi_bus_clock(int fpi)
{
return CLOCK_133M;
}
EXPORT_SYMBOL(ltq_get_fpi_bus_clock);
unsigned int ltq_get_cpu_hz(void)
{
if (ltq_cgu_r32(LTQ_CGU_SYS) & (1 << 5))
return CLOCK_266M;
else
return CLOCK_133M;
}
EXPORT_SYMBOL(ltq_get_cpu_hz);
unsigned int ltq_get_fpi_hz(void)
{
return CLOCK_133M;
}
EXPORT_SYMBOL(ltq_get_fpi_hz);

View File

@ -1,223 +0,0 @@
/*
* 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.
*
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
*/
#include <linux/io.h>
#include <linux/export.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <asm/time.h>
#include <asm/irq.h>
#include <asm/div64.h>
#include <lantiq_soc.h>
static unsigned int ltq_ram_clocks[] = {
CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M };
#define DDR_HZ ltq_ram_clocks[ltq_cgu_r32(LTQ_CGU_SYS) & 0x3]
#define BASIC_FREQUENCY_1 35328000
#define BASIC_FREQUENCY_2 36000000
#define BASIS_REQUENCY_USB 12000000
#define GET_BITS(x, msb, lsb) \
(((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb))
#define LTQ_CGU_PLL0_CFG 0x0004
#define LTQ_CGU_PLL1_CFG 0x0008
#define LTQ_CGU_PLL2_CFG 0x000C
#define LTQ_CGU_SYS 0x0010
#define LTQ_CGU_UPDATE 0x0014
#define LTQ_CGU_IF_CLK 0x0018
#define LTQ_CGU_OSC_CON 0x001C
#define LTQ_CGU_SMD 0x0020
#define LTQ_CGU_CT1SR 0x0028
#define LTQ_CGU_CT2SR 0x002C
#define LTQ_CGU_PCMCR 0x0030
#define LTQ_CGU_PCI_CR 0x0034
#define LTQ_CGU_PD_PC 0x0038
#define LTQ_CGU_FMR 0x003C
#define CGU_PLL0_PHASE_DIVIDER_ENABLE \
(ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 31))
#define CGU_PLL0_BYPASS \
(ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 30))
#define CGU_PLL0_CFG_DSMSEL \
(ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 28))
#define CGU_PLL0_CFG_FRAC_EN \
(ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 27))
#define CGU_PLL1_SRC \
(ltq_cgu_r32(LTQ_CGU_PLL1_CFG) & (1 << 31))
#define CGU_PLL2_PHASE_DIVIDER_ENABLE \
(ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & (1 << 20))
#define CGU_SYS_FPI_SEL (1 << 6)
#define CGU_SYS_DDR_SEL 0x3
#define CGU_PLL0_SRC (1 << 29)
#define CGU_PLL0_CFG_PLLK GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 26, 17)
#define CGU_PLL0_CFG_PLLN GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 12, 6)
#define CGU_PLL0_CFG_PLLM GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 5, 2)
#define CGU_PLL2_SRC GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 18, 17)
#define CGU_PLL2_CFG_INPUT_DIV GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 16, 13)
static unsigned int ltq_get_pll0_fdiv(void);
static inline unsigned int get_input_clock(int pll)
{
switch (pll) {
case 0:
if (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & CGU_PLL0_SRC)
return BASIS_REQUENCY_USB;
else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
return BASIC_FREQUENCY_1;
else
return BASIC_FREQUENCY_2;
case 1:
if (CGU_PLL1_SRC)
return BASIS_REQUENCY_USB;
else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
return BASIC_FREQUENCY_1;
else
return BASIC_FREQUENCY_2;
case 2:
switch (CGU_PLL2_SRC) {
case 0:
return ltq_get_pll0_fdiv();
case 1:
return CGU_PLL2_PHASE_DIVIDER_ENABLE ?
BASIC_FREQUENCY_1 :
BASIC_FREQUENCY_2;
case 2:
return BASIS_REQUENCY_USB;
}
default:
return 0;
}
}
static inline unsigned int cal_dsm(int pll, unsigned int num, unsigned int den)
{
u64 res, clock = get_input_clock(pll);
res = num * clock;
do_div(res, den);
return res;
}
static inline unsigned int mash_dsm(int pll, unsigned int M, unsigned int N,
unsigned int K)
{
unsigned int num = ((N + 1) << 10) + K;
unsigned int den = (M + 1) << 10;
return cal_dsm(pll, num, den);
}
static inline unsigned int ssff_dsm_1(int pll, unsigned int M, unsigned int N,
unsigned int K)
{
unsigned int num = ((N + 1) << 11) + K + 512;
unsigned int den = (M + 1) << 11;
return cal_dsm(pll, num, den);
}
static inline unsigned int ssff_dsm_2(int pll, unsigned int M, unsigned int N,
unsigned int K)
{
unsigned int num = K >= 512 ?
((N + 1) << 12) + K - 512 : ((N + 1) << 12) + K + 3584;
unsigned int den = (M + 1) << 12;
return cal_dsm(pll, num, den);
}
static inline unsigned int dsm(int pll, unsigned int M, unsigned int N,
unsigned int K, unsigned int dsmsel, unsigned int phase_div_en)
{
if (!dsmsel)
return mash_dsm(pll, M, N, K);
else if (!phase_div_en)
return mash_dsm(pll, M, N, K);
else
return ssff_dsm_2(pll, M, N, K);
}
static inline unsigned int ltq_get_pll0_fosc(void)
{
if (CGU_PLL0_BYPASS)
return get_input_clock(0);
else
return !CGU_PLL0_CFG_FRAC_EN
? dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN, 0,
CGU_PLL0_CFG_DSMSEL,
CGU_PLL0_PHASE_DIVIDER_ENABLE)
: dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN,
CGU_PLL0_CFG_PLLK, CGU_PLL0_CFG_DSMSEL,
CGU_PLL0_PHASE_DIVIDER_ENABLE);
}
static unsigned int ltq_get_pll0_fdiv(void)
{
unsigned int div = CGU_PLL2_CFG_INPUT_DIV + 1;
return (ltq_get_pll0_fosc() + (div >> 1)) / div;
}
unsigned int ltq_get_io_region_clock(void)
{
unsigned int ret = ltq_get_pll0_fosc();
switch (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & CGU_SYS_DDR_SEL) {
default:
case 0:
return (ret + 1) / 2;
case 1:
return (ret * 2 + 2) / 5;
case 2:
return (ret + 1) / 3;
case 3:
return (ret + 2) / 4;
}
}
EXPORT_SYMBOL(ltq_get_io_region_clock);
unsigned int ltq_get_fpi_bus_clock(int fpi)
{
unsigned int ret = ltq_get_io_region_clock();
if ((fpi == 2) && (ltq_cgu_r32(LTQ_CGU_SYS) & CGU_SYS_FPI_SEL))
ret >>= 1;
return ret;
}
EXPORT_SYMBOL(ltq_get_fpi_bus_clock);
unsigned int ltq_get_cpu_hz(void)
{
switch (ltq_cgu_r32(LTQ_CGU_SYS) & 0xc) {
case 0:
return CLOCK_333M;
case 4:
return DDR_HZ;
case 8:
return DDR_HZ << 1;
default:
return DDR_HZ >> 1;
}
}
EXPORT_SYMBOL(ltq_get_cpu_hz);
unsigned int ltq_get_fpi_hz(void)
{
unsigned int ddr_clock = DDR_HZ;
if (ltq_cgu_r32(LTQ_CGU_SYS) & 0x40)
return ddr_clock >> 1;
return ddr_clock;
}
EXPORT_SYMBOL(ltq_get_fpi_hz);

View File

@ -0,0 +1,151 @@
/*
* 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.
*
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
*/
#include <linux/io.h>
#include <linux/export.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <asm/time.h>
#include <asm/irq.h>
#include <asm/div64.h>
#include <lantiq_soc.h>
#include "../clk.h"
static unsigned int ram_clocks[] = {
CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M };
#define DDR_HZ ram_clocks[ltq_cgu_r32(CGU_SYS) & 0x3]
/* legacy xway clock */
#define CGU_SYS 0x10
/* vr9 clock */
#define CGU_SYS_VR9 0x0c
#define CGU_IF_CLK_VR9 0x24
unsigned long ltq_danube_fpi_hz(void)
{
unsigned long ddr_clock = DDR_HZ;
if (ltq_cgu_r32(CGU_SYS) & 0x40)
return ddr_clock >> 1;
return ddr_clock;
}
unsigned long ltq_danube_cpu_hz(void)
{
switch (ltq_cgu_r32(CGU_SYS) & 0xc) {
case 0:
return CLOCK_333M;
case 4:
return DDR_HZ;
case 8:
return DDR_HZ << 1;
default:
return DDR_HZ >> 1;
}
}
unsigned long ltq_ar9_sys_hz(void)
{
if (((ltq_cgu_r32(CGU_SYS) >> 3) & 0x3) == 0x2)
return CLOCK_393M;
return CLOCK_333M;
}
unsigned long ltq_ar9_fpi_hz(void)
{
unsigned long sys = ltq_ar9_sys_hz();
if (ltq_cgu_r32(CGU_SYS) & BIT(0))
return sys;
return sys >> 1;
}
unsigned long ltq_ar9_cpu_hz(void)
{
if (ltq_cgu_r32(CGU_SYS) & BIT(2))
return ltq_ar9_fpi_hz();
else
return ltq_ar9_sys_hz();
}
unsigned long ltq_vr9_cpu_hz(void)
{
unsigned int cpu_sel;
unsigned long clk;
cpu_sel = (ltq_cgu_r32(CGU_SYS_VR9) >> 4) & 0xf;
switch (cpu_sel) {
case 0:
clk = CLOCK_600M;
break;
case 1:
clk = CLOCK_500M;
break;
case 2:
clk = CLOCK_393M;
break;
case 3:
clk = CLOCK_333M;
break;
case 5:
case 6:
clk = CLOCK_196_608M;
break;
case 7:
clk = CLOCK_167M;
break;
case 4:
case 8:
case 9:
clk = CLOCK_125M;
break;
default:
clk = 0;
break;
}
return clk;
}
unsigned long ltq_vr9_fpi_hz(void)
{
unsigned int ocp_sel, cpu_clk;
unsigned long clk;
cpu_clk = ltq_vr9_cpu_hz();
ocp_sel = ltq_cgu_r32(CGU_SYS_VR9) & 0x3;
switch (ocp_sel) {
case 0:
/* OCP ratio 1 */
clk = cpu_clk;
break;
case 2:
/* OCP ratio 2 */
clk = cpu_clk / 2;
break;
case 3:
/* OCP ratio 2.5 */
clk = (cpu_clk * 2) / 5;
break;
case 4:
/* OCP ratio 3 */
clk = cpu_clk / 3;
break;
default:
clk = 0;
break;
}
return clk;
}

View File

@ -1,119 +0,0 @@
/*
* 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.
*
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
*/
#include <linux/init.h>
#include <linux/export.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/mtd/physmap.h>
#include <linux/kernel.h>
#include <linux/reboot.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/etherdevice.h>
#include <linux/time.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <asm/bootinfo.h>
#include <asm/irq.h>
#include <lantiq_soc.h>
#include <lantiq_irq.h>
#include <lantiq_platform.h>
#include "devices.h"
/* gpio */
static struct resource ltq_gpio_resource[] = {
{
.name = "gpio0",
.start = LTQ_GPIO0_BASE_ADDR,
.end = LTQ_GPIO0_BASE_ADDR + LTQ_GPIO_SIZE - 1,
.flags = IORESOURCE_MEM,
}, {
.name = "gpio1",
.start = LTQ_GPIO1_BASE_ADDR,
.end = LTQ_GPIO1_BASE_ADDR + LTQ_GPIO_SIZE - 1,
.flags = IORESOURCE_MEM,
}, {
.name = "gpio2",
.start = LTQ_GPIO2_BASE_ADDR,
.end = LTQ_GPIO2_BASE_ADDR + LTQ_GPIO_SIZE - 1,
.flags = IORESOURCE_MEM,
}
};
void __init ltq_register_gpio(void)
{
platform_device_register_simple("ltq_gpio", 0,
&ltq_gpio_resource[0], 1);
platform_device_register_simple("ltq_gpio", 1,
&ltq_gpio_resource[1], 1);
/* AR9 and VR9 have an extra gpio block */
if (ltq_is_ar9() || ltq_is_vr9()) {
platform_device_register_simple("ltq_gpio", 2,
&ltq_gpio_resource[2], 1);
}
}
/* serial to parallel conversion */
static struct resource ltq_stp_resource = {
.name = "stp",
.start = LTQ_STP_BASE_ADDR,
.end = LTQ_STP_BASE_ADDR + LTQ_STP_SIZE - 1,
.flags = IORESOURCE_MEM,
};
void __init ltq_register_gpio_stp(void)
{
platform_device_register_simple("ltq_stp", 0, &ltq_stp_resource, 1);
}
/* asc ports - amazon se has its own serial mapping */
static struct resource ltq_ase_asc_resources[] = {
{
.name = "asc0",
.start = LTQ_ASC1_BASE_ADDR,
.end = LTQ_ASC1_BASE_ADDR + LTQ_ASC_SIZE - 1,
.flags = IORESOURCE_MEM,
},
IRQ_RES(tx, LTQ_ASC_ASE_TIR),
IRQ_RES(rx, LTQ_ASC_ASE_RIR),
IRQ_RES(err, LTQ_ASC_ASE_EIR),
};
void __init ltq_register_ase_asc(void)
{
platform_device_register_simple("ltq_asc", 0,
ltq_ase_asc_resources, ARRAY_SIZE(ltq_ase_asc_resources));
}
/* ethernet */
static struct resource ltq_etop_resources = {
.name = "etop",
.start = LTQ_ETOP_BASE_ADDR,
.end = LTQ_ETOP_BASE_ADDR + LTQ_ETOP_SIZE - 1,
.flags = IORESOURCE_MEM,
};
static struct platform_device ltq_etop = {
.name = "ltq_etop",
.resource = &ltq_etop_resources,
.num_resources = 1,
};
void __init
ltq_register_etop(struct ltq_eth_data *eth)
{
if (eth) {
ltq_etop.dev.platform_data = eth;
platform_device_register(&ltq_etop);
}
}

View File

@ -1,20 +0,0 @@
/*
* 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.
*
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
*/
#ifndef _LTQ_DEVICES_XWAY_H__
#define _LTQ_DEVICES_XWAY_H__
#include "../devices.h"
#include <linux/phy.h>
extern void ltq_register_gpio(void);
extern void ltq_register_gpio_stp(void);
extern void ltq_register_ase_asc(void);
extern void ltq_register_etop(struct ltq_eth_data *eth);
#endif

View File

@ -19,7 +19,8 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <linux/export.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <lantiq_soc.h>
#include <xway_dma.h>
@ -55,13 +56,6 @@
#define ltq_dma_w32_mask(x, y, z) ltq_w32_mask(x, y, \
ltq_dma_membase + (z))
static struct resource ltq_dma_resource = {
.name = "dma",
.start = LTQ_DMA_BASE_ADDR,
.end = LTQ_DMA_BASE_ADDR + LTQ_DMA_SIZE - 1,
.flags = IORESOURCE_MEM,
};
static void __iomem *ltq_dma_membase;
void
@ -215,27 +209,28 @@ ltq_dma_init_port(int p)
}
EXPORT_SYMBOL_GPL(ltq_dma_init_port);
int __init
ltq_dma_init(void)
static int __devinit
ltq_dma_init(struct platform_device *pdev)
{
struct clk *clk;
struct resource *res;
int i;
/* insert and request the memory region */
if (insert_resource(&iomem_resource, &ltq_dma_resource) < 0)
panic("Failed to insert dma memory");
if (request_mem_region(ltq_dma_resource.start,
resource_size(&ltq_dma_resource), "dma") < 0)
panic("Failed to request dma memory");
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
panic("Failed to get dma resource");
/* remap dma register range */
ltq_dma_membase = ioremap_nocache(ltq_dma_resource.start,
resource_size(&ltq_dma_resource));
ltq_dma_membase = devm_request_and_ioremap(&pdev->dev, res);
if (!ltq_dma_membase)
panic("Failed to remap dma memory");
panic("Failed to remap dma resource");
/* power up and reset the dma engine */
ltq_pmu_enable(PMU_DMA);
clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(clk))
panic("Failed to get dma clock");
clk_enable(clk);
ltq_dma_w32_mask(0, DMA_RESET, LTQ_DMA_CTRL);
/* disable all interrupts */
@ -248,7 +243,29 @@ ltq_dma_init(void)
ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL);
ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
}
dev_info(&pdev->dev, "init done\n");
return 0;
}
postcore_initcall(ltq_dma_init);
static const struct of_device_id dma_match[] = {
{ .compatible = "lantiq,dma-xway" },
{},
};
MODULE_DEVICE_TABLE(of, dma_match);
static struct platform_driver dma_driver = {
.probe = ltq_dma_init,
.driver = {
.name = "dma-xway",
.owner = THIS_MODULE,
.of_match_table = dma_match,
},
};
int __init
dma_init(void)
{
return platform_driver_register(&dma_driver);
}
postcore_initcall(dma_init);

View File

@ -1,52 +0,0 @@
/*
* 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.
*
* EBU - the external bus unit attaches PCI, NOR and NAND
*
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <lantiq_soc.h>
/* all access to the ebu must be locked */
DEFINE_SPINLOCK(ebu_lock);
EXPORT_SYMBOL_GPL(ebu_lock);
static struct resource ltq_ebu_resource = {
.name = "ebu",
.start = LTQ_EBU_BASE_ADDR,
.end = LTQ_EBU_BASE_ADDR + LTQ_EBU_SIZE - 1,
.flags = IORESOURCE_MEM,
};
/* remapped base addr of the clock unit and external bus unit */
void __iomem *ltq_ebu_membase;
static int __init lantiq_ebu_init(void)
{
/* insert and request the memory region */
if (insert_resource(&iomem_resource, &ltq_ebu_resource) < 0)
panic("Failed to insert ebu memory");
if (request_mem_region(ltq_ebu_resource.start,
resource_size(&ltq_ebu_resource), "ebu") < 0)
panic("Failed to request ebu memory");
/* remap ebu register range */
ltq_ebu_membase = ioremap_nocache(ltq_ebu_resource.start,
resource_size(&ltq_ebu_resource));
if (!ltq_ebu_membase)
panic("Failed to remap ebu memory");
/* make sure to unprotect the memory region where flash is located */
ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0);
return 0;
}
postcore_initcall(lantiq_ebu_init);

View File

@ -36,18 +36,6 @@ struct ltq_gpio {
static struct ltq_gpio ltq_gpio_port[MAX_PORTS];
int gpio_to_irq(unsigned int gpio)
{
return -EINVAL;
}
EXPORT_SYMBOL(gpio_to_irq);
int irq_to_gpio(unsigned int gpio)
{
return -EINVAL;
}
EXPORT_SYMBOL(irq_to_gpio);
int ltq_gpio_request(unsigned int pin, unsigned int alt0,
unsigned int alt1, unsigned int dir, const char *name)
{

View File

@ -1,126 +0,0 @@
/*
* 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.
*
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
*/
#include <linux/init.h>
#include <linux/export.h>
#include <linux/types.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <lantiq_soc.h>
/*
* By attaching hardware latches to the EBU it is possible to create output
* only gpios. This driver configures a special memory address, which when
* written to outputs 16 bit to the latches.
*/
#define LTQ_EBU_BUSCON 0x1e7ff /* 16 bit access, slowest timing */
#define LTQ_EBU_WP 0x80000000 /* write protect bit */
/* we keep a shadow value of the last value written to the ebu */
static int ltq_ebu_gpio_shadow = 0x0;
static void __iomem *ltq_ebu_gpio_membase;
static void ltq_ebu_apply(void)
{
unsigned long flags;
spin_lock_irqsave(&ebu_lock, flags);
ltq_ebu_w32(LTQ_EBU_BUSCON, LTQ_EBU_BUSCON1);
*((__u16 *)ltq_ebu_gpio_membase) = ltq_ebu_gpio_shadow;
ltq_ebu_w32(LTQ_EBU_BUSCON | LTQ_EBU_WP, LTQ_EBU_BUSCON1);
spin_unlock_irqrestore(&ebu_lock, flags);
}
static void ltq_ebu_set(struct gpio_chip *chip, unsigned offset, int value)
{
if (value)
ltq_ebu_gpio_shadow |= (1 << offset);
else
ltq_ebu_gpio_shadow &= ~(1 << offset);
ltq_ebu_apply();
}
static int ltq_ebu_direction_output(struct gpio_chip *chip, unsigned offset,
int value)
{
ltq_ebu_set(chip, offset, value);
return 0;
}
static struct gpio_chip ltq_ebu_chip = {
.label = "ltq_ebu",
.direction_output = ltq_ebu_direction_output,
.set = ltq_ebu_set,
.base = 72,
.ngpio = 16,
.can_sleep = 1,
.owner = THIS_MODULE,
};
static int ltq_ebu_probe(struct platform_device *pdev)
{
int ret = 0;
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "failed to get memory resource\n");
return -ENOENT;
}
res = devm_request_mem_region(&pdev->dev, res->start,
resource_size(res), dev_name(&pdev->dev));
if (!res) {
dev_err(&pdev->dev, "failed to request memory resource\n");
return -EBUSY;
}
ltq_ebu_gpio_membase = devm_ioremap_nocache(&pdev->dev, res->start,
resource_size(res));
if (!ltq_ebu_gpio_membase) {
dev_err(&pdev->dev, "Failed to ioremap mem region\n");
return -ENOMEM;
}
/* grab the default shadow value passed form the platform code */
ltq_ebu_gpio_shadow = (unsigned int) pdev->dev.platform_data;
/* tell the ebu controller which memory address we will be using */
ltq_ebu_w32(pdev->resource->start | 0x1, LTQ_EBU_ADDRSEL1);
/* write protect the region */
ltq_ebu_w32(LTQ_EBU_BUSCON | LTQ_EBU_WP, LTQ_EBU_BUSCON1);
ret = gpiochip_add(&ltq_ebu_chip);
if (!ret)
ltq_ebu_apply();
return ret;
}
static struct platform_driver ltq_ebu_driver = {
.probe = ltq_ebu_probe,
.driver = {
.name = "ltq_ebu",
.owner = THIS_MODULE,
},
};
static int __init ltq_ebu_init(void)
{
int ret = platform_driver_register(&ltq_ebu_driver);
if (ret)
pr_info("ltq_ebu : Error registering platfom driver!");
return ret;
}
postcore_initcall(ltq_ebu_init);

View File

@ -1,157 +0,0 @@
/*
* 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.
*
* Copyright (C) 2007 John Crispin <blogic@openwrt.org>
*
*/
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/export.h>
#include <linux/types.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <lantiq_soc.h>
#define LTQ_STP_CON0 0x00
#define LTQ_STP_CON1 0x04
#define LTQ_STP_CPU0 0x08
#define LTQ_STP_CPU1 0x0C
#define LTQ_STP_AR 0x10
#define LTQ_STP_CON_SWU (1 << 31)
#define LTQ_STP_2HZ 0
#define LTQ_STP_4HZ (1 << 23)
#define LTQ_STP_8HZ (2 << 23)
#define LTQ_STP_10HZ (3 << 23)
#define LTQ_STP_SPEED_MASK (0xf << 23)
#define LTQ_STP_UPD_FPI (1 << 31)
#define LTQ_STP_UPD_MASK (3 << 30)
#define LTQ_STP_ADSL_SRC (3 << 24)
#define LTQ_STP_GROUP0 (1 << 0)
#define LTQ_STP_RISING 0
#define LTQ_STP_FALLING (1 << 26)
#define LTQ_STP_EDGE_MASK (1 << 26)
#define ltq_stp_r32(reg) __raw_readl(ltq_stp_membase + reg)
#define ltq_stp_w32(val, reg) __raw_writel(val, ltq_stp_membase + reg)
#define ltq_stp_w32_mask(clear, set, reg) \
ltq_w32((ltq_r32(ltq_stp_membase + reg) & ~(clear)) | (set), \
ltq_stp_membase + (reg))
static int ltq_stp_shadow = 0xffff;
static void __iomem *ltq_stp_membase;
static void ltq_stp_set(struct gpio_chip *chip, unsigned offset, int value)
{
if (value)
ltq_stp_shadow |= (1 << offset);
else
ltq_stp_shadow &= ~(1 << offset);
ltq_stp_w32(ltq_stp_shadow, LTQ_STP_CPU0);
}
static int ltq_stp_direction_output(struct gpio_chip *chip, unsigned offset,
int value)
{
ltq_stp_set(chip, offset, value);
return 0;
}
static struct gpio_chip ltq_stp_chip = {
.label = "ltq_stp",
.direction_output = ltq_stp_direction_output,
.set = ltq_stp_set,
.base = 48,
.ngpio = 24,
.can_sleep = 1,
.owner = THIS_MODULE,
};
static int ltq_stp_hw_init(void)
{
/* the 3 pins used to control the external stp */
ltq_gpio_request(4, 1, 0, 1, "stp-st");
ltq_gpio_request(5, 1, 0, 1, "stp-d");
ltq_gpio_request(6, 1, 0, 1, "stp-sh");
/* sane defaults */
ltq_stp_w32(0, LTQ_STP_AR);
ltq_stp_w32(0, LTQ_STP_CPU0);
ltq_stp_w32(0, LTQ_STP_CPU1);
ltq_stp_w32(LTQ_STP_CON_SWU, LTQ_STP_CON0);
ltq_stp_w32(0, LTQ_STP_CON1);
/* rising or falling edge */
ltq_stp_w32_mask(LTQ_STP_EDGE_MASK, LTQ_STP_FALLING, LTQ_STP_CON0);
/* per default stp 15-0 are set */
ltq_stp_w32_mask(0, LTQ_STP_GROUP0, LTQ_STP_CON1);
/* stp are update periodically by the FPI bus */
ltq_stp_w32_mask(LTQ_STP_UPD_MASK, LTQ_STP_UPD_FPI, LTQ_STP_CON1);
/* set stp update speed */
ltq_stp_w32_mask(LTQ_STP_SPEED_MASK, LTQ_STP_8HZ, LTQ_STP_CON1);
/* tell the hardware that pin (led) 0 and 1 are controlled
* by the dsl arc
*/
ltq_stp_w32_mask(0, LTQ_STP_ADSL_SRC, LTQ_STP_CON0);
ltq_pmu_enable(PMU_LED);
return 0;
}
static int __devinit ltq_stp_probe(struct platform_device *pdev)
{
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
int ret = 0;
if (!res)
return -ENOENT;
res = devm_request_mem_region(&pdev->dev, res->start,
resource_size(res), dev_name(&pdev->dev));
if (!res) {
dev_err(&pdev->dev, "failed to request STP memory\n");
return -EBUSY;
}
ltq_stp_membase = devm_ioremap_nocache(&pdev->dev, res->start,
resource_size(res));
if (!ltq_stp_membase) {
dev_err(&pdev->dev, "failed to remap STP memory\n");
return -ENOMEM;
}
ret = gpiochip_add(&ltq_stp_chip);
if (!ret)
ret = ltq_stp_hw_init();
return ret;
}
static struct platform_driver ltq_stp_driver = {
.probe = ltq_stp_probe,
.driver = {
.name = "ltq_stp",
.owner = THIS_MODULE,
},
};
int __init ltq_stp_init(void)
{
int ret = platform_driver_register(&ltq_stp_driver);
if (ret)
pr_info("ltq_stp: error registering platfom driver");
return ret;
}
postcore_initcall(ltq_stp_init);

View File

@ -1,57 +0,0 @@
/*
* 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.
*
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
*/
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/input.h>
#include <lantiq.h>
#include "../machtypes.h"
#include "devices.h"
static struct mtd_partition easy50601_partitions[] = {
{
.name = "uboot",
.offset = 0x0,
.size = 0x10000,
},
{
.name = "uboot_env",
.offset = 0x10000,
.size = 0x10000,
},
{
.name = "linux",
.offset = 0x20000,
.size = 0xE0000,
},
{
.name = "rootfs",
.offset = 0x100000,
.size = 0x300000,
},
};
static struct physmap_flash_data easy50601_flash_data = {
.nr_parts = ARRAY_SIZE(easy50601_partitions),
.parts = easy50601_partitions,
};
static void __init easy50601_init(void)
{
ltq_register_nor(&easy50601_flash_data);
}
MIPS_MACHINE(LTQ_MACH_EASY50601,
"EASY50601",
"EASY50601 Eval Board",
easy50601_init);

View File

@ -1,74 +0,0 @@
/*
* 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.
*
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
*/
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/input.h>
#include <linux/phy.h>
#include <lantiq_soc.h>
#include <irq.h>
#include "../machtypes.h"
#include "devices.h"
static struct mtd_partition easy50712_partitions[] = {
{
.name = "uboot",
.offset = 0x0,
.size = 0x10000,
},
{
.name = "uboot_env",
.offset = 0x10000,
.size = 0x10000,
},
{
.name = "linux",
.offset = 0x20000,
.size = 0xe0000,
},
{
.name = "rootfs",
.offset = 0x100000,
.size = 0x300000,
},
};
static struct physmap_flash_data easy50712_flash_data = {
.nr_parts = ARRAY_SIZE(easy50712_partitions),
.parts = easy50712_partitions,
};
static struct ltq_pci_data ltq_pci_data = {
.clock = PCI_CLOCK_INT,
.gpio = PCI_GNT1 | PCI_REQ1,
.irq = {
[14] = INT_NUM_IM0_IRL0 + 22,
},
};
static struct ltq_eth_data ltq_eth_data = {
.mii_mode = PHY_INTERFACE_MODE_MII,
};
static void __init easy50712_init(void)
{
ltq_register_gpio_stp();
ltq_register_nor(&easy50712_flash_data);
ltq_register_pci(&ltq_pci_data);
ltq_register_etop(&ltq_eth_data);
}
MIPS_MACHINE(LTQ_MACH_EASY50712,
"EASY50712",
"EASY50712 Eval Board",
easy50712_init);

View File

@ -1,69 +0,0 @@
/*
* 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.
*
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <lantiq_soc.h>
/* PMU - the power management unit allows us to turn part of the core
* on and off
*/
/* the enable / disable registers */
#define LTQ_PMU_PWDCR 0x1C
#define LTQ_PMU_PWDSR 0x20
#define ltq_pmu_w32(x, y) ltq_w32((x), ltq_pmu_membase + (y))
#define ltq_pmu_r32(x) ltq_r32(ltq_pmu_membase + (x))
static struct resource ltq_pmu_resource = {
.name = "pmu",
.start = LTQ_PMU_BASE_ADDR,
.end = LTQ_PMU_BASE_ADDR + LTQ_PMU_SIZE - 1,
.flags = IORESOURCE_MEM,
};
static void __iomem *ltq_pmu_membase;
void ltq_pmu_enable(unsigned int module)
{
int err = 1000000;
ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) & ~module, LTQ_PMU_PWDCR);
do {} while (--err && (ltq_pmu_r32(LTQ_PMU_PWDSR) & module));
if (!err)
panic("activating PMU module failed!");
}
EXPORT_SYMBOL(ltq_pmu_enable);
void ltq_pmu_disable(unsigned int module)
{
ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) | module, LTQ_PMU_PWDCR);
}
EXPORT_SYMBOL(ltq_pmu_disable);
int __init ltq_pmu_init(void)
{
if (insert_resource(&iomem_resource, &ltq_pmu_resource) < 0)
panic("Failed to insert pmu memory");
if (request_mem_region(ltq_pmu_resource.start,
resource_size(&ltq_pmu_resource), "pmu") < 0)
panic("Failed to request pmu memory");
ltq_pmu_membase = ioremap_nocache(ltq_pmu_resource.start,
resource_size(&ltq_pmu_resource));
if (!ltq_pmu_membase)
panic("Failed to remap pmu memory");
return 0;
}
core_initcall(ltq_pmu_init);

View File

@ -1,39 +0,0 @@
/*
* 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.
*
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
*/
#include <linux/export.h>
#include <linux/clk.h>
#include <asm/bootinfo.h>
#include <asm/time.h>
#include <lantiq_soc.h>
#include "../prom.h"
#define SOC_AMAZON_SE "Amazon_SE"
#define PART_SHIFT 12
#define PART_MASK 0x0FFFFFFF
#define REV_SHIFT 28
#define REV_MASK 0xF0000000
void __init ltq_soc_detect(struct ltq_soc_info *i)
{
i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
switch (i->partnum) {
case SOC_ID_AMAZON_SE:
i->name = SOC_AMAZON_SE;
i->type = SOC_TYPE_AMAZON_SE;
break;
default:
unreachable();
break;
}
}

View File

@ -1,54 +0,0 @@
/*
* 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.
*
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
*/
#include <linux/export.h>
#include <linux/clk.h>
#include <asm/bootinfo.h>
#include <asm/time.h>
#include <lantiq_soc.h>
#include "../prom.h"
#define SOC_DANUBE "Danube"
#define SOC_TWINPASS "Twinpass"
#define SOC_AR9 "AR9"
#define PART_SHIFT 12
#define PART_MASK 0x0FFFFFFF
#define REV_SHIFT 28
#define REV_MASK 0xF0000000
void __init ltq_soc_detect(struct ltq_soc_info *i)
{
i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
switch (i->partnum) {
case SOC_ID_DANUBE1:
case SOC_ID_DANUBE2:
i->name = SOC_DANUBE;
i->type = SOC_TYPE_DANUBE;
break;
case SOC_ID_TWINPASS:
i->name = SOC_TWINPASS;
i->type = SOC_TYPE_DANUBE;
break;
case SOC_ID_ARX188:
case SOC_ID_ARX168:
case SOC_ID_ARX182:
i->name = SOC_AR9;
i->type = SOC_TYPE_AR9;
break;
default:
unreachable();
break;
}
}

View File

@ -0,0 +1,115 @@
/*
* 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.
*
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
*/
#include <linux/export.h>
#include <linux/clk.h>
#include <asm/bootinfo.h>
#include <asm/time.h>
#include <lantiq_soc.h>
#include "../prom.h"
#define SOC_DANUBE "Danube"
#define SOC_TWINPASS "Twinpass"
#define SOC_AMAZON_SE "Amazon_SE"
#define SOC_AR9 "AR9"
#define SOC_GR9 "GR9"
#define SOC_VR9 "VR9"
#define COMP_DANUBE "lantiq,danube"
#define COMP_TWINPASS "lantiq,twinpass"
#define COMP_AMAZON_SE "lantiq,ase"
#define COMP_AR9 "lantiq,ar9"
#define COMP_GR9 "lantiq,gr9"
#define COMP_VR9 "lantiq,vr9"
#define PART_SHIFT 12
#define PART_MASK 0x0FFFFFFF
#define REV_SHIFT 28
#define REV_MASK 0xF0000000
void __init ltq_soc_detect(struct ltq_soc_info *i)
{
i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
sprintf(i->rev_type, "1.%d", i->rev);
switch (i->partnum) {
case SOC_ID_DANUBE1:
case SOC_ID_DANUBE2:
i->name = SOC_DANUBE;
i->type = SOC_TYPE_DANUBE;
i->compatible = COMP_DANUBE;
break;
case SOC_ID_TWINPASS:
i->name = SOC_TWINPASS;
i->type = SOC_TYPE_DANUBE;
i->compatible = COMP_TWINPASS;
break;
case SOC_ID_ARX188:
case SOC_ID_ARX168_1:
case SOC_ID_ARX168_2:
case SOC_ID_ARX182:
i->name = SOC_AR9;
i->type = SOC_TYPE_AR9;
i->compatible = COMP_AR9;
break;
case SOC_ID_GRX188:
case SOC_ID_GRX168:
i->name = SOC_GR9;
i->type = SOC_TYPE_AR9;
i->compatible = COMP_GR9;
break;
case SOC_ID_AMAZON_SE_1:
case SOC_ID_AMAZON_SE_2:
#ifdef CONFIG_PCI
panic("ase is only supported for non pci kernels");
#endif
i->name = SOC_AMAZON_SE;
i->type = SOC_TYPE_AMAZON_SE;
i->compatible = COMP_AMAZON_SE;
break;
case SOC_ID_VRX282:
case SOC_ID_VRX268:
case SOC_ID_VRX288:
i->name = SOC_VR9;
i->type = SOC_TYPE_VR9;
i->compatible = COMP_VR9;
break;
case SOC_ID_GRX268:
case SOC_ID_GRX288:
i->name = SOC_GR9;
i->type = SOC_TYPE_VR9;
i->compatible = COMP_GR9;
break;
case SOC_ID_VRX268_2:
case SOC_ID_VRX288_2:
i->name = SOC_VR9;
i->type = SOC_TYPE_VR9_2;
i->compatible = COMP_VR9;
break;
case SOC_ID_GRX282_2:
case SOC_ID_GRX288_2:
i->name = SOC_GR9;
i->type = SOC_TYPE_VR9_2;
i->compatible = COMP_GR9;
break;
default:
unreachable();
break;
}
}

View File

@ -11,26 +11,31 @@
#include <linux/ioport.h>
#include <linux/pm.h>
#include <linux/export.h>
#include <linux/delay.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <asm/reboot.h>
#include <lantiq_soc.h>
#include "../prom.h"
#define ltq_rcu_w32(x, y) ltq_w32((x), ltq_rcu_membase + (y))
#define ltq_rcu_r32(x) ltq_r32(ltq_rcu_membase + (x))
/* register definitions */
#define LTQ_RCU_RST 0x0010
#define LTQ_RCU_RST_ALL 0x40000000
/* reset request register */
#define RCU_RST_REQ 0x0010
/* reset status register */
#define RCU_RST_STAT 0x0014
#define LTQ_RCU_RST_STAT 0x0014
#define LTQ_RCU_STAT_SHIFT 26
static struct resource ltq_rcu_resource = {
.name = "rcu",
.start = LTQ_RCU_BASE_ADDR,
.end = LTQ_RCU_BASE_ADDR + LTQ_RCU_SIZE - 1,
.flags = IORESOURCE_MEM,
};
/* reboot bit */
#define RCU_RD_SRST BIT(30)
/* reset cause */
#define RCU_STAT_SHIFT 26
/* boot selection */
#define RCU_BOOT_SEL_SHIFT 26
#define RCU_BOOT_SEL_MASK 0x7
/* remapped base addr of the reset control unit */
static void __iomem *ltq_rcu_membase;
@ -38,48 +43,64 @@ static void __iomem *ltq_rcu_membase;
/* This function is used by the watchdog driver */
int ltq_reset_cause(void)
{
u32 val = ltq_rcu_r32(LTQ_RCU_RST_STAT);
return val >> LTQ_RCU_STAT_SHIFT;
u32 val = ltq_rcu_r32(RCU_RST_STAT);
return val >> RCU_STAT_SHIFT;
}
EXPORT_SYMBOL_GPL(ltq_reset_cause);
/* allow platform code to find out what source we booted from */
unsigned char ltq_boot_select(void)
{
u32 val = ltq_rcu_r32(RCU_RST_STAT);
return (val >> RCU_BOOT_SEL_SHIFT) & RCU_BOOT_SEL_MASK;
}
/* reset a io domain for u micro seconds */
void ltq_reset_once(unsigned int module, ulong u)
{
ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | module, RCU_RST_REQ);
udelay(u);
ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~module, RCU_RST_REQ);
}
static void ltq_machine_restart(char *command)
{
pr_notice("System restart\n");
local_irq_disable();
ltq_rcu_w32(ltq_rcu_r32(LTQ_RCU_RST) | LTQ_RCU_RST_ALL, LTQ_RCU_RST);
ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | RCU_RD_SRST, RCU_RST_REQ);
unreachable();
}
static void ltq_machine_halt(void)
{
pr_notice("System halted.\n");
local_irq_disable();
unreachable();
}
static void ltq_machine_power_off(void)
{
pr_notice("Please turn off the power now.\n");
local_irq_disable();
unreachable();
}
static int __init mips_reboot_setup(void)
{
/* insert and request the memory region */
if (insert_resource(&iomem_resource, &ltq_rcu_resource) < 0)
panic("Failed to insert rcu memory");
struct resource res;
struct device_node *np =
of_find_compatible_node(NULL, NULL, "lantiq,rcu-xway");
if (request_mem_region(ltq_rcu_resource.start,
resource_size(&ltq_rcu_resource), "rcu") < 0)
panic("Failed to request rcu memory");
/* check if all the reset register range is available */
if (!np)
panic("Failed to load reset resources from devicetree");
/* remap rcu register range */
ltq_rcu_membase = ioremap_nocache(ltq_rcu_resource.start,
resource_size(&ltq_rcu_resource));
if (of_address_to_resource(np, 0, &res))
panic("Failed to get rcu memory range");
if (request_mem_region(res.start, resource_size(&res), res.name) < 0)
pr_err("Failed to request rcu memory");
ltq_rcu_membase = ioremap_nocache(res.start, resource_size(&res));
if (!ltq_rcu_membase)
panic("Failed to remap rcu memory");
panic("Failed to remap core memory");
_machine_restart = ltq_machine_restart;
_machine_halt = ltq_machine_halt;

View File

@ -1,19 +0,0 @@
/*
* 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.
*
* Copyright (C) 2011 John Crispin <blogic@openwrt.org>
*/
#include <lantiq_soc.h>
#include "../prom.h"
#include "devices.h"
void __init ltq_soc_setup(void)
{
ltq_register_ase_asc();
ltq_register_gpio();
ltq_register_wdt();
}

View File

@ -1,20 +0,0 @@
/*
* 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.
*
* Copyright (C) 2011 John Crispin <blogic@openwrt.org>
*/
#include <lantiq_soc.h>
#include "../prom.h"
#include "devices.h"
void __init ltq_soc_setup(void)
{
ltq_register_asc(0);
ltq_register_asc(1);
ltq_register_gpio();
ltq_register_wdt();
}

View File

@ -0,0 +1,371 @@
/*
* 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.
*
* Copyright (C) 2011-2012 John Crispin <blogic@openwrt.org>
*/
#include <linux/ioport.h>
#include <linux/export.h>
#include <linux/clkdev.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>
#include <lantiq_soc.h>
#include "../clk.h"
#include "../prom.h"
/* clock control register */
#define CGU_IFCCR 0x0018
/* system clock register */
#define CGU_SYS 0x0010
/* pci control register */
#define CGU_PCICR 0x0034
/* ephy configuration register */
#define CGU_EPHY 0x10
/* power control register */
#define PMU_PWDCR 0x1C
/* power status register */
#define PMU_PWDSR 0x20
/* power control register */
#define PMU_PWDCR1 0x24
/* power status register */
#define PMU_PWDSR1 0x28
/* power control register */
#define PWDCR(x) ((x) ? (PMU_PWDCR1) : (PMU_PWDCR))
/* power status register */
#define PWDSR(x) ((x) ? (PMU_PWDSR1) : (PMU_PWDSR))
/* clock gates that we can en/disable */
#define PMU_USB0_P BIT(0)
#define PMU_PCI BIT(4)
#define PMU_DMA BIT(5)
#define PMU_USB0 BIT(6)
#define PMU_ASC0 BIT(7)
#define PMU_EPHY BIT(7) /* ase */
#define PMU_SPI BIT(8)
#define PMU_DFE BIT(9)
#define PMU_EBU BIT(10)
#define PMU_STP BIT(11)
#define PMU_GPT BIT(12)
#define PMU_AHBS BIT(13) /* vr9 */
#define PMU_FPI BIT(14)
#define PMU_AHBM BIT(15)
#define PMU_ASC1 BIT(17)
#define PMU_PPE_QSB BIT(18)
#define PMU_PPE_SLL01 BIT(19)
#define PMU_PPE_TC BIT(21)
#define PMU_PPE_EMA BIT(22)
#define PMU_PPE_DPLUM BIT(23)
#define PMU_PPE_DPLUS BIT(24)
#define PMU_USB1_P BIT(26)
#define PMU_USB1 BIT(27)
#define PMU_SWITCH BIT(28)
#define PMU_PPE_TOP BIT(29)
#define PMU_GPHY BIT(30)
#define PMU_PCIE_CLK BIT(31)
#define PMU1_PCIE_PHY BIT(0)
#define PMU1_PCIE_CTL BIT(1)
#define PMU1_PCIE_PDI BIT(4)
#define PMU1_PCIE_MSI BIT(5)
#define pmu_w32(x, y) ltq_w32((x), pmu_membase + (y))
#define pmu_r32(x) ltq_r32(pmu_membase + (x))
static void __iomem *pmu_membase;
void __iomem *ltq_cgu_membase;
void __iomem *ltq_ebu_membase;
/* legacy function kept alive to ease clkdev transition */
void ltq_pmu_enable(unsigned int module)
{
int err = 1000000;
pmu_w32(pmu_r32(PMU_PWDCR) & ~module, PMU_PWDCR);
do {} while (--err && (pmu_r32(PMU_PWDSR) & module));
if (!err)
panic("activating PMU module failed!");
}
EXPORT_SYMBOL(ltq_pmu_enable);
/* legacy function kept alive to ease clkdev transition */
void ltq_pmu_disable(unsigned int module)
{
pmu_w32(pmu_r32(PMU_PWDCR) | module, PMU_PWDCR);
}
EXPORT_SYMBOL(ltq_pmu_disable);
/* enable a hw clock */
static int cgu_enable(struct clk *clk)
{
ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) | clk->bits, CGU_IFCCR);
return 0;
}
/* disable a hw clock */
static void cgu_disable(struct clk *clk)
{
ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) & ~clk->bits, CGU_IFCCR);
}
/* enable a clock gate */
static int pmu_enable(struct clk *clk)
{
int retry = 1000000;
pmu_w32(pmu_r32(PWDCR(clk->module)) & ~clk->bits,
PWDCR(clk->module));
do {} while (--retry && (pmu_r32(PWDSR(clk->module)) & clk->bits));
if (!retry)
panic("activating PMU module failed!\n");
return 0;
}
/* disable a clock gate */
static void pmu_disable(struct clk *clk)
{
pmu_w32(pmu_r32(PWDCR(clk->module)) | clk->bits,
PWDCR(clk->module));
}
/* the pci enable helper */
static int pci_enable(struct clk *clk)
{
unsigned int ifccr = ltq_cgu_r32(CGU_IFCCR);
/* set bus clock speed */
if (of_machine_is_compatible("lantiq,ar9")) {
ifccr &= ~0x1f00000;
if (clk->rate == CLOCK_33M)
ifccr |= 0xe00000;
else
ifccr |= 0x700000; /* 62.5M */
} else {
ifccr &= ~0xf00000;
if (clk->rate == CLOCK_33M)
ifccr |= 0x800000;
else
ifccr |= 0x400000; /* 62.5M */
}
ltq_cgu_w32(ifccr, CGU_IFCCR);
pmu_enable(clk);
return 0;
}
/* enable the external clock as a source */
static int pci_ext_enable(struct clk *clk)
{
ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) & ~(1 << 16),
CGU_IFCCR);
ltq_cgu_w32((1 << 30), CGU_PCICR);
return 0;
}
/* disable the external clock as a source */
static void pci_ext_disable(struct clk *clk)
{
ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) | (1 << 16),
CGU_IFCCR);
ltq_cgu_w32((1 << 31) | (1 << 30), CGU_PCICR);
}
/* enable a clockout source */
static int clkout_enable(struct clk *clk)
{
int i;
/* get the correct rate */
for (i = 0; i < 4; i++) {
if (clk->rates[i] == clk->rate) {
int shift = 14 - (2 * clk->module);
unsigned int ifccr = ltq_cgu_r32(CGU_IFCCR);
ifccr &= ~(3 << shift);
ifccr |= i << shift;
ltq_cgu_w32(ifccr, CGU_IFCCR);
return 0;
}
}
return -1;
}
/* manage the clock gates via PMU */
static void clkdev_add_pmu(const char *dev, const char *con,
unsigned int module, unsigned int bits)
{
struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
clk->cl.dev_id = dev;
clk->cl.con_id = con;
clk->cl.clk = clk;
clk->enable = pmu_enable;
clk->disable = pmu_disable;
clk->module = module;
clk->bits = bits;
clkdev_add(&clk->cl);
}
/* manage the clock generator */
static void clkdev_add_cgu(const char *dev, const char *con,
unsigned int bits)
{
struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
clk->cl.dev_id = dev;
clk->cl.con_id = con;
clk->cl.clk = clk;
clk->enable = cgu_enable;
clk->disable = cgu_disable;
clk->bits = bits;
clkdev_add(&clk->cl);
}
/* pci needs its own enable function as the setup is a bit more complex */
static unsigned long valid_pci_rates[] = {CLOCK_33M, CLOCK_62_5M, 0};
static void clkdev_add_pci(void)
{
struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
struct clk *clk_ext = kzalloc(sizeof(struct clk), GFP_KERNEL);
/* main pci clock */
clk->cl.dev_id = "17000000.pci";
clk->cl.con_id = NULL;
clk->cl.clk = clk;
clk->rate = CLOCK_33M;
clk->rates = valid_pci_rates;
clk->enable = pci_enable;
clk->disable = pmu_disable;
clk->module = 0;
clk->bits = PMU_PCI;
clkdev_add(&clk->cl);
/* use internal/external bus clock */
clk_ext->cl.dev_id = "17000000.pci";
clk_ext->cl.con_id = "external";
clk_ext->cl.clk = clk_ext;
clk_ext->enable = pci_ext_enable;
clk_ext->disable = pci_ext_disable;
clkdev_add(&clk_ext->cl);
}
/* xway socs can generate clocks on gpio pins */
static unsigned long valid_clkout_rates[4][5] = {
{CLOCK_32_768K, CLOCK_1_536M, CLOCK_2_5M, CLOCK_12M, 0},
{CLOCK_40M, CLOCK_12M, CLOCK_24M, CLOCK_48M, 0},
{CLOCK_25M, CLOCK_40M, CLOCK_30M, CLOCK_60M, 0},
{CLOCK_12M, CLOCK_50M, CLOCK_32_768K, CLOCK_25M, 0},
};
static void clkdev_add_clkout(void)
{
int i;
for (i = 0; i < 4; i++) {
struct clk *clk;
char *name;
name = kzalloc(sizeof("clkout0"), GFP_KERNEL);
sprintf(name, "clkout%d", i);
clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
clk->cl.dev_id = "1f103000.cgu";
clk->cl.con_id = name;
clk->cl.clk = clk;
clk->rate = 0;
clk->rates = valid_clkout_rates[i];
clk->enable = clkout_enable;
clk->module = i;
clkdev_add(&clk->cl);
}
}
/* bring up all register ranges that we need for basic system control */
void __init ltq_soc_init(void)
{
struct resource res_pmu, res_cgu, res_ebu;
struct device_node *np_pmu =
of_find_compatible_node(NULL, NULL, "lantiq,pmu-xway");
struct device_node *np_cgu =
of_find_compatible_node(NULL, NULL, "lantiq,cgu-xway");
struct device_node *np_ebu =
of_find_compatible_node(NULL, NULL, "lantiq,ebu-xway");
/* check if all the core register ranges are available */
if (!np_pmu || !np_cgu || !np_ebu)
panic("Failed to load core nodess from devicetree");
if (of_address_to_resource(np_pmu, 0, &res_pmu) ||
of_address_to_resource(np_cgu, 0, &res_cgu) ||
of_address_to_resource(np_ebu, 0, &res_ebu))
panic("Failed to get core resources");
if ((request_mem_region(res_pmu.start, resource_size(&res_pmu),
res_pmu.name) < 0) ||
(request_mem_region(res_cgu.start, resource_size(&res_cgu),
res_cgu.name) < 0) ||
(request_mem_region(res_ebu.start, resource_size(&res_ebu),
res_ebu.name) < 0))
pr_err("Failed to request core reources");
pmu_membase = ioremap_nocache(res_pmu.start, resource_size(&res_pmu));
ltq_cgu_membase = ioremap_nocache(res_cgu.start,
resource_size(&res_cgu));
ltq_ebu_membase = ioremap_nocache(res_ebu.start,
resource_size(&res_ebu));
if (!pmu_membase || !ltq_cgu_membase || !ltq_ebu_membase)
panic("Failed to remap core resources");
/* make sure to unprotect the memory region where flash is located */
ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0);
/* add our generic xway clocks */
clkdev_add_pmu("10000000.fpi", NULL, 0, PMU_FPI);
clkdev_add_pmu("1e100400.serial", NULL, 0, PMU_ASC0);
clkdev_add_pmu("1e100a00.gptu", NULL, 0, PMU_GPT);
clkdev_add_pmu("1e100bb0.stp", NULL, 0, PMU_STP);
clkdev_add_pmu("1e104100.dma", NULL, 0, PMU_DMA);
clkdev_add_pmu("1e100800.spi", NULL, 0, PMU_SPI);
clkdev_add_pmu("1e105300.ebu", NULL, 0, PMU_EBU);
clkdev_add_clkout();
/* add the soc dependent clocks */
if (!of_machine_is_compatible("lantiq,vr9"))
clkdev_add_pmu("1e180000.etop", NULL, 0, PMU_PPE);
if (!of_machine_is_compatible("lantiq,ase")) {
clkdev_add_pmu("1e100c00.serial", NULL, 0, PMU_ASC1);
clkdev_add_pci();
}
if (of_machine_is_compatible("lantiq,ase")) {
if (ltq_cgu_r32(CGU_SYS) & (1 << 5))
clkdev_add_static(CLOCK_266M, CLOCK_133M, CLOCK_133M);
else
clkdev_add_static(CLOCK_133M, CLOCK_133M, CLOCK_133M);
clkdev_add_cgu("1e180000.etop", "ephycgu", CGU_EPHY),
clkdev_add_pmu("1e180000.etop", "ephy", 0, PMU_EPHY);
} else if (of_machine_is_compatible("lantiq,vr9")) {
clkdev_add_static(ltq_vr9_cpu_hz(), ltq_vr9_fpi_hz(),
ltq_vr9_fpi_hz());
clkdev_add_pmu("1d900000.pcie", "phy", 1, PMU1_PCIE_PHY);
clkdev_add_pmu("1d900000.pcie", "bus", 0, PMU_PCIE_CLK);
clkdev_add_pmu("1d900000.pcie", "msi", 1, PMU1_PCIE_MSI);
clkdev_add_pmu("1d900000.pcie", "pdi", 1, PMU1_PCIE_PDI);
clkdev_add_pmu("1d900000.pcie", "ctl", 1, PMU1_PCIE_CTL);
clkdev_add_pmu("1d900000.pcie", "ahb", 0, PMU_AHBM | PMU_AHBS);
} else if (of_machine_is_compatible("lantiq,ar9")) {
clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(),
ltq_ar9_fpi_hz());
clkdev_add_pmu("1e180000.etop", "switch", 0, PMU_SWITCH);
} else {
clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(),
ltq_danube_fpi_hz());
}
}

View File

@ -21,6 +21,7 @@
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/r4kcache.h>
#include <asm/traps.h>
#include <asm/mmu_context.h>
#include <asm/war.h>
@ -248,6 +249,11 @@ static void __cpuinit probe_octeon(void)
}
}
static void __cpuinit octeon_cache_error_setup(void)
{
extern char except_vec2_octeon;
set_handler(0x100, &except_vec2_octeon, 0x80);
}
/**
* Setup the Octeon cache flush routines
@ -255,12 +261,6 @@ static void __cpuinit probe_octeon(void)
*/
void __cpuinit octeon_cache_init(void)
{
extern unsigned long ebase;
extern char except_vec2_octeon;
memcpy((void *)(ebase + 0x100), &except_vec2_octeon, 0x80);
octeon_flush_cache_sigtramp(ebase + 0x100);
probe_octeon();
shm_align_mask = PAGE_SIZE - 1;
@ -280,6 +280,8 @@ void __cpuinit octeon_cache_init(void)
build_clear_page();
build_copy_page();
board_cache_error_setup = octeon_cache_error_setup;
}
/**

View File

@ -32,7 +32,7 @@
#include <asm/mmu_context.h>
#include <asm/war.h>
#include <asm/cacheflush.h> /* for run_uncached() */
#include <asm/traps.h>
/*
* Special Variant of smp_call_function for use by cache functions:
@ -1385,10 +1385,8 @@ static int __init setcoherentio(char *str)
__setup("coherentio", setcoherentio);
#endif
void __cpuinit r4k_cache_init(void)
static void __cpuinit r4k_cache_error_setup(void)
{
extern void build_clear_page(void);
extern void build_copy_page(void);
extern char __weak except_vec2_generic;
extern char __weak except_vec2_sb1;
struct cpuinfo_mips *c = &current_cpu_data;
@ -1403,6 +1401,13 @@ void __cpuinit r4k_cache_init(void)
set_uncached_handler(0x100, &except_vec2_generic, 0x80);
break;
}
}
void __cpuinit r4k_cache_init(void)
{
extern void build_clear_page(void);
extern void build_copy_page(void);
struct cpuinfo_mips *c = &current_cpu_data;
probe_pcache();
setup_scache();
@ -1465,4 +1470,5 @@ void __cpuinit r4k_cache_init(void)
local_r4k___flush_cache_all(NULL);
#endif
coherency_setup();
board_cache_error_setup = r4k_cache_error_setup;
}

Some files were not shown because too many files have changed in this diff Show More