Commit d20e5880 authored by David S. Miller's avatar David S. Miller

Merge tag 'linux-can-next-for-5.15-20210725' of...

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

linux-can-next-for-5.15-20210725

Marc Kleine-Budde says:

====================
pull-request: can-next 2021-07-25

this is a pull request of 46 patches for net-next/master.

The first 6 patches target the CAN J1939 protocol. One is from
gushengxian, fixing a grammatical error, 5 are by me fixing a checkpatch
warning, make use of the fallthrough pseudo-keyword, and use
consistent variable naming.

The next 3 patches target the rx-offload helper, are by me and improve
the performance and fix the local softirq work pending error, when
napi_schedule() is called from threaded IRQ context.

The next 3 patches are by Vincent Mailhol and me update the CAN
bittiming and transmitter delay compensation, the documentation for
the struct can_tdc is fixed, clear data_bittiming if FD mode is turned
off and a redundant check is removed.

Followed by 4 patches targeting the m_can driver. Faiz Abbas's patches
add support for CAN PHY via the generic phy subsystem. Yang Yingliang
converts the driver to use devm_platform_ioremap_resource_byname().
And a patch by me which removes the unused support for custom bit
timing.

Andy Shevchenko contributes 2 patches for the mcp251xfd driver to
prepare the driver for ACPI support. A patch by me adds support for
shared IRQ handlers.

Zhen Lei contributes 3 patches to convert the esd_usb2, janz-ican3 and
the at91_can driver to make use of the DEVICE_ATTR_RO/RW() macros.

The next 8 patches are by Peng Li and provide general cleanups for the
at91_can driver.

The next 7 patches target the peak driver. Frist 2 cleanup patches by
me for the peak_pci driver, followed by Stephane Grosjean' patch to
print the name and firmware version of the detected hardware. The
peak_usb driver gets a cleanup patch, loopback and one-shot mode and
an upgrading of the bus state change handling in Stephane Grosjean's
patches.

Vincent Mailhol provides 6 cleanup patches for the etas_es58x driver.

