i2c-for-6.19-rc1

- general cleanups in bcm2835, designware, pcf8584, and stm32
 - amd-mp2: fix device refcount
 - designware: avoid interrupt storms caused by bad firmware
 - spacemit: fix device detection failures
 - new devices: Intel Diamond Rapids, Rockchip RK3506, Qualcomm Kaanapali
   and MSM8953
 - minor fixes to i801, core documentation, elektor Kconfig dependencies
 
 at24 updates:
 - add new compatible for Belling BL24S64
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEOZGx6rniZ1Gk92RdFA3kzBSgKbYFAmk4MacACgkQFA3kzBSg
 KbajAw/8CMDDB6ENq8aqnRqWCWEcjxcklIJi/6aDsnpUJr7jzf98hmrhlFzYQLqu
 iR6YMo9tt3eGTtv+CDAAABLIqQM5ivx155YSfw8tmfB7OZHpe8hTp72+aNJtJqup
 Rp8vu0vIbdcITE6ohxxJHi+DuBghq3CuZIxridx+ApV3JiuEQlqivvkZS2kz7hS6
 wYaUQWh8fc33HUY05jR1oJPoOyf2LkjNqcwSY3LF70GgiQ4TpMFOwWmKIsoW4u+/
 +i15bI8Vp5Q+DQ/Eu5GgDsSs188BGIY/Ydie50DB229ByetpCUrkjGN3MM8YMAP6
 TJHQtl7a6/zfgU5NCEWKKS1Pf1Pd5cVR8TvZcJ7tFiKCSU5het8QAIYtPqJ3ziJs
 WjRBAnkV6c5NVVzWuGx3wx/5NBQk1S5KLMGmjKqfHHRDdMGLnQYtXtf+rhOw0e+Y
 UjF6xG6JBtKYgbBe7vtJIFGcHXBS2yDePgRCKsmB81BpSC2Eb45Z+Dk7IcjUnTSL
 EqyEFs7lQArh+TMMEuxHfccp/L4um5hvC0WOY6nf5hOrV4H+wAbfpLU8mMtlUhr2
 yrxUFskzOCOjsxixwAtYX90wNhYRMUut0hJvW2ezD75JgFxlHJXUUtOjoyiO2weW
 jws5lXJHRiI77SHBoSLlr2j5W/K1rjvu1VTgis2Jv68ceTTU6pc=
 =+PBF
 -----END PGP SIGNATURE-----

Merge tag 'i2c-for-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c updates from Wolfram Sang:

 - general cleanups in bcm2835, designware, pcf8584, and stm32

 - amd-mp2: fix device refcount

 - designware: avoid interrupt storms caused by bad firmware

 - spacemit: fix device detection failures

 - new devices: Intel Diamond Rapids, Rockchip RK3506, Qualcomm
   Kaanapali and MSM8953

 - minor fixes to i801, core documentation, elektor Kconfig dependencies

 - at24 updates: add new compatible for Belling BL24S64

* tag 'i2c-for-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (21 commits)
  i2c: qcom-cci: Add msm8953 compatible
  i2c: spacemit: fix detect issue
  i2c: amd-mp2: fix reference leak in MP2 PCI device
  i2c: i2c.h: fix a bad kernel-doc line
  i2c: i2c-elektor: Allow building on SMP kernels
  dt-bindings: i2c: qcom-cci: Document Kaanapali compatible
  dt-bindings: i2c: qcom-cci: Document msm8953 compatible
  dt-bindings: eeprom: at24: Add compatible for Belling BL24S64
  i2c: i801: Fix the Intel Diamond Rapids features
  i2c: pcf8584: Change pcf_doAdress() to pcf_send_address()
  i2c: pcf8584: Make pcf_doAddress() function void
  i2c: pcf8584: Move 'ret' variable inside for loop, goto out if ret < 0.
  i2c: designware: Disable SMBus interrupts to prevent storms from mis-configured firmware
  dt-bindings: i2c: i2c-rk3x: Add compatible string for RK3506
  i2c: i801: Add support for Intel Diamond Rapids
  i2c: stm32: Omit two variable reassignments in stm32_i2c_dma_request()
  i2c: designware: Omit a variable reassignment in dw_i2c_plat_probe()
  i2c: pcf8584: Fix do not use assignment inside if conditional
  i2c: pcf8584: Remove debug macros from i2c-algo-pcf.c
  i2c: busses: bcm2835: convert from round_rate() to determine_rate()
  ...
