Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

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: Richard Andrysek <richard.andrysek@gomtec.de>
Signed-off-by: Thor Thayer <tthayer@opensource.altera.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

authored by

Thor Thayer and committed by
Marc Kleine-Budde
427460c8 ab522fd6

+31 -7
+31 -7
drivers/net/can/c_can/c_can.c
··· 332 332 333 333 priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl); 334 334 335 - for (i = 0; i < frame->can_dlc; i += 2) { 336 - priv->write_reg(priv, C_CAN_IFACE(DATA1_REG, iface) + i / 2, 337 - frame->data[i] | (frame->data[i + 1] << 8)); 335 + if (priv->type == BOSCH_D_CAN) { 336 + u32 data = 0, dreg = C_CAN_IFACE(DATA1_REG, iface); 337 + 338 + for (i = 0; i < frame->can_dlc; i += 4, dreg += 2) { 339 + data = (u32)frame->data[i]; 340 + data |= (u32)frame->data[i + 1] << 8; 341 + data |= (u32)frame->data[i + 2] << 16; 342 + data |= (u32)frame->data[i + 3] << 24; 343 + priv->write_reg32(priv, dreg, data); 344 + } 345 + } else { 346 + for (i = 0; i < frame->can_dlc; i += 2) { 347 + priv->write_reg(priv, 348 + C_CAN_IFACE(DATA1_REG, iface) + i / 2, 349 + frame->data[i] | 350 + (frame->data[i + 1] << 8)); 351 + } 338 352 } 339 353 } 340 354 ··· 416 402 } else { 417 403 int i, dreg = C_CAN_IFACE(DATA1_REG, iface); 418 404 419 - for (i = 0; i < frame->can_dlc; i += 2, dreg ++) { 420 - data = priv->read_reg(priv, dreg); 421 - frame->data[i] = data; 422 - frame->data[i + 1] = data >> 8; 405 + if (priv->type == BOSCH_D_CAN) { 406 + for (i = 0; i < frame->can_dlc; i += 4, dreg += 2) { 407 + data = priv->read_reg32(priv, dreg); 408 + frame->data[i] = data; 409 + frame->data[i + 1] = data >> 8; 410 + frame->data[i + 2] = data >> 16; 411 + frame->data[i + 3] = data >> 24; 412 + } 413 + } else { 414 + for (i = 0; i < frame->can_dlc; i += 2, dreg++) { 415 + data = priv->read_reg(priv, dreg); 416 + frame->data[i] = data; 417 + frame->data[i + 1] = data >> 8; 418 + } 423 419 } 424 420 } 425 421