imx: ventana: add support for GW5905
authorTim Harvey <tharvey@gateworks.com>
Mon, 4 Feb 2019 21:10:50 +0000 (13:10 -0800)
committerStefano Babic <sbabic@denx.de>
Fri, 15 Feb 2019 21:01:15 +0000 (22:01 +0100)
The GW5905 is single-board tablet computer based on the i.MX6 SoC with the
following peripheral set:
 - eMMC flash (boot device)
 - microSD expansion
 - LVDS display connector for off-board 3D+1C with PWM backlight
   and I2C based touch controller
 - MIPI camera connector supporting the TRULY CM8487-B500SA-E (OV5640)
 - ublox EMMY-W1 WiFi/Bluetooth/NFC module (SDIO/UART)
 - ublox ZOE-M8Q GPS
 - LSM9DS1 9-DOF IMU
 - 1x 1-lane miniPCIe socket with USB 2.0
 - Gateworks System Controller
 - Audio jack with TLV320AIC Audio Codec, Speaker AMP
   and TSA227E Headphone detect
 - MAX8607 3-mode LED camera flash
 - DECT ULE module
 - FUSB302 USB-C PD and ISL9238 Battery charger

Signed-off-by: Tim Harvey <tharvey@gateworks.com>
board/gateworks/gw_ventana/common.c
board/gateworks/gw_ventana/eeprom.c
board/gateworks/gw_ventana/gsc.c
board/gateworks/gw_ventana/gsc.h
board/gateworks/gw_ventana/gw_ventana.c
board/gateworks/gw_ventana/gw_ventana_spl.c
board/gateworks/gw_ventana/ventana_eeprom.h

index 676a1a8..b962b4b 100644 (file)
@@ -457,6 +457,47 @@ static iomux_v3_cfg_t const gw5904_gpio_pads[] = {
        IOMUX_PADS(PAD_SD2_DAT2__GPIO1_IO13 | DIO_PAD_CFG),
 };
 
