diff mbox series

[v3] can: m_can: don't enable transceiver when probing

Message ID 20240530105801.3930087-1-martin@geanix.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series [v3] can: m_can: don't enable transceiver when probing | expand

Checks

Context Check Description
netdev/tree_selection success Series ignored based on subject

Commit Message

Martin Hundebøll May 30, 2024, 10:57 a.m. UTC
The m_can driver sets and clears the CCCR.INIT bit during probe (both
when testing the NON-ISO bit, and when configuring the chip). After
clearing the CCCR.INIT bit, the transceiver enters normal mode, where it
affects the CAN bus (i.e. it ACKs frames). This can cause troubles when
the m_can node is only used for monitoring the bus, as one cannot setup
listen-only mode before the device is probed.

Rework the probe flow, so that the CCCR.INIT bit is only cleared when
upping the device. First, the tcan4x5x driver is changed to stay in
standby mode during/after probe. This in turn requires changes when
setting bits in the CCCR register, as its CSR and CSA bits are always
high in standby mode.

Signed-off-by: Martin Hundebøll <martin@geanix.com>
---
 drivers/net/can/m_can/m_can.c         | 169 ++++++++++++++++----------
 drivers/net/can/m_can/tcan4x5x-core.c |  13 +-
 2 files changed, 116 insertions(+), 66 deletions(-)

Comments

kernel test robot May 30, 2024, 4:15 p.m. UTC | #1
Hi Martin,

kernel test robot noticed the following build warnings:

