svn commit: r237130 - head/sys/arm/at91

Warner Losh imp at FreeBSD.org
Fri Jun 15 08:37:51 UTC 2012


Author: imp
Date: Fri Jun 15 08:37:50 2012
New Revision: 237130
URL: http://svn.freebsd.org/changeset/base/237130

Log:
  Make it possible to link together a sam and an rm kernel.  The results
  aren't very pretty yet, but this takes DELAY and cpu_reset and makes
  them pointers.
  
  # I worry that these are set too late in the boot, especially cpu_reset.

Modified:
  head/sys/arm/at91/at91_machdep.c
  head/sys/arm/at91/at91_pit.c
  head/sys/arm/at91/at91_rst.c
  head/sys/arm/at91/at91_st.c
  head/sys/arm/at91/at91var.h

Modified: head/sys/arm/at91/at91_machdep.c
==============================================================================
--- head/sys/arm/at91/at91_machdep.c	Fri Jun 15 08:37:46 2012	(r237129)
+++ head/sys/arm/at91/at91_machdep.c	Fri Jun 15 08:37:50 2012	(r237130)
@@ -201,11 +201,22 @@ const struct pmap_devmap at91_devmap[] =
 	{ 0, 0, 0, 0, 0, }
 };
 
+#ifdef LINUX_BOOT_ABI
+extern int membanks;
+extern int memstart[];
+extern int memsize[];
+#endif
+
 long
 at91_ramsize(void)
 {
 	uint32_t cr, mr;
 	int banks, rows, cols, bw;
+#ifdef LINUX_BOOT_ABI
+	// If we found any ATAGs that were for memory, return the first bank.
+	if (membanks > 0)
+		return memsize[0];
+#endif
 
 	if (at91_is_rm92()) {
 		uint32_t *SDRAMC = (uint32_t *)(AT91_BASE + AT91RM92_SDRAMC_BASE);
@@ -593,3 +604,19 @@ cpu_initclocks(void)
 {
 
 }
+
+void
+DELAY(int n)
+{
+	if (soc_data.delay)
+		soc_data.delay(n);
+}
+
+void
+cpu_reset(void)
+{
+	if (soc_data.reset)
+		soc_data.reset();
+	while (1)
+		continue;
+}

Modified: head/sys/arm/at91/at91_pit.c
==============================================================================
--- head/sys/arm/at91/at91_pit.c	Fri Jun 15 08:37:46 2012	(r237129)
+++ head/sys/arm/at91/at91_pit.c	Fri Jun 15 08:37:50 2012	(r237130)
@@ -48,6 +48,10 @@ __FBSDID("$FreeBSD$");
 #include <arm/at91/at91var.h>
 #include <arm/at91/at91_pitreg.h>
 
+#ifndef PIT_PRESCALE
+#define PIT_PRESCALE (16)
+#endif
+
 static struct pit_softc {
 	struct resource	*mem_res;	/* Memory resource */
 	void		*intrhand;	/* Interrupt handle */
@@ -55,6 +59,8 @@ static struct pit_softc {
 } *sc;
 
 static uint32_t timecount = 0;
+static unsigned at91pit_get_timecount(struct timecounter *tc);
+static int pit_intr(void *arg);
 
 static inline uint32_t
 RD4(struct pit_softc *sc, bus_size_t off)
@@ -70,12 +76,28 @@ WR4(struct pit_softc *sc, bus_size_t off
 	bus_write_4(sc->mem_res, off, val);
 }
 
-static unsigned at91pit_get_timecount(struct timecounter *tc);
-static int pit_intr(void *arg);
+static void
+at91pit_delay(int us)
+{
+	int32_t cnt, last, piv;
+	uint64_t pit_freq;
+	const uint64_t mhz  = 1E6;
 
-#ifndef PIT_PRESCALE
-#define PIT_PRESCALE (16)
-#endif
+	last = PIT_PIV(RD4(sc, PIT_PIIR));
+
+	/* Max delay ~= 260s. @ 133Mhz */
+	pit_freq = at91_master_clock / PIT_PRESCALE;
+	cnt  = ((pit_freq * us) + (mhz -1)) / mhz;
+	cnt  = (cnt <= 0) ? 1 : cnt;
+
+	while (cnt > 0) {
+		piv = PIT_PIV(RD4(sc, PIT_PIIR));
+			cnt  -= piv - last ;
+		if (piv < last)
+			cnt -= PIT_PIV(~0u) - last;
+		last = piv;
+	}
+}
 
 static struct timecounter at91pit_timecounter = {
 	at91pit_get_timecount, /* get_timecount */
@@ -90,11 +112,8 @@ static int
 at91pit_probe(device_t dev)
 {
 
-	if (at91_is_sam9() || at91_is_sam9xe()) {
-		device_set_desc(dev, "AT91SAM9 PIT");
-		return (0);
-	}
-	return (ENXIO);
+	device_set_desc(dev, "AT91SAM9 PIT");
+        return (0);
 }
 
 static int
@@ -135,6 +154,7 @@ at91pit_attach(device_t dev)
 	/* Enable the PIT here. */
 	WR4(sc, PIT_MR, PIT_PIV(at91_master_clock / PIT_PRESCALE / hz) |
 	    PIT_EN | PIT_IEN);
+        soc_data.delay = at91pit_delay;
 out:
 	return (err);
 }
@@ -183,26 +203,3 @@ at91pit_get_timecount(struct timecounter
 	icnt = piir >> 20;	/* Overflows */
 	return (timecount + PIT_PIV(piir) + PIT_PIV(RD4(sc, PIT_MR)) * icnt);
 }
-
-void
-DELAY(int us)
-{
-	int32_t cnt, last, piv;
-	uint64_t pit_freq;
-	const uint64_t mhz  = 1E6;
-
-	last = PIT_PIV(RD4(sc, PIT_PIIR));
-
-	/* Max delay ~= 260s. @ 133Mhz */
-	pit_freq = at91_master_clock / PIT_PRESCALE;
-	cnt  = ((pit_freq * us) + (mhz -1)) / mhz;
-	cnt  = (cnt <= 0) ? 1 : cnt;
-
-	while (cnt > 0) {
-		piv = PIT_PIV(RD4(sc, PIT_PIIR));
-			cnt  -= piv - last ;
-		if (piv < last)
-			cnt -= PIT_PIV(~0u) - last;
-		last = piv;
-	}
-}

Modified: head/sys/arm/at91/at91_rst.c
==============================================================================
--- head/sys/arm/at91/at91_rst.c	Fri Jun 15 08:37:46 2012	(r237129)
+++ head/sys/arm/at91/at91_rst.c	Fri Jun 15 08:37:50 2012	(r237130)
@@ -42,50 +42,70 @@ __FBSDID("$FreeBSD$");
 #define RST_TIMEOUT (5)	/* Seconds to hold NRST for hard reset */
 #define RST_TICK (20)	/* sample NRST at hz/RST_TICK intervals */
 
-static int rst_intr(void *arg);
+static int at91rst_intr(void *arg);
 
-static struct rst_softc {
+static struct at91rst_softc {
 	struct resource	*mem_res;	/* Memory resource */
 	struct resource	*irq_res;	/* IRQ resource */
 	void		*intrhand;	/* Interrupt handle */
 	struct callout	tick_ch;	/* Tick callout */
 	device_t	sc_dev;
 	u_int		shutdown;	/* Shutdown in progress */
-} *rst_sc;
+} *at91rst_sc;
 
 static inline uint32_t
-RD4(struct rst_softc *sc, bus_size_t off)
+RD4(struct at91rst_softc *sc, bus_size_t off)
 {
 
 	return (bus_read_4(sc->mem_res, off));
 }
 
 static inline void
-WR4(struct rst_softc *sc, bus_size_t off, uint32_t val)
+WR4(struct at91rst_softc *sc, bus_size_t off, uint32_t val)
 {
 
 	bus_write_4(sc->mem_res, off, val);
 }
 
-static int
-at91_rst_probe(device_t dev)
+void cpu_reset_sam9g20(void) __attribute__((weak));
+void cpu_reset_sam9g20(void) {}
+
+static void
+at91rst_cpu_reset(void)
 {
 
-	if (at91_is_sam9() || at91_is_sam9xe()) {
-		device_set_desc(dev, "AT91SAM9 Reset Controller");
-		return (0);
+	if (at91rst_sc) {
+		cpu_reset_sam9g20(); /* May be null */
+
+		WR4(at91rst_sc, RST_MR,
+		    RST_MR_ERSTL(0xd) | RST_MR_URSTEN | RST_MR_KEY);
+
+		WR4(at91rst_sc, RST_CR,
+		    RST_CR_PROCRST |
+		    RST_CR_PERRST  |
+		    RST_CR_EXTRST  |
+		    RST_CR_KEY);
 	}
-	return (ENXIO);
+	while(1)
+		continue;
+}
+
+static int
+at91rst_probe(device_t dev)
+{
+
+	device_set_desc(dev, "AT91SAM9 Reset Controller");
+	return (0);
 }
 
 static int
-at91_rst_attach(device_t dev)
+at91rst_attach(device_t dev)
 {
-	struct rst_softc *sc;
+	struct at91rst_softc *sc;
 	const char *cause;
 	int rid, err;
 
-	rst_sc = sc = device_get_softc(dev);
+	at91rst_sc = sc = device_get_softc(dev);
 	sc->sc_dev = dev;
 
 	callout_init(&sc->tick_ch, 0);
@@ -109,11 +129,11 @@ at91_rst_attach(device_t dev)
 
 	/* Activate the interrupt. */
 	err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
-	    rst_intr, NULL, sc, &sc->intrhand);
+	    at91rst_intr, NULL, sc, &sc->intrhand);
 	if (err)
 		device_printf(dev, "could not establish interrupt handler.\n");
 
-	WR4(rst_sc, RST_MR, RST_MR_ERSTL(0xd) | RST_MR_URSIEN | RST_MR_KEY);
+	WR4(at91rst_sc, RST_MR, RST_MR_ERSTL(0xd) | RST_MR_URSIEN | RST_MR_KEY);
 
 	switch (RD4(sc, RST_SR) & RST_SR_RST_MASK) {
 		case	RST_SR_RST_POW:
@@ -137,16 +157,15 @@ at91_rst_attach(device_t dev)
 	}
 
 	device_printf(dev, "Reset cause: %s.\n", cause);
-	/* cpu_reset_addr = cpu_reset; */
-
+	soc_data.reset = at91rst_cpu_reset;
 out:
 	return (err);
 }
 
 static void
-rst_tick(void *argp)
+at91rst_tick(void *argp)
 {
-	struct rst_softc *sc = argp;
+	struct at91rst_softc *sc = argp;
 
 	if (sc->shutdown++ >= RST_TIMEOUT * RST_TICK) {
 		/* User released the button in morre than RST_TIMEOUT */
@@ -157,60 +176,36 @@ rst_tick(void *argp)
 		device_printf(sc->sc_dev, "shutting down...\n");
 		shutdown_nice(0);
 	} else {
-		callout_reset(&sc->tick_ch, hz/RST_TICK, rst_tick, sc);
+		callout_reset(&sc->tick_ch, hz/RST_TICK, at91rst_tick, sc);
 	}
 }
 
 static int
-rst_intr(void *argp)
+at91rst_intr(void *argp)
 {
-	struct rst_softc *sc = argp;
+	struct at91rst_softc *sc = argp;
 
 	if (RD4(sc, RST_SR) & RST_SR_URSTS) {
 		if (sc->shutdown == 0)
-			callout_reset(&sc->tick_ch, hz/RST_TICK, rst_tick, sc);
+			callout_reset(&sc->tick_ch, hz/RST_TICK, at91rst_tick, sc);
 		return (FILTER_HANDLED);
 	}
 	return (FILTER_STRAY);
 }
 
-static device_method_t at91_rst_methods[] = {
-	DEVMETHOD(device_probe, at91_rst_probe),
-	DEVMETHOD(device_attach, at91_rst_attach),
+static device_method_t at91rst_methods[] = {
+	DEVMETHOD(device_probe, at91rst_probe),
+	DEVMETHOD(device_attach, at91rst_attach),
 	DEVMETHOD_END
 };
 
-static driver_t at91_rst_driver = {
+static driver_t at91rst_driver = {
 	"at91_rst",
-	at91_rst_methods,
-	sizeof(struct rst_softc),
+	at91rst_methods,
+	sizeof(struct at91rst_softc),
 };
 
-static devclass_t at91_rst_devclass;
+static devclass_t at91rst_devclass;
 
-DRIVER_MODULE(at91_rst, atmelarm, at91_rst_driver, at91_rst_devclass, NULL,
+DRIVER_MODULE(at91_rst, atmelarm, at91rst_driver, at91rst_devclass, NULL,
     NULL);
-
-void cpu_reset_sam9g20(void) __attribute__((weak));
-void cpu_reset_sam9g20(void) {}
-
-void
-cpu_reset(void)
-{
-
-	if (rst_sc) {
-		cpu_reset_sam9g20(); /* May be null */
-
-		WR4(rst_sc, RST_MR,
-		    RST_MR_ERSTL(0xd) | RST_MR_URSTEN | RST_MR_KEY);
-
-		WR4(rst_sc, RST_CR,
-		    RST_CR_PROCRST |
-		    RST_CR_PERRST  |
-		    RST_CR_EXTRST  |
-		    RST_CR_KEY);
-	}
-
-	for(;;)
-		;
-}

Modified: head/sys/arm/at91/at91_st.c
==============================================================================
--- head/sys/arm/at91/at91_st.c	Fri Jun 15 08:37:46 2012	(r237129)
+++ head/sys/arm/at91/at91_st.c	Fri Jun 15 08:37:50 2012	(r237130)
@@ -84,6 +84,40 @@ static struct timecounter at91st_timecou
 	1000 /* quality */
 };
 
+static void
+at91st_delay(int n)
+{
+	uint32_t start, end, cur;
+
+	start = st_crtr();
+	n = (n * 1000) / 32768;
+	if (n <= 0)
+		n = 1;
+	end = (start + n) & ST_CRTR_MASK;
+	cur = start;
+	if (start > end) {
+		while (cur >= start || cur < end)
+			cur = st_crtr();
+	} else {
+		while (cur < end)
+			cur = st_crtr();
+	}
+}
+
+static void
+at91st_cpu_reset(void)
+{
+	/*
+	 * Reset the CPU by programmig the watchdog timer to reset the
+	 * CPU after 128 'slow' clocks, or about ~4ms.  Loop until
+	 * the reset happens for safety.
+	 */
+	WR4(ST_WDMR, ST_WDMR_RSTEN | 2);
+	WR4(ST_CR, ST_CR_WDRST);
+	while (1)
+		continue;
+}
+
 static int
 at91st_probe(device_t dev)
 {
@@ -112,6 +146,8 @@ at91st_attach(device_t dev)
 	WR4(ST_IDR, 0xffffffff);
 	/* disable watchdog timer */
 	WR4(ST_WDMR, 0);
+        soc_data.delay = at91st_delay;
+        soc_data.reset = at91st_cpu_reset;      // XXX kinda late to be setting this...
 
 	timer_softc->sc_wet = EVENTHANDLER_REGISTER(watchdog_list,
 	  at91st_watchdog, dev, 0);
@@ -221,37 +257,3 @@ at91st_initclocks(struct at91st_softc *s
 	WR4(ST_IER, ST_SR_PITS);
 	tc_init(&at91st_timecounter);
 }
-
-void
-DELAY(int n)
-{
-	uint32_t start, end, cur;
-
-	start = st_crtr();
-	n = (n * 1000) / 32768;
-	if (n <= 0)
-		n = 1;
-	end = (start + n) & ST_CRTR_MASK;
-	cur = start;
-	if (start > end) {
-		while (cur >= start || cur < end)
-			cur = st_crtr();
-	} else {
-		while (cur < end)
-			cur = st_crtr();
-	}
-}
-
-void
-cpu_reset(void)
-{
-	/*
-	 * Reset the CPU by programmig the watchdog timer to reset the
-	 * CPU after 128 'slow' clocks, or about ~4ms.  Loop until
-	 * the reset happens for safety.
-	 */
-	WR4(ST_WDMR, ST_WDMR_RSTEN | 2);
-	WR4(ST_CR, ST_CR_WDRST);
-	while (1)
-		continue;
-}

Modified: head/sys/arm/at91/at91var.h
==============================================================================
--- head/sys/arm/at91/at91var.h	Fri Jun 15 08:37:46 2012	(r237129)
+++ head/sys/arm/at91/at91var.h	Fri Jun 15 08:37:50 2012	(r237130)
@@ -102,6 +102,9 @@ enum at91_soc_family {
 
 #define AT91_SOC_NAME_MAX 50
 
+typedef void (*DELAY_t)(int);
+typedef void (*cpu_reset_t)(void);
+
 struct at91_soc_info {
 	enum at91_soc_type type;
 	enum at91_soc_subtype subtype;
@@ -109,6 +112,8 @@ struct at91_soc_info {
 	uint32_t cidr;
 	uint32_t exid;
 	char name[AT91_SOC_NAME_MAX];
+	DELAY_t delay;
+	cpu_reset_t reset;
 };
 
 extern struct at91_soc_info soc_data;


More information about the svn-src-all mailing list