From patchwork Wed Jul 1 17:26:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Reichel X-Patchwork-Id: 240637 List-Id: U-Boot discussion From: sebastian.reichel at collabora.com (Sebastian Reichel) Date: Wed, 1 Jul 2020 19:26:14 +0200 Subject: [PATCH 01/12] treewide: Replace CONFIG_DM_SPI_FLASH with CONFIG_IS_ENABLED(DM_SPI_FLASH) In-Reply-To: <20200701172625.121978-1-sebastian.reichel@collabora.com> References: <20200701172625.121978-1-sebastian.reichel@collabora.com> Message-ID: <20200701172625.121978-2-sebastian.reichel@collabora.com> From: Marek Vasut Perform the replacement to allow platforms use non-DM SPI flash access in SPL/TPL. This is thus far needed on platforms with size constraints. Signed-off-by: Marek Vasut Signed-off-by: Sebastian Reichel --- cmd/sf.c | 4 ++-- drivers/mtd/spi/sf_probe.c | 2 +- drivers/net/fm/fm.c | 4 ++-- include/spi_flash.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/sf.c b/cmd/sf.c index d18f6a888ce4..a6fed36b7c3e 100644 --- a/cmd/sf.c +++ b/cmd/sf.c @@ -91,7 +91,7 @@ static int do_spi_flash_probe(int argc, char *const argv[]) unsigned int speed = CONFIG_SF_DEFAULT_SPEED; unsigned int mode = CONFIG_SF_DEFAULT_MODE; char *endp; -#ifdef CONFIG_DM_SPI_FLASH +#if CONFIG_IS_ENABLED(CONFIG_DM_SPI_FLASH) struct udevice *new, *bus_dev; int ret; #else @@ -124,7 +124,7 @@ static int do_spi_flash_probe(int argc, char *const argv[]) return -1; } -#ifdef CONFIG_DM_SPI_FLASH +#if CONFIG_IS_ENABLED(CONFIG_DM_SPI_FLASH) /* Remove the old device, otherwise probe will just be a nop */ ret = spi_find_bus_and_cs(bus, cs, &bus_dev, &new); if (!ret) { diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 3548d6319b30..afda241dd067 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -53,7 +53,7 @@ err_read_id: return ret; } -#ifndef CONFIG_DM_SPI_FLASH +#if !CONFIG_IS_ENABLED(DM_SPI_FLASH) struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs, unsigned int max_hz, unsigned int spi_mode) { diff --git a/drivers/net/fm/fm.c b/drivers/net/fm/fm.c index 8ab18163954c..bbb1738c4bdc 100644 --- a/drivers/net/fm/fm.c +++ b/drivers/net/fm/fm.c @@ -383,7 +383,7 @@ int fm_init_common(int index, struct ccsr_fman *reg) addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH); int ret = 0; -#ifdef CONFIG_DM_SPI_FLASH +#if CONFIG_IS_ENABLED(DM_SPI_FLASH) struct udevice *new; /* speed and mode will be read from DT */ @@ -470,7 +470,7 @@ int fm_init_common(int index, struct ccsr_fman *reg) void *addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH); int ret = 0; -#ifdef CONFIG_DM_SPI_FLASH +#if CONFIG_IS_ENABLED(DM_SPI_FLASH) struct udevice *new; /* speed and mode will be read from DT */ diff --git a/include/spi_flash.h b/include/spi_flash.h index d9b2af856c08..b33661948765 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -39,7 +39,7 @@ struct dm_spi_flash_ops { /* Access the serial operations for a device */ #define sf_get_ops(dev) ((struct dm_spi_flash_ops *)(dev)->driver->ops) -#ifdef CONFIG_DM_SPI_FLASH +#if CONFIG_IS_ENABLED(DM_SPI_FLASH) /** * spi_flash_read_dm() - Read data from SPI flash * From patchwork Wed Jul 1 17:26:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Reichel X-Patchwork-Id: 240636 List-Id: U-Boot discussion From: sebastian.reichel at collabora.com (Sebastian Reichel) Date: Wed, 1 Jul 2020 19:26:15 +0200 Subject: [PATCH 02/12] bootcount: add a DM SPI flash backing store for bootcount In-Reply-To: <20200701172625.121978-1-sebastian.reichel@collabora.com> References: <20200701172625.121978-1-sebastian.reichel@collabora.com> Message-ID: <20200701172625.121978-3-sebastian.reichel@collabora.com> This driver allows to use SPI flash as backing store for boot counter values with DM enabled. Signed-off-by: Sebastian Reichel --- drivers/bootcount/Kconfig | 10 +++ drivers/bootcount/Makefile | 1 + drivers/bootcount/spi-flash.c | 125 ++++++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 drivers/bootcount/spi-flash.c diff --git a/drivers/bootcount/Kconfig b/drivers/bootcount/Kconfig index c8e6fa7f8925..b5ccea0d9c20 100644 --- a/drivers/bootcount/Kconfig +++ b/drivers/bootcount/Kconfig @@ -108,6 +108,16 @@ config DM_BOOTCOUNT_I2C_EEPROM pointing to the underlying i2c eeprom device) and an optional 'offset' property are supported. +config DM_BOOTCOUNT_SPI_FLASH + bool "Support SPI flash devices as a backing store for bootcount" + depends on DM_SPI_FLASH + help + Enabled reading/writing the bootcount in a DM SPI flash device. + The wrapper device is to be specified with the compatible string + 'u-boot,bootcount-spi-flash' and the 'spi-flash'-property (a phandle + pointing to the underlying SPI flash device) and an optional 'offset' + property are supported. + config BOOTCOUNT_MEM bool "Support memory based bootcounter" help diff --git a/drivers/bootcount/Makefile b/drivers/bootcount/Makefile index 059d40d16b0c..51d860b00e18 100644 --- a/drivers/bootcount/Makefile +++ b/drivers/bootcount/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_BOOTCOUNT_EXT) += bootcount_ext.o obj-$(CONFIG_DM_BOOTCOUNT) += bootcount-uclass.o obj-$(CONFIG_DM_BOOTCOUNT_RTC) += rtc.o obj-$(CONFIG_DM_BOOTCOUNT_I2C_EEPROM) += i2c-eeprom.o +obj-$(CONFIG_DM_BOOTCOUNT_SPI_FLASH) += spi-flash.o diff --git a/drivers/bootcount/spi-flash.c b/drivers/bootcount/spi-flash.c new file mode 100644 index 000000000000..7cd388e6616c --- /dev/null +++ b/drivers/bootcount/spi-flash.c @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2019 Collabora + * (C) Copyright 2019 GE + */ + +#include +#include +#include +#include + +static const u8 bootcount_magic = 0xbc; + +struct bootcount_spi_flash_priv { + struct udevice *spi_flash; + u32 offset; +}; + +static int bootcount_spi_flash_update(struct udevice *dev, u32 offset, u32 len, const void *buf) +{ + struct spi_flash *flash = dev_get_uclass_priv(dev); + u32 sector_size = flash->sector_size; + u32 sector_offset = offset % sector_size; + u32 sector = offset - sector_offset; + int err = 0; + + /* code only supports updating a single sector */ + if (sector_offset + len > sector_size) + return -ENOSYS; + + u8 *buffer = malloc(sector_size); + if (!buffer) + return -ENOMEM; + + err = spi_flash_read_dm(dev, sector, sector_size, buffer); + if (err < 0) + goto out; + + memcpy(buffer + sector_offset, buf, len); + + err = spi_flash_erase_dm(dev, sector, sector_size); + if (err < 0) + goto out; + + err = spi_flash_write_dm(dev, sector, sector_size, buffer); + if (err < 0) + goto out; + +out: + free(buffer); + return err; +} + +static int bootcount_spi_flash_set(struct udevice *dev, const u32 a) +{ + struct bootcount_spi_flash_priv *priv = dev_get_priv(dev); + const u16 val = bootcount_magic << 8 | (a & 0xff); + + if (bootcount_spi_flash_update(priv->spi_flash, priv->offset, 2, &val) < 0) { + debug("%s: write failed\n", __func__); + return -EIO; + } + + return 0; +} + +static int bootcount_spi_flash_get(struct udevice *dev, u32 *a) +{ + struct bootcount_spi_flash_priv *priv = dev_get_priv(dev); + u16 val; + + if (spi_flash_read_dm(priv->spi_flash, priv->offset, 2, &val) < 0) { + debug("%s: read failed\n", __func__); + return -EIO; + } + + if (val >> 8 == bootcount_magic) { + *a = val & 0xff; + return 0; + } + + debug("%s: bootcount magic does not match on %04x\n", __func__, val); + return -EIO; +} + +static int bootcount_spi_flash_probe(struct udevice *dev) +{ + struct ofnode_phandle_args phandle_args; + struct bootcount_spi_flash_priv *priv = dev_get_priv(dev); + struct udevice *spi_flash; + + if (dev_read_phandle_with_args(dev, "spi-flash", NULL, 0, 0, &phandle_args)) { + debug("%s: spi-flash backing device not specified\n", dev->name); + return -ENOENT; + } + + if (uclass_get_device_by_ofnode(UCLASS_SPI_FLASH, phandle_args.node, &spi_flash)) { + debug("%s: could not get backing device\n", dev->name); + return -ENODEV; + } + + priv->spi_flash = spi_flash; + priv->offset = dev_read_u32_default(dev, "offset", 0); + + return 0; +} + +static const struct bootcount_ops bootcount_spi_flash_ops = { + .get = bootcount_spi_flash_get, + .set = bootcount_spi_flash_set, +}; + +static const struct udevice_id bootcount_spi_flash_ids[] = { + { .compatible = "u-boot,bootcount-spi-flash" }, + { } +}; + +U_BOOT_DRIVER(bootcount_spi_flash) = { + .name = "bootcount-spi-flash", + .id = UCLASS_BOOTCOUNT, + .priv_auto_alloc_size = sizeof(struct bootcount_spi_flash_priv), + .probe = bootcount_spi_flash_probe, + .of_match = bootcount_spi_flash_ids, + .ops = &bootcount_spi_flash_ops, +}; From patchwork Wed Jul 1 17:26:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Reichel X-Patchwork-Id: 240639 List-Id: U-Boot discussion From: sebastian.reichel at collabora.com (Sebastian Reichel) Date: Wed, 1 Jul 2020 19:26:16 +0200 Subject: [PATCH 03/12] gpio: mxc_gpio: add support to read status of output gpios In-Reply-To: <20200701172625.121978-1-sebastian.reichel@collabora.com> References: <20200701172625.121978-1-sebastian.reichel@collabora.com> Message-ID: <20200701172625.121978-4-sebastian.reichel@collabora.com> This is supported by the hardware when the pinmux is configured correctly. Usually it is not, so this adds explicit code for this. This fixes all GPIO regulators being shown as disabled. Signed-off-by: Sebastian Reichel --- drivers/gpio/mxc_gpio.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/mxc_gpio.c b/drivers/gpio/mxc_gpio.c index c924e52f0713..a3df636e60b9 100644 --- a/drivers/gpio/mxc_gpio.c +++ b/drivers/gpio/mxc_gpio.c @@ -203,6 +203,11 @@ static void mxc_gpio_bank_set_value(struct gpio_regs *regs, int offset, writel(l, ®s->gpio_dr); } +static int mxc_gpio_bank_get_out_value(struct gpio_regs *regs, int offset) +{ + return (readl(®s->gpio_dr) >> offset) & 1; +} + static int mxc_gpio_bank_get_value(struct gpio_regs *regs, int offset) { return (readl(®s->gpio_psr) >> offset) & 0x01; @@ -239,7 +244,10 @@ static int mxc_gpio_get_value(struct udevice *dev, unsigned offset) { struct mxc_bank_info *bank = dev_get_priv(dev); - return mxc_gpio_bank_get_value(bank->regs, offset); + if (mxc_gpio_is_output(bank->regs, offset)) + return mxc_gpio_bank_get_out_value(bank->regs, offset); + else + return mxc_gpio_bank_get_value(bank->regs, offset); } /* write GPIO OUT value to pin 'gpio' */ From patchwork Wed Jul 1 17:26:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Reichel X-Patchwork-Id: 240642 List-Id: U-Boot discussion From: sebastian.reichel at collabora.com (Sebastian Reichel) Date: Wed, 1 Jul 2020 19:26:17 +0200 Subject: [PATCH 04/12] rtc: m41t62: reset SQW in m41t62_rtc_reset In-Reply-To: <20200701172625.121978-1-sebastian.reichel@collabora.com> References: <20200701172625.121978-1-sebastian.reichel@collabora.com> Message-ID: <20200701172625.121978-5-sebastian.reichel@collabora.com> This takes care of resetting the 32kHz square wave, which is used by some boards as clock source for the SoC. Signed-off-by: Sebastian Reichel --- drivers/rtc/m41t62.c | 89 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 6 deletions(-) diff --git a/drivers/rtc/m41t62.c b/drivers/rtc/m41t62.c index 94a6b523aab3..85d6eb02593f 100644 --- a/drivers/rtc/m41t62.c +++ b/drivers/rtc/m41t62.c @@ -22,6 +22,7 @@ #include #include #include +#include #define M41T62_REG_SSEC 0 #define M41T62_REG_SEC 1 @@ -49,6 +50,11 @@ #define M41T62_FLAGS_AF (1 << 6) /* AF: Alarm Flag Bit */ #define M41T62_FLAGS_BATT_LOW (1 << 4) /* BL: Battery Low Bit */ +#define M41T62_WDAY_SQW_FREQ_MASK 0xf0 +#define M41T62_WDAY_SQW_FREQ_SHIFT 4 + +#define M41T62_SQW_MAX_FREQ 32768 + #define M41T62_FEATURE_HT (1 << 0) #define M41T62_FEATURE_BL (1 << 1) @@ -139,21 +145,92 @@ static int m41t62_rtc_set(struct udevice *dev, const struct rtc_time *tm) return 0; } -static int m41t62_rtc_reset(struct udevice *dev) +static int m41t62_sqw_enable(struct udevice *dev, bool enable) +{ + u8 val; + int ret; + + ret = dm_i2c_read(dev, M41T62_REG_ALARM_MON, &val, sizeof(val)); + if (ret) + return ret; + + if (enable) + val |= M41T62_ALMON_SQWE; + else + val &= ~M41T62_ALMON_SQWE; + + return dm_i2c_write(dev, M41T62_REG_ALARM_MON, &val, sizeof(val)); +} + +static int m41t62_sqw_set_rate(struct udevice *dev, unsigned int rate) +{ + u8 val, newval, sqwrateval; + int ret; + + if (rate >= M41T62_SQW_MAX_FREQ) + sqwrateval = 1; + else if (rate >= M41T62_SQW_MAX_FREQ / 4) + sqwrateval = 2; + else if (rate) + sqwrateval = 15 - ilog2(rate); + + ret = dm_i2c_read(dev, M41T62_REG_WDAY, &val, sizeof(val)); + if (ret) + return ret; + + newval = val; + newval &= ~M41T62_WDAY_SQW_FREQ_MASK; + newval |= (sqwrateval << M41T62_WDAY_SQW_FREQ_SHIFT); + + /* + * Try to avoid writing unchanged values. Writing to this register + * will reset the internal counter pipeline and thus affect system + * time. + */ + if (newval == val) + return 0; + + return dm_i2c_write(dev, M41T62_REG_WDAY, &newval, sizeof(newval)); +} + +static int m41t62_rtc_clear_ht(struct udevice *dev) { u8 val; + int ret; /* * M41T82: Make sure HT (Halt Update) bit is cleared. * This bit is 0 in M41T62 so its save to clear it always. */ - int ret = dm_i2c_read(dev, M41T62_REG_ALARM_HOUR, &val, sizeof(val)); - + ret = dm_i2c_read(dev, M41T62_REG_ALARM_HOUR, &val, sizeof(val)); + if (ret) + return ret; val &= ~M41T80_ALHOUR_HT; - ret |= dm_i2c_write(dev, M41T62_REG_ALARM_HOUR, &val, sizeof(val)); + ret = dm_i2c_write(dev, M41T62_REG_ALARM_HOUR, &val, sizeof(val)); + if (ret) + return ret; + + return 0; +} - return ret; +static int m41t62_rtc_reset(struct udevice *dev) +{ + int ret; + + ret = m41t62_rtc_clear_ht(dev); + if (ret) + return ret; + + /* + * Some boards feed the square wave as clock input into + * the SoC. This enables a 32.768kHz square wave, which is + * also the hardware default after power-loss. + */ + ret = m41t62_sqw_set_rate(dev, 32768); + if (ret) + return ret; + return m41t62_sqw_enable(dev, true); } /* @@ -162,7 +239,7 @@ static int m41t62_rtc_reset(struct udevice *dev) */ static int m41t62_rtc_probe(struct udevice *dev) { - return m41t62_rtc_reset(dev); + return m41t62_rtc_clear_ht(dev); } static const struct rtc_ops m41t62_rtc_ops = { From patchwork Wed Jul 1 17:26:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Reichel X-Patchwork-Id: 240643 List-Id: U-Boot discussion From: sebastian.reichel at collabora.com (Sebastian Reichel) Date: Wed, 1 Jul 2020 19:26:18 +0200 Subject: [PATCH 05/12] rtc: m41t62: add oscillator fail bit reset support In-Reply-To: <20200701172625.121978-1-sebastian.reichel@collabora.com> References: <20200701172625.121978-1-sebastian.reichel@collabora.com> Message-ID: <20200701172625.121978-6-sebastian.reichel@collabora.com> In case of empty battery or glitches the oscillator fail bit might be set. This will reset the bit in the reset routine. Signed-off-by: Sebastian Reichel --- drivers/rtc/m41t62.c | 50 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/drivers/rtc/m41t62.c b/drivers/rtc/m41t62.c index 85d6eb02593f..0a4e12d69827 100644 --- a/drivers/rtc/m41t62.c +++ b/drivers/rtc/m41t62.c @@ -23,6 +23,7 @@ #include #include #include +#include #define M41T62_REG_SSEC 0 #define M41T62_REG_SEC 1 @@ -48,6 +49,7 @@ #define M41T62_ALMON_SQWE (1 << 6) /* SQWE: SQW Enable Bit */ #define M41T62_ALHOUR_HT (1 << 6) /* HT: Halt Update Bit */ #define M41T62_FLAGS_AF (1 << 6) /* AF: Alarm Flag Bit */ +#define M41T62_FLAGS_OF (1 << 2) /* OF: Oscillator Flag Bit */ #define M41T62_FLAGS_BATT_LOW (1 << 4) /* BL: Battery Low Bit */ #define M41T62_WDAY_SQW_FREQ_MASK 0xf0 @@ -193,6 +195,50 @@ static int m41t62_sqw_set_rate(struct udevice *dev, unsigned int rate) return dm_i2c_write(dev, M41T62_REG_WDAY, &newval, sizeof(newval)); } +static int m41t62_rtc_restart_osc(struct udevice *dev) +{ + u8 val; + int ret; + + /* 0. check if oscillator failure happened */ + ret = dm_i2c_read(dev, M41T62_REG_FLAGS, &val, sizeof(val)); + if (ret) + return ret; + if (!(val & M41T62_FLAGS_OF)) + return 0; + + ret = dm_i2c_read(dev, M41T62_REG_SEC, &val, sizeof(val)); + if (ret) + return ret; + + /* 1. Set stop bit */ + val |= M41T62_SEC_ST; + ret = dm_i2c_write(dev, M41T62_REG_ALARM_HOUR, &val, sizeof(val)); + if (ret) + return ret; + + /* 2. Clear stop bit */ + val &= ~M41T62_SEC_ST; + ret = dm_i2c_write(dev, M41T62_REG_ALARM_HOUR, &val, sizeof(val)); + if (ret) + return ret; + + /* 3. wait 4 seconds */ + mdelay(4000); + + ret = dm_i2c_read(dev, M41T62_REG_FLAGS, &val, sizeof(val)); + if (ret) + return ret; + + /* 4. clear M41T62_FLAGS_OF bit */ + val &= ~M41T62_FLAGS_OF; + ret = dm_i2c_write(dev, M41T62_REG_FLAGS, &val, sizeof(val)); + if (ret) + return ret; + + return 0; +} + static int m41t62_rtc_clear_ht(struct udevice *dev) { u8 val; @@ -218,6 +264,10 @@ static int m41t62_rtc_reset(struct udevice *dev) { int ret; + ret = m41t62_rtc_restart_osc(dev); + if (ret) + return ret; + ret = m41t62_rtc_clear_ht(dev); if (ret) return ret; From patchwork Wed Jul 1 17:26:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Reichel X-Patchwork-Id: 240641 List-Id: U-Boot discussion From: sebastian.reichel at collabora.com (Sebastian Reichel) Date: Wed, 1 Jul 2020 19:26:19 +0200 Subject: [PATCH 06/12] imx6: allow usage of disable_ldb_di_clock_sources for CONFIG_MX6QDL In-Reply-To: <20200701172625.121978-1-sebastian.reichel@collabora.com> References: <20200701172625.121978-1-sebastian.reichel@collabora.com> Message-ID: <20200701172625.121978-7-sebastian.reichel@collabora.com> Allow using disable_ldb_di_clock_sources with just the combined CONFIG_MX6QDL being enabled. Signed-off-by: Sebastian Reichel --- arch/arm/mach-imx/mx6/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-imx/mx6/clock.c b/arch/arm/mach-imx/mx6/clock.c index fb5e5b6f05c4..cb9d629be408 100644 --- a/arch/arm/mach-imx/mx6/clock.c +++ b/arch/arm/mach-imx/mx6/clock.c @@ -1341,7 +1341,7 @@ int do_mx6_showclocks(struct cmd_tbl *cmdtp, int flag, int argc, } #if defined(CONFIG_MX6Q) || defined(CONFIG_MX6D) || defined(CONFIG_MX6DL) || \ - defined(CONFIG_MX6S) + defined(CONFIG_MX6S) || defined(CONFIG_MX6QDL) static void disable_ldb_di_clock_sources(void) { struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; From patchwork Wed Jul 1 17:26:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Reichel X-Patchwork-Id: 240640 List-Id: U-Boot discussion From: sebastian.reichel at collabora.com (Sebastian Reichel) Date: Wed, 1 Jul 2020 19:26:20 +0200 Subject: [PATCH 07/12] poweroff: Introduce poweroff uclass In-Reply-To: <20200701172625.121978-1-sebastian.reichel@collabora.com> References: <20200701172625.121978-1-sebastian.reichel@collabora.com> Message-ID: <20200701172625.121978-8-sebastian.reichel@collabora.com> This adds infrastructure for DM based poweroff drivers including a generic poweroff command, that is exposed via existing CONFIG_CMD_POWEROFF and uses the first registered poweroff driver. Signed-off-by: Sebastian Reichel --- drivers/power/Kconfig | 9 +++++++ drivers/power/Makefile | 2 ++ drivers/power/poweroff-uclass.c | 43 +++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/power/poweroff.h | 32 ++++++++++++++++++++++++ 5 files changed, 87 insertions(+) create mode 100644 drivers/power/poweroff-uclass.c create mode 100644 include/power/poweroff.h diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 5910926faca4..5a76e23b5fb0 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -373,4 +373,13 @@ config POWER_MT6323 This adds poweroff driver for mt6323 this pmic is used on mt7623 / Bananapi R2 +config POWEROFF + bool "power-off support" + depends on DM + help + Most boards have support to power-off themself. U-Boot provides + a uclass API to implement this feature. Poweroff drivers can + provide access to board-specific implementations. Using device + tree for configuration is recommended. + endmenu diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 2dcc7bb99d02..924e99114ccd 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -21,3 +21,5 @@ obj-$(CONFIG_POWER_FSL) += power_fsl.o obj-$(CONFIG_POWER_I2C) += power_i2c.o obj-$(CONFIG_POWER_SPI) += power_spi.o obj-$(CONFIG_POWER_MT6323) += mt6323.o + +obj-$(CONFIG_POWEROFF) += poweroff-uclass.o diff --git a/drivers/power/poweroff-uclass.c b/drivers/power/poweroff-uclass.c new file mode 100644 index 000000000000..c7ffaaca9bee --- /dev/null +++ b/drivers/power/poweroff-uclass.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2019 Collabora Ltd. + * Copyright (c) 2019 GE Inc. + * + * Written by Sebastian Reichel + */ + +#include +#include +#include +#include + +#ifdef CONFIG_CMD_POWEROFF +int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device(UCLASS_POWEROFF, 0, &dev); + if (ret) { + printf("Could not find poweroff device: %d\n", ret); + return ret; + } + + return dm_poweroff(dev); +} +#endif + +int dm_poweroff(struct udevice *dev) +{ + struct poweroff_ops *ops = poweroff_get_ops(dev); + + if (!ops->poweroff) + return -ENOSYS; + + return ops->poweroff(dev); +} + +UCLASS_DRIVER(poweroff) = { + .id = UCLASS_POWEROFF, + .name = "poweroff", +}; diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 7837d459f18c..4adc415ffcfe 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -84,6 +84,7 @@ enum uclass_id { UCLASS_PINCONFIG, /* Pin configuration node device */ UCLASS_PINCTRL, /* Pinctrl (pin muxing/configuration) device */ UCLASS_PMIC, /* PMIC I/O device */ + UCLASS_POWEROFF, /* Poweroff, e.g. via gpio or a special register */ UCLASS_POWER_DOMAIN, /* (SoC) Power domains */ UCLASS_PWM, /* Pulse-width modulator */ UCLASS_PWRSEQ, /* Power sequence device */ diff --git a/include/power/poweroff.h b/include/power/poweroff.h new file mode 100644 index 000000000000..ffaff24649a6 --- /dev/null +++ b/include/power/poweroff.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2019 Collabora Ltd. + * Copyright (c) 2019 GE Inc. + * + * Written by Sebastian Reichel + */ + +#ifndef __POWEROFF_H +#define __POWEROFF_H + +struct poweroff_ops { + /** + * poweroff() - poweroff the system + * + * @dev: Device used for powering off the system + * @return -ve on error (system is powered off otherwise) + */ + int (*poweroff)(struct udevice *dev); +}; + +#define poweroff_get_ops(dev) ((struct poweroff_ops *)(dev)->driver->ops) + +/** + * dm_poweroff() - Poweroff system via DM poweroff driver + * + * @dev: Device used for powering off the system + * @return -ve on error (system is powered off otherwise) + */ +int dm_poweroff(struct udevice *dev); + +#endif From patchwork Wed Jul 1 17:26:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Reichel X-Patchwork-Id: 240644 List-Id: U-Boot discussion From: sebastian.reichel at collabora.com (Sebastian Reichel) Date: Wed, 1 Jul 2020 19:26:21 +0200 Subject: [PATCH 08/12] poweroff: Add poweroff-gpio driver In-Reply-To: <20200701172625.121978-1-sebastian.reichel@collabora.com> References: <20200701172625.121978-1-sebastian.reichel@collabora.com> Message-ID: <20200701172625.121978-9-sebastian.reichel@collabora.com> Add GPIO poweroff driver, which is based on the Linux driver and uses the same DT binding. Signed-off-by: Sebastian Reichel --- drivers/power/Kconfig | 8 ++++ drivers/power/Makefile | 1 + drivers/power/poweroff-gpio.c | 87 +++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 drivers/power/poweroff-gpio.c diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 5a76e23b5fb0..d1eaa0895ddd 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -382,4 +382,12 @@ config POWEROFF provide access to board-specific implementations. Using device tree for configuration is recommended. +config POWEROFF_GPIO + bool "GPIO power-off driver" + depends on POWEROFF + help + This driver supports turning off your board via a GPIO line. + If your board needs a GPIO high/low to power down, say Y and + create a binding in your devicetree. + endmenu diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 924e99114ccd..34a2c2c48195 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -23,3 +23,4 @@ obj-$(CONFIG_POWER_SPI) += power_spi.o obj-$(CONFIG_POWER_MT6323) += mt6323.o obj-$(CONFIG_POWEROFF) += poweroff-uclass.o +obj-$(CONFIG_POWEROFF_GPIO) += poweroff-gpio.o diff --git a/drivers/power/poweroff-gpio.c b/drivers/power/poweroff-gpio.c new file mode 100644 index 000000000000..cf2bdab9e551 --- /dev/null +++ b/drivers/power/poweroff-gpio.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Toggles a GPIO pin to power down a device + * + * Created using the Linux driver as reference, which + * has been written by: + * + * Jamie Lentin + * Andrew Lunn + * + * Copyright (C) 2012 Jamie Lentin + */ + +#include +#include +#include +#include +#include +#include + +struct poweroff_gpio_info { + struct gpio_desc gpio; + u32 active_delay; + u32 inactive_delay; + u32 timeout; +}; + +static int poweroff_gpio_do_poweroff(struct udevice *dev) +{ + struct poweroff_gpio_info *priv = dev_get_priv(dev); + + /* drive it active, also inactive->active edge */ + dm_gpio_set_value(&priv->gpio, 1); + mdelay(priv->active_delay); + + /* drive inactive, also active->inactive edge */ + dm_gpio_set_value(&priv->gpio, 0); + mdelay(priv->inactive_delay); + + /* drive it active, also inactive->active edge */ + dm_gpio_set_value(&priv->gpio, 1); + + /* give it some time */ + mdelay(priv->timeout); + + return -ETIMEDOUT; +} + +static int poweroff_gpio_probe(struct udevice *dev) +{ + struct poweroff_gpio_info *priv = dev_get_priv(dev); + int flags; + + if (dev_read_bool(dev, "input")) + flags = GPIOD_IS_IN; + else + flags = GPIOD_IS_OUT; + + priv->active_delay = 100; + dev_read_u32(dev, "active-delay-ms", &priv->active_delay); + + priv->inactive_delay = 100; + dev_read_u32(dev, "inactive-delay-ms", &priv->inactive_delay); + + priv->timeout = 3000; + dev_read_u32(dev, "timeout-ms", &priv->timeout); + + return gpio_request_by_name(dev, "gpios", 0, &priv->gpio, flags); +} + +static const struct poweroff_ops poweroff_gpio_ops = { + .poweroff = poweroff_gpio_do_poweroff, +}; + +static const struct udevice_id poweroff_gpio_ids[] = { + { .compatible = "gpio-poweroff", }, + {}, +}; + +U_BOOT_DRIVER(poweroff_gpio) = { + .name = "poweroff-gpio", + .id = UCLASS_POWEROFF, + .ops = &poweroff_gpio_ops, + .probe = poweroff_gpio_probe, + .priv_auto_alloc_size = sizeof(struct poweroff_gpio_info), + .of_match = poweroff_gpio_ids, +}; From patchwork Wed Jul 1 17:26:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Reichel X-Patchwork-Id: 240645 List-Id: U-Boot discussion From: sebastian.reichel at collabora.com (Sebastian Reichel) Date: Wed, 1 Jul 2020 19:26:22 +0200 Subject: [PATCH 09/12] board: ge: common: rename ge_common.c to ge_rtc.c In-Reply-To: <20200701172625.121978-1-sebastian.reichel@collabora.com> References: <20200701172625.121978-1-sebastian.reichel@collabora.com> Message-ID: <20200701172625.121978-10-sebastian.reichel@collabora.com> The file only contains RTC related code, so let's name it accordingly. Signed-off-by: Sebastian Reichel --- board/ge/bx50v3/bx50v3.c | 2 +- board/ge/common/Makefile | 2 +- board/ge/common/{ge_common.c => ge_rtc.c} | 0 board/ge/common/{ge_common.h => ge_rtc.h} | 0 board/ge/mx53ppd/mx53ppd.c | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) rename board/ge/common/{ge_common.c => ge_rtc.c} (100%) rename board/ge/common/{ge_common.h => ge_rtc.h} (100%) diff --git a/board/ge/bx50v3/bx50v3.c b/board/ge/bx50v3/bx50v3.c index edccfd03b3c5..50a7070f8126 100644 --- a/board/ge/bx50v3/bx50v3.c +++ b/board/ge/bx50v3/bx50v3.c @@ -35,7 +35,7 @@ #include #include #include -#include "../common/ge_common.h" +#include "../common/ge_rtc.h" #include "../common/vpd_reader.h" #include "../../../drivers/net/e1000.h" #include diff --git a/board/ge/common/Makefile b/board/ge/common/Makefile index 8a21dcb8b533..36bedb198077 100644 --- a/board/ge/common/Makefile +++ b/board/ge/common/Makefile @@ -2,4 +2,4 @@ # # Copyright 2017 General Electric Company -obj-y := vpd_reader.o ge_common.o +obj-y := vpd_reader.o ge_rtc.o diff --git a/board/ge/common/ge_common.c b/board/ge/common/ge_rtc.c similarity index 100% rename from board/ge/common/ge_common.c rename to board/ge/common/ge_rtc.c diff --git a/board/ge/common/ge_common.h b/board/ge/common/ge_rtc.h similarity index 100% rename from board/ge/common/ge_common.h rename to board/ge/common/ge_rtc.h diff --git a/board/ge/mx53ppd/mx53ppd.c b/board/ge/mx53ppd/mx53ppd.c index f8320ffe8f39..d8cfa3cb4556 100644 --- a/board/ge/mx53ppd/mx53ppd.c +++ b/board/ge/mx53ppd/mx53ppd.c @@ -36,7 +36,7 @@ #include #include "ppd_gpio.h" #include -#include "../../ge/common/ge_common.h" +#include "../../ge/common/ge_rtc.h" #include "../../ge/common/vpd_reader.h" DECLARE_GLOBAL_DATA_PTR; From patchwork Wed Jul 1 17:26:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Reichel X-Patchwork-Id: 240646 List-Id: U-Boot discussion From: sebastian.reichel at collabora.com (Sebastian Reichel) Date: Wed, 1 Jul 2020 19:26:23 +0200 Subject: [PATCH 10/12] board: ge: common: add config option for RTC and VPD feature In-Reply-To: <20200701172625.121978-1-sebastian.reichel@collabora.com> References: <20200701172625.121978-1-sebastian.reichel@collabora.com> Message-ID: <20200701172625.121978-11-sebastian.reichel@collabora.com> While this code is being used by all GE platforms its useful to have it behind a config option for hardware bringup of new platforms. Signed-off-by: Sebastian Reichel --- board/ge/bx50v3/Kconfig | 2 ++ board/ge/common/Kconfig | 7 +++++++ board/ge/common/Makefile | 3 ++- board/ge/mx53ppd/Kconfig | 2 ++ 4 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 board/ge/common/Kconfig diff --git a/board/ge/bx50v3/Kconfig b/board/ge/bx50v3/Kconfig index 993b0559302b..05938560abda 100644 --- a/board/ge/bx50v3/Kconfig +++ b/board/ge/bx50v3/Kconfig @@ -15,4 +15,6 @@ config SYS_SOC config SYS_CONFIG_NAME default "ge_bx50v3" +source "board/ge/common/Kconfig" + endif diff --git a/board/ge/common/Kconfig b/board/ge/common/Kconfig new file mode 100644 index 000000000000..323ed1f99607 --- /dev/null +++ b/board/ge/common/Kconfig @@ -0,0 +1,7 @@ +config GE_VPD + bool "Enable GE VPD Support" + default y + +config GE_RTC + bool "Enable GE RTC Support" + default y diff --git a/board/ge/common/Makefile b/board/ge/common/Makefile index 36bedb198077..8bd44e3c8a0f 100644 --- a/board/ge/common/Makefile +++ b/board/ge/common/Makefile @@ -2,4 +2,5 @@ # # Copyright 2017 General Electric Company -obj-y := vpd_reader.o ge_rtc.o +obj-$(CONFIG_GE_VPD) += vpd_reader.o +obj-$(CONFIG_GE_RTC) += ge_rtc.o diff --git a/board/ge/mx53ppd/Kconfig b/board/ge/mx53ppd/Kconfig index 6dc3818cb7bb..bebb2fab0173 100644 --- a/board/ge/mx53ppd/Kconfig +++ b/board/ge/mx53ppd/Kconfig @@ -13,4 +13,6 @@ config SYS_SOC config SYS_CONFIG_NAME default "mx53ppd" +source "board/ge/common/Kconfig" + endif From patchwork Wed Jul 1 17:26:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Reichel X-Patchwork-Id: 240647 List-Id: U-Boot discussion From: sebastian.reichel at collabora.com (Sebastian Reichel) Date: Wed, 1 Jul 2020 19:26:24 +0200 Subject: [PATCH 11/12] board: ge: common: vpd: separate I2C specific code In-Reply-To: <20200701172625.121978-1-sebastian.reichel@collabora.com> References: <20200701172625.121978-1-sebastian.reichel@collabora.com> Message-ID: <20200701172625.121978-12-sebastian.reichel@collabora.com> This separates the I2C specific code from the generic GE vital product data code, so that the generic parts can be used on hardware with VPD stored in SPI flash memory. Signed-off-by: Sebastian Reichel --- board/ge/bx50v3/bx50v3.c | 2 +- board/ge/common/vpd_reader.c | 12 ++++++------ board/ge/common/vpd_reader.h | 23 +++++++++++++++++++---- board/ge/mx53ppd/mx53ppd.c | 2 +- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/board/ge/bx50v3/bx50v3.c b/board/ge/bx50v3/bx50v3.c index 50a7070f8126..8343fdec26a6 100644 --- a/board/ge/bx50v3/bx50v3.c +++ b/board/ge/bx50v3/bx50v3.c @@ -429,7 +429,7 @@ static void set_confidx(const struct vpd_cache* vpd) int board_init(void) { - if (!read_vpd(&vpd, vpd_callback)) { + if (!read_i2c_vpd(&vpd, vpd_callback)) { int ret, rescan; vpd.is_read = true; diff --git a/board/ge/common/vpd_reader.c b/board/ge/common/vpd_reader.c index d42b00da2fe6..421fee592291 100644 --- a/board/ge/common/vpd_reader.c +++ b/board/ge/common/vpd_reader.c @@ -110,9 +110,9 @@ static const size_t HEADER_BLOCK_ECC_LEN = 4; static const u8 ECC_BLOCK_ID = 0xFF; -static int vpd_reader(size_t size, u8 *data, struct vpd_cache *userdata, - int (*fn)(struct vpd_cache *, u8 id, u8 version, u8 type, - size_t size, u8 const *data)) +int vpd_reader(size_t size, u8 *data, struct vpd_cache *userdata, + int (*fn)(struct vpd_cache *, u8 id, u8 version, u8 type, + size_t size, u8 const *data)) { if (size < HEADER_BLOCK_LEN || !data || !fn) return -EINVAL; @@ -200,9 +200,9 @@ static int vpd_reader(size_t size, u8 *data, struct vpd_cache *userdata, } } -int read_vpd(struct vpd_cache *cache, - int (*process_block)(struct vpd_cache *, u8 id, u8 version, - u8 type, size_t size, u8 const *data)) +int read_i2c_vpd(struct vpd_cache *cache, + int (*process_block)(struct vpd_cache *, u8 id, u8 version, + u8 type, size_t size, u8 const *data)) { struct udevice *dev; int ret; diff --git a/board/ge/common/vpd_reader.h b/board/ge/common/vpd_reader.h index 3045b7e21e22..0c51dc57e902 100644 --- a/board/ge/common/vpd_reader.h +++ b/board/ge/common/vpd_reader.h @@ -16,7 +16,22 @@ struct vpd_cache; * * Returns Non-zero on error. Negative numbers encode errno. */ -int read_vpd(struct vpd_cache *cache, - int (*process_block)(struct vpd_cache *, - u8 id, u8 version, u8 type, - size_t size, u8 const *data)); +int read_i2c_vpd(struct vpd_cache *cache, + int (*process_block)(struct vpd_cache *, u8 id, u8 version, + u8 type, size_t size, u8 const *data)); + +/* + * Read VPD from given data, verify content, call callback for each vital + * product data block. + * + * size: size of the raw VPD data in bytes + * data: raw VPD data read from device + * cache: structure used by process block to store VPD information + * process_block: callback called for each VPD data block + * + * Returns Non-zero on error. Negative numbers encode errno. + */ + +int vpd_reader(size_t size, u8 *data, struct vpd_cache *cache, + int (*process_block)(struct vpd_cache *, u8 id, u8 version, u8 type, + size_t size, u8 const *data)); diff --git a/board/ge/mx53ppd/mx53ppd.c b/board/ge/mx53ppd/mx53ppd.c index d8cfa3cb4556..302eb24ce4c0 100644 --- a/board/ge/mx53ppd/mx53ppd.c +++ b/board/ge/mx53ppd/mx53ppd.c @@ -225,7 +225,7 @@ int board_late_init(void) struct vpd_cache vpd; memset(&vpd, 0, sizeof(vpd)); - res = read_vpd(&vpd, vpd_callback); + res = read_i2c_vpd(&vpd, vpd_callback); if (!res) process_vpd(&vpd); else From patchwork Wed Jul 1 17:26:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Reichel X-Patchwork-Id: 240648 List-Id: U-Boot discussion From: sebastian.reichel at collabora.com (Sebastian Reichel) Date: Wed, 1 Jul 2020 19:26:25 +0200 Subject: [PATCH 12/12] board: ge: b1x5v2: Add GE B1x5v2 and B1x5Pv2 In-Reply-To: <20200701172625.121978-1-sebastian.reichel@collabora.com> References: <20200701172625.121978-1-sebastian.reichel@collabora.com> Message-ID: <20200701172625.121978-13-sebastian.reichel@collabora.com> GE B1x5v2 patient monitor series is similar to the CARESCAPE Monitor series (GE Bx50). It consists of a carrier PCB used in combination with a Congatec QMX6 SoM. This adds U-Boot support using device model everywhere and SPL for memory initialization. Proper configuration is provided as 'ge_b1x5v2_defconfig' and the combined image u-boot-with-spi.imx can be flashed directly to 1024 byte offset to /dev/mtdblock0. Alternatively SPL and u-boot.imx can be loaded separately via USB-OTG using e.g. imx_usb. Signed-off-by: Sebastian Reichel --- arch/arm/dts/Makefile | 1 + arch/arm/dts/imx6dl-b1x5v2.dts | 624 +++++++++++++++++++++++++++++ arch/arm/mach-imx/mx6/Kconfig | 10 + board/ge/b1x5v2/Kconfig | 14 + board/ge/b1x5v2/Makefile | 6 + board/ge/b1x5v2/b1x5v2.c | 710 +++++++++++++++++++++++++++++++++ board/ge/b1x5v2/spl.c | 587 +++++++++++++++++++++++++++ configs/ge_b1x5v2_defconfig | 148 +++++++ include/configs/ge_b1x5v2.h | 125 ++++++ 9 files changed, 2225 insertions(+) create mode 100644 arch/arm/dts/imx6dl-b1x5v2.dts create mode 100644 board/ge/b1x5v2/Kconfig create mode 100644 board/ge/b1x5v2/Makefile create mode 100644 board/ge/b1x5v2/b1x5v2.c create mode 100644 board/ge/b1x5v2/spl.c create mode 100644 configs/ge_b1x5v2_defconfig create mode 100644 include/configs/ge_b1x5v2.h diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 9900b4427412..a949a74ba936 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -938,6 +938,7 @@ dtb-$(CONFIG_TARGET_GE_BX50V3) += \ imx6q-b650v3.dtb \ imx6q-b450v3.dtb +dtb-$(CONFIG_TARGET_GE_B1X5V2) += imx6dl-b1x5v2.dtb dtb-$(CONFIG_TARGET_MX53PPD) += imx53-ppd.dtb dtb-$(CONFIG_TARGET_VEXPRESS_CA5X2) += vexpress-v2p-ca5s.dtb diff --git a/arch/arm/dts/imx6dl-b1x5v2.dts b/arch/arm/dts/imx6dl-b1x5v2.dts new file mode 100644 index 000000000000..f3dffe88886d --- /dev/null +++ b/arch/arm/dts/imx6dl-b1x5v2.dts @@ -0,0 +1,624 @@ +/* + * GE B1x5v2 Patient Monitor + * + * Copyright 2018-2020 GE Inc. + * Copyright 2018-2020 Collabora Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include + +/ { + compatible = "ge,imx6dl-b1x5v2", "congatec,qmx6", "fsl,imx6dl"; + + chosen { + bootargs = "console=ttymxc2,115200"; + stdout-path = &uart3; + }; + + reg_3p3v: 3p3v { + compatible = "regulator-fixed"; + regulator-name = "3P3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; + + reg_5v0_audio: regulator-5v0-audio { + compatible = "regulator-fixed"; + regulator-name = "5V0_AUDIO"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <®_5v>; + + gpio = <&tca6424a 16 GPIO_ACTIVE_HIGH>; + enable-active-high; + + /* + * This must be always-on for da7212, which has some not properly + * documented dependencies for it's speaker supply pin. The issue + * manifests as speaker volume being very low. + */ + regulator-always-on; + regulator-boot-on; + }; + + reg_lcd: regulator-lcd { + compatible = "regulator-fixed"; + regulator-name = "LED_VCC"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + + pinctrl-0 = <&pinctrl_q7_lcd_power>; + pinctrl-names = "default"; + gpio = <&gpio1 7 GPIO_ACTIVE_HIGH>; // LCDPWR + enable-active-high; + }; + + backlight: backlight { + compatible = "pwm-backlight"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_q7_backlight_enable>; + power-supply = <®_lcd>; + pwms = <&pwm4 0 5000000>; + brightness-levels = <0 4 8 16 32 64 128 255>; + default-brightness-level = <7>; + enable-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>; + }; + + panel { + compatible = "simple-panel"; + backlight = <&backlight>; + + port { + panel_in: endpoint { + remote-endpoint = <&lvds0_out>; + }; + }; + }; + + bootcount { + compatible = "u-boot,bootcount-spi-flash"; + spi-flash = <&flash>; + offset = <0x01003fe>; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_q7_gpio1 &pinctrl_q7_gpio3 &pinctrl_q7_gpio5>; + + alarm1 { + label = "alarm:red"; + gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>; + }; + + alarm2 { + label = "alarm:yellow"; + gpios = <&gpio4 27 GPIO_ACTIVE_HIGH>; + }; + + alarm3 { + label = "alarm:blue"; + gpios = <&gpio4 15 GPIO_ACTIVE_HIGH>; + }; + }; + + poweroff { + compatible = "gpio-poweroff"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_q7_spi_cs1>; + gpios = <&gpio4 25 GPIO_ACTIVE_LOW>; + active-delay-ms = <1000>; + inactive-delay-ms = <0>; + timeout-ms = <5000>; + }; + + i2cmux { + compatible = "i2c-mux-gpio"; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2cmux>; + mux-gpios = <&gpio6 9 GPIO_ACTIVE_HIGH>; + i2c-parent = <&i2c2>; + idle-state = <1>; + + i2c5: i2c at 0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + tmp112: temperature-sensor at 48 { + compatible = "ti,tmp112"; + reg = <0x48>; + interrupt-parent = <&tca6424a>; + interrupts = <2 IRQ_TYPE_LEVEL_LOW>; + }; + + tca6424a: gpio-controller at 22 { + compatible = "ti,tca6424"; + reg = <0x22>; + gpio-controller; + #gpio-cells = <2>; + + interrupt-parent = <&gpio7>; + interrupts = <11 IRQ_TYPE_EDGE_RISING>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_q7_gpio6>; + interrupt-controller; + #interrupt-cells = <2>; + + gpio-line-names = "GPIO_ROTOR#", "", "TMP_SENSOR_IRQ", "ACM_GPIO1", "ACM_GPIO2", "BATT_T", "", "", + "ACM_GPIO3", "ACM_GPIO4", "USB1_POWER_EN", "EGPIO_CC_CTL0", "EGPIO_CC_CTL1", "12V_OEMNBP_EN", "CP2105_RST", "", + "SPEAKER_PA_EN", "ARM7_UPI_RESET", "ARM7_PWR_RST", "NURSE_CALL", "MARKER_EN", "EGPIO_TOUCH_RST", "", ""; + }; + }; + + i2c6: i2c at 1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + pmic: pmic at 08 { + compatible = "fsl,pfuze100"; + reg = <0x08>; + }; + }; + }; +}; + +&pmic { + regulators { + sw1a_reg: sw1ab { + regulator-min-microvolt = <300000>; + regulator-max-microvolt = <1875000>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <6250>; + }; + + sw1c_reg: sw1c { + regulator-min-microvolt = <300000>; + regulator-max-microvolt = <1875000>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <6250>; + }; + + sw2_reg: sw2 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + sw3a_reg: sw3a { + regulator-min-microvolt = <400000>; + regulator-max-microvolt = <1975000>; + regulator-boot-on; + regulator-always-on; + }; + + sw3b_reg: sw3b { + regulator-min-microvolt = <400000>; + regulator-max-microvolt = <1975000>; + regulator-boot-on; + regulator-always-on; + }; + + sw4_reg: sw4 { + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + swbst_reg: swbst { + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5150000>; + }; + + snvs_reg: vsnvs { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <3000000>; + regulator-boot-on; + regulator-always-on; + }; + + vref_reg: vrefddr { + regulator-boot-on; + regulator-always-on; + }; + + /* keep VGEN3, VGEN4 and VGEN5 enabled in order to maintain backward compatibility with hw-rev. A.0 */ + vgen3_reg: vgen3 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vgen4_reg: vgen4 { + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + }; + + vgen5_reg: vgen5 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + /* supply voltage for eMMC */ + vgen6_reg: vgen6 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + }; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + status = "okay"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; + status = "okay"; +}; + +&usdhc2 { + /* MicroSD card slot */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc2>; + cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; + no-1-8-v; + keep-power-in-suspend; + wakeup-source; + vmmc-supply = <®_3p3v>; + status = "okay"; +}; + +&usdhc3 { + /* eMMC module */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc3>; + non-removable; + bus-width = <8>; + no-1-8-v; + keep-power-in-suspend; + wakeup-source; + vmmc-supply = <®_3p3v>; + status = "okay"; +}; + +&i2c1 { + status = "okay"; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c1>; + pinctrl-1 = <&pinctrl_i2c1_gpio>; + scl-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>; + sda-gpios = <&gpio3 28 GPIO_ACTIVE_HIGH>; + + clock-frequency = <100000>; +}; + +&i2c2 { + status = "okay"; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c2>; + pinctrl-1 = <&pinctrl_i2c2_gpio>; + scl-gpios = <&gpio4 12 GPIO_ACTIVE_HIGH>; + sda-gpios = <&gpio4 13 GPIO_ACTIVE_HIGH>; + + clock-frequency = <100000>; +}; + +&i2c3 { + status = "okay"; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c3>; + pinctrl-1 = <&pinctrl_i2c3_gpio>; + scl-gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>; + sda-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>; + + clock-frequency = <100000>; + + rtc: m41t62 at 68 { + compatible = "st,m41t62"; + reg = <0x68>; + }; +}; + +&ldb { + status = "okay"; + + lvds0: lvds-channel at 0 { + status = "okay"; + fsl,data-mapping = "spwg"; + fsl,data-width = <24>; + + port at 4 { + reg = <4>; + lvds0_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; + }; +}; + +&hdmi { + status = "okay"; +}; + +&fec { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet &pinctrl_phy_reset>; + phy-mode = "rgmii"; + status = "okay"; + + phy-reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>; + phy-reset-duration = <2>; + + fsl,magic-packet; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy at 6 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <6>; + }; + }; +}; + +&ecspi1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi1>; + status = "okay"; + + num-cs = <1>; + cs-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>; + + flash: m25p80 at 0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,sst25vf032b", "jedec,spi-nor"; + spi-max-frequency = <20000000>; + reg = <0>; + + partition at 0 { + label = "bootloader"; + reg = <0x0000000 0x100000>; + }; + + partition at 100000 { + label = "user"; + reg = <0x0100000 0x2fc000>; + }; + + partition at 3fc000 { + label = "reserved"; + reg = <0x03fc000 0x4000>; + read-only; + }; + }; +}; + +&pwm4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm4>; + status = "okay"; +}; + +&wdog1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdog>; + fsl,ext-reset-output; +}; + +&iomuxc { + imx6qdl-congatec-qmx6 { + pinctrl_uart2: uart2grp { + fsl,pins = < + MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1 + MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1 + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1 + MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1 + >; + }; + + pinctrl_wdog: wdoggrp { + fsl,pins = < + MX6QDL_PAD_DISP0_DAT8__WDOG1_B 0x1b0b0 + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059 + MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059 + MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059 + MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059 + MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059 + MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059 + >; + }; + + pinctrl_usdhc2_cd: sd2cdgrp { + fsl,pins = < + MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b0 + >; + }; + + pinctrl_usdhc3: usdhc4grp { + fsl,pins = < + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 + MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059 + MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059 + MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059 + MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059 + >; + }; + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1 + MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1 + >; + }; + + pinctrl_i2c1_gpio: i2c1gpiogrp { + fsl,pins = < + MX6QDL_PAD_EIM_D21__GPIO3_IO21 0x1b0b0 + MX6QDL_PAD_EIM_D28__GPIO3_IO28 0x1b0b0 + >; + }; + + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 + >; + }; + + pinctrl_i2c2_gpio: i2c2gpiogrp { + fsl,pins = < + MX6QDL_PAD_KEY_COL3__GPIO4_IO12 0x1b0b0 + MX6QDL_PAD_KEY_ROW3__GPIO4_IO13 0x1b0b0 + >; + }; + + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1 + MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1 + >; + }; + + pinctrl_i2c3_gpio: i2c3gpiogrp { + fsl,pins = < + MX6QDL_PAD_GPIO_3__GPIO1_IO03 0x1b0b0 + MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x1b0b0 + >; + }; + + pinctrl_ecspi1: ecspi1grp { + fsl,pins = < + MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1 + MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1 + MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1 + MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x1b0b0 + >; + }; + + pinctrl_enet: enetgrp { + fsl,pins = < + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b030 + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030 + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030 + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030 + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030 + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030 + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030 + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b030 + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b030 + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030 + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030 + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b030 + MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0 + >; + }; + + pinctrl_phy_reset: phyrstgrp { + fsl,pins = < + MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x1b0b0 /* RGMII Phy Reset */ + >; + }; + + pinctrl_pwm4: pwm4grp { + fsl,pins = < + MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1 /* Q7[123] LVDS_BLT_CTRL */ + >; + }; + + pinctrl_q7_lcd_power: lcdpwrgrp { + fsl,pins = < + MX6QDL_PAD_GPIO_7__GPIO1_IO07 0x1b0b0 /* Q7[111] LVDS_PPEN */ + >; + }; + + pinctrl_q7_backlight_enable: blengrp { + fsl,pins = < + MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x1b0b0 /* Q7[112] LVDS_BLEN */ + >; + }; + + pinctrl_q7_gpio1: q7gpio1grp { + fsl,pins = < + MX6QDL_PAD_GPIO_8__GPIO1_IO08 0x1b0b0 /* Q7[186] GPIO1 */ + >; + }; + + pinctrl_q7_gpio3: q7gpio3grp { + fsl,pins = < + MX6QDL_PAD_DISP0_DAT6__GPIO4_IO27 0x1b0b0 /* Q7[188] GPIO3 */ + >; + }; + + pinctrl_q7_gpio5: q7gpio5grp { + fsl,pins = < + MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x1b0b0 /* Q7[190] GPIO5 */ + >; + }; + + pinctrl_q7_gpio6: q7gpio6grp { + fsl,pins = < + MX6QDL_PAD_GPIO_16__GPIO7_IO11 0x1b0b0 /* Q7[191] GPIO6 */ + >; + }; + + pinctrl_q7_spi_cs1: spics1grp { + fsl,pins = < + MX6QDL_PAD_DISP0_DAT4__GPIO4_IO25 0x1b0b0 /* Q7[202] SPI_CS1# */ + >; + }; + + pinctrl_i2cmux: i2cmuxgrp { + fsl,pins = < + MX6QDL_PAD_NANDF_WP_B__GPIO6_IO09 0x1b0b0 + >; + }; + }; +}; diff --git a/arch/arm/mach-imx/mx6/Kconfig b/arch/arm/mach-imx/mx6/Kconfig index fa6e1112e62d..c6fbb356d47d 100644 --- a/arch/arm/mach-imx/mx6/Kconfig +++ b/arch/arm/mach-imx/mx6/Kconfig @@ -249,6 +249,15 @@ config TARGET_GE_BX50V3 select BOARD_LATE_INIT select MX6Q +config TARGET_GE_B1X5V2 + bool "General Electric B1x5v2" + select CPU_V7 + select BOARD_LATE_INIT + select DM + select DM_THERMAL + select MX6QDL + select SUPPORT_SPL + config TARGET_GW_VENTANA bool "gw_ventana" select MX6QDL @@ -687,6 +696,7 @@ config SYS_SOC default "mx6" source "board/ge/bx50v3/Kconfig" +source "board/ge/b1x5v2/Kconfig" source "board/advantech/dms-ba16/Kconfig" source "board/aristainetos/Kconfig" source "board/armadeus/opos6uldev/Kconfig" diff --git a/board/ge/b1x5v2/Kconfig b/board/ge/b1x5v2/Kconfig new file mode 100644 index 000000000000..80a5bcae7dee --- /dev/null +++ b/board/ge/b1x5v2/Kconfig @@ -0,0 +1,14 @@ +if TARGET_GE_B1X5V2 + +config SYS_BOARD + default "b1x5v2" + +config SYS_VENDOR + default "ge" + +config SYS_CONFIG_NAME + default "ge_b1x5v2" + +source "board/ge/common/Kconfig" + +endif diff --git a/board/ge/b1x5v2/Makefile b/board/ge/b1x5v2/Makefile new file mode 100644 index 000000000000..8a27af52e1ae --- /dev/null +++ b/board/ge/b1x5v2/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2018-2020 Collabora +# Copyright 2018-2020 GE + +obj-y := b1x5v2.o spl.o diff --git a/board/ge/b1x5v2/b1x5v2.c b/board/ge/b1x5v2/b1x5v2.c new file mode 100644 index 000000000000..84189088314d --- /dev/null +++ b/board/ge/b1x5v2/b1x5v2.c @@ -0,0 +1,710 @@ +/* + * GE B105v2, B125v2, B155v2 + * + * Copyright 2018-2020 GE Inc. + * Copyright 2018-2020 Collabora Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../common/vpd_reader.h" + +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_SPL_BUILD + +#define B1X5V2_GE_VPD_OFFSET 0x0100000 +#define B1X5V2_GE_VPD_SIZE 1022 + +#define VPD_TYPE_INVALID 0x00 +#define VPD_BLOCK_NETWORK 0x20 +#define VPD_BLOCK_HWID 0x44 +#define VPD_MAC_ADDRESS_LENGTH 6 + +#define VPD_FLAG_VALID_MAC BIT(1) + +static struct vpd_cache { + bool is_read; + u8 product_id; + unsigned char mac[VPD_MAC_ADDRESS_LENGTH]; + u32 flags; +} vpd; + +enum product_type { + PRODUCT_TYPE_B105V2 = 6, + PRODUCT_TYPE_B105PV2 = 7, + PRODUCT_TYPE_B125V2 = 8, + PRODUCT_TYPE_B125PV2 = 9, + PRODUCT_TYPE_B155V2 = 10, + + PRODUCT_TYPE_INVALID = 0, +}; + +int dram_init(void) { + gd->ram_size = imx_ddr_size(); + return 0; +} + +int power_init_board(void) +{ + /* all required PMIC configuration happens via DT */ + return 0; +} + +int mx6_rgmii_rework(struct phy_device *phydev) +{ + unsigned short id1, id2; + unsigned short val; + + id1 = phy_read(phydev, MDIO_DEVAD_NONE, 2); + id2 = phy_read(phydev, MDIO_DEVAD_NONE, 3); + + if ((id1 == 0x004d) && (id2 == 0xd072)) { /* AR8035 */ + /* enable AR8035 ouput a 125MHz clk from CLK_25M */ + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, 0x7); + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, MII_KSZ9031_MOD_DATA_POST_INC_RW | 0x16); + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, MII_KSZ9031_MOD_DATA_NO_POST_INC | 0x7); + val = phy_read(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA); + val &= 0xfe63; + val |= 0x18; + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, val); + + /* introduce tx clock delay */ + phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x5); + val = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e); + val |= 0x0100; + phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, val); + + /* disable hibernation */ + phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0xb); + val = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e); + phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x3c40); + } else { + printf("Unknown PHY ID: %04x %04x\n", id1, id2); + } + + return 0; +} + +int board_phy_config(struct phy_device *phydev) +{ + mx6_rgmii_rework(phydev); + + if (phydev->drv->config) + phydev->drv->config(phydev); + + return 0; +} + +static int auo_g101evn01_detect(const struct display_info_t *info) +{ + char *dev = env_get("devicetype"); + return !strcmp(dev, "B105v2") || !strcmp(dev, "B105Pv2"); +} + +static int auo_g121ean01_detect(const struct display_info_t *info) +{ + char *dev = env_get("devicetype"); + return !strcmp(dev, "B125v2") || !strcmp(dev, "B125Pv2");; +} + +static int auo_g156xtn01_detect(const struct display_info_t *info) +{ + char *dev = env_get("devicetype"); + return !strcmp(dev, "B155v2"); +} + +static void b1x5v2_backlight_enable(int percent) +{ + struct udevice *panel; + int ret; + + ret = uclass_get_device(UCLASS_PANEL, 0, &panel); + if (ret) { + printf("Could not find panel: %d\n", ret); + return; + } + + panel_set_backlight(panel, percent); + panel_enable_backlight(panel); + +} + +static void lcd_enable(const struct display_info_t *info) +{ + printf("Enable backlight...\n"); + b1x5v2_backlight_enable(100); +} + +struct display_info_t const displays[] = { +{ + .di = 0, + .bus = -1, + .addr = -1, + .pixfmt = IPU_PIX_FMT_RGB24, + .detect = auo_g156xtn01_detect, + .enable = lcd_enable, + .mode = { + .name = "AUO G156XTN01", + .refresh = 60, + .xres = 1368, /* because of i.MX6 limitation, actually 1366 */ + .yres = 768, + .pixclock = 13158, /* 76 MHz in ps */ + .left_margin = 33, + .right_margin = 67, + .upper_margin = 4, + .lower_margin = 4, + .hsync_len = 94, + .vsync_len = 30, + .sync = FB_SYNC_EXT, + .vmode = FB_VMODE_NONINTERLACED + } +}, +{ + .di = 0, + .bus = -1, + .addr = -1, + .pixfmt = IPU_PIX_FMT_RGB24, + .detect = auo_g121ean01_detect, + .enable = lcd_enable, + .mode = { + .name = "AUO G121EAN01.4", + .refresh = 60, + .xres = 1280, + .yres = 800, + .pixclock = 14992, /* 66.7 MHz in ps */ + .left_margin = 8, + .right_margin = 58, + .upper_margin = 6, + .lower_margin = 4, + .hsync_len = 70, + .vsync_len = 10, + .sync = FB_SYNC_EXT, + .vmode = FB_VMODE_NONINTERLACED + } +}, +{ + .di = 0, + .bus = -1, + .addr = -1, + .pixfmt = IPU_PIX_FMT_RGB24, + .detect = auo_g101evn01_detect, + .enable = lcd_enable, + .mode = { + .name = "AUO G101EVN01.3", + .refresh = 60, + .xres = 1280, + .yres = 800, + .pixclock = 14992, /* 66.7 MHz in ps */ + .left_margin = 8, + .right_margin = 58, + .upper_margin = 6, + .lower_margin = 4, + .hsync_len = 70, + .vsync_len = 10, + .sync = FB_SYNC_EXT, + .vmode = FB_VMODE_NONINTERLACED + } +} +}; +size_t display_count = ARRAY_SIZE(displays); + +static void enable_videopll(void) +{ + struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; + s32 timeout = 100000; + + setbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN); + + /* PLL_VIDEO 455MHz (24MHz * (37+11/12) / 2) + * | + * PLL5 + * | + * CS2CDR[LDB_DI0_CLK_SEL] + * | + * +----> LDB_DI0_SERIAL_CLK_ROOT + * | + * +--> CSCMR2[LDB_DI0_IPU_DIV] --> LDB_DI0_IPU 455 / 7 = 65 MHz + */ + + clrsetbits_le32(&ccm->analog_pll_video, + BM_ANADIG_PLL_VIDEO_DIV_SELECT | + BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT, + BF_ANADIG_PLL_VIDEO_DIV_SELECT(37) | + BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(1)); + + writel(BF_ANADIG_PLL_VIDEO_NUM_A(11), &ccm->analog_pll_video_num); + writel(BF_ANADIG_PLL_VIDEO_DENOM_B(12), &ccm->analog_pll_video_denom); + + clrbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN); + + while (timeout--) + if (readl(&ccm->analog_pll_video) & BM_ANADIG_PLL_VIDEO_LOCK) + break; + + if (timeout < 0) + printf("Warning: video pll lock timeout!\n"); + + clrsetbits_le32(&ccm->analog_pll_video, + BM_ANADIG_PLL_VIDEO_BYPASS, + BM_ANADIG_PLL_VIDEO_ENABLE); +} + +static void setup_display(void) +{ + struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; + struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; + + enable_videopll(); + + /* When a reset/reboot is performed the display power needs to be turned + * off for atleast 500ms. The boot time is ~300ms, we need to wait for + * an additional 200ms here. Unfortunately we use external PMIC for + * doing the reset, so can not differentiate between POR vs soft reset + */ + mdelay(200); + + /* CCM_CSCMR2 -> ldb_di0_ipu_div [IMX6SDLRM page 839] */ + /* divide IPU clock by 7 */ + setbits_le32(&mxc_ccm->cscmr2, MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV); + + /* CCM_CHSCCDR -> ipu1_di0_clk_sel [IMX6SDLRM page 849] */ + /* Set LDB_DI0 as clock source for IPU_DI0 */ + clrsetbits_le32(&mxc_ccm->chsccdr, + MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK, + (CHSCCDR_CLK_SEL_LDB_DI0 << + MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET)); + + /* Turn on IPU LDB DI0 clocks */ + setbits_le32(&mxc_ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK); + + enable_ipu_clock(); + + /* IOMUXC_GPR2 [IMX6SDLRM page 2049] */ + /* Set LDB Channel 0 in SPWG 24 Bit mode */ + writel(IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_HIGH | + IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG | + IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT | + IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0, + &iomux->gpr[2]); + + /* IOMUXC_GPR3 [IMX6SDLRM page 2051] */ + /* LVDS0 is connected to IPU DI0 */ + clrsetbits_le32(&iomux->gpr[3], + IOMUXC_GPR3_LVDS0_MUX_CTL_MASK, + (IOMUXC_GPR3_MUX_SRC_IPU1_DI0 << + IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET)); +} + +/* + * Do not overwrite the console + * Use always serial for U-Boot console + */ +int overwrite_console(void) +{ + return 1; +} + +int board_early_init_f(void) +{ + select_ldb_di_clock_source(MXC_PLL5_CLK); + + return 0; +} + +int eeti_touch_get_model(struct udevice *dev, char *result) { + u8 query[68] = {0x67, 0x00, 0x42, 0x00, 0x03, 0x01, 'E', 0x00, 0x00, 0x00}; + struct i2c_msg qmsg = { + .addr = 0x2a, + .flags = 0, + .len = sizeof(query), + .buf = query, + }; + u8 reply[66] = {0}; + struct i2c_msg rmsg = { + .addr = 0x2a, + .flags = I2C_M_RD, + .len = sizeof(reply), + .buf = reply, + }; + int err; + + err = dm_i2c_xfer(dev, &qmsg, 1); + if (err) + return err; + + /* + * device sends IRQ when its ok to read. To keep the code + * simple we just wait an arbitrary, long enough time period. + */ + mdelay(10); + + err = dm_i2c_xfer(dev, &rmsg, 1); + if (err) + return err; + + if (reply[0] != 0x42 || reply[1] != 0x00 || + reply[2] != 0x03 || reply[4] != 'E') + return -EPROTO; + + memcpy(result, reply+5, 10); + return 0; +} + +bool b1x5v2_board_is_p_model(void) +{ + struct udevice *bus = NULL; + struct udevice *dev = NULL; + int err; + + err = uclass_get_device_by_name(UCLASS_I2C, "i2c at 21a0000", &bus); + if (err || !bus) { + printf("Could not get I2C bus: %d\n", err); + return true; + } + + /* The P models do not have this port expander */ + err = dm_i2c_probe(bus, 0x21, 0, &dev); + if (err || !dev) { + return true; + } + + return false; +} + +enum product_type b1x5v2_board_type(void) +{ + struct udevice *bus = NULL; + struct udevice *dev = NULL; + char model[11] = {0}; + int err; + int retry; + + err = uclass_get_device_by_name(UCLASS_I2C, "i2c at 21a8000", &bus); + if (err) { + printf("Could not get I2C bus: %d\n", err); + return PRODUCT_TYPE_INVALID; + } + + err = dm_i2c_probe(bus, 0x41, 0, &dev); + if (!err && dev) { /* Ilitek Touchscreen */ + if (b1x5v2_board_is_p_model()) { + return PRODUCT_TYPE_B105PV2; + } else { + return PRODUCT_TYPE_B105V2; + } + } + + err = dm_i2c_probe(bus, 0x2a, 0, &dev); + if (err || !dev) { + printf("Could not find touchscreen: %d\n", err); + return PRODUCT_TYPE_INVALID; + } + + for (retry = 0; retry < 3; ++retry) { + err = eeti_touch_get_model(dev, model); + if (!err) + break; + printf("Retry %d read EETI touchscreen model: %d\n", retry + 1, err); + } + if (err) { + printf("Could not read EETI touchscreen model: %d\n", err); + return PRODUCT_TYPE_INVALID; + } + + if (!strcmp(model, "Orion_1320")) { /* EETI EXC80H60 */ + if (b1x5v2_board_is_p_model()) { + return PRODUCT_TYPE_B125PV2; + } else { + return PRODUCT_TYPE_B125V2; + } + } else if (!strcmp(model, "Orion_1343")) { /* EETI EXC80H84 */ + return PRODUCT_TYPE_B155V2; + } + + printf("Unknown EETI touchscreen model: %s\n", model); + return PRODUCT_TYPE_INVALID; +} + +void set_env_per_board_type(enum product_type type) +{ + switch (type) { + case PRODUCT_TYPE_B105V2: + env_set("resolution", "1280x800"); + env_set("devicetype", "B105v2"); + env_set("fdtfile", "imx6dl-b105v2.dtb"); + break; + case PRODUCT_TYPE_B105PV2: + env_set("resolution", "1280x800"); + env_set("devicetype", "B105Pv2"); + env_set("fdtfile", "imx6dl-b105pv2.dtb"); + break; + case PRODUCT_TYPE_B125V2: + env_set("resolution", "1280x800"); + env_set("devicetype", "B125v2"); + env_set("fdtfile", "imx6dl-b125v2.dtb"); + break; + case PRODUCT_TYPE_B125PV2: + env_set("resolution", "1280x800"); + env_set("devicetype", "B125Pv2"); + env_set("fdtfile", "imx6dl-b125pv2.dtb"); + break; + case PRODUCT_TYPE_B155V2: + env_set("resolution", "1366x768"); + env_set("devicetype", "B155v2"); + env_set("fdtfile", "imx6dl-b155v2.dtb"); + break; + default: + break; + } +} + +int b1x5v2_board_type_autodetect(void) +{ + enum product_type product = b1x5v2_board_type(); + if (product != PRODUCT_TYPE_INVALID) { + set_env_per_board_type(product); + return 0; + } + return -1; +} + +/* + * Extracts MAC and product information from the VPD. + */ +static int vpd_callback(struct vpd_cache *vpd, u8 id, u8 version, u8 type, + size_t size, u8 const *data) +{ + if (type == VPD_TYPE_INVALID) + return 0; + + if (id == VPD_BLOCK_HWID && version == 1 && size >= 1) { + vpd->product_id = data[0]; + } else if (id == VPD_BLOCK_NETWORK && version == 1) { + if (size >= VPD_MAC_ADDRESS_LENGTH) { + memcpy(vpd->mac, data, VPD_MAC_ADDRESS_LENGTH); + vpd->flags |= VPD_FLAG_VALID_MAC; + } + } + + return 0; +} + +int read_spi_vpd(struct vpd_cache *cache, + int (*process_block)(struct vpd_cache *, u8 id, u8 version, + u8 type, size_t size, u8 const *data)) +{ + static const int size = B1X5V2_GE_VPD_SIZE; + struct udevice *dev; + int ret; + u8 *data; + + ret = uclass_get_device_by_name(UCLASS_SPI_FLASH, "m25p80 at 0", &dev); + if (ret) + return ret; + + data = malloc(size); + if (!data) + return -ENOMEM; + + ret = spi_flash_read_dm(dev, B1X5V2_GE_VPD_OFFSET, size, data); + if (ret) { + free(data); + return ret; + } + + ret = vpd_reader(size, data, cache, process_block); + + free(data); + + return ret; +} + +int board_init(void) +{ + if (!read_spi_vpd(&vpd, vpd_callback)) { + vpd.is_read = true; + } + + /* address of boot parameters */ + gd->bd->bi_boot_params = PHYS_SDRAM + 0x100; + setup_display(); + + return 0; +} + +void init_bootcause(void) +{ + const char *cause; + + /* We care about WDOG only, treating everything else as + * a power-on-reset. + */ + if (get_imx_reset_cause() & 0x0010) + cause = "WDOG"; + else + cause = "POR"; + + env_set("bootcause", cause); +} + +int misc_init_r(void) +{ + init_bootcause(); + + return 0; +} + +#define M41T62_REG_FLAGS 0xf +#define M41T62_FLAGS_OF (1 << 2) +void check_time(void) +{ + struct udevice *rtc = NULL; + struct rtc_time tm; + u8 val; + int ret; + + ret = uclass_get_device_by_name(UCLASS_RTC, "m41t62 at 68", &rtc); + if (ret) { + printf("Could not get RTC: %d\n", ret); + env_set("rtc_status", "FAIL"); + return; + } + + ret = dm_i2c_read(rtc, M41T62_REG_FLAGS, &val, sizeof(val)); + if (ret) { + printf("Could not read RTC register: %d\n", ret); + env_set("rtc_status", "FAIL"); + return; + } + + ret = dm_rtc_reset(rtc); + if (ret) { + printf("Could not reset RTC: %d\n", ret); + env_set("rtc_status", "FAIL"); + return; + } + + if (val & M41T62_FLAGS_OF) { + env_set("rtc_status", "STOP"); + return; + } + + ret = dm_rtc_get(rtc, &tm); + if (ret) { + printf("Could not read RTC: %d\n", ret); + env_set("rtc_status", "FAIL"); + return; + } + + if (tm.tm_year > 2037) { + tm.tm_sec = 0; + tm.tm_min = 0; + tm.tm_hour = 0; + tm.tm_mday = 1; + tm.tm_wday = 2; + tm.tm_mon = 1; + tm.tm_year = 2036; + + ret = dm_rtc_set(rtc, &tm); + if (ret) { + printf("Could not update RTC: %d\n", ret); + env_set("rtc_status", "FAIL"); + return; + } + + printf("RTC behind 2037, capped to 2036 for userspace handling\n"); + env_set("rtc_status", "2038"); + return; + } + + env_set("rtc_status", "OK"); +} + +static void process_vpd(struct vpd_cache *vpd) +{ + if (!vpd->is_read) { + printf("VPD wasn't read\n"); + return; + } + + if (vpd->flags & VPD_FLAG_VALID_MAC) { + eth_env_set_enetaddr_by_index("eth", 0, vpd->mac); + env_set("ethact", "eth0"); + } +} + +int board_late_init(void) +{ + process_vpd(&vpd); + + if (vpd.product_id >= PRODUCT_TYPE_B105V2 && + vpd.product_id <= PRODUCT_TYPE_B155V2) { + set_env_per_board_type((enum product_type)vpd.product_id); + } else { + b1x5v2_board_type_autodetect(); + } + + printf("Board: GE %s\n", env_get("devicetype")); + + check_time(); + + return 0; +} + +#ifdef CONFIG_OF_BOARD_SETUP +int ft_board_setup(void *blob, bd_t *bd) +{ + char *rtc_status = env_get("rtc_status"); + + fdt_setprop(blob, 0, "ge,boot-ver", version_string, + strlen(version_string) + 1); + fdt_setprop(blob, 0, "ge,rtc-status", rtc_status, + strlen(rtc_status) + 1); + + return 0; +} +#endif + +static int do_b1x5v2_autodetect(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) +{ + int err; + + err = b1x5v2_board_type_autodetect(); + if (!err) + printf("Identified %s\n", env_get("devicetype")); + + return 0; +} + +U_BOOT_CMD( + autodetect_devtype, 1, 1, do_b1x5v2_autodetect, + "autodetect b1x5v2 device type", + "" +); + +#endif // CONFIG_SPL_BUILD diff --git a/board/ge/b1x5v2/spl.c b/board/ge/b1x5v2/spl.c new file mode 100644 index 000000000000..2e6f905219fe --- /dev/null +++ b/board/ge/b1x5v2/spl.c @@ -0,0 +1,587 @@ +/* + * GE b1x5v2 - QMX6 SPL + * + * Copyright 2013, Adeneo Embedded + * Copyright 2018-2020 GE Inc. + * Copyright 2018-2020 Collabora Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_SPL_BUILD) + +#include + +#define IMX6DQ_DRIVE_STRENGTH_40_OHM 0x30 +#define IMX6DQ_DRIVE_STRENGTH_48_OHM 0x28 +#define IMX6DQ_DRIVE_STRENGTH IMX6DQ_DRIVE_STRENGTH_40_OHM + +#define QMX6_DDR_PKE_DISABLED 0x00000000 +#define QMX6_DDR_ODT_60_OHM (2 << 16) +#define QMX6_DDR_TYPE_DDR3 0x000c0000 + +#define QMX6_DRAM_SDCKE_PULLUP_100K 0x00003000 +#define QMX6_DRAM_SDBA2_PULLUP_NONE 0x00000000 + +#define SPI_PAD_CTRL (PAD_CTL_HYS | \ + PAD_CTL_SPEED_MED | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST) + +#define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ + PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \ + PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define SPI1_CS0 IMX_GPIO_NR(3, 19) +#define POWEROFF IMX_GPIO_NR(4, 25) + +static iomux_v3_cfg_t const poweroff_pads[] = { + IOMUX_PADS(PAD_DISP0_DAT4__GPIO4_IO25 | MUX_PAD_CTRL(NO_PAD_CTRL)), +}; + +static iomux_v3_cfg_t const uart2_pads[] = { + IOMUX_PADS(PAD_EIM_D26__UART2_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), + IOMUX_PADS(PAD_EIM_D27__UART2_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), +}; + +static iomux_v3_cfg_t const uart3_pads[] = { + IOMUX_PADS(PAD_EIM_D24__UART3_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), + IOMUX_PADS(PAD_EIM_D25__UART3_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), +}; + +static iomux_v3_cfg_t const ecspi1_pads[] = { + IOMUX_PADS(PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL)), + IOMUX_PADS(PAD_EIM_D17__ECSPI1_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL)), + IOMUX_PADS(PAD_EIM_D18__ECSPI1_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL)), + IOMUX_PADS(PAD_EIM_D19__GPIO3_IO19 | MUX_PAD_CTRL(NO_PAD_CTRL)), +}; + +static struct mx6dq_iomux_ddr_regs mx6q_ddr_ioregs = { + .dram_sdclk_0 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdclk_1 = IMX6DQ_DRIVE_STRENGTH, + .dram_cas = IMX6DQ_DRIVE_STRENGTH, + .dram_ras = IMX6DQ_DRIVE_STRENGTH, + .dram_reset = IMX6DQ_DRIVE_STRENGTH, + .dram_sdcke0 = QMX6_DRAM_SDCKE_PULLUP_100K, + .dram_sdcke1 = QMX6_DRAM_SDCKE_PULLUP_100K, + .dram_sdba2 = QMX6_DRAM_SDBA2_PULLUP_NONE, + .dram_sdodt0 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdodt1 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs0 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs1 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs2 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs3 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs4 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs5 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs6 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs7 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm0 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm1 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm2 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm3 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm4 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm5 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm6 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm7 = IMX6DQ_DRIVE_STRENGTH, +}; + +static const struct mx6sdl_iomux_ddr_regs mx6dl_ddr_ioregs = { + .dram_sdclk_0 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdclk_1 = IMX6DQ_DRIVE_STRENGTH, + .dram_cas = IMX6DQ_DRIVE_STRENGTH, + .dram_ras = IMX6DQ_DRIVE_STRENGTH, + .dram_reset = IMX6DQ_DRIVE_STRENGTH, + .dram_sdcke0 = QMX6_DRAM_SDCKE_PULLUP_100K, + .dram_sdcke1 = QMX6_DRAM_SDCKE_PULLUP_100K, + .dram_sdba2 = QMX6_DRAM_SDBA2_PULLUP_NONE, + .dram_sdodt0 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdodt1 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs0 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs1 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs2 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs3 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs4 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs5 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs6 = IMX6DQ_DRIVE_STRENGTH, + .dram_sdqs7 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm0 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm1 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm2 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm3 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm4 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm5 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm6 = IMX6DQ_DRIVE_STRENGTH, + .dram_dqm7 = IMX6DQ_DRIVE_STRENGTH, +}; + +static struct mx6dq_iomux_grp_regs mx6q_grp_ioregs = { + .grp_ddr_type = QMX6_DDR_TYPE_DDR3, + .grp_ddrmode_ctl = QMX6_DDR_ODT_60_OHM, + .grp_ddrpke = QMX6_DDR_PKE_DISABLED, + .grp_addds = IMX6DQ_DRIVE_STRENGTH, + .grp_ctlds = IMX6DQ_DRIVE_STRENGTH, + .grp_ddrmode = QMX6_DDR_ODT_60_OHM, + .grp_b0ds = IMX6DQ_DRIVE_STRENGTH, + .grp_b1ds = IMX6DQ_DRIVE_STRENGTH, + .grp_b2ds = IMX6DQ_DRIVE_STRENGTH, + .grp_b3ds = IMX6DQ_DRIVE_STRENGTH, + .grp_b4ds = IMX6DQ_DRIVE_STRENGTH, + .grp_b5ds = IMX6DQ_DRIVE_STRENGTH, + .grp_b6ds = IMX6DQ_DRIVE_STRENGTH, + .grp_b7ds = IMX6DQ_DRIVE_STRENGTH, +}; + +static const struct mx6sdl_iomux_grp_regs mx6sdl_grp_ioregs = { + .grp_ddr_type = QMX6_DDR_TYPE_DDR3, + .grp_ddrmode_ctl = QMX6_DDR_ODT_60_OHM, + .grp_ddrpke = QMX6_DDR_PKE_DISABLED, + .grp_addds = IMX6DQ_DRIVE_STRENGTH, + .grp_ctlds = IMX6DQ_DRIVE_STRENGTH, + .grp_ddrmode = QMX6_DDR_ODT_60_OHM, + .grp_b0ds = IMX6DQ_DRIVE_STRENGTH, + .grp_b1ds = IMX6DQ_DRIVE_STRENGTH, + .grp_b2ds = IMX6DQ_DRIVE_STRENGTH, + .grp_b3ds = IMX6DQ_DRIVE_STRENGTH, + .grp_b4ds = IMX6DQ_DRIVE_STRENGTH, + .grp_b5ds = IMX6DQ_DRIVE_STRENGTH, + .grp_b6ds = IMX6DQ_DRIVE_STRENGTH, + .grp_b7ds = IMX6DQ_DRIVE_STRENGTH, +}; + +const struct mx6_mmdc_calibration mx6q_mmcd_calib = { + .p0_mpwldectrl0 = 0x0016001A, + .p0_mpwldectrl1 = 0x0023001C, + .p1_mpwldectrl0 = 0x0028003A, + .p1_mpwldectrl1 = 0x001F002C, + .p0_mpdgctrl0 = 0x43440354, + .p0_mpdgctrl1 = 0x033C033C, + .p1_mpdgctrl0 = 0x43300368, + .p1_mpdgctrl1 = 0x03500330, + .p0_mprddlctl = 0x3228242E, + .p1_mprddlctl = 0x2C2C2636, + .p0_mpwrdlctl = 0x36323A38, + .p1_mpwrdlctl = 0x42324440, +}; + +const struct mx6_mmdc_calibration mx6q_2g_mmcd_calib = { + .p0_mpwldectrl0 = 0x00080016, + .p0_mpwldectrl1 = 0x001D0016, + .p1_mpwldectrl0 = 0x0018002C, + .p1_mpwldectrl1 = 0x000D001D, + .p0_mpdgctrl0 = 0x43200334, + .p0_mpdgctrl1 = 0x0320031C, + .p1_mpdgctrl0 = 0x0344034C, + .p1_mpdgctrl1 = 0x03380314, + .p0_mprddlctl = 0x3E36383A, + .p1_mprddlctl = 0x38363240, + .p0_mpwrdlctl = 0x36364238, + .p1_mpwrdlctl = 0x4230423E, +}; + +const struct mx6_mmdc_calibration mx6q_4g_mmcd_calib = { + .p0_mpwldectrl0 = 0x00180018, + .p0_mpwldectrl1 = 0x00220018, + .p1_mpwldectrl0 = 0x00330046, + .p1_mpwldectrl1 = 0x002B003D, + .p0_mpdgctrl0 = 0x4344034C, + .p0_mpdgctrl1 = 0x033C033C, + .p1_mpdgctrl0 = 0x03700374, + .p1_mpdgctrl1 = 0x03600338, + .p0_mprddlctl = 0x443E3E40, + .p1_mprddlctl = 0x423E3E48, + .p0_mpwrdlctl = 0x3C3C4442, + .p1_mpwrdlctl = 0x46384C46, +}; + +static const struct mx6_mmdc_calibration mx6s_mmcd_calib = { + .p0_mpwldectrl0 = 0x00480049, + .p0_mpwldectrl1 = 0x00410044, + .p0_mpdgctrl0 = 0x42480248, + .p0_mpdgctrl1 = 0x023C023C, + .p0_mprddlctl = 0x40424644, + .p0_mpwrdlctl = 0x34323034, +}; + +static const struct mx6_mmdc_calibration mx6s_2g_mmcd_calib = { + .p0_mpwldectrl0 = 0x00450048, + .p0_mpwldectrl1 = 0x003B003F, + .p0_mpdgctrl0 = 0x424C0248, + .p0_mpdgctrl1 = 0x0234023C, + .p0_mprddlctl = 0x40444848, + .p0_mpwrdlctl = 0x38363232, +}; + +static const struct mx6_mmdc_calibration mx6dl_mmcd_calib = { + .p0_mpwldectrl0 = 0x0043004B, + .p0_mpwldectrl1 = 0x003A003E, + .p1_mpwldectrl0 = 0x0047004F, + .p1_mpwldectrl1 = 0x004E0061, + .p0_mpdgctrl0 = 0x42500250, + .p0_mpdgctrl1 = 0x0238023C, + .p1_mpdgctrl0 = 0x42640264, + .p1_mpdgctrl1 = 0x02500258, + .p0_mprddlctl = 0x40424846, + .p1_mprddlctl = 0x46484842, + .p0_mpwrdlctl = 0x38382C30, + .p1_mpwrdlctl = 0x34343430, +}; + +static const struct mx6_mmdc_calibration mx6dl_2g_mmcd_calib = { + .p0_mpwldectrl0 = 0x00450045, + .p0_mpwldectrl1 = 0x00390043, + .p1_mpwldectrl0 = 0x0049004D, + .p1_mpwldectrl1 = 0x004E0061, + .p0_mpdgctrl0 = 0x4240023C, + .p0_mpdgctrl1 = 0x0228022C, + .p1_mpdgctrl0 = 0x02400244, + .p1_mpdgctrl1 = 0x02340238, + .p0_mprddlctl = 0x42464648, + .p1_mprddlctl = 0x4446463C, + .p0_mpwrdlctl = 0x3C38323A, + .p1_mpwrdlctl = 0x34323430, +}; + +static struct mx6_ddr3_cfg mem_ddr_2g = { + .mem_speed = 1600, + .density = 2, + .width = 16, + .banks = 8, + .rowaddr = 14, + .coladdr = 10, + .pagesz = 2, + .trcd = 1310, + .trcmin = 4875, + .trasmin = 3500, +}; + +static struct mx6_ddr3_cfg mem_ddr_4g = { + .mem_speed = 1600, + .density = 4, + .width = 16, + .banks = 8, + .rowaddr = 15, + .coladdr = 10, + .pagesz = 2, + .trcd = 1310, + .trcmin = 4875, + .trasmin = 3500, +}; + +static struct mx6_ddr3_cfg mem_ddr_8g = { + .mem_speed = 1600, + .density = 8, + .width = 16, + .banks = 8, + .rowaddr = 16, + .coladdr = 10, + .pagesz = 2, + .trcd = 1310, + .trcmin = 4875, + .trasmin = 3500, +}; + +static void spl_dram_init(u8 width, u32 memsize) { + struct mx6_ddr_sysinfo sysinfo = { + /* width of data bus: 0=16, 1=32, 2=64 */ + .dsize = width / 32, + /* config for full 4GB range so that get_mem_size() works */ + .cs_density = 32, /* 32Gb per CS */ + + .ncs = 1, + .cs1_mirror = 0, + .rtt_wr = 2, + .rtt_nom = 2, + .walat = 0, + .ralat = 5, + .mif3_mode = 3, + .bi_on = 1, + .sde_to_rst = 0x0d, + .rst_to_cke = 0x20, + }; + + if (is_cpu_type(MXC_CPU_MX6SOLO)) { + sysinfo.walat = 1; + mx6sdl_dram_iocfg(width, &mx6dl_ddr_ioregs, &mx6sdl_grp_ioregs); + + switch(memsize) { + case 512: + mx6_dram_cfg(&sysinfo, &mx6s_2g_mmcd_calib, &mem_ddr_2g); + break; + default: + mx6_dram_cfg(&sysinfo, &mx6s_mmcd_calib, &mem_ddr_4g); + break; + } + } else if (is_cpu_type(MXC_CPU_MX6DL)) { + sysinfo.walat = 1; + mx6sdl_dram_iocfg(width, &mx6dl_ddr_ioregs, &mx6sdl_grp_ioregs); + + switch(memsize) { + case 2048: + mx6_dram_cfg(&sysinfo, &mx6dl_2g_mmcd_calib, &mem_ddr_4g); + break; + default: + mx6_dram_cfg(&sysinfo, &mx6dl_mmcd_calib, &mem_ddr_2g); + break; + } + } else if (is_cpu_type(MXC_CPU_MX6Q)) { + mx6dq_dram_iocfg(width, &mx6q_ddr_ioregs, &mx6q_grp_ioregs); + + switch(memsize) { + case 4096: + sysinfo.cs_density = 16; + sysinfo.ncs = 2; + mx6_dram_cfg(&sysinfo, &mx6q_4g_mmcd_calib, &mem_ddr_8g); + break; + case 2048: + mx6_dram_cfg(&sysinfo, &mx6q_2g_mmcd_calib, &mem_ddr_4g); + break; + default: + mx6_dram_cfg(&sysinfo, &mx6q_mmcd_calib, &mem_ddr_2g); + break; + } + } +} + +/* Define a minimal structure so that the part number can be read via SPL */ +#define CFG_MFG_ADDR_OFFSET (spi->size - SZ_16K) +struct mfgdata { + unsigned char tsize; + /* size of checksummed part in bytes */ + unsigned char ckcnt; + /* checksum corrected byte */ + unsigned char cksum; + /* decimal serial number, packed BCD */ + unsigned char serial[6]; + /* part number, right justified, ASCII */ + unsigned char pn[16]; +}; + +static void conv_ascii(unsigned char *dst, unsigned char *src, int len) +{ + int remain = len; + unsigned char *sptr = src; + unsigned char *dptr = dst; + + while (remain) { + if (*sptr) { + *dptr = *sptr; + dptr++; + } + sptr++; + remain--; + } + *dptr = 0x0; +} + +/* + * Returns the total size of the memory [in MB] the board is equipped with + * + * This is determined via the partnumber which is stored in the + * congatec manufacturing area + */ +static int get_boardmem_size(struct spi_flash *spi) +{ + int ret; + int i; + int arraysize; + char buf[sizeof(struct mfgdata)]; + struct mfgdata *data = (struct mfgdata *)buf; + unsigned char outbuf[32]; + char partnumbers_2g[4][7] = { "016104", "016105", "016304", "016305" }; + char partnumbers_4g[2][7] = { "016308", "016318" }; + char partnumbers_512m[2][7] = { "016203", "616300" }; + + ret = spi_flash_read(spi, CFG_MFG_ADDR_OFFSET, sizeof(struct mfgdata), + buf); + if (ret) + return 1024; /* default to 1GByte in case of error */ + + conv_ascii(outbuf, data->pn, sizeof(data->pn)); + + printf("Detected Congatec QMX6 SOM: %s\n", outbuf); + + /* congatec PN 016104, 016105, 016304, 016305 have 2GiB of RAM */ + arraysize = sizeof(partnumbers_2g) / sizeof(partnumbers_2g[0]); + for (i=0; i < arraysize; i++) { + if (!memcmp(outbuf,partnumbers_2g[i],6)) + return 2048; + } + + /* congatec PN 016308, 016318 have 4GiB of RAM */ + arraysize = sizeof(partnumbers_4g) / sizeof(partnumbers_4g[0]); + for (i=0; i < arraysize; i++) { + if (!memcmp(outbuf,partnumbers_4g[i],6)) + return 4096; + } + + /* congatec PN 016203, 616300 has 512MiB of RAM */ + arraysize = sizeof(partnumbers_512m) / sizeof(partnumbers_512m[0]); + for (i=0; i < arraysize; i++) { + if (!memcmp(outbuf,partnumbers_512m[i],6)) + return 512; + } + + /* default to 1GByte */ + return 1024; +} + +void reset_cpu(ulong addr) +{ +} + +int board_spi_cs_gpio(unsigned bus, unsigned cs) +{ + if (bus == 0 && cs == 0) + return (SPI1_CS0); + else + return -1; +} + +static void memory_init(void) { + struct spi_flash *spi; + u8 width; + u32 size; + + SETUP_IOMUX_PADS(ecspi1_pads); + gpio_direction_output(SPI1_CS0, 0); + + spi = spi_flash_probe(CONFIG_ENV_SPI_BUS, + CONFIG_ENV_SPI_CS, + CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE); + if (!spi) + panic("Cannot identify board type: SPI-NOR flash module not detected\n"); + + /* lock manufacturer area */ + spi_flash_protect(spi, CFG_MFG_ADDR_OFFSET, SZ_16K, true); + + width = is_cpu_type(MXC_CPU_MX6SOLO) ? 32 : 64; + size = get_boardmem_size(spi); + printf("Detected Memory Size: %u\n", size); + + spl_dram_init(width, size); +} + +static void ccgr_init(void) +{ + struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; + + static const uint32_t ccgr0 = + MXC_CCM_CCGR0_AIPS_TZ1_MASK | + MXC_CCM_CCGR0_AIPS_TZ2_MASK | + MXC_CCM_CCGR0_APBHDMA_MASK | + MXC_CCM_CCGR0_CAAM_SECURE_MEM_MASK | + MXC_CCM_CCGR0_CAAM_WRAPPER_ACLK_MASK | + MXC_CCM_CCGR0_CAAM_WRAPPER_IPG_MASK | + MXC_CCM_CCGR0_CHEETAH_DBG_CLK_MASK; + + static const uint32_t ccgr1 = + MXC_CCM_CCGR1_ECSPI1S_MASK | + MXC_CCM_CCGR1_ENET_MASK | + MXC_CCM_CCGR1_EPIT1S_MASK | + MXC_CCM_CCGR1_EPIT2S_MASK | + MXC_CCM_CCGR1_GPT_BUS_MASK; + + static const uint32_t ccgr2 = + MXC_CCM_CCGR2_IOMUX_IPT_CLK_IO_MASK | + MXC_CCM_CCGR2_IPMUX1_MASK | + MXC_CCM_CCGR2_IPMUX2_MASK | + MXC_CCM_CCGR2_IPMUX3_MASK | + MXC_CCM_CCGR2_IPSYNC_IP2APB_TZASC1_IPGS_MASK | + MXC_CCM_CCGR2_IPSYNC_IP2APB_TZASC2_IPG_MASK | + MXC_CCM_CCGR2_IPSYNC_VDOA_IPG_MASTER_CLK_MASK; + + static const uint32_t ccgr3 = + MXC_CCM_CCGR3_MMDC_CORE_ACLK_FAST_CORE_P0_MASK | + MXC_CCM_CCGR3_MMDC_CORE_ACLK_FAST_CORE_P1_MASK | + MXC_CCM_CCGR3_MMDC_CORE_IPG_CLK_P0_MASK | + MXC_CCM_CCGR3_MMDC_CORE_IPG_CLK_P1_MASK | + MXC_CCM_CCGR3_OCRAM_MASK; + + static const uint32_t ccgr4 = + MXC_CCM_CCGR4_PL301_MX6QFAST1_S133_MASK | + MXC_CCM_CCGR4_PL301_MX6QPER1_BCH_MASK | + MXC_CCM_CCGR4_PL301_MX6QPER2_MAINCLK_ENABLE_MASK | + MXC_CCM_CCGR4_PWM1_MASK | + MXC_CCM_CCGR4_PWM2_MASK | + MXC_CCM_CCGR4_PWM3_MASK | + MXC_CCM_CCGR4_PWM4_MASK; + + static const uint32_t ccgr5 = + MXC_CCM_CCGR5_ROM_MASK | + MXC_CCM_CCGR5_SDMA_MASK | + MXC_CCM_CCGR5_UART_MASK | + MXC_CCM_CCGR5_UART_SERIAL_MASK; + + static const uint32_t ccgr6 = + MXC_CCM_CCGR6_USBOH3_MASK | + MXC_CCM_CCGR6_USDHC1_MASK | + MXC_CCM_CCGR6_USDHC2_MASK | + MXC_CCM_CCGR6_SIM1_CLK_MASK | + MXC_CCM_CCGR6_SIM2_CLK_MASK; + + writel(ccgr0, &ccm->CCGR0); + writel(ccgr1, &ccm->CCGR1); + writel(ccgr2, &ccm->CCGR2); + writel(ccgr3, &ccm->CCGR3); + writel(ccgr4, &ccm->CCGR4); + writel(ccgr5, &ccm->CCGR5); + writel(ccgr6, &ccm->CCGR6); +} + +void board_init_f(ulong dummy) +{ + /* setup clock gating */ + ccgr_init(); + + /* setup AIPS and disable watchdog */ + arch_cpu_init(); + + /* setup AXI */ + gpr_init(); + + /* + * setup poweroff GPIO. This controls system power regulator. Once + * the power button is released this must be enabled to keep system + * running. Not enabling it (or disabling it later) will turn off + * the main system regulator and instantly poweroff the system. We + * do this very early, to reduce the time users have to press the + * power button. + */ + SETUP_IOMUX_PADS(poweroff_pads); + gpio_direction_output(POWEROFF, 1); + + /* setup GP timer */ + timer_init(); + + /* iomux */ + if (CONFIG_MXC_UART_BASE == UART2_BASE) + SETUP_IOMUX_PADS(uart2_pads); + else if (CONFIG_MXC_UART_BASE == UART3_BASE) + SETUP_IOMUX_PADS(uart3_pads); + + /* UART clocks enabled and gd valid - init serial console */ + preloader_console_init(); + + /* Needed for malloc() [used by SPI] to work in SPL prior to board_init_r() */ + spl_init(); + + /* DDR initialization */ + memory_init(); +} + +void spl_board_prepare_for_boot(void) +{ + printf("Load normal U-Boot...\n"); +} +#endif diff --git a/configs/ge_b1x5v2_defconfig b/configs/ge_b1x5v2_defconfig new file mode 100644 index 000000000000..dd375e5b34b1 --- /dev/null +++ b/configs/ge_b1x5v2_defconfig @@ -0,0 +1,148 @@ +CONFIG_DEFAULT_FDT_FILE="imx6dl-b1x5v2.dtb" +CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/mach-imx/spl_sd.cfg" +CONFIG_ARM=y +CONFIG_ARCH_MX6=y +CONFIG_BCH=y +CONFIG_SYS_TEXT_BASE=0x17800000 +CONFIG_SPL_TEXT_BASE=0x00908000 +CONFIG_ENV_SIZE=0x2000 +CONFIG_ENV_OFFSET=0xC0000 +CONFIG_ENV_SECT_SIZE=0x10000 +CONFIG_SYS_SPI_U_BOOT_OFFS=0x11400 +CONFIG_TARGET_GE_B1X5V2=y +CONFIG_NR_DRAM_BANKS=1 +CONFIG_FIT=y +CONFIG_BOOTDELAY=0 +CONFIG_SYS_CONSOLE_IS_IN_ENV=y +CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE=y +CONFIG_SUPPORT_RAW_INITRD=y +CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_HUSH_PARSER=y +CONFIG_CMD_BOOTZ=y +CONFIG_CMD_I2C=y +CONFIG_CMD_SPI=y +CONFIG_CMD_MMC=y +CONFIG_CMD_NET=y +CONFIG_OF_LIBFDT=y +CONFIG_SYS_I2C_MXC=y +CONFIG_MXC_GPIO=y +CONFIG_CMD_GPIO=y +CONFIG_PHYLIB=y +CONFIG_PHY_ATHEROS=y +CONFIG_FEC_MXC=y +CONFIG_MII=y +CONFIG_CMD_FS_GENERIC=y +CONFIG_CMD_EXT2=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_CMD_FAT=y +CONFIG_CMD_PING=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_MII=y +CONFIG_MXC_UART=y +CONFIG_DEBUG_UART=y +CONFIG_DEBUG_UART_MXC=y +# CONFIG_DEBUG_UART_BASE=0x21e8000 +CONFIG_DEBUG_UART_BASE=0x21ec000 +CONFIG_DEBUG_UART_CLOCK=24000000 +CONFIG_SPL=y +CONFIG_SPL_GPIO_SUPPORT=y +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_SPL_LIBDISK_SUPPORT=y +CONFIG_SPL_SPI_SUPPORT=y +CONFIG_SPL_SPI_FLASH_SUPPORT=y +CONFIG_SPL_SPI_LOAD=y +CONFIG_SPL_USB_GADGET=y +CONFIG_SPL_USB_SDP_SUPPORT=y +CONFIG_FSL_ESDHC=y +CONFIG_SPI=y +CONFIG_MXC_SPI=y +CONFIG_CMD_SF=y +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_ENV_SPI_BUS=0 +CONFIG_ENV_SPI_CS=0 +CONFIG_ENV_SPI_MODE=0 +CONFIG_ENV_SPI_MAX_HZ=20000000 +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_SST=y +CONFIG_SPI_FLASH_WINBOND=y +# CONFIG_GE_RTC is not set +CONFIG_IMX_THERMAL=y +CONFIG_WDT=y +CONFIG_WDT_IMX=y +CONFIG_WATCHDOG_TIMEOUT_MSECS=30000 +CONFIG_RTC_M41T62=y +CONFIG_USB=y +CONFIG_USB_KEYBOARD=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_MANUFACTURER="Congatec" +CONFIG_USB_GADGET_VENDOR_NUM=0x0525 +CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5 +CONFIG_SPL_USB_HOST_SUPPORT=y +CONFIG_CI_UDC=y +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_BOUNCE_BUFFER=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_USB=y +CONFIG_CMD_REGULATOR=y +CONFIG_MISC_INIT_R=y +CONFIG_SF_DEFAULT_MODE=0 +CONFIG_SF_DEFAULT_SPEED=20000000 +CONFIG_VIDEO_IPUV3=y +CONFIG_BACKLIGHT_PWM=y +CONFIG_DM=y +CONFIG_CMD_DM=y +CONFIG_OF_CONTROL=y +CONFIG_DEFAULT_DEVICE_TREE="imx6dl-b1x5v2" +CONFIG_DM_MMC=y +CONFIG_BLK=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_IMX6=y +CONFIG_DM_GPIO=y +CONFIG_DM_I2C=y +CONFIG_I2C_MUX=y +CONFIG_I2C_MUX_GPIO=y +CONFIG_DM_PMIC=y +CONFIG_DM_PMIC_PFUZE100=y +CONFIG_DM_SPI=y +CONFIG_DM_SPI_FLASH=y +CONFIG_DM_ETH=y +CONFIG_DM_USB=y +CONFIG_DM_VIDEO=y +CONFIG_DM_REGULATOR=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_GPIO=y +CONFIG_DM_PWM=y +CONFIG_PWM_IMX=y +CONFIG_DM_RTC=y +CONFIG_DM_PCA953X=y +CONFIG_LED=y +CONFIG_LED_GPIO=y +CONFIG_SYS_MALLOC_F_LEN=0x4000 +CONFIG_CMD_BOOTCOUNT=y +CONFIG_BOOTCOUNT_LIMIT=y +CONFIG_BOOTCOUNT_BOOTLIMIT=10 +CONFIG_DM_BOOTCOUNT=y +CONFIG_DM_BOOTCOUNT_SPI_FLASH=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_GREPENV=y +CONFIG_CMD_SNTP=y +CONFIG_CMD_DNS=y +CONFIG_CMD_TIME=y +CONFIG_CMD_PMIC=y +CONFIG_CMD_LED=y +CONFIG_CMD_BMP=y +CONFIG_CMD_LOG=y +CONFIG_CMD_CLS=y +CONFIG_LOG_MAX_LEVEL=8 +CONFIG_DM_SERIAL=y +CONFIG_SPECIFY_CONSOLE_INDEX=y +CONFIG_POWEROFF=y +CONFIG_POWEROFF_GPIO=y +CONFIG_CMD_POWEROFF=y +# CONFIG_SPL_PMIC_CHILDREN is not set +# CONFIG_SPL_DOS_PARTITION is not set +CONFIG_OF_BOARD_SETUP=y +CONFIG_SPL_PAYLOAD="u-boot.img" diff --git a/include/configs/ge_b1x5v2.h b/include/configs/ge_b1x5v2.h new file mode 100644 index 000000000000..91ad67cfe249 --- /dev/null +++ b/include/configs/ge_b1x5v2.h @@ -0,0 +1,125 @@ +/* + * GE B1x5v2 + * + * Copyright 2018-2020 GE Inc. + * Copyright 2018-2020 Collabora Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __GE_B1X5V2_CONFIG_H +#define __GE_B1X5V2_CONFIG_H + +#include "mx6_common.h" + +#include "imx6_spl.h" +#define CONFIG_SPL_TARGET "u-boot-with-spl.imx" + +/* Size of malloc() pool */ +#define CONFIG_SYS_MALLOC_LEN (10 * SZ_1M) + +/* PWM */ +#define CONFIG_IMX6_PWM_PER_CLK 66000000 + +/* UART */ +#define CONFIG_MXC_UART_BASE UART3_BASE + +#if CONFIG_MXC_UART_BASE == UART2_BASE +#define CONSOLE_DEVICE "ttymxc1" /* System on Module debug connector */ +#else +#define CONSOLE_DEVICE "ttymxc2" /* Base board debug connector */ +#endif + +/* USB */ +#define CONFIG_EHCI_HCD_INIT_AFTER_RESET +#define CONFIG_MXC_USB_PORTSC (PORT_PTS_UTMI | PORT_PTS_PTW) +#define CONFIG_MXC_USB_FLAGS 0 +#define CONFIG_USB_MAX_CONTROLLER_COUNT 2 /* Enabled USB controller number */ +#define CONFIG_USBD_HS + +/* Video */ +#define CONFIG_HIDE_LOGO_VERSION +#define CONFIG_IMX_VIDEO_SKIP + +/* Memory */ +#define PHYS_SDRAM MMDC0_ARB_BASE_ADDR + +#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM +#define CONFIG_SYS_INIT_RAM_ADDR IRAM_BASE_ADDR +#define CONFIG_SYS_INIT_RAM_SIZE IRAM_SIZE + +#define CONFIG_SYS_INIT_SP_OFFSET \ + (CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE) +#define CONFIG_SYS_INIT_SP_ADDR \ + (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET) + +/* Command definition */ +#define CONFIG_EXTRA_ENV_SETTINGS \ + "image=/boot/fitImage\0" \ + "fdt_addr_r=0x18000000\0" \ + "splash_addr_r=0x20000000\0" \ + "mmcdev=2\0" \ + "mmcpart=1\0" \ + "console=console="CONSOLE_DEVICE",115200\0" \ + "quiet=quiet loglevel=0\0" \ + "rootdev=/dev/mmcblk1p\0" \ + "setargs=setenv bootargs ${console} ${quiet} ${fsckforcerepair} " \ + "bootcause=${bootcause} vt.global_cursor_default=0 vt.cur_default=1 " \ + "root=${rootdev}${mmcpart} video=HDMI-A-1:${resolution} rootwait ro\0" \ + "loadimage=load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}\0" \ + "showsplashscreen=load mmc ${mmcdev}:${mmcpart} ${splash_addr_r} /boot/splashscreen-${resolution}.bmp; " \ + "bmp display ${splash_addr_r};\0" \ + "setconfidx=" \ + "if test \"${devicetype}\" = \"B105v2\"; then " \ + "setenv confidx 1; " \ + "elif test \"${devicetype}\" = \"B125v2\"; then " \ + "setenv confidx 2; " \ + "elif test \"${devicetype}\" = \"B155v2\"; then " \ + "setenv confidx 3; " \ + "elif test \"${devicetype}\" = \"B105Pv2\"; then " \ + "setenv confidx 4; " \ + "elif test \"${devicetype}\" = \"B125Pv2\"; then " \ + "setenv confidx 5; " \ + "fi;\0" \ + "set_default_type=setenv devicetype B155v2; setenv resolution 1366x768;" \ + "setenv fdtfile imx6dl-b155v2.dtb; run setconfidx;\0" \ + "checkconfidx=env exists confidx || run set_default_type;\0" \ + "checkfsckforcerepair=" \ + "if test \"${bootcount}\" > \"3\" ; then " \ + "setenv fsckforcerepair fsck.repair=1; " \ + "fi;\0" \ + "helix=run setconfidx; run checkconfidx; run checkfsckforcerepair; run setargs; " \ + "regulator dev LED_VCC; regulator enable; " \ + "regulator dev 5V0_AUDIO; regulator enable; " \ + "bootm ${loadaddr}#conf@${confidx};\0" \ + "failbootcmd=" \ + "echo reached failbootcmd;" \ + "cls; setcurs 5 4; " \ + "lcdputs \"Monitor failed to start. Try again, or contact GE Service for support.\"; " \ + "bootcount reset; \0" \ + "hasfirstboot=" \ + "load mmc ${mmcdev}:${mmcpart} ${loadaddr} " \ + "/boot/bootcause/firstboot;\0" \ + "swappartitions=" \ + "setexpr mmcpart 3 - ${mmcpart};\0" \ + "doboot=" \ + "echo Booting from mmc:${mmcdev}:${mmcpart} ...; " \ + "run helix;\0" \ + "altbootcmd=" \ + "setenv mmcpart 1; run hasfirstboot || setenv mmcpart 2; " \ + "run hasfirstboot || setenv mmcpart 0; " \ + "if test ${mmcpart} != 0; then " \ + "setenv bootcause REVERT; " \ + "run swappartitions loadimage doboot; " \ + "fi; " \ + "run failbootcmd\0" \ + "tryboot=" \ + "setenv mmcpart 1; run hasfirstboot || setenv mmcpart 2; " \ + "run loadimage || run swappartitions && run loadimage || " \ + "setenv mmcpart 0 && echo MISSING IMAGE;" \ + "run showsplashscreen; sleep 1; " \ + "run doboot; run failbootcmd;\0" \ + +#define CONFIG_BOOTCOMMAND "run tryboot;" + +#endif /* __GE_B1X5V2_CONFIG_H */