Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 8 Feb 2009 23:42:01 GMT
From:      Arnar Mar Sig <antab@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 157407 for review
Message-ID:  <200902082342.n18Ng1en053173@repoman.freebsd.org>

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

Change 157407 by antab@antab_farm on 2009/02/08 23:41:58

	Change nexus and at32bus to use hints instead of builtin list.
	Add interrupt handling, seems to be working but need to test more.
	Add at32_pm, at32_intc and at32_sdramc driver skeletons for testing.
	First draft of clock handling, just a api skeleton for device drivers
	to call to enable/disable and get/set rate.

Affected files ...

.. //depot/projects/avr32/src/sys/avr32/avr32/at32.c#3 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/at32_intc.c#1 add
.. //depot/projects/avr32/src/sys/avr32/avr32/at32_pio.c#2 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/at32_pm.c#1 add
.. //depot/projects/avr32/src/sys/avr32/avr32/at32_rtc.c#2 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/at32_sdramc.c#1 add
.. //depot/projects/avr32/src/sys/avr32/avr32/at32ap700x.c#2 delete
.. //depot/projects/avr32/src/sys/avr32/avr32/clock.c#3 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/cpu.c#4 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/exception.S#3 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/intr.c#3 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/machdep.c#4 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/nexus.c#3 edit
.. //depot/projects/avr32/src/sys/avr32/conf/NGW100#4 edit
.. //depot/projects/avr32/src/sys/avr32/conf/cpu/at32ap7000.hints#1 add
.. //depot/projects/avr32/src/sys/avr32/conf/cpu/at32ap7002.hints#1 add
.. //depot/projects/avr32/src/sys/avr32/conf/cpu/at32ap700x.hints#1 add
.. //depot/projects/avr32/src/sys/avr32/include/at32.h#3 delete
.. //depot/projects/avr32/src/sys/avr32/include/at32ap700x.h#2 edit
.. //depot/projects/avr32/src/sys/avr32/include/cpu.h#4 edit
.. //depot/projects/avr32/src/sys/avr32/include/intr.h#3 edit
.. //depot/projects/avr32/src/sys/avr32/include/reg.h#3 edit
.. //depot/projects/avr32/src/sys/avr32/include/reg_intc.h#2 edit
.. //depot/projects/avr32/src/sys/avr32/include/reg_pm.h#1 add
.. //depot/projects/avr32/src/sys/avr32/include/reg_rtc.h#2 edit
.. //depot/projects/avr32/src/sys/avr32/include/reg_sdramc.h#1 add
.. //depot/projects/avr32/src/sys/conf/files#2 edit
.. //depot/projects/avr32/src/sys/conf/files.avr32#4 edit
.. //depot/projects/avr32/src/sys/conf/ldscript.avr32#3 edit
.. //depot/projects/avr32/src/sys/dev/uart/uart_dev_atmel.c#3 edit
.. //depot/projects/avr32/src/sys/sys/devclk.h#1 add

Differences ...

==== //depot/projects/avr32/src/sys/avr32/avr32/at32.c#3 (text+ko) ====

@@ -29,6 +29,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/bus.h>
+#include <sys/devclk.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
 #include <sys/module.h>
@@ -43,39 +44,66 @@
 #include <machine/cpu.h>
 #include <machine/bus.h>
 #include <machine/intr.h>
-#include <machine/at32.h>
+#include <machine/reg.h>
+#include <machine/reg_pm.h>
 #include <machine/at32ap700x.h>
 #include <machine/debug.h>
 
 /* Prototypes */
+static int at32_probe(device_t);
+static int at32_attach(device_t);
+static device_t at32_add_child(device_t, int, const char *, int);
+static void at32_hinted_child(device_t, const char *, int);
 static struct resource_list *at32_get_resource_list(device_t, device_t);
 static int at32_print_child(device_t, device_t);
-static int at32_activate_resource(device_t, device_t, int, int, struct resource *);
+static int at32_activate_resource(device_t, device_t, int, int,
+	struct resource *);
+static int at32_deactivate_resource(device_t, device_t, int, int,
+	struct resource *);
 static int at32_teardown_intr(device_t, device_t, struct resource *, void *);
