Commit d55fc378 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull i2c updates from Wolfram Sang:

 - New drivers: UniPhier (with and without FIFO)

 - some drivers got some bigger rework: ismt, designware, img-scb (rcar
   had to be reverted because issues were showing up just lately)

 - ACPI: reworked the device scanning and added support for muxes

... and quite a lot of driver bugfixes and cleanups this time.  All
files touched outside of the i2c realm have proper acks.

* 'i2c/for-4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (70 commits)
  i2c: rcar: Revert the latest refactoring series
  i2c: pnx: remove superfluous assignment
  MAINTAINERS: i2c: drop i2c-pnx maintainer
  MAINTAINERS: i2c: mark also subdirectories as maintained
  i2c: cadence: enable driver for ARM64
  i2c: i801: Document Intel DNV and Broxton
  i2c: at91: manage unexpected RXRDY flag when starting a transfer
  i2c: pnx: Use setup_timer instead of open coding it
  i2c: add ACPI support for I2C mux ports
  acpi: add acpi_preset_companion() stub
  i2c: pxa: Add support for pxa910/988 & new configuration features
  i2c: au1550: Convert to devm_kzalloc and devm_ioremap_resource
  i2c-dev: Fix I2C_SLAVE ioctl comment
  i2c-dev: Fix typo in ioctl name reference
  i2c: sirf: tune the divider to make i2c bus freq more accurate
  i2c: imx: Use -ENXIO as error in the NACK case
  i2c: i801: Add support for Intel Broxton
  i2c: i801: Add support for Intel DNV
  i2c: mediatek: add i2c resume support
  i2c: imx: implement bus recovery
  ...