master
Linus Torvalds 2025-12-10 07:48:05 +09:00
commit c9b47175e9
16 changed files with 120 additions and 111 deletions

View File

@ -131,6 +131,7 @@ properties:
- const: atmel,24c32
- items:
- enum:
- belling,bl24s64
- onnn,n24s64b
- puya,p24c64f
- const: atmel,24c64

View File

@ -37,6 +37,7 @@ properties:
- rockchip,px30-i2c
- rockchip,rk3308-i2c
- rockchip,rk3328-i2c
- rockchip,rk3506-i2c
- rockchip,rk3528-i2c
- rockchip,rk3562-i2c
- rockchip,rk3568-i2c

View File

@ -15,6 +15,7 @@ properties:
oneOf:
- enum:
- qcom,msm8226-cci
- qcom,msm8953-cci
- qcom,msm8974-cci
- qcom,msm8996-cci
@ -25,6 +26,7 @@ properties:
- items:
- enum:
- qcom,kaanapali-cci
- qcom,qcm2290-cci
- qcom,sa8775p-cci
- qcom,sc7280-cci
@ -128,6 +130,7 @@ allOf:
compatible:
contains:
enum:
- qcom,kaanapali-cci
- qcom,qcm2290-cci
then:
properties:
@ -146,6 +149,7 @@ allOf:
- contains:
enum:
- qcom,msm8916-cci
- qcom,msm8953-cci
- const: qcom,msm8996-cci
then:

View File

@ -51,6 +51,7 @@ Supported adapters:
* Intel Arrow Lake (SOC)
* Intel Panther Lake (SOC)
* Intel Wildcat Lake (SOC)
* Intel Diamond Rapids (SOC)
Datasheets: Publicly available at the Intel website

View File

