mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
Merge tag 'i2c-for-6.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang:
"Core:
- list-based mechanisms for handling auto-detected and userspace
created clients are replaced with a flag-based approach. The
resulting code is much simpler as well as the locking.
- i2c clients now get a default debugfs dir managed by the I2C core.
Drivers don't have to maintain their own directory anymore.
Driver updates:
- xiic: atomic_transfer support
- imx-lpi2c: DMA and target mode support
- riic cleanups
- npcm: better timeout handling and more precise frequency setups
- davinci: remove unused platform_data
- at24: add new compatibles for variants from Giantec and Puya
Semiconductor (together with a new vendor prefix)"
* tag 'i2c-for-6.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (52 commits)
i2c: add kdoc for the new debugfs entry of clients
i2c: designware: Actually make use of the I2C_DW_COMMON and I2C_DW symbol namespaces
i2c: add core-managed per-client directory in debugfs
i2c: Force ELAN06FA touchpad I2C bus freq to 100KHz
i2c: riic: Add `riic_bus_barrier()` to check bus availability
i2c: riic: Use predefined macro and simplify clock tick calculation
i2c: riic: Mark riic_irqs array as const
i2c: riic: Make use of devres helper to request deasserted reset line
i2c: riic: Use GENMASK() macro for bitmask definitions
i2c: riic: Use BIT macro consistently
i2c: riic: Use local `dev` pointer in `dev_err_probe()`
i2c: riic: Use dev_err_probe in probe and riic_init_hw functions
i2c: riic: Introduce a separate variable for IRQ
i2c: amd756: Remove superfluous TODO
Revert "i2c: amd756: Fix endianness handling for word data"
i2c: i801: Add lis3lv02d for Dell Precision M6800
i2c: i801: Remove unnecessary PCI function call
i2c: core: Allocate temp client on the stack in i2c_detect
i2c: slave-eeprom: Constify 'struct bin_attribute'
i2c: imx-lpi2c: make controller available until the system enters suspend_noirq() and from resume_noirq().
...
This commit is contained in:
@@ -134,9 +134,14 @@ properties:
|
||||
- const: atmel,24c64
|
||||
- items:
|
||||
- enum:
|
||||
- giantec,gt24p128f
|
||||
- renesas,r1ex24128
|
||||
- samsung,s524ad0xd1
|
||||
- const: atmel,24c128
|
||||
- items:
|
||||
- enum:
|
||||
- puya,p24c256c
|
||||
- const: atmel,24c256
|
||||
- items:
|
||||
- const: microchip,24aa025e48
|
||||
- items:
|
||||
|
||||
@@ -25,6 +25,7 @@ properties:
|
||||
- samsung,exynos5250-hsi2c # Exynos5250 and Exynos5420
|
||||
- samsung,exynos5260-hsi2c # Exynos5260
|
||||
- samsung,exynos7-hsi2c # Exynos7
|
||||
- samsung,exynos8895-hsi2c
|
||||
- samsung,exynosautov9-hsi2c
|
||||
- items:
|
||||
- enum:
|
||||
|
||||
@@ -34,6 +34,7 @@ properties:
|
||||
- qcom,sm8450-cci
|
||||
- qcom,sm8550-cci
|
||||
- qcom,sm8650-cci
|
||||
- qcom,x1e80100-cci
|
||||
- const: qcom,msm8996-cci # CCI v2
|
||||
|
||||
"#address-cells":
|
||||
@@ -224,6 +225,7 @@ allOf:
|
||||
enum:
|
||||
- qcom,sm8550-cci
|
||||
- qcom,sm8650-cci
|
||||
- qcom,x1e80100-cci
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
|
||||
@@ -26,7 +26,9 @@ properties:
|
||||
- const: renesas,riic-rz # RZ/A or RZ/G2L
|
||||
|
||||
- items:
|
||||
- const: renesas,riic-r9a08g045 # RZ/G3S
|
||||
- enum:
|
||||
- renesas,riic-r9a08g045 # RZ/G3S
|
||||
- renesas,riic-r9a09g047 # RZ/G3E
|
||||
- const: renesas,riic-r9a09g057 # RZ/V2H(P)
|
||||
|
||||
- const: renesas,riic-r9a09g057 # RZ/V2H(P)
|
||||
@@ -89,6 +91,7 @@ if:
|
||||
- renesas,riic-r9a07g043
|
||||
- renesas,riic-r9a07g044
|
||||
- renesas,riic-r9a07g054
|
||||
- renesas,riic-r9a09g057
|
||||
then:
|
||||
required:
|
||||
- resets
|
||||
|
||||
@@ -1204,6 +1204,8 @@ patternProperties:
|
||||
description: PulsedLight, Inc
|
||||
"^purism,.*":
|
||||
description: Purism, SPC
|
||||
"^puya,.*":
|
||||
description: Puya Semiconductor (Shanghai) Co., Ltd.
|
||||
"^qca,.*":
|
||||
description: Qualcomm Atheros, Inc.
|
||||
"^qcom,.*":
|
||||
|
||||
@@ -503,7 +503,7 @@ config I2C_BRCMSTB
|
||||
tristate "BRCM Settop/DSL I2C controller"
|
||||
depends on ARCH_BCM2835 || ARCH_BCMBCA || ARCH_BRCMSTB || \
|
||||
BMIPS_GENERIC || COMPILE_TEST
|
||||
default y
|
||||
default ARCH_BCM2835 || ARCH_BCMBCA || ARCH_BRCMSTB || BMIPS_GENERIC
|
||||
help
|
||||
If you say yes to this option, support will be included for the
|
||||
I2C interface on the Broadcom Settop/DSL SoCs.
|
||||
@@ -910,7 +910,7 @@ config I2C_MXS
|
||||
|
||||
config I2C_NOMADIK
|
||||
tristate "ST-Ericsson Nomadik/Ux500 I2C Controller"
|
||||
depends on ARM_AMBA
|
||||
depends on ARM_AMBA || COMPILE_TEST
|
||||
help
|
||||
If you say yes to this option, support will be included for the
|
||||
I2C interface from ST-Ericsson's Nomadik and Ux500 architectures,
|
||||
|
||||
@@ -211,7 +211,7 @@ static s32 amd756_access(struct i2c_adapter * adap, u16 addr,
|
||||
SMB_HOST_ADDRESS);
|
||||
outb_p(command, SMB_HOST_COMMAND);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
outw_p(data->word, SMB_HOST_DATA); /* TODO: endian???? */
|
||||
outw_p(data->word, SMB_HOST_DATA);
|
||||
size = AMD756_WORD_DATA;
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
@@ -256,7 +256,7 @@ static s32 amd756_access(struct i2c_adapter * adap, u16 addr,
|
||||
data->byte = inw_p(SMB_HOST_DATA);
|
||||
break;
|
||||
case AMD756_WORD_DATA:
|
||||
data->word = inw_p(SMB_HOST_DATA); /* TODO: endian???? */
|
||||
data->word = inw_p(SMB_HOST_DATA);
|
||||
break;
|
||||
case AMD756_BLOCK_DATA:
|
||||
data->block[0] = inw_p(SMB_HOST_DATA) & 0x3f;
|
||||
|
||||
@@ -11,23 +11,23 @@
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_data/i2c-davinci.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
/* ----- global defines ----------------------------------------------- */
|
||||
|
||||
@@ -117,6 +117,8 @@
|
||||
/* timeout for pm runtime autosuspend */
|
||||
#define DAVINCI_I2C_PM_TIMEOUT 1000 /* ms */
|
||||
|
||||
#define DAVINCI_I2C_DEFAULT_BUS_FREQ 100
|
||||
|
||||
struct davinci_i2c_dev {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
@@ -132,13 +134,10 @@ struct davinci_i2c_dev {
|
||||
#ifdef CONFIG_CPU_FREQ
|
||||
struct notifier_block freq_transition;
|
||||
#endif
|
||||
struct davinci_i2c_platform_data *pdata;
|
||||
};
|
||||
|
||||
/* default platform data to use if not supplied in the platform_device */
|
||||
static struct davinci_i2c_platform_data davinci_i2c_platform_data_default = {
|
||||
.bus_freq = 100,
|
||||
.bus_delay = 0,
|
||||
/* standard bus frequency (kHz) */
|
||||
unsigned int bus_freq;
|
||||
/* Chip has a ICPFUNC register */
|
||||
bool has_pfunc;
|
||||
};
|
||||
|
||||
static inline void davinci_i2c_write_reg(struct davinci_i2c_dev *i2c_dev,
|
||||
@@ -168,14 +167,12 @@ static inline void davinci_i2c_reset_ctrl(struct davinci_i2c_dev *i2c_dev,
|
||||
|
||||
static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev)
|
||||
{
|
||||
struct davinci_i2c_platform_data *pdata = dev->pdata;
|
||||
u16 psc;
|
||||
u32 clk;
|
||||
u32 d;
|
||||
u32 clkh;
|
||||
u32 clkl;
|
||||
u32 input_clock = clk_get_rate(dev->clk);
|
||||
struct device_node *of_node = dev->dev->of_node;
|
||||
|
||||
/* NOTE: I2C Clock divider programming info
|
||||
* As per I2C specs the following formulas provide prescaler
|
||||
@@ -209,19 +206,19 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev)
|
||||
psc++; /* better to run under spec than over */
|
||||
d = (psc >= 2) ? 5 : 7 - psc;
|
||||
|
||||
if (of_node && of_device_is_compatible(of_node, "ti,keystone-i2c"))
|
||||
if (device_is_compatible(dev->dev, "ti,keystone-i2c"))
|
||||
d = 6;
|
||||
|
||||
clk = ((input_clock / (psc + 1)) / (pdata->bus_freq * 1000));
|
||||
clk = ((input_clock / (psc + 1)) / (dev->bus_freq * 1000));
|
||||
/* Avoid driving the bus too fast because of rounding errors above */
|
||||
if (input_clock / (psc + 1) / clk > pdata->bus_freq * 1000)
|
||||
if (input_clock / (psc + 1) / clk > dev->bus_freq * 1000)
|
||||
clk++;
|
||||
/*
|
||||
* According to I2C-BUS Spec 2.1, in FAST-MODE LOW period should be at
|
||||
* least 1.3uS, which is not the case with 50% duty cycle. Driving HIGH
|
||||
* to LOW ratio as 1 to 2 is more safe.
|
||||
*/
|
||||
if (pdata->bus_freq > 100)
|
||||
if (dev->bus_freq > 100)
|
||||
clkl = (clk << 1) / 3;
|
||||
else
|
||||
clkl = (clk >> 1);
|
||||
@@ -255,8 +252,6 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev)
|
||||
*/
|
||||
static int i2c_davinci_init(struct davinci_i2c_dev *dev)
|
||||
{
|
||||
struct davinci_i2c_platform_data *pdata = dev->pdata;
|
||||
|
||||
/* put I2C into reset */
|
||||
davinci_i2c_reset_ctrl(dev, 0);
|
||||
|
||||
@@ -274,8 +269,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
|
||||
davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKL_REG));
|
||||
dev_dbg(dev->dev, "CLKH = %d\n",
|
||||
davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKH_REG));
|
||||
dev_dbg(dev->dev, "bus_freq = %dkHz, bus_delay = %d\n",
|
||||
pdata->bus_freq, pdata->bus_delay);
|
||||
dev_dbg(dev->dev, "bus_freq = %dkHz\n", dev->bus_freq);
|
||||
|
||||
|
||||
/* Take the I2C module out of reset: */
|
||||
@@ -309,12 +303,6 @@ static void davinci_i2c_unprepare_recovery(struct i2c_adapter *adap)
|
||||
i2c_davinci_init(dev);
|
||||
}
|
||||
|
||||
static struct i2c_bus_recovery_info davinci_i2c_gpio_recovery_info = {
|
||||
.recover_bus = i2c_generic_scl_recovery,
|
||||
.prepare_recovery = davinci_i2c_prepare_recovery,
|
||||
.unprepare_recovery = davinci_i2c_unprepare_recovery,
|
||||
};
|
||||
|
||||
static void davinci_i2c_set_scl(struct i2c_adapter *adap, int val)
|
||||
{
|
||||
struct davinci_i2c_dev *dev = i2c_get_adapdata(adap);
|
||||
@@ -414,7 +402,6 @@ static int
|
||||
i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
|
||||
{
|
||||
struct davinci_i2c_dev *dev = i2c_get_adapdata(adap);
|
||||
struct davinci_i2c_platform_data *pdata = dev->pdata;
|
||||
u32 flag;
|
||||
u16 w;
|
||||
unsigned long time_left;
|
||||
@@ -424,10 +411,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
/* Introduce a delay, required for some boards (e.g Davinci EVM) */
|
||||
if (pdata->bus_delay)
|
||||
udelay(pdata->bus_delay);
|
||||
|
||||
/* set the target address */
|
||||
davinci_i2c_write_reg(dev, DAVINCI_I2C_SAR_REG, msg->addr);
|
||||
|
||||
@@ -758,8 +741,8 @@ static int davinci_i2c_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct davinci_i2c_dev *dev;
|
||||
struct i2c_adapter *adap;
|
||||
struct i2c_bus_recovery_info *rinfo;
|
||||
int r, irq;
|
||||
u32 prop;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
@@ -773,29 +756,15 @@ static int davinci_i2c_probe(struct platform_device *pdev)
|
||||
|
||||
dev->dev = &pdev->dev;
|
||||
dev->irq = irq;
|
||||
dev->pdata = dev_get_platdata(&pdev->dev);
|
||||
platform_set_drvdata(pdev, dev);
|
||||
|
||||
if (!dev->pdata && pdev->dev.of_node) {
|
||||
u32 prop;
|
||||
r = device_property_read_u32(&pdev->dev, "clock-frequency", &prop);
|
||||
if (r)
|
||||
prop = DAVINCI_I2C_DEFAULT_BUS_FREQ;
|
||||
|
||||
dev->pdata = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct davinci_i2c_platform_data), GFP_KERNEL);
|
||||
if (!dev->pdata)
|
||||
return -ENOMEM;
|
||||
dev->bus_freq = prop / 1000;
|
||||
|
||||
memcpy(dev->pdata, &davinci_i2c_platform_data_default,
|
||||
sizeof(struct davinci_i2c_platform_data));
|
||||
if (!of_property_read_u32(pdev->dev.of_node, "clock-frequency",
|
||||
&prop))
|
||||
dev->pdata->bus_freq = prop / 1000;
|
||||
|
||||
dev->pdata->has_pfunc =
|
||||
of_property_read_bool(pdev->dev.of_node,
|
||||
"ti,has-pfunc");
|
||||
} else if (!dev->pdata) {
|
||||
dev->pdata = &davinci_i2c_platform_data_default;
|
||||
}
|
||||
dev->has_pfunc = device_property_present(&pdev->dev, "ti,has-pfunc");
|
||||
|
||||
dev->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(dev->clk))
|
||||
@@ -841,25 +810,10 @@ static int davinci_i2c_probe(struct platform_device *pdev)
|
||||
adap->algo = &i2c_davinci_algo;
|
||||
adap->dev.parent = &pdev->dev;
|
||||
adap->timeout = DAVINCI_I2C_TIMEOUT;
|
||||
adap->dev.of_node = pdev->dev.of_node;
|
||||
adap->dev.of_node = dev_of_node(&pdev->dev);
|
||||
|
||||
if (dev->pdata->has_pfunc)
|
||||
if (dev->has_pfunc)
|
||||
adap->bus_recovery_info = &davinci_i2c_scl_recovery_info;
|
||||
else if (dev->pdata->gpio_recovery) {
|
||||
rinfo = &davinci_i2c_gpio_recovery_info;
|
||||
adap->bus_recovery_info = rinfo;
|
||||
rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl",
|
||||
GPIOD_OUT_HIGH_OPEN_DRAIN);
|
||||
if (IS_ERR(rinfo->scl_gpiod)) {
|
||||
r = PTR_ERR(rinfo->scl_gpiod);
|
||||
goto err_unuse_clocks;
|
||||
}
|
||||
rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_IN);
|
||||
if (IS_ERR(rinfo->sda_gpiod)) {
|
||||
r = PTR_ERR(rinfo->sda_gpiod);
|
||||
goto err_unuse_clocks;
|
||||
}
|
||||
}
|
||||
|
||||
adap->nr = pdev->id;
|
||||
r = i2c_add_numbered_adapter(adap);
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
* Copyright (C) 2007 MontaVista Software Inc.
|
||||
* Copyright (C) 2009 Provigent Ltd.
|
||||
*/
|
||||
|
||||
#define DEFAULT_SYMBOL_NAMESPACE "I2C_DW_COMMON"
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
@@ -29,8 +32,6 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#define DEFAULT_SYMBOL_NAMESPACE "I2C_DW_COMMON"
|
||||
|
||||
#include "i2c-designware-core.h"
|
||||
|
||||
static const char *const abort_sources[] = {
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
* Copyright (C) 2007 MontaVista Software Inc.
|
||||
* Copyright (C) 2009 Provigent Ltd.
|
||||
*/
|
||||
|
||||
#define DEFAULT_SYMBOL_NAMESPACE "I2C_DW"
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
@@ -22,8 +25,6 @@
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
#define DEFAULT_SYMBOL_NAMESPACE "I2C_DW"
|
||||
|
||||
#include "i2c-designware-core.h"
|
||||
|
||||
#define AMD_TIMEOUT_MIN_US 25
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
*
|
||||
* Copyright (C) 2016 Synopsys Inc.
|
||||
*/
|
||||
|
||||
#define DEFAULT_SYMBOL_NAMESPACE "I2C_DW"
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
@@ -16,8 +19,6 @@
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define DEFAULT_SYMBOL_NAMESPACE "I2C_DW"
|
||||
|
||||
#include "i2c-designware-core.h"
|
||||
|
||||
static void i2c_dw_configure_fifo_slave(struct dw_i2c_dev *dev)
|
||||
|
||||
@@ -168,6 +168,7 @@ enum i2c_type_exynos {
|
||||
I2C_TYPE_EXYNOS5,
|
||||
I2C_TYPE_EXYNOS7,
|
||||
I2C_TYPE_EXYNOSAUTOV9,
|
||||
I2C_TYPE_EXYNOS8895,
|
||||
};
|
||||
|
||||
struct exynos5_i2c {
|
||||
@@ -240,6 +241,11 @@ static const struct exynos_hsi2c_variant exynosautov9_hsi2c_data = {
|
||||
.hw = I2C_TYPE_EXYNOSAUTOV9,
|
||||
};
|
||||
|
||||
static const struct exynos_hsi2c_variant exynos8895_hsi2c_data = {
|
||||
.fifo_depth = 64,
|
||||
.hw = I2C_TYPE_EXYNOS8895,
|
||||
};
|
||||
|
||||
static const struct of_device_id exynos5_i2c_match[] = {
|
||||
{
|
||||
.compatible = "samsung,exynos5-hsi2c",
|
||||
@@ -256,6 +262,9 @@ static const struct of_device_id exynos5_i2c_match[] = {
|
||||
}, {
|
||||
.compatible = "samsung,exynosautov9-hsi2c",
|
||||
.data = &exynosautov9_hsi2c_data
|
||||
}, {
|
||||
.compatible = "samsung,exynos8895-hsi2c",
|
||||
.data = &exynos8895_hsi2c_data
|
||||
}, {},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, exynos5_i2c_match);
|
||||
@@ -331,6 +340,14 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings)
|
||||
* clk_cycle := TSCLK_L + TSCLK_H
|
||||
* temp := (CLK_DIV + 1) * (clk_cycle + 2)
|
||||
*
|
||||
* In case of HSI2C controllers in Exynos8895
|
||||
* FPCLK / FI2C =
|
||||
* (CLK_DIV + 1) * (TSCLK_L + TSCLK_H + 2) +
|
||||
* 2 * ((FLT_CYCLE + 3) - (FLT_CYCLE + 3) % (CLK_DIV + 1))
|
||||
*
|
||||
* clk_cycle := TSCLK_L + TSCLK_H
|
||||
* temp := (FPCLK / FI2C) - (FLT_CYCLE + 3) * 2
|
||||
*
|
||||
* Constraints: 4 <= temp, 0 <= CLK_DIV < 256, 2 <= clk_cycle <= 510
|
||||
*
|
||||
* To split SCL clock into low, high periods appropriately, one
|
||||
@@ -352,11 +369,19 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings)
|
||||
*
|
||||
*/
|
||||
t_ftl_cycle = (readl(i2c->regs + HSI2C_CONF) >> 16) & 0x7;
|
||||
temp = clkin / op_clk - 8 - t_ftl_cycle;
|
||||
if (i2c->variant->hw != I2C_TYPE_EXYNOS7)
|
||||
temp -= t_ftl_cycle;
|
||||
if (i2c->variant->hw == I2C_TYPE_EXYNOS8895)
|
||||
temp = clkin / op_clk - (t_ftl_cycle + 3) * 2;
|
||||
else if (i2c->variant->hw == I2C_TYPE_EXYNOS7)
|
||||
temp = clkin / op_clk - 8 - t_ftl_cycle;
|
||||
else
|
||||
temp = clkin / op_clk - 8 - (t_ftl_cycle * 2);
|
||||
div = temp / 512;
|
||||
clk_cycle = temp / (div + 1) - 2;
|
||||
|
||||
if (i2c->variant->hw == I2C_TYPE_EXYNOS8895)
|
||||
clk_cycle = (temp + ((t_ftl_cycle + 3) % (div + 1)) * 2) /
|
||||
(div + 1) - 2;
|
||||
else
|
||||
clk_cycle = temp / (div + 1) - 2;
|
||||
if (temp < 4 || div >= 256 || clk_cycle < 2) {
|
||||
dev_err(i2c->dev, "%s clock set-up failed\n",
|
||||
hs_timings ? "HS" : "FS");
|
||||
@@ -491,6 +516,8 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)
|
||||
switch (i2c->variant->hw) {
|
||||
case I2C_TYPE_EXYNOSAUTOV9:
|
||||
fallthrough;
|
||||
case I2C_TYPE_EXYNOS8895:
|
||||
fallthrough;
|
||||
case I2C_TYPE_EXYNOS7:
|
||||
if (int_status & HSI2C_INT_TRANS_DONE) {
|
||||
i2c->trans_done = 1;
|
||||
|
||||
@@ -1252,6 +1252,7 @@ static const struct {
|
||||
*/
|
||||
{ "Latitude 5480", 0x29 },
|
||||
{ "Precision 3540", 0x29 },
|
||||
{ "Precision M6800", 0x29 },
|
||||
{ "Vostro V131", 0x1d },
|
||||
{ "Vostro 5568", 0x29 },
|
||||
{ "XPS 15 7590", 0x29 },
|
||||
@@ -1682,13 +1683,16 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
if (!(priv->features & FEATURE_BLOCK_BUFFER))
|
||||
priv->features &= ~FEATURE_BLOCK_PROC;
|
||||
|
||||
err = pcim_enable_device(dev);
|
||||
/*
|
||||
* Do not call pcim_enable_device(), because the device has to remain
|
||||
* enabled on driver detach. See i801_remove() for the reasoning.
|
||||
*/
|
||||
err = pci_enable_device(dev);
|
||||
if (err) {
|
||||
dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
pcim_pin_device(dev);
|
||||
|
||||
/* Determine the address of the SMBus area */
|
||||
priv->smba = pci_resource_start(dev, SMBBAR);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -397,17 +397,16 @@ static void i2c_imx_reset_regs(struct imx_i2c_struct *i2c_imx)
|
||||
}
|
||||
|
||||
/* Functions for DMA support */
|
||||
static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
|
||||
dma_addr_t phy_addr)
|
||||
static int i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx, dma_addr_t phy_addr)
|
||||
{
|
||||
struct imx_i2c_dma *dma;
|
||||
struct dma_slave_config dma_sconfig;
|
||||
struct device *dev = &i2c_imx->adapter.dev;
|
||||
struct device *dev = i2c_imx->adapter.dev.parent;
|
||||
int ret;
|
||||
|
||||
dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
|
||||
if (!dma)
|
||||
return;
|
||||
return -ENOMEM;
|
||||
|
||||
dma->chan_tx = dma_request_chan(dev, "tx");
|
||||
if (IS_ERR(dma->chan_tx)) {
|
||||
@@ -452,7 +451,7 @@ static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
|
||||
dev_info(dev, "using %s (tx) and %s (rx) for DMA transfers\n",
|
||||
dma_chan_name(dma->chan_tx), dma_chan_name(dma->chan_rx));
|
||||
|
||||
return;
|
||||
return 0;
|
||||
|
||||
fail_rx:
|
||||
dma_release_channel(dma->chan_rx);
|
||||
@@ -460,6 +459,8 @@ fail_tx:
|
||||
dma_release_channel(dma->chan_tx);
|
||||
fail_al:
|
||||
devm_kfree(dev, dma);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void i2c_imx_dma_callback(void *arg)
|
||||
@@ -621,8 +622,8 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
|
||||
unsigned int i2c_clk_rate)
|
||||
static int 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;
|
||||
unsigned int div;
|
||||
@@ -637,7 +638,11 @@ static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
|
||||
|
||||
/* Divider value calculation */
|
||||
if (i2c_imx->cur_clk == i2c_clk_rate)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
/* Keep the denominator of the following program always NOT equal to 0. */
|
||||
if (!(i2c_clk_rate / 2))
|
||||
return -EINVAL;
|
||||
|
||||
i2c_imx->cur_clk = i2c_clk_rate;
|
||||
|
||||
@@ -668,6 +673,8 @@ static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
|
||||
dev_dbg(&i2c_imx->adapter.dev, "IFDR[IC]=0x%x, REAL DIV=%d\n",
|
||||
i2c_clk_div[i].val, i2c_clk_div[i].div);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2c_imx_clk_notifier_call(struct notifier_block *nb,
|
||||
@@ -677,11 +684,12 @@ static int i2c_imx_clk_notifier_call(struct notifier_block *nb,
|
||||
struct imx_i2c_struct *i2c_imx = container_of(nb,
|
||||
struct imx_i2c_struct,
|
||||
clk_change_nb);
|
||||
int ret = 0;
|
||||
|
||||
if (action & POST_RATE_CHANGE)
|
||||
i2c_imx_set_clk(i2c_imx, ndata->new_rate);
|
||||
ret = i2c_imx_set_clk(i2c_imx, ndata->new_rate);
|
||||
|
||||
return NOTIFY_OK;
|
||||
return notifier_from_errno(ret);
|
||||
}
|
||||
|
||||
static int i2c_imx_start(struct imx_i2c_struct *i2c_imx, bool atomic)
|
||||
@@ -1760,7 +1768,8 @@ static int i2c_imx_probe(struct platform_device *pdev)
|
||||
goto rpm_disable;
|
||||
|
||||
/* Request IRQ */
|
||||
ret = request_irq(irq, i2c_imx_isr, IRQF_SHARED, pdev->name, i2c_imx);
|
||||
ret = request_irq(irq, i2c_imx_isr, IRQF_SHARED | IRQF_NO_SUSPEND,
|
||||
pdev->name, i2c_imx);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "can't claim irq %d\n", irq);
|
||||
goto rpm_disable;
|
||||
@@ -1780,7 +1789,11 @@ static int i2c_imx_probe(struct platform_device *pdev)
|
||||
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));
|
||||
ret = i2c_imx_set_clk(i2c_imx, clk_get_rate(i2c_imx->clk));
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "can't get I2C clock\n");
|
||||
goto clk_notifier_unregister;
|
||||
}
|
||||
|
||||
i2c_imx_reset_regs(i2c_imx);
|
||||
|
||||
@@ -1790,6 +1803,22 @@ static int i2c_imx_probe(struct platform_device *pdev)
|
||||
if (ret == -EPROBE_DEFER)
|
||||
goto clk_notifier_unregister;
|
||||
|
||||
/*
|
||||
* DMA mode should be optional for I2C, when encountering DMA errors,
|
||||
* no need to exit I2C probe. Only print warning to show DMA error and
|
||||
* use PIO mode directly to ensure I2C bus available as much as possible.
|
||||
*/
|
||||
ret = i2c_imx_dma_request(i2c_imx, phy_addr);
|
||||
if (ret) {
|
||||
if (ret == -EPROBE_DEFER)
|
||||
goto clk_notifier_unregister;
|
||||
else if (ret == -ENODEV)
|
||||
dev_dbg(&pdev->dev, "Only use PIO mode\n");
|
||||
else
|
||||
dev_warn(&pdev->dev, "Failed to setup DMA (%pe), only use PIO mode\n",
|
||||
ERR_PTR(ret));
|
||||
}
|
||||
|
||||
/* Add I2C adapter */
|
||||
ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
|
||||
if (ret < 0)
|
||||
@@ -1804,9 +1833,6 @@ static int i2c_imx_probe(struct platform_device *pdev)
|
||||
i2c_imx->adapter.name);
|
||||
dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");
|
||||
|
||||
/* Init DMA config if supported */
|
||||
i2c_imx_dma_request(i2c_imx, phy_addr);
|
||||
|
||||
return 0; /* Return OK */
|
||||
|
||||
clk_notifier_unregister:
|
||||
@@ -1858,8 +1884,7 @@ static int i2c_imx_runtime_suspend(struct device *dev)
|
||||
struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
|
||||
|
||||
clk_disable(i2c_imx->clk);
|
||||
|
||||
return 0;
|
||||
return pinctrl_pm_select_sleep_state(dev);
|
||||
}
|
||||
|
||||
static int i2c_imx_runtime_resume(struct device *dev)
|
||||
@@ -1867,6 +1892,10 @@ static int i2c_imx_runtime_resume(struct device *dev)
|
||||
struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = pinctrl_pm_select_default_state(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_enable(i2c_imx->clk);
|
||||
if (ret)
|
||||
dev_err(dev, "can't enable I2C clock, ret=%d\n", ret);
|
||||
@@ -1874,7 +1903,43 @@ static int i2c_imx_runtime_resume(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int i2c_imx_suspend(struct device *dev)
|
||||
{
|
||||
/*
|
||||
* Some I2C devices may need the I2C controller to remain active
|
||||
* during resume_noirq() or suspend_noirq(). If the controller is
|
||||
* autosuspended, there is no way to wake it up once runtime PM is
|
||||
* disabled (in suspend_late()).
|
||||
*
|
||||
* During system resume, the I2C controller will be available only
|
||||
* after runtime PM is re-enabled (in resume_early()). However, this
|
||||
* may be too late for some devices.
|
||||
*
|
||||
* Wake up the controller in the suspend() callback while runtime PM
|
||||
* is still enabled. The I2C controller will remain available until
|
||||
* the suspend_noirq() callback (pm_runtime_force_suspend()) is
|
||||
* called. During resume, the I2C controller can be restored by the
|
||||
* resume_noirq() callback (pm_runtime_force_resume()).
|
||||
*
|
||||
* Finally, the resume() callback re-enables autosuspend, ensuring
|
||||
* the I2C controller remains available until the system enters
|
||||
* suspend_noirq() and from resume_noirq().
|
||||
*/
|
||||
return pm_runtime_resume_and_get(dev);
|
||||
}
|
||||
|
||||
static int i2c_imx_resume(struct device *dev)
|
||||
{
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops i2c_imx_pm_ops = {
|
||||
NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
SYSTEM_SLEEP_PM_OPS(i2c_imx_suspend, i2c_imx_resume)
|
||||
RUNTIME_PM_OPS(i2c_imx_runtime_suspend, i2c_imx_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
|
||||
@@ -291,9 +291,9 @@ static int smbus_sch_probe(struct platform_device *pdev)
|
||||
|
||||
/* Set up the sysfs linkage to our parent device */
|
||||
priv->adapter.dev.parent = dev;
|
||||
priv->adapter.owner = THIS_MODULE,
|
||||
priv->adapter.class = I2C_CLASS_HWMON,
|
||||
priv->adapter.algo = &smbus_algorithm,
|
||||
priv->adapter.owner = THIS_MODULE;
|
||||
priv->adapter.class = I2C_CLASS_HWMON;
|
||||
priv->adapter.algo = &smbus_algorithm;
|
||||
|
||||
snprintf(priv->adapter.name, sizeof(priv->adapter.name),
|
||||
"SMBus SCH adapter at %04x", (unsigned short)res->start);
|
||||
|
||||
@@ -464,12 +464,8 @@ static void ki2c_unregister_devices(struct ki2c *ki2c)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ki2c->client_size; i++) {
|
||||
struct i2c_client *client = ki2c->client[i];
|
||||
|
||||
if (client)
|
||||
i2c_unregister_device(client);
|
||||
}
|
||||
for (i = 0; i < ki2c->client_size; i++)
|
||||
i2c_unregister_device(ki2c->client[i]);
|
||||
}
|
||||
|
||||
static int ki2c_register_devices(struct ki2c *ki2c)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -823,11 +823,9 @@ static int geni_i2c_probe(struct platform_device *pdev)
|
||||
return gi2c->irq;
|
||||
|
||||
ret = geni_i2c_clk_map_idx(gi2c);
|
||||
if (ret) {
|
||||
dev_err(dev, "Invalid clk frequency %d Hz: %d\n",
|
||||
gi2c->clk_freq_out, ret);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Invalid clk frequency %d Hz\n",
|
||||
gi2c->clk_freq_out);
|
||||
|
||||
gi2c->adap.algo = &geni_i2c_algo;
|
||||
init_completion(&gi2c->done);
|
||||
@@ -837,11 +835,10 @@ static int geni_i2c_probe(struct platform_device *pdev)
|
||||
/* Keep interrupts disabled initially to allow for low-power modes */
|
||||
ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, IRQF_NO_AUTOEN,
|
||||
dev_name(dev), gi2c);
|
||||
if (ret) {
|
||||
dev_err(dev, "Request_irq failed:%d: err:%d\n",
|
||||
gi2c->irq, ret);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"Request_irq failed: %d\n", gi2c->irq);
|
||||
|
||||
i2c_set_adapdata(&gi2c->adap, gi2c);
|
||||
gi2c->adap.dev.parent = dev;
|
||||
gi2c->adap.dev.of_node = dev->of_node;
|
||||
@@ -870,16 +867,13 @@ static int geni_i2c_probe(struct platform_device *pdev)
|
||||
|
||||
ret = geni_se_resources_on(&gi2c->se);
|
||||
if (ret) {
|
||||
dev_err(dev, "Error turning on resources %d\n", ret);
|
||||
clk_disable_unprepare(gi2c->core_clk);
|
||||
return ret;
|
||||
dev_err_probe(dev, ret, "Error turning on resources\n");
|
||||
goto err_clk;
|
||||
}
|
||||
proto = geni_se_read_proto(&gi2c->se);
|
||||
if (proto != GENI_SE_I2C) {
|
||||
dev_err(dev, "Invalid proto %d\n", proto);
|
||||
geni_se_resources_off(&gi2c->se);
|
||||
clk_disable_unprepare(gi2c->core_clk);
|
||||
return -ENXIO;
|
||||
ret = dev_err_probe(dev, -ENXIO, "Invalid proto %d\n", proto);
|
||||
goto err_resources;
|
||||
}
|
||||
|
||||
if (desc && desc->no_dma_support)
|
||||
@@ -891,11 +885,8 @@ static int geni_i2c_probe(struct platform_device *pdev)
|
||||
/* FIFO is disabled, so we can only use GPI DMA */
|
||||
gi2c->gpi_mode = true;
|
||||
ret = setup_gpi_dma(gi2c);
|
||||
if (ret) {
|
||||
geni_se_resources_off(&gi2c->se);
|
||||
clk_disable_unprepare(gi2c->core_clk);
|
||||
return dev_err_probe(dev, ret, "Failed to setup GPI DMA mode\n");
|
||||
}
|
||||
if (ret)
|
||||
goto err_resources;
|
||||
|
||||
dev_dbg(dev, "Using GPI DMA mode for I2C\n");
|
||||
} else {
|
||||
@@ -907,10 +898,9 @@ static int geni_i2c_probe(struct platform_device *pdev)
|
||||
tx_depth = desc->tx_fifo_depth;
|
||||
|
||||
if (!tx_depth) {
|
||||
dev_err(dev, "Invalid TX FIFO depth\n");
|
||||
geni_se_resources_off(&gi2c->se);
|
||||
clk_disable_unprepare(gi2c->core_clk);
|
||||
return -EINVAL;
|
||||
ret = dev_err_probe(dev, -EINVAL,
|
||||
"Invalid TX FIFO depth\n");
|
||||
goto err_resources;
|
||||
}
|
||||
|
||||
gi2c->tx_wm = tx_depth - 1;
|
||||
@@ -924,7 +914,7 @@ static int geni_i2c_probe(struct platform_device *pdev)
|
||||
clk_disable_unprepare(gi2c->core_clk);
|
||||
ret = geni_se_resources_off(&gi2c->se);
|
||||
if (ret) {
|
||||
dev_err(dev, "Error turning off resources %d\n", ret);
|
||||
dev_err_probe(dev, ret, "Error turning off resources\n");
|
||||
goto err_dma;
|
||||
}
|
||||
|
||||
@@ -940,17 +930,25 @@ static int geni_i2c_probe(struct platform_device *pdev)
|
||||
|
||||
ret = i2c_add_adapter(&gi2c->adap);
|
||||
if (ret) {
|
||||
dev_err(dev, "Error adding i2c adapter %d\n", ret);
|
||||
dev_err_probe(dev, ret, "Error adding i2c adapter\n");
|
||||
pm_runtime_disable(gi2c->se.dev);
|
||||
goto err_dma;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "Geni-I2C adaptor successfully added\n");
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
|
||||
err_resources:
|
||||
geni_se_resources_off(&gi2c->se);
|
||||
err_clk:
|
||||
clk_disable_unprepare(gi2c->core_clk);
|
||||
|
||||
return ret;
|
||||
|
||||
err_dma:
|
||||
release_gpi_dma(gi2c);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,46 +34,51 @@
|
||||
* Also check the comments in the interrupt routines for some gory details.
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/time.h>
|
||||
|
||||
#define ICCR1_ICE 0x80
|
||||
#define ICCR1_IICRST 0x40
|
||||
#define ICCR1_SOWP 0x10
|
||||
#define ICCR1_ICE BIT(7)
|
||||
#define ICCR1_IICRST BIT(6)
|
||||
#define ICCR1_SOWP BIT(4)
|
||||
#define ICCR1_SCLI BIT(1)
|
||||
#define ICCR1_SDAI BIT(0)
|
||||
|
||||
#define ICCR2_BBSY 0x80
|
||||
#define ICCR2_SP 0x08
|
||||
#define ICCR2_RS 0x04
|
||||
#define ICCR2_ST 0x02
|
||||
#define ICCR2_BBSY BIT(7)
|
||||
#define ICCR2_SP BIT(3)
|
||||
#define ICCR2_RS BIT(2)
|
||||
#define ICCR2_ST BIT(1)
|
||||
|
||||
#define ICMR1_CKS_MASK 0x70
|
||||
#define ICMR1_BCWP 0x08
|
||||
#define ICMR1_CKS_MASK GENMASK(6, 4)
|
||||
#define ICMR1_BCWP BIT(3)
|
||||
#define ICMR1_CKS(_x) ((((_x) << 4) & ICMR1_CKS_MASK) | ICMR1_BCWP)
|
||||
|
||||
#define ICMR3_RDRFS 0x20
|
||||
#define ICMR3_ACKWP 0x10
|
||||
#define ICMR3_ACKBT 0x08
|
||||
#define ICMR3_RDRFS BIT(5)
|
||||
#define ICMR3_ACKWP BIT(4)
|
||||
#define ICMR3_ACKBT BIT(3)
|
||||
|
||||
#define ICFER_FMPE 0x80
|
||||
#define ICFER_FMPE BIT(7)
|
||||
|
||||
#define ICIER_TIE 0x80
|
||||
#define ICIER_TEIE 0x40
|
||||
#define ICIER_RIE 0x20
|
||||
#define ICIER_NAKIE 0x10
|
||||
#define ICIER_SPIE 0x08
|
||||
#define ICIER_TIE BIT(7)
|
||||
#define ICIER_TEIE BIT(6)
|
||||
#define ICIER_RIE BIT(5)
|
||||
#define ICIER_NAKIE BIT(4)
|
||||
#define ICIER_SPIE BIT(3)
|
||||
|
||||
#define ICSR2_NACKF 0x10
|
||||
#define ICSR2_NACKF BIT(4)
|
||||
|
||||
#define ICBR_RESERVED 0xe0 /* Should be 1 on writes */
|
||||
#define ICBR_RESERVED GENMASK(7, 5) /* Should be 1 on writes */
|
||||
|
||||
#define RIIC_INIT_MSG -1
|
||||
|
||||
@@ -134,6 +139,27 @@ static inline void riic_clear_set_bit(struct riic_dev *riic, u8 clear, u8 set, u
|
||||
riic_writeb(riic, (riic_readb(riic, reg) & ~clear) | set, reg);
|
||||
}
|
||||
|
||||
static int riic_bus_barrier(struct riic_dev *riic)
|
||||
{
|
||||
int ret;
|
||||
u8 val;
|
||||
|
||||
/*
|
||||
* The SDA line can still be low even when BBSY = 0. Therefore, after checking
|
||||
* the BBSY flag, also verify that the SDA and SCL lines are not being held low.
|
||||
*/
|
||||
ret = readb_poll_timeout(riic->base + riic->info->regs[RIIC_ICCR2], val,
|
||||
!(val & ICCR2_BBSY), 10, riic->adapter.timeout);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if ((riic_readb(riic, RIIC_ICCR1) & (ICCR1_SDAI | ICCR1_SCLI)) !=
|
||||
(ICCR1_SDAI | ICCR1_SCLI))
|
||||
return -EBUSY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int riic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
|
||||
{
|
||||
struct riic_dev *riic = i2c_get_adapdata(adap);
|
||||
@@ -146,13 +172,11 @@ static int riic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (riic_readb(riic, RIIC_ICCR2) & ICCR2_BBSY) {
|
||||
riic->err = -EBUSY;
|
||||
riic->err = riic_bus_barrier(riic);
|
||||
if (riic->err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
reinit_completion(&riic->msg_done);
|
||||
riic->err = 0;
|
||||
|
||||
riic_writeb(riic, 0, RIIC_ICSR2);
|
||||
|
||||
@@ -312,6 +336,7 @@ static int riic_init_hw(struct riic_dev *riic)
|
||||
{
|
||||
int ret;
|
||||
unsigned long rate;
|
||||
unsigned long ns_per_tick;
|
||||
int total_ticks, cks, brl, brh;
|
||||
struct i2c_timings *t = &riic->i2c_t;
|
||||
struct device *dev = riic->adapter.dev.parent;
|
||||
@@ -320,7 +345,7 @@ static int riic_init_hw(struct riic_dev *riic)
|
||||
: I2C_MAX_FAST_MODE_FREQ;
|
||||
|
||||
if (t->bus_freq_hz > max_freq)
|
||||
return dev_err_probe(&riic->adapter.dev, -EINVAL,
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"unsupported bus speed %uHz (%u max)\n",
|
||||
t->bus_freq_hz, max_freq);
|
||||
|
||||
@@ -356,11 +381,9 @@ static int riic_init_hw(struct riic_dev *riic)
|
||||
rate /= 2;
|
||||
}
|
||||
|
||||
if (brl > (0x1F + 3)) {
|
||||
dev_err(&riic->adapter.dev, "invalid speed (%lu). Too slow.\n",
|
||||
(unsigned long)t->bus_freq_hz);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (brl > (0x1F + 3))
|
||||
return dev_err_probe(dev, -EINVAL, "invalid speed (%uHz). Too slow.\n",
|
||||
t->bus_freq_hz);
|
||||
|
||||
brh = total_ticks - brl;
|
||||
|
||||
@@ -377,8 +400,9 @@ static int riic_init_hw(struct riic_dev *riic)
|
||||
* Remove clock ticks for rise and fall times. Convert ns to clock
|
||||
* ticks.
|
||||
*/
|
||||
brl -= t->scl_fall_ns / (1000000000 / rate);
|
||||
brh -= t->scl_rise_ns / (1000000000 / rate);
|
||||
ns_per_tick = NSEC_PER_SEC / rate;
|
||||
brl -= t->scl_fall_ns / ns_per_tick;
|
||||
brh -= t->scl_rise_ns / ns_per_tick;
|
||||
|
||||
/* Adjust for min register values for when SCLE=1 and NFE=1 */
|
||||
if (brl < 1)
|
||||
@@ -388,8 +412,7 @@ static int riic_init_hw(struct riic_dev *riic)
|
||||
|
||||
pr_debug("i2c-riic: freq=%lu, duty=%d, fall=%lu, rise=%lu, cks=%d, brl=%d, brh=%d\n",
|
||||
rate / total_ticks, ((brl + 3) * 100) / (brl + brh + 6),
|
||||
t->scl_fall_ns / (1000000000 / rate),
|
||||
t->scl_rise_ns / (1000000000 / rate), cks, brl, brh);
|
||||
t->scl_fall_ns / ns_per_tick, t->scl_rise_ns / ns_per_tick, cks, brl, brh);
|
||||
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret)
|
||||
@@ -416,7 +439,7 @@ static int riic_init_hw(struct riic_dev *riic)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct riic_irq_desc riic_irqs[] = {
|
||||
static const struct riic_irq_desc riic_irqs[] = {
|
||||
{ .res_num = 0, .isr = riic_tend_isr, .name = "riic-tend" },
|
||||
{ .res_num = 1, .isr = riic_rdrf_isr, .name = "riic-rdrf" },
|
||||
{ .res_num = 2, .isr = riic_tdre_isr, .name = "riic-tdre" },
|
||||
@@ -424,11 +447,6 @@ static struct riic_irq_desc riic_irqs[] = {
|
||||
{ .res_num = 5, .isr = riic_tend_isr, .name = "riic-nack" },
|
||||
};
|
||||
|
||||
static void riic_reset_control_assert(void *data)
|
||||
{
|
||||
reset_control_assert(data);
|
||||
}
|
||||
|
||||
static int riic_i2c_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@@ -445,35 +463,27 @@ static int riic_i2c_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(riic->base);
|
||||
|
||||
riic->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(riic->clk)) {
|
||||
dev_err(dev, "missing controller clock");
|
||||
return PTR_ERR(riic->clk);
|
||||
}
|
||||
if (IS_ERR(riic->clk))
|
||||
return dev_err_probe(dev, PTR_ERR(riic->clk),
|
||||
"missing controller clock");
|
||||
|
||||
riic->rstc = devm_reset_control_get_optional_exclusive(dev, NULL);
|
||||
riic->rstc = devm_reset_control_get_optional_exclusive_deasserted(dev, NULL);
|
||||
if (IS_ERR(riic->rstc))
|
||||
return dev_err_probe(dev, PTR_ERR(riic->rstc),
|
||||
"Error: missing reset ctrl\n");
|
||||
|
||||
ret = reset_control_deassert(riic->rstc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, riic_reset_control_assert, riic->rstc);
|
||||
if (ret)
|
||||
return ret;
|
||||
"failed to acquire deasserted reset\n");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(riic_irqs); i++) {
|
||||
ret = platform_get_irq(pdev, riic_irqs[i].res_num);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
int irq;
|
||||
|
||||
ret = devm_request_irq(dev, ret, riic_irqs[i].isr,
|
||||
irq = platform_get_irq(pdev, riic_irqs[i].res_num);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
ret = devm_request_irq(dev, irq, riic_irqs[i].isr,
|
||||
0, riic_irqs[i].name, riic);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to request irq %s\n", riic_irqs[i].name);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "failed to request irq %s\n",
|
||||
riic_irqs[i].name);
|
||||
}
|
||||
|
||||
riic->info = of_device_get_match_data(dev);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user