Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 24 Feb 2009 09:53:55 GMT
From:      Andrew Turner <andrew@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 158191 for review
Message-ID:  <200902240953.n1O9rtCu039270@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=158191

Change 158191 by andrew@andrew_bender on 2009/02/24 09:53:24

	Correctly calculate the clock speeds on s3c244x
	Fix the console so it will only appear on the uart the kernel sends it's output to.
	Support the UART in both s3c241x and s3c244x.

Affected files ...

.. //depot/projects/arm/src/sys/arm/s3c2xx0/s3c2440reg.h#1 add
.. //depot/projects/arm/src/sys/arm/s3c2xx0/s3c24x0.c#9 edit
.. //depot/projects/arm/src/sys/arm/s3c2xx0/s3c24x0_machdep.c#5 edit
.. //depot/projects/arm/src/sys/arm/s3c2xx0/s3c24x0reg.h#4 edit
.. //depot/projects/arm/src/sys/arm/s3c2xx0/s3c24x0var.h#4 edit
.. //depot/projects/arm/src/sys/arm/s3c2xx0/uart_bus_s3c2410.c#5 edit
.. //depot/projects/arm/src/sys/arm/s3c2xx0/uart_dev_s3c2410.c#11 edit

Differences ...

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

@@ -46,6 +46,7 @@
 #include <machine/cpufunc.h>
 #include <machine/intr.h>
 #include <arm/s3c2xx0/s3c2410reg.h>
+#include <arm/s3c2xx0/s3c2440reg.h>
 #include <arm/s3c2xx0/s3c24x0var.h>
 #include <sys/rman.h>
 
@@ -334,6 +335,11 @@
 		S3C24X0_TIMER_SIZE, 0, &sc->sc_timer_ioh))
 		panic("cannot map TIMER");
 
+	/*
+	 * Identify the CPU
+	 */
+	s3c24x0_identify_cpu(dev);
+
 	/* calculate current clock frequency */
 	s3c24x0_clock_freq(&sc->sc_sx);
 	printf(": fclk %d MHz hclk %d MHz pclk %d MHz",
@@ -342,11 +348,6 @@
 	printf("\n");
 
 	/*
-	 * Identify the CPU
-	 */
-	s3c24x0_identify_cpu(dev);
-
-	/*
 	 * Attach children devices
 	 */
 	s3c2xx0_softc->s3c2xx0_irq_rman.rm_type = RMAN_ARRAY;
@@ -373,7 +374,7 @@
 	    S3C2410_SDI_SIZE);
 
 	/* Add the uart and set it's irq and registers */
