All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sam Protsenko <semen.protsenko@linaro.org>
To: Jaewon Kim <jaewon02.kim@samsung.com>
Cc: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>,
	Wolfram Sang <wsa@kernel.org>,  Rob Herring <robh+dt@kernel.org>,
	linux-samsung-soc@vger.kernel.org,  linux-i2c@vger.kernel.org,
	devicetree@vger.kernel.org,  linux-kernel@vger.kernel.org,
	chanho61.park@samsung.com,  linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v3 2/2] i2c: exynos5: add support for ExynosAutov9 SoC
Date: Mon, 15 Nov 2021 20:55:12 +0200	[thread overview]
Message-ID: <CAPLW+4==X+irRBKHiDfgJeAb0oDKkzbcWERFs7Y3=PSOg0+qAw@mail.gmail.com> (raw)
In-Reply-To: <20211112010137.149174-3-jaewon02.kim@samsung.com>

On Fri, 12 Nov 2021 at 03:06, Jaewon Kim <jaewon02.kim@samsung.com> wrote:
>
> Serial IPs(UART, I2C, SPI) are integrated into New IP-Core
> called USI(Universal Serial Interface).
>
> As it is integrated into USI, there are additinal HW changes.
> Registers to control USI and sysreg to set serial IPs have been added.
> Also, some timing registres have been changed.
>
> Signed-off-by: Jaewon Kim <jaewon02.kim@samsung.com>
> ---

Reviewed-by: Sam Protsenko <semen.protsenko@linaro.org>
Tested-by: Sam Protsenko <semen.protsenko@linaro.org>

With this patch the Exynos850 HSI2C becomes functional. The only
nit-pick from my side (just a food for thought): do we want to
configure USI related config inside of particular drivers (SPI, I2C,
UART)? Or it would be better design to implement some platform driver
for that, so we can choose USI configuration (SPI/I2C/UART) in device
tree? I think this series is good to be merged as is, but we should
probably consider all upsides and downsides of each option, for the
future work.

Thanks!