[auto build test WARNING on mkl-can-next/testing]
[also build test WARNING on linus/master v6.10-rc1 next-20240529]
[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/Martin-Hundeb-ll/can-m_can-don-t-enable-transceiver-when-probing/20240530-185906
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git testing
patch link:    https://lore.kernel.org/r/20240530105801.3930087-1-martin%40geanix.com
patch subject: [PATCH v3] can: m_can: don't enable transceiver when probing
config: i386-buildonly-randconfig-003-20240530 (https://download.01.org/0day-ci/archive/20240530/202405302307.MKjlGruk-lkp@intel.com/config)
compiler: clang version 18.1.5 (https://github.com/llvm/llvm-project 617a15a9eac96088ae5e9134248d8236e34b91b1)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240530/202405302307.MKjlGruk-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/202405302307.MKjlGruk-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/net/can/m_can/m_can.c:1725:11: warning: variable 'err' is uninitialized when used here [-Wuninitialized]
    1725 |                         return err;
         |                                ^~~
   drivers/net/can/m_can/m_can.c:1674:24: note: initialize the variable 'err' to silence this warning
    1674 |         int m_can_version, err, niso;
         |                               ^
         |                                = 0
   1 warning generated.


vim +/err +1725 drivers/net/can/m_can/m_can.c

  1670	
  1671	static int m_can_dev_setup(struct m_can_classdev *cdev)
  1672	{
  1673		struct net_device *dev = cdev->net;
  1674		int m_can_version, err, niso;
  1675	
  1676		m_can_version = m_can_check_core_release(cdev);
  1677		/* return if unsupported version */
  1678		if (!m_can_version) {
  1679			dev_err(cdev->dev, "Unsupported version number: %2d",
  1680				m_can_version);
  1681			return -EINVAL;
  1682		}
  1683	
  1684		if (!cdev->is_peripheral)
  1685			netif_napi_add(dev, &cdev->napi, m_can_poll);
  1686	
  1687		/* Shared properties of all M_CAN versions */
  1688		cdev->version = m_can_version;
  1689		cdev->can.do_set_mode = m_can_set_mode;
  1690		cdev->can.do_get_berr_counter = m_can_get_berr_counter;
  1691	
  1692		/* Set M_CAN supported operations */
  1693		cdev->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
  1694			CAN_CTRLMODE_LISTENONLY |
  1695			CAN_CTRLMODE_BERR_REPORTING |
  1696			CAN_CTRLMODE_FD |
  1697			CAN_CTRLMODE_ONE_SHOT;
  1698	
  1699		/* Set properties depending on M_CAN version */
  1700		switch (cdev->version) {
  1701		case 30:
  1702			/* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.0.x */
  1703			err = can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO);
  1704			if (err)
  1705				return err;
  1706			cdev->can.bittiming_const = &m_can_bittiming_const_30X;
  1707			cdev->can.data_bittiming_const = &m_can_data_bittiming_const_30X;
  1708			break;
  1709		case 31:
  1710			/* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.1.x */
  1711			err = can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO);
  1712			if (err)
  1713				return err;
  1714			cdev->can.bittiming_const = &m_can_bittiming_const_31X;
  1715			cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X;
  1716			break;
  1717		case 32:
  1718		case 33:
  1719			/* Support both MCAN version v3.2.x and v3.3.0 */
  1720			cdev->can.bittiming_const = &m_can_bittiming_const_31X;
  1721			cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X;
  1722	
  1723			niso = m_can_niso_supported(cdev);
  1724			if (niso < 0)
> 1725				return err;
  1726			if (niso)
  1727				cdev->can.ctrlmode_supported |= CAN_CTRLMODE_FD_NON_ISO;
  1728			break;
  1729		default:
  1730			dev_err(cdev->dev, "Unsupported version number: %2d",
  1731				cdev->version);
  1732			return -EINVAL;
  1733		}
  1734	
  1735		/* Forcing standby mode should be redunant, as the chip should be in
  1736		 * standby after a reset. Write the INIT bit anyways, should the chip
  1737		 * be configured by previous stage.
  1738		 */
  1739		return m_can_cccr_update_bits(cdev, CCCR_INIT, CCCR_INIT);
  1740	}
  1741
Simon Horman June 1, 2024, 1:10 p.m. UTC | #2
On Thu, May 30, 2024 at 12:57:58PM +0200, Martin Hundebøll wrote:
> The m_can driver sets and clears the CCCR.INIT bit during probe (both
> when testing the NON-ISO bit, and when configuring the chip). After
> clearing the CCCR.INIT bit, the transceiver enters normal mode, where it
> affects the CAN bus (i.e. it ACKs frames). This can cause troubles when
> the m_can node is only used for monitoring the bus, as one cannot setup
> listen-only mode before the device is probed.
> 
> Rework the probe flow, so that the CCCR.INIT bit is only cleared when
> upping the device. First, the tcan4x5x driver is changed to stay in
> standby mode during/after probe. This in turn requires changes when
> setting bits in the CCCR register, as its CSR and CSA bits are always
> high in standby mode.
> 
> Signed-off-by: Martin Hundebøll <martin@geanix.com>
> ---
>  drivers/net/can/m_can/m_can.c         | 169 ++++++++++++++++----------
>  drivers/net/can/m_can/tcan4x5x-core.c |  13 +-
>  2 files changed, 116 insertions(+), 66 deletions(-)
> 
> diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c

...

> @@ -1694,21 +1732,26 @@ static int m_can_dev_setup(struct m_can_classdev *cdev)
>  		return -EINVAL;
>  	}
>  
> -	if (cdev->ops->init)
> -		cdev->ops->init(cdev);
> -
> -	return 0;
> +	/* Forcing standby mode should be redunant, as the chip should be in

Hi Martin,

A minor nit from my side as it looks like there will be another revision
anyway.

redunant -> redundant

> +	 * standby after a reset. Write the INIT bit anyways, should the chip
> +	 * be configured by previous stage.
> +	 */
> +	return m_can_cccr_update_bits(cdev, CCCR_INIT, CCCR_INIT);
>  }

...
Dan Carpenter June 4, 2024, 9:44 a.m. UTC | #3
Hi Martin,

kernel test robot noticed the following build warnings:

