All of lore.kernel.org
 help / color / mirror / Atom feed
From: Heiko Schocher <hs@denx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 6/6 v4] i2c: designware_i2c: Add support for PCI(e) based I2C cores (x86)
Date: Thu, 21 Apr 2016 09:31:47 +0200	[thread overview]
Message-ID: <571881E3.2060805@denx.de> (raw)
In-Reply-To: <1461219582-16788-6-git-send-email-sr@denx.de>

Hello Simon,

Am 21.04.2016 um 08:19 schrieb Stefan Roese:
> This patch adds support for the PCI(e) based I2C cores. Which can be
> found for example on the Intel Bay Trail SoC. It has 7 I2C controllers
> implemented as PCI devices.
>
> This patch also adds the fixed values for the timing registers for
> BayTrail which are taken from the Linux designware I2C driver.
>
> Signed-off-by: Stefan Roese <sr@denx.de>
> Cc: Simon Glass <sjg@chromium.org>
> Cc: Bin Meng <bmeng.cn@gmail.com>
> Cc: Marek Vasut <marex@denx.de>
> Cc: Heiko Schocher <hs@denx.de>
> ---
> v4:
> - Used new function dev_get_addr_ptr() in probe function
>    to avoid cast.
>    For this to work, this patch need to be applied:
>    http://patchwork.ozlabs.org/patch/612948/

Is it Ok for you, if I apply this patch through the i2c tree?
Or do you want to pick up this patchserie?

