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

Pull i2c updates from Wolfram Sang:
 "The biggest news in this pull request is that it will start the last
  cycle of me handling the I2C subsystem. From 7.2. on, I will pass
  maintainership to Andi Shyti who has been maintaining the I2C drivers
  for a while now and who has done a great job in doing so.

  We will use this cycle for a hopefully smooth transition. Thanks must
  go to Andi for stepping up! I will still be around for guidance.

  Updates:
   - generic cleanups in npcm7xx, qcom-cci, xiic and designware DT
     bindings
   - atr: use kzalloc_flex for alias pool allocation
   - ixp4xx: convert bindings to DT schema
   - ocores: use read_poll_timeout_atomic() for polling waits
   - qcom-geni: skip extra TX DMA TRE for single read messages
   - s3c24xx: validate SMBus block length before using it
   - spacemit: refactor xfer path and add K1 PIO support
   - tegra: identify DVC and VI with SoC data variants
   - tegra: support SoC-specific register offsets
   - xiic: switch to devres and generic fw properties
   - xiic: skip input clock setup on non-OF systems
   - various minor improvements in other drivers

  rtl9300:
   - add per-SoC callbacks and clock support for RTL9607C
   - add support for new 50 kHz and 2.5 MHz bus speeds
   - general refactoring in preparation for RTL9607C support

  New support:
   - DesignWare GOOG5000 (ACPI HID)
   - Intel Nova Lake (ACPI ID)
   - Realtek RTL9607C
   - SpacemiT K3 binding
   - Tegra410 register layout support"

* tag 'i2c-for-7.1-rc1-part1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (40 commits)
  i2c: usbio: Add ACPI device-id for NVL platforms
  i2c: qcom-geni: Avoid extra TX DMA TRE for single read message in GPI mode
  i2c: atr: use kzalloc_flex
  i2c: spacemit: introduce pio for k1
  i2c: spacemit: move i2c_xfer_msg()
  i2c: xiic: skip input clock setup on non-OF systems
  i2c: xiic: use numbered adapter registration
  i2c: xiic: cosmetic: use resource format specifier in debug log
  i2c: xiic: cosmetic cleanup
  i2c: xiic: switch to generic device property accessors
  i2c: xiic: remove duplicate error message
  i2c: xiic: switch to devres managed APIs
  i2c: rtl9300: add RTL9607C i2c controller support
  i2c: rtl9300: introduce new function properties to driver data
  i2c: rtl9300: introduce clk struct for upcoming rtl9607 support
  dt-bindings: i2c: realtek,rtl9301-i2c: extend for clocks and RTL9607C support
  i2c: rtl9300: introduce a property for 8 bit width reg address
  i2c: rtl9300: introduce F_BUSY to the reg_fields struct
  i2c: rtl9300: introduce max length property to driver data
  i2c: rtl9300: split data_reg into read and write reg
  ...
