Skip to content

Commit 5b512f4

Browse files
Haibo Chenmarckleinebudde
authored andcommitted
can: flexcan: add wakeup support for imx95
iMX95 defines a bit in GPR that sets/unsets the IPG_STOP signal to the FlexCAN module, controlling its entry into STOP mode. Wakeup should work even if FlexCAN is in STOP mode. Due to iMX95 architecture design, the A-Core cannot access GPR; only the system manager (SM) can configure GPR. To support the wakeup feature, follow these steps: - For suspend: 1) During Linux suspend, when CAN suspends, do nothing for GPR and keep CAN-related clocks on. 2) In ATF, check whether CAN needs to support wakeup; if yes, send a request to SM through the SCMI protocol. 3) In SM, configure the GPR and unset IPG_STOP. 4) A-Core suspends. - For wakeup and resume: 1) A-Core wakeup event arrives. 2) In SM, deassert IPG_STOP. 3) Linux resumes. Add a new fsl_imx95_devtype_data and FLEXCAN_QUIRK_SETUP_STOP_MODE_SCMI to reflect this. Reviewed-by: Han Xu <[email protected]> Signed-off-by: Haibo Chen <[email protected]> Reviewed-by: Vincent Mailhol <[email protected]> Signed-off-by: Frank Li <[email protected]> Link: https://lore.kernel.org/all/[email protected] Signed-off-by: Marc Kleine-Budde <[email protected]>
1 parent 3eea16b commit 5b512f4

File tree

2 files changed

+45
-7
lines changed

2 files changed

+45
-7
lines changed

drivers/net/can/flexcan/flexcan-core.c

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,14 @@ static struct flexcan_devtype_data fsl_imx93_devtype_data = {
354354
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR,
355355
};
356356

357+
static const struct flexcan_devtype_data fsl_imx95_devtype_data = {
358+
.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
359+
FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_RX_MAILBOX |
360+
FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_SUPPORT_FD |
361+
FLEXCAN_QUIRK_SUPPORT_ECC | FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
362+
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR | FLEXCAN_QUIRK_SETUP_STOP_MODE_SCMI,
363+
};
364+
357365
static const struct flexcan_devtype_data fsl_vf610_devtype_data = {
358366
.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
359367
FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_RX_MAILBOX |
@@ -544,6 +552,13 @@ static inline int flexcan_enter_stop_mode(struct flexcan_priv *priv)
544552
} else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR) {
545553
regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
546554
1 << priv->stm.req_bit, 1 << priv->stm.req_bit);
555+
} else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCMI) {
556+
/* For the SCMI mode, driver do nothing, ATF will send request to
557+
* SM(system manager, M33 core) through SCMI protocol after linux
558+
* suspend. Once SM get this request, it will send IPG_STOP signal
559+
* to Flex_CAN, let CAN in STOP mode.
560+
*/
561+
return 0;
547562
}
548563

549564
return flexcan_low_power_enter_ack(priv);
@@ -555,7 +570,11 @@ static inline int flexcan_exit_stop_mode(struct flexcan_priv *priv)
555570
u32 reg_mcr;
556571
int ret;
557572

558-
/* remove stop request */
573+
/* Remove stop request, for FLEXCAN_QUIRK_SETUP_STOP_MODE_SCMI,
574+
* do nothing here, because ATF already send request to SM before
575+
* linux resume. Once SM get this request, it will deassert the
576+
* IPG_STOP signal to Flex_CAN.
577+
*/
559578
if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW) {
560579
ret = flexcan_stop_mode_enable_scfw(priv, false);
561580
if (ret < 0)
@@ -1983,6 +2002,9 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev)
19832002
ret = flexcan_setup_stop_mode_scfw(pdev);
19842003
else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR)
19852004
ret = flexcan_setup_stop_mode_gpr(pdev);
2005+
else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCMI)
2006+
/* ATF will handle all STOP_IPG related work */
2007+
ret = 0;
19862008
else
19872009
/* return 0 directly if doesn't support stop mode feature */
19882010
return 0;
@@ -2009,6 +2031,7 @@ static const struct of_device_id flexcan_of_match[] = {
20092031
{ .compatible = "fsl,imx8qm-flexcan", .data = &fsl_imx8qm_devtype_data, },
20102032
{ .compatible = "fsl,imx8mp-flexcan", .data = &fsl_imx8mp_devtype_data, },
20112033
{ .compatible = "fsl,imx93-flexcan", .data = &fsl_imx93_devtype_data, },
2034+
{ .compatible = "fsl,imx95-flexcan", .data = &fsl_imx95_devtype_data, },
20122035
{ .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, },
20132036
{ .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, },
20142037
{ .compatible = "fsl,imx53-flexcan", .data = &fsl_imx25_devtype_data, },
@@ -2309,9 +2332,19 @@ static int __maybe_unused flexcan_noirq_suspend(struct device *device)
23092332
if (device_may_wakeup(device))
23102333
flexcan_enable_wakeup_irq(priv, true);
23112334

2312-
err = pm_runtime_force_suspend(device);
2313-
if (err)
2314-
return err;
2335+
/* For FLEXCAN_QUIRK_SETUP_STOP_MODE_SCMI, it need ATF to send
2336+
* to SM through SCMI protocol, SM will assert the IPG_STOP
2337+
* signal. But all this works need the CAN clocks keep on.
2338+
* After the CAN module get the IPG_STOP mode, and switch to
2339+
* STOP mode, whether still keep the CAN clocks on or gate them
2340+
* off depend on the Hardware design.
2341+
*/
2342+
if (!(device_may_wakeup(device) &&
2343+
priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCMI)) {
2344+
err = pm_runtime_force_suspend(device);
2345+
if (err)
2346+
return err;
2347+
}
23152348
}
23162349

23172350
return 0;
@@ -2325,9 +2358,12 @@ static int __maybe_unused flexcan_noirq_resume(struct device *device)
23252358
if (netif_running(dev)) {
23262359
int err;
23272360

2328-
err = pm_runtime_force_resume(device);
2329-
if (err)
2330-
return err;
2361+
if (!(device_may_wakeup(device) &&
2362+
priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCMI)) {
2363+
err = pm_runtime_force_resume(device);
2364+
if (err)
2365+
return err;
2366+
}
23312367

23322368
if (device_may_wakeup(device))
23332369
flexcan_enable_wakeup_irq(priv, false);

drivers/net/can/flexcan/flexcan.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@
6868
#define FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR BIT(15)
6969
/* Device supports RX via FIFO */
7070
#define FLEXCAN_QUIRK_SUPPORT_RX_FIFO BIT(16)
71+
/* Setup stop mode with ATF SCMI protocol to support wakeup */
72+
#define FLEXCAN_QUIRK_SETUP_STOP_MODE_SCMI BIT(17)
7173

7274
struct flexcan_devtype_data {
7375
u32 quirks; /* quirks needed for different IP cores */

0 commit comments

Comments
 (0)