Index: stable/11/sys/arm/altera/socfpga/socfpga_common.c
===================================================================
--- stable/11/sys/arm/altera/socfpga/socfpga_common.c (revision 314502)
+++ stable/11/sys/arm/altera/socfpga/socfpga_common.c (revision 314503)
@@ -1,96 +1,94 @@
/*-
* Copyright (c) 2014 Ruslan Bukin
* All rights reserved.
*
* This software was developed by SRI International and the University of
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
* ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include
__FBSDID("$FreeBSD$");
#include
#include
#include
#include
-#include
#include
#include
#include
#include
void
cpu_reset(void)
{
- uint32_t addr, paddr;
+ uint32_t paddr;
bus_addr_t vaddr;
phandle_t node;
if (rstmgr_warmreset() == 0)
goto end;
node = OF_finddevice("rstmgr");
if (node == -1)
goto end;
- if ((OF_getprop(node, "reg", &paddr, sizeof(paddr))) > 0) {
- addr = fdt32_to_cpu(paddr);
- if (bus_space_map(fdtbus_bs_tag, addr, 0x8, 0, &vaddr) == 0) {
+ if ((OF_getencprop(node, "reg", &paddr, sizeof(paddr))) > 0) {
+ if (bus_space_map(fdtbus_bs_tag, paddr, 0x8, 0, &vaddr) == 0) {
bus_space_write_4(fdtbus_bs_tag, vaddr,
RSTMGR_CTRL, CTRL_SWWARMRSTREQ);
}
}
end:
while (1);
}
struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
#ifndef INTRNG
static int
fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
int *pol)
{
if (!fdt_is_compatible(node, "arm,gic"))
return (ENXIO);
*interrupt = fdt32_to_cpu(intr[0]);
*trig = INTR_TRIGGER_CONFORM;
*pol = INTR_POLARITY_CONFORM;
return (0);
}
fdt_pic_decode_t fdt_pic_table[] = {
&fdt_pic_decode_ic,
NULL
};
#endif
Index: stable/11/sys/arm/altera/socfpga/socfpga_rstmgr.c
===================================================================
--- stable/11/sys/arm/altera/socfpga/socfpga_rstmgr.c (revision 314502)
+++ stable/11/sys/arm/altera/socfpga/socfpga_rstmgr.c (revision 314503)
@@ -1,259 +1,257 @@
/*-
* Copyright (c) 2014 Ruslan Bukin
* All rights reserved.
*
* This software was developed by SRI International and the University of
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
* ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* SOCFPGA Reset Manager.
* Chapter 3, Cyclone V Device Handbook (CV-5V2 2014.07.22)
*/
#include
__FBSDID("$FreeBSD$");
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
-#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct rstmgr_softc {
struct resource *res[1];
bus_space_tag_t bst;
bus_space_handle_t bsh;
device_t dev;
};
struct rstmgr_softc *rstmgr_sc;
static struct resource_spec rstmgr_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ -1, 0 }
};
enum {
RSTMGR_SYSCTL_FPGA2HPS,
RSTMGR_SYSCTL_LWHPS2FPGA,
RSTMGR_SYSCTL_HPS2FPGA
};
static int
l3remap(struct rstmgr_softc *sc, int remap, int enable)
{
- uint32_t addr, paddr;
+ uint32_t paddr;
bus_addr_t vaddr;
phandle_t node;
int reg;
/*
* Control whether bridge is visible to L3 masters or not.
* Register is write-only.
*/
reg = REMAP_MPUZERO;
if (enable)
reg |= (remap);
else
reg &= ~(remap);
node = OF_finddevice("l3regs");
if (node == -1) {
device_printf(sc->dev, "Can't find l3regs node\n");
return (1);
}
- if ((OF_getprop(node, "reg", &paddr, sizeof(paddr))) > 0) {
- addr = fdt32_to_cpu(paddr);
- if (bus_space_map(fdtbus_bs_tag, addr, 0x4, 0, &vaddr) == 0) {
+ if ((OF_getencprop(node, "reg", &paddr, sizeof(paddr))) > 0) {
+ if (bus_space_map(fdtbus_bs_tag, paddr, 0x4, 0, &vaddr) == 0) {
bus_space_write_4(fdtbus_bs_tag, vaddr,
L3REGS_REMAP, reg);
return (0);
}
}
return (1);
}
static int
rstmgr_sysctl(SYSCTL_HANDLER_ARGS)
{
struct rstmgr_softc *sc;
int enable;
int remap;
int err;
int reg;
int bit;
sc = arg1;
switch (arg2) {
case RSTMGR_SYSCTL_FPGA2HPS:
bit = BRGMODRST_FPGA2HPS;
remap = 0;
break;
case RSTMGR_SYSCTL_LWHPS2FPGA:
bit = BRGMODRST_LWHPS2FPGA;
remap = REMAP_LWHPS2FPGA;
break;
case RSTMGR_SYSCTL_HPS2FPGA:
bit = BRGMODRST_HPS2FPGA;
remap = REMAP_HPS2FPGA;
break;
default:
return (1);
}
reg = READ4(sc, RSTMGR_BRGMODRST);
enable = reg & bit ? 0 : 1;
err = sysctl_handle_int(oidp, &enable, 0, req);
if (err || !req->newptr)
return (err);
if (enable == 1)
reg &= ~(bit);
else if (enable == 0)
reg |= (bit);
else
return (EINVAL);
WRITE4(sc, RSTMGR_BRGMODRST, reg);
l3remap(sc, remap, enable);
return (0);
}
int
rstmgr_warmreset(void)
{
struct rstmgr_softc *sc;
sc = rstmgr_sc;
if (sc == NULL)
return (1);
/* Request warm reset */
WRITE4(sc, RSTMGR_CTRL,
CTRL_SWWARMRSTREQ);
return (0);
}
static int
rstmgr_add_sysctl(struct rstmgr_softc *sc)
{
struct sysctl_oid_list *children;
struct sysctl_ctx_list *ctx;
ctx = device_get_sysctl_ctx(sc->dev);
children = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev));
SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "fpga2hps",
CTLTYPE_UINT | CTLFLAG_RW, sc, RSTMGR_SYSCTL_FPGA2HPS,
rstmgr_sysctl, "I", "Enable fpga2hps bridge");
SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "lwhps2fpga",
CTLTYPE_UINT | CTLFLAG_RW, sc, RSTMGR_SYSCTL_LWHPS2FPGA,
rstmgr_sysctl, "I", "Enable lwhps2fpga bridge");
SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "hps2fpga",
CTLTYPE_UINT | CTLFLAG_RW, sc, RSTMGR_SYSCTL_HPS2FPGA,
rstmgr_sysctl, "I", "Enable hps2fpga bridge");
return (0);
}
static int
rstmgr_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "altr,rst-mgr"))
return (ENXIO);
device_set_desc(dev, "Reset Manager");
return (BUS_PROBE_DEFAULT);
}
static int
rstmgr_attach(device_t dev)
{
struct rstmgr_softc *sc;
sc = device_get_softc(dev);
sc->dev = dev;
if (bus_alloc_resources(dev, rstmgr_spec, sc->res)) {
device_printf(dev, "could not allocate resources\n");
return (ENXIO);
}
/* Memory interface */
sc->bst = rman_get_bustag(sc->res[0]);
sc->bsh = rman_get_bushandle(sc->res[0]);
rstmgr_sc = sc;
rstmgr_add_sysctl(sc);
return (0);
}
static device_method_t rstmgr_methods[] = {
DEVMETHOD(device_probe, rstmgr_probe),
DEVMETHOD(device_attach, rstmgr_attach),
{ 0, 0 }
};
static driver_t rstmgr_driver = {
"rstmgr",
rstmgr_methods,
sizeof(struct rstmgr_softc),
};
static devclass_t rstmgr_devclass;
DRIVER_MODULE(rstmgr, simplebus, rstmgr_driver, rstmgr_devclass, 0, 0);
Index: stable/11/sys/arm/broadcom/bcm2835/bcm2835_fb.c
===================================================================
--- stable/11/sys/arm/broadcom/bcm2835/bcm2835_fb.c (revision 314502)
+++ stable/11/sys/arm/broadcom/bcm2835/bcm2835_fb.c (revision 314503)
@@ -1,870 +1,870 @@
/*-
* Copyright (c) 2012 Oleksandr Tymoshenko
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include
__FBSDID("$FreeBSD$");
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "mbox_if.h"
struct argb {
uint8_t a;
uint8_t r;
uint8_t g;
uint8_t b;
};
static struct argb bcmfb_palette[16] = {
{0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0xaa},
{0x00, 0x00, 0xaa, 0x00},
{0x00, 0x00, 0xaa, 0xaa},
{0x00, 0xaa, 0x00, 0x00},
{0x00, 0xaa, 0x00, 0xaa},
{0x00, 0xaa, 0x55, 0x00},
{0x00, 0xaa, 0xaa, 0xaa},
{0x00, 0x55, 0x55, 0x55},
{0x00, 0x55, 0x55, 0xff},
{0x00, 0x55, 0xff, 0x55},
{0x00, 0x55, 0xff, 0xff},
{0x00, 0xff, 0x55, 0x55},
{0x00, 0xff, 0x55, 0xff},
{0x00, 0xff, 0xff, 0x55},
{0x00, 0xff, 0xff, 0xff}
};
/* mouse pointer from dev/syscons/scgfbrndr.c */
static u_char mouse_pointer[16] = {
0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68,
0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00
};
#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 {
/* Videoadpater part */
video_adapter_t va;
intptr_t fb_addr;
intptr_t fb_paddr;
unsigned int fb_size;
unsigned int height;
unsigned int width;
unsigned int depth;
unsigned int stride;
unsigned int xmargin;
unsigned int ymargin;
unsigned char *font;
int fbswap;
int initialized;
};
static struct bcmsc_softc bcmsc;
static struct ofw_compat_data compat_data[] = {
{"broadcom,bcm2835-fb", 1},
{"brcm,bcm2708-fb", 1},
{NULL, 0}
};
static int bcm_fb_probe(device_t);
static int bcm_fb_attach(device_t);
static void bcmfb_update_margins(video_adapter_t *adp);
static int bcmfb_configure(int);
static int
bcm_fb_probe(device_t dev)
{
int error;
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
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 bcm2835_fb_config fb;
struct bcmsc_softc *sc;
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);
memset(&fb, 0, sizeof(fb));
if (bcm2835_mbox_fb_get_w_h(&fb) != 0)
return (ENXIO);
fb.bpp = FB_DEPTH;
fb.vxres = fb.xres;
fb.vyres = fb.yres;
fb.xoffset = fb.yoffset = 0;
if (bcm2835_mbox_fb_init(&fb) != 0)
return (ENXIO);
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");
return (ENXIO);
}
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);
}
static device_method_t bcm_fb_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, bcm_fb_probe),
DEVMETHOD(device_attach, bcm_fb_attach),
{ 0, 0 }
};
static devclass_t bcm_fb_devclass;
static driver_t bcm_fb_driver = {
"fb",
bcm_fb_methods,
sizeof(struct bcmsc_softc),
};
DRIVER_MODULE(bcm2835fb, ofwbus, bcm_fb_driver, bcm_fb_devclass, 0, 0);
DRIVER_MODULE(bcm2835fb, simplebus, bcm_fb_driver, bcm_fb_devclass, 0, 0);
/*
* Video driver routines and glue.
*/
static vi_probe_t bcmfb_probe;
static vi_init_t bcmfb_init;
static vi_get_info_t bcmfb_get_info;
static vi_query_mode_t bcmfb_query_mode;
static vi_set_mode_t bcmfb_set_mode;
static vi_save_font_t bcmfb_save_font;
static vi_load_font_t bcmfb_load_font;
static vi_show_font_t bcmfb_show_font;
static vi_save_palette_t bcmfb_save_palette;
static vi_load_palette_t bcmfb_load_palette;
static vi_set_border_t bcmfb_set_border;
static vi_save_state_t bcmfb_save_state;
static vi_load_state_t bcmfb_load_state;
static vi_set_win_org_t bcmfb_set_win_org;
static vi_read_hw_cursor_t bcmfb_read_hw_cursor;
static vi_set_hw_cursor_t bcmfb_set_hw_cursor;
static vi_set_hw_cursor_shape_t bcmfb_set_hw_cursor_shape;
static vi_blank_display_t bcmfb_blank_display;
static vi_mmap_t bcmfb_mmap;
static vi_ioctl_t bcmfb_ioctl;
static vi_clear_t bcmfb_clear;
static vi_fill_rect_t bcmfb_fill_rect;
static vi_bitblt_t bcmfb_bitblt;
static vi_diag_t bcmfb_diag;
static vi_save_cursor_palette_t bcmfb_save_cursor_palette;
static vi_load_cursor_palette_t bcmfb_load_cursor_palette;
static vi_copy_t bcmfb_copy;
static vi_putp_t bcmfb_putp;
static vi_putc_t bcmfb_putc;
static vi_puts_t bcmfb_puts;
static vi_putm_t bcmfb_putm;
static video_switch_t bcmfbvidsw = {
.probe = bcmfb_probe,
.init = bcmfb_init,
.get_info = bcmfb_get_info,
.query_mode = bcmfb_query_mode,
.set_mode = bcmfb_set_mode,
.save_font = bcmfb_save_font,
.load_font = bcmfb_load_font,
.show_font = bcmfb_show_font,
.save_palette = bcmfb_save_palette,
.load_palette = bcmfb_load_palette,
.set_border = bcmfb_set_border,
.save_state = bcmfb_save_state,
.load_state = bcmfb_load_state,
.set_win_org = bcmfb_set_win_org,
.read_hw_cursor = bcmfb_read_hw_cursor,
.set_hw_cursor = bcmfb_set_hw_cursor,
.set_hw_cursor_shape = bcmfb_set_hw_cursor_shape,
.blank_display = bcmfb_blank_display,
.mmap = bcmfb_mmap,
.ioctl = bcmfb_ioctl,
.clear = bcmfb_clear,
.fill_rect = bcmfb_fill_rect,
.bitblt = bcmfb_bitblt,
.diag = bcmfb_diag,
.save_cursor_palette = bcmfb_save_cursor_palette,
.load_cursor_palette = bcmfb_load_cursor_palette,
.copy = bcmfb_copy,
.putp = bcmfb_putp,
.putc = bcmfb_putc,
.puts = bcmfb_puts,
.putm = bcmfb_putm,
};
VIDEO_DRIVER(bcmfb, bcmfbvidsw, bcmfb_configure);
static vr_init_t bcmrend_init;
static vr_clear_t bcmrend_clear;
static vr_draw_border_t bcmrend_draw_border;
static vr_draw_t bcmrend_draw;
static vr_set_cursor_t bcmrend_set_cursor;
static vr_draw_cursor_t bcmrend_draw_cursor;
static vr_blink_cursor_t bcmrend_blink_cursor;
static vr_set_mouse_t bcmrend_set_mouse;
static vr_draw_mouse_t bcmrend_draw_mouse;
/*
* We use our own renderer; this is because we must emulate a hardware
* cursor.
*/
static sc_rndr_sw_t bcmrend = {
bcmrend_init,
bcmrend_clear,
bcmrend_draw_border,
bcmrend_draw,
bcmrend_set_cursor,
bcmrend_draw_cursor,
bcmrend_blink_cursor,
bcmrend_set_mouse,
bcmrend_draw_mouse
};
RENDERER(bcmfb, 0, bcmrend, gfb_set);
RENDERER_MODULE(bcmfb, gfb_set);
static void
bcmrend_init(scr_stat* scp)
{
}
static void
bcmrend_clear(scr_stat* scp, int c, int attr)
{
}
static void
bcmrend_draw_border(scr_stat* scp, int color)
{
}
static void
bcmrend_draw(scr_stat* scp, int from, int count, int flip)
{
video_adapter_t* adp = scp->sc->adp;
int i, c, a;
if (!flip) {
/* Normal printing */
vidd_puts(adp, from, (uint16_t*)sc_vtb_pointer(&scp->vtb, from), count);
} else {
/* This is for selections and such: invert the color attribute */
for (i = count; i-- > 0; ++from) {
c = sc_vtb_getc(&scp->vtb, from);
a = sc_vtb_geta(&scp->vtb, from) >> 8;
vidd_putc(adp, from, c, (a >> 4) | ((a & 0xf) << 4));
}
}
}
static void
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)
{
int bytes, col, i, j, row;
struct bcmsc_softc *sc;
uint8_t *addr;
video_adapter_t *adp;
adp = scp->sc->adp;
sc = (struct bcmsc_softc *)adp;
if (scp->curs_attr.height <= 0)
return;
if (sc->fb_addr == 0)
return;
if (off >= adp->va_info.vi_width * adp->va_info.vi_height)
return;
/* calculate the coordinates in the video buffer */
row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight;
col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth;
addr = (uint8_t *)sc->fb_addr
+ (row + sc->ymargin)*(sc->stride)
+ (sc->depth/8) * (col + sc->xmargin);
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++) {
switch (sc->depth) {
case 32:
case 24:
addr[bytes*j + 2] ^= 0xff;
/* FALLTHROUGH */
case 16:
addr[bytes*j + 1] ^= 0xff;
addr[bytes*j] ^= 0xff;
break;
default:
break;
}
}
addr += sc->stride;
}
}
static void
bcmrend_blink_cursor(scr_stat* scp, int at, int flip)
{
}
static void
bcmrend_set_mouse(scr_stat* scp)
{
}
static void
bcmrend_draw_mouse(scr_stat* scp, int x, int y, int on)
{
vidd_putm(scp->sc->adp, x, y, mouse_pointer, 0xffffffff, 16, 8);
}
static uint16_t bcmfb_static_window[ROW*COL];
extern u_char dflt_font_16[];
/*
* Update videoadapter settings after changing resolution
*/
static void
bcmfb_update_margins(video_adapter_t *adp)
{
struct bcmsc_softc *sc;
video_info_t *vi;
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;
}
static int
bcmfb_configure(int flags)
{
char bootargs[2048], *n, *p, *v;
pcell_t cell;
phandle_t chosen, display, root;
struct bcmsc_softc *sc;
sc = &bcmsc;
if (sc->initialized)
return (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 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 (sc->width == 0) {
- if ((OF_getprop(display, "broadcom,width",
+ if ((OF_getencprop(display, "broadcom,width",
&cell, sizeof(cell))) > 0)
- sc->width = (int)fdt32_to_cpu(cell);
+ sc->width = cell;
}
if (sc->height == 0) {
if ((OF_getprop(display, "broadcom,height",
&cell, sizeof(cell))) > 0)
- sc->height = (int)fdt32_to_cpu(cell);
+ sc->height = cell;
}
}
if (sc->width == 0)
sc->width = FB_WIDTH;
if (sc->height == 0)
sc->height = FB_HEIGHT;
bcmfb_init(0, &sc->va, 0);
sc->initialized = 1;
return (0);
}
static int
bcmfb_probe(int unit, video_adapter_t **adp, void *arg, int flags)
{
return (0);
}
static int
bcmfb_init(int unit, video_adapter_t *adp, int flags)
{
struct bcmsc_softc *sc;
video_info_t *vi;
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 = 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
*/
if (vi->vi_width > COL)
vi->vi_width = COL;
if (vi->vi_height > ROW)
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;
adp->va_window = (vm_offset_t) bcmfb_static_window;
adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */;
vid_register(&sc->va);
return (0);
}
static int
bcmfb_get_info(video_adapter_t *adp, int mode, video_info_t *info)
{
bcopy(&adp->va_info, info, sizeof(*info));
return (0);
}
static int
bcmfb_query_mode(video_adapter_t *adp, video_info_t *info)
{
return (0);
}
static int
bcmfb_set_mode(video_adapter_t *adp, int mode)
{
return (0);
}
static int
bcmfb_save_font(video_adapter_t *adp, int page, int size, int width,
u_char *data, int c, int count)
{
return (0);
}
static int
bcmfb_load_font(video_adapter_t *adp, int page, int size, int width,
u_char *data, int c, int count)
{
struct bcmsc_softc *sc;
sc = (struct bcmsc_softc *)adp;
sc->font = data;
return (0);
}
static int
bcmfb_show_font(video_adapter_t *adp, int page)
{
return (0);
}
static int
bcmfb_save_palette(video_adapter_t *adp, u_char *palette)
{
return (0);
}
static int
bcmfb_load_palette(video_adapter_t *adp, u_char *palette)
{
return (0);
}
static int
bcmfb_set_border(video_adapter_t *adp, int border)
{
return (bcmfb_blank_display(adp, border));
}
static int
bcmfb_save_state(video_adapter_t *adp, void *p, size_t size)
{
return (0);
}
static int
bcmfb_load_state(video_adapter_t *adp, void *p)
{
return (0);
}
static int
bcmfb_set_win_org(video_adapter_t *adp, off_t offset)
{
return (0);
}
static int
bcmfb_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
{
*col = *row = 0;
return (0);
}
static int
bcmfb_set_hw_cursor(video_adapter_t *adp, int col, int row)
{
return (0);
}
static int
bcmfb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
int celsize, int blink)
{
return (0);
}
static int
bcmfb_blank_display(video_adapter_t *adp, int mode)
{
struct bcmsc_softc *sc;
sc = (struct bcmsc_softc *)adp;
if (sc && sc->fb_addr)
memset((void*)sc->fb_addr, 0, sc->fb_size);
return (0);
}
static int
bcmfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr,
int prot, vm_memattr_t *memattr)
{
struct bcmsc_softc *sc;
sc = (struct bcmsc_softc *)adp;
/*
* This might be a legacy VGA mem request: if so, just point it at the
* framebuffer, since it shouldn't be touched
*/
if (offset < sc->stride*sc->height) {
*paddr = sc->fb_paddr + offset;
return (0);
}
return (EINVAL);
}
static int
bcmfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data)
{
struct bcmsc_softc *sc;
struct fbtype *fb;
sc = (struct bcmsc_softc *)adp;
switch (cmd) {
case FBIOGTYPE:
fb = (struct fbtype *)data;
fb->fb_type = FBTYPE_PCIMISC;
fb->fb_height = sc->height;
fb->fb_width = sc->width;
fb->fb_depth = sc->depth;
if (sc->depth <= 1 || sc->depth > 8)
fb->fb_cmsize = 0;
else
fb->fb_cmsize = 1 << sc->depth;
fb->fb_size = sc->fb_size;
break;
default:
return (fb_commonioctl(adp, cmd, data));
}
return (0);
}
static int
bcmfb_clear(video_adapter_t *adp)
{
return (bcmfb_blank_display(adp, 0));
}
static int
bcmfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
{
return (0);
}
static int
bcmfb_bitblt(video_adapter_t *adp, ...)
{
return (0);
}
static int
bcmfb_diag(video_adapter_t *adp, int level)
{
return (0);
}
static int
bcmfb_save_cursor_palette(video_adapter_t *adp, u_char *palette)
{
return (0);
}
static int
bcmfb_load_cursor_palette(video_adapter_t *adp, u_char *palette)
{
return (0);
}
static int
bcmfb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n)
{
return (0);
}
static int
bcmfb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a,
int size, int bpp, int bit_ltor, int byte_ltor)
{
return (0);
}
static int
bcmfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
{
int bytes, col, i, j, k, row;
struct bcmsc_softc *sc;
u_char *p;
uint8_t *addr, fg, bg, color;
uint16_t rgb;
sc = (struct bcmsc_softc *)adp;
if (sc->fb_addr == 0)
return (0);
row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight;
col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth;
p = sc->font + c*BCMFB_FONT_HEIGHT;
addr = (uint8_t *)sc->fb_addr
+ (row + sc->ymargin)*(sc->stride)
+ (sc->depth/8) * (col + sc->xmargin);
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)
color = bg;
else
color = fg;
switch (sc->depth) {
case 32:
case 24:
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[bytes * j] = rgb & 0xff;
addr[bytes * j + 1] = (rgb >> 8) & 0xff;
default:
/* Not supported yet */
break;
}
}
addr += (sc->stride);
}
return (0);
}
static int
bcmfb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len)
{
int i;
for (i = 0; i < len; i++)
bcmfb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8);
return (0);
}
static int
bcmfb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
uint32_t pixel_mask, int size, int width)
{
return (0);
}
/*
* Define a stub keyboard driver in case one hasn't been
* compiled into the kernel
*/
#include
#include
static int dummy_kbd_configure(int flags);
keyboard_switch_t bcmdummysw;
static int
dummy_kbd_configure(int flags)
{
return (0);
}
KEYBOARD_DRIVER(bcmdummy, bcmdummysw, dummy_kbd_configure);
Index: stable/11/sys/arm/broadcom/bcm2835/bcm2835_machdep.c
===================================================================
--- stable/11/sys/arm/broadcom/bcm2835/bcm2835_machdep.c (revision 314502)
+++ stable/11/sys/arm/broadcom/bcm2835/bcm2835_machdep.c (revision 314503)
@@ -1,157 +1,159 @@
/*-
* Copyright (c) 2012 Oleksandr Tymoshenko.
* Copyright (c) 1994-1998 Mark Brinicombe.
* Copyright (c) 1994 Brini.
* All rights reserved.
*
* This code is derived from software written for Brini by Mark Brinicombe
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Brini.
* 4. The name of the company nor the name of the author may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: FreeBSD: //depot/projects/arm/src/sys/arm/at91/kb920x_machdep.c, rev 45
*/
#include "opt_ddb.h"
#include "opt_platform.h"
#include
__FBSDID("$FreeBSD$");
#define _ARM32_BUS_DMA_PRIVATE
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "platform_if.h"
static vm_offset_t
bcm2835_lastaddr(platform_t plat)
{
return (devmap_lastaddr());
}
static void
bcm2835_late_init(platform_t plat)
{
phandle_t system;
pcell_t cells[2];
int len;
system = OF_finddevice("/system");
if (system != 0) {
- len = OF_getprop(system, "linux,serial", &cells, sizeof(cells));
+ len = OF_getencprop(system, "linux,serial", cells,
+ sizeof(cells));
if (len > 0)
- board_set_serial(fdt64_to_cpu(*((uint64_t *)cells)));
+ board_set_serial(((uint64_t)cells[0]) << 32 | cells[1]);
- len = OF_getprop(system, "linux,revision", &cells, sizeof(cells));
+ len = OF_getencprop(system, "linux,revision", cells,
+ sizeof(cells));
if (len > 0)
- board_set_revision(fdt32_to_cpu(*((uint32_t *)cells)));
+ board_set_revision(cells[0]);
}
}
#ifdef SOC_BCM2835
/*
* Set up static device mappings.
* All on-chip peripherals exist in a 16MB range starting at 0x20000000.
* Map the entire range using 1MB section mappings.
*/
static int
bcm2835_devmap_init(platform_t plat)
{
devmap_add_entry(0x20000000, 0x01000000);
return (0);
}
#endif
#ifdef SOC_BCM2836
static int
bcm2836_devmap_init(platform_t plat)
{
devmap_add_entry(0x3f000000, 0x01000000);
return (0);
}
#endif
struct arm32_dma_range *
bus_dma_get_range(void)
{
return (NULL);
}
int
bus_dma_get_range_nb(void)
{
return (0);
}
void
cpu_reset()
{
bcmwd_watchdog_reset();
while (1);
}
#ifdef SOC_BCM2835
static platform_method_t bcm2835_methods[] = {
PLATFORMMETHOD(platform_devmap_init, bcm2835_devmap_init),
PLATFORMMETHOD(platform_lastaddr, bcm2835_lastaddr),
PLATFORMMETHOD(platform_late_init, bcm2835_late_init),
PLATFORMMETHOD_END,
};
FDT_PLATFORM_DEF(bcm2835, "bcm2835", 0, "raspberrypi,model-b", 0);
#endif
#ifdef SOC_BCM2836
static platform_method_t bcm2836_methods[] = {
PLATFORMMETHOD(platform_devmap_init, bcm2836_devmap_init),
PLATFORMMETHOD(platform_lastaddr, bcm2835_lastaddr),
PLATFORMMETHOD(platform_late_init, bcm2835_late_init),
PLATFORMMETHOD_END,
};
FDT_PLATFORM_DEF(bcm2836, "bcm2836", 0, "brcm,bcm2709", 0);
#endif
Index: stable/11/sys/arm/freescale/imx/imx51_ipuv3.c
===================================================================
--- stable/11/sys/arm/freescale/imx/imx51_ipuv3.c (revision 314502)
+++ stable/11/sys/arm/freescale/imx/imx51_ipuv3.c (revision 314503)
@@ -1,898 +1,897 @@
/*-
* Copyright (c) 2012 Oleksandr Tymoshenko
* Copyright (c) 2012, 2013 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by Oleksandr Rybalko
* under sponsorship from the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include
__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
#define IMX51_IPU_HSP_CLOCK 665000000
#define IPU3FB_FONT_HEIGHT 16
struct ipu3sc_softc {
device_t dev;
bus_addr_t pbase;
bus_addr_t vbase;
bus_space_tag_t iot;
bus_space_handle_t ioh;
bus_space_handle_t cm_ioh;
bus_space_handle_t dp_ioh;
bus_space_handle_t di0_ioh;
bus_space_handle_t di1_ioh;
bus_space_handle_t dctmpl_ioh;
bus_space_handle_t dc_ioh;
bus_space_handle_t dmfc_ioh;
bus_space_handle_t idmac_ioh;
bus_space_handle_t cpmem_ioh;
};
struct video_adapter_softc {
/* Videoadpater part */
video_adapter_t va;
intptr_t fb_addr;
intptr_t fb_paddr;
unsigned int fb_size;
int bpp;
int depth;
unsigned int height;
unsigned int width;
unsigned int stride;
unsigned int xmargin;
unsigned int ymargin;
unsigned char *font;
int initialized;
};
static struct ipu3sc_softc *ipu3sc_softc;
static struct video_adapter_softc va_softc;
/* FIXME: not only 2 bytes color supported */
static uint16_t colors[16] = {
0x0000, /* black */
0x001f, /* blue */
0x07e0, /* green */
0x07ff, /* cyan */
0xf800, /* red */
0xf81f, /* magenta */
0x3800, /* brown */
0xc618, /* light grey */
0xc618, /* XXX: dark grey */
0x001f, /* XXX: light blue */
0x07e0, /* XXX: light green */
0x07ff, /* XXX: light cyan */
0xf800, /* XXX: light red */
0xf81f, /* XXX: light magenta */
0xffe0, /* yellow */
0xffff, /* white */
};
static uint32_t colors_24[16] = {
0x000000,/* Black */
0x000080,/* Blue */
0x008000,/* Green */
0x008080,/* Cyan */
0x800000,/* Red */
0x800080,/* Magenta */
0xcc6600,/* brown */
0xC0C0C0,/* Silver */
0x808080,/* Gray */
0x0000FF,/* Light Blue */
0x00FF00,/* Light Green */
0x00FFFF,/* Light Cyan */
0xFF0000,/* Light Red */
0xFF00FF,/* Light Magenta */
0xFFFF00,/* Yellow */
0xFFFFFF,/* White */
};
#define IPUV3_READ(ipuv3, module, reg) \
bus_space_read_4((ipuv3)->iot, (ipuv3)->module##_ioh, (reg))
#define IPUV3_WRITE(ipuv3, module, reg, val) \
bus_space_write_4((ipuv3)->iot, (ipuv3)->module##_ioh, (reg), (val))
#define CPMEM_CHANNEL_OFFSET(_c) ((_c) * 0x40)
#define CPMEM_WORD_OFFSET(_w) ((_w) * 0x20)
#define CPMEM_DP_OFFSET(_d) ((_d) * 0x10000)
#define IMX_IPU_DP0 0
#define IMX_IPU_DP1 1
#define CPMEM_CHANNEL(_dp, _ch, _w) \
(CPMEM_DP_OFFSET(_dp) + CPMEM_CHANNEL_OFFSET(_ch) + \
CPMEM_WORD_OFFSET(_w))
#define CPMEM_OFFSET(_dp, _ch, _w, _o) \
(CPMEM_CHANNEL((_dp), (_ch), (_w)) + (_o))
#define IPUV3_DEBUG 100
#ifdef IPUV3_DEBUG
#define SUBMOD_DUMP_REG(_sc, _m, _l) \
{ \
int i; \
printf("*** " #_m " ***\n"); \
for (i = 0; i <= (_l); i += 4) { \
if ((i % 32) == 0) \
printf("%04x: ", i & 0xffff); \
printf("0x%08x%c", IPUV3_READ((_sc), _m, i), \
((i + 4) % 32)?' ':'\n'); \
} \
printf("\n"); \
}
#endif
#ifdef IPUV3_DEBUG
int ipuv3_debug = IPUV3_DEBUG;
#define DPRINTFN(n,x) if (ipuv3_debug>(n)) printf x; else
#else
#define DPRINTFN(n,x)
#endif
static int ipu3_fb_probe(device_t);
static int ipu3_fb_attach(device_t);
static int
ipu3_fb_malloc(struct ipu3sc_softc *sc, size_t size)
{
sc->vbase = (uint32_t)contigmalloc(size, M_DEVBUF, M_ZERO, 0, ~0,
PAGE_SIZE, 0);
sc->pbase = vtophys(sc->vbase);
return (0);
}
static void
ipu3_fb_init(void *arg)
{
struct ipu3sc_softc *sc = arg;
struct video_adapter_softc *va_sc = &va_softc;
uint64_t w0sh96;
uint32_t w1sh96;
/* FW W0[137:125] - 96 = [41:29] */
/* FH W0[149:138] - 96 = [53:42] */
w0sh96 = IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 0, 16));
w0sh96 <<= 32;
w0sh96 |= IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 0, 12));
va_sc->width = ((w0sh96 >> 29) & 0x1fff) + 1;
va_sc->height = ((w0sh96 >> 42) & 0x0fff) + 1;
/* SLY W1[115:102] - 96 = [19:6] */
w1sh96 = IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 12));
va_sc->stride = ((w1sh96 >> 6) & 0x3fff) + 1;
printf("%dx%d [%d]\n", va_sc->width, va_sc->height, va_sc->stride);
va_sc->fb_size = va_sc->height * va_sc->stride;
ipu3_fb_malloc(sc, va_sc->fb_size);
/* DP1 + config_ch_23 + word_2 */
IPUV3_WRITE(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 0),
((sc->pbase >> 3) | ((sc->pbase >> 3) << 29)) & 0xffffffff);
IPUV3_WRITE(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 4),
((sc->pbase >> 3) >> 3) & 0xffffffff);
va_sc->fb_addr = (intptr_t)sc->vbase;
va_sc->fb_paddr = (intptr_t)sc->pbase;
va_sc->bpp = va_sc->stride / va_sc->width;
va_sc->depth = va_sc->bpp * 8;
}
static int
ipu3_fb_probe(device_t dev)
{
int error;
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "fsl,ipu3"))
return (ENXIO);
device_set_desc(dev, "i.MX5x Image Processing Unit v3 (FB)");
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
ipu3_fb_attach(device_t dev)
{
struct ipu3sc_softc *sc = device_get_softc(dev);
bus_space_tag_t iot;
bus_space_handle_t ioh;
phandle_t node;
pcell_t reg;
int err;
uintptr_t base;
if (ipu3sc_softc)
return (ENXIO);
ipu3sc_softc = sc;
if (bootverbose)
device_printf(dev, "clock gate status is %d\n",
imx51_get_clk_gating(IMX51CLK_IPU_HSP_CLK_ROOT));
sc->dev = dev;
err = (sc_attach_unit(device_get_unit(dev),
device_get_flags(dev) | SC_AUTODETECT_KBD));
if (err) {
device_printf(dev, "failed to attach syscons\n");
goto fail;
}
sc = device_get_softc(dev);
sc->iot = iot = fdtbus_bs_tag;
/*
* Retrieve the device address based on the start address in the
* DTS. The DTS for i.MX51 specifies 0x5e000000 as the first register
* address, so we just subtract IPU_CM_BASE to get the offset at which
* the IPU device was memory mapped.
* On i.MX53, the offset is 0.
*/
node = ofw_bus_get_node(dev);
- if ((OF_getprop(node, "reg", ®, sizeof(reg))) <= 0)
+ if ((OF_getencprop(node, "reg", ®, sizeof(reg))) <= 0)
base = 0;
else
- base = fdt32_to_cpu(reg) - IPU_CM_BASE(0);
+ base = reg - IPU_CM_BASE(0);
/* map controller registers */
err = bus_space_map(iot, IPU_CM_BASE(base), IPU_CM_SIZE, 0, &ioh);
if (err)
goto fail_retarn_cm;
sc->cm_ioh = ioh;
/* map Display Multi FIFO Controller registers */
err = bus_space_map(iot, IPU_DMFC_BASE(base), IPU_DMFC_SIZE, 0, &ioh);
if (err)
goto fail_retarn_dmfc;
sc->dmfc_ioh = ioh;
/* map Display Interface 0 registers */
err = bus_space_map(iot, IPU_DI0_BASE(base), IPU_DI0_SIZE, 0, &ioh);
if (err)
goto fail_retarn_di0;
sc->di0_ioh = ioh;
/* map Display Interface 1 registers */
err = bus_space_map(iot, IPU_DI1_BASE(base), IPU_DI0_SIZE, 0, &ioh);
if (err)
goto fail_retarn_di1;
sc->di1_ioh = ioh;
/* map Display Processor registers */
err = bus_space_map(iot, IPU_DP_BASE(base), IPU_DP_SIZE, 0, &ioh);
if (err)
goto fail_retarn_dp;
sc->dp_ioh = ioh;
/* map Display Controller registers */
err = bus_space_map(iot, IPU_DC_BASE(base), IPU_DC_SIZE, 0, &ioh);
if (err)
goto fail_retarn_dc;
sc->dc_ioh = ioh;
/* map Image DMA Controller registers */
err = bus_space_map(iot, IPU_IDMAC_BASE(base), IPU_IDMAC_SIZE, 0,
&ioh);
if (err)
goto fail_retarn_idmac;
sc->idmac_ioh = ioh;
/* map CPMEM registers */
err = bus_space_map(iot, IPU_CPMEM_BASE(base), IPU_CPMEM_SIZE, 0,
&ioh);
if (err)
goto fail_retarn_cpmem;
sc->cpmem_ioh = ioh;
/* map DCTEMPL registers */
err = bus_space_map(iot, IPU_DCTMPL_BASE(base), IPU_DCTMPL_SIZE, 0,
&ioh);
if (err)
goto fail_retarn_dctmpl;
sc->dctmpl_ioh = ioh;
#ifdef notyet
sc->ih = imx51_ipuv3_intr_establish(IMX51_INT_IPUV3, IPL_BIO,
ipuv3intr, sc);
if (sc->ih == NULL) {
device_printf(sc->dev,
"unable to establish interrupt at irq %d\n",
IMX51_INT_IPUV3);
return (ENXIO);
}
#endif
/*
* We have to wait until interrupts are enabled.
* Mailbox relies on it to get data from VideoCore
*/
ipu3_fb_init(sc);
return (0);
fail:
return (ENXIO);
fail_retarn_dctmpl:
bus_space_unmap(sc->iot, sc->cpmem_ioh, IPU_CPMEM_SIZE);
fail_retarn_cpmem:
bus_space_unmap(sc->iot, sc->idmac_ioh, IPU_IDMAC_SIZE);
fail_retarn_idmac:
bus_space_unmap(sc->iot, sc->dc_ioh, IPU_DC_SIZE);
fail_retarn_dp:
bus_space_unmap(sc->iot, sc->dp_ioh, IPU_DP_SIZE);
fail_retarn_dc:
bus_space_unmap(sc->iot, sc->di1_ioh, IPU_DI1_SIZE);
fail_retarn_di1:
bus_space_unmap(sc->iot, sc->di0_ioh, IPU_DI0_SIZE);
fail_retarn_di0:
bus_space_unmap(sc->iot, sc->dmfc_ioh, IPU_DMFC_SIZE);
fail_retarn_dmfc:
bus_space_unmap(sc->iot, sc->dc_ioh, IPU_CM_SIZE);
fail_retarn_cm:
device_printf(sc->dev,
"failed to map registers (errno=%d)\n", err);
return (err);
}
static device_method_t ipu3_fb_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ipu3_fb_probe),
DEVMETHOD(device_attach, ipu3_fb_attach),
{ 0, 0 }
};
static devclass_t ipu3_fb_devclass;
static driver_t ipu3_fb_driver = {
"fb",
ipu3_fb_methods,
sizeof(struct ipu3sc_softc),
};
DRIVER_MODULE(ipu3fb, simplebus, ipu3_fb_driver, ipu3_fb_devclass, 0, 0);
/*
* Video driver routines and glue.
*/
static int ipu3fb_configure(int);
static vi_probe_t ipu3fb_probe;
static vi_init_t ipu3fb_init;
static vi_get_info_t ipu3fb_get_info;
static vi_query_mode_t ipu3fb_query_mode;
static vi_set_mode_t ipu3fb_set_mode;
static vi_save_font_t ipu3fb_save_font;
static vi_load_font_t ipu3fb_load_font;
static vi_show_font_t ipu3fb_show_font;
static vi_save_palette_t ipu3fb_save_palette;
static vi_load_palette_t ipu3fb_load_palette;
static vi_set_border_t ipu3fb_set_border;
static vi_save_state_t ipu3fb_save_state;
static vi_load_state_t ipu3fb_load_state;
static vi_set_win_org_t ipu3fb_set_win_org;
static vi_read_hw_cursor_t ipu3fb_read_hw_cursor;
static vi_set_hw_cursor_t ipu3fb_set_hw_cursor;
static vi_set_hw_cursor_shape_t ipu3fb_set_hw_cursor_shape;
static vi_blank_display_t ipu3fb_blank_display;
static vi_mmap_t ipu3fb_mmap;
static vi_ioctl_t ipu3fb_ioctl;
static vi_clear_t ipu3fb_clear;
static vi_fill_rect_t ipu3fb_fill_rect;
static vi_bitblt_t ipu3fb_bitblt;
static vi_diag_t ipu3fb_diag;
static vi_save_cursor_palette_t ipu3fb_save_cursor_palette;
static vi_load_cursor_palette_t ipu3fb_load_cursor_palette;
static vi_copy_t ipu3fb_copy;
static vi_putp_t ipu3fb_putp;
static vi_putc_t ipu3fb_putc;
static vi_puts_t ipu3fb_puts;
static vi_putm_t ipu3fb_putm;
static video_switch_t ipu3fbvidsw = {
.probe = ipu3fb_probe,
.init = ipu3fb_init,
.get_info = ipu3fb_get_info,
.query_mode = ipu3fb_query_mode,
.set_mode = ipu3fb_set_mode,
.save_font = ipu3fb_save_font,
.load_font = ipu3fb_load_font,
.show_font = ipu3fb_show_font,
.save_palette = ipu3fb_save_palette,
.load_palette = ipu3fb_load_palette,
.set_border = ipu3fb_set_border,
.save_state = ipu3fb_save_state,
.load_state = ipu3fb_load_state,
.set_win_org = ipu3fb_set_win_org,
.read_hw_cursor = ipu3fb_read_hw_cursor,
.set_hw_cursor = ipu3fb_set_hw_cursor,
.set_hw_cursor_shape = ipu3fb_set_hw_cursor_shape,
.blank_display = ipu3fb_blank_display,
.mmap = ipu3fb_mmap,
.ioctl = ipu3fb_ioctl,
.clear = ipu3fb_clear,
.fill_rect = ipu3fb_fill_rect,
.bitblt = ipu3fb_bitblt,
.diag = ipu3fb_diag,
.save_cursor_palette = ipu3fb_save_cursor_palette,
.load_cursor_palette = ipu3fb_load_cursor_palette,
.copy = ipu3fb_copy,
.putp = ipu3fb_putp,
.putc = ipu3fb_putc,
.puts = ipu3fb_puts,
.putm = ipu3fb_putm,
};
VIDEO_DRIVER(ipu3fb, ipu3fbvidsw, ipu3fb_configure);
extern sc_rndr_sw_t txtrndrsw;
RENDERER(ipu3fb, 0, txtrndrsw, gfb_set);
RENDERER_MODULE(ipu3fb, gfb_set);
static uint16_t ipu3fb_static_window[ROW*COL];
extern u_char dflt_font_16[];
static int
ipu3fb_configure(int flags)
{
struct video_adapter_softc *sc;
sc = &va_softc;
if (sc->initialized)
return 0;
sc->width = 640;
sc->height = 480;
sc->bpp = 2;
sc->stride = sc->width * sc->bpp;
ipu3fb_init(0, &sc->va, 0);
sc->initialized = 1;
return (0);
}
static int
ipu3fb_probe(int unit, video_adapter_t **adp, void *arg, int flags)
{
return (0);
}
static int
ipu3fb_init(int unit, video_adapter_t *adp, int flags)
{
struct video_adapter_softc *sc;
video_info_t *vi;
sc = (struct video_adapter_softc *)adp;
vi = &adp->va_info;
vid_init_struct(adp, "ipu3fb", -1, unit);
sc->font = dflt_font_16;
vi->vi_cheight = IPU3FB_FONT_HEIGHT;
vi->vi_cwidth = 8;
vi->vi_width = sc->width/8;
vi->vi_height = sc->height/vi->vi_cheight;
/*
* Clamp width/height to syscons maximums
*/
if (vi->vi_width > COL)
vi->vi_width = COL;
if (vi->vi_height > ROW)
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;
adp->va_window = (vm_offset_t) ipu3fb_static_window;
adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */;
adp->va_line_width = sc->stride;
adp->va_buffer_size = sc->fb_size;
vid_register(&sc->va);
return (0);
}
static int
ipu3fb_get_info(video_adapter_t *adp, int mode, video_info_t *info)
{
bcopy(&adp->va_info, info, sizeof(*info));
return (0);
}
static int
ipu3fb_query_mode(video_adapter_t *adp, video_info_t *info)
{
return (0);
}
static int
ipu3fb_set_mode(video_adapter_t *adp, int mode)
{
return (0);
}
static int
ipu3fb_save_font(video_adapter_t *adp, int page, int size, int width,
u_char *data, int c, int count)
{
return (0);
}
static int
ipu3fb_load_font(video_adapter_t *adp, int page, int size, int width,
u_char *data, int c, int count)
{
struct video_adapter_softc *sc;
sc = (struct video_adapter_softc *)adp;
sc->font = data;
return (0);
}
static int
ipu3fb_show_font(video_adapter_t *adp, int page)
{
return (0);
}
static int
ipu3fb_save_palette(video_adapter_t *adp, u_char *palette)
{
return (0);
}
static int
ipu3fb_load_palette(video_adapter_t *adp, u_char *palette)
{
return (0);
}
static int
ipu3fb_set_border(video_adapter_t *adp, int border)
{
return (ipu3fb_blank_display(adp, border));
}
static int
ipu3fb_save_state(video_adapter_t *adp, void *p, size_t size)
{
return (0);
}
static int
ipu3fb_load_state(video_adapter_t *adp, void *p)
{
return (0);
}
static int
ipu3fb_set_win_org(video_adapter_t *adp, off_t offset)
{
return (0);
}
static int
ipu3fb_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
{
*col = *row = 0;
return (0);
}
static int
ipu3fb_set_hw_cursor(video_adapter_t *adp, int col, int row)
{
return (0);
}
static int
ipu3fb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
int celsize, int blink)
{
return (0);
}
static int
ipu3fb_blank_display(video_adapter_t *adp, int mode)
{
return (0);
}
static int
ipu3fb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr,
int prot, vm_memattr_t *memattr)
{
struct video_adapter_softc *sc;
sc = (struct video_adapter_softc *)adp;
/*
* This might be a legacy VGA mem request: if so, just point it at the
* framebuffer, since it shouldn't be touched
*/
if (offset < sc->stride * sc->height) {
*paddr = sc->fb_paddr + offset;
return (0);
}
return (EINVAL);
}
static int
ipu3fb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data)
{
struct video_adapter_softc *sc;
struct fbtype *fb;
sc = (struct video_adapter_softc *)adp;
switch (cmd) {
case FBIOGTYPE:
fb = (struct fbtype *)data;
fb->fb_type = FBTYPE_PCIMISC;
fb->fb_height = sc->height;
fb->fb_width = sc->width;
fb->fb_depth = sc->depth;
if (sc->depth <= 1 || sc->depth > 8)
fb->fb_cmsize = 0;
else
fb->fb_cmsize = 1 << sc->depth;
fb->fb_size = sc->fb_size;
break;
case FBIOSCURSOR:
return (ENODEV);
default:
return (fb_commonioctl(adp, cmd, data));
}
return (0);
}
static int
ipu3fb_clear(video_adapter_t *adp)
{
return (ipu3fb_blank_display(adp, 0));
}
static int
ipu3fb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
{
return (0);
}
static int
ipu3fb_bitblt(video_adapter_t *adp, ...)
{
return (0);
}
static int
ipu3fb_diag(video_adapter_t *adp, int level)
{
return (0);
}
static int
ipu3fb_save_cursor_palette(video_adapter_t *adp, u_char *palette)
{
return (0);
}
static int
ipu3fb_load_cursor_palette(video_adapter_t *adp, u_char *palette)
{
return (0);
}
static int
ipu3fb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n)
{
return (0);
}
static int
ipu3fb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a,
int size, int bpp, int bit_ltor, int byte_ltor)
{
return (0);
}
static int
ipu3fb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
{
struct video_adapter_softc *sc;
int col, row, bpp;
int b, i, j, k;
uint8_t *addr;
u_char *p;
uint32_t fg, bg, color;
sc = (struct video_adapter_softc *)adp;
bpp = sc->bpp;
if (sc->fb_addr == 0)
return (0);
row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight;
col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth;
p = sc->font + c * IPU3FB_FONT_HEIGHT;
addr = (uint8_t *)sc->fb_addr
+ (row + sc->ymargin) * (sc->stride)
+ bpp * (col + sc->xmargin);
if (bpp == 2) {
bg = colors[(a >> 4) & 0x0f];
fg = colors[a & 0x0f];
} else if (bpp == 3) {
bg = colors_24[(a >> 4) & 0x0f];
fg = colors_24[a & 0x0f];
} else {
return (ENXIO);
}
for (i = 0; i < IPU3FB_FONT_HEIGHT; i++) {
for (j = 0, k = 7; j < 8; j++, k--) {
if ((p[i] & (1 << k)) == 0)
color = bg;
else
color = fg;
/* FIXME: BPP maybe different */
for (b = 0; b < bpp; b ++)
addr[bpp * j + b] =
(color >> (b << 3)) & 0xff;
}
addr += (sc->stride);
}
return (0);
}
static int
ipu3fb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len)
{
int i;
for (i = 0; i < len; i++)
ipu3fb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8);
return (0);
}
static int
ipu3fb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
uint32_t pixel_mask, int size, int width)
{
return (0);
}
/*
* Define a stub keyboard driver in case one hasn't been
* compiled into the kernel
*/
#include
#include
static int dummy_kbd_configure(int flags);
keyboard_switch_t ipu3dummysw;
static int
dummy_kbd_configure(int flags)
{
return (0);
}
KEYBOARD_DRIVER(ipu3dummy, ipu3dummysw, dummy_kbd_configure);
Index: stable/11/sys/arm/freescale/imx/imx51_ipuv3_fbd.c
===================================================================
--- stable/11/sys/arm/freescale/imx/imx51_ipuv3_fbd.c (revision 314502)
+++ stable/11/sys/arm/freescale/imx/imx51_ipuv3_fbd.c (revision 314503)
@@ -1,363 +1,363 @@
/*-
* Copyright (c) 2012 Oleksandr Tymoshenko
* Copyright (c) 2012, 2013 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by Oleksandr Rybalko
* under sponsorship from the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include
__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 "fb_if.h"
#define IMX51_IPU_HSP_CLOCK 665000000
struct ipu3sc_softc {
device_t dev;
device_t sc_fbd; /* fbd child */
struct fb_info sc_info;
bus_space_tag_t iot;
bus_space_handle_t ioh;
bus_space_handle_t cm_ioh;
bus_space_handle_t dp_ioh;
bus_space_handle_t di0_ioh;
bus_space_handle_t di1_ioh;
bus_space_handle_t dctmpl_ioh;
bus_space_handle_t dc_ioh;
bus_space_handle_t dmfc_ioh;
bus_space_handle_t idmac_ioh;
bus_space_handle_t cpmem_ioh;
};
static struct ipu3sc_softc *ipu3sc_softc;
#define IPUV3_READ(ipuv3, module, reg) \
bus_space_read_4((ipuv3)->iot, (ipuv3)->module##_ioh, (reg))
#define IPUV3_WRITE(ipuv3, module, reg, val) \
bus_space_write_4((ipuv3)->iot, (ipuv3)->module##_ioh, (reg), (val))
#define CPMEM_CHANNEL_OFFSET(_c) ((_c) * 0x40)
#define CPMEM_WORD_OFFSET(_w) ((_w) * 0x20)
#define CPMEM_DP_OFFSET(_d) ((_d) * 0x10000)
#define IMX_IPU_DP0 0
#define IMX_IPU_DP1 1
#define CPMEM_CHANNEL(_dp, _ch, _w) \
(CPMEM_DP_OFFSET(_dp) + CPMEM_CHANNEL_OFFSET(_ch) + \
CPMEM_WORD_OFFSET(_w))
#define CPMEM_OFFSET(_dp, _ch, _w, _o) \
(CPMEM_CHANNEL((_dp), (_ch), (_w)) + (_o))
static int ipu3_fb_probe(device_t);
static int ipu3_fb_attach(device_t);
static void
ipu3_fb_init(struct ipu3sc_softc *sc)
{
uint64_t w0sh96;
uint32_t w1sh96;
/* FW W0[137:125] - 96 = [41:29] */
/* FH W0[149:138] - 96 = [53:42] */
w0sh96 = IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 0, 16));
w0sh96 <<= 32;
w0sh96 |= IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 0, 12));
sc->sc_info.fb_width = ((w0sh96 >> 29) & 0x1fff) + 1;
sc->sc_info.fb_height = ((w0sh96 >> 42) & 0x0fff) + 1;
/* SLY W1[115:102] - 96 = [19:6] */
w1sh96 = IPUV3_READ(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 12));
sc->sc_info.fb_stride = ((w1sh96 >> 6) & 0x3fff) + 1;
printf("%dx%d [%d]\n", sc->sc_info.fb_width, sc->sc_info.fb_height,
sc->sc_info.fb_stride);
sc->sc_info.fb_size = sc->sc_info.fb_height * sc->sc_info.fb_stride;
sc->sc_info.fb_vbase = (intptr_t)contigmalloc(sc->sc_info.fb_size,
M_DEVBUF, M_ZERO, 0, ~0, PAGE_SIZE, 0);
sc->sc_info.fb_pbase = (intptr_t)vtophys(sc->sc_info.fb_vbase);
/* DP1 + config_ch_23 + word_2 */
IPUV3_WRITE(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 0),
(((uint32_t)sc->sc_info.fb_pbase >> 3) |
(((uint32_t)sc->sc_info.fb_pbase >> 3) << 29)) & 0xffffffff);
IPUV3_WRITE(sc, cpmem, CPMEM_OFFSET(IMX_IPU_DP1, 23, 1, 4),
(((uint32_t)sc->sc_info.fb_pbase >> 3) >> 3) & 0xffffffff);
/* XXX: fetch or set it from/to IPU. */
sc->sc_info.fb_bpp = sc->sc_info.fb_depth = sc->sc_info.fb_stride /
sc->sc_info.fb_width * 8;
}
/* Use own color map, because of different RGB offset. */
static int
ipu3_fb_init_cmap(uint32_t *cmap, int bytespp)
{
switch (bytespp) {
case 8:
return (vt_generate_cons_palette(cmap, COLOR_FORMAT_RGB,
0x7, 5, 0x7, 2, 0x3, 0));
case 15:
return (vt_generate_cons_palette(cmap, COLOR_FORMAT_RGB,
0x1f, 10, 0x1f, 5, 0x1f, 0));
case 16:
return (vt_generate_cons_palette(cmap, COLOR_FORMAT_RGB,
0x1f, 11, 0x3f, 5, 0x1f, 0));
case 24:
case 32: /* Ignore alpha. */
return (vt_generate_cons_palette(cmap, COLOR_FORMAT_RGB,
0xff, 0, 0xff, 8, 0xff, 16));
default:
return (1);
}
}
static int
ipu3_fb_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "fsl,ipu3"))
return (ENXIO);
device_set_desc(dev, "i.MX5x Image Processing Unit v3 (FB)");
return (BUS_PROBE_DEFAULT);
}
static int
ipu3_fb_attach(device_t dev)
{
struct ipu3sc_softc *sc = device_get_softc(dev);
bus_space_tag_t iot;
bus_space_handle_t ioh;
phandle_t node;
pcell_t reg;
int err;
uintptr_t base;
ipu3sc_softc = sc;
if (bootverbose)
device_printf(dev, "clock gate status is %d\n",
imx51_get_clk_gating(IMX51CLK_IPU_HSP_CLK_ROOT));
sc->dev = dev;
sc = device_get_softc(dev);
sc->iot = iot = fdtbus_bs_tag;
/*
* Retrieve the device address based on the start address in the
* DTS. The DTS for i.MX51 specifies 0x5e000000 as the first register
* address, so we just subtract IPU_CM_BASE to get the offset at which
* the IPU device was memory mapped.
* On i.MX53, the offset is 0.
*/
node = ofw_bus_get_node(dev);
- if ((OF_getprop(node, "reg", ®, sizeof(reg))) <= 0)
+ if ((OF_getencprop(node, "reg", ®, sizeof(reg))) <= 0)
base = 0;
else
- base = fdt32_to_cpu(reg) - IPU_CM_BASE(0);
+ base = reg - IPU_CM_BASE(0);
/* map controller registers */
err = bus_space_map(iot, IPU_CM_BASE(base), IPU_CM_SIZE, 0, &ioh);
if (err)
goto fail_retarn_cm;
sc->cm_ioh = ioh;
/* map Display Multi FIFO Controller registers */
err = bus_space_map(iot, IPU_DMFC_BASE(base), IPU_DMFC_SIZE, 0, &ioh);
if (err)
goto fail_retarn_dmfc;
sc->dmfc_ioh = ioh;
/* map Display Interface 0 registers */
err = bus_space_map(iot, IPU_DI0_BASE(base), IPU_DI0_SIZE, 0, &ioh);
if (err)
goto fail_retarn_di0;
sc->di0_ioh = ioh;
/* map Display Interface 1 registers */
err = bus_space_map(iot, IPU_DI1_BASE(base), IPU_DI0_SIZE, 0, &ioh);
if (err)
goto fail_retarn_di1;
sc->di1_ioh = ioh;
/* map Display Processor registers */
err = bus_space_map(iot, IPU_DP_BASE(base), IPU_DP_SIZE, 0, &ioh);
if (err)
goto fail_retarn_dp;
sc->dp_ioh = ioh;
/* map Display Controller registers */
err = bus_space_map(iot, IPU_DC_BASE(base), IPU_DC_SIZE, 0, &ioh);
if (err)
goto fail_retarn_dc;
sc->dc_ioh = ioh;
/* map Image DMA Controller registers */
err = bus_space_map(iot, IPU_IDMAC_BASE(base), IPU_IDMAC_SIZE, 0,
&ioh);
if (err)
goto fail_retarn_idmac;
sc->idmac_ioh = ioh;
/* map CPMEM registers */
err = bus_space_map(iot, IPU_CPMEM_BASE(base), IPU_CPMEM_SIZE, 0,
&ioh);
if (err)
goto fail_retarn_cpmem;
sc->cpmem_ioh = ioh;
/* map DCTEMPL registers */
err = bus_space_map(iot, IPU_DCTMPL_BASE(base), IPU_DCTMPL_SIZE, 0,
&ioh);
if (err)
goto fail_retarn_dctmpl;
sc->dctmpl_ioh = ioh;
#ifdef notyet
sc->ih = imx51_ipuv3_intr_establish(IMX51_INT_IPUV3, IPL_BIO,
ipuv3intr, sc);
if (sc->ih == NULL) {
device_printf(sc->dev,
"unable to establish interrupt at irq %d\n",
IMX51_INT_IPUV3);
return (ENXIO);
}
#endif
/*
* We have to wait until interrupts are enabled.
* Mailbox relies on it to get data from VideoCore
*/
ipu3_fb_init(sc);
sc->sc_info.fb_name = device_get_nameunit(dev);
ipu3_fb_init_cmap(sc->sc_info.fb_cmap, sc->sc_info.fb_depth);
sc->sc_info.fb_cmsize = 16;
/* Ask newbus to attach framebuffer device to me. */
sc->sc_fbd = device_add_child(dev, "fbd", device_get_unit(dev));
if (sc->sc_fbd == NULL)
device_printf(dev, "Can't attach fbd device\n");
return (bus_generic_attach(dev));
fail_retarn_dctmpl:
bus_space_unmap(sc->iot, sc->cpmem_ioh, IPU_CPMEM_SIZE);
fail_retarn_cpmem:
bus_space_unmap(sc->iot, sc->idmac_ioh, IPU_IDMAC_SIZE);
fail_retarn_idmac:
bus_space_unmap(sc->iot, sc->dc_ioh, IPU_DC_SIZE);
fail_retarn_dp:
bus_space_unmap(sc->iot, sc->dp_ioh, IPU_DP_SIZE);
fail_retarn_dc:
bus_space_unmap(sc->iot, sc->di1_ioh, IPU_DI1_SIZE);
fail_retarn_di1:
bus_space_unmap(sc->iot, sc->di0_ioh, IPU_DI0_SIZE);
fail_retarn_di0:
bus_space_unmap(sc->iot, sc->dmfc_ioh, IPU_DMFC_SIZE);
fail_retarn_dmfc:
bus_space_unmap(sc->iot, sc->dc_ioh, IPU_CM_SIZE);
fail_retarn_cm:
device_printf(sc->dev,
"failed to map registers (errno=%d)\n", err);
return (err);
}
static struct fb_info *
ipu3_fb_getinfo(device_t dev)
{
struct ipu3sc_softc *sc = device_get_softc(dev);
return (&sc->sc_info);
}
static device_method_t ipu3_fb_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ipu3_fb_probe),
DEVMETHOD(device_attach, ipu3_fb_attach),
/* Framebuffer service methods */
DEVMETHOD(fb_getinfo, ipu3_fb_getinfo),
{ 0, 0 }
};
static devclass_t ipu3_fb_devclass;
static driver_t ipu3_fb_driver = {
"fb",
ipu3_fb_methods,
sizeof(struct ipu3sc_softc),
};
DRIVER_MODULE(fb, simplebus, ipu3_fb_driver, ipu3_fb_devclass, 0, 0);
Index: stable/11/sys/arm/freescale/imx/imx6_ssi.c
===================================================================
--- stable/11/sys/arm/freescale/imx/imx6_ssi.c (revision 314502)
+++ stable/11/sys/arm/freescale/imx/imx6_ssi.c (revision 314503)
@@ -1,854 +1,854 @@
/*-
* Copyright (c) 2015 Ruslan Bukin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* i.MX6 Synchronous Serial Interface (SSI)
*
* Chapter 61, i.MX 6Dual/6Quad Applications Processor Reference Manual,
* Rev. 1, 04/2013
*/
#include
__FBSDID("$FreeBSD$");
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define READ4(_sc, _reg) \
bus_space_read_4(_sc->bst, _sc->bsh, _reg)
#define WRITE4(_sc, _reg, _val) \
bus_space_write_4(_sc->bst, _sc->bsh, _reg, _val)
#define SSI_NCHANNELS 1
/* i.MX6 SSI registers */
#define SSI_STX0 0x00 /* Transmit Data Register n */
#define SSI_STX1 0x04 /* Transmit Data Register n */
#define SSI_SRX0 0x08 /* Receive Data Register n */
#define SSI_SRX1 0x0C /* Receive Data Register n */
#define SSI_SCR 0x10 /* Control Register */
#define SCR_I2S_MODE_S 5 /* I2S Mode Select. */
#define SCR_I2S_MODE_M 0x3
#define SCR_SYN (1 << 4)
#define SCR_NET (1 << 3) /* Network mode */
#define SCR_RE (1 << 2) /* Receive Enable. */
#define SCR_TE (1 << 1) /* Transmit Enable. */
#define SCR_SSIEN (1 << 0) /* SSI Enable */
#define SSI_SISR 0x14 /* Interrupt Status Register */
#define SSI_SIER 0x18 /* Interrupt Enable Register */
#define SIER_RDMAE (1 << 22) /* Receive DMA Enable. */
#define SIER_RIE (1 << 21) /* Receive Interrupt Enable. */
#define SIER_TDMAE (1 << 20) /* Transmit DMA Enable. */
#define SIER_TIE (1 << 19) /* Transmit Interrupt Enable. */
#define SIER_TDE0IE (1 << 12) /* Transmit Data Register Empty 0. */
#define SIER_TUE0IE (1 << 8) /* Transmitter Underrun Error 0. */
#define SIER_TFE0IE (1 << 0) /* Transmit FIFO Empty 0 IE. */
#define SSI_STCR 0x1C /* Transmit Configuration Register */
#define STCR_TXBIT0 (1 << 9) /* Transmit Bit 0 shift MSB/LSB */
#define STCR_TFEN1 (1 << 8) /* Transmit FIFO Enable 1. */
#define STCR_TFEN0 (1 << 7) /* Transmit FIFO Enable 0. */
#define STCR_TFDIR (1 << 6) /* Transmit Frame Direction. */
#define STCR_TXDIR (1 << 5) /* Transmit Clock Direction. */
#define STCR_TSHFD (1 << 4) /* Transmit Shift Direction. */
#define STCR_TSCKP (1 << 3) /* Transmit Clock Polarity. */
#define STCR_TFSI (1 << 2) /* Transmit Frame Sync Invert. */
#define STCR_TFSL (1 << 1) /* Transmit Frame Sync Length. */
#define STCR_TEFS (1 << 0) /* Transmit Early Frame Sync. */
#define SSI_SRCR 0x20 /* Receive Configuration Register */
#define SSI_STCCR 0x24 /* Transmit Clock Control Register */
#define STCCR_DIV2 (1 << 18) /* Divide By 2. */
#define STCCR_PSR (1 << 17) /* Divide clock by 8. */
#define WL3_WL0_S 13
#define WL3_WL0_M 0xf
#define DC4_DC0_S 8
#define DC4_DC0_M 0x1f
#define PM7_PM0_S 0
#define PM7_PM0_M 0xff
#define SSI_SRCCR 0x28 /* Receive Clock Control Register */
#define SSI_SFCSR 0x2C /* FIFO Control/Status Register */
#define SFCSR_RFWM1_S 20 /* Receive FIFO Empty WaterMark 1 */
#define SFCSR_RFWM1_M 0xf
#define SFCSR_TFWM1_S 16 /* Transmit FIFO Empty WaterMark 1 */
#define SFCSR_TFWM1_M 0xf
#define SFCSR_RFWM0_S 4 /* Receive FIFO Empty WaterMark 0 */
#define SFCSR_RFWM0_M 0xf
#define SFCSR_TFWM0_S 0 /* Transmit FIFO Empty WaterMark 0 */
#define SFCSR_TFWM0_M 0xf
#define SSI_SACNT 0x38 /* AC97 Control Register */
#define SSI_SACADD 0x3C /* AC97 Command Address Register */
#define SSI_SACDAT 0x40 /* AC97 Command Data Register */
#define SSI_SATAG 0x44 /* AC97 Tag Register */
#define SSI_STMSK 0x48 /* Transmit Time Slot Mask Register */
#define SSI_SRMSK 0x4C /* Receive Time Slot Mask Register */
#define SSI_SACCST 0x50 /* AC97 Channel Status Register */
#define SSI_SACCEN 0x54 /* AC97 Channel Enable Register */
#define SSI_SACCDIS 0x58 /* AC97 Channel Disable Register */
static MALLOC_DEFINE(M_SSI, "ssi", "ssi audio");
uint32_t ssi_dma_intr(void *arg, int chn);
struct ssi_rate {
uint32_t speed;
uint32_t mfi; /* PLL4 Multiplication Factor Integer */
uint32_t mfn; /* PLL4 Multiplication Factor Numerator */
uint32_t mfd; /* PLL4 Multiplication Factor Denominator */
/* More dividers to configure can be added here */
};
static struct ssi_rate rate_map[] = {
{ 192000, 49, 152, 1000 }, /* PLL4 49.152 Mhz */
/* TODO: add more frequences */
{ 0, 0 },
};
/*
* i.MX6 example bit clock formula
*
* BCLK = 2 channels * 192000 hz * 24 bit = 9216000 hz =
* (24000000 * (49 + 152/1000.0) / 4 / 4 / 2 / 2 / 2 / 1 / 1)
* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
* | | | | | | | | | | |
* Fref ------/ | | | | | | | | | |
* PLL4 div select -/ | | | | | | | | |
* PLL4 num --------------/ | | | | | | | |
* PLL4 denom -------------------/ | | | | | | |
* PLL4 post div ---------------------/ | | | | | |
* CCM ssi pre div (CCM_CS1CDR) ----------/ | | | | |
* CCM ssi post div (CCM_CS1CDR) -------------/ | | | |
* SSI PM7_PM0_S ---------------------------------/ | | |
* SSI Fixed divider ---------------------------------/ | |
* SSI DIV2 ----------------------------------------------/ |
* SSI PSR (prescaler /1 or /8) ------------------------------/
*
* MCLK (Master clock) depends on DAC, usually BCLK * 4
*/
struct sc_info {
struct resource *res[2];
bus_space_tag_t bst;
bus_space_handle_t bsh;
device_t dev;
struct mtx *lock;
void *ih;
int pos;
int dma_size;
bus_dma_tag_t dma_tag;
bus_dmamap_t dma_map;
bus_addr_t buf_base_phys;
uint32_t *buf_base;
struct sdma_conf *conf;
struct ssi_rate *sr;
struct sdma_softc *sdma_sc;
int sdma_ev_rx;
int sdma_ev_tx;
int sdma_channel;
};
/* Channel registers */
struct sc_chinfo {
struct snd_dbuf *buffer;
struct pcm_channel *channel;
struct sc_pcminfo *parent;
/* Channel information */
uint32_t dir;
uint32_t format;
/* Flags */
uint32_t run;
};
/* PCM device private data */
struct sc_pcminfo {
device_t dev;
uint32_t (*ih)(struct sc_pcminfo *scp);
uint32_t chnum;
struct sc_chinfo chan[SSI_NCHANNELS];
struct sc_info *sc;
};
static struct resource_spec ssi_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ SYS_RES_IRQ, 0, RF_ACTIVE },
{ -1, 0 }
};
static int setup_dma(struct sc_pcminfo *scp);
static void setup_ssi(struct sc_info *);
static void ssi_configure_clock(struct sc_info *);
/*
* Mixer interface.
*/
static int
ssimixer_init(struct snd_mixer *m)
{
struct sc_pcminfo *scp;
struct sc_info *sc;
int mask;
scp = mix_getdevinfo(m);
sc = scp->sc;
if (sc == NULL)
return -1;
mask = SOUND_MASK_PCM;
mask |= SOUND_MASK_VOLUME;
snd_mtxlock(sc->lock);
pcm_setflags(scp->dev, pcm_getflags(scp->dev) | SD_F_SOFTPCMVOL);
mix_setdevs(m, mask);
snd_mtxunlock(sc->lock);
return (0);
}
static int
ssimixer_set(struct snd_mixer *m, unsigned dev,
unsigned left, unsigned right)
{
struct sc_pcminfo *scp;
scp = mix_getdevinfo(m);
/* Here we can configure hardware volume on our DAC */
#if 1
device_printf(scp->dev, "ssimixer_set() %d %d\n",
left, right);
#endif
return (0);
}
static kobj_method_t ssimixer_methods[] = {
KOBJMETHOD(mixer_init, ssimixer_init),
KOBJMETHOD(mixer_set, ssimixer_set),
KOBJMETHOD_END
};
MIXER_DECLARE(ssimixer);
/*
* Channel interface.
*/
static void *
ssichan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
struct pcm_channel *c, int dir)
{
struct sc_pcminfo *scp;
struct sc_chinfo *ch;
struct sc_info *sc;
scp = (struct sc_pcminfo *)devinfo;
sc = scp->sc;
snd_mtxlock(sc->lock);
ch = &scp->chan[0];
ch->dir = dir;
ch->run = 0;
ch->buffer = b;
ch->channel = c;
ch->parent = scp;
snd_mtxunlock(sc->lock);
if (sndbuf_setup(ch->buffer, sc->buf_base, sc->dma_size) != 0) {
device_printf(scp->dev, "Can't setup sndbuf.\n");
return NULL;
}
return ch;
}
static int
ssichan_free(kobj_t obj, void *data)
{
struct sc_chinfo *ch = data;
struct sc_pcminfo *scp = ch->parent;
struct sc_info *sc = scp->sc;
#if 0
device_printf(scp->dev, "ssichan_free()\n");
#endif
snd_mtxlock(sc->lock);
/* TODO: free channel buffer */
snd_mtxunlock(sc->lock);
return (0);
}
static int
ssichan_setformat(kobj_t obj, void *data, uint32_t format)
{
struct sc_chinfo *ch = data;
ch->format = format;
return (0);
}
static uint32_t
ssichan_setspeed(kobj_t obj, void *data, uint32_t speed)
{
struct sc_pcminfo *scp;
struct sc_chinfo *ch;
struct ssi_rate *sr;
struct sc_info *sc;
int threshold;
int i;
ch = data;
scp = ch->parent;
sc = scp->sc;
sr = NULL;
/* First look for equal frequency. */
for (i = 0; rate_map[i].speed != 0; i++) {
if (rate_map[i].speed == speed)
sr = &rate_map[i];
}
/* If no match, just find nearest. */
if (sr == NULL) {
for (i = 0; rate_map[i].speed != 0; i++) {
sr = &rate_map[i];
threshold = sr->speed + ((rate_map[i + 1].speed != 0) ?
((rate_map[i + 1].speed - sr->speed) >> 1) : 0);
if (speed < threshold)
break;
}
}
sc->sr = sr;
ssi_configure_clock(sc);
return (sr->speed);
}
static void
ssi_configure_clock(struct sc_info *sc)
{
struct ssi_rate *sr;
sr = sc->sr;
pll4_configure_output(sr->mfi, sr->mfn, sr->mfd);
/* Configure other dividers here, if any */
}
static uint32_t
ssichan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
{
struct sc_chinfo *ch = data;
struct sc_pcminfo *scp = ch->parent;
struct sc_info *sc = scp->sc;
sndbuf_resize(ch->buffer, sc->dma_size / blocksize, blocksize);
setup_dma(scp);
return (sndbuf_getblksz(ch->buffer));
}
uint32_t
ssi_dma_intr(void *arg, int chn)
{
struct sc_pcminfo *scp;
struct sdma_conf *conf;
struct sc_chinfo *ch;
struct sc_info *sc;
int bufsize;
scp = arg;
ch = &scp->chan[0];
sc = scp->sc;
conf = sc->conf;
bufsize = sndbuf_getsize(ch->buffer);
sc->pos += conf->period;
if (sc->pos >= bufsize)
sc->pos -= bufsize;
if (ch->run)
chn_intr(ch->channel);
return (0);
}
static int
find_sdma_controller(struct sc_info *sc)
{
struct sdma_softc *sdma_sc;
phandle_t node, sdma_node;
device_t sdma_dev;
int dts_value[8];
int len;
if ((node = ofw_bus_get_node(sc->dev)) == -1)
return (ENXIO);
if ((len = OF_getproplen(node, "dmas")) <= 0)
return (ENXIO);
- OF_getprop(node, "dmas", &dts_value, len);
+ OF_getencprop(node, "dmas", &dts_value, len);
- sc->sdma_ev_rx = fdt32_to_cpu(dts_value[1]);
- sc->sdma_ev_tx = fdt32_to_cpu(dts_value[5]);
+ sc->sdma_ev_rx = dts_value[1];
+ sc->sdma_ev_tx = dts_value[5];
- sdma_node = OF_node_from_xref(fdt32_to_cpu(dts_value[0]));
+ sdma_node = OF_node_from_xref(dts_value[0]);
sdma_sc = NULL;
sdma_dev = devclass_get_device(devclass_find("sdma"), 0);
if (sdma_dev)
sdma_sc = device_get_softc(sdma_dev);
if (sdma_sc == NULL) {
device_printf(sc->dev, "No sDMA found. Can't operate\n");
return (ENXIO);
}
sc->sdma_sc = sdma_sc;
return (0);
};
static int
setup_dma(struct sc_pcminfo *scp)
{
struct sdma_conf *conf;
struct sc_chinfo *ch;
struct sc_info *sc;
int fmt;
ch = &scp->chan[0];
sc = scp->sc;
conf = sc->conf;
conf->ih = ssi_dma_intr;
conf->ih_user = scp;
conf->saddr = sc->buf_base_phys;
conf->daddr = rman_get_start(sc->res[0]) + SSI_STX0;
conf->event = sc->sdma_ev_tx; /* SDMA TX event */
conf->period = sndbuf_getblksz(ch->buffer);
conf->num_bd = sndbuf_getblkcnt(ch->buffer);
/*
* Word Length
* Can be 32, 24, 16 or 8 for sDMA.
*
* SSI supports 24 at max.
*/
fmt = sndbuf_getfmt(ch->buffer);
if (fmt & AFMT_16BIT) {
conf->word_length = 16;
conf->command = CMD_2BYTES;
} else if (fmt & AFMT_24BIT) {
conf->word_length = 24;
conf->command = CMD_3BYTES;
} else {
device_printf(sc->dev, "Unknown format\n");
return (-1);
}
return (0);
}
static int
ssi_start(struct sc_pcminfo *scp)
{
struct sc_info *sc;
int reg;
sc = scp->sc;
if (sdma_configure(sc->sdma_channel, sc->conf) != 0) {
device_printf(sc->dev, "Can't configure sDMA\n");
return (-1);
}
/* Enable DMA interrupt */
reg = (SIER_TDMAE);
WRITE4(sc, SSI_SIER, reg);
sdma_start(sc->sdma_channel);
return (0);
}
static int
ssi_stop(struct sc_pcminfo *scp)
{
struct sc_info *sc;
int reg;
sc = scp->sc;
reg = READ4(sc, SSI_SIER);
reg &= ~(SIER_TDMAE);
WRITE4(sc, SSI_SIER, reg);
sdma_stop(sc->sdma_channel);
bzero(sc->buf_base, sc->dma_size);
return (0);
}
static int
ssichan_trigger(kobj_t obj, void *data, int go)
{
struct sc_pcminfo *scp;
struct sc_chinfo *ch;
struct sc_info *sc;
ch = data;
scp = ch->parent;
sc = scp->sc;
snd_mtxlock(sc->lock);
switch (go) {
case PCMTRIG_START:
#if 0
device_printf(scp->dev, "trigger start\n");
#endif
ch->run = 1;
ssi_start(scp);
break;
case PCMTRIG_STOP:
case PCMTRIG_ABORT:
#if 0
device_printf(scp->dev, "trigger stop or abort\n");
#endif
ch->run = 0;
ssi_stop(scp);
break;
}
snd_mtxunlock(sc->lock);
return (0);
}
static uint32_t
ssichan_getptr(kobj_t obj, void *data)
{
struct sc_pcminfo *scp;
struct sc_chinfo *ch;
struct sc_info *sc;
ch = data;
scp = ch->parent;
sc = scp->sc;
return (sc->pos);
}
static uint32_t ssi_pfmt[] = {
SND_FORMAT(AFMT_S24_LE, 2, 0),
0
};
static struct pcmchan_caps ssi_pcaps = {44100, 192000, ssi_pfmt, 0};
static struct pcmchan_caps *
ssichan_getcaps(kobj_t obj, void *data)
{
return (&ssi_pcaps);
}
static kobj_method_t ssichan_methods[] = {
KOBJMETHOD(channel_init, ssichan_init),
KOBJMETHOD(channel_free, ssichan_free),
KOBJMETHOD(channel_setformat, ssichan_setformat),
KOBJMETHOD(channel_setspeed, ssichan_setspeed),
KOBJMETHOD(channel_setblocksize, ssichan_setblocksize),
KOBJMETHOD(channel_trigger, ssichan_trigger),
KOBJMETHOD(channel_getptr, ssichan_getptr),
KOBJMETHOD(channel_getcaps, ssichan_getcaps),
KOBJMETHOD_END
};
CHANNEL_DECLARE(ssichan);
static int
ssi_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "fsl,imx6q-ssi"))
return (ENXIO);
device_set_desc(dev, "i.MX6 Synchronous Serial Interface (SSI)");
return (BUS_PROBE_DEFAULT);
}
static void
ssi_intr(void *arg)
{
struct sc_pcminfo *scp;
struct sc_chinfo *ch;
struct sc_info *sc;
scp = arg;
sc = scp->sc;
ch = &scp->chan[0];
/* We don't use SSI interrupt */
#if 0
device_printf(sc->dev, "SSI Intr 0x%08x\n",
READ4(sc, SSI_SISR));
#endif
}
static void
setup_ssi(struct sc_info *sc)
{
int reg;
reg = READ4(sc, SSI_STCCR);
reg &= ~(WL3_WL0_M << WL3_WL0_S);
reg |= (0xb << WL3_WL0_S); /* 24 bit */
reg &= ~(DC4_DC0_M << DC4_DC0_S);
reg |= (1 << DC4_DC0_S); /* 2 words per frame */
reg &= ~(STCCR_DIV2); /* Divide by 1 */
reg &= ~(STCCR_PSR); /* Divide by 1 */
reg &= ~(PM7_PM0_M << PM7_PM0_S);
reg |= (1 << PM7_PM0_S); /* Divide by 2 */
WRITE4(sc, SSI_STCCR, reg);
reg = READ4(sc, SSI_SFCSR);
reg &= ~(SFCSR_TFWM0_M << SFCSR_TFWM0_S);
reg |= (8 << SFCSR_TFWM0_S); /* empty slots */
WRITE4(sc, SSI_SFCSR, reg);
reg = READ4(sc, SSI_STCR);
reg |= (STCR_TFEN0);
reg &= ~(STCR_TFEN1);
reg &= ~(STCR_TSHFD); /* MSB */
reg |= (STCR_TXBIT0);
reg |= (STCR_TXDIR | STCR_TFDIR);
reg |= (STCR_TSCKP); /* falling edge */
reg |= (STCR_TFSI);
reg &= ~(STCR_TFSI); /* active high frame sync */
reg &= ~(STCR_TFSL);
reg |= STCR_TEFS;
WRITE4(sc, SSI_STCR, reg);
reg = READ4(sc, SSI_SCR);
reg &= ~(SCR_I2S_MODE_M << SCR_I2S_MODE_S); /* Not master */
reg |= (SCR_SSIEN | SCR_TE);
reg |= (SCR_NET);
reg |= (SCR_SYN);
WRITE4(sc, SSI_SCR, reg);
}
static void
ssi_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 = segs[0].ds_addr;
}
static int
ssi_attach(device_t dev)
{
char status[SND_STATUSLEN];
struct sc_pcminfo *scp;
struct sc_info *sc;
int err;
sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
sc->dev = dev;
sc->sr = &rate_map[0];
sc->pos = 0;
sc->conf = malloc(sizeof(struct sdma_conf), M_DEVBUF, M_WAITOK | M_ZERO);
sc->lock = snd_mtxcreate(device_get_nameunit(dev), "ssi softc");
if (sc->lock == NULL) {
device_printf(dev, "Can't create mtx\n");
return (ENXIO);
}
if (bus_alloc_resources(dev, ssi_spec, sc->res)) {
device_printf(dev, "could not allocate resources\n");
return (ENXIO);
}
/* Memory interface */
sc->bst = rman_get_bustag(sc->res[0]);
sc->bsh = rman_get_bushandle(sc->res[0]);
/* SDMA */
if (find_sdma_controller(sc)) {
device_printf(dev, "could not find active SDMA\n");
return (ENXIO);
}
/* Setup PCM */
scp = malloc(sizeof(struct sc_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
scp->sc = sc;
scp->dev = dev;
/*
* Maximum possible DMA buffer.
* Will be used partially to match 24 bit word.
*/
sc->dma_size = 131072;
/*
* Must use dma_size boundary as modulo feature required.
* Modulo feature allows setup circular buffer.
*/
err = bus_dma_tag_create(
bus_get_dma_tag(sc->dev),
4, sc->dma_size, /* alignment, boundary */
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
sc->dma_size, 1, /* maxsize, nsegments */
sc->dma_size, 0, /* maxsegsize, flags */
NULL, NULL, /* lockfunc, lockarg */
&sc->dma_tag);
err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->buf_base,
BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &sc->dma_map);
if (err) {
device_printf(dev, "cannot allocate framebuffer\n");
return (ENXIO);
}
err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->buf_base,
sc->dma_size, ssi_dmamap_cb, &sc->buf_base_phys, BUS_DMA_NOWAIT);
if (err) {
device_printf(dev, "cannot load DMA map\n");
return (ENXIO);
}
bzero(sc->buf_base, sc->dma_size);
/* Setup interrupt handler */
err = bus_setup_intr(dev, sc->res[1], INTR_MPSAFE | INTR_TYPE_AV,
NULL, ssi_intr, scp, &sc->ih);
if (err) {
device_printf(dev, "Unable to alloc interrupt resource.\n");
return (ENXIO);
}
pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE);
err = pcm_register(dev, scp, 1, 0);
if (err) {
device_printf(dev, "Can't register pcm.\n");
return (ENXIO);
}
scp->chnum = 0;
pcm_addchan(dev, PCMDIR_PLAY, &ssichan_class, scp);
scp->chnum++;
snprintf(status, SND_STATUSLEN, "at simplebus");
pcm_setstatus(dev, status);
mixer_init(dev, &ssimixer_class, scp);
setup_ssi(sc);
imx_ccm_ssi_configure(dev);
sc->sdma_channel = sdma_alloc();
if (sc->sdma_channel < 0) {
device_printf(sc->dev, "Can't get sDMA channel\n");
return (1);
}
return (0);
}
static device_method_t ssi_pcm_methods[] = {
DEVMETHOD(device_probe, ssi_probe),
DEVMETHOD(device_attach, ssi_attach),
{ 0, 0 }
};
static driver_t ssi_pcm_driver = {
"pcm",
ssi_pcm_methods,
PCM_SOFTC_SIZE,
};
DRIVER_MODULE(ssi, simplebus, ssi_pcm_driver, pcm_devclass, 0, 0);
MODULE_DEPEND(ssi, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
MODULE_VERSION(ssi, 1);
Index: stable/11/sys/arm/freescale/vybrid/vf_common.c
===================================================================
--- stable/11/sys/arm/freescale/vybrid/vf_common.c (revision 314502)
+++ stable/11/sys/arm/freescale/vybrid/vf_common.c (revision 314503)
@@ -1,88 +1,86 @@
/*-
* Copyright (c) 2013 Ruslan Bukin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include
__FBSDID("$FreeBSD$");
#include
#include
#include
#include
-#include
#include
#include
#include
#include
void
cpu_reset(void)
{
phandle_t src;
- uint32_t addr, paddr;
+ uint32_t paddr;
bus_addr_t vaddr;
if (src_swreset() == 0)
goto end;
src = OF_finddevice("src");
- if ((src != 0) && (OF_getprop(src, "reg", &paddr, sizeof(paddr))) > 0) {
- addr = fdt32_to_cpu(paddr);
- if (bus_space_map(fdtbus_bs_tag, addr, 0x10, 0, &vaddr) == 0) {
+ if ((src != 0) && (OF_getencprop(src, "reg", &paddr, sizeof(paddr))) > 0) {
+ if (bus_space_map(fdtbus_bs_tag, paddr, 0x10, 0, &vaddr) == 0) {
bus_space_write_4(fdtbus_bs_tag, vaddr, 0x00, SW_RST);
}
}
end:
while (1);
}
struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
#ifndef INTRNG
static int
fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
int *pol)
{
if (!fdt_is_compatible(node, "arm,gic"))
return (ENXIO);
*interrupt = fdt32_to_cpu(intr[0]);
*trig = INTR_TRIGGER_CONFORM;
*pol = INTR_POLARITY_CONFORM;
return (0);
}
fdt_pic_decode_t fdt_pic_table[] = {
&fdt_pic_decode_ic,
NULL
};
#endif
Index: stable/11/sys/arm/freescale/vybrid/vf_dcu4.c
===================================================================
--- stable/11/sys/arm/freescale/vybrid/vf_dcu4.c (revision 314502)
+++ stable/11/sys/arm/freescale/vybrid/vf_dcu4.c (revision 314503)
@@ -1,470 +1,469 @@
/*-
* Copyright (c) 2014 Ruslan Bukin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Vybrid Family Display Control Unit (DCU4)
* Chapter 55, Vybrid Reference Manual, Rev. 5, 07/2013
*/
#include
__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 "gpio_if.h"
#include
#include
#include
#include
#include "fb_if.h"
#include
#define DCU_CTRLDESCCURSOR1 0x000 /* Control Descriptor Cursor 1 */
#define DCU_CTRLDESCCURSOR2 0x004 /* Control Descriptor Cursor 2 */
#define DCU_CTRLDESCCURSOR3 0x008 /* Control Descriptor Cursor 3 */
#define DCU_CTRLDESCCURSOR4 0x00C /* Control Descriptor Cursor 4 */
#define DCU_DCU_MODE 0x010 /* DCU4 Mode */
#define DCU_MODE_M 0x3
#define DCU_MODE_S 0
#define DCU_MODE_NORMAL 0x1
#define DCU_MODE_TEST 0x2
#define DCU_MODE_COLBAR 0x3
#define RASTER_EN (1 << 14) /* Raster scan of pixel data */
#define PDI_EN (1 << 13)
#define PDI_DE_MODE (1 << 11)
#define PDI_MODE_M 2
#define DCU_BGND 0x014 /* Background */
#define DCU_DISP_SIZE 0x018 /* Display Size */
#define DELTA_M 0x7ff
#define DELTA_Y_S 16
#define DELTA_X_S 0
#define DCU_HSYN_PARA 0x01C /* Horizontal Sync Parameter */
#define BP_H_SHIFT 22
#define PW_H_SHIFT 11
#define FP_H_SHIFT 0
#define DCU_VSYN_PARA 0x020 /* Vertical Sync Parameter */
#define BP_V_SHIFT 22
#define PW_V_SHIFT 11
#define FP_V_SHIFT 0
#define DCU_SYNPOL 0x024 /* Synchronize Polarity */
#define INV_HS (1 << 0)
#define INV_VS (1 << 1)
#define INV_PDI_VS (1 << 8) /* Polarity of PDI input VSYNC. */
#define INV_PDI_HS (1 << 9) /* Polarity of PDI input HSYNC. */
#define INV_PDI_DE (1 << 10) /* Polarity of PDI input DE. */
#define DCU_THRESHOLD 0x028 /* Threshold */
#define LS_BF_VS_SHIFT 16
#define OUT_BUF_HIGH_SHIFT 8
#define OUT_BUF_LOW_SHIFT 0
#define DCU_INT_STATUS 0x02C /* Interrupt Status */
#define DCU_INT_MASK 0x030 /* Interrupt Mask */
#define DCU_COLBAR_1 0x034 /* COLBAR_1 */
#define DCU_COLBAR_2 0x038 /* COLBAR_2 */
#define DCU_COLBAR_3 0x03C /* COLBAR_3 */
#define DCU_COLBAR_4 0x040 /* COLBAR_4 */
#define DCU_COLBAR_5 0x044 /* COLBAR_5 */
#define DCU_COLBAR_6 0x048 /* COLBAR_6 */
#define DCU_COLBAR_7 0x04C /* COLBAR_7 */
#define DCU_COLBAR_8 0x050 /* COLBAR_8 */
#define DCU_DIV_RATIO 0x054 /* Divide Ratio */
#define DCU_SIGN_CALC_1 0x058 /* Sign Calculation 1 */
#define DCU_SIGN_CALC_2 0x05C /* Sign Calculation 2 */
#define DCU_CRC_VAL 0x060 /* CRC Value */
#define DCU_PDI_STATUS 0x064 /* PDI Status */
#define DCU_PDI_STA_MSK 0x068 /* PDI Status Mask */
#define DCU_PARR_ERR_STATUS1 0x06C /* Parameter Error Status 1 */
#define DCU_PARR_ERR_STATUS2 0x070 /* Parameter Error Status 2 */
#define DCU_PARR_ERR_STATUS3 0x07C /* Parameter Error Status 3 */
#define DCU_MASK_PARR_ERR_ST1 0x080 /* Mask Parameter Error Status 1 */
#define DCU_MASK_PARR_ERR_ST2 0x084 /* Mask Parameter Error Status 2 */
#define DCU_MASK_PARR_ERR_ST3 0x090 /* Mask Parameter Error Status 3 */
#define DCU_THRESHOLD_INP_BUF_1 0x094 /* Threshold Input 1 */
#define DCU_THRESHOLD_INP_BUF_2 0x098 /* Threshold Input 2 */
#define DCU_THRESHOLD_INP_BUF_3 0x09C /* Threshold Input 3 */
#define DCU_LUMA_COMP 0x0A0 /* LUMA Component */
#define DCU_CHROMA_RED 0x0A4 /* Red Chroma Components */
#define DCU_CHROMA_GREEN 0x0A8 /* Green Chroma Components */
#define DCU_CHROMA_BLUE 0x0AC /* Blue Chroma Components */
#define DCU_CRC_POS 0x0B0 /* CRC Position */
#define DCU_LYR_INTPOL_EN 0x0B4 /* Layer Interpolation Enable */
#define DCU_LYR_LUMA_COMP 0x0B8 /* Layer Luminance Component */
#define DCU_LYR_CHRM_RED 0x0BC /* Layer Chroma Red */
#define DCU_LYR_CHRM_GRN 0x0C0 /* Layer Chroma Green */
#define DCU_LYR_CHRM_BLUE 0x0C4 /* Layer Chroma Blue */
#define DCU_COMP_IMSIZE 0x0C8 /* Compression Image Size */
#define DCU_UPDATE_MODE 0x0CC /* Update Mode */
#define READREG (1 << 30)
#define MODE (1 << 31)
#define DCU_UNDERRUN 0x0D0 /* Underrun */
#define DCU_GLBL_PROTECT 0x100 /* Global Protection */
#define DCU_SFT_LCK_BIT_L0 0x104 /* Soft Lock Bit Layer 0 */
#define DCU_SFT_LCK_BIT_L1 0x108 /* Soft Lock Bit Layer 1 */
#define DCU_SFT_LCK_DISP_SIZE 0x10C /* Soft Lock Display Size */
#define DCU_SFT_LCK_HS_VS_PARA 0x110 /* Soft Lock Hsync/Vsync Parameter */
#define DCU_SFT_LCK_POL 0x114 /* Soft Lock POL */
#define DCU_SFT_LCK_L0_TRANSP 0x118 /* Soft Lock L0 Transparency */
#define DCU_SFT_LCK_L1_TRANSP 0x11C /* Soft Lock L1 Transparency */
/* Control Descriptor */
#define DCU_CTRLDESCL(n, m) 0x200 + (0x40 * n) + 0x4 * (m - 1)
#define DCU_CTRLDESCLn_1(n) DCU_CTRLDESCL(n, 1)
#define DCU_CTRLDESCLn_2(n) DCU_CTRLDESCL(n, 2)
#define DCU_CTRLDESCLn_3(n) DCU_CTRLDESCL(n, 3)
#define TRANS_SHIFT 20
#define DCU_CTRLDESCLn_4(n) DCU_CTRLDESCL(n, 4)
#define BPP_MASK 0xf /* Bit per pixel Mask */
#define BPP_SHIFT 16 /* Bit per pixel Shift */
#define BPP24 0x5
#define EN_LAYER (1 << 31) /* Enable the layer */
#define DCU_CTRLDESCLn_5(n) DCU_CTRLDESCL(n, 5)
#define DCU_CTRLDESCLn_6(n) DCU_CTRLDESCL(n, 6)
#define DCU_CTRLDESCLn_7(n) DCU_CTRLDESCL(n, 7)
#define DCU_CTRLDESCLn_8(n) DCU_CTRLDESCL(n, 8)
#define DCU_CTRLDESCLn_9(n) DCU_CTRLDESCL(n, 9)
#define NUM_LAYERS 64
struct panel_info {
uint32_t width;
uint32_t height;
uint32_t h_back_porch;
uint32_t h_pulse_width;
uint32_t h_front_porch;
uint32_t v_back_porch;
uint32_t v_pulse_width;
uint32_t v_front_porch;
uint32_t clk_div;
uint32_t backlight_pin;
};
struct dcu_softc {
struct resource *res[2];
bus_space_tag_t bst;
bus_space_handle_t bsh;
void *ih;
device_t dev;
device_t sc_fbd; /* fbd child */
struct fb_info sc_info;
struct panel_info *panel;
};
static struct resource_spec dcu_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ SYS_RES_IRQ, 0, RF_ACTIVE },
{ -1, 0 }
};
static int
dcu_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "fsl,mvf600-dcu4"))
return (ENXIO);
device_set_desc(dev, "Vybrid Family Display Control Unit (DCU4)");
return (BUS_PROBE_DEFAULT);
}
static void
dcu_intr(void *arg)
{
struct dcu_softc *sc;
int reg;
sc = arg;
/* Ack interrupts */
reg = READ4(sc, DCU_INT_STATUS);
WRITE4(sc, DCU_INT_STATUS, reg);
/* TODO interrupt handler */
}
static int
get_panel_info(struct dcu_softc *sc, struct panel_info *panel)
{
phandle_t node;
pcell_t dts_value[3];
int len;
if ((node = ofw_bus_get_node(sc->dev)) == -1)
return (ENXIO);
/* panel size */
if ((len = OF_getproplen(node, "panel-size")) <= 0)
return (ENXIO);
- OF_getprop(node, "panel-size", &dts_value, len);
- panel->width = fdt32_to_cpu(dts_value[0]);
- panel->height = fdt32_to_cpu(dts_value[1]);
+ OF_getencprop(node, "panel-size", dts_value, len);
+ panel->width = dts_value[0];
+ panel->height = dts_value[1];
/* hsync */
if ((len = OF_getproplen(node, "panel-hsync")) <= 0)
return (ENXIO);
- OF_getprop(node, "panel-hsync", &dts_value, len);
- panel->h_back_porch = fdt32_to_cpu(dts_value[0]);
- panel->h_pulse_width = fdt32_to_cpu(dts_value[1]);
- panel->h_front_porch = fdt32_to_cpu(dts_value[2]);
+ OF_getencprop(node, "panel-hsync", dts_value, len);
+ panel->h_back_porch = dts_value[0];
+ panel->h_pulse_width = dts_value[1];
+ panel->h_front_porch = dts_value[2];
/* vsync */
if ((len = OF_getproplen(node, "panel-vsync")) <= 0)
return (ENXIO);
- OF_getprop(node, "panel-vsync", &dts_value, len);
- panel->v_back_porch = fdt32_to_cpu(dts_value[0]);
- panel->v_pulse_width = fdt32_to_cpu(dts_value[1]);
- panel->v_front_porch = fdt32_to_cpu(dts_value[2]);
+ OF_getencprop(node, "panel-vsync", dts_value, len);
+ panel->v_back_porch = dts_value[0];
+ panel->v_pulse_width = dts_value[1];
+ panel->v_front_porch = dts_value[2];
/* clk divider */
if ((len = OF_getproplen(node, "panel-clk-div")) <= 0)
return (ENXIO);
- OF_getprop(node, "panel-clk-div", &dts_value, len);
- panel->clk_div = fdt32_to_cpu(dts_value[0]);
+ OF_getencprop(node, "panel-clk-div", dts_value, len);
+ panel->clk_div = dts_value[0];
/* backlight pin */
if ((len = OF_getproplen(node, "panel-backlight-pin")) <= 0)
return (ENXIO);
- OF_getprop(node, "panel-backlight-pin", &dts_value, len);
- panel->backlight_pin = fdt32_to_cpu(dts_value[0]);
+ OF_getencprop(node, "panel-backlight-pin", dts_value, len);
+ panel->backlight_pin = dts_value[0];
return (0);
}
static int
dcu_init(struct dcu_softc *sc)
{
struct panel_info *panel;
int reg;
int i;
panel = sc->panel;
/* Configure DCU */
reg = ((sc->sc_info.fb_height) << DELTA_Y_S);
reg |= (sc->sc_info.fb_width / 16);
WRITE4(sc, DCU_DISP_SIZE, reg);
reg = (panel->h_back_porch << BP_H_SHIFT);
reg |= (panel->h_pulse_width << PW_H_SHIFT);
reg |= (panel->h_front_porch << FP_H_SHIFT);
WRITE4(sc, DCU_HSYN_PARA, reg);
reg = (panel->v_back_porch << BP_V_SHIFT);
reg |= (panel->v_pulse_width << PW_V_SHIFT);
reg |= (panel->v_front_porch << FP_V_SHIFT);
WRITE4(sc, DCU_VSYN_PARA, reg);
WRITE4(sc, DCU_BGND, 0);
WRITE4(sc, DCU_DIV_RATIO, panel->clk_div);
reg = (INV_VS | INV_HS);
WRITE4(sc, DCU_SYNPOL, reg);
/* TODO: export to panel info */
reg = (0x3 << LS_BF_VS_SHIFT);
reg |= (0x78 << OUT_BUF_HIGH_SHIFT);
reg |= (0 << OUT_BUF_LOW_SHIFT);
WRITE4(sc, DCU_THRESHOLD, reg);
/* Mask all the interrupts */
WRITE4(sc, DCU_INT_MASK, 0xffffffff);
/* Reset all layers */
for (i = 0; i < NUM_LAYERS; i++) {
WRITE4(sc, DCU_CTRLDESCLn_1(i), 0x0);
WRITE4(sc, DCU_CTRLDESCLn_2(i), 0x0);
WRITE4(sc, DCU_CTRLDESCLn_3(i), 0x0);
WRITE4(sc, DCU_CTRLDESCLn_4(i), 0x0);
WRITE4(sc, DCU_CTRLDESCLn_5(i), 0x0);
WRITE4(sc, DCU_CTRLDESCLn_6(i), 0x0);
WRITE4(sc, DCU_CTRLDESCLn_7(i), 0x0);
WRITE4(sc, DCU_CTRLDESCLn_8(i), 0x0);
WRITE4(sc, DCU_CTRLDESCLn_9(i), 0x0);
}
/* Setup first layer */
reg = (sc->sc_info.fb_width | (sc->sc_info.fb_height << 16));
WRITE4(sc, DCU_CTRLDESCLn_1(0), reg);
WRITE4(sc, DCU_CTRLDESCLn_2(0), 0x0);
WRITE4(sc, DCU_CTRLDESCLn_3(0), sc->sc_info.fb_pbase);
reg = (BPP24 << BPP_SHIFT);
reg |= EN_LAYER;
reg |= (0xFF << TRANS_SHIFT); /* completely opaque */
WRITE4(sc, DCU_CTRLDESCLn_4(0), reg);
WRITE4(sc, DCU_CTRLDESCLn_5(0), 0xffffff);
WRITE4(sc, DCU_CTRLDESCLn_6(0), 0x0);
WRITE4(sc, DCU_CTRLDESCLn_7(0), 0x0);
WRITE4(sc, DCU_CTRLDESCLn_8(0), 0x0);
WRITE4(sc, DCU_CTRLDESCLn_9(0), 0x0);
/* Enable DCU in normal mode */
reg = READ4(sc, DCU_DCU_MODE);
reg &= ~(DCU_MODE_M << DCU_MODE_S);
reg |= (DCU_MODE_NORMAL << DCU_MODE_S);
reg |= (RASTER_EN);
WRITE4(sc, DCU_DCU_MODE, reg);
WRITE4(sc, DCU_UPDATE_MODE, READREG);
return (0);
}
static int
dcu_attach(device_t dev)
{
struct panel_info panel;
struct dcu_softc *sc;
device_t gpio_dev;
int err;
sc = device_get_softc(dev);
sc->dev = dev;
if (bus_alloc_resources(dev, dcu_spec, sc->res)) {
device_printf(dev, "could not allocate resources\n");
return (ENXIO);
}
/* Memory interface */
sc->bst = rman_get_bustag(sc->res[0]);
sc->bsh = rman_get_bushandle(sc->res[0]);
/* Setup interrupt handler */
err = bus_setup_intr(dev, sc->res[1], INTR_TYPE_BIO | INTR_MPSAFE,
NULL, dcu_intr, sc, &sc->ih);
if (err) {
device_printf(dev, "Unable to alloc interrupt resource.\n");
return (ENXIO);
}
if (get_panel_info(sc, &panel)) {
device_printf(dev, "Can't get panel info\n");
return (ENXIO);
}
sc->panel = &panel;
/* Bypass timing control (used for raw lcd panels) */
tcon_bypass();
/* Get the GPIO device, we need this to give power to USB */
gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
if (gpio_dev == NULL) {
device_printf(sc->dev, "Error: failed to get the GPIO dev\n");
return (1);
}
/* Turn on backlight */
/* TODO: Use FlexTimer/PWM */
GPIO_PIN_SETFLAGS(gpio_dev, panel.backlight_pin, GPIO_PIN_OUTPUT);
GPIO_PIN_SET(gpio_dev, panel.backlight_pin, GPIO_PIN_HIGH);
sc->sc_info.fb_width = panel.width;
sc->sc_info.fb_height = panel.height;
sc->sc_info.fb_stride = sc->sc_info.fb_width * 3;
sc->sc_info.fb_bpp = sc->sc_info.fb_depth = 24;
sc->sc_info.fb_size = sc->sc_info.fb_height * sc->sc_info.fb_stride;
sc->sc_info.fb_vbase = (intptr_t)contigmalloc(sc->sc_info.fb_size,
M_DEVBUF, M_ZERO, 0, ~0, PAGE_SIZE, 0);
sc->sc_info.fb_pbase = (intptr_t)vtophys(sc->sc_info.fb_vbase);
#if 0
printf("%dx%d [%d]\n", sc->sc_info.fb_width, sc->sc_info.fb_height,
sc->sc_info.fb_stride);
printf("pbase == 0x%08x\n", sc->sc_info.fb_pbase);
#endif
memset((int8_t *)sc->sc_info.fb_vbase, 0x0, sc->sc_info.fb_size);
dcu_init(sc);
sc->sc_info.fb_name = device_get_nameunit(dev);
/* Ask newbus to attach framebuffer device to me. */
sc->sc_fbd = device_add_child(dev, "fbd", device_get_unit(dev));
if (sc->sc_fbd == NULL)
device_printf(dev, "Can't attach fbd device\n");
if (device_probe_and_attach(sc->sc_fbd) != 0) {
device_printf(sc->dev, "Failed to attach fbd device\n");
}
return (0);
}
static struct fb_info *
dcu4_fb_getinfo(device_t dev)
{
struct dcu_softc *sc = device_get_softc(dev);
return (&sc->sc_info);
}
static device_method_t dcu_methods[] = {
DEVMETHOD(device_probe, dcu_probe),
DEVMETHOD(device_attach, dcu_attach),
/* Framebuffer service methods */
DEVMETHOD(fb_getinfo, dcu4_fb_getinfo),
{ 0, 0 }
};
static driver_t dcu_driver = {
"fb",
dcu_methods,
sizeof(struct dcu_softc),
};
static devclass_t dcu_devclass;
DRIVER_MODULE(fb, simplebus, dcu_driver, dcu_devclass, 0, 0);
Index: stable/11/sys/arm/freescale/vybrid/vf_edma.c
===================================================================
--- stable/11/sys/arm/freescale/vybrid/vf_edma.c (revision 314502)
+++ stable/11/sys/arm/freescale/vybrid/vf_edma.c (revision 314503)
@@ -1,337 +1,336 @@
/*-
* Copyright (c) 2014 Ruslan Bukin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Vybrid Family Enhanced Direct Memory Access Controller (eDMA)
* Chapter 21, Vybrid Reference Manual, Rev. 5, 07/2013
*/
#include
__FBSDID("$FreeBSD$");
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
-#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct edma_channel {
uint32_t enabled;
uint32_t mux_num;
uint32_t mux_src;
uint32_t mux_chn;
uint32_t (*ih) (void *, int);
void *ih_user;
};
static struct edma_channel edma_map[EDMA_NUM_CHANNELS];
static struct resource_spec edma_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ SYS_RES_MEMORY, 1, RF_ACTIVE }, /* TCD */
{ SYS_RES_IRQ, 0, RF_ACTIVE }, /* Transfer complete */
{ SYS_RES_IRQ, 1, RF_ACTIVE }, /* Error Interrupt */
{ -1, 0 }
};
static int
edma_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "fsl,mvf600-edma"))
return (ENXIO);
device_set_desc(dev, "Vybrid Family eDMA Controller");
return (BUS_PROBE_DEFAULT);
}
static void
edma_transfer_complete_intr(void *arg)
{
struct edma_channel *ch;
struct edma_softc *sc;
int interrupts;
int i;
sc = arg;
interrupts = READ4(sc, DMA_INT);
WRITE1(sc, DMA_CINT, CINT_CAIR);
for (i = 0; i < EDMA_NUM_CHANNELS; i++) {
if (interrupts & (0x1 << i)) {
ch = &edma_map[i];
if (ch->enabled == 1) {
if (ch->ih != NULL) {
ch->ih(ch->ih_user, i);
}
}
}
}
}
static void
edma_err_intr(void *arg)
{
struct edma_softc *sc;
int reg;
sc = arg;
reg = READ4(sc, DMA_ERR);
#if 0
device_printf(sc->dev, "DMA_ERR 0x%08x, ES 0x%08x\n",
reg, READ4(sc, DMA_ES));
#endif
WRITE1(sc, DMA_CERR, CERR_CAEI);
}
static int
channel_free(struct edma_softc *sc, int chnum)
{
struct edma_channel *ch;
ch = &edma_map[chnum];
ch->enabled = 0;
dmamux_configure(ch->mux_num, ch->mux_src, ch->mux_chn, 0);
return (0);
}
static int
channel_configure(struct edma_softc *sc, int mux_grp, int mux_src)
{
struct edma_channel *ch;
int channel_first;
int mux_num;
int chnum;
int i;
if ((sc->device_id == 0 && mux_grp == 1) || \
(sc->device_id == 1 && mux_grp == 0)) {
channel_first = NCHAN_PER_MUX;
mux_num = (sc->device_id * 2) + 1;
} else {
channel_first = 0;
mux_num = sc->device_id * 2;
}
/* Take first unused eDMA channel */
ch = NULL;
for (i = channel_first; i < (channel_first + NCHAN_PER_MUX); i++) {
ch = &edma_map[i];
if (ch->enabled == 0) {
break;
}
ch = NULL;
}
if (ch == NULL) {
/* Can't find free channel */
return (-1);
}
chnum = i;
ch->enabled = 1;
ch->mux_num = mux_num;
ch->mux_src = mux_src;
ch->mux_chn = (chnum - channel_first); /* 0 to 15 */
dmamux_configure(ch->mux_num, ch->mux_src, ch->mux_chn, 1);
return (chnum);
}
static int
dma_stop(struct edma_softc *sc, int chnum)
{
int reg;
reg = READ4(sc, DMA_ERQ);
reg &= ~(0x1 << chnum);
WRITE4(sc, DMA_ERQ, reg);
return (0);
}
static int
dma_setup(struct edma_softc *sc, struct tcd_conf *tcd)
{
struct edma_channel *ch;
int chnum;
int reg;
chnum = tcd->channel;
ch = &edma_map[chnum];
ch->ih = tcd->ih;
ch->ih_user = tcd->ih_user;
TCD_WRITE4(sc, DMA_TCDn_SADDR(chnum), tcd->saddr);
TCD_WRITE4(sc, DMA_TCDn_DADDR(chnum), tcd->daddr);
reg = (tcd->smod << TCD_ATTR_SMOD_SHIFT);
reg |= (tcd->dmod << TCD_ATTR_DMOD_SHIFT);
reg |= (tcd->ssize << TCD_ATTR_SSIZE_SHIFT);
reg |= (tcd->dsize << TCD_ATTR_DSIZE_SHIFT);
TCD_WRITE2(sc, DMA_TCDn_ATTR(chnum), reg);
TCD_WRITE2(sc, DMA_TCDn_SOFF(chnum), tcd->soff);
TCD_WRITE2(sc, DMA_TCDn_DOFF(chnum), tcd->doff);
TCD_WRITE4(sc, DMA_TCDn_SLAST(chnum), tcd->slast);
TCD_WRITE4(sc, DMA_TCDn_DLASTSGA(chnum), tcd->dlast_sga);
TCD_WRITE4(sc, DMA_TCDn_NBYTES_MLOFFYES(chnum), tcd->nbytes);
reg = tcd->nmajor; /* Current Major Iteration Count */
TCD_WRITE2(sc, DMA_TCDn_CITER_ELINKNO(chnum), reg);
TCD_WRITE2(sc, DMA_TCDn_BITER_ELINKNO(chnum), reg);
reg = (TCD_CSR_INTMAJOR);
if(tcd->majorelink == 1) {
reg |= TCD_CSR_MAJORELINK;
reg |= (tcd->majorelinkch << TCD_CSR_MAJORELINKCH_SHIFT);
}
TCD_WRITE2(sc, DMA_TCDn_CSR(chnum), reg);
/* Enable requests */
reg = READ4(sc, DMA_ERQ);
reg |= (0x1 << chnum);
WRITE4(sc, DMA_ERQ, reg);
/* Enable error interrupts */
reg = READ4(sc, DMA_EEI);
reg |= (0x1 << chnum);
WRITE4(sc, DMA_EEI, reg);
return (0);
}
static int
dma_request(struct edma_softc *sc, int chnum)
{
int reg;
/* Start */
reg = TCD_READ2(sc, DMA_TCDn_CSR(chnum));
reg |= TCD_CSR_START;
TCD_WRITE2(sc, DMA_TCDn_CSR(chnum), reg);
return (0);
}
static int
edma_attach(device_t dev)
{
struct edma_softc *sc;
phandle_t node;
int dts_value;
int len;
sc = device_get_softc(dev);
sc->dev = dev;
if ((node = ofw_bus_get_node(sc->dev)) == -1)
return (ENXIO);
if ((len = OF_getproplen(node, "device-id")) <= 0)
return (ENXIO);
- OF_getprop(node, "device-id", &dts_value, len);
- sc->device_id = fdt32_to_cpu(dts_value);
+ OF_getencprop(node, "device-id", &dts_value, len);
+ sc->device_id = dts_value;
sc->dma_stop = dma_stop;
sc->dma_setup = dma_setup;
sc->dma_request = dma_request;
sc->channel_configure = channel_configure;
sc->channel_free = channel_free;
if (bus_alloc_resources(dev, edma_spec, sc->res)) {
device_printf(dev, "could not allocate resources\n");
return (ENXIO);
}
/* Memory interface */
sc->bst = rman_get_bustag(sc->res[0]);
sc->bsh = rman_get_bushandle(sc->res[0]);
sc->bst_tcd = rman_get_bustag(sc->res[1]);
sc->bsh_tcd = rman_get_bushandle(sc->res[1]);
/* Setup interrupt handlers */
if (bus_setup_intr(dev, sc->res[2], INTR_TYPE_BIO | INTR_MPSAFE,
NULL, edma_transfer_complete_intr, sc, &sc->tc_ih)) {
device_printf(dev, "Unable to alloc DMA intr resource.\n");
return (ENXIO);
}
if (bus_setup_intr(dev, sc->res[3], INTR_TYPE_BIO | INTR_MPSAFE,
NULL, edma_err_intr, sc, &sc->err_ih)) {
device_printf(dev, "Unable to alloc DMA Err intr resource.\n");
return (ENXIO);
}
return (0);
}
static device_method_t edma_methods[] = {
DEVMETHOD(device_probe, edma_probe),
DEVMETHOD(device_attach, edma_attach),
{ 0, 0 }
};
static driver_t edma_driver = {
"edma",
edma_methods,
sizeof(struct edma_softc),
};
static devclass_t edma_devclass;
DRIVER_MODULE(edma, simplebus, edma_driver, edma_devclass, 0, 0);
Index: stable/11/sys/arm/freescale/vybrid/vf_iomuxc.c
===================================================================
--- stable/11/sys/arm/freescale/vybrid/vf_iomuxc.c (revision 314502)
+++ stable/11/sys/arm/freescale/vybrid/vf_iomuxc.c (revision 314503)
@@ -1,211 +1,211 @@
/*-
* Copyright (c) 2013-2014 Ruslan Bukin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Vybrid Family Input/Output Multiplexer Controller (IOMUXC)
* Chapter 5, Vybrid Reference Manual, Rev. 5, 07/2013
*/
#include
__FBSDID("$FreeBSD$");
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MUX_MODE_MASK 7
#define MUX_MODE_SHIFT 20
#define MUX_MODE_GPIO 0
#define MUX_MODE_VBUS_EN_OTG 2
#define IBE (1 << 0) /* Input Buffer Enable Field */
#define OBE (1 << 1) /* Output Buffer Enable Field. */
#define PUE (1 << 2) /* Pull / Keep Select Field. */
#define PKE (1 << 3) /* Pull / Keep Enable Field. */
#define HYS (1 << 9) /* Hysteresis Enable Field */
#define ODE (1 << 10) /* Open Drain Enable Field. */
#define SRE (1 << 11) /* Slew Rate Field. */
#define SPEED_SHIFT 12
#define SPEED_MASK 0x3
#define SPEED_LOW 0 /* 50 MHz */
#define SPEED_MEDIUM 0x1 /* 100 MHz */
#define SPEED_HIGH 0x3 /* 200 MHz */
#define PUS_SHIFT 4 /* Pull Up / Down Config Field Shift */
#define PUS_MASK 0x3
#define PUS_100_KOHM_PULL_DOWN 0
#define PUS_47_KOHM_PULL_UP 0x1
#define PUS_100_KOHM_PULL_UP 0x2
#define PUS_22_KOHM_PULL_UP 0x3
#define DSE_SHIFT 6 /* Drive Strength Field Shift */
#define DSE_MASK 0x7
#define DSE_DISABLED 0 /* Output driver disabled */
#define DSE_150_OHM 0x1
#define DSE_75_OHM 0x2
#define DSE_50_OHM 0x3
#define DSE_37_OHM 0x4
#define DSE_30_OHM 0x5
#define DSE_25_OHM 0x6
#define DSE_20_OHM 0x7
#define MAX_MUX_LEN 1024
struct iomuxc_softc {
struct resource *tmr_res[1];
bus_space_tag_t bst;
bus_space_handle_t bsh;
device_t dev;
};
static struct resource_spec iomuxc_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ -1, 0 }
};
static int
iomuxc_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "fsl,mvf600-iomuxc"))
return (ENXIO);
device_set_desc(dev, "Vybrid Family IOMUXC Unit");
return (BUS_PROBE_DEFAULT);
}
static int
pinmux_set(struct iomuxc_softc *sc)
{
phandle_t child, parent, root;
pcell_t iomux_config[MAX_MUX_LEN];
int len;
int values;
int pin;
int pin_cfg;
int i;
root = OF_finddevice("/");
len = 0;
parent = root;
/* Find 'iomux_config' prop in the nodes */
for (child = OF_child(parent); child != 0; child = OF_peer(child)) {
/* Find a 'leaf'. Start the search from this node. */
while (OF_child(child)) {
parent = child;
child = OF_child(child);
}
if (!fdt_is_enabled(child))
continue;
if ((len = OF_getproplen(child, "iomux_config")) > 0) {
- OF_getprop(child, "iomux_config", &iomux_config, len);
+ OF_getencprop(child, "iomux_config", iomux_config, len);
values = len / (sizeof(uint32_t));
for (i = 0; i < values; i += 2) {
- pin = fdt32_to_cpu(iomux_config[i]);
- pin_cfg = fdt32_to_cpu(iomux_config[i+1]);
+ pin = iomux_config[i];
+ pin_cfg = iomux_config[i+1];
#if 0
device_printf(sc->dev, "Set pin %d to 0x%08x\n",
pin, pin_cfg);
#endif
WRITE4(sc, IOMUXC(pin), pin_cfg);
}
}
if (OF_peer(child) == 0) {
/* No more siblings. */
child = parent;
parent = OF_parent(child);
}
}
return (0);
}
static int
iomuxc_attach(device_t dev)
{
struct iomuxc_softc *sc;
sc = device_get_softc(dev);
sc->dev = dev;
if (bus_alloc_resources(dev, iomuxc_spec, sc->tmr_res)) {
device_printf(dev, "could not allocate resources\n");
return (ENXIO);
}
/* Memory interface */
sc->bst = rman_get_bustag(sc->tmr_res[0]);
sc->bsh = rman_get_bushandle(sc->tmr_res[0]);
pinmux_set(sc);
return (0);
}
static device_method_t iomuxc_methods[] = {
DEVMETHOD(device_probe, iomuxc_probe),
DEVMETHOD(device_attach, iomuxc_attach),
{ 0, 0 }
};
static driver_t iomuxc_driver = {
"iomuxc",
iomuxc_methods,
sizeof(struct iomuxc_softc),
};
static devclass_t iomuxc_devclass;
DRIVER_MODULE(iomuxc, simplebus, iomuxc_driver, iomuxc_devclass, 0, 0);
Index: stable/11/sys/arm/freescale/vybrid/vf_sai.c
===================================================================
--- stable/11/sys/arm/freescale/vybrid/vf_sai.c (revision 314502)
+++ stable/11/sys/arm/freescale/vybrid/vf_sai.c (revision 314503)
@@ -1,804 +1,803 @@
/*-
* Copyright (c) 2014 Ruslan Bukin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Vybrid Family Synchronous Audio Interface (SAI)
* Chapter 51, Vybrid Reference Manual, Rev. 5, 07/2013
*/
#include
__FBSDID("$FreeBSD$");
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
-#include
#include