2018-07-06 20: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 12:20:10 +04:00
# include <linux/netdevice.h>
# include <linux/can.h>
# include <linux/can/dev.h>
# include <linux/can/error.h>
2012-12-18 21:50:58 +04:00
# include <linux/can/led.h>
2015-05-10 16:26:58 +03:00
# include <linux/can/rx-offload.h>
2009-07-29 12:20:10 +04:00
# include <linux/clk.h>
# include <linux/delay.h>
# include <linux/interrupt.h>
# include <linux/io.h>
2018-11-23 11:35:33 +03:00
# include <linux/mfd/syscon.h>
2009-07-29 12:20:10 +04:00
# include <linux/module.h>
2011-08-16 21:32:23 +04:00
# include <linux/of.h>
2012-06-28 12:21:35 +04:00
# include <linux/of_device.h>
2009-07-29 12:20:10 +04:00
# include <linux/platform_device.h>
2018-11-30 11:53:26 +03:00
# include <linux/pm_runtime.h>
2013-06-11 06:12:57 +04:00
# include <linux/regulator/consumer.h>
2018-11-23 11:35:33 +03:00
# include <linux/regmap.h>
2009-07-29 12:20:10 +04: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 17:01:27 +03:00
# define FLEXCAN_MCR_IRMQ BIT(16)
2009-07-29 12:20:10 +04:00
# define FLEXCAN_MCR_LPRIO_EN BIT(13)
# define FLEXCAN_MCR_AEN BIT(12)
2015-09-01 10:00:13 +03:00
/* MCR_MAXMB: maximum used MBs is MAXMB + 1 */
2014-09-02 18:54:17 +04:00
# define FLEXCAN_MCR_MAXMB(x) ((x) & 0x7f)
2015-08-06 15:53:57 +03: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 12:20:10 +04: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 16:56:21 +04:00
/* FLEXCAN control register 2 (CTRL2) bits */
2014-09-23 13:03:01 +04: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 16:56:21 +04: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 12:20:10 +04: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 19:09:28 +04:00
# define FLEXCAN_ESR_ALL_INT \
( FLEXCAN_ESR_TWRN_INT | FLEXCAN_ESR_RWRN_INT | \
2018-11-23 11:35:33 +03:00
FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT | \
FLEXCAN_ESR_WAK_INT )
2009-07-29 12:20:10 +04:00
/* FLEXCAN interrupt flag register (IFLAG) bits */
2014-09-03 18:47:22 +04:00
/* Errata ERR005829 step7: Reserve first valid MB */
2018-10-11 18:01:25 +03:00
# define FLEXCAN_TX_MB_RESERVED_OFF_FIFO 8
2015-09-01 10:00:13 +03:00
# define FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP 0
2018-10-11 18:01:25 +03:00
# define FLEXCAN_RX_MB_OFF_TIMESTAMP_FIRST (FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP + 1)
2019-03-01 14:17:30 +03:00
# define FLEXCAN_IFLAG_MB(x) BIT_ULL(x)
2009-07-29 12:20:10 +04: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 10:00:13 +03:00
# define FLEXCAN_MB_CODE_MASK (0xf << 24)
# define FLEXCAN_MB_CODE_RX_BUSY_BIT (0x1 << 24)
2014-09-16 14:39:28 +04: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 15:53:57 +03:00
# define FLEXCAN_MB_CODE_RX_OVERRUN (0x6 << 24)
2014-09-16 14:39:28 +04: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 12:20:10 +04: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)
2019-01-31 12:37:22 +03:00
# define FLEXCAN_TIMEOUT_US (250)
2009-07-29 12:20:10 +04:00
2015-08-06 15:53:57 +03:00
/* FLEXCAN hardware feature flags
2012-10-10 23:10:42 +04:00
*
* Below is some version info we got :
2017-09-15 10:03:58 +03: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 15:01:08 +03:00
* MX25 FlexCAN2 03.00 .00 .00 no no no no no
2017-09-15 10:03:58 +03:00
* MX28 FlexCAN2 03.00 .04 .00 yes yes no no no
2017-11-22 15:01:08 +03:00
* MX35 FlexCAN2 03.00 .00 .00 no no no no no
2017-09-15 10:03:58 +03: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 11:18:21 +03:00
* VF610 FlexCAN3 ? no yes no yes yes ?
2017-11-24 16:22:09 +03:00
* LS1021A FlexCAN2 03.00 .04 .00 no yes no no yes
2012-10-10 23:10:42 +04:00
*
* Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected .
*/
2017-09-15 10:01:23 +03:00
# define FLEXCAN_QUIRK_BROKEN_WERR_STATE BIT(1) /* [TR]WRN_INT not connected */
2015-05-08 16:22:36 +03:00
# define FLEXCAN_QUIRK_DISABLE_RXFG BIT(2) /* Disable RX FIFO Global mask */
2015-09-01 09:57:55 +03:00
# define FLEXCAN_QUIRK_ENABLE_EACEN_RRS BIT(3) /* Enable EACEN and RRS bit in ctrl2 */
2017-03-02 17:42:49 +03:00
# define FLEXCAN_QUIRK_DISABLE_MECR BIT(4) /* Disable Memory error detection */
2015-09-01 10:00:13 +03:00
# define FLEXCAN_QUIRK_USE_OFF_TIMESTAMP BIT(5) /* Use timestamp based offloading */
2017-09-15 10:03:58 +03:00
# define FLEXCAN_QUIRK_BROKEN_PERR_STATE BIT(6) /* No interrupt for error passive */
2018-04-25 17:50:39 +03:00
# define FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN BIT(7) /* default to BE register access */
2018-11-23 11:35:33 +03:00
# define FLEXCAN_QUIRK_SETUP_STOP_MODE BIT(8) /* Setup stop mode to support wakeup */
2012-09-28 07:17:15 +04:00
2009-07-29 12:20:10 +04:00
/* Structure of the message buffer */
struct flexcan_mb {
u32 can_ctrl ;
u32 can_id ;
2018-11-24 00:18:44 +03:00
u32 data [ ] ;
2009-07-29 12:20:10 +04:00
} ;
/* 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 17:01:27 +03:00
union { /* 0x34 */
u32 gfwr_mx28 ; /* MX28, MX53 */
u32 ctrl2 ; /* MX6, VF610 */
} ;
2012-06-28 12:21:35 +04:00
u32 esr2 ; /* 0x38 */
u32 imeur ; /* 0x3c */
u32 lrfr ; /* 0x40 */
u32 crcr ; /* 0x44 */
u32 rxfgmask ; /* 0x48 */
u32 rxfir ; /* 0x4c */
2014-07-15 16:56:21 +04:00
u32 _reserved3 [ 12 ] ; /* 0x50 */
2018-08-28 20:49:12 +03:00
u8 mb [ 2 ] [ 512 ] ; /* 0x80 */
2014-09-17 14:50:48 +04: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 15:53:57 +03:00
* size conf ' ed via ctrl2 : : RFFN
2014-09-17 14:50:48 +04:00
* ( mx6 , vf610 )
*/
2015-08-27 17:01:27 +03: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 16:56:21 +04: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 12:20:10 +04:00
} ;
2012-06-28 12:21:35 +04:00
struct flexcan_devtype_data {
2015-05-08 16:22:36 +03:00
u32 quirks ; /* quirks needed for different IP cores */
2012-06-28 12:21:35 +04:00
} ;
2018-11-23 11:35:33 +03:00
struct flexcan_stop_mode {
struct regmap * gpr ;
u8 req_gpr ;
u8 req_bit ;
u8 ack_gpr ;
u8 ack_bit ;
} ;
2009-07-29 12:20:10 +04:00
struct flexcan_priv {
struct can_priv can ;
2015-05-10 16:26:58 +03:00
struct can_rx_offload offload ;
2018-11-30 11:53:26 +03:00
struct device * dev ;
2009-07-29 12:20:10 +04:00
2015-05-08 10:32:58 +03:00
struct flexcan_regs __iomem * regs ;
2018-11-24 00:18:44 +03:00
struct flexcan_mb __iomem * tx_mb ;
2015-07-12 01:47:47 +03:00
struct flexcan_mb __iomem * tx_mb_reserved ;
2018-11-24 00:18:44 +03:00
u8 tx_mb_idx ;
u8 mb_count ;
u8 mb_size ;
2018-12-13 10:08:00 +03:00
u8 clk_src ; /* clock source of CAN Protocol Engine */
2019-03-01 14:17:30 +03:00
u64 rx_mask ;
2019-03-01 15:54:19 +03:00
u64 tx_mask ;
2009-07-29 12:20:10 +04:00
u32 reg_ctrl_default ;
2012-07-17 18:14:34 +04:00
struct clk * clk_ipg ;
struct clk * clk_per ;
2012-07-13 16:52:48 +04:00
const struct flexcan_devtype_data * devtype_data ;
2013-06-11 06:12:57 +04:00
struct regulator * reg_xceiver ;
2018-11-23 11:35:33 +03:00
struct flexcan_stop_mode stm ;
2017-11-24 16:22:08 +03:00
/* Read and Write APIs */
u32 ( * read ) ( void __iomem * addr ) ;
void ( * write ) ( u32 val , void __iomem * addr ) ;
2012-06-28 12:21:35 +04:00
} ;
2016-07-04 15:45:44 +03:00
static const struct flexcan_devtype_data fsl_p1010_devtype_data = {
2018-04-25 17:50:39 +03: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 10:09:37 +03:00
. quirks = FLEXCAN_QUIRK_BROKEN_WERR_STATE |
FLEXCAN_QUIRK_BROKEN_PERR_STATE ,
2012-06-28 12:21:35 +04:00
} ;
2015-08-06 15:53:57 +03:00
2017-09-15 10:08:23 +03:00
static const struct flexcan_devtype_data fsl_imx28_devtype_data = {
. quirks = FLEXCAN_QUIRK_BROKEN_PERR_STATE ,
} ;
2015-08-06 15:53:57 +03:00
2016-07-04 15:45:44 +03:00
static const struct flexcan_devtype_data fsl_imx6q_devtype_data = {
2015-09-01 11:28:46 +03:00
. quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
2018-11-23 11:35:33 +03:00
FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | FLEXCAN_QUIRK_BROKEN_PERR_STATE |
FLEXCAN_QUIRK_SETUP_STOP_MODE ,
2009-07-29 12:20:10 +04:00
} ;
2015-08-06 15:53:57 +03:00
2016-07-04 15:45:44 +03:00
static const struct flexcan_devtype_data fsl_vf610_devtype_data = {
2015-09-01 09:57:55 +03:00
. quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
2017-11-27 11:18:21 +03:00
FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_OFF_TIMESTAMP |
FLEXCAN_QUIRK_BROKEN_PERR_STATE ,
2014-07-15 16:56:21 +04:00
} ;
2009-07-29 12:20:10 +04:00
2017-11-24 16:22:09 +03:00
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 14:58:31 +04:00
static const struct can_bittiming_const flexcan_bittiming_const = {
2009-07-29 12:20:10 +04: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 16:22:08 +03:00
/* 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 21:32:20 +04:00
*/
2017-11-24 16:22:08 +03:00
static inline u32 flexcan_read_be ( void __iomem * addr )
2011-08-16 21:32:20 +04:00
{
2017-11-24 16:22:08 +03:00
return ioread32be ( addr ) ;
2011-08-16 21:32:20 +04:00
}
2017-11-24 16:22:08 +03:00
static inline void flexcan_write_be ( u32 val , void __iomem * addr )
2011-08-16 21:32:20 +04:00
{
2017-11-24 16:22:08 +03:00
iowrite32be ( val , addr ) ;
2011-08-16 21:32:20 +04:00
}
2017-11-24 16:22:08 +03:00
static inline u32 flexcan_read_le ( void __iomem * addr )
2011-08-16 21:32:20 +04:00
{
2017-11-24 16:22:08 +03:00
return ioread32 ( addr ) ;
2011-08-16 21:32:20 +04:00
}
2017-11-24 16:22:08 +03:00
static inline void flexcan_write_le ( u32 val , void __iomem * addr )
2011-08-16 21:32:20 +04:00
{
2017-11-24 16:22:08 +03:00
iowrite32 ( val , addr ) ;
2011-08-16 21:32:20 +04:00
}
2018-11-24 00:18:44 +03:00
static struct flexcan_mb __iomem * flexcan_get_mb ( const struct flexcan_priv * priv ,
u8 mb_index )
{
2018-08-28 20:49:12 +03:00
u8 bank_size ;
bool bank ;
2018-11-24 00:18:44 +03:00
if ( WARN_ON ( mb_index > = priv - > mb_count ) )
return NULL ;
2018-08-28 20:49:12 +03:00
bank_size = sizeof ( priv - > regs - > mb [ 0 ] ) / priv - > mb_size ;
bank = mb_index > = bank_size ;
if ( bank )
mb_index - = bank_size ;
2018-11-24 00:18:44 +03:00
return ( struct flexcan_mb __iomem * )
2018-08-28 20:49:12 +03:00
( & priv - > regs - > mb [ bank ] [ priv - > mb_size * mb_index ] ) ;
2018-11-24 00:18:44 +03:00
}
2019-12-04 14:36:11 +03:00
static int flexcan_low_power_enter_ack ( struct flexcan_priv * priv )
{
struct flexcan_regs __iomem * regs = priv - > regs ;
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10 ;
while ( timeout - - & & ! ( priv - > read ( & regs - > mcr ) & FLEXCAN_MCR_LPM_ACK ) )
udelay ( 10 ) ;
if ( ! ( priv - > read ( & regs - > mcr ) & FLEXCAN_MCR_LPM_ACK ) )
return - ETIMEDOUT ;
return 0 ;
}
static int flexcan_low_power_exit_ack ( struct flexcan_priv * priv )
{
struct flexcan_regs __iomem * regs = priv - > regs ;
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10 ;
while ( timeout - - & & ( priv - > read ( & regs - > mcr ) & FLEXCAN_MCR_LPM_ACK ) )
udelay ( 10 ) ;
if ( priv - > read ( & regs - > mcr ) & FLEXCAN_MCR_LPM_ACK )
return - ETIMEDOUT ;
return 0 ;
}
2018-11-23 11:35:33 +03:00
static void flexcan_enable_wakeup_irq ( struct flexcan_priv * priv , bool enable )
{
struct flexcan_regs __iomem * regs = priv - > regs ;
u32 reg_mcr ;
reg_mcr = priv - > read ( & regs - > mcr ) ;
if ( enable )
reg_mcr | = FLEXCAN_MCR_WAK_MSK ;
else
reg_mcr & = ~ FLEXCAN_MCR_WAK_MSK ;
priv - > write ( reg_mcr , & regs - > mcr ) ;
}
2019-07-02 04:45:41 +03:00
static inline int flexcan_enter_stop_mode ( struct flexcan_priv * priv )
2018-11-23 11:35:33 +03:00
{
struct flexcan_regs __iomem * regs = priv - > regs ;
u32 reg_mcr ;
reg_mcr = priv - > read ( & regs - > mcr ) ;
reg_mcr | = FLEXCAN_MCR_SLF_WAK ;
priv - > write ( reg_mcr , & regs - > mcr ) ;
/* enable stop request */
regmap_update_bits ( priv - > stm . gpr , priv - > stm . req_gpr ,
1 < < priv - > stm . req_bit , 1 < < priv - > stm . req_bit ) ;
2019-07-02 04:45:41 +03:00
2019-12-04 14:36:14 +03:00
return flexcan_low_power_enter_ack ( priv ) ;
2018-11-23 11:35:33 +03:00
}
2019-07-02 04:45:41 +03:00
static inline int flexcan_exit_stop_mode ( struct flexcan_priv * priv )
2018-11-23 11:35:33 +03:00
{
struct flexcan_regs __iomem * regs = priv - > regs ;
u32 reg_mcr ;
/* remove stop request */
regmap_update_bits ( priv - > stm . gpr , priv - > stm . req_gpr ,
1 < < priv - > stm . req_bit , 0 ) ;
2019-07-02 04:45:41 +03:00
2018-11-23 11:35:33 +03:00
reg_mcr = priv - > read ( & regs - > mcr ) ;
reg_mcr & = ~ FLEXCAN_MCR_SLF_WAK ;
priv - > write ( reg_mcr , & regs - > mcr ) ;
2019-07-02 04:45:41 +03:00
2019-12-04 14:36:14 +03:00
return flexcan_low_power_exit_ack ( priv ) ;
2018-11-23 11:35:33 +03:00
}
2017-09-15 10:03:58 +03: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 16:22:08 +03:00
priv - > write ( reg_ctrl , & regs - > ctrl ) ;
2017-09-15 10:03:58 +03: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 16:22:08 +03:00
priv - > write ( reg_ctrl , & regs - > ctrl ) ;
2017-09-15 10:03:58 +03:00
}
2018-11-30 11:53:26 +03:00
static int flexcan_clks_enable ( const struct flexcan_priv * priv )
{
int err ;
err = clk_prepare_enable ( priv - > clk_ipg ) ;
if ( err )
return err ;
err = clk_prepare_enable ( priv - > clk_per ) ;
if ( err )
clk_disable_unprepare ( priv - > clk_ipg ) ;
return err ;
}
static void flexcan_clks_disable ( const struct flexcan_priv * priv )
{
clk_disable_unprepare ( priv - > clk_per ) ;
clk_disable_unprepare ( priv - > clk_ipg ) ;
}
2014-02-28 20:18:27 +04: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 18:30:18 +04:00
static int flexcan_chip_enable ( struct flexcan_priv * priv )
2009-07-29 12:20:10 +04:00
{
2015-05-08 10:32:58 +03:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2009-07-29 12:20:10 +04:00
u32 reg ;
2017-11-24 16:22:08 +03:00
reg = priv - > read ( & regs - > mcr ) ;
2009-07-29 12:20:10 +04:00
reg & = ~ FLEXCAN_MCR_MDIS ;
2017-11-24 16:22:08 +03:00
priv - > write ( reg , & regs - > mcr ) ;
2009-07-29 12:20:10 +04:00
2019-12-04 14:36:11 +03:00
return flexcan_low_power_exit_ack ( priv ) ;
2009-07-29 12:20:10 +04:00
}
2014-02-28 18:30:18 +04:00
static int flexcan_chip_disable ( struct flexcan_priv * priv )
2009-07-29 12:20:10 +04:00
{
2015-05-08 10:32:58 +03:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2009-07-29 12:20:10 +04:00
u32 reg ;
2017-11-24 16:22:08 +03:00
reg = priv - > read ( & regs - > mcr ) ;
2009-07-29 12:20:10 +04:00
reg | = FLEXCAN_MCR_MDIS ;
2017-11-24 16:22:08 +03:00
priv - > write ( reg , & regs - > mcr ) ;
2014-02-28 18:30:18 +04:00
2019-12-04 14:36:11 +03:00
return flexcan_low_power_enter_ack ( priv ) ;
2009-07-29 12:20:10 +04:00
}
2014-02-28 20:08:21 +04:00
static int flexcan_chip_freeze ( struct flexcan_priv * priv )
{
2015-05-08 10:32:58 +03:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2014-02-28 20:08:21 +04:00
unsigned int timeout = 1000 * 1000 * 10 / priv - > can . bittiming . bitrate ;
u32 reg ;
2017-11-24 16:22:08 +03:00
reg = priv - > read ( & regs - > mcr ) ;
2014-02-28 20:08:21 +04:00
reg | = FLEXCAN_MCR_HALT ;
2017-11-24 16:22:08 +03:00
priv - > write ( reg , & regs - > mcr ) ;
2014-02-28 20:08:21 +04:00
2017-11-24 16:22:08 +03:00
while ( timeout - - & & ! ( priv - > read ( & regs - > mcr ) & FLEXCAN_MCR_FRZ_ACK ) )
2014-08-27 14:02:16 +04:00
udelay ( 100 ) ;
2014-02-28 20:08:21 +04:00
2017-11-24 16:22:08 +03:00
if ( ! ( priv - > read ( & regs - > mcr ) & FLEXCAN_MCR_FRZ_ACK ) )
2014-02-28 20:08:21 +04:00
return - ETIMEDOUT ;
return 0 ;
}
static int flexcan_chip_unfreeze ( struct flexcan_priv * priv )
{
2015-05-08 10:32:58 +03:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2014-02-28 20:08:21 +04:00
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10 ;
u32 reg ;
2017-11-24 16:22:08 +03:00
reg = priv - > read ( & regs - > mcr ) ;
2014-02-28 20:08:21 +04:00
reg & = ~ FLEXCAN_MCR_HALT ;
2017-11-24 16:22:08 +03:00
priv - > write ( reg , & regs - > mcr ) ;
2014-02-28 20:08:21 +04:00
2017-11-24 16:22:08 +03:00
while ( timeout - - & & ( priv - > read ( & regs - > mcr ) & FLEXCAN_MCR_FRZ_ACK ) )
2014-08-27 14:02:16 +04:00
udelay ( 10 ) ;
2014-02-28 20:08:21 +04:00
2017-11-24 16:22:08 +03:00
if ( priv - > read ( & regs - > mcr ) & FLEXCAN_MCR_FRZ_ACK )
2014-02-28 20:08:21 +04:00
return - ETIMEDOUT ;
return 0 ;
}
2014-02-28 18:16:59 +04:00
static int flexcan_chip_softreset ( struct flexcan_priv * priv )
{
2015-05-08 10:32:58 +03:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2014-02-28 18:16:59 +04:00
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10 ;
2017-11-24 16:22:08 +03:00
priv - > write ( FLEXCAN_MCR_SOFTRST , & regs - > mcr ) ;
while ( timeout - - & & ( priv - > read ( & regs - > mcr ) & FLEXCAN_MCR_SOFTRST ) )
2014-08-27 14:02:16 +04:00
udelay ( 10 ) ;
2014-02-28 18:16:59 +04:00
2017-11-24 16:22:08 +03:00
if ( priv - > read ( & regs - > mcr ) & FLEXCAN_MCR_SOFTRST )
2014-02-28 18:16:59 +04:00
return - ETIMEDOUT ;
return 0 ;
}
2014-07-15 16:56:20 +04:00
static int __flexcan_get_berr_counter ( const struct net_device * dev ,
struct can_berr_counter * bec )
2009-07-29 12:20:10 +04:00
{
const struct flexcan_priv * priv = netdev_priv ( dev ) ;
2015-05-08 10:32:58 +03:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2017-11-24 16:22:08 +03:00
u32 reg = priv - > read ( & regs - > ecr ) ;
2009-07-29 12:20:10 +04:00
bec - > txerr = ( reg > > 0 ) & 0xff ;
bec - > rxerr = ( reg > > 8 ) & 0xff ;
return 0 ;
}
2014-07-15 16:56:20 +04: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 ;
2018-11-30 11:53:26 +03:00
err = pm_runtime_get_sync ( priv - > dev ) ;
if ( err < 0 )
2014-07-15 16:56:20 +04:00
return err ;
err = __flexcan_get_berr_counter ( dev , bec ) ;
2018-11-30 11:53:26 +03:00
pm_runtime_put ( priv - > dev ) ;
2014-07-15 16:56:20 +04:00
return err ;
}
2018-04-27 00:13:38 +03:00
static netdev_tx_t flexcan_start_xmit ( struct sk_buff * skb , struct net_device * dev )
2009-07-29 12:20:10 +04:00
{
const struct flexcan_priv * priv = netdev_priv ( dev ) ;
struct can_frame * cf = ( struct can_frame * ) skb - > data ;
u32 can_id ;
2015-08-06 15:53:57 +03:00
u32 data ;
2014-09-23 13:18:11 +04:00
u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | ( cf - > can_dlc < < 16 ) ;
2018-11-24 00:18:44 +03:00
int i ;
2009-07-29 12:20:10 +04: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 ;
2018-11-24 00:18:44 +03:00
for ( i = 0 ; i < cf - > can_dlc ; i + = sizeof ( u32 ) ) {
data = be32_to_cpup ( ( __be32 * ) & cf - > data [ i ] ) ;
priv - > write ( data , & priv - > tx_mb - > data [ i / sizeof ( u32 ) ] ) ;
2009-07-29 12:20:10 +04:00
}
2011-11-01 02:18:03 +04:00
can_put_echo_skb ( skb , dev , 0 ) ;
2018-11-24 00:18:44 +03:00
priv - > write ( can_id , & priv - > tx_mb - > can_id ) ;
priv - > write ( ctrl , & priv - > tx_mb - > can_ctrl ) ;
2009-07-29 12:20:10 +04:00
2014-09-03 18:47:22 +04:00
/* Errata ERR005829 step8:
* Write twice INACTIVE ( 0x8 ) code to first MB .
*/
2017-11-24 16:22:08 +03:00
priv - > write ( FLEXCAN_MB_CODE_TX_INACTIVE ,
2018-11-12 17:33:57 +03:00
& priv - > tx_mb_reserved - > can_ctrl ) ;
2017-11-24 16:22:08 +03:00
priv - > write ( FLEXCAN_MB_CODE_TX_INACTIVE ,
2018-11-12 17:33:57 +03:00
& priv - > tx_mb_reserved - > can_ctrl ) ;
2014-09-03 18:47:22 +04:00
2009-07-29 12:20:10 +04:00
return NETDEV_TX_OK ;
}
2015-05-10 16:26:58 +03:00
static void flexcan_irq_bus_err ( struct net_device * dev , u32 reg_esr )
2009-07-29 12:20:10 +04:00
{
struct flexcan_priv * priv = netdev_priv ( dev ) ;
2018-09-18 12:40:41 +03:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2017-01-18 13:38:26 +03:00
struct sk_buff * skb ;
struct can_frame * cf ;
2017-01-17 19:33:46 +03:00
bool rx_errors = false , tx_errors = false ;
2018-09-18 12:40:41 +03:00
u32 timestamp ;
2019-07-15 21:53:08 +03:00
int err ;
2018-09-18 12:40:41 +03:00
timestamp = priv - > read ( & regs - > timer ) < < 16 ;
2009-07-29 12:20:10 +04:00
2017-01-18 13:38:26 +03:00
skb = alloc_can_err_skb ( dev , & cf ) ;
if ( unlikely ( ! skb ) )
2015-05-10 16:26:58 +03:00
return ;
2017-01-18 13:38:26 +03:00
2009-07-29 12:20:10 +04:00
cf - > can_id | = CAN_ERR_PROT | CAN_ERR_BUSERROR ;
if ( reg_esr & FLEXCAN_ESR_BIT1_ERR ) {
2012-02-01 14:02:05 +04:00
netdev_dbg ( dev , " BIT1_ERR irq \n " ) ;
2009-07-29 12:20:10 +04:00
cf - > data [ 2 ] | = CAN_ERR_PROT_BIT1 ;
2017-01-17 19:33:46 +03:00
tx_errors = true ;
2009-07-29 12:20:10 +04:00
}
if ( reg_esr & FLEXCAN_ESR_BIT0_ERR ) {
2012-02-01 14:02:05 +04:00
netdev_dbg ( dev , " BIT0_ERR irq \n " ) ;
2009-07-29 12:20:10 +04:00
cf - > data [ 2 ] | = CAN_ERR_PROT_BIT0 ;
2017-01-17 19:33:46 +03:00
tx_errors = true ;
2009-07-29 12:20:10 +04:00
}
if ( reg_esr & FLEXCAN_ESR_ACK_ERR ) {
2012-02-01 14:02:05 +04:00
netdev_dbg ( dev , " ACK_ERR irq \n " ) ;
2009-07-29 12:20:10 +04:00
cf - > can_id | = CAN_ERR_ACK ;
2015-11-21 20:41:20 +03:00
cf - > data [ 3 ] = CAN_ERR_PROT_LOC_ACK ;
2017-01-17 19:33:46 +03:00
tx_errors = true ;
2009-07-29 12:20:10 +04:00
}
if ( reg_esr & FLEXCAN_ESR_CRC_ERR ) {
2012-02-01 14:02:05 +04:00
netdev_dbg ( dev , " CRC_ERR irq \n " ) ;
2009-07-29 12:20:10 +04:00
cf - > data [ 2 ] | = CAN_ERR_PROT_BIT ;
2015-11-21 20:41:20 +03:00
cf - > data [ 3 ] = CAN_ERR_PROT_LOC_CRC_SEQ ;
2017-01-17 19:33:46 +03:00
rx_errors = true ;
2009-07-29 12:20:10 +04:00
}
if ( reg_esr & FLEXCAN_ESR_FRM_ERR ) {
2012-02-01 14:02:05 +04:00
netdev_dbg ( dev , " FRM_ERR irq \n " ) ;
2009-07-29 12:20:10 +04:00
cf - > data [ 2 ] | = CAN_ERR_PROT_FORM ;
2017-01-17 19:33:46 +03:00
rx_errors = true ;
2009-07-29 12:20:10 +04:00
}
if ( reg_esr & FLEXCAN_ESR_STF_ERR ) {
2012-02-01 14:02:05 +04:00
netdev_dbg ( dev , " STF_ERR irq \n " ) ;
2009-07-29 12:20:10 +04:00
cf - > data [ 2 ] | = CAN_ERR_PROT_STUFF ;
2017-01-17 19:33:46 +03:00
rx_errors = true ;
2009-07-29 12:20:10 +04:00
}
priv - > can . can_stats . bus_error + + ;
if ( rx_errors )
dev - > stats . rx_errors + + ;
if ( tx_errors )
dev - > stats . tx_errors + + ;
2019-07-15 21:53:08 +03:00
err = can_rx_offload_queue_sorted ( & priv - > offload , skb , timestamp ) ;
if ( err )
dev - > stats . rx_fifo_errors + + ;
2009-07-29 12:20:10 +04:00
}
2015-05-10 16:26:58 +03:00
static void flexcan_irq_state ( struct net_device * dev , u32 reg_esr )
2009-07-29 12:20:10 +04:00
{
struct flexcan_priv * priv = netdev_priv ( dev ) ;
2018-09-18 12:40:41 +03:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2009-07-29 12:20:10 +04:00
struct sk_buff * skb ;
struct can_frame * cf ;
2017-01-18 13:25:41 +03:00
enum can_state new_state , rx_state , tx_state ;
2009-07-29 12:20:10 +04:00
int flt ;
2014-12-03 20:54:15 +03:00
struct can_berr_counter bec ;
2018-09-18 12:40:41 +03:00
u32 timestamp ;
2019-07-15 21:53:08 +03:00
int err ;
2018-09-18 12:40:41 +03:00
2009-07-29 12:20:10 +04:00
flt = reg_esr & FLEXCAN_ESR_FLT_CONF_MASK ;
if ( likely ( flt = = FLEXCAN_ESR_FLT_CONF_ACTIVE ) ) {
2014-12-03 20:54:15 +03:00
tx_state = unlikely ( reg_esr & FLEXCAN_ESR_TX_WRN ) ?
2015-08-06 15:53:57 +03:00
CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE ;
2014-12-03 20:54:15 +03:00
rx_state = unlikely ( reg_esr & FLEXCAN_ESR_RX_WRN ) ?
2015-08-06 15:53:57 +03:00
CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE ;
2014-12-03 20:54:15 +03:00
new_state = max ( tx_state , rx_state ) ;
2015-03-17 16:03:09 +03:00
} else {
2014-12-03 20:54:15 +03:00
__flexcan_get_berr_counter ( dev , & bec ) ;
2015-03-17 16:03:09 +03:00
new_state = flt = = FLEXCAN_ESR_FLT_CONF_PASSIVE ?
2015-08-06 15:53:57 +03:00
CAN_STATE_ERROR_PASSIVE : CAN_STATE_BUS_OFF ;
2014-12-03 20:54:15 +03:00
rx_state = bec . rxerr > = bec . txerr ? new_state : 0 ;
tx_state = bec . rxerr < = bec . txerr ? new_state : 0 ;
}
2009-07-29 12:20:10 +04:00
/* state hasn't changed */
if ( likely ( new_state = = priv - > can . state ) )
2015-05-10 16:26:58 +03:00
return ;
2009-07-29 12:20:10 +04:00
2019-10-09 16:15:37 +03:00
timestamp = priv - > read ( & regs - > timer ) < < 16 ;
2009-07-29 12:20:10 +04:00
skb = alloc_can_err_skb ( dev , & cf ) ;
if ( unlikely ( ! skb ) )
2015-05-10 16:26:58 +03:00
return ;
2009-07-29 12:20:10 +04:00
2014-12-03 20:54:15 +03:00
can_change_state ( dev , cf , tx_state , rx_state ) ;
if ( unlikely ( new_state = = CAN_STATE_BUS_OFF ) )
can_bus_off ( dev ) ;
2019-07-15 21:53:08 +03:00
err = can_rx_offload_queue_sorted ( & priv - > offload , skb , timestamp ) ;
if ( err )
dev - > stats . rx_fifo_errors + + ;
2015-05-10 16:26:58 +03:00
}
2009-07-29 12:20:10 +04:00
2019-03-01 17:38:05 +03:00
static inline u64 flexcan_read64_mask ( struct flexcan_priv * priv , void __iomem * addr , u64 mask )
{
u64 reg = 0 ;
if ( upper_32_bits ( mask ) )
reg = ( u64 ) priv - > read ( addr - 4 ) < < 32 ;
if ( lower_32_bits ( mask ) )
reg | = priv - > read ( addr ) ;
return reg & mask ;
}
2019-03-01 17:38:05 +03:00
static inline void flexcan_write64 ( struct flexcan_priv * priv , u64 val , void __iomem * addr )
{
if ( upper_32_bits ( val ) )
priv - > write ( upper_32_bits ( val ) , addr - 4 ) ;
if ( lower_32_bits ( val ) )
priv - > write ( lower_32_bits ( val ) , addr ) ;
}
2019-03-01 17:38:05 +03:00
static inline u64 flexcan_read_reg_iflag_rx ( struct flexcan_priv * priv )
{
return flexcan_read64_mask ( priv , & priv - > regs - > iflag1 , priv - > rx_mask ) ;
}
2019-03-01 17:38:05 +03:00
static inline u64 flexcan_read_reg_iflag_tx ( struct flexcan_priv * priv )
{
return flexcan_read64_mask ( priv , & priv - > regs - > iflag1 , priv - > tx_mask ) ;
}
2015-05-10 16:26:58 +03: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 12:20:10 +04:00
}
2019-07-12 11:02:38 +03:00
static struct sk_buff * flexcan_mailbox_read ( struct can_rx_offload * offload ,
unsigned int n , u32 * timestamp ,
bool drop )
2009-07-29 12:20:10 +04:00
{
2015-05-10 16:26:58 +03:00
struct flexcan_priv * priv = rx_offload_to_priv ( offload ) ;
2015-05-08 10:32:58 +03:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2018-11-24 00:18:44 +03:00
struct flexcan_mb __iomem * mb ;
2019-07-12 11:02:38 +03:00
struct sk_buff * skb ;
struct can_frame * cf ;
2015-05-10 16:26:58 +03:00
u32 reg_ctrl , reg_id , reg_iflag1 ;
2018-11-24 00:18:44 +03:00
int i ;
2019-07-12 11:02:38 +03:00
if ( unlikely ( drop ) ) {
skb = ERR_PTR ( - ENOBUFS ) ;
goto mark_as_read ;
}
2018-11-24 00:18:44 +03:00
mb = flexcan_get_mb ( priv , n ) ;
2015-05-10 16:26:58 +03:00
2015-09-01 10:00:13 +03:00
if ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP ) {
u32 code ;
do {
2017-11-24 16:22:08 +03:00
reg_ctrl = priv - > read ( & mb - > can_ctrl ) ;
2015-09-01 10:00:13 +03: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 ) )
2019-07-12 11:02:38 +03:00
return NULL ;
2015-09-01 10:00:13 +03:00
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 16:22:08 +03:00
reg_iflag1 = priv - > read ( & regs - > iflag1 ) ;
2015-09-01 10:00:13 +03:00
if ( ! ( reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE ) )
2019-07-12 11:02:38 +03:00
return NULL ;
2015-09-01 10:00:13 +03:00
2017-11-24 16:22:08 +03:00
reg_ctrl = priv - > read ( & mb - > can_ctrl ) ;
2015-09-01 10:00:13 +03:00
}
2009-07-29 12:20:10 +04:00
2019-07-12 11:02:38 +03:00
skb = alloc_can_skb ( offload - > dev , & cf ) ;
if ( ! skb ) {
skb = ERR_PTR ( - ENOMEM ) ;
goto mark_as_read ;
}
2015-05-10 16:26:58 +03:00
/* increase timstamp to full 32 bit */
* timestamp = reg_ctrl < < 16 ;
2017-11-24 16:22:08 +03:00
reg_id = priv - > read ( & mb - > can_id ) ;
2009-07-29 12:20:10 +04: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 ) ;
2018-11-24 00:18:44 +03:00
for ( i = 0 ; i < cf - > can_dlc ; i + = sizeof ( u32 ) ) {
__be32 data = cpu_to_be32 ( priv - > read ( & mb - > data [ i / sizeof ( u32 ) ] ) ) ;
* ( __be32 * ) ( cf - > data + i ) = data ;
}
2009-07-29 12:20:10 +04:00
2019-07-12 11:02:38 +03:00
mark_as_read :
2019-03-01 18:27:59 +03:00
if ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP )
flexcan_write64 ( priv , FLEXCAN_IFLAG_MB ( n ) , & regs - > iflag1 ) ;
else
2017-11-24 16:22:08 +03:00
priv - > write ( FLEXCAN_IFLAG_RX_FIFO_AVAILABLE , & regs - > iflag1 ) ;
2012-12-18 21:50:58 +04:00
2018-08-01 17:06:46 +03:00
/* 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 ) ;
2019-07-12 11:02:38 +03:00
return skb ;
2009-07-29 12:20:10 +04: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 10:32:58 +03:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2017-01-18 13:45:14 +03:00
irqreturn_t handled = IRQ_NONE ;
2019-03-01 15:54:19 +03:00
u64 reg_iflag_tx ;
u32 reg_esr ;
2017-09-15 10:03:58 +03:00
enum can_state last_state = priv - > can . state ;
2009-07-29 12:20:10 +04:00
2015-05-10 16:26:58 +03:00
/* reception interrupt */
2015-09-01 10:00:13 +03:00
if ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP ) {
2019-03-01 18:29:47 +03:00
u64 reg_iflag_rx ;
2015-09-01 10:00:13 +03:00
int ret ;
2019-03-01 18:29:47 +03:00
while ( ( reg_iflag_rx = flexcan_read_reg_iflag_rx ( priv ) ) ) {
2015-09-01 10:00:13 +03:00
handled = IRQ_HANDLED ;
ret = can_rx_offload_irq_offload_timestamp ( & priv - > offload ,
2019-03-01 18:29:47 +03:00
reg_iflag_rx ) ;
2015-09-01 10:00:13 +03:00
if ( ! ret )
break ;
}
} else {
2018-10-11 18:01:25 +03:00
u32 reg_iflag1 ;
reg_iflag1 = priv - > read ( & regs - > iflag1 ) ;
2015-09-01 10:00:13 +03:00
if ( reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE ) {
handled = IRQ_HANDLED ;
can_rx_offload_irq_offload_fifo ( & priv - > offload ) ;
}
2009-07-29 12:20:10 +04:00
2015-09-01 10:00:13 +03:00
/* FIFO overflow interrupt */
if ( reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_OVERFLOW ) {
handled = IRQ_HANDLED ;
2017-11-24 16:22:08 +03:00
priv - > write ( FLEXCAN_IFLAG_RX_FIFO_OVERFLOW ,
& regs - > iflag1 ) ;
2015-09-01 10:00:13 +03:00
dev - > stats . rx_over_errors + + ;
dev - > stats . rx_errors + + ;
}
2009-07-29 12:20:10 +04:00
}
2019-03-01 17:38:05 +03:00
reg_iflag_tx = flexcan_read_reg_iflag_tx ( priv ) ;
2018-10-11 18:01:25 +03:00
2009-07-29 12:20:10 +04:00
/* transmission complete interrupt */
2019-03-01 15:54:19 +03:00
if ( reg_iflag_tx & priv - > tx_mask ) {
2018-11-24 00:18:44 +03:00
u32 reg_ctrl = priv - > read ( & priv - > tx_mb - > can_ctrl ) ;
2018-09-18 12:40:39 +03:00
2017-01-18 13:45:14 +03:00
handled = IRQ_HANDLED ;
2018-09-18 12:40:39 +03:00
stats - > tx_bytes + = can_rx_offload_get_echo_skb ( & priv - > offload ,
0 , reg_ctrl < < 16 ) ;
2009-07-29 12:20:10 +04:00
stats - > tx_packets + + ;
2012-12-18 21:50:58 +04:00
can_led_event ( dev , CAN_LED_EVENT_TX ) ;
2015-08-06 15:53:57 +03:00
/* after sending a RTR frame MB is in RX mode */
2017-11-24 16:22:08 +03:00
priv - > write ( FLEXCAN_MB_CODE_TX_INACTIVE ,
2018-11-24 00:18:44 +03:00
& priv - > tx_mb - > can_ctrl ) ;
2019-03-01 17:38:05 +03:00
flexcan_write64 ( priv , priv - > tx_mask , & regs - > iflag1 ) ;
2009-07-29 12:20:10 +04:00
netif_wake_queue ( dev ) ;
}
2017-11-24 16:22:08 +03:00
reg_esr = priv - > read ( & regs - > esr ) ;
2015-05-10 16:26:58 +03:00
2017-01-18 13:45:14 +03:00
/* ACK all bus error and state change IRQ sources */
if ( reg_esr & FLEXCAN_ESR_ALL_INT ) {
handled = IRQ_HANDLED ;
2017-11-24 16:22:08 +03:00
priv - > write ( reg_esr & FLEXCAN_ESR_ALL_INT , & regs - > esr ) ;
2017-01-18 13:45:14 +03:00
}
2017-09-15 09:59:15 +03:00
/* state change interrupt or broken error state quirk fix is enabled */
if ( ( reg_esr & FLEXCAN_ESR_ERR_STATE ) | |
2017-09-15 10:03:58 +03:00
( priv - > devtype_data - > quirks & ( FLEXCAN_QUIRK_BROKEN_WERR_STATE |
2018-11-28 17:45:27 +03:00
FLEXCAN_QUIRK_BROKEN_PERR_STATE ) ) )
2015-05-10 16:26:58 +03: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 10:03:58 +03: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 13:45:14 +03:00
return handled ;
2009-07-29 12:20:10 +04: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 10:32:58 +03:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2009-07-29 12:20:10 +04:00
u32 reg ;
2017-11-24 16:22:08 +03:00
reg = priv - > read ( & regs - > ctrl ) ;
2009-07-29 12:20:10 +04: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 18:16:03 +03:00
netdev_dbg ( dev , " writing ctrl=0x%08x \n " , reg ) ;
2017-11-24 16:22:08 +03:00
priv - > write ( reg , & regs - > ctrl ) ;
2009-07-29 12:20:10 +04:00
/* print chip status */
2012-02-01 14:02:05 +04:00
netdev_dbg ( dev , " %s: mcr=0x%08x ctrl=0x%08x \n " , __func__ ,
2017-11-24 16:22:08 +03:00
priv - > read ( & regs - > mcr ) , priv - > read ( & regs - > ctrl ) ) ;
2009-07-29 12:20:10 +04:00
}
2015-08-06 15:53:57 +03:00
/* flexcan_chip_start
2009-07-29 12:20:10 +04: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 10:32:58 +03:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2014-09-23 13:03:01 +04:00
u32 reg_mcr , reg_ctrl , reg_ctrl2 , reg_mecr ;
2019-03-01 14:17:30 +03:00
u64 reg_imask ;
2014-09-23 20:09:27 +04:00
int err , i ;
2018-11-24 00:18:44 +03:00
struct flexcan_mb __iomem * mb ;
2009-07-29 12:20:10 +04:00
/* enable module */
2014-02-28 18:30:18 +04:00
err = flexcan_chip_enable ( priv ) ;
if ( err )
return err ;
2009-07-29 12:20:10 +04:00
/* soft reset */
2014-02-28 18:16:59 +04:00
err = flexcan_chip_softreset ( priv ) ;
if ( err )
2014-02-28 20:08:21 +04:00
goto out_chip_disable ;
2009-07-29 12:20:10 +04:00
flexcan_set_bittiming ( dev ) ;
2015-08-06 15:53:57 +03:00
/* MCR
2009-07-29 12:20:10 +04:00
*
* enable freeze
* halt now
* only supervisor access
* enable warning int
2015-08-31 22:03:29 +03:00
* enable individual RX masking
2015-08-31 22:32:34 +03:00
* choose format C
* set max mailbox number
2009-07-29 12:20:10 +04:00
*/
2017-11-24 16:22:08 +03:00
reg_mcr = priv - > read ( & regs - > mcr ) ;
2013-10-04 12:52:36 +04:00
reg_mcr & = ~ FLEXCAN_MCR_MAXMB ( 0xff ) ;
2015-09-01 10:00:13 +03:00
reg_mcr | = FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT | FLEXCAN_MCR_SUPV |
2018-08-13 21:20:48 +03:00
FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_IRMQ | FLEXCAN_MCR_IDAM_C |
2018-11-24 00:18:44 +03:00
FLEXCAN_MCR_MAXMB ( priv - > tx_mb_idx ) ;
2015-09-01 10:00:13 +03:00
2018-08-17 15:52:58 +03:00
/* MCR
*
* FIFO :
* - disable for timestamp mode
* - enable for FIFO mode
*/
2018-10-11 18:01:25 +03:00
if ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP )
2015-09-01 10:00:13 +03:00
reg_mcr & = ~ FLEXCAN_MCR_FEN ;
2018-10-11 18:01:25 +03:00
else
reg_mcr | = FLEXCAN_MCR_FEN ;
2018-08-13 21:20:48 +03:00
/* MCR
*
* NOTE : In loopback mode , the CAN_MCR [ SRXDIS ] cannot be
* asserted because this will impede the self reception
* of a transmitted message . This is not documented in
* earlier versions of flexcan block guide .
*
* Self Reception :
* - enable Self Reception for loopback mode
* ( by clearing " Self Reception Disable " bit )
* - disable for normal operation
*/
if ( priv - > can . ctrlmode & CAN_CTRLMODE_LOOPBACK )
reg_mcr & = ~ FLEXCAN_MCR_SRX_DIS ;
else
reg_mcr | = FLEXCAN_MCR_SRX_DIS ;
2012-02-01 14:02:05 +04:00
netdev_dbg ( dev , " %s: writing mcr=0x%08x " , __func__ , reg_mcr ) ;
2017-11-24 16:22:08 +03:00
priv - > write ( reg_mcr , & regs - > mcr ) ;
2009-07-29 12:20:10 +04:00
2015-08-06 15:53:57 +03:00
/* CTRL
2009-07-29 12:20:10 +04: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 16:22:08 +03:00
reg_ctrl = priv - > read ( & regs - > ctrl ) ;
2009-07-29 12:20:10 +04:00
reg_ctrl & = ~ FLEXCAN_CTRL_TSYN ;
reg_ctrl | = FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF |
2012-09-28 07:17:15 +04:00
FLEXCAN_CTRL_ERR_STATE ;
2015-08-06 15:53:57 +03:00
/* enable the "error interrupt" (FLEXCAN_CTRL_ERR_MSK),
2012-09-28 07:17:15 +04:00
* on most Flexcan cores , too . Otherwise we don ' t get
* any error warning or passive interrupts .
*/
2017-09-15 10:01:23 +03:00
if ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_BROKEN_WERR_STATE | |
2012-09-28 07:17:15 +04:00
priv - > can . ctrlmode & CAN_CTRLMODE_BERR_REPORTING )
reg_ctrl | = FLEXCAN_CTRL_ERR_MSK ;
2014-08-12 12:47:21 +04:00
else
reg_ctrl & = ~ FLEXCAN_CTRL_ERR_MSK ;
2009-07-29 12:20:10 +04:00
/* save for later use */
priv - > reg_ctrl_default = reg_ctrl ;
2015-08-27 15:24:48 +03:00
/* leave interrupts disabled for now */
reg_ctrl & = ~ FLEXCAN_CTRL_ERR_ALL ;
2012-02-01 14:02:05 +04:00
netdev_dbg ( dev , " %s: writing ctrl=0x%08x " , __func__ , reg_ctrl ) ;
2017-11-24 16:22:08 +03:00
priv - > write ( reg_ctrl , & regs - > ctrl ) ;
2009-07-29 12:20:10 +04:00
2015-09-01 09:57:55 +03:00
if ( ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_ENABLE_EACEN_RRS ) ) {
2017-11-24 16:22:08 +03:00
reg_ctrl2 = priv - > read ( & regs - > ctrl2 ) ;
2015-09-01 09:57:55 +03:00
reg_ctrl2 | = FLEXCAN_CTRL2_EACEN | FLEXCAN_CTRL2_RRS ;
2017-11-24 16:22:08 +03:00
priv - > write ( reg_ctrl2 , & regs - > ctrl2 ) ;
2015-09-01 09:57:55 +03:00
}
2015-09-01 10:00:13 +03:00
if ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP ) {
2018-10-11 18:01:25 +03:00
for ( i = priv - > offload . mb_first ; i < = priv - > offload . mb_last ; i + + ) {
2018-11-24 00:18:44 +03:00
mb = flexcan_get_mb ( priv , i ) ;
2017-11-24 16:22:08 +03:00
priv - > write ( FLEXCAN_MB_CODE_RX_EMPTY ,
2018-11-24 00:18:44 +03:00
& mb - > can_ctrl ) ;
2018-10-11 18:01:25 +03:00
}
} else {
/* clear and invalidate unused mailboxes first */
can: flexcan: fix NULL pointer exception during bringup
Commit cbffaf7aa09e ("can: flexcan: Always use last mailbox for TX")
introduced a loop letting i run up to (including) ARRAY_SIZE(regs->mb)
and in the body accessed regs->mb[i] which is an out-of-bounds array
access that then resulted in an access to an reserved register area.
Later this was changed by commit 0517961ccdf1 ("can: flexcan: Add
provision for variable payload size") to iterate a bit differently but
still runs one iteration too much resulting to call
flexcan_get_mb(priv, priv->mb_count)
which results in a WARN_ON and then a NULL pointer exception. This
only affects devices compatible with "fsl,p1010-flexcan",
"fsl,imx53-flexcan", "fsl,imx35-flexcan", "fsl,imx25-flexcan",
"fsl,imx28-flexcan", so newer i.MX SoCs are not affected.
Fixes: cbffaf7aa09e ("can: flexcan: Always use last mailbox for TX")
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Cc: linux-stable <stable@vger.kernel.org> # >= 4.20
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2019-01-11 14:20:41 +03:00
for ( i = FLEXCAN_TX_MB_RESERVED_OFF_FIFO ; i < priv - > mb_count ; i + + ) {
2018-11-24 00:18:44 +03:00
mb = flexcan_get_mb ( priv , i ) ;
2018-10-11 18:01:25 +03:00
priv - > write ( FLEXCAN_MB_CODE_RX_INACTIVE ,
2018-11-24 00:18:44 +03:00
& mb - > can_ctrl ) ;
2018-10-11 18:01:25 +03:00
}
2015-09-01 10:00:13 +03:00
}
2014-09-03 18:47:22 +04:00
/* Errata ERR005829: mark first TX mailbox as INACTIVE */
2017-11-24 16:22:08 +03:00
priv - > write ( FLEXCAN_MB_CODE_TX_INACTIVE ,
& priv - > tx_mb_reserved - > can_ctrl ) ;
2014-09-03 18:47:22 +04:00
2014-09-16 14:39:28 +04:00
/* mark TX mailbox as INACTIVE */
2017-11-24 16:22:08 +03:00
priv - > write ( FLEXCAN_MB_CODE_TX_INACTIVE ,
2018-11-24 00:18:44 +03:00
& priv - > tx_mb - > can_ctrl ) ;
2013-10-04 12:52:36 +04:00
2009-07-29 12:20:10 +04:00
/* acceptance mask/acceptance code (accept everything) */
2017-11-24 16:22:08 +03:00
priv - > write ( 0x0 , & regs - > rxgmask ) ;
priv - > write ( 0x0 , & regs - > rx14mask ) ;
priv - > write ( 0x0 , & regs - > rx15mask ) ;
2009-07-29 12:20:10 +04:00
2015-05-08 16:22:36 +03:00
if ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_DISABLE_RXFG )
2017-11-24 16:22:08 +03:00
priv - > write ( 0x0 , & regs - > rxfgmask ) ;
2012-06-28 12:21:35 +04:00
2015-08-31 22:03:29 +03:00
/* clear acceptance filters */
2018-11-24 00:18:44 +03:00
for ( i = 0 ; i < priv - > mb_count ; i + + )
2017-11-24 16:22:08 +03:00
priv - > write ( 0 , & regs - > rximr [ i ] ) ;
2015-08-31 22:03:29 +03:00
2015-08-06 15:53:57 +03:00
/* On Vybrid, disable memory error detection interrupts
2014-07-15 16:56:21 +04: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 16:22:36 +03:00
if ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_DISABLE_MECR ) {
2015-08-06 15:53:57 +03:00
/* Follow the protocol as described in "Detection
2014-07-15 16:56:21 +04:00
* and Correction of Memory Errors " to write to
* MECR register
*/
2017-11-24 16:22:08 +03:00
reg_ctrl2 = priv - > read ( & regs - > ctrl2 ) ;
2014-09-23 13:03:01 +04:00
reg_ctrl2 | = FLEXCAN_CTRL2_ECRWRE ;
2017-11-24 16:22:08 +03:00
priv - > write ( reg_ctrl2 , & regs - > ctrl2 ) ;
2014-07-15 16:56:21 +04:00
2017-11-24 16:22:08 +03:00
reg_mecr = priv - > read ( & regs - > mecr ) ;
2014-07-15 16:56:21 +04:00
reg_mecr & = ~ FLEXCAN_MECR_ECRWRDIS ;
2017-11-24 16:22:08 +03:00
priv - > write ( reg_mecr , & regs - > mecr ) ;
2019-08-15 11:00:26 +03:00
reg_mecr | = FLEXCAN_MECR_ECCDIS ;
2014-07-15 16:56:21 +04:00
reg_mecr & = ~ ( FLEXCAN_MECR_NCEFAFRZ | FLEXCAN_MECR_HANCEI_MSK |
2015-08-06 15:53:57 +03:00
FLEXCAN_MECR_FANCEI_MSK ) ;
2017-11-24 16:22:08 +03:00
priv - > write ( reg_mecr , & regs - > mecr ) ;
2014-07-15 16:56:21 +04:00
}
2014-02-28 20:18:27 +04:00
err = flexcan_transceiver_enable ( priv ) ;
if ( err )
2014-02-28 20:08:21 +04:00
goto out_chip_disable ;
2009-07-29 12:20:10 +04:00
/* synchronize with the can bus */
2014-02-28 20:08:21 +04:00
err = flexcan_chip_unfreeze ( priv ) ;
if ( err )
goto out_transceiver_disable ;
2009-07-29 12:20:10 +04:00
priv - > can . state = CAN_STATE_ERROR_ACTIVE ;
2015-08-27 15:24:48 +03:00
/* enable interrupts atomically */
disable_irq ( dev - > irq ) ;
2017-11-24 16:22:08 +03:00
priv - > write ( priv - > reg_ctrl_default , & regs - > ctrl ) ;
2019-03-01 15:54:19 +03:00
reg_imask = priv - > rx_mask | priv - > tx_mask ;
2019-03-01 14:17:30 +03:00
priv - > write ( upper_32_bits ( reg_imask ) , & regs - > imask2 ) ;
priv - > write ( lower_32_bits ( reg_imask ) , & regs - > imask1 ) ;
2015-08-27 15:24:48 +03:00
enable_irq ( dev - > irq ) ;
2009-07-29 12:20:10 +04:00
/* print chip status */
2012-02-01 14:02:05 +04:00
netdev_dbg ( dev , " %s: reading mcr=0x%08x ctrl=0x%08x \n " , __func__ ,
2017-11-24 16:22:08 +03:00
priv - > read ( & regs - > mcr ) , priv - > read ( & regs - > ctrl ) ) ;
2009-07-29 12:20:10 +04:00
return 0 ;
2014-02-28 20:08:21 +04:00
out_transceiver_disable :
flexcan_transceiver_disable ( priv ) ;
out_chip_disable :
2009-07-29 12:20:10 +04:00
flexcan_chip_disable ( priv ) ;
return err ;
}
2015-08-06 15:53:57 +03:00
/* flexcan_chip_stop
2009-07-29 12:20:10 +04: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 10:32:58 +03:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2009-07-29 12:20:10 +04:00
2014-02-28 20:08:21 +04:00
/* freeze + disable module */
flexcan_chip_freeze ( priv ) ;
flexcan_chip_disable ( priv ) ;
2009-07-29 12:20:10 +04:00
2014-02-19 15:00:51 +04:00
/* Disable all interrupts */
2017-11-24 16:22:08 +03:00
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 15:00:51 +04:00
2014-02-28 20:18:27 +04:00
flexcan_transceiver_disable ( priv ) ;
2009-07-29 12:20:10 +04:00
priv - > can . state = CAN_STATE_STOPPED ;
}
static int flexcan_open ( struct net_device * dev )
{
struct flexcan_priv * priv = netdev_priv ( dev ) ;
int err ;
2018-11-30 11:53:26 +03:00
err = pm_runtime_get_sync ( priv - > dev ) ;
if ( err < 0 )
2013-07-22 19:41:40 +04:00
return err ;
2009-07-29 12:20:10 +04:00
err = open_candev ( dev ) ;
if ( err )
2018-11-30 11:53:26 +03:00
goto out_runtime_put ;
2009-07-29 12:20:10 +04:00
err = request_irq ( dev - > irq , flexcan_irq , IRQF_SHARED , dev - > name , dev ) ;
if ( err )
goto out_close ;
2018-11-24 00:18:44 +03:00
priv - > mb_size = sizeof ( struct flexcan_mb ) + CAN_MAX_DLEN ;
2018-08-28 20:49:12 +03:00
priv - > mb_count = ( sizeof ( priv - > regs - > mb [ 0 ] ) / priv - > mb_size ) +
( sizeof ( priv - > regs - > mb [ 1 ] ) / priv - > mb_size ) ;
2018-11-24 00:18:44 +03:00
2018-08-13 21:20:49 +03:00
if ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP )
2018-11-24 00:18:44 +03:00
priv - > tx_mb_reserved =
flexcan_get_mb ( priv , FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP ) ;
2018-08-13 21:20:49 +03:00
else
2018-11-24 00:18:44 +03:00
priv - > tx_mb_reserved =
flexcan_get_mb ( priv , FLEXCAN_TX_MB_RESERVED_OFF_FIFO ) ;
priv - > tx_mb_idx = priv - > mb_count - 1 ;
priv - > tx_mb = flexcan_get_mb ( priv , priv - > tx_mb_idx ) ;
2019-03-01 15:54:19 +03:00
priv - > tx_mask = FLEXCAN_IFLAG_MB ( priv - > tx_mb_idx ) ;
2018-08-13 21:20:49 +03:00
priv - > offload . mailbox_read = flexcan_mailbox_read ;
if ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP ) {
priv - > offload . mb_first = FLEXCAN_RX_MB_OFF_TIMESTAMP_FIRST ;
2018-11-24 00:18:44 +03:00
priv - > offload . mb_last = priv - > mb_count - 2 ;
2018-08-13 21:20:49 +03:00
2019-03-01 14:17:30 +03:00
priv - > rx_mask = GENMASK_ULL ( priv - > offload . mb_last ,
priv - > offload . mb_first ) ;
2018-08-13 21:20:49 +03:00
err = can_rx_offload_add_timestamp ( dev , & priv - > offload ) ;
} else {
2019-03-01 14:17:30 +03:00
priv - > rx_mask = FLEXCAN_IFLAG_RX_FIFO_OVERFLOW |
2018-08-13 21:20:49 +03:00
FLEXCAN_IFLAG_RX_FIFO_AVAILABLE ;
err = can_rx_offload_add_fifo ( dev , & priv - > offload ,
FLEXCAN_NAPI_WEIGHT ) ;
}
if ( err )
goto out_free_irq ;
2009-07-29 12:20:10 +04:00
/* start chip and queuing */
err = flexcan_chip_start ( dev ) ;
if ( err )
2018-08-13 21:20:49 +03:00
goto out_offload_del ;
2012-12-18 21:50:58 +04:00
can_led_event ( dev , CAN_LED_EVENT_OPEN ) ;
2015-05-10 16:26:58 +03:00
can_rx_offload_enable ( & priv - > offload ) ;
2009-07-29 12:20:10 +04:00
netif_start_queue ( dev ) ;
return 0 ;
2018-08-13 21:20:49 +03:00
out_offload_del :
can_rx_offload_del ( & priv - > offload ) ;
2014-02-28 17:52:01 +04:00
out_free_irq :
free_irq ( dev - > irq , dev ) ;
2009-07-29 12:20:10 +04:00
out_close :
close_candev ( dev ) ;
2018-11-30 11:53:26 +03:00
out_runtime_put :
pm_runtime_put ( priv - > dev ) ;
2009-07-29 12:20:10 +04: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 16:26:58 +03:00
can_rx_offload_disable ( & priv - > offload ) ;
2009-07-29 12:20:10 +04:00
flexcan_chip_stop ( dev ) ;
2018-08-13 21:20:49 +03:00
can_rx_offload_del ( & priv - > offload ) ;
2009-07-29 12:20:10 +04:00
free_irq ( dev - > irq , dev ) ;
close_candev ( dev ) ;
2018-11-30 11:53:26 +03:00
pm_runtime_put ( priv - > dev ) ;
2009-07-29 12:20:10 +04:00
2012-12-18 21:50:58 +04:00
can_led_event ( dev , CAN_LED_EVENT_STOP ) ;
2009-07-29 12:20:10 +04: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 12:23:41 +04:00
. ndo_change_mtu = can_change_mtu ,
2009-07-29 12:20:10 +04:00
} ;
2012-12-03 18:22:44 +04:00
static int register_flexcandev ( struct net_device * dev )
2009-07-29 12:20:10 +04:00
{
struct flexcan_priv * priv = netdev_priv ( dev ) ;
2015-05-08 10:32:58 +03:00
struct flexcan_regs __iomem * regs = priv - > regs ;
2009-07-29 12:20:10 +04:00
u32 reg , err ;
2018-11-30 11:53:26 +03:00
err = flexcan_clks_enable ( priv ) ;
2013-07-22 19:41:40 +04:00
if ( err )
return err ;
2009-07-29 12:20:10 +04:00
/* select "bus clock", chip must be disabled */
2014-02-28 18:30:18 +04:00
err = flexcan_chip_disable ( priv ) ;
if ( err )
2018-11-30 11:53:26 +03:00
goto out_clks_disable ;
2017-11-24 16:22:08 +03:00
reg = priv - > read ( & regs - > ctrl ) ;
2018-12-13 10:08:00 +03:00
if ( priv - > clk_src )
reg | = FLEXCAN_CTRL_CLK_SRC ;
else
reg & = ~ FLEXCAN_CTRL_CLK_SRC ;
2017-11-24 16:22:08 +03:00
priv - > write ( reg , & regs - > ctrl ) ;
2009-07-29 12:20:10 +04:00
2014-02-28 18:30:18 +04:00
err = flexcan_chip_enable ( priv ) ;
if ( err )
goto out_chip_disable ;
2009-07-29 12:20:10 +04:00
/* set freeze, halt and activate FIFO, restrict register access */
2017-11-24 16:22:08 +03:00
reg = priv - > read ( & regs - > mcr ) ;
2009-07-29 12:20:10 +04:00
reg | = FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT |
FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV ;
2017-11-24 16:22:08 +03:00
priv - > write ( reg , & regs - > mcr ) ;
2009-07-29 12:20:10 +04:00
2015-08-06 15:53:57 +03:00
/* Currently we only support newer versions of this core
2015-09-01 10:00:13 +03: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 12:20:10 +04:00
*/
2017-11-24 16:22:08 +03:00
reg = priv - > read ( & regs - > mcr ) ;
2009-07-29 12:20:10 +04:00
if ( ! ( reg & FLEXCAN_MCR_FEN ) ) {
2012-02-01 14:02:05 +04:00
netdev_err ( dev , " Could not enable RX FIFO, unsupported core \n " ) ;
2009-07-29 12:20:10 +04:00
err = - ENODEV ;
2014-02-28 18:30:18 +04:00
goto out_chip_disable ;
2009-07-29 12:20:10 +04:00
}
err = register_candev ( dev ) ;
2018-11-30 11:53:26 +03:00
if ( err )
goto out_chip_disable ;
2009-07-29 12:20:10 +04:00
2018-11-30 11:53:26 +03:00
/* Disable core and let pm_runtime_put() disable the clocks.
* If CONFIG_PM is not enabled , the clocks will stay powered .
*/
2009-07-29 12:20:10 +04:00
flexcan_chip_disable ( priv ) ;
2018-11-30 11:53:26 +03:00
pm_runtime_put ( priv - > dev ) ;
return 0 ;
2009-07-29 12:20:10 +04:00
2018-11-30 11:53:26 +03:00
out_chip_disable :
flexcan_chip_disable ( priv ) ;
out_clks_disable :
flexcan_clks_disable ( priv ) ;
2009-07-29 12:20:10 +04:00
return err ;
}
2012-12-03 18:22:44 +04:00
static void unregister_flexcandev ( struct net_device * dev )
2009-07-29 12:20:10 +04:00
{
unregister_candev ( dev ) ;
}
2018-11-23 11:35:33 +03:00
static int flexcan_setup_stop_mode ( struct platform_device * pdev )
{
struct net_device * dev = platform_get_drvdata ( pdev ) ;
struct device_node * np = pdev - > dev . of_node ;
struct device_node * gpr_np ;
struct flexcan_priv * priv ;
phandle phandle ;
u32 out_val [ 5 ] ;
int ret ;
if ( ! np )
return - EINVAL ;
/* stop mode property format is:
* < & gpr req_gpr req_bit ack_gpr ack_bit > .
*/
ret = of_property_read_u32_array ( np , " fsl,stop-mode " , out_val ,
ARRAY_SIZE ( out_val ) ) ;
if ( ret ) {
dev_dbg ( & pdev - > dev , " no stop-mode property \n " ) ;
return ret ;
}
phandle = * out_val ;
gpr_np = of_find_node_by_phandle ( phandle ) ;
if ( ! gpr_np ) {
dev_dbg ( & pdev - > dev , " could not find gpr node by phandle \n " ) ;
2018-12-12 12:24:01 +03:00
return - ENODEV ;
2018-11-23 11:35:33 +03:00
}
priv = netdev_priv ( dev ) ;
priv - > stm . gpr = syscon_node_to_regmap ( gpr_np ) ;
if ( IS_ERR ( priv - > stm . gpr ) ) {
dev_dbg ( & pdev - > dev , " could not find gpr regmap \n " ) ;
2019-07-06 06:37:20 +03:00
ret = PTR_ERR ( priv - > stm . gpr ) ;
goto out_put_node ;
2018-11-23 11:35:33 +03:00
}
priv - > stm . req_gpr = out_val [ 1 ] ;
priv - > stm . req_bit = out_val [ 2 ] ;
priv - > stm . ack_gpr = out_val [ 3 ] ;
priv - > stm . ack_bit = out_val [ 4 ] ;
dev_dbg ( & pdev - > dev ,
" gpr %s req_gpr=0x02%x req_bit=%u ack_gpr=0x02%x ack_bit=%u \n " ,
gpr_np - > full_name , priv - > stm . req_gpr , priv - > stm . req_bit ,
priv - > stm . ack_gpr , priv - > stm . ack_bit ) ;
device_set_wakeup_capable ( & pdev - > dev , true ) ;
2019-04-09 11:39:48 +03:00
if ( of_property_read_bool ( np , " wakeup-source " ) )
device_set_wakeup_enable ( & pdev - > dev , true ) ;
2018-11-23 11:35:33 +03:00
return 0 ;
2019-08-07 04:44:57 +03:00
2019-07-06 06:37:20 +03:00
out_put_node :
of_node_put ( gpr_np ) ;
return ret ;
2018-11-23 11:35:33 +03:00
}
2012-06-28 12:21:35 +04:00
static const struct of_device_id flexcan_of_match [ ] = {
{ . compatible = " fsl,imx6q-flexcan " , . data = & fsl_imx6q_devtype_data , } ,
2013-10-04 01:51:55 +04:00
{ . compatible = " fsl,imx28-flexcan " , . data = & fsl_imx28_devtype_data , } ,
2018-04-25 17:50:39 +03: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-04 01:51:55 +04:00
{ . compatible = " fsl,p1010-flexcan " , . data = & fsl_p1010_devtype_data , } ,
2014-07-15 16:56:21 +04:00
{ . compatible = " fsl,vf610-flexcan " , . data = & fsl_vf610_devtype_data , } ,
2017-11-24 16:22:09 +03:00
{ . compatible = " fsl,ls1021ar2-flexcan " , . data = & fsl_ls1021a_r2_devtype_data , } ,
2012-06-28 12:21:35 +04:00
{ /* sentinel */ } ,
} ;
2012-10-04 12:55:35 +04:00
MODULE_DEVICE_TABLE ( of , flexcan_of_match ) ;
2012-06-28 12:21:35 +04: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 12:55:35 +04:00
MODULE_DEVICE_TABLE ( platform , flexcan_id_table ) ;
2012-06-28 12:21:35 +04:00
2012-12-03 18:22:44 +04:00
static int flexcan_probe ( struct platform_device * pdev )
2009-07-29 12:20:10 +04:00
{
2012-06-28 12:21:35 +04:00
const struct of_device_id * of_id ;
2012-07-13 16:52:48 +04:00
const struct flexcan_devtype_data * devtype_data ;
2009-07-29 12:20:10 +04:00
struct net_device * dev ;
struct flexcan_priv * priv ;
2015-03-22 19:35:52 +03:00
struct regulator * reg_xceiver ;
2012-07-17 18:14:34 +04:00
struct clk * clk_ipg = NULL , * clk_per = NULL ;
2015-05-08 10:32:58 +03:00
struct flexcan_regs __iomem * regs ;
2009-07-29 12:20:10 +04:00
int err , irq ;
2018-12-13 10:08:00 +03:00
u8 clk_src = 1 ;
2011-08-16 21:32:23 +04:00
u32 clock_freq = 0 ;
2015-03-22 19:35:52 +03: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 ;
2018-12-13 10:08:00 +03:00
if ( pdev - > dev . of_node ) {
2012-06-28 12:21:34 +04:00
of_property_read_u32 ( pdev - > dev . of_node ,
2015-08-06 15:53:57 +03:00
" clock-frequency " , & clock_freq ) ;
2018-12-13 10:08:00 +03:00
of_property_read_u8 ( pdev - > dev . of_node ,
" fsl,clk-source " , & clk_src ) ;
}
2011-08-16 21:32:23 +04:00
if ( ! clock_freq ) {
2012-07-17 18:14:34 +04: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 19:41:39 +04:00
return PTR_ERR ( clk_ipg ) ;
2012-07-17 18:14:34 +04: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 19:41:39 +04:00
return PTR_ERR ( clk_per ) ;
2011-08-16 21:32:23 +04:00
}
2013-11-26 01:15:20 +04:00
clock_freq = clk_get_rate ( clk_per ) ;
2009-07-29 12:20:10 +04:00
}
irq = platform_get_irq ( pdev , 0 ) ;
2013-07-22 19:41:39 +04:00
if ( irq < = 0 )
return - ENODEV ;
2009-07-29 12:20:10 +04:00
2019-09-29 11:32:09 +03:00
regs = devm_platform_ioremap_resource ( pdev , 0 ) ;
2015-05-08 10:32:58 +03:00
if ( IS_ERR ( regs ) )
return PTR_ERR ( regs ) ;
2009-07-29 12:20:10 +04:00
2012-06-28 12:21:35 +04:00
of_id = of_match_device ( flexcan_of_match , & pdev - > dev ) ;
if ( of_id ) {
devtype_data = of_id - > data ;
2014-03-05 01:04:22 +04:00
} else if ( platform_get_device_id ( pdev ) - > driver_data ) {
2012-06-28 12:21:35 +04:00
devtype_data = ( struct flexcan_devtype_data * )
2014-03-05 01:04:22 +04:00
platform_get_device_id ( pdev ) - > driver_data ;
2012-06-28 12:21:35 +04:00
} else {
2013-07-22 19:41:39 +04:00
return - ENODEV ;
2012-06-28 12:21:35 +04:00
}
2013-07-22 19:41:39 +04:00
dev = alloc_candev ( sizeof ( struct flexcan_priv ) , 1 ) ;
if ( ! dev )
return - ENOMEM ;
2015-05-10 16:26:58 +03:00
platform_set_drvdata ( pdev , dev ) ;
SET_NETDEV_DEV ( dev , & pdev - > dev ) ;
2009-07-29 12:20:10 +04:00
dev - > netdev_ops = & flexcan_netdev_ops ;
dev - > irq = irq ;
2011-11-01 02:18:03 +04:00
dev - > flags | = IFF_ECHO ;
2009-07-29 12:20:10 +04:00
priv = netdev_priv ( dev ) ;
2017-11-24 16:22:08 +03:00
2018-04-25 17:50:39 +03:00
if ( of_property_read_bool ( pdev - > dev . of_node , " big-endian " ) | |
devtype_data - > quirks & FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN ) {
2017-11-24 16:22:08 +03:00
priv - > read = flexcan_read_be ;
priv - > write = flexcan_write_be ;
} else {
2018-04-25 17:50:39 +03:00
priv - > read = flexcan_read_le ;
priv - > write = flexcan_write_le ;
2017-11-24 16:22:08 +03:00
}
2018-11-30 11:53:26 +03:00
priv - > dev = & pdev - > dev ;
2011-08-16 21:32:23 +04:00
priv - > can . clock . freq = clock_freq ;
2009-07-29 12:20:10 +04: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 10:32:58 +03:00
priv - > regs = regs ;
2012-07-17 18:14:34 +04:00
priv - > clk_ipg = clk_ipg ;
priv - > clk_per = clk_per ;
2018-12-13 10:08:00 +03:00
priv - > clk_src = clk_src ;
2012-06-28 12:21:35 +04:00
priv - > devtype_data = devtype_data ;
2015-03-22 19:35:52 +03:00
priv - > reg_xceiver = reg_xceiver ;
2013-06-11 06:12:57 +04:00
2018-11-30 11:53:26 +03:00
pm_runtime_get_noresume ( & pdev - > dev ) ;
pm_runtime_set_active ( & pdev - > dev ) ;
pm_runtime_enable ( & pdev - > dev ) ;
2009-07-29 12:20:10 +04:00
err = register_flexcandev ( dev ) ;
if ( err ) {
dev_err ( & pdev - > dev , " registering netdev failed \n " ) ;
goto failed_register ;
}
2012-12-18 21:50:58 +04:00
devm_can_led_init ( dev ) ;
2018-11-23 11:35:33 +03:00
if ( priv - > devtype_data - > quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE ) {
err = flexcan_setup_stop_mode ( pdev ) ;
if ( err )
dev_dbg ( & pdev - > dev , " failed to setup stop-mode \n " ) ;
}
2009-07-29 12:20:10 +04:00
return 0 ;
failed_register :
free_candev ( dev ) ;
return err ;
}
2012-12-03 18:22:44 +04:00
static int flexcan_remove ( struct platform_device * pdev )
2009-07-29 12:20:10 +04:00
{
struct net_device * dev = platform_get_drvdata ( pdev ) ;
unregister_flexcandev ( dev ) ;
2018-11-30 11:53:26 +03:00
pm_runtime_disable ( & pdev - > dev ) ;
2010-10-21 09:07:58 +04:00
free_candev ( dev ) ;
2009-07-29 12:20:10 +04:00
return 0 ;
}
2014-03-05 22:10:44 +04:00
static int __maybe_unused flexcan_suspend ( struct device * device )
2012-05-08 19:12:17 +04:00
{
2013-05-20 22:43:43 +04:00
struct net_device * dev = dev_get_drvdata ( device ) ;
2012-05-08 19:12:17 +04:00
struct flexcan_priv * priv = netdev_priv ( dev ) ;
2018-11-30 11:53:26 +03:00
int err = 0 ;
2012-05-08 19:12:17 +04:00
if ( netif_running ( dev ) ) {
2018-11-23 11:35:33 +03:00
/* if wakeup is enabled, enter stop mode
* else enter disabled mode .
*/
if ( device_may_wakeup ( device ) ) {
enable_irq_wake ( dev - > irq ) ;
2019-07-02 04:45:41 +03:00
err = flexcan_enter_stop_mode ( priv ) ;
if ( err )
return err ;
2018-11-23 11:35:33 +03:00
} else {
err = flexcan_chip_disable ( priv ) ;
if ( err )
return err ;
2018-11-30 11:53:26 +03:00
err = pm_runtime_force_suspend ( device ) ;
2018-11-23 11:35:33 +03:00
}
2012-05-08 19:12:17 +04:00
netif_stop_queue ( dev ) ;
netif_device_detach ( dev ) ;
}
priv - > can . state = CAN_STATE_SLEEPING ;
2018-11-30 11:53:26 +03:00
return err ;
2012-05-08 19:12:17 +04:00
}
2014-03-05 22:10:44 +04:00
static int __maybe_unused flexcan_resume ( struct device * device )
2012-05-08 19:12:17 +04:00
{
2013-05-20 22:43:43 +04:00
struct net_device * dev = dev_get_drvdata ( device ) ;
2012-05-08 19:12:17 +04:00
struct flexcan_priv * priv = netdev_priv ( dev ) ;
2018-11-30 11:53:26 +03:00
int err = 0 ;
2012-05-08 19:12:17 +04:00
priv - > can . state = CAN_STATE_ERROR_ACTIVE ;
if ( netif_running ( dev ) ) {
netif_device_attach ( dev ) ;
netif_start_queue ( dev ) ;
2018-11-23 11:35:33 +03:00
if ( device_may_wakeup ( device ) ) {
disable_irq_wake ( dev - > irq ) ;
2019-12-04 14:36:06 +03:00
err = flexcan_exit_stop_mode ( priv ) ;
if ( err )
return err ;
2018-11-23 11:35:33 +03:00
} else {
2018-11-30 11:53:26 +03:00
err = pm_runtime_force_resume ( device ) ;
2018-11-23 11:35:33 +03:00
if ( err )
return err ;
2018-11-30 11:53:26 +03:00
err = flexcan_chip_enable ( priv ) ;
2018-11-23 11:35:33 +03:00
}
2012-05-08 19:12:17 +04:00
}
2018-11-30 11:53:26 +03:00
return err ;
}
static int __maybe_unused flexcan_runtime_suspend ( struct device * device )
{
struct net_device * dev = dev_get_drvdata ( device ) ;
struct flexcan_priv * priv = netdev_priv ( dev ) ;
flexcan_clks_disable ( priv ) ;
2016-08-17 18:41:08 +03:00
return 0 ;
2012-05-08 19:12:17 +04:00
}
2013-05-20 22:43:43 +04:00
2018-11-30 11:53:26 +03:00
static int __maybe_unused flexcan_runtime_resume ( struct device * device )
{
struct net_device * dev = dev_get_drvdata ( device ) ;
struct flexcan_priv * priv = netdev_priv ( dev ) ;
return flexcan_clks_enable ( priv ) ;
}
2018-11-23 11:35:33 +03:00
static int __maybe_unused flexcan_noirq_suspend ( struct device * device )
{
struct net_device * dev = dev_get_drvdata ( device ) ;
struct flexcan_priv * priv = netdev_priv ( dev ) ;
if ( netif_running ( dev ) & & device_may_wakeup ( device ) )
flexcan_enable_wakeup_irq ( priv , true ) ;
return 0 ;
}
static int __maybe_unused flexcan_noirq_resume ( struct device * device )
{
struct net_device * dev = dev_get_drvdata ( device ) ;
struct flexcan_priv * priv = netdev_priv ( dev ) ;
2019-12-04 14:36:06 +03:00
if ( netif_running ( dev ) & & device_may_wakeup ( device ) )
2018-11-23 11:35:33 +03:00
flexcan_enable_wakeup_irq ( priv , false ) ;
return 0 ;
}
static const struct dev_pm_ops flexcan_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS ( flexcan_suspend , flexcan_resume )
2018-11-30 11:53:26 +03:00
SET_RUNTIME_PM_OPS ( flexcan_runtime_suspend , flexcan_runtime_resume , NULL )
2018-11-23 11:35:33 +03:00
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS ( flexcan_noirq_suspend , flexcan_noirq_resume )
} ;
2012-05-08 19:12:17 +04:00
2009-07-29 12:20:10 +04:00
static struct platform_driver flexcan_driver = {
2011-08-16 21:32:22 +04:00
. driver = {
. name = DRV_NAME ,
2013-05-20 22:43:43 +04:00
. pm = & flexcan_pm_ops ,
2011-08-16 21:32:22 +04:00
. of_match_table = flexcan_of_match ,
} ,
2009-07-29 12:20:10 +04:00
. probe = flexcan_probe ,
2012-12-03 18:22:44 +04:00
. remove = flexcan_remove ,
2012-06-28 12:21:35 +04:00
. id_table = flexcan_id_table ,
2009-07-29 12:20:10 +04:00
} ;
2011-11-27 19:42:31 +04:00
module_platform_driver ( flexcan_driver ) ;
2009-07-29 12:20:10 +04: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 " ) ;