In the last 3 patches Angelo Dureghello add support for the mcf5441x
SoC to the flexcan driver.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents af996031 8dad5561
...@@ -107,6 +107,9 @@ properties: ...@@ -107,6 +107,9 @@ properties:
can-transceiver: can-transceiver:
$ref: can-transceiver.yaml# $ref: can-transceiver.yaml#
phys:
maxItems: 1
required: required:
- compatible - compatible
- reg - reg
......
...@@ -97,7 +97,8 @@ config CAN_AT91 ...@@ -97,7 +97,8 @@ config CAN_AT91
config CAN_FLEXCAN config CAN_FLEXCAN
tristate "Support for Freescale FLEXCAN based chips" tristate "Support for Freescale FLEXCAN based chips"
depends on OF && HAS_IOMEM depends on OF || COLDFIRE || COMPILE_TEST
depends on HAS_IOMEM
help help
Say Y here if you want to support for Freescale FlexCAN. Say Y here if you want to support for Freescale FlexCAN.
......
...@@ -43,14 +43,14 @@ enum at91_reg { ...@@ -43,14 +43,14 @@ enum at91_reg {
}; };
/* Mailbox registers (0 <= i <= 15) */ /* Mailbox registers (0 <= i <= 15) */
#define AT91_MMR(i) (enum at91_reg)(0x200 + ((i) * 0x20)) #define AT91_MMR(i) ((enum at91_reg)(0x200 + ((i) * 0x20)))
#define AT91_MAM(i) (enum at91_reg)(0x204 + ((i) * 0x20)) #define AT91_MAM(i) ((enum at91_reg)(0x204 + ((i) * 0x20)))
#define AT91_MID(i) (enum at91_reg)(0x208 + ((i) * 0x20)) #define AT91_MID(i) ((enum at91_reg)(0x208 + ((i) * 0x20)))
#define AT91_MFID(i) (enum at91_reg)(0x20C + ((i) * 0x20)) #define AT91_MFID(i) ((enum at91_reg)(0x20C + ((i) * 0x20)))
#define AT91_MSR(i) (enum at91_reg)(0x210 + ((i) * 0x20)) #define AT91_MSR(i) ((enum at91_reg)(0x210 + ((i) * 0x20)))
#define AT91_MDL(i) (enum at91_reg)(0x214 + ((i) * 0x20)) #define AT91_MDL(i) ((enum at91_reg)(0x214 + ((i) * 0x20)))
#define AT91_MDH(i) (enum at91_reg)(0x218 + ((i) * 0x20)) #define AT91_MDH(i) ((enum at91_reg)(0x218 + ((i) * 0x20)))
#define AT91_MCR(i) (enum at91_reg)(0x21C + ((i) * 0x20)) #define AT91_MCR(i) ((enum at91_reg)(0x21C + ((i) * 0x20)))
/* Register bits */ /* Register bits */
#define AT91_MR_CANEN BIT(0) #define AT91_MR_CANEN BIT(0)
...@@ -87,19 +87,19 @@ enum at91_mb_mode { ...@@ -87,19 +87,19 @@ enum at91_mb_mode {
}; };
/* Interrupt mask bits */ /* Interrupt mask bits */
#define AT91_IRQ_ERRA (1 << 16) #define AT91_IRQ_ERRA BIT(16)
#define AT91_IRQ_WARN (1 << 17) #define AT91_IRQ_WARN BIT(17)
#define AT91_IRQ_ERRP (1 << 18) #define AT91_IRQ_ERRP BIT(18)
#define AT91_IRQ_BOFF (1 << 19) #define AT91_IRQ_BOFF BIT(19)
#define AT91_IRQ_SLEEP (1 << 20) #define AT91_IRQ_SLEEP BIT(20)
#define AT91_IRQ_WAKEUP (1 << 21) #define AT91_IRQ_WAKEUP BIT(21)
#define AT91_IRQ_TOVF (1 << 22) #define AT91_IRQ_TOVF BIT(22)
#define AT91_IRQ_TSTP (1 << 23) #define AT91_IRQ_TSTP BIT(23)
#define AT91_IRQ_CERR (1 << 24) #define AT91_IRQ_CERR BIT(24)
#define AT91_IRQ_SERR (1 << 25) #define AT91_IRQ_SERR BIT(25)
#define AT91_IRQ_AERR (1 << 26) #define AT91_IRQ_AERR BIT(26)
#define AT91_IRQ_FERR (1 << 27) #define AT91_IRQ_FERR BIT(27)
#define AT91_IRQ_BERR (1 << 28) #define AT91_IRQ_BERR BIT(28)
#define AT91_IRQ_ERR_ALL (0x1fff0000) #define AT91_IRQ_ERR_ALL (0x1fff0000)
#define AT91_IRQ_ERR_FRAME (AT91_IRQ_CERR | AT91_IRQ_SERR | \ #define AT91_IRQ_ERR_FRAME (AT91_IRQ_CERR | AT91_IRQ_SERR | \
...@@ -163,7 +163,7 @@ static const struct can_bittiming_const at91_bittiming_const = { ...@@ -163,7 +163,7 @@ static const struct can_bittiming_const at91_bittiming_const = {
.tseg2_min = 2, .tseg2_min = 2,
.tseg2_max = 8, .tseg2_max = 8,
.sjw_max = 4, .sjw_max = 4,
.brp_min = 2, .brp_min = 2,
.brp_max = 128, .brp_max = 128,
.brp_inc = 1, .brp_inc = 1,
}; };
...@@ -281,19 +281,20 @@ static inline u32 at91_read(const struct at91_priv *priv, enum at91_reg reg) ...@@ -281,19 +281,20 @@ static inline u32 at91_read(const struct at91_priv *priv, enum at91_reg reg)
} }
static inline void at91_write(const struct at91_priv *priv, enum at91_reg reg, static inline void at91_write(const struct at91_priv *priv, enum at91_reg reg,
u32 value) u32 value)
{ {
writel_relaxed(value, priv->reg_base + reg); writel_relaxed(value, priv->reg_base + reg);
} }
static inline void set_mb_mode_prio(const struct at91_priv *priv, static inline void set_mb_mode_prio(const struct at91_priv *priv,
unsigned int mb, enum at91_mb_mode mode, int prio) unsigned int mb, enum at91_mb_mode mode,
int prio)
{ {
at91_write(priv, AT91_MMR(mb), (mode << 24) | (prio << 16)); at91_write(priv, AT91_MMR(mb), (mode << 24) | (prio << 16));
} }
static inline void set_mb_mode(const struct at91_priv *priv, unsigned int mb, static inline void set_mb_mode(const struct at91_priv *priv, unsigned int mb,
enum at91_mb_mode mode) enum at91_mb_mode mode)
{ {
set_mb_mode_prio(priv, mb, mode, 0); set_mb_mode_prio(priv, mb, mode, 0);
} }
...@@ -316,8 +317,7 @@ static void at91_setup_mailboxes(struct net_device *dev) ...@@ -316,8 +317,7 @@ static void at91_setup_mailboxes(struct net_device *dev)
unsigned int i; unsigned int i;
u32 reg_mid; u32 reg_mid;
/* /* Due to a chip bug (errata 50.2.6.3 & 50.3.5.3) the first
* Due to a chip bug (errata 50.2.6.3 & 50.3.5.3) the first
* mailbox is disabled. The next 11 mailboxes are used as a * mailbox is disabled. The next 11 mailboxes are used as a
* reception FIFO. The last mailbox is configured with * reception FIFO. The last mailbox is configured with
* overwrite option. The overwrite flag indicates a FIFO * overwrite option. The overwrite flag indicates a FIFO
...@@ -368,7 +368,7 @@ static int at91_set_bittiming(struct net_device *dev) ...@@ -368,7 +368,7 @@ static int at91_set_bittiming(struct net_device *dev)
} }
static int at91_get_berr_counter(const struct net_device *dev, static int at91_get_berr_counter(const struct net_device *dev,
struct can_berr_counter *bec) struct can_berr_counter *bec)
{ {
const struct at91_priv *priv = netdev_priv(dev); const struct at91_priv *priv = netdev_priv(dev);
u32 reg_ecr = at91_read(priv, AT91_ECR); u32 reg_ecr = at91_read(priv, AT91_ECR);
...@@ -423,8 +423,7 @@ static void at91_chip_stop(struct net_device *dev, enum can_state state) ...@@ -423,8 +423,7 @@ static void at91_chip_stop(struct net_device *dev, enum can_state state)
priv->can.state = state; priv->can.state = state;
} }
/* /* theory of operation:
* theory of operation:
* *
* According to the datasheet priority 0 is the highest priority, 15 * According to the datasheet priority 0 is the highest priority, 15
* is the lowest. If two mailboxes have the same priority level the * is the lowest. If two mailboxes have the same priority level the
...@@ -486,8 +485,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -486,8 +485,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */ /* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */
can_put_echo_skb(skb, dev, mb - get_mb_tx_first(priv), 0); can_put_echo_skb(skb, dev, mb - get_mb_tx_first(priv), 0);
/* /* we have to stop the queue and deliver all messages in case
* we have to stop the queue and deliver all messages in case
* of a prio+mb counter wrap around. This is the case if * of a prio+mb counter wrap around. This is the case if
* tx_next buffer prio and mailbox equals 0. * tx_next buffer prio and mailbox equals 0.
* *
...@@ -515,6 +513,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -515,6 +513,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
static inline void at91_activate_rx_low(const struct at91_priv *priv) static inline void at91_activate_rx_low(const struct at91_priv *priv)
{ {
u32 mask = get_mb_rx_low_mask(priv); u32 mask = get_mb_rx_low_mask(priv);
at91_write(priv, AT91_TCR, mask); at91_write(priv, AT91_TCR, mask);
} }
...@@ -526,9 +525,10 @@ static inline void at91_activate_rx_low(const struct at91_priv *priv) ...@@ -526,9 +525,10 @@ static inline void at91_activate_rx_low(const struct at91_priv *priv)
* Reenables given mailbox for reception of new CAN messages * Reenables given mailbox for reception of new CAN messages
*/ */
static inline void at91_activate_rx_mb(const struct at91_priv *priv, static inline void at91_activate_rx_mb(const struct at91_priv *priv,
unsigned int mb) unsigned int mb)
{ {
u32 mask = 1 << mb; u32 mask = 1 << mb;
at91_write(priv, AT91_TCR, mask); at91_write(priv, AT91_TCR, mask);
} }
...@@ -568,7 +568,7 @@ static void at91_rx_overflow_err(struct net_device *dev) ...@@ -568,7 +568,7 @@ static void at91_rx_overflow_err(struct net_device *dev)
* given can frame. "mb" and "cf" must be valid. * given can frame. "mb" and "cf" must be valid.
*/ */
static void at91_read_mb(struct net_device *dev, unsigned int mb, static void at91_read_mb(struct net_device *dev, unsigned int mb,
struct can_frame *cf) struct can_frame *cf)
{ {
const struct at91_priv *priv = netdev_priv(dev); const struct at91_priv *priv = netdev_priv(dev);
u32 reg_msr, reg_mid; u32 reg_msr, reg_mid;
...@@ -582,9 +582,9 @@ static void at91_read_mb(struct net_device *dev, unsigned int mb, ...@@ -582,9 +582,9 @@ static void at91_read_mb(struct net_device *dev, unsigned int mb,
reg_msr = at91_read(priv, AT91_MSR(mb)); reg_msr = at91_read(priv, AT91_MSR(mb));
cf->len = can_cc_dlc2len((reg_msr >> 16) & 0xf); cf->len = can_cc_dlc2len((reg_msr >> 16) & 0xf);
if (reg_msr & AT91_MSR_MRTR) if (reg_msr & AT91_MSR_MRTR) {
cf->can_id |= CAN_RTR_FLAG; cf->can_id |= CAN_RTR_FLAG;
else { } else {
*(u32 *)(cf->data + 0) = at91_read(priv, AT91_MDL(mb)); *(u32 *)(cf->data + 0) = at91_read(priv, AT91_MDL(mb));
*(u32 *)(cf->data + 4) = at91_read(priv, AT91_MDH(mb)); *(u32 *)(cf->data + 4) = at91_read(priv, AT91_MDH(mb));
} }
...@@ -685,7 +685,7 @@ static int at91_poll_rx(struct net_device *dev, int quota) ...@@ -685,7 +685,7 @@ static int at91_poll_rx(struct net_device *dev, int quota)
if (priv->rx_next > get_mb_rx_low_last(priv) && if (priv->rx_next > get_mb_rx_low_last(priv) &&
reg_sr & get_mb_rx_low_mask(priv)) reg_sr & get_mb_rx_low_mask(priv))
netdev_info(dev, netdev_info(dev,
"order of incoming frames cannot be guaranteed\n"); "order of incoming frames cannot be guaranteed\n");
again: again:
for (mb = find_next_bit(addr, get_mb_tx_first(priv), priv->rx_next); for (mb = find_next_bit(addr, get_mb_tx_first(priv), priv->rx_next);
...@@ -718,7 +718,7 @@ static int at91_poll_rx(struct net_device *dev, int quota) ...@@ -718,7 +718,7 @@ static int at91_poll_rx(struct net_device *dev, int quota)
} }
static void at91_poll_err_frame(struct net_device *dev, static void at91_poll_err_frame(struct net_device *dev,
struct can_frame *cf, u32 reg_sr) struct can_frame *cf, u32 reg_sr)
{ {
struct at91_priv *priv = netdev_priv(dev); struct at91_priv *priv = netdev_priv(dev);
...@@ -796,8 +796,7 @@ static int at91_poll(struct napi_struct *napi, int quota) ...@@ -796,8 +796,7 @@ static int at91_poll(struct napi_struct *napi, int quota)
if (reg_sr & get_irq_mb_rx(priv)) if (reg_sr & get_irq_mb_rx(priv))
work_done += at91_poll_rx(dev, quota - work_done); work_done += at91_poll_rx(dev, quota - work_done);
/* /* The error bits are clear on read,
* The error bits are clear on read,
* so use saved value from irq handler. * so use saved value from irq handler.
*/ */
reg_sr |= priv->reg_sr; reg_sr |= priv->reg_sr;
...@@ -807,6 +806,7 @@ static int at91_poll(struct napi_struct *napi, int quota) ...@@ -807,6 +806,7 @@ static int at91_poll(struct napi_struct *napi, int quota)
if (work_done < quota) { if (work_done < quota) {
/* enable IRQs for frame errors and all mailboxes >= rx_next */ /* enable IRQs for frame errors and all mailboxes >= rx_next */
u32 reg_ier = AT91_IRQ_ERR_FRAME; u32 reg_ier = AT91_IRQ_ERR_FRAME;
reg_ier |= get_irq_mb_rx(priv) & ~AT91_MB_MASK(priv->rx_next); reg_ier |= get_irq_mb_rx(priv) & ~AT91_MB_MASK(priv->rx_next);
napi_complete_done(napi, work_done); napi_complete_done(napi, work_done);
...@@ -816,8 +816,7 @@ static int at91_poll(struct napi_struct *napi, int quota) ...@@ -816,8 +816,7 @@ static int at91_poll(struct napi_struct *napi, int quota)
return work_done; return work_done;
} }
/* /* theory of operation:
* theory of operation:
* *
* priv->tx_echo holds the number of the oldest can_frame put for * priv->tx_echo holds the number of the oldest can_frame put for
* transmission into the hardware, but not yet ACKed by the CAN tx * transmission into the hardware, but not yet ACKed by the CAN tx
...@@ -846,8 +845,7 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr) ...@@ -846,8 +845,7 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr)
/* Disable irq for this TX mailbox */ /* Disable irq for this TX mailbox */
at91_write(priv, AT91_IDR, 1 << mb); at91_write(priv, AT91_IDR, 1 << mb);
/* /* only echo if mailbox signals us a transfer
* only echo if mailbox signals us a transfer
* complete (MSR_MRDY). Otherwise it's a tansfer * complete (MSR_MRDY). Otherwise it's a tansfer
* abort. "can_bus_off()" takes care about the skbs * abort. "can_bus_off()" takes care about the skbs
* parked in the echo queue. * parked in the echo queue.
...@@ -862,8 +860,7 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr) ...@@ -862,8 +860,7 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr)
} }
} }
/* /* restart queue if we don't have a wrap around but restart if
* restart queue if we don't have a wrap around but restart if
* we get a TX int for the last can frame directly before a * we get a TX int for the last can frame directly before a
* wrap around. * wrap around.
*/ */
...@@ -873,7 +870,7 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr) ...@@ -873,7 +870,7 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr)
} }
static void at91_irq_err_state(struct net_device *dev, static void at91_irq_err_state(struct net_device *dev,
struct can_frame *cf, enum can_state new_state) struct can_frame *cf, enum can_state new_state)
{ {
struct at91_priv *priv = netdev_priv(dev); struct at91_priv *priv = netdev_priv(dev);
u32 reg_idr = 0, reg_ier = 0; u32 reg_idr = 0, reg_ier = 0;
...@@ -883,8 +880,7 @@ static void at91_irq_err_state(struct net_device *dev, ...@@ -883,8 +880,7 @@ static void at91_irq_err_state(struct net_device *dev,
switch (priv->can.state) { switch (priv->can.state) {
case CAN_STATE_ERROR_ACTIVE: case CAN_STATE_ERROR_ACTIVE:
/* /* from: ERROR_ACTIVE
* from: ERROR_ACTIVE
* to : ERROR_WARNING, ERROR_PASSIVE, BUS_OFF * to : ERROR_WARNING, ERROR_PASSIVE, BUS_OFF
* => : there was a warning int * => : there was a warning int
*/ */
...@@ -900,8 +896,7 @@ static void at91_irq_err_state(struct net_device *dev, ...@@ -900,8 +896,7 @@ static void at91_irq_err_state(struct net_device *dev,
} }
fallthrough; fallthrough;
case CAN_STATE_ERROR_WARNING: case CAN_STATE_ERROR_WARNING:
/* /* from: ERROR_ACTIVE, ERROR_WARNING
* from: ERROR_ACTIVE, ERROR_WARNING
* to : ERROR_PASSIVE, BUS_OFF * to : ERROR_PASSIVE, BUS_OFF
* => : error passive int * => : error passive int
*/ */
...@@ -917,8 +912,7 @@ static void at91_irq_err_state(struct net_device *dev, ...@@ -917,8 +912,7 @@ static void at91_irq_err_state(struct net_device *dev,
} }
break; break;
case CAN_STATE_BUS_OFF: case CAN_STATE_BUS_OFF:
/* /* from: BUS_OFF
* from: BUS_OFF
* to : ERROR_ACTIVE, ERROR_WARNING, ERROR_PASSIVE * to : ERROR_ACTIVE, ERROR_WARNING, ERROR_PASSIVE
*/ */
if (new_state <= CAN_STATE_ERROR_PASSIVE) { if (new_state <= CAN_STATE_ERROR_PASSIVE) {
...@@ -935,12 +929,10 @@ static void at91_irq_err_state(struct net_device *dev, ...@@ -935,12 +929,10 @@ static void at91_irq_err_state(struct net_device *dev,
break; break;
} }
/* process state changes depending on the new state */ /* process state changes depending on the new state */
switch (new_state) { switch (new_state) {
case CAN_STATE_ERROR_ACTIVE: case CAN_STATE_ERROR_ACTIVE:
/* /* actually we want to enable AT91_IRQ_WARN here, but
* actually we want to enable AT91_IRQ_WARN here, but
* it screws up the system under certain * it screws up the system under certain
* circumstances. so just enable AT91_IRQ_ERRP, thus * circumstances. so just enable AT91_IRQ_ERRP, thus
* the "fallthrough" * the "fallthrough"
...@@ -983,7 +975,7 @@ static void at91_irq_err_state(struct net_device *dev, ...@@ -983,7 +975,7 @@ static void at91_irq_err_state(struct net_device *dev,
} }
static int at91_get_state_by_bec(const struct net_device *dev, static int at91_get_state_by_bec(const struct net_device *dev,
enum can_state *state) enum can_state *state)
{ {
struct can_berr_counter bec; struct can_berr_counter bec;
int err; int err;
...@@ -1004,7 +996,6 @@ static int at91_get_state_by_bec(const struct net_device *dev, ...@@ -1004,7 +996,6 @@ static int at91_get_state_by_bec(const struct net_device *dev,
return 0; return 0;
} }
static void at91_irq_err(struct net_device *dev) static void at91_irq_err(struct net_device *dev)
{ {
struct at91_priv *priv = netdev_priv(dev); struct at91_priv *priv = netdev_priv(dev);
...@@ -1018,15 +1009,15 @@ static void at91_irq_err(struct net_device *dev) ...@@ -1018,15 +1009,15 @@ static void at91_irq_err(struct net_device *dev)
reg_sr = at91_read(priv, AT91_SR); reg_sr = at91_read(priv, AT91_SR);
/* we need to look at the unmasked reg_sr */ /* we need to look at the unmasked reg_sr */
if (unlikely(reg_sr & AT91_IRQ_BOFF)) if (unlikely(reg_sr & AT91_IRQ_BOFF)) {
new_state = CAN_STATE_BUS_OFF; new_state = CAN_STATE_BUS_OFF;
else if (unlikely(reg_sr & AT91_IRQ_ERRP)) } else if (unlikely(reg_sr & AT91_IRQ_ERRP)) {
new_state = CAN_STATE_ERROR_PASSIVE; new_state = CAN_STATE_ERROR_PASSIVE;
else if (unlikely(reg_sr & AT91_IRQ_WARN)) } else if (unlikely(reg_sr & AT91_IRQ_WARN)) {
new_state = CAN_STATE_ERROR_WARNING; new_state = CAN_STATE_ERROR_WARNING;
else if (likely(reg_sr & AT91_IRQ_ERRA)) } else if (likely(reg_sr & AT91_IRQ_ERRA)) {
new_state = CAN_STATE_ERROR_ACTIVE; new_state = CAN_STATE_ERROR_ACTIVE;
else { } else {
netdev_err(dev, "BUG! hardware in undefined state\n"); netdev_err(dev, "BUG! hardware in undefined state\n");
return; return;
} }
...@@ -1053,8 +1044,7 @@ static void at91_irq_err(struct net_device *dev) ...@@ -1053,8 +1044,7 @@ static void at91_irq_err(struct net_device *dev)
priv->can.state = new_state; priv->can.state = new_state;
} }
/* /* interrupt handler
* interrupt handler
*/ */
static irqreturn_t at91_irq(int irq, void *dev_id) static irqreturn_t at91_irq(int irq, void *dev_id)
{ {
...@@ -1075,8 +1065,7 @@ static irqreturn_t at91_irq(int irq, void *dev_id) ...@@ -1075,8 +1065,7 @@ static irqreturn_t at91_irq(int irq, void *dev_id)
/* Receive or error interrupt? -> napi */ /* Receive or error interrupt? -> napi */
if (reg_sr & (get_irq_mb_rx(priv) | AT91_IRQ_ERR_FRAME)) { if (reg_sr & (get_irq_mb_rx(priv) | AT91_IRQ_ERR_FRAME)) {
/* /* The error bits are clear on read,
* The error bits are clear on read,
* save for later use. * save for later use.
*/ */
priv->reg_sr = reg_sr; priv->reg_sr = reg_sr;
...@@ -1133,8 +1122,7 @@ static int at91_open(struct net_device *dev) ...@@ -1133,8 +1122,7 @@ static int at91_open(struct net_device *dev)
return err; return err;
} }
/* /* stop CAN bus activity
* stop CAN bus activity
*/ */
static int at91_close(struct net_device *dev) static int at91_close(struct net_device *dev)
{ {
...@@ -1176,8 +1164,8 @@ static const struct net_device_ops at91_netdev_ops = { ...@@ -1176,8 +1164,8 @@ static const struct net_device_ops at91_netdev_ops = {
.ndo_change_mtu = can_change_mtu, .ndo_change_mtu = can_change_mtu,
}; };
static ssize_t at91_sysfs_show_mb0_id(struct device *dev, static ssize_t mb0_id_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct at91_priv *priv = netdev_priv(to_net_dev(dev)); struct at91_priv *priv = netdev_priv(to_net_dev(dev));
...@@ -1187,8 +1175,9 @@ static ssize_t at91_sysfs_show_mb0_id(struct device *dev, ...@@ -1187,8 +1175,9 @@ static ssize_t at91_sysfs_show_mb0_id(struct device *dev,
return snprintf(buf, PAGE_SIZE, "0x%03x\n", priv->mb0_id); return snprintf(buf, PAGE_SIZE, "0x%03x\n", priv->mb0_id);
} }
static ssize_t at91_sysfs_set_mb0_id(struct device *dev, static ssize_t mb0_id_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count) struct device_attribute *attr,
const char *buf, size_t count)
{ {
struct net_device *ndev = to_net_dev(dev); struct net_device *ndev = to_net_dev(dev);
struct at91_priv *priv = netdev_priv(ndev); struct at91_priv *priv = netdev_priv(ndev);
...@@ -1222,7 +1211,7 @@ static ssize_t at91_sysfs_set_mb0_id(struct device *dev, ...@@ -1222,7 +1211,7 @@ static ssize_t at91_sysfs_set_mb0_id(struct device *dev,
return ret; return ret;
} }
static DEVICE_ATTR(mb0_id, 0644, at91_sysfs_show_mb0_id, at91_sysfs_set_mb0_id); static DEVICE_ATTR_RW(mb0_id);
static struct attribute *at91_sysfs_attrs[] = { static struct attribute *at91_sysfs_attrs[] = {
&dev_attr_mb0_id.attr, &dev_attr_mb0_id.attr,
......
...@@ -47,7 +47,7 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[], ...@@ -47,7 +47,7 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[],
} }
if (data[IFLA_CAN_DATA_BITTIMING]) { if (data[IFLA_CAN_DATA_BITTIMING]) {
if (!is_can_fd || !data[IFLA_CAN_BITTIMING]) if (!is_can_fd)
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
...@@ -132,10 +132,13 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[], ...@@ -132,10 +132,13 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
priv->ctrlmode |= maskedflags; priv->ctrlmode |= maskedflags;
/* CAN_CTRLMODE_FD can only be set when driver supports FD */ /* CAN_CTRLMODE_FD can only be set when driver supports FD */
if (priv->ctrlmode & CAN_CTRLMODE_FD) if (priv->ctrlmode & CAN_CTRLMODE_FD) {
dev->mtu = CANFD_MTU; dev->mtu = CANFD_MTU;
else } else {
dev->mtu = CAN_MTU; dev->mtu = CAN_MTU;
memset(&priv->data_bittiming, 0,
sizeof(priv->data_bittiming));
}
} }
if (data[IFLA_CAN_RESTART_MS]) { if (data[IFLA_CAN_RESTART_MS]) {
......
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2014 Protonic Holland, /* Copyright (c) 2014 Protonic Holland,
* David Jander * David Jander
* Copyright (C) 2014-2017 Pengutronix, * Copyright (C) 2014-2021 Pengutronix,
* Marc Kleine-Budde <kernel@pengutronix.de> * Marc Kleine-Budde <kernel@pengutronix.de>
*/ */
...@@ -174,10 +174,8 @@ can_rx_offload_offload_one(struct can_rx_offload *offload, unsigned int n) ...@@ -174,10 +174,8 @@ can_rx_offload_offload_one(struct can_rx_offload *offload, unsigned int n)
int can_rx_offload_irq_offload_timestamp(struct can_rx_offload *offload, int can_rx_offload_irq_offload_timestamp(struct can_rx_offload *offload,
u64 pending) u64 pending)
{ {
struct sk_buff_head skb_queue;
unsigned int i; unsigned int i;
int received = 0;
__skb_queue_head_init(&skb_queue);
for (i = offload->mb_first; for (i = offload->mb_first;
can_rx_offload_le(offload, i, offload->mb_last); can_rx_offload_le(offload, i, offload->mb_last);
...@@ -191,26 +189,12 @@ int can_rx_offload_irq_offload_timestamp(struct can_rx_offload *offload, ...@@ -191,26 +189,12 @@ int can_rx_offload_irq_offload_timestamp(struct can_rx_offload *offload,
if (IS_ERR_OR_NULL(skb)) if (IS_ERR_OR_NULL(skb))
continue; continue;
__skb_queue_add_sort(&skb_queue, skb, can_rx_offload_compare); __skb_queue_add_sort(&offload->skb_irq_queue, skb,
} can_rx_offload_compare);
received++;
if (!skb_queue_empty(&skb_queue)) {
unsigned long flags;
u32 queue_len;
spin_lock_irqsave(&offload->skb_queue.lock, flags);
skb_queue_splice_tail(&skb_queue, &offload->skb_queue);
spin_unlock_irqrestore(&offload->skb_queue.lock, flags);
queue_len = skb_queue_len(&offload->skb_queue);
if (queue_len > offload->skb_queue_len_max / 8)
netdev_dbg(offload->dev, "%s: queue_len=%d\n",
__func__, queue_len);
can_rx_offload_schedule(offload);
} }
return skb_queue_len(&skb_queue); return received;
} }
EXPORT_SYMBOL_GPL(can_rx_offload_irq_offload_timestamp); EXPORT_SYMBOL_GPL(can_rx_offload_irq_offload_timestamp);
...@@ -226,13 +210,10 @@ int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload) ...@@ -226,13 +210,10 @@ int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload)
if (!skb) if (!skb)
break; break;
skb_queue_tail(&offload->skb_queue, skb); __skb_queue_tail(&offload->skb_irq_queue, skb);
received++; received++;
} }
if (received)
can_rx_offload_schedule(offload);
return received; return received;
} }
EXPORT_SYMBOL_GPL(can_rx_offload_irq_offload_fifo); EXPORT_SYMBOL_GPL(can_rx_offload_irq_offload_fifo);
...@@ -241,7 +222,6 @@ int can_rx_offload_queue_sorted(struct can_rx_offload *offload, ...@@ -241,7 +222,6 @@ int can_rx_offload_queue_sorted(struct can_rx_offload *offload,
struct sk_buff *skb, u32 timestamp) struct sk_buff *skb, u32 timestamp)
{ {
struct can_rx_offload_cb *cb; struct can_rx_offload_cb *cb;
unsigned long flags;
if (skb_queue_len(&offload->skb_queue) > if (skb_queue_len(&offload->skb_queue) >
offload->skb_queue_len_max) { offload->skb_queue_len_max) {
...@@ -252,11 +232,8 @@ int can_rx_offload_queue_sorted(struct can_rx_offload *offload, ...@@ -252,11 +232,8 @@ int can_rx_offload_queue_sorted(struct can_rx_offload *offload,
cb = can_rx_offload_get_cb(skb); cb = can_rx_offload_get_cb(skb);
cb->timestamp = timestamp; cb->timestamp = timestamp;
spin_lock_irqsave(&offload->skb_queue.lock, flags); __skb_queue_add_sort(&offload->skb_irq_queue, skb,
__skb_queue_add_sort(&offload->skb_queue, skb, can_rx_offload_compare); can_rx_offload_compare);
spin_unlock_irqrestore(&offload->skb_queue.lock, flags);
can_rx_offload_schedule(offload);
return 0; return 0;
} }
...@@ -295,13 +272,56 @@ int can_rx_offload_queue_tail(struct can_rx_offload *offload, ...@@ -295,13 +272,56 @@ int can_rx_offload_queue_tail(struct can_rx_offload *offload,
return -ENOBUFS; return -ENOBUFS;
} }
skb_queue_tail(&offload->skb_queue, skb); __skb_queue_tail(&offload->skb_irq_queue, skb);
can_rx_offload_schedule(offload);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(can_rx_offload_queue_tail); EXPORT_SYMBOL_GPL(can_rx_offload_queue_tail);
void can_rx_offload_irq_finish(struct can_rx_offload *offload)
{
unsigned long flags;
int queue_len;
if (skb_queue_empty_lockless(&offload->skb_irq_queue))
return;
spin_lock_irqsave(&offload->skb_queue.lock, flags);
skb_queue_splice_tail_init(&offload->skb_irq_queue, &offload->skb_queue);
spin_unlock_irqrestore(&offload->skb_queue.lock, flags);
queue_len = skb_queue_len(&offload->skb_queue);
if (queue_len > offload->skb_queue_len_max / 8)
netdev_dbg(offload->dev, "%s: queue_len=%d\n",
__func__, queue_len);
napi_schedule(&offload->napi);
}
EXPORT_SYMBOL_GPL(can_rx_offload_irq_finish);
void can_rx_offload_threaded_irq_finish(struct can_rx_offload *offload)
{
unsigned long flags;
int queue_len;
if (skb_queue_empty_lockless(&offload->skb_irq_queue))
return;
spin_lock_irqsave(&offload->skb_queue.lock, flags);
skb_queue_splice_tail_init(&offload->skb_irq_queue, &offload->skb_queue);
spin_unlock_irqrestore(&offload->skb_queue.lock, flags);
queue_len = skb_queue_len(&offload->skb_queue);
if (queue_len > offload->skb_queue_len_max / 8)
netdev_dbg(offload->dev, "%s: queue_len=%d\n",
__func__, queue_len);
local_bh_disable();
napi_schedule(&offload->napi);
local_bh_enable();
}
EXPORT_SYMBOL_GPL(can_rx_offload_threaded_irq_finish);
static int can_rx_offload_init_queue(struct net_device *dev, static int can_rx_offload_init_queue(struct net_device *dev,
struct can_rx_offload *offload, struct can_rx_offload *offload,
unsigned int weight) unsigned int weight)
...@@ -312,6 +332,7 @@ static int can_rx_offload_init_queue(struct net_device *dev, ...@@ -312,6 +332,7 @@ static int can_rx_offload_init_queue(struct net_device *dev,
offload->skb_queue_len_max = 2 << fls(weight); offload->skb_queue_len_max = 2 << fls(weight);
offload->skb_queue_len_max *= 4; offload->skb_queue_len_max *= 4;
skb_queue_head_init(&offload->skb_queue); skb_queue_head_init(&offload->skb_queue);
__skb_queue_head_init(&offload->skb_irq_queue);
netif_napi_add(dev, &offload->napi, can_rx_offload_napi_poll, weight); netif_napi_add(dev, &offload->napi, can_rx_offload_napi_poll, weight);
...@@ -373,5 +394,6 @@ void can_rx_offload_del(struct can_rx_offload *offload) ...@@ -373,5 +394,6 @@ void can_rx_offload_del(struct can_rx_offload *offload)
{ {
netif_napi_del(&offload->napi); netif_napi_del(&offload->napi);
skb_queue_purge(&offload->skb_queue); skb_queue_purge(&offload->skb_queue);
__skb_queue_purge(&offload->skb_irq_queue);
} }
EXPORT_SYMBOL_GPL(can_rx_offload_del); EXPORT_SYMBOL_GPL(can_rx_offload_del);
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/can/platform/flexcan.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
...@@ -208,18 +209,19 @@ ...@@ -208,18 +209,19 @@
/* FLEXCAN hardware feature flags /* FLEXCAN hardware feature flags
* *
* Below is some version info we got: * Below is some version info we got:
* SOC Version IP-Version Glitch- [TR]WRN_INT IRQ Err Memory err RTR rece- FD Mode * SOC Version IP-Version Glitch- [TR]WRN_INT IRQ Err Memory err RTR rece- FD Mode MB
* Filter? connected? Passive detection ption in MB Supported? * Filter? connected? Passive detection ption in MB Supported?
* MX25 FlexCAN2 03.00.00.00 no no no no no no * MCF5441X FlexCAN2 ? no yes no no yes no 16
* MX28 FlexCAN2 03.00.04.00 yes yes no no no no * MX25 FlexCAN2 03.00.00.00 no no no no no no 64
* MX35 FlexCAN2 03.00.00.00 no no no no no no * MX28 FlexCAN2 03.00.04.00 yes yes no no no no 64
* MX53 FlexCAN2 03.00.00.00 yes no no no no no * MX35 FlexCAN2 03.00.00.00 no no no no no no 64
* MX6s FlexCAN3 10.00.12.00 yes yes no no yes no * MX53 FlexCAN2 03.00.00.00 yes no no no no no 64
* MX8QM FlexCAN3 03.00.23.00 yes yes no no yes yes * MX6s FlexCAN3 10.00.12.00 yes yes no no yes no 64
* MX8MP FlexCAN3 03.00.17.01 yes yes no yes yes yes * MX8QM FlexCAN3 03.00.23.00 yes yes no no yes yes 64
* VF610 FlexCAN3 ? no yes no yes yes? no * MX8MP FlexCAN3 03.00.17.01 yes yes no yes yes yes 64
* LS1021A FlexCAN2 03.00.04.00 no yes no no yes no * VF610 FlexCAN3 ? no yes no yes yes? no 64
* LX2160A FlexCAN3 03.00.23.00 no yes no yes yes yes * LS1021A FlexCAN2 03.00.04.00 no yes no no yes no 64
* LX2160A FlexCAN3 03.00.23.00 no yes no yes yes yes 64
* *
* Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected. * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected.
*/ */
...@@ -246,6 +248,10 @@ ...@@ -246,6 +248,10 @@
#define FLEXCAN_QUIRK_SUPPORT_ECC BIT(10) #define FLEXCAN_QUIRK_SUPPORT_ECC BIT(10)
/* Setup stop mode with SCU firmware to support wakeup */ /* Setup stop mode with SCU firmware to support wakeup */
#define FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW BIT(11) #define FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW BIT(11)
/* Setup 3 separate interrupts, main, boff and err */
#define FLEXCAN_QUIRK_NR_IRQ_3 BIT(12)
/* Setup 16 mailboxes */
#define FLEXCAN_QUIRK_NR_MB_16 BIT(13)
/* Structure of the message buffer */ /* Structure of the message buffer */
struct flexcan_mb { struct flexcan_mb {
...@@ -363,6 +369,9 @@ struct flexcan_priv { ...@@ -363,6 +369,9 @@ struct flexcan_priv {
struct regulator *reg_xceiver; struct regulator *reg_xceiver;
struct flexcan_stop_mode stm; struct flexcan_stop_mode stm;
int irq_boff;
int irq_err;
/* IPC handle when setup stop mode by System Controller firmware(scfw) */ /* IPC handle when setup stop mode by System Controller firmware(scfw) */
struct imx_sc_ipc *sc_ipc_handle; struct imx_sc_ipc *sc_ipc_handle;
...@@ -371,6 +380,11 @@ struct flexcan_priv { ...@@ -371,6 +380,11 @@ struct flexcan_priv {
void (*write)(u32 val, void __iomem *addr); void (*write)(u32 val, void __iomem *addr);
}; };
static const struct flexcan_devtype_data fsl_mcf5441x_devtype_data = {
.quirks = FLEXCAN_QUIRK_BROKEN_PERR_STATE |
FLEXCAN_QUIRK_NR_IRQ_3 | FLEXCAN_QUIRK_NR_MB_16,
};
static const struct flexcan_devtype_data fsl_p1010_devtype_data = { static const struct flexcan_devtype_data fsl_p1010_devtype_data = {
.quirks = FLEXCAN_QUIRK_BROKEN_WERR_STATE | .quirks = FLEXCAN_QUIRK_BROKEN_WERR_STATE |
FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_BROKEN_PERR_STATE |
...@@ -637,13 +651,17 @@ static int flexcan_clks_enable(const struct flexcan_priv *priv) ...@@ -637,13 +651,17 @@ static int flexcan_clks_enable(const struct flexcan_priv *priv)
{ {
int err; int err;
err = clk_prepare_enable(priv->clk_ipg); if (priv->clk_ipg) {
if (err) err = clk_prepare_enable(priv->clk_ipg);
return err; if (err)
return err;
}
err = clk_prepare_enable(priv->clk_per); if (priv->clk_per) {
if (err) err = clk_prepare_enable(priv->clk_per);
clk_disable_unprepare(priv->clk_ipg); if (err)
clk_disable_unprepare(priv->clk_ipg);
}
return err; return err;
} }
...@@ -1198,6 +1216,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) ...@@ -1198,6 +1216,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
} }
} }
if (handled)
can_rx_offload_irq_finish(&priv->offload);
return handled; return handled;
} }
...@@ -1401,8 +1422,12 @@ static int flexcan_rx_offload_setup(struct net_device *dev) ...@@ -1401,8 +1422,12 @@ static int flexcan_rx_offload_setup(struct net_device *dev)
priv->mb_size = sizeof(struct flexcan_mb) + CANFD_MAX_DLEN; priv->mb_size = sizeof(struct flexcan_mb) + CANFD_MAX_DLEN;
else else
priv->mb_size = sizeof(struct flexcan_mb) + CAN_MAX_DLEN; priv->mb_size = sizeof(struct flexcan_mb) + CAN_MAX_DLEN;
priv->mb_count = (sizeof(priv->regs->mb[0]) / priv->mb_size) +
(sizeof(priv->regs->mb[1]) / priv->mb_size); if (priv->devtype_data->quirks & FLEXCAN_QUIRK_NR_MB_16)
priv->mb_count = 16;
else
priv->mb_count = (sizeof(priv->regs->mb[0]) / priv->mb_size) +
(sizeof(priv->regs->mb[1]) / priv->mb_size);
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)
priv->tx_mb_reserved = priv->tx_mb_reserved =
...@@ -1774,6 +1799,18 @@ static int flexcan_open(struct net_device *dev) ...@@ -1774,6 +1799,18 @@ static int flexcan_open(struct net_device *dev)
if (err) if (err)
goto out_can_rx_offload_disable; goto out_can_rx_offload_disable;
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
err = request_irq(priv->irq_boff,
flexcan_irq, IRQF_SHARED, dev->name, dev);
if (err)
goto out_free_irq;
err = request_irq(priv->irq_err,
flexcan_irq, IRQF_SHARED, dev->name, dev);
if (err)
goto out_free_irq_boff;
}
flexcan_chip_interrupts_enable(dev); flexcan_chip_interrupts_enable(dev);
can_led_event(dev, CAN_LED_EVENT_OPEN); can_led_event(dev, CAN_LED_EVENT_OPEN);
...@@ -1782,6 +1819,10 @@ static int flexcan_open(struct net_device *dev) ...@@ -1782,6 +1819,10 @@ static int flexcan_open(struct net_device *dev)
return 0; return 0;
out_free_irq_boff:
free_irq(priv->irq_boff, dev);
out_free_irq:
free_irq(dev->irq, dev);
out_can_rx_offload_disable: out_can_rx_offload_disable:
can_rx_offload_disable(&priv->offload); can_rx_offload_disable(&priv->offload);
flexcan_chip_stop(dev); flexcan_chip_stop(dev);
...@@ -1803,6 +1844,12 @@ static int flexcan_close(struct net_device *dev) ...@@ -1803,6 +1844,12 @@ static int flexcan_close(struct net_device *dev)
netif_stop_queue(dev); netif_stop_queue(dev);
flexcan_chip_interrupts_disable(dev); flexcan_chip_interrupts_disable(dev);
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
free_irq(priv->irq_err, dev);
free_irq(priv->irq_boff, dev);
}
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
can_rx_offload_disable(&priv->offload); can_rx_offload_disable(&priv->offload);
flexcan_chip_stop_disable_on_error(dev); flexcan_chip_stop_disable_on_error(dev);
...@@ -2039,14 +2086,26 @@ static const struct of_device_id flexcan_of_match[] = { ...@@ -2039,14 +2086,26 @@ static const struct of_device_id flexcan_of_match[] = {
}; };
MODULE_DEVICE_TABLE(of, flexcan_of_match); MODULE_DEVICE_TABLE(of, flexcan_of_match);
static const struct platform_device_id flexcan_id_table[] = {
{
.name = "flexcan-mcf5441x",
.driver_data = (kernel_ulong_t)&fsl_mcf5441x_devtype_data,
}, {
/* sentinel */
},
};
MODULE_DEVICE_TABLE(platform, flexcan_id_table);
static int flexcan_probe(struct platform_device *pdev) static int flexcan_probe(struct platform_device *pdev)
{ {
const struct of_device_id *of_id;
const struct flexcan_devtype_data *devtype_data; const struct flexcan_devtype_data *devtype_data;
struct net_device *dev; struct net_device *dev;
struct flexcan_priv *priv; struct flexcan_priv *priv;
struct regulator *reg_xceiver; struct regulator *reg_xceiver;
struct clk *clk_ipg = NULL, *clk_per = NULL; struct clk *clk_ipg = NULL, *clk_per = NULL;
struct flexcan_regs __iomem *regs; struct flexcan_regs __iomem *regs;
struct flexcan_platform_data *pdata;
int err, irq; int err, irq;
u8 clk_src = 1; u8 clk_src = 1;
u32 clock_freq = 0; u32 clock_freq = 0;
...@@ -2064,6 +2123,12 @@ static int flexcan_probe(struct platform_device *pdev) ...@@ -2064,6 +2123,12 @@ static int flexcan_probe(struct platform_device *pdev)
"clock-frequency", &clock_freq); "clock-frequency", &clock_freq);
of_property_read_u8(pdev->dev.of_node, of_property_read_u8(pdev->dev.of_node,
"fsl,clk-source", &clk_src); "fsl,clk-source", &clk_src);
} else {
pdata = dev_get_platdata(&pdev->dev);
if (pdata) {
clock_freq = pdata->clock_frequency;
clk_src = pdata->clk_src;
}
} }
if (!clock_freq) { if (!clock_freq) {
...@@ -2089,7 +2154,14 @@ static int flexcan_probe(struct platform_device *pdev) ...@@ -2089,7 +2154,14 @@ static int flexcan_probe(struct platform_device *pdev)
if (IS_ERR(regs)) if (IS_ERR(regs))
return PTR_ERR(regs); return PTR_ERR(regs);
devtype_data = of_device_get_match_data(&pdev->dev); of_id = of_match_device(flexcan_of_match, &pdev->dev);
if (of_id)
devtype_data = of_id->data;
else if (platform_get_device_id(pdev)->driver_data)
devtype_data = (struct flexcan_devtype_data *)
platform_get_device_id(pdev)->driver_data;
else
return -ENODEV;
if ((devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_FD) && if ((devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_FD) &&
!(devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)) { !(devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)) {
...@@ -2133,6 +2205,19 @@ static int flexcan_probe(struct platform_device *pdev) ...@@ -2133,6 +2205,19 @@ static int flexcan_probe(struct platform_device *pdev)
priv->devtype_data = devtype_data; priv->devtype_data = devtype_data;
priv->reg_xceiver = reg_xceiver; priv->reg_xceiver = reg_xceiver;
if (devtype_data->quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
priv->irq_boff = platform_get_irq(pdev, 1);
if (priv->irq_boff <= 0) {
err = -ENODEV;
goto failed_platform_get_irq;
}
priv->irq_err = platform_get_irq(pdev, 2);
if (priv->irq_err <= 0) {
err = -ENODEV;
goto failed_platform_get_irq;
}
}
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_FD) { if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_FD) {
priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD | priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD |
CAN_CTRLMODE_FD_NON_ISO; CAN_CTRLMODE_FD_NON_ISO;
...@@ -2170,6 +2255,7 @@ static int flexcan_probe(struct platform_device *pdev) ...@@ -2170,6 +2255,7 @@ static int flexcan_probe(struct platform_device *pdev)
failed_register: failed_register:
pm_runtime_put_noidle(&pdev->dev); pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
failed_platform_get_irq:
free_candev(dev); free_candev(dev);
return err; return err;
} }
...@@ -2322,6 +2408,7 @@ static struct platform_driver flexcan_driver = { ...@@ -2322,6 +2408,7 @@ static struct platform_driver flexcan_driver = {
}, },
.probe = flexcan_probe, .probe = flexcan_probe,
.remove = flexcan_remove, .remove = flexcan_remove,
.id_table = flexcan_id_table,
}; };
module_platform_driver(flexcan_driver); module_platform_driver(flexcan_driver);
......
...@@ -1815,9 +1815,9 @@ static int ican3_get_berr_counter(const struct net_device *ndev, ...@@ -1815,9 +1815,9 @@ static int ican3_get_berr_counter(const struct net_device *ndev,
* Sysfs Attributes * Sysfs Attributes
*/ */
static ssize_t ican3_sysfs_show_term(struct device *dev, static ssize_t termination_show(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct ican3_dev *mod = netdev_priv(to_net_dev(dev)); struct ican3_dev *mod = netdev_priv(to_net_dev(dev));
int ret; int ret;
...@@ -1834,9 +1834,9 @@ static ssize_t ican3_sysfs_show_term(struct device *dev, ...@@ -1834,9 +1834,9 @@ static ssize_t ican3_sysfs_show_term(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%u\n", mod->termination_enabled); return snprintf(buf, PAGE_SIZE, "%u\n", mod->termination_enabled);
} }
static ssize_t ican3_sysfs_set_term(struct device *dev, static ssize_t termination_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct ican3_dev *mod = netdev_priv(to_net_dev(dev)); struct ican3_dev *mod = netdev_priv(to_net_dev(dev));
unsigned long enable; unsigned long enable;
...@@ -1852,18 +1852,17 @@ static ssize_t ican3_sysfs_set_term(struct device *dev, ...@@ -1852,18 +1852,17 @@ static ssize_t ican3_sysfs_set_term(struct device *dev,
return count; return count;
} }
static ssize_t ican3_sysfs_show_fwinfo(struct device *dev, static ssize_t fwinfo_show(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct ican3_dev *mod = netdev_priv(to_net_dev(dev)); struct ican3_dev *mod = netdev_priv(to_net_dev(dev));
return scnprintf(buf, PAGE_SIZE, "%s\n", mod->fwinfo); return scnprintf(buf, PAGE_SIZE, "%s\n", mod->fwinfo);
} }
static DEVICE_ATTR(termination, 0644, ican3_sysfs_show_term, static DEVICE_ATTR_RW(termination);
ican3_sysfs_set_term); static DEVICE_ATTR_RO(fwinfo);
static DEVICE_ATTR(fwinfo, 0444, ican3_sysfs_show_fwinfo, NULL);
static struct attribute *ican3_sysfs_attrs[] = { static struct attribute *ican3_sysfs_attrs[] = {
&dev_attr_termination.attr, &dev_attr_termination.attr,
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/iopoll.h> #include <linux/iopoll.h>
#include <linux/can/dev.h> #include <linux/can/dev.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#include <linux/phy/phy.h>
#include "m_can.h" #include "m_can.h"
...@@ -1058,6 +1059,9 @@ static irqreturn_t m_can_isr(int irq, void *dev_id) ...@@ -1058,6 +1059,9 @@ static irqreturn_t m_can_isr(int irq, void *dev_id)
} }
} }
if (cdev->is_peripheral)
can_rx_offload_threaded_irq_finish(&cdev->offload);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -1436,32 +1440,20 @@ static int m_can_dev_setup(struct m_can_classdev *cdev) ...@@ -1436,32 +1440,20 @@ static int m_can_dev_setup(struct m_can_classdev *cdev)
case 30: case 30:
/* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.0.x */ /* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.0.x */
can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO); can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO);
cdev->can.bittiming_const = cdev->bit_timing ? cdev->can.bittiming_const = &m_can_bittiming_const_30X;
cdev->bit_timing : &m_can_bittiming_const_30X; cdev->can.data_bittiming_const = &m_can_data_bittiming_const_30X;
cdev->can.data_bittiming_const = cdev->data_timing ?
cdev->data_timing :
&m_can_data_bittiming_const_30X;
break; break;
case 31: case 31:
/* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.1.x */ /* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.1.x */
can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO); can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO);
cdev->can.bittiming_const = cdev->bit_timing ? cdev->can.bittiming_const = &m_can_bittiming_const_31X;
cdev->bit_timing : &m_can_bittiming_const_31X; cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X;
cdev->can.data_bittiming_const = cdev->data_timing ?
cdev->data_timing :
&m_can_data_bittiming_const_31X;
break; break;
case 32: case 32:
case 33: case 33:
/* Support both MCAN version v3.2.x and v3.3.0 */ /* Support both MCAN version v3.2.x and v3.3.0 */
cdev->can.bittiming_const = cdev->bit_timing ? cdev->can.bittiming_const = &m_can_bittiming_const_31X;
cdev->bit_timing : &m_can_bittiming_const_31X; cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X;
cdev->can.data_bittiming_const = cdev->data_timing ?
cdev->data_timing :
&m_can_data_bittiming_const_31X;
cdev->can.ctrlmode_supported |= cdev->can.ctrlmode_supported |=
(m_can_niso_supported(cdev) ? (m_can_niso_supported(cdev) ?
...@@ -1518,6 +1510,8 @@ static int m_can_close(struct net_device *dev) ...@@ -1518,6 +1510,8 @@ static int m_can_close(struct net_device *dev)
close_candev(dev); close_candev(dev);
can_led_event(dev, CAN_LED_EVENT_STOP); can_led_event(dev, CAN_LED_EVENT_STOP);
phy_power_off(cdev->transceiver);
return 0; return 0;
} }
...@@ -1703,10 +1697,14 @@ static int m_can_open(struct net_device *dev) ...@@ -1703,10 +1697,14 @@ static int m_can_open(struct net_device *dev)
struct m_can_classdev *cdev = netdev_priv(dev); struct m_can_classdev *cdev = netdev_priv(dev);
int err; int err;
err = m_can_clk_start(cdev); err = phy_power_on(cdev->transceiver);
if (err) if (err)
return err; return err;
err = m_can_clk_start(cdev);
if (err)
goto out_phy_power_off;
/* open the can device */ /* open the can device */
err = open_candev(dev); err = open_candev(dev);
if (err) { if (err) {
...@@ -1763,6 +1761,8 @@ static int m_can_open(struct net_device *dev) ...@@ -1763,6 +1761,8 @@ static int m_can_open(struct net_device *dev)
close_candev(dev); close_candev(dev);
exit_disable_clks: exit_disable_clks:
m_can_clk_stop(cdev); m_can_clk_stop(cdev);
out_phy_power_off:
phy_power_off(cdev->transceiver);
return err; return err;
} }
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/iopoll.h> #include <linux/iopoll.h>
#include <linux/can/dev.h> #include <linux/can/dev.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#include <linux/phy/phy.h>
/* m_can lec values */ /* m_can lec values */
enum m_can_lec_type { enum m_can_lec_type {
...@@ -82,9 +83,7 @@ struct m_can_classdev { ...@@ -82,9 +83,7 @@ struct m_can_classdev {
struct workqueue_struct *tx_wq; struct workqueue_struct *tx_wq;
struct work_struct tx_work; struct work_struct tx_work;
struct sk_buff *tx_skb; struct sk_buff *tx_skb;
struct phy *transceiver;
struct can_bittiming_const *bit_timing;
struct can_bittiming_const *data_timing;
struct m_can_ops *ops; struct m_can_ops *ops;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
// Copyright (C) 2018-19 Texas Instruments Incorporated - http://www.ti.com/ // Copyright (C) 2018-19 Texas Instruments Incorporated - http://www.ti.com/
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/phy/phy.h>
#include "m_can.h" #include "m_can.h"
...@@ -67,6 +68,7 @@ static int m_can_plat_probe(struct platform_device *pdev) ...@@ -67,6 +68,7 @@ static int m_can_plat_probe(struct platform_device *pdev)
struct resource *res; struct resource *res;
void __iomem *addr; void __iomem *addr;
void __iomem *mram_addr; void __iomem *mram_addr;
struct phy *transceiver;
int irq, ret = 0; int irq, ret = 0;
mcan_class = m_can_class_allocate_dev(&pdev->dev, mcan_class = m_can_class_allocate_dev(&pdev->dev,
...@@ -80,8 +82,7 @@ static int m_can_plat_probe(struct platform_device *pdev) ...@@ -80,8 +82,7 @@ static int m_can_plat_probe(struct platform_device *pdev)
if (ret) if (ret)
goto probe_fail; goto probe_fail;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "m_can"); addr = devm_platform_ioremap_resource_byname(pdev, "m_can");
addr = devm_ioremap_resource(&pdev->dev, res);
irq = platform_get_irq_byname(pdev, "int0"); irq = platform_get_irq_byname(pdev, "int0");
if (IS_ERR(addr) || irq < 0) { if (IS_ERR(addr) || irq < 0) {
ret = -EINVAL; ret = -EINVAL;
...@@ -101,6 +102,16 @@ static int m_can_plat_probe(struct platform_device *pdev) ...@@ -101,6 +102,16 @@ static int m_can_plat_probe(struct platform_device *pdev)
goto probe_fail; goto probe_fail;
} }
transceiver = devm_phy_optional_get(&pdev->dev, NULL);
if (IS_ERR(transceiver)) {
ret = PTR_ERR(transceiver);
dev_err_probe(&pdev->dev, ret, "failed to get phy\n");
goto probe_fail;
}
if (transceiver)
mcan_class->can.bitrate_max = transceiver->attrs.max_link_rate;
priv->base = addr; priv->base = addr;
priv->mram_base = mram_addr; priv->mram_base = mram_addr;
...@@ -108,6 +119,7 @@ static int m_can_plat_probe(struct platform_device *pdev) ...@@ -108,6 +119,7 @@ static int m_can_plat_probe(struct platform_device *pdev)
mcan_class->pm_clock_support = 1; mcan_class->pm_clock_support = 1;
mcan_class->can.clock.freq = clk_get_rate(mcan_class->cclk); mcan_class->can.clock.freq = clk_get_rate(mcan_class->cclk);
mcan_class->dev = &pdev->dev; mcan_class->dev = &pdev->dev;
mcan_class->transceiver = transceiver;
mcan_class->ops = &m_can_plat_ops; mcan_class->ops = &m_can_plat_ops;
......
...@@ -28,6 +28,10 @@ MODULE_LICENSE("GPL v2"); ...@@ -28,6 +28,10 @@ MODULE_LICENSE("GPL v2");
#define DRV_NAME "peak_pci" #define DRV_NAME "peak_pci"
/* FPGA cards FW version registers */
#define PEAK_VER_REG1 0x40
#define PEAK_VER_REG2 0x44
struct peak_pciec_card; struct peak_pciec_card;
struct peak_pci_chan { struct peak_pci_chan {
void __iomem *cfg_base; /* Common for all channels */ void __iomem *cfg_base; /* Common for all channels */
...@@ -41,9 +45,7 @@ struct peak_pci_chan { ...@@ -41,9 +45,7 @@ struct peak_pci_chan {
#define PEAK_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK) #define PEAK_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK)
#define PEAK_PCI_OCR OCR_TX0_PUSHPULL #define PEAK_PCI_OCR OCR_TX0_PUSHPULL
/* /* Important PITA registers */
* Important PITA registers
*/
#define PITA_ICR 0x00 /* Interrupt control register */ #define PITA_ICR 0x00 /* Interrupt control register */
#define PITA_GPIOICR 0x18 /* GPIO interface control register */ #define PITA_GPIOICR 0x18 /* GPIO interface control register */
#define PITA_MISC 0x1C /* Miscellaneous register */ #define PITA_MISC 0x1C /* Miscellaneous register */
...@@ -70,27 +72,47 @@ static const u16 peak_pci_icr_masks[PEAK_PCI_CHAN_MAX] = { ...@@ -70,27 +72,47 @@ static const u16 peak_pci_icr_masks[PEAK_PCI_CHAN_MAX] = {
}; };
static const struct pci_device_id peak_pci_tbl[] = { static const struct pci_device_id peak_pci_tbl[] = {
{PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, {
{PEAK_PCI_VENDOR_ID, PEAK_PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
{PEAK_PCI_VENDOR_ID, PEAK_MPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, .driver_data = (kernel_ulong_t)"PCAN-PCI",
{PEAK_PCI_VENDOR_ID, PEAK_MPCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, }, {
{PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, PEAK_PCI_VENDOR_ID, PEAK_PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
{PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, .driver_data = (kernel_ulong_t)"PCAN-PCI Express",
{PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, }, {
{PEAK_PCI_VENDOR_ID, PEAK_PCIE_OEM_ID, PCI_ANY_ID, PCI_ANY_ID,}, PEAK_PCI_VENDOR_ID, PEAK_MPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
.driver_data = (kernel_ulong_t)"PCAN-miniPCI",
}, {
PEAK_PCI_VENDOR_ID, PEAK_MPCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
.driver_data = (kernel_ulong_t)"PCAN-miniPCIe",
}, {
PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
.driver_data = (kernel_ulong_t)"PCAN-PC/104-Plus Quad",
}, {
PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
.driver_data = (kernel_ulong_t)"PCAN-PCI/104-Express",
}, {
PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
.driver_data = (kernel_ulong_t)"PCAN-cPCI",
}, {
PEAK_PCI_VENDOR_ID, PEAK_PCIE_OEM_ID, PCI_ANY_ID, PCI_ANY_ID,
.driver_data = (kernel_ulong_t)"PCAN-Chip PCIe",
},
#ifdef CONFIG_CAN_PEAK_PCIEC #ifdef CONFIG_CAN_PEAK_PCIEC
{PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, {
{PEAK_PCI_VENDOR_ID, PEAK_PCIEC34_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
.driver_data = (kernel_ulong_t)"PCAN-ExpressCard",
}, {
PEAK_PCI_VENDOR_ID, PEAK_PCIEC34_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
.driver_data = (kernel_ulong_t)"PCAN-ExpressCard 34",
},
#endif #endif
{0,} { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(pci, peak_pci_tbl); MODULE_DEVICE_TABLE(pci, peak_pci_tbl);
#ifdef CONFIG_CAN_PEAK_PCIEC #ifdef CONFIG_CAN_PEAK_PCIEC
/* /* PCAN-ExpressCard needs I2C bit-banging configuration option. */
* PCAN-ExpressCard needs I2C bit-banging configuration option.
*/
/* GPIOICR byte access offsets */ /* GPIOICR byte access offsets */
#define PITA_GPOUT 0x18 /* GPx output value */ #define PITA_GPOUT 0x18 /* GPx output value */
...@@ -156,12 +178,14 @@ static void peak_pci_write_reg(const struct sja1000_priv *priv, ...@@ -156,12 +178,14 @@ static void peak_pci_write_reg(const struct sja1000_priv *priv,
static inline void pita_set_scl_highz(struct peak_pciec_card *card) static inline void pita_set_scl_highz(struct peak_pciec_card *card)
{ {
u8 gp_outen = readb(card->cfg_base + PITA_GPOEN) & ~PITA_GPIN_SCL; u8 gp_outen = readb(card->cfg_base + PITA_GPOEN) & ~PITA_GPIN_SCL;
writeb(gp_outen, card->cfg_base + PITA_GPOEN); writeb(gp_outen, card->cfg_base + PITA_GPOEN);
} }
static inline void pita_set_sda_highz(struct peak_pciec_card *card) static inline void pita_set_sda_highz(struct peak_pciec_card *card)
{ {
u8 gp_outen = readb(card->cfg_base + PITA_GPOEN) & ~PITA_GPIN_SDA; u8 gp_outen = readb(card->cfg_base + PITA_GPOEN) & ~PITA_GPIN_SDA;
writeb(gp_outen, card->cfg_base + PITA_GPOEN); writeb(gp_outen, card->cfg_base + PITA_GPOEN);
} }
...@@ -230,9 +254,7 @@ static int pita_getscl(void *data) ...@@ -230,9 +254,7 @@ static int pita_getscl(void *data)
return (readb(card->cfg_base + PITA_GPIN) & PITA_GPIN_SCL) ? 1 : 0; return (readb(card->cfg_base + PITA_GPIN) & PITA_GPIN_SCL) ? 1 : 0;
} }
/* /* write commands to the LED chip though the I2C-bus of the PCAN-PCIeC */
* write commands to the LED chip though the I2C-bus of the PCAN-PCIeC
*/
static int peak_pciec_write_pca9553(struct peak_pciec_card *card, static int peak_pciec_write_pca9553(struct peak_pciec_card *card,
u8 offset, u8 data) u8 offset, u8 data)
{ {
...@@ -248,7 +270,7 @@ static int peak_pciec_write_pca9553(struct peak_pciec_card *card, ...@@ -248,7 +270,7 @@ static int peak_pciec_write_pca9553(struct peak_pciec_card *card,
int ret; int ret;
/* cache led mask */ /* cache led mask */
if ((offset == 5) && (data == card->led_cache)) if (offset == 5 && data == card->led_cache)
return 0; return 0;
ret = i2c_transfer(&card->led_chip, &msg, 1); ret = i2c_transfer(&card->led_chip, &msg, 1);
...@@ -261,9 +283,7 @@ static int peak_pciec_write_pca9553(struct peak_pciec_card *card, ...@@ -261,9 +283,7 @@ static int peak_pciec_write_pca9553(struct peak_pciec_card *card,
return 0; return 0;
} }
/* /* delayed work callback used to control the LEDs */
* delayed work callback used to control the LEDs
*/
static void peak_pciec_led_work(struct work_struct *work) static void peak_pciec_led_work(struct work_struct *work)
{ {
struct peak_pciec_card *card = struct peak_pciec_card *card =
...@@ -309,9 +329,7 @@ static void peak_pciec_led_work(struct work_struct *work) ...@@ -309,9 +329,7 @@ static void peak_pciec_led_work(struct work_struct *work)
schedule_delayed_work(&card->led_work, HZ); schedule_delayed_work(&card->led_work, HZ);
} }
/* /* set LEDs blinking state */
* set LEDs blinking state
*/
static void peak_pciec_set_leds(struct peak_pciec_card *card, u8 led_mask, u8 s) static void peak_pciec_set_leds(struct peak_pciec_card *card, u8 led_mask, u8 s)
{ {
u8 new_led = card->led_cache; u8 new_led = card->led_cache;
...@@ -328,25 +346,19 @@ static void peak_pciec_set_leds(struct peak_pciec_card *card, u8 led_mask, u8 s) ...@@ -328,25 +346,19 @@ static void peak_pciec_set_leds(struct peak_pciec_card *card, u8 led_mask, u8 s)
peak_pciec_write_pca9553(card, 5, new_led); peak_pciec_write_pca9553(card, 5, new_led);
} }
/* /* start one second delayed work to control LEDs */
* start one second delayed work to control LEDs
*/
static void peak_pciec_start_led_work(struct peak_pciec_card *card) static void peak_pciec_start_led_work(struct peak_pciec_card *card)
{ {
schedule_delayed_work(&card->led_work, HZ); schedule_delayed_work(&card->led_work, HZ);
} }
/* /* stop LEDs delayed work */
* stop LEDs delayed work
*/
static void peak_pciec_stop_led_work(struct peak_pciec_card *card) static void peak_pciec_stop_led_work(struct peak_pciec_card *card)
{ {
cancel_delayed_work_sync(&card->led_work); cancel_delayed_work_sync(&card->led_work);
} }
/* /* initialize the PCA9553 4-bit I2C-bus LED chip */
* initialize the PCA9553 4-bit I2C-bus LED chip
*/
static int peak_pciec_init_leds(struct peak_pciec_card *card) static int peak_pciec_init_leds(struct peak_pciec_card *card)
{ {
int err; int err;
...@@ -375,17 +387,14 @@ static int peak_pciec_init_leds(struct peak_pciec_card *card) ...@@ -375,17 +387,14 @@ static int peak_pciec_init_leds(struct peak_pciec_card *card)
return peak_pciec_write_pca9553(card, 5, PCA9553_LS0_INIT); return peak_pciec_write_pca9553(card, 5, PCA9553_LS0_INIT);
} }
/* /* restore LEDs state to off peak_pciec_leds_exit */
* restore LEDs state to off peak_pciec_leds_exit
*/
static void peak_pciec_leds_exit(struct peak_pciec_card *card) static void peak_pciec_leds_exit(struct peak_pciec_card *card)
{ {
/* switch LEDs to off */ /* switch LEDs to off */
peak_pciec_write_pca9553(card, 5, PCA9553_LED_OFF_ALL); peak_pciec_write_pca9553(card, 5, PCA9553_LED_OFF_ALL);
} }
/* /* normal write sja1000 register method overloaded to catch when controller
* normal write sja1000 register method overloaded to catch when controller
* is started or stopped, to control leds * is started or stopped, to control leds
*/ */
static void peak_pciec_write_reg(const struct sja1000_priv *priv, static void peak_pciec_write_reg(const struct sja1000_priv *priv,
...@@ -443,7 +452,7 @@ static int peak_pciec_probe(struct pci_dev *pdev, struct net_device *dev) ...@@ -443,7 +452,7 @@ static int peak_pciec_probe(struct pci_dev *pdev, struct net_device *dev)
/* channel is the first one: do the init part */ /* channel is the first one: do the init part */
} else { } else {
/* create the bit banging I2C adapter structure */ /* create the bit banging I2C adapter structure */
card = kzalloc(sizeof(struct peak_pciec_card), GFP_KERNEL); card = kzalloc(sizeof(*card), GFP_KERNEL);
if (!card) if (!card)
return -ENOMEM; return -ENOMEM;
...@@ -506,9 +515,7 @@ static void peak_pciec_remove(struct peak_pciec_card *card) ...@@ -506,9 +515,7 @@ static void peak_pciec_remove(struct peak_pciec_card *card)
#else /* CONFIG_CAN_PEAK_PCIEC */ #else /* CONFIG_CAN_PEAK_PCIEC */
/* /* Placebo functions when PCAN-ExpressCard support is not selected */
* Placebo functions when PCAN-ExpressCard support is not selected
*/
static inline int peak_pciec_probe(struct pci_dev *pdev, struct net_device *dev) static inline int peak_pciec_probe(struct pci_dev *pdev, struct net_device *dev)
{ {
return -ENODEV; return -ENODEV;
...@@ -549,6 +556,7 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -549,6 +556,7 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
void __iomem *cfg_base, *reg_base; void __iomem *cfg_base, *reg_base;
u16 sub_sys_id, icr; u16 sub_sys_id, icr;
int i, err, channels; int i, err, channels;
char fw_str[14] = "";
err = pci_enable_device(pdev); err = pci_enable_device(pdev);
if (err) if (err)
...@@ -602,6 +610,21 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -602,6 +610,21 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Leave parport mux mode */ /* Leave parport mux mode */
writeb(0x04, cfg_base + PITA_MISC + 3); writeb(0x04, cfg_base + PITA_MISC + 3);
/* FPGA equipped card if not 0 */
if (readl(cfg_base + PEAK_VER_REG1)) {
/* FPGA card: display version of the running firmware */
u32 fw_ver = readl(cfg_base + PEAK_VER_REG2);
snprintf(fw_str, sizeof(fw_str), " FW v%u.%u.%u",
(fw_ver >> 12) & 0xf,
(fw_ver >> 8) & 0xf,
(fw_ver >> 4) & 0xf);
}
/* Display commercial name (and, eventually, FW version) of the card */
dev_info(&pdev->dev, "%ux CAN %s%s\n",
channels, (const char *)ent->driver_data, fw_str);
icr = readw(cfg_base + PITA_ICR + 2); icr = readw(cfg_base + PITA_ICR + 2);
for (i = 0; i < channels; i++) { for (i = 0; i < channels; i++) {
...@@ -642,8 +665,7 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -642,8 +665,7 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
chan->prev_dev = pci_get_drvdata(pdev); chan->prev_dev = pci_get_drvdata(pdev);
pci_set_drvdata(pdev, dev); pci_set_drvdata(pdev, dev);
/* /* PCAN-ExpressCard needs some additional i2c init.
* PCAN-ExpressCard needs some additional i2c init.
* This must be done *before* register_sja1000dev() but * This must be done *before* register_sja1000dev() but
* *after* devices linkage * *after* devices linkage
*/ */
...@@ -709,7 +731,8 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -709,7 +731,8 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* pci_xxx_config_word() return positive PCIBIOS_xxx error codes while /* pci_xxx_config_word() return positive PCIBIOS_xxx error codes while
* the probe() function must return a negative errno in case of failure * the probe() function must return a negative errno in case of failure
* (err is unchanged if negative) */ * (err is unchanged if negative)
*/
return pcibios_err_to_errno(err); return pcibios_err_to_errno(err);
} }
......
...@@ -15,10 +15,10 @@ ...@@ -15,10 +15,10 @@
#include <linux/bitfield.h> #include <linux/bitfield.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/property.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
...@@ -2195,8 +2195,10 @@ static irqreturn_t mcp251xfd_irq(int irq, void *dev_id) ...@@ -2195,8 +2195,10 @@ static irqreturn_t mcp251xfd_irq(int irq, void *dev_id)
FIELD_GET(MCP251XFD_REG_INT_IE_MASK, FIELD_GET(MCP251XFD_REG_INT_IE_MASK,
priv->regs_status.intf); priv->regs_status.intf);
if (!(intf_pending)) if (!(intf_pending)) {
can_rx_offload_threaded_irq_finish(&priv->offload);
return handled; return handled;
}
/* Some interrupts must be ACKed in the /* Some interrupts must be ACKed in the
* MCP251XFD_REG_INT register. * MCP251XFD_REG_INT register.
...@@ -2296,6 +2298,8 @@ static irqreturn_t mcp251xfd_irq(int irq, void *dev_id) ...@@ -2296,6 +2298,8 @@ static irqreturn_t mcp251xfd_irq(int irq, void *dev_id)
} while (1); } while (1);
out_fail: out_fail:
can_rx_offload_threaded_irq_finish(&priv->offload);
netdev_err(priv->ndev, "IRQ handler returned %d (intf=0x%08x).\n", netdev_err(priv->ndev, "IRQ handler returned %d (intf=0x%08x).\n",
err, priv->regs_status.intf); err, priv->regs_status.intf);
mcp251xfd_dump(priv); mcp251xfd_dump(priv);
...@@ -2523,8 +2527,8 @@ static int mcp251xfd_open(struct net_device *ndev) ...@@ -2523,8 +2527,8 @@ static int mcp251xfd_open(struct net_device *ndev)
can_rx_offload_enable(&priv->offload); can_rx_offload_enable(&priv->offload);
err = request_threaded_irq(spi->irq, NULL, mcp251xfd_irq, err = request_threaded_irq(spi->irq, NULL, mcp251xfd_irq,
IRQF_ONESHOT, dev_name(&spi->dev), IRQF_SHARED | IRQF_ONESHOT,
priv); dev_name(&spi->dev), priv);
if (err) if (err)
goto out_can_rx_offload_disable; goto out_can_rx_offload_disable;
...@@ -2856,7 +2860,7 @@ static int mcp251xfd_probe(struct spi_device *spi) ...@@ -2856,7 +2860,7 @@ static int mcp251xfd_probe(struct spi_device *spi)
struct gpio_desc *rx_int; struct gpio_desc *rx_int;
struct regulator *reg_vdd, *reg_xceiver; struct regulator *reg_vdd, *reg_xceiver;
struct clk *clk; struct clk *clk;
u32 freq; u32 freq = 0;
int err; int err;
if (!spi->irq) if (!spi->irq)
...@@ -2883,11 +2887,19 @@ static int mcp251xfd_probe(struct spi_device *spi) ...@@ -2883,11 +2887,19 @@ static int mcp251xfd_probe(struct spi_device *spi)
return dev_err_probe(&spi->dev, PTR_ERR(reg_xceiver), return dev_err_probe(&spi->dev, PTR_ERR(reg_xceiver),
"Failed to get Transceiver regulator!\n"); "Failed to get Transceiver regulator!\n");
clk = devm_clk_get(&spi->dev, NULL); clk = devm_clk_get_optional(&spi->dev, NULL);
if (IS_ERR(clk)) if (IS_ERR(clk))
return dev_err_probe(&spi->dev, PTR_ERR(clk), return dev_err_probe(&spi->dev, PTR_ERR(clk),
"Failed to get Oscillator (clock)!\n"); "Failed to get Oscillator (clock)!\n");
freq = clk_get_rate(clk); if (clk) {
freq = clk_get_rate(clk);
} else {
err = device_property_read_u32(&spi->dev, "clock-frequency",
&freq);
if (err)
return dev_err_probe(&spi->dev, err,
"Failed to get clock-frequency!\n");
}
/* Sanity check */ /* Sanity check */
if (freq < MCP251XFD_SYSCLOCK_HZ_MIN || if (freq < MCP251XFD_SYSCLOCK_HZ_MIN ||
......
...@@ -786,6 +786,8 @@ static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id) ...@@ -786,6 +786,8 @@ static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id)
int_status = hecc_read(priv, HECC_CANGIF0); int_status = hecc_read(priv, HECC_CANGIF0);
} }
can_rx_offload_irq_finish(&priv->offload);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -474,7 +474,7 @@ static void esd_usb2_write_bulk_callback(struct urb *urb) ...@@ -474,7 +474,7 @@ static void esd_usb2_write_bulk_callback(struct urb *urb)
netif_trans_update(netdev); netif_trans_update(netdev);
} }
static ssize_t show_firmware(struct device *d, static ssize_t firmware_show(struct device *d,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct usb_interface *intf = to_usb_interface(d); struct usb_interface *intf = to_usb_interface(d);
...@@ -485,9 +485,9 @@ static ssize_t show_firmware(struct device *d, ...@@ -485,9 +485,9 @@ static ssize_t show_firmware(struct device *d,
(dev->version >> 8) & 0xf, (dev->version >> 8) & 0xf,
dev->version & 0xff); dev->version & 0xff);
} }
static DEVICE_ATTR(firmware, 0444, show_firmware, NULL); static DEVICE_ATTR_RO(firmware);
static ssize_t show_hardware(struct device *d, static ssize_t hardware_show(struct device *d,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct usb_interface *intf = to_usb_interface(d); struct usb_interface *intf = to_usb_interface(d);
...@@ -498,9 +498,9 @@ static ssize_t show_hardware(struct device *d, ...@@ -498,9 +498,9 @@ static ssize_t show_hardware(struct device *d,
(dev->version >> 24) & 0xf, (dev->version >> 24) & 0xf,
(dev->version >> 16) & 0xff); (dev->version >> 16) & 0xff);
} }
static DEVICE_ATTR(hardware, 0444, show_hardware, NULL); static DEVICE_ATTR_RO(hardware);
static ssize_t show_nets(struct device *d, static ssize_t nets_show(struct device *d,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct usb_interface *intf = to_usb_interface(d); struct usb_interface *intf = to_usb_interface(d);
...@@ -508,7 +508,7 @@ static ssize_t show_nets(struct device *d, ...@@ -508,7 +508,7 @@ static ssize_t show_nets(struct device *d,
return sprintf(buf, "%d", dev->net_count); return sprintf(buf, "%d", dev->net_count);
} }
static DEVICE_ATTR(nets, 0444, show_nets, NULL); static DEVICE_ATTR_RO(nets);
static int esd_usb2_send_msg(struct esd_usb2 *dev, struct esd_usb2_msg *msg) static int esd_usb2_send_msg(struct esd_usb2 *dev, struct esd_usb2_msg *msg)
{ {
......
...@@ -355,7 +355,7 @@ static int es581_4_tx_can_msg(struct es58x_priv *priv, ...@@ -355,7 +355,7 @@ static int es581_4_tx_can_msg(struct es58x_priv *priv,
return -EMSGSIZE; return -EMSGSIZE;
if (priv->tx_can_msg_cnt == 0) { if (priv->tx_can_msg_cnt == 0) {
msg_len = 1; /* struct es581_4_bulk_tx_can_msg:num_can_msg */ msg_len = sizeof(es581_4_urb_cmd->bulk_tx_can_msg.num_can_msg);
es581_4_fill_urb_header(urb_cmd, ES581_4_CAN_COMMAND_TYPE, es581_4_fill_urb_header(urb_cmd, ES581_4_CAN_COMMAND_TYPE,
ES581_4_CMD_ID_TX_MSG, ES581_4_CMD_ID_TX_MSG,
priv->channel_idx, msg_len); priv->channel_idx, msg_len);
...@@ -371,8 +371,7 @@ static int es581_4_tx_can_msg(struct es58x_priv *priv, ...@@ -371,8 +371,7 @@ static int es581_4_tx_can_msg(struct es58x_priv *priv,
return ret; return ret;
/* Fill message contents. */ /* Fill message contents. */
tx_can_msg = (struct es581_4_tx_can_msg *) tx_can_msg = (typeof(tx_can_msg))&es581_4_urb_cmd->raw_msg[msg_len];
&es581_4_urb_cmd->bulk_tx_can_msg.tx_can_msg_buf[msg_len - 1];
put_unaligned_le32(es58x_get_raw_can_id(cf), &tx_can_msg->can_id); put_unaligned_le32(es58x_get_raw_can_id(cf), &tx_can_msg->can_id);
put_unaligned_le32(priv->tx_head, &tx_can_msg->packet_idx); put_unaligned_le32(priv->tx_head, &tx_can_msg->packet_idx);
put_unaligned_le16((u16)es58x_get_flags(skb), &tx_can_msg->flags); put_unaligned_le16((u16)es58x_get_flags(skb), &tx_can_msg->flags);
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#include "es58x_core.h" #include "es58x_core.h"
#define DRV_VERSION "1.00" #define DRV_VERSION "1.00"
MODULE_AUTHOR("Mailhol Vincent <mailhol.vincent@wanadoo.fr>"); MODULE_AUTHOR("Vincent Mailhol <mailhol.vincent@wanadoo.fr>");
MODULE_AUTHOR("Arunachalam Santhanam <arunachalam.santhanam@in.bosch.com>"); MODULE_AUTHOR("Arunachalam Santhanam <arunachalam.santhanam@in.bosch.com>");
MODULE_DESCRIPTION("Socket CAN driver for ETAS ES58X USB adapters"); MODULE_DESCRIPTION("Socket CAN driver for ETAS ES58X USB adapters");
MODULE_VERSION(DRV_VERSION); MODULE_VERSION(DRV_VERSION);
...@@ -70,7 +70,7 @@ MODULE_DEVICE_TABLE(usb, es58x_id_table); ...@@ -70,7 +70,7 @@ MODULE_DEVICE_TABLE(usb, es58x_id_table);
* bytes (the start of frame) are skipped and the CRC calculation * bytes (the start of frame) are skipped and the CRC calculation
* starts on the third byte. * starts on the third byte.
*/ */
#define ES58X_CRC_CALC_OFFSET 2 #define ES58X_CRC_CALC_OFFSET sizeof_field(union es58x_urb_cmd, sof)
/** /**
* es58x_calculate_crc() - Compute the crc16 of a given URB. * es58x_calculate_crc() - Compute the crc16 of a given URB.
...@@ -2107,6 +2107,25 @@ static int es58x_init_netdev(struct es58x_device *es58x_dev, int channel_idx) ...@@ -2107,6 +2107,25 @@ static int es58x_init_netdev(struct es58x_device *es58x_dev, int channel_idx)
return ret; return ret;
} }
/**
* es58x_free_netdevs() - Release all network resources of the device.
* @es58x_dev: ES58X device.
*/
static void es58x_free_netdevs(struct es58x_device *es58x_dev)
{
int i;
for (i = 0; i < es58x_dev->num_can_ch; i++) {
struct net_device *netdev = es58x_dev->netdev[i];
if (!netdev)
continue;
unregister_candev(netdev);
es58x_dev->netdev[i] = NULL;
free_candev(netdev);
}
}
/** /**
* es58x_get_product_info() - Get the product information and print them. * es58x_get_product_info() - Get the product information and print them.
* @es58x_dev: ES58X device. * @es58x_dev: ES58X device.
...@@ -2152,14 +2171,13 @@ static int es58x_get_product_info(struct es58x_device *es58x_dev) ...@@ -2152,14 +2171,13 @@ static int es58x_get_product_info(struct es58x_device *es58x_dev)
/** /**
* es58x_init_es58x_dev() - Initialize the ES58X device. * es58x_init_es58x_dev() - Initialize the ES58X device.
* @intf: USB interface. * @intf: USB interface.
* @p_es58x_dev: pointer to the address of the ES58X device.
* @driver_info: Quirks of the device. * @driver_info: Quirks of the device.
* *
* Return: zero on success, errno when any error occurs. * Return: pointer to an ES58X device on success, error pointer when
* any error occurs.
*/ */
static int es58x_init_es58x_dev(struct usb_interface *intf, static struct es58x_device *es58x_init_es58x_dev(struct usb_interface *intf,
struct es58x_device **p_es58x_dev, kernel_ulong_t driver_info)
kernel_ulong_t driver_info)
{ {
struct device *dev = &intf->dev; struct device *dev = &intf->dev;
struct es58x_device *es58x_dev; struct es58x_device *es58x_dev;
...@@ -2176,7 +2194,7 @@ static int es58x_init_es58x_dev(struct usb_interface *intf, ...@@ -2176,7 +2194,7 @@ static int es58x_init_es58x_dev(struct usb_interface *intf,
ret = usb_find_common_endpoints(intf->cur_altsetting, &ep_in, &ep_out, ret = usb_find_common_endpoints(intf->cur_altsetting, &ep_in, &ep_out,
NULL, NULL); NULL, NULL);
if (ret) if (ret)
return ret; return ERR_PTR(ret);
if (driver_info & ES58X_FD_FAMILY) { if (driver_info & ES58X_FD_FAMILY) {
param = &es58x_fd_param; param = &es58x_fd_param;
...@@ -2186,9 +2204,10 @@ static int es58x_init_es58x_dev(struct usb_interface *intf, ...@@ -2186,9 +2204,10 @@ static int es58x_init_es58x_dev(struct usb_interface *intf,
ops = &es581_4_ops; ops = &es581_4_ops;
} }
es58x_dev = kzalloc(es58x_sizeof_es58x_device(param), GFP_KERNEL); es58x_dev = devm_kzalloc(dev, es58x_sizeof_es58x_device(param),
GFP_KERNEL);
if (!es58x_dev) if (!es58x_dev)
return -ENOMEM; return ERR_PTR(-ENOMEM);
es58x_dev->param = param; es58x_dev->param = param;
es58x_dev->ops = ops; es58x_dev->ops = ops;
...@@ -2213,9 +2232,7 @@ static int es58x_init_es58x_dev(struct usb_interface *intf, ...@@ -2213,9 +2232,7 @@ static int es58x_init_es58x_dev(struct usb_interface *intf,
ep_out->bEndpointAddress); ep_out->bEndpointAddress);
es58x_dev->rx_max_packet_size = le16_to_cpu(ep_in->wMaxPacketSize); es58x_dev->rx_max_packet_size = le16_to_cpu(ep_in->wMaxPacketSize);
*p_es58x_dev = es58x_dev; return es58x_dev;
return 0;
} }
/** /**
...@@ -2232,30 +2249,21 @@ static int es58x_probe(struct usb_interface *intf, ...@@ -2232,30 +2249,21 @@ static int es58x_probe(struct usb_interface *intf,
struct es58x_device *es58x_dev; struct es58x_device *es58x_dev;
int ch_idx, ret; int ch_idx, ret;
ret = es58x_init_es58x_dev(intf, &es58x_dev, id->driver_info); es58x_dev = es58x_init_es58x_dev(intf, id->driver_info);
if (ret) if (IS_ERR(es58x_dev))
return ret; return PTR_ERR(es58x_dev);
ret = es58x_get_product_info(es58x_dev); ret = es58x_get_product_info(es58x_dev);
if (ret) if (ret)
goto cleanup_es58x_dev; return ret;
for (ch_idx = 0; ch_idx < es58x_dev->num_can_ch; ch_idx++) { for (ch_idx = 0; ch_idx < es58x_dev->num_can_ch; ch_idx++) {
ret = es58x_init_netdev(es58x_dev, ch_idx); ret = es58x_init_netdev(es58x_dev, ch_idx);
if (ret) if (ret) {
goto cleanup_candev; es58x_free_netdevs(es58x_dev);
} return ret;
return ret;
cleanup_candev:
for (ch_idx = 0; ch_idx < es58x_dev->num_can_ch; ch_idx++)
if (es58x_dev->netdev[ch_idx]) {
unregister_candev(es58x_dev->netdev[ch_idx]);
free_candev(es58x_dev->netdev[ch_idx]);
} }
cleanup_es58x_dev: }
kfree(es58x_dev);
return ret; return ret;
} }
...@@ -2270,24 +2278,12 @@ static int es58x_probe(struct usb_interface *intf, ...@@ -2270,24 +2278,12 @@ static int es58x_probe(struct usb_interface *intf,
static void es58x_disconnect(struct usb_interface *intf) static void es58x_disconnect(struct usb_interface *intf)
{ {
struct es58x_device *es58x_dev = usb_get_intfdata(intf); struct es58x_device *es58x_dev = usb_get_intfdata(intf);
struct net_device *netdev;
int i;
dev_info(&intf->dev, "Disconnecting %s %s\n", dev_info(&intf->dev, "Disconnecting %s %s\n",
es58x_dev->udev->manufacturer, es58x_dev->udev->product); es58x_dev->udev->manufacturer, es58x_dev->udev->product);
for (i = 0; i < es58x_dev->num_can_ch; i++) { es58x_free_netdevs(es58x_dev);
netdev = es58x_dev->netdev[i];
if (!netdev)
continue;
unregister_candev(netdev);
es58x_dev->netdev[i] = NULL;
free_candev(netdev);
}
es58x_free_urbs(es58x_dev); es58x_free_urbs(es58x_dev);
kfree(es58x_dev);
usb_set_intfdata(intf, NULL); usb_set_intfdata(intf, NULL);
} }
......
...@@ -287,7 +287,7 @@ struct es58x_priv { ...@@ -287,7 +287,7 @@ struct es58x_priv {
* @rx_urb_cmd_max_len: Maximum length of a RX URB command. * @rx_urb_cmd_max_len: Maximum length of a RX URB command.
* @fifo_mask: Bit mask to quickly convert the tx_tail and tx_head * @fifo_mask: Bit mask to quickly convert the tx_tail and tx_head
* field of the struct es58x_priv into echo_skb * field of the struct es58x_priv into echo_skb
* indexes. Properties: @fifo_mask = echos_skb_max - 1 where * indexes. Properties: @fifo_mask = echo_skb_max - 1 where
* echo_skb_max must be a power of two. Also, echo_skb_max must * echo_skb_max must be a power of two. Also, echo_skb_max must
* not exceed the maximum size of the device internal TX FIFO * not exceed the maximum size of the device internal TX FIFO
* length. This parameter is used to control the network queue * length. This parameter is used to control the network queue
......
...@@ -357,8 +357,7 @@ static int es58x_fd_tx_can_msg(struct es58x_priv *priv, ...@@ -357,8 +357,7 @@ static int es58x_fd_tx_can_msg(struct es58x_priv *priv,
return ret; return ret;
/* Fill message contents. */ /* Fill message contents. */
tx_can_msg = (struct es58x_fd_tx_can_msg *) tx_can_msg = (typeof(tx_can_msg))&es58x_fd_urb_cmd->raw_msg[msg_len];
&es58x_fd_urb_cmd->tx_can_msg_buf[msg_len];
tx_can_msg->packet_idx = (u8)priv->tx_head; tx_can_msg->packet_idx = (u8)priv->tx_head;
put_unaligned_le32(es58x_get_raw_can_id(cf), &tx_can_msg->can_id); put_unaligned_le32(es58x_get_raw_can_id(cf), &tx_can_msg->can_id);
tx_can_msg->flags = (u8)es58x_get_flags(skb); tx_can_msg->flags = (u8)es58x_get_flags(skb);
...@@ -463,9 +462,9 @@ static int es58x_fd_get_timestamp(struct es58x_device *es58x_dev) ...@@ -463,9 +462,9 @@ static int es58x_fd_get_timestamp(struct es58x_device *es58x_dev)
} }
/* Nominal bittiming constants for ES582.1 and ES584.1 as specified in /* Nominal bittiming constants for ES582.1 and ES584.1 as specified in
* the microcontroller datasheet: "SAM E701/S70/V70/V71 Family" * the microcontroller datasheet: "SAM E70/S70/V70/V71 Family" section
* section 49.6.8 "MCAN Nominal Bit Timing and Prescaler Register" * 49.6.8 "MCAN Nominal Bit Timing and Prescaler Register" from
* from Microchip. * Microchip.
* *
* The values from the specification are the hardware register * The values from the specification are the hardware register
* values. To convert them to the functional values, all ranges were * values. To convert them to the functional values, all ranges were
...@@ -484,8 +483,8 @@ static const struct can_bittiming_const es58x_fd_nom_bittiming_const = { ...@@ -484,8 +483,8 @@ static const struct can_bittiming_const es58x_fd_nom_bittiming_const = {
}; };
/* Data bittiming constants for ES582.1 and ES584.1 as specified in /* Data bittiming constants for ES582.1 and ES584.1 as specified in
* the microcontroller datasheet: "SAM E701/S70/V70/V71 Family" * the microcontroller datasheet: "SAM E70/S70/V70/V71 Family" section
* section 49.6.4 "MCAN Data Bit Timing and Prescaler Register" from * 49.6.4 "MCAN Data Bit Timing and Prescaler Register" from
* Microchip. * Microchip.
*/ */
static const struct can_bittiming_const es58x_fd_data_bittiming_const = { static const struct can_bittiming_const es58x_fd_data_bittiming_const = {
...@@ -501,9 +500,9 @@ static const struct can_bittiming_const es58x_fd_data_bittiming_const = { ...@@ -501,9 +500,9 @@ static const struct can_bittiming_const es58x_fd_data_bittiming_const = {
}; };
/* Transmission Delay Compensation constants for ES582.1 and ES584.1 /* Transmission Delay Compensation constants for ES582.1 and ES584.1
* as specified in the microcontroller datasheet: "SAM * as specified in the microcontroller datasheet: "SAM E70/S70/V70/V71
* E701/S70/V70/V71 Family" section 49.6.15 "MCAN Transmitter Delay * Family" section 49.6.15 "MCAN Transmitter Delay Compensation
* Compensation Register" from Microchip. * Register" from Microchip.
*/ */
static const struct can_tdc_const es58x_tdc_const = { static const struct can_tdc_const es58x_tdc_const = {
.tdcv_max = 0, /* Manual mode not supported. */ .tdcv_max = 0, /* Manual mode not supported. */
......
...@@ -63,6 +63,8 @@ ...@@ -63,6 +63,8 @@
#define PCAN_USB_MSG_HEADER_LEN 2 #define PCAN_USB_MSG_HEADER_LEN 2
#define PCAN_USB_MSG_TX_CAN 2 /* Tx msg is a CAN frame */
/* PCAN-USB adapter internal clock (MHz) */ /* PCAN-USB adapter internal clock (MHz) */
#define PCAN_USB_CRYSTAL_HZ 16000000 #define PCAN_USB_CRYSTAL_HZ 16000000
...@@ -73,6 +75,10 @@ ...@@ -73,6 +75,10 @@
#define PCAN_USB_STATUSLEN_RTR (1 << 4) #define PCAN_USB_STATUSLEN_RTR (1 << 4)
#define PCAN_USB_STATUSLEN_DLC (0xf) #define PCAN_USB_STATUSLEN_DLC (0xf)
/* PCAN-USB 4.1 CAN Id tx extended flags */
#define PCAN_USB_TX_SRR 0x01 /* SJA1000 SRR command */
#define PCAN_USB_TX_AT 0x02 /* SJA1000 AT command */
/* PCAN-USB error flags */ /* PCAN-USB error flags */
#define PCAN_USB_ERROR_TXFULL 0x01 #define PCAN_USB_ERROR_TXFULL 0x01
#define PCAN_USB_ERROR_RXQOVR 0x02 #define PCAN_USB_ERROR_RXQOVR 0x02
...@@ -384,7 +390,8 @@ static int pcan_usb_get_device_id(struct peak_usb_device *dev, u32 *device_id) ...@@ -384,7 +390,8 @@ static int pcan_usb_get_device_id(struct peak_usb_device *dev, u32 *device_id)
if (err) if (err)
netdev_err(dev->netdev, "getting device id failure: %d\n", err); netdev_err(dev->netdev, "getting device id failure: %d\n", err);
*device_id = args[0]; else
*device_id = args[0];
return err; return err;
} }
...@@ -445,145 +452,65 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n, ...@@ -445,145 +452,65 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n,
{ {
struct sk_buff *skb; struct sk_buff *skb;
struct can_frame *cf; struct can_frame *cf;
enum can_state new_state; enum can_state new_state = CAN_STATE_ERROR_ACTIVE;
/* ignore this error until 1st ts received */ /* ignore this error until 1st ts received */
if (n == PCAN_USB_ERROR_QOVR) if (n == PCAN_USB_ERROR_QOVR)
if (!mc->pdev->time_ref.tick_count) if (!mc->pdev->time_ref.tick_count)
return 0; return 0;
new_state = mc->pdev->dev.can.state;
switch (mc->pdev->dev.can.state) {
case CAN_STATE_ERROR_ACTIVE:
if (n & PCAN_USB_ERROR_BUS_LIGHT) {
new_state = CAN_STATE_ERROR_WARNING;
break;
}
fallthrough;
case CAN_STATE_ERROR_WARNING:
if (n & PCAN_USB_ERROR_BUS_HEAVY) {
new_state = CAN_STATE_ERROR_PASSIVE;
break;
}
if (n & PCAN_USB_ERROR_BUS_OFF) {
new_state = CAN_STATE_BUS_OFF;
break;
}
if (n & ~PCAN_USB_ERROR_BUS) {
/*
* trick to bypass next comparison and process other
* errors
*/
new_state = CAN_STATE_MAX;
break;
}
if ((n & PCAN_USB_ERROR_BUS_LIGHT) == 0) {
/* no error (back to active state) */
new_state = CAN_STATE_ERROR_ACTIVE;
break;
}
break;
case CAN_STATE_ERROR_PASSIVE:
if (n & PCAN_USB_ERROR_BUS_OFF) {
new_state = CAN_STATE_BUS_OFF;
break;
}
if (n & PCAN_USB_ERROR_BUS_LIGHT) {
new_state = CAN_STATE_ERROR_WARNING;
break;
}
if (n & ~PCAN_USB_ERROR_BUS) {
/*
* trick to bypass next comparison and process other
* errors
*/
new_state = CAN_STATE_MAX;
break;
}
if ((n & PCAN_USB_ERROR_BUS_HEAVY) == 0) {
/* no error (back to warning state) */
new_state = CAN_STATE_ERROR_WARNING;
break;
}
break;
default:
/* do nothing waiting for restart */
return 0;
}
/* donot post any error if current state didn't change */
if (mc->pdev->dev.can.state == new_state)
return 0;
/* allocate an skb to store the error frame */ /* allocate an skb to store the error frame */
skb = alloc_can_err_skb(mc->netdev, &cf); skb = alloc_can_err_skb(mc->netdev, &cf);
if (!skb)
return -ENOMEM;
switch (new_state) {
case CAN_STATE_BUS_OFF:
cf->can_id |= CAN_ERR_BUSOFF;
mc->pdev->dev.can.can_stats.bus_off++;
can_bus_off(mc->netdev);
break;
case CAN_STATE_ERROR_PASSIVE:
cf->can_id |= CAN_ERR_CRTL;
cf->data[1] = (mc->pdev->bec.txerr > mc->pdev->bec.rxerr) ?
CAN_ERR_CRTL_TX_PASSIVE :
CAN_ERR_CRTL_RX_PASSIVE;
cf->data[6] = mc->pdev->bec.txerr;
cf->data[7] = mc->pdev->bec.rxerr;
mc->pdev->dev.can.can_stats.error_passive++;
break;
case CAN_STATE_ERROR_WARNING:
cf->can_id |= CAN_ERR_CRTL;
cf->data[1] = (mc->pdev->bec.txerr > mc->pdev->bec.rxerr) ?
CAN_ERR_CRTL_TX_WARNING :
CAN_ERR_CRTL_RX_WARNING;
cf->data[6] = mc->pdev->bec.txerr;
cf->data[7] = mc->pdev->bec.rxerr;
mc->pdev->dev.can.can_stats.error_warning++;
break;
case CAN_STATE_ERROR_ACTIVE: if (n & PCAN_USB_ERROR_RXQOVR) {
cf->can_id |= CAN_ERR_CRTL; /* data overrun interrupt */
cf->data[1] = CAN_ERR_CRTL_ACTIVE; netdev_dbg(mc->netdev, "data overrun interrupt\n");
mc->netdev->stats.rx_over_errors++;
/* sync local copies of rxerr/txerr counters */ mc->netdev->stats.rx_errors++;
mc->pdev->bec.txerr = 0; if (cf) {
mc->pdev->bec.rxerr = 0;
break;
default:
/* CAN_STATE_MAX (trick to handle other errors) */
if (n & PCAN_USB_ERROR_TXQFULL)
netdev_dbg(mc->netdev, "device Tx queue full)\n");
if (n & PCAN_USB_ERROR_RXQOVR) {
netdev_dbg(mc->netdev, "data overrun interrupt\n");
cf->can_id |= CAN_ERR_CRTL; cf->can_id |= CAN_ERR_CRTL;
cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW; cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW;
mc->netdev->stats.rx_over_errors++;
mc->netdev->stats.rx_errors++;
} }
}
cf->data[6] = mc->pdev->bec.txerr; if (n & PCAN_USB_ERROR_TXQFULL)
cf->data[7] = mc->pdev->bec.rxerr; netdev_dbg(mc->netdev, "device Tx queue full)\n");
new_state = mc->pdev->dev.can.state; if (n & PCAN_USB_ERROR_BUS_OFF) {
break; new_state = CAN_STATE_BUS_OFF;
} else if (n & PCAN_USB_ERROR_BUS_HEAVY) {
new_state = ((mc->pdev->bec.txerr >= 128) ||
(mc->pdev->bec.rxerr >= 128)) ?
CAN_STATE_ERROR_PASSIVE :
CAN_STATE_ERROR_WARNING;
} else {
new_state = CAN_STATE_ERROR_ACTIVE;
} }
mc->pdev->dev.can.state = new_state; /* handle change of state */
if (new_state != mc->pdev->dev.can.state) {
enum can_state tx_state =
(mc->pdev->bec.txerr >= mc->pdev->bec.rxerr) ?
new_state : 0;
enum can_state rx_state =
(mc->pdev->bec.txerr <= mc->pdev->bec.rxerr) ?
new_state : 0;
can_change_state(mc->netdev, cf, tx_state, rx_state);
if (new_state == CAN_STATE_BUS_OFF) {
can_bus_off(mc->netdev);
} else if (cf && (cf->can_id & CAN_ERR_CRTL)) {
/* Supply TX/RX error counters in case of
* controller error.
*/
cf->data[6] = mc->pdev->bec.txerr;
cf->data[7] = mc->pdev->bec.rxerr;
}
}
if (!skb)
return -ENOMEM;
if (status_len & PCAN_USB_STATUSLEN_TIMESTAMP) { if (status_len & PCAN_USB_STATUSLEN_TIMESTAMP) {
struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb); struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb);
...@@ -704,6 +631,7 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len) ...@@ -704,6 +631,7 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len)
struct sk_buff *skb; struct sk_buff *skb;
struct can_frame *cf; struct can_frame *cf;
struct skb_shared_hwtstamps *hwts; struct skb_shared_hwtstamps *hwts;
u32 can_id_flags;
skb = alloc_can_skb(mc->netdev, &cf); skb = alloc_can_skb(mc->netdev, &cf);
if (!skb) if (!skb)
...@@ -713,13 +641,15 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len) ...@@ -713,13 +641,15 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len)
if ((mc->ptr + 4) > mc->end) if ((mc->ptr + 4) > mc->end)
goto decode_failed; goto decode_failed;
cf->can_id = get_unaligned_le32(mc->ptr) >> 3 | CAN_EFF_FLAG; can_id_flags = get_unaligned_le32(mc->ptr);
cf->can_id = can_id_flags >> 3 | CAN_EFF_FLAG;
mc->ptr += 4; mc->ptr += 4;
} else { } else {
if ((mc->ptr + 2) > mc->end) if ((mc->ptr + 2) > mc->end)
goto decode_failed; goto decode_failed;
cf->can_id = get_unaligned_le16(mc->ptr) >> 5; can_id_flags = get_unaligned_le16(mc->ptr);
cf->can_id = can_id_flags >> 5;
mc->ptr += 2; mc->ptr += 2;
} }
...@@ -742,6 +672,10 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len) ...@@ -742,6 +672,10 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len)
memcpy(cf->data, mc->ptr, cf->len); memcpy(cf->data, mc->ptr, cf->len);
mc->ptr += rec_len; mc->ptr += rec_len;
/* Ignore next byte (client private id) if SRR bit is set */
if (can_id_flags & PCAN_USB_TX_SRR)
mc->ptr++;
} }
/* convert timestamp into kernel time */ /* convert timestamp into kernel time */
...@@ -819,10 +753,11 @@ static int pcan_usb_encode_msg(struct peak_usb_device *dev, struct sk_buff *skb, ...@@ -819,10 +753,11 @@ static int pcan_usb_encode_msg(struct peak_usb_device *dev, struct sk_buff *skb,
struct net_device *netdev = dev->netdev; struct net_device *netdev = dev->netdev;
struct net_device_stats *stats = &netdev->stats; struct net_device_stats *stats = &netdev->stats;
struct can_frame *cf = (struct can_frame *)skb->data; struct can_frame *cf = (struct can_frame *)skb->data;
u32 can_id_flags = cf->can_id & CAN_ERR_MASK;
u8 *pc; u8 *pc;
obuf[0] = 2; obuf[0] = PCAN_USB_MSG_TX_CAN;
obuf[1] = 1; obuf[1] = 1; /* only one CAN frame is stored in the packet */
pc = obuf + PCAN_USB_MSG_HEADER_LEN; pc = obuf + PCAN_USB_MSG_HEADER_LEN;
...@@ -837,12 +772,28 @@ static int pcan_usb_encode_msg(struct peak_usb_device *dev, struct sk_buff *skb, ...@@ -837,12 +772,28 @@ static int pcan_usb_encode_msg(struct peak_usb_device *dev, struct sk_buff *skb,
*pc |= PCAN_USB_STATUSLEN_EXT_ID; *pc |= PCAN_USB_STATUSLEN_EXT_ID;
pc++; pc++;
put_unaligned_le32((cf->can_id & CAN_ERR_MASK) << 3, pc); can_id_flags <<= 3;
if (dev->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
can_id_flags |= PCAN_USB_TX_SRR;
if (dev->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
can_id_flags |= PCAN_USB_TX_AT;
put_unaligned_le32(can_id_flags, pc);
pc += 4; pc += 4;
} else { } else {
pc++; pc++;
put_unaligned_le16((cf->can_id & CAN_ERR_MASK) << 5, pc); can_id_flags <<= 5;
if (dev->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
can_id_flags |= PCAN_USB_TX_SRR;
if (dev->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
can_id_flags |= PCAN_USB_TX_AT;
put_unaligned_le16(can_id_flags, pc);
pc += 2; pc += 2;
} }
...@@ -852,6 +803,10 @@ static int pcan_usb_encode_msg(struct peak_usb_device *dev, struct sk_buff *skb, ...@@ -852,6 +803,10 @@ static int pcan_usb_encode_msg(struct peak_usb_device *dev, struct sk_buff *skb,
pc += cf->len; pc += cf->len;
} }
/* SRR bit needs a writer id (useless here) */
if (can_id_flags & PCAN_USB_TX_SRR)
*pc++ = 0x80;
obuf[(*size)-1] = (u8)(stats->tx_packets & 0xff); obuf[(*size)-1] = (u8)(stats->tx_packets & 0xff);
return 0; return 0;
...@@ -926,6 +881,19 @@ static int pcan_usb_init(struct peak_usb_device *dev) ...@@ -926,6 +881,19 @@ static int pcan_usb_init(struct peak_usb_device *dev)
return err; return err;
} }
/* Since rev 4.1, PCAN-USB is able to make single-shot as well as
* looped back frames.
*/
if (dev->device_rev >= 41) {
struct can_priv *priv = netdev_priv(dev->netdev);
priv->ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT |
CAN_CTRLMODE_LOOPBACK;
} else {
dev_info(dev->netdev->dev.parent,
"Firmware update available. Please contact support@peak-system.com\n");
}
dev_info(dev->netdev->dev.parent, dev_info(dev->netdev->dev.parent,
"PEAK-System %s adapter hwrev %u serial %08X (%u channel)\n", "PEAK-System %s adapter hwrev %u serial %08X (%u channel)\n",
pcan_usb.name, dev->device_rev, serial_number, pcan_usb.name, dev->device_rev, serial_number,
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* quanta, from when the bit is sent on the TX pin to when it is * quanta, from when the bit is sent on the TX pin to when it is
* received on the RX pin of the transmitter. Possible options: * received on the RX pin of the transmitter. Possible options:
* *
* O: automatic mode. The controller dynamically measure @tdcv * 0: automatic mode. The controller dynamically measures @tdcv
* for each transmitted CAN FD frame. * for each transmitted CAN FD frame.
* *
* Other values: manual mode. Use the fixed provided value. * Other values: manual mode. Use the fixed provided value.
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
* @tdco: Transmitter Delay Compensation Offset. Offset value, in time * @tdco: Transmitter Delay Compensation Offset. Offset value, in time
* quanta, defining the distance between the start of the bit * quanta, defining the distance between the start of the bit
* reception on the RX pin of the transceiver and the SSP * reception on the RX pin of the transceiver and the SSP
* position such as SSP = @tdcv + @tdco. * position such that SSP = @tdcv + @tdco.
* *
* If @tdco is zero, then TDC is disabled and both @tdcv and * If @tdco is zero, then TDC is disabled and both @tdcv and
* @tdcf should be ignored. * @tdcf should be ignored.
......
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2021 Angelo Dureghello <angelo@kernel-space.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _CAN_PLATFORM_FLEXCAN_H
#define _CAN_PLATFORM_FLEXCAN_H
struct flexcan_platform_data {
u32 clock_frequency;
u8 clk_src;
};
#endif /* _CAN_PLATFORM_FLEXCAN_H */
...@@ -20,6 +20,7 @@ struct can_rx_offload { ...@@ -20,6 +20,7 @@ struct can_rx_offload {
bool drop); bool drop);
struct sk_buff_head skb_queue; struct sk_buff_head skb_queue;
struct sk_buff_head skb_irq_queue;
u32 skb_queue_len_max; u32 skb_queue_len_max;
unsigned int mb_first; unsigned int mb_first;
...@@ -48,14 +49,11 @@ unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload, ...@@ -48,14 +49,11 @@ unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
unsigned int *frame_len_ptr); unsigned int *frame_len_ptr);
int can_rx_offload_queue_tail(struct can_rx_offload *offload, int can_rx_offload_queue_tail(struct can_rx_offload *offload,
struct sk_buff *skb); struct sk_buff *skb);
void can_rx_offload_irq_finish(struct can_rx_offload *offload);
void can_rx_offload_threaded_irq_finish(struct can_rx_offload *offload);
void can_rx_offload_del(struct can_rx_offload *offload); void can_rx_offload_del(struct can_rx_offload *offload);
void can_rx_offload_enable(struct can_rx_offload *offload); void can_rx_offload_enable(struct can_rx_offload *offload);
static inline void can_rx_offload_schedule(struct can_rx_offload *offload)
{
napi_schedule(&offload->napi);
}
static inline void can_rx_offload_disable(struct can_rx_offload *offload) static inline void can_rx_offload_disable(struct can_rx_offload *offload)
{ {
napi_disable(&offload->napi); napi_disable(&offload->napi);
......
...@@ -352,7 +352,7 @@ static void j1939_sk_sock_destruct(struct sock *sk) ...@@ -352,7 +352,7 @@ static void j1939_sk_sock_destruct(struct sock *sk)
{ {
struct j1939_sock *jsk = j1939_sk(sk); struct j1939_sock *jsk = j1939_sk(sk);
/* This function will be call by the generic networking code, when then /* This function will be called by the generic networking code, when
* the socket is ultimately closed (sk->sk_destruct). * the socket is ultimately closed (sk->sk_destruct).
* *
* The race between * The race between
......
...@@ -776,7 +776,7 @@ static int j1939_session_tx_dpo(struct j1939_session *session) ...@@ -776,7 +776,7 @@ static int j1939_session_tx_dpo(struct j1939_session *session)
static int j1939_session_tx_dat(struct j1939_session *session) static int j1939_session_tx_dat(struct j1939_session *session)
{ {
struct j1939_priv *priv = session->priv; struct j1939_priv *priv = session->priv;
struct j1939_sk_buff_cb *skcb; struct j1939_sk_buff_cb *se_skcb;
int offset, pkt_done, pkt_end; int offset, pkt_done, pkt_end;
unsigned int len, pdelay; unsigned int len, pdelay;
struct sk_buff *se_skb; struct sk_buff *se_skb;
...@@ -788,7 +788,7 @@ static int j1939_session_tx_dat(struct j1939_session *session) ...@@ -788,7 +788,7 @@ static int j1939_session_tx_dat(struct j1939_session *session)
if (!se_skb) if (!se_skb)
return -ENOBUFS; return -ENOBUFS;
skcb = j1939_skb_to_cb(se_skb); se_skcb = j1939_skb_to_cb(se_skb);
tpdat = se_skb->data; tpdat = se_skb->data;
ret = 0; ret = 0;
pkt_done = 0; pkt_done = 0;
...@@ -800,7 +800,7 @@ static int j1939_session_tx_dat(struct j1939_session *session) ...@@ -800,7 +800,7 @@ static int j1939_session_tx_dat(struct j1939_session *session)
while (session->pkt.tx < pkt_end) { while (session->pkt.tx < pkt_end) {
dat[0] = session->pkt.tx - session->pkt.dpo + 1; dat[0] = session->pkt.tx - session->pkt.dpo + 1;
offset = (session->pkt.tx * 7) - skcb->offset; offset = (session->pkt.tx * 7) - se_skcb->offset;
len = se_skb->len - offset; len = se_skb->len - offset;
if (len > 7) if (len > 7)
len = 7; len = 7;
...@@ -808,7 +808,8 @@ static int j1939_session_tx_dat(struct j1939_session *session) ...@@ -808,7 +808,8 @@ static int j1939_session_tx_dat(struct j1939_session *session)
if (offset + len > se_skb->len) { if (offset + len > se_skb->len) {
netdev_err_once(priv->ndev, netdev_err_once(priv->ndev,
"%s: 0x%p: requested data outside of queued buffer: offset %i, len %i, pkt.tx: %i\n", "%s: 0x%p: requested data outside of queued buffer: offset %i, len %i, pkt.tx: %i\n",
__func__, session, skcb->offset, se_skb->len , session->pkt.tx); __func__, session, se_skcb->offset,
se_skb->len , session->pkt.tx);
ret = -EOVERFLOW; ret = -EOVERFLOW;
goto out_free; goto out_free;
} }
...@@ -1092,7 +1093,7 @@ j1939_session_deactivate_activate_next(struct j1939_session *session) ...@@ -1092,7 +1093,7 @@ j1939_session_deactivate_activate_next(struct j1939_session *session)
} }
static void __j1939_session_cancel(struct j1939_session *session, static void __j1939_session_cancel(struct j1939_session *session,
enum j1939_xtp_abort err) enum j1939_xtp_abort err)
{ {
struct j1939_priv *priv = session->priv; struct j1939_priv *priv = session->priv;
...@@ -1190,13 +1191,13 @@ static enum hrtimer_restart j1939_tp_txtimer(struct hrtimer *hrtimer) ...@@ -1190,13 +1191,13 @@ static enum hrtimer_restart j1939_tp_txtimer(struct hrtimer *hrtimer)
static void j1939_session_completed(struct j1939_session *session) static void j1939_session_completed(struct j1939_session *session)
{ {
struct sk_buff *skb; struct sk_buff *se_skb;
if (!session->transmission) { if (!session->transmission) {
skb = j1939_session_skb_get(session); se_skb = j1939_session_skb_get(session);
/* distribute among j1939 receivers */ /* distribute among j1939 receivers */
j1939_sk_recv(session->priv, skb); j1939_sk_recv(session->priv, se_skb);
consume_skb(skb); consume_skb(se_skb);
} }
j1939_session_deactivate_activate_next(session); j1939_session_deactivate_activate_next(session);
...@@ -1263,12 +1264,14 @@ static bool j1939_xtp_rx_cmd_bad_pgn(struct j1939_session *session, ...@@ -1263,12 +1264,14 @@ static bool j1939_xtp_rx_cmd_bad_pgn(struct j1939_session *session,
break; break;
case J1939_ETP_CMD_RTS: case J1939_ETP_CMD_RTS:
case J1939_TP_CMD_RTS: /* fall through */ fallthrough;
case J1939_TP_CMD_RTS:
abort = J1939_XTP_ABORT_BUSY; abort = J1939_XTP_ABORT_BUSY;
break; break;
case J1939_ETP_CMD_CTS: case J1939_ETP_CMD_CTS:
case J1939_TP_CMD_CTS: /* fall through */ fallthrough;
case J1939_TP_CMD_CTS:
abort = J1939_XTP_ABORT_ECTS_UNXPECTED_PGN; abort = J1939_XTP_ABORT_ECTS_UNXPECTED_PGN;
break; break;
...@@ -1277,7 +1280,8 @@ static bool j1939_xtp_rx_cmd_bad_pgn(struct j1939_session *session, ...@@ -1277,7 +1280,8 @@ static bool j1939_xtp_rx_cmd_bad_pgn(struct j1939_session *session,
break; break;
case J1939_ETP_CMD_EOMA: case J1939_ETP_CMD_EOMA:
case J1939_TP_CMD_EOMA: /* fall through */ fallthrough;
case J1939_TP_CMD_EOMA:
abort = J1939_XTP_ABORT_OTHER; abort = J1939_XTP_ABORT_OTHER;
break; break;
...@@ -1767,7 +1771,7 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session, ...@@ -1767,7 +1771,7 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct j1939_priv *priv = session->priv; struct j1939_priv *priv = session->priv;
struct j1939_sk_buff_cb *skcb; struct j1939_sk_buff_cb *skcb, *se_skcb;
struct sk_buff *se_skb = NULL; struct sk_buff *se_skb = NULL;
const u8 *dat; const u8 *dat;
u8 *tpdat; u8 *tpdat;
...@@ -1792,7 +1796,8 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session, ...@@ -1792,7 +1796,8 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session,
break; break;
fallthrough; fallthrough;
case J1939_TP_CMD_BAM: case J1939_TP_CMD_BAM:
case J1939_TP_CMD_CTS: /* fall through */ fallthrough;
case J1939_TP_CMD_CTS:
if (skcb->addr.type != J1939_ETP) if (skcb->addr.type != J1939_ETP)
break; break;
fallthrough; fallthrough;
...@@ -1817,8 +1822,8 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session, ...@@ -1817,8 +1822,8 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session,
goto out_session_cancel; goto out_session_cancel;
} }
skcb = j1939_skb_to_cb(se_skb); se_skcb = j1939_skb_to_cb(se_skb);
offset = packet * 7 - skcb->offset; offset = packet * 7 - se_skcb->offset;
nbytes = se_skb->len - offset; nbytes = se_skb->len - offset;
if (nbytes > 7) if (nbytes > 7)
nbytes = 7; nbytes = 7;
...@@ -1846,7 +1851,7 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session, ...@@ -1846,7 +1851,7 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session,
if (packet == session->pkt.rx) if (packet == session->pkt.rx)
session->pkt.rx++; session->pkt.rx++;
if (skcb->addr.type != J1939_ETP && if (se_skcb->addr.type != J1939_ETP &&
j1939_cb_is_broadcast(&session->skcb)) { j1939_cb_is_broadcast(&session->skcb)) {
if (session->pkt.rx >= session->pkt.total) if (session->pkt.rx >= session->pkt.total)
final = true; final = true;
...@@ -1995,7 +2000,8 @@ static void j1939_tp_cmd_recv(struct j1939_priv *priv, struct sk_buff *skb) ...@@ -1995,7 +2000,8 @@ static void j1939_tp_cmd_recv(struct j1939_priv *priv, struct sk_buff *skb)
extd = J1939_ETP; extd = J1939_ETP;
fallthrough; fallthrough;
case J1939_TP_CMD_BAM: case J1939_TP_CMD_BAM:
case J1939_TP_CMD_RTS: /* fall through */ fallthrough;
case J1939_TP_CMD_RTS:
if (skcb->addr.type != extd) if (skcb->addr.type != extd)
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment