diff mbox series

[1/3] can: flexcan: add auto stop mode for IMX93 to support wakeup

Message ID 1669116752-4260-1-git-send-email-haibo.chen@nxp.com (mailing list archive)
State Awaiting Upstream
Delegated to: Netdev Maintainers
Headers show
Series [1/3] can: flexcan: add auto stop mode for IMX93 to support wakeup | expand

Checks

Context Check Description
netdev/tree_selection success Guessed tree name to be net-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter warning Series does not have a cover letter
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers success CCed 8 of 8 maintainers
netdev/build_clang success Errors and warnings before: 0 this patch: 0
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/checkpatch warning WARNING: DT compatible string "fsl,imx93-flexcan" appears un-documented -- check ./Documentation/devicetree/bindings/ WARNING: line length of 83 exceeds 80 columns WARNING: line length of 85 exceeds 80 columns WARNING: line length of 87 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Bough Chen Nov. 22, 2022, 11:32 a.m. UTC
From: Haibo Chen <haibo.chen@nxp.com>

IMX93 do not contain a GPR to config the stop mode, it will set
the flexcan into stop mode automatically once the ARM core go
into low power mode (WFI instruct) and gate off the flexcan
related clock automatically. But to let these logic work as
expect, before ARM core go into low power mode, need to make
sure the flexcan related clock keep on.

To support stop mode and wakeup feature on imx93, this patch
add a new fsl_imx93_devtype_data to separate from imx8mp.

Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
---
 drivers/net/can/flexcan/flexcan-core.c | 37 +++++++++++++++++++++++---
 drivers/net/can/flexcan/flexcan.h      |  2 ++
 2 files changed, 36 insertions(+), 3 deletions(-)

Comments

Marc Kleine-Budde Nov. 24, 2022, 2:39 p.m. UTC | #1
On 22.11.2022 19:32:30, haibo.chen@nxp.com wrote:
> From: Haibo Chen <haibo.chen@nxp.com>
> 
> IMX93 do not contain a GPR to config the stop mode, it will set
> the flexcan into stop mode automatically once the ARM core go
> into low power mode (WFI instruct) and gate off the flexcan
> related clock automatically. But to let these logic work as
> expect, before ARM core go into low power mode, need to make
> sure the flexcan related clock keep on.
> 
> To support stop mode and wakeup feature on imx93, this patch
> add a new fsl_imx93_devtype_data to separate from imx8mp.
> 
> Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
> ---
>  drivers/net/can/flexcan/flexcan-core.c | 37 +++++++++++++++++++++++---
>  drivers/net/can/flexcan/flexcan.h      |  2 ++
>  2 files changed, 36 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
> index 9bdadd716f4e..0aeff34e5ae1 100644
> --- a/drivers/net/can/flexcan/flexcan-core.c
> +++ b/drivers/net/can/flexcan/flexcan-core.c
> @@ -345,6 +345,15 @@ static struct flexcan_devtype_data fsl_imx8mp_devtype_data = {
>  		FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR,
>  };
>  
> +static struct flexcan_devtype_data fsl_imx93_devtype_data = {
> +	.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
> +		FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_RX_MAILBOX |
> +		FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_AUTO_STOP_MODE |
> +		FLEXCAN_QUIRK_SUPPORT_FD | FLEXCAN_QUIRK_SUPPORT_ECC |
> +		FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
> +		FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR,
> +};
> +
>  static const struct flexcan_devtype_data fsl_vf610_devtype_data = {
>  	.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
>  		FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_RX_MAILBOX |
> @@ -532,9 +541,14 @@ static inline int flexcan_enter_stop_mode(struct flexcan_priv *priv)
>  		ret = flexcan_stop_mode_enable_scfw(priv, true);
>  		if (ret < 0)
>  			return ret;
> -	} else {
> +	} else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR) {
>  		regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
>  				   1 << priv->stm.req_bit, 1 << priv->stm.req_bit);
> +	} else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_AUTO_STOP_MODE) {
> +		/* For the auto stop mode, software do nothing, hardware will cover
> +		 * all the operation automatically after system go into low power mode.
> +		 */
> +		return 0;
>  	}
>  
>  	return flexcan_low_power_enter_ack(priv);
> @@ -551,7 +565,7 @@ static inline int flexcan_exit_stop_mode(struct flexcan_priv *priv)
>  		ret = flexcan_stop_mode_enable_scfw(priv, false);
>  		if (ret < 0)
>  			return ret;
> -	} else {
> +	} else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR) {
>  		regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
>  				   1 << priv->stm.req_bit, 0);
>  	}
> @@ -560,6 +574,12 @@ static inline int flexcan_exit_stop_mode(struct flexcan_priv *priv)
>  	reg_mcr &= ~FLEXCAN_MCR_SLF_WAK;
>  	priv->write(reg_mcr, &regs->mcr);
>  
> +	/* For the auto stop mode, hardware will exist stop mode
                                                 ^^^^^
                                                 exit?

No need to resend.

Marc
Marc Kleine-Budde Nov. 30, 2022, 10:54 a.m. UTC | #2
On 22.11.2022 19:32:30, haibo.chen@nxp.com wrote:
> From: Haibo Chen <haibo.chen@nxp.com>
> 
> IMX93 do not contain a GPR to config the stop mode, it will set
> the flexcan into stop mode automatically once the ARM core go
> into low power mode (WFI instruct) and gate off the flexcan
> related clock automatically. But to let these logic work as
> expect, before ARM core go into low power mode, need to make
> sure the flexcan related clock keep on.
> 
> To support stop mode and wakeup feature on imx93, this patch
> add a new fsl_imx93_devtype_data to separate from imx8mp.
> 
> Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
> ---
>  drivers/net/can/flexcan/flexcan-core.c | 37 +++++++++++++++++++++++---
>  drivers/net/can/flexcan/flexcan.h      |  2 ++
>  2 files changed, 36 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
> index 9bdadd716f4e..0aeff34e5ae1 100644
> --- a/drivers/net/can/flexcan/flexcan-core.c
> +++ b/drivers/net/can/flexcan/flexcan-core.c

[...]

> @@ -2299,8 +2322,16 @@ static int __maybe_unused flexcan_noirq_suspend(struct device *device)
>  	if (netif_running(dev)) {
>  		int err;
>  
> -		if (device_may_wakeup(device))
> +		if (device_may_wakeup(device)) {
>  			flexcan_enable_wakeup_irq(priv, true);
> +			/* For auto stop mode, need to keep the clock on before
> +			 * system go into low power mode. After system go into
> +			 * low power mode, hardware will config the flexcan into
> +			 * stop mode, and gate off the clock automatically.
> +			 */
> +			if (priv->devtype_data.quirks & FLEXCAN_QUIRK_AUTO_STOP_MODE)
> +				return 0;
> +		}

With this change the flexcan_noirq_resume() is not symmetrical any more:
pm_runtime_force_suspend() is not called for mx93, but
pm_runtime_force_resume() is called.

>  
>  		err = pm_runtime_force_suspend(device);
>  		if (err)

