diff mbox series

[2/2] i3c: master: svc: use slow speed for first broadcast address

Message ID 20240806064851.2425797-2-carlos.song@nxp.com (mailing list archive)
State Superseded
Headers show
Series [1/2] i3c: master: support to adjust first broadcast address speed | expand

Commit Message

Carlos Song Aug. 6, 2024, 6:48 a.m. UTC
From: Carlos Song <carlos.song@nxp.com>

I3C controller should support adjusting open drain timing for the first
broadcast address to make I3C device working as a i2c device can see slow
broadcast address to close its Spike Filter to change working at i3c mode.

Signed-off-by: Carlos Song <carlos.song@nxp.com>
---
 drivers/i3c/master/svc-i3c-master.c | 51 +++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

Comments

kernel test robot Aug. 6, 2024, 3:46 p.m. UTC | #1
Hi,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.11-rc2 next-20240806]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/carlos-song-nxp-com/i3c-master-svc-use-slow-speed-for-first-broadcast-address/20240806-144941
base:   linus/master
patch link:    https://lore.kernel.org/r/20240806064851.2425797-2-carlos.song%40nxp.com
patch subject: [PATCH 2/2] i3c: master: svc: use slow speed for first broadcast address
config: i386-buildonly-randconfig-001-20240806 (https://download.01.org/0day-ci/archive/20240806/202408062304.MtyfBIl7-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-12) 11.3.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240806/202408062304.MtyfBIl7-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202408062304.MtyfBIl7-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/i3c/master/svc-i3c-master.c:216: warning: Function parameter or struct member 'mctrl_config' not described in 'svc_i3c_master'


vim +216 drivers/i3c/master/svc-i3c-master.c

1c5ee2a77b1bac Clark Wang    2023-05-17  158  
dd3c52846d5954 Miquel Raynal 2021-01-21  159  /**
dd3c52846d5954 Miquel Raynal 2021-01-21  160   * struct svc_i3c_master - Silvaco I3C Master structure
dd3c52846d5954 Miquel Raynal 2021-01-21  161   * @base: I3C master controller
dd3c52846d5954 Miquel Raynal 2021-01-21  162   * @dev: Corresponding device
dd3c52846d5954 Miquel Raynal 2021-01-21  163   * @regs: Memory mapping
5496eac6ad7428 Miquel Raynal 2023-08-17  164   * @saved_regs: Volatile values for PM operations
dd3c52846d5954 Miquel Raynal 2021-01-21  165   * @free_slots: Bit array of available slots
dd3c52846d5954 Miquel Raynal 2021-01-21  166   * @addrs: Array containing the dynamic addresses of each attached device
dd3c52846d5954 Miquel Raynal 2021-01-21  167   * @descs: Array of descriptors, one per attached device
dd3c52846d5954 Miquel Raynal 2021-01-21  168   * @hj_work: Hot-join work
dd3c52846d5954 Miquel Raynal 2021-01-21  169   * @ibi_work: IBI work
dd3c52846d5954 Miquel Raynal 2021-01-21  170   * @irq: Main interrupt
dd3c52846d5954 Miquel Raynal 2021-01-21  171   * @pclk: System clock
dd3c52846d5954 Miquel Raynal 2021-01-21  172   * @fclk: Fast clock (bus)
dd3c52846d5954 Miquel Raynal 2021-01-21  173   * @sclk: Slow clock (other events)
dd3c52846d5954 Miquel Raynal 2021-01-21  174   * @xferqueue: Transfer queue structure
dd3c52846d5954 Miquel Raynal 2021-01-21  175   * @xferqueue.list: List member
dd3c52846d5954 Miquel Raynal 2021-01-21  176   * @xferqueue.cur: Current ongoing transfer
dd3c52846d5954 Miquel Raynal 2021-01-21  177   * @xferqueue.lock: Queue lock
dd3c52846d5954 Miquel Raynal 2021-01-21  178   * @ibi: IBI structure
dd3c52846d5954 Miquel Raynal 2021-01-21  179   * @ibi.num_slots: Number of slots available in @ibi.slots
dd3c52846d5954 Miquel Raynal 2021-01-21  180   * @ibi.slots: Available IBI slots
dd3c52846d5954 Miquel Raynal 2021-01-21  181   * @ibi.tbq_slot: To be queued IBI slot
dd3c52846d5954 Miquel Raynal 2021-01-21  182   * @ibi.lock: IBI lock
6bf3fc26818381 Frank Li      2023-10-23  183   * @lock: Transfer lock, protect between IBI work thread and callbacks from master
05b26c31a4859a Frank Li      2023-12-01  184   * @enabled_events: Bit masks for enable events (IBI, HotJoin).
dd3c52846d5954 Miquel Raynal 2021-01-21  185   */
dd3c52846d5954 Miquel Raynal 2021-01-21  186  struct svc_i3c_master {
dd3c52846d5954 Miquel Raynal 2021-01-21  187  	struct i3c_master_controller base;
dd3c52846d5954 Miquel Raynal 2021-01-21  188  	struct device *dev;
dd3c52846d5954 Miquel Raynal 2021-01-21  189  	void __iomem *regs;
1c5ee2a77b1bac Clark Wang    2023-05-17  190  	struct svc_i3c_regs_save saved_regs;
dd3c52846d5954 Miquel Raynal 2021-01-21  191  	u32 free_slots;
dd3c52846d5954 Miquel Raynal 2021-01-21  192  	u8 addrs[SVC_I3C_MAX_DEVS];
dd3c52846d5954 Miquel Raynal 2021-01-21  193  	struct i3c_dev_desc *descs[SVC_I3C_MAX_DEVS];
dd3c52846d5954 Miquel Raynal 2021-01-21  194  	struct work_struct hj_work;
dd3c52846d5954 Miquel Raynal 2021-01-21  195  	struct work_struct ibi_work;
dd3c52846d5954 Miquel Raynal 2021-01-21  196  	int irq;
dd3c52846d5954 Miquel Raynal 2021-01-21  197  	struct clk *pclk;
dd3c52846d5954 Miquel Raynal 2021-01-21  198  	struct clk *fclk;
dd3c52846d5954 Miquel Raynal 2021-01-21  199  	struct clk *sclk;
dd3c52846d5954 Miquel Raynal 2021-01-21  200  	struct {
dd3c52846d5954 Miquel Raynal 2021-01-21  201  		struct list_head list;
dd3c52846d5954 Miquel Raynal 2021-01-21  202  		struct svc_i3c_xfer *cur;
dd3c52846d5954 Miquel Raynal 2021-01-21  203  		/* Prevent races between transfers */
dd3c52846d5954 Miquel Raynal 2021-01-21  204  		spinlock_t lock;
dd3c52846d5954 Miquel Raynal 2021-01-21  205  	} xferqueue;
dd3c52846d5954 Miquel Raynal 2021-01-21  206  	struct {
dd3c52846d5954 Miquel Raynal 2021-01-21  207  		unsigned int num_slots;
dd3c52846d5954 Miquel Raynal 2021-01-21  208  		struct i3c_dev_desc **slots;
dd3c52846d5954 Miquel Raynal 2021-01-21  209  		struct i3c_ibi_slot *tbq_slot;
dd3c52846d5954 Miquel Raynal 2021-01-21  210  		/* Prevent races within IBI handlers */
dd3c52846d5954 Miquel Raynal 2021-01-21  211  		spinlock_t lock;
dd3c52846d5954 Miquel Raynal 2021-01-21  212  	} ibi;
6bf3fc26818381 Frank Li      2023-10-23  213  	struct mutex lock;
05b26c31a4859a Frank Li      2023-12-01  214  	int enabled_events;
7f8771c6b3f96d Carlos Song   2024-08-06  215  	u32 mctrl_config;
dd3c52846d5954 Miquel Raynal 2021-01-21 @216  };
dd3c52846d5954 Miquel Raynal 2021-01-21  217
Frank Li Aug. 6, 2024, 4:02 p.m. UTC | #2
On Tue, Aug 06, 2024 at 02:48:51PM +0800, carlos.song@nxp.com wrote:
> From: Carlos Song <carlos.song@nxp.com>
>
> I3C controller should support adjusting open drain timing for the first
> broadcast address to make I3C device working as a i2c device can see slow
> broadcast address to close its Spike Filter to change working at i3c mode.
>
> Signed-off-by: Carlos Song <carlos.song@nxp.com>
> ---

A small nik below.

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/i3c/master/svc-i3c-master.c | 51 +++++++++++++++++++++++++++++
>  1 file changed, 51 insertions(+)
>
> diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
> index 0a68fd1b81d4..4cdce25c5cf7 100644
> --- a/drivers/i3c/master/svc-i3c-master.c
> +++ b/drivers/i3c/master/svc-i3c-master.c
> @@ -212,6 +212,7 @@ struct svc_i3c_master {
>  	} ibi;
>  	struct mutex lock;
>  	int enabled_events;
> +	u32 mctrl_config;
>  };
>
>  /**
> @@ -529,6 +530,54 @@ static irqreturn_t svc_i3c_master_irq_handler(int irq, void *dev_id)
>  	return IRQ_HANDLED;
>  }
>
> +static int svc_i3c_master_set_speed(struct i3c_master_controller *m,
> +				     enum i3c_open_drain_speed speed)
> +{
> +	struct svc_i3c_master *master = to_svc_i3c_master(m);
> +	struct i3c_bus *bus = i3c_master_get_bus(&master->base);
> +	unsigned long fclk_rate;
> +	u32 ppbaud, odbaud, odhpp, mconfig;
> +	int ret;

try keep reverse christmas tree order.

> +
> +	ret = pm_runtime_resume_and_get(master->dev);
> +	if (ret < 0) {
> +		dev_err(master->dev, "<%s> Cannot get runtime PM.\n", __func__);
> +		return ret;
> +	}
> +
> +	switch (speed) {
> +	case I3C_OPEN_DRAIN_SLOW_SPEED:
> +		fclk_rate = clk_get_rate(master->fclk);
> +		if (!fclk_rate) {
> +			ret = -EINVAL;
> +			goto rpm_out;
> +		}
> +		/*
> +		 * Set 50% duty-cycle I2C speed to I3C OPEN-DRAIN mode, so the first
> +		 * broadcast address is visible to all I2C/I3C devices on the I3C bus.
> +		 * I3C device working as a I2C device will turn off its 50ns Spike
> +		 * Filter to change to I3C mode.
> +		 */
> +		mconfig = master->mctrl_config;
> +		ppbaud = FIELD_GET(GENMASK(11, 8), mconfig);
> +		odhpp = 0;
> +		odbaud = DIV_ROUND_UP(fclk_rate, bus->scl_rate.i2c * (2 + 2 * ppbaud)) - 1;
> +		mconfig &= ~GENMASK(24, 16);
> +		mconfig |= SVC_I3C_MCONFIG_ODBAUD(odbaud) | SVC_I3C_MCONFIG_ODHPP(odhpp);
> +		writel(mconfig, master->regs + SVC_I3C_MCONFIG);
> +		break;
> +	case I3C_OPEN_DRAIN_NORMAL_SPEED:
> +		writel(master->mctrl_config, master->regs + SVC_I3C_MCONFIG);
> +		break;
> +	}
> +
> +rpm_out:
> +	pm_runtime_mark_last_busy(master->dev);
> +	pm_runtime_put_autosuspend(master->dev);
> +
> +	return ret;
> +}
> +
>  static int svc_i3c_master_bus_init(struct i3c_master_controller *m)
>  {
>  	struct svc_i3c_master *master = to_svc_i3c_master(m);
> @@ -611,6 +660,7 @@ static int svc_i3c_master_bus_init(struct i3c_master_controller *m)
>  	      SVC_I3C_MCONFIG_I2CBAUD(i2cbaud);
>  	writel(reg, master->regs + SVC_I3C_MCONFIG);
>
> +	master->mctrl_config = reg;
>  	/* Master core's registration */
>  	ret = i3c_master_get_free_addr(m, 0);
>  	if (ret < 0)
> @@ -1645,6 +1695,7 @@ static const struct i3c_master_controller_ops svc_i3c_master_ops = {
>  	.disable_ibi = svc_i3c_master_disable_ibi,
>  	.enable_hotjoin = svc_i3c_master_enable_hotjoin,
>  	.disable_hotjoin = svc_i3c_master_disable_hotjoin,
> +	.set_speed = svc_i3c_master_set_speed,
>  };
>
>  static int svc_i3c_master_prepare_clks(struct svc_i3c_master *master)
> --
> 2.34.1
>
diff mbox series

Patch

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index 0a68fd1b81d4..4cdce25c5cf7 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -212,6 +212,7 @@  struct svc_i3c_master {
 	} ibi;
 	struct mutex lock;
 	int enabled_events;
+	u32 mctrl_config;
 };
 
 /**
@@ -529,6 +530,54 @@  static irqreturn_t svc_i3c_master_irq_handler(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static int svc_i3c_master_set_speed(struct i3c_master_controller *m,
+				     enum i3c_open_drain_speed speed)
+{
+	struct svc_i3c_master *master = to_svc_i3c_master(m);
+	struct i3c_bus *bus = i3c_master_get_bus(&master->base);
+	unsigned long fclk_rate;
+	u32 ppbaud, odbaud, odhpp, mconfig;
+	int ret;
+
+	ret = pm_runtime_resume_and_get(master->dev);
+	if (ret < 0) {
+		dev_err(master->dev, "<%s> Cannot get runtime PM.\n", __func__);
+		return ret;
+	}
+
+	switch (speed) {
+	case I3C_OPEN_DRAIN_SLOW_SPEED:
+		fclk_rate = clk_get_rate(master->fclk);
+		if (!fclk_rate) {
+			ret = -EINVAL;
+			goto rpm_out;
+		}
+		/*
+		 * Set 50% duty-cycle I2C speed to I3C OPEN-DRAIN mode, so the first
+		 * broadcast address is visible to all I2C/I3C devices on the I3C bus.
+		 * I3C device working as a I2C device will turn off its 50ns Spike
+		 * Filter to change to I3C mode.
+		 */
+		mconfig = master->mctrl_config;
+		ppbaud = FIELD_GET(GENMASK(11, 8), mconfig);
+		odhpp = 0;
+		odbaud = DIV_ROUND_UP(fclk_rate, bus->scl_rate.i2c * (2 + 2 * ppbaud)) - 1;
+		mconfig &= ~GENMASK(24, 16);
+		mconfig |= SVC_I3C_MCONFIG_ODBAUD(odbaud) | SVC_I3C_MCONFIG_ODHPP(odhpp);
+		writel(mconfig, master->regs + SVC_I3C_MCONFIG);
+		break;
+	case I3C_OPEN_DRAIN_NORMAL_SPEED:
+		writel(master->mctrl_config, master->regs + SVC_I3C_MCONFIG);
+		break;
+	}
+
+rpm_out:
+	pm_runtime_mark_last_busy(master->dev);
+	pm_runtime_put_autosuspend(master->dev);
+
+	return ret;
+}
+
 static int svc_i3c_master_bus_init(struct i3c_master_controller *m)
 {
 	struct svc_i3c_master *master = to_svc_i3c_master(m);
@@ -611,6 +660,7 @@  static int svc_i3c_master_bus_init(struct i3c_master_controller *m)
 	      SVC_I3C_MCONFIG_I2CBAUD(i2cbaud);
 	writel(reg, master->regs + SVC_I3C_MCONFIG);
 
+	master->mctrl_config = reg;
 	/* Master core's registration */
 	ret = i3c_master_get_free_addr(m, 0);
 	if (ret < 0)
@@ -1645,6 +1695,7 @@  static const struct i3c_master_controller_ops svc_i3c_master_ops = {
 	.disable_ibi = svc_i3c_master_disable_ibi,
 	.enable_hotjoin = svc_i3c_master_enable_hotjoin,
 	.disable_hotjoin = svc_i3c_master_disable_hotjoin,
+	.set_speed = svc_i3c_master_set_speed,
 };
 
 static int svc_i3c_master_prepare_clks(struct svc_i3c_master *master)