i2c-for-7.1-rc1-part1

- 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
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEOZGx6rniZ1Gk92RdFA3kzBSgKbYFAmnjHO8ACgkQFA3kzBSg
 KbaWaw//eCB8xtFFo2S4i/ZJrnLnEo317VJBtHiAQjQdV+9LgVIk8S66JG5mzzJO
 yFVBXZ6Qx6RuPUxYo8V+PvW/4/GemcWANcnztT3G6+SQXF6ATcnnDzzCf9KjV5PI
 m7RNH44hZInP39TBpAj/hG2eas4F4S0zkcpuV+s5IB7tUkxdQhkSjrseMoTVZGh8
 FDEsiQIlJR3qxjIa/FPw1/iuC7FJHJfuWjT3czNil0uLb/i+xOpHWjDvgaAXi+wU
 U58zz2AyJTbUPclO0H4udbQbQ+qACjOSaelEf+v5wlWmy6BT0ZI+CO/pRteD+Iix
 UHb/zPilrBG42JN+L7ndJat4jW1POEi6fol9y1gg9yWtH09QGEfR16+YlqDag4/M
 Cgu1I3QUatGlT7jXkg8pr2Q/u7IFi4XGyvsNIs4k7oqYkbZKMCyWFDPVC5EByNus
 JcnpRACuJldDv3Rj1jZXUjVE1vDBb438lR8XRrrGpYd+j7xS7vFRjDxE/47y+weR
 sP83ODZH2GesQx3VkZPOnINd9/qfKEPYqilxkkoAO+0mh+iCdstyrjg3VlFbZNpf
 eeSZqlGNLVcDEpY8HENSLxdp3PANRxTqDVlGrYPEt3WH0EmWOhhXLOysKtDEgehL
 qKYiouyXgcCwVgBkp3sR7REQ0+LfRi+U8Y2Rw02WKjMk1jclRUA=
 =G0Mn
 -----END PGP SIGNATURE-----

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
commit fba676bd29
24 changed files with 967 additions and 390 deletions

View File

@ -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>;
};

View File

@ -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>;
};

View File

@ -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:

View File

@ -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

View File

@ -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)

View File

@ -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:

View File

@ -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

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

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,
};

View File

@ -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 },

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");
}

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,
};

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);

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",

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

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;

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 = {

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);

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 */

View File

