Add tracepoints to the Qualcomm GENI (Generic Interface) SPI driver. These trace events enable runtime debugging and performance analysis of SPI operations.
The trace events capture SPI clock configuration, FIFO parameters, transfer details, interrupt status, and actual transmitted/received data in hexadecimal format. Usage examples: Enable all SPI traces: echo 1 > /sys/kernel/debug/tracing/events/qcom_geni_spi/enable cat /sys/kernel/debug/tracing/trace_pipe Example trace output: 71.364028: geni_spi_fifo_params: 888000.spi: cs=0 mode=0x00000020 mode_changed=0x00000020 cs_changed=0 71.364054: geni_spi_clk_cfg: 888000.spi: req_hz=10000000 sclk_hz=100000000 clk_idx=5 clk_div=10 bpw=8 71.364095: geni_spi_transfer: 888000.spi: len=16 m_cmd=0x00000003 71.364096: geni_spi_tx_data: 888000.spi: tx_len=16 tx_rem=0 data=56 f1 0d 95 c1 09 33 d2 27 e7 ec 9d 9c e2 11 ff 71.364121: geni_spi_irq: 888000.spi: m_irq=0x08000081 dma_tx=0x00000000 dma_rx=0x00000000 71.364126: geni_spi_rx_data: 888000.spi: rx_len=16 rx_rem=0 data=56 f1 0d 95 c1 09 33 d2 27 e7 ec 9d 9c e2 11 ff Signed-off-by: Praveen Talari <[email protected]> --- drivers/spi/spi-geni-qcom.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index d5fb0edc8e0c..4da888359cfc 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -1,6 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2017-2018, The Linux foundation. All rights reserved. +#define CREATE_TRACE_POINTS +#include <trace/events/qcom_geni_spi.h> + #include <linux/clk.h> #include <linux/dmaengine.h> #include <linux/dma-mapping.h> @@ -332,6 +335,9 @@ static int geni_spi_set_clock_and_bw(struct spi_geni_master *mas, writel(clk_sel, se->base + SE_GENI_CLK_SEL); writel(m_clk_cfg, se->base + GENI_SER_M_CLK_CFG); + trace_geni_spi_clk_cfg(mas->dev, clk_hz, mas->cur_sclk_hz, idx, div, + mas->cur_bits_per_word); + /* Set BW quota for CPU as driver supports FIFO mode only. */ se->icc_paths[CPU_TO_GENI].avg_bw = Bps_to_icc(mas->cur_speed_hz); ret = geni_icc_set_bw(se); @@ -366,6 +372,9 @@ static int setup_fifo_params(struct spi_device *spi_slv, if ((mode_changed & SPI_CS_HIGH) || (cs_changed && (spi_slv->mode & SPI_CS_HIGH))) writel((spi_slv->mode & SPI_CS_HIGH) ? BIT(chipselect) : 0, se->base + SE_SPI_DEMUX_OUTPUT_INV); + trace_geni_spi_fifo_params(mas->dev, chipselect, spi_slv->mode, + mode_changed, cs_changed); + return 0; } @@ -717,6 +726,7 @@ static bool geni_spi_handle_tx(struct spi_geni_master *mas) max_bytes = mas->tx_rem_bytes; tx_buf = mas->cur_xfer->tx_buf + mas->cur_xfer->len - mas->tx_rem_bytes; + while (i < max_bytes) { unsigned int j; unsigned int bytes_to_write; @@ -729,6 +739,7 @@ static bool geni_spi_handle_tx(struct spi_geni_master *mas) iowrite32_rep(se->base + SE_GENI_TX_FIFOn, &fifo_word, 1); } mas->tx_rem_bytes -= max_bytes; + trace_geni_spi_tx_data(mas->dev, tx_buf, max_bytes, mas->tx_rem_bytes); if (!mas->tx_rem_bytes) { writel(0, se->base + SE_GENI_TX_WATERMARK_REG); return false; @@ -778,6 +789,8 @@ static void geni_spi_handle_rx(struct spi_geni_master *mas) rx_buf[i++] = fifo_byte[j]; } mas->rx_rem_bytes -= rx_bytes; + + trace_geni_spi_rx_data(mas->dev, rx_buf, rx_bytes, mas->rx_rem_bytes); } static int setup_se_xfer(struct spi_transfer *xfer, @@ -861,6 +874,8 @@ static int setup_se_xfer(struct spi_transfer *xfer, spin_lock_irq(&mas->lock); geni_se_setup_m_cmd(se, m_cmd, m_params); + trace_geni_spi_transfer(mas->dev, len, m_cmd); + if (mas->cur_xfer_mode == GENI_SE_DMA) { if (m_cmd & SPI_RX_ONLY) geni_se_rx_init_dma(se, sg_dma_address(xfer->rx_sg.sgl), @@ -915,6 +930,8 @@ static irqreturn_t geni_spi_isr(int irq, void *data) if (!m_irq && !dma_tx_status && !dma_rx_status) return IRQ_NONE; + trace_geni_spi_irq(mas->dev, m_irq, dma_tx_status, dma_rx_status); + if (m_irq & (M_CMD_OVERRUN_EN | M_ILLEGAL_CMD_EN | M_CMD_FAILURE_EN | M_RX_FIFO_RD_ERR_EN | M_RX_FIFO_WR_ERR_EN | M_TX_FIFO_RD_ERR_EN | M_TX_FIFO_WR_ERR_EN)) -- 2.34.1
