From d5888a1e75c79957822f0c107e61ee301091da10 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 3 Nov 2017 17:31:36 +0100 Subject: [PATCH 01/10] can: peak_usb: remove some 'struct timeval' users We want to remove 'struct timeval' and related interfaces since this is generally not safe for use beyond 2038. For peak_usb, we can simplify the internal interface by using ktime_t directly. This should not change any behavior, but it avoids a few conversions. Signed-off-by: Arnd Bergmann Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/peak_usb/pcan_usb.c | 9 +++------ drivers/net/can/usb/peak_usb/pcan_usb_core.c | 15 +++++++-------- drivers/net/can/usb/peak_usb/pcan_usb_core.h | 3 +-- drivers/net/can/usb/peak_usb/pcan_usb_pro.c | 9 +++------ 4 files changed, 14 insertions(+), 22 deletions(-) diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c index 25a9b79cc42d..f530a80f5051 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb.c @@ -408,7 +408,6 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n, { struct sk_buff *skb; struct can_frame *cf; - struct timeval tv; enum can_state new_state; /* ignore this error until 1st ts received */ @@ -525,8 +524,8 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n, if (status_len & PCAN_USB_STATUSLEN_TIMESTAMP) { struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb); - peak_usb_get_ts_tv(&mc->pdev->time_ref, mc->ts16, &tv); - hwts->hwtstamp = timeval_to_ktime(tv); + peak_usb_get_ts_time(&mc->pdev->time_ref, mc->ts16, + &hwts->hwtstamp); } mc->netdev->stats.rx_packets++; @@ -610,7 +609,6 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len) u8 rec_len = status_len & PCAN_USB_STATUSLEN_DLC; struct sk_buff *skb; struct can_frame *cf; - struct timeval tv; struct skb_shared_hwtstamps *hwts; skb = alloc_can_skb(mc->netdev, &cf); @@ -658,9 +656,8 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len) } /* convert timestamp into kernel time */ - peak_usb_get_ts_tv(&mc->pdev->time_ref, mc->ts16, &tv); hwts = skb_hwtstamps(skb); - hwts->hwtstamp = timeval_to_ktime(tv); + peak_usb_get_ts_time(&mc->pdev->time_ref, mc->ts16, &hwts->hwtstamp); /* update statistics */ mc->netdev->stats.rx_packets++; diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c index 1ca76e03e965..695a75a9b4bb 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c @@ -148,11 +148,11 @@ void peak_usb_set_ts_now(struct peak_time_ref *time_ref, u32 ts_now) /* * compute timeval according to current ts and time_ref data */ -void peak_usb_get_ts_tv(struct peak_time_ref *time_ref, u32 ts, - struct timeval *tv) +void peak_usb_get_ts_time(struct peak_time_ref *time_ref, u32 ts, ktime_t *time) { /* protect from getting timeval before setting now */ if (time_ref->tv_host.tv_sec > 0) { + struct timeval tv; u64 delta_us; delta_us = ts - time_ref->ts_dev_2; @@ -164,10 +164,11 @@ void peak_usb_get_ts_tv(struct peak_time_ref *time_ref, u32 ts, delta_us *= time_ref->adapter->us_per_ts_scale; delta_us >>= time_ref->adapter->us_per_ts_shift; - *tv = time_ref->tv_host_0; - peak_usb_add_us(tv, (u32)delta_us); + tv = time_ref->tv_host_0; + peak_usb_add_us(&tv, (u32)delta_us); + *time = timeval_to_ktime(tv); } else { - *tv = ktime_to_timeval(ktime_get()); + *time = ktime_get(); } } @@ -178,10 +179,8 @@ int peak_usb_netif_rx(struct sk_buff *skb, struct peak_time_ref *time_ref, u32 ts_low, u32 ts_high) { struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb); - struct timeval tv; - peak_usb_get_ts_tv(time_ref, ts_low, &tv); - hwts->hwtstamp = timeval_to_ktime(tv); + peak_usb_get_ts_time(time_ref, ts_low, &hwts->hwtstamp); return netif_rx(skb); } diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.h b/drivers/net/can/usb/peak_usb/pcan_usb_core.h index c01316cac354..b9a221ea7e5c 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.h +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.h @@ -151,8 +151,7 @@ void peak_usb_init_time_ref(struct peak_time_ref *time_ref, const struct peak_usb_adapter *adapter); void peak_usb_update_ts_now(struct peak_time_ref *time_ref, u32 ts_now); void peak_usb_set_ts_now(struct peak_time_ref *time_ref, u32 ts_now); -void peak_usb_get_ts_tv(struct peak_time_ref *time_ref, u32 ts, - struct timeval *tv); +void peak_usb_get_ts_time(struct peak_time_ref *time_ref, u32 ts, ktime_t *tv); int peak_usb_netif_rx(struct sk_buff *skb, struct peak_time_ref *time_ref, u32 ts_low, u32 ts_high); void peak_usb_async_complete(struct urb *urb); diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c index bbdd6058cd2f..0105fbfea273 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c @@ -531,7 +531,6 @@ static int pcan_usb_pro_handle_canmsg(struct pcan_usb_pro_interface *usb_if, struct net_device *netdev = dev->netdev; struct can_frame *can_frame; struct sk_buff *skb; - struct timeval tv; struct skb_shared_hwtstamps *hwts; skb = alloc_can_skb(netdev, &can_frame); @@ -549,9 +548,9 @@ static int pcan_usb_pro_handle_canmsg(struct pcan_usb_pro_interface *usb_if, else memcpy(can_frame->data, rx->data, can_frame->can_dlc); - peak_usb_get_ts_tv(&usb_if->time_ref, le32_to_cpu(rx->ts32), &tv); hwts = skb_hwtstamps(skb); - hwts->hwtstamp = timeval_to_ktime(tv); + peak_usb_get_ts_time(&usb_if->time_ref, le32_to_cpu(rx->ts32), + &hwts->hwtstamp); netdev->stats.rx_packets++; netdev->stats.rx_bytes += can_frame->can_dlc; @@ -571,7 +570,6 @@ static int pcan_usb_pro_handle_error(struct pcan_usb_pro_interface *usb_if, enum can_state new_state = CAN_STATE_ERROR_ACTIVE; u8 err_mask = 0; struct sk_buff *skb; - struct timeval tv; struct skb_shared_hwtstamps *hwts; /* nothing should be sent while in BUS_OFF state */ @@ -667,9 +665,8 @@ static int pcan_usb_pro_handle_error(struct pcan_usb_pro_interface *usb_if, dev->can.state = new_state; - peak_usb_get_ts_tv(&usb_if->time_ref, le32_to_cpu(er->ts32), &tv); hwts = skb_hwtstamps(skb); - hwts->hwtstamp = timeval_to_ktime(tv); + peak_usb_get_ts_time(&usb_if->time_ref, le32_to_cpu(er->ts32), &hwts->hwtstamp); netdev->stats.rx_packets++; netdev->stats.rx_bytes += can_frame->can_dlc; netif_rx(skb); From aa4f3c660a24bfdcc8f03f21f6e7be714b16b8e8 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 3 Nov 2017 17:31:37 +0100 Subject: [PATCH 02/10] can: peak_usb: use ktime_t consistently This changes the calculation of the timestamps to use ktime_t instead of struct timeval as the base. This gets rid of one of the few remaining users of the deprecated ktime_to_timeval() and timeval_to_ktime() helpers. The code should also get more efficient, as we have now removed all of the divisions. I have left the cut-off for resetting the counters as 4.200 seconds, in order to leave the behavior unchanged otherwise. Signed-off-by: Arnd Bergmann Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/peak_usb/pcan_usb_core.c | 46 ++++++-------------- drivers/net/can/usb/peak_usb/pcan_usb_core.h | 2 +- 2 files changed, 15 insertions(+), 33 deletions(-) diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c index 695a75a9b4bb..8f699ee6a528 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c @@ -80,21 +80,6 @@ void peak_usb_init_time_ref(struct peak_time_ref *time_ref, } } -static void peak_usb_add_us(struct timeval *tv, u32 delta_us) -{ - /* number of s. to add to final time */ - u32 delta_s = delta_us / 1000000; - - delta_us -= delta_s * 1000000; - - tv->tv_usec += delta_us; - if (tv->tv_usec >= 1000000) { - tv->tv_usec -= 1000000; - delta_s++; - } - tv->tv_sec += delta_s; -} - /* * sometimes, another now may be more recent than current one... */ @@ -103,7 +88,7 @@ void peak_usb_update_ts_now(struct peak_time_ref *time_ref, u32 ts_now) time_ref->ts_dev_2 = ts_now; /* should wait at least two passes before computing */ - if (time_ref->tv_host.tv_sec > 0) { + if (ktime_to_ns(time_ref->tv_host) > 0) { u32 delta_ts = time_ref->ts_dev_2 - time_ref->ts_dev_1; if (time_ref->ts_dev_2 < time_ref->ts_dev_1) @@ -118,26 +103,26 @@ void peak_usb_update_ts_now(struct peak_time_ref *time_ref, u32 ts_now) */ void peak_usb_set_ts_now(struct peak_time_ref *time_ref, u32 ts_now) { - if (time_ref->tv_host_0.tv_sec == 0) { + if (ktime_to_ns(time_ref->tv_host_0) == 0) { /* use monotonic clock to correctly compute further deltas */ - time_ref->tv_host_0 = ktime_to_timeval(ktime_get()); - time_ref->tv_host.tv_sec = 0; + time_ref->tv_host_0 = ktime_get(); + time_ref->tv_host = ktime_set(0, 0); } else { /* - * delta_us should not be >= 2^32 => delta_s should be < 4294 + * delta_us should not be >= 2^32 => delta should be < 4294s * handle 32-bits wrapping here: if count of s. reaches 4200, * reset counters and change time base */ - if (time_ref->tv_host.tv_sec != 0) { - u32 delta_s = time_ref->tv_host.tv_sec - - time_ref->tv_host_0.tv_sec; - if (delta_s > 4200) { + if (ktime_to_ns(time_ref->tv_host)) { + ktime_t delta = ktime_sub(time_ref->tv_host, + time_ref->tv_host_0); + if (ktime_to_ns(delta) > (4200ull * NSEC_PER_SEC)) { time_ref->tv_host_0 = time_ref->tv_host; time_ref->ts_total = 0; } } - time_ref->tv_host = ktime_to_timeval(ktime_get()); + time_ref->tv_host = ktime_get(); time_ref->tick_count++; } @@ -146,13 +131,12 @@ void peak_usb_set_ts_now(struct peak_time_ref *time_ref, u32 ts_now) } /* - * compute timeval according to current ts and time_ref data + * compute time according to current ts and time_ref data */ void peak_usb_get_ts_time(struct peak_time_ref *time_ref, u32 ts, ktime_t *time) { - /* protect from getting timeval before setting now */ - if (time_ref->tv_host.tv_sec > 0) { - struct timeval tv; + /* protect from getting time before setting now */ + if (ktime_to_ns(time_ref->tv_host)) { u64 delta_us; delta_us = ts - time_ref->ts_dev_2; @@ -164,9 +148,7 @@ void peak_usb_get_ts_time(struct peak_time_ref *time_ref, u32 ts, ktime_t *time) delta_us *= time_ref->adapter->us_per_ts_scale; delta_us >>= time_ref->adapter->us_per_ts_shift; - tv = time_ref->tv_host_0; - peak_usb_add_us(&tv, (u32)delta_us); - *time = timeval_to_ktime(tv); + *time = ktime_add_us(time_ref->tv_host_0, delta_us); } else { *time = ktime_get(); } diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.h b/drivers/net/can/usb/peak_usb/pcan_usb_core.h index b9a221ea7e5c..29f03dccca10 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.h +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.h @@ -96,7 +96,7 @@ extern const struct peak_usb_adapter pcan_usb_pro_fd; extern const struct peak_usb_adapter pcan_usb_x6; struct peak_time_ref { - struct timeval tv_host_0, tv_host; + ktime_t tv_host_0, tv_host; u32 ts_dev_1, ts_dev_2; u64 ts_total; u32 tick_count; From 48794a82c016e7c5a58b5e6f30ad6fea431a7940 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Wed, 1 Nov 2017 14:56:15 +0100 Subject: [PATCH 03/10] can: vxcan: Use common error handling code in vxcan_newlink() Add a jump target so that a bit of exception handling can be better reused at the end of this function. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Acked-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- drivers/net/can/vxcan.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c index 8404e8852a0f..5d1753cfacea 100644 --- a/drivers/net/can/vxcan.c +++ b/drivers/net/can/vxcan.c @@ -227,10 +227,8 @@ static int vxcan_newlink(struct net *net, struct net_device *dev, netif_carrier_off(peer); err = rtnl_configure_link(peer, ifmp); - if (err < 0) { - unregister_netdevice(peer); - return err; - } + if (err < 0) + goto unregister_network_device; /* register first device */ if (tb[IFLA_IFNAME]) @@ -239,10 +237,8 @@ static int vxcan_newlink(struct net *net, struct net_device *dev, snprintf(dev->name, IFNAMSIZ, DRV_NAME "%%d"); err = register_netdevice(dev); - if (err < 0) { - unregister_netdevice(peer); - return err; - } + if (err < 0) + goto unregister_network_device; netif_carrier_off(dev); @@ -254,6 +250,10 @@ static int vxcan_newlink(struct net *net, struct net_device *dev, rcu_assign_pointer(priv->peer, dev); return 0; + +unregister_network_device: + unregister_netdevice(peer); + return err; } static void vxcan_dellink(struct net_device *dev, struct list_head *head) From a4efd5d8a46e2ff3f04ba22b1f3b9ab52eca7154 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sun, 6 Aug 2017 12:18:31 +0530 Subject: [PATCH 04/10] can: c_can_pci: make c_can_pci_data const Make c_can_pci_data structures const as they are only used during a copy operation. Signed-off-by: Bhumika Goyal Signed-off-by: Marc Kleine-Budde --- drivers/net/can/c_can/c_can_pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c index d065c0e2d18e..406b4847e5dc 100644 --- a/drivers/net/can/c_can/c_can_pci.c +++ b/drivers/net/can/c_can/c_can_pci.c @@ -251,14 +251,14 @@ static void c_can_pci_remove(struct pci_dev *pdev) pci_disable_device(pdev); } -static struct c_can_pci_data c_can_sta2x11= { +static const struct c_can_pci_data c_can_sta2x11= { .type = BOSCH_C_CAN, .reg_align = C_CAN_REG_ALIGN_32, .freq = 52000000, /* 52 Mhz */ .bar = 0, }; -static struct c_can_pci_data c_can_pch = { +static const struct c_can_pci_data c_can_pch = { .type = BOSCH_C_CAN, .reg_align = C_CAN_REG_32, .freq = 50000000, /* 50 MHz */ From 88462d2a7830b23edb31f467e8fcd06e56d4cb98 Mon Sep 17 00:00:00 2001 From: Pankaj Bansal Date: Fri, 24 Nov 2017 18:52:08 +0530 Subject: [PATCH 05/10] can: flexcan: Remodel FlexCAN register r/w APIs for big endian FlexCAN controllers. The FlexCAN driver assumed that FlexCAN controller is big endian for powerpc architecture and little endian for other architectures. But this may not be the case. FlexCAN controller can be little or big endian on any architecture. For e.g. NXP LS1021A ARM based SOC has big endian FlexCAN controller. Therefore, the driver has been modified to add a provision for both types of controllers using an additional device tree property. On a "fsl,p1010-flexcan" device BE is default, on all other devices LE is. Big Endian controllers should have "big-endian" set in the device tree. check "Documentation/devicetree/bindings/net/can/fsl-flexcan.txt" for usage. This is the standard practice followed in linux. for more info check: Documentation/devicetree/bindings/common-properties.txt Signed-off-by: Pankaj Bansal Signed-off-by: Bhupesh Sharma Signed-off-by: Sakar Arora Reviewed-by: Zhengxiong Jin Reviewed-by: Poonam Aggrwal Signed-off-by: Marc Kleine-Budde --- drivers/net/can/flexcan.c | 237 +++++++++++++++++++++----------------- 1 file changed, 133 insertions(+), 104 deletions(-) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index a13a4896a8bd..4c873fbe661f 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -279,6 +279,10 @@ struct flexcan_priv { struct clk *clk_per; const struct flexcan_devtype_data *devtype_data; struct regulator *reg_xceiver; + + /* Read and Write APIs */ + u32 (*read)(void __iomem *addr); + void (*write)(u32 val, void __iomem *addr); }; static const struct flexcan_devtype_data fsl_p1010_devtype_data = { @@ -312,39 +316,45 @@ static const struct can_bittiming_const flexcan_bittiming_const = { .brp_inc = 1, }; -/* Abstract off the read/write for arm versus ppc. This - * assumes that PPC uses big-endian registers and everything - * else uses little-endian registers, independent of CPU - * endianness. +/* FlexCAN module is essentially modelled as a little-endian IP in most + * SoCs, i.e the registers as well as the message buffer areas are + * implemented in a little-endian fashion. + * + * However there are some SoCs (e.g. LS1021A) which implement the FlexCAN + * module in a big-endian fashion (i.e the registers as well as the + * message buffer areas are implemented in a big-endian way). + * + * In addition, the FlexCAN module can be found on SoCs having ARM or + * PPC cores. So, we need to abstract off the register read/write + * functions, ensuring that these cater to all the combinations of module + * endianness and underlying CPU endianness. */ -#if defined(CONFIG_PPC) -static inline u32 flexcan_read(void __iomem *addr) +static inline u32 flexcan_read_be(void __iomem *addr) { - return in_be32(addr); + return ioread32be(addr); } -static inline void flexcan_write(u32 val, void __iomem *addr) +static inline void flexcan_write_be(u32 val, void __iomem *addr) { - out_be32(addr, val); -} -#else -static inline u32 flexcan_read(void __iomem *addr) -{ - return readl(addr); + iowrite32be(val, addr); } -static inline void flexcan_write(u32 val, void __iomem *addr) +static inline u32 flexcan_read_le(void __iomem *addr) { - writel(val, addr); + return ioread32(addr); +} + +static inline void flexcan_write_le(u32 val, void __iomem *addr) +{ + iowrite32(val, addr); } -#endif static inline void flexcan_error_irq_enable(const struct flexcan_priv *priv) { struct flexcan_regs __iomem *regs = priv->regs; u32 reg_ctrl = (priv->reg_ctrl_default | FLEXCAN_CTRL_ERR_MSK); - flexcan_write(reg_ctrl, ®s->ctrl); + priv->write(reg_ctrl, ®s->ctrl); } static inline void flexcan_error_irq_disable(const struct flexcan_priv *priv) @@ -352,7 +362,7 @@ static inline void flexcan_error_irq_disable(const struct flexcan_priv *priv) struct flexcan_regs __iomem *regs = priv->regs; u32 reg_ctrl = (priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_MSK); - flexcan_write(reg_ctrl, ®s->ctrl); + priv->write(reg_ctrl, ®s->ctrl); } static inline int flexcan_transceiver_enable(const struct flexcan_priv *priv) @@ -377,14 +387,14 @@ static int flexcan_chip_enable(struct flexcan_priv *priv) unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; u32 reg; - reg = flexcan_read(®s->mcr); + reg = priv->read(®s->mcr); reg &= ~FLEXCAN_MCR_MDIS; - flexcan_write(reg, ®s->mcr); + priv->write(reg, ®s->mcr); - while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) + while (timeout-- && (priv->read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) udelay(10); - if (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK) + if (priv->read(®s->mcr) & FLEXCAN_MCR_LPM_ACK) return -ETIMEDOUT; return 0; @@ -396,14 +406,14 @@ static int flexcan_chip_disable(struct flexcan_priv *priv) unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; u32 reg; - reg = flexcan_read(®s->mcr); + reg = priv->read(®s->mcr); reg |= FLEXCAN_MCR_MDIS; - flexcan_write(reg, ®s->mcr); + priv->write(reg, ®s->mcr); - while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) + while (timeout-- && !(priv->read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) udelay(10); - if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) + if (!(priv->read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) return -ETIMEDOUT; return 0; @@ -415,14 +425,14 @@ static int flexcan_chip_freeze(struct flexcan_priv *priv) unsigned int timeout = 1000 * 1000 * 10 / priv->can.bittiming.bitrate; u32 reg; - reg = flexcan_read(®s->mcr); + reg = priv->read(®s->mcr); reg |= FLEXCAN_MCR_HALT; - flexcan_write(reg, ®s->mcr); + priv->write(reg, ®s->mcr); - while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) + while (timeout-- && !(priv->read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) udelay(100); - if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) + if (!(priv->read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) return -ETIMEDOUT; return 0; @@ -434,14 +444,14 @@ static int flexcan_chip_unfreeze(struct flexcan_priv *priv) unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; u32 reg; - reg = flexcan_read(®s->mcr); + reg = priv->read(®s->mcr); reg &= ~FLEXCAN_MCR_HALT; - flexcan_write(reg, ®s->mcr); + priv->write(reg, ®s->mcr); - while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) + while (timeout-- && (priv->read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) udelay(10); - if (flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK) + if (priv->read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK) return -ETIMEDOUT; return 0; @@ -452,11 +462,11 @@ static int flexcan_chip_softreset(struct flexcan_priv *priv) struct flexcan_regs __iomem *regs = priv->regs; unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; - flexcan_write(FLEXCAN_MCR_SOFTRST, ®s->mcr); - while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST)) + priv->write(FLEXCAN_MCR_SOFTRST, ®s->mcr); + while (timeout-- && (priv->read(®s->mcr) & FLEXCAN_MCR_SOFTRST)) udelay(10); - if (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST) + if (priv->read(®s->mcr) & FLEXCAN_MCR_SOFTRST) return -ETIMEDOUT; return 0; @@ -467,7 +477,7 @@ static int __flexcan_get_berr_counter(const struct net_device *dev, { const struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_regs __iomem *regs = priv->regs; - u32 reg = flexcan_read(®s->ecr); + u32 reg = priv->read(®s->ecr); bec->txerr = (reg >> 0) & 0xff; bec->rxerr = (reg >> 8) & 0xff; @@ -523,24 +533,24 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev) if (cf->can_dlc > 0) { data = be32_to_cpup((__be32 *)&cf->data[0]); - flexcan_write(data, &priv->tx_mb->data[0]); + priv->write(data, &priv->tx_mb->data[0]); } if (cf->can_dlc > 3) { data = be32_to_cpup((__be32 *)&cf->data[4]); - flexcan_write(data, &priv->tx_mb->data[1]); + priv->write(data, &priv->tx_mb->data[1]); } can_put_echo_skb(skb, dev, 0); - flexcan_write(can_id, &priv->tx_mb->can_id); - flexcan_write(ctrl, &priv->tx_mb->can_ctrl); + priv->write(can_id, &priv->tx_mb->can_id); + priv->write(ctrl, &priv->tx_mb->can_ctrl); /* Errata ERR005829 step8: * Write twice INACTIVE(0x8) code to first MB. */ - flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, + priv->write(FLEXCAN_MB_CODE_TX_INACTIVE, &priv->tx_mb_reserved->can_ctrl); - flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, + priv->write(FLEXCAN_MB_CODE_TX_INACTIVE, &priv->tx_mb_reserved->can_ctrl); return NETDEV_TX_OK; @@ -659,7 +669,7 @@ static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload, u32 code; do { - reg_ctrl = flexcan_read(&mb->can_ctrl); + reg_ctrl = priv->read(&mb->can_ctrl); } while (reg_ctrl & FLEXCAN_MB_CODE_RX_BUSY_BIT); /* is this MB empty? */ @@ -674,17 +684,17 @@ static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload, offload->dev->stats.rx_errors++; } } else { - reg_iflag1 = flexcan_read(®s->iflag1); + reg_iflag1 = priv->read(®s->iflag1); if (!(reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE)) return 0; - reg_ctrl = flexcan_read(&mb->can_ctrl); + reg_ctrl = priv->read(&mb->can_ctrl); } /* increase timstamp to full 32 bit */ *timestamp = reg_ctrl << 16; - reg_id = flexcan_read(&mb->can_id); + reg_id = priv->read(&mb->can_id); if (reg_ctrl & FLEXCAN_MB_CNT_IDE) cf->can_id = ((reg_id >> 0) & CAN_EFF_MASK) | CAN_EFF_FLAG; else @@ -694,19 +704,19 @@ static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload, cf->can_id |= CAN_RTR_FLAG; cf->can_dlc = get_can_dlc((reg_ctrl >> 16) & 0xf); - *(__be32 *)(cf->data + 0) = cpu_to_be32(flexcan_read(&mb->data[0])); - *(__be32 *)(cf->data + 4) = cpu_to_be32(flexcan_read(&mb->data[1])); + *(__be32 *)(cf->data + 0) = cpu_to_be32(priv->read(&mb->data[0])); + *(__be32 *)(cf->data + 4) = cpu_to_be32(priv->read(&mb->data[1])); /* mark as read */ if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) { /* Clear IRQ */ if (n < 32) - flexcan_write(BIT(n), ®s->iflag1); + priv->write(BIT(n), ®s->iflag1); else - flexcan_write(BIT(n - 32), ®s->iflag2); + priv->write(BIT(n - 32), ®s->iflag2); } else { - flexcan_write(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, ®s->iflag1); - flexcan_read(®s->timer); + priv->write(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, ®s->iflag1); + priv->read(®s->timer); } return 1; @@ -718,8 +728,8 @@ static inline u64 flexcan_read_reg_iflag_rx(struct flexcan_priv *priv) struct flexcan_regs __iomem *regs = priv->regs; u32 iflag1, iflag2; - iflag2 = flexcan_read(®s->iflag2) & priv->reg_imask2_default; - iflag1 = flexcan_read(®s->iflag1) & priv->reg_imask1_default & + iflag2 = priv->read(®s->iflag2) & priv->reg_imask2_default; + iflag1 = priv->read(®s->iflag1) & priv->reg_imask1_default & ~FLEXCAN_IFLAG_MB(priv->tx_mb_idx); return (u64)iflag2 << 32 | iflag1; @@ -735,7 +745,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) u32 reg_iflag1, reg_esr; enum can_state last_state = priv->can.state; - reg_iflag1 = flexcan_read(®s->iflag1); + reg_iflag1 = priv->read(®s->iflag1); /* reception interrupt */ if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) { @@ -758,7 +768,8 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) /* FIFO overflow interrupt */ if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_OVERFLOW) { handled = IRQ_HANDLED; - flexcan_write(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, ®s->iflag1); + priv->write(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, + ®s->iflag1); dev->stats.rx_over_errors++; dev->stats.rx_errors++; } @@ -772,18 +783,18 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) can_led_event(dev, CAN_LED_EVENT_TX); /* after sending a RTR frame MB is in RX mode */ - flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, - &priv->tx_mb->can_ctrl); - flexcan_write(FLEXCAN_IFLAG_MB(priv->tx_mb_idx), ®s->iflag1); + priv->write(FLEXCAN_MB_CODE_TX_INACTIVE, + &priv->tx_mb->can_ctrl); + priv->write(FLEXCAN_IFLAG_MB(priv->tx_mb_idx), ®s->iflag1); netif_wake_queue(dev); } - reg_esr = flexcan_read(®s->esr); + reg_esr = priv->read(®s->esr); /* ACK all bus error and state change IRQ sources */ if (reg_esr & FLEXCAN_ESR_ALL_INT) { handled = IRQ_HANDLED; - flexcan_write(reg_esr & FLEXCAN_ESR_ALL_INT, ®s->esr); + priv->write(reg_esr & FLEXCAN_ESR_ALL_INT, ®s->esr); } /* state change interrupt or broken error state quirk fix is enabled */ @@ -845,7 +856,7 @@ static void flexcan_set_bittiming(struct net_device *dev) struct flexcan_regs __iomem *regs = priv->regs; u32 reg; - reg = flexcan_read(®s->ctrl); + reg = priv->read(®s->ctrl); reg &= ~(FLEXCAN_CTRL_PRESDIV(0xff) | FLEXCAN_CTRL_RJW(0x3) | FLEXCAN_CTRL_PSEG1(0x7) | @@ -869,11 +880,11 @@ static void flexcan_set_bittiming(struct net_device *dev) reg |= FLEXCAN_CTRL_SMP; netdev_dbg(dev, "writing ctrl=0x%08x\n", reg); - flexcan_write(reg, ®s->ctrl); + priv->write(reg, ®s->ctrl); /* print chip status */ netdev_dbg(dev, "%s: mcr=0x%08x ctrl=0x%08x\n", __func__, - flexcan_read(®s->mcr), flexcan_read(®s->ctrl)); + priv->read(®s->mcr), priv->read(®s->ctrl)); } /* flexcan_chip_start @@ -912,7 +923,7 @@ static int flexcan_chip_start(struct net_device *dev) * choose format C * set max mailbox number */ - reg_mcr = flexcan_read(®s->mcr); + reg_mcr = priv->read(®s->mcr); reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff); reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT | FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_SRX_DIS | FLEXCAN_MCR_IRMQ | @@ -926,7 +937,7 @@ static int flexcan_chip_start(struct net_device *dev) FLEXCAN_MCR_MAXMB(priv->tx_mb_idx); } netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr); - flexcan_write(reg_mcr, ®s->mcr); + priv->write(reg_mcr, ®s->mcr); /* CTRL * @@ -939,7 +950,7 @@ static int flexcan_chip_start(struct net_device *dev) * enable bus off interrupt * (== FLEXCAN_CTRL_ERR_STATE) */ - reg_ctrl = flexcan_read(®s->ctrl); + reg_ctrl = priv->read(®s->ctrl); reg_ctrl &= ~FLEXCAN_CTRL_TSYN; reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF | FLEXCAN_CTRL_ERR_STATE; @@ -959,45 +970,45 @@ static int flexcan_chip_start(struct net_device *dev) /* leave interrupts disabled for now */ reg_ctrl &= ~FLEXCAN_CTRL_ERR_ALL; netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl); - flexcan_write(reg_ctrl, ®s->ctrl); + priv->write(reg_ctrl, ®s->ctrl); if ((priv->devtype_data->quirks & FLEXCAN_QUIRK_ENABLE_EACEN_RRS)) { - reg_ctrl2 = flexcan_read(®s->ctrl2); + reg_ctrl2 = priv->read(®s->ctrl2); reg_ctrl2 |= FLEXCAN_CTRL2_EACEN | FLEXCAN_CTRL2_RRS; - flexcan_write(reg_ctrl2, ®s->ctrl2); + priv->write(reg_ctrl2, ®s->ctrl2); } /* clear and invalidate all mailboxes first */ for (i = priv->tx_mb_idx; i < ARRAY_SIZE(regs->mb); i++) { - flexcan_write(FLEXCAN_MB_CODE_RX_INACTIVE, - ®s->mb[i].can_ctrl); + priv->write(FLEXCAN_MB_CODE_RX_INACTIVE, + ®s->mb[i].can_ctrl); } if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) { for (i = priv->offload.mb_first; i <= priv->offload.mb_last; i++) - flexcan_write(FLEXCAN_MB_CODE_RX_EMPTY, - ®s->mb[i].can_ctrl); + priv->write(FLEXCAN_MB_CODE_RX_EMPTY, + ®s->mb[i].can_ctrl); } /* Errata ERR005829: mark first TX mailbox as INACTIVE */ - flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, - &priv->tx_mb_reserved->can_ctrl); + priv->write(FLEXCAN_MB_CODE_TX_INACTIVE, + &priv->tx_mb_reserved->can_ctrl); /* mark TX mailbox as INACTIVE */ - flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, - &priv->tx_mb->can_ctrl); + priv->write(FLEXCAN_MB_CODE_TX_INACTIVE, + &priv->tx_mb->can_ctrl); /* acceptance mask/acceptance code (accept everything) */ - flexcan_write(0x0, ®s->rxgmask); - flexcan_write(0x0, ®s->rx14mask); - flexcan_write(0x0, ®s->rx15mask); + priv->write(0x0, ®s->rxgmask); + priv->write(0x0, ®s->rx14mask); + priv->write(0x0, ®s->rx15mask); if (priv->devtype_data->quirks & FLEXCAN_QUIRK_DISABLE_RXFG) - flexcan_write(0x0, ®s->rxfgmask); + priv->write(0x0, ®s->rxfgmask); /* clear acceptance filters */ for (i = 0; i < ARRAY_SIZE(regs->mb); i++) - flexcan_write(0, ®s->rximr[i]); + priv->write(0, ®s->rximr[i]); /* On Vybrid, disable memory error detection interrupts * and freeze mode. @@ -1010,16 +1021,16 @@ static int flexcan_chip_start(struct net_device *dev) * and Correction of Memory Errors" to write to * MECR register */ - reg_ctrl2 = flexcan_read(®s->ctrl2); + reg_ctrl2 = priv->read(®s->ctrl2); reg_ctrl2 |= FLEXCAN_CTRL2_ECRWRE; - flexcan_write(reg_ctrl2, ®s->ctrl2); + priv->write(reg_ctrl2, ®s->ctrl2); - reg_mecr = flexcan_read(®s->mecr); + reg_mecr = priv->read(®s->mecr); reg_mecr &= ~FLEXCAN_MECR_ECRWRDIS; - flexcan_write(reg_mecr, ®s->mecr); + priv->write(reg_mecr, ®s->mecr); reg_mecr &= ~(FLEXCAN_MECR_NCEFAFRZ | FLEXCAN_MECR_HANCEI_MSK | FLEXCAN_MECR_FANCEI_MSK); - flexcan_write(reg_mecr, ®s->mecr); + priv->write(reg_mecr, ®s->mecr); } err = flexcan_transceiver_enable(priv); @@ -1035,14 +1046,14 @@ static int flexcan_chip_start(struct net_device *dev) /* enable interrupts atomically */ disable_irq(dev->irq); - flexcan_write(priv->reg_ctrl_default, ®s->ctrl); - flexcan_write(priv->reg_imask1_default, ®s->imask1); - flexcan_write(priv->reg_imask2_default, ®s->imask2); + priv->write(priv->reg_ctrl_default, ®s->ctrl); + priv->write(priv->reg_imask1_default, ®s->imask1); + priv->write(priv->reg_imask2_default, ®s->imask2); enable_irq(dev->irq); /* print chip status */ netdev_dbg(dev, "%s: reading mcr=0x%08x ctrl=0x%08x\n", __func__, - flexcan_read(®s->mcr), flexcan_read(®s->ctrl)); + priv->read(®s->mcr), priv->read(®s->ctrl)); return 0; @@ -1067,10 +1078,10 @@ static void flexcan_chip_stop(struct net_device *dev) flexcan_chip_disable(priv); /* Disable all interrupts */ - flexcan_write(0, ®s->imask2); - flexcan_write(0, ®s->imask1); - flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL, - ®s->ctrl); + priv->write(0, ®s->imask2); + priv->write(0, ®s->imask1); + priv->write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL, + ®s->ctrl); flexcan_transceiver_disable(priv); priv->can.state = CAN_STATE_STOPPED; @@ -1185,26 +1196,26 @@ static int register_flexcandev(struct net_device *dev) err = flexcan_chip_disable(priv); if (err) goto out_disable_per; - reg = flexcan_read(®s->ctrl); + reg = priv->read(®s->ctrl); reg |= FLEXCAN_CTRL_CLK_SRC; - flexcan_write(reg, ®s->ctrl); + priv->write(reg, ®s->ctrl); err = flexcan_chip_enable(priv); if (err) goto out_chip_disable; /* set freeze, halt and activate FIFO, restrict register access */ - reg = flexcan_read(®s->mcr); + reg = priv->read(®s->mcr); reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT | FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV; - flexcan_write(reg, ®s->mcr); + priv->write(reg, ®s->mcr); /* Currently we only support newer versions of this core * featuring a RX hardware FIFO (although this driver doesn't * make use of it on some cores). Older cores, found on some * Coldfire derivates are not tested. */ - reg = flexcan_read(®s->mcr); + reg = priv->read(®s->mcr); if (!(reg & FLEXCAN_MCR_FEN)) { netdev_err(dev, "Could not enable RX FIFO, unsupported core\n"); err = -ENODEV; @@ -1232,6 +1243,9 @@ static void unregister_flexcandev(struct net_device *dev) static const struct of_device_id flexcan_of_match[] = { { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, }, { .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, }, + { .compatible = "fsl,imx53-flexcan", .data = &fsl_p1010_devtype_data, }, + { .compatible = "fsl,imx35-flexcan", .data = &fsl_p1010_devtype_data, }, + { .compatible = "fsl,imx25-flexcan", .data = &fsl_p1010_devtype_data, }, { .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, }, { .compatible = "fsl,vf610-flexcan", .data = &fsl_vf610_devtype_data, }, { /* sentinel */ }, @@ -1313,6 +1327,21 @@ static int flexcan_probe(struct platform_device *pdev) dev->flags |= IFF_ECHO; priv = netdev_priv(dev); + + if (of_property_read_bool(pdev->dev.of_node, "big-endian")) { + priv->read = flexcan_read_be; + priv->write = flexcan_write_be; + } else { + if (of_device_is_compatible(pdev->dev.of_node, + "fsl,p1010-flexcan")) { + priv->read = flexcan_read_be; + priv->write = flexcan_write_be; + } else { + priv->read = flexcan_read_le; + priv->write = flexcan_write_le; + } + } + priv->can.clock.freq = clock_freq; priv->can.bittiming_const = &flexcan_bittiming_const; priv->can.do_set_mode = flexcan_set_mode; From 99b7668c04b2752cd672aed650fa93f8446ba28f Mon Sep 17 00:00:00 2001 From: Pankaj Bansal Date: Fri, 24 Nov 2017 18:52:09 +0530 Subject: [PATCH 06/10] can: flexcan: adding platform specific details for LS1021A This patch adds platform specific details for NXP SOC LS1021A to the flexcan driver code. Signed-off-by: Pankaj Bansal Signed-off-by: Bhupesh Sharma Reviewed-by: Zhengxiong Jin Reviewed-by: Poonam Aggrwal Signed-off-by: Marc Kleine-Budde --- drivers/net/can/flexcan.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 4c873fbe661f..3a370d8437b0 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -190,6 +190,7 @@ * MX53 FlexCAN2 03.00.00.00 yes no no no no * MX6s FlexCAN3 10.00.12.00 yes yes no no yes * VF610 FlexCAN3 ? no yes ? yes yes? + * LS1021A FlexCAN2 03.00.04.00 no yes no no yes * * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected. */ @@ -304,6 +305,12 @@ static const struct flexcan_devtype_data fsl_vf610_devtype_data = { FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_OFF_TIMESTAMP, }; +static const struct flexcan_devtype_data fsl_ls1021a_r2_devtype_data = { + .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS | + FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_BROKEN_PERR_STATE | + FLEXCAN_QUIRK_USE_OFF_TIMESTAMP, +}; + static const struct can_bittiming_const flexcan_bittiming_const = { .name = DRV_NAME, .tseg1_min = 4, @@ -1248,6 +1255,7 @@ static const struct of_device_id flexcan_of_match[] = { { .compatible = "fsl,imx25-flexcan", .data = &fsl_p1010_devtype_data, }, { .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, }, { .compatible = "fsl,vf610-flexcan", .data = &fsl_vf610_devtype_data, }, + { .compatible = "fsl,ls1021ar2-flexcan", .data = &fsl_ls1021a_r2_devtype_data, }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, flexcan_of_match); From 525d70a9390a577fcec57e71e142b876a0c226cd Mon Sep 17 00:00:00 2001 From: Pankaj Bansal Date: Fri, 24 Nov 2017 18:52:10 +0530 Subject: [PATCH 07/10] Documentation: can: flexcan: Add big-endian property to device tree The FlexCAN controller can be modelled as little or big endian depending on SOC design. This device tree property identifies the controller endianness and the driver reads/writes controller registers based on that. This is optional property. i.e. if this property is not present in device tree node then controller is assumed to be little endian. if this property is present then controller is assumed to be big endian. Signed-off-by: Pankaj Bansal Reviewed-by: Poonam Aggrwal Acked-by: Rob Herring Signed-off-by: Marc Kleine-Budde --- Documentation/devicetree/bindings/net/can/fsl-flexcan.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt index 56d6cc336e1c..bfc0c433654f 100644 --- a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt +++ b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt @@ -18,6 +18,12 @@ Optional properties: - xceiver-supply: Regulator that powers the CAN transceiver +- big-endian: This means the registers of FlexCAN controller are big endian. + This is optional property.i.e. if this property is not present in + device tree node then controller is assumed to be little endian. + if this property is present then controller is assumed to be big + endian. + Example: can@1c000 { From c8ae67fe02ff4c0e9b0007d60cef3a8ef64eafaf Mon Sep 17 00:00:00 2001 From: Pankaj Bansal Date: Fri, 24 Nov 2017 18:52:11 +0530 Subject: [PATCH 08/10] powerpc: dts: P1010: Add endianness property to flexcan node The flexcan driver assumed that flexcan controller is big endian for powerpc architecture and little endian for other architectures. But this is not universally true. flexcan controller can be little or big endian on any architecture. Therefore the flexcan driver has been modified to check for "big-endian" device tree property for controllers that are big endian. consequently add the property to freescale P1010 SOC device tree. Signed-off-by: Pankaj Bansal Reviewed-by: Poonam Aggrwal Signed-off-by: Marc Kleine-Budde --- arch/powerpc/boot/dts/fsl/p1010si-post.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi index af12ead88c5f..1b4aafc1f6a2 100644 --- a/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi @@ -137,12 +137,14 @@ compatible = "fsl,p1010-flexcan"; reg = <0x1c000 0x1000>; interrupts = <48 0x2 0 0>; + big-endian; }; can1: can@1d000 { compatible = "fsl,p1010-flexcan"; reg = <0x1d000 0x1000>; interrupts = <61 0x2 0 0>; + big-endian; }; L2: l2-cache-controller@20000 { From d50f4630c2e1c7bbfa508ebf1107694d70780be0 Mon Sep 17 00:00:00 2001 From: Pankaj Bansal Date: Fri, 24 Nov 2017 18:52:12 +0530 Subject: [PATCH 09/10] arm: dts: Remove p1010-flexcan compatible from imx series dts The flexcan driver has been modified to check for big-endian dts property for be read/write to flexcan registers/mb. An exception to this rule is powerpc P1010RDB, which is always big-endian, even if big-endian is not present in dts. This is checked using p1010-flexcan compatible in dts. Therefore, remove p1010-flexcan compatible from imx series dts, as their flexcan core is little endian. Signed-off-by: Pankaj Bansal Signed-off-by: Marc Kleine-Budde --- arch/arm/boot/dts/imx25.dtsi | 4 ++-- arch/arm/boot/dts/imx28.dtsi | 4 ++-- arch/arm/boot/dts/imx35.dtsi | 4 ++-- arch/arm/boot/dts/imx53.dtsi | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/imx25.dtsi b/arch/arm/boot/dts/imx25.dtsi index 09ce8b81fafa..fcaff1c66bcb 100644 --- a/arch/arm/boot/dts/imx25.dtsi +++ b/arch/arm/boot/dts/imx25.dtsi @@ -122,7 +122,7 @@ }; can1: can@43f88000 { - compatible = "fsl,imx25-flexcan", "fsl,p1010-flexcan"; + compatible = "fsl,imx25-flexcan"; reg = <0x43f88000 0x4000>; interrupts = <43>; clocks = <&clks 75>, <&clks 75>; @@ -131,7 +131,7 @@ }; can2: can@43f8c000 { - compatible = "fsl,imx25-flexcan", "fsl,p1010-flexcan"; + compatible = "fsl,imx25-flexcan"; reg = <0x43f8c000 0x4000>; interrupts = <44>; clocks = <&clks 76>, <&clks 76>; diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi index 2f4ebe0318d3..e52e05c0fe56 100644 --- a/arch/arm/boot/dts/imx28.dtsi +++ b/arch/arm/boot/dts/imx28.dtsi @@ -1038,7 +1038,7 @@ }; can0: can@80032000 { - compatible = "fsl,imx28-flexcan", "fsl,p1010-flexcan"; + compatible = "fsl,imx28-flexcan"; reg = <0x80032000 0x2000>; interrupts = <8>; clocks = <&clks 58>, <&clks 58>; @@ -1047,7 +1047,7 @@ }; can1: can@80034000 { - compatible = "fsl,imx28-flexcan", "fsl,p1010-flexcan"; + compatible = "fsl,imx28-flexcan"; reg = <0x80034000 0x2000>; interrupts = <9>; clocks = <&clks 59>, <&clks 59>; diff --git a/arch/arm/boot/dts/imx35.dtsi b/arch/arm/boot/dts/imx35.dtsi index 6d5e6a60bee7..1f0e2203b576 100644 --- a/arch/arm/boot/dts/imx35.dtsi +++ b/arch/arm/boot/dts/imx35.dtsi @@ -303,7 +303,7 @@ }; can1: can@53fe4000 { - compatible = "fsl,imx35-flexcan", "fsl,p1010-flexcan"; + compatible = "fsl,imx35-flexcan"; reg = <0x53fe4000 0x1000>; clocks = <&clks 33>, <&clks 33>; clock-names = "ipg", "per"; @@ -312,7 +312,7 @@ }; can2: can@53fe8000 { - compatible = "fsl,imx35-flexcan", "fsl,p1010-flexcan"; + compatible = "fsl,imx35-flexcan"; reg = <0x53fe8000 0x1000>; clocks = <&clks 34>, <&clks 34>; clock-names = "ipg", "per"; diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi index 589a67c5f796..a5a050703320 100644 --- a/arch/arm/boot/dts/imx53.dtsi +++ b/arch/arm/boot/dts/imx53.dtsi @@ -545,7 +545,7 @@ }; can1: can@53fc8000 { - compatible = "fsl,imx53-flexcan", "fsl,p1010-flexcan"; + compatible = "fsl,imx53-flexcan"; reg = <0x53fc8000 0x4000>; interrupts = <82>; clocks = <&clks IMX5_CLK_CAN1_IPG_GATE>, @@ -555,7 +555,7 @@ }; can2: can@53fcc000 { - compatible = "fsl,imx53-flexcan", "fsl,p1010-flexcan"; + compatible = "fsl,imx53-flexcan"; reg = <0x53fcc000 0x4000>; interrupts = <83>; clocks = <&clks IMX5_CLK_CAN2_IPG_GATE>, From fa2edcfb5f2e99e9f47f7ecba9abc5f192aa388b Mon Sep 17 00:00:00 2001 From: Pankaj Bansal Date: Fri, 24 Nov 2017 18:52:13 +0530 Subject: [PATCH 10/10] arm: dts: Add nodes for flexcan devices present on LS1021A-Rev2 SoC This patch adds the device nodes for flexcan controller(s) present on LS1021A-Rev2 SoC. Signed-off-by: Pankaj Bansal Signed-off-by: Bhupesh Sharma Signed-off-by: Sakar Arora Reviewed-by: Zhengxiong Jin Reviewed-by: Poonam Aggrwal Signed-off-by: Marc Kleine-Budde --- arch/arm/boot/dts/ls1021a-qds.dts | 16 ++++++++++++++ arch/arm/boot/dts/ls1021a-twr.dts | 16 ++++++++++++++ arch/arm/boot/dts/ls1021a.dtsi | 36 +++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/arch/arm/boot/dts/ls1021a-qds.dts b/arch/arm/boot/dts/ls1021a-qds.dts index 940875316d0f..4f211e3c903a 100644 --- a/arch/arm/boot/dts/ls1021a-qds.dts +++ b/arch/arm/boot/dts/ls1021a-qds.dts @@ -331,3 +331,19 @@ &uart1 { status = "okay"; }; + +&can0 { + status = "okay"; +}; + +&can1 { + status = "okay"; +}; + +&can2 { + status = "disabled"; +}; + +&can3 { + status = "disabled"; +}; diff --git a/arch/arm/boot/dts/ls1021a-twr.dts b/arch/arm/boot/dts/ls1021a-twr.dts index a8b148ad1dd2..7202d9c504be 100644 --- a/arch/arm/boot/dts/ls1021a-twr.dts +++ b/arch/arm/boot/dts/ls1021a-twr.dts @@ -243,3 +243,19 @@ &uart1 { status = "okay"; }; + +&can0 { + status = "okay"; +}; + +&can1 { + status = "okay"; +}; + +&can2 { + status = "disabled"; +}; + +&can3 { + status = "disabled"; +}; diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi index 9319e1f0f1d8..7789031898b0 100644 --- a/arch/arm/boot/dts/ls1021a.dtsi +++ b/arch/arm/boot/dts/ls1021a.dtsi @@ -730,5 +730,41 @@ <0000 0 0 3 &gic GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 4 &gic GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>; }; + + can0: can@2a70000 { + compatible = "fsl,ls1021ar2-flexcan"; + reg = <0x0 0x2a70000 0x0 0x1000>; + interrupts = ; + clocks = <&clockgen 4 1>, <&clockgen 4 1>; + clock-names = "ipg", "per"; + big-endian; + }; + + can1: can@2a80000 { + compatible = "fsl,ls1021ar2-flexcan"; + reg = <0x0 0x2a80000 0x0 0x1000>; + interrupts = ; + clocks = <&clockgen 4 1>, <&clockgen 4 1>; + clock-names = "ipg", "per"; + big-endian; + }; + + can2: can@2a90000 { + compatible = "fsl,ls1021ar2-flexcan"; + reg = <0x0 0x2a90000 0x0 0x1000>; + interrupts = ; + clocks = <&clockgen 4 1>, <&clockgen 4 1>; + clock-names = "ipg", "per"; + big-endian; + }; + + can3: can@2aa0000 { + compatible = "fsl,ls1021ar2-flexcan"; + reg = <0x0 0x2aa0000 0x0 0x1000>; + interrupts = ; + clocks = <&clockgen 4 1>, <&clockgen 4 1>; + clock-names = "ipg", "per"; + big-endian; + }; }; };