2018-07-06 14:35:12 -03:00
// SPDX-License-Identifier: GPL-2.0
//
// flexcan.c - FLEXCAN CAN controller driver
//
// Copyright (c) 2005-2006 Varma Electronics Oy
// Copyright (c) 2009 Sascha Hauer, Pengutronix
// Copyright (c) 2010-2017 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
// Copyright (c) 2014 David Jander, Protonic Holland
//
// Based on code originally by Andrey Volkov <avolkov@varma-el.com>
2009-07-29 10:20:10 +02:00
# include <linux/netdevice.h>
# include <linux/can.h>
# include <linux/can/dev.h>
# include <linux/can/error.h>
2012-12-18 18:50:58 +01:00
# include <linux/can/led.h>
2015-05-10 15:26:58 +02:00
# include <linux/can/rx-offload.h>
2009-07-29 10:20:10 +02:00
# include <linux/clk.h>
# include <linux/delay.h>
# include <linux/interrupt.h>
# include <linux/io.h>
# include <linux/module.h>
2011-08-16 17:32:23 +00:00
# include <linux/of.h>
2012-06-28 16:21:35 +08:00
# include <linux/of_device.h>
2009-07-29 10:20:10 +02:00
# include <linux/platform_device.h>
2013-06-10 23:12:57 -03:00
# include <linux/regulator/consumer.h>
2009-07-29 10:20:10 +02:00
# define DRV_NAME "flexcan"
/* 8 for RX fifo and 2 error handling */
# define FLEXCAN_NAPI_WEIGHT (8 + 2)
/* FLEXCAN module configuration register (CANMCR) bits */
# define FLEXCAN_MCR_MDIS BIT(31)
# define FLEXCAN_MCR_FRZ BIT(30)
# define FLEXCAN_MCR_FEN BIT(29)
# define FLEXCAN_MCR_HALT BIT(28)
# define FLEXCAN_MCR_NOT_RDY BIT(27)
# define FLEXCAN_MCR_WAK_MSK BIT(26)
# define FLEXCAN_MCR_SOFTRST BIT(25)
# define FLEXCAN_MCR_FRZ_ACK BIT(24)
# define FLEXCAN_MCR_SUPV BIT(23)
# define FLEXCAN_MCR_SLF_WAK BIT(22)
# define FLEXCAN_MCR_WRN_EN BIT(21)
# define FLEXCAN_MCR_LPM_ACK BIT(20)
# define FLEXCAN_MCR_WAK_SRC BIT(19)
# define FLEXCAN_MCR_DOZE BIT(18)
# define FLEXCAN_MCR_SRX_DIS BIT(17)
2015-08-27 16:01:27 +02:00
# define FLEXCAN_MCR_IRMQ BIT(16)
2009-07-29 10:20:10 +02:00
# define FLEXCAN_MCR_LPRIO_EN BIT(13)
# define FLEXCAN_MCR_AEN BIT(12)
2015-09-01 09:00:13 +02:00
/* MCR_MAXMB: maximum used MBs is MAXMB + 1 */
2014-09-02 16:54:17 +02:00
# define FLEXCAN_MCR_MAXMB(x) ((x) & 0x7f)
2015-08-06 14:53:57 +02:00
# define FLEXCAN_MCR_IDAM_A (0x0 << 8)
# define FLEXCAN_MCR_IDAM_B (0x1 << 8)
# define FLEXCAN_MCR_IDAM_C (0x2 << 8)
# define FLEXCAN_MCR_IDAM_D (0x3 << 8)
2009-07-29 10:20:10 +02:00
/* FLEXCAN control register (CANCTRL) bits */
# define FLEXCAN_CTRL_PRESDIV(x) (((x) & 0xff) << 24)
# define FLEXCAN_CTRL_RJW(x) (((x) & 0x03) << 22)
# define FLEXCAN_CTRL_PSEG1(x) (((x) & 0x07) << 19)
# define FLEXCAN_CTRL_PSEG2(x) (((x) & 0x07) << 16)
# define FLEXCAN_CTRL_BOFF_MSK BIT(15)
# define FLEXCAN_CTRL_ERR_MSK BIT(14)
# define FLEXCAN_CTRL_CLK_SRC BIT(13)
# define FLEXCAN_CTRL_LPB BIT(12)
# define FLEXCAN_CTRL_TWRN_MSK BIT(11)
# define FLEXCAN_CTRL_RWRN_MSK BIT(10)
# define FLEXCAN_CTRL_SMP BIT(7)
# define FLEXCAN_CTRL_BOFF_REC BIT(6)
# define FLEXCAN_CTRL_TSYN BIT(5)
# define FLEXCAN_CTRL_LBUF BIT(4)
# define FLEXCAN_CTRL_LOM BIT(3)
# define FLEXCAN_CTRL_PROPSEG(x) ((x) & 0x07)
# define FLEXCAN_CTRL_ERR_BUS (FLEXCAN_CTRL_ERR_MSK)
# define FLEXCAN_CTRL_ERR_STATE \
( FLEXCAN_CTRL_TWRN_MSK | FLEXCAN_CTRL_RWRN_MSK | \
FLEXCAN_CTRL_BOFF_MSK )
# define FLEXCAN_CTRL_ERR_ALL \
( FLEXCAN_CTRL_ERR_BUS | FLEXCAN_CTRL_ERR_STATE )
2014-07-15 14:56:21 +02:00
/* FLEXCAN control register 2 (CTRL2) bits */
2014-09-23 11:03:01 +02:00
# define FLEXCAN_CTRL2_ECRWRE BIT(29)
# define FLEXCAN_CTRL2_WRMFRZ BIT(28)
# define FLEXCAN_CTRL2_RFFN(x) (((x) & 0x0f) << 24)
# define FLEXCAN_CTRL2_TASD(x) (((x) & 0x1f) << 19)
# define FLEXCAN_CTRL2_MRP BIT(18)
# define FLEXCAN_CTRL2_RRS BIT(17)
# define FLEXCAN_CTRL2_EACEN BIT(16)
2014-07-15 14:56:21 +02:00
/* FLEXCAN memory error control register (MECR) bits */
# define FLEXCAN_MECR_ECRWRDIS BIT(31)
# define FLEXCAN_MECR_HANCEI_MSK BIT(19)
# define FLEXCAN_MECR_FANCEI_MSK BIT(18)
# define FLEXCAN_MECR_CEI_MSK BIT(16)
# define FLEXCAN_MECR_HAERRIE BIT(15)
# define FLEXCAN_MECR_FAERRIE BIT(14)
# define FLEXCAN_MECR_EXTERRIE BIT(13)
# define FLEXCAN_MECR_RERRDIS BIT(9)
# define FLEXCAN_MECR_ECCDIS BIT(8)
# define FLEXCAN_MECR_NCEFAFRZ BIT(7)
2009-07-29 10:20:10 +02:00
/* FLEXCAN error and status register (ESR) bits */
# define FLEXCAN_ESR_TWRN_INT BIT(17)
# define FLEXCAN_ESR_RWRN_INT BIT(16)
# define FLEXCAN_ESR_BIT1_ERR BIT(15)
# define FLEXCAN_ESR_BIT0_ERR BIT(14)
# define FLEXCAN_ESR_ACK_ERR BIT(13)
# define FLEXCAN_ESR_CRC_ERR BIT(12)
# define FLEXCAN_ESR_FRM_ERR BIT(11)
# define FLEXCAN_ESR_STF_ERR BIT(10)
# define FLEXCAN_ESR_TX_WRN BIT(9)
# define FLEXCAN_ESR_RX_WRN BIT(8)
# define FLEXCAN_ESR_IDLE BIT(7)
# define FLEXCAN_ESR_TXRX BIT(6)
# define FLEXCAN_EST_FLT_CONF_SHIFT (4)
# define FLEXCAN_ESR_FLT_CONF_MASK (0x3 << FLEXCAN_EST_FLT_CONF_SHIFT)
# define FLEXCAN_ESR_FLT_CONF_ACTIVE (0x0 << FLEXCAN_EST_FLT_CONF_SHIFT)
# define FLEXCAN_ESR_FLT_CONF_PASSIVE (0x1 << FLEXCAN_EST_FLT_CONF_SHIFT)
# define FLEXCAN_ESR_BOFF_INT BIT(2)
# define FLEXCAN_ESR_ERR_INT BIT(1)
# define FLEXCAN_ESR_WAK_INT BIT(0)
# define FLEXCAN_ESR_ERR_BUS \
( FLEXCAN_ESR_BIT1_ERR | FLEXCAN_ESR_BIT0_ERR | \
FLEXCAN_ESR_ACK_ERR | FLEXCAN_ESR_CRC_ERR | \
FLEXCAN_ESR_FRM_ERR | FLEXCAN_ESR_STF_ERR )
# define FLEXCAN_ESR_ERR_STATE \
( FLEXCAN_ESR_TWRN_INT | FLEXCAN_ESR_RWRN_INT | FLEXCAN_ESR_BOFF_INT )
# define FLEXCAN_ESR_ERR_ALL \
( FLEXCAN_ESR_ERR_BUS | FLEXCAN_ESR_ERR_STATE )
2011-12-12 16:09:28 +01:00
# define FLEXCAN_ESR_ALL_INT \
( FLEXCAN_ESR_TWRN_INT | FLEXCAN_ESR_RWRN_INT | \
FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT )
2009-07-29 10:20:10 +02:00
/* FLEXCAN interrupt flag register (IFLAG) bits */
2014-09-03 16:47:22 +02:00
/* Errata ERR005829 step7: Reserve first valid MB */
2018-10-11 17:01:25 +02:00
# define FLEXCAN_TX_MB_RESERVED_OFF_FIFO 8
2015-09-01 09:00:13 +02:00
# define FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP 0
2018-10-11 17:01:25 +02:00
# define FLEXCAN_TX_MB 63
# define FLEXCAN_RX_MB_OFF_TIMESTAMP_FIRST (FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP + 1)
# define FLEXCAN_RX_MB_OFF_TIMESTAMP_LAST (FLEXCAN_TX_MB - 1)
# define FLEXCAN_IFLAG_MB(x) BIT(x & 0x1f)
2009-07-29 10:20:10 +02:00
# define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW BIT(7)
# define FLEXCAN_IFLAG_RX_FIFO_WARN BIT(6)
# define FLEXCAN_IFLAG_RX_FIFO_AVAILABLE BIT(5)
/* FLEXCAN message buffers */
2015-09-01 09:00:13 +02:00
# define FLEXCAN_MB_CODE_MASK (0xf << 24)
# define FLEXCAN_MB_CODE_RX_BUSY_BIT (0x1 << 24)
2014-09-16 12:39:28 +02:00
# define FLEXCAN_MB_CODE_RX_INACTIVE (0x0 << 24)
# define FLEXCAN_MB_CODE_RX_EMPTY (0x4 << 24)
# define FLEXCAN_MB_CODE_RX_FULL (0x2 << 24)
2015-08-06 14:53:57 +02:00
# define FLEXCAN_MB_CODE_RX_OVERRUN (0x6 << 24)
2014-09-16 12:39:28 +02:00
# define FLEXCAN_MB_CODE_RX_RANSWER (0xa << 24)
# define FLEXCAN_MB_CODE_TX_INACTIVE (0x8 << 24)
# define FLEXCAN_MB_CODE_TX_ABORT (0x9 << 24)
# define FLEXCAN_MB_CODE_TX_DATA (0xc << 24)
# define FLEXCAN_MB_CODE_TX_TANSWER (0xe << 24)
2009-07-29 10:20:10 +02:00
# define FLEXCAN_MB_CNT_SRR BIT(22)
# define FLEXCAN_MB_CNT_IDE BIT(21)
# define FLEXCAN_MB_CNT_RTR BIT(20)
# define FLEXCAN_MB_CNT_LENGTH(x) (((x) & 0xf) << 16)
# define FLEXCAN_MB_CNT_TIMESTAMP(x) ((x) & 0xffff)
2015-08-06 14:53:57 +02:00
# define FLEXCAN_TIMEOUT_US (50)
2009-07-29 10:20:10 +02:00
2015-08-06 14:53:57 +02:00
/* FLEXCAN hardware feature flags
2012-10-10 21:10:42 +02:00
*
* Below is some version info we got :
2017-09-15 07:03:58 +00:00
* SOC Version IP - Version Glitch - [ TR ] WRN_INT IRQ Err Memory err RTR re -
* Filter ? connected ? Passive detection ception in MB
2017-11-22 13:01:08 +01:00
* MX25 FlexCAN2 03.00 .00 .00 no no no no no
2017-09-15 07:03:58 +00:00
* MX28 FlexCAN2 03.00 .04 .00 yes yes no no no
2017-11-22 13:01:08 +01:00
* MX35 FlexCAN2 03.00 .00 .00 no no no no no
2017-09-15 07:03:58 +00:00
* MX53 FlexCAN2 03.00 .00 .00 yes no no no no
* MX6s FlexCAN3 10.00 .12 .00 yes yes no no yes
2017-11-27 09:18:21 +01:00
* VF610 FlexCAN3 ? no yes no yes yes ?
2017-11-24 18:52:09 +05:30
* LS1021A FlexCAN2 03.00 .04 .00 no yes no no yes
2012-10-10 21:10:42 +02:00
*
* Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected .
*/
2017-09-15 07:01:23 +00:00
# define FLEXCAN_QUIRK_BROKEN_WERR_STATE BIT(1) /* [TR]WRN_INT not connected */
2015-05-08 15:22:36 +02:00
# define FLEXCAN_QUIRK_DISABLE_RXFG BIT(2) /* Disable RX FIFO Global mask */
2015-09-01 08:57:55 +02:00
# define FLEXCAN_QUIRK_ENABLE_EACEN_RRS BIT(3) /* Enable EACEN and RRS bit in ctrl2 */
2017-03-02 15:42:49 +01:00
# define FLEXCAN_QUIRK_DISABLE_MECR BIT(4) /* Disable Memory error detection */
2015-09-01 09:00:13 +02:00
# define FLEXCAN_QUIRK_USE_OFF_TIMESTAMP BIT(5) /* Use timestamp based offloading */
2017-09-15 07:03:58 +00:00
# define FLEXCAN_QUIRK_BROKEN_PERR_STATE BIT(6) /* No interrupt for error passive */
2018-04-25 16:50:39 +02:00
# define FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN BIT(7) /* default to BE register access */
2012-09-28 03:17:15 +00:00
2009-07-29 10:20:10 +02:00
/* Structure of the message buffer */
struct flexcan_mb {
u32 can_ctrl ;
u32 can_id ;
u32 data [ 2 ] ;
} ;
/* Structure of the hardware registers */
struct flexcan_regs {
u32 mcr ; /* 0x00 */
u32 ctrl ; /* 0x04 */
u32 timer ; /* 0x08 */
u32 _reserved1 ; /* 0x0c */
u32 rxgmask ; /* 0x10 */
u32 rx14mask ; /* 0x14 */
u32 rx15mask ; /* 0x18 */
u32 ecr ; /* 0x1c */
u32 esr ; /* 0x20 */
u32 imask2 ; /* 0x24 */
u32 imask1 ; /* 0x28 */
u32 iflag2 ; /* 0x2c */
u32 iflag1 ; /* 0x30 */
2015-08-27 16:01:27 +02:00
union { /* 0x34 */
u32 gfwr_mx28 ; /* MX28, MX53 */
u32 ctrl2 ; /* MX6, VF610 */
} ;
2012-06-28 16:21:35 +08:00
u32 esr2 ; /* 0x38 */
u32 imeur ; /* 0x3c */
u32 lrfr ; /* 0x40 */
u32 crcr ; /* 0x44 */
u32 rxfgmask ; /* 0x48 */
u32 rxfir ; /* 0x4c */
2014-07-15 14:56:21 +02:00
u32 _reserved3 [ 12 ] ; /* 0x50 */
2015-08-25 10:39:19 +02:00
struct flexcan_mb mb [ 64 ] ; /* 0x80 */
2014-09-17 12:50:48 +02:00
/* FIFO-mode:
* MB
* 0x080 . . .0 x08f 0 RX message buffer
* 0x090 . . .0 x0df 1 - 5 reserverd
* 0x0e0 . . .0 x0ff 6 - 7 8 entry ID table
* ( mx25 , mx28 , mx35 , mx53 )
* 0x0e0 . . .0 x2df 6 - 7. .37 8. .128 entry ID table
2015-08-06 14:53:57 +02:00
* size conf ' ed via ctrl2 : : RFFN
2014-09-17 12:50:48 +02:00
* ( mx6 , vf610 )
*/
2015-08-27 16:01:27 +02:00
u32 _reserved4 [ 256 ] ; /* 0x480 */
u32 rximr [ 64 ] ; /* 0x880 */
u32 _reserved5 [ 24 ] ; /* 0x980 */
u32 gfwr_mx6 ; /* 0x9e0 - MX6 */
u32 _reserved6 [ 63 ] ; /* 0x9e4 */
2014-07-15 14:56:21 +02:00
u32 mecr ; /* 0xae0 */
u32 erriar ; /* 0xae4 */
u32 erridpr ; /* 0xae8 */
u32 errippr ; /* 0xaec */
u32 rerrar ; /* 0xaf0 */
u32 rerrdr ; /* 0xaf4 */
u32 rerrsynr ; /* 0xaf8 */
u32 errsr ; /* 0xafc */
2009-07-29 10:20:10 +02:00
} ;
2012-06-28 16:21:35 +08:00
struct flexcan_devtype_data {
2015-05-08 15:22:36 +02:00
u32 quirks ; /* quirks needed for different IP cores */
2012-06-28 16:21:35 +08:00
} ;
2009-07-29 10:20:10 +02:00
struct flexcan_priv {
struct can_priv can ;
2015-05-10 15:26:58 +02:00
struct can_rx_offload offload ;
2009-07-29 10:20:10 +02:00
2015-05-08 09:32:58 +02:00
struct flexcan_regs __iomem * regs ;
2015-07-12 00:47:47 +02:00
struct flexcan_mb __iomem * tx_mb_reserved ;
2009-07-29 10:20:10 +02:00
u32 reg_ctrl_default ;
2015-08-04 13:46:10 +02:00
u32 reg_imask1_default ;
2015-09-01 09:00:13 +02:00
u32 reg_imask2_default ;
2009-07-29 10:20:10 +02:00
2012-07-17 16:14:34 +02:00
struct clk * clk_ipg ;
struct clk * clk_per ;
2012-07-13 14:52:48 +02:00
const struct flexcan_devtype_data * devtype_data ;
2013-06-10 23:12:57 -03:00
struct regulator * reg_xceiver ;
2017-11-24 18:52:08 +05:30
/* Read and Write APIs */
u32 ( * read ) ( void __iomem * addr ) ;
void ( * write ) ( u32 val , void __iomem * addr ) ;
2012-06-28 16:21:35 +08:00
} ;
2016-07-04 14:45:44 +02:00
static const struct flexcan_devtype_data fsl_p1010_devtype_data = {
2018-04-25 16:50:39 +02:00
. quirks = FLEXCAN_QUIRK_BROKEN_WERR_STATE |
FLEXCAN_QUIRK_BROKEN_PERR_STATE |
FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN ,
} ;
static const struct flexcan_devtype_data fsl_imx25_devtype_data = {
2017-09-15 07:09:37 +00:00
. quirks = FLEXCAN_QUIRK_BROKEN_WERR_STATE |
FLEXCAN_QUIRK_BROKEN_PERR_STATE ,
2012-06-28 16:21:35 +08:00
} ;
2015-08-06 14:53:57 +02:00
2017-09-15 07:08:23 +00:00
static const struct flexcan_devtype_data fsl_imx28_devtype_data = {
. quirks = FLEXCAN_QUIRK_BROKEN_PERR_STATE ,
} ;
2015-08-06 14:53:57 +02:00
2016-07-04 14:45:44 +02:00
static const struct flexcan_devtype_data fsl_imx6q_devtype_data = {
2015-09-01 10:28:46 +02:00
. quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
2017-09-15 07:05:50 +00:00
FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | FLEXCAN_QUIRK_BROKEN_PERR_STATE ,
2009-07-29 10:20:10 +02:00
} ;
2015-08-06 14:53:57 +02:00
2016-07-04 14:45:44 +02:00
static const struct flexcan_devtype_data fsl_vf610_devtype_data = {
2015-09-01 08:57:55 +02:00
. quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
2017-11-27 09:18:21 +01:00
FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_OFF_TIMESTAMP |
FLEXCAN_QUIRK_BROKEN_PERR_STATE ,
2014-07-15 14:56:21 +02:00
} ;
2009-07-29 10:20:10 +02:00
2017-11-24 18:52:09 +05:30
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 ,
} ;
2012-07-16 12:58:31 +02:00
static const struct can_bittiming_const flexcan_bittiming_const = {
2009-07-29 10:20:10 +02:00
. name = DRV_NAME ,
. tseg1_min = 4 ,
. tseg1_max = 16 ,
. tseg2_min = 2 ,
. tseg2_max = 8 ,
. sjw_max = 4 ,
. brp_min = 1 ,
. brp_max = 256 ,
. brp_inc = 1 ,
} ;
2017-11-24 18:52:08 +05:30
/* 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 .
2011-08-16 17:32:20 +00:00
*/
2017-11-24 18:52:08 +05:30
static inline u32 flexcan_read_be ( void __iomem * addr )
2011-08-16 17:32:20 +00:00
{
2017-11-24 18:52:08 +05:30
return ioread32be ( addr ) ;
2011-08-16 17:32:20 +00:00
}
2017-11-24 18:52:08 +05:30
static inline void flexcan_write_be ( u32 val , void __iomem * addr )
2011-08-16 17:32:20 +00:00
{
2017-11-24 18:52:08 +05:30
iowrite32be ( val , addr ) ;
2011-08-16 17:32:20 +00:00
}
2017-11-24 18:52:08 +05:30
static inline u32 flexcan_read_le ( void __iomem * addr )
2011-08-16 17:32:20 +00:00
{
2017-11-24 18:52:08 +05:30
return ioread32 ( addr ) ;
2011-08-16 17:32:20 +00:00
}
2017-11-24 18:52:08 +05:30
static inline void flexcan_write_le ( u32 val , void __iomem * addr )
2011-08-16 17:32:20 +00:00
{
2017-11-24 18:52:08 +05:30
iowrite32 ( val , addr ) ;
2011-08-16 17:32:20 +00:00
}
2017-09-15 07:03:58 +00:00
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 ) ;
2017-11-24 18:52:08 +05:30
priv - > write ( reg_ctrl , & regs - > ctrl ) ;
2017-09-15 07:03:58 +00:00
}
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 ) ;
2017-11-24 18:52:08 +05:30
priv - > write ( reg_ctrl , & regs - > ctrl ) ;
2017-09-15 07:03:58 +00:00
}
2014-02-28 17:18:27 +01:00
static inline int flexcan_transceiver_enable ( const struct flexcan_priv * priv )
{
if ( ! priv - > reg_xceiver )
return 0 ;
return regulator_enable ( priv - > reg_xceiver ) ;
}
static inline int flexcan_transceiver_disable ( const struct flexcan_priv * priv )
{
if ( ! priv - > reg_xceiver )
return 0 ;
return regulator_disable ( priv - > reg_xceiver ) ;
}
2014-02-28 15:30:18 +01:00
static int flexcan_chip_enable ( struct flexcan_priv * priv )
2009-07-29 10:20:10 +02:00
{
2015-05-08 09:32:58 +02:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2014-02-28 15:30:18 +01:00
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10 ;
2009-07-29 10:20:10 +02:00
u32 reg ;
2017-11-24 18:52:08 +05:30
reg = priv - > read ( & regs - > mcr ) ;
2009-07-29 10:20:10 +02:00
reg & = ~ FLEXCAN_MCR_MDIS ;
2017-11-24 18:52:08 +05:30
priv - > write ( reg , & regs - > mcr ) ;
2009-07-29 10:20:10 +02:00
2017-11-24 18:52:08 +05:30
while ( timeout - - & & ( priv - > read ( & regs - > mcr ) & FLEXCAN_MCR_LPM_ACK ) )
2014-08-27 12:02:16 +02:00
udelay ( 10 ) ;
2014-02-28 15:30:18 +01:00
2017-11-24 18:52:08 +05:30
if ( priv - > read ( & regs - > mcr ) & FLEXCAN_MCR_LPM_ACK )
2014-02-28 15:30:18 +01:00
return - ETIMEDOUT ;
return 0 ;
2009-07-29 10:20:10 +02:00
}
2014-02-28 15:30:18 +01:00
static int flexcan_chip_disable ( struct flexcan_priv * priv )
2009-07-29 10:20:10 +02:00
{
2015-05-08 09:32:58 +02:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2014-02-28 15:30:18 +01:00
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10 ;
2009-07-29 10:20:10 +02:00
u32 reg ;
2017-11-24 18:52:08 +05:30
reg = priv - > read ( & regs - > mcr ) ;
2009-07-29 10:20:10 +02:00
reg | = FLEXCAN_MCR_MDIS ;
2017-11-24 18:52:08 +05:30
priv - > write ( reg , & regs - > mcr ) ;
2014-02-28 15:30:18 +01:00
2017-11-24 18:52:08 +05:30
while ( timeout - - & & ! ( priv - > read ( & regs - > mcr ) & FLEXCAN_MCR_LPM_ACK ) )
2014-08-27 12:02:16 +02:00
udelay ( 10 ) ;
2014-02-28 15:30:18 +01:00
2017-11-24 18:52:08 +05:30
if ( ! ( priv - > read ( & regs - > mcr ) & FLEXCAN_MCR_LPM_ACK ) )
2014-02-28 15:30:18 +01:00
return - ETIMEDOUT ;
return 0 ;
2009-07-29 10:20:10 +02:00
}
2014-02-28 17:08:21 +01:00
static int flexcan_chip_freeze ( struct flexcan_priv * priv )
{
2015-05-08 09:32:58 +02:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2014-02-28 17:08:21 +01:00
unsigned int timeout = 1000 * 1000 * 10 / priv - > can . bittiming . bitrate ;
u32 reg ;
2017-11-24 18:52:08 +05:30
reg = priv - > read ( & regs - > mcr ) ;
2014-02-28 17:08:21 +01:00
reg | = FLEXCAN_MCR_HALT ;
2017-11-24 18:52:08 +05:30
priv - > write ( reg , & regs - > mcr ) ;
2014-02-28 17:08:21 +01:00
2017-11-24 18:52:08 +05:30
while ( timeout - - & & ! ( priv - > read ( & regs - > mcr ) & FLEXCAN_MCR_FRZ_ACK ) )
2014-08-27 12:02:16 +02:00
udelay ( 100 ) ;
2014-02-28 17:08:21 +01:00
2017-11-24 18:52:08 +05:30
if ( ! ( priv - > read ( & regs - > mcr ) & FLEXCAN_MCR_FRZ_ACK ) )
2014-02-28 17:08:21 +01:00
return - ETIMEDOUT ;
return 0 ;
}
static int flexcan_chip_unfreeze ( struct flexcan_priv * priv )
{
2015-05-08 09:32:58 +02:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2014-02-28 17:08:21 +01:00
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10 ;
u32 reg ;
2017-11-24 18:52:08 +05:30
reg = priv - > read ( & regs - > mcr ) ;
2014-02-28 17:08:21 +01:00
reg & = ~ FLEXCAN_MCR_HALT ;
2017-11-24 18:52:08 +05:30
priv - > write ( reg , & regs - > mcr ) ;
2014-02-28 17:08:21 +01:00
2017-11-24 18:52:08 +05:30
while ( timeout - - & & ( priv - > read ( & regs - > mcr ) & FLEXCAN_MCR_FRZ_ACK ) )
2014-08-27 12:02:16 +02:00
udelay ( 10 ) ;
2014-02-28 17:08:21 +01:00
2017-11-24 18:52:08 +05:30
if ( priv - > read ( & regs - > mcr ) & FLEXCAN_MCR_FRZ_ACK )
2014-02-28 17:08:21 +01:00
return - ETIMEDOUT ;
return 0 ;
}
2014-02-28 15:16:59 +01:00
static int flexcan_chip_softreset ( struct flexcan_priv * priv )
{
2015-05-08 09:32:58 +02:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2014-02-28 15:16:59 +01:00
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10 ;
2017-11-24 18:52:08 +05:30
priv - > write ( FLEXCAN_MCR_SOFTRST , & regs - > mcr ) ;
while ( timeout - - & & ( priv - > read ( & regs - > mcr ) & FLEXCAN_MCR_SOFTRST ) )
2014-08-27 12:02:16 +02:00
udelay ( 10 ) ;
2014-02-28 15:16:59 +01:00
2017-11-24 18:52:08 +05:30
if ( priv - > read ( & regs - > mcr ) & FLEXCAN_MCR_SOFTRST )
2014-02-28 15:16:59 +01:00
return - ETIMEDOUT ;
return 0 ;
}
2014-07-15 14:56:20 +02:00
static int __flexcan_get_berr_counter ( const struct net_device * dev ,
struct can_berr_counter * bec )
2009-07-29 10:20:10 +02:00
{
const struct flexcan_priv * priv = netdev_priv ( dev ) ;
2015-05-08 09:32:58 +02:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2017-11-24 18:52:08 +05:30
u32 reg = priv - > read ( & regs - > ecr ) ;
2009-07-29 10:20:10 +02:00
bec - > txerr = ( reg > > 0 ) & 0xff ;
bec - > rxerr = ( reg > > 8 ) & 0xff ;
return 0 ;
}
2014-07-15 14:56:20 +02:00
static int flexcan_get_berr_counter ( const struct net_device * dev ,
struct can_berr_counter * bec )
{
const struct flexcan_priv * priv = netdev_priv ( dev ) ;
int err ;
err = clk_prepare_enable ( priv - > clk_ipg ) ;
if ( err )
return err ;
err = clk_prepare_enable ( priv - > clk_per ) ;
if ( err )
goto out_disable_ipg ;
err = __flexcan_get_berr_counter ( dev , bec ) ;
clk_disable_unprepare ( priv - > clk_per ) ;
out_disable_ipg :
clk_disable_unprepare ( priv - > clk_ipg ) ;
return err ;
}
2018-04-26 23:13:38 +02:00
static netdev_tx_t flexcan_start_xmit ( struct sk_buff * skb , struct net_device * dev )
2009-07-29 10:20:10 +02:00
{
const struct flexcan_priv * priv = netdev_priv ( dev ) ;
2018-11-09 15:01:50 +01:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2009-07-29 10:20:10 +02:00
struct can_frame * cf = ( struct can_frame * ) skb - > data ;
u32 can_id ;
2015-08-06 14:53:57 +02:00
u32 data ;
2014-09-23 11:18:11 +02:00
u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | ( cf - > can_dlc < < 16 ) ;
2009-07-29 10:20:10 +02:00
if ( can_dropped_invalid_skb ( dev , skb ) )
return NETDEV_TX_OK ;
netif_stop_queue ( dev ) ;
if ( cf - > can_id & CAN_EFF_FLAG ) {
can_id = cf - > can_id & CAN_EFF_MASK ;
ctrl | = FLEXCAN_MB_CNT_IDE | FLEXCAN_MB_CNT_SRR ;
} else {
can_id = ( cf - > can_id & CAN_SFF_MASK ) < < 18 ;
}
if ( cf - > can_id & CAN_RTR_FLAG )
ctrl | = FLEXCAN_MB_CNT_RTR ;
if ( cf - > can_dlc > 0 ) {
2015-08-06 14:53:57 +02:00
data = be32_to_cpup ( ( __be32 * ) & cf - > data [ 0 ] ) ;
2018-11-09 15:01:50 +01:00
priv - > write ( data , & regs - > mb [ FLEXCAN_TX_MB ] . data [ 0 ] ) ;
2009-07-29 10:20:10 +02:00
}
2018-01-02 10:44:18 +07:00
if ( cf - > can_dlc > 4 ) {
2015-08-06 14:53:57 +02:00
data = be32_to_cpup ( ( __be32 * ) & cf - > data [ 4 ] ) ;
2018-11-09 15:01:50 +01:00
priv - > write ( data , & regs - > mb [ FLEXCAN_TX_MB ] . data [ 1 ] ) ;
2009-07-29 10:20:10 +02:00
}
2011-11-01 11:18:03 +13:00
can_put_echo_skb ( skb , dev , 0 ) ;
2018-11-09 15:01:50 +01:00
priv - > write ( can_id , & regs - > mb [ FLEXCAN_TX_MB ] . can_id ) ;
priv - > write ( ctrl , & regs - > mb [ FLEXCAN_TX_MB ] . can_ctrl ) ;
2009-07-29 10:20:10 +02:00
2014-09-03 16:47:22 +02:00
/* Errata ERR005829 step8:
* Write twice INACTIVE ( 0x8 ) code to first MB .
*/
2017-11-24 18:52:08 +05:30
priv - > write ( FLEXCAN_MB_CODE_TX_INACTIVE ,
2015-07-12 00:47:47 +02:00
& priv - > tx_mb_reserved - > can_ctrl ) ;
2017-11-24 18:52:08 +05:30
priv - > write ( FLEXCAN_MB_CODE_TX_INACTIVE ,
2015-07-12 00:47:47 +02:00
& priv - > tx_mb_reserved - > can_ctrl ) ;
2014-09-03 16:47:22 +02:00
2009-07-29 10:20:10 +02:00
return NETDEV_TX_OK ;
}
2015-05-10 15:26:58 +02:00
static void flexcan_irq_bus_err ( struct net_device * dev , u32 reg_esr )
2009-07-29 10:20:10 +02:00
{
struct flexcan_priv * priv = netdev_priv ( dev ) ;
2018-09-18 11:40:41 +02:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2017-01-18 11:38:26 +01:00
struct sk_buff * skb ;
struct can_frame * cf ;
2017-01-17 17:33:46 +01:00
bool rx_errors = false , tx_errors = false ;
2018-09-18 11:40:41 +02:00
u32 timestamp ;
timestamp = priv - > read ( & regs - > timer ) < < 16 ;
2009-07-29 10:20:10 +02:00
2017-01-18 11:38:26 +01:00
skb = alloc_can_err_skb ( dev , & cf ) ;
if ( unlikely ( ! skb ) )
2015-05-10 15:26:58 +02:00
return ;
2017-01-18 11:38:26 +01:00
2009-07-29 10:20:10 +02:00
cf - > can_id | = CAN_ERR_PROT | CAN_ERR_BUSERROR ;
if ( reg_esr & FLEXCAN_ESR_BIT1_ERR ) {
2012-02-01 11:02:05 +01:00
netdev_dbg ( dev , " BIT1_ERR irq \n " ) ;
2009-07-29 10:20:10 +02:00
cf - > data [ 2 ] | = CAN_ERR_PROT_BIT1 ;
2017-01-17 17:33:46 +01:00
tx_errors = true ;
2009-07-29 10:20:10 +02:00
}
if ( reg_esr & FLEXCAN_ESR_BIT0_ERR ) {
2012-02-01 11:02:05 +01:00
netdev_dbg ( dev , " BIT0_ERR irq \n " ) ;
2009-07-29 10:20:10 +02:00
cf - > data [ 2 ] | = CAN_ERR_PROT_BIT0 ;
2017-01-17 17:33:46 +01:00
tx_errors = true ;
2009-07-29 10:20:10 +02:00
}
if ( reg_esr & FLEXCAN_ESR_ACK_ERR ) {
2012-02-01 11:02:05 +01:00
netdev_dbg ( dev , " ACK_ERR irq \n " ) ;
2009-07-29 10:20:10 +02:00
cf - > can_id | = CAN_ERR_ACK ;
2015-11-21 18:41:20 +01:00
cf - > data [ 3 ] = CAN_ERR_PROT_LOC_ACK ;
2017-01-17 17:33:46 +01:00
tx_errors = true ;
2009-07-29 10:20:10 +02:00
}
if ( reg_esr & FLEXCAN_ESR_CRC_ERR ) {
2012-02-01 11:02:05 +01:00
netdev_dbg ( dev , " CRC_ERR irq \n " ) ;
2009-07-29 10:20:10 +02:00
cf - > data [ 2 ] | = CAN_ERR_PROT_BIT ;
2015-11-21 18:41:20 +01:00
cf - > data [ 3 ] = CAN_ERR_PROT_LOC_CRC_SEQ ;
2017-01-17 17:33:46 +01:00
rx_errors = true ;
2009-07-29 10:20:10 +02:00
}
if ( reg_esr & FLEXCAN_ESR_FRM_ERR ) {
2012-02-01 11:02:05 +01:00
netdev_dbg ( dev , " FRM_ERR irq \n " ) ;
2009-07-29 10:20:10 +02:00
cf - > data [ 2 ] | = CAN_ERR_PROT_FORM ;
2017-01-17 17:33:46 +01:00
rx_errors = true ;
2009-07-29 10:20:10 +02:00
}
if ( reg_esr & FLEXCAN_ESR_STF_ERR ) {
2012-02-01 11:02:05 +01:00
netdev_dbg ( dev , " STF_ERR irq \n " ) ;
2009-07-29 10:20:10 +02:00
cf - > data [ 2 ] | = CAN_ERR_PROT_STUFF ;
2017-01-17 17:33:46 +01:00
rx_errors = true ;
2009-07-29 10:20:10 +02:00
}
priv - > can . can_stats . bus_error + + ;
if ( rx_errors )
dev - > stats . rx_errors + + ;
if ( tx_errors )
dev - > stats . tx_errors + + ;
2018-09-18 11:40:41 +02:00
can_rx_offload_queue_sorted ( & priv - > offload , skb , timestamp ) ;
2009-07-29 10:20:10 +02:00
}
2015-05-10 15:26:58 +02:00
static void flexcan_irq_state ( struct net_device * dev , u32 reg_esr )
2009-07-29 10:20:10 +02:00
{
struct flexcan_priv * priv = netdev_priv ( dev ) ;
2018-09-18 11:40:41 +02:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2009-07-29 10:20:10 +02:00
struct sk_buff * skb ;
struct can_frame * cf ;
2017-01-18 11:25:41 +01:00
enum can_state new_state , rx_state , tx_state ;
2009-07-29 10:20:10 +02:00
int flt ;
2014-12-03 17:54:15 +00:00
struct can_berr_counter bec ;
2018-09-18 11:40:41 +02:00
u32 timestamp ;
timestamp = priv - > read ( & regs - > timer ) < < 16 ;
2009-07-29 10:20:10 +02:00
flt = reg_esr & FLEXCAN_ESR_FLT_CONF_MASK ;
if ( likely ( flt = = FLEXCAN_ESR_FLT_CONF_ACTIVE ) ) {
2014-12-03 17:54:15 +00:00
tx_state = unlikely ( reg_esr & FLEXCAN_ESR_TX_WRN ) ?
2015-08-06 14:53:57 +02:00
CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE ;
2014-12-03 17:54:15 +00:00
rx_state = unlikely ( reg_esr & FLEXCAN_ESR_RX_WRN ) ?
2015-08-06 14:53:57 +02:00
CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE ;
2014-12-03 17:54:15 +00:00
new_state = max ( tx_state , rx_state ) ;
2015-03-17 13:03:09 +00:00
} else {
2014-12-03 17:54:15 +00:00
__flexcan_get_berr_counter ( dev , & bec ) ;
2015-03-17 13:03:09 +00:00
new_state = flt = = FLEXCAN_ESR_FLT_CONF_PASSIVE ?
2015-08-06 14:53:57 +02:00
CAN_STATE_ERROR_PASSIVE : CAN_STATE_BUS_OFF ;
2014-12-03 17:54:15 +00:00
rx_state = bec . rxerr > = bec . txerr ? new_state : 0 ;
tx_state = bec . rxerr < = bec . txerr ? new_state : 0 ;
}
2009-07-29 10:20:10 +02:00
/* state hasn't changed */
if ( likely ( new_state = = priv - > can . state ) )
2015-05-10 15:26:58 +02:00
return ;
2009-07-29 10:20:10 +02:00
skb = alloc_can_err_skb ( dev , & cf ) ;
if ( unlikely ( ! skb ) )
2015-05-10 15:26:58 +02:00
return ;
2009-07-29 10:20:10 +02:00
2014-12-03 17:54:15 +00:00
can_change_state ( dev , cf , tx_state , rx_state ) ;
if ( unlikely ( new_state = = CAN_STATE_BUS_OFF ) )
can_bus_off ( dev ) ;
2018-09-18 11:40:41 +02:00
can_rx_offload_queue_sorted ( & priv - > offload , skb , timestamp ) ;
2015-05-10 15:26:58 +02:00
}
2009-07-29 10:20:10 +02:00
2015-05-10 15:26:58 +02:00
static inline struct flexcan_priv * rx_offload_to_priv ( struct can_rx_offload * offload )
{
return container_of ( offload , struct flexcan_priv , offload ) ;
2009-07-29 10:20:10 +02:00
}
2015-05-10 15:26:58 +02:00
static unsigned int flexcan_mailbox_read ( struct can_rx_offload * offload ,
struct can_frame * cf ,
u32 * timestamp , unsigned int n )
2009-07-29 10:20:10 +02:00
{
2015-05-10 15:26:58 +02:00
struct flexcan_priv * priv = rx_offload_to_priv ( offload ) ;
2015-05-08 09:32:58 +02:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2015-05-10 15:26:58 +02:00
struct flexcan_mb __iomem * mb = & regs - > mb [ n ] ;
u32 reg_ctrl , reg_id , reg_iflag1 ;
2015-09-01 09:00:13 +02:00
if ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP ) {
u32 code ;
do {
2017-11-24 18:52:08 +05:30
reg_ctrl = priv - > read ( & mb - > can_ctrl ) ;
2015-09-01 09:00:13 +02:00
} while ( reg_ctrl & FLEXCAN_MB_CODE_RX_BUSY_BIT ) ;
/* is this MB empty? */
code = reg_ctrl & FLEXCAN_MB_CODE_MASK ;
if ( ( code ! = FLEXCAN_MB_CODE_RX_FULL ) & &
( code ! = FLEXCAN_MB_CODE_RX_OVERRUN ) )
return 0 ;
if ( code = = FLEXCAN_MB_CODE_RX_OVERRUN ) {
/* This MB was overrun, we lost data */
offload - > dev - > stats . rx_over_errors + + ;
offload - > dev - > stats . rx_errors + + ;
}
} else {
2017-11-24 18:52:08 +05:30
reg_iflag1 = priv - > read ( & regs - > iflag1 ) ;
2015-09-01 09:00:13 +02:00
if ( ! ( reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE ) )
return 0 ;
2017-11-24 18:52:08 +05:30
reg_ctrl = priv - > read ( & mb - > can_ctrl ) ;
2015-09-01 09:00:13 +02:00
}
2009-07-29 10:20:10 +02:00
2015-05-10 15:26:58 +02:00
/* increase timstamp to full 32 bit */
* timestamp = reg_ctrl < < 16 ;
2017-11-24 18:52:08 +05:30
reg_id = priv - > read ( & mb - > can_id ) ;
2009-07-29 10:20:10 +02:00
if ( reg_ctrl & FLEXCAN_MB_CNT_IDE )
cf - > can_id = ( ( reg_id > > 0 ) & CAN_EFF_MASK ) | CAN_EFF_FLAG ;
else
cf - > can_id = ( reg_id > > 18 ) & CAN_SFF_MASK ;
if ( reg_ctrl & FLEXCAN_MB_CNT_RTR )
cf - > can_id | = CAN_RTR_FLAG ;
cf - > can_dlc = get_can_dlc ( ( reg_ctrl > > 16 ) & 0xf ) ;
2017-11-24 18:52:08 +05:30
* ( __be32 * ) ( cf - > data + 0 ) = cpu_to_be32 ( priv - > read ( & mb - > data [ 0 ] ) ) ;
* ( __be32 * ) ( cf - > data + 4 ) = cpu_to_be32 ( priv - > read ( & mb - > data [ 1 ] ) ) ;
2009-07-29 10:20:10 +02:00
/* mark as read */
2015-09-01 09:00:13 +02:00
if ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP ) {
/* Clear IRQ */
if ( n < 32 )
2017-11-24 18:52:08 +05:30
priv - > write ( BIT ( n ) , & regs - > iflag1 ) ;
2015-09-01 09:00:13 +02:00
else
2017-11-24 18:52:08 +05:30
priv - > write ( BIT ( n - 32 ) , & regs - > iflag2 ) ;
2015-09-01 09:00:13 +02:00
} else {
2017-11-24 18:52:08 +05:30
priv - > write ( FLEXCAN_IFLAG_RX_FIFO_AVAILABLE , & regs - > iflag1 ) ;
2015-09-01 09:00:13 +02:00
}
2012-12-18 18:50:58 +01:00
2018-08-01 19:36:46 +05:30
/* Read the Free Running Timer. It is optional but recommended
* to unlock Mailbox as soon as possible and make it available
* for reception .
*/
priv - > read ( & regs - > timer ) ;
2009-07-29 10:20:10 +02:00
return 1 ;
}
2015-09-01 09:00:13 +02:00
static inline u64 flexcan_read_reg_iflag_rx ( struct flexcan_priv * priv )
{
struct flexcan_regs __iomem * regs = priv - > regs ;
u32 iflag1 , iflag2 ;
2018-10-11 17:01:25 +02:00
iflag2 = priv - > read ( & regs - > iflag2 ) & priv - > reg_imask2_default &
2018-11-09 15:01:50 +01:00
~ FLEXCAN_IFLAG_MB ( FLEXCAN_TX_MB ) ;
2018-10-11 17:01:25 +02:00
iflag1 = priv - > read ( & regs - > iflag1 ) & priv - > reg_imask1_default ;
2015-09-01 09:00:13 +02:00
return ( u64 ) iflag2 < < 32 | iflag1 ;
}
2009-07-29 10:20:10 +02:00
static irqreturn_t flexcan_irq ( int irq , void * dev_id )
{
struct net_device * dev = dev_id ;
struct net_device_stats * stats = & dev - > stats ;
struct flexcan_priv * priv = netdev_priv ( dev ) ;
2015-05-08 09:32:58 +02:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2017-01-18 11:45:14 +01:00
irqreturn_t handled = IRQ_NONE ;
2018-10-11 17:01:25 +02:00
u32 reg_iflag2 , reg_esr ;
2017-09-15 07:03:58 +00:00
enum can_state last_state = priv - > can . state ;
2009-07-29 10:20:10 +02:00
2015-05-10 15:26:58 +02:00
/* reception interrupt */
2015-09-01 09:00:13 +02:00
if ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP ) {
u64 reg_iflag ;
int ret ;
while ( ( reg_iflag = flexcan_read_reg_iflag_rx ( priv ) ) ) {
handled = IRQ_HANDLED ;
ret = can_rx_offload_irq_offload_timestamp ( & priv - > offload ,
reg_iflag ) ;
if ( ! ret )
break ;
}
} else {
2018-10-11 17:01:25 +02:00
u32 reg_iflag1 ;
reg_iflag1 = priv - > read ( & regs - > iflag1 ) ;
2015-09-01 09:00:13 +02:00
if ( reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE ) {
handled = IRQ_HANDLED ;
can_rx_offload_irq_offload_fifo ( & priv - > offload ) ;
}
2009-07-29 10:20:10 +02:00
2015-09-01 09:00:13 +02:00
/* FIFO overflow interrupt */
if ( reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_OVERFLOW ) {
handled = IRQ_HANDLED ;
2017-11-24 18:52:08 +05:30
priv - > write ( FLEXCAN_IFLAG_RX_FIFO_OVERFLOW ,
& regs - > iflag1 ) ;
2015-09-01 09:00:13 +02:00
dev - > stats . rx_over_errors + + ;
dev - > stats . rx_errors + + ;
}
2009-07-29 10:20:10 +02:00
}
2018-10-11 17:01:25 +02:00
reg_iflag2 = priv - > read ( & regs - > iflag2 ) ;
2009-07-29 10:20:10 +02:00
/* transmission complete interrupt */
2018-11-09 15:01:50 +01:00
if ( reg_iflag2 & FLEXCAN_IFLAG_MB ( FLEXCAN_TX_MB ) ) {
2018-09-18 11:40:39 +02:00
u32 reg_ctrl = priv - > read ( & regs - > mb [ FLEXCAN_TX_MB ] . can_ctrl ) ;
2017-01-18 11:45:14 +01:00
handled = IRQ_HANDLED ;
2018-09-18 11:40:39 +02:00
stats - > tx_bytes + = can_rx_offload_get_echo_skb ( & priv - > offload ,
0 , reg_ctrl < < 16 ) ;
2009-07-29 10:20:10 +02:00
stats - > tx_packets + + ;
2012-12-18 18:50:58 +01:00
can_led_event ( dev , CAN_LED_EVENT_TX ) ;
2015-08-06 14:53:57 +02:00
/* after sending a RTR frame MB is in RX mode */
2017-11-24 18:52:08 +05:30
priv - > write ( FLEXCAN_MB_CODE_TX_INACTIVE ,
2018-11-09 15:01:50 +01:00
& regs - > mb [ FLEXCAN_TX_MB ] . can_ctrl ) ;
priv - > write ( FLEXCAN_IFLAG_MB ( FLEXCAN_TX_MB ) , & regs - > iflag2 ) ;
2009-07-29 10:20:10 +02:00
netif_wake_queue ( dev ) ;
}
2017-11-24 18:52:08 +05:30
reg_esr = priv - > read ( & regs - > esr ) ;
2015-05-10 15:26:58 +02:00
2017-01-18 11:45:14 +01:00
/* ACK all bus error and state change IRQ sources */
if ( reg_esr & FLEXCAN_ESR_ALL_INT ) {
handled = IRQ_HANDLED ;
2017-11-24 18:52:08 +05:30
priv - > write ( reg_esr & FLEXCAN_ESR_ALL_INT , & regs - > esr ) ;
2017-01-18 11:45:14 +01:00
}
2017-09-15 06:59:15 +00:00
/* state change interrupt or broken error state quirk fix is enabled */
if ( ( reg_esr & FLEXCAN_ESR_ERR_STATE ) | |
2017-09-15 07:03:58 +00:00
( priv - > devtype_data - > quirks & ( FLEXCAN_QUIRK_BROKEN_WERR_STATE |
FLEXCAN_QUIRK_BROKEN_PERR_STATE ) ) )
2015-05-10 15:26:58 +02:00
flexcan_irq_state ( dev , reg_esr ) ;
/* bus error IRQ - handle if bus error reporting is activated */
if ( ( reg_esr & FLEXCAN_ESR_ERR_BUS ) & &
( priv - > can . ctrlmode & CAN_CTRLMODE_BERR_REPORTING ) )
flexcan_irq_bus_err ( dev , reg_esr ) ;
2017-09-15 07:03:58 +00:00
/* availability of error interrupt among state transitions in case
* bus error reporting is de - activated and
* FLEXCAN_QUIRK_BROKEN_PERR_STATE is enabled :
* + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
* | + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + [ stopped / |
* | | | sleeping ] - +
* + - + - > active < - > warning < - > passive - > bus off - +
* ___________ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ _______________________________
* disabled ( 1 ) enabled disabled
*
* ( 1 ) : enabled if FLEXCAN_QUIRK_BROKEN_WERR_STATE is enabled
*/
if ( ( last_state ! = priv - > can . state ) & &
( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_BROKEN_PERR_STATE ) & &
! ( priv - > can . ctrlmode & CAN_CTRLMODE_BERR_REPORTING ) ) {
switch ( priv - > can . state ) {
case CAN_STATE_ERROR_ACTIVE :
if ( priv - > devtype_data - > quirks &
FLEXCAN_QUIRK_BROKEN_WERR_STATE )
flexcan_error_irq_enable ( priv ) ;
else
flexcan_error_irq_disable ( priv ) ;
break ;
case CAN_STATE_ERROR_WARNING :
flexcan_error_irq_enable ( priv ) ;
break ;
case CAN_STATE_ERROR_PASSIVE :
case CAN_STATE_BUS_OFF :
flexcan_error_irq_disable ( priv ) ;
break ;
default :
break ;
}
}
2017-01-18 11:45:14 +01:00
return handled ;
2009-07-29 10:20:10 +02:00
}
static void flexcan_set_bittiming ( struct net_device * dev )
{
const struct flexcan_priv * priv = netdev_priv ( dev ) ;
const struct can_bittiming * bt = & priv - > can . bittiming ;
2015-05-08 09:32:58 +02:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2009-07-29 10:20:10 +02:00
u32 reg ;
2017-11-24 18:52:08 +05:30
reg = priv - > read ( & regs - > ctrl ) ;
2009-07-29 10:20:10 +02:00
reg & = ~ ( FLEXCAN_CTRL_PRESDIV ( 0xff ) |
FLEXCAN_CTRL_RJW ( 0x3 ) |
FLEXCAN_CTRL_PSEG1 ( 0x7 ) |
FLEXCAN_CTRL_PSEG2 ( 0x7 ) |
FLEXCAN_CTRL_PROPSEG ( 0x7 ) |
FLEXCAN_CTRL_LPB |
FLEXCAN_CTRL_SMP |
FLEXCAN_CTRL_LOM ) ;
reg | = FLEXCAN_CTRL_PRESDIV ( bt - > brp - 1 ) |
FLEXCAN_CTRL_PSEG1 ( bt - > phase_seg1 - 1 ) |
FLEXCAN_CTRL_PSEG2 ( bt - > phase_seg2 - 1 ) |
FLEXCAN_CTRL_RJW ( bt - > sjw - 1 ) |
FLEXCAN_CTRL_PROPSEG ( bt - > prop_seg - 1 ) ;
if ( priv - > can . ctrlmode & CAN_CTRLMODE_LOOPBACK )
reg | = FLEXCAN_CTRL_LPB ;
if ( priv - > can . ctrlmode & CAN_CTRLMODE_LISTENONLY )
reg | = FLEXCAN_CTRL_LOM ;
if ( priv - > can . ctrlmode & CAN_CTRLMODE_3_SAMPLES )
reg | = FLEXCAN_CTRL_SMP ;
2015-08-07 17:16:03 +02:00
netdev_dbg ( dev , " writing ctrl=0x%08x \n " , reg ) ;
2017-11-24 18:52:08 +05:30
priv - > write ( reg , & regs - > ctrl ) ;
2009-07-29 10:20:10 +02:00
/* print chip status */
2012-02-01 11:02:05 +01:00
netdev_dbg ( dev , " %s: mcr=0x%08x ctrl=0x%08x \n " , __func__ ,
2017-11-24 18:52:08 +05:30
priv - > read ( & regs - > mcr ) , priv - > read ( & regs - > ctrl ) ) ;
2009-07-29 10:20:10 +02:00
}
2015-08-06 14:53:57 +02:00
/* flexcan_chip_start
2009-07-29 10:20:10 +02:00
*
* this functions is entered with clocks enabled
*
*/
static int flexcan_chip_start ( struct net_device * dev )
{
struct flexcan_priv * priv = netdev_priv ( dev ) ;
2015-05-08 09:32:58 +02:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2014-09-23 11:03:01 +02:00
u32 reg_mcr , reg_ctrl , reg_ctrl2 , reg_mecr ;
2014-09-23 12:09:27 -04:00
int err , i ;
2009-07-29 10:20:10 +02:00
/* enable module */
2014-02-28 15:30:18 +01:00
err = flexcan_chip_enable ( priv ) ;
if ( err )
return err ;
2009-07-29 10:20:10 +02:00
/* soft reset */
2014-02-28 15:16:59 +01:00
err = flexcan_chip_softreset ( priv ) ;
if ( err )
2014-02-28 17:08:21 +01:00
goto out_chip_disable ;
2009-07-29 10:20:10 +02:00
flexcan_set_bittiming ( dev ) ;
2015-08-06 14:53:57 +02:00
/* MCR
2009-07-29 10:20:10 +02:00
*
* enable freeze
* enable fifo
* halt now
* only supervisor access
* enable warning int
2011-11-01 11:18:03 +13:00
* disable local echo
2015-08-31 21:03:29 +02:00
* enable individual RX masking
2015-08-31 21:32:34 +02:00
* choose format C
* set max mailbox number
2009-07-29 10:20:10 +02:00
*/
2017-11-24 18:52:08 +05:30
reg_mcr = priv - > read ( & regs - > mcr ) ;
2013-10-04 10:52:36 +02:00
reg_mcr & = ~ FLEXCAN_MCR_MAXMB ( 0xff ) ;
2015-09-01 09:00:13 +02:00
reg_mcr | = FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT | FLEXCAN_MCR_SUPV |
FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_SRX_DIS | FLEXCAN_MCR_IRMQ |
2018-11-09 15:01:50 +01:00
FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_MAXMB ( FLEXCAN_TX_MB ) ;
2015-09-01 09:00:13 +02:00
2018-10-11 17:01:25 +02:00
if ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP )
2015-09-01 09:00:13 +02:00
reg_mcr & = ~ FLEXCAN_MCR_FEN ;
2018-10-11 17:01:25 +02:00
else
reg_mcr | = FLEXCAN_MCR_FEN ;
2012-02-01 11:02:05 +01:00
netdev_dbg ( dev , " %s: writing mcr=0x%08x " , __func__ , reg_mcr ) ;
2017-11-24 18:52:08 +05:30
priv - > write ( reg_mcr , & regs - > mcr ) ;
2009-07-29 10:20:10 +02:00
2015-08-06 14:53:57 +02:00
/* CTRL
2009-07-29 10:20:10 +02:00
*
* disable timer sync feature
*
* disable auto busoff recovery
* transmit lowest buffer first
*
* enable tx and rx warning interrupt
* enable bus off interrupt
* ( = = FLEXCAN_CTRL_ERR_STATE )
*/
2017-11-24 18:52:08 +05:30
reg_ctrl = priv - > read ( & regs - > ctrl ) ;
2009-07-29 10:20:10 +02:00
reg_ctrl & = ~ FLEXCAN_CTRL_TSYN ;
reg_ctrl | = FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF |
2012-09-28 03:17:15 +00:00
FLEXCAN_CTRL_ERR_STATE ;
2015-08-06 14:53:57 +02:00
/* enable the "error interrupt" (FLEXCAN_CTRL_ERR_MSK),
2012-09-28 03:17:15 +00:00
* on most Flexcan cores , too . Otherwise we don ' t get
* any error warning or passive interrupts .
*/
2017-09-15 07:01:23 +00:00
if ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_BROKEN_WERR_STATE | |
2012-09-28 03:17:15 +00:00
priv - > can . ctrlmode & CAN_CTRLMODE_BERR_REPORTING )
reg_ctrl | = FLEXCAN_CTRL_ERR_MSK ;
2014-08-12 10:47:21 +02:00
else
reg_ctrl & = ~ FLEXCAN_CTRL_ERR_MSK ;
2009-07-29 10:20:10 +02:00
/* save for later use */
priv - > reg_ctrl_default = reg_ctrl ;
2015-08-27 14:24:48 +02:00
/* leave interrupts disabled for now */
reg_ctrl & = ~ FLEXCAN_CTRL_ERR_ALL ;
2012-02-01 11:02:05 +01:00
netdev_dbg ( dev , " %s: writing ctrl=0x%08x " , __func__ , reg_ctrl ) ;
2017-11-24 18:52:08 +05:30
priv - > write ( reg_ctrl , & regs - > ctrl ) ;
2009-07-29 10:20:10 +02:00
2015-09-01 08:57:55 +02:00
if ( ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_ENABLE_EACEN_RRS ) ) {
2017-11-24 18:52:08 +05:30
reg_ctrl2 = priv - > read ( & regs - > ctrl2 ) ;
2015-09-01 08:57:55 +02:00
reg_ctrl2 | = FLEXCAN_CTRL2_EACEN | FLEXCAN_CTRL2_RRS ;
2017-11-24 18:52:08 +05:30
priv - > write ( reg_ctrl2 , & regs - > ctrl2 ) ;
2015-09-01 08:57:55 +02:00
}
2015-09-01 09:00:13 +02:00
if ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP ) {
2018-10-11 17:01:25 +02:00
for ( i = priv - > offload . mb_first ; i < = priv - > offload . mb_last ; i + + ) {
2017-11-24 18:52:08 +05:30
priv - > write ( FLEXCAN_MB_CODE_RX_EMPTY ,
& regs - > mb [ i ] . can_ctrl ) ;
2018-10-11 17:01:25 +02:00
}
} else {
/* clear and invalidate unused mailboxes first */
for ( i = FLEXCAN_TX_MB_RESERVED_OFF_FIFO ; i < = ARRAY_SIZE ( regs - > mb ) ; i + + ) {
priv - > write ( FLEXCAN_MB_CODE_RX_INACTIVE ,
& regs - > mb [ i ] . can_ctrl ) ;
}
2015-09-01 09:00:13 +02:00
}
2014-09-03 16:47:22 +02:00
/* Errata ERR005829: mark first TX mailbox as INACTIVE */
2017-11-24 18:52:08 +05:30
priv - > write ( FLEXCAN_MB_CODE_TX_INACTIVE ,
& priv - > tx_mb_reserved - > can_ctrl ) ;
2014-09-03 16:47:22 +02:00
2014-09-16 12:39:28 +02:00
/* mark TX mailbox as INACTIVE */
2017-11-24 18:52:08 +05:30
priv - > write ( FLEXCAN_MB_CODE_TX_INACTIVE ,
2018-11-09 15:01:50 +01:00
& regs - > mb [ FLEXCAN_TX_MB ] . can_ctrl ) ;
2013-10-04 10:52:36 +02:00
2009-07-29 10:20:10 +02:00
/* acceptance mask/acceptance code (accept everything) */
2017-11-24 18:52:08 +05:30
priv - > write ( 0x0 , & regs - > rxgmask ) ;
priv - > write ( 0x0 , & regs - > rx14mask ) ;
priv - > write ( 0x0 , & regs - > rx15mask ) ;
2009-07-29 10:20:10 +02:00
2015-05-08 15:22:36 +02:00
if ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_DISABLE_RXFG )
2017-11-24 18:52:08 +05:30
priv - > write ( 0x0 , & regs - > rxfgmask ) ;
2012-06-28 16:21:35 +08:00
2015-08-31 21:03:29 +02:00
/* clear acceptance filters */
for ( i = 0 ; i < ARRAY_SIZE ( regs - > mb ) ; i + + )
2017-11-24 18:52:08 +05:30
priv - > write ( 0 , & regs - > rximr [ i ] ) ;
2015-08-31 21:03:29 +02:00
2015-08-06 14:53:57 +02:00
/* On Vybrid, disable memory error detection interrupts
2014-07-15 14:56:21 +02:00
* and freeze mode .
* This also works around errata e5295 which generates
* false positive memory errors and put the device in
* freeze mode .
*/
2015-05-08 15:22:36 +02:00
if ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_DISABLE_MECR ) {
2015-08-06 14:53:57 +02:00
/* Follow the protocol as described in "Detection
2014-07-15 14:56:21 +02:00
* and Correction of Memory Errors " to write to
* MECR register
*/
2017-11-24 18:52:08 +05:30
reg_ctrl2 = priv - > read ( & regs - > ctrl2 ) ;
2014-09-23 11:03:01 +02:00
reg_ctrl2 | = FLEXCAN_CTRL2_ECRWRE ;
2017-11-24 18:52:08 +05:30
priv - > write ( reg_ctrl2 , & regs - > ctrl2 ) ;
2014-07-15 14:56:21 +02:00
2017-11-24 18:52:08 +05:30
reg_mecr = priv - > read ( & regs - > mecr ) ;
2014-07-15 14:56:21 +02:00
reg_mecr & = ~ FLEXCAN_MECR_ECRWRDIS ;
2017-11-24 18:52:08 +05:30
priv - > write ( reg_mecr , & regs - > mecr ) ;
2014-07-15 14:56:21 +02:00
reg_mecr & = ~ ( FLEXCAN_MECR_NCEFAFRZ | FLEXCAN_MECR_HANCEI_MSK |
2015-08-06 14:53:57 +02:00
FLEXCAN_MECR_FANCEI_MSK ) ;
2017-11-24 18:52:08 +05:30
priv - > write ( reg_mecr , & regs - > mecr ) ;
2014-07-15 14:56:21 +02:00
}
2014-02-28 17:18:27 +01:00
err = flexcan_transceiver_enable ( priv ) ;
if ( err )
2014-02-28 17:08:21 +01:00
goto out_chip_disable ;
2009-07-29 10:20:10 +02:00
/* synchronize with the can bus */
2014-02-28 17:08:21 +01:00
err = flexcan_chip_unfreeze ( priv ) ;
if ( err )
goto out_transceiver_disable ;
2009-07-29 10:20:10 +02:00
priv - > can . state = CAN_STATE_ERROR_ACTIVE ;
2015-08-27 14:24:48 +02:00
/* enable interrupts atomically */
disable_irq ( dev - > irq ) ;
2017-11-24 18:52:08 +05:30
priv - > write ( priv - > reg_ctrl_default , & regs - > ctrl ) ;
priv - > write ( priv - > reg_imask1_default , & regs - > imask1 ) ;
priv - > write ( priv - > reg_imask2_default , & regs - > imask2 ) ;
2015-08-27 14:24:48 +02:00
enable_irq ( dev - > irq ) ;
2009-07-29 10:20:10 +02:00
/* print chip status */
2012-02-01 11:02:05 +01:00
netdev_dbg ( dev , " %s: reading mcr=0x%08x ctrl=0x%08x \n " , __func__ ,
2017-11-24 18:52:08 +05:30
priv - > read ( & regs - > mcr ) , priv - > read ( & regs - > ctrl ) ) ;
2009-07-29 10:20:10 +02:00
return 0 ;
2014-02-28 17:08:21 +01:00
out_transceiver_disable :
flexcan_transceiver_disable ( priv ) ;
out_chip_disable :
2009-07-29 10:20:10 +02:00
flexcan_chip_disable ( priv ) ;
return err ;
}
2015-08-06 14:53:57 +02:00
/* flexcan_chip_stop
2009-07-29 10:20:10 +02:00
*
* this functions is entered with clocks enabled
*/
static void flexcan_chip_stop ( struct net_device * dev )
{
struct flexcan_priv * priv = netdev_priv ( dev ) ;
2015-05-08 09:32:58 +02:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2009-07-29 10:20:10 +02:00
2014-02-28 17:08:21 +01:00
/* freeze + disable module */
flexcan_chip_freeze ( priv ) ;
flexcan_chip_disable ( priv ) ;
2009-07-29 10:20:10 +02:00
2014-02-19 12:00:51 +01:00
/* Disable all interrupts */
2017-11-24 18:52:08 +05:30
priv - > write ( 0 , & regs - > imask2 ) ;
priv - > write ( 0 , & regs - > imask1 ) ;
priv - > write ( priv - > reg_ctrl_default & ~ FLEXCAN_CTRL_ERR_ALL ,
& regs - > ctrl ) ;
2014-02-19 12:00:51 +01:00
2014-02-28 17:18:27 +01:00
flexcan_transceiver_disable ( priv ) ;
2009-07-29 10:20:10 +02:00
priv - > can . state = CAN_STATE_STOPPED ;
}
static int flexcan_open ( struct net_device * dev )
{
struct flexcan_priv * priv = netdev_priv ( dev ) ;
int err ;
2013-07-22 12:41:40 -03:00
err = clk_prepare_enable ( priv - > clk_ipg ) ;
if ( err )
return err ;
err = clk_prepare_enable ( priv - > clk_per ) ;
if ( err )
goto out_disable_ipg ;
2009-07-29 10:20:10 +02:00
err = open_candev ( dev ) ;
if ( err )
2013-07-22 12:41:40 -03:00
goto out_disable_per ;
2009-07-29 10:20:10 +02:00
err = request_irq ( dev - > irq , flexcan_irq , IRQF_SHARED , dev - > name , dev ) ;
if ( err )
goto out_close ;
/* start chip and queuing */
err = flexcan_chip_start ( dev ) ;
if ( err )
2014-02-28 14:52:01 +01:00
goto out_free_irq ;
2012-12-18 18:50:58 +01:00
can_led_event ( dev , CAN_LED_EVENT_OPEN ) ;
2015-05-10 15:26:58 +02:00
can_rx_offload_enable ( & priv - > offload ) ;
2009-07-29 10:20:10 +02:00
netif_start_queue ( dev ) ;
return 0 ;
2014-02-28 14:52:01 +01:00
out_free_irq :
free_irq ( dev - > irq , dev ) ;
2009-07-29 10:20:10 +02:00
out_close :
close_candev ( dev ) ;
2013-07-22 12:41:40 -03:00
out_disable_per :
2012-07-17 16:14:34 +02:00
clk_disable_unprepare ( priv - > clk_per ) ;
2013-07-22 12:41:40 -03:00
out_disable_ipg :
2012-07-17 16:14:34 +02:00
clk_disable_unprepare ( priv - > clk_ipg ) ;
2009-07-29 10:20:10 +02:00
return err ;
}
static int flexcan_close ( struct net_device * dev )
{
struct flexcan_priv * priv = netdev_priv ( dev ) ;
netif_stop_queue ( dev ) ;
2015-05-10 15:26:58 +02:00
can_rx_offload_disable ( & priv - > offload ) ;
2009-07-29 10:20:10 +02:00
flexcan_chip_stop ( dev ) ;
free_irq ( dev - > irq , dev ) ;
2012-07-17 16:14:34 +02:00
clk_disable_unprepare ( priv - > clk_per ) ;
clk_disable_unprepare ( priv - > clk_ipg ) ;
2009-07-29 10:20:10 +02:00
close_candev ( dev ) ;
2012-12-18 18:50:58 +01:00
can_led_event ( dev , CAN_LED_EVENT_STOP ) ;
2009-07-29 10:20:10 +02:00
return 0 ;
}
static int flexcan_set_mode ( struct net_device * dev , enum can_mode mode )
{
int err ;
switch ( mode ) {
case CAN_MODE_START :
err = flexcan_chip_start ( dev ) ;
if ( err )
return err ;
netif_wake_queue ( dev ) ;
break ;
default :
return - EOPNOTSUPP ;
}
return 0 ;
}
static const struct net_device_ops flexcan_netdev_ops = {
. ndo_open = flexcan_open ,
. ndo_stop = flexcan_close ,
. ndo_start_xmit = flexcan_start_xmit ,
2014-03-07 09:23:41 +01:00
. ndo_change_mtu = can_change_mtu ,
2009-07-29 10:20:10 +02:00
} ;
2012-12-03 09:22:44 -05:00
static int register_flexcandev ( struct net_device * dev )
2009-07-29 10:20:10 +02:00
{
struct flexcan_priv * priv = netdev_priv ( dev ) ;
2015-05-08 09:32:58 +02:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2009-07-29 10:20:10 +02:00
u32 reg , err ;
2013-07-22 12:41:40 -03:00
err = clk_prepare_enable ( priv - > clk_ipg ) ;
if ( err )
return err ;
err = clk_prepare_enable ( priv - > clk_per ) ;
if ( err )
goto out_disable_ipg ;
2009-07-29 10:20:10 +02:00
/* select "bus clock", chip must be disabled */
2014-02-28 15:30:18 +01:00
err = flexcan_chip_disable ( priv ) ;
if ( err )
goto out_disable_per ;
2017-11-24 18:52:08 +05:30
reg = priv - > read ( & regs - > ctrl ) ;
2009-07-29 10:20:10 +02:00
reg | = FLEXCAN_CTRL_CLK_SRC ;
2017-11-24 18:52:08 +05:30
priv - > write ( reg , & regs - > ctrl ) ;
2009-07-29 10:20:10 +02:00
2014-02-28 15:30:18 +01:00
err = flexcan_chip_enable ( priv ) ;
if ( err )
goto out_chip_disable ;
2009-07-29 10:20:10 +02:00
/* set freeze, halt and activate FIFO, restrict register access */
2017-11-24 18:52:08 +05:30
reg = priv - > read ( & regs - > mcr ) ;
2009-07-29 10:20:10 +02:00
reg | = FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT |
FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV ;
2017-11-24 18:52:08 +05:30
priv - > write ( reg , & regs - > mcr ) ;
2009-07-29 10:20:10 +02:00
2015-08-06 14:53:57 +02:00
/* Currently we only support newer versions of this core
2015-09-01 09:00:13 +02:00
* 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 .
2009-07-29 10:20:10 +02:00
*/
2017-11-24 18:52:08 +05:30
reg = priv - > read ( & regs - > mcr ) ;
2009-07-29 10:20:10 +02:00
if ( ! ( reg & FLEXCAN_MCR_FEN ) ) {
2012-02-01 11:02:05 +01:00
netdev_err ( dev , " Could not enable RX FIFO, unsupported core \n " ) ;
2009-07-29 10:20:10 +02:00
err = - ENODEV ;
2014-02-28 15:30:18 +01:00
goto out_chip_disable ;
2009-07-29 10:20:10 +02:00
}
err = register_candev ( dev ) ;
/* disable core and turn off clocks */
2014-02-28 15:30:18 +01:00
out_chip_disable :
2009-07-29 10:20:10 +02:00
flexcan_chip_disable ( priv ) ;
2014-02-28 15:30:18 +01:00
out_disable_per :
2012-07-17 16:14:34 +02:00
clk_disable_unprepare ( priv - > clk_per ) ;
2013-07-22 12:41:40 -03:00
out_disable_ipg :
2012-07-17 16:14:34 +02:00
clk_disable_unprepare ( priv - > clk_ipg ) ;
2009-07-29 10:20:10 +02:00
return err ;
}
2012-12-03 09:22:44 -05:00
static void unregister_flexcandev ( struct net_device * dev )
2009-07-29 10:20:10 +02:00
{
unregister_candev ( dev ) ;
}
2012-06-28 16:21:35 +08:00
static const struct of_device_id flexcan_of_match [ ] = {
{ . compatible = " fsl,imx6q-flexcan " , . data = & fsl_imx6q_devtype_data , } ,
2013-10-03 23:51:55 +02:00
{ . compatible = " fsl,imx28-flexcan " , . data = & fsl_imx28_devtype_data , } ,
2018-04-25 16:50:39 +02:00
{ . compatible = " fsl,imx53-flexcan " , . data = & fsl_imx25_devtype_data , } ,
{ . compatible = " fsl,imx35-flexcan " , . data = & fsl_imx25_devtype_data , } ,
{ . compatible = " fsl,imx25-flexcan " , . data = & fsl_imx25_devtype_data , } ,
2013-10-03 23:51:55 +02:00
{ . compatible = " fsl,p1010-flexcan " , . data = & fsl_p1010_devtype_data , } ,
2014-07-15 14:56:21 +02:00
{ . compatible = " fsl,vf610-flexcan " , . data = & fsl_vf610_devtype_data , } ,
2017-11-24 18:52:09 +05:30
{ . compatible = " fsl,ls1021ar2-flexcan " , . data = & fsl_ls1021a_r2_devtype_data , } ,
2012-06-28 16:21:35 +08:00
{ /* sentinel */ } ,
} ;
2012-10-04 10:55:35 +02:00
MODULE_DEVICE_TABLE ( of , flexcan_of_match ) ;
2012-06-28 16:21:35 +08:00
static const struct platform_device_id flexcan_id_table [ ] = {
{ . name = " flexcan " , . driver_data = ( kernel_ulong_t ) & fsl_p1010_devtype_data , } ,
{ /* sentinel */ } ,
} ;
2012-10-04 10:55:35 +02:00
MODULE_DEVICE_TABLE ( platform , flexcan_id_table ) ;
2012-06-28 16:21:35 +08:00
2012-12-03 09:22:44 -05:00
static int flexcan_probe ( struct platform_device * pdev )
2009-07-29 10:20:10 +02:00
{
2012-06-28 16:21:35 +08:00
const struct of_device_id * of_id ;
2012-07-13 14:52:48 +02:00
const struct flexcan_devtype_data * devtype_data ;
2009-07-29 10:20:10 +02:00
struct net_device * dev ;
struct flexcan_priv * priv ;
2015-03-22 17:35:52 +01:00
struct regulator * reg_xceiver ;
2009-07-29 10:20:10 +02:00
struct resource * mem ;
2012-07-17 16:14:34 +02:00
struct clk * clk_ipg = NULL , * clk_per = NULL ;
2015-05-08 09:32:58 +02:00
struct flexcan_regs __iomem * regs ;
2009-07-29 10:20:10 +02:00
int err , irq ;
2011-08-16 17:32:23 +00:00
u32 clock_freq = 0 ;
2015-03-22 17:35:52 +01:00
reg_xceiver = devm_regulator_get ( & pdev - > dev , " xceiver " ) ;
if ( PTR_ERR ( reg_xceiver ) = = - EPROBE_DEFER )
return - EPROBE_DEFER ;
else if ( IS_ERR ( reg_xceiver ) )
reg_xceiver = NULL ;
2012-06-28 16:21:34 +08:00
if ( pdev - > dev . of_node )
of_property_read_u32 ( pdev - > dev . of_node ,
2015-08-06 14:53:57 +02:00
" clock-frequency " , & clock_freq ) ;
2011-08-16 17:32:23 +00:00
if ( ! clock_freq ) {
2012-07-17 16:14:34 +02:00
clk_ipg = devm_clk_get ( & pdev - > dev , " ipg " ) ;
if ( IS_ERR ( clk_ipg ) ) {
dev_err ( & pdev - > dev , " no ipg clock defined \n " ) ;
2013-07-22 12:41:39 -03:00
return PTR_ERR ( clk_ipg ) ;
2012-07-17 16:14:34 +02:00
}
clk_per = devm_clk_get ( & pdev - > dev , " per " ) ;
if ( IS_ERR ( clk_per ) ) {
dev_err ( & pdev - > dev , " no per clock defined \n " ) ;
2013-07-22 12:41:39 -03:00
return PTR_ERR ( clk_per ) ;
2011-08-16 17:32:23 +00:00
}
2013-11-25 22:15:20 +01:00
clock_freq = clk_get_rate ( clk_per ) ;
2009-07-29 10:20:10 +02:00
}
mem = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
irq = platform_get_irq ( pdev , 0 ) ;
2013-07-22 12:41:39 -03:00
if ( irq < = 0 )
return - ENODEV ;
2009-07-29 10:20:10 +02:00
2015-05-08 09:32:58 +02:00
regs = devm_ioremap_resource ( & pdev - > dev , mem ) ;
if ( IS_ERR ( regs ) )
return PTR_ERR ( regs ) ;
2009-07-29 10:20:10 +02:00
2012-06-28 16:21:35 +08:00
of_id = of_match_device ( flexcan_of_match , & pdev - > dev ) ;
if ( of_id ) {
devtype_data = of_id - > data ;
2014-03-04 22:04:22 +01:00
} else if ( platform_get_device_id ( pdev ) - > driver_data ) {
2012-06-28 16:21:35 +08:00
devtype_data = ( struct flexcan_devtype_data * )
2014-03-04 22:04:22 +01:00
platform_get_device_id ( pdev ) - > driver_data ;
2012-06-28 16:21:35 +08:00
} else {
2013-07-22 12:41:39 -03:00
return - ENODEV ;
2012-06-28 16:21:35 +08:00
}
2013-07-22 12:41:39 -03:00
dev = alloc_candev ( sizeof ( struct flexcan_priv ) , 1 ) ;
if ( ! dev )
return - ENOMEM ;
2015-05-10 15:26:58 +02:00
platform_set_drvdata ( pdev , dev ) ;
SET_NETDEV_DEV ( dev , & pdev - > dev ) ;
2009-07-29 10:20:10 +02:00
dev - > netdev_ops = & flexcan_netdev_ops ;
dev - > irq = irq ;
2011-11-01 11:18:03 +13:00
dev - > flags | = IFF_ECHO ;
2009-07-29 10:20:10 +02:00
priv = netdev_priv ( dev ) ;
2017-11-24 18:52:08 +05:30
2018-04-25 16:50:39 +02:00
if ( of_property_read_bool ( pdev - > dev . of_node , " big-endian " ) | |
devtype_data - > quirks & FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN ) {
2017-11-24 18:52:08 +05:30
priv - > read = flexcan_read_be ;
priv - > write = flexcan_write_be ;
} else {
2018-04-25 16:50:39 +02:00
priv - > read = flexcan_read_le ;
priv - > write = flexcan_write_le ;
2017-11-24 18:52:08 +05:30
}
2011-08-16 17:32:23 +00:00
priv - > can . clock . freq = clock_freq ;
2009-07-29 10:20:10 +02:00
priv - > can . bittiming_const = & flexcan_bittiming_const ;
priv - > can . do_set_mode = flexcan_set_mode ;
priv - > can . do_get_berr_counter = flexcan_get_berr_counter ;
priv - > can . ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_3_SAMPLES |
CAN_CTRLMODE_BERR_REPORTING ;
2015-05-08 09:32:58 +02:00
priv - > regs = regs ;
2012-07-17 16:14:34 +02:00
priv - > clk_ipg = clk_ipg ;
priv - > clk_per = clk_per ;
2012-06-28 16:21:35 +08:00
priv - > devtype_data = devtype_data ;
2015-03-22 17:35:52 +01:00
priv - > reg_xceiver = reg_xceiver ;
2013-06-10 23:12:57 -03:00
2018-10-11 17:01:25 +02:00
if ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP )
2015-09-01 09:00:13 +02:00
priv - > tx_mb_reserved = & regs - > mb [ FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP ] ;
2018-10-11 17:01:25 +02:00
else
2015-09-01 09:00:13 +02:00
priv - > tx_mb_reserved = & regs - > mb [ FLEXCAN_TX_MB_RESERVED_OFF_FIFO ] ;
2015-07-12 00:47:47 +02:00
2018-10-11 17:01:25 +02:00
priv - > reg_imask1_default = 0 ;
2018-11-09 15:01:50 +01:00
priv - > reg_imask2_default = FLEXCAN_IFLAG_MB ( FLEXCAN_TX_MB ) ;
2015-08-04 13:46:10 +02:00
2015-05-10 15:26:58 +02:00
priv - > offload . mailbox_read = flexcan_mailbox_read ;
2009-07-29 10:20:10 +02:00
2015-09-01 09:00:13 +02:00
if ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP ) {
u64 imask ;
priv - > offload . mb_first = FLEXCAN_RX_MB_OFF_TIMESTAMP_FIRST ;
priv - > offload . mb_last = FLEXCAN_RX_MB_OFF_TIMESTAMP_LAST ;
imask = GENMASK_ULL ( priv - > offload . mb_last , priv - > offload . mb_first ) ;
priv - > reg_imask1_default | = imask ;
priv - > reg_imask2_default | = imask > > 32 ;
err = can_rx_offload_add_timestamp ( dev , & priv - > offload ) ;
} else {
priv - > reg_imask1_default | = FLEXCAN_IFLAG_RX_FIFO_OVERFLOW |
FLEXCAN_IFLAG_RX_FIFO_AVAILABLE ;
err = can_rx_offload_add_fifo ( dev , & priv - > offload , FLEXCAN_NAPI_WEIGHT ) ;
}
2015-05-10 15:26:58 +02:00
if ( err )
goto failed_offload ;
2009-07-29 10:20:10 +02:00
err = register_flexcandev ( dev ) ;
if ( err ) {
dev_err ( & pdev - > dev , " registering netdev failed \n " ) ;
goto failed_register ;
}
2012-12-18 18:50:58 +01:00
devm_can_led_init ( dev ) ;
2009-07-29 10:20:10 +02:00
dev_info ( & pdev - > dev , " device registered (reg_base=%p, irq=%d) \n " ,
2015-05-08 09:32:58 +02:00
priv - > regs , dev - > irq ) ;
2009-07-29 10:20:10 +02:00
return 0 ;
2015-05-10 15:26:58 +02:00
failed_offload :
2009-07-29 10:20:10 +02:00
failed_register :
free_candev ( dev ) ;
return err ;
}
2012-12-03 09:22:44 -05:00
static int flexcan_remove ( struct platform_device * pdev )
2009-07-29 10:20:10 +02:00
{
struct net_device * dev = platform_get_drvdata ( pdev ) ;
2014-02-28 20:48:36 +01:00
struct flexcan_priv * priv = netdev_priv ( dev ) ;
2009-07-29 10:20:10 +02:00
unregister_flexcandev ( dev ) ;
2015-05-10 15:26:58 +02:00
can_rx_offload_del ( & priv - > offload ) ;
2010-10-21 05:07:58 +00:00
free_candev ( dev ) ;
2009-07-29 10:20:10 +02:00
return 0 ;
}
2014-03-05 19:10:44 +01:00
static int __maybe_unused flexcan_suspend ( struct device * device )
2012-05-08 17:12:17 +02:00
{
2013-05-20 15:43:43 -03:00
struct net_device * dev = dev_get_drvdata ( device ) ;
2012-05-08 17:12:17 +02:00
struct flexcan_priv * priv = netdev_priv ( dev ) ;
2014-02-28 15:30:18 +01:00
int err ;
2012-05-08 17:12:17 +02:00
if ( netif_running ( dev ) ) {
2016-08-17 12:41:08 -03:00
err = flexcan_chip_disable ( priv ) ;
if ( err )
return err ;
2012-05-08 17:12:17 +02:00
netif_stop_queue ( dev ) ;
netif_device_detach ( dev ) ;
}
priv - > can . state = CAN_STATE_SLEEPING ;
return 0 ;
}
2014-03-05 19:10:44 +01:00
static int __maybe_unused flexcan_resume ( struct device * device )
2012-05-08 17:12:17 +02:00
{
2013-05-20 15:43:43 -03:00
struct net_device * dev = dev_get_drvdata ( device ) ;
2012-05-08 17:12:17 +02:00
struct flexcan_priv * priv = netdev_priv ( dev ) ;
2016-08-17 12:41:08 -03:00
int err ;
2012-05-08 17:12:17 +02:00
priv - > can . state = CAN_STATE_ERROR_ACTIVE ;
if ( netif_running ( dev ) ) {
netif_device_attach ( dev ) ;
netif_start_queue ( dev ) ;
2016-08-17 12:41:08 -03:00
err = flexcan_chip_enable ( priv ) ;
if ( err )
return err ;
2012-05-08 17:12:17 +02:00
}
2016-08-17 12:41:08 -03:00
return 0 ;
2012-05-08 17:12:17 +02:00
}
2013-05-20 15:43:43 -03:00
static SIMPLE_DEV_PM_OPS ( flexcan_pm_ops , flexcan_suspend , flexcan_resume ) ;
2012-05-08 17:12:17 +02:00
2009-07-29 10:20:10 +02:00
static struct platform_driver flexcan_driver = {
2011-08-16 17:32:22 +00:00
. driver = {
. name = DRV_NAME ,
2013-05-20 15:43:43 -03:00
. pm = & flexcan_pm_ops ,
2011-08-16 17:32:22 +00:00
. of_match_table = flexcan_of_match ,
} ,
2009-07-29 10:20:10 +02:00
. probe = flexcan_probe ,
2012-12-03 09:22:44 -05:00
. remove = flexcan_remove ,
2012-06-28 16:21:35 +08:00
. id_table = flexcan_id_table ,
2009-07-29 10:20:10 +02:00
} ;
2011-11-27 15:42:31 +00:00
module_platform_driver ( flexcan_driver ) ;
2009-07-29 10:20:10 +02:00
MODULE_AUTHOR ( " Sascha Hauer <kernel@pengutronix.de>, "
" Marc Kleine-Budde <kernel@pengutronix.de> " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_DESCRIPTION ( " CAN port driver for flexcan based chip " ) ;