1
0
Fork 0

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
  ...
hifive-unleashed-5.1
Linus Torvalds 2017-11-14 17:52:21 -08:00
commit 4008e6a9bc
70 changed files with 1687 additions and 602 deletions

View File

@ -36,6 +36,8 @@ Optional properties:
- read-only: this parameterless property disables writes to the eeprom
- size: total eeprom size in bytes
Example:
eeprom@52 {

View File

@ -7,7 +7,9 @@ Required Properties:
- compatible : should be "aspeed,ast2400-i2c-bus"
or "aspeed,ast2500-i2c-bus"
- 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
- interrupt-parent : interrupt controller for bus, should reference a
aspeed,ast2400-i2c-ic or aspeed,ast2500-i2c-ic
@ -40,7 +42,8 @@ i2c {
#interrupt-cells = <1>;
reg = <0x40 0x40>;
compatible = "aspeed,ast2400-i2c-bus";
clocks = <&clk_apb>;
clocks = <&syscon ASPEED_CLK_APB>;
resets = <&syscon ASPEED_RESET_I2C>;
bus-frequency = <100000>;
interrupts = <0>;
interrupt-parent = <&i2c_ic>;

View File

@ -6,6 +6,18 @@ davinci/keystone i2c interface contains.
Required properties:
- compatible: "ti,davinci-i2c" or "ti,keystone-i2c";
- 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 :
- interrupts : standard interrupt property.

View File

@ -2,25 +2,39 @@ Device-Tree bindings for i2c gpio driver
Required properties:
- 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:
- 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,delay-us: delay between GPIO operations (may depend on each platform)
- 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:
#include <dt-bindings/gpio/gpio.h>
i2c@0 {
compatible = "i2c-gpio";
gpios = <&pioA 23 0 /* sda */
&pioA 24 0 /* scl */
>;
i2c-gpio,sda-open-drain;
i2c-gpio,scl-open-drain;
sda-gpios = <&pioA 23 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
scl-gpios = <&pioA 24 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
i2c-gpio,delay-us = <2>; /* ~100 kHz */
#address-cells = <1>;
#size-cells = <0>;

View File

@ -6,10 +6,10 @@ multiplexer/switch will have one child node for each child bus.
Optional properties:
- #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>;
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
For i2c multiplexers/switches that have child nodes that are a mixture

View File

@ -13,6 +13,7 @@ Required properties:
"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-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-gen2-i2c" for a generic R-Car Gen2 or RZ/G1 compatible
device.

View File

@ -59,8 +59,8 @@ wants to support one of the below features, it should adapt the bindings below.
interrupts used by the device.
- interrupt-names
"irq" and "wakeup" names are recognized by I2C core, other names are
left to individual drivers.
"irq", "wakeup" and "smbus_alert" names are recognized by I2C core,
other names are left to individual drivers.
- host-notify
device uses SMBus host notify protocol instead of interrupt line.

View File

@ -0,0 +1,66 @@
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>;
};
};
};

View File

@ -2249,7 +2249,7 @@ F: include/linux/dmaengine.h
F: include/linux/async_tx.h
AT24 EEPROM DRIVER
M: Wolfram Sang <wsa@the-dreams.de>
M: Bartosz Golaszewski <brgl@bgdev.pl>
L: linux-i2c@vger.kernel.org
S: Maintained
F: drivers/misc/eeprom/at24.c

View File

@ -31,7 +31,7 @@
#include <linux/amba/serial.h>
#include <linux/mtd/physmap.h>
#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <linux/gpio/machine.h>
#include <linux/spi/spi.h>
#include <linux/export.h>
#include <linux/irqchip/arm-vic.h>
@ -320,42 +320,47 @@ void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr)
/*************************************************************************
* 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 = {
.name = "i2c-gpio",
.id = 0,
.dev = {
.platform_data = &ep93xx_i2c_data,
.platform_data = NULL,
},
};
/**
* ep93xx_register_i2c - Register the i2c platform device.
* @data: platform specific i2c-gpio configuration (__initdata)
* @devices: platform specific i2c bus device information (__initdata)
* @num: the number of devices on the i2c bus
*/
void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
struct i2c_board_info *devices, int num)
void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num)
{
/*
* Set the EEPROM interface pin drive type control.
* Defines the driver type for the EECLK and EEDAT pins as either
* open drain, which will require an external pull-up, or a normal
* CMOS driver.
* FIXME: this just sets the two pins as non-opendrain, as no
* platforms tries to do that anyway. Flag the applicable lines
* as open drain in the GPIO_LOOKUP above and the driver or
* 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)
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),
__raw_writel((0 << 1) | (0 << 0),
EP93XX_GPIO_EEDRIVE);
ep93xx_i2c_data = *data;
i2c_register_board_info(0, devices, num);
gpiod_add_lookup_table(&ep93xx_i2c_gpiod_table);
platform_device_register(&ep93xx_i2c_device);
}

View File

@ -28,7 +28,6 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <linux/spi/spi.h>
#include <sound/cs4271.h>
@ -61,14 +60,6 @@ static struct ep93xx_eth_data __initdata edb93xx_eth_data = {
/*************************************************************************
* 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[] = {
{
@ -86,13 +77,11 @@ static void __init edb93xx_register_i2c(void)
{
if (machine_is_edb9302a() || machine_is_edb9307a() ||
machine_is_edb9315a()) {
ep93xx_register_i2c(&edb93xx_i2c_gpio_data,
edb93xxa_i2c_board_info,
ep93xx_register_i2c(edb93xxa_i2c_board_info,
ARRAY_SIZE(edb93xxa_i2c_board_info));
} else if (machine_is_edb9302() || machine_is_edb9307()
|| machine_is_edb9312() || machine_is_edb9315()) {
ep93xx_register_i2c(&edb93xx_i2c_gpio_data,
edb93xx_i2c_board_info,
ep93xx_register_i2c(edb93xx_i2c_board_info,
ARRAY_SIZE(edb93xx_i2c_board_info));
}
}

View File

@ -8,7 +8,6 @@
#include <linux/reboot.h>
struct device;
struct i2c_gpio_platform_data;
struct i2c_board_info;
struct spi_board_info;
struct platform_device;
@ -37,8 +36,7 @@ void ep93xx_register_flash(unsigned int width,
resource_size_t start, resource_size_t size);
void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr);
void ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
struct i2c_board_info *devices, int num);
void ep93xx_register_i2c(struct i2c_board_info *devices, int num);
void ep93xx_register_spi(struct ep93xx_spi_info *info,
struct spi_board_info *devices, int num);
void ep93xx_register_fb(struct ep93xxfb_mach_info *data);

View File

@ -19,7 +19,6 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <linux/mmc/host.h>
#include <linux/spi/spi.h>
#include <linux/spi/mmc_spi.h>
@ -129,15 +128,6 @@ static struct ep93xx_spi_info simone_spi_info __initdata = {
.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[] = {
{
I2C_BOARD_INFO("ds1337", 0x68),
@ -161,7 +151,7 @@ static void __init simone_init_machine(void)
ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_8M);
ep93xx_register_eth(&simone_eth_data, 1);
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));
ep93xx_register_spi(&simone_spi_info, simone_spi_devices,
ARRAY_SIZE(simone_spi_devices));

View File

@ -21,7 +21,6 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <linux/fb.h>
#include <linux/mtd/partitions.h>
@ -127,15 +126,6 @@ static struct ep93xx_eth_data __initdata snappercl15_eth_data = {
.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[] = {
{
/* Audio codec */
@ -161,7 +151,7 @@ static void __init snappercl15_init_machine(void)
{
ep93xx_init_devices();
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));
ep93xx_register_fb(&snappercl15_fb_info);
snappercl15_register_audio();

View File

