diff options
Diffstat (limited to 'target/linux')
6 files changed, 551 insertions, 0 deletions
| diff --git a/target/linux/rdc/files-2.6.30/arch/x86/include/asm/mach-rdc321x/gpio.h b/target/linux/rdc/files-2.6.30/arch/x86/include/asm/mach-rdc321x/gpio.h new file mode 100644 index 000000000..873bffe30 --- /dev/null +++ b/target/linux/rdc/files-2.6.30/arch/x86/include/asm/mach-rdc321x/gpio.h @@ -0,0 +1,59 @@ +#ifndef _ASM_X86_MACH_RDC321X_GPIO_H +#define _ASM_X86_MACH_RDC321X_GPIO_H + +#include <linux/kernel.h> + +extern int rdc_gpio_get_value(unsigned gpio); +extern void rdc_gpio_set_value(unsigned gpio, int value); +extern int rdc_gpio_direction_input(unsigned gpio); +extern int rdc_gpio_direction_output(unsigned gpio, int value); +extern int rdc_gpio_request(unsigned gpio, const char *label); +extern void rdc_gpio_free(unsigned gpio); + +/* Wrappers for the arch-neutral GPIO API */ + +static inline int gpio_request(unsigned gpio, const char *label) +{ +	return rdc_gpio_request(gpio, label); +} + +static inline void gpio_free(unsigned gpio) +{ +	might_sleep(); +	rdc_gpio_free(gpio); +} + +static inline int gpio_direction_input(unsigned gpio) +{ +	return rdc_gpio_direction_input(gpio); +} + +static inline int gpio_direction_output(unsigned gpio, int value) +{ +	return rdc_gpio_direction_output(gpio, value); +} + +static inline int gpio_get_value(unsigned gpio) +{ +	return rdc_gpio_get_value(gpio); +} + +static inline void gpio_set_value(unsigned gpio, int value) +{ +	rdc_gpio_set_value(gpio, value); +} + +static inline int gpio_to_irq(unsigned gpio) +{ +	return gpio; +} + +static inline int irq_to_gpio(unsigned irq) +{ +	return irq; +} + +/* For cansleep */ +#include <asm-generic/gpio.h> + +#endif /* _ASM_X86_MACH_RDC321X_GPIO_H */ diff --git a/target/linux/rdc/files-2.6.30/arch/x86/include/asm/mach-rdc321x/rdc321x_defs.h b/target/linux/rdc/files-2.6.30/arch/x86/include/asm/mach-rdc321x/rdc321x_defs.h new file mode 100644 index 000000000..c8e9c8bed --- /dev/null +++ b/target/linux/rdc/files-2.6.30/arch/x86/include/asm/mach-rdc321x/rdc321x_defs.h @@ -0,0 +1,12 @@ +#define PFX	"rdc321x: " + +/* General purpose configuration and data registers */ +#define RDC3210_CFGREG_ADDR     0x0CF8 +#define RDC3210_CFGREG_DATA     0x0CFC + +#define RDC321X_GPIO_CTRL_REG1	0x48 +#define RDC321X_GPIO_CTRL_REG2	0x84 +#define RDC321X_GPIO_DATA_REG1	0x4c +#define RDC321X_GPIO_DATA_REG2	0x88 + +#define RDC321X_MAX_GPIO	58 diff --git a/target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/Makefile b/target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/Makefile new file mode 100644 index 000000000..8325b4ca4 --- /dev/null +++ b/target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the RDC321x specific parts of the kernel +# +obj-$(CONFIG_X86_RDC321X)        := gpio.o platform.o + diff --git a/target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/gpio.c b/target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/gpio.c new file mode 100644 index 000000000..c7eff5d2c --- /dev/null +++ b/target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/gpio.c @@ -0,0 +1,198 @@ +/* + *  GPIO support for RDC SoC R3210/R8610 + * + *  Copyright (C) 2007, Florian Fainelli <florian@openwrt.org> + *  Copyright (C) 2008, Volker Weiss <dev@tintuc.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + + +#include <linux/spinlock.h> +#include <linux/io.h> +#include <linux/types.h> +#include <linux/module.h> + +#include <asm/mach-rdc321x/gpio.h> +#include <asm/mach-rdc321x/rdc321x_defs.h> + + +/* spin lock to protect our private copy of GPIO data register plus +   the access to PCI conf registers. */ +static DEFINE_SPINLOCK(gpio_lock); + +/* copy of GPIO data registers */ +static u32 gpio_data_reg1; +static u32 gpio_data_reg2; + +static u32 gpio_request_data[2]; + + +static inline void rdc321x_conf_write(unsigned addr, u32 value) +{ +	outl((1 << 31) | (7 << 11) | addr, RDC3210_CFGREG_ADDR); +	outl(value, RDC3210_CFGREG_DATA); +} + +static inline void rdc321x_conf_or(unsigned addr, u32 value) +{ +	outl((1 << 31) | (7 << 11) | addr, RDC3210_CFGREG_ADDR); +	value |= inl(RDC3210_CFGREG_DATA); +	outl(value, RDC3210_CFGREG_DATA); +} + +static inline u32 rdc321x_conf_read(unsigned addr) +{ +	outl((1 << 31) | (7 << 11) | addr, RDC3210_CFGREG_ADDR); + +	return inl(RDC3210_CFGREG_DATA); +} + +/* configure pin as GPIO */ +static void rdc321x_configure_gpio(unsigned gpio) +{ +	unsigned long flags; + +	spin_lock_irqsave(&gpio_lock, flags); +	rdc321x_conf_or(gpio < 32 +		? RDC321X_GPIO_CTRL_REG1 : RDC321X_GPIO_CTRL_REG2, +		1 << (gpio & 0x1f)); +	spin_unlock_irqrestore(&gpio_lock, flags); +} + +/* initially setup the 2 copies of the gpio data registers. +   This function is called before the platform setup code. */ +static int __init rdc321x_gpio_setup(void) +{ +	/* this might not be, what others (BIOS, bootloader, etc.) +	   wrote to these registers before, but it's a good guess. Still +	   better than just using 0xffffffff. */ + +	gpio_data_reg1 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG1); +	gpio_data_reg2 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG2); + +	return 0; +} + +/* determine, if gpio number is valid */ +static inline int rdc321x_is_gpio(unsigned gpio) +{ +	return gpio <= RDC321X_MAX_GPIO; +} + +/* request GPIO */ +int rdc_gpio_request(unsigned gpio, const char *label) +{ +	unsigned long flags; + +	if (!rdc321x_is_gpio(gpio)) +		return -EINVAL; + +	spin_lock_irqsave(&gpio_lock, flags); +	if (gpio_request_data[(gpio & 0x20) ? 1 : 0] & (1 << (gpio & 0x1f))) +		goto inuse; +	gpio_request_data[(gpio & 0x20) ? 1 : 0] |= (1 << (gpio & 0x1f)); +	spin_unlock_irqrestore(&gpio_lock, flags); + +	return 0; +inuse: +	spin_unlock_irqrestore(&gpio_lock, flags); +	return -EINVAL; +} +EXPORT_SYMBOL(rdc_gpio_request); + +/* release previously-claimed GPIO */ +void rdc_gpio_free(unsigned gpio) +{ +	unsigned long flags; + +	if (!rdc321x_is_gpio(gpio)) +		return; + +	spin_lock_irqsave(&gpio_lock, flags); +	gpio_request_data[(gpio & 0x20) ? 1 : 0] &= ~(1 << (gpio & 0x1f)); +	spin_unlock_irqrestore(&gpio_lock, flags); +} +EXPORT_SYMBOL(rdc_gpio_free); + +/* read GPIO pin */ +int rdc_gpio_get_value(unsigned gpio) +{ +	u32 reg; +	unsigned long flags; + +	spin_lock_irqsave(&gpio_lock, flags); +	reg = rdc321x_conf_read(gpio < 32 +		? RDC321X_GPIO_DATA_REG1 : RDC321X_GPIO_DATA_REG2); +	spin_unlock_irqrestore(&gpio_lock, flags); + +	return (1 << (gpio & 0x1f)) & reg ? 1 : 0; +} +EXPORT_SYMBOL(rdc_gpio_get_value); + +/* set GPIO pin to value */ +void rdc_gpio_set_value(unsigned gpio, int value) +{ +	unsigned long flags; +	u32 reg; + +	reg = 1 << (gpio & 0x1f); +	if (gpio < 32) { +		spin_lock_irqsave(&gpio_lock, flags); +		if (value) +			gpio_data_reg1 |= reg; +		else +			gpio_data_reg1 &= ~reg; +		rdc321x_conf_write(RDC321X_GPIO_DATA_REG1, gpio_data_reg1); +		spin_unlock_irqrestore(&gpio_lock, flags); +	} else { +		spin_lock_irqsave(&gpio_lock, flags); +		if (value) +			gpio_data_reg2 |= reg; +		else +			gpio_data_reg2 &= ~reg; +		rdc321x_conf_write(RDC321X_GPIO_DATA_REG2, gpio_data_reg2); +		spin_unlock_irqrestore(&gpio_lock, flags); +	} +} +EXPORT_SYMBOL(rdc_gpio_set_value); + +/* configure GPIO pin as input */ +int rdc_gpio_direction_input(unsigned gpio) +{ +	if (!rdc321x_is_gpio(gpio)) +		return -EINVAL; + +	rdc321x_configure_gpio(gpio); + +	return 0; +} +EXPORT_SYMBOL(rdc_gpio_direction_input); + +/* configure GPIO pin as output and set value */ +int rdc_gpio_direction_output(unsigned gpio, int value) +{ +	if (!rdc321x_is_gpio(gpio)) +		return -EINVAL; + +	gpio_set_value(gpio, value); +	rdc321x_configure_gpio(gpio); + +	return 0; +} +EXPORT_SYMBOL(rdc_gpio_direction_output); + +arch_initcall(rdc321x_gpio_setup); diff --git a/target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/platform.c b/target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/platform.c new file mode 100644 index 000000000..9eb08c8dd --- /dev/null +++ b/target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/platform.c @@ -0,0 +1,264 @@ +/* + *  Generic RDC321x platform devices + * + *  Copyright (C) 2007-2008 OpenWrt.org + *  Copyright (C) 2007 Florian Fainelli <florian@openwrt.org> + *  Copyright (C) 2008 Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us> + * + *  This program is free software; you can redistribute it and/or + *  modify it under the terms of the GNU General Public License + *  as published by the Free Software Foundation; either version 2 + *  of the License, or (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the + *  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + *  Boston, MA  02110-1301, USA. + * + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/version.h> +#include <linux/leds.h> +#include <linux/gpio_keys.h> +#include <linux/input.h> +#include <linux/mtd/map.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/physmap.h> +#include <linux/root_dev.h> + +#include <asm/mach-rdc321x/gpio.h> + +/* Flash */ +#ifdef CONFIG_MTD_R8610 +#define CONFIG_MTD_RDC3210 1 +#elif defined CONFIG_MTD_RDC3210 +static struct resource rdc_flash_resource[] = { +	[0] = { +		.start = (u32)-CONFIG_MTD_RDC3210_SIZE, +		.end = (u32)-1, +		.flags = IORESOURCE_MEM, +	}, +}; + +static struct platform_device rdc_flash_device = { +	.name = "rdc321x-flash", +	.id = -1, +	.num_resources = ARRAY_SIZE(rdc_flash_resource), +	.resource = rdc_flash_resource, +}; +#else +static struct mtd_partition rdc_flash_parts[15]; + +static struct resource rdc_flash_resource = { +	.end = (u32)-1, +	.flags = IORESOURCE_MEM, +}; + +static struct physmap_flash_data rdc_flash_data = { +	.parts = rdc_flash_parts, +}; + +static struct platform_device rdc_flash_device = { +	.name = "physmap-flash", +	.id = -1, +	.resource = &rdc_flash_resource, +	.num_resources = 1, +	.dev.platform_data = &rdc_flash_data, +}; +#endif + +/* LEDS */ +static struct gpio_led default_leds[] = { +	{ .name = "rdc321x:dmz", .gpio = 1, }, +}; + +static struct gpio_led_platform_data rdc321x_led_data = { +	.num_leds = ARRAY_SIZE(default_leds), +	.leds = default_leds, +}; + +static struct platform_device rdc321x_leds = { +	.name = "leds-gpio", +	.id = -1, +	.dev = { +		.platform_data = &rdc321x_led_data, +	} +}; + +/* Watchdog */ +static struct platform_device rdc321x_wdt = { +	.name = "rdc321x-wdt", +	.id = -1, +	.num_resources = 0, +}; + +/* Button */ +static struct gpio_keys_button rdc321x_gpio_btn[] = { +	{ +		.gpio = 0, +		.code = BTN_0, +		.desc = "Reset", +		.active_low = 1, +	} +}; + +static struct gpio_keys_platform_data rdc321x_gpio_btn_data = { +	.buttons = rdc321x_gpio_btn, +	.nbuttons = ARRAY_SIZE(rdc321x_gpio_btn), +}; + +static struct platform_device rdc321x_button = { +	.name = "gpio-keys", +	.id = -1, +	.dev = { +		.platform_data = &rdc321x_gpio_btn_data, +	} +}; + +static struct platform_device *rdc321x_devs[] = { +	&rdc_flash_device, +	&rdc321x_leds, +	&rdc321x_wdt, +	&rdc321x_button, +}; + +static int probe_flash_start(struct map_info *the_map) +{ +	struct mtd_info *res; + +	the_map->virt = ioremap(the_map->phys, the_map->size); +	if (the_map->virt == NULL) +		return 1; +	for (the_map->bankwidth = 32; the_map->bankwidth; the_map->bankwidth +			>>= 1) { +		res = do_map_probe("cfi_probe", the_map); +		if (res == NULL) +			res = do_map_probe("jedec_probe", the_map); +		if (res != NULL) +			break; +	} +	iounmap(the_map->virt); +	if (res != NULL) +		the_map->phys = (u32)-(s32)(the_map->size = res->size); +	return res == NULL; +} + +static int __init rdc_board_setup(void) +{ +#ifndef CONFIG_MTD_RDC3210 +	struct map_info rdc_map_info; +	u32 the_header[4]; + +	ROOT_DEV = 0; +	rdc_map_info.name = rdc_flash_device.name; +	rdc_map_info.phys = 0xff000000; +	rdc_map_info.size = 0x1000000; +	rdc_map_info.bankwidth = 2; +	rdc_map_info.set_vpp = NULL; +	simple_map_init(&rdc_map_info); +	while (probe_flash_start(&rdc_map_info)) { +		rdc_map_info.phys++; +		if (--rdc_map_info.size) +			panic("Could not find start of flash!"); +	} +	rdc_flash_resource.start = rdc_map_info.phys; +	rdc_flash_data.width = rdc_map_info.bankwidth; +	rdc_map_info.virt = ioremap_nocache(rdc_map_info.phys, 0x10); +	if (rdc_map_info.virt == NULL) +		panic("Could not ioremap to read device magic!"); +	the_header[0] = ((u32 *)rdc_map_info.virt)[0]; +	the_header[1] = ((u32 *)rdc_map_info.virt)[1]; +	the_header[2] = ((u32 *)rdc_map_info.virt)[2]; +	the_header[3] = ((u32 *)rdc_map_info.virt)[3]; +	iounmap(rdc_map_info.virt); +	if (!memcmp(the_header, "GMTK", 4)) {	/* Gemtek */ +		/* TODO */ +	} else if (!memcmp(the_header, "CSYS", 4)) {	/* Sitecom */ +		/* TODO */ +	} else if (!memcmp(((u8 *)the_header) + 14, "Li", 2)) {	/* AMIT */ +		rdc_flash_parts[0].name = "kernel_parthdr"; +		rdc_flash_parts[0].offset = 0; +		rdc_flash_parts[0].size = 0x10; +		rdc_flash_parts[1].name = "kernel"; +		rdc_flash_parts[1].offset = 0x10; +		rdc_flash_parts[1].size = 0xffff0; +		rdc_flash_parts[2].name = "rootfs_parthdr"; +		rdc_flash_parts[2].offset = 0x100000; +		rdc_flash_parts[2].size = 0x10; +		rdc_flash_parts[3].name = "rootfs"; +		rdc_flash_parts[3].offset = 0x100010; +		rdc_flash_parts[3].size = rdc_map_info.size - 0x160010; +		rdc_flash_parts[4].name = "config_parthdr"; +		rdc_flash_parts[4].offset = rdc_map_info.size - 0x60000; +		rdc_flash_parts[4].size = 0x10; +		rdc_flash_parts[5].name = "config"; +		rdc_flash_parts[5].offset = rdc_map_info.size - 0x5fff0; +		rdc_flash_parts[5].size = 0xfff0; +		rdc_flash_parts[6].name = "recoveryfs_parthdr"; +		rdc_flash_parts[6].offset = rdc_map_info.size - 0x50000; +		rdc_flash_parts[6].size = 0x10; +		rdc_flash_parts[7].name = "recoveryfs"; +		rdc_flash_parts[7].offset = rdc_map_info.size - 0x4fff0; +		rdc_flash_parts[7].size = 0x3fff0; +		rdc_flash_parts[8].name = "recovery_parthdr"; +		rdc_flash_parts[8].offset = rdc_map_info.size - 0x10000; +		rdc_flash_parts[8].size = 0x10; +		rdc_flash_parts[9].name = "recovery"; +		rdc_flash_parts[9].offset = rdc_map_info.size - 0xfff0; +		rdc_flash_parts[9].size = 0x7ff0; +		rdc_flash_parts[10].name = "productinfo_parthdr"; +		rdc_flash_parts[10].offset = rdc_map_info.size - 0x8000; +		rdc_flash_parts[10].size = 0x10; +		rdc_flash_parts[11].name = "productinfo"; +		rdc_flash_parts[11].offset = rdc_map_info.size - 0x7ff0; +		rdc_flash_parts[11].size = 0x1ff0; +		rdc_flash_parts[12].name = "bootloader_parthdr"; +		rdc_flash_parts[12].offset = rdc_map_info.size - 0x6000; +		rdc_flash_parts[12].size = 0x10; +		rdc_flash_parts[13].name = "bootloader"; +		rdc_flash_parts[13].offset = rdc_map_info.size - 0x5ff0; +		rdc_flash_parts[13].size = 0x5ff0; +		rdc_flash_parts[14].name = "everything"; +		rdc_flash_parts[14].offset = 0; +		rdc_flash_parts[14].size = rdc_map_info.size; +		rdc_flash_data.nr_parts = 15; +	} else {	/* ZyXEL */ +		rdc_flash_parts[0].name = "kernel"; +		rdc_flash_parts[0].offset = 0; +		rdc_flash_parts[0].size = 0x100000; +		rdc_flash_parts[1].name = "rootfs"; +		rdc_flash_parts[1].offset = 0x100000; +		rdc_flash_parts[1].size = rdc_map_info.size - 0x140000; +		rdc_flash_parts[2].name = "linux"; +		rdc_flash_parts[2].offset = 0; +		rdc_flash_parts[2].size = rdc_map_info.size - 0x40000; +		rdc_flash_parts[3].name = "config"; +		rdc_flash_parts[3].offset = rdc_map_info.size - 0x40000; +		rdc_flash_parts[3].size = 0x10000; +		rdc_flash_parts[4].name = "productinfo"; +		rdc_flash_parts[4].offset = rdc_map_info.size - 0x30000; +		rdc_flash_parts[4].size = 0x10000; +		rdc_flash_parts[5].name = "bootloader"; +		rdc_flash_parts[5].offset = rdc_map_info.size - 0x20000; +		rdc_flash_parts[5].size = 0x20000; +		rdc_flash_data.nr_parts = 6; +	} +#endif +	return platform_add_devices(rdc321x_devs, ARRAY_SIZE(rdc321x_devs)); +} + +#ifdef CONFIG_MTD_RDC3210 +arch_initcall(rdc_board_setup); +#else +late_initcall(rdc_board_setup); +#endif diff --git a/target/linux/rdc/patches-2.6.30/002-platform_support.patch b/target/linux/rdc/patches-2.6.30/002-platform_support.patch new file mode 100644 index 000000000..74fa95dbe --- /dev/null +++ b/target/linux/rdc/patches-2.6.30/002-platform_support.patch @@ -0,0 +1,13 @@ +--- a/arch/x86/Makefile ++++ b/arch/x86/Makefile +@@ -124,6 +124,10 @@ core-y += $(fcore-y) + # Xen paravirtualization support + core-$(CONFIG_XEN) += arch/x86/xen/ +  ++# RDC R-321X support ++cflags-$(CONFIG_X86_RDC321X)  := -Iarch/x86/include/asm/mach-rdc321x ++core-$(CONFIG_X86_RDC321X)   += arch/x86/mach-rdc321x/ ++ + # lguest paravirtualization support + core-$(CONFIG_LGUEST_GUEST) += arch/x86/lguest/ +  | 