-static int at32_setup_intr(device_t, device_t, struct resource *, int, driver_filter_t *, driver_intr_t *, void *, void **);
-static int at32_release_resource(device_t, device_t, int, int, struct resource *);
-static struct resource *at32_alloc_resource(device_t, device_t, int, int *, u_long, u_long, u_long, u_int);
-static int at32_attach(device_t);
-static void at32_add_child(device_t, int, const char *, int, bus_addr_t, bus_size_t, int);
-static void at32_identify(driver_t *, device_t);
-static int at32_probe(device_t);
+static int at32_setup_intr(device_t, device_t, struct resource *, int,
+	driver_filter_t *, driver_intr_t *, void *, void **);
+static int at32_release_resource(device_t, device_t, int, int,
+	struct resource *);
+static struct resource *at32_alloc_resource(device_t, device_t, int, int *,
+	u_long, u_long, u_long, u_int);
+static uint64_t at32_clk_get_rate(device_t, device_t);
+static int at32_clk_set_rate(device_t, device_t, uint64_t);
+static void at32_clk_enable(device_t, device_t);
+static void at32_clk_disable(device_t, device_t);
 
 /* Driver variables and private data */
+struct at32_softc {
+	struct rman		sc_irq_rman;
+	struct resource		*sc_mem_res;
+	struct rman		sc_mem_rman;
+};
+struct at32_ivar {
+	struct resource_list	resources;
+	int			clk_bus;
+	int			clk_index;
+};
 static device_method_t at32_methods[] = {
 	DEVMETHOD(device_probe,			at32_probe),
 	DEVMETHOD(device_attach,		at32_attach),
-	DEVMETHOD(device_identify,		at32_identify),
 
+	DEVMETHOD(bus_add_child,		at32_add_child),
+	DEVMETHOD(bus_hinted_child,		at32_hinted_child),
+	DEVMETHOD(bus_print_child,		at32_print_child),
 	DEVMETHOD(bus_alloc_resource,		at32_alloc_resource),
 	DEVMETHOD(bus_setup_intr,		at32_setup_intr),
 	DEVMETHOD(bus_teardown_intr,		at32_teardown_intr),
 	DEVMETHOD(bus_activate_resource,	at32_activate_resource),
-	DEVMETHOD(bus_deactivate_resource,	bus_generic_deactivate_resource),
+	DEVMETHOD(bus_deactivate_resource,	at32_deactivate_resource),
 	DEVMETHOD(bus_get_resource_list,	at32_get_resource_list),
 	DEVMETHOD(bus_set_resource,		bus_generic_rl_set_resource),
 	DEVMETHOD(bus_get_resource,		bus_generic_rl_get_resource),
 	DEVMETHOD(bus_release_resource,		at32_release_resource),
-	DEVMETHOD(bus_print_child,		at32_print_child),
+
+	DEVMETHOD(devclk_get_rate,		at32_clk_get_rate),
+	DEVMETHOD(devclk_set_rate,		at32_clk_set_rate),
+	DEVMETHOD(devclk_enable,		at32_clk_enable),
+	DEVMETHOD(devclk_disable,		at32_clk_disable),
 	{0, 0},
 };
 static driver_t at32_driver = {
@@ -94,87 +122,94 @@
 	return (0);
 }
 
-static void
-at32_identify(driver_t *drv, device_t parent)
-{
-	BUS_ADD_CHILD(parent, 0, "at32bus", 0);
-}
-
-static void
-at32_add_child(device_t dev, int prio, const char *name, int unit,
-    bus_addr_t addr, bus_size_t size, int irq)
-{
-	device_t kid;
-	struct at32_ivar *ivar;
-
-	kid = device_add_child_ordered(dev, prio, name, unit);
-	if (kid == NULL) {
-		printf("Can't add child %s%d ordered\n", name, unit);
-		return;
-	}
-	ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
-	if (ivar == NULL) {
-		device_delete_child(dev, kid);
-		printf("Can't add alloc ivar\n");
-		return;
-	}
-	device_set_ivars(kid, ivar);
-	resource_list_init(&ivar->resources);
-	if (addr != 0) {
-		bus_set_resource(kid, SYS_RES_MEMORY, 0, addr, size);
-	}
-	if (irq != -1) {
-		bus_set_resource(kid, SYS_RES_IRQ, 0, irq, 1);
-	}
-}
-
 static int
 at32_attach(device_t dev)
 {
-	int i;
+	int rid;
 	struct at32_softc *sc = device_get_softc(dev);
-	struct at32_cpu_device *walker;
 
-	sc->sc_st = 0;
-	sc->sc_sh = AT32AP700X_BASE;
-	sc->dev = dev;
-
-	// Resource list for IRQ
+	/* Resource list for IRQ */
+	/* Reserve irqs from nexus ? */
 	sc->sc_irq_rman.rm_type = RMAN_ARRAY;
 	sc->sc_irq_rman.rm_descr = "AT32 IRQs";
 	if (rman_init(&sc->sc_irq_rman) != 0 ||
-	    rman_manage_region(&sc->sc_irq_rman, 1, IRQ_COUNT) != 0) {
-		panic("at32_attach: failed to set up IRQ rman");
+		rman_manage_region(&sc->sc_irq_rman, 1, IRQ_COUNT) != 0) {
+		panic("at32_attach: failed to set up IRQ rman\n");
 	}
 
-	// Resource list for system memory
+	/* Resource list for system memory */
+	rid = 0;
+	sc->sc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
+		AVR32_SEG_P4, 0xfffffffful, 0, RF_ACTIVE);
+	if (sc->sc_mem_res == NULL) {
+		panic("at32_attach: failed to alloc bus memory\n");
+	}
 	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
 	sc->sc_mem_rman.rm_descr = "AT32 Memory";
 	if (rman_init(&sc->sc_mem_rman) != 0 ||
-	    rman_manage_region(&sc->sc_mem_rman, AVR32_SEG_P4,
-	    0xfffffffful) != 0) {
+		rman_manage_region(&sc->sc_mem_rman, AVR32_SEG_P4,
+		0xfffffffful) != 0) {
 		panic("at32_attach: fail to set up memory rman\n");
 	}
 
