drivers: spi: add kbus
Signed-off-by: Oleg Karfich <oleg.karfich@wago.com>
This commit is contained in:
@@ -256,6 +256,8 @@ CONFIG_I2C_MUX_PCA9541=y
|
||||
CONFIG_I2C_MUX_PCA954x=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_SPI_OMAP24XX=y
|
||||
CONFIG_SPI_KBUS=y
|
||||
CONFIG_SPI_SPIDEV=y
|
||||
CONFIG_PINCTRL_SINGLE=y
|
||||
CONFIG_GPIO_SYSFS=y
|
||||
CONFIG_GPIO_PCA953X=y
|
||||
|
||||
@@ -758,6 +758,22 @@ config SPI_TI_QSPI
|
||||
This device supports single, dual and quad read support, while
|
||||
it only supports single write mode.
|
||||
|
||||
config SPI_KBUS_OMAP_EXTENSION
|
||||
bool "KBUS Extension for OMAP MCSPI Driver (Read Notes!)"
|
||||
depends on SPI_OMAP24XX
|
||||
help
|
||||
KBUS Extension for the McSPI OMAP driver.
|
||||
It implements the communication protocol for the infineon XE164 Chip
|
||||
which does the communication with the KBUS logic.
|
||||
ATTENTION: This disbles the use of a worker thread (work queue).
|
||||
In its current state only one userspace process is allowed.
|
||||
|
||||
config SPI_KBUS
|
||||
select SPI_KBUS_OMAP_EXTENSION
|
||||
tristate "WAGO KBUS Driver"
|
||||
help
|
||||
This is driver provides access to the KBUS interface.
|
||||
|
||||
config SPI_ORION
|
||||
tristate "Orion SPI master"
|
||||
depends on PLAT_ORION || ARCH_MVEBU || COMPILE_TEST
|
||||
|
||||
@@ -152,6 +152,8 @@ obj-$(CONFIG_SPI_XTENSA_XTFPGA) += spi-xtensa-xtfpga.o
|
||||
obj-$(CONFIG_SPI_ZYNQ_QSPI) += spi-zynq-qspi.o
|
||||
obj-$(CONFIG_SPI_ZYNQMP_GQSPI) += spi-zynqmp-gqspi.o
|
||||
obj-$(CONFIG_SPI_AMD) += spi-amd.o
|
||||
obj-$(CONFIG_SPI_KBUS) += spi-kbus.o
|
||||
obj-$(CONFIG_SPI_OMAP24XX) += spi-omap2-mcspi.o
|
||||
|
||||
# SPI slave protocol handlers
|
||||
obj-$(CONFIG_SPI_SLAVE_TIME) += spi-slave-time.o
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,6 +29,20 @@
|
||||
|
||||
#include <linux/platform_data/spi-omap2-mcspi.h>
|
||||
|
||||
#include <linux/errno.h>
|
||||
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
#include <linux/sched.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
#include <linux/spi/kbus.h>
|
||||
#include <misc/wago-tests.h>
|
||||
#define PXC_SPI_KBUS_TRACER
|
||||
#include <trace/events/pxc.h>
|
||||
static int kbusdelay = 0; /* KBUS Inter-Frame-Delay in nanoseconds */
|
||||
#endif
|
||||
|
||||
#define OMAP2_MCSPI_MAX_FREQ 48000000
|
||||
#define OMAP2_MCSPI_MAX_DIVIDER 4096
|
||||
#define OMAP2_MCSPI_MAX_FIFODEPTH 64
|
||||
@@ -290,6 +304,25 @@ static void omap2_mcspi_set_mode(struct spi_controller *ctlr)
|
||||
ctx->modulctrl = l;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_SET_SPIDAT_DIR
|
||||
static void omap2_mcspi_set_spidat_direction(struct spi_master *master)
|
||||
{
|
||||
u32 l;
|
||||
|
||||
#define OMAP2_MCSPI_SYST_SPIDATDIR0_INPUT_EN BIT(8)
|
||||
#define OMAP2_MCSPI_SYST_SPIDATDIR1_INPUT_EN BIT(9)
|
||||
l = mcspi_read_reg(master, OMAP2_MCSPI_SYST);
|
||||
pr_info("%s: read-OMAP2_MCSPI_SYST: 0x%x\n", __func__, l);
|
||||
l &= ~(OMAP2_MCSPI_SYST_SPIDATDIR0_INPUT_EN | OMAP2_MCSPI_SYST_SPIDATDIR1_INPUT_EN);
|
||||
l |= OMAP2_MCSPI_SYST_SPIDATDIR0_INPUT_EN;
|
||||
pr_info("%s: write-OMAP2_MCSPI_SYST: 0x%x\n", __func__, l);
|
||||
mcspi_write_reg(master, OMAP2_MCSPI_SYST, l);
|
||||
|
||||
l = mcspi_read_reg(master, OMAP2_MCSPI_SYST);
|
||||
pr_info("%s: (update) read-OMAP2_MCSPI_SYST: 0x%x\n", __func__, l);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void omap2_mcspi_set_fifo(const struct spi_device *spi,
|
||||
struct spi_transfer *t, int enable)
|
||||
{
|
||||
@@ -386,6 +419,11 @@ static void omap2_mcspi_rx_callback(void *data)
|
||||
/* We must disable the DMA RX request */
|
||||
omap2_mcspi_set_dma_req(spi, 1, 0);
|
||||
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
if (spi->dev.driver == &kbus_driver.driver)
|
||||
trace_pxc_kbus(__func__, "DMA: RX completed!");
|
||||
#endif
|
||||
|
||||
complete(&mcspi_dma->dma_rx_completion);
|
||||
}
|
||||
|
||||
@@ -398,6 +436,11 @@ static void omap2_mcspi_tx_callback(void *data)
|
||||
/* We must disable the DMA TX request */
|
||||
omap2_mcspi_set_dma_req(spi, 0, 0);
|
||||
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
if (spi->dev.driver == &kbus_driver.driver)
|
||||
trace_pxc_kbus(__func__, "DMA: TX completed!");
|
||||
#endif
|
||||
|
||||
complete(&mcspi_dma->dma_tx_completion);
|
||||
}
|
||||
|
||||
@@ -522,6 +565,11 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
if (spi->dev.driver == &kbus_driver.driver)
|
||||
if (xfer->rx_buf && ((char *) xfer->rx_buf)[96-1] == 0x66)
|
||||
trace_pxc_kbus(__func__, "DMA: RX Data MATCH (0x66)");
|
||||
#endif
|
||||
for (x = 0; x < nb_sizes; x++)
|
||||
kfree(sg_out[x]);
|
||||
|
||||
@@ -592,6 +640,12 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
|
||||
void __iomem *irqstat_reg;
|
||||
int wait_res;
|
||||
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
trace_pxc_kbus(__func__, "enter");
|
||||
|
||||
kbus_boost_dma_task(1);
|
||||
#endif
|
||||
|
||||
mcspi = spi_controller_get_devdata(spi->controller);
|
||||
mcspi_dma = &mcspi->dma_channels[spi_get_chipselect(spi, 0)];
|
||||
|
||||
@@ -682,6 +736,11 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
|
||||
dev_err(&spi->dev, "EOT timed out\n");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
trace_pxc_kbus(__func__, "leave");
|
||||
#endif
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -696,11 +755,20 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
|
||||
void __iomem *rx_reg;
|
||||
void __iomem *chstat_reg;
|
||||
int word_len;
|
||||
struct omap2_mcspi_device_config *cd;
|
||||
|
||||
cd = spi->controller_data;
|
||||
count = xfer->len;
|
||||
c = count;
|
||||
word_len = cs->word_len;
|
||||
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
trace_pxc_kbus(__func__, "enter");
|
||||
kbus_dbg("%s[%d]: count: %d\n", __func__,__LINE__, count);
|
||||
|
||||
kbus_boost_dma_task(0);
|
||||
#endif
|
||||
|
||||
l = mcspi_cached_chconf0(spi);
|
||||
|
||||
/* We store the pre-calculated register addresses on stack to speed
|
||||
@@ -712,6 +780,10 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
|
||||
if (c < (word_len>>3))
|
||||
return 0;
|
||||
|
||||
dev_dbg(&spi->dev, "xx: %s-%d %d %s:%s\n", xfer->tx_buf ? "tx" : "rx",
|
||||
word_len, count, cd->turbo_mode ? "turbo" : "-",
|
||||
(l & OMAP2_MCSPI_CHCONF_TURBO) ? "1" : "-");
|
||||
|
||||
if (word_len <= 8) {
|
||||
u8 *rx;
|
||||
const u8 *tx;
|
||||
@@ -722,6 +794,9 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
|
||||
do {
|
||||
c -= 1;
|
||||
if (tx != NULL) {
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
kbus_wago_mpoint(); /* MX */
|
||||
#endif
|
||||
if (mcspi_wait_for_reg_bit(chstat_reg,
|
||||
OMAP2_MCSPI_CHSTAT_TXS) < 0) {
|
||||
dev_err(&spi->dev, "TXS timed out\n");
|
||||
@@ -729,9 +804,15 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
|
||||
}
|
||||
dev_vdbg(&spi->dev, "write-%d %02x\n",
|
||||
word_len, *tx);
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
trace_pxc_kbusdump(__func__, "write", word_len, *tx);
|
||||
#endif
|
||||
writel_relaxed(*tx++, tx_reg);
|
||||
}
|
||||
if (rx != NULL) {
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
kbus_wago_mpoint(); /* MX */
|
||||
#endif
|
||||
if (mcspi_wait_for_reg_bit(chstat_reg,
|
||||
OMAP2_MCSPI_CHSTAT_RXS) < 0) {
|
||||
dev_err(&spi->dev, "RXS timed out\n");
|
||||
@@ -744,6 +825,9 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
|
||||
*rx++ = readl_relaxed(rx_reg);
|
||||
dev_vdbg(&spi->dev, "read-%d %02x\n",
|
||||
word_len, *(rx - 1));
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
trace_pxc_kbusdump(__func__, "readtb", word_len, *(rx - 1));
|
||||
#endif
|
||||
if (mcspi_wait_for_reg_bit(chstat_reg,
|
||||
OMAP2_MCSPI_CHSTAT_RXS) < 0) {
|
||||
dev_err(&spi->dev,
|
||||
@@ -756,8 +840,14 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
|
||||
}
|
||||
|
||||
*rx++ = readl_relaxed(rx_reg);
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
kbus_wago_mpoint(); /* MX */
|
||||
#endif
|
||||
dev_vdbg(&spi->dev, "read-%d %02x\n",
|
||||
word_len, *(rx - 1));
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
trace_pxc_kbusdump(__func__, "read", word_len, *(rx - 1));
|
||||
#endif
|
||||
}
|
||||
/* Add word delay between each word */
|
||||
spi_delay_exec(&xfer->word_delay, xfer);
|
||||
@@ -768,22 +858,34 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
|
||||
|
||||
rx = xfer->rx_buf;
|
||||
tx = xfer->tx_buf;
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
kbus_wago_mpoint(); /* MX */
|
||||
#endif
|
||||
do {
|
||||
c -= 2;
|
||||
if (tx != NULL) {
|
||||
if (mcspi_wait_for_reg_bit(chstat_reg,
|
||||
OMAP2_MCSPI_CHSTAT_TXS) < 0) {
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
trace_pxc_kbus(__func__, "TXS timed out");
|
||||
#endif
|
||||
dev_err(&spi->dev, "TXS timed out\n");
|
||||
goto out;
|
||||
}
|
||||
dev_vdbg(&spi->dev, "write-%d %04x\n",
|
||||
word_len, *tx);
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
trace_pxc_kbusdump(__func__, "write", word_len, *tx);
|
||||
#endif
|
||||
writel_relaxed(*tx++, tx_reg);
|
||||
}
|
||||
if (rx != NULL) {
|
||||
if (mcspi_wait_for_reg_bit(chstat_reg,
|
||||
OMAP2_MCSPI_CHSTAT_RXS) < 0) {
|
||||
dev_err(&spi->dev, "RXS timed out\n");
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
trace_pxc_kbus(__func__, "RXS timed out");
|
||||
#endif
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -793,6 +895,9 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
|
||||
*rx++ = readl_relaxed(rx_reg);
|
||||
dev_vdbg(&spi->dev, "read-%d %04x\n",
|
||||
word_len, *(rx - 1));
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
trace_pxc_kbusdump(__func__, "readtb", word_len, *(rx - 1));
|
||||
#endif
|
||||
if (mcspi_wait_for_reg_bit(chstat_reg,
|
||||
OMAP2_MCSPI_CHSTAT_RXS) < 0) {
|
||||
dev_err(&spi->dev,
|
||||
@@ -804,13 +909,30 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
|
||||
omap2_mcspi_set_enable(spi, 0);
|
||||
}
|
||||
|
||||
/* INFO:
|
||||
* We have a timing problem here!!!
|
||||
* During extensive spi traffic some bytes were lost
|
||||
* during read. Some tests also showed that the Infineon
|
||||
* needs some more time between the spi words.
|
||||
*/
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
if (kbusdelay)
|
||||
ndelay(kbusdelay); /* 400: With this delay we did a test over 14h successfully! */
|
||||
#endif
|
||||
|
||||
*rx++ = readl_relaxed(rx_reg);
|
||||
dev_vdbg(&spi->dev, "read-%d %04x\n",
|
||||
word_len, *(rx - 1));
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
trace_pxc_kbusdump(__func__, "read", word_len, *(rx - 1));
|
||||
#endif
|
||||
}
|
||||
/* Add word delay between each word */
|
||||
spi_delay_exec(&xfer->word_delay, xfer);
|
||||
} while (c >= 2);
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
kbus_wago_mpoint(); /* MX */
|
||||
#endif
|
||||
} else if (word_len <= 32) {
|
||||
u32 *rx;
|
||||
const u32 *tx;
|
||||
@@ -840,6 +962,14 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
|
||||
(l & OMAP2_MCSPI_CHCONF_TURBO)) {
|
||||
omap2_mcspi_set_enable(spi, 0);
|
||||
*rx++ = readl_relaxed(rx_reg);
|
||||
|
||||
/* For some reason while beeing in
|
||||
* turbo mode we need a short delay
|
||||
* here. Otherwise it will hang if we
|
||||
* try to disable and enable
|
||||
* turbo mode again */
|
||||
ndelay(1);
|
||||
|
||||
dev_vdbg(&spi->dev, "read-%d %08x\n",
|
||||
word_len, *(rx - 1));
|
||||
if (mcspi_wait_for_reg_bit(chstat_reg,
|
||||
@@ -879,6 +1009,10 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
|
||||
}
|
||||
out:
|
||||
omap2_mcspi_set_enable(spi, 1);
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
kbus_wago_mpoint(); /* MX */
|
||||
trace_pxc_kbus(__func__, "leave");
|
||||
#endif
|
||||
return count - c;
|
||||
}
|
||||
|
||||
@@ -936,6 +1070,9 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
|
||||
l &= ~OMAP2_MCSPI_CHCONF_IS;
|
||||
l &= ~OMAP2_MCSPI_CHCONF_DPE1;
|
||||
l |= OMAP2_MCSPI_CHCONF_DPE0;
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_SET_SPIDAT_DIR
|
||||
omap2_mcspi_set_spidat_direction(spi->master);
|
||||
#endif
|
||||
} else {
|
||||
l |= OMAP2_MCSPI_CHCONF_IS;
|
||||
l |= OMAP2_MCSPI_CHCONF_DPE1;
|
||||
@@ -1061,6 +1198,12 @@ static int omap2_mcspi_setup(struct spi_device *spi)
|
||||
struct omap2_mcspi_regs *ctx = &mcspi->ctx;
|
||||
struct omap2_mcspi_cs *cs = spi->controller_state;
|
||||
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
if (spi->max_speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15) ||
|
||||
spi->max_speed_hz > OMAP2_MCSPI_MAX_FREQ)
|
||||
return -EINVAL;
|
||||
#endif
|
||||
|
||||
if (!cs) {
|
||||
cs = kzalloc(sizeof(*cs), GFP_KERNEL);
|
||||
if (!cs)
|
||||
@@ -1140,15 +1283,29 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr,
|
||||
struct omap2_mcspi_dma *mcspi_dma;
|
||||
struct omap2_mcspi_cs *cs;
|
||||
struct omap2_mcspi_device_config *cd;
|
||||
int par_override = 0;
|
||||
#ifndef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
int par_override = 0;
|
||||
#endif
|
||||
int status = 0;
|
||||
u32 chconf;
|
||||
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
struct kbus_drv_data *kdrvdata = NULL;
|
||||
|
||||
trace_pxc_kbus(__func__, "enter");
|
||||
kbus_wago_mpoint(); /* M4 */
|
||||
#endif
|
||||
|
||||
mcspi = spi_controller_get_devdata(ctlr);
|
||||
mcspi_dma = mcspi->dma_channels + spi_get_chipselect(spi, 0);
|
||||
cs = spi->controller_state;
|
||||
cd = spi->controller_data;
|
||||
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
if (spi->dev.driver == &kbus_driver.driver)
|
||||
kdrvdata = spi_get_drvdata(spi);
|
||||
#endif
|
||||
#ifndef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
/*
|
||||
* The target driver could have changed spi->mode in which case
|
||||
* it will be different from cs->mode (the current hardware setup).
|
||||
@@ -1158,12 +1315,14 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr,
|
||||
*/
|
||||
if (spi->mode != cs->mode)
|
||||
par_override = 1;
|
||||
#endif
|
||||
|
||||
omap2_mcspi_set_enable(spi, 0);
|
||||
|
||||
if (spi_get_csgpiod(spi, 0))
|
||||
omap2_mcspi_set_cs(spi, spi->mode & SPI_CS_HIGH);
|
||||
|
||||
#ifndef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
if (par_override ||
|
||||
(t->speed_hz != spi->max_speed_hz) ||
|
||||
(t->bits_per_word != spi->bits_per_word)) {
|
||||
@@ -1175,6 +1334,8 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr,
|
||||
t->bits_per_word == spi->bits_per_word)
|
||||
par_override = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cd && cd->cs_per_word) {
|
||||
chconf = mcspi->ctx.modulctrl;
|
||||
chconf &= ~OMAP2_MCSPI_MODULCTRL_SINGLE;
|
||||
@@ -1202,11 +1363,19 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr,
|
||||
|
||||
if (t->len) {
|
||||
unsigned count;
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
int i;
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
/* FIXME
|
||||
At this moment keep fifo disabled due to some issues
|
||||
that were coming up with large kbus nodes. */
|
||||
if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
|
||||
ctlr->cur_msg_mapped &&
|
||||
ctlr->can_dma(ctlr, spi, t))
|
||||
omap2_mcspi_set_fifo(spi, t, 1);
|
||||
#endif
|
||||
|
||||
omap2_mcspi_set_enable(spi, 1);
|
||||
|
||||
@@ -1215,10 +1384,47 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr,
|
||||
writel_relaxed(0, cs->base
|
||||
+ OMAP2_MCSPI_TX0);
|
||||
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
/*
|
||||
* kbus:
|
||||
* release irq and check the sync signal
|
||||
* before sending data
|
||||
*/
|
||||
if (kdrvdata && t->tx_buf) {
|
||||
/*
|
||||
* XE164 should be ready a long time ago (several us).
|
||||
* Otherwise something is wrong with the controller!
|
||||
*/
|
||||
for (i = 0; i < PAC_KBUS_SYNC_CYCLES; i++) {
|
||||
if (gpiod_get_value(kdrvdata->gpio_nsync)) /* active low */
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= PAC_KBUS_SYNC_CYCLES) {
|
||||
trace_pxc_kbus(__func__, "err: sync pin is always high [-EBUSY(-16)]!");
|
||||
status = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* release the irq pin */
|
||||
gpiod_set_value(kdrvdata->gpio_nirq, 1);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
|
||||
ctlr->cur_msg_mapped &&
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
ctlr->can_dma(ctlr, spi, t)) {
|
||||
if (kdrvdata)
|
||||
trace_pxc_kbus(__func__, "DMA: TXRX: Trigger DMA Transfer.");
|
||||
#endif
|
||||
#ifndef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
ctlr->can_dma(ctlr, spi, t))
|
||||
#endif
|
||||
count = omap2_mcspi_txrx_dma(spi, t);
|
||||
}
|
||||
else
|
||||
count = omap2_mcspi_txrx_pio(spi, t);
|
||||
|
||||
@@ -1233,12 +1439,97 @@ static int omap2_mcspi_transfer_one(struct spi_controller *ctlr,
|
||||
if (mcspi->fifo_depth > 0)
|
||||
omap2_mcspi_set_fifo(spi, t, 0);
|
||||
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
/*
|
||||
* Special KBUS Treatment
|
||||
*
|
||||
*/
|
||||
if (kdrvdata) {
|
||||
static u16 *kcmd_txbuf;
|
||||
int tmp_ret;
|
||||
|
||||
kbus_wago_mpoint(); /* MX */
|
||||
if (t->tx_buf) { /* after tx transfer */
|
||||
kcmd_txbuf = (u16 *) t->tx_buf;
|
||||
/* wait for READYn IRQ from xe164 */
|
||||
|
||||
trace_pxc_kbus(__func__, "TX0");
|
||||
kbus_dbg("%s: irq timeout is %dms\n",
|
||||
__func__, kdrvdata->timeout_ms);
|
||||
tmp_ret = wait_event_interruptible_timeout(kdrvdata->kbus_irq_wq,
|
||||
kdrvdata->kbus_irq_state == 0,
|
||||
msecs_to_jiffies(kdrvdata->timeout_ms));
|
||||
|
||||
if (tmp_ret == 0 && kdrvdata->kbus_irq_state) {
|
||||
status = -ETIMEDOUT;
|
||||
trace_pxc_kbus(__func__, "TX0: IRQ timeout!");
|
||||
goto out;
|
||||
}
|
||||
if (kbus_error() < 0) {
|
||||
status = -ENODATA;
|
||||
trace_pxc_kbus(__func__, "TX0: KBUS ERROR.");
|
||||
goto out;
|
||||
}
|
||||
trace_pxc_kbus(__func__, "TX0: IRQ received");
|
||||
}
|
||||
|
||||
if (kdrvdata->cmdsel) { /* special treatment in command mode */
|
||||
/* We're getting the data in two nibbles.
|
||||
* First: 6 bytes header where we get the length for the rest.
|
||||
* Second: The remaining N bytes.
|
||||
*/
|
||||
if (t->rx_buf == kdrvdata->rx_buf) { /* This RX0 */
|
||||
u16 *kcmd_hdr = (u16 *) t->rx_buf;
|
||||
u8 lb_cmd = kcmd_hdr[0] & 0xff;
|
||||
u8 hb_cmd_inv = ~(kcmd_hdr[0] >> 8) & 0xff;
|
||||
u8 lb_wlen = kcmd_hdr[2] & 0xff;
|
||||
u8 hb_wlen_inv = ~(kcmd_hdr[2] >> 8) & 0xff;
|
||||
unsigned int byte_len;
|
||||
struct spi_transfer *kcmd_tnext;
|
||||
|
||||
trace_pxc_kbus(__func__, "RX0");
|
||||
|
||||
/* validate header data here */
|
||||
if (lb_cmd != (kcmd_txbuf[0] & 0xff) ||
|
||||
hb_cmd_inv != lb_cmd ||
|
||||
hb_wlen_inv != lb_wlen) {
|
||||
trace_pxc_kbus(__func__, "RX0: RX0 HDR not valid.");
|
||||
kbus_dbg("%s[%d]: RX0 HDR not valid: 0x%.4x(TX:0x%.2x)|0x%.4x|0x%.4x\n",
|
||||
__func__, __LINE__, kcmd_hdr[0], kcmd_txbuf[0] & 0xff,
|
||||
kcmd_hdr[1], kcmd_hdr[2]);
|
||||
status = -EPROTO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* get next transfer entry */
|
||||
kcmd_tnext = list_entry(t->transfer_list.next,
|
||||
struct spi_transfer, transfer_list);
|
||||
|
||||
/* regard word (16bit) count */
|
||||
byte_len = (kcmd_hdr[2] & 0xff) << 1;
|
||||
if (byte_len < kcmd_tnext->len) {
|
||||
kcmd_tnext->len = byte_len;
|
||||
trace_pxc_kbus(__func__, "RX0: RX1 len updated.");
|
||||
}
|
||||
|
||||
kbus_dbg("%s[%d]: RX1 len set to: %d\n",
|
||||
__func__, __LINE__, kcmd_tnext->len);
|
||||
} else if (t->rx_buf != NULL) {
|
||||
trace_pxc_kbus(__func__, "RX1");
|
||||
}
|
||||
}
|
||||
kbus_wago_mpoint(); /* MX */
|
||||
}
|
||||
#endif
|
||||
|
||||
out:
|
||||
#ifndef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
/* Restore defaults if they were overriden */
|
||||
if (par_override) {
|
||||
par_override = 0;
|
||||
status = omap2_mcspi_setup_transfer(spi, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cd && cd->cs_per_word) {
|
||||
chconf = mcspi->ctx.modulctrl;
|
||||
@@ -1540,6 +1831,16 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
|
||||
if (status < 0)
|
||||
goto disable_pm;
|
||||
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
dev_dbg(&pdev->dev, "kbusdelay=%d, %s interframe gap delay.\n",
|
||||
kbusdelay, kbusdelay ? "using" : "NOT using");
|
||||
#endif
|
||||
|
||||
#if 0 /* #ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION */
|
||||
if (omap2_mcspi_enable_clocks(mcspi) < 0)
|
||||
goto free_master;
|
||||
#endif
|
||||
|
||||
return status;
|
||||
|
||||
disable_pm:
|
||||
@@ -1618,4 +1919,7 @@ static struct platform_driver omap2_mcspi_driver = {
|
||||
};
|
||||
|
||||
module_platform_driver(omap2_mcspi_driver);
|
||||
#ifdef CONFIG_SPI_KBUS_OMAP_EXTENSION
|
||||
core_param(kbusdelay, kbusdelay, int, 0000);
|
||||
#endif
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* include/linux/spi/kbus.h
|
||||
*
|
||||
* Copyright (C) 2020 WAGO
|
||||
* Heinrich Toews <heinrich.toews@wago.com>
|
||||
*/
|
||||
|
||||
#ifndef KBUS_H
|
||||
#define KBUS_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define KBUS_DRIVER_MAJOR 240
|
||||
#define KBUS_IRQ_TIMEOUT 10 /* wait for a max. of 10 ms */
|
||||
|
||||
#define KBUS__DEFAULT_SPEED 12000000
|
||||
#define KBUS_READYN_IRQ
|
||||
#define KBUS_DATA_FULLDPX
|
||||
|
||||
#undef KBUS__WAIT_ACTIVE
|
||||
#undef KBUS_IRQN_IRQ
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#define PAC_KBUS_SYNC_CYCLES 3
|
||||
#define SPI_MODE_MASK \
|
||||
(SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST | SPI_3WIRE | \
|
||||
SPI_LOOP | SPI_NO_CS | SPI_READY)
|
||||
|
||||
#define KBUS__MAX_BUF_LEN PAGE_SIZE /* FIXME */
|
||||
|
||||
#define KBUS_TESTING 0 /* enable when gpio testing wanted */
|
||||
|
||||
#define KBUS__USE_DMA_ONLY 0
|
||||
|
||||
#if KBUS_TESTING
|
||||
#define kbus_wago_mpoint(k) wago_mpoint()
|
||||
#define kbus_dbg(format, arg...) pr_debug("kbus-dbg:" format, ##arg)
|
||||
#else
|
||||
#define kbus_wago_mpoint(k) \
|
||||
({ \
|
||||
if (0) \
|
||||
wago_mpoint(); \
|
||||
0; \
|
||||
})
|
||||
#define kbus_dbg(format, arg...) \
|
||||
({ \
|
||||
if (0) \
|
||||
pr_debug("kbus-dbg:" format, ##arg); \
|
||||
0; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#define KBUS_ENABLE_IRQ(irq) \
|
||||
do { \
|
||||
if (irq != -1) \
|
||||
enable_irq(irq); \
|
||||
} while (0)
|
||||
|
||||
#define KBUS_DISABLE_IRQ(irq) \
|
||||
do { \
|
||||
if (irq != -1) \
|
||||
disable_irq(irq); \
|
||||
} while (0)
|
||||
|
||||
struct kbus_drv_data {
|
||||
u8 cmdsel; /* 0: data, 1: cmd mode */
|
||||
int kbus_err;
|
||||
int kbus_err_state;
|
||||
u8 *tx_buf;
|
||||
u8 *rx_buf;
|
||||
bool use_dma;
|
||||
u32 timeout_ms;
|
||||
dma_addr_t tx_buf_dma;
|
||||
dma_addr_t rx_buf_dma;
|
||||
int kbus_irq;
|
||||
int kbus_irq_enabled;
|
||||
int kbus_irq_state;
|
||||
struct task_struct
|
||||
*dma_task; /* task pointer to boost the dma task if necessary */
|
||||
bool kbus_dma_boost_en;
|
||||
u8 kbus_dma_boost_prio;
|
||||
const char *kbus_dma_boost_irq_thread;
|
||||
u8 kbus_dma_normal_prio;
|
||||
|
||||
/* gpios */
|
||||
struct gpio_desc *gpio_nrdy;
|
||||
struct gpio_desc *gpio_nrst;
|
||||
struct gpio_desc *gpio_nsync;
|
||||
struct gpio_desc *gpio_cmdsel;
|
||||
struct gpio_desc *gpio_nirq;
|
||||
struct gpio_desc *gpio_nerr;
|
||||
|
||||
wait_queue_head_t kbus_irq_wq;
|
||||
struct spi_device *spi;
|
||||
const char *kbus_tty_device_name;
|
||||
};
|
||||
|
||||
/* For userspace ioctl communication */
|
||||
struct kbus_data {
|
||||
__u8 __user *tx_buf;
|
||||
__u8 __user *rx_buf;
|
||||
__u32 byte_len;
|
||||
__u8 __user *err; /* will only be set when err occurs! */
|
||||
__u8 __user *err_state;
|
||||
__u32 timeout_ms;
|
||||
};
|
||||
|
||||
struct kbus_cmd {
|
||||
__u8 __user *tx_buf;
|
||||
__u8 __user *rx_buf;
|
||||
__u32 byte_len_tx;
|
||||
__u32 byte_len_rx;
|
||||
__u8 __user *err; /* will only be set when err occurs! */
|
||||
__u8 __user *err_state;
|
||||
__u32 timeout_ms;
|
||||
};
|
||||
|
||||
struct kbus_spi_config {
|
||||
__u8 bits_per_word; /* bits_per_word */
|
||||
__u8 mode; /* see SPI_ mode bits in spi.h */
|
||||
__u32 max_speed_hz;
|
||||
};
|
||||
|
||||
extern int kbus_wait_for_irq(void);
|
||||
extern int kbus_wait_for_event(int *event);
|
||||
extern int kbus_error(void);
|
||||
extern int kbus_wait_for_gpio(int gpio);
|
||||
extern void kbus_boost_dma_task(u8 enable);
|
||||
|
||||
/* IOCTL commands */
|
||||
#define KBUS_IOC_MAGIC 'K'
|
||||
#define KBUS_IOC_DATA _IOW(KBUS_IOC_MAGIC, 1, struct kbus_data)
|
||||
#define KBUS_IOC_CMD _IOW(KBUS_IOC_MAGIC, 2, struct kbus_cmd)
|
||||
#define KBUS_IOC_CONFIG _IOW(KBUS_IOC_MAGIC, 3, struct kbus_spi_config)
|
||||
#define KBUS_IOC_BINARY _IOW(KBUS_IOC_MAGIC, 4, struct kbus_data)
|
||||
|
||||
extern struct spi_driver
|
||||
kbus_driver; /* used by spi-omap2-mcspi to recognize the kbus device */
|
||||
|
||||
#endif /* KBUS_H */
|
||||
@@ -0,0 +1,40 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2014 WAGO GmbH & Co. KG
|
||||
*
|
||||
* Author: Heinrich Toews <heinrich.toews@wago.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _WAGO_TESTS_H_
|
||||
#define _WAGO_TESTS_H_
|
||||
|
||||
#define WAGO_TEST_DEBUG
|
||||
|
||||
#ifdef WAGO_TEST_DEBUG
|
||||
#define pac_kdebug(format, arg...) \
|
||||
printk(KERN_INFO "pac-kdebug: " format , ## arg)
|
||||
#else
|
||||
#define pac_kdebug(format, arg...) \
|
||||
({ if (0) printk(KERN_INFO "pac-kdebug: " format , ## arg); 0; })
|
||||
#endif
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/time.h>
|
||||
|
||||
#define WAGO_TEST__MAX_MEASUREMENTS 20
|
||||
#define WAGO_TEST__GPIO 175 /* FB-nINT_GPIO175 */
|
||||
|
||||
struct wago_trace_data {
|
||||
struct timespec64 mpoints[WAGO_TEST__MAX_MEASUREMENTS];
|
||||
int mpoint_index;
|
||||
};
|
||||
|
||||
extern void wago_tests_init(struct wago_trace_data *tdata, u8 gpios_enable);
|
||||
extern void wago_tests_deinit(void);
|
||||
extern void wago_measure_reset(void);
|
||||
extern void wago_mpoint(void);
|
||||
|
||||
#endif /* _WAGO_TESTS_H_ */
|
||||
@@ -0,0 +1,377 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2015 WAGO GmbH & Co. KG
|
||||
*
|
||||
* Author: Heinrich Toews <heinrich.toews@wago.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM pxc
|
||||
|
||||
#if !defined(_TRACE_PXC_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _TRACE_PXC_H
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
#ifdef PFC_CLOCK_TRACER
|
||||
TRACE_EVENT(pfc_clock, /* trace pfc clock events */
|
||||
|
||||
TP_PROTO(cycle_t cycle_now, cycle_t cycle_delta, struct timekeeper *tk, s64 nsec, char *msg),
|
||||
|
||||
TP_ARGS(cycle_now, cycle_delta, tk, nsec, msg),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(cycle_t, cycle_now)
|
||||
__field(cycle_t, cycle_delta)
|
||||
__field(s64, nsec)
|
||||
__field(u32, mult)
|
||||
__field(u32, shift)
|
||||
__field(u64, xtime_nsec)
|
||||
__array(char, msg, 128)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->cycle_now = cycle_now;
|
||||
__entry->cycle_delta = cycle_delta;
|
||||
__entry->nsec = nsec;
|
||||
__entry->mult = tk->mult;
|
||||
__entry->shift = tk->shift;
|
||||
__entry->xtime_nsec = tk->xtime_nsec;
|
||||
strncpy( __entry->msg, msg, 128);
|
||||
),
|
||||
|
||||
TP_printk("%llu d:%llu->%lli|%u|%u|%llu|%s",
|
||||
__entry->cycle_now, __entry->cycle_delta, __entry->nsec,
|
||||
__entry->mult, __entry->shift, __entry->xtime_nsec,
|
||||
__entry->msg)
|
||||
);
|
||||
#endif
|
||||
|
||||
#if defined(PXC_ETH_EMAC)
|
||||
TRACE_EVENT(pxc_eth_emac, /* trace davinci_emac events */
|
||||
|
||||
TP_PROTO(struct emac_priv *priv, char *msg),
|
||||
|
||||
TP_ARGS(priv, msg),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned, link)
|
||||
__field(unsigned, speed)
|
||||
__field(unsigned, duplex)
|
||||
__array(char, phy_id, 32)
|
||||
__array(char, other_phy_id, 32)
|
||||
__array(char, msg, 128)
|
||||
__array(char, devname, 64)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->link = priv->link;
|
||||
__entry->speed = priv->speed;
|
||||
__entry->duplex = priv->duplex;
|
||||
strncpy( __entry->phy_id, priv->phy_id, 32);
|
||||
strncpy(__entry->other_phy_id, priv->other_phy_id, 32);
|
||||
strncpy( __entry->msg, msg, 128);
|
||||
if (priv->ndev)
|
||||
strncpy(__entry->devname, priv->ndev->name, 64);
|
||||
),
|
||||
|
||||
TP_printk("%6s 1-%s 2-%s: %4s|%d/%4s %s", __entry->devname, __entry->phy_id, __entry->other_phy_id,
|
||||
__entry->link ? "UP" : "DOWN", __entry->speed, __entry->duplex == 1 ? "Full" : "Half",
|
||||
__entry->msg)
|
||||
);
|
||||
|
||||
TRACE_EVENT(pxc_eth_emac_phy, /* trace phy events */
|
||||
|
||||
TP_PROTO(struct phy_device *phydev, char *msg),
|
||||
|
||||
TP_ARGS(phydev, msg),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__array(char, msg, 128)
|
||||
__array(char, phyname, 16)
|
||||
__field(int, link)
|
||||
__field(int, speed)
|
||||
__field(int, duplex) /* DUPLEX_HALF=0, DUPLEX_FULL=1 */
|
||||
__field(int, state)
|
||||
__field(int, irq)
|
||||
__array(char, devname, 64)
|
||||
__field(u32, dev_flags)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
if (phydev->attached_dev)
|
||||
strncpy(__entry->devname, phydev->attached_dev->name, 64);
|
||||
strncpy(__entry->msg, msg, 128);
|
||||
strncpy(__entry->phyname, dev_name(&phydev->dev), 16);
|
||||
__entry->link = phydev->link;
|
||||
__entry->speed = phydev->speed;
|
||||
__entry->duplex = phydev->duplex;
|
||||
__entry->state = phydev->state;
|
||||
__entry->irq = phydev->irq;
|
||||
__entry->dev_flags = phydev->dev_flags;
|
||||
),
|
||||
|
||||
TP_printk("%6s(%s) %4s|%d/%4s|%d|%d|%u %s", __entry->devname, __entry->phyname,
|
||||
__entry->link ? "UP" : "DOWN", __entry->speed, __entry->duplex == 1 ? "Full" : "Half",
|
||||
__entry->state, __entry->irq, __entry->dev_flags, __entry->msg)
|
||||
);
|
||||
#endif
|
||||
|
||||
#if defined(PXC_SPI_TRACER)
|
||||
TRACE_EVENT(pxc_spi, /* trace mcspi events */
|
||||
|
||||
TP_PROTO(char *msg, const char *func, int data),
|
||||
|
||||
TP_ARGS(msg, func, data),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__array(char, msg, 128)
|
||||
__array(char, func, 32)
|
||||
__field(int, data)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
strncpy( __entry->msg, msg, 128);
|
||||
strncpy( __entry->func, func, 32);
|
||||
__entry->data = data;
|
||||
),
|
||||
|
||||
TP_printk("%s[%d]: %s", __entry->func, __entry->data, __entry->msg)
|
||||
);
|
||||
|
||||
TRACE_EVENT(pxc_spi_measure_a, /* trace mcspi events */
|
||||
|
||||
TP_PROTO(char *msg, struct wago_trace_data *tdata),
|
||||
|
||||
TP_ARGS(msg, tdata),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__array(char, msg, 128)
|
||||
__field(unsigned int, completion_delay)
|
||||
__field(unsigned int, completion_delay_work)
|
||||
__field(unsigned int, async_delay)
|
||||
__field(unsigned int, enqueue_delay)
|
||||
__field(unsigned int, work_delay)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
strncpy( __entry->msg, msg, 128);
|
||||
if (tdata->mpoint_index > 5) {
|
||||
__entry->completion_delay = tdata->mpoints[5].tv_nsec - tdata->mpoints[1].tv_nsec;
|
||||
__entry->completion_delay_work = tdata->mpoints[4].tv_nsec - tdata->mpoints[2].tv_nsec;
|
||||
__entry->async_delay = tdata->mpoints[1].tv_nsec - tdata->mpoints[0].tv_nsec;
|
||||
__entry->enqueue_delay = tdata->mpoints[2].tv_nsec - tdata->mpoints[1].tv_nsec;
|
||||
__entry->work_delay = tdata->mpoints[3].tv_nsec - tdata->mpoints[2].tv_nsec;
|
||||
}
|
||||
),
|
||||
|
||||
TP_printk("%s: completion_delay=%u, completion_delay_work=%u, async_delay=%u, enqueue_delay=%u, work_delay=%u",
|
||||
__entry->msg, __entry->completion_delay, __entry->completion_delay_work,
|
||||
__entry->async_delay, __entry->enqueue_delay, __entry->work_delay)
|
||||
);
|
||||
|
||||
TRACE_EVENT(pxc_spi_measure_b, /* trace mcspi events */
|
||||
|
||||
TP_PROTO(char *msg, struct wago_trace_data *tdata),
|
||||
|
||||
TP_ARGS(msg, tdata),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__array(char, msg, 128)
|
||||
__field(unsigned int, completion_delay)
|
||||
__field(unsigned int, completion_delay_work)
|
||||
__field(unsigned int, async_delay)
|
||||
__field(unsigned int, enqueue_delay)
|
||||
__field(unsigned int, work_delay)
|
||||
__field(unsigned int, delay1)
|
||||
__field(unsigned int, delay2)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
strncpy( __entry->msg, msg, 128);
|
||||
if (tdata->mpoint_index > 8) {
|
||||
__entry->completion_delay = tdata->mpoints[7].tv_nsec - tdata->mpoints[2].tv_nsec;
|
||||
__entry->completion_delay_work = tdata->mpoints[6].tv_nsec - tdata->mpoints[4].tv_nsec;
|
||||
__entry->async_delay = tdata->mpoints[2].tv_nsec - tdata->mpoints[1].tv_nsec;
|
||||
__entry->enqueue_delay = tdata->mpoints[4].tv_nsec - tdata->mpoints[2].tv_nsec;
|
||||
__entry->work_delay = tdata->mpoints[5].tv_nsec - tdata->mpoints[4].tv_nsec;
|
||||
__entry->delay1 = tdata->mpoints[7].tv_nsec - tdata->mpoints[1].tv_nsec;
|
||||
__entry->delay2 = tdata->mpoints[8].tv_nsec - tdata->mpoints[0].tv_nsec;
|
||||
}
|
||||
),
|
||||
|
||||
TP_printk("%s: completion_delay=%u, completion_delay_work=%u, async_delay=%u, enqueue_delay=%u, work_delay=%u, delay1=%u, delay2=%u",
|
||||
__entry->msg, __entry->completion_delay, __entry->completion_delay_work,
|
||||
__entry->async_delay, __entry->enqueue_delay, __entry->work_delay, __entry->delay1, __entry->delay2)
|
||||
);
|
||||
#endif /* PXC_SPI_TRACER */
|
||||
|
||||
#if defined(PXC_SPI_KBUS_TRACER)
|
||||
TRACE_EVENT(pxc_kbus, /* trace kbus events */
|
||||
|
||||
TP_PROTO(const char *func, char *msg),
|
||||
|
||||
TP_ARGS(func, msg),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__array(char, msg, 128)
|
||||
__array(char, func, 32)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
strncpy( __entry->msg, msg, 128);
|
||||
strncpy( __entry->func, func, 32);
|
||||
),
|
||||
|
||||
TP_printk("%s:%s", __entry->func, __entry->msg)
|
||||
);
|
||||
|
||||
TRACE_EVENT(pxc_kbusmsg, /* trace kbus events */
|
||||
|
||||
TP_PROTO(const char *func, struct spi_message *m, char *msg),
|
||||
|
||||
TP_ARGS(func, m, msg),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__array(char, msg, 128)
|
||||
__array(char, func, 32)
|
||||
__field(int, status)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
strncpy( __entry->msg, msg, 128);
|
||||
strncpy( __entry->func, func, 32);
|
||||
__entry->status = m->status;
|
||||
),
|
||||
|
||||
TP_printk("%s:%s m->status=%d", __entry->func, __entry->msg, __entry->status)
|
||||
);
|
||||
|
||||
TRACE_EVENT(pxc_kbusdump, /* trace kbus events */
|
||||
|
||||
TP_PROTO(const char *func, char *msg, int word_len, u16 word),
|
||||
|
||||
TP_ARGS(func, msg, word_len, word),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__array(char, func, 32)
|
||||
__array(char, msg, 128)
|
||||
__field( int, word_len)
|
||||
__field( u16, word)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
strncpy( __entry->func, func, 32);
|
||||
strncpy( __entry->msg, msg, 128);
|
||||
__entry->word_len = word_len;
|
||||
__entry->word = word;
|
||||
),
|
||||
|
||||
TP_printk("%s:%s-%d 0x%x", __entry->func, __entry->msg, __entry->word_len, __entry->word) /* 0x%04x */
|
||||
);
|
||||
|
||||
TRACE_EVENT(pxc_buf32,
|
||||
|
||||
TP_PROTO(const char *prefix, char *in_buf, int len, int offs),
|
||||
|
||||
TP_ARGS(prefix, in_buf, len, offs),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__array(char, prefix, 32)
|
||||
__field(int, copy_len)
|
||||
__array(char, buf, 32)
|
||||
__field(char *, in_buf_p)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
strncpy(__entry->prefix, prefix, 32);
|
||||
if (len < 32)
|
||||
memset(__entry->buf, 0, 32);
|
||||
strncpy(__entry->buf, in_buf + offs, len > 32 ? 32 : len);
|
||||
__entry->copy_len = len;
|
||||
__entry->in_buf_p = in_buf;
|
||||
),
|
||||
|
||||
TP_printk("DATADUMP(%s) copylen %4d (in_buf_p %p) "
|
||||
"[%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x"
|
||||
"-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x"
|
||||
"-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x"
|
||||
"-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x]",
|
||||
__entry->prefix,
|
||||
__entry->copy_len,
|
||||
__entry->in_buf_p,
|
||||
__entry->buf[0], __entry->buf[1], __entry->buf[2], __entry->buf[3],
|
||||
__entry->buf[4], __entry->buf[5], __entry->buf[6], __entry->buf[7],
|
||||
__entry->buf[8], __entry->buf[9], __entry->buf[10], __entry->buf[11],
|
||||
__entry->buf[12], __entry->buf[13], __entry->buf[14], __entry->buf[15],
|
||||
__entry->buf[16], __entry->buf[17], __entry->buf[18], __entry->buf[19],
|
||||
__entry->buf[20], __entry->buf[21], __entry->buf[22], __entry->buf[23],
|
||||
__entry->buf[24], __entry->buf[25], __entry->buf[26], __entry->buf[27],
|
||||
__entry->buf[28], __entry->buf[29], __entry->buf[30], __entry->buf[31])
|
||||
);
|
||||
|
||||
TRACE_EVENT(pxc_kbus_mdata, /* trace kbus measurement events */
|
||||
|
||||
TP_PROTO(const char *func, char *msg, struct wago_trace_data *tdata),
|
||||
|
||||
TP_ARGS(func, msg, tdata),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__array(char, msg, 128)
|
||||
__array(char, func, 32)
|
||||
__field(unsigned int, delay1)
|
||||
__field(unsigned int, delay2)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
strncpy( __entry->msg, msg, 128);
|
||||
strncpy( __entry->func, func, 32);
|
||||
if (tdata->mpoint_index > 3) {
|
||||
__entry->delay1 = tdata->mpoints[3].tv_nsec - tdata->mpoints[0].tv_nsec;
|
||||
__entry->delay2 = tdata->mpoints[2].tv_nsec - tdata->mpoints[1].tv_nsec;
|
||||
}
|
||||
),
|
||||
|
||||
TP_printk("%s:%s delay1=%u delay2=%u", __entry->func, __entry->msg,
|
||||
__entry->delay1, __entry->delay2)
|
||||
);
|
||||
#endif /* PXC_SPI_KBUS_TRACER */
|
||||
|
||||
#if defined(PXC_CAN_TRACER)
|
||||
TRACE_EVENT(pxc_canpkt,
|
||||
|
||||
TP_PROTO(struct can_frame *canframe),
|
||||
|
||||
TP_ARGS(canframe),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(struct can_frame *, canframe)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->canframe = canframe;
|
||||
),
|
||||
|
||||
TP_printk("%s-0x%x: can_id=0x%x, len=%d, data:%.2x.%.2x.%.2x.%.2x.%.2x.%.2x.%.2x.%.2x",
|
||||
(__entry->canframe->can_id & CAN_ERR_FLAG) ? " err" : "data",
|
||||
__entry->canframe->can_id >> CAN_EFF_ID_BITS,
|
||||
__entry->canframe->can_id & CAN_ERR_MASK,
|
||||
__entry->canframe->can_dlc,
|
||||
__entry->canframe->data[0],
|
||||
__entry->canframe->data[1],
|
||||
__entry->canframe->data[2],
|
||||
__entry->canframe->data[3],
|
||||
__entry->canframe->data[4],
|
||||
__entry->canframe->data[5],
|
||||
__entry->canframe->data[6],
|
||||
__entry->canframe->data[7])
|
||||
);
|
||||
#endif /* PXC_CAN_TRACER */
|
||||
|
||||
#endif /* if !defined(_TRACE_PXC_H) || defined(TRACE_HEADER_MULTI_READ) */
|
||||
|
||||
/* This part must be outside protection */
|
||||
#include <trace/define_trace.h>
|
||||
Reference in New Issue
Block a user