diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-10-25 08:19:59 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-10-25 08:19:59 +0100 |
commit | bdf4e9482360a3ddc1619efbd5d1c928ede8c3fa (patch) | |
tree | b02319e809c5b8abfca85409a11472775e27f597 /arch/arm/mach-sa1100 | |
parent | 06afb1a087d49ae0f676b2e5b9ffe5f4b3aba355 (diff) | |
parent | eb0474544bc16a9dab53b26abd846e86ba814eb1 (diff) | |
download | blackbird-op-linux-bdf4e9482360a3ddc1619efbd5d1c928ede8c3fa.tar.gz blackbird-op-linux-bdf4e9482360a3ddc1619efbd5d1c928ede8c3fa.zip |
Merge branch 'misc' into for-linus
Conflicts:
arch/arm/mach-integrator/integrator_ap.c
Diffstat (limited to 'arch/arm/mach-sa1100')
-rw-r--r-- | arch/arm/mach-sa1100/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/Makefile.boot | 5 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/assabet.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/include/mach/simpad.h | 94 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/leds-simpad.c | 100 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/leds.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/leds.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/simpad.c | 213 |
8 files changed, 263 insertions, 156 deletions
diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile index 41252d22e659..00631787e80a 100644 --- a/arch/arm/mach-sa1100/Makefile +++ b/arch/arm/mach-sa1100/Makefile @@ -45,7 +45,6 @@ obj-$(CONFIG_SA1100_PLEB) += pleb.o obj-$(CONFIG_SA1100_SHANNON) += shannon.o obj-$(CONFIG_SA1100_SIMPAD) += simpad.o -led-$(CONFIG_SA1100_SIMPAD) += leds-simpad.o # LEDs support obj-$(CONFIG_LEDS) += $(led-y) diff --git a/arch/arm/mach-sa1100/Makefile.boot b/arch/arm/mach-sa1100/Makefile.boot index a56ad0417cf2..5a616f6e5612 100644 --- a/arch/arm/mach-sa1100/Makefile.boot +++ b/arch/arm/mach-sa1100/Makefile.boot @@ -1,6 +1,7 @@ - zreladdr-y := 0xc0008000 ifeq ($(CONFIG_ARCH_SA1100),y) - zreladdr-$(CONFIG_SA1111) := 0xc0208000 + zreladdr-$(CONFIG_SA1111) += 0xc0208000 +else + zreladdr-y += 0xc0008000 endif params_phys-y := 0xc0000100 initrd_phys-y := 0xc0800000 diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index 26257df19b63..6290ce28b883 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -301,8 +301,7 @@ static void __init get_assabet_scr(void) } static void __init -fixup_assabet(struct machine_desc *desc, struct tag *tags, - char **cmdline, struct meminfo *mi) +fixup_assabet(struct tag *tags, char **cmdline, struct meminfo *mi) { /* This must be done before any call to machine_has_neponset() */ map_sa1100_gpio_regs(); diff --git a/arch/arm/mach-sa1100/include/mach/simpad.h b/arch/arm/mach-sa1100/include/mach/simpad.h index 9296c4513ce1..db28118103eb 100644 --- a/arch/arm/mach-sa1100/include/mach/simpad.h +++ b/arch/arm/mach-sa1100/include/mach/simpad.h @@ -48,32 +48,80 @@ #define GPIO_SMART_CARD GPIO_GPIO10 #define IRQ_GPIO_SMARD_CARD IRQ_GPIO10 -// CS3 Latch is write only, a shadow is necessary +/*--- ucb1x00 GPIO ---*/ +#define SIMPAD_UCB1X00_GPIO_BASE (GPIO_MAX + 1) +#define SIMPAD_UCB1X00_GPIO_PROG1 (SIMPAD_UCB1X00_GPIO_BASE) +#define SIMPAD_UCB1X00_GPIO_PROG2 (SIMPAD_UCB1X00_GPIO_BASE + 1) +#define SIMPAD_UCB1X00_GPIO_UP (SIMPAD_UCB1X00_GPIO_BASE + 2) +#define SIMPAD_UCB1X00_GPIO_DOWN (SIMPAD_UCB1X00_GPIO_BASE + 3) +#define SIMPAD_UCB1X00_GPIO_LEFT (SIMPAD_UCB1X00_GPIO_BASE + 4) +#define SIMPAD_UCB1X00_GPIO_RIGHT (SIMPAD_UCB1X00_GPIO_BASE + 5) +#define SIMPAD_UCB1X00_GPIO_6 (SIMPAD_UCB1X00_GPIO_BASE + 6) +#define SIMPAD_UCB1X00_GPIO_7 (SIMPAD_UCB1X00_GPIO_BASE + 7) +#define SIMPAD_UCB1X00_GPIO_HEADSET (SIMPAD_UCB1X00_GPIO_BASE + 8) +#define SIMPAD_UCB1X00_GPIO_SPEAKER (SIMPAD_UCB1X00_GPIO_BASE + 9) + +/*--- CS3 Latch ---*/ +#define SIMPAD_CS3_GPIO_BASE (GPIO_MAX + 11) +#define SIMPAD_CS3_VCC_5V_EN (SIMPAD_CS3_GPIO_BASE) +#define SIMPAD_CS3_VCC_3V_EN (SIMPAD_CS3_GPIO_BASE + 1) +#define SIMPAD_CS3_EN1 (SIMPAD_CS3_GPIO_BASE + 2) +#define SIMPAD_CS3_EN0 (SIMPAD_CS3_GPIO_BASE + 3) +#define SIMPAD_CS3_DISPLAY_ON (SIMPAD_CS3_GPIO_BASE + 4) +#define SIMPAD_CS3_PCMCIA_BUFF_DIS (SIMPAD_CS3_GPIO_BASE + 5) +#define SIMPAD_CS3_MQ_RESET (SIMPAD_CS3_GPIO_BASE + 6) +#define SIMPAD_CS3_PCMCIA_RESET (SIMPAD_CS3_GPIO_BASE + 7) +#define SIMPAD_CS3_DECT_POWER_ON (SIMPAD_CS3_GPIO_BASE + 8) +#define SIMPAD_CS3_IRDA_SD (SIMPAD_CS3_GPIO_BASE + 9) +#define SIMPAD_CS3_RS232_ON (SIMPAD_CS3_GPIO_BASE + 10) +#define SIMPAD_CS3_SD_MEDIAQ (SIMPAD_CS3_GPIO_BASE + 11) +#define SIMPAD_CS3_LED2_ON (SIMPAD_CS3_GPIO_BASE + 12) +#define SIMPAD_CS3_IRDA_MODE (SIMPAD_CS3_GPIO_BASE + 13) +#define SIMPAD_CS3_ENABLE_5V (SIMPAD_CS3_GPIO_BASE + 14) +#define SIMPAD_CS3_RESET_SIMCARD (SIMPAD_CS3_GPIO_BASE + 15) + +#define SIMPAD_CS3_PCMCIA_BVD1 (SIMPAD_CS3_GPIO_BASE + 16) +#define SIMPAD_CS3_PCMCIA_BVD2 (SIMPAD_CS3_GPIO_BASE + 17) +#define SIMPAD_CS3_PCMCIA_VS1 (SIMPAD_CS3_GPIO_BASE + 18) +#define SIMPAD_CS3_PCMCIA_VS2 (SIMPAD_CS3_GPIO_BASE + 19) +#define SIMPAD_CS3_LOCK_IND (SIMPAD_CS3_GPIO_BASE + 20) +#define SIMPAD_CS3_CHARGING_STATE (SIMPAD_CS3_GPIO_BASE + 21) +#define SIMPAD_CS3_PCMCIA_SHORT (SIMPAD_CS3_GPIO_BASE + 22) +#define SIMPAD_CS3_GPIO_23 (SIMPAD_CS3_GPIO_BASE + 23) -#define CS3BUSTYPE unsigned volatile long #define CS3_BASE 0xf1000000 -#define VCC_5V_EN 0x0001 // For 5V PCMCIA -#define VCC_3V_EN 0x0002 // FOR 3.3V PCMCIA -#define EN1 0x0004 // This is only for EPROM's -#define EN0 0x0008 // Both should be enable for 3.3V or 5V -#define DISPLAY_ON 0x0010 -#define PCMCIA_BUFF_DIS 0x0020 -#define MQ_RESET 0x0040 -#define PCMCIA_RESET 0x0080 -#define DECT_POWER_ON 0x0100 -#define IRDA_SD 0x0200 // Shutdown for powersave -#define RS232_ON 0x0400 -#define SD_MEDIAQ 0x0800 // Shutdown for powersave -#define LED2_ON 0x1000 -#define IRDA_MODE 0x2000 // Fast/Slow IrDA mode -#define ENABLE_5V 0x4000 // Enable 5V circuit -#define RESET_SIMCARD 0x8000 - -#define RS232_ENABLE 0x0440 -#define PCMCIAMASK 0x402f - - +long simpad_get_cs3_ro(void); +long simpad_get_cs3_shadow(void); +void simpad_set_cs3_bit(int value); +void simpad_clear_cs3_bit(int value); + +#define VCC_5V_EN 0x0001 /* For 5V PCMCIA */ +#define VCC_3V_EN 0x0002 /* FOR 3.3V PCMCIA */ +#define EN1 0x0004 /* This is only for EPROM's */ +#define EN0 0x0008 /* Both should be enable for 3.3V or 5V */ +#define DISPLAY_ON 0x0010 +#define PCMCIA_BUFF_DIS 0x0020 +#define MQ_RESET 0x0040 +#define PCMCIA_RESET 0x0080 +#define DECT_POWER_ON 0x0100 +#define IRDA_SD 0x0200 /* Shutdown for powersave */ +#define RS232_ON 0x0400 +#define SD_MEDIAQ 0x0800 /* Shutdown for powersave */ +#define LED2_ON 0x1000 +#define IRDA_MODE 0x2000 /* Fast/Slow IrDA mode */ +#define ENABLE_5V 0x4000 /* Enable 5V circuit */ +#define RESET_SIMCARD 0x8000 + +#define PCMCIA_BVD1 0x01 +#define PCMCIA_BVD2 0x02 +#define PCMCIA_VS1 0x04 +#define PCMCIA_VS2 0x08 +#define LOCK_IND 0x10 +#define CHARGING_STATE 0x20 +#define PCMCIA_SHORT 0x40 + +/*--- Battery ---*/ struct simpad_battery { unsigned char ac_status; /* line connected yes/no */ unsigned char status; /* battery loading yes/no */ diff --git a/arch/arm/mach-sa1100/leds-simpad.c b/arch/arm/mach-sa1100/leds-simpad.c deleted file mode 100644 index d50f4eeaa12e..000000000000 --- a/arch/arm/mach-sa1100/leds-simpad.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * linux/arch/arm/mach-sa1100/leds-simpad.c - * - * Author: Juergen Messerer <juergen.messerer@siemens.ch> - */ -#include <linux/init.h> - -#include <mach/hardware.h> -#include <asm/leds.h> -#include <asm/system.h> -#include <mach/simpad.h> - -#include "leds.h" - - -#define LED_STATE_ENABLED 1 -#define LED_STATE_CLAIMED 2 - -static unsigned int led_state; -static unsigned int hw_led_state; - -#define LED_GREEN (1) -#define LED_MASK (1) - -extern void set_cs3_bit(int value); -extern void clear_cs3_bit(int value); - -void simpad_leds_event(led_event_t evt) -{ - switch (evt) - { - case led_start: - hw_led_state = LED_GREEN; - led_state = LED_STATE_ENABLED; - break; - - case led_stop: - led_state &= ~LED_STATE_ENABLED; - break; - - case led_claim: - led_state |= LED_STATE_CLAIMED; - hw_led_state = LED_GREEN; - break; - - case led_release: - led_state &= ~LED_STATE_CLAIMED; - hw_led_state = LED_GREEN; - break; - -#ifdef CONFIG_LEDS_TIMER - case led_timer: - if (!(led_state & LED_STATE_CLAIMED)) - hw_led_state ^= LED_GREEN; - break; -#endif - -#ifdef CONFIG_LEDS_CPU - case led_idle_start: - break; - - case led_idle_end: - break; -#endif - - case led_halted: - break; - - case led_green_on: - if (led_state & LED_STATE_CLAIMED) - hw_led_state |= LED_GREEN; - break; - - case led_green_off: - if (led_state & LED_STATE_CLAIMED) - hw_led_state &= ~LED_GREEN; - break; - - case led_amber_on: - break; - - case led_amber_off: - break; - - case led_red_on: - break; - - case led_red_off: - break; - - default: - break; - } - - if (led_state & LED_STATE_ENABLED) - set_cs3_bit(LED2_ON); - else - clear_cs3_bit(LED2_ON); -} - diff --git a/arch/arm/mach-sa1100/leds.c b/arch/arm/mach-sa1100/leds.c index bbfe197fb4d6..5fe71a0f1053 100644 --- a/arch/arm/mach-sa1100/leds.c +++ b/arch/arm/mach-sa1100/leds.c @@ -42,8 +42,6 @@ sa1100_leds_init(void) leds_event = adsbitsy_leds_event; if (machine_is_pt_system3()) leds_event = system3_leds_event; - if (machine_is_simpad()) - leds_event = simpad_leds_event; /* what about machine registry? including led, apm... -zecke */ leds_event(led_start); return 0; diff --git a/arch/arm/mach-sa1100/leds.h b/arch/arm/mach-sa1100/leds.h index 68cc9f773d6d..776b6020f550 100644 --- a/arch/arm/mach-sa1100/leds.h +++ b/arch/arm/mach-sa1100/leds.h @@ -11,4 +11,3 @@ extern void pfs168_leds_event(led_event_t evt); extern void graphicsmaster_leds_event(led_event_t evt); extern void adsbitsy_leds_event(led_event_t evt); extern void system3_leds_event(led_event_t evt); -extern void simpad_leds_event(led_event_t evt); diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c index cfb76077bd25..34659f354bef 100644 --- a/arch/arm/mach-sa1100/simpad.c +++ b/arch/arm/mach-sa1100/simpad.c @@ -13,6 +13,7 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/io.h> +#include <linux/gpio.h> #include <asm/irq.h> #include <mach/hardware.h> @@ -28,35 +29,92 @@ #include <linux/serial_core.h> #include <linux/ioport.h> +#include <linux/input.h> +#include <linux/gpio_keys.h> +#include <linux/leds.h> +#include <linux/i2c-gpio.h> #include "generic.h" -long cs3_shadow; +/* + * CS3 support + */ -long get_cs3_shadow(void) +static long cs3_shadow; +static spinlock_t cs3_lock; +static struct gpio_chip cs3_gpio; + +long simpad_get_cs3_ro(void) +{ + return readl(CS3_BASE); +} +EXPORT_SYMBOL(simpad_get_cs3_ro); + +long simpad_get_cs3_shadow(void) { return cs3_shadow; } +EXPORT_SYMBOL(simpad_get_cs3_shadow); -void set_cs3(long value) +static void __simpad_write_cs3(void) { - *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow = value; + writel(cs3_shadow, CS3_BASE); } -void set_cs3_bit(int value) +void simpad_set_cs3_bit(int value) { + unsigned long flags; + + spin_lock_irqsave(&cs3_lock, flags); cs3_shadow |= value; - *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow; + __simpad_write_cs3(); + spin_unlock_irqrestore(&cs3_lock, flags); } +EXPORT_SYMBOL(simpad_set_cs3_bit); -void clear_cs3_bit(int value) +void simpad_clear_cs3_bit(int value) { + unsigned long flags; + + spin_lock_irqsave(&cs3_lock, flags); cs3_shadow &= ~value; - *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow; + __simpad_write_cs3(); + spin_unlock_irqrestore(&cs3_lock, flags); } +EXPORT_SYMBOL(simpad_clear_cs3_bit); + +static void cs3_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + if (offset > 15) + return; + if (value) + simpad_set_cs3_bit(1 << offset); + else + simpad_clear_cs3_bit(1 << offset); +}; + +static int cs3_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + if (offset > 15) + return simpad_get_cs3_ro() & (1 << (offset - 16)); + return simpad_get_cs3_shadow() & (1 << offset); +}; -EXPORT_SYMBOL(set_cs3_bit); -EXPORT_SYMBOL(clear_cs3_bit); +static int cs3_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + if (offset > 15) + return 0; + return -EINVAL; +}; + +static int cs3_gpio_direction_output(struct gpio_chip *chip, unsigned offset, + int value) +{ + if (offset > 15) + return -EINVAL; + cs3_gpio_set(chip, offset, value); + return 0; +}; static struct map_desc simpad_io_desc[] __initdata = { { /* MQ200 */ @@ -64,9 +122,9 @@ static struct map_desc simpad_io_desc[] __initdata = { .pfn = __phys_to_pfn(0x4b800000), .length = 0x00800000, .type = MT_DEVICE - }, { /* Paules CS3, write only */ - .virtual = 0xf1000000, - .pfn = __phys_to_pfn(0x18000000), + }, { /* Simpad CS3 */ + .virtual = CS3_BASE, + .pfn = __phys_to_pfn(SA1100_CS3_PHYS), .length = 0x00100000, .type = MT_DEVICE }, @@ -78,12 +136,12 @@ static void simpad_uart_pm(struct uart_port *port, u_int state, u_int oldstate) if (port->mapbase == (u_int)&Ser1UTCR0) { if (state) { - clear_cs3_bit(RS232_ON); - clear_cs3_bit(DECT_POWER_ON); + simpad_clear_cs3_bit(RS232_ON); + simpad_clear_cs3_bit(DECT_POWER_ON); }else { - set_cs3_bit(RS232_ON); - set_cs3_bit(DECT_POWER_ON); + simpad_set_cs3_bit(RS232_ON); + simpad_set_cs3_bit(DECT_POWER_ON); } } } @@ -132,6 +190,7 @@ static struct resource simpad_flash_resources [] = { static struct mcp_plat_data simpad_mcp_data = { .mccr0 = MCCR0_ADM, .sclk_rate = 11981000, + .gpio_base = SIMPAD_UCB1X00_GPIO_BASE, }; @@ -142,9 +201,10 @@ static void __init simpad_map_io(void) iotable_init(simpad_io_desc, ARRAY_SIZE(simpad_io_desc)); - set_cs3_bit (EN1 | EN0 | LED2_ON | DISPLAY_ON | RS232_ON | - ENABLE_5V | RESET_SIMCARD | DECT_POWER_ON); - + /* Initialize CS3 */ + cs3_shadow = (EN1 | EN0 | LED2_ON | DISPLAY_ON | + RS232_ON | ENABLE_5V | RESET_SIMCARD | DECT_POWER_ON); + __simpad_write_cs3(); /* Spinlocks not yet initialized */ sa1100_register_uart_fns(&simpad_port_fns); sa1100_register_uart(0, 3); /* serial interface */ @@ -170,13 +230,14 @@ static void __init simpad_map_io(void) static void simpad_power_off(void) { - local_irq_disable(); // was cli - set_cs3(0x800); /* only SD_MEDIAQ */ + local_irq_disable(); + cs3_shadow = SD_MEDIAQ; + __simpad_write_cs3(); /* Bypass spinlock here */ /* disable internal oscillator, float CS lines */ PCFR = (PCFR_OPDE | PCFR_FP | PCFR_FS); - /* enable wake-up on GPIO0 (Assabet...) */ - PWER = GFER = GRER = 1; + /* enable wake-up on GPIO0 */ + PWER = GFER = GRER = PWER_GPIO0; /* * set scratchpad to zero, just in case it is used as a * restart address by the bootloader. @@ -192,6 +253,91 @@ static void simpad_power_off(void) } +/* + * gpio_keys +*/ + +static struct gpio_keys_button simpad_button_table[] = { + { KEY_POWER, IRQ_GPIO_POWER_BUTTON, 1, "power button" }, +}; + +static struct gpio_keys_platform_data simpad_keys_data = { + .buttons = simpad_button_table, + .nbuttons = ARRAY_SIZE(simpad_button_table), +}; + +static struct platform_device simpad_keys = { + .name = "gpio-keys", + .dev = { + .platform_data = &simpad_keys_data, + }, +}; + +static struct gpio_keys_button simpad_polled_button_table[] = { + { KEY_PROG1, SIMPAD_UCB1X00_GPIO_PROG1, 1, "prog1 button" }, + { KEY_PROG2, SIMPAD_UCB1X00_GPIO_PROG2, 1, "prog2 button" }, + { KEY_UP, SIMPAD_UCB1X00_GPIO_UP, 1, "up button" }, + { KEY_DOWN, SIMPAD_UCB1X00_GPIO_DOWN, 1, "down button" }, + { KEY_LEFT, SIMPAD_UCB1X00_GPIO_LEFT, 1, "left button" }, + { KEY_RIGHT, SIMPAD_UCB1X00_GPIO_RIGHT, 1, "right button" }, +}; + +static struct gpio_keys_platform_data simpad_polled_keys_data = { + .buttons = simpad_polled_button_table, + .nbuttons = ARRAY_SIZE(simpad_polled_button_table), + .poll_interval = 50, +}; + +static struct platform_device simpad_polled_keys = { + .name = "gpio-keys-polled", + .dev = { + .platform_data = &simpad_polled_keys_data, + }, +}; + +/* + * GPIO LEDs + */ + +static struct gpio_led simpad_leds[] = { + { + .name = "simpad:power", + .gpio = SIMPAD_CS3_LED2_ON, + .active_low = 0, + .default_trigger = "default-on", + }, +}; + +static struct gpio_led_platform_data simpad_led_data = { + .num_leds = ARRAY_SIZE(simpad_leds), + .leds = simpad_leds, +}; + +static struct platform_device simpad_gpio_leds = { + .name = "leds-gpio", + .id = 0, + .dev = { + .platform_data = &simpad_led_data, + }, +}; + +/* + * i2c + */ +static struct i2c_gpio_platform_data simpad_i2c_data = { + .sda_pin = GPIO_GPIO21, + .scl_pin = GPIO_GPIO25, + .udelay = 10, + .timeout = HZ, +}; + +static struct platform_device simpad_i2c = { + .name = "i2c-gpio", + .id = 0, + .dev = { + .platform_data = &simpad_i2c_data, + }, +}; /* * MediaQ Video Device @@ -202,7 +348,11 @@ static struct platform_device simpad_mq200fb = { }; static struct platform_device *devices[] __initdata = { - &simpad_mq200fb + &simpad_keys, + &simpad_polled_keys, + &simpad_mq200fb, + &simpad_gpio_leds, + &simpad_i2c, }; @@ -211,6 +361,19 @@ static int __init simpad_init(void) { int ret; + spin_lock_init(&cs3_lock); + + cs3_gpio.label = "simpad_cs3"; + cs3_gpio.base = SIMPAD_CS3_GPIO_BASE; + cs3_gpio.ngpio = 24; + cs3_gpio.set = cs3_gpio_set; + cs3_gpio.get = cs3_gpio_get; + cs3_gpio.direction_input = cs3_gpio_direction_input; + cs3_gpio.direction_output = cs3_gpio_direction_output; + ret = gpiochip_add(&cs3_gpio); + if (ret) + printk(KERN_WARNING "simpad: Unable to register cs3 GPIO device"); + pm_power_off = simpad_power_off; sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources, |