Commit 4008e6a9 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull i2c updates from Wolfram Sang:
 "This contains two bigger than usual tree-wide changes this time. They
  all have proper acks, caused no merge conflicts in linux-next where
  they have been for a while. They are namely:

   - to-gpiod conversion of the i2c-gpio driver and its users (touching
     arch/* and drivers/mfd/*)

   - adding a sbs-manager based on I2C core updates to SMBus alerts
     (touching drivers/power/*)

  Other notable changes:

   - i2c_boardinfo can now carry a dev_name to be used when the device
     is created. This is because some devices in ACPI world need fixed
     names to find the regulators.

   - the designware driver got a long discussed overhaul of its PM
     handling. img-scb and davinci got PM support, too.

   - at24 driver has way better OF support. And it has a new maintainer.
     Thanks Bartosz for stepping up!

  The rest is regular driver updates and fixes"

* 'i2c/for-4.15' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (55 commits)
  ARM: sa1100: simpad: Correct I2C GPIO offsets
  i2c: aspeed: Deassert reset in probe
  eeprom: at24: Add OF device ID table
  MAINTAINERS: new maintainer for AT24 driver
  i2c: nuc900: remove platform_data, too
  i2c: thunderx: Remove duplicate NULL check
  i2c: taos-evm: Remove duplicate NULL check
  i2c: Make i2c_unregister_device() NULL-aware
  i2c: xgene-slimpro: Support v2
  i2c: mpc: remove useless variable initialization
  i2c: omap: Trigger bus recovery in lockup case
  i2c: gpio: Add support for named gpios in DT
  dt-bindings: i2c: i2c-gpio: Add support for named gpios
  i2c: gpio: Local vars in probe
  i2c: gpio: Augment all boardfiles to use open drain
  i2c: gpio: Enforce open drain through gpiolib
  gpio: Make it possible for consumers to enforce open drain
  i2c: gpio: Convert to use descriptors
  power: supply: sbs-message: fix some code style issues
  power: supply: sbs-battery: remove unchecked return var
  ...
parents 6aa2f944 d82e99a6
...@@ -36,6 +36,8 @@ Optional properties: ...@@ -36,6 +36,8 @@ Optional properties:
- read-only: this parameterless property disables writes to the eeprom - read-only: this parameterless property disables writes to the eeprom
- size: total eeprom size in bytes
Example: Example:
eeprom@52 { eeprom@52 {
......
...@@ -7,7 +7,9 @@ Required Properties: ...@@ -7,7 +7,9 @@ Required Properties:
- compatible : should be "aspeed,ast2400-i2c-bus" - compatible : should be "aspeed,ast2400-i2c-bus"
or "aspeed,ast2500-i2c-bus" or "aspeed,ast2500-i2c-bus"
- clocks : root clock of bus, should reference the APB - clocks : root clock of bus, should reference the APB
clock clock in the second cell
- resets : phandle to reset controller with the reset number in
the second cell
- interrupts : interrupt number - interrupts : interrupt number
- interrupt-parent : interrupt controller for bus, should reference a - interrupt-parent : interrupt controller for bus, should reference a
aspeed,ast2400-i2c-ic or aspeed,ast2500-i2c-ic aspeed,ast2400-i2c-ic or aspeed,ast2500-i2c-ic
...@@ -40,7 +42,8 @@ i2c { ...@@ -40,7 +42,8 @@ i2c {
#interrupt-cells = <1>; #interrupt-cells = <1>;
reg = <0x40 0x40>; reg = <0x40 0x40>;
compatible = "aspeed,ast2400-i2c-bus"; compatible = "aspeed,ast2400-i2c-bus";
clocks = <&clk_apb>; clocks = <&syscon ASPEED_CLK_APB>;
resets = <&syscon ASPEED_RESET_I2C>;
bus-frequency = <100000>; bus-frequency = <100000>;
interrupts = <0>; interrupts = <0>;
interrupt-parent = <&i2c_ic>; interrupt-parent = <&i2c_ic>;
......
...@@ -6,6 +6,18 @@ davinci/keystone i2c interface contains. ...@@ -6,6 +6,18 @@ davinci/keystone i2c interface contains.
Required properties: Required properties:
- compatible: "ti,davinci-i2c" or "ti,keystone-i2c"; - compatible: "ti,davinci-i2c" or "ti,keystone-i2c";
- reg : Offset and length of the register set for the device - reg : Offset and length of the register set for the device
- clocks: I2C functional clock phandle.
For 66AK2G this property should be set per binding,
Documentation/devicetree/bindings/clock/ti,sci-clk.txt
SoC-specific Required Properties:
The following are mandatory properties for Keystone 2 66AK2G SoCs only:
- power-domains: Should contain a phandle to a PM domain provider node
and an args specifier containing the I2C device id
value. This property is as per the binding,
Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
Recommended properties : Recommended properties :
- interrupts : standard interrupt property. - interrupts : standard interrupt property.
......
...@@ -2,25 +2,39 @@ Device-Tree bindings for i2c gpio driver ...@@ -2,25 +2,39 @@ Device-Tree bindings for i2c gpio driver
Required properties: Required properties:
- compatible = "i2c-gpio"; - compatible = "i2c-gpio";
- gpios: sda and scl gpio - sda-gpios: gpio used for the sda signal, this should be flagged as
active high using open drain with (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)
from <dt-bindings/gpio/gpio.h> since the signal is by definition
open drain.
- scl-gpios: gpio used for the scl signal, this should be flagged as
active high using open drain with (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)
from <dt-bindings/gpio/gpio.h> since the signal is by definition
open drain.
Optional properties: Optional properties:
- i2c-gpio,sda-open-drain: sda as open drain
- i2c-gpio,scl-open-drain: scl as open drain
- i2c-gpio,scl-output-only: scl as output only - i2c-gpio,scl-output-only: scl as output only
- i2c-gpio,delay-us: delay between GPIO operations (may depend on each platform) - i2c-gpio,delay-us: delay between GPIO operations (may depend on each platform)
- i2c-gpio,timeout-ms: timeout to get data - i2c-gpio,timeout-ms: timeout to get data
Deprecated properties, do not use in new device tree sources:
- gpios: sda and scl gpio, alternative for {sda,scl}-gpios
- i2c-gpio,sda-open-drain: this means that something outside of our
control has put the GPIO line used for SDA into open drain mode, and
that something is not the GPIO chip. It is essentially an
inconsistency flag.
- i2c-gpio,scl-open-drain: this means that something outside of our
control has put the GPIO line used for SCL into open drain mode, and
that something is not the GPIO chip. It is essentially an
inconsistency flag.
Example nodes: Example nodes:
#include <dt-bindings/gpio/gpio.h>
i2c@0 { i2c@0 {
compatible = "i2c-gpio"; compatible = "i2c-gpio";
gpios = <&pioA 23 0 /* sda */ sda-gpios = <&pioA 23 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
&pioA 24 0 /* scl */ scl-gpios = <&pioA 24 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
>;
i2c-gpio,sda-open-drain;
i2c-gpio,scl-open-drain;
i2c-gpio,delay-us = <2>; /* ~100 kHz */ i2c-gpio,delay-us = <2>; /* ~100 kHz */
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
......
...@@ -6,10 +6,10 @@ multiplexer/switch will have one child node for each child bus. ...@@ -6,10 +6,10 @@ multiplexer/switch will have one child node for each child bus.
Optional properties: Optional properties:
- #address-cells = <1>; - #address-cells = <1>;
This property is required is the i2c-mux child node does not exist. This property is required if the i2c-mux child node does not exist.
- #size-cells = <0>; - #size-cells = <0>;
This property is required is the i2c-mux child node does not exist. This property is required if the i2c-mux child node does not exist.
- i2c-mux - i2c-mux
For i2c multiplexers/switches that have child nodes that are a mixture For i2c multiplexers/switches that have child nodes that are a mixture
......
...@@ -13,6 +13,7 @@ Required properties: ...@@ -13,6 +13,7 @@ Required properties:
"renesas,i2c-r8a7794" if the device is a part of a R8A7794 SoC. "renesas,i2c-r8a7794" if the device is a part of a R8A7794 SoC.
"renesas,i2c-r8a7795" if the device is a part of a R8A7795 SoC. "renesas,i2c-r8a7795" if the device is a part of a R8A7795 SoC.
"renesas,i2c-r8a7796" if the device is a part of a R8A7796 SoC. "renesas,i2c-r8a7796" if the device is a part of a R8A7796 SoC.
"renesas,i2c-r8a77970" if the device is a part of a R8A77970 SoC.
"renesas,rcar-gen1-i2c" for a generic R-Car Gen1 compatible device. "renesas,rcar-gen1-i2c" for a generic R-Car Gen1 compatible device.
"renesas,rcar-gen2-i2c" for a generic R-Car Gen2 or RZ/G1 compatible "renesas,rcar-gen2-i2c" for a generic R-Car Gen2 or RZ/G1 compatible
device. device.
......
...@@ -59,8 +59,8 @@ wants to support one of the below features, it should adapt the bindings below. ...@@ -59,8 +59,8 @@ wants to support one of the below features, it should adapt the bindings below.
interrupts used by the device. interrupts used by the device.
- interrupt-names - interrupt-names
"irq" and "wakeup" names are recognized by I2C core, other names are "irq", "wakeup" and "smbus_alert" names are recognized by I2C core,
left to individual drivers. other names are left to individual drivers.
- host-notify - host-notify
device uses SMBus host notify protocol instead of interrupt line. device uses SMBus host notify protocol instead of interrupt line.
......
Binding for sbs-manager
Required properties:
- compatible: "<vendor>,<part-number>", "sbs,sbs-charger" as fallback. The part
number compatible string might be used in order to take care of vendor
specific registers.
- reg: integer, i2c address of the device. Should be <0xa>.
Optional properties:
- gpio-controller: Marks the port as GPIO controller.
See "gpio-specifier" in .../devicetree/bindings/gpio/gpio.txt.
- #gpio-cells: Should be <2>. The first cell is the pin number, the second cell
is used to specify optional parameters:
See "gpio-specifier" in .../devicetree/bindings/gpio/gpio.txt.
From OS view the device is basically an i2c-mux used to communicate with up to
four smart battery devices at address 0xb. The driver actually implements this
behaviour. So standard i2c-mux nodes can be used to register up to four slave
batteries. Channels will be numerated starting from 1 to 4.
Example:
batman@a {
compatible = "lltc,ltc1760", "sbs,sbs-manager";
reg = <0x0a>;
#address-cells = <1>;
#size-cells = <0>;
gpio-controller;
#gpio-cells = <2>;
i2c@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
battery@b {
compatible = "ti,bq2060", "sbs,sbs-battery";
reg = <0x0b>;
sbs,battery-detect-gpios = <&batman 1 1>;
};
};
i2c@2 {
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
battery@b {
compatible = "ti,bq2060", "sbs,sbs-battery";
reg = <0x0b>;
sbs,battery-detect-gpios = <&batman 2 1>;
};
};
i2c@3 {
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
battery@b {
compatible = "ti,bq2060", "sbs,sbs-battery";
reg = <0x0b>;
sbs,battery-detect-gpios = <&batman 3 1>;
};
};
};
...@@ -2249,7 +2249,7 @@ F: include/linux/dmaengine.h ...@@ -2249,7 +2249,7 @@ F: include/linux/dmaengine.h
F: include/linux/async_tx.h F: include/linux/async_tx.h
AT24 EEPROM DRIVER AT24 EEPROM DRIVER
M: Wolfram Sang <wsa@the-dreams.de> M: Bartosz Golaszewski <brgl@bgdev.pl>
L: linux-i2c@vger.kernel.org L: linux-i2c@vger.kernel.org
S: Maintained S: Maintained
F: drivers/misc/eeprom/at24.c F: drivers/misc/eeprom/at24.c
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include <linux/amba/serial.h> #include <linux/amba/serial.h>
#include <linux/mtd/physmap.h> #include <linux/mtd/physmap.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-gpio.h> #include <linux/gpio/machine.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/irqchip/arm-vic.h> #include <linux/irqchip/arm-vic.h>
...@@ -320,42 +320,47 @@ void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr) ...@@ -320,42 +320,47 @@ void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr)
/************************************************************************* /*************************************************************************
* EP93xx i2c peripheral handling * EP93xx i2c peripheral handling
*************************************************************************/ *************************************************************************/
static struct i2c_gpio_platform_data ep93xx_i2c_data;
/* All EP93xx devices use the same two GPIO pins for I2C bit-banging */
static struct gpiod_lookup_table ep93xx_i2c_gpiod_table = {
.dev_id = "i2c-gpio",
.table = {
/* Use local offsets on gpiochip/port "G" */
GPIO_LOOKUP_IDX("G", 1, NULL, 0,
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
GPIO_LOOKUP_IDX("G", 0, NULL, 1,
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
},
};
static struct platform_device ep93xx_i2c_device = { static struct platform_device ep93xx_i2c_device = {
.name = "i2c-gpio", .name = "i2c-gpio",
.id = 0, .id = 0,
.dev = { .dev = {
.platform_data = &ep93xx_i2c_data, .platform_data = NULL,
}, },
}; };
/** /**
* ep93xx_register_i2c - Register the i2c platform device. * ep93xx_register_i2c - Register the i2c platform device.
* @data: platform specific i2c-gpio configuration (__initdata)
* @devices: platform specific i2c bus device information (__initdata) * @devices: platform specific i2c bus device information (__initdata)
* @num: the number of devices on the i2c bus * @num: the number of devices on the i2c bus
*/ */
void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *data, void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num)
struct i2c_board_info *devices, int num)
{ {
/* /*
* Set the EEPROM interface pin drive type control. * FIXME: this just sets the two pins as non-opendrain, as no
* Defines the driver type for the EECLK and EEDAT pins as either * platforms tries to do that anyway. Flag the applicable lines
* open drain, which will require an external pull-up, or a normal * as open drain in the GPIO_LOOKUP above and the driver or
* CMOS driver. * gpiolib will handle open drain/open drain emulation as need
* be. Right now i2c-gpio emulates open drain which is not
* optimal.
*/ */
if (data->sda_is_open_drain && data->sda_pin != EP93XX_GPIO_LINE_EEDAT) __raw_writel((0 << 1) | (0 << 0),
pr_warning("sda != EEDAT, open drain has no effect\n");
if (data->scl_is_open_drain && data->scl_pin != EP93XX_GPIO_LINE_EECLK)
pr_warning("scl != EECLK, open drain has no effect\n");
__raw_writel((data->sda_is_open_drain << 1) |
(data->scl_is_open_drain << 0),
EP93XX_GPIO_EEDRIVE); EP93XX_GPIO_EEDRIVE);
ep93xx_i2c_data = *data;
i2c_register_board_info(0, devices, num); i2c_register_board_info(0, devices, num);
gpiod_add_lookup_table(&ep93xx_i2c_gpiod_table);
platform_device_register(&ep93xx_i2c_device); platform_device_register(&ep93xx_i2c_device);
} }
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <sound/cs4271.h> #include <sound/cs4271.h>
...@@ -61,14 +60,6 @@ static struct ep93xx_eth_data __initdata edb93xx_eth_data = { ...@@ -61,14 +60,6 @@ static struct ep93xx_eth_data __initdata edb93xx_eth_data = {
/************************************************************************* /*************************************************************************
* EDB93xx i2c peripheral handling * EDB93xx i2c peripheral handling
*************************************************************************/ *************************************************************************/
static struct i2c_gpio_platform_data __initdata edb93xx_i2c_gpio_data = {
.sda_pin = EP93XX_GPIO_LINE_EEDAT,
.sda_is_open_drain = 0,
.scl_pin = EP93XX_GPIO_LINE_EECLK,
.scl_is_open_drain = 0,
.udelay = 0, /* default to 100 kHz */
.timeout = 0, /* default to 100 ms */
};
static struct i2c_board_info __initdata edb93xxa_i2c_board_info[] = { static struct i2c_board_info __initdata edb93xxa_i2c_board_info[] = {
{ {
...@@ -86,13 +77,11 @@ static void __init edb93xx_register_i2c(void) ...@@ -86,13 +77,11 @@ static void __init edb93xx_register_i2c(void)
{ {
if (machine_is_edb9302a() || machine_is_edb9307a() || if (machine_is_edb9302a() || machine_is_edb9307a() ||
machine_is_edb9315a()) { machine_is_edb9315a()) {
ep93xx_register_i2c(&edb93xx_i2c_gpio_data, ep93xx_register_i2c(edb93xxa_i2c_board_info,
edb93xxa_i2c_board_info,
ARRAY_SIZE(edb93xxa_i2c_board_info)); ARRAY_SIZE(edb93xxa_i2c_board_info));
} else if (machine_is_edb9302() || machine_is_edb9307() } else if (machine_is_edb9302() || machine_is_edb9307()
|| machine_is_edb9312() || machine_is_edb9315()) { || machine_is_edb9312() || machine_is_edb9315()) {
ep93xx_register_i2c(&edb93xx_i2c_gpio_data, ep93xx_register_i2c(edb93xx_i2c_board_info,
edb93xx_i2c_board_info,
ARRAY_SIZE(edb93xx_i2c_board_info)); ARRAY_SIZE(edb93xx_i2c_board_info));
} }
} }
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#include <linux/reboot.h> #include <linux/reboot.h>
struct device; struct device;
struct i2c_gpio_platform_data;
struct i2c_board_info; struct i2c_board_info;
struct spi_board_info; struct spi_board_info;
struct platform_device; struct platform_device;
...@@ -37,8 +36,7 @@ void ep93xx_register_flash(unsigned int width, ...@@ -37,8 +36,7 @@ void ep93xx_register_flash(unsigned int width,
resource_size_t start, resource_size_t size); resource_size_t start, resource_size_t size);
void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr); void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr);
void ep93xx_register_i2c(struct i2c_gpio_platform_data *data, void ep93xx_register_i2c(struct i2c_board_info *devices, int num);
struct i2c_board_info *devices, int num);
void ep93xx_register_spi(struct ep93xx_spi_info *info, void ep93xx_register_spi(struct ep93xx_spi_info *info,
struct spi_board_info *devices, int num); struct spi_board_info *devices, int num);
void ep93xx_register_fb(struct ep93xxfb_mach_info *data); void ep93xx_register_fb(struct ep93xxfb_mach_info *data);
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/mmc_spi.h> #include <linux/spi/mmc_spi.h>
...@@ -129,15 +128,6 @@ static struct ep93xx_spi_info simone_spi_info __initdata = { ...@@ -129,15 +128,6 @@ static struct ep93xx_spi_info simone_spi_info __initdata = {
.use_dma = 1, .use_dma = 1,
}; };
static struct i2c_gpio_platform_data __initdata simone_i2c_gpio_data = {
.sda_pin = EP93XX_GPIO_LINE_EEDAT,
.sda_is_open_drain = 0,
.scl_pin = EP93XX_GPIO_LINE_EECLK,
.scl_is_open_drain = 0,
.udelay = 0,
.timeout = 0,
};
static struct i2c_board_info __initdata simone_i2c_board_info[] = { static struct i2c_board_info __initdata simone_i2c_board_info[] = {
{ {
I2C_BOARD_INFO("ds1337", 0x68), I2C_BOARD_INFO("ds1337", 0x68),
...@@ -161,7 +151,7 @@ static void __init simone_init_machine(void) ...@@ -161,7 +151,7 @@ static void __init simone_init_machine(void)
ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_8M); ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_8M);
ep93xx_register_eth(&simone_eth_data, 1); ep93xx_register_eth(&simone_eth_data, 1);
ep93xx_register_fb(&simone_fb_info); ep93xx_register_fb(&simone_fb_info);
ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info, ep93xx_register_i2c(simone_i2c_board_info,
ARRAY_SIZE(simone_i2c_board_info)); ARRAY_SIZE(simone_i2c_board_info));
ep93xx_register_spi(&simone_spi_info, simone_spi_devices, ep93xx_register_spi(&simone_spi_info, simone_spi_devices,
ARRAY_SIZE(simone_spi_devices)); ARRAY_SIZE(simone_spi_devices));
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/mtd/partitions.h> #include <linux/mtd/partitions.h>
...@@ -127,15 +126,6 @@ static struct ep93xx_eth_data __initdata snappercl15_eth_data = { ...@@ -127,15 +126,6 @@ static struct ep93xx_eth_data __initdata snappercl15_eth_data = {
.phy_id = 1, .phy_id = 1,
}; };
static struct i2c_gpio_platform_data __initdata snappercl15_i2c_gpio_data = {
.sda_pin = EP93XX_GPIO_LINE_EEDAT,
.sda_is_open_drain = 0,
.scl_pin = EP93XX_GPIO_LINE_EECLK,
.scl_is_open_drain = 0,
.udelay = 0,
.timeout = 0,
};
static struct i2c_board_info __initdata snappercl15_i2c_data[] = { static struct i2c_board_info __initdata snappercl15_i2c_data[] = {
{ {
/* Audio codec */ /* Audio codec */
...@@ -161,7 +151,7 @@ static void __init snappercl15_init_machine(void) ...@@ -161,7 +151,7 @@ static void __init snappercl15_init_machine(void)
{ {
ep93xx_init_devices(); ep93xx_init_devices();
ep93xx_register_eth(&snappercl15_eth_data, 1); ep93xx_register_eth(&snappercl15_eth_data, 1);
ep93xx_register_i2c(&snappercl15_i2c_gpio_data, snappercl15_i2c_data, ep93xx_register_i2c(snappercl15_i2c_data,
ARRAY_SIZE(snappercl15_i2c_data)); ARRAY_SIZE(snappercl15_i2c_data));
ep93xx_register_fb(&snappercl15_fb_info); ep93xx_register_fb(&snappercl15_fb_info);
snappercl15_register_audio(); snappercl15_register_audio();
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/mtd/partitions.h> #include <linux/mtd/partitions.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <linux/platform_data/pca953x.h> #include <linux/platform_data/pca953x.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/flash.h> #include <linux/spi/flash.h>
...@@ -144,10 +143,6 @@ static struct pca953x_platform_data pca953x_77_gpio_data = { ...@@ -144,10 +143,6 @@ static struct pca953x_platform_data pca953x_77_gpio_data = {
/************************************************************************* /*************************************************************************
* I2C Bus * I2C Bus
*************************************************************************/ *************************************************************************/
static struct i2c_gpio_platform_data vision_i2c_gpio_data __initdata = {
.sda_pin = EP93XX_GPIO_LINE_EEDAT,
.scl_pin = EP93XX_GPIO_LINE_EECLK,
};
static struct i2c_board_info vision_i2c_info[] __initdata = { static struct i2c_board_info vision_i2c_info[] __initdata = {
{ {
...@@ -289,7 +284,7 @@ static void __init vision_init_machine(void) ...@@ -289,7 +284,7 @@ static void __init vision_init_machine(void)
vision_i2c_info[1].irq = gpio_to_irq(EP93XX_GPIO_LINE_F(7)); vision_i2c_info[1].irq = gpio_to_irq(EP93XX_GPIO_LINE_F(7));
ep93xx_register_i2c(&vision_i2c_gpio_data, vision_i2c_info, ep93xx_register_i2c(vision_i2c_info,
ARRAY_SIZE(vision_i2c_info)); ARRAY_SIZE(vision_i2c_info));
ep93xx_register_spi(&vision_spi_master, vision_spi_board_info, ep93xx_register_spi(&vision_spi_master, vision_spi_board_info,
ARRAY_SIZE(vision_spi_board_info)); ARRAY_SIZE(vision_spi_board_info));
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <linux/i2c-gpio.h> #include <linux/gpio/machine.h>
#include <asm/types.h> #include <asm/types.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/memory.h> #include <asm/memory.h>
...@@ -50,16 +50,21 @@ static struct platform_device avila_flash = { ...@@ -50,16 +50,21 @@ static struct platform_device avila_flash = {
.resource = &avila_flash_resource, .resource = &avila_flash_resource,
}; };
static struct i2c_gpio_platform_data avila_i2c_gpio_data = { static struct gpiod_lookup_table avila_i2c_gpiod_table = {
.sda_pin = AVILA_SDA_PIN, .dev_id = "i2c-gpio",
.scl_pin = AVILA_SCL_PIN, .table = {
GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", AVILA_SDA_PIN,
NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", AVILA_SCL_PIN,
NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
},
}; };
static struct platform_device avila_i2c_gpio = { static struct platform_device avila_i2c_gpio = {
.name = "i2c-gpio", .name = "i2c-gpio",
.id = 0, .id = 0,
.dev = { .dev = {
.platform_data = &avila_i2c_gpio_data, .platform_data = NULL,
}, },
}; };
...@@ -148,6 +153,8 @@ static void __init avila_init(void) ...@@ -148,6 +153,8 @@ static void __init avila_init(void)
avila_flash_resource.end = avila_flash_resource.end =
IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1; IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
gpiod_add_lookup_table(&avila_i2c_gpiod_table);
platform_add_devices(avila_devices, ARRAY_SIZE(avila_devices)); platform_add_devices(avila_devices, ARRAY_SIZE(avila_devices));
avila_pata_resources[0].start = IXP4XX_EXP_BUS_BASE(1); avila_pata_resources[0].start = IXP4XX_EXP_BUS_BASE(1);
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-gpio.h> #include <linux/gpio/machine.h>
#include <mach/hardware.h> #include <mach/hardware.h>
...@@ -69,16 +69,21 @@ static struct platform_device dsmg600_flash = { ...@@ -69,16 +69,21 @@ static struct platform_device dsmg600_flash = {
.resource = &dsmg600_flash_resource, .resource = &dsmg600_flash_resource,
}; };
static struct i2c_gpio_platform_data dsmg600_i2c_gpio_data = { static struct gpiod_lookup_table dsmg600_i2c_gpiod_table = {
.sda_pin = DSMG600_SDA_PIN, .dev_id = "i2c-gpio",
.scl_pin = DSMG600_SCL_PIN, .table = {
GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", DSMG600_SDA_PIN,
NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", DSMG600_SCL_PIN,
NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
},
}; };
static struct platform_device dsmg600_i2c_gpio = { static struct platform_device dsmg600_i2c_gpio = {
.name = "i2c-gpio", .name = "i2c-gpio",
.id = 0, .id = 0,
.dev = { .dev = {
.platform_data = &dsmg600_i2c_gpio_data, .platform_data = NULL,
}, },
}; };
...@@ -270,6 +275,7 @@ static void __init dsmg600_init(void) ...@@ -270,6 +275,7 @@ static void __init dsmg600_init(void)
dsmg600_flash_resource.end = dsmg600_flash_resource.end =
IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1; IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
gpiod_add_lookup_table(&dsmg600_i2c_gpiod_table);
i2c_register_board_info(0, dsmg600_i2c_board_info, i2c_register_board_info(0, dsmg600_i2c_board_info,
ARRAY_SIZE(dsmg600_i2c_board_info)); ARRAY_SIZE(dsmg600_i2c_board_info));
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-gpio.h> #include <linux/gpio/machine.h>
#include <linux/io.h> #include <linux/io.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
...@@ -55,16 +55,21 @@ static struct platform_device fsg_flash = { ...@@ -55,16 +55,21 @@ static struct platform_device fsg_flash = {
.resource = &fsg_flash_resource, .resource = &fsg_flash_resource,
}; };
static struct i2c_gpio_platform_data fsg_i2c_gpio_data = { static struct gpiod_lookup_table fsg_i2c_gpiod_table = {
.sda_pin = FSG_SDA_PIN, .dev_id = "i2c-gpio",
.scl_pin = FSG_SCL_PIN, .table = {
GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", FSG_SDA_PIN,
NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", FSG_SCL_PIN,
NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
},
}; };
static struct platform_device fsg_i2c_gpio = { static struct platform_device fsg_i2c_gpio = {
.name = "i2c-gpio", .name = "i2c-gpio",
.id = 0, .id = 0,
.dev = { .dev = {
.platform_data = &fsg_i2c_gpio_data, .platform_data = NULL,
}, },
}; };
...@@ -197,6 +202,7 @@ static void __init fsg_init(void) ...@@ -197,6 +202,7 @@ static void __init fsg_init(void)
/* Configure CS2 for operation, 8bit and writable */ /* Configure CS2 for operation, 8bit and writable */
*IXP4XX_EXP_CS2 = 0xbfff0002; *IXP4XX_EXP_CS2 = 0xbfff0002;
gpiod_add_lookup_table(&fsg_i2c_gpiod_table);
i2c_register_board_info(0, fsg_i2c_board_info, i2c_register_board_info(0, fsg_i2c_board_info,
ARRAY_SIZE(fsg_i2c_board_info)); ARRAY_SIZE(fsg_i2c_board_info));
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/hdlc.h> #include <linux/hdlc.h>
#include <linux/i2c-gpio.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -79,6 +78,12 @@ ...@@ -79,6 +78,12 @@
static u32 hw_bits = 0xFFFFFFFD; /* assume all hardware present */; static u32 hw_bits = 0xFFFFFFFD; /* assume all hardware present */;
static u8 control_value; static u8 control_value;
/*
* FIXME: this is reimplementing I2C bit-bangining. Move this
* over to using driver/i2c/busses/i2c-gpio.c like all other boards
* and register proper I2C device(s) on the bus for this. (See
* other IXP4xx boards for examples.)
*/
static void set_scl(u8 value) static void set_scl(u8 value)
{ {
gpio_set_value(GPIO_SCL, !!value); gpio_set_value(GPIO_SCL, !!value);
...@@ -217,20 +222,6 @@ static struct platform_device device_flash = { ...@@ -217,20 +222,6 @@ static struct platform_device device_flash = {
.resource = &flash_resource, .resource = &flash_resource,
}; };
/* I^2C interface */
static struct i2c_gpio_platform_data i2c_data = {
.sda_pin = GPIO_SDA,
.scl_pin = GPIO_SCL,
};
static struct platform_device device_i2c = {
.name = "i2c-gpio",
.id = 0,
.dev = { .platform_data = &i2c_data },
};
/* IXP425 2 UART ports */ /* IXP425 2 UART ports */
static struct resource uart_resources[] = { static struct resource uart_resources[] = {
{ {
...@@ -412,9 +403,6 @@ static void __init gmlr_init(void) ...@@ -412,9 +403,6 @@ static void __init gmlr_init(void)
if (hw_bits & CFG_HW_HAS_HSS1) if (hw_bits & CFG_HW_HAS_HSS1)
device_tab[devices++] = &device_hss_tab[1]; /* max index 5 */ device_tab[devices++] = &device_hss_tab[1]; /* max index 5 */
if (hw_bits & CFG_HW_HAS_EEPROM)
device_tab[devices++] = &device_i2c; /* max index 6 */
gpio_request(GPIO_SCL, "SCL/clock"); gpio_request(GPIO_SCL, "SCL/clock");
gpio_request(GPIO_SDA, "SDA/data"); gpio_request(GPIO_SDA, "SDA/data");
gpio_request(GPIO_STR, "strobe"); gpio_request(GPIO_STR, "strobe");
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <linux/i2c-gpio.h> #include <linux/gpio/machine.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h> #include <linux/mtd/rawnand.h>
...@@ -123,16 +123,21 @@ static struct platform_device ixdp425_flash_nand = { ...@@ -123,16 +123,21 @@ static struct platform_device ixdp425_flash_nand = {
}; };
#endif /* CONFIG_MTD_NAND_PLATFORM */ #endif /* CONFIG_MTD_NAND_PLATFORM */
static struct i2c_gpio_platform_data ixdp425_i2c_gpio_data = { static struct gpiod_lookup_table ixdp425_i2c_gpiod_table = {
.sda_pin = IXDP425_SDA_PIN, .dev_id = "i2c-gpio",
.scl_pin = IXDP425_SCL_PIN, .table = {
GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", IXDP425_SDA_PIN,
NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", IXDP425_SCL_PIN,
NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
},
}; };
static struct platform_device ixdp425_i2c_gpio = { static struct platform_device ixdp425_i2c_gpio = {
.name = "i2c-gpio", .name = "i2c-gpio",
.id = 0, .id = 0,
.dev = { .dev = {
.platform_data = &ixdp425_i2c_gpio_data, .platform_data = NULL,
}, },
}; };
...@@ -246,6 +251,7 @@ static void __init ixdp425_init(void) ...@@ -246,6 +251,7 @@ static void __init ixdp425_init(void)
ixdp425_uart_data[1].flags = 0; ixdp425_uart_data[1].flags = 0;
} }
gpiod_add_lookup_table(&ixdp425_i2c_gpiod_table);
platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices)); platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices));
} }
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-gpio.h> #include <linux/gpio/machine.h>
#include <linux/io.h> #include <linux/io.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
...@@ -101,16 +101,21 @@ static struct platform_device nas100d_leds = { ...@@ -101,16 +101,21 @@ static struct platform_device nas100d_leds = {
.dev.platform_data = &nas100d_led_data, .dev.platform_data = &nas100d_led_data,
}; };
static struct i2c_gpio_platform_data nas100d_i2c_gpio_data = { static struct gpiod_lookup_table nas100d_i2c_gpiod_table = {
.sda_pin = NAS100D_SDA_PIN, .dev_id = "i2c-gpio",
.scl_pin = NAS100D_SCL_PIN, .table = {
GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", NAS100D_SDA_PIN,
NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", NAS100D_SCL_PIN,
NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
},
}; };
static struct platform_device nas100d_i2c_gpio = { static struct platform_device nas100d_i2c_gpio = {
.name = "i2c-gpio", .name = "i2c-gpio",
.id = 0, .id = 0,
.dev = { .dev = {
.platform_data = &nas100d_i2c_gpio_data, .platform_data = NULL,
}, },
}; };
...@@ -281,6 +286,7 @@ static void __init nas100d_init(void) ...@@ -281,6 +286,7 @@ static void __init nas100d_init(void)
nas100d_flash_resource.end = nas100d_flash_resource.end =
IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1; IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
gpiod_add_lookup_table(&nas100d_i2c_gpiod_table);
i2c_register_board_info(0, nas100d_i2c_board_info, i2c_register_board_info(0, nas100d_i2c_board_info,
ARRAY_SIZE(nas100d_i2c_board_info)); ARRAY_SIZE(nas100d_i2c_board_info));
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-gpio.h> #include <linux/gpio/machine.h>
#include <linux/io.h> #include <linux/io.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
...@@ -69,9 +69,14 @@ static struct platform_device nslu2_flash = { ...@@ -69,9 +69,14 @@ static struct platform_device nslu2_flash = {
.resource = &nslu2_flash_resource, .resource = &nslu2_flash_resource,
}; };
static struct i2c_gpio_platform_data nslu2_i2c_gpio_data = { static struct gpiod_lookup_table nslu2_i2c_gpiod_table = {
.sda_pin = NSLU2_SDA_PIN, .dev_id = "i2c-gpio",
.scl_pin = NSLU2_SCL_PIN, .table = {
GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", NSLU2_SDA_PIN,
NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
GPIO_LOOKUP_IDX("IXP4XX_GPIO_CHIP", NSLU2_SCL_PIN,
NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
},
}; };
static struct i2c_board_info __initdata nslu2_i2c_board_info [] = { static struct i2c_board_info __initdata nslu2_i2c_board_info [] = {
...@@ -116,7 +121,7 @@ static struct platform_device nslu2_i2c_gpio = { ...@@ -116,7 +121,7 @@ static struct platform_device nslu2_i2c_gpio = {
.name = "i2c-gpio", .name = "i2c-gpio",
.id = 0, .id = 0,
.dev = { .dev = {
.platform_data = &nslu2_i2c_gpio_data, .platform_data = NULL,
}, },
}; };
...@@ -251,6 +256,7 @@ static void __init nslu2_init(void) ...@@ -251,6 +256,7 @@ static void __init nslu2_init(void)
nslu2_flash_resource.end = nslu2_flash_resource.end =
IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1; IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
gpiod_add_lookup_table(&nslu2_i2c_gpiod_table);
i2c_register_board_info(0, nslu2_i2c_board_info, i2c_register_board_info(0, nslu2_i2c_board_info,
ARRAY_SIZE(nslu2_i2c_board_info)); ARRAY_SIZE(nslu2_i2c_board_info));
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/gpio/machine.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-algo-bit.h> #include <linux/i2c-algo-bit.h>
#include <linux/i2c-gpio.h> #include <linux/i2c-gpio.h>
...@@ -38,9 +38,17 @@ ...@@ -38,9 +38,17 @@
#include "generic.h" #include "generic.h"
static struct gpiod_lookup_table acs5k_i2c_gpiod_table = {
.dev_id = "i2c-gpio",
.table = {
GPIO_LOOKUP_IDX("KS8695", 4, NULL, 0,
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
GPIO_LOOKUP_IDX("KS8695", 5, NULL, 1,
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
},
};
static struct i2c_gpio_platform_data acs5k_i2c_device_platdata = { static struct i2c_gpio_platform_data acs5k_i2c_device_platdata = {
.sda_pin = 4,
.scl_pin = 5,
.udelay = 10, .udelay = 10,
}; };
...@@ -95,6 +103,7 @@ static struct i2c_board_info acs5k_i2c_devs[] __initdata = { ...@@ -95,6 +103,7 @@ static struct i2c_board_info acs5k_i2c_devs[] __initdata = {
static void acs5k_i2c_init(void) static void acs5k_i2c_init(void)
{ {
/* The gpio interface */ /* The gpio interface */
gpiod_add_lookup_table(&acs5k_i2c_gpiod_table);
platform_device_register(&acs5k_i2c_device); platform_device_register(&acs5k_i2c_device);
/* I2C devices */ /* I2C devices */
i2c_register_board_info(0, acs5k_i2c_devs, i2c_register_board_info(0, acs5k_i2c_devs,
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/power_supply.h> #include <linux/power_supply.h>
#include <linux/usb/gpio_vbus.h> #include <linux/usb/gpio_vbus.h>
#include <linux/i2c-gpio.h> #include <linux/i2c-gpio.h>
#include <linux/gpio/machine.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/suspend.h> #include <asm/suspend.h>
...@@ -320,9 +321,17 @@ static struct soc_camera_link palmz72_iclink = { ...@@ -320,9 +321,17 @@ static struct soc_camera_link palmz72_iclink = {
.flags = SOCAM_DATAWIDTH_8, .flags = SOCAM_DATAWIDTH_8,
}; };
static struct gpiod_lookup_table palmz72_i2c_gpiod_table = {
.dev_id = "i2c-gpio",
.table = {
GPIO_LOOKUP_IDX("gpio-pxa", 118, NULL, 0,
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
GPIO_LOOKUP_IDX("gpio-pxa", 117, NULL, 1,
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
},
};
static struct i2c_gpio_platform_data palmz72_i2c_bus_data = { static struct i2c_gpio_platform_data palmz72_i2c_bus_data = {
.sda_pin = 118,
.scl_pin = 117,
.udelay = 10, .udelay = 10,
.timeout = 100, .timeout = 100,
}; };
...@@ -369,6 +378,7 @@ static void __init palmz72_camera_init(void) ...@@ -369,6 +378,7 @@ static void __init palmz72_camera_init(void)
{ {
palmz72_cam_gpio_init(); palmz72_cam_gpio_init();
pxa_set_camera_info(&palmz72_pxacamera_platform_data); pxa_set_camera_info(&palmz72_pxacamera_platform_data);
gpiod_add_lookup_table(&palmz72_i2c_gpiod_table);
platform_device_register(&palmz72_i2c_bus_device); platform_device_register(&palmz72_i2c_bus_device);
platform_device_register(&palmz72_camera); platform_device_register(&palmz72_camera);
} }
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/i2c-gpio.h> #include <linux/i2c-gpio.h>
#include <linux/gpio/machine.h>
#include <linux/i2c/pxa-i2c.h> #include <linux/i2c/pxa-i2c.h>
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <linux/smc91x.h> #include <linux/smc91x.h>
...@@ -458,9 +459,17 @@ static struct platform_device smc91x_device = { ...@@ -458,9 +459,17 @@ static struct platform_device smc91x_device = {
}; };
/* i2c */ /* i2c */
static struct gpiod_lookup_table viper_i2c_gpiod_table = {
.dev_id = "i2c-gpio",
.table = {
GPIO_LOOKUP_IDX("gpio-pxa", VIPER_RTC_I2C_SDA_GPIO,
NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
GPIO_LOOKUP_IDX("gpio-pxa", VIPER_RTC_I2C_SCL_GPIO,
NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
},
};
static struct i2c_gpio_platform_data i2c_bus_data = { static struct i2c_gpio_platform_data i2c_bus_data = {
.sda_pin = VIPER_RTC_I2C_SDA_GPIO,
.scl_pin = VIPER_RTC_I2C_SCL_GPIO,
.udelay = 10, .udelay = 10,
.timeout = HZ, .timeout = HZ,
}; };
...@@ -779,12 +788,20 @@ static int __init viper_tpm_setup(char *str) ...@@ -779,12 +788,20 @@ static int __init viper_tpm_setup(char *str)
__setup("tpm=", viper_tpm_setup); __setup("tpm=", viper_tpm_setup);
struct gpiod_lookup_table viper_tpm_i2c_gpiod_table = {
.dev_id = "i2c-gpio",
.table = {
GPIO_LOOKUP_IDX("gpio-pxa", VIPER_TPM_I2C_SDA_GPIO,
NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
GPIO_LOOKUP_IDX("gpio-pxa", VIPER_TPM_I2C_SCL_GPIO,
NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
},
};
static void __init viper_tpm_init(void) static void __init viper_tpm_init(void)
{ {
struct platform_device *tpm_device; struct platform_device *tpm_device;
struct i2c_gpio_platform_data i2c_tpm_data = { struct i2c_gpio_platform_data i2c_tpm_data = {
.sda_pin = VIPER_TPM_I2C_SDA_GPIO,
.scl_pin = VIPER_TPM_I2C_SCL_GPIO,
.udelay = 10, .udelay = 10,
.timeout = HZ, .timeout = HZ,
}; };
...@@ -794,6 +811,7 @@ static void __init viper_tpm_init(void) ...@@ -794,6 +811,7 @@ static void __init viper_tpm_init(void)
if (!viper_tpm) if (!viper_tpm)
return; return;
gpiod_add_lookup_table(&viper_tpm_i2c_gpiod_table);
tpm_device = platform_device_alloc("i2c-gpio", 2); tpm_device = platform_device_alloc("i2c-gpio", 2);
if (tpm_device) { if (tpm_device) {
if (!platform_device_add_data(tpm_device, if (!platform_device_add_data(tpm_device,
...@@ -943,6 +961,7 @@ static void __init viper_init(void) ...@@ -943,6 +961,7 @@ static void __init viper_init(void)
smc91x_device.num_resources--; smc91x_device.num_resources--;
pxa_set_i2c_info(NULL); pxa_set_i2c_info(NULL);
gpiod_add_lookup_table(&viper_i2c_gpiod_table);
pwm_add_table(viper_pwm_lookup, ARRAY_SIZE(viper_pwm_lookup)); pwm_add_table(viper_pwm_lookup, ARRAY_SIZE(viper_pwm_lookup));
platform_add_devices(viper_devs, ARRAY_SIZE(viper_devs)); platform_add_devices(viper_devs, ARRAY_SIZE(viper_devs));
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/mtd/partitions.h> #include <linux/mtd/partitions.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio/driver.h> #include <linux/gpio/driver.h>
#include <linux/gpio/machine.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/setup.h> #include <asm/setup.h>
...@@ -324,9 +325,17 @@ static struct platform_device simpad_gpio_leds = { ...@@ -324,9 +325,17 @@ static struct platform_device simpad_gpio_leds = {
/* /*
* i2c * i2c
*/ */
static struct gpiod_lookup_table simpad_i2c_gpiod_table = {
.dev_id = "i2c-gpio",
.table = {
GPIO_LOOKUP_IDX("gpio", 21, NULL, 0,
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
GPIO_LOOKUP_IDX("gpio", 25, NULL, 1,
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
},
};
static struct i2c_gpio_platform_data simpad_i2c_data = { static struct i2c_gpio_platform_data simpad_i2c_data = {
.sda_pin = GPIO_GPIO21,
.scl_pin = GPIO_GPIO25,
.udelay = 10, .udelay = 10,
.timeout = HZ, .timeout = HZ,
}; };
...@@ -381,6 +390,7 @@ static int __init simpad_init(void) ...@@ -381,6 +390,7 @@ static int __init simpad_init(void)
ARRAY_SIZE(simpad_flash_resources)); ARRAY_SIZE(simpad_flash_resources));
sa11x0_register_mcp(&simpad_mcp_data); sa11x0_register_mcp(&simpad_mcp_data);
gpiod_add_lookup_table(&simpad_i2c_gpiod_table);
ret = platform_add_devices(devices, ARRAY_SIZE(devices)); ret = platform_add_devices(devices, ARRAY_SIZE(devices));
if(ret) if(ret)
printk(KERN_WARNING "simpad: Unable to register mq200 framebuffer device"); printk(KERN_WARNING "simpad: Unable to register mq200 framebuffer device");
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/gpio/machine.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/bfin5xx_spi.h> #include <asm/bfin5xx_spi.h>
#include <asm/portmux.h> #include <asm/portmux.h>
...@@ -362,11 +363,17 @@ static struct platform_device bfin_device_gpiokeys = { ...@@ -362,11 +363,17 @@ static struct platform_device bfin_device_gpiokeys = {
#if IS_ENABLED(CONFIG_I2C_GPIO) #if IS_ENABLED(CONFIG_I2C_GPIO)
#include <linux/i2c-gpio.h> #include <linux/i2c-gpio.h>
static struct gpiod_lookup_table bfin_i2c_gpiod_table = {
.dev_id = "i2c-gpio",
.table = {
GPIO_LOOKUP_IDX("BFIN-GPIO", GPIO_PF8, NULL, 0,
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
GPIO_LOOKUP_IDX("BFIN-GPIO", GPIO_PF9, NULL, 1,
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
},
};
static struct i2c_gpio_platform_data i2c_gpio_data = { static struct i2c_gpio_platform_data i2c_gpio_data = {
.sda_pin = GPIO_PF8,
.scl_pin = GPIO_PF9,
.sda_is_open_drain = 0,
.scl_is_open_drain = 0,
.udelay = 40, .udelay = 40,
}; /* This hasn't actually been used these pins }; /* This hasn't actually been used these pins
* are (currently) free pins on the expansion connector */ * are (currently) free pins on the expansion connector */
...@@ -462,7 +469,9 @@ static int __init blackstamp_init(void) ...@@ -462,7 +469,9 @@ static int __init blackstamp_init(void)
int ret; int ret;
printk(KERN_INFO "%s(): registering device resources\n", __func__); printk(KERN_INFO "%s(): registering device resources\n", __func__);
#if IS_ENABLED(CONFIG_I2C_GPIO)
gpiod_add_lookup_table(&bfin_i2c_gpiod_table);
#endif
i2c_register_board_info(0, bfin_i2c_board_info, i2c_register_board_info(0, bfin_i2c_board_info,
ARRAY_SIZE(bfin_i2c_board_info)); ARRAY_SIZE(bfin_i2c_board_info));
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#endif #endif
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/gpio/machine.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/bfin5xx_spi.h> #include <asm/bfin5xx_spi.h>
#include <asm/portmux.h> #include <asm/portmux.h>
...@@ -390,11 +391,17 @@ static struct platform_device bfin_device_gpiokeys = { ...@@ -390,11 +391,17 @@ static struct platform_device bfin_device_gpiokeys = {
#if IS_ENABLED(CONFIG_I2C_GPIO) #if IS_ENABLED(CONFIG_I2C_GPIO)
#include <linux/i2c-gpio.h> #include <linux/i2c-gpio.h>
static struct gpiod_lookup_table bfin_i2c_gpiod_table = {
.dev_id = "i2c-gpio",
.table = {
GPIO_LOOKUP_IDX("BFIN-GPIO", GPIO_PF1, NULL, 0,
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
GPIO_LOOKUP_IDX("BFIN-GPIO", GPIO_PF0, NULL, 1,
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
},
};
static struct i2c_gpio_platform_data i2c_gpio_data = { static struct i2c_gpio_platform_data i2c_gpio_data = {
.sda_pin = GPIO_PF1,
.scl_pin = GPIO_PF0,
.sda_is_open_drain = 0,
.scl_is_open_drain = 0,
.udelay = 40, .udelay = 40,
}; };
...@@ -516,6 +523,9 @@ static struct platform_device *ezkit_devices[] __initdata = { ...@@ -516,6 +523,9 @@ static struct platform_device *ezkit_devices[] __initdata = {
static int __init ezkit_init(void) static int __init ezkit_init(void)
{ {
printk(KERN_INFO "%s(): registering device resources\n", __func__); printk(KERN_INFO "%s(): registering device resources\n", __func__);
#if IS_ENABLED(CONFIG_I2C_GPIO)
gpiod_add_lookup_table(&bfin_i2c_gpiod_table);
#endif
platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices)); platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices));
spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info)); spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
i2c_register_board_info(0, bfin_i2c_board_info, i2c_register_board_info(0, bfin_i2c_board_info,
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/gpio/machine.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/bfin5xx_spi.h> #include <asm/bfin5xx_spi.h>
#include <asm/reboot.h> #include <asm/reboot.h>
...@@ -512,11 +513,17 @@ static struct platform_device bfin_device_gpiokeys = { ...@@ -512,11 +513,17 @@ static struct platform_device bfin_device_gpiokeys = {
#if IS_ENABLED(CONFIG_I2C_GPIO) #if IS_ENABLED(CONFIG_I2C_GPIO)
#include <linux/i2c-gpio.h> #include <linux/i2c-gpio.h>
static struct gpiod_lookup_table bfin_i2c_gpiod_table = {
.dev_id = "i2c-gpio",
.table = {
GPIO_LOOKUP_IDX("BFIN-GPIO", GPIO_PF2, NULL, 0,
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
GPIO_LOOKUP_IDX("BFIN-GPIO", GPIO_PF3, NULL, 1,
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
},
};
static struct i2c_gpio_platform_data i2c_gpio_data = { static struct i2c_gpio_platform_data i2c_gpio_data = {
.sda_pin = GPIO_PF2,
.scl_pin = GPIO_PF3,
.sda_is_open_drain = 0,
.scl_is_open_drain = 0,
.udelay = 10, .udelay = 10,
}; };
...@@ -848,6 +855,9 @@ static int __init stamp_init(void) ...@@ -848,6 +855,9 @@ static int __init stamp_init(void)
printk(KERN_INFO "%s(): registering device resources\n", __func__); printk(KERN_INFO "%s(): registering device resources\n", __func__);
#if IS_ENABLED(CONFIG_I2C_GPIO)
gpiod_add_lookup_table(&bfin_i2c_gpiod_table);
#endif
i2c_register_board_info(0, bfin_i2c_board_info, i2c_register_board_info(0, bfin_i2c_board_info,
ARRAY_SIZE(bfin_i2c_board_info)); ARRAY_SIZE(bfin_i2c_board_info));
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gpio/machine.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/bfin5xx_spi.h> #include <asm/bfin5xx_spi.h>
#include <asm/portmux.h> #include <asm/portmux.h>
...@@ -379,11 +380,17 @@ static struct platform_device bfin_device_gpiokeys = { ...@@ -379,11 +380,17 @@ static struct platform_device bfin_device_gpiokeys = {
#if IS_ENABLED(CONFIG_I2C_GPIO) #if IS_ENABLED(CONFIG_I2C_GPIO)
#include <linux/i2c-gpio.h> #include <linux/i2c-gpio.h>
static struct gpiod_lookup_table bfin_i2c_gpiod_table = {
.dev_id = "i2c-gpio",
.table = {
GPIO_LOOKUP_IDX("BFIN-GPIO", GPIO_PF1, NULL, 0,
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
GPIO_LOOKUP_IDX("BFIN-GPIO", GPIO_PF0, NULL, 1,
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
},
};
static struct i2c_gpio_platform_data i2c_gpio_data = { static struct i2c_gpio_platform_data i2c_gpio_data = {
.sda_pin = GPIO_PF1,
.scl_pin = GPIO_PF0,
.sda_is_open_drain = 0,
.scl_is_open_drain = 0,
.udelay = 10, .udelay = 10,
}; };
...@@ -633,6 +640,9 @@ static int __init ezkit_init(void) ...@@ -633,6 +640,9 @@ static int __init ezkit_init(void)
printk(KERN_INFO "%s(): registering device resources\n", __func__); printk(KERN_INFO "%s(): registering device resources\n", __func__);
#if IS_ENABLED(CONFIG_I2C_GPIO)
gpiod_add_lookup_table(&bfin_i2c_gpiod_table);
#endif
ret = platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices)); ret = platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices));
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-gpio.h> #include <linux/i2c-gpio.h>
#include <linux/gpio/machine.h>
#include <asm/bootinfo.h> #include <asm/bootinfo.h>
#include <asm/idle.h> #include <asm/idle.h>
#include <asm/reboot.h> #include <asm/reboot.h>
...@@ -218,10 +219,27 @@ static struct platform_device gpr_led_devices = { ...@@ -218,10 +219,27 @@ static struct platform_device gpr_led_devices = {
/* /*
* I2C * I2C
*/ */
static struct gpiod_lookup_table gpr_i2c_gpiod_table = {
.dev_id = "i2c-gpio",
.table = {
/*
* This should be on "GPIO2" which has base at 200 so
* the global numbers 209 and 210 should correspond to
* local offsets 9 and 10.
*/
GPIO_LOOKUP_IDX("alchemy-gpio2", 9, NULL, 0,
GPIO_ACTIVE_HIGH),
GPIO_LOOKUP_IDX("alchemy-gpio2", 10, NULL, 1,
GPIO_ACTIVE_HIGH),
},
};
static struct i2c_gpio_platform_data gpr_i2c_data = { static struct i2c_gpio_platform_data gpr_i2c_data = {
.sda_pin = 209, /*
* The open drain mode is hardwired somewhere or an electrical
* property of the alchemy GPIO controller.
*/
.sda_is_open_drain = 1, .sda_is_open_drain = 1,
.scl_pin = 210,
.scl_is_open_drain = 1, .scl_is_open_drain = 1,
.udelay = 2, /* ~100 kHz */ .udelay = 2, /* ~100 kHz */
.timeout = HZ, .timeout = HZ,
...@@ -295,6 +313,7 @@ arch_initcall(gpr_pci_init); ...@@ -295,6 +313,7 @@ arch_initcall(gpr_pci_init);
static int __init gpr_dev_init(void) static int __init gpr_dev_init(void)
{ {
gpiod_add_lookup_table(&gpr_i2c_gpiod_table);
i2c_register_board_info(0, gpr_i2c_info, ARRAY_SIZE(gpr_i2c_info)); i2c_register_board_info(0, gpr_i2c_info, ARRAY_SIZE(gpr_i2c_info));
return platform_add_devices(gpr_devices, ARRAY_SIZE(gpr_devices)); return platform_add_devices(gpr_devices, ARRAY_SIZE(gpr_devices));
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-gpio.h> #include <linux/gpio/machine.h>
#include <linux/platform_data/pcf857x.h> #include <linux/platform_data/pcf857x.h>
#include "machtypes.h" #include "machtypes.h"
...@@ -33,16 +33,21 @@ ...@@ -33,16 +33,21 @@
#define PB44_KEYS_POLL_INTERVAL 20 /* msecs */ #define PB44_KEYS_POLL_INTERVAL 20 /* msecs */
#define PB44_KEYS_DEBOUNCE_INTERVAL (3 * PB44_KEYS_POLL_INTERVAL) #define PB44_KEYS_DEBOUNCE_INTERVAL (3 * PB44_KEYS_POLL_INTERVAL)
static struct i2c_gpio_platform_data pb44_i2c_gpio_data = { static struct gpiod_lookup_table pb44_i2c_gpiod_table = {
.sda_pin = PB44_GPIO_I2C_SDA, .dev_id = "i2c-gpio",
.scl_pin = PB44_GPIO_I2C_SCL, .table = {
GPIO_LOOKUP_IDX("ath79-gpio", PB44_GPIO_I2C_SDA,
NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
GPIO_LOOKUP_IDX("ath79-gpio", PB44_GPIO_I2C_SCL,
NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
},
}; };
static struct platform_device pb44_i2c_gpio_device = { static struct platform_device pb44_i2c_gpio_device = {
.name = "i2c-gpio", .name = "i2c-gpio",
.id = 0, .id = 0,
.dev = { .dev = {
.platform_data = &pb44_i2c_gpio_data, .platform_data = NULL,
} }
}; };
...@@ -103,6 +108,7 @@ static struct ath79_spi_platform_data pb44_spi_data = { ...@@ -103,6 +108,7 @@ static struct ath79_spi_platform_data pb44_spi_data = {
static void __init pb44_init(void) static void __init pb44_init(void)
{ {
gpiod_add_lookup_table(&pb44_i2c_gpiod_table);
i2c_register_board_info(0, pb44_i2c_board_info, i2c_register_board_info(0, pb44_i2c_board_info,
ARRAY_SIZE(pb44_i2c_board_info)); ARRAY_SIZE(pb44_i2c_board_info));
platform_device_register(&pb44_i2c_gpio_device); platform_device_register(&pb44_i2c_gpio_device);
......
...@@ -116,6 +116,10 @@ static const struct apd_device_desc hip08_i2c_desc = { ...@@ -116,6 +116,10 @@ static const struct apd_device_desc hip08_i2c_desc = {
.setup = acpi_apd_setup, .setup = acpi_apd_setup,
.fixed_clk_rate = 250000000, .fixed_clk_rate = 250000000,
}; };
static const struct apd_device_desc thunderx2_i2c_desc = {
.setup = acpi_apd_setup,
.fixed_clk_rate = 125000000,
};
#endif #endif
#else #else
...@@ -180,6 +184,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = { ...@@ -180,6 +184,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = {
{ "APMC0D0F", APD_ADDR(xgene_i2c_desc) }, { "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
{ "BRCM900D", APD_ADDR(vulcan_spi_desc) }, { "BRCM900D", APD_ADDR(vulcan_spi_desc) },
{ "CAV900D", APD_ADDR(vulcan_spi_desc) }, { "CAV900D", APD_ADDR(vulcan_spi_desc) },
{ "CAV9007", APD_ADDR(thunderx2_i2c_desc) },
{ "HISI02A1", APD_ADDR(hip07_i2c_desc) }, { "HISI02A1", APD_ADDR(hip07_i2c_desc) },
{ "HISI02A2", APD_ADDR(hip08_i2c_desc) }, { "HISI02A2", APD_ADDR(hip08_i2c_desc) },
#endif #endif
......
...@@ -3528,8 +3528,21 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id, ...@@ -3528,8 +3528,21 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
if (lflags & GPIO_ACTIVE_LOW) if (lflags & GPIO_ACTIVE_LOW)
set_bit(FLAG_ACTIVE_LOW, &desc->flags); set_bit(FLAG_ACTIVE_LOW, &desc->flags);
if (lflags & GPIO_OPEN_DRAIN) if (lflags & GPIO_OPEN_DRAIN)
set_bit(FLAG_OPEN_DRAIN, &desc->flags); set_bit(FLAG_OPEN_DRAIN, &desc->flags);
else if (dflags & GPIOD_FLAGS_BIT_OPEN_DRAIN) {
/*
* This enforces open drain mode from the consumer side.
* This is necessary for some busses like I2C, but the lookup
* should *REALLY* have specified them as open drain in the
* first place, so print a little warning here.
*/
set_bit(FLAG_OPEN_DRAIN, &desc->flags);
gpiod_warn(desc,
"enforced open drain please flag it properly in DT/ACPI DSDT/board file\n");
}
if (lflags & GPIO_OPEN_SOURCE) if (lflags & GPIO_OPEN_SOURCE)
set_bit(FLAG_OPEN_SOURCE, &desc->flags); set_bit(FLAG_OPEN_SOURCE, &desc->flags);
if (lflags & GPIO_SLEEP_MAY_LOSE_VALUE) if (lflags & GPIO_SLEEP_MAY_LOSE_VALUE)
......
...@@ -198,6 +198,11 @@ config I2C_CHT_WC ...@@ -198,6 +198,11 @@ config I2C_CHT_WC
SMBus controller found in the Intel Cherry Trail Whiskey Cove PMIC SMBus controller found in the Intel Cherry Trail Whiskey Cove PMIC
found on some Intel Cherry Trail systems. found on some Intel Cherry Trail systems.
Note this controller is hooked up to a TI bq24292i charger-IC,
combined with a FUSB302 Type-C port-controller as such it is advised
to also select CONFIG_CHARGER_BQ24190=m and CONFIG_TYPEC_FUSB302=m
(the fusb302 driver currently is in drivers/staging).
config I2C_NFORCE2 config I2C_NFORCE2
tristate "Nvidia nForce2, nForce3 and nForce4" tristate "Nvidia nForce2, nForce3 and nForce4"
depends on PCI depends on PCI
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/of_irq.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/reset.h>
#include <linux/slab.h> #include <linux/slab.h>
/* I2C Register */ /* I2C Register */
...@@ -132,6 +133,7 @@ struct aspeed_i2c_bus { ...@@ -132,6 +133,7 @@ struct aspeed_i2c_bus {
struct i2c_adapter adap; struct i2c_adapter adap;
struct device *dev; struct device *dev;
void __iomem *base; void __iomem *base;
struct reset_control *rst;
/* Synchronizes I/O mem access to base. */ /* Synchronizes I/O mem access to base. */
spinlock_t lock; spinlock_t lock;
struct completion cmd_complete; struct completion cmd_complete;
...@@ -847,6 +849,14 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) ...@@ -847,6 +849,14 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
/* We just need the clock rate, we don't actually use the clk object. */ /* We just need the clock rate, we don't actually use the clk object. */
devm_clk_put(&pdev->dev, parent_clk); devm_clk_put(&pdev->dev, parent_clk);
bus->rst = devm_reset_control_get_shared(&pdev->dev, NULL);
if (IS_ERR(bus->rst)) {
dev_err(&pdev->dev,
"missing or invalid reset controller device tree entry");
return PTR_ERR(bus->rst);
}
reset_control_deassert(bus->rst);
ret = of_property_read_u32(pdev->dev.of_node, ret = of_property_read_u32(pdev->dev.of_node,
"bus-frequency", &bus->bus_frequency); "bus-frequency", &bus->bus_frequency);
if (ret < 0) { if (ret < 0) {
...@@ -917,6 +927,8 @@ static int aspeed_i2c_remove_bus(struct platform_device *pdev) ...@@ -917,6 +927,8 @@ static int aspeed_i2c_remove_bus(struct platform_device *pdev)
spin_unlock_irqrestore(&bus->lock, flags); spin_unlock_irqrestore(&bus->lock, flags);
reset_control_assert(bus->rst);
i2c_del_adapter(&bus->adap); i2c_del_adapter(&bus->adap);
return 0; return 0;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#include <linux/acpi.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/i2c.h> #include <linux/i2c.h>
...@@ -25,6 +26,7 @@ ...@@ -25,6 +26,7 @@
#include <linux/mfd/intel_soc_pmic.h> #include <linux/mfd/intel_soc_pmic.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/power/bq24190_charger.h>
#include <linux/slab.h> #include <linux/slab.h>
#define CHT_WC_I2C_CTRL 0x5e24 #define CHT_WC_I2C_CTRL 0x5e24
...@@ -232,13 +234,35 @@ static const struct irq_chip cht_wc_i2c_irq_chip = { ...@@ -232,13 +234,35 @@ static const struct irq_chip cht_wc_i2c_irq_chip = {
.name = "cht_wc_ext_chrg_irq_chip", .name = "cht_wc_ext_chrg_irq_chip",
}; };
static const char * const bq24190_suppliers[] = { "fusb302-typec-source" };
static const struct property_entry bq24190_props[] = { static const struct property_entry bq24190_props[] = {
PROPERTY_ENTRY_STRING("extcon-name", "cht_wcove_pwrsrc"), PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq24190_suppliers),
PROPERTY_ENTRY_BOOL("omit-battery-class"), PROPERTY_ENTRY_BOOL("omit-battery-class"),
PROPERTY_ENTRY_BOOL("disable-reset"), PROPERTY_ENTRY_BOOL("disable-reset"),
{ } { }
}; };
static struct regulator_consumer_supply fusb302_consumer = {
.supply = "vbus",
/* Must match fusb302 dev_name in intel_cht_int33fe.c */
.dev_name = "i2c-fusb302",
};
static const struct regulator_init_data bq24190_vbus_init_data = {
.constraints = {
/* The name is used in intel_cht_int33fe.c do not change. */
.name = "cht_wc_usb_typec_vbus",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
.consumer_supplies = &fusb302_consumer,
.num_consumer_supplies = 1,
};
static struct bq24190_platform_data bq24190_pdata = {
.regulator_init_data = &bq24190_vbus_init_data,
};
static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev) static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)
{ {
struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent); struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
...@@ -246,7 +270,9 @@ static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev) ...@@ -246,7 +270,9 @@ static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)
struct i2c_board_info board_info = { struct i2c_board_info board_info = {
.type = "bq24190", .type = "bq24190",
.addr = 0x6b, .addr = 0x6b,
.dev_name = "bq24190",
.properties = bq24190_props, .properties = bq24190_props,
.platform_data = &bq24190_pdata,
}; };
int ret, reg, irq; int ret, reg, irq;
...@@ -314,11 +340,21 @@ static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev) ...@@ -314,11 +340,21 @@ static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)
if (ret) if (ret)
goto remove_irq_domain; goto remove_irq_domain;
board_info.irq = adap->client_irq; /*
adap->client = i2c_new_device(&adap->adapter, &board_info); * Normally the Whiskey Cove PMIC is paired with a TI bq24292i charger,
if (!adap->client) { * connected to this i2c bus, and a max17047 fuel-gauge and a fusb302
ret = -ENOMEM; * USB Type-C controller connected to another i2c bus. In this setup
goto del_adapter; * the max17047 and fusb302 devices are enumerated through an INT33FE
* ACPI device. If this device is present register an i2c-client for
* the TI bq24292i charger.
*/
if (acpi_dev_present("INT33FE", NULL, -1)) {
board_info.irq = adap->client_irq;
adap->client = i2c_new_device(&adap->adapter, &board_info);
if (!adap->client) {
ret = -ENOMEM;
goto del_adapter;
}
} }
platform_set_drvdata(pdev, adap); platform_set_drvdata(pdev, adap);
...@@ -335,7 +371,8 @@ static int cht_wc_i2c_adap_i2c_remove(struct platform_device *pdev) ...@@ -335,7 +371,8 @@ static int cht_wc_i2c_adap_i2c_remove(struct platform_device *pdev)
{ {
struct cht_wc_i2c_adap *adap = platform_get_drvdata(pdev); struct cht_wc_i2c_adap *adap = platform_get_drvdata(pdev);
i2c_unregister_device(adap->client); if (adap->client)
i2c_unregister_device(adap->client);
i2c_del_adapter(&adap->adapter); i2c_del_adapter(&adap->adapter);
irq_domain_remove(adap->irq_domain); irq_domain_remove(adap->irq_domain);
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/platform_data/i2c-davinci.h> #include <linux/platform_data/i2c-davinci.h>
#include <linux/pm_runtime.h>
/* ----- global defines ----------------------------------------------- */ /* ----- global defines ----------------------------------------------- */
...@@ -122,6 +123,9 @@ ...@@ -122,6 +123,9 @@
/* set the SDA GPIO low */ /* set the SDA GPIO low */
#define DAVINCI_I2C_DCLR_PDCLR1 BIT(1) #define DAVINCI_I2C_DCLR_PDCLR1 BIT(1)
/* timeout for pm runtime autosuspend */
#define DAVINCI_I2C_PM_TIMEOUT 1000 /* ms */
struct davinci_i2c_dev { struct davinci_i2c_dev {
struct device *dev; struct device *dev;
void __iomem *base; void __iomem *base;
...@@ -500,7 +504,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) ...@@ -500,7 +504,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
/* This should be 0 if all bytes were transferred /* This should be 0 if all bytes were transferred
* or dev->cmd_err denotes an error. * or dev->cmd_err denotes an error.
*/ */
dev_err(dev->dev, "abnormal termination buf_len=%i\n", dev_err(dev->dev, "abnormal termination buf_len=%zu\n",
dev->buf_len); dev->buf_len);
dev->terminate = 1; dev->terminate = 1;
wmb(); wmb();
...@@ -541,10 +545,17 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) ...@@ -541,10 +545,17 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num); dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
ret = pm_runtime_get_sync(dev->dev);
if (ret < 0) {
dev_err(dev->dev, "Failed to runtime_get device: %d\n", ret);
pm_runtime_put_noidle(dev->dev);
return ret;
}
ret = i2c_davinci_wait_bus_not_busy(dev); ret = i2c_davinci_wait_bus_not_busy(dev);
if (ret < 0) { if (ret < 0) {
dev_warn(dev->dev, "timeout waiting for bus ready\n"); dev_warn(dev->dev, "timeout waiting for bus ready\n");
return ret; goto out;
} }
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
...@@ -552,14 +563,19 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) ...@@ -552,14 +563,19 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
dev_dbg(dev->dev, "%s [%d/%d] ret: %d\n", __func__, i + 1, num, dev_dbg(dev->dev, "%s [%d/%d] ret: %d\n", __func__, i + 1, num,
ret); ret);
if (ret < 0) if (ret < 0)
return ret; goto out;
} }
ret = num;
#ifdef CONFIG_CPU_FREQ #ifdef CONFIG_CPU_FREQ
complete(&dev->xfr_complete); complete(&dev->xfr_complete);
#endif #endif
return num; out:
pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
return ret;
} }
static u32 i2c_davinci_func(struct i2c_adapter *adap) static u32 i2c_davinci_func(struct i2c_adapter *adap)
...@@ -599,6 +615,9 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) ...@@ -599,6 +615,9 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
int count = 0; int count = 0;
u16 w; u16 w;
if (pm_runtime_suspended(dev->dev))
return IRQ_NONE;
while ((stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG))) { while ((stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG))) {
dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat); dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat);
if (count++ == 100) { if (count++ == 100) {
...@@ -802,13 +821,24 @@ static int davinci_i2c_probe(struct platform_device *pdev) ...@@ -802,13 +821,24 @@ static int davinci_i2c_probe(struct platform_device *pdev)
dev->clk = devm_clk_get(&pdev->dev, NULL); dev->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(dev->clk)) if (IS_ERR(dev->clk))
return PTR_ERR(dev->clk); return PTR_ERR(dev->clk);
clk_prepare_enable(dev->clk);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dev->base = devm_ioremap_resource(&pdev->dev, mem); dev->base = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(dev->base)) { if (IS_ERR(dev->base)) {
r = PTR_ERR(dev->base); return PTR_ERR(dev->base);
goto err_unuse_clocks; }
pm_runtime_set_autosuspend_delay(dev->dev,
DAVINCI_I2C_PM_TIMEOUT);
pm_runtime_use_autosuspend(dev->dev);
pm_runtime_enable(dev->dev);
r = pm_runtime_get_sync(dev->dev);
if (r < 0) {
dev_err(dev->dev, "failed to runtime_get device: %d\n", r);
pm_runtime_put_noidle(dev->dev);
return r;
} }
i2c_davinci_init(dev); i2c_davinci_init(dev);
...@@ -849,27 +879,40 @@ static int davinci_i2c_probe(struct platform_device *pdev) ...@@ -849,27 +879,40 @@ static int davinci_i2c_probe(struct platform_device *pdev)
if (r) if (r)
goto err_unuse_clocks; goto err_unuse_clocks;
pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
return 0; return 0;
err_unuse_clocks: err_unuse_clocks:
clk_disable_unprepare(dev->clk); pm_runtime_dont_use_autosuspend(dev->dev);
dev->clk = NULL; pm_runtime_put_sync(dev->dev);
pm_runtime_disable(dev->dev);
return r; return r;
} }
static int davinci_i2c_remove(struct platform_device *pdev) static int davinci_i2c_remove(struct platform_device *pdev)
{ {
struct davinci_i2c_dev *dev = platform_get_drvdata(pdev); struct davinci_i2c_dev *dev = platform_get_drvdata(pdev);
int ret;
i2c_davinci_cpufreq_deregister(dev); i2c_davinci_cpufreq_deregister(dev);
i2c_del_adapter(&dev->adapter); i2c_del_adapter(&dev->adapter);
clk_disable_unprepare(dev->clk); ret = pm_runtime_get_sync(&pdev->dev);
dev->clk = NULL; if (ret < 0) {
pm_runtime_put_noidle(&pdev->dev);
return ret;
}
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0); davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0);
pm_runtime_dont_use_autosuspend(dev->dev);
pm_runtime_put_sync(dev->dev);
pm_runtime_disable(dev->dev);
return 0; return 0;
} }
...@@ -880,7 +923,6 @@ static int davinci_i2c_suspend(struct device *dev) ...@@ -880,7 +923,6 @@ static int davinci_i2c_suspend(struct device *dev)
/* put I2C into reset */ /* put I2C into reset */
davinci_i2c_reset_ctrl(i2c_dev, 0); davinci_i2c_reset_ctrl(i2c_dev, 0);
clk_disable_unprepare(i2c_dev->clk);
return 0; return 0;
} }
...@@ -889,7 +931,6 @@ static int davinci_i2c_resume(struct device *dev) ...@@ -889,7 +931,6 @@ static int davinci_i2c_resume(struct device *dev)
{ {
struct davinci_i2c_dev *i2c_dev = dev_get_drvdata(dev); struct davinci_i2c_dev *i2c_dev = dev_get_drvdata(dev);
clk_prepare_enable(i2c_dev->clk);
/* take I2C out of reset */ /* take I2C out of reset */
davinci_i2c_reset_ctrl(i2c_dev, 1); davinci_i2c_reset_ctrl(i2c_dev, 1);
...@@ -899,6 +940,8 @@ static int davinci_i2c_resume(struct device *dev) ...@@ -899,6 +940,8 @@ static int davinci_i2c_resume(struct device *dev)
static const struct dev_pm_ops davinci_i2c_pm = { static const struct dev_pm_ops davinci_i2c_pm = {
.suspend = davinci_i2c_suspend, .suspend = davinci_i2c_suspend,
.resume = davinci_i2c_resume, .resume = davinci_i2c_resume,
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
}; };
#define davinci_i2c_pm_ops (&davinci_i2c_pm) #define davinci_i2c_pm_ops (&davinci_i2c_pm)
......
...@@ -280,6 +280,8 @@ struct dw_i2c_dev { ...@@ -280,6 +280,8 @@ struct dw_i2c_dev {
int (*acquire_lock)(struct dw_i2c_dev *dev); int (*acquire_lock)(struct dw_i2c_dev *dev);
void (*release_lock)(struct dw_i2c_dev *dev); void (*release_lock)(struct dw_i2c_dev *dev);
bool pm_disabled; bool pm_disabled;
bool suspended;
bool skip_resume;
void (*disable)(struct dw_i2c_dev *dev); void (*disable)(struct dw_i2c_dev *dev);
void (*disable_int)(struct dw_i2c_dev *dev); void (*disable_int)(struct dw_i2c_dev *dev);
int (*init)(struct dw_i2c_dev *dev); int (*init)(struct dw_i2c_dev *dev);
......
...@@ -249,6 +249,14 @@ static void dw_i2c_set_fifo_size(struct dw_i2c_dev *dev, int id) ...@@ -249,6 +249,14 @@ static void dw_i2c_set_fifo_size(struct dw_i2c_dev *dev, int id)
} }
} }
static void dw_i2c_plat_pm_cleanup(struct dw_i2c_dev *dev)
{
pm_runtime_disable(dev->dev);
if (dev->pm_disabled)
pm_runtime_put_noidle(dev->dev);
}
static int dw_i2c_plat_probe(struct platform_device *pdev) static int dw_i2c_plat_probe(struct platform_device *pdev)
{ {
struct dw_i2c_platform_data *pdata = dev_get_platdata(&pdev->dev); struct dw_i2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
...@@ -257,7 +265,9 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) ...@@ -257,7 +265,9 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
u32 acpi_speed, ht = 0; u32 acpi_speed, ht = 0;
struct resource *mem; struct resource *mem;
int i, irq, ret; int i, irq, ret;
const int supported_speeds[] = { 0, 100000, 400000, 1000000, 3400000 }; static const int supported_speeds[] = {
0, 100000, 400000, 1000000, 3400000
};
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) if (irq < 0)
...@@ -362,14 +372,17 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) ...@@ -362,14 +372,17 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
ACPI_COMPANION_SET(&adap->dev, ACPI_COMPANION(&pdev->dev)); ACPI_COMPANION_SET(&adap->dev, ACPI_COMPANION(&pdev->dev));
adap->dev.of_node = pdev->dev.of_node; adap->dev.of_node = pdev->dev.of_node;
if (dev->pm_disabled) { /* The code below assumes runtime PM to be disabled. */
pm_runtime_forbid(&pdev->dev); WARN_ON(pm_runtime_enabled(&pdev->dev));
} else {
pm_runtime_set_autosuspend_delay(&pdev->dev, 1000); pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_active(&pdev->dev); pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
} if (dev->pm_disabled)
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_enable(&pdev->dev);
if (dev->mode == DW_IC_SLAVE) if (dev->mode == DW_IC_SLAVE)
ret = i2c_dw_probe_slave(dev); ret = i2c_dw_probe_slave(dev);
...@@ -382,8 +395,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) ...@@ -382,8 +395,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
return ret; return ret;
exit_probe: exit_probe:
if (!dev->pm_disabled) dw_i2c_plat_pm_cleanup(dev);
pm_runtime_disable(&pdev->dev);
exit_reset: exit_reset:
if (!IS_ERR_OR_NULL(dev->rst)) if (!IS_ERR_OR_NULL(dev->rst))
reset_control_assert(dev->rst); reset_control_assert(dev->rst);
...@@ -402,8 +414,8 @@ static int dw_i2c_plat_remove(struct platform_device *pdev) ...@@ -402,8 +414,8 @@ static int dw_i2c_plat_remove(struct platform_device *pdev)
pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_put_sync(&pdev->dev); pm_runtime_put_sync(&pdev->dev);
if (!dev->pm_disabled) dw_i2c_plat_pm_cleanup(dev);
pm_runtime_disable(&pdev->dev);
if (!IS_ERR_OR_NULL(dev->rst)) if (!IS_ERR_OR_NULL(dev->rst))
reset_control_assert(dev->rst); reset_control_assert(dev->rst);
...@@ -437,13 +449,20 @@ static void dw_i2c_plat_complete(struct device *dev) ...@@ -437,13 +449,20 @@ static void dw_i2c_plat_complete(struct device *dev)
#endif #endif
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int dw_i2c_plat_runtime_suspend(struct device *dev) static int dw_i2c_plat_suspend(struct device *dev)
{ {
struct dw_i2c_dev *i_dev = dev_get_drvdata(dev); struct dw_i2c_dev *i_dev = dev_get_drvdata(dev);
if (i_dev->suspended) {
i_dev->skip_resume = true;
return 0;
}
i_dev->disable(i_dev); i_dev->disable(i_dev);
i2c_dw_plat_prepare_clk(i_dev, false); i2c_dw_plat_prepare_clk(i_dev, false);
i_dev->suspended = true;
return 0; return 0;
} }
...@@ -451,27 +470,27 @@ static int dw_i2c_plat_resume(struct device *dev) ...@@ -451,27 +470,27 @@ static int dw_i2c_plat_resume(struct device *dev)
{ {
struct dw_i2c_dev *i_dev = dev_get_drvdata(dev); struct dw_i2c_dev *i_dev = dev_get_drvdata(dev);
if (!i_dev->suspended)
return 0;
if (i_dev->skip_resume) {
i_dev->skip_resume = false;
return 0;
}
i2c_dw_plat_prepare_clk(i_dev, true); i2c_dw_plat_prepare_clk(i_dev, true);
i_dev->init(i_dev); i_dev->init(i_dev);
return 0; i_dev->suspended = false;
}
#ifdef CONFIG_PM_SLEEP return 0;
static int dw_i2c_plat_suspend(struct device *dev)
{
pm_runtime_resume(dev);
return dw_i2c_plat_runtime_suspend(dev);
} }
#endif
static const struct dev_pm_ops dw_i2c_dev_pm_ops = { static const struct dev_pm_ops dw_i2c_dev_pm_ops = {
.prepare = dw_i2c_plat_prepare, .prepare = dw_i2c_plat_prepare,
.complete = dw_i2c_plat_complete, .complete = dw_i2c_plat_complete,
SET_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume) SET_LATE_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume)
SET_RUNTIME_PM_OPS(dw_i2c_plat_runtime_suspend, SET_RUNTIME_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume, NULL)
dw_i2c_plat_resume,
NULL)
}; };
#define DW_I2C_DEV_PMOPS (&dw_i2c_dev_pm_ops) #define DW_I2C_DEV_PMOPS (&dw_i2c_dev_pm_ops)
......
...@@ -14,27 +14,17 @@ ...@@ -14,27 +14,17 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/gpio.h> #include <linux/gpio/consumer.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_gpio.h>
struct i2c_gpio_private_data { struct i2c_gpio_private_data {
struct gpio_desc *sda;
struct gpio_desc *scl;
struct i2c_adapter adap; struct i2c_adapter adap;
struct i2c_algo_bit_data bit_data; struct i2c_algo_bit_data bit_data;
struct i2c_gpio_platform_data pdata; struct i2c_gpio_platform_data pdata;
}; };
/* Toggle SDA by changing the direction of the pin */
static void i2c_gpio_setsda_dir(void *data, int state)
{
struct i2c_gpio_platform_data *pdata = data;
if (state)
gpio_direction_input(pdata->sda_pin);
else
gpio_direction_output(pdata->sda_pin, 0);
}
/* /*
* Toggle SDA by changing the output value of the pin. This is only * Toggle SDA by changing the output value of the pin. This is only
* valid for pins configured as open drain (i.e. setting the value * valid for pins configured as open drain (i.e. setting the value
...@@ -42,20 +32,9 @@ static void i2c_gpio_setsda_dir(void *data, int state) ...@@ -42,20 +32,9 @@ static void i2c_gpio_setsda_dir(void *data, int state)
*/ */
static void i2c_gpio_setsda_val(void *data, int state) static void i2c_gpio_setsda_val(void *data, int state)
{ {
struct i2c_gpio_platform_data *pdata = data; struct i2c_gpio_private_data *priv = data;
gpio_set_value(pdata->sda_pin, state);
}
/* Toggle SCL by changing the direction of the pin. */
static void i2c_gpio_setscl_dir(void *data, int state)
{
struct i2c_gpio_platform_data *pdata = data;
if (state) gpiod_set_value(priv->sda, state);
gpio_direction_input(pdata->scl_pin);
else
gpio_direction_output(pdata->scl_pin, 0);
} }
/* /*
...@@ -66,44 +45,23 @@ static void i2c_gpio_setscl_dir(void *data, int state) ...@@ -66,44 +45,23 @@ static void i2c_gpio_setscl_dir(void *data, int state)
*/ */
static void i2c_gpio_setscl_val(void *data, int state) static void i2c_gpio_setscl_val(void *data, int state)
{ {
struct i2c_gpio_platform_data *pdata = data; struct i2c_gpio_private_data *priv = data;
gpio_set_value(pdata->scl_pin, state); gpiod_set_value(priv->scl, state);
} }
static int i2c_gpio_getsda(void *data) static int i2c_gpio_getsda(void *data)
{ {
struct i2c_gpio_platform_data *pdata = data; struct i2c_gpio_private_data *priv = data;
return gpio_get_value(pdata->sda_pin); return gpiod_get_value(priv->sda);
} }
static int i2c_gpio_getscl(void *data) static int i2c_gpio_getscl(void *data)
{ {
struct i2c_gpio_platform_data *pdata = data; struct i2c_gpio_private_data *priv = data;
return gpio_get_value(pdata->scl_pin);
}
static int of_i2c_gpio_get_pins(struct device_node *np,
unsigned int *sda_pin, unsigned int *scl_pin)
{
if (of_gpio_count(np) < 2)
return -ENODEV;
*sda_pin = of_get_gpio(np, 0);
*scl_pin = of_get_gpio(np, 1);
if (*sda_pin == -EPROBE_DEFER || *scl_pin == -EPROBE_DEFER)
return -EPROBE_DEFER;
if (!gpio_is_valid(*sda_pin) || !gpio_is_valid(*scl_pin)) {
pr_err("%pOF: invalid GPIO pins, sda=%d/scl=%d\n",
np, *sda_pin, *scl_pin);
return -ENODEV;
}
return 0; return gpiod_get_value(priv->scl);
} }
static void of_i2c_gpio_get_props(struct device_node *np, static void of_i2c_gpio_get_props(struct device_node *np,
...@@ -124,72 +82,105 @@ static void of_i2c_gpio_get_props(struct device_node *np, ...@@ -124,72 +82,105 @@ static void of_i2c_gpio_get_props(struct device_node *np,
of_property_read_bool(np, "i2c-gpio,scl-output-only"); of_property_read_bool(np, "i2c-gpio,scl-output-only");
} }
static struct gpio_desc *i2c_gpio_get_desc(struct device *dev,
const char *con_id,
unsigned int index,
enum gpiod_flags gflags)
{
struct gpio_desc *retdesc;
int ret;
retdesc = devm_gpiod_get(dev, con_id, gflags);
if (!IS_ERR(retdesc)) {
dev_dbg(dev, "got GPIO from name %s\n", con_id);
return retdesc;
}
retdesc = devm_gpiod_get_index(dev, NULL, index, gflags);
if (!IS_ERR(retdesc)) {
dev_dbg(dev, "got GPIO from index %u\n", index);
return retdesc;
}
ret = PTR_ERR(retdesc);
/* FIXME: hack in the old code, is this really necessary? */
if (ret == -EINVAL)
retdesc = ERR_PTR(-EPROBE_DEFER);
/* This happens if the GPIO driver is not yet probed, let's defer */
if (ret == -ENOENT)
retdesc = ERR_PTR(-EPROBE_DEFER);
if (ret != -EPROBE_DEFER)
dev_err(dev, "error trying to get descriptor: %d\n", ret);
return retdesc;
}
static int i2c_gpio_probe(struct platform_device *pdev) static int i2c_gpio_probe(struct platform_device *pdev)
{ {
struct i2c_gpio_private_data *priv; struct i2c_gpio_private_data *priv;
struct i2c_gpio_platform_data *pdata; struct i2c_gpio_platform_data *pdata;
struct i2c_algo_bit_data *bit_data; struct i2c_algo_bit_data *bit_data;
struct i2c_adapter *adap; struct i2c_adapter *adap;
unsigned int sda_pin, scl_pin; struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
enum gpiod_flags gflags;
int ret; int ret;
/* First get the GPIO pins; if it fails, we'll defer the probe. */ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (pdev->dev.of_node) {
ret = of_i2c_gpio_get_pins(pdev->dev.of_node,
&sda_pin, &scl_pin);
if (ret)
return ret;
} else {
if (!dev_get_platdata(&pdev->dev))
return -ENXIO;
pdata = dev_get_platdata(&pdev->dev);
sda_pin = pdata->sda_pin;
scl_pin = pdata->scl_pin;
}
ret = devm_gpio_request(&pdev->dev, sda_pin, "sda");
if (ret) {
if (ret == -EINVAL)
ret = -EPROBE_DEFER; /* Try again later */
return ret;
}
ret = devm_gpio_request(&pdev->dev, scl_pin, "scl");
if (ret) {
if (ret == -EINVAL)
ret = -EPROBE_DEFER; /* Try again later */
return ret;
}
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
adap = &priv->adap; adap = &priv->adap;
bit_data = &priv->bit_data; bit_data = &priv->bit_data;
pdata = &priv->pdata; pdata = &priv->pdata;
if (pdev->dev.of_node) { if (np) {
pdata->sda_pin = sda_pin; of_i2c_gpio_get_props(np, pdata);
pdata->scl_pin = scl_pin;
of_i2c_gpio_get_props(pdev->dev.of_node, pdata);
} else { } else {
memcpy(pdata, dev_get_platdata(&pdev->dev), sizeof(*pdata)); /*
* If all platform data settings are zero it is OK
* to not provide any platform data from the board.
*/
if (dev_get_platdata(dev))
memcpy(pdata, dev_get_platdata(dev), sizeof(*pdata));
} }
if (pdata->sda_is_open_drain) { /*
gpio_direction_output(pdata->sda_pin, 1); * First get the GPIO pins; if it fails, we'll defer the probe.
bit_data->setsda = i2c_gpio_setsda_val; * If the SDA line is marked from platform data or device tree as
} else { * "open drain" it means something outside of our control is making
gpio_direction_input(pdata->sda_pin); * this line being handled as open drain, and we should just handle
bit_data->setsda = i2c_gpio_setsda_dir; * it as any other output. Else we enforce open drain as this is
} * required for an I2C bus.
*/
if (pdata->sda_is_open_drain)
gflags = GPIOD_OUT_HIGH;
else
gflags = GPIOD_OUT_HIGH_OPEN_DRAIN;
priv->sda = i2c_gpio_get_desc(dev, "sda", 0, gflags);
if (IS_ERR(priv->sda))
return PTR_ERR(priv->sda);
/*
* If the SCL line is marked from platform data or device tree as
* "open drain" it means something outside of our control is making
* this line being handled as open drain, and we should just handle
* it as any other output. Else we enforce open drain as this is
* required for an I2C bus.
*/
if (pdata->scl_is_open_drain)
gflags = GPIOD_OUT_LOW;
else
gflags = GPIOD_OUT_LOW_OPEN_DRAIN;
priv->scl = i2c_gpio_get_desc(dev, "scl", 1, gflags);
if (IS_ERR(priv->scl))
return PTR_ERR(priv->scl);
if (pdata->scl_is_open_drain || pdata->scl_is_output_only) { bit_data->setsda = i2c_gpio_setsda_val;
gpio_direction_output(pdata->scl_pin, 1); bit_data->setscl = i2c_gpio_setscl_val;
bit_data->setscl = i2c_gpio_setscl_val;
} else {
gpio_direction_input(pdata->scl_pin);
bit_data->setscl = i2c_gpio_setscl_dir;
}
if (!pdata->scl_is_output_only) if (!pdata->scl_is_output_only)
bit_data->getscl = i2c_gpio_getscl; bit_data->getscl = i2c_gpio_getscl;
...@@ -207,18 +198,18 @@ static int i2c_gpio_probe(struct platform_device *pdev) ...@@ -207,18 +198,18 @@ static int i2c_gpio_probe(struct platform_device *pdev)
else else
bit_data->timeout = HZ / 10; /* 100 ms */ bit_data->timeout = HZ / 10; /* 100 ms */
bit_data->data = pdata; bit_data->data = priv;
adap->owner = THIS_MODULE; adap->owner = THIS_MODULE;
if (pdev->dev.of_node) if (np)
strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); strlcpy(adap->name, dev_name(dev), sizeof(adap->name));
else else
snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id); snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
adap->algo_data = bit_data; adap->algo_data = bit_data;
adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adap->dev.parent = &pdev->dev; adap->dev.parent = dev;
adap->dev.of_node = pdev->dev.of_node; adap->dev.of_node = np;
adap->nr = pdev->id; adap->nr = pdev->id;
ret = i2c_bit_add_numbered_bus(adap); ret = i2c_bit_add_numbered_bus(adap);
...@@ -227,8 +218,13 @@ static int i2c_gpio_probe(struct platform_device *pdev) ...@@ -227,8 +218,13 @@ static int i2c_gpio_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, priv); platform_set_drvdata(pdev, priv);
dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n", /*
pdata->sda_pin, pdata->scl_pin, * FIXME: using global GPIO numbers is not helpful. If/when we
* get accessors to get the actual name of the GPIO line,
* from the descriptor, then provide that instead.
*/
dev_info(dev, "using lines %u (SDA) and %u (SCL%s)\n",
desc_to_gpio(priv->sda), desc_to_gpio(priv->scl),
pdata->scl_is_output_only pdata->scl_is_output_only
? ", no clock stretching" : ""); ? ", no clock stretching" : "");
......
...@@ -82,6 +82,7 @@ ...@@ -82,6 +82,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/timer.h> #include <linux/timer.h>
...@@ -280,6 +281,8 @@ ...@@ -280,6 +281,8 @@
#define ISR_COMPLETE(err) (ISR_COMPLETE_M | (ISR_STATUS_M & (err))) #define ISR_COMPLETE(err) (ISR_COMPLETE_M | (ISR_STATUS_M & (err)))
#define ISR_FATAL(err) (ISR_COMPLETE(err) | ISR_FATAL_M) #define ISR_FATAL(err) (ISR_COMPLETE(err) | ISR_FATAL_M)
#define IMG_I2C_PM_TIMEOUT 1000 /* ms */
enum img_i2c_mode { enum img_i2c_mode {
MODE_INACTIVE, MODE_INACTIVE,
MODE_RAW, MODE_RAW,
...@@ -408,6 +411,9 @@ struct img_i2c { ...@@ -408,6 +411,9 @@ struct img_i2c {
unsigned int raw_timeout; unsigned int raw_timeout;
}; };
static int img_i2c_runtime_suspend(struct device *dev);
static int img_i2c_runtime_resume(struct device *dev);
static void img_i2c_writel(struct img_i2c *i2c, u32 offset, u32 value) static void img_i2c_writel(struct img_i2c *i2c, u32 offset, u32 value)
{ {
writel(value, i2c->base + offset); writel(value, i2c->base + offset);
...@@ -826,9 +832,9 @@ static unsigned int img_i2c_atomic(struct img_i2c *i2c, ...@@ -826,9 +832,9 @@ static unsigned int img_i2c_atomic(struct img_i2c *i2c,
* Timer function to check if something has gone wrong in automatic mode (so we * Timer function to check if something has gone wrong in automatic mode (so we
* don't have to handle so many interrupts just to catch an exception). * don't have to handle so many interrupts just to catch an exception).
*/ */
static void img_i2c_check_timer(unsigned long arg) static void img_i2c_check_timer(struct timer_list *t)
{ {
struct img_i2c *i2c = (struct img_i2c *)arg; struct img_i2c *i2c = from_timer(i2c, t, check_timer);
unsigned long flags; unsigned long flags;
unsigned int line_status; unsigned int line_status;
...@@ -1054,8 +1060,8 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ...@@ -1054,8 +1060,8 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
atomic = true; atomic = true;
} }
ret = clk_prepare_enable(i2c->scb_clk); ret = pm_runtime_get_sync(adap->dev.parent);
if (ret) if (ret < 0)
return ret; return ret;
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
...@@ -1131,7 +1137,8 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ...@@ -1131,7 +1137,8 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
break; break;
} }
clk_disable_unprepare(i2c->scb_clk); pm_runtime_mark_last_busy(adap->dev.parent);
pm_runtime_put_autosuspend(adap->dev.parent);
return i2c->msg_status ? i2c->msg_status : num; return i2c->msg_status ? i2c->msg_status : num;
} }
...@@ -1149,12 +1156,13 @@ static const struct i2c_algorithm img_i2c_algo = { ...@@ -1149,12 +1156,13 @@ static const struct i2c_algorithm img_i2c_algo = {
static int img_i2c_init(struct img_i2c *i2c) static int img_i2c_init(struct img_i2c *i2c)
{ {
unsigned int clk_khz, bitrate_khz, clk_period, tckh, tckl, tsdh; unsigned int clk_khz, bitrate_khz, clk_period, tckh, tckl, tsdh;
unsigned int i, ret, data, prescale, inc, int_bitrate, filt; unsigned int i, data, prescale, inc, int_bitrate, filt;
struct img_i2c_timings timing; struct img_i2c_timings timing;
u32 rev; u32 rev;
int ret;
ret = clk_prepare_enable(i2c->scb_clk); ret = pm_runtime_get_sync(i2c->adap.dev.parent);
if (ret) if (ret < 0)
return ret; return ret;
rev = img_i2c_readl(i2c, SCB_CORE_REV_REG); rev = img_i2c_readl(i2c, SCB_CORE_REV_REG);
...@@ -1163,7 +1171,8 @@ static int img_i2c_init(struct img_i2c *i2c) ...@@ -1163,7 +1171,8 @@ static int img_i2c_init(struct img_i2c *i2c)
"Unknown hardware revision (%d.%d.%d.%d)\n", "Unknown hardware revision (%d.%d.%d.%d)\n",
(rev >> 24) & 0xff, (rev >> 16) & 0xff, (rev >> 24) & 0xff, (rev >> 16) & 0xff,
(rev >> 8) & 0xff, rev & 0xff); (rev >> 8) & 0xff, rev & 0xff);
clk_disable_unprepare(i2c->scb_clk); pm_runtime_mark_last_busy(i2c->adap.dev.parent);
pm_runtime_put_autosuspend(i2c->adap.dev.parent);
return -EINVAL; return -EINVAL;
} }
...@@ -1314,7 +1323,8 @@ static int img_i2c_init(struct img_i2c *i2c) ...@@ -1314,7 +1323,8 @@ static int img_i2c_init(struct img_i2c *i2c)
/* Perform a synchronous sequence to reset the bus */ /* Perform a synchronous sequence to reset the bus */
ret = img_i2c_reset_bus(i2c); ret = img_i2c_reset_bus(i2c);
clk_disable_unprepare(i2c->scb_clk); pm_runtime_mark_last_busy(i2c->adap.dev.parent);
pm_runtime_put_autosuspend(i2c->adap.dev.parent);
return ret; return ret;
} }
...@@ -1362,8 +1372,7 @@ static int img_i2c_probe(struct platform_device *pdev) ...@@ -1362,8 +1372,7 @@ static int img_i2c_probe(struct platform_device *pdev)
} }
/* Set up the exception check timer */ /* Set up the exception check timer */
setup_timer(&i2c->check_timer, img_i2c_check_timer, timer_setup(&i2c->check_timer, img_i2c_check_timer, 0);
(unsigned long)i2c);
i2c->bitrate = timings[0].max_bitrate; i2c->bitrate = timings[0].max_bitrate;
if (!of_property_read_u32(node, "clock-frequency", &val)) if (!of_property_read_u32(node, "clock-frequency", &val))
...@@ -1384,22 +1393,30 @@ static int img_i2c_probe(struct platform_device *pdev) ...@@ -1384,22 +1393,30 @@ static int img_i2c_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, i2c); platform_set_drvdata(pdev, i2c);
ret = clk_prepare_enable(i2c->sys_clk); pm_runtime_set_autosuspend_delay(&pdev->dev, IMG_I2C_PM_TIMEOUT);
if (ret) pm_runtime_use_autosuspend(&pdev->dev);
return ret; pm_runtime_enable(&pdev->dev);
if (!pm_runtime_enabled(&pdev->dev)) {
ret = img_i2c_runtime_resume(&pdev->dev);
if (ret)
return ret;
}
ret = img_i2c_init(i2c); ret = img_i2c_init(i2c);
if (ret) if (ret)
goto disable_clk; goto rpm_disable;
ret = i2c_add_numbered_adapter(&i2c->adap); ret = i2c_add_numbered_adapter(&i2c->adap);
if (ret < 0) if (ret < 0)
goto disable_clk; goto rpm_disable;
return 0; return 0;
disable_clk: rpm_disable:
clk_disable_unprepare(i2c->sys_clk); if (!pm_runtime_enabled(&pdev->dev))
img_i2c_runtime_suspend(&pdev->dev);
pm_runtime_disable(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
return ret; return ret;
} }
...@@ -1408,19 +1425,55 @@ static int img_i2c_remove(struct platform_device *dev) ...@@ -1408,19 +1425,55 @@ static int img_i2c_remove(struct platform_device *dev)
struct img_i2c *i2c = platform_get_drvdata(dev); struct img_i2c *i2c = platform_get_drvdata(dev);
i2c_del_adapter(&i2c->adap); i2c_del_adapter(&i2c->adap);
pm_runtime_disable(&dev->dev);
if (!pm_runtime_status_suspended(&dev->dev))
img_i2c_runtime_suspend(&dev->dev);
return 0;
}
static int img_i2c_runtime_suspend(struct device *dev)
{
struct img_i2c *i2c = dev_get_drvdata(dev);
clk_disable_unprepare(i2c->scb_clk);
clk_disable_unprepare(i2c->sys_clk); clk_disable_unprepare(i2c->sys_clk);
return 0; return 0;
} }
static int img_i2c_runtime_resume(struct device *dev)
{
struct img_i2c *i2c = dev_get_drvdata(dev);
int ret;
ret = clk_prepare_enable(i2c->sys_clk);
if (ret) {
dev_err(dev, "Unable to enable sys clock\n");
return ret;
}
ret = clk_prepare_enable(i2c->scb_clk);
if (ret) {
dev_err(dev, "Unable to enable scb clock\n");
clk_disable_unprepare(i2c->sys_clk);
return ret;
}
return 0;
}
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int img_i2c_suspend(struct device *dev) static int img_i2c_suspend(struct device *dev)
{ {
struct img_i2c *i2c = dev_get_drvdata(dev); struct img_i2c *i2c = dev_get_drvdata(dev);
int ret;
img_i2c_switch_mode(i2c, MODE_SUSPEND); ret = pm_runtime_force_suspend(dev);
if (ret)
return ret;
clk_disable_unprepare(i2c->sys_clk); img_i2c_switch_mode(i2c, MODE_SUSPEND);
return 0; return 0;
} }
...@@ -1430,7 +1483,7 @@ static int img_i2c_resume(struct device *dev) ...@@ -1430,7 +1483,7 @@ static int img_i2c_resume(struct device *dev)
struct img_i2c *i2c = dev_get_drvdata(dev); struct img_i2c *i2c = dev_get_drvdata(dev);
int ret; int ret;
ret = clk_prepare_enable(i2c->sys_clk); ret = pm_runtime_force_resume(dev);
if (ret) if (ret)
return ret; return ret;
...@@ -1440,7 +1493,12 @@ static int img_i2c_resume(struct device *dev) ...@@ -1440,7 +1493,12 @@ static int img_i2c_resume(struct device *dev)
} }
#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM_SLEEP */
static SIMPLE_DEV_PM_OPS(img_i2c_pm, img_i2c_suspend, img_i2c_resume); static const struct dev_pm_ops img_i2c_pm = {
SET_RUNTIME_PM_OPS(img_i2c_runtime_suspend,
img_i2c_runtime_resume,
NULL)
SET_SYSTEM_SLEEP_PM_OPS(img_i2c_suspend, img_i2c_resume)
};
static const struct of_device_id img_scb_i2c_match[] = { static const struct of_device_id img_scb_i2c_match[] = {
{ .compatible = "img,scb-i2c" }, { .compatible = "img,scb-i2c" },
......
...@@ -322,7 +322,7 @@ static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] = { ...@@ -322,7 +322,7 @@ static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] = {
static u32 mpc_i2c_get_sec_cfg_8xxx(void) static u32 mpc_i2c_get_sec_cfg_8xxx(void)
{ {
struct device_node *node = NULL; struct device_node *node;
u32 __iomem *reg; u32 __iomem *reg;
u32 val = 0; u32 val = 0;
...@@ -700,7 +700,7 @@ static int fsl_i2c_probe(struct platform_device *op) ...@@ -700,7 +700,7 @@ static int fsl_i2c_probe(struct platform_device *op)
} }
} }
if (of_get_property(op->dev.of_node, "fsl,preserve-clocking", NULL)) { if (of_property_read_bool(op->dev.of_node, "fsl,preserve-clocking")) {
clock = MPC_I2C_CLOCK_PRESERVE; clock = MPC_I2C_CLOCK_PRESERVE;
} else { } else {
prop = of_get_property(op->dev.of_node, "clock-frequency", prop = of_get_property(op->dev.of_node, "clock-frequency",
......
...@@ -486,6 +486,22 @@ static int omap_i2c_init(struct omap_i2c_dev *omap) ...@@ -486,6 +486,22 @@ static int omap_i2c_init(struct omap_i2c_dev *omap)
return 0; return 0;
} }
/*
* Try bus recovery, but only if SDA is actually low.
*/
static int omap_i2c_recover_bus(struct omap_i2c_dev *omap)
{
u16 systest;
systest = omap_i2c_read_reg(omap, OMAP_I2C_SYSTEST_REG);
if ((systest & OMAP_I2C_SYSTEST_SCL_I_FUNC) &&
(systest & OMAP_I2C_SYSTEST_SDA_I_FUNC))
return 0; /* bus seems to already be fine */
if (!(systest & OMAP_I2C_SYSTEST_SCL_I_FUNC))
return -EBUSY; /* recovery would not fix SCL */
return i2c_recover_bus(&omap->adapter);
}
/* /*
* Waiting on Bus Busy * Waiting on Bus Busy
*/ */
...@@ -496,7 +512,7 @@ static int omap_i2c_wait_for_bb(struct omap_i2c_dev *omap) ...@@ -496,7 +512,7 @@ static int omap_i2c_wait_for_bb(struct omap_i2c_dev *omap)
timeout = jiffies + OMAP_I2C_TIMEOUT; timeout = jiffies + OMAP_I2C_TIMEOUT;
while (omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG) & OMAP_I2C_STAT_BB) { while (omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG) & OMAP_I2C_STAT_BB) {
if (time_after(jiffies, timeout)) if (time_after(jiffies, timeout))
return i2c_recover_bus(&omap->adapter); return omap_i2c_recover_bus(omap);
msleep(1); msleep(1);
} }
...@@ -577,8 +593,13 @@ static int omap_i2c_wait_for_bb_valid(struct omap_i2c_dev *omap) ...@@ -577,8 +593,13 @@ static int omap_i2c_wait_for_bb_valid(struct omap_i2c_dev *omap)
} }
if (time_after(jiffies, timeout)) { if (time_after(jiffies, timeout)) {
/*
* SDA or SCL were low for the entire timeout without
* any activity detected. Most likely, a slave is
* locking up the bus with no master driving the clock.
*/
dev_warn(omap->dev, "timeout waiting for bus ready\n"); dev_warn(omap->dev, "timeout waiting for bus ready\n");
return -ETIMEDOUT; return omap_i2c_recover_bus(omap);
} }
msleep(1); msleep(1);
......
...@@ -123,7 +123,6 @@ static struct i2c_adapter parport_adapter = { ...@@ -123,7 +123,6 @@ static struct i2c_adapter parport_adapter = {
/* SMBus alert support */ /* SMBus alert support */
static struct i2c_smbus_alert_setup alert_data = { static struct i2c_smbus_alert_setup alert_data = {
.alert_edge_triggered = 1,
}; };
static struct i2c_client *ara; static struct i2c_client *ara;
static struct lineop parport_ctrl_irq = { static struct lineop parport_ctrl_irq = {
......
...@@ -237,7 +237,6 @@ static void i2c_parport_attach(struct parport *port) ...@@ -237,7 +237,6 @@ static void i2c_parport_attach(struct parport *port)
/* Setup SMBus alert if supported */ /* Setup SMBus alert if supported */
if (adapter_parm[type].smbus_alert) { if (adapter_parm[type].smbus_alert) {
adapter->alert_data.alert_edge_triggered = 1;
adapter->ara = i2c_setup_smbus_alert(&adapter->adapter, adapter->ara = i2c_setup_smbus_alert(&adapter->adapter,
&adapter->alert_data); &adapter->alert_data);
if (adapter->ara) if (adapter->ara)
......
...@@ -112,7 +112,6 @@ static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data) ...@@ -112,7 +112,6 @@ static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)
jiffies, expires); jiffies, expires);
timer->expires = jiffies + expires; timer->expires = jiffies + expires;
timer->data = (unsigned long)alg_data;
add_timer(timer); add_timer(timer);
} }
...@@ -435,9 +434,9 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id) ...@@ -435,9 +434,9 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void i2c_pnx_timeout(unsigned long data) static void i2c_pnx_timeout(struct timer_list *t)
{ {
struct i2c_pnx_algo_data *alg_data = (struct i2c_pnx_algo_data *)data; struct i2c_pnx_algo_data *alg_data = from_timer(alg_data, t, mif.timer);
u32 ctl; u32 ctl;
dev_err(&alg_data->adapter.dev, dev_err(&alg_data->adapter.dev,
...@@ -659,8 +658,7 @@ static int i2c_pnx_probe(struct platform_device *pdev) ...@@ -659,8 +658,7 @@ static int i2c_pnx_probe(struct platform_device *pdev)
if (IS_ERR(alg_data->clk)) if (IS_ERR(alg_data->clk))
return PTR_ERR(alg_data->clk); return PTR_ERR(alg_data->clk);
setup_timer(&alg_data->mif.timer, i2c_pnx_timeout, timer_setup(&alg_data->mif.timer, i2c_pnx_timeout, 0);
(unsigned long)alg_data);
snprintf(alg_data->adapter.name, sizeof(alg_data->adapter.name), snprintf(alg_data->adapter.name, sizeof(alg_data->adapter.name),
"%s", pdev->name); "%s", pdev->name);
......
...@@ -84,12 +84,7 @@ ...@@ -84,12 +84,7 @@
#define ICSR2_NACKF 0x10 #define ICSR2_NACKF 0x10
/* ICBRx (@ PCLK 33MHz) */
#define ICBR_RESERVED 0xe0 /* Should be 1 on writes */ #define ICBR_RESERVED 0xe0 /* Should be 1 on writes */
#define ICBRL_SP100K (19 | ICBR_RESERVED)
#define ICBRH_SP100K (16 | ICBR_RESERVED)
#define ICBRL_SP400K (21 | ICBR_RESERVED)
#define ICBRH_SP400K (9 | ICBR_RESERVED)
#define RIIC_INIT_MSG -1 #define RIIC_INIT_MSG -1
...@@ -288,48 +283,99 @@ static const struct i2c_algorithm riic_algo = { ...@@ -288,48 +283,99 @@ static const struct i2c_algorithm riic_algo = {
.functionality = riic_func, .functionality = riic_func,
}; };
static int riic_init_hw(struct riic_dev *riic, u32 spd) static int riic_init_hw(struct riic_dev *riic, struct i2c_timings *t)
{ {
int ret; int ret;
unsigned long rate; unsigned long rate;
int total_ticks, cks, brl, brh;
ret = clk_prepare_enable(riic->clk); ret = clk_prepare_enable(riic->clk);
if (ret) if (ret)
return ret; return ret;
if (t->bus_freq_hz > 400000) {
dev_err(&riic->adapter.dev,
"unsupported bus speed (%dHz). 400000 max\n",
t->bus_freq_hz);
clk_disable_unprepare(riic->clk);
return -EINVAL;
}
rate = clk_get_rate(riic->clk);
/* /*
* TODO: Implement formula to calculate the timing values depending on * Assume the default register settings:
* variable parent clock rate and arbitrary bus speed * FER.SCLE = 1 (SCL sync circuit enabled, adds 2 or 3 cycles)
* FER.NFE = 1 (noise circuit enabled)
* MR3.NF = 0 (1 cycle of noise filtered out)
*
* Freq (CKS=000) = (I2CCLK + tr + tf)/ (BRH + 3 + 1) + (BRL + 3 + 1)
* Freq (CKS!=000) = (I2CCLK + tr + tf)/ (BRH + 2 + 1) + (BRL + 2 + 1)
*/ */
rate = clk_get_rate(riic->clk);
if (rate != 33325000) { /*
dev_err(&riic->adapter.dev, * Determine reference clock rate. We must be able to get the desired
"invalid parent clk (%lu). Must be 33325000Hz\n", rate); * frequency with only 62 clock ticks max (31 high, 31 low).
* Aim for a duty of 60% LOW, 40% HIGH.
*/
total_ticks = DIV_ROUND_UP(rate, t->bus_freq_hz);
for (cks = 0; cks < 7; cks++) {
/*
* 60% low time must be less than BRL + 2 + 1
* BRL max register value is 0x1F.
*/
brl = ((total_ticks * 6) / 10);
if (brl <= (0x1F + 3))
break;
total_ticks /= 2;
rate /= 2;
}
if (brl > (0x1F + 3)) {
dev_err(&riic->adapter.dev, "invalid speed (%lu). Too slow.\n",
(unsigned long)t->bus_freq_hz);
clk_disable_unprepare(riic->clk); clk_disable_unprepare(riic->clk);
return -EINVAL; return -EINVAL;
} }
brh = total_ticks - brl;
/* Remove automatic clock ticks for sync circuit and NF */
if (cks == 0) {
brl -= 4;
brh -= 4;
} else {
brl -= 3;
brh -= 3;
}
/*
* Remove clock ticks for rise and fall times. Convert ns to clock
* ticks.
*/
brl -= t->scl_fall_ns / (1000000000 / rate);
brh -= t->scl_rise_ns / (1000000000 / rate);
/* Adjust for min register values for when SCLE=1 and NFE=1 */
if (brl < 1)
brl = 1;
if (brh < 1)
brh = 1;
pr_debug("i2c-riic: freq=%lu, duty=%d, fall=%lu, rise=%lu, cks=%d, brl=%d, brh=%d\n",
rate / total_ticks, ((brl + 3) * 100) / (brl + brh + 6),
t->scl_fall_ns / (1000000000 / rate),
t->scl_rise_ns / (1000000000 / rate), cks, brl, brh);
/* Changing the order of accessing IICRST and ICE may break things! */ /* Changing the order of accessing IICRST and ICE may break things! */
writeb(ICCR1_IICRST | ICCR1_SOWP, riic->base + RIIC_ICCR1); writeb(ICCR1_IICRST | ICCR1_SOWP, riic->base + RIIC_ICCR1);
riic_clear_set_bit(riic, 0, ICCR1_ICE, RIIC_ICCR1); riic_clear_set_bit(riic, 0, ICCR1_ICE, RIIC_ICCR1);
switch (spd) { writeb(ICMR1_CKS(cks), riic->base + RIIC_ICMR1);
case 100000: writeb(brh | ICBR_RESERVED, riic->base + RIIC_ICBRH);
writeb(ICMR1_CKS(3), riic->base + RIIC_ICMR1); writeb(brl | ICBR_RESERVED, riic->base + RIIC_ICBRL);
writeb(ICBRH_SP100K, riic->base + RIIC_ICBRH);
writeb(ICBRL_SP100K, riic->base + RIIC_ICBRL);
break;
case 400000:
writeb(ICMR1_CKS(1), riic->base + RIIC_ICMR1);
writeb(ICBRH_SP400K, riic->base + RIIC_ICBRH);
writeb(ICBRL_SP400K, riic->base + RIIC_ICBRL);
break;
default:
dev_err(&riic->adapter.dev,
"unsupported bus speed (%dHz). Use 100000 or 400000\n", spd);
clk_disable_unprepare(riic->clk);
return -EINVAL;
}
writeb(0, riic->base + RIIC_ICSER); writeb(0, riic->base + RIIC_ICSER);
writeb(ICMR3_ACKWP | ICMR3_RDRFS, riic->base + RIIC_ICMR3); writeb(ICMR3_ACKWP | ICMR3_RDRFS, riic->base + RIIC_ICMR3);
...@@ -351,11 +397,10 @@ static struct riic_irq_desc riic_irqs[] = { ...@@ -351,11 +397,10 @@ static struct riic_irq_desc riic_irqs[] = {
static int riic_i2c_probe(struct platform_device *pdev) static int riic_i2c_probe(struct platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node;
struct riic_dev *riic; struct riic_dev *riic;
struct i2c_adapter *adap; struct i2c_adapter *adap;
struct resource *res; struct resource *res;
u32 bus_rate = 0; struct i2c_timings i2c_t;
int i, ret; int i, ret;
riic = devm_kzalloc(&pdev->dev, sizeof(*riic), GFP_KERNEL); riic = devm_kzalloc(&pdev->dev, sizeof(*riic), GFP_KERNEL);
...@@ -396,8 +441,9 @@ static int riic_i2c_probe(struct platform_device *pdev) ...@@ -396,8 +441,9 @@ static int riic_i2c_probe(struct platform_device *pdev)
init_completion(&riic->msg_done); init_completion(&riic->msg_done);
of_property_read_u32(np, "clock-frequency", &bus_rate); i2c_parse_fw_timings(&pdev->dev, &i2c_t, true);
ret = riic_init_hw(riic, bus_rate);
ret = riic_init_hw(riic, &i2c_t);
if (ret) if (ret)
return ret; return ret;
...@@ -408,7 +454,8 @@ static int riic_i2c_probe(struct platform_device *pdev) ...@@ -408,7 +454,8 @@ static int riic_i2c_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, riic); platform_set_drvdata(pdev, riic);
dev_info(&pdev->dev, "registered with %dHz bus speed\n", bus_rate); dev_info(&pdev->dev, "registered with %dHz bus speed\n",
i2c_t.bus_freq_hz);
return 0; return 0;
} }
......
...@@ -881,7 +881,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) ...@@ -881,7 +881,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
struct sh_mobile_i2c_data *pd; struct sh_mobile_i2c_data *pd;
struct i2c_adapter *adap; struct i2c_adapter *adap;
struct resource *res; struct resource *res;
const struct of_device_id *match; const struct sh_mobile_dt_config *config;
int ret; int ret;
u32 bus_speed; u32 bus_speed;
...@@ -913,10 +913,8 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) ...@@ -913,10 +913,8 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
pd->bus_speed = ret ? STANDARD_MODE : bus_speed; pd->bus_speed = ret ? STANDARD_MODE : bus_speed;
pd->clks_per_count = 1; pd->clks_per_count = 1;
match = of_match_device(sh_mobile_i2c_dt_ids, &dev->dev); config = of_device_get_match_data(&dev->dev);
if (match) { if (config) {
const struct sh_mobile_dt_config *config = match->data;
pd->clks_per_count = config->clks_per_count; pd->clks_per_count = config->clks_per_count;
if (config->setup) if (config->setup)
......
...@@ -282,8 +282,7 @@ static void taos_disconnect(struct serio *serio) ...@@ -282,8 +282,7 @@ static void taos_disconnect(struct serio *serio)
{ {
struct taos_data *taos = serio_get_drvdata(serio); struct taos_data *taos = serio_get_drvdata(serio);
if (taos->client) i2c_unregister_device(taos->client);
i2c_unregister_device(taos->client);
i2c_del_adapter(&taos->adapter); i2c_del_adapter(&taos->adapter);
serio_close(serio); serio_close(serio);
kfree(taos); kfree(taos);
......
...@@ -118,8 +118,6 @@ static void thunder_i2c_clock_disable(struct device *dev, struct clk *clk) ...@@ -118,8 +118,6 @@ static void thunder_i2c_clock_disable(struct device *dev, struct clk *clk)
static int thunder_i2c_smbus_setup_of(struct octeon_i2c *i2c, static int thunder_i2c_smbus_setup_of(struct octeon_i2c *i2c,
struct device_node *node) struct device_node *node)
{ {
u32 type;
if (!node) if (!node)
return -EINVAL; return -EINVAL;
...@@ -127,10 +125,6 @@ static int thunder_i2c_smbus_setup_of(struct octeon_i2c *i2c, ...@@ -127,10 +125,6 @@ static int thunder_i2c_smbus_setup_of(struct octeon_i2c *i2c,
if (!i2c->alert_data.irq) if (!i2c->alert_data.irq)
return -EINVAL; return -EINVAL;
type = irqd_get_trigger_type(irq_get_irq_data(i2c->alert_data.irq));
i2c->alert_data.alert_edge_triggered =
(type & IRQ_TYPE_LEVEL_MASK) ? 1 : 0;
i2c->ara = i2c_setup_smbus_alert(&i2c->adap, &i2c->alert_data); i2c->ara = i2c_setup_smbus_alert(&i2c->adap, &i2c->alert_data);
if (!i2c->ara) if (!i2c->ara)
return -ENODEV; return -ENODEV;
...@@ -149,8 +143,7 @@ static int thunder_i2c_smbus_setup(struct octeon_i2c *i2c, ...@@ -149,8 +143,7 @@ static int thunder_i2c_smbus_setup(struct octeon_i2c *i2c,
static void thunder_i2c_smbus_remove(struct octeon_i2c *i2c) static void thunder_i2c_smbus_remove(struct octeon_i2c *i2c)
{ {
if (i2c->ara) i2c_unregister_device(i2c->ara);
i2c_unregister_device(i2c->ara);
} }
static int thunder_i2c_probe_pci(struct pci_dev *pdev, static int thunder_i2c_probe_pci(struct pci_dev *pdev,
......
...@@ -129,6 +129,11 @@ struct slimpro_i2c_dev { ...@@ -129,6 +129,11 @@ struct slimpro_i2c_dev {
#define to_slimpro_i2c_dev(cl) \ #define to_slimpro_i2c_dev(cl) \
container_of(cl, struct slimpro_i2c_dev, mbox_client) container_of(cl, struct slimpro_i2c_dev, mbox_client)
enum slimpro_i2c_version {
XGENE_SLIMPRO_I2C_V1 = 0,
XGENE_SLIMPRO_I2C_V2 = 1,
};
/* /*
* This function tests and clears a bitmask then returns its old value * This function tests and clears a bitmask then returns its old value
*/ */
...@@ -476,6 +481,15 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev) ...@@ -476,6 +481,15 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
} }
} else { } else {
struct acpi_pcct_hw_reduced *cppc_ss; struct acpi_pcct_hw_reduced *cppc_ss;
const struct acpi_device_id *acpi_id;
int version = XGENE_SLIMPRO_I2C_V1;
acpi_id = acpi_match_device(pdev->dev.driver->acpi_match_table,
&pdev->dev);
if (!acpi_id)
return -EINVAL;
version = (int)acpi_id->driver_data;
if (device_property_read_u32(&pdev->dev, "pcc-channel", if (device_property_read_u32(&pdev->dev, "pcc-channel",
&ctx->mbox_idx)) &ctx->mbox_idx))
...@@ -514,9 +528,16 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev) ...@@ -514,9 +528,16 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
*/ */
ctx->comm_base_addr = cppc_ss->base_address; ctx->comm_base_addr = cppc_ss->base_address;
if (ctx->comm_base_addr) { if (ctx->comm_base_addr) {
ctx->pcc_comm_addr = memremap(ctx->comm_base_addr, if (version == XGENE_SLIMPRO_I2C_V2)
cppc_ss->length, ctx->pcc_comm_addr = memremap(
MEMREMAP_WB); ctx->comm_base_addr,
cppc_ss->length,
MEMREMAP_WT);
else
ctx->pcc_comm_addr = memremap(
ctx->comm_base_addr,
cppc_ss->length,
MEMREMAP_WB);
} else { } else {
dev_err(&pdev->dev, "Failed to get PCC comm region\n"); dev_err(&pdev->dev, "Failed to get PCC comm region\n");
rc = -ENOENT; rc = -ENOENT;
...@@ -581,7 +602,8 @@ MODULE_DEVICE_TABLE(of, xgene_slimpro_i2c_dt_ids); ...@@ -581,7 +602,8 @@ MODULE_DEVICE_TABLE(of, xgene_slimpro_i2c_dt_ids);
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
static const struct acpi_device_id xgene_slimpro_i2c_acpi_ids[] = { static const struct acpi_device_id xgene_slimpro_i2c_acpi_ids[] = {
{"APMC0D40", 0}, {"APMC0D40", XGENE_SLIMPRO_I2C_V1},
{"APMC0D8B", XGENE_SLIMPRO_I2C_V2},
{} {}
}; };
MODULE_DEVICE_TABLE(acpi, xgene_slimpro_i2c_acpi_ids); MODULE_DEVICE_TABLE(acpi, xgene_slimpro_i2c_acpi_ids);
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
*/ */
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -81,9 +82,12 @@ struct xlp9xx_i2c_dev { ...@@ -81,9 +82,12 @@ struct xlp9xx_i2c_dev {
struct completion msg_complete; struct completion msg_complete;
int irq; int irq;
bool msg_read; bool msg_read;
bool len_recv;
bool client_pec;
u32 __iomem *base; u32 __iomem *base;
u32 msg_buf_remaining; u32 msg_buf_remaining;
u32 msg_len; u32 msg_len;
u32 ip_clk_hz;
u32 clk_hz; u32 clk_hz;
u32 msg_err; u32 msg_err;
u8 *msg_buf; u8 *msg_buf;
...@@ -141,10 +145,25 @@ static void xlp9xx_i2c_fill_tx_fifo(struct xlp9xx_i2c_dev *priv) ...@@ -141,10 +145,25 @@ static void xlp9xx_i2c_fill_tx_fifo(struct xlp9xx_i2c_dev *priv)
static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv) static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv)
{ {
u32 len, i; u32 len, i;
u8 *buf = priv->msg_buf; u8 rlen, *buf = priv->msg_buf;
len = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_FIFOWCNT) & len = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_FIFOWCNT) &
XLP9XX_I2C_FIFO_WCNT_MASK; XLP9XX_I2C_FIFO_WCNT_MASK;
if (!len)
return;
if (priv->len_recv) {
/* read length byte */
rlen = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO);
*buf++ = rlen;
len--;
if (priv->client_pec)
++rlen;
/* update remaining bytes and message length */
priv->msg_buf_remaining = rlen;
priv->msg_len = rlen + 1;
priv->len_recv = false;
}
len = min(priv->msg_buf_remaining, len); len = min(priv->msg_buf_remaining, len);
for (i = 0; i < len; i++, buf++) for (i = 0; i < len; i++, buf++)
*buf = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO); *buf = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO);
...@@ -213,7 +232,7 @@ static int xlp9xx_i2c_init(struct xlp9xx_i2c_dev *priv) ...@@ -213,7 +232,7 @@ static int xlp9xx_i2c_init(struct xlp9xx_i2c_dev *priv)
* The controller uses 5 * SCL clock internally. * The controller uses 5 * SCL clock internally.
* So prescale value should be divided by 5. * So prescale value should be divided by 5.
*/ */
prescale = DIV_ROUND_UP(XLP9XX_I2C_IP_CLK_FREQ, priv->clk_hz); prescale = DIV_ROUND_UP(priv->ip_clk_hz, priv->clk_hz);
prescale = ((prescale - 8) / 5) - 1; prescale = ((prescale - 8) / 5) - 1;
xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, XLP9XX_I2C_CTRL_RST); xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, XLP9XX_I2C_CTRL_RST);
xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, XLP9XX_I2C_CTRL_EN | xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, XLP9XX_I2C_CTRL_EN |
...@@ -228,7 +247,7 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg, ...@@ -228,7 +247,7 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
int last_msg) int last_msg)
{ {
unsigned long timeleft; unsigned long timeleft;
u32 intr_mask, cmd, val; u32 intr_mask, cmd, val, len;
priv->msg_buf = msg->buf; priv->msg_buf = msg->buf;
priv->msg_buf_remaining = priv->msg_len = msg->len; priv->msg_buf_remaining = priv->msg_len = msg->len;
...@@ -261,9 +280,13 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg, ...@@ -261,9 +280,13 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
else else
val &= ~XLP9XX_I2C_CTRL_ADDMODE; val &= ~XLP9XX_I2C_CTRL_ADDMODE;
priv->len_recv = msg->flags & I2C_M_RECV_LEN;
len = priv->len_recv ? XLP9XX_I2C_FIFO_SIZE : msg->len;
priv->client_pec = msg->flags & I2C_CLIENT_PEC;
/* set data length to be transferred */ /* set data length to be transferred */
val = (val & ~XLP9XX_I2C_CTRL_MCTLEN_MASK) | val = (val & ~XLP9XX_I2C_CTRL_MCTLEN_MASK) |
(msg->len << XLP9XX_I2C_CTRL_MCTLEN_SHIFT); (len << XLP9XX_I2C_CTRL_MCTLEN_SHIFT);
xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, val); xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, val);
/* fill fifo during tx */ /* fill fifo during tx */
...@@ -310,6 +333,9 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg, ...@@ -310,6 +333,9 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
return -ETIMEDOUT; return -ETIMEDOUT;
} }
/* update msg->len with actual received length */
if (msg->flags & I2C_M_RECV_LEN)
msg->len = priv->msg_len;
return 0; return 0;
} }
...@@ -342,9 +368,19 @@ static const struct i2c_algorithm xlp9xx_i2c_algo = { ...@@ -342,9 +368,19 @@ static const struct i2c_algorithm xlp9xx_i2c_algo = {
static int xlp9xx_i2c_get_frequency(struct platform_device *pdev, static int xlp9xx_i2c_get_frequency(struct platform_device *pdev,
struct xlp9xx_i2c_dev *priv) struct xlp9xx_i2c_dev *priv)
{ {
struct clk *clk;
u32 freq; u32 freq;
int err; int err;
clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) {
priv->ip_clk_hz = XLP9XX_I2C_IP_CLK_FREQ;
dev_dbg(&pdev->dev, "using default input frequency %u\n",
priv->ip_clk_hz);
} else {
priv->ip_clk_hz = clk_get_rate(clk);
}
err = device_property_read_u32(&pdev->dev, "clock-frequency", &freq); err = device_property_read_u32(&pdev->dev, "clock-frequency", &freq);
if (err) { if (err) {
freq = XLP9XX_I2C_DEFAULT_FREQ; freq = XLP9XX_I2C_DEFAULT_FREQ;
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-smbus.h>
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/irqflags.h> #include <linux/irqflags.h>
...@@ -205,9 +206,6 @@ static int i2c_generic_recovery(struct i2c_adapter *adap) ...@@ -205,9 +206,6 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)
*/ */
while (i++ < RECOVERY_CLK_CNT * 2) { while (i++ < RECOVERY_CLK_CNT * 2) {
if (val) { if (val) {
/* Break if SDA is high */
if (bri->get_sda && bri->get_sda(adap))
break;
/* SCL shouldn't be low here */ /* SCL shouldn't be low here */
if (!bri->get_scl(adap)) { if (!bri->get_scl(adap)) {
dev_err(&adap->dev, dev_err(&adap->dev,
...@@ -215,6 +213,9 @@ static int i2c_generic_recovery(struct i2c_adapter *adap) ...@@ -215,6 +213,9 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)
ret = -EBUSY; ret = -EBUSY;
break; break;
} }
/* Break if SDA is high */
if (bri->get_sda && bri->get_sda(adap))
break;
} }
val = !val; val = !val;
...@@ -222,6 +223,10 @@ static int i2c_generic_recovery(struct i2c_adapter *adap) ...@@ -222,6 +223,10 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)
ndelay(RECOVERY_NDELAY); ndelay(RECOVERY_NDELAY);
} }
/* check if recovery actually succeeded */
if (bri->get_sda && !bri->get_sda(adap))
ret = -EBUSY;
if (bri->unprepare_recovery) if (bri->unprepare_recovery)
bri->unprepare_recovery(adap); bri->unprepare_recovery(adap);
...@@ -666,10 +671,16 @@ static void i2c_adapter_unlock_bus(struct i2c_adapter *adapter, ...@@ -666,10 +671,16 @@ static void i2c_adapter_unlock_bus(struct i2c_adapter *adapter,
} }
static void i2c_dev_set_name(struct i2c_adapter *adap, static void i2c_dev_set_name(struct i2c_adapter *adap,
struct i2c_client *client) struct i2c_client *client,
struct i2c_board_info const *info)
{ {
struct acpi_device *adev = ACPI_COMPANION(&client->dev); struct acpi_device *adev = ACPI_COMPANION(&client->dev);
if (info && info->dev_name) {
dev_set_name(&client->dev, "i2c-%s", info->dev_name);
return;
}
if (adev) { if (adev) {
dev_set_name(&client->dev, "i2c-%s", acpi_dev_name(adev)); dev_set_name(&client->dev, "i2c-%s", acpi_dev_name(adev));
return; return;
...@@ -766,7 +777,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) ...@@ -766,7 +777,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
client->dev.of_node = info->of_node; client->dev.of_node = info->of_node;
client->dev.fwnode = info->fwnode; client->dev.fwnode = info->fwnode;
i2c_dev_set_name(adap, client); i2c_dev_set_name(adap, client, info);
if (info->properties) { if (info->properties) {
status = device_add_properties(&client->dev, info->properties); status = device_add_properties(&client->dev, info->properties);
...@@ -808,6 +819,8 @@ EXPORT_SYMBOL_GPL(i2c_new_device); ...@@ -808,6 +819,8 @@ EXPORT_SYMBOL_GPL(i2c_new_device);
*/ */
void i2c_unregister_device(struct i2c_client *client) void i2c_unregister_device(struct i2c_client *client)
{ {
if (!client)
return;
if (client->dev.of_node) if (client->dev.of_node)
of_node_clear_flag(client->dev.of_node, OF_POPULATED); of_node_clear_flag(client->dev.of_node, OF_POPULATED);
if (ACPI_COMPANION(&client->dev)) if (ACPI_COMPANION(&client->dev))
...@@ -1259,6 +1272,10 @@ static int i2c_register_adapter(struct i2c_adapter *adap) ...@@ -1259,6 +1272,10 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
goto out_list; goto out_list;
} }
res = of_i2c_setup_smbus_alert(adap);
if (res)
goto out_reg;
dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name); dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
pm_runtime_no_callbacks(&adap->dev); pm_runtime_no_callbacks(&adap->dev);
...@@ -1290,6 +1307,10 @@ static int i2c_register_adapter(struct i2c_adapter *adap) ...@@ -1290,6 +1307,10 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
return 0; return 0;
out_reg:
init_completion(&adap->dev_released);
device_unregister(&adap->dev);
wait_for_completion(&adap->dev_released);
out_list: out_list:
mutex_lock(&core_lock); mutex_lock(&core_lock);
idr_remove(&i2c_adapter_idr, adap->nr); idr_remove(&i2c_adapter_idr, adap->nr);
...@@ -1417,8 +1438,7 @@ static int __unregister_client(struct device *dev, void *dummy) ...@@ -1417,8 +1438,7 @@ static int __unregister_client(struct device *dev, void *dummy)
static int __unregister_dummy(struct device *dev, void *dummy) static int __unregister_dummy(struct device *dev, void *dummy)
{ {
struct i2c_client *client = i2c_verify_client(dev); struct i2c_client *client = i2c_verify_client(dev);
if (client) i2c_unregister_device(client);
i2c_unregister_device(client);
return 0; return 0;
} }
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-smbus.h>
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include <trace/events/smbus.h> #include <trace/events/smbus.h>
...@@ -592,3 +593,57 @@ s32 i2c_smbus_read_i2c_block_data_or_emulated(const struct i2c_client *client, ...@@ -592,3 +593,57 @@ s32 i2c_smbus_read_i2c_block_data_or_emulated(const struct i2c_client *client,
return i; return i;
} }
EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data_or_emulated); EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data_or_emulated);
/**
* i2c_setup_smbus_alert - Setup SMBus alert support
* @adapter: the target adapter
* @setup: setup data for the SMBus alert handler
* Context: can sleep
*
* Setup handling of the SMBus alert protocol on a given I2C bus segment.
*
* Handling can be done either through our IRQ handler, or by the
* adapter (from its handler, periodic polling, or whatever).
*
* NOTE that if we manage the IRQ, we *MUST* know if it's level or
* edge triggered in order to hand it to the workqueue correctly.
* If triggering the alert seems to wedge the system, you probably
* should have said it's level triggered.
*
* This returns the ara client, which should be saved for later use with
* i2c_handle_smbus_alert() and ultimately i2c_unregister_device(); or NULL
* to indicate an error.
*/
struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter,
struct i2c_smbus_alert_setup *setup)
{
struct i2c_board_info ara_board_info = {
I2C_BOARD_INFO("smbus_alert", 0x0c),
.platform_data = setup,
};
return i2c_new_device(adapter, &ara_board_info);
}
EXPORT_SYMBOL_GPL(i2c_setup_smbus_alert);
#if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_OF)
int of_i2c_setup_smbus_alert(struct i2c_adapter *adapter)
{
struct i2c_client *client;
int irq;
irq = of_property_match_string(adapter->dev.of_node, "interrupt-names",
"smbus_alert");
if (irq == -EINVAL || irq == -ENODATA)
return 0;
else if (irq < 0)
return irq;
client = i2c_setup_smbus_alert(adapter, NULL);
if (!client)
return -ENODEV;
return 0;
}
EXPORT_SYMBOL_GPL(of_i2c_setup_smbus_alert);
#endif
...@@ -21,12 +21,11 @@ ...@@ -21,12 +21,11 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_irq.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
struct i2c_smbus_alert { struct i2c_smbus_alert {
unsigned int alert_edge_triggered:1;
int irq;
struct work_struct alert; struct work_struct alert;
struct i2c_client *ara; /* Alert response address */ struct i2c_client *ara; /* Alert response address */
}; };
...@@ -72,13 +71,12 @@ static int smbus_do_alert(struct device *dev, void *addrp) ...@@ -72,13 +71,12 @@ static int smbus_do_alert(struct device *dev, void *addrp)
* The alert IRQ handler needs to hand work off to a task which can issue * The alert IRQ handler needs to hand work off to a task which can issue
* SMBus calls, because those sleeping calls can't be made in IRQ context. * SMBus calls, because those sleeping calls can't be made in IRQ context.
*/ */
static void smbus_alert(struct work_struct *work) static irqreturn_t smbus_alert(int irq, void *d)
{ {
struct i2c_smbus_alert *alert; struct i2c_smbus_alert *alert = d;
struct i2c_client *ara; struct i2c_client *ara;
unsigned short prev_addr = 0; /* Not a valid address */ unsigned short prev_addr = 0; /* Not a valid address */
alert = container_of(work, struct i2c_smbus_alert, alert);
ara = alert->ara; ara = alert->ara;
for (;;) { for (;;) {
...@@ -115,21 +113,17 @@ static void smbus_alert(struct work_struct *work) ...@@ -115,21 +113,17 @@ static void smbus_alert(struct work_struct *work)
prev_addr = data.addr; prev_addr = data.addr;
} }
/* We handled all alerts; re-enable level-triggered IRQs */ return IRQ_HANDLED;
if (!alert->alert_edge_triggered)
enable_irq(alert->irq);
} }
static irqreturn_t smbalert_irq(int irq, void *d) static void smbalert_work(struct work_struct *work)
{ {
struct i2c_smbus_alert *alert = d; struct i2c_smbus_alert *alert;
/* Disable level-triggered IRQs until we handle them */ alert = container_of(work, struct i2c_smbus_alert, alert);
if (!alert->alert_edge_triggered)
disable_irq_nosync(irq); smbus_alert(0, alert);
schedule_work(&alert->alert);
return IRQ_HANDLED;
} }
/* Setup SMBALERT# infrastructure */ /* Setup SMBALERT# infrastructure */
...@@ -139,28 +133,35 @@ static int smbalert_probe(struct i2c_client *ara, ...@@ -139,28 +133,35 @@ static int smbalert_probe(struct i2c_client *ara,
struct i2c_smbus_alert_setup *setup = dev_get_platdata(&ara->dev); struct i2c_smbus_alert_setup *setup = dev_get_platdata(&ara->dev);
struct i2c_smbus_alert *alert; struct i2c_smbus_alert *alert;
struct i2c_adapter *adapter = ara->adapter; struct i2c_adapter *adapter = ara->adapter;
int res; int res, irq;
alert = devm_kzalloc(&ara->dev, sizeof(struct i2c_smbus_alert), alert = devm_kzalloc(&ara->dev, sizeof(struct i2c_smbus_alert),
GFP_KERNEL); GFP_KERNEL);
if (!alert) if (!alert)
return -ENOMEM; return -ENOMEM;
alert->alert_edge_triggered = setup->alert_edge_triggered; if (setup) {
alert->irq = setup->irq; irq = setup->irq;
INIT_WORK(&alert->alert, smbus_alert); } else {
irq = of_irq_get_byname(adapter->dev.of_node, "smbus_alert");
if (irq <= 0)
return irq;
}
INIT_WORK(&alert->alert, smbalert_work);
alert->ara = ara; alert->ara = ara;
if (setup->irq > 0) { if (irq > 0) {
res = devm_request_irq(&ara->dev, setup->irq, smbalert_irq, res = devm_request_threaded_irq(&ara->dev, irq,
0, "smbus_alert", alert); NULL, smbus_alert,
IRQF_SHARED | IRQF_ONESHOT,
"smbus_alert", alert);
if (res) if (res)
return res; return res;
} }
i2c_set_clientdata(ara, alert); i2c_set_clientdata(ara, alert);
dev_info(&adapter->dev, "supports SMBALERT#, %s trigger\n", dev_info(&adapter->dev, "supports SMBALERT#\n");
setup->alert_edge_triggered ? "edge" : "level");
return 0; return 0;
} }
...@@ -189,38 +190,6 @@ static struct i2c_driver smbalert_driver = { ...@@ -189,38 +190,6 @@ static struct i2c_driver smbalert_driver = {
.id_table = smbalert_ids, .id_table = smbalert_ids,
}; };
/**
* i2c_setup_smbus_alert - Setup SMBus alert support
* @adapter: the target adapter
* @setup: setup data for the SMBus alert handler
* Context: can sleep
*
* Setup handling of the SMBus alert protocol on a given I2C bus segment.
*
* Handling can be done either through our IRQ handler, or by the
* adapter (from its handler, periodic polling, or whatever).
*
* NOTE that if we manage the IRQ, we *MUST* know if it's level or
* edge triggered in order to hand it to the workqueue correctly.
* If triggering the alert seems to wedge the system, you probably
* should have said it's level triggered.
*
* This returns the ara client, which should be saved for later use with
* i2c_handle_smbus_alert() and ultimately i2c_unregister_device(); or NULL
* to indicate an error.
*/
struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter,
struct i2c_smbus_alert_setup *setup)
{
struct i2c_board_info ara_board_info = {
I2C_BOARD_INFO("smbus_alert", 0x0c),
.platform_data = setup,
};
return i2c_new_device(adapter, &ara_board_info);
}
EXPORT_SYMBOL_GPL(i2c_setup_smbus_alert);
/** /**
* i2c_handle_smbus_alert - Handle an SMBus alert * i2c_handle_smbus_alert - Handle an SMBus alert
* @ara: the ARA client on the relevant adapter * @ara: the ARA client on the relevant adapter
......
...@@ -246,36 +246,6 @@ static irqreturn_t pca954x_irq_handler(int irq, void *dev_id) ...@@ -246,36 +246,6 @@ static irqreturn_t pca954x_irq_handler(int irq, void *dev_id)
return handled ? IRQ_HANDLED : IRQ_NONE; return handled ? IRQ_HANDLED : IRQ_NONE;
} }
static void pca954x_irq_mask(struct irq_data *idata)
{
struct pca954x *data = irq_data_get_irq_chip_data(idata);
unsigned int pos = idata->hwirq;
unsigned long flags;
raw_spin_lock_irqsave(&data->lock, flags);
data->irq_mask &= ~BIT(pos);
if (!data->irq_mask)
disable_irq(data->client->irq);
raw_spin_unlock_irqrestore(&data->lock, flags);
}
static void pca954x_irq_unmask(struct irq_data *idata)
{
struct pca954x *data = irq_data_get_irq_chip_data(idata);
unsigned int pos = idata->hwirq;
unsigned long flags;
raw_spin_lock_irqsave(&data->lock, flags);
if (!data->irq_mask)
enable_irq(data->client->irq);
data->irq_mask |= BIT(pos);
raw_spin_unlock_irqrestore(&data->lock, flags);
}
static int pca954x_irq_set_type(struct irq_data *idata, unsigned int type) static int pca954x_irq_set_type(struct irq_data *idata, unsigned int type)
{ {
if ((type & IRQ_TYPE_SENSE_MASK) != IRQ_TYPE_LEVEL_LOW) if ((type & IRQ_TYPE_SENSE_MASK) != IRQ_TYPE_LEVEL_LOW)
...@@ -285,8 +255,6 @@ static int pca954x_irq_set_type(struct irq_data *idata, unsigned int type) ...@@ -285,8 +255,6 @@ static int pca954x_irq_set_type(struct irq_data *idata, unsigned int type)
static struct irq_chip pca954x_irq_chip = { static struct irq_chip pca954x_irq_chip = {
.name = "i2c-mux-pca954x", .name = "i2c-mux-pca954x",
.irq_mask = pca954x_irq_mask,
.irq_unmask = pca954x_irq_unmask,
.irq_set_type = pca954x_irq_set_type, .irq_set_type = pca954x_irq_set_type,
}; };
...@@ -294,7 +262,7 @@ static int pca954x_irq_setup(struct i2c_mux_core *muxc) ...@@ -294,7 +262,7 @@ static int pca954x_irq_setup(struct i2c_mux_core *muxc)
{ {
struct pca954x *data = i2c_mux_priv(muxc); struct pca954x *data = i2c_mux_priv(muxc);
struct i2c_client *client = data->client; struct i2c_client *client = data->client;
int c, err, irq; int c, irq;
if (!data->chip->has_irq || client->irq <= 0) if (!data->chip->has_irq || client->irq <= 0)
return 0; return 0;
...@@ -309,29 +277,31 @@ static int pca954x_irq_setup(struct i2c_mux_core *muxc) ...@@ -309,29 +277,31 @@ static int pca954x_irq_setup(struct i2c_mux_core *muxc)
for (c = 0; c < data->chip->nchans; c++) { for (c = 0; c < data->chip->nchans; c++) {
irq = irq_create_mapping(data->irq, c); irq = irq_create_mapping(data->irq, c);
if (!irq) {
dev_err(&client->dev, "failed irq create map\n");
return -EINVAL;
}
irq_set_chip_data(irq, data); irq_set_chip_data(irq, data);
irq_set_chip_and_handler(irq, &pca954x_irq_chip, irq_set_chip_and_handler(irq, &pca954x_irq_chip,
handle_simple_irq); handle_simple_irq);
} }
err = devm_request_threaded_irq(&client->dev, data->client->irq, NULL, return 0;
pca954x_irq_handler, }
IRQF_ONESHOT | IRQF_SHARED,
"pca954x", data);
if (err)
goto err_req_irq;
disable_irq(data->client->irq); static void pca954x_cleanup(struct i2c_mux_core *muxc)
{
struct pca954x *data = i2c_mux_priv(muxc);
int c, irq;
return 0; if (data->irq) {
err_req_irq: for (c = 0; c < data->chip->nchans; c++) {
for (c = 0; c < data->chip->nchans; c++) { irq = irq_find_mapping(data->irq, c);
irq = irq_find_mapping(data->irq, c); irq_dispose_mapping(irq);
irq_dispose_mapping(irq); }
irq_domain_remove(data->irq);
} }
irq_domain_remove(data->irq); i2c_mux_del_adapters(muxc);
return err;
} }
/* /*
...@@ -391,7 +361,7 @@ static int pca954x_probe(struct i2c_client *client, ...@@ -391,7 +361,7 @@ static int pca954x_probe(struct i2c_client *client,
ret = pca954x_irq_setup(muxc); ret = pca954x_irq_setup(muxc);
if (ret) if (ret)
goto fail_del_adapters; goto fail_cleanup;
/* Now create an adapter for each channel */ /* Now create an adapter for each channel */
for (num = 0; num < data->chip->nchans; num++) { for (num = 0; num < data->chip->nchans; num++) {
...@@ -414,7 +384,16 @@ static int pca954x_probe(struct i2c_client *client, ...@@ -414,7 +384,16 @@ static int pca954x_probe(struct i2c_client *client,
ret = i2c_mux_add_adapter(muxc, force, num, class); ret = i2c_mux_add_adapter(muxc, force, num, class);
if (ret) if (ret)
goto fail_del_adapters; goto fail_cleanup;
}
if (data->irq) {
ret = devm_request_threaded_irq(&client->dev, data->client->irq,
NULL, pca954x_irq_handler,
IRQF_ONESHOT | IRQF_SHARED,
"pca954x", data);
if (ret)
goto fail_cleanup;
} }
dev_info(&client->dev, dev_info(&client->dev,
...@@ -424,26 +403,16 @@ static int pca954x_probe(struct i2c_client *client, ...@@ -424,26 +403,16 @@ static int pca954x_probe(struct i2c_client *client,
return 0; return 0;
fail_del_adapters: fail_cleanup:
i2c_mux_del_adapters(muxc); pca954x_cleanup(muxc);
return ret; return ret;
} }
static int pca954x_remove(struct i2c_client *client) static int pca954x_remove(struct i2c_client *client)
{ {
struct i2c_mux_core *muxc = i2c_get_clientdata(client); struct i2c_mux_core *muxc = i2c_get_clientdata(client);
struct pca954x *data = i2c_mux_priv(muxc);
int c, irq;
if (data->irq) { pca954x_cleanup(muxc);
for (c = 0; c < data->chip->nchans; c++) {
irq = irq_find_mapping(data->irq, c);
irq_dispose_mapping(irq);
}
irq_domain_remove(data->irq);
}
i2c_mux_del_adapters(muxc);
return 0; return 0;
} }
......
...@@ -107,9 +107,9 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux, ...@@ -107,9 +107,9 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
put_device(&adapter->dev); put_device(&adapter->dev);
mux->data.n_values = of_get_child_count(np); mux->data.n_values = of_get_child_count(np);
if (of_find_property(np, "little-endian", NULL)) { if (of_property_read_bool(np, "little-endian")) {
mux->data.little_endian = true; mux->data.little_endian = true;
} else if (of_find_property(np, "big-endian", NULL)) { } else if (of_property_read_bool(np, "big-endian")) {
mux->data.little_endian = false; mux->data.little_endian = false;
} else { } else {
#if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : \ #if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : \
...@@ -122,10 +122,7 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux, ...@@ -122,10 +122,7 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
#error Endianness not defined? #error Endianness not defined?
#endif #endif
} }
if (of_find_property(np, "write-only", NULL)) mux->data.write_only = of_property_read_bool(np, "write-only");
mux->data.write_only = true;
else
mux->data.write_only = false;
values = devm_kzalloc(&pdev->dev, values = devm_kzalloc(&pdev->dev,
sizeof(*mux->data.values) * mux->data.n_values, sizeof(*mux->data.values) * mux->data.n_values,
......
...@@ -38,12 +38,7 @@ int intel_lpss_resume(struct device *dev); ...@@ -38,12 +38,7 @@ int intel_lpss_resume(struct device *dev);
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
#define INTEL_LPSS_SLEEP_PM_OPS \ #define INTEL_LPSS_SLEEP_PM_OPS \
.prepare = intel_lpss_prepare, \ .prepare = intel_lpss_prepare, \
.suspend = intel_lpss_suspend, \ SET_LATE_SYSTEM_SLEEP_PM_OPS(intel_lpss_suspend, intel_lpss_resume)
.resume = intel_lpss_resume, \
.freeze = intel_lpss_suspend, \
.thaw = intel_lpss_resume, \
.poweroff = intel_lpss_suspend, \
.restore = intel_lpss_resume,
#else #else
#define INTEL_LPSS_SLEEP_PM_OPS #define INTEL_LPSS_SLEEP_PM_OPS
#endif #endif
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/i2c-gpio.h> #include <linux/i2c-gpio.h>
#include <linux/gpio/machine.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/sm501.h> #include <linux/sm501.h>
...@@ -1107,14 +1108,6 @@ static void sm501_gpio_remove(struct sm501_devdata *sm) ...@@ -1107,14 +1108,6 @@ static void sm501_gpio_remove(struct sm501_devdata *sm)
kfree(gpio->regs_res); kfree(gpio->regs_res);
} }
static inline int sm501_gpio_pin2nr(struct sm501_devdata *sm, unsigned int pin)
{
struct sm501_gpio *gpio = &sm->gpio;
int base = (pin < 32) ? gpio->low.gpio.base : gpio->high.gpio.base;
return (pin % 32) + base;
}
static inline int sm501_gpio_isregistered(struct sm501_devdata *sm) static inline int sm501_gpio_isregistered(struct sm501_devdata *sm)
{ {
return sm->gpio.registered; return sm->gpio.registered;
...@@ -1129,11 +1122,6 @@ static inline void sm501_gpio_remove(struct sm501_devdata *sm) ...@@ -1129,11 +1122,6 @@ static inline void sm501_gpio_remove(struct sm501_devdata *sm)
{ {
} }
static inline int sm501_gpio_pin2nr(struct sm501_devdata *sm, unsigned int pin)
{
return -1;
}
static inline int sm501_gpio_isregistered(struct sm501_devdata *sm) static inline int sm501_gpio_isregistered(struct sm501_devdata *sm)
{ {
return 0; return 0;
...@@ -1145,20 +1133,37 @@ static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm, ...@@ -1145,20 +1133,37 @@ static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm,
{ {
struct i2c_gpio_platform_data *icd; struct i2c_gpio_platform_data *icd;
struct platform_device *pdev; struct platform_device *pdev;
struct gpiod_lookup_table *lookup;
pdev = sm501_create_subdev(sm, "i2c-gpio", 0, pdev = sm501_create_subdev(sm, "i2c-gpio", 0,
sizeof(struct i2c_gpio_platform_data)); sizeof(struct i2c_gpio_platform_data));
if (!pdev) if (!pdev)
return -ENOMEM; return -ENOMEM;
icd = dev_get_platdata(&pdev->dev); /* Create a gpiod lookup using gpiochip-local offsets */
lookup = devm_kzalloc(&pdev->dev,
/* We keep the pin_sda and pin_scl fields relative in case the sizeof(*lookup) + 3 * sizeof(struct gpiod_lookup),
* same platform data is passed to >1 SM501. GFP_KERNEL);
*/ lookup->dev_id = "i2c-gpio";
if (iic->pin_sda < 32)
lookup->table[0].chip_label = "SM501-LOW";
else
lookup->table[0].chip_label = "SM501-HIGH";
lookup->table[0].chip_hwnum = iic->pin_sda % 32;
lookup->table[0].con_id = NULL;
lookup->table[0].idx = 0;
lookup->table[0].flags = GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN;
if (iic->pin_scl < 32)
lookup->table[1].chip_label = "SM501-LOW";
else
lookup->table[1].chip_label = "SM501-HIGH";
lookup->table[1].chip_hwnum = iic->pin_scl % 32;
lookup->table[1].con_id = NULL;
lookup->table[1].idx = 1;
lookup->table[1].flags = GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN;
gpiod_add_lookup_table(lookup);
icd->sda_pin = sm501_gpio_pin2nr(sm, iic->pin_sda); icd = dev_get_platdata(&pdev->dev);
icd->scl_pin = sm501_gpio_pin2nr(sm, iic->pin_scl);
icd->timeout = iic->timeout; icd->timeout = iic->timeout;
icd->udelay = iic->udelay; icd->udelay = iic->udelay;
...@@ -1170,9 +1175,9 @@ static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm, ...@@ -1170,9 +1175,9 @@ static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm,
pdev->id = iic->bus_num; pdev->id = iic->bus_num;
dev_info(sm->dev, "registering i2c-%d: sda=%d (%d), scl=%d (%d)\n", dev_info(sm->dev, "registering i2c-%d: sda=%d, scl=%d\n",
iic->bus_num, iic->bus_num,
icd->sda_pin, iic->pin_sda, icd->scl_pin, iic->pin_scl); iic->pin_sda, iic->pin_scl);
return sm501_register_device(sm, pdev); return sm501_register_device(sm, pdev);
} }
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mutex.h> #include <linux/mutex.h>
...@@ -24,6 +25,7 @@ ...@@ -24,6 +25,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/nvmem-provider.h> #include <linux/nvmem-provider.h>
#include <linux/platform_data/at24.h> #include <linux/platform_data/at24.h>
#include <linux/pm_runtime.h>
/* /*
* I2C EEPROMs from most vendors are inexpensive and mostly interchangeable. * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable.
...@@ -175,6 +177,64 @@ static const struct i2c_device_id at24_ids[] = { ...@@ -175,6 +177,64 @@ static const struct i2c_device_id at24_ids[] = {
}; };
MODULE_DEVICE_TABLE(i2c, at24_ids); MODULE_DEVICE_TABLE(i2c, at24_ids);
static const struct of_device_id at24_of_match[] = {
{
.compatible = "atmel,24c00",
.data = (void *)AT24_DEVICE_MAGIC(128 / 8, AT24_FLAG_TAKE8ADDR)
},
{
.compatible = "atmel,24c01",
.data = (void *)AT24_DEVICE_MAGIC(1024 / 8, 0)
},
{
.compatible = "atmel,24c02",
.data = (void *)AT24_DEVICE_MAGIC(2048 / 8, 0)
},
{
.compatible = "atmel,spd",
.data = (void *)AT24_DEVICE_MAGIC(2048 / 8,
AT24_FLAG_READONLY | AT24_FLAG_IRUGO)
},
{
.compatible = "atmel,24c04",
.data = (void *)AT24_DEVICE_MAGIC(4096 / 8, 0)
},
{
.compatible = "atmel,24c08",
.data = (void *)AT24_DEVICE_MAGIC(8192 / 8, 0)
},
{
.compatible = "atmel,24c16",
.data = (void *)AT24_DEVICE_MAGIC(16384 / 8, 0)
},
{
.compatible = "atmel,24c32",
.data = (void *)AT24_DEVICE_MAGIC(32768 / 8, AT24_FLAG_ADDR16)
},
{
.compatible = "atmel,24c64",
.data = (void *)AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16)
},
{
.compatible = "atmel,24c128",
.data = (void *)AT24_DEVICE_MAGIC(131072 / 8, AT24_FLAG_ADDR16)
},
{
.compatible = "atmel,24c256",
.data = (void *)AT24_DEVICE_MAGIC(262144 / 8, AT24_FLAG_ADDR16)
},
{
.compatible = "atmel,24c512",
.data = (void *)AT24_DEVICE_MAGIC(524288 / 8, AT24_FLAG_ADDR16)
},
{
.compatible = "atmel,24c1024",
.data = (void *)AT24_DEVICE_MAGIC(1048576 / 8, AT24_FLAG_ADDR16)
},
{ },
};
MODULE_DEVICE_TABLE(of, at24_of_match);
static const struct acpi_device_id at24_acpi_ids[] = { static const struct acpi_device_id at24_acpi_ids[] = {
{ "INT3499", AT24_DEVICE_MAGIC(8192 / 8, 0) }, { "INT3499", AT24_DEVICE_MAGIC(8192 / 8, 0) },
{ } { }
...@@ -501,11 +561,21 @@ static ssize_t at24_eeprom_write_i2c(struct at24_data *at24, const char *buf, ...@@ -501,11 +561,21 @@ static ssize_t at24_eeprom_write_i2c(struct at24_data *at24, const char *buf,
static int at24_read(void *priv, unsigned int off, void *val, size_t count) static int at24_read(void *priv, unsigned int off, void *val, size_t count)
{ {
struct at24_data *at24 = priv; struct at24_data *at24 = priv;
struct i2c_client *client;
char *buf = val; char *buf = val;
int ret;
if (unlikely(!count)) if (unlikely(!count))
return count; return count;
client = at24_translate_offset(at24, &off);
ret = pm_runtime_get_sync(&client->dev);
if (ret < 0) {
pm_runtime_put_noidle(&client->dev);
return ret;
}
/* /*
* Read data from chip, protecting against concurrent updates * Read data from chip, protecting against concurrent updates
* from this host, but not from other I2C masters. * from this host, but not from other I2C masters.
...@@ -518,6 +588,7 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count) ...@@ -518,6 +588,7 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count)
status = at24->read_func(at24, buf, off, count); status = at24->read_func(at24, buf, off, count);
if (status < 0) { if (status < 0) {
mutex_unlock(&at24->lock); mutex_unlock(&at24->lock);
pm_runtime_put(&client->dev);
return status; return status;
} }
buf += status; buf += status;
...@@ -527,17 +598,29 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count) ...@@ -527,17 +598,29 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count)
mutex_unlock(&at24->lock); mutex_unlock(&at24->lock);
pm_runtime_put(&client->dev);
return 0; return 0;
} }
static int at24_write(void *priv, unsigned int off, void *val, size_t count) static int at24_write(void *priv, unsigned int off, void *val, size_t count)
{ {
struct at24_data *at24 = priv; struct at24_data *at24 = priv;
struct i2c_client *client;
char *buf = val; char *buf = val;
int ret;
if (unlikely(!count)) if (unlikely(!count))
return -EINVAL; return -EINVAL;
client = at24_translate_offset(at24, &off);
ret = pm_runtime_get_sync(&client->dev);
if (ret < 0) {
pm_runtime_put_noidle(&client->dev);
return ret;
}
/* /*
* Write data to chip, protecting against concurrent updates * Write data to chip, protecting against concurrent updates
* from this host, but not from other I2C masters. * from this host, but not from other I2C masters.
...@@ -550,6 +633,7 @@ static int at24_write(void *priv, unsigned int off, void *val, size_t count) ...@@ -550,6 +633,7 @@ static int at24_write(void *priv, unsigned int off, void *val, size_t count)
status = at24->write_func(at24, buf, off, count); status = at24->write_func(at24, buf, off, count);
if (status < 0) { if (status < 0) {
mutex_unlock(&at24->lock); mutex_unlock(&at24->lock);
pm_runtime_put(&client->dev);
return status; return status;
} }
buf += status; buf += status;
...@@ -559,6 +643,8 @@ static int at24_write(void *priv, unsigned int off, void *val, size_t count) ...@@ -559,6 +643,8 @@ static int at24_write(void *priv, unsigned int off, void *val, size_t count)
mutex_unlock(&at24->lock); mutex_unlock(&at24->lock);
pm_runtime_put(&client->dev);
return 0; return 0;
} }
...@@ -570,6 +656,10 @@ static void at24_get_pdata(struct device *dev, struct at24_platform_data *chip) ...@@ -570,6 +656,10 @@ static void at24_get_pdata(struct device *dev, struct at24_platform_data *chip)
if (device_property_present(dev, "read-only")) if (device_property_present(dev, "read-only"))
chip->flags |= AT24_FLAG_READONLY; chip->flags |= AT24_FLAG_READONLY;
err = device_property_read_u32(dev, "size", &val);
if (!err)
chip->byte_len = val;
err = device_property_read_u32(dev, "pagesize", &val); err = device_property_read_u32(dev, "pagesize", &val);
if (!err) { if (!err) {
chip->page_size = val; chip->page_size = val;
...@@ -598,7 +688,16 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -598,7 +688,16 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
if (client->dev.platform_data) { if (client->dev.platform_data) {
chip = *(struct at24_platform_data *)client->dev.platform_data; chip = *(struct at24_platform_data *)client->dev.platform_data;
} else { } else {
if (id) { /*
* The I2C core allows OF nodes compatibles to match against the
* I2C device ID table as a fallback, so check not only if an OF
* node is present but also if it matches an OF device ID entry.
*/
if (client->dev.of_node &&
of_match_device(at24_of_match, &client->dev)) {
magic = (kernel_ulong_t)
of_device_get_match_data(&client->dev);
} else if (id) {
magic = id->driver_data; magic = id->driver_data;
} else { } else {
const struct acpi_device_id *aid; const struct acpi_device_id *aid;
...@@ -739,11 +838,16 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -739,11 +838,16 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
i2c_set_clientdata(client, at24); i2c_set_clientdata(client, at24);
/* enable runtime pm */
pm_runtime_set_active(&client->dev);
pm_runtime_enable(&client->dev);
/* /*
* Perform a one-byte test read to verify that the * Perform a one-byte test read to verify that the
* chip is functional. * chip is functional.
*/ */
err = at24_read(at24, 0, &test_byte, 1); err = at24_read(at24, 0, &test_byte, 1);
pm_runtime_idle(&client->dev);
if (err) { if (err) {
err = -ENODEV; err = -ENODEV;
goto err_clients; goto err_clients;
...@@ -791,6 +895,8 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -791,6 +895,8 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
if (at24->client[i]) if (at24->client[i])
i2c_unregister_device(at24->client[i]); i2c_unregister_device(at24->client[i]);
pm_runtime_disable(&client->dev);
return err; return err;
} }
...@@ -806,6 +912,9 @@ static int at24_remove(struct i2c_client *client) ...@@ -806,6 +912,9 @@ static int at24_remove(struct i2c_client *client)
for (i = 1; i < at24->num_addresses; i++) for (i = 1; i < at24->num_addresses; i++)
i2c_unregister_device(at24->client[i]); i2c_unregister_device(at24->client[i]);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
return 0; return 0;
} }
...@@ -814,6 +923,7 @@ static int at24_remove(struct i2c_client *client) ...@@ -814,6 +923,7 @@ static int at24_remove(struct i2c_client *client)
static struct i2c_driver at24_driver = { static struct i2c_driver at24_driver = {
.driver = { .driver = {
.name = "at24", .name = "at24",
.of_match_table = at24_of_match,
.acpi_match_table = ACPI_PTR(at24_acpi_ids), .acpi_match_table = ACPI_PTR(at24_acpi_ids),
}, },
.probe = at24_probe, .probe = at24_probe,
......
...@@ -184,6 +184,20 @@ config CHARGER_SBS ...@@ -184,6 +184,20 @@ config CHARGER_SBS
help help
Say Y to include support for SBS compilant battery chargers. Say Y to include support for SBS compilant battery chargers.
config MANAGER_SBS
tristate "Smart Battery System Manager"
depends on I2C && I2C_MUX && GPIOLIB
select I2C_SMBUS
help
Say Y here to include support for Smart Battery System Manager
ICs. The driver reports online and charging status via sysfs.
It presents itself also as I2C mux which allows to bind
smart battery driver to its ports.
Supported is for example LTC1760.
This driver can also be built as a module. If so, the module will be
called sbs-manager.
config BATTERY_BQ27XXX config BATTERY_BQ27XXX
tristate "BQ27xxx battery driver" tristate "BQ27xxx battery driver"
help help
......
...@@ -37,6 +37,7 @@ obj-$(CONFIG_BATTERY_IPAQ_MICRO) += ipaq_micro_battery.o ...@@ -37,6 +37,7 @@ obj-$(CONFIG_BATTERY_IPAQ_MICRO) += ipaq_micro_battery.o
obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o
obj-$(CONFIG_BATTERY_SBS) += sbs-battery.o obj-$(CONFIG_BATTERY_SBS) += sbs-battery.o
obj-$(CONFIG_CHARGER_SBS) += sbs-charger.o obj-$(CONFIG_CHARGER_SBS) += sbs-charger.o
obj-$(CONFIG_MANAGER_SBS) += sbs-manager.o
obj-$(CONFIG_BATTERY_BQ27XXX) += bq27xxx_battery.o obj-$(CONFIG_BATTERY_BQ27XXX) += bq27xxx_battery.o
obj-$(CONFIG_BATTERY_BQ27XXX_I2C) += bq27xxx_battery_i2c.o obj-$(CONFIG_BATTERY_BQ27XXX_I2C) += bq27xxx_battery_i2c.o
obj-$(CONFIG_BATTERY_BQ27XXX_HDQ) += bq27xxx_battery_hdq.o obj-$(CONFIG_BATTERY_BQ27XXX_HDQ) += bq27xxx_battery_hdq.o
......
...@@ -177,10 +177,8 @@ static bool force_load; ...@@ -177,10 +177,8 @@ static bool force_load;
static int sbs_read_word_data(struct i2c_client *client, u8 address) static int sbs_read_word_data(struct i2c_client *client, u8 address)
{ {
struct sbs_info *chip = i2c_get_clientdata(client); struct sbs_info *chip = i2c_get_clientdata(client);
int retries = chip->i2c_retry_count;
s32 ret = 0; s32 ret = 0;
int retries = 1;
retries = chip->i2c_retry_count;
while (retries > 0) { while (retries > 0) {
ret = i2c_smbus_read_word_data(client, address); ret = i2c_smbus_read_word_data(client, address);
...@@ -204,7 +202,7 @@ static int sbs_read_string_data(struct i2c_client *client, u8 address, ...@@ -204,7 +202,7 @@ static int sbs_read_string_data(struct i2c_client *client, u8 address,
{ {
struct sbs_info *chip = i2c_get_clientdata(client); struct sbs_info *chip = i2c_get_clientdata(client);
s32 ret = 0, block_length = 0; s32 ret = 0, block_length = 0;
int retries_length = 1, retries_block = 1; int retries_length, retries_block;
u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1]; u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1];
retries_length = chip->i2c_retry_count; retries_length = chip->i2c_retry_count;
...@@ -269,10 +267,8 @@ static int sbs_write_word_data(struct i2c_client *client, u8 address, ...@@ -269,10 +267,8 @@ static int sbs_write_word_data(struct i2c_client *client, u8 address,
u16 value) u16 value)
{ {
struct sbs_info *chip = i2c_get_clientdata(client); struct sbs_info *chip = i2c_get_clientdata(client);
int retries = chip->i2c_retry_count;
s32 ret = 0; s32 ret = 0;
int retries = 1;
retries = chip->i2c_retry_count;
while (retries > 0) { while (retries > 0) {
ret = i2c_smbus_write_word_data(client, address, value); ret = i2c_smbus_write_word_data(client, address, value);
...@@ -321,16 +317,6 @@ static int sbs_get_battery_presence_and_health( ...@@ -321,16 +317,6 @@ static int sbs_get_battery_presence_and_health(
union power_supply_propval *val) union power_supply_propval *val)
{ {
s32 ret; s32 ret;
struct sbs_info *chip = i2c_get_clientdata(client);
if (psp == POWER_SUPPLY_PROP_PRESENT && chip->gpio_detect) {
ret = gpiod_get_value_cansleep(chip->gpio_detect);
if (ret < 0)
return ret;
val->intval = ret;
chip->is_present = val->intval;
return ret;
}
/* /*
* Write to ManufacturerAccess with ManufacturerAccess command * Write to ManufacturerAccess with ManufacturerAccess command
...@@ -570,7 +556,7 @@ static int sbs_get_battery_serial_number(struct i2c_client *client, ...@@ -570,7 +556,7 @@ static int sbs_get_battery_serial_number(struct i2c_client *client,
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = sprintf(sbs_serial, "%04x", ret); sprintf(sbs_serial, "%04x", ret);
val->strval = sbs_serial; val->strval = sbs_serial;
return 0; return 0;
...@@ -598,6 +584,19 @@ static int sbs_get_property(struct power_supply *psy, ...@@ -598,6 +584,19 @@ static int sbs_get_property(struct power_supply *psy,
struct sbs_info *chip = power_supply_get_drvdata(psy); struct sbs_info *chip = power_supply_get_drvdata(psy);
struct i2c_client *client = chip->client; struct i2c_client *client = chip->client;
if (chip->gpio_detect) {
ret = gpiod_get_value_cansleep(chip->gpio_detect);
if (ret < 0)
return ret;
if (psp == POWER_SUPPLY_PROP_PRESENT) {
val->intval = ret;
chip->is_present = val->intval;
return 0;
}
if (ret == 0)
return -ENODATA;
}
switch (psp) { switch (psp) {
case POWER_SUPPLY_PROP_PRESENT: case POWER_SUPPLY_PROP_PRESENT:
case POWER_SUPPLY_PROP_HEALTH: case POWER_SUPPLY_PROP_HEALTH:
......
This diff is collapsed.
...@@ -29,6 +29,7 @@ struct gpio_descs { ...@@ -29,6 +29,7 @@ struct gpio_descs {
#define GPIOD_FLAGS_BIT_DIR_SET BIT(0) #define GPIOD_FLAGS_BIT_DIR_SET BIT(0)
#define GPIOD_FLAGS_BIT_DIR_OUT BIT(1) #define GPIOD_FLAGS_BIT_DIR_OUT BIT(1)
#define GPIOD_FLAGS_BIT_DIR_VAL BIT(2) #define GPIOD_FLAGS_BIT_DIR_VAL BIT(2)
#define GPIOD_FLAGS_BIT_OPEN_DRAIN BIT(3)
/** /**
* Optional flags that can be passed to one of gpiod_* to configure direction * Optional flags that can be passed to one of gpiod_* to configure direction
...@@ -40,6 +41,11 @@ enum gpiod_flags { ...@@ -40,6 +41,11 @@ enum gpiod_flags {
GPIOD_OUT_LOW = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT, GPIOD_OUT_LOW = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT,
GPIOD_OUT_HIGH = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT | GPIOD_OUT_HIGH = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT |
GPIOD_FLAGS_BIT_DIR_VAL, GPIOD_FLAGS_BIT_DIR_VAL,
GPIOD_OUT_LOW_OPEN_DRAIN = GPIOD_FLAGS_BIT_DIR_SET |
GPIOD_FLAGS_BIT_DIR_OUT | GPIOD_FLAGS_BIT_OPEN_DRAIN,
GPIOD_OUT_HIGH_OPEN_DRAIN = GPIOD_FLAGS_BIT_DIR_SET |
GPIOD_FLAGS_BIT_DIR_OUT | GPIOD_FLAGS_BIT_DIR_VAL |
GPIOD_FLAGS_BIT_OPEN_DRAIN,
}; };
#ifdef CONFIG_GPIOLIB #ifdef CONFIG_GPIOLIB
......
...@@ -12,8 +12,6 @@ ...@@ -12,8 +12,6 @@
/** /**
* struct i2c_gpio_platform_data - Platform-dependent data for i2c-gpio * struct i2c_gpio_platform_data - Platform-dependent data for i2c-gpio
* @sda_pin: GPIO pin ID to use for SDA
* @scl_pin: GPIO pin ID to use for SCL
* @udelay: signal toggle delay. SCL frequency is (500 / udelay) kHz * @udelay: signal toggle delay. SCL frequency is (500 / udelay) kHz
* @timeout: clock stretching timeout in jiffies. If the slave keeps * @timeout: clock stretching timeout in jiffies. If the slave keeps
* SCL low for longer than this, the transfer will time out. * SCL low for longer than this, the transfer will time out.
...@@ -26,8 +24,6 @@ ...@@ -26,8 +24,6 @@
* @scl_is_output_only: SCL output drivers cannot be turned off. * @scl_is_output_only: SCL output drivers cannot be turned off.
*/ */
struct i2c_gpio_platform_data { struct i2c_gpio_platform_data {
unsigned int sda_pin;
unsigned int scl_pin;
int udelay; int udelay;
int timeout; int timeout;
unsigned int sda_is_open_drain:1; unsigned int sda_is_open_drain:1;
......
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
* properly set. * properly set.
*/ */
struct i2c_smbus_alert_setup { struct i2c_smbus_alert_setup {
unsigned int alert_edge_triggered:1;
int irq; int irq;
}; };
...@@ -50,4 +49,13 @@ struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter, ...@@ -50,4 +49,13 @@ struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter,
struct i2c_smbus_alert_setup *setup); struct i2c_smbus_alert_setup *setup);
int i2c_handle_smbus_alert(struct i2c_client *ara); int i2c_handle_smbus_alert(struct i2c_client *ara);
#if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_OF)
int of_i2c_setup_smbus_alert(struct i2c_adapter *adap);
#else
static inline int of_i2c_setup_smbus_alert(struct i2c_adapter *adap)
{
return 0;
}
#endif
#endif /* _LINUX_I2C_SMBUS_H */ #endif /* _LINUX_I2C_SMBUS_H */
...@@ -304,6 +304,7 @@ static inline bool i2c_detect_slave_mode(struct device *dev) { return false; } ...@@ -304,6 +304,7 @@ static inline bool i2c_detect_slave_mode(struct device *dev) { return false; }
* @type: chip type, to initialize i2c_client.name * @type: chip type, to initialize i2c_client.name
* @flags: to initialize i2c_client.flags * @flags: to initialize i2c_client.flags
* @addr: stored in i2c_client.addr * @addr: stored in i2c_client.addr
* @dev_name: Overrides the default <busnr>-<addr> dev_name if set
* @platform_data: stored in i2c_client.dev.platform_data * @platform_data: stored in i2c_client.dev.platform_data
* @archdata: copied into i2c_client.dev.archdata * @archdata: copied into i2c_client.dev.archdata
* @of_node: pointer to OpenFirmware device node * @of_node: pointer to OpenFirmware device node
...@@ -328,6 +329,7 @@ struct i2c_board_info { ...@@ -328,6 +329,7 @@ struct i2c_board_info {
char type[I2C_NAME_SIZE]; char type[I2C_NAME_SIZE];
unsigned short flags; unsigned short flags;
unsigned short addr; unsigned short addr;
const char *dev_name;
void *platform_data; void *platform_data;
struct dev_archdata *archdata; struct dev_archdata *archdata;
struct device_node *of_node; struct device_node *of_node;
......
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_ARCH_NUC900_I2C_H
#define __ASM_ARCH_NUC900_I2C_H
struct nuc900_platform_i2c {
int bus_num;
unsigned long bus_freq;
};
#endif /* __ASM_ARCH_NUC900_I2C_H */
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