2 * vrc4173.c, NEC VRC4173 base driver for NEC VR4122/VR4131.
4 * Copyright (C) 2001-2003 MontaVista Software Inc.
5 * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com>
6 * Copyright (C) 2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
7 * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <linux/init.h>
24 #include <linux/module.h>
25 #include <linux/interrupt.h>
26 #include <linux/irq.h>
27 #include <linux/pci.h>
28 #include <linux/spinlock.h>
29 #include <linux/types.h>
31 #include <asm/vr41xx/irq.h>
32 #include <asm/vr41xx/vr41xx.h>
33 #include <asm/vr41xx/vrc4173.h>
35 MODULE_DESCRIPTION("NEC VRC4173 base driver for NEC VR4122/4131");
36 MODULE_AUTHOR("Yoichi Yuasa <yyuasa@mvista.com>");
37 MODULE_LICENSE("GPL");
39 #define VRC4173_CMUCLKMSK 0x040
43 #define MSKPS2CH1 0x0008
44 #define MSKPS2CH2 0x0010
46 #define MSKCARD1 0x0040
47 #define MSKCARD2 0x0080
48 #define MSKAC97 0x0100
49 #define MSK48MUSB 0x0400
50 #define MSK48MPIN 0x0800
51 #define MSK48MOSC 0x1000
52 #define VRC4173_CMUSRST 0x042
54 #define CARD1RST 0x0002
55 #define CARD2RST 0x0004
56 #define AC97RST 0x0008
58 #define VRC4173_SYSINT1REG 0x060
59 #define VRC4173_MSYSINT1REG 0x06c
60 #define VRC4173_MPIUINTREG 0x06e
61 #define VRC4173_MAIUINTREG 0x070
62 #define VRC4173_MKIUINTREG 0x072
64 #define VRC4173_SELECTREG 0x09e
70 static struct pci_device_id vrc4173_id_table
[] __devinitdata
= {
71 { .vendor
= PCI_VENDOR_ID_NEC
,
72 .device
= PCI_DEVICE_ID_NEC_VRC4173
,
73 .subvendor
= PCI_ANY_ID
,
74 .subdevice
= PCI_ANY_ID
, },
78 unsigned long vrc4173_io_offset
= 0;
80 EXPORT_SYMBOL(vrc4173_io_offset
);
82 static int vrc4173_initialized
;
83 static uint16_t vrc4173_cmuclkmsk
;
84 static uint16_t vrc4173_selectreg
;
85 static DEFINE_SPINLOCK(vrc4173_cmu_lock
);
86 static DEFINE_SPINLOCK(vrc4173_giu_lock
);
88 static inline void set_cmusrst(uint16_t val
)
92 cmusrst
= vrc4173_inw(VRC4173_CMUSRST
);
94 vrc4173_outw(cmusrst
, VRC4173_CMUSRST
);
97 static inline void clear_cmusrst(uint16_t val
)
101 cmusrst
= vrc4173_inw(VRC4173_CMUSRST
);
103 vrc4173_outw(cmusrst
, VRC4173_CMUSRST
);
106 void vrc4173_supply_clock(vrc4173_clock_t clock
)
108 if (vrc4173_initialized
) {
109 spin_lock_irq(&vrc4173_cmu_lock
);
112 case VRC4173_PIU_CLOCK
:
113 vrc4173_cmuclkmsk
|= MSKPIU
;
115 case VRC4173_KIU_CLOCK
:
116 vrc4173_cmuclkmsk
|= MSKKIU
;
118 case VRC4173_AIU_CLOCK
:
119 vrc4173_cmuclkmsk
|= MSKAIU
;
121 case VRC4173_PS2_CH1_CLOCK
:
122 vrc4173_cmuclkmsk
|= MSKPS2CH1
;
124 case VRC4173_PS2_CH2_CLOCK
:
125 vrc4173_cmuclkmsk
|= MSKPS2CH2
;
127 case VRC4173_USBU_PCI_CLOCK
:
129 vrc4173_cmuclkmsk
|= MSKUSB
;
131 case VRC4173_CARDU1_PCI_CLOCK
:
132 set_cmusrst(CARD1RST
);
133 vrc4173_cmuclkmsk
|= MSKCARD1
;
135 case VRC4173_CARDU2_PCI_CLOCK
:
136 set_cmusrst(CARD2RST
);
137 vrc4173_cmuclkmsk
|= MSKCARD2
;
139 case VRC4173_AC97U_PCI_CLOCK
:
140 set_cmusrst(AC97RST
);
141 vrc4173_cmuclkmsk
|= MSKAC97
;
143 case VRC4173_USBU_48MHz_CLOCK
:
145 vrc4173_cmuclkmsk
|= MSK48MUSB
;
147 case VRC4173_EXT_48MHz_CLOCK
:
148 if (vrc4173_cmuclkmsk
& MSK48MOSC
)
149 vrc4173_cmuclkmsk
|= MSK48MPIN
;
152 "vrc4173_supply_clock: "
153 "Please supply VRC4173_48MHz_CLOCK first "
154 "rather than VRC4173_EXT_48MHz_CLOCK.\n");
156 case VRC4173_48MHz_CLOCK
:
157 vrc4173_cmuclkmsk
|= MSK48MOSC
;
161 "vrc4173_supply_clock: Invalid CLOCK value %u\n", clock
);
165 vrc4173_outw(vrc4173_cmuclkmsk
, VRC4173_CMUCLKMSK
);
168 case VRC4173_USBU_PCI_CLOCK
:
169 case VRC4173_USBU_48MHz_CLOCK
:
170 clear_cmusrst(USBRST
);
172 case VRC4173_CARDU1_PCI_CLOCK
:
173 clear_cmusrst(CARD1RST
);
175 case VRC4173_CARDU2_PCI_CLOCK
:
176 clear_cmusrst(CARD2RST
);
178 case VRC4173_AC97U_PCI_CLOCK
:
179 clear_cmusrst(AC97RST
);
185 spin_unlock_irq(&vrc4173_cmu_lock
);
189 EXPORT_SYMBOL(vrc4173_supply_clock
);
191 void vrc4173_mask_clock(vrc4173_clock_t clock
)
193 if (vrc4173_initialized
) {
194 spin_lock_irq(&vrc4173_cmu_lock
);
197 case VRC4173_PIU_CLOCK
:
198 vrc4173_cmuclkmsk
&= ~MSKPIU
;
200 case VRC4173_KIU_CLOCK
:
201 vrc4173_cmuclkmsk
&= ~MSKKIU
;
203 case VRC4173_AIU_CLOCK
:
204 vrc4173_cmuclkmsk
&= ~MSKAIU
;
206 case VRC4173_PS2_CH1_CLOCK
:
207 vrc4173_cmuclkmsk
&= ~MSKPS2CH1
;
209 case VRC4173_PS2_CH2_CLOCK
:
210 vrc4173_cmuclkmsk
&= ~MSKPS2CH2
;
212 case VRC4173_USBU_PCI_CLOCK
:
214 vrc4173_cmuclkmsk
&= ~MSKUSB
;
216 case VRC4173_CARDU1_PCI_CLOCK
:
217 set_cmusrst(CARD1RST
);
218 vrc4173_cmuclkmsk
&= ~MSKCARD1
;
220 case VRC4173_CARDU2_PCI_CLOCK
:
221 set_cmusrst(CARD2RST
);
222 vrc4173_cmuclkmsk
&= ~MSKCARD2
;
224 case VRC4173_AC97U_PCI_CLOCK
:
225 set_cmusrst(AC97RST
);
226 vrc4173_cmuclkmsk
&= ~MSKAC97
;
228 case VRC4173_USBU_48MHz_CLOCK
:
230 vrc4173_cmuclkmsk
&= ~MSK48MUSB
;
232 case VRC4173_EXT_48MHz_CLOCK
:
233 vrc4173_cmuclkmsk
&= ~MSK48MPIN
;
235 case VRC4173_48MHz_CLOCK
:
236 vrc4173_cmuclkmsk
&= ~MSK48MOSC
;
239 printk(KERN_WARNING
"vrc4173_mask_clock: Invalid CLOCK value %u\n", clock
);
243 vrc4173_outw(vrc4173_cmuclkmsk
, VRC4173_CMUCLKMSK
);
246 case VRC4173_USBU_PCI_CLOCK
:
247 case VRC4173_USBU_48MHz_CLOCK
:
248 clear_cmusrst(USBRST
);
250 case VRC4173_CARDU1_PCI_CLOCK
:
251 clear_cmusrst(CARD1RST
);
253 case VRC4173_CARDU2_PCI_CLOCK
:
254 clear_cmusrst(CARD2RST
);
256 case VRC4173_AC97U_PCI_CLOCK
:
257 clear_cmusrst(AC97RST
);
263 spin_unlock_irq(&vrc4173_cmu_lock
);
267 EXPORT_SYMBOL(vrc4173_mask_clock
);
269 static inline void vrc4173_cmu_init(void)
271 vrc4173_cmuclkmsk
= vrc4173_inw(VRC4173_CMUCLKMSK
);
273 spin_lock_init(&vrc4173_cmu_lock
);
276 void vrc4173_select_function(vrc4173_function_t function
)
278 if (vrc4173_initialized
) {
279 spin_lock_irq(&vrc4173_giu_lock
);
283 vrc4173_selectreg
|= SEL2
;
286 vrc4173_selectreg
|= SEL1
;
289 vrc4173_selectreg
&= SEL2
| SEL1
| SEL0
;
291 case KEYBOARD_8SCANLINES
:
292 vrc4173_selectreg
&= SEL3
| SEL2
| SEL1
;
294 case KEYBOARD_10SCANLINES
:
295 vrc4173_selectreg
&= SEL3
| SEL2
;
297 case KEYBOARD_12SCANLINES
:
298 vrc4173_selectreg
&= SEL3
;
301 vrc4173_selectreg
|= SEL0
;
304 vrc4173_selectreg
|= SEL3
;
308 vrc4173_outw(vrc4173_selectreg
, VRC4173_SELECTREG
);
310 spin_unlock_irq(&vrc4173_giu_lock
);
314 EXPORT_SYMBOL(vrc4173_select_function
);
316 static inline void vrc4173_giu_init(void)
318 vrc4173_selectreg
= vrc4173_inw(VRC4173_SELECTREG
);
320 spin_lock_init(&vrc4173_giu_lock
);
323 void vrc4173_enable_piuint(uint16_t mask
)
325 struct irq_desc
*desc
= irq_desc
+ VRC4173_PIU_IRQ
;
329 spin_lock_irqsave(&desc
->lock
, flags
);
330 val
= vrc4173_inw(VRC4173_MPIUINTREG
);
332 vrc4173_outw(val
, VRC4173_MPIUINTREG
);
333 spin_unlock_irqrestore(&desc
->lock
, flags
);
336 EXPORT_SYMBOL(vrc4173_enable_piuint
);
338 void vrc4173_disable_piuint(uint16_t mask
)
340 struct irq_desc
*desc
= irq_desc
+ VRC4173_PIU_IRQ
;
344 spin_lock_irqsave(&desc
->lock
, flags
);
345 val
= vrc4173_inw(VRC4173_MPIUINTREG
);
347 vrc4173_outw(val
, VRC4173_MPIUINTREG
);
348 spin_unlock_irqrestore(&desc
->lock
, flags
);
351 EXPORT_SYMBOL(vrc4173_disable_piuint
);
353 void vrc4173_enable_aiuint(uint16_t mask
)
355 struct irq_desc
*desc
= irq_desc
+ VRC4173_AIU_IRQ
;
359 spin_lock_irqsave(&desc
->lock
, flags
);
360 val
= vrc4173_inw(VRC4173_MAIUINTREG
);
362 vrc4173_outw(val
, VRC4173_MAIUINTREG
);
363 spin_unlock_irqrestore(&desc
->lock
, flags
);
366 EXPORT_SYMBOL(vrc4173_enable_aiuint
);
368 void vrc4173_disable_aiuint(uint16_t mask
)
370 struct irq_desc
*desc
= irq_desc
+ VRC4173_AIU_IRQ
;
374 spin_lock_irqsave(&desc
->lock
, flags
);
375 val
= vrc4173_inw(VRC4173_MAIUINTREG
);
377 vrc4173_outw(val
, VRC4173_MAIUINTREG
);
378 spin_unlock_irqrestore(&desc
->lock
, flags
);
381 EXPORT_SYMBOL(vrc4173_disable_aiuint
);
383 void vrc4173_enable_kiuint(uint16_t mask
)
385 struct irq_desc
*desc
= irq_desc
+ VRC4173_KIU_IRQ
;
389 spin_lock_irqsave(&desc
->lock
, flags
);
390 val
= vrc4173_inw(VRC4173_MKIUINTREG
);
392 vrc4173_outw(val
, VRC4173_MKIUINTREG
);
393 spin_unlock_irqrestore(&desc
->lock
, flags
);
396 EXPORT_SYMBOL(vrc4173_enable_kiuint
);
398 void vrc4173_disable_kiuint(uint16_t mask
)
400 struct irq_desc
*desc
= irq_desc
+ VRC4173_KIU_IRQ
;
404 spin_lock_irqsave(&desc
->lock
, flags
);
405 val
= vrc4173_inw(VRC4173_MKIUINTREG
);
407 vrc4173_outw(val
, VRC4173_MKIUINTREG
);
408 spin_unlock_irqrestore(&desc
->lock
, flags
);
411 EXPORT_SYMBOL(vrc4173_disable_kiuint
);
413 static void enable_vrc4173_irq(unsigned int irq
)
417 val
= vrc4173_inw(VRC4173_MSYSINT1REG
);
418 val
|= (uint16_t)1 << (irq
- VRC4173_IRQ_BASE
);
419 vrc4173_outw(val
, VRC4173_MSYSINT1REG
);
422 static void disable_vrc4173_irq(unsigned int irq
)
426 val
= vrc4173_inw(VRC4173_MSYSINT1REG
);
427 val
&= ~((uint16_t)1 << (irq
- VRC4173_IRQ_BASE
));
428 vrc4173_outw(val
, VRC4173_MSYSINT1REG
);
431 static unsigned int startup_vrc4173_irq(unsigned int irq
)
433 enable_vrc4173_irq(irq
);
434 return 0; /* never anything pending */
437 #define shutdown_vrc4173_irq disable_vrc4173_irq
438 #define ack_vrc4173_irq disable_vrc4173_irq
440 static void end_vrc4173_irq(unsigned int irq
)
442 if (!(irq_desc
[irq
].status
& (IRQ_DISABLED
| IRQ_INPROGRESS
)))
443 enable_vrc4173_irq(irq
);
446 static struct irq_chip vrc4173_irq_type
= {
447 .typename
= "VRC4173",
448 .startup
= startup_vrc4173_irq
,
449 .shutdown
= shutdown_vrc4173_irq
,
450 .enable
= enable_vrc4173_irq
,
451 .disable
= disable_vrc4173_irq
,
452 .ack
= ack_vrc4173_irq
,
453 .end
= end_vrc4173_irq
,
456 static int vrc4173_get_irq_number(int irq
)
458 uint16_t status
, mask
;
461 status
= vrc4173_inw(VRC4173_SYSINT1REG
);
462 mask
= vrc4173_inw(VRC4173_MSYSINT1REG
);
466 for (i
= 0; i
< 16; i
++)
467 if (status
& (0x0001 << i
))
468 return VRC4173_IRQ(i
);
474 static inline int vrc4173_icu_init(int cascade_irq
)
478 if (cascade_irq
< GIU_IRQ(0) || cascade_irq
> GIU_IRQ(15))
481 vrc4173_outw(0, VRC4173_MSYSINT1REG
);
483 vr41xx_set_irq_trigger(GIU_IRQ_TO_PIN(cascade_irq
), TRIGGER_LEVEL
, SIGNAL_THROUGH
);
484 vr41xx_set_irq_level(GIU_IRQ_TO_PIN(cascade_irq
), LEVEL_LOW
);
486 for (i
= VRC4173_IRQ_BASE
; i
<= VRC4173_IRQ_LAST
; i
++)
487 irq_desc
[i
].chip
= &vrc4173_irq_type
;
492 static int __devinit
vrc4173_probe(struct pci_dev
*dev
,
493 const struct pci_device_id
*id
)
495 unsigned long start
, flags
;
498 err
= pci_enable_device(dev
);
500 printk(KERN_ERR
"vrc4173: Failed to enable PCI device, aborting\n");
506 start
= pci_resource_start(dev
, 0);
508 printk(KERN_ERR
"vrc4173:No such PCI I/O resource, aborting\n");
512 flags
= pci_resource_flags(dev
, 0);
513 if ((flags
& IORESOURCE_IO
) == 0) {
514 printk(KERN_ERR
"vrc4173: No such PCI I/O resource, aborting\n");
518 err
= pci_request_regions(dev
, "NEC VRC4173");
520 printk(KERN_ERR
"vrc4173: PCI resources are busy, aborting\n");
524 set_vrc4173_io_offset(start
);
529 err
= vrc4173_icu_init(dev
->irq
);
531 printk(KERN_ERR
"vrc4173: Invalid IRQ %d, aborting\n", dev
->irq
);
535 err
= vr41xx_cascade_irq(dev
->irq
, vrc4173_get_irq_number
);
537 printk(KERN_ERR
"vrc4173: IRQ resource %d is busy, aborting\n", dev
->irq
);
542 "NEC VRC4173 at 0x%#08lx, IRQ is cascaded to %d\n", start
, dev
->irq
);
547 static void vrc4173_remove(struct pci_dev
*dev
)
549 free_irq(dev
->irq
, NULL
);
551 pci_release_regions(dev
);
554 static struct pci_driver vrc4173_driver
= {
555 .name
= "NEC VRC4173",
556 .probe
= vrc4173_probe
,
557 .remove
= vrc4173_remove
,
558 .id_table
= vrc4173_id_table
,
561 static int __devinit
vrc4173_init(void)
565 err
= pci_register_driver(&vrc4173_driver
);
569 vrc4173_initialized
= 1;
574 static void __devexit
vrc4173_exit(void)
576 vrc4173_initialized
= 0;
578 pci_unregister_driver(&vrc4173_driver
);
581 module_init(vrc4173_init
);
582 module_exit(vrc4173_exit
);