mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 00:53:34 +02:00
I3C for 6.17
New driver: - Renesas I3C controller Subsystem: - use adapter timeout value for I2C transfers - don't fail if GETHDRCAP is unsupported - replace ENOTSUPP with SUSV4-compliant EOPNOTSUPP Drivers: - svc: Fix npcm845 FIFO_EMPTY quirk -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEBqsFVZXh8s/0O5JiY6TcMGxwOjIFAmiOnMkACgkQY6TcMGxw OjLNIBAAi5Snj3ZjHxO+MdLE27vsJq+gW7Pk0jxrG0bkPNOrbRtIjmuZNT+hPxZ+ bqN3Vi/l5+iy8ZuZETYOabW7LG5nDKUF4M4RmewwtkkfXchRfsTQeCnVL8wDXdCp GYYBT0mPXU4+9F0vXVlezjTPuT9V/gry0SnsjK+NfegjmYZ/bFY+RExsYZQpeHut W6TPq5M+ytLnHqsx/bxfez4voxkir6vR+ydPO6reBGaxW8KUQmOki1mNTW4J4crs WZg+egFmnWFZjU8BUzjCkvgnvLqJws5oKg+4AlY5q4zPHMSuDAgRtjHprISEGcQc 6LQZwZBx2YocgiuQo09jjX6q4FbRjaAbdZLAvtPOFUqX0SpeFZA1HJ3tmPEdmJ6S JwGVNjh2kda/SHqY0LlAojEApX9Z8z0C0dexR51YxWvnX8duwww0Rhhi/yvwWrzP rVIDgRXv9UAKk1sZG7/mRbpCJHtEwKlBOnU3DxQKjFnKVVazdnP6zOZjptxRkXBX tVxTB/HASjlA8EoncBh+vhq7Xm81+Py7VR02yY0dhdeLdgfKTVfdL8tVPf8cQ/bO 6bo4vn1BgO4jyb4GW0ikB7tVVo4azYQcCNHvDB7zJ9Magv17FVW1bqnRVEvaprpx 0Ty10paXD58vPgJNe03hiU91e2L05wpoggYuX3MQqe7UpkJKVkI= =cX/f -----END PGP SIGNATURE----- Merge tag 'i3c/for-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux Pull i3c updates from Alexandre Belloni: "New driver: - Renesas I3C controller Subsystem: - use adapter timeout value for I2C transfers - don't fail if GETHDRCAP is unsupported - replace ENOTSUPP with SUSV4-compliant EOPNOTSUPP Drivers: - svc: Fix npcm845 FIFO_EMPTY quirk" * tag 'i3c/for-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux: (25 commits) i3c: add missing include to internal header i3c: dw: Remove redundant pm_runtime_mark_last_busy() calls i3c: master: svc: Remove redundant pm_runtime_mark_last_busy() calls i3c: master: svc: Fix npcm845 FIFO_EMPTY quirk i3c: master: Add basic driver for the Renesas I3C controller dt-bindings: i3c: Add Renesas I3C controller i3c: Add more parameters for controllers to the header i3c: Standardize defines for specification parameters i3c: fix module_i3c_i2c_driver() with I3C=n i3c: master: cdns: Simplify handling clocks in probe() i3c: Fix i3c_device_do_priv_xfers() kernel-doc indentation i3c: master: dw: Use i3c_writel_fifo() and i3c_readl_fifo() i3c: master: cdns: Use i3c_writel_fifo() and i3c_readl_fifo() i3c: master: Add inline i3c_readl_fifo() and i3c_writel_fifo() i3c: prefix hexadecimal entries in sysfs i3c: master: cdns: replace ENOTSUPP with SUSV4-compliant EOPNOTSUPP i3c: dw: replace ENOTSUPP with SUSV4-compliant EOPNOTSUPP i3c: master: replace ENOTSUPP with SUSV4-compliant EOPNOTSUPP i3c: don't fail if GETHDRCAP is unsupported i3c: add patchwork entry to MAINTAINERS ...
This commit is contained in:
commit
546b0ad6a8
179
Documentation/devicetree/bindings/i3c/renesas,i3c.yaml
Normal file
179
Documentation/devicetree/bindings/i3c/renesas,i3c.yaml
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/i3c/renesas,i3c.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas RZ/G3S and RZ/G3E I3C Bus Interface
|
||||
|
||||
maintainers:
|
||||
- Wolfram Sang <wsa+renesas@sang-engineering.com>
|
||||
- Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- renesas,r9a08g045-i3c # RZ/G3S
|
||||
- renesas,r9a09g047-i3c # RZ/G3E
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: Non-recoverable internal error interrupt
|
||||
- description: Normal transfer error interrupt
|
||||
- description: Normal transfer abort interrupt
|
||||
- description: Normal response status buffer full interrupt
|
||||
- description: Normal command buffer empty interrupt
|
||||
- description: Normal IBI status buffer full interrupt
|
||||
- description: Normal Rx data buffer full interrupt
|
||||
- description: Normal Tx data buffer empty interrupt
|
||||
- description: Normal receive status buffer full interrupt
|
||||
- description: START condition detection interrupt
|
||||
- description: STOP condition detection interrupt
|
||||
- description: Transmit end interrupt
|
||||
- description: NACK detection interrupt
|
||||
- description: Arbitration lost interrupt
|
||||
- description: Timeout detection interrupt
|
||||
- description: Wake-up condition detection interrupt
|
||||
- description: HDR Exit Pattern detection interrupt
|
||||
minItems: 16
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: ierr
|
||||
- const: terr
|
||||
- const: abort
|
||||
- const: resp
|
||||
- const: cmd
|
||||
- const: ibi
|
||||
- const: rx
|
||||
- const: tx
|
||||
- const: rcv
|
||||
- const: st
|
||||
- const: sp
|
||||
- const: tend
|
||||
- const: nack
|
||||
- const: al
|
||||
- const: tmo
|
||||
- const: wu
|
||||
- const: exit
|
||||
minItems: 16
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: APB bus clock
|
||||
- description: transfer clock
|
||||
- description: SFRs clock
|
||||
minItems: 2
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: pclk
|
||||
- const: tclk
|
||||
- const: pclkrw
|
||||
minItems: 2
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
items:
|
||||
- description: Reset signal
|
||||
- description: APB interface reset signal/SCAN reset signal
|
||||
|
||||
reset-names:
|
||||
items:
|
||||
- const: presetn
|
||||
- const: tresetn
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
- clock-names
|
||||
- clocks
|
||||
- power-domains
|
||||
- resets
|
||||
- reset-names
|
||||
|
||||
allOf:
|
||||
- $ref: i3c.yaml#
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,r9a08g045-i3c
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 2
|
||||
clock-names:
|
||||
maxItems: 2
|
||||
interrupts:
|
||||
minItems: 17
|
||||
interrupt-names:
|
||||
minItems: 17
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,r9a09g047-i3c
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 3
|
||||
clock-names:
|
||||
minItems: 3
|
||||
interrupts:
|
||||
maxItems: 16
|
||||
interrupt-names:
|
||||
maxItems: 16
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/r9a08g045-cpg.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
i3c@1005b000 {
|
||||
compatible = "renesas,r9a08g045-i3c";
|
||||
reg = <0x1005b000 0x1000>;
|
||||
clocks = <&cpg CPG_MOD R9A08G045_I3C_PCLK>,
|
||||
<&cpg CPG_MOD R9A08G045_I3C_TCLK>;
|
||||
clock-names = "pclk", "tclk";
|
||||
interrupts = <GIC_SPI 289 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 293 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 294 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 295 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 296 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 297 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 298 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 299 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 304 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 305 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 306 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "ierr", "terr", "abort", "resp",
|
||||
"cmd", "ibi", "rx", "tx", "rcv",
|
||||
"st", "sp", "tend", "nack",
|
||||
"al", "tmo", "wu", "exit";
|
||||
resets = <&cpg R9A08G045_I3C_PRESETN>,
|
||||
<&cpg R9A08G045_I3C_TRESETN>;
|
||||
reset-names = "presetn", "tresetn";
|
||||
power-domains = <&cpg>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
...
|
||||
|
|
@ -11612,6 +11612,13 @@ S: Maintained
|
|||
F: Documentation/devicetree/bindings/i3c/cdns,i3c-master.yaml
|
||||
F: drivers/i3c/master/i3c-master-cdns.c
|
||||
|
||||
I3C DRIVER FOR RENESAS
|
||||
M: Wolfram Sang <wsa+renesas@sang-engineering.com>
|
||||
M: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/i3c/renesas,i3c.yaml
|
||||
F: drivers/i3c/master/renesas-i3c.c
|
||||
|
||||
I3C DRIVER FOR SYNOPSYS DESIGNWARE
|
||||
S: Orphan
|
||||
F: Documentation/devicetree/bindings/i3c/snps,dw-i3c-master.yaml
|
||||
|
|
@ -11622,6 +11629,7 @@ M: Alexandre Belloni <alexandre.belloni@bootlin.com>
|
|||
R: Frank Li <Frank.Li@nxp.com>
|
||||
L: linux-i3c@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
Q: https://patchwork.kernel.org/project/linux-i3c/list/
|
||||
C: irc://chat.freenode.net/linux-i3c
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux.git
|
||||
F: Documentation/ABI/testing/sysfs-bus-i3c
|
||||
|
|
|
|||
|
|
@ -26,11 +26,12 @@
|
|||
*
|
||||
* This function can sleep and thus cannot be called in atomic context.
|
||||
*
|
||||
* Return: 0 in case of success, a negative error core otherwise.
|
||||
* -EAGAIN: controller lost address arbitration. Target
|
||||
* (IBI, HJ or controller role request) win the bus. Client
|
||||
* driver needs to resend the 'xfers' some time later.
|
||||
* See I3C spec ver 1.1.1 09-Jun-2021. Section: 5.1.2.2.3.
|
||||
* Return:
|
||||
* * 0 in case of success, a negative error core otherwise.
|
||||
* * -EAGAIN: controller lost address arbitration. Target (IBI, HJ or
|
||||
* controller role request) win the bus. Client driver needs to resend the
|
||||
* 'xfers' some time later. See I3C spec ver 1.1.1 09-Jun-2021. Section:
|
||||
* 5.1.2.2.3.
|
||||
*/
|
||||
int i3c_device_do_priv_xfers(struct i3c_device *dev,
|
||||
struct i3c_priv_xfer *xfers,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#define I3C_INTERNALS_H
|
||||
|
||||
#include <linux/i3c/master.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
void i3c_bus_normaluse_lock(struct i3c_bus *bus);
|
||||
void i3c_bus_normaluse_unlock(struct i3c_bus *bus);
|
||||
|
|
@ -22,4 +23,41 @@ int i3c_dev_enable_ibi_locked(struct i3c_dev_desc *dev);
|
|||
int i3c_dev_request_ibi_locked(struct i3c_dev_desc *dev,
|
||||
const struct i3c_ibi_setup *req);
|
||||
void i3c_dev_free_ibi_locked(struct i3c_dev_desc *dev);
|
||||
|
||||
/**
|
||||
* i3c_writel_fifo - Write data buffer to 32bit FIFO
|
||||
* @addr: FIFO Address to write to
|
||||
* @buf: Pointer to the data bytes to write
|
||||
* @nbytes: Number of bytes to write
|
||||
*/
|
||||
static inline void i3c_writel_fifo(void __iomem *addr, const void *buf,
|
||||
int nbytes)
|
||||
{
|
||||
writesl(addr, buf, nbytes / 4);
|
||||
if (nbytes & 3) {
|
||||
u32 tmp = 0;
|
||||
|
||||
memcpy(&tmp, buf + (nbytes & ~3), nbytes & 3);
|
||||
writel(tmp, addr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* i3c_readl_fifo - Read data buffer from 32bit FIFO
|
||||
* @addr: FIFO Address to read from
|
||||
* @buf: Pointer to the buffer to store read bytes
|
||||
* @nbytes: Number of bytes to read
|
||||
*/
|
||||
static inline void i3c_readl_fifo(const void __iomem *addr, void *buf,
|
||||
int nbytes)
|
||||
{
|
||||
readsl(addr, buf, nbytes / 4);
|
||||
if (nbytes & 3) {
|
||||
u32 tmp;
|
||||
|
||||
tmp = readl(addr);
|
||||
memcpy(buf + (nbytes & ~3), &tmp, nbytes & 3);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* I3C_INTERNAL_H */
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ static ssize_t bcr_show(struct device *dev,
|
|||
|
||||
i3c_bus_normaluse_lock(bus);
|
||||
desc = dev_to_i3cdesc(dev);
|
||||
ret = sprintf(buf, "%x\n", desc->info.bcr);
|
||||
ret = sprintf(buf, "0x%02x\n", desc->info.bcr);
|
||||
i3c_bus_normaluse_unlock(bus);
|
||||
|
||||
return ret;
|
||||
|
|
@ -158,7 +158,7 @@ static ssize_t dcr_show(struct device *dev,
|
|||
|
||||
i3c_bus_normaluse_lock(bus);
|
||||
desc = dev_to_i3cdesc(dev);
|
||||
ret = sprintf(buf, "%x\n", desc->info.dcr);
|
||||
ret = sprintf(buf, "0x%02x\n", desc->info.dcr);
|
||||
i3c_bus_normaluse_unlock(bus);
|
||||
|
||||
return ret;
|
||||
|
|
@ -727,12 +727,12 @@ static int i3c_bus_set_mode(struct i3c_bus *i3cbus, enum i3c_bus_mode mode,
|
|||
switch (i3cbus->mode) {
|
||||
case I3C_BUS_MODE_PURE:
|
||||
if (!i3cbus->scl_rate.i3c)
|
||||
i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE;
|
||||
i3cbus->scl_rate.i3c = I3C_BUS_I3C_SCL_TYP_RATE;
|
||||
break;
|
||||
case I3C_BUS_MODE_MIXED_FAST:
|
||||
case I3C_BUS_MODE_MIXED_LIMITED:
|
||||
if (!i3cbus->scl_rate.i3c)
|
||||
i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE;
|
||||
i3cbus->scl_rate.i3c = I3C_BUS_I3C_SCL_TYP_RATE;
|
||||
if (!i3cbus->scl_rate.i2c)
|
||||
i3cbus->scl_rate.i2c = max_i2c_scl_rate;
|
||||
break;
|
||||
|
|
@ -754,8 +754,8 @@ static int i3c_bus_set_mode(struct i3c_bus *i3cbus, enum i3c_bus_mode mode,
|
|||
* I3C/I2C frequency may have been overridden, check that user-provided
|
||||
* values are not exceeding max possible frequency.
|
||||
*/
|
||||
if (i3cbus->scl_rate.i3c > I3C_BUS_MAX_I3C_SCL_RATE ||
|
||||
i3cbus->scl_rate.i2c > I3C_BUS_I2C_FM_PLUS_SCL_RATE)
|
||||
if (i3cbus->scl_rate.i3c > I3C_BUS_I3C_SCL_MAX_RATE ||
|
||||
i3cbus->scl_rate.i2c > I3C_BUS_I2C_FM_PLUS_SCL_MAX_RATE)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
|
|
@ -837,14 +837,14 @@ static int i3c_master_send_ccc_cmd_locked(struct i3c_master_controller *master,
|
|||
return -EINVAL;
|
||||
|
||||
if (!master->ops->send_ccc_cmd)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if ((cmd->id & I3C_CCC_DIRECT) && (!cmd->dests || !cmd->ndests))
|
||||
return -EINVAL;
|
||||
|
||||
if (master->ops->supports_ccc_cmd &&
|
||||
!master->ops->supports_ccc_cmd(master, cmd))
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ret = master->ops->send_ccc_cmd(master, cmd);
|
||||
if (ret) {
|
||||
|
|
@ -1439,7 +1439,7 @@ static int i3c_master_retrieve_dev_info(struct i3c_dev_desc *dev)
|
|||
|
||||
if (dev->info.bcr & I3C_BCR_HDR_CAP) {
|
||||
ret = i3c_master_gethdrcap_locked(master, &dev->info);
|
||||
if (ret)
|
||||
if (ret && ret != -EOPNOTSUPP)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -2210,7 +2210,7 @@ of_i3c_master_add_i2c_boardinfo(struct i3c_master_controller *master,
|
|||
*/
|
||||
if (boardinfo->base.flags & I2C_CLIENT_TEN) {
|
||||
dev_err(dev, "I2C device with 10 bit address not supported.");
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* LVR is encoded in reg[2]. */
|
||||
|
|
@ -2340,13 +2340,13 @@ static int i3c_master_i2c_adapter_xfer(struct i2c_adapter *adap,
|
|||
return -EINVAL;
|
||||
|
||||
if (!master->ops->i2c_xfers)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Doing transfers to different devices is not supported. */
|
||||
addr = xfers[0].addr;
|
||||
for (i = 1; i < nxfers; i++) {
|
||||
if (addr != xfers[i].addr)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
i3c_bus_normaluse_lock(&master->bus);
|
||||
|
|
@ -2467,6 +2467,8 @@ static int i3c_i2c_notifier_call(struct notifier_block *nb, unsigned long action
|
|||
case BUS_NOTIFY_DEL_DEVICE:
|
||||
ret = i3c_master_i2c_detach(adap, client);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
i3c_bus_maintenance_unlock(&master->bus);
|
||||
|
||||
|
|
@ -2766,7 +2768,7 @@ static int i3c_master_check_ops(const struct i3c_master_controller_ops *ops)
|
|||
* controller)
|
||||
* @ops: the master controller operations
|
||||
* @secondary: true if you are registering a secondary master. Will return
|
||||
* -ENOTSUPP if set to true since secondary masters are not yet
|
||||
* -EOPNOTSUPP if set to true since secondary masters are not yet
|
||||
* supported
|
||||
*
|
||||
* This function takes care of everything for you:
|
||||
|
|
@ -2785,7 +2787,7 @@ int i3c_master_register(struct i3c_master_controller *master,
|
|||
const struct i3c_master_controller_ops *ops,
|
||||
bool secondary)
|
||||
{
|
||||
unsigned long i2c_scl_rate = I3C_BUS_I2C_FM_PLUS_SCL_RATE;
|
||||
unsigned long i2c_scl_rate = I3C_BUS_I2C_FM_PLUS_SCL_MAX_RATE;
|
||||
struct i3c_bus *i3cbus = i3c_master_get_bus(master);
|
||||
enum i3c_bus_mode mode = I3C_BUS_MODE_PURE;
|
||||
struct i2c_dev_boardinfo *i2cbi;
|
||||
|
|
@ -2793,7 +2795,7 @@ int i3c_master_register(struct i3c_master_controller *master,
|
|||
|
||||
/* We do not support secondary masters yet. */
|
||||
if (secondary)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ret = i3c_master_check_ops(ops);
|
||||
if (ret)
|
||||
|
|
@ -2844,7 +2846,7 @@ int i3c_master_register(struct i3c_master_controller *master,
|
|||
}
|
||||
|
||||
if (i2cbi->lvr & I3C_LVR_I2C_FM_MODE)
|
||||
i2c_scl_rate = I3C_BUS_I2C_FM_SCL_RATE;
|
||||
i2c_scl_rate = I3C_BUS_I2C_FM_SCL_MAX_RATE;
|
||||
}
|
||||
|
||||
ret = i3c_bus_set_mode(i3cbus, mode, i2c_scl_rate);
|
||||
|
|
@ -2954,7 +2956,7 @@ int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev,
|
|||
return -EINVAL;
|
||||
|
||||
if (!master->ops->priv_xfers)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return master->ops->priv_xfers(dev, xfers, nxfers);
|
||||
}
|
||||
|
|
@ -3004,7 +3006,7 @@ int i3c_dev_request_ibi_locked(struct i3c_dev_desc *dev,
|
|||
int ret;
|
||||
|
||||
if (!master->ops->request_ibi)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (dev->ibi)
|
||||
return -EBUSY;
|
||||
|
|
|
|||
|
|
@ -64,3 +64,13 @@ config MIPI_I3C_HCI_PCI
|
|||
|
||||
This driver can also be built as a module. If so, the module will be
|
||||
called mipi-i3c-hci-pci.
|
||||
|
||||
config RENESAS_I3C
|
||||
tristate "Renesas I3C controller driver"
|
||||
depends on HAS_IOMEM
|
||||
depends on ARCH_RENESAS || COMPILE_TEST
|
||||
help
|
||||
Support the Renesas I3C controller as found in some RZ variants.
|
||||
|
||||
This driver can also be built as a module. If so, the module will be
|
||||
called renesas-i3c.
|
||||
|
|
|
|||
|
|
@ -4,3 +4,4 @@ obj-$(CONFIG_DW_I3C_MASTER) += dw-i3c-master.o
|
|||
obj-$(CONFIG_AST2600_I3C_MASTER) += ast2600-i3c-master.o
|
||||
obj-$(CONFIG_SVC_I3C_MASTER) += svc-i3c-master.o
|
||||
obj-$(CONFIG_MIPI_I3C_HCI) += mipi-i3c-hci/
|
||||
obj-$(CONFIG_RENESAS_I3C) += renesas-i3c.o
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/reset.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "../internals.h"
|
||||
#include "dw-i3c-master.h"
|
||||
|
||||
#define DEVICE_CTRL 0x0
|
||||
|
|
@ -336,37 +337,19 @@ static int dw_i3c_master_get_free_pos(struct dw_i3c_master *master)
|
|||
static void dw_i3c_master_wr_tx_fifo(struct dw_i3c_master *master,
|
||||
const u8 *bytes, int nbytes)
|
||||
{
|
||||
writesl(master->regs + RX_TX_DATA_PORT, bytes, nbytes / 4);
|
||||
if (nbytes & 3) {
|
||||
u32 tmp = 0;
|
||||
|
||||
memcpy(&tmp, bytes + (nbytes & ~3), nbytes & 3);
|
||||
writesl(master->regs + RX_TX_DATA_PORT, &tmp, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void dw_i3c_master_read_fifo(struct dw_i3c_master *master,
|
||||
int reg, u8 *bytes, int nbytes)
|
||||
{
|
||||
readsl(master->regs + reg, bytes, nbytes / 4);
|
||||
if (nbytes & 3) {
|
||||
u32 tmp;
|
||||
|
||||
readsl(master->regs + reg, &tmp, 1);
|
||||
memcpy(bytes + (nbytes & ~3), &tmp, nbytes & 3);
|
||||
}
|
||||
i3c_writel_fifo(master->regs + RX_TX_DATA_PORT, bytes, nbytes);
|
||||
}
|
||||
|
||||
static void dw_i3c_master_read_rx_fifo(struct dw_i3c_master *master,
|
||||
u8 *bytes, int nbytes)
|
||||
{
|
||||
return dw_i3c_master_read_fifo(master, RX_TX_DATA_PORT, bytes, nbytes);
|
||||
i3c_readl_fifo(master->regs + RX_TX_DATA_PORT, bytes, nbytes);
|
||||
}
|
||||
|
||||
static void dw_i3c_master_read_ibi_fifo(struct dw_i3c_master *master,
|
||||
u8 *bytes, int nbytes)
|
||||
{
|
||||
return dw_i3c_master_read_fifo(master, IBI_QUEUE_STATUS, bytes, nbytes);
|
||||
i3c_readl_fifo(master->regs + IBI_QUEUE_STATUS, bytes, nbytes);
|
||||
}
|
||||
|
||||
static struct dw_i3c_xfer *
|
||||
|
|
@ -622,14 +605,14 @@ static int dw_i2c_clk_cfg(struct dw_i3c_master *master)
|
|||
core_period = DIV_ROUND_UP(1000000000, core_rate);
|
||||
|
||||
lcnt = DIV_ROUND_UP(I3C_BUS_I2C_FMP_TLOW_MIN_NS, core_period);
|
||||
hcnt = DIV_ROUND_UP(core_rate, I3C_BUS_I2C_FM_PLUS_SCL_RATE) - lcnt;
|
||||
hcnt = DIV_ROUND_UP(core_rate, I3C_BUS_I2C_FM_PLUS_SCL_MAX_RATE) - lcnt;
|
||||
scl_timing = SCL_I2C_FMP_TIMING_HCNT(hcnt) |
|
||||
SCL_I2C_FMP_TIMING_LCNT(lcnt);
|
||||
writel(scl_timing, master->regs + SCL_I2C_FMP_TIMING);
|
||||
master->i2c_fmp_timing = scl_timing;
|
||||
|
||||
lcnt = DIV_ROUND_UP(I3C_BUS_I2C_FM_TLOW_MIN_NS, core_period);
|
||||
hcnt = DIV_ROUND_UP(core_rate, I3C_BUS_I2C_FM_SCL_RATE) - lcnt;
|
||||
hcnt = DIV_ROUND_UP(core_rate, I3C_BUS_I2C_FM_SCL_MAX_RATE) - lcnt;
|
||||
scl_timing = SCL_I2C_FM_TIMING_HCNT(hcnt) |
|
||||
SCL_I2C_FM_TIMING_LCNT(lcnt);
|
||||
writel(scl_timing, master->regs + SCL_I2C_FM_TIMING);
|
||||
|
|
@ -699,7 +682,6 @@ static int dw_i3c_master_bus_init(struct i3c_master_controller *m)
|
|||
dw_i3c_master_enable(master);
|
||||
|
||||
rpm_out:
|
||||
pm_runtime_mark_last_busy(master->dev);
|
||||
pm_runtime_put_autosuspend(master->dev);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -829,7 +811,6 @@ static int dw_i3c_master_send_ccc_cmd(struct i3c_master_controller *m,
|
|||
else
|
||||
ret = dw_i3c_ccc_set(master, ccc);
|
||||
|
||||
pm_runtime_mark_last_busy(master->dev);
|
||||
pm_runtime_put_autosuspend(master->dev);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -912,7 +893,6 @@ static int dw_i3c_master_daa(struct i3c_master_controller *m)
|
|||
dw_i3c_master_free_xfer(xfer);
|
||||
|
||||
rpm_out:
|
||||
pm_runtime_mark_last_busy(master->dev);
|
||||
pm_runtime_put_autosuspend(master->dev);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -932,7 +912,7 @@ static int dw_i3c_master_priv_xfers(struct i3c_dev_desc *dev,
|
|||
return 0;
|
||||
|
||||
if (i3c_nxfers > master->caps.cmdfifodepth)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
for (i = 0; i < i3c_nxfers; i++) {
|
||||
if (i3c_xfers[i].rnw)
|
||||
|
|
@ -943,7 +923,7 @@ static int dw_i3c_master_priv_xfers(struct i3c_dev_desc *dev,
|
|||
|
||||
if (ntxwords > master->caps.datafifodepth ||
|
||||
nrxwords > master->caps.datafifodepth)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
xfer = dw_i3c_master_alloc_xfer(master, i3c_nxfers);
|
||||
if (!xfer)
|
||||
|
|
@ -998,7 +978,6 @@ static int dw_i3c_master_priv_xfers(struct i3c_dev_desc *dev,
|
|||
ret = xfer->ret;
|
||||
dw_i3c_master_free_xfer(xfer);
|
||||
|
||||
pm_runtime_mark_last_busy(master->dev);
|
||||
pm_runtime_put_autosuspend(master->dev);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1093,7 +1072,7 @@ static int dw_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
|
|||
return 0;
|
||||
|
||||
if (i2c_nxfers > master->caps.cmdfifodepth)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
for (i = 0; i < i2c_nxfers; i++) {
|
||||
if (i2c_xfers[i].flags & I2C_M_RD)
|
||||
|
|
@ -1104,7 +1083,7 @@ static int dw_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
|
|||
|
||||
if (ntxwords > master->caps.datafifodepth ||
|
||||
nrxwords > master->caps.datafifodepth)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
xfer = dw_i3c_master_alloc_xfer(master, i2c_nxfers);
|
||||
if (!xfer)
|
||||
|
|
@ -1142,13 +1121,12 @@ static int dw_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
|
|||
}
|
||||
|
||||
dw_i3c_master_enqueue_xfer(master, xfer);
|
||||
if (!wait_for_completion_timeout(&xfer->comp, XFER_TIMEOUT))
|
||||
if (!wait_for_completion_timeout(&xfer->comp, m->i2c.timeout))
|
||||
dw_i3c_master_dequeue_xfer(master, xfer);
|
||||
|
||||
ret = xfer->ret;
|
||||
dw_i3c_master_free_xfer(xfer);
|
||||
|
||||
pm_runtime_mark_last_busy(master->dev);
|
||||
pm_runtime_put_autosuspend(master->dev);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1316,7 +1294,6 @@ static int dw_i3c_master_disable_hotjoin(struct i3c_master_controller *m)
|
|||
writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_HOT_JOIN_NACK,
|
||||
master->regs + DEVICE_CTRL);
|
||||
|
||||
pm_runtime_mark_last_busy(master->dev);
|
||||
pm_runtime_put_autosuspend(master->dev);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1342,7 +1319,6 @@ static int dw_i3c_master_enable_ibi(struct i3c_dev_desc *dev)
|
|||
|
||||
if (rc) {
|
||||
dw_i3c_master_set_sir_enabled(master, dev, data->index, false);
|
||||
pm_runtime_mark_last_busy(master->dev);
|
||||
pm_runtime_put_autosuspend(master->dev);
|
||||
}
|
||||
|
||||
|
|
@ -1362,7 +1338,6 @@ static int dw_i3c_master_disable_ibi(struct i3c_dev_desc *dev)
|
|||
|
||||
dw_i3c_master_set_sir_enabled(master, dev, data->index, false);
|
||||
|
||||
pm_runtime_mark_last_busy(master->dev);
|
||||
pm_runtime_put_autosuspend(master->dev);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
#include <linux/spinlock.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include "../internals.h"
|
||||
|
||||
#define DEV_ID 0x0
|
||||
#define DEV_ID_I3C_MASTER 0x5034
|
||||
|
||||
|
|
@ -412,7 +414,6 @@ struct cdns_i3c_master {
|
|||
} xferqueue;
|
||||
void __iomem *regs;
|
||||
struct clk *sysclk;
|
||||
struct clk *pclk;
|
||||
struct cdns_i3c_master_caps caps;
|
||||
unsigned long i3c_scl_lim;
|
||||
const struct cdns_i3c_data *devdata;
|
||||
|
|
@ -427,25 +428,13 @@ to_cdns_i3c_master(struct i3c_master_controller *master)
|
|||
static void cdns_i3c_master_wr_to_tx_fifo(struct cdns_i3c_master *master,
|
||||
const u8 *bytes, int nbytes)
|
||||
{
|
||||
writesl(master->regs + TX_FIFO, bytes, nbytes / 4);
|
||||
if (nbytes & 3) {
|
||||
u32 tmp = 0;
|
||||
|
||||
memcpy(&tmp, bytes + (nbytes & ~3), nbytes & 3);
|
||||
writesl(master->regs + TX_FIFO, &tmp, 1);
|
||||
}
|
||||
i3c_writel_fifo(master->regs + TX_FIFO, bytes, nbytes);
|
||||
}
|
||||
|
||||
static void cdns_i3c_master_rd_from_rx_fifo(struct cdns_i3c_master *master,
|
||||
u8 *bytes, int nbytes)
|
||||
{
|
||||
readsl(master->regs + RX_FIFO, bytes, nbytes / 4);
|
||||
if (nbytes & 3) {
|
||||
u32 tmp;
|
||||
|
||||
readsl(master->regs + RX_FIFO, &tmp, 1);
|
||||
memcpy(bytes + (nbytes & ~3), &tmp, nbytes & 3);
|
||||
}
|
||||
i3c_readl_fifo(master->regs + RX_FIFO, bytes, nbytes);
|
||||
}
|
||||
|
||||
static bool cdns_i3c_master_supports_ccc_cmd(struct i3c_master_controller *m,
|
||||
|
|
@ -742,7 +731,7 @@ static int cdns_i3c_master_priv_xfers(struct i3c_dev_desc *dev,
|
|||
|
||||
for (i = 0; i < nxfers; i++) {
|
||||
if (xfers[i].len > CMD0_FIFO_PL_LEN_MAX)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (!nxfers)
|
||||
|
|
@ -750,7 +739,7 @@ static int cdns_i3c_master_priv_xfers(struct i3c_dev_desc *dev,
|
|||
|
||||
if (nxfers > master->caps.cmdfifodepth ||
|
||||
nxfers > master->caps.cmdrfifodepth)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/*
|
||||
* First make sure that all transactions (block of transfers separated
|
||||
|
|
@ -765,7 +754,7 @@ static int cdns_i3c_master_priv_xfers(struct i3c_dev_desc *dev,
|
|||
|
||||
if (rxslots > master->caps.rxfifodepth ||
|
||||
txslots > master->caps.txfifodepth)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
cdns_xfer = cdns_i3c_master_alloc_xfer(master, nxfers);
|
||||
if (!cdns_xfer)
|
||||
|
|
@ -822,11 +811,11 @@ static int cdns_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
|
|||
int i, ret = 0;
|
||||
|
||||
if (nxfers > master->caps.cmdfifodepth)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
for (i = 0; i < nxfers; i++) {
|
||||
if (xfers[i].len > CMD0_FIFO_PL_LEN_MAX)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (xfers[i].flags & I2C_M_RD)
|
||||
nrxwords += DIV_ROUND_UP(xfers[i].len, 4);
|
||||
|
|
@ -836,7 +825,7 @@ static int cdns_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
|
|||
|
||||
if (ntxwords > master->caps.txfifodepth ||
|
||||
nrxwords > master->caps.rxfifodepth)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
xfer = cdns_i3c_master_alloc_xfer(master, nxfers);
|
||||
if (!xfer)
|
||||
|
|
@ -863,7 +852,7 @@ static int cdns_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
|
|||
}
|
||||
|
||||
cdns_i3c_master_queue_xfer(master, xfer);
|
||||
if (!wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000)))
|
||||
if (!wait_for_completion_timeout(&xfer->comp, m->i2c.timeout))
|
||||
cdns_i3c_master_unqueue_xfer(master, xfer);
|
||||
|
||||
ret = xfer->ret;
|
||||
|
|
@ -1330,12 +1319,7 @@ static void cdns_i3c_master_handle_ibi(struct cdns_i3c_master *master,
|
|||
buf = slot->data;
|
||||
|
||||
nbytes = IBIR_XFER_BYTES(ibir);
|
||||
readsl(master->regs + IBI_DATA_FIFO, buf, nbytes / 4);
|
||||
if (nbytes % 3) {
|
||||
u32 tmp = __raw_readl(master->regs + IBI_DATA_FIFO);
|
||||
|
||||
memcpy(buf + (nbytes & ~3), &tmp, nbytes & 3);
|
||||
}
|
||||
i3c_readl_fifo(master->regs + IBI_DATA_FIFO, buf, nbytes);
|
||||
|
||||
slot->len = min_t(unsigned int, IBIR_XFER_BYTES(ibir),
|
||||
dev->ibi->max_payload_len);
|
||||
|
|
@ -1566,6 +1550,7 @@ MODULE_DEVICE_TABLE(of, cdns_i3c_master_of_ids);
|
|||
static int cdns_i3c_master_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct cdns_i3c_master *master;
|
||||
struct clk *pclk;
|
||||
int ret, irq;
|
||||
u32 val;
|
||||
|
||||
|
|
@ -1581,11 +1566,11 @@ static int cdns_i3c_master_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(master->regs))
|
||||
return PTR_ERR(master->regs);
|
||||
|
||||
master->pclk = devm_clk_get(&pdev->dev, "pclk");
|
||||
if (IS_ERR(master->pclk))
|
||||
return PTR_ERR(master->pclk);
|
||||
pclk = devm_clk_get_enabled(&pdev->dev, "pclk");
|
||||
if (IS_ERR(pclk))
|
||||
return PTR_ERR(pclk);
|
||||
|
||||
master->sysclk = devm_clk_get(&pdev->dev, "sysclk");
|
||||
master->sysclk = devm_clk_get_enabled(&pdev->dev, "sysclk");
|
||||
if (IS_ERR(master->sysclk))
|
||||
return PTR_ERR(master->sysclk);
|
||||
|
||||
|
|
@ -1593,18 +1578,8 @@ static int cdns_i3c_master_probe(struct platform_device *pdev)
|
|||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
ret = clk_prepare_enable(master->pclk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_prepare_enable(master->sysclk);
|
||||
if (ret)
|
||||
goto err_disable_pclk;
|
||||
|
||||
if (readl(master->regs + DEV_ID) != DEV_ID_I3C_MASTER) {
|
||||
ret = -EINVAL;
|
||||
goto err_disable_sysclk;
|
||||
}
|
||||
if (readl(master->regs + DEV_ID) != DEV_ID_I3C_MASTER)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_init(&master->xferqueue.lock);
|
||||
INIT_LIST_HEAD(&master->xferqueue.list);
|
||||
|
|
@ -1615,7 +1590,7 @@ static int cdns_i3c_master_probe(struct platform_device *pdev)
|
|||
ret = devm_request_irq(&pdev->dev, irq, cdns_i3c_master_interrupt, 0,
|
||||
dev_name(&pdev->dev), master);
|
||||
if (ret)
|
||||
goto err_disable_sysclk;
|
||||
return ret;
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
|
||||
|
|
@ -1637,29 +1612,15 @@ static int cdns_i3c_master_probe(struct platform_device *pdev)
|
|||
master->ibi.slots = devm_kcalloc(&pdev->dev, master->ibi.num_slots,
|
||||
sizeof(*master->ibi.slots),
|
||||
GFP_KERNEL);
|
||||
if (!master->ibi.slots) {
|
||||
ret = -ENOMEM;
|
||||
goto err_disable_sysclk;
|
||||
}
|
||||
if (!master->ibi.slots)
|
||||
return -ENOMEM;
|
||||
|
||||
writel(IBIR_THR(1), master->regs + CMD_IBI_THR_CTRL);
|
||||
writel(MST_INT_IBIR_THR, master->regs + MST_IER);
|
||||
writel(DEVS_CTRL_DEV_CLR_ALL, master->regs + DEVS_CTRL);
|
||||
|
||||
ret = i3c_master_register(&master->base, &pdev->dev,
|
||||
&cdns_i3c_master_ops, false);
|
||||
if (ret)
|
||||
goto err_disable_sysclk;
|
||||
|
||||
return 0;
|
||||
|
||||
err_disable_sysclk:
|
||||
clk_disable_unprepare(master->sysclk);
|
||||
|
||||
err_disable_pclk:
|
||||
clk_disable_unprepare(master->pclk);
|
||||
|
||||
return ret;
|
||||
return i3c_master_register(&master->base, &pdev->dev,
|
||||
&cdns_i3c_master_ops, false);
|
||||
}
|
||||
|
||||
static void cdns_i3c_master_remove(struct platform_device *pdev)
|
||||
|
|
@ -1668,9 +1629,6 @@ static void cdns_i3c_master_remove(struct platform_device *pdev)
|
|||
|
||||
cancel_work_sync(&master->hj_work);
|
||||
i3c_master_unregister(&master->base);
|
||||
|
||||
clk_disable_unprepare(master->sysclk);
|
||||
clk_disable_unprepare(master->pclk);
|
||||
}
|
||||
|
||||
static struct platform_driver cdns_i3c_master = {
|
||||
|
|
|
|||
|
|
@ -395,7 +395,7 @@ static int i3c_hci_i2c_xfers(struct i2c_dev_desc *dev,
|
|||
ret = hci->io->queue_xfer(hci, xfer, nxfers);
|
||||
if (ret)
|
||||
goto out;
|
||||
if (!wait_for_completion_timeout(&done, HZ) &&
|
||||
if (!wait_for_completion_timeout(&done, m->i2c.timeout) &&
|
||||
hci->io->dequeue_xfer(hci, xfer, nxfers)) {
|
||||
ret = -ETIME;
|
||||
goto out;
|
||||
|
|
|
|||
1404
drivers/i3c/master/renesas-i3c.c
Normal file
1404
drivers/i3c/master/renesas-i3c.c
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -104,6 +104,7 @@
|
|||
#define SVC_I3C_MDATACTRL_TXTRIG_FIFO_NOT_FULL GENMASK(5, 4)
|
||||
#define SVC_I3C_MDATACTRL_RXTRIG_FIFO_NOT_EMPTY 0
|
||||
#define SVC_I3C_MDATACTRL_RXCOUNT(x) FIELD_GET(GENMASK(28, 24), (x))
|
||||
#define SVC_I3C_MDATACTRL_TXCOUNT(x) FIELD_GET(GENMASK(20, 16), (x))
|
||||
#define SVC_I3C_MDATACTRL_TXFULL BIT(30)
|
||||
#define SVC_I3C_MDATACTRL_RXEMPTY BIT(31)
|
||||
|
||||
|
|
@ -664,7 +665,6 @@ static int svc_i3c_master_set_speed(struct i3c_master_controller *m,
|
|||
}
|
||||
|
||||
rpm_out:
|
||||
pm_runtime_mark_last_busy(master->dev);
|
||||
pm_runtime_put_autosuspend(master->dev);
|
||||
|
||||
return ret;
|
||||
|
|
@ -779,7 +779,6 @@ static int svc_i3c_master_bus_init(struct i3c_master_controller *m)
|
|||
goto rpm_out;
|
||||
|
||||
rpm_out:
|
||||
pm_runtime_mark_last_busy(master->dev);
|
||||
pm_runtime_put_autosuspend(master->dev);
|
||||
|
||||
return ret;
|
||||
|
|
@ -801,7 +800,6 @@ static void svc_i3c_master_bus_cleanup(struct i3c_master_controller *m)
|
|||
/* Disable master */
|
||||
writel(0, master->regs + SVC_I3C_MCONFIG);
|
||||
|
||||
pm_runtime_mark_last_busy(master->dev);
|
||||
pm_runtime_put_autosuspend(master->dev);
|
||||
}
|
||||
|
||||
|
|
@ -1207,7 +1205,6 @@ static int svc_i3c_master_do_daa(struct i3c_master_controller *m)
|
|||
dev_err(master->dev, "Cannot handle such a list of devices");
|
||||
|
||||
rpm_out:
|
||||
pm_runtime_mark_last_busy(master->dev);
|
||||
pm_runtime_put_autosuspend(master->dev);
|
||||
|
||||
return ret;
|
||||
|
|
@ -1304,14 +1301,19 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
|
|||
* FIFO start filling as soon as possible after EmitStartAddr.
|
||||
*/
|
||||
if (svc_has_quirk(master, SVC_I3C_QUIRK_FIFO_EMPTY) && !rnw && xfer_len) {
|
||||
u32 end = xfer_len > SVC_I3C_FIFO_SIZE ? 0 : SVC_I3C_MWDATAB_END;
|
||||
u32 len = min_t(u32, xfer_len, SVC_I3C_FIFO_SIZE);
|
||||
u32 space, end, len;
|
||||
|
||||
writesb(master->regs + SVC_I3C_MWDATAB1, out, len - 1);
|
||||
/* Mark END bit if this is the last byte */
|
||||
writel(out[len - 1] | end, master->regs + SVC_I3C_MWDATAB);
|
||||
xfer_len -= len;
|
||||
out += len;
|
||||
reg = readl(master->regs + SVC_I3C_MDATACTRL);
|
||||
space = SVC_I3C_FIFO_SIZE - SVC_I3C_MDATACTRL_TXCOUNT(reg);
|
||||
if (space) {
|
||||
end = xfer_len > space ? 0 : SVC_I3C_MWDATAB_END;
|
||||
len = min_t(u32, xfer_len, space);
|
||||
writesb(master->regs + SVC_I3C_MWDATAB1, out, len - 1);
|
||||
/* Mark END bit if this is the last byte */
|
||||
writel(out[len - 1] | end, master->regs + SVC_I3C_MWDATAB);
|
||||
xfer_len -= len;
|
||||
out += len;
|
||||
}
|
||||
}
|
||||
|
||||
ret = readl_poll_timeout(master->regs + SVC_I3C_MSTATUS, reg,
|
||||
|
|
@ -1511,7 +1513,6 @@ static void svc_i3c_master_enqueue_xfer(struct svc_i3c_master *master,
|
|||
}
|
||||
spin_unlock_irqrestore(&master->xferqueue.lock, flags);
|
||||
|
||||
pm_runtime_mark_last_busy(master->dev);
|
||||
pm_runtime_put_autosuspend(master->dev);
|
||||
}
|
||||
|
||||
|
|
@ -1708,7 +1709,7 @@ static int svc_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
|
|||
|
||||
mutex_lock(&master->lock);
|
||||
svc_i3c_master_enqueue_xfer(master, xfer);
|
||||
if (!wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000)))
|
||||
if (!wait_for_completion_timeout(&xfer->comp, m->i2c.timeout))
|
||||
svc_i3c_master_dequeue_xfer(master, xfer);
|
||||
mutex_unlock(&master->lock);
|
||||
|
||||
|
|
@ -1801,7 +1802,6 @@ static int svc_i3c_master_disable_ibi(struct i3c_dev_desc *dev)
|
|||
|
||||
ret = i3c_master_disec_locked(m, dev->info.dyn_addr, I3C_CCC_EVENT_SIR);
|
||||
|
||||
pm_runtime_mark_last_busy(master->dev);
|
||||
pm_runtime_put_autosuspend(master->dev);
|
||||
|
||||
return ret;
|
||||
|
|
@ -1834,7 +1834,6 @@ static int svc_i3c_master_disable_hotjoin(struct i3c_master_controller *m)
|
|||
if (!master->enabled_events)
|
||||
svc_i3c_master_disable_interrupts(master);
|
||||
|
||||
pm_runtime_mark_last_busy(master->dev);
|
||||
pm_runtime_put_autosuspend(master->dev);
|
||||
|
||||
return 0;
|
||||
|
|
@ -1954,7 +1953,6 @@ static int svc_i3c_master_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto rpm_disable;
|
||||
|
||||
pm_runtime_mark_last_busy(&pdev->dev);
|
||||
pm_runtime_put_autosuspend(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ void i3c_driver_unregister(struct i3c_driver *drv);
|
|||
*
|
||||
* Return: 0 if both registrations succeeds, a negative error code otherwise.
|
||||
*/
|
||||
static inline int i3c_i2c_driver_register(struct i3c_driver *i3cdrv,
|
||||
static __always_inline int i3c_i2c_driver_register(struct i3c_driver *i3cdrv,
|
||||
struct i2c_driver *i2cdrv)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -270,7 +270,7 @@ static inline int i3c_i2c_driver_register(struct i3c_driver *i3cdrv,
|
|||
* Note that when CONFIG_I3C is not enabled, this function only unregisters the
|
||||
* @i2cdrv.
|
||||
*/
|
||||
static inline void i3c_i2c_driver_unregister(struct i3c_driver *i3cdrv,
|
||||
static __always_inline void i3c_i2c_driver_unregister(struct i3c_driver *i3cdrv,
|
||||
struct i2c_driver *i2cdrv)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_I3C))
|
||||
|
|
|
|||
|
|
@ -249,10 +249,15 @@ struct i3c_device {
|
|||
*/
|
||||
#define I3C_BUS_MAX_DEVS 11
|
||||
|
||||
#define I3C_BUS_MAX_I3C_SCL_RATE 12900000
|
||||
#define I3C_BUS_TYP_I3C_SCL_RATE 12500000
|
||||
#define I3C_BUS_I2C_FM_PLUS_SCL_RATE 1000000
|
||||
#define I3C_BUS_I2C_FM_SCL_RATE 400000
|
||||
/* Taken from the I3C Spec V1.1.1, chapter 6.2. "Timing specification" */
|
||||
#define I3C_BUS_I2C_FM_PLUS_SCL_MAX_RATE 1000000
|
||||
#define I3C_BUS_I2C_FM_SCL_MAX_RATE 400000
|
||||
#define I3C_BUS_I3C_SCL_MAX_RATE 12900000
|
||||
#define I3C_BUS_I3C_SCL_TYP_RATE 12500000
|
||||
#define I3C_BUS_TAVAL_MIN_NS 1000
|
||||
#define I3C_BUS_TBUF_MIXED_FM_MIN_NS 1300
|
||||
#define I3C_BUS_THIGH_MIXED_MAX_NS 41
|
||||
#define I3C_BUS_TIDLE_MIN_NS 200000
|
||||
#define I3C_BUS_TLOW_OD_MIN_NS 200
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user