Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 14 Dec 2005 18:24:15 GMT
From:      Warner Losh <imp@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 88185 for review
Message-ID:  <200512141824.jBEIOFc6082501@repoman.freebsd.org>

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

Change 88185 by imp@imp_Speedy on 2005/12/14 18:23:48

	attempt to make the atmelarm bus do real resource allocation.

Affected files ...

.. //depot/projects/arm/src/sys/arm/at91/at91rm92.c#6 edit
.. //depot/projects/arm/src/sys/arm/at91/at91rm92var.h#3 edit

Differences ...

==== //depot/projects/arm/src/sys/arm/at91/at91rm92.c#6 (text+ko) ====

@@ -29,6 +29,7 @@
 #include <sys/systm.h>
 #include <sys/bus.h>
 #include <sys/kernel.h>
+#include <sys/malloc.h>
 #include <sys/module.h>
 
 #include <vm/vm.h>
@@ -160,7 +161,7 @@
 static int
 at91rm92_probe(device_t dev)
 {
-	device_set_desc(dev, "AT91RM9200");
+	device_set_desc(dev, "AT91 CPU");
 	return (0);
 }
 
@@ -186,6 +187,30 @@
 
 extern void irq_entry(void);
 
+static void
+at91rm92_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 at91rm92_ivar *ivar;
+
+	kid = device_add_child_ordered(dev, prio, name, unit);
+	if (kid == NULL)
+		return;
+	ivar = malloc(sizeof(*ivar), M_DEVBUF, M_WAITOK | M_ZERO);
+	if (ivar == NULL) {
+		device_delete_child(dev, kid);
+		return;
+	}
+	device_set_ivars(kid, ivar);
+	resource_list_init(&ivar->resources);
+	if (irq != -1)
+		bus_set_resource(kid, SYS_RES_IRQ, 0, irq, 1);
+	if (addr != 0)
+		bus_set_resource(kid, SYS_RES_MEMORY, 0, addr, size);
+}
+
+
 static int
 at91rm92_attach(device_t dev)
 {
@@ -196,14 +221,20 @@
 	sc->sc_st = &at91rm92_bs_tag;
 	sc->sc_sh = AT91RM92_BASE;
 	sc->dev = dev;
-	sc->sc_irq_rman.rm_type = RMAN_ARRAY;
-	sc->sc_irq_rman.rm_descr = "AT91RM92 IRQs";
 	if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_SYS_BASE,
 	    AT91RM92_SYS_SIZE, &sc->sc_sys_sh) != 0)
 		panic("Enable to map IRQ registers");
+	sc->sc_irq_rman.rm_type = RMAN_ARRAY;
+	sc->sc_irq_rman.rm_descr = "AT91RM92 IRQs";
+	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
+	sc->sc_mem_rman.rm_descr = "AT91RM92 Memory";
 	if (rman_init(&sc->sc_irq_rman) != 0 ||
 	    rman_manage_region(&sc->sc_irq_rman, 1, 31) != 0)
 		panic("at91rm92_attach: failed to set up IRQ rman");
+	if (rman_init(&sc->sc_mem_rman) != 0 ||
+	    rman_manage_region(&sc->sc_mem_rman, 0xfff00000ul,
+		0xfffffffful) != 0)
+		panic("at91rm92_attach: failed to set up memory rman");
 
 	for (i = 0; i < 32; i++) {
 		bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_SVR + 
@@ -223,7 +254,18 @@
 	/* Disable and clear all interrupts. */
 	bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_IDCR, 0xffffffff);
 	bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_ICCR, 0xffffffff);
-	device_add_child(dev, "at91rm92_timer", 0);
+
+	at91rm92_add_child(dev, 0, "at91rm92_timer", 0, 0, 0, 1);
+	at91rm92_add_child(dev, 10, "uart", 0, AT91RM92_BASE +
+	    AT91RM92_SYS_BASE + DBGU, DBGU_SIZE, 1);		// DBGU
+	at91rm92_add_child(dev, 10, "uart", 1, AT91RM92_BASE +
+	    AT91RM92_USART0_BASE, AT91RM92_USART_SIZE, 6);	// USART0
+	at91rm92_add_child(dev, 10, "uart", 2, AT91RM92_BASE +
+	    AT91RM92_USART1_BASE, AT91RM92_USART_SIZE, 7);	// USART1
+	at91rm92_add_child(dev, 10, "uart", 3, AT91RM92_BASE +
+	    AT91RM92_USART2_BASE, AT91RM92_USART_SIZE, 8);	// USART2
+	at91rm92_add_child(dev, 10, "uart", 4, AT91RM92_BASE +
+	    AT91RM92_USART3_BASE, AT91RM92_USART_SIZE, 9);	// USART3
 	bus_generic_probe(dev);
 	bus_generic_attach(dev);
 	enable_interrupts(I32_bit | F32_bit);