@ -30,38 +30,29 @@
#define BYTES_PER_FIFO_WORD 4
#define I2C_CNFG 0x000
#define I2C_CNFG_DEBOUNCE_CNT GENMASK(14, 12)
#define I2C_CNFG_PACKET_MODE_EN BIT(10)
#define I2C_CNFG_NEW_MASTER_FSM BIT(11)
#define I2C_CNFG_MULTI_MASTER_MODE BIT(17)
#define I2C_STATUS 0x01c
#define I2C_SL_CNFG 0x020
#define I2C_SL_CNFG_NACK BIT(1)
#define I2C_SL_CNFG_NEWSL BIT(2)
#define I2C_SL_ADDR1 0x02c
#define I2C_SL_ADDR2 0x030
#define I2C_TLOW_SEXT 0x034
#define I2C_TX_FIFO 0x050
#define I2C_RX_FIFO 0x054
#define I2C_PACKET_TRANSFER_STATUS 0x058
#define I2C_FIFO_CONTROL 0x05c
#define I2C_FIFO_CONTROL_TX_FLUSH BIT(1)
#define I2C_FIFO_CONTROL_RX_FLUSH BIT(0)
#define I2C_FIFO_CONTROL_TX_TRIG(x) (((x) - 1) << 5)
#define I2C_FIFO_CONTROL_RX_TRIG(x) (((x) - 1) << 2)
#define I2C_FIFO_STATUS 0x060
#define I2C_FIFO_STATUS_TX GENMASK(7, 4)
#define I2C_FIFO_STATUS_RX GENMASK(3, 0)
#define I2C_INT_MASK 0x064
#define I2C_INT_STATUS 0x068
#define I2C_INT_BUS_CLR_DONE BIT(11)
#define I2C_INT_PACKET_XFER_COMPLETE BIT(7)
#define I2C_INT_NO_ACK BIT(3)
#define I2C_INT_ARBITRATION_LOST BIT(2)
#define I2C_INT_TX_FIFO_DATA_REQ BIT(1)
#define I2C_INT_RX_FIFO_DATA_REQ BIT(0)
#define I2C_CLK_DIVISOR 0x06c
#define I2C_CLK_DIVISOR_STD_FAST_MODE GENMASK(31, 16)
#define I2C_CLK_DIVISOR_HSMODE GENMASK(15, 0)
@ -94,50 +85,38 @@
#define I2C_HEADER_CONTINUE_XFER BIT(15)
#define I2C_HEADER_SLAVE_ADDR_SHIFT 1
#define I2C_BUS_CLEAR_CNFG 0x084
#define I2C_BC_SCLK_THRESHOLD GENMASK(23, 16)
#define I2C_BC_STOP_COND BIT(2)
#define I2C_BC_TERMINATE BIT(1)
#define I2C_BC_ENABLE BIT(0)
#define I2C_BUS_CLEAR_STATUS 0x088
#define I2C_BC_STATUS BIT(0)
#define I2C_CONFIG_LOAD 0x08c
#define I2C_MSTR_CONFIG_LOAD BIT(0)
#define I2C_CLKEN_OVERRIDE 0x090
#define I2C_MST_CORE_CLKEN_OVR BIT(0)
#define I2C_INTERFACE_TIMING_0 0x094
#define I2C_INTERFACE_TIMING_THIGH GENMASK(13, 8)
#define I2C_INTERFACE_TIMING_TLOW GENMASK(5, 0)
#define I2C_INTERFACE_TIMING_1 0x098
#define I2C_INTERFACE_TIMING_TBUF GENMASK(29, 24)
#define I2C_INTERFACE_TIMING_TSU_STO GENMASK(21, 16)
#define I2C_INTERFACE_TIMING_THD_STA GENMASK(13, 8)
#define I2C_INTERFACE_TIMING_TSU_STA GENMASK(5, 0)
#define I2C_INTERFACE_TIMING_THIGH GENMASK(13, 8)
#define I2C_INTERFACE_TIMING_TLOW GENMASK(5, 0)
#define I2C_INTERFACE_TIMING_TBUF GENMASK(29, 24)
#define I2C_INTERFACE_TIMING_TSU_STO GENMASK(21, 16)
#define I2C_INTERFACE_TIMING_THD_STA GENMASK(13, 8)
#define I2C_INTERFACE_TIMING_TSU_STA GENMASK(5, 0)
#define I2C_HS_INTERFACE_TIMING_0 0x09c
#define I2C_HS_INTERFACE_TIMING_THIGH GENMASK(13, 8)
#define I2C_HS_INTERFACE_TIMING_TLOW GENMASK(5, 0)
#define I2C_HS_INTERFACE_TIMING_1 0x0a0
#define I2C_HS_INTERFACE_TIMING_TSU_STO GENMASK(21, 16)
#define I2C_HS_INTERFACE_TIMING_THD_STA GENMASK(13, 8)
#define I2C_HS_INTERFACE_TIMING_TSU_STA GENMASK(5, 0)
#define I2C_HS_INTERFACE_TIMING_THIGH GENMASK(13, 8)
#define I2C_HS_INTERFACE_TIMING_TLOW GENMASK(5, 0)
#define I2C_HS_INTERFACE_TIMING_TSU_STO GENMASK(21, 16)
#define I2C_HS_INTERFACE_TIMING_THD_STA GENMASK(13, 8)
#define I2C_HS_INTERFACE_TIMING_TSU_STA GENMASK(5, 0)
#define I2C_MST_FIFO_CONTROL 0x0b4
#define I2C_MST_FIFO_CONTROL_RX_FLUSH BIT(0)
#define I2C_MST_FIFO_CONTROL_TX_FLUSH BIT(1)
#define I2C_MST_FIFO_CONTROL_RX_TRIG(x) (((x) - 1) << 4)
#define I2C_MST_FIFO_CONTROL_TX_TRIG(x) (((x) - 1) << 16)
#define I2C_MST_FIFO_STATUS 0x0b8
#define I2C_MST_FIFO_STATUS_TX GENMASK(23, 16)
#define I2C_MST_FIFO_STATUS_RX GENMASK(7, 0)
#define I2C_MASTER_RESET_CNTRL 0x0a8
#define I2C_SW_MUTEX 0x0ec
#define I2C_SW_MUTEX_REQUEST GENMASK(3, 0)
#define I2C_SW_MUTEX_GRANT GENMASK(7, 4)
#define I2C_SW_MUTEX_ID_CCPLEX 9
@ -159,6 +138,171 @@
*/
#define I2C_PIO_MODE_PREFERRED_LEN 32
struct tegra_i2c_regs {
unsigned int cnfg;
unsigned int status;
unsigned int sl_cnfg;
unsigned int sl_addr1;
unsigned int sl_addr2;
unsigned int tlow_sext;
unsigned int tx_fifo;
unsigned int rx_fifo;
unsigned int packet_transfer_status;
unsigned int fifo_control;
unsigned int fifo_status;
unsigned int int_mask;
unsigned int int_status;
unsigned int clk_divisor;
unsigned int bus_clear_cnfg;
unsigned int bus_clear_status;
unsigned int config_load;
unsigned int clken_override;
unsigned int interface_timing_0;
unsigned int interface_timing_1;
unsigned int hs_interface_timing_0;
unsigned int hs_interface_timing_1;
unsigned int master_reset_cntrl;
unsigned int mst_fifo_control;
unsigned int mst_fifo_status;
unsigned int sw_mutex;
};
static const struct tegra_i2c_regs tegra20_i2c_regs = {
.cnfg = 0x000,
.status = 0x01c,
.sl_cnfg = 0x020,
.sl_addr1 = 0x02c,
.sl_addr2 = 0x030,
.tx_fifo = 0x050,
.rx_fifo = 0x054,
.packet_transfer_status = 0x058,
.fifo_control = 0x05c,
.fifo_status = 0x060,
.int_mask = 0x064,
.int_status = 0x068,
.clk_divisor = 0x06c,
.bus_clear_cnfg = 0x084,
.bus_clear_status = 0x088,
.config_load = 0x08c,
.clken_override = 0x090,
.interface_timing_0 = 0x094,
.interface_timing_1 = 0x098,
.hs_interface_timing_0 = 0x09c,
.hs_interface_timing_1 = 0x0a0,
.master_reset_cntrl = 0x0a8,
.mst_fifo_control = 0x0b4,
.mst_fifo_status = 0x0b8,
};
#if IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC)
static const struct tegra_i2c_regs tegra20_dvc_i2c_regs = {
.cnfg = 0x040,
.status = 0x05c,
.tx_fifo = 0x060,
.rx_fifo = 0x064,
.packet_transfer_status = 0x068,
.fifo_control = 0x06c,
.fifo_status = 0x070,
.int_mask = 0x074,
.int_status = 0x078,
.clk_divisor = 0x07c,
.bus_clear_cnfg = 0x094,
.bus_clear_status = 0x098,
.config_load = 0x09c,
.clken_override = 0x0a0,
.interface_timing_0 = 0x0a4,
.interface_timing_1 = 0x0a8,
.hs_interface_timing_0 = 0x0ac,
.hs_interface_timing_1 = 0x0b0,
.master_reset_cntrl = 0x0b8,
.mst_fifo_control = 0x0c4,
.mst_fifo_status = 0x0c8,
};
#endif
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
static const struct tegra_i2c_regs tegra210_vi_i2c_regs = {
.cnfg = 0x0c00,
.status = 0x0c70,
.tlow_sext = 0x0cd0,
.tx_fifo = 0x0d40,
.rx_fifo = 0x0d50,
.packet_transfer_status = 0x0d60,
.fifo_control = 0x0d70,
.fifo_status = 0x0d80,
.int_mask = 0x0d90,
.int_status = 0x0da0,
.clk_divisor = 0x0db0,
.bus_clear_cnfg = 0x0e10,
.bus_clear_status = 0x0e20,
.config_load = 0x0e30,
.clken_override = 0x0e40,
.interface_timing_0 = 0x0e50,
.interface_timing_1 = 0x0e60,
.hs_interface_timing_0 = 0x0e70,
.hs_interface_timing_1 = 0x0e80,
.master_reset_cntrl = 0x0ea0,
.mst_fifo_control = 0x0ed0,
.mst_fifo_status = 0x0ee0,
};
#endif
static const struct tegra_i2c_regs tegra264_i2c_regs = {
.cnfg = 0x000,
.status = 0x01c,
.sl_cnfg = 0x020,
.sl_addr1 = 0x02c,
.sl_addr2 = 0x030,
.tx_fifo = 0x050,
.rx_fifo = 0x054,
.packet_transfer_status = 0x058,
.fifo_control = 0x05c,
.fifo_status = 0x060,
.int_mask = 0x064,
.int_status = 0x068,
.clk_divisor = 0x06c,
.bus_clear_cnfg = 0x084,
.bus_clear_status = 0x088,
.config_load = 0x08c,
.clken_override = 0x090,
.interface_timing_0 = 0x094,
.interface_timing_1 = 0x098,
.hs_interface_timing_0 = 0x09c,
.hs_interface_timing_1 = 0x0a0,
.master_reset_cntrl = 0x0a8,
.mst_fifo_control = 0x0b4,
.mst_fifo_status = 0x0b8,
.sw_mutex = 0x0ec,
};
static const struct tegra_i2c_regs tegra410_i2c_regs = {
.cnfg = 0x000,
.status = 0x01c,
.sl_cnfg = 0x020,
.sl_addr1 = 0x02c,
.sl_addr2 = 0x030,
.tx_fifo = 0x054,
.rx_fifo = 0x058,
.packet_transfer_status = 0x05c,
.fifo_control = 0x060,
.fifo_status = 0x064,
.int_mask = 0x068,
.int_status = 0x06c,
.clk_divisor = 0x070,
.bus_clear_cnfg = 0x088,
.bus_clear_status = 0x08c,
.config_load = 0x090,
.clken_override = 0x094,
.interface_timing_0 = 0x098,
.interface_timing_1 = 0x09c,
.hs_interface_timing_0 = 0x0a0,
.hs_interface_timing_1 = 0x0a4,
.master_reset_cntrl = 0x0ac,
.mst_fifo_control = 0x0b8,
.mst_fifo_status = 0x0bc,
.sw_mutex = 0x0f0,
};
/*
* msg_end_type: The bus control which needs to be sent at end of transfer.
* @MSG_END_STOP: Send stop pulse.
@ -171,6 +315,18 @@ enum msg_end_type {
MSG_END_CONTINUE,
};
/*
* tegra_i2c_variant: Identifies the variant of I2C controller.
* @TEGRA_I2C_VARIANT_DEFAULT: Identifies the default I2C controller.
* @TEGRA_I2C_VARIANT_DVC: Identifies the DVC I2C controller, has a different register layout.
* @TEGRA_I2C_VARIANT_VI: Identifies the VI I2C controller, has a different register layout.
*/
enum tegra_i2c_variant {
TEGRA_I2C_VARIANT_DEFAULT,
TEGRA_I2C_VARIANT_DVC,
TEGRA_I2C_VARIANT_VI,
};
/**
* struct tegra_i2c_hw_feature : per hardware generation features
* @has_continue_xfer_support: continue-transfer supported
@ -223,6 +379,8 @@ enum msg_end_type {
* timing settings.
* @enable_hs_mode_support: Enable support for high speed (HS) mode transfers.
* @has_mutex: Has mutex register for mutual exclusion with other firmwares or VMs.
* @variant: This represents the I2C controller variant.
* @regs: Register offsets for the specific SoC variant.
*/
struct tegra_i2c_hw_feature {
bool has_continue_xfer_support;
@ -254,6 +412,8 @@ struct tegra_i2c_hw_feature {
bool has_interface_timing_reg;
bool enable_hs_mode_support;
bool has_mutex;
enum tegra_i2c_variant variant;
const struct tegra_i2c_regs *regs;
};
/**
@ -268,8 +428,6 @@ struct tegra_i2c_hw_feature {
* @base_phys: physical base address of the I2C controller
* @cont_id: I2C controller ID, used for packet header
* @irq: IRQ number of transfer complete interrupt
* @is_dvc: identifies the DVC I2C controller, has a different register layout
* @is_vi: identifies the VI I2C controller, has a different register layout
* @msg_complete: transfer completion notifier
* @msg_buf_remaining: size of unsent data in the message buffer
* @msg_len: length of message in current transfer
@ -321,12 +479,12 @@ struct tegra_i2c_dev {
bool atomic_mode;
bool dma_mode;
bool msg_read;
bool is_dvc;
bool is_vi;
};
#define IS_DVC(dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && (dev)->is_dvc)
#define IS_VI(dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) && (dev)->is_vi)
#define IS_DVC(dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && \
(dev)->hw->variant == TEGRA_I2C_VARIANT_DVC)
#define IS_VI(dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) && \
(dev)->hw->variant == TEGRA_I2C_VARIANT_VI)
static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val,
unsigned int reg)
@ -339,40 +497,26 @@ static u32 dvc_readl(struct tegra_i2c_dev *i2c_dev, unsigned int reg)
return readl_relaxed(i2c_dev->base + reg);
}
/*
* If necessary, i2c_writel() and i2c_readl() will offset the register
* in order to talk to the I2C block inside the DVC block.
*/
static u32 tegra_i2c_reg_addr(struct tegra_i2c_dev *i2c_dev, unsigned int reg)
{
if (IS_DVC(i2c_dev))
reg += (reg >= I2C_TX_FIFO) ? 0x10 : 0x40;
else if (IS_VI(i2c_dev))
reg = 0xc00 + (reg << 2);
return reg;
}
static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned int reg)
{
writel_relaxed(val, i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
writel_relaxed(val, i2c_dev->base + reg);
/* read back register to make sure that register writes completed */
if (reg != I2C_TX_FIFO)
readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
if (reg != i2c_dev->hw->regs->tx_fifo)
readl_relaxed(i2c_dev->base + reg);
else if (IS_VI(i2c_dev))
readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, I2C_INT_STATUS));
readl_relaxed(i2c_dev->base + i2c_dev->hw->regs->int_status);
}
static u32 i2c_readl(struct tegra_i2c_dev *i2c_dev, unsigned int reg)
{
return readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
return readl_relaxed(i2c_dev->base + reg);
}
static void i2c_writesl(struct tegra_i2c_dev *i2c_dev, void *data,
unsigned int reg, unsigned int len)
{
writesl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len);
writesl(i2c_dev->base + reg, data, len);
}
static void i2c_writesl_vi(struct tegra_i2c_dev *i2c_dev, void *data,
@ -393,12 +537,12 @@ static void i2c_writesl_vi(struct tegra_i2c_dev *i2c_dev, void *data,
static void i2c_readsl(struct tegra_i2c_dev *i2c_dev, void *data,
unsigned int reg, unsigned int len)
{
readsl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len);
readsl(i2c_dev->base + reg, data, len);
}
static bool tegra_i2c_mutex_acquired(struct tegra_i2c_dev *i2c_dev)
{
unsigned int reg = tegra_i2c_reg_addr(i2c_dev, I2C_SW_MUTEX);
unsigned int reg = i2c_dev->hw->regs->sw_mutex;
u32 val, id;
val = readl(i2c_dev->base + reg);
@ -409,7 +553,7 @@ static bool tegra_i2c_mutex_acquired(struct tegra_i2c_dev *i2c_dev)
static bool tegra_i2c_mutex_trylock(struct tegra_i2c_dev *i2c_dev)
{
unsigned int reg = tegra_i2c_reg_addr(i2c_dev, I2C_SW_MUTEX);
unsigned int reg = i2c_dev->hw->regs->sw_mutex;
u32 val, id;
val = readl(i2c_dev->base + reg);
@ -447,7 +591,7 @@ static int tegra_i2c_mutex_lock(struct tegra_i2c_dev *i2c_dev)
static int tegra_i2c_mutex_unlock(struct tegra_i2c_dev *i2c_dev)
{
unsigned int reg = tegra_i2c_reg_addr(i2c_dev, I2C_SW_MUTEX);
unsigned int reg = i2c_dev->hw->regs->sw_mutex;
u32 val, id;
if (!i2c_dev->hw->has_mutex)
@ -470,16 +614,16 @@ static void tegra_i2c_mask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask)
{
u32 int_mask;
int_mask = i2c_readl(i2c_dev, I2C_INT_MASK) & ~mask;
i2c_writel(i2c_dev, int_mask, I2C_INT_MASK);
int_mask = i2c_readl(i2c_dev, i2c_dev->hw->regs->int_mask) & ~mask;
i2c_writel(i2c_dev, int_mask, i2c_dev->hw->regs->int_mask);
}
static void tegra_i2c_unmask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask)
{
u32 int_mask;
int_mask = i2c_readl(i2c_dev, I2C_INT_MASK) | mask;
i2c_writel(i2c_dev, int_mask, I2C_INT_MASK);
int_mask = i2c_readl(i2c_dev, i2c_dev->hw->regs->int_mask) | mask;
i2c_writel(i2c_dev, int_mask, i2c_dev->hw->regs->int_mask);
}
static void tegra_i2c_dma_complete(void *args)
@ -623,34 +767,34 @@ static void tegra_i2c_vi_init(struct tegra_i2c_dev *i2c_dev)
value = FIELD_PREP(I2C_INTERFACE_TIMING_THIGH, 2) |
FIELD_PREP(I2C_INTERFACE_TIMING_TLOW, 4);
i2c_writel(i2c_dev, value, I2C_INTERFACE_TIMING_0);
i2c_writel(i2c_dev, value, i2c_dev->hw->regs->interface_timing_0);
value = FIELD_PREP(I2C_INTERFACE_TIMING_TBUF, 4) |
FIELD_PREP(I2C_INTERFACE_TIMING_TSU_STO, 7) |
FIELD_PREP(I2C_INTERFACE_TIMING_THD_STA, 4) |
FIELD_PREP(I2C_INTERFACE_TIMING_TSU_STA, 4);
i2c_writel(i2c_dev, value, I2C_INTERFACE_TIMING_1);
i2c_writel(i2c_dev, value, i2c_dev->hw->regs->interface_timing_1);
value = FIELD_PREP(I2C_HS_INTERFACE_TIMING_THIGH, 3) |
FIELD_PREP(I2C_HS_INTERFACE_TIMING_TLOW, 8);
i2c_writel(i2c_dev, value, I2C_HS_INTERFACE_TIMING_0);
i2c_writel(i2c_dev, value, i2c_dev->hw->regs->hs_interface_timing_0);
value = FIELD_PREP(I2C_HS_INTERFACE_TIMING_TSU_STO, 11) |
FIELD_PREP(I2C_HS_INTERFACE_TIMING_THD_STA, 11) |
FIELD_PREP(I2C_HS_INTERFACE_TIMING_TSU_STA, 11);
i2c_writel(i2c_dev, value, I2C_HS_INTERFACE_TIMING_1);
i2c_writel(i2c_dev, value, i2c_dev->hw->regs->hs_interface_timing_1);
value = FIELD_PREP(I2C_BC_SCLK_THRESHOLD, 9) | I2C_BC_STOP_COND;
i2c_writel(i2c_dev, value, I2C_BUS_CLEAR_CNFG);
i2c_writel(i2c_dev, value, i2c_dev->hw->regs->bus_clear_cnfg);
i2c_writel(i2c_dev, 0x0, I2C_TLOW_SEXT);
i2c_writel(i2c_dev, 0x0, i2c_dev->hw->regs->tlow_sext);
}
static int tegra_i2c_poll_register(struct tegra_i2c_dev *i2c_dev,
u32 reg, u32 mask, u32 delay_us,
u32 timeout_us)
{
void __iomem *addr = i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg);
void __iomem *addr = i2c_dev->base + reg;
u32 val;
if (!i2c_dev->atomic_mode)
@ -669,11 +813,11 @@ static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
if (i2c_dev->hw->has_mst_fifo) {
mask = I2C_MST_FIFO_CONTROL_TX_FLUSH |
I2C_MST_FIFO_CONTROL_RX_FLUSH;
offset = I2C_MST_FIFO_CONTROL;
offset = i2c_dev->hw->regs->mst_fifo_control;
} else {
mask = I2C_FIFO_CONTROL_TX_FLUSH |
I2C_FIFO_CONTROL_RX_FLUSH;
offset = I2C_FIFO_CONTROL;
offset = i2c_dev->hw->regs->fifo_control;
}
val = i2c_readl(i2c_dev, offset);
@ -696,9 +840,9 @@ static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev)
if (!i2c_dev->hw->has_config_load_reg)
return 0;
i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD);
i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, i2c_dev->hw->regs->config_load);
err = tegra_i2c_poll_register(i2c_dev, I2C_CONFIG_LOAD, 0xffffffff,
err = tegra_i2c_poll_register(i2c_dev, i2c_dev->hw->regs->config_load, 0xffffffff,
1000, I2C_CONFIG_LOAD_TIMEOUT);
if (err) {
dev_err(i2c_dev->dev, "failed to load config\n");
@ -719,10 +863,10 @@ static int tegra_i2c_master_reset(struct tegra_i2c_dev *i2c_dev)
* SW needs to wait for 2us after assertion and de-assertion of this soft
* reset.
*/
i2c_writel(i2c_dev, 0x1, I2C_MASTER_RESET_CNTRL);
i2c_writel(i2c_dev, 0x1, i2c_dev->hw->regs->master_reset_cntrl);
fsleep(2);
i2c_writel(i2c_dev, 0x0, I2C_MASTER_RESET_CNTRL);
i2c_writel(i2c_dev, 0x0, i2c_dev->hw->regs->master_reset_cntrl);
fsleep(2);
return 0;
@ -764,8 +908,8 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
if (i2c_dev->hw->has_multi_master_mode)
val |= I2C_CNFG_MULTI_MASTER_MODE;
i2c_writel(i2c_dev, val, I2C_CNFG);
i2c_writel(i2c_dev, 0, I2C_INT_MASK);
i2c_writel(i2c_dev, val, i2c_dev->hw->regs->cnfg);
i2c_writel(i2c_dev, 0, i2c_dev->hw->regs->int_mask);
if (IS_VI(i2c_dev))
tegra_i2c_vi_init(i2c_dev);
@ -810,12 +954,12 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
clk_divisor = FIELD_PREP(I2C_CLK_DIVISOR_HSMODE,
i2c_dev->hw->clk_divisor_hs_mode) |
FIELD_PREP(I2C_CLK_DIVISOR_STD_FAST_MODE, non_hs_mode);
i2c_writel(i2c_dev, clk_divisor, I2C_CLK_DIVISOR);
i2c_writel(i2c_dev, clk_divisor, i2c_dev->hw->regs->clk_divisor);
if (i2c_dev->hw->has_interface_timing_reg) {
val = FIELD_PREP(I2C_INTERFACE_TIMING_THIGH, thigh) |
FIELD_PREP(I2C_INTERFACE_TIMING_TLOW, tlow);
i2c_writel(i2c_dev, val, I2C_INTERFACE_TIMING_0);
i2c_writel(i2c_dev, val, i2c_dev->hw->regs->interface_timing_0);
}
/*
@ -823,7 +967,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
* Otherwise, preserve the chip default values.
*/
if (i2c_dev->hw->has_interface_timing_reg && tsu_thd)
i2c_writel(i2c_dev, tsu_thd, I2C_INTERFACE_TIMING_1);
i2c_writel(i2c_dev, tsu_thd, i2c_dev->hw->regs->interface_timing_1);
/* Write HS mode registers. These will get used only for HS mode*/
if (i2c_dev->hw->enable_hs_mode_support) {
@ -833,8 +977,8 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
val = FIELD_PREP(I2C_HS_INTERFACE_TIMING_THIGH, thigh) |
FIELD_PREP(I2C_HS_INTERFACE_TIMING_TLOW, tlow);
i2c_writel(i2c_dev, val, I2C_HS_INTERFACE_TIMING_0);
i2c_writel(i2c_dev, tsu_thd, I2C_HS_INTERFACE_TIMING_1);
i2c_writel(i2c_dev, val, i2c_dev->hw->regs->hs_interface_timing_0);
i2c_writel(i2c_dev, tsu_thd, i2c_dev->hw->regs->hs_interface_timing_1);
}
clk_multiplier = (tlow + thigh + 2) * (non_hs_mode + 1);
@ -847,12 +991,12 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
}
if (!IS_DVC(i2c_dev) && !IS_VI(i2c_dev)) {
u32 sl_cfg = i2c_readl(i2c_dev, I2C_SL_CNFG);
u32 sl_cfg = i2c_readl(i2c_dev, i2c_dev->hw->regs->sl_cnfg);
sl_cfg |= I2C_SL_CNFG_NACK | I2C_SL_CNFG_NEWSL;
i2c_writel(i2c_dev, sl_cfg, I2C_SL_CNFG);
i2c_writel(i2c_dev, 0xfc, I2C_SL_ADDR1);
i2c_writel(i2c_dev, 0x00, I2C_SL_ADDR2);
i2c_writel(i2c_dev, sl_cfg, i2c_dev->hw->regs->sl_cnfg);
i2c_writel(i2c_dev, 0xfc, i2c_dev->hw->regs->sl_addr1);
i2c_writel(i2c_dev, 0x00, i2c_dev->hw->regs->sl_addr2);
}
err = tegra_i2c_flush_fifos(i2c_dev);
@ -860,7 +1004,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
return err;
if (i2c_dev->multimaster_mode && i2c_dev->hw->has_slcg_override_reg)
i2c_writel(i2c_dev, I2C_MST_CORE_CLKEN_OVR, I2C_CLKEN_OVERRIDE);
i2c_writel(i2c_dev, I2C_MST_CORE_CLKEN_OVR, i2c_dev->hw->regs->clken_override);
err = tegra_i2c_wait_for_config_load(i2c_dev);
if (err)
@ -881,9 +1025,9 @@ static int tegra_i2c_disable_packet_mode(struct tegra_i2c_dev *i2c_dev)
*/
udelay(DIV_ROUND_UP(2 * 1000000, i2c_dev->timings.bus_freq_hz));
cnfg = i2c_readl(i2c_dev, I2C_CNFG);
cnfg = i2c_readl(i2c_dev, i2c_dev->hw->regs->cnfg);
if (cnfg & I2C_CNFG_PACKET_MODE_EN)
i2c_writel(i2c_dev, cnfg & ~I2C_CNFG_PACKET_MODE_EN, I2C_CNFG);
i2c_writel(i2c_dev, cnfg & ~I2C_CNFG_PACKET_MODE_EN, i2c_dev->hw->regs->cnfg);
return tegra_i2c_wait_for_config_load(i2c_dev);
}
@ -903,10 +1047,10 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
return -EINVAL;
if (i2c_dev->hw->has_mst_fifo) {
val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
val = i2c_readl(i2c_dev, i2c_dev->hw->regs->mst_fifo_status);
rx_fifo_avail = FIELD_GET(I2C_MST_FIFO_STATUS_RX, val);
} else {
val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
val = i2c_readl(i2c_dev, i2c_dev->hw->regs->fifo_status);
rx_fifo_avail = FIELD_GET(I2C_FIFO_STATUS_RX, val);
}
@ -915,7 +1059,7 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
if (words_to_transfer > rx_fifo_avail)
words_to_transfer = rx_fifo_avail;
i2c_readsl(i2c_dev, buf, I2C_RX_FIFO, words_to_transfer);
i2c_readsl(i2c_dev, buf, i2c_dev->hw->regs->rx_fifo, words_to_transfer);
buf += words_to_transfer * BYTES_PER_FIFO_WORD;
buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD;
@ -931,7 +1075,7 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
* when (words_to_transfer was > rx_fifo_avail) earlier
* in this function.
*/
val = i2c_readl(i2c_dev, I2C_RX_FIFO);
val = i2c_readl(i2c_dev, i2c_dev->hw->regs->rx_fifo);
val = cpu_to_le32(val);
memcpy(buf, &val, buf_remaining);
buf_remaining = 0;
@ -956,10 +1100,10 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
u32 val;
if (i2c_dev->hw->has_mst_fifo) {
val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
val = i2c_readl(i2c_dev, i2c_dev->hw->regs->mst_fifo_status);
tx_fifo_avail = FIELD_GET(I2C_MST_FIFO_STATUS_TX, val);
} else {
val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
val = i2c_readl(i2c_dev, i2c_dev->hw->regs->fifo_status);
tx_fifo_avail = FIELD_GET(I2C_FIFO_STATUS_TX, val);
}
@ -990,9 +1134,9 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
i2c_dev->msg_buf = buf + words_to_transfer * BYTES_PER_FIFO_WORD;
if (IS_VI(i2c_dev))
i2c_writesl_vi(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
i2c_writesl_vi(i2c_dev, buf, i2c_dev->hw->regs->tx_fifo, words_to_transfer);
else
i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
i2c_writesl(i2c_dev, buf, i2c_dev->hw->regs->tx_fifo, words_to_transfer);
buf += words_to_transfer * BYTES_PER_FIFO_WORD;
}
@ -1014,7 +1158,7 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
i2c_dev->msg_buf_remaining = 0;
i2c_dev->msg_buf = NULL;
i2c_writel(i2c_dev, val, I2C_TX_FIFO);
i2c_writel(i2c_dev, val, i2c_dev->hw->regs->tx_fifo);
}
return 0;
@ -1026,13 +1170,13 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
struct tegra_i2c_dev *i2c_dev = dev_id;
u32 status;
status = i2c_readl(i2c_dev, I2C_INT_STATUS);
status = i2c_readl(i2c_dev, i2c_dev->hw->regs->int_status);
if (status == 0) {
dev_warn(i2c_dev->dev, "IRQ status 0 %08x %08x %08x\n",
i2c_readl(i2c_dev, I2C_PACKET_TRANSFER_STATUS),
i2c_readl(i2c_dev, I2C_STATUS),
i2c_readl(i2c_dev, I2C_CNFG));
i2c_readl(i2c_dev, i2c_dev->hw->regs->packet_transfer_status),
i2c_readl(i2c_dev, i2c_dev->hw->regs->status),
i2c_readl(i2c_dev, i2c_dev->hw->regs->cnfg));
i2c_dev->msg_err |= I2C_ERR_UNKNOWN_INTERRUPT;
goto err;
}
@ -1075,7 +1219,7 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
}
}
i2c_writel(i2c_dev, status, I2C_INT_STATUS);
i2c_writel(i2c_dev, status, i2c_dev->hw->regs->int_status);
if (IS_DVC(i2c_dev))
dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
@ -1113,7 +1257,7 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
if (i2c_dev->hw->supports_bus_clear)
tegra_i2c_mask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE);
i2c_writel(i2c_dev, status, I2C_INT_STATUS);
i2c_writel(i2c_dev, status, i2c_dev->hw->regs->int_status);
if (IS_DVC(i2c_dev))
dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
@ -1136,9 +1280,9 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
int err;
if (i2c_dev->hw->has_mst_fifo)
reg = I2C_MST_FIFO_CONTROL;
reg = i2c_dev->hw->regs->mst_fifo_control;
else
reg = I2C_FIFO_CONTROL;
reg = i2c_dev->hw->regs->fifo_control;
if (i2c_dev->dma_mode) {
if (len & 0xF)
@ -1149,7 +1293,7 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
dma_burst = 8;
if (i2c_dev->msg_read) {
reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_RX_FIFO);
reg_offset = i2c_dev->hw->regs->rx_fifo;
slv_config.src_addr = i2c_dev->base_phys + reg_offset;
slv_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@ -1160,7 +1304,7 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
else
val = I2C_FIFO_CONTROL_RX_TRIG(dma_burst);
} else {
reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_TX_FIFO);
reg_offset = i2c_dev->hw->regs->tx_fifo;
slv_config.dst_addr = i2c_dev->base_phys + reg_offset;
slv_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@ -1203,7 +1347,7 @@ static unsigned long tegra_i2c_poll_completion(struct tegra_i2c_dev *i2c_dev,
ktime_t ktimeout = ktime_add_ms(ktime, timeout_ms);
do {
u32 status = i2c_readl(i2c_dev, I2C_INT_STATUS);
u32 status = i2c_readl(i2c_dev, i2c_dev->hw->regs->int_status);
if (status)
tegra_i2c_isr(i2c_dev->irq, i2c_dev);
@ -1262,14 +1406,14 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap)
val = FIELD_PREP(I2C_BC_SCLK_THRESHOLD, 9) | I2C_BC_STOP_COND |
I2C_BC_TERMINATE;
i2c_writel(i2c_dev, val, I2C_BUS_CLEAR_CNFG);
i2c_writel(i2c_dev, val, i2c_dev->hw->regs->bus_clear_cnfg);
err = tegra_i2c_wait_for_config_load(i2c_dev);
if (err)
return err;
val |= I2C_BC_ENABLE;
i2c_writel(i2c_dev, val, I2C_BUS_CLEAR_CNFG);
i2c_writel(i2c_dev, val, i2c_dev->hw->regs->bus_clear_cnfg);
tegra_i2c_unmask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE);
time_left = tegra_i2c_wait_completion(i2c_dev, &i2c_dev->msg_complete, 50);
@ -1280,7 +1424,7 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap)
return -ETIMEDOUT;
}
val = i2c_readl(i2c_dev, I2C_BUS_CLEAR_STATUS);
val = i2c_readl(i2c_dev, i2c_dev->hw->regs->bus_clear_status);
if (!(val & I2C_BC_STATUS)) {
dev_err(i2c_dev->dev, "un-recovered arbitration lost\n");
return -EIO;
@ -1305,14 +1449,14 @@ static void tegra_i2c_push_packet_header(struct tegra_i2c_dev *i2c_dev,
if (i2c_dev->dma_mode && !i2c_dev->msg_read)
*dma_buf++ = packet_header;
else
i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
i2c_writel(i2c_dev, packet_header, i2c_dev->hw->regs->tx_fifo);
packet_header = i2c_dev->msg_len - 1;
if (i2c_dev->dma_mode && !i2c_dev->msg_read)
*dma_buf++ = packet_header;
else
i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
i2c_writel(i2c_dev, packet_header, i2c_dev->hw->regs->tx_fifo);
packet_header = I2C_HEADER_IE_ENABLE;
@ -1340,7 +1484,7 @@ static void tegra_i2c_push_packet_header(struct tegra_i2c_dev *i2c_dev,
if (i2c_dev->dma_mode && !i2c_dev->msg_read)
*dma_buf++ = packet_header;
else
i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
i2c_writel(i2c_dev, packet_header, i2c_dev->hw->regs->tx_fifo);
}
static int tegra_i2c_error_recover(struct tegra_i2c_dev *i2c_dev,
@ -1461,7 +1605,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
tegra_i2c_unmask_irq(i2c_dev, int_mask);
dev_dbg(i2c_dev->dev, "unmasked IRQ: %02x\n",
i2c_readl(i2c_dev, I2C_INT_MASK));
i2c_readl(i2c_dev, i2c_dev->hw->regs->int_mask));
if (i2c_dev->dma_mode) {
time_left = tegra_i2c_wait_completion(i2c_dev,
@ -1635,8 +1779,44 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
.has_interface_timing_reg = false,
.enable_hs_mode_support = false,
.has_mutex = false,
.variant = TEGRA_I2C_VARIANT_DEFAULT,
.regs = &tegra20_i2c_regs,
};
#if IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC)
static const struct tegra_i2c_hw_feature tegra20_dvc_i2c_hw = {
.has_continue_xfer_support = false,
.has_per_pkt_xfer_complete_irq = false,
.clk_divisor_hs_mode = 3,
.clk_divisor_std_mode = 0,
.clk_divisor_fast_mode = 0,
.clk_divisor_fast_plus_mode = 0,
.has_config_load_reg = false,
.has_multi_master_mode = false,
.has_slcg_override_reg = false,
.has_mst_fifo = false,
.has_mst_reset = false,
.quirks = &tegra_i2c_quirks,
.supports_bus_clear = false,
.has_apb_dma = true,
.tlow_std_mode = 0x4,
.thigh_std_mode = 0x2,
.tlow_fast_mode = 0x4,
.thigh_fast_mode = 0x2,
.tlow_fastplus_mode = 0x4,
.thigh_fastplus_mode = 0x2,
.setup_hold_time_std_mode = 0x0,
.setup_hold_time_fast_mode = 0x0,
.setup_hold_time_fastplus_mode = 0x0,
.setup_hold_time_hs_mode = 0x0,
.has_interface_timing_reg = false,
.enable_hs_mode_support = false,
.has_mutex = false,
.variant = TEGRA_I2C_VARIANT_DVC,
.regs = &tegra20_dvc_i2c_regs,
};
#endif
static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
.has_continue_xfer_support = true,
.has_per_pkt_xfer_complete_irq = false,
@ -1665,6 +1845,8 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
.has_interface_timing_reg = false,
.enable_hs_mode_support = false,
.has_mutex = false,
.variant = TEGRA_I2C_VARIANT_DEFAULT,
.regs = &tegra20_i2c_regs,
};
static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
@ -1695,6 +1877,8 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
.has_interface_timing_reg = false,
.enable_hs_mode_support = false,
.has_mutex = false,
.variant = TEGRA_I2C_VARIANT_DEFAULT,
.regs = &tegra20_i2c_regs,
};
static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
@ -1725,6 +1909,8 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
.has_interface_timing_reg = true,
.enable_hs_mode_support = false,
.has_mutex = false,
.variant = TEGRA_I2C_VARIANT_DEFAULT,
.regs = &tegra20_i2c_regs,
};
static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
@ -1755,8 +1941,44 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
.has_interface_timing_reg = true,
.enable_hs_mode_support = false,
.has_mutex = false,
.variant = TEGRA_I2C_VARIANT_DEFAULT,
.regs = &tegra20_i2c_regs,
};
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
static const struct tegra_i2c_hw_feature tegra210_vi_i2c_hw = {
.has_continue_xfer_support = true,
.has_per_pkt_xfer_complete_irq = true,
.clk_divisor_hs_mode = 1,
.clk_divisor_std_mode = 0x19,
.clk_divisor_fast_mode = 0x19,
.clk_divisor_fast_plus_mode = 0x10,
.has_config_load_reg = true,
.has_multi_master_mode = false,
.has_slcg_override_reg = true,
.has_mst_fifo = false,
.has_mst_reset = false,
.quirks = &tegra_i2c_quirks,
.supports_bus_clear = true,
.has_apb_dma = true,
.tlow_std_mode = 0x4,
.thigh_std_mode = 0x2,
.tlow_fast_mode = 0x4,
.thigh_fast_mode = 0x2,
.tlow_fastplus_mode = 0x4,
.thigh_fastplus_mode = 0x2,
.setup_hold_time_std_mode = 0,
.setup_hold_time_fast_mode = 0,
.setup_hold_time_fastplus_mode = 0,
.setup_hold_time_hs_mode = 0,
.has_interface_timing_reg = true,
.enable_hs_mode_support = false,
.has_mutex = false,
.variant = TEGRA_I2C_VARIANT_VI,
.regs = &tegra210_vi_i2c_regs,
};
#endif
static const struct tegra_i2c_hw_feature tegra186_i2c_hw = {
.has_continue_xfer_support = true,
.has_per_pkt_xfer_complete_irq = true,
@ -1785,6 +2007,8 @@ static const struct tegra_i2c_hw_feature tegra186_i2c_hw = {
.has_interface_timing_reg = true,
.enable_hs_mode_support = false,
.has_mutex = false,
.variant = TEGRA_I2C_VARIANT_DEFAULT,
.regs = &tegra20_i2c_regs,
};
static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
@ -1817,6 +2041,8 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
.has_interface_timing_reg = true,
.enable_hs_mode_support = true,
.has_mutex = false,
.variant = TEGRA_I2C_VARIANT_DEFAULT,
.regs = &tegra20_i2c_regs,
};
static const struct tegra_i2c_hw_feature tegra256_i2c_hw = {
@ -1849,6 +2075,8 @@ static const struct tegra_i2c_hw_feature tegra256_i2c_hw = {
.has_interface_timing_reg = true,
.enable_hs_mode_support = true,
.has_mutex = true,
.variant = TEGRA_I2C_VARIANT_DEFAULT,
.regs = &tegra264_i2c_regs,
};
static const struct tegra_i2c_hw_feature tegra264_i2c_hw = {
@ -1881,6 +2109,42 @@ static const struct tegra_i2c_hw_feature tegra264_i2c_hw = {
.has_interface_timing_reg = true,
.enable_hs_mode_support = true,
.has_mutex = true,
.variant = TEGRA_I2C_VARIANT_DEFAULT,
.regs = &tegra264_i2c_regs,
};
static const struct tegra_i2c_hw_feature tegra410_i2c_hw = {
.has_continue_xfer_support = true,
.has_per_pkt_xfer_complete_irq = true,
.clk_divisor_hs_mode = 1,
.clk_divisor_std_mode = 0x3f,
.clk_divisor_fast_mode = 0x2c,
.clk_divisor_fast_plus_mode = 0x11,
.has_config_load_reg = true,
.has_multi_master_mode = true,
.has_slcg_override_reg = true,
.has_mst_fifo = true,
.has_mst_reset = true,
.quirks = &tegra194_i2c_quirks,
.supports_bus_clear = true,
.has_apb_dma = false,
.tlow_std_mode = 0x8,
.thigh_std_mode = 0x7,
.tlow_fast_mode = 0x2,
.thigh_fast_mode = 0x2,
.tlow_fastplus_mode = 0x2,
.thigh_fastplus_mode = 0x2,
.tlow_hs_mode = 0x8,
.thigh_hs_mode = 0x6,
.setup_hold_time_std_mode = 0x08080808,
.setup_hold_time_fast_mode = 0x02020202,
.setup_hold_time_fastplus_mode = 0x02020202,
.setup_hold_time_hs_mode = 0x0b0b0b,
.has_interface_timing_reg = true,
.enable_hs_mode_support = true,
.has_mutex = true,
.variant = TEGRA_I2C_VARIANT_DEFAULT,
.regs = &tegra410_i2c_regs,
};
static const struct of_device_id tegra_i2c_of_match[] = {
@ -1889,7 +2153,7 @@ static const struct of_device_id tegra_i2c_of_match[] = {
{ .compatible = "nvidia,tegra194-i2c", .data = &tegra194_i2c_hw, },
{ .compatible = "nvidia,tegra186-i2c", .data = &tegra186_i2c_hw, },
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
{ .compatible = "nvidia,tegra210-i2c-vi", .data = &tegra210_i2c_hw, },
{ .compatible = "nvidia,tegra210-i2c-vi", .data = &tegra210_vi_i2c_hw, },
#endif
{ .compatible = "nvidia,tegra210-i2c", .data = &tegra210_i2c_hw, },
{ .compatible = "nvidia,tegra124-i2c", .data = &tegra124_i2c_hw, },
@ -1897,7 +2161,7 @@ static const struct of_device_id tegra_i2c_of_match[] = {
{ .compatible = "nvidia,tegra30-i2c", .data = &tegra30_i2c_hw, },
{ .compatible = "nvidia,tegra20-i2c", .data = &tegra20_i2c_hw, },
#if IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC)
{ .compatible = "nvidia,tegra20-i2c-dvc", .data = &tegra20_i2c_hw, },
{ .compatible = "nvidia,tegra20-i2c-dvc", .data = &tegra20_dvc_i2c_hw, },
#endif
{},
};
@ -1905,21 +2169,12 @@ MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev)
{
struct device_node *np = i2c_dev->dev->of_node;
bool multi_mode;
i2c_parse_fw_timings(i2c_dev->dev, &i2c_dev->timings, true);
multi_mode = device_property_read_bool(i2c_dev->dev, "multi-master");
i2c_dev->multimaster_mode = multi_mode;
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) &&
of_device_is_compatible(np, "nvidia,tegra20-i2c-dvc"))
i2c_dev->is_dvc = true;
if (IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) &&
of_device_is_compatible(np, "nvidia,tegra210-i2c-vi"))
i2c_dev->is_vi = true;
}
static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev)
@ -2205,6 +2460,7 @@ static const struct acpi_device_id tegra_i2c_acpi_match[] = {
{.id = "NVDA0101", .driver_data = (kernel_ulong_t)&tegra210_i2c_hw},
{.id = "NVDA0201", .driver_data = (kernel_ulong_t)&tegra186_i2c_hw},
{.id = "NVDA0301", .driver_data = (kernel_ulong_t)&tegra194_i2c_hw},
{.id = "NVDA2017", .driver_data = (kernel_ulong_t)&tegra410_i2c_hw},
{ }
};
MODULE_DEVICE_TABLE(acpi, tegra_i2c_acpi_match);

