mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-22 04:44:46 +00:00
Merge tag 'i2cfixes-for-v2024-01-rc2' of https://source.denx.de/u-boot/custodians/u-boot-i2c
i2c updates for v2024.01-rc2 - nuvoton: support standard/fast/fast plus mode - bootcount: remove legacy i2c driver and implement DM based version Bugfixes: - designware_i2c: adjust timing calculation SPL probing failed on the StarFive VisionFive 2 board Heinrich fixed this, by syncing timing calculation with linux implementation.
This commit is contained in:
commit
07fe79c93c
8 changed files with 218 additions and 74 deletions
|
@ -79,14 +79,6 @@ config BOOTCOUNT_RAM
|
||||||
Store the bootcount in DRAM protected against bit errors
|
Store the bootcount in DRAM protected against bit errors
|
||||||
due to short power loss or holding a system in RESET.
|
due to short power loss or holding a system in RESET.
|
||||||
|
|
||||||
config BOOTCOUNT_I2C
|
|
||||||
bool "Boot counter on I2C device"
|
|
||||||
help
|
|
||||||
Enable support for the bootcounter on an i2c (like RTC) device.
|
|
||||||
CFG_SYS_I2C_RTC_ADDR = i2c chip address
|
|
||||||
CONFIG_SYS_BOOTCOUNT_ADDR = i2c addr which is used for
|
|
||||||
the bootcounter.
|
|
||||||
|
|
||||||
config BOOTCOUNT_AT91
|
config BOOTCOUNT_AT91
|
||||||
bool "Boot counter for Atmel AT91SAM9XE"
|
bool "Boot counter for Atmel AT91SAM9XE"
|
||||||
depends on AT91SAM9XE
|
depends on AT91SAM9XE
|
||||||
|
@ -117,6 +109,16 @@ config DM_BOOTCOUNT_RTC
|
||||||
Accesses to the backing store are performed using the write16
|
Accesses to the backing store are performed using the write16
|
||||||
and read16 ops of DM RTC devices.
|
and read16 ops of DM RTC devices.
|
||||||
|
|
||||||
|
config DM_BOOTCOUNT_I2C
|
||||||
|
bool "Driver Model boot counter on I2C device"
|
||||||
|
depends on DM_I2C
|
||||||
|
help
|
||||||
|
Enable support for the bootcounter on a generic i2c device, like a RTC
|
||||||
|
or PMIC. The bootcounter is configured in the device tree using the
|
||||||
|
"u-boot,bootcount-i2c" compatible string. It requires a phandle
|
||||||
|
'i2cbcdev' for the i2c device and an 'offset' property used within the
|
||||||
|
device.
|
||||||
|
|
||||||
config DM_BOOTCOUNT_I2C_EEPROM
|
config DM_BOOTCOUNT_I2C_EEPROM
|
||||||
bool "Support i2c eeprom devices as a backing store for bootcount"
|
bool "Support i2c eeprom devices as a backing store for bootcount"
|
||||||
depends on I2C_EEPROM
|
depends on I2C_EEPROM
|
||||||
|
@ -175,14 +177,6 @@ config BOOTCOUNT_BOOTLIMIT
|
||||||
counter being cleared.
|
counter being cleared.
|
||||||
If set to 0, do not set a boot limit in the environment.
|
If set to 0, do not set a boot limit in the environment.
|
||||||
|
|
||||||
config BOOTCOUNT_ALEN
|
|
||||||
int "I2C address length"
|
|
||||||
default 1
|
|
||||||
depends on BOOTCOUNT_I2C
|
|
||||||
help
|
|
||||||
Length of the the I2C address at SYS_BOOTCOUNT_ADDR for storing
|
|
||||||
the boot counter.
|
|
||||||
|
|
||||||
config SYS_BOOTCOUNT_SINGLEWORD
|
config SYS_BOOTCOUNT_SINGLEWORD
|
||||||
bool "Use single word to pack boot count and magic value"
|
bool "Use single word to pack boot count and magic value"
|
||||||
depends on BOOTCOUNT_GENERIC
|
depends on BOOTCOUNT_GENERIC
|
||||||
|
@ -218,7 +212,7 @@ config SYS_BOOTCOUNT_ADDR
|
||||||
default 0x44E3E000 if BOOTCOUNT_AM33XX || BOOTCOUNT_AM33XX_NVMEM
|
default 0x44E3E000 if BOOTCOUNT_AM33XX || BOOTCOUNT_AM33XX_NVMEM
|
||||||
default 0xE0115FF8 if ARCH_LS1043A || ARCH_LS1021A
|
default 0xE0115FF8 if ARCH_LS1043A || ARCH_LS1021A
|
||||||
depends on BOOTCOUNT_AM33XX || BOOTCOUNT_GENERIC || BOOTCOUNT_EXT || \
|
depends on BOOTCOUNT_AM33XX || BOOTCOUNT_GENERIC || BOOTCOUNT_EXT || \
|
||||||
BOOTCOUNT_I2C || BOOTCOUNT_AM33XX_NVMEM
|
BOOTCOUNT_AM33XX_NVMEM
|
||||||
help
|
help
|
||||||
Set the address used for reading and writing the boot counter.
|
Set the address used for reading and writing the boot counter.
|
||||||
|
|
||||||
|
@ -226,13 +220,11 @@ config SYS_BOOTCOUNT_MAGIC
|
||||||
hex "Magic value for the boot counter"
|
hex "Magic value for the boot counter"
|
||||||
default 0xB001C041 if BOOTCOUNT_GENERIC || BOOTCOUNT_EXT || \
|
default 0xB001C041 if BOOTCOUNT_GENERIC || BOOTCOUNT_EXT || \
|
||||||
BOOTCOUNT_AM33XX || BOOTCOUNT_ENV || \
|
BOOTCOUNT_AM33XX || BOOTCOUNT_ENV || \
|
||||||
BOOTCOUNT_RAM || BOOTCOUNT_I2C || \
|
BOOTCOUNT_RAM || BOOTCOUNT_AT91 || DM_BOOTCOUNT
|
||||||
BOOTCOUNT_AT91 || DM_BOOTCOUNT
|
|
||||||
default 0xB0 if BOOTCOUNT_AM33XX_NVMEM
|
default 0xB0 if BOOTCOUNT_AM33XX_NVMEM
|
||||||
depends on BOOTCOUNT_GENERIC || BOOTCOUNT_EXT || \
|
depends on BOOTCOUNT_GENERIC || BOOTCOUNT_EXT || \
|
||||||
BOOTCOUNT_AM33XX || BOOTCOUNT_ENV || \
|
BOOTCOUNT_AM33XX || BOOTCOUNT_ENV || \
|
||||||
BOOTCOUNT_RAM || BOOTCOUNT_I2C || \
|
BOOTCOUNT_RAM || BOOTCOUNT_AT91 || DM_BOOTCOUNT || \
|
||||||
BOOTCOUNT_AT91 || DM_BOOTCOUNT || \
|
|
||||||
BOOTCOUNT_AM33XX_NVMEM
|
BOOTCOUNT_AM33XX_NVMEM
|
||||||
help
|
help
|
||||||
Set the magic value used for the boot counter.
|
Set the magic value used for the boot counter.
|
||||||
|
|
|
@ -6,7 +6,6 @@ obj-$(CONFIG_BOOTCOUNT_AT91) += bootcount_at91.o
|
||||||
obj-$(CONFIG_BOOTCOUNT_AM33XX) += bootcount_davinci.o
|
obj-$(CONFIG_BOOTCOUNT_AM33XX) += bootcount_davinci.o
|
||||||
obj-$(CONFIG_BOOTCOUNT_RAM) += bootcount_ram.o
|
obj-$(CONFIG_BOOTCOUNT_RAM) += bootcount_ram.o
|
||||||
obj-$(CONFIG_BOOTCOUNT_ENV) += bootcount_env.o
|
obj-$(CONFIG_BOOTCOUNT_ENV) += bootcount_env.o
|
||||||
obj-$(CONFIG_BOOTCOUNT_I2C) += bootcount_i2c.o
|
|
||||||
obj-$(CONFIG_BOOTCOUNT_EXT) += bootcount_ext.o
|
obj-$(CONFIG_BOOTCOUNT_EXT) += bootcount_ext.o
|
||||||
obj-$(CONFIG_BOOTCOUNT_AM33XX_NVMEM) += bootcount_nvmem.o
|
obj-$(CONFIG_BOOTCOUNT_AM33XX_NVMEM) += bootcount_nvmem.o
|
||||||
|
|
||||||
|
@ -14,5 +13,6 @@ obj-$(CONFIG_DM_BOOTCOUNT) += bootcount-uclass.o
|
||||||
obj-$(CONFIG_DM_BOOTCOUNT_PMIC_PFUZE100) += pmic_pfuze100.o
|
obj-$(CONFIG_DM_BOOTCOUNT_PMIC_PFUZE100) += pmic_pfuze100.o
|
||||||
obj-$(CONFIG_DM_BOOTCOUNT_RTC) += rtc.o
|
obj-$(CONFIG_DM_BOOTCOUNT_RTC) += rtc.o
|
||||||
obj-$(CONFIG_DM_BOOTCOUNT_I2C_EEPROM) += i2c-eeprom.o
|
obj-$(CONFIG_DM_BOOTCOUNT_I2C_EEPROM) += i2c-eeprom.o
|
||||||
|
obj-$(CONFIG_DM_BOOTCOUNT_I2C) += bootcount_dm_i2c.o
|
||||||
obj-$(CONFIG_DM_BOOTCOUNT_SPI_FLASH) += spi-flash.o
|
obj-$(CONFIG_DM_BOOTCOUNT_SPI_FLASH) += spi-flash.o
|
||||||
obj-$(CONFIG_DM_BOOTCOUNT_SYSCON) += bootcount_syscon.o
|
obj-$(CONFIG_DM_BOOTCOUNT_SYSCON) += bootcount_syscon.o
|
||||||
|
|
102
drivers/bootcount/bootcount_dm_i2c.c
Normal file
102
drivers/bootcount/bootcount_dm_i2c.c
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2023
|
||||||
|
* Philip Richard Oberfichtner <pro@denx.de>
|
||||||
|
*
|
||||||
|
* Based on previous work from Heiko Schocher (legacy bootcount_i2c.c driver)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <bootcount.h>
|
||||||
|
#include <dm.h>
|
||||||
|
#include <i2c.h>
|
||||||
|
|
||||||
|
#define BC_MAGIC 0x55
|
||||||
|
|
||||||
|
struct bootcount_i2c_priv {
|
||||||
|
struct udevice *bcdev;
|
||||||
|
unsigned int offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int bootcount_i2c_set(struct udevice *dev, const u32 val)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct bootcount_i2c_priv *priv = dev_get_priv(dev);
|
||||||
|
|
||||||
|
ret = dm_i2c_reg_write(priv->bcdev, priv->offset, BC_MAGIC);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err_exit;
|
||||||
|
|
||||||
|
ret = dm_i2c_reg_write(priv->bcdev, priv->offset + 1, val & 0xff);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err_exit;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_exit:
|
||||||
|
log_debug("%s: Error writing to I2C device (%d)\n", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bootcount_i2c_get(struct udevice *dev, u32 *val)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct bootcount_i2c_priv *priv = dev_get_priv(dev);
|
||||||
|
|
||||||
|
ret = dm_i2c_reg_read(priv->bcdev, priv->offset);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err_exit;
|
||||||
|
|
||||||
|
if ((ret & 0xff) != BC_MAGIC) {
|
||||||
|
log_debug("%s: Invalid Magic, reset bootcounter.\n", __func__);
|
||||||
|
*val = 0;
|
||||||
|
return bootcount_i2c_set(dev, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = dm_i2c_reg_read(priv->bcdev, priv->offset + 1);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err_exit;
|
||||||
|
|
||||||
|
*val = ret;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_exit:
|
||||||
|
log_debug("%s: Error reading from I2C device (%d)\n", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bootcount_i2c_probe(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct bootcount_i2c_priv *priv = dev_get_priv(dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = dev_read_u32(dev, "offset", &priv->offset);
|
||||||
|
if (ret)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
ret = i2c_get_chip_by_phandle(dev, "i2cbcdev", &priv->bcdev);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (ret)
|
||||||
|
log_debug("%s failed, ret = %d\n", __func__, ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct bootcount_ops bootcount_i2c_ops = {
|
||||||
|
.get = bootcount_i2c_get,
|
||||||
|
.set = bootcount_i2c_set,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct udevice_id bootcount_i2c_ids[] = {
|
||||||
|
{ .compatible = "u-boot,bootcount-i2c" },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(bootcount_i2c) = {
|
||||||
|
.name = "bootcount-i2c",
|
||||||
|
.id = UCLASS_BOOTCOUNT,
|
||||||
|
.priv_auto = sizeof(struct bootcount_i2c_priv),
|
||||||
|
.probe = bootcount_i2c_probe,
|
||||||
|
.of_match = bootcount_i2c_ids,
|
||||||
|
.ops = &bootcount_i2c_ops,
|
||||||
|
};
|
|
@ -1,43 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0+
|
|
||||||
/*
|
|
||||||
* (C) Copyright 2013
|
|
||||||
* Heiko Schocher, DENX Software Engineering, hs@denx.de.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <bootcount.h>
|
|
||||||
#include <linux/compiler.h>
|
|
||||||
#include <i2c.h>
|
|
||||||
|
|
||||||
#define BC_MAGIC 0xbc
|
|
||||||
|
|
||||||
void bootcount_store(ulong a)
|
|
||||||
{
|
|
||||||
unsigned char buf[3];
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
buf[0] = BC_MAGIC;
|
|
||||||
buf[1] = (a & 0xff);
|
|
||||||
ret = i2c_write(CFG_SYS_I2C_RTC_ADDR, CONFIG_SYS_BOOTCOUNT_ADDR,
|
|
||||||
CONFIG_BOOTCOUNT_ALEN, buf, 2);
|
|
||||||
if (ret != 0)
|
|
||||||
puts("Error writing bootcount\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
ulong bootcount_load(void)
|
|
||||||
{
|
|
||||||
unsigned char buf[3];
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = i2c_read(CFG_SYS_I2C_RTC_ADDR, CONFIG_SYS_BOOTCOUNT_ADDR,
|
|
||||||
CONFIG_BOOTCOUNT_ALEN, buf, 2);
|
|
||||||
if (ret != 0) {
|
|
||||||
puts("Error loading bootcount\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (buf[0] == BC_MAGIC)
|
|
||||||
return buf[1];
|
|
||||||
|
|
||||||
bootcount_store(0);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -24,6 +24,17 @@
|
||||||
*/
|
*/
|
||||||
#define DW_I2C_COMP_TYPE 0x44570140
|
#define DW_I2C_COMP_TYPE 0x44570140
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This constant is used to calculate when during the clock high phase the data
|
||||||
|
* bit shall be read. The value was copied from the Linux v6.5 function
|
||||||
|
* i2c_dw_scl_hcnt() which provides the following explanation:
|
||||||
|
*
|
||||||
|
* "This is just an experimental rule: the tHD;STA period turned out to be
|
||||||
|
* proportinal to (_HCNT + 3). With this setting, we could meet both tHIGH and
|
||||||
|
* tHD;STA timing specs."
|
||||||
|
*/
|
||||||
|
#define T_HD_STA_OFFSET 3
|
||||||
|
|
||||||
static int dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
|
static int dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
|
||||||
{
|
{
|
||||||
u32 ena = enable ? IC_ENABLE_0B : 0;
|
u32 ena = enable ? IC_ENABLE_0B : 0;
|
||||||
|
@ -155,10 +166,10 @@ static int dw_i2c_calc_timing(struct dw_i2c *priv, enum i2c_speed_mode mode,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Back-solve for hcnt and lcnt according to the following equations:
|
* Back-solve for hcnt and lcnt according to the following equations:
|
||||||
* SCL_High_time = [(HCNT + IC_*_SPKLEN + 7) * ic_clk] + SCL_Fall_time
|
* SCL_High_time = [(HCNT + IC_*_SPKLEN + T_HD_STA_OFFSET) * ic_clk] + SCL_Fall_time
|
||||||
* SCL_Low_time = [(LCNT + 1) * ic_clk] - SCL_Fall_time + SCL_Rise_time
|
* SCL_Low_time = [(LCNT + 1) * ic_clk] - SCL_Fall_time + SCL_Rise_time
|
||||||
*/
|
*/
|
||||||
hcnt = min_thigh_cnt - fall_cnt - 7 - spk_cnt;
|
hcnt = min_thigh_cnt - fall_cnt - T_HD_STA_OFFSET - spk_cnt;
|
||||||
lcnt = min_tlow_cnt - rise_cnt + fall_cnt - 1;
|
lcnt = min_tlow_cnt - rise_cnt + fall_cnt - 1;
|
||||||
|
|
||||||
if (hcnt < 0 || lcnt < 0) {
|
if (hcnt < 0 || lcnt < 0) {
|
||||||
|
@ -170,13 +181,13 @@ static int dw_i2c_calc_timing(struct dw_i2c *priv, enum i2c_speed_mode mode,
|
||||||
* Now add things back up to ensure the period is hit. If it is off,
|
* Now add things back up to ensure the period is hit. If it is off,
|
||||||
* split the difference and bias to lcnt for remainder
|
* split the difference and bias to lcnt for remainder
|
||||||
*/
|
*/
|
||||||
tot = hcnt + lcnt + 7 + spk_cnt + rise_cnt + 1;
|
tot = hcnt + lcnt + T_HD_STA_OFFSET + spk_cnt + rise_cnt + 1;
|
||||||
|
|
||||||
if (tot < period_cnt) {
|
if (tot < period_cnt) {
|
||||||
diff = (period_cnt - tot) / 2;
|
diff = (period_cnt - tot) / 2;
|
||||||
hcnt += diff;
|
hcnt += diff;
|
||||||
lcnt += diff;
|
lcnt += diff;
|
||||||
tot = hcnt + lcnt + 7 + spk_cnt + rise_cnt + 1;
|
tot = hcnt + lcnt + T_HD_STA_OFFSET + spk_cnt + rise_cnt + 1;
|
||||||
lcnt += period_cnt - tot;
|
lcnt += period_cnt - tot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -388,6 +388,81 @@ int i2c_get_chip_for_busnum(int busnum, int chip_addr, uint offset_len,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find and probe I2C bus based on a chip attached to it */
|
||||||
|
static int i2c_get_parent_bus(ofnode chip, struct udevice **devp)
|
||||||
|
{
|
||||||
|
ofnode node;
|
||||||
|
struct udevice *dev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
node = ofnode_get_parent(chip);
|
||||||
|
if (!ofnode_valid(node))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
ret = uclass_get_device_by_ofnode(UCLASS_I2C, node, &dev);
|
||||||
|
if (ret) {
|
||||||
|
*devp = NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
*devp = dev;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i2c_get_chip_by_phandle(const struct udevice *parent, const char *prop_name,
|
||||||
|
struct udevice **devp)
|
||||||
|
{
|
||||||
|
ofnode node;
|
||||||
|
uint phandle;
|
||||||
|
struct udevice *bus, *chip;
|
||||||
|
char *dev_name;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
debug("%s: Searching I2C chip for phandle \"%s\"\n",
|
||||||
|
__func__, prop_name);
|
||||||
|
|
||||||
|
dev_name = strdup(prop_name);
|
||||||
|
if (!dev_name) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto err_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = dev_read_u32(parent, "i2cbcdev", &phandle);
|
||||||
|
if (ret)
|
||||||
|
goto err_exit;
|
||||||
|
|
||||||
|
node = ofnode_get_by_phandle(phandle);
|
||||||
|
if (!ofnode_valid(node)) {
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto err_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = i2c_get_parent_bus(node, &bus);
|
||||||
|
if (ret)
|
||||||
|
goto err_exit;
|
||||||
|
|
||||||
|
ret = device_bind_driver_to_node(bus, "i2c_generic_chip_drv",
|
||||||
|
dev_name, node, &chip);
|
||||||
|
if (ret)
|
||||||
|
goto err_exit;
|
||||||
|
|
||||||
|
ret = device_probe(chip);
|
||||||
|
if (ret) {
|
||||||
|
device_unbind(chip);
|
||||||
|
goto err_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug("%s succeeded\n", __func__);
|
||||||
|
*devp = chip;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_exit:
|
||||||
|
free(dev_name);
|
||||||
|
debug("%s failed, ret = %d\n", __func__, ret);
|
||||||
|
*devp = NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int dm_i2c_probe(struct udevice *bus, uint chip_addr, uint chip_flags,
|
int dm_i2c_probe(struct udevice *bus, uint chip_addr, uint chip_flags,
|
||||||
struct udevice **devp)
|
struct udevice **devp)
|
||||||
{
|
{
|
||||||
|
|
|
@ -517,11 +517,6 @@ static int npcm_i2c_init_clk(struct npcm_i2c_bus *bus, u32 bus_freq)
|
||||||
u32 sclfrq;
|
u32 sclfrq;
|
||||||
u8 hldt, val;
|
u8 hldt, val;
|
||||||
|
|
||||||
if (bus_freq > I2C_FREQ_100K) {
|
|
||||||
printf("Support standard mode only\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SCLFRQ = T(SCL)/4/T(CLK) = FREQ(CLK)/4/FREQ(SCL) */
|
/* SCLFRQ = T(SCL)/4/T(CLK) = FREQ(CLK)/4/FREQ(SCL) */
|
||||||
sclfrq = freq / (bus_freq * 4);
|
sclfrq = freq / (bus_freq * 4);
|
||||||
if (sclfrq < SCLFRQ_MIN || sclfrq > SCLFRQ_MAX)
|
if (sclfrq < SCLFRQ_MIN || sclfrq > SCLFRQ_MAX)
|
||||||
|
|
|
@ -537,6 +537,18 @@ int i2c_get_chip(struct udevice *bus, uint chip_addr, uint offset_len,
|
||||||
int i2c_get_chip_for_busnum(int busnum, int chip_addr, uint offset_len,
|
int i2c_get_chip_for_busnum(int busnum, int chip_addr, uint offset_len,
|
||||||
struct udevice **devp);
|
struct udevice **devp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* i2c_get_chip_by_phandle() - get a device to use to access a chip
|
||||||
|
* based on a phandle property pointing to it
|
||||||
|
*
|
||||||
|
* @parent: Parent device containing the phandle pointer
|
||||||
|
* @name: Name of phandle property in the parent device node
|
||||||
|
* @devp: Returns pointer to new device or NULL if not found
|
||||||
|
* Return: 0 on success, -ve on failure
|
||||||
|
*/
|
||||||
|
int i2c_get_chip_by_phandle(const struct udevice *parent, const char *prop_name,
|
||||||
|
struct udevice **devp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* i2c_chip_of_to_plat() - Decode standard I2C platform data
|
* i2c_chip_of_to_plat() - Decode standard I2C platform data
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Reference in a new issue