]> rtime.felk.cvut.cz Git - mf6xx.git/blob - mf614.c
Added README file
[mf6xx.git] / mf614.c
1 #include <linux/init.h>
2 #include <linux/module.h>
3 #include <linux/device.h>
4 #include <linux/pci.h>
5 #include <linux/slab.h>
6
7
8 #include <linux/uio_driver.h>
9 #include <linux/io.h>
10
11 #define PCI_VENDOR_ID_HUMUSOFT          0x186c
12 #define PCI_DEVICE_ID_MF614             0x0614
13 #define PCI_SUBVENDOR_ID_HUMUSOFT       0x186c
14 #define PCI_SUBDEVICE_DEVICE            0x0000
15
16 #define STATUS_OFFSET                   0x10
17 #define STATUS_T5INTE                   (u32) (1 << 19)
18 #define STATUS_T5                       (u32) (1 << 3)
19 #define STATUS_CCINTE                   (u32) (1 << 18)
20 #define STATUS_CC                       (u32) (1 << 2)
21
22
23 static irqreturn_t mf614_irq_handler(int irq, struct uio_info *info)
24 {
25         void __iomem *status_reg = info->priv + STATUS_OFFSET;
26
27         if ((ioread16(status_reg) & STATUS_T5INTE) 
28                 && (ioread16(status_reg) & STATUS_T5))
29         {
30                 iowrite16(ioread16(status_reg) & ~STATUS_T5INTE, status_reg);
31                 return IRQ_HANDLED;
32         }
33
34         if ((ioread16(status_reg) & STATUS_CCINTE) 
35                 && (ioread16(status_reg) & STATUS_CC))
36         {
37                 iowrite16(ioread16(status_reg) & ~STATUS_CCINTE, status_reg);
38                 return IRQ_HANDLED;
39         }
40
41         return IRQ_NONE;
42 }
43
44 static int mf614_irqcontrol(struct uio_info *info, s32 irq_on)
45 {
46         void __iomem *status_reg = info->priv + STATUS_OFFSET;
47
48         if (irq_on == 0) { /* Disable interrupts */
49                 iowrite16(ioread16(status_reg) & ~STATUS_T5INTE, status_reg);
50                 iowrite16(ioread16(status_reg) & ~STATUS_CCINTE, status_reg);
51         } 
52         else if (irq_on == 1) {
53                 iowrite16(ioread16(status_reg) | STATUS_T5INTE, status_reg);
54                 iowrite16(ioread16(status_reg) | STATUS_CCINTE, status_reg);
55         }
56
57         return 0;
58 }
59
60 static int __devinit mf614_pci_probe(struct pci_dev *dev,
61                                      const struct pci_device_id *id)
62 {
63         struct uio_info *info;
64
65         info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
66         if (!info)
67                 return -ENOMEM;
68         
69         if (pci_enable_device(dev))
70                 goto out_free;
71
72         if (pci_request_regions(dev, "mf614"))
73                 goto out_disable;
74         
75         info->name = "MF614";
76         info->version = "0.0.1";
77         
78         info->port[0].name = "Board programming registers";
79         info->port[0].porttype = UIO_PORT_X86;
80         info->port[0].start = pci_resource_start(dev, 0);
81         if (!info->port[0].start)
82                 goto out_release;
83         info->port[0].size = pci_resource_len(dev, 0);
84
85         info->port[1].name = "OX9162 local configuration registers";    
86         info->port[1].porttype = UIO_PORT_X86;
87         info->port[1].start = pci_resource_start(dev, 2);
88         if (!info->port[1].start)
89                 goto out_release;
90         info->port[1].size = pci_resource_len(dev, 2);
91
92         info->priv = pci_iomap(dev, 2, 0);
93         if (!info->priv)
94                 goto out_release; 
95         
96         info->mem[0].name = "Board programming registers";
97         info->mem[0].addr = pci_resource_start(dev, 4);
98         if (!info->mem[0].addr)
99                 goto out_release;
100         info->mem[0].size = pci_resource_len(dev, 4);
101         info->mem[0].memtype = UIO_MEM_PHYS;
102         info->mem[0].internal_addr = pci_ioremap_bar(dev, 4);
103         if (!info->mem[0].internal_addr)
104                 goto out_release;
105         
106         info->irq = dev->irq;
107         info->irq_flags = IRQF_SHARED;
108         info->handler = mf614_irq_handler;
109
110         info->irqcontrol = mf614_irqcontrol;
111
112         if(uio_register_device(&dev->dev, info))
113                 goto out_unmap;
114
115         pci_set_drvdata(dev, info);
116
117         return 0;
118
119 out_unmap:
120         iounmap(info->mem[0].internal_addr);
121 out_release:
122         pci_release_regions(dev);
123 out_disable:
124         pci_disable_device(dev);
125 out_free:
126         kfree(info);
127         return -ENODEV;
128 }
129
130 static void mf614_pci_remove(struct pci_dev *dev)
131 {
132         struct uio_info *info = pci_get_drvdata(dev);
133         void __iomem *status_reg = info->priv + STATUS_OFFSET;
134         
135         /* Disable interrupts */
136         iowrite16(ioread16(status_reg) & ~STATUS_T5INTE, status_reg);   
137         iowrite16(ioread16(status_reg) & ~STATUS_CCINTE, status_reg);   
138         
139         uio_unregister_device(info);
140         pci_release_regions(dev);
141         pci_disable_device(dev);
142         pci_set_drvdata(dev, NULL);
143         iounmap(info->priv);
144         
145         kfree(info);
146 }
147
148 static struct pci_device_id mf614_pci_id[] __devinitdata = {
149         {
150                 .vendor = PCI_VENDOR_ID_HUMUSOFT,
151                 .device = PCI_DEVICE_ID_MF614,
152                 .subvendor = PCI_SUBVENDOR_ID_HUMUSOFT,
153                 .subdevice = PCI_SUBDEVICE_DEVICE,
154         },
155         { 0, }
156 };
157
158 static struct pci_driver mf614_pci_driver = {
159         .name = "mf614",
160         .id_table = mf614_pci_id,
161         .probe = mf614_pci_probe, 
162         .remove = mf614_pci_remove,
163 };
164
165 static int __init mf614_init_module(void)
166 {
167         return pci_register_driver(&mf614_pci_driver);
168 }
169
170 static void __exit mf614_exit_module(void)
171 {
172         pci_unregister_driver(&mf614_pci_driver);
173 }
174
175 module_init(mf614_init_module);
176 module_exit(mf614_exit_module);
177
178 MODULE_LICENSE("GPL v2");
179 MODULE_AUTHOR("Rostislav Lisovy <lisovy@gmail.com>");