-	for (i = 0; i < 1; i++) {
+	for (i = 0; i < 3; i++) {
 		child = s3c24x0_add_child(dev, 0, "uart", i);
 
 		irq = 0;
@@ -425,11 +426,11 @@
 /*
  * fill sc_pclk, sc_hclk, sc_fclk from values of clock controller register.
  *
- * s3c24x0_clock_freq2() is meant to be called from kernel startup routines.
+ * s3c24{1,4}0_clock_freq2() is meant to be called from kernel startup routines.
  * s3c24x0_clock_freq() is for after kernel initialization is done.
  */
 void
-s3c24x0_clock_freq2(vm_offset_t clkman_base, int *fclk, int *hclk, int *pclk)
+s3c2410_clock_freq2(vm_offset_t clkman_base, int *fclk, int *hclk, int *pclk)
 {
 	uint32_t pllcon, divn;
 	int mdiv, pdiv, sdiv;
@@ -444,7 +445,7 @@
 
 	f = ((mdiv + 8) * S3C2XX0_XTAL_CLK) / ((pdiv + 2) * (1 << sdiv));
 	h = f;
-	if (divn & CLKDIVN_HDIVN)
+	if (divn & S3C2410_CLKDIVN_HDIVN)
 		h /= 2;
 	p = h;
 	if (divn & CLKDIVN_PDIVN)
@@ -453,7 +454,53 @@
 	if (fclk) *fclk = f;
 	if (hclk) *hclk = h;
 	if (pclk) *pclk = p;
+}
+
+void
+s3c2440_clock_freq2(vm_offset_t clkman_base, int *fclk, int *hclk, int *pclk)
+{
+	uint32_t pllcon, divn, camdivn;
+	int mdiv, pdiv, sdiv;
+	int f, h, p;
+
+	pllcon = *(volatile uint32_t *)(clkman_base + CLKMAN_MPLLCON);
+	divn = *(volatile uint32_t *)(clkman_base + CLKMAN_CLKDIVN);
+	camdivn = *(volatile uint32_t *)(clkman_base + S3C2440_CLKMAN_CAMDIVN);
+
+	mdiv = (pllcon & PLLCON_MDIV_MASK) >> PLLCON_MDIV_SHIFT;
+	pdiv = (pllcon & PLLCON_PDIV_MASK) >> PLLCON_PDIV_SHIFT;
+	sdiv = (pllcon & PLLCON_SDIV_MASK) >> PLLCON_SDIV_SHIFT;
+
+	f = (2 * (mdiv + 8) * S3C2XX0_XTAL_CLK) / ((pdiv + 2) * (1 << sdiv));
+	h = f;
+	switch((divn >> 1) & 3) {
+	case 0:
+		break;
+	case 1:
+		h /= 2;
+		break;
+	case 2:
+		if ((camdivn & S3C2440_CAMDIVN_HCLK4_HALF) ==
+		    S3C2440_CAMDIVN_HCLK4_HALF)
+			h /= 8;
+		else
+			h /= 4;
+		break;
+	case 3:
+		if ((camdivn & S3C2440_CAMDIVN_HCLK3_HALF) ==
+		    S3C2440_CAMDIVN_HCLK3_HALF)
+			h /= 6;
+		else
+			h /= 3;
+		break;
+	}
+	p = h;
+	if (divn & CLKDIVN_PDIVN)
+		p /= 2;
 
+	if (fclk) *fclk = f;
+	if (hclk) *hclk = h;
+	if (pclk) *pclk = p;
 }
 
 void
@@ -462,7 +509,16 @@
 	vm_offset_t va;
 	
 	va = sc->sc_clkman_ioh;
-	s3c24x0_clock_freq2(va, &sc->sc_fclk, &sc->sc_hclk, &sc->sc_pclk);
+	switch(sc->sc_cpu) {
+	case CPU_S3C2410:
+		s3c2410_clock_freq2(va, &sc->sc_fclk, &sc->sc_hclk,
+		    &sc->sc_pclk);
+		break;
+	case CPU_S3C2440:
+		s3c2440_clock_freq2(va, &sc->sc_fclk, &sc->sc_hclk,
+		    &sc->sc_pclk);
+		break;
+	}
 }
 
 void

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

@@ -149,36 +149,34 @@
 	 * with the MMU on or off.
 	 */
 	{
-		/*
-		 * Map the IRQ Controller
-		 */
-		_A(S3C24X0_INTCTL_BASE),
-		_A(S3C24X0_INTCTL_BASE),
-		_S(S3C24X0_INTCTL_SIZE),
+		_A(S3C24X0_CLKMAN_BASE),
+		_A(S3C24X0_CLKMAN_BASE),
+		_S(S3C24X0_CLKMAN_SIZE),
 		VM_PROT_READ|VM_PROT_WRITE, 
 		PTE_NOCACHE,
 	},
 	{
-		_A(S3C24X0_CLKMAN_BASE),
-		_A(S3C24X0_CLKMAN_BASE),
-		_S(S3C24X0_CLKMAN_SIZE),
-		VM_PROT_READ|VM_PROT_WRITE, 
+		_A(S3C24X0_GPIO_BASE),
+		_A(S3C24X0_GPIO_BASE),
+		_S(S3C2410_GPIO_SIZE),
+		VM_PROT_READ|VM_PROT_WRITE,                             
 		PTE_NOCACHE,
 	},
 	{
-		/*
-		 * Map the UART to VA == PA
-		 */
-		_A(S3C24X0_UART0_BASE),
-		_A(S3C24X0_UART0_BASE),
-		_S(S3C24X0_UART_BASE(3) - S3C24X0_UART0_BASE),
+		_A(S3C24X0_IIC_BASE),
+		_A(S3C24X0_IIC_BASE),
+		_S(S3C24X0_IIC_SIZE),
 		VM_PROT_READ|VM_PROT_WRITE,                             
 		PTE_NOCACHE,
 	},
 	{
-		/*
-		 * Map the LCD to VA == PA
-		 */
+		_A(S3C24X0_INTCTL_BASE),
+		_A(S3C24X0_INTCTL_BASE),
+		_S(S3C24X0_INTCTL_SIZE),
+		VM_PROT_READ|VM_PROT_WRITE, 
+		PTE_NOCACHE,
+	},
+	{
 		_A(S3C24X0_LCDC_BASE),
 		_A(S3C24X0_LCDC_BASE),
 		_S(S3C24X0_LCDC_SIZE),
@@ -186,9 +184,6 @@
 		PTE_NOCACHE,
 	},
 	{
-		/*
-		 * Map the MMC/SD to VA == PA
-		 */
 		_A(S3C24X0_SDI_BASE),
 		_A(S3C24X0_SDI_BASE),
 		_S(S3C2410_SDI_SIZE),
@@ -196,12 +191,9 @@
 		PTE_NOCACHE,
 	},
 	{
-		/*
-		 * Map the IIC to VA == PA
-		 */
-		_A(S3C24X0_IIC_BASE),
-		_A(S3C24X0_IIC_BASE),
-		_S(S3C24X0_IIC_SIZE),
+		_A(S3C24X0_UART0_BASE),
+		_A(S3C24X0_UART0_BASE),
+		_S(S3C24X0_UART_BASE(3) - S3C24X0_UART0_BASE),
 		VM_PROT_READ|VM_PROT_WRITE,                             
 		PTE_NOCACHE,
 	},
@@ -217,6 +209,7 @@
 #undef	_A
 #undef	_S
 
+#define	ioreg_read32(a)  	(*(volatile uint32_t *)(a))
 #define	ioreg_write32(a,v)	(*(volatile uint32_t *)(a)=(v))
 
 #ifdef DDB
@@ -389,7 +382,16 @@
 	ioreg_write32(S3C24X0_INTCTL_BASE + INTCTL_INTMSK, ~0);
 	memsize = board_init();
 	/* Find pclk for uart */
-	s3c24x0_clock_freq2(S3C24X0_CLKMAN_BASE, NULL, NULL, &s3c2410_pclk);
+	switch(ioreg_read32(S3C24X0_GPIO_BASE + GPIO_GSTATUS1) >> 16) {
+	case 0x3241:
+		s3c2410_clock_freq2(S3C24X0_CLKMAN_BASE, NULL, NULL,
+		    &s3c2410_pclk);
+		break;
+	case 0x3244:
+		s3c2440_clock_freq2(S3C24X0_CLKMAN_BASE, NULL, NULL,
+		    &s3c2410_pclk);
+		break;
+	}
 	cninit();
 
 	/* Set stack for exception handlers */

==== //depot/projects/arm/src/sys/arm/s3c2xx0/s3c24x0reg.h#4 (text+ko) ====

@@ -230,7 +230,6 @@
 #define	 CLKSLOW_VAL_MASK  0x0f	/* divider value for slow clock */
 
 #define	CLKMAN_CLKDIVN	0x14	/* Software reset control */
-#define	 CLKDIVN_HDIVN	(1<<1)
 #define	 CLKDIVN_PDIVN	(1<<0)
 
 #define	S3C24X0_CLKMAN_SIZE	0x18

==== //depot/projects/arm/src/sys/arm/s3c2xx0/s3c24x0var.h#4 (text+ko) ====

@@ -42,7 +42,8 @@
 };
 
 void	s3c24x0_clock_freq(struct s3c2xx0_softc *);