-	/* Reserve memory range for INTC, we will handle access to it */
-	sc->sc_intc_res = rman_reserve_resource(&sc->sc_mem_rman,
-	    AT32AP700X_BASE + AT32AP700X_INTC_OFFSET,
-	    AT32AP700X_BASE + AT32AP700X_INTC_OFFSET + AT32AP700X_INTC_SIZE,
-	    AT32AP700X_INTC_SIZE, 0, dev);
-	if (!sc->sc_intc_res) {
-		panic("at32_attach: unable to reserve INTC memory\n");
+	bus_generic_probe(dev);
+	bus_enumerate_hinted_children(dev);
+	bus_generic_attach(dev);
+	return 0;
+}
+
+static device_t
+at32_add_child(device_t bus, int order, const char *name, int unit)
+{
+	device_t child;
+	struct at32_ivar *ivar;
+
+	ivar = malloc(sizeof(struct at32_ivar), M_DEVBUF, M_WAITOK | M_ZERO);
+	if (ivar == NULL) {
+		device_printf(bus, "Failed to allocate ivar\n");
+		return (0);
+	}
+	resource_list_init(&ivar->resources);
+
+	child = device_add_child_ordered(bus, order, name, unit);
+	if (child == NULL) {
+		device_printf(bus, "Can't add child %s%d ordered\n", name, unit);
+		return (0);
 	}
 
+	device_set_ivars(child, ivar);
+
+	return (child);
+}
+
+static void
+at32_hinted_child(device_t bus, const char *dname, int dunit)
+{
+	device_t child;
+	long maddr;
+	int msize, irq, result;
+
+	child = BUS_ADD_CHILD(bus, 0, dname, dunit);
+
+	/*
+	 * Set hard-wired resources for hinted child using
+	 * specific RIDs.
+	 */
+	resource_long_value(dname, dunit, "maddr", &maddr);
+	resource_int_value(dname, dunit, "msize", &msize);
 
-	// Add buildin devices
-	for (i = 0, walker = at32_cpu_devices; walker->name; i++, walker++) {
-		at32_add_child(dev, i, walker->name, walker->unit,
-		    walker->mem_base, walker->mem_len, walker->irq);
-	};
+	result = bus_set_resource(child, SYS_RES_MEMORY, 0, maddr, msize);
+	if (result != 0) {
+		device_printf(bus, "warning: bus_set_resource() failed\n");
+	}
 
-	bus_generic_probe(dev);
-	bus_generic_attach(dev);
-	return 0;
+	if (resource_int_value(dname, dunit, "irq", &irq) == 0) {
+		result = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1);
+		if (result != 0) {
+			device_printf(bus,
+				"warning: bus_set_resource() failed\n");
+		}
+	}
 }
 
 static struct resource *
@@ -247,32 +282,38 @@
 
 static int
 at32_setup_intr(device_t dev, device_t child, struct resource *ires, int flags,
-    driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep)
+	driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep)
 {
 	if ((rman_get_flags(ires) & RF_SHAREABLE) == 0) {
 		flags |= INTR_EXCL;
 	}
-
-	avr32_setup_irqhandler(device_get_nameunit(child),
-	    filt, intr, arg, rman_get_start(ires), flags, cookiep);
+	BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, filt,
+		intr, arg, cookiep);
 	return (0);
 }
 
 static int
 at32_teardown_intr(device_t dev, device_t child, struct resource *res,
-    void *cookie)
+	void *cookie)
 {
-	return (avr32_remove_irqhandler(rman_get_start(res), cookie));
+	return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
 }
 
 static int
 at32_activate_resource(device_t bus, device_t child, int type, int rid,
-    struct resource *r)
+	struct resource *r)
 {
 	return (rman_activate_resource(r));
 }
 
 static int
