diff options
| author | juhosg <juhosg@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-05-27 15:01:07 +0000 | 
|---|---|---|
| committer | juhosg <juhosg@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-05-27 15:01:07 +0000 | 
| commit | e17d6b07094e4c7d1ebbd92ee4e32deac4c9dc29 (patch) | |
| tree | 00b2f220c777b873989bec0ae6fc256ee48bb6e4 /target/linux/omap24xx/patches-3.1/200-omap-platform.patch | |
| parent | 4ea55a169b9832455bbd9ec3c99530640e130c73 (diff) | |
omap24xx: remove 3.1 support
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@31890 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/omap24xx/patches-3.1/200-omap-platform.patch')
| -rw-r--r-- | target/linux/omap24xx/patches-3.1/200-omap-platform.patch | 897 | 
1 files changed, 0 insertions, 897 deletions
diff --git a/target/linux/omap24xx/patches-3.1/200-omap-platform.patch b/target/linux/omap24xx/patches-3.1/200-omap-platform.patch deleted file mode 100644 index 9a2e9436f..000000000 --- a/target/linux/omap24xx/patches-3.1/200-omap-platform.patch +++ /dev/null @@ -1,897 +0,0 @@ ---- /dev/null -+++ b/arch/arm/plat-omap/bootreason.c -@@ -0,0 +1,79 @@ -+/* -+ * linux/arch/arm/plat-omap/bootreason.c -+ * -+ * OMAP Bootreason passing -+ * -+ * Copyright (c) 2004 Nokia -+ * -+ * Written by David Weinehall <david.weinehall@nokia.com> -+ * -+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN -+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * 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/proc_fs.h> -+#include <linux/errno.h> -+#include <plat/board.h> -+ -+static char boot_reason[16]; -+ -+static int omap_bootreason_read_proc(char *page, char **start, off_t off, -+					 int count, int *eof, void *data) -+{ -+	int len = 0; -+ -+	len += sprintf(page + len, "%s\n", boot_reason); -+ -+	*start = page + off; -+ -+	if (len > off) -+		len -= off; -+	else -+		len = 0; -+ -+	return len < count ? len  : count; -+} -+ -+static int __init bootreason_init(void) -+{ -+	const struct omap_boot_reason_config *cfg; -+	int reason_valid = 0; -+ -+	cfg = omap_get_config(OMAP_TAG_BOOT_REASON, struct omap_boot_reason_config); -+	if (cfg != NULL) { -+		strncpy(boot_reason, cfg->reason_str, sizeof(cfg->reason_str)); -+		boot_reason[sizeof(cfg->reason_str)] = 0; -+		reason_valid = 1; -+	} else { -+		/* Read the boot reason from the OMAP registers */ -+	} -+ -+	if (!reason_valid) -+		return -ENOENT; -+ -+	printk(KERN_INFO "Bootup reason: %s\n", boot_reason); -+ -+	if (!create_proc_read_entry("bootreason", S_IRUGO, NULL, -+					omap_bootreason_read_proc, NULL)) -+		return -ENOMEM; -+ -+	return 0; -+} -+ -+late_initcall(bootreason_init); ---- a/arch/arm/plat-omap/common.c -+++ b/arch/arm/plat-omap/common.c -@@ -21,18 +21,90 @@ - #include <plat/vram.h> - #include <plat/dsp.h> -  -+#include <asm/setup.h> -+ -  - #define NO_LENGTH_CHECK 0xffffffff -  - struct omap_board_config_kernel *omap_board_config __initdata; - int omap_board_config_size; -  -+unsigned char omap_bootloader_tag[1024]; -+int omap_bootloader_tag_len; -+ -+/* used by omap-smp.c and board-4430sdp.c */ -+void __iomem *gic_cpu_base_addr; -+ -+#ifdef CONFIG_OMAP_BOOT_TAG -+ -+static int __init parse_tag_omap(const struct tag *tag) -+{ -+	u32 size = tag->hdr.size - (sizeof(tag->hdr) >> 2); -+ -+        size <<= 2; -+	if (size > sizeof(omap_bootloader_tag)) -+		return -1; -+ -+	memcpy(omap_bootloader_tag, tag->u.omap.data, size); -+	omap_bootloader_tag_len = size; -+ -+        return 0; -+} -+ -+__tagtable(ATAG_BOARD, parse_tag_omap); -+ -+#endif -+ - static const void *__init get_config(u16 tag, size_t len, - 		int skip, size_t *len_out) - { - 	struct omap_board_config_kernel *kinfo = NULL; - 	int i; -  -+#ifdef CONFIG_OMAP_BOOT_TAG -+	struct omap_board_config_entry *info = NULL; -+ -+	if (omap_bootloader_tag_len > 4) -+		info = (struct omap_board_config_entry *) omap_bootloader_tag; -+	while (info != NULL) { -+		u8 *next; -+ -+		if (info->tag == tag) { -+			if (skip == 0) -+				break; -+			skip--; -+		} -+ -+		if ((info->len & 0x03) != 0) { -+			/* We bail out to avoid an alignment fault */ -+			printk(KERN_ERR "OMAP peripheral config: Length (%d) not word-aligned (tag %04x)\n", -+			       info->len, info->tag); -+			return NULL; -+		} -+		next = (u8 *) info + sizeof(*info) + info->len; -+		if (next >= omap_bootloader_tag + omap_bootloader_tag_len) -+			info = NULL; -+		else -+			info = (struct omap_board_config_entry *) next; -+	} -+	if (info != NULL) { -+		/* Check the length as a lame attempt to check for -+		 * binary inconsistency. */ -+		if (len != NO_LENGTH_CHECK) { -+			/* Word-align len */ -+			if (len & 0x03) -+				len = (len + 3) & ~0x03; -+			if (info->len != len) { -+				printk(KERN_ERR "OMAP peripheral config: Length mismatch with tag %x (want %d, got %d)\n", -+				       tag, len, info->len); -+				return NULL; -+			} -+		} -+		if (len_out != NULL) -+			*len_out = info->len; -+		return info->data; -+	} -+#endif - 	/* Try to find the config from the board-specific structures - 	 * in the kernel. */ - 	for (i = 0; i < omap_board_config_size; i++) { ---- /dev/null -+++ b/arch/arm/plat-omap/component-version.c -@@ -0,0 +1,64 @@ -+/* -+ *  linux/arch/arm/plat-omap/component-version.c -+ * -+ *  Copyright (C) 2005 Nokia Corporation -+ *  Written by Juha Yrjölä <juha.yrjola@nokia.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. -+ */ -+ -+#include <linux/init.h> -+#include <linux/module.h> -+#include <linux/err.h> -+#include <linux/proc_fs.h> -+#include <plat/board.h> -+ -+static int component_version_read_proc(char *page, char **start, off_t off, -+				       int count, int *eof, void *data) -+{ -+	int len, i; -+	const struct omap_version_config *ver; -+	char *p; -+ -+	i = 0; -+	p = page; -+	while ((ver = omap_get_nr_config(OMAP_TAG_VERSION_STR, -+					 struct omap_version_config, i)) != NULL) { -+		p += sprintf(p, "%-12s%s\n", ver->component, ver->version); -+		i++; -+	} -+ -+	len = (p - page) - off; -+	if (len < 0) -+		len = 0; -+ -+	*eof = (len <= count) ? 1 : 0; -+	*start = page + off; -+ -+	return len; -+} -+ -+static int __init component_version_init(void) -+{ -+	if (omap_get_config(OMAP_TAG_VERSION_STR, struct omap_version_config) == NULL) -+		return -ENODEV; -+	if (!create_proc_read_entry("component_version", S_IRUGO, NULL, -+				    component_version_read_proc, NULL)) -+		return -ENOMEM; -+ -+	return 0; -+} -+ -+static void __exit component_version_exit(void) -+{ -+	remove_proc_entry("component_version", NULL); -+} -+ -+late_initcall(component_version_init); -+module_exit(component_version_exit); -+ -+MODULE_AUTHOR("Juha Yrjölä <juha.yrjola@nokia.com>"); -+MODULE_DESCRIPTION("Component version driver"); -+MODULE_LICENSE("GPL"); ---- a/arch/arm/plat-omap/Kconfig -+++ b/arch/arm/plat-omap/Kconfig -@@ -82,6 +82,38 @@ config OMAP_RESET_CLOCKS - 	  probably do not want this option enabled until your - 	  device drivers work properly. -  -+config OMAP_BOOT_TAG -+	bool "OMAP bootloader information passing" -+        depends on ARCH_OMAP -+        default n -+        help -+          Say Y, if you have a bootloader which passes information -+          about your board and its peripheral configuration. -+ -+config OMAP_BOOT_REASON -+	bool "Support for boot reason" -+        depends on OMAP_BOOT_TAG -+        default n -+        help -+          Say Y, if you want to have a procfs entry for reading the boot -+          reason in user-space. -+ -+config OMAP_COMPONENT_VERSION -+	bool "Support for component version display" -+	depends on OMAP_BOOT_TAG && PROC_FS -+	default n -+	help -+	  Say Y, if you want to have a procfs entry for reading component -+	  versions (supplied by the bootloader) in user-space. -+ -+config OMAP_GPIO_SWITCH -+	bool "GPIO switch support" -+	help -+	  Say Y, if you want to have support for reporting of GPIO -+	  switches (e.g. cover switches) via sysfs. Your bootloader has -+	  to provide information about the switches to the kernel via the -+	  ATAG_BOARD mechanism if they're not defined by the board config. -+ - config OMAP_MUX - 	bool "OMAP multiplexing support" - 	depends on ARCH_OMAP ---- a/arch/arm/plat-omap/Makefile -+++ b/arch/arm/plat-omap/Makefile -@@ -23,6 +23,9 @@ obj-$(CONFIG_OMAP_IOMMU_DEBUG) += iommu- -  - obj-$(CONFIG_CPU_FREQ) += cpu-omap.o - obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o -+obj-$(CONFIG_OMAP_BOOT_REASON) += bootreason.o -+obj-$(CONFIG_OMAP_COMPONENT_VERSION) += component-version.o -+obj-$(CONFIG_OMAP_GPIO_SWITCH) += gpio-switch.o - obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o - obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o - i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o ---- a/arch/arm/include/asm/setup.h -+++ b/arch/arm/include/asm/setup.h -@@ -136,6 +136,13 @@ struct tag_acorn { - 	__u8 adfsdrives; - }; -  -+/* TI OMAP specific information */ -+#define ATAG_BOARD       0x414f4d50 -+ -+struct tag_omap { -+	u8 data[0]; -+}; -+ - /* footbridge memory clock, see arch/arm/mach-footbridge/arch.c */ - #define ATAG_MEMCLK	0x41000402 -  -@@ -162,6 +169,11 @@ struct tag { - 		struct tag_acorn	acorn; -  - 		/* -+		 * OMAP specific -+                 */ -+                struct tag_omap         omap; -+ -+		/* - 		 * DC21285 specific - 		 */ - 		struct tag_memclk	memclk; ---- /dev/null -+++ b/arch/arm/plat-omap/gpio-switch.c -@@ -0,0 +1,554 @@ -+/* -+ *  linux/arch/arm/plat-omap/gpio-switch.c -+ * -+ *  Copyright (C) 2004-2006 Nokia Corporation -+ *  Written by Juha Yrjölä <juha.yrjola@nokia.com> -+ *         and Paul Mundt <paul.mundt@nokia.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. -+ */ -+ -+#include <linux/sched.h> -+#include <linux/init.h> -+#include <linux/list.h> -+#include <linux/irq.h> -+#include <linux/interrupt.h> -+#include <linux/module.h> -+#include <linux/platform_device.h> -+#include <linux/timer.h> -+#include <linux/err.h> -+#include <linux/slab.h> -+#include <linux/gpio.h> -+#include <plat/hardware.h> -+#include <plat/irqs.h> -+#include <plat/mux.h> -+#include <plat/board.h> -+#include <plat/gpio-switch.h> -+ -+struct gpio_switch { -+	char		name[14]; -+	u16		gpio; -+	unsigned	flags:4; -+	unsigned	type:4; -+	unsigned	state:1; -+	unsigned	both_edges:1; -+ -+	u16		debounce_rising; -+	u16		debounce_falling; -+ -+	void (* notify)(void *data, int state); -+	void *notify_data; -+ -+	struct work_struct	work; -+	struct timer_list	timer; -+	struct platform_device	pdev; -+ -+	struct list_head	node; -+}; -+ -+static LIST_HEAD(gpio_switches); -+static struct platform_device *gpio_sw_platform_dev; -+static struct platform_driver gpio_sw_driver; -+ -+static const struct omap_gpio_switch *board_gpio_sw_table; -+static int board_gpio_sw_count; -+ -+static const char *cover_str[2] = { "open", "closed" }; -+static const char *connection_str[2] = { "disconnected", "connected" }; -+static const char *activity_str[2] = { "inactive", "active" }; -+ -+/* -+ * GPIO switch state default debounce delay in ms -+ */ -+#define OMAP_GPIO_SW_DEFAULT_DEBOUNCE		10 -+ -+static const char **get_sw_str(struct gpio_switch *sw) -+{ -+	switch (sw->type) { -+	case OMAP_GPIO_SWITCH_TYPE_COVER: -+		return cover_str; -+	case OMAP_GPIO_SWITCH_TYPE_CONNECTION: -+		return connection_str; -+	case OMAP_GPIO_SWITCH_TYPE_ACTIVITY: -+		return activity_str; -+	default: -+		BUG(); -+		return NULL; -+	} -+} -+ -+static const char *get_sw_type(struct gpio_switch *sw) -+{ -+	switch (sw->type) { -+	case OMAP_GPIO_SWITCH_TYPE_COVER: -+		return "cover"; -+	case OMAP_GPIO_SWITCH_TYPE_CONNECTION: -+		return "connection"; -+	case OMAP_GPIO_SWITCH_TYPE_ACTIVITY: -+		return "activity"; -+	default: -+		BUG(); -+		return NULL; -+	} -+} -+ -+static void print_sw_state(struct gpio_switch *sw, int state) -+{ -+	const char **str; -+ -+	str = get_sw_str(sw); -+	if (str != NULL) -+		printk(KERN_INFO "%s (GPIO %d) is now %s\n", sw->name, sw->gpio, str[state]); -+} -+ -+static int gpio_sw_get_state(struct gpio_switch *sw) -+{ -+	int state; -+ -+	state = gpio_get_value(sw->gpio); -+	if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED) -+		state = !state; -+ -+	return state; -+} -+ -+static ssize_t gpio_sw_state_store(struct device *dev, -+				   struct device_attribute *attr, -+				   const char *buf, -+				   size_t count) -+{ -+	struct gpio_switch *sw = dev_get_drvdata(dev); -+	const char **str; -+	char state[16]; -+	int enable; -+ -+	if (!(sw->flags & OMAP_GPIO_SWITCH_FLAG_OUTPUT)) -+		return -EPERM; -+ -+	if (sscanf(buf, "%15s", state) != 1) -+		return -EINVAL; -+ -+	str = get_sw_str(sw); -+	if (strcmp(state, str[0]) == 0) -+		sw->state = enable = 0; -+	else if (strcmp(state, str[1]) == 0) -+		sw->state = enable = 1; -+	else -+		return -EINVAL; -+ -+	if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED) -+		enable = !enable; -+	gpio_set_value(sw->gpio, enable); -+ -+	return count; -+} -+ -+static ssize_t gpio_sw_state_show(struct device *dev, -+				  struct device_attribute *attr, -+				  char *buf) -+{ -+	struct gpio_switch *sw = dev_get_drvdata(dev); -+	const char **str; -+ -+	str = get_sw_str(sw); -+	return sprintf(buf, "%s\n", str[sw->state]); -+} -+ -+static DEVICE_ATTR(state, S_IRUGO | S_IWUSR, gpio_sw_state_show, -+		   gpio_sw_state_store); -+ -+static ssize_t gpio_sw_type_show(struct device *dev, -+				 struct device_attribute *attr, -+				 char *buf) -+{ -+	struct gpio_switch *sw = dev_get_drvdata(dev); -+ -+	return sprintf(buf, "%s\n", get_sw_type(sw)); -+} -+ -+static DEVICE_ATTR(type, S_IRUGO, gpio_sw_type_show, NULL); -+ -+static ssize_t gpio_sw_direction_show(struct device *dev, -+				      struct device_attribute *attr, -+				      char *buf) -+{ -+	struct gpio_switch *sw = dev_get_drvdata(dev); -+	int is_output; -+ -+	is_output = sw->flags & OMAP_GPIO_SWITCH_FLAG_OUTPUT; -+	return sprintf(buf, "%s\n", is_output ? "output" : "input"); -+} -+ -+static DEVICE_ATTR(direction, S_IRUGO, gpio_sw_direction_show, NULL); -+ -+ -+static irqreturn_t gpio_sw_irq_handler(int irq, void *arg) -+{ -+	struct gpio_switch *sw = arg; -+	unsigned long timeout; -+	int state; -+ -+	if (!sw->both_edges) { -+		if (gpio_get_value(sw->gpio)) -+			irq_set_irq_type(OMAP_GPIO_IRQ(sw->gpio), IRQ_TYPE_EDGE_FALLING); -+		else -+			irq_set_irq_type(OMAP_GPIO_IRQ(sw->gpio), IRQ_TYPE_EDGE_RISING); -+	} -+ -+	state = gpio_sw_get_state(sw); -+	if (sw->state == state) -+		return IRQ_HANDLED; -+ -+	if (state) -+		timeout = sw->debounce_rising; -+	else -+		timeout = sw->debounce_falling; -+	if (!timeout) -+		schedule_work(&sw->work); -+	else -+		mod_timer(&sw->timer, jiffies + msecs_to_jiffies(timeout)); -+ -+	return IRQ_HANDLED; -+} -+ -+static void gpio_sw_timer(unsigned long arg) -+{ -+	struct gpio_switch *sw = (struct gpio_switch *) arg; -+ -+	schedule_work(&sw->work); -+} -+ -+static void gpio_sw_handler(struct work_struct *work) -+{ -+	struct gpio_switch *sw = container_of(work, struct gpio_switch, work); -+	int state; -+ -+	state = gpio_sw_get_state(sw); -+	if (sw->state == state) -+		return; -+ -+	sw->state = state; -+	if (sw->notify != NULL) -+		sw->notify(sw->notify_data, state); -+	sysfs_notify(&sw->pdev.dev.kobj, NULL, "state"); -+	print_sw_state(sw, state); -+} -+ -+static int __init can_do_both_edges(struct gpio_switch *sw) -+{ -+	if (!cpu_class_is_omap1()) -+		return 1; -+	if (OMAP_GPIO_IS_MPUIO(sw->gpio)) -+		return 0; -+	else -+		return 1; -+} -+ -+static void gpio_sw_release(struct device *dev) -+{ -+} -+ -+static int __init new_switch(struct gpio_switch *sw) -+{ -+	int r, direction, trigger; -+ -+	switch (sw->type) { -+	case OMAP_GPIO_SWITCH_TYPE_COVER: -+	case OMAP_GPIO_SWITCH_TYPE_CONNECTION: -+	case OMAP_GPIO_SWITCH_TYPE_ACTIVITY: -+		break; -+	default: -+		printk(KERN_ERR "invalid GPIO switch type: %d\n", sw->type); -+		return -EINVAL; -+	} -+ -+	sw->pdev.name	= sw->name; -+	sw->pdev.id	= -1; -+ -+	sw->pdev.dev.parent = &gpio_sw_platform_dev->dev; -+	sw->pdev.dev.driver = &gpio_sw_driver.driver; -+	sw->pdev.dev.release = gpio_sw_release; -+ -+	r = platform_device_register(&sw->pdev); -+	if (r) { -+		printk(KERN_ERR "gpio-switch: platform device registration " -+		       "failed for %s", sw->name); -+		return r; -+	} -+	dev_set_drvdata(&sw->pdev.dev, sw); -+ -+	r = gpio_request(sw->gpio, "gpio-switch"); -+	if (r < 0) { -+		platform_device_unregister(&sw->pdev); -+		return r; -+	} -+ -+	/* input: 1, output: 0 */ -+	direction = !(sw->flags & OMAP_GPIO_SWITCH_FLAG_OUTPUT); -+	if (direction) -+		gpio_direction_input(sw->gpio); -+	else -+		gpio_direction_output(sw->gpio, 0); -+ -+	sw->state = gpio_sw_get_state(sw); -+ -+	r = 0; -+	r |= device_create_file(&sw->pdev.dev, &dev_attr_state); -+	r |= device_create_file(&sw->pdev.dev, &dev_attr_type); -+	r |= device_create_file(&sw->pdev.dev, &dev_attr_direction); -+	if (r) -+		printk(KERN_ERR "gpio-switch: attribute file creation " -+		       "failed for %s\n", sw->name); -+ -+	if (!direction) -+		return 0; -+ -+	if (can_do_both_edges(sw)) { -+		trigger = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING; -+		sw->both_edges = 1; -+	} else { -+		if (gpio_get_value(sw->gpio)) -+			trigger = IRQF_TRIGGER_FALLING; -+		else -+			trigger = IRQF_TRIGGER_RISING; -+	} -+	r = request_irq(OMAP_GPIO_IRQ(sw->gpio), gpio_sw_irq_handler, -+			IRQF_SHARED | trigger, sw->name, sw); -+	if (r < 0) { -+		printk(KERN_ERR "gpio-switch: request_irq() failed " -+		       "for GPIO %d\n", sw->gpio); -+		platform_device_unregister(&sw->pdev); -+		gpio_free(sw->gpio); -+		return r; -+	} -+ -+	INIT_WORK(&sw->work, gpio_sw_handler); -+	init_timer(&sw->timer); -+ -+	sw->timer.function = gpio_sw_timer; -+	sw->timer.data = (unsigned long)sw; -+ -+	list_add(&sw->node, &gpio_switches); -+ -+	return 0; -+} -+ -+static int __init add_atag_switches(void) -+{ -+	const struct omap_gpio_switch_config *cfg; -+	struct gpio_switch *sw; -+	int i, r; -+ -+	for (i = 0; ; i++) { -+		cfg = omap_get_nr_config(OMAP_TAG_GPIO_SWITCH, -+					 struct omap_gpio_switch_config, i); -+		if (cfg == NULL) -+			break; -+		sw = kzalloc(sizeof(*sw), GFP_KERNEL); -+		if (sw == NULL) { -+			printk(KERN_ERR "gpio-switch: kmalloc failed\n"); -+			return -ENOMEM; -+		} -+		strncpy(sw->name, cfg->name, sizeof(cfg->name)); -+		sw->gpio = cfg->gpio; -+		sw->flags = cfg->flags; -+		sw->type = cfg->type; -+		sw->debounce_rising = OMAP_GPIO_SW_DEFAULT_DEBOUNCE; -+		sw->debounce_falling = OMAP_GPIO_SW_DEFAULT_DEBOUNCE; -+		if ((r = new_switch(sw)) < 0) { -+			kfree(sw); -+			return r; -+		} -+	} -+	return 0; -+} -+ -+static struct gpio_switch * __init find_switch(int gpio, const char *name) -+{ -+	struct gpio_switch *sw; -+ -+	list_for_each_entry(sw, &gpio_switches, node) { -+		if ((gpio < 0 || sw->gpio != gpio) && -+		    (name == NULL || strcmp(sw->name, name) != 0)) -+			continue; -+ -+		if (gpio < 0 || name == NULL) -+			goto no_check; -+ -+		if (strcmp(sw->name, name) != 0) -+			printk("gpio-switch: name mismatch for %d (%s, %s)\n", -+			       gpio, name, sw->name); -+		else if (sw->gpio != gpio) -+			printk("gpio-switch: GPIO mismatch for %s (%d, %d)\n", -+			       name, gpio, sw->gpio); -+no_check: -+		return sw; -+	} -+	return NULL; -+} -+ -+static int __init add_board_switches(void) -+{ -+	int i; -+ -+	for (i = 0; i < board_gpio_sw_count; i++) { -+		const struct omap_gpio_switch *cfg; -+		struct gpio_switch *sw; -+		int r; -+ -+		cfg = board_gpio_sw_table + i; -+		if (strlen(cfg->name) > sizeof(sw->name) - 1) -+			return -EINVAL; -+		/* Check whether we only update an existing switch -+		 * or add a new switch. */ -+		sw = find_switch(cfg->gpio, cfg->name); -+		if (sw != NULL) { -+			sw->debounce_rising = cfg->debounce_rising; -+			sw->debounce_falling = cfg->debounce_falling; -+			sw->notify = cfg->notify; -+			sw->notify_data = cfg->notify_data; -+			continue; -+		} else { -+			if (cfg->gpio < 0 || cfg->name == NULL) { -+				printk("gpio-switch: required switch not " -+				       "found (%d, %s)\n", cfg->gpio, -+				       cfg->name); -+				continue; -+			} -+		} -+		sw = kzalloc(sizeof(*sw), GFP_KERNEL); -+		if (sw == NULL) { -+			printk(KERN_ERR "gpio-switch: kmalloc failed\n"); -+			return -ENOMEM; -+		} -+		strlcpy(sw->name, cfg->name, sizeof(sw->name)); -+		sw->gpio = cfg->gpio; -+		sw->flags = cfg->flags; -+		sw->type = cfg->type; -+		sw->debounce_rising = cfg->debounce_rising; -+		sw->debounce_falling = cfg->debounce_falling; -+		sw->notify = cfg->notify; -+		sw->notify_data = cfg->notify_data; -+		if ((r = new_switch(sw)) < 0) { -+			kfree(sw); -+			return r; -+		} -+	} -+	return 0; -+} -+ -+static void gpio_sw_cleanup(void) -+{ -+	struct gpio_switch *sw = NULL, *old = NULL; -+ -+	list_for_each_entry(sw, &gpio_switches, node) { -+		if (old != NULL) -+			kfree(old); -+		flush_scheduled_work(); -+		del_timer_sync(&sw->timer); -+ -+		free_irq(OMAP_GPIO_IRQ(sw->gpio), sw); -+ -+		device_remove_file(&sw->pdev.dev, &dev_attr_state); -+		device_remove_file(&sw->pdev.dev, &dev_attr_type); -+		device_remove_file(&sw->pdev.dev, &dev_attr_direction); -+ -+		platform_device_unregister(&sw->pdev); -+		gpio_free(sw->gpio); -+		old = sw; -+	} -+	kfree(old); -+} -+ -+static void __init report_initial_state(void) -+{ -+	struct gpio_switch *sw; -+ -+	list_for_each_entry(sw, &gpio_switches, node) { -+		int state; -+ -+		state = gpio_get_value(sw->gpio); -+		if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED) -+			state = !state; -+		if (sw->notify != NULL) -+			sw->notify(sw->notify_data, state); -+		print_sw_state(sw, state); -+	} -+} -+ -+static int gpio_sw_remove(struct platform_device *dev) -+{ -+	return 0; -+} -+ -+static struct platform_driver gpio_sw_driver = { -+	.remove		= gpio_sw_remove, -+	.driver		= { -+		.name	= "gpio-switch", -+	}, -+}; -+ -+void __init omap_register_gpio_switches(const struct omap_gpio_switch *tbl, -+					int count) -+{ -+	BUG_ON(board_gpio_sw_table != NULL); -+ -+	board_gpio_sw_table = tbl; -+	board_gpio_sw_count = count; -+} -+ -+static int __init gpio_sw_init(void) -+{ -+	int r; -+ -+	printk(KERN_INFO "OMAP GPIO switch handler initializing\n"); -+ -+	r = platform_driver_register(&gpio_sw_driver); -+	if (r) -+		return r; -+ -+	gpio_sw_platform_dev = platform_device_register_simple("gpio-switch", -+							       -1, NULL, 0); -+	if (IS_ERR(gpio_sw_platform_dev)) { -+		r = PTR_ERR(gpio_sw_platform_dev); -+		goto err1; -+	} -+ -+	r = add_atag_switches(); -+	if (r < 0) -+		goto err2; -+ -+	r = add_board_switches(); -+	if (r < 0) -+		goto err2; -+ -+	report_initial_state(); -+ -+	return 0; -+err2: -+	gpio_sw_cleanup(); -+	platform_device_unregister(gpio_sw_platform_dev); -+err1: -+	platform_driver_unregister(&gpio_sw_driver); -+	return r; -+} -+ -+static void __exit gpio_sw_exit(void) -+{ -+	gpio_sw_cleanup(); -+	platform_device_unregister(gpio_sw_platform_dev); -+	platform_driver_unregister(&gpio_sw_driver); -+} -+ -+#ifndef MODULE -+late_initcall(gpio_sw_init); -+#else -+module_init(gpio_sw_init); -+#endif -+module_exit(gpio_sw_exit); -+ -+MODULE_AUTHOR("Juha Yrjölä <juha.yrjola@nokia.com>, Paul Mundt <paul.mundt@nokia.com"); -+MODULE_DESCRIPTION("GPIO switch driver"); -+MODULE_LICENSE("GPL"); ---- a/arch/arm/plat-omap/include/plat/board.h -+++ b/arch/arm/plat-omap/include/plat/board.h -@@ -151,6 +151,14 @@ struct omap_board_config_kernel { - 	const void *data; - }; -  -+struct omap_gpio_switch_config { -+	char name[12]; -+	u16 gpio; -+	int flags:4; -+	int type:4; -+	int key_code:24; /* Linux key code */ -+}; -+ - extern const void *__init __omap_get_config(u16 tag, size_t len, int nr); -  - #define omap_get_config(tag, type) \  | 
