diff options
Diffstat (limited to 'board/gateworks/gw_ventana')
-rw-r--r-- | board/gateworks/gw_ventana/common.c | 469 | ||||
-rw-r--r-- | board/gateworks/gw_ventana/common.h | 10 | ||||
-rw-r--r-- | board/gateworks/gw_ventana/gw_ventana.c | 473 |
3 files changed, 661 insertions, 291 deletions
diff --git a/board/gateworks/gw_ventana/common.c b/board/gateworks/gw_ventana/common.c index 929dde9880..4065c5655a 100644 --- a/board/gateworks/gw_ventana/common.c +++ b/board/gateworks/gw_ventana/common.c @@ -132,14 +132,14 @@ void setup_ventana_i2c(void) /* common to add baseboards */ static iomux_v3_cfg_t const gw_gpio_pads[] = { - /* RS232_EN# */ - IOMUX_PADS(PAD_SD4_DAT3__GPIO2_IO11 | DIO_PAD_CFG), /* SD3_VSELECT */ IOMUX_PADS(PAD_NANDF_CS1__GPIO6_IO14 | DIO_PAD_CFG), }; /* prototype */ static iomux_v3_cfg_t const gwproto_gpio_pads[] = { + /* RS232_EN# */ + IOMUX_PADS(PAD_SD4_DAT3__GPIO2_IO11 | DIO_PAD_CFG), /* PANLEDG# */ IOMUX_PADS(PAD_KEY_COL0__GPIO4_IO06 | DIO_PAD_CFG), /* PANLEDR# */ @@ -183,6 +183,8 @@ static iomux_v3_cfg_t const gw51xx_gpio_pads[] = { }; static iomux_v3_cfg_t const gw52xx_gpio_pads[] = { + /* RS232_EN# */ + IOMUX_PADS(PAD_SD4_DAT3__GPIO2_IO11 | DIO_PAD_CFG), /* MSATA_EN */ IOMUX_PADS(PAD_SD4_DAT0__GPIO2_IO08 | DIO_PAD_CFG), /* PANLEDG# */ @@ -214,6 +216,8 @@ static iomux_v3_cfg_t const gw52xx_gpio_pads[] = { }; static iomux_v3_cfg_t const gw53xx_gpio_pads[] = { + /* RS232_EN# */ + IOMUX_PADS(PAD_SD4_DAT3__GPIO2_IO11 | DIO_PAD_CFG), /* MSATA_EN */ IOMUX_PADS(PAD_SD4_DAT0__GPIO2_IO08 | DIO_PAD_CFG), /* CAN_STBY */ @@ -245,6 +249,8 @@ static iomux_v3_cfg_t const gw53xx_gpio_pads[] = { }; static iomux_v3_cfg_t const gw54xx_gpio_pads[] = { + /* RS232_EN# */ + IOMUX_PADS(PAD_SD4_DAT3__GPIO2_IO11 | DIO_PAD_CFG), /* MSATA_EN */ IOMUX_PADS(PAD_SD4_DAT0__GPIO2_IO08 | DIO_PAD_CFG), /* CAN_STBY */ @@ -332,6 +338,219 @@ static iomux_v3_cfg_t const gw553x_gpio_pads[] = { IOMUX_PADS(PAD_GPIO_17__GPIO7_IO12 | DIO_PAD_CFG), }; +/* Digital I/O */ +struct dio_cfg gw51xx_dio[] = { + { + { IOMUX_PADS(PAD_SD1_DAT0__GPIO1_IO16) }, + IMX_GPIO_NR(1, 16), + { 0, 0 }, + 0 + }, + { + { IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) }, + IMX_GPIO_NR(1, 19), + { IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) }, + 2 + }, + { + { IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) }, + IMX_GPIO_NR(1, 17), + { IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) }, + 3 + }, + { + { IOMUX_PADS(PAD_SD1_CMD__GPIO1_IO18) }, + IMX_GPIO_NR(1, 18), + { IOMUX_PADS(PAD_SD1_CMD__PWM4_OUT) }, + 4 + }, +}; + +struct dio_cfg gw52xx_dio[] = { + { + { IOMUX_PADS(PAD_SD1_DAT0__GPIO1_IO16) }, + IMX_GPIO_NR(1, 16), + { 0, 0 }, + 0 + }, + { + { IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) }, + IMX_GPIO_NR(1, 19), + { IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) }, + 2 + }, + { + { IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) }, + IMX_GPIO_NR(1, 17), + { IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) }, + 3 + }, + { + { IOMUX_PADS(PAD_SD1_CLK__GPIO1_IO20) }, + IMX_GPIO_NR(1, 20), + { 0, 0 }, + 0 + }, +}; + +struct dio_cfg gw53xx_dio[] = { + { + { IOMUX_PADS(PAD_SD1_DAT0__GPIO1_IO16) }, + IMX_GPIO_NR(1, 16), + { 0, 0 }, + 0 + }, + { + { IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) }, + IMX_GPIO_NR(1, 19), + { IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) }, + 2 + }, + { + { IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) }, + IMX_GPIO_NR(1, 17), + { IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) }, + 3 + }, + { + {IOMUX_PADS(PAD_SD1_CLK__GPIO1_IO20) }, + IMX_GPIO_NR(1, 20), + { 0, 0 }, + 0 + }, +}; + +struct dio_cfg gw54xx_dio[] = { + { + { IOMUX_PADS(PAD_GPIO_9__GPIO1_IO09) }, + IMX_GPIO_NR(1, 9), + { IOMUX_PADS(PAD_GPIO_9__PWM1_OUT) }, + 1 + }, + { + { IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) }, + IMX_GPIO_NR(1, 19), + { IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) }, + 2 + }, + { + { IOMUX_PADS(PAD_SD4_DAT1__GPIO2_IO09) }, + IMX_GPIO_NR(2, 9), + { IOMUX_PADS(PAD_SD4_DAT1__PWM3_OUT) }, + 3 + }, + { + { IOMUX_PADS(PAD_SD4_DAT2__GPIO2_IO10) }, + IMX_GPIO_NR(2, 10), + { IOMUX_PADS(PAD_SD4_DAT2__PWM4_OUT) }, + 4 + }, +}; + +struct dio_cfg gw551x_dio[] = { + { + { IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) }, + IMX_GPIO_NR(1, 19), + { IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) }, + 2 + }, + { + { IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) }, + IMX_GPIO_NR(1, 17), + { IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) }, + 3 + }, +}; + +struct dio_cfg gw552x_dio[] = { + { + { IOMUX_PADS(PAD_SD1_DAT0__GPIO1_IO16) }, + IMX_GPIO_NR(1, 16), + { 0, 0 }, + 0 + }, + { + { IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) }, + IMX_GPIO_NR(1, 19), + { IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) }, + 2 + }, + { + { IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) }, + IMX_GPIO_NR(1, 17), + { IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) }, + 3 + }, + { + {IOMUX_PADS(PAD_SD1_CLK__GPIO1_IO20) }, + IMX_GPIO_NR(1, 20), + { 0, 0 }, + 0 + }, + { + {IOMUX_PADS(PAD_CSI0_PIXCLK__GPIO5_IO18) }, + IMX_GPIO_NR(5, 18), + { 0, 0 }, + 0 + }, + { + {IOMUX_PADS(PAD_CSI0_DATA_EN__GPIO5_IO20) }, + IMX_GPIO_NR(5, 20), + { 0, 0 }, + 0 + }, + { + {IOMUX_PADS(PAD_CSI0_VSYNC__GPIO5_IO21) }, + IMX_GPIO_NR(5, 21), + { 0, 0 }, + 0 + }, + { + {IOMUX_PADS(PAD_CSI0_DAT4__GPIO5_IO22) }, + IMX_GPIO_NR(5, 22), + { 0, 0 }, + 0 + }, + { + {IOMUX_PADS(PAD_CSI0_DAT5__GPIO5_IO23) }, + IMX_GPIO_NR(5, 23), + { 0, 0 }, + 0 + }, + { + {IOMUX_PADS(PAD_CSI0_DAT7__GPIO5_IO25) }, + IMX_GPIO_NR(5, 25), + { 0, 0 }, + 0 + }, +}; + +struct dio_cfg gw553x_dio[] = { + { + { IOMUX_PADS(PAD_SD1_DAT0__GPIO1_IO16) }, + IMX_GPIO_NR(1, 16), + { 0, 0 }, + 0 + }, + { + { IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) }, + IMX_GPIO_NR(1, 19), + { IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) }, + 2 + }, + { + { IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) }, + IMX_GPIO_NR(1, 17), + { IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) }, + 3 + }, + { + { IOMUX_PADS(PAD_SD1_CMD__GPIO1_IO18) }, + IMX_GPIO_NR(1, 18), + { IOMUX_PADS(PAD_SD1_CMD__PWM4_OUT) }, + 4 + }, +}; /* * Board Specific GPIO @@ -341,33 +560,8 @@ struct ventana gpio_cfg[GW_UNKNOWN] = { { .gpio_pads = gw54xx_gpio_pads, .num_pads = ARRAY_SIZE(gw54xx_gpio_pads)/2, - .dio_cfg = { - { - { IOMUX_PADS(PAD_GPIO_9__GPIO1_IO09) }, - IMX_GPIO_NR(1, 9), - { IOMUX_PADS(PAD_GPIO_9__PWM1_OUT) }, - 1 - }, - { - { IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) }, - IMX_GPIO_NR(1, 19), - { IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) }, - 2 - }, - { - { IOMUX_PADS(PAD_SD4_DAT1__GPIO2_IO09) }, - IMX_GPIO_NR(2, 9), - { IOMUX_PADS(PAD_SD4_DAT1__PWM3_OUT) }, - 3 - }, - { - { IOMUX_PADS(PAD_SD4_DAT2__GPIO2_IO10) }, - IMX_GPIO_NR(2, 10), - { IOMUX_PADS(PAD_SD4_DAT2__PWM4_OUT) }, - 4 - }, - }, - .num_gpios = 4, + .dio_cfg = gw54xx_dio, + .dio_num = ARRAY_SIZE(gw54xx_dio), .leds = { IMX_GPIO_NR(4, 6), IMX_GPIO_NR(4, 10), @@ -385,33 +579,8 @@ struct ventana gpio_cfg[GW_UNKNOWN] = { { .gpio_pads = gw51xx_gpio_pads, .num_pads = ARRAY_SIZE(gw51xx_gpio_pads)/2, - .dio_cfg = { - { - { IOMUX_PADS(PAD_SD1_DAT0__GPIO1_IO16) }, - IMX_GPIO_NR(1, 16), - { 0, 0 }, - 0 - }, - { - { IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) }, - IMX_GPIO_NR(1, 19), - { IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) }, - 2 - }, - { - { IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) }, - IMX_GPIO_NR(1, 17), - { IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) }, - 3 - }, - { - { IOMUX_PADS(PAD_SD1_CMD__GPIO1_IO18) }, - IMX_GPIO_NR(1, 18), - { IOMUX_PADS(PAD_SD1_CMD__PWM4_OUT) }, - 4 - }, - }, - .num_gpios = 4, + .dio_cfg = gw51xx_dio, + .dio_num = ARRAY_SIZE(gw51xx_dio), .leds = { IMX_GPIO_NR(4, 6), IMX_GPIO_NR(4, 10), @@ -428,33 +597,8 @@ struct ventana gpio_cfg[GW_UNKNOWN] = { { .gpio_pads = gw52xx_gpio_pads, .num_pads = ARRAY_SIZE(gw52xx_gpio_pads)/2, - .dio_cfg = { - { - { IOMUX_PADS(PAD_SD1_DAT0__GPIO1_IO16) }, - IMX_GPIO_NR(1, 16), - { 0, 0 }, - 0 - }, - { - { IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) }, - IMX_GPIO_NR(1, 19), - { IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) }, - 2 - }, - { - { IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) }, - IMX_GPIO_NR(1, 17), - { IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) }, - 3 - }, - { - { IOMUX_PADS(PAD_SD1_CLK__GPIO1_IO20) }, - IMX_GPIO_NR(1, 20), - { 0, 0 }, - 0 - }, - }, - .num_gpios = 4, + .dio_cfg = gw52xx_dio, + .dio_num = ARRAY_SIZE(gw52xx_dio), .leds = { IMX_GPIO_NR(4, 6), IMX_GPIO_NR(4, 7), @@ -468,39 +612,15 @@ struct ventana gpio_cfg[GW_UNKNOWN] = { .usb_sel = IMX_GPIO_NR(1, 2), .wdis = IMX_GPIO_NR(7, 12), .msata_en = GP_MSATA_SEL, + .rs232_en = GP_RS232_EN, }, /* GW53xx */ { .gpio_pads = gw53xx_gpio_pads, .num_pads = ARRAY_SIZE(gw53xx_gpio_pads)/2, - .dio_cfg = { - { - { IOMUX_PADS(PAD_SD1_DAT0__GPIO1_IO16) }, - IMX_GPIO_NR(1, 16), - { 0, 0 }, - 0 - }, - { - { IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) }, - IMX_GPIO_NR(1, 19), - { IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) }, - 2 - }, - { - { IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) }, - IMX_GPIO_NR(1, 17), - { IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) }, - 3 - }, - { - {IOMUX_PADS(PAD_SD1_CLK__GPIO1_IO20) }, - IMX_GPIO_NR(1, 20), - { 0, 0 }, - 0 - }, - }, - .num_gpios = 4, + .dio_cfg = gw53xx_dio, + .dio_num = ARRAY_SIZE(gw53xx_dio), .leds = { IMX_GPIO_NR(4, 6), IMX_GPIO_NR(4, 7), @@ -513,39 +633,15 @@ struct ventana gpio_cfg[GW_UNKNOWN] = { .vidin_en = IMX_GPIO_NR(3, 31), .wdis = IMX_GPIO_NR(7, 12), .msata_en = GP_MSATA_SEL, + .rs232_en = GP_RS232_EN, }, /* GW54xx */ { .gpio_pads = gw54xx_gpio_pads, .num_pads = ARRAY_SIZE(gw54xx_gpio_pads)/2, - .dio_cfg = { - { - { IOMUX_PADS(PAD_GPIO_9__GPIO1_IO09) }, - IMX_GPIO_NR(1, 9), - { IOMUX_PADS(PAD_GPIO_9__PWM1_OUT) }, - 1 - }, - { - { IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) }, - IMX_GPIO_NR(1, 19), - { IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) }, - 2 - }, - { - { IOMUX_PADS(PAD_SD4_DAT1__GPIO2_IO09) }, - IMX_GPIO_NR(2, 9), - { IOMUX_PADS(PAD_SD4_DAT1__PWM3_OUT) }, - 3 - }, - { - { IOMUX_PADS(PAD_SD4_DAT2__GPIO2_IO10) }, - IMX_GPIO_NR(2, 10), - { IOMUX_PADS(PAD_SD4_DAT2__PWM4_OUT) }, - 4 - }, - }, - .num_gpios = 4, + .dio_cfg = gw54xx_dio, + .dio_num = ARRAY_SIZE(gw54xx_dio), .leds = { IMX_GPIO_NR(4, 6), IMX_GPIO_NR(4, 7), @@ -560,27 +656,15 @@ struct ventana gpio_cfg[GW_UNKNOWN] = { .pcie_sson = IMX_GPIO_NR(1, 20), .wdis = IMX_GPIO_NR(5, 17), .msata_en = GP_MSATA_SEL, + .rs232_en = GP_RS232_EN, }, /* GW551x */ { .gpio_pads = gw551x_gpio_pads, .num_pads = ARRAY_SIZE(gw551x_gpio_pads)/2, - .dio_cfg = { - { - { IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) }, - IMX_GPIO_NR(1, 19), - { IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) }, - 2 - }, - { - { IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) }, - IMX_GPIO_NR(1, 17), - { IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) }, - 3 - }, - }, - .num_gpios = 2, + .dio_cfg = gw551x_dio, + .dio_num = ARRAY_SIZE(gw551x_dio), .leds = { IMX_GPIO_NR(4, 7), }, @@ -592,33 +676,8 @@ struct ventana gpio_cfg[GW_UNKNOWN] = { { .gpio_pads = gw552x_gpio_pads, .num_pads = ARRAY_SIZE(gw552x_gpio_pads)/2, - .dio_cfg = { - { - { IOMUX_PADS(PAD_SD1_DAT0__GPIO1_IO16) }, - IMX_GPIO_NR(1, 16), - { 0, 0 }, - 0 - }, - { - { IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) }, - IMX_GPIO_NR(1, 19), - { IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) }, - 2 - }, - { - { IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) }, - IMX_GPIO_NR(1, 17), - { IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) }, - 3 - }, - { - {IOMUX_PADS(PAD_SD1_CLK__GPIO1_IO20) }, - IMX_GPIO_NR(1, 20), - { 0, 0 }, - 0 - }, - }, - .num_gpios = 4, + .dio_cfg = gw552x_dio, + .dio_num = ARRAY_SIZE(gw552x_dio), .leds = { IMX_GPIO_NR(4, 6), IMX_GPIO_NR(4, 7), @@ -634,33 +693,8 @@ struct ventana gpio_cfg[GW_UNKNOWN] = { { .gpio_pads = gw553x_gpio_pads, .num_pads = ARRAY_SIZE(gw553x_gpio_pads)/2, - .dio_cfg = { - { - { IOMUX_PADS(PAD_SD1_DAT0__GPIO1_IO16) }, - IMX_GPIO_NR(1, 16), - { 0, 0 }, - 0 - }, - { - { IOMUX_PADS(PAD_SD1_DAT2__GPIO1_IO19) }, - IMX_GPIO_NR(1, 19), - { IOMUX_PADS(PAD_SD1_DAT2__PWM2_OUT) }, - 2 - }, - { - { IOMUX_PADS(PAD_SD1_DAT1__GPIO1_IO17) }, - IMX_GPIO_NR(1, 17), - { IOMUX_PADS(PAD_SD1_DAT1__PWM3_OUT) }, - 3 - }, - { - { IOMUX_PADS(PAD_SD1_CMD__GPIO1_IO18) }, - IMX_GPIO_NR(1, 18), - { IOMUX_PADS(PAD_SD1_CMD__PWM4_OUT) }, - 4 - }, - }, - .num_gpios = 4, + .dio_cfg = gw553x_dio, + .dio_num = ARRAY_SIZE(gw553x_dio), .leds = { IMX_GPIO_NR(4, 10), IMX_GPIO_NR(4, 11), @@ -682,10 +716,6 @@ void setup_iomux_gpio(int board, struct ventana_board_info *info) gpio_request(GP_USB_OTG_PWR, "usbotg_pwr"); gpio_direction_output(GP_USB_OTG_PWR, 0); - /* RS232_EN# */ - gpio_request(GP_RS232_EN, "rs232_en"); - gpio_direction_output(GP_RS232_EN, 0); - if (board >= GW_UNKNOWN) return; @@ -693,6 +723,12 @@ void setup_iomux_gpio(int board, struct ventana_board_info *info) imx_iomux_v3_setup_multiple_pads(gpio_cfg[board].gpio_pads, gpio_cfg[board].num_pads); + /* RS232_EN# */ + if (gpio_cfg[board].rs232_en) { + gpio_request(gpio_cfg[board].rs232_en, "rs232_en"); + gpio_direction_output(gpio_cfg[board].rs232_en, 0); + } + /* GW522x Uses GPIO3_IO23 for PCIE_RST# */ if (board == GW52xx && info->model[4] == '2') gpio_cfg[board].pcie_rst = IMX_GPIO_NR(3, 23); @@ -788,7 +824,10 @@ void setup_board_gpio(int board, struct ventana_board_info *info) return; /* RS232_EN# */ - gpio_direction_output(GP_RS232_EN, (hwconfig("rs232")) ? 0 : 1); + if (gpio_cfg[board].rs232_en) { + gpio_direction_output(gpio_cfg[board].rs232_en, + (hwconfig("rs232")) ? 0 : 1); + } /* MSATA Enable */ if (gpio_cfg[board].msata_en && is_cpu_type(MXC_CPU_MX6Q)) { @@ -806,7 +845,7 @@ void setup_board_gpio(int board, struct ventana_board_info *info) * Configure DIO pinmux/padctl registers * see IMX6DQRM/IMX6SDLRM IOMUXC_SW_PAD_CTL_PAD_* register definitions */ - for (i = 0; i < gpio_cfg[board].num_gpios; i++) { + for (i = 0; i < gpio_cfg[board].dio_num; i++) { struct dio_cfg *cfg = &gpio_cfg[board].dio_cfg[i]; iomux_v3_cfg_t ctrl = DIO_PAD_CFG; unsigned cputype = is_cpu_type(MXC_CPU_MX6Q) ? 0 : 1; @@ -851,8 +890,10 @@ void setup_board_gpio(int board, struct ventana_board_info *info) printf("MSATA: %s\n", (hwconfig("msata") ? "enabled" : "disabled")); } - printf("RS232: %s\n", (hwconfig("rs232")) ? - "enabled" : "disabled"); + if (gpio_cfg[board].rs232_en) { + printf("RS232: %s\n", (hwconfig("rs232")) ? + "enabled" : "disabled"); + } } } diff --git a/board/gateworks/gw_ventana/common.h b/board/gateworks/gw_ventana/common.h index d037767ecc..3d7aff1077 100644 --- a/board/gateworks/gw_ventana/common.h +++ b/board/gateworks/gw_ventana/common.h @@ -48,8 +48,8 @@ #define PC MUX_PAD_CTRL(I2C_PAD_CTRL) /* - * each baseboard has 4 user configurable Digital IO lines which can - * be pinmuxed as a GPIO or in some cases a PWM + * each baseboard has an optional set user configurable Digital IO lines which + * can be pinmuxed as a GPIO or in some cases a PWM */ struct dio_cfg { iomux_v3_cfg_t gpio_padmux[2]; @@ -63,8 +63,8 @@ struct ventana { iomux_v3_cfg_t const *gpio_pads; int num_pads; /* DIO pinmux/val */ - struct dio_cfg dio_cfg[4]; - int num_gpios; + struct dio_cfg *dio_cfg; + int dio_num; /* various gpios (0 if non-existent) */ int leds[3]; int pcie_rst; @@ -78,6 +78,8 @@ struct ventana { int usb_sel; int wdis; int msata_en; + int rs232_en; + /* various features */ bool usd_vsel; }; diff --git a/board/gateworks/gw_ventana/gw_ventana.c b/board/gateworks/gw_ventana/gw_ventana.c index 70395ac91d..5d871ceed9 100644 --- a/board/gateworks/gw_ventana/gw_ventana.c +++ b/board/gateworks/gw_ventana/gw_ventana.c @@ -491,14 +491,54 @@ int imx6_pcie_toggle_reset(void) * GPIO's as PERST# signals for its downstream ports - configure the GPIO's * properly and assert reset for 100ms. */ +#define MAX_PCI_DEVS 32 +struct pci_dev { + pci_dev_t devfn; + unsigned short vendor; + unsigned short device; + unsigned short class; + unsigned short busno; /* subbordinate busno */ + struct pci_dev *ppar; +}; +struct pci_dev pci_devs[MAX_PCI_DEVS]; +int pci_devno; +int pci_bridgeno; + void board_pci_fixup_dev(struct pci_controller *hose, pci_dev_t dev, unsigned short vendor, unsigned short device, unsigned short class) { + int i; u32 dw; + struct pci_dev *pdev = &pci_devs[pci_devno++]; debug("%s: %02d:%02d.%02d: %04x:%04x\n", __func__, PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev), vendor, device); + + /* store array of devs for later use in device-tree fixup */ + pdev->devfn = dev; + pdev->vendor = vendor; + pdev->device = device; + pdev->class = class; + pdev->ppar = NULL; + if (class == PCI_CLASS_BRIDGE_PCI) + pdev->busno = ++pci_bridgeno; + else + pdev->busno = 0; + + /* fixup RC - it should be 00:00.0 not 00:01.0 */ + if (PCI_BUS(dev) == 0) + pdev->devfn = 0; + + /* find dev's parent */ + for (i = 0; i < pci_devno; i++) { + if (pci_devs[i].busno == PCI_BUS(pdev->devfn)) { + pdev->ppar = &pci_devs[i]; + break; + } + } + + /* assert downstream PERST# */ if (vendor == PCI_VENDOR_ID_PLX && (device & 0xfff0) == 0x8600 && PCI_DEV(dev) == 0 && PCI_FUNC(dev) == 0) { @@ -660,13 +700,14 @@ static const struct boot_mode board_boot_modes[] = { int misc_init_r(void) { struct ventana_board_info *info = &ventana_info; + char buf[256]; + int i; /* set env vars based on EEPROM data */ if (ventana_info.model[0]) { char str[16], fdt[36]; char *p; const char *cputype = ""; - int i; /* * FDT name will be prefixed with CPU type. Three versions @@ -729,6 +770,19 @@ int misc_init_r(void) setenv("mem_mb", str); } + /* Set a non-initialized hwconfig based on board configuration */ + if (!strcmp(getenv("hwconfig"), "_UNKNOWN_")) { + sprintf(buf, "hwconfig="); + if (gpio_cfg[board_type].rs232_en) + strcat(buf, "rs232;"); + for (i = 0; i < gpio_cfg[board_type].dio_num; i++) { + char buf1[32]; + sprintf(buf1, "dio%d:mode=gpio;", i); + if (strlen(buf) + strlen(buf1) < sizeof(buf)) + strcat(buf, buf1); + } + setenv("hwconfig", buf); + } /* setup baseboard specific GPIO based on board and env */ setup_board_gpio(board_type, info); @@ -802,6 +856,224 @@ static inline void ft_delprop_path(void *blob, const char *path, } } +#if defined(CONFIG_CMD_PCI) +#define PCI_ID(x) ( \ + (PCI_BUS(x->devfn)<<16)| \ + (PCI_DEV(x->devfn)<<11)| \ + (PCI_FUNC(x->devfn)<<8) \ + ) +#define PCIE_PATH "/soc/pcie@0x01000000" +int fdt_add_pci_node(void *blob, int par, struct pci_dev *dev) +{ + uint32_t reg[5]; + char node[32]; + int np; + + sprintf(node, "pcie@%d,%d,%d", PCI_BUS(dev->devfn), + PCI_DEV(dev->devfn), PCI_FUNC(dev->devfn)); + + np = fdt_subnode_offset(blob, par, node); + if (np >= 0) + return np; + np = fdt_add_subnode(blob, par, node); + if (np < 0) { + printf(" %s failed: no space\n", __func__); + return np; + } + + memset(reg, 0, sizeof(reg)); + reg[0] = cpu_to_fdt32(PCI_ID(dev)); + fdt_setprop(blob, np, "reg", reg, sizeof(reg)); + + return np; +} + +/* build a path of nested PCI devs for all bridges passed through */ +int fdt_add_pci_path(void *blob, struct pci_dev *dev) +{ + struct pci_dev *bridges[MAX_PCI_DEVS]; + int k, np; + + /* build list of parents */ + np = fdt_path_offset(blob, PCIE_PATH); + if (np < 0) + return np; + + k = 0; + while (dev) { + bridges[k++] = dev; + dev = dev->ppar; + }; + + /* now add them the to DT in reverse order */ + while (k--) { + np = fdt_add_pci_node(blob, np, bridges[k]); + if (np < 0) + break; + } + + return np; +} + +/* + * The GW16082 has a hardware errata errata such that it's + * INTA/B/C/D are mis-mapped to its four slots (slot12-15). Because + * of this normal PCI interrupt swizzling will not work so we will + * provide an irq-map via device-tree. + */ +int fdt_fixup_gw16082(void *blob, int np, struct pci_dev *dev) +{ + int len; + int host; + uint32_t imap_new[8*4*4]; + const uint32_t *imap; + uint32_t irq[4]; + uint32_t reg[4]; + int i; + + /* build irq-map based on host controllers map */ + host = fdt_path_offset(blob, PCIE_PATH); + if (host < 0) { + printf(" %s failed: missing host\n", __func__); + return host; + } + + /* use interrupt data from root complex's node */ + imap = fdt_getprop(blob, host, "interrupt-map", &len); + if (!imap || len != 128) { + printf(" %s failed: invalid interrupt-map\n", + __func__); + return -FDT_ERR_NOTFOUND; + } + + /* obtain irq's of host controller in pin order */ + for (i = 0; i < 4; i++) + irq[(fdt32_to_cpu(imap[(i*8)+3])-1)%4] = imap[(i*8)+6]; + + /* + * determine number of swizzles necessary: + * For each bridge we pass through we need to swizzle + * the number of the slot we are on. + */ + struct pci_dev *d; + int b; + b = 0; + d = dev->ppar; + while(d && d->ppar) { + b += PCI_DEV(d->devfn); + d = d->ppar; + } + + /* create new irq mappings for slots12-15 + * <skt> <idsel> <slot> <skt-inta> <skt-intb> + * J3 AD28 12 INTD INTA + * J4 AD29 13 INTC INTD + * J5 AD30 14 INTB INTC + * J2 AD31 15 INTA INTB + */ + for (i = 0; i < 4; i++) { + /* addr matches bus:dev:func */ + u32 addr = dev->busno << 16 | (12+i) << 11; + + /* default cells from root complex */ + memcpy(&imap_new[i*32], imap, 128); + /* first cell is PCI device address (BDF) */ + imap_new[(i*32)+(0*8)+0] = cpu_to_fdt32(addr); + imap_new[(i*32)+(1*8)+0] = cpu_to_fdt32(addr); + imap_new[(i*32)+(2*8)+0] = cpu_to_fdt32(addr); + imap_new[(i*32)+(3*8)+0] = cpu_to_fdt32(addr); + /* third cell is pin */ + imap_new[(i*32)+(0*8)+3] = cpu_to_fdt32(1); + imap_new[(i*32)+(1*8)+3] = cpu_to_fdt32(2); + imap_new[(i*32)+(2*8)+3] = cpu_to_fdt32(3); + imap_new[(i*32)+(3*8)+3] = cpu_to_fdt32(4); + /* sixth cell is relative interrupt */ + imap_new[(i*32)+(0*8)+6] = irq[(15-(12+i)+b+0)%4]; + imap_new[(i*32)+(1*8)+6] = irq[(15-(12+i)+b+1)%4]; + imap_new[(i*32)+(2*8)+6] = irq[(15-(12+i)+b+2)%4]; + imap_new[(i*32)+(3*8)+6] = irq[(15-(12+i)+b+3)%4]; + } + fdt_setprop(blob, np, "interrupt-map", imap_new, + sizeof(imap_new)); + reg[0] = cpu_to_fdt32(0xfff00); + reg[1] = 0; + reg[2] = 0; + reg[3] = cpu_to_fdt32(0x7); + fdt_setprop(blob, np, "interrupt-map-mask", reg, sizeof(reg)); + fdt_setprop_cell(blob, np, "#interrupt-cells", 1); + fdt_setprop_string(blob, np, "device_type", "pci"); + fdt_setprop_cell(blob, np, "#address-cells", 3); + fdt_setprop_cell(blob, np, "#size-cells", 2); + printf(" Added custom interrupt-map for GW16082\n"); + + return 0; +} + +/* The sky2 GigE MAC obtains it's MAC addr from device-tree by default */ +int fdt_fixup_sky2(void *blob, int np, struct pci_dev *dev) +{ + char *tmp, *end; + char mac[16]; + unsigned char mac_addr[6]; + int j; + + sprintf(mac, "eth1addr"); + tmp = getenv(mac); + if (tmp) { + for (j = 0; j < 6; j++) { + mac_addr[j] = tmp ? + simple_strtoul(tmp, &end,16) : 0; + if (tmp) + tmp = (*end) ? end+1 : end; + } + fdt_setprop(blob, np, "local-mac-address", mac_addr, + sizeof(mac_addr)); + printf(" Added mac addr for eth1\n"); + return 0; + } + + return -1; +} + +/* + * PCI DT nodes must be nested therefore if we need to apply a DT fixup + * we will walk the PCI bus and add bridge nodes up to the device receiving + * the fixup. + */ +void ft_board_pci_fixup(void *blob, bd_t *bd) +{ + int i, np; + struct pci_dev *dev; + + for (i = 0; i < pci_devno; i++) { + dev = &pci_devs[i]; + + /* + * The GW16082 consists of a TI XIO2001 PCIe-to-PCI bridge and + * an EEPROM at i2c1-0x50. + */ + if ((dev->vendor == PCI_VENDOR_ID_TI) && + (dev->device == 0x8240) && + (i2c_set_bus_num(1) == 0) && + (i2c_probe(0x50) == 0)) + { + np = fdt_add_pci_path(blob, dev); + if (np > 0) + fdt_fixup_gw16082(blob, np, dev); + } + + /* ethernet1 mac address */ + else if ((dev->vendor == PCI_VENDOR_ID_MARVELL) && + (dev->device == 0x4380)) + { + np = fdt_add_pci_path(blob, dev); + if (np > 0) + fdt_fixup_sky2(blob, np, dev); + } + } +} +#endif /* if defined(CONFIG_CMD_PCI) */ + /* * called prior to booting kernel or by 'fdt boardsetup' command * @@ -811,6 +1083,10 @@ static inline void ft_delprop_path(void *blob, const char *path, * - board (full model from EEPROM) * - peripherals removed from DTB if not loaded on board (per EEPROM config) */ +#define UART1_PATH "/soc/aips-bus@02100000/serial@021ec000" +#define WDOG1_PATH "/soc/aips-bus@02000000/wdog@020bc000" +#define WDOG2_PATH "/soc/aips-bus@02000000/wdog@020c0000" +#define GPIO3_PATH "/soc/aips-bus@02000000/gpio@020a4000" int ft_board_setup(void *blob, bd_t *bd) { struct ventana_board_info *info = &ventana_info; @@ -864,94 +1140,140 @@ int ft_board_setup(void *blob, bd_t *bd) ft_sethdmiinfmt(blob, getenv("hdmiinfmt")); /* - * disable serial2 node for GW54xx for compatibility with older - * 3.10.x kernel that improperly had this node enabled in the DT + * Board model specific fixups */ - if (board_type == GW54xx) { - i = fdt_path_offset(blob, - "/soc/aips-bus@02100000/serial@021ec000"); - if (i) - fdt_del_node(blob, i); - } - - /* - * disable wdog1/wdog2 nodes for GW51xx below revC to work around - * errata causing wdog timer to be unreliable. - */ - if (board_type == GW51xx && rev >= 'A' && rev < 'C') { - i = fdt_path_offset(blob, - "/soc/aips-bus@02000000/wdog@020bc000"); - if (i) - fdt_status_disabled(blob, i); - } + switch (board_type) { + case GW51xx: + /* + * disable wdog node for GW51xx-A/B to work around + * errata causing wdog timer to be unreliable. + */ + if (rev >= 'A' && rev < 'C') { + i = fdt_path_offset(blob, WDOG1_PATH); + if (i) + fdt_status_disabled(blob, i); + } - /* GW522x Uses GPIO3_IO23 instead of GPIO1_IO29 */ - else if (board_type == GW52xx && info->model[4] == '2') { - u32 handle = 0; - u32 *range = NULL; + /* GW51xx-E adds WDOG1_B external reset */ + if (rev < 'E') + ft_delprop_path(blob, WDOG1_PATH, + "fsl,ext-reset-output"); + break; - i = fdt_node_offset_by_compatible(blob, -1, "fsl,imx6q-pcie"); - if (i) - range = (u32 *)fdt_getprop(blob, i, "reset-gpio", - NULL); + case GW52xx: + /* GW522x Uses GPIO3_IO23 instead of GPIO1_IO29 */ + if (info->model[4] == '2') { + u32 handle = 0; + u32 *range = NULL; - if (range) { - i = fdt_path_offset(blob, - "/soc/aips-bus@02000000/gpio@020a4000"); + i = fdt_node_offset_by_compatible(blob, -1, + "fsl,imx6q-pcie"); if (i) - handle = fdt_get_phandle(blob, i); - if (handle) { - range[0] = cpu_to_fdt32(handle); - range[1] = cpu_to_fdt32(23); + range = (u32 *)fdt_getprop(blob, i, + "reset-gpio", NULL); + + if (range) { + i = fdt_path_offset(blob, GPIO3_PATH); + if (i) + handle = fdt_get_phandle(blob, i); + if (handle) { + range[0] = cpu_to_fdt32(handle); + range[1] = cpu_to_fdt32(23); + } } - } - /* these have broken usd_vsel */ - if (strstr((const char *)info->model, "SP318-B") || - strstr((const char *)info->model, "SP331-B")) - gpio_cfg[board_type].usd_vsel = 0; - } + /* these have broken usd_vsel */ + if (strstr((const char *)info->model, "SP318-B") || + strstr((const char *)info->model, "SP331-B")) + gpio_cfg[board_type].usd_vsel = 0; - /* - * isolate CSI0_DATA_EN for GW551x below revB to work around - * errata causing non functional digital video in (it is not hooked up) - */ - else if (board_type == GW551x && rev == 'A') { - u32 *range = NULL; - int len; - const u32 *handle = NULL; + /* GW520x-E adds WDOG1_B external reset */ + if (info->model[4] == '0' && rev < 'E') + ft_delprop_path(blob, WDOG1_PATH, + "fsl,ext-reset-output"); - i = fdt_node_offset_by_compatible(blob, -1, - "fsl,imx-tda1997x-video"); - if (i) - handle = fdt_getprop(blob, i, "pinctrl-0", NULL); - if (handle) - i = fdt_node_offset_by_phandle(blob, - fdt32_to_cpu(*handle)); + /* GW522x-B adds WDOG1_B external reset */ + if (info->model[4] == '2' && rev < 'B') + ft_delprop_path(blob, WDOG1_PATH, + "fsl,ext-reset-output"); + } + break; + + case GW53xx: + /* GW53xx-E adds WDOG1_B external reset */ + if (rev < 'E') + ft_delprop_path(blob, WDOG1_PATH, + "fsl,ext-reset-output"); + break; + + case GW54xx: + /* + * disable serial2 node for GW54xx for compatibility with older + * 3.10.x kernel that improperly had this node enabled in the DT + */ + i = fdt_path_offset(blob, UART1_PATH); if (i) - range = (u32 *)fdt_getprop(blob, i, "fsl,pins", &len); - if (range) { - len /= sizeof(u32); - for (i = 0; i < len; i += 6) { - u32 mux_reg = fdt32_to_cpu(range[i+0]); - u32 conf_reg = fdt32_to_cpu(range[i+1]); - /* mux PAD_CSI0_DATA_EN to GPIO */ - if (is_cpu_type(MXC_CPU_MX6Q) && - mux_reg == 0x260 && conf_reg == 0x630) - range[i+3] = cpu_to_fdt32(0x5); - else if (!is_cpu_type(MXC_CPU_MX6Q) && - mux_reg == 0x08c && conf_reg == 0x3a0) - range[i+3] = cpu_to_fdt32(0x5); + fdt_del_node(blob, i); + + /* GW54xx-E adds WDOG2_B external reset */ + if (rev < 'E') + ft_delprop_path(blob, WDOG2_PATH, + "fsl,ext-reset-output"); + break; + + case GW551x: + /* + * isolate CSI0_DATA_EN for GW551x-A to work around errata + * causing non functional digital video in (it is not hooked up) + */ + if (rev == 'A') { + u32 *range = NULL; + int len; + const u32 *handle = NULL; + + i = fdt_node_offset_by_compatible(blob, -1, + "fsl,imx-tda1997x-video"); + if (i) + handle = fdt_getprop(blob, i, "pinctrl-0", + NULL); + if (handle) + i = fdt_node_offset_by_phandle(blob, + fdt32_to_cpu(*handle)); + if (i) + range = (u32 *)fdt_getprop(blob, i, "fsl,pins", + &len); + if (range) { + len /= sizeof(u32); + for (i = 0; i < len; i += 6) { + u32 mux_reg = fdt32_to_cpu(range[i+0]); + u32 conf_reg = fdt32_to_cpu(range[i+1]); + /* mux PAD_CSI0_DATA_EN to GPIO */ + if (is_cpu_type(MXC_CPU_MX6Q) && + mux_reg == 0x260 && + conf_reg == 0x630) + range[i+3] = cpu_to_fdt32(0x5); + else if (!is_cpu_type(MXC_CPU_MX6Q) && + mux_reg == 0x08c && + conf_reg == 0x3a0) + range[i+3] = cpu_to_fdt32(0x5); + } + fdt_setprop_inplace(blob, i, "fsl,pins", range, + len); } - fdt_setprop_inplace(blob, i, "fsl,pins", range, len); + + /* set BT656 video format */ + ft_sethdmiinfmt(blob, "yuv422bt656"); } - /* set BT656 video format */ - ft_sethdmiinfmt(blob, "yuv422bt656"); + /* GW551x-C adds WDOG1_B external reset */ + if (rev < 'C') + ft_delprop_path(blob, WDOG1_PATH, + "fsl,ext-reset-output"); + break; } /* Configure DIO */ - for (i = 0; i < gpio_cfg[board_type].num_gpios; i++) { + for (i = 0; i < gpio_cfg[board_type].dio_num; i++) { struct dio_cfg *cfg = &gpio_cfg[board_type].dio_cfg[i]; char arg[10]; @@ -976,6 +1298,11 @@ int ft_board_setup(void *blob, bd_t *bd) "no-1-8-v"); } +#if defined(CONFIG_CMD_PCI) + if (!getenv("nopcifixup")) + ft_board_pci_fixup(blob, bd); +#endif + /* * Peripheral Config: * remove nodes by alias path if EEPROM config tells us the |