-void	s3c24x0_clock_freq2(vm_offset_t, int *, int *, int *);
+void	s3c2410_clock_freq2(vm_offset_t, int *, int *, int *);
+void	s3c2440_clock_freq2(vm_offset_t, int *, int *, int *);
 
 void	s3c24x0_sleep(int);
 

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

@@ -15,6 +15,8 @@
 #include <dev/uart/uart_bus.h>
 #include <dev/uart/uart_cpu.h>
 
+#include <arm/s3c2xx0/s3c24x0reg.h>
+
 #include "uart_if.h"
 
 static int uart_s3c2410_probe(device_t dev);
@@ -38,14 +40,20 @@
 static int
 uart_s3c2410_probe(device_t dev)
 {
+	struct uart_devinfo *sysdev;
 	struct uart_softc *sc;
+	int unit;
 
 	sc = device_get_softc(dev);
-	sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs);
 	sc->sc_class = &uart_s3c2410_class;
-	bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
-	return(uart_bus_probe(dev, 0, 0, 0, 0));
-	return (0);
+
+	unit = device_get_unit(dev);
+	sysdev = SLIST_FIRST(&uart_sysdevs);
+	if (S3C24X0_UART_BASE(unit) == sysdev->bas.bsh) {
+		sc->sc_sysdev = sysdev;
+		bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
+	}
+	return(uart_bus_probe(dev, 0, 0, 0, unit));
 }
 
 DRIVER_MODULE(uart, s3c24x0, uart_s3c2410_driver, uart_devclass, 0, 0);

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

