Blame view

drivers/bus/omap_l3_noc.c 10.5 KB
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
1
  /*
c10d5c9e1   Sricharan R   bus: omap_l3_noc:...
2
   * OMAP L3 Interconnect error handling driver
ed0e35207   sricharan   OMAP: Fix indenta...
3
   *
e7309c267   Suman Anna   bus: omap_l3_noc:...
4
   * Copyright (C) 2011-2015 Texas Instruments Incorporated - http://www.ti.com/
ed0e35207   sricharan   OMAP: Fix indenta...
5
6
7
8
   *	Santosh Shilimkar <santosh.shilimkar@ti.com>
   *	Sricharan <r.sricharan@ti.com>
   *
   * This program is free software; you can redistribute it and/or modify
c5f2aea0e   Nishanth Menon   bus: omap_l3_noc:...
9
10
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
ed0e35207   sricharan   OMAP: Fix indenta...
11
   *
c5f2aea0e   Nishanth Menon   bus: omap_l3_noc:...
12
13
14
   * This program is distributed "as is" WITHOUT ANY WARRANTY of any
   * kind, whether express or implied; without even the implied warranty
   * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ed0e35207   sricharan   OMAP: Fix indenta...
15
   * GNU General Public License for more details.
ed0e35207   sricharan   OMAP: Fix indenta...
16
   */
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
17
  #include <linux/init.h>
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
18
  #include <linux/interrupt.h>
0659452dd   Sricharan R   bus: omap_l3_noc:...
19
  #include <linux/io.h>
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
20
  #include <linux/kernel.h>
0659452dd   Sricharan R   bus: omap_l3_noc:...
21
22
23
24
  #include <linux/module.h>
  #include <linux/of_device.h>
  #include <linux/of.h>
  #include <linux/platform_device.h>
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
25
26
27
  #include <linux/slab.h>
  
  #include "omap_l3_noc.h"
e4be3f3a0   Nishanth Menon   bus: omap_l3_noc:...
28
29
30
31
32
33
  /**
   * l3_handle_target() - Handle Target specific parse and reporting
   * @l3:		pointer to l3 struct
   * @base:	base address of clkdm
   * @flag_mux:	flagmux corresponding to the event
   * @err_src:	error source index of the slave (target)
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
34
   *
e4be3f3a0   Nishanth Menon   bus: omap_l3_noc:...
35
36
37
38
39
40
41
   * This does the second part of the error interrupt handling:
   *	3) Parse in the slave information
   *	4) Print the logged information.
   *	5) Add dump stack to provide kernel trace.
   *	6) Clear the source if known.
   *
   * This handles two types of errors:
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
   *	1) Custom errors in L3 :
   *		Target like DMM/FW/EMIF generates SRESP=ERR error
   *	2) Standard L3 error:
   *		- Unsupported CMD.
   *			L3 tries to access target while it is idle
   *		- OCP disconnect.
   *		- Address hole error:
   *			If DSS/ISS/FDIF/USBHOSTFS access a target where they
   *			do not have connectivity, the error is logged in
   *			their default target which is DMM2.
   *
   *	On High Secure devices, firewall errors are possible and those
   *	can be trapped as well. But the trapping is implemented as part
   *	secure software and hence need not be implemented here.
   */
