mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 03:27:03 +02:00
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:
commit
6152f40d4f
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user