Adds an sdhci-trace object file that is linked with the sdhci module. This will allow sdhci-core to call the trace functions. There weren't constants defined for some of the fields, so I just used the raw values. See the next change for usage. Signed-off-by: Raul E Rangel <rrangel@xxxxxxxxxxxx> --- drivers/mmc/host/Makefile | 5 +- drivers/mmc/host/sdhci-trace.c | 319 +++++++++++++++++++++++++++++++++ drivers/mmc/host/sdhci-trace.h | 93 ++++++++++ 3 files changed, 416 insertions(+), 1 deletion(-) create mode 100644 drivers/mmc/host/sdhci-trace.c create mode 100644 drivers/mmc/host/sdhci-trace.h diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 11174945c116..1cb695a3b359 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -3,6 +3,9 @@ # Makefile for MMC/SD host controller drivers # +# tell define_trace.h where to find the sdhci trace header +CFLAGS_sdhci-trace.o := -I$(src) + obj-$(CONFIG_MMC_ARMMMCI) += armmmci.o armmmci-y := mmci.o armmmci-$(CONFIG_MMC_QCOM_DML) += mmci_qcom_dml.o @@ -11,7 +14,7 @@ obj-$(CONFIG_MMC_PXA) += pxamci.o obj-$(CONFIG_MMC_MXC) += mxcmmc.o obj-$(CONFIG_MMC_MXS) += mxs-mmc.o obj-$(CONFIG_MMC_SDHCI) += sdhci.o -sdhci-objs += sdhci-core.o +sdhci-objs += sdhci-core.o sdhci-trace.o obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o sdhci-pci-y += sdhci-pci-core.o sdhci-pci-o2micro.o sdhci-pci-arasan.o \ sdhci-pci-dwc-mshc.o diff --git a/drivers/mmc/host/sdhci-trace.c b/drivers/mmc/host/sdhci-trace.c new file mode 100644 index 000000000000..a7d803470664 --- /dev/null +++ b/drivers/mmc/host/sdhci-trace.c @@ -0,0 +1,319 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright 2019 Google LLC. + +#include <linux/trace_events.h> +#include "sdhci.h" + +#define SDHCI_REGS \ + {SDHCI_DMA_ADDRESS, "DMA_ADDRESS"}, \ + {SDHCI_BLOCK_SIZE, "BLOCK_SIZE"}, \ + {SDHCI_ARGUMENT, "ARGUMENT"}, \ + {SDHCI_TRANSFER_MODE, "TRANSFER_MODE"}, \ + {SDHCI_RESPONSE, "RESP10"}, \ + {SDHCI_RESPONSE + 4, "RESP32"}, \ + {SDHCI_RESPONSE + 8, "RESP54"}, \ + {SDHCI_RESPONSE + 12, "RESP76"}, \ + {SDHCI_BUFFER, "BUFFER"}, \ + {SDHCI_PRESENT_STATE, "PRESENT_STATE"}, \ + {SDHCI_HOST_CONTROL, "HOST_CONTROL"}, \ + {SDHCI_CLOCK_CONTROL, "CLOCK_CONTROL"}, \ + {SDHCI_INT_STATUS, "INT_STATUS"}, \ + {SDHCI_INT_ENABLE, "INT_ENABLE"}, \ + {SDHCI_SIGNAL_ENABLE, "SIGNAL_ENABLE"}, \ + {SDHCI_ACMD12_ERR, "ACMD12_ERR"}, \ + {SDHCI_CAPABILITIES, "CAPABILITIES"}, \ + {SDHCI_CAPABILITIES_1, "CAPABILITIES_1"}, \ + {SDHCI_MAX_CURRENT, "MAX_CURRENT"}, \ + {SDHCI_SET_ACMD12_ERROR, "SET_ACMD12_ERROR"}, \ + {SDHCI_ADMA_ERROR, "ADMA_ERROR"}, \ + {SDHCI_ADMA_ADDRESS, "ADMA_ADDRESS"}, \ + {SDHCI_ADMA_ADDRESS_HI, "ADMA_ADDRESS_HI"}, \ + {SDHCI_SLOT_INT_STATUS, "SLOT_INT_STATUS"} + +static const struct trace_print_flags const int_flags[] = { + {SDHCI_INT_RESPONSE, "RESPONSE"}, + {SDHCI_INT_DATA_END, "DATA_END"}, + {SDHCI_INT_BLK_GAP, "BLK_GAP"}, + {SDHCI_INT_DMA_END, "DMA_END"}, + {SDHCI_INT_SPACE_AVAIL, "SPACE_AVAIL"}, + {SDHCI_INT_DATA_AVAIL, "DATA_AVAIL"}, + {SDHCI_INT_CARD_INSERT, "CARD_INSERT"}, + {SDHCI_INT_CARD_REMOVE, "CARD_REMOVE"}, + {SDHCI_INT_CARD_INT, "CARD_INT"}, + {SDHCI_INT_RETUNE, "RETUNE"}, + {SDHCI_INT_CQE, "CQE"}, + {SDHCI_INT_ERROR, "ERROR"}, + {SDHCI_INT_TIMEOUT, "TIMEOUT"}, + {SDHCI_INT_CRC, "CRC"}, + {SDHCI_INT_END_BIT, "END_BIT"}, + {SDHCI_INT_INDEX, "INDEX"}, + {SDHCI_INT_DATA_TIMEOUT, "DATA_TIMEOUT"}, + {SDHCI_INT_DATA_CRC, "DATA_CRC"}, + {SDHCI_INT_DATA_END_BIT, "DATA_END_BIT"}, + {SDHCI_INT_BUS_POWER, "BUS_POWER"}, + {SDHCI_INT_ACMD12ERR, "ACMD12ERR"}, + {SDHCI_INT_ADMA_ERROR, "ADMA_ERROR"}, + { -1, NULL } +}; + +static const struct trace_print_flags const present_state_flags[] = { + {SDHCI_CMD_INHIBIT, "CMD_INHIBIT"}, + {SDHCI_DATA_INHIBIT, "DATA_INHIBIT"}, + {1<<2, "DAT_LINE_ACTIVE"}, + {SDHCI_DOING_WRITE, "DOING_WRITE"}, + {SDHCI_DOING_READ, "DOING_READ"}, + {SDHCI_SPACE_AVAILABLE, "SPACE_AVAILABLE"}, + {SDHCI_DATA_AVAILABLE, "DATA_AVAILABLE"}, + {SDHCI_CARD_PRESENT, "CARD_PRESENT"}, + {1<<17, "CARD_STABLE"}, + {1<<18, "CD_HIGH"}, + {SDHCI_WRITE_PROTECT, "WRITE_PROTECT"}, + {1<<20, "DATA0"}, + {1<<21, "DATA1"}, + {1<<22, "DATA2"}, + {1<<23, "DATA3"}, + {SDHCI_CMD_LVL, "CMD_LVL"}, + { -1, NULL } +}; + +static const struct trace_print_field block_cnt_reg[] = { + { + .mask = 0xFFF, + .name = "BLOCK_SIZE" + }, + { + .mask = 7 << 12, + .name = "DMA_BUF_BOUNDARY", + .symbols = (const struct trace_print_flags[]) { + {0, "4K"}, + {1, "8K"}, + {2, "16K"}, + {3, "32K"}, + {4, "64K"}, + {5, "128K"}, + {6, "256K"}, + {7, "512K"}, + {} + } + }, + { + .mask = 0xFFFF << 16, + .name = "BLOCK_CNT" + }, +}; + +static const struct trace_print_field host_control_reg[] = { + { + .mask = SDHCI_CTRL_LED, + .name = "LED", + .symbols = (const struct trace_print_flags[]) { + {0, "OFF"}, + {1, "ON"}, + {} + } + }, { + .mask = SDHCI_CTRL_4BITBUS, + .name = "TX_WIDTH", + .symbols = (const struct trace_print_flags[]) { + {0, "1-BIT"}, + {1, "4-BIT"}, + {} + } + }, { + .mask = SDHCI_CTRL_HISPD, + .name = "HIGH_SPEED" + }, { + .mask = SDHCI_CTRL_DMA_MASK, + .symbols = (const struct trace_print_flags[]) { + {0, "SDMA"}, + {1, "ADMA-32"}, + {2, "ADMA2-32"}, + {3, "ADMA2-64"}, + {} + } + }, { + .mask = SDHCI_CTRL_8BITBUS, + .name = "MMC_WIDTH", + .symbols = (const struct trace_print_flags[]) { + {0, "DAT_WIDTH"}, + {1, "8-BIT"}, + {} + } + }, + {SDHCI_CTRL_CDTEST_INS, "CDTEST_INS"}, + {SDHCI_CTRL_CDTEST_EN, "CDTEST_EN"}, + {1<<8, "BUS_POWER"}, + { + .mask = 0x7 << 9, + .name = "BUS_VOLTAGE", + .symbols = (const struct trace_print_flags[]) { + {0x00, "0.0V"}, + {0x05, "1.8V"}, + {0x06, "3.0V"}, + {0x07, "3.3V"}, + {} + } + }, + {1<<16, "BLOCK_GAP_STOP"}, + {1<<17, "CONT_REQ"}, + {1<<18, "READ_WAIT_EN"}, + {1<<19, "BLOCK_GAP_INT_EN"}, + {1<<24, "INT_WAKE_EN"}, + {1<<25, "INS_WAKE_EN"}, + {1<<26, "REM_WAKE_EN"}, + {}, +}; + +static const struct trace_print_field transfer_mode_reg[] = { + {SDHCI_TRNS_DMA, "DMA_EN"}, + {SDHCI_TRNS_BLK_CNT_EN, "BLK_CNT_EN"}, + { + .mask = 0xC, + .name = "AUTO_CMD", + .symbols = (const struct trace_print_flags[]) { + {0, "DISABLED"}, + {1, "12"}, + {2, "23"}, + {3, "RESERVED"}, + {} + } + }, { + .mask = SDHCI_TRNS_READ, + .name = "DATA_DIR", + .symbols = (const struct trace_print_flags[]) { + {0, "WRITE"}, + {1, "READ"}, + {} + } + }, + {SDHCI_TRNS_MULTI, "MULTI_BLK"}, + { + .mask = 0x3 << 16, + .name = "RESP_TYPE", + .symbols = (const struct trace_print_flags[]) { + {0, "NONE"}, + {1, "136-BITS"}, + {2, "48-BITS"}, + {3, "48-BITS W/ BUSY"}, + {} + } + }, + {1<<19, "CRC_CHECK_EN"}, + {1<<20, "CMD_IDX_CHECK_EN"}, + {1<<21, "DATA_PRESENT"}, + { + .mask = 0x3 << 22, + .name = "CMD_TYPE", + .symbols = (const struct trace_print_flags[]) { + {0, "NORMAL"}, + {1, "SUSPEND CMD52"}, + {2, "RESUME CMD52"}, + {3, "ABORT"}, + {} + } + }, + {0x3f << 24, "CMD"}, + {}, +}; + +static const struct trace_print_field const clk_control_reg[] = { + {1<<0, "SYSCLK_EN"}, + {1<<1, "SYSCLK_STABLE"}, + {1<<2, "SDCLK_EN"}, + {1<<5, "PRG_CLK_MODE"}, + {0xc0, "SD_CLK_DIV[9:8]"}, + {0xFF00, "SD_CLK_DIV"}, + {0xF0000, "DATA_TIMEOUT_CNT"}, + {1<<24, "SOFT_RESET_ALL"}, + {1<<25, "SOFT_RESET_CMD"}, + {1<<26, "SOFT_RESET_DAT"}, + {} +}; + +static const struct trace_print_field const acmd_err_flags[] = { + {1<<0, "EXEC_ERROR"}, + {1<<1, "TIMEOUT_ERROR"}, + {1<<2, "CRC_ERROR"}, + {1<<3, "END_BIT_ERROR"}, + {1<<4, "INDEX_ERROR"}, + {1<<7, "CMD_ERROR"}, + { + .mask = 7 << 16, + .name = "UHS_MODE", + .symbols = (const struct trace_print_flags[]) { + {0, "SDR12"}, + {1, "SDR25"}, + {2, "SDR50"}, + {3, "SDR104"}, + {4, "DDR50"}, + {} + } + }, + { + .mask = 1 << 19, + .symbols = (const struct trace_print_flags[]) { + {0, "3.3V"}, + {1, "1.8V"}, + {} + } + }, + { + .mask = 3 << 20, + .name = "DRIVE_STRENGTH", + .symbols = (const struct trace_print_flags[]) { + {0, "B"}, + {1, "A"}, + {2, "C"}, + {3, "D"}, + {} + } + }, + {1<<22, "TUNING"}, + {1<<23, "SAMPLE_CLK"}, + {1<<30, "ASYNC_INT_EN"}, + {1<<31, "AUTO_PRESENT_VAL"}, + {} +}; + +/** + * sdhci_decode_register() - Decodes a SDHCI register + * + * @reg: Register offset that was accessed + * @val: Value written to the register + * @mask: Mask containing the number of bits written to the register. e.g., + * byte = 0xFF, word = 0xFFFF, long = 0xFFFFFFFF. + */ +static const char *sdhci_decode_register(struct trace_seq *p, u32 reg, u32 val, + u32 mask) +{ + u32 aligned = reg & ~3UL; + int shift = (reg - aligned) * 8; + + val <<= shift; + mask <<= shift; + + switch (aligned) { + case SDHCI_BLOCK_SIZE: + return trace_print_register(p, block_cnt_reg, val, mask); + case SDHCI_INT_STATUS: + case SDHCI_INT_ENABLE: + case SDHCI_SIGNAL_ENABLE: + return trace_print_flags_seq(p, " | ", val, int_flags); + case SDHCI_PRESENT_STATE: + return trace_print_flags_seq(p, " | ", val, + present_state_flags); + case SDHCI_HOST_CONTROL: + return trace_print_register(p, host_control_reg, val, mask); + case SDHCI_TRANSFER_MODE: + return trace_print_register(p, transfer_mode_reg, val, mask); + case SDHCI_CLOCK_CONTROL: + return trace_print_register(p, clk_control_reg, val, mask); + case SDHCI_ACMD12_ERR: + return trace_print_register(p, acmd_err_flags, val, mask); + default: + return ""; + } +} + +#define CREATE_TRACE_POINTS +#include "sdhci-trace.h" diff --git a/drivers/mmc/host/sdhci-trace.h b/drivers/mmc/host/sdhci-trace.h new file mode 100644 index 000000000000..938a032ea38a --- /dev/null +++ b/drivers/mmc/host/sdhci-trace.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright 2019 Google LLC. */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM sdhci + +#if !defined(_TRACE_SDHCI_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_SDHCI_H + +#include <linux/mmc/host.h> +#include <linux/tracepoint.h> +#include "sdhci.h" + +TRACE_EVENT(sdhci_read, + + TP_PROTO(struct sdhci_host *host, u32 reg, u32 val, u32 mask), + + TP_ARGS(host, reg, val, mask), + + TP_STRUCT__entry( + __field(u32, reg) + __field(u32, val) + __field(u32, mask) + __string(name, mmc_hostname(host->mmc)) + ), + + TP_fast_assign( + __entry->reg = reg; + __entry->val = val; + __entry->mask = mask; + __assign_str(name, mmc_hostname(host->mmc)); + ), + + TP_printk("%s: %#x [%s] => %#x: %s", + __get_str(name), + __entry->reg, + __print_symbolic(__entry->reg & ~3UL, SDHCI_REGS), + __entry->val, + sdhci_decode_register( + p, + __entry->reg, + __entry->val, + __entry->mask + ) + ) +); + +TRACE_EVENT(sdhci_write, + + TP_PROTO(struct sdhci_host *host, u32 reg, u32 val, u32 mask), + + TP_ARGS(host, reg, val, mask), + + TP_STRUCT__entry( + __field(u32, reg) + __field(u32, val) + __field(u32, mask) + __string(name, mmc_hostname(host->mmc)) + ), + + TP_fast_assign( + __entry->reg = reg; + __entry->val = val; + __entry->mask = mask; + __assign_str(name, mmc_hostname(host->mmc)); + ), + + TP_printk("%s: %#x [%s] <= %#x: %s", + __get_str(name), + __entry->reg, + __print_symbolic(__entry->reg & ~3UL, SDHCI_REGS), + __entry->val, + sdhci_decode_register( + p, + __entry->reg, + __entry->val, + __entry->mask + ) + ) +); + + +#endif /* _TRACE_SDHCI_H */ + +/* this part must be outside header guard */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . + +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE sdhci-trace + +#include <trace/define_trace.h> -- 2.21.0.392.gf8f6787159e-goog