diff options
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r-- | arch/arm/mach-omap2/board-3430sdp.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-ldp.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-omap3beagle.c | 7 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-omap3evm.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-omap3pandora.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-rx51-peripherals.c | 90 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-zoom2.c | 14 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock24xx.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock34xx.c | 35 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clockdomain.c | 74 | ||||
-rw-r--r-- | arch/arm/mach-omap2/cm4xxx.c | 17 | ||||
-rw-r--r-- | arch/arm/mach-omap2/devices.c | 65 | ||||
-rw-r--r-- | arch/arm/mach-omap2/io.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-omap2/iommu2.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/mailbox.c | 33 | ||||
-rw-r--r-- | arch/arm/mach-omap2/mux.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm-debug.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm34xx.c | 187 | ||||
-rw-r--r-- | arch/arm/mach-omap2/powerdomain.c | 39 | ||||
-rw-r--r-- | arch/arm/mach-omap2/serial.c | 6 |
20 files changed, 394 insertions, 228 deletions
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index bd57ec7..efaf053 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -54,7 +54,7 @@ #define TWL4030_MSECURE_GPIO 22 -static int sdp3430_keymap[] = { +static int board_keymap[] = { KEY(0, 0, KEY_LEFT), KEY(0, 1, KEY_RIGHT), KEY(0, 2, KEY_A), @@ -88,11 +88,15 @@ static int sdp3430_keymap[] = { 0 }; +static struct matrix_keymap_data board_map_data = { + .keymap = board_keymap, + .keymap_size = ARRAY_SIZE(board_keymap), +}; + static struct twl4030_keypad_data sdp3430_kp_data = { + .keymap_data = &board_map_data, .rows = 5, .cols = 6, - .keymap = sdp3430_keymap, - .keymapsize = ARRAY_SIZE(sdp3430_keymap), .rep = 1, }; diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index ec6854c..d110a7f 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c @@ -80,7 +80,7 @@ static struct platform_device ldp_smsc911x_device = { }, }; -static int ldp_twl4030_keymap[] = { +static int board_keymap[] = { KEY(0, 0, KEY_1), KEY(1, 0, KEY_2), KEY(2, 0, KEY_3), @@ -101,11 +101,15 @@ static int ldp_twl4030_keymap[] = { 0 }; +static struct matrix_keymap_data board_map_data = { + .keymap = board_keymap, + .keymap_size = ARRAY_SIZE(board_keymap), +}; + static struct twl4030_keypad_data ldp_kp_twl4030_data = { + .keymap_data = &board_map_data, .rows = 6, .cols = 6, - .keymap = ldp_twl4030_keymap, - .keymapsize = ARRAY_SIZE(ldp_twl4030_keymap), .rep = 1, }; diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 500c995..70df6b4 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -139,8 +139,13 @@ static struct gpio_led gpio_leds[]; static int beagle_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio) { + if (system_rev >= 0x20 && system_rev <= 0x34301000) { + omap_cfg_reg(AG9_34XX_GPIO23); + mmc[0].gpio_wp = 23; + } else { + omap_cfg_reg(AH8_34XX_GPIO29); + } /* gpio + 0 is "mmc0_cd" (input/IRQ) */ - omap_cfg_reg(AH8_34XX_GPIO29); mmc[0].gpio_cd = gpio + 0; twl4030_mmc_init(mmc); diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index d50b9be..e4ec0c5 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -159,7 +159,7 @@ static struct twl4030_usb_data omap3evm_usb_data = { .usb_mode = T2_USB_MODE_ULPI, }; -static int omap3evm_keymap[] = { +static int board_keymap[] = { KEY(0, 0, KEY_LEFT), KEY(0, 1, KEY_RIGHT), KEY(0, 2, KEY_A), @@ -178,11 +178,15 @@ static int omap3evm_keymap[] = { KEY(3, 3, KEY_P) }; +static struct matrix_keymap_data board_map_data = { + .keymap = board_keymap, + .keymap_size = ARRAY_SIZE(board_keymap), +}; + static struct twl4030_keypad_data omap3evm_kp_data = { + .keymap_data = &board_map_data, .rows = 4, .cols = 4, - .keymap = omap3evm_keymap, - .keymapsize = ARRAY_SIZE(omap3evm_keymap), .rep = 1, }; diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index b43f6e3..7f6bf87 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -133,7 +133,7 @@ static void __init pandora_keys_gpio_init(void) omap_set_gpio_debounce_time(32 * 5, GPIO_DEBOUNCE_TIME); } -static int pandora_keypad_map[] = { +static int board_keymap[] = { /* col, row, code */ KEY(0, 0, KEY_9), KEY(0, 1, KEY_0), @@ -180,11 +180,15 @@ static int pandora_keypad_map[] = { KEY(5, 2, KEY_FN), }; +static struct matrix_keymap_data board_map_data = { + .keymap = board_keymap, + .keymap_size = ARRAY_SIZE(board_keymap), +}; + static struct twl4030_keypad_data pandora_kp_data = { + .keymap_data = &board_map_data, .rows = 8, .cols = 6, - .keymap = pandora_keypad_map, - .keymapsize = ARRAY_SIZE(pandora_keypad_map), .rep = 1, }; diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index e6e8290..2b0eb1b 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -36,58 +36,62 @@ #define SYSTEM_REV_B_USES_VAUX3 0x1699 #define SYSTEM_REV_S_USES_VAUX3 0x8 -static int rx51_keymap[] = { +static int board_keymap[] = { KEY(0, 0, KEY_Q), - KEY(0, 1, KEY_W), - KEY(0, 2, KEY_E), - KEY(0, 3, KEY_R), - KEY(0, 4, KEY_T), - KEY(0, 5, KEY_Y), - KEY(0, 6, KEY_U), - KEY(0, 7, KEY_I), - KEY(1, 0, KEY_O), + KEY(0, 1, KEY_O), + KEY(0, 2, KEY_P), + KEY(0, 3, KEY_COMMA), + KEY(0, 4, KEY_BACKSPACE), + KEY(0, 6, KEY_A), + KEY(0, 7, KEY_S), + KEY(1, 0, KEY_W), KEY(1, 1, KEY_D), - KEY(1, 2, KEY_DOT), - KEY(1, 3, KEY_V), - KEY(1, 4, KEY_DOWN), - KEY(2, 0, KEY_P), - KEY(2, 1, KEY_F), + KEY(1, 2, KEY_F), + KEY(1, 3, KEY_G), + KEY(1, 4, KEY_H), + KEY(1, 5, KEY_J), + KEY(1, 6, KEY_K), + KEY(1, 7, KEY_L), + KEY(2, 0, KEY_E), + KEY(2, 1, KEY_DOT), KEY(2, 2, KEY_UP), - KEY(2, 3, KEY_B), - KEY(2, 4, KEY_RIGHT), - KEY(3, 0, KEY_COMMA), - KEY(3, 1, KEY_G), - KEY(3, 2, KEY_ENTER), + KEY(2, 3, KEY_ENTER), + KEY(2, 5, KEY_Z), + KEY(2, 6, KEY_X), + KEY(2, 7, KEY_C), + KEY(3, 0, KEY_R), + KEY(3, 1, KEY_V), + KEY(3, 2, KEY_B), KEY(3, 3, KEY_N), - KEY(4, 0, KEY_BACKSPACE), - KEY(4, 1, KEY_H), - KEY(4, 3, KEY_M), + KEY(3, 4, KEY_M), + KEY(3, 5, KEY_SPACE), + KEY(3, 6, KEY_SPACE), + KEY(3, 7, KEY_LEFT), + KEY(4, 0, KEY_T), + KEY(4, 1, KEY_DOWN), + KEY(4, 2, KEY_RIGHT), KEY(4, 4, KEY_LEFTCTRL), - KEY(5, 1, KEY_J), - KEY(5, 2, KEY_Z), - KEY(5, 3, KEY_SPACE), - KEY(5, 4, KEY_LEFTSHIFT), - KEY(6, 0, KEY_A), - KEY(6, 1, KEY_K), - KEY(6, 2, KEY_X), - KEY(6, 3, KEY_SPACE), - KEY(6, 4, KEY_FN), - KEY(7, 0, KEY_S), - KEY(7, 1, KEY_L), - KEY(7, 2, KEY_C), - KEY(7, 3, KEY_LEFT), - KEY(0xff, 0, KEY_F6), - KEY(0xff, 1, KEY_F7), - KEY(0xff, 2, KEY_F8), - KEY(0xff, 4, KEY_F9), - KEY(0xff, 5, KEY_F10), + KEY(4, 5, KEY_RIGHTALT), + KEY(4, 6, KEY_LEFTSHIFT), + KEY(5, 0, KEY_Y), + KEY(6, 0, KEY_U), + KEY(7, 0, KEY_I), + KEY(7, 1, KEY_F7), + KEY(7, 2, KEY_F8), + KEY(0xff, 2, KEY_F9), + KEY(0xff, 4, KEY_F10), + KEY(0xff, 5, KEY_F11), +}; + +static struct matrix_keymap_data board_map_data = { + .keymap = board_keymap, + .keymap_size = ARRAY_SIZE(board_keymap), }; static struct twl4030_keypad_data rx51_kp_data = { + .keymap_data = &board_map_data, .rows = 8, .cols = 8, - .keymap = rx51_keymap, - .keymapsize = ARRAY_SIZE(rx51_keymap), .rep = 1, }; @@ -440,7 +444,7 @@ static int __init rx51_i2c_init(void) rx51_twldata.vaux3 = &rx51_vaux3_cam; rx51_twldata.vmmc2 = &rx51_vmmc2; } - omap_register_i2c_bus(1, 2600, rx51_peripherals_i2c_board_info_1, + omap_register_i2c_bus(1, 2200, rx51_peripherals_i2c_board_info_1, ARRAY_SIZE(rx51_peripherals_i2c_board_info_1)); omap_register_i2c_bus(2, 100, NULL, 0); omap_register_i2c_bus(3, 400, NULL, 0); diff --git a/arch/arm/mach-omap2/board-zoom2.c b/arch/arm/mach-omap2/board-zoom2.c index 324009e..fd3369d 100644 --- a/arch/arm/mach-omap2/board-zoom2.c +++ b/arch/arm/mach-omap2/board-zoom2.c @@ -25,9 +25,10 @@ #include <mach/keypad.h> #include "mmc-twl4030.h" +#include "sdram-micron-mt46h32m32lf-6.h" /* Zoom2 has Qwerty keyboard*/ -static int zoom2_twl4030_keymap[] = { +static int board_keymap[] = { KEY(0, 0, KEY_E), KEY(1, 0, KEY_R), KEY(2, 0, KEY_T), @@ -82,11 +83,15 @@ static int zoom2_twl4030_keymap[] = { 0 }; +static struct matrix_keymap_data board_map_data = { + .keymap = board_keymap, + .keymap_size = ARRAY_SIZE(board_keymap), +}; + static struct twl4030_keypad_data zoom2_kp_twl4030_data = { + .keymap_data = &board_map_data, .rows = 8, .cols = 8, - .keymap = zoom2_twl4030_keymap, - .keymapsize = ARRAY_SIZE(zoom2_twl4030_keymap), .rep = 1, }; @@ -209,7 +214,8 @@ static void __init omap_zoom2_init_irq(void) { omap_board_config = zoom2_config; omap_board_config_size = ARRAY_SIZE(zoom2_config); - omap2_init_common_hw(NULL, NULL); + omap2_init_common_hw(mt46h32m32lf6_sdrc_params, + mt46h32m32lf6_sdrc_params); omap_init_irq(); omap_gpio_init(); } diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index bc5d3ac..e2dbedd 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -769,6 +769,7 @@ int __init omap2_clk_init(void) if (c->cpu & cpu_mask) { clkdev_add(&c->lk); clk_register(c->lk.clk); + omap2_init_clk_clkdm(c->lk.clk); } /* Check the MPU rate set by bootloader */ diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index fafcd32..489556e 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -338,6 +338,13 @@ static struct omap_clk omap34xx_clks[] = { */ #define SDRC_MPURATE_LOOPS 96 +/* + * DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks + * that are sourced by DPLL5, and both of these require this clock + * to be at 120 MHz for proper operation. + */ +#define DPLL5_FREQ_FOR_USBHOST 120000000 + /** * omap3430es2_clk_ssi_find_idlest - return CM_IDLEST info for SSI * @clk: struct clk * being enabled @@ -1056,6 +1063,28 @@ void omap2_clk_prepare_for_reboot(void) #endif } +static void omap3_clk_lock_dpll5(void) +{ + struct clk *dpll5_clk; + struct clk *dpll5_m2_clk; + + dpll5_clk = clk_get(NULL, "dpll5_ck"); + clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST); + clk_enable(dpll5_clk); + + /* Enable autoidle to allow it to enter low power bypass */ + omap3_dpll_allow_idle(dpll5_clk); + + /* Program dpll5_m2_clk divider for no division */ + dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck"); + clk_enable(dpll5_m2_clk); + clk_set_rate(dpll5_m2_clk, DPLL5_FREQ_FOR_USBHOST); + + clk_disable(dpll5_m2_clk); + clk_disable(dpll5_clk); + return; +} + /* REVISIT: Move this init stuff out into clock.c */ /* @@ -1148,6 +1177,12 @@ int __init omap2_clk_init(void) */ clk_enable_init_clocks(); + /* + * Lock DPLL5 and put it in autoidle. + */ + if (omap_rev() >= OMAP3430_REV_ES2_0) + omap3_clk_lock_dpll5(); + /* Avoid sleeping during omap2_clk_prepare_for_reboot() */ /* REVISIT: not yet ready for 343x */ #if 0 diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 4ef7b4f..58aff84 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -137,6 +137,36 @@ static void _clkdm_del_autodeps(struct clockdomain *clkdm) } } +/* + * _omap2_clkdm_set_hwsup - set the hwsup idle transition bit + * @clkdm: struct clockdomain * + * @enable: int 0 to disable, 1 to enable + * + * Internal helper for actually switching the bit that controls hwsup + * idle transitions for clkdm. + */ +static void _omap2_clkdm_set_hwsup(struct clockdomain *clkdm, int enable) +{ + u32 v; + + if (cpu_is_omap24xx()) { + if (enable) + v = OMAP24XX_CLKSTCTRL_ENABLE_AUTO; + else + v = OMAP24XX_CLKSTCTRL_DISABLE_AUTO; + } else if (cpu_is_omap34xx()) { + if (enable) + v = OMAP34XX_CLKSTCTRL_ENABLE_AUTO; + else + v = OMAP34XX_CLKSTCTRL_DISABLE_AUTO; + } else { + BUG(); + } + + cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, + v << __ffs(clkdm->clktrctrl_mask), + clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL); +} static struct clockdomain *_clkdm_lookup(const char *name) { @@ -456,8 +486,6 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm) */ void omap2_clkdm_allow_idle(struct clockdomain *clkdm) { - u32 v; - if (!clkdm) return; @@ -473,18 +501,7 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm) if (atomic_read(&clkdm->usecount) > 0) _clkdm_add_autodeps(clkdm); - if (cpu_is_omap24xx()) - v = OMAP24XX_CLKSTCTRL_ENABLE_AUTO; - else if (cpu_is_omap34xx()) - v = OMAP34XX_CLKSTCTRL_ENABLE_AUTO; - else - BUG(); - - - cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, - v << __ffs(clkdm->clktrctrl_mask), - clkdm->pwrdm.ptr->prcm_offs, - CM_CLKSTCTRL); + _omap2_clkdm_set_hwsup(clkdm, 1); pwrdm_clkdm_state_switch(clkdm); } @@ -500,8 +517,6 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm) */ void omap2_clkdm_deny_idle(struct clockdomain *clkdm) { - u32 v; - if (!clkdm) return; @@ -514,16 +529,7 @@ void omap2_clkdm_deny_idle(struct clockdomain *clkdm) pr_debug("clockdomain: disabling automatic idle transitions for %s\n", clkdm->name); - if (cpu_is_omap24xx()) - v = OMAP24XX_CLKSTCTRL_DISABLE_AUTO; - else if (cpu_is_omap34xx()) - v = OMAP34XX_CLKSTCTRL_DISABLE_AUTO; - else - BUG(); - - cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, - v << __ffs(clkdm->clktrctrl_mask), - clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL); + _omap2_clkdm_set_hwsup(clkdm, 0); if (atomic_read(&clkdm->usecount) > 0) _clkdm_del_autodeps(clkdm); @@ -569,10 +575,14 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) v = omap2_clkdm_clktrctrl_read(clkdm); if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) || - (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) + (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) { + /* Disable HW transitions when we are changing deps */ + _omap2_clkdm_set_hwsup(clkdm, 0); _clkdm_add_autodeps(clkdm); - else + _omap2_clkdm_set_hwsup(clkdm, 1); + } else { omap2_clkdm_wakeup(clkdm); + } pwrdm_wait_transition(clkdm->pwrdm.ptr); pwrdm_clkdm_state_switch(clkdm); @@ -623,10 +633,14 @@ int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) v = omap2_clkdm_clktrctrl_read(clkdm); if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) || - (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) + (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) { + /* Disable HW transitions when we are changing deps */ + _omap2_clkdm_set_hwsup(clkdm, 0); _clkdm_del_autodeps(clkdm); - else + _omap2_clkdm_set_hwsup(clkdm, 1); + } else { omap2_clkdm_sleep(clkdm); + } pwrdm_clkdm_state_switch(clkdm); diff --git a/arch/arm/mach-omap2/cm4xxx.c b/arch/arm/mach-omap2/cm4xxx.c index e4ebd6d..4af76bb 100644 --- a/arch/arm/mach-omap2/cm4xxx.c +++ b/arch/arm/mach-omap2/cm4xxx.c @@ -22,7 +22,6 @@ #include <asm/atomic.h> #include "cm.h" -#include "cm-regbits-4xxx.h" /* XXX move this to cm.h */ /* MAX_MODULE_READY_TIME: max milliseconds for module to leave idle */ @@ -50,19 +49,7 @@ */ int omap4_cm_wait_idlest_ready(u32 prcm_mod, u8 prcm_dev_offs) { - int i = 0; - u8 cm_id; - u16 prcm_mod_offs; - u32 mask = OMAP4_PRCM_CM_CLKCTRL_IDLEST_MASK; - - cm_id = prcm_mod >> OMAP4_PRCM_MOD_CM_ID_SHIFT; - prcm_mod_offs = prcm_mod & OMAP4_PRCM_MOD_OFFS_MASK; - - while (((omap4_cm_read_mod_reg(cm_id, prcm_mod_offs, prcm_dev_offs, - OMAP4_CM_CLKCTRL_DREG) & mask) != 0) && - (i++ < MAX_MODULE_READY_TIME)) - udelay(1); - - return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY; + /* FIXME: Add clock manager related code */ + return 0; } diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index bcfcfc7..faf7a1e 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -355,29 +355,60 @@ static struct platform_device omap2_mcspi4 = { }; #endif -static void omap_init_mcspi(void) +#ifdef CONFIG_ARCH_OMAP4 +static inline void omap4_mcspi_fixup(void) { - if (cpu_is_omap44xx()) { - omap2_mcspi1_resources[0].start = OMAP4_MCSPI1_BASE; - omap2_mcspi1_resources[0].end = OMAP4_MCSPI1_BASE + 0xff; - omap2_mcspi2_resources[0].start = OMAP4_MCSPI2_BASE; - omap2_mcspi2_resources[0].end = OMAP4_MCSPI2_BASE + 0xff; - omap2_mcspi3_resources[0].start = OMAP4_MCSPI3_BASE; - omap2_mcspi3_resources[0].end = OMAP4_MCSPI3_BASE + 0xff; - omap2_mcspi4_resources[0].start = OMAP4_MCSPI4_BASE; - omap2_mcspi4_resources[0].end = OMAP4_MCSPI4_BASE + 0xff; - } - platform_device_register(&omap2_mcspi1); - platform_device_register(&omap2_mcspi2); + omap2_mcspi1_resources[0].start = OMAP4_MCSPI1_BASE; + omap2_mcspi1_resources[0].end = OMAP4_MCSPI1_BASE + 0xff; + omap2_mcspi2_resources[0].start = OMAP4_MCSPI2_BASE; + omap2_mcspi2_resources[0].end = OMAP4_MCSPI2_BASE + 0xff; + omap2_mcspi3_resources[0].start = OMAP4_MCSPI3_BASE; + omap2_mcspi3_resources[0].end = OMAP4_MCSPI3_BASE + 0xff; + omap2_mcspi4_resources[0].start = OMAP4_MCSPI4_BASE; + omap2_mcspi4_resources[0].end = OMAP4_MCSPI4_BASE + 0xff; +} +#else +static inline void omap4_mcspi_fixup(void) +{ +} +#endif + #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \ defined(CONFIG_ARCH_OMAP4) - if (cpu_is_omap2430() || cpu_is_omap343x() || cpu_is_omap44xx()) - platform_device_register(&omap2_mcspi3); +static inline void omap2_mcspi3_init(void) +{ + platform_device_register(&omap2_mcspi3); +} +#else +static inline void omap2_mcspi3_init(void) +{ +} #endif + #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) - if (cpu_is_omap343x() || cpu_is_omap44xx()) - platform_device_register(&omap2_mcspi4); +static inline void omap2_mcspi4_init(void) +{ + platform_device_register(&omap2_mcspi4); +} +#else +static inline void omap2_mcspi4_init(void) +{ +} #endif + +static void omap_init_mcspi(void) +{ + if (cpu_is_omap44xx()) + omap4_mcspi_fixup(); + + platform_device_register(&omap2_mcspi1); + platform_device_register(&omap2_mcspi2); + + if (cpu_is_omap2430() || cpu_is_omap343x() || cpu_is_omap44xx()) + omap2_mcspi3_init(); + + if (cpu_is_omap343x() || cpu_is_omap44xx()) + omap2_mcspi4_init(); } #else diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 7574b6f..e3a3bad 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -294,10 +294,10 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0, else if (cpu_is_omap34xx()) hwmods = omap34xx_hwmods; - omap_hwmod_init(hwmods); - omap2_mux_init(); #ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once the clkdev is ready */ /* The OPP tables have to be registered before a clk init */ + omap_hwmod_init(hwmods); + omap2_mux_init(); omap_pm_if_early_init(mpu_opps, dsp_opps, l3_opps); pwrdm_init(powerdomains_omap); clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps); diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c index 2d9b5cc..4a0e1cd 100644 --- a/arch/arm/mach-omap2/iommu2.c +++ b/arch/arm/mach-omap2/iommu2.c @@ -79,7 +79,7 @@ static int omap2_iommu_enable(struct iommu *obj) l = iommu_read_reg(obj, MMU_SYSSTATUS); if (l & MMU_SYS_RESETDONE) break; - } while (time_after(jiffies, timeout)); + } while (!time_after(jiffies, timeout)); if (!(l & MMU_SYS_RESETDONE)) { dev_err(obj->dev, "can't take mmu out of reset\n"); diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c index 6f71f37..c035ad3 100644 --- a/arch/arm/mach-omap2/mailbox.c +++ b/arch/arm/mach-omap2/mailbox.c @@ -30,6 +30,14 @@ #define MAILBOX_IRQ_NEWMSG(u) (1 << (2 * (u))) #define MAILBOX_IRQ_NOTFULL(u) (1 << (2 * (u) + 1)) +/* SYSCONFIG: register bit definition */ +#define AUTOIDLE (1 << 0) +#define SOFTRESET (1 << 1) +#define SMARTIDLE (2 << 3) + +/* SYSSTATUS: register bit definition */ +#define RESETDONE (1 << 0) + #define MBOX_REG_SIZE 0x120 #define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32)) @@ -69,21 +77,33 @@ static inline void mbox_write_reg(u32 val, size_t ofs) /* Mailbox H/W preparations */ static int omap2_mbox_startup(struct omap_mbox *mbox) { - unsigned int l; + u32 l; + unsigned long timeout; mbox_ick_handle = clk_get(NULL, "mailboxes_ick"); if (IS_ERR(mbox_ick_handle)) { - printk("Could not get mailboxes_ick\n"); + pr_err("Can't get mailboxes_ick\n"); return -ENODEV; } clk_enable(mbox_ick_handle); + mbox_write_reg(SOFTRESET, MAILBOX_SYSCONFIG); + timeout = jiffies + msecs_to_jiffies(20); + do { + l = mbox_read_reg(MAILBOX_SYSSTATUS); + if (l & RESETDONE) + break; + } while (!time_after(jiffies, timeout)); + + if (!(l & RESETDONE)) { + pr_err("Can't take mmu out of reset\n"); + return -ENODEV; + } + l = mbox_read_reg(MAILBOX_REVISION); pr_info("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f)); - /* set smart-idle & autoidle */ - l = mbox_read_reg(MAILBOX_SYSCONFIG); - l |= 0x00000011; + l = SMARTIDLE | AUTOIDLE; mbox_write_reg(l, MAILBOX_SYSCONFIG); omap2_mbox_enable_irq(mbox, IRQ_RX); @@ -156,6 +176,9 @@ static void omap2_mbox_ack_irq(struct omap_mbox *mbox, u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; mbox_write_reg(bit, p->irqstatus); + + /* Flush posted write for irq status to avoid spurious interrupts */ + mbox_read_reg(p->irqstatus); } static int omap2_mbox_is_irq(struct omap_mbox *mbox, diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index 2daa595..b5fac32 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c @@ -460,6 +460,8 @@ MUX_CFG_34XX("AF26_34XX_GPIO0", 0x1e0, OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) MUX_CFG_34XX("AF22_34XX_GPIO9", 0xa18, OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) +MUX_CFG_34XX("AG9_34XX_GPIO23", 0x5ee, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) MUX_CFG_34XX("AH8_34XX_GPIO29", 0x5fa, OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT) MUX_CFG_34XX("U8_34XX_GPIO54_OUT", 0x0b4, @@ -472,6 +474,8 @@ MUX_CFG_34XX("G25_34XX_GPIO86_OUT", 0x0fc, OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT) MUX_CFG_34XX("AG4_34XX_GPIO134_OUT", 0x160, OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT) +MUX_CFG_34XX("AF4_34XX_GPIO135_OUT", 0x162, + OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT) MUX_CFG_34XX("AE4_34XX_GPIO136_OUT", 0x164, OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT) MUX_CFG_34XX("AF6_34XX_GPIO140_UP", 0x16c, diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c index 1b4c160..2fc4d6a 100644 --- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c @@ -541,7 +541,7 @@ static int __init pm_dbg_init(void) printk(KERN_ERR "%s: only OMAP3 supported\n", __func__); return -ENODEV; } - + d = debugfs_create_dir("pm_debug", NULL); if (IS_ERR(d)) return PTR_ERR(d); @@ -551,7 +551,7 @@ static int __init pm_dbg_init(void) (void) debugfs_create_file("time", S_IRUGO, d, (void *)DEBUG_FILE_TIMERS, &debug_fops); - pwrdm_for_each(pwrdms_setup, (void *)d); + pwrdm_for_each_nolock(pwrdms_setup, (void *)d); pm_dbg_dir = debugfs_create_dir("registers", d); if (IS_ERR(pm_dbg_dir)) diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 0ff5a6c..378c2f6 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -51,97 +51,112 @@ static void (*_omap_sram_idle)(u32 *addr, int save_state); static struct powerdomain *mpu_pwrdm; -/* PRCM Interrupt Handler for wakeups */ -static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id) +/* + * PRCM Interrupt Handler Helper Function + * + * The purpose of this function is to clear any wake-up events latched + * in the PRCM PM_WKST_x registers. It is possible that a wake-up event + * may occur whilst attempting to clear a PM_WKST_x register and thus + * set another bit in this register. A while loop is used to ensure + * that any peripheral wake-up events occurring while attempting to + * clear the PM_WKST_x are detected and cleared. + */ +static int prcm_clear_mod_irqs(s16 module, u8 regs) { - u32 wkst, irqstatus_mpu; - u32 fclk, iclk; - - /* WKUP */ - wkst = prm_read_mod_reg(WKUP_MOD, PM_WKST); + u32 wkst, fclk, iclk, clken; + u16 wkst_off = (regs == 3) ? OMAP3430ES2_PM_WKST3 : PM_WKST1; + u16 fclk_off = (regs == 3) ? OMAP3430ES2_CM_FCLKEN3 : CM_FCLKEN1; + u16 iclk_off = (regs == 3) ? CM_ICLKEN3 : CM_ICLKEN1; + u16 grpsel_off = (regs == 3) ? + OMAP3430ES2_PM_MPUGRPSEL3 : OMAP3430_PM_MPUGRPSEL; + int c = 0; + + wkst = prm_read_mod_reg(module, wkst_off); + wkst &= prm_read_mod_reg(module, grpsel_off); if (wkst) { - iclk = cm_read_mod_reg(WKUP_MOD, CM_ICLKEN); - fclk = cm_read_mod_reg(WKUP_MOD, CM_FCLKEN); - cm_set_mod_reg_bits(wkst, WKUP_MOD, CM_ICLKEN); - cm_set_mod_reg_bits(wkst, WKUP_MOD, CM_FCLKEN); - prm_write_mod_reg(wkst, WKUP_MOD, PM_WKST); - while (prm_read_mod_reg(WKUP_MOD, PM_WKST)) - cpu_relax(); - cm_write_mod_reg(iclk, WKUP_MOD, CM_ICLKEN); - cm_write_mod_reg(fclk, WKUP_MOD, CM_FCLKEN); + iclk = cm_read_mod_reg(module, iclk_off); + fclk = cm_read_mod_reg(module, fclk_off); + while (wkst) { + clken = wkst; + cm_set_mod_reg_bits(clken, module, iclk_off); + /* + * For USBHOST, we don't know whether HOST1 or + * HOST2 woke us up, so enable both f-clocks + */ + if (module == OMAP3430ES2_USBHOST_MOD) + clken |= 1 << OMAP3430ES2_EN_USBHOST2_SHIFT; + cm_set_mod_reg_bits(clken, module, fclk_off); + prm_write_mod_reg(wkst, module, wkst_off); + wkst = prm_read_mod_reg(module, wkst_off); + c++; + } + cm_write_mod_reg(iclk, module, iclk_off); + cm_write_mod_reg(fclk, module, fclk_off); } - /* CORE */ - wkst = prm_read_mod_reg(CORE_MOD, PM_WKST1); - if (wkst) { - iclk = cm_read_mod_reg(CORE_MOD, CM_ICLKEN1); - fclk = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1); - cm_set_mod_reg_bits(wkst, CORE_MOD, CM_ICLKEN1); - cm_set_mod_reg_bits(wkst, CORE_MOD, CM_FCLKEN1); - prm_write_mod_reg(wkst, CORE_MOD, PM_WKST1); - while (prm_read_mod_reg(CORE_MOD, PM_WKST1)) - cpu_relax(); - cm_write_mod_reg(iclk, CORE_MOD, CM_ICLKEN1); - cm_write_mod_reg(fclk, CORE_MOD, CM_FCLKEN1); - } - wkst = prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_WKST3); - if (wkst) { - iclk = cm_read_mod_reg(CORE_MOD, CM_ICLKEN3); - fclk = cm_read_mod_reg(CORE_MOD, OMAP3430ES2_CM_FCLKEN3); - cm_set_mod_reg_bits(wkst, CORE_MOD, CM_ICLKEN3); - cm_set_mod_reg_bits(wkst, CORE_MOD, OMAP3430ES2_CM_FCLKEN3); - prm_write_mod_reg(wkst, CORE_MOD, OMAP3430ES2_PM_WKST3); - while (prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_WKST3)) - cpu_relax(); - cm_write_mod_reg(iclk, CORE_MOD, CM_ICLKEN3); - cm_write_mod_reg(fclk, CORE_MOD, OMAP3430ES2_CM_FCLKEN3); - } + return c; +} - /* PER */ - wkst = prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKST); - if (wkst) { - iclk = cm_read_mod_reg(OMAP3430_PER_MOD, CM_ICLKEN); - fclk = cm_read_mod_reg(OMAP3430_PER_MOD, CM_FCLKEN); - cm_set_mod_reg_bits(wkst, OMAP3430_PER_MOD, CM_ICLKEN); - cm_set_mod_reg_bits(wkst, OMAP3430_PER_MOD, CM_FCLKEN); - prm_write_mod_reg(wkst, OMAP3430_PER_MOD, PM_WKST); - while (prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKST)) - cpu_relax(); - cm_write_mod_reg(iclk, OMAP3430_PER_MOD, CM_ICLKEN); - cm_write_mod_reg(fclk, OMAP3430_PER_MOD, CM_FCLKEN); - } +static int _prcm_int_handle_wakeup(void) +{ + int c; + c = prcm_clear_mod_irqs(WKUP_MOD, 1); + c += prcm_clear_mod_irqs(CORE_MOD, 1); + c += prcm_clear_mod_irqs(OMAP3430_PER_MOD, 1); if (omap_rev() > OMAP3430_REV_ES1_0) { - /* USBHOST */ - wkst = prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, PM_WKST); - if (wkst) { - iclk = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, - CM_ICLKEN); - fclk = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, - CM_FCLKEN); - cm_set_mod_reg_bits(wkst, OMAP3430ES2_USBHOST_MOD, - CM_ICLKEN); - cm_set_mod_reg_bits(wkst, OMAP3430ES2_USBHOST_MOD, - CM_FCLKEN); - prm_write_mod_reg(wkst, OMAP3430ES2_USBHOST_MOD, - PM_WKST); - while (prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, - PM_WKST)) - cpu_relax(); - cm_write_mod_reg(iclk, OMAP3430ES2_USBHOST_MOD, - CM_ICLKEN); - cm_write_mod_reg(fclk, OMAP3430ES2_USBHOST_MOD, - CM_FCLKEN); - } + c += prcm_clear_mod_irqs(CORE_MOD, 3); + c += prcm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1); } - irqstatus_mpu = prm_read_mod_reg(OCP_MOD, - OMAP3_PRM_IRQSTATUS_MPU_OFFSET); - prm_write_mod_reg(irqstatus_mpu, OCP_MOD, - OMAP3_PRM_IRQSTATUS_MPU_OFFSET); + return c; +} + +/* + * PRCM Interrupt Handler + * + * The PRM_IRQSTATUS_MPU register indicates if there are any pending + * interrupts from the PRCM for the MPU. These bits must be cleared in + * order to clear the PRCM interrupt. The PRCM interrupt handler is + * implemented to simply clear the PRM_IRQSTATUS_MPU in order to clear + * the PRCM interrupt. Please note that bit 0 of the PRM_IRQSTATUS_MPU + * register indicates that a wake-up event is pending for the MPU and + * this bit can only be cleared if the all the wake-up events latched + * in the various PM_WKST_x registers have been cleared. The interrupt + * handler is implemented using a do-while loop so that if a wake-up + * event occurred during the processing of the prcm interrupt handler + * (setting a bit in the corresponding PM_WKST_x register and thus + * preventing us from clearing bit 0 of the PRM_IRQSTATUS_MPU register) + * this would be handled. + */ +static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id) +{ + u32 irqstatus_mpu; + int c = 0; + + do { + irqstatus_mpu = prm_read_mod_reg(OCP_MOD, + OMAP3_PRM_IRQSTATUS_MPU_OFFSET); + + if (irqstatus_mpu & (OMAP3430_WKUP_ST | OMAP3430_IO_ST)) { + c = _prcm_int_handle_wakeup(); + + /* + * Is the MPU PRCM interrupt handler racing with the + * IVA2 PRCM interrupt handler ? + */ + WARN(c == 0, "prcm: WARNING: PRCM indicated MPU wakeup " + "but no wakeup sources are marked\n"); + } else { + /* XXX we need to expand our PRCM interrupt handler */ + WARN(1, "prcm: WARNING: PRCM interrupt received, but " + "no code to handle it (%08x)\n", irqstatus_mpu); + } + + prm_write_mod_reg(irqstatus_mpu, OCP_MOD, + OMAP3_PRM_IRQSTATUS_MPU_OFFSET); - while (prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET)) - cpu_relax(); + } while (prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET)); return IRQ_HANDLED; } @@ -624,6 +639,16 @@ static void __init prcm_setup_regs(void) prm_write_mod_reg(OMAP3430_IO_EN | OMAP3430_WKUP_EN, OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET); + /* Enable GPIO wakeups in PER */ + prm_write_mod_reg(OMAP3430_EN_GPIO2 | OMAP3430_EN_GPIO3 | + OMAP3430_EN_GPIO4 | OMAP3430_EN_GPIO5 | + OMAP3430_EN_GPIO6, OMAP3430_PER_MOD, PM_WKEN); + /* and allow them to wake up MPU */ + prm_write_mod_reg(OMAP3430_GRPSEL_GPIO2 | OMAP3430_EN_GPIO3 | + OMAP3430_GRPSEL_GPIO4 | OMAP3430_EN_GPIO5 | + OMAP3430_GRPSEL_GPIO6, + OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL); + /* Don't attach IVA interrupts */ prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL); prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1); diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 2594cbf..f00289a 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -273,35 +273,50 @@ struct powerdomain *pwrdm_lookup(const char *name) } /** - * pwrdm_for_each - call function on each registered clockdomain + * pwrdm_for_each_nolock - call function on each registered clockdomain * @fn: callback function * * * Call the supplied function for each registered powerdomain. The * callback function can return anything but 0 to bail out early from - * the iterator. The callback function is called with the pwrdm_rwlock - * held for reading, so no powerdomain structure manipulation - * functions should be called from the callback, although hardware - * powerdomain control functions are fine. Returns the last return - * value of the callback function, which should be 0 for success or - * anything else to indicate failure; or -EINVAL if the function - * pointer is null. + * the iterator. Returns the last return value of the callback function, which + * should be 0 for success or anything else to indicate failure; or -EINVAL if + * the function pointer is null. */ -int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user), - void *user) +int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user), + void *user) { struct powerdomain *temp_pwrdm; - unsigned long flags; int ret = 0; if (!fn) return -EINVAL; - read_lock_irqsave(&pwrdm_rwlock, flags); list_for_each_entry(temp_pwrdm, &pwrdm_list, node) { ret = (*fn)(temp_pwrdm, user); if (ret) break; } + + return ret; +} + +/** + * pwrdm_for_each - call function on each registered clockdomain + * @fn: callback function * + * + * This function is the same as 'pwrdm_for_each_nolock()', but keeps the + * &pwrdm_rwlock locked for reading, so no powerdomain structure manipulation + * functions should be called from the callback, although hardware powerdomain + * control functions are fine. + */ +int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user), + void *user) +{ + unsigned long flags; + int ret; + + read_lock_irqsave(&pwrdm_rwlock, flags); + ret = pwrdm_for_each_nolock(fn, user); read_unlock_irqrestore(&pwrdm_rwlock, flags); return ret; diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 3a529c7..ae21868 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -110,7 +110,7 @@ static struct plat_serial8250_port serial_platform_data2[] = { .uartclk = OMAP24XX_BASE_BAUD * 16, }, { #ifdef CONFIG_ARCH_OMAP4 - .membase = IO_ADDRESS(OMAP_UART4_BASE), + .membase = OMAP2_IO_ADDRESS(OMAP_UART4_BASE), .mapbase = OMAP_UART4_BASE, .irq = 70, .flags = UPF_BOOT_AUTOCONF, @@ -126,7 +126,7 @@ static struct plat_serial8250_port serial_platform_data2[] = { #ifdef CONFIG_ARCH_OMAP4 static struct plat_serial8250_port serial_platform_data3[] = { { - .membase = IO_ADDRESS(OMAP_UART4_BASE), + .membase = OMAP2_IO_ADDRESS(OMAP_UART4_BASE), .mapbase = OMAP_UART4_BASE, .irq = 70, .flags = UPF_BOOT_AUTOCONF, @@ -579,7 +579,7 @@ static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS] = { { .pdev = { .name = "serial8250", - .id = 3 + .id = 3, .dev = { .platform_data = serial_platform_data3, }, |