refresh 2.6.30 patches
[openwrt-10.03/.git] / target / linux / generic-2.6 / patches-2.6.30 / 924-cs5535_gpio.patch
1 --- a/drivers/char/cs5535_gpio.c
2 +++ b/drivers/char/cs5535_gpio.c
3 @@ -15,6 +15,7 @@
4  #include <linux/kernel.h>
5  #include <linux/init.h>
6  #include <linux/cdev.h>
7 +#include <linux/device.h>
8  #include <linux/ioport.h>
9  #include <linux/pci.h>
10  #include <linux/smp_lock.h>
11 @@ -48,6 +49,7 @@ static struct pci_device_id divil_pci[]
12  MODULE_DEVICE_TABLE(pci, divil_pci);
13  
14  static struct cdev cs5535_gpio_cdev;
15 +static struct class *cs5535_gpio_class;
16  
17  /* reserve 32 entries even though some aren't usable */
18  #define CS5535_GPIO_COUNT      32
19 @@ -66,9 +68,14 @@ static struct gpio_regmap rm[] =
20         { 0x30, 0x00, '1', '0' },       /* GPIOx_READ_BACK / GPIOx_OUT_VAL */
21         { 0x20, 0x20, 'I', 'i' },       /* GPIOx_IN_EN */
22         { 0x04, 0x04, 'O', 'o' },       /* GPIOx_OUT_EN */
23 +       { 0x10, 0x10, 'A', 'a' },       /* GPIOx_OUT_AUX1_SEL */
24 +       { 0x14, 0x14, 'B', 'b' },       /* GPIOx_OUT_AUX2_SEL */
25         { 0x08, 0x08, 't', 'T' },       /* GPIOx_OUT_OD_EN */
26         { 0x18, 0x18, 'P', 'p' },       /* GPIOx_OUT_PU_EN */
27         { 0x1c, 0x1c, 'D', 'd' },       /* GPIOx_OUT_PD_EN */
28 +       { 0x24, 0x24, 'N', 'n' },       /* GPIOx_IN_INV_EN */
29 +       { 0x0c, 0x0c, 'X', 'x' },       /* GPIOx_OUT_INV_EN */
30 +       { 0x00, 0x00, 'H', 'L' },       /* GPIOx_OUT_VAL */
31  };
32  
33  
34 @@ -177,7 +184,7 @@ static int __init cs5535_gpio_init(void)
35  {
36         dev_t   dev_id;
37         u32     low, hi;
38 -       int     retval;
39 +       int     retval, i;
40  
41         if (pci_dev_present(divil_pci) == 0) {
42                 printk(KERN_WARNING NAME ": DIVIL not found\n");
43 @@ -232,23 +239,54 @@ static int __init cs5535_gpio_init(void)
44                 major = MAJOR(dev_id);
45         }
46  
47 -       if (retval) {
48 -               release_region(gpio_base, CS5535_GPIO_SIZE);
49 -               return -1;
50 -       }
51 +       if (retval)
52 +               goto error;
53  
54         printk(KERN_DEBUG NAME ": base=%#x mask=%#lx major=%d\n",
55                gpio_base, mask, major);
56  
57         cdev_init(&cs5535_gpio_cdev, &cs5535_gpio_fops);
58 -       cdev_add(&cs5535_gpio_cdev, dev_id, CS5535_GPIO_COUNT);
59 +       retval = cdev_add(&cs5535_gpio_cdev, dev_id, CS5535_GPIO_COUNT);
60 +       if (retval) {
61 +               kobject_put(&cs5535_gpio_cdev.kobj);
62 +               goto error_region;
63 +       }
64 +
65 +       cs5535_gpio_class = class_create(THIS_MODULE, "cs5535_gpio");
66 +       if (IS_ERR(cs5535_gpio_class)) {
67 +               printk(KERN_ERR "Error creating cs5535_gpio class\n");
68 +               cdev_del(&cs5535_gpio_cdev);
69 +               retval = PTR_ERR(cs5535_gpio_class);
70 +               goto error_region;
71 +       }
72 +
73 +       for (i = 0; i < CS5535_GPIO_COUNT; i++) {
74 +               if (mask & (1<<i)) {
75 +                       device_create(cs5535_gpio_class, NULL, MKDEV(major, i), NULL, "cs5535_gpio%d", i);
76 +               }
77 +       }
78  
79         return 0;
80 +
81 +error_region:
82 +       unregister_chrdev_region(dev_id, CS5535_GPIO_COUNT);
83 +error:
84 +       release_region(gpio_base, CS5535_GPIO_SIZE);
85 +       return retval;
86  }
87  
88  static void __exit cs5535_gpio_cleanup(void)
89  {
90         dev_t dev_id = MKDEV(major, 0);
91 +       int i;
92 +
93 +       for (i = 0; i < CS5535_GPIO_COUNT; i++) {
94 +               if (mask & (1<<i)) {
95 +                       device_destroy(cs5535_gpio_class, MKDEV(major, i));
96 +               }
97 +       }
98 +
99 +       class_destroy(cs5535_gpio_class);
100  
101         cdev_del(&cs5535_gpio_cdev);
102         unregister_chrdev_region(dev_id, CS5535_GPIO_COUNT);