svn commit: r280294 - head/sys/arm/broadcom/bcm2835

Andrew Turner andrew at FreeBSD.org
Fri Mar 20 16:54:23 UTC 2015


Author: andrew
Date: Fri Mar 20 16:54:21 2015
New Revision: 280294
URL: https://svnweb.freebsd.org/changeset/base/280294

Log:
  Add a helper function to read clock frequencies from videocore and use this
  to get the default frequency of the sdhci device.
  
  While here use a u_int to hold the frequency as it may be too large to fit
  in a 32-bit signed integer. This is the case when we have a 250MHz clock.

Modified:
  head/sys/arm/broadcom/bcm2835/bcm2835_mbox.c
  head/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h
  head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c

Modified: head/sys/arm/broadcom/bcm2835/bcm2835_mbox.c
==============================================================================
--- head/sys/arm/broadcom/bcm2835/bcm2835_mbox.c	Fri Mar 20 16:05:13 2015	(r280293)
+++ head/sys/arm/broadcom/bcm2835/bcm2835_mbox.c	Fri Mar 20 16:54:21 2015	(r280294)
@@ -284,53 +284,63 @@ bcm2835_mbox_dma_cb(void *arg, bus_dma_s
 	*addr = PHYS_TO_VCBUS(segs[0].ds_addr);
 }
 
-int
-bcm2835_mbox_set_power_state(device_t dev, uint32_t device_id, boolean_t on)
+static void *
+bcm2835_mbox_init_dma(device_t dev, size_t len, bus_dma_tag_t *tag,
+    bus_dmamap_t *map, bus_addr_t *phys)
 {
-	struct msg_set_power_state *msg;
-	bus_dma_tag_t msg_tag;
-	bus_dmamap_t msg_map;
-	bus_addr_t msg_phys;
-	void *msg_buf;
-	uint32_t reg;
-	device_t mbox;
+	void *buf;
 	int err;
 
-	/* get mbox device */
-	mbox = devclass_get_device(devclass_find("mbox"), 0);
-	if (mbox == NULL) {
-		device_printf(dev, "can't find mbox\n");
-		return (ENXIO);
-	}
-
 	err = bus_dma_tag_create(bus_get_dma_tag(dev), 16, 0,
 	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
-	    sizeof(struct msg_set_power_state), 1,
-	    sizeof(struct msg_set_power_state), 0,
-	    NULL, NULL, &msg_tag);
+	    len, 1, len, 0, NULL, NULL, tag);
 	if (err != 0) {
 		device_printf(dev, "can't create DMA tag\n");
-		return (ENXIO);
+		return (NULL);
 	}
 
-	err = bus_dmamem_alloc(msg_tag, (void **)&msg_buf, 0, &msg_map);
+	err = bus_dmamem_alloc(*tag, &buf, 0, map);
 	if (err != 0) {
-		bus_dma_tag_destroy(msg_tag);
+		bus_dma_tag_destroy(*tag);
 		device_printf(dev, "can't allocate dmamem\n");
-		return (ENXIO);
+		return (NULL);
 	}
 
