u-boot-imx for 2021.1
---------------------

- new boards : GE (new B1x5v2), phytec phyCORE-i.MX8MM
- converted doc to reST
- fixes for verdin-imx8mm (Toradex)
- fixes for i.MX thermal driver
- mx7ulp: Align the PLL_USB frequency
- mx53: primary/secondary bmode

Travis: https://travis-ci.org/github/sbabic/u-boot-imx/builds/741465284
This commit is contained in:
Tom Rini
2020-11-05 11:57:50 -05:00
72 changed files with 6099 additions and 535 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,125 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2019 Collabora
* (C) Copyright 2019 GE
*/
#include <common.h>
#include <bootcount.h>
#include <dm.h>
#include <spi_flash.h>
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,
};

View File

@@ -22,6 +22,8 @@
#include <log.h>
#include <rtc.h>
#include <i2c.h>
#include <linux/log2.h>
#include <linux/delay.h>
#define M41T62_REG_SSEC 0
#define M41T62_REG_SEC 1
@@ -47,8 +49,14 @@
#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
#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 +147,140 @@ 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_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;
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 ret;
return 0;
}
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;
/*
* 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 +289,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 = {

View File

@@ -43,6 +43,13 @@ config SYSRESET_CMD_POWEROFF
endif
config POWEROFF_GPIO
bool "Enable support for GPIO poweroff driver"
select DM_GPIO
help
Support for system poweroff using a GPIO pin. This can be used
for systems having a single GPIO to trigger a system poweroff.
config SYSRESET_GPIO
bool "Enable support for GPIO reset driver"
select DM_GPIO

View File

@@ -7,6 +7,7 @@ obj-$(CONFIG_ARCH_ASPEED) += sysreset_ast.o
obj-$(CONFIG_ARCH_ROCKCHIP) += sysreset_rockchip.o
obj-$(CONFIG_ARCH_STI) += sysreset_sti.o
obj-$(CONFIG_SANDBOX) += sysreset_sandbox.o
obj-$(CONFIG_POWEROFF_GPIO) += poweroff_gpio.o
obj-$(CONFIG_SYSRESET_GPIO) += sysreset_gpio.o
obj-$(CONFIG_SYSRESET_MPC83XX) += sysreset_mpc83xx.o
obj-$(CONFIG_SYSRESET_MICROBLAZE) += sysreset_microblaze.o

View File

@@ -0,0 +1,92 @@
// 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 <jm@lentin.co.uk>
* Andrew Lunn <andrew@lunn.ch>
*
* Copyright (C) 2012 Jamie Lentin
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <log.h>
#include <sysreset.h>
#include <asm/gpio.h>
#include <linux/delay.h>
struct poweroff_gpio_info {
struct gpio_desc gpio;
u32 active_delay_ms;
u32 inactive_delay_ms;
u32 timeout_ms;
};
static int poweroff_gpio_request(struct udevice *dev, enum sysreset_t type)
{
struct poweroff_gpio_info *priv = dev_get_priv(dev);
int r;
if (type != SYSRESET_POWER_OFF)
return -ENOSYS;
debug("GPIO poweroff\n");
/* drive it active, also inactive->active edge */
r = dm_gpio_set_value(&priv->gpio, 1);
if (r < 0)
return r;
mdelay(priv->active_delay_ms);
/* drive inactive, also active->inactive edge */
r = dm_gpio_set_value(&priv->gpio, 0);
if (r < 0)
return r;
mdelay(priv->inactive_delay_ms);
/* drive it active, also inactive->active edge */
r = dm_gpio_set_value(&priv->gpio, 1);
if (r < 0)
return r;
/* give it some time */
mdelay(priv->timeout_ms);
return -EINPROGRESS;
}
static int poweroff_gpio_probe(struct udevice *dev)
{
struct poweroff_gpio_info *priv = dev_get_priv(dev);
int flags;
flags = dev_read_bool(dev, "input") ? GPIOD_IS_IN : GPIOD_IS_OUT;
priv->active_delay_ms = dev_read_u32_default(dev, "active-delay-ms", 100);
priv->inactive_delay_ms = dev_read_u32_default(dev, "inactive-delay-ms", 100);
priv->timeout_ms = dev_read_u32_default(dev, "timeout-ms", 3000);
return gpio_request_by_name(dev, "gpios", 0, &priv->gpio, flags);
}
static struct sysreset_ops poweroff_gpio_ops = {
.request = poweroff_gpio_request,
};
static const struct udevice_id poweroff_gpio_ids[] = {
{ .compatible = "gpio-poweroff", },
{},
};
U_BOOT_DRIVER(poweroff_gpio) = {
.name = "poweroff-gpio",
.id = UCLASS_SYSRESET,
.ops = &poweroff_gpio_ops,
.probe = poweroff_gpio_probe,
.priv_auto_alloc_size = sizeof(struct poweroff_gpio_info),
.of_match = poweroff_gpio_ids,
};

View File

@@ -14,6 +14,7 @@
#include <dm/device.h>
#include <errno.h>
#include <fuse.h>
#include <linux/delay.h>
#include <malloc.h>
#include <thermal.h>

View File

@@ -21,12 +21,6 @@ config WATCHDOG_TIMEOUT_MSECS
config HW_WATCHDOG
bool
config WATCHDOG_RESET_DISABLE
bool "Disable reset watchdog"
help
Disable reset watchdog, which can let WATCHDOG_RESET invalid, so
that the watchdog will not be fed in u-boot.
config IMX_WATCHDOG
bool "Enable Watchdog Timer support for IMX and LSCH2 of NXP"
select HW_WATCHDOG if !WDT
@@ -34,6 +28,13 @@ config IMX_WATCHDOG
Select this to enable the IMX and LSCH2 of Layerscape watchdog
driver.
config WATCHDOG_RESET_DISABLE
bool "Disable reset watchdog"
depends on IMX_WATCHDOG
help
Disable reset watchdog, which can let WATCHDOG_RESET invalid, so
that the watchdog will not be fed in u-boot.
config OMAP_WATCHDOG
bool "TI OMAP watchdog driver"
depends on ARCH_OMAP2PLUS