/** * Put message queue into TXB. * * @tx: TXB bits(Bit 0 -- TXB0, Bit 1 -- TXB1, Bit 2 -- TXB2) */ static void transmit_message(uint8_t tx) { struct can_frame frame; uint8_t rts = 0; /* Clear interrupt flags */ mcp2515_bit_modify(CANINTF, tx << TXIF_SHF, 0); /* Load messages into empty TX buffers. */ for (int i = TXB_NUM - 1; i >= 0; i--) { if (tx & BIT(i)) { canid_clear_cache(i); switch (i) { case 0: txb0_ack_emit(); break; case 1: txb1_ack_emit(); break; case 2: txb2_ack_emit(); break; default: break; } if (tx_queue_pop(&frame)) { /* Make sure the previous message is sent. */ while (mcp2515_read_reg(TXBCTRL(i) & TXBCTRL_TXREQ)); load_txb(i, &frame); rts |= BIT(i); } else { /* The TX queue is empty, stop transmission. */ sync_spinlock_lock(&txb_lock); xmit_stopped = 1; sync_spinlock_unlock(&txb_lock); } } } /* Initiating transmission */ mcp2515_rts(rts); }
/* * Note about handling of error return of mcp251x_spi_trans: accessing * registers via SPI is not really different conceptually than using * normal I/O assembler instructions, although it's much more * complicated from a practical POV. So it's not advisable to always * check the return value of this function. Imagine that every * read{b,l}, write{b,l} and friends would be bracketed in "if ( < 0) * error();", it would be a great mess (well there are some situation * when exception handling C++ like could be useful after all). So we * just check that transfers are OK at the beginning of our * conversation with the chip and to avoid doing really nasty things * (like injecting bogus packets in the network stack). */ static int mcp251x_spi_trans(struct spi_device *spi, int len) { struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); struct spi_transfer t = { .tx_buf = priv->spi_tx_buf, .rx_buf = priv->spi_rx_buf, .len = len, .cs_change = 0, }; struct spi_message m; int ret; spi_message_init(&m); if (mcp251x_enable_dma) { t.tx_dma = priv->spi_tx_dma; t.rx_dma = priv->spi_rx_dma; m.is_dma_mapped = 1; } spi_message_add_tail(&t, &m); ret = spi_sync(spi, &m); if (ret) dev_err(&spi->dev, "spi transfer failed: ret = %d\n", ret); return ret; } static u8 mcp251x_read_reg(struct spi_device *spi, uint8_t reg) { struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); u8 val = 0; priv->spi_tx_buf[0] = INSTRUCTION_READ; priv->spi_tx_buf[1] = reg; mcp251x_spi_trans(spi, 3); val = priv->spi_rx_buf[2]; return val; } static void mcp251x_write_reg(struct spi_device *spi, u8 reg, uint8_t val) { struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); priv->spi_tx_buf[0] = INSTRUCTION_WRITE; priv->spi_tx_buf[1] = reg; priv->spi_tx_buf[2] = val; mcp251x_spi_trans(spi, 3); } static void mcp251x_write_bits(struct spi_device *spi, u8 reg, u8 mask, uint8_t val) { struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); priv->spi_tx_buf[0] = INSTRUCTION_BIT_MODIFY; priv->spi_tx_buf[1] = reg; priv->spi_tx_buf[2] = mask; priv->spi_tx_buf[3] = val; mcp251x_spi_trans(spi, 4); } static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf, int len, int tx_buf_idx) { struct mcp251x_platform_data *pdata = spi->dev.platform_data; struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); if (pdata->model == CAN_MCP251X_MCP2510) { int i; for (i = 1; i < TXBDAT_OFF + len; i++) mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx) + i, buf[i]); } else { memcpy(priv->spi_tx_buf, buf, TXBDAT_OFF + len); mcp251x_spi_trans(spi, TXBDAT_OFF + len); } } static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame, int tx_buf_idx) { u32 sid, eid, exide, rtr; u8 buf[SPI_TRANSFER_BUF_LEN]; exide = (frame->can_id & CAN_EFF_FLAG) ? 1 : 0; /* Extended ID Enable */ if (exide) sid = (frame->can_id & CAN_EFF_MASK) >> 18; else