aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Mayer <markus.mayer@linaro.org>2014-01-06 16:56:10 -0500
committerWim Van Sebroeck <wim@iguana.be>2014-01-28 15:17:53 -0500
commit6e2ac20e9c47cf26a1dd5a0f05b93ef0afd3c1c5 (patch)
tree05126e58c1dc75a751f7552934fb0561057344d3
parent6adb730dc2085c16c52a2f991cc1661e4a7fd6d5 (diff)
watchdog: bcm281xx: Debugfs support
This change introduces debugfs support for the BCM281xx watchdog driver. Signed-off-by: Markus Mayer <markus.mayer@linaro.org> Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
-rw-r--r--arch/arm/configs/bcm_defconfig1
-rw-r--r--drivers/watchdog/Kconfig10
-rw-r--r--drivers/watchdog/bcm_kona_wdt.c108
3 files changed, 115 insertions, 4 deletions
diff --git a/arch/arm/configs/bcm_defconfig b/arch/arm/configs/bcm_defconfig
index fc3afd887a26..2519d6de0640 100644
--- a/arch/arm/configs/bcm_defconfig
+++ b/arch/arm/configs/bcm_defconfig
@@ -128,3 +128,4 @@ CONFIG_AVERAGE=y
128CONFIG_PINCTRL_CAPRI=y 128CONFIG_PINCTRL_CAPRI=y
129CONFIG_WATCHDOG=y 129CONFIG_WATCHDOG=y
130CONFIG_BCM_KONA_WDT=y 130CONFIG_BCM_KONA_WDT=y
131CONFIG_BCM_KONA_WDT_DEBUG=y
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 042e4521a8b8..1491f0f4d41d 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1151,6 +1151,16 @@ config BCM_KONA_WDT
1151 Say 'Y' or 'M' here to enable the driver. The module will be called 1151 Say 'Y' or 'M' here to enable the driver. The module will be called
1152 bcm_kona_wdt. 1152 bcm_kona_wdt.
1153 1153
1154config BCM_KONA_WDT_DEBUG
1155 bool "DEBUGFS support for BCM Kona Watchdog"
1156 depends on BCM_KONA_WDT
1157 help
1158 If enabled, adds /sys/kernel/debug/bcm_kona_wdt/info which provides
1159 access to the driver's internal data structures as well as watchdog
1160 timer hardware registres.
1161
1162 If in doubt, say 'N'.
1163
1154config LANTIQ_WDT 1164config LANTIQ_WDT
1155 tristate "Lantiq SoC watchdog" 1165 tristate "Lantiq SoC watchdog"
1156 depends on LANTIQ 1166 depends on LANTIQ
diff --git a/drivers/watchdog/bcm_kona_wdt.c b/drivers/watchdog/bcm_kona_wdt.c
index 7e41a83eb45e..9c248099f4a2 100644
--- a/drivers/watchdog/bcm_kona_wdt.c
+++ b/drivers/watchdog/bcm_kona_wdt.c
@@ -11,6 +11,7 @@
11 * GNU General Public License for more details. 11 * GNU General Public License for more details.
12 */ 12 */
13 13
14#include <linux/debugfs.h>
14#include <linux/delay.h> 15#include <linux/delay.h>
15#include <linux/err.h> 16#include <linux/err.h>
16#include <linux/io.h> 17#include <linux/io.h>
@@ -55,9 +56,13 @@ struct bcm_kona_wdt {
55 */ 56 */
56 int resolution; 57 int resolution;
57 spinlock_t lock; 58 spinlock_t lock;
59#ifdef CONFIG_BCM_KONA_WDT_DEBUG
60 unsigned long busy_count;
61 struct dentry *debugfs;
62#endif
58}; 63};
59 64
60static int secure_register_read(void __iomem *addr) 65static int secure_register_read(struct bcm_kona_wdt *wdt, uint32_t offset)
61{ 66{
62 uint32_t val; 67 uint32_t val;
63 unsigned count = 0; 68 unsigned count = 0;
@@ -70,10 +75,16 @@ static int secure_register_read(void __iomem *addr)
70 do { 75 do {
71 if (unlikely(count > 1)) 76 if (unlikely(count > 1))
72 udelay(5); 77 udelay(5);
73 val = readl_relaxed(addr); 78 val = readl_relaxed(wdt->base + offset);
74 count++; 79 count++;
75 } while ((val & SECWDOG_WD_LOAD_FLAG) && count < SECWDOG_MAX_TRY); 80 } while ((val & SECWDOG_WD_LOAD_FLAG) && count < SECWDOG_MAX_TRY);
76 81
82#ifdef CONFIG_BCM_KONA_WDT_DEBUG
83 /* Remember the maximum number iterations due to WD_LOAD_FLAG */
84 if (count > wdt->busy_count)
85 wdt->busy_count = count;
86#endif
87
77 /* This is the only place we return a negative value. */ 88 /* This is the only place we return a negative value. */
78 if (val & SECWDOG_WD_LOAD_FLAG) 89 if (val & SECWDOG_WD_LOAD_FLAG)
79 return -ETIMEDOUT; 90 return -ETIMEDOUT;
@@ -84,6 +95,93 @@ static int secure_register_read(void __iomem *addr)
84 return val; 95 return val;
85} 96}
86 97
98#ifdef CONFIG_BCM_KONA_WDT_DEBUG
99
100static int bcm_kona_wdt_dbg_show(struct seq_file *s, void *data)
101{
102 int ctl_val, cur_val, ret;
103 unsigned long flags;
104 struct bcm_kona_wdt *wdt = s->private;
105
106 if (!wdt)
107 return seq_puts(s, "No device pointer\n");
108
109 spin_lock_irqsave(&wdt->lock, flags);
110 ctl_val = secure_register_read(wdt, SECWDOG_CTRL_REG);
111 cur_val = secure_register_read(wdt, SECWDOG_COUNT_REG);
112 spin_unlock_irqrestore(&wdt->lock, flags);
113
114 if (ctl_val < 0 || cur_val < 0) {
115 ret = seq_puts(s, "Error accessing hardware\n");
116 } else {
117 int ctl, cur, ctl_sec, cur_sec, res;
118
119 ctl = ctl_val & SECWDOG_COUNT_MASK;
120 res = (ctl_val & SECWDOG_RES_MASK) >> SECWDOG_CLKS_SHIFT;
121 cur = cur_val & SECWDOG_COUNT_MASK;
122 ctl_sec = TICKS_TO_SECS(ctl, wdt);
123 cur_sec = TICKS_TO_SECS(cur, wdt);
124 ret = seq_printf(s, "Resolution: %d / %d\n"
125 "Control: %d s / %d (%#x) ticks\n"
126 "Current: %d s / %d (%#x) ticks\n"
127 "Busy count: %lu\n", res,
128 wdt->resolution, ctl_sec, ctl, ctl, cur_sec,
129 cur, cur, wdt->busy_count);
130 }
131
132 return ret;
133}
134
135static int bcm_kona_dbg_open(struct inode *inode, struct file *file)
136{
137 return single_open(file, bcm_kona_wdt_dbg_show, inode->i_private);
138}
139
140static const struct file_operations bcm_kona_dbg_operations = {
141 .open = bcm_kona_dbg_open,
142 .read = seq_read,
143 .llseek = seq_lseek,
144 .release = single_release,
145};
146
147static void bcm_kona_wdt_debug_init(struct platform_device *pdev)
148{
149 struct dentry *dir;
150 struct bcm_kona_wdt *wdt = platform_get_drvdata(pdev);
151
152 if (!wdt)
153 return;
154
155 wdt->debugfs = NULL;
156
157 dir = debugfs_create_dir(BCM_KONA_WDT_NAME, NULL);
158 if (IS_ERR_OR_NULL(dir))
159 return;
160
161 if (debugfs_create_file("info", S_IFREG | S_IRUGO, dir, wdt,
162 &bcm_kona_dbg_operations))
163 wdt->debugfs = dir;
164 else
165 debugfs_remove_recursive(dir);
166}
167
168static void bcm_kona_wdt_debug_exit(struct platform_device *pdev)
169{
170 struct bcm_kona_wdt *wdt = platform_get_drvdata(pdev);
171
172 if (wdt && wdt->debugfs) {
173 debugfs_remove_recursive(wdt->debugfs);
174 wdt->debugfs = NULL;
175 }
176}
177
178#else
179
180static void bcm_kona_wdt_debug_init(struct platform_device *pdev) {}
181static void bcm_kona_wdt_debug_exit(struct platform_device *pdev) {}
182
183#endif /* CONFIG_BCM_KONA_WDT_DEBUG */
184
87static int bcm_kona_wdt_ctrl_reg_modify(struct bcm_kona_wdt *wdt, 185static int bcm_kona_wdt_ctrl_reg_modify(struct bcm_kona_wdt *wdt,
88 unsigned mask, unsigned newval) 186 unsigned mask, unsigned newval)
89{ 187{
@@ -93,7 +191,7 @@ static int bcm_kona_wdt_ctrl_reg_modify(struct bcm_kona_wdt *wdt,
93 191
94 spin_lock_irqsave(&wdt->lock, flags); 192 spin_lock_irqsave(&wdt->lock, flags);
95 193
96 val = secure_register_read(wdt->base + SECWDOG_CTRL_REG); 194 val = secure_register_read(wdt, SECWDOG_CTRL_REG);
97 if (val < 0) { 195 if (val < 0) {
98 ret = val; 196 ret = val;
99 } else { 197 } else {
@@ -140,7 +238,7 @@ static unsigned int bcm_kona_wdt_get_timeleft(struct watchdog_device *wdog)
140 unsigned long flags; 238 unsigned long flags;
141 239
142 spin_lock_irqsave(&wdt->lock, flags); 240 spin_lock_irqsave(&wdt->lock, flags);
143 val = secure_register_read(wdt->base + SECWDOG_COUNT_REG); 241 val = secure_register_read(wdt, SECWDOG_COUNT_REG);
144 spin_unlock_irqrestore(&wdt->lock, flags); 242 spin_unlock_irqrestore(&wdt->lock, flags);
145 243
146 if (val < 0) 244 if (val < 0)
@@ -229,6 +327,7 @@ static int bcm_kona_wdt_probe(struct platform_device *pdev)
229 return ret; 327 return ret;
230 } 328 }
231 329
330 bcm_kona_wdt_debug_init(pdev);
232 dev_dbg(dev, "Broadcom Kona Watchdog Timer"); 331 dev_dbg(dev, "Broadcom Kona Watchdog Timer");
233 332
234 return 0; 333 return 0;
@@ -236,6 +335,7 @@ static int bcm_kona_wdt_probe(struct platform_device *pdev)
236 335
237static int bcm_kona_wdt_remove(struct platform_device *pdev) 336static int bcm_kona_wdt_remove(struct platform_device *pdev)
238{ 337{
338 bcm_kona_wdt_debug_exit(pdev);
239 bcm_kona_wdt_shutdown(pdev); 339 bcm_kona_wdt_shutdown(pdev);
240 watchdog_unregister_device(&bcm_kona_wdt_wdd); 340 watchdog_unregister_device(&bcm_kona_wdt_wdd);
241 dev_dbg(&pdev->dev, "Watchdog driver disabled"); 341 dev_dbg(&pdev->dev, "Watchdog driver disabled");