+at32_deactivate_resource(device_t bus, device_t child, int type, int rid,
+	struct resource *r)
+{
+	return (rman_deactivate_resource(r));
+}
+
+static int
 at32_print_child(device_t dev, device_t child)
 {
 	struct at32_ivar *ivars;
@@ -284,7 +325,6 @@
 
 	retval += bus_print_child_header(dev, child);
 
-	retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx");
 	retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
 	retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
 	if (device_get_flags(dev)) {
@@ -304,4 +344,28 @@
 	return (&(ivar->resources));
 }
 
+static uint64_t
+at32_clk_get_rate(device_t dev, device_t child)
+{
+	avr32_impl();
+	return (0);
+}
+
+static int
+at32_clk_set_rate(device_t dev, device_t child, uint64_t rate)
+{
+	avr32_impl();
+	return (0);
+}
+
+static void
+at32_clk_enable(device_t dev, device_t child)
+{
+	/* TODO: Implement */
+}
 
+static void
+at32_clk_disable(device_t dev, device_t child)
+{
+	/* TODO: Implement */
+}

==== //depot/projects/avr32/src/sys/avr32/avr32/at32_pio.c#2 (text+ko) ====

@@ -33,6 +33,7 @@
 #include <sys/module.h>
 #include <sys/time.h>
 #include <sys/bus.h>
+#include <sys/devclk.h>
 #include <sys/resource.h>
 #include <sys/rman.h>
 #include <sys/timetc.h>
@@ -42,7 +43,6 @@
 #include <machine/cpu.h>
 #include <machine/cpufunc.h>
 #include <machine/resource.h>
-#include <machine/at32.h>
 #include <machine/reg.h>
 #include <machine/reg_pio.h>
 #include <machine/debug.h>
@@ -105,8 +105,10 @@
 at32_pio_attach(device_t dev)
 {
 	struct at32_pio_softc *sc = device_get_softc(dev);
+	sc->dev = dev;
 
-	sc->dev = dev;
+	/* Make sure clock is active before doing anything */
+	devclk_enable(dev);
 
 	return 0;
 }

==== //depot/projects/avr32/src/sys/avr32/avr32/at32_rtc.c#2 (text+ko) ====

@@ -30,7 +30,7 @@
  *    fRTC = 2 ^ -(PSEL + 1) * 32KHz
  * The datasheet also says we should set PSEL to at last 2 to ensure no ticks
  * are missed when entering sleep modes.
- * So we will set PSEL to 14 giving us a 1Hz clock
+ * So we will set PSEL to 14 giving us a 1Hz
  */
 
 #include <sys/cdefs.h>
@@ -42,6 +42,7 @@
 #include <sys/module.h>
 #include <sys/time.h>
 #include <sys/bus.h>
+#include <sys/devclk.h>
 #include <sys/resource.h>
 #include <sys/rman.h>
 #include <sys/clock.h>
@@ -49,16 +50,15 @@
 #include <machine/bus.h>
 #include <machine/cpu.h>
 #include <machine/resource.h>
-#include <machine/at32.h>
 #include <machine/reg.h>
 #include <machine/reg_rtc.h>
 
 #include "clock_if.h"
 
 #define RD4(off) \
-	bus_space_read_4(sc->sc_bst, sc->sc_bsh, (off))
+	bus_space_read_4(sc->bst, sc->bsh, (off))
 #define WR4(off, val) \
-	bus_space_write_4(sc->sc_bst, sc->sc_bsh, (off), (val))
+	bus_space_write_4(sc->bst, sc->bsh, (off), (val))
 
 /* Prototypes */
 static int at32_rtc_probe(device_t);
@@ -66,14 +66,16 @@
 static int at32_rtc_detach(device_t);
 static int at32_rtc_gettime(device_t, struct timespec *);
 static int at32_rtc_settime(device_t, struct timespec *);
+static int at32_rtc_activate(device_t);
+static void at32_rtc_deactivate(device_t);
 
 /* Driver variables and private data */
-static struct at32_rtc_softc {
-	struct resource		*sc_regs_res;
-	int			sc_regs_rid;
-	bus_space_tag_t		sc_bst;
-	bus_space_handle_t	sc_bsh;
-} *rtc_softc;
+struct at32_rtc_softc {
+	struct resource		*regs_res;
+	int			regs_rid;
+	bus_space_tag_t		bst;
+	bus_space_handle_t	bsh;
+};
 static device_method_t at32_rtc_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		at32_rtc_probe),