@ -22,7 +22,6 @@
#include <linux/io.h>
#include <linux/mtd/partitions.h>
#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <linux/platform_data/pca953x.h>
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
@ -144,10 +143,6 @@ static struct pca953x_platform_data pca953x_77_gpio_data = {
/*************************************************************************
* 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 = {
{
@ -289,7 +284,7 @@ static void __init vision_init_machine(void)
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));
ep93xx_register_spi(&vision_spi_master, vision_spi_board_info,
ARRAY_SIZE(vision_spi_board_info));

View File

@ -18,7 +18,7 @@
#include <linux/serial.h>
#include <linux/tty.h>
#include <linux/serial_8250.h>
#include <linux/i2c-gpio.h>
#include <linux/gpio/machine.h>
#include <asm/types.h>
#include <asm/setup.h>
#include <asm/memory.h>
@ -50,16 +50,21 @@ static struct platform_device avila_flash = {
.resource = &avila_flash_resource,
};
static struct i2c_gpio_platform_data avila_i2c_gpio_data = {
.sda_pin = AVILA_SDA_PIN,
.scl_pin = AVILA_SCL_PIN,
static struct gpiod_lookup_table avila_i2c_gpiod_table = {
.dev_id = "i2c-gpio",
.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 = {
.name = "i2c-gpio",
.id = 0,
.dev = {
.platform_data = &avila_i2c_gpio_data,
.platform_data = NULL,
},
};
@ -148,6 +153,8 @@ static void __init avila_init(void)
avila_flash_resource.end =
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));
avila_pata_resources[0].start = IXP4XX_EXP_BUS_BASE(1);

View File

@ -26,7 +26,7 @@
#include <linux/leds.h>
#include <linux/reboot.h>
#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <linux/gpio/machine.h>
#include <mach/hardware.h>
@ -69,16 +69,21 @@ static struct platform_device dsmg600_flash = {
.resource = &dsmg600_flash_resource,
};
static struct i2c_gpio_platform_data dsmg600_i2c_gpio_data = {
.sda_pin = DSMG600_SDA_PIN,
.scl_pin = DSMG600_SCL_PIN,
static struct gpiod_lookup_table dsmg600_i2c_gpiod_table = {
.dev_id = "i2c-gpio",
.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 = {
.name = "i2c-gpio",
.id = 0,
.dev = {
.platform_data = &dsmg600_i2c_gpio_data,
.platform_data = NULL,
},
};
@ -270,6 +275,7 @@ static void __init dsmg600_init(void)
dsmg600_flash_resource.end =
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,
ARRAY_SIZE(dsmg600_i2c_board_info));

View File

@ -23,7 +23,7 @@
#include <linux/leds.h>
#include <linux/reboot.h>
#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <linux/gpio/machine.h>
#include <linux/io.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@ -55,16 +55,21 @@ static struct platform_device fsg_flash = {
.resource = &fsg_flash_resource,
};
static struct i2c_gpio_platform_data fsg_i2c_gpio_data = {
.sda_pin = FSG_SDA_PIN,
.scl_pin = FSG_SCL_PIN,
static struct gpiod_lookup_table fsg_i2c_gpiod_table = {
.dev_id = "i2c-gpio",
.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 = {
.name = "i2c-gpio",
.id = 0,
.dev = {
.platform_data = &fsg_i2c_gpio_data,
.platform_data = NULL,
},
};
@ -197,6 +202,7 @@ static void __init fsg_init(void)
/* Configure CS2 for operation, 8bit and writable */
*IXP4XX_EXP_CS2 = 0xbfff0002;
gpiod_add_lookup_table(&fsg_i2c_gpiod_table);
i2c_register_board_info(0, fsg_i2c_board_info,
ARRAY_SIZE(fsg_i2c_board_info));

View File

@ -7,7 +7,6 @@
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/hdlc.h>
#include <linux/i2c-gpio.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/kernel.h>
@ -79,6 +78,12 @@
static u32 hw_bits = 0xFFFFFFFD; /* assume all hardware present */;
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)
{
gpio_set_value(GPIO_SCL, !!value);
@ -217,20 +222,6 @@ static struct platform_device device_flash = {
.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 */
static struct resource uart_resources[] = {
{
@ -412,9 +403,6 @@ static void __init gmlr_init(void)
if (hw_bits & CFG_HW_HAS_HSS1)
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_SDA, "SDA/data");
gpio_request(GPIO_STR, "strobe");

View File

@ -15,7 +15,7 @@
#include <linux/serial.h>
#include <linux/tty.h>
#include <linux/serial_8250.h>
#include <linux/i2c-gpio.h>
#include <linux/gpio/machine.h>
#include <linux/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
@ -123,16 +123,21 @@ static struct platform_device ixdp425_flash_nand = {
};
#endif /* CONFIG_MTD_NAND_PLATFORM */
static struct i2c_gpio_platform_data ixdp425_i2c_gpio_data = {
.sda_pin = IXDP425_SDA_PIN,
.scl_pin = IXDP425_SCL_PIN,
static struct gpiod_lookup_table ixdp425_i2c_gpiod_table = {
.dev_id = "i2c-gpio",
.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 = {
.name = "i2c-gpio",
.id = 0,
.dev = {
.platform_data = &ixdp425_i2c_gpio_data,
.platform_data = NULL,
},
};
@ -246,6 +251,7 @@ static void __init ixdp425_init(void)
ixdp425_uart_data[1].flags = 0;
}
gpiod_add_lookup_table(&ixdp425_i2c_gpiod_table);
platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices));
}

View File

@ -28,7 +28,7 @@
#include <linux/leds.h>
#include <linux/reboot.h>
#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <linux/gpio/machine.h>
#include <linux/io.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@ -101,16 +101,21 @@ static struct platform_device nas100d_leds = {
.dev.platform_data = &nas100d_led_data,
};
static struct i2c_gpio_platform_data nas100d_i2c_gpio_data = {
.sda_pin = NAS100D_SDA_PIN,
.scl_pin = NAS100D_SCL_PIN,
static struct gpiod_lookup_table nas100d_i2c_gpiod_table = {
.dev_id = "i2c-gpio",
.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 = {
.name = "i2c-gpio",
.id = 0,
.dev = {
.platform_data = &nas100d_i2c_gpio_data,
.platform_data = NULL,
},
};
@ -281,6 +286,7 @@ static void __init nas100d_init(void)
nas100d_flash_resource.end =
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,
ARRAY_SIZE(nas100d_i2c_board_info));

View File

@ -25,7 +25,7 @@
#include <linux/leds.h>
#include <linux/reboot.h>
#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <linux/gpio/machine.h>
#include <linux/io.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@ -69,9 +69,14 @@ static struct platform_device nslu2_flash = {
.resource = &nslu2_flash_resource,
};
static struct i2c_gpio_platform_data nslu2_i2c_gpio_data = {
.sda_pin = NSLU2_SDA_PIN,
.scl_pin = NSLU2_SCL_PIN,
static struct gpiod_lookup_table nslu2_i2c_gpiod_table = {
.dev_id = "i2c-gpio",
.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 [] = {
@ -116,7 +121,7 @@ static struct platform_device nslu2_i2c_gpio = {
.name = "i2c-gpio",
.id = 0,
.dev = {
.platform_data = &nslu2_i2c_gpio_data,
.platform_data = NULL,
},
};
@ -251,6 +256,7 @@ static void __init nslu2_init(void)
nslu2_flash_resource.end =
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,
ARRAY_SIZE(nslu2_i2c_board_info));

View File

@ -16,7 +16,7 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/gpio/machine.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/i2c-gpio.h>
@ -38,9 +38,17 @@
#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 = {
.sda_pin = 4,
.scl_pin = 5,
.udelay = 10,
};
@ -95,6 +103,7 @@ static struct i2c_board_info acs5k_i2c_devs[] __initdata = {
static void acs5k_i2c_init(void)
{
/* The gpio interface */
gpiod_add_lookup_table(&acs5k_i2c_gpiod_table);
platform_device_register(&acs5k_i2c_device);
/* I2C devices */
i2c_register_board_info(0, acs5k_i2c_devs,

View File

@ -31,6 +31,7 @@
#include <linux/power_supply.h>
#include <linux/usb/gpio_vbus.h>
#include <linux/i2c-gpio.h>
#include <linux/gpio/machine.h>
#include <asm/mach-types.h>
#include <asm/suspend.h>
@ -320,9 +321,17 @@ static struct soc_camera_link palmz72_iclink = {
.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 = {
.sda_pin = 118,
.scl_pin = 117,
.udelay = 10,
.timeout = 100,
};
@ -369,6 +378,7 @@ static void __init palmz72_camera_init(void)
{
palmz72_cam_gpio_init();
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_camera);
}

View File

@ -36,6 +36,7 @@
#include <linux/gpio.h>
#include <linux/jiffies.h>
#include <linux/i2c-gpio.h>
#include <linux/gpio/machine.h>
#include <linux/i2c/pxa-i2c.h>
#include <linux/serial_8250.h>
#include <linux/smc91x.h>
@ -458,9 +459,17 @@ static struct platform_device smc91x_device = {
};
/* 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 = {
.sda_pin = VIPER_RTC_I2C_SDA_GPIO,
.scl_pin = VIPER_RTC_I2C_SCL_GPIO,
.udelay = 10,
.timeout = HZ,
};
@ -779,12 +788,20 @@ static int __init viper_tpm_setup(char *str)
__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)
{
struct platform_device *tpm_device;
struct i2c_gpio_platform_data i2c_tpm_data = {
.sda_pin = VIPER_TPM_I2C_SDA_GPIO,
.scl_pin = VIPER_TPM_I2C_SCL_GPIO,
.udelay = 10,
.timeout = HZ,
};
@ -794,6 +811,7 @@ static void __init viper_tpm_init(void)
if (!viper_tpm)
return;
gpiod_add_lookup_table(&viper_tpm_i2c_gpiod_table);
tpm_device = platform_device_alloc("i2c-gpio", 2);
if (tpm_device) {
if (!platform_device_add_data(tpm_device,
@ -943,6 +961,7 @@ static void __init viper_init(void)
smc91x_device.num_resources--;
pxa_set_i2c_info(NULL);
gpiod_add_lookup_table(&viper_i2c_gpiod_table);
pwm_add_table(viper_pwm_lookup, ARRAY_SIZE(viper_pwm_lookup));
platform_add_devices(viper_devs, ARRAY_SIZE(viper_devs));

View File

@ -17,6 +17,7 @@
#include <linux/mtd/partitions.h>
#include <linux/io.h>
#include <linux/gpio/driver.h>
#include <linux/gpio/machine.h>
#include <mach/hardware.h>
#include <asm/setup.h>
@ -324,9 +325,17 @@ static struct platform_device simpad_gpio_leds = {
/*
* 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 = {
.sda_pin = GPIO_GPIO21,
.scl_pin = GPIO_GPIO25,
.udelay = 10,
.timeout = HZ,
};
@ -381,6 +390,7 @@ static int __init simpad_init(void)
ARRAY_SIZE(simpad_flash_resources));
sa11x0_register_mcp(&simpad_mcp_data);
gpiod_add_lookup_table(&simpad_i2c_gpiod_table);
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
if(ret)
printk(KERN_WARNING "simpad: Unable to register mq200 framebuffer device");

View File

@ -22,6 +22,7 @@
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/gpio/machine.h>
#include <asm/dma.h>
#include <asm/bfin5xx_spi.h>
#include <asm/portmux.h>
@ -362,11 +363,17 @@ static struct platform_device bfin_device_gpiokeys = {
#if IS_ENABLED(CONFIG_I2C_GPIO)
#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 = {
.sda_pin = GPIO_PF8,
.scl_pin = GPIO_PF9,
.sda_is_open_drain = 0,
.scl_is_open_drain = 0,
.udelay = 40,
}; /* This hasn't actually been used these pins
* are (currently) free pins on the expansion connector */
@ -462,7 +469,9 @@ static int __init blackstamp_init(void)
int ret;
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,
ARRAY_SIZE(bfin_i2c_board_info));

View File

@ -19,6 +19,7 @@
#endif
#include <linux/irq.h>
#include <linux/i2c.h>
#include <linux/gpio/machine.h>
#include <asm/dma.h>
#include <asm/bfin5xx_spi.h>
#include <asm/portmux.h>
@ -390,11 +391,17 @@ static struct platform_device bfin_device_gpiokeys = {
#if IS_ENABLED(CONFIG_I2C_GPIO)
#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 = {
.sda_pin = GPIO_PF1,
.scl_pin = GPIO_PF0,
.sda_is_open_drain = 0,
.scl_is_open_drain = 0,
.udelay = 40,
};
@ -516,6 +523,9 @@ static struct platform_device *ezkit_devices[] __initdata = {
static int __init ezkit_init(void)
{
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));
spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
i2c_register_board_info(0, bfin_i2c_board_info,

View File

@ -21,6 +21,7 @@
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/i2c.h>
#include <linux/gpio/machine.h>
#include <asm/dma.h>
#include <asm/bfin5xx_spi.h>
#include <asm/reboot.h>
@ -512,11 +513,17 @@ static struct platform_device bfin_device_gpiokeys = {
#if IS_ENABLED(CONFIG_I2C_GPIO)
#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 = {
.sda_pin = GPIO_PF2,
.scl_pin = GPIO_PF3,
.sda_is_open_drain = 0,
.scl_is_open_drain = 0,
.udelay = 10,
};
@ -848,6 +855,9 @@ static int __init stamp_init(void)
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,
ARRAY_SIZE(bfin_i2c_board_info));

View File

@ -16,6 +16,7 @@
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/gpio/machine.h>
#include <asm/dma.h>
#include <asm/bfin5xx_spi.h>
#include <asm/portmux.h>
@ -379,11 +380,17 @@ static struct platform_device bfin_device_gpiokeys = {
#if IS_ENABLED(CONFIG_I2C_GPIO)
#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 = {
.sda_pin = GPIO_PF1,
.scl_pin = GPIO_PF0,
.sda_is_open_drain = 0,
.scl_is_open_drain = 0,
.udelay = 10,
};
@ -633,6 +640,9 @@ static int __init ezkit_init(void)
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));
if (ret < 0)
return ret;

View File

@ -30,6 +30,7 @@
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <linux/gpio/machine.h>
#include <asm/bootinfo.h>
#include <asm/idle.h>
#include <asm/reboot.h>
@ -218,10 +219,27 @@ static struct platform_device gpr_led_devices = {
/*
* 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 = {
.sda_pin = 209,
/*
* The open drain mode is hardwired somewhere or an electrical
* property of the alchemy GPIO controller.
*/
.sda_is_open_drain = 1,
.scl_pin = 210,
.scl_is_open_drain = 1,
.udelay = 2, /* ~100 kHz */
.timeout = HZ,
@ -295,6 +313,7 @@ arch_initcall(gpr_pci_init);
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));
return platform_add_devices(gpr_devices, ARRAY_SIZE(gpr_devices));