+static iomux_v3_cfg_t const gw5905_gpio_pads[] = {
+       /* EMMY_PDN# */
+       IOMUX_PADS(PAD_NANDF_D3__GPIO2_IO03 | DIO_PAD_CFG),
+       /* MX6_LOCLED# */
+       IOMUX_PADS(PAD_NANDF_CS1__GPIO6_IO14 | DIO_PAD_CFG),
+       /* MIPI_RST */
+       IOMUX_PADS(PAD_SD2_DAT0__GPIO1_IO15 | DIO_PAD_CFG),
+       /* MIPI_PWDN */
+       IOMUX_PADS(PAD_SD2_DAT1__GPIO1_IO14 | DIO_PAD_CFG),
+       /* USBEHCI_SEL */
+       IOMUX_PADS(PAD_GPIO_7__GPIO1_IO07 | DIO_PAD_CFG),
+       /* PCI_RST# */
+       IOMUX_PADS(PAD_GPIO_16__GPIO7_IO11 | DIO_PAD_CFG),
+       /* LVDS_BKLEN # */
+       IOMUX_PADS(PAD_GPIO_17__GPIO7_IO12 | DIO_PAD_CFG),
+       /* PCIESKT_WDIS# */
+       IOMUX_PADS(PAD_GPIO_18__GPIO7_IO13 | DIO_PAD_CFG),
+       /* SPK_SHDN# */
+       IOMUX_PADS(PAD_GPIO_19__GPIO4_IO05 | DIO_PAD_CFG),
+       /* LOCLED# */
+       IOMUX_PADS(PAD_NANDF_CS1__GPIO6_IO14 | DIO_PAD_CFG),
+       /* FLASH LED1 */
+       IOMUX_PADS(PAD_DISP0_DAT11__GPIO5_IO05 | DIO_PAD_CFG),
+       /* FLASH LED2 */
+       IOMUX_PADS(PAD_DISP0_DAT12__GPIO5_IO06 | DIO_PAD_CFG),
+       /* DECT_RST# */
+       IOMUX_PADS(PAD_DISP0_DAT20__GPIO5_IO14 | DIO_PAD_CFG),
+       /* USBH1_PEN (EHCI) */
+       IOMUX_PADS(PAD_EIM_D31__GPIO3_IO31 | DIO_PAD_CFG),
+       /* LVDS_PWM */
+       IOMUX_PADS(PAD_GPIO_9__GPIO1_IO09 | DIO_PAD_CFG),
+       /* CODEC_RST */
+       IOMUX_PADS(PAD_DISP0_DAT23__GPIO5_IO17 | DIO_PAD_CFG),
+       /* GYRO_CONTROL/DATA_EN */
+       IOMUX_PADS(PAD_CSI0_DAT8__GPIO5_IO26 | DIO_PAD_CFG),
+       /* TOUCH_RST */
+       IOMUX_PADS(PAD_KEY_COL1__GPIO4_IO08 | DIO_PAD_CFG),
+       /* TOUCH_IRQ */
+       IOMUX_PADS(PAD_KEY_COL0__GPIO4_IO06 | DIO_PAD_CFG),
+};
+
 /* Digital I/O */
 struct dio_cfg gw51xx_dio[] = {
        {
@@ -993,8 +1034,25 @@ struct ventana gpio_cfg[GW_UNKNOWN] = {
                .mezz_irq = IMX_GPIO_NR(2, 18),
                .otgpwr_en = IMX_GPIO_NR(3, 22),
        },
+
+       /* GW5905 */
+       {
+               .gpio_pads = gw5905_gpio_pads,
+               .num_pads = ARRAY_SIZE(gw5905_gpio_pads)/2,
+               .leds = {
+                       IMX_GPIO_NR(6, 14),
+               },
+               .pcie_rst = IMX_GPIO_NR(7, 11),
+               .wdis = IMX_GPIO_NR(7, 13),
+       },
 };
 
+#define SETUP_GPIO_OUTPUT(gpio, name, level) \
+       gpio_request(gpio, name); \
+       gpio_direction_output(gpio, level);
+#define SETUP_GPIO_INPUT(gpio, name) \
+       gpio_request(gpio, name); \
+       gpio_direction_input(gpio);
 void setup_iomux_gpio(int board, struct ventana_board_info *info)
 {
        int i;
@@ -1143,6 +1201,28 @@ void setup_iomux_gpio(int board, struct ventana_board_info *info)
                gpio_request(IMX_GPIO_NR(1, 13), "m2_rst#");
                gpio_direction_output(IMX_GPIO_NR(1, 13), 1);
                break;
+       case GW5905:
+               SETUP_GPIO_OUTPUT(IMX_GPIO_NR(1, 7), "usb_pcisel", 0);
+               SETUP_GPIO_OUTPUT(IMX_GPIO_NR(1, 9), "lvds_cabc", 1);
+               SETUP_GPIO_OUTPUT(IMX_GPIO_NR(1, 14), "mipi_pdwn", 1);
+               SETUP_GPIO_OUTPUT(IMX_GPIO_NR(1, 15), "mipi_rst#", 0);
+               SETUP_GPIO_OUTPUT(IMX_GPIO_NR(2, 3), "emmy_pdwn#", 1);
+               SETUP_GPIO_OUTPUT(IMX_GPIO_NR(4, 5), "spk_shdn#", 0);
+               SETUP_GPIO_OUTPUT(IMX_GPIO_NR(4, 8), "touch_rst", 0);
+               SETUP_GPIO_OUTPUT(IMX_GPIO_NR(4, 6), "touch_irq", 0);
+               SETUP_GPIO_OUTPUT(IMX_GPIO_NR(5, 5), "flash_en1", 0);
+               SETUP_GPIO_OUTPUT(IMX_GPIO_NR(5, 6), "flash_en2", 0);
+               SETUP_GPIO_OUTPUT(IMX_GPIO_NR(5, 14), "dect_rst#", 1);
+               SETUP_GPIO_OUTPUT(IMX_GPIO_NR(5, 17), "codec_rst#", 0);
+               SETUP_GPIO_OUTPUT(IMX_GPIO_NR(5, 26), "imu_den", 1);
+               SETUP_GPIO_OUTPUT(IMX_GPIO_NR(7, 12), "lvds_cabc", 0);
+               mdelay(100);
+               /*
+                * gauruntee touch controller comes out of reset with INT
+                * low for address
+                */
+               SETUP_GPIO_OUTPUT(IMX_GPIO_NR(4, 8), "touch_rst", 1);
+               break;
        }
 }
 
@@ -1292,7 +1372,7 @@ void setup_pmic(void)
                        pmic_reg_write(p, LTC3676_DVB3A, 0x1f);
                        break;
                case GW5903:
-                       /* mask PGOOD during SW1 transition */
+                       /* mask PGOOD during SW3 transition */
                        pmic_reg_write(p, LTC3676_DVB3B,
                                       0x1f | LTC3676_PGOOD_MASK);
                        /* set SW3 (VDD_ARM) */