https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Martin-Hundeb-ll/can-m_can-don-t-enable-transceiver-when-probing/20240530-185906
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git testing
patch link:    https://lore.kernel.org/r/20240530105801.3930087-1-martin%40geanix.com
patch subject: [PATCH v3] can: m_can: don't enable transceiver when probing
config: i386-randconfig-r081-20240603 (https://download.01.org/0day-ci/archive/20240603/202406031513.ByfTbHww-lkp@intel.com/config)
compiler: clang version 18.1.5 (https://github.com/llvm/llvm-project 617a15a9eac96088ae5e9134248d8236e34b91b1)

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>
| Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
| Closes: https://lore.kernel.org/r/202406031513.ByfTbHww-lkp@intel.com/

New smatch warnings:
drivers/net/can/m_can/m_can.c:1725 m_can_dev_setup() error: uninitialized symbol 'err'.

vim +/err +1725 drivers/net/can/m_can/m_can.c

3b464affd89821 Marc Kleine-Budde 2020-12-12  1671  static int m_can_dev_setup(struct m_can_classdev *cdev)
e0d1f4816f2a7e Dong Aisheng      2014-07-16  1672  {
3b464affd89821 Marc Kleine-Budde 2020-12-12  1673  	struct net_device *dev = cdev->net;
e96c73eab56aed Martin Hundebøll  2024-05-30  1674  	int m_can_version, err, niso;
e0d1f4816f2a7e Dong Aisheng      2014-07-16  1675  
3b464affd89821 Marc Kleine-Budde 2020-12-12  1676  	m_can_version = m_can_check_core_release(cdev);
b03cfc5bb0e11f Mario Huettel     2017-04-08  1677  	/* return if unsupported version */
b03cfc5bb0e11f Mario Huettel     2017-04-08  1678  	if (!m_can_version) {
3b464affd89821 Marc Kleine-Budde 2020-12-12  1679  		dev_err(cdev->dev, "Unsupported version number: %2d",
5e520edd91f0cd Faiz Abbas        2018-01-16  1680  			m_can_version);
5e520edd91f0cd Faiz Abbas        2018-01-16  1681  		return -EINVAL;
b03cfc5bb0e11f Mario Huettel     2017-04-08  1682  	}
b03cfc5bb0e11f Mario Huettel     2017-04-08  1683  
3b464affd89821 Marc Kleine-Budde 2020-12-12  1684  	if (!cdev->is_peripheral)
b48b89f9c189d2 Jakub Kicinski    2022-09-27  1685  		netif_napi_add(dev, &cdev->napi, m_can_poll);
e0d1f4816f2a7e Dong Aisheng      2014-07-16  1686  
b03cfc5bb0e11f Mario Huettel     2017-04-08  1687  	/* Shared properties of all M_CAN versions */
3b464affd89821 Marc Kleine-Budde 2020-12-12  1688  	cdev->version = m_can_version;
3b464affd89821 Marc Kleine-Budde 2020-12-12  1689  	cdev->can.do_set_mode = m_can_set_mode;
3b464affd89821 Marc Kleine-Budde 2020-12-12  1690  	cdev->can.do_get_berr_counter = m_can_get_berr_counter;
6cfda7fbebe8a4 Oliver Hartkopp   2015-01-05  1691  
b03cfc5bb0e11f Mario Huettel     2017-04-08  1692  	/* Set M_CAN supported operations */
3b464affd89821 Marc Kleine-Budde 2020-12-12  1693  	cdev->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
e0d1f4816f2a7e Dong Aisheng      2014-07-16  1694  		CAN_CTRLMODE_LISTENONLY |
80646733f11c2e Dong Aisheng      2014-11-18  1695  		CAN_CTRLMODE_BERR_REPORTING |
fb7d6a81c22017 Pankaj Sharma     2019-10-21  1696  		CAN_CTRLMODE_FD |
fb7d6a81c22017 Pankaj Sharma     2019-10-21  1697  		CAN_CTRLMODE_ONE_SHOT;
e0d1f4816f2a7e Dong Aisheng      2014-07-16  1698  
b03cfc5bb0e11f Mario Huettel     2017-04-08  1699  	/* Set properties depending on M_CAN version */
3b464affd89821 Marc Kleine-Budde 2020-12-12  1700  	switch (cdev->version) {
b03cfc5bb0e11f Mario Huettel     2017-04-08  1701  	case 30:
b03cfc5bb0e11f Mario Huettel     2017-04-08  1702  		/* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.0.x */
7d4a101c0bd3c6 Vincent Mailhol   2021-12-14  1703  		err = can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO);
7d4a101c0bd3c6 Vincent Mailhol   2021-12-14  1704  		if (err)
7d4a101c0bd3c6 Vincent Mailhol   2021-12-14  1705  			return err;
d6da7881020f9b Jarkko Nikula     2022-05-12  1706  		cdev->can.bittiming_const = &m_can_bittiming_const_30X;
d6da7881020f9b Jarkko Nikula     2022-05-12  1707  		cdev->can.data_bittiming_const = &m_can_data_bittiming_const_30X;
b03cfc5bb0e11f Mario Huettel     2017-04-08  1708  		break;
b03cfc5bb0e11f Mario Huettel     2017-04-08  1709  	case 31:
b03cfc5bb0e11f Mario Huettel     2017-04-08  1710  		/* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.1.x */
7d4a101c0bd3c6 Vincent Mailhol   2021-12-14  1711  		err = can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO);
7d4a101c0bd3c6 Vincent Mailhol   2021-12-14  1712  		if (err)
7d4a101c0bd3c6 Vincent Mailhol   2021-12-14  1713  			return err;
d6da7881020f9b Jarkko Nikula     2022-05-12  1714  		cdev->can.bittiming_const = &m_can_bittiming_const_31X;
d6da7881020f9b Jarkko Nikula     2022-05-12  1715  		cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X;
b03cfc5bb0e11f Mario Huettel     2017-04-08  1716  		break;
b03cfc5bb0e11f Mario Huettel     2017-04-08  1717  	case 32:
5c7d55bded77da Pankaj Sharma     2020-11-26  1718  	case 33:
5c7d55bded77da Pankaj Sharma     2020-11-26  1719  		/* Support both MCAN version v3.2.x and v3.3.0 */
d6da7881020f9b Jarkko Nikula     2022-05-12  1720  		cdev->can.bittiming_const = &m_can_bittiming_const_31X;
d6da7881020f9b Jarkko Nikula     2022-05-12  1721  		cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X;
f524f829b75a7d Dan Murphy        2019-05-09  1722  
e96c73eab56aed Martin Hundebøll  2024-05-30  1723  		niso = m_can_niso_supported(cdev);
e96c73eab56aed Martin Hundebøll  2024-05-30  1724  		if (niso < 0)
e96c73eab56aed Martin Hundebøll  2024-05-30 @1725  			return err;

s/err/niso/

e96c73eab56aed Martin Hundebøll  2024-05-30  1726  		if (niso)
e96c73eab56aed Martin Hundebøll  2024-05-30  1727  			cdev->can.ctrlmode_supported |= CAN_CTRLMODE_FD_NON_ISO;
b03cfc5bb0e11f Mario Huettel     2017-04-08  1728  		break;
b03cfc5bb0e11f Mario Huettel     2017-04-08  1729  	default:
3b464affd89821 Marc Kleine-Budde 2020-12-12  1730  		dev_err(cdev->dev, "Unsupported version number: %2d",
3b464affd89821 Marc Kleine-Budde 2020-12-12  1731  			cdev->version);
5e520edd91f0cd Faiz Abbas        2018-01-16  1732  		return -EINVAL;
b03cfc5bb0e11f Mario Huettel     2017-04-08  1733  	}
b03cfc5bb0e11f Mario Huettel     2017-04-08  1734  
e96c73eab56aed Martin Hundebøll  2024-05-30  1735  	/* Forcing standby mode should be redunant, as the chip should be in
e96c73eab56aed Martin Hundebøll  2024-05-30  1736  	 * standby after a reset. Write the INIT bit anyways, should the chip
e96c73eab56aed Martin Hundebøll  2024-05-30  1737  	 * be configured by previous stage.
e96c73eab56aed Martin Hundebøll  2024-05-30  1738  	 */
e96c73eab56aed Martin Hundebøll  2024-05-30  1739  	return m_can_cccr_update_bits(cdev, CCCR_INIT, CCCR_INIT);
e0d1f4816f2a7e Dong Aisheng      2014-07-16  1740  }
diff mbox series