View File

@ -11,7 +11,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/i2c-gpio.h>
#include <linux/gpio/machine.h>
#include <linux/platform_data/pcf857x.h>
#include "machtypes.h"
@ -33,16 +33,21 @@
#define PB44_KEYS_POLL_INTERVAL 20 /* msecs */
#define PB44_KEYS_DEBOUNCE_INTERVAL (3 * PB44_KEYS_POLL_INTERVAL)
static struct i2c_gpio_platform_data pb44_i2c_gpio_data = {
.sda_pin = PB44_GPIO_I2C_SDA,
.scl_pin = PB44_GPIO_I2C_SCL,
static struct gpiod_lookup_table pb44_i2c_gpiod_table = {
.dev_id = "i2c-gpio",
.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 = {
.name = "i2c-gpio",
.id = 0,
.dev = {
.platform_data = &pb44_i2c_gpio_data,
.platform_data = NULL,
}
};
@ -103,6 +108,7 @@ static struct ath79_spi_platform_data pb44_spi_data = {
static void __init pb44_init(void)
{
gpiod_add_lookup_table(&pb44_i2c_gpiod_table);
i2c_register_board_info(0, pb44_i2c_board_info,
ARRAY_SIZE(pb44_i2c_board_info));
platform_device_register(&pb44_i2c_gpio_device);

View File

@ -116,6 +116,10 @@ static const struct apd_device_desc hip08_i2c_desc = {
.setup = acpi_apd_setup,
.fixed_clk_rate = 250000000,
};
static const struct apd_device_desc thunderx2_i2c_desc = {
.setup = acpi_apd_setup,
.fixed_clk_rate = 125000000,
};
#endif
#else
@ -180,6 +184,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = {
{ "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
{ "BRCM900D", APD_ADDR(vulcan_spi_desc) },
{ "CAV900D", APD_ADDR(vulcan_spi_desc) },
{ "CAV9007", APD_ADDR(thunderx2_i2c_desc) },
{ "HISI02A1", APD_ADDR(hip07_i2c_desc) },
{ "HISI02A2", APD_ADDR(hip08_i2c_desc) },
#endif

View File

@ -3528,8 +3528,21 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
if (lflags & GPIO_ACTIVE_LOW)
set_bit(FLAG_ACTIVE_LOW, &desc->flags);
if (lflags & GPIO_OPEN_DRAIN)
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)
set_bit(FLAG_OPEN_SOURCE, &desc->flags);
if (lflags & GPIO_SLEEP_MAY_LOSE_VALUE)

View File

@ -198,6 +198,11 @@ config I2C_CHT_WC
SMBus controller found in the Intel Cherry Trail Whiskey Cove PMIC
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
tristate "Nvidia nForce2, nForce3 and nForce4"
depends on PCI

View File

@ -27,6 +27,7 @@
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <linux/slab.h>
/* I2C Register */
@ -132,6 +133,7 @@ struct aspeed_i2c_bus {
struct i2c_adapter adap;
struct device *dev;
void __iomem *base;
struct reset_control *rst;
/* Synchronizes I/O mem access to base. */
spinlock_t lock;
struct completion cmd_complete;
@ -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. */
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,
"bus-frequency", &bus->bus_frequency);
if (ret < 0) {
@ -917,6 +927,8 @@ static int aspeed_i2c_remove_bus(struct platform_device *pdev)
spin_unlock_irqrestore(&bus->lock, flags);
reset_control_assert(bus->rst);
i2c_del_adapter(&bus->adap);
return 0;

View File

@ -16,6 +16,7 @@
* GNU General Public License for more details.
*/
#include <linux/acpi.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/i2c.h>
@ -25,6 +26,7 @@
#include <linux/mfd/intel_soc_pmic.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/power/bq24190_charger.h>
#include <linux/slab.h>
#define CHT_WC_I2C_CTRL 0x5e24
@ -232,13 +234,35 @@ static const struct irq_chip cht_wc_i2c_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[] = {
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("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)
{
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)
struct i2c_board_info board_info = {
.type = "bq24190",
.addr = 0x6b,
.dev_name = "bq24190",
.properties = bq24190_props,
.platform_data = &bq24190_pdata,
};
int ret, reg, irq;
@ -314,11 +340,21 @@ static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)
if (ret)
goto remove_irq_domain;
board_info.irq = adap->client_irq;
adap->client = i2c_new_device(&adap->adapter, &board_info);
if (!adap->client) {
ret = -ENOMEM;
goto del_adapter;
/*
* Normally the Whiskey Cove PMIC is paired with a TI bq24292i charger,
* connected to this i2c bus, and a max17047 fuel-gauge and a fusb302
* USB Type-C controller connected to another i2c bus. In this setup
* 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);
@ -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);
i2c_unregister_device(adap->client);
if (adap->client)
i2c_unregister_device(adap->client);
i2c_del_adapter(&adap->adapter);
irq_domain_remove(adap->irq_domain);

View File

@ -36,6 +36,7 @@
#include <linux/gpio.h>
#include <linux/of_device.h>
#include <linux/platform_data/i2c-davinci.h>
#include <linux/pm_runtime.h>
/* ----- global defines ----------------------------------------------- */
@ -122,6 +123,9 @@
/* set the SDA GPIO low */
#define DAVINCI_I2C_DCLR_PDCLR1 BIT(1)
/* timeout for pm runtime autosuspend */
#define DAVINCI_I2C_PM_TIMEOUT 1000 /* ms */
struct davinci_i2c_dev {
struct device *dev;
void __iomem *base;
@ -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
* 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->terminate = 1;
wmb();
@ -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);
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);
if (ret < 0) {
dev_warn(dev->dev, "timeout waiting for bus ready\n");
return ret;
goto out;
}
for (i = 0; i < num; i++) {
@ -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,
ret);
if (ret < 0)
return ret;
goto out;
}
ret = num;
#ifdef CONFIG_CPU_FREQ
complete(&dev->xfr_complete);
#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)
@ -599,6 +615,9 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
int count = 0;
u16 w;
if (pm_runtime_suspended(dev->dev))
return IRQ_NONE;
while ((stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG))) {
dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat);
if (count++ == 100) {
@ -802,13 +821,24 @@ static int davinci_i2c_probe(struct platform_device *pdev)
dev->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(dev->clk))
return PTR_ERR(dev->clk);
clk_prepare_enable(dev->clk);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dev->base = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(dev->base)) {
r = PTR_ERR(dev->base);
goto err_unuse_clocks;
return PTR_ERR(dev->base);
}
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);
@ -849,27 +879,40 @@ static int davinci_i2c_probe(struct platform_device *pdev)
if (r)
goto err_unuse_clocks;
pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
return 0;
err_unuse_clocks:
clk_disable_unprepare(dev->clk);
dev->clk = NULL;
pm_runtime_dont_use_autosuspend(dev->dev);
pm_runtime_put_sync(dev->dev);
pm_runtime_disable(dev->dev);
return r;
}
static int davinci_i2c_remove(struct platform_device *pdev)
{
struct davinci_i2c_dev *dev = platform_get_drvdata(pdev);
int ret;
i2c_davinci_cpufreq_deregister(dev);
i2c_del_adapter(&dev->adapter);
clk_disable_unprepare(dev->clk);
dev->clk = NULL;
ret = pm_runtime_get_sync(&pdev->dev);
if (ret < 0) {
pm_runtime_put_noidle(&pdev->dev);
return ret;
}
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;
}
@ -880,7 +923,6 @@ static int davinci_i2c_suspend(struct device *dev)
/* put I2C into reset */
davinci_i2c_reset_ctrl(i2c_dev, 0);
clk_disable_unprepare(i2c_dev->clk);
return 0;
}
@ -889,7 +931,6 @@ static int davinci_i2c_resume(struct device *dev)
{
struct davinci_i2c_dev *i2c_dev = dev_get_drvdata(dev);
clk_prepare_enable(i2c_dev->clk);
/* take I2C out of reset */
davinci_i2c_reset_ctrl(i2c_dev, 1);
@ -899,6 +940,8 @@ static int davinci_i2c_resume(struct device *dev)
static const struct dev_pm_ops davinci_i2c_pm = {
.suspend = davinci_i2c_suspend,
.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)

View File

@ -280,6 +280,8 @@ struct dw_i2c_dev {
int (*acquire_lock)(struct dw_i2c_dev *dev);
void (*release_lock)(struct dw_i2c_dev *dev);
bool pm_disabled;
bool suspended;
bool skip_resume;
void (*disable)(struct dw_i2c_dev *dev);
void (*disable_int)(struct dw_i2c_dev *dev);
int (*init)(struct dw_i2c_dev *dev);

View File

@ -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)
{
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)
u32 acpi_speed, ht = 0;
struct resource *mem;
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);
if (irq < 0)
@ -362,14 +372,17 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
ACPI_COMPANION_SET(&adap->dev, ACPI_COMPANION(&pdev->dev));
adap->dev.of_node = pdev->dev.of_node;
if (dev->pm_disabled) {
pm_runtime_forbid(&pdev->dev);
} else {
pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
}
/* The code below assumes runtime PM to be disabled. */
WARN_ON(pm_runtime_enabled(&pdev->dev));
pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
if (dev->pm_disabled)
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_enable(&pdev->dev);
if (dev->mode == DW_IC_SLAVE)
ret = i2c_dw_probe_slave(dev);
@ -382,8 +395,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
return ret;
exit_probe:
if (!dev->pm_disabled)
pm_runtime_disable(&pdev->dev);
dw_i2c_plat_pm_cleanup(dev);
exit_reset:
if (!IS_ERR_OR_NULL(dev->rst))
reset_control_assert(dev->rst);
@ -402,8 +414,8 @@ static int dw_i2c_plat_remove(struct platform_device *pdev)
pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_put_sync(&pdev->dev);
if (!dev->pm_disabled)
pm_runtime_disable(&pdev->dev);
dw_i2c_plat_pm_cleanup(dev);
if (!IS_ERR_OR_NULL(dev->rst))
reset_control_assert(dev->rst);
@ -437,13 +449,20 @@ static void dw_i2c_plat_complete(struct device *dev)
#endif
#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);
if (i_dev->suspended) {
i_dev->skip_resume = true;
return 0;
}
i_dev->disable(i_dev);
i2c_dw_plat_prepare_clk(i_dev, false);
i_dev->suspended = true;
return 0;
}
@ -451,27 +470,27 @@ static int dw_i2c_plat_resume(struct device *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);
i_dev->init(i_dev);
i_dev->suspended = false;
return 0;
}
#ifdef CONFIG_PM_SLEEP
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 = {
.prepare = dw_i2c_plat_prepare,
.complete = dw_i2c_plat_complete,
SET_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume)
SET_RUNTIME_PM_OPS(dw_i2c_plat_runtime_suspend,
dw_i2c_plat_resume,
NULL)
SET_LATE_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume)
SET_RUNTIME_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume, NULL)
};
#define DW_I2C_DEV_PMOPS (&dw_i2c_dev_pm_ops)