@@ -104,29 +106,23 @@
 at32_rtc_attach(device_t dev)
 {
 	struct at32_rtc_softc *sc = device_get_softc(dev);
+	int err;
 
-	/* Global Pointer to private data, (cant i get with passed in
-	 * timecounter callback? */
-	rtc_softc = sc;
-
-	/* Set private data and map register space */
-	sc->sc_regs_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->sc_regs_rid, 0,
-	   ~0, 0, RF_ACTIVE);
-	if (!sc->sc_regs_res) {
-		return (ENOMEM);
+	err = at32_rtc_activate(dev);
+	if (err) {
+		return (err);
 	}
-	sc->sc_bsh = rman_get_bushandle(sc->sc_regs_res);
-	sc->sc_bst = rman_get_bustag(sc->sc_regs_res);
 
-	/* Enable RTC and set prescaler to 14 */
+	/* Enable RTC and set prescaler to 2 */
 	WR4(AT32_RTC_CTRL,
-	    2 << bit_shift(RTC, CTRL, PSEL) |
-	    bit_offset(RTC, CTRL, PCLR) |
-	    bit_offset(RTC, CTRL, EN));
+		2 << bit_shift(RTC, CTRL, PSEL) |
+		bit_offset(RTC, CTRL, PCLR) |
+		bit_offset(RTC, CTRL, EN));
+
+	/* Enable interrupt on TOP */
+	WR4(AT32_RTC_IER, bit_offset(RTC, IER, TOPI));
 
 	clock_register(dev, 1000000);
-
-
 	return (0);
 }
 
@@ -134,7 +130,12 @@
 at32_rtc_detach(device_t dev)
 {
 	struct at32_rtc_softc *sc = device_get_softc(dev);
-	bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_regs_rid, sc->sc_regs_res);
+
+	/* Disable interrupt */
+	WR4(AT32_RTC_IER, bit_offset(RTC, IER, TOPI));
+
+	at32_rtc_deactivate(dev);
+	return (0);
 }
 
 static int
@@ -153,3 +154,42 @@
 	WR4(AT32_RTC_VAL, ts->tv_sec);
 	return (0);
 }
+
+static int
+at32_rtc_activate(device_t dev)
+{
+	struct at32_rtc_softc *sc = device_get_softc(dev);
+	int rid, err = ENOMEM;
+
+	/* Make sure device clock is enabled before writing */
+	devclk_enable(dev);
+
+	/* Set private data and map register space */
+	sc->regs_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->regs_rid, 0,
+		~0, 0, RF_ACTIVE);
+	if (!sc->regs_res) {
+		goto err;
+	}
+	sc->bsh = rman_get_bushandle(sc->regs_res);
+	sc->bst = rman_get_bustag(sc->regs_res);
+
+	return (0);
+
+err:
+	at32_rtc_deactivate(dev);
+	return (err);
+}
+
+static void
+at32_rtc_deactivate(device_t dev)
+{
+	struct at32_rtc_softc *sc = device_get_softc(dev);
+
+	if (sc->regs_res) {
+		bus_release_resource(dev, SYS_RES_MEMORY,
+		    rman_get_rid(sc->regs_res), sc->regs_res);
+	}
+
+	/* Turn off device clock */
+	devclk_disable(dev);
+}

==== //depot/projects/avr32/src/sys/avr32/avr32/clock.c#3 (text+ko) ====

@@ -38,6 +38,7 @@
 #include <sys/smp.h>
 #include <sys/time.h>
 #include <sys/timetc.h>
+#include <sys/cpu.h>
 
 #include <machine/clock.h>
 #include <machine/reg.h>

==== //depot/projects/avr32/src/sys/avr32/avr32/cpu.c#4 (text+ko) ====

@@ -64,25 +64,13 @@
 #include <machine/at32ap700x.h>
 
 extern vm_offset_t _evba;
-extern vm_offset_t _evba_irq;
 
 void
 cpu_init(void)
 {
-	int i;
-
 	/* Set exception vector */
 	sysreg_write(EVBA, (uint32_t)&_evba);
 	__asm__ __volatile__ ("csrf %0" : : "i"(AT32_SYS_SR_EM));
-
-
-	/* Setup INTC, every interrupt is at priority 0 */
-/*	for (i = 0; i < IRQ_COUNT; i++) {
-		reg_write(AT32AP700X_BASE + AT32AP700X_INTC_OFFSET +
-		    (i * sizeof(register_t)), INTC, IPR,
-		    (_evba_irq - _evba));
-	}
-*/
 }
 
 void

