diff mbox series

[U-Boot,v3,011/108] i2c: Tidy up designware PCI support

Message ID 20191021033322.217715-12-sjg@chromium.org
State Superseded
Delegated to: Bin Meng
Headers show
Series x86: Add initial support for apollolake | expand

Commit Message

Simon Glass Oct. 21, 2019, 3:31 a.m. UTC
This is hacked into the driver at present. It seems better to have it as
a separate driver that uses the base driver. Create a new file and put
the X86 code into it.

Actually the Baytrail settings should really come from the device tree.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 drivers/i2c/Makefile         |   3 +
 drivers/i2c/designware_i2c.c | 104 ++++++-----------------------------
 drivers/i2c/designware_i2c.h |  35 ++++++++++++
 drivers/i2c/dw_i2c_pci.c     |  78 ++++++++++++++++++++++++++
 4 files changed, 132 insertions(+), 88 deletions(-)
 create mode 100644 drivers/i2c/dw_i2c_pci.c

Comments

Heiko Schocher Oct. 28, 2019, 4:40 a.m. UTC | #1
Hello Simon,

Am 21.10.2019 um 05:31 schrieb Simon Glass:
> This is hacked into the driver at present. It seems better to have it as
> a separate driver that uses the base driver. Create a new file and put
> the X86 code into it.
> 
> Actually the Baytrail settings should really come from the device tree.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
> Changes in v3: None
> Changes in v2: None
> 
>   drivers/i2c/Makefile         |   3 +
>   drivers/i2c/designware_i2c.c | 104 ++++++-----------------------------
>   drivers/i2c/designware_i2c.h |  35 ++++++++++++
>   drivers/i2c/dw_i2c_pci.c     |  78 ++++++++++++++++++++++++++
>   4 files changed, 132 insertions(+), 88 deletions(-)
>   create mode 100644 drivers/i2c/dw_i2c_pci.c

Reviewed-by: Heiko Schocher <hs@denx.de>

Thanks!

bye,
Heiko
Bin Meng Oct. 28, 2019, 5:54 a.m. UTC | #2
+Stefan

Hi Simon,

On Mon, Oct 21, 2019 at 11:33 AM Simon Glass <sjg@chromium.org> wrote:
>
> This is hacked into the driver at present. It seems better to have it as
> a separate driver that uses the base driver. Create a new file and put
> the X86 code into it.
>
> Actually the Baytrail settings should really come from the device tree.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  drivers/i2c/Makefile         |   3 +
>  drivers/i2c/designware_i2c.c | 104 ++++++-----------------------------
>  drivers/i2c/designware_i2c.h |  35 ++++++++++++
>  drivers/i2c/dw_i2c_pci.c     |  78 ++++++++++++++++++++++++++
>  4 files changed, 132 insertions(+), 88 deletions(-)
>  create mode 100644 drivers/i2c/dw_i2c_pci.c
>
> diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
> index c2f75d87559..a7fa38b8dcf 100644
> --- a/drivers/i2c/Makefile
> +++ b/drivers/i2c/Makefile
> @@ -14,6 +14,9 @@ obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o
>  obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
>  obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
>  obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o
> +ifdef CONFIG_DM_PCI
> +obj-$(CONFIG_SYS_I2C_DW) += dw_i2c_pci.o

nits: designware_i2c_pci.o for consistency?

