Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 19 Mar 2009 20:27:25 GMT
From:      Ulf Lilleengen <lulf@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 159469 for review
Message-ID:  <200903192027.n2JKRPa5022228@repoman.freebsd.org>

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

Change 159469 by lulf@lulf_carrot on 2009/03/19 20:27:12

	- Re-add the device clock data to the ivar structure, which means that
	  we need to look it up from devclk. This is done by having lookup
	  routines which are supposed to registered for a devices' parent. This
	  routine will be called when there is a need to lookup the appropriate
	  clock for a device before operations are performed on it. Add these
	  handlers to at32_tc as well, because it's children will need to lookup
	  their clocks.
	- Add PBA clocks.
	- Add device clock for uart as an example.
	- Make sure pm is startup before other devices. Is there a prettier way
	  than reordering the hints? or should this be considered a design flaw
	  in devclk?

Affected files ...

.. //depot/projects/avr32/src/sys/avr32/avr32/at32.c#10 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/at32_pm.c#6 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/at32_tc.c#2 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/at32_tc_channel.c#2 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/clock.c#6 edit
.. //depot/projects/avr32/src/sys/avr32/conf/cpu/at32ap700x.hints#4 edit
.. //depot/projects/avr32/src/sys/dev/mmc/atmel_mci.c#3 edit
.. //depot/projects/avr32/src/sys/dev/uart/uart_bus_atmel.c#3 edit
.. //depot/projects/avr32/src/sys/dev/uart/uart_dev_atmel.c#5 edit
.. //depot/projects/avr32/src/sys/kern/devclk_if.m#5 edit
.. //depot/projects/avr32/src/sys/kern/subr_devclk.c#5 edit
.. //depot/projects/avr32/src/sys/sys/devclk.h#5 edit

Differences ...

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

@@ -72,6 +72,8 @@
 static void at32_clk_enable(device_t, device_t);
 static void at32_clk_disable(device_t, device_t);
 
+static const char *at32_clk_lookup_name(device_t, device_t);
+static int at32_clk_lookup_index(device_t, device_t);
 /* Driver variables and private data */
 struct at32_softc {
 	struct rman		sc_irq_rman;
@@ -79,6 +81,8 @@
 	struct rman		sc_mem_rman;
 };
 struct at32_ivar {
+	char *clk_name;
+	int clk_index;
 	struct resource_list	resources;
 };
 
@@ -99,6 +103,8 @@
 	DEVMETHOD(bus_get_resource,		bus_generic_rl_get_resource),
 	DEVMETHOD(bus_release_resource,		at32_release_resource),
 
+	DEVMETHOD(devclk_lookup_name,		at32_clk_lookup_name),
+	DEVMETHOD(devclk_lookup_index,		at32_clk_lookup_index),
 /*
 	DEVMETHOD(devclk_get_rate,		at32_clk_get_rate),
 	DEVMETHOD(devclk_set_rate,		at32_clk_set_rate),
@@ -189,9 +195,10 @@
 static void
 at32_hinted_child(device_t bus, const char *dname, int dunit)
 {
+	struct at32_ivar *ivar;
 	device_t child;
 	long maddr;
-	int msize, irq, result, clk_index;
+	int msize, irq, result;
 	const char *resval;
 	
 
@@ -216,11 +223,15 @@
 				"warning: bus_set_resource() failed\n");
 		}
 	}
+	ivar = device_get_ivars(child);
+	ivar->clk_name = NULL;
 	if (resource_string_value(dname, dunit, "clk", &resval) == 0) {
 		if (resource_int_value(dname, dunit, "clk_index",
-		    &clk_index) != 0)
-			clk_index = 0; /* Default */
-		devclk_register_map(child, resval, clk_index);
+		    &ivar->clk_index) != 0)
+			ivar->clk_index = 0; /* Default */
+		ivar->clk_name = malloc(strlen(resval) + 1, M_DEVBUF, M_WAITOK |
+		    M_ZERO);
+		strlcpy(ivar->clk_name, resval, strlen(resval) + 1);
 	}
 }
 
@@ -355,6 +366,25 @@
 	ivar = device_get_ivars(child);
 	return (&(ivar->resources));
 }
+
+static const char *
+at32_clk_lookup_name(device_t dev, device_t child)
+{
+	struct at32_ivar *ivar;
+
+	ivar = device_get_ivars(child);
+	return (ivar->clk_name);
+}
+
+static int
+at32_clk_lookup_index(device_t dev, device_t child)
+{
+	struct at32_ivar *ivar;
+
+	ivar = device_get_ivars(child);
+	return (ivar->clk_index);
+}
+
 #if 0
 static uint64_t
 at32_clk_get_rate(device_t dev, device_t child)

