From owner-p4-projects@FreeBSD.ORG Thu Jan 28 11:46:36 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id EFB7E1065672; Thu, 28 Jan 2010 11:46:35 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B3D54106566B for ; Thu, 28 Jan 2010 11:46:35 +0000 (UTC) (envelope-from raj@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 69AC88FC17 for ; Thu, 28 Jan 2010 11:46:35 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id o0SBkZbb034820 for ; Thu, 28 Jan 2010 11:46:35 GMT (envelope-from raj@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id o0SBkZUA034818 for perforce@freebsd.org; Thu, 28 Jan 2010 11:46:35 GMT (envelope-from raj@freebsd.org) Date: Thu, 28 Jan 2010 11:46:35 GMT Message-Id: <201001281146.o0SBkZUA034818@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to raj@freebsd.org using -f From: Rafal Jaworowski To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 173821 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 28 Jan 2010 11:46:36 -0000 http://p4web.freebsd.org/chv.cgi?CH=173821 Change 173821 by raj@raj_fdt on 2010/01/28 11:46:08 Refactor FDT infrastructure to better suit multiple platforms and architectures. - Move fdt_pic_table[] and IRQ info parsing routines to platform specific files. - Introduce machine-specific fdt.h header which is a fron-end interface between platform independent code of {fdt,simple}bus and local platform-specific defines and other items (including IRQ lines number, base VA of the internal registers etc.). - Make the [early access] fdt_is_compatible() a common public routine, as there's multiple consumers besides uart(4) attachment. - Teach fdtbus, simplebus and helper code a bit more endian-safety. - Eliminate diag output from early access routines (where console can be unavailable yet, which could lead to a hang). - Simplify parent #address-cells and #size-cells processing. - There's still a couple of rough edges, but we are capable of running {fdt,simple}bus driver on both ARM and PowerPC systems. Affected files ... .. //depot/projects/fdt/sys/dev/fdt/fdt_common.c#7 edit .. //depot/projects/fdt/sys/dev/fdt/fdt_common.h#3 edit .. //depot/projects/fdt/sys/dev/fdt/fdt_powerpc.c#1 add .. //depot/projects/fdt/sys/dev/fdt/fdtbus.c#3 edit .. //depot/projects/fdt/sys/dev/fdt/simplebus.c#4 edit .. //depot/projects/fdt/sys/dev/uart/uart_cpu_powerpc.c#3 edit .. //depot/projects/fdt/sys/powerpc/include/fdt.h#1 add Differences ... ==== //depot/projects/fdt/sys/dev/fdt/fdt_common.c#7 (text+ko) ==== @@ -32,12 +32,11 @@ #include #include -#include #include #include #include -#include +#include #include #include @@ -58,7 +57,48 @@ #define debugf(fmt, args...) #endif +/* + * This routine is an early-usage version of the ofw_bus_is_compatible() when + * the ofw_bus I/F is not available (like early console routines and similar). + * Note the buffer has to be on the stack since malloc() is usually not + * available in such cases either. + */ int +fdt_is_compatible(phandle_t node, const char *compatstr) +{ +#define FDT_COMPAT_LEN 255 + char *buf[FDT_COMPAT_LEN]; + char *compat; + int len, onelen, l, rv; + + if ((len = OF_getproplen(node, "compatible")) <= 0) + return (0); + + compat = (char *)&buf; + bzero(compat, FDT_COMPAT_LEN); + + if (OF_getprop(node, "compatible", compat, len) < 0) + return (0); + + onelen = strlen(compatstr); + rv = 0; + while (len > 0) { + if (strncasecmp(compat, compatstr, onelen) == 0) { + /* Found it. */ + rv = 1; + break; + } + /* Slide to the next sub-string. */ + l = strlen(compat) + 1; + compat += l; + len -= l; + } + + return (rv); +} + + +int fdt_is_enabled(phandle_t node) { char *stat; @@ -90,7 +130,7 @@ sizeof(addr_cells)) <= 0) addr_cells = 2; - return ((int)addr_cells); + return (fdt32_to_cpu((int)addr_cells)); } void @@ -156,11 +196,11 @@ cell_size = sizeof(cell); if (OF_getprop(node, "#address-cells", &cell, cell_size) < cell_size) cell = 2; - *addr_cells = (int)cell; + *addr_cells = fdt32_to_cpu((int)cell); if (OF_getprop(node, "#size-cells", &cell, cell_size) < cell_size) cell = 1; - *size_cells = (int)cell; + *size_cells = fdt32_to_cpu((int)cell); if (*addr_cells > 2 || *size_cells > 2) return (ERANGE); @@ -215,18 +255,16 @@ { /* Address portion. */ - if (fdt_data_verify((void *)data, addr_cells)) { - debugf("tuple #%d: unsupported addr value\n", addr_cells); + if (fdt_data_verify((void *)data, addr_cells)) return (ERANGE); - } + *start = fdt_data_get((void *)data, addr_cells); data += addr_cells; /* Size portion. */ - if (fdt_data_verify((void *)data, size_cells)) { - debugf("tuple #%d: unsupported size value\n", size_cells); + if (fdt_data_verify((void *)data, size_cells)) return (ERANGE); - } + *count = fdt_data_get((void *)data, size_cells); return (0); } @@ -240,14 +278,8 @@ int tuple_size, tuples; int i, rv; - addr_cells = fdt_parent_addr_cells(node); - if (addr_cells > 0) { - rv = OF_searchprop(OF_parent(node), "#size-cells", - &size_cells, sizeof(size_cells)); - if (rv <= 0) - size_cells = 1; - } else - size_cells = 0; + if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells) != 0) + return (ENXIO); tuple_size = sizeof(pcell_t) * (addr_cells + size_cells); tuples = OF_getprop_alloc(node, "reg", tuple_size, (void **)®); @@ -286,81 +318,6 @@ } static int -fdt_pic_decode_iic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, - int *pol) -{ - - /* TODO */ - return (ENXIO); -} - -static int -fdt_pic_decode_openpic(phandle_t node, pcell_t *intr, int *interrupt, - int *trig, int *pol) -{ - char *compat; - ssize_t prop_len; - int rv; - - prop_len = OF_getprop_alloc(node, "compatible", 1, (void **)&compat); - if (prop_len <= 0) - return (ENXIO); - - rv = 0; - if (strncmp("open-pic", compat, 8) < 0) { - rv = ENXIO; - goto out; - } - - /* - * XXX The interrupt number read out from the device tree is already - * offset by 16 to reflect the 'internal' IRQ range shift on the - * OpenPIC. We still however need to account for the ISA IRQ block, - * potentially in use as well. - */ - *interrupt = ISA_IRQ_COUNT + intr[0]; - - switch (intr[1]) { - case 0: - /* L to H edge */ - *trig = INTR_TRIGGER_EDGE; - *pol = INTR_POLARITY_HIGH; - break; - case 1: - /* Active L level */ - *trig = INTR_TRIGGER_LEVEL; - *pol = INTR_POLARITY_LOW; - break; - case 2: - /* Active H level */ - *trig = INTR_TRIGGER_LEVEL; - *pol = INTR_POLARITY_HIGH; - break; - case 3: - /* H to L edge */ - *trig = INTR_TRIGGER_EDGE; - *pol = INTR_POLARITY_LOW; - break; - default: - *trig = INTR_TRIGGER_CONFORM; - *pol = INTR_POLARITY_CONFORM; - } - -out: - free(compat, M_OFWPROP); - return (rv); -} - -typedef int (*fdt_pic_decode_t)(phandle_t, pcell_t *, int *, int *, - int *); - -static fdt_pic_decode_t fdt_pic_table[] = { - &fdt_pic_decode_iic, - &fdt_pic_decode_openpic, - NULL -}; - -static int fdt_intr_decode(phandle_t intr_parent, pcell_t *intr, int *interrupt, int *trig, int *pol) { @@ -403,14 +360,17 @@ if (OF_getprop(node, "interrupt-parent", &iph, sizeof(iph)) <= 0) { debugf("no intr-parent phandle\n"); intr_par = OF_parent(node); - } else + } else { + iph = fdt32_to_cpu(iph); intr_par = OF_instance_to_package(iph); + } if (OF_getprop(intr_par, "#interrupt-cells", &intr_cells, sizeof(intr_cells)) <= 0) { debugf("no intr-cells defined, defaulting to 1\n"); intr_cells = 1; } + intr_cells = fdt32_to_cpu(intr_cells); intr_num = OF_getprop_alloc(node, "interrupts", intr_cells * sizeof(pcell_t), (void **)&intr); ==== //depot/projects/fdt/sys/dev/fdt/fdt_common.h#3 (text+ko) ==== @@ -39,6 +39,10 @@ enum intr_polarity pol; }; +typedef int (*fdt_pic_decode_t)(phandle_t, pcell_t *, int *, int *, int *); + +extern fdt_pic_decode_t fdt_pic_table[]; + int fdt_addrsize_cells(phandle_t, int *, int *); u_long fdt_data_get(void *, int); int fdt_parent_addr_cells(phandle_t); @@ -47,6 +51,7 @@ int fdt_reg_to_rl(phandle_t, struct resource_list *, u_long); int fdt_intr_to_rl(phandle_t, struct resource_list *, struct sense_level *); int fdt_data_to_res(pcell_t *, int, int, u_long *, u_long *); +int fdt_is_compatible(phandle_t, const char *); int fdt_is_enabled(phandle_t); #endif /* FDT_COMMON_H */ ==== //depot/projects/fdt/sys/dev/fdt/fdtbus.c#3 (text+ko) ==== @@ -30,6 +30,7 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_platform.h" #include #include #include @@ -41,7 +42,7 @@ #include -#include +#include #include "fdt_common.h" #include "ofw_bus_if.h" @@ -58,8 +59,6 @@ static MALLOC_DEFINE(M_FDTBUS, "fdtbus", "FDTbus devices information"); -extern struct bus_space bs_be_tag; - struct fdtbus_devinfo { phandle_t di_node; char *di_name; @@ -174,7 +173,7 @@ * IRQ rman. */ start = 0; - end = INTR_VECTORS - 1; + end = FDT_INTR_MAX - 1; sc->sc_irq.rm_start = start; sc->sc_irq.rm_end = end; sc->sc_irq.rm_type = RMAN_ARRAY; @@ -261,6 +260,7 @@ static device_t newbus_device_from_fdt_node(device_t parent, phandle_t node) { + u_long base; device_t child; struct fdtbus_devinfo *di; char *name, *type, *compat; @@ -286,13 +286,17 @@ di->di_compat = compat; resource_list_init(&di->di_res); - +#ifdef MPC85XX /* * XXX this 0x1ef00000 offset is a gross hack, which assumes: * - physical addresses in the DTS are 0xe0000000 range, and * - virtual CCSR base in kernel is 0xfef00000 */ - if (fdt_reg_to_rl(node, &di->di_res, 0x1ef00000)) { + base = 0x1ef00000; +#else + base = 0; +#endif + if (fdt_reg_to_rl(node, &di->di_res, base)) { device_printf(child, "could not process 'reg' " "property\n"); newbus_device_destroy(child); @@ -383,7 +387,7 @@ if (type == SYS_RES_IOPORT || type == SYS_RES_MEMORY) { /* XXX endianess should be set based on SOC node */ - rman_set_bustag(res, &bs_be_tag); + rman_set_bustag(res, fdtbus_bs_tag); rman_set_bushandle(res, rman_get_start(res)); } @@ -427,8 +431,12 @@ if (err) return (err); +#if defined(__powerpc__) err = powerpc_setup_intr(device_get_nameunit(child), rman_get_start(res), filter, ihand, arg, flags, cookiep); +#elif defined(__arm__) + /* TODO */ +#endif return (err); } @@ -455,7 +463,11 @@ void *cookie) { +#if defined(__powerpc__) return (powerpc_teardown_intr(cookie)); +#elif defined(__arm__) + return (arm_remove_irqhandler(rman_get_start(res), cookie)); +#endif } static const char * ==== //depot/projects/fdt/sys/dev/fdt/simplebus.c#4 (text+ko) ==== @@ -30,6 +30,7 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_platform.h" #include #include #include @@ -39,8 +40,7 @@ #include #include -#include -#include +#include #include #include @@ -140,11 +140,16 @@ static int simplebus_probe(device_t dev) { + struct simplebus_softc *sc; if (!ofw_bus_is_compatible(dev, "simple-bus")) return (ENXIO); device_set_desc(dev, "Flattened device tree simple bus"); + + sc = device_get_softc(dev); + sc->sc_start_va = FDT_SIMPLEBUS_VA; + return (BUS_PROBE_DEFAULT); } @@ -240,7 +245,6 @@ } debugf("start = %lx, size = %lx\n", start, size); sc->sc_start_pa = start; - sc->sc_start_va = CCSRBAR_VA; sc->sc_size = size; /* @@ -387,7 +391,13 @@ debugf("intr config: irq = %d, trig = %d, pol = %d\n", irq, trig, pol); +#if defined(__powerpc__) err = powerpc_config_intr(irq, trig, pol); +#elif defined(__arm__) + arm_setup_irqhandler(device_get_nameunit(child), filter, ihand, arg, + irq, flags, cookiep); + return (0); +#endif if (err) return (err); ==== //depot/projects/fdt/sys/dev/uart/uart_cpu_powerpc.c#3 (text) ==== @@ -40,7 +40,7 @@ #include #include #include -#include +#include #endif #include @@ -92,45 +92,6 @@ } #ifdef FDT -/* - * Since ofw_bus_is_compatible() cannot be used at this early stage, we need - * a similar function locally. Note the buffer has to be on the stack since - * malloc() is not yet available. - */ -static int -fdt_is_compatible(phandle_t node, const char *compatstr) -{ -#define FDT_COMPAT_LEN 255 - char *buf[FDT_COMPAT_LEN]; - char *compat; - int len, onelen, l, rv; - - if ((len = OF_getproplen(node, "compatible")) <= 0) - return (0); - - compat = (char *)&buf; - bzero(compat, FDT_COMPAT_LEN); - - if (OF_getprop(node, "compatible", compat, len) < 0) - return (0); - - onelen = strlen(compatstr); - rv = 0; - while (len > 0) { - if (strncasecmp(compat, compatstr, onelen) == 0) { - /* Found it. */ - rv = 1; - break; - } - /* Slide to the next sub-string. */ - l = strlen(compat) + 1; - compat += l; - len -= l; - } - - return (rv); -} - static int fdt_uart_addr(phandle_t node, bus_space_tag_t *tag, bus_space_handle_t *handle) { @@ -179,8 +140,7 @@ rv = fdt_data_to_res(prop, par_addr_cells, par_size_cells, &start, &size); - /* XXX this is an MPC85XX specific hack and needs to go away. */ - start += CCSRBAR_VA; + start += FDT_SIMPLEBUS_VA; rv = bus_space_map(*tag, start, size, 0, handle); if (rv)