@@ -251,11 +293,67 @@
     u_long start, u_long end, u_long count, u_int flags)
 {
 	struct at91rm92_softc *sc = device_get_softc(dev);
+	struct resource_list_entry *rle;
+	struct at91rm92_ivar *ivar = device_get_ivars(child);
+	struct resource_list *rl = &ivar->resources;
+
+	if (device_get_parent(child) != dev)
+		return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
+		    type, rid, start, end, count, flags));
 	
-	if (type == SYS_RES_IRQ) 
-		return (rman_reserve_resource(&sc->sc_irq_rman,
-		    start, end, count, flags, child));
-	return (NULL);
+	rle = resource_list_find(rl, type, *rid);
+	if (rle == NULL)
+		return (NULL);
+	if (rle->res)
+		panic("Resource rid %d type %d already in use", *rid, type);
+	if (start == 0UL && end == ~0UL) {
+		start = rle->start;
+		count = ulmax(count, rle->count);
+		end = ulmax(rle->end, start + count - 1);
+	}
+	switch (type)
+	{
+	case SYS_RES_IRQ:
+		rle->res = rman_reserve_resource(&sc->sc_irq_rman,
+		    start, end, count, flags, child);
+		break;
+	case SYS_RES_MEMORY:
+		rle->res = rman_reserve_resource(&sc->sc_mem_rman,
+		    start, end, count, flags, child);
+	}
+	if (rle->res) {
+		rle->start = rman_get_start(rle->res);
+		rle->end = rman_get_end(rle->res);
+		rle->count = count;
+	}
+	return (rle->res);
+}
+
+static struct resource_list *
+at91rm92_get_resource_list(device_t dev, device_t child)
+{
+	struct at91rm92_ivar *ivar;
+
+	ivar = device_get_ivars(child);
+	return (&(ivar->resources));
+}
+
+static int
+at91rm92_release_resource(device_t dev, device_t child, int type,
+    int rid, struct resource *r)
+{
+	struct resource_list *rl;
+	struct resource_list_entry *rle;
+
+	rl = at91rm92_get_resource_list(dev, child);
+	if (rl == NULL)
+		return (EINVAL);
+	rle = resource_list_find(rl, type, rid);
+	if (rle == NULL)
+		return (EINVAL);
+	rman_release_resource(r);
+	rle->res = NULL;
+	return (0);
 }
 
 static int
@@ -287,6 +385,7 @@
 at91rm92_activate_resource(device_t bus, device_t child, int type, int rid,
     struct resource *r)
 {
+#if 0
 	u_long p;
 	int error;
 	
@@ -296,11 +395,34 @@
 		if (error) 
 			return (error);
 		rman_set_bushandle(r, p);
-	
 	}
+#endif	
 	return (rman_activate_resource(r));
 }
 
+static int
+at91rm92_print_child(device_t dev, device_t child)
+{
+	struct at91rm92_ivar *ivars;
+	struct resource_list *rl;
+	int retval = 0;
+
+	ivars = device_get_ivars(child);
+	rl = &ivars->resources;
+
+	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))
+		retval += printf(" flags %#x", device_get_flags(dev));
+
+	retval += bus_print_child_footer(dev, child);
+
+	return (retval);
+}
+
 void
 arm_mask_irq(uintptr_t nb)
 {
@@ -342,12 +464,17 @@
 	DEVMETHOD(device_probe, at91rm92_probe),
 	DEVMETHOD(device_attach, at91rm92_attach),
 	DEVMETHOD(device_identify, at91rm92_identify),
+
 	DEVMETHOD(bus_alloc_resource, at91rm92_alloc_resource),
 	DEVMETHOD(bus_setup_intr, at91rm92_setup_intr),
 	DEVMETHOD(bus_teardown_intr, at91rm92_teardown_intr),
-	DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
 	DEVMETHOD(bus_activate_resource, at91rm92_activate_resource),
 	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+	DEVMETHOD(bus_get_resource_list,at91rm92_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,	at91rm92_release_resource),
+	DEVMETHOD(bus_print_child,	at91rm92_print_child),
 
 	{0, 0},
 };

==== //depot/projects/arm/src/sys/arm/at91/at91rm92var.h#3 (text+ko) ====

@@ -35,6 +35,12 @@
 	bus_space_handle_t sc_sh;
 	bus_space_handle_t sc_sys_sh;
 	struct rman sc_irq_rman;
+	struct rman sc_mem_rman;
+};
+
+struct at91rm92_ivar {
+	struct resource_list resources;
 };
 
+
 #endif /* _AT91RM92VAR_H_ */



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