Exemple #1
0
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);
}
Exemple #2
0
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;
}
Exemple #3
0
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);
}
Exemple #4
0
void arch_program_segment_loaded(void const *addr, size_t len)
{
	dcache_clean_invalidate_by_mva(addr, len);
	icache_invalidate_all();
}