This commit is contained in:
Linus Torvalds
2026-04-18 09:44:22 -07:00
24 changed files with 967 additions and 390 deletions
@@ -1,20 +0,0 @@
i2c Controller on XScale platforms such as IOP3xx and IXP4xx
Required properties:
- compatible : Must be one of
"intel,iop3xx-i2c"
"intel,ixp4xx-i2c";
- reg
- #address-cells = <1>;
- #size-cells = <0>;
Optional properties:
- Child nodes conforming to i2c bus binding
Example:
i2c@c8011000 {
compatible = "intel,ixp4xx-i2c";
reg = <0xc8011000 0x18>;
interrupts = <33 IRQ_TYPE_LEVEL_LOW>;
};
@@ -0,0 +1,41 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/i2c/intel,ixp4xx-i2c.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: I2c Controller on XScale platforms such as IOP3xx and IXP4xx
maintainers:
- Andi Shyti <andi.shyti@kernel.org>
allOf:
- $ref: /schemas/i2c/i2c-controller.yaml#
properties:
compatible:
enum:
- intel,iop3xx-i2c
- intel,ixp4xx-i2c
reg:
maxItems: 1
interrupts:
maxItems: 1
required:
- compatible
- reg
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c@c8011000 {
compatible = "intel,ixp4xx-i2c";
reg = <0xc8011000 0x18>;
interrupts = <33 IRQ_TYPE_LEVEL_LOW>;
};
@@ -27,6 +27,7 @@ properties:
- items:
- enum:
- qcom,kaanapali-cci
- qcom,milos-cci
- qcom,qcm2290-cci
- qcom,qcs8300-cci
- qcom,sa8775p-cci
@@ -34,6 +35,7 @@ properties:
- qcom,sc8280xp-cci
- qcom,sdm670-cci
- qcom,sdm845-cci
- qcom,sm6150-cci
- qcom,sm6350-cci
- qcom,sm8250-cci
- qcom,sm8450-cci
@@ -251,6 +253,7 @@ allOf:
contains:
enum:
- qcom,sa8775p-cci
- qcom,sm6150-cci
- qcom,sm8550-cci
- qcom,sm8650-cci
- qcom,x1e80100-cci
@@ -265,6 +268,23 @@ allOf:
- const: cpas_ahb
- const: cci
- if:
properties:
compatible:
contains:
enum:
- qcom,milos-cci
then:
properties:
clocks:
minItems: 3
maxItems: 3
clock-names:
items:
- const: soc_ahb
- const: cpas_ahb
- const: cci
additionalProperties: false
examples:
@@ -15,6 +15,8 @@ description:
assigned to either I2C controller.
RTL9310 SoCs have equal capabilities but support 12 common SDA lines which
can be assigned to either I2C controller.
RTL9607C SoCs have equal capabilities but each controller only supports 1
SCL/SDA line.
properties:
compatible:
@@ -34,6 +36,7 @@ properties:
- enum:
- realtek,rtl9301-i2c
- realtek,rtl9310-i2c
- realtek,rtl9607-i2c
reg:
items:
@@ -51,6 +54,9 @@ properties:
The SCL line number of this I2C controller.
enum: [ 0, 1 ]
clocks:
maxItems: 1
patternProperties:
'^i2c@[0-9ab]$':
$ref: /schemas/i2c/i2c-controller.yaml
@@ -81,6 +87,15 @@ allOf:
then:
patternProperties:
'^i2c@[89ab]$': false
- if:
properties:
compatible:
contains:
const: realtek,rtl9607-i2c
then:
required:
- realtek,scl
- clocks
required:
- compatible
@@ -25,6 +25,7 @@ properties:
- items:
- enum:
- renesas,riic-r9a08g045 # RZ/G3S
- renesas,riic-r9a08g046 # RZ/G3L
- renesas,riic-r9a09g047 # RZ/G3E
- renesas,riic-r9a09g056 # RZ/V2N
- const: renesas,riic-r9a09g057 # RZ/V2H(P)
@@ -32,8 +32,6 @@ properties:
- const: renesas,r9a06g032-i2c # RZ/N1D
- const: renesas,rzn1-i2c # RZ/N1
- const: snps,designware-i2c
- description: Baikal-T1 SoC System I2C controller
const: baikal,bt1-sys-i2c
- description: Mobileye EyeQ DesignWare I2C controller
items:
- enum:
@@ -14,7 +14,11 @@ allOf:
properties:
compatible:
const: spacemit,k1-i2c
oneOf:
- items:
- const: spacemit,k3-i2c
- const: spacemit,k1-i2c
- const: spacemit,k1-i2c
reg:
maxItems: 1
+1 -2
View File
@@ -1211,8 +1211,7 @@ config I2C_SYNQUACER
config I2C_TEGRA
tristate "NVIDIA Tegra internal I2C controller"
depends on ARCH_TEGRA || (COMPILE_TEST && (ARC || ARM || ARM64 || M68K || RISCV || SUPERH || SPARC))
# COMPILE_TEST needs architectures with readsX()/writesX() primitives
depends on ARCH_TEGRA || COMPILE_TEST
depends on PINCTRL
# ARCH_TEGRA implies PINCTRL, but the COMPILE_TEST side doesn't.
help
+2 -3
View File
@@ -270,8 +270,7 @@ static struct i2c_adapter_quirks cp2615_i2c_quirks = {
.max_comb_2nd_msg_len = MAX_I2C_SIZE
};
static void
cp2615_i2c_remove(struct usb_interface *usbif)
static void cp2615_i2c_disconnect(struct usb_interface *usbif)
{
struct i2c_adapter *adap = usb_get_intfdata(usbif);
@@ -328,7 +327,7 @@ MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver cp2615_i2c_driver = {
.name = "i2c-cp2615",
.probe = cp2615_i2c_probe,
.disconnect = cp2615_i2c_remove,
.disconnect = cp2615_i2c_disconnect,
.id_table = id_table,
};
@@ -268,6 +268,7 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = {
{ "AMDI0510", 0 },
{ "APMC0D0F", 0 },
{ "FUJI200B", 0 },
{ "GOOG5000", 0 },
{ "HISI02A1", 0 },
{ "HISI02A2", 0 },
{ "HISI02A3", 0 },
+3 -9
View File
@@ -427,12 +427,6 @@ static const struct usb_device_id diolan_u2c_table[] = {
MODULE_DEVICE_TABLE(usb, diolan_u2c_table);
static void diolan_u2c_free(struct i2c_diolan_u2c *dev)
{
usb_put_dev(dev->usb_dev);
kfree(dev);
}
static int diolan_u2c_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
@@ -453,7 +447,7 @@ static int diolan_u2c_probe(struct usb_interface *interface,
dev->ep_out = hostif->endpoint[0].desc.bEndpointAddress;
dev->ep_in = hostif->endpoint[1].desc.bEndpointAddress;
dev->usb_dev = usb_get_dev(interface_to_usbdev(interface));
dev->usb_dev = interface_to_usbdev(interface);
dev->interface = interface;
/* save our data pointer in this interface device */
@@ -488,7 +482,7 @@ static int diolan_u2c_probe(struct usb_interface *interface,
error_free:
usb_set_intfdata(interface, NULL);
diolan_u2c_free(dev);
kfree(dev);
error:
return ret;
}
@@ -499,7 +493,7 @@ static void diolan_u2c_disconnect(struct usb_interface *interface)
i2c_del_adapter(&dev->adapter);
usb_set_intfdata(interface, NULL);
diolan_u2c_free(dev);
kfree(dev);
dev_dbg(&interface->dev, "disconnected\n");
}
+235 -79
View File
@@ -98,6 +98,10 @@
#define SPACEMIT_BUS_RESET_CLK_CNT_MAX 9
#define SPACEMIT_WAIT_TIMEOUT 1000 /* ms */
#define SPACEMIT_POLL_TIMEOUT 1000 /* us */
#define SPACEMIT_POLL_INTERVAL 30 /* us */
enum spacemit_i2c_state {
SPACEMIT_STATE_IDLE,
SPACEMIT_STATE_START,
@@ -126,6 +130,7 @@ struct spacemit_i2c_dev {
enum spacemit_i2c_state state;
bool read;
bool use_pio;
struct completion complete;
u32 status;
};
@@ -172,6 +177,14 @@ static int spacemit_i2c_handle_err(struct spacemit_i2c_dev *i2c)
return i2c->status & SPACEMIT_SR_ACKNAK ? -ENXIO : -EIO;
}
static inline void spacemit_i2c_delay(struct spacemit_i2c_dev *i2c, unsigned int us)
{
if (i2c->use_pio)
udelay(us);
else
fsleep(us);
}
static void spacemit_i2c_conditionally_reset_bus(struct spacemit_i2c_dev *i2c)
{
u32 status;
@@ -183,7 +196,8 @@ static void spacemit_i2c_conditionally_reset_bus(struct spacemit_i2c_dev *i2c)
return;
spacemit_i2c_reset(i2c);
usleep_range(10, 20);
spacemit_i2c_delay(i2c, 10);
for (clk_cnt = 0; clk_cnt < SPACEMIT_BUS_RESET_CLK_CNT_MAX; clk_cnt++) {
status = readl(i2c->base + SPACEMIT_IBMR);
@@ -212,9 +226,15 @@ static int spacemit_i2c_wait_bus_idle(struct spacemit_i2c_dev *i2c)
if (!(val & (SPACEMIT_SR_UB | SPACEMIT_SR_IBB)))
return 0;
ret = readl_poll_timeout(i2c->base + SPACEMIT_ISR,
val, !(val & (SPACEMIT_SR_UB | SPACEMIT_SR_IBB)),
1500, SPACEMIT_I2C_BUS_BUSY_TIMEOUT);
if (i2c->use_pio)
ret = readl_poll_timeout_atomic(i2c->base + SPACEMIT_ISR,
val, !(val & (SPACEMIT_SR_UB | SPACEMIT_SR_IBB)),
1500, SPACEMIT_I2C_BUS_BUSY_TIMEOUT);
else
ret = readl_poll_timeout(i2c->base + SPACEMIT_ISR,
val, !(val & (SPACEMIT_SR_UB | SPACEMIT_SR_IBB)),
1500, SPACEMIT_I2C_BUS_BUSY_TIMEOUT);
if (ret)
spacemit_i2c_reset(i2c);
@@ -226,7 +246,7 @@ static void spacemit_i2c_check_bus_release(struct spacemit_i2c_dev *i2c)
/* in case bus is not released after transfer completes */
if (readl(i2c->base + SPACEMIT_ISR) & SPACEMIT_SR_EBB) {
spacemit_i2c_conditionally_reset_bus(i2c);
usleep_range(90, 150);
spacemit_i2c_delay(i2c, 90);
}
}
@@ -238,25 +258,33 @@ spacemit_i2c_clear_int_status(struct spacemit_i2c_dev *i2c, u32 mask)
static void spacemit_i2c_init(struct spacemit_i2c_dev *i2c)
{
u32 val;
u32 val = 0;
/*
* Unmask interrupt bits for all xfer mode:
* bus error, arbitration loss detected.
* For transaction complete signal, we use master stop
* interrupt, so we don't need to unmask SPACEMIT_CR_TXDONEIE.
*/
val = SPACEMIT_CR_BEIE | SPACEMIT_CR_ALDIE;
if (!i2c->use_pio) {
/*
* Enable interrupt bits for all xfer mode:
* bus error, arbitration loss detected.
*/
val |= SPACEMIT_CR_BEIE | SPACEMIT_CR_ALDIE;
/*
* Unmask interrupt bits for interrupt xfer mode:
* When IDBR receives a byte, an interrupt is triggered.
*
* For the tx empty interrupt, it will be enabled in the
* i2c_start function.
* Otherwise, it will cause an erroneous empty interrupt before i2c_start.
*/
val |= SPACEMIT_CR_DRFIE;
/*
* Unmask interrupt bits for interrupt xfer mode:
* When IDBR receives a byte, an interrupt is triggered.
*
* For the tx empty interrupt, it will be enabled in the
* i2c_start().
* We don't want a TX empty interrupt until we start
* a transfer in i2c_start().
*/
val |= SPACEMIT_CR_DRFIE;
/*
* Enable master stop interrupt bit.
* For transaction complete signal, we use master stop
* interrupt, so we don't need to unmask SPACEMIT_CR_TXDONEIE.
*/
val |= SPACEMIT_CR_MSDIE;
}
if (i2c->clock_freq == SPACEMIT_I2C_MAX_FAST_MODE_FREQ)
val |= SPACEMIT_CR_MODE_FAST;
@@ -268,7 +296,7 @@ static void spacemit_i2c_init(struct spacemit_i2c_dev *i2c)
val |= SPACEMIT_CR_SCLE;
/* enable master stop detected */
val |= SPACEMIT_CR_MSDE | SPACEMIT_CR_MSDIE;
val |= SPACEMIT_CR_MSDE;
writel(val, i2c->base + SPACEMIT_ICR);
@@ -301,41 +329,15 @@ static void spacemit_i2c_start(struct spacemit_i2c_dev *i2c)
/* send start pulse */
val = readl(i2c->base + SPACEMIT_ICR);
val &= ~SPACEMIT_CR_STOP;
val |= SPACEMIT_CR_START | SPACEMIT_CR_TB | SPACEMIT_CR_DTEIE;
val |= SPACEMIT_CR_START | SPACEMIT_CR_TB;
/* Enable the TX empty interrupt */
if (!i2c->use_pio)
val |= SPACEMIT_CR_DTEIE;
writel(val, i2c->base + SPACEMIT_ICR);
}
static int spacemit_i2c_xfer_msg(struct spacemit_i2c_dev *i2c)
{
unsigned long time_left;
struct i2c_msg *msg;
for (i2c->msg_idx = 0; i2c->msg_idx < i2c->msg_num; i2c->msg_idx++) {
msg = &i2c->msgs[i2c->msg_idx];
i2c->msg_buf = msg->buf;
i2c->unprocessed = msg->len;
i2c->status = 0;
reinit_completion(&i2c->complete);
spacemit_i2c_start(i2c);
time_left = wait_for_completion_timeout(&i2c->complete,
i2c->adapt.timeout);
if (!time_left) {
dev_err(i2c->dev, "msg completion timeout\n");
spacemit_i2c_conditionally_reset_bus(i2c);
spacemit_i2c_reset(i2c);
return -ETIMEDOUT;
}
if (i2c->status & SPACEMIT_SR_ERR)
return spacemit_i2c_handle_err(i2c);
}
return 0;
}
static bool spacemit_i2c_is_last_msg(struct spacemit_i2c_dev *i2c)
{
if (i2c->msg_idx != i2c->msg_num - 1)
@@ -347,8 +349,23 @@ static bool spacemit_i2c_is_last_msg(struct spacemit_i2c_dev *i2c)
return !i2c->unprocessed;
}
static inline void spacemit_i2c_complete(struct spacemit_i2c_dev *i2c)
{
/* SPACEMIT_STATE_IDLE avoids triggering the next byte */
i2c->state = SPACEMIT_STATE_IDLE;
if (i2c->use_pio)
return;
complete(&i2c->complete);
}
static void spacemit_i2c_handle_write(struct spacemit_i2c_dev *i2c)
{
/* If there's no space in the IDBR, we're done */
if (!(i2c->status & SPACEMIT_SR_ITE))
return;
/* if transfer completes, SPACEMIT_ISR will handle it */
if (i2c->status & SPACEMIT_SR_MSD)
return;
@@ -359,16 +376,19 @@ static void spacemit_i2c_handle_write(struct spacemit_i2c_dev *i2c)
return;
}
/* SPACEMIT_STATE_IDLE avoids trigger next byte */
i2c->state = SPACEMIT_STATE_IDLE;
complete(&i2c->complete);
spacemit_i2c_complete(i2c);
}
static void spacemit_i2c_handle_read(struct spacemit_i2c_dev *i2c)
{
/* If there's nothing in the IDBR, we're done */
if (!(i2c->status & SPACEMIT_SR_IRF))
return;
if (i2c->unprocessed) {
*i2c->msg_buf++ = readl(i2c->base + SPACEMIT_IDBR);
i2c->unprocessed--;
return;
}
/* if transfer completes, SPACEMIT_ISR will handle it */
@@ -379,9 +399,7 @@ static void spacemit_i2c_handle_read(struct spacemit_i2c_dev *i2c)
if (i2c->unprocessed)
return;
/* SPACEMIT_STATE_IDLE avoids trigger next byte */
i2c->state = SPACEMIT_STATE_IDLE;
complete(&i2c->complete);
spacemit_i2c_complete(i2c);
}
static void spacemit_i2c_handle_start(struct spacemit_i2c_dev *i2c)
@@ -415,29 +433,16 @@ static void spacemit_i2c_err_check(struct spacemit_i2c_dev *i2c)
spacemit_i2c_clear_int_status(i2c, SPACEMIT_I2C_INT_STATUS_MASK);
i2c->state = SPACEMIT_STATE_IDLE;
complete(&i2c->complete);
spacemit_i2c_complete(i2c);
}
static irqreturn_t spacemit_i2c_irq_handler(int irq, void *devid)
static void spacemit_i2c_handle_state(struct spacemit_i2c_dev *i2c)
{
struct spacemit_i2c_dev *i2c = devid;
u32 status, val;
status = readl(i2c->base + SPACEMIT_ISR);
if (!status)
return IRQ_HANDLED;
i2c->status = status;
spacemit_i2c_clear_int_status(i2c, status);
u32 val;
if (i2c->status & SPACEMIT_SR_ERR)
goto err_out;
val = readl(i2c->base + SPACEMIT_ICR);
val &= ~(SPACEMIT_CR_TB | SPACEMIT_CR_ACKNAK | SPACEMIT_CR_STOP | SPACEMIT_CR_START);
switch (i2c->state) {
case SPACEMIT_STATE_START:
spacemit_i2c_handle_start(i2c);
@@ -453,7 +458,12 @@ static irqreturn_t spacemit_i2c_irq_handler(int irq, void *devid)
}
if (i2c->state != SPACEMIT_STATE_IDLE) {
val |= SPACEMIT_CR_TB | SPACEMIT_CR_ALDIE;
val = readl(i2c->base + SPACEMIT_ICR);
val &= ~(SPACEMIT_CR_TB | SPACEMIT_CR_ACKNAK |
SPACEMIT_CR_STOP | SPACEMIT_CR_START);
val |= SPACEMIT_CR_TB;
if (!i2c->use_pio)
val |= SPACEMIT_CR_ALDIE;
if (spacemit_i2c_is_last_msg(i2c)) {
/* trigger next byte with stop */
@@ -467,6 +477,133 @@ static irqreturn_t spacemit_i2c_irq_handler(int irq, void *devid)
err_out:
spacemit_i2c_err_check(i2c);
}
/*
* In PIO mode, this function is used as a replacement for
* wait_for_completion_timeout(), whose return value indicates
* the remaining time.
*
* We do not have a meaningful remaining-time value here, so
* return a non-zero value on success to indicate "not timed out".
* Returning 1 ensures callers treating the return value as
* time_left will not incorrectly report a timeout.
*/
static int spacemit_i2c_wait_pio_xfer(struct spacemit_i2c_dev *i2c)
{
u32 mask, msec = jiffies_to_msecs(i2c->adapt.timeout);
ktime_t timeout = ktime_add_ms(ktime_get(), msec);
int ret;
mask = SPACEMIT_SR_IRF | SPACEMIT_SR_ITE;
do {
i2c->status = readl(i2c->base + SPACEMIT_ISR);
spacemit_i2c_clear_int_status(i2c, i2c->status);
if (i2c->status & mask)
spacemit_i2c_handle_state(i2c);
else
udelay(SPACEMIT_POLL_INTERVAL);
} while (i2c->unprocessed && ktime_compare(ktime_get(), timeout) < 0);
if (i2c->unprocessed)
return 0;
if (i2c->read)
return 1;
/*
* If this is the last byte to write of the current message,
* we have to wait here. Otherwise, control will proceed directly
* to start(), which would overwrite the current data.
*/
ret = readl_poll_timeout_atomic(i2c->base + SPACEMIT_ISR,
i2c->status, i2c->status & SPACEMIT_SR_ITE,
SPACEMIT_POLL_INTERVAL, SPACEMIT_POLL_TIMEOUT);
if (ret)
return 0;
/*
* For writes: in interrupt mode, an ITE (write-empty) interrupt is triggered
* after the last byte, and the MSD-related handling takes place there.
* In PIO mode, however, we need to explicitly call err_check() to emulate this
* step, otherwise the next transfer will fail.
*/
if (i2c->msg_idx == i2c->msg_num - 1) {
mask = SPACEMIT_SR_MSD | SPACEMIT_SR_ERR;
/*
* In some cases, MSD may not arrive immediately;
* wait here to handle that.
*/
ret = readl_poll_timeout_atomic(i2c->base + SPACEMIT_ISR,
i2c->status, i2c->status & mask,
SPACEMIT_POLL_INTERVAL, SPACEMIT_POLL_TIMEOUT);
if (ret)
return 0;
spacemit_i2c_err_check(i2c);
}
return 1;
}
static int spacemit_i2c_wait_xfer_complete(struct spacemit_i2c_dev *i2c)
{
if (i2c->use_pio)
return spacemit_i2c_wait_pio_xfer(i2c);
return wait_for_completion_timeout(&i2c->complete,
i2c->adapt.timeout);
}
static int spacemit_i2c_xfer_msg(struct spacemit_i2c_dev *i2c)
{
unsigned long time_left;
struct i2c_msg *msg;
for (i2c->msg_idx = 0; i2c->msg_idx < i2c->msg_num; i2c->msg_idx++) {
msg = &i2c->msgs[i2c->msg_idx];
i2c->msg_buf = msg->buf;
i2c->unprocessed = msg->len;
i2c->status = 0;
reinit_completion(&i2c->complete);
spacemit_i2c_start(i2c);
time_left = spacemit_i2c_wait_xfer_complete(i2c);
if (!time_left) {
dev_err(i2c->dev, "msg completion timeout\n");
spacemit_i2c_conditionally_reset_bus(i2c);
spacemit_i2c_reset(i2c);
return -ETIMEDOUT;
}
if (i2c->status & SPACEMIT_SR_ERR)
return spacemit_i2c_handle_err(i2c);
}
return 0;
}
static irqreturn_t spacemit_i2c_irq_handler(int irq, void *devid)
{
struct spacemit_i2c_dev *i2c = devid;
u32 status;
status = readl(i2c->base + SPACEMIT_ISR);
if (!status)
return IRQ_HANDLED;
i2c->status = status;
spacemit_i2c_clear_int_status(i2c, status);
spacemit_i2c_handle_state(i2c);
return IRQ_HANDLED;
}
@@ -475,6 +612,11 @@ static void spacemit_i2c_calc_timeout(struct spacemit_i2c_dev *i2c)
unsigned long timeout;
int idx = 0, cnt = 0;
if (i2c->use_pio) {
i2c->adapt.timeout = msecs_to_jiffies(SPACEMIT_WAIT_TIMEOUT);
return;
}
for (; idx < i2c->msg_num; idx++)
cnt += (i2c->msgs + idx)->len + 1;
@@ -487,11 +629,14 @@ static void spacemit_i2c_calc_timeout(struct spacemit_i2c_dev *i2c)
i2c->adapt.timeout = usecs_to_jiffies(timeout + USEC_PER_SEC / 10) / i2c->msg_num;
}
static int spacemit_i2c_xfer(struct i2c_adapter *adapt, struct i2c_msg *msgs, int num)
static inline int
spacemit_i2c_xfer_common(struct i2c_adapter *adapt, struct i2c_msg *msgs, int num, bool use_pio)
{
struct spacemit_i2c_dev *i2c = i2c_get_adapdata(adapt);
int ret;
i2c->use_pio = use_pio;
i2c->msgs = msgs;
i2c->msg_num = num;
@@ -519,6 +664,16 @@ static int spacemit_i2c_xfer(struct i2c_adapter *adapt, struct i2c_msg *msgs, in
return ret < 0 ? ret : num;
}
static int spacemit_i2c_xfer(struct i2c_adapter *adapt, struct i2c_msg *msgs, int num)
{
return spacemit_i2c_xfer_common(adapt, msgs, num, false);
}
static int spacemit_i2c_pio_xfer_atomic(struct i2c_adapter *adapt, struct i2c_msg *msgs, int num)
{
return spacemit_i2c_xfer_common(adapt, msgs, num, true);
}
static u32 spacemit_i2c_func(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
@@ -526,6 +681,7 @@ static u32 spacemit_i2c_func(struct i2c_adapter *adap)
static const struct i2c_algorithm spacemit_i2c_algo = {
.xfer = spacemit_i2c_xfer,
.xfer_atomic = spacemit_i2c_pio_xfer_atomic,
.functionality = spacemit_i2c_func,
};
+1 -1
View File
@@ -1384,7 +1384,7 @@ static irqreturn_t npcm_i2c_int_slave_handler(struct npcm_i2c *bus)
*/
bus->operation = I2C_NO_OPER;
bus->own_slave_addr = 0xFF;
i2c_slave_event(bus->slave, I2C_SLAVE_STOP, 0);
i2c_slave_event(bus->slave, I2C_SLAVE_STOP, NULL);
iowrite8(NPCM_I2CST_SLVSTP, bus->reg + NPCM_I2CST);
if (bus->fifo_use) {
npcm_i2c_clear_fifo_int(bus);
+9 -15
View File
@@ -24,6 +24,7 @@
#include <linux/io.h>
#include <linux/log2.h>
#include <linux/spinlock.h>
#include <linux/iopoll.h>
#include <linux/jiffies.h>
/*
@@ -258,7 +259,7 @@ static void ocores_process_timeout(struct ocores_i2c *i2c)
* @reg: register to query
* @mask: bitmask to apply on register value
* @val: expected result
* @timeout: timeout in jiffies
* @timeout_us: timeout in microseconds
*
* Timeout is necessary to avoid to stay here forever when the chip
* does not answer correctly.
@@ -267,21 +268,14 @@ static void ocores_process_timeout(struct ocores_i2c *i2c)
*/
static int ocores_wait(struct ocores_i2c *i2c,
int reg, u8 mask, u8 val,
const unsigned long timeout)
unsigned long timeout_us)
{
unsigned long j;
u8 status;
j = jiffies + timeout;
while (1) {
u8 status = oc_getreg(i2c, reg);
if ((status & mask) == val)
break;
if (time_after(jiffies, j))
return -ETIMEDOUT;
}
return 0;
return read_poll_timeout_atomic(oc_getreg, status,
(status & mask) == val,
0, timeout_us, false,
i2c, reg);
}
/**
@@ -314,7 +308,7 @@ static int ocores_poll_wait(struct ocores_i2c *i2c)
* once we are here we expect to get the expected result immediately
* so if after 1ms we timeout then something is broken.
*/
err = ocores_wait(i2c, OCI2C_STATUS, mask, 0, msecs_to_jiffies(1));
err = ocores_wait(i2c, OCI2C_STATUS, mask, 0, 1000);
if (err)
dev_warn(i2c->adap.dev.parent,
"%s: STATUS timeout, bit 0x%x did not clear in 1ms\n",
-3
View File
@@ -71,9 +71,6 @@
#define NUM_MASTERS 2
#define NUM_QUEUES 2
/* Max number of resources + 1 for a NULL terminator */
#define CCI_RES_MAX 6
#define CCI_I2C_SET_PARAM 1
#define CCI_I2C_REPORT 8
#define CCI_I2C_WRITE 9
+19 -5
View File
@@ -625,8 +625,8 @@ static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[],
{
struct gpi_i2c_config *peripheral;
unsigned int flags;
void *dma_buf;
dma_addr_t addr;
void *dma_buf = NULL;
dma_addr_t addr = 0;
enum dma_data_direction map_dirn;
enum dma_transfer_direction dma_dirn;
struct dma_async_tx_descriptor *desc;
@@ -639,6 +639,16 @@ static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[],
gi2c_gpi_xfer = &gi2c->i2c_multi_desc_config;
msg_idx = gi2c_gpi_xfer->msg_idx_cnt;
/*
* Skip TX DMA mapping for a read message (I2C_M_RD) to avoid
* programming an extra TX DMA TRE that would cause an unintended
* write cycle on the I2C bus before the actual read operation.
*/
if (op == I2C_WRITE && msgs[msg_idx].flags & I2C_M_RD) {
peripheral->multi_msg = true;
goto skip_tx_dma_map;
}
dma_buf = i2c_get_dma_safe_msg_buf(&msgs[msg_idx], 1);
if (!dma_buf) {
ret = -ENOMEM;
@@ -658,6 +668,7 @@ static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[],
goto out;
}
skip_tx_dma_map:
if (gi2c->is_tx_multi_desc_xfer) {
flags = DMA_CTRL_ACK;
@@ -740,9 +751,12 @@ static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[],
return 0;
err_config:
dma_unmap_single(gi2c->se.dev->parent, addr,
msgs[msg_idx].len, map_dirn);
i2c_put_dma_safe_msg_buf(dma_buf, &msgs[msg_idx], false);
/* Avoid DMA unmap as the write operation skipped DMA mapping */
if (dma_buf) {
dma_unmap_single(gi2c->se.dev->parent, addr,
msgs[msg_idx].len, map_dirn);
i2c_put_dma_safe_msg_buf(dma_buf, &msgs[msg_idx], false);
}
out:
gi2c->err = ret;
+1 -3
View File
@@ -141,7 +141,7 @@ static int osif_probe(struct usb_interface *interface,
if (!priv)
return -ENOMEM;
priv->usb_dev = usb_get_dev(interface_to_usbdev(interface));
priv->usb_dev = interface_to_usbdev(interface);
priv->interface = interface;
usb_set_intfdata(interface, priv);
@@ -163,7 +163,6 @@ static int osif_probe(struct usb_interface *interface,
NULL, 0);
if (ret) {
dev_err(&interface->dev, "failure sending bit rate");
usb_put_dev(priv->usb_dev);
return ret;
}
@@ -184,7 +183,6 @@ static void osif_disconnect(struct usb_interface *interface)
i2c_del_adapter(&(priv->adapter));
usb_set_intfdata(interface, NULL);
usb_put_dev(priv->usb_dev);
}
static struct usb_driver osif_driver = {
+164 -31
View File
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/i2c.h>
#include <linux/i2c-mux.h>
#include <linux/mod_devicetable.h>
@@ -11,10 +12,16 @@
#include <linux/unaligned.h>
enum rtl9300_bus_freq {
RTL9300_I2C_STD_FREQ,
RTL9300_I2C_FAST_FREQ,
RTL9300_I2C_STD_FREQ, // 100kHz
RTL9300_I2C_FAST_FREQ, // 400kHz
RTL9300_I2C_SUPER_FAST_FREQ, // 2.5MHz
RTL9300_I2C_SLOW_FREQ, // 50kHz
};
#define RTL9300_I2C_MAX_SUPER_FAST_FREQ 2500000
#define RTL9300_I2C_MAX_SLOW_FREQ 50000
struct rtl9300_i2c;
struct rtl9300_i2c_chan {
@@ -22,6 +29,7 @@ struct rtl9300_i2c_chan {
struct rtl9300_i2c *i2c;
enum rtl9300_bus_freq bus_freq;
u8 sda_num;
u32 clk_div;
};
enum rtl9300_i2c_reg_scope {
@@ -47,6 +55,9 @@ enum rtl9300_i2c_reg_fields {
F_SCL_SEL,
F_SDA_OUT_SEL,
F_SDA_SEL,
F_BUSY,
F_CLK_DIV,
F_EXT_SCK_5MS,
/* keep last */
F_NUM_FIELDS
@@ -55,12 +66,22 @@ enum rtl9300_i2c_reg_fields {
struct rtl9300_i2c_drv_data {
struct rtl9300_i2c_reg_field field_desc[F_NUM_FIELDS];
int (*select_scl)(struct rtl9300_i2c *i2c, u8 scl);
u32 data_reg;
int (*config_chan)(struct rtl9300_i2c *i2c, struct rtl9300_i2c_chan *chan);
void (*config_clock)(u32 clock_freq, struct rtl9300_i2c_chan *chan);
int (*misc_init)(struct rtl9300_i2c *i2c);
u32 rd_reg;
u32 wd_reg;
u8 max_nchan;
u8 max_data_len;
u8 reg_addr_8bit_len;
};
#define RTL9300_I2C_MUX_NCHAN 8
#define RTL9310_I2C_MUX_NCHAN 12
#define RTL9607_I2C_MUX_NCHAN 1
#define RTL9300_I2C_MAX_DATA_LEN 16
#define RTL9607_I2C_MAX_DATA_LEN 4
struct rtl9300_i2c {
struct regmap *regmap;
@@ -68,10 +89,12 @@ struct rtl9300_i2c {
struct rtl9300_i2c_chan chans[RTL9310_I2C_MUX_NCHAN];
struct regmap_field *fields[F_NUM_FIELDS];
u32 reg_base;
u32 data_reg;
u32 rd_reg;
u32 wd_reg;
u8 scl_num;
u8 sda_num;
struct mutex lock;
struct clk *clk;
};
DEFINE_GUARD(rtl9300_i2c, struct rtl9300_i2c *, mutex_lock(&_T->lock), mutex_unlock(&_T->lock))
@@ -99,6 +122,7 @@ struct rtl9300_i2c_xfer {
#define RTL9300_I2C_MST_DATA_WORD2 0x10
#define RTL9300_I2C_MST_DATA_WORD3 0x14
#define RTL9300_I2C_MST_GLB_CTRL 0x384
#define RTL9300_REG_ADDR_8BIT_LEN 1
#define RTL9310_I2C_MST_IF_CTRL 0x1004
#define RTL9310_I2C_MST_IF_SEL 0x1008
@@ -106,6 +130,14 @@ struct rtl9300_i2c_xfer {
#define RTL9310_I2C_MST_MEMADDR_CTRL 0x4
#define RTL9310_I2C_MST_DATA_CTRL 0x8
#define RTL9607_I2C_CONFIG 0x22f50
#define RTL9607_IO_MODE_EN 0x23014
#define RTL9607_I2C_IND_WD 0x0
#define RTL9607_I2C_IND_ADR 0x8
#define RTL9607_I2C_IND_CMD 0x10
#define RTL9607_I2C_IND_RD 0x18
#define RTL9607_REG_ADDR_8BIT_LEN 0
static int rtl9300_i2c_reg_addr_set(struct rtl9300_i2c *i2c, u32 reg, u16 len)
{
int ret;
@@ -157,6 +189,58 @@ static int rtl9300_i2c_config_chan(struct rtl9300_i2c *i2c, struct rtl9300_i2c_c
return 0;
}
static int rtl9607_i2c_config_chan(struct rtl9300_i2c *i2c, struct rtl9300_i2c_chan *chan)
{
const struct rtl9300_i2c_drv_data *drv_data;
int ret;
if (i2c->sda_num == chan->sda_num)
return 0;
ret = regmap_field_write(i2c->fields[F_CLK_DIV], chan->clk_div);
if (ret)
return ret;
drv_data = device_get_match_data(i2c->dev);
ret = drv_data->select_scl(i2c, i2c->scl_num);
if (ret)
return ret;
i2c->sda_num = chan->sda_num;
return 0;
}
static void rtl9300_i2c_config_clock(u32 clock_freq, struct rtl9300_i2c_chan *chan)
{
struct rtl9300_i2c *i2c = chan->i2c;
switch (clock_freq) {
case I2C_MAX_STANDARD_MODE_FREQ:
chan->bus_freq = RTL9300_I2C_STD_FREQ;
break;
case I2C_MAX_FAST_MODE_FREQ:
chan->bus_freq = RTL9300_I2C_FAST_FREQ;
break;
case RTL9300_I2C_MAX_SUPER_FAST_FREQ:
chan->bus_freq = RTL9300_I2C_SUPER_FAST_FREQ;
break;
case RTL9300_I2C_MAX_SLOW_FREQ:
chan->bus_freq = RTL9300_I2C_SLOW_FREQ;
break;
default:
dev_warn(i2c->dev, "SDA%d clock-frequency %d not supported using default\n",
chan->sda_num, clock_freq);
break;
}
}
static void rtl9607_i2c_config_clock(u32 clock_freq, struct rtl9300_i2c_chan *chan)
{
struct rtl9300_i2c *i2c = chan->i2c;
chan->clk_div = clk_get_rate(i2c->clk) / clock_freq - 1;
}
static int rtl9300_i2c_read(struct rtl9300_i2c *i2c, u8 *buf, u8 len)
{
u32 vals[4] = {};
@@ -165,7 +249,7 @@ static int rtl9300_i2c_read(struct rtl9300_i2c *i2c, u8 *buf, u8 len)
if (len > 16)
return -EIO;
ret = regmap_bulk_read(i2c->regmap, i2c->data_reg, vals, ARRAY_SIZE(vals));
ret = regmap_bulk_read(i2c->regmap, i2c->rd_reg, vals, ARRAY_SIZE(vals));
if (ret)
return ret;
@@ -192,19 +276,21 @@ static int rtl9300_i2c_write(struct rtl9300_i2c *i2c, u8 *buf, u8 len)
vals[reg] |= buf[i] << shift;
}
return regmap_bulk_write(i2c->regmap, i2c->data_reg, vals, ARRAY_SIZE(vals));
return regmap_bulk_write(i2c->regmap, i2c->wd_reg, vals, ARRAY_SIZE(vals));
}
static int rtl9300_i2c_writel(struct rtl9300_i2c *i2c, u32 data)
{
return regmap_write(i2c->regmap, i2c->data_reg, data);
return regmap_write(i2c->regmap, i2c->wd_reg, data);
}
static int rtl9300_i2c_prepare_xfer(struct rtl9300_i2c *i2c, struct rtl9300_i2c_xfer *xfer)
{
const struct rtl9300_i2c_drv_data *drv_data;
int ret;
if (xfer->data_len < 1 || xfer->data_len > 16)
drv_data = device_get_match_data(i2c->dev);
if (xfer->data_len < 1 || xfer->data_len > drv_data->max_data_len)
return -EINVAL;
ret = regmap_field_write(i2c->fields[F_DEV_ADDR], xfer->dev_addr);
@@ -249,7 +335,7 @@ static int rtl9300_i2c_do_xfer(struct rtl9300_i2c *i2c, struct rtl9300_i2c_xfer
if (ret)
return ret;
ret = regmap_field_read_poll_timeout(i2c->fields[F_I2C_TRIG], val, !val, 100, 100000);
ret = regmap_field_read_poll_timeout(i2c->fields[F_BUSY], val, !val, 100, 100000);
if (ret)
return ret;
@@ -262,14 +348,14 @@ static int rtl9300_i2c_do_xfer(struct rtl9300_i2c *i2c, struct rtl9300_i2c_xfer
if (!xfer->write) {
switch (xfer->type) {
case RTL9300_I2C_XFER_BYTE:
ret = regmap_read(i2c->regmap, i2c->data_reg, &val);
ret = regmap_read(i2c->regmap, i2c->rd_reg, &val);
if (ret)
return ret;
*xfer->data = val & 0xff;
break;
case RTL9300_I2C_XFER_WORD:
ret = regmap_read(i2c->regmap, i2c->data_reg, &val);
ret = regmap_read(i2c->regmap, i2c->rd_reg, &val);
if (ret)
return ret;
@@ -291,6 +377,7 @@ static int rtl9300_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr, unsigned s
union i2c_smbus_data *data)
{
struct rtl9300_i2c_chan *chan = i2c_get_adapdata(adap);
const struct rtl9300_i2c_drv_data *drv_data;
struct rtl9300_i2c *i2c = chan->i2c;
struct rtl9300_i2c_xfer xfer = {0};
int ret;
@@ -300,14 +387,15 @@ static int rtl9300_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr, unsigned s
guard(rtl9300_i2c)(i2c);
ret = rtl9300_i2c_config_chan(i2c, chan);
drv_data = device_get_match_data(i2c->dev);
ret = drv_data->config_chan(i2c, chan);
if (ret)
return ret;
xfer.dev_addr = addr & 0x7f;
xfer.write = (read_write == I2C_SMBUS_WRITE);
xfer.reg_addr = command;
xfer.reg_addr_len = 1;
xfer.reg_addr_len = drv_data->reg_addr_8bit_len;
switch (size) {
case I2C_SMBUS_BYTE:
@@ -367,6 +455,17 @@ static struct i2c_adapter_quirks rtl9300_i2c_quirks = {
.max_write_len = 16,
};
static int rtl9300_i2c_init(struct rtl9300_i2c *i2c)
{
/* only use standard read format */
return regmap_field_write(i2c->fields[F_RD_MODE], 0);
}
static int rtl9607_i2c_init(struct rtl9300_i2c *i2c)
{
return regmap_field_write(i2c->fields[F_EXT_SCK_5MS], 1);
}
static int rtl9300_i2c_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -402,7 +501,8 @@ static int rtl9300_i2c_probe(struct platform_device *pdev)
if (device_get_child_node_count(dev) > drv_data->max_nchan)
return dev_err_probe(dev, -EINVAL, "Too many channels\n");
i2c->data_reg = i2c->reg_base + drv_data->data_reg;
i2c->rd_reg = i2c->reg_base + drv_data->rd_reg;
i2c->wd_reg = i2c->reg_base + drv_data->wd_reg;
for (i = 0; i < F_NUM_FIELDS; i++) {
fields[i] = drv_data->field_desc[i].field;
if (drv_data->field_desc[i].scope == REG_SCOPE_MASTER)
@@ -413,6 +513,10 @@ static int rtl9300_i2c_probe(struct platform_device *pdev)
if (ret)
return ret;
i2c->clk = devm_clk_get_optional_enabled(dev, NULL);
if (IS_ERR(i2c->clk))
return dev_err_probe(dev, PTR_ERR(i2c->clk), "Failed to enable i2c clock\n");
i = 0;
for_each_child_of_node_scoped(dev->of_node, child) {
struct rtl9300_i2c_chan *chan = &i2c->chans[i];
@@ -426,21 +530,11 @@ static int rtl9300_i2c_probe(struct platform_device *pdev)
if (ret)
clock_freq = I2C_MAX_STANDARD_MODE_FREQ;
switch (clock_freq) {
case I2C_MAX_STANDARD_MODE_FREQ:
chan->bus_freq = RTL9300_I2C_STD_FREQ;
break;
case I2C_MAX_FAST_MODE_FREQ:
chan->bus_freq = RTL9300_I2C_FAST_FREQ;
break;
default:
dev_warn(i2c->dev, "SDA%d clock-frequency %d not supported using default\n",
sda_num, clock_freq);
break;
}
chan->sda_num = sda_num;
chan->i2c = i2c;
drv_data->config_clock(clock_freq, chan);
adap = &i2c->chans[i].adap;
adap->owner = THIS_MODULE;
adap->algo = &rtl9300_i2c_algo;
@@ -458,8 +552,7 @@ static int rtl9300_i2c_probe(struct platform_device *pdev)
}
i2c->sda_num = 0xff;
/* only use standard read format */
ret = regmap_field_write(i2c->fields[F_RD_MODE], 0);
ret = drv_data->misc_init(i2c);
if (ret)
return ret;
@@ -485,10 +578,17 @@ static const struct rtl9300_i2c_drv_data rtl9300_i2c_drv_data = {
[F_MEM_ADDR_WIDTH] = MST_REG_FIELD(RTL9300_I2C_MST_CTRL2, 2, 3),
[F_SCL_FREQ] = MST_REG_FIELD(RTL9300_I2C_MST_CTRL2, 0, 1),
[F_SDA_SEL] = GLB_REG_FIELD(RTL9300_I2C_MST_GLB_CTRL, 0, 7),
[F_BUSY] = MST_REG_FIELD(RTL9300_I2C_MST_CTRL1, 0, 0),
},
.select_scl = rtl9300_i2c_select_scl,
.data_reg = RTL9300_I2C_MST_DATA_WORD0,
.config_chan = rtl9300_i2c_config_chan,
.config_clock = rtl9300_i2c_config_clock,
.misc_init = rtl9300_i2c_init,
.rd_reg = RTL9300_I2C_MST_DATA_WORD0,
.wd_reg = RTL9300_I2C_MST_DATA_WORD0,
.max_nchan = RTL9300_I2C_MUX_NCHAN,
.max_data_len = RTL9300_I2C_MAX_DATA_LEN,
.reg_addr_8bit_len = RTL9300_REG_ADDR_8BIT_LEN,
};
static const struct rtl9300_i2c_drv_data rtl9310_i2c_drv_data = {
@@ -505,10 +605,42 @@ static const struct rtl9300_i2c_drv_data rtl9310_i2c_drv_data = {
[F_I2C_FAIL] = MST_REG_FIELD(RTL9310_I2C_MST_CTRL, 1, 1),
[F_I2C_TRIG] = MST_REG_FIELD(RTL9310_I2C_MST_CTRL, 0, 0),
[F_MEM_ADDR] = MST_REG_FIELD(RTL9310_I2C_MST_MEMADDR_CTRL, 0, 23),
[F_BUSY] = MST_REG_FIELD(RTL9310_I2C_MST_CTRL, 0, 0),
},
.select_scl = rtl9310_i2c_select_scl,
.data_reg = RTL9310_I2C_MST_DATA_CTRL,
.config_chan = rtl9300_i2c_config_chan,
.config_clock = rtl9300_i2c_config_clock,
.misc_init = rtl9300_i2c_init,
.rd_reg = RTL9310_I2C_MST_DATA_CTRL,
.wd_reg = RTL9310_I2C_MST_DATA_CTRL,
.max_nchan = RTL9310_I2C_MUX_NCHAN,
.max_data_len = RTL9300_I2C_MAX_DATA_LEN,
.reg_addr_8bit_len = RTL9300_REG_ADDR_8BIT_LEN,
};
static const struct rtl9300_i2c_drv_data rtl9607_i2c_drv_data = {
.field_desc = {
[F_SCL_SEL] = GLB_REG_FIELD(RTL9607_IO_MODE_EN, 13, 14),
[F_EXT_SCK_5MS] = MST_REG_FIELD(RTL9607_I2C_CONFIG, 26, 26),
[F_DEV_ADDR] = MST_REG_FIELD(RTL9607_I2C_CONFIG, 14, 20),
[F_MEM_ADDR_WIDTH] = MST_REG_FIELD(RTL9607_I2C_CONFIG, 12, 13),
[F_DATA_WIDTH] = MST_REG_FIELD(RTL9607_I2C_CONFIG, 10, 11),
[F_CLK_DIV] = MST_REG_FIELD(RTL9607_I2C_CONFIG, 0, 9),
[F_I2C_FAIL] = MST_REG_FIELD(RTL9607_I2C_IND_CMD, 3, 3),
[F_BUSY] = MST_REG_FIELD(RTL9607_I2C_IND_CMD, 2, 2),
[F_RWOP] = MST_REG_FIELD(RTL9607_I2C_IND_CMD, 1, 1),
[F_I2C_TRIG] = MST_REG_FIELD(RTL9607_I2C_IND_CMD, 0, 0),
[F_MEM_ADDR] = MST_REG_FIELD(RTL9607_I2C_IND_ADR, 0, 31),
},
.select_scl = rtl9310_i2c_select_scl,
.config_chan = rtl9607_i2c_config_chan,
.config_clock = rtl9607_i2c_config_clock,
.misc_init = rtl9607_i2c_init,
.rd_reg = RTL9607_I2C_IND_RD,
.wd_reg = RTL9607_I2C_IND_WD,
.max_nchan = RTL9607_I2C_MUX_NCHAN,
.max_data_len = RTL9607_I2C_MAX_DATA_LEN,
.reg_addr_8bit_len = RTL9607_REG_ADDR_8BIT_LEN,
};
static const struct of_device_id i2c_rtl9300_dt_ids[] = {
@@ -520,6 +652,7 @@ static const struct of_device_id i2c_rtl9300_dt_ids[] = {
{ .compatible = "realtek,rtl9311-i2c", .data = (void *) &rtl9310_i2c_drv_data },
{ .compatible = "realtek,rtl9312-i2c", .data = (void *) &rtl9310_i2c_drv_data },
{ .compatible = "realtek,rtl9313-i2c", .data = (void *) &rtl9310_i2c_drv_data },
{ .compatible = "realtek,rtl9607-i2c", .data = (void *) &rtl9607_i2c_drv_data },
{}
};
MODULE_DEVICE_TABLE(of, i2c_rtl9300_dt_ids);
+6 -1
View File
@@ -503,8 +503,13 @@ static void i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
i2c->msg->buf[i2c->msg_ptr++] = byte;
/* Add actual length to read for smbus block read */
if (i2c->msg->flags & I2C_M_RECV_LEN && i2c->msg->len == 1)
if (i2c->msg->flags & I2C_M_RECV_LEN && i2c->msg->len == 1) {
if (byte == 0 || byte > I2C_SMBUS_BLOCK_MAX) {
s3c24xx_i2c_stop(i2c, -EPROTO);
break;
}
i2c->msg->len += byte;
}
prepare_read:
if (is_msglast(i2c)) {
/* last byte of buffer */
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More