View File

@ -213,12 +213,6 @@ static int usb_write(struct i2c_adapter *adapter, int cmd,
return ret;
}
static void i2c_tiny_usb_free(struct i2c_tiny_usb *dev)
{
usb_put_dev(dev->usb_dev);
kfree(dev);
}
static int i2c_tiny_usb_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
@ -237,7 +231,7 @@ static int i2c_tiny_usb_probe(struct usb_interface *interface,
if (!dev)
goto error;
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 */
@ -277,8 +271,7 @@ static int i2c_tiny_usb_probe(struct usb_interface *interface,
return 0;
error:
if (dev)
i2c_tiny_usb_free(dev);
kfree(dev);
return retval;
}
@ -289,7 +282,7 @@ static void i2c_tiny_usb_disconnect(struct usb_interface *interface)
i2c_del_adapter(&dev->adapter);
usb_set_intfdata(interface, NULL);
i2c_tiny_usb_free(dev);
kfree(dev);
dev_dbg(&interface->dev, "disconnected\n");
}

View File

@ -29,6 +29,7 @@ static const struct acpi_device_id usbio_i2c_acpi_hids[] = {
{ "INTC10B6" }, /* LNL */
{ "INTC10D2" }, /* MTL-CVF */
{ "INTC10E3" }, /* PTL */
{ "INTC1118" }, /* NVL */
{ }
};