View File

@ -14,27 +14,17 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
struct i2c_gpio_private_data {
struct gpio_desc *sda;
struct gpio_desc *scl;
struct i2c_adapter adap;
struct i2c_algo_bit_data bit_data;
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
* 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)
*/
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)
gpio_direction_input(pdata->scl_pin);
else
gpio_direction_output(pdata->scl_pin, 0);
gpiod_set_value(priv->sda, 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)
{
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)
{
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)
{
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,
@ -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");
}
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)
{
struct i2c_gpio_private_data *priv;
struct i2c_gpio_platform_data *pdata;
struct i2c_algo_bit_data *bit_data;
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;
/* First get the GPIO pins; if it fails, we'll defer the probe. */
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);
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
adap = &priv->adap;
bit_data = &priv->bit_data;
pdata = &priv->pdata;
if (pdev->dev.of_node) {
pdata->sda_pin = sda_pin;
pdata->scl_pin = scl_pin;
of_i2c_gpio_get_props(pdev->dev.of_node, pdata);
if (np) {
of_i2c_gpio_get_props(np, pdata);
} 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);
bit_data->setsda = i2c_gpio_setsda_val;
} else {
gpio_direction_input(pdata->sda_pin);
bit_data->setsda = i2c_gpio_setsda_dir;
}
/*
* First get the GPIO pins; if it fails, we'll defer the probe.
* If the SDA 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->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 (pdata->scl_is_open_drain || pdata->scl_is_output_only) {
gpio_direction_output(pdata->scl_pin, 1);
bit_data->setscl = i2c_gpio_setscl_val;
} else {
gpio_direction_input(pdata->scl_pin);
bit_data->setscl = i2c_gpio_setscl_dir;
}
/*
* 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);
bit_data->setsda = i2c_gpio_setsda_val;
bit_data->setscl = i2c_gpio_setscl_val;
if (!pdata->scl_is_output_only)
bit_data->getscl = i2c_gpio_getscl;
@ -207,18 +198,18 @@ static int i2c_gpio_probe(struct platform_device *pdev)
else
bit_data->timeout = HZ / 10; /* 100 ms */
bit_data->data = pdata;
bit_data->data = priv;
adap->owner = THIS_MODULE;
if (pdev->dev.of_node)
strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name));
if (np)
strlcpy(adap->name, dev_name(dev), sizeof(adap->name));
else
snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
adap->algo_data = bit_data;
adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adap->dev.parent = &pdev->dev;
adap->dev.of_node = pdev->dev.of_node;
adap->dev.parent = dev;
adap->dev.of_node = np;
adap->nr = pdev->id;
ret = i2c_bit_add_numbered_bus(adap);
@ -227,8 +218,13 @@ static int i2c_gpio_probe(struct platform_device *pdev)
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
? ", no clock stretching" : "");

View File

@ -82,6 +82,7 @@
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/timer.h>
@ -280,6 +281,8 @@
#define ISR_COMPLETE(err) (ISR_COMPLETE_M | (ISR_STATUS_M & (err)))
#define ISR_FATAL(err) (ISR_COMPLETE(err) | ISR_FATAL_M)
#define IMG_I2C_PM_TIMEOUT 1000 /* ms */
enum img_i2c_mode {
MODE_INACTIVE,
MODE_RAW,
@ -408,6 +411,9 @@ struct img_i2c {
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)
{
writel(value, i2c->base + offset);
@ -826,9 +832,9 @@ next_atomic_cmd:
* 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).
*/
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 int line_status;
@ -1054,8 +1060,8 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
atomic = true;
}
ret = clk_prepare_enable(i2c->scb_clk);
if (ret)
ret = pm_runtime_get_sync(adap->dev.parent);
if (ret < 0)
return ret;
for (i = 0; i < num; i++) {
@ -1131,7 +1137,8 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
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;
}
@ -1149,12 +1156,13 @@ static const struct i2c_algorithm img_i2c_algo = {
static int img_i2c_init(struct img_i2c *i2c)
{
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;
u32 rev;
int ret;
ret = clk_prepare_enable(i2c->scb_clk);
if (ret)
ret = pm_runtime_get_sync(i2c->adap.dev.parent);
if (ret < 0)
return ret;
rev = img_i2c_readl(i2c, SCB_CORE_REV_REG);
@ -1163,7 +1171,8 @@ static int img_i2c_init(struct img_i2c *i2c)
"Unknown hardware revision (%d.%d.%d.%d)\n",
(rev >> 24) & 0xff, (rev >> 16) & 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;
}
@ -1314,7 +1323,8 @@ static int img_i2c_init(struct img_i2c *i2c)
/* Perform a synchronous sequence to reset the bus */
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;
}
@ -1362,8 +1372,7 @@ static int img_i2c_probe(struct platform_device *pdev)
}
/* Set up the exception check timer */
setup_timer(&i2c->check_timer, img_i2c_check_timer,
(unsigned long)i2c);
timer_setup(&i2c->check_timer, img_i2c_check_timer, 0);
i2c->bitrate = timings[0].max_bitrate;
if (!of_property_read_u32(node, "clock-frequency", &val))
@ -1384,22 +1393,30 @@ static int img_i2c_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, i2c);
ret = clk_prepare_enable(i2c->sys_clk);
if (ret)
return ret;
pm_runtime_set_autosuspend_delay(&pdev->dev, IMG_I2C_PM_TIMEOUT);
pm_runtime_use_autosuspend(&pdev->dev);
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);
if (ret)
goto disable_clk;
goto rpm_disable;
ret = i2c_add_numbered_adapter(&i2c->adap);
if (ret < 0)
goto disable_clk;
goto rpm_disable;
return 0;
disable_clk:
clk_disable_unprepare(i2c->sys_clk);
rpm_disable:
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;
}
@ -1408,20 +1425,56 @@ static int img_i2c_remove(struct platform_device *dev)
struct img_i2c *i2c = platform_get_drvdata(dev);
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);
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
static int img_i2c_suspend(struct device *dev)
{
struct img_i2c *i2c = dev_get_drvdata(dev);
int ret;
ret = pm_runtime_force_suspend(dev);
if (ret)
return ret;
img_i2c_switch_mode(i2c, MODE_SUSPEND);
clk_disable_unprepare(i2c->sys_clk);
return 0;
}
@ -1430,7 +1483,7 @@ static int img_i2c_resume(struct device *dev)
struct img_i2c *i2c = dev_get_drvdata(dev);
int ret;
ret = clk_prepare_enable(i2c->sys_clk);
ret = pm_runtime_force_resume(dev);
if (ret)
return ret;
@ -1440,7 +1493,12 @@ static int img_i2c_resume(struct device *dev)
}
#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[] = {
{ .compatible = "img,scb-i2c" },

