xref: /linux/arch/powerpc/sysdev/ipic.c (revision f3d9478b2ce468c3115b02ecae7e975990697f15)
1 /*
2  * include/asm-ppc/ipic.c
3  *
4  * IPIC routines implementations.
5  *
6  * Copyright 2005 Freescale Semiconductor, Inc.
7  *
8  * This program is free software; you can redistribute  it and/or modify it
9  * under  the terms of  the GNU General  Public License as published by the
10  * Free Software Foundation;  either version 2 of the  License, or (at your
11  * option) any later version.
12  */
13 #include <linux/kernel.h>
14 #include <linux/init.h>
15 #include <linux/errno.h>
16 #include <linux/reboot.h>
17 #include <linux/slab.h>
18 #include <linux/stddef.h>
19 #include <linux/sched.h>
20 #include <linux/signal.h>
21 #include <linux/sysdev.h>
22 #include <asm/irq.h>
23 #include <asm/io.h>
24 #include <asm/ipic.h>
25 #include <asm/mpc83xx.h>
26 
27 #include "ipic.h"
28 
29 static struct ipic p_ipic;
30 static struct ipic * primary_ipic;
31 
32 static struct ipic_info ipic_info[] = {
33 	[9] = {
34 		.pend	= IPIC_SIPNR_H,
35 		.mask	= IPIC_SIMSR_H,
36 		.prio	= IPIC_SIPRR_D,
37 		.force	= IPIC_SIFCR_H,
38 		.bit	= 24,
39 		.prio_mask = 0,
40 	},
41 	[10] = {
42 		.pend	= IPIC_SIPNR_H,
43 		.mask	= IPIC_SIMSR_H,
44 		.prio	= IPIC_SIPRR_D,
45 		.force	= IPIC_SIFCR_H,
46 		.bit	= 25,
47 		.prio_mask = 1,
48 	},
49 	[11] = {
50 		.pend	= IPIC_SIPNR_H,
51 		.mask	= IPIC_SIMSR_H,
52 		.prio	= IPIC_SIPRR_D,
53 		.force	= IPIC_SIFCR_H,
54 		.bit	= 26,
55 		.prio_mask = 2,
56 	},
57 	[14] = {
58 		.pend	= IPIC_SIPNR_H,
59 		.mask	= IPIC_SIMSR_H,
60 		.prio	= IPIC_SIPRR_D,
61 		.force	= IPIC_SIFCR_H,
62 		.bit	= 29,
63 		.prio_mask = 5,
64 	},
65 	[15] = {
66 		.pend	= IPIC_SIPNR_H,
67 		.mask	= IPIC_SIMSR_H,
68 		.prio	= IPIC_SIPRR_D,
69 		.force	= IPIC_SIFCR_H,
70 		.bit	= 30,
71 		.prio_mask = 6,
72 	},
73 	[16] = {
74 		.pend	= IPIC_SIPNR_H,
75 		.mask	= IPIC_SIMSR_H,
76 		.prio	= IPIC_SIPRR_D,
77 		.force	= IPIC_SIFCR_H,
78 		.bit	= 31,
79 		.prio_mask = 7,
80 	},
81 	[17] = {
82 		.pend	= IPIC_SEPNR,
83 		.mask	= IPIC_SEMSR,
84 		.prio	= IPIC_SMPRR_A,
85 		.force	= IPIC_SEFCR,
86 		.bit	= 1,
87 		.prio_mask = 5,
88 	},
89 	[18] = {
90 		.pend	= IPIC_SEPNR,
91 		.mask	= IPIC_SEMSR,
92 		.prio	= IPIC_SMPRR_A,
93 		.force	= IPIC_SEFCR,
94 		.bit	= 2,
95 		.prio_mask = 6,
96 	},
97 	[19] = {
98 		.pend	= IPIC_SEPNR,
99 		.mask	= IPIC_SEMSR,
100 		.prio	= IPIC_SMPRR_A,
101 		.force	= IPIC_SEFCR,
102 		.bit	= 3,
103 		.prio_mask = 7,
104 	},
105 	[20] = {
106 		.pend	= IPIC_SEPNR,
107 		.mask	= IPIC_SEMSR,
108 		.prio	= IPIC_SMPRR_B,
109 		.force	= IPIC_SEFCR,
110 		.bit	= 4,
111 		.prio_mask = 4,
112 	},
113 	[21] = {
114 		.pend	= IPIC_SEPNR,
115 		.mask	= IPIC_SEMSR,
116 		.prio	= IPIC_SMPRR_B,
117 		.force	= IPIC_SEFCR,
118 		.bit	= 5,
119 		.prio_mask = 5,
120 	},
121 	[22] = {
122 		.pend	= IPIC_SEPNR,
123 		.mask	= IPIC_SEMSR,
124 		.prio	= IPIC_SMPRR_B,
125 		.force	= IPIC_SEFCR,
126 		.bit	= 6,
127 		.prio_mask = 6,
128 	},
129 	[23] = {
130 		.pend	= IPIC_SEPNR,
131 		.mask	= IPIC_SEMSR,
132 		.prio	= IPIC_SMPRR_B,
133 		.force	= IPIC_SEFCR,
134 		.bit	= 7,
135 		.prio_mask = 7,
136 	},
137 	[32] = {
138 		.pend	= IPIC_SIPNR_H,
139 		.mask	= IPIC_SIMSR_H,
140 		.prio	= IPIC_SIPRR_A,
141 		.force	= IPIC_SIFCR_H,
142 		.bit	= 0,
143 		.prio_mask = 0,
144 	},
145 	[33] = {
146 		.pend	= IPIC_SIPNR_H,
147 		.mask	= IPIC_SIMSR_H,
148 		.prio	= IPIC_SIPRR_A,
149 		.force	= IPIC_SIFCR_H,
150 		.bit	= 1,
151 		.prio_mask = 1,
152 	},
153 	[34] = {
154 		.pend	= IPIC_SIPNR_H,
155 		.mask	= IPIC_SIMSR_H,
156 		.prio	= IPIC_SIPRR_A,
157 		.force	= IPIC_SIFCR_H,
158 		.bit	= 2,
159 		.prio_mask = 2,
160 	},
161 	[35] = {
162 		.pend	= IPIC_SIPNR_H,
163 		.mask	= IPIC_SIMSR_H,
164 		.prio	= IPIC_SIPRR_A,
165 		.force	= IPIC_SIFCR_H,
166 		.bit	= 3,
167 		.prio_mask = 3,
168 	},
169 	[36] = {
170 		.pend	= IPIC_SIPNR_H,
171 		.mask	= IPIC_SIMSR_H,
172 		.prio	= IPIC_SIPRR_A,
173 		.force	= IPIC_SIFCR_H,
174 		.bit	= 4,
175 		.prio_mask = 4,
176 	},
177 	[37] = {
178 		.pend	= IPIC_SIPNR_H,
179 		.mask	= IPIC_SIMSR_H,
180 		.prio	= IPIC_SIPRR_A,
181 		.force	= IPIC_SIFCR_H,
182 		.bit	= 5,
183 		.prio_mask = 5,
184 	},
185 	[38] = {
186 		.pend	= IPIC_SIPNR_H,
187 		.mask	= IPIC_SIMSR_H,
188 		.prio	= IPIC_SIPRR_A,
189 		.force	= IPIC_SIFCR_H,
190 		.bit	= 6,
191 		.prio_mask = 6,
192 	},
193 	[39] = {
194 		.pend	= IPIC_SIPNR_H,
195 		.mask	= IPIC_SIMSR_H,
196 		.prio	= IPIC_SIPRR_A,
197 		.force	= IPIC_SIFCR_H,
198 		.bit	= 7,
199 		.prio_mask = 7,
200 	},
201 	[48] = {
202 		.pend	= IPIC_SEPNR,
203 		.mask	= IPIC_SEMSR,
204 		.prio	= IPIC_SMPRR_A,
205 		.force	= IPIC_SEFCR,
206 		.bit	= 0,
207 		.prio_mask = 4,
208 	},
209 	[64] = {
210 		.pend	= IPIC_SIPNR_H,
211 		.mask	= IPIC_SIMSR_L,
212 		.prio	= IPIC_SMPRR_A,
213 		.force	= IPIC_SIFCR_L,
214 		.bit	= 0,
215 		.prio_mask = 0,
216 	},
217 	[65] = {
218 		.pend	= IPIC_SIPNR_H,
219 		.mask	= IPIC_SIMSR_L,
220 		.prio	= IPIC_SMPRR_A,
221 		.force	= IPIC_SIFCR_L,
222 		.bit	= 1,
223 		.prio_mask = 1,
224 	},
225 	[66] = {
226 		.pend	= IPIC_SIPNR_H,
227 		.mask	= IPIC_SIMSR_L,
228 		.prio	= IPIC_SMPRR_A,
229 		.force	= IPIC_SIFCR_L,
230 		.bit	= 2,
231 		.prio_mask = 2,
232 	},
233 	[67] = {
234 		.pend	= IPIC_SIPNR_H,
235 		.mask	= IPIC_SIMSR_L,
236 		.prio	= IPIC_SMPRR_A,
237 		.force	= IPIC_SIFCR_L,
238 		.bit	= 3,
239 		.prio_mask = 3,
240 	},
241 	[68] = {
242 		.pend	= IPIC_SIPNR_H,
243 		.mask	= IPIC_SIMSR_L,
244 		.prio	= IPIC_SMPRR_B,
245 		.force	= IPIC_SIFCR_L,
246 		.bit	= 4,
247 		.prio_mask = 0,
248 	},
249 	[69] = {
250 		.pend	= IPIC_SIPNR_H,
251 		.mask	= IPIC_SIMSR_L,
252 		.prio	= IPIC_SMPRR_B,
253 		.force	= IPIC_SIFCR_L,
254 		.bit	= 5,
255 		.prio_mask = 1,
256 	},
257 	[70] = {
258 		.pend	= IPIC_SIPNR_H,
259 		.mask	= IPIC_SIMSR_L,
260 		.prio	= IPIC_SMPRR_B,
261 		.force	= IPIC_SIFCR_L,
262 		.bit	= 6,
263 		.prio_mask = 2,
264 	},
265 	[71] = {
266 		.pend	= IPIC_SIPNR_H,
267 		.mask	= IPIC_SIMSR_L,
268 		.prio	= IPIC_SMPRR_B,
269 		.force	= IPIC_SIFCR_L,
270 		.bit	= 7,
271 		.prio_mask = 3,
272 	},
273 	[72] = {
274 		.pend	= IPIC_SIPNR_H,
275 		.mask	= IPIC_SIMSR_L,
276 		.prio	= 0,
277 		.force	= IPIC_SIFCR_L,
278 		.bit	= 8,
279 	},
280 	[73] = {
281 		.pend	= IPIC_SIPNR_H,
282 		.mask	= IPIC_SIMSR_L,
283 		.prio	= 0,
284 		.force	= IPIC_SIFCR_L,
285 		.bit	= 9,
286 	},
287 	[74] = {
288 		.pend	= IPIC_SIPNR_H,
289 		.mask	= IPIC_SIMSR_L,
290 		.prio	= 0,
291 		.force	= IPIC_SIFCR_L,
292 		.bit	= 10,
293 	},
294 	[75] = {
295 		.pend	= IPIC_SIPNR_H,
296 		.mask	= IPIC_SIMSR_L,
297 		.prio	= 0,
298 		.force	= IPIC_SIFCR_L,
299 		.bit	= 11,
300 	},
301 	[76] = {
302 		.pend	= IPIC_SIPNR_H,
303 		.mask	= IPIC_SIMSR_L,
304 		.prio	= 0,
305 		.force	= IPIC_SIFCR_L,
306 		.bit	= 12,
307 	},
308 	[77] = {
309 		.pend	= IPIC_SIPNR_H,
310 		.mask	= IPIC_SIMSR_L,
311 		.prio	= 0,
312 		.force	= IPIC_SIFCR_L,
313 		.bit	= 13,
314 	},
315 	[78] = {
316 		.pend	= IPIC_SIPNR_H,
317 		.mask	= IPIC_SIMSR_L,
318 		.prio	= 0,
319 		.force	= IPIC_SIFCR_L,
320 		.bit	= 14,
321 	},
322 	[79] = {
323 		.pend	= IPIC_SIPNR_H,
324 		.mask	= IPIC_SIMSR_L,
325 		.prio	= 0,
326 		.force	= IPIC_SIFCR_L,
327 		.bit	= 15,
328 	},
329 	[80] = {
330 		.pend	= IPIC_SIPNR_H,
331 		.mask	= IPIC_SIMSR_L,
332 		.prio	= 0,
333 		.force	= IPIC_SIFCR_L,
334 		.bit	= 16,
335 	},
336 	[84] = {
337 		.pend	= IPIC_SIPNR_H,
338 		.mask	= IPIC_SIMSR_L,
339 		.prio	= 0,
340 		.force	= IPIC_SIFCR_L,
341 		.bit	= 20,
342 	},
343 	[85] = {
344 		.pend	= IPIC_SIPNR_H,
345 		.mask	= IPIC_SIMSR_L,
346 		.prio	= 0,
347 		.force	= IPIC_SIFCR_L,
348 		.bit	= 21,
349 	},
350 	[90] = {
351 		.pend	= IPIC_SIPNR_H,
352 		.mask	= IPIC_SIMSR_L,
353 		.prio	= 0,
354 		.force	= IPIC_SIFCR_L,
355 		.bit	= 26,
356 	},
357 	[91] = {
358 		.pend	= IPIC_SIPNR_H,
359 		.mask	= IPIC_SIMSR_L,
360 		.prio	= 0,
361 		.force	= IPIC_SIFCR_L,
362 		.bit	= 27,
363 	},
364 };
365 
366 static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg)
367 {
368 	return in_be32(base + (reg >> 2));
369 }
370 
371 static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value)
372 {
373 	out_be32(base + (reg >> 2), value);
374 }
375 
376 static inline struct ipic * ipic_from_irq(unsigned int irq)
377 {
378 	return primary_ipic;
379 }
380 
381 static void ipic_enable_irq(unsigned int irq)
382 {
383 	struct ipic *ipic = ipic_from_irq(irq);
384 	unsigned int src = irq - ipic->irq_offset;
385 	u32 temp;
386 
387 	temp = ipic_read(ipic->regs, ipic_info[src].mask);
388 	temp |= (1 << (31 - ipic_info[src].bit));
389 	ipic_write(ipic->regs, ipic_info[src].mask, temp);
390 }
391 
392 static void ipic_disable_irq(unsigned int irq)
393 {
394 	struct ipic *ipic = ipic_from_irq(irq);
395 	unsigned int src = irq - ipic->irq_offset;
396 	u32 temp;
397 
398 	temp = ipic_read(ipic->regs, ipic_info[src].mask);
399 	temp &= ~(1 << (31 - ipic_info[src].bit));
400 	ipic_write(ipic->regs, ipic_info[src].mask, temp);
401 }
402 
403 static void ipic_disable_irq_and_ack(unsigned int irq)
404 {
405 	struct ipic *ipic = ipic_from_irq(irq);
406 	unsigned int src = irq - ipic->irq_offset;
407 	u32 temp;
408 
409 	ipic_disable_irq(irq);
410 
411 	temp = ipic_read(ipic->regs, ipic_info[src].pend);
412 	temp |= (1 << (31 - ipic_info[src].bit));
413 	ipic_write(ipic->regs, ipic_info[src].pend, temp);
414 }
415 
416 static void ipic_end_irq(unsigned int irq)
417 {
418 	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
419 		ipic_enable_irq(irq);
420 }
421 
422 struct hw_interrupt_type ipic = {
423 	.typename = " IPIC  ",
424 	.enable = ipic_enable_irq,
425 	.disable = ipic_disable_irq,
426 	.ack = ipic_disable_irq_and_ack,
427 	.end = ipic_end_irq,
428 };
429 
430 void __init ipic_init(phys_addr_t phys_addr,
431 		unsigned int flags,
432 		unsigned int irq_offset,
433 		unsigned char *senses,
434 		unsigned int senses_count)
435 {
436 	u32 i, temp = 0;
437 
438 	primary_ipic = &p_ipic;
439 	primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE);
440 
441 	primary_ipic->irq_offset = irq_offset;
442 
443 	ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0);
444 
445 	/* default priority scheme is grouped. If spread mode is required
446 	 * configure SICFR accordingly */
447 	if (flags & IPIC_SPREADMODE_GRP_A)
448 		temp |= SICFR_IPSA;
449 	if (flags & IPIC_SPREADMODE_GRP_D)
450 		temp |= SICFR_IPSD;
451 	if (flags & IPIC_SPREADMODE_MIX_A)
452 		temp |= SICFR_MPSA;
453 	if (flags & IPIC_SPREADMODE_MIX_B)
454 		temp |= SICFR_MPSB;
455 
456 	ipic_write(primary_ipic->regs, IPIC_SICNR, temp);
457 
458 	/* handle MCP route */
459 	temp = 0;
460 	if (flags & IPIC_DISABLE_MCP_OUT)
461 		temp = SERCR_MCPR;
462 	ipic_write(primary_ipic->regs, IPIC_SERCR, temp);
463 
464 	/* handle routing of IRQ0 to MCP */
465 	temp = ipic_read(primary_ipic->regs, IPIC_SEMSR);
466 
467 	if (flags & IPIC_IRQ0_MCP)
468 		temp |= SEMSR_SIRQ0;
469 	else
470 		temp &= ~SEMSR_SIRQ0;
471 
472 	ipic_write(primary_ipic->regs, IPIC_SEMSR, temp);
473 
474 	for (i = 0 ; i < NR_IPIC_INTS ; i++) {
475 		irq_desc[i+irq_offset].handler = &ipic;
476 		irq_desc[i+irq_offset].status = IRQ_LEVEL;
477 	}
478 
479 	temp = 0;
480 	for (i = 0 ; i < senses_count ; i++) {
481 		if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
482 			temp |= 1 << (15 - i);
483 			if (i != 0)
484 				irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
485 			else
486 				irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0;
487 		}
488 	}
489 	ipic_write(primary_ipic->regs, IPIC_SECNR, temp);
490 
491 	printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS,
492 			senses_count, primary_ipic->regs);
493 }
494 
495 int ipic_set_priority(unsigned int irq, unsigned int priority)
496 {
497 	struct ipic *ipic = ipic_from_irq(irq);
498 	unsigned int src = irq - ipic->irq_offset;
499 	u32 temp;
500 
501 	if (priority > 7)
502 		return -EINVAL;
503 	if (src > 127)
504 		return -EINVAL;
505 	if (ipic_info[src].prio == 0)
506 		return -EINVAL;
507 
508 	temp = ipic_read(ipic->regs, ipic_info[src].prio);
509 
510 	if (priority < 4) {
511 		temp &= ~(0x7 << (20 + (3 - priority) * 3));
512 		temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3);
513 	} else {
514 		temp &= ~(0x7 << (4 + (7 - priority) * 3));
515 		temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3);
516 	}
517 
518 	ipic_write(ipic->regs, ipic_info[src].prio, temp);
519 
520 	return 0;
521 }
522 
523 void ipic_set_highest_priority(unsigned int irq)
524 {
525 	struct ipic *ipic = ipic_from_irq(irq);
526 	unsigned int src = irq - ipic->irq_offset;
527 	u32 temp;
528 
529 	temp = ipic_read(ipic->regs, IPIC_SICFR);
530 
531 	/* clear and set HPI */
532 	temp &= 0x7f000000;
533 	temp |= (src & 0x7f) << 24;
534 
535 	ipic_write(ipic->regs, IPIC_SICFR, temp);
536 }
537 
538 void ipic_set_default_priority(void)
539 {
540 	ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0);
541 	ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1);
542 	ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2);
543 	ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3);
544 	ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4);
545 	ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5);
546 	ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6);
547 	ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7);
548 
549 	ipic_set_priority(MPC83xx_IRQ_UART1, 0);
550 	ipic_set_priority(MPC83xx_IRQ_UART2, 1);
551 	ipic_set_priority(MPC83xx_IRQ_SEC2, 2);
552 	ipic_set_priority(MPC83xx_IRQ_IIC1, 5);
553 	ipic_set_priority(MPC83xx_IRQ_IIC2, 6);
554 	ipic_set_priority(MPC83xx_IRQ_SPI, 7);
555 	ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0);
556 	ipic_set_priority(MPC83xx_IRQ_PIT, 1);
557 	ipic_set_priority(MPC83xx_IRQ_PCI1, 2);
558 	ipic_set_priority(MPC83xx_IRQ_PCI2, 3);
559 	ipic_set_priority(MPC83xx_IRQ_EXT0, 4);
560 	ipic_set_priority(MPC83xx_IRQ_EXT1, 5);
561 	ipic_set_priority(MPC83xx_IRQ_EXT2, 6);
562 	ipic_set_priority(MPC83xx_IRQ_EXT3, 7);
563 	ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0);
564 	ipic_set_priority(MPC83xx_IRQ_MU, 1);
565 	ipic_set_priority(MPC83xx_IRQ_SBA, 2);
566 	ipic_set_priority(MPC83xx_IRQ_DMA, 3);
567 	ipic_set_priority(MPC83xx_IRQ_EXT4, 4);
568 	ipic_set_priority(MPC83xx_IRQ_EXT5, 5);
569 	ipic_set_priority(MPC83xx_IRQ_EXT6, 6);
570 	ipic_set_priority(MPC83xx_IRQ_EXT7, 7);
571 }
572 
573 void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
574 {
575 	struct ipic *ipic = primary_ipic;
576 	u32 temp;
577 
578 	temp = ipic_read(ipic->regs, IPIC_SERMR);
579 	temp |= (1 << (31 - mcp_irq));
580 	ipic_write(ipic->regs, IPIC_SERMR, temp);
581 }
582 
583 void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq)
584 {
585 	struct ipic *ipic = primary_ipic;
586 	u32 temp;
587 
588 	temp = ipic_read(ipic->regs, IPIC_SERMR);
589 	temp &= (1 << (31 - mcp_irq));
590 	ipic_write(ipic->regs, IPIC_SERMR, temp);
591 }
592 
593 u32 ipic_get_mcp_status(void)
594 {
595 	return ipic_read(primary_ipic->regs, IPIC_SERMR);
596 }
597 
598 void ipic_clear_mcp_status(u32 mask)
599 {
600 	ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
601 }
602 
603 /* Return an interrupt vector or -1 if no interrupt is pending. */
604 int ipic_get_irq(struct pt_regs *regs)
605 {
606 	int irq;
607 
608 	irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f;
609 
610 	if (irq == 0)    /* 0 --> no irq is pending */
611 		irq = -1;
612 
613 	return irq;
614 }
615 
616 static struct sysdev_class ipic_sysclass = {
617 	set_kset_name("ipic"),
618 };
619 
620 static struct sys_device device_ipic = {
621 	.id		= 0,
622 	.cls		= &ipic_sysclass,
623 };
624 
625 static int __init init_ipic_sysfs(void)
626 {
627 	int rc;
628 
629 	if (!primary_ipic->regs)
630 		return -ENODEV;
631 	printk(KERN_DEBUG "Registering ipic with sysfs...\n");
632 
633 	rc = sysdev_class_register(&ipic_sysclass);
634 	if (rc) {
635 		printk(KERN_ERR "Failed registering ipic sys class\n");
636 		return -ENODEV;
637 	}
638 	rc = sysdev_register(&device_ipic);
639 	if (rc) {
640 		printk(KERN_ERR "Failed registering ipic sys device\n");
641 		return -ENODEV;
642 	}
643 	return 0;
644 }
645 
646 subsys_initcall(init_ipic_sysfs);
647