Patch

diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index 14b231c4d7ec..0f74ab249b35 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -379,38 +379,72 @@  m_can_txe_fifo_read(struct m_can_classdev *cdev, u32 fgi, u32 offset, u32 *val)
 	return cdev->ops->read_fifo(cdev, addr_offset, val, 1);
 }
 
-static void m_can_config_endisable(struct m_can_classdev *cdev, bool enable)
+static int m_can_cccr_update_bits(struct m_can_classdev *cdev, u32 mask, u32 val)
 {
-	u32 cccr = m_can_read(cdev, M_CAN_CCCR);
-	u32 timeout = 10;
-	u32 val = 0;
-
-	/* Clear the Clock stop request if it was set */
-	if (cccr & CCCR_CSR)
-		cccr &= ~CCCR_CSR;
-
-	if (enable) {
-		/* enable m_can configuration */
-		m_can_write(cdev, M_CAN_CCCR, cccr | CCCR_INIT);
-		udelay(5);
-		/* CCCR.CCE can only be set/reset while CCCR.INIT = '1' */
-		m_can_write(cdev, M_CAN_CCCR, cccr | CCCR_INIT | CCCR_CCE);
-	} else {
-		m_can_write(cdev, M_CAN_CCCR, cccr & ~(CCCR_INIT | CCCR_CCE));
+	u32 val_before = m_can_read(cdev, M_CAN_CCCR);
+	u32 val_after = (val_before & ~mask) | val;
+	size_t tries = 10;
+
+	if (!(mask & CCCR_INIT) && !(val_before & CCCR_INIT)) {
+		dev_err(cdev->dev,
+			"refusing to configure device when in normal mode\n");
+		return -EBUSY;
 	}
 
-	/* there's a delay for module initialization */
-	if (enable)
-		val = CCCR_INIT | CCCR_CCE;
-
-	while ((m_can_read(cdev, M_CAN_CCCR) & (CCCR_INIT | CCCR_CCE)) != val) {
-		if (timeout == 0) {
-			netdev_warn(cdev->net, "Failed to init module\n");
-			return;
-		}
-		timeout--;
-		udelay(1);
+	/* The chip should be in standby mode when changing the CCCR register,
+	 * and some chips set the CSR and CSA bits when in standby. Furthermore,
+	 * the CSR and CSA bits should be written as zeros, even when they read
+	 * ones.
+	 */
+	val_after &= ~(CCCR_CSR | CCCR_CSA);
+
+	while (tries--) {
+		u32 val_read;
+
+		/* Write the desired value in each try, as setting some bits in
+		 * the CCCR register require other bits to be set first. E.g.
+		 * setting the NISO bit requires setting the CCE bit first.
+		 */
+		m_can_write(cdev, M_CAN_CCCR, val_after);
+
+		val_read = m_can_read(cdev, M_CAN_CCCR) & ~(CCCR_CSR | CCCR_CSA);
+
+		if (val_read == val_after)
+			return 0;
+
+		usleep_range(1, 5);
 	}
+
+	return -ETIMEDOUT;
+}
+
+static int m_can_config_enable(struct m_can_classdev *cdev)
+{
+	int err;
+
+	/* CCCR_INIT must be set in order to set CCCR_CCE, but access to
+	 * configuration registers should only be enabled when in standby mode,
+	 * where CCCR_INIT is always set.
+	 */
+	err = m_can_cccr_update_bits(cdev, CCCR_CCE, CCCR_CCE);
+	if (err)
+		netdev_err(cdev->net, "failed to enable configuration mode\n");
+
+	return err;
+}
+
+static int m_can_config_disable(struct m_can_classdev *cdev)
+{
+	int err;
+
+	/* Only clear CCCR_CCE, since CCCR_INIT cannot be cleared while in
+	 * standby mode
+	 */
+	err = m_can_cccr_update_bits(cdev, CCCR_CCE, 0);
+	if (err)
+		netdev_err(cdev->net, "failed to disable configuration registers\n");
+
+	return err;
 }
 
 static void m_can_interrupt_enable(struct m_can_classdev *cdev, u32 interrupts)
@@ -1403,7 +1437,9 @@  static int m_can_chip_config(struct net_device *dev)
 	interrupts &= ~(IR_ARA | IR_ELO | IR_DRX | IR_TEFF | IR_TFE | IR_TCF |
 			IR_HPM | IR_RF1F | IR_RF1W | IR_RF1N | IR_RF0F);
 
-	m_can_config_endisable(cdev, true);
+	err = m_can_config_enable(cdev);
+	if (err)
+		return err;
 
 	/* RX Buffer/FIFO Element Size 64 bytes data field */
 	m_can_write(cdev, M_CAN_RXESC,
@@ -1521,7 +1557,9 @@  static int m_can_chip_config(struct net_device *dev)
 		    FIELD_PREP(TSCC_TCP_MASK, 0xf) |
 		    FIELD_PREP(TSCC_TSS_MASK, TSCC_TSS_INTERNAL));
 
-	m_can_config_endisable(cdev, false);
+	err = m_can_config_disable(cdev);
+	if (err)
+		return err;
 
 	if (cdev->ops->init)
 		cdev->ops->init(cdev);
@@ -1550,7 +1588,11 @@  static int m_can_start(struct net_device *dev)
 		cdev->tx_fifo_putidx = FIELD_GET(TXFQS_TFQPI_MASK,
 						 m_can_read(cdev, M_CAN_TXFQS));
 
-	return 0;
+	ret = m_can_cccr_update_bits(cdev, CCCR_INIT, 0);
+	if (ret)
+		netdev_err(dev, "failed to enter normal mode\n");
+
+	return ret;
 }
 
 static int m_can_set_mode(struct net_device *dev, enum can_mode mode)
@@ -1599,43 +1641,37 @@  static int m_can_check_core_release(struct m_can_classdev *cdev)
 }
 
 /* Selectable Non ISO support only in version 3.2.x
- * This function checks if the bit is writable.
+ * Return 1 if the bit is writable, 0 if it is not, or negative on error.
  */
