1. 27 May, 2021 1 commit
  2. 10 Apr, 2021 1 commit
  3. 05 Apr, 2021 3 commits
  4. 26 Feb, 2021 1 commit
  5. 30 May, 2020 1 commit
    • Serge Semin's avatar
      i2c: designware: Convert driver to using regmap API · 0daede80
      Serge Semin authored
      
      
      Seeing the DW I2C driver is using flags-based accessors with two
      conditional clauses it would be better to replace them with the regmap
      API IO methods and to initialize the regmap object with read/write
      callbacks specific to the controller registers map implementation. This
      will be also handy for the drivers with non-standard registers mapping
      (like an embedded into the Baikal-T1 System Controller DW I2C block, which
      glue-driver is a part of this series).
      
      As before the driver tries to detect the mapping setup at probe stage and
      creates a regmap object accordingly, which will be used by the rest of the
      code to correctly access the controller registers. In two places it was
      appropriate to convert the hand-written read-modify-write and
      read-poll-loop design patterns to the corresponding regmap API
      ready-to-use methods.
      
      Note the regmap IO methods return value is checked only at the probe
      stage. The rest of the code won't do this because basically we have
      MMIO-based regmap so non of the read/write methods can fail (this also
      won't be needed for the Baikal-T1-specific I2C controller).
      Suggested-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
      Signed-off-by: default avatarSerge Semin <Sergey.Semin@baikalelectronics.ru>
      Tested-by: default avatarJarkko Nikula <jarkko.nikula@linux.intel.com>
      Acked-by: default avatarJarkko Nikula <jarkko.nikula@linux.intel.com>
      Reviewed-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
      [wsa: fix type of 'rx_valid' and remove outdated kdoc var description]
      Signed-off-by: default avatarWolfram Sang <wsa@kernel.org>
      0daede80
  6. 13 May, 2020 2 commits
  7. 15 Apr, 2020 2 commits
  8. 21 Mar, 2020 2 commits
  9. 06 Aug, 2019 1 commit
  10. 01 Aug, 2019 1 commit
  11. 02 May, 2019 1 commit
  12. 23 Feb, 2019 1 commit
    • Hans de Goede's avatar
      i2c: designware: Do not allow i2c_dw_xfer() calls while suspended · 27515415
      Hans de Goede authored
      
      
      On most Intel Bay- and Cherry-Trail systems the PMIC is connected over I2C
      and the PMIC is accessed through various means by the _PS0 and _PS3 ACPI
      methods (power on / off methods) of various devices.
      
      This leads to suspend/resume ordering problems where a device may be
      resumed and get its _PS0 method executed before the I2C controller is
      resumed. On Cherry Trail this leads to errors like these:
      
           i2c_designware 808622C1:06: controller timed out
           ACPI Error: AE_ERROR, Returned by Handler for [UserDefinedRegion]
           ACPI Error: Method parse/execution failed \_SB.P18W._ON, AE_ERROR
           video LNXVIDEO:00: Failed to change power state to D0
      
      But on Bay Trail this caused I2C reads to seem to succeed, but they end
      up returning wrong data, which ends up getting written back by the typical
      read-modify-write cycle done to turn on various power-resources.
      
      Debugging the problems caused by this silent data corruption is quite
      nasty. This commit adds a check which disallows i2c_dw_xfer() calls to
      happen until the controller's resume method has completed.
      
      Which turns the silent data corruption into getting these errors in
      dmesg instead:
      
          i2c_designware 80860F41:04: Error i2c_dw_xfer call while suspended
          ACPI Error: AE_ERROR, Returned by Handler for [UserDefinedRegion]
          ACPI Error: Method parse/execution failed \_SB.PCI0.GFX0._PS0, AE_ERROR
      
      Which is much better.
      
      Note the above errors are an example of issues which this patch will
      help to debug, the actual fix requires fixing the suspend order and
      this has been fixed by a different commit.
      
      Note the setting / clearing of the suspended flag in the suspend / resume
      methods is NOT protected by i2c_lock_bus(). This is intentional as these
      methods get called from i2c_dw_xfer() (through pm_runtime_get/put) a nd
      i2c_dw_xfer() is called with the i2c_bus_lock held, so otherwise we would
      deadlock. This means that there is a theoretical race between a non runtime
      suspend and the suspended check in i2c_dw_xfer(), this is not a problem
      since normally we should not hit the race and this check is primarily a
      debugging tool so hitting the check if there are suspend/resume ordering
      problems does not need to be 100% reliable.
      Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
      Reviewed-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
      Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
      27515415
  13. 11 Oct, 2018 1 commit
  14. 05 Oct, 2018 1 commit
  15. 06 Sep, 2018 1 commit
  16. 30 Aug, 2018 1 commit
    • Hans de Goede's avatar
      i2c: designware: Re-init controllers with pm_disabled set on resume · 9d9a152e
      Hans de Goede authored
      On Bay Trail and Cherry Trail devices we set the pm_disabled flag for I2C
      busses which the OS shares with the PUNIT as these need special handling.
      Until now we called dev_pm_syscore_device(dev, true) for I2C controllers
      with this flag set to keep these I2C controllers always on.
      
      After commit 12864ff8 ("ACPI / LPSS: Avoid PM quirks on suspend and
      resume from hibernation"), this no longer works. This commit modifies
      lpss_iosf_exit_d3_state() to only run if lpss_iosf_enter_d3_state() has ran
      before it, so that it does not run on a resume from hibernate (or from S3).
      
      On these systems the conditions for lpss_iosf_enter_d3_state() to run
      never become true, so lpss_iosf_exit_d3_state() never gets called and
      the 2 LPSS DMA controllers never get forced into D0 mode, instead they
      are left in their default automatic power-on when needed mode.
      
      The not forcing of D0 mode for the DMA controllers enables these systems
      to properly enter S0ix modes, which is a good thing.
      
      But after entering S0ix modes the I2C controller connected to the PMIC
      no longer works, leading to e.g. broken battery monitoring.
      
      The _PS3 method for this I2C controller looks like this:
      
                  Method (_PS3, 0, NotSerialized)  // _PS3: Power State 3
                  {
                      If ((((PMID == 0x04) || (PMID == 0x05)) || (PMID == 0x06)))
                      {
                          Return (Zero)
                      }
      
                      PSAT |= 0x03
                      Local0 = PSAT /* \_SB_.I2C5.PSAT */
                  }
      
      Where PMID = 0x05, so we enter the Return (Zero) path on these systems.
      
      So even if we were to not call dev_pm_syscore_device(dev, true) the
      I2C controller will be left in D0 rather then be switched to D3.
      
      Yet on other Bay and Cherry Trail devices S0ix is not entered unless *all*
      I2C controllers are in D3 mode. This combined with the I2C controller no
      longer working now that we reach S0ix states on these systems leads to me
      believing that the PUNIT itself puts the I2C controller in D3 when all
      other conditions for entering S0ix states are true.
      
      Since now the I2C controller is put in D3 over a suspend/resume we must
      re-initialize it afterwards and that does indeed fix it no longer working.
      
      This commit implements this fix by:
      
      1) Making the suspend_late callback a no-op if pm_disabled is set and
      making the resume_early callback skip the clock re-enable (since it now was
      not disabled) while still doing the necessary I2C controller re-init.
      
      2) Removing the dev_pm_syscore_device(dev, true) call, so that the suspend
      and resume callbacks are actually called. Normally this would cause the
      ACPI pm code to call _PS3 putting the I2C controller in D3, wreaking havoc
      since it is shared with the PUNIT, but in this special case the _PS3 method
      is a no-op so we can safely allow a "fake" suspend / resume.
      
      Fixes: 12864ff8 ("ACPI / LPSS: Avoid PM quirks on suspend and resume ...")
      Link: https://bugzilla.kernel.org/show_bug.cgi?id=200861
      
      
      Cc: 4.15+ <stable@vger.kernel.org> # 4.15+
      Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
      Reviewed-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
      Acked-by: default avatarJarkko Nikula <jarkko.nikula@linux.intel.com>
      Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
      9d9a152e
  17. 20 Aug, 2018 1 commit
  18. 08 Aug, 2018 1 commit
  19. 04 Aug, 2018 1 commit
  20. 03 Jul, 2018 5 commits
  21. 15 May, 2018 1 commit
    • Alexander Monakov's avatar
      i2c: designware: refactor low-level enable/disable · 9f4659ba
      Alexander Monakov authored
      
      
      Low-level controller enable function __i2c_dw_enable is overloaded to
      also handle disabling. What's worse, even though the documentation
      requires polling the IC_ENABLE_STATUS register when disabling, this
      is not done: polling needs to be requested specifically by calling
      __i2c_dw_enable_and_wait, which can also poll on enabling, but that
      doesn't work if the IC_ENABLE_STATUS register is not implemented.
      This is quite confusing if not in fact backwards.
      
      Especially since the documentation says that disabling should be
      followed by polling, the driver should be using a separate function
      where it does one-shot disables to make the optimization stand out.
      
      This refactors the two functions so that requested status is given
      in the name rather than in a boolean argument. Specifically:
      
       - __i2c_dw_enable: enable without polling (in accordance with docs)
       - __i2c_dw_disable: disable and do poll (also as suggested by docs)
       - __i2c_dw_disable_nowait: disable without polling (Linux-specific)
      
      No functional change.
      Signed-off-by: default avatarAlexander Monakov <amonakov@ispras.ru>
      Acked-by: default avatarJarkko Nikula <jarkko.nikula@linux.intel.com>
      [wsa: fixed blank lines in header file]
      Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
      9f4659ba
  22. 10 May, 2018 1 commit
  23. 17 Mar, 2018 1 commit
  24. 22 Feb, 2018 1 commit
  25. 21 Feb, 2018 1 commit
    • Ben Gardner's avatar
      i2c: designware: must wait for enable · fba4adbb
      Ben Gardner authored
      One I2C bus on my Atom E3845 board has been broken since 4.9.
      It has two devices, both declared by ACPI and with built-in drivers.
      
      There are two back-to-back transactions originating from the kernel, one
      targeting each device. The first transaction works, the second one locks
      up the I2C controller. The controller never recovers.
      
      These kernel logs show up whenever an I2C transaction is attempted after
      this failure.
      i2c-designware-pci 0000:00:18.3: timeout in disabling adapter
      i2c-designware-pci 0000:00:18.3: timeout waiting for bus ready
      
      Waiting for the I2C controller status to indicate that it is enabled
      before programming it fixes the issue.
      
      I have tested this patch on 4.14 and 4.15.
      
      Fixes: commit 2702ea7d
      
       ("i2c: designware: wait for disable/enable only if necessary")
      Cc: linux-stable <stable@vger.kernel.org> #4.13+
      Signed-off-by: default avatarBen Gardner <gardner.ben@gmail.com>
      Acked-by: default avatarJarkko Nikula <jarkko.nikula@linux.intel.com>
      Reviewed-by: default avatarJosé Roberto de Souza <jose.souza@intel.com>
      Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
      fba4adbb
  26. 27 Nov, 2017 1 commit
  27. 04 Jul, 2017 1 commit
  28. 19 Jun, 2017 3 commits
  29. 31 May, 2017 1 commit