Commit 0d5b1bd3 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull i2c updates from Wolfram Sang:

 -I2C core now reports proper OF style module alias. I'd like to repeat
  the note from the commit msg here (Thanks, Javier!):

      NOTE: This patch may break out-of-tree drivers that were relying
            on this behavior, and only had an I2C device ID table even
            when the device was registered via OF.

            There are no remaining drivers in mainline that do this, but
            out-of-tree drivers have to be fixed and define a proper OF
            device ID table to have module auto-loading working.

 - new driver for the SynQuacer I2C controller

 - major refactoring of the QUP driver

 - the piix4 driver now uses request_muxed_region which should fix a
   long standing resource conflict with the sp5100_tco watchdog

 - a bunch of small core & driver improvements

* 'i2c/for-4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (53 commits)
  i2c: add support for Socionext SynQuacer I2C controller
  dt-bindings: i2c: add binding for Socionext SynQuacer I2C
  i2c: Update i2c_trace_msg static key to modern api
  i2c: fix parameter of trace_i2c_result
  i2c: imx: avoid taking clk_prepare mutex in PM callbacks
  i2c: imx: use clk notifier for rate changes
  i2c: make i2c_check_addr_validity() static
  i2c: rcar: fix mask value of prohibited bit
  dt-bindings: i2c: document R8A77965 bindings
  i2c: pca-platform: drop gpio from platform data
  i2c: pca-platform: use device_property_read_u32
  i2c: pca-platform: unconditionally use devm_gpiod_get_optional
  sh: sh7785lcr: add GPIO lookup table for i2c controller reset
  i2c: qup: reorganization of driver code to remove polling for qup v2
  i2c: qup: reorganization of driver code to remove polling for qup v1
  i2c: qup: send NACK for last read sub transfers
  i2c: qup: fix buffer overflow for multiple msg of maximum xfer len
  i2c: qup: change completion timeout according to transfer length
  i2c: qup: use the complete transfer length to choose DMA mode
  i2c: qup: proper error handling for i2c error in BAM mode
  ...
