diff options
Diffstat (limited to 'arch/mips/ath79')
-rw-r--r-- | arch/mips/ath79/Kconfig | 50 | ||||
-rw-r--r-- | arch/mips/ath79/Makefile | 28 | ||||
-rw-r--r-- | arch/mips/ath79/Platform | 7 | ||||
-rw-r--r-- | arch/mips/ath79/clock.c | 183 | ||||
-rw-r--r-- | arch/mips/ath79/common.c | 97 | ||||
-rw-r--r-- | arch/mips/ath79/common.h | 31 | ||||
-rw-r--r-- | arch/mips/ath79/dev-ar913x-wmac.c | 60 | ||||
-rw-r--r-- | arch/mips/ath79/dev-ar913x-wmac.h | 17 | ||||
-rw-r--r-- | arch/mips/ath79/dev-common.c | 77 | ||||
-rw-r--r-- | arch/mips/ath79/dev-common.h | 18 | ||||
-rw-r--r-- | arch/mips/ath79/dev-gpio-buttons.c | 58 | ||||
-rw-r--r-- | arch/mips/ath79/dev-gpio-buttons.h | 23 | ||||
-rw-r--r-- | arch/mips/ath79/dev-leds-gpio.c | 56 | ||||
-rw-r--r-- | arch/mips/ath79/dev-leds-gpio.h | 21 | ||||
-rw-r--r-- | arch/mips/ath79/dev-spi.c | 38 | ||||
-rw-r--r-- | arch/mips/ath79/dev-spi.h | 22 | ||||
-rw-r--r-- | arch/mips/ath79/early_printk.c | 36 | ||||
-rw-r--r-- | arch/mips/ath79/gpio.c | 197 | ||||
-rw-r--r-- | arch/mips/ath79/irq.c | 187 | ||||
-rw-r--r-- | arch/mips/ath79/mach-ap81.c | 98 | ||||
-rw-r--r-- | arch/mips/ath79/mach-pb44.c | 118 | ||||
-rw-r--r-- | arch/mips/ath79/machtypes.h | 23 | ||||
-rw-r--r-- | arch/mips/ath79/prom.c | 57 | ||||
-rw-r--r-- | arch/mips/ath79/setup.c | 206 |
24 files changed, 1708 insertions, 0 deletions
diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig new file mode 100644 index 00000000000..b05828260f7 --- /dev/null +++ b/arch/mips/ath79/Kconfig @@ -0,0 +1,50 @@ +if ATH79 + +menu "Atheros AR71XX/AR724X/AR913X machine selection" + +config ATH79_MACH_AP81 + bool "Atheros AP81 reference board" + select SOC_AR913X + select ATH79_DEV_AR913X_WMAC + select ATH79_DEV_GPIO_BUTTONS + select ATH79_DEV_LEDS_GPIO + select ATH79_DEV_SPI + help + Say 'Y' here if you want your kernel to support the + Atheros AP81 reference board. + +config ATH79_MACH_PB44 + bool "Atheros PB44 reference board" + select SOC_AR71XX + select ATH79_DEV_GPIO_BUTTONS + select ATH79_DEV_LEDS_GPIO + select ATH79_DEV_SPI + help + Say 'Y' here if you want your kernel to support the + Atheros PB44 reference board. + +endmenu + +config SOC_AR71XX + def_bool n + +config SOC_AR724X + def_bool n + +config SOC_AR913X + def_bool n + +config ATH79_DEV_AR913X_WMAC + depends on SOC_AR913X + def_bool n + +config ATH79_DEV_GPIO_BUTTONS + def_bool n + +config ATH79_DEV_LEDS_GPIO + def_bool n + +config ATH79_DEV_SPI + def_bool n + +endif diff --git a/arch/mips/ath79/Makefile b/arch/mips/ath79/Makefile new file mode 100644 index 00000000000..c33d4653007 --- /dev/null +++ b/arch/mips/ath79/Makefile @@ -0,0 +1,28 @@ +# +# Makefile for the Atheros AR71XX/AR724X/AR913X specific parts of the kernel +# +# 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. + +obj-y := prom.o setup.o irq.o common.o clock.o gpio.o + +obj-$(CONFIG_EARLY_PRINTK) += early_printk.o + +# +# Devices +# +obj-y += dev-common.o +obj-$(CONFIG_ATH79_DEV_AR913X_WMAC) += dev-ar913x-wmac.o +obj-$(CONFIG_ATH79_DEV_GPIO_BUTTONS) += dev-gpio-buttons.o +obj-$(CONFIG_ATH79_DEV_LEDS_GPIO) += dev-leds-gpio.o +obj-$(CONFIG_ATH79_DEV_SPI) += dev-spi.o + +# +# Machines +# +obj-$(CONFIG_ATH79_MACH_AP81) += mach-ap81.o +obj-$(CONFIG_ATH79_MACH_PB44) += mach-pb44.o diff --git a/arch/mips/ath79/Platform b/arch/mips/ath79/Platform new file mode 100644 index 00000000000..2bd663647d2 --- /dev/null +++ b/arch/mips/ath79/Platform @@ -0,0 +1,7 @@ +# +# Atheros AR71xx/AR724x/AR913x +# + +platform-$(CONFIG_ATH79) += ath79/ +cflags-$(CONFIG_ATH79) += -I$(srctree)/arch/mips/include/asm/mach-ath79 +load-$(CONFIG_ATH79) = 0xffffffff80060000 diff --git a/arch/mips/ath79/clock.c b/arch/mips/ath79/clock.c new file mode 100644 index 00000000000..680bde99a26 --- /dev/null +++ b/arch/mips/ath79/clock.c @@ -0,0 +1,183 @@ +/* + * Atheros AR71XX/AR724X/AR913X common routines + * + * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/clk.h> + +#include <asm/mach-ath79/ath79.h> +#include <asm/mach-ath79/ar71xx_regs.h> +#include "common.h" + +#define AR71XX_BASE_FREQ 40000000 +#define AR724X_BASE_FREQ 5000000 +#define AR913X_BASE_FREQ 5000000 + +struct clk { + unsigned long rate; +}; + +static struct clk ath79_ref_clk; +static struct clk ath79_cpu_clk; +static struct clk ath79_ddr_clk; +static struct clk ath79_ahb_clk; +static struct clk ath79_wdt_clk; +static struct clk ath79_uart_clk; + +static void __init ar71xx_clocks_init(void) +{ + u32 pll; + u32 freq; + u32 div; + + ath79_ref_clk.rate = AR71XX_BASE_FREQ; + + pll = ath79_pll_rr(AR71XX_PLL_REG_CPU_CONFIG); + + div = ((pll >> AR71XX_PLL_DIV_SHIFT) & AR71XX_PLL_DIV_MASK) + 1; + freq = div * ath79_ref_clk.rate; + + div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1; + ath79_cpu_clk.rate = freq / div; + + div = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1; + ath79_ddr_clk.rate = freq / div; + + div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2; + ath79_ahb_clk.rate = ath79_cpu_clk.rate / div; + + ath79_wdt_clk.rate = ath79_ahb_clk.rate; + ath79_uart_clk.rate = ath79_ahb_clk.rate; +} + +static void __init ar724x_clocks_init(void) +{ + u32 pll; + u32 freq; + u32 div; + + ath79_ref_clk.rate = AR724X_BASE_FREQ; + pll = ath79_pll_rr(AR724X_PLL_REG_CPU_CONFIG); + + div = ((pll >> AR724X_PLL_DIV_SHIFT) & AR724X_PLL_DIV_MASK); + freq = div * ath79_ref_clk.rate; + + div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK); + freq *= div; + + ath79_cpu_clk.rate = freq; + + div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1; + ath79_ddr_clk.rate = freq / div; + + div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2; + ath79_ahb_clk.rate = ath79_cpu_clk.rate / div; + + ath79_wdt_clk.rate = ath79_ahb_clk.rate; + ath79_uart_clk.rate = ath79_ahb_clk.rate; +} + +static void __init ar913x_clocks_init(void) +{ + u32 pll; + u32 freq; + u32 div; + + ath79_ref_clk.rate = AR913X_BASE_FREQ; + pll = ath79_pll_rr(AR913X_PLL_REG_CPU_CONFIG); + + div = ((pll >> AR913X_PLL_DIV_SHIFT) & AR913X_PLL_DIV_MASK); + freq = div * ath79_ref_clk.rate; + + ath79_cpu_clk.rate = freq; + + div = ((pll >> AR913X_DDR_DIV_SHIFT) & AR913X_DDR_DIV_MASK) + 1; + ath79_ddr_clk.rate = freq / div; + + div = (((pll >> AR913X_AHB_DIV_SHIFT) & AR913X_AHB_DIV_MASK) + 1) * 2; + ath79_ahb_clk.rate = ath79_cpu_clk.rate / div; + + ath79_wdt_clk.rate = ath79_ahb_clk.rate; + ath79_uart_clk.rate = ath79_ahb_clk.rate; +} + +void __init ath79_clocks_init(void) +{ + if (soc_is_ar71xx()) + ar71xx_clocks_init(); + else if (soc_is_ar724x()) + ar724x_clocks_init(); + else if (soc_is_ar913x()) + ar913x_clocks_init(); + else + BUG(); + + pr_info("Clocks: CPU:%lu.%03luMHz, DDR:%lu.%03luMHz, AHB:%lu.%03luMHz, " + "Ref:%lu.%03luMHz", + ath79_cpu_clk.rate / 1000000, + (ath79_cpu_clk.rate / 1000) % 1000, + ath79_ddr_clk.rate / 1000000, + (ath79_ddr_clk.rate / 1000) % 1000, + ath79_ahb_clk.rate / 1000000, + (ath79_ahb_clk.rate / 1000) % 1000, + ath79_ref_clk.rate / 1000000, + (ath79_ref_clk.rate / 1000) % 1000); +} + +/* + * Linux clock API + */ +struct clk *clk_get(struct device *dev, const char *id) +{ + if (!strcmp(id, "ref")) + return &ath79_ref_clk; + + if (!strcmp(id, "cpu")) + return &ath79_cpu_clk; + + if (!strcmp(id, "ddr")) + return &ath79_ddr_clk; + + if (!strcmp(id, "ahb")) + return &ath79_ahb_clk; + + if (!strcmp(id, "wdt")) + return &ath79_wdt_clk; + + if (!strcmp(id, "uart")) + return &ath79_uart_clk; + + return ERR_PTR(-ENOENT); +} +EXPORT_SYMBOL(clk_get); + +int clk_enable(struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + return clk->rate; +} +EXPORT_SYMBOL(clk_get_rate); + +void clk_put(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_put); diff --git a/arch/mips/ath79/common.c b/arch/mips/ath79/common.c new file mode 100644 index 00000000000..58f60e722a0 --- /dev/null +++ b/arch/mips/ath79/common.c @@ -0,0 +1,97 @@ +/* + * Atheros AR71XX/AR724X/AR913X common routines + * + * Copyright (C) 2008-2010 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. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/spinlock.h> + +#include <asm/mach-ath79/ath79.h> +#include <asm/mach-ath79/ar71xx_regs.h> +#include "common.h" + +static DEFINE_SPINLOCK(ath79_device_reset_lock); + +u32 ath79_cpu_freq; +EXPORT_SYMBOL_GPL(ath79_cpu_freq); + +u32 ath79_ahb_freq; +EXPORT_SYMBOL_GPL(ath79_ahb_freq); + +u32 ath79_ddr_freq; +EXPORT_SYMBOL_GPL(ath79_ddr_freq); + +enum ath79_soc_type ath79_soc; + +void __iomem *ath79_pll_base; +void __iomem *ath79_reset_base; +EXPORT_SYMBOL_GPL(ath79_reset_base); +void __iomem *ath79_ddr_base; + +void ath79_ddr_wb_flush(u32 reg) +{ + void __iomem *flush_reg = ath79_ddr_base + reg; + + /* Flush the DDR write buffer. */ + __raw_writel(0x1, flush_reg); + while (__raw_readl(flush_reg) & 0x1) + ; + + /* It must be run twice. */ + __raw_writel(0x1, flush_reg); + while (__raw_readl(flush_reg) & 0x1) + ; +} +EXPORT_SYMBOL_GPL(ath79_ddr_wb_flush); + +void ath79_device_reset_set(u32 mask) +{ + unsigned long flags; + u32 reg; + u32 t; + + if (soc_is_ar71xx()) + reg = AR71XX_RESET_REG_RESET_MODULE; + else if (soc_is_ar724x()) + reg = AR724X_RESET_REG_RESET_MODULE; + else if (soc_is_ar913x()) + reg = AR913X_RESET_REG_RESET_MODULE; + else + BUG(); + + spin_lock_irqsave(&ath79_device_reset_lock, flags); + t = ath79_reset_rr(reg); + ath79_reset_wr(reg, t | mask); + spin_unlock_irqrestore(&ath79_device_reset_lock, flags); +} +EXPORT_SYMBOL_GPL(ath79_device_reset_set); + +void ath79_device_reset_clear(u32 mask) +{ + unsigned long flags; + u32 reg; + u32 t; + + if (soc_is_ar71xx()) + reg = AR71XX_RESET_REG_RESET_MODULE; + else if (soc_is_ar724x()) + reg = AR724X_RESET_REG_RESET_MODULE; + else if (soc_is_ar913x()) + reg = AR913X_RESET_REG_RESET_MODULE; + else + BUG(); + + spin_lock_irqsave(&ath79_device_reset_lock, flags); + t = ath79_reset_rr(reg); + ath79_reset_wr(reg, t & ~mask); + spin_unlock_irqrestore(&ath79_device_reset_lock, flags); +} +EXPORT_SYMBOL_GPL(ath79_device_reset_clear); diff --git a/arch/mips/ath79/common.h b/arch/mips/ath79/common.h new file mode 100644 index 00000000000..561906c2345 --- /dev/null +++ b/arch/mips/ath79/common.h @@ -0,0 +1,31 @@ +/* + * Atheros AR71XX/AR724X/AR913X common definitions + * + * 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. + */ + +#ifndef __ATH79_COMMON_H +#define __ATH79_COMMON_H + +#include <linux/types.h> +#include <linux/init.h> + +#define ATH79_MEM_SIZE_MIN (2 * 1024 * 1024) +#define ATH79_MEM_SIZE_MAX (128 * 1024 * 1024) + +void ath79_clocks_init(void); +void ath79_ddr_wb_flush(unsigned int reg); + +void ath79_gpio_function_enable(u32 mask); +void ath79_gpio_function_disable(u32 mask); +void ath79_gpio_function_setup(u32 set, u32 clear); +void ath79_gpio_init(void); + +#endif /* __ATH79_COMMON_H */ diff --git a/arch/mips/ath79/dev-ar913x-wmac.c b/arch/mips/ath79/dev-ar913x-wmac.c new file mode 100644 index 00000000000..48f425a5ba2 --- /dev/null +++ b/arch/mips/ath79/dev-ar913x-wmac.c @@ -0,0 +1,60 @@ +/* + * Atheros AR913X SoC built-in WMAC device support + * + * Copyright (C) 2008-2010 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. + */ + +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/irq.h> +#include <linux/platform_device.h> +#include <linux/ath9k_platform.h> + +#include <asm/mach-ath79/ath79.h> +#include <asm/mach-ath79/ar71xx_regs.h> +#include "dev-ar913x-wmac.h" + +static struct ath9k_platform_data ar913x_wmac_data; + +static struct resource ar913x_wmac_resources[] = { + { + .start = AR913X_WMAC_BASE, + .end = AR913X_WMAC_BASE + AR913X_WMAC_SIZE - 1, + .flags = IORESOURCE_MEM, + }, { + .start = ATH79_CPU_IRQ_IP2, + .end = ATH79_CPU_IRQ_IP2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device ar913x_wmac_device = { + .name = "ath9k", + .id = -1, + .resource = ar913x_wmac_resources, + .num_resources = ARRAY_SIZE(ar913x_wmac_resources), + .dev = { + .platform_data = &ar913x_wmac_data, + }, +}; + +void __init ath79_register_ar913x_wmac(u8 *cal_data) +{ + if (cal_data) + memcpy(ar913x_wmac_data.eeprom_data, cal_data, + sizeof(ar913x_wmac_data.eeprom_data)); + + /* reset the WMAC */ + ath79_device_reset_set(AR913X_RESET_AMBA2WMAC); + mdelay(10); + + ath79_device_reset_clear(AR913X_RESET_AMBA2WMAC); + mdelay(10); + + platform_device_register(&ar913x_wmac_device); +} diff --git a/arch/mips/ath79/dev-ar913x-wmac.h b/arch/mips/ath79/dev-ar913x-wmac.h new file mode 100644 index 00000000000..579d562bbda --- /dev/null +++ b/arch/mips/ath79/dev-ar913x-wmac.h @@ -0,0 +1,17 @@ +/* + * Atheros AR913X SoC built-in WMAC device support + * + * Copyright (C) 2008-2010 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_DEV_AR913X_WMAC_H +#define _ATH79_DEV_AR913X_WMAC_H + +void ath79_register_ar913x_wmac(u8 *cal_data); + +#endif /* _ATH79_DEV_AR913X_WMAC_H */ diff --git a/arch/mips/ath79/dev-common.c b/arch/mips/ath79/dev-common.c new file mode 100644 index 00000000000..3b82e325beb --- /dev/null +++ b/arch/mips/ath79/dev-common.c @@ -0,0 +1,77 @@ +/* + * Atheros AR71XX/AR724X/AR913X common devices + * + * 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/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/serial_8250.h> +#include <linux/clk.h> +#include <linux/err.h> + +#include <asm/mach-ath79/ath79.h> +#include <asm/mach-ath79/ar71xx_regs.h> +#include "common.h" +#include "dev-common.h" + +static struct resource ath79_uart_resources[] = { + { + .start = AR71XX_UART_BASE, + .end = AR71XX_UART_BASE + AR71XX_UART_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +#define AR71XX_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP) +static struct plat_serial8250_port ath79_uart_data[] = { + { + .mapbase = AR71XX_UART_BASE, + .irq = ATH79_MISC_IRQ_UART, + .flags = AR71XX_UART_FLAGS, + .iotype = UPIO_MEM32, + .regshift = 2, + }, { + /* terminating entry */ + } +}; + +static struct platform_device ath79_uart_device = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .resource = ath79_uart_resources, + .num_resources = ARRAY_SIZE(ath79_uart_resources), + .dev = { + .platform_data = ath79_uart_data + }, +}; + +void __init ath79_register_uart(void) +{ + struct clk *clk; + + clk = clk_get(NULL, "uart"); + if (IS_ERR(clk)) + panic("unable to get UART clock, err=%ld", PTR_ERR(clk)); + + ath79_uart_data[0].uartclk = clk_get_rate(clk); + platform_device_register(&ath79_uart_device); +} + +static struct platform_device ath79_wdt_device = { + .name = "ath79-wdt", + .id = -1, +}; + +void __init ath79_register_wdt(void) +{ + platform_device_register(&ath79_wdt_device); +} diff --git a/arch/mips/ath79/dev-common.h b/arch/mips/ath79/dev-common.h new file mode 100644 index 00000000000..0f514e1affc --- /dev/null +++ b/arch/mips/ath79/dev-common.h @@ -0,0 +1,18 @@ +/* + * Atheros AR71XX/AR724X/AR913X common devices + * + * Copyright (C) 2008-2010 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_DEV_COMMON_H +#define _ATH79_DEV_COMMON_H + +void ath79_register_uart(void); +void ath79_register_wdt(void); + +#endif /* _ATH79_DEV_COMMON_H */ diff --git a/arch/mips/ath79/dev-gpio-buttons.c b/arch/mips/ath79/dev-gpio-buttons.c new file mode 100644 index 00000000000..4b0168a11c0 --- /dev/null +++ b/arch/mips/ath79/dev-gpio-buttons.c @@ -0,0 +1,58 @@ +/* + * Atheros AR71XX/AR724X/AR913X GPIO button support + * + * Copyright (C) 2008-2010 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. + */ + +#include "linux/init.h" +#include "linux/slab.h" +#include <linux/platform_device.h> + +#include "dev-gpio-buttons.h" + +void __init ath79_register_gpio_keys_polled(int id, + unsigned poll_interval, + unsigned nbuttons, + struct gpio_keys_button *buttons) +{ + struct platform_device *pdev; + struct gpio_keys_platform_data pdata; + struct gpio_keys_button *p; + int err; + + p = kmalloc(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; + + memset(&pdata, 0, sizeof(pdata)); + pdata.poll_interval = poll_interval; + pdata.nbuttons = nbuttons; + pdata.buttons = p; + + err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); + if (err) + goto err_put_pdev; + + err = platform_device_add(pdev); + if (err) + goto err_put_pdev; + + return; + +err_put_pdev: + platform_device_put(pdev); + +err_free_buttons: + kfree(p); +} diff --git a/arch/mips/ath79/dev-gpio-buttons.h b/arch/mips/ath79/dev-gpio-buttons.h new file mode 100644 index 00000000000..481847ac1cb --- /dev/null +++ b/arch/mips/ath79/dev-gpio-buttons.h @@ -0,0 +1,23 @@ +/* + * Atheros AR71XX/AR724X/AR913X GPIO button support + * + * Copyright (C) 2008-2010 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_DEV_GPIO_BUTTONS_H +#define _ATH79_DEV_GPIO_BUTTONS_H + +#include <linux/input.h> +#include <linux/gpio_keys.h> + +void ath79_register_gpio_keys_polled(int id, + unsigned poll_interval, + unsigned nbuttons, + struct gpio_keys_button *buttons); + +#endif /* _ATH79_DEV_GPIO_BUTTONS_H */ diff --git a/arch/mips/ath79/dev-leds-gpio.c b/arch/mips/ath79/dev-leds-gpio.c new file mode 100644 index 00000000000..cdade68dcd1 --- /dev/null +++ b/arch/mips/ath79/dev-leds-gpio.c @@ -0,0 +1,56 @@ +/* + * Atheros AR71XX/AR724X/AR913X common GPIO LEDs support + * + * Copyright (C) 2008-2010 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. + */ + +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/platform_device.h> + +#include "dev-leds-gpio.h" + +void __init ath79_register_leds_gpio(int id, + unsigned num_leds, + struct gpio_led *leds) +{ + struct platform_device *pdev; + struct gpio_led_platform_data pdata; + struct gpio_led *p; + int err; + + p = kmalloc(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; + + memset(&pdata, 0, sizeof(pdata)); + pdata.num_leds = num_leds; + pdata.leds = p; + + err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); + if (err) + goto err_put_pdev; + + err = platform_device_add(pdev); + if (err) + goto err_put_pdev; + + return; + +err_put_pdev: + platform_device_put(pdev); + +err_free_leds: + kfree(p); +} diff --git a/arch/mips/ath79/dev-leds-gpio.h b/arch/mips/ath79/dev-leds-gpio.h new file mode 100644 index 00000000000..6e5d8851ebc --- /dev/null +++ b/arch/mips/ath79/dev-leds-gpio.h @@ -0,0 +1,21 @@ +/* + * Atheros AR71XX/AR724X/AR913X common GPIO LEDs support + * + * Copyright (C) 2008-2010 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_DEV_LEDS_GPIO_H +#define _ATH79_DEV_LEDS_GPIO_H + +#include <linux/leds.h> + +void ath79_register_leds_gpio(int id, + unsigned num_leds, + struct gpio_led *leds); + +#endif /* _ATH79_DEV_LEDS_GPIO_H */ diff --git a/arch/mips/ath79/dev-spi.c b/arch/mips/ath79/dev-spi.c new file mode 100644 index 00000000000..aa30163efbf --- /dev/null +++ b/arch/mips/ath79/dev-spi.c @@ -0,0 +1,38 @@ +/* + * Atheros AR71XX/AR724X/AR913X SPI controller device + * + * Copyright (C) 2008-2010 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. + */ + +#include <linux/platform_device.h> +#include <asm/mach-ath79/ar71xx_regs.h> +#include "dev-spi.h" + +static struct resource ath79_spi_resources[] = { + { + .start = AR71XX_SPI_BASE, + .end = AR71XX_SPI_BASE + AR71XX_SPI_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device ath79_spi_device = { + .name = "ath79-spi", + .id = -1, + .resource = ath79_spi_resources, + .num_resources = ARRAY_SIZE(ath79_spi_resources), +}; + +void __init ath79_register_spi(struct ath79_spi_platform_data *pdata, + struct spi_board_info const *info, + unsigned n) +{ + spi_register_board_info(info, n); + ath79_spi_device.dev.platform_data = pdata; + platform_device_register(&ath79_spi_device); +} diff --git a/arch/mips/ath79/dev-spi.h b/arch/mips/ath79/dev-spi.h new file mode 100644 index 00000000000..d732565ca73 --- /dev/null +++ b/arch/mips/ath79/dev-spi.h @@ -0,0 +1,22 @@ +/* + * Atheros AR71XX/AR724X/AR913X SPI controller device + * + * Copyright (C) 2008-2010 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_DEV_SPI_H +#define _ATH79_DEV_SPI_H + +#include <linux/spi/spi.h> +#include <asm/mach-ath79/ath79_spi_platform.h> + +void ath79_register_spi(struct ath79_spi_platform_data *pdata, + struct spi_board_info const *info, + unsigned n); + +#endif /* _ATH79_DEV_SPI_H */ diff --git a/arch/mips/ath79/early_printk.c b/arch/mips/ath79/early_printk.c new file mode 100644 index 00000000000..7499b0e9df2 --- /dev/null +++ b/arch/mips/ath79/early_printk.c @@ -0,0 +1,36 @@ +/* + * Atheros AR71XX/AR724X/AR913X SoC early printk support + * + * Copyright (C) 2008-2010 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. + */ + +#include <linux/io.h> +#include <linux/serial_reg.h> +#include <asm/addrspace.h> + +#include <asm/mach-ath79/ar71xx_regs.h> + +static inline void prom_wait_thre(void __iomem *base) +{ + u32 lsr; + + do { + lsr = __raw_readl(base + UART_LSR * 4); + if (lsr & UART_LSR_THRE) + break; + } while (1); +} + +void prom_putchar(unsigned char ch) +{ + void __iomem *base = (void __iomem *)(KSEG1ADDR(AR71XX_UART_BASE)); + + prom_wait_thre(base); + __raw_writel(ch, base + UART_TX * 4); + prom_wait_thre(base); +} diff --git a/arch/mips/ath79/gpio.c b/arch/mips/ath79/gpio.c new file mode 100644 index 00000000000..a0c426b8212 --- /dev/null +++ b/arch/mips/ath79/gpio.c @@ -0,0 +1,197 @@ +/* + * Atheros AR71XX/AR724X/AR913X GPIO API support + * + * Copyright (C) 2008-2010 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. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/spinlock.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <linux/gpio.h> + +#include <asm/mach-ath79/ar71xx_regs.h> +#include <asm/mach-ath79/ath79.h> +#include "common.h" + +static void __iomem *ath79_gpio_base; +static unsigned long ath79_gpio_count; +static DEFINE_SPINLOCK(ath79_gpio_lock); + +static void __ath79_gpio_set_value(unsigned gpio, int value) +{ + void __iomem *base = ath79_gpio_base; + + if (value) + __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_SET); + else + __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_CLEAR); +} + +static int __ath79_gpio_get_value(unsigned gpio) +{ + return (__raw_readl(ath79_gpio_base + AR71XX_GPIO_REG_IN) >> gpio) & 1; +} + +static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned offset) +{ + return __ath79_gpio_get_value(offset); +} + +static void ath79_gpio_set_value(struct gpio_chip *chip, + unsigned offset, int value) +{ + __ath79_gpio_set_value(offset, value); +} + +static int ath79_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 ath79_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); + |