View File

@ -322,7 +322,7 @@ static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] = {
static u32 mpc_i2c_get_sec_cfg_8xxx(void)
{
struct device_node *node = NULL;
struct device_node *node;
u32 __iomem *reg;
u32 val = 0;
@ -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;
} else {
prop = of_get_property(op->dev.of_node, "clock-frequency",

View File

@ -486,6 +486,22 @@ static int omap_i2c_init(struct omap_i2c_dev *omap)
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
*/
@ -496,7 +512,7 @@ static int omap_i2c_wait_for_bb(struct omap_i2c_dev *omap)
timeout = jiffies + OMAP_I2C_TIMEOUT;
while (omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG) & OMAP_I2C_STAT_BB) {
if (time_after(jiffies, timeout))
return i2c_recover_bus(&omap->adapter);
return omap_i2c_recover_bus(omap);
msleep(1);
}
@ -577,8 +593,13 @@ static int omap_i2c_wait_for_bb_valid(struct omap_i2c_dev *omap)
}
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");
return -ETIMEDOUT;
return omap_i2c_recover_bus(omap);
}
msleep(1);

View File

@ -123,7 +123,6 @@ static struct i2c_adapter parport_adapter = {
/* SMBus alert support */
static struct i2c_smbus_alert_setup alert_data = {
.alert_edge_triggered = 1,
};
static struct i2c_client *ara;
static struct lineop parport_ctrl_irq = {

View File

@ -237,7 +237,6 @@ static void i2c_parport_attach(struct parport *port)
/* Setup SMBus alert if supported */
if (adapter_parm[type].smbus_alert) {
adapter->alert_data.alert_edge_triggered = 1;
adapter->ara = i2c_setup_smbus_alert(&adapter->adapter,
&adapter->alert_data);
if (adapter->ara)

View File

@ -112,7 +112,6 @@ static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)
jiffies, expires);
timer->expires = jiffies + expires;
timer->data = (unsigned long)alg_data;
add_timer(timer);
}
@ -435,9 +434,9 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
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;
dev_err(&alg_data->adapter.dev,
@ -659,8 +658,7 @@ static int i2c_pnx_probe(struct platform_device *pdev)
if (IS_ERR(alg_data->clk))
return PTR_ERR(alg_data->clk);
setup_timer(&alg_data->mif.timer, i2c_pnx_timeout,
(unsigned long)alg_data);
timer_setup(&alg_data->mif.timer, i2c_pnx_timeout, 0);
snprintf(alg_data->adapter.name, sizeof(alg_data->adapter.name),
"%s", pdev->name);

View File

@ -84,12 +84,7 @@
#define ICSR2_NACKF 0x10
/* ICBRx (@ PCLK 33MHz) */
#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
@ -288,48 +283,99 @@ static const struct i2c_algorithm riic_algo = {
.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;
unsigned long rate;
int total_ticks, cks, brl, brh;
ret = clk_prepare_enable(riic->clk);
if (ret)
return ret;
/*
* TODO: Implement formula to calculate the timing values depending on
* variable parent clock rate and arbitrary bus speed
*/
rate = clk_get_rate(riic->clk);
if (rate != 33325000) {
if (t->bus_freq_hz > 400000) {
dev_err(&riic->adapter.dev,
"invalid parent clk (%lu). Must be 33325000Hz\n", rate);
"unsupported bus speed (%dHz). 400000 max\n",
t->bus_freq_hz);
clk_disable_unprepare(riic->clk);
return -EINVAL;
}
rate = clk_get_rate(riic->clk);
/*
* Assume the default register settings:
* 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)
*/
/*
* Determine reference clock rate. We must be able to get the desired
* 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);
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! */
writeb(ICCR1_IICRST | ICCR1_SOWP, riic->base + RIIC_ICCR1);
riic_clear_set_bit(riic, 0, ICCR1_ICE, RIIC_ICCR1);
switch (spd) {
case 100000:
writeb(ICMR1_CKS(3), riic->base + RIIC_ICMR1);
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(ICMR1_CKS(cks), riic->base + RIIC_ICMR1);
writeb(brh | ICBR_RESERVED, riic->base + RIIC_ICBRH);
writeb(brl | ICBR_RESERVED, riic->base + RIIC_ICBRL);
writeb(0, riic->base + RIIC_ICSER);
writeb(ICMR3_ACKWP | ICMR3_RDRFS, riic->base + RIIC_ICMR3);
@ -351,11 +397,10 @@ static struct riic_irq_desc riic_irqs[] = {
static int riic_i2c_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct riic_dev *riic;
struct i2c_adapter *adap;
struct resource *res;
u32 bus_rate = 0;
struct i2c_timings i2c_t;
int i, ret;
riic = devm_kzalloc(&pdev->dev, sizeof(*riic), GFP_KERNEL);
@ -396,8 +441,9 @@ static int riic_i2c_probe(struct platform_device *pdev)
init_completion(&riic->msg_done);
of_property_read_u32(np, "clock-frequency", &bus_rate);
ret = riic_init_hw(riic, bus_rate);
i2c_parse_fw_timings(&pdev->dev, &i2c_t, true);
ret = riic_init_hw(riic, &i2c_t);
if (ret)
return ret;
@ -408,7 +454,8 @@ static int riic_i2c_probe(struct platform_device *pdev)
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;
}

View File

@ -881,7 +881,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
struct sh_mobile_i2c_data *pd;
struct i2c_adapter *adap;
struct resource *res;
const struct of_device_id *match;
const struct sh_mobile_dt_config *config;
int ret;
u32 bus_speed;
@ -913,10 +913,8 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
pd->bus_speed = ret ? STANDARD_MODE : bus_speed;
pd->clks_per_count = 1;
match = of_match_device(sh_mobile_i2c_dt_ids, &dev->dev);
if (match) {
const struct sh_mobile_dt_config *config = match->data;
config = of_device_get_match_data(&dev->dev);
if (config) {
pd->clks_per_count = config->clks_per_count;
if (config->setup)

View File

@ -282,8 +282,7 @@ static void taos_disconnect(struct serio *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);
serio_close(serio);
kfree(taos);

View File

@ -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,
struct device_node *node)
{
u32 type;
if (!node)
return -EINVAL;
@ -127,10 +125,6 @@ static int thunder_i2c_smbus_setup_of(struct octeon_i2c *i2c,
if (!i2c->alert_data.irq)
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);
if (!i2c->ara)
return -ENODEV;
@ -149,8 +143,7 @@ static int thunder_i2c_smbus_setup(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,

View File

@ -129,6 +129,11 @@ struct slimpro_i2c_dev {
#define to_slimpro_i2c_dev(cl) \
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
*/
@ -476,6 +481,15 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
}
} else {
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",
&ctx->mbox_idx))
@ -514,9 +528,16 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
*/
ctx->comm_base_addr = cppc_ss->base_address;
if (ctx->comm_base_addr) {
ctx->pcc_comm_addr = memremap(ctx->comm_base_addr,
cppc_ss->length,
MEMREMAP_WB);
if (version == XGENE_SLIMPRO_I2C_V2)
ctx->pcc_comm_addr = memremap(
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 {
dev_err(&pdev->dev, "Failed to get PCC comm region\n");
rc = -ENOENT;
@ -581,7 +602,8 @@ MODULE_DEVICE_TABLE(of, xgene_slimpro_i2c_dt_ids);
#ifdef CONFIG_ACPI
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);

View File

@ -7,6 +7,7 @@
*/
#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/i2c.h>
#include <linux/init.h>
@ -81,9 +82,12 @@ struct xlp9xx_i2c_dev {
struct completion msg_complete;
int irq;
bool msg_read;
bool len_recv;
bool client_pec;
u32 __iomem *base;
u32 msg_buf_remaining;
u32 msg_len;
u32 ip_clk_hz;
u32 clk_hz;
u32 msg_err;
u8 *msg_buf;
@ -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)
{
u32 len, i;
u8 *buf = priv->msg_buf;
u8 rlen, *buf = priv->msg_buf;
len = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_FIFOWCNT) &
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);
for (i = 0; i < len; i++, buf++)
*buf = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO);
@ -213,7 +232,7 @@ static int xlp9xx_i2c_init(struct xlp9xx_i2c_dev *priv)
* The controller uses 5 * SCL clock internally.
* 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;
xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, XLP9XX_I2C_CTRL_RST);
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,
int last_msg)
{
unsigned long timeleft;
u32 intr_mask, cmd, val;
u32 intr_mask, cmd, val, len;
priv->msg_buf = msg->buf;
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,
else
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 */
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);
/* fill fifo during tx */
@ -310,6 +333,9 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
return -ETIMEDOUT;
}
/* update msg->len with actual received length */
if (msg->flags & I2C_M_RECV_LEN)
msg->len = priv->msg_len;
return 0;
}
@ -342,9 +368,19 @@ static const struct i2c_algorithm xlp9xx_i2c_algo = {
static int xlp9xx_i2c_get_frequency(struct platform_device *pdev,
struct xlp9xx_i2c_dev *priv)
{
struct clk *clk;
u32 freq;
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);
if (err) {
freq = XLP9XX_I2C_DEFAULT_FREQ;

View File

@ -29,6 +29,7 @@
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/i2c-smbus.h>
#include <linux/idr.h>
#include <linux/init.h>
#include <linux/irqflags.h>
@ -205,9 +206,6 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)
*/
while (i++ < RECOVERY_CLK_CNT * 2) {
if (val) {
/* Break if SDA is high */
if (bri->get_sda && bri->get_sda(adap))
break;
/* SCL shouldn't be low here */
if (!bri->get_scl(adap)) {
dev_err(&adap->dev,
@ -215,6 +213,9 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)
ret = -EBUSY;
break;
}
/* Break if SDA is high */
if (bri->get_sda && bri->get_sda(adap))
break;
}
val = !val;
@ -222,6 +223,10 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)
ndelay(RECOVERY_NDELAY);
}
/* check if recovery actually succeeded */
if (bri->get_sda && !bri->get_sda(adap))
ret = -EBUSY;
if (bri->unprepare_recovery)
bri->unprepare_recovery(adap);
@ -666,10 +671,16 @@ static void i2c_adapter_unlock_bus(struct i2c_adapter *adapter,
}
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);
if (info && info->dev_name) {
dev_set_name(&client->dev, "i2c-%s", info->dev_name);
return;
}
if (adev) {
dev_set_name(&client->dev, "i2c-%s", acpi_dev_name(adev));
return;
@ -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.fwnode = info->fwnode;
i2c_dev_set_name(adap, client);
i2c_dev_set_name(adap, client, info);
if (info->properties) {
status = device_add_properties(&client->dev, info->properties);
@ -808,6 +819,8 @@ EXPORT_SYMBOL_GPL(i2c_new_device);
*/
void i2c_unregister_device(struct i2c_client *client)
{
if (!client)
return;
if (client->dev.of_node)
of_node_clear_flag(client->dev.of_node, OF_POPULATED);
if (ACPI_COMPANION(&client->dev))
@ -1259,6 +1272,10 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
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);
pm_runtime_no_callbacks(&adap->dev);
@ -1290,6 +1307,10 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
return 0;
out_reg:
init_completion(&adap->dev_released);
device_unregister(&adap->dev);
wait_for_completion(&adap->dev_released);
out_list:
mutex_lock(&core_lock);
idr_remove(&i2c_adapter_idr, adap->nr);
@ -1417,8 +1438,7 @@ static int __unregister_client(struct device *dev, void *dummy)
static int __unregister_dummy(struct device *dev, void *dummy)
{
struct i2c_client *client = i2c_verify_client(dev);
if (client)
i2c_unregister_device(client);
i2c_unregister_device(client);
return 0;
}

View File

@ -17,6 +17,7 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/i2c-smbus.h>
#define CREATE_TRACE_POINTS
#include <trace/events/smbus.h>
@ -592,3 +593,57 @@ s32 i2c_smbus_read_i2c_block_data_or_emulated(const struct i2c_client *client,
return i;
}
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

View File

@ -21,12 +21,11 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_irq.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
struct i2c_smbus_alert {
unsigned int alert_edge_triggered:1;
int irq;
struct work_struct alert;
struct i2c_client *ara; /* Alert response address */
};
@ -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
* 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;
unsigned short prev_addr = 0; /* Not a valid address */
alert = container_of(work, struct i2c_smbus_alert, alert);
ara = alert->ara;
for (;;) {
@ -115,21 +113,17 @@ static void smbus_alert(struct work_struct *work)
prev_addr = data.addr;
}
/* We handled all alerts; re-enable level-triggered IRQs */
if (!alert->alert_edge_triggered)
enable_irq(alert->irq);
return IRQ_HANDLED;
}
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 */
if (!alert->alert_edge_triggered)
disable_irq_nosync(irq);
alert = container_of(work, struct i2c_smbus_alert, alert);
smbus_alert(0, alert);
schedule_work(&alert->alert);
return IRQ_HANDLED;
}
/* Setup SMBALERT# infrastructure */
@ -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 *alert;
struct i2c_adapter *adapter = ara->adapter;
int res;
int res, irq;
alert = devm_kzalloc(&ara->dev, sizeof(struct i2c_smbus_alert),
GFP_KERNEL);
if (!alert)
return -ENOMEM;
alert->alert_edge_triggered = setup->alert_edge_triggered;
alert->irq = setup->irq;
INIT_WORK(&alert->alert, smbus_alert);
if (setup) {
irq = setup->irq;
} 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;
if (setup->irq > 0) {
res = devm_request_irq(&ara->dev, setup->irq, smbalert_irq,
0, "smbus_alert", alert);
if (irq > 0) {
res = devm_request_threaded_irq(&ara->dev, irq,
NULL, smbus_alert,
IRQF_SHARED | IRQF_ONESHOT,
"smbus_alert", alert);
if (res)
return res;
}
i2c_set_clientdata(ara, alert);
dev_info(&adapter->dev, "supports SMBALERT#, %s trigger\n",
setup->alert_edge_triggered ? "edge" : "level");
dev_info(&adapter->dev, "supports SMBALERT#\n");
return 0;
}
@ -189,38 +190,6 @@ static struct i2c_driver smbalert_driver = {
.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
* @ara: the ARA client on the relevant adapter

View File

@ -246,36 +246,6 @@ static irqreturn_t pca954x_irq_handler(int irq, void *dev_id)
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)
{
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)
static struct irq_chip pca954x_irq_chip = {
.name = "i2c-mux-pca954x",
.irq_mask = pca954x_irq_mask,
.irq_unmask = pca954x_irq_unmask,
.irq_set_type = pca954x_irq_set_type,
};
@ -294,7 +262,7 @@ static int pca954x_irq_setup(struct i2c_mux_core *muxc)
{
struct pca954x *data = i2c_mux_priv(muxc);
struct i2c_client *client = data->client;
int c, err, irq;
int c, irq;
if (!data->chip->has_irq || client->irq <= 0)
return 0;
@ -309,29 +277,31 @@ static int pca954x_irq_setup(struct i2c_mux_core *muxc)
for (c = 0; c < data->chip->nchans; 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_and_handler(irq, &pca954x_irq_chip,
handle_simple_irq);
}
err = devm_request_threaded_irq(&client->dev, data->client->irq, NULL,
pca954x_irq_handler,
IRQF_ONESHOT | IRQF_SHARED,
"pca954x", data);
if (err)
goto err_req_irq;
disable_irq(data->client->irq);
return 0;
err_req_irq:
for (c = 0; c < data->chip->nchans; c++) {
irq = irq_find_mapping(data->irq, c);
irq_dispose_mapping(irq);
}
irq_domain_remove(data->irq);
}
return err;
static void pca954x_cleanup(struct i2c_mux_core *muxc)
{
struct pca954x *data = i2c_mux_priv(muxc);
int c, irq;
if (data->irq) {
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);
}
/*
@ -391,7 +361,7 @@ static int pca954x_probe(struct i2c_client *client,
ret = pca954x_irq_setup(muxc);
if (ret)
goto fail_del_adapters;
goto fail_cleanup;
/* Now create an adapter for each channel */
for (num = 0; num < data->chip->nchans; num++) {
@ -414,7 +384,16 @@ static int pca954x_probe(struct i2c_client *client,
ret = i2c_mux_add_adapter(muxc, force, num, class);
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,
@ -424,26 +403,16 @@ static int pca954x_probe(struct i2c_client *client,
return 0;
fail_del_adapters:
i2c_mux_del_adapters(muxc);
fail_cleanup:
pca954x_cleanup(muxc);
return ret;
}
static int pca954x_remove(struct i2c_client *client)
{
struct i2c_mux_core *muxc = i2c_get_clientdata(client);
struct pca954x *data = i2c_mux_priv(muxc);
int c, irq;
if (data->irq) {
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);
pca954x_cleanup(muxc);
return 0;
}

View File

@ -107,9 +107,9 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
put_device(&adapter->dev);
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;
} else if (of_find_property(np, "big-endian", NULL)) {
} else if (of_property_read_bool(np, "big-endian")) {
mux->data.little_endian = false;
} else {
#if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : \
@ -122,10 +122,7 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
#error Endianness not defined?
#endif
}
if (of_find_property(np, "write-only", NULL))
mux->data.write_only = true;
else
mux->data.write_only = false;
mux->data.write_only = of_property_read_bool(np, "write-only");
values = devm_kzalloc(&pdev->dev,
sizeof(*mux->data.values) * mux->data.n_values,

View File

@ -38,12 +38,7 @@ int intel_lpss_resume(struct device *dev);
#ifdef CONFIG_PM_SLEEP
#define INTEL_LPSS_SLEEP_PM_OPS \
.prepare = intel_lpss_prepare, \
.suspend = intel_lpss_suspend, \
.resume = intel_lpss_resume, \
.freeze = intel_lpss_suspend, \
.thaw = intel_lpss_resume, \
.poweroff = intel_lpss_suspend, \
.restore = intel_lpss_resume,
SET_LATE_SYSTEM_SLEEP_PM_OPS(intel_lpss_suspend, intel_lpss_resume)
#else
#define INTEL_LPSS_SLEEP_PM_OPS
#endif

View File

@ -20,6 +20,7 @@
#include <linux/platform_device.h>
#include <linux/pci.h>
#include <linux/i2c-gpio.h>
#include <linux/gpio/machine.h>
#include <linux/slab.h>
#include <linux/sm501.h>
@ -1107,14 +1108,6 @@ static void sm501_gpio_remove(struct sm501_devdata *sm)
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)
{
return sm->gpio.registered;
@ -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)
{
return 0;
@ -1145,20 +1133,37 @@ static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm,
{
struct i2c_gpio_platform_data *icd;
struct platform_device *pdev;
struct gpiod_lookup_table *lookup;
pdev = sm501_create_subdev(sm, "i2c-gpio", 0,
sizeof(struct i2c_gpio_platform_data));
if (!pdev)
return -ENOMEM;
/* Create a gpiod lookup using gpiochip-local offsets */
lookup = devm_kzalloc(&pdev->dev,
sizeof(*lookup) + 3 * sizeof(struct gpiod_lookup),
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 = dev_get_platdata(&pdev->dev);
/* We keep the pin_sda and pin_scl fields relative in case the
* same platform data is passed to >1 SM501.
*/
icd->sda_pin = sm501_gpio_pin2nr(sm, iic->pin_sda);
icd->scl_pin = sm501_gpio_pin2nr(sm, iic->pin_scl);
icd->timeout = iic->timeout;
icd->udelay = iic->udelay;
@ -1170,9 +1175,9 @@ static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm,
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,
icd->sda_pin, iic->pin_sda, icd->scl_pin, iic->pin_scl);
iic->pin_sda, iic->pin_scl);
return sm501_register_device(sm, pdev);
}

View File

@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/mutex.h>
@ -24,6 +25,7 @@
#include <linux/i2c.h>
#include <linux/nvmem-provider.h>
#include <linux/platform_data/at24.h>
#include <linux/pm_runtime.h>
/*
* I2C EEPROMs from most vendors are inexpensive and mostly interchangeable.
@ -175,6 +177,64 @@ static const struct i2c_device_id 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[] = {
{ "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,
static int at24_read(void *priv, unsigned int off, void *val, size_t count)
{
struct at24_data *at24 = priv;
struct i2c_client *client;
char *buf = val;
int ret;
if (unlikely(!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
* 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)
status = at24->read_func(at24, buf, off, count);
if (status < 0) {
mutex_unlock(&at24->lock);
pm_runtime_put(&client->dev);
return status;
}
buf += status;
@ -527,17 +598,29 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count)
mutex_unlock(&at24->lock);
pm_runtime_put(&client->dev);
return 0;
}
static int at24_write(void *priv, unsigned int off, void *val, size_t count)
{
struct at24_data *at24 = priv;
struct i2c_client *client;
char *buf = val;
int ret;
if (unlikely(!count))
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
* 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)
status = at24->write_func(at24, buf, off, count);
if (status < 0) {
mutex_unlock(&at24->lock);
pm_runtime_put(&client->dev);
return status;
}
buf += status;
@ -559,6 +643,8 @@ static int at24_write(void *priv, unsigned int off, void *val, size_t count)
mutex_unlock(&at24->lock);
pm_runtime_put(&client->dev);
return 0;
}
@ -570,6 +656,10 @@ static void at24_get_pdata(struct device *dev, struct at24_platform_data *chip)
if (device_property_present(dev, "read-only"))
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);
if (!err) {
chip->page_size = val;
@ -598,7 +688,16 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
if (client->dev.platform_data) {
chip = *(struct at24_platform_data *)client->dev.platform_data;
} 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;
} else {
const struct acpi_device_id *aid;
@ -739,11 +838,16 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
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
* chip is functional.
*/
err = at24_read(at24, 0, &test_byte, 1);
pm_runtime_idle(&client->dev);
if (err) {
err = -ENODEV;
goto err_clients;
@ -791,6 +895,8 @@ err_clients:
if (at24->client[i])
i2c_unregister_device(at24->client[i]);
pm_runtime_disable(&client->dev);
return err;
}
@ -806,6 +912,9 @@ static int at24_remove(struct i2c_client *client)
for (i = 1; i < at24->num_addresses; i++)
i2c_unregister_device(at24->client[i]);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
return 0;
}
@ -814,6 +923,7 @@ static int at24_remove(struct i2c_client *client)
static struct i2c_driver at24_driver = {
.driver = {
.name = "at24",
.of_match_table = at24_of_match,
.acpi_match_table = ACPI_PTR(at24_acpi_ids),
},
.probe = at24_probe,

View File

@ -184,6 +184,20 @@ config CHARGER_SBS
help
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
tristate "BQ27xxx battery driver"
help

View File

@ -37,6 +37,7 @@ obj-$(CONFIG_BATTERY_IPAQ_MICRO) += ipaq_micro_battery.o
obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o
obj-$(CONFIG_BATTERY_SBS) += sbs-battery.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_I2C) += bq27xxx_battery_i2c.o
obj-$(CONFIG_BATTERY_BQ27XXX_HDQ) += bq27xxx_battery_hdq.o