View File

@ -27,7 +27,6 @@
#include <linux/platform_data/i2c-xiic.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/clk.h>
#include <linux/pm_runtime.h>
#include <linux/iopoll.h>
@ -1408,7 +1407,6 @@ static const struct i2c_adapter xiic_adapter = {
.algo = &xiic_algorithm,
};
#if defined(CONFIG_OF)
static const struct xiic_version_data xiic_2_00 = {
.quirks = DYNAMIC_MODE_READ_BROKEN_BIT,
};
@ -1419,28 +1417,26 @@ static const struct of_device_id xiic_of_match[] = {
{},
};
MODULE_DEVICE_TABLE(of, xiic_of_match);
#endif
static int xiic_i2c_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct fwnode_handle *fwnode = dev_fwnode(dev);
struct xiic_i2c *i2c;
struct xiic_i2c_platform_data *pdata;
const struct of_device_id *match;
const struct xiic_version_data *data;
struct resource *res;
int ret, irq;
u8 i;
u32 sr;
i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL);
if (!i2c)
return -ENOMEM;
match = of_match_node(xiic_of_match, pdev->dev.of_node);
if (match && match->data) {
const struct xiic_version_data *data = match->data;
data = device_get_match_data(dev);
if (data)
i2c->quirks = data->quirks;
}
i2c->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(i2c->base))
@ -1450,50 +1446,52 @@ static int xiic_i2c_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
pdata = dev_get_platdata(&pdev->dev);
pdata = dev_get_platdata(dev);
/* hook up driver to tree */
platform_set_drvdata(pdev, i2c);
i2c->adap = xiic_adapter;
i2c->adap.nr = pdev->id;
i2c_set_adapdata(&i2c->adap, i2c);
i2c->adap.dev.parent = &pdev->dev;
i2c->adap.dev.of_node = pdev->dev.of_node;
device_set_node(&i2c->adap.dev, fwnode);
snprintf(i2c->adap.name, sizeof(i2c->adap.name),
DRIVER_NAME " %s", pdev->name);
mutex_init(&i2c->lock);
ret = devm_mutex_init(dev, &i2c->lock);
if (ret)
return ret;
spin_lock_init(&i2c->atomic_lock);
i2c->clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(i2c->clk))
return dev_err_probe(&pdev->dev, PTR_ERR(i2c->clk),
"failed to enable input clock.\n");
if (is_of_node(fwnode)) {
i2c->clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(i2c->clk))
return dev_err_probe(dev, PTR_ERR(i2c->clk),
"failed to enable input clock.\n");
}
i2c->dev = &pdev->dev;
pm_runtime_set_autosuspend_delay(i2c->dev, XIIC_PM_TIMEOUT);
pm_runtime_use_autosuspend(i2c->dev);
pm_runtime_set_active(i2c->dev);
pm_runtime_enable(i2c->dev);
i2c->dev = dev;
pm_runtime_set_autosuspend_delay(dev, XIIC_PM_TIMEOUT);
pm_runtime_use_autosuspend(dev);
ret = devm_pm_runtime_set_active_enabled(dev);
if (ret)
return ret;
/* SCL frequency configuration */
i2c->input_clk = clk_get_rate(i2c->clk);
ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
&i2c->i2c_clk);
ret = device_property_read_u32(dev, "clock-frequency", &i2c->i2c_clk);
/* If clock-frequency not specified in DT, do not configure in SW */
if (ret || i2c->i2c_clk > I2C_MAX_FAST_MODE_PLUS_FREQ)
i2c->i2c_clk = 0;
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
xiic_process, IRQF_ONESHOT,
pdev->name, i2c);
ret = devm_request_threaded_irq(dev, irq, NULL, xiic_process,
IRQF_ONESHOT, pdev->name, i2c);
if (ret)
return ret;
if (ret < 0) {
dev_err_probe(&pdev->dev, ret, "Cannot claim IRQ\n");
goto err_pm_disable;
}
i2c->singlemaster =
of_property_read_bool(pdev->dev.of_node, "single-master");
i2c->singlemaster = device_property_read_bool(dev, "single-master");
/*
* Detect endianness
@ -1508,16 +1506,14 @@ static int xiic_i2c_probe(struct platform_device *pdev)
i2c->endianness = BIG;
ret = xiic_reinit(i2c);
if (ret < 0) {
dev_err_probe(&pdev->dev, ret, "Cannot xiic_reinit\n");
goto err_pm_disable;
}
if (ret)
return dev_err_probe(dev, ret, "Cannot xiic_reinit\n");
/* add i2c adapter to i2c tree */
ret = i2c_add_adapter(&i2c->adap);
ret = i2c_add_numbered_adapter(&i2c->adap);
if (ret) {
xiic_deinit(i2c);
goto err_pm_disable;
return ret;
}
if (pdata) {
@ -1526,38 +1522,29 @@ static int xiic_i2c_probe(struct platform_device *pdev)
i2c_new_client_device(&i2c->adap, pdata->devices + i);
}
dev_dbg(&pdev->dev, "mmio %08lx irq %d scl clock frequency %d\n",
(unsigned long)res->start, irq, i2c->i2c_clk);
dev_dbg(dev, "mmio %pR irq %d scl clock frequency %d\n",
res, irq, i2c->i2c_clk);
return 0;
err_pm_disable:
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
return ret;
}
static void xiic_i2c_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct xiic_i2c *i2c = platform_get_drvdata(pdev);
int ret;
/* remove adapter & data */
i2c_del_adapter(&i2c->adap);
ret = pm_runtime_get_sync(i2c->dev);
ret = pm_runtime_get_sync(dev);
if (ret < 0)
dev_warn(&pdev->dev, "Failed to activate device for removal (%pe)\n",
dev_warn(dev, "Failed to activate device for removal (%pe)\n",
ERR_PTR(ret));
else
xiic_deinit(i2c);
pm_runtime_put_sync(i2c->dev);
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_put_sync(dev);
}
static const struct dev_pm_ops xiic_dev_pm_ops = {

View File

@ -49,8 +49,8 @@ struct i2c_atr_alias_pair {
* @shared: Indicates if this alias pool is shared by multiple channels
*
* @lock: Lock protecting @aliases and @use_mask
* @aliases: Array of aliases, must hold exactly @size elements
* @use_mask: Mask of used aliases
* @aliases: Array of aliases, must hold exactly @size elements
*/
struct i2c_atr_alias_pool {
size_t size;
@ -58,8 +58,8 @@ struct i2c_atr_alias_pool {
/* Protects aliases and use_mask */
spinlock_t lock;
u16 *aliases;
unsigned long *use_mask;
u16 aliases[] __counted_by(size);
};
/**
@ -137,22 +137,16 @@ static struct i2c_atr_alias_pool *i2c_atr_alloc_alias_pool(size_t num_aliases, b
struct i2c_atr_alias_pool *alias_pool;
int ret;
alias_pool = kzalloc_obj(*alias_pool);
alias_pool = kzalloc_flex(*alias_pool, aliases, num_aliases);
if (!alias_pool)
return ERR_PTR(-ENOMEM);
alias_pool->size = num_aliases;
alias_pool->aliases = kcalloc(num_aliases, sizeof(*alias_pool->aliases), GFP_KERNEL);
if (!alias_pool->aliases) {
ret = -ENOMEM;
goto err_free_alias_pool;
}
alias_pool->use_mask = bitmap_zalloc(num_aliases, GFP_KERNEL);
if (!alias_pool->use_mask) {
ret = -ENOMEM;
goto err_free_aliases;
goto err_free_alias_pool;
}
alias_pool->shared = shared;
@ -161,8 +155,6 @@ static struct i2c_atr_alias_pool *i2c_atr_alloc_alias_pool(size_t num_aliases, b
return alias_pool;
err_free_aliases:
kfree(alias_pool->aliases);
err_free_alias_pool:
kfree(alias_pool);
return ERR_PTR(ret);
@ -171,7 +163,6 @@ static struct i2c_atr_alias_pool *i2c_atr_alloc_alias_pool(size_t num_aliases, b
static void i2c_atr_free_alias_pool(struct i2c_atr_alias_pool *alias_pool)
{
bitmap_free(alias_pool->use_mask);
kfree(alias_pool->aliases);
kfree(alias_pool);
}