linux-can-next-for-7.1-20260401

-----BEGIN PGP SIGNATURE-----
 
 iIkEABYKADEWIQSl+MghEFFAdY3pYJLMOmT6rpmt0gUCaczJHBMcbWtsQHBlbmd1
 dHJvbml4LmRlAAoJEMw6ZPquma3ST7UA/jiqjNrcEJlY2wOBfq103IeCPIIoP/Ys
 2mheO9GofkwwAQCj6CpLd6wiVX/Ht4j0QW5pDRm+4+zBkg5Tc6QZpyiPDw==
 =2+yi
 -----END PGP SIGNATURE-----

Merge tag 'linux-can-next-for-7.1-20260401' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next

Marc Kleine-Budde says:

====================
pull-request: can-next 2026-04-01

The first patch is by Ethan Nelson-Moore and removes a useless copy of
PCI_DEVICE_DATA from the ctucanfd driver.

Geert Uytterhoeven's patch for the rcar_can converts the driver to use
the FIELD_MODIFY macro.

Viken Dadhaniya contributes 2 patches for the mcp251xfd driver that
add transceiver standby control.

The last 2 aptches are by Johan Hovold and refactor the usb endpoint
lookup of the kvaser_usb and ucan driver.

* tag 'linux-can-next-for-7.1-20260401' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next:
  can: ucan: refactor endpoint lookup
  can: rcar_can: Convert to FIELD_MODIFY()
  can: mcp251xfd: add support for XSTBYEN transceiver standby control
  can: kvaser_usb: leaf: refactor endpoint lookup
  net: can: ctucanfd: remove useless copy of PCI_DEVICE_DATA macro
  dt-bindings: can: mcp251xfd: add microchip,xstbyen property
====================

Link: https://patch.msgid.link/20260401073338.5592-1-mkl@pengutronix.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-04-01 19:15:39 -07:00
commit 6152f40d4f
7 changed files with 66 additions and 56 deletions

View File

@ -44,6 +44,14 @@ properties:
signals a pending RX interrupt.
maxItems: 1
microchip,xstbyen:
type: boolean
description:
If present, configure the INT0/GPIO0/XSTBY pin as transceiver standby
control. The pin is driven low when the controller is active and high
when it enters Sleep mode, allowing automatic standby control of an
external CAN transceiver connected to this pin.
spi-max-frequency:
description:
Must be half or less of "clocks" frequency.

View File

@ -22,14 +22,6 @@
#include "ctucanfd.h"
#ifndef PCI_DEVICE_DATA
#define PCI_DEVICE_DATA(vend, dev, data) \
.vendor = PCI_VENDOR_ID_##vend, \
.device = PCI_DEVICE_ID_##vend##_##dev, \
.subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, 0, 0, \
.driver_data = (kernel_ulong_t)(data)
#endif
#ifndef PCI_VENDOR_ID_TEDIA
#define PCI_VENDOR_ID_TEDIA 0x1760
#endif

View File

