18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Qualcomm Technologies HIDMA debug file 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/debugfs.h> 98c2ecf20Sopenharmony_ci#include <linux/device.h> 108c2ecf20Sopenharmony_ci#include <linux/list.h> 118c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include "hidma.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_cistatic void hidma_ll_chstats(struct seq_file *s, void *llhndl, u32 tre_ch) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci struct hidma_lldev *lldev = llhndl; 188c2ecf20Sopenharmony_ci struct hidma_tre *tre; 198c2ecf20Sopenharmony_ci u32 length; 208c2ecf20Sopenharmony_ci dma_addr_t src_start; 218c2ecf20Sopenharmony_ci dma_addr_t dest_start; 228c2ecf20Sopenharmony_ci u32 *tre_local; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci if (tre_ch >= lldev->nr_tres) { 258c2ecf20Sopenharmony_ci dev_err(lldev->dev, "invalid TRE number in chstats:%d", tre_ch); 268c2ecf20Sopenharmony_ci return; 278c2ecf20Sopenharmony_ci } 288c2ecf20Sopenharmony_ci tre = &lldev->trepool[tre_ch]; 298c2ecf20Sopenharmony_ci seq_printf(s, "------Channel %d -----\n", tre_ch); 308c2ecf20Sopenharmony_ci seq_printf(s, "allocated=%d\n", atomic_read(&tre->allocated)); 318c2ecf20Sopenharmony_ci seq_printf(s, "queued = 0x%x\n", tre->queued); 328c2ecf20Sopenharmony_ci seq_printf(s, "err_info = 0x%x\n", tre->err_info); 338c2ecf20Sopenharmony_ci seq_printf(s, "err_code = 0x%x\n", tre->err_code); 348c2ecf20Sopenharmony_ci seq_printf(s, "status = 0x%x\n", tre->status); 358c2ecf20Sopenharmony_ci seq_printf(s, "idx = 0x%x\n", tre->idx); 368c2ecf20Sopenharmony_ci seq_printf(s, "dma_sig = 0x%x\n", tre->dma_sig); 378c2ecf20Sopenharmony_ci seq_printf(s, "dev_name=%s\n", tre->dev_name); 388c2ecf20Sopenharmony_ci seq_printf(s, "callback=%p\n", tre->callback); 398c2ecf20Sopenharmony_ci seq_printf(s, "data=%p\n", tre->data); 408c2ecf20Sopenharmony_ci seq_printf(s, "tre_index = 0x%x\n", tre->tre_index); 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci tre_local = &tre->tre_local[0]; 438c2ecf20Sopenharmony_ci src_start = tre_local[HIDMA_TRE_SRC_LOW_IDX]; 448c2ecf20Sopenharmony_ci src_start = ((u64) (tre_local[HIDMA_TRE_SRC_HI_IDX]) << 32) + src_start; 458c2ecf20Sopenharmony_ci dest_start = tre_local[HIDMA_TRE_DEST_LOW_IDX]; 468c2ecf20Sopenharmony_ci dest_start += ((u64) (tre_local[HIDMA_TRE_DEST_HI_IDX]) << 32); 478c2ecf20Sopenharmony_ci length = tre_local[HIDMA_TRE_LEN_IDX]; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci seq_printf(s, "src=%pap\n", &src_start); 508c2ecf20Sopenharmony_ci seq_printf(s, "dest=%pap\n", &dest_start); 518c2ecf20Sopenharmony_ci seq_printf(s, "length = 0x%x\n", length); 528c2ecf20Sopenharmony_ci} 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic void hidma_ll_devstats(struct seq_file *s, void *llhndl) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci struct hidma_lldev *lldev = llhndl; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci seq_puts(s, "------Device -----\n"); 598c2ecf20Sopenharmony_ci seq_printf(s, "lldev init = 0x%x\n", lldev->initialized); 608c2ecf20Sopenharmony_ci seq_printf(s, "trch_state = 0x%x\n", lldev->trch_state); 618c2ecf20Sopenharmony_ci seq_printf(s, "evch_state = 0x%x\n", lldev->evch_state); 628c2ecf20Sopenharmony_ci seq_printf(s, "chidx = 0x%x\n", lldev->chidx); 638c2ecf20Sopenharmony_ci seq_printf(s, "nr_tres = 0x%x\n", lldev->nr_tres); 648c2ecf20Sopenharmony_ci seq_printf(s, "trca=%p\n", lldev->trca); 658c2ecf20Sopenharmony_ci seq_printf(s, "tre_ring=%p\n", lldev->tre_ring); 668c2ecf20Sopenharmony_ci seq_printf(s, "tre_ring_handle=%pap\n", &lldev->tre_dma); 678c2ecf20Sopenharmony_ci seq_printf(s, "tre_ring_size = 0x%x\n", lldev->tre_ring_size); 688c2ecf20Sopenharmony_ci seq_printf(s, "tre_processed_off = 0x%x\n", lldev->tre_processed_off); 698c2ecf20Sopenharmony_ci seq_printf(s, "pending_tre_count=%d\n", 708c2ecf20Sopenharmony_ci atomic_read(&lldev->pending_tre_count)); 718c2ecf20Sopenharmony_ci seq_printf(s, "evca=%p\n", lldev->evca); 728c2ecf20Sopenharmony_ci seq_printf(s, "evre_ring=%p\n", lldev->evre_ring); 738c2ecf20Sopenharmony_ci seq_printf(s, "evre_ring_handle=%pap\n", &lldev->evre_dma); 748c2ecf20Sopenharmony_ci seq_printf(s, "evre_ring_size = 0x%x\n", lldev->evre_ring_size); 758c2ecf20Sopenharmony_ci seq_printf(s, "evre_processed_off = 0x%x\n", lldev->evre_processed_off); 768c2ecf20Sopenharmony_ci seq_printf(s, "tre_write_offset = 0x%x\n", lldev->tre_write_offset); 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci/* 808c2ecf20Sopenharmony_ci * hidma_chan_show: display HIDMA channel statistics 818c2ecf20Sopenharmony_ci * 828c2ecf20Sopenharmony_ci * Display the statistics for the current HIDMA virtual channel device. 838c2ecf20Sopenharmony_ci */ 848c2ecf20Sopenharmony_cistatic int hidma_chan_show(struct seq_file *s, void *unused) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci struct hidma_chan *mchan = s->private; 878c2ecf20Sopenharmony_ci struct hidma_desc *mdesc; 888c2ecf20Sopenharmony_ci struct hidma_dev *dmadev = mchan->dmadev; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci pm_runtime_get_sync(dmadev->ddev.dev); 918c2ecf20Sopenharmony_ci seq_printf(s, "paused=%u\n", mchan->paused); 928c2ecf20Sopenharmony_ci seq_printf(s, "dma_sig=%u\n", mchan->dma_sig); 938c2ecf20Sopenharmony_ci seq_puts(s, "prepared\n"); 948c2ecf20Sopenharmony_ci list_for_each_entry(mdesc, &mchan->prepared, node) 958c2ecf20Sopenharmony_ci hidma_ll_chstats(s, mchan->dmadev->lldev, mdesc->tre_ch); 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci seq_puts(s, "active\n"); 988c2ecf20Sopenharmony_ci list_for_each_entry(mdesc, &mchan->active, node) 998c2ecf20Sopenharmony_ci hidma_ll_chstats(s, mchan->dmadev->lldev, mdesc->tre_ch); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci seq_puts(s, "completed\n"); 1028c2ecf20Sopenharmony_ci list_for_each_entry(mdesc, &mchan->completed, node) 1038c2ecf20Sopenharmony_ci hidma_ll_chstats(s, mchan->dmadev->lldev, mdesc->tre_ch); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci hidma_ll_devstats(s, mchan->dmadev->lldev); 1068c2ecf20Sopenharmony_ci pm_runtime_mark_last_busy(dmadev->ddev.dev); 1078c2ecf20Sopenharmony_ci pm_runtime_put_autosuspend(dmadev->ddev.dev); 1088c2ecf20Sopenharmony_ci return 0; 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci/* 1128c2ecf20Sopenharmony_ci * hidma_dma_show: display HIDMA device info 1138c2ecf20Sopenharmony_ci * 1148c2ecf20Sopenharmony_ci * Display the info for the current HIDMA device. 1158c2ecf20Sopenharmony_ci */ 1168c2ecf20Sopenharmony_cistatic int hidma_dma_show(struct seq_file *s, void *unused) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci struct hidma_dev *dmadev = s->private; 1198c2ecf20Sopenharmony_ci resource_size_t sz; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci seq_printf(s, "nr_descriptors=%d\n", dmadev->nr_descriptors); 1228c2ecf20Sopenharmony_ci seq_printf(s, "dev_trca=%p\n", &dmadev->dev_trca); 1238c2ecf20Sopenharmony_ci seq_printf(s, "dev_trca_phys=%pa\n", &dmadev->trca_resource->start); 1248c2ecf20Sopenharmony_ci sz = resource_size(dmadev->trca_resource); 1258c2ecf20Sopenharmony_ci seq_printf(s, "dev_trca_size=%pa\n", &sz); 1268c2ecf20Sopenharmony_ci seq_printf(s, "dev_evca=%p\n", &dmadev->dev_evca); 1278c2ecf20Sopenharmony_ci seq_printf(s, "dev_evca_phys=%pa\n", &dmadev->evca_resource->start); 1288c2ecf20Sopenharmony_ci sz = resource_size(dmadev->evca_resource); 1298c2ecf20Sopenharmony_ci seq_printf(s, "dev_evca_size=%pa\n", &sz); 1308c2ecf20Sopenharmony_ci return 0; 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(hidma_chan); 1348c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(hidma_dma); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_civoid hidma_debug_uninit(struct hidma_dev *dmadev) 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci debugfs_remove_recursive(dmadev->debugfs); 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_civoid hidma_debug_init(struct hidma_dev *dmadev) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci int chidx = 0; 1448c2ecf20Sopenharmony_ci struct list_head *position = NULL; 1458c2ecf20Sopenharmony_ci struct dentry *dir; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci dmadev->debugfs = debugfs_create_dir(dev_name(dmadev->ddev.dev), NULL); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci /* walk through the virtual channel list */ 1508c2ecf20Sopenharmony_ci list_for_each(position, &dmadev->ddev.channels) { 1518c2ecf20Sopenharmony_ci struct hidma_chan *chan; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci chan = list_entry(position, struct hidma_chan, 1548c2ecf20Sopenharmony_ci chan.device_node); 1558c2ecf20Sopenharmony_ci sprintf(chan->dbg_name, "chan%d", chidx); 1568c2ecf20Sopenharmony_ci dir = debugfs_create_dir(chan->dbg_name, 1578c2ecf20Sopenharmony_ci dmadev->debugfs); 1588c2ecf20Sopenharmony_ci debugfs_create_file("stats", S_IRUGO, dir, chan, 1598c2ecf20Sopenharmony_ci &hidma_chan_fops); 1608c2ecf20Sopenharmony_ci chidx++; 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci debugfs_create_file("stats", S_IRUGO, dmadev->debugfs, dmadev, 1648c2ecf20Sopenharmony_ci &hidma_dma_fops); 1658c2ecf20Sopenharmony_ci} 166