patch-2.4.22 linux-2.4.22/arch/cris/drivers/gpio.c
Next file: linux-2.4.22/arch/cris/drivers/i2c.c
Previous file: linux-2.4.22/arch/cris/drivers/examples/kiobuftest.c
Back to the patch index
Back to the overall index
- Lines: 230
- Date:
2003-08-25 04:44:39.000000000 -0700
- Orig file:
linux-2.4.21/arch/cris/drivers/gpio.c
- Orig date:
2003-06-13 07:51:29.000000000 -0700
diff -urN linux-2.4.21/arch/cris/drivers/gpio.c linux-2.4.22/arch/cris/drivers/gpio.c
@@ -1,4 +1,4 @@
-/* $Id: gpio.c,v 1.21 2002/12/02 08:11:41 starvik Exp $
+/* $Id: gpio.c,v 1.25 2003/06/24 07:24:31 johana Exp $
*
* Etrax general port I/O device
*
@@ -9,6 +9,22 @@
* Johan Adolfsson (read/set directions, write, port G)
*
* $Log: gpio.c,v $
+ * Revision 1.25 2003/06/24 07:24:31 johana
+ * Added gpio_pa_irq_enabled_mask to keep track of what interrupts we have
+ * enabled so we anly clear those that we have enabled and let bits/pins
+ * used by other drivers alone.
+ * Update gpio_some_alarms in IO_CLRALARM ioctl().
+ *
+ * Revision 1.24 2003/06/19 08:58:25 johana
+ * Turn off interrupts while fiddling with genconfig_shadow.
+ * Put some printk within D() macro.
+ *
+ * Revision 1.23 2003/04/01 14:12:06 starvik
+ * Added loglevel for lots of printks
+ *
+ * Revision 1.22 2003/01/09 18:03:47 starvik
+ * init_ioremap is now called by kernel before device drivers are initialized
+ *
* Revision 1.21 2002/12/02 08:11:41 starvik
* Merge of Linux 2.4.20
*
@@ -169,6 +185,7 @@
static struct gpio_private *alarmlist = 0;
static int gpio_some_alarms = 0; /* Set if someone uses alarm */
+static unsigned long gpio_pa_irq_enabled_mask = 0;
/* Port A and B use 8 bit access, but Port G is 32 bit */
#define NUM_PORTS (GPIO_MINOR_B+1)
@@ -238,13 +255,19 @@
unsigned long data;
poll_wait(file, &priv->alarm_wq, wait);
if (priv->minor == GPIO_MINOR_A) {
+ unsigned long flags;
unsigned long tmp;
data = *R_PORT_PA_DATA;
/* PA has support for high level interrupt -
* lets activate for those low and with highalarm set
*/
tmp = ~data & priv->highalarm & 0xFF;
- *R_IRQ_MASK1_SET = (tmp << R_IRQ_MASK1_SET__pa0__BITNR);
+ tmp = (tmp << R_IRQ_MASK1_SET__pa0__BITNR);
+ save_flags(flags); cli();
+ gpio_pa_irq_enabled_mask |= tmp;
+ *R_IRQ_MASK1_SET = tmp;
+ restore_flags(flags);
+
} else if (priv->minor == GPIO_MINOR_B)
data = *R_PORT_PB_DATA;
else if (priv->minor == GPIO_MINOR_G)
@@ -293,12 +316,15 @@
{
unsigned long tmp;
/* Find what PA interrupts are active */
- tmp = (*R_IRQ_READ1 >> R_IRQ_READ1__pa0__BITNR) & 0xFF;
+ tmp = (*R_IRQ_READ1);
+
+ /* Find those that we have enabled */
+ tmp &= gpio_pa_irq_enabled_mask;
+
/* Clear them.. */
- /* NOTE: Maybe we need to be more careful here if some other
- * driver uses PA interrupt as well?
- */
- *R_IRQ_MASK1_CLR = (tmp << R_IRQ_MASK1_CLR__pa0__BITNR);
+ *R_IRQ_MASK1_CLR = tmp;
+ gpio_pa_irq_enabled_mask &= ~tmp;
+
if (gpio_some_alarms) {
etrax_gpio_wake_up_check();
}
@@ -437,7 +463,7 @@
p = p->next;
}
gpio_some_alarms = 0;
-
+
return 0;
}
@@ -459,6 +485,7 @@
return ~(*priv->dir_shadow) & 0xFF; /* Only 8 bits */
} else if (priv->minor == GPIO_MINOR_G) {
/* We must fiddle with R_GEN_CONFIG to change dir */
+ save_flags(flags); cli();
if (((arg & dir_g_in_bits) != arg) &&
(arg & changeable_dir_g)) {
arg &= changeable_dir_g;
@@ -483,16 +510,17 @@
dir_g_in_bits |= (1<<24);
dir_g_out_bits &= ~(1<<24);
}
- printk("gpio: SETINPUT on port G set "
- "genconfig to 0x%08lX "
- "in_bits: 0x%08lX "
- "out_bits: 0x%08lX\n",
- (unsigned long)genconfig_shadow,
- dir_g_in_bits, dir_g_out_bits);
+ D(printk(KERN_INFO "gpio: SETINPUT on port G set "
+ "genconfig to 0x%08lX "
+ "in_bits: 0x%08lX "
+ "out_bits: 0x%08lX\n",
+ (unsigned long)genconfig_shadow,
+ dir_g_in_bits, dir_g_out_bits));
*R_GEN_CONFIG = genconfig_shadow;
/* Must be a >120 ns delay before writing this again */
}
+ restore_flags(flags);
return dir_g_in_bits;
}
return 0;
@@ -508,7 +536,8 @@
restore_flags(flags);
return *priv->dir_shadow;
} else if (priv->minor == GPIO_MINOR_G) {
- /* We must fiddle with R_GEN_CONFIG to change dir */
+ /* We must fiddle with R_GEN_CONFIG to change dir */
+ save_flags(flags); cli();
if (((arg & dir_g_out_bits) != arg) &&
(arg & changeable_dir_g)) {
/* Set bits in genconfig to set to output */
@@ -532,15 +561,16 @@
dir_g_out_bits |= (1<<24);
dir_g_in_bits &= ~(1<<24);
}
- printk("gpio: SETOUTPUT on port G set "
- "genconfig to 0x%08lX "
- "in_bits: 0x%08lX "
- "out_bits: 0x%08lX\n",
- (unsigned long)genconfig_shadow,
- dir_g_in_bits, dir_g_out_bits);
+ D(printk(KERN_INFO "gpio: SETOUTPUT on port G set "
+ "genconfig to 0x%08lX "
+ "in_bits: 0x%08lX "
+ "out_bits: 0x%08lX\n",
+ (unsigned long)genconfig_shadow,
+ dir_g_in_bits, dir_g_out_bits));
*R_GEN_CONFIG = genconfig_shadow;
/* Must be a >120 ns delay before writing this again */
}
+ restore_flags(flags);
return dir_g_out_bits & 0x7FFFFFFF;
}
return 0;
@@ -605,6 +635,20 @@
// clear alarm for bits with 1 in arg
priv->highalarm &= ~arg;
priv->lowalarm &= ~arg;
+ {
+ /* Must update gpio_some_alarms */
+ struct gpio_private *p = alarmlist;
+ int some_alarms;
+ some_alarms = 0;
+ while (p) {
+ if (p->highalarm | p->lowalarm) {
+ some_alarms = 1;
+ break;
+ }
+ p = p->next;
+ }
+ gpio_some_alarms = some_alarms;
+ }
break;
case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */
/* Read direction 0=input 1=output */
@@ -824,9 +868,11 @@
dir_g_in_bits |= (~dir_g_shadow & changeable_dir_g);
- printk("GPIO port G: in_bits: 0x%08lX out_bits: 0x%08lX val: %08lX\n",
+ printk(KERN_INFO
+ "GPIO port G: in_bits: 0x%08lX out_bits: 0x%08lX val: %08lX\n",
dir_g_in_bits, dir_g_out_bits, (unsigned long)*R_PORT_G_DATA);
- printk("GPIO port G: dir: %08lX changeable: %08lX\n",
+ printk(KERN_INFO
+ "GPIO port G: dir: %08lX changeable: %08lX\n",
dir_g_shadow, changeable_dir_g);
}
@@ -835,7 +881,6 @@
static __init int
gpio_init(void)
{
- extern void init_ioremap(void);
int res;
#if defined (CONFIG_ETRAX_CSP0_LEDS)
int i;
@@ -850,8 +895,7 @@
}
/* Clear all leds */
-#if defined (CONFIG_ETRAX_CSP0_LEDS) || defined (CONFIG_ETRAX_PA_LEDS) || defined (CONFIG_ETRAX_PB_LEDS)
- init_ioremap();
+#if defined (CONFIG_ETRAX_CSP0_LEDS) || defined (CONFIG_ETRAX_PA_LEDS) || defined (CONFIG_ETRAX_PB_LEDS)
LED_NETWORK_SET(0);
LED_ACTIVE_SET(0);
LED_DISK_READ(0);
@@ -865,7 +909,8 @@
#endif
gpio_init_port_g();
- printk("ETRAX 100LX GPIO driver v2.5, (c) 2001, 2002 Axis Communications AB\n");
+ printk(KERN_INFO
+ "ETRAX 100LX GPIO driver v2.5, (c) 2001, 2002 Axis Communications AB\n");
/* We call etrax_gpio_wake_up_check() from timer interrupt and
* from cpu_idle() in kernel/process.c
* The check in cpu_idle() reduces latency from ~15 ms to ~6 ms
@@ -873,11 +918,11 @@
*/
if (request_irq(TIMER0_IRQ_NBR, gpio_poll_timer_interrupt,
SA_SHIRQ | SA_INTERRUPT,"gpio poll", NULL)) {
- printk("err: timer0 irq for gpio\n");
+ printk(KERN_CRIT "err: timer0 irq for gpio\n");
}
if (request_irq(PA_IRQ_NBR, gpio_pa_interrupt,
SA_SHIRQ | SA_INTERRUPT,"gpio PA", NULL)) {
- printk("err: PA irq for gpio\n");
+ printk(KERN_CRIT "err: PA irq for gpio\n");
}
return res;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)