diff options
Diffstat (limited to 'drivers/char/pc8736x_gpio.c')
-rw-r--r-- | drivers/char/pc8736x_gpio.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c index 48ff1fc8b06d..b8183d508332 100644 --- a/drivers/char/pc8736x_gpio.c +++ b/drivers/char/pc8736x_gpio.c | |||
@@ -33,6 +33,7 @@ MODULE_PARM_DESC(major, "Major device number"); | |||
33 | 33 | ||
34 | static DEFINE_SPINLOCK(pc8736x_gpio_config_lock); | 34 | static DEFINE_SPINLOCK(pc8736x_gpio_config_lock); |
35 | static unsigned pc8736x_gpio_base; | 35 | static unsigned pc8736x_gpio_base; |
36 | static u8 pc8736x_gpio_shadow[4]; | ||
36 | 37 | ||
37 | #define SIO_BASE1 0x2E /* 1st command-reg to check */ | 38 | #define SIO_BASE1 0x2E /* 1st command-reg to check */ |
38 | #define SIO_BASE2 0x4E /* alt command-reg to check */ | 39 | #define SIO_BASE2 0x4E /* alt command-reg to check */ |
@@ -184,6 +185,7 @@ static void pc8736x_gpio_set(unsigned minor, int val) | |||
184 | val = inb_p(pc8736x_gpio_base + port_offset[port] + PORT_IN); | 185 | val = inb_p(pc8736x_gpio_base + port_offset[port] + PORT_IN); |
185 | 186 | ||
186 | dev_dbg(&pdev->dev, "wrote %x, read: %x\n", curval, val); | 187 | dev_dbg(&pdev->dev, "wrote %x, read: %x\n", curval, val); |
188 | pc8736x_gpio_shadow[port] = val; | ||
187 | } | 189 | } |
188 | 190 | ||
189 | static void pc8736x_gpio_set_high(unsigned index) | 191 | static void pc8736x_gpio_set_high(unsigned index) |
@@ -196,15 +198,18 @@ static void pc8736x_gpio_set_low(unsigned index) | |||
196 | pc8736x_gpio_set(index, 0); | 198 | pc8736x_gpio_set(index, 0); |
197 | } | 199 | } |
198 | 200 | ||
199 | static int pc8736x_gpio_current(unsigned index) | 201 | static int pc8736x_gpio_current(unsigned minor) |
200 | { | 202 | { |
201 | dev_warn(&pdev->dev, "pc8736x_gpio_current unimplemented\n"); | 203 | int port, bit; |
202 | return 0; | 204 | minor &= 0x1f; |
205 | port = minor >> 3; | ||
206 | bit = minor & 7; | ||
207 | return ((pc8736x_gpio_shadow[port] >> bit) & 0x01); | ||
203 | } | 208 | } |
204 | 209 | ||
205 | static void pc8736x_gpio_change(unsigned index) | 210 | static void pc8736x_gpio_change(unsigned index) |
206 | { | 211 | { |
207 | pc8736x_gpio_set(index, !pc8736x_gpio_get(index)); | 212 | pc8736x_gpio_set(index, !pc8736x_gpio_current(index)); |
208 | } | 213 | } |
209 | 214 | ||
210 | static struct nsc_gpio_ops pc8736x_access = { | 215 | static struct nsc_gpio_ops pc8736x_access = { |
@@ -238,6 +243,18 @@ static struct file_operations pc8736x_gpio_fops = { | |||
238 | .read = nsc_gpio_read, | 243 | .read = nsc_gpio_read, |
239 | }; | 244 | }; |
240 | 245 | ||
246 | static void __init pc8736x_init_shadow(void) | ||
247 | { | ||
248 | int port; | ||
249 | |||
250 | /* read the current values driven on the GPIO signals */ | ||
251 | for (port = 0; port < 4; ++port) | ||
252 | pc8736x_gpio_shadow[port] | ||
253 | = inb_p(pc8736x_gpio_base + port_offset[port] | ||
254 | + PORT_OUT); | ||
255 | |||
256 | } | ||
257 | |||
241 | static int __init pc8736x_gpio_init(void) | 258 | static int __init pc8736x_gpio_init(void) |
242 | { | 259 | { |
243 | int rc = 0; | 260 | int rc = 0; |
@@ -317,5 +334,7 @@ static void __exit pc8736x_gpio_cleanup(void) | |||
317 | unregister_chrdev(major, DEVNAME); | 334 | unregister_chrdev(major, DEVNAME); |
318 | } | 335 | } |
319 | 336 | ||
337 | EXPORT_SYMBOL(pc8736x_access); | ||
338 | |||
320 | module_init(pc8736x_gpio_init); | 339 | module_init(pc8736x_gpio_init); |
321 | module_exit(pc8736x_gpio_cleanup); | 340 | module_exit(pc8736x_gpio_cleanup); |