Marc
Bough Chen Nov. 30, 2022, 11:39 a.m. UTC | #3
> -----Original Message-----
> From: Marc Kleine-Budde <mkl@pengutronix.de>
> Sent: 2022年11月30日 18:54
> To: Bough Chen <haibo.chen@nxp.com>
> Cc: wg@grandegger.com; davem@davemloft.net; edumazet@google.com;
> kuba@kernel.org; pabeni@redhat.com; robh+dt@kernel.org;
> krzysztof.kozlowski+dt@linaro.org; shawnguo@kernel.org;
> s.hauer@pengutronix.de; kernel@pengutronix.de; festevam@gmail.com;
> dl-linux-imx <linux-imx@nxp.com>; linux-can@vger.kernel.org;
> netdev@vger.kernel.org; devicetree@vger.kernel.org
> Subject: Re: [PATCH 1/3] can: flexcan: add auto stop mode for IMX93 to support
> wakeup
> 
> On 22.11.2022 19:32:30, haibo.chen@nxp.com wrote:
> > From: Haibo Chen <haibo.chen@nxp.com>
> >
> > IMX93 do not contain a GPR to config the stop mode, it will set the
> > flexcan into stop mode automatically once the ARM core go into low
> > power mode (WFI instruct) and gate off the flexcan related clock
> > automatically. But to let these logic work as expect, before ARM core
> > go into low power mode, need to make sure the flexcan related clock
> > keep on.
> >
> > To support stop mode and wakeup feature on imx93, this patch add a new
> > fsl_imx93_devtype_data to separate from imx8mp.
> >
> > Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
> > ---
> >  drivers/net/can/flexcan/flexcan-core.c | 37 +++++++++++++++++++++++---
> >  drivers/net/can/flexcan/flexcan.h      |  2 ++
> >  2 files changed, 36 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/net/can/flexcan/flexcan-core.c
> > b/drivers/net/can/flexcan/flexcan-core.c
> > index 9bdadd716f4e..0aeff34e5ae1 100644
> > --- a/drivers/net/can/flexcan/flexcan-core.c
> > +++ b/drivers/net/can/flexcan/flexcan-core.c
> 
> [...]
> 
> > @@ -2299,8 +2322,16 @@ static int __maybe_unused
> flexcan_noirq_suspend(struct device *device)
> >  	if (netif_running(dev)) {
> >  		int err;
> >
> > -		if (device_may_wakeup(device))
> > +		if (device_may_wakeup(device)) {
> >  			flexcan_enable_wakeup_irq(priv, true);
> > +			/* For auto stop mode, need to keep the clock on before
> > +			 * system go into low power mode. After system go into
> > +			 * low power mode, hardware will config the flexcan into
> > +			 * stop mode, and gate off the clock automatically.
> > +			 */
> > +			if (priv->devtype_data.quirks &
> FLEXCAN_QUIRK_AUTO_STOP_MODE)
> > +				return 0;
> > +		}
> 
> With this change the flexcan_noirq_resume() is not symmetrical any more:
> pm_runtime_force_suspend() is not called for mx93, but
> pm_runtime_force_resume() is called.

Yes, I do not understand the logic of pm_runtime_force_suspend correctly. I also find there is an unbalance warning show up. My bad.

Will fix this and send a V2 patch.

Best Regards
Haibo Chen
> 
> >
> >  		err = pm_runtime_force_suspend(device);
> >  		if (err)
> 
> Marc
> 
> --
> Pengutronix e.K.                 | Marc Kleine-Budde           |
> Embedded Linux                   | https://www.pengutronix.de  |
> Vertretung West/Dortmund         | Phone: +49-231-2826-924     |
> Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-5555 |
diff mbox series

Patch

diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
index 9bdadd716f4e..0aeff34e5ae1 100644
--- a/drivers/net/can/flexcan/flexcan-core.c
+++ b/drivers/net/can/flexcan/flexcan-core.c
@@ -345,6 +345,15 @@  static struct flexcan_devtype_data fsl_imx8mp_devtype_data = {
 		FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR,
 };
 
+static struct flexcan_devtype_data fsl_imx93_devtype_data = {
+	.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
+		FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_RX_MAILBOX |
+		FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_AUTO_STOP_MODE |
+		FLEXCAN_QUIRK_SUPPORT_FD | FLEXCAN_QUIRK_SUPPORT_ECC |
+		FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
+		FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR,
+};
+
 static const struct flexcan_devtype_data fsl_vf610_devtype_data = {
 	.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
 		FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_RX_MAILBOX |
@@ -532,9 +541,14 @@  static inline int flexcan_enter_stop_mode(struct flexcan_priv *priv)
 		ret = flexcan_stop_mode_enable_scfw(priv, true);
 		if (ret < 0)
 			return ret;
-	} else {
+	} else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR) {
 		regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
 				   1 << priv->stm.req_bit, 1 << priv->stm.req_bit);
