aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bus
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2014-05-26 16:29:22 -0400
committerOlof Johansson <olof@lixom.net>2014-05-26 16:29:22 -0400
commit75d6bc5f7ab41a166deb6e9ebc8434706799fb00 (patch)
treea9fddb9739c2e478d61d47eb5bf22866fe27a7f7 /drivers/bus
parent1b7f0c7b931864642e825a6fd01cde5881b064cc (diff)
parent27b7d5f3cc49f2e5cd6c005d73696058b7140c5c (diff)
Merge tag 'omap-for-v3.16/l3-noc-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/drivers
Merge "ARM: omap l3-noc bus driver changes for v3.16 merge window, resend" from Tony Lindgren: Improvments to omap l3-noc bus driver for v3.16 merge window to add support for am347x and dra7. * tag 'omap-for-v3.16/l3-noc-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: (25 commits) bus: omap_l3_noc: Add AM4372 interconnect error data bus: omap_l3_noc: Add DRA7 interconnect error data bus: omap_l3_noc: introduce concept of submodule bus: omap_l3_noc: Add information about the context of operation bus: omap_l3_noc: add information about the type of operation bus: omap_l3_noc: ignore masked out unclearable targets bus: omap_l3_noc: improve readability by using helper for slave event parsing bus: omap_l3_noc: make error reporting and handling common bus: omap_l3_noc: fix masterid detection bus: omap_l3_noc: convert flagmux information into a structure bus: omap_l3_noc: use of_match_data to pick up SoC information bus: omap_l3_noc: Add support for discountinous flag mux input numbers bus: omap_l3_noc: convert target information into a structure bus: omap_l3_noc: move L3 master data structure out bus: omap_l3_noc: un-obfuscate l3_targ address computation bus: omap_l3_noc: switch over to relaxed variants of readl/writel bus: omap_l3_noc: populate l3->dev and use it bus: omap_l3_noc: remove iclk from omap_l3 struct bus: omap_l3_noc: rename functions and data to omap_l3 bus: omap_l3_noc: Fix copyright information ... Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'drivers/bus')
-rw-r--r--drivers/bus/omap_l3_noc.c406
-rw-r--r--drivers/bus/omap_l3_noc.h545
2 files changed, 651 insertions, 300 deletions
diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index feeecae623f6..531ae591783b 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -1,43 +1,45 @@
1/* 1/*
2 * OMAP4XXX L3 Interconnect error handling driver 2 * OMAP L3 Interconnect error handling driver
3 * 3 *
4 * Copyright (C) 2011 Texas Corporation 4 * Copyright (C) 2011-2014 Texas Instruments Incorporated - http://www.ti.com/
5 * Santosh Shilimkar <santosh.shilimkar@ti.com> 5 * Santosh Shilimkar <santosh.shilimkar@ti.com>
6 * Sricharan <r.sricharan@ti.com> 6 * Sricharan <r.sricharan@ti.com>
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License version 2 as
10 * the Free Software Foundation; either version 2 of the License, or 10 * published by the Free Software Foundation.
11 * (at your option) any later version.
12 * 11 *
13 * This program is distributed in the hope that it will be useful, 12 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * kind, whether express or implied; without even the implied warranty
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 15 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 * USA
22 */ 16 */
23#include <linux/module.h>
24#include <linux/init.h> 17#include <linux/init.h>
25#include <linux/io.h>
26#include <linux/platform_device.h>
27#include <linux/interrupt.h> 18#include <linux/interrupt.h>
19#include <linux/io.h>
28#include <linux/kernel.h> 20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/of_device.h>
23#include <linux/of.h>
24#include <linux/platform_device.h>
29#include <linux/slab.h> 25#include <linux/slab.h>
30 26
31#include "omap_l3_noc.h" 27#include "omap_l3_noc.h"
32 28
33/* 29/**
34 * Interrupt Handler for L3 error detection. 30 * l3_handle_target() - Handle Target specific parse and reporting
35 * 1) Identify the L3 clockdomain partition to which the error belongs to. 31 * @l3: pointer to l3 struct
36 * 2) Identify the slave where the error information is logged 32 * @base: base address of clkdm
37 * 3) Print the logged information. 33 * @flag_mux: flagmux corresponding to the event
38 * 4) Add dump stack to provide kernel trace. 34 * @err_src: error source index of the slave (target)
39 * 35 *
40 * 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:
41 * 1) Custom errors in L3 : 43 * 1) Custom errors in L3 :
42 * Target like DMM/FW/EMIF generates SRESP=ERR error 44 * Target like DMM/FW/EMIF generates SRESP=ERR error
43 * 2) Standard L3 error: 45 * 2) Standard L3 error:
@@ -53,214 +55,264 @@
53 * 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
54 * secure software and hence need not be implemented here. 56 * secure software and hence need not be implemented here.
55 */ 57 */
56static 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)
57{ 60{
61 int k;
62 u32 std_err_main, clear, masterid;
63 u8 op_code, m_req_info;
64 void __iomem *l3_targ_base;
65 void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
66 void __iomem *l3_targ_hdr, *l3_targ_info;
67 struct l3_target_data *l3_targ_inst;
68 struct l3_masters_data *master;
69 char *target_name, *master_name = "UN IDENTIFIED";
70 char *err_description;
71 char err_string[30] = { 0 };
72 char info_string[60] = { 0 };
73
74 /* We DONOT expect err_src to go out of bounds */
75 BUG_ON(err_src > MAX_CLKDM_TARGETS);
76
77 if (err_src < flag_mux->num_targ_data) {
78 l3_targ_inst = &flag_mux->l3_targ[err_src];
79 target_name = l3_targ_inst->name;
80 l3_targ_base = base + l3_targ_inst->offset;
81 } else {
82 target_name = L3_TARGET_NOT_SUPPORTED;
83 }
58 84
59 struct omap4_l3 *l3 = _l3; 85 if (target_name == L3_TARGET_NOT_SUPPORTED)
60 int inttype, i, k; 86 return -ENODEV;
87
88 /* Read the stderrlog_main_source from clk domain */
89 l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
90 l3_targ_slvofslsb = l3_targ_base + L3_TARG_STDERRLOG_SLVOFSLSB;
91
92 std_err_main = readl_relaxed(l3_targ_stderr);
93
94 switch (std_err_main & CUSTOM_ERROR) {
95 case STANDARD_ERROR:
96 err_description = "Standard";
97 snprintf(err_string, sizeof(err_string),
98 ": At Address: 0x%08X ",
99 readl_relaxed(l3_targ_slvofslsb));
100
101 l3_targ_mstaddr = l3_targ_base + L3_TARG_STDERRLOG_MSTADDR;
102 l3_targ_hdr = l3_targ_base + L3_TARG_STDERRLOG_HDR;
103 l3_targ_info = l3_targ_base + L3_TARG_STDERRLOG_INFO;
104 break;
105
106 case CUSTOM_ERROR:
107 err_description = "Custom";
108
109 l3_targ_mstaddr = l3_targ_base +
110 L3_TARG_STDERRLOG_CINFO_MSTADDR;
111 l3_targ_hdr = l3_targ_base + L3_TARG_STDERRLOG_CINFO_OPCODE;
112 l3_targ_info = l3_targ_base + L3_TARG_STDERRLOG_CINFO_INFO;
113 break;
114
115 default:
116 /* Nothing to be handled here as of now */
117 return 0;
118 }
119
120 /* STDERRLOG_MSTADDR Stores the NTTP master address. */
121 masterid = (readl_relaxed(l3_targ_mstaddr) &
122 l3->mst_addr_mask) >> __ffs(l3->mst_addr_mask);
123
124 for (k = 0, master = l3->l3_masters; k < l3->num_masters;
125 k++, master++) {
126 if (masterid == master->id) {
127 master_name = master->name;
128 break;
129 }
130 }
131
132 op_code = readl_relaxed(l3_targ_hdr) & 0x7;
133
134 m_req_info = readl_relaxed(l3_targ_info) & 0xF;
135 snprintf(info_string, sizeof(info_string),
136 ": %s in %s mode during %s access",
137 (m_req_info & BIT(0)) ? "Opcode Fetch" : "Data Access",
138 (m_req_info & BIT(1)) ? "Supervisor" : "User",
139 (m_req_info & BIT(3)) ? "Debug" : "Functional");
140
141 WARN(true,
142 "%s:L3 %s Error: MASTER %s TARGET %s (%s)%s%s\n",
143 dev_name(l3->dev),
144 err_description,
145 master_name, target_name,
146 l3_transaction_type[op_code],
147 err_string, info_string);
148
149 /* clear the std error log*/
150 clear = std_err_main | CLEAR_STDERR_LOG;
151 writel_relaxed(clear, l3_targ_stderr);
152
153 return 0;
154}
155
156/**
157 * l3_interrupt_handler() - interrupt handler for l3 events
158 * @irq: irq number
159 * @_l3: pointer to l3 structure
160 *
161 * Interrupt Handler for L3 error detection.
162 * 1) Identify the L3 clockdomain partition to which the error belongs to.
163 * 2) Identify the slave where the error information is logged
164 * ... handle the slave event..
165 * 7) if the slave is unknown, mask out the slave.
166 */
167static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
168{
169 struct omap_l3 *l3 = _l3;
170 int inttype, i, ret;
61 int err_src = 0; 171 int err_src = 0;
62 u32 std_err_main, err_reg, clear, masterid; 172 u32 err_reg, mask_val;
63 void __iomem *base, *l3_targ_base; 173 void __iomem *base, *mask_reg;
64 char *target_name, *master_name = "UN IDENTIFIED"; 174 struct l3_flagmux_data *flag_mux;
65 175
66 /* Get the Type of interrupt */ 176 /* Get the Type of interrupt */
67 inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR; 177 inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
68 178
69 for (i = 0; i < L3_MODULES; i++) { 179 for (i = 0; i < l3->num_modules; i++) {
70 /* 180 /*
71 * Read the regerr register of the clock domain 181 * Read the regerr register of the clock domain
72 * to determine the source 182 * to determine the source
73 */ 183 */
74 base = l3->l3_base[i]; 184 base = l3->l3_base[i];
75 err_reg = __raw_readl(base + l3_flagmux[i] + 185 flag_mux = l3->l3_flagmux[i];
76 + L3_FLAGMUX_REGERR0 + (inttype << 3)); 186 err_reg = readl_relaxed(base + flag_mux->offset +
187 L3_FLAGMUX_REGERR0 + (inttype << 3));
188
189 err_reg &= ~(inttype ? flag_mux->mask_app_bits :
190 flag_mux->mask_dbg_bits);
77 191
78 /* Get the corresponding error and analyse */ 192 /* Get the corresponding error and analyse */
79 if (err_reg) { 193 if (err_reg) {
80 /* Identify the source from control status register */ 194 /* Identify the source from control status register */
81 err_src = __ffs(err_reg); 195 err_src = __ffs(err_reg);
82 196
83 /* Read the stderrlog_main_source from clk domain */ 197 ret = l3_handle_target(l3, base, flag_mux, err_src);
84 l3_targ_base = base + *(l3_targ[i] + err_src); 198
85 std_err_main = __raw_readl(l3_targ_base + 199 /*
86 L3_TARG_STDERRLOG_MAIN); 200 * Certain plaforms may have "undocumented" status
87 masterid = __raw_readl(l3_targ_base + 201 * pending on boot. So dont generate a severe warning
88 L3_TARG_STDERRLOG_MSTADDR); 202 * here. Just mask it off to prevent the error from
89 203 * reoccuring and locking up the system.
90 switch (std_err_main & CUSTOM_ERROR) { 204 */
91 case STANDARD_ERROR: 205 if (ret) {
92 target_name = 206 dev_err(l3->dev,
93 l3_targ_inst_name[i][err_src]; 207 "L3 %s error: target %d mod:%d %s\n",
94 WARN(true, "L3 standard error: TARGET:%s at address 0x%x\n", 208 inttype ? "debug" : "application",
95 target_name, 209 err_src, i, "(unclearable)");
96 __raw_readl(l3_targ_base + 210
97 L3_TARG_STDERRLOG_SLVOFSLSB)); 211 mask_reg = base + flag_mux->offset +
98 /* clear the std error log*/ 212 L3_FLAGMUX_MASK0 + (inttype << 3);
99 clear = std_err_main | CLEAR_STDERR_LOG; 213 mask_val = readl_relaxed(mask_reg);
100 writel(clear, l3_targ_base + 214 mask_val &= ~(1 << err_src);
101 L3_TARG_STDERRLOG_MAIN); 215 writel_relaxed(mask_val, mask_reg);
102 break; 216
103 217 /* Mark these bits as to be ignored */
104 case CUSTOM_ERROR: 218 if (inttype)
105 target_name = 219 flag_mux->mask_app_bits |= 1 << err_src;
106 l3_targ_inst_name[i][err_src]; 220 else
107 for (k = 0; k < NUM_OF_L3_MASTERS; k++) { 221 flag_mux->mask_dbg_bits |= 1 << err_src;
108 if (masterid == l3_masters[k].id)
109 master_name =
110 l3_masters[k].name;
111 }
112 WARN(true, "L3 custom error: MASTER:%s TARGET:%s\n",
113 master_name, target_name);
114 /* clear the std error log*/
115 clear = std_err_main | CLEAR_STDERR_LOG;
116 writel(clear, l3_targ_base +
117 L3_TARG_STDERRLOG_MAIN);
118 break;
119
120 default:
121 /* Nothing to be handled here as of now */
122 break;
123 } 222 }
124 /* Error found so break the for loop */ 223
125 break; 224 /* Error found so break the for loop */
225 break;
126 } 226 }
127 } 227 }
128 return IRQ_HANDLED; 228 return IRQ_HANDLED;
129} 229}
130 230
131static int omap4_l3_probe(struct platform_device *pdev) 231static const struct of_device_id l3_noc_match[] = {
232 {.compatible = "ti,omap4-l3-noc", .data = &omap_l3_data},
233 {.compatible = "ti,dra7-l3-noc", .data = &dra_l3_data},
234 {.compatible = "ti,am4372-l3-noc", .data = &am4372_l3_data},
235 {},
236};
237MODULE_DEVICE_TABLE(of, l3_noc_match);
238
239static int omap_l3_probe(struct platform_device *pdev)
132{ 240{
133 static struct omap4_l3 *l3; 241 const struct of_device_id *of_id;
134 struct resource *res; 242 static struct omap_l3 *l3;
135 int ret; 243 int ret, i, res_idx;
244
245 of_id = of_match_device(l3_noc_match, &pdev->dev);
246 if (!of_id) {
247 dev_err(&pdev->dev, "OF data missing\n");
248 return -EINVAL;
249 }
136 250
137 l3 = kzalloc(sizeof(*l3), GFP_KERNEL); 251 l3 = devm_kzalloc(&pdev->dev, sizeof(*l3), GFP_KERNEL);
138 if (!l3) 252 if (!l3)
139 return -ENOMEM; 253 return -ENOMEM;
140 254
255 memcpy(l3, of_id->data, sizeof(*l3));
256 l3->dev = &pdev->dev;
141 platform_set_drvdata(pdev, l3); 257 platform_set_drvdata(pdev, l3);
142 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
143 if (!res) {
144 dev_err(&pdev->dev, "couldn't find resource 0\n");
145 ret = -ENODEV;
146 goto err0;
147 }
148
149 l3->l3_base[0] = ioremap(res->start, resource_size(res));
150 if (!l3->l3_base[0]) {
151 dev_err(&pdev->dev, "ioremap failed\n");
152 ret = -ENOMEM;
153 goto err0;
154 }
155
156 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
157 if (!res) {
158 dev_err(&pdev->dev, "couldn't find resource 1\n");
159 ret = -ENODEV;
160 goto err1;
161 }
162
163 l3->l3_base[1] = ioremap(res->start, resource_size(res));
164 if (!l3->l3_base[1]) {
165 dev_err(&pdev->dev, "ioremap failed\n");
166 ret = -ENOMEM;
167 goto err1;
168 }
169 258
170 res = platform_get_resource(pdev, IORESOURCE_MEM, 2); 259 /* Get mem resources */
171 if (!res) { 260 for (i = 0, res_idx = 0; i < l3->num_modules; i++) {
172 dev_err(&pdev->dev, "couldn't find resource 2\n"); 261 struct resource *res;
173 ret = -ENODEV;
174 goto err2;
175 }
176 262
177 l3->l3_base[2] = ioremap(res->start, resource_size(res)); 263 if (l3->l3_base[i] == L3_BASE_IS_SUBMODULE) {
178 if (!l3->l3_base[2]) { 264 /* First entry cannot be submodule */
179 dev_err(&pdev->dev, "ioremap failed\n"); 265 BUG_ON(i == 0);
180 ret = -ENOMEM; 266 l3->l3_base[i] = l3->l3_base[i - 1];
181 goto err2; 267 continue;
268 }
269 res = platform_get_resource(pdev, IORESOURCE_MEM, res_idx);
270 l3->l3_base[i] = devm_ioremap_resource(&pdev->dev, res);
271 if (IS_ERR(l3->l3_base[i])) {
272 dev_err(l3->dev, "ioremap %d failed\n", i);
273 return PTR_ERR(l3->l3_base[i]);
274 }
275 res_idx++;
182 } 276 }
183 277
184 /* 278 /*
185 * Setup interrupt Handlers 279 * Setup interrupt Handlers
186 */ 280 */
187 l3->debug_irq = platform_get_irq(pdev, 0); 281 l3->debug_irq = platform_get_irq(pdev, 0);
188 ret = request_irq(l3->debug_irq, 282 ret = devm_request_irq(l3->dev, l3->debug_irq, l3_interrupt_handler,
189 l3_interrupt_handler, 283 IRQF_DISABLED, "l3-dbg-irq", l3);
190 IRQF_DISABLED, "l3-dbg-irq", l3);
191 if (ret) { 284 if (ret) {
192 pr_crit("L3: request_irq failed to register for 0x%x\n", 285 dev_err(l3->dev, "request_irq failed for %d\n",
193 l3->debug_irq); 286 l3->debug_irq);
194 goto err3; 287 return ret;
195 } 288 }
196 289
197 l3->app_irq = platform_get_irq(pdev, 1); 290 l3->app_irq = platform_get_irq(pdev, 1);
198 ret = request_irq(l3->app_irq, 291 ret = devm_request_irq(l3->dev, l3->app_irq, l3_interrupt_handler,
199 l3_interrupt_handler, 292 IRQF_DISABLED, "l3-app-irq", l3);
200 IRQF_DISABLED, "l3-app-irq", l3); 293 if (ret)
201 if (ret) { 294 dev_err(l3->dev, "request_irq failed for %d\n", l3->app_irq);
202 pr_crit("L3: request_irq failed to register for 0x%x\n",
203 l3->app_irq);
204 goto err4;
205 }
206 295
207 return 0;
208
209err4:
210 free_irq(l3->debug_irq, l3);
211err3:
212 iounmap(l3->l3_base[2]);
213err2:
214 iounmap(l3->l3_base[1]);
215err1:
216 iounmap(l3->l3_base[0]);
217err0:
218 kfree(l3);
219 return ret; 296 return ret;
220} 297}
221 298
222static int omap4_l3_remove(struct platform_device *pdev) 299static struct platform_driver omap_l3_driver = {
223{ 300 .probe = omap_l3_probe,
224 struct omap4_l3 *l3 = platform_get_drvdata(pdev);
225
226 free_irq(l3->app_irq, l3);
227 free_irq(l3->debug_irq, l3);
228 iounmap(l3->l3_base[0]);
229 iounmap(l3->l3_base[1]);
230 iounmap(l3->l3_base[2]);
231 kfree(l3);
232
233 return 0;
234}
235
236#if defined(CONFIG_OF)
237static const struct of_device_id l3_noc_match[] = {
238 {.compatible = "ti,omap4-l3-noc", },
239 {},
240};
241MODULE_DEVICE_TABLE(of, l3_noc_match);
242#else
243#define l3_noc_match NULL
244#endif
245
246static struct platform_driver omap4_l3_driver = {
247 .probe = omap4_l3_probe,
248 .remove = omap4_l3_remove,
249 .driver = { 301 .driver = {
250 .name = "omap_l3_noc", 302 .name = "omap_l3_noc",
251 .owner = THIS_MODULE, 303 .owner = THIS_MODULE,
252 .of_match_table = l3_noc_match, 304 .of_match_table = of_match_ptr(l3_noc_match),
253 }, 305 },
254}; 306};
255 307
256static int __init omap4_l3_init(void) 308static int __init omap_l3_init(void)
257{ 309{
258 return platform_driver_register(&omap4_l3_driver); 310 return platform_driver_register(&omap_l3_driver);
259} 311}
260postcore_initcall_sync(omap4_l3_init); 312postcore_initcall_sync(omap_l3_init);
261 313
262static void __exit omap4_l3_exit(void) 314static void __exit omap_l3_exit(void)
263{ 315{
264 platform_driver_unregister(&omap4_l3_driver); 316 platform_driver_unregister(&omap_l3_driver);
265} 317}
266module_exit(omap4_l3_exit); 318module_exit(omap_l3_exit);
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
index a6ce34dc4814..551e01061434 100644
--- a/drivers/bus/omap_l3_noc.h
+++ b/drivers/bus/omap_l3_noc.h
@@ -1,29 +1,25 @@
1/* 1/*
2 * OMAP4XXX L3 Interconnect error handling driver header 2 * OMAP L3 Interconnect error handling driver header
3 * 3 *
4 * Copyright (C) 2011 Texas Corporation 4 * Copyright (C) 2011-2014 Texas Instruments Incorporated - http://www.ti.com/
5 * Santosh Shilimkar <santosh.shilimkar@ti.com> 5 * Santosh Shilimkar <santosh.shilimkar@ti.com>
6 * sricharan <r.sricharan@ti.com> 6 * sricharan <r.sricharan@ti.com>
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License version 2 as
10 * the Free Software Foundation; either version 2 of the License, or 10 * published by the Free Software Foundation.
11 * (at your option) any later version.
12 * 11 *
13 * This program is distributed in the hope that it will be useful, 12 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * kind, whether express or implied; without even the implied warranty
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 15 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 * USA
22 */ 16 */
23#ifndef __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H 17#ifndef __OMAP_L3_NOC_H
24#define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H 18#define __OMAP_L3_NOC_H
19
20#define MAX_L3_MODULES 3
21#define MAX_CLKDM_TARGETS 31
25 22
26#define L3_MODULES 3
27#define CLEAR_STDERR_LOG (1 << 31) 23#define CLEAR_STDERR_LOG (1 << 31)
28#define CUSTOM_ERROR 0x2 24#define CUSTOM_ERROR 0x2
29#define STANDARD_ERROR 0x0 25#define STANDARD_ERROR 0x0
@@ -33,63 +29,165 @@
33 29
34/* L3 TARG register offsets */ 30/* L3 TARG register offsets */
35#define L3_TARG_STDERRLOG_MAIN 0x48 31#define L3_TARG_STDERRLOG_MAIN 0x48
32#define L3_TARG_STDERRLOG_HDR 0x4c
33#define L3_TARG_STDERRLOG_MSTADDR 0x50
34#define L3_TARG_STDERRLOG_INFO 0x58
36#define L3_TARG_STDERRLOG_SLVOFSLSB 0x5c 35#define L3_TARG_STDERRLOG_SLVOFSLSB 0x5c
37#define L3_TARG_STDERRLOG_MSTADDR 0x68 36#define L3_TARG_STDERRLOG_CINFO_INFO 0x64
37#define L3_TARG_STDERRLOG_CINFO_MSTADDR 0x68
38#define L3_TARG_STDERRLOG_CINFO_OPCODE 0x6c
38#define L3_FLAGMUX_REGERR0 0xc 39#define L3_FLAGMUX_REGERR0 0xc
40#define L3_FLAGMUX_MASK0 0x8
41
42#define L3_TARGET_NOT_SUPPORTED NULL
43
44#define L3_BASE_IS_SUBMODULE ((void __iomem *)(1 << 0))
45
46static const char * const l3_transaction_type[] = {
47 /* 0 0 0 */ "Idle",
48 /* 0 0 1 */ "Write",
49 /* 0 1 0 */ "Read",
50 /* 0 1 1 */ "ReadEx",
51 /* 1 0 0 */ "Read Link",
52 /* 1 0 1 */ "Write Non-Posted",
53 /* 1 1 0 */ "Write Conditional",
54 /* 1 1 1 */ "Write Broadcast",
55};
39 56
40#define NUM_OF_L3_MASTERS (sizeof(l3_masters)/sizeof(l3_masters[0])) 57/**
41 58 * struct l3_masters_data - L3 Master information
42static u32 l3_flagmux[L3_MODULES] = { 59 * @id: ID of the L3 Master
43 0x500, 60 * @name: master name
44 0x1000, 61 */
45 0X0200 62struct l3_masters_data {
46};
47
48/* L3 Target standard Error register offsets */
49static u32 l3_targ_inst_clk1[] = {
50 0x100, /* DMM1 */
51 0x200, /* DMM2 */
52 0x300, /* ABE */
53 0x400, /* L4CFG */
54 0x600, /* CLK2 PWR DISC */
55 0x0, /* Host CLK1 */
56 0x900 /* L4 Wakeup */
57};
58
59static u32 l3_targ_inst_clk2[] = {
60 0x500, /* CORTEX M3 */
61 0x300, /* DSS */
62 0x100, /* GPMC */
63 0x400, /* ISS */
64 0x700, /* IVAHD */
65 0xD00, /* missing in TRM corresponds to AES1*/
66 0x900, /* L4 PER0*/
67 0x200, /* OCMRAM */
68 0x100, /* missing in TRM corresponds to GPMC sERROR*/
69 0x600, /* SGX */
70 0x800, /* SL2 */
71 0x1600, /* C2C */
72 0x1100, /* missing in TRM corresponds PWR DISC CLK1*/
73 0xF00, /* missing in TRM corrsponds to SHA1*/
74 0xE00, /* missing in TRM corresponds to AES2*/
75 0xC00, /* L4 PER3 */
76 0xA00, /* L4 PER1*/
77 0xB00, /* L4 PER2*/
78 0x0, /* HOST CLK2 */
79 0x1800, /* CAL */
80 0x1700 /* LLI */
81};
82
83static u32 l3_targ_inst_clk3[] = {
84 0x0100 /* EMUSS */,
85 0x0300, /* DEBUGSS_CT_TBR */
86 0x0 /* HOST CLK3 */
87};
88
89static struct l3_masters_data {
90 u32 id; 63 u32 id;
91 char name[10]; 64 char *name;
92} l3_masters[] = { 65};
66
67/**
68 * struct l3_target_data - L3 Target information
69 * @offset: Offset from base for L3 Target
70 * @name: Target name
71 *
72 * Target information is organized indexed by bit field definitions.
73 */
74struct l3_target_data {
75 u32 offset;
76 char *name;
77};
78
79/**
80 * struct l3_flagmux_data - Flag Mux information
81 * @offset: offset from base for flagmux register
82 * @l3_targ: array indexed by flagmux index (bit offset) pointing to the
83 * target data. unsupported ones are marked with
84 * L3_TARGET_NOT_SUPPORTED
85 * @num_targ_data: number of entries in target data
86 * @mask_app_bits: ignore these from raw application irq status
87 * @mask_dbg_bits: ignore these from raw debug irq status
88 */
89struct l3_flagmux_data {
90 u32 offset;
91 struct l3_target_data *l3_targ;
92 u8 num_targ_data;
93 u32 mask_app_bits;
94 u32 mask_dbg_bits;
95};
96
97
98/**
99 * struct omap_l3 - Description of data relevant for L3 bus.
100 * @dev: device representing the bus (populated runtime)
101 * @l3_base: base addresses of modules (populated runtime if 0)
102 * if set to L3_BASE_IS_SUBMODULE, then uses previous
103 * module index as the base address
104 * @l3_flag_mux: array containing flag mux data per module
105 * offset from corresponding module base indexed per
106 * module.
107 * @num_modules: number of clock domains / modules.
108 * @l3_masters: array pointing to master data containing name and register
109 * offset for the master.
110 * @num_master: number of masters
111 * @mst_addr_mask: Mask representing MSTADDR information of NTTP packet
112 * @debug_irq: irq number of the debug interrupt (populated runtime)
113 * @app_irq: irq number of the application interrupt (populated runtime)
114 */
115struct omap_l3 {
116 struct device *dev;
117
118 void __iomem *l3_base[MAX_L3_MODULES];
119 struct l3_flagmux_data **l3_flagmux;
120 int num_modules;
121
122 struct l3_masters_data *l3_masters;
123 int num_masters;
124 u32 mst_addr_mask;
125
126 int debug_irq;
127 int app_irq;
128};
129
130static struct l3_target_data omap_l3_target_data_clk1[] = {
131 {0x100, "DMM1",},
132 {0x200, "DMM2",},
133 {0x300, "ABE",},
134 {0x400, "L4CFG",},
135 {0x600, "CLK2PWRDISC",},
136 {0x0, "HOSTCLK1",},
137 {0x900, "L4WAKEUP",},
138};
139
140static struct l3_flagmux_data omap_l3_flagmux_clk1 = {
141 .offset = 0x500,
142 .l3_targ = omap_l3_target_data_clk1,
143 .num_targ_data = ARRAY_SIZE(omap_l3_target_data_clk1),
144};
145
146
147static struct l3_target_data omap_l3_target_data_clk2[] = {
148 {0x500, "CORTEXM3",},
149 {0x300, "DSS",},
150 {0x100, "GPMC",},
151 {0x400, "ISS",},
152 {0x700, "IVAHD",},
153 {0xD00, "AES1",},
154 {0x900, "L4PER0",},
155 {0x200, "OCMRAM",},
156 {0x100, "GPMCsERROR",},
157 {0x600, "SGX",},
158 {0x800, "SL2",},
159 {0x1600, "C2C",},
160 {0x1100, "PWRDISCCLK1",},
161 {0xF00, "SHA1",},
162 {0xE00, "AES2",},
163 {0xC00, "L4PER3",},
164 {0xA00, "L4PER1",},
165 {0xB00, "L4PER2",},
166 {0x0, "HOSTCLK2",},
167 {0x1800, "CAL",},
168 {0x1700, "LLI",},
169};
170
171static struct l3_flagmux_data omap_l3_flagmux_clk2 = {
172 .offset = 0x1000,
173 .l3_targ = omap_l3_target_data_clk2,
174 .num_targ_data = ARRAY_SIZE(omap_l3_target_data_clk2),
175};
176
177
178static struct l3_target_data omap_l3_target_data_clk3[] = {
179 {0x0100, "EMUSS",},
180 {0x0300, "DEBUG SOURCE",},
181 {0x0, "HOST CLK3",},
182};
183
184static struct l3_flagmux_data omap_l3_flagmux_clk3 = {
185 .offset = 0x0200,
186 .l3_targ = omap_l3_target_data_clk3,
187 .num_targ_data = ARRAY_SIZE(omap_l3_target_data_clk3),
188};
189
190static struct l3_masters_data omap_l3_masters[] = {
93 { 0x0 , "MPU"}, 191 { 0x0 , "MPU"},
94 { 0x10, "CS_ADP"}, 192 { 0x10, "CS_ADP"},
95 { 0x14, "xxx"}, 193 { 0x14, "xxx"},
@@ -117,60 +215,261 @@ static struct l3_masters_data {
117 { 0xC8, "USBHOSTFS"} 215 { 0xC8, "USBHOSTFS"}
118}; 216};
119 217
120static char *l3_targ_inst_name[L3_MODULES][21] = { 218static struct l3_flagmux_data *omap_l3_flagmux[] = {
121 { 219 &omap_l3_flagmux_clk1,
122 "DMM1", 220 &omap_l3_flagmux_clk2,
123 "DMM2", 221 &omap_l3_flagmux_clk3,
124 "ABE", 222};
125 "L4CFG", 223
126 "CLK2 PWR DISC", 224static const struct omap_l3 omap_l3_data = {
127 "HOST CLK1", 225 .l3_flagmux = omap_l3_flagmux,
128 "L4 WAKEUP" 226 .num_modules = ARRAY_SIZE(omap_l3_flagmux),
129 }, 227 .l3_masters = omap_l3_masters,
130 { 228 .num_masters = ARRAY_SIZE(omap_l3_masters),
131 "CORTEX M3" , 229 /* The 6 MSBs of register field used to distinguish initiator */
132 "DSS ", 230 .mst_addr_mask = 0xFC,
133 "GPMC ", 231};
134 "ISS ",
135 "IVAHD ",
136 "AES1",
137 "L4 PER0",
138 "OCMRAM ",
139 "GPMC sERROR",
140 "SGX ",
141 "SL2 ",
142 "C2C ",
143 "PWR DISC CLK1",
144 "SHA1",
145 "AES2",
146 "L4 PER3",
147 "L4 PER1",
148 "L4 PER2",
149 "HOST CLK2",
150 "CAL",
151 "LLI"
152 },
153 {
154 "EMUSS",
155 "DEBUG SOURCE",
156 "HOST CLK3"
157 },
158};
159
160static u32 *l3_targ[L3_MODULES] = {
161 l3_targ_inst_clk1,
162 l3_targ_inst_clk2,
163 l3_targ_inst_clk3,
164};
165
166struct omap4_l3 {
167 struct device *dev;
168 struct clk *ick;
169 232
170 /* memory base */ 233/* DRA7 data */
171 void __iomem *l3_base[L3_MODULES]; 234static struct l3_target_data dra_l3_target_data_clk1[] = {
235 {0x2a00, "AES1",},
236 {0x0200, "DMM_P1",},
237 {0x0600, "DSP2_SDMA",},
238 {0x0b00, "EVE2",},
239 {0x1300, "DMM_P2",},
240 {0x2c00, "AES2",},
241 {0x0300, "DSP1_SDMA",},
242 {0x0a00, "EVE1",},
243 {0x0c00, "EVE3",},
244 {0x0d00, "EVE4",},
245 {0x2900, "DSS",},
246 {0x0100, "GPMC",},
247 {0x3700, "PCIE1",},
248 {0x1600, "IVA_CONFIG",},
249 {0x1800, "IVA_SL2IF",},
250 {0x0500, "L4_CFG",},
251 {0x1d00, "L4_WKUP",},
252 {0x3800, "PCIE2",},
253 {0x3300, "SHA2_1",},
254 {0x1200, "GPU",},
255 {0x1000, "IPU1",},
256 {0x1100, "IPU2",},
257 {0x2000, "TPCC_EDMA",},
258 {0x2e00, "TPTC1_EDMA",},
259 {0x2b00, "TPTC2_EDMA",},
260 {0x0700, "VCP1",},
261 {0x2500, "L4_PER2_P3",},
262 {0x0e00, "L4_PER3_P3",},
263 {0x2200, "MMU1",},
264 {0x1400, "PRUSS1",},
265 {0x1500, "PRUSS2"},
266 {0x0800, "VCP1",},
267};
172 268
173 int debug_irq; 269static struct l3_flagmux_data dra_l3_flagmux_clk1 = {
174 int app_irq; 270 .offset = 0x803500,
271 .l3_targ = dra_l3_target_data_clk1,
272 .num_targ_data = ARRAY_SIZE(dra_l3_target_data_clk1),
273};
274
275static struct l3_target_data dra_l3_target_data_clk2[] = {
276 {0x0, "HOST CLK1",},
277 {0x0, "HOST CLK2",},
278 {0xdead, L3_TARGET_NOT_SUPPORTED,},
279 {0x3400, "SHA2_2",},
280 {0x0900, "BB2D",},
281 {0xdead, L3_TARGET_NOT_SUPPORTED,},
282 {0x2100, "L4_PER1_P3",},
283 {0x1c00, "L4_PER1_P1",},
284 {0x1f00, "L4_PER1_P2",},
285 {0x2300, "L4_PER2_P1",},
286 {0x2400, "L4_PER2_P2",},
287 {0x2600, "L4_PER3_P1",},
288 {0x2700, "L4_PER3_P2",},
289 {0x2f00, "MCASP1",},
290 {0x3000, "MCASP2",},
291 {0x3100, "MCASP3",},
292 {0x2800, "MMU2",},
293 {0x0f00, "OCMC_RAM1",},
294 {0x1700, "OCMC_RAM2",},
295 {0x1900, "OCMC_RAM3",},
296 {0x1e00, "OCMC_ROM",},
297 {0x3900, "QSPI",},
298};
299
300static struct l3_flagmux_data dra_l3_flagmux_clk2 = {
301 .offset = 0x803600,
302 .l3_targ = dra_l3_target_data_clk2,
303 .num_targ_data = ARRAY_SIZE(dra_l3_target_data_clk2),
304};
305
306static struct l3_target_data dra_l3_target_data_clk3[] = {
307 {0x0100, "L3_INSTR"},
308 {0x0300, "DEBUGSS_CT_TBR"},
309 {0x0, "HOST CLK3"},
310};
311
312static struct l3_flagmux_data dra_l3_flagmux_clk3 = {
313 .offset = 0x200,
314 .l3_targ = dra_l3_target_data_clk3,
315 .num_targ_data = ARRAY_SIZE(dra_l3_target_data_clk3),
316};
317
318static struct l3_masters_data dra_l3_masters[] = {
319 { 0x0, "MPU" },
320 { 0x4, "CS_DAP" },
321 { 0x5, "IEEE1500_2_OCP" },
322 { 0x8, "DSP1_MDMA" },
323 { 0x9, "DSP1_CFG" },
324 { 0xA, "DSP1_DMA" },
325 { 0xB, "DSP2_MDMA" },
326 { 0xC, "DSP2_CFG" },
327 { 0xD, "DSP2_DMA" },
328 { 0xE, "IVA" },
329 { 0x10, "EVE1_P1" },
330 { 0x11, "EVE2_P1" },
331 { 0x12, "EVE3_P1" },
332 { 0x13, "EVE4_P1" },
333 { 0x14, "PRUSS1 PRU1" },
334 { 0x15, "PRUSS1 PRU2" },
335 { 0x16, "PRUSS2 PRU1" },
336 { 0x17, "PRUSS2 PRU2" },
337 { 0x18, "IPU1" },
338 { 0x19, "IPU2" },
339 { 0x1A, "SDMA" },
340 { 0x1B, "CDMA" },
341 { 0x1C, "TC1_EDMA" },
342 { 0x1D, "TC2_EDMA" },
343 { 0x20, "DSS" },
344 { 0x21, "MMU1" },
345 { 0x22, "PCIE1" },
346 { 0x23, "MMU2" },
347 { 0x24, "VIP1" },
348 { 0x25, "VIP2" },
349 { 0x26, "VIP3" },
350 { 0x27, "VPE" },
351 { 0x28, "GPU_P1" },
352 { 0x29, "BB2D" },
353 { 0x29, "GPU_P2" },
354 { 0x2B, "GMAC_SW" },
355 { 0x2C, "USB3" },
356 { 0x2D, "USB2_SS" },
357 { 0x2E, "USB2_ULPI_SS1" },
358 { 0x2F, "USB2_ULPI_SS2" },
359 { 0x30, "CSI2_1" },
360 { 0x31, "CSI2_2" },
361 { 0x33, "SATA" },
362 { 0x34, "EVE1_P2" },
363 { 0x35, "EVE2_P2" },
364 { 0x36, "EVE3_P2" },
365 { 0x37, "EVE4_P2" }
175}; 366};
176#endif 367
368static struct l3_flagmux_data *dra_l3_flagmux[] = {
369 &dra_l3_flagmux_clk1,
370 &dra_l3_flagmux_clk2,
371 &dra_l3_flagmux_clk3,
372};
373
374static const struct omap_l3 dra_l3_data = {
375 .l3_base = { [1] = L3_BASE_IS_SUBMODULE },
376 .l3_flagmux = dra_l3_flagmux,
377 .num_modules = ARRAY_SIZE(dra_l3_flagmux),
378 .l3_masters = dra_l3_masters,
379 .num_masters = ARRAY_SIZE(dra_l3_masters),
380 /* The 6 MSBs of register field used to distinguish initiator */
381 .mst_addr_mask = 0xFC,
382};
383
384/* AM4372 data */
385static struct l3_target_data am4372_l3_target_data_200f[] = {
386 {0xf00, "EMIF",},
387 {0x1200, "DES",},
388 {0x400, "OCMCRAM",},
389 {0x700, "TPTC0",},
390 {0x800, "TPTC1",},
391 {0x900, "TPTC2"},
392 {0xb00, "TPCC",},
393 {0xd00, "DEBUGSS",},
394 {0xdead, L3_TARGET_NOT_SUPPORTED,},
395 {0x200, "SHA",},
396 {0xc00, "SGX530",},
397 {0x500, "AES0",},
398 {0xa00, "L4_FAST",},
399 {0x300, "MPUSS_L2_RAM",},
400 {0x100, "ICSS",},
401};
402
403static struct l3_flagmux_data am4372_l3_flagmux_200f = {
404 .offset = 0x1000,
405 .l3_targ = am4372_l3_target_data_200f,
406 .num_targ_data = ARRAY_SIZE(am4372_l3_target_data_200f),
407};
408
409static struct l3_target_data am4372_l3_target_data_100s[] = {
410 {0x100, "L4_PER_0",},
411 {0x200, "L4_PER_1",},
412 {0x300, "L4_PER_2",},
413 {0x400, "L4_PER_3",},
414 {0x800, "McASP0",},
415 {0x900, "McASP1",},
416 {0xC00, "MMCHS2",},
417 {0x700, "GPMC",},
418 {0xD00, "L4_FW",},
419 {0xdead, L3_TARGET_NOT_SUPPORTED,},
420 {0x500, "ADCTSC",},
421 {0xE00, "L4_WKUP",},
422 {0xA00, "MAG_CARD",},
423};
424
425static struct l3_flagmux_data am4372_l3_flagmux_100s = {
426 .offset = 0x600,
427 .l3_targ = am4372_l3_target_data_100s,
428 .num_targ_data = ARRAY_SIZE(am4372_l3_target_data_100s),
429};
430
431static struct l3_masters_data am4372_l3_masters[] = {
432 { 0x0, "M1 (128-bit)"},
433 { 0x1, "M2 (64-bit)"},
434 { 0x4, "DAP"},
435 { 0x5, "P1500"},
436 { 0xC, "ICSS0"},
437 { 0xD, "ICSS1"},
438 { 0x14, "Wakeup Processor"},
439 { 0x18, "TPTC0 Read"},
440 { 0x19, "TPTC0 Write"},
441 { 0x1A, "TPTC1 Read"},
442 { 0x1B, "TPTC1 Write"},
443 { 0x1C, "TPTC2 Read"},
444 { 0x1D, "TPTC2 Write"},
445 { 0x20, "SGX530"},
446 { 0x21, "OCP WP Traffic Probe"},
447 { 0x22, "OCP WP DMA Profiling"},
448 { 0x23, "OCP WP Event Trace"},
449 { 0x25, "DSS"},
450 { 0x28, "Crypto DMA RD"},
451 { 0x29, "Crypto DMA WR"},
452 { 0x2C, "VPFE0"},
453 { 0x2D, "VPFE1"},
454 { 0x30, "GEMAC"},
455 { 0x34, "USB0 RD"},
456 { 0x35, "USB0 WR"},
457 { 0x36, "USB1 RD"},
458 { 0x37, "USB1 WR"},
459};
460
461static struct l3_flagmux_data *am4372_l3_flagmux[] = {
462 &am4372_l3_flagmux_200f,
463 &am4372_l3_flagmux_100s,
464};
465
466static const struct omap_l3 am4372_l3_data = {
467 .l3_flagmux = am4372_l3_flagmux,
468 .num_modules = ARRAY_SIZE(am4372_l3_flagmux),
469 .l3_masters = am4372_l3_masters,
470 .num_masters = ARRAY_SIZE(am4372_l3_masters),
471 /* All 6 bits of register field used to distinguish initiator */
472 .mst_addr_mask = 0x3F,
473};
474
475#endif /* __OMAP_L3_NOC_H */