@ -23,17 +23,8 @@
#include "i2c-algo-pcf.h"
#define DEB2(x) if (i2c_debug >= 2) x
#define DEB3(x) if (i2c_debug >= 3) x /* print several statistical values */
#define DEBPROTO(x) if (i2c_debug >= 9) x;
/* debug the protocol by showing transferred bits */
#define DEF_TIMEOUT 16
/*
* module parameters:
*/
static int i2c_debug;
/* setting states on the bus with the right timing: */
#define set_pcf(adap, ctl, val) adap->setpcf(adap->data, ctl, val)
@ -47,27 +38,21 @@ static int i2c_debug;
static void i2c_start(struct i2c_algo_pcf_data *adap)
{
DEBPROTO(printk(KERN_DEBUG "S "));
set_pcf(adap, 1, I2C_PCF_START);
}
static void i2c_repstart(struct i2c_algo_pcf_data *adap)
{
DEBPROTO(printk(" Sr "));
set_pcf(adap, 1, I2C_PCF_REPSTART);
}
static void i2c_stop(struct i2c_algo_pcf_data *adap)
{
DEBPROTO(printk("P\n"));
set_pcf(adap, 1, I2C_PCF_STOP);
}
static void handle_lab(struct i2c_algo_pcf_data *adap, const int *status)
{
DEB2(printk(KERN_INFO
"i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n",
*status));
/*
* Cleanup from LAB -- reset and enable ESO.
* This resets the PCF8584; since we've lost the bus, no
@ -88,9 +73,6 @@ static void handle_lab(struct i2c_algo_pcf_data *adap, const int *status)
if (adap->lab_mdelay)
mdelay(adap->lab_mdelay);
DEB2(printk(KERN_INFO
"i2c-algo-pcf.o: reset LAB condition (CSR 0x%02x)\n",
get_pcf(adap, 1)));
}
static int wait_for_bb(struct i2c_algo_pcf_data *adap)
@ -147,56 +129,48 @@ static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status)
*
* vdovikin: added detect code for PCF8584
*/
static int pcf_init_8584 (struct i2c_algo_pcf_data *adap)
static int pcf_init_8584(struct i2c_algo_pcf_data *adap)
{
unsigned char temp;
DEB3(printk(KERN_DEBUG "i2c-algo-pcf.o: PCF state 0x%02x\n",
get_pcf(adap, 1)));
/* S1=0x80: S0 selected, serial interface off */
set_pcf(adap, 1, I2C_PCF_PIN);
/*
* check to see S1 now used as R/W ctrl -
* PCF8584 does that when ESO is zero
*/
if (((temp = get_pcf(adap, 1)) & 0x7f) != (0)) {
DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S0 (0x%02x).\n", temp));
temp = get_pcf(adap, 1);
if ((temp & 0x7f) != 0)
return -ENXIO; /* definitely not PCF8584 */
}
/* load own address in S0, effective address is (own << 1) */
i2c_outb(adap, get_own(adap));
/* check it's really written */
if ((temp = i2c_inb(adap)) != get_own(adap)) {
DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't set S0 (0x%02x).\n", temp));
temp = i2c_inb(adap);
if (temp != get_own(adap))
return -ENXIO;
}
/* S1=0xA0, next byte in S2 */
set_pcf(adap, 1, I2C_PCF_PIN | I2C_PCF_ES1);
/* check to see S2 now selected */
if (((temp = get_pcf(adap, 1)) & 0x7f) != I2C_PCF_ES1) {
DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S2 (0x%02x).\n", temp));
temp = get_pcf(adap, 1);
if ((temp & 0x7f) != I2C_PCF_ES1)
return -ENXIO;
}
/* load clock register S2 */
i2c_outb(adap, get_clock(adap));
/* check it's really written, the only 5 lowest bits does matter */
if (((temp = i2c_inb(adap)) & 0x1f) != get_clock(adap)) {
DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't set S2 (0x%02x).\n", temp));
temp = i2c_inb(adap);
if ((temp & 0x1f) != get_clock(adap))
return -ENXIO;
}
/* Enable serial interface, idle, S0 selected */
set_pcf(adap, 1, I2C_PCF_IDLE);
/* check to see PCF is really idled and we can access status register */
if ((temp = get_pcf(adap, 1)) != (I2C_PCF_PIN | I2C_PCF_BB)) {
DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S1` (0x%02x).\n", temp));
temp = get_pcf(adap, 1);
if (temp != (I2C_PCF_PIN | I2C_PCF_BB))
return -ENXIO;
}
printk(KERN_DEBUG "i2c-algo-pcf.o: detected and initialized PCF8584.\n");
@ -209,9 +183,7 @@ static int pcf_sendbytes(struct i2c_adapter *i2c_adap, const char *buf,
struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
int wrcount, status, timeout;
for (wrcount=0; wrcount<count; ++wrcount) {
DEB2(dev_dbg(&i2c_adap->dev, "i2c_write: writing %2.2X\n",
buf[wrcount] & 0xff));
for (wrcount = 0; wrcount < count; ++wrcount) {
i2c_outb(adap, buf[wrcount]);
timeout = wait_for_pin(adap, &status);
if (timeout) {
@ -246,7 +218,8 @@ static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf,
/* increment number of bytes to read by one -- read dummy byte */
for (i = 0; i <= count; i++) {
if ((wfp = wait_for_pin(adap, &status))) {
wfp = wait_for_pin(adap, &status);
if (wfp) {
if (wfp == -EINTR)
return -EINTR; /* arbitration lost */
@ -280,7 +253,7 @@ static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf,
}
static int pcf_doAddress(struct i2c_algo_pcf_data *adap,
static void pcf_send_address(struct i2c_algo_pcf_data *adap,
struct i2c_msg *msg)
{
unsigned char addr = i2c_8bit_addr_from_msg(msg);
@ -288,8 +261,6 @@ static int pcf_doAddress(struct i2c_algo_pcf_data *adap,
if (msg->flags & I2C_M_REV_DIR_ADDR)
addr ^= 1;
i2c_outb(adap, addr);
return 0;
}
static int pcf_xfer(struct i2c_adapter *i2c_adap,
@ -299,7 +270,7 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
struct i2c_msg *pmsg;
int i;
int ret=0, timeout, status;
int timeout, status;
if (adap->xfer_begin)
adap->xfer_begin(adap->data);
@ -307,20 +278,15 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
/* Check for bus busy */
timeout = wait_for_bb(adap);
if (timeout) {
DEB2(printk(KERN_ERR "i2c-algo-pcf.o: "
"Timeout waiting for BB in pcf_xfer\n");)
i = -EIO;
goto out;
}
for (i = 0;ret >= 0 && i < num; i++) {
for (i = 0; i < num; i++) {
int ret;
pmsg = &msgs[i];
DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: Doing %s %d bytes to 0x%02x - %d of %d messages\n",
str_read_write(pmsg->flags & I2C_M_RD),
pmsg->len, pmsg->addr, i + 1, num);)
ret = pcf_doAddress(adap, pmsg);
pcf_send_address(adap, pmsg);
/* Send START */
if (i == 0)
@ -335,8 +301,6 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
goto out;
}
i2c_stop(adap);
DEB2(printk(KERN_ERR "i2c-algo-pcf.o: Timeout waiting "
"for PIN(1) in pcf_xfer\n");)
i = -EREMOTEIO;
goto out;
}
@ -344,35 +308,21 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
/* Check LRB (last rcvd bit - slave ack) */
if (status & I2C_PCF_LRB) {
i2c_stop(adap);
DEB2(printk(KERN_ERR "i2c-algo-pcf.o: No LRB(1) in pcf_xfer\n");)
i = -EREMOTEIO;
goto out;
}
DEB3(printk(KERN_DEBUG "i2c-algo-pcf.o: Msg %d, addr=0x%x, flags=0x%x, len=%d\n",
i, msgs[i].addr, msgs[i].flags, msgs[i].len);)
if (pmsg->flags & I2C_M_RD) {
ret = pcf_readbytes(i2c_adap, pmsg->buf, pmsg->len,
(i + 1 == num));
if (ret != pmsg->len) {
DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: fail: "
"only read %d bytes.\n",ret));
} else {
DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: read %d bytes.\n",ret));
}
} else {
ret = pcf_sendbytes(i2c_adap, pmsg->buf, pmsg->len,
(i + 1 == num));
if (ret != pmsg->len) {
DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: fail: "
"only wrote %d bytes.\n",ret));
} else {
DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: wrote %d bytes.\n",ret));
}
}
if (ret < 0)
goto out;
}
out:
@ -401,12 +351,11 @@ int i2c_pcf_add_bus(struct i2c_adapter *adap)
struct i2c_algo_pcf_data *pcf_adap = adap->algo_data;
int rval;
DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
/* register new adapter to i2c module... */
adap->algo = &pcf_algo;
if ((rval = pcf_init_8584(pcf_adap)))
rval = pcf_init_8584(pcf_adap);
if (rval)
return rval;
rval = i2c_add_adapter(adap);
@ -418,7 +367,3 @@ EXPORT_SYMBOL(i2c_pcf_add_bus);
MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm");
MODULE_LICENSE("GPL");
module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(i2c_debug,
"debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol");

View File

@ -166,6 +166,7 @@ config I2C_I801
Arrow Lake (SOC)
Panther Lake (SOC)
Wildcat Lake (SOC)
Diamond Rapids (SOC)
This driver can also be built as a module. If so, the module
will be called i2c-i801.
@ -1474,7 +1475,7 @@ config I2C_ACORN
config I2C_ELEKTOR
tristate "Elektor ISA card"
depends on ISA && HAS_IOPORT_MAP && BROKEN_ON_SMP
depends on ISA && HAS_IOPORT_MAP
select I2C_ALGOPCF
help
This supports the PCF8584 ISA bus I2C adapter. Say Y if you own

View File

@ -458,13 +458,16 @@ struct amd_mp2_dev *amd_mp2_find_device(void)
{
struct device *dev;
struct pci_dev *pci_dev;
struct amd_mp2_dev *mp2_dev;
dev = driver_find_next_device(&amd_mp2_pci_driver.driver, NULL);
if (!dev)
return NULL;
pci_dev = to_pci_dev(dev);
return (struct amd_mp2_dev *)pci_get_drvdata(pci_dev);
mp2_dev = (struct amd_mp2_dev *)pci_get_drvdata(pci_dev);
put_device(dev);
return mp2_dev;
}
EXPORT_SYMBOL_GPL(amd_mp2_find_device);

View File

@ -137,12 +137,14 @@ static int clk_bcm2835_i2c_set_rate(struct clk_hw *hw, unsigned long rate,
return 0;
}
static long clk_bcm2835_i2c_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int clk_bcm2835_i2c_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
u32 divider = clk_bcm2835_i2c_calc_divider(rate, *parent_rate);
u32 divider = clk_bcm2835_i2c_calc_divider(req->rate, req->best_parent_rate);
return DIV_ROUND_UP(*parent_rate, divider);
req->rate = DIV_ROUND_UP(req->best_parent_rate, divider);
return 0;
}
static unsigned long clk_bcm2835_i2c_recalc_rate(struct clk_hw *hw,
@ -156,7 +158,7 @@ static unsigned long clk_bcm2835_i2c_recalc_rate(struct clk_hw *hw,
static const struct clk_ops clk_bcm2835_i2c_ops = {
.set_rate = clk_bcm2835_i2c_set_rate,
.round_rate = clk_bcm2835_i2c_round_rate,
.determine_rate = clk_bcm2835_i2c_determine_rate,
.recalc_rate = clk_bcm2835_i2c_recalc_rate,
};

View File

@ -78,6 +78,7 @@
#define DW_IC_TX_ABRT_SOURCE 0x80
#define DW_IC_ENABLE_STATUS 0x9c
#define DW_IC_CLR_RESTART_DET 0xa8
#define DW_IC_SMBUS_INTR_MASK 0xcc
#define DW_IC_COMP_PARAM_1 0xf4
#define DW_IC_COMP_VERSION 0xf8
#define DW_IC_SDA_HOLD_MIN_VERS 0x3131312A /* "111*" == v1.11* */
@ -330,7 +331,6 @@ struct dw_i2c_dev {
struct i2c_dw_semaphore_callbacks {
int (*probe)(struct dw_i2c_dev *dev);
void (*remove)(struct dw_i2c_dev *dev);
};
int i2c_dw_init_regmap(struct dw_i2c_dev *dev);

View File

@ -220,6 +220,13 @@ static int i2c_dw_init_master(struct dw_i2c_dev *dev)
/* Disable the adapter */
__i2c_dw_disable(dev);
/*
* Mask SMBus interrupts to block storms from broken
* firmware that leaves IC_SMBUS=1; the handler never
* services them.
*/
regmap_write(dev->map, DW_IC_SMBUS_INTR_MASK, 0);
/* Write standard speed timing parameters */
regmap_write(dev->map, DW_IC_SS_SCL_HCNT, dev->ss_hcnt);
regmap_write(dev->map, DW_IC_SS_SCL_LCNT, dev->ss_lcnt);

View File

@ -197,15 +197,6 @@ static int i2c_dw_probe_lock_support(struct dw_i2c_dev *dev)
return 0;
}
static void i2c_dw_remove_lock_support(struct dw_i2c_dev *dev)
{
if (dev->semaphore_idx < 0)
return;
if (i2c_dw_semaphore_cb_table[dev->semaphore_idx].remove)
i2c_dw_semaphore_cb_table[dev->semaphore_idx].remove(dev);
}
static int dw_i2c_plat_probe(struct platform_device *pdev)
{
u32 flags = (uintptr_t)device_get_match_data(&pdev->dev);
@ -248,7 +239,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
ret = i2c_dw_probe_lock_support(dev);
if (ret) {
ret = dev_err_probe(device, ret, "failed to probe lock support\n");
dev_err_probe(device, ret, "failed to probe lock support\n");
goto exit_reset;
}
@ -339,8 +330,6 @@ static void dw_i2c_plat_remove(struct platform_device *pdev)
i2c_dw_prepare_clk(dev, false);
i2c_dw_remove_lock_support(dev);
reset_control_assert(dev->rst);
}

View File

@ -84,6 +84,7 @@
* Panther Lake-H (SOC) 0xe322 32 hard yes yes yes
* Panther Lake-P (SOC) 0xe422 32 hard yes yes yes
* Wildcat Lake-U (SOC) 0x4d22 32 hard yes yes yes
* Diamond Rapids (SOC) 0x5827 32 hard yes yes yes
*
* Features supported by this driver:
* Software PEC no
@ -242,6 +243,7 @@
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_P_SMBUS 0x51a3
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_M_SMBUS 0x54a3
#define PCI_DEVICE_ID_INTEL_BIRCH_STREAM_SMBUS 0x5796
#define PCI_DEVICE_ID_INTEL_DIAMOND_RAPIDS_SMBUS 0x5827
#define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4
#define PCI_DEVICE_ID_INTEL_ARROW_LAKE_H_SMBUS 0x7722
#define PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_S_SMBUS 0x7a23
@ -1054,6 +1056,7 @@ static const struct pci_device_id i801_ids[] = {
{ PCI_DEVICE_DATA(INTEL, METEOR_LAKE_SOC_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
{ PCI_DEVICE_DATA(INTEL, METEOR_LAKE_PCH_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
{ PCI_DEVICE_DATA(INTEL, BIRCH_STREAM_SMBUS, FEATURES_ICH5) },
{ PCI_DEVICE_DATA(INTEL, DIAMOND_RAPIDS_SMBUS, FEATURES_ICH5) },
{ PCI_DEVICE_DATA(INTEL, ARROW_LAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
{ PCI_DEVICE_DATA(INTEL, PANTHER_LAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
{ PCI_DEVICE_DATA(INTEL, PANTHER_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },

View File

@ -158,11 +158,16 @@ static int spacemit_i2c_handle_err(struct spacemit_i2c_dev *i2c)
{
dev_dbg(i2c->dev, "i2c error status: 0x%08x\n", i2c->status);
if (i2c->status & (SPACEMIT_SR_BED | SPACEMIT_SR_ALD)) {
/* Arbitration Loss Detected */
if (i2c->status & SPACEMIT_SR_ALD) {
spacemit_i2c_reset(i2c);
return -EAGAIN;
}
/* Bus Error No ACK/NAK */
if (i2c->status & SPACEMIT_SR_BED)
spacemit_i2c_reset(i2c);
return i2c->status & SPACEMIT_SR_ACKNAK ? -ENXIO : -EIO;
}
@ -224,6 +229,12 @@ static void spacemit_i2c_check_bus_release(struct spacemit_i2c_dev *i2c)
}
}
static inline void
spacemit_i2c_clear_int_status(struct spacemit_i2c_dev *i2c, u32 mask)
{
writel(mask & SPACEMIT_I2C_INT_STATUS_MASK, i2c->base + SPACEMIT_ISR);
}
static void spacemit_i2c_init(struct spacemit_i2c_dev *i2c)
{
u32 val;
@ -267,12 +278,8 @@ static void spacemit_i2c_init(struct spacemit_i2c_dev *i2c)
val = readl(i2c->base + SPACEMIT_IRCR);
val |= SPACEMIT_RCR_SDA_GLITCH_NOFIX;
writel(val, i2c->base + SPACEMIT_IRCR);
}
static inline void
spacemit_i2c_clear_int_status(struct spacemit_i2c_dev *i2c, u32 mask)
{
writel(mask & SPACEMIT_I2C_INT_STATUS_MASK, i2c->base + SPACEMIT_ISR);
spacemit_i2c_clear_int_status(i2c, SPACEMIT_I2C_INT_STATUS_MASK);
}
static void spacemit_i2c_start(struct spacemit_i2c_dev *i2c)

View File

@ -783,8 +783,54 @@ static const struct cci_data cci_v2_data = {
},
};
static const struct cci_data cci_msm8953_data = {
.num_masters = 2,
.queue_size = { 64, 16 },
.quirks = {
.max_write_len = 11,
.max_read_len = 12,
},
.params[I2C_MODE_STANDARD] = {
.thigh = 78,
.tlow = 114,
.tsu_sto = 28,
.tsu_sta = 28,
.thd_dat = 10,
.thd_sta = 77,
.tbuf = 118,
.scl_stretch_en = 0,
.trdhld = 6,
.tsp = 1
},
.params[I2C_MODE_FAST] = {
.thigh = 20,
.tlow = 28,
.tsu_sto = 21,
.tsu_sta = 21,
.thd_dat = 13,
.thd_sta = 18,
.tbuf = 32,
.scl_stretch_en = 0,
.trdhld = 6,
.tsp = 3
},
.params[I2C_MODE_FAST_PLUS] = {
.thigh = 16,
.tlow = 22,
.tsu_sto = 17,
.tsu_sta = 18,
.thd_dat = 16,
.thd_sta = 15,
.tbuf = 19,
.scl_stretch_en = 1,
.trdhld = 3,
.tsp = 3
},
};
static const struct of_device_id cci_dt_match[] = {
{ .compatible = "qcom,msm8226-cci", .data = &cci_v1_data},
{ .compatible = "qcom,msm8953-cci", .data = &cci_msm8953_data},
{ .compatible = "qcom,msm8974-cci", .data = &cci_v1_5_data},
{ .compatible = "qcom,msm8996-cci", .data = &cci_v2_data},

View File

@ -27,8 +27,8 @@ struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev,
if (IS_ERR(dma->chan_tx)) {
ret = PTR_ERR(dma->chan_tx);
if (ret != -ENODEV)
ret = dev_err_probe(dev, ret,
"can't request DMA tx channel\n");
dev_err_probe(dev, ret, "can't request DMA tx channel\n");
goto fail_al;
}
@ -48,8 +48,7 @@ struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev,
if (IS_ERR(dma->chan_rx)) {
ret = PTR_ERR(dma->chan_rx);
if (ret != -ENODEV)
ret = dev_err_probe(dev, ret,
"can't request DMA rx channel\n");
dev_err_probe(dev, ret, "can't request DMA rx channel\n");
goto fail_tx;
}

View File

@ -36,7 +36,7 @@
*
* Only if I2C_FUNC_NOSTART is set:
* %I2C_M_NOSTART: skip repeated start sequence
*
* Only if I2C_FUNC_PROTOCOL_MANGLING is set:
* %I2C_M_NO_RD_ACK: in a read message, master ACK/NACK bit is skipped
* %I2C_M_IGNORE_NAK: treat NACK from client as ACK