1 /* linux/arch/i386/kernel/scx200.c
3 Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
5 National Semiconductor SCx200 support. */
7 #include <linux/config.h>
8 #include <linux/module.h>
9 #include <linux/errno.h>
10 #include <linux/kernel.h>
11 #include <linux/init.h>
12 #include <linux/pci.h>
14 #include <linux/scx200.h>
18 MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
19 MODULE_DESCRIPTION("NatSemi SCx200 Driver");
20 MODULE_LICENSE("GPL");
22 unsigned scx200_gpio_base = 0;
23 long scx200_gpio_shadow[2];
25 static struct pci_device_id scx200_tbl[] = {
26 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) },
27 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) },
30 MODULE_DEVICE_TABLE(pci,scx200_tbl);
32 static int __devinit scx200_probe(struct pci_dev *, const struct pci_device_id *);
34 static struct pci_driver scx200_pci_driver = {
36 .id_table = scx200_tbl,
37 .probe = scx200_probe,
40 DEFINE_SPINLOCK(scx200_gpio_lock);
41 static DEFINE_SPINLOCK(scx200_gpio_config_lock);
43 static int __devinit scx200_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
48 base = pci_resource_start(pdev, 0);
49 printk(KERN_INFO NAME ": GPIO base 0x%x\n", base);
51 if (request_region(base, SCx200_GPIO_SIZE, "NatSemi SCx200 GPIO") == 0) {
52 printk(KERN_ERR NAME ": can't allocate I/O for GPIOs\n");
56 scx200_gpio_base = base;
58 /* read the current values driven on the GPIO signals */
59 for (bank = 0; bank < 2; ++bank)
60 scx200_gpio_shadow[bank] = inl(scx200_gpio_base + 0x10 * bank);
66 u32 scx200_gpio_configure(int index, u32 mask, u32 bits)
68 u32 config, new_config;
71 spin_lock_irqsave(&scx200_gpio_config_lock, flags);
73 outl(index, scx200_gpio_base + 0x20);
74 config = inl(scx200_gpio_base + 0x24);
76 new_config = (config & mask) | bits;
77 outl(new_config, scx200_gpio_base + 0x24);
79 spin_unlock_irqrestore(&scx200_gpio_config_lock, flags);
84 void scx200_gpio_dump(unsigned index)
86 u32 config = scx200_gpio_configure(index, ~0, 0);
87 printk(KERN_DEBUG "GPIO%02u: 0x%08lx", index, (unsigned long)config);
90 printk(" OE"); /* output enabled */
92 printk(" TS"); /* tristate */
94 printk(" PP"); /* push pull */
96 printk(" OD"); /* open drain */
98 printk(" PUE"); /* pull up enabled */
100 printk(" PUD"); /* pull up disabled */
102 printk(" LOCKED"); /* locked */
104 printk(" LEVEL"); /* level input */
106 printk(" EDGE"); /* edge input */
108 printk(" HI"); /* trigger on rising edge */
110 printk(" LO"); /* trigger on falling edge */
112 printk(" DEBOUNCE"); /* debounce */
116 int __init scx200_init(void)
118 printk(KERN_INFO NAME ": NatSemi SCx200 Driver\n");
120 return pci_module_init(&scx200_pci_driver);
123 void __exit scx200_cleanup(void)
125 pci_unregister_driver(&scx200_pci_driver);
126 release_region(scx200_gpio_base, SCx200_GPIO_SIZE);
129 module_init(scx200_init);
130 module_exit(scx200_cleanup);
132 EXPORT_SYMBOL(scx200_gpio_base);
133 EXPORT_SYMBOL(scx200_gpio_shadow);
134 EXPORT_SYMBOL(scx200_gpio_lock);
135 EXPORT_SYMBOL(scx200_gpio_configure);
136 EXPORT_SYMBOL(scx200_gpio_dump);
140 compile-command: "make -k -C ../../.. SUBDIRS=arch/i386/kernel modules"