> +endif
>  obj-$(CONFIG_SYS_I2C_FSL) += fsl_i2c.o
>  obj-$(CONFIG_SYS_I2C_IHS) += ihs_i2c.o
>  obj-$(CONFIG_SYS_I2C_INTEL) += intel_i2c.o
> diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
> index 6daa90e7442..54e4a70c74c 100644
> --- a/drivers/i2c/designware_i2c.c
> +++ b/drivers/i2c/designware_i2c.c
> @@ -13,34 +13,6 @@
>  #include <asm/io.h>
>  #include "designware_i2c.h"
>
> -struct dw_scl_sda_cfg {
> -       u32 ss_hcnt;
> -       u32 fs_hcnt;
> -       u32 ss_lcnt;
> -       u32 fs_lcnt;
> -       u32 sda_hold;
> -};
> -
> -#ifdef CONFIG_X86
> -/* BayTrail HCNT/LCNT/SDA hold time */
> -static struct dw_scl_sda_cfg byt_config = {
> -       .ss_hcnt = 0x200,
> -       .fs_hcnt = 0x55,
> -       .ss_lcnt = 0x200,
> -       .fs_lcnt = 0x99,
> -       .sda_hold = 0x6,
> -};
> -#endif
> -
> -struct dw_i2c {
> -       struct i2c_regs *regs;
> -       struct dw_scl_sda_cfg *scl_sda_cfg;
> -       struct reset_ctl_bulk resets;
> -#if CONFIG_IS_ENABLED(CLK)
> -       struct clk clk;
> -#endif
> -};
> -
>  #ifdef CONFIG_SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
>  static int  dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
>  {
> @@ -90,7 +62,8 @@ static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
>         unsigned int ena;
>         int i2c_spd;
>
> -       if (speed >= I2C_MAX_SPEED)
> +       if (speed >= I2C_MAX_SPEED &&
> +           (!scl_sda_cfg || scl_sda_cfg->has_max_speed))

I think the logic should be && not ||

And I don't see scl_sda_cfg->has_max_speed in the original driver. Is
this new functionality?

>                 i2c_spd = IC_SPEED_MODE_MAX;
>         else if (speed >= I2C_FAST_SPEED)
>                 i2c_spd = IC_SPEED_MODE_FAST;
> @@ -106,7 +79,6 @@ static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
>         cntl = (readl(&i2c_base->ic_con) & (~IC_CON_SPD_MSK));
>
>         switch (i2c_spd) {
> -#ifndef CONFIG_X86 /* No High-speed for BayTrail yet */
>         case IC_SPEED_MODE_MAX:
>                 cntl |= IC_CON_SPD_SS;
>                 if (scl_sda_cfg) {
> @@ -119,7 +91,6 @@ static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
>                 writel(hcnt, &i2c_base->ic_hs_scl_hcnt);
>                 writel(lcnt, &i2c_base->ic_hs_scl_lcnt);
>                 break;
> -#endif
>
>         case IC_SPEED_MODE_STANDARD:
>                 cntl |= IC_CON_SPD_SS;
> @@ -565,24 +536,20 @@ static int designware_i2c_probe_chip(struct udevice *bus, uint chip_addr,
>         return ret;
>  }
>
> -static int designware_i2c_probe(struct udevice *bus)
> +static int designware_i2c_ofdata_to_platdata(struct udevice *bus)
>  {
>         struct dw_i2c *priv = dev_get_priv(bus);
> -       int ret;
>
> -       if (device_is_on_pci_bus(bus)) {
> -#ifdef CONFIG_DM_PCI
> -               /* Save base address from PCI BAR */
> -               priv->regs = (struct i2c_regs *)
> -                       dm_pci_map_bar(bus, PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
> -#ifdef CONFIG_X86
> -               /* Use BayTrail specific timing values */
> -               priv->scl_sda_cfg = &byt_config;
> -#endif
> -#endif
> -       } else {
> -               priv->regs = (struct i2c_regs *)devfdt_get_addr_ptr(bus);
> -       }
> +       printf("bad\n");

What's this?

> +       priv->regs = (struct i2c_regs *)devfdt_get_addr_ptr(bus);
> +
> +       return 0;
> +}
> +
> +int designware_i2c_probe(struct udevice *bus)
> +{
> +       struct dw_i2c *priv = dev_get_priv(bus);
> +       int ret;
>
>         ret = reset_get_bulk(bus, &priv->resets);
>         if (ret)
> @@ -606,7 +573,7 @@ static int designware_i2c_probe(struct udevice *bus)
>         return __dw_i2c_init(priv->regs, 0, 0);
>  }
>
> -static int designware_i2c_remove(struct udevice *dev)
> +int designware_i2c_remove(struct udevice *dev)
>  {
>         struct dw_i2c *priv = dev_get_priv(dev);
>
> @@ -618,30 +585,7 @@ static int designware_i2c_remove(struct udevice *dev)
>         return reset_release_bulk(&priv->resets);
>  }
>
> -static int designware_i2c_bind(struct udevice *dev)
> -{
> -       static int num_cards;
> -       char name[20];
> -
> -       /* Create a unique device name for PCI type devices */
> -       if (device_is_on_pci_bus(dev)) {
> -               /*
> -                * ToDo:
> -                * Setting req_seq in the driver is probably not recommended.
> -                * But without a DT alias the number is not configured. And
> -                * using this driver is impossible for PCIe I2C devices.
> -                * This can be removed, once a better (correct) way for this
> -                * is found and implemented.
> -                */
> -               dev->req_seq = num_cards;
> -               sprintf(name, "i2c_designware#%u", num_cards++);
> -               device_set_name(dev, name);
> -       }
> -
> -       return 0;
> -}
> -
> -static const struct dm_i2c_ops designware_i2c_ops = {
> +const struct dm_i2c_ops designware_i2c_ops = {
>         .xfer           = designware_i2c_xfer,
>         .probe_chip     = designware_i2c_probe_chip,
>         .set_bus_speed  = designware_i2c_set_bus_speed,
> @@ -656,7 +600,7 @@ U_BOOT_DRIVER(i2c_designware) = {
>         .name   = "i2c_designware",
>         .id     = UCLASS_I2C,
>         .of_match = designware_i2c_ids,
> -       .bind   = designware_i2c_bind,
> +       .ofdata_to_platdata = designware_i2c_ofdata_to_platdata,
>         .probe  = designware_i2c_probe,
>         .priv_auto_alloc_size = sizeof(struct dw_i2c),
>         .remove = designware_i2c_remove,
> @@ -664,20 +608,4 @@ U_BOOT_DRIVER(i2c_designware) = {
>         .ops    = &designware_i2c_ops,
>  };
>
> -#ifdef CONFIG_X86
> -static struct pci_device_id designware_pci_supported[] = {
> -       /* Intel BayTrail has 7 I2C controller located on the PCI bus */
> -       { PCI_VDEVICE(INTEL, 0x0f41) },
> -       { PCI_VDEVICE(INTEL, 0x0f42) },
> -       { PCI_VDEVICE(INTEL, 0x0f43) },
> -       { PCI_VDEVICE(INTEL, 0x0f44) },
> -       { PCI_VDEVICE(INTEL, 0x0f45) },
> -       { PCI_VDEVICE(INTEL, 0x0f46) },
> -       { PCI_VDEVICE(INTEL, 0x0f47) },
> -       {},
> -};
> -
> -U_BOOT_PCI_DEVICE(i2c_designware, designware_pci_supported);
> -#endif
> -
>  #endif /* CONFIG_DM_I2C */
> diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h
> index 20ff20d9b83..48766d08067 100644
> --- a/drivers/i2c/designware_i2c.h
> +++ b/drivers/i2c/designware_i2c.h
> @@ -7,6 +7,8 @@
>  #ifndef __DW_I2C_H_
>  #define __DW_I2C_H_
>
> +#include <reset.h>
> +
>  struct i2c_regs {
>         u32 ic_con;             /* 0x00 */
>         u32 ic_tar;             /* 0x04 */
> @@ -131,4 +133,37 @@ struct i2c_regs {
>  #define I2C_FAST_SPEED         400000
>  #define I2C_STANDARD_SPEED     100000
>
> +/**
> + * struct dw_scl_sda_cfg - I2C timing configuration
> + *
> + * @has_max_speed: Support maximum speed (1Mbps)
> + * @ss_hcnt: Standard speed high time in ns
> + * @fs_hcnt: Fast speed high time in ns
> + * @ss_lcnt: Standard speed low time in ns
> + * @fs_lcnt: Fast speed low time in ns
> + * @sda_hold: SDA hold time
> + */
> +struct dw_scl_sda_cfg {
> +       bool has_max_speed;
> +       u32 ss_hcnt;
> +       u32 fs_hcnt;
> +       u32 ss_lcnt;
> +       u32 fs_lcnt;
> +       u32 sda_hold;
> +};
> +
> +struct dw_i2c {
> +       struct i2c_regs *regs;
> +       struct dw_scl_sda_cfg *scl_sda_cfg;
> +       struct reset_ctl_bulk resets;
> +#if CONFIG_IS_ENABLED(CLK)
> +       struct clk clk;
> +#endif
> +};
> +
> +extern const struct dm_i2c_ops designware_i2c_ops;
> +
> +int designware_i2c_probe(struct udevice *bus);
> +int designware_i2c_remove(struct udevice *dev);
> +
>  #endif /* __DW_I2C_H_ */
> diff --git a/drivers/i2c/dw_i2c_pci.c b/drivers/i2c/dw_i2c_pci.c
> new file mode 100644
> index 00000000000..065c0aa5994
> --- /dev/null
> +++ b/drivers/i2c/dw_i2c_pci.c
> @@ -0,0 +1,78 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2009
> + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
> + * Copyright 2019 Google Inc
> + */
> +
> +#include <dm.h>
> +#include "designware_i2c.h"
> +
> +/* BayTrail HCNT/LCNT/SDA hold time */
> +static struct dw_scl_sda_cfg byt_config = {
> +       .ss_hcnt = 0x200,
> +       .fs_hcnt = 0x55,
> +       .ss_lcnt = 0x200,
> +       .fs_lcnt = 0x99,
> +       .sda_hold = 0x6,
> +};
> +
> +static int designware_i2c_pci_probe(struct udevice *dev)
> +{
> +       struct dw_i2c *priv = dev_get_priv(dev);
> +
> +       /* Save base address from PCI BAR */
> +       priv->regs = (struct i2c_regs *)
> +               dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
> +       if (IS_ENABLED(CONFIG_INTEL_BAYTRAIL))
> +               /* Use BayTrail specific timing values */
> +               priv->scl_sda_cfg = &byt_config;
> +
> +       return designware_i2c_probe(dev);
> +}
> +
> +static int designware_i2c_pci_bind(struct udevice *dev)
> +{
> +       static int num_cards;
> +       char name[20];
> +
> +       /*
> +        * Create a unique device name for PCI type devices
> +        * ToDo:
> +        * Setting req_seq in the driver is probably not recommended.
> +        * But without a DT alias the number is not configured. And
> +        * using this driver is impossible for PCIe I2C devices.
> +        * This can be removed, once a better (correct) way for this
> +        * is found and implemented.
> +        */
> +       dev->req_seq = num_cards;
> +       sprintf(name, "i2c_designware#%u", num_cards++);
> +       device_set_name(dev, name);
> +
> +       return 0;
> +}
> +
> +U_BOOT_DRIVER(i2c_designware_pci) = {
> +       .name   = "i2c_designware_pci",
> +       .id     = UCLASS_I2C,
> +       .bind   = designware_i2c_pci_bind,
> +       .probe  = designware_i2c_pci_probe,
> +       .priv_auto_alloc_size = sizeof(struct dw_i2c),
> +       .remove = designware_i2c_remove,
> +       .flags = DM_FLAG_OS_PREPARE,
> +       .ops    = &designware_i2c_ops,
> +};
> +
> +static struct pci_device_id designware_pci_supported[] = {
> +       /* Intel BayTrail has 7 I2C controller located on the PCI bus */
> +       { PCI_VDEVICE(INTEL, 0x0f41) },
> +       { PCI_VDEVICE(INTEL, 0x0f42) },
> +       { PCI_VDEVICE(INTEL, 0x0f43) },
> +       { PCI_VDEVICE(INTEL, 0x0f44) },
> +       { PCI_VDEVICE(INTEL, 0x0f45) },
> +       { PCI_VDEVICE(INTEL, 0x0f46) },
> +       { PCI_VDEVICE(INTEL, 0x0f47) },
> +       {},
> +};
> +
> +U_BOOT_PCI_DEVICE(i2c_designware_pci, designware_pci_supported);
> --

Regards,
Bin
Stefan Roese Oct. 28, 2019, 10:43 a.m. UTC | #3
On 21.10.19 05:31, Simon Glass wrote:
> This is hacked into the driver at present. It seems better to have it as
> a separate driver that uses the base driver. Create a new file and put
> the X86 code into it.
> 
> Actually the Baytrail settings should really come from the device tree.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>

Apart from the comments from Bin, I only have one nitpicking comments
below...

> ---
> 
> Changes in v3: None
> Changes in v2: None
> 
>   drivers/i2c/Makefile         |   3 +
>   drivers/i2c/designware_i2c.c | 104 ++++++-----------------------------
>   drivers/i2c/designware_i2c.h |  35 ++++++++++++
>   drivers/i2c/dw_i2c_pci.c     |  78 ++++++++++++++++++++++++++
>   4 files changed, 132 insertions(+), 88 deletions(-)
>   create mode 100644 drivers/i2c/dw_i2c_pci.c
> 
> diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
> index c2f75d87559..a7fa38b8dcf 100644
> --- a/drivers/i2c/Makefile
> +++ b/drivers/i2c/Makefile
> @@ -14,6 +14,9 @@ obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o
>   obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
>   obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
>   obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o
> +ifdef CONFIG_DM_PCI
> +obj-$(CONFIG_SYS_I2C_DW) += dw_i2c_pci.o
> +endif
>   obj-$(CONFIG_SYS_I2C_FSL) += fsl_i2c.o
>   obj-$(CONFIG_SYS_I2C_IHS) += ihs_i2c.o
>   obj-$(CONFIG_SYS_I2C_INTEL) += intel_i2c.o
> diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
> index 6daa90e7442..54e4a70c74c 100644
> --- a/drivers/i2c/designware_i2c.c
> +++ b/drivers/i2c/designware_i2c.c
> @@ -13,34 +13,6 @@
>   #include <asm/io.h>
>   #include "designware_i2c.h"
>   
> -struct dw_scl_sda_cfg {
> -	u32 ss_hcnt;
> -	u32 fs_hcnt;
> -	u32 ss_lcnt;
> -	u32 fs_lcnt;
> -	u32 sda_hold;
> -};
> -
> -#ifdef CONFIG_X86
> -/* BayTrail HCNT/LCNT/SDA hold time */
> -static struct dw_scl_sda_cfg byt_config = {
> -	.ss_hcnt = 0x200,
> -	.fs_hcnt = 0x55,
> -	.ss_lcnt = 0x200,
> -	.fs_lcnt = 0x99,
> -	.sda_hold = 0x6,
> -};
> -#endif
> -
> -struct dw_i2c {
> -	struct i2c_regs *regs;
> -	struct dw_scl_sda_cfg *scl_sda_cfg;
> -	struct reset_ctl_bulk resets;
> -#if CONFIG_IS_ENABLED(CLK)
> -	struct clk clk;
> -#endif
> -};
> -
>   #ifdef CONFIG_SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
>   static int  dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
>   {
> @@ -90,7 +62,8 @@ static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
>   	unsigned int ena;
>   	int i2c_spd;
>   
> -	if (speed >= I2C_MAX_SPEED)
> +	if (speed >= I2C_MAX_SPEED &&
> +	    (!scl_sda_cfg || scl_sda_cfg->has_max_speed))
>   		i2c_spd = IC_SPEED_MODE_MAX;
>   	else if (speed >= I2C_FAST_SPEED)
>   		i2c_spd = IC_SPEED_MODE_FAST;
> @@ -106,7 +79,6 @@ static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
>   	cntl = (readl(&i2c_base->ic_con) & (~IC_CON_SPD_MSK));
>   
>   	switch (i2c_spd) {
> -#ifndef CONFIG_X86 /* No High-speed for BayTrail yet */
>   	case IC_SPEED_MODE_MAX:
>   		cntl |= IC_CON_SPD_SS;
>   		if (scl_sda_cfg) {
> @@ -119,7 +91,6 @@ static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
>   		writel(hcnt, &i2c_base->ic_hs_scl_hcnt);
>   		writel(lcnt, &i2c_base->ic_hs_scl_lcnt);
>   		break;
> -#endif
>   
>   	case IC_SPEED_MODE_STANDARD:
>   		cntl |= IC_CON_SPD_SS;
> @@ -565,24 +536,20 @@ static int designware_i2c_probe_chip(struct udevice *bus, uint chip_addr,
>   	return ret;
>   }
>   
> -static int designware_i2c_probe(struct udevice *bus)
> +static int designware_i2c_ofdata_to_platdata(struct udevice *bus)
>   {
>   	struct dw_i2c *priv = dev_get_priv(bus);
> -	int ret;
>   
> -	if (device_is_on_pci_bus(bus)) {
> -#ifdef CONFIG_DM_PCI
> -		/* Save base address from PCI BAR */
> -		priv->regs = (struct i2c_regs *)
> -			dm_pci_map_bar(bus, PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
> -#ifdef CONFIG_X86
> -		/* Use BayTrail specific timing values */
> -		priv->scl_sda_cfg = &byt_config;
> -#endif
> -#endif
> -	} else {
> -		priv->regs = (struct i2c_regs *)devfdt_get_addr_ptr(bus);
> -	}
> +	printf("bad\n");
> +	priv->regs = (struct i2c_regs *)devfdt_get_addr_ptr(bus);
> +
> +	return 0;
> +}
> +
> +int designware_i2c_probe(struct udevice *bus)
> +{
> +	struct dw_i2c *priv = dev_get_priv(bus);
> +	int ret;
>   
>   	ret = reset_get_bulk(bus, &priv->resets);
>   	if (ret)
> @@ -606,7 +573,7 @@ static int designware_i2c_probe(struct udevice *bus)
>   	return __dw_i2c_init(priv->regs, 0, 0);
>   }
>   
> -static int designware_i2c_remove(struct udevice *dev)
> +int designware_i2c_remove(struct udevice *dev)
>   {
>   	struct dw_i2c *priv = dev_get_priv(dev);
>   
> @@ -618,30 +585,7 @@ static int designware_i2c_remove(struct udevice *dev)
>   	return reset_release_bulk(&priv->resets);
>   }
>   
> -static int designware_i2c_bind(struct udevice *dev)
> -{
> -	static int num_cards;
> -	char name[20];
> -
> -	/* Create a unique device name for PCI type devices */
> -	if (device_is_on_pci_bus(dev)) {
> -		/*
> -		 * ToDo:
> -		 * Setting req_seq in the driver is probably not recommended.
> -		 * But without a DT alias the number is not configured. And
> -		 * using this driver is impossible for PCIe I2C devices.
> -		 * This can be removed, once a better (correct) way for this
> -		 * is found and implemented.
> -		 */
> -		dev->req_seq = num_cards;
> -		sprintf(name, "i2c_designware#%u", num_cards++);
> -		device_set_name(dev, name);
> -	}
> -
> -	return 0;
> -}
> -
> -static const struct dm_i2c_ops designware_i2c_ops = {
> +const struct dm_i2c_ops designware_i2c_ops = {
>   	.xfer		= designware_i2c_xfer,
>   	.probe_chip	= designware_i2c_probe_chip,
>   	.set_bus_speed	= designware_i2c_set_bus_speed,
> @@ -656,7 +600,7 @@ U_BOOT_DRIVER(i2c_designware) = {
>   	.name	= "i2c_designware",
>   	.id	= UCLASS_I2C,
>   	.of_match = designware_i2c_ids,
> -	.bind	= designware_i2c_bind,
> +	.ofdata_to_platdata = designware_i2c_ofdata_to_platdata,
>   	.probe	= designware_i2c_probe,
>   	.priv_auto_alloc_size = sizeof(struct dw_i2c),
>   	.remove = designware_i2c_remove,
> @@ -664,20 +608,4 @@ U_BOOT_DRIVER(i2c_designware) = {
>   	.ops	= &designware_i2c_ops,
>   };
>   
> -#ifdef CONFIG_X86
> -static struct pci_device_id designware_pci_supported[] = {
> -	/* Intel BayTrail has 7 I2C controller located on the PCI bus */
> -	{ PCI_VDEVICE(INTEL, 0x0f41) },
> -	{ PCI_VDEVICE(INTEL, 0x0f42) },
> -	{ PCI_VDEVICE(INTEL, 0x0f43) },
> -	{ PCI_VDEVICE(INTEL, 0x0f44) },
> -	{ PCI_VDEVICE(INTEL, 0x0f45) },
> -	{ PCI_VDEVICE(INTEL, 0x0f46) },
> -	{ PCI_VDEVICE(INTEL, 0x0f47) },
> -	{},
> -};
> -
> -U_BOOT_PCI_DEVICE(i2c_designware, designware_pci_supported);
> -#endif
> -
>   #endif /* CONFIG_DM_I2C */
> diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h
> index 20ff20d9b83..48766d08067 100644
> --- a/drivers/i2c/designware_i2c.h
> +++ b/drivers/i2c/designware_i2c.h
> @@ -7,6 +7,8 @@
>   #ifndef __DW_I2C_H_
>   #define __DW_I2C_H_
>   
> +#include <reset.h>
> +
>   struct i2c_regs {
>   	u32 ic_con;		/* 0x00 */
>   	u32 ic_tar;		/* 0x04 */
> @@ -131,4 +133,37 @@ struct i2c_regs {
>   #define I2C_FAST_SPEED		400000
>   #define I2C_STANDARD_SPEED	100000
>   
> +/**
> + * struct dw_scl_sda_cfg - I2C timing configuration
> + *
> + * @has_max_speed: Support maximum speed (1Mbps)
> + * @ss_hcnt: Standard speed high time in ns
> + * @fs_hcnt: Fast speed high time in ns
> + * @ss_lcnt: Standard speed low time in ns
> + * @fs_lcnt: Fast speed low time in ns
> + * @sda_hold: SDA hold time
> + */
> +struct dw_scl_sda_cfg {
> +	bool has_max_speed;
> +	u32 ss_hcnt;
> +	u32 fs_hcnt;
> +	u32 ss_lcnt;
> +	u32 fs_lcnt;
> +	u32 sda_hold;
> +};
> +
> +struct dw_i2c {
> +	struct i2c_regs *regs;
> +	struct dw_scl_sda_cfg *scl_sda_cfg;
> +	struct reset_ctl_bulk resets;
> +#if CONFIG_IS_ENABLED(CLK)
> +	struct clk clk;
> +#endif
> +};
> +
> +extern const struct dm_i2c_ops designware_i2c_ops;
> +
> +int designware_i2c_probe(struct udevice *bus);
> +int designware_i2c_remove(struct udevice *dev);
> +
>   #endif /* __DW_I2C_H_ */
> diff --git a/drivers/i2c/dw_i2c_pci.c b/drivers/i2c/dw_i2c_pci.c
> new file mode 100644
> index 00000000000..065c0aa5994
> --- /dev/null
> +++ b/drivers/i2c/dw_i2c_pci.c
> @@ -0,0 +1,78 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2009
> + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
> + * Copyright 2019 Google Inc
> + */
> +
> +#include <dm.h>
> +#include "designware_i2c.h"
> +
> +/* BayTrail HCNT/LCNT/SDA hold time */
> +static struct dw_scl_sda_cfg byt_config = {
> +	.ss_hcnt = 0x200,
> +	.fs_hcnt = 0x55,
> +	.ss_lcnt = 0x200,
> +	.fs_lcnt = 0x99,
> +	.sda_hold = 0x6,
> +};
> +
> +static int designware_i2c_pci_probe(struct udevice *dev)
> +{
> +	struct dw_i2c *priv = dev_get_priv(dev);
> +
> +	/* Save base address from PCI BAR */
> +	priv->regs = (struct i2c_regs *)
> +		dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
> +	if (IS_ENABLED(CONFIG_INTEL_BAYTRAIL))
> +		/* Use BayTrail specific timing values */
> +		priv->scl_sda_cfg = &byt_config;
> +
> +	return designware_i2c_probe(dev);
> +}
> +
> +static int designware_i2c_pci_bind(struct udevice *dev)
> +{
> +	static int num_cards;
> +	char name[20];
> +
> +	/*
> +	 * Create a unique device name for PCI type devices
> +	 * ToDo:
> +	 * Setting req_seq in the driver is probably not recommended.
> +	 * But without a DT alias the number is not configured. And
> +	 * using this driver is impossible for PCIe I2C devices.
> +	 * This can be removed, once a better (correct) way for this
> +	 * is found and implemented.
> +	 */
> +	dev->req_seq = num_cards;
> +	sprintf(name, "i2c_designware#%u", num_cards++);
> +	device_set_name(dev, name);
> +
> +	return 0;
> +}
> +
> +U_BOOT_DRIVER(i2c_designware_pci) = {
> +	.name	= "i2c_designware_pci",
> +	.id	= UCLASS_I2C,
> +	.bind	= designware_i2c_pci_bind,
> +	.probe	= designware_i2c_pci_probe,
> +	.priv_auto_alloc_size = sizeof(struct dw_i2c),
> +	.remove = designware_i2c_remove,
> +	.flags = DM_FLAG_OS_PREPARE,

Indentation seems wrong in the line above.

Thanks,
Stefan
diff mbox series

Patch

diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index c2f75d87559..a7fa38b8dcf 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -14,6 +14,9 @@  obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o
 obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
 obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
 obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o
+ifdef CONFIG_DM_PCI
+obj-$(CONFIG_SYS_I2C_DW) += dw_i2c_pci.o
+endif
 obj-$(CONFIG_SYS_I2C_FSL) += fsl_i2c.o
 obj-$(CONFIG_SYS_I2C_IHS) += ihs_i2c.o
 obj-$(CONFIG_SYS_I2C_INTEL) += intel_i2c.o
diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index 6daa90e7442..54e4a70c74c 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -13,34 +13,6 @@ 
 #include <asm/io.h>
 #include "designware_i2c.h"
 
-struct dw_scl_sda_cfg {
-	u32 ss_hcnt;
-	u32 fs_hcnt;
-	u32 ss_lcnt;
-	u32 fs_lcnt;
-	u32 sda_hold;
-};
-
-#ifdef CONFIG_X86
-/* BayTrail HCNT/LCNT/SDA hold time */
-static struct dw_scl_sda_cfg byt_config = {
-	.ss_hcnt = 0x200,
-	.fs_hcnt = 0x55,
-	.ss_lcnt = 0x200,
-	.fs_lcnt = 0x99,
-	.sda_hold = 0x6,
-};
-#endif
-
-struct dw_i2c {
-	struct i2c_regs *regs;
-	struct dw_scl_sda_cfg *scl_sda_cfg;
-	struct reset_ctl_bulk resets;
-#if CONFIG_IS_ENABLED(CLK)
-	struct clk clk;
-#endif
-};
-
 #ifdef CONFIG_SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
 static int  dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
 {
@@ -90,7 +62,8 @@  static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
 	unsigned int ena;
 	int i2c_spd;
 
-	if (speed >= I2C_MAX_SPEED)
+	if (speed >= I2C_MAX_SPEED &&
+	    (!scl_sda_cfg || scl_sda_cfg->has_max_speed))
 		i2c_spd = IC_SPEED_MODE_MAX;
 	else if (speed >= I2C_FAST_SPEED)
 		i2c_spd = IC_SPEED_MODE_FAST;
@@ -106,7 +79,6 @@  static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
 	cntl = (readl(&i2c_base->ic_con) & (~IC_CON_SPD_MSK));
 
 	switch (i2c_spd) {
-#ifndef CONFIG_X86 /* No High-speed for BayTrail yet */
 	case IC_SPEED_MODE_MAX:
 		cntl |= IC_CON_SPD_SS;
 		if (scl_sda_cfg) {
@@ -119,7 +91,6 @@  static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
 		writel(hcnt, &i2c_base->ic_hs_scl_hcnt);
 		writel(lcnt, &i2c_base->ic_hs_scl_lcnt);
 		break;
-#endif
 
 	case IC_SPEED_MODE_STANDARD:
 		cntl |= IC_CON_SPD_SS;
@@ -565,24 +536,20 @@  static int designware_i2c_probe_chip(struct udevice *bus, uint chip_addr,
 	return ret;
 }
 
-static int designware_i2c_probe(struct udevice *bus)
+static int designware_i2c_ofdata_to_platdata(struct udevice *bus)
 {
 	struct dw_i2c *priv = dev_get_priv(bus);
-	int ret;
 
-	if (device_is_on_pci_bus(bus)) {
-#ifdef CONFIG_DM_PCI
-		/* Save base address from PCI BAR */
-		priv->regs = (struct i2c_regs *)
-			dm_pci_map_bar(bus, PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
-#ifdef CONFIG_X86
-		/* Use BayTrail specific timing values */
-		priv->scl_sda_cfg = &byt_config;
-#endif
-#endif
-	} else {
-		priv->regs = (struct i2c_regs *)devfdt_get_addr_ptr(bus);
-	}
+	printf("bad\n");
+	priv->regs = (struct i2c_regs *)devfdt_get_addr_ptr(bus);
+
+	return 0;
+}
+
+int designware_i2c_probe(struct udevice *bus)
+{
+	struct dw_i2c *priv = dev_get_priv(bus);
+	int ret;
 
 	ret = reset_get_bulk(bus, &priv->resets);
 	if (ret)
@@ -606,7 +573,7 @@  static int designware_i2c_probe(struct udevice *bus)
 	return __dw_i2c_init(priv->regs, 0, 0);
 }
 
-static int designware_i2c_remove(struct udevice *dev)
+int designware_i2c_remove(struct udevice *dev)
 {
 	struct dw_i2c *priv = dev_get_priv(dev);
 
@@ -618,30 +585,7 @@  static int designware_i2c_remove(struct udevice *dev)
 	return reset_release_bulk(&priv->resets);
 }
 
-static int designware_i2c_bind(struct udevice *dev)
-{
-	static int num_cards;
-	char name[20];
-
-	/* Create a unique device name for PCI type devices */
-	if (device_is_on_pci_bus(dev)) {
-		/*
-		 * ToDo:
-		 * Setting req_seq in the driver is probably not recommended.
-		 * But without a DT alias the number is not configured. And
-		 * using this driver is impossible for PCIe I2C devices.
-		 * This can be removed, once a better (correct) way for this
-		 * is found and implemented.
-		 */
-		dev->req_seq = num_cards;
-		sprintf(name, "i2c_designware#%u", num_cards++);
-		device_set_name(dev, name);
-	}
-
-	return 0;
-}
-
-static const struct dm_i2c_ops designware_i2c_ops = {
+const struct dm_i2c_ops designware_i2c_ops = {
 	.xfer		= designware_i2c_xfer,
 	.probe_chip	= designware_i2c_probe_chip,
 	.set_bus_speed	= designware_i2c_set_bus_speed,
@@ -656,7 +600,7 @@  U_BOOT_DRIVER(i2c_designware) = {
 	.name	= "i2c_designware",
 	.id	= UCLASS_I2C,
 	.of_match = designware_i2c_ids,
-	.bind	= designware_i2c_bind,
+	.ofdata_to_platdata = designware_i2c_ofdata_to_platdata,
 	.probe	= designware_i2c_probe,
 	.priv_auto_alloc_size = sizeof(struct dw_i2c),
 	.remove = designware_i2c_remove,
@@ -664,20 +608,4 @@  U_BOOT_DRIVER(i2c_designware) = {
 	.ops	= &designware_i2c_ops,
 };
 
-#ifdef CONFIG_X86
-static struct pci_device_id designware_pci_supported[] = {
-	/* Intel BayTrail has 7 I2C controller located on the PCI bus */
-	{ PCI_VDEVICE(INTEL, 0x0f41) },
-	{ PCI_VDEVICE(INTEL, 0x0f42) },
-	{ PCI_VDEVICE(INTEL, 0x0f43) },
-	{ PCI_VDEVICE(INTEL, 0x0f44) },
-	{ PCI_VDEVICE(INTEL, 0x0f45) },
-	{ PCI_VDEVICE(INTEL, 0x0f46) },
-	{ PCI_VDEVICE(INTEL, 0x0f47) },
-	{},
-};
-
-U_BOOT_PCI_DEVICE(i2c_designware, designware_pci_supported);
-#endif
-
 #endif /* CONFIG_DM_I2C */
diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h
index 20ff20d9b83..48766d08067 100644
--- a/drivers/i2c/designware_i2c.h
+++ b/drivers/i2c/designware_i2c.h
@@ -7,6 +7,8 @@ 
 #ifndef __DW_I2C_H_
 #define __DW_I2C_H_
 
+#include <reset.h>
+
 struct i2c_regs {
 	u32 ic_con;		/* 0x00 */
 	u32 ic_tar;		/* 0x04 */
@@ -131,4 +133,37 @@  struct i2c_regs {
 #define I2C_FAST_SPEED		400000
 #define I2C_STANDARD_SPEED	100000
 
+/**
+ * struct dw_scl_sda_cfg - I2C timing configuration
+ *
+ * @has_max_speed: Support maximum speed (1Mbps)
+ * @ss_hcnt: Standard speed high time in ns
+ * @fs_hcnt: Fast speed high time in ns
+ * @ss_lcnt: Standard speed low time in ns
+ * @fs_lcnt: Fast speed low time in ns
+ * @sda_hold: SDA hold time
+ */
+struct dw_scl_sda_cfg {
+	bool has_max_speed;
+	u32 ss_hcnt;
+	u32 fs_hcnt;
+	u32 ss_lcnt;
+	u32 fs_lcnt;
+	u32 sda_hold;
+};
+
+struct dw_i2c {
+	struct i2c_regs *regs;
+	struct dw_scl_sda_cfg *scl_sda_cfg;
+	struct reset_ctl_bulk resets;
+#if CONFIG_IS_ENABLED(CLK)
+	struct clk clk;
+#endif
+};
+
+extern const struct dm_i2c_ops designware_i2c_ops;
+
+int designware_i2c_probe(struct udevice *bus);
+int designware_i2c_remove(struct udevice *dev);
+
 #endif /* __DW_I2C_H_ */
diff --git a/drivers/i2c/dw_i2c_pci.c b/drivers/i2c/dw_i2c_pci.c
new file mode 100644
index 00000000000..065c0aa5994
--- /dev/null
+++ b/drivers/i2c/dw_i2c_pci.c
@@ -0,0 +1,78 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2009
+ * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
+ * Copyright 2019 Google Inc
+ */
+
+#include <dm.h>
+#include "designware_i2c.h"
+
+/* BayTrail HCNT/LCNT/SDA hold time */
+static struct dw_scl_sda_cfg byt_config = {
+	.ss_hcnt = 0x200,
+	.fs_hcnt = 0x55,
+	.ss_lcnt = 0x200,
+	.fs_lcnt = 0x99,
+	.sda_hold = 0x6,
+};
+
+static int designware_i2c_pci_probe(struct udevice *dev)
+{
+	struct dw_i2c *priv = dev_get_priv(dev);
+
+	/* Save base address from PCI BAR */
+	priv->regs = (struct i2c_regs *)
+		dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
+	if (IS_ENABLED(CONFIG_INTEL_BAYTRAIL))
+		/* Use BayTrail specific timing values */
+		priv->scl_sda_cfg = &byt_config;
+
+	return designware_i2c_probe(dev);
+}
+
+static int designware_i2c_pci_bind(struct udevice *dev)
+{
+	static int num_cards;
+	char name[20];
+
+	/*
+	 * Create a unique device name for PCI type devices
+	 * ToDo:
+	 * Setting req_seq in the driver is probably not recommended.
+	 * But without a DT alias the number is not configured. And
+	 * using this driver is impossible for PCIe I2C devices.
+	 * This can be removed, once a better (correct) way for this
+	 * is found and implemented.
+	 */
+	dev->req_seq = num_cards;
+	sprintf(name, "i2c_designware#%u", num_cards++);
+	device_set_name(dev, name);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(i2c_designware_pci) = {
+	.name	= "i2c_designware_pci",
+	.id	= UCLASS_I2C,
+	.bind	= designware_i2c_pci_bind,
+	.probe	= designware_i2c_pci_probe,
+	.priv_auto_alloc_size = sizeof(struct dw_i2c),
+	.remove = designware_i2c_remove,
+	.flags = DM_FLAG_OS_PREPARE,
+	.ops	= &designware_i2c_ops,
+};
+
+static struct pci_device_id designware_pci_supported[] = {
+	/* Intel BayTrail has 7 I2C controller located on the PCI bus */
+	{ PCI_VDEVICE(INTEL, 0x0f41) },
+	{ PCI_VDEVICE(INTEL, 0x0f42) },
+	{ PCI_VDEVICE(INTEL, 0x0f43) },
+	{ PCI_VDEVICE(INTEL, 0x0f44) },
+	{ PCI_VDEVICE(INTEL, 0x0f45) },
+	{ PCI_VDEVICE(INTEL, 0x0f46) },
+	{ PCI_VDEVICE(INTEL, 0x0f47) },
+	{},
+};
+
+U_BOOT_PCI_DEVICE(i2c_designware_pci, designware_pci_supported);