Commit 273cbf61 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'i2c/for-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c updates from Wolfram Sang:
 "New stuff from the I2C world:

   - in the core, getting irqs from ACPI is now similar to OF

   - new driver for MediaTek MT7621/7628/7688 SoCs

   - bcm2835, i801, and tegra drivers got some more attention

   - GPIO API cleanups

   - cleanups in the core headers

   - lots of usual driver updates"

* 'i2c/for-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (74 commits)
  i2c: mt7621: Fix platform_no_drv_owner.cocci warnings
  i2c: cpm: remove casting dma_alloc
  dt-bindings: i2c: sun6i-p2wi: Fix the binding example
  dt-bindings: i2c: mv64xxx: Fix the example compatible
  i2c: i801: Documentation update
  i2c: i801: Add support for Intel Tiger Lake
  i2c: i801: Fix PCI ID sorting
  dt-bindings: i2c-stm32: document optional dmas
  i2c: i2c-stm32f7: Add I2C_SMBUS_I2C_BLOCK_DATA support
  i2c: core: Tidy up handling of init_irq
  i2c: core: Move ACPI gpio IRQ handling into i2c_acpi_get_irq
  i2c: core: Move ACPI IRQ handling to probe time
  i2c: acpi: Factor out getting the IRQ from ACPI
  i2c: acpi: Use available IRQ helper functions
  i2c: core: Allow whole core to use i2c_dev_irq_from_resources
  eeprom: at24: modify a comment referring to platform data
  dt-bindings: i2c: omap: Add new compatible for J721E SoCs
  dt-bindings: i2c: mv64xxx: Add YAML schemas
  dt-bindings: i2c: sun6i-p2wi: Add YAML schemas
  i2c: mt7621: Add MediaTek MT7621/7628/7688 I2C driver
  ...