==== //depot/projects/avr32/src/sys/avr32/avr32/exception.S#3 (text+ko) ====

@@ -26,27 +26,52 @@
  */
 
 #include <machine/asm.h>
+#include <machine/at32ap700x.h>
 #include <machine/reg_sys.h>
+#include <machine/reg_intc.h>
 #include "assym.s"
 
 __FBSDID("$FreeBSD: $");
 
 /* Save a trapfrome to stack */
-#define PUSH_TRAPFRAME					\
-	sub		sp, 4;						\
-	stmts	--sp, r0-lr;				\
-	mfsr	r11, AT32_SYS_RAR_EX;		\
-	mfsr	r12, AT32_SYS_RSR_EX;		\
+#define PUSH_TRAPFRAME(context)					\
+	sub	sp, 4;						\
+	stmts	--sp, r0-lr;					\
+	mfsr	r11, AT32_SYS_RAR_##context;			\
+	mfsr	r12, AT32_SYS_RSR_##context;			\
 	pushm	r11-r12;
 
 /* Restore trapframe from stack */
-#define POP_TRAPFRAME					\
+#define POP_TRAPFRAME(context)					\
 	popm	r11-r12;					\
-	mtsr	AT32_SYS_RAR_EX, r11;		\
-	mtsr	AT32_SYS_RSR_EX, r12;		\
-	ldmts	sp++, r0-lr;				\
-	sub		sp, -4
+	mtsr	AT32_SYS_RAR_##context, r11;			\
+	mtsr	AT32_SYS_RSR_##context, r12;			\
+	ldmts	sp++, r0-lr;					\
+	sub	sp, -4;
+
+/* Handle IRQ */
+#define IRQ(num)						\
+	GLOBAL(intr_handle##num);				\
+	PUSH_TRAPFRAME(INT##num);				\
+	mov	r10, num;					\
+	lddpc	r12, intr_cause_offset##num;			\
+	ld.w	r11, r12;					\
+	mov	r12, sp;					\
+	call	intr_handle;					\
+	POP_TRAPFRAME(INT##num);				\
+	rete;							\
+intr_cause_offset##num:;					\
+	.long AT32AP700X_BASE + AT32AP700X_INTC_OFFSET +	\
+	    AT32_INTC_ICR0 - (4 * num);
+
+#if 0
+#define IRQ(num)					\
+	GLOBAL(intr_handle##num);			\
+	sub	r12, pc, (. - i##num);			\
+	bral    panic;					\
+i##num:	.asciz  "IRQ!";
 
+#endif
 .section .text.evba,"ax",@progbits
 
 .align 2
@@ -110,12 +135,12 @@
 
 /* later this should be done in assembly, but using C for now */
 tlb_miss:
-	PUSH_TRAPFRAME
+	PUSH_TRAPFRAME(EX)
 	mfsr    r12, AT32_SYS_ECR
 	mfsr    r11, AT32_SYS_TLBEAR
 	mfsr    r10, AT32_SYS_TLBEHI
 	rcall   pmap_tlb_miss
-	POP_TRAPFRAME
+	POP_TRAPFRAME(EX)
 	rete
 
 handle_critical:
@@ -126,26 +151,26 @@
 	rete
 
 handle_illegal_opcode:
-	PUSH_TRAPFRAME
+	PUSH_TRAPFRAME(EX)
 	mfsr    r12, AT32_SYS_ECR
-	mov		r11, sp
+	mov	r11, sp
 	rcall	trap_handle_illegal_opcode
 	rete
 
 handle_address_fault:
-	PUSH_TRAPFRAME
+	PUSH_TRAPFRAME(EX)
 	mfsr	r12, AT32_SYS_ECR
-	mov		r11, sp
+	mov	r11, sp
 	rcall	trap_handle_address_fault
-	POP_TRAPFRAME
+	POP_TRAPFRAME(EX)
 	rete
 
 handle_protection_fault:
-	PUSH_TRAPFRAME
+	PUSH_TRAPFRAME(EX)
 	mfsr	r12, AT32_SYS_ECR
-	mov		r11, sp
+	mov	r11, sp
 	rcall	trap_handle_protection_fault
-	POP_TRAPFRAME
+	POP_TRAPFRAME(EX)
 	rete
 
 handle_dtlb_modified:
@@ -153,16 +178,14 @@
 	rete
 
 handle_breakpoint:
-	PUSH_TRAPFRAME
-	mov		r12, AT32_SYS_ECR
-	mov		r11, sp
+	PUSH_TRAPFRAME(EX)
+	mov	r12, AT32_SYS_ECR
+	mov	r11, sp
 	rcall	trap_handle_breakpoint
-	POP_TRAPFRAME
+	POP_TRAPFRAME(EX)
 	rete
 
-.section .text.evba.irq
-ENTRY(handle_irq)
-	sub r12, pc, (. - 2f)
-	bral    panic
-	rete
-2:  .asciz  "Interrupt handler needed"
+IRQ(0)
+IRQ(1)
+IRQ(2)
+IRQ(3)

==== //depot/projects/avr32/src/sys/avr32/avr32/intr.c#3 (text+ko) ====

@@ -41,10 +41,12 @@
 #include <machine/reg.h>
 #include <machine/reg_sys.h>
 #include <machine/reg_intc.h>
+#include <machine/reg_pm.h>
 #include <machine/at32ap700x.h>
 
 /* Private data */
-static struct intr_event *intr_events[IRQ_COUNT];
+static struct intr_event *intr_event[IRQ_COUNT];
+extern vm_offset_t _evba;
 
 /* Code */
 register_t
@@ -70,14 +72,46 @@
 }
 
 void
+intr_init()
+{
+	size_t offset;
+	int i;
+
+	/* Setup INTC, every interrupt is at priority 0 */
+	for (i = 0; i < IRQ_COUNT; i++) {
+		offset = AT32AP700X_BASE + AT32AP700X_INTC_OFFSET +
+			(i * sizeof(register_t));
+
+		reg_write(offset, INTC, IPR,
+			(vm_offset_t)intr_handle0 - (vm_offset_t)&_evba);
+	}
+
+	/* Enable interrupts */
+	sysreg_write(COMPARE, 0);
+	sysreg_write(SR, sysreg_read(SR) & ~INTR_MASK);
+}
+
+void
+intr_handle(struct trapframe *tf, int irq, int pri)
+{
+	if (!intr_event[irq] || TAILQ_EMPTY(&intr_event[irq]->ie_handlers)) {
+		printf("stray interrupt %d, priority %d\n", irq, pri);
+		return;
+	}
+
+	if (intr_event_handle(intr_event[irq], tf) != 0) {
+		panic("stray interrupt %d, priority %d\n", irq, pri);
+	}
+}
+
+void
 avr32_mask_irq(uintptr_t irq)
 {
 	int pri;
 
-	avr32_impl();
 	pri = bit_value(INTC, IPR, INTLEVEL,
-	    reg_read(AT32AP700X_BASE + AT32AP700X_INTC_OFFSET +
-		(irq * sizeof(register_t)), INTC, IPR));
+		reg_read(AT32AP700X_BASE + AT32AP700X_INTC_OFFSET +
+			(irq * sizeof(register_t)), INTC, IPR));
 	sysreg_write(SR, sysreg_read(SR) | (bit_offset(SYS, SR, I0M) << pri));
 }
 
@@ -86,12 +120,10 @@
 {
 	int pri;
 
-	avr32_impl();
 	pri = bit_value(INTC, IPR, INTLEVEL,
-	    reg_read(AT32AP700X_BASE + AT32AP700X_INTC_OFFSET +
-		(irq * sizeof(register_t)), INTC, IPR));
+		reg_read(AT32AP700X_BASE + AT32AP700X_INTC_OFFSET +
+			(irq * sizeof(register_t)), INTC, IPR));
 	sysreg_write(SR, sysreg_read(SR) | ~(bit_offset(SYS, SR, I0M) << pri));
-
 }
 
 void
@@ -105,18 +137,18 @@
 		return;
 	}
 
-	event = intr_events[irq];
+	event = intr_event[irq];
 	if (event == NULL) {
 		error = intr_event_create(&event, (void *)irq, 0, irq,
-		    (mask_fn)avr32_mask_irq, (mask_fn)avr32_unmask_irq,
-		    NULL, NULL, "intr%d:", irq);
+			(mask_fn)avr32_mask_irq, (mask_fn)avr32_unmask_irq,
+			NULL, NULL, "intr%d:", irq);
 		if (error) {
 			return;
 		}
-		intr_events[irq] = event;
+		intr_event[irq] = event;
 	}
 	intr_event_add_handler(event, name, filt, hand, arg,
-	    intr_priority(flags), flags, cookiep);
+		intr_priority(flags), flags, cookiep);
 }
 int
 avr32_remove_irqhandler(int irq, void *cookie)
