Path: blob/master/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
26282 views
// SPDX-License-Identifier: GPL-2.01/*2* Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.3* Synopsys DesignWare eDMA v0 core4*5* Author: Gustavo Pimentel <[email protected]>6*/78#include <linux/debugfs.h>9#include <linux/bitfield.h>1011#include "dw-edma-v0-debugfs.h"12#include "dw-edma-v0-regs.h"13#include "dw-edma-core.h"1415#define REGS_ADDR(dw, name) \16({ \17struct dw_edma_v0_regs __iomem *__regs = (dw)->chip->reg_base; \18\19(void __iomem *)&__regs->name; \20})2122#define REGS_CH_ADDR(dw, name, _dir, _ch) \23({ \24struct dw_edma_v0_ch_regs __iomem *__ch_regs; \25\26if ((dw)->chip->mf == EDMA_MF_EDMA_LEGACY) \27__ch_regs = REGS_ADDR(dw, type.legacy.ch); \28else if (_dir == EDMA_DIR_READ) \29__ch_regs = REGS_ADDR(dw, type.unroll.ch[_ch].rd); \30else \31__ch_regs = REGS_ADDR(dw, type.unroll.ch[_ch].wr); \32\33(void __iomem *)&__ch_regs->name; \34})3536#define REGISTER(dw, name) \37{ dw, #name, REGS_ADDR(dw, name) }3839#define CTX_REGISTER(dw, name, dir, ch) \40{ dw, #name, REGS_CH_ADDR(dw, name, dir, ch), dir, ch }4142#define WR_REGISTER(dw, name) \43{ dw, #name, REGS_ADDR(dw, wr_##name) }44#define RD_REGISTER(dw, name) \45{ dw, #name, REGS_ADDR(dw, rd_##name) }4647#define WR_REGISTER_LEGACY(dw, name) \48{ dw, #name, REGS_ADDR(dw, type.legacy.wr_##name) }49#define RD_REGISTER_LEGACY(name) \50{ dw, #name, REGS_ADDR(dw, type.legacy.rd_##name) }5152#define WR_REGISTER_UNROLL(dw, name) \53{ dw, #name, REGS_ADDR(dw, type.unroll.wr_##name) }54#define RD_REGISTER_UNROLL(dw, name) \55{ dw, #name, REGS_ADDR(dw, type.unroll.rd_##name) }5657#define WRITE_STR "write"58#define READ_STR "read"59#define CHANNEL_STR "channel"60#define REGISTERS_STR "registers"6162struct dw_edma_debugfs_entry {63struct dw_edma *dw;64const char *name;65void __iomem *reg;66enum dw_edma_dir dir;67u16 ch;68};6970static int dw_edma_debugfs_u32_get(void *data, u64 *val)71{72struct dw_edma_debugfs_entry *entry = data;73struct dw_edma *dw = entry->dw;74void __iomem *reg = entry->reg;7576if (dw->chip->mf == EDMA_MF_EDMA_LEGACY &&77reg >= REGS_ADDR(dw, type.legacy.ch)) {78unsigned long flags;79u32 viewport_sel;8081viewport_sel = entry->dir == EDMA_DIR_READ ? BIT(31) : 0;82viewport_sel |= FIELD_PREP(EDMA_V0_VIEWPORT_MASK, entry->ch);8384raw_spin_lock_irqsave(&dw->lock, flags);8586writel(viewport_sel, REGS_ADDR(dw, type.legacy.viewport_sel));87*val = readl(reg);8889raw_spin_unlock_irqrestore(&dw->lock, flags);90} else {91*val = readl(reg);92}9394return 0;95}96DEFINE_DEBUGFS_ATTRIBUTE(fops_x32, dw_edma_debugfs_u32_get, NULL, "0x%08llx\n");9798static void dw_edma_debugfs_create_x32(struct dw_edma *dw,99const struct dw_edma_debugfs_entry ini[],100int nr_entries, struct dentry *dent)101{102struct dw_edma_debugfs_entry *entries;103int i;104105entries = devm_kcalloc(dw->chip->dev, nr_entries, sizeof(*entries),106GFP_KERNEL);107if (!entries)108return;109110for (i = 0; i < nr_entries; i++) {111entries[i] = ini[i];112113debugfs_create_file_unsafe(entries[i].name, 0444, dent,114&entries[i], &fops_x32);115}116}117118static void dw_edma_debugfs_regs_ch(struct dw_edma *dw, enum dw_edma_dir dir,119u16 ch, struct dentry *dent)120{121struct dw_edma_debugfs_entry debugfs_regs[] = {122CTX_REGISTER(dw, ch_control1, dir, ch),123CTX_REGISTER(dw, ch_control2, dir, ch),124CTX_REGISTER(dw, transfer_size, dir, ch),125CTX_REGISTER(dw, sar.lsb, dir, ch),126CTX_REGISTER(dw, sar.msb, dir, ch),127CTX_REGISTER(dw, dar.lsb, dir, ch),128CTX_REGISTER(dw, dar.msb, dir, ch),129CTX_REGISTER(dw, llp.lsb, dir, ch),130CTX_REGISTER(dw, llp.msb, dir, ch),131};132int nr_entries;133134nr_entries = ARRAY_SIZE(debugfs_regs);135dw_edma_debugfs_create_x32(dw, debugfs_regs, nr_entries, dent);136}137138static noinline_for_stack void139dw_edma_debugfs_regs_wr(struct dw_edma *dw, struct dentry *dent)140{141const struct dw_edma_debugfs_entry debugfs_regs[] = {142/* eDMA global registers */143WR_REGISTER(dw, engine_en),144WR_REGISTER(dw, doorbell),145WR_REGISTER(dw, ch_arb_weight.lsb),146WR_REGISTER(dw, ch_arb_weight.msb),147/* eDMA interrupts registers */148WR_REGISTER(dw, int_status),149WR_REGISTER(dw, int_mask),150WR_REGISTER(dw, int_clear),151WR_REGISTER(dw, err_status),152WR_REGISTER(dw, done_imwr.lsb),153WR_REGISTER(dw, done_imwr.msb),154WR_REGISTER(dw, abort_imwr.lsb),155WR_REGISTER(dw, abort_imwr.msb),156WR_REGISTER(dw, ch01_imwr_data),157WR_REGISTER(dw, ch23_imwr_data),158WR_REGISTER(dw, ch45_imwr_data),159WR_REGISTER(dw, ch67_imwr_data),160WR_REGISTER(dw, linked_list_err_en),161};162const struct dw_edma_debugfs_entry debugfs_unroll_regs[] = {163/* eDMA channel context grouping */164WR_REGISTER_UNROLL(dw, engine_chgroup),165WR_REGISTER_UNROLL(dw, engine_hshake_cnt.lsb),166WR_REGISTER_UNROLL(dw, engine_hshake_cnt.msb),167WR_REGISTER_UNROLL(dw, ch0_pwr_en),168WR_REGISTER_UNROLL(dw, ch1_pwr_en),169WR_REGISTER_UNROLL(dw, ch2_pwr_en),170WR_REGISTER_UNROLL(dw, ch3_pwr_en),171WR_REGISTER_UNROLL(dw, ch4_pwr_en),172WR_REGISTER_UNROLL(dw, ch5_pwr_en),173WR_REGISTER_UNROLL(dw, ch6_pwr_en),174WR_REGISTER_UNROLL(dw, ch7_pwr_en),175};176struct dentry *regs_dent, *ch_dent;177int nr_entries, i;178char name[32];179180regs_dent = debugfs_create_dir(WRITE_STR, dent);181182nr_entries = ARRAY_SIZE(debugfs_regs);183dw_edma_debugfs_create_x32(dw, debugfs_regs, nr_entries, regs_dent);184185if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {186nr_entries = ARRAY_SIZE(debugfs_unroll_regs);187dw_edma_debugfs_create_x32(dw, debugfs_unroll_regs, nr_entries,188regs_dent);189}190191for (i = 0; i < dw->wr_ch_cnt; i++) {192snprintf(name, sizeof(name), "%s:%d", CHANNEL_STR, i);193194ch_dent = debugfs_create_dir(name, regs_dent);195196dw_edma_debugfs_regs_ch(dw, EDMA_DIR_WRITE, i, ch_dent);197}198}199200static noinline_for_stack void dw_edma_debugfs_regs_rd(struct dw_edma *dw,201struct dentry *dent)202{203const struct dw_edma_debugfs_entry debugfs_regs[] = {204/* eDMA global registers */205RD_REGISTER(dw, engine_en),206RD_REGISTER(dw, doorbell),207RD_REGISTER(dw, ch_arb_weight.lsb),208RD_REGISTER(dw, ch_arb_weight.msb),209/* eDMA interrupts registers */210RD_REGISTER(dw, int_status),211RD_REGISTER(dw, int_mask),212RD_REGISTER(dw, int_clear),213RD_REGISTER(dw, err_status.lsb),214RD_REGISTER(dw, err_status.msb),215RD_REGISTER(dw, linked_list_err_en),216RD_REGISTER(dw, done_imwr.lsb),217RD_REGISTER(dw, done_imwr.msb),218RD_REGISTER(dw, abort_imwr.lsb),219RD_REGISTER(dw, abort_imwr.msb),220RD_REGISTER(dw, ch01_imwr_data),221RD_REGISTER(dw, ch23_imwr_data),222RD_REGISTER(dw, ch45_imwr_data),223RD_REGISTER(dw, ch67_imwr_data),224};225const struct dw_edma_debugfs_entry debugfs_unroll_regs[] = {226/* eDMA channel context grouping */227RD_REGISTER_UNROLL(dw, engine_chgroup),228RD_REGISTER_UNROLL(dw, engine_hshake_cnt.lsb),229RD_REGISTER_UNROLL(dw, engine_hshake_cnt.msb),230RD_REGISTER_UNROLL(dw, ch0_pwr_en),231RD_REGISTER_UNROLL(dw, ch1_pwr_en),232RD_REGISTER_UNROLL(dw, ch2_pwr_en),233RD_REGISTER_UNROLL(dw, ch3_pwr_en),234RD_REGISTER_UNROLL(dw, ch4_pwr_en),235RD_REGISTER_UNROLL(dw, ch5_pwr_en),236RD_REGISTER_UNROLL(dw, ch6_pwr_en),237RD_REGISTER_UNROLL(dw, ch7_pwr_en),238};239struct dentry *regs_dent, *ch_dent;240int nr_entries, i;241char name[32];242243regs_dent = debugfs_create_dir(READ_STR, dent);244245nr_entries = ARRAY_SIZE(debugfs_regs);246dw_edma_debugfs_create_x32(dw, debugfs_regs, nr_entries, regs_dent);247248if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {249nr_entries = ARRAY_SIZE(debugfs_unroll_regs);250dw_edma_debugfs_create_x32(dw, debugfs_unroll_regs, nr_entries,251regs_dent);252}253254for (i = 0; i < dw->rd_ch_cnt; i++) {255snprintf(name, sizeof(name), "%s:%d", CHANNEL_STR, i);256257ch_dent = debugfs_create_dir(name, regs_dent);258259dw_edma_debugfs_regs_ch(dw, EDMA_DIR_READ, i, ch_dent);260}261}262263static void dw_edma_debugfs_regs(struct dw_edma *dw)264{265const struct dw_edma_debugfs_entry debugfs_regs[] = {266REGISTER(dw, ctrl_data_arb_prior),267REGISTER(dw, ctrl),268};269struct dentry *regs_dent;270int nr_entries;271272regs_dent = debugfs_create_dir(REGISTERS_STR, dw->dma.dbg_dev_root);273274nr_entries = ARRAY_SIZE(debugfs_regs);275dw_edma_debugfs_create_x32(dw, debugfs_regs, nr_entries, regs_dent);276277dw_edma_debugfs_regs_wr(dw, regs_dent);278dw_edma_debugfs_regs_rd(dw, regs_dent);279}280281void dw_edma_v0_debugfs_on(struct dw_edma *dw)282{283if (!debugfs_initialized())284return;285286debugfs_create_u32("mf", 0444, dw->dma.dbg_dev_root, &dw->chip->mf);287debugfs_create_u16("wr_ch_cnt", 0444, dw->dma.dbg_dev_root, &dw->wr_ch_cnt);288debugfs_create_u16("rd_ch_cnt", 0444, dw->dma.dbg_dev_root, &dw->rd_ch_cnt);289290dw_edma_debugfs_regs(dw);291}292293294