@@ -41,9 +41,10 @@
 #include <dev/uart/uart.h>
 #include <dev/uart/uart_cpu.h>
 #include <dev/uart/uart_bus.h>
-#include <arm/s3c2xx0/s3c2410reg.h>
+#include <arm/s3c2xx0/s3c2440reg.h>
 #include <arm/s3c2xx0/uart_dev_s3c2410.h>
 #include <arm/s3c2xx0/s3c2xx0reg.h>
+#include <arm/s3c2xx0/s3c2xx0var.h>
 #include "uart_if.h"
 
 /* Finds the subirq from the parent */
@@ -240,14 +241,19 @@
 {
 	uintptr_t irq;
 
-	bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
-
-	/*
-	 * TODO: The S3C2410 has a 16 byte fifo, the s3c2440 has a
-	 * 64 byte fifo. figure out which CPU we are on to set this
-	 */
-	sc->sc_txfifosz = 16;
-	sc->sc_rxfifosz = 16;
+	switch(s3c2xx0_softc->sc_cpu) {
+	case CPU_S3C2410:
+		sc->sc_txfifosz = 16;
+		sc->sc_rxfifosz = 16;
+		break;
+	case CPU_S3C2440:
+		sc->sc_txfifosz = 64;
+		sc->sc_rxfifosz = 64;
+		break;
+	default:
+		return (ENXIO);
+	}
+		
 	sc->sc_hwiflow = 0;
 	sc->sc_hwoflow = 0;
 
@@ -256,6 +262,7 @@
 	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);
 }
 
@@ -316,22 +323,32 @@
 static int
 s3c2410_bus_ipend(struct uart_softc *sc)
 {
+	uint32_t ufstat, txmask, rxmask;
 	uintptr_t irq;
-	uint32_t ufstat;
 	int ipend = 0;
 
 	uart_lock(sc->sc_hwmtx);
 	ufstat = bus_space_read_4(sc->sc_bas.bst, sc->sc_bas.bsh, SSCOM_UFSTAT);
 	uart_unlock(sc->sc_hwmtx);
 
-	/* XXX: The register values are incorrect on the s3c244x */
-	if ((ufstat & UFSTAT_TXCOUNT) == 0) {
+	txmask = rxmask = 0;
+	switch (s3c2xx0_softc->sc_cpu) {
+	case CPU_S3C2410:
+		txmask = UFSTAT_TXCOUNT;
+		rxmask = UFSTAT_RXCOUNT;
+		break;
+	case CPU_S3C2440:
+		txmask = S3C2440_UFSTAT_TXCOUNT;
+		rxmask = S3C2440_UFSTAT_RXCOUNT;
+		break;
+	}
+	if ((ufstat & txmask) == 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 ((ufstat & UFSTAT_RXCOUNT) > 0) {
+	if ((ufstat & rxmask) > 0) {
 		ipend |= SER_INT_RXREADY;
 	}
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200902240953.n1O9rtCu039270>