All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bin Meng <bmeng.cn@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 6/6] i2c: designware_i2c: Add support for PCI(e) based I2C cores (x86)
Date: Mon, 21 Mar 2016 17:05:45 +0800	[thread overview]
Message-ID: <CAEUhbmXFrv+L7GOhr3ikrHMuxRxnw==QivE4fPhgO1qTVgLv9Q@mail.gmail.com> (raw)
In-Reply-To: <56EFB8D2.5030306@denx.de>

Hi Stefan,

On Mon, Mar 21, 2016 at 5:03 PM, Stefan Roese <sr@denx.de> wrote:
> Hi Bin,
>
> On 21.03.2016 09:54, Bin Meng wrote:
>> On Fri, Mar 18, 2016 at 3:54 PM, Stefan Roese <sr@denx.de> wrote:
>>> 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>
>>> ---
>>>   drivers/i2c/designware_i2c.c | 111 +++++++++++++++++++++++++++++++++++++++----
>>>   1 file changed, 101 insertions(+), 10 deletions(-)
>>>
>>> diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
>>> index 4e5340d..f7f2eba 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)
>>> @@ -42,6 +63,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;
>>> @@ -61,34 +83,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, 1);
>>>
>>> @@ -315,7 +358,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
>>>
>>> @@ -356,7 +399,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)
>>> @@ -451,7 +494,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,
>>> @@ -476,14 +519,45 @@ static int designware_i2c_probe(struct udevice *bus)
>>>   {
>>>          struct dw_i2c *priv = dev_get_priv(bus);
>>>
>>> +#ifdef CONFIG_X86
>>> +       /* Save base address from PCI BAR */
>>> +       priv->regs = (struct i2c_regs *)
>>> +               dm_pci_map_bar(bus, PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
>>> +       /* Use BayTrail specific timing values */
>>> +       priv->scl_sda_cfg = &byt_config;
>>> +#else
>>
>> How about:
>>
>>      if (device_is_on_pci_bus(dev)) {
>>      do the PCI I2C stuff here;
>>      }
>
> I've tried this but it generated compilation errors on socfpga, as the
> dm_pci_xxx functions are not available there. So it definitely needs
> some #ifdef here. I could go with your suggestion and use
> #if CONFIG_DM_PCI as well.
>
>> See driver/net/designware.c for example.
>>
>>>          /* Save base address from device-tree */
>>>          priv->regs = (struct i2c_regs *)dev_get_addr(bus);
>>> +#endif
>>>
>>>          __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);
>>> +       }
>>
>> I believe the above should be wrapped by #ifdef CONFIG_DM_PCI #endif,
>> otherwise it won't build when DM_PCI is not enabled.
>
> It does build and work on socfpga without CONFIG_DM_PCI enabled. I've
> double-checked this. The only problem is the dm_pci_xxx() in
> designware_i2c_probe() as I mentioned above.
>

Great. So looks we may consolidate one usage for such both PCI and SoC
devices, like the one used in drivers/net/designware.c?

Regards,
Bin

  reply	other threads:[~2016-03-21  9:05 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-18  7:54 [U-Boot] [PATCH 1/6] i2c: designware_i2c: Add ic_enable_status to ic_regs struct Stefan Roese
2016-03-18  7:54 ` [U-Boot] [PATCH 2/6] i2c: designware_i2c: Add dw_i2c_enable() helper function Stefan Roese
2016-03-18 11:12   ` Marek Vasut
2016-03-18 12:04     ` Stefan Roese
2016-03-18 12:14       ` Marek Vasut
2016-03-21  8:54   ` Bin Meng
2016-03-18  7:54 ` [U-Boot] [PATCH 3/6] i2c: designware_i2c: Integrate set_speed() into dw_i2c_set_bus_speed() Stefan Roese
2016-03-18 11:13   ` Marek Vasut
2016-03-21  8:54   ` Bin Meng
2016-03-18  7:54 ` [U-Boot] [PATCH 4/6] i2c: designware_i2c: Prepare for DM driver conversion Stefan Roese
2016-03-21  8:54   ` Bin Meng
2016-03-18  7:54 ` [U-Boot] [PATCH 5/6] i2c: designware_i2c: Add DM support Stefan Roese
2016-03-21  8:54   ` Bin Meng
2016-04-09 18:35   ` Simon Glass
2016-03-18  7:54 ` [U-Boot] [PATCH 6/6] i2c: designware_i2c: Add support for PCI(e) based I2C cores (x86) Stefan Roese
2016-03-21  8:54   ` Bin Meng
2016-03-21  9:03     ` Stefan Roese
2016-03-21  9:05       ` Bin Meng [this message]
2016-03-21 12:04       ` Stefan Roese
2016-03-21 12:43         ` Bin Meng
2016-03-21 12:52           ` Stefan Roese
2016-03-21 14:04           ` Stefan Roese
2016-03-28  6:01             ` Bin Meng
2016-04-04 14:53               ` Stefan Roese
2016-04-11 15:03                 ` Stefan Roese
2016-04-20 14:40                   ` Simon Glass
2016-04-20 14:58                     ` Stefan Roese
2016-04-20 15:09                       ` Simon Glass
2016-04-20 15:17                         ` Stefan Roese
2016-03-18 11:09 ` [U-Boot] [PATCH 1/6] i2c: designware_i2c: Add ic_enable_status to ic_regs struct Marek Vasut
2016-03-21  8:54 ` Bin Meng

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='CAEUhbmXFrv+L7GOhr3ikrHMuxRxnw==QivE4fPhgO1qTVgLv9Q@mail.gmail.com' \
    --to=bmeng.cn@gmail.com \
    --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.