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