e4be3f3a0   Nishanth Menon   bus: omap_l3_noc:...
57
58
  static int l3_handle_target(struct omap_l3 *l3, void __iomem *base,
  			    struct l3_flagmux_data *flag_mux, int err_src)
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
59
  {
e4be3f3a0   Nishanth Menon   bus: omap_l3_noc:...
60
61
  	int k;
  	u32 std_err_main, clear, masterid;
cf52b2ecd   Nishanth Menon   bus: omap_l3_noc:...
62
  	u8 op_code, m_req_info;
e4be3f3a0   Nishanth Menon   bus: omap_l3_noc:...
63
  	void __iomem *l3_targ_base;
9e224c8ff   Nishanth Menon   bus: omap_l3_noc:...
64
  	void __iomem *l3_targ_stderr, *l3_targ_slvofslsb, *l3_targ_mstaddr;
cf52b2ecd   Nishanth Menon   bus: omap_l3_noc:...
65
  	void __iomem *l3_targ_hdr, *l3_targ_info;
3ae9af7c9   Nishanth Menon   bus: omap_l3_noc:...
66
  	struct l3_target_data *l3_targ_inst;
0659452dd   Sricharan R   bus: omap_l3_noc:...
67
  	struct l3_masters_data *master;
e4be3f3a0   Nishanth Menon   bus: omap_l3_noc:...
68
  	char *target_name, *master_name = "UN IDENTIFIED";
c98aa7aaa   Nishanth Menon   bus: omap_l3_noc:...
69
70
  	char *err_description;
  	char err_string[30] = { 0 };
cf52b2ecd   Nishanth Menon   bus: omap_l3_noc:...
71
  	char info_string[60] = { 0 };
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
72

e4be3f3a0   Nishanth Menon   bus: omap_l3_noc:...
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
  	/* We DONOT expect err_src to go out of bounds */
  	BUG_ON(err_src > MAX_CLKDM_TARGETS);
  
  	if (err_src < flag_mux->num_targ_data) {
  		l3_targ_inst = &flag_mux->l3_targ[err_src];
  		target_name = l3_targ_inst->name;
  		l3_targ_base = base + l3_targ_inst->offset;
  	} else {
  		target_name = L3_TARGET_NOT_SUPPORTED;
  	}
  
  	if (target_name == L3_TARGET_NOT_SUPPORTED)
  		return -ENODEV;
  
  	/* Read the stderrlog_main_source from clk domain */
  	l3_targ_stderr = l3_targ_base + L3_TARG_STDERRLOG_MAIN;
  	l3_targ_slvofslsb = l3_targ_base + L3_TARG_STDERRLOG_SLVOFSLSB;
  
  	std_err_main = readl_relaxed(l3_targ_stderr);
  
  	switch (std_err_main & CUSTOM_ERROR) {
  	case STANDARD_ERROR:
  		err_description = "Standard";
  		snprintf(err_string, sizeof(err_string),
  			 ": At Address: 0x%08X ",
  			 readl_relaxed(l3_targ_slvofslsb));
  
  		l3_targ_mstaddr = l3_targ_base + L3_TARG_STDERRLOG_MSTADDR;
7f9de02d6   Nishanth Menon   bus: omap_l3_noc:...
101
  		l3_targ_hdr = l3_targ_base + L3_TARG_STDERRLOG_HDR;
cf52b2ecd   Nishanth Menon   bus: omap_l3_noc:...
102
  		l3_targ_info = l3_targ_base + L3_TARG_STDERRLOG_INFO;
e4be3f3a0   Nishanth Menon   bus: omap_l3_noc:...
103
104
105
106
107
108
109
  		break;
  
  	case CUSTOM_ERROR:
  		err_description = "Custom";
  
  		l3_targ_mstaddr = l3_targ_base +
  				  L3_TARG_STDERRLOG_CINFO_MSTADDR;
7f9de02d6   Nishanth Menon   bus: omap_l3_noc:...
110
  		l3_targ_hdr = l3_targ_base + L3_TARG_STDERRLOG_CINFO_OPCODE;
cf52b2ecd   Nishanth Menon   bus: omap_l3_noc:...
111
  		l3_targ_info = l3_targ_base + L3_TARG_STDERRLOG_CINFO_INFO;
e4be3f3a0   Nishanth Menon   bus: omap_l3_noc:...
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  		break;
  
  	default:
  		/* Nothing to be handled here as of now */
  		return 0;
  	}
  
  	/* STDERRLOG_MSTADDR Stores the NTTP master address. */
  	masterid = (readl_relaxed(l3_targ_mstaddr) &
  		    l3->mst_addr_mask) >> __ffs(l3->mst_addr_mask);
  
  	for (k = 0, master = l3->l3_masters; k < l3->num_masters;
  	     k++, master++) {
  		if (masterid == master->id) {
  			master_name = master->name;
  			break;
  		}
  	}
7f9de02d6   Nishanth Menon   bus: omap_l3_noc:...
130
  	op_code = readl_relaxed(l3_targ_hdr) & 0x7;
cf52b2ecd   Nishanth Menon   bus: omap_l3_noc:...
131
132
133
134
135
136
  	m_req_info = readl_relaxed(l3_targ_info) & 0xF;
  	snprintf(info_string, sizeof(info_string),
  		 ": %s in %s mode during %s access",
  		 (m_req_info & BIT(0)) ? "Opcode Fetch" : "Data Access",
  		 (m_req_info & BIT(1)) ? "Supervisor" : "User",
  		 (m_req_info & BIT(3)) ? "Debug" : "Functional");
e4be3f3a0   Nishanth Menon   bus: omap_l3_noc:...
137
  	WARN(true,
cf52b2ecd   Nishanth Menon   bus: omap_l3_noc:...
138
139
  	     "%s:L3 %s Error: MASTER %s TARGET %s (%s)%s%s
  ",
e4be3f3a0   Nishanth Menon   bus: omap_l3_noc:...
140
141
142
  	     dev_name(l3->dev),
  	     err_description,
  	     master_name, target_name,
7f9de02d6   Nishanth Menon   bus: omap_l3_noc:...
143
  	     l3_transaction_type[op_code],
cf52b2ecd   Nishanth Menon   bus: omap_l3_noc:...
144
  	     err_string, info_string);
e4be3f3a0   Nishanth Menon   bus: omap_l3_noc:...
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
  
  	/* clear the std error log*/
  	clear = std_err_main | CLEAR_STDERR_LOG;
  	writel_relaxed(clear, l3_targ_stderr);
  
  	return 0;
  }
  
  /**
   * l3_interrupt_handler() - interrupt handler for l3 events
   * @irq:	irq number
   * @_l3:	pointer to l3 structure
   *
   * Interrupt Handler for L3 error detection.
   *	1) Identify the L3 clockdomain partition to which the error belongs to.
   *	2) Identify the slave where the error information is logged
   *	... handle the slave event..
   *	7) if the slave is unknown, mask out the slave.
   */
  static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
  {
  	struct omap_l3 *l3 = _l3;
  	int inttype, i, ret;
  	int err_src = 0;
  	u32 err_reg, mask_val;
  	void __iomem *base, *mask_reg;
  	struct l3_flagmux_data *flag_mux;
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
172
  	/* Get the Type of interrupt */
35f7b9610   omar ramirez   OMAP3/4: l3: mino...
173
  	inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
174

0659452dd   Sricharan R   bus: omap_l3_noc:...
175
  	for (i = 0; i < l3->num_modules; i++) {
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
176
177
178
179
  		/*
  		 * Read the regerr register of the clock domain
  		 * to determine the source
  		 */
6616aac66   sricharan   OMAP: Fix sparse ...
180
  		base = l3->l3_base[i];
97708c08c   Nishanth Menon   bus: omap_l3_noc:...
181
182
  		flag_mux = l3->l3_flagmux[i];
  		err_reg = readl_relaxed(base + flag_mux->offset +
9e224c8ff   Nishanth Menon   bus: omap_l3_noc:...
183
  					L3_FLAGMUX_REGERR0 + (inttype << 3));
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
184

2100b595b   Afzal Mohammed   bus: omap_l3_noc:...
185
186
  		err_reg &= ~(inttype ? flag_mux->mask_app_bits :
  				flag_mux->mask_dbg_bits);
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
187
188
189
  		/* Get the corresponding error and analyse */
  		if (err_reg) {
  			/* Identify the source from control status register */
342fd1442   Todd Poynor   OMAP: Improve reg...
190
  			err_src = __ffs(err_reg);
3340d739f   Rajendra Nayak   bus: omap_l3_noc:...
191

e4be3f3a0   Nishanth Menon   bus: omap_l3_noc:...
192
  			ret = l3_handle_target(l3, base, flag_mux, err_src);
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
193

3340d739f   Rajendra Nayak   bus: omap_l3_noc:...
194
  			/*
e4be3f3a0   Nishanth Menon   bus: omap_l3_noc:...
195
196
197
198
  			 * Certain plaforms may have "undocumented" status
  			 * pending on boot. So dont generate a severe warning
  			 * here. Just mask it off to prevent the error from
  			 * reoccuring and locking up the system.
3340d739f   Rajendra Nayak   bus: omap_l3_noc:...
199
  			 */
e4be3f3a0   Nishanth Menon   bus: omap_l3_noc:...
200
  			if (ret) {
3340d739f   Rajendra Nayak   bus: omap_l3_noc:...
201
202
203
204
205
  				dev_err(l3->dev,
  					"L3 %s error: target %d mod:%d %s
  ",
  					inttype ? "debug" : "application",
  					err_src, i, "(unclearable)");
97708c08c   Nishanth Menon   bus: omap_l3_noc:...
206
  				mask_reg = base + flag_mux->offset +
3340d739f   Rajendra Nayak   bus: omap_l3_noc:...
207
208
209
210
  					   L3_FLAGMUX_MASK0 + (inttype << 3);
  				mask_val = readl_relaxed(mask_reg);
  				mask_val &= ~(1 << err_src);
  				writel_relaxed(mask_val, mask_reg);
2100b595b   Afzal Mohammed   bus: omap_l3_noc:...
211
212
213
214
215
216
  
  				/* Mark these bits as to be ignored */
  				if (inttype)
  					flag_mux->mask_app_bits |= 1 << err_src;
  				else
  					flag_mux->mask_dbg_bits |= 1 << err_src;
3340d739f   Rajendra Nayak   bus: omap_l3_noc:...
217
  			}
c98aa7aaa   Nishanth Menon   bus: omap_l3_noc:...
218
  			/* Error found so break the for loop */
c4cf0935a   Keerthy   bus: omap_l3_noc:...
219
  			return IRQ_HANDLED;
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
220
221
  		}
  	}
c4cf0935a   Keerthy   bus: omap_l3_noc:...
222
223
224
225
226
227
  
  	dev_err(l3->dev, "L3 %s IRQ not handled!!
  ",
  		inttype ? "debug" : "application");
  
  	return IRQ_NONE;
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
228
  }
