aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can
diff options
context:
space:
mode:
authorWolfgang Grandegger <wg@grandegger.com>2012-09-27 23:17:15 -0400
committerDavid S. Miller <davem@davemloft.net>2012-10-01 17:18:21 -0400
commit4f72e5f00dea3eca9139a23cf70fbf18d62fd1db (patch)
treed14d7292b719fb92de48e7e79590d650e0e092eb /drivers/net/can
parentf674e72ff1aad23a99c7c205473cf02c85c2ac33 (diff)
flexcan: disable bus error interrupts for the i.MX28
Due to a bug in most Flexcan cores, the bus error interrupt needs to be enabled. Otherwise we don't get any error warning or passive interrupts. This is _not_ necessary for the i.MX28 and this patch disables bus error interrupts if "berr-reporting" is not requested. This avoids bus error flooding, which might harm, especially on low-end systems. To handle such quirks of the Flexcan cores, a hardware feature flag has been introduced, also replacing the "hw_ver" variable. So far nobody could tell what Flexcan core version is available on what Freescale SOC, apart from the i.MX6Q and P1010, and which bugs or features are present on the various "hw_rev". CC: Hui Wang <jason77.wang@gmail.com> CC: Shawn Guo <shawn.guo@linaro.org> Signed-off-by: Wolfgang Grandegger <wg@grandegger.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/can')
-rw-r--r--drivers/net/can/flexcan.c29
1 files changed, 19 insertions, 10 deletions
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index c5f143165f80..c78ecfca1e45 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -144,6 +144,10 @@
144 144
145#define FLEXCAN_MB_CODE_MASK (0xf0ffffff) 145#define FLEXCAN_MB_CODE_MASK (0xf0ffffff)
146 146
147/* FLEXCAN hardware feature flags */
148#define FLEXCAN_HAS_V10_FEATURES BIT(1) /* For core version >= 10 */
149#define FLEXCAN_HAS_BROKEN_ERR_STATE BIT(2) /* Broken error state handling */
150
147/* Structure of the message buffer */ 151/* Structure of the message buffer */
148struct flexcan_mb { 152struct flexcan_mb {
149 u32 can_ctrl; 153 u32 can_ctrl;
@@ -178,7 +182,7 @@ struct flexcan_regs {
178}; 182};
179 183
180struct flexcan_devtype_data { 184struct flexcan_devtype_data {
181 u32 hw_ver; /* hardware controller version */ 185 u32 features; /* hardware controller features */
182}; 186};
183 187
184struct flexcan_priv { 188struct flexcan_priv {
@@ -197,11 +201,11 @@ struct flexcan_priv {
197}; 201};
198 202
199static struct flexcan_devtype_data fsl_p1010_devtype_data = { 203static struct flexcan_devtype_data fsl_p1010_devtype_data = {
200 .hw_ver = 3, 204 .features = FLEXCAN_HAS_BROKEN_ERR_STATE,
201}; 205};
202 206static struct flexcan_devtype_data fsl_imx28_devtype_data;
203static struct flexcan_devtype_data fsl_imx6q_devtype_data = { 207static struct flexcan_devtype_data fsl_imx6q_devtype_data = {
204 .hw_ver = 10, 208 .features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_BROKEN_ERR_STATE,
205}; 209};
206 210
207static const struct can_bittiming_const flexcan_bittiming_const = { 211static const struct can_bittiming_const flexcan_bittiming_const = {
@@ -741,15 +745,19 @@ static int flexcan_chip_start(struct net_device *dev)
741 * enable tx and rx warning interrupt 745 * enable tx and rx warning interrupt
742 * enable bus off interrupt 746 * enable bus off interrupt
743 * (== FLEXCAN_CTRL_ERR_STATE) 747 * (== FLEXCAN_CTRL_ERR_STATE)
744 *
745 * _note_: we enable the "error interrupt"
746 * (FLEXCAN_CTRL_ERR_MSK), too. Otherwise we don't get any
747 * warning or bus passive interrupts.
748 */ 748 */
749 reg_ctrl = flexcan_read(&regs->ctrl); 749 reg_ctrl = flexcan_read(&regs->ctrl);
750 reg_ctrl &= ~FLEXCAN_CTRL_TSYN; 750 reg_ctrl &= ~FLEXCAN_CTRL_TSYN;
751 reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF | 751 reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF |
752 FLEXCAN_CTRL_ERR_STATE | FLEXCAN_CTRL_ERR_MSK; 752 FLEXCAN_CTRL_ERR_STATE;
753 /*
754 * enable the "error interrupt" (FLEXCAN_CTRL_ERR_MSK),
755 * on most Flexcan cores, too. Otherwise we don't get
756 * any error warning or passive interrupts.
757 */
758 if (priv->devtype_data->features & FLEXCAN_HAS_BROKEN_ERR_STATE ||
759 priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
760 reg_ctrl |= FLEXCAN_CTRL_ERR_MSK;
753 761
754 /* save for later use */ 762 /* save for later use */
755 priv->reg_ctrl_default = reg_ctrl; 763 priv->reg_ctrl_default = reg_ctrl;
@@ -772,7 +780,7 @@ static int flexcan_chip_start(struct net_device *dev)
772 flexcan_write(0x0, &regs->rx14mask); 780 flexcan_write(0x0, &regs->rx14mask);
773 flexcan_write(0x0, &regs->rx15mask); 781 flexcan_write(0x0, &regs->rx15mask);
774 782
775 if (priv->devtype_data->hw_ver >= 10) 783 if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES)
776 flexcan_write(0x0, &regs->rxfgmask); 784 flexcan_write(0x0, &regs->rxfgmask);
777 785
778 flexcan_transceiver_switch(priv, 1); 786 flexcan_transceiver_switch(priv, 1);
@@ -954,6 +962,7 @@ static void __devexit unregister_flexcandev(struct net_device *dev)
954 962
955static const struct of_device_id flexcan_of_match[] = { 963static const struct of_device_id flexcan_of_match[] = {
956 { .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, }, 964 { .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, },
965 { .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, },
957 { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, }, 966 { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, },
958 { /* sentinel */ }, 967 { /* sentinel */ },
959}; 968};