From 9f9ea47b6a547808c68ff3d8a9a36e230bf0108e Mon Sep 17 00:00:00 2001 From: loos Date: Sat, 2 May 2015 22:24:33 +0000 Subject: Add the routines to query and setup the framebuffer state using the BCM2835_MBOX_CHAN_PROP channel. The old channel (BCM2835_MBOX_CHAN_FB) seems deprecated on recent firmware versions and is causing a freeze on RPi 2. The actual changes in the framebuffer drivers will follow in subsequent commits. --- sys/arm/broadcom/bcm2835/bcm2835_mbox.c | 174 +++++++++++++++++++++++++++ sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h | 153 +++++++++++++++++++++++ 2 files changed, 327 insertions(+) (limited to 'sys/arm/broadcom/bcm2835') diff --git a/sys/arm/broadcom/bcm2835/bcm2835_mbox.c b/sys/arm/broadcom/bcm2835/bcm2835_mbox.c index af600ca..5940ad6 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_mbox.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_mbox.c @@ -318,6 +318,47 @@ bcm2835_mbox_init_dma(device_t dev, size_t len, bus_dma_tag_t *tag, return (buf); } +static int +bcm2835_mbox_err(device_t dev, bus_addr_t msg_phys, uint32_t resp_phys, + struct bcm2835_mbox_hdr *msg, size_t len) +{ + int idx; + struct bcm2835_mbox_tag_hdr *tag; + uint8_t *last; + + if ((uint32_t)msg_phys != resp_phys) { + device_printf(dev, "response channel mismatch\n"); + return (EIO); + } + if (msg->code != BCM2835_MBOX_CODE_RESP_SUCCESS) { + device_printf(dev, "mbox response error\n"); + return (EIO); + } + + /* Loop until the end tag. */ + tag = (struct bcm2835_mbox_tag_hdr *)(msg + 1); + last = (uint8_t *)msg + len; + for (idx = 0; tag->tag != 0; idx++) { + if ((tag->val_len & BCM2835_MBOX_TAG_VAL_LEN_RESPONSE) == 0) { + device_printf(dev, "tag %d response error\n", idx); + return (EIO); + } + /* Clear the response bit. */ + tag->val_len &= ~BCM2835_MBOX_TAG_VAL_LEN_RESPONSE; + + /* Next tag. */ + tag = (struct bcm2835_mbox_tag_hdr *)((uint8_t *)tag + + sizeof(*tag) + tag->val_buf_size); + + if ((uint8_t *)tag > last) { + device_printf(dev, "mbox buffer size error\n"); + return (EIO); + } + } + + return (0); +} + int bcm2835_mbox_set_power_state(device_t dev, uint32_t device_id, boolean_t on) { @@ -413,3 +454,136 @@ bcm2835_mbox_get_clock_rate(device_t dev, uint32_t clock_id, uint32_t *hz) return (0); } + +int +bcm2835_mbox_fb_get_w_h(device_t dev, struct bcm2835_fb_config *fb) +{ + device_t mbox; + int err; + bus_dma_tag_t msg_tag; + bus_dmamap_t msg_map; + bus_addr_t msg_phys; + struct msg_fb_get_w_h *msg; + uint32_t reg; + + /* 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; + BCM2835_MBOX_INIT_TAG(&msg->physical_w_h, GET_PHYSICAL_W_H); + msg->physical_w_h.tag_hdr.val_len = 0; + BCM2835_MBOX_INIT_TAG(&msg->virtual_w_h, GET_VIRTUAL_W_H); + msg->virtual_w_h.tag_hdr.val_len = 0; + BCM2835_MBOX_INIT_TAG(&msg->offset, GET_VIRTUAL_OFFSET); + msg->offset.tag_hdr.val_len = 0; + 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); + + err = bcm2835_mbox_err(dev, msg_phys, reg, &msg->hdr, sizeof(*msg)); + if (err == 0) { + fb->xres = msg->physical_w_h.body.resp.width; + fb->yres = msg->physical_w_h.body.resp.height; + fb->vxres = msg->virtual_w_h.body.resp.width; + fb->vyres = msg->virtual_w_h.body.resp.height; + fb->xoffset = msg->offset.body.resp.x; + fb->yoffset = msg->offset.body.resp.y; + } + + bus_dmamap_unload(msg_tag, msg_map); + bus_dmamem_free(msg_tag, msg, msg_map); + bus_dma_tag_destroy(msg_tag); + + return (err); +} + +int +bcm2835_mbox_fb_init(device_t dev, struct bcm2835_fb_config *fb) +{ + device_t mbox; + int err; + bus_dma_tag_t msg_tag; + bus_dmamap_t msg_map; + bus_addr_t msg_phys; + struct msg_fb_setup *msg; + uint32_t reg; + + /* 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; + BCM2835_MBOX_INIT_TAG(&msg->physical_w_h, SET_PHYSICAL_W_H); + msg->physical_w_h.body.req.width = fb->xres; + msg->physical_w_h.body.req.height = fb->yres; + BCM2835_MBOX_INIT_TAG(&msg->virtual_w_h, SET_VIRTUAL_W_H); + msg->virtual_w_h.body.req.width = fb->vxres; + msg->virtual_w_h.body.req.height = fb->vyres; + BCM2835_MBOX_INIT_TAG(&msg->offset, GET_VIRTUAL_OFFSET); + msg->offset.body.req.x = fb->xoffset; + msg->offset.body.req.y = fb->yoffset; + BCM2835_MBOX_INIT_TAG(&msg->depth, SET_DEPTH); + msg->depth.body.req.bpp = fb->bpp; + BCM2835_MBOX_INIT_TAG(&msg->alpha, SET_ALPHA_MODE); + msg->alpha.body.req.alpha = BCM2835_MBOX_ALPHA_MODE_IGNORED; + BCM2835_MBOX_INIT_TAG(&msg->buffer, ALLOCATE_BUFFER); + msg->buffer.body.req.alignment = PAGE_SIZE; + BCM2835_MBOX_INIT_TAG(&msg->pitch, GET_PITCH); + 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); + + err = bcm2835_mbox_err(dev, msg_phys, reg, &msg->hdr, sizeof(*msg)); + if (err == 0) { + fb->xres = msg->physical_w_h.body.resp.width; + fb->yres = msg->physical_w_h.body.resp.height; + fb->vxres = msg->virtual_w_h.body.resp.width; + fb->vyres = msg->virtual_w_h.body.resp.height; + fb->xoffset = msg->offset.body.resp.x; + fb->yoffset = msg->offset.body.resp.y; + fb->pitch = msg->pitch.body.resp.pitch; + fb->base = msg->buffer.body.resp.fb_address; + fb->size = msg->buffer.body.resp.fb_size; + } + + bus_dmamap_unload(msg_tag, msg_map); + bus_dmamem_free(msg_tag, msg, msg_map); + bus_dma_tag_destroy(msg_tag); + + return (err); +} diff --git a/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h b/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h index 76f2a16..a425f2a 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h +++ b/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h @@ -52,6 +52,12 @@ struct bcm2835_mbox_tag_hdr { uint32_t val_len; }; +#define BCM2835_MBOX_INIT_TAG(tag_, tagid_) do { \ + (tag_)->tag_hdr.tag = BCM2835_MBOX_TAG_##tagid_; \ + (tag_)->tag_hdr.val_buf_size = sizeof((tag_)->body); \ + (tag_)->tag_hdr.val_len = sizeof((tag_)->body.req); \ +} while (0) + #define BCM2835_MBOX_POWER_ID_EMMC 0x00000000 #define BCM2835_MBOX_POWER_ID_UART0 0x00000001 #define BCM2835_MBOX_POWER_ID_UART1 0x00000002 @@ -322,4 +328,151 @@ struct msg_get_max_temperature { uint32_t end_tag; }; +#define BCM2835_MBOX_TAG_GET_PHYSICAL_W_H 0x00040003 +#define BCM2835_MBOX_TAG_SET_PHYSICAL_W_H 0x00048003 +#define BCM2835_MBOX_TAG_GET_VIRTUAL_W_H 0x00040004 +#define BCM2835_MBOX_TAG_SET_VIRTUAL_W_H 0x00048004 + +struct bcm2835_mbox_tag_fb_w_h { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + uint32_t width; + uint32_t height; + } req; + struct { + uint32_t width; + uint32_t height; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_GET_DEPTH 0x00040005 +#define BCM2835_MBOX_TAG_SET_DEPTH 0x00048005 + +struct bcm2835_mbox_tag_depth { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + uint32_t bpp; + } req; + struct { + uint32_t bpp; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_GET_ALPHA_MODE 0x00040007 +#define BCM2835_MBOX_TAG_SET_ALPHA_MODE 0x00048007 + +#define BCM2835_MBOX_ALPHA_MODE_0_OPAQUE 0 +#define BCM2835_MBOX_ALPHA_MODE_0_TRANSPARENT 1 +#define BCM2835_MBOX_ALPHA_MODE_IGNORED 2 + +struct bcm2835_mbox_tag_alpha_mode { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + uint32_t alpha; + } req; + struct { + uint32_t alpha; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_GET_VIRTUAL_OFFSET 0x00040009 +#define BCM2835_MBOX_TAG_SET_VIRTUAL_OFFSET 0x00048009 + +struct bcm2835_mbox_tag_virtual_offset { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + uint32_t x; + uint32_t y; + } req; + struct { + uint32_t x; + uint32_t y; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_GET_PITCH 0x00040008 + +struct bcm2835_mbox_tag_pitch { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + } req; + struct { + uint32_t pitch; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_ALLOCATE_BUFFER 0x00040001 + +struct bcm2835_mbox_tag_allocate_buffer { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + uint32_t alignment; + } req; + struct { + uint32_t fb_address; + uint32_t fb_size; + } resp; + } body; +}; + +#define BCM2835_MBOX_TAG_RELEASE_BUFFER 0x00048001 + +struct bcm2835_mbox_tag_release_buffer { + struct bcm2835_mbox_tag_hdr tag_hdr; + union { + struct { + } req; + struct { + } resp; + } body; +}; + +struct bcm2835_fb_config { + uint32_t xres; + uint32_t yres; + uint32_t vxres; + uint32_t vyres; + uint32_t xoffset; + uint32_t yoffset; + uint32_t bpp; + uint32_t pitch; + uint32_t base; + uint32_t size; +}; + +struct msg_fb_get_w_h { + struct bcm2835_mbox_hdr hdr; + struct bcm2835_mbox_tag_fb_w_h physical_w_h; + struct bcm2835_mbox_tag_fb_w_h virtual_w_h; + struct bcm2835_mbox_tag_virtual_offset offset; + uint32_t end_tag; +}; + +int bcm2835_mbox_fb_get_w_h(device_t, struct bcm2835_fb_config *); + +struct msg_fb_setup { + struct bcm2835_mbox_hdr hdr; + struct bcm2835_mbox_tag_fb_w_h physical_w_h; + struct bcm2835_mbox_tag_fb_w_h virtual_w_h; + struct bcm2835_mbox_tag_virtual_offset offset; + struct bcm2835_mbox_tag_depth depth; + struct bcm2835_mbox_tag_alpha_mode alpha; + struct bcm2835_mbox_tag_allocate_buffer buffer; + struct bcm2835_mbox_tag_pitch pitch; + uint32_t end_tag; +}; + +int bcm2835_mbox_fb_init(device_t, struct bcm2835_fb_config *); + #endif /* _BCM2835_MBOX_PROP_H_ */ -- cgit v1.1 From d98c32fd6285bf111fca182658134384adfec1f4 Mon Sep 17 00:00:00 2001 From: loos Date: Sat, 2 May 2015 22:40:41 +0000 Subject: Fix the sc(4) framebuffer driver on RPi 2. Use the BCM2835_MBOX_CHAN_PROP mbox channel to setup the framebuffer, remove unused code and unnecessary includes. Adjust the color palette when bcm2708_fb.fbswap is set on /chosen/bootargs node of DTB. The firmware used on RPi 2 uses this mode. Tested on: RPi-B and RPi 2 with 16, 24 and 32bpp --- sys/arm/broadcom/bcm2835/bcm2835_fb.c | 416 ++++++++++++---------------------- 1 file changed, 139 insertions(+), 277 deletions(-) (limited to 'sys/arm/broadcom/bcm2835') diff --git a/sys/arm/broadcom/bcm2835/bcm2835_fb.c b/sys/arm/broadcom/bcm2835/bcm2835_fb.c index 3270da1..6e6cfda 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_fb.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_fb.c @@ -29,46 +29,27 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include -#include -#include +#include +#include +#include #include -#include -#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include +#include +#include +#include #include #include #include - -#include #include -#include -#include +#include #include "mbox_if.h" -#define BCMFB_FONT_HEIGHT 16 - struct argb { uint8_t a; uint8_t r; @@ -101,40 +82,15 @@ static u_char mouse_pointer[16] = { 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 }; -#define FB_WIDTH 640 -#define FB_HEIGHT 480 -#define FB_DEPTH 24 - -struct bcm_fb_config { - uint32_t xres; - uint32_t yres; - uint32_t vxres; - uint32_t vyres; - uint32_t pitch; - uint32_t bpp; - uint32_t xoffset; - uint32_t yoffset; - /* Filled by videocore */ - uint32_t base; - uint32_t screen_size; -}; +#define BCMFB_FONT_HEIGHT 16 +#define BCMFB_FONT_WIDTH 8 +#define FB_WIDTH 640 +#define FB_HEIGHT 480 +#define FB_DEPTH 24 struct bcmsc_softc { - device_t dev; - struct cdev * cdev; - struct mtx mtx; - bus_dma_tag_t dma_tag; - bus_dmamap_t dma_map; - struct bcm_fb_config* fb_config; - bus_addr_t fb_config_phys; - struct intr_config_hook init_hook; - -}; - -struct video_adapter_softc { /* Videoadpater part */ video_adapter_t va; - int console; intptr_t fb_addr; intptr_t fb_paddr; @@ -149,199 +105,75 @@ struct video_adapter_softc { unsigned int ymargin; unsigned char *font; + int fbswap; int initialized; }; -static struct bcmsc_softc *bcmsc_softc; -static struct video_adapter_softc va_softc; - -#define bcm_fb_lock(_sc) mtx_lock(&(_sc)->mtx) -#define bcm_fb_unlock(_sc) mtx_unlock(&(_sc)->mtx) -#define bcm_fb_lock_assert(sc) mtx_assert(&(_sc)->mtx, MA_OWNED) +static struct bcmsc_softc bcmsc; static int bcm_fb_probe(device_t); static int bcm_fb_attach(device_t); -static void bcm_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err); static void bcmfb_update_margins(video_adapter_t *adp); static int bcmfb_configure(int); -static void -bcm_fb_init(void *arg) -{ - struct bcmsc_softc *sc = arg; - struct video_adapter_softc *va_sc = &va_softc; - int err; - volatile struct bcm_fb_config* fb_config = sc->fb_config; - phandle_t node; - pcell_t cell; - device_t mbox; - - node = ofw_bus_get_node(sc->dev); - - fb_config->xres = 0; - fb_config->yres = 0; - fb_config->bpp = 0; - - if ((OF_getprop(node, "broadcom,width", &cell, sizeof(cell))) > 0) - fb_config->xres = (int)fdt32_to_cpu(cell); - if (fb_config->xres == 0) - fb_config->xres = FB_WIDTH; - - if ((OF_getprop(node, "broadcom,height", &cell, sizeof(cell))) > 0) - fb_config->yres = (uint32_t)fdt32_to_cpu(cell); - if (fb_config->yres == 0) - fb_config->yres = FB_HEIGHT; - - if ((OF_getprop(node, "broadcom,depth", &cell, sizeof(cell))) > 0) - fb_config->bpp = (uint32_t)fdt32_to_cpu(cell); - if (fb_config->bpp == 0) - fb_config->bpp = FB_DEPTH; - - fb_config->vxres = 0; - fb_config->vyres = 0; - fb_config->xoffset = 0; - fb_config->yoffset = 0; - fb_config->base = 0; - fb_config->pitch = 0; - fb_config->screen_size = 0; - - bus_dmamap_sync(sc->dma_tag, sc->dma_map, - BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); - - mbox = devclass_get_device(devclass_find("mbox"), 0); - if (mbox) { - MBOX_WRITE(mbox, BCM2835_MBOX_CHAN_FB, sc->fb_config_phys); - MBOX_READ(mbox, BCM2835_MBOX_CHAN_FB, &err); - } - bus_dmamap_sync(sc->dma_tag, sc->dma_map, - BUS_DMASYNC_POSTREAD); - - if (fb_config->base != 0) { - device_printf(sc->dev, "%dx%d(%dx%d@%d,%d) %dbpp\n", - fb_config->xres, fb_config->yres, - fb_config->vxres, fb_config->vyres, - fb_config->xoffset, fb_config->yoffset, - fb_config->bpp); - - - device_printf(sc->dev, "pitch %d, base 0x%08x, screen_size %d\n", - fb_config->pitch, fb_config->base, - fb_config->screen_size); - - va_sc->fb_addr = (intptr_t)pmap_mapdev(fb_config->base, fb_config->screen_size); - va_sc->fb_paddr = fb_config->base; - va_sc->fb_size = fb_config->screen_size; - va_sc->depth = fb_config->bpp; - va_sc->stride = fb_config->pitch; - - va_sc->width = fb_config->xres; - va_sc->height = fb_config->yres; - bcmfb_update_margins(&va_sc->va); - } - else { - device_printf(sc->dev, "Failed to set framebuffer info\n"); - } - - config_intrhook_disestablish(&sc->init_hook); -} - static int bcm_fb_probe(device_t dev) { - int error = 0; + int error; if (!ofw_bus_is_compatible(dev, "broadcom,bcm2835-fb")) return (ENXIO); - device_set_desc(dev, "BCM2835 framebuffer device"); - error = sc_probe_unit(device_get_unit(dev), device_get_flags(dev) | SC_AUTODETECT_KBD); if (error != 0) return (error); - return (BUS_PROBE_DEFAULT); } static int bcm_fb_attach(device_t dev) { - struct bcmsc_softc *sc = device_get_softc(dev); - int dma_size = sizeof(struct bcm_fb_config); - int err; - - if (bcmsc_softc) - return (ENXIO); + struct bcm2835_fb_config fb; + struct bcmsc_softc *sc; - bcmsc_softc = sc; - - sc->dev = dev; - mtx_init(&sc->mtx, "bcm2835fb", "fb", MTX_DEF); - - err = bus_dma_tag_create( - bus_get_dma_tag(sc->dev), - PAGE_SIZE, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - dma_size, 1, /* maxsize, nsegments */ - dma_size, 0, /* maxsegsize, flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->dma_tag); - - err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->fb_config, - 0, &sc->dma_map); - if (err) { - device_printf(dev, "cannot allocate framebuffer\n"); - goto fail; - } - - err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->fb_config, - dma_size, bcm_fb_dmamap_cb, &sc->fb_config_phys, BUS_DMA_NOWAIT); - - if (err) { - device_printf(dev, "cannot load DMA map\n"); - goto fail; - } + sc = (struct bcmsc_softc *)vid_get_adapter(vid_find_adapter( + "bcmfb", 0)); + if (sc != NULL) + device_set_softc(dev, sc); + else + sc = device_get_softc(dev); - err = (sc_attach_unit(device_get_unit(dev), - device_get_flags(dev) | SC_AUTODETECT_KBD)); + memset(&fb, 0, sizeof(fb)); + if (bcm2835_mbox_fb_get_w_h(dev, &fb) != 0) + return (ENXIO); + fb.bpp = FB_DEPTH; + if (bcm2835_mbox_fb_init(dev, &fb) != 0) + return (ENXIO); - if (err) { + sc->fb_addr = (intptr_t)pmap_mapdev(fb.base, fb.size); + sc->fb_paddr = fb.base; + sc->fb_size = fb.size; + sc->depth = fb.bpp; + sc->stride = fb.pitch; + sc->width = fb.xres; + sc->height = fb.yres; + bcmfb_update_margins(&sc->va); + + if (sc_attach_unit(device_get_unit(dev), + device_get_flags(dev) | SC_AUTODETECT_KBD) != 0) { device_printf(dev, "failed to attach syscons\n"); - goto fail; + return (ENXIO); } - /* - * We have to wait until interrupts are enabled. - * Mailbox relies on it to get data from VideoCore - */ - sc->init_hook.ich_func = bcm_fb_init; - sc->init_hook.ich_arg = sc; - - if (config_intrhook_establish(&sc->init_hook) != 0) { - device_printf(dev, "failed to establish intrhook\n"); - return (ENOMEM); - } + device_printf(dev, "%dx%d(%dx%d@%d,%d) %dbpp\n", fb.xres, fb.yres, + fb.vxres, fb.vyres, fb.xoffset, fb.yoffset, fb.bpp); + device_printf(dev, + "fbswap: %d, pitch %d, base 0x%08x, screen_size %d\n", + sc->fbswap, fb.pitch, fb.base, fb.size); return (0); - -fail: - return (ENXIO); -} - - -static void -bcm_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err) -{ - bus_addr_t *addr; - - if (err) - return; - - addr = (bus_addr_t*)arg; - *addr = PHYS_TO_VCBUS(segs[0].ds_addr); } static device_method_t bcm_fb_methods[] = { @@ -504,13 +336,13 @@ bcmrend_set_cursor(scr_stat* scp, int base, int height, int blink) static void bcmrend_draw_cursor(scr_stat* scp, int off, int blink, int on, int flip) { - video_adapter_t* adp = scp->sc->adp; - struct video_adapter_softc *sc; - int row, col; + int bytes, col, i, j, row; + struct bcmsc_softc *sc; uint8_t *addr; - int i, j, bytes; + video_adapter_t *adp; - sc = (struct video_adapter_softc *)adp; + adp = scp->sc->adp; + sc = (struct bcmsc_softc *)adp; if (scp->curs_attr.height <= 0) return; @@ -529,8 +361,7 @@ bcmrend_draw_cursor(scr_stat* scp, int off, int blink, int on, int flip) + (row + sc->ymargin)*(sc->stride) + (sc->depth/8) * (col + sc->xmargin); - bytes = sc->depth/8; - + bytes = sc->depth / 8; /* our cursor consists of simply inverting the char under it */ for (i = 0; i < adp->va_info.vi_cheight; i++) { for (j = 0; j < adp->va_info.vi_cwidth; j++) { @@ -577,56 +408,80 @@ extern u_char dflt_font_16[]; static void bcmfb_update_margins(video_adapter_t *adp) { - struct video_adapter_softc *sc; + struct bcmsc_softc *sc; video_info_t *vi; - sc = (struct video_adapter_softc *)adp; + sc = (struct bcmsc_softc *)adp; vi = &adp->va_info; sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; - sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; + sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight)) / 2; } static int bcmfb_configure(int flags) { - struct video_adapter_softc *va_sc; - - va_sc = &va_softc; - phandle_t display, root; + char bootargs[2048], *n, *p, *v; pcell_t cell; + phandle_t chosen, display, root; + struct bcmsc_softc *sc; - if (va_sc->initialized) + sc = &bcmsc; + if (sc->initialized) return (0); - va_sc->width = 0; - va_sc->height = 0; + sc->width = 0; + sc->height = 0; /* * It seems there is no way to let syscons framework know * that framebuffer resolution has changed. So just try - * to fetch data from FDT and go with defaults if failed + * to fetch data from FDT bootargs, FDT display data and + * finally go with defaults if everything else has failed. */ + chosen = OF_finddevice("/chosen"); + if (chosen != 0 && + OF_getprop(chosen, "bootargs", &bootargs, sizeof(bootargs)) > 0) { + p = bootargs; + while ((v = strsep(&p, " ")) != NULL) { + if (*v == '\0') + continue; + n = strsep(&v, "="); + if (strcmp(n, "bcm2708_fb.fbwidth") == 0 && v != NULL) + sc->width = (unsigned int)strtol(v, NULL, 0); + else if (strcmp(n, "bcm2708_fb.fbheight") == 0 && + v != NULL) + sc->height = (unsigned int)strtol(v, NULL, 0); + else if (strcmp(n, "bcm2708_fb.fbswap") == 0 && + v != NULL) + if (*v == '1') + sc->fbswap = 1; + } + } + root = OF_finddevice("/"); if ((root != 0) && (display = fdt_find_compatible(root, "broadcom,bcm2835-fb", 1))) { - if ((OF_getprop(display, "broadcom,width", - &cell, sizeof(cell))) > 0) - va_sc->width = (int)fdt32_to_cpu(cell); + if (sc->width == 0) { + if ((OF_getprop(display, "broadcom,width", + &cell, sizeof(cell))) > 0) + sc->width = (int)fdt32_to_cpu(cell); + } - if ((OF_getprop(display, "broadcom,height", - &cell, sizeof(cell))) > 0) - va_sc->height = (int)fdt32_to_cpu(cell); + if (sc->height == 0) { + if ((OF_getprop(display, "broadcom,height", + &cell, sizeof(cell))) > 0) + sc->height = (int)fdt32_to_cpu(cell); + } } - if (va_sc->width == 0) - va_sc->width = FB_WIDTH; - if (va_sc->height == 0) - va_sc->height = FB_HEIGHT; - - bcmfb_init(0, &va_sc->va, 0); + if (sc->width == 0) + sc->width = FB_WIDTH; + if (sc->height == 0) + sc->height = FB_HEIGHT; - va_sc->initialized = 1; + bcmfb_init(0, &sc->va, 0); + sc->initialized = 1; return (0); } @@ -641,20 +496,19 @@ bcmfb_probe(int unit, video_adapter_t **adp, void *arg, int flags) static int bcmfb_init(int unit, video_adapter_t *adp, int flags) { - struct video_adapter_softc *sc; + struct bcmsc_softc *sc; video_info_t *vi; - sc = (struct video_adapter_softc *)adp; + sc = (struct bcmsc_softc *)adp; vi = &adp->va_info; vid_init_struct(adp, "bcmfb", -1, unit); sc->font = dflt_font_16; vi->vi_cheight = BCMFB_FONT_HEIGHT; - vi->vi_cwidth = 8; - - vi->vi_width = sc->width/8; - vi->vi_height = sc->height/vi->vi_cheight; + vi->vi_cwidth = BCMFB_FONT_WIDTH; + vi->vi_width = sc->width / vi->vi_cwidth; + vi->vi_height = sc->height / vi->vi_cheight; /* * Clamp width/height to syscons maximums @@ -665,8 +519,7 @@ bcmfb_init(int unit, video_adapter_t *adp, int flags) vi->vi_height = ROW; sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; - sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; - + sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight)) / 2; adp->va_window = (vm_offset_t) bcmfb_static_window; adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */; @@ -706,8 +559,9 @@ static int bcmfb_load_font(video_adapter_t *adp, int page, int size, int width, u_char *data, int c, int count) { - struct video_adapter_softc *sc = (struct video_adapter_softc *)adp; + struct bcmsc_softc *sc; + sc = (struct bcmsc_softc *)adp; sc->font = data; return (0); @@ -780,9 +634,9 @@ static int bcmfb_blank_display(video_adapter_t *adp, int mode) { - struct video_adapter_softc *sc; + struct bcmsc_softc *sc; - sc = (struct video_adapter_softc *)adp; + sc = (struct bcmsc_softc *)adp; if (sc && sc->fb_addr) memset((void*)sc->fb_addr, 0, sc->fb_size); @@ -793,9 +647,9 @@ static int bcmfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, int prot, vm_memattr_t *memattr) { - struct video_adapter_softc *sc; + struct bcmsc_softc *sc; - sc = (struct video_adapter_softc *)adp; + sc = (struct bcmsc_softc *)adp; /* * This might be a legacy VGA mem request: if so, just point it at the @@ -812,10 +666,10 @@ bcmfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, static int bcmfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) { - struct video_adapter_softc *sc; + struct bcmsc_softc *sc; struct fbtype *fb; - sc = (struct video_adapter_softc *)adp; + sc = (struct bcmsc_softc *)adp; switch (cmd) { case FBIOGTYPE: @@ -897,16 +751,13 @@ bcmfb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, static int bcmfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) { - struct video_adapter_softc *sc; - int row; - int col; - int i, j, k; - uint8_t *addr; + int bytes, col, i, j, k, row; + struct bcmsc_softc *sc; u_char *p; - uint8_t fg, bg, color; + uint8_t *addr, fg, bg, color; uint16_t rgb; - sc = (struct video_adapter_softc *)adp; + sc = (struct bcmsc_softc *)adp; if (sc->fb_addr == 0) return (0); @@ -921,6 +772,7 @@ bcmfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) fg = a & 0xf ; bg = (a >> 4) & 0xf; + bytes = sc->depth / 8; for (i = 0; i < BCMFB_FONT_HEIGHT; i++) { for (j = 0, k = 7; j < 8; j++, k--) { if ((p[i] & (1 << k)) == 0) @@ -930,22 +782,32 @@ bcmfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) switch (sc->depth) { case 32: - addr[4*j+0] = bcmfb_palette[color].r; - addr[4*j+1] = bcmfb_palette[color].g; - addr[4*j+2] = bcmfb_palette[color].b; - addr[4*j+3] = bcmfb_palette[color].a; - break; case 24: - addr[3*j] = bcmfb_palette[color].r; - addr[3*j+1] = bcmfb_palette[color].g; - addr[3*j+2] = bcmfb_palette[color].b; + if (sc->fbswap) { + addr[bytes * j + 0] = + bcmfb_palette[color].b; + addr[bytes * j + 1] = + bcmfb_palette[color].g; + addr[bytes * j + 2] = + bcmfb_palette[color].r; + } else { + addr[bytes * j + 0] = + bcmfb_palette[color].r; + addr[bytes * j + 1] = + bcmfb_palette[color].g; + addr[bytes * j + 2] = + bcmfb_palette[color].b; + } + if (sc->depth == 32) + addr[bytes * j + 3] = + bcmfb_palette[color].a; break; case 16: rgb = (bcmfb_palette[color].r >> 3) << 11; rgb |= (bcmfb_palette[color].g >> 2) << 5; rgb |= (bcmfb_palette[color].b >> 3); - addr[2*j] = rgb & 0xff; - addr[2*j + 1] = (rgb >> 8) & 0xff; + addr[bytes * j] = rgb & 0xff; + addr[bytes * j + 1] = (rgb >> 8) & 0xff; default: /* Not supported yet */ break; -- cgit v1.1 From fe9d317ae250f926f3bc6ad79fce4a6fc8a11569 Mon Sep 17 00:00:00 2001 From: loos Date: Sat, 2 May 2015 22:48:56 +0000 Subject: Fix the vt(4) framebuffer driver on RPi 2. Use the BCM2835_MBOX_CHAN_PROP mbox channel to setup the framebuffer, remove DMA code (its now done in bcm2835_mbox.c). Also adjust the color palette when bcm2708_fb.fbswap is set. The firmware used on RPi 2 uses this mode. Tested on: RPi-B and RPi 2 with 16, 24 and 32bpp Note: The 32bpp mode on RPi-B has the red and blue swapped, this is a know problem (not a driver problem). --- sys/arm/broadcom/bcm2835/bcm2835_fbd.c | 263 +++++++++------------------------ 1 file changed, 72 insertions(+), 191 deletions(-) (limited to 'sys/arm/broadcom/bcm2835') diff --git a/sys/arm/broadcom/bcm2835/bcm2835_fbd.c b/sys/arm/broadcom/bcm2835/bcm2835_fbd.c index f41e6e2..34a7af8 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_fbd.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_fbd.c @@ -35,170 +35,35 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include +#include #include -#include -#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include - -#include #include #include -#include -#include -#include -#include -#include -#include - #include #include #include #include #include +#include -#include -#include +#include #include "fb_if.h" #include "mbox_if.h" -#define FB_WIDTH 640 -#define FB_HEIGHT 480 -#define FB_DEPTH 24 - -struct bcm_fb_config { - uint32_t xres; - uint32_t yres; - uint32_t vxres; - uint32_t vyres; - uint32_t pitch; - uint32_t bpp; - uint32_t xoffset; - uint32_t yoffset; - /* Filled by videocore */ - uint32_t base; - uint32_t screen_size; -}; +#define FB_DEPTH 24 struct bcmsc_softc { - device_t dev; struct fb_info *info; - bus_dma_tag_t dma_tag; - bus_dmamap_t dma_map; - struct bcm_fb_config* fb_config; - bus_addr_t fb_config_phys; - struct intr_config_hook init_hook; }; static int bcm_fb_probe(device_t); static int bcm_fb_attach(device_t); -static void bcm_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, - int err); - -static void -bcm_fb_init(void *arg) -{ - volatile struct bcm_fb_config *fb_config; - struct bcmsc_softc *sc; - struct fb_info *info; - phandle_t node; - pcell_t cell; - device_t mbox; - device_t fbd; - int err = 0; - - sc = arg; - fb_config = sc->fb_config; - node = ofw_bus_get_node(sc->dev); - - fb_config->xres = 0; - fb_config->yres = 0; - fb_config->bpp = 0; - fb_config->vxres = 0; - fb_config->vyres = 0; - fb_config->xoffset = 0; - fb_config->yoffset = 0; - fb_config->base = 0; - fb_config->pitch = 0; - fb_config->screen_size = 0; - - if ((OF_getprop(node, "broadcom,width", &cell, sizeof(cell))) > 0) - fb_config->xres = (int)fdt32_to_cpu(cell); - if (fb_config->xres == 0) - fb_config->xres = FB_WIDTH; - - if ((OF_getprop(node, "broadcom,height", &cell, sizeof(cell))) > 0) - fb_config->yres = (uint32_t)fdt32_to_cpu(cell); - if (fb_config->yres == 0) - fb_config->yres = FB_HEIGHT; - - if ((OF_getprop(node, "broadcom,depth", &cell, sizeof(cell))) > 0) - fb_config->bpp = (uint32_t)fdt32_to_cpu(cell); - if (fb_config->bpp == 0) - fb_config->bpp = FB_DEPTH; - - bus_dmamap_sync(sc->dma_tag, sc->dma_map, - BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); - - mbox = devclass_get_device(devclass_find("mbox"), 0); - if (mbox) { - MBOX_WRITE(mbox, BCM2835_MBOX_CHAN_FB, sc->fb_config_phys); - MBOX_READ(mbox, BCM2835_MBOX_CHAN_FB, &err); - } - bus_dmamap_sync(sc->dma_tag, sc->dma_map, - BUS_DMASYNC_POSTREAD); - - if (fb_config->base != 0) { - device_printf(sc->dev, "%dx%d(%dx%d@%d,%d) %dbpp\n", - fb_config->xres, fb_config->yres, - fb_config->vxres, fb_config->vyres, - fb_config->xoffset, fb_config->yoffset, - fb_config->bpp); - - device_printf(sc->dev, "pitch %d, base 0x%08x, screen_size %d\n", - fb_config->pitch, fb_config->base, - fb_config->screen_size); - - info = malloc(sizeof(struct fb_info), M_DEVBUF, - M_WAITOK | M_ZERO); - info->fb_name = device_get_nameunit(sc->dev); - info->fb_vbase = (intptr_t)pmap_mapdev(fb_config->base, - fb_config->screen_size); - info->fb_pbase = fb_config->base; - info->fb_size = fb_config->screen_size; - info->fb_bpp = info->fb_depth = fb_config->bpp; - info->fb_stride = fb_config->pitch; - info->fb_width = fb_config->xres; - info->fb_height = fb_config->yres; - - sc->info = info; - - fbd = device_add_child(sc->dev, "fbd", - device_get_unit(sc->dev)); - if (fbd == NULL) - device_printf(sc->dev, "Failed to add fbd child\n"); - else if (device_probe_and_attach(fbd) != 0) - device_printf(sc->dev, "Failed to attach fbd device\n"); - } else { - device_printf(sc->dev, "Failed to set framebuffer info\n"); - } - - config_intrhook_disestablish(&sc->init_hook); -} static int bcm_fb_probe(device_t dev) @@ -214,66 +79,82 @@ bcm_fb_probe(device_t dev) static int bcm_fb_attach(device_t dev) { - struct bcmsc_softc *sc = device_get_softc(dev); - int dma_size = sizeof(struct bcm_fb_config); - int err; - - sc->dev = dev; + char bootargs[2048], *n, *p, *v; + device_t fbd; + int fbswap; + phandle_t chosen; + struct bcm2835_fb_config fb; + struct bcmsc_softc *sc; + struct fb_info *info; - err = bus_dma_tag_create( - bus_get_dma_tag(sc->dev), - PAGE_SIZE, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - dma_size, 1, /* maxsize, nsegments */ - dma_size, 0, /* maxsegsize, flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->dma_tag); + sc = device_get_softc(dev); + memset(&fb, 0, sizeof(fb)); + if (bcm2835_mbox_fb_get_w_h(dev, &fb) != 0) + return (ENXIO); + fb.bpp = FB_DEPTH; + if (bcm2835_mbox_fb_init(dev, &fb) != 0) + return (ENXIO); - err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->fb_config, 0, - &sc->dma_map); - if (err) { - device_printf(dev, "cannot allocate framebuffer\n"); - goto fail; + info = malloc(sizeof(struct fb_info), M_DEVBUF, M_WAITOK | M_ZERO); + info->fb_name = device_get_nameunit(dev); + info->fb_vbase = (intptr_t)pmap_mapdev(fb.base, fb.size); + info->fb_pbase = fb.base; + info->fb_size = fb.size; + info->fb_bpp = info->fb_depth = fb.bpp; + info->fb_stride = fb.pitch; + info->fb_width = fb.xres; + info->fb_height = fb.yres; + sc->info = info; + + /* Newer firmware versions needs an inverted color palette. */ + fbswap = 0; + chosen = OF_finddevice("/chosen"); + if (chosen != 0 && + OF_getprop(chosen, "bootargs", &bootargs, sizeof(bootargs)) > 0) { + p = bootargs; + while ((v = strsep(&p, " ")) != NULL) { + if (*v == '\0') + continue; + n = strsep(&v, "="); + if (strcmp(n, "bcm2708_fb.fbswap") == 0 && v != NULL) + if (*v == '1') + fbswap = 1; + } + } + if (fbswap) { + switch (info->fb_bpp) { + case 24: + vt_generate_cons_palette(info->fb_cmap, + COLOR_FORMAT_RGB, 0xff, 0, 0xff, 8, 0xff, 16); + info->fb_cmsize = 16; + break; + case 32: + vt_generate_cons_palette(info->fb_cmap, + COLOR_FORMAT_RGB, 0xff, 16, 0xff, 8, 0xff, 0); + info->fb_cmsize = 16; + break; + } } - err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->fb_config, - dma_size, bcm_fb_dmamap_cb, &sc->fb_config_phys, BUS_DMA_NOWAIT); - - if (err) { - device_printf(dev, "cannot load DMA map\n"); - goto fail; + fbd = device_add_child(dev, "fbd", device_get_unit(dev)); + if (fbd == NULL) { + device_printf(dev, "Failed to add fbd child\n"); + free(info, M_DEVBUF); + return (ENXIO); + } else if (device_probe_and_attach(fbd) != 0) { + device_printf(dev, "Failed to attach fbd device\n"); + device_delete_child(dev, fbd); + free(info, M_DEVBUF); + return (ENXIO); } - /* - * We have to wait until interrupts are enabled. - * Mailbox relies on it to get data from VideoCore - */ - sc->init_hook.ich_func = bcm_fb_init; - sc->init_hook.ich_arg = sc; - - if (config_intrhook_establish(&sc->init_hook) != 0) { - device_printf(dev, "failed to establish intrhook\n"); - return (ENOMEM); - } + device_printf(dev, "%dx%d(%dx%d@%d,%d) %dbpp\n", fb.xres, fb.yres, + fb.vxres, fb.vyres, fb.xoffset, fb.yoffset, fb.bpp); + device_printf(dev, + "fbswap: %d, pitch %d, base 0x%08x, screen_size %d\n", + fbswap, fb.pitch, fb.base, fb.size); return (0); - -fail: - return (ENXIO); -} - -static void -bcm_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err) -{ - bus_addr_t *addr; - - if (err) - return; - - addr = (bus_addr_t*)arg; - *addr = PHYS_TO_VCBUS(segs[0].ds_addr); } static struct fb_info * -- cgit v1.1 From 60b473436405a59c1120bfa7b1bd13c3dfa97282 Mon Sep 17 00:00:00 2001 From: loos Date: Mon, 4 May 2015 00:01:35 +0000 Subject: Fix the voltage and clock levels for cpufreq on RPi 2. Submitted by: Daisuke Aoyama --- sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c | 59 +++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 17 deletions(-) (limited to 'sys/arm/broadcom/bcm2835') diff --git a/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c b/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c index 2ea5b49..ab0f901 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c @@ -1,5 +1,5 @@ /*- - * Copyright (C) 2013-2014 Daisuke Aoyama + * Copyright (C) 2013-2015 Daisuke Aoyama * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -60,21 +60,28 @@ __FBSDID("$FreeBSD$"); #define DPRINTF(fmt, ...) #endif -#define HZ2MHZ(freq) ((freq) / (1000 * 1000)) -#define MHZ2HZ(freq) ((freq) * (1000 * 1000)) -#define OFFSET2MVOLT(val) (1200 + ((val) * 25)) -#define MVOLT2OFFSET(val) (((val) - 1200) / 25) - -#define DEFAULT_ARM_FREQUENCY 700 -#define DEFAULT_CORE_FREQUENCY 250 -#define DEFAULT_SDRAM_FREQUENCY 400 -#define DEFAULT_LOWEST_FREQ 300 -#define TRANSITION_LATENCY 1000 -#define MIN_OVER_VOLTAGE -16 -#define MAX_OVER_VOLTAGE 6 -#define MSG_ERROR -999999999 -#define MHZSTEP 100 -#define HZSTEP (MHZ2HZ(MHZSTEP)) +#define HZ2MHZ(freq) ((freq) / (1000 * 1000)) +#define MHZ2HZ(freq) ((freq) * (1000 * 1000)) + +#ifdef SOC_BCM2836 +#define OFFSET2MVOLT(val) (((val) / 1000)) +#define MVOLT2OFFSET(val) (((val) * 1000)) +#define DEFAULT_ARM_FREQUENCY 600 +#define DEFAULT_LOWEST_FREQ 600 +#else +#define OFFSET2MVOLT(val) (1200 + ((val) * 25)) +#define MVOLT2OFFSET(val) (((val) - 1200) / 25) +#define DEFAULT_ARM_FREQUENCY 700 +#define DEFAULT_LOWEST_FREQ 300 +#endif +#define DEFAULT_CORE_FREQUENCY 250 +#define DEFAULT_SDRAM_FREQUENCY 400 +#define TRANSITION_LATENCY 1000 +#define MIN_OVER_VOLTAGE -16 +#define MAX_OVER_VOLTAGE 6 +#define MSG_ERROR -999999999 +#define MHZSTEP 100 +#define HZSTEP (MHZ2HZ(MHZSTEP)) #define TZ_ZEROC 2732 #define VC_LOCK(sc) do { \ @@ -1740,6 +1747,23 @@ bcm2835_cpufreq_make_freq_list(device_t dev, struct cf_setting *sets, if (min_freq > cpufreq_lowest_freq) min_freq = cpufreq_lowest_freq; +#ifdef SOC_BCM2836 + /* XXX RPi2 have only 900/600MHz */ + idx = 0; + volts = sc->min_voltage_core; + sets[idx].freq = freq; + sets[idx].volts = volts; + sets[idx].lat = TRANSITION_LATENCY; + sets[idx].dev = dev; + idx++; + if (freq != min_freq) { + sets[idx].freq = min_freq; + sets[idx].volts = volts; + sets[idx].lat = TRANSITION_LATENCY; + sets[idx].dev = dev; + idx++; + } +#else /* from freq to min_freq */ for (idx = 0; idx < *count && freq >= min_freq; idx++) { if (freq > sc->arm_min_freq) @@ -1752,7 +1776,8 @@ bcm2835_cpufreq_make_freq_list(device_t dev, struct cf_setting *sets, sets[idx].dev = dev; freq -= MHZSTEP; } - *count = ++idx; +#endif + *count = idx; return (0); } -- cgit v1.1 From d1a453b983b0126d206e471c98f27f86bb720ba7 Mon Sep 17 00:00:00 2001 From: loos Date: Tue, 5 May 2015 00:19:04 +0000 Subject: Fix DMA on RPi 2. BCM2836 has a different base address for peripherals. Obtained from: netbsd --- sys/arm/broadcom/bcm2835/bcm2835_vcbus.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'sys/arm/broadcom/bcm2835') diff --git a/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h b/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h index cb871f2..7b79b1a 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h +++ b/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h @@ -37,14 +37,20 @@ #define BCM2835_VCBUS_IO_BASE 0x7E000000 #define BCM2835_VCBUS_SDRAM_UNCACHED 0xC0000000 +#ifdef SOC_BCM2836 +#define BCM2835_ARM_IO_BASE 0x3f000000 +#define BCM2835_VCBUS_SDRAM_BASE BCM2835_VCBUS_SDRAM_UNCACHED +#else #define BCM2835_ARM_IO_BASE 0x20000000 -#define BCM2835_ARM_IO_SIZE 0x02000000 +#define BCM2835_VCBUS_SDRAM_BASE BCM2835_VCBUS_SDRAM_CACHED +#endif +#define BCM2835_ARM_IO_SIZE 0x01000000 /* * Convert physical address to VC bus address. Should be used * when submitting address over mailbox interface */ -#define PHYS_TO_VCBUS(pa) ((pa) + BCM2835_VCBUS_SDRAM_CACHED) +#define PHYS_TO_VCBUS(pa) ((pa) + BCM2835_VCBUS_SDRAM_BASE) /* Check whether pa bellong top IO window */ #define BCM2835_ARM_IS_IO(pa) (((pa) >= BCM2835_ARM_IO_BASE) && \ @@ -61,6 +67,6 @@ * when address is returned by VC over mailbox interface. e.g. * framebuffer base */ -#define VCBUS_TO_PHYS(vca) ((vca) - BCM2835_VCBUS_SDRAM_CACHED) +#define VCBUS_TO_PHYS(vca) ((vca) - BCM2835_VCBUS_SDRAM_BASE) #endif /* _BCM2835_VCBUS_H_ */ -- cgit v1.1 From 08c997829821400a9925653728b98122560f81f1 Mon Sep 17 00:00:00 2001 From: loos Date: Tue, 5 May 2015 00:27:55 +0000 Subject: Enable DMA for sdhci on RPi 2 (BCM2836). --- sys/arm/broadcom/bcm2835/bcm2835_sdhci.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'sys/arm/broadcom/bcm2835') diff --git a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c index 1024a48..e950ec6 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c @@ -68,15 +68,8 @@ __FBSDID("$FreeBSD$"); #define dprintf(fmt, args...) #endif -/* DMA doesn't yet work with the bcm3826 */ -#ifdef SOC_BCM2836 -#define PIO_MODE 1 -#else -#define PIO_MODE 0 -#endif - static int bcm2835_sdhci_hs = 1; -static int bcm2835_sdhci_pio_mode = PIO_MODE; +static int bcm2835_sdhci_pio_mode = 0; TUNABLE_INT("hw.bcm2835.sdhci.hs", &bcm2835_sdhci_hs); TUNABLE_INT("hw.bcm2835.sdhci.pio_mode", &bcm2835_sdhci_pio_mode); -- cgit v1.1