Beispiel #1
0
static void kgsl_ringbuffer_submit(struct kgsl_ringbuffer *rb)
{
	BUG_ON(rb->wptr == 0);

	GSL_RB_UPDATE_WPTR_POLLING(rb);
	/* Drain write buffer and data memory barrier */
	dsb();
	wmb();

	/* Memory fence to ensure all data has posted.  On some systems,
	* like 7x27, the register block is not allocated as strongly ordered
	* memory.  Adding a memory fence ensures ordering during ringbuffer
	* submits.*/
	mb();
	outer_sync();

	kgsl_yamato_regwrite(rb->device, REG_CP_RB_WPTR, rb->wptr);

	rb->flags |= KGSL_FLAGS_ACTIVE;
}
/* Set the DDR to either 528MHz or 400MHz for MX6q
 * or 400MHz for MX6DL.
 */
int set_high_bus_freq(int high_bus_freq)
{
	if (bus_freq_scaling_initialized && bus_freq_scaling_is_active)
		cancel_delayed_work_sync(&low_bus_freq_handler);

	if (busfreq_suspended)
		return 0;


	if (!bus_freq_scaling_initialized || !bus_freq_scaling_is_active)
		return 0;

	if (cpu_is_mx6sl())
		high_bus_freq = 1;

	if (high_bus_freq_mode && high_bus_freq)
		return 0;


	/* medium bus freq is only supported for MX6DQ */
	if (cpu_is_mx6q() && med_bus_freq_mode && !high_bus_freq)
		return 0;

	if (cpu_is_mx6dl() && high_bus_freq)
		high_bus_freq = 0;

	if (cpu_is_mx6dl() && med_bus_freq_mode)
		return 0;

	if ((high_bus_freq_mode && (high_bus_freq || lp_high_freq)) ||
	    (med_bus_freq_mode && !high_bus_freq && lp_med_freq &&
	     !lp_high_freq))
		return 0;

	if (cpu_is_mx6sl()) {
		u32 reg;
		unsigned long flags;
		u32 ttbr1;

		spin_lock_irqsave(&freq_lock, flags);
		/* sync the outer cache. */
		outer_sync();

		ttbr1 = save_ttbr1();

		/* Change DDR freq in IRAM. */
		mx6sl_ddr_freq_change_iram(ddr_normal_rate, low_bus_freq_mode);

		restore_ttbr1(ttbr1);

		spin_unlock_irqrestore(&freq_lock, flags);

		/* Set periph_clk to be sourced from pll2_pfd2_400M */
		/* First need to set the divider before changing the */
		/* parent if parent clock is larger than previous one */
		clk_set_rate(ahb_clk, clk_round_rate(ahb_clk,
						     LPAPM_CLK / 3));
		clk_set_rate(axi_clk,
			     clk_round_rate(axi_clk, LPAPM_CLK / 2));
		clk_set_parent(periph_clk, pll2_400);

		if (low_bus_freq_mode) {
			/* Now move ARM to be sourced from PLL2_400 too. */
			clk_set_parent(pll1_sw_clk, pll2_400);

			/* Ensure that the clock will be at original speed. */
			reg = __raw_writel(org_arm_podf, MXC_CCM_CACRR);
			while (__raw_readl(MXC_CCM_CDHIPR))
				;
			clk_disable(pll1);
		}
		high_bus_freq_mode = 1;
		low_bus_freq_mode = 0;
		audio_bus_freq_mode = 0;
	} else {
		clk_enable(pll3);
		if (high_bus_freq) {
			update_ddr_freq(ddr_normal_rate);
			/* Make sure periph clk's parent also got updated */
			clk_set_parent(periph_clk, pll2);
			if (med_bus_freq_mode)
				clk_disable(pll2_400);
			high_bus_freq_mode = 1;
			med_bus_freq_mode = 0;
		} else {
			clk_enable(pll2_400);
			update_ddr_freq(ddr_med_rate);
			/* Make sure periph clk's parent also got updated */
			clk_set_parent(periph_clk, pll2_400);
			high_bus_freq_mode = 0;
			med_bus_freq_mode = 1;
		}
		if (audio_bus_freq_mode)
			clk_disable(pll2_400);

		/* AXI_CLK is sourced from PLL3_PFD_540 on MX6DL */
		if (cpu_is_mx6dl() &&
			clk_get_parent(axi_clk) != pll3_540)
			clk_set_parent(axi_clk, pll3_540);

		low_bus_freq_mode = 0;
		audio_bus_freq_mode = 0;

		clk_disable(pll3);
	}
	return 0;
}
void reduce_bus_freq(void)
{
	if (!cpu_is_mx6sl()) {
		if (cpu_is_mx6dl() &&
			(clk_get_parent(axi_clk) != periph_clk))
			/* Set the axi_clk to be sourced from the periph_clk.
			  * So that its frequency can be lowered down to 50MHz
			  * or 24MHz as the case may be.
			  */
			clk_set_parent(axi_clk, periph_clk);

		clk_enable(pll3);
		if (lp_audio_freq) {
			/* Need to ensure that PLL2_PFD_400M is kept ON. */
			clk_enable(pll2_400);
			update_ddr_freq(DDR_AUDIO_CLK);
			/* Make sure periph clk's parent also got updated */
			clk_set_parent(periph_clk, pll2_200);
			audio_bus_freq_mode = 1;
			low_bus_freq_mode = 0;
		} else {
			update_ddr_freq(LPAPM_CLK);
			/* Make sure periph clk's parent also got updated */
			clk_set_parent(periph_clk, osc_clk);
			if (audio_bus_freq_mode)
				clk_disable(pll2_400);
			low_bus_freq_mode = 1;
			audio_bus_freq_mode = 0;
		}

		if (med_bus_freq_mode)
			clk_disable(pll2_400);

		clk_disable(pll3);
		med_bus_freq_mode = 0;
	} else {
		u32 reg;
		u32  div;
		unsigned long flags;

		if (high_bus_freq_mode) {
			/* Set periph_clk to be sourced from OSC_CLK */
			/* Set AXI to 24MHz. */
			clk_set_parent(periph_clk, osc_clk);
			clk_set_rate(axi_clk,
				clk_round_rate(axi_clk, LPAPM_CLK));
			/* Set AHB to 24MHz. */
			clk_set_rate(ahb_clk,
				clk_round_rate(ahb_clk, LPAPM_CLK));
		}
		if (lp_audio_freq) {
			u32 ttbr1;
			/* PLL2 is on in this mode, as DDR is at 100MHz. */
			/* Now change DDR freq while running from IRAM. */

			/* Set AHB to 24MHz. */
			clk_set_rate(ahb_clk,
				clk_round_rate(ahb_clk, LPAPM_CLK / 3));

			spin_lock_irqsave(&freq_lock, flags);
			/* sync the outer cache. */
			outer_sync();

			/* Save TTBR1 */
			ttbr1 = save_ttbr1();

			mx6sl_ddr_freq_change_iram(DDR_AUDIO_CLK,
							low_bus_freq_mode);
			restore_ttbr1(ttbr1);

			spin_unlock_irqrestore(&freq_lock, flags);

			if (low_bus_freq_mode) {
				/* Swtich ARM to run off PLL2_PFD2_400MHz
				 * since DDR is anyway at 100MHz.
				 */
				clk_set_parent(pll1_sw_clk, pll2_400);

				/* Ensure that the clock will be
				  * at original speed.
				  */
				reg = __raw_writel(org_arm_podf, MXC_CCM_CACRR);
				while (__raw_readl(MXC_CCM_CDHIPR))
					;
				/* We have enabled PLL1 in the code below when
				  * ARM is from PLL1, so disable it here.
				  */
				clk_disable(pll1);
			}
			low_bus_freq_mode = 0;
			audio_bus_freq_mode = 1;
		} else {
			u32 ttbr1;
			/* Set MMDC clk to 24MHz. */
			/* Since we are going to set PLL2 in bypass mode,
			  * move the CPU clock off PLL2.
			  */
			/* Ensure that the clock will be at
			  * lowest possible freq.
			  */
			org_arm_podf = __raw_readl(MXC_CCM_CACRR);
			/* Need to enable PLL1 before setting its rate. */
			clk_enable(pll1);
			clk_set_rate(pll1,
				cpu_op_tbl[cpu_op_nr - 1].pll_lpm_rate);
			div = clk_get_rate(pll1) /
					cpu_op_tbl[cpu_op_nr - 1].cpu_rate;

			reg = __raw_writel(div - 1, MXC_CCM_CACRR);
			while (__raw_readl(MXC_CCM_CDHIPR))
				;
			clk_set_parent(pll1_sw_clk, pll1);

			spin_lock_irqsave(&freq_lock, flags);
			/* sync the outer cache. */
			outer_sync();

			ttbr1 = save_ttbr1();
			/* Now change DDR freq while running from IRAM. */
			mx6sl_ddr_freq_change_iram(LPAPM_CLK,
					low_bus_freq_mode);
			restore_ttbr1(ttbr1);

			spin_unlock_irqrestore(&freq_lock, flags);

			low_bus_freq_mode = 1;
			audio_bus_freq_mode = 0;
		}
	}
	high_bus_freq_mode = 0;

}
Beispiel #4
0
static ssize_t outer_sync_store(struct device_driver *driver, const char *buf, size_t count)
{
    outer_sync();

    return count;
}
static uint32_t
kgsl_ringbuffer_addcmds(struct kgsl_ringbuffer *rb,
				unsigned int flags, unsigned int *cmds,
				int sizedwords)
{
	unsigned int *ringcmds;
	unsigned int timestamp;
	unsigned int total_sizedwords = sizedwords + 6;
	unsigned int i;
	unsigned int rcmd_gpu;

	/* reserve space to temporarily turn off protected mode
	*  error checking if needed
	*/
	total_sizedwords += flags & KGSL_CMD_FLAGS_PMODE ? 4 : 0;
	total_sizedwords += !(flags & KGSL_CMD_FLAGS_NO_TS_CMP) ? 7 : 0;
	total_sizedwords += (flags & KGSL_CMD_FLAGS_CONTEXT_CHANGE) ? 2 : 0;

	ringcmds = kgsl_ringbuffer_allocspace(rb, total_sizedwords);
	rcmd_gpu = rb->buffer_desc.gpuaddr
		+ sizeof(uint)*(rb->wptr-total_sizedwords);

	if (flags & KGSL_CMD_FLAGS_CONTEXT_CHANGE) {
		GSL_RB_WRITE(ringcmds, rcmd_gpu, pm4_nop_packet(1));
		GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_CTXT_IDENTIFIER);
	}

	if (flags & KGSL_CMD_FLAGS_PMODE) {
		/* disable protected mode error checking */
		GSL_RB_WRITE(ringcmds, rcmd_gpu,
			pm4_type3_packet(PM4_SET_PROTECTED_MODE, 1));
		GSL_RB_WRITE(ringcmds, rcmd_gpu, 0);
	}

	for (i = 0; i < sizedwords; i++) {
		GSL_RB_WRITE(ringcmds, rcmd_gpu, *cmds);
		cmds++;
	}

	if (flags & KGSL_CMD_FLAGS_PMODE) {
		/* re-enable protected mode error checking */
		GSL_RB_WRITE(ringcmds, rcmd_gpu,
			pm4_type3_packet(PM4_SET_PROTECTED_MODE, 1));
		GSL_RB_WRITE(ringcmds, rcmd_gpu, 1);
	}

	rb->timestamp++;
	timestamp = rb->timestamp;

	/* start-of-pipeline and end-of-pipeline timestamps */
	GSL_RB_WRITE(ringcmds, rcmd_gpu, pm4_type0_packet(REG_CP_TIMESTAMP, 1));
	GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp);
	GSL_RB_WRITE(ringcmds, rcmd_gpu, pm4_type3_packet(PM4_EVENT_WRITE, 3));
	GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
	GSL_RB_WRITE(ringcmds, rcmd_gpu,
		     (rb->device->memstore.gpuaddr +
		      KGSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp)));
	GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp);

	/*memory barriers added for the timestamp update*/
	mb();
	dsb();
	outer_sync();

	if (!(flags & KGSL_CMD_FLAGS_NO_TS_CMP)) {
		/* Conditional execution based on memory values */
		GSL_RB_WRITE(ringcmds, rcmd_gpu,
			pm4_type3_packet(PM4_COND_EXEC, 4));
		GSL_RB_WRITE(ringcmds, rcmd_gpu, (rb->device->memstore.gpuaddr +
			KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable)) >> 2);
		GSL_RB_WRITE(ringcmds, rcmd_gpu, (rb->device->memstore.gpuaddr +
			KGSL_DEVICE_MEMSTORE_OFFSET(ref_wait_ts)) >> 2);
		GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp);
		/* # of conditional command DWORDs */
		GSL_RB_WRITE(ringcmds, rcmd_gpu, 2);
		GSL_RB_WRITE(ringcmds, rcmd_gpu,
			pm4_type3_packet(PM4_INTERRUPT, 1));
		GSL_RB_WRITE(ringcmds, rcmd_gpu, CP_INT_CNTL__RB_INT_MASK);
	}