* [PATCH net-next 0/11] pull-request: can-next 2025-11-12
@ 2025-11-12 9:13 Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 01/11] can: convert generic HW timestamp ioctl to ndo_hwtstamp callbacks Marc Kleine-Budde
` (11 more replies)
0 siblings, 12 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2025-11-12 9:13 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, linux-can, kernel
Hello netdev-team,
this is a pull request of 11 patches for net-next/main.
The first 3 patches are by Vadim Fedorenko and convert the CAN drivers
to use the ndo_hwtstamp callbacks.
Maud Spierings contributes a patch to the mcp251x driver that converts
it to use dev_err_probe()
The remaining patches target the mcp251xfd driver and are by Gregor
Herburger and me. They add GPIO controller functionality to the
driver.
regards,
Marc
---
The following changes since commit ea7d0d60ebc9bddf3ad768557dfa1495bc032bf6:
Merge branch 'add-cn20k-nix-and-npa-contexts' (2025-10-30 10:44:12 +0100)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git tags/linux-can-next-for-6.19-20251112
for you to fetch changes up to 5bce93417a62b1da306a33f1e7ebb12bc915a80e:
can: bxcan: Fix a typo error for assign (2025-11-12 09:48:07 +0100)
----------------------------------------------------------------
linux-can-next-for-6.19-20251112
----------------------------------------------------------------
Chu Guangqing (1):
can: bxcan: Fix a typo error for assign
Gregor Herburger (5):
can: mcp251xfd: utilize gather_write function for all non-CRC writes
can: mcp251xfd: add workaround for errata 5
can: mcp251xfd: only configure PIN1 when rx_int is set
can: mcp251xfd: add gpio functionality
dt-bindings: can: mcp251xfd: add gpio-controller property
Marc Kleine-Budde (3):
Merge patch series "convert can drivers to use ndo_hwtstamp callbacks"
can: mcp251xfd: move chip sleep mode into runtime pm
Merge patch series "can: mcp251xfd: add gpio functionality"
Maud Spierings (1):
can: mcp251x: mcp251x_can_probe(): use dev_err_probe()
Vadim Fedorenko (3):
can: convert generic HW timestamp ioctl to ndo_hwtstamp callbacks
can: peak_canfd: convert to use ndo_hwtstamp callbacks
can: peak_usb: convert to use ndo_hwtstamp callbacks
.../bindings/net/can/microchip,mcp251xfd.yaml | 5 +
drivers/net/can/bxcan.c | 2 +-
drivers/net/can/dev/dev.c | 45 ++--
drivers/net/can/esd/esd_402_pci-core.c | 3 +-
drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c | 3 +-
drivers/net/can/peak_canfd/peak_canfd.c | 35 ++-
drivers/net/can/spi/mcp251x.c | 31 ++-
drivers/net/can/spi/mcp251xfd/Kconfig | 1 +
drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c | 284 +++++++++++++++++----
drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c | 114 +++++++--
drivers/net/can/spi/mcp251xfd/mcp251xfd.h | 8 +
drivers/net/can/usb/etas_es58x/es58x_core.c | 3 +-
drivers/net/can/usb/gs_usb.c | 20 +-
drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c | 3 +-
drivers/net/can/usb/peak_usb/pcan_usb_core.c | 35 ++-
include/linux/can/dev.h | 6 +-
16 files changed, 446 insertions(+), 152 deletions(-)
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH net-next 01/11] can: convert generic HW timestamp ioctl to ndo_hwtstamp callbacks
2025-11-12 9:13 [PATCH net-next 0/11] pull-request: can-next 2025-11-12 Marc Kleine-Budde
@ 2025-11-12 9:13 ` Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 02/11] can: peak_canfd: convert to use " Marc Kleine-Budde
` (10 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2025-11-12 9:13 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Vadim Fedorenko, Kory Maincent,
Vincent Mailhol, Marc Kleine-Budde
From: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Can has generic implementation of ndo_eth_ioctl which implements only HW
timestamping commands. Implement generic ndo_hwtstamp callbacks and use
it in drivers instead of generic ioctl interface.
Signed-off-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Reviewed-by: Kory Maincent <kory.maincent@bootlin.com>
Reviewed-by: Vincent Mailhol <mailhol@kernel.org>
Link: https://patch.msgid.link/20251029231620.1135640-2-vadim.fedorenko@linux.dev
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
drivers/net/can/dev/dev.c | 45 +++++++++----------
drivers/net/can/esd/esd_402_pci-core.c | 3 +-
.../can/kvaser_pciefd/kvaser_pciefd_core.c | 3 +-
.../net/can/spi/mcp251xfd/mcp251xfd-core.c | 3 +-
drivers/net/can/usb/etas_es58x/es58x_core.c | 3 +-
drivers/net/can/usb/gs_usb.c | 20 +++++++--
.../net/can/usb/kvaser_usb/kvaser_usb_core.c | 3 +-
include/linux/can/dev.h | 6 ++-
8 files changed, 54 insertions(+), 32 deletions(-)
diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c
index 0cc3d008adb3..80e1ab18de87 100644
--- a/drivers/net/can/dev/dev.c
+++ b/drivers/net/can/dev/dev.c
@@ -379,34 +379,33 @@ int can_set_static_ctrlmode(struct net_device *dev, u32 static_mode)
}
EXPORT_SYMBOL_GPL(can_set_static_ctrlmode);
-/* generic implementation of netdev_ops::ndo_eth_ioctl for CAN devices
+/* generic implementation of netdev_ops::ndo_hwtstamp_get for CAN devices
* supporting hardware timestamps
*/
-int can_eth_ioctl_hwts(struct net_device *netdev, struct ifreq *ifr, int cmd)
+int can_hwtstamp_get(struct net_device *netdev,
+ struct kernel_hwtstamp_config *cfg)
{
- struct hwtstamp_config hwts_cfg = { 0 };
+ cfg->tx_type = HWTSTAMP_TX_ON;
+ cfg->rx_filter = HWTSTAMP_FILTER_ALL;
- switch (cmd) {
- case SIOCSHWTSTAMP: /* set */
- if (copy_from_user(&hwts_cfg, ifr->ifr_data, sizeof(hwts_cfg)))
- return -EFAULT;
- if (hwts_cfg.tx_type == HWTSTAMP_TX_ON &&
- hwts_cfg.rx_filter == HWTSTAMP_FILTER_ALL)
- return 0;
- return -ERANGE;
-
- case SIOCGHWTSTAMP: /* get */
- hwts_cfg.tx_type = HWTSTAMP_TX_ON;
- hwts_cfg.rx_filter = HWTSTAMP_FILTER_ALL;
- if (copy_to_user(ifr->ifr_data, &hwts_cfg, sizeof(hwts_cfg)))
- return -EFAULT;
- return 0;
-
- default:
- return -EOPNOTSUPP;
- }
+ return 0;
}
-EXPORT_SYMBOL(can_eth_ioctl_hwts);
+EXPORT_SYMBOL(can_hwtstamp_get);
+
+/* generic implementation of netdev_ops::ndo_hwtstamp_set for CAN devices
+ * supporting hardware timestamps
+ */
+int can_hwtstamp_set(struct net_device *netdev,
+ struct kernel_hwtstamp_config *cfg,
+ struct netlink_ext_ack *extack)
+{
+ if (cfg->tx_type == HWTSTAMP_TX_ON &&
+ cfg->rx_filter == HWTSTAMP_FILTER_ALL)
+ return 0;
+ NL_SET_ERR_MSG_MOD(extack, "Only TX on and RX all packets filter supported");
+ return -ERANGE;
+}
+EXPORT_SYMBOL(can_hwtstamp_set);
/* generic implementation of ethtool_ops::get_ts_info for CAN devices
* supporting hardware timestamps
diff --git a/drivers/net/can/esd/esd_402_pci-core.c b/drivers/net/can/esd/esd_402_pci-core.c
index 05adecae6375..c826f00c551b 100644
--- a/drivers/net/can/esd/esd_402_pci-core.c
+++ b/drivers/net/can/esd/esd_402_pci-core.c
@@ -86,7 +86,8 @@ static const struct net_device_ops pci402_acc_netdev_ops = {
.ndo_open = acc_open,
.ndo_stop = acc_close,
.ndo_start_xmit = acc_start_xmit,
- .ndo_eth_ioctl = can_eth_ioctl_hwts,
+ .ndo_hwtstamp_get = can_hwtstamp_get,
+ .ndo_hwtstamp_set = can_hwtstamp_set,
};
static const struct ethtool_ops pci402_acc_ethtool_ops = {
diff --git a/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c b/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c
index 705f9bb74cd2..d8c9bfb20230 100644
--- a/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c
+++ b/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c
@@ -902,8 +902,9 @@ static void kvaser_pciefd_bec_poll_timer(struct timer_list *data)
static const struct net_device_ops kvaser_pciefd_netdev_ops = {
.ndo_open = kvaser_pciefd_open,
.ndo_stop = kvaser_pciefd_stop,
- .ndo_eth_ioctl = can_eth_ioctl_hwts,
.ndo_start_xmit = kvaser_pciefd_start_xmit,
+ .ndo_hwtstamp_get = can_hwtstamp_get,
+ .ndo_hwtstamp_set = can_hwtstamp_set,
};
static int kvaser_pciefd_set_phys_id(struct net_device *netdev,
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
index 9402530ba3d4..c0f9d9fed02e 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
@@ -1714,7 +1714,8 @@ static const struct net_device_ops mcp251xfd_netdev_ops = {
.ndo_open = mcp251xfd_open,
.ndo_stop = mcp251xfd_stop,
.ndo_start_xmit = mcp251xfd_start_xmit,
- .ndo_eth_ioctl = can_eth_ioctl_hwts,
+ .ndo_hwtstamp_get = can_hwtstamp_get,
+ .ndo_hwtstamp_set = can_hwtstamp_set,
};
static void
diff --git a/drivers/net/can/usb/etas_es58x/es58x_core.c b/drivers/net/can/usb/etas_es58x/es58x_core.c
index 47d9e03f3044..f799233c2b72 100644
--- a/drivers/net/can/usb/etas_es58x/es58x_core.c
+++ b/drivers/net/can/usb/etas_es58x/es58x_core.c
@@ -1976,7 +1976,8 @@ static const struct net_device_ops es58x_netdev_ops = {
.ndo_open = es58x_open,
.ndo_stop = es58x_stop,
.ndo_start_xmit = es58x_start_xmit,
- .ndo_eth_ioctl = can_eth_ioctl_hwts,
+ .ndo_hwtstamp_get = can_hwtstamp_get,
+ .ndo_hwtstamp_set = can_hwtstamp_set,
};
static const struct ethtool_ops es58x_ethtool_ops = {
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index 30608901a974..1321eb5e89ae 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -1087,12 +1087,25 @@ static int gs_can_close(struct net_device *netdev)
return 0;
}
-static int gs_can_eth_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+static int gs_can_hwtstamp_get(struct net_device *netdev,
+ struct kernel_hwtstamp_config *cfg)
{
const struct gs_can *dev = netdev_priv(netdev);
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
- return can_eth_ioctl_hwts(netdev, ifr, cmd);
+ return can_hwtstamp_get(netdev, cfg);
+
+ return -EOPNOTSUPP;
+}
+
+static int gs_can_hwtstamp_set(struct net_device *netdev,
+ struct kernel_hwtstamp_config *cfg,
+ struct netlink_ext_ack *extack)
+{
+ const struct gs_can *dev = netdev_priv(netdev);
+
+ if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
+ return can_hwtstamp_set(netdev, cfg, extack);
return -EOPNOTSUPP;
}
@@ -1101,7 +1114,8 @@ static const struct net_device_ops gs_usb_netdev_ops = {
.ndo_open = gs_can_open,
.ndo_stop = gs_can_close,
.ndo_start_xmit = gs_can_start_xmit,
- .ndo_eth_ioctl = gs_can_eth_ioctl,
+ .ndo_hwtstamp_get = gs_can_hwtstamp_get,
+ .ndo_hwtstamp_set = gs_can_hwtstamp_set,
};
static int gs_usb_set_identify(struct net_device *netdev, bool do_identify)
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
index 89e22b66f919..62701ec34272 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
@@ -784,8 +784,9 @@ static int kvaser_usb_set_phys_id(struct net_device *netdev,
static const struct net_device_ops kvaser_usb_netdev_ops = {
.ndo_open = kvaser_usb_open,
.ndo_stop = kvaser_usb_close,
- .ndo_eth_ioctl = can_eth_ioctl_hwts,
.ndo_start_xmit = kvaser_usb_start_xmit,
+ .ndo_hwtstamp_get = can_hwtstamp_get,
+ .ndo_hwtstamp_set = can_hwtstamp_set,
};
static const struct ethtool_ops kvaser_usb_ethtool_ops = {
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 0fe8f80f223e..bd7410b5d8a6 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -129,7 +129,11 @@ void close_candev(struct net_device *dev);
void can_set_default_mtu(struct net_device *dev);
int __must_check can_set_static_ctrlmode(struct net_device *dev,
u32 static_mode);
-int can_eth_ioctl_hwts(struct net_device *netdev, struct ifreq *ifr, int cmd);
+int can_hwtstamp_get(struct net_device *netdev,
+ struct kernel_hwtstamp_config *cfg);
+int can_hwtstamp_set(struct net_device *netdev,
+ struct kernel_hwtstamp_config *cfg,
+ struct netlink_ext_ack *extack);
int can_ethtool_op_get_ts_info_hwts(struct net_device *dev,
struct kernel_ethtool_ts_info *info);
base-commit: ea7d0d60ebc9bddf3ad768557dfa1495bc032bf6
--
2.51.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH net-next 02/11] can: peak_canfd: convert to use ndo_hwtstamp callbacks
2025-11-12 9:13 [PATCH net-next 0/11] pull-request: can-next 2025-11-12 Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 01/11] can: convert generic HW timestamp ioctl to ndo_hwtstamp callbacks Marc Kleine-Budde
@ 2025-11-12 9:13 ` Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 03/11] can: peak_usb: " Marc Kleine-Budde
` (9 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2025-11-12 9:13 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Vadim Fedorenko, Kory Maincent,
Vincent Mailhol, Marc Kleine-Budde
From: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Convert driver to use ndo_hwtstamp_set()/ndo_hwtstamp_get() callbacks.
ndo_eth_ioctl handler does nothing after conversion - remove it.
Signed-off-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Reviewed-by: Kory Maincent <kory.maincent@bootlin.com>
Reviewed-by: Vincent Mailhol <mailhol@kernel.org>
Link: https://patch.msgid.link/20251029231620.1135640-3-vadim.fedorenko@linux.dev
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
drivers/net/can/peak_canfd/peak_canfd.c | 35 +++++++++++--------------
1 file changed, 16 insertions(+), 19 deletions(-)
diff --git a/drivers/net/can/peak_canfd/peak_canfd.c b/drivers/net/can/peak_canfd/peak_canfd.c
index a53c9d347b7b..06cb2629f66a 100644
--- a/drivers/net/can/peak_canfd/peak_canfd.c
+++ b/drivers/net/can/peak_canfd/peak_canfd.c
@@ -743,36 +743,33 @@ static netdev_tx_t peak_canfd_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
}
-static int peak_eth_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+static int peak_eth_hwtstamp_get(struct net_device *netdev,
+ struct kernel_hwtstamp_config *config)
{
- struct hwtstamp_config hwts_cfg = { 0 };
+ config->tx_type = HWTSTAMP_TX_OFF;
+ config->rx_filter = HWTSTAMP_FILTER_ALL;
- switch (cmd) {
- case SIOCSHWTSTAMP: /* set */
- if (copy_from_user(&hwts_cfg, ifr->ifr_data, sizeof(hwts_cfg)))
- return -EFAULT;
- if (hwts_cfg.tx_type == HWTSTAMP_TX_OFF &&
- hwts_cfg.rx_filter == HWTSTAMP_FILTER_ALL)
- return 0;
- return -ERANGE;
+ return 0;
+}
- case SIOCGHWTSTAMP: /* get */
- hwts_cfg.tx_type = HWTSTAMP_TX_OFF;
- hwts_cfg.rx_filter = HWTSTAMP_FILTER_ALL;
- if (copy_to_user(ifr->ifr_data, &hwts_cfg, sizeof(hwts_cfg)))
- return -EFAULT;
+static int peak_eth_hwtstamp_set(struct net_device *netdev,
+ struct kernel_hwtstamp_config *config,
+ struct netlink_ext_ack *extack)
+{
+ if (config->tx_type == HWTSTAMP_TX_OFF &&
+ config->rx_filter == HWTSTAMP_FILTER_ALL)
return 0;
- default:
- return -EOPNOTSUPP;
- }
+ NL_SET_ERR_MSG_MOD(extack, "Only RX HWTSTAMP_FILTER_ALL is supported");
+ return -ERANGE;
}
static const struct net_device_ops peak_canfd_netdev_ops = {
.ndo_open = peak_canfd_open,
.ndo_stop = peak_canfd_close,
- .ndo_eth_ioctl = peak_eth_ioctl,
.ndo_start_xmit = peak_canfd_start_xmit,
+ .ndo_hwtstamp_get = peak_eth_hwtstamp_get,
+ .ndo_hwtstamp_set = peak_eth_hwtstamp_set,
};
static int peak_get_ts_info(struct net_device *dev,
--
2.51.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH net-next 03/11] can: peak_usb: convert to use ndo_hwtstamp callbacks
2025-11-12 9:13 [PATCH net-next 0/11] pull-request: can-next 2025-11-12 Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 01/11] can: convert generic HW timestamp ioctl to ndo_hwtstamp callbacks Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 02/11] can: peak_canfd: convert to use " Marc Kleine-Budde
@ 2025-11-12 9:13 ` Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 04/11] can: mcp251x: mcp251x_can_probe(): use dev_err_probe() Marc Kleine-Budde
` (8 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2025-11-12 9:13 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Vadim Fedorenko, Kory Maincent,
Vincent Mailhol, Marc Kleine-Budde
From: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Convert driver to use ndo_hwtstamp_set()/ndo_hwtstamp_get() callbacks.
ndo_eth_ioctl handler does nothing after conversion - remove it.
Signed-off-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Reviewed-by: Kory Maincent <kory.maincent@bootlin.com>
Reviewed-by: Vincent Mailhol <mailhol@kernel.org>
Link: https://patch.msgid.link/20251029231620.1135640-4-vadim.fedorenko@linux.dev
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
drivers/net/can/usb/peak_usb/pcan_usb_core.c | 35 +++++++++-----------
1 file changed, 16 insertions(+), 19 deletions(-)
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
index 94b1d7f15d27..cf48bb26d46d 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
@@ -784,36 +784,33 @@ static int peak_usb_set_data_bittiming(struct net_device *netdev)
return 0;
}
-static int peak_eth_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+static int peak_hwtstamp_get(struct net_device *netdev,
+ struct kernel_hwtstamp_config *config)
{
- struct hwtstamp_config hwts_cfg = { 0 };
+ config->tx_type = HWTSTAMP_TX_OFF;
+ config->rx_filter = HWTSTAMP_FILTER_ALL;
- switch (cmd) {
- case SIOCSHWTSTAMP: /* set */
- if (copy_from_user(&hwts_cfg, ifr->ifr_data, sizeof(hwts_cfg)))
- return -EFAULT;
- if (hwts_cfg.tx_type == HWTSTAMP_TX_OFF &&
- hwts_cfg.rx_filter == HWTSTAMP_FILTER_ALL)
- return 0;
- return -ERANGE;
+ return 0;
+}
- case SIOCGHWTSTAMP: /* get */
- hwts_cfg.tx_type = HWTSTAMP_TX_OFF;
- hwts_cfg.rx_filter = HWTSTAMP_FILTER_ALL;
- if (copy_to_user(ifr->ifr_data, &hwts_cfg, sizeof(hwts_cfg)))
- return -EFAULT;
+static int peak_hwtstamp_set(struct net_device *netdev,
+ struct kernel_hwtstamp_config *config,
+ struct netlink_ext_ack *extack)
+{
+ if (config->tx_type == HWTSTAMP_TX_OFF &&
+ config->rx_filter == HWTSTAMP_FILTER_ALL)
return 0;
- default:
- return -EOPNOTSUPP;
- }
+ NL_SET_ERR_MSG_MOD(extack, "Only RX HWTSTAMP_FILTER_ALL is supported");
+ return -ERANGE;
}
static const struct net_device_ops peak_usb_netdev_ops = {
.ndo_open = peak_usb_ndo_open,
.ndo_stop = peak_usb_ndo_stop,
- .ndo_eth_ioctl = peak_eth_ioctl,
.ndo_start_xmit = peak_usb_ndo_start_xmit,
+ .ndo_hwtstamp_get = peak_hwtstamp_get,
+ .ndo_hwtstamp_set = peak_hwtstamp_set,
};
/* CAN-USB devices generally handle 32-bit CAN channel IDs.
--
2.51.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH net-next 04/11] can: mcp251x: mcp251x_can_probe(): use dev_err_probe()
2025-11-12 9:13 [PATCH net-next 0/11] pull-request: can-next 2025-11-12 Marc Kleine-Budde
` (2 preceding siblings ...)
2025-11-12 9:13 ` [PATCH net-next 03/11] can: peak_usb: " Marc Kleine-Budde
@ 2025-11-12 9:13 ` Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 05/11] can: mcp251xfd: move chip sleep mode into runtime pm Marc Kleine-Budde
` (7 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2025-11-12 9:13 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, linux-can, kernel, Maud Spierings, Marc Kleine-Budde
From: Maud Spierings <maudspierings@gocontroll.com>
The currently used combination of dev_err() plus return leaves a loud error
in dmesg even when the error is a deferred probe which gets resolved later.
For example a supply that has not been probed yet.
Use dev_err_probe() to improve the handling/display of errors.
Signed-off-by: Maud Spierings <maudspierings@gocontroll.com>
Link: https://patch.msgid.link/20251030-mcp_err-v1-1-eecf737823b7@gocontroll.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
drivers/net/can/spi/mcp251x.c | 31 ++++++++++++++++++++-----------
1 file changed, 20 insertions(+), 11 deletions(-)
diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c
index 1e54e1a22702..fa97adf25b73 100644
--- a/drivers/net/can/spi/mcp251x.c
+++ b/drivers/net/can/spi/mcp251x.c
@@ -1320,7 +1320,7 @@ static int mcp251x_can_probe(struct spi_device *spi)
clk = devm_clk_get_optional(&spi->dev, NULL);
if (IS_ERR(clk))
- return PTR_ERR(clk);
+ return dev_err_probe(&spi->dev, PTR_ERR(clk), "Cannot get clock\n");
freq = clk_get_rate(clk);
if (freq == 0)
@@ -1328,7 +1328,7 @@ static int mcp251x_can_probe(struct spi_device *spi)
/* Sanity check */
if (freq < 1000000 || freq > 25000000)
- return -ERANGE;
+ return dev_err_probe(&spi->dev, -ERANGE, "clock frequency out of range\n");
/* Allocate can/net device */
net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX);
@@ -1336,8 +1336,10 @@ static int mcp251x_can_probe(struct spi_device *spi)
return -ENOMEM;
ret = clk_prepare_enable(clk);
- if (ret)
+ if (ret) {
+ dev_err_probe(&spi->dev, ret, "Cannot enable clock\n");
goto out_free;
+ }
net->netdev_ops = &mcp251x_netdev_ops;
net->ethtool_ops = &mcp251x_ethtool_ops;
@@ -1362,20 +1364,25 @@ static int mcp251x_can_probe(struct spi_device *spi)
else
spi->max_speed_hz = spi->max_speed_hz ? : 10 * 1000 * 1000;
ret = spi_setup(spi);
- if (ret)
+ if (ret) {
+ dev_err_probe(&spi->dev, ret, "Cannot set up spi\n");
goto out_clk;
+ }
priv->power = devm_regulator_get_optional(&spi->dev, "vdd");
priv->transceiver = devm_regulator_get_optional(&spi->dev, "xceiver");
if ((PTR_ERR(priv->power) == -EPROBE_DEFER) ||
(PTR_ERR(priv->transceiver) == -EPROBE_DEFER)) {
ret = -EPROBE_DEFER;
+ dev_err_probe(&spi->dev, ret, "supply deferred\n");
goto out_clk;
}
ret = mcp251x_power_enable(priv->power, 1);
- if (ret)
+ if (ret) {
+ dev_err_probe(&spi->dev, ret, "Cannot enable power\n");
goto out_clk;
+ }
priv->wq = alloc_workqueue("mcp251x_wq",
WQ_FREEZABLE | WQ_MEM_RECLAIM | WQ_PERCPU,
@@ -1409,21 +1416,24 @@ static int mcp251x_can_probe(struct spi_device *spi)
/* Here is OK to not lock the MCP, no one knows about it yet */
ret = mcp251x_hw_probe(spi);
if (ret) {
- if (ret == -ENODEV)
- dev_err(&spi->dev, "Cannot initialize MCP%x. Wrong wiring?\n",
- priv->model);
+ dev_err_probe(&spi->dev, ret, "Cannot initialize MCP%x. Wrong wiring?\n",
+ priv->model);
goto error_probe;
}
mcp251x_hw_sleep(spi);
ret = register_candev(net);
- if (ret)
+ if (ret) {
+ dev_err_probe(&spi->dev, ret, "Cannot register CAN device\n");
goto error_probe;
+ }
ret = mcp251x_gpio_setup(priv);
- if (ret)
+ if (ret) {
+ dev_err_probe(&spi->dev, ret, "Cannot set up gpios\n");
goto out_unregister_candev;
+ }
netdev_info(net, "MCP%x successfully initialized.\n", priv->model);
return 0;
@@ -1442,7 +1452,6 @@ static int mcp251x_can_probe(struct spi_device *spi)
out_free:
free_candev(net);
- dev_err(&spi->dev, "Probe failed, err=%d\n", -ret);
return ret;
}
--
2.51.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH net-next 05/11] can: mcp251xfd: move chip sleep mode into runtime pm
2025-11-12 9:13 [PATCH net-next 0/11] pull-request: can-next 2025-11-12 Marc Kleine-Budde
` (3 preceding siblings ...)
2025-11-12 9:13 ` [PATCH net-next 04/11] can: mcp251x: mcp251x_can_probe(): use dev_err_probe() Marc Kleine-Budde
@ 2025-11-12 9:13 ` Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 06/11] can: mcp251xfd: utilize gather_write function for all non-CRC writes Marc Kleine-Budde
` (6 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2025-11-12 9:13 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Marc Kleine-Budde,
Gregor Herburger, Viken Dadhaniya, Manivannan Sadhasivam
This is a preparation patch to add GPIO support.
Up to now, the Vdd regulator and the clocks have been managed by
Runtime-PM (on systems without CONFIG_PM these remain permanently
switched on).
During the mcp251xfd_open() callback the mcp251xfd is powered,
soft-reset and configured. In mcp251xfd_stop() the chip is shut down
again. To support the on-chip GPIOs, the chip must be supplied with
power while GPIOs are being requested, even if the networking
interface is down.
To support this, move the functions mcp251xfd_chip_softreset() and
mcp251xfd_chip_clock_init() from mcp251xfd_chip_start() to
mcp251xfd_runtime_resume(). Instead of setting the controller to sleep
mode in mcp251xfd_chip_stop(), bring it into configuration mode. This
way it doesn't take part in bus activity and doesn't enter sleep mode.
Signed-off-by: Gregor Herburger <gregor.herburger@ew.tq-group.com>
Tested-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
Signed-off-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Link: https://patch.msgid.link/20251001091006.4003841-2-viken.dadhaniya@oss.qualcomm.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
.../net/can/spi/mcp251xfd/mcp251xfd-core.c | 99 ++++++++++++-------
1 file changed, 61 insertions(+), 38 deletions(-)
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
index c0f9d9fed02e..9104561e0995 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
@@ -767,21 +767,13 @@ static void mcp251xfd_chip_stop(struct mcp251xfd_priv *priv,
mcp251xfd_chip_interrupts_disable(priv);
mcp251xfd_chip_rx_int_disable(priv);
mcp251xfd_timestamp_stop(priv);
- mcp251xfd_chip_sleep(priv);
+ mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_CONFIG);
}
static int mcp251xfd_chip_start(struct mcp251xfd_priv *priv)
{
int err;
- err = mcp251xfd_chip_softreset(priv);
- if (err)
- goto out_chip_stop;
-
- err = mcp251xfd_chip_clock_init(priv);
- if (err)
- goto out_chip_stop;
-
err = mcp251xfd_chip_timestamp_init(priv);
if (err)
goto out_chip_stop;
@@ -1625,8 +1617,11 @@ static int mcp251xfd_open(struct net_device *ndev)
return err;
err = pm_runtime_resume_and_get(ndev->dev.parent);
- if (err)
+ if (err) {
+ if (err == -ETIMEDOUT || err == -ENODEV)
+ pm_runtime_set_suspended(ndev->dev.parent);
goto out_close_candev;
+ }
err = mcp251xfd_ring_alloc(priv);
if (err)
@@ -1907,53 +1902,53 @@ static int mcp251xfd_register(struct mcp251xfd_priv *priv)
struct net_device *ndev = priv->ndev;
int err;
+ mcp251xfd_register_quirks(priv);
+
err = mcp251xfd_clks_and_vdd_enable(priv);
if (err)
return err;
+ err = mcp251xfd_chip_softreset(priv);
+ if (err == -ENODEV)
+ goto out_clks_and_vdd_disable;
+ if (err)
+ goto out_chip_sleep;
+
+ err = mcp251xfd_chip_clock_init(priv);
+ if (err == -ENODEV)
+ goto out_clks_and_vdd_disable;
+ if (err)
+ goto out_chip_sleep;
+
pm_runtime_get_noresume(ndev->dev.parent);
err = pm_runtime_set_active(ndev->dev.parent);
if (err)
goto out_runtime_put_noidle;
pm_runtime_enable(ndev->dev.parent);
- mcp251xfd_register_quirks(priv);
-
- err = mcp251xfd_chip_softreset(priv);
- if (err == -ENODEV)
- goto out_runtime_disable;
- if (err)
- goto out_chip_sleep;
-
- err = mcp251xfd_chip_clock_init(priv);
- if (err == -ENODEV)
- goto out_runtime_disable;
- if (err)
- goto out_chip_sleep;
-
err = mcp251xfd_register_chip_detect(priv);
if (err)
- goto out_chip_sleep;
+ goto out_runtime_disable;
err = mcp251xfd_register_check_rx_int(priv);
if (err)
- goto out_chip_sleep;
+ goto out_runtime_disable;
mcp251xfd_ethtool_init(priv);
err = register_candev(ndev);
if (err)
- goto out_chip_sleep;
+ goto out_runtime_disable;
err = mcp251xfd_register_done(priv);
if (err)
goto out_unregister_candev;
- /* Put controller into sleep mode and let pm_runtime_put()
- * disable the clocks and vdd. If CONFIG_PM is not enabled,
- * the clocks and vdd will stay powered.
+ /* Put controller into Config mode and let pm_runtime_put()
+ * put in sleep mode, disable the clocks and vdd. If CONFIG_PM
+ * is not enabled, the clocks and vdd will stay powered.
*/
- err = mcp251xfd_chip_sleep(priv);
+ err = mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_CONFIG);
if (err)
goto out_unregister_candev;
@@ -1963,12 +1958,13 @@ static int mcp251xfd_register(struct mcp251xfd_priv *priv)
out_unregister_candev:
unregister_candev(ndev);
-out_chip_sleep:
- mcp251xfd_chip_sleep(priv);
out_runtime_disable:
pm_runtime_disable(ndev->dev.parent);
out_runtime_put_noidle:
pm_runtime_put_noidle(ndev->dev.parent);
+out_chip_sleep:
+ mcp251xfd_chip_sleep(priv);
+out_clks_and_vdd_disable:
mcp251xfd_clks_and_vdd_disable(priv);
return err;
@@ -1980,10 +1976,12 @@ static inline void mcp251xfd_unregister(struct mcp251xfd_priv *priv)
unregister_candev(ndev);
- if (pm_runtime_enabled(ndev->dev.parent))
+ if (pm_runtime_enabled(ndev->dev.parent)) {
pm_runtime_disable(ndev->dev.parent);
- else
+ } else {
+ mcp251xfd_chip_sleep(priv);
mcp251xfd_clks_and_vdd_disable(priv);
+ }
}
static const struct of_device_id mcp251xfd_of_match[] = {
@@ -2206,16 +2204,41 @@ static void mcp251xfd_remove(struct spi_device *spi)
static int __maybe_unused mcp251xfd_runtime_suspend(struct device *device)
{
- const struct mcp251xfd_priv *priv = dev_get_drvdata(device);
+ struct mcp251xfd_priv *priv = dev_get_drvdata(device);
+ mcp251xfd_chip_sleep(priv);
return mcp251xfd_clks_and_vdd_disable(priv);
}
static int __maybe_unused mcp251xfd_runtime_resume(struct device *device)
{
- const struct mcp251xfd_priv *priv = dev_get_drvdata(device);
+ struct mcp251xfd_priv *priv = dev_get_drvdata(device);
+ int err;
- return mcp251xfd_clks_and_vdd_enable(priv);
+ err = mcp251xfd_clks_and_vdd_enable(priv);
+ if (err)
+ return err;
+
+ err = mcp251xfd_chip_softreset(priv);
+ if (err == -ENODEV)
+ goto out_clks_and_vdd_disable;
+ if (err)
+ goto out_chip_sleep;
+
+ err = mcp251xfd_chip_clock_init(priv);
+ if (err == -ENODEV)
+ goto out_clks_and_vdd_disable;
+ if (err)
+ goto out_chip_sleep;
+
+ return 0;
+
+out_chip_sleep:
+ mcp251xfd_chip_sleep(priv);
+out_clks_and_vdd_disable:
+ mcp251xfd_clks_and_vdd_disable(priv);
+
+ return err;
}
static const struct dev_pm_ops mcp251xfd_pm_ops = {
--
2.51.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH net-next 06/11] can: mcp251xfd: utilize gather_write function for all non-CRC writes
2025-11-12 9:13 [PATCH net-next 0/11] pull-request: can-next 2025-11-12 Marc Kleine-Budde
` (4 preceding siblings ...)
2025-11-12 9:13 ` [PATCH net-next 05/11] can: mcp251xfd: move chip sleep mode into runtime pm Marc Kleine-Budde
@ 2025-11-12 9:13 ` Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 07/11] can: mcp251xfd: add workaround for errata 5 Marc Kleine-Budde
` (5 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2025-11-12 9:13 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Gregor Herburger, Viken Dadhaniya,
Manivannan Sadhasivam, Marc Kleine-Budde
From: Gregor Herburger <gregor.herburger@ew.tq-group.com>
This is a preparation patch to add errata workaround for non crc writes.
Currently for non-crc writes to the chip can go through the
.gather_write, .write or the reg_update_bits callback.
To allow the addition of the errata fix at a single location use
mcp251xfd_regmap_nocrc_gather_write for all non-CRC write instructions,
similar to the crc regmap.
Signed-off-by: Gregor Herburger <gregor.herburger@ew.tq-group.com>
Tested-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
Signed-off-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Link: https://patch.msgid.link/20251001091006.4003841-3-viken.dadhaniya@oss.qualcomm.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
.../net/can/spi/mcp251xfd/mcp251xfd-regmap.c | 25 ++++++++++---------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c
index 8c5be8d1c519..e61cbd209955 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c
@@ -12,14 +12,6 @@
static const struct regmap_config mcp251xfd_regmap_crc;
-static int
-mcp251xfd_regmap_nocrc_write(void *context, const void *data, size_t count)
-{
- struct spi_device *spi = context;
-
- return spi_write(spi, data, count);
-}
-
static int
mcp251xfd_regmap_nocrc_gather_write(void *context,
const void *reg, size_t reg_len,
@@ -47,6 +39,15 @@ mcp251xfd_regmap_nocrc_gather_write(void *context,
return spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
}
+static int
+mcp251xfd_regmap_nocrc_write(void *context, const void *data, size_t count)
+{
+ const size_t data_offset = sizeof(__be16);
+
+ return mcp251xfd_regmap_nocrc_gather_write(context, data, data_offset,
+ data + data_offset, count - data_offset);
+}
+
static inline bool
mcp251xfd_update_bits_read_reg(const struct mcp251xfd_priv *priv,
unsigned int reg)
@@ -64,6 +65,7 @@ mcp251xfd_update_bits_read_reg(const struct mcp251xfd_priv *priv,
case MCP251XFD_REG_CON:
case MCP251XFD_REG_OSC:
case MCP251XFD_REG_ECCCON:
+ case MCP251XFD_REG_IOCON:
return true;
default:
mcp251xfd_for_each_rx_ring(priv, ring, n) {
@@ -139,10 +141,9 @@ mcp251xfd_regmap_nocrc_update_bits(void *context, unsigned int reg,
tmp_le32 = orig_le32 & ~mask_le32;
tmp_le32 |= val_le32 & mask_le32;
- mcp251xfd_spi_cmd_write_nocrc(&buf_tx->cmd, reg + first_byte);
- memcpy(buf_tx->data, &tmp_le32, len);
-
- return spi_write(spi, buf_tx, sizeof(buf_tx->cmd) + len);
+ reg += first_byte;
+ mcp251xfd_spi_cmd_write_nocrc(&buf_tx->cmd, reg);
+ return mcp251xfd_regmap_nocrc_gather_write(context, &buf_tx->cmd, 2, &tmp_le32, len);
}
static int
--
2.51.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH net-next 07/11] can: mcp251xfd: add workaround for errata 5
2025-11-12 9:13 [PATCH net-next 0/11] pull-request: can-next 2025-11-12 Marc Kleine-Budde
` (5 preceding siblings ...)
2025-11-12 9:13 ` [PATCH net-next 06/11] can: mcp251xfd: utilize gather_write function for all non-CRC writes Marc Kleine-Budde
@ 2025-11-12 9:13 ` Marc Kleine-Budde
2025-11-12 17:28 ` Jakub Kicinski
2025-11-12 9:13 ` [PATCH net-next 08/11] can: mcp251xfd: only configure PIN1 when rx_int is set Marc Kleine-Budde
` (4 subsequent siblings)
11 siblings, 1 reply; 17+ messages in thread
From: Marc Kleine-Budde @ 2025-11-12 9:13 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Gregor Herburger, Viken Dadhaniya,
Manivannan Sadhasivam, Marc Kleine-Budde
From: Gregor Herburger <gregor.herburger@ew.tq-group.com>
According to Errata DS80000789E 5 writing IOCON register using one SPI
write command clears LAT0/LAT1.
Errata Fix/Work Around suggests to write registers with single byte write
instructions. However, it seems that every write to the second byte
causes the overwrite of LAT0/LAT1.
Never write byte 2 of IOCON register to avoid clearing of LAT0/LAT1.
Signed-off-by: Gregor Herburger <gregor.herburger@ew.tq-group.com>
Tested-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
Signed-off-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Link: https://patch.msgid.link/20251001091006.4003841-4-viken.dadhaniya@oss.qualcomm.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
.../net/can/spi/mcp251xfd/mcp251xfd-regmap.c | 89 +++++++++++++++++--
1 file changed, 83 insertions(+), 6 deletions(-)
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c
index e61cbd209955..70d5ff0ae7ac 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c
@@ -13,9 +13,9 @@
static const struct regmap_config mcp251xfd_regmap_crc;
static int
-mcp251xfd_regmap_nocrc_gather_write(void *context,
- const void *reg, size_t reg_len,
- const void *val, size_t val_len)
+_mcp251xfd_regmap_nocrc_gather_write(void *context,
+ const void *reg, size_t reg_len,
+ const void *val, size_t val_len)
{
struct spi_device *spi = context;
struct mcp251xfd_priv *priv = spi_get_drvdata(spi);
@@ -39,6 +39,45 @@ mcp251xfd_regmap_nocrc_gather_write(void *context,
return spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
}
+static int
+mcp251xfd_regmap_nocrc_gather_write(void *context,
+ const void *reg_p, size_t reg_len,
+ const void *val, size_t val_len)
+{
+ const u16 byte_exclude = MCP251XFD_REG_IOCON +
+ mcp251xfd_first_byte_set(MCP251XFD_REG_IOCON_GPIO_MASK);
+ u16 reg = be16_to_cpu(*(__be16 *)reg_p) & MCP251XFD_SPI_ADDRESS_MASK;
+ int ret;
+
+ /* Never write to bits 16..23 of IOCON register to avoid clearing of LAT0/LAT1
+ *
+ * According to MCP2518FD Errata DS80000789E 5 writing IOCON register using one
+ * SPI write command clears LAT0/LAT1.
+ *
+ * Errata Fix/Work Around suggests to write registers with single byte
+ * write instructions. However, it seems that the byte at 0xe06(IOCON[23:16])
+ * is for read-only access and writing to it causes the clearing of LAT0/LAT1.
+ */
+ if (reg <= byte_exclude && reg + val_len > byte_exclude) {
+ size_t len = byte_exclude - reg;
+
+ /* Write up to 0xe05 */
+ ret = _mcp251xfd_regmap_nocrc_gather_write(context, reg_p, reg_len, val, len);
+ if (ret)
+ return ret;
+
+ /* Write from 0xe07 on */
+ reg += len + 1;
+ reg = (__force unsigned short)cpu_to_be16(MCP251XFD_SPI_INSTRUCTION_WRITE | reg);
+ return _mcp251xfd_regmap_nocrc_gather_write(context, ®, reg_len,
+ val + len + 1,
+ val_len - len - 1);
+ }
+
+ return _mcp251xfd_regmap_nocrc_gather_write(context, reg_p, reg_len,
+ val, val_len);
+}
+
static int
mcp251xfd_regmap_nocrc_write(void *context, const void *data, size_t count)
{
@@ -197,9 +236,9 @@ mcp251xfd_regmap_nocrc_read(void *context,
}
static int
-mcp251xfd_regmap_crc_gather_write(void *context,
- const void *reg_p, size_t reg_len,
- const void *val, size_t val_len)
+_mcp251xfd_regmap_crc_gather_write(void *context,
+ const void *reg_p, size_t reg_len,
+ const void *val, size_t val_len)
{
struct spi_device *spi = context;
struct mcp251xfd_priv *priv = spi_get_drvdata(spi);
@@ -230,6 +269,44 @@ mcp251xfd_regmap_crc_gather_write(void *context,
return spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
}
+static int
+mcp251xfd_regmap_crc_gather_write(void *context,
+ const void *reg_p, size_t reg_len,
+ const void *val, size_t val_len)
+{
+ const u16 byte_exclude = MCP251XFD_REG_IOCON +
+ mcp251xfd_first_byte_set(MCP251XFD_REG_IOCON_GPIO_MASK);
+ u16 reg = *(u16 *)reg_p;
+ int ret;
+
+ /* Never write to bits 16..23 of IOCON register to avoid clearing of LAT0/LAT1
+ *
+ * According to MCP2518FD Errata DS80000789E 5 writing IOCON register using one
+ * SPI write command clears LAT0/LAT1.
+ *
+ * Errata Fix/Work Around suggests to write registers with single byte
+ * write instructions. However, it seems that the byte at 0xe06(IOCON[23:16])
+ * is for read-only access and writing to it causes the clearing of LAT0/LAT1.
+ */
+ if (reg <= byte_exclude && reg + val_len > byte_exclude) {
+ size_t len = byte_exclude - reg;
+
+ /* Write up to 0xe05 */
+ ret = _mcp251xfd_regmap_crc_gather_write(context, ®, reg_len, val, len);
+ if (ret)
+ return ret;
+
+ /* Write from 0xe07 on */
+ reg += len + 1;
+ return _mcp251xfd_regmap_crc_gather_write(context, ®, reg_len,
+ val + len + 1,
+ val_len - len - 1);
+ }
+
+ return _mcp251xfd_regmap_crc_gather_write(context, reg_p, reg_len,
+ val, val_len);
+}
+
static int
mcp251xfd_regmap_crc_write(void *context,
const void *data, size_t count)
--
2.51.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH net-next 08/11] can: mcp251xfd: only configure PIN1 when rx_int is set
2025-11-12 9:13 [PATCH net-next 0/11] pull-request: can-next 2025-11-12 Marc Kleine-Budde
` (6 preceding siblings ...)
2025-11-12 9:13 ` [PATCH net-next 07/11] can: mcp251xfd: add workaround for errata 5 Marc Kleine-Budde
@ 2025-11-12 9:13 ` Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 09/11] can: mcp251xfd: add gpio functionality Marc Kleine-Budde
` (3 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2025-11-12 9:13 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Gregor Herburger, Viken Dadhaniya,
Manivannan Sadhasivam, Marc Kleine-Budde
From: Gregor Herburger <gregor.herburger@ew.tq-group.com>
When rx_int is used th mcp251xfd_chip_rx_int_enable and
mcp251xfd_chip_rx_int_disable function configure both PIN0 and PIN1. To
prepare the support of the GPIOS only configure PIN1 with
regmap_update_bits.
This way PIN0 can be used as GPIO while PIN1 is used as rx_int
interrupt.
Signed-off-by: Gregor Herburger <gregor.herburger@ew.tq-group.com>
Tested-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
Signed-off-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Link: https://patch.msgid.link/20251001091006.4003841-5-viken.dadhaniya@oss.qualcomm.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
.../net/can/spi/mcp251xfd/mcp251xfd-core.c | 22 +++++++------------
drivers/net/can/spi/mcp251xfd/mcp251xfd.h | 6 +++++
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
index 9104561e0995..565327bf9c43 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
@@ -608,23 +608,21 @@ static int mcp251xfd_set_bittiming(const struct mcp251xfd_priv *priv)
static int mcp251xfd_chip_rx_int_enable(const struct mcp251xfd_priv *priv)
{
- u32 val;
+ u32 val, mask;
if (!priv->rx_int)
return 0;
- /* Configure GPIOs:
- * - PIN0: GPIO Input
- * - PIN1: GPIO Input/RX Interrupt
+ /* Configure PIN1 as RX Interrupt:
*
* PIN1 must be Input, otherwise there is a glitch on the
* rx-INT line. It happens between setting the PIN as output
* (in the first byte of the SPI transfer) and configuring the
* PIN as interrupt (in the last byte of the SPI transfer).
*/
- val = MCP251XFD_REG_IOCON_PM0 | MCP251XFD_REG_IOCON_TRIS1 |
- MCP251XFD_REG_IOCON_TRIS0;
- return regmap_write(priv->map_reg, MCP251XFD_REG_IOCON, val);
+ val = MCP251XFD_REG_IOCON_TRIS(1);
+ mask = MCP251XFD_REG_IOCON_TRIS(1) | MCP251XFD_REG_IOCON_PM(1);
+ return regmap_update_bits(priv->map_reg, MCP251XFD_REG_IOCON, mask, val);
}
static int mcp251xfd_chip_rx_int_disable(const struct mcp251xfd_priv *priv)
@@ -634,13 +632,9 @@ static int mcp251xfd_chip_rx_int_disable(const struct mcp251xfd_priv *priv)
if (!priv->rx_int)
return 0;
- /* Configure GPIOs:
- * - PIN0: GPIO Input
- * - PIN1: GPIO Input
- */
- val = MCP251XFD_REG_IOCON_PM1 | MCP251XFD_REG_IOCON_PM0 |
- MCP251XFD_REG_IOCON_TRIS1 | MCP251XFD_REG_IOCON_TRIS0;
- return regmap_write(priv->map_reg, MCP251XFD_REG_IOCON, val);
+ /* Configure PIN1 as GPIO Input */
+ val = MCP251XFD_REG_IOCON_PM(1) | MCP251XFD_REG_IOCON_TRIS(1);
+ return regmap_update_bits(priv->map_reg, MCP251XFD_REG_IOCON, val, val);
}
static int mcp251xfd_chip_ecc_init(struct mcp251xfd_priv *priv)
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
index dcbbd2b2fae8..bd28510a6583 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
@@ -335,13 +335,19 @@
#define MCP251XFD_REG_IOCON_TXCANOD BIT(28)
#define MCP251XFD_REG_IOCON_PM1 BIT(25)
#define MCP251XFD_REG_IOCON_PM0 BIT(24)
+#define MCP251XFD_REG_IOCON_PM(n) (MCP251XFD_REG_IOCON_PM0 << (n))
#define MCP251XFD_REG_IOCON_GPIO1 BIT(17)
#define MCP251XFD_REG_IOCON_GPIO0 BIT(16)
+#define MCP251XFD_REG_IOCON_GPIO(n) (MCP251XFD_REG_IOCON_GPIO0 << (n))
+#define MCP251XFD_REG_IOCON_GPIO_MASK GENMASK(17, 16)
#define MCP251XFD_REG_IOCON_LAT1 BIT(9)
#define MCP251XFD_REG_IOCON_LAT0 BIT(8)
+#define MCP251XFD_REG_IOCON_LAT(n) (MCP251XFD_REG_IOCON_LAT0 << (n))
+#define MCP251XFD_REG_IOCON_LAT_MASK GENMASK(9, 8)
#define MCP251XFD_REG_IOCON_XSTBYEN BIT(6)
#define MCP251XFD_REG_IOCON_TRIS1 BIT(1)
#define MCP251XFD_REG_IOCON_TRIS0 BIT(0)
+#define MCP251XFD_REG_IOCON_TRIS(n) (MCP251XFD_REG_IOCON_TRIS0 << (n))
#define MCP251XFD_REG_CRC 0xe08
#define MCP251XFD_REG_CRC_FERRIE BIT(25)
--
2.51.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH net-next 09/11] can: mcp251xfd: add gpio functionality
2025-11-12 9:13 [PATCH net-next 0/11] pull-request: can-next 2025-11-12 Marc Kleine-Budde
` (7 preceding siblings ...)
2025-11-12 9:13 ` [PATCH net-next 08/11] can: mcp251xfd: only configure PIN1 when rx_int is set Marc Kleine-Budde
@ 2025-11-12 9:13 ` Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 10/11] dt-bindings: can: mcp251xfd: add gpio-controller property Marc Kleine-Budde
` (2 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2025-11-12 9:13 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Gregor Herburger,
Bartosz Golaszewski, Viken Dadhaniya, Manivannan Sadhasivam,
Marc Kleine-Budde
From: Gregor Herburger <gregor.herburger@ew.tq-group.com>
The mcp251xfd devices allow two pins to be configured as gpio. Add this
functionality to driver.
Acked-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Signed-off-by: Gregor Herburger <gregor.herburger@ew.tq-group.com>
Tested-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
Signed-off-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Link: https://patch.msgid.link/20251001091006.4003841-6-viken.dadhaniya@oss.qualcomm.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
drivers/net/can/spi/mcp251xfd/Kconfig | 1 +
.../net/can/spi/mcp251xfd/mcp251xfd-core.c | 160 ++++++++++++++++++
drivers/net/can/spi/mcp251xfd/mcp251xfd.h | 2 +
3 files changed, 163 insertions(+)
diff --git a/drivers/net/can/spi/mcp251xfd/Kconfig b/drivers/net/can/spi/mcp251xfd/Kconfig
index 877e4356010d..7c29846e6051 100644
--- a/drivers/net/can/spi/mcp251xfd/Kconfig
+++ b/drivers/net/can/spi/mcp251xfd/Kconfig
@@ -5,6 +5,7 @@ config CAN_MCP251XFD
select CAN_RX_OFFLOAD
select REGMAP
select WANT_DEV_COREDUMP
+ select GPIOLIB
help
Driver for the Microchip MCP251XFD SPI FD-CAN controller
family.
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
index 565327bf9c43..5134ebb85880 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
@@ -1797,6 +1797,160 @@ static int mcp251xfd_register_check_rx_int(struct mcp251xfd_priv *priv)
return 0;
}
+static const char * const mcp251xfd_gpio_names[] = { "GPIO0", "GPIO1" };
+
+static int mcp251xfd_gpio_request(struct gpio_chip *chip, unsigned int offset)
+{
+ struct mcp251xfd_priv *priv = gpiochip_get_data(chip);
+ u32 pin_mask = MCP251XFD_REG_IOCON_PM(offset);
+ int ret;
+
+ if (priv->rx_int && offset == 1) {
+ netdev_err(priv->ndev, "Can't use GPIO 1 with RX-INT!\n");
+ return -EINVAL;
+ }
+
+ ret = pm_runtime_resume_and_get(priv->ndev->dev.parent);
+ if (ret)
+ return ret;
+
+ return regmap_update_bits(priv->map_reg, MCP251XFD_REG_IOCON, pin_mask, pin_mask);
+}
+
+static void mcp251xfd_gpio_free(struct gpio_chip *chip, unsigned int offset)
+{
+ struct mcp251xfd_priv *priv = gpiochip_get_data(chip);
+
+ pm_runtime_put(priv->ndev->dev.parent);
+}
+
+static int mcp251xfd_gpio_get_direction(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ struct mcp251xfd_priv *priv = gpiochip_get_data(chip);
+ u32 mask = MCP251XFD_REG_IOCON_TRIS(offset);
+ u32 val;
+ int ret;
+
+ ret = regmap_read(priv->map_reg, MCP251XFD_REG_IOCON, &val);
+ if (ret)
+ return ret;
+
+ if (mask & val)
+ return GPIO_LINE_DIRECTION_IN;
+
+ return GPIO_LINE_DIRECTION_OUT;
+}
+
+static int mcp251xfd_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ struct mcp251xfd_priv *priv = gpiochip_get_data(chip);
+ u32 mask = MCP251XFD_REG_IOCON_GPIO(offset);
+ u32 val;
+ int ret;
+
+ ret = regmap_read(priv->map_reg, MCP251XFD_REG_IOCON, &val);
+ if (ret)
+ return ret;
+
+ return !!(mask & val);
+}
+
+static int mcp251xfd_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
+ unsigned long *bit)
+{
+ struct mcp251xfd_priv *priv = gpiochip_get_data(chip);
+ u32 val;
+ int ret;
+
+ ret = regmap_read(priv->map_reg, MCP251XFD_REG_IOCON, &val);
+ if (ret)
+ return ret;
+
+ *bit = FIELD_GET(MCP251XFD_REG_IOCON_GPIO_MASK, val) & *mask;
+
+ return 0;
+}
+
+static int mcp251xfd_gpio_direction_output(struct gpio_chip *chip,
+ unsigned int offset, int value)
+{
+ struct mcp251xfd_priv *priv = gpiochip_get_data(chip);
+ u32 dir_mask = MCP251XFD_REG_IOCON_TRIS(offset);
+ u32 val_mask = MCP251XFD_REG_IOCON_LAT(offset);
+ u32 val;
+
+ if (value)
+ val = val_mask;
+ else
+ val = 0;
+
+ return regmap_update_bits(priv->map_reg, MCP251XFD_REG_IOCON,
+ dir_mask | val_mask, val);
+}
+
+static int mcp251xfd_gpio_direction_input(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ struct mcp251xfd_priv *priv = gpiochip_get_data(chip);
+ u32 dir_mask = MCP251XFD_REG_IOCON_TRIS(offset);
+
+ return regmap_update_bits(priv->map_reg, MCP251XFD_REG_IOCON, dir_mask, dir_mask);
+}
+
+static int mcp251xfd_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
+{
+ struct mcp251xfd_priv *priv = gpiochip_get_data(chip);
+ u32 val_mask = MCP251XFD_REG_IOCON_LAT(offset);
+ u32 val;
+
+ if (value)
+ val = val_mask;
+ else
+ val = 0;
+
+ return regmap_update_bits(priv->map_reg, MCP251XFD_REG_IOCON, val_mask, val);
+}
+
+static int mcp251xfd_gpio_set_multiple(struct gpio_chip *chip, unsigned long *mask,
+ unsigned long *bits)
+{
+ struct mcp251xfd_priv *priv = gpiochip_get_data(chip);
+ u32 val;
+
+ val = FIELD_PREP(MCP251XFD_REG_IOCON_LAT_MASK, *bits);
+
+ return regmap_update_bits(priv->map_reg, MCP251XFD_REG_IOCON,
+ MCP251XFD_REG_IOCON_LAT_MASK, val);
+}
+
+static int mcp251fdx_gpio_setup(struct mcp251xfd_priv *priv)
+{
+ struct gpio_chip *gc = &priv->gc;
+
+ if (!device_property_present(&priv->spi->dev, "gpio-controller"))
+ return 0;
+
+ gc->label = dev_name(&priv->spi->dev);
+ gc->parent = &priv->spi->dev;
+ gc->owner = THIS_MODULE;
+ gc->request = mcp251xfd_gpio_request;
+ gc->free = mcp251xfd_gpio_free;
+ gc->get_direction = mcp251xfd_gpio_get_direction;
+ gc->direction_output = mcp251xfd_gpio_direction_output;
+ gc->direction_input = mcp251xfd_gpio_direction_input;
+ gc->get = mcp251xfd_gpio_get;
+ gc->get_multiple = mcp251xfd_gpio_get_multiple;
+ gc->set = mcp251xfd_gpio_set;
+ gc->set_multiple = mcp251xfd_gpio_set_multiple;
+ gc->base = -1;
+ gc->can_sleep = true;
+ gc->ngpio = ARRAY_SIZE(mcp251xfd_gpio_names);
+ gc->names = mcp251xfd_gpio_names;
+
+ return devm_gpiochip_add_data(&priv->spi->dev, gc, priv);
+}
+
static int
mcp251xfd_register_get_dev_id(const struct mcp251xfd_priv *priv, u32 *dev_id,
u32 *effective_speed_hz_slow,
@@ -1930,6 +2084,12 @@ static int mcp251xfd_register(struct mcp251xfd_priv *priv)
mcp251xfd_ethtool_init(priv);
+ err = mcp251fdx_gpio_setup(priv);
+ if (err) {
+ dev_err_probe(&priv->spi->dev, err, "Failed to register gpio-controller.\n");
+ goto out_runtime_disable;
+ }
+
err = register_candev(ndev);
if (err)
goto out_runtime_disable;
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
index bd28510a6583..085d7101e595 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
@@ -15,6 +15,7 @@
#include <linux/can/dev.h>
#include <linux/can/rx-offload.h>
#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/regmap.h>
@@ -676,6 +677,7 @@ struct mcp251xfd_priv {
struct mcp251xfd_devtype_data devtype_data;
struct can_berr_counter bec;
+ struct gpio_chip gc;
};
#define MCP251XFD_IS(_model) \
--
2.51.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH net-next 10/11] dt-bindings: can: mcp251xfd: add gpio-controller property
2025-11-12 9:13 [PATCH net-next 0/11] pull-request: can-next 2025-11-12 Marc Kleine-Budde
` (8 preceding siblings ...)
2025-11-12 9:13 ` [PATCH net-next 09/11] can: mcp251xfd: add gpio functionality Marc Kleine-Budde
@ 2025-11-12 9:13 ` Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 11/11] can: bxcan: Fix a typo error for assign Marc Kleine-Budde
2025-11-12 9:36 ` [PATCH net-next 0/11] pull-request: can-next 2025-11-12 Marc Kleine-Budde
11 siblings, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2025-11-12 9:13 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Gregor Herburger,
Krzysztof Kozlowski, Viken Dadhaniya, Manivannan Sadhasivam,
Marc Kleine-Budde
From: Gregor Herburger <gregor.herburger@ew.tq-group.com>
The mcp251xfd has two pins that can be used as gpio. Add gpio-controller
property to binding description.
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Gregor Herburger <gregor.herburger@ew.tq-group.com>
Signed-off-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Link: https://patch.msgid.link/20251001091006.4003841-7-viken.dadhaniya@oss.qualcomm.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
.../devicetree/bindings/net/can/microchip,mcp251xfd.yaml | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/can/microchip,mcp251xfd.yaml b/Documentation/devicetree/bindings/net/can/microchip,mcp251xfd.yaml
index c155c9c6db39..2d13638ebc6a 100644
--- a/Documentation/devicetree/bindings/net/can/microchip,mcp251xfd.yaml
+++ b/Documentation/devicetree/bindings/net/can/microchip,mcp251xfd.yaml
@@ -49,6 +49,11 @@ properties:
Must be half or less of "clocks" frequency.
maximum: 20000000
+ gpio-controller: true
+
+ "#gpio-cells":
+ const: 2
+
required:
- compatible
- reg
--
2.51.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH net-next 11/11] can: bxcan: Fix a typo error for assign
2025-11-12 9:13 [PATCH net-next 0/11] pull-request: can-next 2025-11-12 Marc Kleine-Budde
` (9 preceding siblings ...)
2025-11-12 9:13 ` [PATCH net-next 10/11] dt-bindings: can: mcp251xfd: add gpio-controller property Marc Kleine-Budde
@ 2025-11-12 9:13 ` Marc Kleine-Budde
2025-11-12 9:36 ` [PATCH net-next 0/11] pull-request: can-next 2025-11-12 Marc Kleine-Budde
11 siblings, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2025-11-12 9:13 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Chu Guangqing, Dario Binacchi,
Marc Kleine-Budde
From: Chu Guangqing <chuguangqing@inspur.com>
Fix the spelling error of "assign".
Signed-off-by: Chu Guangqing <chuguangqing@inspur.com>
Reviewed-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
Link: https://patch.msgid.link/20251103074009.4708-1-chuguangqing@inspur.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
drivers/net/can/bxcan.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/can/bxcan.c b/drivers/net/can/bxcan.c
index 0b579e7bb3b6..baf494d20bef 100644
--- a/drivers/net/can/bxcan.c
+++ b/drivers/net/can/bxcan.c
@@ -227,7 +227,7 @@ static void bxcan_enable_filters(struct bxcan_priv *priv, enum bxcan_cfg cfg)
* mask mode with 32 bits width.
*/
- /* Enter filter initialization mode and assing filters to CAN
+ /* Enter filter initialization mode and assign filters to CAN
* controllers.
*/
regmap_update_bits(priv->gcan, BXCAN_FMR_REG,
--
2.51.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH net-next 0/11] pull-request: can-next 2025-11-12
2025-11-12 9:13 [PATCH net-next 0/11] pull-request: can-next 2025-11-12 Marc Kleine-Budde
` (10 preceding siblings ...)
2025-11-12 9:13 ` [PATCH net-next 11/11] can: bxcan: Fix a typo error for assign Marc Kleine-Budde
@ 2025-11-12 9:36 ` Marc Kleine-Budde
11 siblings, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2025-11-12 9:36 UTC (permalink / raw)
To: netdev; +Cc: kuba, davem, kernel, linux-can
[-- Attachment #1: Type: text/plain, Size: 1279 bytes --]
On 12.11.2025 10:13:40, Marc Kleine-Budde wrote:
> Hello netdev-team,
>
> this is a pull request of 11 patches for net-next/main.
>
> The first 3 patches are by Vadim Fedorenko and convert the CAN drivers
> to use the ndo_hwtstamp callbacks.
>
> Maud Spierings contributes a patch to the mcp251x driver that converts
> it to use dev_err_probe()
>
> The remaining patches target the mcp251xfd driver and are by Gregor
> Herburger and me. They add GPIO controller functionality to the
> driver.
Doh! I missed the last patch, here's an updated description:
The first 3 patches are by Vadim Fedorenko and convert the CAN drivers
to use the ndo_hwtstamp callbacks.
Maud Spierings contributes a patch to the mcp251x driver that converts
it to use dev_err_probe()
The next 6 patches target the mcp251xfd driver and are by Gregor
Herburger and me. They add GPIO controller functionality to the driver.
The final patch is by Chu Guangqing and fixes a typo in the bxcan
driver.
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Embedded Linux | https://www.pengutronix.de |
Vertretung Nürnberg | Phone: +49-5121-206917-129 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-9 |
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH net-next 07/11] can: mcp251xfd: add workaround for errata 5
2025-11-12 9:13 ` [PATCH net-next 07/11] can: mcp251xfd: add workaround for errata 5 Marc Kleine-Budde
@ 2025-11-12 17:28 ` Jakub Kicinski
2025-11-12 18:17 ` Marc Kleine-Budde
0 siblings, 1 reply; 17+ messages in thread
From: Jakub Kicinski @ 2025-11-12 17:28 UTC (permalink / raw)
To: Marc Kleine-Budde
Cc: netdev, davem, linux-can, kernel, Gregor Herburger,
Viken Dadhaniya, Manivannan Sadhasivam
On Wed, 12 Nov 2025 10:13:47 +0100 Marc Kleine-Budde wrote:
> +static int
> +mcp251xfd_regmap_nocrc_gather_write(void *context,
> + const void *reg_p, size_t reg_len,
> + const void *val, size_t val_len)
> +{
> + const u16 byte_exclude = MCP251XFD_REG_IOCON +
> + mcp251xfd_first_byte_set(MCP251XFD_REG_IOCON_GPIO_MASK);
Looks like this is added by the next patch :(
drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c:48:59: error: ‘MCP251XFD_REG_IOCON_GPIO_MASK’ undeclared (first use in this function); did you mean ‘MCP251XFD_REG_IOCON_GPIO0’?
48 | mcp251xfd_first_byte_set(MCP251XFD_REG_IOCON_GPIO_MASK);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| MCP251XFD_REG_IOCON_GPIO0
Do you do rebases or do we have to take it as is?
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH net-next 07/11] can: mcp251xfd: add workaround for errata 5
2025-11-12 17:28 ` Jakub Kicinski
@ 2025-11-12 18:17 ` Marc Kleine-Budde
2025-11-12 18:45 ` Marc Kleine-Budde
0 siblings, 1 reply; 17+ messages in thread
From: Marc Kleine-Budde @ 2025-11-12 18:17 UTC (permalink / raw)
To: Jakub Kicinski
Cc: netdev, davem, linux-can, kernel, Gregor Herburger,
Viken Dadhaniya, Manivannan Sadhasivam
[-- Attachment #1: Type: text/plain, Size: 1337 bytes --]
On 12.11.2025 09:28:00, Jakub Kicinski wrote:
> On Wed, 12 Nov 2025 10:13:47 +0100 Marc Kleine-Budde wrote:
> > +static int
> > +mcp251xfd_regmap_nocrc_gather_write(void *context,
> > + const void *reg_p, size_t reg_len,
> > + const void *val, size_t val_len)
> > +{
> > + const u16 byte_exclude = MCP251XFD_REG_IOCON +
> > + mcp251xfd_first_byte_set(MCP251XFD_REG_IOCON_GPIO_MASK);
>
> Looks like this is added by the next patch :(
>
> drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c:48:59: error: ‘MCP251XFD_REG_IOCON_GPIO_MASK’ undeclared (first use in this function); did you mean ‘MCP251XFD_REG_IOCON_GPIO0’?
> 48 | mcp251xfd_first_byte_set(MCP251XFD_REG_IOCON_GPIO_MASK);
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> | MCP251XFD_REG_IOCON_GPIO0
>
> Do you do rebases or do we have to take it as is?
I'll fix it and send a new PR.
Sorry for the noise,
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Embedded Linux | https://www.pengutronix.de |
Vertretung Nürnberg | Phone: +49-5121-206917-129 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-9 |
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH net-next 07/11] can: mcp251xfd: add workaround for errata 5
2025-11-12 18:40 Marc Kleine-Budde
@ 2025-11-12 18:40 ` Marc Kleine-Budde
0 siblings, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2025-11-12 18:40 UTC (permalink / raw)
To: netdev
Cc: davem, kuba, linux-can, kernel, Gregor Herburger, Viken Dadhaniya,
Manivannan Sadhasivam, Marc Kleine-Budde
From: Gregor Herburger <gregor.herburger@ew.tq-group.com>
According to Errata DS80000789E 5 writing IOCON register using one SPI
write command clears LAT0/LAT1.
Errata Fix/Work Around suggests to write registers with single byte write
instructions. However, it seems that every write to the second byte
causes the overwrite of LAT0/LAT1.
Never write byte 2 of IOCON register to avoid clearing of LAT0/LAT1.
Signed-off-by: Gregor Herburger <gregor.herburger@ew.tq-group.com>
Tested-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
Signed-off-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Link: https://patch.msgid.link/20251001091006.4003841-4-viken.dadhaniya@oss.qualcomm.com
[mkl: add missing MCP251XFD_REG_IOCON_GPIO_MASK]
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
.../net/can/spi/mcp251xfd/mcp251xfd-regmap.c | 89 +++++++++++++++++--
drivers/net/can/spi/mcp251xfd/mcp251xfd.h | 1 +
2 files changed, 84 insertions(+), 6 deletions(-)
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c
index e61cbd209955..70d5ff0ae7ac 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c
@@ -13,9 +13,9 @@
static const struct regmap_config mcp251xfd_regmap_crc;
static int
-mcp251xfd_regmap_nocrc_gather_write(void *context,
- const void *reg, size_t reg_len,
- const void *val, size_t val_len)
+_mcp251xfd_regmap_nocrc_gather_write(void *context,
+ const void *reg, size_t reg_len,
+ const void *val, size_t val_len)
{
struct spi_device *spi = context;
struct mcp251xfd_priv *priv = spi_get_drvdata(spi);
@@ -39,6 +39,45 @@ mcp251xfd_regmap_nocrc_gather_write(void *context,
return spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
}
+static int
+mcp251xfd_regmap_nocrc_gather_write(void *context,
+ const void *reg_p, size_t reg_len,
+ const void *val, size_t val_len)
+{
+ const u16 byte_exclude = MCP251XFD_REG_IOCON +
+ mcp251xfd_first_byte_set(MCP251XFD_REG_IOCON_GPIO_MASK);
+ u16 reg = be16_to_cpu(*(__be16 *)reg_p) & MCP251XFD_SPI_ADDRESS_MASK;
+ int ret;
+
+ /* Never write to bits 16..23 of IOCON register to avoid clearing of LAT0/LAT1
+ *
+ * According to MCP2518FD Errata DS80000789E 5 writing IOCON register using one
+ * SPI write command clears LAT0/LAT1.
+ *
+ * Errata Fix/Work Around suggests to write registers with single byte
+ * write instructions. However, it seems that the byte at 0xe06(IOCON[23:16])
+ * is for read-only access and writing to it causes the clearing of LAT0/LAT1.
+ */
+ if (reg <= byte_exclude && reg + val_len > byte_exclude) {
+ size_t len = byte_exclude - reg;
+
+ /* Write up to 0xe05 */
+ ret = _mcp251xfd_regmap_nocrc_gather_write(context, reg_p, reg_len, val, len);
+ if (ret)
+ return ret;
+
+ /* Write from 0xe07 on */
+ reg += len + 1;
+ reg = (__force unsigned short)cpu_to_be16(MCP251XFD_SPI_INSTRUCTION_WRITE | reg);
+ return _mcp251xfd_regmap_nocrc_gather_write(context, ®, reg_len,
+ val + len + 1,
+ val_len - len - 1);
+ }
+
+ return _mcp251xfd_regmap_nocrc_gather_write(context, reg_p, reg_len,
+ val, val_len);
+}
+
static int
mcp251xfd_regmap_nocrc_write(void *context, const void *data, size_t count)
{
@@ -197,9 +236,9 @@ mcp251xfd_regmap_nocrc_read(void *context,
}
static int
-mcp251xfd_regmap_crc_gather_write(void *context,
- const void *reg_p, size_t reg_len,
- const void *val, size_t val_len)
+_mcp251xfd_regmap_crc_gather_write(void *context,
+ const void *reg_p, size_t reg_len,
+ const void *val, size_t val_len)
{
struct spi_device *spi = context;
struct mcp251xfd_priv *priv = spi_get_drvdata(spi);
@@ -230,6 +269,44 @@ mcp251xfd_regmap_crc_gather_write(void *context,
return spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
}
+static int
+mcp251xfd_regmap_crc_gather_write(void *context,
+ const void *reg_p, size_t reg_len,
+ const void *val, size_t val_len)
+{
+ const u16 byte_exclude = MCP251XFD_REG_IOCON +
+ mcp251xfd_first_byte_set(MCP251XFD_REG_IOCON_GPIO_MASK);
+ u16 reg = *(u16 *)reg_p;
+ int ret;
+
+ /* Never write to bits 16..23 of IOCON register to avoid clearing of LAT0/LAT1
+ *
+ * According to MCP2518FD Errata DS80000789E 5 writing IOCON register using one
+ * SPI write command clears LAT0/LAT1.
+ *
+ * Errata Fix/Work Around suggests to write registers with single byte
+ * write instructions. However, it seems that the byte at 0xe06(IOCON[23:16])
+ * is for read-only access and writing to it causes the clearing of LAT0/LAT1.
+ */
+ if (reg <= byte_exclude && reg + val_len > byte_exclude) {
+ size_t len = byte_exclude - reg;
+
+ /* Write up to 0xe05 */
+ ret = _mcp251xfd_regmap_crc_gather_write(context, ®, reg_len, val, len);
+ if (ret)
+ return ret;
+
+ /* Write from 0xe07 on */
+ reg += len + 1;
+ return _mcp251xfd_regmap_crc_gather_write(context, ®, reg_len,
+ val + len + 1,
+ val_len - len - 1);
+ }
+
+ return _mcp251xfd_regmap_crc_gather_write(context, reg_p, reg_len,
+ val, val_len);
+}
+
static int
mcp251xfd_regmap_crc_write(void *context,
const void *data, size_t count)
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
index dcbbd2b2fae8..e63034fd5947 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
@@ -337,6 +337,7 @@
#define MCP251XFD_REG_IOCON_PM0 BIT(24)
#define MCP251XFD_REG_IOCON_GPIO1 BIT(17)
#define MCP251XFD_REG_IOCON_GPIO0 BIT(16)
+#define MCP251XFD_REG_IOCON_GPIO_MASK GENMASK(17, 16)
#define MCP251XFD_REG_IOCON_LAT1 BIT(9)
#define MCP251XFD_REG_IOCON_LAT0 BIT(8)
#define MCP251XFD_REG_IOCON_XSTBYEN BIT(6)
--
2.51.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH net-next 07/11] can: mcp251xfd: add workaround for errata 5
2025-11-12 18:17 ` Marc Kleine-Budde
@ 2025-11-12 18:45 ` Marc Kleine-Budde
0 siblings, 0 replies; 17+ messages in thread
From: Marc Kleine-Budde @ 2025-11-12 18:45 UTC (permalink / raw)
To: Jakub Kicinski
Cc: netdev, davem, linux-can, kernel, Gregor Herburger,
Viken Dadhaniya, Manivannan Sadhasivam
[-- Attachment #1: Type: text/plain, Size: 1068 bytes --]
On 12.11.2025 19:17:01, Marc Kleine-Budde wrote:
> > Looks like this is added by the next patch :(
> >
> > drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c:48:59: error: ‘MCP251XFD_REG_IOCON_GPIO_MASK’ undeclared (first use in this function); did you mean ‘MCP251XFD_REG_IOCON_GPIO0’?
> > 48 | mcp251xfd_first_byte_set(MCP251XFD_REG_IOCON_GPIO_MASK);
> > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > | MCP251XFD_REG_IOCON_GPIO0
> >
> > Do you do rebases or do we have to take it as is?
>
> I'll fix it and send a new PR.
Here it is: https://lore.kernel.org/all/20251112184344.189863-1-mkl@pengutronix.de/
regards,
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Embedded Linux | https://www.pengutronix.de |
Vertretung Nürnberg | Phone: +49-5121-206917-129 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-9 |
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2025-11-12 18:45 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-12 9:13 [PATCH net-next 0/11] pull-request: can-next 2025-11-12 Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 01/11] can: convert generic HW timestamp ioctl to ndo_hwtstamp callbacks Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 02/11] can: peak_canfd: convert to use " Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 03/11] can: peak_usb: " Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 04/11] can: mcp251x: mcp251x_can_probe(): use dev_err_probe() Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 05/11] can: mcp251xfd: move chip sleep mode into runtime pm Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 06/11] can: mcp251xfd: utilize gather_write function for all non-CRC writes Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 07/11] can: mcp251xfd: add workaround for errata 5 Marc Kleine-Budde
2025-11-12 17:28 ` Jakub Kicinski
2025-11-12 18:17 ` Marc Kleine-Budde
2025-11-12 18:45 ` Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 08/11] can: mcp251xfd: only configure PIN1 when rx_int is set Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 09/11] can: mcp251xfd: add gpio functionality Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 10/11] dt-bindings: can: mcp251xfd: add gpio-controller property Marc Kleine-Budde
2025-11-12 9:13 ` [PATCH net-next 11/11] can: bxcan: Fix a typo error for assign Marc Kleine-Budde
2025-11-12 9:36 ` [PATCH net-next 0/11] pull-request: can-next 2025-11-12 Marc Kleine-Budde
-- strict thread matches above, loose matches on Subject: below --
2025-11-12 18:40 Marc Kleine-Budde
2025-11-12 18:40 ` [PATCH net-next 07/11] can: mcp251xfd: add workaround for errata 5 Marc Kleine-Budde
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).