|
18 | 18 | #include <linux/string.h> |
19 | 19 | #include <linux/debugfs.h> |
20 | 20 | #include <linux/uaccess.h> |
| 21 | +#include <linux/seq_file.h> |
21 | 22 | #include <linux/firmware.h> |
22 | 23 | #include <linux/interrupt.h> |
23 | 24 | #include <linux/types.h> |
@@ -1931,6 +1932,90 @@ static const struct file_operations adrv9025_debugfs_reg_fops = { |
1931 | 1932 | .write = adrv9025_debugfs_write, |
1932 | 1933 | }; |
1933 | 1934 |
|
| 1935 | +static int adrv9025_tx_advanced_dpd_status_show(struct seq_file *s, void *ignored) |
| 1936 | +{ |
| 1937 | + struct adrv9025_tx_chan_ctx *ctx = s->private; |
| 1938 | + adi_adrv9025_DpdStatus_v2_t dpdStatus = { 0 }; |
| 1939 | + struct adrv9025_rf_phy *phy = ctx->phy; |
| 1940 | + adi_adrv9025_TxChannels_e txChannel; |
| 1941 | + u8 chan = ctx->channel; |
| 1942 | + int ret; |
| 1943 | + |
| 1944 | + /* Convert channel index to TX channel enum */ |
| 1945 | + txChannel = ADI_ADRV9025_TX1 << chan; |
| 1946 | + |
| 1947 | + mutex_lock(&phy->lock); |
| 1948 | + ret = adi_adrv9025_DpdStatusGet_v2(phy->madDevice, txChannel, &dpdStatus); |
| 1949 | + mutex_unlock(&phy->lock); |
| 1950 | + if (ret) |
| 1951 | + return adrv9025_dev_err(phy); |
| 1952 | + |
| 1953 | + seq_printf(s, "ADRV9025 TX%u Advanced DPD Status\n", chan); |
| 1954 | + |
| 1955 | + /* Basic Status */ |
| 1956 | + seq_puts(s, "Basic Status:\n"); |
| 1957 | + seq_printf(s, " Error Code: %d\n", dpdStatus.dpdErrorCode); |
| 1958 | + seq_printf(s, " Percent Complete: %u%%\n", dpdStatus.dpdPercentComplete); |
| 1959 | + seq_printf(s, " Iteration Count: %u\n", dpdStatus.dpdIterCount); |
| 1960 | + seq_printf(s, " Update Count: %u\n", dpdStatus.dpdUpdateCount); |
| 1961 | + seq_printf(s, " Sync Status: %d\n", dpdStatus.dpdSyncStatus); |
| 1962 | + seq_printf(s, " Model Table: %d\n", dpdStatus.dpdModelTable); |
| 1963 | + |
| 1964 | + /* Power Statistics */ |
| 1965 | + seq_puts(s, "\nPower Statistics:\n"); |
| 1966 | + seq_printf(s, " Mean TU Power: %d.%03d dBFS\n", |
| 1967 | + dpdStatus.dpdStatistics.dpdMeanTuPower_mdB / 1000, |
| 1968 | + abs(dpdStatus.dpdStatistics.dpdMeanTuPower_mdB % 1000)); |
| 1969 | + seq_printf(s, " Peak TU Power: %d.%03d dBFS\n", |
| 1970 | + dpdStatus.dpdStatistics.dpdPeakTuPower_mdB / 1000, |
| 1971 | + abs(dpdStatus.dpdStatistics.dpdPeakTuPower_mdB % 1000)); |
| 1972 | + seq_printf(s, " Mean TX Power: %d.%03d dBFS\n", |
| 1973 | + dpdStatus.dpdStatistics.dpdMeanTxPower_mdB / 1000, |
| 1974 | + abs(dpdStatus.dpdStatistics.dpdMeanTxPower_mdB % 1000)); |
| 1975 | + seq_printf(s, " Peak TX Power: %d.%03d dBFS\n", |
| 1976 | + dpdStatus.dpdStatistics.dpdPeakTxPower_mdB / 1000, |
| 1977 | + abs(dpdStatus.dpdStatistics.dpdPeakTxPower_mdB % 1000)); |
| 1978 | + seq_printf(s, " Mean ORx Power: %d.%03d dBFS\n", |
| 1979 | + dpdStatus.dpdStatistics.dpdMeanOrxPower_mdB / 1000, |
| 1980 | + abs(dpdStatus.dpdStatistics.dpdMeanOrxPower_mdB % 1000)); |
| 1981 | + seq_printf(s, " Peak ORx Power: %d.%03d dBFS\n", |
| 1982 | + dpdStatus.dpdStatistics.dpdPeakOrxPower_mdB / 1000, |
| 1983 | + abs(dpdStatus.dpdStatistics.dpdPeakOrxPower_mdB % 1000)); |
| 1984 | + |
| 1985 | + /* Error Metrics */ |
| 1986 | + seq_puts(s, "\nError Metrics:\n"); |
| 1987 | + seq_printf(s, " Direct EVM: %u.%04u%%\n", |
| 1988 | + dpdStatus.dpdStatistics.dpdDirectEvm_xM / 10000, |
| 1989 | + dpdStatus.dpdStatistics.dpdDirectEvm_xM % 10000); |
| 1990 | + seq_printf(s, " Indirect EVM: %u.%04u%%\n", |
| 1991 | + dpdStatus.dpdStatistics.dpdIndirectEvm_xM / 10000, |
| 1992 | + dpdStatus.dpdStatistics.dpdIndirectEvm_xM % 10000); |
| 1993 | + seq_printf(s, " Select Error: %u.%04u%%\n", |
| 1994 | + dpdStatus.dpdStatistics.dpdSelectError_xM / 10000, |
| 1995 | + dpdStatus.dpdStatistics.dpdSelectError_xM % 10000); |
| 1996 | + seq_printf(s, " Indirect Error: %u.%04u%%\n", |
| 1997 | + dpdStatus.dpdStatistics.dpdIndirectError_xM / 10000, |
| 1998 | + dpdStatus.dpdStatistics.dpdIndirectError_xM % 10000); |
| 1999 | + |
| 2000 | + /* Error Status */ |
| 2001 | + seq_puts(s, "\nError Status:\n"); |
| 2002 | + seq_printf(s, " Error Status 0: metrics_mask=0x%04x, action_mask=0x%04x\n", |
| 2003 | + dpdStatus.dpdErrorStatus0.dpdMetricsMask, |
| 2004 | + dpdStatus.dpdErrorStatus0.dpdActionMask); |
| 2005 | + seq_printf(s, " Error Status 1: metrics_mask=0x%04x, action_mask=0x%04x\n", |
| 2006 | + dpdStatus.dpdErrorStatus1.dpdMetricsMask, |
| 2007 | + dpdStatus.dpdErrorStatus1.dpdActionMask); |
| 2008 | + seq_printf(s, " Persistent Error 0: metrics_mask=0x%04x, action_mask=0x%04x\n", |
| 2009 | + dpdStatus.dpdPersistentErrorStatus0.dpdMetricsMask, |
| 2010 | + dpdStatus.dpdPersistentErrorStatus0.dpdActionMask); |
| 2011 | + seq_printf(s, " Persistent Error 1: metrics_mask=0x%04x, action_mask=0x%04x\n", |
| 2012 | + dpdStatus.dpdPersistentErrorStatus1.dpdMetricsMask, |
| 2013 | + dpdStatus.dpdPersistentErrorStatus1.dpdActionMask); |
| 2014 | + |
| 2015 | + return 0; |
| 2016 | +} |
| 2017 | +DEFINE_SHOW_ATTRIBUTE(adrv9025_tx_advanced_dpd_status); |
| 2018 | + |
1934 | 2019 | static void adrv9025_add_debugfs_entry(struct adrv9025_rf_phy *phy, |
1935 | 2020 | const char *propname, unsigned int cmd) |
1936 | 2021 | { |
@@ -1991,6 +2076,21 @@ static int adrv9025_register_debugfs(struct iio_dev *indio_dev) |
1991 | 2076 | &phy->debugfs_entry[i], |
1992 | 2077 | &adrv9025_debugfs_reg_fops); |
1993 | 2078 | } |
| 2079 | + |
| 2080 | + /* Create seqfile-based debugfs entries for each TX channel */ |
| 2081 | + for (i = 0; i < ADRV9025_NUMBER_OF_TX_CHANNELS; i++) { |
| 2082 | + char attr[64]; |
| 2083 | + |
| 2084 | + phy->tx_chan_ctx[i].phy = phy; |
| 2085 | + phy->tx_chan_ctx[i].channel = i; |
| 2086 | + |
| 2087 | + sprintf(attr, "tx%d_advanced_dpd_status", i); |
| 2088 | + debugfs_create_file(attr, 0444, |
| 2089 | + iio_get_debugfs_dentry(indio_dev), |
| 2090 | + &phy->tx_chan_ctx[i], |
| 2091 | + &adrv9025_tx_advanced_dpd_status_fops); |
| 2092 | + } |
| 2093 | + |
1994 | 2094 | return 0; |
1995 | 2095 | } |
1996 | 2096 |
|
|
0 commit comments