@@ -1304,6 +1384,19 @@ void setup_pmic(void)
                        /* set SW4 (VDD_SOC) */
                        pmic_reg_write(p, LTC3676_DVB4A, 0x1f);
                        break;
+               case GW5905:
+                       /* mask PGOOD during SW1 transition */
+                       pmic_reg_write(p, LTC3676_DVB1B,
+                                      0x1f | LTC3676_PGOOD_MASK);
+                       /* set SW1 (VDD_ARM) */
+                       pmic_reg_write(p, LTC3676_DVB1A, 0x1f);
+
+                       /* mask PGOOD during SW3 transition */
+                       pmic_reg_write(p, LTC3676_DVB3B,
+                                      0x1f | LTC3676_PGOOD_MASK);
+                       /* set SW3 (VDD_SOC) */
+                       pmic_reg_write(p, LTC3676_DVB3A, 0x1f);
+                       break;
                default:
                        /* mask PGOOD during SW1 transition */
                        pmic_reg_write(p, LTC3676_DVB1B,
@@ -1371,6 +1464,7 @@ int board_mmc_init(bd_t *bis)
                usdhc_cfg[1].max_bus_width = 4;
                return fsl_esdhc_initialize(bis, &usdhc_cfg[1]);
        case GW5904:
+       case GW5905:
                /* usdhc3: 8bit eMMC */
                SETUP_IOMUX_PADS(gw5904_emmc_pads);
                usdhc_cfg[0].esdhc_base = USDHC3_BASE_ADDR;
@@ -1399,6 +1493,7 @@ int board_mmc_getcd(struct mmc *mmc)
                break;
        case GW5903:
        case GW5904:
+       case GW5905:
                /* emmc is always present */
                if (cfg->esdhc_base == USDHC3_BASE_ADDR)
                        return 1;
index f0ae820..13ccf2b 100644 (file)
@@ -99,8 +99,10 @@ read_eeprom(int bus, struct ventana_board_info *info)
        case '9':
                if (info->model[4] == '0' && info->model[5] == '3')
                        type = GW5903;
-               if (info->model[4] == '0' && info->model[5] == '4')
+               else if (info->model[4] == '0' && info->model[5] == '4')
                        type = GW5904;
+               else if (info->model[4] == '0' && info->model[5] == '5')
+                       type = GW5905;
                break;
        }
        return type;
index c31ef11..068f8cd 100644 (file)
@@ -70,7 +70,7 @@ static void read_hwmon(const char *name, uint reg, uint size)
                puts("fRD\n");
        } else {
                ui = buf[0] | (buf[1]<<8) | (buf[2]<<16);
-               if (reg == GSC_HWMON_TEMP && ui > 0x8000)
+               if (size == 2 && ui > 0x8000)
                        ui -= 0xffff;
                if (ui == 0xffffff)
                        puts("invalid\n");
@@ -140,6 +140,10 @@ int gsc_info(int verbose)
                read_hwmon("VDD_IO4",  GSC_HWMON_VDD_IO4, 3);
                read_hwmon("VDD_GPS",  GSC_HWMON_VDD_IO3, 3);
                break;
+       case '9': /* GW590x */
+               read_hwmon("AMONBMON",  GSC_HWMON_VDD_IO3, 3);
+               read_hwmon("BAT_VOLT",  GSC_HWMON_VDD_EXT, 3);
+               read_hwmon("BAT_TEMP",  GSC_HWMON_VDD_IO4, 2);
        }
        return 0;
 }