bye,
Heiko
> - Rebased on latest mainline
>
>   drivers/i2c/designware_i2c.c | 118 ++++++++++++++++++++++++++++++++++++++-----
>   1 file changed, 106 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
> index d653eff..0c7cd0b 100644
> --- a/drivers/i2c/designware_i2c.c
> +++ b/drivers/i2c/designware_i2c.c
> @@ -8,11 +8,32 @@
>   #include <common.h>
>   #include <dm.h>
>   #include <i2c.h>
> +#include <pci.h>
>   #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;
>   };
>
>   static void dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
> @@ -43,6 +64,7 @@ static void dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
>    * Set the i2c speed.
>    */
>   static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
> +					   struct dw_scl_sda_cfg *scl_sda_cfg,
>   					   unsigned int speed)
>   {
>   	unsigned int cntl;
> @@ -62,34 +84,55 @@ 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_HS;
> -		hcnt = (IC_CLK * MIN_HS_SCL_HIGHTIME) / NANO_TO_MICRO;
> +		cntl |= IC_CON_SPD_SS;
> +		if (scl_sda_cfg) {
> +			hcnt = scl_sda_cfg->fs_hcnt;
> +			lcnt = scl_sda_cfg->fs_lcnt;
> +		} else {
> +			hcnt = (IC_CLK * MIN_HS_SCL_HIGHTIME) / NANO_TO_MICRO;
> +			lcnt = (IC_CLK * MIN_HS_SCL_LOWTIME) / NANO_TO_MICRO;
> +		}
>   		writel(hcnt, &i2c_base->ic_hs_scl_hcnt);
> -		lcnt = (IC_CLK * MIN_HS_SCL_LOWTIME) / NANO_TO_MICRO;
>   		writel(lcnt, &i2c_base->ic_hs_scl_lcnt);
>   		break;
> +#endif
>
>   	case IC_SPEED_MODE_STANDARD:
>   		cntl |= IC_CON_SPD_SS;
> -		hcnt = (IC_CLK * MIN_SS_SCL_HIGHTIME) / NANO_TO_MICRO;
> +		if (scl_sda_cfg) {
> +			hcnt = scl_sda_cfg->ss_hcnt;
> +			lcnt = scl_sda_cfg->ss_lcnt;
> +		} else {
> +			hcnt = (IC_CLK * MIN_SS_SCL_HIGHTIME) / NANO_TO_MICRO;
> +			lcnt = (IC_CLK * MIN_SS_SCL_LOWTIME) / NANO_TO_MICRO;
> +		}
>   		writel(hcnt, &i2c_base->ic_ss_scl_hcnt);
> -		lcnt = (IC_CLK * MIN_SS_SCL_LOWTIME) / NANO_TO_MICRO;
>   		writel(lcnt, &i2c_base->ic_ss_scl_lcnt);
>   		break;
>
>   	case IC_SPEED_MODE_FAST:
>   	default:
>   		cntl |= IC_CON_SPD_FS;
> -		hcnt = (IC_CLK * MIN_FS_SCL_HIGHTIME) / NANO_TO_MICRO;
> +		if (scl_sda_cfg) {
> +			hcnt = scl_sda_cfg->fs_hcnt;
> +			lcnt = scl_sda_cfg->fs_lcnt;
> +		} else {
> +			hcnt = (IC_CLK * MIN_FS_SCL_HIGHTIME) / NANO_TO_MICRO;
> +			lcnt = (IC_CLK * MIN_FS_SCL_LOWTIME) / NANO_TO_MICRO;
> +		}
>   		writel(hcnt, &i2c_base->ic_fs_scl_hcnt);
> -		lcnt = (IC_CLK * MIN_FS_SCL_LOWTIME) / NANO_TO_MICRO;
>   		writel(lcnt, &i2c_base->ic_fs_scl_lcnt);
>   		break;
>   	}
>
>   	writel(cntl, &i2c_base->ic_con);
>
> +	/* Configure SDA Hold Time if required */
> +	if (scl_sda_cfg)
> +		writel(scl_sda_cfg->sda_hold, &i2c_base->ic_sda_hold);
> +
>   	/* Enable back i2c now speed set */
>   	dw_i2c_enable(i2c_base, true);
>
> @@ -316,7 +359,7 @@ static void __dw_i2c_init(struct i2c_regs *i2c_base, int speed, int slaveaddr)
>   	writel(IC_TX_TL, &i2c_base->ic_tx_tl);
>   	writel(IC_STOP_DET, &i2c_base->ic_intr_mask);
>   #ifndef CONFIG_DM_I2C
> -	__dw_i2c_set_bus_speed(i2c_base, speed);
> +	__dw_i2c_set_bus_speed(i2c_base, NULL, speed);
>   	writel(slaveaddr, &i2c_base->ic_sar);
>   #endif
>
> @@ -357,7 +400,7 @@ static unsigned int dw_i2c_set_bus_speed(struct i2c_adapter *adap,
>   					 unsigned int speed)
>   {
>   	adap->speed = speed;
> -	return __dw_i2c_set_bus_speed(i2c_get_base(adap), speed);
> +	return __dw_i2c_set_bus_speed(i2c_get_base(adap), NULL, speed);
>   }
>
>   static void dw_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
> @@ -448,7 +491,7 @@ static int designware_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
>   {
>   	struct dw_i2c *i2c = dev_get_priv(bus);
>
> -	return __dw_i2c_set_bus_speed(i2c->regs, speed);
> +	return __dw_i2c_set_bus_speed(i2c->regs, i2c->scl_sda_cfg, speed);
>   }
>
>   static int designware_i2c_probe_chip(struct udevice *bus, uint chip_addr,
> @@ -471,14 +514,48 @@ static int designware_i2c_probe(struct udevice *bus)
>   {
>   	struct dw_i2c *priv = dev_get_priv(bus);
>
> -	/* Save base address from device-tree */
> -	priv->regs = (struct i2c_regs *)dev_get_addr(bus);
> +	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 *)dev_get_addr_ptr(bus);
> +	}
>
>   	__dw_i2c_init(priv->regs, 0, 0);
>
>   	return 0;
>   }
>
> +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 = {
>   	.xfer		= designware_i2c_xfer,
>   	.probe_chip	= designware_i2c_probe_chip,
> @@ -494,9 +571,26 @@ U_BOOT_DRIVER(i2c_designware) = {
>   	.name	= "i2c_designware",
>   	.id	= UCLASS_I2C,
>   	.of_match = designware_i2c_ids,
> +	.bind	= designware_i2c_bind,
>   	.probe	= designware_i2c_probe,
>   	.priv_auto_alloc_size = sizeof(struct dw_i2c),
>   	.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 */
>

-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

  reply	other threads:[~2016-04-21  7:31 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-21  6:19 [U-Boot] [PATCH 1/6 v4] i2c: designware_i2c: Add ic_enable_status to ic_regs struct Stefan Roese
2016-04-21  6:19 ` [U-Boot] [PATCH 2/6 v4] i2c: designware_i2c: Add dw_i2c_enable() helper function Stefan Roese
2016-04-21  8:06   ` Bin Meng
2016-04-21  6:19 ` [U-Boot] [PATCH 3/6 v4] i2c: designware_i2c: Integrate set_speed() into dw_i2c_set_bus_speed() Stefan Roese
2016-04-21  6:19 ` [U-Boot] [PATCH 4/6 v4] i2c: designware_i2c: Prepare for DM driver conversion Stefan Roese
2016-04-21  6:19 ` [U-Boot] [PATCH 5/6 v4] i2c: designware_i2c: Add DM support Stefan Roese
2016-04-21  6:19 ` [U-Boot] [PATCH 6/6 v4] i2c: designware_i2c: Add support for PCI(e) based I2C cores (x86) Stefan Roese
2016-04-21  7:31   ` Heiko Schocher [this message]
2016-04-21  8:14     ` Bin Meng
2016-05-01 18:54       ` Simon Glass

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=571881E3.2060805@denx.de \
    --to=hs@denx.de \
    --cc=u-boot@lists.denx.de \
    /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.