==== //depot/projects/avr32/src/sys/avr32/avr32/at32_pm.c#6 (text+ko) ====

@@ -65,6 +65,11 @@
 static int at32_pm_activate(device_t);
 static void at32_pm_deactivate(device_t);
 
+static void at32_pba_enable(devclk_t, int);
+static void at32_pba_disable(devclk_t, int);
+static uint64_t at32_pba_get_rate(devclk_t, int);
+static int at32_pba_set_rate(devclk_t, int, uint64_t);
+
 static void at32_pbb_enable(devclk_t, int);
 static void at32_pbb_disable(devclk_t, int);
 static uint64_t at32_pbb_get_rate(devclk_t, int);
@@ -135,6 +140,17 @@
 };
 DEFINE_CLASS(at32_pbb, at32_pbb_methods, sizeof(struct devclk));
 
+/* Class defining the pba clock mask. */
+static kobj_method_t at32_pba_methods[] = {
+	KOBJMETHOD(devclk_enable,	at32_pba_enable),
+	KOBJMETHOD(devclk_disable,	at32_pba_disable),
+	KOBJMETHOD(devclk_set_rate,	at32_pba_set_rate),
+	KOBJMETHOD(devclk_get_rate,	at32_pba_get_rate),
+	{0, 0},
+};
+DEFINE_CLASS(at32_pba, at32_pba_methods, sizeof(struct devclk));
+
+
 /* Code */
 static int
 at32_pm_probe(device_t dev)
@@ -194,6 +210,7 @@
 
 	/* Register master device clocks. */
 	devclk_register_clock(dev, &at32_pbb_class, "pbb", "pll0");
+	devclk_register_clock(dev, &at32_pba_class, "pba", "pll0");
 //	devclk_register_clock(dev, &sc->cpu, "cpu", &sc->pll0);
 //	devclk_register_clock(dev, &sc->hsb, "hsb", &sc->cpu);
 //	devclk_register_clock(dev, &sc->pba, "pba", &sc->hsb);
@@ -261,6 +278,45 @@
 }
 
 static void
+at32_pba_enable(devclk_t clk, int index)
+{
+	struct at32_pm_softc *sc;
+	uint32_t reg;
+
+	KASSERT(clk != NULL, ("NULL clk"));
+	KASSERT(index < 31, ("index > register width"));
+	sc = device_get_softc(clk->dev);
+	reg = RD4(AT32_PM_PBAMASK);
+	WR4(AT32_PM_PBAMASK, reg | (1 << index));
+}
+
+static void
+at32_pba_disable(devclk_t clk, int index)
+{
+	struct at32_pm_softc *sc;
+	uint32_t reg;
+
+	KASSERT(clk != NULL, ("NULL clk"));
+	KASSERT(index < 31, ("index > register width"));
+	sc = device_get_softc(clk->dev);
+	reg = RD4(AT32_PM_PBAMASK);
+	WR4(AT32_PM_PBAMASK, reg & ~(1 << index));
+}
+
+static uint64_t
+at32_pba_get_rate(devclk_t clk, int index)
+{
+	/* XXX: Temporary. */
+	return (clock_cpu_frequency);
+}
+
+static int
+at32_pba_set_rate(devclk_t clk, int index, uint64_t rate)
+{
+	return (0);
+}
+
+static void
 at32_osc_enable(devclk_t clk, int index)
 {
 	/* In this case, index means which oscilliator. */

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

@@ -67,6 +67,8 @@
 	u_long, u_long, u_long, u_int);
 static int at32_tc_release_resource(device_t, device_t, int, int,
 	struct resource *);
+static const char *at32_tc_clk_lookup_name(device_t, device_t);
+static int at32_tc_clk_lookup_index(device_t, device_t);
 
 /*** Driver variables and private data */
 struct at32_tc_softc {
@@ -97,6 +99,9 @@
 	DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
 	DEVMETHOD(bus_teardown_intr,		bus_generic_teardown_intr),
 
+	DEVMETHOD(devclk_lookup_name,		at32_tc_clk_lookup_name),
+	DEVMETHOD(devclk_lookup_index,		at32_tc_clk_lookup_index),
+
 	{0, 0},
 };
 static driver_t at32_tc_driver = {
@@ -348,3 +353,24 @@
 	return (0);
 }
 