+	} else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_AUTO_STOP_MODE) {
+		/* For the auto stop mode, software do nothing, hardware will cover
+		 * all the operation automatically after system go into low power mode.
+		 */
+		return 0;
 	}
 
 	return flexcan_low_power_enter_ack(priv);
@@ -551,7 +565,7 @@  static inline int flexcan_exit_stop_mode(struct flexcan_priv *priv)
 		ret = flexcan_stop_mode_enable_scfw(priv, false);
 		if (ret < 0)
 			return ret;
-	} else {
+	} else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR) {
 		regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
 				   1 << priv->stm.req_bit, 0);
 	}
@@ -560,6 +574,12 @@  static inline int flexcan_exit_stop_mode(struct flexcan_priv *priv)
 	reg_mcr &= ~FLEXCAN_MCR_SLF_WAK;
 	priv->write(reg_mcr, &regs->mcr);
 
+	/* For the auto stop mode, hardware will exist stop mode
+	 * automatically after system go out of low power mode.
+	 */
+	if (priv->devtype_data.quirks & FLEXCAN_QUIRK_AUTO_STOP_MODE)
+		return 0;
+
 	return flexcan_low_power_exit_ack(priv);
 }
 
@@ -1974,6 +1994,8 @@  static int flexcan_setup_stop_mode(struct platform_device *pdev)
 		ret = flexcan_setup_stop_mode_scfw(pdev);
 	else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR)
 		ret = flexcan_setup_stop_mode_gpr(pdev);
+	else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_AUTO_STOP_MODE)
+		ret = 0;
 	else
 		/* return 0 directly if doesn't support stop mode feature */
 		return 0;
@@ -1992,6 +2014,7 @@  static int flexcan_setup_stop_mode(struct platform_device *pdev)
 static const struct of_device_id flexcan_of_match[] = {
 	{ .compatible = "fsl,imx8qm-flexcan", .data = &fsl_imx8qm_devtype_data, },
 	{ .compatible = "fsl,imx8mp-flexcan", .data = &fsl_imx8mp_devtype_data, },
+	{ .compatible = "fsl,imx93-flexcan", .data = &fsl_imx93_devtype_data, },
 	{ .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, },
 	{ .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, },
 	{ .compatible = "fsl,imx53-flexcan", .data = &fsl_imx25_devtype_data, },
@@ -2299,8 +2322,16 @@  static int __maybe_unused flexcan_noirq_suspend(struct device *device)
 	if (netif_running(dev)) {
 		int err;
 
-		if (device_may_wakeup(device))
+		if (device_may_wakeup(device)) {
 			flexcan_enable_wakeup_irq(priv, true);
+			/* For auto stop mode, need to keep the clock on before
+			 * system go into low power mode. After system go into
+			 * low power mode, hardware will config the flexcan into
+			 * stop mode, and gate off the clock automatically.
+			 */
+			if (priv->devtype_data.quirks & FLEXCAN_QUIRK_AUTO_STOP_MODE)
+				return 0;
+		}
 
 		err = pm_runtime_force_suspend(device);
 		if (err)
diff --git a/drivers/net/can/flexcan/flexcan.h b/drivers/net/can/flexcan/flexcan.h
index 025c3417031f..91402977780b 100644
--- a/drivers/net/can/flexcan/flexcan.h
+++ b/drivers/net/can/flexcan/flexcan.h
@@ -68,6 +68,8 @@ 
 #define FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR BIT(15)
 /* Device supports RX via FIFO */
 #define FLEXCAN_QUIRK_SUPPORT_RX_FIFO BIT(16)
+/* auto enter stop mode to support wakeup */
+#define FLEXCAN_QUIRK_AUTO_STOP_MODE BIT(17)
 
 struct flexcan_devtype_data {
 	u32 quirks;		/* quirks needed for different IP cores */