]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
i2c: samsung: Support platforms other than EXYNOS4 and EXYNOS5
authorDavid Virag <virag.david003@gmail.com>
Fri, 2 Aug 2024 19:19:16 +0000 (21:19 +0200)
committerHeiko Schocher <hs@denx.de>
Fri, 9 Aug 2024 12:46:05 +0000 (14:46 +0200)
Newer Samsung SoCs (including newer Exynos, ExynosAuto, Google Tensor)
still use these IPs, or slightly newer versions of it.

Make these drivers available on these platforms by guarding
EXYNOS4/EXYNOS5 specific code behind their configs, and using CCF for
clocks on other platforms.

Tested S3C I2C driver on Exynos7885.
This along with extended clock driver should enable S3C I2C on
Exynos850.

Signed-off-by: David Virag <virag.david003@gmail.com>
Tested-by: Henrik Grimler <henrik@grimler.se>
Reviewed-by: Heiko Schocher <hs@denx.de>
drivers/i2c/Kconfig
drivers/i2c/exynos_hs_i2c.c
drivers/i2c/s3c24x0_i2c.c
drivers/i2c/s3c24x0_i2c.h

index cba7f848942ffe2e21bc83e2295512d0c2072a91..52067fa7c1fff5db2b65af24fd10a260254be896 100644 (file)
@@ -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.
 
index 189ce6d5096af1b802cd6228493169c3f545b657..fa0d1c8f64ab593942a4ebe52f7b028366ce489c 100644 (file)
@@ -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,15 +141,26 @@ 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 IS_ENABLED(CONFIG_ARCH_EXYNOS4) || IS_ENABLED(CONFIG_ARCH_EXYNOS5)
        clkin = get_i2c_clk();
+#else
+       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
         * uTemp0 = (CLK_DIV + 1) * (TSCLK_L + TSCLK_H + 2)
@@ -487,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);
 
@@ -514,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;
 
@@ -522,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",
@@ -530,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;
 
index ae3a801cad186ddb73fffcae1ac143fa4dfbf7be..ade1ad6cef7d98f88d50107b8a681caf5eb7b178 100644 (file)
@@ -9,12 +9,15 @@
 #include <fdtdec.h>
 #include <time.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 <i2c.h>
+#include <clk.h>
 #include "s3c24x0_i2c.h"
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -46,10 +49,23 @@ 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 IS_ENABLED(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_ARCH_EXYNOS5)
        freq = get_i2c_clk();
+#else
+       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)
                /* set prescaler to 512 */
@@ -67,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
@@ -77,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;
 }
@@ -293,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;
 
@@ -301,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",
@@ -309,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;
 
index ec8f1acaef5416165a31c421ecbc33e4b0cfb744..12249d5c141b9ffadf618ef592b39a68ee647958 100644 (file)
@@ -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;
 };