+static const char *
+at32_tc_clk_lookup_name(device_t dev, device_t child)
+{
+	device_t parent;
+
+	parent = device_get_parent(dev);
+	if (parent != NULL)
+		return (DEVCLK_LOOKUP_NAME(parent, dev));
+	return (NULL);
+}
+
+static int
+at32_tc_clk_lookup_index(device_t dev, device_t child)
+{
+	device_t parent;
+
+	parent = device_get_parent(dev);
+	if (parent != NULL)
+		return (DEVCLK_LOOKUP_INDEX(parent, dev));
+	return (NULL);
+}

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


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


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

@@ -10,6 +10,11 @@
 hint.at32_dmaca.0.msize="0x100000"
 hint.at32_dmaca.0.irq="2"
 
+hint.at32_pm.0.at="at32bus0"
+hint.at32_pm.0.maddr="0xFFF00000"
+hint.at32_pm.0.msize="0x80"
+hint.at32_pm.0.irq="20"
+
 hint.atmel_spi.0.at="at32bus0"
 hint.atmel_spi.0.maddr="0xFFE00000"
 hint.atmel_spi.0.msize="0x400"
@@ -29,21 +34,29 @@
 hint.uart.0.maddr="0xFFE00C00"
 hint.uart.0.msize="0x400"
 hint.uart.0.irq="6"
+hint.uart.0.clk="pba"
+hint.uart.0.clk_index="3"
 
 hint.uart.1.at="at32bus0"
 hint.uart.1.maddr="0xFFE01000"
 hint.uart.1.msize="0x400"
 hint.uart.1.irq="7"
+#hint.uart.1.clk="pba"
+#hint.uart.1.clk_index="4"
 
 hint.uart.2.at="at32bus0"
 hint.uart.2.maddr="0xFFE01400"
 hint.uart.2.msize="0x400"
 hint.uart.2.irq="8"
+#hint.uart.2.clk="pba"
+#hint.uart.2.clk_index="5"
 
 hint.uart.3.at="at32bus0"
 hint.uart.3.maddr="0xFFE01800"
 hint.uart.3.msize="0x400"
 hint.uart.3.irq="9"
+#hint.uart.3.clk="pba"
+#hint.uart.3.clk_index="6"
 
 hint.atmel_ssc.0.at="at32bus0"
 hint.atmel_ssc.0.maddr="0xFFE01C00"
@@ -90,11 +103,6 @@
 hint.at32_psif.0.msize="0x124"
 hint.at32_psif.0.irq="18"
 
-hint.at32_pm.0.at="at32bus0"
-hint.at32_pm.0.maddr="0xFFF00000"
-hint.at32_pm.0.msize="0x80"
-hint.at32_pm.0.irq="20"
-
 hint.at32_rtc.0.at="at32bus0"
 hint.at32_rtc.0.maddr="0xFFF00080"
 hint.at32_rtc.0.msize="0x30"

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


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


==== //depot/projects/avr32/src/sys/dev/uart/uart_dev_atmel.c#5 (text+ko) ====


==== //depot/projects/avr32/src/sys/kern/devclk_if.m#5 (text+ko) ====

@@ -54,3 +54,15 @@
 	devclk_t	_clk;
 	int		_index;
 };
+
+# Look for clock name
+METHOD const char* lookup_name {
+	device_t	_dev;
+	device_t	_child;
+};
+
+# Look for clock index
+METHOD int lookup_index {
+	device_t	_dev;
+	device_t	_child;
+};

==== //depot/projects/avr32/src/sys/kern/subr_devclk.c#5 (text+ko) ====

@@ -39,19 +39,7 @@
 
 #include "devclk_if.h"
 
-/* TODO:
- - Maybe a bit inefficient.
- */
-
-struct devclk_map {
-	device_t dev;
-	char clk_name[32];
-	int clk_index;
-	STAILQ_ENTRY(devclk_map) link;
-};
-
 static devclk_list_t devclks;
-static STAILQ_HEAD(, devclk_map) devclk_maps;
 
 static devclk_t devclk_find_clock(const char *);
 