>  drivers/i2c/busses/i2c-exynos5.c | 135 ++++++++++++++++++++++++++++---
>  1 file changed, 125 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c
> index 97d4f3ac0abd..6ce94795a618 100644
> --- a/drivers/i2c/busses/i2c-exynos5.c
> +++ b/drivers/i2c/busses/i2c-exynos5.c
> @@ -22,6 +22,8 @@
>  #include <linux/of_device.h>
>  #include <linux/of_irq.h>
>  #include <linux/spinlock.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
>
>  /*
>   * HSI2C controller from Samsung supports 2 modes of operation
> @@ -166,9 +168,21 @@
>
>  #define EXYNOS5_I2C_TIMEOUT (msecs_to_jiffies(100))
>
> +/* USI(Universal Serial Interface) Register map */
> +#define USI_CON                                        0xc4
> +#define USI_OPTION                             0xc8
> +
> +/* USI(Universal Serial Interface) Register bits */
> +#define USI_CON_RESET                          BIT(0)
> +
> +/* SYSREG Register bit */
> +#define SYSREG_USI_SW_CONF_MASK                        (0x7 << 0)
> +#define SYSREG_I2C_SW_CONF                     BIT(2)
> +
>  enum i2c_type_exynos {
>         I2C_TYPE_EXYNOS5,
>         I2C_TYPE_EXYNOS7,
> +       I2C_TYPE_EXYNOSAUTOV9,
>  };
>
>  struct exynos5_i2c {
> @@ -199,6 +213,10 @@ struct exynos5_i2c {
>
>         /* Version of HS-I2C Hardware */
>         const struct exynos_hsi2c_variant *variant;
> +
> +       /* USI sysreg info */
> +       struct regmap           *usi_sysreg;
> +       unsigned int            usi_offset;
>  };
>
>  /**
> @@ -213,21 +231,31 @@ struct exynos5_i2c {
>  struct exynos_hsi2c_variant {
>         unsigned int            fifo_depth;
>         enum i2c_type_exynos    hw;
> +       bool                    has_usi;
>  };
>
>  static const struct exynos_hsi2c_variant exynos5250_hsi2c_data = {
>         .fifo_depth     = 64,
>         .hw             = I2C_TYPE_EXYNOS5,
> +       .has_usi        = false,
>  };
>
>  static const struct exynos_hsi2c_variant exynos5260_hsi2c_data = {
>         .fifo_depth     = 16,
>         .hw             = I2C_TYPE_EXYNOS5,
> +       .has_usi        = false,
>  };
>
>  static const struct exynos_hsi2c_variant exynos7_hsi2c_data = {
>         .fifo_depth     = 16,
>         .hw             = I2C_TYPE_EXYNOS7,
> +       .has_usi        = false,
> +};
> +
> +static const struct exynos_hsi2c_variant exynosautov9_hsi2c_data = {
> +       .fifo_depth     = 64,
> +       .hw             = I2C_TYPE_EXYNOSAUTOV9,
> +       .has_usi        = true,
>  };
>
>  static const struct of_device_id exynos5_i2c_match[] = {
> @@ -243,6 +271,9 @@ static const struct of_device_id exynos5_i2c_match[] = {
>         }, {
>                 .compatible = "samsung,exynos7-hsi2c",
>                 .data = &exynos7_hsi2c_data
> +       }, {
> +               .compatible = "samsung,exynosautov9-hsi2c",
> +               .data = &exynosautov9_hsi2c_data
>         }, {},
>  };
>  MODULE_DEVICE_TABLE(of, exynos5_i2c_match);
> @@ -281,6 +312,32 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings)
>                 i2c->op_clock;
>         int div, clk_cycle, temp;
>
> +       /*
> +        * In case of HSI2C controllers in EXYNOSAUTOV9
> +        * timing control formula changed.
> +        *
> +        * FSCL = IPCLK / ((CLK_DIV + 1) * 16)
> +        * T_SCL_LOW = IPCLK * (CLK_DIV + 1) * (N + M)
> +        *  [N : number of 0's in the TSCL_H_HS]
> +        *  [M : number of 0's in the TSCL_L_HS]
> +        * T_SCL_HIGH = IPCLK * (CLK_DIV + 1) * (N + M)
> +        *  [N : number of 1's in the TSCL_H_HS]
> +        *  [M : number of 1's in the TSCL_L_HS]
> +        *
> +        *  result of (N + M) is always 8.
> +        *  In general use case, we don't need to control timing_s1, timing_s2.
> +        */
> +       if (i2c->variant->hw == I2C_TYPE_EXYNOSAUTOV9) {
> +               div = ((clkin / (16 * i2c->op_clock)) - 1);
> +               i2c_timing_s3 = div << 16;
> +               if (hs_timings)
> +                       writel(i2c_timing_s3, i2c->regs + HSI2C_TIMING_HS3);
> +               else
> +                       writel(i2c_timing_s3, i2c->regs + HSI2C_TIMING_FS3);
> +
> +               return 0;
> +       }
> +
>         /*
>          * In case of HSI2C controller in Exynos5 series
>          * FPCLK / FI2C =
> @@ -355,6 +412,20 @@ static int exynos5_hsi2c_clock_setup(struct exynos5_i2c *i2c)
>         return exynos5_i2c_set_timing(i2c, true);
>  }
>
> +static void exynos_usi_reset(struct exynos5_i2c *i2c)
> +{
> +       u32 val;
> +
> +       val = readl(i2c->regs + USI_CON);
> +       val |= USI_CON_RESET;
> +       writel(val, i2c->regs + USI_CON);
> +       udelay(1);
> +
> +       val = readl(i2c->regs + USI_CON);
> +       val &= ~USI_CON_RESET;
> +       writel(val, i2c->regs + USI_CON);
> +}
> +
>  /*
>   * exynos5_i2c_init: configures the controller for I2C functionality
>   * Programs I2C controller for Master mode operation
> @@ -385,6 +456,9 @@ static void exynos5_i2c_reset(struct exynos5_i2c *i2c)
>  {
>         u32 i2c_ctl;
>
> +       if (i2c->variant->hw == I2C_TYPE_EXYNOSAUTOV9)
> +               exynos_usi_reset(i2c);
> +
>         /* Set and clear the bit for reset */
>         i2c_ctl = readl(i2c->regs + HSI2C_CTL);
>         i2c_ctl |= HSI2C_SW_RST;
> @@ -422,7 +496,8 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)
>         writel(int_status, i2c->regs + HSI2C_INT_STATUS);
>
>         /* handle interrupt related to the transfer status */
> -       if (i2c->variant->hw == I2C_TYPE_EXYNOS7) {
> +       if (i2c->variant->hw == I2C_TYPE_EXYNOS7 ||
> +                       i2c->variant->hw == I2C_TYPE_EXYNOSAUTOV9) {
>                 if (int_status & HSI2C_INT_TRANS_DONE) {
>                         i2c->trans_done = 1;
>                         i2c->state = 0;
> @@ -569,13 +644,13 @@ static void exynos5_i2c_bus_check(struct exynos5_i2c *i2c)
>  {
>         unsigned long timeout;
>
> -       if (i2c->variant->hw != I2C_TYPE_EXYNOS7)
> +       if (i2c->variant->hw == I2C_TYPE_EXYNOS5)
>                 return;
>
>         /*
> -        * HSI2C_MASTER_ST_LOSE state in EXYNOS7 variant before transaction
> -        * indicates that bus is stuck (SDA is low). In such case bus recovery
> -        * can be performed.
> +        * HSI2C_MASTER_ST_LOSE state in EXYNOS7 or EXYNOSAUTOV9 variant before
> +        * transaction indicates that bus is stuck (SDA is low).
> +        * In such case bus recovery can be performed.
>          */
>         timeout = jiffies + msecs_to_jiffies(100);
>         for (;;) {
> @@ -611,10 +686,10 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
>         unsigned long flags;
>         unsigned short trig_lvl;
>
> -       if (i2c->variant->hw == I2C_TYPE_EXYNOS7)
> -               int_en |= HSI2C_INT_I2C_TRANS;
> -       else
> +       if (i2c->variant->hw == I2C_TYPE_EXYNOS5)
>                 int_en |= HSI2C_INT_I2C;
> +       else
> +               int_en |= HSI2C_INT_I2C_TRANS;
>
>         i2c_ctl = readl(i2c->regs + HSI2C_CTL);
>         i2c_ctl &= ~(HSI2C_TXCHON | HSI2C_RXCHON);
> @@ -738,6 +813,42 @@ static const struct i2c_algorithm exynos5_i2c_algorithm = {
>         .functionality          = exynos5_i2c_func,
>  };
>
> +static int exynos_usi_init(struct exynos5_i2c *i2c)
> +{
> +       struct device *dev = i2c->dev;
> +       int ret;
> +
> +       if (!i2c->variant->has_usi)
> +               return 0;
> +
> +       /*
> +        * System Register has a field that can select the serial IP
> +        * provided by USI. We need to set it to I2C to use I2C.
> +        */
> +       i2c->usi_sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
> +                                                         "samsung,sysreg");
> +       if (IS_ERR(i2c->usi_sysreg)) {
> +               dev_err(dev, "Cannot find sysreg\n");
> +               return PTR_ERR(i2c->usi_sysreg);
> +       }
> +
> +       ret = of_property_read_u32_index(dev->of_node, "samsung,sysreg",
> +                                        1, &i2c->usi_offset);
> +       if (ret) {
> +               dev_err(dev, "sysreg offset is not specified\n");
> +               return ret;
> +       }
> +
> +       ret = regmap_update_bits(i2c->usi_sysreg, i2c->usi_offset,
> +                       SYSREG_USI_SW_CONF_MASK, SYSREG_I2C_SW_CONF);
> +       if (ret < 0)
> +               return ret;
> +
> +       exynos_usi_reset(i2c);
> +
> +       return 0;
> +}
> +
>  static int exynos5_i2c_probe(struct platform_device *pdev)
>  {
>         struct device_node *np = pdev->dev.of_node;
> @@ -777,6 +888,12 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
>         i2c->adap.algo_data = i2c;
>         i2c->adap.dev.parent = &pdev->dev;
>
> +       i2c->variant = of_device_get_match_data(&pdev->dev);
> +
> +       ret = exynos_usi_init(i2c);
> +       if (ret)
> +               return ret;
> +
>         /* Clear pending interrupts from u-boot or misc causes */
>         exynos5_i2c_clr_pend_irq(i2c);
>
> @@ -794,8 +911,6 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
>                 goto err_clk;
>         }
>
> -       i2c->variant = of_device_get_match_data(&pdev->dev);
> -
>         ret = exynos5_hsi2c_clock_setup(i2c);
>         if (ret)
>                 goto err_clk;
> --
> 2.33.1
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

WARNING: multiple messages have this Message-ID (diff)
From: Sam Protsenko <semen.protsenko@linaro.org>
To: Jaewon Kim <jaewon02.kim@samsung.com>
Cc: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>,
	Wolfram Sang <wsa@kernel.org>, Rob Herring <robh+dt@kernel.org>,
	linux-samsung-soc@vger.kernel.org, linux-i2c@vger.kernel.org,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	chanho61.park@samsung.com, linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v3 2/2] i2c: exynos5: add support for ExynosAutov9 SoC
Date: Mon, 15 Nov 2021 20:55:12 +0200	[thread overview]
Message-ID: <CAPLW+4==X+irRBKHiDfgJeAb0oDKkzbcWERFs7Y3=PSOg0+qAw@mail.gmail.com> (raw)
In-Reply-To: <20211112010137.149174-3-jaewon02.kim@samsung.com>

On Fri, 12 Nov 2021 at 03:06, Jaewon Kim <jaewon02.kim@samsung.com> wrote:
>
> Serial IPs(UART, I2C, SPI) are integrated into New IP-Core
> called USI(Universal Serial Interface).
>
> As it is integrated into USI, there are additinal HW changes.
> Registers to control USI and sysreg to set serial IPs have been added.
> Also, some timing registres have been changed.
>
> Signed-off-by: Jaewon Kim <jaewon02.kim@samsung.com>
> ---

Reviewed-by: Sam Protsenko <semen.protsenko@linaro.org>
Tested-by: Sam Protsenko <semen.protsenko@linaro.org>

With this patch the Exynos850 HSI2C becomes functional. The only
nit-pick from my side (just a food for thought): do we want to
configure USI related config inside of particular drivers (SPI, I2C,
UART)? Or it would be better design to implement some platform driver
for that, so we can choose USI configuration (SPI/I2C/UART) in device
tree? I think this series is good to be merged as is, but we should
probably consider all upsides and downsides of each option, for the
future work.

Thanks!

>  drivers/i2c/busses/i2c-exynos5.c | 135 ++++++++++++++++++++++++++++---
>  1 file changed, 125 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c
> index 97d4f3ac0abd..6ce94795a618 100644
> --- a/drivers/i2c/busses/i2c-exynos5.c
> +++ b/drivers/i2c/busses/i2c-exynos5.c
> @@ -22,6 +22,8 @@
>  #include <linux/of_device.h>
>  #include <linux/of_irq.h>
>  #include <linux/spinlock.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
>
>  /*
>   * HSI2C controller from Samsung supports 2 modes of operation
> @@ -166,9 +168,21 @@
>
>  #define EXYNOS5_I2C_TIMEOUT (msecs_to_jiffies(100))
>
> +/* USI(Universal Serial Interface) Register map */
> +#define USI_CON                                        0xc4
> +#define USI_OPTION                             0xc8
> +
> +/* USI(Universal Serial Interface) Register bits */
> +#define USI_CON_RESET                          BIT(0)
> +
> +/* SYSREG Register bit */
> +#define SYSREG_USI_SW_CONF_MASK                        (0x7 << 0)
> +#define SYSREG_I2C_SW_CONF                     BIT(2)
> +
>  enum i2c_type_exynos {
>         I2C_TYPE_EXYNOS5,
>         I2C_TYPE_EXYNOS7,
> +       I2C_TYPE_EXYNOSAUTOV9,
>  };
>
>  struct exynos5_i2c {
> @@ -199,6 +213,10 @@ struct exynos5_i2c {
>
>         /* Version of HS-I2C Hardware */
>         const struct exynos_hsi2c_variant *variant;
> +
> +       /* USI sysreg info */
> +       struct regmap           *usi_sysreg;
> +       unsigned int            usi_offset;
>  };
>
>  /**
> @@ -213,21 +231,31 @@ struct exynos5_i2c {
>  struct exynos_hsi2c_variant {
>         unsigned int            fifo_depth;
>         enum i2c_type_exynos    hw;
> +       bool                    has_usi;
>  };
>
>  static const struct exynos_hsi2c_variant exynos5250_hsi2c_data = {
>         .fifo_depth     = 64,
>         .hw             = I2C_TYPE_EXYNOS5,
> +       .has_usi        = false,
>  };
>
>  static const struct exynos_hsi2c_variant exynos5260_hsi2c_data = {
>         .fifo_depth     = 16,
>         .hw             = I2C_TYPE_EXYNOS5,
> +       .has_usi        = false,
>  };
>
>  static const struct exynos_hsi2c_variant exynos7_hsi2c_data = {
>         .fifo_depth     = 16,
>         .hw             = I2C_TYPE_EXYNOS7,
> +       .has_usi        = false,
> +};
> +
> +static const struct exynos_hsi2c_variant exynosautov9_hsi2c_data = {
> +       .fifo_depth     = 64,
> +       .hw             = I2C_TYPE_EXYNOSAUTOV9,
> +       .has_usi        = true,
>  };
>
>  static const struct of_device_id exynos5_i2c_match[] = {
> @@ -243,6 +271,9 @@ static const struct of_device_id exynos5_i2c_match[] = {
>         }, {
>                 .compatible = "samsung,exynos7-hsi2c",
>                 .data = &exynos7_hsi2c_data
> +       }, {
> +               .compatible = "samsung,exynosautov9-hsi2c",
> +               .data = &exynosautov9_hsi2c_data
>         }, {},
>  };
>  MODULE_DEVICE_TABLE(of, exynos5_i2c_match);
> @@ -281,6 +312,32 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings)
>                 i2c->op_clock;
>         int div, clk_cycle, temp;
>
> +       /*
> +        * In case of HSI2C controllers in EXYNOSAUTOV9
> +        * timing control formula changed.
> +        *
> +        * FSCL = IPCLK / ((CLK_DIV + 1) * 16)
> +        * T_SCL_LOW = IPCLK * (CLK_DIV + 1) * (N + M)
> +        *  [N : number of 0's in the TSCL_H_HS]
> +        *  [M : number of 0's in the TSCL_L_HS]
> +        * T_SCL_HIGH = IPCLK * (CLK_DIV + 1) * (N + M)
> +        *  [N : number of 1's in the TSCL_H_HS]
> +        *  [M : number of 1's in the TSCL_L_HS]
> +        *
> +        *  result of (N + M) is always 8.
> +        *  In general use case, we don't need to control timing_s1, timing_s2.
> +        */
> +       if (i2c->variant->hw == I2C_TYPE_EXYNOSAUTOV9) {
> +               div = ((clkin / (16 * i2c->op_clock)) - 1);
> +               i2c_timing_s3 = div << 16;
> +               if (hs_timings)
> +                       writel(i2c_timing_s3, i2c->regs + HSI2C_TIMING_HS3);
> +               else
> +                       writel(i2c_timing_s3, i2c->regs + HSI2C_TIMING_FS3);
> +
> +               return 0;
> +       }
> +
>         /*
>          * In case of HSI2C controller in Exynos5 series
>          * FPCLK / FI2C =
> @@ -355,6 +412,20 @@ static int exynos5_hsi2c_clock_setup(struct exynos5_i2c *i2c)
>         return exynos5_i2c_set_timing(i2c, true);
>  }
>
> +static void exynos_usi_reset(struct exynos5_i2c *i2c)
> +{
> +       u32 val;
> +
> +       val = readl(i2c->regs + USI_CON);
> +       val |= USI_CON_RESET;
> +       writel(val, i2c->regs + USI_CON);
> +       udelay(1);
> +
> +       val = readl(i2c->regs + USI_CON);
> +       val &= ~USI_CON_RESET;
> +       writel(val, i2c->regs + USI_CON);
> +}
> +
>  /*
>   * exynos5_i2c_init: configures the controller for I2C functionality
>   * Programs I2C controller for Master mode operation
> @@ -385,6 +456,9 @@ static void exynos5_i2c_reset(struct exynos5_i2c *i2c)
>  {
>         u32 i2c_ctl;
>
> +       if (i2c->variant->hw == I2C_TYPE_EXYNOSAUTOV9)
> +               exynos_usi_reset(i2c);
> +
>         /* Set and clear the bit for reset */
>         i2c_ctl = readl(i2c->regs + HSI2C_CTL);
>         i2c_ctl |= HSI2C_SW_RST;
> @@ -422,7 +496,8 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)
>         writel(int_status, i2c->regs + HSI2C_INT_STATUS);
>
>         /* handle interrupt related to the transfer status */
> -       if (i2c->variant->hw == I2C_TYPE_EXYNOS7) {
> +       if (i2c->variant->hw == I2C_TYPE_EXYNOS7 ||
> +                       i2c->variant->hw == I2C_TYPE_EXYNOSAUTOV9) {
>                 if (int_status & HSI2C_INT_TRANS_DONE) {
>                         i2c->trans_done = 1;
>                         i2c->state = 0;
> @@ -569,13 +644,13 @@ static void exynos5_i2c_bus_check(struct exynos5_i2c *i2c)
>  {
>         unsigned long timeout;
>
> -       if (i2c->variant->hw != I2C_TYPE_EXYNOS7)
> +       if (i2c->variant->hw == I2C_TYPE_EXYNOS5)
>                 return;
>
>         /*
> -        * HSI2C_MASTER_ST_LOSE state in EXYNOS7 variant before transaction
> -        * indicates that bus is stuck (SDA is low). In such case bus recovery
> -        * can be performed.
> +        * HSI2C_MASTER_ST_LOSE state in EXYNOS7 or EXYNOSAUTOV9 variant before
> +        * transaction indicates that bus is stuck (SDA is low).
> +        * In such case bus recovery can be performed.
>          */
>         timeout = jiffies + msecs_to_jiffies(100);
>         for (;;) {
> @@ -611,10 +686,10 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
>         unsigned long flags;
>         unsigned short trig_lvl;
>
> -       if (i2c->variant->hw == I2C_TYPE_EXYNOS7)
> -               int_en |= HSI2C_INT_I2C_TRANS;
> -       else
> +       if (i2c->variant->hw == I2C_TYPE_EXYNOS5)
>                 int_en |= HSI2C_INT_I2C;
> +       else
> +               int_en |= HSI2C_INT_I2C_TRANS;
>
>         i2c_ctl = readl(i2c->regs + HSI2C_CTL);
>         i2c_ctl &= ~(HSI2C_TXCHON | HSI2C_RXCHON);
> @@ -738,6 +813,42 @@ static const struct i2c_algorithm exynos5_i2c_algorithm = {
>         .functionality          = exynos5_i2c_func,
>  };
>
> +static int exynos_usi_init(struct exynos5_i2c *i2c)
> +{
> +       struct device *dev = i2c->dev;
> +       int ret;
> +
> +       if (!i2c->variant->has_usi)
> +               return 0;
> +
> +       /*
> +        * System Register has a field that can select the serial IP
> +        * provided by USI. We need to set it to I2C to use I2C.
> +        */
> +       i2c->usi_sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
> +                                                         "samsung,sysreg");
> +       if (IS_ERR(i2c->usi_sysreg)) {
> +               dev_err(dev, "Cannot find sysreg\n");
> +               return PTR_ERR(i2c->usi_sysreg);
> +       }
> +
> +       ret = of_property_read_u32_index(dev->of_node, "samsung,sysreg",
> +                                        1, &i2c->usi_offset);
> +       if (ret) {
> +               dev_err(dev, "sysreg offset is not specified\n");
> +               return ret;
> +       }
> +
> +       ret = regmap_update_bits(i2c->usi_sysreg, i2c->usi_offset,
> +                       SYSREG_USI_SW_CONF_MASK, SYSREG_I2C_SW_CONF);
> +       if (ret < 0)
> +               return ret;
> +
> +       exynos_usi_reset(i2c);
> +
> +       return 0;
> +}
> +
>  static int exynos5_i2c_probe(struct platform_device *pdev)
>  {
>         struct device_node *np = pdev->dev.of_node;
> @@ -777,6 +888,12 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
>         i2c->adap.algo_data = i2c;
>         i2c->adap.dev.parent = &pdev->dev;
>
> +       i2c->variant = of_device_get_match_data(&pdev->dev);
> +
> +       ret = exynos_usi_init(i2c);
> +       if (ret)
> +               return ret;
> +
>         /* Clear pending interrupts from u-boot or misc causes */
>         exynos5_i2c_clr_pend_irq(i2c);
>
> @@ -794,8 +911,6 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
>                 goto err_clk;
>         }
>
> -       i2c->variant = of_device_get_match_data(&pdev->dev);
> -
>         ret = exynos5_hsi2c_clock_setup(i2c);
>         if (ret)
>                 goto err_clk;
> --
> 2.33.1
>

  parent reply	other threads:[~2021-11-15 18:56 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CGME20211112010603epcas2p331fe717eabfd9fc0280792921b25c535@epcas2p3.samsung.com>
2021-11-12  1:01 ` [PATCH v3 0/2] i2c: exynos5: add support for ExynosAutov9 SoC Jaewon Kim
2021-11-12  1:01   ` Jaewon Kim
     [not found]   ` <CGME20211112010603epcas2p26c076e65e0cb286cb53f06053165ef60@epcas2p2.samsung.com>
2021-11-12  1:01     ` [PATCH v3 1/2] dt-bindings: i2c: exynos5: add exynosautov9-hsi2c compatible Jaewon Kim
2021-11-12  1:01       ` Jaewon Kim
2021-11-15 18:56       ` Sam Protsenko
2021-11-15 18:56         ` Sam Protsenko
2021-11-19  8:57       ` Krzysztof Kozlowski
2021-11-19  8:57         ` Krzysztof Kozlowski
     [not found]   ` <CGME20211112010603epcas2p339d1a6ef3df7cdbe61c87c8afa541fd0@epcas2p3.samsung.com>
2021-11-12  1:01     ` [PATCH v3 2/2] i2c: exynos5: add support for ExynosAutov9 SoC Jaewon Kim
2021-11-12  1:01       ` Jaewon Kim
2021-11-12  8:09       ` Krzysztof Kozlowski
2021-11-12  8:09         ` Krzysztof Kozlowski
2021-11-15 18:55       ` Sam Protsenko [this message]
2021-11-15 18:55         ` Sam Protsenko
2021-11-16  1:12         ` Chanho Park
2021-11-16  1:12           ` Chanho Park
2021-11-16  9:31           ` Krzysztof Kozlowski
2021-11-16  9:31             ` Krzysztof Kozlowski
2021-11-16 15:31             ` Sam Protsenko
2021-11-16 15:31               ` Sam Protsenko
2021-11-19  8:51               ` Krzysztof Kozlowski
2021-11-19  8:51                 ` Krzysztof Kozlowski
2021-11-18 19:59             ` Sam Protsenko
2021-11-18 19:59               ` Sam Protsenko
2021-11-19  8:54               ` Krzysztof Kozlowski
2021-11-19  8:54                 ` Krzysztof Kozlowski
2021-11-19 14:12                 ` Sam Protsenko
2021-11-19 14:12                   ` Sam Protsenko
2021-11-22  2:51                   ` Jaewon Kim
2021-11-22  2:51                     ` Jaewon Kim
2021-11-17 22:17           ` David Virag
2021-11-17 22:17             ` David Virag

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAPLW+4==X+irRBKHiDfgJeAb0oDKkzbcWERFs7Y3=PSOg0+qAw@mail.gmail.com' \
    --to=semen.protsenko@linaro.org \
    --cc=chanho61.park@samsung.com \
    --cc=devicetree@vger.kernel.org \
    --cc=jaewon02.kim@samsung.com \
    --cc=krzysztof.kozlowski@canonical.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-i2c@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-samsung-soc@vger.kernel.org \
    --cc=robh+dt@kernel.org \
    --cc=wsa@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.