From owner-p4-projects@FreeBSD.ORG Sun Feb 22 08:28:26 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 87A0A1065673; Sun, 22 Feb 2009 08:28:25 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 44FF41065670 for ; Sun, 22 Feb 2009 08:28:25 +0000 (UTC) (envelope-from andrew@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 3299E8FC1A for ; Sun, 22 Feb 2009 08:28:25 +0000 (UTC) (envelope-from andrew@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n1M8SPwo081571 for ; Sun, 22 Feb 2009 08:28:25 GMT (envelope-from andrew@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n1M8SPpC081569 for perforce@freebsd.org; Sun, 22 Feb 2009 08:28:25 GMT (envelope-from andrew@freebsd.org) Date: Sun, 22 Feb 2009 08:28:25 GMT Message-Id: <200902220828.n1M8SPpC081569@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to andrew@freebsd.org using -f From: Andrew Turner To: Perforce Change Reviews Cc: Subject: PERFORCE change 158057 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 22 Feb 2009 08:28:26 -0000 http://perforce.freebsd.org/chv.cgi?CH=158057 Change 158057 by andrew@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 #include #include +#include #include +#include #include #include @@ -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; }