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