aboutsummaryrefslogtreecommitdiffstats
path: root/arch/cris/arch-v32
diff options
context:
space:
mode:
authorJesper Nilsson <jesper.nilsson@axis.com>2008-02-08 10:28:36 -0500
committerJesper Nilsson <jesper.nilsson@axis.com>2008-02-08 10:28:36 -0500
commita34d24425e9c133e875a26c0bbc91783cf485b93 (patch)
tree86f0d6481a0b4f369fbcb7e2bc7eeb4513683570 /arch/cris/arch-v32
parent7800029df321b033ef27122fbb599ee0a839eb53 (diff)
CRIS v32: Rewrite ARTPEC-3 gpio driver to avoid volatiles and general cleanup.
Changes as suggested by Andrew Morton, plus general cleanup to ease later consolidation of driver into machine common driver. - Correct parameter type of gpio_write to const char __user * - Remove volatile from the arrays of machine dependent registers, use readl and writel to access them instead. - Remove useless casts of void. - Use spin_lock_irqsave for locking. - Break gpio_write into smaller sub-functions. - Remove useless breaks after returns. - Don't perform any change in IO_CFG_WRITE_MODE if values are invalid. (previously values were set and then set to zero) - Change cast for copy_to_user to (void __user *) - Make file_operations gpio_fops static and const. - Make setget_output static. (However, it's still inline since the CRIS architecture is still not SMP, which makes the function small enough to inline)
Diffstat (limited to 'arch/cris/arch-v32')
-rw-r--r--arch/cris/arch-v32/drivers/mach-a3/gpio.c348
1 files changed, 174 insertions, 174 deletions
diff --git a/arch/cris/arch-v32/drivers/mach-a3/gpio.c b/arch/cris/arch-v32/drivers/mach-a3/gpio.c
index 30a2b6e526df..de107dad9f4f 100644
--- a/arch/cris/arch-v32/drivers/mach-a3/gpio.c
+++ b/arch/cris/arch-v32/drivers/mach-a3/gpio.c
@@ -72,13 +72,13 @@ static int virtual_gpio_ioctl(struct file *file, unsigned int cmd,
72 unsigned long arg); 72 unsigned long arg);
73#endif 73#endif
74static int gpio_ioctl(struct inode *inode, struct file *file, 74static int gpio_ioctl(struct inode *inode, struct file *file,
75 unsigned int cmd, unsigned long arg); 75 unsigned int cmd, unsigned long arg);
76static ssize_t gpio_write(struct file *file, const char *buf, size_t count, 76static ssize_t gpio_write(struct file *file, const char __user *buf,
77 loff_t *off); 77 size_t count, loff_t *off);
78static int gpio_open(struct inode *inode, struct file *filp); 78static int gpio_open(struct inode *inode, struct file *filp);
79static int gpio_release(struct inode *inode, struct file *filp); 79static int gpio_release(struct inode *inode, struct file *filp);
80static unsigned int gpio_poll(struct file *filp, 80static unsigned int gpio_poll(struct file *filp,
81 struct poll_table_struct *wait); 81 struct poll_table_struct *wait);
82 82
83/* private data per open() of this driver */ 83/* private data per open() of this driver */
84 84
@@ -96,6 +96,10 @@ struct gpio_private {
96}; 96};
97 97
98static void gpio_set_alarm(struct gpio_private *priv); 98static void gpio_set_alarm(struct gpio_private *priv);
99static int gpio_leds_ioctl(unsigned int cmd, unsigned long arg);
100static int gpio_pwm_ioctl(struct gpio_private *priv, unsigned int cmd,
101 unsigned long arg);
102
99 103
100/* linked list of alarms to check for */ 104/* linked list of alarms to check for */
101 105
@@ -103,23 +107,23 @@ static struct gpio_private *alarmlist;
103 107
104static int wanted_interrupts; 108static int wanted_interrupts;
105 109
106static DEFINE_SPINLOCK(alarm_lock); 110static DEFINE_SPINLOCK(gpio_lock);
107 111
108#define NUM_PORTS (GPIO_MINOR_LAST+1) 112#define NUM_PORTS (GPIO_MINOR_LAST+1)
109#define GIO_REG_RD_ADDR(reg) \ 113#define GIO_REG_RD_ADDR(reg) \
110 (volatile unsigned long *)(regi_gio + REG_RD_ADDR_gio_##reg) 114 (unsigned long *)(regi_gio + REG_RD_ADDR_gio_##reg)
111#define GIO_REG_WR_ADDR(reg) \ 115#define GIO_REG_WR_ADDR(reg) \
112 (volatile unsigned long *)(regi_gio + REG_WR_ADDR_gio_##reg) 116 (unsigned long *)(regi_gio + REG_WR_ADDR_gio_##reg)
113unsigned long led_dummy; 117static unsigned long led_dummy;
114unsigned long port_d_dummy; /* Only input on Artpec-3 */ 118static unsigned long port_d_dummy; /* Only input on Artpec-3 */
115unsigned long port_e_dummy; /* Non existent on Artpec-3 */
116#ifdef CONFIG_ETRAX_VIRTUAL_GPIO 119#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
120static unsigned long port_e_dummy; /* Non existent on Artpec-3 */
117static unsigned long virtual_dummy; 121static unsigned long virtual_dummy;
118static unsigned long virtual_rw_pv_oe = CONFIG_ETRAX_DEF_GIO_PV_OE; 122static unsigned long virtual_rw_pv_oe = CONFIG_ETRAX_DEF_GIO_PV_OE;
119static unsigned short cached_virtual_gpio_read; 123static unsigned short cached_virtual_gpio_read;
120#endif 124#endif
121 125
122static volatile unsigned long *data_out[NUM_PORTS] = { 126static unsigned long *data_out[NUM_PORTS] = {
123 GIO_REG_WR_ADDR(rw_pa_dout), 127 GIO_REG_WR_ADDR(rw_pa_dout),
124 GIO_REG_WR_ADDR(rw_pb_dout), 128 GIO_REG_WR_ADDR(rw_pb_dout),
125 &led_dummy, 129 &led_dummy,
@@ -131,7 +135,7 @@ static volatile unsigned long *data_out[NUM_PORTS] = {
131#endif 135#endif
132}; 136};
133 137
134static volatile unsigned long *data_in[NUM_PORTS] = { 138static unsigned long *data_in[NUM_PORTS] = {
135 GIO_REG_RD_ADDR(r_pa_din), 139 GIO_REG_RD_ADDR(r_pa_din),
136 GIO_REG_RD_ADDR(r_pb_din), 140 GIO_REG_RD_ADDR(r_pb_din),
137 &led_dummy, 141 &led_dummy,
@@ -167,7 +171,7 @@ static unsigned long changeable_bits[NUM_PORTS] = {
167#endif 171#endif
168}; 172};
169 173
170static volatile unsigned long *dir_oe[NUM_PORTS] = { 174static unsigned long *dir_oe[NUM_PORTS] = {
171 GIO_REG_WR_ADDR(rw_pa_oe), 175 GIO_REG_WR_ADDR(rw_pa_oe),
172 GIO_REG_WR_ADDR(rw_pb_oe), 176 GIO_REG_WR_ADDR(rw_pb_oe),
173 &led_dummy, 177 &led_dummy,
@@ -179,8 +183,7 @@ static volatile unsigned long *dir_oe[NUM_PORTS] = {
179#endif 183#endif
180}; 184};
181 185
182static void 186static void gpio_set_alarm(struct gpio_private *priv)
183gpio_set_alarm(struct gpio_private *priv)
184{ 187{
185 int bit; 188 int bit;
186 int intr_cfg; 189 int intr_cfg;
@@ -188,7 +191,7 @@ gpio_set_alarm(struct gpio_private *priv)
188 int pins; 191 int pins;
189 unsigned long flags; 192 unsigned long flags;
190 193
191 local_irq_save(flags); 194 spin_lock_irqsave(&gpio_lock, flags);
192 intr_cfg = REG_RD_INT(gio, regi_gio, rw_intr_cfg); 195 intr_cfg = REG_RD_INT(gio, regi_gio, rw_intr_cfg);
193 pins = REG_RD_INT(gio, regi_gio, rw_intr_pins); 196 pins = REG_RD_INT(gio, regi_gio, rw_intr_pins);
194 mask = REG_RD_INT(gio, regi_gio, rw_intr_mask) & I2C_INTERRUPT_BITS; 197 mask = REG_RD_INT(gio, regi_gio, rw_intr_mask) & I2C_INTERRUPT_BITS;
@@ -218,14 +221,13 @@ gpio_set_alarm(struct gpio_private *priv)
218 REG_WR_INT(gio, regi_gio, rw_intr_pins, pins); 221 REG_WR_INT(gio, regi_gio, rw_intr_pins, pins);
219 REG_WR_INT(gio, regi_gio, rw_intr_mask, mask); 222 REG_WR_INT(gio, regi_gio, rw_intr_mask, mask);
220 223
221 local_irq_restore(flags); 224 spin_unlock_irqrestore(&gpio_lock, flags);
222} 225}
223 226
224static unsigned int 227static unsigned int gpio_poll(struct file *file, struct poll_table_struct *wait)
225gpio_poll(struct file *file, struct poll_table_struct *wait)
226{ 228{
227 unsigned int mask = 0; 229 unsigned int mask = 0;
228 struct gpio_private *priv = (struct gpio_private *)file->private_data; 230 struct gpio_private *priv = file->private_data;
229 unsigned long data; 231 unsigned long data;
230 unsigned long tmp; 232 unsigned long tmp;
231 233
@@ -235,7 +237,7 @@ gpio_poll(struct file *file, struct poll_table_struct *wait)
235 237
236 poll_wait(file, &priv->alarm_wq, wait); 238 poll_wait(file, &priv->alarm_wq, wait);
237 if (priv->minor <= GPIO_MINOR_D) { 239 if (priv->minor <= GPIO_MINOR_D) {
238 data = *data_in[priv->minor]; 240 data = readl(data_in[priv->minor]);
239 REG_WR_INT(gio, regi_gio, rw_ack_intr, wanted_interrupts); 241 REG_WR_INT(gio, regi_gio, rw_ack_intr, wanted_interrupts);
240 tmp = REG_RD_INT(gio, regi_gio, rw_intr_mask); 242 tmp = REG_RD_INT(gio, regi_gio, rw_intr_mask);
241 tmp &= I2C_INTERRUPT_BITS; 243 tmp &= I2C_INTERRUPT_BITS;
@@ -251,12 +253,12 @@ gpio_poll(struct file *file, struct poll_table_struct *wait)
251 return mask; 253 return mask;
252} 254}
253 255
254static irqreturn_t 256static irqreturn_t gpio_interrupt(int irq, void *dev_id)
255gpio_interrupt(int irq, void *dev_id)
256{ 257{
257 reg_gio_rw_intr_mask intr_mask; 258 reg_gio_rw_intr_mask intr_mask;
258 reg_gio_r_masked_intr masked_intr; 259 reg_gio_r_masked_intr masked_intr;
259 reg_gio_rw_ack_intr ack_intr; 260 reg_gio_rw_ack_intr ack_intr;
261 unsigned long flags;
260 unsigned long tmp; 262 unsigned long tmp;
261 unsigned long tmp2; 263 unsigned long tmp2;
262#ifdef CONFIG_ETRAX_VIRTUAL_GPIO 264#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
@@ -268,9 +270,9 @@ gpio_interrupt(int irq, void *dev_id)
268 tmp = REG_TYPE_CONV(unsigned long, reg_gio_r_masked_intr, masked_intr); 270 tmp = REG_TYPE_CONV(unsigned long, reg_gio_r_masked_intr, masked_intr);
269 271
270 /* Find those that we have enabled */ 272 /* Find those that we have enabled */
271 spin_lock(&alarm_lock); 273 spin_lock_irqsave(&gpio_lock, flags);
272 tmp &= wanted_interrupts; 274 tmp &= wanted_interrupts;
273 spin_unlock(&alarm_lock); 275 spin_unlock_irqrestore(&gpio_lock, flags);
274 276
275#ifdef CONFIG_ETRAX_VIRTUAL_GPIO 277#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
276 /* Something changed on virtual GPIO. Interrupt is acked by 278 /* Something changed on virtual GPIO. Interrupt is acked by
@@ -304,15 +306,42 @@ gpio_interrupt(int irq, void *dev_id)
304 return IRQ_RETVAL(tmp); 306 return IRQ_RETVAL(tmp);
305} 307}
306 308
309static void gpio_write_bit(unsigned long *port, unsigned char data, int bit,
310 unsigned char clk_mask, unsigned char data_mask)
311{
312 unsigned long shadow = readl(port) & ~clk_mask;
313 writel(shadow, port);
314 if (data & 1 << bit)
315 shadow |= data_mask;
316 else
317 shadow &= ~data_mask;
318 writel(shadow, port);
319 /* For FPGA: min 5.0ns (DCC) before CCLK high */
320 shadow |= clk_mask;
321 writel(shadow, port);
322}
323
324static void gpio_write_byte(struct gpio_private *priv, unsigned long *port,
325 unsigned char data)
326{
327 int i;
328
329 if (priv->write_msb)
330 for (i = 7; i >= 0; i--)
331 gpio_write_bit(port, data, i, priv->clk_mask,
332 priv->data_mask);
333 else
334 for (i = 0; i <= 7; i++)
335 gpio_write_bit(port, data, i, priv->clk_mask,
336 priv->data_mask);
337}
338
307 339
308static ssize_t gpio_write(struct file *file, const char *buf, size_t count, 340static ssize_t gpio_write(struct file *file, const char __user *buf,
309 loff_t *off) 341 size_t count, loff_t *off)
310{ 342{
311 struct gpio_private *priv = (struct gpio_private *)file->private_data; 343 struct gpio_private *priv = file->private_data;
312 unsigned char data, clk_mask, data_mask, write_msb;
313 unsigned long flags; 344 unsigned long flags;
314 unsigned long shadow;
315 volatile unsigned long *port;
316 ssize_t retval = count; 345 ssize_t retval = count;
317 /* Only bits 0-7 may be used for write operations but allow all 346 /* Only bits 0-7 may be used for write operations but allow all
318 devices except leds... */ 347 devices except leds... */
@@ -330,55 +359,25 @@ static ssize_t gpio_write(struct file *file, const char *buf, size_t count,
330 if (!access_ok(VERIFY_READ, buf, count)) 359 if (!access_ok(VERIFY_READ, buf, count))
331 return -EFAULT; 360 return -EFAULT;
332 361
333 clk_mask = priv->clk_mask;
334 data_mask = priv->data_mask;
335 /* It must have been configured using the IO_CFG_WRITE_MODE */ 362 /* It must have been configured using the IO_CFG_WRITE_MODE */
336 /* Perhaps a better error code? */ 363 /* Perhaps a better error code? */
337 if (clk_mask == 0 || data_mask == 0) 364 if (priv->clk_mask == 0 || priv->data_mask == 0)
338 return -EPERM; 365 return -EPERM;
339 366
340 write_msb = priv->write_msb;
341 D(printk(KERN_DEBUG "gpio_write: %lu to data 0x%02X clk 0x%02X " 367 D(printk(KERN_DEBUG "gpio_write: %lu to data 0x%02X clk 0x%02X "
342 "msb: %i\n", 368 "msb: %i\n",
343 count, data_mask, clk_mask, write_msb)); 369 count, priv->data_mask, priv->clk_mask, priv->write_msb));
344 port = data_out[priv->minor]; 370
345 371 spin_lock_irqsave(&gpio_lock, flags);
346 while (count--) { 372
347 int i; 373 while (count--)
348 data = *buf++; 374 gpio_write_byte(priv, data_out[priv->minor], *buf++);
349 if (priv->write_msb) { 375
350 for (i = 7; i >= 0; i--) { 376 spin_unlock_irqrestore(&gpio_lock, flags);
351 local_irq_save(flags);
352 shadow = *port;
353 *port = shadow &= ~clk_mask;
354 if (data & 1<<i)
355 *port = shadow |= data_mask;
356 else
357 *port = shadow &= ~data_mask;
358 /* For FPGA: min 5.0ns (DCC) before CCLK high */
359 *port = shadow |= clk_mask;
360 local_irq_restore(flags);
361 }
362 } else {
363 for (i = 0; i <= 7; i++) {
364 local_irq_save(flags);
365 shadow = *port;
366 *port = shadow &= ~clk_mask;
367 if (data & 1<<i)
368 *port = shadow |= data_mask;
369 else
370 *port = shadow &= ~data_mask;
371 /* For FPGA: min 5.0ns (DCC) before CCLK high */
372 *port = shadow |= clk_mask;
373 local_irq_restore(flags);
374 }
375 }
376 }
377 return retval; 377 return retval;
378} 378}
379 379
380static int 380static int gpio_open(struct inode *inode, struct file *filp)
381gpio_open(struct inode *inode, struct file *filp)
382{ 381{
383 struct gpio_private *priv; 382 struct gpio_private *priv;
384 int p = iminor(inode); 383 int p = iminor(inode);
@@ -394,7 +393,7 @@ gpio_open(struct inode *inode, struct file *filp)
394 memset(priv, 0, sizeof(*priv)); 393 memset(priv, 0, sizeof(*priv));
395 394
396 priv->minor = p; 395 priv->minor = p;
397 filp->private_data = (void *)priv; 396 filp->private_data = priv;
398 397
399 /* initialize the io/alarm struct, not for PWM ports though */ 398 /* initialize the io/alarm struct, not for PWM ports though */
400 if (p <= GPIO_MINOR_LAST) { 399 if (p <= GPIO_MINOR_LAST) {
@@ -407,17 +406,16 @@ gpio_open(struct inode *inode, struct file *filp)
407 init_waitqueue_head(&priv->alarm_wq); 406 init_waitqueue_head(&priv->alarm_wq);
408 407
409 /* link it into our alarmlist */ 408 /* link it into our alarmlist */
410 spin_lock_irq(&alarm_lock); 409 spin_lock_irq(&gpio_lock);
411 priv->next = alarmlist; 410 priv->next = alarmlist;
412 alarmlist = priv; 411 alarmlist = priv;
413 spin_unlock_irq(&alarm_lock); 412 spin_unlock_irq(&gpio_lock);
414 } 413 }
415 414
416 return 0; 415 return 0;
417} 416}
418 417
419static int 418static int gpio_release(struct inode *inode, struct file *filp)
420gpio_release(struct inode *inode, struct file *filp)
421{ 419{
422 struct gpio_private *p; 420 struct gpio_private *p;
423 struct gpio_private *todel; 421 struct gpio_private *todel;
@@ -425,11 +423,11 @@ gpio_release(struct inode *inode, struct file *filp)
425 unsigned long a_high, a_low; 423 unsigned long a_high, a_low;
426 424
427 /* prepare to free private structure */ 425 /* prepare to free private structure */
428 todel = (struct gpio_private *)filp->private_data; 426 todel = filp->private_data;
429 427
430 /* unlink from alarmlist - only for non-PWM ports though */ 428 /* unlink from alarmlist - only for non-PWM ports though */
431 if (todel->minor <= GPIO_MINOR_LAST) { 429 if (todel->minor <= GPIO_MINOR_LAST) {
432 spin_lock_irq(&alarm_lock); 430 spin_lock_irq(&gpio_lock);
433 p = alarmlist; 431 p = alarmlist;
434 432
435 if (p == todel) 433 if (p == todel)
@@ -463,7 +461,7 @@ gpio_release(struct inode *inode, struct file *filp)
463 a_low |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN); 461 a_low |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
464#endif 462#endif
465 463
466 spin_unlock_irq(&alarm_lock); 464 spin_unlock_irq(&gpio_lock);
467 } 465 }
468 kfree(todel); 466 kfree(todel);
469 467
@@ -482,11 +480,13 @@ inline unsigned long setget_input(struct gpio_private *priv, unsigned long arg)
482 unsigned long flags; 480 unsigned long flags;
483 unsigned long dir_shadow; 481 unsigned long dir_shadow;
484 482
485 local_irq_save(flags); 483 spin_lock_irqsave(&gpio_lock, flags);
486 dir_shadow = *dir_oe[priv->minor]; 484
487 dir_shadow &= ~(arg & changeable_dir[priv->minor]); 485 dir_shadow = readl(dir_oe[priv->minor]) &
488 *dir_oe[priv->minor] = dir_shadow; 486 ~(arg & changeable_dir[priv->minor]);
489 local_irq_restore(flags); 487 writel(dir_shadow, dir_oe[priv->minor]);
488
489 spin_unlock_irqrestore(&gpio_lock, flags);
490 490
491 if (priv->minor == GPIO_MINOR_C) 491 if (priv->minor == GPIO_MINOR_C)
492 dir_shadow ^= 0xFFFF; /* Only 16 bits */ 492 dir_shadow ^= 0xFFFF; /* Only 16 bits */
@@ -501,36 +501,32 @@ inline unsigned long setget_input(struct gpio_private *priv, unsigned long arg)
501 501
502} /* setget_input */ 502} /* setget_input */
503 503
504inline unsigned long setget_output(struct gpio_private *priv, unsigned long arg) 504static inline unsigned long setget_output(struct gpio_private *priv,
505 unsigned long arg)
505{ 506{
506 unsigned long flags; 507 unsigned long flags;
507 unsigned long dir_shadow; 508 unsigned long dir_shadow;
508 509
509 local_irq_save(flags); 510 spin_lock_irqsave(&gpio_lock, flags);
510 dir_shadow = *dir_oe[priv->minor];
511 dir_shadow |= (arg & changeable_dir[priv->minor]);
512 *dir_oe[priv->minor] = dir_shadow;
513 local_irq_restore(flags);
514 return dir_shadow;
515} /* setget_output */
516 511
517static int 512 dir_shadow = readl(dir_oe[priv->minor]) |
518gpio_leds_ioctl(unsigned int cmd, unsigned long arg); 513 (arg & changeable_dir[priv->minor]);
514 writel(dir_shadow, dir_oe[priv->minor]);
519 515
520static int 516 spin_unlock_irqrestore(&gpio_lock, flags);
521gpio_pwm_ioctl(struct gpio_private *priv, unsigned int cmd, unsigned long arg); 517 return dir_shadow;
518} /* setget_output */
522 519
523static int 520static int gpio_ioctl(struct inode *inode, struct file *file,
524gpio_ioctl(struct inode *inode, struct file *file, 521 unsigned int cmd, unsigned long arg)
525 unsigned int cmd, unsigned long arg)
526{ 522{
527 unsigned long flags; 523 unsigned long flags;
528 unsigned long val; 524 unsigned long val;
529 unsigned long shadow; 525 unsigned long shadow;
530 struct gpio_private *priv = (struct gpio_private *)file->private_data; 526 struct gpio_private *priv = file->private_data;
531 527
532 if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) 528 if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE)
533 return -EINVAL; 529 return -ENOTTY;
534 530
535 /* Check for special ioctl handlers first */ 531 /* Check for special ioctl handlers first */
536 532
@@ -549,23 +545,22 @@ gpio_ioctl(struct inode *inode, struct file *file,
549 switch (_IOC_NR(cmd)) { 545 switch (_IOC_NR(cmd)) {
550 case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */ 546 case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */
551 /* Read the port. */ 547 /* Read the port. */
552 return *data_in[priv->minor]; 548 return readl(data_in[priv->minor]);
553 break;
554 case IO_SETBITS: 549 case IO_SETBITS:
555 local_irq_save(flags); 550 spin_lock_irqsave(&gpio_lock, flags);
556 /* Set changeable bits with a 1 in arg. */ 551 /* Set changeable bits with a 1 in arg. */
557 shadow = *data_out[priv->minor]; 552 shadow = readl(data_out[priv->minor]) |
558 shadow |= (arg & changeable_bits[priv->minor]); 553 (arg & changeable_bits[priv->minor]);
559 *data_out[priv->minor] = shadow; 554 writel(shadow, data_out[priv->minor]);
560 local_irq_restore(flags); 555 spin_unlock_irqrestore(&gpio_lock, flags);
561 break; 556 break;
562 case IO_CLRBITS: 557 case IO_CLRBITS:
563 local_irq_save(flags); 558 spin_lock_irqsave(&gpio_lock, flags);
564 /* Clear changeable bits with a 1 in arg. */ 559 /* Clear changeable bits with a 1 in arg. */
565 shadow = *data_out[priv->minor]; 560 shadow = readl(data_out[priv->minor]) &
566 shadow &= ~(arg & changeable_bits[priv->minor]); 561 ~(arg & changeable_bits[priv->minor]);
567 *data_out[priv->minor] = shadow; 562 writel(shadow, data_out[priv->minor]);
568 local_irq_restore(flags); 563 spin_unlock_irqrestore(&gpio_lock, flags);
569 break; 564 break;
570 case IO_HIGHALARM: 565 case IO_HIGHALARM:
571 /* Set alarm when bits with 1 in arg go high. */ 566 /* Set alarm when bits with 1 in arg go high. */
@@ -585,13 +580,14 @@ gpio_ioctl(struct inode *inode, struct file *file,
585 break; 580 break;
586 case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */ 581 case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */
587 /* Read direction 0=input 1=output */ 582 /* Read direction 0=input 1=output */
588 return *dir_oe[priv->minor]; 583 return readl(dir_oe[priv->minor]);
584
589 case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */ 585 case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */
590 /* Set direction 0=unchanged 1=input, 586 /* Set direction 0=unchanged 1=input,
591 * return mask with 1=input 587 * return mask with 1=input
592 */ 588 */
593 return setget_input(priv, arg); 589 return setget_input(priv, arg);
594 break; 590
595 case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */ 591 case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */
596 /* Set direction 0=unchanged 1=output, 592 /* Set direction 0=unchanged 1=output,
597 * return mask with 1=output 593 * return mask with 1=output
@@ -600,56 +596,61 @@ gpio_ioctl(struct inode *inode, struct file *file,
600 596
601 case IO_CFG_WRITE_MODE: 597 case IO_CFG_WRITE_MODE:
602 { 598 {
603 unsigned long dir_shadow; 599 int res = -EPERM;
604 dir_shadow = *dir_oe[priv->minor]; 600 unsigned long dir_shadow, clk_mask, data_mask, write_msb;
601
602 clk_mask = arg & 0xFF;
603 data_mask = (arg >> 8) & 0xFF;
604 write_msb = (arg >> 16) & 0x01;
605 605
606 priv->clk_mask = arg & 0xFF;
607 priv->data_mask = (arg >> 8) & 0xFF;
608 priv->write_msb = (arg >> 16) & 0x01;
609 /* Check if we're allowed to change the bits and 606 /* Check if we're allowed to change the bits and
610 * the direction is correct 607 * the direction is correct
611 */ 608 */
612 if (!((priv->clk_mask & changeable_bits[priv->minor]) && 609 spin_lock_irqsave(&gpio_lock, flags);
613 (priv->data_mask & changeable_bits[priv->minor]) && 610 dir_shadow = readl(dir_oe[priv->minor]);
614 (priv->clk_mask & dir_shadow) && 611 if ((clk_mask & changeable_bits[priv->minor]) &&
615 (priv->data_mask & dir_shadow))) { 612 (data_mask & changeable_bits[priv->minor]) &&
616 priv->clk_mask = 0; 613 (clk_mask & dir_shadow) &&
617 priv->data_mask = 0; 614 (data_mask & dir_shadow)) {
618 return -EPERM; 615 priv->clk_mask = clk_mask;
616 priv->data_mask = data_mask;
617 priv->write_msb = write_msb;
618 res = 0;
619 } 619 }
620 break; 620 spin_unlock_irqrestore(&gpio_lock, flags);
621
622 return res;
621 } 623 }
622 case IO_READ_INBITS: 624 case IO_READ_INBITS:
623 /* *arg is result of reading the input pins */ 625 /* *arg is result of reading the input pins */
624 val = *data_in[priv->minor]; 626 val = readl(data_in[priv->minor]);
625 if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) 627 if (copy_to_user((void __user *)arg, &val, sizeof(val)))
626 return -EFAULT; 628 return -EFAULT;
627 return 0; 629 return 0;
628 break;
629 case IO_READ_OUTBITS: 630 case IO_READ_OUTBITS:
630 /* *arg is result of reading the output shadow */ 631 /* *arg is result of reading the output shadow */
631 val = *data_out[priv->minor]; 632 val = *data_out[priv->minor];
632 if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) 633 if (copy_to_user((void __user *)arg, &val, sizeof(val)))
633 return -EFAULT; 634 return -EFAULT;
634 break; 635 break;
635 case IO_SETGET_INPUT: 636 case IO_SETGET_INPUT:
636 /* bits set in *arg is set to input, 637 /* bits set in *arg is set to input,
637 * *arg updated with current input pins. 638 * *arg updated with current input pins.
638 */ 639 */
639 if (copy_from_user(&val, (unsigned long *)arg, sizeof(val))) 640 if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
640 return -EFAULT; 641 return -EFAULT;
641 val = setget_input(priv, val); 642 val = setget_input(priv, val);
642 if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) 643 if (copy_to_user((void __user *)arg, &val, sizeof(val)))
643 return -EFAULT; 644 return -EFAULT;
644 break; 645 break;
645 case IO_SETGET_OUTPUT: 646 case IO_SETGET_OUTPUT:
646 /* bits set in *arg is set to output, 647 /* bits set in *arg is set to output,
647 * *arg updated with current output pins. 648 * *arg updated with current output pins.
648 */ 649 */
649 if (copy_from_user(&val, (unsigned long *)arg, sizeof(val))) 650 if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
650 return -EFAULT; 651 return -EFAULT;
651 val = setget_output(priv, val); 652 val = setget_output(priv, val);
652 if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) 653 if (copy_to_user((void __user *)arg, &val, sizeof(val)))
653 return -EFAULT; 654 return -EFAULT;
654 break; 655 break;
655 default: 656 default:
@@ -660,32 +661,32 @@ gpio_ioctl(struct inode *inode, struct file *file,
660} 661}
661 662
662#ifdef CONFIG_ETRAX_VIRTUAL_GPIO 663#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
663static int 664static int virtual_gpio_ioctl(struct file *file, unsigned int cmd,
664virtual_gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 665 unsigned long arg)
665{ 666{
666 unsigned long flags; 667 unsigned long flags;
667 unsigned short val; 668 unsigned short val;
668 unsigned short shadow; 669 unsigned short shadow;
669 struct gpio_private *priv = (struct gpio_private *)file->private_data; 670 struct gpio_private *priv = file->private_data;
670 671
671 switch (_IOC_NR(cmd)) { 672 switch (_IOC_NR(cmd)) {
672 case IO_SETBITS: 673 case IO_SETBITS:
673 local_irq_save(flags); 674 spin_lock_irqsave(&gpio_lock, flags);
674 /* Set changeable bits with a 1 in arg. */ 675 /* Set changeable bits with a 1 in arg. */
675 i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); 676 i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
676 shadow |= ~*dir_oe[priv->minor]; 677 shadow |= ~readl(dir_oe[priv->minor]) |
677 shadow |= (arg & changeable_bits[priv->minor]); 678 (arg & changeable_bits[priv->minor]);
678 i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); 679 i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
679 local_irq_restore(flags); 680 spin_lock_irqrestore(&gpio_lock, flags);
680 break; 681 break;
681 case IO_CLRBITS: 682 case IO_CLRBITS:
682 local_irq_save(flags); 683 spin_lock_irqsave(&gpio_lock, flags);
683 /* Clear changeable bits with a 1 in arg. */ 684 /* Clear changeable bits with a 1 in arg. */
684 i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); 685 i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
685 shadow |= ~*dir_oe[priv->minor]; 686 shadow |= ~readl(dir_oe[priv->minor]) &
686 shadow &= ~(arg & changeable_bits[priv->minor]); 687 ~(arg & changeable_bits[priv->minor]);
687 i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); 688 i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
688 local_irq_restore(flags); 689 spin_lock_irqrestore(&gpio_lock, flags);
689 break; 690 break;
690 case IO_HIGHALARM: 691 case IO_HIGHALARM:
691 /* Set alarm when bits with 1 in arg go high. */ 692 /* Set alarm when bits with 1 in arg go high. */
@@ -703,7 +704,7 @@ virtual_gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
703 case IO_CFG_WRITE_MODE: 704 case IO_CFG_WRITE_MODE:
704 { 705 {
705 unsigned long dir_shadow; 706 unsigned long dir_shadow;
706 dir_shadow = *dir_oe[priv->minor]; 707 dir_shadow = readl(dir_oe[priv->minor]);
707 708
708 priv->clk_mask = arg & 0xFF; 709 priv->clk_mask = arg & 0xFF;
709 priv->data_mask = (arg >> 8) & 0xFF; 710 priv->data_mask = (arg >> 8) & 0xFF;
@@ -723,17 +724,16 @@ virtual_gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
723 } 724 }
724 case IO_READ_INBITS: 725 case IO_READ_INBITS:
725 /* *arg is result of reading the input pins */ 726 /* *arg is result of reading the input pins */
726 val = cached_virtual_gpio_read; 727 val = cached_virtual_gpio_read & ~readl(dir_oe[priv->minor]);
727 val &= ~*dir_oe[priv->minor]; 728 if (copy_to_user((void __user *)arg, &val, sizeof(val)))
728 if (copy_to_user((unsigned long *)arg, &val, sizeof(val)))
729 return -EFAULT; 729 return -EFAULT;
730 return 0; 730 return 0;
731 break; 731
732 case IO_READ_OUTBITS: 732 case IO_READ_OUTBITS:
733 /* *arg is result of reading the output shadow */ 733 /* *arg is result of reading the output shadow */
734 i2c_read(VIRT_I2C_ADDR, (void *)&val, sizeof(val)); 734 i2c_read(VIRT_I2C_ADDR, (void *)&val, sizeof(val));
735 val &= *dir_oe[priv->minor]; 735 val &= readl(dir_oe[priv->minor]);
736 if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) 736 if (copy_to_user((void __user *)arg, &val, sizeof(val)))
737 return -EFAULT; 737 return -EFAULT;
738 break; 738 break;
739 case IO_SETGET_INPUT: 739 case IO_SETGET_INPUT:
@@ -741,11 +741,11 @@ virtual_gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
741 /* bits set in *arg is set to input, 741 /* bits set in *arg is set to input,
742 * *arg updated with current input pins. 742 * *arg updated with current input pins.
743 */ 743 */
744 unsigned short input_mask = ~*dir_oe[priv->minor]; 744 unsigned short input_mask = ~readl(dir_oe[priv->minor]);
745 if (copy_from_user(&val, (unsigned long *)arg, sizeof(val))) 745 if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
746 return -EFAULT; 746 return -EFAULT;
747 val = setget_input(priv, val); 747 val = setget_input(priv, val);
748 if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) 748 if (copy_to_user((void __user *)arg, &val, sizeof(val)))
749 return -EFAULT; 749 return -EFAULT;
750 if ((input_mask & val) != input_mask) { 750 if ((input_mask & val) != input_mask) {
751 /* Input pins changed. All ports desired as input 751 /* Input pins changed. All ports desired as input
@@ -765,10 +765,10 @@ virtual_gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
765 /* bits set in *arg is set to output, 765 /* bits set in *arg is set to output,
766 * *arg updated with current output pins. 766 * *arg updated with current output pins.
767 */ 767 */
768 if (copy_from_user(&val, (unsigned long *)arg, sizeof(val))) 768 if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
769 return -EFAULT; 769 return -EFAULT;
770 val = setget_output(priv, val); 770 val = setget_output(priv, val);
771 if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) 771 if (copy_to_user((void __user *)arg, &val, sizeof(val)))
772 return -EFAULT; 772 return -EFAULT;
773 break; 773 break;
774 default: 774 default:
@@ -778,8 +778,7 @@ virtual_gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
778} 778}
779#endif /* CONFIG_ETRAX_VIRTUAL_GPIO */ 779#endif /* CONFIG_ETRAX_VIRTUAL_GPIO */
780 780
781static int 781static int gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
782gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
783{ 782{
784 unsigned char green; 783 unsigned char green;
785 unsigned char red; 784 unsigned char red;
@@ -829,8 +828,7 @@ static int gpio_pwm_set_period(unsigned long arg, int pwm_port)
829 struct io_pwm_set_period periods; 828 struct io_pwm_set_period periods;
830 reg_gio_rw_pwm0_var rw_pwm_widths; 829 reg_gio_rw_pwm0_var rw_pwm_widths;
831 830
832 if (copy_from_user(&periods, (struct io_pwm_set_period *) arg, 831 if (copy_from_user(&periods, (void __user *)arg, sizeof(periods)))
833 sizeof(periods)))
834 return -EFAULT; 832 return -EFAULT;
835 if (periods.lo > 8191 || periods.hi > 8191) 833 if (periods.lo > 8191 || periods.hi > 8191)
836 return -EINVAL; 834 return -EINVAL;
@@ -856,8 +854,8 @@ static int gpio_pwm_set_duty(unsigned long arg, int pwm_port)
856 return 0; 854 return 0;
857} 855}
858 856
859static int 857static int gpio_pwm_ioctl(struct gpio_private *priv, unsigned int cmd,
860gpio_pwm_ioctl(struct gpio_private *priv, unsigned int cmd, unsigned long arg) 858 unsigned long arg)
861{ 859{
862 int pwm_port = priv->minor - GPIO_MINOR_PWM0; 860 int pwm_port = priv->minor - GPIO_MINOR_PWM0;
863 861
@@ -874,7 +872,7 @@ gpio_pwm_ioctl(struct gpio_private *priv, unsigned int cmd, unsigned long arg)
874 return 0; 872 return 0;
875} 873}
876 874
877struct file_operations gpio_fops = { 875static const struct file_operations gpio_fops = {
878 .owner = THIS_MODULE, 876 .owner = THIS_MODULE,
879 .poll = gpio_poll, 877 .poll = gpio_poll,
880 .ioctl = gpio_ioctl, 878 .ioctl = gpio_ioctl,
@@ -884,8 +882,7 @@ struct file_operations gpio_fops = {
884}; 882};
885 883
886#ifdef CONFIG_ETRAX_VIRTUAL_GPIO 884#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
887static void 885static void __init virtual_gpio_init(void)
888virtual_gpio_init(void)
889{ 886{
890 reg_gio_rw_intr_cfg intr_cfg; 887 reg_gio_rw_intr_cfg intr_cfg;
891 reg_gio_rw_intr_mask intr_mask; 888 reg_gio_rw_intr_mask intr_mask;
@@ -943,11 +940,13 @@ virtual_gpio_init(void)
943 940
944/* main driver initialization routine, called from mem.c */ 941/* main driver initialization routine, called from mem.c */
945 942
946static __init int 943static int __init gpio_init(void)
947gpio_init(void)
948{ 944{
949 int res; 945 int res;
950 946
947 printk(KERN_INFO "ETRAX FS GPIO driver v2.7, (c) 2003-2008 "
948 "Axis Communications AB\n");
949
951 /* do the formalities */ 950 /* do the formalities */
952 951
953 res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops); 952 res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops);
@@ -963,11 +962,12 @@ gpio_init(void)
963 CRIS_LED_DISK_READ(0); 962 CRIS_LED_DISK_READ(0);
964 CRIS_LED_DISK_WRITE(0); 963 CRIS_LED_DISK_WRITE(0);
965 964
966 printk(KERN_INFO "ETRAX FS GPIO driver v2.6, (c) 2003-2007 " 965 int res2 = request_irq(GIO_INTR_VECT, gpio_interrupt,
967 "Axis Communications AB\n"); 966 IRQF_SHARED | IRQF_DISABLED, "gpio", &alarmlist);
968 if (request_irq(GIO_INTR_VECT, gpio_interrupt, 967 if (res2) {
969 IRQF_SHARED | IRQF_DISABLED, "gpio", &alarmlist))
970 printk(KERN_ERR "err: irq for gpio\n"); 968 printk(KERN_ERR "err: irq for gpio\n");
969 return res2;
970 }
971 971
972 /* No IRQs by default. */ 972 /* No IRQs by default. */
973 REG_WR_INT(gio, regi_gio, rw_intr_pins, 0); 973 REG_WR_INT(gio, regi_gio, rw_intr_pins, 0);