PERFORCE change 158057 for review

Andrew Turner andrew at FreeBSD.org
Sun Feb 22 00:28:26 PST 2009


http://perforce.freebsd.org/chv.cgi?CH=158057

Change 158057 by andrew at andrew_bender on 2009/02/22 08:27:50

	Cleanup unmasking of interrupts to only unmask the requested interrupt.
	Have arm_get_next_irq return the uart interrupt rather than the subinterrupt as we are only interested in this.
	Call rman_activate_resource in s3c24x0_activate_resource.
	Get the uart driver working well enough to ask for the single user shell.

Affected files ...

.. //depot/projects/arm/src/sys/arm/s3c2xx0/s3c24x0.c#6 edit
.. //depot/projects/arm/src/sys/arm/s3c2xx0/uart_dev_s3c2410.c#9 edit

Differences ...

==== //depot/projects/arm/src/sys/arm/s3c2xx0/s3c24x0.c#6 (text+ko) ====

@@ -247,7 +247,7 @@
 s3c24x0_activate_resource(device_t bus, device_t child, int type, int rid,
         struct resource *r)
 {
-	return (0);
+	return (rman_activate_resource(r));
 }
 
 static int
@@ -502,17 +502,17 @@
 arm_get_next_irq(void)
 {
 	uint32_t intpnd;
-	int irq;
+	int irq, subirq;
 
 	if ((irq = bus_space_read_4(&s3c2xx0_bs_tag,
 	    s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTOFFSET)) != 0) {
 
 		/* Clear the pending bit */
-		bus_space_write_4(&s3c2xx0_bs_tag, s3c2xx0_softc->sc_intctl_ioh,
-		    INTCTL_SRCPND, (1 << irq));
 		intpnd = bus_space_read_4(&s3c2xx0_bs_tag,
 		    s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTPND);
 		bus_space_write_4(&s3c2xx0_bs_tag, s3c2xx0_softc->sc_intctl_ioh,
+		    INTCTL_SRCPND, intpnd);
+		bus_space_write_4(&s3c2xx0_bs_tag, s3c2xx0_softc->sc_intctl_ioh,
 		    INTCTL_INTPND, intpnd);
 
 		switch (irq) {
@@ -521,22 +521,26 @@
 		case S3C24X0_INT_UART1:
 		case S3C24X0_INT_UART2:
 			/* Find the sub IRQ */
-			irq = 0x7ff;
-			irq &= bus_space_read_4(&s3c2xx0_bs_tag,
+			subirq = 0x7ff;
+			subirq &= bus_space_read_4(&s3c2xx0_bs_tag,
 			    s3c2xx0_softc->sc_intctl_ioh, INTCTL_SUBSRCPND);
-			irq &= ~(bus_space_read_4(&s3c2xx0_bs_tag,
+			subirq &= ~(bus_space_read_4(&s3c2xx0_bs_tag,
 			    s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK));
-			if (irq == 0)
-				return (-1);
+			if (subirq == 0)
+				return (irq);
 
-			irq = ffs(irq);
+			subirq = ffs(subirq);
 
 			/* Clear the sub irq pending bit */
 			bus_space_write_4(&s3c2xx0_bs_tag,
 			    s3c2xx0_softc->sc_intctl_ioh, INTCTL_SUBSRCPND,
-			    (1 << irq));
+			    (1 << subirq));
+
+			/* Return the parent IRQ for UART as that is all we ever need */
+			if (subirq <= 8)
+				return (irq);
 
-			return (S3C24X0_SUBIRQ_MIN + irq);
+			return (S3C24X0_SUBIRQ_MIN + subirq);
 		}
 
 		return (irq);
@@ -569,46 +573,17 @@
 {
 	u_int32_t mask;
 
-	if (irq >= S3C24X0_SUBIRQ_MIN) {
+	if (irq < S3C24X0_SUBIRQ_MIN) {
+		mask = bus_space_read_4(&s3c2xx0_bs_tag,
+		    s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTMSK);
+		mask &= ~(1 << irq);
+		bus_space_write_4(&s3c2xx0_bs_tag, s3c2xx0_softc->sc_intctl_ioh,
+		    INTCTL_INTMSK, mask);
+	} else {
 		mask = bus_space_read_4(&s3c2xx0_bs_tag,
 		    s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK);
 		mask &= ~(1 << (irq - S3C24X0_SUBIRQ_MIN));
 		bus_space_write_4(&s3c2xx0_bs_tag, 
 		    s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK, mask);
-
-		/* Find the other irq to unmask */
-		switch (irq) {
-		case S3C24X0_INT_ADC:
-		case S3C24X0_INT_TC:
-			irq = S3C24X0_INT_ADCTC;
-			break;
-		case S3C24X0_INT_RXD0:
-		case S3C24X0_INT_TXD0:
-		case S3C24X0_INT_ERR0:
-			irq = S3C24X0_INT_UART0;
-			break;
-
-		case S3C24X0_INT_RXD1:
-		case S3C24X0_INT_TXD1:
-		case S3C24X0_INT_ERR1:
-			irq = S3C24X0_INT_UART1;
-			break;
-
-		case S3C24X0_INT_RXD2:
-		case S3C24X0_INT_TXD2:
-		case S3C24X0_INT_ERR2:
-			irq = S3C24X0_INT_UART2;
-			break;
-		default:
-			/* We don't know which other IRQ to unmask */
-			return;
-		}
-		arm_mask_irq(irq);
-		return;
 	}
-	mask = bus_space_read_4(&s3c2xx0_bs_tag, s3c2xx0_softc->sc_intctl_ioh,
-	    INTCTL_INTMSK);
-	mask &= ~(1 << irq);
-	bus_space_write_4(&s3c2xx0_bs_tag, s3c2xx0_softc->sc_intctl_ioh,
-	    INTCTL_INTMSK, mask);
 }

==== //depot/projects/arm/src/sys/arm/s3c2xx0/uart_dev_s3c2410.c#9 (text+ko) ====

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2003 Marcel Moolenaar
- * Copyright (c) 2007 Andrew Turner
+ * Copyright (c) 2007-2009 Andrew Turner
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,9 @@
 #include <sys/conf.h>
 #include <sys/cons.h>
 #include <sys/tty.h>
+#include <sys/rman.h>
 #include <machine/bus.h>
+#include <machine/intr.h>
 
 #include <dev/uart/uart.h>
 #include <dev/uart/uart_cpu.h>
@@ -46,6 +48,15 @@
 
 #define      DEFAULT_RCLK    3686400
 
+/* Finds the subirq from the parent */
+#define get_sub_irq(parent, offset) \
+	((parent == S3C24X0_INT_UART0) ? S3C24X0_SUBIRQ_MIN + offset : \
+	((parent == S3C24X0_INT_UART1) ? S3C24X0_SUBIRQ_MIN + 3 + offset : \
+	  S3C24X0_SUBIRQ_MIN + 6 + offset))
+#define RX_OFF	0
+#define TX_OFF	1
+#define ERR_OFF	2
+
 static int sscomspeed(long, long);
 static int s3c24x0_uart_param(struct uart_bas *, int, int, int, int);
 
@@ -163,7 +174,8 @@
 	s3c24x0_uart_param(bas, baudrate, databits, stopbits, parity);
 
 	/* Enable UART. */
-	uart_setreg(bas, SSCOM_UCON, UCON_TXMODE_INT|UCON_RXMODE_INT|UCON_TOINT);
+	uart_setreg(bas, SSCOM_UCON, UCON_TXMODE_INT | UCON_RXMODE_INT |
+	    UCON_TOINT);
 	uart_setreg(bas, SSCOM_UMCON, UMCON_RTS);
 }
 
@@ -176,7 +188,8 @@
 static void
 s3c2410_putc(struct uart_bas *bas, int c)
 {
-	while (!(uart_getreg(bas, SSCOM_UTRSTAT) & UTRSTAT_TXEMPTY))
+	while ((bus_space_read_4(bas->bst, bas->bsh, SSCOM_UFSTAT) &
+	    UFSTAT_TXFULL) == UFSTAT_TXFULL)
 		continue;
 
 	uart_setreg(bas, SSCOM_UTXH, c);
@@ -233,6 +246,8 @@
 static int
 s3c2410_bus_attach(struct uart_softc *sc)
 {
+	uintptr_t irq;
+
 	bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
 
 	/*
@@ -243,19 +258,34 @@
 	sc->sc_rxfifosz = 16;
 	sc->sc_hwiflow = 0;
 	sc->sc_hwoflow = 0;
+
+	irq = rman_get_start(sc->sc_ires);
+	arm_unmask_irq(irq);
+	arm_unmask_irq(get_sub_irq(irq, RX_OFF));
+	arm_unmask_irq(get_sub_irq(irq, TX_OFF));
+	arm_unmask_irq(get_sub_irq(irq, ERR_OFF));
 	return (0);
 }
 
 static int
 s3c2410_bus_transmit(struct uart_softc *sc)
 {
+	uintptr_t irq;
+
 	uart_lock(sc->sc_hwmtx);
+
 	for (int i = 0; i < sc->sc_txdatasz; i++) {
 		s3c2410_putc(&sc->sc_bas, sc->sc_txbuf[i]);
 		uart_barrier(&sc->sc_bas);
 	}
+
+	sc->sc_txbusy = 1;
+
 	uart_unlock(sc->sc_hwmtx);
 
+	irq = rman_get_start(sc->sc_ires);
+	arm_unmask_irq(get_sub_irq(irq, TX_OFF));
+
 	return (0);
 }
 
@@ -290,17 +320,22 @@
 static int
 s3c2410_bus_ipend(struct uart_softc *sc)
 {
-	uint32_t utrstat;
+	uintptr_t irq;
+	uint32_t ufstat;
 	int ipend = 0;
 
 	uart_lock(sc->sc_hwmtx);
-	utrstat = uart_getreg(&sc->sc_bas, SSCOM_UTRSTAT);
+	ufstat = bus_space_read_4(sc->sc_bas.bst, sc->sc_bas.bsh, SSCOM_UFSTAT);
 	uart_unlock(sc->sc_hwmtx);
 
-	if ((utrstat & UTRSTAT_TXEMPTY) == UTRSTAT_TXEMPTY && sc->sc_txbusy != 0) {
-		ipend |= SER_INT_TXIDLE;
+	/* XXX: The register values are incorrect on the s3c244x */
+	if ((ufstat & UFSTAT_TXCOUNT) == 0) {
+		if (sc->sc_txbusy != 0)
+			ipend |= SER_INT_TXIDLE;
+		irq = rman_get_start(sc->sc_ires);
+		arm_mask_irq(get_sub_irq(irq, TX_OFF));
 	}
-	if ((utrstat & UTRSTAT_RXREADY) == UTRSTAT_RXREADY) {
+	if ((ufstat & UFSTAT_RXCOUNT) > 0) {
 		ipend |= SER_INT_RXREADY;
 	}
 


More information about the p4-projects mailing list