0659452dd   Sricharan R   bus: omap_l3_noc:...
229
  static const struct of_device_id l3_noc_match[] = {
e7309c267   Suman Anna   bus: omap_l3_noc:...
230
231
  	{.compatible = "ti,omap4-l3-noc", .data = &omap4_l3_data},
  	{.compatible = "ti,omap5-l3-noc", .data = &omap5_l3_data},
53a848be0   Rajendra Nayak   bus: omap_l3_noc:...
232
  	{.compatible = "ti,dra7-l3-noc", .data = &dra_l3_data},
27b7d5f3c   Afzal Mohammed   bus: omap_l3_noc:...
233
  	{.compatible = "ti,am4372-l3-noc", .data = &am4372_l3_data},
0659452dd   Sricharan R   bus: omap_l3_noc:...
234
235
236
  	{},
  };
  MODULE_DEVICE_TABLE(of, l3_noc_match);
c10d5c9e1   Sricharan R   bus: omap_l3_noc:...
237
  static int omap_l3_probe(struct platform_device *pdev)
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
238
  {
0659452dd   Sricharan R   bus: omap_l3_noc:...
239
  	const struct of_device_id *of_id;
c10d5c9e1   Sricharan R   bus: omap_l3_noc:...
240
  	static struct omap_l3 *l3;
f33ddf745   Nishanth Menon   bus: omap_l3_noc:...
241
  	int ret, i, res_idx;
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
242

0659452dd   Sricharan R   bus: omap_l3_noc:...
243
244
245
246
247
248
  	of_id = of_match_device(l3_noc_match, &pdev->dev);
  	if (!of_id) {
  		dev_err(&pdev->dev, "OF data missing
  ");
  		return -EINVAL;
  	}
bae745101   Peter Ujfalusi   drivers: bus: oma...
249
  	l3 = devm_kzalloc(&pdev->dev, sizeof(*l3), GFP_KERNEL);
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
250
  	if (!l3)
7529b7038   omar ramirez   OMAP3/4: l3: fix ...
251
  		return -ENOMEM;
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
252

0659452dd   Sricharan R   bus: omap_l3_noc:...
253
  	memcpy(l3, of_id->data, sizeof(*l3));
ca6a34935   Nishanth Menon   bus: omap_l3_noc:...
254
  	l3->dev = &pdev->dev;
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
255
  	platform_set_drvdata(pdev, l3);
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
256

56c4a0224   Peter Ujfalusi   drivers: bus: oma...
257
  	/* Get mem resources */
f33ddf745   Nishanth Menon   bus: omap_l3_noc:...
258
259
260
261
262
263
264
265
266
267
  	for (i = 0, res_idx = 0; i < l3->num_modules; i++) {
  		struct resource	*res;
  
  		if (l3->l3_base[i] == L3_BASE_IS_SUBMODULE) {
  			/* First entry cannot be submodule */
  			BUG_ON(i == 0);
  			l3->l3_base[i] = l3->l3_base[i - 1];
  			continue;
  		}
  		res = platform_get_resource(pdev, IORESOURCE_MEM, res_idx);
56c4a0224   Peter Ujfalusi   drivers: bus: oma...
268
269
  		l3->l3_base[i] = devm_ioremap_resource(&pdev->dev, res);
  		if (IS_ERR(l3->l3_base[i])) {
ca6a34935   Nishanth Menon   bus: omap_l3_noc:...
270
271
  			dev_err(l3->dev, "ioremap %d failed
  ", i);
56c4a0224   Peter Ujfalusi   drivers: bus: oma...
272
273
  			return PTR_ERR(l3->l3_base[i]);
  		}
f33ddf745   Nishanth Menon   bus: omap_l3_noc:...
274
  		res_idx++;
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
275
276
277
278
279
  	}
  
  	/*
  	 * Setup interrupt Handlers
  	 */
c1df2dcc9   Todd Poynor   OMAP: Fix a BUG i...
280
  	l3->debug_irq = platform_get_irq(pdev, 0);
ca6a34935   Nishanth Menon   bus: omap_l3_noc:...
281
  	ret = devm_request_irq(l3->dev, l3->debug_irq, l3_interrupt_handler,
d8bf368d0   Valentin Rothberg   genirq: Remove th...
282
  			       0x0, "l3-dbg-irq", l3);
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
283
  	if (ret) {
ca6a34935   Nishanth Menon   bus: omap_l3_noc:...
284
285
  		dev_err(l3->dev, "request_irq failed for %d
  ",
ae22598a1   Peter Ujfalusi   drivers: bus: oma...
286
  			l3->debug_irq);
56c4a0224   Peter Ujfalusi   drivers: bus: oma...
287
  		return ret;
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
288
  	}
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
289

c1df2dcc9   Todd Poynor   OMAP: Fix a BUG i...
290
  	l3->app_irq = platform_get_irq(pdev, 1);
ca6a34935   Nishanth Menon   bus: omap_l3_noc:...
291
  	ret = devm_request_irq(l3->dev, l3->app_irq, l3_interrupt_handler,
d8bf368d0   Valentin Rothberg   genirq: Remove th...
292
  			       0x0, "l3-app-irq", l3);
a0ef78f35   Peter Ujfalusi   drivers: bus: oma...
293
  	if (ret)
ca6a34935   Nishanth Menon   bus: omap_l3_noc:...
294
295
  		dev_err(l3->dev, "request_irq failed for %d
  ", l3->app_irq);
7529b7038   omar ramirez   OMAP3/4: l3: fix ...
296

2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
297
298
  	return ret;
  }
258d2a109   Grygorii Strashko   bus: omap_l3_noc:...
299
  #ifdef	CONFIG_PM_SLEEP
61b43d4e9   Keerthy   bus: omap_l3_noc:...
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
  
  /**
   * l3_resume_noirq() - resume function for l3_noc
   * @dev:	pointer to l3_noc device structure
   *
   * We only have the resume handler only since we
   * have already maintained the delta register
   * configuration as part of configuring the system
   */
  static int l3_resume_noirq(struct device *dev)
  {
  	struct omap_l3 *l3 = dev_get_drvdata(dev);
  	int i;
  	struct l3_flagmux_data *flag_mux;
  	void __iomem *base, *mask_regx = NULL;
  	u32 mask_val;
  
  	for (i = 0; i < l3->num_modules; i++) {
  		base = l3->l3_base[i];
  		flag_mux = l3->l3_flagmux[i];
  		if (!flag_mux->mask_app_bits && !flag_mux->mask_dbg_bits)
  			continue;
  
  		mask_regx = base + flag_mux->offset + L3_FLAGMUX_MASK0 +
  			   (L3_APPLICATION_ERROR << 3);
  		mask_val = readl_relaxed(mask_regx);
  		mask_val &= ~(flag_mux->mask_app_bits);
  
  		writel_relaxed(mask_val, mask_regx);
  		mask_regx = base + flag_mux->offset + L3_FLAGMUX_MASK0 +
  			   (L3_DEBUG_ERROR << 3);
  		mask_val = readl_relaxed(mask_regx);
  		mask_val &= ~(flag_mux->mask_dbg_bits);
  
  		writel_relaxed(mask_val, mask_regx);
  	}
  
  	/* Dummy read to force OCP barrier */
  	if (mask_regx)
  		(void)readl(mask_regx);
  
  	return 0;
  }
  
  static const struct dev_pm_ops l3_dev_pm_ops = {
258d2a109   Grygorii Strashko   bus: omap_l3_noc:...
345
  	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(NULL, l3_resume_noirq)
61b43d4e9   Keerthy   bus: omap_l3_noc:...
346
347
348
349
350
351
  };
  
  #define L3_DEV_PM_OPS (&l3_dev_pm_ops)
  #else
  #define L3_DEV_PM_OPS NULL
  #endif
c10d5c9e1   Sricharan R   bus: omap_l3_noc:...
352
353
  static struct platform_driver omap_l3_driver = {
  	.probe		= omap_l3_probe,
d039c5b9f   Benoit Cousson   ARM: OMAP2+: l3-n...
354
355
  	.driver		= {
  		.name		= "omap_l3_noc",
61b43d4e9   Keerthy   bus: omap_l3_noc:...
356
  		.pm		= L3_DEV_PM_OPS,
0659452dd   Sricharan R   bus: omap_l3_noc:...
357
  		.of_match_table = of_match_ptr(l3_noc_match),
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
358
359
  	},
  };
c10d5c9e1   Sricharan R   bus: omap_l3_noc:...
360
  static int __init omap_l3_init(void)
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
361
  {
c10d5c9e1   Sricharan R   bus: omap_l3_noc:...
362
  	return platform_driver_register(&omap_l3_driver);
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
363
  }
c10d5c9e1   Sricharan R   bus: omap_l3_noc:...
364
  postcore_initcall_sync(omap_l3_init);
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
365

c10d5c9e1   Sricharan R   bus: omap_l3_noc:...
366
  static void __exit omap_l3_exit(void)
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
367
  {
c10d5c9e1   Sricharan R   bus: omap_l3_noc:...
368
  	platform_driver_unregister(&omap_l3_driver);
2722e56de   Santosh Shilimkar   OMAP4: l3: Introd...
369
  }
c10d5c9e1   Sricharan R   bus: omap_l3_noc:...
370
  module_exit(omap_l3_exit);