index 0cce9b1..6dcaafa 100644 (file)
@@ -48,9 +48,10 @@ enum {
        GSC_HWMON_VBATT         = 0x08,
        GSC_HWMON_VDD_5P0       = 0x0b,
        GSC_HWMON_VDD_CORE      = 0x0e,
+       GSC_HWMON_VDD_SOC       = 0x11,
        GSC_HWMON_VDD_HIGH      = 0x14,
        GSC_HWMON_VDD_DDR       = 0x17,
-       GSC_HWMON_VDD_SOC       = 0x11,
+       GSC_HWMON_VDD_EXT       = 0x1a,
        GSC_HWMON_VDD_1P8       = 0x1d,
        GSC_HWMON_VDD_IO2       = 0x20,
        GSC_HWMON_VDD_2P5       = 0x23,
index c0b0cc9..e1ad0fc 100644 (file)
@@ -709,7 +709,7 @@ static const struct boot_mode board_boot_modes[] = {
        /* NAND: 64pages per block, 3 row addr cycles, 2 copies of FCB/DBBT */
        { "nand", MAKE_CFGVAL(0x80, 0x02, 0x00, 0x00) },
        { "emmc2", MAKE_CFGVAL(0x60, 0x48, 0x00, 0x00) }, /* GW5600 */
-       { "emmc3", MAKE_CFGVAL(0x60, 0x50, 0x00, 0x00) }, /* GW5903/GW5904 */
+       { "emmc3", MAKE_CFGVAL(0x60, 0x50, 0x00, 0x00) }, /* GW5903/4/5 */
        { NULL, 0 },
 };
 #endif
index 80ade9f..280493d 100644 (file)
@@ -390,6 +390,25 @@ static struct mx6_mmdc_calibration mx6sdl_256x64x2_mmdc_calib = {
        .p1_mpwrdlctl   = 0x3F36363F,
 };
 
+static struct mx6_mmdc_calibration mx6sdl_128x64x2_mmdc_calib = {
+       /* write leveling calibration determine */
+       .p0_mpwldectrl0 = 0x001F003F,
+       .p0_mpwldectrl1 = 0x001F001F,
+       .p1_mpwldectrl0 = 0x001F004E,
+       .p1_mpwldectrl1 = 0x0059001F,
+       /* Read DQS Gating calibration */
+       .p0_mpdgctrl0   = 0x42220225,
+       .p0_mpdgctrl1   = 0x0213021F,
+       .p1_mpdgctrl0   = 0x022C0242,
+       .p1_mpdgctrl1   = 0x022C0244,
+       /* Read Calibration: DQS delay relative to DQ read access */
+       .p0_mprddlctl   = 0x474A4C4A,
+       .p1_mprddlctl   = 0x48494C45,
+       /* Write Calibration: DQ/DM delay relative to DQS write access */
+       .p0_mpwrdlctl   = 0x3F3F3F36,
+       .p1_mpwrdlctl   = 0x3F36363F,
+};
+
 static struct mx6_mmdc_calibration mx6dq_512x32_mmdc_calib = {
        /* write leveling calibration determine */
        .p0_mpwldectrl0 = 0x002A0025,
@@ -519,18 +538,33 @@ static void spl_dram_init(int width, int size_mb, int board_model)
                        calib = &mx6sdl_128x64_mmdc_calib;
                debug("2gB density\n");
        } else if (width == 64 && size_mb == 2048) {
-               mem = &mt41k256m16ha_125;
-               if (is_cpu_type(MXC_CPU_MX6Q))
-                       calib = &mx6dq_256x64_mmdc_calib;
-               else
-                       calib = &mx6sdl_256x64_mmdc_calib;
-               debug("4gB density\n");
+               switch(board_model) {
+               case GW5905:
+                       /* 8xMT41K128M16 (2GiB) fly-by mirrored 2-chipsels */
+                       mem = &mt41k128m16jt_125;
+                       debug("2gB density - 2 chipsel\n");
+                       if (!is_cpu_type(MXC_CPU_MX6Q)) {
+                               calib = &mx6sdl_128x64x2_mmdc_calib;
+                               sysinfo.ncs = 2;
+                               sysinfo.cs_density = 10; /* CS0_END=39 */
+                               sysinfo.cs1_mirror = 1; /* mirror enabled */
+                       }
+                       break;
+               default:
+                       mem = &mt41k256m16ha_125;
+                       if (is_cpu_type(MXC_CPU_MX6Q))
+                               calib = &mx6dq_256x64_mmdc_calib;
+                       else
+                               calib = &mx6sdl_256x64_mmdc_calib;
+                       debug("4gB density\n");
+                       break;
+               }
        } else if (width == 64 && size_mb == 4096) {
                switch(board_model) {
                case GW5903:
                        /* 8xMT41K256M16 (4GiB) fly-by mirrored 2-chipsels */
                        mem = &mt41k256m16ha_125;
-                       debug("4gB density\n");
+                       debug("4gB density - 2 chipsel\n");
                        if (!is_cpu_type(MXC_CPU_MX6Q)) {
                                calib = &mx6sdl_256x64x2_mmdc_calib;
                                sysinfo.ncs = 2;
index d2a16f1..f2d8737 100644 (file)
@@ -114,6 +114,7 @@ enum {
        GW560x,
        GW5903,
        GW5904,
+       GW5905,
        GW_UNKNOWN,
        GW_BADCRC,
 };