void t3_disable_la_scaling(enum tegra_la_id id)
{
	unsigned long reg;
	void __iomem *scaling_enable_reg =
				(void __iomem *)(T3_MC_RA(ARB_OVERRIDE));
	int idx;

	BUG_ON(id >= TEGRA_LA_MAX_ID);
	idx = cs->id_to_index[id];
	BUG_ON(cs->la_info_array[idx].id != id);

	if (cs->la_info_array[idx].scaling_supported == false)
		return;
	spin_lock(&cs->lock);
	la_debug("\n%s: id=%d", __func__, id);
	cs->scaling_info[idx].scaling_ref_count--;
	BUG_ON(cs->scaling_info[idx].scaling_ref_count < 0);

	if (!--cs->la_scaling_enable_count) {
		reg = readl(scaling_enable_reg);
		reg = reg & ~(1 << GLOBAL_LATENCY_SCALING_ENABLE_BIT);
		writel(reg, scaling_enable_reg);
		la_debug("disabled scaling.");
	}
	spin_unlock(&cs->lock);
}
static void set_thresholds(struct la_scaling_reg_info *info,
			    enum tegra_la_id id)
{
	unsigned long reg_read;
	unsigned long reg_write;
	unsigned int thresh_low;
	unsigned int thresh_mid;
	unsigned int thresh_high;
	int la_set;
	int idx = cs->id_to_index[id];

	reg_read = readl(cs->la_info_array[idx].reg_addr);
	la_set = (reg_read & cs->la_info_array[idx].mask) >>
		 cs->la_info_array[idx].shift;
	/* la should be set before enabling scaling. */
	BUG_ON(la_set != cs->scaling_info[idx].la_set);

	thresh_low = (cs->scaling_info[idx].threshold_low * la_set) / 100;
	thresh_mid = (cs->scaling_info[idx].threshold_mid * la_set) / 100;
	thresh_high = (cs->scaling_info[idx].threshold_high * la_set) / 100;
	la_debug("%s: la_set=%d, thresh_low=%d(%d%%), thresh_mid=%d(%d%%),"
		" thresh_high=%d(%d%%) ", __func__, la_set,
		thresh_low, cs->scaling_info[idx].threshold_low,
		thresh_mid, cs->scaling_info[idx].threshold_mid,
		thresh_high, cs->scaling_info[idx].threshold_high);

	reg_read = readl(info->tl_reg_addr);
	reg_write = (reg_read & ~info->tl_mask) |
		(thresh_low << info->tl_shift);
	writel(reg_write, info->tl_reg_addr);
	la_debug("reg_addr=0x%x, read=0x%x, write=0x%x",
		(u32)info->tl_reg_addr, (u32)reg_read, (u32)reg_write);

	reg_read = readl(info->tm_reg_addr);
	reg_write = (reg_read & ~info->tm_mask) |
		(thresh_mid << info->tm_shift);
	writel(reg_write, info->tm_reg_addr);
	la_debug("reg_addr=0x%x, read=0x%x, write=0x%x",
		(u32)info->tm_reg_addr, (u32)reg_read, (u32)reg_write);

