diff options
-rw-r--r-- | drivers/net/can/flexcan.c | 81 |
1 files changed, 71 insertions, 10 deletions
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 6bfe24aefea0..ff1beb92a985 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c | |||
@@ -92,6 +92,27 @@ | |||
92 | #define FLEXCAN_CTRL_ERR_ALL \ | 92 | #define FLEXCAN_CTRL_ERR_ALL \ |
93 | (FLEXCAN_CTRL_ERR_BUS | FLEXCAN_CTRL_ERR_STATE) | 93 | (FLEXCAN_CTRL_ERR_BUS | FLEXCAN_CTRL_ERR_STATE) |
94 | 94 | ||
95 | /* FLEXCAN control register 2 (CTRL2) bits */ | ||
96 | #define FLEXCAN_CRL2_ECRWRE BIT(29) | ||
97 | #define FLEXCAN_CRL2_WRMFRZ BIT(28) | ||
98 | #define FLEXCAN_CRL2_RFFN(x) (((x) & 0x0f) << 24) | ||
99 | #define FLEXCAN_CRL2_TASD(x) (((x) & 0x1f) << 19) | ||
100 | #define FLEXCAN_CRL2_MRP BIT(18) | ||
101 | #define FLEXCAN_CRL2_RRS BIT(17) | ||
102 | #define FLEXCAN_CRL2_EACEN BIT(16) | ||
103 | |||
104 | /* FLEXCAN memory error control register (MECR) bits */ | ||
105 | #define FLEXCAN_MECR_ECRWRDIS BIT(31) | ||
106 | #define FLEXCAN_MECR_HANCEI_MSK BIT(19) | ||
107 | #define FLEXCAN_MECR_FANCEI_MSK BIT(18) | ||
108 | #define FLEXCAN_MECR_CEI_MSK BIT(16) | ||
109 | #define FLEXCAN_MECR_HAERRIE BIT(15) | ||
110 | #define FLEXCAN_MECR_FAERRIE BIT(14) | ||
111 | #define FLEXCAN_MECR_EXTERRIE BIT(13) | ||
112 | #define FLEXCAN_MECR_RERRDIS BIT(9) | ||
113 | #define FLEXCAN_MECR_ECCDIS BIT(8) | ||
114 | #define FLEXCAN_MECR_NCEFAFRZ BIT(7) | ||
115 | |||
95 | /* FLEXCAN error and status register (ESR) bits */ | 116 | /* FLEXCAN error and status register (ESR) bits */ |
96 | #define FLEXCAN_ESR_TWRN_INT BIT(17) | 117 | #define FLEXCAN_ESR_TWRN_INT BIT(17) |
97 | #define FLEXCAN_ESR_RWRN_INT BIT(16) | 118 | #define FLEXCAN_ESR_RWRN_INT BIT(16) |
@@ -150,18 +171,20 @@ | |||
150 | * FLEXCAN hardware feature flags | 171 | * FLEXCAN hardware feature flags |
151 | * | 172 | * |
152 | * Below is some version info we got: | 173 | * Below is some version info we got: |
153 | * SOC Version IP-Version Glitch- [TR]WRN_INT | 174 | * SOC Version IP-Version Glitch- [TR]WRN_INT Memory err |
154 | * Filter? connected? | 175 | * Filter? connected? detection |
155 | * MX25 FlexCAN2 03.00.00.00 no no | 176 | * MX25 FlexCAN2 03.00.00.00 no no no |
156 | * MX28 FlexCAN2 03.00.04.00 yes yes | 177 | * MX28 FlexCAN2 03.00.04.00 yes yes no |
157 | * MX35 FlexCAN2 03.00.00.00 no no | 178 | * MX35 FlexCAN2 03.00.00.00 no no no |
158 | * MX53 FlexCAN2 03.00.00.00 yes no | 179 | * MX53 FlexCAN2 03.00.00.00 yes no no |
159 | * MX6s FlexCAN3 10.00.12.00 yes yes | 180 | * MX6s FlexCAN3 10.00.12.00 yes yes no |
181 | * VF610 FlexCAN3 ? no yes yes | ||
160 | * | 182 | * |
161 | * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected. | 183 | * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected. |
162 | */ | 184 | */ |
163 | #define FLEXCAN_HAS_V10_FEATURES BIT(1) /* For core version >= 10 */ | 185 | #define FLEXCAN_HAS_V10_FEATURES BIT(1) /* For core version >= 10 */ |
164 | #define FLEXCAN_HAS_BROKEN_ERR_STATE BIT(2) /* [TR]WRN_INT not connected */ | 186 | #define FLEXCAN_HAS_BROKEN_ERR_STATE BIT(2) /* [TR]WRN_INT not connected */ |
187 | #define FLEXCAN_HAS_MECR_FEATURES BIT(3) /* Memory error detection */ | ||
165 | 188 | ||
166 | /* Structure of the message buffer */ | 189 | /* Structure of the message buffer */ |
167 | struct flexcan_mb { | 190 | struct flexcan_mb { |
@@ -192,8 +215,17 @@ struct flexcan_regs { | |||
192 | u32 crcr; /* 0x44 */ | 215 | u32 crcr; /* 0x44 */ |
193 | u32 rxfgmask; /* 0x48 */ | 216 | u32 rxfgmask; /* 0x48 */ |
194 | u32 rxfir; /* 0x4c */ | 217 | u32 rxfir; /* 0x4c */ |
195 | u32 _reserved3[12]; | 218 | u32 _reserved3[12]; /* 0x50 */ |
196 | struct flexcan_mb cantxfg[64]; | 219 | struct flexcan_mb cantxfg[64]; /* 0x80 */ |
220 | u32 _reserved4[408]; | ||
221 | u32 mecr; /* 0xae0 */ | ||
222 | u32 erriar; /* 0xae4 */ | ||
223 | u32 erridpr; /* 0xae8 */ | ||
224 | u32 errippr; /* 0xaec */ | ||
225 | u32 rerrar; /* 0xaf0 */ | ||
226 | u32 rerrdr; /* 0xaf4 */ | ||
227 | u32 rerrsynr; /* 0xaf8 */ | ||
228 | u32 errsr; /* 0xafc */ | ||
197 | }; | 229 | }; |
198 | 230 | ||
199 | struct flexcan_devtype_data { | 231 | struct flexcan_devtype_data { |
@@ -223,6 +255,9 @@ static struct flexcan_devtype_data fsl_imx28_devtype_data; | |||
223 | static struct flexcan_devtype_data fsl_imx6q_devtype_data = { | 255 | static struct flexcan_devtype_data fsl_imx6q_devtype_data = { |
224 | .features = FLEXCAN_HAS_V10_FEATURES, | 256 | .features = FLEXCAN_HAS_V10_FEATURES, |
225 | }; | 257 | }; |
258 | static struct flexcan_devtype_data fsl_vf610_devtype_data = { | ||
259 | .features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_MECR_FEATURES, | ||
260 | }; | ||
226 | 261 | ||
227 | static const struct can_bittiming_const flexcan_bittiming_const = { | 262 | static const struct can_bittiming_const flexcan_bittiming_const = { |
228 | .name = DRV_NAME, | 263 | .name = DRV_NAME, |
@@ -817,7 +852,7 @@ static int flexcan_chip_start(struct net_device *dev) | |||
817 | struct flexcan_priv *priv = netdev_priv(dev); | 852 | struct flexcan_priv *priv = netdev_priv(dev); |
818 | struct flexcan_regs __iomem *regs = priv->base; | 853 | struct flexcan_regs __iomem *regs = priv->base; |
819 | int err; | 854 | int err; |
820 | u32 reg_mcr, reg_ctrl; | 855 | u32 reg_mcr, reg_ctrl, reg_crl2, reg_mecr; |
821 | 856 | ||
822 | /* enable module */ | 857 | /* enable module */ |
823 | err = flexcan_chip_enable(priv); | 858 | err = flexcan_chip_enable(priv); |
@@ -894,6 +929,31 @@ static int flexcan_chip_start(struct net_device *dev) | |||
894 | if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES) | 929 | if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES) |
895 | flexcan_write(0x0, ®s->rxfgmask); | 930 | flexcan_write(0x0, ®s->rxfgmask); |
896 | 931 | ||
932 | /* | ||
933 | * On Vybrid, disable memory error detection interrupts | ||
934 | * and freeze mode. | ||
935 | * This also works around errata e5295 which generates | ||
936 | * false positive memory errors and put the device in | ||
937 | * freeze mode. | ||
938 | */ | ||
939 | if (priv->devtype_data->features & FLEXCAN_HAS_MECR_FEATURES) { | ||
940 | /* | ||
941 | * Follow the protocol as described in "Detection | ||
942 | * and Correction of Memory Errors" to write to | ||
943 | * MECR register | ||
944 | */ | ||
945 | reg_crl2 = flexcan_read(®s->crl2); | ||
946 | reg_crl2 |= FLEXCAN_CRL2_ECRWRE; | ||
947 | flexcan_write(reg_crl2, ®s->crl2); | ||
948 | |||
949 | reg_mecr = flexcan_read(®s->mecr); | ||
950 | reg_mecr &= ~FLEXCAN_MECR_ECRWRDIS; | ||
951 | flexcan_write(reg_mecr, ®s->mecr); | ||
952 | reg_mecr &= ~(FLEXCAN_MECR_NCEFAFRZ | FLEXCAN_MECR_HANCEI_MSK | | ||
953 | FLEXCAN_MECR_FANCEI_MSK); | ||
954 | flexcan_write(reg_mecr, ®s->mecr); | ||
955 | } | ||
956 | |||
897 | err = flexcan_transceiver_enable(priv); | 957 | err = flexcan_transceiver_enable(priv); |
898 | if (err) | 958 | if (err) |
899 | goto out_chip_disable; | 959 | goto out_chip_disable; |
@@ -1104,6 +1164,7 @@ static const struct of_device_id flexcan_of_match[] = { | |||
1104 | { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, }, | 1164 | { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, }, |
1105 | { .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, }, | 1165 | { .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, }, |
1106 | { .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, }, | 1166 | { .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, }, |
1167 | { .compatible = "fsl,vf610-flexcan", .data = &fsl_vf610_devtype_data, }, | ||
1107 | { /* sentinel */ }, | 1168 | { /* sentinel */ }, |
1108 | }; | 1169 | }; |
1109 | MODULE_DEVICE_TABLE(of, flexcan_of_match); | 1170 | MODULE_DEVICE_TABLE(of, flexcan_of_match); |