Merge tag 'v2024.10-rc3' into next
Prepare v2024.10-rc3
This commit is contained in:
@@ -650,7 +650,7 @@ config SYS_I2C_GENI
|
||||
|
||||
config SYS_I2C_S3C24X0
|
||||
bool "Samsung I2C driver"
|
||||
depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5) && DM_I2C
|
||||
depends on DM_I2C
|
||||
help
|
||||
Support for Samsung I2C controller as Samsung SoCs.
|
||||
|
||||
|
||||
@@ -9,11 +9,15 @@
|
||||
#include <dm.h>
|
||||
#include <i2c.h>
|
||||
#include <log.h>
|
||||
#if IS_ENABLED(CONFIG_ARCH_EXYNOS4) || IS_ENABLED(CONFIG_ARCH_EXYNOS5)
|
||||
#include <asm/arch/clk.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/pinmux.h>
|
||||
#endif
|
||||
#include <asm/global_data.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/delay.h>
|
||||
#include <clk.h>
|
||||
#include "s3c24x0_i2c.h"
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
@@ -137,18 +141,25 @@ static int hsi2c_wait_for_trx(struct exynos5_hsi2c *i2c)
|
||||
return I2C_NOK_TOUT;
|
||||
}
|
||||
|
||||
static int hsi2c_get_clk_details(struct s3c24x0_i2c_bus *i2c_bus)
|
||||
static int hsi2c_get_clk_details(struct udevice *dev)
|
||||
{
|
||||
struct s3c24x0_i2c_bus *i2c_bus = dev_get_priv(dev);
|
||||
struct exynos5_hsi2c *hsregs = i2c_bus->hsregs;
|
||||
ulong clkin;
|
||||
unsigned int op_clk = i2c_bus->clock_frequency;
|
||||
unsigned int i = 0, utemp0 = 0, utemp1 = 0;
|
||||
unsigned int t_ftl_cycle;
|
||||
|
||||
#if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_ARCH_EXYNOS5)
|
||||
#if IS_ENABLED(CONFIG_ARCH_EXYNOS4) || IS_ENABLED(CONFIG_ARCH_EXYNOS5)
|
||||
clkin = get_i2c_clk();
|
||||
#else
|
||||
clkin = get_PCLK();
|
||||
struct clk clk;
|
||||
int ret;
|
||||
|
||||
ret = clk_get_by_name(dev, "hsi2c", &clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
clkin = clk_get_rate(&clk);
|
||||
#endif
|
||||
/* FPCLK / FI2C =
|
||||
* (CLK_DIV + 1) * (TSCLK_L + TSCLK_H + 2) + 8 + 2 * FLT_CYCLE
|
||||
@@ -491,7 +502,7 @@ static int s3c24x0_i2c_set_bus_speed(struct udevice *dev, unsigned int speed)
|
||||
|
||||
i2c_bus->clock_frequency = speed;
|
||||
|
||||
if (hsi2c_get_clk_details(i2c_bus))
|
||||
if (hsi2c_get_clk_details(dev))
|
||||
return -EFAULT;
|
||||
hsi2c_ch_init(i2c_bus);
|
||||
|
||||
@@ -518,7 +529,9 @@ static int s3c24x0_i2c_probe(struct udevice *dev, uint chip, uint chip_flags)
|
||||
|
||||
static int s3c_i2c_of_to_plat(struct udevice *dev)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_ARCH_EXYNOS4) || IS_ENABLED(CONFIG_ARCH_EXYNOS5)
|
||||
const void *blob = gd->fdt_blob;
|
||||
#endif
|
||||
struct s3c24x0_i2c_bus *i2c_bus = dev_get_priv(dev);
|
||||
int node;
|
||||
|
||||
@@ -526,7 +539,9 @@ static int s3c_i2c_of_to_plat(struct udevice *dev)
|
||||
|
||||
i2c_bus->hsregs = dev_read_addr_ptr(dev);
|
||||
|
||||
#if IS_ENABLED(CONFIG_ARCH_EXYNOS4) || IS_ENABLED(CONFIG_ARCH_EXYNOS5)
|
||||
i2c_bus->id = pinmux_decode_periph_id(blob, node);
|
||||
#endif
|
||||
|
||||
i2c_bus->clock_frequency =
|
||||
dev_read_u32_default(dev, "clock-frequency",
|
||||
@@ -534,7 +549,9 @@ static int s3c_i2c_of_to_plat(struct udevice *dev)
|
||||
i2c_bus->node = node;
|
||||
i2c_bus->bus_num = dev_seq(dev);
|
||||
|
||||
#if IS_ENABLED(CONFIG_ARCH_EXYNOS4) || IS_ENABLED(CONFIG_ARCH_EXYNOS5)
|
||||
exynos_pinmux_config(i2c_bus->id, PINMUX_FLAG_HS_MODE);
|
||||
#endif
|
||||
|
||||
i2c_bus->active = true;
|
||||
|
||||
|
||||
@@ -19,7 +19,10 @@
|
||||
#define LPI2C_NACK_TOUT_MS 1
|
||||
#define LPI2C_TIMEOUT_MS 100
|
||||
|
||||
static int bus_i2c_init(struct udevice *bus, int speed);
|
||||
#define LPI2C_CHUNK_DATA 256U
|
||||
#define LPI2C_CHUNK_LEN_MIN 1U
|
||||
|
||||
static int bus_i2c_init(struct udevice *bus);
|
||||
|
||||
/* Weak linked function for overridden by some SoC power function */
|
||||
int __weak init_i2c_power(unsigned i2c_num)
|
||||
@@ -118,8 +121,10 @@ static int bus_i2c_send(struct udevice *bus, u8 *txbuf, int len)
|
||||
|
||||
static int bus_i2c_receive(struct udevice *bus, u8 *rxbuf, int len)
|
||||
{
|
||||
struct dm_i2c_bus *i2c = dev_get_uclass_priv(bus);
|
||||
struct imx_lpi2c_bus *i2c_bus = dev_get_priv(bus);
|
||||
struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)(i2c_bus->base);
|
||||
unsigned int chunk_len, rx_remain, timeout;
|
||||
lpi2c_status_t result = LPI2C_SUCESS;
|
||||
u32 val;
|
||||
ulong start_time = get_timer(0);
|
||||
@@ -128,33 +133,50 @@ static int bus_i2c_receive(struct udevice *bus, u8 *rxbuf, int len)
|
||||
if (!len)
|
||||
return result;
|
||||
|
||||
result = bus_i2c_wait_for_tx_ready(regs);
|
||||
if (result) {
|
||||
debug("i2c: receive wait fot tx ready: %d\n", result);
|
||||
return result;
|
||||
}
|
||||
/*
|
||||
* Extend the timeout for a bulk read if needed.
|
||||
* The calculated timeout is the result of multiplying the
|
||||
* transfer length with 8 bit + ACK + one clock of extra time,
|
||||
* considering the I2C bus frequency.
|
||||
*/
|
||||
timeout = max(len * 10 * 1000 / i2c->speed_hz, LPI2C_TIMEOUT_MS);
|
||||
|
||||
/* clear all status flags */
|
||||
writel(0x7f00, ®s->msr);
|
||||
/* send receive command */
|
||||
val = LPI2C_MTDR_CMD(0x1) | LPI2C_MTDR_DATA(len - 1);
|
||||
writel(val, ®s->mtdr);
|
||||
rx_remain = len;
|
||||
while (rx_remain > 0) {
|
||||
chunk_len = clamp(rx_remain, LPI2C_CHUNK_LEN_MIN, LPI2C_CHUNK_DATA) - 1;
|
||||
|
||||
while (len--) {
|
||||
do {
|
||||
result = imx_lpci2c_check_clear_error(regs);
|
||||
if (result) {
|
||||
debug("i2c: receive check clear error: %d\n",
|
||||
result);
|
||||
return result;
|
||||
}
|
||||
if (get_timer(start_time) > LPI2C_TIMEOUT_MS) {
|
||||
debug("i2c: receive mrdr: timeout\n");
|
||||
return -1;
|
||||
}
|
||||
val = readl(®s->mrdr);
|
||||
} while (val & LPI2C_MRDR_RXEMPTY_MASK);
|
||||
*rxbuf++ = LPI2C_MRDR_DATA(val);
|
||||
result = bus_i2c_wait_for_tx_ready(regs);
|
||||
if (result) {
|
||||
debug("i2c: receive wait for tx ready: %d\n", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* clear all status flags */
|
||||
writel(0x7f00, ®s->msr);
|
||||
/* send receive command */
|
||||
writel(LPI2C_MTDR_CMD(0x1) | LPI2C_MTDR_DATA(chunk_len), ®s->mtdr);
|
||||
rx_remain = rx_remain - (chunk_len & 0xff) - 1;
|
||||
|
||||
while (len--) {
|
||||
do {
|
||||
result = imx_lpci2c_check_clear_error(regs);
|
||||
if (result) {
|
||||
debug("i2c: receive check clear error: %d\n",
|
||||
result);
|
||||
return result;
|
||||
}
|
||||
if (get_timer(start_time) > timeout) {
|
||||
debug("i2c: receive mrdr: timeout\n");
|
||||
return -1;
|
||||
}
|
||||
val = readl(®s->mrdr);
|
||||
} while (val & LPI2C_MRDR_RXEMPTY_MASK);
|
||||
*rxbuf++ = LPI2C_MRDR_DATA(val);
|
||||
|
||||
/* send next receive command before controller NACKs last byte */
|
||||
if ((len - rx_remain) < 2 && rx_remain > 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -172,7 +194,7 @@ static int bus_i2c_start(struct udevice *bus, u8 addr, u8 dir)
|
||||
debug("i2c: start check busy bus: 0x%x\n", result);
|
||||
|
||||
/* Try to init the lpi2c then check the bus busy again */
|
||||
bus_i2c_init(bus, I2C_SPEED_STANDARD_RATE);
|
||||
bus_i2c_init(bus);
|
||||
result = imx_lpci2c_check_busy_bus(regs);
|
||||
if (result) {
|
||||
printf("i2c: Error check busy bus: 0x%x\n", result);
|
||||
@@ -344,11 +366,14 @@ static int bus_i2c_set_bus_speed(struct udevice *bus, int speed)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bus_i2c_init(struct udevice *bus, int speed)
|
||||
static int bus_i2c_init(struct udevice *bus)
|
||||
{
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
struct dm_i2c_bus *i2c = dev_get_uclass_priv(bus);
|
||||
int speed = i2c->speed_hz;
|
||||
|
||||
struct imx_lpi2c_bus *i2c_bus = dev_get_priv(bus);
|
||||
struct imx_lpi2c_reg *regs = (struct imx_lpi2c_reg *)(i2c_bus->base);
|
||||
/* reset peripheral */
|
||||
@@ -388,13 +413,13 @@ static int imx_lpi2c_probe_chip(struct udevice *bus, u32 chip,
|
||||
result = bus_i2c_start(bus, chip, 0);
|
||||
if (result) {
|
||||
bus_i2c_stop(bus);
|
||||
bus_i2c_init(bus, I2C_SPEED_STANDARD_RATE);
|
||||
bus_i2c_init(bus);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = bus_i2c_stop(bus);
|
||||
if (result)
|
||||
bus_i2c_init(bus, I2C_SPEED_STANDARD_RATE);
|
||||
bus_i2c_init(bus);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -489,7 +514,7 @@ static int imx_lpi2c_probe(struct udevice *bus)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = bus_i2c_init(bus, I2C_SPEED_STANDARD_RATE);
|
||||
ret = bus_i2c_init(bus);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ int i2c_arbitrator_select(struct udevice *mux, struct udevice *bus,
|
||||
/* Indicate that we want to claim the bus */
|
||||
ret = dm_gpio_set_value(&priv->ap_claim, 1);
|
||||
if (ret)
|
||||
goto err;
|
||||
return ret;
|
||||
udelay(priv->slew_delay_us);
|
||||
|
||||
/* Wait for the EC to release it */
|
||||
@@ -62,7 +62,7 @@ int i2c_arbitrator_select(struct udevice *mux, struct udevice *bus,
|
||||
while (get_timer(start_retry) < priv->wait_retry_ms) {
|
||||
ret = dm_gpio_get_value(&priv->ec_claim);
|
||||
if (ret < 0) {
|
||||
goto err;
|
||||
return ret;
|
||||
} else if (!ret) {
|
||||
/* We got it, so return */
|
||||
return 0;
|
||||
@@ -75,17 +75,14 @@ int i2c_arbitrator_select(struct udevice *mux, struct udevice *bus,
|
||||
/* It didn't release, so give up, wait, and try again */
|
||||
ret = dm_gpio_set_value(&priv->ap_claim, 0);
|
||||
if (ret)
|
||||
goto err;
|
||||
return ret;
|
||||
|
||||
mdelay(priv->wait_retry_ms);
|
||||
} while (get_timer(start) < priv->wait_free_ms);
|
||||
|
||||
/* Give up, release our claim */
|
||||
printf("I2C: Could not claim bus, timeout %lu\n", get_timer(start));
|
||||
ret = -ETIMEDOUT;
|
||||
ret = 0;
|
||||
err:
|
||||
return ret;
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int i2c_arbitrator_probe(struct udevice *dev)
|
||||
|
||||
@@ -10,12 +10,9 @@
|
||||
#include <i2c.h>
|
||||
#include <log.h>
|
||||
#include <malloc.h>
|
||||
#include <asm/global_data.h>
|
||||
|
||||
#include <asm-generic/gpio.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
enum pca_type {
|
||||
PCA9543,
|
||||
PCA9544,
|
||||
|
||||
@@ -8,17 +8,16 @@
|
||||
#include <dm.h>
|
||||
#include <fdtdec.h>
|
||||
#include <time.h>
|
||||
#if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_ARCH_EXYNOS5)
|
||||
#include <log.h>
|
||||
#if IS_ENABLED(CONFIG_ARCH_EXYNOS4) || IS_ENABLED(CONFIG_ARCH_EXYNOS5)
|
||||
#include <asm/arch/clk.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/pinmux.h>
|
||||
#else
|
||||
#include <asm/arch/s3c24x0_cpu.h>
|
||||
#endif
|
||||
#include <asm/global_data.h>
|
||||
#include <asm/io.h>
|
||||
#include <i2c.h>
|
||||
#include <clk.h>
|
||||
#include "s3c24x0_i2c.h"
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
@@ -50,13 +49,22 @@ static void read_write_byte(struct s3c24x0_i2c *i2c)
|
||||
clrbits_le32(&i2c->iiccon, I2CCON_IRPND);
|
||||
}
|
||||
|
||||
static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd)
|
||||
static int i2c_ch_init(struct udevice *dev, int speed, int slaveadd)
|
||||
{
|
||||
struct s3c24x0_i2c_bus *i2c_bus = dev_get_priv(dev);
|
||||
struct s3c24x0_i2c *i2c = i2c_bus->regs;
|
||||
ulong freq, pres = 16, div;
|
||||
#if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_ARCH_EXYNOS5)
|
||||
|
||||
#if IS_ENABLED(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_ARCH_EXYNOS5)
|
||||
freq = get_i2c_clk();
|
||||
#else
|
||||
freq = get_PCLK();
|
||||
struct clk clk;
|
||||
int ret;
|
||||
|
||||
ret = clk_get_by_name(dev, "i2c", &clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
freq = clk_get_rate(&clk);
|
||||
#endif
|
||||
/* calculate prescaler and divisor values */
|
||||
if ((freq / pres / (16 + 1)) > speed)
|
||||
@@ -75,6 +83,7 @@ static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd)
|
||||
writel(slaveadd, &i2c->iicadd);
|
||||
/* program Master Transmit (and implicit STOP) */
|
||||
writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define SYS_I2C_S3C24X0_SLAVE_ADDR 0
|
||||
@@ -85,8 +94,9 @@ static int s3c24x0_i2c_set_bus_speed(struct udevice *dev, unsigned int speed)
|
||||
|
||||
i2c_bus->clock_frequency = speed;
|
||||
|
||||
i2c_ch_init(i2c_bus->regs, i2c_bus->clock_frequency,
|
||||
SYS_I2C_S3C24X0_SLAVE_ADDR);
|
||||
if (i2c_ch_init(dev, i2c_bus->clock_frequency,
|
||||
SYS_I2C_S3C24X0_SLAVE_ADDR))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -301,7 +311,9 @@ static int s3c24x0_i2c_xfer(struct udevice *dev, struct i2c_msg *msg,
|
||||
|
||||
static int s3c_i2c_of_to_plat(struct udevice *dev)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_ARCH_EXYNOS4) || IS_ENABLED(CONFIG_ARCH_EXYNOS5)
|
||||
const void *blob = gd->fdt_blob;
|
||||
#endif
|
||||
struct s3c24x0_i2c_bus *i2c_bus = dev_get_priv(dev);
|
||||
int node;
|
||||
|
||||
@@ -309,7 +321,9 @@ static int s3c_i2c_of_to_plat(struct udevice *dev)
|
||||
|
||||
i2c_bus->regs = dev_read_addr_ptr(dev);
|
||||
|
||||
#if IS_ENABLED(CONFIG_ARCH_EXYNOS4) || IS_ENABLED(CONFIG_ARCH_EXYNOS5)
|
||||
i2c_bus->id = pinmux_decode_periph_id(blob, node);
|
||||
#endif
|
||||
|
||||
i2c_bus->clock_frequency =
|
||||
dev_read_u32_default(dev, "clock-frequency",
|
||||
@@ -317,7 +331,9 @@ static int s3c_i2c_of_to_plat(struct udevice *dev)
|
||||
i2c_bus->node = node;
|
||||
i2c_bus->bus_num = dev_seq(dev);
|
||||
|
||||
#if IS_ENABLED(CONFIG_ARCH_EXYNOS4) || IS_ENABLED(CONFIG_ARCH_EXYNOS5)
|
||||
exynos_pinmux_config(i2c_bus->id, 0);
|
||||
#endif
|
||||
|
||||
i2c_bus->active = true;
|
||||
|
||||
|
||||
@@ -54,7 +54,9 @@ struct s3c24x0_i2c_bus {
|
||||
struct exynos5_hsi2c *hsregs;
|
||||
int is_highspeed; /* High speed type, rather than I2C */
|
||||
unsigned clock_frequency;
|
||||
#if IS_ENABLED(CONFIG_ARCH_EXYNOS4) || IS_ENABLED(CONFIG_ARCH_EXYNOS5)
|
||||
int id;
|
||||
#endif
|
||||
unsigned clk_cycle;
|
||||
unsigned clk_div;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user