	reg_read = readl(info->th_reg_addr);
	reg_write = (reg_read & ~info->th_mask) |
		(thresh_high << info->th_shift);
	writel(reg_write, info->th_reg_addr);
	la_debug("reg_addr=0x%x, read=0x%x, write=0x%x",
		(u32)info->th_reg_addr, (u32)reg_read, (u32)reg_write);
}
Esempio n. 3
0
static void t11x_init_ptsa(void)
{
	struct clk *emc_clk __attribute__((unused));
	unsigned long emc_freq __attribute__((unused));
	unsigned long same_freq __attribute__((unused));
	unsigned long grant_dec __attribute__((unused));
	unsigned long ring1_rate __attribute__((unused));

	emc_clk = clk_get(NULL, "emc");
	la_debug("**** emc clk_rate=%luMHz", clk_get_rate(emc_clk)/1000000);

	emc_freq = clk_get_rate(emc_clk);
	emc_freq /= 1000000;
	/* Compute initial value for grant dec */
	same_freq = readl(T11X_MC_RA(EMEM_ARB_MISC0_0));
	same_freq = same_freq >> 27 & 1;
	grant_dec = 256 * (same_freq ? 2 : 1) * emc_freq;
	if (grant_dec > 511)
		grant_dec = 511;
	writel(grant_dec, T11X_MC_RA(PTSA_GRANT_DECREMENT_0));

	writel(0x3d, T11X_MC_RA(DIS_PTSA_MIN_0));
	writel(0x14, T11X_MC_RA(DIS_PTSA_MAX_0));

	writel(0x3d, T11X_MC_RA(DISB_PTSA_MIN_0));
	writel(0x14, T11X_MC_RA(DISB_PTSA_MAX_0));

	writel(t11x_get_ptsa_rate(T11X_MAX_CAMERA_BW_MHZ),
		T11X_MC_RA(VE_PTSA_RATE_0));
	writel(0x3d, T11X_MC_RA(VE_PTSA_MIN_0));
	writel(0x14, T11X_MC_RA(VE_PTSA_MAX_0));

	writel(0x01, T11X_MC_RA(RING2_PTSA_RATE_0));
	writel(0x3f, T11X_MC_RA(RING2_PTSA_MIN_0));
	writel(0x05, T11X_MC_RA(RING2_PTSA_MAX_0));

	writel(38 * emc_freq / T11X_BASE_EMC_FREQ_MHZ,
		T11X_MC_RA(MLL_MPCORER_PTSA_RATE_0));
	writel(0x3f, T11X_MC_RA(MLL_MPCORER_PTSA_MIN_0));
	writel(0x05, T11X_MC_RA(MLL_MPCORER_PTSA_MAX_0));

	writel(0x01, T11X_MC_RA(SMMU_SMMU_PTSA_RATE_0));
	writel(0x01, T11X_MC_RA(SMMU_SMMU_PTSA_MIN_0));
	writel(0x01, T11X_MC_RA(SMMU_SMMU_PTSA_MAX_0));

	ring1_rate = readl(T11X_MC_RA(DIS_PTSA_RATE_0)) +
		     readl(T11X_MC_RA(DISB_PTSA_RATE_0));
#if defined(CONFIG_TEGRA_ERRATA_977223)
	ring1_rate /= 2;
#endif
	ring1_rate += readl(T11X_MC_RA(VE_PTSA_RATE_0)) +
		      readl(T11X_MC_RA(RING2_PTSA_RATE_0));
	writel(ring1_rate, T11X_MC_RA(RING1_PTSA_RATE_0));
	writel(0x36, T11X_MC_RA(RING1_PTSA_MIN_0));
	writel(0x1f, T11X_MC_RA(RING1_PTSA_MAX_0));

	writel(0x00, T11X_MC_RA(DIS_EXTRA_SNAP_LEVELS_0));
	writel(0x03, T11X_MC_RA(HEG_EXTRA_SNAP_LEVELS_0));
}
/* Thresholds for scaling are specified in % of fifo freeness.
 * If threshold_low is specified as 20%, it means when the fifo free
 * between 0 to 20%, use la as programmed_la.
 * If threshold_mid is specified as 50%, it means when the fifo free
 * between 20 to 50%, use la as programmed_la/2 .
 * If threshold_high is specified as 80%, it means when the fifo free
 * between 50 to 80%, use la as programmed_la/4.
 * When the fifo is free between 80 to 100%, use la as 0(highest priority).
 */
int t3_enable_la_scaling(enum tegra_la_id id,
				    unsigned int threshold_low,
				    unsigned int threshold_mid,
				    unsigned int threshold_high)
{
	unsigned long reg;
	void __iomem *scaling_enable_reg =
				(void __iomem *)(T3_MC_RA(ARB_OVERRIDE));
	int idx = cs->id_to_index[id];

	VALIDATE_ID(id, cs);
	VALIDATE_THRESHOLDS(threshold_low, threshold_mid, threshold_high);

	if (cs->la_info_array[idx].scaling_supported == false)
		goto exit;

	spin_lock(&cs->lock);

	la_debug("\n%s: id=%d, tl=%d, tm=%d, th=%d", __func__,
		id, threshold_low, threshold_mid, threshold_high);
	cs->scaling_info[idx].threshold_low = threshold_low;
	cs->scaling_info[idx].threshold_mid = threshold_mid;
	cs->scaling_info[idx].threshold_high = threshold_high;
	cs->scaling_info[idx].scaling_ref_count++;

	if (id >= ID(DISPLAY_0A) && id <= ID(DISPLAY_1BB))
		set_disp_latency_thresholds(id);
	else if (id >= ID(VI_WSB) && id <= ID(VI_WY))
		set_vi_latency_thresholds(id);
	if (!cs->la_scaling_enable_count++) {
		reg = readl(scaling_enable_reg);
		reg |= (1 << GLOBAL_LATENCY_SCALING_ENABLE_BIT);
		writel(reg,  scaling_enable_reg);
		la_debug("enabled scaling.");
	}
	spin_unlock(&cs->lock);
exit:
	return 0;
}