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 | |
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>
-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 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/Makefile | 5 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/fasttimer.c | 55 | ||||
-rw-r--r-- | include/asm-cris/arch-v10/ide.h | 99 | ||||
-rw-r--r-- | include/asm-cris/ide.h | 1 |
10 files changed, 376 insertions, 172 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 | } |
diff --git a/arch/cris/arch-v10/kernel/Makefile b/arch/cris/arch-v10/kernel/Makefile index 52761603b6a5..dcfec41d3533 100644 --- a/arch/cris/arch-v10/kernel/Makefile +++ b/arch/cris/arch-v10/kernel/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | # $Id: Makefile,v 1.5 2004/06/02 08:24:38 starvik Exp $ | 1 | # $Id: Makefile,v 1.6 2004/12/13 12:21:51 starvik Exp $ |
2 | # | 2 | # |
3 | # Makefile for the linux kernel. | 3 | # Makefile for the linux kernel. |
4 | # | 4 | # |
@@ -7,7 +7,8 @@ extra-y := head.o | |||
7 | 7 | ||
8 | 8 | ||
9 | obj-y := entry.o traps.o shadows.o debugport.o irq.o \ | 9 | obj-y := entry.o traps.o shadows.o debugport.o irq.o \ |
10 | process.o setup.o signal.o traps.o time.o ptrace.o | 10 | process.o setup.o signal.o traps.o time.o ptrace.o \ |
11 | dma.o io_interface_mux.o | ||
11 | 12 | ||
12 | obj-$(CONFIG_ETRAX_KGDB) += kgdb.o | 13 | obj-$(CONFIG_ETRAX_KGDB) += kgdb.o |
13 | obj-$(CONFIG_ETRAX_FAST_TIMER) += fasttimer.o | 14 | obj-$(CONFIG_ETRAX_FAST_TIMER) += fasttimer.o |
diff --git a/arch/cris/arch-v10/kernel/fasttimer.c b/arch/cris/arch-v10/kernel/fasttimer.c index 4717f7ae8e51..094ff45ae85b 100644 --- a/arch/cris/arch-v10/kernel/fasttimer.c +++ b/arch/cris/arch-v10/kernel/fasttimer.c | |||
@@ -1,10 +1,20 @@ | |||
1 | /* $Id: fasttimer.c,v 1.6 2004/05/14 10:18:39 starvik Exp $ | 1 | /* $Id: fasttimer.c,v 1.9 2005/03/04 08:16:16 starvik Exp $ |
2 | * linux/arch/cris/kernel/fasttimer.c | 2 | * linux/arch/cris/kernel/fasttimer.c |
3 | * | 3 | * |
4 | * Fast timers for ETRAX100/ETRAX100LX | 4 | * Fast timers for ETRAX100/ETRAX100LX |
5 | * This may be useful in other OS than Linux so use 2 space indentation... | 5 | * This may be useful in other OS than Linux so use 2 space indentation... |
6 | * | 6 | * |
7 | * $Log: fasttimer.c,v $ | 7 | * $Log: fasttimer.c,v $ |
8 | * Revision 1.9 2005/03/04 08:16:16 starvik | ||
9 | * Merge of Linux 2.6.11. | ||
10 | * | ||
11 | * Revision 1.8 2005/01/05 06:09:29 starvik | ||
12 | * cli()/sti() will be obsolete in 2.6.11. | ||
13 | * | ||
14 | * Revision 1.7 2005/01/03 13:35:46 starvik | ||
15 | * Removed obsolete stuff. | ||
16 | * Mark fast timer IRQ as not shared. | ||
17 | * | ||
8 | * Revision 1.6 2004/05/14 10:18:39 starvik | 18 | * Revision 1.6 2004/05/14 10:18:39 starvik |
9 | * Export fast_timer_list | 19 | * Export fast_timer_list |
10 | * | 20 | * |
@@ -148,8 +158,7 @@ static int debug_log_cnt_wrapped = 0; | |||
148 | #define DEBUG_LOG(string, value) \ | 158 | #define DEBUG_LOG(string, value) \ |
149 | { \ | 159 | { \ |
150 | unsigned long log_flags; \ | 160 | unsigned long log_flags; \ |
151 | save_flags(log_flags); \ | 161 | local_irq_save(log_flags); \ |
152 | cli(); \ | ||
153 | debug_log_string[debug_log_cnt] = (string); \ | 162 | debug_log_string[debug_log_cnt] = (string); \ |
154 | debug_log_value[debug_log_cnt] = (unsigned long)(value); \ | 163 | debug_log_value[debug_log_cnt] = (unsigned long)(value); \ |
155 | if (++debug_log_cnt >= DEBUG_LOG_MAX) \ | 164 | if (++debug_log_cnt >= DEBUG_LOG_MAX) \ |
@@ -157,7 +166,7 @@ static int debug_log_cnt_wrapped = 0; | |||
157 | debug_log_cnt = debug_log_cnt % DEBUG_LOG_MAX; \ | 166 | debug_log_cnt = debug_log_cnt % DEBUG_LOG_MAX; \ |
158 | debug_log_cnt_wrapped = 1; \ | 167 | debug_log_cnt_wrapped = 1; \ |
159 | } \ | 168 | } \ |
160 | restore_flags(log_flags); \ | 169 | local_irq_restore(log_flags); \ |
161 | } | 170 | } |
162 | #else | 171 | #else |
163 | #define DEBUG_LOG(string, value) | 172 | #define DEBUG_LOG(string, value) |
@@ -320,8 +329,7 @@ void start_one_shot_timer(struct fast_timer *t, | |||
320 | 329 | ||
321 | D1(printk("sft %s %d us\n", name, delay_us)); | 330 | D1(printk("sft %s %d us\n", name, delay_us)); |
322 | 331 | ||
323 | save_flags(flags); | 332 | local_irq_save(flags); |
324 | cli(); | ||
325 | 333 | ||
326 | do_gettimeofday_fast(&t->tv_set); | 334 | do_gettimeofday_fast(&t->tv_set); |
327 | tmp = fast_timer_list; | 335 | tmp = fast_timer_list; |
@@ -395,7 +403,7 @@ void start_one_shot_timer(struct fast_timer *t, | |||
395 | 403 | ||
396 | D2(printk("start_one_shot_timer: %d us done\n", delay_us)); | 404 | D2(printk("start_one_shot_timer: %d us done\n", delay_us)); |
397 | 405 | ||
398 | restore_flags(flags); | 406 | local_irq_restore(flags); |
399 | } /* start_one_shot_timer */ | 407 | } /* start_one_shot_timer */ |
400 | 408 | ||
401 | static inline int fast_timer_pending (const struct fast_timer * t) | 409 | static inline int fast_timer_pending (const struct fast_timer * t) |
@@ -425,11 +433,10 @@ int del_fast_timer(struct fast_timer * t) | |||
425 | unsigned long flags; | 433 | unsigned long flags; |
426 | int ret; | 434 | int ret; |
427 | 435 | ||
428 | save_flags(flags); | 436 | local_irq_save(flags); |
429 | cli(); | ||
430 | ret = detach_fast_timer(t); | 437 | ret = detach_fast_timer(t); |
431 | t->next = t->prev = NULL; | 438 | t->next = t->prev = NULL; |
432 | restore_flags(flags); | 439 | local_irq_restore(flags); |
433 | return ret; | 440 | return ret; |
434 | } /* del_fast_timer */ | 441 | } /* del_fast_timer */ |
435 | 442 | ||
@@ -444,8 +451,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
444 | struct fast_timer *t; | 451 | struct fast_timer *t; |
445 | unsigned long flags; | 452 | unsigned long flags; |
446 | 453 | ||
447 | save_flags(flags); | 454 | local_irq_save(flags); |
448 | cli(); | ||
449 | 455 | ||
450 | /* Clear timer1 irq */ | 456 | /* Clear timer1 irq */ |
451 | *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr); | 457 | *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr); |
@@ -462,7 +468,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
462 | fast_timer_running = 0; | 468 | fast_timer_running = 0; |
463 | fast_timer_ints++; | 469 | fast_timer_ints++; |
464 | 470 | ||
465 | restore_flags(flags); | 471 | local_irq_restore(flags); |
466 | 472 | ||
467 | t = fast_timer_list; | 473 | t = fast_timer_list; |
468 | while (t) | 474 | while (t) |
@@ -482,8 +488,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
482 | fast_timers_expired++; | 488 | fast_timers_expired++; |
483 | 489 | ||
484 | /* Remove this timer before call, since it may reuse the timer */ | 490 | /* Remove this timer before call, since it may reuse the timer */ |
485 | save_flags(flags); | 491 | local_irq_save(flags); |
486 | cli(); | ||
487 | if (t->prev) | 492 | if (t->prev) |
488 | { | 493 | { |
489 | t->prev->next = t->next; | 494 | t->prev->next = t->next; |
@@ -498,7 +503,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
498 | } | 503 | } |
499 | t->prev = NULL; | 504 | t->prev = NULL; |
500 | t->next = NULL; | 505 | t->next = NULL; |
501 | restore_flags(flags); | 506 | local_irq_restore(flags); |
502 | 507 | ||
503 | if (t->function != NULL) | 508 | if (t->function != NULL) |
504 | { | 509 | { |
@@ -515,8 +520,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
515 | D1(printk(".\n")); | 520 | D1(printk(".\n")); |
516 | } | 521 | } |
517 | 522 | ||
518 | save_flags(flags); | 523 | local_irq_save(flags); |
519 | cli(); | ||
520 | if ((t = fast_timer_list) != NULL) | 524 | if ((t = fast_timer_list) != NULL) |
521 | { | 525 | { |
522 | /* Start next timer.. */ | 526 | /* Start next timer.. */ |
@@ -535,7 +539,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
535 | #endif | 539 | #endif |
536 | start_timer1(us); | 540 | start_timer1(us); |
537 | } | 541 | } |
538 | restore_flags(flags); | 542 | local_irq_restore(flags); |
539 | break; | 543 | break; |
540 | } | 544 | } |
541 | else | 545 | else |
@@ -546,7 +550,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
546 | D1(printk("e! %d\n", us)); | 550 | D1(printk("e! %d\n", us)); |
547 | } | 551 | } |
548 | } | 552 | } |
549 | restore_flags(flags); | 553 | local_irq_restore(flags); |
550 | } | 554 | } |
551 | 555 | ||
552 | if (!t) | 556 | if (!t) |
@@ -748,13 +752,12 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len | |||
748 | #endif | 752 | #endif |
749 | 753 | ||
750 | used += sprintf(bigbuf + used, "Active timers:\n"); | 754 | used += sprintf(bigbuf + used, "Active timers:\n"); |
751 | save_flags(flags); | 755 | local_irq_save(flags); |
752 | cli(); | ||
753 | t = fast_timer_list; | 756 | t = fast_timer_list; |
754 | while (t != NULL && (used+100 < BIG_BUF_SIZE)) | 757 | while (t != NULL && (used+100 < BIG_BUF_SIZE)) |
755 | { | 758 | { |
756 | nextt = t->next; | 759 | nextt = t->next; |
757 | restore_flags(flags); | 760 | local_irq_restore(flags); |
758 | used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu " | 761 | used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu " |
759 | "d: %6li us data: 0x%08lX" | 762 | "d: %6li us data: 0x%08lX" |
760 | /* " func: 0x%08lX" */ | 763 | /* " func: 0x%08lX" */ |
@@ -768,14 +771,14 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len | |||
768 | t->data | 771 | t->data |
769 | /* , t->function */ | 772 | /* , t->function */ |
770 | ); | 773 | ); |
771 | cli(); | 774 | local_irq_disable(); |
772 | if (t->next != nextt) | 775 | if (t->next != nextt) |
773 | { | 776 | { |
774 | printk(KERN_WARNING "timer removed!\n"); | 777 | printk(KERN_WARNING "timer removed!\n"); |
775 | } | 778 | } |
776 | t = nextt; | 779 | t = nextt; |
777 | } | 780 | } |
778 | restore_flags(flags); | 781 | local_irq_restore(flags); |
779 | } | 782 | } |
780 | 783 | ||
781 | if (used - offset < len) | 784 | if (used - offset < len) |
@@ -963,7 +966,7 @@ void fast_timer_init(void) | |||
963 | if ((fasttimer_proc_entry = create_proc_entry( "fasttimer", 0, 0 ))) | 966 | if ((fasttimer_proc_entry = create_proc_entry( "fasttimer", 0, 0 ))) |
964 | fasttimer_proc_entry->read_proc = proc_fasttimer_read; | 967 | fasttimer_proc_entry->read_proc = proc_fasttimer_read; |
965 | #endif /* PROC_FS */ | 968 | #endif /* PROC_FS */ |
966 | if(request_irq(TIMER1_IRQ_NBR, timer1_handler, SA_SHIRQ, | 969 | if(request_irq(TIMER1_IRQ_NBR, timer1_handler, 0, |
967 | "fast timer int", NULL)) | 970 | "fast timer int", NULL)) |
968 | { | 971 | { |
969 | printk("err: timer1 irq\n"); | 972 | printk("err: timer1 irq\n"); |
diff --git a/include/asm-cris/arch-v10/ide.h b/include/asm-cris/arch-v10/ide.h new file mode 100644 index 000000000000..8cf2d7cb22ac --- /dev/null +++ b/include/asm-cris/arch-v10/ide.h | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | * linux/include/asm-cris/ide.h | ||
3 | * | ||
4 | * Copyright (C) 2000, 2001, 2002 Axis Communications AB | ||
5 | * | ||
6 | * Authors: Bjorn Wesen | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * This file contains the ETRAX 100LX specific IDE code. | ||
12 | */ | ||
13 | |||
14 | #ifndef __ASMCRIS_IDE_H | ||
15 | #define __ASMCRIS_IDE_H | ||
16 | |||
17 | #ifdef __KERNEL__ | ||
18 | |||
19 | #include <asm/arch/svinto.h> | ||
20 | #include <asm/io.h> | ||
21 | #include <asm-generic/ide_iops.h> | ||
22 | |||
23 | |||
24 | /* ETRAX 100 can support 4 IDE busses on the same pins (serialized) */ | ||
25 | |||
26 | #define MAX_HWIFS 4 | ||
27 | |||
28 | extern __inline__ int ide_default_irq(unsigned long base) | ||
29 | { | ||
30 | /* all IDE busses share the same IRQ, number 4. | ||
31 | * this has the side-effect that ide-probe.c will cluster our 4 interfaces | ||
32 | * together in a hwgroup, and will serialize accesses. this is good, because | ||
33 | * we can't access more than one interface at the same time on ETRAX100. | ||
34 | */ | ||
35 | return 4; | ||
36 | } | ||
37 | |||
38 | extern __inline__ unsigned long ide_default_io_base(int index) | ||
39 | { | ||
40 | /* we have no real I/O base address per interface, since all go through the | ||
41 | * same register. but in a bitfield in that register, we have the i/f number. | ||
42 | * so we can use the io_base to remember that bitfield. | ||
43 | */ | ||
44 | static const unsigned long io_bases[MAX_HWIFS] = { | ||
45 | IO_FIELD(R_ATA_CTRL_DATA, sel, 0), | ||
46 | IO_FIELD(R_ATA_CTRL_DATA, sel, 1), | ||
47 | IO_FIELD(R_ATA_CTRL_DATA, sel, 2), | ||
48 | IO_FIELD(R_ATA_CTRL_DATA, sel, 3) | ||
49 | }; | ||
50 | return io_bases[index]; | ||
51 | } | ||
52 | |||
53 | /* this is called once for each interface, to setup the port addresses. data_port is the result | ||
54 | * of the ide_default_io_base call above. ctrl_port will be 0, but that is don't care for us. | ||
55 | */ | ||
56 | |||
57 | extern __inline__ void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, unsigned long ctrl_port, int *irq) | ||
58 | { | ||
59 | int i; | ||
60 | |||
61 | /* fill in ports for ATA addresses 0 to 7 */ | ||
62 | |||
63 | for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { | ||
64 | hw->io_ports[i] = data_port | | ||
65 | IO_FIELD(R_ATA_CTRL_DATA, addr, i) | | ||
66 | IO_STATE(R_ATA_CTRL_DATA, cs0, active); | ||
67 | } | ||
68 | |||
69 | /* the IDE control register is at ATA address 6, with CS1 active instead of CS0 */ | ||
70 | |||
71 | hw->io_ports[IDE_CONTROL_OFFSET] = data_port | | ||
72 | IO_FIELD(R_ATA_CTRL_DATA, addr, 6) | | ||
73 | IO_STATE(R_ATA_CTRL_DATA, cs1, active); | ||
74 | |||
75 | /* whats this for ? */ | ||
76 | |||
77 | hw->io_ports[IDE_IRQ_OFFSET] = 0; | ||
78 | } | ||
79 | |||
80 | extern __inline__ void ide_init_default_hwifs(void) | ||
81 | { | ||
82 | hw_regs_t hw; | ||
83 | int index; | ||
84 | |||
85 | for(index = 0; index < MAX_HWIFS; index++) { | ||
86 | ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL); | ||
87 | hw.irq = ide_default_irq(ide_default_io_base(index)); | ||
88 | ide_register_hw(&hw, NULL); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | /* some configuration options we don't need */ | ||
93 | |||
94 | #undef SUPPORT_VLB_SYNC | ||
95 | #define SUPPORT_VLB_SYNC 0 | ||
96 | |||
97 | #endif /* __KERNEL__ */ | ||
98 | |||
99 | #endif /* __ASMCRIS_IDE_H */ | ||
diff --git a/include/asm-cris/ide.h b/include/asm-cris/ide.h new file mode 100644 index 000000000000..a894f66665f8 --- /dev/null +++ b/include/asm-cris/ide.h | |||
@@ -0,0 +1 @@ | |||
#include <asm/arch/ide.h> | |||