@ -496,8 +496,7 @@ static void rcar_can_start(struct net_device *ndev)
priv->can.state = CAN_STATE_ERROR_ACTIVE;
/* Go to operation mode */
ctlr &= ~RCAR_CAN_CTLR_CANM;
ctlr |= FIELD_PREP(RCAR_CAN_CTLR_CANM, RCAR_CAN_CTLR_CANM_OPER);
FIELD_MODIFY(RCAR_CAN_CTLR_CANM, &ctlr, RCAR_CAN_CTLR_CANM_OPER);
writew(ctlr, &priv->regs->ctlr);
for (i = 0; i < MAX_STR_READS; i++) {
if (!(readw(&priv->regs->str) & RCAR_CAN_STR_RSTST))

View File

@ -764,6 +764,31 @@ static void mcp251xfd_chip_stop(struct mcp251xfd_priv *priv,
mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_CONFIG);
}
static int mcp251xfd_chip_xstbyen_enable(const struct mcp251xfd_priv *priv)
{
/* Configure the INT0/GPIO0/XSTBY pin as transceiver standby control:
*
* - XSTBYEN=1: route the pin to the transceiver standby function
* - TRIS0=0: set output direction; the reset default is 1 (input),
* which leaves the pin floating HIGH and keeps the
* transceiver in standby regardless of XSTBYEN
* - LAT0=0: drive pin LOW => transceiver active (not in standby)
*
* All three bits are included in the mask; only XSTBYEN is set in
* val, so TRIS0 and LAT0 are cleared to 0 atomically.
*
* Pin behaviour by mode:
* - Config mode: controlled by LAT0 (LAT0=0 => LOW => active)
* - Normal mode: hardware drives pin LOW (active)
* - Sleep mode: hardware drives pin HIGH (standby)
*/
return regmap_update_bits(priv->map_reg, MCP251XFD_REG_IOCON,
MCP251XFD_REG_IOCON_XSTBYEN |
MCP251XFD_REG_IOCON_TRIS0 |
MCP251XFD_REG_IOCON_LAT0,
MCP251XFD_REG_IOCON_XSTBYEN);
}
static int mcp251xfd_chip_start(struct mcp251xfd_priv *priv)
{
int err;
@ -796,6 +821,12 @@ static int mcp251xfd_chip_start(struct mcp251xfd_priv *priv)
priv->can.state = CAN_STATE_ERROR_ACTIVE;
if (priv->xstbyen) {
err = mcp251xfd_chip_xstbyen_enable(priv);
if (err)
goto out_chip_stop;
}
err = mcp251xfd_chip_set_normal_mode(priv);
if (err)
goto out_chip_stop;
@ -1805,6 +1836,11 @@ static int mcp251xfd_gpio_request(struct gpio_chip *chip, unsigned int offset)
u32 pin_mask = MCP251XFD_REG_IOCON_PM(offset);
int ret;
if (priv->xstbyen && offset == 0) {
netdev_err(priv->ndev, "Can't use GPIO 0 with XSTBYEN!\n");
return -EINVAL;
}
if (priv->rx_int && offset == 1) {
netdev_err(priv->ndev, "Can't use GPIO 1 with RX-INT!\n");
return -EINVAL;
@ -2271,6 +2307,7 @@ static int mcp251xfd_probe(struct spi_device *spi)
priv->pll_enable = pll_enable;
priv->reg_vdd = reg_vdd;
priv->reg_xceiver = reg_xceiver;
priv->xstbyen = device_property_present(&spi->dev, "microchip,xstbyen");
priv->devtype_data = *(struct mcp251xfd_devtype_data *)spi_get_device_match_data(spi);
/* Errata Reference:

View File

@ -672,6 +672,7 @@ struct mcp251xfd_priv {
struct gpio_desc *rx_int;
struct clk *clk;
bool pll_enable;
bool xstbyen;
struct regulator *reg_vdd;
struct regulator *reg_xceiver;

View File

@ -1957,27 +1957,18 @@ static int kvaser_usb_leaf_get_berr_counter(const struct net_device *netdev,
static int kvaser_usb_leaf_setup_endpoints(struct kvaser_usb *dev)
{
const struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
int i;
struct usb_host_interface *iface_desc;
int ret;
iface_desc = dev->intf->cur_altsetting;
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
/* use first bulk endpoint for in and out */
ret = usb_find_common_endpoints(iface_desc, &dev->bulk_in, &dev->bulk_out,
NULL, NULL);
if (ret)
return -ENODEV;
if (!dev->bulk_in && usb_endpoint_is_bulk_in(endpoint))
dev->bulk_in = endpoint;
if (!dev->bulk_out && usb_endpoint_is_bulk_out(endpoint))
dev->bulk_out = endpoint;
/* use first bulk endpoint for in and out */
if (dev->bulk_in && dev->bulk_out)
return 0;
}
return -ENODEV;
return 0;
}
const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops = {

View File

@ -1302,13 +1302,12 @@ static int ucan_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
int ret;
int i;
u32 protocol_version;
struct usb_device *udev;
struct net_device *netdev;
struct usb_host_interface *iface_desc;
struct ucan_priv *up;
struct usb_endpoint_descriptor *ep;
struct usb_endpoint_descriptor *ep_in, *ep_out;
u16 in_ep_size;
u16 out_ep_size;
u8 in_ep_addr;
@ -1343,37 +1342,20 @@ static int ucan_probe(struct usb_interface *intf,
}
/* check interface endpoints */
in_ep_addr = 0;
out_ep_addr = 0;
in_ep_size = 0;
out_ep_size = 0;
for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
ep = &iface_desc->endpoint[i].desc;
if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != 0) &&
((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK)) {
/* In Endpoint */
in_ep_addr = ep->bEndpointAddress;
in_ep_addr &= USB_ENDPOINT_NUMBER_MASK;
in_ep_size = le16_to_cpu(ep->wMaxPacketSize);
} else if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
0) &&
((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK)) {
/* Out Endpoint */
out_ep_addr = ep->bEndpointAddress;
out_ep_addr &= USB_ENDPOINT_NUMBER_MASK;
out_ep_size = le16_to_cpu(ep->wMaxPacketSize);
}
}
/* check if interface is sane */
if (!in_ep_addr || !out_ep_addr) {
ret = usb_find_common_endpoints_reverse(iface_desc, &ep_in, &ep_out,
NULL, NULL);
if (ret) {
dev_err(&udev->dev, "%s: invalid endpoint configuration\n",
UCAN_DRIVER_NAME);
goto err_firmware_needs_update;
}
in_ep_addr = usb_endpoint_num(ep_in);
out_ep_addr = usb_endpoint_num(ep_out);
in_ep_size = usb_endpoint_maxp(ep_in);
out_ep_size = usb_endpoint_maxp(ep_out);
/* check if interface is sane */
if (in_ep_size < sizeof(struct ucan_message_in)) {
dev_err(&udev->dev, "%s: invalid in_ep MaxPacketSize\n",
UCAN_DRIVER_NAME);