diff options
author | Mikael Starvik <mikael.starvik@axis.com> | 2005-07-27 14:44:34 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-27 19:25:59 -0400 |
commit | 7e9204265b4ec6680fad9abc7a78b94087983916 (patch) | |
tree | 50ff709f7d37193bb56599a4e1646509d8e353ff /arch/cris/arch-v10/drivers | |
parent | 059163cabc01a15b9e2cf10e5de5b6dc06e0da1f (diff) |
[PATCH] CRIS update: drivers
Updates to device drivers.
* Use I/O and DMA allocators.
* Use wait_event_interruptible instead of interrutiple_sleep_on.
* Added spinlocks SMP.
* Changed restore_flags to local_irq_restore etc.
* Updated IDE driver include to fit 2.6.12.
Signed-off-by: Mikael Starvik <starvik@axis.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/cris/arch-v10/drivers')
-rw-r--r-- | arch/cris/arch-v10/drivers/axisflashmap.c | 5 | ||||
-rw-r--r-- | arch/cris/arch-v10/drivers/ds1302.c | 71 | ||||
-rw-r--r-- | arch/cris/arch-v10/drivers/eeprom.c | 29 | ||||
-rw-r--r-- | arch/cris/arch-v10/drivers/gpio.c | 201 | ||||
-rw-r--r-- | arch/cris/arch-v10/drivers/i2c.c | 62 | ||||
-rw-r--r-- | arch/cris/arch-v10/drivers/pcf8563.c | 20 |
6 files changed, 244 insertions, 144 deletions
diff --git a/arch/cris/arch-v10/drivers/axisflashmap.c b/arch/cris/arch-v10/drivers/axisflashmap.c index fb7d4855ea62..11ab3836aac6 100644 --- a/arch/cris/arch-v10/drivers/axisflashmap.c +++ b/arch/cris/arch-v10/drivers/axisflashmap.c | |||
@@ -11,6 +11,9 @@ | |||
11 | * partition split defined below. | 11 | * partition split defined below. |
12 | * | 12 | * |
13 | * $Log: axisflashmap.c,v $ | 13 | * $Log: axisflashmap.c,v $ |
14 | * Revision 1.11 2004/11/15 10:27:14 starvik | ||
15 | * Corrected typo (Thanks to Milton Miller <miltonm@bga.com>). | ||
16 | * | ||
14 | * Revision 1.10 2004/08/16 12:37:22 starvik | 17 | * Revision 1.10 2004/08/16 12:37:22 starvik |
15 | * Merge of Linux 2.6.8 | 18 | * Merge of Linux 2.6.8 |
16 | * | 19 | * |
@@ -161,7 +164,7 @@ | |||
161 | #elif CONFIG_ETRAX_FLASH_BUSWIDTH==2 | 164 | #elif CONFIG_ETRAX_FLASH_BUSWIDTH==2 |
162 | #define flash_data __u16 | 165 | #define flash_data __u16 |
163 | #elif CONFIG_ETRAX_FLASH_BUSWIDTH==4 | 166 | #elif CONFIG_ETRAX_FLASH_BUSWIDTH==4 |
164 | #define flash_data __u16 | 167 | #define flash_data __u32 |
165 | #endif | 168 | #endif |
166 | 169 | ||
167 | /* From head.S */ | 170 | /* From head.S */ |
diff --git a/arch/cris/arch-v10/drivers/ds1302.c b/arch/cris/arch-v10/drivers/ds1302.c index fba530fcfaeb..10795f67f687 100644 --- a/arch/cris/arch-v10/drivers/ds1302.c +++ b/arch/cris/arch-v10/drivers/ds1302.c | |||
@@ -7,6 +7,15 @@ | |||
7 | *! Functions exported: ds1302_readreg, ds1302_writereg, ds1302_init | 7 | *! Functions exported: ds1302_readreg, ds1302_writereg, ds1302_init |
8 | *! | 8 | *! |
9 | *! $Log: ds1302.c,v $ | 9 | *! $Log: ds1302.c,v $ |
10 | *! Revision 1.18 2005/01/24 09:11:26 mikaelam | ||
11 | *! Minor changes to get DS1302 RTC chip driver to work | ||
12 | *! | ||
13 | *! Revision 1.17 2005/01/05 06:11:22 starvik | ||
14 | *! No need to do local_irq_disable after local_irq_save. | ||
15 | *! | ||
16 | *! Revision 1.16 2004/12/13 12:21:52 starvik | ||
17 | *! Added I/O and DMA allocators from Linux 2.4 | ||
18 | *! | ||
10 | *! Revision 1.14 2004/08/24 06:48:43 starvik | 19 | *! Revision 1.14 2004/08/24 06:48:43 starvik |
11 | *! Whitespace cleanup | 20 | *! Whitespace cleanup |
12 | *! | 21 | *! |
@@ -124,9 +133,9 @@ | |||
124 | *! | 133 | *! |
125 | *! --------------------------------------------------------------------------- | 134 | *! --------------------------------------------------------------------------- |
126 | *! | 135 | *! |
127 | *! (C) Copyright 1999, 2000, 2001 Axis Communications AB, LUND, SWEDEN | 136 | *! (C) Copyright 1999, 2000, 2001, 2002, 2003, 2004 Axis Communications AB, LUND, SWEDEN |
128 | *! | 137 | *! |
129 | *! $Id: ds1302.c,v 1.14 2004/08/24 06:48:43 starvik Exp $ | 138 | *! $Id: ds1302.c,v 1.18 2005/01/24 09:11:26 mikaelam Exp $ |
130 | *! | 139 | *! |
131 | *!***************************************************************************/ | 140 | *!***************************************************************************/ |
132 | 141 | ||
@@ -145,6 +154,7 @@ | |||
145 | #include <asm/arch/svinto.h> | 154 | #include <asm/arch/svinto.h> |
146 | #include <asm/io.h> | 155 | #include <asm/io.h> |
147 | #include <asm/rtc.h> | 156 | #include <asm/rtc.h> |
157 | #include <asm/arch/io_interface_mux.h> | ||
148 | 158 | ||
149 | #define RTC_MAJOR_NR 121 /* local major, change later */ | 159 | #define RTC_MAJOR_NR 121 /* local major, change later */ |
150 | 160 | ||
@@ -320,7 +330,6 @@ get_rtc_time(struct rtc_time *rtc_tm) | |||
320 | unsigned long flags; | 330 | unsigned long flags; |
321 | 331 | ||
322 | local_irq_save(flags); | 332 | local_irq_save(flags); |
323 | local_irq_disable(); | ||
324 | 333 | ||
325 | rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS); | 334 | rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS); |
326 | rtc_tm->tm_min = CMOS_READ(RTC_MINUTES); | 335 | rtc_tm->tm_min = CMOS_READ(RTC_MINUTES); |
@@ -358,7 +367,7 @@ static int | |||
358 | rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 367 | rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, |
359 | unsigned long arg) | 368 | unsigned long arg) |
360 | { | 369 | { |
361 | unsigned long flags; | 370 | unsigned long flags; |
362 | 371 | ||
363 | switch(cmd) { | 372 | switch(cmd) { |
364 | case RTC_RD_TIME: /* read the time/date from RTC */ | 373 | case RTC_RD_TIME: /* read the time/date from RTC */ |
@@ -382,7 +391,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
382 | return -EPERM; | 391 | return -EPERM; |
383 | 392 | ||
384 | if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time))) | 393 | if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time))) |
385 | return -EFAULT; | 394 | return -EFAULT; |
386 | 395 | ||
387 | yrs = rtc_tm.tm_year + 1900; | 396 | yrs = rtc_tm.tm_year + 1900; |
388 | mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ | 397 | mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ |
@@ -419,7 +428,6 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
419 | BIN_TO_BCD(yrs); | 428 | BIN_TO_BCD(yrs); |
420 | 429 | ||
421 | local_irq_save(flags); | 430 | local_irq_save(flags); |
422 | local_irq_disable(); | ||
423 | CMOS_WRITE(yrs, RTC_YEAR); | 431 | CMOS_WRITE(yrs, RTC_YEAR); |
424 | CMOS_WRITE(mon, RTC_MONTH); | 432 | CMOS_WRITE(mon, RTC_MONTH); |
425 | CMOS_WRITE(day, RTC_DAY_OF_MONTH); | 433 | CMOS_WRITE(day, RTC_DAY_OF_MONTH); |
@@ -438,7 +446,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
438 | 446 | ||
439 | case RTC_SET_CHARGE: /* set the RTC TRICKLE CHARGE register */ | 447 | case RTC_SET_CHARGE: /* set the RTC TRICKLE CHARGE register */ |
440 | { | 448 | { |
441 | int tcs_val; | 449 | int tcs_val; |
442 | 450 | ||
443 | if (!capable(CAP_SYS_TIME)) | 451 | if (!capable(CAP_SYS_TIME)) |
444 | return -EPERM; | 452 | return -EPERM; |
@@ -492,8 +500,8 @@ print_rtc_status(void) | |||
492 | /* The various file operations we support. */ | 500 | /* The various file operations we support. */ |
493 | 501 | ||
494 | static struct file_operations rtc_fops = { | 502 | static struct file_operations rtc_fops = { |
495 | .owner = THIS_MODULE, | 503 | .owner = THIS_MODULE, |
496 | .ioctl = rtc_ioctl, | 504 | .ioctl = rtc_ioctl, |
497 | }; | 505 | }; |
498 | 506 | ||
499 | /* Probe for the chip by writing something to its RAM and try reading it back. */ | 507 | /* Probe for the chip by writing something to its RAM and try reading it back. */ |
@@ -532,7 +540,7 @@ ds1302_probe(void) | |||
532 | "PB", | 540 | "PB", |
533 | #endif | 541 | #endif |
534 | CONFIG_ETRAX_DS1302_RSTBIT); | 542 | CONFIG_ETRAX_DS1302_RSTBIT); |
535 | print_rtc_status(); | 543 | print_rtc_status(); |
536 | retval = 1; | 544 | retval = 1; |
537 | } else { | 545 | } else { |
538 | stop(); | 546 | stop(); |
@@ -548,7 +556,9 @@ ds1302_probe(void) | |||
548 | int __init | 556 | int __init |
549 | ds1302_init(void) | 557 | ds1302_init(void) |
550 | { | 558 | { |
559 | #ifdef CONFIG_ETRAX_I2C | ||
551 | i2c_init(); | 560 | i2c_init(); |
561 | #endif | ||
552 | 562 | ||
553 | if (!ds1302_probe()) { | 563 | if (!ds1302_probe()) { |
554 | #ifdef CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT | 564 | #ifdef CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT |
@@ -558,25 +568,42 @@ ds1302_init(void) | |||
558 | * | 568 | * |
559 | * Make sure that R_GEN_CONFIG is setup correct. | 569 | * Make sure that R_GEN_CONFIG is setup correct. |
560 | */ | 570 | */ |
561 | genconfig_shadow = ((genconfig_shadow & | 571 | /* Allocating the ATA interface will grab almost all |
562 | ~IO_MASK(R_GEN_CONFIG, ata)) | | 572 | * pins in I/O groups a, b, c and d. A consequence of |
563 | (IO_STATE(R_GEN_CONFIG, ata, select))); | 573 | * allocating the ATA interface is that the fixed |
564 | *R_GEN_CONFIG = genconfig_shadow; | 574 | * interfaces shared RAM, parallel port 0, parallel |
575 | * port 1, parallel port W, SCSI-8 port 0, SCSI-8 port | ||
576 | * 1, SCSI-W, serial port 2, serial port 3, | ||
577 | * synchronous serial port 3 and USB port 2 and almost | ||
578 | * all GPIO pins on port g cannot be used. | ||
579 | */ | ||
580 | if (cris_request_io_interface(if_ata, "ds1302/ATA")) { | ||
581 | printk(KERN_WARNING "ds1302: Failed to get IO interface\n"); | ||
582 | return -1; | ||
583 | } | ||
584 | |||
565 | #elif CONFIG_ETRAX_DS1302_RSTBIT == 0 | 585 | #elif CONFIG_ETRAX_DS1302_RSTBIT == 0 |
566 | 586 | if (cris_io_interface_allocate_pins(if_gpio_grp_a, | |
567 | /* Set the direction of this bit to out. */ | 587 | 'g', |
568 | genconfig_shadow = ((genconfig_shadow & | 588 | CONFIG_ETRAX_DS1302_RSTBIT, |
569 | ~IO_MASK(R_GEN_CONFIG, g0dir)) | | 589 | CONFIG_ETRAX_DS1302_RSTBIT)) { |
570 | (IO_STATE(R_GEN_CONFIG, g0dir, out))); | 590 | printk(KERN_WARNING "ds1302: Failed to get IO interface\n"); |
571 | *R_GEN_CONFIG = genconfig_shadow; | 591 | return -1; |
592 | } | ||
593 | |||
594 | /* Set the direction of this bit to out. */ | ||
595 | genconfig_shadow = ((genconfig_shadow & | ||
596 | ~IO_MASK(R_GEN_CONFIG, g0dir)) | | ||
597 | (IO_STATE(R_GEN_CONFIG, g0dir, out))); | ||
598 | *R_GEN_CONFIG = genconfig_shadow; | ||
572 | #endif | 599 | #endif |
573 | if (!ds1302_probe()) { | 600 | if (!ds1302_probe()) { |
574 | printk(KERN_WARNING "%s: RTC not found.\n", ds1302_name); | 601 | printk(KERN_WARNING "%s: RTC not found.\n", ds1302_name); |
575 | return -1; | 602 | return -1; |
576 | } | 603 | } |
577 | #else | 604 | #else |
578 | printk(KERN_WARNING "%s: RTC not found.\n", ds1302_name); | 605 | printk(KERN_WARNING "%s: RTC not found.\n", ds1302_name); |
579 | return -1; | 606 | return -1; |
580 | #endif | 607 | #endif |
581 | } | 608 | } |
582 | /* Initialise trickle charger */ | 609 | /* Initialise trickle charger */ |
diff --git a/arch/cris/arch-v10/drivers/eeprom.c b/arch/cris/arch-v10/drivers/eeprom.c index 316ca15d6802..512f16dec060 100644 --- a/arch/cris/arch-v10/drivers/eeprom.c +++ b/arch/cris/arch-v10/drivers/eeprom.c | |||
@@ -20,6 +20,12 @@ | |||
20 | *! in the spin-lock. | 20 | *! in the spin-lock. |
21 | *! | 21 | *! |
22 | *! $Log: eeprom.c,v $ | 22 | *! $Log: eeprom.c,v $ |
23 | *! Revision 1.12 2005/06/19 17:06:46 starvik | ||
24 | *! Merge of Linux 2.6.12. | ||
25 | *! | ||
26 | *! Revision 1.11 2005/01/26 07:14:46 starvik | ||
27 | *! Applied diff from kernel janitors (Nish Aravamudan). | ||
28 | *! | ||
23 | *! Revision 1.10 2003/09/11 07:29:48 starvik | 29 | *! Revision 1.10 2003/09/11 07:29:48 starvik |
24 | *! Merge of Linux 2.6.0-test5 | 30 | *! Merge of Linux 2.6.0-test5 |
25 | *! | 31 | *! |
@@ -94,6 +100,7 @@ | |||
94 | #include <linux/init.h> | 100 | #include <linux/init.h> |
95 | #include <linux/delay.h> | 101 | #include <linux/delay.h> |
96 | #include <linux/interrupt.h> | 102 | #include <linux/interrupt.h> |
103 | #include <linux/wait.h> | ||
97 | #include <asm/uaccess.h> | 104 | #include <asm/uaccess.h> |
98 | #include "i2c.h" | 105 | #include "i2c.h" |
99 | 106 | ||
@@ -526,15 +533,10 @@ static ssize_t eeprom_read(struct file * file, char * buf, size_t count, loff_t | |||
526 | return -EFAULT; | 533 | return -EFAULT; |
527 | } | 534 | } |
528 | 535 | ||
529 | while(eeprom.busy) | 536 | wait_event_interruptible(eeprom.wait_q, !eeprom.busy); |
530 | { | 537 | if (signal_pending(current)) |
531 | interruptible_sleep_on(&eeprom.wait_q); | 538 | return -EINTR; |
532 | 539 | ||
533 | /* bail out if we get interrupted */ | ||
534 | if (signal_pending(current)) | ||
535 | return -EINTR; | ||
536 | |||
537 | } | ||
538 | eeprom.busy++; | 540 | eeprom.busy++; |
539 | 541 | ||
540 | page = (unsigned char) (p >> 8); | 542 | page = (unsigned char) (p >> 8); |
@@ -604,13 +606,10 @@ static ssize_t eeprom_write(struct file * file, const char * buf, size_t count, | |||
604 | return -EFAULT; | 606 | return -EFAULT; |
605 | } | 607 | } |
606 | 608 | ||
607 | while(eeprom.busy) | 609 | wait_event_interruptible(eeprom.wait_q, !eeprom.busy); |
608 | { | 610 | /* bail out if we get interrupted */ |
609 | interruptible_sleep_on(&eeprom.wait_q); | 611 | if (signal_pending(current)) |
610 | /* bail out if we get interrupted */ | 612 | return -EINTR; |
611 | if (signal_pending(current)) | ||
612 | return -EINTR; | ||
613 | } | ||
614 | eeprom.busy++; | 613 | eeprom.busy++; |
615 | for(i = 0; (i < EEPROM_RETRIES) && (restart > 0); i++) | 614 | for(i = 0; (i < EEPROM_RETRIES) && (restart > 0); i++) |
616 | { | 615 | { |
diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c index c095de82a0da..09963fe299a7 100644 --- a/arch/cris/arch-v10/drivers/gpio.c +++ b/arch/cris/arch-v10/drivers/gpio.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: gpio.c,v 1.12 2004/08/24 07:19:59 starvik Exp $ | 1 | /* $Id: gpio.c,v 1.17 2005/06/19 17:06:46 starvik Exp $ |
2 | * | 2 | * |
3 | * Etrax general port I/O device | 3 | * Etrax general port I/O device |
4 | * | 4 | * |
@@ -9,6 +9,18 @@ | |||
9 | * Johan Adolfsson (read/set directions, write, port G) | 9 | * Johan Adolfsson (read/set directions, write, port G) |
10 | * | 10 | * |
11 | * $Log: gpio.c,v $ | 11 | * $Log: gpio.c,v $ |
12 | * Revision 1.17 2005/06/19 17:06:46 starvik | ||
13 | * Merge of Linux 2.6.12. | ||
14 | * | ||
15 | * Revision 1.16 2005/03/07 13:02:29 starvik | ||
16 | * Protect driver global states with spinlock | ||
17 | * | ||
18 | * Revision 1.15 2005/01/05 06:08:55 starvik | ||
19 | * No need to do local_irq_disable after local_irq_save. | ||
20 | * | ||
21 | * Revision 1.14 2004/12/13 12:21:52 starvik | ||
22 | * Added I/O and DMA allocators from Linux 2.4 | ||
23 | * | ||
12 | * Revision 1.12 2004/08/24 07:19:59 starvik | 24 | * Revision 1.12 2004/08/24 07:19:59 starvik |
13 | * Whitespace cleanup | 25 | * Whitespace cleanup |
14 | * | 26 | * |
@@ -142,6 +154,7 @@ | |||
142 | #include <asm/io.h> | 154 | #include <asm/io.h> |
143 | #include <asm/system.h> | 155 | #include <asm/system.h> |
144 | #include <asm/irq.h> | 156 | #include <asm/irq.h> |
157 | #include <asm/arch/io_interface_mux.h> | ||
145 | 158 | ||
146 | #define GPIO_MAJOR 120 /* experimental MAJOR number */ | 159 | #define GPIO_MAJOR 120 /* experimental MAJOR number */ |
147 | 160 | ||
@@ -194,6 +207,8 @@ static struct gpio_private *alarmlist = 0; | |||
194 | static int gpio_some_alarms = 0; /* Set if someone uses alarm */ | 207 | static int gpio_some_alarms = 0; /* Set if someone uses alarm */ |
195 | static unsigned long gpio_pa_irq_enabled_mask = 0; | 208 | static unsigned long gpio_pa_irq_enabled_mask = 0; |
196 | 209 | ||
210 | static DEFINE_SPINLOCK(gpio_lock); /* Protect directions etc */ | ||
211 | |||
197 | /* Port A and B use 8 bit access, but Port G is 32 bit */ | 212 | /* Port A and B use 8 bit access, but Port G is 32 bit */ |
198 | #define NUM_PORTS (GPIO_MINOR_B+1) | 213 | #define NUM_PORTS (GPIO_MINOR_B+1) |
199 | 214 | ||
@@ -241,6 +256,9 @@ static volatile unsigned char *dir_shadow[NUM_PORTS] = { | |||
241 | &port_pb_dir_shadow | 256 | &port_pb_dir_shadow |
242 | }; | 257 | }; |
243 | 258 | ||
259 | /* All bits in port g that can change dir. */ | ||
260 | static const unsigned long int changeable_dir_g_mask = 0x01FFFF01; | ||
261 | |||
244 | /* Port G is 32 bit, handle it special, some bits are both inputs | 262 | /* Port G is 32 bit, handle it special, some bits are both inputs |
245 | and outputs at the same time, only some of the bits can change direction | 263 | and outputs at the same time, only some of the bits can change direction |
246 | and some of them in groups of 8 bit. */ | 264 | and some of them in groups of 8 bit. */ |
@@ -260,6 +278,7 @@ gpio_poll(struct file *file, | |||
260 | unsigned int mask = 0; | 278 | unsigned int mask = 0; |
261 | struct gpio_private *priv = (struct gpio_private *)file->private_data; | 279 | struct gpio_private *priv = (struct gpio_private *)file->private_data; |
262 | unsigned long data; | 280 | unsigned long data; |
281 | spin_lock(&gpio_lock); | ||
263 | poll_wait(file, &priv->alarm_wq, wait); | 282 | poll_wait(file, &priv->alarm_wq, wait); |
264 | if (priv->minor == GPIO_MINOR_A) { | 283 | if (priv->minor == GPIO_MINOR_A) { |
265 | unsigned long flags; | 284 | unsigned long flags; |
@@ -270,10 +289,10 @@ gpio_poll(struct file *file, | |||
270 | */ | 289 | */ |
271 | tmp = ~data & priv->highalarm & 0xFF; | 290 | tmp = ~data & priv->highalarm & 0xFF; |
272 | tmp = (tmp << R_IRQ_MASK1_SET__pa0__BITNR); | 291 | tmp = (tmp << R_IRQ_MASK1_SET__pa0__BITNR); |
273 | save_flags(flags); cli(); | 292 | local_irq_save(flags); |
274 | gpio_pa_irq_enabled_mask |= tmp; | 293 | gpio_pa_irq_enabled_mask |= tmp; |
275 | *R_IRQ_MASK1_SET = tmp; | 294 | *R_IRQ_MASK1_SET = tmp; |
276 | restore_flags(flags); | 295 | local_irq_restore(flags); |
277 | 296 | ||
278 | } else if (priv->minor == GPIO_MINOR_B) | 297 | } else if (priv->minor == GPIO_MINOR_B) |
279 | data = *R_PORT_PB_DATA; | 298 | data = *R_PORT_PB_DATA; |
@@ -286,8 +305,11 @@ gpio_poll(struct file *file, | |||
286 | (~data & priv->lowalarm)) { | 305 | (~data & priv->lowalarm)) { |
287 | mask = POLLIN|POLLRDNORM; | 306 | mask = POLLIN|POLLRDNORM; |
288 | } | 307 | } |
308 | |||
309 | spin_unlock(&gpio_lock); | ||
289 | 310 | ||
290 | DP(printk("gpio_poll ready: mask 0x%08X\n", mask)); | 311 | DP(printk("gpio_poll ready: mask 0x%08X\n", mask)); |
312 | |||
291 | return mask; | 313 | return mask; |
292 | } | 314 | } |
293 | 315 | ||
@@ -296,6 +318,7 @@ int etrax_gpio_wake_up_check(void) | |||
296 | struct gpio_private *priv = alarmlist; | 318 | struct gpio_private *priv = alarmlist; |
297 | unsigned long data = 0; | 319 | unsigned long data = 0; |
298 | int ret = 0; | 320 | int ret = 0; |
321 | spin_lock(&gpio_lock); | ||
299 | while (priv) { | 322 | while (priv) { |
300 | if (USE_PORTS(priv)) { | 323 | if (USE_PORTS(priv)) { |
301 | data = *priv->port; | 324 | data = *priv->port; |
@@ -310,6 +333,7 @@ int etrax_gpio_wake_up_check(void) | |||
310 | } | 333 | } |
311 | priv = priv->next; | 334 | priv = priv->next; |
312 | } | 335 | } |
336 | spin_unlock(&gpio_lock); | ||
313 | return ret; | 337 | return ret; |
314 | } | 338 | } |
315 | 339 | ||
@@ -327,6 +351,7 @@ static irqreturn_t | |||
327 | gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 351 | gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
328 | { | 352 | { |
329 | unsigned long tmp; | 353 | unsigned long tmp; |
354 | spin_lock(&gpio_lock); | ||
330 | /* Find what PA interrupts are active */ | 355 | /* Find what PA interrupts are active */ |
331 | tmp = (*R_IRQ_READ1); | 356 | tmp = (*R_IRQ_READ1); |
332 | 357 | ||
@@ -337,6 +362,8 @@ gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
337 | *R_IRQ_MASK1_CLR = tmp; | 362 | *R_IRQ_MASK1_CLR = tmp; |
338 | gpio_pa_irq_enabled_mask &= ~tmp; | 363 | gpio_pa_irq_enabled_mask &= ~tmp; |
339 | 364 | ||
365 | spin_unlock(&gpio_lock); | ||
366 | |||
340 | if (gpio_some_alarms) { | 367 | if (gpio_some_alarms) { |
341 | return IRQ_RETVAL(etrax_gpio_wake_up_check()); | 368 | return IRQ_RETVAL(etrax_gpio_wake_up_check()); |
342 | } | 369 | } |
@@ -350,6 +377,9 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count, | |||
350 | struct gpio_private *priv = (struct gpio_private *)file->private_data; | 377 | struct gpio_private *priv = (struct gpio_private *)file->private_data; |
351 | unsigned char data, clk_mask, data_mask, write_msb; | 378 | unsigned char data, clk_mask, data_mask, write_msb; |
352 | unsigned long flags; | 379 | unsigned long flags; |
380 | |||
381 | spin_lock(&gpio_lock); | ||
382 | |||
353 | ssize_t retval = count; | 383 | ssize_t retval = count; |
354 | if (priv->minor !=GPIO_MINOR_A && priv->minor != GPIO_MINOR_B) { | 384 | if (priv->minor !=GPIO_MINOR_A && priv->minor != GPIO_MINOR_B) { |
355 | return -EFAULT; | 385 | return -EFAULT; |
@@ -372,7 +402,7 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count, | |||
372 | data = *buf++; | 402 | data = *buf++; |
373 | if (priv->write_msb) { | 403 | if (priv->write_msb) { |
374 | for (i = 7; i >= 0;i--) { | 404 | for (i = 7; i >= 0;i--) { |
375 | local_irq_save(flags); local_irq_disable(); | 405 | local_irq_save(flags); |
376 | *priv->port = *priv->shadow &= ~clk_mask; | 406 | *priv->port = *priv->shadow &= ~clk_mask; |
377 | if (data & 1<<i) | 407 | if (data & 1<<i) |
378 | *priv->port = *priv->shadow |= data_mask; | 408 | *priv->port = *priv->shadow |= data_mask; |
@@ -384,7 +414,7 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count, | |||
384 | } | 414 | } |
385 | } else { | 415 | } else { |
386 | for (i = 0; i <= 7;i++) { | 416 | for (i = 0; i <= 7;i++) { |
387 | local_irq_save(flags); local_irq_disable(); | 417 | local_irq_save(flags); |
388 | *priv->port = *priv->shadow &= ~clk_mask; | 418 | *priv->port = *priv->shadow &= ~clk_mask; |
389 | if (data & 1<<i) | 419 | if (data & 1<<i) |
390 | *priv->port = *priv->shadow |= data_mask; | 420 | *priv->port = *priv->shadow |= data_mask; |
@@ -396,6 +426,7 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count, | |||
396 | } | 426 | } |
397 | } | 427 | } |
398 | } | 428 | } |
429 | spin_unlock(&gpio_lock); | ||
399 | return retval; | 430 | return retval; |
400 | } | 431 | } |
401 | 432 | ||
@@ -452,9 +483,14 @@ gpio_open(struct inode *inode, struct file *filp) | |||
452 | static int | 483 | static int |
453 | gpio_release(struct inode *inode, struct file *filp) | 484 | gpio_release(struct inode *inode, struct file *filp) |
454 | { | 485 | { |
455 | struct gpio_private *p = alarmlist; | 486 | struct gpio_private *p; |
456 | struct gpio_private *todel = (struct gpio_private *)filp->private_data; | 487 | struct gpio_private *todel; |
457 | 488 | ||
489 | spin_lock(&gpio_lock); | ||
490 | |||
491 | p = alarmlist; | ||
492 | todel = (struct gpio_private *)filp->private_data; | ||
493 | |||
458 | /* unlink from alarmlist and free the private structure */ | 494 | /* unlink from alarmlist and free the private structure */ |
459 | 495 | ||
460 | if (p == todel) { | 496 | if (p == todel) { |
@@ -476,7 +512,7 @@ gpio_release(struct inode *inode, struct file *filp) | |||
476 | p = p->next; | 512 | p = p->next; |
477 | } | 513 | } |
478 | gpio_some_alarms = 0; | 514 | gpio_some_alarms = 0; |
479 | 515 | spin_unlock(&gpio_lock); | |
480 | return 0; | 516 | return 0; |
481 | } | 517 | } |
482 | 518 | ||
@@ -491,14 +527,14 @@ unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg) | |||
491 | */ | 527 | */ |
492 | unsigned long flags; | 528 | unsigned long flags; |
493 | if (USE_PORTS(priv)) { | 529 | if (USE_PORTS(priv)) { |
494 | local_irq_save(flags); local_irq_disable(); | 530 | local_irq_save(flags); |
495 | *priv->dir = *priv->dir_shadow &= | 531 | *priv->dir = *priv->dir_shadow &= |
496 | ~((unsigned char)arg & priv->changeable_dir); | 532 | ~((unsigned char)arg & priv->changeable_dir); |
497 | local_irq_restore(flags); | 533 | local_irq_restore(flags); |
498 | return ~(*priv->dir_shadow) & 0xFF; /* Only 8 bits */ | 534 | return ~(*priv->dir_shadow) & 0xFF; /* Only 8 bits */ |
499 | } else if (priv->minor == GPIO_MINOR_G) { | 535 | } else if (priv->minor == GPIO_MINOR_G) { |
500 | /* We must fiddle with R_GEN_CONFIG to change dir */ | 536 | /* We must fiddle with R_GEN_CONFIG to change dir */ |
501 | save_flags(flags); cli(); | 537 | local_irq_save(flags); |
502 | if (((arg & dir_g_in_bits) != arg) && | 538 | if (((arg & dir_g_in_bits) != arg) && |
503 | (arg & changeable_dir_g)) { | 539 | (arg & changeable_dir_g)) { |
504 | arg &= changeable_dir_g; | 540 | arg &= changeable_dir_g; |
@@ -533,7 +569,7 @@ unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg) | |||
533 | /* Must be a >120 ns delay before writing this again */ | 569 | /* Must be a >120 ns delay before writing this again */ |
534 | 570 | ||
535 | } | 571 | } |
536 | restore_flags(flags); | 572 | local_irq_restore(flags); |
537 | return dir_g_in_bits; | 573 | return dir_g_in_bits; |
538 | } | 574 | } |
539 | return 0; | 575 | return 0; |
@@ -543,14 +579,14 @@ unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg) | |||
543 | { | 579 | { |
544 | unsigned long flags; | 580 | unsigned long flags; |
545 | if (USE_PORTS(priv)) { | 581 | if (USE_PORTS(priv)) { |
546 | local_irq_save(flags); local_irq_disable(); | 582 | local_irq_save(flags); |
547 | *priv->dir = *priv->dir_shadow |= | 583 | *priv->dir = *priv->dir_shadow |= |
548 | ((unsigned char)arg & priv->changeable_dir); | 584 | ((unsigned char)arg & priv->changeable_dir); |
549 | local_irq_restore(flags); | 585 | local_irq_restore(flags); |
550 | return *priv->dir_shadow; | 586 | return *priv->dir_shadow; |
551 | } else if (priv->minor == GPIO_MINOR_G) { | 587 | } else if (priv->minor == GPIO_MINOR_G) { |
552 | /* We must fiddle with R_GEN_CONFIG to change dir */ | 588 | /* We must fiddle with R_GEN_CONFIG to change dir */ |
553 | save_flags(flags); cli(); | 589 | local_irq_save(flags); |
554 | if (((arg & dir_g_out_bits) != arg) && | 590 | if (((arg & dir_g_out_bits) != arg) && |
555 | (arg & changeable_dir_g)) { | 591 | (arg & changeable_dir_g)) { |
556 | /* Set bits in genconfig to set to output */ | 592 | /* Set bits in genconfig to set to output */ |
@@ -583,7 +619,7 @@ unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg) | |||
583 | *R_GEN_CONFIG = genconfig_shadow; | 619 | *R_GEN_CONFIG = genconfig_shadow; |
584 | /* Must be a >120 ns delay before writing this again */ | 620 | /* Must be a >120 ns delay before writing this again */ |
585 | } | 621 | } |
586 | restore_flags(flags); | 622 | local_irq_restore(flags); |
587 | return dir_g_out_bits & 0x7FFFFFFF; | 623 | return dir_g_out_bits & 0x7FFFFFFF; |
588 | } | 624 | } |
589 | return 0; | 625 | return 0; |
@@ -598,22 +634,26 @@ gpio_ioctl(struct inode *inode, struct file *file, | |||
598 | { | 634 | { |
599 | unsigned long flags; | 635 | unsigned long flags; |
600 | unsigned long val; | 636 | unsigned long val; |
637 | int ret = 0; | ||
638 | |||
601 | struct gpio_private *priv = (struct gpio_private *)file->private_data; | 639 | struct gpio_private *priv = (struct gpio_private *)file->private_data; |
602 | if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) { | 640 | if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) { |
603 | return -EINVAL; | 641 | return -EINVAL; |
604 | } | 642 | } |
605 | 643 | ||
644 | spin_lock(&gpio_lock); | ||
645 | |||
606 | switch (_IOC_NR(cmd)) { | 646 | switch (_IOC_NR(cmd)) { |
607 | case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */ | 647 | case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */ |
608 | // read the port | 648 | // read the port |
609 | if (USE_PORTS(priv)) { | 649 | if (USE_PORTS(priv)) { |
610 | return *priv->port; | 650 | ret = *priv->port; |
611 | } else if (priv->minor == GPIO_MINOR_G) { | 651 | } else if (priv->minor == GPIO_MINOR_G) { |
612 | return (*R_PORT_G_DATA) & 0x7FFFFFFF; | 652 | ret = (*R_PORT_G_DATA) & 0x7FFFFFFF; |
613 | } | 653 | } |
614 | break; | 654 | break; |
615 | case IO_SETBITS: | 655 | case IO_SETBITS: |
616 | local_irq_save(flags); local_irq_disable(); | 656 | local_irq_save(flags); |
617 | // set changeable bits with a 1 in arg | 657 | // set changeable bits with a 1 in arg |
618 | if (USE_PORTS(priv)) { | 658 | if (USE_PORTS(priv)) { |
619 | *priv->port = *priv->shadow |= | 659 | *priv->port = *priv->shadow |= |
@@ -624,7 +664,7 @@ gpio_ioctl(struct inode *inode, struct file *file, | |||
624 | local_irq_restore(flags); | 664 | local_irq_restore(flags); |
625 | break; | 665 | break; |
626 | case IO_CLRBITS: | 666 | case IO_CLRBITS: |
627 | local_irq_save(flags); local_irq_disable(); | 667 | local_irq_save(flags); |
628 | // clear changeable bits with a 1 in arg | 668 | // clear changeable bits with a 1 in arg |
629 | if (USE_PORTS(priv)) { | 669 | if (USE_PORTS(priv)) { |
630 | *priv->port = *priv->shadow &= | 670 | *priv->port = *priv->shadow &= |
@@ -666,33 +706,34 @@ gpio_ioctl(struct inode *inode, struct file *file, | |||
666 | case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */ | 706 | case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */ |
667 | /* Read direction 0=input 1=output */ | 707 | /* Read direction 0=input 1=output */ |
668 | if (USE_PORTS(priv)) { | 708 | if (USE_PORTS(priv)) { |
669 | return *priv->dir_shadow; | 709 | ret = *priv->dir_shadow; |
670 | } else if (priv->minor == GPIO_MINOR_G) { | 710 | } else if (priv->minor == GPIO_MINOR_G) { |
671 | /* Note: Some bits are both in and out, | 711 | /* Note: Some bits are both in and out, |
672 | * Those that are dual is set here as well. | 712 | * Those that are dual is set here as well. |
673 | */ | 713 | */ |
674 | return (dir_g_shadow | dir_g_out_bits) & 0x7FFFFFFF; | 714 | ret = (dir_g_shadow | dir_g_out_bits) & 0x7FFFFFFF; |
675 | } | 715 | } |
716 | break; | ||
676 | case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */ | 717 | case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */ |
677 | /* Set direction 0=unchanged 1=input, | 718 | /* Set direction 0=unchanged 1=input, |
678 | * return mask with 1=input | 719 | * return mask with 1=input |
679 | */ | 720 | */ |
680 | return setget_input(priv, arg) & 0x7FFFFFFF; | 721 | ret = setget_input(priv, arg) & 0x7FFFFFFF; |
681 | break; | 722 | break; |
682 | case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */ | 723 | case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */ |
683 | /* Set direction 0=unchanged 1=output, | 724 | /* Set direction 0=unchanged 1=output, |
684 | * return mask with 1=output | 725 | * return mask with 1=output |
685 | */ | 726 | */ |
686 | return setget_output(priv, arg) & 0x7FFFFFFF; | 727 | ret = setget_output(priv, arg) & 0x7FFFFFFF; |
687 | 728 | break; | |
688 | case IO_SHUTDOWN: | 729 | case IO_SHUTDOWN: |
689 | SOFT_SHUTDOWN(); | 730 | SOFT_SHUTDOWN(); |
690 | break; | 731 | break; |
691 | case IO_GET_PWR_BT: | 732 | case IO_GET_PWR_BT: |
692 | #if defined (CONFIG_ETRAX_SOFT_SHUTDOWN) | 733 | #if defined (CONFIG_ETRAX_SOFT_SHUTDOWN) |
693 | return (*R_PORT_G_DATA & ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT)); | 734 | ret = (*R_PORT_G_DATA & ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT)); |
694 | #else | 735 | #else |
695 | return 0; | 736 | ret = 0; |
696 | #endif | 737 | #endif |
697 | break; | 738 | break; |
698 | case IO_CFG_WRITE_MODE: | 739 | case IO_CFG_WRITE_MODE: |
@@ -709,7 +750,7 @@ gpio_ioctl(struct inode *inode, struct file *file, | |||
709 | { | 750 | { |
710 | priv->clk_mask = 0; | 751 | priv->clk_mask = 0; |
711 | priv->data_mask = 0; | 752 | priv->data_mask = 0; |
712 | return -EPERM; | 753 | ret = -EPERM; |
713 | } | 754 | } |
714 | break; | 755 | break; |
715 | case IO_READ_INBITS: | 756 | case IO_READ_INBITS: |
@@ -720,8 +761,7 @@ gpio_ioctl(struct inode *inode, struct file *file, | |||
720 | val = *R_PORT_G_DATA; | 761 | val = *R_PORT_G_DATA; |
721 | } | 762 | } |
722 | if (copy_to_user((unsigned long*)arg, &val, sizeof(val))) | 763 | if (copy_to_user((unsigned long*)arg, &val, sizeof(val))) |
723 | return -EFAULT; | 764 | ret = -EFAULT; |
724 | return 0; | ||
725 | break; | 765 | break; |
726 | case IO_READ_OUTBITS: | 766 | case IO_READ_OUTBITS: |
727 | /* *arg is result of reading the output shadow */ | 767 | /* *arg is result of reading the output shadow */ |
@@ -731,36 +771,43 @@ gpio_ioctl(struct inode *inode, struct file *file, | |||
731 | val = port_g_data_shadow; | 771 | val = port_g_data_shadow; |
732 | } | 772 | } |
733 | if (copy_to_user((unsigned long*)arg, &val, sizeof(val))) | 773 | if (copy_to_user((unsigned long*)arg, &val, sizeof(val))) |
734 | return -EFAULT; | 774 | ret = -EFAULT; |
735 | break; | 775 | break; |
736 | case IO_SETGET_INPUT: | 776 | case IO_SETGET_INPUT: |
737 | /* bits set in *arg is set to input, | 777 | /* bits set in *arg is set to input, |
738 | * *arg updated with current input pins. | 778 | * *arg updated with current input pins. |
739 | */ | 779 | */ |
740 | if (copy_from_user(&val, (unsigned long*)arg, sizeof(val))) | 780 | if (copy_from_user(&val, (unsigned long*)arg, sizeof(val))) |
741 | return -EFAULT; | 781 | { |
782 | ret = -EFAULT; | ||
783 | break; | ||
784 | } | ||
742 | val = setget_input(priv, val); | 785 | val = setget_input(priv, val); |
743 | if (copy_to_user((unsigned long*)arg, &val, sizeof(val))) | 786 | if (copy_to_user((unsigned long*)arg, &val, sizeof(val))) |
744 | return -EFAULT; | 787 | ret = -EFAULT; |
745 | break; | 788 | break; |
746 | case IO_SETGET_OUTPUT: | 789 | case IO_SETGET_OUTPUT: |
747 | /* bits set in *arg is set to output, | 790 | /* bits set in *arg is set to output, |
748 | * *arg updated with current output pins. | 791 | * *arg updated with current output pins. |
749 | */ | 792 | */ |
750 | if (copy_from_user(&val, (unsigned long*)arg, sizeof(val))) | 793 | if (copy_from_user(&val, (unsigned long*)arg, sizeof(val))) |
751 | return -EFAULT; | 794 | { |
795 | ret = -EFAULT; | ||
796 | break; | ||
797 | } | ||
752 | val = setget_output(priv, val); | 798 | val = setget_output(priv, val); |
753 | if (copy_to_user((unsigned long*)arg, &val, sizeof(val))) | 799 | if (copy_to_user((unsigned long*)arg, &val, sizeof(val))) |
754 | return -EFAULT; | 800 | ret = -EFAULT; |
755 | break; | 801 | break; |
756 | default: | 802 | default: |
757 | if (priv->minor == GPIO_MINOR_LEDS) | 803 | if (priv->minor == GPIO_MINOR_LEDS) |
758 | return gpio_leds_ioctl(cmd, arg); | 804 | ret = gpio_leds_ioctl(cmd, arg); |
759 | else | 805 | else |
760 | return -EINVAL; | 806 | ret = -EINVAL; |
761 | } /* switch */ | 807 | } /* switch */ |
762 | 808 | ||
763 | return 0; | 809 | spin_unlock(&gpio_lock); |
810 | return ret; | ||
764 | } | 811 | } |
765 | 812 | ||
766 | static int | 813 | static int |
@@ -802,60 +849,20 @@ struct file_operations gpio_fops = { | |||
802 | }; | 849 | }; |
803 | 850 | ||
804 | 851 | ||
805 | static void __init gpio_init_port_g(void) | 852 | void ioif_watcher(const unsigned int gpio_in_available, |
853 | const unsigned int gpio_out_available, | ||
854 | const unsigned char pa_available, | ||
855 | const unsigned char pb_available) | ||
806 | { | 856 | { |
807 | #define GROUPA (0x0000FF3F) | 857 | unsigned long int flags; |
808 | #define GROUPB (1<<6 | 1<<7) | 858 | D(printk("gpio.c: ioif_watcher called\n")); |
809 | #define GROUPC (1<<30 | 1<<31) | 859 | D(printk("gpio.c: G in: 0x%08x G out: 0x%08x PA: 0x%02x PB: 0x%02x\n", |
810 | #define GROUPD (0x3FFF0000) | 860 | gpio_in_available, gpio_out_available, pa_available, pb_available)); |
811 | #define GROUPD_LOW (0x00FF0000) | ||
812 | unsigned long used_in_bits = 0; | ||
813 | unsigned long used_out_bits = 0; | ||
814 | if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi0, select)){ | ||
815 | used_in_bits |= GROUPA | GROUPB | 0 | 0; | ||
816 | used_out_bits |= GROUPA | GROUPB | 0 | 0; | ||
817 | } | ||
818 | if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ata, select)) { | ||
819 | used_in_bits |= GROUPA | GROUPB | GROUPC | (GROUPD & ~(1<<25|1<<26)); | ||
820 | used_out_bits |= GROUPA | GROUPB | GROUPC | GROUPD; | ||
821 | } | ||
822 | 861 | ||
823 | if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, par0, select)) { | 862 | spin_lock_irqsave(&gpio_lock, flags); |
824 | used_in_bits |= (GROUPA & ~(1<<0)) | 0 | 0 | 0; | ||
825 | used_out_bits |= (GROUPA & ~(1<<0)) | 0 | 0 | 0; | ||
826 | } | ||
827 | if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ser2, select)) { | ||
828 | used_in_bits |= 0 | GROUPB | 0 | 0; | ||
829 | used_out_bits |= 0 | GROUPB | 0 | 0; | ||
830 | } | ||
831 | /* mio same as shared RAM ? */ | ||
832 | if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, mio, select)) { | ||
833 | used_in_bits |= (GROUPA & ~(1<<0)) | 0 |0 |GROUPD_LOW; | ||
834 | used_out_bits |= (GROUPA & ~(1<<0|1<<1|1<<2)) | 0 |0 |GROUPD_LOW; | ||
835 | } | ||
836 | if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi1, select)) { | ||
837 | used_in_bits |= 0 | 0 | GROUPC | GROUPD; | ||
838 | used_out_bits |= 0 | 0 | GROUPC | GROUPD; | ||
839 | } | ||
840 | if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi0w, select)) { | ||
841 | used_in_bits |= GROUPA | GROUPB | 0 | (GROUPD_LOW | 1<<24); | ||
842 | used_out_bits |= GROUPA | GROUPB | 0 | (GROUPD_LOW | 1<<24 | 1<<25|1<<26); | ||
843 | } | ||
844 | 863 | ||
845 | if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, par1, select)) { | 864 | dir_g_in_bits = gpio_in_available; |
846 | used_in_bits |= 0 | 0 | 0 | (GROUPD & ~(1<<24)); | 865 | dir_g_out_bits = gpio_out_available; |
847 | used_out_bits |= 0 | 0 | 0 | (GROUPD & ~(1<<24)); | ||
848 | } | ||
849 | if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ser3, select)) { | ||
850 | used_in_bits |= 0 | 0 | GROUPC | 0; | ||
851 | used_out_bits |= 0 | 0 | GROUPC | 0; | ||
852 | } | ||
853 | /* mio same as shared RAM-W? */ | ||
854 | if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, mio_w, select)) { | ||
855 | used_in_bits |= (GROUPA & ~(1<<0)) | 0 | 0 |GROUPD_LOW; | ||
856 | used_out_bits |= (GROUPA & ~(1<<0|1<<1|1<<2)) | 0 | 0 |GROUPD_LOW; | ||
857 | } | ||
858 | /* TODO: USB p2, parw, sync ser3? */ | ||
859 | 866 | ||
860 | /* Initialise the dir_g_shadow etc. depending on genconfig */ | 867 | /* Initialise the dir_g_shadow etc. depending on genconfig */ |
861 | /* 0=input 1=output */ | 868 | /* 0=input 1=output */ |
@@ -868,10 +875,7 @@ static void __init gpio_init_port_g(void) | |||
868 | if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g24dir, out)) | 875 | if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g24dir, out)) |
869 | dir_g_shadow |= (1 << 24); | 876 | dir_g_shadow |= (1 << 24); |
870 | 877 | ||
871 | dir_g_in_bits = ~used_in_bits; | 878 | changeable_dir_g = changeable_dir_g_mask; |
872 | dir_g_out_bits = ~used_out_bits; | ||
873 | |||
874 | changeable_dir_g = 0x01FFFF01; /* all that can change dir */ | ||
875 | changeable_dir_g &= dir_g_out_bits; | 879 | changeable_dir_g &= dir_g_out_bits; |
876 | changeable_dir_g &= dir_g_in_bits; | 880 | changeable_dir_g &= dir_g_in_bits; |
877 | /* Correct the bits that can change direction */ | 881 | /* Correct the bits that can change direction */ |
@@ -880,6 +884,7 @@ static void __init gpio_init_port_g(void) | |||
880 | dir_g_in_bits &= ~changeable_dir_g; | 884 | dir_g_in_bits &= ~changeable_dir_g; |
881 | dir_g_in_bits |= (~dir_g_shadow & changeable_dir_g); | 885 | dir_g_in_bits |= (~dir_g_shadow & changeable_dir_g); |
882 | 886 | ||
887 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
883 | 888 | ||
884 | printk(KERN_INFO "GPIO port G: in_bits: 0x%08lX out_bits: 0x%08lX val: %08lX\n", | 889 | printk(KERN_INFO "GPIO port G: in_bits: 0x%08lX out_bits: 0x%08lX val: %08lX\n", |
885 | dir_g_in_bits, dir_g_out_bits, (unsigned long)*R_PORT_G_DATA); | 890 | dir_g_in_bits, dir_g_out_bits, (unsigned long)*R_PORT_G_DATA); |
@@ -896,6 +901,7 @@ gpio_init(void) | |||
896 | #if defined (CONFIG_ETRAX_CSP0_LEDS) | 901 | #if defined (CONFIG_ETRAX_CSP0_LEDS) |
897 | int i; | 902 | int i; |
898 | #endif | 903 | #endif |
904 | printk("gpio init\n"); | ||
899 | 905 | ||
900 | /* do the formalities */ | 906 | /* do the formalities */ |
901 | 907 | ||
@@ -919,8 +925,13 @@ gpio_init(void) | |||
919 | #endif | 925 | #endif |
920 | 926 | ||
921 | #endif | 927 | #endif |
922 | gpio_init_port_g(); | 928 | /* The I/O interface allocation watcher will be called when |
923 | printk(KERN_INFO "ETRAX 100LX GPIO driver v2.5, (c) 2001, 2002 Axis Communications AB\n"); | 929 | * registering it. */ |
930 | if (cris_io_interface_register_watcher(ioif_watcher)){ | ||
931 | printk(KERN_WARNING "gpio_init: Failed to install IO if allocator watcher\n"); | ||
932 | } | ||
933 | |||
934 | printk(KERN_INFO "ETRAX 100LX GPIO driver v2.5, (c) 2001, 2002, 2003, 2004 Axis Communications AB\n"); | ||
924 | /* We call etrax_gpio_wake_up_check() from timer interrupt and | 935 | /* We call etrax_gpio_wake_up_check() from timer interrupt and |
925 | * from cpu_idle() in kernel/process.c | 936 | * from cpu_idle() in kernel/process.c |
926 | * The check in cpu_idle() reduces latency from ~15 ms to ~6 ms | 937 | * The check in cpu_idle() reduces latency from ~15 ms to ~6 ms |
diff --git a/arch/cris/arch-v10/drivers/i2c.c b/arch/cris/arch-v10/drivers/i2c.c index 8bbe233ba7b1..b38267d60d30 100644 --- a/arch/cris/arch-v10/drivers/i2c.c +++ b/arch/cris/arch-v10/drivers/i2c.c | |||
@@ -12,6 +12,15 @@ | |||
12 | *! don't use PB_I2C if DS1302 uses same bits, | 12 | *! don't use PB_I2C if DS1302 uses same bits, |
13 | *! use PB. | 13 | *! use PB. |
14 | *! $Log: i2c.c,v $ | 14 | *! $Log: i2c.c,v $ |
15 | *! Revision 1.13 2005/03/07 13:13:07 starvik | ||
16 | *! Added spinlocks to protect states etc | ||
17 | *! | ||
18 | *! Revision 1.12 2005/01/05 06:11:22 starvik | ||
19 | *! No need to do local_irq_disable after local_irq_save. | ||
20 | *! | ||
21 | *! Revision 1.11 2004/12/13 12:21:52 starvik | ||
22 | *! Added I/O and DMA allocators from Linux 2.4 | ||
23 | *! | ||
15 | *! Revision 1.9 2004/08/24 06:49:14 starvik | 24 | *! Revision 1.9 2004/08/24 06:49:14 starvik |
16 | *! Whitespace cleanup | 25 | *! Whitespace cleanup |
17 | *! | 26 | *! |
@@ -75,7 +84,7 @@ | |||
75 | *! (C) Copyright 1999-2002 Axis Communications AB, LUND, SWEDEN | 84 | *! (C) Copyright 1999-2002 Axis Communications AB, LUND, SWEDEN |
76 | *! | 85 | *! |
77 | *!***************************************************************************/ | 86 | *!***************************************************************************/ |
78 | /* $Id: i2c.c,v 1.9 2004/08/24 06:49:14 starvik Exp $ */ | 87 | /* $Id: i2c.c,v 1.13 2005/03/07 13:13:07 starvik Exp $ */ |
79 | 88 | ||
80 | /****************** INCLUDE FILES SECTION ***********************************/ | 89 | /****************** INCLUDE FILES SECTION ***********************************/ |
81 | 90 | ||
@@ -95,6 +104,7 @@ | |||
95 | #include <asm/arch/svinto.h> | 104 | #include <asm/arch/svinto.h> |
96 | #include <asm/io.h> | 105 | #include <asm/io.h> |
97 | #include <asm/delay.h> | 106 | #include <asm/delay.h> |
107 | #include <asm/arch/io_interface_mux.h> | ||
98 | 108 | ||
99 | #include "i2c.h" | 109 | #include "i2c.h" |
100 | 110 | ||
@@ -184,6 +194,7 @@ static const char i2c_name[] = "i2c"; | |||
184 | 194 | ||
185 | #define i2c_delay(usecs) udelay(usecs) | 195 | #define i2c_delay(usecs) udelay(usecs) |
186 | 196 | ||
197 | static DEFINE_SPINLOCK(i2c_lock); /* Protect directions etc */ | ||
187 | 198 | ||
188 | /****************** FUNCTION DEFINITION SECTION *************************/ | 199 | /****************** FUNCTION DEFINITION SECTION *************************/ |
189 | 200 | ||
@@ -488,13 +499,14 @@ i2c_writereg(unsigned char theSlave, unsigned char theReg, | |||
488 | int error, cntr = 3; | 499 | int error, cntr = 3; |
489 | unsigned long flags; | 500 | unsigned long flags; |
490 | 501 | ||
502 | spin_lock(&i2c_lock); | ||
503 | |||
491 | do { | 504 | do { |
492 | error = 0; | 505 | error = 0; |
493 | /* | 506 | /* |
494 | * we don't like to be interrupted | 507 | * we don't like to be interrupted |
495 | */ | 508 | */ |
496 | local_irq_save(flags); | 509 | local_irq_save(flags); |
497 | local_irq_disable(); | ||
498 | 510 | ||
499 | i2c_start(); | 511 | i2c_start(); |
500 | /* | 512 | /* |
@@ -538,6 +550,8 @@ i2c_writereg(unsigned char theSlave, unsigned char theReg, | |||
538 | 550 | ||
539 | i2c_delay(CLOCK_LOW_TIME); | 551 | i2c_delay(CLOCK_LOW_TIME); |
540 | 552 | ||
553 | spin_unlock(&i2c_lock); | ||
554 | |||
541 | return -error; | 555 | return -error; |
542 | } | 556 | } |
543 | 557 | ||
@@ -555,13 +569,14 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg) | |||
555 | int error, cntr = 3; | 569 | int error, cntr = 3; |
556 | unsigned long flags; | 570 | unsigned long flags; |
557 | 571 | ||
572 | spin_lock(&i2c_lock); | ||
573 | |||
558 | do { | 574 | do { |
559 | error = 0; | 575 | error = 0; |
560 | /* | 576 | /* |
561 | * we don't like to be interrupted | 577 | * we don't like to be interrupted |
562 | */ | 578 | */ |
563 | local_irq_save(flags); | 579 | local_irq_save(flags); |
564 | local_irq_disable(); | ||
565 | /* | 580 | /* |
566 | * generate start condition | 581 | * generate start condition |
567 | */ | 582 | */ |
@@ -620,6 +635,8 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg) | |||
620 | 635 | ||
621 | } while(error && cntr--); | 636 | } while(error && cntr--); |
622 | 637 | ||
638 | spin_unlock(&i2c_lock); | ||
639 | |||
623 | return b; | 640 | return b; |
624 | } | 641 | } |
625 | 642 | ||
@@ -686,15 +703,26 @@ static struct file_operations i2c_fops = { | |||
686 | int __init | 703 | int __init |
687 | i2c_init(void) | 704 | i2c_init(void) |
688 | { | 705 | { |
706 | static int res = 0; | ||
707 | static int first = 1; | ||
708 | |||
709 | if (!first) { | ||
710 | return res; | ||
711 | } | ||
712 | |||
689 | /* Setup and enable the Port B I2C interface */ | 713 | /* Setup and enable the Port B I2C interface */ |
690 | 714 | ||
691 | #ifndef CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C | 715 | #ifndef CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C |
716 | if ((res = cris_request_io_interface(if_i2c, "I2C"))) { | ||
717 | printk(KERN_CRIT "i2c_init: Failed to get IO interface\n"); | ||
718 | return res; | ||
719 | } | ||
720 | |||
692 | *R_PORT_PB_I2C = port_pb_i2c_shadow |= | 721 | *R_PORT_PB_I2C = port_pb_i2c_shadow |= |
693 | IO_STATE(R_PORT_PB_I2C, i2c_en, on) | | 722 | IO_STATE(R_PORT_PB_I2C, i2c_en, on) | |
694 | IO_FIELD(R_PORT_PB_I2C, i2c_d, 1) | | 723 | IO_FIELD(R_PORT_PB_I2C, i2c_d, 1) | |
695 | IO_FIELD(R_PORT_PB_I2C, i2c_clk, 1) | | 724 | IO_FIELD(R_PORT_PB_I2C, i2c_clk, 1) | |
696 | IO_STATE(R_PORT_PB_I2C, i2c_oe_, enable); | 725 | IO_STATE(R_PORT_PB_I2C, i2c_oe_, enable); |
697 | #endif | ||
698 | 726 | ||
699 | port_pb_dir_shadow &= ~IO_MASK(R_PORT_PB_DIR, dir0); | 727 | port_pb_dir_shadow &= ~IO_MASK(R_PORT_PB_DIR, dir0); |
700 | port_pb_dir_shadow &= ~IO_MASK(R_PORT_PB_DIR, dir1); | 728 | port_pb_dir_shadow &= ~IO_MASK(R_PORT_PB_DIR, dir1); |
@@ -702,8 +730,26 @@ i2c_init(void) | |||
702 | *R_PORT_PB_DIR = (port_pb_dir_shadow |= | 730 | *R_PORT_PB_DIR = (port_pb_dir_shadow |= |
703 | IO_STATE(R_PORT_PB_DIR, dir0, input) | | 731 | IO_STATE(R_PORT_PB_DIR, dir0, input) | |
704 | IO_STATE(R_PORT_PB_DIR, dir1, output)); | 732 | IO_STATE(R_PORT_PB_DIR, dir1, output)); |
733 | #else | ||
734 | if ((res = cris_io_interface_allocate_pins(if_i2c, | ||
735 | 'b', | ||
736 | CONFIG_ETRAX_I2C_DATA_PORT, | ||
737 | CONFIG_ETRAX_I2C_DATA_PORT))) { | ||
738 | printk(KERN_WARNING "i2c_init: Failed to get IO pin for I2C data port\n"); | ||
739 | return res; | ||
740 | } else if ((res = cris_io_interface_allocate_pins(if_i2c, | ||
741 | 'b', | ||
742 | CONFIG_ETRAX_I2C_CLK_PORT, | ||
743 | CONFIG_ETRAX_I2C_CLK_PORT))) { | ||
744 | cris_io_interface_free_pins(if_i2c, | ||
745 | 'b', | ||
746 | CONFIG_ETRAX_I2C_DATA_PORT, | ||
747 | CONFIG_ETRAX_I2C_DATA_PORT); | ||
748 | printk(KERN_WARNING "i2c_init: Failed to get IO pin for I2C clk port\n"); | ||
749 | } | ||
750 | #endif | ||
705 | 751 | ||
706 | return 0; | 752 | return res; |
707 | } | 753 | } |
708 | 754 | ||
709 | static int __init | 755 | static int __init |
@@ -711,14 +757,16 @@ i2c_register(void) | |||
711 | { | 757 | { |
712 | int res; | 758 | int res; |
713 | 759 | ||
714 | i2c_init(); | 760 | res = i2c_init(); |
761 | if (res < 0) | ||
762 | return res; | ||
715 | res = register_chrdev(I2C_MAJOR, i2c_name, &i2c_fops); | 763 | res = register_chrdev(I2C_MAJOR, i2c_name, &i2c_fops); |
716 | if(res < 0) { | 764 | if(res < 0) { |
717 | printk(KERN_ERR "i2c: couldn't get a major number.\n"); | 765 | printk(KERN_ERR "i2c: couldn't get a major number.\n"); |
718 | return res; | 766 | return res; |
719 | } | 767 | } |
720 | 768 | ||
721 | printk(KERN_INFO "I2C driver v2.2, (c) 1999-2001 Axis Communications AB\n"); | 769 | printk(KERN_INFO "I2C driver v2.2, (c) 1999-2004 Axis Communications AB\n"); |
722 | 770 | ||
723 | return 0; | 771 | return 0; |
724 | } | 772 | } |
diff --git a/arch/cris/arch-v10/drivers/pcf8563.c b/arch/cris/arch-v10/drivers/pcf8563.c index b3dfdf7b8fc5..201f4c90d961 100644 --- a/arch/cris/arch-v10/drivers/pcf8563.c +++ b/arch/cris/arch-v10/drivers/pcf8563.c | |||
@@ -15,7 +15,7 @@ | |||
15 | * | 15 | * |
16 | * Author: Tobias Anderberg <tobiasa@axis.com>. | 16 | * Author: Tobias Anderberg <tobiasa@axis.com>. |
17 | * | 17 | * |
18 | * $Id: pcf8563.c,v 1.8 2004/08/24 06:42:51 starvik Exp $ | 18 | * $Id: pcf8563.c,v 1.11 2005/03/07 13:13:07 starvik Exp $ |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/config.h> | 21 | #include <linux/config.h> |
@@ -40,7 +40,7 @@ | |||
40 | #define PCF8563_MAJOR 121 /* Local major number. */ | 40 | #define PCF8563_MAJOR 121 /* Local major number. */ |
41 | #define DEVICE_NAME "rtc" /* Name which is registered in /proc/devices. */ | 41 | #define DEVICE_NAME "rtc" /* Name which is registered in /proc/devices. */ |
42 | #define PCF8563_NAME "PCF8563" | 42 | #define PCF8563_NAME "PCF8563" |
43 | #define DRIVER_VERSION "$Revision: 1.8 $" | 43 | #define DRIVER_VERSION "$Revision: 1.11 $" |
44 | 44 | ||
45 | /* I2C bus slave registers. */ | 45 | /* I2C bus slave registers. */ |
46 | #define RTC_I2C_READ 0xa3 | 46 | #define RTC_I2C_READ 0xa3 |
@@ -49,6 +49,8 @@ | |||
49 | /* Two simple wrapper macros, saves a few keystrokes. */ | 49 | /* Two simple wrapper macros, saves a few keystrokes. */ |
50 | #define rtc_read(x) i2c_readreg(RTC_I2C_READ, x) | 50 | #define rtc_read(x) i2c_readreg(RTC_I2C_READ, x) |
51 | #define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y) | 51 | #define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y) |
52 | |||
53 | static DEFINE_SPINLOCK(rtc_lock); /* Protect state etc */ | ||
52 | 54 | ||
53 | static const unsigned char days_in_month[] = | 55 | static const unsigned char days_in_month[] = |
54 | { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; | 56 | { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
@@ -125,9 +127,12 @@ get_rtc_time(struct rtc_time *tm) | |||
125 | int __init | 127 | int __init |
126 | pcf8563_init(void) | 128 | pcf8563_init(void) |
127 | { | 129 | { |
128 | unsigned char ret; | 130 | int ret; |
129 | 131 | ||
130 | i2c_init(); | 132 | if ((ret = i2c_init())) { |
133 | printk(KERN_CRIT "pcf8563_init: failed to init i2c\n"); | ||
134 | return ret; | ||
135 | } | ||
131 | 136 | ||
132 | /* | 137 | /* |
133 | * First of all we need to reset the chip. This is done by | 138 | * First of all we need to reset the chip. This is done by |
@@ -200,12 +205,15 @@ pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned | |||
200 | { | 205 | { |
201 | struct rtc_time tm; | 206 | struct rtc_time tm; |
202 | 207 | ||
208 | spin_lock(&rtc_lock); | ||
203 | get_rtc_time(&tm); | 209 | get_rtc_time(&tm); |
204 | 210 | ||
205 | if (copy_to_user((struct rtc_time *) arg, &tm, sizeof(struct rtc_time))) { | 211 | if (copy_to_user((struct rtc_time *) arg, &tm, sizeof(struct rtc_time))) { |
212 | spin_unlock(&rtc_lock); | ||
206 | return -EFAULT; | 213 | return -EFAULT; |
207 | } | 214 | } |
208 | 215 | ||
216 | spin_unlock(&rtc_lock); | ||
209 | return 0; | 217 | return 0; |
210 | } | 218 | } |
211 | break; | 219 | break; |
@@ -250,6 +258,8 @@ pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned | |||
250 | BIN_TO_BCD(tm.tm_min); | 258 | BIN_TO_BCD(tm.tm_min); |
251 | BIN_TO_BCD(tm.tm_sec); | 259 | BIN_TO_BCD(tm.tm_sec); |
252 | tm.tm_mon |= century; | 260 | tm.tm_mon |= century; |
261 | |||
262 | spin_lock(&rtc_lock); | ||
253 | 263 | ||
254 | rtc_write(RTC_YEAR, tm.tm_year); | 264 | rtc_write(RTC_YEAR, tm.tm_year); |
255 | rtc_write(RTC_MONTH, tm.tm_mon); | 265 | rtc_write(RTC_MONTH, tm.tm_mon); |
@@ -258,6 +268,8 @@ pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned | |||
258 | rtc_write(RTC_MINUTES, tm.tm_min); | 268 | rtc_write(RTC_MINUTES, tm.tm_min); |
259 | rtc_write(RTC_SECONDS, tm.tm_sec); | 269 | rtc_write(RTC_SECONDS, tm.tm_sec); |
260 | 270 | ||
271 | spin_unlock(&rtc_lock); | ||
272 | |||
261 | return 0; | 273 | return 0; |
262 | #endif /* !CONFIG_ETRAX_RTC_READONLY */ | 274 | #endif /* !CONFIG_ETRAX_RTC_READONLY */ |
263 | } | 275 | } |