aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bus/omap_l3_noc.c
diff options
context:
space:
mode:
authorNishanth Menon <nm@ti.com>2014-04-17 13:33:50 -0400
committerNishanth Menon <nm@ti.com>2014-05-05 15:33:58 -0400
commite4be3f3a040432398225d3634d44fc21f4807b7a (patch)
tree740df09c5e084c793de6417185e69ae9775766b6 /drivers/bus/omap_l3_noc.c
parentc98aa7aaa24b7687a170b93c4bf3111a6d166069 (diff)
bus: omap_l3_noc: improve readability by using helper for slave event parsing
Current interrupt handler does the first level parse to identify the slave and then handles the slave even identification, reporting and clearing of event as well. It is hence logical to split the handler into two where the primary handler just parses the flagmux till it identifies a slave and the slave handling, reporting and clearing is done in a helper function. While at it update the documentation in kerneldoc style. Signed-off-by: Nishanth Menon <nm@ti.com> Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Acked-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Tested-by: Darren Etheridge <detheridge@ti.com> Tested-by: Sekhar Nori <nsekhar@ti.com>
Diffstat (limited to 'drivers/bus/omap_l3_noc.c')
-rw-r--r--drivers/bus/omap_l3_noc.c211
1 files changed, 113 insertions, 98 deletions
diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 42e411457494..0691e6d9c1e4 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -26,14 +26,20 @@
26 26
27#include "omap_l3_noc.h" 27#include "omap_l3_noc.h"
28 28
29/* 29/**
30 * Interrupt Handler for L3 error detection. 30 * l3_handle_target() - Handle Target specific parse and reporting
31 * 1) Identify the L3 clockdomain partition to which the error belongs to. 31 * @l3: pointer to l3 struct
32 * 2) Identify the slave where the error information is logged 32 * @base: base address of clkdm
33 * 3) Print the logged information. 33 * @flag_mux: flagmux corresponding to the event
34 * 4) Add dump stack to provide kernel trace. 34 * @err_src: error source index of the slave (target)
35 * 35 *
36 * Two Types of errors : 36 * This does the second part of the error interrupt handling:
37 * 3) Parse in the slave information
38 * 4) Print the logged information.
39 * 5) Add dump stack to provide kernel trace.
40 * 6) Clear the source if known.
41 *
42 * This handles two types of errors:
37 * 1) Custom errors in L3 : 43 * 1) Custom errors in L3 :
38 * Target like DMM/FW/EMIF generates SRESP=ERR error 44 * Target like DMM/FW/EMIF generates SRESP=ERR error
39 * 2) Standard L3 error: 45 * 2) Standard L3 error:
@@ -49,22 +55,107 @@
49 * can be trapped as well. But the trapping is implemented as part 55 * can be trapped as well. But the trapping is implemented as part
50 * secure software and hence need not be implemented here. 56 * secure software and hence need not be implemented here.
51 */ 57 */
52static irqreturn_t l3_interrupt_handler(int irq, void *_l3) 58static int l3_handle_target(struct omap_l3 *l3, void __iomem *base,
59 struct l3_flagmux_data *flag_mux, int err_src)
53{ 60{
54 61 int k;
55 struct omap_l3 *l3 = _l3; 62 u32 std_err_main, clear, masterid;
56 int inttype, i, k; 63 void __iomem *l3_targ_base;
57 int err_src = 0;
58 u32 std_err_main, err_reg, clear, masterid;
59 void __iomem *base, *l3_targ_base;
60 void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr; 64 void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
61 char *target_name, *master_name = "UN IDENTIFIED";
62 struct l3_target_data *l3_targ_inst; 65 struct l3_target_data *l3_targ_inst;
63 struct l3_flagmux_data *flag_mux;
64 struct l3_masters_data *master; 66 struct l3_masters_data *master;
67 char *target_name, *master_name = "UN IDENTIFIED";
65 char *err_description; 68 char *err_description;
66 char err_string[30] = { 0 }; 69 char err_string[30] = { 0 };
67 70
71 /* We DONOT expect err_src to go out of bounds */
72 BUG_ON(err_src > MAX_CLKDM_TARGETS);
73
74 if (err_src < flag_mux->num_targ_data) {
75 l3_targ_inst = &flag_mux->l3_targ[err_src];
76 target_name = l3_targ_inst->name;
77 l3_targ_base = base + l3_targ_inst->offset;
78 } else {
79 target_name = L3_TARGET_NOT_SUPPORTED;
80 }
81
82 if (target_name == L3_TARGET_NOT_SUPPORTED)
83 return -ENODEV;
84
85 /* Read the stderrlog_main_source from clk domain */
86 l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
87 l3_targ_slvofslsb = l3_targ_base + L3_TARG_STDERRLOG_SLVOFSLSB;
88
89 std_err_main = readl_relaxed(l3_targ_stderr);
90
91 switch (std_err_main & CUSTOM_ERROR) {
92 case STANDARD_ERROR:
93 err_description = "Standard";
94 snprintf(err_string, sizeof(err_string),
95 ": At Address: 0x%08X ",
96 readl_relaxed(l3_targ_slvofslsb));
97
98 l3_targ_mstaddr = l3_targ_base + L3_TARG_STDERRLOG_MSTADDR;
99 break;
100
101 case CUSTOM_ERROR:
102 err_description = "Custom";
103
104 l3_targ_mstaddr = l3_targ_base +
105 L3_TARG_STDERRLOG_CINFO_MSTADDR;
106 break;
107
108 default:
109 /* Nothing to be handled here as of now */
110 return 0;
111 }
112
113 /* STDERRLOG_MSTADDR Stores the NTTP master address. */
114 masterid = (readl_relaxed(l3_targ_mstaddr) &
115 l3->mst_addr_mask) >> __ffs(l3->mst_addr_mask);
116
117 for (k = 0, master = l3->l3_masters; k < l3->num_masters;
118 k++, master++) {
119 if (masterid == master->id) {
120 master_name = master->name;
121 break;
122 }
123 }
124
125 WARN(true,
126 "%s:L3 %s Error: MASTER %s TARGET %s%s\n",
127 dev_name(l3->dev),
128 err_description,
129 master_name, target_name,
130 err_string);
131
132 /* clear the std error log*/
133 clear = std_err_main | CLEAR_STDERR_LOG;
134 writel_relaxed(clear, l3_targ_stderr);
135
136 return 0;
137}
138
139/**
140 * l3_interrupt_handler() - interrupt handler for l3 events
141 * @irq: irq number
142 * @_l3: pointer to l3 structure
143 *
144 * Interrupt Handler for L3 error detection.
145 * 1) Identify the L3 clockdomain partition to which the error belongs to.
146 * 2) Identify the slave where the error information is logged
147 * ... handle the slave event..
148 * 7) if the slave is unknown, mask out the slave.
149 */
150static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
151{
152 struct omap_l3 *l3 = _l3;
153 int inttype, i, ret;
154 int err_src = 0;
155 u32 err_reg, mask_val;
156 void __iomem *base, *mask_reg;
157 struct l3_flagmux_data *flag_mux;
158
68 /* Get the Type of interrupt */ 159 /* Get the Type of interrupt */
69 inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR; 160 inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
70 161
@@ -80,35 +171,18 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
80 171
81 /* Get the corresponding error and analyse */ 172 /* Get the corresponding error and analyse */
82 if (err_reg) { 173 if (err_reg) {
83 bool std_err = true;
84
85 /* Identify the source from control status register */ 174 /* Identify the source from control status register */
86 err_src = __ffs(err_reg); 175 err_src = __ffs(err_reg);
87 176
88 /* We DONOT expect err_src to go out of bounds */ 177 ret = l3_handle_target(l3, base, flag_mux, err_src);
89 BUG_ON(err_src > MAX_CLKDM_TARGETS);
90
91 if (err_src < flag_mux->num_targ_data) {
92 l3_targ_inst = &flag_mux->l3_targ[err_src];
93 target_name = l3_targ_inst->name;
94 l3_targ_base = base + l3_targ_inst->offset;
95 } else {
96 target_name = L3_TARGET_NOT_SUPPORTED;
97 }
98 178
99 /* 179 /*
100 * If we do not know of a register offset to decode 180 * Certain plaforms may have "undocumented" status
101 * and clear, then mask. 181 * pending on boot. So dont generate a severe warning
182 * here. Just mask it off to prevent the error from
183 * reoccuring and locking up the system.
102 */ 184 */
103 if (target_name == L3_TARGET_NOT_SUPPORTED) { 185 if (ret) {
104 u32 mask_val;
105 void __iomem *mask_reg;
106
107 /*
108 * Certain plaforms may have "undocumented"
109 * status pending on boot.. So dont generate
110 * a severe warning here.
111 */
112 dev_err(l3->dev, 186 dev_err(l3->dev,
113 "L3 %s error: target %d mod:%d %s\n", 187 "L3 %s error: target %d mod:%d %s\n",
114 inttype ? "debug" : "application", 188 inttype ? "debug" : "application",
@@ -119,67 +193,8 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
119 mask_val = readl_relaxed(mask_reg); 193 mask_val = readl_relaxed(mask_reg);
120 mask_val &= ~(1 << err_src); 194 mask_val &= ~(1 << err_src);
121 writel_relaxed(mask_val, mask_reg); 195 writel_relaxed(mask_val, mask_reg);
122
123 break;
124 } 196 }
125 197
126 /* Read the stderrlog_main_source from clk domain */
127 l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
128 l3_targ_slvofslsb = l3_targ_base +
129 L3_TARG_STDERRLOG_SLVOFSLSB;
130
131 std_err_main = readl_relaxed(l3_targ_stderr);
132
133 switch (std_err_main & CUSTOM_ERROR) {
134 case STANDARD_ERROR:
135 err_description = "Standard";
136 snprintf(err_string, sizeof(err_string),
137 ": At Address: 0x%08X ",
138 readl_relaxed(l3_targ_slvofslsb));
139
140 l3_targ_mstaddr = l3_targ_base +
141 L3_TARG_STDERRLOG_MSTADDR;
142 break;
143
144 case CUSTOM_ERROR:
145 err_description = "Custom";
146
147 l3_targ_mstaddr = l3_targ_base +
148 L3_TARG_STDERRLOG_CINFO_MSTADDR;
149 break;
150
151 default:
152 std_err = false;
153 /* Nothing to be handled here as of now */
154 break;
155 }
156
157 if (!std_err)
158 break;
159
160 /* STDERRLOG_MSTADDR Stores the NTTP master address. */
161 masterid = (readl_relaxed(l3_targ_mstaddr) &
162 l3->mst_addr_mask) >>
163 __ffs(l3->mst_addr_mask);
164
165 for (k = 0, master = l3->l3_masters;
166 k < l3->num_masters; k++, master++) {
167 if (masterid == master->id) {
168 master_name = master->name;
169 break;
170 }
171 }
172
173 WARN(true,
174 "%s:L3 %s Error: MASTER %s TARGET %s%s\n",
175 dev_name(l3->dev),
176 err_description,
177 master_name, target_name,
178 err_string);
179 /* clear the std error log*/
180 clear = std_err_main | CLEAR_STDERR_LOG;
181 writel_relaxed(clear, l3_targ_stderr);
182
183 /* Error found so break the for loop */ 198 /* Error found so break the for loop */
184 break; 199 break;
185 } 200 }