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, ®);
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, ®);
+ 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-all
mailing list