static void __init xgene_check_pirq_eoi(void) { const struct dt_device_node *node; int res; paddr_t dbase; const struct dt_device_match xgene_dt_int_ctrl_match[] = { DT_MATCH_COMPATIBLE("arm,cortex-a15-gic"), { /*sentinel*/ }, }; node = dt_find_interrupt_controller(xgene_dt_int_ctrl_match); if ( !node ) panic("%s: Can not find interrupt controller node", __func__); res = dt_device_get_address(node, 0, &dbase, NULL); if ( !dbase ) panic("%s: Cannot find a valid address for the distributor", __func__); /* * In old X-Gene Storm firmware and DT, secure mode addresses have * been mentioned in GICv2 node. We have to use maintenance interrupt * instead of EOI HW in this case. We check the GIC Distributor Base * Address to maintain compatibility with older firmware. */ if ( dbase == XGENE_SEC_GICV2_DIST_ADDR ) { xgene_quirks |= PLATFORM_QUIRK_GUEST_PIRQ_NEED_EOI; printk("Xen: WARNING: OLD X-Gene Firmware, disabling PIRQ EOI mode\n"); } }
static void __init xgene_check_pirq_eoi(void) { const struct dt_device_node *node; int res; paddr_t dbase; const struct dt_device_match xgene_dt_int_ctrl_match[] = { DT_MATCH_COMPATIBLE("arm,cortex-a15-gic"), { /*sentinel*/ }, }; node = dt_find_interrupt_controller(xgene_dt_int_ctrl_match); if ( !node ) panic("%s: Can not find interrupt controller node", __func__); res = dt_device_get_address(node, 0, &dbase, NULL); if ( !dbase ) panic("%s: Cannot find a valid address for the distributor", __func__); /* * In old X-Gene Storm firmware and DT, secure mode addresses have * been mentioned in GICv2 node. EOI HW won't work in this case. * We check the GIC Distributor Base Address to deny Xen booting * with older firmware. */ if ( dbase == XGENE_SEC_GICV2_DIST_ADDR ) panic("OLD X-Gene Firmware is not supported by Xen.\n" "Please upgrade your firmware to the latest version"); }
static int exynos5_get_pmu_baseandsize(u64 *power_base_addr, u64 *size) { struct dt_device_node *node; int rc; static const struct dt_device_match exynos_dt_pmu_matches[] = { DT_MATCH_COMPATIBLE("samsung,exynos5250-pmu"), DT_MATCH_COMPATIBLE("samsung,exynos5410-pmu"), DT_MATCH_COMPATIBLE("samsung,exynos5420-pmu"), { /*sentinel*/ }, }; node = dt_find_matching_node(NULL, exynos_dt_pmu_matches); if ( !node ) { dprintk(XENLOG_ERR, "samsung,exynos5XXX-pmu missing in DT\n"); return -ENXIO; } rc = dt_device_get_address(node, 0, power_base_addr, size); if ( rc ) { dprintk(XENLOG_ERR, "Error in \"samsung,exynos5XXX-pmu\"\n"); return -ENXIO; } dprintk(XENLOG_DEBUG, "power_base_addr: %016llx size: %016llx\n", *power_base_addr, *size); return 0; }
static __init int brcm_get_dt_node(char *compat_str, const struct dt_device_node **dn, u32 *reg_base) { const struct dt_device_node *node; u64 reg_base_64; int rc; node = dt_find_compatible_node(NULL, NULL, compat_str); if ( !node ) { dprintk(XENLOG_ERR, "%s: missing \"%s\" node\n", __func__, compat_str); return -ENOENT; } rc = dt_device_get_address(node, 0, ®_base_64, NULL); if ( rc ) { dprintk(XENLOG_ERR, "%s: missing \"reg\" prop\n", __func__); return rc; } if ( dn ) *dn = node; if ( reg_base ) *reg_base = reg_base_64; return 0; }
static int __init exynos5_smp_init(void) { struct dt_device_node *node; void __iomem *sysram; char *compatible; u64 sysram_addr; u64 size; u64 sysram_offset; int rc; node = dt_find_compatible_node(NULL, NULL, "samsung,secure-firmware"); if ( node ) { /* Have to use sysram_ns_base_addr + 0x1c for boot address */ compatible = "samsung,exynos4210-sysram-ns"; sysram_offset = 0x1c; secure_firmware = 1; printk("Running under secure firmware.\n"); } else { /* Have to use sysram_base_addr + offset 0 for boot address */ compatible = "samsung,exynos4210-sysram"; sysram_offset = 0; } node = dt_find_compatible_node(NULL, NULL, compatible); if ( !node ) { dprintk(XENLOG_ERR, "%s missing in DT\n", compatible); return -ENXIO; } rc = dt_device_get_address(node, 0, &sysram_addr, &size); if ( rc ) { dprintk(XENLOG_ERR, "Error in %s\n", compatible); return -ENXIO; } dprintk(XENLOG_INFO, "sysram_addr: %016llx size: %016llx offset: %016llx\n", sysram_addr, size, sysram_offset); sysram = ioremap_nocache(sysram_addr, size); if ( !sysram ) { dprintk(XENLOG_ERR, "Unable to map exynos5 MMIO\n"); return -EFAULT; } printk("Set SYSRAM to %"PRIpaddr" (%p)\n", __pa(init_secondary), init_secondary); writel(__pa(init_secondary), sysram + sysram_offset); iounmap(sysram); return 0; }
/* * Xen does not currently support mapping MMIO regions and interrupt * for bus child devices (referenced via the "ranges" and * "interrupt-map" properties to domain 0). Instead for now map the * necessary resources manually. */ static int xgene_storm_specific_mapping(struct domain *d) { struct dt_device_node *node = NULL; int ret; while ( (node = dt_find_compatible_node(node, "pci", "apm,xgene-pcie")) ) { u64 addr; /* Identify the bus via it's control register address */ ret = dt_device_get_address(node, 0, &addr, NULL); if ( ret < 0 ) return ret; if ( !dt_device_is_available(node) ) continue; switch ( addr ) { case 0x1f2b0000: /* PCIe0 */ ret = xgene_storm_pcie_specific_mapping(d, node, 0x0e000000000UL, 0x10000000000UL, 0xc2); break; case 0x1f2c0000: /* PCIe1 */ ret = xgene_storm_pcie_specific_mapping(d, node, 0x0d000000000UL, 0x0e000000000UL, 0xc8); break; case 0x1f2d0000: /* PCIe2 */ ret = xgene_storm_pcie_specific_mapping(d, node, 0x09000000000UL, 0x0a000000000UL, 0xce); break; case 0x1f500000: /* PCIe3 */ ret = xgene_storm_pcie_specific_mapping(d, node, 0x0a000000000UL, 0x0c000000000UL, 0xd4); break; case 0x1f510000: /* PCIe4 */ ret = xgene_storm_pcie_specific_mapping(d, node, 0x0c000000000UL, 0x0d000000000UL, 0xda); break; default: printk("Ignoring unknown PCI bus %s\n", dt_node_full_name(node)); continue; } if ( ret < 0 ) return ret; } return 0; }
/* TODO: Parse UART config from the command line */ static int __init exynos4210_uart_init(struct dt_device_node *dev, const void *data) { const char *config = data; struct exynos4210_uart *uart; int res; u64 addr, size; if ( strcmp(config, "") ) printk("WARNING: UART configuration is not supported\n"); uart = &exynos4210_com; /* uart->clock_hz = 0x16e3600; */ uart->baud = BAUD_AUTO; uart->data_bits = 8; uart->parity = PARITY_NONE; uart->stop_bits = 1; res = dt_device_get_address(dev, 0, &addr, &size); if ( res ) { printk("exynos4210: Unable to retrieve the base" " address of the UART\n"); return res; } res = platform_get_irq(dev, 0); if ( res < 0 ) { printk("exynos4210: Unable to retrieve the IRQ\n"); return -EINVAL; } uart->irq = res; uart->regs = ioremap_nocache(addr, size); if ( !uart->regs ) { printk("exynos4210: Unable to map the UART memory\n"); return -ENOMEM; } uart->vuart.base_addr = addr; uart->vuart.size = size; uart->vuart.data_off = UTXH; uart->vuart.status_off = UTRSTAT; uart->vuart.status = UTRSTAT_TXE | UTRSTAT_TXFE; /* Register with generic serial driver. */ serial_register_uart(SERHND_DTUART, &exynos4210_uart_driver, uart); dt_device_set_used_by(dev, DOMID_XEN); return 0; }
static int exynos5_init_time(void) { uint32_t reg; void __iomem *mct; int rc; struct dt_device_node *node; u64 mct_base_addr; u64 size; node = dt_find_compatible_node(NULL, NULL, "samsung,exynos4210-mct"); if ( !node ) { dprintk(XENLOG_ERR, "samsung,exynos4210-mct missing in DT\n"); return -ENXIO; } rc = dt_device_get_address(node, 0, &mct_base_addr, &size); if ( rc ) { dprintk(XENLOG_ERR, "Error in \"samsung,exynos4210-mct\"\n"); return -ENXIO; } dprintk(XENLOG_INFO, "mct_base_addr: %016llx size: %016llx\n", mct_base_addr, size); mct = ioremap_attr(mct_base_addr, size, PAGE_HYPERVISOR_NOCACHE); if ( !mct ) { dprintk(XENLOG_ERR, "Unable to map MCT\n"); return -ENOMEM; } /* Enable timer on Exynos 5250 should probably be done by u-boot */ reg = readl(mct + EXYNOS5_MCT_G_TCON); writel(reg | EXYNOS5_MCT_G_TCON_START, mct + EXYNOS5_MCT_G_TCON); iounmap(mct); return 0; }
static int __init omap_uart_init(struct dt_device_node *dev, const void *data) { const char *config = data; struct omap_uart *uart; u32 clkspec; int res; u64 addr, size; if ( strcmp(config, "") ) printk("WARNING: UART configuration is not supported\n"); uart = &omap_com; res = dt_property_read_u32(dev, "clock-frequency", &clkspec); if ( !res ) { printk("omap-uart: Unable to retrieve the clock frequency\n"); return -EINVAL; } uart->clock_hz = clkspec; uart->baud = 115200; uart->data_bits = 8; uart->parity = UART_PARITY_NONE; uart->stop_bits = 1; res = dt_device_get_address(dev, 0, &addr, &size); if ( res ) { printk("omap-uart: Unable to retrieve the base" " address of the UART\n"); return res; } res = platform_get_irq(dev, 0); if ( res < 0 ) { printk("omap-uart: Unable to retrieve the IRQ\n"); return -EINVAL; } uart->irq = res; uart->regs = ioremap_nocache(addr, size); if ( !uart->regs ) { printk("omap-uart: Unable to map the UART memory\n"); return -ENOMEM; } uart->vuart.base_addr = addr; uart->vuart.size = size; uart->vuart.data_off = UART_THR; uart->vuart.status_off = UART_LSR << REG_SHIFT; uart->vuart.status = UART_LSR_THRE; /* Register with generic serial driver */ serial_register_uart(SERHND_DTUART, &omap_uart_driver, uart); dt_device_set_used_by(dev, DOMID_XEN); return 0; }
void __init video_init(void) { struct lfb_prop lfbp; unsigned char *lfb; paddr_t hdlcd_start, hdlcd_size; paddr_t framebuffer_start, framebuffer_size; const char *mode_string; char _mode_string[16]; int bytes_per_pixel = 4; struct color_masks *c = NULL; struct modeline *videomode = NULL; int i; const struct dt_device_node *dev; const __be32 *cells; u32 lenp; int res; dev = dt_find_compatible_node(NULL, NULL, "arm,hdlcd"); if ( !dev ) { early_printk("HDLCD: Cannot find node compatible with \"arm,hdcld\"\n"); return; } res = dt_device_get_address(dev, 0, &hdlcd_start, &hdlcd_size); if ( !res ) { early_printk("HDLCD: Unable to retrieve MMIO base address\n"); return; } cells = dt_get_property(dev, "framebuffer", &lenp); if ( !cells ) { early_printk("HDLCD: Unable to retrieve framebuffer property\n"); return; } framebuffer_start = dt_next_cell(dt_n_addr_cells(dev), &cells); framebuffer_size = dt_next_cell(dt_n_size_cells(dev), &cells); if ( !hdlcd_start ) { early_printk(KERN_ERR "HDLCD: address missing from device tree, disabling driver\n"); return; } if ( !framebuffer_start ) { early_printk(KERN_ERR "HDLCD: framebuffer address missing from device tree, disabling driver\n"); return; } res = dt_property_read_string(dev, "mode", &mode_string); if ( res ) { get_color_masks("32", &c); memcpy(_mode_string, "1280x1024@60", strlen("1280x1024@60") + 1); bytes_per_pixel = 4; } else if ( strlen(mode_string) < strlen("800x600@60") || strlen(mode_string) > sizeof(_mode_string) - 1 ) { early_printk(KERN_ERR "HDLCD: invalid modeline=%s\n", mode_string); return; } else { char *s = strchr(mode_string, '-'); if ( !s ) { early_printk(KERN_INFO "HDLCD: bpp not found in modeline %s, assume 32 bpp\n", mode_string); get_color_masks("32", &c); memcpy(_mode_string, mode_string, strlen(mode_string) + 1); bytes_per_pixel = 4; } else { if ( strlen(s) < 6 ) { early_printk(KERN_ERR "HDLCD: invalid mode %s\n", mode_string); return; } s++; if ( get_color_masks(s, &c) < 0 ) { early_printk(KERN_WARNING "HDLCD: unsupported bpp %s\n", s); return; } bytes_per_pixel = simple_strtoll(s, NULL, 10) / 8; } i = s - mode_string - 1; memcpy(_mode_string, mode_string, i); memcpy(_mode_string + i, mode_string + i + 3, 4); } for ( i = 0; i < ARRAY_SIZE(videomodes); i++ ) { if ( !strcmp(_mode_string, videomodes[i].mode) ) { videomode = &videomodes[i]; break; } } if ( !videomode ) { early_printk(KERN_WARNING "HDLCD: unsupported videomode %s\n", _mode_string); return; } if ( framebuffer_size < bytes_per_pixel * videomode->xres * videomode->yres ) { early_printk(KERN_ERR "HDLCD: the framebuffer is too small, disabling the HDLCD driver\n"); return; } early_printk(KERN_INFO "Initializing HDLCD driver\n"); lfb = ioremap_wc(framebuffer_start, framebuffer_size); if ( !lfb ) { early_printk(KERN_ERR "Couldn't map the framebuffer\n"); return; } memset(lfb, 0x00, bytes_per_pixel * videomode->xres * videomode->yres); /* uses FIXMAP_MISC */ set_pixclock(videomode->pixclock); set_fixmap(FIXMAP_MISC, hdlcd_start >> PAGE_SHIFT, DEV_SHARED); HDLCD[HDLCD_COMMAND] = 0; HDLCD[HDLCD_LINELENGTH] = videomode->xres * bytes_per_pixel; HDLCD[HDLCD_LINECOUNT] = videomode->yres - 1; HDLCD[HDLCD_LINEPITCH] = videomode->xres * bytes_per_pixel; HDLCD[HDLCD_PF] = ((bytes_per_pixel - 1) << 3); HDLCD[HDLCD_INTMASK] = 0; HDLCD[HDLCD_FBBASE] = framebuffer_start; HDLCD[HDLCD_BUS] = 0xf00 | (1 << 4); HDLCD[HDLCD_VBACK] = videomode->vback - 1; HDLCD[HDLCD_VSYNC] = videomode->vsync - 1; HDLCD[HDLCD_VDATA] = videomode->yres - 1; HDLCD[HDLCD_VFRONT] = videomode->vfront - 1; HDLCD[HDLCD_HBACK] = videomode->hback - 1; HDLCD[HDLCD_HSYNC] = videomode->hsync - 1; HDLCD[HDLCD_HDATA] = videomode->xres - 1; HDLCD[HDLCD_HFRONT] = videomode->hfront - 1; HDLCD[HDLCD_POLARITIES] = (1 << 2) | (1 << 3); HDLCD[HDLCD_RED] = (c->red_size << 8) | c->red_shift; HDLCD[HDLCD_GREEN] = (c->green_size << 8) | c->green_shift; HDLCD[HDLCD_BLUE] = (c->blue_size << 8) | c->blue_shift; HDLCD[HDLCD_COMMAND] = 1; clear_fixmap(FIXMAP_MISC); lfbp.pixel_on = (((1 << c->red_size) - 1) << c->red_shift) | (((1 << c->green_size) - 1) << c->green_shift) | (((1 << c->blue_size) - 1) << c->blue_shift); lfbp.lfb = lfb; lfbp.font = &font_vga_8x16; lfbp.bits_per_pixel = bytes_per_pixel*8; lfbp.bytes_per_line = bytes_per_pixel*videomode->xres; lfbp.width = videomode->xres; lfbp.height = videomode->yres; lfbp.flush = hdlcd_flush; lfbp.text_columns = videomode->xres / 8; lfbp.text_rows = videomode->yres / 16; if ( lfb_init(&lfbp) < 0 ) return; video_puts = lfb_scroll_puts; }