parents 5fe7b600 cc6b9dfb
What: /sys/devices/platform/<i2c-demux-name>/available_masters What: /sys/devices/platform/<i2c-demux-name>/available_masters
Date: January 2016 Date: January 2016
KernelVersion: 4.6 KernelVersion: 4.6
Contact: Wolfram Sang <wsa@the-dreams.de> Contact: Wolfram Sang <wsa+renesas@sang-engineering.com>
Description: Description:
Reading the file will give you a list of masters which can be Reading the file will give you a list of masters which can be
selected for a demultiplexed bus. The format is selected for a demultiplexed bus. The format is
...@@ -12,7 +12,7 @@ Description: ...@@ -12,7 +12,7 @@ Description:
What: /sys/devices/platform/<i2c-demux-name>/current_master What: /sys/devices/platform/<i2c-demux-name>/current_master
Date: January 2016 Date: January 2016
KernelVersion: 4.6 KernelVersion: 4.6
Contact: Wolfram Sang <wsa@the-dreams.de> Contact: Wolfram Sang <wsa+renesas@sang-engineering.com>
Description: Description:
This file selects/shows the active I2C master for a demultiplexed This file selects/shows the active I2C master for a demultiplexed
bus. It uses the <index> value from the file 'available_masters'. bus. It uses the <index> value from the file 'available_masters'.
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/i2c/allwinner,sun6i-a31-p2wi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner A31 P2WI (Push/Pull 2 Wires Interface) Device Tree Bindings
maintainers:
- Chen-Yu Tsai <wens@csie.org>
- Maxime Ripard <maxime.ripard@bootlin.com>
allOf:
- $ref: /schemas/i2c/i2c-controller.yaml#
properties:
compatible:
const: allwinner,sun6i-a31-p2wi
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
resets:
maxItems: 1
clock-frequency:
minimum: 1
maximum: 6000000
required:
- compatible
- reg
- interrupts
- clocks
- resets
# FIXME: We should set it, but it would report all the generic
# properties as additional properties.
# additionalProperties: false
examples:
- |
i2c@1f03400 {
compatible = "allwinner,sun6i-a31-p2wi";
reg = <0x01f03400 0x400>;
interrupts = <0 39 4>;
clocks = <&apb0_gates 3>;
clock-frequency = <100000>;
resets = <&apb0_rst 3>;
#address-cells = <1>;
#size-cells = <0>;
axp221: pmic@68 {
compatible = "x-powers,axp221";
reg = <0x68>;
};
};
...
MediaTek MT7621/MT7628 I2C master controller
Required properties:
- compatible: Should be one of the following:
- "mediatek,mt7621-i2c": for MT7621/MT7628/MT7688 platforms
- #address-cells: should be 1.
- #size-cells: should be 0.
- reg: Address and length of the register set for the device
- resets: phandle to the reset controller asserting this device in
reset
See ../reset/reset.txt for details.
Optional properties :
Example:
i2c: i2c@900 {
compatible = "mediatek,mt7621-i2c";
reg = <0x900 0x100>;
#address-cells = <1>;
#size-cells = <0>;
resets = <&rstctrl 16>;
reset-names = "i2c";
};
* Marvell MV64XXX I2C controller
Required properties :
- reg : Offset and length of the register set for the device
- compatible : Should be either:
- "allwinner,sun4i-a10-i2c"
- "allwinner,sun6i-a31-i2c"
- "marvell,mv64xxx-i2c"
- "marvell,mv78230-i2c"
- "marvell,mv78230-a0-i2c"
* Note: Only use "marvell,mv78230-a0-i2c" for a
very rare, initial version of the SoC which
had broken offload support. Linux
auto-detects this and sets it appropriately.
- interrupts : The interrupt number
Optional properties :
- clock-frequency : Desired I2C bus clock frequency in Hz. If not set the
default frequency is 100kHz
- resets : phandle to the parent reset controller. Mandatory
whenever you're using the "allwinner,sun6i-a31-i2c"
compatible.
- clocks: : pointers to the reference clocks for this device, the
first one is the one used for the clock on the i2c bus,
the second one is the clock used to acces the registers
of the controller
- clock-names : names of used clocks, mandatory if the second clock is
used, the name must be "core", and "reg" (the latter is
only for Armada 7K/8K).
Examples:
i2c@11000 {
compatible = "marvell,mv64xxx-i2c";
reg = <0x11000 0x20>;
interrupts = <29>;
clock-frequency = <100000>;
};
For the Armada XP:
i2c@11000 {
compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
reg = <0x11000 0x100>;
interrupts = <29>;
clock-frequency = <100000>;
};
For the Armada 7040:
i2c@701000 {
compatible = "marvell,mv78230-i2c";
reg = <0x701000 0x20>;
interrupts = <29>;
clock-frequency = <100000>;
clock-names = "core", "reg";
clocks = <&core_clock>, <&reg_clock>;
};
Device tree configuration for i2c-ocores Device tree configuration for i2c-ocores
Required properties: Required properties:
- compatible : "opencores,i2c-ocores" or "aeroflexgaisler,i2cmst" - compatible : "opencores,i2c-ocores"
"aeroflexgaisler,i2cmst"
"sifive,fu540-c000-i2c", "sifive,i2c0"
For Opencore based I2C IP block reimplemented in
FU540-C000 SoC. Please refer to sifive-blocks-ip-versioning.txt
for additional details.
- reg : bus address start and address range size of device - reg : bus address start and address range size of device
- interrupts : interrupt number
- clocks : handle to the controller clock; see the note below. - clocks : handle to the controller clock; see the note below.
Mutually exclusive with opencores,ip-clock-frequency Mutually exclusive with opencores,ip-clock-frequency
- opencores,ip-clock-frequency: frequency of the controller clock in Hz; - opencores,ip-clock-frequency: frequency of the controller clock in Hz;
...@@ -12,6 +16,7 @@ Required properties: ...@@ -12,6 +16,7 @@ Required properties:
- #size-cells : should be <0> - #size-cells : should be <0>
Optional properties: Optional properties:
- interrupts : interrupt number.
- clock-frequency : frequency of bus clock in Hz; see the note below. - clock-frequency : frequency of bus clock in Hz; see the note below.
Defaults to 100 KHz when the property is not specified Defaults to 100 KHz when the property is not specified
- reg-shift : device register offsets are shifted by this value - reg-shift : device register offsets are shifted by this value
......
...@@ -7,6 +7,7 @@ Required properties : ...@@ -7,6 +7,7 @@ Required properties :
"ti,omap3-i2c" for OMAP3 SoCs "ti,omap3-i2c" for OMAP3 SoCs
"ti,omap4-i2c" for OMAP4+ SoCs "ti,omap4-i2c" for OMAP4+ SoCs
"ti,am654-i2c", "ti,omap4-i2c" for AM654 SoCs "ti,am654-i2c", "ti,omap4-i2c" for AM654 SoCs
"ti,j721e-i2c", "ti,omap4-i2c" for J721E SoCs
- ti,hwmods : Must be "i2c<n>", n being the instance number (1-based) - ti,hwmods : Must be "i2c<n>", n being the instance number (1-based)
- #address-cells = <1>; - #address-cells = <1>;
- #size-cells = <0>; - #size-cells = <0>;
......
...@@ -21,6 +21,8 @@ Optional properties: ...@@ -21,6 +21,8 @@ Optional properties:
100000 and 400000. 100000 and 400000.
For STM32F7, STM32H7 and STM32MP1 SoCs, Standard-mode, Fast-mode and Fast-mode For STM32F7, STM32H7 and STM32MP1 SoCs, Standard-mode, Fast-mode and Fast-mode
Plus are supported, possible values are 100000, 400000 and 1000000. Plus are supported, possible values are 100000, 400000 and 1000000.
- dmas: List of phandles to rx and tx DMA channels. Refer to stm32-dma.txt.
- dma-names: List of dma names. Valid names are: "rx" and "tx".
- i2c-scl-rising-time-ns: I2C SCL Rising time for the board (default: 25) - i2c-scl-rising-time-ns: I2C SCL Rising time for the board (default: 25)
For STM32F7, STM32H7 and STM32MP1 only. For STM32F7, STM32H7 and STM32MP1 only.
- i2c-scl-falling-time-ns: I2C SCL Falling time for the board (default: 10) - i2c-scl-falling-time-ns: I2C SCL Falling time for the board (default: 10)
......
* Allwinner P2WI (Push/Pull 2 Wire Interface) controller
Required properties :
- reg : Offset and length of the register set for the device.
- compatible : Should one of the following:
- "allwinner,sun6i-a31-p2wi"
- interrupts : The interrupt line connected to the P2WI peripheral.
- clocks : The gate clk connected to the P2WI peripheral.
- resets : The reset line connected to the P2WI peripheral.
Optional properties :
- clock-frequency : Desired P2WI bus clock frequency in Hz. If not set the
default frequency is 100kHz
A P2WI may contain one child node encoding a P2WI slave device.
Slave device properties:
Required properties:
- reg : the I2C slave address used during the initialization
process to switch from I2C to P2WI mode
Example:
p2wi@1f03400 {
compatible = "allwinner,sun6i-a31-p2wi";
reg = <0x01f03400 0x400>;
interrupts = <0 39 4>;
clocks = <&apb0_gates 3>;
clock-frequency = <6000000>;
resets = <&apb0_rst 3>;
axp221: pmic@68 {
compatible = "x-powers,axp221";
reg = <0x68>;
/* ... */
};
};
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/i2c/marvell,mv64xxx-i2c.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Marvell MV64XXX I2C Controller Device Tree Bindings
maintainers:
- Gregory CLEMENT <gregory.clement@bootlin.com>
properties:
compatible:
oneOf:
- const: allwinner,sun4i-a10-i2c
- items:
- const: allwinner,sun7i-a20-i2c
- const: allwinner,sun4i-a10-i2c
- const: allwinner,sun6i-a31-i2c
- items:
- const: allwinner,sun8i-a23-i2c
- const: allwinner,sun6i-a31-i2c
- items:
- const: allwinner,sun8i-a83t-i2c
- const: allwinner,sun6i-a31-i2c
- items:
- const: allwinner,sun50i-a64-i2c
- const: allwinner,sun6i-a31-i2c
- const: marvell,mv64xxx-i2c
- const: marvell,mv78230-i2c
- const: marvell,mv78230-a0-i2c
description:
Only use "marvell,mv78230-a0-i2c" for a very rare, initial
version of the SoC which had broken offload support. Linux
auto-detects this and sets it appropriately.
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
minItems: 1
maxItems: 2
items:
- description: Reference clock for the I2C bus
- description: Bus clock (Only for Armada 7K/8K)
clock-names:
minItems: 1
maxItems: 2
items:
- const: core
- const: reg
description:
Mandatory if two clocks are used (only for Armada 7k and 8k).
resets:
maxItems: 1
required:
- compatible
- reg
- interrupts
allOf:
- $ref: /schemas/i2c/i2c-controller.yaml#
- if:
properties:
compatible:
contains:
enum:
- allwinner,sun4i-a10-i2c
- allwinner,sun6i-a31-i2c
then:
required:
- clocks
- if:
properties:
compatible:
contains:
const: allwinner,sun6i-a31-i2c
then:
required:
- resets
# FIXME: We should set it, but it would report all the generic
# properties as additional properties.
# additionalProperties: false
examples:
- |
i2c@11000 {
compatible = "marvell,mv64xxx-i2c";
reg = <0x11000 0x20>;
interrupts = <29>;
clock-frequency = <100000>;
};
- |
i2c@11000 {
compatible = "marvell,mv78230-i2c";
reg = <0x11000 0x100>;
interrupts = <29>;
clock-frequency = <100000>;
};
- |
i2c@701000 {
compatible = "marvell,mv78230-i2c";
reg = <0x701000 0x20>;
interrupts = <29>;
clock-frequency = <100000>;
clock-names = "core", "reg";
clocks = <&core_clock>, <&reg_clock>;
};
...
...@@ -37,6 +37,8 @@ Supported adapters: ...@@ -37,6 +37,8 @@ Supported adapters:
* Intel Cedar Fork (PCH) * Intel Cedar Fork (PCH)
* Intel Ice Lake (PCH) * Intel Ice Lake (PCH)
* Intel Comet Lake (PCH) * Intel Comet Lake (PCH)
* Intel Elkhart Lake (PCH)
* Intel Tiger Lake (PCH)
Datasheets: Publicly available at the Intel website Datasheets: Publicly available at the Intel website
On Intel Patsburg and later chipsets, both the normal host SMBus controller On Intel Patsburg and later chipsets, both the normal host SMBus controller
...@@ -58,6 +60,7 @@ question doesn't work as intended for whatever reason. Bit values: ...@@ -58,6 +60,7 @@ question doesn't work as intended for whatever reason. Bit values:
0x02 disable the block buffer 0x02 disable the block buffer
0x08 disable the I2C block read functionality 0x08 disable the I2C block read functionality
0x10 don't use interrupts 0x10 don't use interrupts
0x20 disable SMBus Host Notify
Description Description
...@@ -88,7 +91,7 @@ SMBus controller. ...@@ -88,7 +91,7 @@ SMBus controller.
Process Call Support Process Call Support
-------------------- --------------------
Not supported. Block process call is supported on the 82801EB (ICH5) and later chips.
I2C Block Read Support I2C Block Read Support
...@@ -118,16 +121,15 @@ BIOS to enable it, it means it has been hidden by the BIOS code. Asus is ...@@ -118,16 +121,15 @@ BIOS to enable it, it means it has been hidden by the BIOS code. Asus is
well known for first doing this on their P4B motherboard, and many other well known for first doing this on their P4B motherboard, and many other
boards after that. Some vendor machines are affected as well. boards after that. Some vendor machines are affected as well.
The first thing to try is the "i2c_ec" ACPI driver. It could be that the The first thing to try is the "i2c-scmi" ACPI driver. It could be that the
SMBus was hidden on purpose because it'll be driven by ACPI. If the SMBus was hidden on purpose because it'll be driven by ACPI. If the
i2c_ec driver works for you, just forget about the i2c-i801 driver and i2c-scmi driver works for you, just forget about the i2c-i801 driver and
don't try to unhide the ICH SMBus. Even if i2c_ec doesn't work, you don't try to unhide the ICH SMBus. Even if i2c-scmi doesn't work, you
better make sure that the SMBus isn't used by the ACPI code. Try loading better make sure that the SMBus isn't used by the ACPI code. Try loading
the "fan" and "thermal" drivers, and check in /proc/acpi/fan and the "fan" and "thermal" drivers, and check in /sys/class/thermal. If you
/proc/acpi/thermal_zone. If you find anything there, it's likely that find a thermal zone with type "acpitz", it's likely that the ACPI is
the ACPI is accessing the SMBus and it's safer not to unhide it. Only accessing the SMBus and it's safer not to unhide it. Only once you are
once you are certain that ACPI isn't using the SMBus, you can attempt certain that ACPI isn't using the SMBus, you can attempt to unhide it.
to unhide it.
In order to unhide the SMBus, we need to change the value of a PCI In order to unhide the SMBus, we need to change the value of a PCI
register before the kernel enumerates the PCI devices. This is done in register before the kernel enumerates the PCI devices. This is done in
......
...@@ -10123,6 +10123,13 @@ L: linux-wireless@vger.kernel.org ...@@ -10123,6 +10123,13 @@ L: linux-wireless@vger.kernel.org
S: Maintained S: Maintained
F: drivers/net/wireless/mediatek/mt7601u/ F: drivers/net/wireless/mediatek/mt7601u/
MEDIATEK MT7621/28/88 I2C DRIVER
M: Stefan Roese <sr@denx.de>
L: linux-i2c@vger.kernel.org
S: Maintained
F: drivers/i2c/busses/i2c-mt7621.c
F: Documentation/devicetree/bindings/i2c/i2c-mt7621.txt
MEDIATEK NAND CONTROLLER DRIVER MEDIATEK NAND CONTROLLER DRIVER
M: Xiaolei Li <xiaolei.li@mediatek.com> M: Xiaolei Li <xiaolei.li@mediatek.com>
L: linux-mtd@lists.infradead.org L: linux-mtd@lists.infradead.org
......
...@@ -302,6 +302,8 @@ extern struct platform_device iop3xx_dma_1_channel; ...@@ -302,6 +302,8 @@ extern struct platform_device iop3xx_dma_1_channel;
extern struct platform_device iop3xx_aau_channel; extern struct platform_device iop3xx_aau_channel;
extern struct platform_device iop3xx_i2c0_device; extern struct platform_device iop3xx_i2c0_device;
extern struct platform_device iop3xx_i2c1_device; extern struct platform_device iop3xx_i2c1_device;
extern struct gpiod_lookup_table iop3xx_i2c0_gpio_lookup;
extern struct gpiod_lookup_table iop3xx_i2c1_gpio_lookup;
#endif #endif
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/irq.h> #include <linux/irq.h>
...@@ -207,6 +208,8 @@ static void __init em7210_init_machine(void) ...@@ -207,6 +208,8 @@ static void __init em7210_init_machine(void)
{ {
register_iop32x_gpio(); register_iop32x_gpio();
platform_device_register(&em7210_serial_device); platform_device_register(&em7210_serial_device);
gpiod_add_lookup_table(&iop3xx_i2c0_gpio_lookup);
gpiod_add_lookup_table(&iop3xx_i2c1_gpio_lookup);
platform_device_register(&iop3xx_i2c0_device); platform_device_register(&iop3xx_i2c0_device);
platform_device_register(&iop3xx_i2c1_device); platform_device_register(&iop3xx_i2c1_device);
platform_device_register(&em7210_flash_device); platform_device_register(&em7210_flash_device);
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio/machine.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
...@@ -185,6 +186,8 @@ static void glantank_power_off(void) ...@@ -185,6 +186,8 @@ static void glantank_power_off(void)
static void __init glantank_init_machine(void) static void __init glantank_init_machine(void)
{ {
register_iop32x_gpio(); register_iop32x_gpio();
gpiod_add_lookup_table(&iop3xx_i2c0_gpio_lookup);
gpiod_add_lookup_table(&iop3xx_i2c1_gpio_lookup);
platform_device_register(&iop3xx_i2c0_device); platform_device_register(&iop3xx_i2c0_device);
platform_device_register(&iop3xx_i2c1_device); platform_device_register(&iop3xx_i2c1_device);
platform_device_register(&glantank_flash_device); platform_device_register(&glantank_flash_device);
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/mtd/physmap.h> #include <linux/mtd/physmap.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio/machine.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/cputype.h> #include <asm/cputype.h>
#include <asm/irq.h> #include <asm/irq.h>
...@@ -281,6 +282,8 @@ void ep80219_power_off(void) ...@@ -281,6 +282,8 @@ void ep80219_power_off(void)
static void __init iq31244_init_machine(void) static void __init iq31244_init_machine(void)
{ {
register_iop32x_gpio(); register_iop32x_gpio();
gpiod_add_lookup_table(&iop3xx_i2c0_gpio_lookup);
gpiod_add_lookup_table(&iop3xx_i2c1_gpio_lookup);
platform_device_register(&iop3xx_i2c0_device); platform_device_register(&iop3xx_i2c0_device);
platform_device_register(&iop3xx_i2c1_device); platform_device_register(&iop3xx_i2c1_device);
platform_device_register(&iq31244_flash_device); platform_device_register(&iq31244_flash_device);
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/mtd/physmap.h> #include <linux/mtd/physmap.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio/machine.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
...@@ -168,6 +169,8 @@ static struct platform_device iq80321_serial_device = { ...@@ -168,6 +169,8 @@ static struct platform_device iq80321_serial_device = {
static void __init iq80321_init_machine(void) static void __init iq80321_init_machine(void)
{ {
register_iop32x_gpio(); register_iop32x_gpio();
gpiod_add_lookup_table(&iop3xx_i2c0_gpio_lookup);
gpiod_add_lookup_table(&iop3xx_i2c1_gpio_lookup);
platform_device_register(&iop3xx_i2c0_device); platform_device_register(&iop3xx_i2c0_device);
platform_device_register(&iop3xx_i2c1_device); platform_device_register(&iop3xx_i2c1_device);
platform_device_register(&iq80321_flash_device); platform_device_register(&iq80321_flash_device);
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
...@@ -341,6 +342,7 @@ device_initcall(n2100_request_gpios); ...@@ -341,6 +342,7 @@ device_initcall(n2100_request_gpios);
static void __init n2100_init_machine(void) static void __init n2100_init_machine(void)
{ {
register_iop32x_gpio(); register_iop32x_gpio();
gpiod_add_lookup_table(&iop3xx_i2c0_gpio_lookup);
platform_device_register(&iop3xx_i2c0_device); platform_device_register(&iop3xx_i2c0_device);
platform_device_register(&n2100_flash_device); platform_device_register(&n2100_flash_device);
platform_device_register(&n2100_serial_device); platform_device_register(&n2100_serial_device);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/serial_core.h> #include <linux/serial_core.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio/machine.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
...@@ -34,6 +35,29 @@ ...@@ -34,6 +35,29 @@
#define IRQ_IOP3XX_I2C_1 IRQ_IOP33X_I2C_1 #define IRQ_IOP3XX_I2C_1 IRQ_IOP33X_I2C_1
#endif #endif
/*
* Each of the I2C busses have corresponding GPIO lines, and the driver
* need to access these directly to drive the bus low at times.
*/
struct gpiod_lookup_table iop3xx_i2c0_gpio_lookup = {
.dev_id = "IOP3xx-I2C.0",
.table = {
GPIO_LOOKUP("gpio-iop", 7, "scl", GPIO_ACTIVE_HIGH),
GPIO_LOOKUP("gpio-iop", 6, "sda", GPIO_ACTIVE_HIGH),
{ }
},
};
struct gpiod_lookup_table iop3xx_i2c1_gpio_lookup = {
.dev_id = "IOP3xx-I2C.1",
.table = {
GPIO_LOOKUP("gpio-iop", 5, "scl", GPIO_ACTIVE_HIGH),
GPIO_LOOKUP("gpio-iop", 4, "sda", GPIO_ACTIVE_HIGH),
{ }
},
};
static struct resource iop3xx_i2c0_resources[] = { static struct resource iop3xx_i2c0_resources[] = {
[0] = { [0] = {
.start = 0xfffff680, .start = 0xfffff680,
......
...@@ -36,6 +36,7 @@ static int iop3xx_gpio_probe(struct platform_device *pdev) ...@@ -36,6 +36,7 @@ static int iop3xx_gpio_probe(struct platform_device *pdev)
gc->base = 0; gc->base = 0;
gc->owner = THIS_MODULE; gc->owner = THIS_MODULE;
gc->label = "gpio-iop";
return devm_gpiochip_add_data(&pdev->dev, gc, NULL); return devm_gpiochip_add_data(&pdev->dev, gc, NULL);
} }
......
...@@ -143,6 +143,8 @@ config I2C_I801 ...@@ -143,6 +143,8 @@ config I2C_I801
Cedar Fork (PCH) Cedar Fork (PCH)
Ice Lake (PCH) Ice Lake (PCH)
Comet Lake (PCH) Comet Lake (PCH)
Elkhart Lake (PCH)
Tiger Lake (PCH)
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called i2c-i801. will be called i2c-i801.
...@@ -436,7 +438,7 @@ config I2C_AXXIA ...@@ -436,7 +438,7 @@ config I2C_AXXIA
config I2C_BCM2835 config I2C_BCM2835
tristate "Broadcom BCM2835 I2C controller" tristate "Broadcom BCM2835 I2C controller"
depends on ARCH_BCM2835 depends on ARCH_BCM2835 || ARCH_BRCMSTB
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
BCM2835 I2C controller. BCM2835 I2C controller.
...@@ -692,7 +694,7 @@ config I2C_IOP3XX ...@@ -692,7 +694,7 @@ config I2C_IOP3XX
config I2C_JZ4780 config I2C_JZ4780
tristate "JZ4780 I2C controller interface support" tristate "JZ4780 I2C controller interface support"
depends on MACH_JZ4780 || COMPILE_TEST depends on MIPS || COMPILE_TEST
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
Ingenic JZ4780 I2C controller. Ingenic JZ4780 I2C controller.
...@@ -746,6 +748,13 @@ config I2C_MT65XX ...@@ -746,6 +748,13 @@ config I2C_MT65XX
If you want to use MediaTek(R) I2C interface, say Y or M here. If you want to use MediaTek(R) I2C interface, say Y or M here.
If unsure, say N. If unsure, say N.
config I2C_MT7621
tristate "MT7621/MT7628 I2C Controller"
depends on (RALINK && (SOC_MT7620 || SOC_MT7621)) || COMPILE_TEST
help
Say Y here to include support for I2C controller in the
MediaTek MT7621/MT7628 SoCs.
config I2C_MV64XXX config I2C_MV64XXX
tristate "Marvell mv64xxx I2C Controller" tristate "Marvell mv64xxx I2C Controller"
depends on MV64X60 || PLAT_ORION || ARCH_SUNXI || ARCH_MVEBU depends on MV64X60 || PLAT_ORION || ARCH_SUNXI || ARCH_MVEBU
......
...@@ -77,6 +77,7 @@ obj-$(CONFIG_I2C_LPC2K) += i2c-lpc2k.o ...@@ -77,6 +77,7 @@ obj-$(CONFIG_I2C_LPC2K) += i2c-lpc2k.o
obj-$(CONFIG_I2C_MESON) += i2c-meson.o obj-$(CONFIG_I2C_MESON) += i2c-meson.o
obj-$(CONFIG_I2C_MPC) += i2c-mpc.o obj-$(CONFIG_I2C_MPC) += i2c-mpc.o
obj-$(CONFIG_I2C_MT65XX) += i2c-mt65xx.o obj-$(CONFIG_I2C_MT65XX) += i2c-mt65xx.o
obj-$(CONFIG_I2C_MT7621) += i2c-mt7621.o
obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o
obj-$(CONFIG_I2C_MXS) += i2c-mxs.o obj-$(CONFIG_I2C_MXS) += i2c-mxs.o
obj-$(CONFIG_I2C_NOMADIK) += i2c-nomadik.o obj-$(CONFIG_I2C_NOMADIK) += i2c-nomadik.o
......
...@@ -165,12 +165,6 @@ enum i2c_slave_read_status { ...@@ -165,12 +165,6 @@ enum i2c_slave_read_status {
I2C_SLAVE_RX_END, I2C_SLAVE_RX_END,
}; };
enum i2c_slave_xfer_dir {
I2C_SLAVE_DIR_READ = 0,
I2C_SLAVE_DIR_WRITE,
I2C_SLAVE_DIR_NONE,
};
enum bus_speed_index { enum bus_speed_index {
I2C_SPD_100K = 0, I2C_SPD_100K = 0,
I2C_SPD_400K, I2C_SPD_400K,
...@@ -203,7 +197,6 @@ struct bcm_iproc_i2c_dev { ...@@ -203,7 +197,6 @@ struct bcm_iproc_i2c_dev {
struct i2c_msg *msg; struct i2c_msg *msg;
struct i2c_client *slave; struct i2c_client *slave;
enum i2c_slave_xfer_dir xfer_dir;
/* bytes that have been transferred */ /* bytes that have been transferred */
unsigned int tx_bytes; unsigned int tx_bytes;
...@@ -219,7 +212,8 @@ struct bcm_iproc_i2c_dev { ...@@ -219,7 +212,8 @@ struct bcm_iproc_i2c_dev {
| BIT(IS_M_RX_THLD_SHIFT)) | BIT(IS_M_RX_THLD_SHIFT))
#define ISR_MASK_SLAVE (BIT(IS_S_START_BUSY_SHIFT)\ #define ISR_MASK_SLAVE (BIT(IS_S_START_BUSY_SHIFT)\
| BIT(IS_S_RX_EVENT_SHIFT) | BIT(IS_S_RD_EVENT_SHIFT)) | BIT(IS_S_RX_EVENT_SHIFT) | BIT(IS_S_RD_EVENT_SHIFT)\
| BIT(IS_S_TX_UNDERRUN_SHIFT))
static int bcm_iproc_i2c_reg_slave(struct i2c_client *slave); static int bcm_iproc_i2c_reg_slave(struct i2c_client *slave);
static int bcm_iproc_i2c_unreg_slave(struct i2c_client *slave); static int bcm_iproc_i2c_unreg_slave(struct i2c_client *slave);
...@@ -297,15 +291,11 @@ static void bcm_iproc_i2c_slave_init( ...@@ -297,15 +291,11 @@ static void bcm_iproc_i2c_slave_init(
/* clear all pending slave interrupts */ /* clear all pending slave interrupts */
iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, ISR_MASK_SLAVE); iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, ISR_MASK_SLAVE);
/* Enable interrupt register for any READ event */
val = BIT(IE_S_RD_EVENT_SHIFT);
/* Enable interrupt register to indicate a valid byte in receive fifo */ /* Enable interrupt register to indicate a valid byte in receive fifo */
val |= BIT(IE_S_RX_EVENT_SHIFT); val = BIT(IE_S_RX_EVENT_SHIFT);
/* Enable interrupt register for the Slave BUSY command */ /* Enable interrupt register for the Slave BUSY command */
val |= BIT(IE_S_START_BUSY_SHIFT); val |= BIT(IE_S_START_BUSY_SHIFT);
iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val); iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val);
iproc_i2c->xfer_dir = I2C_SLAVE_DIR_NONE;
} }
static void bcm_iproc_i2c_check_slave_status( static void bcm_iproc_i2c_check_slave_status(
...@@ -314,8 +304,11 @@ static void bcm_iproc_i2c_check_slave_status( ...@@ -314,8 +304,11 @@ static void bcm_iproc_i2c_check_slave_status(
u32 val; u32 val;
val = iproc_i2c_rd_reg(iproc_i2c, S_CMD_OFFSET); val = iproc_i2c_rd_reg(iproc_i2c, S_CMD_OFFSET);
val = (val >> S_CMD_STATUS_SHIFT) & S_CMD_STATUS_MASK; /* status is valid only when START_BUSY is cleared after it was set */
if (val & BIT(S_CMD_START_BUSY_SHIFT))
return;
val = (val >> S_CMD_STATUS_SHIFT) & S_CMD_STATUS_MASK;
if (val == S_CMD_STATUS_TIMEOUT) { if (val == S_CMD_STATUS_TIMEOUT) {
dev_err(iproc_i2c->device, "slave random stretch time timeout\n"); dev_err(iproc_i2c->device, "slave random stretch time timeout\n");
...@@ -329,68 +322,64 @@ static void bcm_iproc_i2c_check_slave_status( ...@@ -329,68 +322,64 @@ static void bcm_iproc_i2c_check_slave_status(
static bool bcm_iproc_i2c_slave_isr(struct bcm_iproc_i2c_dev *iproc_i2c, static bool bcm_iproc_i2c_slave_isr(struct bcm_iproc_i2c_dev *iproc_i2c,
u32 status) u32 status)
{ {
u8 value;
u32 val; u32 val;
u32 rd_status; u8 value, rx_status;
u32 tmp;
/* Start of transaction. check address and populate the direction */ /* Slave RX byte receive */
if (iproc_i2c->xfer_dir == I2C_SLAVE_DIR_NONE) { if (status & BIT(IS_S_RX_EVENT_SHIFT)) {
tmp = iproc_i2c_rd_reg(iproc_i2c, S_RX_OFFSET); val = iproc_i2c_rd_reg(iproc_i2c, S_RX_OFFSET);
rd_status = (tmp >> S_RX_STATUS_SHIFT) & S_RX_STATUS_MASK; rx_status = (val >> S_RX_STATUS_SHIFT) & S_RX_STATUS_MASK;
/* This condition checks whether the request is a new request */ if (rx_status == I2C_SLAVE_RX_START) {
if (((rd_status == I2C_SLAVE_RX_START) && /* Start of SMBUS for Master write */
(status & BIT(IS_S_RX_EVENT_SHIFT))) ||
((rd_status == I2C_SLAVE_RX_END) &&
(status & BIT(IS_S_RD_EVENT_SHIFT)))) {
/* Last bit is W/R bit.
* If 1 then its a read request(by master).
*/
iproc_i2c->xfer_dir = tmp & SLAVE_READ_WRITE_BIT_MASK;
if (iproc_i2c->xfer_dir == I2C_SLAVE_DIR_WRITE)
i2c_slave_event(iproc_i2c->slave,
I2C_SLAVE_READ_REQUESTED, &value);
else
i2c_slave_event(iproc_i2c->slave, i2c_slave_event(iproc_i2c->slave,
I2C_SLAVE_WRITE_REQUESTED, &value); I2C_SLAVE_WRITE_REQUESTED, &value);
}
}
/* read request from master */ val = iproc_i2c_rd_reg(iproc_i2c, S_RX_OFFSET);
if ((status & BIT(IS_S_RD_EVENT_SHIFT)) && value = (u8)((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK);
(iproc_i2c->xfer_dir == I2C_SLAVE_DIR_WRITE)) {
i2c_slave_event(iproc_i2c->slave, i2c_slave_event(iproc_i2c->slave,
I2C_SLAVE_READ_PROCESSED, &value); I2C_SLAVE_WRITE_RECEIVED, &value);
} else if (status & BIT(IS_S_RD_EVENT_SHIFT)) {
/* Start of SMBUS for Master Read */
i2c_slave_event(iproc_i2c->slave,
I2C_SLAVE_READ_REQUESTED, &value);
iproc_i2c_wr_reg(iproc_i2c, S_TX_OFFSET, value); iproc_i2c_wr_reg(iproc_i2c, S_TX_OFFSET, value);
val = BIT(S_CMD_START_BUSY_SHIFT); val = BIT(S_CMD_START_BUSY_SHIFT);
iproc_i2c_wr_reg(iproc_i2c, S_CMD_OFFSET, val); iproc_i2c_wr_reg(iproc_i2c, S_CMD_OFFSET, val);
}
/* write request from master */ /*
if ((status & BIT(IS_S_RX_EVENT_SHIFT)) && * Enable interrupt for TX FIFO becomes empty and
(iproc_i2c->xfer_dir == I2C_SLAVE_DIR_READ)) { * less than PKT_LENGTH bytes were output on the SMBUS
val = iproc_i2c_rd_reg(iproc_i2c, S_RX_OFFSET);
/* Its a write request by Master to Slave.
* We read data present in receive FIFO
*/ */
val = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET);
val |= BIT(IE_S_TX_UNDERRUN_SHIFT);
iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val);
} else {
/* Master write other than start */
value = (u8)((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK); value = (u8)((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK);
i2c_slave_event(iproc_i2c->slave, i2c_slave_event(iproc_i2c->slave,
I2C_SLAVE_WRITE_RECEIVED, &value); I2C_SLAVE_WRITE_RECEIVED, &value);
}
} else if (status & BIT(IS_S_TX_UNDERRUN_SHIFT)) {
/* Master read other than start */
i2c_slave_event(iproc_i2c->slave,
I2C_SLAVE_READ_PROCESSED, &value);
/* check the status for the last byte of the transaction */ iproc_i2c_wr_reg(iproc_i2c, S_TX_OFFSET, value);
rd_status = (val >> S_RX_STATUS_SHIFT) & S_RX_STATUS_MASK; val = BIT(S_CMD_START_BUSY_SHIFT);
if (rd_status == I2C_SLAVE_RX_END) iproc_i2c_wr_reg(iproc_i2c, S_CMD_OFFSET, val);
iproc_i2c->xfer_dir = I2C_SLAVE_DIR_NONE;
dev_dbg(iproc_i2c->device, "\nread value = 0x%x\n", value);
} }
/* Stop */ /* Stop */
if (status & BIT(IS_S_START_BUSY_SHIFT)) { if (status & BIT(IS_S_START_BUSY_SHIFT)) {
i2c_slave_event(iproc_i2c->slave, I2C_SLAVE_STOP, &value); i2c_slave_event(iproc_i2c->slave, I2C_SLAVE_STOP, &value);
iproc_i2c->xfer_dir = I2C_SLAVE_DIR_NONE; /*
* Enable interrupt for TX FIFO becomes empty and
* less than PKT_LENGTH bytes were output on the SMBUS
*/
val = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET);
val &= ~BIT(IE_S_TX_UNDERRUN_SHIFT);
iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val);
} }
/* clear interrupt status */ /* clear interrupt status */
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
*/ */
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/i2c.h> #include <linux/i2c.h>
...@@ -51,9 +53,7 @@ ...@@ -51,9 +53,7 @@
struct bcm2835_i2c_dev { struct bcm2835_i2c_dev {
struct device *dev; struct device *dev;
void __iomem *regs; void __iomem *regs;
struct clk *clk;
int irq; int irq;
u32 bus_clk_rate;
struct i2c_adapter adapter; struct i2c_adapter adapter;
struct completion completion; struct completion completion;
struct i2c_msg *curr_msg; struct i2c_msg *curr_msg;
...@@ -74,12 +74,17 @@ static inline u32 bcm2835_i2c_readl(struct bcm2835_i2c_dev *i2c_dev, u32 reg) ...@@ -74,12 +74,17 @@ static inline u32 bcm2835_i2c_readl(struct bcm2835_i2c_dev *i2c_dev, u32 reg)
return readl(i2c_dev->regs + reg); return readl(i2c_dev->regs + reg);
} }
static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev) #define to_clk_bcm2835_i2c(_hw) container_of(_hw, struct clk_bcm2835_i2c, hw)
struct clk_bcm2835_i2c {
struct clk_hw hw;
struct bcm2835_i2c_dev *i2c_dev;
};
static int clk_bcm2835_i2c_calc_divider(unsigned long rate,
unsigned long parent_rate)
{ {
u32 divider, redl, fedl; u32 divider = DIV_ROUND_UP(parent_rate, rate);
divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk),
i2c_dev->bus_clk_rate);
/* /*
* Per the datasheet, the register is always interpreted as an even * Per the datasheet, the register is always interpreted as an even
* number, by rounding down. In other words, the LSB is ignored. So, * number, by rounding down. In other words, the LSB is ignored. So,
...@@ -88,12 +93,23 @@ static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev) ...@@ -88,12 +93,23 @@ static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev)
if (divider & 1) if (divider & 1)
divider++; divider++;
if ((divider < BCM2835_I2C_CDIV_MIN) || if ((divider < BCM2835_I2C_CDIV_MIN) ||
(divider > BCM2835_I2C_CDIV_MAX)) { (divider > BCM2835_I2C_CDIV_MAX))
dev_err_ratelimited(i2c_dev->dev, "Invalid clock-frequency\n");
return -EINVAL; return -EINVAL;
}
bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider); return divider;
}
static int clk_bcm2835_i2c_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_bcm2835_i2c *div = to_clk_bcm2835_i2c(hw);
u32 redl, fedl;
u32 divider = clk_bcm2835_i2c_calc_divider(rate, parent_rate);
if (divider == -EINVAL)
return -EINVAL;
bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_DIV, divider);
/* /*
* Number of core clocks to wait after falling edge before * Number of core clocks to wait after falling edge before
...@@ -108,12 +124,65 @@ static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev) ...@@ -108,12 +124,65 @@ static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev)
*/ */
redl = max(divider / 4, 1u); redl = max(divider / 4, 1u);
bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DEL, bcm2835_i2c_writel(div->i2c_dev, BCM2835_I2C_DEL,
(fedl << BCM2835_I2C_FEDL_SHIFT) | (fedl << BCM2835_I2C_FEDL_SHIFT) |
(redl << BCM2835_I2C_REDL_SHIFT)); (redl << BCM2835_I2C_REDL_SHIFT));
return 0; return 0;
} }
static long clk_bcm2835_i2c_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
u32 divider = clk_bcm2835_i2c_calc_divider(rate, *parent_rate);
return DIV_ROUND_UP(*parent_rate, divider);
}
static unsigned long clk_bcm2835_i2c_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_bcm2835_i2c *div = to_clk_bcm2835_i2c(hw);
u32 divider = bcm2835_i2c_readl(div->i2c_dev, BCM2835_I2C_DIV);
return DIV_ROUND_UP(parent_rate, divider);
}
static const struct clk_ops clk_bcm2835_i2c_ops = {
.set_rate = clk_bcm2835_i2c_set_rate,
.round_rate = clk_bcm2835_i2c_round_rate,
.recalc_rate = clk_bcm2835_i2c_recalc_rate,
};
static struct clk *bcm2835_i2c_register_div(struct device *dev,
struct clk *mclk,
struct bcm2835_i2c_dev *i2c_dev)
{
struct clk_init_data init;
struct clk_bcm2835_i2c *priv;
char name[32];
const char *mclk_name;
snprintf(name, sizeof(name), "%s_div", dev_name(dev));
mclk_name = __clk_get_name(mclk);
init.ops = &clk_bcm2835_i2c_ops;
init.name = name;
init.parent_names = (const char* []) { mclk_name };
init.num_parents = 1;
init.flags = 0;
priv = devm_kzalloc(dev, sizeof(struct clk_bcm2835_i2c), GFP_KERNEL);
if (priv == NULL)
return ERR_PTR(-ENOMEM);
priv->hw.init = &init;
priv->i2c_dev = i2c_dev;
clk_hw_register_clkdev(&priv->hw, "div", dev_name(dev));
return devm_clk_register(dev, &priv->hw);
}
static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev) static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev)
{ {
u32 val; u32 val;
...@@ -271,7 +340,7 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], ...@@ -271,7 +340,7 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
{ {
struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap); struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
unsigned long time_left; unsigned long time_left;
int i, ret; int i;
for (i = 0; i < (num - 1); i++) for (i = 0; i < (num - 1); i++)
if (msgs[i].flags & I2C_M_RD) { if (msgs[i].flags & I2C_M_RD) {
...@@ -280,10 +349,6 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], ...@@ -280,10 +349,6 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
ret = bcm2835_i2c_set_divider(i2c_dev);
if (ret)
return ret;
i2c_dev->curr_msg = msgs; i2c_dev->curr_msg = msgs;
i2c_dev->num_msgs = num; i2c_dev->num_msgs = num;
reinit_completion(&i2c_dev->completion); reinit_completion(&i2c_dev->completion);
...@@ -338,6 +403,9 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) ...@@ -338,6 +403,9 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
struct resource *mem, *irq; struct resource *mem, *irq;
int ret; int ret;
struct i2c_adapter *adap; struct i2c_adapter *adap;
struct clk *bus_clk;
struct clk *mclk;
u32 bus_clk_rate;
i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
if (!i2c_dev) if (!i2c_dev)
...@@ -351,19 +419,38 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) ...@@ -351,19 +419,38 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
if (IS_ERR(i2c_dev->regs)) if (IS_ERR(i2c_dev->regs))
return PTR_ERR(i2c_dev->regs); return PTR_ERR(i2c_dev->regs);
i2c_dev->clk = devm_clk_get(&pdev->dev, NULL); mclk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(i2c_dev->clk)) { if (IS_ERR(mclk)) {
if (PTR_ERR(i2c_dev->clk) != -EPROBE_DEFER) if (PTR_ERR(mclk) != -EPROBE_DEFER)
dev_err(&pdev->dev, "Could not get clock\n"); dev_err(&pdev->dev, "Could not get clock\n");
return PTR_ERR(i2c_dev->clk); return PTR_ERR(mclk);
}
bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk, i2c_dev);
if (IS_ERR(bus_clk)) {
dev_err(&pdev->dev, "Could not register clock\n");
return PTR_ERR(bus_clk);
} }
ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
&i2c_dev->bus_clk_rate); &bus_clk_rate);
if (ret < 0) { if (ret < 0) {
dev_warn(&pdev->dev, dev_warn(&pdev->dev,
"Could not read clock-frequency property\n"); "Could not read clock-frequency property\n");
i2c_dev->bus_clk_rate = 100000; bus_clk_rate = 100000;
}
ret = clk_set_rate_exclusive(bus_clk, bus_clk_rate);
if (ret < 0) {
dev_err(&pdev->dev, "Could not set clock frequency\n");
return ret;
}
ret = clk_prepare_enable(bus_clk);
if (ret) {
dev_err(&pdev->dev, "Couldn't prepare clock");
return ret;
} }
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
...@@ -402,6 +489,10 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) ...@@ -402,6 +489,10 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
static int bcm2835_i2c_remove(struct platform_device *pdev) static int bcm2835_i2c_remove(struct platform_device *pdev)
{ {
struct bcm2835_i2c_dev *i2c_dev = platform_get_drvdata(pdev); struct bcm2835_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
struct clk *bus_clk = devm_clk_get(i2c_dev->dev, "div");
clk_rate_exclusive_put(bus_clk);
clk_disable_unprepare(bus_clk);
free_irq(i2c_dev->irq, i2c_dev); free_irq(i2c_dev->irq, i2c_dev);
i2c_del_adapter(&i2c_dev->adapter); i2c_del_adapter(&i2c_dev->adapter);
......
...@@ -531,7 +531,9 @@ static int cpm_i2c_setup(struct cpm_i2c *cpm) ...@@ -531,7 +531,9 @@ static int cpm_i2c_setup(struct cpm_i2c *cpm)
} }
out_be32(&rbdf[i].cbd_bufaddr, ((cpm->rxdma[i] + 1) & ~1)); out_be32(&rbdf[i].cbd_bufaddr, ((cpm->rxdma[i] + 1) & ~1));
cpm->txbuf[i] = (unsigned char *)dma_alloc_coherent(&cpm->ofdev->dev, CPM_MAX_READ + 1, &cpm->txdma[i], GFP_KERNEL); cpm->txbuf[i] = dma_alloc_coherent(&cpm->ofdev->dev,
CPM_MAX_READ + 1,
&cpm->txdma[i], GFP_KERNEL);
if (!cpm->txbuf[i]) { if (!cpm->txbuf[i]) {
ret = -ENOMEM; ret = -ENOMEM;
goto out_muram; goto out_muram;
......
...@@ -658,13 +658,29 @@ static const struct i2c_algorithm fsi_i2c_algorithm = { ...@@ -658,13 +658,29 @@ static const struct i2c_algorithm fsi_i2c_algorithm = {
.functionality = fsi_i2c_functionality, .functionality = fsi_i2c_functionality,
}; };
static struct device_node *fsi_i2c_find_port_of_node(struct device_node *fsi,
int port)
{
struct device_node *np;
u32 port_no;
int rc;
for_each_child_of_node(fsi, np) {
rc = of_property_read_u32(np, "reg", &port_no);
if (!rc && port_no == port)
return np;
}
return NULL;
}
static int fsi_i2c_probe(struct device *dev) static int fsi_i2c_probe(struct device *dev)
{ {
struct fsi_i2c_master *i2c; struct fsi_i2c_master *i2c;
struct fsi_i2c_port *port; struct fsi_i2c_port *port;
struct device_node *np; struct device_node *np;
u32 port_no, ports, stat;
int rc; int rc;
u32 port_no;
i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL); i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL);
if (!i2c) if (!i2c)
...@@ -678,10 +694,16 @@ static int fsi_i2c_probe(struct device *dev) ...@@ -678,10 +694,16 @@ static int fsi_i2c_probe(struct device *dev)
if (rc) if (rc)
return rc; return rc;
/* Add adapter for each i2c port of the master. */ rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_STAT, &stat);
for_each_available_child_of_node(dev->of_node, np) { if (rc)
rc = of_property_read_u32(np, "reg", &port_no); return rc;
if (rc || port_no > USHRT_MAX)
ports = FIELD_GET(I2C_STAT_MAX_PORT, stat) + 1;
dev_dbg(dev, "I2C master has %d ports\n", ports);
for (port_no = 0; port_no < ports; port_no++) {
np = fsi_i2c_find_port_of_node(dev->of_node, port_no);
if (np && !of_device_is_available(np))
continue; continue;
port = kzalloc(sizeof(*port), GFP_KERNEL); port = kzalloc(sizeof(*port), GFP_KERNEL);
......
This diff is collapsed.
...@@ -1220,8 +1220,7 @@ static int i2c_imx_remove(struct platform_device *pdev) ...@@ -1220,8 +1220,7 @@ static int i2c_imx_remove(struct platform_device *pdev)
return 0; return 0;
} }
#ifdef CONFIG_PM static int __maybe_unused i2c_imx_runtime_suspend(struct device *dev)
static int i2c_imx_runtime_suspend(struct device *dev)
{ {
struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev); struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
...@@ -1230,7 +1229,7 @@ static int i2c_imx_runtime_suspend(struct device *dev) ...@@ -1230,7 +1229,7 @@ static int i2c_imx_runtime_suspend(struct device *dev)
return 0; return 0;
} }
static int i2c_imx_runtime_resume(struct device *dev) static int __maybe_unused i2c_imx_runtime_resume(struct device *dev)
{ {
struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev); struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
int ret; int ret;
...@@ -1246,17 +1245,13 @@ static const struct dev_pm_ops i2c_imx_pm_ops = { ...@@ -1246,17 +1245,13 @@ static const struct dev_pm_ops i2c_imx_pm_ops = {
SET_RUNTIME_PM_OPS(i2c_imx_runtime_suspend, SET_RUNTIME_PM_OPS(i2c_imx_runtime_suspend,
i2c_imx_runtime_resume, NULL) i2c_imx_runtime_resume, NULL)
}; };
#define I2C_IMX_PM_OPS (&i2c_imx_pm_ops)
#else
#define I2C_IMX_PM_OPS NULL
#endif /* CONFIG_PM */
static struct platform_driver i2c_imx_driver = { static struct platform_driver i2c_imx_driver = {
.probe = i2c_imx_probe, .probe = i2c_imx_probe,
.remove = i2c_imx_remove, .remove = i2c_imx_remove,
.driver = { .driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.pm = I2C_IMX_PM_OPS, .pm = &i2c_imx_pm_ops,
.of_match_table = i2c_imx_dt_ids, .of_match_table = i2c_imx_dt_ids,
}, },
.id_table = imx_i2c_devtype, .id_table = imx_i2c_devtype,
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio.h> #include <linux/gpio/consumer.h>
#include "i2c-iop3xx.h" #include "i2c-iop3xx.h"
...@@ -68,17 +68,16 @@ iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap) ...@@ -68,17 +68,16 @@ iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
/* /*
* Every time unit enable is asserted, GPOD needs to be cleared * Every time unit enable is asserted, GPOD needs to be cleared
* on IOP3XX to avoid data corruption on the bus. * on IOP3XX to avoid data corruption on the bus. We use the
* gpiod_set_raw_value() to make sure the 0 hits the hardware
* GPOD register. These descriptors are only passed along to
* the device if this is necessary.
*/ */
#if defined(CONFIG_ARCH_IOP32X) || defined(CONFIG_ARCH_IOP33X) if (iop3xx_adap->gpio_scl)
if (iop3xx_adap->id == 0) { gpiod_set_raw_value(iop3xx_adap->gpio_scl, 0);
gpio_set_value(7, 0); if (iop3xx_adap->gpio_sda)
gpio_set_value(6, 0); gpiod_set_raw_value(iop3xx_adap->gpio_sda, 0);
} else {
gpio_set_value(5, 0);
gpio_set_value(4, 0);
}
#endif
/* NB SR bits not same position as CR IE bits :-( */ /* NB SR bits not same position as CR IE bits :-( */
iop3xx_adap->SR_enabled = iop3xx_adap->SR_enabled =
IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD |
...@@ -431,6 +430,17 @@ iop3xx_i2c_probe(struct platform_device *pdev) ...@@ -431,6 +430,17 @@ iop3xx_i2c_probe(struct platform_device *pdev)
goto free_adapter; goto free_adapter;
} }
adapter_data->gpio_scl = devm_gpiod_get_optional(&pdev->dev,
"scl",
GPIOD_ASIS);
if (IS_ERR(adapter_data->gpio_scl))
return PTR_ERR(adapter_data->gpio_scl);
adapter_data->gpio_sda = devm_gpiod_get_optional(&pdev->dev,
"sda",
GPIOD_ASIS);
if (IS_ERR(adapter_data->gpio_sda))
return PTR_ERR(adapter_data->gpio_sda);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) { if (!res) {
ret = -ENODEV; ret = -ENODEV;
......
...@@ -92,6 +92,8 @@ struct i2c_algo_iop3xx_data { ...@@ -92,6 +92,8 @@ struct i2c_algo_iop3xx_data {
spinlock_t lock; spinlock_t lock;
u32 SR_enabled, SR_received; u32 SR_enabled, SR_received;
int id; int id;
struct gpio_desc *gpio_scl;
struct gpio_desc *gpio_sda;
}; };
#endif /* I2C_IOP3XX_H */ #endif /* I2C_IOP3XX_H */
// SPDX-License-Identifier: GPL-2.0
/*
* drivers/i2c/busses/i2c-mt7621.c
*
* Copyright (C) 2013 Steven Liu <steven_liu@mediatek.com>
* Copyright (C) 2016 Michael Lee <igvtee@gmail.com>
* Copyright (C) 2018 Jan Breuer <jan.breuer@jaybee.cz>
*
* Improve driver for i2cdetect from i2c-tools to detect i2c devices on the bus.
* (C) 2014 Sittisak <sittisaks@hotmail.com>
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/reset.h>
#define REG_SM0CFG2_REG 0x28
#define REG_SM0CTL0_REG 0x40
#define REG_SM0CTL1_REG 0x44
#define REG_SM0D0_REG 0x50
#define REG_SM0D1_REG 0x54
#define REG_PINTEN_REG 0x5c
#define REG_PINTST_REG 0x60
#define REG_PINTCL_REG 0x64
/* REG_SM0CFG2_REG */
#define SM0CFG2_IS_AUTOMODE BIT(0)
/* REG_SM0CTL0_REG */
#define SM0CTL0_ODRAIN BIT(31)
#define SM0CTL0_CLK_DIV_MASK (0x7ff << 16)
#define SM0CTL0_CLK_DIV_MAX 0x7ff
#define SM0CTL0_CS_STATUS BIT(4)
#define SM0CTL0_SCL_STATE BIT(3)
#define SM0CTL0_SDA_STATE BIT(2)
#define SM0CTL0_EN BIT(1)
#define SM0CTL0_SCL_STRETCH BIT(0)
/* REG_SM0CTL1_REG */
#define SM0CTL1_ACK_MASK (0xff << 16)
#define SM0CTL1_PGLEN_MASK (0x7 << 8)
#define SM0CTL1_PGLEN(x) ((((x) - 1) << 8) & SM0CTL1_PGLEN_MASK)
#define SM0CTL1_READ (5 << 4)
#define SM0CTL1_READ_LAST (4 << 4)
#define SM0CTL1_STOP (3 << 4)
#define SM0CTL1_WRITE (2 << 4)
#define SM0CTL1_START (1 << 4)
#define SM0CTL1_MODE_MASK (0x7 << 4)
#define SM0CTL1_TRI BIT(0)
/* timeout waiting for I2C devices to respond */
#define TIMEOUT_MS 1000
struct mtk_i2c {
void __iomem *base;
struct device *dev;
struct i2c_adapter adap;
u32 bus_freq;
u32 clk_div;
u32 flags;
struct clk *clk;
};
static int mtk_i2c_wait_idle(struct mtk_i2c *i2c)
{
int ret;
u32 val;
ret = readl_relaxed_poll_timeout(i2c->base + REG_SM0CTL1_REG,
val, !(val & SM0CTL1_TRI),
10, TIMEOUT_MS * 1000);
if (ret)
dev_dbg(i2c->dev, "idle err(%d)\n", ret);
return ret;
}
static void mtk_i2c_reset(struct mtk_i2c *i2c)
{
int ret;
ret = device_reset(i2c->adap.dev.parent);
if (ret)
dev_err(i2c->dev, "I2C reset failed!\n");
/*
* Don't set SM0CTL0_ODRAIN as its bit meaning is inverted. To
* configure open-drain mode, this bit needs to be cleared.
*/
iowrite32(((i2c->clk_div << 16) & SM0CTL0_CLK_DIV_MASK) | SM0CTL0_EN |
SM0CTL0_SCL_STRETCH, i2c->base + REG_SM0CTL0_REG);
iowrite32(0, i2c->base + REG_SM0CFG2_REG);
}
static void mtk_i2c_dump_reg(struct mtk_i2c *i2c)
{
dev_dbg(i2c->dev,
"SM0CFG2 %08x, SM0CTL0 %08x, SM0CTL1 %08x, SM0D0 %08x, SM0D1 %08x\n",
ioread32(i2c->base + REG_SM0CFG2_REG),
ioread32(i2c->base + REG_SM0CTL0_REG),
ioread32(i2c->base + REG_SM0CTL1_REG),
ioread32(i2c->base + REG_SM0D0_REG),
ioread32(i2c->base + REG_SM0D1_REG));
}
static int mtk_i2c_check_ack(struct mtk_i2c *i2c, u32 expected)
{
u32 ack = readl_relaxed(i2c->base + REG_SM0CTL1_REG);
u32 ack_expected = (expected << 16) & SM0CTL1_ACK_MASK;
return ((ack & ack_expected) == ack_expected) ? 0 : -ENXIO;
}
static int mtk_i2c_master_start(struct mtk_i2c *i2c)
{
iowrite32(SM0CTL1_START | SM0CTL1_TRI, i2c->base + REG_SM0CTL1_REG);
return mtk_i2c_wait_idle(i2c);
}
static int mtk_i2c_master_stop(struct mtk_i2c *i2c)
{
iowrite32(SM0CTL1_STOP | SM0CTL1_TRI, i2c->base + REG_SM0CTL1_REG);
return mtk_i2c_wait_idle(i2c);
}
static int mtk_i2c_master_cmd(struct mtk_i2c *i2c, u32 cmd, int page_len)
{
iowrite32(cmd | SM0CTL1_TRI | SM0CTL1_PGLEN(page_len),
i2c->base + REG_SM0CTL1_REG);
return mtk_i2c_wait_idle(i2c);
}
static int mtk_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num)
{
struct mtk_i2c *i2c;
struct i2c_msg *pmsg;
u16 addr;
int i, j, ret, len, page_len;
u32 cmd;
u32 data[2];
i2c = i2c_get_adapdata(adap);
for (i = 0; i < num; i++) {
pmsg = &msgs[i];
/* wait hardware idle */
ret = mtk_i2c_wait_idle(i2c);
if (ret)
goto err_timeout;
/* start sequence */
ret = mtk_i2c_master_start(i2c);
if (ret)
goto err_timeout;
/* write address */
if (pmsg->flags & I2C_M_TEN) {
/* 10 bits address */
addr = 0xf0 | ((pmsg->addr >> 7) & 0x06);
addr |= (pmsg->addr & 0xff) << 8;
if (pmsg->flags & I2C_M_RD)
addr |= 1;
iowrite32(addr, i2c->base + REG_SM0D0_REG);
ret = mtk_i2c_master_cmd(i2c, SM0CTL1_WRITE, 2);
if (ret)
goto err_timeout;
} else {
/* 7 bits address */
addr = i2c_8bit_addr_from_msg(pmsg);
iowrite32(addr, i2c->base + REG_SM0D0_REG);
ret = mtk_i2c_master_cmd(i2c, SM0CTL1_WRITE, 1);
if (ret)
goto err_timeout;
}
/* check address ACK */
if (!(pmsg->flags & I2C_M_IGNORE_NAK)) {
ret = mtk_i2c_check_ack(i2c, BIT(0));
if (ret)
goto err_ack;
}
/* transfer data */
for (len = pmsg->len, j = 0; len > 0; len -= 8, j += 8) {
page_len = (len >= 8) ? 8 : len;
if (pmsg->flags & I2C_M_RD) {
cmd = (len > 8) ?
SM0CTL1_READ : SM0CTL1_READ_LAST;
} else {
memcpy(data, &pmsg->buf[j], page_len);
iowrite32(data[0], i2c->base + REG_SM0D0_REG);
iowrite32(data[1], i2c->base + REG_SM0D1_REG);
cmd = SM0CTL1_WRITE;
}
ret = mtk_i2c_master_cmd(i2c, cmd, page_len);
if (ret)
goto err_timeout;
if (pmsg->flags & I2C_M_RD) {
data[0] = ioread32(i2c->base + REG_SM0D0_REG);
data[1] = ioread32(i2c->base + REG_SM0D1_REG);
memcpy(&pmsg->buf[j], data, page_len);
} else {
if (!(pmsg->flags & I2C_M_IGNORE_NAK)) {
ret = mtk_i2c_check_ack(i2c,
(1 << page_len)
- 1);
if (ret)
goto err_ack;
}
}
}
}
ret = mtk_i2c_master_stop(i2c);
if (ret)
goto err_timeout;
/* the return value is number of executed messages */
return i;
err_ack:
ret = mtk_i2c_master_stop(i2c);
if (ret)
goto err_timeout;
return -ENXIO;
err_timeout:
mtk_i2c_dump_reg(i2c);
mtk_i2c_reset(i2c);
return ret;
}
static u32 mtk_i2c_func(struct i2c_adapter *a)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING;
}
static const struct i2c_algorithm mtk_i2c_algo = {
.master_xfer = mtk_i2c_master_xfer,
.functionality = mtk_i2c_func,
};
static const struct of_device_id i2c_mtk_dt_ids[] = {
{ .compatible = "mediatek,mt7621-i2c" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, i2c_mtk_dt_ids);
static void mtk_i2c_init(struct mtk_i2c *i2c)
{
i2c->clk_div = clk_get_rate(i2c->clk) / i2c->bus_freq - 1;
if (i2c->clk_div < 99)
i2c->clk_div = 99;
if (i2c->clk_div > SM0CTL0_CLK_DIV_MAX)
i2c->clk_div = SM0CTL0_CLK_DIV_MAX;
mtk_i2c_reset(i2c);
}
static int mtk_i2c_probe(struct platform_device *pdev)
{
struct resource *res;
struct mtk_i2c *i2c;
struct i2c_adapter *adap;
int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
i2c = devm_kzalloc(&pdev->dev, sizeof(struct mtk_i2c), GFP_KERNEL);
if (!i2c)
return -ENOMEM;
i2c->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(i2c->base))
return PTR_ERR(i2c->base);
i2c->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(i2c->clk)) {
dev_err(&pdev->dev, "no clock defined\n");
return PTR_ERR(i2c->clk);
}
ret = clk_prepare_enable(i2c->clk);
if (ret) {
dev_err(&pdev->dev, "Unable to enable clock\n");
return ret;
}
i2c->dev = &pdev->dev;
if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
&i2c->bus_freq))
i2c->bus_freq = 100000;
if (i2c->bus_freq == 0) {
dev_warn(i2c->dev, "clock-frequency 0 not supported\n");
return -EINVAL;
}
adap = &i2c->adap;
adap->owner = THIS_MODULE;
adap->algo = &mtk_i2c_algo;
adap->retries = 3;
adap->dev.parent = &pdev->dev;
i2c_set_adapdata(adap, i2c);
adap->dev.of_node = pdev->dev.of_node;
strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name));
platform_set_drvdata(pdev, i2c);
mtk_i2c_init(i2c);
ret = i2c_add_adapter(adap);
if (ret < 0)
return ret;
dev_info(&pdev->dev, "clock %u kHz\n", i2c->bus_freq / 1000);
return ret;
}
static int mtk_i2c_remove(struct platform_device *pdev)
{
struct mtk_i2c *i2c = platform_get_drvdata(pdev);
clk_disable_unprepare(i2c->clk);
i2c_del_adapter(&i2c->adap);
return 0;
}
static struct platform_driver mtk_i2c_driver = {
.probe = mtk_i2c_probe,
.remove = mtk_i2c_remove,
.driver = {
.name = "i2c-mt7621",
.of_match_table = i2c_mtk_dt_ids,
},
};
module_platform_driver(mtk_i2c_driver);
MODULE_AUTHOR("Steven Liu");
MODULE_DESCRIPTION("MT7621 I2C host driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:MT7621-I2C");
...@@ -51,6 +51,7 @@ struct gpu_i2c_dev { ...@@ -51,6 +51,7 @@ struct gpu_i2c_dev {
void __iomem *regs; void __iomem *regs;
struct i2c_adapter adapter; struct i2c_adapter adapter;
struct i2c_board_info *gpu_ccgx_ucsi; struct i2c_board_info *gpu_ccgx_ucsi;
struct i2c_client *ccgx_client;
}; };
static void gpu_enable_i2c_bus(struct gpu_i2c_dev *i2cd) static void gpu_enable_i2c_bus(struct gpu_i2c_dev *i2cd)
...@@ -169,12 +170,14 @@ static int gpu_i2c_master_xfer(struct i2c_adapter *adap, ...@@ -169,12 +170,14 @@ static int gpu_i2c_master_xfer(struct i2c_adapter *adap,
{ {
struct gpu_i2c_dev *i2cd = i2c_get_adapdata(adap); struct gpu_i2c_dev *i2cd = i2c_get_adapdata(adap);
int status, status2; int status, status2;
bool send_stop = true;
int i, j; int i, j;
/* /*
* The controller supports maximum 4 byte read due to known * The controller supports maximum 4 byte read due to known
* limitation of sending STOP after every read. * limitation of sending STOP after every read.
*/ */
pm_runtime_get_sync(i2cd->dev);
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
if (msgs[i].flags & I2C_M_RD) { if (msgs[i].flags & I2C_M_RD) {
/* program client address before starting read */ /* program client address before starting read */
...@@ -182,37 +185,42 @@ static int gpu_i2c_master_xfer(struct i2c_adapter *adap, ...@@ -182,37 +185,42 @@ static int gpu_i2c_master_xfer(struct i2c_adapter *adap,
/* gpu_i2c_read has implicit start */ /* gpu_i2c_read has implicit start */
status = gpu_i2c_read(i2cd, msgs[i].buf, msgs[i].len); status = gpu_i2c_read(i2cd, msgs[i].buf, msgs[i].len);
if (status < 0) if (status < 0)
goto stop; goto exit;
} else { } else {
u8 addr = i2c_8bit_addr_from_msg(msgs + i); u8 addr = i2c_8bit_addr_from_msg(msgs + i);
status = gpu_i2c_start(i2cd); status = gpu_i2c_start(i2cd);
if (status < 0) { if (status < 0) {
if (i == 0) if (i == 0)
return status; send_stop = false;
goto stop; goto exit;
} }
status = gpu_i2c_write(i2cd, addr); status = gpu_i2c_write(i2cd, addr);
if (status < 0) if (status < 0)
goto stop; goto exit;
for (j = 0; j < msgs[i].len; j++) { for (j = 0; j < msgs[i].len; j++) {
status = gpu_i2c_write(i2cd, msgs[i].buf[j]); status = gpu_i2c_write(i2cd, msgs[i].buf[j]);
if (status < 0) if (status < 0)
goto stop; goto exit;
} }
} }
} }
send_stop = false;
status = gpu_i2c_stop(i2cd); status = gpu_i2c_stop(i2cd);
if (status < 0) if (status < 0)
return status; goto exit;
return i; status = i;
stop: exit:
if (send_stop) {
status2 = gpu_i2c_stop(i2cd); status2 = gpu_i2c_stop(i2cd);
if (status2 < 0) if (status2 < 0)
dev_err(i2cd->dev, "i2c stop failed %d\n", status2); dev_err(i2cd->dev, "i2c stop failed %d\n", status2);
}
pm_runtime_mark_last_busy(i2cd->dev);
pm_runtime_put_autosuspend(i2cd->dev);
return status; return status;
} }
...@@ -261,8 +269,6 @@ static const struct property_entry ccgx_props[] = { ...@@ -261,8 +269,6 @@ static const struct property_entry ccgx_props[] = {
static int gpu_populate_client(struct gpu_i2c_dev *i2cd, int irq) static int gpu_populate_client(struct gpu_i2c_dev *i2cd, int irq)
{ {
struct i2c_client *ccgx_client;
i2cd->gpu_ccgx_ucsi = devm_kzalloc(i2cd->dev, i2cd->gpu_ccgx_ucsi = devm_kzalloc(i2cd->dev,
sizeof(*i2cd->gpu_ccgx_ucsi), sizeof(*i2cd->gpu_ccgx_ucsi),
GFP_KERNEL); GFP_KERNEL);
...@@ -274,8 +280,8 @@ static int gpu_populate_client(struct gpu_i2c_dev *i2cd, int irq) ...@@ -274,8 +280,8 @@ static int gpu_populate_client(struct gpu_i2c_dev *i2cd, int irq)
i2cd->gpu_ccgx_ucsi->addr = 0x8; i2cd->gpu_ccgx_ucsi->addr = 0x8;
i2cd->gpu_ccgx_ucsi->irq = irq; i2cd->gpu_ccgx_ucsi->irq = irq;
i2cd->gpu_ccgx_ucsi->properties = ccgx_props; i2cd->gpu_ccgx_ucsi->properties = ccgx_props;
ccgx_client = i2c_new_device(&i2cd->adapter, i2cd->gpu_ccgx_ucsi); i2cd->ccgx_client = i2c_new_device(&i2cd->adapter, i2cd->gpu_ccgx_ucsi);
if (!ccgx_client) if (!i2cd->ccgx_client)
return -ENODEV; return -ENODEV;
return 0; return 0;
...@@ -332,6 +338,11 @@ static int gpu_i2c_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -332,6 +338,11 @@ static int gpu_i2c_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto del_adapter; goto del_adapter;
} }
pm_runtime_set_autosuspend_delay(&pdev->dev, 3000);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev);
pm_runtime_allow(&pdev->dev);
return 0; return 0;
del_adapter: del_adapter:
...@@ -345,19 +356,38 @@ static void gpu_i2c_remove(struct pci_dev *pdev) ...@@ -345,19 +356,38 @@ static void gpu_i2c_remove(struct pci_dev *pdev)
{ {
struct gpu_i2c_dev *i2cd = dev_get_drvdata(&pdev->dev); struct gpu_i2c_dev *i2cd = dev_get_drvdata(&pdev->dev);
pm_runtime_get_noresume(i2cd->dev);
i2c_del_adapter(&i2cd->adapter); i2c_del_adapter(&i2cd->adapter);
pci_free_irq_vectors(pdev); pci_free_irq_vectors(pdev);
} }
/*
* We need gpu_i2c_suspend() even if it is stub, for runtime pm to work
* correctly. Without it, lspci shows runtime pm status as "D0" for the card.
* Documentation/power/pci.txt also insists for driver to provide this.
*/
static __maybe_unused int gpu_i2c_suspend(struct device *dev)
{
return 0;
}
static __maybe_unused int gpu_i2c_resume(struct device *dev) static __maybe_unused int gpu_i2c_resume(struct device *dev)
{ {
struct gpu_i2c_dev *i2cd = dev_get_drvdata(dev); struct gpu_i2c_dev *i2cd = dev_get_drvdata(dev);
gpu_enable_i2c_bus(i2cd); gpu_enable_i2c_bus(i2cd);
/*
* Runtime resume ccgx client so that it can see for any
* connector change event. Old ccg firmware has known
* issue of not triggering interrupt when a device is
* connected to runtime resume the controller.
*/
pm_request_resume(&i2cd->ccgx_client->dev);
return 0; return 0;
} }
static UNIVERSAL_DEV_PM_OPS(gpu_i2c_driver_pm, NULL, gpu_i2c_resume, NULL); static UNIVERSAL_DEV_PM_OPS(gpu_i2c_driver_pm, gpu_i2c_suspend, gpu_i2c_resume,
NULL);
static struct pci_driver gpu_i2c_driver = { static struct pci_driver gpu_i2c_driver = {
.name = "nvidia-gpu", .name = "nvidia-gpu",
......
...@@ -35,6 +35,7 @@ struct ocores_i2c { ...@@ -35,6 +35,7 @@ struct ocores_i2c {
int iobase; int iobase;
u32 reg_shift; u32 reg_shift;
u32 reg_io_width; u32 reg_io_width;
unsigned long flags;
wait_queue_head_t wait; wait_queue_head_t wait;
struct i2c_adapter adap; struct i2c_adapter adap;
struct i2c_msg *msg; struct i2c_msg *msg;
...@@ -82,6 +83,9 @@ struct ocores_i2c { ...@@ -82,6 +83,9 @@ struct ocores_i2c {
#define TYPE_OCORES 0 #define TYPE_OCORES 0
#define TYPE_GRLIB 1 #define TYPE_GRLIB 1
#define TYPE_SIFIVE_REV0 2
#define OCORES_FLAG_BROKEN_IRQ BIT(1) /* Broken IRQ for FU540-C000 SoC */
static void oc_setreg_8(struct ocores_i2c *i2c, int reg, u8 value) static void oc_setreg_8(struct ocores_i2c *i2c, int reg, u8 value)
{ {
...@@ -235,9 +239,12 @@ static irqreturn_t ocores_isr(int irq, void *dev_id) ...@@ -235,9 +239,12 @@ static irqreturn_t ocores_isr(int irq, void *dev_id)
struct ocores_i2c *i2c = dev_id; struct ocores_i2c *i2c = dev_id;
u8 stat = oc_getreg(i2c, OCI2C_STATUS); u8 stat = oc_getreg(i2c, OCI2C_STATUS);
if (!(stat & OCI2C_STAT_IF)) if (i2c->flags & OCORES_FLAG_BROKEN_IRQ) {
if ((stat & OCI2C_STAT_IF) && !(stat & OCI2C_STAT_BUSY))
return IRQ_NONE; return IRQ_NONE;
} else if (!(stat & OCI2C_STAT_IF)) {
return IRQ_NONE;
}
ocores_process(i2c, stat); ocores_process(i2c, stat);
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -352,6 +359,11 @@ static void ocores_process_polling(struct ocores_i2c *i2c) ...@@ -352,6 +359,11 @@ static void ocores_process_polling(struct ocores_i2c *i2c)
ret = ocores_isr(-1, i2c); ret = ocores_isr(-1, i2c);
if (ret == IRQ_NONE) if (ret == IRQ_NONE)
break; /* all messages have been transferred */ break; /* all messages have been transferred */
else {
if (i2c->flags & OCORES_FLAG_BROKEN_IRQ)
if (i2c->state == STATE_DONE)
break;
}
} }
} }
...@@ -462,6 +474,14 @@ static const struct of_device_id ocores_i2c_match[] = { ...@@ -462,6 +474,14 @@ static const struct of_device_id ocores_i2c_match[] = {
.compatible = "aeroflexgaisler,i2cmst", .compatible = "aeroflexgaisler,i2cmst",
.data = (void *)TYPE_GRLIB, .data = (void *)TYPE_GRLIB,
}, },
{
.compatible = "sifive,fu540-c000-i2c",
.data = (void *)TYPE_SIFIVE_REV0,
},
{
.compatible = "sifive,i2c0",
.data = (void *)TYPE_SIFIVE_REV0,
},
{}, {},
}; };
MODULE_DEVICE_TABLE(of, ocores_i2c_match); MODULE_DEVICE_TABLE(of, ocores_i2c_match);
...@@ -586,6 +606,7 @@ static int ocores_i2c_probe(struct platform_device *pdev) ...@@ -586,6 +606,7 @@ static int ocores_i2c_probe(struct platform_device *pdev)
{ {
struct ocores_i2c *i2c; struct ocores_i2c *i2c;
struct ocores_i2c_platform_data *pdata; struct ocores_i2c_platform_data *pdata;
const struct of_device_id *match;
struct resource *res; struct resource *res;
int irq; int irq;
int ret; int ret;
...@@ -668,6 +689,14 @@ static int ocores_i2c_probe(struct platform_device *pdev) ...@@ -668,6 +689,14 @@ static int ocores_i2c_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq == -ENXIO) { if (irq == -ENXIO) {
ocores_algorithm.master_xfer = ocores_xfer_polling; ocores_algorithm.master_xfer = ocores_xfer_polling;
/*
* Set in OCORES_FLAG_BROKEN_IRQ to enable workaround for
* FU540-C000 SoC in polling mode.
*/
match = of_match_node(ocores_i2c_match, pdev->dev.of_node);
if (match && (long)match->data == TYPE_SIFIVE_REV0)
i2c->flags |= OCORES_FLAG_BROKEN_IRQ;
} else { } else {
if (irq < 0) if (irq < 0)
return irq; return irq;
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. // Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
#include <linux/acpi.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/err.h> #include <linux/err.h>
...@@ -483,6 +484,14 @@ static const struct i2c_algorithm geni_i2c_algo = { ...@@ -483,6 +484,14 @@ static const struct i2c_algorithm geni_i2c_algo = {
.functionality = geni_i2c_func, .functionality = geni_i2c_func,
}; };
#ifdef CONFIG_ACPI
static const struct acpi_device_id geni_i2c_acpi_match[] = {
{ "QCOM0220"},
{ },
};
MODULE_DEVICE_TABLE(acpi, geni_i2c_acpi_match);
#endif
static int geni_i2c_probe(struct platform_device *pdev) static int geni_i2c_probe(struct platform_device *pdev)
{ {
struct geni_i2c_dev *gi2c; struct geni_i2c_dev *gi2c;
...@@ -502,7 +511,7 @@ static int geni_i2c_probe(struct platform_device *pdev) ...@@ -502,7 +511,7 @@ static int geni_i2c_probe(struct platform_device *pdev)
return PTR_ERR(gi2c->se.base); return PTR_ERR(gi2c->se.base);
gi2c->se.clk = devm_clk_get(&pdev->dev, "se"); gi2c->se.clk = devm_clk_get(&pdev->dev, "se");
if (IS_ERR(gi2c->se.clk)) { if (IS_ERR(gi2c->se.clk) && !has_acpi_companion(&pdev->dev)) {
ret = PTR_ERR(gi2c->se.clk); ret = PTR_ERR(gi2c->se.clk);
dev_err(&pdev->dev, "Err getting SE Core clk %d\n", ret); dev_err(&pdev->dev, "Err getting SE Core clk %d\n", ret);
return ret; return ret;
...@@ -516,6 +525,9 @@ static int geni_i2c_probe(struct platform_device *pdev) ...@@ -516,6 +525,9 @@ static int geni_i2c_probe(struct platform_device *pdev)
gi2c->clk_freq_out = KHZ(100); gi2c->clk_freq_out = KHZ(100);
} }
if (has_acpi_companion(&pdev->dev))
ACPI_COMPANION_SET(&gi2c->adap.dev, ACPI_COMPANION(&pdev->dev));
gi2c->irq = platform_get_irq(pdev, 0); gi2c->irq = platform_get_irq(pdev, 0);
if (gi2c->irq < 0) { if (gi2c->irq < 0) {
dev_err(&pdev->dev, "IRQ error for i2c-geni\n"); dev_err(&pdev->dev, "IRQ error for i2c-geni\n");
...@@ -584,6 +596,8 @@ static int geni_i2c_probe(struct platform_device *pdev) ...@@ -584,6 +596,8 @@ static int geni_i2c_probe(struct platform_device *pdev)
return ret; return ret;
} }
dev_dbg(&pdev->dev, "Geni-I2C adaptor successfully added\n");
return 0; return 0;
} }
...@@ -660,6 +674,7 @@ static struct platform_driver geni_i2c_driver = { ...@@ -660,6 +674,7 @@ static struct platform_driver geni_i2c_driver = {
.name = "geni_i2c", .name = "geni_i2c",
.pm = &geni_i2c_pm_ops, .pm = &geni_i2c_pm_ops,
.of_match_table = geni_i2c_dt_match, .of_match_table = geni_i2c_dt_match,
.acpi_match_table = ACPI_PTR(geni_i2c_acpi_match),
}, },
}; };
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_gpio.h> #include <linux/gpio/consumer.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <linux/regmap.h> #include <linux/regmap.h>
...@@ -113,7 +113,7 @@ struct s3c24xx_i2c { ...@@ -113,7 +113,7 @@ struct s3c24xx_i2c {
struct i2c_adapter adap; struct i2c_adapter adap;
struct s3c2410_platform_i2c *pdata; struct s3c2410_platform_i2c *pdata;
int gpios[2]; struct gpio_desc *gpios[2];
struct pinctrl *pctrl; struct pinctrl *pctrl;
#if defined(CONFIG_ARM_S3C24XX_CPUFREQ) #if defined(CONFIG_ARM_S3C24XX_CPUFREQ)
struct notifier_block freq_transition; struct notifier_block freq_transition;
...@@ -947,53 +947,27 @@ static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c) ...@@ -947,53 +947,27 @@ static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c)
#ifdef CONFIG_OF #ifdef CONFIG_OF
static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c) static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)
{ {
int idx, gpio, ret; int i;
if (i2c->quirks & QUIRK_NO_GPIO) if (i2c->quirks & QUIRK_NO_GPIO)
return 0; return 0;
for (idx = 0; idx < 2; idx++) { for (i = 0; i < 2; i++) {
gpio = of_get_gpio(i2c->dev->of_node, idx); i2c->gpios[i] = devm_gpiod_get_index(i2c->dev, NULL,
if (!gpio_is_valid(gpio)) { i, GPIOD_ASIS);
dev_err(i2c->dev, "invalid gpio[%d]: %d\n", idx, gpio); if (IS_ERR(i2c->gpios[i])) {
goto free_gpio; dev_err(i2c->dev, "i2c gpio invalid at index %d\n", i);
} return -EINVAL;
i2c->gpios[idx] = gpio;
ret = gpio_request(gpio, "i2c-bus");
if (ret) {
dev_err(i2c->dev, "gpio [%d] request failed (%d)\n",
gpio, ret);
goto free_gpio;
} }
} }
return 0; return 0;
free_gpio:
while (--idx >= 0)
gpio_free(i2c->gpios[idx]);
return -EINVAL;
} }
static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c)
{
unsigned int idx;
if (i2c->quirks & QUIRK_NO_GPIO)
return;
for (idx = 0; idx < 2; idx++)
gpio_free(i2c->gpios[idx]);
}
#else #else
static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c) static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)
{ {
return 0; return 0;
} }
static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c)
{
}
#endif #endif
/* /*
...@@ -1222,9 +1196,6 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev) ...@@ -1222,9 +1196,6 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
i2c_del_adapter(&i2c->adap); i2c_del_adapter(&i2c->adap);
if (pdev->dev.of_node && IS_ERR(i2c->pctrl))
s3c24xx_i2c_dt_gpio_free(i2c);
return 0; return 0;
} }
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
...@@ -953,6 +952,9 @@ static int stm32f7_i2c_smbus_xfer_msg(struct stm32f7_i2c_dev *i2c_dev, ...@@ -953,6 +952,9 @@ static int stm32f7_i2c_smbus_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
cr2 &= ~STM32F7_I2C_CR2_RD_WRN; cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
f7_msg->read_write = I2C_SMBUS_READ; f7_msg->read_write = I2C_SMBUS_READ;
break; break;
case I2C_SMBUS_I2C_BLOCK_DATA:
/* Rely on emulated i2c transfer (through master_xfer) */
return -EOPNOTSUPP;
default: default:
dev_err(dev, "Unsupported smbus protocol %d\n", f7_msg->size); dev_err(dev, "Unsupported smbus protocol %d\n", f7_msg->size);
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -1803,7 +1805,8 @@ static u32 stm32f7_i2c_func(struct i2c_adapter *adap) ...@@ -1803,7 +1805,8 @@ static u32 stm32f7_i2c_func(struct i2c_adapter *adap)
I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_PEC; I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_PEC |
I2C_FUNC_SMBUS_I2C_BLOCK;
} }
static struct i2c_algorithm stm32f7_i2c_algo = { static struct i2c_algorithm stm32f7_i2c_algo = {
...@@ -1816,15 +1819,14 @@ static struct i2c_algorithm stm32f7_i2c_algo = { ...@@ -1816,15 +1819,14 @@ static struct i2c_algorithm stm32f7_i2c_algo = {
static int stm32f7_i2c_probe(struct platform_device *pdev) static int stm32f7_i2c_probe(struct platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node;
struct stm32f7_i2c_dev *i2c_dev; struct stm32f7_i2c_dev *i2c_dev;
const struct stm32f7_i2c_setup *setup; const struct stm32f7_i2c_setup *setup;
struct resource *res; struct resource *res;
u32 irq_error, irq_event, clk_rate, rise_time, fall_time; u32 clk_rate, rise_time, fall_time;
struct i2c_adapter *adap; struct i2c_adapter *adap;
struct reset_control *rst; struct reset_control *rst;
dma_addr_t phy_addr; dma_addr_t phy_addr;
int ret; int irq_error, irq_event, ret;
i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
if (!i2c_dev) if (!i2c_dev)
...@@ -1836,16 +1838,20 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) ...@@ -1836,16 +1838,20 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
return PTR_ERR(i2c_dev->base); return PTR_ERR(i2c_dev->base);
phy_addr = (dma_addr_t)res->start; phy_addr = (dma_addr_t)res->start;
irq_event = irq_of_parse_and_map(np, 0); irq_event = platform_get_irq(pdev, 0);
if (!irq_event) { if (irq_event <= 0) {
dev_err(&pdev->dev, "IRQ event missing or invalid\n"); if (irq_event != -EPROBE_DEFER)
return -EINVAL; dev_err(&pdev->dev, "Failed to get IRQ event: %d\n",
irq_event);
return irq_event ? : -ENOENT;
} }
irq_error = irq_of_parse_and_map(np, 1); irq_error = platform_get_irq(pdev, 1);
if (!irq_error) { if (irq_error <= 0) {
dev_err(&pdev->dev, "IRQ error missing or invalid\n"); if (irq_error != -EPROBE_DEFER)
return -EINVAL; dev_err(&pdev->dev, "Failed to get IRQ error: %d\n",
irq_error);
return irq_error ? : -ENOENT;
} }
i2c_dev->clk = devm_clk_get(&pdev->dev, NULL); i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
......
...@@ -54,20 +54,15 @@ ...@@ -54,20 +54,15 @@
#define I2C_INT_STATUS 0x068 #define I2C_INT_STATUS 0x068
#define I2C_INT_BUS_CLR_DONE BIT(11) #define I2C_INT_BUS_CLR_DONE BIT(11)
#define I2C_INT_PACKET_XFER_COMPLETE BIT(7) #define I2C_INT_PACKET_XFER_COMPLETE BIT(7)
#define I2C_INT_ALL_PACKETS_XFER_COMPLETE BIT(6)
#define I2C_INT_TX_FIFO_OVERFLOW BIT(5)
#define I2C_INT_RX_FIFO_UNDERFLOW BIT(4)
#define I2C_INT_NO_ACK BIT(3) #define I2C_INT_NO_ACK BIT(3)
#define I2C_INT_ARBITRATION_LOST BIT(2) #define I2C_INT_ARBITRATION_LOST BIT(2)
#define I2C_INT_TX_FIFO_DATA_REQ BIT(1) #define I2C_INT_TX_FIFO_DATA_REQ BIT(1)
#define I2C_INT_RX_FIFO_DATA_REQ BIT(0) #define I2C_INT_RX_FIFO_DATA_REQ BIT(0)
#define I2C_CLK_DIVISOR 0x06c #define I2C_CLK_DIVISOR 0x06c
#define I2C_CLK_DIVISOR_STD_FAST_MODE_SHIFT 16 #define I2C_CLK_DIVISOR_STD_FAST_MODE_SHIFT 16
#define I2C_CLK_MULTIPLIER_STD_FAST_MODE 8
#define DVC_CTRL_REG1 0x000 #define DVC_CTRL_REG1 0x000
#define DVC_CTRL_REG1_INTR_EN BIT(10) #define DVC_CTRL_REG1_INTR_EN BIT(10)
#define DVC_CTRL_REG2 0x004
#define DVC_CTRL_REG3 0x008 #define DVC_CTRL_REG3 0x008
#define DVC_CTRL_REG3_SW_PROG BIT(26) #define DVC_CTRL_REG3_SW_PROG BIT(26)
#define DVC_CTRL_REG3_I2C_DONE_INTR_EN BIT(30) #define DVC_CTRL_REG3_I2C_DONE_INTR_EN BIT(30)
...@@ -75,24 +70,22 @@ ...@@ -75,24 +70,22 @@
#define DVC_STATUS_I2C_DONE_INTR BIT(30) #define DVC_STATUS_I2C_DONE_INTR BIT(30)
#define I2C_ERR_NONE 0x00 #define I2C_ERR_NONE 0x00
#define I2C_ERR_NO_ACK 0x01 #define I2C_ERR_NO_ACK BIT(0)
#define I2C_ERR_ARBITRATION_LOST 0x02 #define I2C_ERR_ARBITRATION_LOST BIT(1)
#define I2C_ERR_UNKNOWN_INTERRUPT 0x04 #define I2C_ERR_UNKNOWN_INTERRUPT BIT(2)
#define I2C_ERR_RX_BUFFER_OVERFLOW BIT(3)
#define PACKET_HEADER0_HEADER_SIZE_SHIFT 28 #define PACKET_HEADER0_HEADER_SIZE_SHIFT 28
#define PACKET_HEADER0_PACKET_ID_SHIFT 16 #define PACKET_HEADER0_PACKET_ID_SHIFT 16
#define PACKET_HEADER0_CONT_ID_SHIFT 12 #define PACKET_HEADER0_CONT_ID_SHIFT 12
#define PACKET_HEADER0_PROTOCOL_I2C BIT(4) #define PACKET_HEADER0_PROTOCOL_I2C BIT(4)
#define I2C_HEADER_HIGHSPEED_MODE BIT(22)
#define I2C_HEADER_CONT_ON_NAK BIT(21) #define I2C_HEADER_CONT_ON_NAK BIT(21)
#define I2C_HEADER_SEND_START_BYTE BIT(20)
#define I2C_HEADER_READ BIT(19) #define I2C_HEADER_READ BIT(19)
#define I2C_HEADER_10BIT_ADDR BIT(18) #define I2C_HEADER_10BIT_ADDR BIT(18)
#define I2C_HEADER_IE_ENABLE BIT(17) #define I2C_HEADER_IE_ENABLE BIT(17)
#define I2C_HEADER_REPEAT_START BIT(16) #define I2C_HEADER_REPEAT_START BIT(16)
#define I2C_HEADER_CONTINUE_XFER BIT(15) #define I2C_HEADER_CONTINUE_XFER BIT(15)
#define I2C_HEADER_MASTER_ADDR_SHIFT 12
#define I2C_HEADER_SLAVE_ADDR_SHIFT 1 #define I2C_HEADER_SLAVE_ADDR_SHIFT 1
#define I2C_BUS_CLEAR_CNFG 0x084 #define I2C_BUS_CLEAR_CNFG 0x084
...@@ -106,8 +99,6 @@ ...@@ -106,8 +99,6 @@
#define I2C_CONFIG_LOAD 0x08C #define I2C_CONFIG_LOAD 0x08C
#define I2C_MSTR_CONFIG_LOAD BIT(0) #define I2C_MSTR_CONFIG_LOAD BIT(0)
#define I2C_SLV_CONFIG_LOAD BIT(1)
#define I2C_TIMEOUT_CONFIG_LOAD BIT(2)
#define I2C_CLKEN_OVERRIDE 0x090 #define I2C_CLKEN_OVERRIDE 0x090
#define I2C_MST_CORE_CLKEN_OVR BIT(0) #define I2C_MST_CORE_CLKEN_OVR BIT(0)
...@@ -133,7 +124,6 @@ ...@@ -133,7 +124,6 @@
#define I2C_STANDARD_MODE 100000 #define I2C_STANDARD_MODE 100000
#define I2C_FAST_MODE 400000 #define I2C_FAST_MODE 400000
#define I2C_FAST_PLUS_MODE 1000000 #define I2C_FAST_PLUS_MODE 1000000
#define I2C_HS_MODE 3500000
/* Packet header size in bytes */ /* Packet header size in bytes */
#define I2C_PACKET_HEADER_SIZE 12 #define I2C_PACKET_HEADER_SIZE 12
...@@ -280,6 +270,7 @@ struct tegra_i2c_dev { ...@@ -280,6 +270,7 @@ struct tegra_i2c_dev {
u32 bus_clk_rate; u32 bus_clk_rate;
u16 clk_divisor_non_hs_mode; u16 clk_divisor_non_hs_mode;
bool is_multimaster_mode; bool is_multimaster_mode;
/* xfer_lock: lock to serialize transfer submission and processing */
spinlock_t xfer_lock; spinlock_t xfer_lock;
struct dma_chan *tx_dma_chan; struct dma_chan *tx_dma_chan;
struct dma_chan *rx_dma_chan; struct dma_chan *rx_dma_chan;
...@@ -486,7 +477,7 @@ static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev) ...@@ -486,7 +477,7 @@ static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
dev_warn(i2c_dev->dev, "timeout waiting for fifo flush\n"); dev_warn(i2c_dev->dev, "timeout waiting for fifo flush\n");
return -ETIMEDOUT; return -ETIMEDOUT;
} }
msleep(1); usleep_range(1000, 2000);
} }
return 0; return 0;
} }
...@@ -499,6 +490,13 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev) ...@@ -499,6 +490,13 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
size_t buf_remaining = i2c_dev->msg_buf_remaining; size_t buf_remaining = i2c_dev->msg_buf_remaining;
int words_to_transfer; int words_to_transfer;
/*
* Catch overflow due to message fully sent
* before the check for RX FIFO availability.
*/
if (WARN_ON_ONCE(!(i2c_dev->msg_buf_remaining)))
return -EINVAL;
if (i2c_dev->hw->has_mst_fifo) { if (i2c_dev->hw->has_mst_fifo) {
val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS); val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
rx_fifo_avail = (val & I2C_MST_FIFO_STATUS_RX_MASK) >> rx_fifo_avail = (val & I2C_MST_FIFO_STATUS_RX_MASK) >>
...@@ -525,7 +523,11 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev) ...@@ -525,7 +523,11 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
* prevent overwriting past the end of buf * prevent overwriting past the end of buf
*/ */
if (rx_fifo_avail > 0 && buf_remaining > 0) { if (rx_fifo_avail > 0 && buf_remaining > 0) {
BUG_ON(buf_remaining > 3); /*
* buf_remaining > 3 check not needed as rx_fifo_avail == 0
* when (words_to_transfer was > rx_fifo_avail) earlier
* in this function.
*/
val = i2c_readl(i2c_dev, I2C_RX_FIFO); val = i2c_readl(i2c_dev, I2C_RX_FIFO);
val = cpu_to_le32(val); val = cpu_to_le32(val);
memcpy(buf, &val, buf_remaining); memcpy(buf, &val, buf_remaining);
...@@ -533,7 +535,10 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev) ...@@ -533,7 +535,10 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
rx_fifo_avail--; rx_fifo_avail--;
} }
BUG_ON(rx_fifo_avail > 0 && buf_remaining > 0); /* RX FIFO must be drained, otherwise it's an Overflow case. */
if (WARN_ON_ONCE(rx_fifo_avail))
return -EINVAL;
i2c_dev->msg_buf_remaining = buf_remaining; i2c_dev->msg_buf_remaining = buf_remaining;
i2c_dev->msg_buf = buf; i2c_dev->msg_buf = buf;
...@@ -591,7 +596,11 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev) ...@@ -591,7 +596,11 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
* boundary and fault. * boundary and fault.
*/ */
if (tx_fifo_avail > 0 && buf_remaining > 0) { if (tx_fifo_avail > 0 && buf_remaining > 0) {
BUG_ON(buf_remaining > 3); /*
* buf_remaining > 3 check not needed as tx_fifo_avail == 0
* when (words_to_transfer was > tx_fifo_avail) earlier
* in this function for non-zero words_to_transfer.
*/
memcpy(&val, buf, buf_remaining); memcpy(&val, buf, buf_remaining);
val = le32_to_cpu(val); val = le32_to_cpu(val);
...@@ -680,10 +689,11 @@ static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev) ...@@ -680,10 +689,11 @@ static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev)
i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD); i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD);
if (in_interrupt()) if (in_interrupt())
err = readl_poll_timeout_atomic(addr, val, val == 0, err = readl_poll_timeout_atomic(addr, val, val == 0,
1000, I2C_CONFIG_LOAD_TIMEOUT); 1000,
I2C_CONFIG_LOAD_TIMEOUT);
else else
err = readl_poll_timeout(addr, val, val == 0, err = readl_poll_timeout(addr, val, val == 0, 1000,
1000, I2C_CONFIG_LOAD_TIMEOUT); I2C_CONFIG_LOAD_TIMEOUT);
if (err) { if (err) {
dev_warn(i2c_dev->dev, dev_warn(i2c_dev->dev,
...@@ -700,7 +710,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit) ...@@ -700,7 +710,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit)
u32 val; u32 val;
int err; int err;
u32 clk_divisor, clk_multiplier; u32 clk_divisor, clk_multiplier;
u32 tsu_thd = 0; u32 tsu_thd;
u8 tlow, thigh; u8 tlow, thigh;
err = pm_runtime_get_sync(i2c_dev->dev); err = pm_runtime_get_sync(i2c_dev->dev);
...@@ -856,10 +866,15 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) ...@@ -856,10 +866,15 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
if (!i2c_dev->is_curr_dma_xfer) { if (!i2c_dev->is_curr_dma_xfer) {
if (i2c_dev->msg_read && (status & I2C_INT_RX_FIFO_DATA_REQ)) { if (i2c_dev->msg_read && (status & I2C_INT_RX_FIFO_DATA_REQ)) {
if (i2c_dev->msg_buf_remaining) if (tegra_i2c_empty_rx_fifo(i2c_dev)) {
tegra_i2c_empty_rx_fifo(i2c_dev); /*
else * Overflow error condition: message fully sent,
BUG(); * with no XFER_COMPLETE interrupt but hardware
* asks to transfer more.
*/
i2c_dev->msg_err |= I2C_ERR_RX_BUFFER_OVERFLOW;
goto err;
}
} }
if (!i2c_dev->msg_read && (status & I2C_INT_TX_FIFO_DATA_REQ)) { if (!i2c_dev->msg_read && (status & I2C_INT_TX_FIFO_DATA_REQ)) {
...@@ -885,7 +900,14 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) ...@@ -885,7 +900,14 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
if (status & I2C_INT_PACKET_XFER_COMPLETE) { if (status & I2C_INT_PACKET_XFER_COMPLETE) {
if (i2c_dev->is_curr_dma_xfer) if (i2c_dev->is_curr_dma_xfer)
i2c_dev->msg_buf_remaining = 0; i2c_dev->msg_buf_remaining = 0;
BUG_ON(i2c_dev->msg_buf_remaining); /*
* Underflow error condition: XFER_COMPLETE before message
* fully sent.
*/
if (WARN_ON_ONCE(i2c_dev->msg_buf_remaining)) {
i2c_dev->msg_err |= I2C_ERR_UNKNOWN_INTERRUPT;
goto err;
}
complete(&i2c_dev->msg_complete); complete(&i2c_dev->msg_complete);
} }
goto done; goto done;
...@@ -1024,7 +1046,8 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap) ...@@ -1024,7 +1046,8 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap)
} }
static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
struct i2c_msg *msg, enum msg_end_type end_state) struct i2c_msg *msg,
enum msg_end_type end_state)
{ {
u32 packet_header; u32 packet_header;
u32 int_mask; u32 int_mask;
...@@ -1161,8 +1184,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, ...@@ -1161,8 +1184,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
if (err) if (err)
return err; return err;
time_left = wait_for_completion_timeout( time_left = wait_for_completion_timeout(&i2c_dev->dma_complete,
&i2c_dev->dma_complete,
msecs_to_jiffies(xfer_time)); msecs_to_jiffies(xfer_time));
if (time_left == 0) { if (time_left == 0) {
dev_err(i2c_dev->dev, "DMA transfer timeout\n"); dev_err(i2c_dev->dev, "DMA transfer timeout\n");
...@@ -1229,7 +1251,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], ...@@ -1229,7 +1251,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
{ {
struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap); struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
int i; int i;
int ret = 0; int ret;
ret = pm_runtime_get_sync(i2c_dev->dev); ret = pm_runtime_get_sync(i2c_dev->dev);
if (ret < 0) { if (ret < 0) {
...@@ -1271,14 +1293,15 @@ static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev) ...@@ -1271,14 +1293,15 @@ static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev)
{ {
struct device_node *np = i2c_dev->dev->of_node; struct device_node *np = i2c_dev->dev->of_node;
int ret; int ret;
bool multi_mode;
ret = of_property_read_u32(np, "clock-frequency", ret = of_property_read_u32(np, "clock-frequency",
&i2c_dev->bus_clk_rate); &i2c_dev->bus_clk_rate);
if (ret) if (ret)
i2c_dev->bus_clk_rate = 100000; /* default clock rate */ i2c_dev->bus_clk_rate = 100000; /* default clock rate */
i2c_dev->is_multimaster_mode = of_property_read_bool(np, multi_mode = of_property_read_bool(np, "multi-master");
"multi-master"); i2c_dev->is_multimaster_mode = multi_mode;
} }
static const struct i2c_algorithm tegra_i2c_algo = { static const struct i2c_algorithm tegra_i2c_algo = {
...@@ -1500,7 +1523,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) ...@@ -1500,7 +1523,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
void __iomem *base; void __iomem *base;
phys_addr_t base_phys; phys_addr_t base_phys;
int irq; int irq;
int ret = 0; int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base_phys = res->start; base_phys = res->start;
...@@ -1517,7 +1540,9 @@ static int tegra_i2c_probe(struct platform_device *pdev) ...@@ -1517,7 +1540,9 @@ static int tegra_i2c_probe(struct platform_device *pdev)
div_clk = devm_clk_get(&pdev->dev, "div-clk"); div_clk = devm_clk_get(&pdev->dev, "div-clk");
if (IS_ERR(div_clk)) { if (IS_ERR(div_clk)) {
if (PTR_ERR(div_clk) != -EPROBE_DEFER)
dev_err(&pdev->dev, "missing controller clock\n"); dev_err(&pdev->dev, "missing controller clock\n");
return PTR_ERR(div_clk); return PTR_ERR(div_clk);
} }
...@@ -1687,10 +1712,35 @@ static int tegra_i2c_remove(struct platform_device *pdev) ...@@ -1687,10 +1712,35 @@ static int tegra_i2c_remove(struct platform_device *pdev)
} }
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int tegra_i2c_suspend(struct device *dev)
{
struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
i2c_mark_adapter_suspended(&i2c_dev->adapter);
return 0;
}
static int tegra_i2c_resume(struct device *dev)
{
struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
int err;
err = tegra_i2c_init(i2c_dev, false);
if (err)
return err;
i2c_mark_adapter_resumed(&i2c_dev->adapter);
return 0;
}
static const struct dev_pm_ops tegra_i2c_pm = { static const struct dev_pm_ops tegra_i2c_pm = {
SET_SYSTEM_SLEEP_PM_OPS(tegra_i2c_suspend, tegra_i2c_resume)
SET_RUNTIME_PM_OPS(tegra_i2c_runtime_suspend, tegra_i2c_runtime_resume, SET_RUNTIME_PM_OPS(tegra_i2c_runtime_suspend, tegra_i2c_runtime_resume,
NULL) NULL)
}; };
#define TEGRA_I2C_PM (&tegra_i2c_pm) #define TEGRA_I2C_PM (&tegra_i2c_pm)
#else #else
#define TEGRA_I2C_PM NULL #define TEGRA_I2C_PM NULL
......
...@@ -132,13 +132,52 @@ static int i2c_acpi_do_lookup(struct acpi_device *adev, ...@@ -132,13 +132,52 @@ static int i2c_acpi_do_lookup(struct acpi_device *adev,
return 0; return 0;
} }
static int i2c_acpi_add_resource(struct acpi_resource *ares, void *data)
{
int *irq = data;
struct resource r;
if (*irq <= 0 && acpi_dev_resource_interrupt(ares, 0, &r))
*irq = i2c_dev_irq_from_resources(&r, 1);
return 1; /* No need to add resource to the list */
}
/**
* i2c_acpi_get_irq - get device IRQ number from ACPI
* @client: Pointer to the I2C client device
*
* Find the IRQ number used by a specific client device.
*
* Return: The IRQ number or an error code.
*/
int i2c_acpi_get_irq(struct i2c_client *client)
{
struct acpi_device *adev = ACPI_COMPANION(&client->dev);
struct list_head resource_list;
int irq = -ENOENT;
int ret;
INIT_LIST_HEAD(&resource_list);
ret = acpi_dev_get_resources(adev, &resource_list,
i2c_acpi_add_resource, &irq);
if (ret < 0)
return ret;
acpi_dev_free_resource_list(&resource_list);
if (irq == -ENOENT)
irq = acpi_dev_gpio_irq_get(adev, 0);
return irq;
}
static int i2c_acpi_get_info(struct acpi_device *adev, static int i2c_acpi_get_info(struct acpi_device *adev,
struct i2c_board_info *info, struct i2c_board_info *info,
struct i2c_adapter *adapter, struct i2c_adapter *adapter,
acpi_handle *adapter_handle) acpi_handle *adapter_handle)
{ {
struct list_head resource_list;
struct resource_entry *entry;
struct i2c_acpi_lookup lookup; struct i2c_acpi_lookup lookup;
int ret; int ret;
...@@ -172,21 +211,6 @@ static int i2c_acpi_get_info(struct acpi_device *adev, ...@@ -172,21 +211,6 @@ static int i2c_acpi_get_info(struct acpi_device *adev,
if (adapter_handle) if (adapter_handle)
*adapter_handle = lookup.adapter_handle; *adapter_handle = lookup.adapter_handle;
/* Then fill IRQ number if any */
INIT_LIST_HEAD(&resource_list);
ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
if (ret < 0)
return -EINVAL;
resource_list_for_each_entry(entry, &resource_list) {
if (resource_type(entry->res) == IORESOURCE_IRQ) {
info->irq = entry->res->start;
break;
}
}
acpi_dev_free_resource_list(&resource_list);
acpi_set_modalias(adev, dev_name(&adev->dev), info->type, acpi_set_modalias(adev, dev_name(&adev->dev), info->type,
sizeof(info->type)); sizeof(info->type));
......
...@@ -314,6 +314,8 @@ static int i2c_device_probe(struct device *dev) ...@@ -314,6 +314,8 @@ static int i2c_device_probe(struct device *dev)
driver = to_i2c_driver(dev->driver); driver = to_i2c_driver(dev->driver);
client->irq = client->init_irq;
if (!client->irq && !driver->disable_i2c_core_irq_mapping) { if (!client->irq && !driver->disable_i2c_core_irq_mapping) {
int irq = -ENOENT; int irq = -ENOENT;
...@@ -327,7 +329,7 @@ static int i2c_device_probe(struct device *dev) ...@@ -327,7 +329,7 @@ static int i2c_device_probe(struct device *dev)
if (irq == -EINVAL || irq == -ENODATA) if (irq == -EINVAL || irq == -ENODATA)
irq = of_irq_get(dev->of_node, 0); irq = of_irq_get(dev->of_node, 0);
} else if (ACPI_COMPANION(dev)) { } else if (ACPI_COMPANION(dev)) {
irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(dev), 0); irq = i2c_acpi_get_irq(client);
} }
if (irq == -EPROBE_DEFER) if (irq == -EPROBE_DEFER)
return irq; return irq;
...@@ -424,7 +426,7 @@ static int i2c_device_remove(struct device *dev) ...@@ -424,7 +426,7 @@ static int i2c_device_remove(struct device *dev)
dev_pm_clear_wake_irq(&client->dev); dev_pm_clear_wake_irq(&client->dev);
device_init_wakeup(&client->dev, false); device_init_wakeup(&client->dev, false);
client->irq = client->init_irq; client->irq = 0;
if (client->flags & I2C_CLIENT_HOST_NOTIFY) if (client->flags & I2C_CLIENT_HOST_NOTIFY)
pm_runtime_put(&client->adapter->dev); pm_runtime_put(&client->adapter->dev);
...@@ -679,7 +681,7 @@ static void i2c_dev_set_name(struct i2c_adapter *adap, ...@@ -679,7 +681,7 @@ static void i2c_dev_set_name(struct i2c_adapter *adap,
i2c_encode_flags_to_addr(client)); i2c_encode_flags_to_addr(client));
} }
static int i2c_dev_irq_from_resources(const struct resource *resources, int i2c_dev_irq_from_resources(const struct resource *resources,
unsigned int num_resources) unsigned int num_resources)
{ {
struct irq_data *irqd; struct irq_data *irqd;
...@@ -721,7 +723,7 @@ static int i2c_dev_irq_from_resources(const struct resource *resources, ...@@ -721,7 +723,7 @@ static int i2c_dev_irq_from_resources(const struct resource *resources,
* This returns the new i2c client, which may be saved for later use with * This returns the new i2c client, which may be saved for later use with
* i2c_unregister_device(); or an ERR_PTR to describe the error. * i2c_unregister_device(); or an ERR_PTR to describe the error.
*/ */
static struct i2c_client * struct i2c_client *
i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *info) i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
{ {
struct i2c_client *client; struct i2c_client *client;
...@@ -741,7 +743,6 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf ...@@ -741,7 +743,6 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf
if (!client->init_irq) if (!client->init_irq)
client->init_irq = i2c_dev_irq_from_resources(info->resources, client->init_irq = i2c_dev_irq_from_resources(info->resources,
info->num_resources); info->num_resources);
client->irq = client->init_irq;
strlcpy(client->name, info->type, sizeof(client->name)); strlcpy(client->name, info->type, sizeof(client->name));
...@@ -887,8 +888,7 @@ static struct i2c_driver dummy_driver = { ...@@ -887,8 +888,7 @@ static struct i2c_driver dummy_driver = {
* This returns the new i2c client, which should be saved for later use with * This returns the new i2c client, which should be saved for later use with
* i2c_unregister_device(); or an ERR_PTR to describe the error. * i2c_unregister_device(); or an ERR_PTR to describe the error.
*/ */
static struct i2c_client * struct i2c_client *i2c_new_dummy_device(struct i2c_adapter *adapter, u16 address)
i2c_new_dummy_device(struct i2c_adapter *adapter, u16 address)
{ {
struct i2c_board_info info = { struct i2c_board_info info = {
I2C_BOARD_INFO("dummy", address), I2C_BOARD_INFO("dummy", address),
...@@ -1663,7 +1663,7 @@ EXPORT_SYMBOL_GPL(i2c_parse_fw_timings); ...@@ -1663,7 +1663,7 @@ EXPORT_SYMBOL_GPL(i2c_parse_fw_timings);
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *)) int i2c_for_each_dev(void *data, int (*fn)(struct device *dev, void *data))
{ {
int res; int res;
...@@ -2276,7 +2276,7 @@ struct i2c_client * ...@@ -2276,7 +2276,7 @@ struct i2c_client *
i2c_new_probed_device(struct i2c_adapter *adap, i2c_new_probed_device(struct i2c_adapter *adap,
struct i2c_board_info *info, struct i2c_board_info *info,
unsigned short const *addr_list, unsigned short const *addr_list,
int (*probe)(struct i2c_adapter *, unsigned short addr)) int (*probe)(struct i2c_adapter *adap, unsigned short addr))
{ {
int i; int i;
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/sysfs.h>
#include "i2c-core.h" #include "i2c-core.h"
......
...@@ -19,6 +19,8 @@ extern struct list_head __i2c_board_list; ...@@ -19,6 +19,8 @@ extern struct list_head __i2c_board_list;
extern int __i2c_first_dynamic_bus_num; extern int __i2c_first_dynamic_bus_num;
int i2c_check_7bit_addr_validity_strict(unsigned short addr); int i2c_check_7bit_addr_validity_strict(unsigned short addr);
int i2c_dev_irq_from_resources(const struct resource *resources,
unsigned int num_resources);
/* /*
* We only allow atomic transfers for very late communication, e.g. to send * We only allow atomic transfers for very late communication, e.g. to send
...@@ -61,6 +63,8 @@ const struct acpi_device_id * ...@@ -61,6 +63,8 @@ const struct acpi_device_id *
i2c_acpi_match_device(const struct acpi_device_id *matches, i2c_acpi_match_device(const struct acpi_device_id *matches,
struct i2c_client *client); struct i2c_client *client);
void i2c_acpi_register_devices(struct i2c_adapter *adap); void i2c_acpi_register_devices(struct i2c_adapter *adap);
int i2c_acpi_get_irq(struct i2c_client *client);
#else /* CONFIG_ACPI */ #else /* CONFIG_ACPI */
static inline void i2c_acpi_register_devices(struct i2c_adapter *adap) { } static inline void i2c_acpi_register_devices(struct i2c_adapter *adap) { }
static inline const struct acpi_device_id * static inline const struct acpi_device_id *
...@@ -69,6 +73,11 @@ i2c_acpi_match_device(const struct acpi_device_id *matches, ...@@ -69,6 +73,11 @@ i2c_acpi_match_device(const struct acpi_device_id *matches,
{ {
return NULL; return NULL;
} }
static inline int i2c_acpi_get_irq(struct i2c_client *client)
{
return 0;
}
#endif /* CONFIG_ACPI */ #endif /* CONFIG_ACPI */
extern struct notifier_block i2c_acpi_notifier; extern struct notifier_block i2c_acpi_notifier;
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/sysfs.h>
/* multiplexer per channel data */ /* multiplexer per channel data */
struct i2c_mux_priv { struct i2c_mux_priv {
...@@ -243,8 +244,7 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent, ...@@ -243,8 +244,7 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
{ {
struct i2c_mux_core *muxc; struct i2c_mux_core *muxc;
muxc = devm_kzalloc(dev, sizeof(*muxc) muxc = devm_kzalloc(dev, struct_size(muxc, adapter, max_adapters)
+ max_adapters * sizeof(muxc->adapter[0])
+ sizeof_priv, GFP_KERNEL); + sizeof_priv, GFP_KERNEL);
if (!muxc) if (!muxc)
return NULL; return NULL;
......
...@@ -6,12 +6,11 @@ ...@@ -6,12 +6,11 @@
*/ */
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gpio.h> #include <linux/gpio/consumer.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-mux.h> #include <linux/i2c-mux.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -19,22 +18,16 @@ ...@@ -19,22 +18,16 @@
/** /**
* struct i2c_arbitrator_data - Driver data for I2C arbitrator * struct i2c_arbitrator_data - Driver data for I2C arbitrator
* *
* @our_gpio: GPIO we'll use to claim. * @our_gpio: GPIO descriptor we'll use to claim.
* @our_gpio_release: 0 if active high; 1 if active low; AKA if the GPIO == * @their_gpio: GPIO descriptor that the other side will use to claim.
* this then consider it released.
* @their_gpio: GPIO that the other side will use to claim.
* @their_gpio_release: 0 if active high; 1 if active low; AKA if the GPIO ==
* this then consider it released.
* @slew_delay_us: microseconds to wait for a GPIO to go high. * @slew_delay_us: microseconds to wait for a GPIO to go high.
* @wait_retry_us: we'll attempt another claim after this many microseconds. * @wait_retry_us: we'll attempt another claim after this many microseconds.
* @wait_free_us: we'll give up after this many microseconds. * @wait_free_us: we'll give up after this many microseconds.
*/ */
struct i2c_arbitrator_data { struct i2c_arbitrator_data {
int our_gpio; struct gpio_desc *our_gpio;
int our_gpio_release; struct gpio_desc *their_gpio;
int their_gpio;
int their_gpio_release;
unsigned int slew_delay_us; unsigned int slew_delay_us;
unsigned int wait_retry_us; unsigned int wait_retry_us;
unsigned int wait_free_us; unsigned int wait_free_us;
...@@ -55,15 +48,15 @@ static int i2c_arbitrator_select(struct i2c_mux_core *muxc, u32 chan) ...@@ -55,15 +48,15 @@ static int i2c_arbitrator_select(struct i2c_mux_core *muxc, u32 chan)
stop_time = jiffies + usecs_to_jiffies(arb->wait_free_us) + 1; stop_time = jiffies + usecs_to_jiffies(arb->wait_free_us) + 1;
do { do {
/* Indicate that we want to claim the bus */ /* Indicate that we want to claim the bus */
gpio_set_value(arb->our_gpio, !arb->our_gpio_release); gpiod_set_value(arb->our_gpio, 1);
udelay(arb->slew_delay_us); udelay(arb->slew_delay_us);
/* Wait for the other master to release it */ /* Wait for the other master to release it */
stop_retry = jiffies + usecs_to_jiffies(arb->wait_retry_us) + 1; stop_retry = jiffies + usecs_to_jiffies(arb->wait_retry_us) + 1;
while (time_before(jiffies, stop_retry)) { while (time_before(jiffies, stop_retry)) {
int gpio_val = !!gpio_get_value(arb->their_gpio); int gpio_val = gpiod_get_value(arb->their_gpio);
if (gpio_val == arb->their_gpio_release) { if (!gpio_val) {
/* We got it, so return */ /* We got it, so return */
return 0; return 0;
} }
...@@ -72,13 +65,13 @@ static int i2c_arbitrator_select(struct i2c_mux_core *muxc, u32 chan) ...@@ -72,13 +65,13 @@ static int i2c_arbitrator_select(struct i2c_mux_core *muxc, u32 chan)
} }
/* It didn't release, so give up, wait, and try again */ /* It didn't release, so give up, wait, and try again */
gpio_set_value(arb->our_gpio, arb->our_gpio_release); gpiod_set_value(arb->our_gpio, 0);
usleep_range(arb->wait_retry_us, arb->wait_retry_us * 2); usleep_range(arb->wait_retry_us, arb->wait_retry_us * 2);
} while (time_before(jiffies, stop_time)); } while (time_before(jiffies, stop_time));
/* Give up, release our claim */ /* Give up, release our claim */
gpio_set_value(arb->our_gpio, arb->our_gpio_release); gpiod_set_value(arb->our_gpio, 0);
udelay(arb->slew_delay_us); udelay(arb->slew_delay_us);
dev_err(muxc->dev, "Could not claim bus, timeout\n"); dev_err(muxc->dev, "Could not claim bus, timeout\n");
return -EBUSY; return -EBUSY;
...@@ -94,7 +87,7 @@ static int i2c_arbitrator_deselect(struct i2c_mux_core *muxc, u32 chan) ...@@ -94,7 +87,7 @@ static int i2c_arbitrator_deselect(struct i2c_mux_core *muxc, u32 chan)
const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc); const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc);
/* Release the bus and wait for the other master to notice */ /* Release the bus and wait for the other master to notice */
gpio_set_value(arb->our_gpio, arb->our_gpio_release); gpiod_set_value(arb->our_gpio, 0);
udelay(arb->slew_delay_us); udelay(arb->slew_delay_us);
return 0; return 0;
...@@ -107,8 +100,7 @@ static int i2c_arbitrator_probe(struct platform_device *pdev) ...@@ -107,8 +100,7 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
struct device_node *parent_np; struct device_node *parent_np;
struct i2c_mux_core *muxc; struct i2c_mux_core *muxc;
struct i2c_arbitrator_data *arb; struct i2c_arbitrator_data *arb;
enum of_gpio_flags gpio_flags; struct gpio_desc *dummy;
unsigned long out_init;
int ret; int ret;
/* We only support probing from device tree; no platform_data */ /* We only support probing from device tree; no platform_data */
...@@ -129,45 +121,28 @@ static int i2c_arbitrator_probe(struct platform_device *pdev) ...@@ -129,45 +121,28 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, muxc); platform_set_drvdata(pdev, muxc);
/* Request GPIOs */ /* Request GPIOs, our GPIO as unclaimed to begin with */
ret = of_get_named_gpio_flags(np, "our-claim-gpio", 0, &gpio_flags); arb->our_gpio = devm_gpiod_get(dev, "our-claim", GPIOD_OUT_LOW);
if (!gpio_is_valid(ret)) { if (IS_ERR(arb->our_gpio)) {
if (ret != -EPROBE_DEFER) dev_err(dev, "could not get \"our-claim\" GPIO (%ld)\n",
dev_err(dev, "Error getting our-claim-gpio\n"); PTR_ERR(arb->our_gpio));
return ret; return PTR_ERR(arb->our_gpio);
}
arb->our_gpio = ret;
arb->our_gpio_release = !!(gpio_flags & OF_GPIO_ACTIVE_LOW);
out_init = (gpio_flags & OF_GPIO_ACTIVE_LOW) ?
GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
ret = devm_gpio_request_one(dev, arb->our_gpio, out_init,
"our-claim-gpio");
if (ret) {
if (ret != -EPROBE_DEFER)
dev_err(dev, "Error requesting our-claim-gpio\n");
return ret;
} }
ret = of_get_named_gpio_flags(np, "their-claim-gpios", 0, &gpio_flags); arb->their_gpio = devm_gpiod_get(dev, "their-claim", GPIOD_IN);
if (!gpio_is_valid(ret)) { if (IS_ERR(arb->their_gpio)) {
if (ret != -EPROBE_DEFER) dev_err(dev, "could not get \"their-claim\" GPIO (%ld)\n",
dev_err(dev, "Error getting their-claim-gpio\n"); PTR_ERR(arb->their_gpio));
return ret; return PTR_ERR(arb->their_gpio);
}
arb->their_gpio = ret;
arb->their_gpio_release = !!(gpio_flags & OF_GPIO_ACTIVE_LOW);
ret = devm_gpio_request_one(dev, arb->their_gpio, GPIOF_IN,
"their-claim-gpio");
if (ret) {
if (ret != -EPROBE_DEFER)
dev_err(dev, "Error requesting their-claim-gpio\n");
return ret;
} }
/* At the moment we only support a single two master (us + 1 other) */ /* At the moment we only support a single two master (us + 1 other) */
if (gpio_is_valid(of_get_named_gpio(np, "their-claim-gpios", 1))) { dummy = devm_gpiod_get_index(dev, "their-claim", 1, GPIOD_IN);
if (!IS_ERR(dummy)) {
dev_err(dev, "Only one other master is supported\n"); dev_err(dev, "Only one other master is supported\n");
return -EINVAL; return -EINVAL;
} else if (PTR_ERR(dummy) == -EPROBE_DEFER) {
return -EPROBE_DEFER;
} }
/* Arbitration parameters */ /* Arbitration parameters */
......
...@@ -11,13 +11,14 @@ ...@@ -11,13 +11,14 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/gpio.h> #include <linux/bits.h>
#include <linux/gpio/consumer.h>
/* FIXME: stop poking around inside gpiolib */
#include "../../gpio/gpiolib.h" #include "../../gpio/gpiolib.h"
#include <linux/of_gpio.h>
struct gpiomux { struct gpiomux {
struct i2c_mux_gpio_platform_data data; struct i2c_mux_gpio_platform_data data;
unsigned gpio_base; int ngpios;
struct gpio_desc **gpios; struct gpio_desc **gpios;
}; };
...@@ -27,8 +28,7 @@ static void i2c_mux_gpio_set(const struct gpiomux *mux, unsigned val) ...@@ -27,8 +28,7 @@ static void i2c_mux_gpio_set(const struct gpiomux *mux, unsigned val)
values[0] = val; values[0] = val;
gpiod_set_array_value_cansleep(mux->data.n_gpios, mux->gpios, NULL, gpiod_set_array_value_cansleep(mux->ngpios, mux->gpios, NULL, values);
values);
} }
static int i2c_mux_gpio_select(struct i2c_mux_core *muxc, u32 chan) static int i2c_mux_gpio_select(struct i2c_mux_core *muxc, u32 chan)
...@@ -49,12 +49,6 @@ static int i2c_mux_gpio_deselect(struct i2c_mux_core *muxc, u32 chan) ...@@ -49,12 +49,6 @@ static int i2c_mux_gpio_deselect(struct i2c_mux_core *muxc, u32 chan)
return 0; return 0;
} }
static int match_gpio_chip_by_label(struct gpio_chip *chip,
void *data)
{
return !strcmp(chip->label, data);
}
#ifdef CONFIG_OF #ifdef CONFIG_OF
static int i2c_mux_gpio_probe_dt(struct gpiomux *mux, static int i2c_mux_gpio_probe_dt(struct gpiomux *mux,
struct platform_device *pdev) struct platform_device *pdev)
...@@ -62,8 +56,8 @@ static int i2c_mux_gpio_probe_dt(struct gpiomux *mux, ...@@ -62,8 +56,8 @@ static int i2c_mux_gpio_probe_dt(struct gpiomux *mux,
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct device_node *adapter_np, *child; struct device_node *adapter_np, *child;
struct i2c_adapter *adapter; struct i2c_adapter *adapter;
unsigned *values, *gpios; unsigned *values;
int i = 0, ret; int i = 0;
if (!np) if (!np)
return -ENODEV; return -ENODEV;
...@@ -100,29 +94,6 @@ static int i2c_mux_gpio_probe_dt(struct gpiomux *mux, ...@@ -100,29 +94,6 @@ static int i2c_mux_gpio_probe_dt(struct gpiomux *mux,
if (of_property_read_u32(np, "idle-state", &mux->data.idle)) if (of_property_read_u32(np, "idle-state", &mux->data.idle))
mux->data.idle = I2C_MUX_GPIO_NO_IDLE; mux->data.idle = I2C_MUX_GPIO_NO_IDLE;
mux->data.n_gpios = of_gpio_named_count(np, "mux-gpios");
if (mux->data.n_gpios < 0) {
dev_err(&pdev->dev, "Missing mux-gpios property in the DT.\n");
return -EINVAL;
}
gpios = devm_kcalloc(&pdev->dev,
mux->data.n_gpios, sizeof(*mux->data.gpios),
GFP_KERNEL);
if (!gpios) {
dev_err(&pdev->dev, "Cannot allocate gpios array");
return -ENOMEM;
}
for (i = 0; i < mux->data.n_gpios; i++) {
ret = of_get_named_gpio(np, "mux-gpios", i);
if (ret < 0)
return ret;
gpios[i] = ret;
}
mux->data.gpios = gpios;
return 0; return 0;
} }
#else #else
...@@ -139,8 +110,8 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev) ...@@ -139,8 +110,8 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
struct gpiomux *mux; struct gpiomux *mux;
struct i2c_adapter *parent; struct i2c_adapter *parent;
struct i2c_adapter *root; struct i2c_adapter *root;
unsigned initial_state, gpio_base; unsigned initial_state;
int i, ret; int i, ngpios, ret;
mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL); mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
if (!mux) if (!mux)
...@@ -155,29 +126,19 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev) ...@@ -155,29 +126,19 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
sizeof(mux->data)); sizeof(mux->data));
} }
/* ngpios = gpiod_count(&pdev->dev, "mux");
* If a GPIO chip name is provided, the GPIO pin numbers provided are if (ngpios <= 0) {
* relative to its base GPIO number. Otherwise they are absolute. dev_err(&pdev->dev, "no valid gpios provided\n");
*/ return ngpios ?: -EINVAL;
if (mux->data.gpio_chip) {
struct gpio_chip *gpio;
gpio = gpiochip_find(mux->data.gpio_chip,
match_gpio_chip_by_label);
if (!gpio)
return -EPROBE_DEFER;
gpio_base = gpio->base;
} else {
gpio_base = 0;
} }
mux->ngpios = ngpios;
parent = i2c_get_adapter(mux->data.parent); parent = i2c_get_adapter(mux->data.parent);
if (!parent) if (!parent)
return -EPROBE_DEFER; return -EPROBE_DEFER;
muxc = i2c_mux_alloc(parent, &pdev->dev, mux->data.n_values, muxc = i2c_mux_alloc(parent, &pdev->dev, mux->data.n_values,
mux->data.n_gpios * sizeof(*mux->gpios), 0, ngpios * sizeof(*mux->gpios), 0,
i2c_mux_gpio_select, NULL); i2c_mux_gpio_select, NULL);
if (!muxc) { if (!muxc) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -191,7 +152,6 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev) ...@@ -191,7 +152,6 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
root = i2c_root_adapter(&parent->dev); root = i2c_root_adapter(&parent->dev);
muxc->mux_locked = true; muxc->mux_locked = true;
mux->gpio_base = gpio_base;
if (mux->data.idle != I2C_MUX_GPIO_NO_IDLE) { if (mux->data.idle != I2C_MUX_GPIO_NO_IDLE) {
initial_state = mux->data.idle; initial_state = mux->data.idle;
...@@ -200,34 +160,28 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev) ...@@ -200,34 +160,28 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
initial_state = mux->data.values[0]; initial_state = mux->data.values[0];
} }
for (i = 0; i < mux->data.n_gpios; i++) { for (i = 0; i < ngpios; i++) {
struct device *gpio_dev; struct device *gpio_dev;
struct gpio_desc *gpio_desc; struct gpio_desc *gpiod;
enum gpiod_flags flag;
ret = gpio_request(gpio_base + mux->data.gpios[i], "i2c-mux-gpio");
if (ret) { if (initial_state & BIT(i))
dev_err(&pdev->dev, "Failed to request GPIO %d\n", flag = GPIOD_OUT_HIGH;
mux->data.gpios[i]); else
goto err_request_gpio; flag = GPIOD_OUT_LOW;
} gpiod = devm_gpiod_get_index(&pdev->dev, "mux", i, flag);
if (IS_ERR(gpiod)) {
ret = gpio_direction_output(gpio_base + mux->data.gpios[i], ret = PTR_ERR(gpiod);
initial_state & (1 << i)); goto alloc_failed;
if (ret) {
dev_err(&pdev->dev,
"Failed to set direction of GPIO %d to output\n",
mux->data.gpios[i]);
i++; /* gpio_request above succeeded, so must free */
goto err_request_gpio;
} }
gpio_desc = gpio_to_desc(gpio_base + mux->data.gpios[i]); mux->gpios[i] = gpiod;
mux->gpios[i] = gpio_desc;
if (!muxc->mux_locked) if (!muxc->mux_locked)
continue; continue;
gpio_dev = &gpio_desc->gdev->dev; /* FIXME: find a proper way to access the GPIO device */
gpio_dev = &gpiod->gdev->dev;
muxc->mux_locked = i2c_root_adapter(gpio_dev) == root; muxc->mux_locked = i2c_root_adapter(gpio_dev) == root;
} }
...@@ -250,10 +204,6 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev) ...@@ -250,10 +204,6 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
add_adapter_failed: add_adapter_failed:
i2c_mux_del_adapters(muxc); i2c_mux_del_adapters(muxc);
i = mux->data.n_gpios;
err_request_gpio:
for (; i > 0; i--)
gpio_free(gpio_base + mux->data.gpios[i - 1]);
alloc_failed: alloc_failed:
i2c_put_adapter(parent); i2c_put_adapter(parent);
...@@ -263,14 +213,8 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev) ...@@ -263,14 +213,8 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
static int i2c_mux_gpio_remove(struct platform_device *pdev) static int i2c_mux_gpio_remove(struct platform_device *pdev)
{ {
struct i2c_mux_core *muxc = platform_get_drvdata(pdev); struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
struct gpiomux *mux = i2c_mux_priv(muxc);
int i;
i2c_mux_del_adapters(muxc); i2c_mux_del_adapters(muxc);
for (i = 0; i < mux->data.n_gpios; i++)
gpio_free(mux->gpio_base + mux->data.gpios[i]);
i2c_put_adapter(muxc->parent); i2c_put_adapter(muxc->parent);
return 0; return 0;
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
struct i2c_mux_pinctrl { struct i2c_mux_pinctrl {
struct pinctrl *pinctrl; struct pinctrl *pinctrl;
struct pinctrl_state **states; struct pinctrl_state *states[];
}; };
static int i2c_mux_pinctrl_select(struct i2c_mux_core *muxc, u32 chan) static int i2c_mux_pinctrl_select(struct i2c_mux_core *muxc, u32 chan)
...@@ -93,14 +93,13 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) ...@@ -93,14 +93,13 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
return PTR_ERR(parent); return PTR_ERR(parent);
muxc = i2c_mux_alloc(parent, dev, num_names, muxc = i2c_mux_alloc(parent, dev, num_names,
sizeof(*mux) + num_names * sizeof(*mux->states), struct_size(mux, states, num_names),
0, i2c_mux_pinctrl_select, NULL); 0, i2c_mux_pinctrl_select, NULL);
if (!muxc) { if (!muxc) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_put_parent; goto err_put_parent;
} }
mux = i2c_mux_priv(muxc); mux = i2c_mux_priv(muxc);
mux->states = (struct pinctrl_state **)(mux + 1);
platform_set_drvdata(pdev, muxc); platform_set_drvdata(pdev, muxc);
......
...@@ -507,38 +507,24 @@ static const struct at24_chip_data *at24_get_chip_data(struct device *dev) ...@@ -507,38 +507,24 @@ static const struct at24_chip_data *at24_get_chip_data(struct device *dev)
return cdata; return cdata;
} }
static void at24_remove_dummy_clients(struct at24_data *at24)
{
int i;
for (i = 1; i < at24->num_addresses; i++)
i2c_unregister_device(at24->client[i].client);
}
static int at24_make_dummy_client(struct at24_data *at24, unsigned int index, static int at24_make_dummy_client(struct at24_data *at24, unsigned int index,
struct regmap_config *regmap_config) struct regmap_config *regmap_config)
{ {
struct i2c_client *base_client, *dummy_client; struct i2c_client *base_client, *dummy_client;
unsigned short int addr;
struct regmap *regmap; struct regmap *regmap;
struct device *dev; struct device *dev;
base_client = at24->client[0].client; base_client = at24->client[0].client;
dev = &base_client->dev; dev = &base_client->dev;
addr = base_client->addr + index;
dummy_client = i2c_new_dummy(base_client->adapter, dummy_client = devm_i2c_new_dummy_device(dev, base_client->adapter,
base_client->addr + index); base_client->addr + index);
if (!dummy_client) { if (IS_ERR(dummy_client))
dev_err(dev, "address 0x%02x unavailable\n", addr); return PTR_ERR(dummy_client);
return -EADDRINUSE;
}
regmap = devm_regmap_init_i2c(dummy_client, regmap_config); regmap = devm_regmap_init_i2c(dummy_client, regmap_config);
if (IS_ERR(regmap)) { if (IS_ERR(regmap))
i2c_unregister_device(dummy_client);
return PTR_ERR(regmap); return PTR_ERR(regmap);
}
at24->client[index].client = dummy_client; at24->client[index].client = dummy_client;
at24->client[index].regmap = regmap; at24->client[index].regmap = regmap;
...@@ -580,7 +566,6 @@ static int at24_probe(struct i2c_client *client) ...@@ -580,7 +566,6 @@ static int at24_probe(struct i2c_client *client)
unsigned int i, num_addresses; unsigned int i, num_addresses;
struct at24_data *at24; struct at24_data *at24;
struct regmap *regmap; struct regmap *regmap;
size_t at24_size;
bool writable; bool writable;
u8 test_byte; u8 test_byte;
int err; int err;
...@@ -597,8 +582,8 @@ static int at24_probe(struct i2c_client *client) ...@@ -597,8 +582,8 @@ static int at24_probe(struct i2c_client *client)
if (err) if (err)
/* /*
* This is slow, but we can't know all eeproms, so we better * This is slow, but we can't know all eeproms, so we better
* play safe. Specifying custom eeprom-types via platform_data * play safe. Specifying custom eeprom-types via device tree
* is recommended anyhow. * or properties is recommended anyhow.
*/ */
page_size = 1; page_size = 1;
...@@ -664,8 +649,8 @@ static int at24_probe(struct i2c_client *client) ...@@ -664,8 +649,8 @@ static int at24_probe(struct i2c_client *client)
if (IS_ERR(regmap)) if (IS_ERR(regmap))
return PTR_ERR(regmap); return PTR_ERR(regmap);
at24_size = sizeof(*at24) + num_addresses * sizeof(struct at24_client); at24 = devm_kzalloc(dev, struct_size(at24, client, num_addresses),
at24 = devm_kzalloc(dev, at24_size, GFP_KERNEL); GFP_KERNEL);
if (!at24) if (!at24)
return -ENOMEM; return -ENOMEM;
...@@ -693,28 +678,9 @@ static int at24_probe(struct i2c_client *client) ...@@ -693,28 +678,9 @@ static int at24_probe(struct i2c_client *client)
/* use dummy devices for multiple-address chips */ /* use dummy devices for multiple-address chips */
for (i = 1; i < num_addresses; i++) { for (i = 1; i < num_addresses; i++) {
err = at24_make_dummy_client(at24, i, &regmap_config); err = at24_make_dummy_client(at24, i, &regmap_config);
if (err) { if (err)
at24_remove_dummy_clients(at24);
return err; return err;
} }
}
i2c_set_clientdata(client, at24);
/* enable runtime pm */
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
/*
* Perform a one-byte test read to verify that the
* chip is functional.
*/
err = at24_read(at24, 0, &test_byte, 1);
pm_runtime_idle(dev);
if (err) {
err = -ENODEV;
goto err_clients;
}
nvmem_config.name = dev_name(dev); nvmem_config.name = dev_name(dev);
nvmem_config.dev = dev; nvmem_config.dev = dev;
...@@ -731,9 +697,24 @@ static int at24_probe(struct i2c_client *client) ...@@ -731,9 +697,24 @@ static int at24_probe(struct i2c_client *client)
nvmem_config.size = byte_len; nvmem_config.size = byte_len;
at24->nvmem = devm_nvmem_register(dev, &nvmem_config); at24->nvmem = devm_nvmem_register(dev, &nvmem_config);
if (IS_ERR(at24->nvmem)) { if (IS_ERR(at24->nvmem))
err = PTR_ERR(at24->nvmem); return PTR_ERR(at24->nvmem);
goto err_clients;
i2c_set_clientdata(client, at24);
/* enable runtime pm */
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
/*
* Perform a one-byte test read to verify that the
* chip is functional.
*/
err = at24_read(at24, 0, &test_byte, 1);
pm_runtime_idle(dev);
if (err) {
pm_runtime_disable(dev);
return -ENODEV;
} }
dev_info(dev, "%u byte %s EEPROM, %s, %u bytes/write\n", dev_info(dev, "%u byte %s EEPROM, %s, %u bytes/write\n",
...@@ -741,21 +722,10 @@ static int at24_probe(struct i2c_client *client) ...@@ -741,21 +722,10 @@ static int at24_probe(struct i2c_client *client)
writable ? "writable" : "read-only", at24->write_max); writable ? "writable" : "read-only", at24->write_max);
return 0; return 0;
err_clients:
at24_remove_dummy_clients(at24);
pm_runtime_disable(dev);
return err;
} }
static int at24_remove(struct i2c_client *client) static int at24_remove(struct i2c_client *client)
{ {
struct at24_data *at24;
at24 = i2c_get_clientdata(client);
at24_remove_dummy_clients(at24);
pm_runtime_disable(&client->dev); pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev); pm_runtime_set_suspended(&client->dev);
......
...@@ -198,6 +198,7 @@ static int smo8800_remove(struct acpi_device *device) ...@@ -198,6 +198,7 @@ static int smo8800_remove(struct acpi_device *device)
return 0; return 0;
} }
/* NOTE: Keep this list in sync with drivers/i2c/busses/i2c-i801.c */
static const struct acpi_device_id smo8800_ids[] = { static const struct acpi_device_id smo8800_ids[] = {
{ "SMO8800", 0 }, { "SMO8800", 0 },
{ "SMO8801", 0 }, { "SMO8801", 0 },
......
...@@ -206,7 +206,17 @@ int ucsi_send_command(struct ucsi *ucsi, struct ucsi_control *ctrl, ...@@ -206,7 +206,17 @@ int ucsi_send_command(struct ucsi *ucsi, struct ucsi_control *ctrl,
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(ucsi_send_command);
int ucsi_resume(struct ucsi *ucsi)
{
struct ucsi_control ctrl;
/* Restore UCSI notification enable mask after system resume */
UCSI_CMD_SET_NTFY_ENABLE(ctrl, UCSI_ENABLE_NTFY_ALL);
return ucsi_send_command(ucsi, &ctrl, NULL, 0);
}
EXPORT_SYMBOL_GPL(ucsi_resume);
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
void ucsi_altmode_update_active(struct ucsi_connector *con) void ucsi_altmode_update_active(struct ucsi_connector *con)
......
...@@ -430,6 +430,7 @@ int ucsi_send_command(struct ucsi *ucsi, struct ucsi_control *ctrl, ...@@ -430,6 +430,7 @@ int ucsi_send_command(struct ucsi *ucsi, struct ucsi_control *ctrl,
void *retval, size_t size); void *retval, size_t size);
void ucsi_altmode_update_active(struct ucsi_connector *con); void ucsi_altmode_update_active(struct ucsi_connector *con);
int ucsi_resume(struct ucsi *ucsi);
#if IS_ENABLED(CONFIG_TYPEC_DP_ALTMODE) #if IS_ENABLED(CONFIG_TYPEC_DP_ALTMODE)
struct typec_altmode * struct typec_altmode *
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include "ucsi.h" #include "ucsi.h"
...@@ -107,12 +109,21 @@ struct version_format { ...@@ -107,12 +109,21 @@ struct version_format {
__le16 build; __le16 build;
u8 patch; u8 patch;
u8 ver; u8 ver;
#define CCG_VERSION_PATCH(x) ((x) << 16)
#define CCG_VERSION(x) ((x) << 24)
#define CCG_VERSION_MIN_SHIFT (0) #define CCG_VERSION_MIN_SHIFT (0)
#define CCG_VERSION_MIN_MASK (0xf << CCG_VERSION_MIN_SHIFT) #define CCG_VERSION_MIN_MASK (0xf << CCG_VERSION_MIN_SHIFT)
#define CCG_VERSION_MAJ_SHIFT (4) #define CCG_VERSION_MAJ_SHIFT (4)
#define CCG_VERSION_MAJ_MASK (0xf << CCG_VERSION_MAJ_SHIFT) #define CCG_VERSION_MAJ_MASK (0xf << CCG_VERSION_MAJ_SHIFT)
} __packed; } __packed;
/*
* Firmware version 3.1.10 or earlier, built for NVIDIA has known issue
* of missing interrupt when a device is connected for runtime resume
*/
#define CCG_FW_BUILD_NVIDIA (('n' << 8) | 'v')
#define CCG_OLD_FW_VERSION (CCG_VERSION(0x31) | CCG_VERSION_PATCH(10))
struct version_info { struct version_info {
struct version_format base; struct version_format base;
struct version_format app; struct version_format app;
...@@ -170,6 +181,7 @@ struct ucsi_ccg { ...@@ -170,6 +181,7 @@ struct ucsi_ccg {
struct ccg_dev_info info; struct ccg_dev_info info;
/* version info for boot, primary and secondary */ /* version info for boot, primary and secondary */
struct version_info version[FW2 + 1]; struct version_info version[FW2 + 1];
u32 fw_version;
/* CCG HPI communication flags */ /* CCG HPI communication flags */
unsigned long flags; unsigned long flags;
#define RESET_PENDING 0 #define RESET_PENDING 0
...@@ -183,6 +195,8 @@ struct ucsi_ccg { ...@@ -183,6 +195,8 @@ struct ucsi_ccg {
/* fw build with vendor information */ /* fw build with vendor information */
u16 fw_build; u16 fw_build;
bool run_isr; /* flag to call ISR routine during resume */
struct work_struct pm_work;
}; };
static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len) static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
...@@ -210,6 +224,19 @@ static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len) ...@@ -210,6 +224,19 @@ static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
if (quirks && quirks->max_read_len) if (quirks && quirks->max_read_len)
max_read_len = quirks->max_read_len; max_read_len = quirks->max_read_len;
if (uc->fw_build == CCG_FW_BUILD_NVIDIA &&
uc->fw_version <= CCG_OLD_FW_VERSION) {
mutex_lock(&uc->lock);
/*
* Do not schedule pm_work to run ISR in
* ucsi_ccg_runtime_resume() after pm_runtime_get_sync()
* since we are already in ISR path.
*/
uc->run_isr = false;
mutex_unlock(&uc->lock);
}
pm_runtime_get_sync(uc->dev);
while (rem_len > 0) { while (rem_len > 0) {
msgs[1].buf = &data[len - rem_len]; msgs[1].buf = &data[len - rem_len];
rlen = min_t(u16, rem_len, max_read_len); rlen = min_t(u16, rem_len, max_read_len);
...@@ -218,12 +245,14 @@ static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len) ...@@ -218,12 +245,14 @@ static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
status = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); status = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
if (status < 0) { if (status < 0) {
dev_err(uc->dev, "i2c_transfer failed %d\n", status); dev_err(uc->dev, "i2c_transfer failed %d\n", status);
pm_runtime_put_sync(uc->dev);
return status; return status;
} }
rab += rlen; rab += rlen;
rem_len -= rlen; rem_len -= rlen;
} }
pm_runtime_put_sync(uc->dev);
return 0; return 0;
} }
...@@ -249,13 +278,28 @@ static int ccg_write(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len) ...@@ -249,13 +278,28 @@ static int ccg_write(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
msgs[0].len = len + sizeof(rab); msgs[0].len = len + sizeof(rab);
msgs[0].buf = buf; msgs[0].buf = buf;
if (uc->fw_build == CCG_FW_BUILD_NVIDIA &&
uc->fw_version <= CCG_OLD_FW_VERSION) {
mutex_lock(&uc->lock);
/*
* Do not schedule pm_work to run ISR in
* ucsi_ccg_runtime_resume() after pm_runtime_get_sync()
* since we are already in ISR path.
*/
uc->run_isr = false;
mutex_unlock(&uc->lock);
}
pm_runtime_get_sync(uc->dev);
status = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); status = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
if (status < 0) { if (status < 0) {
dev_err(uc->dev, "i2c_transfer failed %d\n", status); dev_err(uc->dev, "i2c_transfer failed %d\n", status);
pm_runtime_put_sync(uc->dev);
kfree(buf); kfree(buf);
return status; return status;
} }
pm_runtime_put_sync(uc->dev);
kfree(buf); kfree(buf);
return 0; return 0;
} }
...@@ -375,6 +419,13 @@ static irqreturn_t ccg_irq_handler(int irq, void *data) ...@@ -375,6 +419,13 @@ static irqreturn_t ccg_irq_handler(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void ccg_pm_workaround_work(struct work_struct *pm_work)
{
struct ucsi_ccg *uc = container_of(pm_work, struct ucsi_ccg, pm_work);
ucsi_notify(uc->ucsi);
}
static int get_fw_info(struct ucsi_ccg *uc) static int get_fw_info(struct ucsi_ccg *uc)
{ {
int err; int err;
...@@ -384,6 +435,9 @@ static int get_fw_info(struct ucsi_ccg *uc) ...@@ -384,6 +435,9 @@ static int get_fw_info(struct ucsi_ccg *uc)
if (err < 0) if (err < 0)
return err; return err;
uc->fw_version = CCG_VERSION(uc->version[FW2].app.ver) |
CCG_VERSION_PATCH(uc->version[FW2].app.patch);
err = ccg_read(uc, CCGX_RAB_DEVICE_MODE, (u8 *)(&uc->info), err = ccg_read(uc, CCGX_RAB_DEVICE_MODE, (u8 *)(&uc->info),
sizeof(uc->info)); sizeof(uc->info));
if (err < 0) if (err < 0)
...@@ -732,11 +786,12 @@ static bool ccg_check_fw_version(struct ucsi_ccg *uc, const char *fw_name, ...@@ -732,11 +786,12 @@ static bool ccg_check_fw_version(struct ucsi_ccg *uc, const char *fw_name,
} }
/* compare input version with FWCT version */ /* compare input version with FWCT version */
cur_version = le16_to_cpu(app->build) | app->patch << 16 | cur_version = le16_to_cpu(app->build) | CCG_VERSION_PATCH(app->patch) |
app->ver << 24; CCG_VERSION(app->ver);
new_version = le16_to_cpu(fw_cfg.app.build) | fw_cfg.app.patch << 16 | new_version = le16_to_cpu(fw_cfg.app.build) |
fw_cfg.app.ver << 24; CCG_VERSION_PATCH(fw_cfg.app.patch) |
CCG_VERSION(fw_cfg.app.ver);
if (!ccg_check_vendor_version(uc, app, &fw_cfg)) if (!ccg_check_vendor_version(uc, app, &fw_cfg))
goto out_release_firmware; goto out_release_firmware;
...@@ -1078,8 +1133,10 @@ static int ucsi_ccg_probe(struct i2c_client *client, ...@@ -1078,8 +1133,10 @@ static int ucsi_ccg_probe(struct i2c_client *client,
uc->ppm.sync = ucsi_ccg_sync; uc->ppm.sync = ucsi_ccg_sync;
uc->dev = dev; uc->dev = dev;
uc->client = client; uc->client = client;
uc->run_isr = true;
mutex_init(&uc->lock); mutex_init(&uc->lock);
INIT_WORK(&uc->work, ccg_update_firmware); INIT_WORK(&uc->work, ccg_update_firmware);
INIT_WORK(&uc->pm_work, ccg_pm_workaround_work);
/* Only fail FW flashing when FW build information is not provided */ /* Only fail FW flashing when FW build information is not provided */
status = device_property_read_u16(dev, "ccgx,firmware-build", status = device_property_read_u16(dev, "ccgx,firmware-build",
...@@ -1136,6 +1193,10 @@ static int ucsi_ccg_probe(struct i2c_client *client, ...@@ -1136,6 +1193,10 @@ static int ucsi_ccg_probe(struct i2c_client *client,
if (status) if (status)
dev_err(uc->dev, "cannot create sysfs group: %d\n", status); dev_err(uc->dev, "cannot create sysfs group: %d\n", status);
pm_runtime_set_active(uc->dev);
pm_runtime_enable(uc->dev);
pm_runtime_idle(uc->dev);
return 0; return 0;
} }
...@@ -1143,8 +1204,10 @@ static int ucsi_ccg_remove(struct i2c_client *client) ...@@ -1143,8 +1204,10 @@ static int ucsi_ccg_remove(struct i2c_client *client)
{ {
struct ucsi_ccg *uc = i2c_get_clientdata(client); struct ucsi_ccg *uc = i2c_get_clientdata(client);
cancel_work_sync(&uc->pm_work);
cancel_work_sync(&uc->work); cancel_work_sync(&uc->work);
ucsi_unregister_ppm(uc->ucsi); ucsi_unregister_ppm(uc->ucsi);
pm_runtime_disable(uc->dev);
free_irq(uc->irq, uc); free_irq(uc->irq, uc);
sysfs_remove_group(&uc->dev->kobj, &ucsi_ccg_attr_group); sysfs_remove_group(&uc->dev->kobj, &ucsi_ccg_attr_group);
...@@ -1157,9 +1220,56 @@ static const struct i2c_device_id ucsi_ccg_device_id[] = { ...@@ -1157,9 +1220,56 @@ static const struct i2c_device_id ucsi_ccg_device_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, ucsi_ccg_device_id); MODULE_DEVICE_TABLE(i2c, ucsi_ccg_device_id);
static int ucsi_ccg_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct ucsi_ccg *uc = i2c_get_clientdata(client);
return ucsi_resume(uc->ucsi);
}
static int ucsi_ccg_runtime_suspend(struct device *dev)
{
return 0;
}
static int ucsi_ccg_runtime_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct ucsi_ccg *uc = i2c_get_clientdata(client);
bool schedule = true;
/*
* Firmware version 3.1.10 or earlier, built for NVIDIA has known issue
* of missing interrupt when a device is connected for runtime resume.
* Schedule a work to call ISR as a workaround.
*/
if (uc->fw_build == CCG_FW_BUILD_NVIDIA &&
uc->fw_version <= CCG_OLD_FW_VERSION) {
mutex_lock(&uc->lock);
if (!uc->run_isr) {
uc->run_isr = true;
schedule = false;
}
mutex_unlock(&uc->lock);
if (schedule)
schedule_work(&uc->pm_work);
}
return 0;
}
static const struct dev_pm_ops ucsi_ccg_pm = {
.resume = ucsi_ccg_resume,
.runtime_suspend = ucsi_ccg_runtime_suspend,
.runtime_resume = ucsi_ccg_runtime_resume,
};
static struct i2c_driver ucsi_ccg_driver = { static struct i2c_driver ucsi_ccg_driver = {
.driver = { .driver = {
.name = "ucsi_ccg", .name = "ucsi_ccg",
.pm = &ucsi_ccg_pm,
}, },
.probe = ucsi_ccg_probe, .probe = ucsi_ccg_probe,
.remove = ucsi_ccg_remove, .remove = ucsi_ccg_remove,
......
/* SPDX-License-Identifier: GPL-2.0-or-later */ /* SPDX-License-Identifier: GPL-2.0-or-later */
/* ------------------------------------------------------------------------- */ /*
/* */ * i2c.h - definitions for the Linux i2c bus interface
/* i2c.h - definitions for the i2c-bus interface */ * Copyright (C) 1995-2000 Simon G. Vogl
/* */ * Copyright (C) 2013-2019 Wolfram Sang <wsa@the-dreams.de>
/* ------------------------------------------------------------------------- */ *
/* Copyright (C) 1995-2000 Simon G. Vogl * With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
* Frodo Looijaard <frodol@dds.nl>
*/ */
/* ------------------------------------------------------------------------- */
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
Frodo Looijaard <frodol@dds.nl> */
#ifndef _LINUX_I2C_H #ifndef _LINUX_I2C_H
#define _LINUX_I2C_H #define _LINUX_I2C_H
...@@ -40,7 +36,8 @@ struct i2c_device_identity; ...@@ -40,7 +36,8 @@ struct i2c_device_identity;
union i2c_smbus_data; union i2c_smbus_data;
struct i2c_board_info; struct i2c_board_info;
enum i2c_slave_event; enum i2c_slave_event;
typedef int (*i2c_slave_cb_t)(struct i2c_client *, enum i2c_slave_event, u8 *); typedef int (*i2c_slave_cb_t)(struct i2c_client *client,
enum i2c_slave_event event, u8 *val);
struct module; struct module;
struct property_entry; struct property_entry;
...@@ -257,16 +254,16 @@ struct i2c_driver { ...@@ -257,16 +254,16 @@ struct i2c_driver {
unsigned int class; unsigned int class;
/* Standard driver model interfaces */ /* Standard driver model interfaces */
int (*probe)(struct i2c_client *, const struct i2c_device_id *); int (*probe)(struct i2c_client *client, const struct i2c_device_id *id);
int (*remove)(struct i2c_client *); int (*remove)(struct i2c_client *client);
/* New driver model interface to aid the seamless removal of the /* New driver model interface to aid the seamless removal of the
* current probe()'s, more commonly unused than used second parameter. * current probe()'s, more commonly unused than used second parameter.
*/ */
int (*probe_new)(struct i2c_client *); int (*probe_new)(struct i2c_client *client);
/* driver model interfaces that don't relate to enumeration */ /* driver model interfaces that don't relate to enumeration */
void (*shutdown)(struct i2c_client *); void (*shutdown)(struct i2c_client *client);
/* Alert callback, for example for the SMBus alert protocol. /* Alert callback, for example for the SMBus alert protocol.
* The format and meaning of the data value depends on the protocol. * The format and meaning of the data value depends on the protocol.
...@@ -275,7 +272,7 @@ struct i2c_driver { ...@@ -275,7 +272,7 @@ struct i2c_driver {
* For the SMBus Host Notify protocol, the data corresponds to the * For the SMBus Host Notify protocol, the data corresponds to the
* 16-bit payload data reported by the slave device acting as master. * 16-bit payload data reported by the slave device acting as master.
*/ */
void (*alert)(struct i2c_client *, enum i2c_alert_protocol protocol, void (*alert)(struct i2c_client *client, enum i2c_alert_protocol protocol,
unsigned int data); unsigned int data);
/* a ioctl like command that can be used to perform specific functions /* a ioctl like command that can be used to perform specific functions
...@@ -287,7 +284,7 @@ struct i2c_driver { ...@@ -287,7 +284,7 @@ struct i2c_driver {
const struct i2c_device_id *id_table; const struct i2c_device_id *id_table;
/* Device detection callback for automatic device creation */ /* Device detection callback for automatic device creation */
int (*detect)(struct i2c_client *, struct i2c_board_info *); int (*detect)(struct i2c_client *client, struct i2c_board_info *info);
const unsigned short *address_list; const unsigned short *address_list;
struct list_head clients; struct list_head clients;
...@@ -297,8 +294,7 @@ struct i2c_driver { ...@@ -297,8 +294,7 @@ struct i2c_driver {
/** /**
* struct i2c_client - represent an I2C slave device * struct i2c_client - represent an I2C slave device
* @flags: I2C_CLIENT_TEN indicates the device uses a ten bit chip address; * @flags: see I2C_CLIENT_* for possible flags
* I2C_CLIENT_PEC indicates it uses SMBus Packet Error Checking
* @addr: Address used on the I2C bus connected to the parent adapter. * @addr: Address used on the I2C bus connected to the parent adapter.
* @name: Indicates the type of the device, usually a chip name that's * @name: Indicates the type of the device, usually a chip name that's
* generic enough to hide second-sourcing and compatible revisions. * generic enough to hide second-sourcing and compatible revisions.
...@@ -316,6 +312,15 @@ struct i2c_driver { ...@@ -316,6 +312,15 @@ struct i2c_driver {
*/ */
struct i2c_client { struct i2c_client {
unsigned short flags; /* div., see below */ unsigned short flags; /* div., see below */
#define I2C_CLIENT_PEC 0x04 /* Use Packet Error Checking */
#define I2C_CLIENT_TEN 0x10 /* we have a ten bit chip address */
/* Must equal I2C_M_TEN below */
#define I2C_CLIENT_SLAVE 0x20 /* we are the slave */
#define I2C_CLIENT_HOST_NOTIFY 0x40 /* We want to use I2C host notify */
#define I2C_CLIENT_WAKE 0x80 /* for board_info; true iff can wake */
#define I2C_CLIENT_SCCB 0x9000 /* Use Omnivision SCCB protocol */
/* Must match I2C_M_STOP|IGNORE_NAK */
unsigned short addr; /* chip address - NOTE: 7bit */ unsigned short addr; /* chip address - NOTE: 7bit */
/* addresses are stored in the */ /* addresses are stored in the */
/* _LOWER_ 7 bits */ /* _LOWER_ 7 bits */
...@@ -437,6 +442,9 @@ struct i2c_board_info { ...@@ -437,6 +442,9 @@ struct i2c_board_info {
extern struct i2c_client * extern struct i2c_client *
i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info); i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info);
extern struct i2c_client *
i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *info);
/* If you don't know the exact address of an I2C device, use this variant /* If you don't know the exact address of an I2C device, use this variant
* instead, which can probe for device presence in a list of possible * instead, which can probe for device presence in a list of possible
* addresses. The "probe" callback function is optional. If it is provided, * addresses. The "probe" callback function is optional. If it is provided,
...@@ -447,10 +455,10 @@ extern struct i2c_client * ...@@ -447,10 +455,10 @@ extern struct i2c_client *
i2c_new_probed_device(struct i2c_adapter *adap, i2c_new_probed_device(struct i2c_adapter *adap,
struct i2c_board_info *info, struct i2c_board_info *info,
unsigned short const *addr_list, unsigned short const *addr_list,
int (*probe)(struct i2c_adapter *, unsigned short addr)); int (*probe)(struct i2c_adapter *adap, unsigned short addr));
/* Common custom probe functions */ /* Common custom probe functions */
extern int i2c_probe_func_quick_read(struct i2c_adapter *, unsigned short addr); extern int i2c_probe_func_quick_read(struct i2c_adapter *adap, unsigned short addr);
/* For devices that use several addresses, use i2c_new_dummy() to make /* For devices that use several addresses, use i2c_new_dummy() to make
* client handles for the extra addresses. * client handles for the extra addresses.
...@@ -458,6 +466,9 @@ extern int i2c_probe_func_quick_read(struct i2c_adapter *, unsigned short addr); ...@@ -458,6 +466,9 @@ extern int i2c_probe_func_quick_read(struct i2c_adapter *, unsigned short addr);
extern struct i2c_client * extern struct i2c_client *
i2c_new_dummy(struct i2c_adapter *adap, u16 address); i2c_new_dummy(struct i2c_adapter *adap, u16 address);
extern struct i2c_client *
i2c_new_dummy_device(struct i2c_adapter *adapter, u16 address);
extern struct i2c_client * extern struct i2c_client *
devm_i2c_new_dummy_device(struct device *dev, struct i2c_adapter *adap, u16 address); devm_i2c_new_dummy_device(struct device *dev, struct i2c_adapter *adap, u16 address);
...@@ -466,7 +477,7 @@ i2c_new_secondary_device(struct i2c_client *client, ...@@ -466,7 +477,7 @@ i2c_new_secondary_device(struct i2c_client *client,
const char *name, const char *name,
u16 default_addr); u16 default_addr);
extern void i2c_unregister_device(struct i2c_client *); extern void i2c_unregister_device(struct i2c_client *client);
#endif /* I2C */ #endif /* I2C */
/* Mainboard arch_initcall() code should register all its I2C devices. /* Mainboard arch_initcall() code should register all its I2C devices.
...@@ -551,9 +562,9 @@ struct i2c_algorithm { ...@@ -551,9 +562,9 @@ struct i2c_algorithm {
* The main operations are wrapped by i2c_lock_bus and i2c_unlock_bus. * The main operations are wrapped by i2c_lock_bus and i2c_unlock_bus.
*/ */
struct i2c_lock_operations { struct i2c_lock_operations {
void (*lock_bus)(struct i2c_adapter *, unsigned int flags); void (*lock_bus)(struct i2c_adapter *adapter, unsigned int flags);
int (*trylock_bus)(struct i2c_adapter *, unsigned int flags); int (*trylock_bus)(struct i2c_adapter *adapter, unsigned int flags);
void (*unlock_bus)(struct i2c_adapter *, unsigned int flags); void (*unlock_bus)(struct i2c_adapter *adapter, unsigned int flags);
}; };
/** /**
...@@ -703,14 +714,14 @@ struct i2c_adapter { ...@@ -703,14 +714,14 @@ struct i2c_adapter {
}; };
#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev) #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
static inline void *i2c_get_adapdata(const struct i2c_adapter *dev) static inline void *i2c_get_adapdata(const struct i2c_adapter *adap)
{ {
return dev_get_drvdata(&dev->dev); return dev_get_drvdata(&adap->dev);
} }
static inline void i2c_set_adapdata(struct i2c_adapter *dev, void *data) static inline void i2c_set_adapdata(struct i2c_adapter *adap, void *data)
{ {
dev_set_drvdata(&dev->dev, data); dev_set_drvdata(&adap->dev, data);
} }
static inline struct i2c_adapter * static inline struct i2c_adapter *
...@@ -726,7 +737,7 @@ i2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter) ...@@ -726,7 +737,7 @@ i2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter)
return NULL; return NULL;
} }
int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *)); int i2c_for_each_dev(void *data, int (*fn)(struct device *dev, void *data));
/* Adapter locking functions, exported for shared pin cases */ /* Adapter locking functions, exported for shared pin cases */
#define I2C_LOCK_ROOT_ADAPTER BIT(0) #define I2C_LOCK_ROOT_ADAPTER BIT(0)
...@@ -802,16 +813,6 @@ static inline void i2c_mark_adapter_resumed(struct i2c_adapter *adap) ...@@ -802,16 +813,6 @@ static inline void i2c_mark_adapter_resumed(struct i2c_adapter *adap)
i2c_unlock_bus(adap, I2C_LOCK_ROOT_ADAPTER); i2c_unlock_bus(adap, I2C_LOCK_ROOT_ADAPTER);
} }
/*flags for the client struct: */
#define I2C_CLIENT_PEC 0x04 /* Use Packet Error Checking */
#define I2C_CLIENT_TEN 0x10 /* we have a ten bit chip address */
/* Must equal I2C_M_TEN below */
#define I2C_CLIENT_SLAVE 0x20 /* we are the slave */
#define I2C_CLIENT_HOST_NOTIFY 0x40 /* We want to use I2C host notify */
#define I2C_CLIENT_WAKE 0x80 /* for board_info; true iff can wake */
#define I2C_CLIENT_SCCB 0x9000 /* Use Omnivision SCCB protocol */
/* Must match I2C_M_STOP|IGNORE_NAK */
/* i2c adapter classes (bitmask) */ /* i2c adapter classes (bitmask) */
#define I2C_CLASS_HWMON (1<<0) /* lm_sensors, ... */ #define I2C_CLASS_HWMON (1<<0) /* lm_sensors, ... */
#define I2C_CLASS_DDC (1<<3) /* DDC bus on graphics adapters */ #define I2C_CLASS_DDC (1<<3) /* DDC bus on graphics adapters */
...@@ -832,12 +833,12 @@ static inline void i2c_mark_adapter_resumed(struct i2c_adapter *adap) ...@@ -832,12 +833,12 @@ static inline void i2c_mark_adapter_resumed(struct i2c_adapter *adap)
/* administration... /* administration...
*/ */
#if IS_ENABLED(CONFIG_I2C) #if IS_ENABLED(CONFIG_I2C)
extern int i2c_add_adapter(struct i2c_adapter *); extern int i2c_add_adapter(struct i2c_adapter *adap);
extern void i2c_del_adapter(struct i2c_adapter *); extern void i2c_del_adapter(struct i2c_adapter *adap);
extern int i2c_add_numbered_adapter(struct i2c_adapter *); extern int i2c_add_numbered_adapter(struct i2c_adapter *adap);
extern int i2c_register_driver(struct module *, struct i2c_driver *); extern int i2c_register_driver(struct module *owner, struct i2c_driver *driver);
extern void i2c_del_driver(struct i2c_driver *); extern void i2c_del_driver(struct i2c_driver *driver);
/* use a define to avoid include chaining to get THIS_MODULE */ /* use a define to avoid include chaining to get THIS_MODULE */
#define i2c_add_driver(driver) \ #define i2c_add_driver(driver) \
......
...@@ -19,10 +19,6 @@ ...@@ -19,10 +19,6 @@
* position * position
* @n_values: Number of multiplexer positions (busses to instantiate) * @n_values: Number of multiplexer positions (busses to instantiate)
* @classes: Optional I2C auto-detection classes * @classes: Optional I2C auto-detection classes
* @gpio_chip: Optional GPIO chip name; if set, GPIO pin numbers are given
* relative to the base GPIO number of that chip
* @gpios: Array of GPIO numbers used to control MUX
* @n_gpios: Number of GPIOs used to control MUX
* @idle: Bitmask to write to MUX when idle or GPIO_I2CMUX_NO_IDLE if not used * @idle: Bitmask to write to MUX when idle or GPIO_I2CMUX_NO_IDLE if not used
*/ */
struct i2c_mux_gpio_platform_data { struct i2c_mux_gpio_platform_data {
...@@ -31,9 +27,6 @@ struct i2c_mux_gpio_platform_data { ...@@ -31,9 +27,6 @@ struct i2c_mux_gpio_platform_data {
const unsigned *values; const unsigned *values;
int n_values; int n_values;
const unsigned *classes; const unsigned *classes;
char *gpio_chip;
const unsigned *gpios;
int n_gpios;
unsigned idle; unsigned idle;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment