diff options
Diffstat (limited to 'drivers/net/can')
-rw-r--r-- | drivers/net/can/Kconfig | 2 | ||||
-rw-r--r-- | drivers/net/can/at91_can.c | 4 | ||||
-rw-r--r-- | drivers/net/can/bfin_can.c | 258 | ||||
-rw-r--r-- | drivers/net/can/cc770/cc770_platform.c | 2 | ||||
-rw-r--r-- | drivers/net/can/flexcan.c | 18 | ||||
-rw-r--r-- | drivers/net/can/grcan.c | 2 | ||||
-rw-r--r-- | drivers/net/can/led.c | 22 | ||||
-rw-r--r-- | drivers/net/can/m_can/m_can.c | 4 | ||||
-rw-r--r-- | drivers/net/can/mscan/mpc5xxx_can.c | 2 | ||||
-rw-r--r-- | drivers/net/can/sja1000/sja1000_platform.c | 2 | ||||
-rw-r--r-- | drivers/net/can/usb/ems_usb.c | 11 | ||||
-rw-r--r-- | drivers/net/can/usb/esd_usb2.c | 4 | ||||
-rw-r--r-- | drivers/net/can/usb/gs_usb.c | 2 | ||||
-rw-r--r-- | drivers/net/can/usb/kvaser_usb.c | 136 | ||||
-rw-r--r-- | drivers/net/can/usb/peak_usb/pcan_ucan.h | 15 | ||||
-rw-r--r-- | drivers/net/can/usb/peak_usb/pcan_usb_fd.c | 75 | ||||
-rw-r--r-- | drivers/net/can/xilinx_can.c | 2 |
17 files changed, 369 insertions, 192 deletions
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index 98d73aab52fe..58808f651452 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -131,7 +131,7 @@ config CAN_RCAR config CAN_XILINXCAN tristate "Xilinx CAN" - depends on ARCH_ZYNQ || MICROBLAZE || COMPILE_TEST + depends on ARCH_ZYNQ || ARM64 || MICROBLAZE || COMPILE_TEST depends on COMMON_CLK && HAS_IOMEM ---help--- Xilinx CAN driver. This driver supports both soft AXI CAN IP and diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index eeb4b8b6b335..f4e40aa4d2a2 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -291,13 +291,13 @@ static inline unsigned int get_tx_echo_mb(const struct at91_priv *priv) static inline u32 at91_read(const struct at91_priv *priv, enum at91_reg reg) { - return __raw_readl(priv->reg_base + reg); + return readl_relaxed(priv->reg_base + reg); } static inline void at91_write(const struct at91_priv *priv, enum at91_reg reg, u32 value) { - __raw_writel(value, priv->reg_base + reg); + writel_relaxed(value, priv->reg_base + reg); } static inline void set_mb_mode_prio(const struct at91_priv *priv, diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c index e7a6363e736b..27ad312e7abf 100644 --- a/drivers/net/can/bfin_can.c +++ b/drivers/net/can/bfin_can.c @@ -20,13 +20,121 @@ #include <linux/can/dev.h> #include <linux/can/error.h> -#include <asm/bfin_can.h> #include <asm/portmux.h> #define DRV_NAME "bfin_can" #define BFIN_CAN_TIMEOUT 100 #define TX_ECHO_SKB_MAX 1 +/* transmit and receive channels */ +#define TRANSMIT_CHL 24 +#define RECEIVE_STD_CHL 0 +#define RECEIVE_EXT_CHL 4 +#define RECEIVE_RTR_CHL 8 +#define RECEIVE_EXT_RTR_CHL 12 +#define MAX_CHL_NUMBER 32 + +/* All Blackfin system MMRs are padded to 32bits even if the register + * itself is only 16bits. So use a helper macro to streamline this + */ +#define __BFP(m) u16 m; u16 __pad_##m + +/* bfin can registers layout */ +struct bfin_can_mask_regs { + __BFP(aml); + __BFP(amh); +}; + +struct bfin_can_channel_regs { + /* data[0,2,4,6] -> data{0,1,2,3} while data[1,3,5,7] is padding */ + u16 data[8]; + __BFP(dlc); + __BFP(tsv); + __BFP(id0); + __BFP(id1); +}; + +struct bfin_can_regs { + /* global control and status registers */ + __BFP(mc1); /* offset 0x00 */ + __BFP(md1); /* offset 0x04 */ + __BFP(trs1); /* offset 0x08 */ + __BFP(trr1); /* offset 0x0c */ + __BFP(ta1); /* offset 0x10 */ + __BFP(aa1); /* offset 0x14 */ + __BFP(rmp1); /* offset 0x18 */ + __BFP(rml1); /* offset 0x1c */ + __BFP(mbtif1); /* offset 0x20 */ + __BFP(mbrif1); /* offset 0x24 */ + __BFP(mbim1); /* offset 0x28 */ + __BFP(rfh1); /* offset 0x2c */ + __BFP(opss1); /* offset 0x30 */ + u32 __pad1[3]; + __BFP(mc2); /* offset 0x40 */ + __BFP(md2); /* offset 0x44 */ + __BFP(trs2); /* offset 0x48 */ + __BFP(trr2); /* offset 0x4c */ + __BFP(ta2); /* offset 0x50 */ + __BFP(aa2); /* offset 0x54 */ + __BFP(rmp2); /* offset 0x58 */ + __BFP(rml2); /* offset 0x5c */ + __BFP(mbtif2); /* offset 0x60 */ + __BFP(mbrif2); /* offset 0x64 */ + __BFP(mbim2); /* offset 0x68 */ + __BFP(rfh2); /* offset 0x6c */ + __BFP(opss2); /* offset 0x70 */ + u32 __pad2[3]; + __BFP(clock); /* offset 0x80 */ + __BFP(timing); /* offset 0x84 */ + __BFP(debug); /* offset 0x88 */ + __BFP(status); /* offset 0x8c */ + __BFP(cec); /* offset 0x90 */ + __BFP(gis); /* offset 0x94 */ + __BFP(gim); /* offset 0x98 */ + __BFP(gif); /* offset 0x9c */ + __BFP(control); /* offset 0xa0 */ + __BFP(intr); /* offset 0xa4 */ + __BFP(version); /* offset 0xa8 */ + __BFP(mbtd); /* offset 0xac */ + __BFP(ewr); /* offset 0xb0 */ + __BFP(esr); /* offset 0xb4 */ + u32 __pad3[2]; + __BFP(ucreg); /* offset 0xc0 */ + __BFP(uccnt); /* offset 0xc4 */ + __BFP(ucrc); /* offset 0xc8 */ + __BFP(uccnf); /* offset 0xcc */ + u32 __pad4[1]; + __BFP(version2); /* offset 0xd4 */ + u32 __pad5[10]; + + /* channel(mailbox) mask and message registers */ + struct bfin_can_mask_regs msk[MAX_CHL_NUMBER]; /* offset 0x100 */ + struct bfin_can_channel_regs chl[MAX_CHL_NUMBER]; /* offset 0x200 */ +}; + +#undef __BFP + +#define SRS 0x0001 /* Software Reset */ +#define SER 0x0008 /* Stuff Error */ +#define BOIM 0x0008 /* Enable Bus Off Interrupt */ +#define CCR 0x0080 /* CAN Configuration Mode Request */ +#define CCA 0x0080 /* Configuration Mode Acknowledge */ +#define SAM 0x0080 /* Sampling */ +#define AME 0x8000 /* Acceptance Mask Enable */ +#define RMLIM 0x0080 /* Enable RX Message Lost Interrupt */ +#define RMLIS 0x0080 /* RX Message Lost IRQ Status */ +#define RTR 0x4000 /* Remote Frame Transmission Request */ +#define BOIS 0x0008 /* Bus Off IRQ Status */ +#define IDE 0x2000 /* Identifier Extension */ +#define EPIS 0x0004 /* Error-Passive Mode IRQ Status */ +#define EPIM 0x0004 /* Enable Error-Passive Mode Interrupt */ +#define EWTIS 0x0001 /* TX Error Count IRQ Status */ +#define EWRIS 0x0002 /* RX Error Count IRQ Status */ +#define BEF 0x0040 /* Bit Error Flag */ +#define FER 0x0080 /* Form Error Flag */ +#define SMR 0x0020 /* Sleep Mode Request */ +#define SMACK 0x0008 /* Sleep Mode Acknowledge */ + /* * bfin can private data */ @@ -78,8 +186,8 @@ static int bfin_can_set_bittiming(struct net_device *dev) if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) timing |= SAM; - bfin_write(®->clock, clk); - bfin_write(®->timing, timing); + writew(clk, ®->clock); + writew(timing, ®->timing); netdev_info(dev, "setting CLOCK=0x%04x TIMING=0x%04x\n", clk, timing); @@ -94,16 +202,14 @@ static void bfin_can_set_reset_mode(struct net_device *dev) int i; /* disable interrupts */ - bfin_write(®->mbim1, 0); - bfin_write(®->mbim2, 0); - bfin_write(®->gim, 0); + writew(0, ®->mbim1); + writew(0, ®->mbim2); + writew(0, ®->gim); /* reset can and enter configuration mode */ - bfin_write(®->control, SRS | CCR); - SSYNC(); - bfin_write(®->control, CCR); - SSYNC(); - while (!(bfin_read(®->control) & CCA)) { + writew(SRS | CCR, ®->control); + writew(CCR, ®->control); + while (!(readw(®->control) & CCA)) { udelay(10); if (--timeout == 0) { netdev_err(dev, "fail to enter configuration mode\n"); @@ -116,34 +222,33 @@ static void bfin_can_set_reset_mode(struct net_device *dev) * by writing to CAN Mailbox Configuration Registers 1 and 2 * For all bits: 0 - Mailbox disabled, 1 - Mailbox enabled */ - bfin_write(®->mc1, 0); - bfin_write(®->mc2, 0); + writew(0, ®->mc1); + writew(0, ®->mc2); /* Set Mailbox Direction */ - bfin_write(®->md1, 0xFFFF); /* mailbox 1-16 are RX */ - bfin_write(®->md2, 0); /* mailbox 17-32 are TX */ + writew(0xFFFF, ®->md1); /* mailbox 1-16 are RX */ + writew(0, ®->md2); /* mailbox 17-32 are TX */ /* RECEIVE_STD_CHL */ for (i = 0; i < 2; i++) { - bfin_write(®->chl[RECEIVE_STD_CHL + i].id0, 0); - bfin_write(®->chl[RECEIVE_STD_CHL + i].id1, AME); - bfin_write(®->chl[RECEIVE_STD_CHL + i].dlc, 0); - bfin_write(®->msk[RECEIVE_STD_CHL + i].amh, 0x1FFF); - bfin_write(®->msk[RECEIVE_STD_CHL + i].aml, 0xFFFF); + writew(0, ®->chl[RECEIVE_STD_CHL + i].id0); + writew(AME, ®->chl[RECEIVE_STD_CHL + i].id1); + writew(0, ®->chl[RECEIVE_STD_CHL + i].dlc); + writew(0x1FFF, ®->msk[RECEIVE_STD_CHL + i].amh); + writew(0xFFFF, ®->msk[RECEIVE_STD_CHL + i].aml); } /* RECEIVE_EXT_CHL */ for (i = 0; i < 2; i++) { - bfin_write(®->chl[RECEIVE_EXT_CHL + i].id0, 0); - bfin_write(®->chl[RECEIVE_EXT_CHL + i].id1, AME | IDE); - bfin_write(®->chl[RECEIVE_EXT_CHL + i].dlc, 0); - bfin_write(®->msk[RECEIVE_EXT_CHL + i].amh, 0x1FFF); - bfin_write(®->msk[RECEIVE_EXT_CHL + i].aml, 0xFFFF); + writew(0, ®->chl[RECEIVE_EXT_CHL + i].id0); + writew(AME | IDE, ®->chl[RECEIVE_EXT_CHL + i].id1); + writew(0, ®->chl[RECEIVE_EXT_CHL + i].dlc); + writew(0x1FFF, ®->msk[RECEIVE_EXT_CHL + i].amh); + writew(0xFFFF, ®->msk[RECEIVE_EXT_CHL + i].aml); } - bfin_write(®->mc2, BIT(TRANSMIT_CHL - 16)); - bfin_write(®->mc1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL)); - SSYNC(); + writew(BIT(TRANSMIT_CHL - 16), ®->mc2); + writew(BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL), ®->mc1); priv->can.state = CAN_STATE_STOPPED; } @@ -157,9 +262,9 @@ static void bfin_can_set_normal_mode(struct net_device *dev) /* * leave configuration mode */ - bfin_write(®->control, bfin_read(®->control) & ~CCR); + writew(readw(®->control) & ~CCR, ®->control); - while (bfin_read(®->status) & CCA) { + while (readw(®->status) & CCA) { udelay(10); if (--timeout == 0) { netdev_err(dev, "fail to leave configuration mode\n"); @@ -170,26 +275,25 @@ static void bfin_can_set_normal_mode(struct net_device *dev) /* * clear _All_ tx and rx interrupts */ - bfin_write(®->mbtif1, 0xFFFF); - bfin_write(®->mbtif2, 0xFFFF); - bfin_write(®->mbrif1, 0xFFFF); - bfin_write(®->mbrif2, 0xFFFF); + writew(0xFFFF, ®->mbtif1); + writew(0xFFFF, ®->mbtif2); + writew(0xFFFF, ®->mbrif1); + writew(0xFFFF, ®->mbrif2); /* * clear global interrupt status register */ - bfin_write(®->gis, 0x7FF); /* overwrites with '1' */ + writew(0x7FF, ®->gis); /* overwrites with '1' */ /* * Initialize Interrupts * - set bits in the mailbox interrupt mask register * - global interrupt mask */ - bfin_write(®->mbim1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL)); - bfin_write(®->mbim2, BIT(TRANSMIT_CHL - 16)); + writew(BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL), ®->mbim1); + writew(BIT(TRANSMIT_CHL - 16), ®->mbim2); - bfin_write(®->gim, EPIM | BOIM | RMLIM); - SSYNC(); + writew(EPIM | BOIM | RMLIM, ®->gim); } static void bfin_can_start(struct net_device *dev) @@ -226,7 +330,7 @@ static int bfin_can_get_berr_counter(const struct net_device *dev, struct bfin_can_priv *priv = netdev_priv(dev); struct bfin_can_regs __iomem *reg = priv->membase; - u16 cec = bfin_read(®->cec); + u16 cec = readw(®->cec); bec->txerr = cec >> 8; bec->rxerr = cec; @@ -252,28 +356,28 @@ static int bfin_can_start_xmit(struct sk_buff *skb, struct net_device *dev) /* fill id */ if (id & CAN_EFF_FLAG) { - bfin_write(®->chl[TRANSMIT_CHL].id0, id); + writew(id, ®->chl[TRANSMIT_CHL].id0); val = ((id & 0x1FFF0000) >> 16) | IDE; } else val = (id << 2); if (id & CAN_RTR_FLAG) val |= RTR; - bfin_write(®->chl[TRANSMIT_CHL].id1, val | AME); + writew(val | AME, ®->chl[TRANSMIT_CHL].id1); /* fill payload */ for (i = 0; i < 8; i += 2) { val = ((7 - i) < dlc ? (data[7 - i]) : 0) + ((6 - i) < dlc ? (data[6 - i] << 8) : 0); - bfin_write(®->chl[TRANSMIT_CHL].data[i], val); + writew(val, ®->chl[TRANSMIT_CHL].data[i]); } /* fill data length code */ - bfin_write(®->chl[TRANSMIT_CHL].dlc, dlc); + writew(dlc, ®->chl[TRANSMIT_CHL].dlc); can_put_echo_skb(skb, dev, 0); /* set transmit request */ - bfin_write(®->trs2, BIT(TRANSMIT_CHL - 16)); + writew(BIT(TRANSMIT_CHL - 16), ®->trs2); return 0; } @@ -296,26 +400,26 @@ static void bfin_can_rx(struct net_device *dev, u16 isrc) /* get id */ if (isrc & BIT(RECEIVE_EXT_CHL)) { /* extended frame format (EFF) */ - cf->can_id = ((bfin_read(®->chl[RECEIVE_EXT_CHL].id1) + cf->can_id = ((readw(®->chl[RECEIVE_EXT_CHL].id1) & 0x1FFF) << 16) - + bfin_read(®->chl[RECEIVE_EXT_CHL].id0); + + readw(®->chl[RECEIVE_EXT_CHL].id0); cf->can_id |= CAN_EFF_FLAG; obj = RECEIVE_EXT_CHL; } else { /* standard frame format (SFF) */ - cf->can_id = (bfin_read(®->chl[RECEIVE_STD_CHL].id1) + cf->can_id = (readw(®->chl[RECEIVE_STD_CHL].id1) & 0x1ffc) >> 2; obj = RECEIVE_STD_CHL; } - if (bfin_read(®->chl[obj].id1) & RTR) + if (readw(®->chl[obj].id1) & RTR) cf->can_id |= CAN_RTR_FLAG; /* get data length code */ - cf->can_dlc = get_can_dlc(bfin_read(®->chl[obj].dlc) & 0xF); + cf->can_dlc = get_can_dlc(readw(®->chl[obj].dlc) & 0xF); /* get payload */ for (i = 0; i < 8; i += 2) { - val = bfin_read(®->chl[obj].data[i]); + val = readw(®->chl[obj].data[i]); cf->data[7 - i] = (7 - i) < cf->can_dlc ? val : 0; cf->data[6 - i] = (6 - i) < cf->can_dlc ? (val >> 8) : 0; } @@ -369,7 +473,7 @@ static int bfin_can_err(struct net_device *dev, u16 isrc, u16 status) if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING || state == CAN_STATE_ERROR_PASSIVE)) { - u16 cec = bfin_read(®->cec); + u16 cec = readw(®->cec); u8 rxerr = cec; u8 txerr = cec >> 8; @@ -420,23 +524,23 @@ static irqreturn_t bfin_can_interrupt(int irq, void *dev_id) struct net_device_stats *stats = &dev->stats; u16 status, isrc; - if ((irq == priv->tx_irq) && bfin_read(®->mbtif2)) { + if ((irq == priv->tx_irq) && readw(®->mbtif2)) { /* transmission complete interrupt */ - bfin_write(®->mbtif2, 0xFFFF); + writew(0xFFFF, ®->mbtif2); stats->tx_packets++; - stats->tx_bytes += bfin_read(®->chl[TRANSMIT_CHL].dlc); + stats->tx_bytes += readw(®->chl[TRANSMIT_CHL].dlc); can_get_echo_skb(dev, 0); netif_wake_queue(dev); - } else if ((irq == priv->rx_irq) && bfin_read(®->mbrif1)) { + } else if ((irq == priv->rx_irq) && readw(®->mbrif1)) { /* receive interrupt */ - isrc = bfin_read(®->mbrif1); - bfin_write(®->mbrif1, 0xFFFF); + isrc = readw(®->mbrif1); + writew(0xFFFF, ®->mbrif1); bfin_can_rx(dev, isrc); - } else if ((irq == priv->err_irq) && bfin_read(®->gis)) { + } else if ((irq == priv->err_irq) && readw(®->gis)) { /* error interrupt */ - isrc = bfin_read(®->gis); - status = bfin_read(®->esr); - bfin_write(®->gis, 0x7FF); + isrc = readw(®->gis); + status = readw(®->esr); + writew(0x7FF, ®->gis); bfin_can_err(dev, isrc, status); } else { return IRQ_NONE; @@ -556,16 +660,10 @@ static int bfin_can_probe(struct platform_device *pdev) goto exit; } - if (!request_mem_region(res_mem->start, resource_size(res_mem), - dev_name(&pdev->dev))) { - err = -EBUSY; - goto exit; - } - /* request peripheral pins */ err = peripheral_request_list(pdata, dev_name(&pdev->dev)); if (err) - goto exit_mem_release; + goto exit; dev = alloc_bfin_candev(); if (!dev) { @@ -574,7 +672,13 @@ static int bfin_can_probe(struct platform_device *pdev) } priv = netdev_priv(dev); - priv->membase = (void __iomem *)res_mem->start; + + priv->membase = devm_ioremap_resource(&pdev->dev, res_mem); + if (IS_ERR(priv->membase)) { + err = PTR_ERR(priv->membase); + goto exit_peri_pin_free; + } + priv->rx_irq = rx_irq->start; priv->tx_irq = tx_irq->start; priv->err_irq = err_irq->start; @@ -606,8 +710,6 @@ exit_candev_free: free_candev(dev); exit_peri_pin_free: peripheral_free_list(pdata); -exit_mem_release: - release_mem_region(res_mem->start, resource_size(res_mem)); exit: return err; } @@ -616,15 +718,11 @@ static int bfin_can_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct bfin_can_priv *priv = netdev_priv(dev); - struct resource *res; bfin_can_set_reset_mode(dev); unregister_candev(dev); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, resource_size(res)); - peripheral_free_list(priv->pin_list); free_candev(dev); @@ -641,9 +739,8 @@ static int bfin_can_suspend(struct platform_device *pdev, pm_message_t mesg) if (netif_running(dev)) { /* enter sleep mode */ - bfin_write(®->control, bfin_read(®->control) | SMR); - SSYNC(); - while (!(bfin_read(®->intr) & SMACK)) { + writew(readw(®->control) | SMR, ®->control); + while (!(readw(®->intr) & SMACK)) { udelay(10); if (--timeout == 0) { netdev_err(dev, "fail to enter sleep mode\n"); @@ -663,8 +760,7 @@ static int bfin_can_resume(struct platform_device *pdev) if (netif_running(dev)) { /* leave sleep mode */ - bfin_write(®->intr, 0); - SSYNC(); + writew(0, ®->intr); } return 0; diff --git a/drivers/net/can/cc770/cc770_platform.c b/drivers/net/can/cc770/cc770_platform.c index b1e8851d3cc4..866e5e12fdd2 100644 --- a/drivers/net/can/cc770/cc770_platform.c +++ b/drivers/net/can/cc770/cc770_platform.c @@ -254,7 +254,7 @@ static int cc770_platform_remove(struct platform_device *pdev) return 0; } -static struct of_device_id cc770_platform_table[] = { +static const struct of_device_id cc770_platform_table[] = { {.compatible = "bosch,cc770"}, /* CC770 from Bosch */ {.compatible = "intc,82527"}, /* AN82527 from Intel CP */ {}, diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 80c46ad4cee4..ad0a7e8c2c2b 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -592,13 +592,12 @@ static int flexcan_poll_state(struct net_device *dev, u32 reg_esr) rx_state = unlikely(reg_esr & FLEXCAN_ESR_RX_WRN) ? CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE; new_state = max(tx_state, rx_state); - } else if (unlikely(flt == FLEXCAN_ESR_FLT_CONF_PASSIVE)) { + } else { __flexcan_get_berr_counter(dev, &bec); - new_state = CAN_STATE_ERROR_PASSIVE; + new_state = flt == FLEXCAN_ESR_FLT_CONF_PASSIVE ? + CAN_STATE_ERROR_PASSIVE : CAN_STATE_BUS_OFF; rx_state = bec.rxerr >= bec.txerr ? new_state : 0; tx_state = bec.rxerr <= bec.txerr ? new_state : 0; - } else { - new_state = CAN_STATE_BUS_OFF; } /* state hasn't changed */ @@ -1158,12 +1157,19 @@ static int flexcan_probe(struct platform_device *pdev) const struct flexcan_devtype_data *devtype_data; struct net_device *dev; struct flexcan_priv *priv; + struct regulator *reg_xceiver; struct resource *mem; struct clk *clk_ipg = NULL, *clk_per = NULL; void __iomem *base; int err, irq; u32 clock_freq = 0; + reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver"); + if (PTR_ERR(reg_xceiver) == -EPROBE_DEFER) + return -EPROBE_DEFER; + else if (IS_ERR(reg_xceiver)) + reg_xceiver = NULL; + if (pdev->dev.of_node) of_property_read_u32(pdev->dev.of_node, "clock-frequency", &clock_freq); @@ -1224,9 +1230,7 @@ static int flexcan_probe(struct platform_device *pdev) priv->pdata = dev_get_platdata(&pdev->dev); priv->devtype_data = devtype_data; - priv->reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver"); - if (IS_ERR(priv->reg_xceiver)) - priv->reg_xceiver = NULL; + priv->reg_xceiver = reg_xceiver; netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT); diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c index fed1bbd0b0d2..e3d7e22a4fa0 100644 --- a/drivers/net/can/grcan.c +++ b/drivers/net/can/grcan.c @@ -1725,7 +1725,7 @@ static int grcan_remove(struct platform_device *ofdev) return 0; } -static struct of_device_id grcan_match[] = { +static const struct of_device_id grcan_match[] = { {.name = "GAISLER_GRCAN"}, {.name = "01_03d"}, {.name = "GAISLER_GRHCAN"}, diff --git a/drivers/net/can/led.c b/drivers/net/can/led.c index ab7f1b01be49..c1b667675fa1 100644 --- a/drivers/net/can/led.c +++ b/drivers/net/can/led.c @@ -30,20 +30,28 @@ void can_led_event(struct net_device *netdev, enum can_led_event event) case CAN_LED_EVENT_OPEN: led_trigger_event(priv->tx_led_trig, LED_FULL); led_trigger_event(priv->rx_led_trig, LED_FULL); + led_trigger_event(priv->rxtx_led_trig, LED_FULL); break; case CAN_LED_EVENT_STOP: led_trigger_event(priv->tx_led_trig, LED_OFF); led_trigger_event(priv->rx_led_trig, LED_OFF); + led_trigger_event(priv->rxtx_led_trig, LED_OFF); break; case CAN_LED_EVENT_TX: - if (led_delay) + if (led_delay) { led_trigger_blink_oneshot(priv->tx_led_trig, &led_delay, &led_delay, 1); + led_trigger_blink_oneshot(priv->rxtx_led_trig, + &led_delay, &led_delay, 1); + } break; case CAN_LED_EVENT_RX: - if (led_delay) + if (led_delay) { led_trigger_blink_oneshot(priv->rx_led_trig, &led_delay, &led_delay, 1); + led_trigger_blink_oneshot(priv->rxtx_led_trig, + &led_delay, &led_delay, 1); + } break; } } @@ -55,6 +63,7 @@ static void can_led_release(struct device *gendev, void *res) led_trigger_unregister_simple(priv->tx_led_trig); led_trigger_unregister_simple(priv->rx_led_trig); + led_trigger_unregister_simple(priv->rxtx_led_trig); } /* Register CAN LED triggers for a CAN device @@ -76,11 +85,15 @@ void devm_can_led_init(struct net_device *netdev) "%s-tx", netdev->name); snprintf(priv->rx_led_trig_name, sizeof(priv->rx_led_trig_name), "%s-rx", netdev->name); + snprintf(priv->rxtx_led_trig_name, sizeof(priv->rxtx_led_trig_name), + "%s-rxtx", netdev->name); led_trigger_register_simple(priv->tx_led_trig_name, &priv->tx_led_trig); led_trigger_register_simple(priv->rx_led_trig_name, &priv->rx_led_trig); + led_trigger_register_simple(priv->rxtx_led_trig_name, + &priv->rxtx_led_trig); devres_add(&netdev->dev, res); } @@ -97,7 +110,7 @@ static int can_led_notifier(struct notifier_block *nb, unsigned long msg, if (!priv) return NOTIFY_DONE; - if (!priv->tx_led_trig || !priv->rx_led_trig) + if (!priv->tx_led_trig || !priv->rx_led_trig || !priv->rxtx_led_trig) return NOTIFY_DONE; if (msg == NETDEV_CHANGENAME) { @@ -106,6 +119,9 @@ static int can_led_notifier(struct notifier_block *nb, unsigned long msg, snprintf(name, sizeof(name), "%s-rx", netdev->name); led_trigger_rename_static(name, priv->rx_led_trig); + + snprintf(name, sizeof(name), "%s-rxtx", netdev->name); + led_trigger_rename_static(name, priv->rxtx_led_trig); } return NOTIFY_DONE; diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index 2e04b3aeeb37..ef655177bb5e 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -312,8 +312,8 @@ static inline u32 m_can_fifo_read(const struct m_can_priv *priv, static inline void m_can_fifo_write(const struct m_can_priv *priv, u32 fpi, unsigned int offset, u32 val) { - return writel(val, priv->mram_base + priv->mcfg[MRAM_TXB].off + - fpi * TXB_ELEMENT_SIZE + offset); + writel(val, priv->mram_base + priv->mcfg[MRAM_TXB].off + + fpi * TXB_ELEMENT_SIZE + offset); } static inline void m_can_config_endisable(const struct m_can_priv *priv, diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index ad024e60ba8c..c7427bdd3a4b 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -43,7 +43,7 @@ struct mpc5xxx_can_data { }; #ifdef CONFIG_PPC_MPC52xx -static struct of_device_id mpc52xx_cdm_ids[] = { +static const struct of_device_id mpc52xx_cdm_ids[] = { { .compatible = "fsl,mpc5200-cdm", }, {} }; diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c index 93115250eaf5..0552ed46a206 100644 --- a/drivers/net/can/sja1000/sja1000_platform.c +++ b/drivers/net/can/sja1000/sja1000_platform.c @@ -242,7 +242,7 @@ static int sp_remove(struct platform_device *pdev) return 0; } -static struct of_device_id sp_of_table[] = { +static const struct of_device_id sp_of_table[] = { {.compatible = "nxp,sja1000"}, {}, }; diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index 9376f5e5b94e..866bac0ae7e9 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -123,7 +123,7 @@ MODULE_LICENSE("GPL v2"); * CPC_MSG_TYPE_EXT_CAN_FRAME or CPC_MSG_TYPE_EXT_RTR_FRAME. */ struct cpc_can_msg { - u32 id; + __le32 id; u8 length; u8 msg[8]; }; @@ -200,8 +200,8 @@ struct __packed ems_cpc_msg { u8 type; /* type of message */ u8 length; /* length of data within union 'msg' */ u8 msgid; /* confirmation handle */ - u32 ts_sec; /* timestamp in seconds */ - u32 ts_nsec; /* timestamp in nano seconds */ + __le32 ts_sec; /* timestamp in seconds */ + __le32 ts_nsec; /* timestamp in nano seconds */ union { u8 generic[64]; @@ -765,7 +765,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne msg = (struct ems_cpc_msg *)&buf[CPC_HEADER_SIZE]; - msg->msg.can_msg.id = cf->can_id & CAN_ERR_MASK; + msg->msg.can_msg.id = cpu_to_le32(cf->can_id & CAN_ERR_MASK); msg->msg.can_msg.length = cf->can_dlc; if (cf->can_id & CAN_RTR_FLAG) { @@ -783,9 +783,6 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne msg->length = CPC_CAN_MSG_MIN_SIZE + cf->can_dlc; } - /* Respect byte order */ - msg->msg.can_msg.id = cpu_to_le32(msg->msg.can_msg.id); - for (i = 0; i < MAX_TX_URBS; i++) { if (dev->tx_contexts[i].echo_index == MAX_TX_URBS) { context = &dev->tx_contexts[i]; diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c index bacca0bd89c1..411c1af92c62 100644 --- a/drivers/net/can/usb/esd_usb2.c +++ b/drivers/net/can/usb/esd_usb2.c @@ -139,7 +139,7 @@ struct tx_msg { u8 cmd; u8 net; u8 dlc; - __le32 hnd; + u32 hnd; /* opaque handle, not used by device */ __le32 id; /* upper 3 bits contain flags */ u8 data[8]; }; @@ -149,7 +149,7 @@ struct tx_done_msg { u8 cmd; u8 net; u8 status; - __le32 hnd; + u32 hnd; /* opaque handle, not used by device */ __le32 ts; }; diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 009acc8641fc..8b4d3e6875eb 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -901,6 +901,8 @@ static int gs_usb_probe(struct usb_interface *intf, const struct usb_device_id * } dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; init_usb_anchor(&dev->rx_submitted); atomic_set(&dev->active_channels, 0); diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c index a316fa4b91ab..4643914859b2 100644 --- a/drivers/net/can/usb/kvaser_usb.c +++ b/drivers/net/can/usb/kvaser_usb.c @@ -14,6 +14,7 @@ * Copyright (C) 2015 Valeo S.A. */ +#include <linux/spinlock.h> #include <linux/kernel.h> #include <linux/completion.h> #include <linux/module.h> @@ -24,7 +25,6 @@ #include <linux/can/dev.h> #include <linux/can/error.h> -#define MAX_TX_URBS 16 #define MAX_RX_URBS 4 #define START_TIMEOUT 1000 /* msecs */ #define STOP_TIMEOUT 1000 /* msecs */ @@ -442,6 +442,7 @@ struct kvaser_usb_error_summary { }; }; +/* Context for an outstanding, not yet ACKed, transmission */ struct kvaser_usb_tx_urb_context { struct kvaser_usb_net_priv *priv; u32 echo_index; @@ -455,8 +456,13 @@ struct kvaser_usb { struct usb_endpoint_descriptor *bulk_in, *bulk_out; struct usb_anchor rx_submitted; + /* @max_tx_urbs: Firmware-reported maximum number of oustanding, + * not yet ACKed, transmissions on this device. This value is + * also used as a sentinel for marking free tx contexts. + */ u32 fw_version; unsigned int nchannels; + unsigned int max_tx_urbs; enum kvaser_usb_family family; bool rxinitdone; @@ -466,18 +472,18 @@ struct kvaser_usb { struct kvaser_usb_net_priv { struct can_priv can; - - atomic_t active_tx_urbs; - struct usb_anchor tx_submitted; - struct kvaser_usb_tx_urb_context tx_contexts[MAX_TX_URBS]; - - struct completion start_comp, stop_comp; + struct can_berr_counter bec; struct kvaser_usb *dev; struct net_device *netdev; int channel; - struct can_berr_counter bec; + struct completion start_comp, stop_comp; + struct usb_anchor tx_submitted; + + spinlock_t tx_contexts_lock; + int active_tx_contexts; + struct kvaser_usb_tx_urb_context tx_contexts[]; }; static const struct usb_device_id kvaser_usb_table[] = { @@ -590,8 +596,8 @@ static int kvaser_usb_wait_msg(const struct kvaser_usb *dev, u8 id, * for further details. */ if (tmp->len == 0) { - pos = round_up(pos, - dev->bulk_in->wMaxPacketSize); + pos = round_up(pos, le16_to_cpu(dev->bulk_in-> + wMaxPacketSize)); continue; } @@ -655,9 +661,13 @@ static int kvaser_usb_get_software_info(struct kvaser_usb *dev) switch (dev->family) { case KVASER_LEAF: dev->fw_version = le32_to_cpu(msg.u.leaf.softinfo.fw_version); + dev->max_tx_urbs = + le16_to_cpu(msg.u.leaf.softinfo.max_outstanding_tx); break; case KVASER_USBCAN: dev->fw_version = le32_to_cpu(msg.u.usbcan.softinfo.fw_version); + dev->max_tx_urbs = + le16_to_cpu(msg.u.usbcan.softinfo.max_outstanding_tx); break; } @@ -694,6 +704,7 @@ static void kvaser_usb_tx_acknowledge(const struct kvaser_usb *dev, struct kvaser_usb_net_priv *priv; struct sk_buff *skb; struct can_frame *cf; + unsigned long flags; u8 channel, tid; channel = msg->u.tx_acknowledge_header.channel; @@ -712,7 +723,7 @@ static void kvaser_usb_tx_acknowledge(const struct kvaser_usb *dev, stats = &priv->netdev->stats; - context = &priv->tx_contexts[tid % MAX_TX_URBS]; + context = &priv->tx_contexts[tid % dev->max_tx_urbs]; /* Sometimes the state change doesn't come after a bus-off event */ if (priv->can.restart_ms && @@ -737,12 +748,15 @@ static void kvaser_usb_tx_acknowledge(const struct kvaser_usb *dev, stats->tx_packets++; stats->tx_bytes += context->dlc; - can_get_echo_skb(priv->netdev, context->echo_index); - context->echo_index = MAX_TX_URBS; - atomic_dec(&priv->active_tx_urbs); + spin_lock_irqsave(&priv->tx_contexts_lock, flags); + can_get_echo_skb(priv->netdev, context->echo_index); + context->echo_index = dev->max_tx_urbs; + --priv->active_tx_contexts; netif_wake_queue(priv->netdev); + + spin_unlock_irqrestore(&priv->tx_contexts_lock, flags); } static void kvaser_usb_simple_msg_callback(struct urb *urb) @@ -803,17 +817,6 @@ static int kvaser_usb_simple_msg_async(struct kvaser_usb_net_priv *priv, return 0; } -static void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv) -{ - int i; - - usb_kill_anchored_urbs(&priv->tx_submitted); - atomic_set(&priv->active_tx_urbs, 0); - - for (i = 0; i < MAX_TX_URBS; i++) - priv->tx_contexts[i].echo_index = MAX_TX_URBS; -} - static void kvaser_usb_rx_error_update_can_state(struct kvaser_usb_net_priv *priv, const struct kvaser_usb_error_summary *es, struct can_frame *cf) @@ -1334,7 +1337,8 @@ static void kvaser_usb_read_bulk_callback(struct urb *urb) * number of events in case of a heavy rx load on the bus. */ if (msg->len == 0) { - pos = round_up(pos, dev->bulk_in->wMaxPacketSize); + pos = round_up(pos, le16_to_cpu(dev->bulk_in-> + wMaxPacketSize)); continue; } @@ -1515,6 +1519,26 @@ error: return err; } +static void kvaser_usb_reset_tx_urb_contexts(struct kvaser_usb_net_priv *priv) +{ + int i, max_tx_urbs; + + max_tx_urbs = priv->dev->max_tx_urbs; + + priv->active_tx_contexts = 0; + for (i = 0; i < max_tx_urbs; i++) + priv->tx_contexts[i].echo_index = max_tx_urbs; +} + +/* This method might sleep. Do not call it in the atomic context + * of URB completions. + */ +static void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv) +{ + usb_kill_anchored_urbs(&priv->tx_submitted); + kvaser_usb_reset_tx_urb_contexts(priv); +} + static void kvaser_usb_unlink_all_urbs(struct kvaser_usb *dev) { int i; @@ -1634,6 +1658,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb, struct kvaser_msg *msg; int i, err, ret = NETDEV_TX_OK; u8 *msg_tx_can_flags = NULL; /* GCC */ + unsigned long flags; if (can_dropped_invalid_skb(netdev, skb)) return NETDEV_TX_OK; @@ -1687,12 +1712,21 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb, if (cf->can_id & CAN_RTR_FLAG) *msg_tx_can_flags |= MSG_FLAG_REMOTE_FRAME; - for (i = 0; i < ARRAY_SIZE(priv->tx_contexts); i++) { - if (priv->tx_contexts[i].echo_index == MAX_TX_URBS) { + spin_lock_irqsave(&priv->tx_contexts_lock, flags); + for (i = 0; i < dev->max_tx_urbs; i++) { + if (priv->tx_contexts[i].echo_index == dev->max_tx_urbs) { context = &priv->tx_contexts[i]; + + context->echo_index = i; + can_put_echo_skb(skb, netdev, context->echo_index); + ++priv->active_tx_contexts; + if (priv->active_tx_contexts >= dev->max_tx_urbs) + netif_stop_queue(netdev); + break; } } + spin_unlock_irqrestore(&priv->tx_contexts_lock, flags); /* This should never happen; it implies a flow control bug */ if (!context) { @@ -1704,7 +1738,6 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb, } context->priv = priv; - context->echo_index = i; context->dlc = cf->can_dlc; msg->u.tx_can.tid = context->echo_index; @@ -1716,18 +1749,17 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb, kvaser_usb_write_bulk_callback, context); usb_anchor_urb(urb, &priv->tx_submitted); - can_put_echo_skb(skb, netdev, context->echo_index); - - atomic_inc(&priv->active_tx_urbs); - - if (atomic_read(&priv->active_tx_urbs) >= MAX_TX_URBS) - netif_stop_queue(netdev); - err = usb_submit_urb(urb, GFP_ATOMIC); if (unlikely(err)) { + spin_lock_irqsave(&priv->tx_contexts_lock, flags); + can_free_echo_skb(netdev, context->echo_index); + context->echo_index = dev->max_tx_urbs; + --priv->active_tx_contexts; + netif_wake_queue(netdev); + + spin_unlock_irqrestore(&priv->tx_contexts_lock, flags); - atomic_dec(&priv->active_tx_urbs); usb_unanchor_urb(urb); stats->tx_dropped++; @@ -1835,7 +1867,7 @@ static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev) if (!dev->nets[i]) continue; - unregister_netdev(dev->nets[i]->netdev); + unregister_candev(dev->nets[i]->netdev); } kvaser_usb_unlink_all_urbs(dev); @@ -1854,13 +1886,15 @@ static int kvaser_usb_init_one(struct usb_interface *intf, struct kvaser_usb *dev = usb_get_intfdata(intf); struct net_device *netdev; struct kvaser_usb_net_priv *priv; - int i, err; + int err; err = kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, channel); if (err) return err; - netdev = alloc_candev(sizeof(*priv), MAX_TX_URBS); + netdev = alloc_candev(sizeof(*priv) + + dev->max_tx_urbs * sizeof(*priv->tx_contexts), + dev->max_tx_urbs); if (!netdev) { dev_err(&intf->dev, "Cannot alloc candev\n"); return -ENOMEM; @@ -1868,19 +1902,17 @@ static int kvaser_usb_init_one(struct usb_interface *intf, priv = netdev_priv(netdev); + init_usb_anchor(&priv->tx_submitted); init_completion(&priv->start_comp); init_completion(&priv->stop_comp); - init_usb_anchor(&priv->tx_submitted); - atomic_set(&priv->active_tx_urbs, 0); - - for (i = 0; i < ARRAY_SIZE(priv->tx_contexts); i++) - priv->tx_contexts[i].echo_index = MAX_TX_URBS; - priv->dev = dev; priv->netdev = netdev; priv->channel = channel; + spin_lock_init(&priv->tx_contexts_lock); + kvaser_usb_reset_tx_urb_contexts(priv); + priv->can.state = CAN_STATE_STOPPED; priv->can.clock.freq = CAN_USB_CLOCK; priv->can.bittiming_const = &kvaser_usb_bittiming_const; @@ -1990,6 +2022,13 @@ static int kvaser_usb_probe(struct usb_interface *intf, return err; } + dev_dbg(&intf->dev, "Firmware version: %d.%d.%d\n", + ((dev->fw_version >> 24) & 0xff), + ((dev->fw_version >> 16) & 0xff), + (dev->fw_version & 0xffff)); + + dev_dbg(&intf->dev, "Max oustanding tx = %d URBs\n", dev->max_tx_urbs); + err = kvaser_usb_get_card_info(dev); if (err) { dev_err(&intf->dev, @@ -1997,11 +2036,6 @@ static int kvaser_usb_probe(struct usb_interface *intf, return err; } - dev_dbg(&intf->dev, "Firmware version: %d.%d.%d\n", - ((dev->fw_version >> 24) & 0xff), - ((dev->fw_version >> 16) & 0xff), - (dev->fw_version & 0xffff)); - for (i = 0; i < dev->nchannels; i++) { err = kvaser_usb_init_one(intf, id, i); if (err) { diff --git a/drivers/net/can/usb/peak_usb/pcan_ucan.h b/drivers/net/can/usb/peak_usb/pcan_ucan.h index 1ba7c25002e1..e8fc4952c6b0 100644 --- a/drivers/net/can/usb/peak_usb/pcan_ucan.h +++ b/drivers/net/can/usb/peak_usb/pcan_ucan.h @@ -26,8 +26,8 @@ #define PUCAN_CMD_FILTER_STD 0x008 #define PUCAN_CMD_TX_ABORT 0x009 #define PUCAN_CMD_WR_ERR_CNT 0x00a -#define PUCAN_CMD_RX_FRAME_ENABLE 0x00b -#define PUCAN_CMD_RX_FRAME_DISABLE 0x00c +#define PUCAN_CMD_SET_EN_OPTION 0x00b +#define PUCAN_CMD_CLR_DIS_OPTION 0x00c #define PUCAN_CMD_END_OF_COLLECTION 0x3ff /* uCAN received messages list */ @@ -101,14 +101,15 @@ struct __packed pucan_wr_err_cnt { u16 unused; }; -/* uCAN RX_FRAME_ENABLE command fields */ -#define PUCAN_FLTEXT_ERROR 0x0001 -#define PUCAN_FLTEXT_BUSLOAD 0x0002 +/* uCAN SET_EN/CLR_DIS _OPTION command fields */ +#define PUCAN_OPTION_ERROR 0x0001 +#define PUCAN_OPTION_BUSLOAD 0x0002 +#define PUCAN_OPTION_CANDFDISO 0x0004 -struct __packed pucan_filter_ext { +struct __packed pucan_options { __le16 opcode_channel; - __le16 ext_mask; + __le16 options; u32 unused; }; diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c index 0bac0f14edc3..09d14e70abd7 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c @@ -110,13 +110,13 @@ struct __packed pcan_ufd_led { u8 unused[5]; }; -/* Extended usage of uCAN commands CMD_RX_FRAME_xxxABLE for PCAN-USB Pro FD */ +/* Extended usage of uCAN commands CMD_xxx_xx_OPTION for PCAN-USB Pro FD */ #define PCAN_UFD_FLTEXT_CALIBRATION 0x8000 -struct __packed pcan_ufd_filter_ext { +struct __packed pcan_ufd_options { __le16 opcode_channel; - __le16 ext_mask; + __le16 ucan_mask; u16 unused; __le16 usb_mask; }; @@ -182,7 +182,7 @@ static inline void *pcan_usb_fd_cmd_buffer(struct peak_usb_device *dev) static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail) { void *cmd_head = pcan_usb_fd_cmd_buffer(dev); - int err; + int err = 0; u8 *packet_ptr; int i, n = 1, packet_len; ptrdiff_t cmd_len; @@ -251,6 +251,27 @@ static int pcan_usb_fd_build_restart_cmd(struct peak_usb_device *dev, u8 *buf) /* moves the pointer forward */ pc += sizeof(struct pucan_wr_err_cnt); + /* add command to switch from ISO to non-ISO mode, if fw allows it */ + if (dev->can.ctrlmode_supported & CAN_CTRLMODE_FD_NON_ISO) { + struct pucan_options *puo = (struct pucan_options *)pc; + + puo->opcode_channel = + (dev->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO) ? + pucan_cmd_opcode_channel(dev, + PUCAN_CMD_CLR_DIS_OPTION) : + pucan_cmd_opcode_channel(dev, PUCAN_CMD_SET_EN_OPTION); + + puo->options = cpu_to_le16(PUCAN_OPTION_CANDFDISO); + + /* to be sure that no other extended bits will be taken into + * account + */ + puo->unused = 0; + + /* moves the pointer forward */ + pc += sizeof(struct pucan_options); + } + /* next, go back to operational mode */ cmd = (struct pucan_command *)pc; cmd->opcode_channel = pucan_cmd_opcode_channel(dev, @@ -321,21 +342,21 @@ static int pcan_usb_fd_set_filter_std(struct peak_usb_device *dev, int idx, return pcan_usb_fd_send_cmd(dev, cmd); } -/* set/unset notifications filter: +/* set/unset options * - * onoff sets(1)/unset(0) notifications - * mask each bit defines a kind of notification to set/unset + * onoff set(1)/unset(0) options + * mask each bit defines a kind of options to set/unset */ -static int pcan_usb_fd_set_filter_ext(struct peak_usb_device *dev, - bool onoff, u16 ext_mask, u16 usb_mask) +static int pcan_usb_fd_set_options(struct peak_usb_device *dev, + bool onoff, u16 ucan_mask, u16 usb_mask) { - struct pcan_ufd_filter_ext *cmd = pcan_usb_fd_cmd_buffer(dev); + struct pcan_ufd_options *cmd = pcan_usb_fd_cmd_buffer(dev); cmd->opcode_channel = pucan_cmd_opcode_channel(dev, - (onoff) ? PUCAN_CMD_RX_FRAME_ENABLE : - PUCAN_CMD_RX_FRAME_DISABLE); + (onoff) ? PUCAN_CMD_SET_EN_OPTION : + PUCAN_CMD_CLR_DIS_OPTION); - cmd->ext_mask = cpu_to_le16(ext_mask); + cmd->ucan_mask = cpu_to_le16(ucan_mask); cmd->usb_mask = cpu_to_le16(usb_mask); /* send the command */ @@ -770,9 +791,9 @@ static int pcan_usb_fd_start(struct peak_usb_device *dev) &pcan_usb_pro_fd); /* enable USB calibration messages */ - err = pcan_usb_fd_set_filter_ext(dev, 1, - PUCAN_FLTEXT_ERROR, - PCAN_UFD_FLTEXT_CALIBRATION); + err = pcan_usb_fd_set_options(dev, 1, + PUCAN_OPTION_ERROR, + PCAN_UFD_FLTEXT_CALIBRATION); } pdev->usb_if->dev_opened_count++; @@ -806,9 +827,9 @@ static int pcan_usb_fd_stop(struct peak_usb_device *dev) /* turn off special msgs for that interface if no other dev opened */ if (pdev->usb_if->dev_opened_count == 1) - pcan_usb_fd_set_filter_ext(dev, 0, - PUCAN_FLTEXT_ERROR, - PCAN_UFD_FLTEXT_CALIBRATION); + pcan_usb_fd_set_options(dev, 0, + PUCAN_OPTION_ERROR, + PCAN_UFD_FLTEXT_CALIBRATION); pdev->usb_if->dev_opened_count--; return 0; @@ -860,8 +881,14 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev) pdev->usb_if->fw_info.fw_version[2], dev->adapter->ctrl_count); - /* the currently supported hw is non-ISO */ - dev->can.ctrlmode = CAN_CTRLMODE_FD_NON_ISO; + /* check for ability to switch between ISO/non-ISO modes */ + if (pdev->usb_if->fw_info.fw_version[0] >= 2) { + /* firmware >= 2.x supports ISO/non-ISO switching */ + dev->can.ctrlmode_supported |= CAN_CTRLMODE_FD_NON_ISO; + } else { + /* firmware < 2.x only supports fixed(!) non-ISO */ + dev->can.ctrlmode |= CAN_CTRLMODE_FD_NON_ISO; + } /* tell the hardware the can driver is running */ err = pcan_usb_fd_drv_loaded(dev, 1); @@ -937,9 +964,9 @@ static void pcan_usb_fd_exit(struct peak_usb_device *dev) if (dev->ctrl_idx == 0) { /* turn off calibration message if any device were opened */ if (pdev->usb_if->dev_opened_count > 0) - pcan_usb_fd_set_filter_ext(dev, 0, - PUCAN_FLTEXT_ERROR, - PCAN_UFD_FLTEXT_CALIBRATION); + pcan_usb_fd_set_options(dev, 0, + PUCAN_OPTION_ERROR, + PCAN_UFD_FLTEXT_CALIBRATION); /* tell USB adapter that the driver is being unloaded */ pcan_usb_fd_drv_loaded(dev, 0); diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 6c6764312285..6bddfe062b51 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -1185,7 +1185,7 @@ static int xcan_remove(struct platform_device *pdev) } /* Match table for OF platform binding */ -static struct of_device_id xcan_of_match[] = { +static const struct of_device_id xcan_of_match[] = { { .compatible = "xlnx,zynq-can-1.0", }, { .compatible = "xlnx,axi-can-1.00.a", }, { /* end of list */ }, |