@@ -59,86 +47,101 @@
 devclk_init(void)
 {
 	STAILQ_INIT(&devclks);
-	STAILQ_INIT(&devclk_maps);
 }
 
 uint64_t
 devclk_get_rate(device_t dev)
 {
-	struct devclk_map *map;
+	device_t parent;
 	devclk_t clk;
-	/* XXX: We need to think of the mapping here. */
-	STAILQ_FOREACH(map, &devclk_maps, link) {
-		if (map->dev != dev)
-			continue;
-		clk = devclk_find_clock(map->clk_name);
+	const char *name;
+	int index;
+
+	/* The device parent should know which clock to use. */
+	parent = device_get_parent(dev);
+	if (parent != NULL) {
+		name = DEVCLK_LOOKUP_NAME(parent, dev);
+		if (name == NULL)
+			goto bad;
+		index = DEVCLK_LOOKUP_INDEX(parent, dev);
+		clk = devclk_find_clock(name);
 		if (clk == NULL)
-			continue;
-		return (DEVCLK_GET_RATE(clk, map->clk_index));
+			goto bad;
+		return (DEVCLK_GET_RATE(clk, index));
 	}
+bad:
 	return (EINVAL);
 }
 
 int
 devclk_set_rate(device_t dev, uint64_t rate)
 {
-	struct devclk_map *map;
+	device_t parent;
 	devclk_t clk;
-	/* XXX: We need to think of the mapping here. */
-	STAILQ_FOREACH(map, &devclk_maps, link) {
-		if (map->dev != dev)
-			continue;
-		clk = devclk_find_clock(map->clk_name);
+	const char *name;
+	int index;
+
+	/* The device parent should know which clock to use. */
+	parent = device_get_parent(dev);
+	if (parent != NULL) {
+		name = DEVCLK_LOOKUP_NAME(parent, dev);
+		if (name == NULL)
+			goto bad;
+		index = DEVCLK_LOOKUP_INDEX(parent, dev);
+		clk = devclk_find_clock(name);
 		if (clk == NULL)
-			continue;
-		/* XXX: Enable parent too ? */
-		DEVCLK_SET_RATE(clk, map->clk_index, rate);
+			goto bad;
+		DEVCLK_SET_RATE(clk, index, rate);
 		return (0);
 	}
+bad:
 	return (EINVAL);
 }
 
 void
 devclk_enable(device_t dev)
 {
-	struct devclk_map *map;
+	device_t parent;
 	devclk_t clk;
+	const char *name;
+	int index;
 
-	/* Enable all clocks this device is mapped to. */
-	/*
-	 * XXX: This looks a bit silly right now, and this information should
-	 * perhaps be retrieved from the device somehow, but that makes it
-	 * machine dependant.
-	 */
-	STAILQ_FOREACH(map, &devclk_maps, link) {
-		if (map->dev != dev)
-			continue;
-		clk = devclk_find_clock(map->clk_name);
-		if (clk == NULL)
-			continue;
-		/* XXX: Enable parent too ? */
-		DEVCLK_ENABLE(clk, map->clk_index);
+	/* The device parent should know which clock to use. */
+	parent = device_get_parent(dev);
+	if (parent != NULL) {
+		name = DEVCLK_LOOKUP_NAME(parent, dev);
+		if (name == NULL)
+			return;
+		index = DEVCLK_LOOKUP_INDEX(parent, dev);
+		clk = devclk_find_clock(name);
+		if (clk != NULL)
+			DEVCLK_ENABLE(clk, index);
 	}
 }
 
 void
 devclk_disable(device_t dev)
 {
-	struct devclk_map *map;
+	device_t parent;
 	devclk_t clk;
+	const char *name;
+	int index;
 
-	/* Enable all clocks this device is mapped to. */
-	STAILQ_FOREACH(map, &devclk_maps, link) {
-		clk = devclk_find_clock(map->clk_name);
-		if (clk == NULL)
-			continue;
-		/* XXX: Enable parent too ? */
-		DEVCLK_DISABLE(clk, map->clk_index);
+	/* The device parent should know which clock to use. */
+	parent = device_get_parent(dev);
+	if (parent != NULL) {
+		name = DEVCLK_LOOKUP_NAME(parent, dev);
+		if (name == NULL)
+			return;
+		index = DEVCLK_LOOKUP_INDEX(parent, dev);
+		clk = devclk_find_clock(name);
+		if (clk != NULL)
+			DEVCLK_DISABLE(clk, index);
 	}
 }
 
 /**
- * Register clock name handled by device dev, with the parent clock parent
+ * Register clock to be associated with dev
  */
 void
 devclk_register_clock(device_t dev, kobj_class_t cls, const char *name,
@@ -155,23 +158,6 @@
 	STAILQ_INSERT_HEAD(&devclks, clk, link);
 }
 
-/*
- * Register a mapping between a clock and a device.
- */
-void
-devclk_register_map(device_t dev, const char *clk, int index)
-{
-	struct devclk_map *map;
-
-	map = malloc(sizeof(*clk), M_DEVBUF, M_WAITOK | M_ZERO);
-	map->dev = dev;
-	strlcpy(map->clk_name, clk, sizeof(map->clk_name));
-	map->clk_index = index;
-
-	/* Insert into map. */
-	STAILQ_INSERT_HEAD(&devclk_maps, map, link);
-}
-
 static devclk_t
 devclk_find_clock(const char *name)
 {

==== //depot/projects/avr32/src/sys/sys/devclk.h#5 (text+ko) ====




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