parents 49a695ba 0d676a6c
...@@ -41,12 +41,16 @@ Required properties: ...@@ -41,12 +41,16 @@ Required properties:
"nxp", "nxp",
"ramtron", "ramtron",
"renesas", "renesas",
"rohm",
"st", "st",
Some vendors use different model names for chips which are just Some vendors use different model names for chips which are just
variants of the above. Known such exceptions are listed below: variants of the above. Known such exceptions are listed below:
"nxp,se97b" - the fallback is "atmel,24c02",
"renesas,r1ex24002" - the fallback is "atmel,24c02" "renesas,r1ex24002" - the fallback is "atmel,24c02"
"renesas,r1ex24128" - the fallback is "atmel,24c128"
"rohm,br24t01" - the fallback is "atmel,24c01"
- reg: The I2C address of the EEPROM. - reg: The I2C address of the EEPROM.
......
...@@ -13,7 +13,9 @@ Required properties: ...@@ -13,7 +13,9 @@ Required properties:
"renesas,i2c-r8a7794" if the device is a part of a R8A7794 SoC. "renesas,i2c-r8a7794" if the device is a part of a R8A7794 SoC.
"renesas,i2c-r8a7795" if the device is a part of a R8A7795 SoC. "renesas,i2c-r8a7795" if the device is a part of a R8A7795 SoC.
"renesas,i2c-r8a7796" if the device is a part of a R8A7796 SoC. "renesas,i2c-r8a7796" if the device is a part of a R8A7796 SoC.
"renesas,i2c-r8a77965" if the device is a part of a R8A77965 SoC.
"renesas,i2c-r8a77970" if the device is a part of a R8A77970 SoC. "renesas,i2c-r8a77970" if the device is a part of a R8A77970 SoC.
"renesas,i2c-r8a77995" if the device is a part of a R8A77995 SoC.
"renesas,rcar-gen1-i2c" for a generic R-Car Gen1 compatible device. "renesas,rcar-gen1-i2c" for a generic R-Car Gen1 compatible device.
"renesas,rcar-gen2-i2c" for a generic R-Car Gen2 or RZ/G1 compatible "renesas,rcar-gen2-i2c" for a generic R-Car Gen2 or RZ/G1 compatible
device. device.
......
...@@ -13,6 +13,7 @@ Required properties: ...@@ -13,6 +13,7 @@ Required properties:
- "renesas,iic-r8a7794" (R-Car E2) - "renesas,iic-r8a7794" (R-Car E2)
- "renesas,iic-r8a7795" (R-Car H3) - "renesas,iic-r8a7795" (R-Car H3)
- "renesas,iic-r8a7796" (R-Car M3-W) - "renesas,iic-r8a7796" (R-Car M3-W)
- "renesas,iic-r8a77965" (R-Car M3-N)
- "renesas,iic-sh73a0" (SH-Mobile AG5) - "renesas,iic-sh73a0" (SH-Mobile AG5)
- "renesas,rcar-gen2-iic" (generic R-Car Gen2 or RZ/G1 - "renesas,rcar-gen2-iic" (generic R-Car Gen2 or RZ/G1
compatible device) compatible device)
......
Socionext SynQuacer I2C
Required properties:
- compatible : Must be "socionext,synquacer-i2c"
- reg : Offset and length of the register set for the device
- interrupts : A single interrupt specifier
- #address-cells : Must be <1>;
- #size-cells : Must be <0>;
- clock-names : Must contain "pclk".
- clocks : Must contain an entry for each name in clock-names.
(See the common clock bindings.)
Optional properties:
- clock-frequency : Desired I2C bus clock frequency in Hz. As only Normal and
Fast modes are supported, possible values are 100000 and
400000.
Example :
i2c@51210000 {
compatible = "socionext,synquacer-i2c";
reg = <0x51210000 0x1000>;
interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
clock-names = "pclk";
clocks = <&clk_i2c>;
clock-frequency = <400000>;
};
...@@ -6559,7 +6559,7 @@ F: drivers/i2c/muxes/ ...@@ -6559,7 +6559,7 @@ F: drivers/i2c/muxes/
F: include/linux/i2c-mux.h F: include/linux/i2c-mux.h
I2C MV64XXX MARVELL AND ALLWINNER DRIVER I2C MV64XXX MARVELL AND ALLWINNER DRIVER
M: Gregory CLEMENT <gregory.clement@free-electrons.com> M: Gregory CLEMENT <gregory.clement@bootlin.com>
L: linux-i2c@vger.kernel.org L: linux-i2c@vger.kernel.org
S: Maintained S: Maintained
F: drivers/i2c/busses/i2c-mv64xxx.c F: drivers/i2c/busses/i2c-mv64xxx.c
...@@ -12902,6 +12902,13 @@ F: include/media/soc* ...@@ -12902,6 +12902,13 @@ F: include/media/soc*
F: drivers/media/i2c/soc_camera/ F: drivers/media/i2c/soc_camera/
F: drivers/media/platform/soc_camera/ F: drivers/media/platform/soc_camera/
SOCIONEXT SYNQUACER I2C DRIVER
M: Ard Biesheuvel <ard.biesheuvel@linaro.org>
L: linux-i2c@vger.kernel.org
S: Maintained
F: drivers/i2c/busses/i2c-synquacer.c
F: Documentation/devicetree/bindings/i2c/i2c-synquacer.txt
SOCIONEXT UNIPHIER SOUND DRIVER SOCIONEXT UNIPHIER SOUND DRIVER
M: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com> M: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers) L: alsa-devel@alsa-project.org (moderated for non-subscribers)
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/gpio/machine.h>
#include <mach/sh7785lcr.h> #include <mach/sh7785lcr.h>
#include <cpu/sh7785.h> #include <cpu/sh7785.h>
#include <asm/heartbeat.h> #include <asm/heartbeat.h>
...@@ -243,8 +244,15 @@ static struct resource i2c_resources[] = { ...@@ -243,8 +244,15 @@ static struct resource i2c_resources[] = {
}, },
}; };
static struct gpiod_lookup_table i2c_gpio_table = {
.dev_id = "i2c.0",
.table = {
GPIO_LOOKUP("pfc-sh7757", 0, "reset-gpios", GPIO_ACTIVE_LOW),
{ },
},
};
static struct i2c_pca9564_pf_platform_data i2c_platform_data = { static struct i2c_pca9564_pf_platform_data i2c_platform_data = {
.gpio = 0,
.i2c_clock_speed = I2C_PCA_CON_330kHz, .i2c_clock_speed = I2C_PCA_CON_330kHz,
.timeout = HZ, .timeout = HZ,
}; };
...@@ -283,6 +291,7 @@ static int __init sh7785lcr_devices_setup(void) ...@@ -283,6 +291,7 @@ static int __init sh7785lcr_devices_setup(void)
i2c_device.num_resources = ARRAY_SIZE(i2c_proto_resources); i2c_device.num_resources = ARRAY_SIZE(i2c_proto_resources);
} }
gpiod_add_lookup_table(&i2c_gpio_table);
return platform_add_devices(sh7785lcr_devices, return platform_add_devices(sh7785lcr_devices,
ARRAY_SIZE(sh7785lcr_devices)); ARRAY_SIZE(sh7785lcr_devices));
} }
......
...@@ -979,6 +979,16 @@ config I2C_SUN6I_P2WI ...@@ -979,6 +979,16 @@ config I2C_SUN6I_P2WI
This interface is used to connect to specific PMIC devices (like the This interface is used to connect to specific PMIC devices (like the
AXP221). AXP221).
config I2C_SYNQUACER
tristate "Socionext SynQuacer I2C controller"
depends on ARCH_SYNQUACER || COMPILE_TEST
help
Say Y here to include support for the I2C controller used in some
Fujitsu and Socionext SoCs.
This driver can also be built as a module. If so, the module
will be called i2c-synquacer.
config I2C_TEGRA config I2C_TEGRA
tristate "NVIDIA Tegra internal I2C controller" tristate "NVIDIA Tegra internal I2C controller"
depends on ARCH_TEGRA depends on ARCH_TEGRA
......
...@@ -97,6 +97,7 @@ obj-$(CONFIG_I2C_STM32F4) += i2c-stm32f4.o ...@@ -97,6 +97,7 @@ obj-$(CONFIG_I2C_STM32F4) += i2c-stm32f4.o
obj-$(CONFIG_I2C_STM32F7) += i2c-stm32f7.o obj-$(CONFIG_I2C_STM32F7) += i2c-stm32f7.o
obj-$(CONFIG_I2C_STU300) += i2c-stu300.o obj-$(CONFIG_I2C_STU300) += i2c-stu300.o
obj-$(CONFIG_I2C_SUN6I_P2WI) += i2c-sun6i-p2wi.o obj-$(CONFIG_I2C_SUN6I_P2WI) += i2c-sun6i-p2wi.o
obj-$(CONFIG_I2C_SYNQUACER) += i2c-synquacer.o
obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o
obj-$(CONFIG_I2C_TEGRA_BPMP) += i2c-tegra-bpmp.o obj-$(CONFIG_I2C_TEGRA_BPMP) += i2c-tegra-bpmp.o
obj-$(CONFIG_I2C_UNIPHIER) += i2c-uniphier.o obj-$(CONFIG_I2C_UNIPHIER) += i2c-uniphier.o
......
...@@ -163,7 +163,7 @@ static int i2c_dw_init_master(struct dw_i2c_dev *dev) ...@@ -163,7 +163,7 @@ static int i2c_dw_init_master(struct dw_i2c_dev *dev)
if (!(dev->sda_hold_time & DW_IC_SDA_HOLD_RX_MASK)) if (!(dev->sda_hold_time & DW_IC_SDA_HOLD_RX_MASK))
dev->sda_hold_time |= 1 << DW_IC_SDA_HOLD_RX_SHIFT; dev->sda_hold_time |= 1 << DW_IC_SDA_HOLD_RX_SHIFT;
dw_writel(dev, dev->sda_hold_time, DW_IC_SDA_HOLD); dw_writel(dev, dev->sda_hold_time, DW_IC_SDA_HOLD);
} else { } else if (dev->sda_hold_time) {
dev_warn(dev->dev, dev_warn(dev->dev,
"Hardware too old to adjust SDA hold time.\n"); "Hardware too old to adjust SDA hold time.\n");
} }
......
...@@ -128,6 +128,10 @@ ...@@ -128,6 +128,10 @@
#define HSI2C_TIMEOUT_EN (1u << 31) #define HSI2C_TIMEOUT_EN (1u << 31)
#define HSI2C_TIMEOUT_MASK 0xff #define HSI2C_TIMEOUT_MASK 0xff
/* I2C_MANUAL_CMD register bits */
#define HSI2C_CMD_READ_DATA (1u << 4)
#define HSI2C_CMD_SEND_STOP (1u << 2)
/* I2C_TRANS_STATUS register bits */ /* I2C_TRANS_STATUS register bits */
#define HSI2C_MASTER_BUSY (1u << 17) #define HSI2C_MASTER_BUSY (1u << 17)
#define HSI2C_SLAVE_BUSY (1u << 16) #define HSI2C_SLAVE_BUSY (1u << 16)
...@@ -441,12 +445,6 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id) ...@@ -441,12 +445,6 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)
i2c->state = -ETIMEDOUT; i2c->state = -ETIMEDOUT;
goto stop; goto stop;
} }
trans_status = readl(i2c->regs + HSI2C_TRANS_STATUS);
if ((trans_status & HSI2C_MASTER_ST_MASK) == HSI2C_MASTER_ST_LOSE) {
i2c->state = -EAGAIN;
goto stop;
}
} else if (int_status & HSI2C_INT_I2C) { } else if (int_status & HSI2C_INT_I2C) {
trans_status = readl(i2c->regs + HSI2C_TRANS_STATUS); trans_status = readl(i2c->regs + HSI2C_TRANS_STATUS);
if (trans_status & HSI2C_NO_DEV_ACK) { if (trans_status & HSI2C_NO_DEV_ACK) {
...@@ -544,6 +542,57 @@ static int exynos5_i2c_wait_bus_idle(struct exynos5_i2c *i2c) ...@@ -544,6 +542,57 @@ static int exynos5_i2c_wait_bus_idle(struct exynos5_i2c *i2c)
return -EBUSY; return -EBUSY;
} }
static void exynos5_i2c_bus_recover(struct exynos5_i2c *i2c)
{
u32 val;
val = readl(i2c->regs + HSI2C_CTL) | HSI2C_RXCHON;
writel(val, i2c->regs + HSI2C_CTL);
val = readl(i2c->regs + HSI2C_CONF) & ~HSI2C_AUTO_MODE;
writel(val, i2c->regs + HSI2C_CONF);
/*
* Specification says master should send nine clock pulses. It can be
* emulated by sending manual read command (nine pulses for read eight
* bits + one pulse for NACK).
*/
writel(HSI2C_CMD_READ_DATA, i2c->regs + HSI2C_MANUAL_CMD);
exynos5_i2c_wait_bus_idle(i2c);
writel(HSI2C_CMD_SEND_STOP, i2c->regs + HSI2C_MANUAL_CMD);
exynos5_i2c_wait_bus_idle(i2c);
val = readl(i2c->regs + HSI2C_CTL) & ~HSI2C_RXCHON;
writel(val, i2c->regs + HSI2C_CTL);
val = readl(i2c->regs + HSI2C_CONF) | HSI2C_AUTO_MODE;
writel(val, i2c->regs + HSI2C_CONF);
}
static void exynos5_i2c_bus_check(struct exynos5_i2c *i2c)
{
unsigned long timeout;
if (i2c->variant->hw != HSI2C_EXYNOS7)
return;
/*
* HSI2C_MASTER_ST_LOSE state in EXYNOS7 variant before transaction
* indicates that bus is stuck (SDA is low). In such case bus recovery
* can be performed.
*/
timeout = jiffies + msecs_to_jiffies(100);
for (;;) {
u32 st = readl(i2c->regs + HSI2C_TRANS_STATUS);
if ((st & HSI2C_MASTER_ST_MASK) != HSI2C_MASTER_ST_LOSE)
return;
if (time_is_before_jiffies(timeout))
return;
exynos5_i2c_bus_recover(i2c);
}
}
/* /*
* exynos5_i2c_message_start: Configures the bus and starts the xfer * exynos5_i2c_message_start: Configures the bus and starts the xfer
* i2c: struct exynos5_i2c pointer for the current bus * i2c: struct exynos5_i2c pointer for the current bus
...@@ -598,6 +647,8 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop) ...@@ -598,6 +647,8 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
writel(fifo_ctl, i2c->regs + HSI2C_FIFO_CTL); writel(fifo_ctl, i2c->regs + HSI2C_FIFO_CTL);
writel(i2c_ctl, i2c->regs + HSI2C_CTL); writel(i2c_ctl, i2c->regs + HSI2C_CTL);
exynos5_i2c_bus_check(i2c);
/* /*
* Enable interrupts before starting the transfer so that we don't * Enable interrupts before starting the transfer so that we don't
* miss any INT_I2C interrupts. * miss any INT_I2C interrupts.
......
...@@ -194,6 +194,7 @@ struct imx_i2c_dma { ...@@ -194,6 +194,7 @@ struct imx_i2c_dma {
struct imx_i2c_struct { struct imx_i2c_struct {
struct i2c_adapter adapter; struct i2c_adapter adapter;
struct clk *clk; struct clk *clk;
struct notifier_block clk_change_nb;
void __iomem *base; void __iomem *base;
wait_queue_head_t queue; wait_queue_head_t queue;
unsigned long i2csr; unsigned long i2csr;
...@@ -467,15 +468,14 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx) ...@@ -467,15 +468,14 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx)
return 0; return 0;
} }
static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx) static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
unsigned int i2c_clk_rate)
{ {
struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div; struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div;
unsigned int i2c_clk_rate;
unsigned int div; unsigned int div;
int i; int i;
/* Divider value calculation */ /* Divider value calculation */
i2c_clk_rate = clk_get_rate(i2c_imx->clk);
if (i2c_imx->cur_clk == i2c_clk_rate) if (i2c_imx->cur_clk == i2c_clk_rate)
return; return;
...@@ -510,6 +510,20 @@ static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx) ...@@ -510,6 +510,20 @@ static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx)
#endif #endif
} }
static int i2c_imx_clk_notifier_call(struct notifier_block *nb,
unsigned long action, void *data)
{
struct clk_notifier_data *ndata = data;
struct imx_i2c_struct *i2c_imx = container_of(&ndata->clk,
struct imx_i2c_struct,
clk);
if (action & POST_RATE_CHANGE)
i2c_imx_set_clk(i2c_imx, ndata->new_rate);
return NOTIFY_OK;
}
static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
{ {
unsigned int temp = 0; unsigned int temp = 0;
...@@ -517,8 +531,6 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) ...@@ -517,8 +531,6 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
i2c_imx_set_clk(i2c_imx);
imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR); imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR);
/* Enable I2C controller */ /* Enable I2C controller */
imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR); imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);
...@@ -1131,6 +1143,9 @@ static int i2c_imx_probe(struct platform_device *pdev) ...@@ -1131,6 +1143,9 @@ static int i2c_imx_probe(struct platform_device *pdev)
"clock-frequency", &i2c_imx->bitrate); "clock-frequency", &i2c_imx->bitrate);
if (ret < 0 && pdata && pdata->bitrate) if (ret < 0 && pdata && pdata->bitrate)
i2c_imx->bitrate = pdata->bitrate; i2c_imx->bitrate = pdata->bitrate;
i2c_imx->clk_change_nb.notifier_call = i2c_imx_clk_notifier_call;
clk_notifier_register(i2c_imx->clk, &i2c_imx->clk_change_nb);
i2c_imx_set_clk(i2c_imx, clk_get_rate(i2c_imx->clk));
/* Set up chip registers to defaults */ /* Set up chip registers to defaults */
imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN, imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
...@@ -1141,12 +1156,12 @@ static int i2c_imx_probe(struct platform_device *pdev) ...@@ -1141,12 +1156,12 @@ static int i2c_imx_probe(struct platform_device *pdev)
ret = i2c_imx_init_recovery_info(i2c_imx, pdev); ret = i2c_imx_init_recovery_info(i2c_imx, pdev);
/* Give it another chance if pinctrl used is not ready yet */ /* Give it another chance if pinctrl used is not ready yet */
if (ret == -EPROBE_DEFER) if (ret == -EPROBE_DEFER)
goto rpm_disable; goto clk_notifier_unregister;
/* Add I2C adapter */ /* Add I2C adapter */
ret = i2c_add_numbered_adapter(&i2c_imx->adapter); ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
if (ret < 0) if (ret < 0)
goto rpm_disable; goto clk_notifier_unregister;
pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev); pm_runtime_put_autosuspend(&pdev->dev);
...@@ -1162,6 +1177,8 @@ static int i2c_imx_probe(struct platform_device *pdev) ...@@ -1162,6 +1177,8 @@ static int i2c_imx_probe(struct platform_device *pdev)
return 0; /* Return OK */ return 0; /* Return OK */
clk_notifier_unregister:
clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb);
rpm_disable: rpm_disable:
pm_runtime_put_noidle(&pdev->dev); pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
...@@ -1195,6 +1212,7 @@ static int i2c_imx_remove(struct platform_device *pdev) ...@@ -1195,6 +1212,7 @@ static int i2c_imx_remove(struct platform_device *pdev)
imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2CR); imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2CR);
imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR); imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR);
clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb);
clk_disable_unprepare(i2c_imx->clk); clk_disable_unprepare(i2c_imx->clk);
pm_runtime_put_noidle(&pdev->dev); pm_runtime_put_noidle(&pdev->dev);
...@@ -1208,7 +1226,7 @@ static int i2c_imx_runtime_suspend(struct device *dev) ...@@ -1208,7 +1226,7 @@ static int i2c_imx_runtime_suspend(struct device *dev)
{ {
struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev); struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
clk_disable_unprepare(i2c_imx->clk); clk_disable(i2c_imx->clk);
return 0; return 0;
} }
...@@ -1218,7 +1236,7 @@ static int i2c_imx_runtime_resume(struct device *dev) ...@@ -1218,7 +1236,7 @@ static int i2c_imx_runtime_resume(struct device *dev)
struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev); struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
int ret; int ret;
ret = clk_prepare_enable(i2c_imx->clk); ret = clk_enable(i2c_imx->clk);
if (ret) if (ret)
dev_err(dev, "can't enable I2C clock, ret=%d\n", ret); dev_err(dev, "can't enable I2C clock, ret=%d\n", ret);
......
...@@ -845,11 +845,15 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, ...@@ -845,11 +845,15 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
*/ */
if (of_device_is_compatible(np, "marvell,mv78230-i2c")) { if (of_device_is_compatible(np, "marvell,mv78230-i2c")) {
drv_data->offload_enabled = true; drv_data->offload_enabled = true;
/* The delay is only needed in standard mode (100kHz) */
if (bus_freq <= 100000)
drv_data->errata_delay = true; drv_data->errata_delay = true;
} }
if (of_device_is_compatible(np, "marvell,mv78230-a0-i2c")) { if (of_device_is_compatible(np, "marvell,mv78230-a0-i2c")) {
drv_data->offload_enabled = false; drv_data->offload_enabled = false;
/* The delay is only needed in standard mode (100kHz) */
if (bus_freq <= 100000)
drv_data->errata_delay = true; drv_data->errata_delay = true;
} }
......
...@@ -173,33 +173,19 @@ static int i2c_pca_pf_probe(struct platform_device *pdev) ...@@ -173,33 +173,19 @@ static int i2c_pca_pf_probe(struct platform_device *pdev)
i2c->adap.dev.parent = &pdev->dev; i2c->adap.dev.parent = &pdev->dev;
i2c->adap.dev.of_node = np; i2c->adap.dev.of_node = np;
if (platform_data) {
i2c->adap.timeout = platform_data->timeout;
i2c->algo_data.i2c_clock = platform_data->i2c_clock_speed;
if (gpio_is_valid(platform_data->gpio)) {
ret = devm_gpio_request_one(&pdev->dev,
platform_data->gpio,
GPIOF_ACTIVE_LOW,
i2c->adap.name);
if (ret == 0) {
i2c->gpio = gpio_to_desc(platform_data->gpio);
gpiod_direction_output(i2c->gpio, 0);
} else {
dev_warn(&pdev->dev, "Registering gpio failed!\n");
i2c->gpio = NULL;
}
}
} else if (np) {
i2c->adap.timeout = HZ;
i2c->gpio = devm_gpiod_get_optional(&pdev->dev, "reset-gpios", GPIOD_OUT_LOW); i2c->gpio = devm_gpiod_get_optional(&pdev->dev, "reset-gpios", GPIOD_OUT_LOW);
if (IS_ERR(i2c->gpio)) if (IS_ERR(i2c->gpio))
return PTR_ERR(i2c->gpio); return PTR_ERR(i2c->gpio);
of_property_read_u32_index(np, "clock-frequency", 0,
&i2c->algo_data.i2c_clock);
} else {
i2c->adap.timeout = HZ; i2c->adap.timeout = HZ;
ret = device_property_read_u32(&pdev->dev, "clock-frequency",
&i2c->algo_data.i2c_clock);
if (ret)
i2c->algo_data.i2c_clock = 59000; i2c->algo_data.i2c_clock = 59000;
i2c->gpio = NULL;
if (platform_data) {
i2c->adap.timeout = platform_data->timeout;
i2c->algo_data.i2c_clock = platform_data->i2c_clock_speed;
} }
i2c->algo_data.data = i2c; i2c->algo_data.data = i2c;
......
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/mutex.h>
/* PIIX4 SMBus address offsets */ /* PIIX4 SMBus address offsets */
...@@ -153,10 +152,7 @@ static const struct dmi_system_id piix4_dmi_ibm[] = { ...@@ -153,10 +152,7 @@ static const struct dmi_system_id piix4_dmi_ibm[] = {
/* /*
* SB800 globals * SB800 globals
* piix4_mutex_sb800 protects piix4_port_sel_sb800 and the pair
* of I/O ports at SB800_PIIX4_SMB_IDX.
*/ */
static DEFINE_MUTEX(piix4_mutex_sb800);
static u8 piix4_port_sel_sb800; static u8 piix4_port_sel_sb800;
static u8 piix4_port_mask_sb800; static u8 piix4_port_mask_sb800;
static u8 piix4_port_shift_sb800; static u8 piix4_port_shift_sb800;
...@@ -298,12 +294,19 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, ...@@ -298,12 +294,19 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
else else
smb_en = (aux) ? 0x28 : 0x2c; smb_en = (aux) ? 0x28 : 0x2c;
mutex_lock(&piix4_mutex_sb800); if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2, "sb800_piix4_smb")) {
dev_err(&PIIX4_dev->dev,
"SMB base address index region 0x%x already in use.\n",
SB800_PIIX4_SMB_IDX);
return -EBUSY;
}
outb_p(smb_en, SB800_PIIX4_SMB_IDX); outb_p(smb_en, SB800_PIIX4_SMB_IDX);
smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1); smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX); outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX);
smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1); smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1);
mutex_unlock(&piix4_mutex_sb800);
release_region(SB800_PIIX4_SMB_IDX, 2);
if (!smb_en) { if (!smb_en) {
smb_en_status = smba_en_lo & 0x10; smb_en_status = smba_en_lo & 0x10;
...@@ -373,7 +376,12 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, ...@@ -373,7 +376,12 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
break; break;
} }
} else { } else {
mutex_lock(&piix4_mutex_sb800); if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2,
"sb800_piix4_smb")) {
release_region(piix4_smba, SMBIOSIZE);
return -EBUSY;
}
outb_p(SB800_PIIX4_PORT_IDX_SEL, SB800_PIIX4_SMB_IDX); outb_p(SB800_PIIX4_PORT_IDX_SEL, SB800_PIIX4_SMB_IDX);
port_sel = inb_p(SB800_PIIX4_SMB_IDX + 1); port_sel = inb_p(SB800_PIIX4_SMB_IDX + 1);
piix4_port_sel_sb800 = (port_sel & 0x01) ? piix4_port_sel_sb800 = (port_sel & 0x01) ?
...@@ -381,7 +389,7 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, ...@@ -381,7 +389,7 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
SB800_PIIX4_PORT_IDX; SB800_PIIX4_PORT_IDX;
piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK; piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK;
piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT; piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
mutex_unlock(&piix4_mutex_sb800); release_region(SB800_PIIX4_SMB_IDX, 2);
} }
dev_info(&PIIX4_dev->dev, dev_info(&PIIX4_dev->dev,
...@@ -462,13 +470,13 @@ static int piix4_transaction(struct i2c_adapter *piix4_adapter) ...@@ -462,13 +470,13 @@ static int piix4_transaction(struct i2c_adapter *piix4_adapter)
/* We will always wait for a fraction of a second! (See PIIX4 docs errata) */ /* We will always wait for a fraction of a second! (See PIIX4 docs errata) */
if (srvrworks_csb5_delay) /* Extra delay for SERVERWORKS_CSB5 */ if (srvrworks_csb5_delay) /* Extra delay for SERVERWORKS_CSB5 */
msleep(2); usleep_range(2000, 2100);
else else
msleep(1); usleep_range(250, 500);
while ((++timeout < MAX_TIMEOUT) && while ((++timeout < MAX_TIMEOUT) &&
((temp = inb_p(SMBHSTSTS)) & 0x01)) ((temp = inb_p(SMBHSTSTS)) & 0x01))
msleep(1); usleep_range(250, 500);
/* If the SMBus is still busy, we give up */ /* If the SMBus is still busy, we give up */
if (timeout == MAX_TIMEOUT) { if (timeout == MAX_TIMEOUT) {
...@@ -679,7 +687,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, ...@@ -679,7 +687,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
u8 port; u8 port;
int retval; int retval;
mutex_lock(&piix4_mutex_sb800); if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2, "sb800_piix4_smb"))
return -EBUSY;
/* Request the SMBUS semaphore, avoid conflicts with the IMC */ /* Request the SMBUS semaphore, avoid conflicts with the IMC */
smbslvcnt = inb_p(SMBSLVCNT); smbslvcnt = inb_p(SMBSLVCNT);
...@@ -695,8 +704,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, ...@@ -695,8 +704,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
} while (--retries); } while (--retries);
/* SMBus is still owned by the IMC, we give up */ /* SMBus is still owned by the IMC, we give up */
if (!retries) { if (!retries) {
mutex_unlock(&piix4_mutex_sb800); retval = -EBUSY;
return -EBUSY; goto release;
} }
/* /*
...@@ -753,8 +762,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, ...@@ -753,8 +762,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
if ((size == I2C_SMBUS_BLOCK_DATA) && adapdata->notify_imc) if ((size == I2C_SMBUS_BLOCK_DATA) && adapdata->notify_imc)
piix4_imc_wakeup(); piix4_imc_wakeup();
mutex_unlock(&piix4_mutex_sb800); release:
release_region(SB800_PIIX4_SMB_IDX, 2);
return retval; return retval;
} }
...@@ -899,13 +908,6 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -899,13 +908,6 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
bool notify_imc = false; bool notify_imc = false;
is_sb800 = true; is_sb800 = true;
if (!request_region(SB800_PIIX4_SMB_IDX, 2, "smba_idx")) {
dev_err(&dev->dev,
"SMBus base address index region 0x%x already in use!\n",
SB800_PIIX4_SMB_IDX);
return -EBUSY;
}
if (dev->vendor == PCI_VENDOR_ID_AMD && if (dev->vendor == PCI_VENDOR_ID_AMD &&
dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS) { dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS) {
u8 imc; u8 imc;
...@@ -922,20 +924,16 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -922,20 +924,16 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
/* base address location etc changed in SB800 */ /* base address location etc changed in SB800 */
retval = piix4_setup_sb800(dev, id, 0); retval = piix4_setup_sb800(dev, id, 0);
if (retval < 0) { if (retval < 0)
release_region(SB800_PIIX4_SMB_IDX, 2);
return retval; return retval;
}
/* /*
* Try to register multiplexed main SMBus adapter, * Try to register multiplexed main SMBus adapter,
* give up if we can't * give up if we can't
*/ */
retval = piix4_add_adapters_sb800(dev, retval, notify_imc); retval = piix4_add_adapters_sb800(dev, retval, notify_imc);
if (retval < 0) { if (retval < 0)
release_region(SB800_PIIX4_SMB_IDX, 2);
return retval; return retval;
}
} else { } else {
retval = piix4_setup(dev, id); retval = piix4_setup(dev, id);
if (retval < 0) if (retval < 0)
...@@ -983,11 +981,8 @@ static void piix4_adap_remove(struct i2c_adapter *adap) ...@@ -983,11 +981,8 @@ static void piix4_adap_remove(struct i2c_adapter *adap)
if (adapdata->smba) { if (adapdata->smba) {
i2c_del_adapter(adap); i2c_del_adapter(adap);
if (adapdata->port == (0 << piix4_port_shift_sb800)) { if (adapdata->port == (0 << piix4_port_shift_sb800))
release_region(adapdata->smba, SMBIOSIZE); release_region(adapdata->smba, SMBIOSIZE);
if (adapdata->sb800_main)
release_region(SB800_PIIX4_SMB_IDX, 2);
}
kfree(adapdata); kfree(adapdata);
kfree(adap); kfree(adap);
} }
......
// SPDX-License-Identifier: GPL-2.0
/* /*
* Copyright (c) 2009-2013, The Linux Foundation. All rights reserved. * Copyright (c) 2009-2013, 2016-2018, The Linux Foundation. All rights reserved.
* Copyright (c) 2014, Sony Mobile Communications AB. * Copyright (c) 2014, Sony Mobile Communications AB.
* *
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/ */
#include <linux/acpi.h> #include <linux/acpi.h>
...@@ -73,8 +64,11 @@ ...@@ -73,8 +64,11 @@
#define QUP_IN_SVC_FLAG BIT(9) #define QUP_IN_SVC_FLAG BIT(9)
#define QUP_MX_OUTPUT_DONE BIT(10) #define QUP_MX_OUTPUT_DONE BIT(10)
#define QUP_MX_INPUT_DONE BIT(11) #define QUP_MX_INPUT_DONE BIT(11)
#define OUT_BLOCK_WRITE_REQ BIT(12)
#define IN_BLOCK_READ_REQ BIT(13)
/* I2C mini core related values */ /* I2C mini core related values */
#define QUP_NO_INPUT BIT(7)
#define QUP_CLOCK_AUTO_GATE BIT(13) #define QUP_CLOCK_AUTO_GATE BIT(13)
#define I2C_MINI_CORE (2 << 8) #define I2C_MINI_CORE (2 << 8)
#define I2C_N_VAL 15 #define I2C_N_VAL 15
...@@ -113,6 +107,7 @@ ...@@ -113,6 +107,7 @@
#define QUP_TAG_V2_DATAWR 0x82 #define QUP_TAG_V2_DATAWR 0x82
#define QUP_TAG_V2_DATAWR_STOP 0x83 #define QUP_TAG_V2_DATAWR_STOP 0x83
#define QUP_TAG_V2_DATARD 0x85 #define QUP_TAG_V2_DATARD 0x85
#define QUP_TAG_V2_DATARD_NACK 0x86
#define QUP_TAG_V2_DATARD_STOP 0x87 #define QUP_TAG_V2_DATARD_STOP 0x87
/* Status, Error flags */ /* Status, Error flags */
...@@ -127,22 +122,86 @@ ...@@ -127,22 +122,86 @@
#define ONE_BYTE 0x1 #define ONE_BYTE 0x1
#define QUP_I2C_MX_CONFIG_DURING_RUN BIT(31) #define QUP_I2C_MX_CONFIG_DURING_RUN BIT(31)
/* Maximum transfer length for single DMA descriptor */
#define MX_TX_RX_LEN SZ_64K #define MX_TX_RX_LEN SZ_64K
#define MX_BLOCKS (MX_TX_RX_LEN / QUP_READ_LIMIT) #define MX_BLOCKS (MX_TX_RX_LEN / QUP_READ_LIMIT)
/* Maximum transfer length for all DMA descriptors */
#define MX_DMA_TX_RX_LEN (2 * MX_TX_RX_LEN)
#define MX_DMA_BLOCKS (MX_DMA_TX_RX_LEN / QUP_READ_LIMIT)
/* Max timeout in ms for 32k bytes */ /*
#define TOUT_MAX 300 * Minimum transfer timeout for i2c transfers in seconds. It will be added on
* the top of maximum transfer time calculated from i2c bus speed to compensate
* the overheads.
*/
#define TOUT_MIN 2
/* Default values. Use these if FW query fails */ /* Default values. Use these if FW query fails */
#define DEFAULT_CLK_FREQ 100000 #define DEFAULT_CLK_FREQ 100000
#define DEFAULT_SRC_CLK 20000000 #define DEFAULT_SRC_CLK 20000000
/*
* Max tags length (start, stop and maximum 2 bytes address) for each QUP
* data transfer
*/
#define QUP_MAX_TAGS_LEN 4
/* Max data length for each DATARD tags */
#define RECV_MAX_DATA_LEN 254
/* TAG length for DATA READ in RX FIFO */
#define READ_RX_TAGS_LEN 2
/*
* count: no of blocks
* pos: current block number
* tx_tag_len: tx tag length for current block
* rx_tag_len: rx tag length for current block
* data_len: remaining data length for current message
* cur_blk_len: data length for current block
* total_tx_len: total tx length including tag bytes for current QUP transfer
* total_rx_len: total rx length including tag bytes for current QUP transfer
* tx_fifo_data_pos: current byte number in TX FIFO word
* tx_fifo_free: number of free bytes in current QUP block write.
* rx_fifo_data_pos: current byte number in RX FIFO word
* fifo_available: number of available bytes in RX FIFO for current
* QUP block read
* tx_fifo_data: QUP TX FIFO write works on word basis (4 bytes). New byte write
* to TX FIFO will be appended in this data and will be written to
* TX FIFO when all the 4 bytes are available.
* rx_fifo_data: QUP RX FIFO read works on word basis (4 bytes). This will
* contains the 4 bytes of RX data.
* cur_data: pointer to tell cur data position for current message
* cur_tx_tags: pointer to tell cur position in tags
* tx_tags_sent: all tx tag bytes have been written in FIFO word
* send_last_word: for tx FIFO, last word send is pending in current block
* rx_bytes_read: if all the bytes have been read from rx FIFO.
* rx_tags_fetched: all the rx tag bytes have been fetched from rx fifo word
* is_tx_blk_mode: whether tx uses block or FIFO mode in case of non BAM xfer.
* is_rx_blk_mode: whether rx uses block or FIFO mode in case of non BAM xfer.
* tags: contains tx tag bytes for current QUP transfer
*/
struct qup_i2c_block { struct qup_i2c_block {
int count; int count;
int pos; int pos;
int tx_tag_len; int tx_tag_len;
int rx_tag_len; int rx_tag_len;
int data_len; int data_len;
int cur_blk_len;
int total_tx_len;
int total_rx_len;
int tx_fifo_data_pos;
int tx_fifo_free;
int rx_fifo_data_pos;
int fifo_available;
u32 tx_fifo_data;
u32 rx_fifo_data;
u8 *cur_data;
u8 *cur_tx_tags;
bool tx_tags_sent;
bool send_last_word;
bool rx_tags_fetched;
bool rx_bytes_read;
bool is_tx_blk_mode;
bool is_rx_blk_mode;
u8 tags[6]; u8 tags[6];
}; };
...@@ -155,6 +214,7 @@ struct qup_i2c_bam { ...@@ -155,6 +214,7 @@ struct qup_i2c_bam {
struct qup_i2c_tag tag; struct qup_i2c_tag tag;
struct dma_chan *dma; struct dma_chan *dma;
struct scatterlist *sg; struct scatterlist *sg;
unsigned int sg_cnt;
}; };
struct qup_i2c_dev { struct qup_i2c_dev {
...@@ -171,7 +231,9 @@ struct qup_i2c_dev { ...@@ -171,7 +231,9 @@ struct qup_i2c_dev {
int out_blk_sz; int out_blk_sz;
int in_blk_sz; int in_blk_sz;
int blk_xfer_limit;
unsigned long one_byte_t; unsigned long one_byte_t;
unsigned long xfer_timeout;
struct qup_i2c_block blk; struct qup_i2c_block blk;
struct i2c_msg *msg; struct i2c_msg *msg;
...@@ -184,23 +246,37 @@ struct qup_i2c_dev { ...@@ -184,23 +246,37 @@ struct qup_i2c_dev {
/* To check if this is the last msg */ /* To check if this is the last msg */
bool is_last; bool is_last;
bool is_smbus_read;
/* To configure when bus is in run state */ /* To configure when bus is in run state */
int config_run; u32 config_run;
/* dma parameters */ /* dma parameters */
bool is_dma; bool is_dma;
/* To check if the current transfer is using DMA */
bool use_dma;
unsigned int max_xfer_sg_len;
unsigned int tag_buf_pos;
/* The threshold length above which block mode will be used */
unsigned int blk_mode_threshold;
struct dma_pool *dpool; struct dma_pool *dpool;
struct qup_i2c_tag start_tag; struct qup_i2c_tag start_tag;
struct qup_i2c_bam brx; struct qup_i2c_bam brx;
struct qup_i2c_bam btx; struct qup_i2c_bam btx;
struct completion xfer; struct completion xfer;
/* function to write data in tx fifo */
void (*write_tx_fifo)(struct qup_i2c_dev *qup);
/* function to read data from rx fifo */
void (*read_rx_fifo)(struct qup_i2c_dev *qup);
/* function to write tags in tx fifo for i2c read transfer */
void (*write_rx_tags)(struct qup_i2c_dev *qup);
}; };
static irqreturn_t qup_i2c_interrupt(int irq, void *dev) static irqreturn_t qup_i2c_interrupt(int irq, void *dev)
{ {
struct qup_i2c_dev *qup = dev; struct qup_i2c_dev *qup = dev;
struct qup_i2c_block *blk = &qup->blk;
u32 bus_err; u32 bus_err;
u32 qup_err; u32 qup_err;
u32 opflags; u32 opflags;
...@@ -226,17 +302,65 @@ static irqreturn_t qup_i2c_interrupt(int irq, void *dev) ...@@ -226,17 +302,65 @@ static irqreturn_t qup_i2c_interrupt(int irq, void *dev)
if (bus_err) if (bus_err)
writel(bus_err, qup->base + QUP_I2C_STATUS); writel(bus_err, qup->base + QUP_I2C_STATUS);
/*
* Check for BAM mode and returns if already error has come for current
* transfer. In Error case, sometimes, QUP generates more than one
* interrupt.
*/
if (qup->use_dma && (qup->qup_err || qup->bus_err))
return IRQ_HANDLED;
/* Reset the QUP State in case of error */ /* Reset the QUP State in case of error */
if (qup_err || bus_err) { if (qup_err || bus_err) {
/*
* Don’t reset the QUP state in case of BAM mode. The BAM
* flush operation needs to be scheduled in transfer function
* which will clear the remaining schedule descriptors in BAM
* HW FIFO and generates the BAM interrupt.
*/
if (!qup->use_dma)
writel(QUP_RESET_STATE, qup->base + QUP_STATE); writel(QUP_RESET_STATE, qup->base + QUP_STATE);
goto done; goto done;
} }
if (opflags & QUP_IN_SVC_FLAG) if (opflags & QUP_OUT_SVC_FLAG) {
writel(QUP_OUT_SVC_FLAG, qup->base + QUP_OPERATIONAL);
if (opflags & OUT_BLOCK_WRITE_REQ) {
blk->tx_fifo_free += qup->out_blk_sz;
if (qup->msg->flags & I2C_M_RD)
qup->write_rx_tags(qup);
else
qup->write_tx_fifo(qup);
}
}
if (opflags & QUP_IN_SVC_FLAG) {
writel(QUP_IN_SVC_FLAG, qup->base + QUP_OPERATIONAL); writel(QUP_IN_SVC_FLAG, qup->base + QUP_OPERATIONAL);
if (opflags & QUP_OUT_SVC_FLAG) if (!blk->is_rx_blk_mode) {
writel(QUP_OUT_SVC_FLAG, qup->base + QUP_OPERATIONAL); blk->fifo_available += qup->in_fifo_sz;
qup->read_rx_fifo(qup);
} else if (opflags & IN_BLOCK_READ_REQ) {
blk->fifo_available += qup->in_blk_sz;
qup->read_rx_fifo(qup);
}
}
if (qup->msg->flags & I2C_M_RD) {
if (!blk->rx_bytes_read)
return IRQ_HANDLED;
} else {
/*
* Ideally, QUP_MAX_OUTPUT_DONE_FLAG should be checked
* for FIFO mode also. But, QUP_MAX_OUTPUT_DONE_FLAG lags
* behind QUP_OUTPUT_SERVICE_FLAG sometimes. The only reason
* of interrupt for write message in FIFO mode is
* QUP_MAX_OUTPUT_DONE_FLAG condition.
*/
if (blk->is_tx_blk_mode && !(opflags & QUP_MX_OUTPUT_DONE))
return IRQ_HANDLED;
}
done: done:
qup->qup_err = qup_err; qup->qup_err = qup_err;
...@@ -303,147 +427,47 @@ static int qup_i2c_change_state(struct qup_i2c_dev *qup, u32 state) ...@@ -303,147 +427,47 @@ static int qup_i2c_change_state(struct qup_i2c_dev *qup, u32 state)
return 0; return 0;
} }
/** /* Check if I2C bus returns to IDLE state */
* qup_i2c_wait_ready - wait for a give number of bytes in tx/rx path static int qup_i2c_bus_active(struct qup_i2c_dev *qup, int len)
* @qup: The qup_i2c_dev device
* @op: The bit/event to wait on
* @val: value of the bit to wait on, 0 or 1
* @len: The length the bytes to be transferred
*/
static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
int len)
{ {
unsigned long timeout; unsigned long timeout;
u32 opflags;
u32 status; u32 status;
u32 shift = __ffs(op);
int ret = 0; int ret = 0;
len *= qup->one_byte_t;
/* timeout after a wait of twice the max time */
timeout = jiffies + len * 4; timeout = jiffies + len * 4;
for (;;) { for (;;) {
opflags = readl(qup->base + QUP_OPERATIONAL);
status = readl(qup->base + QUP_I2C_STATUS); status = readl(qup->base + QUP_I2C_STATUS);
if (!(status & I2C_STATUS_BUS_ACTIVE))
break;
if (((opflags & op) >> shift) == val) { if (time_after(jiffies, timeout))
if ((op == QUP_OUT_NOT_EMPTY) && qup->is_last) {
if (!(status & I2C_STATUS_BUS_ACTIVE)) {
ret = 0;
goto done;
}
} else {
ret = 0;
goto done;
}
}
if (time_after(jiffies, timeout)) {
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
goto done;
}
usleep_range(len, len * 2);
}
done:
if (qup->bus_err || qup->qup_err)
ret = (qup->bus_err & QUP_I2C_NACK_FLAG) ? -ENXIO : -EIO;
return ret;
}
static void qup_i2c_set_write_mode_v2(struct qup_i2c_dev *qup,
struct i2c_msg *msg)
{
/* Number of entries to shift out, including the tags */
int total = msg->len + qup->blk.tx_tag_len;
total |= qup->config_run;
if (total < qup->out_fifo_sz) {
/* FIFO mode */
writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE);
writel(total, qup->base + QUP_MX_WRITE_CNT);
} else {
/* BLOCK mode (transfer data on chunks) */
writel(QUP_OUTPUT_BLK_MODE | QUP_REPACK_EN,
qup->base + QUP_IO_MODE);
writel(total, qup->base + QUP_MX_OUTPUT_CNT);
}
}
static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg)
{
/* Number of entries to shift out, including the start */
int total = msg->len + 1;
if (total < qup->out_fifo_sz) {
/* FIFO mode */
writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE);
writel(total, qup->base + QUP_MX_WRITE_CNT);
} else {
/* BLOCK mode (transfer data on chunks) */
writel(QUP_OUTPUT_BLK_MODE | QUP_REPACK_EN,
qup->base + QUP_IO_MODE);
writel(total, qup->base + QUP_MX_OUTPUT_CNT);
}
}
static int check_for_fifo_space(struct qup_i2c_dev *qup)
{
int ret;
ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
if (ret)
goto out;
ret = qup_i2c_wait_ready(qup, QUP_OUT_FULL,
RESET_BIT, 4 * ONE_BYTE);
if (ret) {
/* Fifo is full. Drain out the fifo */
ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
if (ret)
goto out;
ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY,
RESET_BIT, 256 * ONE_BYTE);
if (ret) {
dev_err(qup->dev, "timeout for fifo out full");
goto out;
}
ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE); usleep_range(len, len * 2);
if (ret)
goto out;
} }
out:
return ret; return ret;
} }
static int qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg *msg) static void qup_i2c_write_tx_fifo_v1(struct qup_i2c_dev *qup)
{ {
struct qup_i2c_block *blk = &qup->blk;
struct i2c_msg *msg = qup->msg;
u32 addr = msg->addr << 1; u32 addr = msg->addr << 1;
u32 qup_tag; u32 qup_tag;
int idx; int idx;
u32 val; u32 val;
int ret = 0;
if (qup->pos == 0) { if (qup->pos == 0) {
val = QUP_TAG_START | addr; val = QUP_TAG_START | addr;
idx = 1; idx = 1;
blk->tx_fifo_free--;
} else { } else {
val = 0; val = 0;
idx = 0; idx = 0;
} }
while (qup->pos < msg->len) { while (blk->tx_fifo_free && qup->pos < msg->len) {
/* Check that there's space in the FIFO for our pair */
ret = check_for_fifo_space(qup);
if (ret)
return ret;
if (qup->pos == msg->len - 1) if (qup->pos == msg->len - 1)
qup_tag = QUP_TAG_STOP; qup_tag = QUP_TAG_STOP;
else else
...@@ -460,70 +484,24 @@ static int qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg *msg) ...@@ -460,70 +484,24 @@ static int qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg *msg)
qup->pos++; qup->pos++;
idx++; idx++;
blk->tx_fifo_free--;
} }
ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
return ret;
} }
static void qup_i2c_set_blk_data(struct qup_i2c_dev *qup, static void qup_i2c_set_blk_data(struct qup_i2c_dev *qup,
struct i2c_msg *msg) struct i2c_msg *msg)
{ {
memset(&qup->blk, 0, sizeof(qup->blk)); qup->blk.pos = 0;
qup->blk.data_len = msg->len; qup->blk.data_len = msg->len;
qup->blk.count = (msg->len + QUP_READ_LIMIT - 1) / QUP_READ_LIMIT; qup->blk.count = DIV_ROUND_UP(msg->len, qup->blk_xfer_limit);
/* 4 bytes for first block and 2 writes for rest */
qup->blk.tx_tag_len = 4 + (qup->blk.count - 1) * 2;
/* There are 2 tag bytes that are read in to fifo for every block */
if (msg->flags & I2C_M_RD)
qup->blk.rx_tag_len = qup->blk.count * 2;
}
static int qup_i2c_send_data(struct qup_i2c_dev *qup, int tlen, u8 *tbuf,
int dlen, u8 *dbuf)
{
u32 val = 0, idx = 0, pos = 0, i = 0, t;
int len = tlen + dlen;
u8 *buf = tbuf;
int ret = 0;
while (len > 0) {
ret = check_for_fifo_space(qup);
if (ret)
return ret;
t = (len >= 4) ? 4 : len;
while (idx < t) {
if (!i && (pos >= tlen)) {
buf = dbuf;
pos = 0;
i = 1;
}
val |= buf[pos++] << (idx++ * 8);
}
writel(val, qup->base + QUP_OUT_FIFO_BASE);
idx = 0;
val = 0;
len -= 4;
}
ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
return ret;
} }
static int qup_i2c_get_data_len(struct qup_i2c_dev *qup) static int qup_i2c_get_data_len(struct qup_i2c_dev *qup)
{ {
int data_len; int data_len;
if (qup->blk.data_len > QUP_READ_LIMIT) if (qup->blk.data_len > qup->blk_xfer_limit)
data_len = QUP_READ_LIMIT; data_len = qup->blk_xfer_limit;
else else
data_len = qup->blk.data_len; data_len = qup->blk.data_len;
...@@ -540,9 +518,9 @@ static int qup_i2c_set_tags_smb(u16 addr, u8 *tags, struct qup_i2c_dev *qup, ...@@ -540,9 +518,9 @@ static int qup_i2c_set_tags_smb(u16 addr, u8 *tags, struct qup_i2c_dev *qup,
{ {
int len = 0; int len = 0;
if (msg->len > 1) { if (qup->is_smbus_read) {
tags[len++] = QUP_TAG_V2_DATARD_STOP; tags[len++] = QUP_TAG_V2_DATARD_STOP;
tags[len++] = qup_i2c_get_data_len(qup) - 1; tags[len++] = qup_i2c_get_data_len(qup);
} else { } else {
tags[len++] = QUP_TAG_V2_START; tags[len++] = QUP_TAG_V2_START;
tags[len++] = addr & 0xff; tags[len++] = addr & 0xff;
...@@ -558,7 +536,7 @@ static int qup_i2c_set_tags_smb(u16 addr, u8 *tags, struct qup_i2c_dev *qup, ...@@ -558,7 +536,7 @@ static int qup_i2c_set_tags_smb(u16 addr, u8 *tags, struct qup_i2c_dev *qup,
} }
static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup, static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,
struct i2c_msg *msg, int is_dma) struct i2c_msg *msg)
{ {
u16 addr = i2c_8bit_addr_from_msg(msg); u16 addr = i2c_8bit_addr_from_msg(msg);
int len = 0; int len = 0;
...@@ -586,7 +564,9 @@ static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup, ...@@ -586,7 +564,9 @@ static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,
tags[len++] = QUP_TAG_V2_DATAWR_STOP; tags[len++] = QUP_TAG_V2_DATAWR_STOP;
} else { } else {
if (msg->flags & I2C_M_RD) if (msg->flags & I2C_M_RD)
tags[len++] = QUP_TAG_V2_DATARD; tags[len++] = qup->blk.pos == (qup->blk.count - 1) ?
QUP_TAG_V2_DATARD_NACK :
QUP_TAG_V2_DATARD;
else else
tags[len++] = QUP_TAG_V2_DATAWR; tags[len++] = QUP_TAG_V2_DATAWR;
} }
...@@ -599,32 +579,9 @@ static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup, ...@@ -599,32 +579,9 @@ static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,
else else
tags[len++] = data_len; tags[len++] = data_len;
if ((msg->flags & I2C_M_RD) && last && is_dma) {
tags[len++] = QUP_BAM_INPUT_EOT;
tags[len++] = QUP_BAM_FLUSH_STOP;
}
return len; return len;
} }
static int qup_i2c_issue_xfer_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
{
int data_len = 0, tag_len, index;
int ret;
tag_len = qup_i2c_set_tags(qup->blk.tags, qup, msg, 0);
index = msg->len - qup->blk.data_len;
/* only tags are written for read */
if (!(msg->flags & I2C_M_RD))
data_len = qup_i2c_get_data_len(qup);
ret = qup_i2c_send_data(qup, tag_len, qup->blk.tags,
data_len, &msg->buf[index]);
qup->blk.data_len -= data_len;
return ret;
}
static void qup_i2c_bam_cb(void *data) static void qup_i2c_bam_cb(void *data)
{ {
...@@ -684,45 +641,35 @@ static int qup_i2c_req_dma(struct qup_i2c_dev *qup) ...@@ -684,45 +641,35 @@ static int qup_i2c_req_dma(struct qup_i2c_dev *qup)
return 0; return 0;
} }
static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg, static int qup_i2c_bam_make_desc(struct qup_i2c_dev *qup, struct i2c_msg *msg)
int num)
{ {
struct dma_async_tx_descriptor *txd, *rxd = NULL; int ret = 0, limit = QUP_READ_LIMIT;
int ret = 0, idx = 0, limit = QUP_READ_LIMIT; u32 len = 0, blocks, rem;
dma_cookie_t cookie_rx, cookie_tx; u32 i = 0, tlen, tx_len = 0;
u32 rx_nents = 0, tx_nents = 0, len, blocks, rem;
u32 i, tlen, tx_len, tx_buf = 0, rx_buf = 0, off = 0;
u8 *tags; u8 *tags;
while (idx < num) { qup->blk_xfer_limit = QUP_READ_LIMIT;
tx_len = 0, len = 0, i = 0;
qup->is_last = (idx == (num - 1));
qup_i2c_set_blk_data(qup, msg); qup_i2c_set_blk_data(qup, msg);
blocks = qup->blk.count; blocks = qup->blk.count;
rem = msg->len - (blocks - 1) * limit; rem = msg->len - (blocks - 1) * limit;
if (msg->flags & I2C_M_RD) { if (msg->flags & I2C_M_RD) {
rx_nents += (blocks * 2) + 1;
tx_nents += 1;
while (qup->blk.pos < blocks) { while (qup->blk.pos < blocks) {
tlen = (i == (blocks - 1)) ? rem : limit; tlen = (i == (blocks - 1)) ? rem : limit;
tags = &qup->start_tag.start[off + len]; tags = &qup->start_tag.start[qup->tag_buf_pos + len];
len += qup_i2c_set_tags(tags, qup, msg, 1); len += qup_i2c_set_tags(tags, qup, msg);
qup->blk.data_len -= tlen; qup->blk.data_len -= tlen;
/* scratch buf to read the start and len tags */ /* scratch buf to read the start and len tags */
ret = qup_sg_set_buf(&qup->brx.sg[rx_buf++], ret = qup_sg_set_buf(&qup->brx.sg[qup->brx.sg_cnt++],
&qup->brx.tag.start[0], &qup->brx.tag.start[0],
2, qup, DMA_FROM_DEVICE); 2, qup, DMA_FROM_DEVICE);
if (ret) if (ret)
return ret; return ret;
ret = qup_sg_set_buf(&qup->brx.sg[rx_buf++], ret = qup_sg_set_buf(&qup->brx.sg[qup->brx.sg_cnt++],
&msg->buf[limit * i], &msg->buf[limit * i],
tlen, qup, tlen, qup,
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
...@@ -732,36 +679,28 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg, ...@@ -732,36 +679,28 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
i++; i++;
qup->blk.pos = i; qup->blk.pos = i;
} }
ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++], ret = qup_sg_set_buf(&qup->btx.sg[qup->btx.sg_cnt++],
&qup->start_tag.start[off], &qup->start_tag.start[qup->tag_buf_pos],
len, qup, DMA_TO_DEVICE); len, qup, DMA_TO_DEVICE);
if (ret) if (ret)
return ret; return ret;
off += len; qup->tag_buf_pos += len;
/* scratch buf to read the BAM EOT and FLUSH tags */
ret = qup_sg_set_buf(&qup->brx.sg[rx_buf++],
&qup->brx.tag.start[0],
2, qup, DMA_FROM_DEVICE);
if (ret)
return ret;
} else { } else {
tx_nents += (blocks * 2);
while (qup->blk.pos < blocks) { while (qup->blk.pos < blocks) {
tlen = (i == (blocks - 1)) ? rem : limit; tlen = (i == (blocks - 1)) ? rem : limit;
tags = &qup->start_tag.start[off + tx_len]; tags = &qup->start_tag.start[qup->tag_buf_pos + tx_len];
len = qup_i2c_set_tags(tags, qup, msg, 1); len = qup_i2c_set_tags(tags, qup, msg);
qup->blk.data_len -= tlen; qup->blk.data_len -= tlen;
ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++], ret = qup_sg_set_buf(&qup->btx.sg[qup->btx.sg_cnt++],
tags, len, tags, len,
qup, DMA_TO_DEVICE); qup, DMA_TO_DEVICE);
if (ret) if (ret)
return ret; return ret;
tx_len += len; tx_len += len;
ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++], ret = qup_sg_set_buf(&qup->btx.sg[qup->btx.sg_cnt++],
&msg->buf[limit * i], &msg->buf[limit * i],
tlen, qup, DMA_TO_DEVICE); tlen, qup, DMA_TO_DEVICE);
if (ret) if (ret)
...@@ -769,30 +708,42 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg, ...@@ -769,30 +708,42 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
i++; i++;
qup->blk.pos = i; qup->blk.pos = i;
} }
off += tx_len;
if (idx == (num - 1)) { qup->tag_buf_pos += tx_len;
}
return 0;
}
static int qup_i2c_bam_schedule_desc(struct qup_i2c_dev *qup)
{
struct dma_async_tx_descriptor *txd, *rxd = NULL;
int ret = 0;
dma_cookie_t cookie_rx, cookie_tx;
u32 len = 0;
u32 tx_cnt = qup->btx.sg_cnt, rx_cnt = qup->brx.sg_cnt;
/* schedule the EOT and FLUSH I2C tags */
len = 1; len = 1;
if (rx_nents) { if (rx_cnt) {
qup->btx.tag.start[0] = qup->btx.tag.start[0] = QUP_BAM_INPUT_EOT;
QUP_BAM_INPUT_EOT;
len++; len++;
/* scratch buf to read the BAM EOT FLUSH tags */
ret = qup_sg_set_buf(&qup->brx.sg[rx_cnt++],
&qup->brx.tag.start[0],
1, qup, DMA_FROM_DEVICE);
if (ret)
return ret;
} }
qup->btx.tag.start[len - 1] =
QUP_BAM_FLUSH_STOP; qup->btx.tag.start[len - 1] = QUP_BAM_FLUSH_STOP;
ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++], ret = qup_sg_set_buf(&qup->btx.sg[tx_cnt++], &qup->btx.tag.start[0],
&qup->btx.tag.start[0],
len, qup, DMA_TO_DEVICE); len, qup, DMA_TO_DEVICE);
if (ret) if (ret)
return ret; return ret;
tx_nents += 1;
}
}
idx++;
msg++;
}
txd = dmaengine_prep_slave_sg(qup->btx.dma, qup->btx.sg, tx_nents, txd = dmaengine_prep_slave_sg(qup->btx.dma, qup->btx.sg, tx_cnt,
DMA_MEM_TO_DEV, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_PREP_FENCE); DMA_PREP_INTERRUPT | DMA_PREP_FENCE);
if (!txd) { if (!txd) {
...@@ -801,7 +752,7 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg, ...@@ -801,7 +752,7 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
goto desc_err; goto desc_err;
} }
if (!rx_nents) { if (!rx_cnt) {
txd->callback = qup_i2c_bam_cb; txd->callback = qup_i2c_bam_cb;
txd->callback_param = qup; txd->callback_param = qup;
} }
...@@ -814,9 +765,9 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg, ...@@ -814,9 +765,9 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
dma_async_issue_pending(qup->btx.dma); dma_async_issue_pending(qup->btx.dma);
if (rx_nents) { if (rx_cnt) {
rxd = dmaengine_prep_slave_sg(qup->brx.dma, qup->brx.sg, rxd = dmaengine_prep_slave_sg(qup->brx.dma, qup->brx.sg,
rx_nents, DMA_DEV_TO_MEM, rx_cnt, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT); DMA_PREP_INTERRUPT);
if (!rxd) { if (!rxd) {
dev_err(qup->dev, "failed to get rx desc\n"); dev_err(qup->dev, "failed to get rx desc\n");
...@@ -838,49 +789,51 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg, ...@@ -838,49 +789,51 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
dma_async_issue_pending(qup->brx.dma); dma_async_issue_pending(qup->brx.dma);
} }
if (!wait_for_completion_timeout(&qup->xfer, TOUT_MAX * HZ)) { if (!wait_for_completion_timeout(&qup->xfer, qup->xfer_timeout)) {
dev_err(qup->dev, "normal trans timed out\n"); dev_err(qup->dev, "normal trans timed out\n");
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
} }
if (ret || qup->bus_err || qup->qup_err) { if (ret || qup->bus_err || qup->qup_err) {
reinit_completion(&qup->xfer);
if (qup_i2c_change_state(qup, QUP_RUN_STATE)) { if (qup_i2c_change_state(qup, QUP_RUN_STATE)) {
dev_err(qup->dev, "change to run state timed out"); dev_err(qup->dev, "change to run state timed out");
goto desc_err; goto desc_err;
} }
if (rx_nents)
writel(QUP_BAM_INPUT_EOT,
qup->base + QUP_OUT_FIFO_BASE);
writel(QUP_BAM_FLUSH_STOP, qup->base + QUP_OUT_FIFO_BASE);
qup_i2c_flush(qup); qup_i2c_flush(qup);
/* wait for remaining interrupts to occur */ /* wait for remaining interrupts to occur */
if (!wait_for_completion_timeout(&qup->xfer, HZ)) if (!wait_for_completion_timeout(&qup->xfer, HZ))
dev_err(qup->dev, "flush timed out\n"); dev_err(qup->dev, "flush timed out\n");
qup_i2c_rel_dma(qup);
ret = (qup->bus_err & QUP_I2C_NACK_FLAG) ? -ENXIO : -EIO; ret = (qup->bus_err & QUP_I2C_NACK_FLAG) ? -ENXIO : -EIO;
} }
desc_err: desc_err:
dma_unmap_sg(qup->dev, qup->btx.sg, tx_nents, DMA_TO_DEVICE); dma_unmap_sg(qup->dev, qup->btx.sg, tx_cnt, DMA_TO_DEVICE);
if (rx_nents) if (rx_cnt)
dma_unmap_sg(qup->dev, qup->brx.sg, rx_nents, dma_unmap_sg(qup->dev, qup->brx.sg, rx_cnt,
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
return ret; return ret;
} }
static void qup_i2c_bam_clear_tag_buffers(struct qup_i2c_dev *qup)
{
qup->btx.sg_cnt = 0;
qup->brx.sg_cnt = 0;
qup->tag_buf_pos = 0;
}
static int qup_i2c_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, static int qup_i2c_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
int num) int num)
{ {
struct qup_i2c_dev *qup = i2c_get_adapdata(adap); struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
int ret = 0; int ret = 0;
int idx = 0;
enable_irq(qup->irq); enable_irq(qup->irq);
ret = qup_i2c_req_dma(qup); ret = qup_i2c_req_dma(qup);
...@@ -903,9 +856,34 @@ static int qup_i2c_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, ...@@ -903,9 +856,34 @@ static int qup_i2c_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
goto out; goto out;
writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL); writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
qup_i2c_bam_clear_tag_buffers(qup);
for (idx = 0; idx < num; idx++) {
qup->msg = msg + idx;
qup->is_last = idx == (num - 1);
ret = qup_i2c_bam_make_desc(qup, qup->msg);
if (ret)
break;
/*
* Make DMA descriptor and schedule the BAM transfer if its
* already crossed the maximum length. Since the memory for all
* tags buffers have been taken for 2 maximum possible
* transfers length so it will never cross the buffer actual
* length.
*/
if (qup->btx.sg_cnt > qup->max_xfer_sg_len ||
qup->brx.sg_cnt > qup->max_xfer_sg_len ||
qup->is_last) {
ret = qup_i2c_bam_schedule_desc(qup);
if (ret)
break;
qup_i2c_bam_clear_tag_buffers(qup);
}
}
qup->msg = msg;
ret = qup_i2c_bam_do_xfer(qup, qup->msg, num);
out: out:
disable_irq(qup->irq); disable_irq(qup->irq);
...@@ -919,7 +897,7 @@ static int qup_i2c_wait_for_complete(struct qup_i2c_dev *qup, ...@@ -919,7 +897,7 @@ static int qup_i2c_wait_for_complete(struct qup_i2c_dev *qup,
unsigned long left; unsigned long left;
int ret = 0; int ret = 0;
left = wait_for_completion_timeout(&qup->xfer, HZ); left = wait_for_completion_timeout(&qup->xfer, qup->xfer_timeout);
if (!left) { if (!left) {
writel(1, qup->base + QUP_SW_RESET); writel(1, qup->base + QUP_SW_RESET);
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
...@@ -931,363 +909,635 @@ static int qup_i2c_wait_for_complete(struct qup_i2c_dev *qup, ...@@ -931,363 +909,635 @@ static int qup_i2c_wait_for_complete(struct qup_i2c_dev *qup,
return ret; return ret;
} }
static int qup_i2c_write_one_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg) static void qup_i2c_read_rx_fifo_v1(struct qup_i2c_dev *qup)
{ {
int ret = 0; struct qup_i2c_block *blk = &qup->blk;
struct i2c_msg *msg = qup->msg;
u32 val = 0;
int idx = 0;
qup->msg = msg; while (blk->fifo_available && qup->pos < msg->len) {
qup->pos = 0; if ((idx & 1) == 0) {
enable_irq(qup->irq); /* Reading 2 words at time */
qup_i2c_set_blk_data(qup, msg); val = readl(qup->base + QUP_IN_FIFO_BASE);
qup_i2c_set_write_mode_v2(qup, msg); msg->buf[qup->pos++] = val & 0xFF;
} else {
msg->buf[qup->pos++] = val >> QUP_MSW_SHIFT;
}
idx++;
blk->fifo_available--;
}
ret = qup_i2c_change_state(qup, QUP_RUN_STATE); if (qup->pos == msg->len)
if (ret) blk->rx_bytes_read = true;
goto err; }
writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL); static void qup_i2c_write_rx_tags_v1(struct qup_i2c_dev *qup)
{
struct i2c_msg *msg = qup->msg;
u32 addr, len, val;
do { addr = i2c_8bit_addr_from_msg(msg);
ret = qup_i2c_issue_xfer_v2(qup, msg);
if (ret)
goto err;
ret = qup_i2c_wait_for_complete(qup, msg); /* 0 is used to specify a length 256 (QUP_READ_LIMIT) */
if (ret) len = (msg->len == QUP_READ_LIMIT) ? 0 : msg->len;
goto err;
val = ((QUP_TAG_REC | len) << QUP_MSW_SHIFT) | QUP_TAG_START | addr;
writel(val, qup->base + QUP_OUT_FIFO_BASE);
}
qup->blk.pos++; static void qup_i2c_conf_v1(struct qup_i2c_dev *qup)
} while (qup->blk.pos < qup->blk.count); {
struct qup_i2c_block *blk = &qup->blk;
u32 qup_config = I2C_MINI_CORE | I2C_N_VAL;
u32 io_mode = QUP_REPACK_EN;
blk->is_tx_blk_mode =
blk->total_tx_len > qup->out_fifo_sz ? true : false;
blk->is_rx_blk_mode =
blk->total_rx_len > qup->in_fifo_sz ? true : false;
if (blk->is_tx_blk_mode) {
io_mode |= QUP_OUTPUT_BLK_MODE;
writel(0, qup->base + QUP_MX_WRITE_CNT);
writel(blk->total_tx_len, qup->base + QUP_MX_OUTPUT_CNT);
} else {
writel(0, qup->base + QUP_MX_OUTPUT_CNT);
writel(blk->total_tx_len, qup->base + QUP_MX_WRITE_CNT);
}
ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT, ONE_BYTE); if (blk->total_rx_len) {
if (blk->is_rx_blk_mode) {
io_mode |= QUP_INPUT_BLK_MODE;
writel(0, qup->base + QUP_MX_READ_CNT);
writel(blk->total_rx_len, qup->base + QUP_MX_INPUT_CNT);
} else {
writel(0, qup->base + QUP_MX_INPUT_CNT);
writel(blk->total_rx_len, qup->base + QUP_MX_READ_CNT);
}
} else {
qup_config |= QUP_NO_INPUT;
}
err: writel(qup_config, qup->base + QUP_CONFIG);
disable_irq(qup->irq); writel(io_mode, qup->base + QUP_IO_MODE);
qup->msg = NULL; }
return ret; static void qup_i2c_clear_blk_v1(struct qup_i2c_block *blk)
{
blk->tx_fifo_free = 0;
blk->fifo_available = 0;
blk->rx_bytes_read = false;
} }
static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg) static int qup_i2c_conf_xfer_v1(struct qup_i2c_dev *qup, bool is_rx)
{ {
struct qup_i2c_block *blk = &qup->blk;
int ret; int ret;
qup->msg = msg; qup_i2c_clear_blk_v1(blk);
qup->pos = 0; qup_i2c_conf_v1(qup);
enable_irq(qup->irq);
qup_i2c_set_write_mode(qup, msg);
ret = qup_i2c_change_state(qup, QUP_RUN_STATE); ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
if (ret) if (ret)
goto err; return ret;
writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL); writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
do {
ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE); ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
if (ret) if (ret)
goto err; return ret;
ret = qup_i2c_issue_write(qup, msg); reinit_completion(&qup->xfer);
if (ret) enable_irq(qup->irq);
goto err; if (!blk->is_tx_blk_mode) {
blk->tx_fifo_free = qup->out_fifo_sz;
if (is_rx)
qup_i2c_write_rx_tags_v1(qup);
else
qup_i2c_write_tx_fifo_v1(qup);
}
ret = qup_i2c_change_state(qup, QUP_RUN_STATE); ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
if (ret) if (ret)
goto err; goto err;
ret = qup_i2c_wait_for_complete(qup, msg); ret = qup_i2c_wait_for_complete(qup, qup->msg);
if (ret) if (ret)
goto err; goto err;
} while (qup->pos < msg->len);
/* Wait for the outstanding data in the fifo to drain */ ret = qup_i2c_bus_active(qup, ONE_BYTE);
ret = qup_i2c_wait_ready(qup, QUP_OUT_NOT_EMPTY, RESET_BIT, ONE_BYTE);
err: err:
disable_irq(qup->irq); disable_irq(qup->irq);
qup->msg = NULL;
return ret; return ret;
} }
static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len) static int qup_i2c_write_one(struct qup_i2c_dev *qup)
{ {
if (len < qup->in_fifo_sz) { struct i2c_msg *msg = qup->msg;
/* FIFO mode */ struct qup_i2c_block *blk = &qup->blk;
writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE);
writel(len, qup->base + QUP_MX_READ_CNT); qup->pos = 0;
} else { blk->total_tx_len = msg->len + 1;
/* BLOCK mode (transfer data on chunks) */ blk->total_rx_len = 0;
writel(QUP_INPUT_BLK_MODE | QUP_REPACK_EN,
qup->base + QUP_IO_MODE); return qup_i2c_conf_xfer_v1(qup, false);
writel(len, qup->base + QUP_MX_INPUT_CNT); }
static int qup_i2c_read_one(struct qup_i2c_dev *qup)
{
struct qup_i2c_block *blk = &qup->blk;
qup->pos = 0;
blk->total_tx_len = 2;
blk->total_rx_len = qup->msg->len;
return qup_i2c_conf_xfer_v1(qup, true);
}
static int qup_i2c_xfer(struct i2c_adapter *adap,
struct i2c_msg msgs[],
int num)
{
struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
int ret, idx;
ret = pm_runtime_get_sync(qup->dev);
if (ret < 0)
goto out;
qup->bus_err = 0;
qup->qup_err = 0;
writel(1, qup->base + QUP_SW_RESET);
ret = qup_i2c_poll_state(qup, QUP_RESET_STATE);
if (ret)
goto out;
/* Configure QUP as I2C mini core */
writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG);
for (idx = 0; idx < num; idx++) {
if (msgs[idx].len == 0) {
ret = -EINVAL;
goto out;
}
if (qup_i2c_poll_state_i2c_master(qup)) {
ret = -EIO;
goto out;
}
if (qup_i2c_check_msg_len(&msgs[idx])) {
ret = -EINVAL;
goto out;
}
qup->msg = &msgs[idx];
if (msgs[idx].flags & I2C_M_RD)
ret = qup_i2c_read_one(qup);
else
ret = qup_i2c_write_one(qup);
if (ret)
break;
ret = qup_i2c_change_state(qup, QUP_RESET_STATE);
if (ret)
break;
} }
if (ret == 0)
ret = num;
out:
pm_runtime_mark_last_busy(qup->dev);
pm_runtime_put_autosuspend(qup->dev);
return ret;
} }
static void qup_i2c_set_read_mode_v2(struct qup_i2c_dev *qup, int len) /*
* Configure registers related with reconfiguration during run and call it
* before each i2c sub transfer.
*/
static void qup_i2c_conf_count_v2(struct qup_i2c_dev *qup)
{ {
int tx_len = qup->blk.tx_tag_len; struct qup_i2c_block *blk = &qup->blk;
u32 qup_config = I2C_MINI_CORE | I2C_N_VAL_V2;
len += qup->blk.rx_tag_len; if (blk->is_tx_blk_mode)
len |= qup->config_run; writel(qup->config_run | blk->total_tx_len,
tx_len |= qup->config_run; qup->base + QUP_MX_OUTPUT_CNT);
else
writel(qup->config_run | blk->total_tx_len,
qup->base + QUP_MX_WRITE_CNT);
if (len < qup->in_fifo_sz) { if (blk->total_rx_len) {
/* FIFO mode */ if (blk->is_rx_blk_mode)
writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE); writel(qup->config_run | blk->total_rx_len,
writel(tx_len, qup->base + QUP_MX_WRITE_CNT); qup->base + QUP_MX_INPUT_CNT);
writel(len, qup->base + QUP_MX_READ_CNT); else
writel(qup->config_run | blk->total_rx_len,
qup->base + QUP_MX_READ_CNT);
} else { } else {
/* BLOCK mode (transfer data on chunks) */ qup_config |= QUP_NO_INPUT;
writel(QUP_INPUT_BLK_MODE | QUP_REPACK_EN,
qup->base + QUP_IO_MODE);
writel(tx_len, qup->base + QUP_MX_OUTPUT_CNT);
writel(len, qup->base + QUP_MX_INPUT_CNT);
} }
writel(qup_config, qup->base + QUP_CONFIG);
} }
static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg *msg) /*
* Configure registers related with transfer mode (FIFO/Block)
* before starting of i2c transfer. It will be called only once in
* QUP RESET state.
*/
static void qup_i2c_conf_mode_v2(struct qup_i2c_dev *qup)
{ {
u32 addr, len, val; struct qup_i2c_block *blk = &qup->blk;
u32 io_mode = QUP_REPACK_EN;
addr = i2c_8bit_addr_from_msg(msg); if (blk->is_tx_blk_mode) {
io_mode |= QUP_OUTPUT_BLK_MODE;
writel(0, qup->base + QUP_MX_WRITE_CNT);
} else {
writel(0, qup->base + QUP_MX_OUTPUT_CNT);
}
/* 0 is used to specify a length 256 (QUP_READ_LIMIT) */ if (blk->is_rx_blk_mode) {
len = (msg->len == QUP_READ_LIMIT) ? 0 : msg->len; io_mode |= QUP_INPUT_BLK_MODE;
writel(0, qup->base + QUP_MX_READ_CNT);
} else {
writel(0, qup->base + QUP_MX_INPUT_CNT);
}
val = ((QUP_TAG_REC | len) << QUP_MSW_SHIFT) | QUP_TAG_START | addr; writel(io_mode, qup->base + QUP_IO_MODE);
writel(val, qup->base + QUP_OUT_FIFO_BASE);
} }
/* Clear required variables before starting of any QUP v2 sub transfer. */
static void qup_i2c_clear_blk_v2(struct qup_i2c_block *blk)
{
blk->send_last_word = false;
blk->tx_tags_sent = false;
blk->tx_fifo_data = 0;
blk->tx_fifo_data_pos = 0;
blk->tx_fifo_free = 0;
blk->rx_tags_fetched = false;
blk->rx_bytes_read = false;
blk->rx_fifo_data = 0;
blk->rx_fifo_data_pos = 0;
blk->fifo_available = 0;
}
static int qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg) /* Receive data from RX FIFO for read message in QUP v2 i2c transfer. */
static void qup_i2c_recv_data(struct qup_i2c_dev *qup)
{ {
u32 val = 0; struct qup_i2c_block *blk = &qup->blk;
int idx; int j;
int ret = 0;
for (idx = 0; qup->pos < msg->len; idx++) { for (j = blk->rx_fifo_data_pos;
if ((idx & 1) == 0) { blk->cur_blk_len && blk->fifo_available;
/* Check that FIFO have data */ blk->cur_blk_len--, blk->fifo_available--) {
ret = qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY, if (j == 0)
SET_BIT, 4 * ONE_BYTE); blk->rx_fifo_data = readl(qup->base + QUP_IN_FIFO_BASE);
if (ret)
return ret;
/* Reading 2 words at time */ *(blk->cur_data++) = blk->rx_fifo_data;
val = readl(qup->base + QUP_IN_FIFO_BASE); blk->rx_fifo_data >>= 8;
msg->buf[qup->pos++] = val & 0xFF; if (j == 3)
} else { j = 0;
msg->buf[qup->pos++] = val >> QUP_MSW_SHIFT; else
} j++;
} }
return ret; blk->rx_fifo_data_pos = j;
} }
static int qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup, /* Receive tags for read message in QUP v2 i2c transfer. */
struct i2c_msg *msg) static void qup_i2c_recv_tags(struct qup_i2c_dev *qup)
{ {
u32 val; struct qup_i2c_block *blk = &qup->blk;
int idx, pos = 0, ret = 0, total, msg_offset = 0;
/* blk->rx_fifo_data = readl(qup->base + QUP_IN_FIFO_BASE);
* If the message length is already read in blk->rx_fifo_data >>= blk->rx_tag_len * 8;
* the first byte of the buffer, account for blk->rx_fifo_data_pos = blk->rx_tag_len;
* that by setting the offset blk->fifo_available -= blk->rx_tag_len;
}
/*
* Read the data and tags from RX FIFO. Since in read case, the tags will be
* preceded by received data bytes so
* 1. Check if rx_tags_fetched is false i.e. the start of QUP block so receive
* all tag bytes and discard that.
* 2. Read the data from RX FIFO. When all the data bytes have been read then
* set rx_bytes_read to true.
*/ */
if (qup_i2c_check_msg_len(msg) && (msg->len > 1)) static void qup_i2c_read_rx_fifo_v2(struct qup_i2c_dev *qup)
msg_offset = 1; {
total = qup_i2c_get_data_len(qup); struct qup_i2c_block *blk = &qup->blk;
total -= msg_offset;
if (!blk->rx_tags_fetched) {
/* 2 extra bytes for read tags */ qup_i2c_recv_tags(qup);
while (pos < (total + 2)) { blk->rx_tags_fetched = true;
/* Check that FIFO have data */
ret = qup_i2c_wait_ready(qup, QUP_IN_NOT_EMPTY,
SET_BIT, 4 * ONE_BYTE);
if (ret) {
dev_err(qup->dev, "timeout for fifo not empty");
return ret;
} }
val = readl(qup->base + QUP_IN_FIFO_BASE);
for (idx = 0; idx < 4; idx++, val >>= 8, pos++) { qup_i2c_recv_data(qup);
/* first 2 bytes are tag bytes */ if (!blk->cur_blk_len)
if (pos < 2) blk->rx_bytes_read = true;
continue; }
if (pos >= (total + 2)) /*
goto out; * Write bytes in TX FIFO for write message in QUP v2 i2c transfer. QUP TX FIFO
msg->buf[qup->pos + msg_offset] = val & 0xff; * write works on word basis (4 bytes). Append new data byte write for TX FIFO
qup->pos++; * in tx_fifo_data and write to TX FIFO when all the 4 bytes are present.
*/
static void
qup_i2c_write_blk_data(struct qup_i2c_dev *qup, u8 **data, unsigned int *len)
{
struct qup_i2c_block *blk = &qup->blk;
unsigned int j;
for (j = blk->tx_fifo_data_pos; *len && blk->tx_fifo_free;
(*len)--, blk->tx_fifo_free--) {
blk->tx_fifo_data |= *(*data)++ << (j * 8);
if (j == 3) {
writel(blk->tx_fifo_data,
qup->base + QUP_OUT_FIFO_BASE);
blk->tx_fifo_data = 0x0;
j = 0;
} else {
j++;
} }
} }
out: blk->tx_fifo_data_pos = j;
qup->blk.data_len -= total;
return ret;
} }
static int qup_i2c_read_one_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg) /* Transfer tags for read message in QUP v2 i2c transfer. */
static void qup_i2c_write_rx_tags_v2(struct qup_i2c_dev *qup)
{ {
int ret = 0; struct qup_i2c_block *blk = &qup->blk;
qup->msg = msg; qup_i2c_write_blk_data(qup, &blk->cur_tx_tags, &blk->tx_tag_len);
qup->pos = 0; if (blk->tx_fifo_data_pos)
enable_irq(qup->irq); writel(blk->tx_fifo_data, qup->base + QUP_OUT_FIFO_BASE);
qup_i2c_set_blk_data(qup, msg); }
qup_i2c_set_read_mode_v2(qup, msg->len);
ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
if (ret)
goto err;
writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL); /*
* Write the data and tags in TX FIFO. Since in write case, both tags and data
* need to be written and QUP write tags can have maximum 256 data length, so
*
* 1. Check if tx_tags_sent is false i.e. the start of QUP block so write the
* tags to TX FIFO and set tx_tags_sent to true.
* 2. Check if send_last_word is true. It will be set when last few data bytes
* (less than 4 bytes) are reamining to be written in FIFO because of no FIFO
* space. All this data bytes are available in tx_fifo_data so write this
* in FIFO.
* 3. Write the data to TX FIFO and check for cur_blk_len. If it is non zero
* then more data is pending otherwise following 3 cases can be possible
* a. if tx_fifo_data_pos is zero i.e. all the data bytes in this block
* have been written in TX FIFO so nothing else is required.
* b. tx_fifo_free is non zero i.e tx FIFO is free so copy the remaining data
* from tx_fifo_data to tx FIFO. Since, qup_i2c_write_blk_data do write
* in 4 bytes and FIFO space is in multiple of 4 bytes so tx_fifo_free
* will be always greater than or equal to 4 bytes.
* c. tx_fifo_free is zero. In this case, last few bytes (less than 4
* bytes) are copied to tx_fifo_data but couldn't be sent because of
* FIFO full so make send_last_word true.
*/
static void qup_i2c_write_tx_fifo_v2(struct qup_i2c_dev *qup)
{
struct qup_i2c_block *blk = &qup->blk;
do { if (!blk->tx_tags_sent) {
ret = qup_i2c_issue_xfer_v2(qup, msg); qup_i2c_write_blk_data(qup, &blk->cur_tx_tags,
if (ret) &blk->tx_tag_len);
goto err; blk->tx_tags_sent = true;
}
ret = qup_i2c_wait_for_complete(qup, msg); if (blk->send_last_word)
if (ret) goto send_last_word;
goto err;
ret = qup_i2c_read_fifo_v2(qup, msg); qup_i2c_write_blk_data(qup, &blk->cur_data, &blk->cur_blk_len);
if (ret) if (!blk->cur_blk_len) {
goto err; if (!blk->tx_fifo_data_pos)
return;
qup->blk.pos++; if (blk->tx_fifo_free)
goto send_last_word;
/* Handle SMBus block read length */ blk->send_last_word = true;
if (qup_i2c_check_msg_len(msg) && (msg->len == 1)) {
if (msg->buf[0] > I2C_SMBUS_BLOCK_MAX) {
ret = -EPROTO;
goto err;
}
msg->len += msg->buf[0];
qup->pos = 0;
qup_i2c_set_blk_data(qup, msg);
/* set tag length for block read */
qup->blk.tx_tag_len = 2;
qup_i2c_set_read_mode_v2(qup, msg->buf[0]);
} }
} while (qup->blk.pos < qup->blk.count);
err: return;
disable_irq(qup->irq);
qup->msg = NULL;
return ret; send_last_word:
writel(blk->tx_fifo_data, qup->base + QUP_OUT_FIFO_BASE);
} }
static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg) /*
* Main transfer function which read or write i2c data.
* The QUP v2 supports reconfiguration during run in which multiple i2c sub
* transfers can be scheduled.
*/
static int
qup_i2c_conf_xfer_v2(struct qup_i2c_dev *qup, bool is_rx, bool is_first,
bool change_pause_state)
{ {
struct qup_i2c_block *blk = &qup->blk;
struct i2c_msg *msg = qup->msg;
int ret; int ret;
qup->msg = msg; /*
qup->pos = 0; * Check if its SMBus Block read for which the top level read will be
* done into 2 QUP reads. One with message length 1 while other one is
* with actual length.
*/
if (qup_i2c_check_msg_len(msg)) {
if (qup->is_smbus_read) {
/*
* If the message length is already read in
* the first byte of the buffer, account for
* that by setting the offset
*/
blk->cur_data += 1;
is_first = false;
} else {
change_pause_state = false;
}
}
enable_irq(qup->irq); qup->config_run = is_first ? 0 : QUP_I2C_MX_CONFIG_DURING_RUN;
qup_i2c_set_read_mode(qup, msg->len);
qup_i2c_clear_blk_v2(blk);
qup_i2c_conf_count_v2(qup);
/* If it is first sub transfer, then configure i2c bus clocks */
if (is_first) {
ret = qup_i2c_change_state(qup, QUP_RUN_STATE); ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
if (ret) if (ret)
goto err; return ret;
writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL); writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL);
ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE); ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
if (ret) if (ret)
goto err; return ret;
}
qup_i2c_issue_read(qup, msg); reinit_completion(&qup->xfer);
enable_irq(qup->irq);
/*
* In FIFO mode, tx FIFO can be written directly while in block mode the
* it will be written after getting OUT_BLOCK_WRITE_REQ interrupt
*/
if (!blk->is_tx_blk_mode) {
blk->tx_fifo_free = qup->out_fifo_sz;
if (is_rx)
qup_i2c_write_rx_tags_v2(qup);
else
qup_i2c_write_tx_fifo_v2(qup);
}
ret = qup_i2c_change_state(qup, QUP_RUN_STATE); ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
if (ret) if (ret)
goto err; goto err;
do {
ret = qup_i2c_wait_for_complete(qup, msg); ret = qup_i2c_wait_for_complete(qup, msg);
if (ret) if (ret)
goto err; goto err;
ret = qup_i2c_read_fifo(qup, msg); /* Move to pause state for all the transfers, except last one */
if (change_pause_state) {
ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE);
if (ret) if (ret)
goto err; goto err;
} while (qup->pos < msg->len); }
err: err:
disable_irq(qup->irq); disable_irq(qup->irq);
qup->msg = NULL;
return ret; return ret;
} }
static int qup_i2c_xfer(struct i2c_adapter *adap, /*
struct i2c_msg msgs[], * Transfer one read/write message in i2c transfer. It splits the message into
int num) * multiple of blk_xfer_limit data length blocks and schedule each
* QUP block individually.
*/
static int qup_i2c_xfer_v2_msg(struct qup_i2c_dev *qup, int msg_id, bool is_rx)
{ {
struct qup_i2c_dev *qup = i2c_get_adapdata(adap); int ret = 0;
int ret, idx; unsigned int data_len, i;
struct i2c_msg *msg = qup->msg;
struct qup_i2c_block *blk = &qup->blk;
u8 *msg_buf = msg->buf;
ret = pm_runtime_get_sync(qup->dev); qup->blk_xfer_limit = is_rx ? RECV_MAX_DATA_LEN : QUP_READ_LIMIT;
if (ret < 0) qup_i2c_set_blk_data(qup, msg);
goto out;
qup->bus_err = 0; for (i = 0; i < blk->count; i++) {
qup->qup_err = 0; data_len = qup_i2c_get_data_len(qup);
blk->pos = i;
blk->cur_tx_tags = blk->tags;
blk->cur_blk_len = data_len;
blk->tx_tag_len =
qup_i2c_set_tags(blk->cur_tx_tags, qup, qup->msg);
blk->cur_data = msg_buf;
if (is_rx) {
blk->total_tx_len = blk->tx_tag_len;
blk->rx_tag_len = 2;
blk->total_rx_len = blk->rx_tag_len + data_len;
} else {
blk->total_tx_len = blk->tx_tag_len + data_len;
blk->total_rx_len = 0;
}
writel(1, qup->base + QUP_SW_RESET); ret = qup_i2c_conf_xfer_v2(qup, is_rx, !msg_id && !i,
ret = qup_i2c_poll_state(qup, QUP_RESET_STATE); !qup->is_last || i < blk->count - 1);
if (ret) if (ret)
goto out; return ret;
/* Configure QUP as I2C mini core */ /* Handle SMBus block read length */
writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG); if (qup_i2c_check_msg_len(msg) && msg->len == 1 &&
!qup->is_smbus_read) {
if (msg->buf[0] > I2C_SMBUS_BLOCK_MAX)
return -EPROTO;
msg->len = msg->buf[0];
qup->is_smbus_read = true;
ret = qup_i2c_xfer_v2_msg(qup, msg_id, true);
qup->is_smbus_read = false;
if (ret)
return ret;
for (idx = 0; idx < num; idx++) { msg->len += 1;
if (msgs[idx].len == 0) {
ret = -EINVAL;
goto out;
} }
if (qup_i2c_poll_state_i2c_master(qup)) { msg_buf += data_len;
ret = -EIO; blk->data_len -= qup->blk_xfer_limit;
goto out;
} }
if (qup_i2c_check_msg_len(&msgs[idx])) { return ret;
ret = -EINVAL; }
goto out;
} /*
* QUP v2 supports 3 modes
* Programmed IO using FIFO mode : Less than FIFO size
* Programmed IO using Block mode : Greater than FIFO size
* DMA using BAM : Appropriate for any transaction size but the address should
* be DMA applicable
*
* This function determines the mode which will be used for this transfer. An
* i2c transfer contains multiple message. Following are the rules to determine
* the mode used.
* 1. Determine complete length, maximum tx and rx length for complete transfer.
* 2. If complete transfer length is greater than fifo size then use the DMA
* mode.
* 3. In FIFO or block mode, tx and rx can operate in different mode so check
* for maximum tx and rx length to determine mode.
*/
static int
qup_i2c_determine_mode_v2(struct qup_i2c_dev *qup,
struct i2c_msg msgs[], int num)
{
int idx;
bool no_dma = false;
unsigned int max_tx_len = 0, max_rx_len = 0, total_len = 0;
/* All i2c_msgs should be transferred using either dma or cpu */
for (idx = 0; idx < num; idx++) {
if (msgs[idx].len == 0)
return -EINVAL;
if (msgs[idx].flags & I2C_M_RD) if (msgs[idx].flags & I2C_M_RD)
ret = qup_i2c_read_one(qup, &msgs[idx]); max_rx_len = max_t(unsigned int, max_rx_len,
msgs[idx].len);
else else
ret = qup_i2c_write_one(qup, &msgs[idx]); max_tx_len = max_t(unsigned int, max_tx_len,
msgs[idx].len);
if (ret) if (is_vmalloc_addr(msgs[idx].buf))
break; no_dma = true;
ret = qup_i2c_change_state(qup, QUP_RESET_STATE); total_len += msgs[idx].len;
if (ret)
break;
} }
if (ret == 0) if (!no_dma && qup->is_dma &&
ret = num; (total_len > qup->out_fifo_sz || total_len > qup->in_fifo_sz)) {
out: qup->use_dma = true;
} else {
pm_runtime_mark_last_busy(qup->dev); qup->blk.is_tx_blk_mode = max_tx_len > qup->out_fifo_sz -
pm_runtime_put_autosuspend(qup->dev); QUP_MAX_TAGS_LEN ? true : false;
qup->blk.is_rx_blk_mode = max_rx_len > qup->in_fifo_sz -
READ_RX_TAGS_LEN ? true : false;
}
return ret; return 0;
} }
static int qup_i2c_xfer_v2(struct i2c_adapter *adap, static int qup_i2c_xfer_v2(struct i2c_adapter *adap,
...@@ -1295,7 +1545,7 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap, ...@@ -1295,7 +1545,7 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap,
int num) int num)
{ {
struct qup_i2c_dev *qup = i2c_get_adapdata(adap); struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
int ret, len, idx = 0, use_dma = 0; int ret, idx = 0;
qup->bus_err = 0; qup->bus_err = 0;
qup->qup_err = 0; qup->qup_err = 0;
...@@ -1304,6 +1554,10 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap, ...@@ -1304,6 +1554,10 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap,
if (ret < 0) if (ret < 0)
goto out; goto out;
ret = qup_i2c_determine_mode_v2(qup, msgs, num);
if (ret)
goto out;
writel(1, qup->base + QUP_SW_RESET); writel(1, qup->base + QUP_SW_RESET);
ret = qup_i2c_poll_state(qup, QUP_RESET_STATE); ret = qup_i2c_poll_state(qup, QUP_RESET_STATE);
if (ret) if (ret)
...@@ -1313,59 +1567,35 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap, ...@@ -1313,59 +1567,35 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap,
writel(I2C_MINI_CORE | I2C_N_VAL_V2, qup->base + QUP_CONFIG); writel(I2C_MINI_CORE | I2C_N_VAL_V2, qup->base + QUP_CONFIG);
writel(QUP_V2_TAGS_EN, qup->base + QUP_I2C_MASTER_GEN); writel(QUP_V2_TAGS_EN, qup->base + QUP_I2C_MASTER_GEN);
if ((qup->is_dma)) { if (qup_i2c_poll_state_i2c_master(qup)) {
/* All i2c_msgs should be transferred using either dma or cpu */ ret = -EIO;
for (idx = 0; idx < num; idx++) {
if (msgs[idx].len == 0) {
ret = -EINVAL;
goto out; goto out;
} }
len = (msgs[idx].len > qup->out_fifo_sz) || if (qup->use_dma) {
(msgs[idx].len > qup->in_fifo_sz); reinit_completion(&qup->xfer);
ret = qup_i2c_bam_xfer(adap, &msgs[0], num);
if ((!is_vmalloc_addr(msgs[idx].buf)) && len) { qup->use_dma = false;
use_dma = 1;
} else { } else {
use_dma = 0; qup_i2c_conf_mode_v2(qup);
break;
}
}
}
idx = 0; for (idx = 0; idx < num; idx++) {
qup->msg = &msgs[idx];
qup->is_last = idx == (num - 1);
do { ret = qup_i2c_xfer_v2_msg(qup, idx,
if (msgs[idx].len == 0) { !!(msgs[idx].flags & I2C_M_RD));
ret = -EINVAL; if (ret)
goto out; break;
} }
qup->msg = NULL;
if (qup_i2c_poll_state_i2c_master(qup)) {
ret = -EIO;
goto out;
} }
qup->is_last = (idx == (num - 1)); if (!ret)
if (idx) ret = qup_i2c_bus_active(qup, ONE_BYTE);
qup->config_run = QUP_I2C_MX_CONFIG_DURING_RUN;
else
qup->config_run = 0;
reinit_completion(&qup->xfer);
if (use_dma) {
ret = qup_i2c_bam_xfer(adap, &msgs[idx], num);
} else {
if (msgs[idx].flags & I2C_M_RD)
ret = qup_i2c_read_one_v2(qup, &msgs[idx]);
else
ret = qup_i2c_write_one_v2(qup, &msgs[idx]);
}
} while ((idx++ < (num - 1)) && !use_dma && !ret);
if (!ret) if (!ret)
ret = qup_i2c_change_state(qup, QUP_RESET_STATE); qup_i2c_change_state(qup, QUP_RESET_STATE);
if (ret == 0) if (ret == 0)
ret = num; ret = num;
...@@ -1429,6 +1659,7 @@ static int qup_i2c_probe(struct platform_device *pdev) ...@@ -1429,6 +1659,7 @@ static int qup_i2c_probe(struct platform_device *pdev)
u32 src_clk_freq = DEFAULT_SRC_CLK; u32 src_clk_freq = DEFAULT_SRC_CLK;
u32 clk_freq = DEFAULT_CLK_FREQ; u32 clk_freq = DEFAULT_CLK_FREQ;
int blocks; int blocks;
bool is_qup_v1;
qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL); qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL);
if (!qup) if (!qup)
...@@ -1447,8 +1678,10 @@ static int qup_i2c_probe(struct platform_device *pdev) ...@@ -1447,8 +1678,10 @@ static int qup_i2c_probe(struct platform_device *pdev)
if (of_device_is_compatible(pdev->dev.of_node, "qcom,i2c-qup-v1.1.1")) { if (of_device_is_compatible(pdev->dev.of_node, "qcom,i2c-qup-v1.1.1")) {
qup->adap.algo = &qup_i2c_algo; qup->adap.algo = &qup_i2c_algo;
qup->adap.quirks = &qup_i2c_quirks; qup->adap.quirks = &qup_i2c_quirks;
is_qup_v1 = true;
} else { } else {
qup->adap.algo = &qup_i2c_algo_v2; qup->adap.algo = &qup_i2c_algo_v2;
is_qup_v1 = false;
ret = qup_i2c_req_dma(qup); ret = qup_i2c_req_dma(qup);
if (ret == -EPROBE_DEFER) if (ret == -EPROBE_DEFER)
...@@ -1456,7 +1689,8 @@ static int qup_i2c_probe(struct platform_device *pdev) ...@@ -1456,7 +1689,8 @@ static int qup_i2c_probe(struct platform_device *pdev)
else if (ret != 0) else if (ret != 0)
goto nodma; goto nodma;
blocks = (MX_BLOCKS << 1) + 1; qup->max_xfer_sg_len = (MX_BLOCKS << 1);
blocks = (MX_DMA_BLOCKS << 1) + 1;
qup->btx.sg = devm_kzalloc(&pdev->dev, qup->btx.sg = devm_kzalloc(&pdev->dev,
sizeof(*qup->btx.sg) * blocks, sizeof(*qup->btx.sg) * blocks,
GFP_KERNEL); GFP_KERNEL);
...@@ -1573,14 +1807,31 @@ static int qup_i2c_probe(struct platform_device *pdev) ...@@ -1573,14 +1807,31 @@ static int qup_i2c_probe(struct platform_device *pdev)
ret = -EIO; ret = -EIO;
goto fail; goto fail;
} }
qup->out_blk_sz = blk_sizes[size] / 2; qup->out_blk_sz = blk_sizes[size];
size = QUP_INPUT_BLOCK_SIZE(io_mode); size = QUP_INPUT_BLOCK_SIZE(io_mode);
if (size >= ARRAY_SIZE(blk_sizes)) { if (size >= ARRAY_SIZE(blk_sizes)) {
ret = -EIO; ret = -EIO;
goto fail; goto fail;
} }
qup->in_blk_sz = blk_sizes[size] / 2; qup->in_blk_sz = blk_sizes[size];
if (is_qup_v1) {
/*
* in QUP v1, QUP_CONFIG uses N as 15 i.e 16 bits constitutes a
* single transfer but the block size is in bytes so divide the
* in_blk_sz and out_blk_sz by 2
*/
qup->in_blk_sz /= 2;
qup->out_blk_sz /= 2;
qup->write_tx_fifo = qup_i2c_write_tx_fifo_v1;
qup->read_rx_fifo = qup_i2c_read_rx_fifo_v1;
qup->write_rx_tags = qup_i2c_write_rx_tags_v1;
} else {
qup->write_tx_fifo = qup_i2c_write_tx_fifo_v2;
qup->read_rx_fifo = qup_i2c_read_rx_fifo_v2;
qup->write_rx_tags = qup_i2c_write_rx_tags_v2;
}
size = QUP_OUTPUT_FIFO_SIZE(io_mode); size = QUP_OUTPUT_FIFO_SIZE(io_mode);
qup->out_fifo_sz = qup->out_blk_sz * (2 << size); qup->out_fifo_sz = qup->out_blk_sz * (2 << size);
...@@ -1598,6 +1849,8 @@ static int qup_i2c_probe(struct platform_device *pdev) ...@@ -1598,6 +1849,8 @@ static int qup_i2c_probe(struct platform_device *pdev)
*/ */
one_bit_t = (USEC_PER_SEC / clk_freq) + 1; one_bit_t = (USEC_PER_SEC / clk_freq) + 1;
qup->one_byte_t = one_bit_t * 9; qup->one_byte_t = one_bit_t * 9;
qup->xfer_timeout = TOUT_MIN * HZ +
usecs_to_jiffies(MX_DMA_TX_RX_LEN * qup->one_byte_t);
dev_dbg(qup->dev, "IN:block:%d, fifo:%d, OUT:block:%d, fifo:%d\n", dev_dbg(qup->dev, "IN:block:%d, fifo:%d, OUT:block:%d, fifo:%d\n",
qup->in_blk_sz, qup->in_fifo_sz, qup->in_blk_sz, qup->in_fifo_sz,
......
...@@ -102,8 +102,8 @@ ...@@ -102,8 +102,8 @@
#define RCAR_IRQ_RECV (MNR | MAL | MST | MAT | MDR) #define RCAR_IRQ_RECV (MNR | MAL | MST | MAT | MDR)
#define RCAR_IRQ_STOP (MST) #define RCAR_IRQ_STOP (MST)
#define RCAR_IRQ_ACK_SEND (~(MAT | MDE) & 0xFF) #define RCAR_IRQ_ACK_SEND (~(MAT | MDE) & 0x7F)
#define RCAR_IRQ_ACK_RECV (~(MAT | MDR) & 0xFF) #define RCAR_IRQ_ACK_RECV (~(MAT | MDR) & 0x7F)
#define ID_LAST_MSG (1 << 0) #define ID_LAST_MSG (1 << 0)
#define ID_FIRST_MSG (1 << 1) #define ID_FIRST_MSG (1 << 1)
......
...@@ -182,7 +182,8 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, ...@@ -182,7 +182,8 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
status = acpi_evaluate_object(smbus_cmi->handle, method, &input, status = acpi_evaluate_object(smbus_cmi->handle, method, &input,
&buffer); &buffer);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO, "Evaluating %s: %i", method, status)); acpi_handle_err(smbus_cmi->handle,
"Failed to evaluate %s: %i\n", method, status);
return -EIO; return -EIO;
} }
...@@ -190,19 +191,19 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, ...@@ -190,19 +191,19 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
if (pkg && pkg->type == ACPI_TYPE_PACKAGE) if (pkg && pkg->type == ACPI_TYPE_PACKAGE)
obj = pkg->package.elements; obj = pkg->package.elements;
else { else {
ACPI_ERROR((AE_INFO, "Invalid argument type")); acpi_handle_err(smbus_cmi->handle, "Invalid argument type\n");
result = -EIO; result = -EIO;
goto out; goto out;
} }
if (obj == NULL || obj->type != ACPI_TYPE_INTEGER) { if (obj == NULL || obj->type != ACPI_TYPE_INTEGER) {
ACPI_ERROR((AE_INFO, "Invalid argument type")); acpi_handle_err(smbus_cmi->handle, "Invalid argument type\n");
result = -EIO; result = -EIO;
goto out; goto out;
} }
result = obj->integer.value; result = obj->integer.value;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s return status: %i\n", acpi_handle_debug(smbus_cmi->handle, "%s return status: %i\n", method,
method, result)); result);
switch (result) { switch (result) {
case ACPI_SMBUS_STATUS_OK: case ACPI_SMBUS_STATUS_OK:
...@@ -227,7 +228,7 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, ...@@ -227,7 +228,7 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
obj = pkg->package.elements + 1; obj = pkg->package.elements + 1;
if (obj->type != ACPI_TYPE_INTEGER) { if (obj->type != ACPI_TYPE_INTEGER) {
ACPI_ERROR((AE_INFO, "Invalid argument type")); acpi_handle_err(smbus_cmi->handle, "Invalid argument type\n");
result = -EIO; result = -EIO;
goto out; goto out;
} }
...@@ -239,7 +240,8 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, ...@@ -239,7 +240,8 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
case I2C_SMBUS_BYTE_DATA: case I2C_SMBUS_BYTE_DATA:
case I2C_SMBUS_WORD_DATA: case I2C_SMBUS_WORD_DATA:
if (obj->type != ACPI_TYPE_INTEGER) { if (obj->type != ACPI_TYPE_INTEGER) {
ACPI_ERROR((AE_INFO, "Invalid argument type")); acpi_handle_err(smbus_cmi->handle,
"Invalid argument type\n");
result = -EIO; result = -EIO;
goto out; goto out;
} }
...@@ -250,7 +252,8 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, ...@@ -250,7 +252,8 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
break; break;
case I2C_SMBUS_BLOCK_DATA: case I2C_SMBUS_BLOCK_DATA:
if (obj->type != ACPI_TYPE_BUFFER) { if (obj->type != ACPI_TYPE_BUFFER) {
ACPI_ERROR((AE_INFO, "Invalid argument type")); acpi_handle_err(smbus_cmi->handle,
"Invalid argument type\n");
result = -EIO; result = -EIO;
goto out; goto out;
} }
...@@ -300,6 +303,7 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi, ...@@ -300,6 +303,7 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi,
const char *name) const char *name)
{ {
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_handle *handle = smbus_cmi->handle;
union acpi_object *obj; union acpi_object *obj;
acpi_status status; acpi_status status;
...@@ -308,8 +312,8 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi, ...@@ -308,8 +312,8 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi,
smbus_cmi->methods->mt_info, smbus_cmi->methods->mt_info,
NULL, &buffer); NULL, &buffer);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO, "Evaluating %s: %i", acpi_handle_err(handle, "Failed to evaluate %s: %i\n",
smbus_cmi->methods->mt_info, status)); smbus_cmi->methods->mt_info, status);
return -EIO; return -EIO;
} }
...@@ -317,18 +321,18 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi, ...@@ -317,18 +321,18 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi,
if (obj && obj->type == ACPI_TYPE_PACKAGE) if (obj && obj->type == ACPI_TYPE_PACKAGE)
obj = obj->package.elements; obj = obj->package.elements;
else { else {
ACPI_ERROR((AE_INFO, "Invalid argument type")); acpi_handle_err(handle, "Invalid argument type\n");
kfree(buffer.pointer); kfree(buffer.pointer);
return -EIO; return -EIO;
} }
if (obj->type != ACPI_TYPE_INTEGER) { if (obj->type != ACPI_TYPE_INTEGER) {
ACPI_ERROR((AE_INFO, "Invalid argument type")); acpi_handle_err(handle, "Invalid argument type\n");
kfree(buffer.pointer); kfree(buffer.pointer);
return -EIO; return -EIO;
} else } else
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SMBus CMI Version %x" acpi_handle_debug(handle, "SMBus CMI Version %x\n",
"\n", (int)obj->integer.value)); (int)obj->integer.value);
kfree(buffer.pointer); kfree(buffer.pointer);
smbus_cmi->cap_info = 1; smbus_cmi->cap_info = 1;
...@@ -337,8 +341,7 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi, ...@@ -337,8 +341,7 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi,
else if (!strcmp(name, smbus_cmi->methods->mt_sbw)) else if (!strcmp(name, smbus_cmi->methods->mt_sbw))
smbus_cmi->cap_write = 1; smbus_cmi->cap_write = 1;
else else
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported CMI method: %s\n", acpi_handle_debug(handle, "Unsupported CMI method: %s\n", name);
name));
return 0; return 0;
} }
......
...@@ -349,7 +349,7 @@ static void stm32f4_i2c_read_msg(struct stm32f4_i2c_dev *i2c_dev) ...@@ -349,7 +349,7 @@ static void stm32f4_i2c_read_msg(struct stm32f4_i2c_dev *i2c_dev)
static void stm32f4_i2c_terminate_xfer(struct stm32f4_i2c_dev *i2c_dev) static void stm32f4_i2c_terminate_xfer(struct stm32f4_i2c_dev *i2c_dev)
{ {
struct stm32f4_i2c_msg *msg = &i2c_dev->msg; struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2; void __iomem *reg;
stm32f4_i2c_disable_irq(i2c_dev); stm32f4_i2c_disable_irq(i2c_dev);
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2012 FUJITSU SEMICONDUCTOR LIMITED
*/
#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#define WAIT_PCLK(n, rate) \
ndelay(DIV_ROUND_UP(DIV_ROUND_UP(1000000000, rate), n) + 10)
/* I2C register address definitions */
#define SYNQUACER_I2C_REG_BSR (0x00 << 2) // Bus Status
#define SYNQUACER_I2C_REG_BCR (0x01 << 2) // Bus Control
#define SYNQUACER_I2C_REG_CCR (0x02 << 2) // Clock Control
#define SYNQUACER_I2C_REG_ADR (0x03 << 2) // Address
#define SYNQUACER_I2C_REG_DAR (0x04 << 2) // Data
#define SYNQUACER_I2C_REG_CSR (0x05 << 2) // Expansion CS
#define SYNQUACER_I2C_REG_FSR (0x06 << 2) // Bus Clock Freq
#define SYNQUACER_I2C_REG_BC2R (0x07 << 2) // Bus Control 2
/* I2C register bit definitions */
#define SYNQUACER_I2C_BSR_FBT BIT(0) // First Byte Transfer
#define SYNQUACER_I2C_BSR_GCA BIT(1) // General Call Address
#define SYNQUACER_I2C_BSR_AAS BIT(2) // Address as Slave
#define SYNQUACER_I2C_BSR_TRX BIT(3) // Transfer/Receive
#define SYNQUACER_I2C_BSR_LRB BIT(4) // Last Received Bit
#define SYNQUACER_I2C_BSR_AL BIT(5) // Arbitration Lost
#define SYNQUACER_I2C_BSR_RSC BIT(6) // Repeated Start Cond.
#define SYNQUACER_I2C_BSR_BB BIT(7) // Bus Busy
#define SYNQUACER_I2C_BCR_INT BIT(0) // Interrupt
#define SYNQUACER_I2C_BCR_INTE BIT(1) // Interrupt Enable
#define SYNQUACER_I2C_BCR_GCAA BIT(2) // Gen. Call Access Ack.
#define SYNQUACER_I2C_BCR_ACK BIT(3) // Acknowledge
#define SYNQUACER_I2C_BCR_MSS BIT(4) // Master Slave Select
#define SYNQUACER_I2C_BCR_SCC BIT(5) // Start Condition Cont.
#define SYNQUACER_I2C_BCR_BEIE BIT(6) // Bus Error Int Enable
#define SYNQUACER_I2C_BCR_BER BIT(7) // Bus Error
#define SYNQUACER_I2C_CCR_CS_MASK (0x1f) // CCR Clock Period Sel.
#define SYNQUACER_I2C_CCR_EN BIT(5) // Enable
#define SYNQUACER_I2C_CCR_FM BIT(6) // Speed Mode Select
#define SYNQUACER_I2C_CSR_CS_MASK (0x3f) // CSR Clock Period Sel.
#define SYNQUACER_I2C_BC2R_SCLL BIT(0) // SCL Low Drive
#define SYNQUACER_I2C_BC2R_SDAL BIT(1) // SDA Low Drive
#define SYNQUACER_I2C_BC2R_SCLS BIT(4) // SCL Status
#define SYNQUACER_I2C_BC2R_SDAS BIT(5) // SDA Status
/* PCLK frequency */
#define SYNQUACER_I2C_BUS_CLK_FR(rate) (((rate) / 20000000) + 1)
/* STANDARD MODE frequency */
#define SYNQUACER_I2C_CLK_MASTER_STD(rate) \
DIV_ROUND_UP(DIV_ROUND_UP((rate), 100000) - 2, 2)
/* FAST MODE frequency */
#define SYNQUACER_I2C_CLK_MASTER_FAST(rate) \
DIV_ROUND_UP((DIV_ROUND_UP((rate), 400000) - 2) * 2, 3)
/* (clkrate <= 18000000) */
/* calculate the value of CS bits in CCR register on standard mode */
#define SYNQUACER_I2C_CCR_CS_STD_MAX_18M(rate) \
((SYNQUACER_I2C_CLK_MASTER_STD(rate) - 65) \
& SYNQUACER_I2C_CCR_CS_MASK)
/* calculate the value of CS bits in CSR register on standard mode */
#define SYNQUACER_I2C_CSR_CS_STD_MAX_18M(rate) 0x00
/* calculate the value of CS bits in CCR register on fast mode */
#define SYNQUACER_I2C_CCR_CS_FAST_MAX_18M(rate) \
((SYNQUACER_I2C_CLK_MASTER_FAST(rate) - 1) \
& SYNQUACER_I2C_CCR_CS_MASK)
/* calculate the value of CS bits in CSR register on fast mode */
#define SYNQUACER_I2C_CSR_CS_FAST_MAX_18M(rate) 0x00
/* (clkrate > 18000000) */
/* calculate the value of CS bits in CCR register on standard mode */
#define SYNQUACER_I2C_CCR_CS_STD_MIN_18M(rate) \
((SYNQUACER_I2C_CLK_MASTER_STD(rate) - 1) \
& SYNQUACER_I2C_CCR_CS_MASK)
/* calculate the value of CS bits in CSR register on standard mode */
#define SYNQUACER_I2C_CSR_CS_STD_MIN_18M(rate) \
(((SYNQUACER_I2C_CLK_MASTER_STD(rate) - 1) >> 5) \
& SYNQUACER_I2C_CSR_CS_MASK)
/* calculate the value of CS bits in CCR register on fast mode */
#define SYNQUACER_I2C_CCR_CS_FAST_MIN_18M(rate) \
((SYNQUACER_I2C_CLK_MASTER_FAST(rate) - 1) \
& SYNQUACER_I2C_CCR_CS_MASK)
/* calculate the value of CS bits in CSR register on fast mode */
#define SYNQUACER_I2C_CSR_CS_FAST_MIN_18M(rate) \
(((SYNQUACER_I2C_CLK_MASTER_FAST(rate) - 1) >> 5) \
& SYNQUACER_I2C_CSR_CS_MASK)
/* min I2C clock frequency 14M */
#define SYNQUACER_I2C_MIN_CLK_RATE (14 * 1000000)
/* max I2C clock frequency 200M */
#define SYNQUACER_I2C_MAX_CLK_RATE (200 * 1000000)
/* I2C clock frequency 18M */
#define SYNQUACER_I2C_CLK_RATE_18M (18 * 1000000)
#define SYNQUACER_I2C_SPEED_FM 400 // Fast Mode
#define SYNQUACER_I2C_SPEED_SM 100 // Standard Mode
enum i2c_state {
STATE_IDLE,
STATE_START,
STATE_READ,
STATE_WRITE
};
struct synquacer_i2c {
struct completion completion;
struct i2c_msg *msg;
u32 msg_num;
u32 msg_idx;
u32 msg_ptr;
int irq;
struct device *dev;
void __iomem *base;
struct clk *pclk;
u32 pclkrate;
u32 speed_khz;
u32 timeout_ms;
enum i2c_state state;
struct i2c_adapter adapter;
bool is_suspended;
};
static inline int is_lastmsg(struct synquacer_i2c *i2c)
{
return i2c->msg_idx >= (i2c->msg_num - 1);
}
static inline int is_msglast(struct synquacer_i2c *i2c)
{
return i2c->msg_ptr == (i2c->msg->len - 1);
}
static inline int is_msgend(struct synquacer_i2c *i2c)
{
return i2c->msg_ptr >= i2c->msg->len;
}
static inline unsigned long calc_timeout_ms(struct synquacer_i2c *i2c,
struct i2c_msg *msgs,
int num)
{
unsigned long bit_count = 0;
int i;
for (i = 0; i < num; i++, msgs++)
bit_count += msgs->len;
return DIV_ROUND_UP((bit_count * 9 + num * 10) * 3, 200) + 10;
}
static void synquacer_i2c_stop(struct synquacer_i2c *i2c, int ret)
{
/*
* clear IRQ (INT=0, BER=0)
* set Stop Condition (MSS=0)
* Interrupt Disable
*/
writeb(0, i2c->base + SYNQUACER_I2C_REG_BCR);
i2c->state = STATE_IDLE;
i2c->msg_ptr = 0;
i2c->msg = NULL;
i2c->msg_idx++;
i2c->msg_num = 0;
if (ret)
i2c->msg_idx = ret;
complete(&i2c->completion);
}
static void synquacer_i2c_hw_init(struct synquacer_i2c *i2c)
{
unsigned char ccr_cs, csr_cs;
u32 rt = i2c->pclkrate;
/* Set own Address */
writeb(0, i2c->base + SYNQUACER_I2C_REG_ADR);
/* Set PCLK frequency */
writeb(SYNQUACER_I2C_BUS_CLK_FR(i2c->pclkrate),
i2c->base + SYNQUACER_I2C_REG_FSR);
switch (i2c->speed_khz) {
case SYNQUACER_I2C_SPEED_FM:
if (i2c->pclkrate <= SYNQUACER_I2C_CLK_RATE_18M) {
ccr_cs = SYNQUACER_I2C_CCR_CS_FAST_MAX_18M(rt);
csr_cs = SYNQUACER_I2C_CSR_CS_FAST_MAX_18M(rt);
} else {
ccr_cs = SYNQUACER_I2C_CCR_CS_FAST_MIN_18M(rt);
csr_cs = SYNQUACER_I2C_CSR_CS_FAST_MIN_18M(rt);
}
/* Set Clock and enable, Set fast mode */
writeb(ccr_cs | SYNQUACER_I2C_CCR_FM |
SYNQUACER_I2C_CCR_EN,
i2c->base + SYNQUACER_I2C_REG_CCR);
writeb(csr_cs, i2c->base + SYNQUACER_I2C_REG_CSR);
break;
case SYNQUACER_I2C_SPEED_SM:
if (i2c->pclkrate <= SYNQUACER_I2C_CLK_RATE_18M) {
ccr_cs = SYNQUACER_I2C_CCR_CS_STD_MAX_18M(rt);
csr_cs = SYNQUACER_I2C_CSR_CS_STD_MAX_18M(rt);
} else {
ccr_cs = SYNQUACER_I2C_CCR_CS_STD_MIN_18M(rt);
csr_cs = SYNQUACER_I2C_CSR_CS_STD_MIN_18M(rt);
}
/* Set Clock and enable, Set standard mode */
writeb(ccr_cs | SYNQUACER_I2C_CCR_EN,
i2c->base + SYNQUACER_I2C_REG_CCR);
writeb(csr_cs, i2c->base + SYNQUACER_I2C_REG_CSR);
break;
default:
WARN_ON(1);
}
/* clear IRQ (INT=0, BER=0), Interrupt Disable */
writeb(0, i2c->base + SYNQUACER_I2C_REG_BCR);
writeb(0, i2c->base + SYNQUACER_I2C_REG_BC2R);
}
static void synquacer_i2c_hw_reset(struct synquacer_i2c *i2c)
{
/* Disable clock */
writeb(0, i2c->base + SYNQUACER_I2C_REG_CCR);
writeb(0, i2c->base + SYNQUACER_I2C_REG_CSR);
WAIT_PCLK(100, i2c->pclkrate);
}
static int synquacer_i2c_master_start(struct synquacer_i2c *i2c,
struct i2c_msg *pmsg)
{
unsigned char bsr, bcr;
writeb(i2c_8bit_addr_from_msg(pmsg), i2c->base + SYNQUACER_I2C_REG_DAR);
dev_dbg(i2c->dev, "slave:0x%02x\n", pmsg->addr);
/* Generate Start Condition */
bsr = readb(i2c->base + SYNQUACER_I2C_REG_BSR);
bcr = readb(i2c->base + SYNQUACER_I2C_REG_BCR);
dev_dbg(i2c->dev, "bsr:0x%02x, bcr:0x%02x\n", bsr, bcr);
if ((bsr & SYNQUACER_I2C_BSR_BB) &&
!(bcr & SYNQUACER_I2C_BCR_MSS)) {
dev_dbg(i2c->dev, "bus is busy");
return -EBUSY;
}
if (bsr & SYNQUACER_I2C_BSR_BB) { /* Bus is busy */
dev_dbg(i2c->dev, "Continuous Start");
writeb(bcr | SYNQUACER_I2C_BCR_SCC,
i2c->base + SYNQUACER_I2C_REG_BCR);
} else {
if (bcr & SYNQUACER_I2C_BCR_MSS) {
dev_dbg(i2c->dev, "not in master mode");
return -EAGAIN;
}
dev_dbg(i2c->dev, "Start Condition");
/* Start Condition + Enable Interrupts */
writeb(bcr | SYNQUACER_I2C_BCR_MSS |
SYNQUACER_I2C_BCR_INTE | SYNQUACER_I2C_BCR_BEIE,
i2c->base + SYNQUACER_I2C_REG_BCR);
}
WAIT_PCLK(10, i2c->pclkrate);
/* get BSR & BCR registers */
bsr = readb(i2c->base + SYNQUACER_I2C_REG_BSR);
bcr = readb(i2c->base + SYNQUACER_I2C_REG_BCR);
dev_dbg(i2c->dev, "bsr:0x%02x, bcr:0x%02x\n", bsr, bcr);
if ((bsr & SYNQUACER_I2C_BSR_AL) ||
!(bcr & SYNQUACER_I2C_BCR_MSS)) {
dev_dbg(i2c->dev, "arbitration lost\n");
return -EAGAIN;
}
return 0;
}
static int synquacer_i2c_doxfer(struct synquacer_i2c *i2c,
struct i2c_msg *msgs, int num)
{
unsigned char bsr;
unsigned long timeout;
int ret;
if (i2c->is_suspended)
return -EBUSY;
synquacer_i2c_hw_init(i2c);
bsr = readb(i2c->base + SYNQUACER_I2C_REG_BSR);
if (bsr & SYNQUACER_I2C_BSR_BB) {
dev_err(i2c->dev, "cannot get bus (bus busy)\n");
return -EBUSY;
}
reinit_completion(&i2c->completion);
i2c->msg = msgs;
i2c->msg_num = num;
i2c->msg_ptr = 0;
i2c->msg_idx = 0;
i2c->state = STATE_START;
ret = synquacer_i2c_master_start(i2c, i2c->msg);
if (ret < 0) {
dev_dbg(i2c->dev, "Address failed: (%d)\n", ret);
return ret;
}
timeout = wait_for_completion_timeout(&i2c->completion,
msecs_to_jiffies(i2c->timeout_ms));
if (timeout == 0) {
dev_dbg(i2c->dev, "timeout\n");
return -EAGAIN;
}
ret = i2c->msg_idx;
if (ret != num) {
dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret);
return -EAGAIN;
}
/* wait 2 clock periods to ensure the stop has been through the bus */
udelay(DIV_ROUND_UP(2 * 1000, i2c->speed_khz));
return 0;
}
static irqreturn_t synquacer_i2c_isr(int irq, void *dev_id)
{
struct synquacer_i2c *i2c = dev_id;
unsigned char byte;
unsigned char bsr, bcr;
int ret;
bcr = readb(i2c->base + SYNQUACER_I2C_REG_BCR);
bsr = readb(i2c->base + SYNQUACER_I2C_REG_BSR);
dev_dbg(i2c->dev, "bsr:0x%02x, bcr:0x%02x\n", bsr, bcr);
if (bcr & SYNQUACER_I2C_BCR_BER) {
dev_err(i2c->dev, "bus error\n");
synquacer_i2c_stop(i2c, -EAGAIN);
goto out;
}
if ((bsr & SYNQUACER_I2C_BSR_AL) ||
!(bcr & SYNQUACER_I2C_BCR_MSS)) {
dev_dbg(i2c->dev, "arbitration lost\n");
synquacer_i2c_stop(i2c, -EAGAIN);
goto out;
}
switch (i2c->state) {
case STATE_START:
if (bsr & SYNQUACER_I2C_BSR_LRB) {
dev_dbg(i2c->dev, "ack was not received\n");
synquacer_i2c_stop(i2c, -EAGAIN);
goto out;
}
if (i2c->msg->flags & I2C_M_RD)
i2c->state = STATE_READ;
else
i2c->state = STATE_WRITE;
if (is_lastmsg(i2c) && i2c->msg->len == 0) {
synquacer_i2c_stop(i2c, 0);
goto out;
}
if (i2c->state == STATE_READ)
goto prepare_read;
/* fallthru */
case STATE_WRITE:
if (bsr & SYNQUACER_I2C_BSR_LRB) {
dev_dbg(i2c->dev, "WRITE: No Ack\n");
synquacer_i2c_stop(i2c, -EAGAIN);
goto out;
}
if (!is_msgend(i2c)) {
writeb(i2c->msg->buf[i2c->msg_ptr++],
i2c->base + SYNQUACER_I2C_REG_DAR);
/* clear IRQ, and continue */
writeb(SYNQUACER_I2C_BCR_BEIE |
SYNQUACER_I2C_BCR_MSS |
SYNQUACER_I2C_BCR_INTE,
i2c->base + SYNQUACER_I2C_REG_BCR);
break;
}
if (is_lastmsg(i2c)) {
synquacer_i2c_stop(i2c, 0);
break;
}
dev_dbg(i2c->dev, "WRITE: Next Message\n");
i2c->msg_ptr = 0;
i2c->msg_idx++;
i2c->msg++;
/* send the new start */
ret = synquacer_i2c_master_start(i2c, i2c->msg);
if (ret < 0) {
dev_dbg(i2c->dev, "restart error (%d)\n", ret);
synquacer_i2c_stop(i2c, -EAGAIN);
break;
}
i2c->state = STATE_START;
break;
case STATE_READ:
byte = readb(i2c->base + SYNQUACER_I2C_REG_DAR);
if (!(bsr & SYNQUACER_I2C_BSR_FBT)) /* data */
i2c->msg->buf[i2c->msg_ptr++] = byte;
else /* address */
dev_dbg(i2c->dev, "address:0x%02x. ignore it.\n", byte);
prepare_read:
if (is_msglast(i2c)) {
writeb(SYNQUACER_I2C_BCR_MSS |
SYNQUACER_I2C_BCR_BEIE |
SYNQUACER_I2C_BCR_INTE,
i2c->base + SYNQUACER_I2C_REG_BCR);
break;
}
if (!is_msgend(i2c)) {
writeb(SYNQUACER_I2C_BCR_MSS |
SYNQUACER_I2C_BCR_BEIE |
SYNQUACER_I2C_BCR_INTE |
SYNQUACER_I2C_BCR_ACK,
i2c->base + SYNQUACER_I2C_REG_BCR);
break;
}
if (is_lastmsg(i2c)) {
/* last message, send stop and complete */
dev_dbg(i2c->dev, "READ: Send Stop\n");
synquacer_i2c_stop(i2c, 0);
break;
}
dev_dbg(i2c->dev, "READ: Next Transfer\n");
i2c->msg_ptr = 0;
i2c->msg_idx++;
i2c->msg++;
ret = synquacer_i2c_master_start(i2c, i2c->msg);
if (ret < 0) {
dev_dbg(i2c->dev, "restart error (%d)\n", ret);
synquacer_i2c_stop(i2c, -EAGAIN);
} else {
i2c->state = STATE_START;
}
break;
default:
dev_err(i2c->dev, "called in err STATE (%d)\n", i2c->state);
break;
}
out:
WAIT_PCLK(10, i2c->pclkrate);
return IRQ_HANDLED;
}
static int synquacer_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num)
{
struct synquacer_i2c *i2c;
int retry;
int ret;
i2c = i2c_get_adapdata(adap);
i2c->timeout_ms = calc_timeout_ms(i2c, msgs, num);
dev_dbg(i2c->dev, "calculated timeout %d ms\n", i2c->timeout_ms);
for (retry = 0; retry < adap->retries; retry++) {
ret = synquacer_i2c_doxfer(i2c, msgs, num);
if (ret != -EAGAIN)
return ret;
dev_dbg(i2c->dev, "Retrying transmission (%d)\n", retry);
synquacer_i2c_hw_reset(i2c);
}
return -EIO;
}
static u32 synquacer_i2c_functionality(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static const struct i2c_algorithm synquacer_i2c_algo = {
.master_xfer = synquacer_i2c_xfer,
.functionality = synquacer_i2c_functionality,
};
static struct i2c_adapter synquacer_i2c_ops = {
.owner = THIS_MODULE,
.name = "synquacer_i2c-adapter",
.algo = &synquacer_i2c_algo,
.retries = 5,
};
static int synquacer_i2c_probe(struct platform_device *pdev)
{
struct synquacer_i2c *i2c;
struct resource *r;
u32 bus_speed;
int ret;
i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
if (!i2c)
return -ENOMEM;
bus_speed = i2c_acpi_find_bus_speed(&pdev->dev);
if (!bus_speed)
device_property_read_u32(&pdev->dev, "clock-frequency",
&bus_speed);
device_property_read_u32(&pdev->dev, "socionext,pclk-rate",
&i2c->pclkrate);
i2c->pclk = devm_clk_get(&pdev->dev, "pclk");
if (IS_ERR(i2c->pclk) && PTR_ERR(i2c->pclk) == -EPROBE_DEFER)
return -EPROBE_DEFER;
if (!IS_ERR_OR_NULL(i2c->pclk)) {
dev_dbg(&pdev->dev, "clock source %p\n", i2c->pclk);
ret = clk_prepare_enable(i2c->pclk);
if (ret) {
dev_err(&pdev->dev, "failed to enable clock (%d)\n",
ret);
return ret;
}
i2c->pclkrate = clk_get_rate(i2c->pclk);
}
if (i2c->pclkrate < SYNQUACER_I2C_MIN_CLK_RATE ||
i2c->pclkrate > SYNQUACER_I2C_MAX_CLK_RATE) {
dev_err(&pdev->dev, "PCLK missing or out of range (%d)\n",
i2c->pclkrate);
return -EINVAL;
}
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
i2c->base = devm_ioremap_resource(&pdev->dev, r);
if (IS_ERR(i2c->base))
return PTR_ERR(i2c->base);
i2c->irq = platform_get_irq(pdev, 0);
if (i2c->irq < 0) {
dev_err(&pdev->dev, "no IRQ resource found\n");
return -ENODEV;
}
ret = devm_request_irq(&pdev->dev, i2c->irq, synquacer_i2c_isr,
0, dev_name(&pdev->dev), i2c);
if (ret < 0) {
dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
return ret;
}
i2c->state = STATE_IDLE;
i2c->dev = &pdev->dev;
i2c->adapter = synquacer_i2c_ops;
i2c_set_adapdata(&i2c->adapter, i2c);
i2c->adapter.dev.parent = &pdev->dev;
i2c->adapter.nr = pdev->id;
init_completion(&i2c->completion);
if (bus_speed < 400000)
i2c->speed_khz = SYNQUACER_I2C_SPEED_SM;
else
i2c->speed_khz = SYNQUACER_I2C_SPEED_FM;
synquacer_i2c_hw_init(i2c);
ret = i2c_add_numbered_adapter(&i2c->adapter);
if (ret) {
dev_err(&pdev->dev, "failed to add bus to i2c core\n");
return ret;
}
platform_set_drvdata(pdev, i2c);
dev_info(&pdev->dev, "%s: synquacer_i2c adapter\n",
dev_name(&i2c->adapter.dev));
return 0;
}
static int synquacer_i2c_remove(struct platform_device *pdev)
{
struct synquacer_i2c *i2c = platform_get_drvdata(pdev);
i2c_del_adapter(&i2c->adapter);
if (!IS_ERR(i2c->pclk))
clk_disable_unprepare(i2c->pclk);
return 0;
};
static const struct of_device_id synquacer_i2c_dt_ids[] = {
{ .compatible = "socionext,synquacer-i2c" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, synquacer_i2c_dt_ids);
#ifdef CONFIG_ACPI
static const struct acpi_device_id synquacer_i2c_acpi_ids[] = {
{ "SCX0003" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(acpi, synquacer_i2c_acpi_ids);
#endif
static struct platform_driver synquacer_i2c_driver = {
.probe = synquacer_i2c_probe,
.remove = synquacer_i2c_remove,
.driver = {
.name = "synquacer_i2c",
.of_match_table = of_match_ptr(synquacer_i2c_dt_ids),
.acpi_match_table = ACPI_PTR(synquacer_i2c_acpi_ids),
},
};
module_platform_driver(synquacer_i2c_driver);
MODULE_AUTHOR("Fujitsu Semiconductor Ltd");
MODULE_DESCRIPTION("Socionext SynQuacer I2C Driver");
MODULE_LICENSE("GPL v2");
...@@ -851,7 +851,7 @@ static const struct of_device_id xiic_of_match[] = { ...@@ -851,7 +851,7 @@ static const struct of_device_id xiic_of_match[] = {
MODULE_DEVICE_TABLE(of, xiic_of_match); MODULE_DEVICE_TABLE(of, xiic_of_match);
#endif #endif
static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev) static int __maybe_unused xiic_i2c_runtime_suspend(struct device *dev)
{ {
struct xiic_i2c *i2c = dev_get_drvdata(dev); struct xiic_i2c *i2c = dev_get_drvdata(dev);
...@@ -860,7 +860,7 @@ static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev) ...@@ -860,7 +860,7 @@ static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev)
return 0; return 0;
} }
static int __maybe_unused cdns_i2c_runtime_resume(struct device *dev) static int __maybe_unused xiic_i2c_runtime_resume(struct device *dev)
{ {
struct xiic_i2c *i2c = dev_get_drvdata(dev); struct xiic_i2c *i2c = dev_get_drvdata(dev);
int ret; int ret;
...@@ -875,8 +875,8 @@ static int __maybe_unused cdns_i2c_runtime_resume(struct device *dev) ...@@ -875,8 +875,8 @@ static int __maybe_unused cdns_i2c_runtime_resume(struct device *dev)
} }
static const struct dev_pm_ops xiic_dev_pm_ops = { static const struct dev_pm_ops xiic_dev_pm_ops = {
SET_RUNTIME_PM_OPS(cdns_i2c_runtime_suspend, SET_RUNTIME_PM_OPS(xiic_i2c_runtime_suspend,
cdns_i2c_runtime_resume, NULL) xiic_i2c_runtime_resume, NULL)
}; };
static struct platform_driver xiic_i2c_driver = { static struct platform_driver xiic_i2c_driver = {
.probe = xiic_i2c_probe, .probe = xiic_i2c_probe,
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/delay.h>
#define XLP9XX_I2C_DIV 0x0 #define XLP9XX_I2C_DIV 0x0
#define XLP9XX_I2C_CTRL 0x1 #define XLP9XX_I2C_CTRL 0x1
...@@ -36,6 +37,8 @@ ...@@ -36,6 +37,8 @@
#define XLP9XX_I2C_TIMEOUT 0X10 #define XLP9XX_I2C_TIMEOUT 0X10
#define XLP9XX_I2C_GENCALLADDR 0x11 #define XLP9XX_I2C_GENCALLADDR 0x11
#define XLP9XX_I2C_STATUS_BUSY BIT(0)
#define XLP9XX_I2C_CMD_START BIT(7) #define XLP9XX_I2C_CMD_START BIT(7)
#define XLP9XX_I2C_CMD_STOP BIT(6) #define XLP9XX_I2C_CMD_STOP BIT(6)
#define XLP9XX_I2C_CMD_READ BIT(5) #define XLP9XX_I2C_CMD_READ BIT(5)
...@@ -71,6 +74,7 @@ ...@@ -71,6 +74,7 @@
#define XLP9XX_I2C_HIGH_FREQ 400000 #define XLP9XX_I2C_HIGH_FREQ 400000
#define XLP9XX_I2C_FIFO_SIZE 0x80U #define XLP9XX_I2C_FIFO_SIZE 0x80U
#define XLP9XX_I2C_TIMEOUT_MS 1000 #define XLP9XX_I2C_TIMEOUT_MS 1000
#define XLP9XX_I2C_BUSY_TIMEOUT 50
#define XLP9XX_I2C_FIFO_WCNT_MASK 0xff #define XLP9XX_I2C_FIFO_WCNT_MASK 0xff
#define XLP9XX_I2C_STATUS_ERRMASK (XLP9XX_I2C_INTEN_ARLOST | \ #define XLP9XX_I2C_STATUS_ERRMASK (XLP9XX_I2C_INTEN_ARLOST | \
...@@ -125,7 +129,16 @@ static void xlp9xx_i2c_update_rx_fifo_thres(struct xlp9xx_i2c_dev *priv) ...@@ -125,7 +129,16 @@ static void xlp9xx_i2c_update_rx_fifo_thres(struct xlp9xx_i2c_dev *priv)
{ {
u32 thres; u32 thres;
thres = min(priv->msg_buf_remaining, XLP9XX_I2C_FIFO_SIZE); if (priv->len_recv)
/* interrupt after the first read to examine
* the length byte before proceeding further
*/
thres = 1;
else if (priv->msg_buf_remaining > XLP9XX_I2C_FIFO_SIZE)
thres = XLP9XX_I2C_FIFO_SIZE;
else
thres = priv->msg_buf_remaining;
xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_MFIFOCTRL, xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_MFIFOCTRL,
thres << XLP9XX_I2C_MFIFOCTRL_HITH_SHIFT); thres << XLP9XX_I2C_MFIFOCTRL_HITH_SHIFT);
} }
...@@ -144,7 +157,7 @@ static void xlp9xx_i2c_fill_tx_fifo(struct xlp9xx_i2c_dev *priv) ...@@ -144,7 +157,7 @@ static void xlp9xx_i2c_fill_tx_fifo(struct xlp9xx_i2c_dev *priv)
static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv) static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv)
{ {
u32 len, i; u32 len, i, val;
u8 rlen, *buf = priv->msg_buf; u8 rlen, *buf = priv->msg_buf;
len = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_FIFOWCNT) & len = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_FIFOWCNT) &
...@@ -156,19 +169,27 @@ static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv) ...@@ -156,19 +169,27 @@ static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv)
rlen = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO); rlen = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO);
*buf++ = rlen; *buf++ = rlen;
len--; len--;
if (priv->client_pec) if (priv->client_pec)
++rlen; ++rlen;
/* update remaining bytes and message length */ /* update remaining bytes and message length */
priv->msg_buf_remaining = rlen; priv->msg_buf_remaining = rlen;
priv->msg_len = rlen + 1; priv->msg_len = rlen + 1;
priv->len_recv = false; priv->len_recv = false;
}
/* Update transfer length to read only actual data */
val = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_CTRL);
val = (val & ~XLP9XX_I2C_CTRL_MCTLEN_MASK) |
((rlen + 1) << XLP9XX_I2C_CTRL_MCTLEN_SHIFT);
xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, val);
} else {
len = min(priv->msg_buf_remaining, len); len = min(priv->msg_buf_remaining, len);
for (i = 0; i < len; i++, buf++) for (i = 0; i < len; i++, buf++)
*buf = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO); *buf = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO);
priv->msg_buf_remaining -= len; priv->msg_buf_remaining -= len;
}
priv->msg_buf = buf; priv->msg_buf = buf;
if (priv->msg_buf_remaining) if (priv->msg_buf_remaining)
...@@ -224,6 +245,26 @@ static irqreturn_t xlp9xx_i2c_isr(int irq, void *dev_id) ...@@ -224,6 +245,26 @@ static irqreturn_t xlp9xx_i2c_isr(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int xlp9xx_i2c_check_bus_status(struct xlp9xx_i2c_dev *priv)
{
u32 status;
u32 busy_timeout = XLP9XX_I2C_BUSY_TIMEOUT;
while (busy_timeout) {
status = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_STATUS);
if ((status & XLP9XX_I2C_STATUS_BUSY) == 0)
break;
busy_timeout--;
usleep_range(1000, 1100);
}
if (!busy_timeout)
return -EIO;
return 0;
}
static int xlp9xx_i2c_init(struct xlp9xx_i2c_dev *priv) static int xlp9xx_i2c_init(struct xlp9xx_i2c_dev *priv)
{ {
u32 prescale; u32 prescale;
...@@ -311,7 +352,9 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg, ...@@ -311,7 +352,9 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
/* set cmd reg */ /* set cmd reg */
cmd = XLP9XX_I2C_CMD_START; cmd = XLP9XX_I2C_CMD_START;
cmd |= (priv->msg_read ? XLP9XX_I2C_CMD_READ : XLP9XX_I2C_CMD_WRITE); if (msg->len)
cmd |= (priv->msg_read ?
XLP9XX_I2C_CMD_READ : XLP9XX_I2C_CMD_WRITE);
if (last_msg) if (last_msg)
cmd |= XLP9XX_I2C_CMD_STOP; cmd |= XLP9XX_I2C_CMD_STOP;
...@@ -320,11 +363,12 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg, ...@@ -320,11 +363,12 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
timeleft = msecs_to_jiffies(XLP9XX_I2C_TIMEOUT_MS); timeleft = msecs_to_jiffies(XLP9XX_I2C_TIMEOUT_MS);
timeleft = wait_for_completion_timeout(&priv->msg_complete, timeleft); timeleft = wait_for_completion_timeout(&priv->msg_complete, timeleft);
if (priv->msg_err) { if (priv->msg_err & XLP9XX_I2C_INTEN_BUSERR) {
dev_dbg(priv->dev, "transfer error %x!\n", priv->msg_err); dev_dbg(priv->dev, "transfer error %x!\n", priv->msg_err);
if (priv->msg_err & XLP9XX_I2C_INTEN_BUSERR) xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CMD, XLP9XX_I2C_CMD_STOP);
xlp9xx_i2c_init(priv);
return -EIO; return -EIO;
} else if (priv->msg_err & XLP9XX_I2C_INTEN_NACKADDR) {
return -ENXIO;
} }
if (timeleft == 0) { if (timeleft == 0) {
...@@ -345,6 +389,14 @@ static int xlp9xx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ...@@ -345,6 +389,14 @@ static int xlp9xx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
int i, ret; int i, ret;
struct xlp9xx_i2c_dev *priv = i2c_get_adapdata(adap); struct xlp9xx_i2c_dev *priv = i2c_get_adapdata(adap);
ret = xlp9xx_i2c_check_bus_status(priv);
if (ret) {
xlp9xx_i2c_init(priv);
ret = xlp9xx_i2c_check_bus_status(priv);
if (ret)
return ret;
}
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
ret = xlp9xx_i2c_xfer_msg(priv, &msgs[i], i == num - 1); ret = xlp9xx_i2c_xfer_msg(priv, &msgs[i], i == num - 1);
if (ret != 0) if (ret != 0)
...@@ -356,8 +408,8 @@ static int xlp9xx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ...@@ -356,8 +408,8 @@ static int xlp9xx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
static u32 xlp9xx_i2c_functionality(struct i2c_adapter *adapter) static u32 xlp9xx_i2c_functionality(struct i2c_adapter *adapter)
{ {
return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C | return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_READ_BLOCK_DATA |
I2C_FUNC_10BIT_ADDR; I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR;
} }
static const struct i2c_algorithm xlp9xx_i2c_algo = { static const struct i2c_algorithm xlp9xx_i2c_algo = {
......
...@@ -58,6 +58,8 @@ ...@@ -58,6 +58,8 @@
#define I2C_ADDR_7BITS_MAX 0x77 #define I2C_ADDR_7BITS_MAX 0x77
#define I2C_ADDR_7BITS_COUNT (I2C_ADDR_7BITS_MAX + 1) #define I2C_ADDR_7BITS_COUNT (I2C_ADDR_7BITS_MAX + 1)
#define I2C_ADDR_DEVICE_ID 0x7c
/* /*
* core_lock protects i2c_adapter_idr, and guarantees that device detection, * core_lock protects i2c_adapter_idr, and guarantees that device detection,
* deletion of detected devices, and attach_adapter calls are serialized * deletion of detected devices, and attach_adapter calls are serialized
...@@ -67,18 +69,18 @@ static DEFINE_IDR(i2c_adapter_idr); ...@@ -67,18 +69,18 @@ static DEFINE_IDR(i2c_adapter_idr);
static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver); static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
static struct static_key i2c_trace_msg = STATIC_KEY_INIT_FALSE; static DEFINE_STATIC_KEY_FALSE(i2c_trace_msg_key);
static bool is_registered; static bool is_registered;
int i2c_transfer_trace_reg(void) int i2c_transfer_trace_reg(void)
{ {
static_key_slow_inc(&i2c_trace_msg); static_branch_inc(&i2c_trace_msg_key);
return 0; return 0;
} }
void i2c_transfer_trace_unreg(void) void i2c_transfer_trace_unreg(void)
{ {
static_key_slow_dec(&i2c_trace_msg); static_branch_dec(&i2c_trace_msg_key);
} }
const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id, const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
...@@ -124,6 +126,10 @@ static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env) ...@@ -124,6 +126,10 @@ static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
int rc; int rc;
rc = of_device_uevent_modalias(dev, env);
if (rc != -ENODEV)
return rc;
rc = acpi_device_uevent_modalias(dev, env); rc = acpi_device_uevent_modalias(dev, env);
if (rc != -ENODEV) if (rc != -ENODEV)
return rc; return rc;
...@@ -439,6 +445,10 @@ show_modalias(struct device *dev, struct device_attribute *attr, char *buf) ...@@ -439,6 +445,10 @@ show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
int len; int len;
len = of_device_modalias(dev, buf, PAGE_SIZE);
if (len != -ENODEV)
return len;
len = acpi_device_modalias(dev, buf, PAGE_SIZE -1); len = acpi_device_modalias(dev, buf, PAGE_SIZE -1);
if (len != -ENODEV) if (len != -ENODEV)
return len; return len;
...@@ -507,7 +517,7 @@ static unsigned short i2c_encode_flags_to_addr(struct i2c_client *client) ...@@ -507,7 +517,7 @@ static unsigned short i2c_encode_flags_to_addr(struct i2c_client *client)
/* This is a permissive address validity check, I2C address map constraints /* This is a permissive address validity check, I2C address map constraints
* are purposely not enforced, except for the general call address. */ * are purposely not enforced, except for the general call address. */
int i2c_check_addr_validity(unsigned addr, unsigned short flags) static int i2c_check_addr_validity(unsigned int addr, unsigned short flags)
{ {
if (flags & I2C_CLIENT_TEN) { if (flags & I2C_CLIENT_TEN) {
/* 10-bit address, all values are valid */ /* 10-bit address, all values are valid */
...@@ -1838,11 +1848,12 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) ...@@ -1838,11 +1848,12 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
if (adap->quirks && i2c_check_for_quirks(adap, msgs, num)) if (adap->quirks && i2c_check_for_quirks(adap, msgs, num))
return -EOPNOTSUPP; return -EOPNOTSUPP;
/* i2c_trace_msg gets enabled when tracepoint i2c_transfer gets /*
* i2c_trace_msg_key gets enabled when tracepoint i2c_transfer gets
* enabled. This is an efficient way of keeping the for-loop from * enabled. This is an efficient way of keeping the for-loop from
* being executed when not needed. * being executed when not needed.
*/ */
if (static_key_false(&i2c_trace_msg)) { if (static_branch_unlikely(&i2c_trace_msg_key)) {
int i; int i;
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
if (msgs[i].flags & I2C_M_RD) if (msgs[i].flags & I2C_M_RD)
...@@ -1861,12 +1872,12 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) ...@@ -1861,12 +1872,12 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
break; break;
} }
if (static_key_false(&i2c_trace_msg)) { if (static_branch_unlikely(&i2c_trace_msg_key)) {
int i; int i;
for (i = 0; i < ret; i++) for (i = 0; i < ret; i++)
if (msgs[i].flags & I2C_M_RD) if (msgs[i].flags & I2C_M_RD)
trace_i2c_reply(adap, &msgs[i], i); trace_i2c_reply(adap, &msgs[i], i);
trace_i2c_result(adap, i, ret); trace_i2c_result(adap, num, ret);
} }
return ret; return ret;
...@@ -1968,6 +1979,37 @@ int i2c_transfer_buffer_flags(const struct i2c_client *client, char *buf, ...@@ -1968,6 +1979,37 @@ int i2c_transfer_buffer_flags(const struct i2c_client *client, char *buf,
} }
EXPORT_SYMBOL(i2c_transfer_buffer_flags); EXPORT_SYMBOL(i2c_transfer_buffer_flags);
/**
* i2c_get_device_id - get manufacturer, part id and die revision of a device
* @client: The device to query
* @id: The queried information
*
* Returns negative errno on error, zero on success.
*/
int i2c_get_device_id(const struct i2c_client *client,
struct i2c_device_identity *id)
{
struct i2c_adapter *adap = client->adapter;
union i2c_smbus_data raw_id;
int ret;
if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_I2C_BLOCK))
return -EOPNOTSUPP;
raw_id.block[0] = 3;
ret = i2c_smbus_xfer(adap, I2C_ADDR_DEVICE_ID, 0,
I2C_SMBUS_READ, client->addr << 1,
I2C_SMBUS_I2C_BLOCK_DATA, &raw_id);
if (ret)
return ret;
id->manufacturer_id = (raw_id.block[1] << 4) | (raw_id.block[2] >> 4);
id->part_id = ((raw_id.block[2] & 0xf) << 5) | (raw_id.block[3] >> 3);
id->die_revision = raw_id.block[3] & 0x7;
return 0;
}
EXPORT_SYMBOL_GPL(i2c_get_device_id);
/* ---------------------------------------------------- /* ----------------------------------------------------
* the i2c address scanning function * the i2c address scanning function
* Will not work for 10-bit addresses! * Will not work for 10-bit addresses!
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Copyright (C) 2008 Jochen Friedrich <jochen@scram.de> * Copyright (C) 2008 Jochen Friedrich <jochen@scram.de>
* based on a previous patch from Jon Smirl <jonsmirl@gmail.com> * based on a previous patch from Jon Smirl <jonsmirl@gmail.com>
* *
* Copyright (C) 2013 Wolfram Sang <wsa@the-dreams.de> * Copyright (C) 2013, 2018 Wolfram Sang <wsa@the-dreams.de>
* *
* This program is free software; you can redistribute it and/or modify it * 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 * under the terms of the GNU General Public License as published by the Free
...@@ -25,12 +25,11 @@ ...@@ -25,12 +25,11 @@
static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap, static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
struct device_node *node) struct device_node *node)
{ {
struct i2c_client *result; struct i2c_client *client;
struct i2c_board_info info = {}; struct i2c_board_info info = {};
struct dev_archdata dev_ad = {}; struct dev_archdata dev_ad = {};
const __be32 *addr_be;
u32 addr; u32 addr;
int len; int ret;
dev_dbg(&adap->dev, "of_i2c: register %pOF\n", node); dev_dbg(&adap->dev, "of_i2c: register %pOF\n", node);
...@@ -40,13 +39,12 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap, ...@@ -40,13 +39,12 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
addr_be = of_get_property(node, "reg", &len); ret = of_property_read_u32(node, "reg", &addr);
if (!addr_be || (len < sizeof(*addr_be))) { if (ret) {
dev_err(&adap->dev, "of_i2c: invalid reg on %pOF\n", node); dev_err(&adap->dev, "of_i2c: invalid reg on %pOF\n", node);
return ERR_PTR(-EINVAL); return ERR_PTR(ret);
} }
addr = be32_to_cpup(addr_be);
if (addr & I2C_TEN_BIT_ADDRESS) { if (addr & I2C_TEN_BIT_ADDRESS) {
addr &= ~I2C_TEN_BIT_ADDRESS; addr &= ~I2C_TEN_BIT_ADDRESS;
info.flags |= I2C_CLIENT_TEN; info.flags |= I2C_CLIENT_TEN;
...@@ -57,15 +55,9 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap, ...@@ -57,15 +55,9 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
info.flags |= I2C_CLIENT_SLAVE; info.flags |= I2C_CLIENT_SLAVE;
} }
if (i2c_check_addr_validity(addr, info.flags)) {
dev_err(&adap->dev, "of_i2c: invalid addr=%x on %pOF\n",
addr, node);
return ERR_PTR(-EINVAL);
}
info.addr = addr; info.addr = addr;
info.of_node = of_node_get(node);
info.archdata = &dev_ad; info.archdata = &dev_ad;
info.of_node = of_node_get(node);
if (of_property_read_bool(node, "host-notify")) if (of_property_read_bool(node, "host-notify"))
info.flags |= I2C_CLIENT_HOST_NOTIFY; info.flags |= I2C_CLIENT_HOST_NOTIFY;
...@@ -73,13 +65,13 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap, ...@@ -73,13 +65,13 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
if (of_get_property(node, "wakeup-source", NULL)) if (of_get_property(node, "wakeup-source", NULL))
info.flags |= I2C_CLIENT_WAKE; info.flags |= I2C_CLIENT_WAKE;
result = i2c_new_device(adap, &info); client = i2c_new_device(adap, &info);
if (result == NULL) { if (!client) {
dev_err(&adap->dev, "of_i2c: Failure registering %pOF\n", node); dev_err(&adap->dev, "of_i2c: Failure registering %pOF\n", node);
of_node_put(node); of_node_put(node);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
return result; return client;
} }
void of_i2c_register_devices(struct i2c_adapter *adap) void of_i2c_register_devices(struct i2c_adapter *adap)
...@@ -103,7 +95,7 @@ void of_i2c_register_devices(struct i2c_adapter *adap) ...@@ -103,7 +95,7 @@ void of_i2c_register_devices(struct i2c_adapter *adap)
client = of_i2c_register_device(adap, node); client = of_i2c_register_device(adap, node);
if (IS_ERR(client)) { if (IS_ERR(client)) {
dev_warn(&adap->dev, dev_err(&adap->dev,
"Failed to create I2C device for %pOF\n", "Failed to create I2C device for %pOF\n",
node); node);
of_node_clear_flag(node, OF_POPULATED); of_node_clear_flag(node, OF_POPULATED);
......
...@@ -308,17 +308,21 @@ static void i2c_smbus_try_get_dmabuf(struct i2c_msg *msg, u8 init_val) ...@@ -308,17 +308,21 @@ static void i2c_smbus_try_get_dmabuf(struct i2c_msg *msg, u8 init_val)
msg->buf[0] = init_val; msg->buf[0] = init_val;
} }
/* Simulate a SMBus command using the i2c protocol /*
No checking of parameters is done! */ * Simulate a SMBus command using the I2C protocol.
* No checking of parameters is done!
*/
static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
unsigned short flags, unsigned short flags,
char read_write, u8 command, int size, char read_write, u8 command, int size,
union i2c_smbus_data *data) union i2c_smbus_data *data)
{ {
/* So we need to generate a series of msgs. In the case of writing, we /*
need to use only one message; when reading, we need two. We initialize * So we need to generate a series of msgs. In the case of writing, we
most things with sane defaults, to keep the code below somewhat * need to use only one message; when reading, we need two. We
simpler. */ * initialize most things with sane defaults, to keep the code below
* somewhat simpler.
*/
unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3]; unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3];
unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2]; unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2];
int num = read_write == I2C_SMBUS_READ ? 2 : 1; int num = read_write == I2C_SMBUS_READ ? 2 : 1;
......
...@@ -27,7 +27,6 @@ extern struct rw_semaphore __i2c_board_lock; ...@@ -27,7 +27,6 @@ extern struct rw_semaphore __i2c_board_lock;
extern struct list_head __i2c_board_list; extern struct list_head __i2c_board_list;
extern int __i2c_first_dynamic_bus_num; extern int __i2c_first_dynamic_bus_num;
int i2c_check_addr_validity(unsigned addr, unsigned short flags);
int i2c_check_7bit_addr_validity_strict(unsigned short addr); int i2c_check_7bit_addr_validity_strict(unsigned short addr);
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
......
...@@ -77,6 +77,7 @@ struct chip_desc { ...@@ -77,6 +77,7 @@ struct chip_desc {
pca954x_ismux = 0, pca954x_ismux = 0,
pca954x_isswi pca954x_isswi
} muxtype; } muxtype;
struct i2c_device_identity id;
}; };
struct pca954x { struct pca954x {
...@@ -97,59 +98,83 @@ static const struct chip_desc chips[] = { ...@@ -97,59 +98,83 @@ static const struct chip_desc chips[] = {
.nchans = 2, .nchans = 2,
.enable = 0x4, .enable = 0x4,
.muxtype = pca954x_ismux, .muxtype = pca954x_ismux,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9542] = { [pca_9542] = {
.nchans = 2, .nchans = 2,
.enable = 0x4, .enable = 0x4,
.has_irq = 1, .has_irq = 1,
.muxtype = pca954x_ismux, .muxtype = pca954x_ismux,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9543] = { [pca_9543] = {
.nchans = 2, .nchans = 2,
.has_irq = 1, .has_irq = 1,
.muxtype = pca954x_isswi, .muxtype = pca954x_isswi,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9544] = { [pca_9544] = {
.nchans = 4, .nchans = 4,
.enable = 0x4, .enable = 0x4,
.has_irq = 1, .has_irq = 1,
.muxtype = pca954x_ismux, .muxtype = pca954x_ismux,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9545] = { [pca_9545] = {
.nchans = 4, .nchans = 4,
.has_irq = 1, .has_irq = 1,
.muxtype = pca954x_isswi, .muxtype = pca954x_isswi,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9546] = { [pca_9546] = {
.nchans = 4, .nchans = 4,
.muxtype = pca954x_isswi, .muxtype = pca954x_isswi,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9547] = { [pca_9547] = {
.nchans = 8, .nchans = 8,
.enable = 0x8, .enable = 0x8,
.muxtype = pca954x_ismux, .muxtype = pca954x_ismux,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9548] = { [pca_9548] = {
.nchans = 8, .nchans = 8,
.muxtype = pca954x_isswi, .muxtype = pca954x_isswi,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9846] = { [pca_9846] = {
.nchans = 4, .nchans = 4,
.muxtype = pca954x_isswi, .muxtype = pca954x_isswi,
.id = {
.manufacturer_id = I2C_DEVICE_ID_NXP_SEMICONDUCTORS,
.part_id = 0x10b,
},
}, },
[pca_9847] = { [pca_9847] = {
.nchans = 8, .nchans = 8,
.enable = 0x8, .enable = 0x8,
.muxtype = pca954x_ismux, .muxtype = pca954x_ismux,
.id = {
.manufacturer_id = I2C_DEVICE_ID_NXP_SEMICONDUCTORS,
.part_id = 0x108,
},
}, },
[pca_9848] = { [pca_9848] = {
.nchans = 8, .nchans = 8,
.muxtype = pca954x_isswi, .muxtype = pca954x_isswi,
.id = {
.manufacturer_id = I2C_DEVICE_ID_NXP_SEMICONDUCTORS,
.part_id = 0x10a,
},
}, },
[pca_9849] = { [pca_9849] = {
.nchans = 4, .nchans = 4,
.enable = 0x4, .enable = 0x4,
.muxtype = pca954x_ismux, .muxtype = pca954x_ismux,
.id = {
.manufacturer_id = I2C_DEVICE_ID_NXP_SEMICONDUCTORS,
.part_id = 0x109,
},
}, },
}; };
...@@ -369,6 +394,30 @@ static int pca954x_probe(struct i2c_client *client, ...@@ -369,6 +394,30 @@ static int pca954x_probe(struct i2c_client *client,
if (IS_ERR(gpio)) if (IS_ERR(gpio))
return PTR_ERR(gpio); return PTR_ERR(gpio);
match = of_match_device(of_match_ptr(pca954x_of_match), &client->dev);
if (match)
data->chip = of_device_get_match_data(&client->dev);
else
data->chip = &chips[id->driver_data];
if (data->chip->id.manufacturer_id != I2C_DEVICE_ID_NONE) {
struct i2c_device_identity id;
ret = i2c_get_device_id(client, &id);
if (ret && ret != -EOPNOTSUPP)
return ret;
if (!ret &&
(id.manufacturer_id != data->chip->id.manufacturer_id ||
id.part_id != data->chip->id.part_id)) {
dev_warn(&client->dev,
"unexpected device id %03x-%03x-%x\n",
id.manufacturer_id, id.part_id,
id.die_revision);
return -ENODEV;
}
}
/* Write the mux register at addr to verify /* Write the mux register at addr to verify
* that the mux is in fact present. This also * that the mux is in fact present. This also
* initializes the mux to disconnected state. * initializes the mux to disconnected state.
...@@ -378,12 +427,6 @@ static int pca954x_probe(struct i2c_client *client, ...@@ -378,12 +427,6 @@ static int pca954x_probe(struct i2c_client *client,
return -ENODEV; return -ENODEV;
} }
match = of_match_device(of_match_ptr(pca954x_of_match), &client->dev);
if (match)
data->chip = of_device_get_match_data(&client->dev);
else
data->chip = &chips[id->driver_data];
data->last_chan = 0; /* force the first selection */ data->last_chan = 0; /* force the first selection */
idle_disconnect_dt = of_node && idle_disconnect_dt = of_node &&
......
...@@ -3,9 +3,6 @@ ...@@ -3,9 +3,6 @@
#define I2C_PCA9564_PLATFORM_H #define I2C_PCA9564_PLATFORM_H
struct i2c_pca9564_pf_platform_data { struct i2c_pca9564_pf_platform_data {
int gpio; /* pin to reset chip. driver will work when
* not supplied (negative value), but it
* cannot exit some error conditions then */
int i2c_clock_speed; /* values are defined in linux/i2c-algo-pca.h */ int i2c_clock_speed; /* values are defined in linux/i2c-algo-pca.h */
int timeout; /* timeout in jiffies */ int timeout; /* timeout in jiffies */
}; };
......
...@@ -47,6 +47,7 @@ struct i2c_algorithm; ...@@ -47,6 +47,7 @@ struct i2c_algorithm;
struct i2c_adapter; struct i2c_adapter;
struct i2c_client; struct i2c_client;
struct i2c_driver; struct i2c_driver;
struct i2c_device_identity;
union i2c_smbus_data; union i2c_smbus_data;
struct i2c_board_info; struct i2c_board_info;
enum i2c_slave_event; enum i2c_slave_event;
...@@ -186,8 +187,37 @@ extern s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client, ...@@ -186,8 +187,37 @@ extern s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client,
extern s32 extern s32
i2c_smbus_read_i2c_block_data_or_emulated(const struct i2c_client *client, i2c_smbus_read_i2c_block_data_or_emulated(const struct i2c_client *client,
u8 command, u8 length, u8 *values); u8 command, u8 length, u8 *values);
int i2c_get_device_id(const struct i2c_client *client,
struct i2c_device_identity *id);
#endif /* I2C */ #endif /* I2C */
/**
* struct i2c_device_identity - i2c client device identification
* @manufacturer_id: 0 - 4095, database maintained by NXP
* @part_id: 0 - 511, according to manufacturer
* @die_revision: 0 - 7, according to manufacturer
*/
struct i2c_device_identity {
u16 manufacturer_id;
#define I2C_DEVICE_ID_NXP_SEMICONDUCTORS 0
#define I2C_DEVICE_ID_NXP_SEMICONDUCTORS_1 1
#define I2C_DEVICE_ID_NXP_SEMICONDUCTORS_2 2
#define I2C_DEVICE_ID_NXP_SEMICONDUCTORS_3 3
#define I2C_DEVICE_ID_RAMTRON_INTERNATIONAL 4
#define I2C_DEVICE_ID_ANALOG_DEVICES 5
#define I2C_DEVICE_ID_STMICROELECTRONICS 6
#define I2C_DEVICE_ID_ON_SEMICONDUCTOR 7
#define I2C_DEVICE_ID_SPRINTEK_CORPORATION 8
#define I2C_DEVICE_ID_ESPROS_PHOTONICS_AG 9
#define I2C_DEVICE_ID_FUJITSU_SEMICONDUCTOR 10
#define I2C_DEVICE_ID_FLIR 11
#define I2C_DEVICE_ID_O2MICRO 12
#define I2C_DEVICE_ID_ATMEL 13
#define I2C_DEVICE_ID_NONE 0xffff
u16 part_id;
u8 die_revision;
};
enum i2c_alert_protocol { enum i2c_alert_protocol {
I2C_PROTOCOL_SMBUS_ALERT, I2C_PROTOCOL_SMBUS_ALERT,
I2C_PROTOCOL_SMBUS_HOST_NOTIFY, I2C_PROTOCOL_SMBUS_HOST_NOTIFY,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment