void spintable_init(void *monitor_address) { extern void __wait_for_spin_table_request(void); const size_t code_size = 4096; if (monitor_address == NULL) { printk(BIOS_ERR, "spintable: NULL address to monitor.\n"); return; } spin_attrs.entry = cbmem_add(CBMEM_ID_SPINTABLE, code_size); if (spin_attrs.entry == NULL) return; spin_attrs.addr = monitor_address; printk(BIOS_INFO, "spintable @ %p will monitor %p\n", spin_attrs.entry, spin_attrs.addr); /* Ensure the memory location is zero'd out. */ *(uint64_t *)monitor_address = 0; memcpy(spin_attrs.entry, __wait_for_spin_table_request, code_size); dcache_clean_invalidate_by_mva(monitor_address, sizeof(uint64_t)); dcache_clean_invalidate_by_mva(spin_attrs.entry, code_size); }
static int tegra_spi_dma_prepare(struct tegra_spi_channel *spi, unsigned int bytes, enum spi_direction dir) { unsigned int todo, wcount; /* * For DMA we need to think of things in terms of word count. * AHB width is fixed at 32-bits. To avoid overrunning * the in/out buffers we must align down. (Note: lowest 2-bits * in WCOUNT register are ignored, and WCOUNT seems to count * words starting at n-1) * * Example: If "bytes" is 7 and we are transferring 1-byte at a time, * WCOUNT should be 4. The remaining 3 bytes must be transferred * using PIO. */ todo = MIN(bytes, SPI_MAX_TRANSFER_BYTES_DMA - TEGRA_DMA_ALIGN_BYTES); todo = ALIGN_DOWN(todo, TEGRA_DMA_ALIGN_BYTES); wcount = ALIGN_DOWN(todo - TEGRA_DMA_ALIGN_BYTES, TEGRA_DMA_ALIGN_BYTES); flush_fifos(spi); if (dir == SPI_SEND) { spi->dma_out = dma_claim(); if (!spi->dma_out) return -1; /* ensure bytes to send will be visible to DMA controller */ dcache_clean_by_mva(spi->out_buf, bytes); write32(&spi->dma_out->regs->apb_ptr, (uintptr_t) & spi->regs->tx_fifo); write32(&spi->dma_out->regs->ahb_ptr, (uintptr_t)spi->out_buf); setbits_le32(&spi->dma_out->regs->csr, APB_CSR_DIR); setup_dma_params(spi, spi->dma_out); write32(&spi->dma_out->regs->wcount, wcount); } else { spi->dma_in = dma_claim(); if (!spi->dma_in) return -1; /* avoid data collisions */ dcache_clean_invalidate_by_mva(spi->in_buf, bytes); write32(&spi->dma_in->regs->apb_ptr, (uintptr_t)&spi->regs->rx_fifo); write32(&spi->dma_in->regs->ahb_ptr, (uintptr_t)spi->in_buf); clrbits_le32(&spi->dma_in->regs->csr, APB_CSR_DIR); setup_dma_params(spi, spi->dma_in); write32(&spi->dma_in->regs->wcount, wcount); } /* BLOCK_SIZE starts at n-1 */ write32(&spi->regs->dma_blk, todo - 1); return todo; }
void rk_display_init(device_t dev, u32 lcdbase, unsigned long fb_size) { struct edid edid; struct soc_rockchip_rk3288_config *conf = dev->chip_info; uint32_t lower = ALIGN_DOWN(lcdbase, MiB); uint32_t upper = ALIGN_UP(lcdbase + fb_size, MiB); enum vop_modes detected_mode = VOP_MODE_UNKNOWN; printk(BIOS_SPEW, "LCD framebuffer @%p\n", (void *)(lcdbase)); memset((void *)lcdbase, 0, fb_size); /* clear the framebuffer */ dcache_clean_invalidate_by_mva((void *)lower, upper - lower); mmu_config_range(lower / MiB, (upper - lower) / MiB, DCACHE_OFF); switch (conf->vop_mode) { case VOP_MODE_NONE: return; case VOP_MODE_AUTO_DETECT: /* try EDP first, then HDMI */ case VOP_MODE_EDP: printk(BIOS_DEBUG, "Attempting to setup EDP display.\n"); rkclk_configure_edp(); rkclk_configure_vop_aclk(conf->vop_id, 192 * MHz); rk_edp_init(conf->vop_id); if (rk_edp_get_edid(&edid) == 0) { detected_mode = VOP_MODE_EDP; break; } else { printk(BIOS_WARNING, "Cannot get EDID from EDP.\n"); if (conf->vop_mode == VOP_MODE_EDP) return; } /* fall thru */ case VOP_MODE_HDMI: printk(BIOS_DEBUG, "Attempting to setup HDMI display.\n"); rkclk_configure_hdmi(); rkclk_configure_vop_aclk(conf->vop_id, 384 * MHz); rk_hdmi_init(conf->vop_id); if (rk_hdmi_get_edid(&edid) == 0) { detected_mode = VOP_MODE_HDMI; break; } else { printk(BIOS_WARNING, "Cannot get EDID from HDMI.\n"); if (conf->vop_mode == VOP_MODE_HDMI) return; } /* fall thru */ default: printk(BIOS_WARNING, "Cannot read any edid info, aborting.\n"); return; } if (rkclk_configure_vop_dclk(conf->vop_id, edid.pixel_clock * KHz)) { printk(BIOS_WARNING, "config vop err\n"); return; } edid.framebuffer_bits_per_pixel = conf->framebuffer_bits_per_pixel; edid.bytes_per_line = edid.ha * conf->framebuffer_bits_per_pixel / 8; edid.x_resolution = edid.ha; edid.y_resolution = edid.va; rkvop_mode_set(conf->vop_id, &edid, detected_mode); rkvop_enable(conf->vop_id, lcdbase, &edid); switch (detected_mode) { case VOP_MODE_HDMI: if (rk_hdmi_enable(&edid)) { printk(BIOS_WARNING, "hdmi enable err\n"); return; } /* * HACK: if we do remove this delay, HDMI TV may not show * anythings. So we make an delay here, ensure TV have * enough time to respond. */ mdelay(2000); break; case VOP_MODE_EDP: default: if (rk_edp_enable()) { printk(BIOS_WARNING, "edp enable err\n"); return; } mainboard_power_on_backlight(); break; } set_vbe_mode_info_valid(&edid, (uintptr_t)lcdbase); }
void arch_program_segment_loaded(void const *addr, size_t len) { dcache_clean_invalidate_by_mva(addr, len); icache_invalidate_all(); }