]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/staging/crystalhd/crystalhd_lnx.c
Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
[mv-sheeva.git] / drivers / staging / crystalhd / crystalhd_lnx.c
1 /***************************************************************************
2   BCM70010 Linux driver
3   Copyright (c) 2005-2009, Broadcom Corporation.
4
5   This driver is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation, version 2 of the License.
8
9   This driver is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU General Public License for more details.
13
14   You should have received a copy of the GNU General Public License
15   along with this driver.  If not, see <http://www.gnu.org/licenses/>.
16 ***************************************************************************/
17
18 #include <linux/version.h>
19
20 #include "crystalhd_lnx.h"
21
22 static struct class *crystalhd_class;
23
24 static struct crystalhd_adp *g_adp_info;
25
26 static irqreturn_t chd_dec_isr(int irq, void *arg)
27 {
28         struct crystalhd_adp *adp = (struct crystalhd_adp *) arg;
29         int rc = 0;
30         if (adp)
31                 rc = crystalhd_cmd_interrupt(&adp->cmds);
32
33         return IRQ_RETVAL(rc);
34 }
35
36 static int chd_dec_enable_int(struct crystalhd_adp *adp)
37 {
38         int rc = 0;
39
40         if (!adp || !adp->pdev) {
41                 BCMLOG_ERR("Invalid arg!!\n");
42                 return -EINVAL;
43         }
44
45         if (adp->pdev->msi_enabled)
46                 adp->msi = 1;
47         else
48                 adp->msi = pci_enable_msi(adp->pdev);
49
50         rc = request_irq(adp->pdev->irq, chd_dec_isr, IRQF_SHARED,
51                          adp->name, (void *)adp);
52         if (rc) {
53                 BCMLOG_ERR("Interrupt request failed.. \n");
54                 pci_disable_msi(adp->pdev);
55         }
56
57         return rc;
58 }
59
60 static int chd_dec_disable_int(struct crystalhd_adp *adp)
61 {
62         if (!adp || !adp->pdev) {
63                 BCMLOG_ERR("Invalid arg!!\n");
64                 return -EINVAL;
65         }
66
67         free_irq(adp->pdev->irq, adp);
68
69         if (adp->msi)
70                 pci_disable_msi(adp->pdev);
71
72         return 0;
73 }
74
75 crystalhd_ioctl_data *chd_dec_alloc_iodata(struct crystalhd_adp *adp, bool isr)
76 {
77         unsigned long flags = 0;
78         crystalhd_ioctl_data *temp;
79
80         if (!adp)
81                 return NULL;
82
83         spin_lock_irqsave(&adp->lock, flags);
84
85         temp = adp->idata_free_head;
86         if (temp) {
87                 adp->idata_free_head = adp->idata_free_head->next;
88                 memset(temp, 0, sizeof(*temp));
89         }
90
91         spin_unlock_irqrestore(&adp->lock, flags);
92         return temp;
93 }
94
95 void chd_dec_free_iodata(struct crystalhd_adp *adp, crystalhd_ioctl_data *iodata,
96                          bool isr)
97 {
98         unsigned long flags = 0;
99
100         if (!adp || !iodata)
101                 return;
102
103         spin_lock_irqsave(&adp->lock, flags);
104         iodata->next = adp->idata_free_head;
105         adp->idata_free_head = iodata;
106         spin_unlock_irqrestore(&adp->lock, flags);
107 }
108
109 static inline int crystalhd_user_data(unsigned long ud, void *dr, int size, int set)
110 {
111         int rc;
112
113         if (!ud || !dr) {
114                 BCMLOG_ERR("Invalid arg \n");
115                 return -EINVAL;
116         }
117
118         if (set)
119                 rc = copy_to_user((void *)ud, dr, size);
120         else
121                 rc = copy_from_user(dr, (void *)ud, size);
122
123         if (rc) {
124                 BCMLOG_ERR("Invalid args for command \n");
125                 rc = -EFAULT;
126         }
127
128         return rc;
129 }
130
131 static int chd_dec_fetch_cdata(struct crystalhd_adp *adp, crystalhd_ioctl_data *io,
132                                uint32_t m_sz, unsigned long ua)
133 {
134         unsigned long ua_off;
135         int rc = 0;
136
137         if (!adp || !io || !ua || !m_sz) {
138                 BCMLOG_ERR("Invalid Arg!!\n");
139                 return -EINVAL;
140         }
141
142         io->add_cdata = vmalloc(m_sz);
143         if (!io->add_cdata) {
144                 BCMLOG_ERR("kalloc fail for sz:%x\n", m_sz);
145                 return -ENOMEM;
146         }
147
148         io->add_cdata_sz = m_sz;
149         ua_off = ua + sizeof(io->udata);
150         rc = crystalhd_user_data(ua_off, io->add_cdata, io->add_cdata_sz, 0);
151         if (rc) {
152                 BCMLOG_ERR("failed to pull add_cdata sz:%x ua_off:%x\n",
153                            io->add_cdata_sz, (unsigned int)ua_off);
154                 if (io->add_cdata) {
155                         kfree(io->add_cdata);
156                         io->add_cdata = NULL;
157                 }
158                 return -ENODATA;
159         }
160
161         return rc;
162 }
163
164 static int chd_dec_release_cdata(struct crystalhd_adp *adp,
165                                  crystalhd_ioctl_data *io, unsigned long ua)
166 {
167         unsigned long ua_off;
168         int rc;
169
170         if (!adp || !io || !ua) {
171                 BCMLOG_ERR("Invalid Arg!!\n");
172                 return -EINVAL;
173         }
174
175         if (io->cmd != BCM_IOC_FW_DOWNLOAD) {
176                 ua_off = ua + sizeof(io->udata);
177                 rc = crystalhd_user_data(ua_off, io->add_cdata,
178                                         io->add_cdata_sz, 1);
179                 if (rc) {
180                         BCMLOG_ERR("failed to push add_cdata sz:%x ua_off:%x\n",
181                                    io->add_cdata_sz, (unsigned int)ua_off);
182                         return -ENODATA;
183                 }
184         }
185
186         if (io->add_cdata) {
187                 vfree(io->add_cdata);
188                 io->add_cdata = NULL;
189         }
190
191         return 0;
192 }
193
194 static int chd_dec_proc_user_data(struct crystalhd_adp *adp,
195                                   crystalhd_ioctl_data *io,
196                                   unsigned long ua, int set)
197 {
198         int rc;
199         uint32_t m_sz = 0;
200
201         if (!adp || !io || !ua) {
202                 BCMLOG_ERR("Invalid Arg!!\n");
203                 return -EINVAL;
204         }
205
206         rc = crystalhd_user_data(ua, &io->udata, sizeof(io->udata), set);
207         if (rc) {
208                 BCMLOG_ERR("failed to %s iodata \n", (set ? "set" : "get"));
209                 return rc;
210         }
211
212         switch (io->cmd) {
213         case BCM_IOC_MEM_RD:
214         case BCM_IOC_MEM_WR:
215         case BCM_IOC_FW_DOWNLOAD:
216                 m_sz = io->udata.u.devMem.NumDwords * 4;
217                 if (set)
218                         rc = chd_dec_release_cdata(adp, io, ua);
219                 else
220                         rc = chd_dec_fetch_cdata(adp, io, m_sz, ua);
221                 break;
222         default:
223                 break;
224         }
225
226         return rc;
227 }
228
229 static int chd_dec_api_cmd(struct crystalhd_adp *adp, unsigned long ua,
230                            uint32_t uid, uint32_t cmd, crystalhd_cmd_proc func)
231 {
232         int rc;
233         crystalhd_ioctl_data *temp;
234         BC_STATUS sts = BC_STS_SUCCESS;
235
236         temp = chd_dec_alloc_iodata(adp, 0);
237         if (!temp) {
238                 BCMLOG_ERR("Failed to get iodata..\n");
239                 return -EINVAL;
240         }
241
242         temp->u_id = uid;
243         temp->cmd  = cmd;
244
245         rc = chd_dec_proc_user_data(adp, temp, ua, 0);
246         if (!rc) {
247                 sts = func(&adp->cmds, temp);
248                 if (sts == BC_STS_PENDING)
249                         sts = BC_STS_NOT_IMPL;
250                 temp->udata.RetSts = sts;
251                 rc = chd_dec_proc_user_data(adp, temp, ua, 1);
252         }
253
254         if (temp) {
255                 chd_dec_free_iodata(adp, temp, 0);
256                 temp = NULL;
257         }
258
259         return rc;
260 }
261
262 /* API interfaces */
263 static int chd_dec_ioctl(struct inode *in, struct file *fd,
264                          unsigned int cmd, unsigned long ua)
265 {
266         struct crystalhd_adp *adp = chd_get_adp();
267         crystalhd_cmd_proc cproc;
268         struct crystalhd_user *uc;
269
270         if (!adp || !fd) {
271                 BCMLOG_ERR("Invalid adp\n");
272                 return -EINVAL;
273         }
274
275         uc = (struct crystalhd_user *)fd->private_data;
276         if (!uc) {
277                 BCMLOG_ERR("Failed to get uc\n");
278                 return -ENODATA;
279         }
280
281         cproc = crystalhd_get_cmd_proc(&adp->cmds, cmd, uc);
282         if (!cproc) {
283                 BCMLOG_ERR("Unhandled command: %d\n", cmd);
284                 return -EINVAL;
285         }
286
287         return chd_dec_api_cmd(adp, ua, uc->uid, cmd, cproc);
288 }
289
290 static int chd_dec_open(struct inode *in, struct file *fd)
291 {
292         struct crystalhd_adp *adp = chd_get_adp();
293         int rc = 0;
294         BC_STATUS sts = BC_STS_SUCCESS;
295         struct crystalhd_user *uc = NULL;
296
297         BCMLOG_ENTER;
298         if (!adp) {
299                 BCMLOG_ERR("Invalid adp\n");
300                 return -EINVAL;
301         }
302
303         if (adp->cfg_users >= BC_LINK_MAX_OPENS) {
304                 BCMLOG(BCMLOG_INFO, "Already in use.%d\n", adp->cfg_users);
305                 return -EBUSY;
306         }
307
308         sts = crystalhd_user_open(&adp->cmds, &uc);
309         if (sts != BC_STS_SUCCESS) {
310                 BCMLOG_ERR("cmd_user_open - %d \n", sts);
311                 rc = -EBUSY;
312         }
313
314         adp->cfg_users++;
315
316         fd->private_data = uc;
317
318         return rc;
319 }
320
321 static int chd_dec_close(struct inode *in, struct file *fd)
322 {
323         struct crystalhd_adp *adp = chd_get_adp();
324         struct crystalhd_user *uc;
325
326         BCMLOG_ENTER;
327         if (!adp) {
328                 BCMLOG_ERR("Invalid adp \n");
329                 return -EINVAL;
330         }
331
332         uc = (struct crystalhd_user *)fd->private_data;
333         if (!uc) {
334                 BCMLOG_ERR("Failed to get uc\n");
335                 return -ENODATA;
336         }
337
338         crystalhd_user_close(&adp->cmds, uc);
339
340         adp->cfg_users--;
341
342         return 0;
343 }
344
345 static const struct file_operations chd_dec_fops = {
346         .owner   = THIS_MODULE,
347         .ioctl   = chd_dec_ioctl,
348         .open    = chd_dec_open,
349         .release = chd_dec_close,
350 };
351
352 static int __devinit chd_dec_init_chdev(struct crystalhd_adp *adp)
353 {
354         crystalhd_ioctl_data *temp;
355         struct device *dev;
356         int rc = -ENODEV, i = 0;
357
358         if (!adp)
359                 goto fail;
360
361         adp->chd_dec_major = register_chrdev(0, CRYSTALHD_API_NAME,
362                                              &chd_dec_fops);
363         if (adp->chd_dec_major < 0) {
364                 BCMLOG_ERR("Failed to create config dev\n");
365                 rc = adp->chd_dec_major;
366                 goto fail;
367         }
368
369         /* register crystalhd class */
370         crystalhd_class = class_create(THIS_MODULE, "crystalhd");
371         if (IS_ERR(crystalhd_class)) {
372                 BCMLOG_ERR("failed to create class\n");
373                 goto fail;
374         }
375
376         dev = device_create(crystalhd_class, NULL, MKDEV(adp->chd_dec_major, 0),
377                             NULL, "crystalhd");
378         if (!dev) {
379                 BCMLOG_ERR("failed to create device\n");
380                 goto device_create_fail;
381         }
382
383         rc = crystalhd_create_elem_pool(adp, BC_LINK_ELEM_POOL_SZ);
384         if (rc) {
385                 BCMLOG_ERR("failed to create device\n");
386                 goto elem_pool_fail;
387         }
388
389         /* Allocate general purpose ioctl pool. */
390         for (i = 0; i < CHD_IODATA_POOL_SZ; i++) {
391                 /* FIXME: jarod: why atomic? */
392                 temp = kzalloc(sizeof(crystalhd_ioctl_data), GFP_ATOMIC);
393                 if (!temp) {
394                         BCMLOG_ERR("ioctl data pool kzalloc failed\n");
395                         rc = -ENOMEM;
396                         goto kzalloc_fail;
397                 }
398                 /* Add to global pool.. */
399                 chd_dec_free_iodata(adp, temp, 0);
400         }
401
402         return 0;
403
404 kzalloc_fail:
405         crystalhd_delete_elem_pool(adp);
406 elem_pool_fail:
407         device_destroy(crystalhd_class, MKDEV(adp->chd_dec_major, 0));
408 device_create_fail:
409         class_destroy(crystalhd_class);
410 fail:
411         return rc;
412 }
413
414 static void __devexit chd_dec_release_chdev(struct crystalhd_adp *adp)
415 {
416         crystalhd_ioctl_data *temp = NULL;
417         if (!adp)
418                 return;
419
420         if (adp->chd_dec_major > 0) {
421                 /* unregister crystalhd class */
422                 device_destroy(crystalhd_class, MKDEV(adp->chd_dec_major, 0));
423                 unregister_chrdev(adp->chd_dec_major, CRYSTALHD_API_NAME);
424                 BCMLOG(BCMLOG_INFO, "released api device - %d\n",
425                        adp->chd_dec_major);
426                 class_destroy(crystalhd_class);
427         }
428         adp->chd_dec_major = 0;
429
430         /* Clear iodata pool.. */
431         do {
432                 temp = chd_dec_alloc_iodata(adp, 0);
433                 if (temp)
434                         kfree(temp);
435         } while (temp);
436
437         crystalhd_delete_elem_pool(adp);
438 }
439
440 static int __devinit chd_pci_reserve_mem(struct crystalhd_adp *pinfo)
441 {
442         int rc;
443         unsigned long bar2 = pci_resource_start(pinfo->pdev, 2);
444         uint32_t mem_len   = pci_resource_len(pinfo->pdev, 2);
445         unsigned long bar0 = pci_resource_start(pinfo->pdev, 0);
446         uint32_t i2o_len   = pci_resource_len(pinfo->pdev, 0);
447
448         BCMLOG(BCMLOG_SSTEP, "bar2:0x%lx-0x%08x  bar0:0x%lx-0x%08x\n",
449                bar2, mem_len, bar0, i2o_len);
450
451         rc = check_mem_region(bar2, mem_len);
452         if (rc) {
453                 BCMLOG_ERR("No valid mem region...\n");
454                 return -ENOMEM;
455         }
456
457         pinfo->addr = ioremap_nocache(bar2, mem_len);
458         if (!pinfo->addr) {
459                 BCMLOG_ERR("Failed to remap mem region...\n");
460                 return -ENOMEM;
461         }
462
463         pinfo->pci_mem_start = bar2;
464         pinfo->pci_mem_len   = mem_len;
465
466         rc = check_mem_region(bar0, i2o_len);
467         if (rc) {
468                 BCMLOG_ERR("No valid mem region...\n");
469                 return -ENOMEM;
470         }
471
472         pinfo->i2o_addr = ioremap_nocache(bar0, i2o_len);
473         if (!pinfo->i2o_addr) {
474                 BCMLOG_ERR("Failed to remap mem region...\n");
475                 return -ENOMEM;
476         }
477
478         pinfo->pci_i2o_start = bar0;
479         pinfo->pci_i2o_len   = i2o_len;
480
481         rc = pci_request_regions(pinfo->pdev, pinfo->name);
482         if (rc < 0) {
483                 BCMLOG_ERR("Region request failed: %d\n", rc);
484                 return rc;
485         }
486
487         BCMLOG(BCMLOG_SSTEP, "Mapped addr:0x%08lx  i2o_addr:0x%08lx\n",
488                (unsigned long)pinfo->addr, (unsigned long)pinfo->i2o_addr);
489
490         return 0;
491 }
492
493 static void __devexit chd_pci_release_mem(struct crystalhd_adp *pinfo)
494 {
495         if (!pinfo)
496                 return;
497
498         if (pinfo->addr)
499                 iounmap(pinfo->addr);
500
501         if (pinfo->i2o_addr)
502                 iounmap(pinfo->i2o_addr);
503
504         pci_release_regions(pinfo->pdev);
505 }
506
507
508 static void __devexit chd_dec_pci_remove(struct pci_dev *pdev)
509 {
510         struct crystalhd_adp *pinfo;
511         BC_STATUS sts = BC_STS_SUCCESS;
512
513         BCMLOG_ENTER;
514
515         pinfo = (struct crystalhd_adp *) pci_get_drvdata(pdev);
516         if (!pinfo) {
517                 BCMLOG_ERR("could not get adp\n");
518                 return;
519         }
520
521         sts = crystalhd_delete_cmd_context(&pinfo->cmds);
522         if (sts != BC_STS_SUCCESS)
523                 BCMLOG_ERR("cmd delete :%d \n", sts);
524
525         chd_dec_release_chdev(pinfo);
526
527         chd_dec_disable_int(pinfo);
528
529         chd_pci_release_mem(pinfo);
530         pci_disable_device(pinfo->pdev);
531
532         kfree(pinfo);
533         g_adp_info = NULL;
534 }
535
536 static int __devinit chd_dec_pci_probe(struct pci_dev *pdev,
537                              const struct pci_device_id *entry)
538 {
539         struct crystalhd_adp *pinfo;
540         int rc;
541         BC_STATUS sts = BC_STS_SUCCESS;
542
543         BCMLOG(BCMLOG_DBG, "PCI_INFO: Vendor:0x%04x Device:0x%04x "
544                "s_vendor:0x%04x s_device: 0x%04x\n",
545                pdev->vendor, pdev->device, pdev->subsystem_vendor,
546                pdev->subsystem_device);
547
548         /* FIXME: jarod: why atomic? */
549         pinfo = kzalloc(sizeof(struct crystalhd_adp), GFP_ATOMIC);
550         if (!pinfo) {
551                 BCMLOG_ERR("Failed to allocate memory\n");
552                 return -ENOMEM;
553         }
554
555         pinfo->pdev = pdev;
556
557         rc = pci_enable_device(pdev);
558         if (rc) {
559                 BCMLOG_ERR("Failed to enable PCI device\n");
560                 return rc;
561         }
562
563         snprintf(pinfo->name, 31, "crystalhd_pci_e:%d:%d:%d",
564                  pdev->bus->number, PCI_SLOT(pdev->devfn),
565                  PCI_FUNC(pdev->devfn));
566
567         rc = chd_pci_reserve_mem(pinfo);
568         if (rc) {
569                 BCMLOG_ERR("Failed to setup memory regions.\n");
570                 return -ENOMEM;
571         }
572
573         pinfo->present  = 1;
574         pinfo->drv_data = entry->driver_data;
575
576         /* Setup adapter level lock.. */
577         spin_lock_init(&pinfo->lock);
578
579         /* setup api stuff.. */
580         chd_dec_init_chdev(pinfo);
581         rc = chd_dec_enable_int(pinfo);
582         if (rc) {
583                 BCMLOG_ERR("_enable_int err:%d \n", rc);
584                 pci_disable_device(pdev);
585                 return -ENODEV;
586         }
587
588         /* Set dma mask... */
589         if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
590                 pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
591                 pinfo->dmabits = 64;
592         } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
593                 pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
594                 pinfo->dmabits = 32;
595         } else {
596                 BCMLOG_ERR("Unabled to setup DMA %d\n", rc);
597                 pci_disable_device(pdev);
598                 return -ENODEV;
599         }
600
601         sts = crystalhd_setup_cmd_context(&pinfo->cmds, pinfo);
602         if (sts != BC_STS_SUCCESS) {
603                 BCMLOG_ERR("cmd setup :%d \n", sts);
604                 pci_disable_device(pdev);
605                 return -ENODEV;
606         }
607
608         pci_set_master(pdev);
609
610         pci_set_drvdata(pdev, pinfo);
611
612         g_adp_info = pinfo;
613
614         return 0;
615 }
616
617 #ifdef CONFIG_PM
618 int chd_dec_pci_suspend(struct pci_dev *pdev, pm_message_t state)
619 {
620         struct crystalhd_adp *adp;
621         crystalhd_ioctl_data *temp;
622         BC_STATUS sts = BC_STS_SUCCESS;
623
624         adp = (struct crystalhd_adp *)pci_get_drvdata(pdev);
625         if (!adp) {
626                 BCMLOG_ERR("could not get adp\n");
627                 return -ENODEV;
628         }
629
630         temp = chd_dec_alloc_iodata(adp, false);
631         if (!temp) {
632                 BCMLOG_ERR("could not get ioctl data\n");
633                 return -ENODEV;
634         }
635
636         sts = crystalhd_suspend(&adp->cmds, temp);
637         if (sts != BC_STS_SUCCESS) {
638                 BCMLOG_ERR("BCM70012 Suspend %d\n", sts);
639                 return -ENODEV;
640         }
641
642         chd_dec_free_iodata(adp, temp, false);
643         chd_dec_disable_int(adp);
644         pci_save_state(pdev);
645
646         /* Disable IO/bus master/irq router */
647         pci_disable_device(pdev);
648         pci_set_power_state(pdev, pci_choose_state(pdev, state));
649         return 0;
650 }
651
652 int chd_dec_pci_resume(struct pci_dev *pdev)
653 {
654         struct crystalhd_adp *adp;
655         BC_STATUS sts = BC_STS_SUCCESS;
656         int rc;
657
658         adp = (struct crystalhd_adp *)pci_get_drvdata(pdev);
659         if (!adp) {
660                 BCMLOG_ERR("could not get adp\n");
661                 return -ENODEV;
662         }
663
664         pci_set_power_state(pdev, PCI_D0);
665         pci_restore_state(pdev);
666
667         /* device's irq possibly is changed, driver should take care */
668         if (pci_enable_device(pdev)) {
669                 BCMLOG_ERR("Failed to enable PCI device\n");
670                 return 1;
671         }
672
673         pci_set_master(pdev);
674
675         rc = chd_dec_enable_int(adp);
676         if (rc) {
677                 BCMLOG_ERR("_enable_int err:%d \n", rc);
678                 pci_disable_device(pdev);
679                 return -ENODEV;
680         }
681
682         sts = crystalhd_resume(&adp->cmds);
683         if (sts != BC_STS_SUCCESS) {
684                 BCMLOG_ERR("BCM70012 Resume %d\n", sts);
685                 pci_disable_device(pdev);
686                 return -ENODEV;
687         }
688
689         return 0;
690 }
691 #endif
692
693 static DEFINE_PCI_DEVICE_TABLE(chd_dec_pci_id_table) = {
694         { PCI_VDEVICE(BROADCOM, 0x1612), 8 },
695         { 0, },
696 };
697 MODULE_DEVICE_TABLE(pci, chd_dec_pci_id_table);
698
699 static struct pci_driver bc_chd_70012_driver = {
700         .name     = "Broadcom 70012 Decoder",
701         .probe    = chd_dec_pci_probe,
702         .remove   = __devexit_p(chd_dec_pci_remove),
703         .id_table = chd_dec_pci_id_table,
704 #ifdef CONFIG_PM
705         .suspend  = chd_dec_pci_suspend,
706         .resume   = chd_dec_pci_resume
707 #endif
708 };
709
710 void chd_set_log_level(struct crystalhd_adp *adp, char *arg)
711 {
712         if ((!arg) || (strlen(arg) < 3))
713                 g_linklog_level = BCMLOG_ERROR | BCMLOG_DATA;
714         else if (!strncmp(arg, "sstep", 5))
715                 g_linklog_level = BCMLOG_INFO | BCMLOG_DATA | BCMLOG_DBG |
716                                   BCMLOG_SSTEP | BCMLOG_ERROR;
717         else if (!strncmp(arg, "info", 4))
718                 g_linklog_level = BCMLOG_ERROR | BCMLOG_DATA | BCMLOG_INFO;
719         else if (!strncmp(arg, "debug", 5))
720                 g_linklog_level = BCMLOG_ERROR | BCMLOG_DATA | BCMLOG_INFO |
721                                   BCMLOG_DBG;
722         else if (!strncmp(arg, "pball", 5))
723                 g_linklog_level = 0xFFFFFFFF & ~(BCMLOG_SPINLOCK);
724         else if (!strncmp(arg, "silent", 6))
725                 g_linklog_level = 0;
726         else
727                 g_linklog_level = 0;
728 }
729
730 struct crystalhd_adp *chd_get_adp(void)
731 {
732         return g_adp_info;
733 }
734
735 static int __init chd_dec_module_init(void)
736 {
737         int rc;
738
739         chd_set_log_level(NULL, "debug");
740         BCMLOG(BCMLOG_DATA, "Loading crystalhd %d.%d.%d \n",
741                crystalhd_kmod_major, crystalhd_kmod_minor, crystalhd_kmod_rev);
742
743         rc = pci_register_driver(&bc_chd_70012_driver);
744
745         if (rc < 0)
746                 BCMLOG_ERR("Could not find any devices. err:%d \n", rc);
747
748         return rc;
749 }
750 module_init(chd_dec_module_init);
751
752 static void __exit chd_dec_module_cleanup(void)
753 {
754         BCMLOG(BCMLOG_DATA, "unloading crystalhd %d.%d.%d \n",
755                crystalhd_kmod_major, crystalhd_kmod_minor, crystalhd_kmod_rev);
756
757         pci_unregister_driver(&bc_chd_70012_driver);
758 }
759 module_exit(chd_dec_module_cleanup);
760
761 MODULE_AUTHOR("Naren Sankar <nsankar@broadcom.com>");
762 MODULE_AUTHOR("Prasad Bolisetty <prasadb@broadcom.com>");
763 MODULE_DESCRIPTION(CRYSTAL_HD_NAME);
764 MODULE_LICENSE("GPL");
765 MODULE_ALIAS("bcm70012");