-static bool m_can_niso_supported(struct m_can_classdev *cdev)
+static int m_can_niso_supported(struct m_can_classdev *cdev)
 {
-	u32 cccr_reg, cccr_poll = 0;
-	int niso_timeout = -ETIMEDOUT;
-	int i;
+	int ret, niso;
 
-	m_can_config_endisable(cdev, true);
-	cccr_reg = m_can_read(cdev, M_CAN_CCCR);
-	cccr_reg |= CCCR_NISO;
-	m_can_write(cdev, M_CAN_CCCR, cccr_reg);
+	ret = m_can_config_enable(cdev);
+	if (ret)
+		return ret;
 
-	for (i = 0; i <= 10; i++) {
-		cccr_poll = m_can_read(cdev, M_CAN_CCCR);
-		if (cccr_poll == cccr_reg) {
-			niso_timeout = 0;
-			break;
-		}
+	/* First try to set the NISO bit. */
+	niso = m_can_cccr_update_bits(cdev, CCCR_NISO, CCCR_NISO);
 
-		usleep_range(1, 5);
+	/* Then clear the it again. */
+	ret = m_can_cccr_update_bits(cdev, CCCR_NISO, 0);
+	if (ret) {
+		dev_err(cdev->dev, "failed to revert the NON-ISO bit in CCCR\n");
+		return ret;
 	}
 
-	/* Clear NISO */
-	cccr_reg &= ~(CCCR_NISO);
-	m_can_write(cdev, M_CAN_CCCR, cccr_reg);
+	ret = m_can_config_disable(cdev);
+	if (ret)
+		return ret;
 
-	m_can_config_endisable(cdev, false);
-
-	/* return false if time out (-ETIMEDOUT), else return true */
-	return !niso_timeout;
+	return niso == 0;
 }
 
 static int m_can_dev_setup(struct m_can_classdev *cdev)
 {
 	struct net_device *dev = cdev->net;
-	int m_can_version, err;
+	int m_can_version, err, niso;
 
 	m_can_version = m_can_check_core_release(cdev);
 	/* return if unsupported version */
@@ -1684,9 +1720,11 @@  static int m_can_dev_setup(struct m_can_classdev *cdev)
 		cdev->can.bittiming_const = &m_can_bittiming_const_31X;
 		cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X;
 
-		cdev->can.ctrlmode_supported |=
-			(m_can_niso_supported(cdev) ?
-			 CAN_CTRLMODE_FD_NON_ISO : 0);
+		niso = m_can_niso_supported(cdev);
+		if (niso < 0)
+			return err;
+		if (niso)
+			cdev->can.ctrlmode_supported |= CAN_CTRLMODE_FD_NON_ISO;
 		break;
 	default:
 		dev_err(cdev->dev, "Unsupported version number: %2d",
@@ -1694,21 +1732,26 @@  static int m_can_dev_setup(struct m_can_classdev *cdev)
 		return -EINVAL;
 	}
 
-	if (cdev->ops->init)
-		cdev->ops->init(cdev);
-
-	return 0;
+	/* Forcing standby mode should be redunant, as the chip should be in
+	 * standby after a reset. Write the INIT bit anyways, should the chip
+	 * be configured by previous stage.
+	 */
+	return m_can_cccr_update_bits(cdev, CCCR_INIT, CCCR_INIT);
 }
 
 static void m_can_stop(struct net_device *dev)
 {
 	struct m_can_classdev *cdev = netdev_priv(dev);
+	int ret;
 
 	/* disable all interrupts */
 	m_can_disable_all_interrupts(cdev);
 
 	/* Set init mode to disengage from the network */
-	m_can_config_endisable(cdev, true);
+	ret = m_can_cccr_update_bits(cdev, CCCR_INIT, CCCR_INIT);
+	if (ret)
+		netdev_err(dev, "failed to enter standby mode: %pe\n",
+			   ERR_PTR(ret));
 
 	/* set the state as STOPPED */
 	cdev->can.state = CAN_STATE_STOPPED;
diff --git a/drivers/net/can/m_can/tcan4x5x-core.c b/drivers/net/can/m_can/tcan4x5x-core.c
index a42600dac70d..d723206ac7c9 100644
--- a/drivers/net/can/m_can/tcan4x5x-core.c
+++ b/drivers/net/can/m_can/tcan4x5x-core.c
@@ -453,10 +453,17 @@  static int tcan4x5x_can_probe(struct spi_device *spi)
 		goto out_power;
 	}
 
-	ret = tcan4x5x_init(mcan_class);
+	tcan4x5x_check_wake(priv);
+
+	ret = tcan4x5x_write_tcan_reg(mcan_class, TCAN4X5X_INT_EN, 0);
 	if (ret) {
-		dev_err(&spi->dev, "tcan initialization failed %pe\n",
-			ERR_PTR(ret));
+		dev_err(&spi->dev, "Disabling interrupts failed %pe\n", ERR_PTR(ret));
+		goto out_power;
+	}
+
+	ret = tcan4x5x_clear_interrupts(mcan_class);
+	if (ret) {
+		dev_err(&spi->dev, "Clearing interrupts failed %pe\n", ERR_PTR(ret));
 		goto out_power;
 	}