Merge branch 'i2c/for-4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang: - mainly feature additions to drivers (stm32f7, qup, xlp9xx, mlxcpld, ...) - conversion to use the i2c_8bit_addr_from_msg macro consistently - move includes to platform_data - core updates to allow the (still in review) I3C subsystem to connect - and the regular share of smaller driver updates * 'i2c/for-4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (68 commits) i2c: qup: fix building without CONFIG_ACPI i2c: tegra: Remove suspend-resume i2c: imx-lpi2c: Switch to SPDX identifier i2c: mxs: Switch to SPDX identifier i2c: busses: make use of i2c_8bit_addr_from_msg i2c: algos: make use of i2c_8bit_addr_from_msg i2c: rcar: document R8A77980 bindings i2c: qup: Add command-line parameter to override SCL frequency i2c: qup: Correct duty cycle for FM and FM+ i2c: qup: Add support for Fast Mode Plus i2c: qup: add probe path for Centriq ACPI devices i2c: robotfuzz-osif: drop pointless test i2c: robotfuzz-osif: remove pointless local variable i2c: rk3x: Don't print visible virtual mapping MMIO address i2c: opal: don't check number of messages in the driver i2c: ibm_iic: don't check number of messages in the driver i2c: imx: Switch to SPDX identifier i2c: mux: pca954x: merge calls to of_match_device and of_device_get_match_data i2c: mux: demux-pinctrl: use proper parent device for demux adapter i2c: mux: improve error message for failed symlink ...
This commit is contained in:
commit
9bca19a01d
|
@ -24,7 +24,7 @@ Recommended properties :
|
|||
- clock-frequency : desired I2C bus clock frequency in Hz.
|
||||
- ti,has-pfunc: boolean; if defined, it indicates that SoC supports PFUNC
|
||||
registers. PFUNC registers allow to switch I2C pins to function as
|
||||
GPIOs, so they can by toggled manually.
|
||||
GPIOs, so they can be toggled manually.
|
||||
|
||||
Example (enbw_cmc board):
|
||||
i2c@1c22000 {
|
||||
|
|
|
@ -15,6 +15,7 @@ Required properties:
|
|||
"renesas,i2c-r8a7796" if the device is a part of a R8A7796 SoC.
|
||||
"renesas,i2c-r8a77965" if the device is a part of a R8A77965 SoC.
|
||||
"renesas,i2c-r8a77970" if the device is a part of a R8A77970 SoC.
|
||||
"renesas,i2c-r8a77980" if the device is a part of a R8A77980 SoC.
|
||||
"renesas,i2c-r8a77995" if the device is a part of a R8A77995 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
|
||||
|
|
|
@ -8,9 +8,7 @@ Required properties:
|
|||
(b) "samsung, s3c2440-i2c", for i2c compatible with s3c2440 i2c.
|
||||
(c) "samsung, s3c2440-hdmiphy-i2c", for s3c2440-like i2c used
|
||||
inside HDMIPHY block found on several samsung SoCs
|
||||
(d) "samsung, exynos5440-i2c", for s3c2440-like i2c used
|
||||
on EXYNOS5440 which does not need GPIO configuration.
|
||||
(e) "samsung, exynos5-sata-phy-i2c", for s3c2440-like i2c used as
|
||||
(d) "samsung, exynos5-sata-phy-i2c", for s3c2440-like i2c used as
|
||||
a host to SATA PHY controller on an internal bus.
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
|
|
|
@ -20,6 +20,10 @@ The next transaction types are supported:
|
|||
- Write Byte/Block.
|
||||
|
||||
Registers:
|
||||
CPBLTY 0x0 - capability reg.
|
||||
Bits [6:5] - transaction length. b01 - 72B is supported,
|
||||
36B in other case.
|
||||
Bit 7 - SMBus block read support.
|
||||
CTRL 0x1 - control reg.
|
||||
Resets all the registers.
|
||||
HALF_CYC 0x4 - cycle reg.
|
||||
|
|
|
@ -18,7 +18,7 @@ Usage
|
|||
i2c-ocores uses the platform bus, so you need to provide a struct
|
||||
platform_device with the base address and interrupt number. The
|
||||
dev.platform_data of the device should also point to a struct
|
||||
ocores_i2c_platform_data (see linux/i2c-ocores.h) describing the
|
||||
ocores_i2c_platform_data (see linux/platform_data/i2c-ocores.h) describing the
|
||||
distance between registers and the input clock speed.
|
||||
There is also a possibility to attach a list of i2c_board_info which
|
||||
the i2c-ocores driver will add to the bus upon creation.
|
||||
|
|
|
@ -30,12 +30,12 @@ i2c-mux-gpio uses the platform bus, so you need to provide a struct
|
|||
platform_device with the platform_data pointing to a struct
|
||||
i2c_mux_gpio_platform_data with the I2C adapter number of the master
|
||||
bus, the number of bus segments to create and the GPIO pins used
|
||||
to control it. See include/linux/i2c-mux-gpio.h for details.
|
||||
to control it. See include/linux/platform_data/i2c-mux-gpio.h for details.
|
||||
|
||||
E.G. something like this for a MUX providing 4 bus segments
|
||||
controlled through 3 GPIO pins:
|
||||
|
||||
#include <linux/i2c-mux-gpio.h>
|
||||
#include <linux/platform_data/i2c-mux-gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
static const unsigned myboard_gpiomux_gpios[] = {
|
||||
|
|
|
@ -5953,14 +5953,14 @@ GENERIC GPIO I2C DRIVER
|
|||
M: Haavard Skinnemoen <hskinnemoen@gmail.com>
|
||||
S: Supported
|
||||
F: drivers/i2c/busses/i2c-gpio.c
|
||||
F: include/linux/i2c-gpio.h
|
||||
F: include/linux/platform_data/i2c-gpio.h
|
||||
|
||||
GENERIC GPIO I2C MULTIPLEXER DRIVER
|
||||
M: Peter Korsgaard <peter.korsgaard@barco.com>
|
||||
L: linux-i2c@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/i2c/muxes/i2c-mux-gpio.c
|
||||
F: include/linux/i2c-mux-gpio.h
|
||||
F: include/linux/platform_data/i2c-mux-gpio.h
|
||||
F: Documentation/i2c/muxes/i2c-mux-gpio
|
||||
|
||||
GENERIC HDLC (WAN) DRIVERS
|
||||
|
@ -10392,7 +10392,7 @@ F: arch/arm/mach-omap1/
|
|||
F: arch/arm/plat-omap/
|
||||
F: arch/arm/configs/omap1_defconfig
|
||||
F: drivers/i2c/busses/i2c-omap.c
|
||||
F: include/linux/i2c-omap.h
|
||||
F: include/linux/platform_data/i2c-omap.h
|
||||
|
||||
OMAP2+ SUPPORT
|
||||
M: Tony Lindgren <tony@atomide.com>
|
||||
|
@ -10424,7 +10424,7 @@ F: drivers/regulator/tps65218-regulator.c
|
|||
F: drivers/regulator/tps65910-regulator.c
|
||||
F: drivers/regulator/twl-regulator.c
|
||||
F: drivers/regulator/twl6030-regulator.c
|
||||
F: include/linux/i2c-omap.h
|
||||
F: include/linux/platform_data/i2c-omap.h
|
||||
|
||||
ONION OMEGA2+ BOARD
|
||||
M: Harvey Hunt <harveyhuntnexus@gmail.com>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include <linux/gpio/machine.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
#include <linux/i2c-gpio.h>
|
||||
#include <linux/platform_data/i2c-gpio.h>
|
||||
#include <linux/platform_data/pca953x.h>
|
||||
|
||||
#include <linux/mtd/mtd.h>
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include <linux/gpio.h>
|
||||
#include <linux/gpio_keys.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-gpio.h>
|
||||
#include <linux/platform_data/i2c-gpio.h>
|
||||
#include <linux/htcpld.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#define __ARCH_ARM_MACH_OMAP1_COMMON_H
|
||||
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/i2c-omap.h>
|
||||
#include <linux/platform_data/i2c-omap.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#include <asm/exception.h>
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-omap.h>
|
||||
#include <linux/platform_data/i2c-omap.h>
|
||||
#include <mach/mux.h>
|
||||
#include "soc.h"
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mfd/twl.h>
|
||||
#include <linux/i2c-omap.h>
|
||||
#include <linux/platform_data/i2c-omap.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/irqchip/irq-omap-intc.h>
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* XXX these should be marked initdata for multi-OMAP kernels
|
||||
*/
|
||||
|
||||
#include <linux/i2c-omap.h>
|
||||
#include <linux/platform_data/i2c-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
|
||||
#include "omap_hwmod.h"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* XXX these should be marked initdata for multi-OMAP kernels
|
||||
*/
|
||||
|
||||
#include <linux/i2c-omap.h>
|
||||
#include <linux/platform_data/i2c-omap.h>
|
||||
#include <linux/platform_data/hsmmc-omap.h>
|
||||
#include <linux/omap-dma.h>
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/i2c-omap.h>
|
||||
#include <linux/platform_data/i2c-omap.h>
|
||||
|
||||
#include "omap_hwmod.h"
|
||||
#include "omap_hwmod_common_data.h"
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* XXX these should be marked initdata for multi-OMAP kernels
|
||||
*/
|
||||
|
||||
#include <linux/i2c-omap.h>
|
||||
#include <linux/platform_data/i2c-omap.h>
|
||||
#include <linux/power/smartreflex.h>
|
||||
#include <linux/platform_data/hsmmc-omap.h>
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/platform_data/hsmmc-omap.h>
|
||||
#include <linux/power/smartreflex.h>
|
||||
#include <linux/i2c-omap.h>
|
||||
#include <linux/platform_data/i2c-omap.h>
|
||||
|
||||
#include <linux/omap-dma.h>
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/platform_data/hsmmc-omap.h>
|
||||
#include <linux/power/smartreflex.h>
|
||||
#include <linux/i2c-omap.h>
|
||||
#include <linux/platform_data/i2c-omap.h>
|
||||
|
||||
#include <linux/omap-dma.h>
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/platform_data/hsmmc-omap.h>
|
||||
#include <linux/power/smartreflex.h>
|
||||
#include <linux/i2c-omap.h>
|
||||
#include <linux/platform_data/i2c-omap.h>
|
||||
|
||||
#include <linux/omap-dma.h>
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include <linux/wm97xx.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/usb/gpio_vbus.h>
|
||||
#include <linux/i2c-gpio.h>
|
||||
#include <linux/platform_data/i2c-gpio.h>
|
||||
#include <linux/gpio/machine.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c-gpio.h>
|
||||
#include <linux/platform_data/i2c-gpio.h>
|
||||
#include <linux/gpio/machine.h>
|
||||
#include <linux/platform_data/i2c-pxa.h>
|
||||
#include <linux/serial_8250.h>
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#include <linux/input.h>
|
||||
#include <linux/gpio_keys.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/i2c-gpio.h>
|
||||
#include <linux/platform_data/i2c-gpio.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include <linux/leds.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-gpio.h>
|
||||
#include <linux/platform_data/i2c-gpio.h>
|
||||
#include <linux/gpio/machine.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/idle.h>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-pca-platform.h>
|
||||
#include <linux/platform_data/i2c-pca-platform.h>
|
||||
#include <linux/i2c-algo-pca.h>
|
||||
#include <linux/usb/r8a66597.h>
|
||||
#include <linux/sh_intc.h>
|
||||
|
|
|
@ -519,9 +519,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
|
|||
}
|
||||
}
|
||||
} else { /* normal 7bit address */
|
||||
addr = msg->addr << 1;
|
||||
if (flags & I2C_M_RD)
|
||||
addr |= 1;
|
||||
addr = i2c_8bit_addr_from_msg(msg);
|
||||
if (flags & I2C_M_REV_DIR_ADDR)
|
||||
addr ^= 1;
|
||||
ret = try_address(i2c_adap, addr, retries);
|
||||
|
|
|
@ -112,11 +112,8 @@ static int pca_address(struct i2c_algo_pca_data *adap,
|
|||
struct i2c_msg *msg)
|
||||
{
|
||||
int sta = pca_get_con(adap);
|
||||
int addr;
|
||||
int addr = i2c_8bit_addr_from_msg(msg);
|
||||
|
||||
addr = ((0x7f & msg->addr) << 1);
|
||||
if (msg->flags & I2C_M_RD)
|
||||
addr |= 1;
|
||||
DEB2("=== SLAVE ADDRESS %#04x+%c=%#04x\n",
|
||||
msg->addr, msg->flags & I2C_M_RD ? 'R' : 'W', addr);
|
||||
|
||||
|
|
|
@ -291,13 +291,9 @@ static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf,
|
|||
static int pcf_doAddress(struct i2c_algo_pcf_data *adap,
|
||||
struct i2c_msg *msg)
|
||||
{
|
||||
unsigned short flags = msg->flags;
|
||||
unsigned char addr;
|
||||
unsigned char addr = i2c_8bit_addr_from_msg(msg);
|
||||
|
||||
addr = msg->addr << 1;
|
||||
if (flags & I2C_M_RD)
|
||||
addr |= 1;
|
||||
if (flags & I2C_M_REV_DIR_ADDR)
|
||||
if (msg->flags & I2C_M_REV_DIR_ADDR)
|
||||
addr ^= 1;
|
||||
i2c_outb(adap, addr);
|
||||
|
||||
|
|
|
@ -943,6 +943,7 @@ config I2C_STM32F4
|
|||
config I2C_STM32F7
|
||||
tristate "STMicroelectronics STM32F7 I2C support"
|
||||
depends on ARCH_STM32 || COMPILE_TEST
|
||||
select I2C_SLAVE
|
||||
help
|
||||
Enable this option to add support for STM32 I2C controller embedded
|
||||
in STM32F7 SoCs.
|
||||
|
|
|
@ -94,7 +94,8 @@ obj-$(CONFIG_I2C_SIRF) += i2c-sirf.o
|
|||
obj-$(CONFIG_I2C_SPRD) += i2c-sprd.o
|
||||
obj-$(CONFIG_I2C_ST) += i2c-st.o
|
||||
obj-$(CONFIG_I2C_STM32F4) += i2c-stm32f4.o
|
||||
obj-$(CONFIG_I2C_STM32F7) += i2c-stm32f7.o
|
||||
i2c-stm32f7-drv-objs := i2c-stm32f7.o i2c-stm32.o
|
||||
obj-$(CONFIG_I2C_STM32F7) += i2c-stm32f7-drv.o
|
||||
obj-$(CONFIG_I2C_STU300) += i2c-stu300.o
|
||||
obj-$(CONFIG_I2C_SUN6I_P2WI) += i2c-sun6i-p2wi.o
|
||||
obj-$(CONFIG_I2C_SYNQUACER) += i2c-synquacer.o
|
||||
|
|
|
@ -335,13 +335,12 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
|
|||
{
|
||||
u32 command = ASPEED_I2CD_M_START_CMD | ASPEED_I2CD_M_TX_CMD;
|
||||
struct i2c_msg *msg = &bus->msgs[bus->msgs_index];
|
||||
u8 slave_addr = msg->addr << 1;
|
||||
u8 slave_addr = i2c_8bit_addr_from_msg(msg);
|
||||
|
||||
bus->master_state = ASPEED_I2C_MASTER_START;
|
||||
bus->buf_index = 0;
|
||||
|
||||
if (msg->flags & I2C_M_RD) {
|
||||
slave_addr |= 1;
|
||||
command |= ASPEED_I2CD_M_RX_CMD;
|
||||
/* Need to let the hardware know to NACK after RX. */
|
||||
if (msg->len == 1 && !(msg->flags & I2C_M_RECV_LEN))
|
||||
|
|
|
@ -518,8 +518,16 @@ static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id)
|
|||
* the RXRDY interrupt first in order to not keep garbage data in the
|
||||
* Receive Holding Register for the next transfer.
|
||||
*/
|
||||
if (irqstatus & AT91_TWI_RXRDY)
|
||||
at91_twi_read_next_byte(dev);
|
||||
if (irqstatus & AT91_TWI_RXRDY) {
|
||||
/*
|
||||
* Read all available bytes at once by polling RXRDY usable w/
|
||||
* and w/o FIFO. With FIFO enabled we could also read RXFL and
|
||||
* avoid polling RXRDY.
|
||||
*/
|
||||
do {
|
||||
at91_twi_read_next_byte(dev);
|
||||
} while (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY);
|
||||
}
|
||||
|
||||
/*
|
||||
* When a NACK condition is detected, the I2C controller sets the NACK,
|
||||
|
|
|
@ -351,13 +351,15 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
|
|||
* addr_2: addr[7:0]
|
||||
*/
|
||||
addr_1 = 0xF0 | ((msg->addr >> 7) & 0x06);
|
||||
if (i2c_m_rd(msg))
|
||||
addr_1 |= 1; /* Set the R/nW bit of the address */
|
||||
addr_2 = msg->addr & 0xFF;
|
||||
} else {
|
||||
/* 7-bit address
|
||||
* addr_1: addr[6:0] | (R/nW)
|
||||
* addr_2: dont care
|
||||
*/
|
||||
addr_1 = (msg->addr << 1) & 0xFF;
|
||||
addr_1 = i2c_8bit_addr_from_msg(msg);
|
||||
addr_2 = 0;
|
||||
}
|
||||
|
||||
|
@ -365,7 +367,6 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
|
|||
/* I2C read transfer */
|
||||
rx_xfer = i2c_m_recv_len(msg) ? I2C_SMBUS_BLOCK_MAX : msg->len;
|
||||
tx_xfer = 0;
|
||||
addr_1 |= 1; /* Set the R/nW bit of the address */
|
||||
} else {
|
||||
/* I2C write transfer */
|
||||
rx_xfer = 0;
|
||||
|
@ -532,23 +533,23 @@ static int axxia_i2c_probe(struct platform_device *pdev)
|
|||
if (idev->bus_clk_rate == 0)
|
||||
idev->bus_clk_rate = 100000; /* default clock rate */
|
||||
|
||||
ret = clk_prepare_enable(idev->i2c_clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to enable clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = axxia_i2c_init(idev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to initialize\n");
|
||||
return ret;
|
||||
goto error_disable_clk;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, irq, axxia_i2c_isr, 0,
|
||||
pdev->name, idev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to claim IRQ%d\n", irq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(idev->i2c_clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to enable clock\n");
|
||||
return ret;
|
||||
goto error_disable_clk;
|
||||
}
|
||||
|
||||
i2c_set_adapdata(&idev->adapter, idev);
|
||||
|
@ -563,12 +564,14 @@ static int axxia_i2c_probe(struct platform_device *pdev)
|
|||
platform_set_drvdata(pdev, idev);
|
||||
|
||||
ret = i2c_add_adapter(&idev->adapter);
|
||||
if (ret) {
|
||||
clk_disable_unprepare(idev->i2c_clk);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
goto error_disable_clk;
|
||||
|
||||
return 0;
|
||||
|
||||
error_disable_clk:
|
||||
clk_disable_unprepare(idev->i2c_clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int axxia_i2c_remove(struct platform_device *pdev)
|
||||
|
|
|
@ -149,18 +149,17 @@ u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
|
|||
return ((ic_clk * (tLOW + tf) + 500000) / 1000000) - 1 + offset;
|
||||
}
|
||||
|
||||
void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable)
|
||||
{
|
||||
dw_writel(dev, enable, DW_IC_ENABLE);
|
||||
}
|
||||
|
||||
void __i2c_dw_enable_and_wait(struct dw_i2c_dev *dev, bool enable)
|
||||
void __i2c_dw_disable(struct dw_i2c_dev *dev)
|
||||
{
|
||||
int timeout = 100;
|
||||
|
||||
do {
|
||||
__i2c_dw_enable(dev, enable);
|
||||
if ((dw_readl(dev, DW_IC_ENABLE_STATUS) & 1) == enable)
|
||||
__i2c_dw_disable_nowait(dev);
|
||||
/*
|
||||
* The enable status register may be unimplemented, but
|
||||
* in that case this test reads zero and exits the loop.
|
||||
*/
|
||||
if ((dw_readl(dev, DW_IC_ENABLE_STATUS) & 1) == 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
|
@ -171,8 +170,7 @@ void __i2c_dw_enable_and_wait(struct dw_i2c_dev *dev, bool enable)
|
|||
usleep_range(25, 250);
|
||||
} while (timeout--);
|
||||
|
||||
dev_warn(dev->dev, "timeout in %sabling adapter\n",
|
||||
enable ? "en" : "dis");
|
||||
dev_warn(dev->dev, "timeout in disabling adapter\n");
|
||||
}
|
||||
|
||||
unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev)
|
||||
|
@ -277,7 +275,7 @@ u32 i2c_dw_func(struct i2c_adapter *adap)
|
|||
void i2c_dw_disable(struct dw_i2c_dev *dev)
|
||||
{
|
||||
/* Disable controller */
|
||||
__i2c_dw_enable_and_wait(dev, false);
|
||||
__i2c_dw_disable(dev);
|
||||
|
||||
/* Disable all interupts */
|
||||
dw_writel(dev, 0, DW_IC_INTR_MASK);
|
||||
|
|
|
@ -297,8 +297,6 @@ u32 dw_readl(struct dw_i2c_dev *dev, int offset);
|
|||
void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);
|
||||
u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset);
|
||||
u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset);
|
||||
void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable);
|
||||
void __i2c_dw_enable_and_wait(struct dw_i2c_dev *dev, bool enable);
|
||||
unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev);
|
||||
int i2c_dw_prepare_clk(struct dw_i2c_dev *dev, bool prepare);
|
||||
int i2c_dw_acquire_lock(struct dw_i2c_dev *dev);
|
||||
|
@ -309,6 +307,18 @@ u32 i2c_dw_func(struct i2c_adapter *adap);
|
|||
void i2c_dw_disable(struct dw_i2c_dev *dev);
|
||||
void i2c_dw_disable_int(struct dw_i2c_dev *dev);
|
||||
|
||||
static inline void __i2c_dw_enable(struct dw_i2c_dev *dev)
|
||||
{
|
||||
dw_writel(dev, 1, DW_IC_ENABLE);
|
||||
}
|
||||
|
||||
static inline void __i2c_dw_disable_nowait(struct dw_i2c_dev *dev)
|
||||
{
|
||||
dw_writel(dev, 0, DW_IC_ENABLE);
|
||||
}
|
||||
|
||||
void __i2c_dw_disable(struct dw_i2c_dev *dev);
|
||||
|
||||
extern u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev);
|
||||
extern int i2c_dw_probe(struct dw_i2c_dev *dev);
|
||||
#if IS_ENABLED(CONFIG_I2C_DESIGNWARE_SLAVE)
|
||||
|
|
|
@ -81,7 +81,7 @@ static int i2c_dw_init_master(struct dw_i2c_dev *dev)
|
|||
comp_param1 = dw_readl(dev, DW_IC_COMP_PARAM_1);
|
||||
|
||||
/* Disable the adapter */
|
||||
__i2c_dw_enable_and_wait(dev, false);
|
||||
__i2c_dw_disable(dev);
|
||||
|
||||
/* Set standard and fast speed deviders for high/low periods */
|
||||
|
||||
|
@ -180,7 +180,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
|
|||
u32 ic_con, ic_tar = 0;
|
||||
|
||||
/* Disable the adapter */
|
||||
__i2c_dw_enable_and_wait(dev, false);
|
||||
__i2c_dw_disable(dev);
|
||||
|
||||
/* If the slave address is ten bit address, enable 10BITADDR */
|
||||
ic_con = dw_readl(dev, DW_IC_CON);
|
||||
|
@ -209,7 +209,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
|
|||
i2c_dw_disable_int(dev);
|
||||
|
||||
/* Enable the adapter */
|
||||
__i2c_dw_enable(dev, true);
|
||||
__i2c_dw_enable(dev);
|
||||
|
||||
/* Dummy read to avoid the register getting stuck on Bay Trail */
|
||||
dw_readl(dev, DW_IC_ENABLE_STATUS);
|
||||
|
@ -462,7 +462,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
|
|||
* additional interrupts are a hardware bug or this driver doesn't
|
||||
* handle them correctly yet.
|
||||
*/
|
||||
__i2c_dw_enable(dev, false);
|
||||
__i2c_dw_disable_nowait(dev);
|
||||
|
||||
if (dev->msg_err) {
|
||||
ret = dev->msg_err;
|
||||
|
|
|
@ -75,7 +75,7 @@ static int i2c_dw_init_slave(struct dw_i2c_dev *dev)
|
|||
comp_param1 = dw_readl(dev, DW_IC_COMP_PARAM_1);
|
||||
|
||||
/* Disable the adapter. */
|
||||
__i2c_dw_enable_and_wait(dev, false);
|
||||
__i2c_dw_disable(dev);
|
||||
|
||||
/* Configure SDA Hold Time if required. */
|
||||
reg = dw_readl(dev, DW_IC_COMP_VERSION);
|
||||
|
@ -119,11 +119,11 @@ static int i2c_dw_reg_slave(struct i2c_client *slave)
|
|||
* Set slave address in the IC_SAR register,
|
||||
* the address to which the DW_apb_i2c responds.
|
||||
*/
|
||||
__i2c_dw_enable(dev, false);
|
||||
__i2c_dw_disable_nowait(dev);
|
||||
dw_writel(dev, slave->addr, DW_IC_SAR);
|
||||
dev->slave = slave;
|
||||
|
||||
__i2c_dw_enable(dev, true);
|
||||
__i2c_dw_enable(dev);
|
||||
|
||||
dev->cmd_err = 0;
|
||||
dev->msg_write_idx = 0;
|
||||
|
|
|
@ -360,11 +360,11 @@ static int diolan_usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
|
|||
if (ret < 0)
|
||||
goto abort;
|
||||
}
|
||||
ret = diolan_i2c_put_byte_ack(dev,
|
||||
i2c_8bit_addr_from_msg(pmsg));
|
||||
if (ret < 0)
|
||||
goto abort;
|
||||
if (pmsg->flags & I2C_M_RD) {
|
||||
ret =
|
||||
diolan_i2c_put_byte_ack(dev, (pmsg->addr << 1) | 1);
|
||||
if (ret < 0)
|
||||
goto abort;
|
||||
for (j = 0; j < pmsg->len; j++) {
|
||||
u8 byte;
|
||||
bool ack = j < pmsg->len - 1;
|
||||
|
@ -393,9 +393,6 @@ static int diolan_usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
|
|||
pmsg->buf[j] = byte;
|
||||
}
|
||||
} else {
|
||||
ret = diolan_i2c_put_byte_ack(dev, pmsg->addr << 1);
|
||||
if (ret < 0)
|
||||
goto abort;
|
||||
for (j = 0; j < pmsg->len; j++) {
|
||||
ret = diolan_i2c_put_byte_ack(dev,
|
||||
pmsg->buf[j]);
|
||||
|
|
|
@ -144,8 +144,7 @@ static void efm32_i2c_send_next_msg(struct efm32_i2c_ddata *ddata)
|
|||
struct i2c_msg *cur_msg = &ddata->msgs[ddata->current_msg];
|
||||
|
||||
efm32_i2c_write32(ddata, REG_CMD, REG_CMD_START);
|
||||
efm32_i2c_write32(ddata, REG_TXDATA, cur_msg->addr << 1 |
|
||||
(cur_msg->flags & I2C_M_RD ? 1 : 0));
|
||||
efm32_i2c_write32(ddata, REG_TXDATA, i2c_8bit_addr_from_msg(cur_msg));
|
||||
}
|
||||
|
||||
static void efm32_i2c_send_next_byte(struct efm32_i2c_ddata *ddata)
|
||||
|
|
|
@ -414,7 +414,7 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
|
|||
iowrite32(addr_8_lsb, p + PCH_I2CDR);
|
||||
} else {
|
||||
/* set 7 bit slave address and R/W bit as 0 */
|
||||
iowrite32(addr << 1, p + PCH_I2CDR);
|
||||
iowrite32(i2c_8bit_addr_from_msg(msgs), p + PCH_I2CDR);
|
||||
if (first)
|
||||
pch_i2c_start(adap);
|
||||
}
|
||||
|
@ -538,8 +538,7 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
|
|||
iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
|
||||
} else {
|
||||
/* 7 address bits + R/W bit */
|
||||
addr = (((addr) << 1) | (I2C_RD));
|
||||
iowrite32(addr, p + PCH_I2CDR);
|
||||
iowrite32(i2c_8bit_addr_from_msg(msgs), p + PCH_I2CDR);
|
||||
}
|
||||
|
||||
/* check if it is the first message */
|
||||
|
|
|
@ -149,7 +149,7 @@ static int __em_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
|
|||
em_clear_set_bit(priv, 0, I2C_BIT_STT0, I2C_OFS_IICC0);
|
||||
|
||||
/* Send slave address and R/W type */
|
||||
writeb((msg->addr << 1) | read, priv->base + I2C_OFS_IIC0);
|
||||
writeb(i2c_8bit_addr_from_msg(msg), priv->base + I2C_OFS_IIC0);
|
||||
|
||||
/* Wait for transaction */
|
||||
status = em_i2c_wait_for_event(priv);
|
||||
|
|
|
@ -707,7 +707,7 @@ static int exynos5_i2c_xfer(struct i2c_adapter *adap,
|
|||
struct i2c_msg *msgs, int num)
|
||||
{
|
||||
struct exynos5_i2c *i2c = adap->algo_data;
|
||||
int i = 0, ret = 0, stop = 0;
|
||||
int i, ret;
|
||||
|
||||
if (i2c->suspended) {
|
||||
dev_err(i2c->dev, "HS-I2C is not initialized.\n");
|
||||
|
@ -718,30 +718,15 @@ static int exynos5_i2c_xfer(struct i2c_adapter *adap,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < num; i++, msgs++) {
|
||||
stop = (i == num - 1);
|
||||
|
||||
ret = exynos5_i2c_xfer_msg(i2c, msgs, stop);
|
||||
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
for (i = 0; i < num; ++i) {
|
||||
ret = exynos5_i2c_xfer_msg(i2c, msgs + i, i + 1 == num);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == num) {
|
||||
ret = num;
|
||||
} else {
|
||||
/* Only one message, cannot access the device */
|
||||
if (i == 1)
|
||||
ret = -EREMOTEIO;
|
||||
else
|
||||
ret = i;
|
||||
|
||||
dev_warn(i2c->dev, "xfer message failed\n");
|
||||
}
|
||||
|
||||
out:
|
||||
clk_disable(i2c->clk);
|
||||
return ret;
|
||||
|
||||
return ret ?: num;
|
||||
}
|
||||
|
||||
static u32 exynos5_i2c_func(struct i2c_adapter *adap)
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
#include <linux/i2c-gpio.h>
|
||||
#include <linux/platform_data/i2c-gpio.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
|
|
@ -73,7 +73,6 @@
|
|||
#define I2C_OVER_INTR BIT(0)
|
||||
|
||||
#define HIX5I2C_MAX_FREQ 400000 /* 400k */
|
||||
#define HIX5I2C_READ_OPERATION 0x01
|
||||
|
||||
enum hix5hd2_i2c_state {
|
||||
HIX5I2C_STAT_RW_ERR = -1,
|
||||
|
@ -311,12 +310,8 @@ static void hix5hd2_i2c_message_start(struct hix5hd2_i2c_priv *priv, int stop)
|
|||
hix5hd2_i2c_clr_all_irq(priv);
|
||||
hix5hd2_i2c_enable_irq(priv);
|
||||
|
||||
if (priv->msg->flags & I2C_M_RD)
|
||||
writel_relaxed((priv->msg->addr << 1) | HIX5I2C_READ_OPERATION,
|
||||
priv->regs + HIX5I2C_TXR);
|
||||
else
|
||||
writel_relaxed(priv->msg->addr << 1,
|
||||
priv->regs + HIX5I2C_TXR);
|
||||
writel_relaxed(i2c_8bit_addr_from_msg(priv->msg),
|
||||
priv->regs + HIX5I2C_TXR);
|
||||
|
||||
writel_relaxed(I2C_WRITE | I2C_START, priv->regs + HIX5I2C_COM);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
@ -377,17 +372,7 @@ static int hix5hd2_i2c_xfer(struct i2c_adapter *adap,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (i == num) {
|
||||
ret = num;
|
||||
} else {
|
||||
/* Only one message, cannot access the device */
|
||||
if (i == 1)
|
||||
ret = -EREMOTEIO;
|
||||
else
|
||||
ret = i;
|
||||
|
||||
dev_warn(priv->dev, "xfer message failed\n");
|
||||
}
|
||||
ret = num;
|
||||
|
||||
out:
|
||||
pm_runtime_mark_last_busy(priv->dev);
|
||||
|
@ -471,7 +456,6 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev)
|
|||
goto err_clk;
|
||||
}
|
||||
|
||||
pm_suspend_ignore_children(&pdev->dev, true);
|
||||
pm_runtime_set_autosuspend_delay(priv->dev, MSEC_PER_SEC);
|
||||
pm_runtime_use_autosuspend(priv->dev);
|
||||
pm_runtime_set_active(priv->dev);
|
||||
|
|
|
@ -106,7 +106,7 @@
|
|||
|
||||
#if IS_ENABLED(CONFIG_I2C_MUX_GPIO) && defined CONFIG_DMI
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c-mux-gpio.h>
|
||||
#include <linux/platform_data/i2c-mux-gpio.h>
|
||||
#endif
|
||||
|
||||
/* I801 SMBus address offsets */
|
||||
|
@ -1710,7 +1710,7 @@ static void i801_shutdown(struct pci_dev *dev)
|
|||
pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int i801_suspend(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pci_dev = to_pci_dev(dev);
|
||||
|
@ -1731,8 +1731,7 @@ static int i801_resume(struct device *dev)
|
|||
}
|
||||
#endif
|
||||
|
||||
static UNIVERSAL_DEV_PM_OPS(i801_pm_ops, i801_suspend,
|
||||
i801_resume, NULL);
|
||||
static SIMPLE_DEV_PM_OPS(i801_pm_ops, i801_suspend, i801_resume);
|
||||
|
||||
static struct pci_driver i801_driver = {
|
||||
.name = "i801_smbus",
|
||||
|
|
|
@ -561,9 +561,6 @@ static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
|||
|
||||
DBG2("%d: iic_xfer, %d msg(s)\n", dev->idx, num);
|
||||
|
||||
if (!num)
|
||||
return 0;
|
||||
|
||||
/* Check the sanity of the passed messages.
|
||||
* Uhh, generic i2c layer is more suitable place for such code...
|
||||
*/
|
||||
|
|
|
@ -1,18 +1,8 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* This is i.MX low power i2c controller driver.
|
||||
*
|
||||
* Copyright 2016 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
|
@ -180,15 +170,13 @@ static int lpi2c_imx_start(struct lpi2c_imx_struct *lpi2c_imx,
|
|||
struct i2c_msg *msgs)
|
||||
{
|
||||
unsigned int temp;
|
||||
u8 read;
|
||||
|
||||
temp = readl(lpi2c_imx->base + LPI2C_MCR);
|
||||
temp |= MCR_RRF | MCR_RTF;
|
||||
writel(temp, lpi2c_imx->base + LPI2C_MCR);
|
||||
writel(0x7f00, lpi2c_imx->base + LPI2C_MSR);
|
||||
|
||||
read = msgs->flags & I2C_M_RD;
|
||||
temp = (msgs->addr << 1 | read) | (GEN_START << 8);
|
||||
temp = i2c_8bit_addr_from_msg(msgs) | (GEN_START << 8);
|
||||
writel(temp, lpi2c_imx->base + LPI2C_MTDR);
|
||||
|
||||
return lpi2c_imx_bus_busy(lpi2c_imx);
|
||||
|
|
|
@ -1,16 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2002 Motorola GSG-China
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Author:
|
||||
* Darius Augulis, Teltonika Inc.
|
||||
*
|
||||
|
@ -630,7 +621,7 @@ static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx,
|
|||
* Write slave address.
|
||||
* The first byte must be transmitted by the CPU.
|
||||
*/
|
||||
imx_i2c_write_reg(msgs->addr << 1, i2c_imx, IMX_I2C_I2DR);
|
||||
imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
|
||||
reinit_completion(&i2c_imx->dma->cmd_complete);
|
||||
time_left = wait_for_completion_timeout(
|
||||
&i2c_imx->dma->cmd_complete,
|
||||
|
@ -760,10 +751,10 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
|
|||
int i, result;
|
||||
|
||||
dev_dbg(&i2c_imx->adapter.dev, "<%s> write slave address: addr=0x%x\n",
|
||||
__func__, msgs->addr << 1);
|
||||
__func__, i2c_8bit_addr_from_msg(msgs));
|
||||
|
||||
/* write slave address */
|
||||
imx_i2c_write_reg(msgs->addr << 1, i2c_imx, IMX_I2C_I2DR);
|
||||
imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
|
||||
result = i2c_imx_trx_complete(i2c_imx);
|
||||
if (result)
|
||||
return result;
|
||||
|
@ -796,10 +787,10 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo
|
|||
|
||||
dev_dbg(&i2c_imx->adapter.dev,
|
||||
"<%s> write slave address: addr=0x%x\n",
|
||||
__func__, (msgs->addr << 1) | 0x01);
|
||||
__func__, i2c_8bit_addr_from_msg(msgs));
|
||||
|
||||
/* write slave address */
|
||||
imx_i2c_write_reg((msgs->addr << 1) | 0x01, i2c_imx, IMX_I2C_I2DR);
|
||||
imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
|
||||
result = i2c_imx_trx_complete(i2c_imx);
|
||||
if (result)
|
||||
return result;
|
||||
|
|
|
@ -124,15 +124,14 @@ static int kempld_i2c_process(struct kempld_i2c_data *i2c)
|
|||
/* 10 bit address? */
|
||||
if (i2c->msg->flags & I2C_M_TEN) {
|
||||
addr = 0xf0 | ((i2c->msg->addr >> 7) & 0x6);
|
||||
/* Set read bit if necessary */
|
||||
addr |= (i2c->msg->flags & I2C_M_RD) ? 1 : 0;
|
||||
i2c->state = STATE_ADDR10;
|
||||
} else {
|
||||
addr = (i2c->msg->addr << 1);
|
||||
addr = i2c_8bit_addr_from_msg(i2c->msg);
|
||||
i2c->state = STATE_START;
|
||||
}
|
||||
|
||||
/* Set read bit if necessary */
|
||||
addr |= (i2c->msg->flags & I2C_M_RD) ? 1 : 0;
|
||||
|
||||
kempld_write8(pld, KEMPLD_I2C_DATA, addr);
|
||||
kempld_write8(pld, KEMPLD_I2C_CMD, I2C_CMD_START);
|
||||
|
||||
|
|
|
@ -45,13 +45,16 @@
|
|||
#define MLXCPLD_I2C_VALID_FLAG (I2C_M_RECV_LEN | I2C_M_RD)
|
||||
#define MLXCPLD_I2C_BUS_NUM 1
|
||||
#define MLXCPLD_I2C_DATA_REG_SZ 36
|
||||
#define MLXCPLD_I2C_DATA_SZ_BIT BIT(5)
|
||||
#define MLXCPLD_I2C_DATA_SZ_MASK GENMASK(6, 5)
|
||||
#define MLXCPLD_I2C_SMBUS_BLK_BIT BIT(7)
|
||||
#define MLXCPLD_I2C_MAX_ADDR_LEN 4
|
||||
#define MLXCPLD_I2C_RETR_NUM 2
|
||||
#define MLXCPLD_I2C_XFER_TO 500000 /* usec */
|
||||
#define MLXCPLD_I2C_POLL_TIME 2000 /* usec */
|
||||
|
||||
/* LPC I2C registers */
|
||||
#define MLXCPLD_LPCI2C_LPF_REG 0x0
|
||||
#define MLXCPLD_LPCI2C_CPBLTY_REG 0x0
|
||||
#define MLXCPLD_LPCI2C_CTRL_REG 0x1
|
||||
#define MLXCPLD_LPCI2C_HALF_CYC_REG 0x4
|
||||
#define MLXCPLD_LPCI2C_I2C_HOLD_REG 0x5
|
||||
|
@ -83,6 +86,7 @@ struct mlxcpld_i2c_priv {
|
|||
struct mutex lock;
|
||||
struct mlxcpld_i2c_curr_xfer xfer;
|
||||
struct device *dev;
|
||||
bool smbus_block;
|
||||
};
|
||||
|
||||
static void mlxcpld_i2c_lpc_write_buf(u8 *data, u8 len, u32 addr)
|
||||
|
@ -230,7 +234,7 @@ static void mlxcpld_i2c_set_transf_data(struct mlxcpld_i2c_priv *priv,
|
|||
* All upper layers currently are never use transfer with more than
|
||||
* 2 messages. Actually, it's also not so relevant in Mellanox systems
|
||||
* because of HW limitation. Max size of transfer is not more than 32
|
||||
* bytes in the current x86 LPCI2C bridge.
|
||||
* or 68 bytes in the current x86 LPCI2C bridge.
|
||||
*/
|
||||
priv->xfer.cmd = msgs[num - 1].flags & I2C_M_RD;
|
||||
|
||||
|
@ -295,7 +299,7 @@ static int mlxcpld_i2c_wait_for_free(struct mlxcpld_i2c_priv *priv)
|
|||
static int mlxcpld_i2c_wait_for_tc(struct mlxcpld_i2c_priv *priv)
|
||||
{
|
||||
int status, i, timeout = 0;
|
||||
u8 datalen;
|
||||
u8 datalen, val;
|
||||
|
||||
do {
|
||||
usleep_range(MLXCPLD_I2C_POLL_TIME / 2, MLXCPLD_I2C_POLL_TIME);
|
||||
|
@ -324,9 +328,22 @@ static int mlxcpld_i2c_wait_for_tc(struct mlxcpld_i2c_priv *priv)
|
|||
* Actual read data len will be always the same as
|
||||
* requested len. 0xff (line pull-up) will be returned
|
||||
* if slave has no data to return. Thus don't read
|
||||
* MLXCPLD_LPCI2C_NUM_DAT_REG reg from CPLD.
|
||||
* MLXCPLD_LPCI2C_NUM_DAT_REG reg from CPLD. Only in case of
|
||||
* SMBus block read transaction data len can be different,
|
||||
* check this case.
|
||||
*/
|
||||
datalen = priv->xfer.data_len;
|
||||
mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_NUM_ADDR_REG, &val,
|
||||
1);
|
||||
if (priv->smbus_block && (val & MLXCPLD_I2C_SMBUS_BLK_BIT)) {
|
||||
mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_NUM_DAT_REG,
|
||||
&datalen, 1);
|
||||
if (unlikely(datalen > (I2C_SMBUS_BLOCK_MAX + 1))) {
|
||||
dev_err(priv->dev, "Incorrect smbus block read message len\n");
|
||||
return -E2BIG;
|
||||
}
|
||||
} else {
|
||||
datalen = priv->xfer.data_len;
|
||||
}
|
||||
|
||||
mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_DATA_REG,
|
||||
priv->xfer.msg[i].buf, datalen);
|
||||
|
@ -344,12 +361,20 @@ static int mlxcpld_i2c_wait_for_tc(struct mlxcpld_i2c_priv *priv)
|
|||
static void mlxcpld_i2c_xfer_msg(struct mlxcpld_i2c_priv *priv)
|
||||
{
|
||||
int i, len = 0;
|
||||
u8 cmd;
|
||||
u8 cmd, val;
|
||||
|
||||
mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_NUM_DAT_REG,
|
||||
&priv->xfer.data_len, 1);
|
||||
mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_NUM_ADDR_REG,
|
||||
&priv->xfer.addr_width, 1);
|
||||
|
||||
val = priv->xfer.addr_width;
|
||||
/* Notify HW about SMBus block read transaction */
|
||||
if (priv->smbus_block && priv->xfer.msg_num >= 2 &&
|
||||
priv->xfer.msg[1].len == 1 &&
|
||||
(priv->xfer.msg[1].flags & I2C_M_RECV_LEN) &&
|
||||
(priv->xfer.msg[1].flags & I2C_M_RD))
|
||||
val |= MLXCPLD_I2C_SMBUS_BLK_BIT;
|
||||
|
||||
mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_NUM_ADDR_REG, &val, 1);
|
||||
|
||||
for (i = 0; i < priv->xfer.msg_num; i++) {
|
||||
if ((priv->xfer.msg[i].flags & I2C_M_RD) != I2C_M_RD) {
|
||||
|
@ -425,7 +450,14 @@ static int mlxcpld_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
|
|||
|
||||
static u32 mlxcpld_i2c_func(struct i2c_adapter *adap)
|
||||
{
|
||||
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA;
|
||||
struct mlxcpld_i2c_priv *priv = i2c_get_adapdata(adap);
|
||||
|
||||
if (priv->smbus_block)
|
||||
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
|
||||
I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_BLOCK_DATA;
|
||||
else
|
||||
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
|
||||
I2C_FUNC_SMBUS_I2C_BLOCK;
|
||||
}
|
||||
|
||||
static const struct i2c_algorithm mlxcpld_i2c_algo = {
|
||||
|
@ -440,6 +472,13 @@ static const struct i2c_adapter_quirks mlxcpld_i2c_quirks = {
|
|||
.max_comb_1st_msg_len = 4,
|
||||
};
|
||||
|
||||
static const struct i2c_adapter_quirks mlxcpld_i2c_quirks_ext = {
|
||||
.flags = I2C_AQ_COMB_WRITE_THEN_READ,
|
||||
.max_read_len = MLXCPLD_I2C_DATA_REG_SZ * 2 - MLXCPLD_I2C_MAX_ADDR_LEN,
|
||||
.max_write_len = MLXCPLD_I2C_DATA_REG_SZ * 2,
|
||||
.max_comb_1st_msg_len = 4,
|
||||
};
|
||||
|
||||
static struct i2c_adapter mlxcpld_i2c_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "i2c-mlxcpld",
|
||||
|
@ -454,6 +493,7 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct mlxcpld_i2c_priv *priv;
|
||||
int err;
|
||||
u8 val;
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
|
@ -466,6 +506,16 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev)
|
|||
|
||||
/* Register with i2c layer */
|
||||
mlxcpld_i2c_adapter.timeout = usecs_to_jiffies(MLXCPLD_I2C_XFER_TO);
|
||||
/* Read capability register */
|
||||
mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_CPBLTY_REG, &val, 1);
|
||||
/* Check support for extended transaction length */
|
||||
if ((val & MLXCPLD_I2C_DATA_SZ_MASK) == MLXCPLD_I2C_DATA_SZ_BIT)
|
||||
mlxcpld_i2c_adapter.quirks = &mlxcpld_i2c_quirks_ext;
|
||||
/* Check support for smbus block transaction */
|
||||
if (val & MLXCPLD_I2C_SMBUS_BLK_BIT)
|
||||
priv->smbus_block = true;
|
||||
if (pdev->id >= -1)
|
||||
mlxcpld_i2c_adapter.nr = pdev->id;
|
||||
priv->adap = mlxcpld_i2c_adapter;
|
||||
priv->adap.dev.parent = &pdev->dev;
|
||||
priv->base_addr = MLXPLAT_CPLD_LPC_I2C_BASE_ADDR;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/mm.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/scatterlist.h>
|
||||
|
@ -734,7 +735,6 @@ static int mtk_i2c_parse_dt(struct device_node *np, struct mtk_i2c *i2c)
|
|||
|
||||
static int mtk_i2c_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct of_device_id *of_id;
|
||||
int ret = 0;
|
||||
struct mtk_i2c *i2c;
|
||||
struct clk *clk;
|
||||
|
@ -761,11 +761,7 @@ static int mtk_i2c_probe(struct platform_device *pdev)
|
|||
|
||||
init_completion(&i2c->msg_complete);
|
||||
|
||||
of_id = of_match_node(mtk_i2c_of_match, pdev->dev.of_node);
|
||||
if (!of_id)
|
||||
return -EINVAL;
|
||||
|
||||
i2c->dev_comp = of_id->data;
|
||||
i2c->dev_comp = of_device_get_match_data(&pdev->dev);
|
||||
i2c->adap.dev.of_node = pdev->dev.of_node;
|
||||
i2c->dev = &pdev->dev;
|
||||
i2c->adap.dev.parent = &pdev->dev;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Freescale MXS I2C bus driver
|
||||
*
|
||||
|
@ -7,12 +8,6 @@
|
|||
* based on a (non-working) driver which was:
|
||||
*
|
||||
* Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
@ -180,9 +175,10 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
|
|||
struct dma_async_tx_descriptor *desc;
|
||||
struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
|
||||
|
||||
i2c->addr_data = i2c_8bit_addr_from_msg(msg);
|
||||
|
||||
if (msg->flags & I2C_M_RD) {
|
||||
i2c->dma_read = true;
|
||||
i2c->addr_data = (msg->addr << 1) | I2C_SMBUS_READ;
|
||||
|
||||
/*
|
||||
* SELECT command.
|
||||
|
@ -240,7 +236,6 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
|
|||
}
|
||||
} else {
|
||||
i2c->dma_read = false;
|
||||
i2c->addr_data = (msg->addr << 1) | I2C_SMBUS_WRITE;
|
||||
|
||||
/*
|
||||
* WRITE command.
|
||||
|
@ -371,7 +366,7 @@ static int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap,
|
|||
struct i2c_msg *msg, uint32_t flags)
|
||||
{
|
||||
struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
|
||||
uint32_t addr_data = msg->addr << 1;
|
||||
uint32_t addr_data = i2c_8bit_addr_from_msg(msg);
|
||||
uint32_t data = 0;
|
||||
int i, ret, xlen = 0, xmit = 0;
|
||||
uint32_t start;
|
||||
|
@ -411,8 +406,6 @@ static int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap,
|
|||
*/
|
||||
BUG_ON(msg->len > 4);
|
||||
|
||||
addr_data |= I2C_SMBUS_READ;
|
||||
|
||||
/* SELECT command. */
|
||||
mxs_i2c_pio_trigger_write_cmd(i2c, MXS_CMD_I2C_SELECT,
|
||||
addr_data);
|
||||
|
@ -450,7 +443,6 @@ static int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap,
|
|||
* fast enough. It is possible to transfer arbitrary amount
|
||||
* of data using PIO write.
|
||||
*/
|
||||
addr_data |= I2C_SMBUS_WRITE;
|
||||
|
||||
/*
|
||||
* The LSB of data buffer is the first byte blasted across
|
||||
|
|
|
@ -1012,8 +1012,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
goto err_no_mem;
|
||||
}
|
||||
|
||||
pm_suspend_ignore_children(&adev->dev, true);
|
||||
|
||||
dev->clk = devm_clk_get(&adev->dev, NULL);
|
||||
if (IS_ERR(dev->clk)) {
|
||||
dev_err(&adev->dev, "could not get i2c clock\n");
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/i2c-ocores.h>
|
||||
#include <linux/platform_data/i2c-ocores.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/log2.h>
|
||||
|
@ -222,10 +222,7 @@ static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
|||
i2c->nmsgs = num;
|
||||
i2c->state = STATE_START;
|
||||
|
||||
oc_setreg(i2c, OCI2C_DATA,
|
||||
(i2c->msg->addr << 1) |
|
||||
((i2c->msg->flags & I2C_M_RD) ? 1:0));
|
||||
|
||||
oc_setreg(i2c, OCI2C_DATA, i2c_8bit_addr_from_msg(i2c->msg));
|
||||
oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START);
|
||||
|
||||
if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) ||
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c-omap.h>
|
||||
#include <linux/platform_data/i2c-omap.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
|
||||
|
|
|
@ -94,8 +94,6 @@ static int i2c_opal_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
|
|||
*/
|
||||
memset(&req, 0, sizeof(req));
|
||||
switch(num) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
req.type = (msgs[0].flags & I2C_M_RD) ?
|
||||
OPAL_I2C_RAW_READ : OPAL_I2C_RAW_WRITE;
|
||||
|
@ -114,8 +112,6 @@ static int i2c_opal_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
|
|||
req.size = cpu_to_be32(msgs[1].len);
|
||||
req.buffer_ra = cpu_to_be64(__pa(msgs[1].buf));
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
rc = i2c_opal_send_request(opal_id, &req);
|
||||
|
|
|
@ -121,7 +121,7 @@ static int pasemi_i2c_xfer_msg(struct i2c_adapter *adapter,
|
|||
|
||||
read = msg->flags & I2C_M_RD ? 1 : 0;
|
||||
|
||||
TXFIFO_WR(smbus, MTXFIFO_START | (msg->addr << 1) | read);
|
||||
TXFIFO_WR(smbus, MTXFIFO_START | i2c_8bit_addr_from_msg(msg));
|
||||
|
||||
if (read) {
|
||||
TXFIFO_WR(smbus, msg->len | MTXFIFO_READ |
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c-algo-pca.h>
|
||||
#include <linux/i2c-pca-platform.h>
|
||||
#include <linux/platform_data/i2c-pca-platform.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/io.h>
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include <linux/timer.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c-pnx.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
|
@ -29,6 +28,26 @@
|
|||
#define I2C_PNX_SPEED_KHZ_DEFAULT 100
|
||||
#define I2C_PNX_REGION_SIZE 0x100
|
||||
|
||||
struct i2c_pnx_mif {
|
||||
int ret; /* Return value */
|
||||
int mode; /* Interface mode */
|
||||
struct completion complete; /* I/O completion */
|
||||
struct timer_list timer; /* Timeout */
|
||||
u8 * buf; /* Data buffer */
|
||||
int len; /* Length of data buffer */
|
||||
int order; /* RX Bytes to order via TX */
|
||||
};
|
||||
|
||||
struct i2c_pnx_algo_data {
|
||||
void __iomem *ioaddr;
|
||||
struct i2c_pnx_mif mif;
|
||||
int last;
|
||||
struct clk *clk;
|
||||
struct i2c_adapter adapter;
|
||||
int irq;
|
||||
u32 timeout;
|
||||
};
|
||||
|
||||
enum {
|
||||
mstatus_tdi = 0x00000001,
|
||||
mstatus_afi = 0x00000002,
|
||||
|
|
|
@ -136,8 +136,13 @@
|
|||
*/
|
||||
#define TOUT_MIN 2
|
||||
|
||||
/* I2C Frequency Modes */
|
||||
#define I2C_STANDARD_FREQ 100000
|
||||
#define I2C_FAST_MODE_FREQ 400000
|
||||
#define I2C_FAST_MODE_PLUS_FREQ 1000000
|
||||
|
||||
/* Default values. Use these if FW query fails */
|
||||
#define DEFAULT_CLK_FREQ 100000
|
||||
#define DEFAULT_CLK_FREQ I2C_STANDARD_FREQ
|
||||
#define DEFAULT_SRC_CLK 20000000
|
||||
|
||||
/*
|
||||
|
@ -150,6 +155,10 @@
|
|||
/* TAG length for DATA READ in RX FIFO */
|
||||
#define READ_RX_TAGS_LEN 2
|
||||
|
||||
static unsigned int scl_freq;
|
||||
module_param_named(scl_freq, scl_freq, uint, 0444);
|
||||
MODULE_PARM_DESC(scl_freq, "SCL frequency override");
|
||||
|
||||
/*
|
||||
* count: no of blocks
|
||||
* pos: current block number
|
||||
|
@ -453,7 +462,7 @@ static void qup_i2c_write_tx_fifo_v1(struct qup_i2c_dev *qup)
|
|||
{
|
||||
struct qup_i2c_block *blk = &qup->blk;
|
||||
struct i2c_msg *msg = qup->msg;
|
||||
u32 addr = msg->addr << 1;
|
||||
u32 addr = i2c_8bit_addr_from_msg(msg);
|
||||
u32 qup_tag;
|
||||
int idx;
|
||||
u32 val;
|
||||
|
@ -1648,6 +1657,12 @@ static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup)
|
|||
clk_disable_unprepare(qup->pclk);
|
||||
}
|
||||
|
||||
static const struct acpi_device_id qup_i2c_acpi_match[] = {
|
||||
{ "QCOM8010"},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, qup_i2c_acpi_match);
|
||||
|
||||
static int qup_i2c_probe(struct platform_device *pdev)
|
||||
{
|
||||
static const int blk_sizes[] = {4, 16, 32};
|
||||
|
@ -1669,10 +1684,15 @@ static int qup_i2c_probe(struct platform_device *pdev)
|
|||
init_completion(&qup->xfer);
|
||||
platform_set_drvdata(pdev, qup);
|
||||
|
||||
ret = device_property_read_u32(qup->dev, "clock-frequency", &clk_freq);
|
||||
if (ret) {
|
||||
dev_notice(qup->dev, "using default clock-frequency %d",
|
||||
DEFAULT_CLK_FREQ);
|
||||
if (scl_freq) {
|
||||
dev_notice(qup->dev, "Using override frequency of %u\n", scl_freq);
|
||||
clk_freq = scl_freq;
|
||||
} else {
|
||||
ret = device_property_read_u32(qup->dev, "clock-frequency", &clk_freq);
|
||||
if (ret) {
|
||||
dev_notice(qup->dev, "using default clock-frequency %d",
|
||||
DEFAULT_CLK_FREQ);
|
||||
}
|
||||
}
|
||||
|
||||
if (of_device_is_compatible(pdev->dev.of_node, "qcom,i2c-qup-v1.1.1")) {
|
||||
|
@ -1682,7 +1702,10 @@ static int qup_i2c_probe(struct platform_device *pdev)
|
|||
} else {
|
||||
qup->adap.algo = &qup_i2c_algo_v2;
|
||||
is_qup_v1 = false;
|
||||
ret = qup_i2c_req_dma(qup);
|
||||
if (acpi_match_device(qup_i2c_acpi_match, qup->dev))
|
||||
goto nodma;
|
||||
else
|
||||
ret = qup_i2c_req_dma(qup);
|
||||
|
||||
if (ret == -EPROBE_DEFER)
|
||||
goto fail_dma;
|
||||
|
@ -1734,8 +1757,8 @@ static int qup_i2c_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
nodma:
|
||||
/* We support frequencies up to FAST Mode (400KHz) */
|
||||
if (!clk_freq || clk_freq > 400000) {
|
||||
/* We support frequencies up to FAST Mode Plus (1MHz) */
|
||||
if (!clk_freq || clk_freq > I2C_FAST_MODE_PLUS_FREQ) {
|
||||
dev_err(qup->dev, "clock frequency not supported %d\n",
|
||||
clk_freq);
|
||||
return -EINVAL;
|
||||
|
@ -1839,9 +1862,15 @@ static int qup_i2c_probe(struct platform_device *pdev)
|
|||
size = QUP_INPUT_FIFO_SIZE(io_mode);
|
||||
qup->in_fifo_sz = qup->in_blk_sz * (2 << size);
|
||||
|
||||
fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
|
||||
hs_div = 3;
|
||||
qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff);
|
||||
if (clk_freq <= I2C_STANDARD_FREQ) {
|
||||
fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
|
||||
qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff);
|
||||
} else {
|
||||
/* 33%/66% duty cycle */
|
||||
fs_div = ((src_clk_freq / clk_freq) - 6) * 2 / 3;
|
||||
qup->clk_ctl = ((fs_div / 2) << 16) | (hs_div << 8) | (fs_div & 0xff);
|
||||
}
|
||||
|
||||
/*
|
||||
* Time it takes for a byte to be clocked out on the bus.
|
||||
|
@ -1959,14 +1988,6 @@ static const struct of_device_id qup_i2c_dt_match[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(of, qup_i2c_dt_match);
|
||||
|
||||
#if IS_ENABLED(CONFIG_ACPI)
|
||||
static const struct acpi_device_id qup_i2c_acpi_match[] = {
|
||||
{ "QCOM8010"},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, qup_i2c_acpi_match);
|
||||
#endif
|
||||
|
||||
static struct platform_driver qup_i2c_driver = {
|
||||
.probe = qup_i2c_probe,
|
||||
.remove = qup_i2c_remove,
|
||||
|
|
|
@ -329,7 +329,7 @@ static void rcar_i2c_prepare_msg(struct rcar_i2c_priv *priv)
|
|||
if (priv->msgs_left == 1)
|
||||
priv->flags |= ID_LAST_MSG;
|
||||
|
||||
rcar_i2c_write(priv, ICMAR, (priv->msg->addr << 1) | read);
|
||||
rcar_i2c_write(priv, ICMAR, i2c_8bit_addr_from_msg(priv->msg));
|
||||
/*
|
||||
* We don't have a test case but the HW engineers say that the write order
|
||||
* of ICMSR and ICMCR depends on whether we issue START or REP_START. Since
|
||||
|
@ -542,6 +542,8 @@ static void rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
|
|||
* If next received data is the _LAST_, go to STOP phase. Might be
|
||||
* overwritten by REP START when setting up a new msg. Not elegant
|
||||
* but the only stable sequence for REP START I have found so far.
|
||||
* If you want to change this code, make sure sending one transfer with
|
||||
* four messages (WR-RD-WR-RD) works!
|
||||
*/
|
||||
if (priv->pos + 1 >= msg->len)
|
||||
rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP);
|
||||
|
|
|
@ -167,15 +167,14 @@ static irqreturn_t riic_tdre_isr(int irq, void *data)
|
|||
return IRQ_NONE;
|
||||
|
||||
if (riic->bytes_left == RIIC_INIT_MSG) {
|
||||
val = !!(riic->msg->flags & I2C_M_RD);
|
||||
if (val)
|
||||
if (riic->msg->flags & I2C_M_RD)
|
||||
/* On read, switch over to receive interrupt */
|
||||
riic_clear_set_bit(riic, ICIER_TIE, ICIER_RIE, RIIC_ICIER);
|
||||
else
|
||||
/* On write, initialize length */
|
||||
riic->bytes_left = riic->msg->len;
|
||||
|
||||
val |= (riic->msg->addr << 1);
|
||||
val = i2c_8bit_addr_from_msg(riic->msg);
|
||||
} else {
|
||||
val = *riic->buf;
|
||||
riic->buf++;
|
||||
|
|
|
@ -1326,8 +1326,6 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
|
|||
if (ret < 0)
|
||||
goto err_clk_notifier;
|
||||
|
||||
dev_info(&pdev->dev, "Initialized RK3xxx I2C bus at %p\n", i2c->regs);
|
||||
|
||||
return 0;
|
||||
|
||||
err_clk_notifier:
|
||||
|
|
|
@ -62,27 +62,24 @@ static int osif_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
|
|||
{
|
||||
struct osif_priv *priv = adapter->algo_data;
|
||||
struct i2c_msg *pmsg;
|
||||
int ret = 0;
|
||||
int i, cmd;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
for (i = 0; ret >= 0 && i < num; i++) {
|
||||
for (i = 0; i < num; i++) {
|
||||
pmsg = &msgs[i];
|
||||
|
||||
if (pmsg->flags & I2C_M_RD) {
|
||||
cmd = OSIFI2C_READ;
|
||||
|
||||
ret = osif_usb_read(adapter, cmd, pmsg->flags,
|
||||
pmsg->addr, pmsg->buf,
|
||||
pmsg->len);
|
||||
ret = osif_usb_read(adapter, OSIFI2C_READ,
|
||||
pmsg->flags, pmsg->addr,
|
||||
pmsg->buf, pmsg->len);
|
||||
if (ret != pmsg->len) {
|
||||
dev_err(&adapter->dev, "failure reading data\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
} else {
|
||||
cmd = OSIFI2C_WRITE;
|
||||
|
||||
ret = osif_usb_write(adapter, cmd, pmsg->flags,
|
||||
pmsg->addr, pmsg->buf, pmsg->len);
|
||||
ret = osif_usb_write(adapter, OSIFI2C_WRITE,
|
||||
pmsg->flags, pmsg->addr,
|
||||
pmsg->buf, pmsg->len);
|
||||
if (ret != pmsg->len) {
|
||||
dev_err(&adapter->dev, "failure writing data\n");
|
||||
return -EREMOTEIO;
|
||||
|
|
|
@ -154,8 +154,6 @@ static const struct of_device_id s3c24xx_i2c_match[] = {
|
|||
{ .compatible = "samsung,s3c2440-i2c", .data = (void *)QUIRK_S3C2440 },
|
||||
{ .compatible = "samsung,s3c2440-hdmiphy-i2c",
|
||||
.data = (void *)(QUIRK_S3C2440 | QUIRK_HDMIPHY | QUIRK_NO_GPIO) },
|
||||
{ .compatible = "samsung,exynos5440-i2c",
|
||||
.data = (void *)(QUIRK_S3C2440 | QUIRK_NO_GPIO) },
|
||||
{ .compatible = "samsung,exynos5-sata-phy-i2c",
|
||||
.data = (void *)(QUIRK_S3C2440 | QUIRK_POLL | QUIRK_NO_GPIO) },
|
||||
{},
|
||||
|
|
|
@ -899,17 +899,6 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
|
|||
if (resource_size(res) > 0x17)
|
||||
pd->flags |= IIC_FLAG_HAS_ICIC67;
|
||||
|
||||
/* Enable Runtime PM for this device.
|
||||
*
|
||||
* Also tell the Runtime PM core to ignore children
|
||||
* for this device since it is valid for us to suspend
|
||||
* this I2C master driver even though the slave devices
|
||||
* on the I2C bus may not be suspended.
|
||||
*
|
||||
* The state of the I2C hardware bus is unaffected by
|
||||
* the Runtime PM state.
|
||||
*/
|
||||
pm_suspend_ignore_children(&dev->dev, true);
|
||||
pm_runtime_enable(&dev->dev);
|
||||
pm_runtime_get_sync(&dev->dev);
|
||||
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* i2c-stm32.c
|
||||
*
|
||||
* Copyright (C) M'boumba Cedric Madianga 2017
|
||||
* Author: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
|
||||
*
|
||||
* License terms: GNU General Public License (GPL), version 2
|
||||
*/
|
||||
|
||||
#include "i2c-stm32.h"
|
||||
|
||||
/* Functions for DMA support */
|
||||
struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev,
|
||||
dma_addr_t phy_addr,
|
||||
u32 txdr_offset,
|
||||
u32 rxdr_offset)
|
||||
{
|
||||
struct stm32_i2c_dma *dma;
|
||||
struct dma_slave_config dma_sconfig;
|
||||
int ret;
|
||||
|
||||
dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
|
||||
if (!dma)
|
||||
return NULL;
|
||||
|
||||
/* Request and configure I2C TX dma channel */
|
||||
dma->chan_tx = dma_request_slave_channel(dev, "tx");
|
||||
if (!dma->chan_tx) {
|
||||
dev_dbg(dev, "can't request DMA tx channel\n");
|
||||
ret = -EINVAL;
|
||||
goto fail_al;
|
||||
}
|
||||
|
||||
memset(&dma_sconfig, 0, sizeof(dma_sconfig));
|
||||
dma_sconfig.dst_addr = phy_addr + txdr_offset;
|
||||
dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
|
||||
dma_sconfig.dst_maxburst = 1;
|
||||
dma_sconfig.direction = DMA_MEM_TO_DEV;
|
||||
ret = dmaengine_slave_config(dma->chan_tx, &dma_sconfig);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "can't configure tx channel\n");
|
||||
goto fail_tx;
|
||||
}
|
||||
|
||||
/* Request and configure I2C RX dma channel */
|
||||
dma->chan_rx = dma_request_slave_channel(dev, "rx");
|
||||
if (!dma->chan_rx) {
|
||||
dev_err(dev, "can't request DMA rx channel\n");
|
||||
ret = -EINVAL;
|
||||
goto fail_tx;
|
||||
}
|
||||
|
||||
memset(&dma_sconfig, 0, sizeof(dma_sconfig));
|
||||
dma_sconfig.src_addr = phy_addr + rxdr_offset;
|
||||
dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
|
||||
dma_sconfig.src_maxburst = 1;
|
||||
dma_sconfig.direction = DMA_DEV_TO_MEM;
|
||||
ret = dmaengine_slave_config(dma->chan_rx, &dma_sconfig);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "can't configure rx channel\n");
|
||||
goto fail_rx;
|
||||
}
|
||||
|
||||
init_completion(&dma->dma_complete);
|
||||
|
||||
dev_info(dev, "using %s (tx) and %s (rx) for DMA transfers\n",
|
||||
dma_chan_name(dma->chan_tx), dma_chan_name(dma->chan_rx));
|
||||
|
||||
return dma;
|
||||
|
||||
fail_rx:
|
||||
dma_release_channel(dma->chan_rx);
|
||||
fail_tx:
|
||||
dma_release_channel(dma->chan_tx);
|
||||
fail_al:
|
||||
devm_kfree(dev, dma);
|
||||
dev_info(dev, "can't use DMA\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void stm32_i2c_dma_free(struct stm32_i2c_dma *dma)
|
||||
{
|
||||
dma->dma_buf = 0;
|
||||
dma->dma_len = 0;
|
||||
|
||||
dma_release_channel(dma->chan_tx);
|
||||
dma->chan_tx = NULL;
|
||||
|
||||
dma_release_channel(dma->chan_rx);
|
||||
dma->chan_rx = NULL;
|
||||
|
||||
dma->chan_using = NULL;
|
||||
}
|
||||
|
||||
int stm32_i2c_prep_dma_xfer(struct device *dev, struct stm32_i2c_dma *dma,
|
||||
bool rd_wr, u32 len, u8 *buf,
|
||||
dma_async_tx_callback callback,
|
||||
void *dma_async_param)
|
||||
{
|
||||
struct dma_async_tx_descriptor *txdesc;
|
||||
struct device *chan_dev;
|
||||
int ret;
|
||||
|
||||
if (rd_wr) {
|
||||
dma->chan_using = dma->chan_rx;
|
||||
dma->dma_transfer_dir = DMA_DEV_TO_MEM;
|
||||
dma->dma_data_dir = DMA_FROM_DEVICE;
|
||||
} else {
|
||||
dma->chan_using = dma->chan_tx;
|
||||
dma->dma_transfer_dir = DMA_MEM_TO_DEV;
|
||||
dma->dma_data_dir = DMA_TO_DEVICE;
|
||||
}
|
||||
|
||||
dma->dma_len = len;
|
||||
chan_dev = dma->chan_using->device->dev;
|
||||
|
||||
dma->dma_buf = dma_map_single(chan_dev, buf, dma->dma_len,
|
||||
dma->dma_data_dir);
|
||||
if (dma_mapping_error(chan_dev, dma->dma_buf)) {
|
||||
dev_err(dev, "DMA mapping failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
txdesc = dmaengine_prep_slave_single(dma->chan_using, dma->dma_buf,
|
||||
dma->dma_len,
|
||||
dma->dma_transfer_dir,
|
||||
DMA_PREP_INTERRUPT);
|
||||
if (!txdesc) {
|
||||
dev_err(dev, "Not able to get desc for DMA xfer\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
reinit_completion(&dma->dma_complete);
|
||||
|
||||
txdesc->callback = callback;
|
||||
txdesc->callback_param = dma_async_param;
|
||||
ret = dma_submit_error(dmaengine_submit(txdesc));
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "DMA submit failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
dma_async_issue_pending(dma->chan_using);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
dma_unmap_single(chan_dev, dma->dma_buf, dma->dma_len,
|
||||
dma->dma_data_dir);
|
||||
return ret;
|
||||
}
|
|
@ -11,6 +11,10 @@
|
|||
#ifndef _I2C_STM32_H
|
||||
#define _I2C_STM32_H
|
||||
|
||||
#include <linux/dma-direction.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
enum stm32_i2c_speed {
|
||||
STM32_I2C_SPEED_STANDARD, /* 100 kHz */
|
||||
STM32_I2C_SPEED_FAST, /* 400 kHz */
|
||||
|
@ -18,4 +22,37 @@ enum stm32_i2c_speed {
|
|||
STM32_I2C_SPEED_END,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct stm32_i2c_dma - DMA specific data
|
||||
* @chan_tx: dma channel for TX transfer
|
||||
* @chan_rx: dma channel for RX transfer
|
||||
* @chan_using: dma channel used for the current transfer (TX or RX)
|
||||
* @dma_buf: dma buffer
|
||||
* @dma_len: dma buffer len
|
||||
* @dma_transfer_dir: dma transfer direction indicator
|
||||
* @dma_data_dir: dma transfer mode indicator
|
||||
* @dma_complete: dma transfer completion
|
||||
*/
|
||||
struct stm32_i2c_dma {
|
||||
struct dma_chan *chan_tx;
|
||||
struct dma_chan *chan_rx;
|
||||
struct dma_chan *chan_using;
|
||||
dma_addr_t dma_buf;
|
||||
unsigned int dma_len;
|
||||
enum dma_transfer_direction dma_transfer_dir;
|
||||
enum dma_data_direction dma_data_dir;
|
||||
struct completion dma_complete;
|
||||
};
|
||||
|
||||
struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev,
|
||||
dma_addr_t phy_addr,
|
||||
u32 txdr_offset, u32 rxdr_offset);
|
||||
|
||||
void stm32_i2c_dma_free(struct stm32_i2c_dma *dma);
|
||||
|
||||
int stm32_i2c_prep_dma_xfer(struct device *dev, struct stm32_i2c_dma *dma,
|
||||
bool rd_wr, u32 len, u8 *buf,
|
||||
dma_async_tx_callback callback,
|
||||
void *dma_async_param);
|
||||
|
||||
#endif /* _I2C_STM32_H */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -602,20 +602,24 @@ static int stu300_send_address(struct stu300_dev *dev,
|
|||
u32 val;
|
||||
int ret;
|
||||
|
||||
if (msg->flags & I2C_M_TEN)
|
||||
if (msg->flags & I2C_M_TEN) {
|
||||
/* This is probably how 10 bit addresses look */
|
||||
val = (0xf0 | (((u32) msg->addr & 0x300) >> 7)) &
|
||||
I2C_DR_D_MASK;
|
||||
else
|
||||
val = ((msg->addr << 1) & I2C_DR_D_MASK);
|
||||
if (msg->flags & I2C_M_RD)
|
||||
/* This is the direction bit */
|
||||
val |= 0x01;
|
||||
} else {
|
||||
val = i2c_8bit_addr_from_msg(msg);
|
||||
}
|
||||
|
||||
if (msg->flags & I2C_M_RD) {
|
||||
/* This is the direction bit */
|
||||
val |= 0x01;
|
||||
if (resend)
|
||||
if (resend) {
|
||||
if (msg->flags & I2C_M_RD)
|
||||
dev_dbg(&dev->pdev->dev, "read resend\n");
|
||||
} else if (resend)
|
||||
dev_dbg(&dev->pdev->dev, "write resend\n");
|
||||
else
|
||||
dev_dbg(&dev->pdev->dev, "write resend\n");
|
||||
}
|
||||
|
||||
stu300_wr8(val, dev->virtbase + I2C_DR);
|
||||
|
||||
/* For 10bit addressing, await 10bit request (EVENT 9) */
|
||||
|
|
|
@ -509,7 +509,7 @@ static int synquacer_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
|
|||
|
||||
dev_dbg(i2c->dev, "calculated timeout %d ms\n", i2c->timeout_ms);
|
||||
|
||||
for (retry = 0; retry < adap->retries; retry++) {
|
||||
for (retry = 0; retry <= adap->retries; retry++) {
|
||||
ret = synquacer_i2c_doxfer(i2c, msgs, num);
|
||||
if (ret != -EAGAIN)
|
||||
return ret;
|
||||
|
|
|
@ -173,7 +173,6 @@ struct tegra_i2c_hw_feature {
|
|||
* @msg_buf_remaining: size of unsent data in the message buffer
|
||||
* @msg_read: identifies read transfers
|
||||
* @bus_clk_rate: current i2c bus clock rate
|
||||
* @is_suspended: prevents i2c controller accesses after suspend is called
|
||||
*/
|
||||
struct tegra_i2c_dev {
|
||||
struct device *dev;
|
||||
|
@ -194,7 +193,6 @@ struct tegra_i2c_dev {
|
|||
int msg_read;
|
||||
u32 bus_clk_rate;
|
||||
u16 clk_divisor_non_hs_mode;
|
||||
bool is_suspended;
|
||||
bool is_multimaster_mode;
|
||||
spinlock_t xfer_lock;
|
||||
};
|
||||
|
@ -734,9 +732,6 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
|
|||
int i;
|
||||
int ret = 0;
|
||||
|
||||
if (i2c_dev->is_suspended)
|
||||
return -EBUSY;
|
||||
|
||||
ret = pm_runtime_get_sync(i2c_dev->dev);
|
||||
if (ret < 0) {
|
||||
dev_err(i2c_dev->dev, "runtime resume failed %d\n", ret);
|
||||
|
@ -1051,37 +1046,9 @@ static int tegra_i2c_remove(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int tegra_i2c_suspend(struct device *dev)
|
||||
{
|
||||
struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
|
||||
|
||||
i2c_lock_adapter(&i2c_dev->adapter);
|
||||
i2c_dev->is_suspended = true;
|
||||
i2c_unlock_adapter(&i2c_dev->adapter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_i2c_resume(struct device *dev)
|
||||
{
|
||||
struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
i2c_lock_adapter(&i2c_dev->adapter);
|
||||
|
||||
ret = tegra_i2c_init(i2c_dev);
|
||||
if (!ret)
|
||||
i2c_dev->is_suspended = false;
|
||||
|
||||
i2c_unlock_adapter(&i2c_dev->adapter);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops tegra_i2c_pm = {
|
||||
SET_RUNTIME_PM_OPS(tegra_i2c_runtime_suspend, tegra_i2c_runtime_resume,
|
||||
NULL)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(tegra_i2c_suspend, tegra_i2c_resume)
|
||||
};
|
||||
#define TEGRA_I2C_PM (&tegra_i2c_pm)
|
||||
#else
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/i2c-xiic.h>
|
||||
#include <linux/platform_data/i2c-xiic.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
|
@ -143,12 +143,6 @@ struct xiic_i2c {
|
|||
|
||||
#define XIIC_TX_RX_INTERRUPTS (XIIC_INTR_RX_FULL_MASK | XIIC_TX_INTERRUPTS)
|
||||
|
||||
/* The following constants are used with the following macros to specify the
|
||||
* operation, a read or write operation.
|
||||
*/
|
||||
#define XIIC_READ_OPERATION 1
|
||||
#define XIIC_WRITE_OPERATION 0
|
||||
|
||||
/*
|
||||
* Tx Fifo upper bit masks.
|
||||
*/
|
||||
|
@ -415,7 +409,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
|
|||
clr |= XIIC_INTR_RX_FULL_MASK;
|
||||
if (!i2c->rx_msg) {
|
||||
dev_dbg(i2c->adap.dev.parent,
|
||||
"%s unexpexted RX IRQ\n", __func__);
|
||||
"%s unexpected RX IRQ\n", __func__);
|
||||
xiic_clear_rx_fifo(i2c);
|
||||
goto out;
|
||||
}
|
||||
|
@ -470,7 +464,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
|
|||
|
||||
if (!i2c->tx_msg) {
|
||||
dev_dbg(i2c->adap.dev.parent,
|
||||
"%s unexpexted TX IRQ\n", __func__);
|
||||
"%s unexpected TX IRQ\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -556,8 +550,7 @@ static void xiic_start_recv(struct xiic_i2c *i2c)
|
|||
if (!(msg->flags & I2C_M_NOSTART))
|
||||
/* write the address */
|
||||
xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET,
|
||||
(msg->addr << 1) | XIIC_READ_OPERATION |
|
||||
XIIC_TX_DYN_START_MASK);
|
||||
i2c_8bit_addr_from_msg(msg) | XIIC_TX_DYN_START_MASK);
|
||||
|
||||
xiic_irq_clr_en(i2c, XIIC_INTR_BNB_MASK);
|
||||
|
||||
|
@ -585,7 +578,7 @@ static void xiic_start_send(struct xiic_i2c *i2c)
|
|||
|
||||
if (!(msg->flags & I2C_M_NOSTART)) {
|
||||
/* write the address */
|
||||
u16 data = ((msg->addr << 1) & 0xfe) | XIIC_WRITE_OPERATION |
|
||||
u16 data = i2c_8bit_addr_from_msg(msg) |
|
||||
XIIC_TX_DYN_START_MASK;
|
||||
if ((i2c->nmsgs == 1) && msg->len == 0)
|
||||
/* no data and last message -> add STOP */
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-smbus.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
|
@ -84,6 +85,8 @@ struct xlp9xx_i2c_dev {
|
|||
struct device *dev;
|
||||
struct i2c_adapter adapter;
|
||||
struct completion msg_complete;
|
||||
struct i2c_smbus_alert_setup alert_data;
|
||||
struct i2c_client *ara;
|
||||
int irq;
|
||||
bool msg_read;
|
||||
bool len_recv;
|
||||
|
@ -155,9 +158,30 @@ static void xlp9xx_i2c_fill_tx_fifo(struct xlp9xx_i2c_dev *priv)
|
|||
priv->msg_buf += len;
|
||||
}
|
||||
|
||||
static void xlp9xx_i2c_update_rlen(struct xlp9xx_i2c_dev *priv)
|
||||
{
|
||||
u32 val, len;
|
||||
|
||||
/*
|
||||
* Update receive length. Re-read len to get the latest value,
|
||||
* and then add 4 to have a minimum value that can be safely
|
||||
* written. This is to account for the byte read above, the
|
||||
* transfer in progress and any delays in the register I/O
|
||||
*/
|
||||
val = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_CTRL);
|
||||
len = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_FIFOWCNT) &
|
||||
XLP9XX_I2C_FIFO_WCNT_MASK;
|
||||
len = max_t(u32, priv->msg_len, len + 4);
|
||||
if (len >= I2C_SMBUS_BLOCK_MAX + 2)
|
||||
return;
|
||||
val = (val & ~XLP9XX_I2C_CTRL_MCTLEN_MASK) |
|
||||
(len << XLP9XX_I2C_CTRL_MCTLEN_SHIFT);
|
||||
xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, val);
|
||||
}
|
||||
|
||||
static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv)
|
||||
{
|
||||
u32 len, i, val;
|
||||
u32 len, i;
|
||||
u8 rlen, *buf = priv->msg_buf;
|
||||
|
||||
len = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_FIFOWCNT) &
|
||||
|
@ -167,21 +191,20 @@ static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv)
|
|||
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;
|
||||
if (rlen > I2C_SMBUS_BLOCK_MAX || rlen == 0) {
|
||||
rlen = 0; /*abort transfer */
|
||||
priv->msg_buf_remaining = 0;
|
||||
priv->msg_len = 0;
|
||||
} else {
|
||||
*buf++ = rlen;
|
||||
if (priv->client_pec)
|
||||
++rlen; /* account for error check byte */
|
||||
/* update remaining bytes and message length */
|
||||
priv->msg_buf_remaining = rlen;
|
||||
priv->msg_len = rlen + 1;
|
||||
}
|
||||
xlp9xx_i2c_update_rlen(priv);
|
||||
priv->len_recv = false;
|
||||
|
||||
/* Update transfer length to read only actual data */
|
||||
val = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_CTRL);
|
||||
val = (val & ~XLP9XX_I2C_CTRL_MCTLEN_MASK) |
|
||||
((rlen + 1) << XLP9XX_I2C_CTRL_MCTLEN_SHIFT);
|
||||
xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, val);
|
||||
} else {
|
||||
len = min(priv->msg_buf_remaining, len);
|
||||
for (i = 0; i < len; i++, buf++)
|
||||
|
@ -300,10 +323,6 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
|
|||
xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_MFIFOCTRL,
|
||||
XLP9XX_I2C_MFIFOCTRL_RST);
|
||||
|
||||
/* set FIFO threshold if reading */
|
||||
if (priv->msg_read)
|
||||
xlp9xx_i2c_update_rx_fifo_thres(priv);
|
||||
|
||||
/* set slave addr */
|
||||
xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_SLAVEADDR,
|
||||
(msg->addr << XLP9XX_I2C_SLAVEADDR_ADDR_SHIFT) |
|
||||
|
@ -322,9 +341,13 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
|
|||
val &= ~XLP9XX_I2C_CTRL_ADDMODE;
|
||||
|
||||
priv->len_recv = msg->flags & I2C_M_RECV_LEN;
|
||||
len = priv->len_recv ? XLP9XX_I2C_FIFO_SIZE : msg->len;
|
||||
len = priv->len_recv ? I2C_SMBUS_BLOCK_MAX + 2 : msg->len;
|
||||
priv->client_pec = msg->flags & I2C_CLIENT_PEC;
|
||||
|
||||
/* set FIFO threshold if reading */
|
||||
if (priv->msg_read)
|
||||
xlp9xx_i2c_update_rx_fifo_thres(priv);
|
||||
|
||||
/* set data length to be transferred */
|
||||
val = (val & ~XLP9XX_I2C_CTRL_MCTLEN_MASK) |
|
||||
(len << XLP9XX_I2C_CTRL_MCTLEN_SHIFT);
|
||||
|
@ -378,8 +401,11 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
|
|||
}
|
||||
|
||||
/* update msg->len with actual received length */
|
||||
if (msg->flags & I2C_M_RECV_LEN)
|
||||
if (msg->flags & I2C_M_RECV_LEN) {
|
||||
if (!priv->msg_len)
|
||||
return -EPROTO;
|
||||
msg->len = priv->msg_len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -447,6 +473,19 @@ static int xlp9xx_i2c_get_frequency(struct platform_device *pdev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int xlp9xx_i2c_smbus_setup(struct xlp9xx_i2c_dev *priv,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
if (!priv->alert_data.irq)
|
||||
return -EINVAL;
|
||||
|
||||
priv->ara = i2c_setup_smbus_alert(&priv->adapter, &priv->alert_data);
|
||||
if (!priv->ara)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xlp9xx_i2c_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct xlp9xx_i2c_dev *priv;
|
||||
|
@ -467,6 +506,10 @@ static int xlp9xx_i2c_probe(struct platform_device *pdev)
|
|||
dev_err(&pdev->dev, "invalid irq!\n");
|
||||
return priv->irq;
|
||||
}
|
||||
/* SMBAlert irq */
|
||||
priv->alert_data.irq = platform_get_irq(pdev, 1);
|
||||
if (priv->alert_data.irq <= 0)
|
||||
priv->alert_data.irq = 0;
|
||||
|
||||
xlp9xx_i2c_get_frequency(pdev, priv);
|
||||
xlp9xx_i2c_init(priv);
|
||||
|
@ -493,6 +536,10 @@ static int xlp9xx_i2c_probe(struct platform_device *pdev)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
err = xlp9xx_i2c_smbus_setup(priv, pdev);
|
||||
if (err)
|
||||
dev_dbg(&pdev->dev, "No active SMBus alert %d\n", err);
|
||||
|
||||
platform_set_drvdata(pdev, priv);
|
||||
dev_dbg(&pdev->dev, "I2C bus:%d added\n", priv->adapter.nr);
|
||||
|
||||
|
|
|
@ -717,10 +717,6 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
|
|||
client->adapter = adap;
|
||||
|
||||
client->dev.platform_data = info->platform_data;
|
||||
|
||||
if (info->archdata)
|
||||
client->dev.archdata = *info->archdata;
|
||||
|
||||
client->flags = info->flags;
|
||||
client->addr = info->addr;
|
||||
|
||||
|
@ -746,7 +742,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
|
|||
client->dev.parent = &client->adapter->dev;
|
||||
client->dev.bus = &i2c_bus_type;
|
||||
client->dev.type = &i2c_client_type;
|
||||
client->dev.of_node = info->of_node;
|
||||
client->dev.of_node = of_node_get(info->of_node);
|
||||
client->dev.fwnode = info->fwnode;
|
||||
|
||||
i2c_dev_set_name(adap, client, info);
|
||||
|
@ -757,7 +753,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
|
|||
dev_err(&adap->dev,
|
||||
"Failed to add properties to client %s: %d\n",
|
||||
client->name, status);
|
||||
goto out_err;
|
||||
goto out_err_put_of_node;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -773,6 +769,8 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
|
|||
out_free_props:
|
||||
if (info->properties)
|
||||
device_remove_properties(&client->dev);
|
||||
out_err_put_of_node:
|
||||
of_node_put(info->of_node);
|
||||
out_err:
|
||||
dev_err(&adap->dev,
|
||||
"Failed to register i2c client %s at 0x%02x (%d)\n",
|
||||
|
|
|
@ -22,53 +22,64 @@
|
|||
|
||||
#include "i2c-core.h"
|
||||
|
||||
static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
|
||||
struct device_node *node)
|
||||
int of_i2c_get_board_info(struct device *dev, struct device_node *node,
|
||||
struct i2c_board_info *info)
|
||||
{
|
||||
struct i2c_client *client;
|
||||
struct i2c_board_info info = {};
|
||||
struct dev_archdata dev_ad = {};
|
||||
u32 addr;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&adap->dev, "of_i2c: register %pOF\n", node);
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
|
||||
dev_err(&adap->dev, "of_i2c: modalias failure on %pOF\n",
|
||||
node);
|
||||
return ERR_PTR(-EINVAL);
|
||||
if (of_modalias_node(node, info->type, sizeof(info->type)) < 0) {
|
||||
dev_err(dev, "of_i2c: modalias failure on %pOF\n", node);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(node, "reg", &addr);
|
||||
if (ret) {
|
||||
dev_err(&adap->dev, "of_i2c: invalid reg on %pOF\n", node);
|
||||
return ERR_PTR(ret);
|
||||
dev_err(dev, "of_i2c: invalid reg on %pOF\n", node);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (addr & I2C_TEN_BIT_ADDRESS) {
|
||||
addr &= ~I2C_TEN_BIT_ADDRESS;
|
||||
info.flags |= I2C_CLIENT_TEN;
|
||||
info->flags |= I2C_CLIENT_TEN;
|
||||
}
|
||||
|
||||
if (addr & I2C_OWN_SLAVE_ADDRESS) {
|
||||
addr &= ~I2C_OWN_SLAVE_ADDRESS;
|
||||
info.flags |= I2C_CLIENT_SLAVE;
|
||||
info->flags |= I2C_CLIENT_SLAVE;
|
||||
}
|
||||
|
||||
info.addr = addr;
|
||||
info.archdata = &dev_ad;
|
||||
info.of_node = of_node_get(node);
|
||||
info->addr = addr;
|
||||
info->of_node = node;
|
||||
|
||||
if (of_property_read_bool(node, "host-notify"))
|
||||
info.flags |= I2C_CLIENT_HOST_NOTIFY;
|
||||
info->flags |= I2C_CLIENT_HOST_NOTIFY;
|
||||
|
||||
if (of_get_property(node, "wakeup-source", NULL))
|
||||
info.flags |= I2C_CLIENT_WAKE;
|
||||
info->flags |= I2C_CLIENT_WAKE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_i2c_get_board_info);
|
||||
|
||||
static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
|
||||
struct device_node *node)
|
||||
{
|
||||
struct i2c_client *client;
|
||||
struct i2c_board_info info;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&adap->dev, "of_i2c: register %pOF\n", node);
|
||||
|
||||
ret = of_i2c_get_board_info(&adap->dev, node, &info);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
client = i2c_new_device(adap, &info);
|
||||
if (!client) {
|
||||
dev_err(&adap->dev, "of_i2c: Failure registering %pOF\n", node);
|
||||
of_node_put(node);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
return client;
|
||||
|
|
|
@ -466,6 +466,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
|
|||
status = i2c_transfer(adapter, msg, num);
|
||||
if (status < 0)
|
||||
return status;
|
||||
if (status != num)
|
||||
return -EIO;
|
||||
|
||||
/* Check PEC if last message is a read */
|
||||
if (i && (msg[num-1].flags & I2C_M_RD)) {
|
||||
|
|
|
@ -418,7 +418,7 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
|
|||
snprintf(symlink_name, sizeof(symlink_name), "channel-%u", chan_id);
|
||||
WARN(sysfs_create_link(&muxc->dev->kobj, &priv->adap.dev.kobj,
|
||||
symlink_name),
|
||||
"can't create symlink for channel %u\n", chan_id);
|
||||
"can't create symlink to channel %u\n", chan_id);
|
||||
dev_info(&parent->dev, "Added multiplexed i2c bus %d\n",
|
||||
i2c_adapter_id(&priv->adap));
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sysfs.h>
|
||||
|
||||
|
@ -105,7 +106,7 @@ static int i2c_demux_activate_master(struct i2c_demux_pinctrl_priv *priv, u32 ne
|
|||
priv->cur_adap.owner = THIS_MODULE;
|
||||
priv->cur_adap.algo = &priv->algo;
|
||||
priv->cur_adap.algo_data = priv;
|
||||
priv->cur_adap.dev.parent = priv->dev;
|
||||
priv->cur_adap.dev.parent = &adap->dev;
|
||||
priv->cur_adap.class = adap->class;
|
||||
priv->cur_adap.retries = adap->retries;
|
||||
priv->cur_adap.timeout = adap->timeout;
|
||||
|
@ -254,6 +255,8 @@ static int i2c_demux_pinctrl_probe(struct platform_device *pdev)
|
|||
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
pm_runtime_no_callbacks(&pdev->dev);
|
||||
|
||||
/* switch to first parent as active master */
|
||||
i2c_demux_activate_master(priv, 0);
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-mux.h>
|
||||
#include <linux/i2c-mux-gpio.h>
|
||||
#include <linux/platform_data/i2c-mux-gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
|
|
@ -206,8 +206,7 @@ static const struct of_device_id ltc4306_of_match[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(of, ltc4306_of_match);
|
||||
|
||||
static int ltc4306_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int ltc4306_probe(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent);
|
||||
const struct chip_desc *chip;
|
||||
|
@ -221,7 +220,7 @@ static int ltc4306_probe(struct i2c_client *client,
|
|||
chip = of_device_get_match_data(&client->dev);
|
||||
|
||||
if (!chip)
|
||||
chip = &chips[id->driver_data];
|
||||
chip = &chips[i2c_match_id(ltc4306_id, client)->driver_data];
|
||||
|
||||
idle_disc = device_property_read_bool(&client->dev,
|
||||
"i2c-mux-idle-disconnect");
|
||||
|
@ -310,7 +309,7 @@ static struct i2c_driver ltc4306_driver = {
|
|||
.name = "ltc4306",
|
||||
.of_match_table = of_match_ptr(ltc4306_of_match),
|
||||
},
|
||||
.probe = ltc4306_probe,
|
||||
.probe_new = ltc4306_probe,
|
||||
.remove = ltc4306_remove,
|
||||
.id_table = ltc4306_id,
|
||||
};
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-mux.h>
|
||||
|
@ -373,7 +374,6 @@ static int pca954x_probe(struct i2c_client *client,
|
|||
int num, force, class;
|
||||
struct i2c_mux_core *muxc;
|
||||
struct pca954x *data;
|
||||
const struct of_device_id *match;
|
||||
int ret;
|
||||
|
||||
if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE))
|
||||
|
@ -389,15 +389,19 @@ static int pca954x_probe(struct i2c_client *client,
|
|||
i2c_set_clientdata(client, muxc);
|
||||
data->client = client;
|
||||
|
||||
/* Get the mux out of reset if a reset GPIO is specified. */
|
||||
gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW);
|
||||
/* Reset the mux if a reset GPIO is specified. */
|
||||
gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(gpio))
|
||||
return PTR_ERR(gpio);
|
||||
if (gpio) {
|
||||
udelay(1);
|
||||
gpiod_set_value_cansleep(gpio, 0);
|
||||
/* Give the chip some time to recover. */
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
match = of_match_device(of_match_ptr(pca954x_of_match), &client->dev);
|
||||
if (match)
|
||||
data->chip = of_device_get_match_data(&client->dev);
|
||||
else
|
||||
data->chip = of_device_get_match_data(&client->dev);
|
||||
if (!data->chip)
|
||||
data->chip = &chips[id->driver_data];
|
||||
|
||||
if (data->chip->id.manufacturer_id != I2C_DEVICE_ID_NONE) {
|
||||
|
|
|
@ -127,10 +127,8 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
|
|||
values = devm_kcalloc(&pdev->dev,
|
||||
mux->data.n_values, sizeof(*mux->data.values),
|
||||
GFP_KERNEL);
|
||||
if (!values) {
|
||||
dev_err(&pdev->dev, "Cannot allocate values array");
|
||||
if (!values)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for_each_child_of_node(np, child) {
|
||||
of_property_read_u32(child, "reg", values + i);
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-gpio.h>
|
||||
#include <linux/platform_data/i2c-gpio.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/slab.h>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/i2c-gpio.h>
|
||||
#include <linux/platform_data/i2c-gpio.h>
|
||||
#include <linux/gpio/machine.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
#include <linux/timb_gpio.h>
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-ocores.h>
|
||||
#include <linux/i2c-xiic.h>
|
||||
#include <linux/platform_data/i2c-ocores.h>
|
||||
#include <linux/platform_data/i2c-xiic.h>
|
||||
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/xilinx_spi.h>
|
||||
|
|
|
@ -532,6 +532,45 @@ static int at24_get_pdata(struct device *dev, struct at24_platform_data *pdata)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void at24_remove_dummy_clients(struct at24_data *at24)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i < at24->num_addresses; i++)
|
||||
i2c_unregister_device(at24->client[i].client);
|
||||
}
|
||||
|
||||
static int at24_make_dummy_client(struct at24_data *at24, unsigned int index,
|
||||
struct regmap_config *regmap_config)
|
||||
{
|
||||
struct i2c_client *base_client, *dummy_client;
|
||||
unsigned short int addr;
|
||||
struct regmap *regmap;
|
||||
struct device *dev;
|
||||
|
||||
base_client = at24->client[0].client;
|
||||
dev = &base_client->dev;
|
||||
addr = base_client->addr + index;
|
||||
|
||||
dummy_client = i2c_new_dummy(base_client->adapter,
|
||||
base_client->addr + index);
|
||||
if (!dummy_client) {
|
||||
dev_err(dev, "address 0x%02x unavailable\n", addr);
|
||||
return -EADDRINUSE;
|
||||
}
|
||||
|
||||
regmap = devm_regmap_init_i2c(dummy_client, regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
i2c_unregister_device(dummy_client);
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
at24->client[index].client = dummy_client;
|
||||
at24->client[index].regmap = regmap;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int at24_get_offset_adj(u8 flags, unsigned int byte_len)
|
||||
{
|
||||
if (flags & AT24_FLAG_MAC) {
|
||||
|
@ -637,20 +676,10 @@ static int at24_probe(struct i2c_client *client)
|
|||
|
||||
/* use dummy devices for multiple-address chips */
|
||||
for (i = 1; i < num_addresses; i++) {
|
||||
at24->client[i].client = i2c_new_dummy(client->adapter,
|
||||
client->addr + i);
|
||||
if (!at24->client[i].client) {
|
||||
dev_err(dev, "address 0x%02x unavailable\n",
|
||||
client->addr + i);
|
||||
err = -EADDRINUSE;
|
||||
goto err_clients;
|
||||
}
|
||||
at24->client[i].regmap = devm_regmap_init_i2c(
|
||||
at24->client[i].client,
|
||||
®map_config);
|
||||
if (IS_ERR(at24->client[i].regmap)) {
|
||||
err = PTR_ERR(at24->client[i].regmap);
|
||||
goto err_clients;
|
||||
err = at24_make_dummy_client(at24, i, ®map_config);
|
||||
if (err) {
|
||||
at24_remove_dummy_clients(at24);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -685,7 +714,7 @@ static int at24_probe(struct i2c_client *client)
|
|||
nvmem_config.word_size = 1;
|
||||
nvmem_config.size = pdata.byte_len;
|
||||
|
||||
at24->nvmem = nvmem_register(&nvmem_config);
|
||||
at24->nvmem = devm_nvmem_register(dev, &nvmem_config);
|
||||
if (IS_ERR(at24->nvmem)) {
|
||||
err = PTR_ERR(at24->nvmem);
|
||||
goto err_clients;
|
||||
|
@ -702,10 +731,7 @@ static int at24_probe(struct i2c_client *client)
|
|||
return 0;
|
||||
|
||||
err_clients:
|
||||
for (i = 1; i < num_addresses; i++)
|
||||
if (at24->client[i].client)
|
||||
i2c_unregister_device(at24->client[i].client);
|
||||
|
||||
at24_remove_dummy_clients(at24);
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
return err;
|
||||
|
@ -714,15 +740,10 @@ static int at24_probe(struct i2c_client *client)
|
|||
static int at24_remove(struct i2c_client *client)
|
||||
{
|
||||
struct at24_data *at24;
|
||||
int i;
|
||||
|
||||
at24 = i2c_get_clientdata(client);
|
||||
|
||||
nvmem_unregister(at24->nvmem);
|
||||
|
||||
for (i = 1; i < at24->num_addresses; i++)
|
||||
i2c_unregister_device(at24->client[i].client);
|
||||
|
||||
at24_remove_dummy_clients(at24);
|
||||
pm_runtime_disable(&client->dev);
|
||||
pm_runtime_set_suspended(&client->dev);
|
||||
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Header file for I2C support on PNX010x/4008.
|
||||
*
|
||||
* Author: Dennis Kovalev <dkovalev@ru.mvista.com>
|
||||
*
|
||||
* 2004-2006 (c) MontaVista Software, Inc. This file is licensed under
|
||||
* the terms of the GNU General Public License version 2. This program
|
||||
* is licensed "as is" without any warranty of any kind, whether express
|
||||
* or implied.
|
||||
*/
|
||||
|
||||
#ifndef __I2C_PNX_H__
|
||||
#define __I2C_PNX_H__
|
||||
|
||||
struct platform_device;
|
||||
struct clk;
|
||||
|
||||
struct i2c_pnx_mif {
|
||||
int ret; /* Return value */
|
||||
int mode; /* Interface mode */
|
||||
struct completion complete; /* I/O completion */
|
||||
struct timer_list timer; /* Timeout */
|
||||
u8 * buf; /* Data buffer */
|
||||
int len; /* Length of data buffer */
|
||||
int order; /* RX Bytes to order via TX */
|
||||
};
|
||||
|
||||
struct i2c_pnx_algo_data {
|
||||
void __iomem *ioaddr;
|
||||
struct i2c_pnx_mif mif;
|
||||
int last;
|
||||
struct clk *clk;
|
||||
struct i2c_adapter adapter;
|
||||
int irq;
|
||||
u32 timeout;
|
||||
};
|
||||
|
||||
#endif /* __I2C_PNX_H__ */
|
|
@ -394,7 +394,6 @@ static inline bool i2c_detect_slave_mode(struct device *dev) { return false; }
|
|||
* @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
|
||||
* @fwnode: device node supplied by the platform firmware
|
||||
* @properties: additional device properties for the device
|
||||
|
@ -419,7 +418,6 @@ struct i2c_board_info {
|
|||
unsigned short addr;
|
||||
const char *dev_name;
|
||||
void *platform_data;
|
||||
struct dev_archdata *archdata;
|
||||
struct device_node *of_node;
|
||||
struct fwnode_handle *fwnode;
|
||||
const struct property_entry *properties;
|
||||
|
@ -903,6 +901,9 @@ extern const struct of_device_id
|
|||
*i2c_of_match_device(const struct of_device_id *matches,
|
||||
struct i2c_client *client);
|
||||
|
||||
int of_i2c_get_board_info(struct device *dev, struct device_node *node,
|
||||
struct i2c_board_info *info);
|
||||
|
||||
#else
|
||||
|
||||
static inline struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
|
||||
|
@ -927,6 +928,13 @@ static inline const struct of_device_id
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static inline int of_i2c_get_board_info(struct device *dev,
|
||||
struct device_node *node,
|
||||
struct i2c_board_info *info)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
#if IS_ENABLED(CONFIG_ACPI)
|
||||
|
|
Loading…
Reference in New Issue