@@ -124,7 +156,8 @@
 	struct intr_event *event;
 	int error;
 
-	event = intr_events[irq];
+
+	event = intr_event[irq];
 	avr32_mask_irq(irq);
 
 	error = intr_event_remove_handler(cookie);

==== //depot/projects/avr32/src/sys/avr32/avr32/machdep.c#4 (text+ko) ====

@@ -65,10 +65,16 @@
 #include <machine/uboot.h>
 #include <machine/debug.h>
 #include <machine/pte.h>
+#include <machine/intr.h>
+
+/* Prototypes */
+void mi_startup(void);
+void avr32_init(void);
+static void avr32_init_proc0(void);
 
+/* Misc variables and private data */
 struct msgbuf *msgbufp = NULL;
 int cold = 1;
-
 struct pcpu __pcpu;
 struct pcpu *pcpup = &__pcpu;
 struct pcb proc0_pcb;
@@ -82,14 +88,13 @@
 static void cpu_startup(void *);
 SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
 
-// Prototypes (Should be in headers!)
-void mi_startup(void);
-void avr32_init(void);
-void avr32_init_proc0(void);
-
-void avr32_init() {
-	cninit();				// Init console
-	cpu_init();				// Init needed cpu things (evb and irq)
+/* Code */
+void
+avr32_init()
+{
+	cninit();			// Init console
+	cpu_init();			// Init needed cpu things (evb and irq)
+	intr_init();			// Init interrupt handling
 	uboot_parse_tags();		// Parse uboot tags
 
 	realmem = btoc(phys_avail[1] - phys_avail[0]);
@@ -102,7 +107,9 @@
 	mi_startup();			// Call machine independent part
 }
 
-void avr32_init_proc0() {
+static void
+avr32_init_proc0()
+{
 	proc_linkup(&proc0, &thread0);
 	thread0.td_kstack = proc0_stack_end;
 	thread0.td_kstack_pages = KSTACK_PAGES - 1;
@@ -114,14 +121,16 @@
 	PCPU_SET(curpcb, thread0.td_pcb);
 }
 
-static void cpu_startup(void *dummy) {
+static void
+cpu_startup(void *dummy)
+{
 	uint32_t config;
 	char arch_type;
 
 	if (boothowto & RB_VERBOSE) {
 		bootverbose++;
 	}
-	bootverbose++;
+//	bootverbose++;
 
 	vm_ksubmap_init(&kmi);
 
@@ -170,7 +179,7 @@
 
 	printf("real memory  = %u (%u MB)\n", ptoa(realmem),
 		ptoa(realmem) / 1048576);
-	printf("avail memory = %u (%uMB)\n", ptoa(cnt.v_free_count),
+	printf("avail memory = %u (%u MB)\n", ptoa(cnt.v_free_count),
 		ptoa(cnt.v_free_count) / 1048576);
 
 	/*
@@ -180,41 +189,57 @@
 	vm_pager_bufferinit();
 }
 
-void cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) {
+void
+cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
+{
 	pcpu->pc_asid_next = 1;
 	pcpu->pc_asid_generation = 1;
 }
 
-int fill_regs(struct thread *td, struct reg *regs) {
+int
+fill_regs(struct thread *td, struct reg *regs)
+{
 	memcpy(regs, &td->td_frame->regs, sizeof(struct reg));
 	return (0);
 }
 
-int fill_fpregs(struct thread *td, struct fpreg *regs) {
+int
+fill_fpregs(struct thread *td, struct fpreg *regs)
+{
 	/* No FPU on avr32 */
 	memset(regs, 0, sizeof(struct fpreg));
 	return (0);
 }
 
-int set_regs(struct thread *td, struct reg *regs) {
+int
+set_regs(struct thread *td, struct reg *regs)
+{
 	memcpy(&td->td_frame->regs, regs, sizeof(struct reg));
 	return (0);
 }
 
-int set_fpregs(struct thread *td, struct fpreg *regs) {
+int
+set_fpregs(struct thread *td, struct fpreg *regs)
+{
 	/* No FPU on avr32 */
 	return (0);
 }
 
-int fill_dbregs(struct thread *td, struct dbreg *regs) {
+int
+fill_dbregs(struct thread *td, struct dbreg *regs)
+{
 	return (0);
 }
 
-int set_dbregs(struct thread *td, struct dbreg *regs) {
+int
+set_dbregs(struct thread *td, struct dbreg *regs)
+{
 	return (0);
 }

>>> TRUNCATED FOR MAIL (1000 lines) <<<



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