Commit 2283ea0e authored by Thor Thayer's avatar Thor Thayer Committed by Ben Hutchings

can: c_can: Update D_CAN TX and RX functions to 32 bit - fix Altera Cyclone access

commit 427460c8 upstream.

When testing CAN write floods on Altera's CycloneV, the first 2 bytes
are sometimes 0x00, 0x00 or corrupted instead of the values sent. Also
observed bytes 4 & 5 were corrupted in some cases.

The D_CAN Data registers are 32 bits and changing from 16 bit writes to
32 bit writes fixes the problem.

Testing performed on Altera CycloneV (D_CAN).  Requesting tests on other
C_CAN & D_CAN platforms.
Reported-by: default avatarRichard Andrysek <richard.andrysek@gomtec.de>
Signed-off-by: default avatarThor Thayer <tthayer@opensource.altera.com>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent f3ce5ab4
...@@ -331,9 +331,23 @@ static void c_can_setup_tx_object(struct net_device *dev, int iface, ...@@ -331,9 +331,23 @@ static void c_can_setup_tx_object(struct net_device *dev, int iface,
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl); priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl);
if (priv->type == BOSCH_D_CAN) {
u32 data = 0, dreg = C_CAN_IFACE(DATA1_REG, iface);
for (i = 0; i < frame->can_dlc; i += 4, dreg += 2) {
data = (u32)frame->data[i];
data |= (u32)frame->data[i + 1] << 8;
data |= (u32)frame->data[i + 2] << 16;
data |= (u32)frame->data[i + 3] << 24;
priv->write_reg32(priv, dreg, data);
}
} else {
for (i = 0; i < frame->can_dlc; i += 2) { for (i = 0; i < frame->can_dlc; i += 2) {
priv->write_reg(priv, C_CAN_IFACE(DATA1_REG, iface) + i / 2, priv->write_reg(priv,
frame->data[i] | (frame->data[i + 1] << 8)); C_CAN_IFACE(DATA1_REG, iface) + i / 2,
frame->data[i] |
(frame->data[i + 1] << 8));
}
} }
} }
...@@ -401,12 +415,22 @@ static int c_can_read_msg_object(struct net_device *dev, int iface, u32 ctrl) ...@@ -401,12 +415,22 @@ static int c_can_read_msg_object(struct net_device *dev, int iface, u32 ctrl)
} else { } else {
int i, dreg = C_CAN_IFACE(DATA1_REG, iface); int i, dreg = C_CAN_IFACE(DATA1_REG, iface);
for (i = 0; i < frame->can_dlc; i += 2, dreg ++) { if (priv->type == BOSCH_D_CAN) {
for (i = 0; i < frame->can_dlc; i += 4, dreg += 2) {
data = priv->read_reg32(priv, dreg);
frame->data[i] = data;
frame->data[i + 1] = data >> 8;
frame->data[i + 2] = data >> 16;
frame->data[i + 3] = data >> 24;
}
} else {
for (i = 0; i < frame->can_dlc; i += 2, dreg++) {
data = priv->read_reg(priv, dreg); data = priv->read_reg(priv, dreg);
frame->data[i] = data; frame->data[i] = data;
frame->data[i + 1] = data >> 8; frame->data[i + 1] = data >> 8;
} }
} }
}
stats->rx_packets++; stats->rx_packets++;
stats->rx_bytes += frame->can_dlc; stats->rx_bytes += frame->can_dlc;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment