16 You should have received a copy of the GNU General Public License along |
16 You should have received a copy of the GNU General Public License along |
17 with this program; if not, write to the Free Software Foundation, Inc., |
17 with this program; if not, write to the Free Software Foundation, Inc., |
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 */ |
19 */ |
20 |
20 |
21 #include <asm/dma.h> |
|
22 #include <linux/etherdevice.h> |
21 #include <linux/etherdevice.h> |
23 #include <linux/module.h> |
22 #include <linux/module.h> |
24 #include <linux/netdevice.h> |
23 #include <linux/netdevice.h> |
|
24 #include <linux/platform_device.h> |
25 #include <linux/version.h> |
25 #include <linux/version.h> |
26 #include "module.h" |
26 #include "module.h" |
27 #include "netdev.h" |
|
28 #include "update.h" |
|
29 |
27 |
30 MODULE_DESCRIPTION(DRV_DESCRIPTION); |
28 MODULE_DESCRIPTION(DRV_DESCRIPTION); |
31 MODULE_AUTHOR("Patrick Bruenn <p.bruenn@beckhoff.com>"); |
29 MODULE_AUTHOR("Patrick Bruenn <p.bruenn@beckhoff.com>"); |
32 MODULE_LICENSE("GPL"); |
30 MODULE_LICENSE("GPL"); |
33 MODULE_VERSION(DRV_VERSION); |
31 MODULE_VERSION(DRV_VERSION); |
34 |
32 |
35 static void ccat_bar_free(struct ccat_bar *bar) |
33 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,12,27)) |
36 { |
34 /* |
37 if (bar->ioaddr) { |
35 * Set both the DMA mask and the coherent DMA mask to the same thing. |
38 const struct ccat_bar tmp = *bar; |
36 * Note that we don't check the return value from dma_set_coherent_mask() |
39 memset(bar, 0, sizeof(*bar)); |
37 * as the DMA API guarantees that the coherent DMA mask can be set to |
40 iounmap(tmp.ioaddr); |
38 * the same or smaller than the streaming DMA mask. |
41 release_mem_region(tmp.start, tmp.len); |
39 */ |
42 } else { |
40 static inline int dma_set_mask_and_coherent(struct device *dev, u64 mask) |
43 pr_warn("%s(): %p was already done.\n", __FUNCTION__, bar); |
41 { |
44 } |
42 int rc = dma_set_mask(dev, mask); |
45 } |
43 if (rc == 0) |
|
44 dma_set_coherent_mask(dev, mask); |
|
45 return rc; |
|
46 } |
|
47 #endif |
46 |
48 |
47 /** |
49 /** |
48 * ccat_bar_init() - Initialize a CCAT pci bar |
50 * configure the drivers capabilities here |
49 * @bar object which should be initialized |
|
50 * @index 0 and 2 are valid for CCAT, meaning pci bar0 or pci bar2 |
|
51 * @pdev the pci device as which the CCAT was recognized before |
|
52 * |
|
53 * Reading PCI config space; request and map memory region. |
|
54 */ |
51 */ |
55 static int ccat_bar_init(struct ccat_bar *bar, size_t index, |
52 static const struct ccat_driver *const drivers[] = { |
56 struct pci_dev *pdev) |
53 #ifdef CONFIG_PCI |
57 { |
54 ð_dma_driver, /* load Ethernet MAC/EtherCAT Master driver with DMA support from netdev.c */ |
58 struct resource *res; |
55 #endif |
59 |
56 ð_eim_driver, /* load Ethernet MAC/EtherCAT Master driver without DMA support from */ |
60 bar->start = pci_resource_start(pdev, index); |
57 &gpio_driver, /* load GPIO driver from gpio.c */ |
61 bar->end = pci_resource_end(pdev, index); |
58 &sram_driver, /* load SRAM driver from sram.c */ |
62 bar->len = pci_resource_len(pdev, index); |
59 &update_driver, /* load Update driver from update.c */ |
63 bar->flags = pci_resource_flags(pdev, index); |
60 }; |
64 if (!(IORESOURCE_MEM & bar->flags)) { |
61 |
65 pr_info("bar%llu is no mem_region -> abort.\n", (u64) index); |
62 static int __init ccat_class_init(struct ccat_class *base) |
66 return -EIO; |
63 { |
67 } |
64 if (1 == atomic_inc_return(&base->instances)) { |
68 |
65 if (alloc_chrdev_region |
69 res = request_mem_region(bar->start, bar->len, KBUILD_MODNAME); |
66 (&base->dev, 0, base->count, KBUILD_MODNAME)) { |
70 if (!res) { |
67 pr_warn("alloc_chrdev_region() for '%s' failed\n", |
71 pr_info("allocate mem_region failed.\n"); |
68 base->name); |
72 return -EIO; |
69 return -1; |
73 } |
70 } |
74 pr_debug("bar%llu at [%lx,%lx] len=%lu res: %p.\n", (u64) index, |
71 |
75 bar->start, bar->end, bar->len, res); |
72 base->class = class_create(THIS_MODULE, base->name); |
76 |
73 if (!base->class) { |
77 bar->ioaddr = ioremap(bar->start, bar->len); |
74 pr_warn("Create device class '%s' failed\n", |
78 if (!bar->ioaddr) { |
75 base->name); |
79 pr_info("bar%llu ioremap failed.\n", (u64) index); |
76 unregister_chrdev_region(base->dev, base->count); |
80 release_mem_region(bar->start, bar->len); |
77 return -1; |
81 return -EIO; |
78 } |
82 } |
79 } |
83 pr_debug("bar%llu I/O mem mapped to %p.\n", (u64) index, bar->ioaddr); |
80 return 0; |
84 return 0; |
81 } |
85 } |
82 |
86 |
83 static void ccat_class_exit(struct ccat_class *base) |
87 void ccat_dma_free(struct ccat_dma *const dma) |
84 { |
88 { |
85 if (!atomic_dec_return(&base->instances)) { |
89 const struct ccat_dma tmp = *dma; |
86 class_destroy(base->class); |
90 |
87 unregister_chrdev_region(base->dev, base->count); |
91 free_dma(dma->channel); |
88 } |
92 memset(dma, 0, sizeof(*dma)); |
89 } |
93 dma_free_coherent(tmp.dev, tmp.size, tmp.virt, tmp.phys); |
90 |
94 } |
91 static void free_ccat_cdev(struct ccat_cdev *ccdev) |
95 |
92 { |
96 /** |
93 ccat_class_exit(ccdev->class); |
97 * ccat_dma_init() - Initialize CCAT and host memory for DMA transfer |
94 ccdev->dev = 0; |
98 * @dma object for management data which will be initialized |
95 } |
99 * @channel number of the DMA channel |
96 |
100 * @ioaddr of the pci bar2 configspace used to calculate the address of the pci dma configuration |
97 static struct ccat_cdev *alloc_ccat_cdev(struct ccat_class *base) |
101 * @dev which should be configured for DMA |
98 { |
102 */ |
99 int i = 0; |
103 int ccat_dma_init(struct ccat_dma *const dma, size_t channel, |
100 |
104 void __iomem * const ioaddr, struct device *const dev) |
101 ccat_class_init(base); |
105 { |
102 for (i = 0; i < base->count; ++i) { |
106 void *frame; |
103 if (base->devices[i].dev == 0) { |
107 u64 addr; |
104 base->devices[i].dev = MKDEV(MAJOR(base->dev), i); |
108 u32 translateAddr; |
105 return &base->devices[i]; |
109 u32 memTranslate; |
106 } |
110 u32 memSize; |
107 } |
111 u32 data = 0xffffffff; |
108 pr_warn("exceeding max. number of '%s' devices (%d)\n", |
112 u32 offset = (sizeof(u64) * channel) + 0x1000; |
109 base->class->name, base->count); |
113 |
110 atomic_dec_return(&base->instances); |
114 dma->channel = channel; |
111 return NULL; |
115 dma->dev = dev; |
112 } |
116 |
113 |
117 /* calculate size and alignments */ |
114 static int ccat_cdev_init(struct cdev *cdev, dev_t dev, struct class *class, |
118 iowrite32(data, ioaddr + offset); |
115 struct file_operations *fops) |
119 wmb(); |
116 { |
120 data = ioread32(ioaddr + offset); |
117 if (!device_create |
121 memTranslate = data & 0xfffffffc; |
118 (class, NULL, dev, NULL, "%s%d", class->name, MINOR(dev))) { |
122 memSize = (~memTranslate) + 1; |
119 pr_warn("device_create() failed\n"); |
123 dma->size = 2 * memSize - PAGE_SIZE; |
|
124 dma->virt = dma_zalloc_coherent(dev, dma->size, &dma->phys, GFP_KERNEL); |
|
125 if (!dma->virt || !dma->phys) { |
|
126 pr_info("init DMA%llu memory failed.\n", (u64) channel); |
|
127 return -1; |
120 return -1; |
128 } |
121 } |
129 |
122 |
130 if (request_dma(channel, KBUILD_MODNAME)) { |
123 cdev_init(cdev, fops); |
131 pr_info("request dma channel %llu failed\n", (u64) channel); |
124 cdev->owner = fops->owner; |
132 ccat_dma_free(dma); |
125 if (cdev_add(cdev, dev, 1)) { |
|
126 pr_warn("add update device failed\n"); |
|
127 device_destroy(class, dev); |
133 return -1; |
128 return -1; |
134 } |
129 } |
135 |
130 |
136 translateAddr = (dma->phys + memSize - PAGE_SIZE) & memTranslate; |
131 pr_info("registered %s%d.\n", class->name, MINOR(dev)); |
137 addr = translateAddr; |
132 return 0; |
138 memcpy_toio(ioaddr + offset, &addr, sizeof(addr)); |
133 } |
139 frame = dma->virt + translateAddr - dma->phys; |
134 |
140 pr_debug |
135 int ccat_cdev_open(struct inode *const i, struct file *const f) |
141 ("DMA%llu mem initialized\n virt: 0x%p\n phys: 0x%llx\n translated: 0x%llx\n pci addr: 0x%08x%x\n memTranslate: 0x%x\n size: %llu bytes.\n", |
136 { |
142 (u64) channel, dma->virt, (u64) (dma->phys), addr, |
137 struct ccat_cdev *ccdev = |
143 ioread32(ioaddr + offset + 4), ioread32(ioaddr + offset), |
138 container_of(i->i_cdev, struct ccat_cdev, cdev); |
144 memTranslate, (u64) dma->size); |
139 struct cdev_buffer *buf; |
145 return 0; |
140 |
|
141 if (!atomic_dec_and_test(&ccdev->in_use)) { |
|
142 atomic_inc(&ccdev->in_use); |
|
143 return -EBUSY; |
|
144 } |
|
145 |
|
146 buf = kzalloc(sizeof(*buf) + ccdev->iosize, GFP_KERNEL); |
|
147 if (!buf) { |
|
148 atomic_inc(&ccdev->in_use); |
|
149 return -ENOMEM; |
|
150 } |
|
151 |
|
152 buf->ccdev = ccdev; |
|
153 f->private_data = buf; |
|
154 return 0; |
|
155 } |
|
156 |
|
157 int ccat_cdev_probe(struct ccat_function *func, struct ccat_class *cdev_class, |
|
158 size_t iosize) |
|
159 { |
|
160 struct ccat_cdev *const ccdev = alloc_ccat_cdev(cdev_class); |
|
161 if (!ccdev) { |
|
162 return -ENOMEM; |
|
163 } |
|
164 |
|
165 ccdev->ioaddr = func->ccat->bar_0 + func->info.addr; |
|
166 ccdev->iosize = iosize; |
|
167 atomic_set(&ccdev->in_use, 1); |
|
168 |
|
169 if (ccat_cdev_init |
|
170 (&ccdev->cdev, ccdev->dev, cdev_class->class, &cdev_class->fops)) { |
|
171 pr_warn("ccat_cdev_probe() failed\n"); |
|
172 free_ccat_cdev(ccdev); |
|
173 return -1; |
|
174 } |
|
175 ccdev->class = cdev_class; |
|
176 func->private_data = ccdev; |
|
177 return 0; |
|
178 } |
|
179 |
|
180 int ccat_cdev_release(struct inode *const i, struct file *const f) |
|
181 { |
|
182 const struct cdev_buffer *const buf = f->private_data; |
|
183 struct ccat_cdev *const ccdev = buf->ccdev; |
|
184 |
|
185 kfree(f->private_data); |
|
186 atomic_inc(&ccdev->in_use); |
|
187 return 0; |
|
188 } |
|
189 |
|
190 void ccat_cdev_remove(struct ccat_function *func) |
|
191 { |
|
192 struct ccat_cdev *const ccdev = func->private_data; |
|
193 |
|
194 cdev_del(&ccdev->cdev); |
|
195 device_destroy(ccdev->class->class, ccdev->dev); |
|
196 free_ccat_cdev(ccdev); |
|
197 } |
|
198 |
|
199 static const struct ccat_driver *ccat_function_connect(struct ccat_function |
|
200 *const func) |
|
201 { |
|
202 int i; |
|
203 |
|
204 for (i = 0; i < ARRAY_SIZE(drivers); ++i) { |
|
205 if (func->info.type == drivers[i]->type) { |
|
206 return drivers[i]->probe(func) ? NULL : drivers[i]; |
|
207 } |
|
208 } |
|
209 return NULL; |
146 } |
210 } |
147 |
211 |
148 /** |
212 /** |
149 * Initialize all available CCAT functions. |
213 * Initialize all available CCAT functions. |
150 * |
214 * |
151 * Return: count of failed functions |
215 * Return: count of failed functions |
152 */ |
216 */ |
153 static int ccat_functions_init(struct ccat_device *const ccatdev) |
217 static int ccat_functions_init(struct ccat_device *const ccatdev) |
154 { |
218 { |
155 static const size_t block_size = sizeof(struct ccat_info_block); |
219 static const size_t block_size = sizeof(struct ccat_info_block); |
156 void __iomem *addr = ccatdev->bar[0].ioaddr; /** first block is the CCAT information block entry */ |
220 struct ccat_function *next = kzalloc(sizeof(*next), GFP_KERNEL); |
|
221 void __iomem *addr = ccatdev->bar_0; /** first block is the CCAT information block entry */ |
157 const u8 num_func = ioread8(addr + 4); /** number of CCAT function blocks is at offset 0x4 */ |
222 const u8 num_func = ioread8(addr + 4); /** number of CCAT function blocks is at offset 0x4 */ |
158 const void __iomem *end = addr + (block_size * num_func); |
223 const void __iomem *end = addr + (block_size * num_func); |
159 int status = 0; /** count init function failures */ |
224 |
160 |
225 INIT_LIST_HEAD(&ccatdev->functions); |
161 while (addr < end) { |
226 for (; addr < end && next; addr += block_size) { |
162 const u8 type = ioread16(addr); |
227 memcpy_fromio(&next->info, addr, sizeof(next->info)); |
163 switch (type) { |
228 if (CCATINFO_NOTUSED != next->info.type) { |
164 case CCATINFO_NOTUSED: |
229 next->ccat = ccatdev; |
165 break; |
230 next->drv = ccat_function_connect(next); |
166 case CCATINFO_EPCS_PROM: |
231 if (next->drv) { |
167 pr_info("Found: CCAT update(EPCS_PROM) -> init()\n"); |
232 list_add(&next->list, &ccatdev->functions); |
168 ccatdev->update = ccat_update_init(ccatdev, addr); |
233 next = kzalloc(sizeof(*next), GFP_KERNEL); |
169 status += (NULL == ccatdev->update); |
234 } |
170 break; |
235 } |
171 case CCATINFO_ETHERCAT_MASTER_DMA: |
236 } |
172 pr_info("Found: ETHERCAT_MASTER_DMA -> init()\n"); |
237 kfree(next); |
173 ccatdev->ethdev = ccat_eth_init(ccatdev, addr); |
238 return list_empty(&ccatdev->functions); |
174 status += (NULL == ccatdev->ethdev); |
|
175 break; |
|
176 default: |
|
177 pr_info("Found: 0x%04x not supported\n", type); |
|
178 break; |
|
179 } |
|
180 addr += block_size; |
|
181 } |
|
182 return status; |
|
183 } |
239 } |
184 |
240 |
185 /** |
241 /** |
186 * Destroy all previously initialized CCAT functions |
242 * Destroy all previously initialized CCAT functions |
187 */ |
243 */ |
188 static void ccat_functions_remove(struct ccat_device *const ccatdev) |
244 static void ccat_functions_remove(struct ccat_device *const dev) |
189 { |
245 { |
190 if (!ccatdev->ethdev) { |
246 struct ccat_function *func; |
191 pr_warn("%s(): 'ethdev' was not initialized.\n", __FUNCTION__); |
247 struct ccat_function *tmp; |
192 } else { |
248 list_for_each_entry_safe(func, tmp, &dev->functions, list) { |
193 struct ccat_eth_priv *const ethdev = ccatdev->ethdev; |
249 if (func->drv) { |
194 ccatdev->ethdev = NULL; |
250 func->drv->remove(func); |
195 ccat_eth_remove(ethdev); |
251 func->drv = NULL; |
196 } |
252 } |
197 if (!ccatdev->update) { |
253 list_del(&func->list); |
198 pr_warn("%s(): 'update' was not initialized.\n", __FUNCTION__); |
254 kfree(func); |
199 } else { |
255 } |
200 struct ccat_update *const update = ccatdev->update; |
256 } |
201 ccatdev->update = NULL; |
257 |
202 ccat_update_remove(update); |
258 #ifdef CONFIG_PCI |
203 } |
259 static int ccat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
204 } |
260 { |
205 |
261 struct ccat_device *ccatdev; |
206 static int ccat_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
262 u8 rev; |
207 { |
|
208 int status; |
263 int status; |
209 u8 revision; |
264 |
210 struct ccat_device *ccatdev = kmalloc(sizeof(*ccatdev), GFP_KERNEL); |
265 ccatdev = devm_kzalloc(&pdev->dev, sizeof(*ccatdev), GFP_KERNEL); |
211 |
|
212 if (!ccatdev) { |
266 if (!ccatdev) { |
213 pr_err("%s() out of memory.\n", __FUNCTION__); |
267 pr_err("%s() out of memory.\n", __FUNCTION__); |
214 return -ENOMEM; |
268 return -ENOMEM; |
215 } |
269 } |
216 memset(ccatdev, 0, sizeof(*ccatdev)); |
|
217 ccatdev->pdev = pdev; |
270 ccatdev->pdev = pdev; |
218 pci_set_drvdata(pdev, ccatdev); |
271 pci_set_drvdata(pdev, ccatdev); |
219 |
272 |
220 status = pci_enable_device_mem(pdev); |
273 status = pci_enable_device_mem(pdev); |
221 if (status) { |
274 if (status) { |
222 pr_info("enable %s failed: %d\n", pdev->dev.kobj.name, status); |
275 pr_err("enable %s failed: %d\n", pdev->dev.kobj.name, status); |
223 return status; |
276 return status; |
224 } |
277 } |
225 |
278 |
226 status = pci_read_config_byte(pdev, PCI_REVISION_ID, &revision); |
279 status = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); |
227 if (status) { |
280 if (status) { |
228 pr_warn("read CCAT pci revision failed with %d\n", status); |
281 pr_err("read CCAT pci revision failed with %d\n", status); |
229 return status; |
282 goto disable_device; |
230 } |
283 } |
231 |
284 |
232 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) |
285 status = pci_request_regions(pdev, KBUILD_MODNAME); |
233 if (!dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64))) { |
286 if (status) { |
234 pr_debug("64 bit DMA supported, pci rev: %u\n", revision); |
287 pr_err("allocate mem_regions failed.\n"); |
235 } else if (!dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) { |
288 goto disable_device; |
236 pr_debug("32 bit DMA supported, pci rev: %u\n", revision); |
289 } |
|
290 |
|
291 status = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); |
|
292 if (status) { |
|
293 status = |
|
294 dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); |
|
295 if (status) { |
|
296 pr_err("No suitable DMA available, pci rev: %u\n", rev); |
|
297 goto release_regions; |
|
298 } |
|
299 pr_debug("32 bit DMA supported, pci rev: %u\n", rev); |
237 } else { |
300 } else { |
238 pr_warn("No suitable DMA available, pci rev: %u\n", revision); |
301 pr_debug("64 bit DMA supported, pci rev: %u\n", rev); |
239 } |
302 } |
240 #else |
303 |
241 if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { |
304 ccatdev->bar_0 = pci_iomap(pdev, 0, 0); |
242 pr_debug("64 bit DMA supported, pci rev: %u\n", revision); |
305 if (!ccatdev->bar_0) { |
243 } else if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) { |
306 pr_err("initialization of bar0 failed.\n"); |
244 pr_debug("32 bit DMA supported, pci rev: %u\n", revision); |
307 status = -EIO; |
245 } else { |
308 goto release_regions; |
246 pr_warn("No suitable DMA available, pci rev: %u\n", revision); |
309 } |
247 } |
310 |
248 #endif |
311 ccatdev->bar_2 = pci_iomap(pdev, 2, 0); |
249 |
312 if (!ccatdev->bar_2) { |
250 if (ccat_bar_init(&ccatdev->bar[0], 0, pdev)) { |
313 pr_warn("initialization of optional bar2 failed.\n"); |
251 pr_warn("initialization of bar0 failed.\n"); |
|
252 return -EIO; |
|
253 } |
|
254 |
|
255 if (ccat_bar_init(&ccatdev->bar[2], 2, pdev)) { |
|
256 pr_warn("initialization of bar2 failed.\n"); |
|
257 return -EIO; |
|
258 } |
314 } |
259 |
315 |
260 pci_set_master(pdev); |
316 pci_set_master(pdev); |
261 if (ccat_functions_init(ccatdev)) { |
317 if (ccat_functions_init(ccatdev)) { |
262 pr_warn("some functions couldn't be initialized\n"); |
318 pr_warn("some functions couldn't be initialized\n"); |
263 } |
319 } |
264 return 0; |
320 return 0; |
265 } |
321 |
266 |
322 release_regions: |
267 static void ccat_remove(struct pci_dev *pdev) |
323 pci_release_regions(pdev); |
|
324 disable_device: |
|
325 pci_disable_device(pdev); |
|
326 return status; |
|
327 } |
|
328 |
|
329 static void ccat_pci_remove(struct pci_dev *pdev) |
268 { |
330 { |
269 struct ccat_device *ccatdev = pci_get_drvdata(pdev); |
331 struct ccat_device *ccatdev = pci_get_drvdata(pdev); |
270 |
332 |
271 if (ccatdev) { |
333 if (ccatdev) { |
272 ccat_functions_remove(ccatdev); |
334 ccat_functions_remove(ccatdev); |
273 ccat_bar_free(&ccatdev->bar[2]); |
335 if (ccatdev->bar_2) |
274 ccat_bar_free(&ccatdev->bar[0]); |
336 pci_iounmap(pdev, ccatdev->bar_2); |
|
337 pci_iounmap(pdev, ccatdev->bar_0); |
|
338 pci_release_regions(pdev); |
275 pci_disable_device(pdev); |
339 pci_disable_device(pdev); |
276 pci_set_drvdata(pdev, NULL); |
340 } |
277 kfree(ccatdev); |
|
278 } |
|
279 pr_debug("%s() done.\n", __FUNCTION__); |
|
280 } |
341 } |
281 |
342 |
282 #define PCI_DEVICE_ID_BECKHOFF_CCAT 0x5000 |
343 #define PCI_DEVICE_ID_BECKHOFF_CCAT 0x5000 |
283 #define PCI_VENDOR_ID_BECKHOFF 0x15EC |
344 #define PCI_VENDOR_ID_BECKHOFF 0x15EC |
284 |
345 |
285 static const struct pci_device_id pci_ids[] = { |
346 static const struct pci_device_id pci_ids[] = { |
286 {PCI_DEVICE(PCI_VENDOR_ID_BECKHOFF, PCI_DEVICE_ID_BECKHOFF_CCAT)}, |
347 {PCI_DEVICE(PCI_VENDOR_ID_BECKHOFF, PCI_DEVICE_ID_BECKHOFF_CCAT)}, |
287 {0,}, |
348 {0,}, |
288 }; |
349 }; |
289 |
350 |
290 #if 0 /* prevent auto-loading */ |
|
291 MODULE_DEVICE_TABLE(pci, pci_ids); |
351 MODULE_DEVICE_TABLE(pci, pci_ids); |
292 #endif |
352 |
293 |
353 static struct pci_driver ccat_pci_driver = { |
294 static struct pci_driver pci_driver = { |
|
295 .name = KBUILD_MODNAME, |
354 .name = KBUILD_MODNAME, |
296 .id_table = pci_ids, |
355 .id_table = pci_ids, |
297 .probe = ccat_probe, |
356 .probe = ccat_pci_probe, |
298 .remove = ccat_remove, |
357 .remove = ccat_pci_remove, |
299 }; |
358 }; |
300 |
359 |
301 static void __exit ccat_exit_module(void) |
360 module_pci_driver(ccat_pci_driver); |
302 { |
361 |
303 pci_unregister_driver(&pci_driver); |
362 #else /* #ifdef CONFIG_PCI */ |
304 } |
363 |
305 |
364 static int ccat_eim_probe(struct platform_device *pdev) |
306 static int __init ccat_init_module(void) |
365 { |
307 { |
366 struct ccat_device *ccatdev; |
308 pr_info("%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); |
367 |
309 return pci_register_driver(&pci_driver); |
368 ccatdev = devm_kzalloc(&pdev->dev, sizeof(*ccatdev), GFP_KERNEL); |
310 } |
369 if (!ccatdev) { |
311 |
370 pr_err("%s() out of memory.\n", __FUNCTION__); |
312 module_exit(ccat_exit_module); |
371 return -ENOMEM; |
313 module_init(ccat_init_module); |
372 } |
|
373 ccatdev->pdev = pdev; |
|
374 platform_set_drvdata(pdev, ccatdev); |
|
375 |
|
376 if (!request_mem_region(0xf0000000, 0x02000000, pdev->name)) { |
|
377 pr_warn("request mem region failed.\n"); |
|
378 return -EIO; |
|
379 } |
|
380 |
|
381 if (!(ccatdev->bar_0 = ioremap(0xf0000000, 0x02000000))) { |
|
382 pr_warn("initialization of bar0 failed.\n"); |
|
383 return -EIO; |
|
384 } |
|
385 |
|
386 ccatdev->bar_2 = NULL; |
|
387 |
|
388 if (ccat_functions_init(ccatdev)) { |
|
389 pr_warn("some functions couldn't be initialized\n"); |
|
390 } |
|
391 return 0; |
|
392 } |
|
393 |
|
394 static int ccat_eim_remove(struct platform_device *pdev) |
|
395 { |
|
396 struct ccat_device *ccatdev = platform_get_drvdata(pdev); |
|
397 |
|
398 if (ccatdev) { |
|
399 ccat_functions_remove(ccatdev); |
|
400 iounmap(ccatdev->bar_0); |
|
401 release_mem_region(0xf0000000, 0x02000000); |
|
402 } |
|
403 return 0; |
|
404 } |
|
405 |
|
406 static const struct of_device_id bhf_eim_ccat_ids[] = { |
|
407 {.compatible = "bhf,emi-ccat",}, |
|
408 {} |
|
409 }; |
|
410 |
|
411 MODULE_DEVICE_TABLE(of, bhf_eim_ccat_ids); |
|
412 |
|
413 static struct platform_driver ccat_eim_driver = { |
|
414 .driver = { |
|
415 .name = KBUILD_MODNAME, |
|
416 .of_match_table = bhf_eim_ccat_ids, |
|
417 }, |
|
418 .probe = ccat_eim_probe, |
|
419 .remove = ccat_eim_remove, |
|
420 }; |
|
421 |
|
422 module_platform_driver(ccat_eim_driver); |
|
423 #endif /* #ifdef CONFIG_PCI */ |