Merge git://oak/home/sfr/kernels/iseries/work
[linux-2.6] / arch / arm / mach-pxa / akita-ioexp.c
1 /*
2  * Support for the Extra GPIOs on the Sharp SL-C1000 (Akita)
3  * (uses a Maxim MAX7310 8 Port IO Expander)
4  *
5  * Copyright 2005 Openedhand Ltd.
6  *
7  * Author: Richard Purdie <richard@openedhand.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  *
13  */
14
15 #include <linux/kernel.h>
16 #include <linux/init.h>
17 #include <linux/platform_device.h>
18 #include <linux/module.h>
19 #include <linux/i2c.h>
20 #include <linux/slab.h>
21 #include <linux/workqueue.h>
22 #include <asm/arch/akita.h>
23
24 /* MAX7310 Regiser Map */
25 #define MAX7310_INPUT    0x00
26 #define MAX7310_OUTPUT   0x01
27 #define MAX7310_POLINV   0x02
28 #define MAX7310_IODIR    0x03 /* 1 = Input, 0 = Output */
29 #define MAX7310_TIMEOUT  0x04
30
31 /* Addresses to scan */
32 static unsigned short normal_i2c[] = { 0x18, I2C_CLIENT_END };
33
34 /* I2C Magic */
35 I2C_CLIENT_INSMOD;
36
37 static int max7310_write(struct i2c_client *client, int address, int data);
38 static struct i2c_client max7310_template;
39 static void akita_ioexp_work(void *private_);
40
41 static struct device *akita_ioexp_device;
42 static unsigned char ioexp_output_value = AKITA_IOEXP_IO_OUT;
43 DECLARE_WORK(akita_ioexp, akita_ioexp_work, NULL);
44
45
46 /*
47  * MAX7310 Access
48  */
49 static int max7310_config(struct device *dev, int iomode, int polarity)
50 {
51         int ret;
52         struct i2c_client *client = to_i2c_client(dev);
53
54         ret = max7310_write(client, MAX7310_POLINV, polarity);
55         if (ret < 0)
56                 return ret;
57         ret = max7310_write(client, MAX7310_IODIR, iomode);
58         return ret;
59 }
60
61 static int max7310_set_ouputs(struct device *dev, int outputs)
62 {
63         struct i2c_client *client = to_i2c_client(dev);
64
65         return max7310_write(client, MAX7310_OUTPUT, outputs);
66 }
67
68 /*
69  * I2C Functions
70  */
71 static int max7310_write(struct i2c_client *client, int address, int value)
72 {
73         u8 data[2];
74
75         data[0] = address & 0xff;
76         data[1] = value & 0xff;
77
78         if (i2c_master_send(client, data, 2) == 2)
79                 return 0;
80         return -1;
81 }
82
83 static int max7310_detect(struct i2c_adapter *adapter, int address, int kind)
84 {
85         struct i2c_client *new_client;
86         int err;
87
88         if (!(new_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL)))
89                 return -ENOMEM;
90
91         max7310_template.adapter = adapter;
92         max7310_template.addr = address;
93
94         memcpy(new_client, &max7310_template, sizeof(struct i2c_client));
95
96         if ((err = i2c_attach_client(new_client))) {
97                 kfree(new_client);
98                 return err;
99         }
100
101         max7310_config(&new_client->dev, AKITA_IOEXP_IO_DIR, 0);
102         akita_ioexp_device = &new_client->dev;
103         schedule_work(&akita_ioexp);
104
105         return 0;
106 }
107
108 static int max7310_attach_adapter(struct i2c_adapter *adapter)
109 {
110         return i2c_probe(adapter, &addr_data, max7310_detect);
111 }
112
113 static int max7310_detach_client(struct i2c_client *client)
114 {
115         int err;
116
117         akita_ioexp_device = NULL;
118
119         if ((err = i2c_detach_client(client)))
120                 return err;
121
122         kfree(client);
123         return 0;
124 }
125
126 static struct i2c_driver max7310_i2c_driver = {
127         .owner          = THIS_MODULE,
128         .name           = "akita-max7310",
129         .id             = I2C_DRIVERID_AKITAIOEXP,
130         .flags          = I2C_DF_NOTIFY,
131         .attach_adapter = max7310_attach_adapter,
132         .detach_client  = max7310_detach_client,
133 };
134
135 static struct i2c_client max7310_template = {
136         name:   "akita-max7310",
137         flags:  I2C_CLIENT_ALLOW_USE,
138         driver: &max7310_i2c_driver,
139 };
140
141 void akita_set_ioexp(struct device *dev, unsigned char bit)
142 {
143         ioexp_output_value |= bit;
144
145         if (akita_ioexp_device)
146                 schedule_work(&akita_ioexp);
147         return;
148 }
149
150 void akita_reset_ioexp(struct device *dev, unsigned char bit)
151 {
152         ioexp_output_value &= ~bit;
153
154         if (akita_ioexp_device)
155                 schedule_work(&akita_ioexp);
156         return;
157 }
158
159 EXPORT_SYMBOL(akita_set_ioexp);
160 EXPORT_SYMBOL(akita_reset_ioexp);
161
162 static void akita_ioexp_work(void *private_)
163 {
164         if (akita_ioexp_device)
165                 max7310_set_ouputs(akita_ioexp_device, ioexp_output_value);
166 }
167
168
169 #ifdef CONFIG_PM
170 static int akita_ioexp_suspend(struct platform_device *pdev, pm_message_t state)
171 {
172         flush_scheduled_work();
173         return 0;
174 }
175
176 static int akita_ioexp_resume(struct platform_device *pdev)
177 {
178         schedule_work(&akita_ioexp);
179         return 0;
180 }
181 #else
182 #define akita_ioexp_suspend NULL
183 #define akita_ioexp_resume NULL
184 #endif
185
186 static int __init akita_ioexp_probe(struct platform_device *pdev)
187 {
188         return i2c_add_driver(&max7310_i2c_driver);
189 }
190
191 static int akita_ioexp_remove(struct platform_device *pdev)
192 {
193         i2c_del_driver(&max7310_i2c_driver);
194         return 0;
195 }
196
197 static struct platform_driver akita_ioexp_driver = {
198         .probe          = akita_ioexp_probe,
199         .remove         = akita_ioexp_remove,
200         .suspend        = akita_ioexp_suspend,
201         .resume         = akita_ioexp_resume,
202         .driver         = {
203                 .name   = "akita-ioexp",
204         },
205 };
206
207 static int __init akita_ioexp_init(void)
208 {
209         return platform_driver_register(&akita_ioexp_driver);
210 }
211
212 static void __exit akita_ioexp_exit(void)
213 {
214         platform_driver_unregister(&akita_ioexp_driver);
215 }
216
217 MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
218 MODULE_DESCRIPTION("Akita IO-Expander driver");
219 MODULE_LICENSE("GPL");
220
221 fs_initcall(akita_ioexp_init);
222 module_exit(akita_ioexp_exit);
223