aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorBen Dooks <ben@simtec.co.uk>2009-10-01 18:44:17 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-10-01 19:11:15 -0400
commit9bdd203b4dc82e9047486f0fed1977eef8185c6d (patch)
treef547098e58f7d4f4d417a45d40d86614072db82c /drivers/mmc
parente6130aeffd93d342e72ca85cfd335d066f680792 (diff)
s3cmci: add debugfs support for examining driver and hardware state
Export driver state and hardware register state via debugfs entries created under a directory formed from dev_name() on the probed device when CONFIG_DEBUG_FS is set. Signed-off-by: Ben Dooks <ben@simtec.co.uk> Cc: <linux-mmc@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/s3cmci.c126
-rw-r--r--drivers/mmc/host/s3cmci.h6
2 files changed, 132 insertions, 0 deletions
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index 28a4a4535f38..8c2c8b456087 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -17,6 +17,8 @@
17#include <linux/mmc/host.h> 17#include <linux/mmc/host.h>
18#include <linux/platform_device.h> 18#include <linux/platform_device.h>
19#include <linux/cpufreq.h> 19#include <linux/cpufreq.h>
20#include <linux/debugfs.h>
21#include <linux/seq_file.h>
20#include <linux/gpio.h> 22#include <linux/gpio.h>
21#include <linux/irq.h> 23#include <linux/irq.h>
22#include <linux/io.h> 24#include <linux/io.h>
@@ -1244,6 +1246,127 @@ static inline void s3cmci_cpufreq_deregister(struct s3cmci_host *host)
1244#endif 1246#endif
1245 1247
1246 1248
1249#ifdef CONFIG_DEBUG_FS
1250
1251static int s3cmci_state_show(struct seq_file *seq, void *v)
1252{
1253 struct s3cmci_host *host = seq->private;
1254
1255 seq_printf(seq, "Register base = 0x%08x\n", (u32)host->base);
1256 seq_printf(seq, "Clock rate = %ld\n", host->clk_rate);
1257 seq_printf(seq, "Prescale = %d\n", host->prescaler);
1258 seq_printf(seq, "is2440 = %d\n", host->is2440);
1259 seq_printf(seq, "IRQ = %d\n", host->irq);
1260 seq_printf(seq, "CD IRQ = %d\n", host->irq_cd);
1261 seq_printf(seq, "Do DMA = %d\n", host->dodma);
1262 seq_printf(seq, "SDIIMSK at %d\n", host->sdiimsk);
1263 seq_printf(seq, "SDIDATA at %d\n", host->sdidata);
1264
1265 return 0;
1266}
1267
1268static int s3cmci_state_open(struct inode *inode, struct file *file)
1269{
1270 return single_open(file, s3cmci_state_show, inode->i_private);
1271}
1272
1273static const struct file_operations s3cmci_fops_state = {
1274 .owner = THIS_MODULE,
1275 .open = s3cmci_state_open,
1276 .read = seq_read,
1277 .llseek = seq_lseek,
1278 .release = single_release,
1279};
1280
1281#define DBG_REG(_r) { .addr = S3C2410_SDI##_r, .name = #_r }
1282
1283struct s3cmci_reg {
1284 unsigned short addr;
1285 unsigned char *name;
1286} debug_regs[] = {
1287 DBG_REG(CON),
1288 DBG_REG(PRE),
1289 DBG_REG(CMDARG),
1290 DBG_REG(CMDCON),
1291 DBG_REG(CMDSTAT),
1292 DBG_REG(RSP0),
1293 DBG_REG(RSP1),
1294 DBG_REG(RSP2),
1295 DBG_REG(RSP3),
1296 DBG_REG(TIMER),
1297 DBG_REG(BSIZE),
1298 DBG_REG(DCON),
1299 DBG_REG(DCNT),
1300 DBG_REG(DSTA),
1301 DBG_REG(FSTA),
1302 {}
1303};
1304
1305static int s3cmci_regs_show(struct seq_file *seq, void *v)
1306{
1307 struct s3cmci_host *host = seq->private;
1308 struct s3cmci_reg *rptr = debug_regs;
1309
1310 for (; rptr->name; rptr++)
1311 seq_printf(seq, "SDI%s\t=0x%08x\n", rptr->name,
1312 readl(host->base + rptr->addr));
1313
1314 seq_printf(seq, "SDIIMSK\t=0x%08x\n", readl(host->base + host->sdiimsk));
1315
1316 return 0;
1317}
1318
1319static int s3cmci_regs_open(struct inode *inode, struct file *file)
1320{
1321 return single_open(file, s3cmci_regs_show, inode->i_private);
1322}
1323
1324static const struct file_operations s3cmci_fops_regs = {
1325 .owner = THIS_MODULE,
1326 .open = s3cmci_regs_open,
1327 .read = seq_read,
1328 .llseek = seq_lseek,
1329 .release = single_release,
1330};
1331
1332static void s3cmci_debugfs_attach(struct s3cmci_host *host)
1333{
1334 struct device *dev = &host->pdev->dev;
1335
1336 host->debug_root = debugfs_create_dir(dev_name(dev), NULL);
1337 if (IS_ERR(host->debug_root)) {
1338 dev_err(dev, "failed to create debugfs root\n");
1339 return;
1340 }
1341
1342 host->debug_state = debugfs_create_file("state", 0444,
1343 host->debug_root, host,
1344 &s3cmci_fops_state);
1345
1346 if (IS_ERR(host->debug_state))
1347 dev_err(dev, "failed to create debug state file\n");
1348
1349 host->debug_regs = debugfs_create_file("regs", 0444,
1350 host->debug_root, host,
1351 &s3cmci_fops_regs);
1352
1353 if (IS_ERR(host->debug_regs))
1354 dev_err(dev, "failed to create debug regs file\n");
1355}
1356
1357static void s3cmci_debugfs_remove(struct s3cmci_host *host)
1358{
1359 debugfs_remove(host->debug_regs);
1360 debugfs_remove(host->debug_state);
1361 debugfs_remove(host->debug_root);
1362}
1363
1364#else
1365static inline void s3cmci_debugfs_attach(struct s3cmci_host *host) { }
1366static inline void s3cmci_debugfs_remove(struct s3cmci_host *host) { }
1367
1368#endif /* CONFIG_DEBUG_FS */
1369
1247static int __devinit s3cmci_probe(struct platform_device *pdev) 1370static int __devinit s3cmci_probe(struct platform_device *pdev)
1248{ 1371{
1249 struct s3cmci_host *host; 1372 struct s3cmci_host *host;
@@ -1435,6 +1558,8 @@ static int __devinit s3cmci_probe(struct platform_device *pdev)
1435 goto free_cpufreq; 1558 goto free_cpufreq;
1436 } 1559 }
1437 1560
1561 s3cmci_debugfs_attach(host);
1562
1438 platform_set_drvdata(pdev, mmc); 1563 platform_set_drvdata(pdev, mmc);
1439 dev_info(&pdev->dev, "initialisation done.\n"); 1564 dev_info(&pdev->dev, "initialisation done.\n");
1440 1565
@@ -1489,6 +1614,7 @@ static void s3cmci_shutdown(struct platform_device *pdev)
1489 if (host->irq_cd >= 0) 1614 if (host->irq_cd >= 0)
1490 free_irq(host->irq_cd, host); 1615 free_irq(host->irq_cd, host);
1491 1616
1617 s3cmci_debugfs_remove(host);
1492 s3cmci_cpufreq_deregister(host); 1618 s3cmci_cpufreq_deregister(host);
1493 mmc_remove_host(mmc); 1619 mmc_remove_host(mmc);
1494 clk_disable(host->clk); 1620 clk_disable(host->clk);
diff --git a/drivers/mmc/host/s3cmci.h b/drivers/mmc/host/s3cmci.h
index ca1ba3d58cfd..fc96194a06f4 100644
--- a/drivers/mmc/host/s3cmci.h
+++ b/drivers/mmc/host/s3cmci.h
@@ -68,6 +68,12 @@ struct s3cmci_host {
68 unsigned int ccnt, dcnt; 68 unsigned int ccnt, dcnt;
69 struct tasklet_struct pio_tasklet; 69 struct tasklet_struct pio_tasklet;
70 70
71#ifdef CONFIG_DEBUG_FS
72 struct dentry *debug_root;
73 struct dentry *debug_state;
74 struct dentry *debug_regs;
75#endif
76
71#ifdef CONFIG_CPU_FREQ 77#ifdef CONFIG_CPU_FREQ
72 struct notifier_block freq_transition; 78 struct notifier_block freq_transition;
73#endif 79#endif