Merge branch 'i2c/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux into next
Pull i2c updates from Wolfram Sang: "I2C has the following updates for 3.16: - major cleanups to the rcar and sh_mobile drivers - removal of nuc900 driver which had a compile error for years - usual bunch of driver updates, bugfixes and cleanups" * 'i2c/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (44 commits) i2c: pca954x: Fix compilation without CONFIG_GPIOLIB i2c: mux: pca954x: Use the descriptor-based GPIO API i2c: mpc: insert DR read in i2c_fixup() i2c: bfin: turn to Resource-managed API in probe function i2c: Make of_device_id array const i2c: remove unnecessary OOM messages i2c: designware-pci: Add Haswell PCI IDs i2c: designware: Add runtime PM hooks i2c: designware: Disable device on system suspend i2c: nuc900: remove driver i2c: imx: update i2c clock divider for each transaction i2c: imx: fix the i2c bus hang issue when do repeat restart i2c: rcar: update copyright and license information i2c: rcar: janitorial cleanup after refactoring i2c: rcar: reuse status bits as enable bits i2c: rcar: remove spinlock i2c: rcar: refactor status bit handling i2c: rcar: refactor setting up msg i2c: rcar: check bus free before first message i2c: rcar: refactor irq state machine ...
This commit is contained in:
Коммит
7b215de3d0
|
@ -8,6 +8,12 @@ the standard I2C multi-master rules. Using GPIOs is generally useful in
|
|||
the case where there is a device on the bus that has errata and/or bugs
|
||||
that makes standard multimaster mode not feasible.
|
||||
|
||||
Note that this scheme works well enough but has some downsides:
|
||||
* It is nonstandard (not using standard I2C multimaster)
|
||||
* Having two masters on a bus in general makes it relatively hard to debug
|
||||
problems (hard to tell if i2c issues were caused by one master, another, or
|
||||
some device on the bus).
|
||||
|
||||
|
||||
Algorithm:
|
||||
|
||||
|
|
|
@ -5,7 +5,14 @@ at various speeds ranging from 100khz to 3.4Mhz.
|
|||
|
||||
Required properties:
|
||||
- compatible: value should be.
|
||||
-> "samsung,exynos5-hsi2c", for i2c compatible with exynos5 hsi2c.
|
||||
-> "samsung,exynos5-hsi2c", (DEPRECATED)
|
||||
for i2c compatible with HSI2C available
|
||||
on Exynos5250 and Exynos5420 SoCs.
|
||||
-> "samsung,exynos5250-hsi2c", for i2c compatible with HSI2C available
|
||||
on Exynos5250 and Exynos5420 SoCs.
|
||||
-> "samsung,exynos5260-hsi2c", for i2c compatible with HSI2C available
|
||||
on Exynos5260 SoCs.
|
||||
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- interrupts: interrupt number to the cpu.
|
||||
|
@ -26,7 +33,7 @@ Optional properties:
|
|||
Example:
|
||||
|
||||
hsi2c@12ca0000 {
|
||||
compatible = "samsung,exynos5-hsi2c";
|
||||
compatible = "samsung,exynos5250-hsi2c";
|
||||
reg = <0x12ca0000 0x100>;
|
||||
interrupts = <56>;
|
||||
clock-frequency = <100000>;
|
||||
|
|
|
@ -5,7 +5,7 @@ Required properties :
|
|||
|
||||
- reg : Offset and length of the register set for the device
|
||||
- compatible : Should be either:
|
||||
- "allwinner,sun4i-i2c"
|
||||
- "allwinner,sun4i-a10-i2c"
|
||||
- "allwinner,sun6i-a31-i2c"
|
||||
- "marvell,mv64xxx-i2c"
|
||||
- "marvell,mv78230-i2c"
|
||||
|
|
|
@ -7,6 +7,9 @@ Required properties:
|
|||
"renesas,i2c-r8a7779"
|
||||
"renesas,i2c-r8a7790"
|
||||
"renesas,i2c-r8a7791"
|
||||
"renesas,i2c-r8a7792"
|
||||
"renesas,i2c-r8a7793"
|
||||
"renesas,i2c-r8a7794"
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- interrupts: interrupt specifier.
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
Device tree configuration for Renesas IIC (sh_mobile) driver
|
||||
|
||||
Required properties:
|
||||
- compatible : "renesas,iic-<soctype>". "renesas,rmobile-iic" as fallback
|
||||
- reg : address start and address range size of device
|
||||
- interrupts : interrupt of device
|
||||
- clocks : clock for device
|
||||
- #address-cells : should be <1>
|
||||
- #size-cells : should be <0>
|
||||
|
||||
Optional properties:
|
||||
- clock-frequency : frequency of bus clock in Hz. Default 100kHz if unset.
|
||||
|
||||
Pinctrl properties might be needed, too. See there.
|
||||
|
||||
Example:
|
||||
|
||||
iic0: i2c@e6500000 {
|
||||
compatible = "renesas,iic-r8a7790", "renesas,rmobile-iic";
|
||||
reg = <0 0xe6500000 0 0x425>;
|
||||
interrupts = <0 174 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&mstp3_clks R8A7790_CLK_IIC0>;
|
||||
clock-frequency = <400000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
|
@ -713,7 +713,7 @@
|
|||
};
|
||||
|
||||
i2c0: i2c@01c2ac00 {
|
||||
compatible = "allwinner,sun4i-i2c";
|
||||
compatible = "allwinner,sun4i-a10-i2c";
|
||||
reg = <0x01c2ac00 0x400>;
|
||||
interrupts = <7>;
|
||||
clocks = <&apb1_gates 0>;
|
||||
|
@ -724,7 +724,7 @@
|
|||
};
|
||||
|
||||
i2c1: i2c@01c2b000 {
|
||||
compatible = "allwinner,sun4i-i2c";
|
||||
compatible = "allwinner,sun4i-a10-i2c";
|
||||
reg = <0x01c2b000 0x400>;
|
||||
interrupts = <8>;
|
||||
clocks = <&apb1_gates 1>;
|
||||
|
@ -735,7 +735,7 @@
|
|||
};
|
||||
|
||||
i2c2: i2c@01c2b400 {
|
||||
compatible = "allwinner,sun4i-i2c";
|
||||
compatible = "allwinner,sun4i-a10-i2c";
|
||||
reg = <0x01c2b400 0x400>;
|
||||
interrupts = <9>;
|
||||
clocks = <&apb1_gates 2>;
|
||||
|
|
|
@ -560,7 +560,7 @@
|
|||
i2c0: i2c@01c2ac00 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "allwinner,sun4i-i2c";
|
||||
compatible = "allwinner,sun5i-a10s-i2c", "allwinner,sun4i-a10-i2c";
|
||||
reg = <0x01c2ac00 0x400>;
|
||||
interrupts = <7>;
|
||||
clocks = <&apb1_gates 0>;
|
||||
|
@ -571,7 +571,7 @@
|
|||
i2c1: i2c@01c2b000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "allwinner,sun4i-i2c";
|
||||
compatible = "allwinner,sun5i-a10s-i2c", "allwinner,sun4i-a10-i2c";
|
||||
reg = <0x01c2b000 0x400>;
|
||||
interrupts = <8>;
|
||||
clocks = <&apb1_gates 1>;
|
||||
|
@ -582,7 +582,7 @@
|
|||
i2c2: i2c@01c2b400 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "allwinner,sun4i-i2c";
|
||||
compatible = "allwinner,sun5i-a10s-i2c", "allwinner,sun4i-a10-i2c";
|
||||
reg = <0x01c2b400 0x400>;
|
||||
interrupts = <9>;
|
||||
clocks = <&apb1_gates 2>;
|
||||
|
|
|
@ -486,7 +486,7 @@
|
|||
};
|
||||
|
||||
i2c0: i2c@01c2ac00 {
|
||||
compatible = "allwinner,sun4i-i2c";
|
||||
compatible = "allwinner,sun5i-a13-i2c", "allwinner,sun4i-a10-i2c";
|
||||
reg = <0x01c2ac00 0x400>;
|
||||
interrupts = <7>;
|
||||
clocks = <&apb1_gates 0>;
|
||||
|
@ -497,7 +497,7 @@
|
|||
};
|
||||
|
||||
i2c1: i2c@01c2b000 {
|
||||
compatible = "allwinner,sun4i-i2c";
|
||||
compatible = "allwinner,sun5i-a13-i2c", "allwinner,sun4i-a10-i2c";
|
||||
reg = <0x01c2b000 0x400>;
|
||||
interrupts = <8>;
|
||||
clocks = <&apb1_gates 1>;
|
||||
|
@ -508,7 +508,7 @@
|
|||
};
|
||||
|
||||
i2c2: i2c@01c2b400 {
|
||||
compatible = "allwinner,sun4i-i2c";
|
||||
compatible = "allwinner,sun5i-a13-i2c", "allwinner,sun4i-a10-i2c";
|
||||
reg = <0x01c2b400 0x400>;
|
||||
interrupts = <9>;
|
||||
clocks = <&apb1_gates 2>;
|
||||
|
|
|
@ -863,7 +863,7 @@
|
|||
};
|
||||
|
||||
i2c0: i2c@01c2ac00 {
|
||||
compatible = "allwinner,sun4i-i2c";
|
||||
compatible = "allwinner,sun7i-a20-i2c", "allwinner,sun4i-a10-i2c";
|
||||
reg = <0x01c2ac00 0x400>;
|
||||
interrupts = <0 7 4>;
|
||||
clocks = <&apb1_gates 0>;
|
||||
|
@ -874,7 +874,7 @@
|
|||
};
|
||||
|
||||
i2c1: i2c@01c2b000 {
|
||||
compatible = "allwinner,sun4i-i2c";
|
||||
compatible = "allwinner,sun7i-a20-i2c", "allwinner,sun4i-a10-i2c";
|
||||
reg = <0x01c2b000 0x400>;
|
||||
interrupts = <0 8 4>;
|
||||
clocks = <&apb1_gates 1>;
|
||||
|
@ -885,7 +885,7 @@
|
|||
};
|
||||
|
||||
i2c2: i2c@01c2b400 {
|
||||
compatible = "allwinner,sun4i-i2c";
|
||||
compatible = "allwinner,sun7i-a20-i2c", "allwinner,sun4i-a10-i2c";
|
||||
reg = <0x01c2b400 0x400>;
|
||||
interrupts = <0 9 4>;
|
||||
clocks = <&apb1_gates 2>;
|
||||
|
@ -896,7 +896,7 @@
|
|||
};
|
||||
|
||||
i2c3: i2c@01c2b800 {
|
||||
compatible = "allwinner,sun4i-i2c";
|
||||
compatible = "allwinner,sun7i-a20-i2c", "allwinner,sun4i-a10-i2c";
|
||||
reg = <0x01c2b800 0x400>;
|
||||
interrupts = <0 88 4>;
|
||||
clocks = <&apb1_gates 3>;
|
||||
|
@ -907,7 +907,7 @@
|
|||
};
|
||||
|
||||
i2c4: i2c@01c2c000 {
|
||||
compatible = "allwinner,sun4i-i2c";
|
||||
compatible = "allwinner,sun7i-a20-i2c", "allwinner,sun4i-a10-i2c";
|
||||
reg = <0x01c2c000 0x400>;
|
||||
interrupts = <0 89 4>;
|
||||
clocks = <&apb1_gates 15>;
|
||||
|
|
|
@ -449,7 +449,7 @@ config I2C_EFM32
|
|||
|
||||
config I2C_EG20T
|
||||
tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) I2C"
|
||||
depends on PCI
|
||||
depends on PCI && (X86_32 || COMPILE_TEST)
|
||||
help
|
||||
This driver is for PCH(Platform controller Hub) I2C of EG20T which
|
||||
is an IOH(Input/Output Hub) for x86 embedded processor.
|
||||
|
@ -570,13 +570,6 @@ config I2C_NOMADIK
|
|||
I2C interface from ST-Ericsson's Nomadik and Ux500 architectures,
|
||||
as well as the STA2X11 PCIe I/O HUB.
|
||||
|
||||
config I2C_NUC900
|
||||
tristate "NUC900 I2C Driver"
|
||||
depends on ARCH_W90X900
|
||||
help
|
||||
Say Y here to include support for I2C controller in the
|
||||
Winbond/Nuvoton NUC900 based System-on-Chip devices.
|
||||
|
||||
config I2C_OCORES
|
||||
tristate "OpenCores I2C Controller"
|
||||
help
|
||||
|
|
|
@ -55,7 +55,6 @@ obj-$(CONFIG_I2C_MPC) += i2c-mpc.o
|
|||
obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o
|
||||
obj-$(CONFIG_I2C_MXS) += i2c-mxs.o
|
||||
obj-$(CONFIG_I2C_NOMADIK) += i2c-nomadik.o
|
||||
obj-$(CONFIG_I2C_NUC900) += i2c-nuc900.o
|
||||
obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o
|
||||
obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
|
||||
obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
static struct pci_driver ali1563_pci_driver;
|
||||
static unsigned short ali1563_smba;
|
||||
|
||||
static int ali1563_transaction(struct i2c_adapter * a, int size)
|
||||
static int ali1563_transaction(struct i2c_adapter *a, int size)
|
||||
{
|
||||
u32 data;
|
||||
int timeout;
|
||||
|
@ -78,7 +78,7 @@ static int ali1563_transaction(struct i2c_adapter * a, int size)
|
|||
data = inb_p(SMB_HST_STS);
|
||||
if (data & HST_STS_BAD) {
|
||||
dev_err(&a->dev, "ali1563: Trying to reset busy device\n");
|
||||
outb_p(data | HST_STS_BAD,SMB_HST_STS);
|
||||
outb_p(data | HST_STS_BAD, SMB_HST_STS);
|
||||
data = inb_p(SMB_HST_STS);
|
||||
if (data & HST_STS_BAD)
|
||||
return -EBUSY;
|
||||
|
@ -102,10 +102,10 @@ static int ali1563_transaction(struct i2c_adapter * a, int size)
|
|||
if (!timeout) {
|
||||
dev_err(&a->dev, "Timeout - Trying to KILL transaction!\n");
|
||||
/* Issue 'kill' to host controller */
|
||||
outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2);
|
||||
outb_p(HST_CNTL2_KILL, SMB_HST_CNTL2);
|
||||
data = inb_p(SMB_HST_STS);
|
||||
status = -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* device error - no response, ignore the autodetection case */
|
||||
if (data & HST_STS_DEVERR) {
|
||||
|
@ -117,18 +117,18 @@ static int ali1563_transaction(struct i2c_adapter * a, int size)
|
|||
if (data & HST_STS_BUSERR) {
|
||||
dev_err(&a->dev, "Bus collision!\n");
|
||||
/* Issue timeout, hoping it helps */
|
||||
outb_p(HST_CNTL1_TIMEOUT,SMB_HST_CNTL1);
|
||||
outb_p(HST_CNTL1_TIMEOUT, SMB_HST_CNTL1);
|
||||
}
|
||||
|
||||
if (data & HST_STS_FAIL) {
|
||||
dev_err(&a->dev, "Cleaning fail after KILL!\n");
|
||||
outb_p(0x0,SMB_HST_CNTL2);
|
||||
outb_p(0x0, SMB_HST_CNTL2);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int ali1563_block_start(struct i2c_adapter * a)
|
||||
static int ali1563_block_start(struct i2c_adapter *a)
|
||||
{
|
||||
u32 data;
|
||||
int timeout;
|
||||
|
@ -142,8 +142,8 @@ static int ali1563_block_start(struct i2c_adapter * a)
|
|||
|
||||
data = inb_p(SMB_HST_STS);
|
||||
if (data & HST_STS_BAD) {
|
||||
dev_warn(&a->dev,"ali1563: Trying to reset busy device\n");
|
||||
outb_p(data | HST_STS_BAD,SMB_HST_STS);
|
||||
dev_warn(&a->dev, "ali1563: Trying to reset busy device\n");
|
||||
outb_p(data | HST_STS_BAD, SMB_HST_STS);
|
||||
data = inb_p(SMB_HST_STS);
|
||||
if (data & HST_STS_BAD)
|
||||
return -EBUSY;
|
||||
|
@ -184,13 +184,14 @@ static int ali1563_block_start(struct i2c_adapter * a)
|
|||
return status;
|
||||
}
|
||||
|
||||
static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8 rw)
|
||||
static int ali1563_block(struct i2c_adapter *a,
|
||||
union i2c_smbus_data *data, u8 rw)
|
||||
{
|
||||
int i, len;
|
||||
int error = 0;
|
||||
|
||||
/* Do we need this? */
|
||||
outb_p(HST_CNTL1_LAST,SMB_HST_CNTL1);
|
||||
outb_p(HST_CNTL1_LAST, SMB_HST_CNTL1);
|
||||
|
||||
if (rw == I2C_SMBUS_WRITE) {
|
||||
len = data->block[0];
|
||||
|
@ -198,8 +199,8 @@ static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8
|
|||
len = 1;
|
||||
else if (len > 32)
|
||||
len = 32;
|
||||
outb_p(len,SMB_HST_DAT0);
|
||||
outb_p(data->block[1],SMB_BLK_DAT);
|
||||
outb_p(len, SMB_HST_DAT0);
|
||||
outb_p(data->block[1], SMB_BLK_DAT);
|
||||
} else
|
||||
len = 32;
|
||||
|
||||
|
@ -208,10 +209,12 @@ static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8
|
|||
for (i = 0; i < len; i++) {
|
||||
if (rw == I2C_SMBUS_WRITE) {
|
||||
outb_p(data->block[i + 1], SMB_BLK_DAT);
|
||||
if ((error = ali1563_block_start(a)))
|
||||
error = ali1563_block_start(a);
|
||||
if (error)
|
||||
break;
|
||||
} else {
|
||||
if ((error = ali1563_block_start(a)))
|
||||
error = ali1563_block_start(a);
|
||||
if (error)
|
||||
break;
|
||||
if (i == 0) {
|
||||
len = inb_p(SMB_HST_DAT0);
|
||||
|
@ -224,25 +227,26 @@ static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8
|
|||
}
|
||||
}
|
||||
/* Do we need this? */
|
||||
outb_p(HST_CNTL1_LAST,SMB_HST_CNTL1);
|
||||
outb_p(HST_CNTL1_LAST, SMB_HST_CNTL1);
|
||||
return error;
|
||||
}
|
||||
|
||||
static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
|
||||
static s32 ali1563_access(struct i2c_adapter *a, u16 addr,
|
||||
unsigned short flags, char rw, u8 cmd,
|
||||
int size, union i2c_smbus_data * data)
|
||||
int size, union i2c_smbus_data *data)
|
||||
{
|
||||
int error = 0;
|
||||
int timeout;
|
||||
u32 reg;
|
||||
|
||||
for (timeout = ALI1563_MAX_TIMEOUT; timeout; timeout--) {
|
||||
if (!(reg = inb_p(SMB_HST_STS) & HST_STS_BUSY))
|
||||
reg = inb_p(SMB_HST_STS);
|
||||
if (!(reg & HST_STS_BUSY))
|
||||
break;
|
||||
}
|
||||
if (!timeout)
|
||||
dev_warn(&a->dev,"SMBus not idle. HST_STS = %02x\n",reg);
|
||||
outb_p(0xff,SMB_HST_STS);
|
||||
dev_warn(&a->dev, "SMBus not idle. HST_STS = %02x\n", reg);
|
||||
outb_p(0xff, SMB_HST_STS);
|
||||
|
||||
/* Map the size to what the chip understands */
|
||||
switch (size) {
|
||||
|
@ -268,13 +272,14 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
|
|||
}
|
||||
|
||||
outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD);
|
||||
outb_p((inb_p(SMB_HST_CNTL2) & ~HST_CNTL2_SIZEMASK) | (size << 3), SMB_HST_CNTL2);
|
||||
outb_p((inb_p(SMB_HST_CNTL2) & ~HST_CNTL2_SIZEMASK) |
|
||||
(size << 3), SMB_HST_CNTL2);
|
||||
|
||||
/* Write the command register */
|
||||
|
||||
switch(size) {
|
||||
switch (size) {
|
||||
case HST_CNTL2_BYTE:
|
||||
if (rw== I2C_SMBUS_WRITE)
|
||||
if (rw == I2C_SMBUS_WRITE)
|
||||
/* Beware it uses DAT0 register and not CMD! */
|
||||
outb_p(cmd, SMB_HST_DAT0);
|
||||
break;
|
||||
|
@ -292,11 +297,12 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
|
|||
break;
|
||||
case HST_CNTL2_BLOCK:
|
||||
outb_p(cmd, SMB_HST_CMD);
|
||||
error = ali1563_block(a,data,rw);
|
||||
error = ali1563_block(a, data, rw);
|
||||
goto Done;
|
||||
}
|
||||
|
||||
if ((error = ali1563_transaction(a, size)))
|
||||
error = ali1563_transaction(a, size);
|
||||
if (error)
|
||||
goto Done;
|
||||
|
||||
if ((rw == I2C_SMBUS_WRITE) || (size == HST_CNTL2_QUICK))
|
||||
|
@ -317,7 +323,7 @@ Done:
|
|||
return error;
|
||||
}
|
||||
|
||||
static u32 ali1563_func(struct i2c_adapter * a)
|
||||
static u32 ali1563_func(struct i2c_adapter *a)
|
||||
{
|
||||
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||
|
@ -329,13 +335,13 @@ static int ali1563_setup(struct pci_dev *dev)
|
|||
{
|
||||
u16 ctrl;
|
||||
|
||||
pci_read_config_word(dev,ALI1563_SMBBA,&ctrl);
|
||||
pci_read_config_word(dev, ALI1563_SMBBA, &ctrl);
|
||||
|
||||
/* SMB I/O Base in high 12 bits and must be aligned with the
|
||||
* size of the I/O space. */
|
||||
ali1563_smba = ctrl & ~(ALI1563_SMB_IOSIZE - 1);
|
||||
if (!ali1563_smba) {
|
||||
dev_warn(&dev->dev,"ali1563_smba Uninitialized\n");
|
||||
dev_warn(&dev->dev, "ali1563_smba Uninitialized\n");
|
||||
goto Err;
|
||||
}
|
||||
|
||||
|
@ -350,8 +356,8 @@ static int ali1563_setup(struct pci_dev *dev)
|
|||
ctrl | ALI1563_SMB_IOEN);
|
||||
pci_read_config_word(dev, ALI1563_SMBBA, &ctrl);
|
||||
if (!(ctrl & ALI1563_SMB_IOEN)) {
|
||||
dev_err(&dev->dev, "I/O space still not enabled, "
|
||||
"giving up\n");
|
||||
dev_err(&dev->dev,
|
||||
"I/O space still not enabled, giving up\n");
|
||||
goto Err;
|
||||
}
|
||||
}
|
||||
|
@ -375,7 +381,7 @@ Err:
|
|||
|
||||
static void ali1563_shutdown(struct pci_dev *dev)
|
||||
{
|
||||
release_region(ali1563_smba,ALI1563_SMB_IOSIZE);
|
||||
release_region(ali1563_smba, ALI1563_SMB_IOSIZE);
|
||||
}
|
||||
|
||||
static const struct i2c_algorithm ali1563_algorithm = {
|
||||
|
@ -394,12 +400,14 @@ static int ali1563_probe(struct pci_dev *dev,
|
|||
{
|
||||
int error;
|
||||
|
||||
if ((error = ali1563_setup(dev)))
|
||||
error = ali1563_setup(dev);
|
||||
if (error)
|
||||
goto exit;
|
||||
ali1563_adapter.dev.parent = &dev->dev;
|
||||
snprintf(ali1563_adapter.name, sizeof(ali1563_adapter.name),
|
||||
"SMBus ALi 1563 Adapter @ %04x", ali1563_smba);
|
||||
if ((error = i2c_add_adapter(&ali1563_adapter)))
|
||||
error = i2c_add_adapter(&ali1563_adapter);
|
||||
if (error)
|
||||
goto exit_shutdown;
|
||||
return 0;
|
||||
|
||||
|
@ -421,12 +429,12 @@ static const struct pci_device_id ali1563_id_table[] = {
|
|||
{},
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE (pci, ali1563_id_table);
|
||||
MODULE_DEVICE_TABLE(pci, ali1563_id_table);
|
||||
|
||||
static struct pci_driver ali1563_pci_driver = {
|
||||
.name = "ali1563_smbus",
|
||||
.name = "ali1563_smbus",
|
||||
.id_table = ali1563_id_table,
|
||||
.probe = ali1563_probe,
|
||||
.probe = ali1563_probe,
|
||||
.remove = ali1563_remove,
|
||||
};
|
||||
|
||||
|
|
|
@ -225,10 +225,8 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
|
|||
struct i2c_adapter *adap;
|
||||
|
||||
i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
|
||||
if (!i2c_dev) {
|
||||
dev_err(&pdev->dev, "Cannot allocate i2c_dev\n");
|
||||
if (!i2c_dev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
platform_set_drvdata(pdev, i2c_dev);
|
||||
i2c_dev->dev = &pdev->dev;
|
||||
init_completion(&i2c_dev->completion);
|
||||
|
|
|
@ -620,35 +620,27 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
|
|||
int rc;
|
||||
unsigned int clkhilow;
|
||||
|
||||
iface = kzalloc(sizeof(struct bfin_twi_iface), GFP_KERNEL);
|
||||
iface = devm_kzalloc(&pdev->dev, sizeof(struct bfin_twi_iface),
|
||||
GFP_KERNEL);
|
||||
if (!iface) {
|
||||
dev_err(&pdev->dev, "Cannot allocate memory\n");
|
||||
rc = -ENOMEM;
|
||||
goto out_error_nomem;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spin_lock_init(&(iface->lock));
|
||||
|
||||
/* Find and map our resources */
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (res == NULL) {
|
||||
dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
|
||||
rc = -ENOENT;
|
||||
goto out_error_get_res;
|
||||
}
|
||||
|
||||
iface->regs_base = ioremap(res->start, resource_size(res));
|
||||
if (iface->regs_base == NULL) {
|
||||
iface->regs_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(iface->regs_base)) {
|
||||
dev_err(&pdev->dev, "Cannot map IO\n");
|
||||
rc = -ENXIO;
|
||||
goto out_error_ioremap;
|
||||
return PTR_ERR(iface->regs_base);
|
||||
}
|
||||
|
||||
iface->irq = platform_get_irq(pdev, 0);
|
||||
if (iface->irq < 0) {
|
||||
dev_err(&pdev->dev, "No IRQ specified\n");
|
||||
rc = -ENOENT;
|
||||
goto out_error_no_irq;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
p_adap = &iface->adap;
|
||||
|
@ -666,15 +658,15 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
|
|||
"i2c-bfin-twi");
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "Can't setup pin mux!\n");
|
||||
goto out_error_pin_mux;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
rc = request_irq(iface->irq, bfin_twi_interrupt_entry,
|
||||
rc = devm_request_irq(&pdev->dev, iface->irq, bfin_twi_interrupt_entry,
|
||||
0, pdev->name, iface);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq);
|
||||
rc = -ENODEV;
|
||||
goto out_error_req_irq;
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
/* Set TWI internal clock as 10MHz */
|
||||
|
@ -695,7 +687,7 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
|
|||
rc = i2c_add_numbered_adapter(p_adap);
|
||||
if (rc < 0) {
|
||||
dev_err(&pdev->dev, "Can't add i2c adapter!\n");
|
||||
goto out_error_add_adapter;
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, iface);
|
||||
|
@ -705,17 +697,8 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
|
|||
|
||||
return 0;
|
||||
|
||||
out_error_add_adapter:
|
||||
free_irq(iface->irq, iface);
|
||||
out_error_req_irq:
|
||||
out_error_no_irq:
|
||||
out_error:
|
||||
peripheral_free_list(dev_get_platdata(&pdev->dev));
|
||||
out_error_pin_mux:
|
||||
iounmap(iface->regs_base);
|
||||
out_error_ioremap:
|
||||
out_error_get_res:
|
||||
kfree(iface);
|
||||
out_error_nomem:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -724,10 +707,7 @@ static int i2c_bfin_twi_remove(struct platform_device *pdev)
|
|||
struct bfin_twi_iface *iface = platform_get_drvdata(pdev);
|
||||
|
||||
i2c_del_adapter(&(iface->adap));
|
||||
free_irq(iface->irq, iface);
|
||||
peripheral_free_list(dev_get_platdata(&pdev->dev));
|
||||
iounmap(iface->regs_base);
|
||||
kfree(iface);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ enum dw_pci_ctl_id_t {
|
|||
medfield_5,
|
||||
|
||||
baytrail,
|
||||
haswell,
|
||||
};
|
||||
|
||||
struct dw_scl_sda_cfg {
|
||||
|
@ -95,6 +96,15 @@ static struct dw_scl_sda_cfg byt_config = {
|
|||
.sda_hold = 0x6,
|
||||
};
|
||||
|
||||
/* Haswell HCNT/LCNT/SDA hold time */
|
||||
static struct dw_scl_sda_cfg hsw_config = {
|
||||
.ss_hcnt = 0x01b0,
|
||||
.fs_hcnt = 0x48,
|
||||
.ss_lcnt = 0x01fb,
|
||||
.fs_lcnt = 0xa0,
|
||||
.sda_hold = 0x9,
|
||||
};
|
||||
|
||||
static struct dw_pci_controller dw_pci_controllers[] = {
|
||||
[moorestown_0] = {
|
||||
.bus_num = 0,
|
||||
|
@ -168,6 +178,15 @@ static struct dw_pci_controller dw_pci_controllers[] = {
|
|||
.functionality = I2C_FUNC_10BIT_ADDR,
|
||||
.scl_sda_cfg = &byt_config,
|
||||
},
|
||||
[haswell] = {
|
||||
.bus_num = -1,
|
||||
.bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
|
||||
.tx_fifo_depth = 32,
|
||||
.rx_fifo_depth = 32,
|
||||
.clk_khz = 100000,
|
||||
.functionality = I2C_FUNC_10BIT_ADDR,
|
||||
.scl_sda_cfg = &hsw_config,
|
||||
},
|
||||
};
|
||||
static struct i2c_algorithm i2c_dw_algo = {
|
||||
.master_xfer = i2c_dw_xfer,
|
||||
|
@ -328,6 +347,9 @@ static const struct pci_device_id i2_designware_pci_ids[] = {
|
|||
{ PCI_VDEVICE(INTEL, 0x0F45), baytrail },
|
||||
{ PCI_VDEVICE(INTEL, 0x0F46), baytrail },
|
||||
{ PCI_VDEVICE(INTEL, 0x0F47), baytrail },
|
||||
/* Haswell */
|
||||
{ PCI_VDEVICE(INTEL, 0x9c61), haswell },
|
||||
{ PCI_VDEVICE(INTEL, 0x9c62), haswell },
|
||||
{ 0,}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids);
|
||||
|
|
|
@ -247,12 +247,13 @@ static const struct of_device_id dw_i2c_of_match[] = {
|
|||
MODULE_DEVICE_TABLE(of, dw_i2c_of_match);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
#ifdef CONFIG_PM
|
||||
static int dw_i2c_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
|
||||
|
||||
i2c_dw_disable(i_dev);
|
||||
clk_disable_unprepare(i_dev->clk);
|
||||
|
||||
return 0;
|
||||
|
@ -268,13 +269,11 @@ static int dw_i2c_resume(struct device *dev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(dw_i2c_dev_pm_ops, dw_i2c_suspend, dw_i2c_resume);
|
||||
#define DW_I2C_DEV_PM_OPS (&dw_i2c_dev_pm_ops)
|
||||
#else
|
||||
#define DW_I2C_DEV_PM_OPS NULL
|
||||
#endif
|
||||
|
||||
static UNIVERSAL_DEV_PM_OPS(dw_i2c_dev_pm_ops, dw_i2c_suspend,
|
||||
dw_i2c_resume, NULL);
|
||||
|
||||
/* work with hotplug and coldplug */
|
||||
MODULE_ALIAS("platform:i2c_designware");
|
||||
|
||||
|
@ -286,7 +285,7 @@ static struct platform_driver dw_i2c_driver = {
|
|||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(dw_i2c_of_match),
|
||||
.acpi_match_table = ACPI_PTR(dw_i2c_acpi_match),
|
||||
.pm = DW_I2C_DEV_PM_OPS,
|
||||
.pm = &dw_i2c_dev_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -455,7 +455,6 @@ static int diolan_u2c_probe(struct usb_interface *interface,
|
|||
/* allocate memory for our device state and initialize it */
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (dev == NULL) {
|
||||
dev_err(&interface->dev, "no memory for device state\n");
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
|
|
@ -320,10 +320,8 @@ static int efm32_i2c_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
|
||||
ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
|
||||
if (!ddata) {
|
||||
dev_dbg(&pdev->dev, "failed to allocate private data\n");
|
||||
if (!ddata)
|
||||
return -ENOMEM;
|
||||
}
|
||||
platform_set_drvdata(pdev, ddata);
|
||||
|
||||
init_completion(&ddata->done);
|
||||
|
|
|
@ -751,10 +751,8 @@ static int pch_i2c_probe(struct pci_dev *pdev,
|
|||
pch_pci_dbg(pdev, "Entered.\n");
|
||||
|
||||
adap_info = kzalloc((sizeof(struct adapter_info)), GFP_KERNEL);
|
||||
if (adap_info == NULL) {
|
||||
pch_pci_err(pdev, "Memory allocation FAILED\n");
|
||||
if (adap_info == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = pci_enable_device(pdev);
|
||||
if (ret) {
|
||||
|
|
|
@ -76,12 +76,6 @@
|
|||
#define HSI2C_RXFIFO_TRIGGER_LEVEL(x) ((x) << 4)
|
||||
#define HSI2C_TXFIFO_TRIGGER_LEVEL(x) ((x) << 16)
|
||||
|
||||
/* As per user manual FIFO max depth is 64bytes */
|
||||
#define HSI2C_FIFO_MAX 0x40
|
||||
/* default trigger levels for Tx and Rx FIFOs */
|
||||
#define HSI2C_DEF_TXFIFO_LVL (HSI2C_FIFO_MAX - 0x30)
|
||||
#define HSI2C_DEF_RXFIFO_LVL (HSI2C_FIFO_MAX - 0x10)
|
||||
|
||||
/* I2C_TRAILING_CTL Register bits */
|
||||
#define HSI2C_TRAILING_COUNT (0xf)
|
||||
|
||||
|
@ -183,14 +177,54 @@ struct exynos5_i2c {
|
|||
* 2. Fast speed upto 1Mbps
|
||||
*/
|
||||
int speed_mode;
|
||||
|
||||
/* Version of HS-I2C Hardware */
|
||||
struct exynos_hsi2c_variant *variant;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct exynos_hsi2c_variant - platform specific HSI2C driver data
|
||||
* @fifo_depth: the fifo depth supported by the HSI2C module
|
||||
*
|
||||
* Specifies platform specific configuration of HSI2C module.
|
||||
* Note: A structure for driver specific platform data is used for future
|
||||
* expansion of its usage.
|
||||
*/
|
||||
struct exynos_hsi2c_variant {
|
||||
unsigned int fifo_depth;
|
||||
};
|
||||
|
||||
static const struct exynos_hsi2c_variant exynos5250_hsi2c_data = {
|
||||
.fifo_depth = 64,
|
||||
};
|
||||
|
||||
static const struct exynos_hsi2c_variant exynos5260_hsi2c_data = {
|
||||
.fifo_depth = 16,
|
||||
};
|
||||
|
||||
static const struct of_device_id exynos5_i2c_match[] = {
|
||||
{ .compatible = "samsung,exynos5-hsi2c" },
|
||||
{},
|
||||
{
|
||||
.compatible = "samsung,exynos5-hsi2c",
|
||||
.data = &exynos5250_hsi2c_data
|
||||
}, {
|
||||
.compatible = "samsung,exynos5250-hsi2c",
|
||||
.data = &exynos5250_hsi2c_data
|
||||
}, {
|
||||
.compatible = "samsung,exynos5260-hsi2c",
|
||||
.data = &exynos5260_hsi2c_data
|
||||
}, {},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, exynos5_i2c_match);
|
||||
|
||||
static inline struct exynos_hsi2c_variant *exynos5_i2c_get_variant
|
||||
(struct platform_device *pdev)
|
||||
{
|
||||
const struct of_device_id *match;
|
||||
|
||||
match = of_match_node(exynos5_i2c_match, pdev->dev.of_node);
|
||||
return (struct exynos_hsi2c_variant *)match->data;
|
||||
}
|
||||
|
||||
static void exynos5_i2c_clr_pend_irq(struct exynos5_i2c *i2c)
|
||||
{
|
||||
writel(readl(i2c->regs + HSI2C_INT_STATUS),
|
||||
|
@ -415,7 +449,7 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)
|
|||
fifo_status = readl(i2c->regs + HSI2C_FIFO_STATUS);
|
||||
fifo_level = HSI2C_TX_FIFO_LVL(fifo_status);
|
||||
|
||||
len = HSI2C_FIFO_MAX - fifo_level;
|
||||
len = i2c->variant->fifo_depth - fifo_level;
|
||||
if (len > (i2c->msg->len - i2c->msg_ptr))
|
||||
len = i2c->msg->len - i2c->msg_ptr;
|
||||
|
||||
|
@ -483,6 +517,7 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
|
|||
u32 i2c_auto_conf = 0;
|
||||
u32 fifo_ctl;
|
||||
unsigned long flags;
|
||||
unsigned short trig_lvl;
|
||||
|
||||
i2c_ctl = readl(i2c->regs + HSI2C_CTL);
|
||||
i2c_ctl &= ~(HSI2C_TXCHON | HSI2C_RXCHON);
|
||||
|
@ -493,13 +528,19 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
|
|||
|
||||
i2c_auto_conf = HSI2C_READ_WRITE;
|
||||
|
||||
fifo_ctl |= HSI2C_RXFIFO_TRIGGER_LEVEL(HSI2C_DEF_TXFIFO_LVL);
|
||||
trig_lvl = (i2c->msg->len > i2c->variant->fifo_depth) ?
|
||||
(i2c->variant->fifo_depth * 3 / 4) : i2c->msg->len;
|
||||
fifo_ctl |= HSI2C_RXFIFO_TRIGGER_LEVEL(trig_lvl);
|
||||
|
||||
int_en |= (HSI2C_INT_RX_ALMOSTFULL_EN |
|
||||
HSI2C_INT_TRAILING_EN);
|
||||
} else {
|
||||
i2c_ctl |= HSI2C_TXCHON;
|
||||
|
||||
fifo_ctl |= HSI2C_TXFIFO_TRIGGER_LEVEL(HSI2C_DEF_RXFIFO_LVL);
|
||||
trig_lvl = (i2c->msg->len > i2c->variant->fifo_depth) ?
|
||||
(i2c->variant->fifo_depth * 1 / 4) : i2c->msg->len;
|
||||
fifo_ctl |= HSI2C_TXFIFO_TRIGGER_LEVEL(trig_lvl);
|
||||
|
||||
int_en |= HSI2C_INT_TX_ALMOSTEMPTY_EN;
|
||||
}
|
||||
|
||||
|
@ -621,10 +662,8 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
|
|||
int ret;
|
||||
|
||||
i2c = devm_kzalloc(&pdev->dev, sizeof(struct exynos5_i2c), GFP_KERNEL);
|
||||
if (!i2c) {
|
||||
dev_err(&pdev->dev, "no memory for state\n");
|
||||
if (!i2c)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(np, "clock-frequency", &op_clock)) {
|
||||
i2c->speed_mode = HSI2C_FAST_SPD;
|
||||
|
@ -691,7 +730,9 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto err_clk;
|
||||
|
||||
exynos5_i2c_init(i2c);
|
||||
i2c->variant = exynos5_i2c_get_variant(pdev);
|
||||
|
||||
exynos5_i2c_reset(i2c);
|
||||
|
||||
ret = i2c_add_adapter(&i2c->adap);
|
||||
if (ret < 0) {
|
||||
|
|
|
@ -147,24 +147,22 @@ static int i2c_gpio_probe(struct platform_device *pdev)
|
|||
scl_pin = pdata->scl_pin;
|
||||
}
|
||||
|
||||
ret = gpio_request(sda_pin, "sda");
|
||||
ret = devm_gpio_request(&pdev->dev, sda_pin, "sda");
|
||||
if (ret) {
|
||||
if (ret == -EINVAL)
|
||||
ret = -EPROBE_DEFER; /* Try again later */
|
||||
goto err_request_sda;
|
||||
return ret;
|
||||
}
|
||||
ret = gpio_request(scl_pin, "scl");
|
||||
ret = devm_gpio_request(&pdev->dev, scl_pin, "scl");
|
||||
if (ret) {
|
||||
if (ret == -EINVAL)
|
||||
ret = -EPROBE_DEFER; /* Try again later */
|
||||
goto err_request_scl;
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv) {
|
||||
ret = -ENOMEM;
|
||||
goto err_add_bus;
|
||||
}
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
adap = &priv->adap;
|
||||
bit_data = &priv->bit_data;
|
||||
pdata = &priv->pdata;
|
||||
|
@ -225,7 +223,7 @@ static int i2c_gpio_probe(struct platform_device *pdev)
|
|||
adap->nr = pdev->id;
|
||||
ret = i2c_bit_add_numbered_bus(adap);
|
||||
if (ret)
|
||||
goto err_add_bus;
|
||||
return ret;
|
||||
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
|
@ -235,13 +233,6 @@ static int i2c_gpio_probe(struct platform_device *pdev)
|
|||
? ", no clock stretching" : "");
|
||||
|
||||
return 0;
|
||||
|
||||
err_add_bus:
|
||||
gpio_free(scl_pin);
|
||||
err_request_scl:
|
||||
gpio_free(sda_pin);
|
||||
err_request_sda:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int i2c_gpio_remove(struct platform_device *pdev)
|
||||
|
@ -255,8 +246,6 @@ static int i2c_gpio_remove(struct platform_device *pdev)
|
|||
pdata = &priv->pdata;
|
||||
|
||||
i2c_del_adapter(adap);
|
||||
gpio_free(pdata->scl_pin);
|
||||
gpio_free(pdata->sda_pin);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -183,6 +183,8 @@ struct imx_i2c_struct {
|
|||
unsigned int disable_delay;
|
||||
int stopped;
|
||||
unsigned int ifdr; /* IMX_I2C_IFDR */
|
||||
unsigned int cur_clk;
|
||||
unsigned int bitrate;
|
||||
const struct imx_i2c_hwdata *hwdata;
|
||||
};
|
||||
|
||||
|
@ -305,6 +307,48 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx)
|
||||
{
|
||||
struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div;
|
||||
unsigned int i2c_clk_rate;
|
||||
unsigned int div;
|
||||
int i;
|
||||
|
||||
/* Divider value calculation */
|
||||
i2c_clk_rate = clk_get_rate(i2c_imx->clk);
|
||||
if (i2c_imx->cur_clk == i2c_clk_rate)
|
||||
return;
|
||||
else
|
||||
i2c_imx->cur_clk = i2c_clk_rate;
|
||||
|
||||
div = (i2c_clk_rate + i2c_imx->bitrate - 1) / i2c_imx->bitrate;
|
||||
if (div < i2c_clk_div[0].div)
|
||||
i = 0;
|
||||
else if (div > i2c_clk_div[i2c_imx->hwdata->ndivs - 1].div)
|
||||
i = i2c_imx->hwdata->ndivs - 1;
|
||||
else
|
||||
for (i = 0; i2c_clk_div[i].div < div; i++);
|
||||
|
||||
/* Store divider value */
|
||||
i2c_imx->ifdr = i2c_clk_div[i].val;
|
||||
|
||||
/*
|
||||
* There dummy delay is calculated.
|
||||
* It should be about one I2C clock period long.
|
||||
* This delay is used in I2C bus disable function
|
||||
* to fix chip hardware bug.
|
||||
*/
|
||||
i2c_imx->disable_delay = (500000U * i2c_clk_div[i].div
|
||||
+ (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2);
|
||||
|
||||
#ifdef CONFIG_I2C_DEBUG_BUS
|
||||
dev_dbg(&i2c_imx->adapter.dev, "I2C_CLK=%d, REQ DIV=%d\n",
|
||||
i2c_clk_rate, div);
|
||||
dev_dbg(&i2c_imx->adapter.dev, "IFDR[IC]=0x%x, REAL DIV=%d\n",
|
||||
i2c_clk_div[i].val, i2c_clk_div[i].div);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
|
||||
{
|
||||
unsigned int temp = 0;
|
||||
|
@ -312,6 +356,8 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
|
|||
|
||||
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
|
||||
|
||||
i2c_imx_set_clk(i2c_imx);
|
||||
|
||||
result = clk_prepare_enable(i2c_imx->clk);
|
||||
if (result)
|
||||
return result;
|
||||
|
@ -367,45 +413,6 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
|
|||
clk_disable_unprepare(i2c_imx->clk);
|
||||
}
|
||||
|
||||
static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
|
||||
unsigned int rate)
|
||||
{
|
||||
struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div;
|
||||
unsigned int i2c_clk_rate;
|
||||
unsigned int div;
|
||||
int i;
|
||||
|
||||
/* Divider value calculation */
|
||||
i2c_clk_rate = clk_get_rate(i2c_imx->clk);
|
||||
div = (i2c_clk_rate + rate - 1) / rate;
|
||||
if (div < i2c_clk_div[0].div)
|
||||
i = 0;
|
||||
else if (div > i2c_clk_div[i2c_imx->hwdata->ndivs - 1].div)
|
||||
i = i2c_imx->hwdata->ndivs - 1;
|
||||
else
|
||||
for (i = 0; i2c_clk_div[i].div < div; i++);
|
||||
|
||||
/* Store divider value */
|
||||
i2c_imx->ifdr = i2c_clk_div[i].val;
|
||||
|
||||
/*
|
||||
* There dummy delay is calculated.
|
||||
* It should be about one I2C clock period long.
|
||||
* This delay is used in I2C bus disable function
|
||||
* to fix chip hardware bug.
|
||||
*/
|
||||
i2c_imx->disable_delay = (500000U * i2c_clk_div[i].div
|
||||
+ (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2);
|
||||
|
||||
/* dev_dbg() can't be used, because adapter is not yet registered */
|
||||
#ifdef CONFIG_I2C_DEBUG_BUS
|
||||
dev_dbg(&i2c_imx->adapter.dev, "<%s> I2C_CLK=%d, REQ DIV=%d\n",
|
||||
__func__, i2c_clk_rate, div);
|
||||
dev_dbg(&i2c_imx->adapter.dev, "<%s> IFDR[IC]=0x%x, REAL DIV=%d\n",
|
||||
__func__, i2c_clk_div[i].val, i2c_clk_div[i].div);
|
||||
#endif
|
||||
}
|
||||
|
||||
static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
|
||||
{
|
||||
struct imx_i2c_struct *i2c_imx = dev_id;
|
||||
|
@ -458,10 +465,11 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
|
||||
static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bool is_lastmsg)
|
||||
{
|
||||
int i, result;
|
||||
unsigned int temp;
|
||||
int block_data = msgs->flags & I2C_M_RECV_LEN;
|
||||
|
||||
dev_dbg(&i2c_imx->adapter.dev,
|
||||
"<%s> write slave address: addr=0x%x\n",
|
||||
|
@ -481,7 +489,12 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
|
|||
/* setup bus to read data */
|
||||
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
|
||||
temp &= ~I2CR_MTX;
|
||||
if (msgs->len - 1)
|
||||
|
||||
/*
|
||||
* Reset the I2CR_TXAK flag initially for SMBus block read since the
|
||||
* length is unknown
|
||||
*/
|
||||
if ((msgs->len - 1) || block_data)
|
||||
temp &= ~I2CR_TXAK;
|
||||
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
|
||||
imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); /* dummy read */
|
||||
|
@ -490,19 +503,49 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
|
|||
|
||||
/* read data */
|
||||
for (i = 0; i < msgs->len; i++) {
|
||||
u8 len = 0;
|
||||
result = i2c_imx_trx_complete(i2c_imx);
|
||||
if (result)
|
||||
return result;
|
||||
if (i == (msgs->len - 1)) {
|
||||
/* It must generate STOP before read I2DR to prevent
|
||||
controller from generating another clock cycle */
|
||||
/*
|
||||
* First byte is the length of remaining packet
|
||||
* in the SMBus block data read. Add it to
|
||||
* msgs->len.
|
||||
*/
|
||||
if ((!i) && block_data) {
|
||||
len = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
|
||||
if ((len == 0) || (len > I2C_SMBUS_BLOCK_MAX))
|
||||
return -EPROTO;
|
||||
dev_dbg(&i2c_imx->adapter.dev,
|
||||
"<%s> clear MSTA\n", __func__);
|
||||
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
|
||||
temp &= ~(I2CR_MSTA | I2CR_MTX);
|
||||
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
|
||||
i2c_imx_bus_busy(i2c_imx, 0);
|
||||
i2c_imx->stopped = 1;
|
||||
"<%s> read length: 0x%X\n",
|
||||
__func__, len);
|
||||
msgs->len += len;
|
||||
}
|
||||
if (i == (msgs->len - 1)) {
|
||||
if (is_lastmsg) {
|
||||
/*
|
||||
* It must generate STOP before read I2DR to prevent
|
||||
* controller from generating another clock cycle
|
||||
*/
|
||||
dev_dbg(&i2c_imx->adapter.dev,
|
||||
"<%s> clear MSTA\n", __func__);
|
||||
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
|
||||
temp &= ~(I2CR_MSTA | I2CR_MTX);
|
||||
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
|
||||
i2c_imx_bus_busy(i2c_imx, 0);
|
||||
i2c_imx->stopped = 1;
|
||||
} else {
|
||||
/*
|
||||
* For i2c master receiver repeat restart operation like:
|
||||
* read -> repeat MSTA -> read/write
|
||||
* The controller must set MTX before read the last byte in
|
||||
* the first read operation, otherwise the first read cost
|
||||
* one extra clock cycle.
|
||||
*/
|
||||
temp = readb(i2c_imx->base + IMX_I2C_I2CR);
|
||||
temp |= I2CR_MTX;
|
||||
writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
|
||||
}
|
||||
} else if (i == (msgs->len - 2)) {
|
||||
dev_dbg(&i2c_imx->adapter.dev,
|
||||
"<%s> set TXAK\n", __func__);
|
||||
|
@ -510,7 +553,10 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
|
|||
temp |= I2CR_TXAK;
|
||||
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
|
||||
}
|
||||
msgs->buf[i] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
|
||||
if ((!i) && block_data)
|
||||
msgs->buf[0] = len;
|
||||
else
|
||||
msgs->buf[i] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
|
||||
dev_dbg(&i2c_imx->adapter.dev,
|
||||
"<%s> read byte: B%d=0x%X\n",
|
||||
__func__, i, msgs->buf[i]);
|
||||
|
@ -523,6 +569,7 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
|
|||
{
|
||||
unsigned int i, temp;
|
||||
int result;
|
||||
bool is_lastmsg = false;
|
||||
struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter);
|
||||
|
||||
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
|
||||
|
@ -534,6 +581,9 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
|
|||
|
||||
/* read/write data */
|
||||
for (i = 0; i < num; i++) {
|
||||
if (i == num - 1)
|
||||
is_lastmsg = true;
|
||||
|
||||
if (i) {
|
||||
dev_dbg(&i2c_imx->adapter.dev,
|
||||
"<%s> repeated start\n", __func__);
|
||||
|
@ -564,7 +614,7 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
|
|||
(temp & I2SR_RXAK ? 1 : 0));
|
||||
#endif
|
||||
if (msgs[i].flags & I2C_M_RD)
|
||||
result = i2c_imx_read(i2c_imx, &msgs[i]);
|
||||
result = i2c_imx_read(i2c_imx, &msgs[i], is_lastmsg);
|
||||
else
|
||||
result = i2c_imx_write(i2c_imx, &msgs[i]);
|
||||
if (result)
|
||||
|
@ -583,7 +633,8 @@ fail0:
|
|||
|
||||
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
|
||||
| I2C_FUNC_SMBUS_READ_BLOCK_DATA;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm i2c_imx_algo = {
|
||||
|
@ -600,7 +651,6 @@ static int i2c_imx_probe(struct platform_device *pdev)
|
|||
struct imxi2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
void __iomem *base;
|
||||
int irq, ret;
|
||||
u32 bitrate;
|
||||
|
||||
dev_dbg(&pdev->dev, "<%s>\n", __func__);
|
||||
|
||||
|
@ -617,10 +667,8 @@ static int i2c_imx_probe(struct platform_device *pdev)
|
|||
|
||||
i2c_imx = devm_kzalloc(&pdev->dev, sizeof(struct imx_i2c_struct),
|
||||
GFP_KERNEL);
|
||||
if (!i2c_imx) {
|
||||
dev_err(&pdev->dev, "can't allocate interface\n");
|
||||
if (!i2c_imx)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (of_id)
|
||||
i2c_imx->hwdata = of_id->data;
|
||||
|
@ -664,12 +712,11 @@ static int i2c_imx_probe(struct platform_device *pdev)
|
|||
i2c_set_adapdata(&i2c_imx->adapter, i2c_imx);
|
||||
|
||||
/* Set up clock divider */
|
||||
bitrate = IMX_I2C_BIT_RATE;
|
||||
i2c_imx->bitrate = IMX_I2C_BIT_RATE;
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"clock-frequency", &bitrate);
|
||||
"clock-frequency", &i2c_imx->bitrate);
|
||||
if (ret < 0 && pdata && pdata->bitrate)
|
||||
bitrate = pdata->bitrate;
|
||||
i2c_imx_set_clk(i2c_imx, bitrate);
|
||||
i2c_imx->bitrate = pdata->bitrate;
|
||||
|
||||
/* Set up chip registers to defaults */
|
||||
imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
|
||||
|
|
|
@ -115,7 +115,7 @@ static void mpc_i2c_fixup(struct mpc_i2c *i2c)
|
|||
for (k = 9; k; k--) {
|
||||
writeccr(i2c, 0);
|
||||
writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN);
|
||||
udelay(delay_val);
|
||||
readb(i2c->base + MPC_I2C_DR);
|
||||
writeccr(i2c, CCR_MEN);
|
||||
udelay(delay_val << 1);
|
||||
}
|
||||
|
|
|
@ -681,7 +681,7 @@ static const struct i2c_algorithm mv64xxx_i2c_algo = {
|
|||
*****************************************************************************
|
||||
*/
|
||||
static const struct of_device_id mv64xxx_i2c_of_match_table[] = {
|
||||
{ .compatible = "allwinner,sun4i-i2c", .data = &mv64xxx_i2c_regs_sun4i},
|
||||
{ .compatible = "allwinner,sun4i-a10-i2c", .data = &mv64xxx_i2c_regs_sun4i},
|
||||
{ .compatible = "allwinner,sun6i-a31-i2c", .data = &mv64xxx_i2c_regs_sun4i},
|
||||
{ .compatible = "marvell,mv64xxx-i2c", .data = &mv64xxx_i2c_regs_mv64xxx},
|
||||
{ .compatible = "marvell,mv78230-i2c", .data = &mv64xxx_i2c_regs_mv64xxx},
|
||||
|
|
|
@ -879,19 +879,19 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg)
|
|||
#ifdef CONFIG_PM_SLEEP
|
||||
static int nmk_i2c_suspend_late(struct device *dev)
|
||||
{
|
||||
pinctrl_pm_select_sleep_state(dev);
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_force_suspend(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pinctrl_pm_select_sleep_state(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nmk_i2c_resume_early(struct device *dev)
|
||||
{
|
||||
/* First go to the default state */
|
||||
pinctrl_pm_select_default_state(dev);
|
||||
/* Then let's idle the pins until the next transfer happens */
|
||||
pinctrl_pm_select_idle_state(dev);
|
||||
|
||||
return 0;
|
||||
return pm_runtime_force_resume(dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,709 +0,0 @@
|
|||
/*
|
||||
* linux/drivers/i2c/busses/i2c-nuc900.c
|
||||
*
|
||||
* Copyright (c) 2010 Nuvoton technology corporation.
|
||||
*
|
||||
* This driver based on S3C2410 I2C driver of Ben Dooks <ben-Y5A6D6n0/KfQXOPxS62xeg@public.gmane.org>.
|
||||
* Written by Wan ZongShun <mcuos.com-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation;version 2 of the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <mach/mfp.h>
|
||||
#include <linux/platform_data/i2c-nuc900.h>
|
||||
|
||||
/* nuc900 i2c registers offset */
|
||||
|
||||
#define CSR 0x00
|
||||
#define DIVIDER 0x04
|
||||
#define CMDR 0x08
|
||||
#define SWR 0x0C
|
||||
#define RXR 0x10
|
||||
#define TXR 0x14
|
||||
|
||||
/* nuc900 i2c CSR register bits */
|
||||
|
||||
#define IRQEN 0x003
|
||||
#define I2CBUSY 0x400
|
||||
#define I2CSTART 0x018
|
||||
#define IRQFLAG 0x004
|
||||
#define ARBIT_LOST 0x200
|
||||
#define SLAVE_ACK 0x800
|
||||
|
||||
/* nuc900 i2c CMDR register bits */
|
||||
|
||||
#define I2C_CMD_START 0x10
|
||||
#define I2C_CMD_STOP 0x08
|
||||
#define I2C_CMD_READ 0x04
|
||||
#define I2C_CMD_WRITE 0x02
|
||||
#define I2C_CMD_NACK 0x01
|
||||
|
||||
/* i2c controller state */
|
||||
|
||||
enum nuc900_i2c_state {
|
||||
STATE_IDLE,
|
||||
STATE_START,
|
||||
STATE_READ,
|
||||
STATE_WRITE,
|
||||
STATE_STOP
|
||||
};
|
||||
|
||||
/* i2c controller private data */
|
||||
|
||||
struct nuc900_i2c {
|
||||
spinlock_t lock;
|
||||
wait_queue_head_t wait;
|
||||
|
||||
struct i2c_msg *msg;
|
||||
unsigned int msg_num;
|
||||
unsigned int msg_idx;
|
||||
unsigned int msg_ptr;
|
||||
unsigned int irq;
|
||||
|
||||
enum nuc900_i2c_state state;
|
||||
|
||||
void __iomem *regs;
|
||||
struct clk *clk;
|
||||
struct device *dev;
|
||||
struct resource *ioarea;
|
||||
struct i2c_adapter adap;
|
||||
};
|
||||
|
||||
/* nuc900_i2c_master_complete
|
||||
*
|
||||
* complete the message and wake up the caller, using the given return code,
|
||||
* or zero to mean ok.
|
||||
*/
|
||||
|
||||
static inline void nuc900_i2c_master_complete(struct nuc900_i2c *i2c, int ret)
|
||||
{
|
||||
dev_dbg(i2c->dev, "master_complete %d\n", ret);
|
||||
|
||||
i2c->msg_ptr = 0;
|
||||
i2c->msg = NULL;
|
||||
i2c->msg_idx++;
|
||||
i2c->msg_num = 0;
|
||||
if (ret)
|
||||
i2c->msg_idx = ret;
|
||||
|
||||
wake_up(&i2c->wait);
|
||||
}
|
||||
|
||||
/* irq enable/disable functions */
|
||||
|
||||
static inline void nuc900_i2c_disable_irq(struct nuc900_i2c *i2c)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
tmp = readl(i2c->regs + CSR);
|
||||
writel(tmp & ~IRQEN, i2c->regs + CSR);
|
||||
}
|
||||
|
||||
static inline void nuc900_i2c_enable_irq(struct nuc900_i2c *i2c)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
tmp = readl(i2c->regs + CSR);
|
||||
writel(tmp | IRQEN, i2c->regs + CSR);
|
||||
}
|
||||
|
||||
|
||||
/* nuc900_i2c_message_start
|
||||
*
|
||||
* put the start of a message onto the bus
|
||||
*/
|
||||
|
||||
static void nuc900_i2c_message_start(struct nuc900_i2c *i2c,
|
||||
struct i2c_msg *msg)
|
||||
{
|
||||
unsigned int addr = (msg->addr & 0x7f) << 1;
|
||||
|
||||
if (msg->flags & I2C_M_RD)
|
||||
addr |= 0x1;
|
||||
writel(addr & 0xff, i2c->regs + TXR);
|
||||
writel(I2C_CMD_START | I2C_CMD_WRITE, i2c->regs + CMDR);
|
||||
}
|
||||
|
||||
static inline void nuc900_i2c_stop(struct nuc900_i2c *i2c, int ret)
|
||||
{
|
||||
|
||||
dev_dbg(i2c->dev, "STOP\n");
|
||||
|
||||
/* stop the transfer */
|
||||
i2c->state = STATE_STOP;
|
||||
writel(I2C_CMD_STOP, i2c->regs + CMDR);
|
||||
|
||||
nuc900_i2c_master_complete(i2c, ret);
|
||||
nuc900_i2c_disable_irq(i2c);
|
||||
}
|
||||
|
||||
/* helper functions to determine the current state in the set of
|
||||
* messages we are sending
|
||||
*/
|
||||
|
||||
/* is_lastmsg()
|
||||
*
|
||||
* returns TRUE if the current message is the last in the set
|
||||
*/
|
||||
|
||||
static inline int is_lastmsg(struct nuc900_i2c *i2c)
|
||||
{
|
||||
return i2c->msg_idx >= (i2c->msg_num - 1);
|
||||
}
|
||||
|
||||
/* is_msglast
|
||||
*
|
||||
* returns TRUE if we this is the last byte in the current message
|
||||
*/
|
||||
|
||||
static inline int is_msglast(struct nuc900_i2c *i2c)
|
||||
{
|
||||
return i2c->msg_ptr == i2c->msg->len-1;
|
||||
}
|
||||
|
||||
/* is_msgend
|
||||
*
|
||||
* returns TRUE if we reached the end of the current message
|
||||
*/
|
||||
|
||||
static inline int is_msgend(struct nuc900_i2c *i2c)
|
||||
{
|
||||
return i2c->msg_ptr >= i2c->msg->len;
|
||||
}
|
||||
|
||||
/* i2c_nuc900_irq_nextbyte
|
||||
*
|
||||
* process an interrupt and work out what to do
|
||||
*/
|
||||
|
||||
static void i2c_nuc900_irq_nextbyte(struct nuc900_i2c *i2c,
|
||||
unsigned long iicstat)
|
||||
{
|
||||
unsigned char byte;
|
||||
|
||||
switch (i2c->state) {
|
||||
|
||||
case STATE_IDLE:
|
||||
dev_err(i2c->dev, "%s: called in STATE_IDLE\n", __func__);
|
||||
break;
|
||||
|
||||
case STATE_STOP:
|
||||
dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__);
|
||||
nuc900_i2c_disable_irq(i2c);
|
||||
break;
|
||||
|
||||
case STATE_START:
|
||||
/* last thing we did was send a start condition on the
|
||||
* bus, or started a new i2c message
|
||||
*/
|
||||
|
||||
if (iicstat & SLAVE_ACK &&
|
||||
!(i2c->msg->flags & I2C_M_IGNORE_NAK)) {
|
||||
/* ack was not received... */
|
||||
|
||||
dev_dbg(i2c->dev, "ack was not received\n");
|
||||
nuc900_i2c_stop(i2c, -ENXIO);
|
||||
break;
|
||||
}
|
||||
|
||||
if (i2c->msg->flags & I2C_M_RD)
|
||||
i2c->state = STATE_READ;
|
||||
else
|
||||
i2c->state = STATE_WRITE;
|
||||
|
||||
/* terminate the transfer if there is nothing to do
|
||||
* as this is used by the i2c probe to find devices.
|
||||
*/
|
||||
|
||||
if (is_lastmsg(i2c) && i2c->msg->len == 0) {
|
||||
nuc900_i2c_stop(i2c, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (i2c->state == STATE_READ)
|
||||
goto prepare_read;
|
||||
|
||||
/* fall through to the write state, as we will need to
|
||||
* send a byte as well
|
||||
*/
|
||||
|
||||
case STATE_WRITE:
|
||||
/* we are writing data to the device... check for the
|
||||
* end of the message, and if so, work out what to do
|
||||
*/
|
||||
|
||||
if (!(i2c->msg->flags & I2C_M_IGNORE_NAK)) {
|
||||
if (iicstat & SLAVE_ACK) {
|
||||
dev_dbg(i2c->dev, "WRITE: No Ack\n");
|
||||
|
||||
nuc900_i2c_stop(i2c, -ECONNREFUSED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
retry_write:
|
||||
|
||||
if (!is_msgend(i2c)) {
|
||||
byte = i2c->msg->buf[i2c->msg_ptr++];
|
||||
writeb(byte, i2c->regs + TXR);
|
||||
writel(I2C_CMD_WRITE, i2c->regs + CMDR);
|
||||
|
||||
} else if (!is_lastmsg(i2c)) {
|
||||
/* we need to go to the next i2c message */
|
||||
|
||||
dev_dbg(i2c->dev, "WRITE: Next Message\n");
|
||||
|
||||
i2c->msg_ptr = 0;
|
||||
i2c->msg_idx++;
|
||||
i2c->msg++;
|
||||
|
||||
/* check to see if we need to do another message */
|
||||
if (i2c->msg->flags & I2C_M_NOSTART) {
|
||||
|
||||
if (i2c->msg->flags & I2C_M_RD) {
|
||||
/* cannot do this, the controller
|
||||
* forces us to send a new START
|
||||
* when we change direction
|
||||
*/
|
||||
|
||||
nuc900_i2c_stop(i2c, -EINVAL);
|
||||
}
|
||||
|
||||
goto retry_write;
|
||||
} else {
|
||||
/* send the new start */
|
||||
nuc900_i2c_message_start(i2c, i2c->msg);
|
||||
i2c->state = STATE_START;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* send stop */
|
||||
|
||||
nuc900_i2c_stop(i2c, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_READ:
|
||||
/* we have a byte of data in the data register, do
|
||||
* something with it, and then work out whether we are
|
||||
* going to do any more read/write
|
||||
*/
|
||||
|
||||
byte = readb(i2c->regs + RXR);
|
||||
i2c->msg->buf[i2c->msg_ptr++] = byte;
|
||||
|
||||
prepare_read:
|
||||
if (is_msglast(i2c)) {
|
||||
/* last byte of buffer */
|
||||
|
||||
if (is_lastmsg(i2c))
|
||||
writel(I2C_CMD_READ | I2C_CMD_NACK,
|
||||
i2c->regs + CMDR);
|
||||
|
||||
} else if (is_msgend(i2c)) {
|
||||
/* ok, we've read the entire buffer, see if there
|
||||
* is anything else we need to do
|
||||
*/
|
||||
|
||||
if (is_lastmsg(i2c)) {
|
||||
/* last message, send stop and complete */
|
||||
dev_dbg(i2c->dev, "READ: Send Stop\n");
|
||||
|
||||
nuc900_i2c_stop(i2c, 0);
|
||||
} else {
|
||||
/* go to the next transfer */
|
||||
dev_dbg(i2c->dev, "READ: Next Transfer\n");
|
||||
|
||||
i2c->msg_ptr = 0;
|
||||
i2c->msg_idx++;
|
||||
i2c->msg++;
|
||||
|
||||
writel(I2C_CMD_READ, i2c->regs + CMDR);
|
||||
}
|
||||
|
||||
} else {
|
||||
writel(I2C_CMD_READ, i2c->regs + CMDR);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* nuc900_i2c_irq
|
||||
*
|
||||
* top level IRQ servicing routine
|
||||
*/
|
||||
|
||||
static irqreturn_t nuc900_i2c_irq(int irqno, void *dev_id)
|
||||
{
|
||||
struct nuc900_i2c *i2c = dev_id;
|
||||
unsigned long status;
|
||||
|
||||
status = readl(i2c->regs + CSR);
|
||||
writel(status | IRQFLAG, i2c->regs + CSR);
|
||||
|
||||
if (status & ARBIT_LOST) {
|
||||
/* deal with arbitration loss */
|
||||
dev_err(i2c->dev, "deal with arbitration loss\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (i2c->state == STATE_IDLE) {
|
||||
dev_dbg(i2c->dev, "IRQ: error i2c->state == IDLE\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* pretty much this leaves us with the fact that we've
|
||||
* transmitted or received whatever byte we last sent
|
||||
*/
|
||||
|
||||
i2c_nuc900_irq_nextbyte(i2c, status);
|
||||
|
||||
out:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
/* nuc900_i2c_set_master
|
||||
*
|
||||
* get the i2c bus for a master transaction
|
||||
*/
|
||||
|
||||
static int nuc900_i2c_set_master(struct nuc900_i2c *i2c)
|
||||
{
|
||||
int timeout = 400;
|
||||
|
||||
while (timeout-- > 0) {
|
||||
if (((readl(i2c->regs + SWR) & I2CSTART) == I2CSTART) &&
|
||||
((readl(i2c->regs + CSR) & I2CBUSY) == 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
msleep(1);
|
||||
}
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/* nuc900_i2c_doxfer
|
||||
*
|
||||
* this starts an i2c transfer
|
||||
*/
|
||||
|
||||
static int nuc900_i2c_doxfer(struct nuc900_i2c *i2c,
|
||||
struct i2c_msg *msgs, int num)
|
||||
{
|
||||
unsigned long iicstat, timeout;
|
||||
int spins = 20;
|
||||
int ret;
|
||||
|
||||
ret = nuc900_i2c_set_master(i2c);
|
||||
if (ret != 0) {
|
||||
dev_err(i2c->dev, "cannot get bus (error %d)\n", ret);
|
||||
ret = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock_irq(&i2c->lock);
|
||||
|
||||
i2c->msg = msgs;
|
||||
i2c->msg_num = num;
|
||||
i2c->msg_ptr = 0;
|
||||
i2c->msg_idx = 0;
|
||||
i2c->state = STATE_START;
|
||||
|
||||
nuc900_i2c_message_start(i2c, msgs);
|
||||
spin_unlock_irq(&i2c->lock);
|
||||
|
||||
timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
|
||||
|
||||
ret = i2c->msg_idx;
|
||||
|
||||
/* having these next two as dev_err() makes life very
|
||||
* noisy when doing an i2cdetect
|
||||
*/
|
||||
|
||||
if (timeout == 0)
|
||||
dev_dbg(i2c->dev, "timeout\n");
|
||||
else if (ret != num)
|
||||
dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret);
|
||||
|
||||
/* ensure the stop has been through the bus */
|
||||
|
||||
dev_dbg(i2c->dev, "waiting for bus idle\n");
|
||||
|
||||
/* first, try busy waiting briefly */
|
||||
do {
|
||||
iicstat = readl(i2c->regs + CSR);
|
||||
} while ((iicstat & I2CBUSY) && --spins);
|
||||
|
||||
/* if that timed out sleep */
|
||||
if (!spins) {
|
||||
msleep(1);
|
||||
iicstat = readl(i2c->regs + CSR);
|
||||
}
|
||||
|
||||
if (iicstat & I2CBUSY)
|
||||
dev_warn(i2c->dev, "timeout waiting for bus idle\n");
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* nuc900_i2c_xfer
|
||||
*
|
||||
* first port of call from the i2c bus code when an message needs
|
||||
* transferring across the i2c bus.
|
||||
*/
|
||||
|
||||
static int nuc900_i2c_xfer(struct i2c_adapter *adap,
|
||||
struct i2c_msg *msgs, int num)
|
||||
{
|
||||
struct nuc900_i2c *i2c = (struct nuc900_i2c *)adap->algo_data;
|
||||
int retry;
|
||||
int ret;
|
||||
|
||||
nuc900_i2c_enable_irq(i2c);
|
||||
|
||||
for (retry = 0; retry < adap->retries; retry++) {
|
||||
|
||||
ret = nuc900_i2c_doxfer(i2c, msgs, num);
|
||||
|
||||
if (ret != -EAGAIN)
|
||||
return ret;
|
||||
|
||||
dev_dbg(i2c->dev, "Retrying transmission (%d)\n", retry);
|
||||
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
/* declare our i2c functionality */
|
||||
static u32 nuc900_i2c_func(struct i2c_adapter *adap)
|
||||
{
|
||||
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_NOSTART |
|
||||
I2C_FUNC_PROTOCOL_MANGLING;
|
||||
}
|
||||
|
||||
/* i2c bus registration info */
|
||||
|
||||
static const struct i2c_algorithm nuc900_i2c_algorithm = {
|
||||
.master_xfer = nuc900_i2c_xfer,
|
||||
.functionality = nuc900_i2c_func,
|
||||
};
|
||||
|
||||
/* nuc900_i2c_probe
|
||||
*
|
||||
* called by the bus driver when a suitable device is found
|
||||
*/
|
||||
|
||||
static int nuc900_i2c_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct nuc900_i2c *i2c;
|
||||
struct nuc900_platform_i2c *pdata;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
pdata = dev_get_platdata(&pdev->dev);
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "no platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
i2c = kzalloc(sizeof(struct nuc900_i2c), GFP_KERNEL);
|
||||
if (!i2c) {
|
||||
dev_err(&pdev->dev, "no memory for state\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
strlcpy(i2c->adap.name, "nuc900-i2c0", sizeof(i2c->adap.name));
|
||||
i2c->adap.owner = THIS_MODULE;
|
||||
i2c->adap.algo = &nuc900_i2c_algorithm;
|
||||
i2c->adap.retries = 2;
|
||||
i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
||||
|
||||
spin_lock_init(&i2c->lock);
|
||||
init_waitqueue_head(&i2c->wait);
|
||||
|
||||
/* find the clock and enable it */
|
||||
|
||||
i2c->dev = &pdev->dev;
|
||||
i2c->clk = clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(i2c->clk)) {
|
||||
dev_err(&pdev->dev, "cannot get clock\n");
|
||||
ret = -ENOENT;
|
||||
goto err_noclk;
|
||||
}
|
||||
|
||||
dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk);
|
||||
|
||||
clk_enable(i2c->clk);
|
||||
|
||||
/* map the registers */
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (res == NULL) {
|
||||
dev_err(&pdev->dev, "cannot find IO resource\n");
|
||||
ret = -ENOENT;
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
i2c->ioarea = request_mem_region(res->start, resource_size(res),
|
||||
pdev->name);
|
||||
|
||||
if (i2c->ioarea == NULL) {
|
||||
dev_err(&pdev->dev, "cannot request IO\n");
|
||||
ret = -ENXIO;
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
i2c->regs = ioremap(res->start, resource_size(res));
|
||||
|
||||
if (i2c->regs == NULL) {
|
||||
dev_err(&pdev->dev, "cannot map IO\n");
|
||||
ret = -ENXIO;
|
||||
goto err_ioarea;
|
||||
}
|
||||
|
||||
dev_dbg(&pdev->dev, "registers %p (%p, %p)\n",
|
||||
i2c->regs, i2c->ioarea, res);
|
||||
|
||||
/* setup info block for the i2c core */
|
||||
|
||||
i2c->adap.algo_data = i2c;
|
||||
i2c->adap.dev.parent = &pdev->dev;
|
||||
|
||||
mfp_set_groupg(&pdev->dev, NULL);
|
||||
|
||||
clk_get_rate(i2c->clk);
|
||||
|
||||
ret = (i2c->clk.apbfreq)/(pdata->bus_freq * 5) - 1;
|
||||
writel(ret & 0xffff, i2c->regs + DIVIDER);
|
||||
|
||||
/* find the IRQ for this unit (note, this relies on the init call to
|
||||
* ensure no current IRQs pending
|
||||
*/
|
||||
|
||||
i2c->irq = ret = platform_get_irq(pdev, 0);
|
||||
if (ret <= 0) {
|
||||
dev_err(&pdev->dev, "cannot find IRQ\n");
|
||||
goto err_iomap;
|
||||
}
|
||||
|
||||
ret = request_irq(i2c->irq, nuc900_i2c_irq, IRQF_SHARED,
|
||||
dev_name(&pdev->dev), i2c);
|
||||
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
|
||||
goto err_iomap;
|
||||
}
|
||||
|
||||
/* Note, previous versions of the driver used i2c_add_adapter()
|
||||
* to add the bus at any number. We now pass the bus number via
|
||||
* the platform data, so if unset it will now default to always
|
||||
* being bus 0.
|
||||
*/
|
||||
|
||||
i2c->adap.nr = pdata->bus_num;
|
||||
|
||||
ret = i2c_add_numbered_adapter(&i2c->adap);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to add bus to i2c core\n");
|
||||
goto err_irq;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, i2c);
|
||||
|
||||
dev_info(&pdev->dev, "%s: NUC900 I2C adapter\n",
|
||||
dev_name(&i2c->adap.dev));
|
||||
return 0;
|
||||
|
||||
err_irq:
|
||||
free_irq(i2c->irq, i2c);
|
||||
|
||||
err_iomap:
|
||||
iounmap(i2c->regs);
|
||||
|
||||
err_ioarea:
|
||||
release_resource(i2c->ioarea);
|
||||
kfree(i2c->ioarea);
|
||||
|
||||
err_clk:
|
||||
clk_disable(i2c->clk);
|
||||
clk_put(i2c->clk);
|
||||
|
||||
err_noclk:
|
||||
kfree(i2c);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* nuc900_i2c_remove
|
||||
*
|
||||
* called when device is removed from the bus
|
||||
*/
|
||||
|
||||
static int nuc900_i2c_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct nuc900_i2c *i2c = platform_get_drvdata(pdev);
|
||||
|
||||
i2c_del_adapter(&i2c->adap);
|
||||
free_irq(i2c->irq, i2c);
|
||||
|
||||
clk_disable(i2c->clk);
|
||||
clk_put(i2c->clk);
|
||||
|
||||
iounmap(i2c->regs);
|
||||
|
||||
release_resource(i2c->ioarea);
|
||||
kfree(i2c->ioarea);
|
||||
kfree(i2c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver nuc900_i2c_driver = {
|
||||
.probe = nuc900_i2c_probe,
|
||||
.remove = nuc900_i2c_remove,
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "nuc900-i2c0",
|
||||
},
|
||||
};
|
||||
|
||||
static int __init i2c_adap_nuc900_init(void)
|
||||
{
|
||||
return platform_driver_register(&nuc900_i2c_driver);
|
||||
}
|
||||
|
||||
static void __exit i2c_adap_nuc900_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&nuc900_i2c_driver);
|
||||
}
|
||||
subsys_initcall(i2c_adap_nuc900_init);
|
||||
module_exit(i2c_adap_nuc900_exit);
|
||||
|
||||
MODULE_DESCRIPTION("NUC900 I2C Bus driver");
|
||||
MODULE_AUTHOR("Wan ZongShun, <mcuos.com-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:nuc900-i2c0");
|
|
@ -250,7 +250,7 @@ static struct i2c_adapter ocores_adapter = {
|
|||
.algo = &ocores_algorithm,
|
||||
};
|
||||
|
||||
static struct of_device_id ocores_i2c_match[] = {
|
||||
static const struct of_device_id ocores_i2c_match[] = {
|
||||
{
|
||||
.compatible = "opencores,i2c-ocores",
|
||||
.data = (void *)TYPE_OCORES,
|
||||
|
|
|
@ -1114,10 +1114,8 @@ omap_i2c_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
dev = devm_kzalloc(&pdev->dev, sizeof(struct omap_i2c_dev), GFP_KERNEL);
|
||||
if (!dev) {
|
||||
dev_err(&pdev->dev, "Menory allocation failed\n");
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
dev->base = devm_ioremap_resource(&pdev->dev, mem);
|
||||
|
|
|
@ -1084,7 +1084,7 @@ static const struct i2c_algorithm i2c_pxa_pio_algorithm = {
|
|||
.functionality = i2c_pxa_functionality,
|
||||
};
|
||||
|
||||
static 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,pwri2c", .data = (void *)REGS_PXA3XX },
|
||||
{ .compatible = "mrvl,mmp-twsi", .data = (void *)REGS_PXA2XX },
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
/*
|
||||
* drivers/i2c/busses/i2c-rcar.c
|
||||
* Driver for the Renesas RCar I2C unit
|
||||
*
|
||||
* Copyright (C) 2012 Renesas Solutions Corp.
|
||||
* Copyright (C) 2014 Wolfram Sang <wsa@sang-engineering.com>
|
||||
*
|
||||
* Copyright (C) 2012-14 Renesas Solutions Corp.
|
||||
* Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
*
|
||||
* This file is based on the drivers/i2c/busses/i2c-sh7760.c
|
||||
|
@ -12,16 +14,12 @@
|
|||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
|
@ -36,7 +34,6 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
/* register offsets */
|
||||
#define ICSCR 0x00 /* slave ctrl */
|
||||
|
@ -60,7 +57,7 @@
|
|||
#define FSB (1 << 1) /* force stop bit */
|
||||
#define ESG (1 << 0) /* en startbit gen */
|
||||
|
||||
/* ICMSR */
|
||||
/* ICMSR (also for ICMIE) */
|
||||
#define MNR (1 << 6) /* nack received */
|
||||
#define MAL (1 << 5) /* arbitration lost */
|
||||
#define MST (1 << 4) /* sent a stop */
|
||||
|
@ -69,32 +66,18 @@
|
|||
#define MDR (1 << 1)
|
||||
#define MAT (1 << 0) /* slave addr xfer done */
|
||||
|
||||
/* ICMIE */
|
||||
#define MNRE (1 << 6) /* nack irq en */
|
||||
#define MALE (1 << 5) /* arblos irq en */
|
||||
#define MSTE (1 << 4) /* stop irq en */
|
||||
#define MDEE (1 << 3)
|
||||
#define MDTE (1 << 2)
|
||||
#define MDRE (1 << 1)
|
||||
#define MATE (1 << 0) /* address sent irq en */
|
||||
|
||||
#define RCAR_BUS_PHASE_START (MDBS | MIE | ESG)
|
||||
#define RCAR_BUS_PHASE_DATA (MDBS | MIE)
|
||||
#define RCAR_BUS_PHASE_STOP (MDBS | MIE | FSB)
|
||||
|
||||
enum {
|
||||
RCAR_BUS_PHASE_ADDR,
|
||||
RCAR_BUS_PHASE_DATA,
|
||||
RCAR_BUS_PHASE_STOP,
|
||||
};
|
||||
#define RCAR_IRQ_SEND (MNR | MAL | MST | MAT | MDE)
|
||||
#define RCAR_IRQ_RECV (MNR | MAL | MST | MAT | MDR)
|
||||
#define RCAR_IRQ_STOP (MST)
|
||||
|
||||
enum {
|
||||
RCAR_IRQ_CLOSE,
|
||||
RCAR_IRQ_OPEN_FOR_SEND,
|
||||
RCAR_IRQ_OPEN_FOR_RECV,
|
||||
RCAR_IRQ_OPEN_FOR_STOP,
|
||||
};
|
||||
#define RCAR_IRQ_ACK_SEND (~(MAT | MDE))
|
||||
#define RCAR_IRQ_ACK_RECV (~(MAT | MDR))
|
||||
|
||||
/*
|
||||
* flags
|
||||
*/
|
||||
#define ID_LAST_MSG (1 << 0)
|
||||
#define ID_IOERROR (1 << 1)
|
||||
#define ID_DONE (1 << 2)
|
||||
|
@ -112,14 +95,12 @@ struct rcar_i2c_priv {
|
|||
struct i2c_msg *msg;
|
||||
struct clk *clk;
|
||||
|
||||
spinlock_t lock;
|
||||
wait_queue_head_t wait;
|
||||
|
||||
int pos;
|
||||
int irq;
|
||||
u32 icccr;
|
||||
u32 flags;
|
||||
enum rcar_i2c_type devtype;
|
||||
enum rcar_i2c_type devtype;
|
||||
};
|
||||
|
||||
#define rcar_i2c_priv_to_dev(p) ((p)->adap.dev.parent)
|
||||
|
@ -130,9 +111,7 @@ struct rcar_i2c_priv {
|
|||
|
||||
#define LOOP_TIMEOUT 1024
|
||||
|
||||
/*
|
||||
* basic functions
|
||||
*/
|
||||
|
||||
static void rcar_i2c_write(struct rcar_i2c_priv *priv, int reg, u32 val)
|
||||
{
|
||||
writel(val, priv->io + reg);
|
||||
|
@ -161,36 +140,6 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv)
|
|||
rcar_i2c_write(priv, ICMAR, 0);
|
||||
}
|
||||
|
||||
static void rcar_i2c_irq_mask(struct rcar_i2c_priv *priv, int open)
|
||||
{
|
||||
u32 val = MNRE | MALE | MSTE | MATE; /* default */
|
||||
|
||||
switch (open) {
|
||||
case RCAR_IRQ_OPEN_FOR_SEND:
|
||||
val |= MDEE; /* default + send */
|
||||
break;
|
||||
case RCAR_IRQ_OPEN_FOR_RECV:
|
||||
val |= MDRE; /* default + read */
|
||||
break;
|
||||
case RCAR_IRQ_OPEN_FOR_STOP:
|
||||
val = MSTE; /* stop irq only */
|
||||
break;
|
||||
case RCAR_IRQ_CLOSE:
|
||||
default:
|
||||
val = 0; /* all close */
|
||||
break;
|
||||
}
|
||||
rcar_i2c_write(priv, ICMIER, val);
|
||||
}
|
||||
|
||||
static void rcar_i2c_set_addr(struct rcar_i2c_priv *priv, u32 recv)
|
||||
{
|
||||
rcar_i2c_write(priv, ICMAR, (priv->msg->addr << 1) | recv);
|
||||
}
|
||||
|
||||
/*
|
||||
* bus control functions
|
||||
*/
|
||||
static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
|
||||
{
|
||||
int i;
|
||||
|
@ -205,24 +154,6 @@ static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
static void rcar_i2c_bus_phase(struct rcar_i2c_priv *priv, int phase)
|
||||
{
|
||||
switch (phase) {
|
||||
case RCAR_BUS_PHASE_ADDR:
|
||||
rcar_i2c_write(priv, ICMCR, MDBS | MIE | ESG);
|
||||
break;
|
||||
case RCAR_BUS_PHASE_DATA:
|
||||
rcar_i2c_write(priv, ICMCR, MDBS | MIE);
|
||||
break;
|
||||
case RCAR_BUS_PHASE_STOP:
|
||||
rcar_i2c_write(priv, ICMCR, MDBS | MIE | FSB);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* clock function
|
||||
*/
|
||||
static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
|
||||
u32 bus_speed,
|
||||
struct device *dev)
|
||||
|
@ -312,60 +243,18 @@ scgd_find:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void rcar_i2c_clock_start(struct rcar_i2c_priv *priv)
|
||||
static int rcar_i2c_prepare_msg(struct rcar_i2c_priv *priv)
|
||||
{
|
||||
rcar_i2c_write(priv, ICCCR, priv->icccr);
|
||||
}
|
||||
int read = !!rcar_i2c_is_recv(priv);
|
||||
|
||||
/*
|
||||
* status functions
|
||||
*/
|
||||
static u32 rcar_i2c_status_get(struct rcar_i2c_priv *priv)
|
||||
{
|
||||
return rcar_i2c_read(priv, ICMSR);
|
||||
}
|
||||
|
||||
#define rcar_i2c_status_clear(priv) rcar_i2c_status_bit_clear(priv, 0xffffffff)
|
||||
static void rcar_i2c_status_bit_clear(struct rcar_i2c_priv *priv, u32 bit)
|
||||
{
|
||||
rcar_i2c_write(priv, ICMSR, ~bit);
|
||||
}
|
||||
|
||||
/*
|
||||
* recv/send functions
|
||||
*/
|
||||
static int rcar_i2c_recv(struct rcar_i2c_priv *priv)
|
||||
{
|
||||
rcar_i2c_set_addr(priv, 1);
|
||||
rcar_i2c_status_clear(priv);
|
||||
rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_ADDR);
|
||||
rcar_i2c_irq_mask(priv, RCAR_IRQ_OPEN_FOR_RECV);
|
||||
rcar_i2c_write(priv, ICMAR, (priv->msg->addr << 1) | read);
|
||||
rcar_i2c_write(priv, ICMSR, 0);
|
||||
rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
|
||||
rcar_i2c_write(priv, ICMIER, read ? RCAR_IRQ_RECV : RCAR_IRQ_SEND);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rcar_i2c_send(struct rcar_i2c_priv *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* It should check bus status when send case
|
||||
*/
|
||||
ret = rcar_i2c_bus_barrier(priv);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
rcar_i2c_set_addr(priv, 0);
|
||||
rcar_i2c_status_clear(priv);
|
||||
rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_ADDR);
|
||||
rcar_i2c_irq_mask(priv, RCAR_IRQ_OPEN_FOR_SEND);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define rcar_i2c_send_restart(priv) rcar_i2c_status_bit_clear(priv, (MAT | MDE))
|
||||
#define rcar_i2c_recv_restart(priv) rcar_i2c_status_bit_clear(priv, (MAT | MDR))
|
||||
|
||||
/*
|
||||
* interrupt functions
|
||||
*/
|
||||
|
@ -386,7 +275,7 @@ static int rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr)
|
|||
* goto data phase.
|
||||
*/
|
||||
if (msr & MAT)
|
||||
rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_DATA);
|
||||
rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA);
|
||||
|
||||
if (priv->pos < msg->len) {
|
||||
/*
|
||||
|
@ -414,7 +303,7 @@ static int rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr)
|
|||
* prepare stop condition here.
|
||||
* ID_DONE will be set on STOP irq.
|
||||
*/
|
||||
rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_STOP);
|
||||
rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP);
|
||||
else
|
||||
/*
|
||||
* If current msg is _NOT_ last msg,
|
||||
|
@ -425,7 +314,7 @@ static int rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr)
|
|||
return ID_DONE;
|
||||
}
|
||||
|
||||
rcar_i2c_send_restart(priv);
|
||||
rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_SEND);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -462,11 +351,11 @@ static int rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
|
|||
* otherwise, go to DATA phase.
|
||||
*/
|
||||
if (priv->pos + 1 >= msg->len)
|
||||
rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_STOP);
|
||||
rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP);
|
||||
else
|
||||
rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_DATA);
|
||||
rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA);
|
||||
|
||||
rcar_i2c_recv_restart(priv);
|
||||
rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_RECV);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -474,53 +363,31 @@ static int rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
|
|||
static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
|
||||
{
|
||||
struct rcar_i2c_priv *priv = ptr;
|
||||
struct device *dev = rcar_i2c_priv_to_dev(priv);
|
||||
u32 msr;
|
||||
|
||||
/*-------------- spin lock -----------------*/
|
||||
spin_lock(&priv->lock);
|
||||
msr = rcar_i2c_read(priv, ICMSR);
|
||||
|
||||
msr = rcar_i2c_status_get(priv);
|
||||
|
||||
/*
|
||||
* Arbitration lost
|
||||
*/
|
||||
/* Arbitration lost */
|
||||
if (msr & MAL) {
|
||||
/*
|
||||
* CAUTION
|
||||
*
|
||||
* When arbitration lost, device become _slave_ mode.
|
||||
*/
|
||||
dev_dbg(dev, "Arbitration Lost\n");
|
||||
rcar_i2c_flags_set(priv, (ID_DONE | ID_ARBLOST));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop
|
||||
*/
|
||||
/* Stop */
|
||||
if (msr & MST) {
|
||||
dev_dbg(dev, "Stop\n");
|
||||
rcar_i2c_flags_set(priv, ID_DONE);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Nack
|
||||
*/
|
||||
/* Nack */
|
||||
if (msr & MNR) {
|
||||
dev_dbg(dev, "Nack\n");
|
||||
|
||||
/* go to stop phase */
|
||||
rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_STOP);
|
||||
rcar_i2c_irq_mask(priv, RCAR_IRQ_OPEN_FOR_STOP);
|
||||
rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP);
|
||||
rcar_i2c_write(priv, ICMIER, RCAR_IRQ_STOP);
|
||||
rcar_i2c_flags_set(priv, ID_NACK);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* recv/send
|
||||
*/
|
||||
if (rcar_i2c_is_recv(priv))
|
||||
rcar_i2c_flags_set(priv, rcar_i2c_irq_recv(priv, msr));
|
||||
else
|
||||
|
@ -528,14 +395,11 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
|
|||
|
||||
out:
|
||||
if (rcar_i2c_flags_has(priv, ID_DONE)) {
|
||||
rcar_i2c_irq_mask(priv, RCAR_IRQ_CLOSE);
|
||||
rcar_i2c_status_clear(priv);
|
||||
rcar_i2c_write(priv, ICMIER, 0);
|
||||
rcar_i2c_write(priv, ICMSR, 0);
|
||||
wake_up(&priv->wait);
|
||||
}
|
||||
|
||||
spin_unlock(&priv->lock);
|
||||
/*-------------- spin unlock -----------------*/
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -545,21 +409,18 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
|
|||
{
|
||||
struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
|
||||
struct device *dev = rcar_i2c_priv_to_dev(priv);
|
||||
unsigned long flags;
|
||||
int i, ret, timeout;
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
/*-------------- spin lock -----------------*/
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
rcar_i2c_init(priv);
|
||||
rcar_i2c_clock_start(priv);
|
||||
/* start clock */
|
||||
rcar_i2c_write(priv, ICCCR, priv->icccr);
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
/*-------------- spin unlock -----------------*/
|
||||
ret = rcar_i2c_bus_barrier(priv);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = -EINVAL;
|
||||
for (i = 0; i < num; i++) {
|
||||
/* This HW can't send STOP after address phase */
|
||||
if (msgs[i].len == 0) {
|
||||
|
@ -567,9 +428,6 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
|
|||
break;
|
||||
}
|
||||
|
||||
/*-------------- spin lock -----------------*/
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
/* init each data */
|
||||
priv->msg = &msgs[i];
|
||||
priv->pos = 0;
|
||||
|
@ -577,21 +435,11 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
|
|||
if (priv->msg == &msgs[num - 1])
|
||||
rcar_i2c_flags_set(priv, ID_LAST_MSG);
|
||||
|
||||
/* start send/recv */
|
||||
if (rcar_i2c_is_recv(priv))
|
||||
ret = rcar_i2c_recv(priv);
|
||||
else
|
||||
ret = rcar_i2c_send(priv);
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
/*-------------- spin unlock -----------------*/
|
||||
ret = rcar_i2c_prepare_msg(priv);
|
||||
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
/*
|
||||
* wait result
|
||||
*/
|
||||
timeout = wait_event_timeout(priv->wait,
|
||||
rcar_i2c_flags_has(priv, ID_DONE),
|
||||
5 * HZ);
|
||||
|
@ -600,9 +448,6 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
|
|||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* error handling
|
||||
*/
|
||||
if (rcar_i2c_flags_has(priv, ID_NACK)) {
|
||||
ret = -ENXIO;
|
||||
break;
|
||||
|
@ -620,7 +465,7 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
|
|||
|
||||
ret = i + 1; /* The number of transfer */
|
||||
}
|
||||
|
||||
out:
|
||||
pm_runtime_put(dev);
|
||||
|
||||
if (ret < 0 && ret != -ENXIO)
|
||||
|
@ -646,6 +491,9 @@ static const struct of_device_id rcar_i2c_dt_ids[] = {
|
|||
{ .compatible = "renesas,i2c-r8a7779", .data = (void *)I2C_RCAR_GEN1 },
|
||||
{ .compatible = "renesas,i2c-r8a7790", .data = (void *)I2C_RCAR_GEN2 },
|
||||
{ .compatible = "renesas,i2c-r8a7791", .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-r8a7794", .data = (void *)I2C_RCAR_GEN2 },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rcar_i2c_dt_ids);
|
||||
|
@ -658,13 +506,11 @@ static int rcar_i2c_probe(struct platform_device *pdev)
|
|||
struct resource *res;
|
||||
struct device *dev = &pdev->dev;
|
||||
u32 bus_speed;
|
||||
int ret;
|
||||
int irq, ret;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(struct rcar_i2c_priv), GFP_KERNEL);
|
||||
if (!priv) {
|
||||
dev_err(dev, "no mem for private data\n");
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
priv->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(priv->clk)) {
|
||||
|
@ -692,9 +538,8 @@ static int rcar_i2c_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(priv->io))
|
||||
return PTR_ERR(priv->io);
|
||||
|
||||
priv->irq = platform_get_irq(pdev, 0);
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
init_waitqueue_head(&priv->wait);
|
||||
spin_lock_init(&priv->lock);
|
||||
|
||||
adap = &priv->adap;
|
||||
adap->nr = pdev->id;
|
||||
|
@ -706,10 +551,10 @@ static int rcar_i2c_probe(struct platform_device *pdev)
|
|||
i2c_set_adapdata(adap, priv);
|
||||
strlcpy(adap->name, pdev->name, sizeof(adap->name));
|
||||
|
||||
ret = devm_request_irq(dev, priv->irq, rcar_i2c_irq, 0,
|
||||
ret = devm_request_irq(dev, irq, rcar_i2c_irq, 0,
|
||||
dev_name(dev), priv);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "cannot get irq %d\n", priv->irq);
|
||||
dev_err(dev, "cannot get irq %d\n", irq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -759,6 +604,6 @@ static struct platform_driver rcar_i2c_driver = {
|
|||
|
||||
module_platform_driver(rcar_i2c_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("Renesas R-Car I2C bus driver");
|
||||
MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
|
||||
|
|
|
@ -404,7 +404,7 @@ static int riic_i2c_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id riic_i2c_dt_ids[] = {
|
||||
static const struct of_device_id riic_i2c_dt_ids[] = {
|
||||
{ .compatible = "renesas,riic-rz" },
|
||||
{ /* Sentinel */ },
|
||||
};
|
||||
|
|
|
@ -1114,16 +1114,12 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
i2c = devm_kzalloc(&pdev->dev, sizeof(struct s3c24xx_i2c), GFP_KERNEL);
|
||||
if (!i2c) {
|
||||
dev_err(&pdev->dev, "no memory for state\n");
|
||||
if (!i2c)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
i2c->pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!i2c->pdata) {
|
||||
dev_err(&pdev->dev, "no memory for platform data\n");
|
||||
if (!i2c->pdata)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
i2c->quirks = s3c24xx_get_device_quirks(pdev);
|
||||
if (pdata)
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/i2c/i2c-sh_mobile.h>
|
||||
|
||||
/* Transmit operation: */
|
||||
|
@ -139,6 +140,10 @@ struct sh_mobile_i2c_data {
|
|||
bool send_stop;
|
||||
};
|
||||
|
||||
struct sh_mobile_dt_config {
|
||||
int clks_per_count;
|
||||
};
|
||||
|
||||
#define IIC_FLAG_HAS_ICIC67 (1 << 0)
|
||||
|
||||
#define STANDARD_MODE 100000
|
||||
|
@ -194,7 +199,7 @@ static void iic_set_clr(struct sh_mobile_i2c_data *pd, int offs,
|
|||
iic_wr(pd, offs, (iic_rd(pd, offs) | set) & ~clr);
|
||||
}
|
||||
|
||||
static u32 sh_mobile_i2c_iccl(unsigned long count_khz, u32 tLOW, u32 tf, int offset)
|
||||
static u32 sh_mobile_i2c_iccl(unsigned long count_khz, u32 tLOW, u32 tf)
|
||||
{
|
||||
/*
|
||||
* Conditional expression:
|
||||
|
@ -206,10 +211,10 @@ static u32 sh_mobile_i2c_iccl(unsigned long count_khz, u32 tLOW, u32 tf, int off
|
|||
* account the fall time of SCL signal (tf). Default tf value
|
||||
* should be 0.3 us, for safety.
|
||||
*/
|
||||
return (((count_khz * (tLOW + tf)) + 5000) / 10000) + offset;
|
||||
return (((count_khz * (tLOW + tf)) + 5000) / 10000);
|
||||
}
|
||||
|
||||
static u32 sh_mobile_i2c_icch(unsigned long count_khz, u32 tHIGH, u32 tf, int offset)
|
||||
static u32 sh_mobile_i2c_icch(unsigned long count_khz, u32 tHIGH, u32 tf)
|
||||
{
|
||||
/*
|
||||
* Conditional expression:
|
||||
|
@ -225,52 +230,58 @@ static u32 sh_mobile_i2c_icch(unsigned long count_khz, u32 tHIGH, u32 tf, int of
|
|||
* to take into account the fall time of SDA signal (tf) at START
|
||||
* condition, in order to meet both tHIGH and tHD;STA specs.
|
||||
*/
|
||||
return (((count_khz * (tHIGH + tf)) + 5000) / 10000) + offset;
|
||||
return (((count_khz * (tHIGH + tf)) + 5000) / 10000);
|
||||
}
|
||||
|
||||
static void sh_mobile_i2c_init(struct sh_mobile_i2c_data *pd)
|
||||
static int sh_mobile_i2c_init(struct sh_mobile_i2c_data *pd)
|
||||
{
|
||||
unsigned long i2c_clk_khz;
|
||||
u32 tHIGH, tLOW, tf;
|
||||
int offset;
|
||||
uint16_t max_val;
|
||||
|
||||
/* Get clock rate after clock is enabled */
|
||||
clk_prepare_enable(pd->clk);
|
||||
i2c_clk_khz = clk_get_rate(pd->clk) / 1000;
|
||||
clk_disable_unprepare(pd->clk);
|
||||
i2c_clk_khz /= pd->clks_per_count;
|
||||
|
||||
if (pd->bus_speed == STANDARD_MODE) {
|
||||
tLOW = 47; /* tLOW = 4.7 us */
|
||||
tHIGH = 40; /* tHD;STA = tHIGH = 4.0 us */
|
||||
tf = 3; /* tf = 0.3 us */
|
||||
offset = 0; /* No offset */
|
||||
} else if (pd->bus_speed == FAST_MODE) {
|
||||
tLOW = 13; /* tLOW = 1.3 us */
|
||||
tHIGH = 6; /* tHD;STA = tHIGH = 0.6 us */
|
||||
tf = 3; /* tf = 0.3 us */
|
||||
offset = 0; /* No offset */
|
||||
} else {
|
||||
dev_err(pd->dev, "unrecognized bus speed %lu Hz\n",
|
||||
pd->bus_speed);
|
||||
goto out;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pd->iccl = sh_mobile_i2c_iccl(i2c_clk_khz, tLOW, tf);
|
||||
pd->icch = sh_mobile_i2c_icch(i2c_clk_khz, tHIGH, tf);
|
||||
|
||||
max_val = pd->flags & IIC_FLAG_HAS_ICIC67 ? 0x1ff : 0xff;
|
||||
if (pd->iccl > max_val || pd->icch > max_val) {
|
||||
dev_err(pd->dev, "timing values out of range: L/H=0x%x/0x%x\n",
|
||||
pd->iccl, pd->icch);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pd->iccl = sh_mobile_i2c_iccl(i2c_clk_khz, tLOW, tf, offset);
|
||||
/* one more bit of ICCL in ICIC */
|
||||
if ((pd->iccl > 0xff) && (pd->flags & IIC_FLAG_HAS_ICIC67))
|
||||
if (pd->iccl & 0x100)
|
||||
pd->icic |= ICIC_ICCLB8;
|
||||
else
|
||||
pd->icic &= ~ICIC_ICCLB8;
|
||||
|
||||
pd->icch = sh_mobile_i2c_icch(i2c_clk_khz, tHIGH, tf, offset);
|
||||
/* one more bit of ICCH in ICIC */
|
||||
if ((pd->icch > 0xff) && (pd->flags & IIC_FLAG_HAS_ICIC67))
|
||||
if (pd->icch & 0x100)
|
||||
pd->icic |= ICIC_ICCHB8;
|
||||
else
|
||||
pd->icic &= ~ICIC_ICCHB8;
|
||||
|
||||
out:
|
||||
clk_disable_unprepare(pd->clk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void activate_ch(struct sh_mobile_i2c_data *pd)
|
||||
|
@ -316,7 +327,7 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
|
|||
|
||||
switch (op) {
|
||||
case OP_START: /* issue start and trigger DTE interrupt */
|
||||
iic_wr(pd, ICCR, 0x94);
|
||||
iic_wr(pd, ICCR, ICCR_ICE | ICCR_TRS | ICCR_BBSY);
|
||||
break;
|
||||
case OP_TX_FIRST: /* disable DTE interrupt and write data */
|
||||
iic_wr(pd, ICIC, ICIC_WAITE | ICIC_ALE | ICIC_TACKE);
|
||||
|
@ -327,10 +338,11 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
|
|||
break;
|
||||
case OP_TX_STOP: /* write data and issue a stop afterwards */
|
||||
iic_wr(pd, ICDR, data);
|
||||
iic_wr(pd, ICCR, pd->send_stop ? 0x90 : 0x94);
|
||||
iic_wr(pd, ICCR, pd->send_stop ? ICCR_ICE | ICCR_TRS
|
||||
: ICCR_ICE | ICCR_TRS | ICCR_BBSY);
|
||||
break;
|
||||
case OP_TX_TO_RX: /* select read mode */
|
||||
iic_wr(pd, ICCR, 0x81);
|
||||
iic_wr(pd, ICCR, ICCR_ICE | ICCR_SCP);
|
||||
break;
|
||||
case OP_RX: /* just read data */
|
||||
ret = iic_rd(pd, ICDR);
|
||||
|
@ -338,13 +350,13 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
|
|||
case OP_RX_STOP: /* enable DTE interrupt, issue stop */
|
||||
iic_wr(pd, ICIC,
|
||||
ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE);
|
||||
iic_wr(pd, ICCR, 0xc0);
|
||||
iic_wr(pd, ICCR, ICCR_ICE | ICCR_RACK);
|
||||
break;
|
||||
case OP_RX_STOP_DATA: /* enable DTE interrupt, read data, issue stop */
|
||||
iic_wr(pd, ICIC,
|
||||
ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE);
|
||||
ret = iic_rd(pd, ICDR);
|
||||
iic_wr(pd, ICCR, 0xc0);
|
||||
iic_wr(pd, ICCR, ICCR_ICE | ICCR_RACK);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -479,7 +491,7 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg,
|
|||
{
|
||||
if (usr_msg->len == 0 && (usr_msg->flags & I2C_M_RD)) {
|
||||
dev_err(pd->dev, "Unsupported zero length i2c read\n");
|
||||
return -EIO;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (do_init) {
|
||||
|
@ -514,17 +526,12 @@ static int poll_dte(struct sh_mobile_i2c_data *pd)
|
|||
break;
|
||||
|
||||
if (val & ICSR_TACK)
|
||||
return -EIO;
|
||||
return -ENXIO;
|
||||
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
if (!i) {
|
||||
dev_warn(pd->dev, "Timeout polling for DTE!\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return i ? 0 : -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int poll_busy(struct sh_mobile_i2c_data *pd)
|
||||
|
@ -542,20 +549,18 @@ static int poll_busy(struct sh_mobile_i2c_data *pd)
|
|||
*/
|
||||
if (!(val & ICSR_BUSY)) {
|
||||
/* handle missing acknowledge and arbitration lost */
|
||||
if ((val | pd->sr) & (ICSR_TACK | ICSR_AL))
|
||||
return -EIO;
|
||||
val |= pd->sr;
|
||||
if (val & ICSR_TACK)
|
||||
return -ENXIO;
|
||||
if (val & ICSR_AL)
|
||||
return -EAGAIN;
|
||||
break;
|
||||
}
|
||||
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
if (!i) {
|
||||
dev_err(pd->dev, "Polling timed out\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return i ? 0 : -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
|
||||
|
@ -617,42 +622,44 @@ static struct i2c_algorithm sh_mobile_i2c_algorithm = {
|
|||
.master_xfer = sh_mobile_i2c_xfer,
|
||||
};
|
||||
|
||||
static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)
|
||||
static const struct sh_mobile_dt_config default_dt_config = {
|
||||
.clks_per_count = 1,
|
||||
};
|
||||
|
||||
static const struct sh_mobile_dt_config rcar_gen2_dt_config = {
|
||||
.clks_per_count = 2,
|
||||
};
|
||||
|
||||
static const struct of_device_id sh_mobile_i2c_dt_ids[] = {
|
||||
{ .compatible = "renesas,rmobile-iic", .data = &default_dt_config },
|
||||
{ .compatible = "renesas,iic-r8a7790", .data = &rcar_gen2_dt_config },
|
||||
{ .compatible = "renesas,iic-r8a7791", .data = &rcar_gen2_dt_config },
|
||||
{ .compatible = "renesas,iic-r8a7792", .data = &rcar_gen2_dt_config },
|
||||
{ .compatible = "renesas,iic-r8a7793", .data = &rcar_gen2_dt_config },
|
||||
{ .compatible = "renesas,iic-r8a7794", .data = &rcar_gen2_dt_config },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sh_mobile_i2c_dt_ids);
|
||||
|
||||
static int sh_mobile_i2c_hook_irqs(struct platform_device *dev)
|
||||
{
|
||||
struct resource *res;
|
||||
int ret = -ENXIO;
|
||||
int n, k = 0;
|
||||
resource_size_t n;
|
||||
int k = 0, ret;
|
||||
|
||||
while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) {
|
||||
for (n = res->start; hook && n <= res->end; n++) {
|
||||
if (request_irq(n, sh_mobile_i2c_isr, 0,
|
||||
dev_name(&dev->dev), dev)) {
|
||||
for (n--; n >= res->start; n--)
|
||||
free_irq(n, dev);
|
||||
|
||||
goto rollback;
|
||||
for (n = res->start; n <= res->end; n++) {
|
||||
ret = devm_request_irq(&dev->dev, n, sh_mobile_i2c_isr,
|
||||
0, dev_name(&dev->dev), dev);
|
||||
if (ret) {
|
||||
dev_err(&dev->dev, "cannot request IRQ %pa\n", &n);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
k++;
|
||||
}
|
||||
|
||||
if (hook)
|
||||
return k > 0 ? 0 : -ENOENT;
|
||||
|
||||
ret = 0;
|
||||
|
||||
rollback:
|
||||
k--;
|
||||
|
||||
while (k >= 0) {
|
||||
res = platform_get_resource(dev, IORESOURCE_IRQ, k);
|
||||
for (n = res->start; n <= res->end; n++)
|
||||
free_irq(n, dev);
|
||||
|
||||
k--;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return k > 0 ? 0 : -ENOENT;
|
||||
}
|
||||
|
||||
static int sh_mobile_i2c_probe(struct platform_device *dev)
|
||||
|
@ -661,62 +668,64 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
|
|||
struct sh_mobile_i2c_data *pd;
|
||||
struct i2c_adapter *adap;
|
||||
struct resource *res;
|
||||
int size;
|
||||
int ret;
|
||||
u32 bus_speed;
|
||||
|
||||
pd = kzalloc(sizeof(struct sh_mobile_i2c_data), GFP_KERNEL);
|
||||
if (pd == NULL) {
|
||||
dev_err(&dev->dev, "cannot allocate private data\n");
|
||||
pd = devm_kzalloc(&dev->dev, sizeof(struct sh_mobile_i2c_data), GFP_KERNEL);
|
||||
if (!pd)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pd->clk = clk_get(&dev->dev, NULL);
|
||||
pd->clk = devm_clk_get(&dev->dev, NULL);
|
||||
if (IS_ERR(pd->clk)) {
|
||||
dev_err(&dev->dev, "cannot get clock\n");
|
||||
ret = PTR_ERR(pd->clk);
|
||||
goto err;
|
||||
return PTR_ERR(pd->clk);
|
||||
}
|
||||
|
||||
ret = sh_mobile_i2c_hook_irqs(dev, 1);
|
||||
if (ret) {
|
||||
dev_err(&dev->dev, "cannot request IRQ\n");
|
||||
goto err_clk;
|
||||
}
|
||||
ret = sh_mobile_i2c_hook_irqs(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pd->dev = &dev->dev;
|
||||
platform_set_drvdata(dev, pd);
|
||||
|
||||
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
|
||||
if (res == NULL) {
|
||||
dev_err(&dev->dev, "cannot find IO resource\n");
|
||||
ret = -ENOENT;
|
||||
goto err_irq;
|
||||
}
|
||||
|
||||
size = resource_size(res);
|
||||
|
||||
pd->reg = ioremap(res->start, size);
|
||||
if (pd->reg == NULL) {
|
||||
dev_err(&dev->dev, "cannot map IO\n");
|
||||
ret = -ENXIO;
|
||||
goto err_irq;
|
||||
}
|
||||
pd->reg = devm_ioremap_resource(&dev->dev, res);
|
||||
if (IS_ERR(pd->reg))
|
||||
return PTR_ERR(pd->reg);
|
||||
|
||||
/* Use platform data bus speed or STANDARD_MODE */
|
||||
pd->bus_speed = STANDARD_MODE;
|
||||
if (pdata && pdata->bus_speed)
|
||||
pd->bus_speed = pdata->bus_speed;
|
||||
ret = of_property_read_u32(dev->dev.of_node, "clock-frequency", &bus_speed);
|
||||
pd->bus_speed = ret ? STANDARD_MODE : bus_speed;
|
||||
|
||||
pd->clks_per_count = 1;
|
||||
if (pdata && pdata->clks_per_count)
|
||||
pd->clks_per_count = pdata->clks_per_count;
|
||||
|
||||
if (dev->dev.of_node) {
|
||||
const struct of_device_id *match;
|
||||
|
||||
match = of_match_device(sh_mobile_i2c_dt_ids, &dev->dev);
|
||||
if (match) {
|
||||
const struct sh_mobile_dt_config *config;
|
||||
|
||||
config = match->data;
|
||||
pd->clks_per_count = config->clks_per_count;
|
||||
}
|
||||
} else {
|
||||
if (pdata && pdata->bus_speed)
|
||||
pd->bus_speed = pdata->bus_speed;
|
||||
if (pdata && pdata->clks_per_count)
|
||||
pd->clks_per_count = pdata->clks_per_count;
|
||||
}
|
||||
|
||||
/* The IIC blocks on SH-Mobile ARM processors
|
||||
* come with two new bits in ICIC.
|
||||
*/
|
||||
if (size > 0x17)
|
||||
if (resource_size(res) > 0x17)
|
||||
pd->flags |= IIC_FLAG_HAS_ICIC67;
|
||||
|
||||
sh_mobile_i2c_init(pd);
|
||||
ret = sh_mobile_i2c_init(pd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Enable Runtime PM for this device.
|
||||
*
|
||||
|
@ -750,24 +759,14 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
|
|||
ret = i2c_add_numbered_adapter(adap);
|
||||
if (ret < 0) {
|
||||
dev_err(&dev->dev, "cannot add numbered adapter\n");
|
||||
goto err_all;
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_info(&dev->dev,
|
||||
"I2C adapter %d with bus speed %lu Hz (L/H=%x/%x)\n",
|
||||
"I2C adapter %d with bus speed %lu Hz (L/H=0x%x/0x%x)\n",
|
||||
adap->nr, pd->bus_speed, pd->iccl, pd->icch);
|
||||
|
||||
return 0;
|
||||
|
||||
err_all:
|
||||
iounmap(pd->reg);
|
||||
err_irq:
|
||||
sh_mobile_i2c_hook_irqs(dev, 0);
|
||||
err_clk:
|
||||
clk_put(pd->clk);
|
||||
err:
|
||||
kfree(pd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sh_mobile_i2c_remove(struct platform_device *dev)
|
||||
|
@ -775,11 +774,7 @@ static int sh_mobile_i2c_remove(struct platform_device *dev)
|
|||
struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
|
||||
|
||||
i2c_del_adapter(&pd->adap);
|
||||
iounmap(pd->reg);
|
||||
sh_mobile_i2c_hook_irqs(dev, 0);
|
||||
clk_put(pd->clk);
|
||||
pm_runtime_disable(&dev->dev);
|
||||
kfree(pd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -800,12 +795,6 @@ static const struct dev_pm_ops sh_mobile_i2c_dev_pm_ops = {
|
|||
.runtime_resume = sh_mobile_i2c_runtime_nop,
|
||||
};
|
||||
|
||||
static const struct of_device_id sh_mobile_i2c_dt_ids[] = {
|
||||
{ .compatible = "renesas,rmobile-iic", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sh_mobile_i2c_dt_ids);
|
||||
|
||||
static struct platform_driver sh_mobile_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "i2c-sh_mobile",
|
||||
|
|
|
@ -77,10 +77,8 @@ static int simtec_i2c_probe(struct platform_device *dev)
|
|||
int ret;
|
||||
|
||||
pd = kzalloc(sizeof(struct simtec_i2c_data), GFP_KERNEL);
|
||||
if (pd == NULL) {
|
||||
dev_err(&dev->dev, "cannot allocate private data\n");
|
||||
if (pd == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
platform_set_drvdata(dev, pd);
|
||||
|
||||
|
|
|
@ -307,7 +307,6 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev)
|
|||
|
||||
siic = devm_kzalloc(&pdev->dev, sizeof(*siic), GFP_KERNEL);
|
||||
if (!siic) {
|
||||
dev_err(&pdev->dev, "Can't allocate driver data\n");
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -847,7 +847,7 @@ static int st_i2c_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id st_i2c_match[] = {
|
||||
static const struct of_device_id st_i2c_match[] = {
|
||||
{ .compatible = "st,comms-ssc-i2c", },
|
||||
{ .compatible = "st,comms-ssc4-i2c", },
|
||||
{},
|
||||
|
|
|
@ -868,10 +868,8 @@ static int stu300_probe(struct platform_device *pdev)
|
|||
int ret = 0;
|
||||
|
||||
dev = devm_kzalloc(&pdev->dev, sizeof(struct stu300_dev), GFP_KERNEL);
|
||||
if (!dev) {
|
||||
dev_err(&pdev->dev, "could not allocate device struct\n");
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
bus_nr = pdev->id;
|
||||
dev->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
|
|
|
@ -732,10 +732,8 @@ static int tegra_i2c_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
|
||||
if (!i2c_dev) {
|
||||
dev_err(&pdev->dev, "Could not allocate struct tegra_i2c_dev");
|
||||
if (!i2c_dev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
i2c_dev->base = base;
|
||||
i2c_dev->div_clk = div_clk;
|
||||
|
|
|
@ -379,10 +379,8 @@ static int wmt_i2c_probe(struct platform_device *pdev)
|
|||
u32 clk_rate;
|
||||
|
||||
i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
|
||||
if (!i2c_dev) {
|
||||
dev_err(&pdev->dev, "device memory allocation failed\n");
|
||||
if (!i2c_dev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
i2c_dev->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
|
@ -454,7 +452,7 @@ static int wmt_i2c_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id wmt_i2c_dt_ids[] = {
|
||||
static const struct of_device_id wmt_i2c_dt_ids[] = {
|
||||
{ .compatible = "wm,wm8505-i2c" },
|
||||
{ /* Sentinel */ },
|
||||
};
|
||||
|
|
|
@ -431,10 +431,8 @@ static struct scx200_acb_iface *scx200_create_iface(const char *text,
|
|||
struct i2c_adapter *adapter;
|
||||
|
||||
iface = kzalloc(sizeof(*iface), GFP_KERNEL);
|
||||
if (!iface) {
|
||||
pr_err("can't allocate memory\n");
|
||||
if (!iface)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
adapter = &iface->adapter;
|
||||
i2c_set_adapdata(adapter, iface);
|
||||
|
|
|
@ -36,12 +36,11 @@
|
|||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-mux.h>
|
||||
#include <linux/i2c/pca954x.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define PCA954X_MAX_NCHANS 8
|
||||
|
@ -186,7 +185,7 @@ static int pca954x_probe(struct i2c_client *client,
|
|||
{
|
||||
struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent);
|
||||
struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
struct device_node *np = client->dev.of_node;
|
||||
struct gpio_desc *gpio;
|
||||
int num, force, class;
|
||||
struct pca954x *data;
|
||||
int ret;
|
||||
|
@ -200,21 +199,10 @@ static int pca954x_probe(struct i2c_client *client,
|
|||
|
||||
i2c_set_clientdata(client, data);
|
||||
|
||||
if (IS_ENABLED(CONFIG_OF) && np) {
|
||||
enum of_gpio_flags flags;
|
||||
int gpio;
|
||||
|
||||
/* Get the mux out of reset if a reset GPIO is specified. */
|
||||
gpio = of_get_named_gpio_flags(np, "reset-gpio", 0, &flags);
|
||||
if (gpio_is_valid(gpio)) {
|
||||
ret = devm_gpio_request_one(&client->dev, gpio,
|
||||
flags & OF_GPIO_ACTIVE_LOW ?
|
||||
GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
|
||||
"pca954x reset");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
/* Get the mux out of reset if a reset GPIO is specified. */
|
||||
gpio = devm_gpiod_get(&client->dev, "reset");
|
||||
if (!IS_ERR(gpio))
|
||||
gpiod_direction_output(gpio, 0);
|
||||
|
||||
/* Write the mux register at addr to verify
|
||||
* that the mux is in fact present. This also
|
||||
|
|
Загрузка…
Ссылка в новой задаче