parents 42d4ebb4 75ecc64e
ACPI I2C Muxes
--------------
Describing an I2C device hierarchy that includes I2C muxes requires an ACPI
Device () scope per mux channel.
Consider this topology:
+------+ +------+
| SMB1 |-->| MUX0 |--CH00--> i2c client A (0x50)
| | | 0x70 |--CH01--> i2c client B (0x50)
+------+ +------+
which corresponds to the following ASL:
Device (SMB1)
{
Name (_HID, ...)
Device (MUX0)
{
Name (_HID, ...)
Name (_CRS, ResourceTemplate () {
I2cSerialBus (0x70, ControllerInitiated, I2C_SPEED,
AddressingMode7Bit, "^SMB1", 0x00,
ResourceConsumer,,)
}
Device (CH00)
{
Name (_ADR, 0)
Device (CLIA)
{
Name (_HID, ...)
Name (_CRS, ResourceTemplate () {
I2cSerialBus (0x50, ControllerInitiated, I2C_SPEED,
AddressingMode7Bit, "^CH00", 0x00,
ResourceConsumer,,)
}
}
}
Device (CH01)
{
Name (_ADR, 1)
Device (CLIB)
{
Name (_HID, ...)
Name (_CRS, ResourceTemplate () {
I2cSerialBus (0x50, ControllerInitiated, I2C_SPEED,
AddressingMode7Bit, "^CH01", 0x00,
ResourceConsumer,,)
}
}
}
}
}
* Texas Instruments Davinci I2C * Texas Instruments Davinci/Keystone I2C
This file provides information, what the device node for the This file provides information, what the device node for the
davinci i2c interface contain. davinci/keystone i2c interface contains.
Required properties: Required properties:
- compatible: "ti,davinci-i2c"; - compatible: "ti,davinci-i2c" or "ti,keystone-i2c";
- reg : Offset and length of the register set for the device - reg : Offset and length of the register set for the device
Recommended properties : Recommended properties :
......
...@@ -14,6 +14,10 @@ Optional properties: ...@@ -14,6 +14,10 @@ Optional properties:
The absence of the propoerty indicates the default frequency 100 kHz. The absence of the propoerty indicates the default frequency 100 kHz.
- dmas: A list of two dma specifiers, one for each entry in dma-names. - dmas: A list of two dma specifiers, one for each entry in dma-names.
- dma-names: should contain "tx" and "rx". - dma-names: should contain "tx" and "rx".
- scl-gpios: specify the gpio related to SCL pin
- sda-gpios: specify the gpio related to SDA pin
- pinctrl: add extra pinctrl to configure i2c pins to gpio function for i2c
bus recovery, call it "gpio" state
Examples: Examples:
...@@ -37,4 +41,9 @@ i2c0: i2c@40066000 { /* i2c0 on vf610 */ ...@@ -37,4 +41,9 @@ i2c0: i2c@40066000 { /* i2c0 on vf610 */
dmas = <&edma0 0 50>, dmas = <&edma0 0 50>,
<&edma0 0 51>; <&edma0 0 51>;
dma-names = "rx","tx"; dma-names = "rx","tx";
pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c1>;
pinctrl-1 = <&pinctrl_i2c1_gpio>;
scl-gpios = <&gpio5 26 GPIO_ACTIVE_HIGH>;
sda-gpios = <&gpio5 27 GPIO_ACTIVE_HIGH>;
}; };
...@@ -10,6 +10,7 @@ Required properties: ...@@ -10,6 +10,7 @@ Required properties:
"renesas,i2c-r8a7792" "renesas,i2c-r8a7792"
"renesas,i2c-r8a7793" "renesas,i2c-r8a7793"
"renesas,i2c-r8a7794" "renesas,i2c-r8a7794"
"renesas,i2c-r8a7795"
- reg: physical base address of the controller and length of memory mapped - reg: physical base address of the controller and length of memory mapped
region. region.
- interrupts: interrupt specifier. - interrupts: interrupt specifier.
......
...@@ -10,6 +10,7 @@ Required properties: ...@@ -10,6 +10,7 @@ Required properties:
- "renesas,iic-r8a7792" (R-Car V2H) - "renesas,iic-r8a7792" (R-Car V2H)
- "renesas,iic-r8a7793" (R-Car M2-N) - "renesas,iic-r8a7793" (R-Car M2-N)
- "renesas,iic-r8a7794" (R-Car E2) - "renesas,iic-r8a7794" (R-Car E2)
- "renesas,iic-r8a7795" (R-Car H3)
- "renesas,iic-sh73a0" (SH-Mobile AG5) - "renesas,iic-sh73a0" (SH-Mobile AG5)
- reg : address start and address range size of device - reg : address start and address range size of device
- interrupts : interrupt of device - interrupts : interrupt of device
......
UniPhier I2C controller (FIFO-builtin)
Required properties:
- compatible: should be "socionext,uniphier-fi2c".
- #address-cells: should be 1.
- #size-cells: should be 0.
- reg: offset and length of the register set for the device.
- interrupts: a single interrupt specifier.
- clocks: phandle to the input clock.
Optional properties:
- clock-frequency: desired I2C bus frequency in Hz. The maximum supported
value is 400000. Defaults to 100000 if not specified.
Examples:
i2c0: i2c@58780000 {
compatible = "socionext,uniphier-fi2c";
reg = <0x58780000 0x80>;
#address-cells = <1>;
#size-cells = <0>;
interrupts = <0 41 4>;
clocks = <&i2c_clk>;
clock-frequency = <100000>;
};
UniPhier I2C controller (FIFO-less)
Required properties:
- compatible: should be "socionext,uniphier-i2c".
- #address-cells: should be 1.
- #size-cells: should be 0.
- reg: offset and length of the register set for the device.
- interrupts: a single interrupt specifier.
- clocks: phandle to the input clock.
Optional properties:
- clock-frequency: desired I2C bus frequency in Hz. The maximum supported
value is 400000. Defaults to 100000 if not specified.
Examples:
i2c0: i2c@58400000 {
compatible = "socionext,uniphier-i2c";
reg = <0x58400000 0x40>;
#address-cells = <1>;
#size-cells = <0>;
interrupts = <0 41 1>;
clocks = <&i2c_clk>;
clock-frequency = <100000>;
};
...@@ -30,6 +30,8 @@ Supported adapters: ...@@ -30,6 +30,8 @@ Supported adapters:
* Intel BayTrail (SOC) * Intel BayTrail (SOC)
* Intel Sunrise Point-H (PCH) * Intel Sunrise Point-H (PCH)
* Intel Sunrise Point-LP (PCH) * Intel Sunrise Point-LP (PCH)
* Intel DNV (SOC)
* Intel Broxton (SOC)
Datasheets: Publicly available at the Intel website Datasheets: Publicly available at the Intel website
On Intel Patsburg and later chipsets, both the normal host SMBus controller On Intel Patsburg and later chipsets, both the normal host SMBus controller
......
...@@ -1626,6 +1626,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) ...@@ -1626,6 +1626,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained S: Maintained
F: arch/arm/boot/dts/uniphier* F: arch/arm/boot/dts/uniphier*
F: arch/arm/mach-uniphier/ F: arch/arm/mach-uniphier/
F: drivers/i2c/busses/i2c-uniphier*
F: drivers/pinctrl/uniphier/ F: drivers/pinctrl/uniphier/
F: drivers/tty/serial/8250/8250_uniphier.c F: drivers/tty/serial/8250/8250_uniphier.c
N: uniphier N: uniphier
...@@ -5163,6 +5164,7 @@ S: Maintained ...@@ -5163,6 +5164,7 @@ S: Maintained
F: Documentation/devicetree/bindings/i2c/ F: Documentation/devicetree/bindings/i2c/
F: Documentation/i2c/ F: Documentation/i2c/
F: drivers/i2c/ F: drivers/i2c/
F: drivers/i2c/*/
F: include/linux/i2c.h F: include/linux/i2c.h
F: include/linux/i2c-*.h F: include/linux/i2c-*.h
F: include/uapi/linux/i2c.h F: include/uapi/linux/i2c.h
...@@ -8418,12 +8420,6 @@ M: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com> ...@@ -8418,12 +8420,6 @@ M: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
S: Maintained S: Maintained
F: drivers/pnp/ F: drivers/pnp/
PNXxxxx I2C DRIVER
M: Vitaly Wool <vitalywool@gmail.com>
L: linux-i2c@vger.kernel.org
S: Maintained
F: drivers/i2c/busses/i2c-pnx.c
PPP PROTOCOL DRIVERS AND COMPRESSORS PPP PROTOCOL DRIVERS AND COMPRESSORS
M: Paul Mackerras <paulus@samba.org> M: Paul Mackerras <paulus@samba.org>
L: linux-ppp@vger.kernel.org L: linux-ppp@vger.kernel.org
......
...@@ -124,6 +124,8 @@ config I2C_I801 ...@@ -124,6 +124,8 @@ config I2C_I801
BayTrail (SOC) BayTrail (SOC)
Sunrise Point-H (PCH) Sunrise Point-H (PCH)
Sunrise Point-LP (PCH) Sunrise Point-LP (PCH)
DNV (SOC)
Broxton (SOC)
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called i2c-i801. will be called i2c-i801.
...@@ -422,7 +424,7 @@ config I2C_BLACKFIN_TWI_CLK_KHZ ...@@ -422,7 +424,7 @@ config I2C_BLACKFIN_TWI_CLK_KHZ
config I2C_CADENCE config I2C_CADENCE
tristate "Cadence I2C Controller" tristate "Cadence I2C Controller"
depends on ARCH_ZYNQ depends on ARCH_ZYNQ || ARM64
help help
Say yes here to select Cadence I2C Host Controller. This controller is Say yes here to select Cadence I2C Host Controller. This controller is
e.g. used by Xilinx Zynq. e.g. used by Xilinx Zynq.
...@@ -582,10 +584,10 @@ config I2C_IMG ...@@ -582,10 +584,10 @@ config I2C_IMG
config I2C_IMX config I2C_IMX
tristate "IMX I2C interface" tristate "IMX I2C interface"
depends on ARCH_MXC depends on ARCH_MXC || ARCH_LAYERSCAPE
help help
Say Y here if you want to use the IIC bus controller on Say Y here if you want to use the IIC bus controller on
the Freescale i.MX/MXC processors. the Freescale i.MX/MXC or Layerscape processors.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called i2c-imx. will be called i2c-imx.
...@@ -902,6 +904,22 @@ config I2C_TEGRA ...@@ -902,6 +904,22 @@ config I2C_TEGRA
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
I2C controller embedded in NVIDIA Tegra SOCs I2C controller embedded in NVIDIA Tegra SOCs
config I2C_UNIPHIER
tristate "UniPhier FIFO-less I2C controller"
depends on ARCH_UNIPHIER
help
If you say yes to this option, support will be included for
the UniPhier FIFO-less I2C interface embedded in PH1-LD4, PH1-sLD8,
or older UniPhier SoCs.
config I2C_UNIPHIER_F
tristate "UniPhier FIFO-builtin I2C controller"
depends on ARCH_UNIPHIER
help
If you say yes to this option, support will be included for
the UniPhier FIFO-builtin I2C interface embedded in PH1-Pro4,
PH1-Pro5, or newer UniPhier SoCs.
config I2C_VERSATILE config I2C_VERSATILE
tristate "ARM Versatile/Realview I2C bus support" tristate "ARM Versatile/Realview I2C bus support"
depends on ARCH_VERSATILE || ARCH_REALVIEW || ARCH_VEXPRESS depends on ARCH_VERSATILE || ARCH_REALVIEW || ARCH_VEXPRESS
......
...@@ -87,6 +87,8 @@ obj-$(CONFIG_I2C_ST) += i2c-st.o ...@@ -87,6 +87,8 @@ obj-$(CONFIG_I2C_ST) += i2c-st.o
obj-$(CONFIG_I2C_STU300) += i2c-stu300.o obj-$(CONFIG_I2C_STU300) += i2c-stu300.o
obj-$(CONFIG_I2C_SUN6I_P2WI) += i2c-sun6i-p2wi.o obj-$(CONFIG_I2C_SUN6I_P2WI) += i2c-sun6i-p2wi.o
obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o
obj-$(CONFIG_I2C_UNIPHIER) += i2c-uniphier.o
obj-$(CONFIG_I2C_UNIPHIER_F) += i2c-uniphier-f.o
obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
obj-$(CONFIG_I2C_WMT) += i2c-wmt.o obj-$(CONFIG_I2C_WMT) += i2c-wmt.o
obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o
......
...@@ -347,8 +347,14 @@ static void at91_twi_write_data_dma(struct at91_twi_dev *dev) ...@@ -347,8 +347,14 @@ static void at91_twi_write_data_dma(struct at91_twi_dev *dev)
static void at91_twi_read_next_byte(struct at91_twi_dev *dev) static void at91_twi_read_next_byte(struct at91_twi_dev *dev)
{ {
if (!dev->buf_len) /*
* If we are in this case, it means there is garbage data in RHR, so
* delete them.
*/
if (!dev->buf_len) {
at91_twi_read(dev, AT91_TWI_RHR);
return; return;
}
/* 8bit read works with and without FIFO */ /* 8bit read works with and without FIFO */
*dev->buf = readb_relaxed(dev->base + AT91_TWI_RHR); *dev->buf = readb_relaxed(dev->base + AT91_TWI_RHR);
...@@ -465,19 +471,73 @@ static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id) ...@@ -465,19 +471,73 @@ static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id)
if (!irqstatus) if (!irqstatus)
return IRQ_NONE; return IRQ_NONE;
else if (irqstatus & AT91_TWI_RXRDY) /*
* In reception, the behavior of the twi device (before sama5d2) is
* weird. There is some magic about RXRDY flag! When a data has been
* almost received, the reception of a new one is anticipated if there
* is no stop command to send. That is the reason why ask for sending
* the stop command not on the last data but on the second last one.
*
* Unfortunately, we could still have the RXRDY flag set even if the
* transfer is done and we have read the last data. It might happen
* when the i2c slave device sends too quickly data after receiving the
* ack from the master. The data has been almost received before having
* the order to send stop. In this case, sending the stop command could
* cause a RXRDY interrupt with a TXCOMP one. It is better to manage
* 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); at91_twi_read_next_byte(dev);
else if (irqstatus & AT91_TWI_TXRDY)
at91_twi_write_next_byte(dev);
/* catch error flags */
dev->transfer_status |= status;
/*
* When a NACK condition is detected, the I2C controller sets the NACK,
* TXCOMP and TXRDY bits all together in the Status Register (SR).
*
* 1 - Handling NACK errors with CPU write transfer.
*
* In such case, we should not write the next byte into the Transmit
* Holding Register (THR) otherwise the I2C controller would start a new
* transfer and the I2C slave is likely to reply by another NACK.
*
* 2 - Handling NACK errors with DMA write transfer.
*
* By setting the TXRDY bit in the SR, the I2C controller also triggers
* the DMA controller to write the next data into the THR. Then the
* result depends on the hardware version of the I2C controller.
*
* 2a - Without support of the Alternative Command mode.
*
* This is the worst case: the DMA controller is triggered to write the
* next data into the THR, hence starting a new transfer: the I2C slave
* is likely to reply by another NACK.
* Concurrently, this interrupt handler is likely to be called to manage
* the first NACK before the I2C controller detects the second NACK and
* sets once again the NACK bit into the SR.
* When handling the first NACK, this interrupt handler disables the I2C
* controller interruptions, especially the NACK interrupt.
* Hence, the NACK bit is pending into the SR. This is why we should
* read the SR to clear all pending interrupts at the beginning of
* at91_do_twi_transfer() before actually starting a new transfer.
*
* 2b - With support of the Alternative Command mode.
*
* When a NACK condition is detected, the I2C controller also locks the
* THR (and sets the LOCK bit in the SR): even though the DMA controller
* is triggered by the TXRDY bit to write the next data into the THR,
* this data actually won't go on the I2C bus hence a second NACK is not
* generated.
*/
if (irqstatus & (AT91_TWI_TXCOMP | AT91_TWI_NACK)) { if (irqstatus & (AT91_TWI_TXCOMP | AT91_TWI_NACK)) {
at91_disable_twi_interrupts(dev); at91_disable_twi_interrupts(dev);
complete(&dev->cmd_complete); complete(&dev->cmd_complete);
} else if (irqstatus & AT91_TWI_TXRDY) {
at91_twi_write_next_byte(dev);
} }
/* catch error flags */
dev->transfer_status |= status;
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -537,6 +597,9 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) ...@@ -537,6 +597,9 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
reinit_completion(&dev->cmd_complete); reinit_completion(&dev->cmd_complete);
dev->transfer_status = 0; dev->transfer_status = 0;
/* Clear pending interrupts, such as NACK. */
at91_twi_read(dev, AT91_TWI_SR);
if (dev->fifo_size) { if (dev->fifo_size) {
unsigned fifo_mr = at91_twi_read(dev, AT91_TWI_FMR); unsigned fifo_mr = at91_twi_read(dev, AT91_TWI_FMR);
...@@ -558,11 +621,6 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) ...@@ -558,11 +621,6 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
} else if (dev->msg->flags & I2C_M_RD) { } else if (dev->msg->flags & I2C_M_RD) {
unsigned start_flags = AT91_TWI_START; unsigned start_flags = AT91_TWI_START;
if (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY) {
dev_err(dev->dev, "RXRDY still set!");
at91_twi_read(dev, AT91_TWI_RHR);
}
/* if only one byte is to be read, immediately stop transfer */ /* if only one byte is to be read, immediately stop transfer */
if (!has_alt_cmd && dev->buf_len <= 1 && if (!has_alt_cmd && dev->buf_len <= 1 &&
!(dev->msg->flags & I2C_M_RECV_LEN)) !(dev->msg->flags & I2C_M_RECV_LEN))
......
...@@ -48,7 +48,6 @@ struct i2c_au1550_data { ...@@ -48,7 +48,6 @@ struct i2c_au1550_data {
void __iomem *psc_base; void __iomem *psc_base;
int xfer_timeout; int xfer_timeout;
struct i2c_adapter adap; struct i2c_adapter adap;
struct resource *ioarea;
}; };
static inline void WR(struct i2c_au1550_data *a, int r, unsigned long v) static inline void WR(struct i2c_au1550_data *a, int r, unsigned long v)
...@@ -284,10 +283,10 @@ static void i2c_au1550_setup(struct i2c_au1550_data *priv) ...@@ -284,10 +283,10 @@ static void i2c_au1550_setup(struct i2c_au1550_data *priv)
/* Set the protocol timer values. See Table 71 in the /* Set the protocol timer values. See Table 71 in the
* Au1550 Data Book for standard timing values. * Au1550 Data Book for standard timing values.
*/ */
WR(priv, PSC_SMBTMR, PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \ WR(priv, PSC_SMBTMR, PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(20) | \
PSC_SMBTMR_SET_PU(15) | PSC_SMBTMR_SET_SH(15) | \ PSC_SMBTMR_SET_PU(20) | PSC_SMBTMR_SET_SH(20) | \
PSC_SMBTMR_SET_SU(15) | PSC_SMBTMR_SET_CL(15) | \ PSC_SMBTMR_SET_SU(20) | PSC_SMBTMR_SET_CL(20) | \
PSC_SMBTMR_SET_CH(15)); PSC_SMBTMR_SET_CH(20));
cfg |= PSC_SMBCFG_DE_ENABLE; cfg |= PSC_SMBCFG_DE_ENABLE;
WR(priv, PSC_SMBCFG, cfg); WR(priv, PSC_SMBCFG, cfg);
...@@ -315,30 +314,16 @@ i2c_au1550_probe(struct platform_device *pdev) ...@@ -315,30 +314,16 @@ i2c_au1550_probe(struct platform_device *pdev)
struct resource *r; struct resource *r;
int ret; int ret;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv = devm_kzalloc(&pdev->dev, sizeof(struct i2c_au1550_data),
if (!r) { GFP_KERNEL);
ret = -ENODEV; if (!priv)
goto out; return -ENOMEM;
}
priv = kzalloc(sizeof(struct i2c_au1550_data), GFP_KERNEL); r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!priv) { priv->psc_base = devm_ioremap_resource(&pdev->dev, r);
ret = -ENOMEM; if (IS_ERR(priv->psc_base))
goto out; return PTR_ERR(priv->psc_base);
}
priv->ioarea = request_mem_region(r->start, resource_size(r),
pdev->name);
if (!priv->ioarea) {
ret = -EBUSY;
goto out_mem;
}
priv->psc_base = ioremap(r->start, resource_size(r));
if (!priv->psc_base) {
ret = -EIO;
goto out_map;
}
priv->xfer_timeout = 200; priv->xfer_timeout = 200;
priv->adap.nr = pdev->id; priv->adap.nr = pdev->id;
...@@ -351,20 +336,13 @@ i2c_au1550_probe(struct platform_device *pdev) ...@@ -351,20 +336,13 @@ i2c_au1550_probe(struct platform_device *pdev)
i2c_au1550_setup(priv); i2c_au1550_setup(priv);
ret = i2c_add_numbered_adapter(&priv->adap); ret = i2c_add_numbered_adapter(&priv->adap);
if (ret == 0) { if (ret) {
platform_set_drvdata(pdev, priv); i2c_au1550_disable(priv);
return 0; return ret;
} }
i2c_au1550_disable(priv); platform_set_drvdata(pdev, priv);
iounmap(priv->psc_base); return 0;
out_map:
release_resource(priv->ioarea);
kfree(priv->ioarea);
out_mem:
kfree(priv);
out:
return ret;
} }
static int i2c_au1550_remove(struct platform_device *pdev) static int i2c_au1550_remove(struct platform_device *pdev)
...@@ -373,10 +351,6 @@ static int i2c_au1550_remove(struct platform_device *pdev) ...@@ -373,10 +351,6 @@ static int i2c_au1550_remove(struct platform_device *pdev)
i2c_del_adapter(&priv->adap); i2c_del_adapter(&priv->adap);
i2c_au1550_disable(priv); i2c_au1550_disable(priv);
iounmap(priv->psc_base);
release_resource(priv->ioarea);
kfree(priv->ioarea);
kfree(priv);
return 0; return 0;
} }
......
...@@ -181,6 +181,7 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev) ...@@ -181,6 +181,7 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev)
u32 clkh; u32 clkh;
u32 clkl; u32 clkl;
u32 input_clock = clk_get_rate(dev->clk); u32 input_clock = clk_get_rate(dev->clk);
struct device_node *of_node = dev->dev->of_node;
/* NOTE: I2C Clock divider programming info /* NOTE: I2C Clock divider programming info
* As per I2C specs the following formulas provide prescaler * As per I2C specs the following formulas provide prescaler
...@@ -196,6 +197,9 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev) ...@@ -196,6 +197,9 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev)
* where if PSC == 0, d = 7, * where if PSC == 0, d = 7,
* if PSC == 1, d = 6 * if PSC == 1, d = 6
* if PSC > 1 , d = 5 * if PSC > 1 , d = 5
*
* Note:
* d is always 6 on Keystone I2C controller
*/ */
/* get minimum of 7 MHz clock, but max of 12 MHz */ /* get minimum of 7 MHz clock, but max of 12 MHz */
...@@ -204,6 +208,9 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev) ...@@ -204,6 +208,9 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev)
psc++; /* better to run under spec than over */ psc++; /* better to run under spec than over */
d = (psc >= 2) ? 5 : 7 - psc; d = (psc >= 2) ? 5 : 7 - psc;
if (of_node && of_device_is_compatible(of_node, "ti,keystone-i2c"))
d = 6;
clk = ((input_clock / (psc + 1)) / (pdata->bus_freq * 1000)); clk = ((input_clock / (psc + 1)) / (pdata->bus_freq * 1000));
/* Avoid driving the bus too fast because of rounding errors above */ /* Avoid driving the bus too fast because of rounding errors above */
if (input_clock / (psc + 1) / clk > pdata->bus_freq * 1000) if (input_clock / (psc + 1) / clk > pdata->bus_freq * 1000)
...@@ -726,6 +733,7 @@ static struct i2c_algorithm i2c_davinci_algo = { ...@@ -726,6 +733,7 @@ static struct i2c_algorithm i2c_davinci_algo = {
static const struct of_device_id davinci_i2c_of_match[] = { static const struct of_device_id davinci_i2c_of_match[] = {
{.compatible = "ti,davinci-i2c", }, {.compatible = "ti,davinci-i2c", },
{.compatible = "ti,keystone-i2c", },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, davinci_i2c_of_match); MODULE_DEVICE_TABLE(of, davinci_i2c_of_match);
......
...@@ -165,7 +165,7 @@ static char *abort_sources[] = { ...@@ -165,7 +165,7 @@ static char *abort_sources[] = {
"lost arbitration", "lost arbitration",
}; };
u32 dw_readl(struct dw_i2c_dev *dev, int offset) static u32 dw_readl(struct dw_i2c_dev *dev, int offset)
{ {
u32 value; u32 value;
...@@ -181,7 +181,7 @@ u32 dw_readl(struct dw_i2c_dev *dev, int offset) ...@@ -181,7 +181,7 @@ u32 dw_readl(struct dw_i2c_dev *dev, int offset)
return value; return value;
} }
void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset) static void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
{ {
if (dev->accessor_flags & ACCESS_SWAP) if (dev->accessor_flags & ACCESS_SWAP)
b = swab32(b); b = swab32(b);
...@@ -438,7 +438,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) ...@@ -438,7 +438,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
__i2c_dw_enable(dev, true); __i2c_dw_enable(dev, true);
/* Clear and enable interrupts */ /* Clear and enable interrupts */
i2c_dw_clear_int(dev); dw_readl(dev, DW_IC_CLR_INTR);
dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK); dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK);
} }
...@@ -618,7 +618,7 @@ static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev) ...@@ -618,7 +618,7 @@ static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
/* /*
* Prepare controller for a transaction and call i2c_dw_xfer_msg * Prepare controller for a transaction and call i2c_dw_xfer_msg
*/ */
int static int
i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
{ {
struct dw_i2c_dev *dev = i2c_get_adapdata(adap); struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
...@@ -702,14 +702,17 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) ...@@ -702,14 +702,17 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(i2c_dw_xfer);
u32 i2c_dw_func(struct i2c_adapter *adap) static u32 i2c_dw_func(struct i2c_adapter *adap)
{ {
struct dw_i2c_dev *dev = i2c_get_adapdata(adap); struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
return dev->functionality; return dev->functionality;
} }
EXPORT_SYMBOL_GPL(i2c_dw_func);
static struct i2c_algorithm i2c_dw_algo = {
.master_xfer = i2c_dw_xfer,
.functionality = i2c_dw_func,
};
static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev) static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
{ {
...@@ -770,7 +773,7 @@ static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev) ...@@ -770,7 +773,7 @@ static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
* Interrupt service routine. This gets called whenever an I2C interrupt * Interrupt service routine. This gets called whenever an I2C interrupt
* occurs. * occurs.
*/ */
irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
{ {
struct dw_i2c_dev *dev = dev_id; struct dw_i2c_dev *dev = dev_id;
u32 stat, enabled; u32 stat, enabled;
...@@ -813,20 +816,6 @@ irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) ...@@ -813,20 +816,6 @@ irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
EXPORT_SYMBOL_GPL(i2c_dw_isr);
void i2c_dw_enable(struct dw_i2c_dev *dev)
{
/* Enable the adapter */
__i2c_dw_enable(dev, true);
}
EXPORT_SYMBOL_GPL(i2c_dw_enable);
u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev)
{
return dw_readl(dev, DW_IC_ENABLE);
}
EXPORT_SYMBOL_GPL(i2c_dw_is_enabled);
void i2c_dw_disable(struct dw_i2c_dev *dev) void i2c_dw_disable(struct dw_i2c_dev *dev)
{ {
...@@ -839,12 +828,6 @@ void i2c_dw_disable(struct dw_i2c_dev *dev) ...@@ -839,12 +828,6 @@ void i2c_dw_disable(struct dw_i2c_dev *dev)
} }
EXPORT_SYMBOL_GPL(i2c_dw_disable); EXPORT_SYMBOL_GPL(i2c_dw_disable);
void i2c_dw_clear_int(struct dw_i2c_dev *dev)
{
dw_readl(dev, DW_IC_CLR_INTR);
}
EXPORT_SYMBOL_GPL(i2c_dw_clear_int);
void i2c_dw_disable_int(struct dw_i2c_dev *dev) void i2c_dw_disable_int(struct dw_i2c_dev *dev)
{ {
dw_writel(dev, 0, DW_IC_INTR_MASK); dw_writel(dev, 0, DW_IC_INTR_MASK);
...@@ -857,5 +840,40 @@ u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev) ...@@ -857,5 +840,40 @@ u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev)
} }
EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param); EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param);
int i2c_dw_probe(struct dw_i2c_dev *dev)
{
struct i2c_adapter *adap = &dev->adapter;
int r;
init_completion(&dev->cmd_complete);
mutex_init(&dev->lock);
r = i2c_dw_init(dev);
if (r)
return r;
snprintf(adap->name, sizeof(adap->name),
"Synopsys DesignWare I2C adapter");
adap->algo = &i2c_dw_algo;
adap->dev.parent = dev->dev;
i2c_set_adapdata(adap, dev);
i2c_dw_disable_int(dev);
r = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr, IRQF_SHARED,
dev_name(dev->dev), dev);
if (r) {
dev_err(dev->dev, "failure requesting irq %i: %d\n",
dev->irq, r);
return r;
}
r = i2c_add_numbered_adapter(adap);
if (r)
dev_err(dev->dev, "failure adding adapter: %d\n", r);
return r;
}
EXPORT_SYMBOL_GPL(i2c_dw_probe);
MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter core"); MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter core");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -112,19 +112,11 @@ struct dw_i2c_dev { ...@@ -112,19 +112,11 @@ struct dw_i2c_dev {
#define ACCESS_SWAP 0x00000001 #define ACCESS_SWAP 0x00000001
#define ACCESS_16BIT 0x00000002 #define ACCESS_16BIT 0x00000002
extern u32 dw_readl(struct dw_i2c_dev *dev, int offset);
extern void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);
extern int i2c_dw_init(struct dw_i2c_dev *dev); extern int i2c_dw_init(struct dw_i2c_dev *dev);
extern int i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
int num);
extern u32 i2c_dw_func(struct i2c_adapter *adap);
extern irqreturn_t i2c_dw_isr(int this_irq, void *dev_id);
extern void i2c_dw_enable(struct dw_i2c_dev *dev);
extern u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev);
extern void i2c_dw_disable(struct dw_i2c_dev *dev); extern void i2c_dw_disable(struct dw_i2c_dev *dev);
extern void i2c_dw_clear_int(struct dw_i2c_dev *dev);
extern void i2c_dw_disable_int(struct dw_i2c_dev *dev); extern void i2c_dw_disable_int(struct dw_i2c_dev *dev);
extern u32 i2c_dw_read_comp_param(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_BAYTRAIL) #if IS_ENABLED(CONFIG_I2C_DESIGNWARE_BAYTRAIL)
extern int i2c_dw_eval_lock_support(struct dw_i2c_dev *dev); extern int i2c_dw_eval_lock_support(struct dw_i2c_dev *dev);
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/acpi.h>
#include "i2c-designware-core.h" #include "i2c-designware-core.h"
#define DRIVER_NAME "i2c-designware-pci" #define DRIVER_NAME "i2c-designware-pci"
...@@ -158,11 +159,6 @@ static struct dw_pci_controller dw_pci_controllers[] = { ...@@ -158,11 +159,6 @@ static struct dw_pci_controller dw_pci_controllers[] = {
}, },
}; };
static struct i2c_algorithm i2c_dw_algo = {
.master_xfer = i2c_dw_xfer,
.functionality = i2c_dw_func,
};
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int i2c_dw_pci_suspend(struct device *dev) static int i2c_dw_pci_suspend(struct device *dev)
{ {
...@@ -222,13 +218,12 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev, ...@@ -222,13 +218,12 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
if (!dev) if (!dev)
return -ENOMEM; return -ENOMEM;
init_completion(&dev->cmd_complete);
mutex_init(&dev->lock);
dev->clk = NULL; dev->clk = NULL;
dev->controller = controller; dev->controller = controller;
dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz; dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
dev->base = pcim_iomap_table(pdev)[0]; dev->base = pcim_iomap_table(pdev)[0];
dev->dev = &pdev->dev; dev->dev = &pdev->dev;
dev->irq = pdev->irq;
dev->functionality = controller->functionality | dev->functionality = controller->functionality |
DW_DEFAULT_FUNCTIONALITY; DW_DEFAULT_FUNCTIONALITY;
...@@ -246,34 +241,16 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev, ...@@ -246,34 +241,16 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
dev->tx_fifo_depth = controller->tx_fifo_depth; dev->tx_fifo_depth = controller->tx_fifo_depth;
dev->rx_fifo_depth = controller->rx_fifo_depth; dev->rx_fifo_depth = controller->rx_fifo_depth;
r = i2c_dw_init(dev);
if (r)
return r;
adap = &dev->adapter; adap = &dev->adapter;
i2c_set_adapdata(adap, dev);
adap->owner = THIS_MODULE; adap->owner = THIS_MODULE;
adap->class = 0; adap->class = 0;
adap->algo = &i2c_dw_algo; ACPI_COMPANION_SET(&adap->dev, ACPI_COMPANION(&pdev->dev));
adap->dev.parent = &pdev->dev;
adap->nr = controller->bus_num; adap->nr = controller->bus_num;
snprintf(adap->name, sizeof(adap->name), "i2c-designware-pci"); r = i2c_dw_probe(dev);
if (r)
r = devm_request_irq(&pdev->dev, pdev->irq, i2c_dw_isr,
IRQF_SHARED | IRQF_COND_SUSPEND, adap->name, dev);
if (r) {
dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
return r;
}
i2c_dw_disable_int(dev);
i2c_dw_clear_int(dev);
r = i2c_add_numbered_adapter(adap);
if (r) {
dev_err(&pdev->dev, "failure adding adapter\n");
return r; return r;
}
pm_runtime_set_autosuspend_delay(&pdev->dev, 1000); pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_use_autosuspend(&pdev->dev);
......
...@@ -42,10 +42,6 @@ ...@@ -42,10 +42,6 @@
#include <linux/platform_data/i2c-designware.h> #include <linux/platform_data/i2c-designware.h>
#include "i2c-designware-core.h" #include "i2c-designware-core.h"
static struct i2c_algorithm i2c_dw_algo = {
.master_xfer = i2c_dw_xfer,
.functionality = i2c_dw_func,
};
static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev) static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
{ {
return clk_get_rate(dev->clk)/1000; return clk_get_rate(dev->clk)/1000;
...@@ -97,7 +93,6 @@ static void dw_i2c_acpi_params(struct platform_device *pdev, char method[], ...@@ -97,7 +93,6 @@ static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
static int dw_i2c_acpi_configure(struct platform_device *pdev) static int dw_i2c_acpi_configure(struct platform_device *pdev)
{ {
struct dw_i2c_dev *dev = platform_get_drvdata(pdev); struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
const struct acpi_device_id *id;
dev->adapter.nr = -1; dev->adapter.nr = -1;
dev->tx_fifo_depth = 32; dev->tx_fifo_depth = 32;
...@@ -111,29 +106,9 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev) ...@@ -111,29 +106,9 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev)
dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt, dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt,
&dev->sda_hold_time); &dev->sda_hold_time);
/*
* Provide a way for Designware I2C host controllers that are not
* based on Intel LPSS to specify their input clock frequency via
* id->driver_data.
*/
id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
if (id && id->driver_data)
clk_register_fixed_rate(&pdev->dev, dev_name(&pdev->dev), NULL,
CLK_IS_ROOT, id->driver_data);
return 0; return 0;
} }
static void dw_i2c_acpi_unconfigure(struct platform_device *pdev)
{
struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
const struct acpi_device_id *id;
id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
if (id && id->driver_data)
clk_unregister(dev->clk);
}
static const struct acpi_device_id dw_i2c_acpi_match[] = { static const struct acpi_device_id dw_i2c_acpi_match[] = {
{ "INT33C2", 0 }, { "INT33C2", 0 },
{ "INT33C3", 0 }, { "INT33C3", 0 },
...@@ -141,7 +116,7 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = { ...@@ -141,7 +116,7 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = {
{ "INT3433", 0 }, { "INT3433", 0 },
{ "80860F41", 0 }, { "80860F41", 0 },
{ "808622C1", 0 }, { "808622C1", 0 },
{ "AMD0010", 133 * 1000 * 1000 }, { "AMD0010", 0 },
{ } { }
}; };
MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match); MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match);
...@@ -150,10 +125,9 @@ static inline int dw_i2c_acpi_configure(struct platform_device *pdev) ...@@ -150,10 +125,9 @@ static inline int dw_i2c_acpi_configure(struct platform_device *pdev)
{ {
return -ENODEV; return -ENODEV;
} }
static inline void dw_i2c_acpi_unconfigure(struct platform_device *pdev) { }
#endif #endif
static int dw_i2c_probe(struct platform_device *pdev) static int dw_i2c_plat_probe(struct platform_device *pdev)
{ {
struct dw_i2c_dev *dev; struct dw_i2c_dev *dev;
struct i2c_adapter *adap; struct i2c_adapter *adap;
...@@ -175,8 +149,6 @@ static int dw_i2c_probe(struct platform_device *pdev) ...@@ -175,8 +149,6 @@ static int dw_i2c_probe(struct platform_device *pdev)
if (IS_ERR(dev->base)) if (IS_ERR(dev->base))
return PTR_ERR(dev->base); return PTR_ERR(dev->base);
init_completion(&dev->cmd_complete);
mutex_init(&dev->lock);
dev->dev = &pdev->dev; dev->dev = &pdev->dev;
dev->irq = irq; dev->irq = irq;
platform_set_drvdata(pdev, dev); platform_set_drvdata(pdev, dev);
...@@ -251,26 +223,11 @@ static int dw_i2c_probe(struct platform_device *pdev) ...@@ -251,26 +223,11 @@ static int dw_i2c_probe(struct platform_device *pdev)
dev->rx_fifo_depth = ((param1 >> 8) & 0xff) + 1; dev->rx_fifo_depth = ((param1 >> 8) & 0xff) + 1;
dev->adapter.nr = pdev->id; dev->adapter.nr = pdev->id;
} }
r = i2c_dw_init(dev);
if (r)
return r;
i2c_dw_disable_int(dev);
r = devm_request_irq(&pdev->dev, dev->irq, i2c_dw_isr, IRQF_SHARED,
pdev->name, dev);
if (r) {
dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
return r;
}
adap = &dev->adapter; adap = &dev->adapter;
i2c_set_adapdata(adap, dev);
adap->owner = THIS_MODULE; adap->owner = THIS_MODULE;
adap->class = I2C_CLASS_DEPRECATED; adap->class = I2C_CLASS_DEPRECATED;
strlcpy(adap->name, "Synopsys DesignWare I2C adapter", ACPI_COMPANION_SET(&adap->dev, ACPI_COMPANION(&pdev->dev));
sizeof(adap->name));
adap->algo = &i2c_dw_algo;
adap->dev.parent = &pdev->dev;
adap->dev.of_node = pdev->dev.of_node; adap->dev.of_node = pdev->dev.of_node;
if (dev->pm_runtime_disabled) { if (dev->pm_runtime_disabled) {
...@@ -282,9 +239,8 @@ static int dw_i2c_probe(struct platform_device *pdev) ...@@ -282,9 +239,8 @@ static int dw_i2c_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
} }
r = i2c_add_numbered_adapter(adap); r = i2c_dw_probe(dev);
if (r) { if (r) {
dev_err(&pdev->dev, "failure adding adapter\n");
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
return r; return r;
} }
...@@ -292,7 +248,7 @@ static int dw_i2c_probe(struct platform_device *pdev) ...@@ -292,7 +248,7 @@ static int dw_i2c_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int dw_i2c_remove(struct platform_device *pdev) static int dw_i2c_plat_remove(struct platform_device *pdev)
{ {
struct dw_i2c_dev *dev = platform_get_drvdata(pdev); struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
...@@ -306,9 +262,6 @@ static int dw_i2c_remove(struct platform_device *pdev) ...@@ -306,9 +262,6 @@ static int dw_i2c_remove(struct platform_device *pdev)
pm_runtime_put_sync(&pdev->dev); pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
if (has_acpi_companion(&pdev->dev))
dw_i2c_acpi_unconfigure(pdev);
return 0; return 0;
} }
...@@ -321,23 +274,23 @@ MODULE_DEVICE_TABLE(of, dw_i2c_of_match); ...@@ -321,23 +274,23 @@ MODULE_DEVICE_TABLE(of, dw_i2c_of_match);
#endif #endif
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int dw_i2c_prepare(struct device *dev) static int dw_i2c_plat_prepare(struct device *dev)
{ {
return pm_runtime_suspended(dev); return pm_runtime_suspended(dev);
} }
static void dw_i2c_complete(struct device *dev) static void dw_i2c_plat_complete(struct device *dev)
{ {
if (dev->power.direct_complete) if (dev->power.direct_complete)
pm_request_resume(dev); pm_request_resume(dev);
} }
#else #else
#define dw_i2c_prepare NULL #define dw_i2c_plat_prepare NULL
#define dw_i2c_complete NULL #define dw_i2c_plat_complete NULL
#endif #endif
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int dw_i2c_suspend(struct device *dev) static int dw_i2c_plat_suspend(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev); struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
...@@ -348,7 +301,7 @@ static int dw_i2c_suspend(struct device *dev) ...@@ -348,7 +301,7 @@ static int dw_i2c_suspend(struct device *dev)
return 0; return 0;
} }
static int dw_i2c_resume(struct device *dev) static int dw_i2c_plat_resume(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev); struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
...@@ -362,10 +315,10 @@ static int dw_i2c_resume(struct device *dev) ...@@ -362,10 +315,10 @@ static int dw_i2c_resume(struct device *dev)
} }
static const struct dev_pm_ops dw_i2c_dev_pm_ops = { static const struct dev_pm_ops dw_i2c_dev_pm_ops = {
.prepare = dw_i2c_prepare, .prepare = dw_i2c_plat_prepare,
.complete = dw_i2c_complete, .complete = dw_i2c_plat_complete,
SET_SYSTEM_SLEEP_PM_OPS(dw_i2c_suspend, dw_i2c_resume) SET_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume)
SET_RUNTIME_PM_OPS(dw_i2c_suspend, dw_i2c_resume, NULL) SET_RUNTIME_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume, NULL)
}; };
#define DW_I2C_DEV_PMOPS (&dw_i2c_dev_pm_ops) #define DW_I2C_DEV_PMOPS (&dw_i2c_dev_pm_ops)
...@@ -377,8 +330,8 @@ static const struct dev_pm_ops dw_i2c_dev_pm_ops = { ...@@ -377,8 +330,8 @@ static const struct dev_pm_ops dw_i2c_dev_pm_ops = {
MODULE_ALIAS("platform:i2c_designware"); MODULE_ALIAS("platform:i2c_designware");
static struct platform_driver dw_i2c_driver = { static struct platform_driver dw_i2c_driver = {
.probe = dw_i2c_probe, .probe = dw_i2c_plat_probe,
.remove = dw_i2c_remove, .remove = dw_i2c_plat_remove,
.driver = { .driver = {
.name = "i2c_designware", .name = "i2c_designware",
.of_match_table = of_match_ptr(dw_i2c_of_match), .of_match_table = of_match_ptr(dw_i2c_of_match),
......
...@@ -60,6 +60,8 @@ ...@@ -60,6 +60,8 @@
* BayTrail (SOC) 0x0f12 32 hard yes yes yes * BayTrail (SOC) 0x0f12 32 hard yes yes yes
* Sunrise Point-H (PCH) 0xa123 32 hard yes yes yes * Sunrise Point-H (PCH) 0xa123 32 hard yes yes yes
* Sunrise Point-LP (PCH) 0x9d23 32 hard yes yes yes * Sunrise Point-LP (PCH) 0x9d23 32 hard yes yes yes
* DNV (SOC) 0x19df 32 hard yes yes yes
* Broxton (SOC) 0x5ad4 32 hard yes yes yes
* *
* Features supported by this driver: * Features supported by this driver:
* Software PEC no * Software PEC no
...@@ -202,6 +204,8 @@ ...@@ -202,6 +204,8 @@
#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_SMBUS 0x9ca2 #define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_SMBUS 0x9ca2
#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS 0xa123 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS 0xa123
#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS 0x9d23 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS 0x9d23
#define PCI_DEVICE_ID_INTEL_DNV_SMBUS 0x19df
#define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4
struct i801_mux_config { struct i801_mux_config {
char *gpio_chip; char *gpio_chip;
...@@ -863,6 +867,8 @@ static const struct pci_device_id i801_ids[] = { ...@@ -863,6 +867,8 @@ static const struct pci_device_id i801_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BRASWELL_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BRASWELL_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DNV_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BROXTON_SMBUS) },
{ 0, } { 0, }
}; };
...@@ -1251,11 +1257,15 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -1251,11 +1257,15 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
priv->adapter.owner = THIS_MODULE; priv->adapter.owner = THIS_MODULE;
priv->adapter.class = i801_get_adapter_class(priv); priv->adapter.class = i801_get_adapter_class(priv);
priv->adapter.algo = &smbus_algorithm; priv->adapter.algo = &smbus_algorithm;
priv->adapter.dev.parent = &dev->dev;
ACPI_COMPANION_SET(&priv->adapter.dev, ACPI_COMPANION(&dev->dev));
priv->adapter.retries = 3;
priv->pci_dev = dev; priv->pci_dev = dev;
switch (dev->device) { switch (dev->device) {
case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS:
case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS: case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS:
case PCI_DEVICE_ID_INTEL_DNV_SMBUS:
priv->features |= FEATURE_I2C_BLOCK_READ; priv->features |= FEATURE_I2C_BLOCK_READ;
priv->features |= FEATURE_IRQ; priv->features |= FEATURE_IRQ;
priv->features |= FEATURE_SMBUS_PEC; priv->features |= FEATURE_SMBUS_PEC;
...@@ -1381,12 +1391,6 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -1381,12 +1391,6 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
i801_add_tco(priv); i801_add_tco(priv);
/* set up the sysfs linkage to our parent device */
priv->adapter.dev.parent = &dev->dev;
/* Retry up to 3 times on lost arbitration */
priv->adapter.retries = 3;
snprintf(priv->adapter.name, sizeof(priv->adapter.name), snprintf(priv->adapter.name, sizeof(priv->adapter.name),
"SMBus I801 adapter at %04lx", priv->smba); "SMBus I801 adapter at %04lx", priv->smba);
err = i2c_add_adapter(&priv->adapter); err = i2c_add_adapter(&priv->adapter);
......
...@@ -798,6 +798,7 @@ static const struct of_device_id ibm_iic_match[] = { ...@@ -798,6 +798,7 @@ static const struct of_device_id ibm_iic_match[] = {
{ .compatible = "ibm,iic", }, { .compatible = "ibm,iic", },
{} {}
}; };
MODULE_DEVICE_TABLE(of, ibm_iic_match);
static struct platform_driver ibm_iic_driver = { static struct platform_driver ibm_iic_driver = {
.driver = { .driver = {
......
...@@ -278,8 +278,6 @@ ...@@ -278,8 +278,6 @@
#define ISR_COMPLETE(err) (ISR_COMPLETE_M | (ISR_STATUS_M & (err))) #define ISR_COMPLETE(err) (ISR_COMPLETE_M | (ISR_STATUS_M & (err)))
#define ISR_FATAL(err) (ISR_COMPLETE(err) | ISR_FATAL_M) #define ISR_FATAL(err) (ISR_COMPLETE(err) | ISR_FATAL_M)
#define REL_SOC_IP_SCB_2_2_1 0x00020201
enum img_i2c_mode { enum img_i2c_mode {
MODE_INACTIVE, MODE_INACTIVE,
MODE_RAW, MODE_RAW,
...@@ -536,6 +534,7 @@ static void img_i2c_read_fifo(struct img_i2c *i2c) ...@@ -536,6 +534,7 @@ static void img_i2c_read_fifo(struct img_i2c *i2c)
u32 fifo_status; u32 fifo_status;
u8 data; u8 data;
img_i2c_wr_rd_fence(i2c);
fifo_status = img_i2c_readl(i2c, SCB_FIFO_STATUS_REG); fifo_status = img_i2c_readl(i2c, SCB_FIFO_STATUS_REG);
if (fifo_status & FIFO_READ_EMPTY) if (fifo_status & FIFO_READ_EMPTY)
break; break;
...@@ -544,7 +543,6 @@ static void img_i2c_read_fifo(struct img_i2c *i2c) ...@@ -544,7 +543,6 @@ static void img_i2c_read_fifo(struct img_i2c *i2c)
*i2c->msg.buf = data; *i2c->msg.buf = data;
img_i2c_writel(i2c, SCB_READ_FIFO_REG, 0xff); img_i2c_writel(i2c, SCB_READ_FIFO_REG, 0xff);
img_i2c_wr_rd_fence(i2c);
i2c->msg.len--; i2c->msg.len--;
i2c->msg.buf++; i2c->msg.buf++;
} }
...@@ -556,12 +554,12 @@ static void img_i2c_write_fifo(struct img_i2c *i2c) ...@@ -556,12 +554,12 @@ static void img_i2c_write_fifo(struct img_i2c *i2c)
while (i2c->msg.len) { while (i2c->msg.len) {
u32 fifo_status; u32 fifo_status;
img_i2c_wr_rd_fence(i2c);
fifo_status = img_i2c_readl(i2c, SCB_FIFO_STATUS_REG); fifo_status = img_i2c_readl(i2c, SCB_FIFO_STATUS_REG);
if (fifo_status & FIFO_WRITE_FULL) if (fifo_status & FIFO_WRITE_FULL)
break; break;
img_i2c_writel(i2c, SCB_WRITE_DATA_REG, *i2c->msg.buf); img_i2c_writel(i2c, SCB_WRITE_DATA_REG, *i2c->msg.buf);
img_i2c_wr_rd_fence(i2c);
i2c->msg.len--; i2c->msg.len--;
i2c->msg.buf++; i2c->msg.buf++;
} }
...@@ -859,7 +857,7 @@ static unsigned int img_i2c_auto(struct img_i2c *i2c, ...@@ -859,7 +857,7 @@ static unsigned int img_i2c_auto(struct img_i2c *i2c,
} }
/* Enable transaction halt on start bit */ /* Enable transaction halt on start bit */
if (!i2c->last_msg && i2c->line_status & LINESTAT_START_BIT_DET) { if (!i2c->last_msg && line_status & LINESTAT_START_BIT_DET) {
img_i2c_transaction_halt(i2c, true); img_i2c_transaction_halt(i2c, true);
/* we're no longer interested in the slave event */ /* we're no longer interested in the slave event */
i2c->int_enable &= ~INT_SLAVE_EVENT; i2c->int_enable &= ~INT_SLAVE_EVENT;
...@@ -1062,6 +1060,15 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ...@@ -1062,6 +1060,15 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
i2c->last_msg = (i == num - 1); i2c->last_msg = (i == num - 1);
reinit_completion(&i2c->msg_complete); reinit_completion(&i2c->msg_complete);
/*
* Clear line status and all interrupts before starting a
* transfer, as we may have unserviced interrupts from
* previous transfers that might be handled in the context
* of the new transfer.
*/
img_i2c_writel(i2c, SCB_INT_CLEAR_REG, ~0);
img_i2c_writel(i2c, SCB_CLEAR_REG, ~0);
if (atomic) if (atomic)
img_i2c_atomic_start(i2c); img_i2c_atomic_start(i2c);
else if (msg->flags & I2C_M_RD) else if (msg->flags & I2C_M_RD)
...@@ -1120,13 +1127,8 @@ static int img_i2c_init(struct img_i2c *i2c) ...@@ -1120,13 +1127,8 @@ static int img_i2c_init(struct img_i2c *i2c)
return -EINVAL; return -EINVAL;
} }
if (rev == REL_SOC_IP_SCB_2_2_1) { /* Fencing enabled by default. */
i2c->need_wr_rd_fence = true; i2c->need_wr_rd_fence = true;
dev_info(i2c->adap.dev.parent, "fence quirk enabled");
}
bitrate_khz = i2c->bitrate / 1000;
clk_khz = clk_get_rate(i2c->scb_clk) / 1000;
/* Determine what mode we're in from the bitrate */ /* Determine what mode we're in from the bitrate */
timing = timings[0]; timing = timings[0];
...@@ -1136,6 +1138,17 @@ static int img_i2c_init(struct img_i2c *i2c) ...@@ -1136,6 +1138,17 @@ static int img_i2c_init(struct img_i2c *i2c)
break; break;
} }
} }
if (i2c->bitrate > timings[ARRAY_SIZE(timings) - 1].max_bitrate) {
dev_warn(i2c->adap.dev.parent,
"requested bitrate (%u) is higher than the max bitrate supported (%u)\n",
i2c->bitrate,
timings[ARRAY_SIZE(timings) - 1].max_bitrate);
timing = timings[ARRAY_SIZE(timings) - 1];
i2c->bitrate = timing.max_bitrate;
}
bitrate_khz = i2c->bitrate / 1000;
clk_khz = clk_get_rate(i2c->scb_clk) / 1000;
/* Find the prescale that would give us that inc (approx delay = 0) */ /* Find the prescale that would give us that inc (approx delay = 0) */
prescale = SCB_OPT_INC * clk_khz / (256 * 16 * bitrate_khz); prescale = SCB_OPT_INC * clk_khz / (256 * 16 * bitrate_khz);
...@@ -1182,32 +1195,32 @@ static int img_i2c_init(struct img_i2c *i2c) ...@@ -1182,32 +1195,32 @@ static int img_i2c_init(struct img_i2c *i2c)
((bitrate_khz * clk_period) / 2)) ((bitrate_khz * clk_period) / 2))
int_bitrate++; int_bitrate++;
/* Setup TCKH value */ /*
tckh = timing.tckh / clk_period; * Setup clock duty cycle, start with 50% and adjust TCKH and TCKL
if (timing.tckh % clk_period) * values from there if they don't meet minimum timing requirements
tckh++; */
tckh = int_bitrate / 2;
tckl = int_bitrate - tckh;
if (tckh > 0) /* Adjust TCKH and TCKL values */
data = tckh - 1; data = DIV_ROUND_UP(timing.tckl, clk_period);
else
data = 0;
img_i2c_writel(i2c, SCB_TIME_TCKH_REG, data); if (tckl < data) {
tckl = data;
tckh = int_bitrate - tckl;
}
/* Setup TCKL value */ if (tckh > 0)
tckl = int_bitrate - tckh; --tckh;
if (tckl > 0) if (tckl > 0)
data = tckl - 1; --tckl;
else
data = 0;
img_i2c_writel(i2c, SCB_TIME_TCKL_REG, data); img_i2c_writel(i2c, SCB_TIME_TCKH_REG, tckh);
img_i2c_writel(i2c, SCB_TIME_TCKL_REG, tckl);
/* Setup TSDH value */ /* Setup TSDH value */
tsdh = timing.tsdh / clk_period; tsdh = DIV_ROUND_UP(timing.tsdh, clk_period);
if (timing.tsdh % clk_period)
tsdh++;
if (tsdh > 1) if (tsdh > 1)
data = tsdh - 1; data = tsdh - 1;
......
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_dma.h> #include <linux/of_dma.h>
#include <linux/of_gpio.h>
#include <linux/platform_data/i2c-imx.h> #include <linux/platform_data/i2c-imx.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -207,6 +208,11 @@ struct imx_i2c_struct { ...@@ -207,6 +208,11 @@ struct imx_i2c_struct {
unsigned int cur_clk; unsigned int cur_clk;
unsigned int bitrate; unsigned int bitrate;
const struct imx_i2c_hwdata *hwdata; const struct imx_i2c_hwdata *hwdata;
struct i2c_bus_recovery_info rinfo;
struct pinctrl *pinctrl;
struct pinctrl_state *pinctrl_pins_default;
struct pinctrl_state *pinctrl_pins_gpio;
struct imx_i2c_dma *dma; struct imx_i2c_dma *dma;
}; };
...@@ -461,7 +467,7 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx) ...@@ -461,7 +467,7 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx)
{ {
if (imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR) & I2SR_RXAK) { if (imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR) & I2SR_RXAK) {
dev_dbg(&i2c_imx->adapter.dev, "<%s> No ACK\n", __func__); dev_dbg(&i2c_imx->adapter.dev, "<%s> No ACK\n", __func__);
return -EIO; /* No ACK */ return -ENXIO; /* No ACK */
} }
dev_dbg(&i2c_imx->adapter.dev, "<%s> ACK received\n", __func__); dev_dbg(&i2c_imx->adapter.dev, "<%s> ACK received\n", __func__);
...@@ -896,6 +902,13 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, ...@@ -896,6 +902,13 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
/* Start I2C transfer */ /* Start I2C transfer */
result = i2c_imx_start(i2c_imx); result = i2c_imx_start(i2c_imx);
if (result) {
if (i2c_imx->adapter.bus_recovery_info) {
i2c_recover_bus(&i2c_imx->adapter);
result = i2c_imx_start(i2c_imx);
}
}
if (result) if (result)
goto fail0; goto fail0;
...@@ -956,6 +969,55 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, ...@@ -956,6 +969,55 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
return (result < 0) ? result : num; return (result < 0) ? result : num;
} }
static void i2c_imx_prepare_recovery(struct i2c_adapter *adap)
{
struct imx_i2c_struct *i2c_imx;
i2c_imx = container_of(adap, struct imx_i2c_struct, adapter);
pinctrl_select_state(i2c_imx->pinctrl, i2c_imx->pinctrl_pins_gpio);
}
static void i2c_imx_unprepare_recovery(struct i2c_adapter *adap)
{
struct imx_i2c_struct *i2c_imx;
i2c_imx = container_of(adap, struct imx_i2c_struct, adapter);
pinctrl_select_state(i2c_imx->pinctrl, i2c_imx->pinctrl_pins_default);
}
static void i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx,
struct platform_device *pdev)
{
struct i2c_bus_recovery_info *rinfo = &i2c_imx->rinfo;
i2c_imx->pinctrl_pins_default = pinctrl_lookup_state(i2c_imx->pinctrl,
PINCTRL_STATE_DEFAULT);
i2c_imx->pinctrl_pins_gpio = pinctrl_lookup_state(i2c_imx->pinctrl,
"gpio");
rinfo->sda_gpio = of_get_named_gpio_flags(pdev->dev.of_node,
"sda-gpios", 0, NULL);
rinfo->scl_gpio = of_get_named_gpio_flags(pdev->dev.of_node,
"scl-gpios", 0, NULL);
if (!gpio_is_valid(rinfo->sda_gpio) ||
!gpio_is_valid(rinfo->scl_gpio) ||
IS_ERR(i2c_imx->pinctrl_pins_default) ||
IS_ERR(i2c_imx->pinctrl_pins_gpio)) {
dev_dbg(&pdev->dev, "recovery information incomplete\n");
return;
}
dev_dbg(&pdev->dev, "using scl-gpio %d and sda-gpio %d for recovery\n",
rinfo->sda_gpio, rinfo->scl_gpio);
rinfo->prepare_recovery = i2c_imx_prepare_recovery;
rinfo->unprepare_recovery = i2c_imx_unprepare_recovery;
rinfo->recover_bus = i2c_generic_gpio_recovery;
i2c_imx->adapter.bus_recovery_info = rinfo;
}
static u32 i2c_imx_func(struct i2c_adapter *adapter) static u32 i2c_imx_func(struct i2c_adapter *adapter)
{ {
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL
...@@ -1023,6 +1085,13 @@ static int i2c_imx_probe(struct platform_device *pdev) ...@@ -1023,6 +1085,13 @@ static int i2c_imx_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "can't enable I2C clock\n"); dev_err(&pdev->dev, "can't enable I2C clock\n");
return ret; return ret;
} }
i2c_imx->pinctrl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR(i2c_imx->pinctrl)) {
ret = PTR_ERR(i2c_imx->pinctrl);
goto clk_disable;
}
/* Request IRQ */ /* Request IRQ */
ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0, ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0,
pdev->name, i2c_imx); pdev->name, i2c_imx);
...@@ -1056,6 +1125,8 @@ static int i2c_imx_probe(struct platform_device *pdev) ...@@ -1056,6 +1125,8 @@ static int i2c_imx_probe(struct platform_device *pdev)
goto clk_disable; goto clk_disable;
} }
i2c_imx_init_recovery_info(i2c_imx, pdev);
/* Set up platform driver data */ /* Set up platform driver data */
platform_set_drvdata(pdev, i2c_imx); platform_set_drvdata(pdev, i2c_imx);
clk_disable_unprepare(i2c_imx->clk); clk_disable_unprepare(i2c_imx->clk);
......
...@@ -165,14 +165,13 @@ struct ismt_desc { ...@@ -165,14 +165,13 @@ struct ismt_desc {
struct ismt_priv { struct ismt_priv {
struct i2c_adapter adapter; struct i2c_adapter adapter;
void *smba; /* PCI BAR */ void __iomem *smba; /* PCI BAR */
struct pci_dev *pci_dev; struct pci_dev *pci_dev;
struct ismt_desc *hw; /* descriptor virt base addr */ struct ismt_desc *hw; /* descriptor virt base addr */
dma_addr_t io_rng_dma; /* descriptor HW base addr */ dma_addr_t io_rng_dma; /* descriptor HW base addr */
u8 head; /* ring buffer head pointer */ u8 head; /* ring buffer head pointer */
struct completion cmp; /* interrupt completion */ struct completion cmp; /* interrupt completion */
u8 dma_buffer[I2C_SMBUS_BLOCK_MAX + 1]; /* temp R/W data buffer */ u8 dma_buffer[I2C_SMBUS_BLOCK_MAX + 1]; /* temp R/W data buffer */
bool using_msi; /* type of interrupt flag */
}; };
/** /**
...@@ -398,7 +397,7 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, ...@@ -398,7 +397,7 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, read_write); desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, read_write);
/* Initialize common control bits */ /* Initialize common control bits */
if (likely(priv->using_msi)) if (likely(pci_dev_msi_enabled(priv->pci_dev)))
desc->control = ISMT_DESC_INT | ISMT_DESC_FAIR; desc->control = ISMT_DESC_INT | ISMT_DESC_FAIR;
else else
desc->control = ISMT_DESC_FAIR; desc->control = ISMT_DESC_FAIR;
...@@ -789,11 +788,8 @@ static int ismt_int_init(struct ismt_priv *priv) ...@@ -789,11 +788,8 @@ static int ismt_int_init(struct ismt_priv *priv)
/* Try using MSI interrupts */ /* Try using MSI interrupts */
err = pci_enable_msi(priv->pci_dev); err = pci_enable_msi(priv->pci_dev);
if (err) { if (err)
dev_warn(&priv->pci_dev->dev,
"Unable to use MSI interrupts, falling back to legacy\n");
goto intx; goto intx;
}
err = devm_request_irq(&priv->pci_dev->dev, err = devm_request_irq(&priv->pci_dev->dev,
priv->pci_dev->irq, priv->pci_dev->irq,
...@@ -806,11 +802,13 @@ static int ismt_int_init(struct ismt_priv *priv) ...@@ -806,11 +802,13 @@ static int ismt_int_init(struct ismt_priv *priv)
goto intx; goto intx;
} }
priv->using_msi = true; return 0;
goto done;
/* Try using legacy interrupts */ /* Try using legacy interrupts */
intx: intx:
dev_warn(&priv->pci_dev->dev,
"Unable to use MSI interrupts, falling back to legacy\n");
err = devm_request_irq(&priv->pci_dev->dev, err = devm_request_irq(&priv->pci_dev->dev,
priv->pci_dev->irq, priv->pci_dev->irq,
ismt_do_interrupt, ismt_do_interrupt,
...@@ -819,12 +817,9 @@ static int ismt_int_init(struct ismt_priv *priv) ...@@ -819,12 +817,9 @@ static int ismt_int_init(struct ismt_priv *priv)
priv); priv);
if (err) { if (err) {
dev_err(&priv->pci_dev->dev, "no usable interrupts\n"); dev_err(&priv->pci_dev->dev, "no usable interrupts\n");
return -ENODEV; return err;
} }
priv->using_msi = false;
done:
return 0; return 0;
} }
...@@ -847,17 +842,13 @@ ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -847,17 +842,13 @@ ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return -ENOMEM; return -ENOMEM;
pci_set_drvdata(pdev, priv); pci_set_drvdata(pdev, priv);
i2c_set_adapdata(&priv->adapter, priv); i2c_set_adapdata(&priv->adapter, priv);
priv->adapter.owner = THIS_MODULE; priv->adapter.owner = THIS_MODULE;
priv->adapter.class = I2C_CLASS_HWMON; priv->adapter.class = I2C_CLASS_HWMON;
priv->adapter.algo = &smbus_algorithm; priv->adapter.algo = &smbus_algorithm;
/* set up the sysfs linkage to our parent device */
priv->adapter.dev.parent = &pdev->dev; priv->adapter.dev.parent = &pdev->dev;
ACPI_COMPANION_SET(&priv->adapter.dev, ACPI_COMPANION(&pdev->dev));
/* number of retries on lost arbitration */
priv->adapter.retries = ISMT_MAX_RETRIES; priv->adapter.retries = ISMT_MAX_RETRIES;
priv->pci_dev = pdev; priv->pci_dev = pdev;
...@@ -904,8 +895,7 @@ ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -904,8 +895,7 @@ ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id)
priv->smba = pcim_iomap(pdev, SMBBAR, len); priv->smba = pcim_iomap(pdev, SMBBAR, len);
if (!priv->smba) { if (!priv->smba) {
dev_err(&pdev->dev, "Unable to ioremap SMBus BAR\n"); dev_err(&pdev->dev, "Unable to ioremap SMBus BAR\n");
err = -ENODEV; return -ENODEV;
goto fail;
} }
if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) || if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) ||
...@@ -915,32 +905,26 @@ ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -915,32 +905,26 @@ ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id)
DMA_BIT_MASK(32)) != 0)) { DMA_BIT_MASK(32)) != 0)) {
dev_err(&pdev->dev, "pci_set_dma_mask fail %p\n", dev_err(&pdev->dev, "pci_set_dma_mask fail %p\n",
pdev); pdev);
err = -ENODEV; return -ENODEV;
goto fail;
} }
} }
err = ismt_dev_init(priv); err = ismt_dev_init(priv);
if (err) if (err)
goto fail; return err;
ismt_hw_init(priv); ismt_hw_init(priv);
err = ismt_int_init(priv); err = ismt_int_init(priv);
if (err) if (err)
goto fail; return err;
err = i2c_add_adapter(&priv->adapter); err = i2c_add_adapter(&priv->adapter);
if (err) { if (err) {
dev_err(&pdev->dev, "Failed to add SMBus iSMT adapter\n"); dev_err(&pdev->dev, "Failed to add SMBus iSMT adapter\n");
err = -ENODEV; return -ENODEV;
goto fail;
} }
return 0; return 0;
fail:
pci_release_region(pdev, SMBBAR);
return err;
} }
/** /**
...@@ -952,47 +936,13 @@ static void ismt_remove(struct pci_dev *pdev) ...@@ -952,47 +936,13 @@ static void ismt_remove(struct pci_dev *pdev)
struct ismt_priv *priv = pci_get_drvdata(pdev); struct ismt_priv *priv = pci_get_drvdata(pdev);
i2c_del_adapter(&priv->adapter); i2c_del_adapter(&priv->adapter);
pci_release_region(pdev, SMBBAR);
} }
/**
* ismt_suspend() - place the device in suspend
* @pdev: PCI-Express device
* @mesg: PM message
*/
#ifdef CONFIG_PM
static int ismt_suspend(struct pci_dev *pdev, pm_message_t mesg)
{
pci_save_state(pdev);
pci_set_power_state(pdev, pci_choose_state(pdev, mesg));
return 0;
}
/**
* ismt_resume() - PCI resume code
* @pdev: PCI-Express device
*/
static int ismt_resume(struct pci_dev *pdev)
{
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
return pci_enable_device(pdev);
}
#else
#define ismt_suspend NULL
#define ismt_resume NULL
#endif
static struct pci_driver ismt_driver = { static struct pci_driver ismt_driver = {
.name = "ismt_smbus", .name = "ismt_smbus",
.id_table = ismt_ids, .id_table = ismt_ids,
.probe = ismt_probe, .probe = ismt_probe,
.remove = ismt_remove, .remove = ismt_remove,
.suspend = ismt_suspend,
.resume = ismt_resume,
}; };
module_pci_driver(ismt_driver); module_pci_driver(ismt_driver);
......
...@@ -475,6 +475,7 @@ static const struct of_device_id meson_i2c_match[] = { ...@@ -475,6 +475,7 @@ static const struct of_device_id meson_i2c_match[] = {
{ .compatible = "amlogic,meson6-i2c" }, { .compatible = "amlogic,meson6-i2c" },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, meson_i2c_match);
static struct platform_driver meson_i2c_driver = { static struct platform_driver meson_i2c_driver = {
.probe = meson_i2c_probe, .probe = meson_i2c_probe,
......
...@@ -728,11 +728,27 @@ static int mtk_i2c_remove(struct platform_device *pdev) ...@@ -728,11 +728,27 @@ static int mtk_i2c_remove(struct platform_device *pdev)
return 0; return 0;
} }
#ifdef CONFIG_PM_SLEEP
static int mtk_i2c_resume(struct device *dev)
{
struct mtk_i2c *i2c = dev_get_drvdata(dev);
mtk_i2c_init_hw(i2c);
return 0;
}
#endif
static const struct dev_pm_ops mtk_i2c_pm = {
SET_SYSTEM_SLEEP_PM_OPS(NULL, mtk_i2c_resume)
};
static struct platform_driver mtk_i2c_driver = { static struct platform_driver mtk_i2c_driver = {
.probe = mtk_i2c_probe, .probe = mtk_i2c_probe,
.remove = mtk_i2c_remove, .remove = mtk_i2c_remove,
.driver = { .driver = {
.name = I2C_DRV_NAME, .name = I2C_DRV_NAME,
.pm = &mtk_i2c_pm,
.of_match_table = of_match_ptr(mtk_i2c_of_match), .of_match_table = of_match_ptr(mtk_i2c_of_match),
}, },
}; };
......
...@@ -92,6 +92,16 @@ static void oc_setreg_32(struct ocores_i2c *i2c, int reg, u8 value) ...@@ -92,6 +92,16 @@ static void oc_setreg_32(struct ocores_i2c *i2c, int reg, u8 value)
iowrite32(value, i2c->base + (reg << i2c->reg_shift)); iowrite32(value, i2c->base + (reg << i2c->reg_shift));
} }
static void oc_setreg_16be(struct ocores_i2c *i2c, int reg, u8 value)
{
iowrite16be(value, i2c->base + (reg << i2c->reg_shift));
}
static void oc_setreg_32be(struct ocores_i2c *i2c, int reg, u8 value)
{
iowrite32be(value, i2c->base + (reg << i2c->reg_shift));
}
static inline u8 oc_getreg_8(struct ocores_i2c *i2c, int reg) static inline u8 oc_getreg_8(struct ocores_i2c *i2c, int reg)
{ {
return ioread8(i2c->base + (reg << i2c->reg_shift)); return ioread8(i2c->base + (reg << i2c->reg_shift));
...@@ -107,6 +117,16 @@ static inline u8 oc_getreg_32(struct ocores_i2c *i2c, int reg) ...@@ -107,6 +117,16 @@ static inline u8 oc_getreg_32(struct ocores_i2c *i2c, int reg)
return ioread32(i2c->base + (reg << i2c->reg_shift)); return ioread32(i2c->base + (reg << i2c->reg_shift));
} }
static inline u8 oc_getreg_16be(struct ocores_i2c *i2c, int reg)
{
return ioread16be(i2c->base + (reg << i2c->reg_shift));
}
static inline u8 oc_getreg_32be(struct ocores_i2c *i2c, int reg)
{
return ioread32be(i2c->base + (reg << i2c->reg_shift));
}
static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value)
{ {
i2c->setreg(i2c, reg, value); i2c->setreg(i2c, reg, value);
...@@ -428,6 +448,9 @@ static int ocores_i2c_probe(struct platform_device *pdev) ...@@ -428,6 +448,9 @@ static int ocores_i2c_probe(struct platform_device *pdev)
i2c->reg_io_width = 1; /* Set to default value */ i2c->reg_io_width = 1; /* Set to default value */
if (!i2c->setreg || !i2c->getreg) { if (!i2c->setreg || !i2c->getreg) {
bool be = pdata ? pdata->big_endian :
of_device_is_big_endian(pdev->dev.of_node);
switch (i2c->reg_io_width) { switch (i2c->reg_io_width) {
case 1: case 1:
i2c->setreg = oc_setreg_8; i2c->setreg = oc_setreg_8;
...@@ -435,13 +458,13 @@ static int ocores_i2c_probe(struct platform_device *pdev) ...@@ -435,13 +458,13 @@ static int ocores_i2c_probe(struct platform_device *pdev)
break; break;
case 2: case 2:
i2c->setreg = oc_setreg_16; i2c->setreg = be ? oc_setreg_16be : oc_setreg_16;
i2c->getreg = oc_getreg_16; i2c->getreg = be ? oc_getreg_16be : oc_getreg_16;
break; break;
case 4: case 4:
i2c->setreg = oc_setreg_32; i2c->setreg = be ? oc_setreg_32be : oc_setreg_32;
i2c->getreg = oc_getreg_32; i2c->getreg = be ? oc_getreg_32be : oc_getreg_32;
break; break;
default: default:
......
...@@ -496,7 +496,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) ...@@ -496,7 +496,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
struct i2c_msg *pmsg; struct i2c_msg *pmsg;
int rc = 0, completed = 0, i; int rc = 0, completed = 0, i;
struct i2c_pnx_algo_data *alg_data = adap->algo_data; struct i2c_pnx_algo_data *alg_data = adap->algo_data;
u32 stat = ioread32(I2C_REG_STS(alg_data)); u32 stat;
dev_dbg(&alg_data->adapter.dev, dev_dbg(&alg_data->adapter.dev,
"%s(): entering: %d messages, stat = %04x.\n", "%s(): entering: %d messages, stat = %04x.\n",
...@@ -659,9 +659,8 @@ static int i2c_pnx_probe(struct platform_device *pdev) ...@@ -659,9 +659,8 @@ static int i2c_pnx_probe(struct platform_device *pdev)
if (IS_ERR(alg_data->clk)) if (IS_ERR(alg_data->clk))
return PTR_ERR(alg_data->clk); return PTR_ERR(alg_data->clk);
init_timer(&alg_data->mif.timer); setup_timer(&alg_data->mif.timer, i2c_pnx_timeout,
alg_data->mif.timer.function = i2c_pnx_timeout; (unsigned long)alg_data);
alg_data->mif.timer.data = (unsigned long)alg_data;
snprintf(alg_data->adapter.name, sizeof(alg_data->adapter.name), snprintf(alg_data->adapter.name, sizeof(alg_data->adapter.name),
"%s", pdev->name); "%s", pdev->name);
......
...@@ -46,12 +46,15 @@ struct pxa_reg_layout { ...@@ -46,12 +46,15 @@ struct pxa_reg_layout {
u32 icr; u32 icr;
u32 isr; u32 isr;
u32 isar; u32 isar;
u32 ilcr;
u32 iwcr;
}; };
enum pxa_i2c_types { enum pxa_i2c_types {
REGS_PXA2XX, REGS_PXA2XX,
REGS_PXA3XX, REGS_PXA3XX,
REGS_CE4100, REGS_CE4100,
REGS_PXA910,
}; };
/* /*
...@@ -79,12 +82,22 @@ static struct pxa_reg_layout pxa_reg_layout[] = { ...@@ -79,12 +82,22 @@ static struct pxa_reg_layout pxa_reg_layout[] = {
.isr = 0x04, .isr = 0x04,
/* no isar register */ /* no isar register */
}, },
[REGS_PXA910] = {
.ibmr = 0x00,
.idbr = 0x08,
.icr = 0x10,
.isr = 0x18,
.isar = 0x20,
.ilcr = 0x28,
.iwcr = 0x30,
},
}; };
static const struct platform_device_id i2c_pxa_id_table[] = { static const struct platform_device_id i2c_pxa_id_table[] = {
{ "pxa2xx-i2c", REGS_PXA2XX }, { "pxa2xx-i2c", REGS_PXA2XX },
{ "pxa3xx-pwri2c", REGS_PXA3XX }, { "pxa3xx-pwri2c", REGS_PXA3XX },
{ "ce4100-i2c", REGS_CE4100 }, { "ce4100-i2c", REGS_CE4100 },
{ "pxa910-i2c", REGS_PXA910 },
{ }, { },
}; };
MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table); MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
...@@ -124,6 +137,23 @@ MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table); ...@@ -124,6 +137,23 @@ MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
#define ISR_SAD (1 << 9) /* slave address detected */ #define ISR_SAD (1 << 9) /* slave address detected */
#define ISR_BED (1 << 10) /* bus error no ACK/NAK */ #define ISR_BED (1 << 10) /* bus error no ACK/NAK */
/* bit field shift & mask */
#define ILCR_SLV_SHIFT 0
#define ILCR_SLV_MASK (0x1FF << ILCR_SLV_SHIFT)
#define ILCR_FLV_SHIFT 9
#define ILCR_FLV_MASK (0x1FF << ILCR_FLV_SHIFT)
#define ILCR_HLVL_SHIFT 18
#define ILCR_HLVL_MASK (0x1FF << ILCR_HLVL_SHIFT)
#define ILCR_HLVH_SHIFT 27
#define ILCR_HLVH_MASK (0x1F << ILCR_HLVH_SHIFT)
#define IWCR_CNT_SHIFT 0
#define IWCR_CNT_MASK (0x1F << IWCR_CNT_SHIFT)
#define IWCR_HS_CNT1_SHIFT 5
#define IWCR_HS_CNT1_MASK (0x1F << IWCR_HS_CNT1_SHIFT)
#define IWCR_HS_CNT2_SHIFT 10
#define IWCR_HS_CNT2_MASK (0x1F << IWCR_HS_CNT2_SHIFT)
struct pxa_i2c { struct pxa_i2c {
spinlock_t lock; spinlock_t lock;
wait_queue_head_t wait; wait_queue_head_t wait;
...@@ -150,6 +180,8 @@ struct pxa_i2c { ...@@ -150,6 +180,8 @@ struct pxa_i2c {
void __iomem *reg_icr; void __iomem *reg_icr;
void __iomem *reg_isr; void __iomem *reg_isr;
void __iomem *reg_isar; void __iomem *reg_isar;
void __iomem *reg_ilcr;
void __iomem *reg_iwcr;
unsigned long iobase; unsigned long iobase;
unsigned long iosize; unsigned long iosize;
...@@ -168,6 +200,8 @@ struct pxa_i2c { ...@@ -168,6 +200,8 @@ struct pxa_i2c {
#define _ICR(i2c) ((i2c)->reg_icr) #define _ICR(i2c) ((i2c)->reg_icr)
#define _ISR(i2c) ((i2c)->reg_isr) #define _ISR(i2c) ((i2c)->reg_isr)
#define _ISAR(i2c) ((i2c)->reg_isar) #define _ISAR(i2c) ((i2c)->reg_isar)
#define _ILCR(i2c) ((i2c)->reg_ilcr)
#define _IWCR(i2c) ((i2c)->reg_iwcr)
/* /*
* I2C Slave mode address * I2C Slave mode address
...@@ -1102,7 +1136,7 @@ static const struct i2c_algorithm i2c_pxa_pio_algorithm = { ...@@ -1102,7 +1136,7 @@ static const struct i2c_algorithm i2c_pxa_pio_algorithm = {
static const struct of_device_id i2c_pxa_dt_ids[] = { static const struct of_device_id i2c_pxa_dt_ids[] = {
{ .compatible = "mrvl,pxa-i2c", .data = (void *)REGS_PXA2XX }, { .compatible = "mrvl,pxa-i2c", .data = (void *)REGS_PXA2XX },
{ .compatible = "mrvl,pwri2c", .data = (void *)REGS_PXA3XX }, { .compatible = "mrvl,pwri2c", .data = (void *)REGS_PXA3XX },
{ .compatible = "mrvl,mmp-twsi", .data = (void *)REGS_PXA2XX }, { .compatible = "mrvl,mmp-twsi", .data = (void *)REGS_PXA910 },
{} {}
}; };
MODULE_DEVICE_TABLE(of, i2c_pxa_dt_ids); MODULE_DEVICE_TABLE(of, i2c_pxa_dt_ids);
...@@ -1203,6 +1237,11 @@ static int i2c_pxa_probe(struct platform_device *dev) ...@@ -1203,6 +1237,11 @@ static int i2c_pxa_probe(struct platform_device *dev)
if (i2c_type != REGS_CE4100) if (i2c_type != REGS_CE4100)
i2c->reg_isar = i2c->reg_base + pxa_reg_layout[i2c_type].isar; i2c->reg_isar = i2c->reg_base + pxa_reg_layout[i2c_type].isar;
if (i2c_type == REGS_PXA910) {
i2c->reg_ilcr = i2c->reg_base + pxa_reg_layout[i2c_type].ilcr;
i2c->reg_iwcr = i2c->reg_base + pxa_reg_layout[i2c_type].iwcr;
}
i2c->iobase = res->start; i2c->iobase = res->start;
i2c->iosize = resource_size(res); i2c->iosize = resource_size(res);
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c/i2c-rcar.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_device.h> #include <linux/of_device.h>
...@@ -103,6 +102,7 @@ ...@@ -103,6 +102,7 @@
enum rcar_i2c_type { enum rcar_i2c_type {
I2C_RCAR_GEN1, I2C_RCAR_GEN1,
I2C_RCAR_GEN2, I2C_RCAR_GEN2,
I2C_RCAR_GEN3,
}; };
struct rcar_i2c_priv { struct rcar_i2c_priv {
...@@ -178,6 +178,7 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv, ...@@ -178,6 +178,7 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
cdf_width = 2; cdf_width = 2;
break; break;
case I2C_RCAR_GEN2: case I2C_RCAR_GEN2:
case I2C_RCAR_GEN3:
cdf_width = 3; cdf_width = 3;
break; break;
default: default:
...@@ -625,13 +626,13 @@ static const struct of_device_id rcar_i2c_dt_ids[] = { ...@@ -625,13 +626,13 @@ static const struct of_device_id rcar_i2c_dt_ids[] = {
{ .compatible = "renesas,i2c-r8a7792", .data = (void *)I2C_RCAR_GEN2 }, { .compatible = "renesas,i2c-r8a7792", .data = (void *)I2C_RCAR_GEN2 },
{ .compatible = "renesas,i2c-r8a7793", .data = (void *)I2C_RCAR_GEN2 }, { .compatible = "renesas,i2c-r8a7793", .data = (void *)I2C_RCAR_GEN2 },
{ .compatible = "renesas,i2c-r8a7794", .data = (void *)I2C_RCAR_GEN2 }, { .compatible = "renesas,i2c-r8a7794", .data = (void *)I2C_RCAR_GEN2 },
{ .compatible = "renesas,i2c-r8a7795", .data = (void *)I2C_RCAR_GEN3 },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, rcar_i2c_dt_ids); MODULE_DEVICE_TABLE(of, rcar_i2c_dt_ids);
static int rcar_i2c_probe(struct platform_device *pdev) static int rcar_i2c_probe(struct platform_device *pdev)
{ {
struct i2c_rcar_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct rcar_i2c_priv *priv; struct rcar_i2c_priv *priv;
struct i2c_adapter *adap; struct i2c_adapter *adap;
struct resource *res; struct resource *res;
...@@ -650,15 +651,9 @@ static int rcar_i2c_probe(struct platform_device *pdev) ...@@ -650,15 +651,9 @@ static int rcar_i2c_probe(struct platform_device *pdev)
} }
bus_speed = 100000; /* default 100 kHz */ bus_speed = 100000; /* default 100 kHz */
ret = of_property_read_u32(dev->of_node, "clock-frequency", &bus_speed); of_property_read_u32(dev->of_node, "clock-frequency", &bus_speed);
if (ret < 0 && pdata && pdata->bus_speed)
bus_speed = pdata->bus_speed;
if (pdev->dev.of_node) priv->devtype = (enum rcar_i2c_type)of_match_device(rcar_i2c_dt_ids, dev)->data;
priv->devtype = (long)of_match_device(rcar_i2c_dt_ids,
dev)->data;
else
priv->devtype = platform_get_device_id(pdev)->driver_data;
ret = rcar_i2c_clock_calculate(priv, bus_speed, dev); ret = rcar_i2c_clock_calculate(priv, bus_speed, dev);
if (ret < 0) if (ret < 0)
...@@ -716,14 +711,6 @@ static int rcar_i2c_remove(struct platform_device *pdev) ...@@ -716,14 +711,6 @@ static int rcar_i2c_remove(struct platform_device *pdev)
return 0; return 0;
} }
static const struct platform_device_id rcar_i2c_id_table[] = {
{ "i2c-rcar", I2C_RCAR_GEN1 },
{ "i2c-rcar_gen1", I2C_RCAR_GEN1 },
{ "i2c-rcar_gen2", I2C_RCAR_GEN2 },
{},
};
MODULE_DEVICE_TABLE(platform, rcar_i2c_id_table);
static struct platform_driver rcar_i2c_driver = { static struct platform_driver rcar_i2c_driver = {
.driver = { .driver = {
.name = "i2c-rcar", .name = "i2c-rcar",
...@@ -731,7 +718,6 @@ static struct platform_driver rcar_i2c_driver = { ...@@ -731,7 +718,6 @@ static struct platform_driver rcar_i2c_driver = {
}, },
.probe = rcar_i2c_probe, .probe = rcar_i2c_probe,
.remove = rcar_i2c_remove, .remove = rcar_i2c_remove,
.id_table = rcar_i2c_id_table,
}; };
module_platform_driver(rcar_i2c_driver); module_platform_driver(rcar_i2c_driver);
......
...@@ -858,6 +858,7 @@ static const struct of_device_id rk3x_i2c_match[] = { ...@@ -858,6 +858,7 @@ static const struct of_device_id rk3x_i2c_match[] = {
{ .compatible = "rockchip,rk3288-i2c", .data = (void *)&soc_data[2] }, { .compatible = "rockchip,rk3288-i2c", .data = (void *)&soc_data[2] },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, rk3x_i2c_match);
static int rk3x_i2c_probe(struct platform_device *pdev) static int rk3x_i2c_probe(struct platform_device *pdev)
{ {
......
...@@ -836,6 +836,7 @@ static const struct of_device_id sh_mobile_i2c_dt_ids[] = { ...@@ -836,6 +836,7 @@ static const struct of_device_id sh_mobile_i2c_dt_ids[] = {
{ .compatible = "renesas,iic-r8a7792", .data = &fast_clock_dt_config }, { .compatible = "renesas,iic-r8a7792", .data = &fast_clock_dt_config },
{ .compatible = "renesas,iic-r8a7793", .data = &fast_clock_dt_config }, { .compatible = "renesas,iic-r8a7793", .data = &fast_clock_dt_config },
{ .compatible = "renesas,iic-r8a7794", .data = &fast_clock_dt_config }, { .compatible = "renesas,iic-r8a7794", .data = &fast_clock_dt_config },
{ .compatible = "renesas,iic-r8a7795", .data = &fast_clock_dt_config },
{ .compatible = "renesas,iic-sh73a0", .data = &fast_clock_dt_config }, { .compatible = "renesas,iic-sh73a0", .data = &fast_clock_dt_config },
{}, {},
}; };
......
...@@ -358,11 +358,29 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev) ...@@ -358,11 +358,29 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev)
if (err < 0) if (err < 0)
bitrate = SIRFSOC_I2C_DEFAULT_SPEED; bitrate = SIRFSOC_I2C_DEFAULT_SPEED;
if (bitrate < 100000) /*
regval = * Due to some hardware design issues, we need to tune the formula.
(2 * ctrl_speed) / (bitrate * 11); * Since i2c is open drain interface that allows the slave to
else * stall the transaction by holding the SCL line at '0', the RTL
* implementation is waiting for SCL feedback from the pin after
* setting it to High-Z ('1'). This wait adds to the high-time
* interval counter few cycles of the input synchronization
* (depending on the SCL_FILTER_REG field), and also the time it
* takes for the board pull-up resistor to rise the SCL line.
* For slow SCL settings these additions are negligible,
* but they start to affect the speed when clock is set to faster
* frequencies.
* Through the actual tests, use the different user_div value(which
* in the divider formular 'Fio / (Fi2c * user_div)') to adapt
* the different ranges of i2c bus clock frequency, to make the SCL
* more accurate.
*/
if (bitrate <= 30000)
regval = ctrl_speed / (bitrate * 5); regval = ctrl_speed / (bitrate * 5);
else if (bitrate > 30000 && bitrate <= 280000)
regval = (2 * ctrl_speed) / (bitrate * 11);
else
regval = ctrl_speed / (bitrate * 6);
writel(regval, siic->base + SIRFSOC_I2C_CLK_CTRL); writel(regval, siic->base + SIRFSOC_I2C_CLK_CTRL);
if (regval > 0xFF) if (regval > 0xFF)
......
...@@ -977,6 +977,7 @@ static const struct of_device_id stu300_dt_match[] = { ...@@ -977,6 +977,7 @@ static const struct of_device_id stu300_dt_match[] = {
{ .compatible = "st,ddci2c" }, { .compatible = "st,ddci2c" },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, stu300_dt_match);
static struct platform_driver stu300_i2c_driver = { static struct platform_driver stu300_i2c_driver = {
.driver = { .driver = {
......
...@@ -873,7 +873,6 @@ static int tegra_i2c_probe(struct platform_device *pdev) ...@@ -873,7 +873,6 @@ static int tegra_i2c_probe(struct platform_device *pdev)
i2c_dev->adapter.class = I2C_CLASS_DEPRECATED; i2c_dev->adapter.class = I2C_CLASS_DEPRECATED;
strlcpy(i2c_dev->adapter.name, "Tegra I2C adapter", strlcpy(i2c_dev->adapter.name, "Tegra I2C adapter",
sizeof(i2c_dev->adapter.name)); sizeof(i2c_dev->adapter.name));
i2c_dev->adapter.algo = &tegra_i2c_algo;
i2c_dev->adapter.dev.parent = &pdev->dev; i2c_dev->adapter.dev.parent = &pdev->dev;
i2c_dev->adapter.nr = pdev->id; i2c_dev->adapter.nr = pdev->id;
i2c_dev->adapter.dev.of_node = pdev->dev.of_node; i2c_dev->adapter.dev.of_node = pdev->dev.of_node;
......
This diff is collapsed.
This diff is collapsed.
...@@ -99,27 +99,40 @@ struct gsb_buffer { ...@@ -99,27 +99,40 @@ struct gsb_buffer {
}; };
} __packed; } __packed;
static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data) struct acpi_i2c_lookup {
struct i2c_board_info *info;
acpi_handle adapter_handle;
acpi_handle device_handle;
};
static int acpi_i2c_find_address(struct acpi_resource *ares, void *data)
{ {
struct i2c_board_info *info = data; struct acpi_i2c_lookup *lookup = data;
struct i2c_board_info *info = lookup->info;
struct acpi_resource_i2c_serialbus *sb;
acpi_handle adapter_handle;
acpi_status status;
if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { if (info->addr || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
struct acpi_resource_i2c_serialbus *sb; return 1;
sb = &ares->data.i2c_serial_bus; sb = &ares->data.i2c_serial_bus;
if (!info->addr && sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) { if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C)
info->addr = sb->slave_address; return 1;
if (sb->access_mode == ACPI_I2C_10BIT_MODE)
info->flags |= I2C_CLIENT_TEN;
}
} else if (!info->irq) {
struct resource r;
if (acpi_dev_resource_interrupt(ares, 0, &r)) /*
info->irq = r.start; * Extract the ResourceSource and make sure that the handle matches
* with the I2C adapter handle.
*/
status = acpi_get_handle(lookup->device_handle,
sb->resource_source.string_ptr,
&adapter_handle);
if (ACPI_SUCCESS(status) && adapter_handle == lookup->adapter_handle) {
info->addr = sb->slave_address;
if (sb->access_mode == ACPI_I2C_10BIT_MODE)
info->flags |= I2C_CLIENT_TEN;
} }
/* Tell the ACPI core to skip this resource */
return 1; return 1;
} }
...@@ -128,6 +141,8 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, ...@@ -128,6 +141,8 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
{ {
struct i2c_adapter *adapter = data; struct i2c_adapter *adapter = data;
struct list_head resource_list; struct list_head resource_list;
struct acpi_i2c_lookup lookup;
struct resource_entry *entry;
struct i2c_board_info info; struct i2c_board_info info;
struct acpi_device *adev; struct acpi_device *adev;
int ret; int ret;
...@@ -140,14 +155,37 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, ...@@ -140,14 +155,37 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
memset(&info, 0, sizeof(info)); memset(&info, 0, sizeof(info));
info.fwnode = acpi_fwnode_handle(adev); info.fwnode = acpi_fwnode_handle(adev);
memset(&lookup, 0, sizeof(lookup));
lookup.adapter_handle = ACPI_HANDLE(&adapter->dev);
lookup.device_handle = handle;
lookup.info = &info;
/*
* Look up for I2cSerialBus resource with ResourceSource that
* matches with this adapter.
*/
INIT_LIST_HEAD(&resource_list); INIT_LIST_HEAD(&resource_list);
ret = acpi_dev_get_resources(adev, &resource_list, ret = acpi_dev_get_resources(adev, &resource_list,
acpi_i2c_add_resource, &info); acpi_i2c_find_address, &lookup);
acpi_dev_free_resource_list(&resource_list); acpi_dev_free_resource_list(&resource_list);
if (ret < 0 || !info.addr) if (ret < 0 || !info.addr)
return AE_OK; return AE_OK;
/* Then fill IRQ number if any */
ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
if (ret < 0)
return AE_OK;
resource_list_for_each_entry(entry, &resource_list) {
if (resource_type(entry->res) == IORESOURCE_IRQ) {
info.irq = entry->res->start;
break;
}
}
acpi_dev_free_resource_list(&resource_list);
adev->power.flags.ignore_parent = true; adev->power.flags.ignore_parent = true;
strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type)); strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
if (!i2c_new_device(adapter, &info)) { if (!i2c_new_device(adapter, &info)) {
...@@ -160,6 +198,8 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, ...@@ -160,6 +198,8 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
return AE_OK; return AE_OK;
} }
#define ACPI_I2C_MAX_SCAN_DEPTH 32
/** /**
* acpi_i2c_register_devices - enumerate I2C slave devices behind adapter * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
* @adap: pointer to adapter * @adap: pointer to adapter
...@@ -170,17 +210,13 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, ...@@ -170,17 +210,13 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
*/ */
static void acpi_i2c_register_devices(struct i2c_adapter *adap) static void acpi_i2c_register_devices(struct i2c_adapter *adap)
{ {
acpi_handle handle;
acpi_status status; acpi_status status;
if (!adap->dev.parent) if (!has_acpi_companion(&adap->dev))
return;
handle = ACPI_HANDLE(adap->dev.parent);
if (!handle)
return; return;
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_I2C_MAX_SCAN_DEPTH,
acpi_i2c_add_device, NULL, acpi_i2c_add_device, NULL,
adap, NULL); adap, NULL);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
......
...@@ -235,7 +235,7 @@ static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) ...@@ -235,7 +235,7 @@ static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr)
return result; return result;
} }
static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client,
unsigned long arg) unsigned long arg)
{ {
struct i2c_rdwr_ioctl_data rdwr_arg; struct i2c_rdwr_ioctl_data rdwr_arg;
...@@ -250,7 +250,7 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, ...@@ -250,7 +250,7 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client,
/* Put an arbitrary limit on the number of messages that can /* Put an arbitrary limit on the number of messages that can
* be sent at once */ * be sent at once */
if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS) if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS)
return -EINVAL; return -EINVAL;
rdwr_pa = memdup_user(rdwr_arg.msgs, rdwr_pa = memdup_user(rdwr_arg.msgs,
...@@ -421,16 +421,6 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -421,16 +421,6 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
switch (cmd) { switch (cmd) {
case I2C_SLAVE: case I2C_SLAVE:
case I2C_SLAVE_FORCE: case I2C_SLAVE_FORCE:
/* NOTE: devices set up to work with "new style" drivers
* can't use I2C_SLAVE, even when the device node is not
* bound to a driver. Only I2C_SLAVE_FORCE will work.
*
* Setting the PEC flag here won't affect kernel drivers,
* which will be using the i2c_client node registered with
* the driver model core. Likewise, when that client has
* the PEC flag already set, the i2c-dev driver won't see
* (or use) this setting.
*/
if ((arg > 0x3ff) || if ((arg > 0x3ff) ||
(((client->flags & I2C_M_TEN) == 0) && arg > 0x7f)) (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
return -EINVAL; return -EINVAL;
...@@ -446,6 +436,13 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -446,6 +436,13 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
client->flags &= ~I2C_M_TEN; client->flags &= ~I2C_M_TEN;
return 0; return 0;
case I2C_PEC: case I2C_PEC:
/*
* Setting the PEC flag here won't affect kernel drivers,
* which will be using the i2c_client node registered with
* the driver model core. Likewise, when that client has
* the PEC flag already set, the i2c-dev driver won't see
* (or use) this setting.
*/
if (arg) if (arg)
client->flags |= I2C_CLIENT_PEC; client->flags |= I2C_CLIENT_PEC;
else else
...@@ -456,7 +453,7 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -456,7 +453,7 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return put_user(funcs, (unsigned long __user *)arg); return put_user(funcs, (unsigned long __user *)arg);
case I2C_RDWR: case I2C_RDWR:
return i2cdev_ioctl_rdrw(client, arg); return i2cdev_ioctl_rdwr(client, arg);
case I2C_SMBUS: case I2C_SMBUS:
return i2cdev_ioctl_smbus(client, arg); return i2cdev_ioctl_smbus(client, arg);
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-mux.h> #include <linux/i2c-mux.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/acpi.h>
/* multiplexer per channel data */ /* multiplexer per channel data */
struct i2c_mux_priv { struct i2c_mux_priv {
...@@ -173,6 +174,13 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, ...@@ -173,6 +174,13 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
} }
} }
/*
* Associate the mux channel with an ACPI node.
*/
if (has_acpi_companion(mux_dev))
acpi_preset_companion(&priv->adap.dev, ACPI_COMPANION(mux_dev),
chan_id);
if (force_nr) { if (force_nr) {
priv->adap.nr = force_nr; priv->adap.nr = force_nr;
ret = i2c_add_numbered_adapter(&priv->adap); ret = i2c_add_numbered_adapter(&priv->adap);
......
...@@ -686,7 +686,7 @@ static int do_i2c_rdwr_ioctl(unsigned int fd, unsigned int cmd, ...@@ -686,7 +686,7 @@ static int do_i2c_rdwr_ioctl(unsigned int fd, unsigned int cmd,
if (get_user(nmsgs, &udata->nmsgs)) if (get_user(nmsgs, &udata->nmsgs))
return -EFAULT; return -EFAULT;
if (nmsgs > I2C_RDRW_IOCTL_MAX_MSGS) if (nmsgs > I2C_RDWR_IOCTL_MAX_MSGS)
return -EINVAL; return -EINVAL;
if (get_user(datap, &udata->msgs)) if (get_user(datap, &udata->msgs))
......
...@@ -514,6 +514,11 @@ static inline bool has_acpi_companion(struct device *dev) ...@@ -514,6 +514,11 @@ static inline bool has_acpi_companion(struct device *dev)
return false; return false;
} }
static inline void acpi_preset_companion(struct device *dev,
struct acpi_device *parent, u64 addr)
{
}
static inline const char *acpi_dev_name(struct acpi_device *adev) static inline const char *acpi_dev_name(struct acpi_device *adev)
{ {
return NULL; return NULL;
......
...@@ -15,6 +15,7 @@ struct ocores_i2c_platform_data { ...@@ -15,6 +15,7 @@ struct ocores_i2c_platform_data {
u32 reg_shift; /* register offset shift value */ u32 reg_shift; /* register offset shift value */
u32 reg_io_width; /* register io read/write width */ u32 reg_io_width; /* register io read/write width */
u32 clock_khz; /* input clock in kHz */ u32 clock_khz; /* input clock in kHz */
bool big_endian; /* registers are big endian */
u8 num_devices; /* number of devices in the devices list */ u8 num_devices; /* number of devices in the devices list */
struct i2c_board_info const *devices; /* devices connected to the bus */ struct i2c_board_info const *devices; /* devices connected to the bus */
}; };
......
#ifndef __I2C_R_CAR_H__
#define __I2C_R_CAR_H__
#include <linux/platform_device.h>
struct i2c_rcar_platform_data {
u32 bus_speed;
};
#endif /* __I2C_R_CAR_H__ */
...@@ -66,7 +66,9 @@ struct i2c_rdwr_ioctl_data { ...@@ -66,7 +66,9 @@ struct i2c_rdwr_ioctl_data {
__u32 nmsgs; /* number of i2c_msgs */ __u32 nmsgs; /* number of i2c_msgs */
}; };
#define I2C_RDRW_IOCTL_MAX_MSGS 42 #define I2C_RDWR_IOCTL_MAX_MSGS 42
/* Originally defined with a typo, keep it for compatibility */
#define I2C_RDRW_IOCTL_MAX_MSGS I2C_RDWR_IOCTL_MAX_MSGS
#endif /* _UAPI_LINUX_I2C_DEV_H */ #endif /* _UAPI_LINUX_I2C_DEV_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment