can speed optimizations

This commit is contained in:
molnarkares 2013-03-09 09:20:52 +01:00 committed by Piotr Esden-Tempski
parent 9585e59df1
commit 162522b3b2

View File

@ -192,12 +192,9 @@ void can_filter_init(u32 canport, u32 nr, bool scale_32bit, bool id_list_mode,
{ {
u32 filter_select_bit = 0x00000001 << nr; u32 filter_select_bit = 0x00000001 << nr;
/* Request initialization "enter". */ /* Request initialization "enter". */
CAN_FMR(canport) |= CAN_FMR_FINIT; CAN_FMR(canport) |= CAN_FMR_FINIT;
CAN_FMR(canport) &= (~0x3fUL)<<8;
CAN_FMR(canport) |= (14UL)<<8;
/* Deactivate the filter. */ /* Deactivate the filter. */
CAN_FA1R(canport) &= ~filter_select_bit; CAN_FA1R(canport) &= ~filter_select_bit;
@ -344,8 +341,12 @@ selected. -1 if no mailbox was available and no transmission got queued.
*/ */
int can_transmit(u32 canport, u32 id, bool ext, bool rtr, u8 length, u8 *data) int can_transmit(u32 canport, u32 id, bool ext, bool rtr, u8 length, u8 *data)
{ {
int ret = 0, i; int ret = 0;
u32 mailbox = 0; u32 mailbox = 0;
union {
u8 data8[4];
u32 data32;
}tdlxr,tdhxr;
/* Check which transmit mailbox is empty if any. */ /* Check which transmit mailbox is empty if any. */
if ((CAN_TSR(canport) & CAN_TSR_TME0) == CAN_TSR_TME0) { if ((CAN_TSR(canport) & CAN_TSR_TME0) == CAN_TSR_TME0) {
@ -362,36 +363,59 @@ int can_transmit(u32 canport, u32 id, bool ext, bool rtr, u8 length, u8 *data)
} }
/* If we have no empty mailbox return with an error. */ /* If we have no empty mailbox return with an error. */
if (ret == -1) if (ret == -1) {
return ret;
return ret;
}
/* Clear stale register bits */
CAN_TIxR(canport, mailbox) = 0;
if (ext) { if (ext) {
/* Set extended ID. */ /* Set extended ID. */
CAN_TIxR(canport, mailbox) |= id << CAN_TIxR_EXID_SHIFT; CAN_TIxR(canport, mailbox) = (id << CAN_TIxR_EXID_SHIFT) | CAN_TIxR_IDE;
/* Set extended ID indicator bit. */
CAN_TIxR(canport, mailbox) |= CAN_TIxR_IDE;
} else { } else {
/* Set standard ID. */ /* Set standard ID. */
CAN_TIxR(canport, mailbox) |= id << CAN_TIxR_STID_SHIFT; CAN_TIxR(canport, mailbox) = id << CAN_TIxR_STID_SHIFT;
} }
/* Set/clear remote transmission request bit. */ /* Set/clear remote transmission request bit. */
if (rtr) if (rtr){
CAN_TIxR(canport, mailbox) |= CAN_TIxR_RTR; /* Set */ CAN_TIxR(canport, mailbox) |= CAN_TIxR_RTR; /* Set */
}
/* Set the DLC. */ /* Set the DLC. */
CAN_TDTxR(canport, mailbox) &= 0xFFFFFFF0; CAN_TDTxR(canport, mailbox) &= ~CAN_TDTxR_DLC_MASK;
CAN_TDTxR(canport, mailbox) |= length & CAN_TDTxR_DLC_MASK; CAN_TDTxR(canport, mailbox) |= (length & CAN_TDTxR_DLC_MASK);
switch(length) {
case 8:
tdhxr.data8[3] = data[7];
/* no break */
case 7:
tdhxr.data8[2] = data[6];
/* no break */
case 6:
tdhxr.data8[1] = data[5];
/* no break */
case 5:
tdhxr.data8[0] = data[4];
/* no break */
case 4:
tdlxr.data8[3] = data[3];
/* no break */
case 3:
tdlxr.data8[2] = data[2];
/* no break */
case 2:
tdlxr.data8[1] = data[1];
/* no break */
case 1:
tdlxr.data8[0] = data[0];
/* no break */
default:
break;
}
/* Set the data. */ /* Set the data. */
CAN_TDLxR(canport, mailbox) = 0;
CAN_TDHxR(canport, mailbox) = 0; CAN_TDLxR(canport, mailbox) = tdlxr.data32;
for (i = 0; (i < 4) && (i < length); i++) CAN_TDHxR(canport, mailbox) = tdhxr.data32;
CAN_TDLxR(canport, mailbox) |= (u32)data[i] << (8 * i);
for (i = 4; (i < 8) && (i < length); i++)
CAN_TDHxR(canport, mailbox) |= (u32)data[i] << (8 * (i - 4));
/* Request transmission. */ /* Request transmission. */
CAN_TIxR(canport, mailbox) |= CAN_TIxR_TXRQ; CAN_TIxR(canport, mailbox) |= CAN_TIxR_TXRQ;
@ -430,12 +454,13 @@ void can_receive(u32 canport, u8 fifo, bool release, u32 *id, bool *ext,
bool *rtr, u32 *fmi, u8 *length, u8 *data) bool *rtr, u32 *fmi, u8 *length, u8 *data)
{ {
u32 fifo_id = 0; u32 fifo_id = 0;
int i; union {
u8 data8[4];
u32 data32;
}rdlxr,rdhxr;
const u32 fifoid_array[2] = {CAN_FIFO0,CAN_FIFO1};
if (fifo == 0) fifo_id = fifoid_array[fifo];
fifo_id = CAN_FIFO0;
else
fifo_id = CAN_FIFO1;
/* Get type of CAN ID and CAN ID. */ /* Get type of CAN ID and CAN ID. */
if (CAN_RIxR(canport, fifo_id) & CAN_RIxR_IDE) { if (CAN_RIxR(canport, fifo_id) & CAN_RIxR_IDE) {
@ -450,11 +475,15 @@ void can_receive(u32 canport, u8 fifo, bool release, u32 *id, bool *ext,
CAN_RIxR_STID_SHIFT); CAN_RIxR_STID_SHIFT);
} }
/* Get request transmit flag. */ /* Get remote transmit flag. */
if (CAN_RIxR(canport, fifo_id) & CAN_RIxR_RTR) if (CAN_RIxR(canport, fifo_id) & CAN_RIxR_RTR)
{
*rtr = true; *rtr = true;
}
else else
{
*rtr = false; *rtr = false;
}
/* Get filter match ID. */ /* Get filter match ID. */
*fmi = ((CAN_RDTxR(canport, fifo_id) & CAN_RDTxR_FMI_MASK) >> *fmi = ((CAN_RDTxR(canport, fifo_id) & CAN_RDTxR_FMI_MASK) >>
@ -462,17 +491,36 @@ void can_receive(u32 canport, u8 fifo, bool release, u32 *id, bool *ext,
/* Get data length. */ /* Get data length. */
*length = CAN_RDTxR(canport, fifo_id) & CAN_RDTxR_DLC_MASK; *length = CAN_RDTxR(canport, fifo_id) & CAN_RDTxR_DLC_MASK;
/* accelerate reception by copying the CAN data from the controller memory to
* the fast internal RAM */
/* Get data. */ rdlxr.data32 = CAN_RDLxR(canport, fifo_id);
for (i = 0; (i < 4) && (i < *length); i++) rdhxr.data32 = CAN_RDHxR(canport, fifo_id);
data[i] = (CAN_RDLxR(canport, fifo_id) >> (8 * i)) & 0xFF; /* */
/* Get data.
for (i = 4; (i < 8) && (i < *length); i++) * Byte wise copy is needed because we do not know the alignment
data[i] = (CAN_RDHxR(canport, fifo_id) >> (8 * (i - 4))) & 0xFF; * of the input buffer.
* Here copying 8 bytes each is faster than using loop
*
* It is OK to copy all 8 bytes because the upper layer must be
* prepared that the data length of the CAN frame is bigger
* than expected. In contrary the driver has no clue what is expected.
* This could be different if the max length would be handed over
* to the function, but it is not the case
*/
data[0] = rdlxr.data8[0];
data[1] = rdlxr.data8[1];
data[2] = rdlxr.data8[2];
data[3] = rdlxr.data8[3];
data[4] = rdhxr.data8[0];
data[5] = rdhxr.data8[1];
data[6] = rdhxr.data8[2];
data[7] = rdhxr.data8[3];
/* Release the FIFO. */ /* Release the FIFO. */
if (release) if (release){
can_fifo_release(canport, fifo); can_fifo_release(canport, fifo);
}
} }
bool can_available_mailbox(u32 canport) bool can_available_mailbox(u32 canport)