-	err = bus_dmamap_load(msg_tag, msg_map, msg_buf,
+	err = bus_dmamap_load(*tag, *map, buf,
 	    sizeof(struct msg_set_power_state), bcm2835_mbox_dma_cb,
-	    &msg_phys, 0);
+	    phys, 0);
 	if (err != 0) {
-		bus_dmamem_free(msg_tag, msg_buf, msg_map);
-		bus_dma_tag_destroy(msg_tag);
+		bus_dmamem_free(*tag, buf, *map);
+		bus_dma_tag_destroy(*tag);
 		device_printf(dev, "can't load DMA map\n");
+		return (NULL);
+	}
+
+	return (buf);
+}
+
+int
+bcm2835_mbox_set_power_state(device_t dev, uint32_t device_id, boolean_t on)
+{
+	struct msg_set_power_state *msg;
+	bus_dma_tag_t msg_tag;
+	bus_dmamap_t msg_map;
+	bus_addr_t msg_phys;
+	uint32_t reg;
+	device_t mbox;
+
+	/* get mbox device */
+	mbox = devclass_get_device(devclass_find("mbox"), 0);
+	if (mbox == NULL) {
+		device_printf(dev, "can't find mbox\n");
 		return (ENXIO);
 	}
 
-	msg = msg_buf;
+	/* Allocate memory for the message */
+	msg = bcm2835_mbox_init_dma(dev, sizeof(*msg), &msg_tag, &msg_map,
+	    &msg_phys);
+	if (msg == NULL)
+		return (ENOMEM);
 
 	memset(msg, 0, sizeof(*msg));
 	msg->hdr.buf_size = sizeof(*msg);
@@ -350,7 +360,56 @@ bcm2835_mbox_set_power_state(device_t de
 	MBOX_READ(mbox, BCM2835_MBOX_CHAN_PROP, &reg);
 
 	bus_dmamap_unload(msg_tag, msg_map);
-	bus_dmamem_free(msg_tag, msg_buf, msg_map);
+	bus_dmamem_free(msg_tag, msg, msg_map);
+	bus_dma_tag_destroy(msg_tag);
+
+	return (0);
+}
+
+int
+bcm2835_mbox_get_clock_rate(device_t dev, uint32_t clock_id, uint32_t *hz)
+{
+	struct msg_get_clock_rate *msg;
+	bus_dma_tag_t msg_tag;
+	bus_dmamap_t msg_map;
+	bus_addr_t msg_phys;
+	uint32_t reg;
+	device_t mbox;
+
+	/* get mbox device */
+	mbox = devclass_get_device(devclass_find("mbox"), 0);
+	if (mbox == NULL) {
+		device_printf(dev, "can't find mbox\n");
+		return (ENXIO);
+	}
+
+	/* Allocate memory for the message */
+	msg = bcm2835_mbox_init_dma(dev, sizeof(*msg), &msg_tag, &msg_map,
+	    &msg_phys);
+	if (msg == NULL)
+		return (ENOMEM);
+
+	memset(msg, 0, sizeof(*msg));
+	msg->hdr.buf_size = sizeof(*msg);
+	msg->hdr.code = BCM2835_MBOX_CODE_REQ;
+	msg->tag_hdr.tag = BCM2835_MBOX_TAG_GET_CLOCK_RATE;
+	msg->tag_hdr.val_buf_size = sizeof(msg->body);
+	msg->tag_hdr.val_len = sizeof(msg->body.req);
+	msg->body.req.clock_id = clock_id;
+	msg->end_tag = 0;
+
+	bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_PREWRITE);
+	MBOX_WRITE(mbox, BCM2835_MBOX_CHAN_PROP, (uint32_t)msg_phys);
+	bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_POSTWRITE);
+
+	bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_PREREAD);
+	MBOX_READ(mbox, BCM2835_MBOX_CHAN_PROP, &reg);
+	bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_POSTREAD);
+
+	*hz = msg->body.resp.rate_hz;
+
+	bus_dmamap_unload(msg_tag, msg_map);
+	bus_dmamem_free(msg_tag, msg, msg_map);
 	bus_dma_tag_destroy(msg_tag);
 
 	return (0);

Modified: head/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h
==============================================================================
--- head/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h	Fri Mar 20 16:05:13 2015	(r280293)
+++ head/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h	Fri Mar 20 16:54:21 2015	(r280294)
@@ -179,6 +179,8 @@ struct msg_get_min_clock_rate {
 	uint32_t end_tag;
 };
 
+int bcm2835_mbox_get_clock_rate(device_t, uint32_t, uint32_t *);
+
 #define BCM2835_MBOX_TURBO_ON			1
 #define BCM2835_MBOX_TURBO_OFF			0
 

Modified: head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
==============================================================================
--- head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c	Fri Mar 20 16:05:13 2015	(r280293)
+++ head/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c	Fri Mar 20 16:54:21 2015	(r280294)
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
 #include "sdhci_if.h"
 
 #include "bcm2835_dma.h"
+#include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h>
 #include "bcm2835_vcbus.h"
 
 #define	BCM2835_DEFAULT_SDHCI_FREQ	50
@@ -154,18 +155,38 @@ bcm_sdhci_attach(device_t dev)
 	int rid, err;
 	phandle_t node;
 	pcell_t cell;
-	int default_freq;
+	u_int default_freq;
 
 	sc->sc_dev = dev;
 	sc->sc_req = NULL;
-	err = 0;
 
-	default_freq = BCM2835_DEFAULT_SDHCI_FREQ;
+	err = bcm2835_mbox_set_power_state(dev, BCM2835_MBOX_POWER_ID_EMMC,
+	    TRUE);
+	if (err != 0) {
+		if (bootverbose)
+			device_printf(dev, "Unable to enable the power\n");
+		return (err);
+	}
+
+	default_freq = 0;
+	err = bcm2835_mbox_get_clock_rate(dev, BCM2835_MBOX_CLOCK_ID_EMMC,
+	    &default_freq);
+	if (err == 0) {
+		/* Convert to MHz */
+		default_freq /= 1000000;
+		if (bootverbose)
+			device_printf(dev, "default frequency: %dMHz\n",
+			    default_freq);
+	}
+	if (default_freq == 0)
+		default_freq = BCM2835_DEFAULT_SDHCI_FREQ;
+
 	node = ofw_bus_get_node(sc->sc_dev);
 	if ((OF_getprop(node, "clock-frequency", &cell, sizeof(cell))) > 0)
-		default_freq = (int)fdt32_to_cpu(cell)/1000000;
+		default_freq = fdt32_to_cpu(cell)/1000000;
 
-	dprintf("SDHCI frequency: %dMHz\n", default_freq);
+	if (bootverbose)
+		device_printf(dev, "SDHCI frequency: %dMHz\n", default_freq);
 
 	mtx_init(&sc->sc_mtx, "bcm sdhci", "sdhci", MTX_DEF);
 


More information about the svn-src-head mailing list