View File

@ -177,10 +177,8 @@ static bool force_load;
static int sbs_read_word_data(struct i2c_client *client, u8 address)
{
struct sbs_info *chip = i2c_get_clientdata(client);
int retries = chip->i2c_retry_count;
s32 ret = 0;
int retries = 1;
retries = chip->i2c_retry_count;
while (retries > 0) {
ret = i2c_smbus_read_word_data(client, 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);
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];
retries_length = chip->i2c_retry_count;
@ -269,10 +267,8 @@ static int sbs_write_word_data(struct i2c_client *client, u8 address,
u16 value)
{
struct sbs_info *chip = i2c_get_clientdata(client);
int retries = chip->i2c_retry_count;
s32 ret = 0;
int retries = 1;
retries = chip->i2c_retry_count;
while (retries > 0) {
ret = i2c_smbus_write_word_data(client, address, value);
@ -321,16 +317,6 @@ static int sbs_get_battery_presence_and_health(
union power_supply_propval *val)
{
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
@ -570,7 +556,7 @@ static int sbs_get_battery_serial_number(struct i2c_client *client,
if (ret < 0)
return ret;
ret = sprintf(sbs_serial, "%04x", ret);
sprintf(sbs_serial, "%04x", ret);
val->strval = sbs_serial;
return 0;
@ -598,6 +584,19 @@ static int sbs_get_property(struct power_supply *psy,
struct sbs_info *chip = power_supply_get_drvdata(psy);
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) {
case POWER_SUPPLY_PROP_PRESENT:
case POWER_SUPPLY_PROP_HEALTH:

View File

@ -0,0 +1,445 @@
/*
* Driver for SBS compliant Smart Battery System Managers
*
* The device communicates via i2c at address 0x0a and multiplexes access to up
* to four smart batteries at address 0x0b.
*
* Via sysfs interface the online state and charge type are presented.
*
* Datasheet SBSM: http://sbs-forum.org/specs/sbsm100b.pdf
* Datasheet LTC1760: http://cds.linear.com/docs/en/datasheet/1760fb.pdf
*
* Karl-Heinz Schneider <karl-heinz@schneider-inet.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/i2c-mux.h>
#include <linux/power_supply.h>
#include <linux/property.h>
#define SBSM_MAX_BATS 4
#define SBSM_RETRY_CNT 3
/* registers addresses */
#define SBSM_CMD_BATSYSSTATE 0x01
#define SBSM_CMD_BATSYSSTATECONT 0x02
#define SBSM_CMD_BATSYSINFO 0x04
#define SBSM_CMD_LTC 0x3c
#define SBSM_MASK_BAT_SUPPORTED GENMASK(3, 0)
#define SBSM_MASK_CHARGE_BAT GENMASK(7, 4)
#define SBSM_BIT_AC_PRESENT BIT(0)
#define SBSM_BIT_TURBO BIT(7)
#define SBSM_SMB_BAT_OFFSET 11
struct sbsm_data {
struct i2c_client *client;
struct i2c_mux_core *muxc;
struct power_supply *psy;
u8 cur_chan; /* currently selected channel */
struct gpio_chip chip;
bool is_ltc1760; /* special capabilities */
unsigned int supported_bats;
unsigned int last_state;
unsigned int last_state_cont;
};
static enum power_supply_property sbsm_props[] = {
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_CHARGE_TYPE,
};
static int sbsm_read_word(struct i2c_client *client, u8 address)
{
int reg, retries;
for (retries = SBSM_RETRY_CNT; retries > 0; retries--) {
reg = i2c_smbus_read_word_data(client, address);
if (reg >= 0)
break;
}
if (reg < 0) {
dev_err(&client->dev, "failed to read register 0x%02x\n",
address);
}
return reg;
}
static int sbsm_write_word(struct i2c_client *client, u8 address, u16 word)
{
int ret, retries;
for (retries = SBSM_RETRY_CNT; retries > 0; retries--) {
ret = i2c_smbus_write_word_data(client, address, word);
if (ret >= 0)
break;
}
if (ret < 0)
dev_err(&client->dev, "failed to write to register 0x%02x\n",
address);
return ret;
}
static int sbsm_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
struct sbsm_data *data = power_supply_get_drvdata(psy);
int regval = 0;
switch (psp) {
case POWER_SUPPLY_PROP_ONLINE:
regval = sbsm_read_word(data->client, SBSM_CMD_BATSYSSTATECONT);
if (regval < 0)
return regval;
val->intval = !!(regval & SBSM_BIT_AC_PRESENT);
break;
case POWER_SUPPLY_PROP_CHARGE_TYPE:
regval = sbsm_read_word(data->client, SBSM_CMD_BATSYSSTATE);
if (regval < 0)
return regval;
if ((regval & SBSM_MASK_CHARGE_BAT) == 0) {
val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
return 0;
}
val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
if (data->is_ltc1760) {
/* charge mode fast if turbo is active */
regval = sbsm_read_word(data->client, SBSM_CMD_LTC);
if (regval < 0)
return regval;
else if (regval & SBSM_BIT_TURBO)
val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
}
break;
default:
return -EINVAL;
}
return 0;
}
static int sbsm_prop_is_writeable(struct power_supply *psy,
enum power_supply_property psp)
{
struct sbsm_data *data = power_supply_get_drvdata(psy);
return (psp == POWER_SUPPLY_PROP_CHARGE_TYPE) && data->is_ltc1760;
}
static int sbsm_set_property(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *val)
{
struct sbsm_data *data = power_supply_get_drvdata(psy);
int ret = -EINVAL;
u16 regval;
switch (psp) {
case POWER_SUPPLY_PROP_CHARGE_TYPE:
/* write 1 to TURBO if type fast is given */
if (!data->is_ltc1760)
break;
regval = val->intval ==
POWER_SUPPLY_CHARGE_TYPE_FAST ? SBSM_BIT_TURBO : 0;
ret = sbsm_write_word(data->client, SBSM_CMD_LTC, regval);
break;
default:
break;
}
return ret;
}
/*
* Switch to battery
* Parameter chan is directly the content of SMB_BAT* nibble
*/
static int sbsm_select(struct i2c_mux_core *muxc, u32 chan)
{
struct sbsm_data *data = i2c_mux_priv(muxc);
struct device *dev = &data->client->dev;
int ret = 0;
u16 reg;
if (data->cur_chan == chan)
return ret;
/* chan goes from 1 ... 4 */
reg = 1 << BIT(SBSM_SMB_BAT_OFFSET + chan);
ret = sbsm_write_word(data->client, SBSM_CMD_BATSYSSTATE, reg);
if (ret)
dev_err(dev, "Failed to select channel %i\n", chan);
else
data->cur_chan = chan;
return ret;
}
static int sbsm_gpio_get_value(struct gpio_chip *gc, unsigned int off)
{
struct sbsm_data *data = gpiochip_get_data(gc);
int ret;
ret = sbsm_read_word(data->client, SBSM_CMD_BATSYSSTATE);
if (ret < 0)
return ret;
return ret & BIT(off);
}
/*
* This needs to be defined or the GPIO lib fails to register the pin.
* But the 'gpio' is always an input.
*/
static int sbsm_gpio_direction_input(struct gpio_chip *gc, unsigned int off)
{
return 0;
}
static int sbsm_do_alert(struct device *dev, void *d)
{
struct i2c_client *client = i2c_verify_client(dev);
struct i2c_driver *driver;
if (!client || client->addr != 0x0b)
return 0;
device_lock(dev);
if (client->dev.driver) {
driver = to_i2c_driver(client->dev.driver);
if (driver->alert)
driver->alert(client, I2C_PROTOCOL_SMBUS_ALERT, 0);
else
dev_warn(&client->dev, "no driver alert()!\n");
} else {
dev_dbg(&client->dev, "alert with no driver\n");
}
device_unlock(dev);
return -EBUSY;
}
static void sbsm_alert(struct i2c_client *client, enum i2c_alert_protocol prot,
unsigned int d)
{
struct sbsm_data *sbsm = i2c_get_clientdata(client);
int ret, i, irq_bat = 0, state = 0;
ret = sbsm_read_word(sbsm->client, SBSM_CMD_BATSYSSTATE);
if (ret >= 0) {
irq_bat = ret ^ sbsm->last_state;
sbsm->last_state = ret;
state = ret;
}
ret = sbsm_read_word(sbsm->client, SBSM_CMD_BATSYSSTATECONT);
if ((ret >= 0) &&
((ret ^ sbsm->last_state_cont) & SBSM_BIT_AC_PRESENT)) {
irq_bat |= sbsm->supported_bats & state;
power_supply_changed(sbsm->psy);
}
sbsm->last_state_cont = ret;
for (i = 0; i < SBSM_MAX_BATS; i++) {
if (irq_bat & BIT(i)) {
device_for_each_child(&sbsm->muxc->adapter[i]->dev,
NULL, sbsm_do_alert);
}
}
}
static int sbsm_gpio_setup(struct sbsm_data *data)
{
struct gpio_chip *gc = &data->chip;
struct i2c_client *client = data->client;
struct device *dev = &client->dev;
int ret;
if (!device_property_present(dev, "gpio-controller"))
return 0;
ret = sbsm_read_word(client, SBSM_CMD_BATSYSSTATE);
if (ret < 0)
return ret;
data->last_state = ret;
ret = sbsm_read_word(client, SBSM_CMD_BATSYSSTATECONT);
if (ret < 0)
return ret;
data->last_state_cont = ret;
gc->get = sbsm_gpio_get_value;
gc->direction_input = sbsm_gpio_direction_input;
gc->can_sleep = true;
gc->base = -1;
gc->ngpio = SBSM_MAX_BATS;
gc->label = client->name;
gc->parent = dev;
gc->owner = THIS_MODULE;
ret = devm_gpiochip_add_data(dev, gc, data);
if (ret) {
dev_err(dev, "devm_gpiochip_add_data failed: %d\n", ret);
return ret;
}
return ret;
}
static const struct power_supply_desc sbsm_default_psy_desc = {
.type = POWER_SUPPLY_TYPE_MAINS,
.properties = sbsm_props,
.num_properties = ARRAY_SIZE(sbsm_props),
.get_property = &sbsm_get_property,
.set_property = &sbsm_set_property,
.property_is_writeable = &sbsm_prop_is_writeable,
};
static int sbsm_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct sbsm_data *data;
struct device *dev = &client->dev;
struct power_supply_desc *psy_desc;
struct power_supply_config psy_cfg = {};
int ret = 0, i;
/* Device listens only at address 0x0a */
if (client->addr != 0x0a)
return -EINVAL;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
return -EPFNOSUPPORT;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
i2c_set_clientdata(client, data);
data->client = client;
data->is_ltc1760 = !!strstr(id->name, "ltc1760");
ret = sbsm_read_word(client, SBSM_CMD_BATSYSINFO);
if (ret < 0)
return ret;
data->supported_bats = ret & SBSM_MASK_BAT_SUPPORTED;
data->muxc = i2c_mux_alloc(adapter, dev, SBSM_MAX_BATS, 0,
I2C_MUX_LOCKED, &sbsm_select, NULL);
if (!data->muxc) {
dev_err(dev, "failed to alloc i2c mux\n");
ret = -ENOMEM;
goto err_mux_alloc;
}
data->muxc->priv = data;
/* register muxed i2c channels. One for each supported battery */
for (i = 0; i < SBSM_MAX_BATS; ++i) {
if (data->supported_bats & BIT(i)) {
ret = i2c_mux_add_adapter(data->muxc, 0, i + 1, 0);
if (ret)
break;
}
}
if (ret) {
dev_err(dev, "failed to register i2c mux channel %d\n", i + 1);
goto err_mux_register;
}
psy_desc = devm_kmemdup(dev, &sbsm_default_psy_desc,
sizeof(struct power_supply_desc),
GFP_KERNEL);
if (!psy_desc) {
ret = -ENOMEM;
goto err_psy;
}
psy_desc->name = devm_kasprintf(dev, GFP_KERNEL, "sbsm-%s",
dev_name(&client->dev));
if (!psy_desc->name) {
ret = -ENOMEM;
goto err_psy;
}
ret = sbsm_gpio_setup(data);
if (ret < 0)
goto err_psy;
psy_cfg.drv_data = data;
psy_cfg.of_node = dev->of_node;
data->psy = devm_power_supply_register(dev, psy_desc, &psy_cfg);
if (IS_ERR(data->psy)) {
ret = PTR_ERR(data->psy);
dev_err(dev, "failed to register power supply %s\n",
psy_desc->name);
goto err_psy;
}
return 0;
err_psy:
err_mux_register:
i2c_mux_del_adapters(data->muxc);
err_mux_alloc:
return ret;
}
static int sbsm_remove(struct i2c_client *client)
{
struct sbsm_data *data = i2c_get_clientdata(client);
i2c_mux_del_adapters(data->muxc);
return 0;
}
static const struct i2c_device_id sbsm_ids[] = {
{ "sbs-manager", 0 },
{ "ltc1760", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, sbsm_ids);
#ifdef CONFIG_OF
static const struct of_device_id sbsm_dt_ids[] = {
{ .compatible = "sbs,sbs-manager" },
{ .compatible = "lltc,ltc1760" },
{ }
};
MODULE_DEVICE_TABLE(of, sbsm_dt_ids);
#endif
static struct i2c_driver sbsm_driver = {
.driver = {
.name = "sbsm",
.of_match_table = of_match_ptr(sbsm_dt_ids),
},
.probe = sbsm_probe,
.remove = sbsm_remove,
.alert = sbsm_alert,
.id_table = sbsm_ids
};
module_i2c_driver(sbsm_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Karl-Heinz Schneider <karl-heinz@schneider-inet.de>");
MODULE_DESCRIPTION("SBSM Smart Battery System Manager");

View File

@ -29,6 +29,7 @@ struct gpio_descs {
#define GPIOD_FLAGS_BIT_DIR_SET BIT(0)
#define GPIOD_FLAGS_BIT_DIR_OUT BIT(1)
#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
@ -40,6 +41,11 @@ enum gpiod_flags {
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_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

View File

@ -12,8 +12,6 @@
/**
* 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
* @timeout: clock stretching timeout in jiffies. If the slave keeps
* SCL low for longer than this, the transfer will time out.
@ -26,8 +24,6 @@
* @scl_is_output_only: SCL output drivers cannot be turned off.
*/
struct i2c_gpio_platform_data {
unsigned int sda_pin;
unsigned int scl_pin;
int udelay;
int timeout;
unsigned int sda_is_open_drain:1;

View File

@ -42,7 +42,6 @@
* properly set.
*/
struct i2c_smbus_alert_setup {
unsigned int alert_edge_triggered:1;
int irq;
};
@ -50,4 +49,13 @@ struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter,
struct i2c_smbus_alert_setup *setup);
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 */

View File

@ -304,6 +304,7 @@ static inline bool i2c_detect_slave_mode(struct device *dev) { return false; }
* @type: chip type, to initialize i2c_client.name
* @flags: to initialize i2c_client.flags
* @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
* @archdata: copied into i2c_client.dev.archdata
* @of_node: pointer to OpenFirmware device node
@ -328,6 +329,7 @@ struct i2c_board_info {
char type[I2C_NAME_SIZE];
unsigned short flags;
unsigned short addr;
const char *dev_name;
void *platform_data;
struct dev_archdata *archdata;
struct device_node *of_node;

View File

@ -1,10 +0,0 @@
/* 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 */