|  | @@ -461,3 +461,173 @@ static void aurora_pa_range(unsigned long start, unsigned long end,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	raw_spin_lock_irqsave(&l2x0_lock, flags);
 | 
	
		
			
				|  |  |  	writel_relaxed(start, l2x0_base + AURORA_RANGE_BASE_ADDR_REG);
 | 
	
		
			
				|  |  | +	writel_relaxed(end, l2x0_base + offset);
 | 
	
		
			
				|  |  | +	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	cache_sync();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void aurora_inv_range(unsigned long start, unsigned long end)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * round start and end adresses up to cache line size
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	start &= ~(CACHE_LINE_SIZE - 1);
 | 
	
		
			
				|  |  | +	end = ALIGN(end, CACHE_LINE_SIZE);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * Invalidate all full cache lines between 'start' and 'end'.
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	while (start < end) {
 | 
	
		
			
				|  |  | +		unsigned long range_end = calc_range_end(start, end);
 | 
	
		
			
				|  |  | +		aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
 | 
	
		
			
				|  |  | +				AURORA_INVAL_RANGE_REG);
 | 
	
		
			
				|  |  | +		start = range_end;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void aurora_clean_range(unsigned long start, unsigned long end)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	/*
 | 
	
		
			
				|  |  | +	 * If L2 is forced to WT, the L2 will always be clean and we
 | 
	
		
			
				|  |  | +	 * don't need to do anything here.
 | 
	
		
			
				|  |  | +	 */
 | 
	
		
			
				|  |  | +	if (!l2_wt_override) {
 | 
	
		
			
				|  |  | +		start &= ~(CACHE_LINE_SIZE - 1);
 | 
	
		
			
				|  |  | +		end = ALIGN(end, CACHE_LINE_SIZE);
 | 
	
		
			
				|  |  | +		while (start != end) {
 | 
	
		
			
				|  |  | +			unsigned long range_end = calc_range_end(start, end);
 | 
	
		
			
				|  |  | +			aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
 | 
	
		
			
				|  |  | +					AURORA_CLEAN_RANGE_REG);
 | 
	
		
			
				|  |  | +			start = range_end;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void aurora_flush_range(unsigned long start, unsigned long end)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	start &= ~(CACHE_LINE_SIZE - 1);
 | 
	
		
			
				|  |  | +	end = ALIGN(end, CACHE_LINE_SIZE);
 | 
	
		
			
				|  |  | +	while (start != end) {
 | 
	
		
			
				|  |  | +		unsigned long range_end = calc_range_end(start, end);
 | 
	
		
			
				|  |  | +		/*
 | 
	
		
			
				|  |  | +		 * If L2 is forced to WT, the L2 will always be clean and we
 | 
	
		
			
				|  |  | +		 * just need to invalidate.
 | 
	
		
			
				|  |  | +		 */
 | 
	
		
			
				|  |  | +		if (l2_wt_override)
 | 
	
		
			
				|  |  | +			aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
 | 
	
		
			
				|  |  | +							AURORA_INVAL_RANGE_REG);
 | 
	
		
			
				|  |  | +		else
 | 
	
		
			
				|  |  | +			aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
 | 
	
		
			
				|  |  | +							AURORA_FLUSH_RANGE_REG);
 | 
	
		
			
				|  |  | +		start = range_end;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void __init l2x0_of_setup(const struct device_node *np,
 | 
	
		
			
				|  |  | +				 u32 *aux_val, u32 *aux_mask)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	u32 data[2] = { 0, 0 };
 | 
	
		
			
				|  |  | +	u32 tag = 0;
 | 
	
		
			
				|  |  | +	u32 dirty = 0;
 | 
	
		
			
				|  |  | +	u32 val = 0, mask = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	of_property_read_u32(np, "arm,tag-latency", &tag);
 | 
	
		
			
				|  |  | +	if (tag) {
 | 
	
		
			
				|  |  | +		mask |= L2X0_AUX_CTRL_TAG_LATENCY_MASK;
 | 
	
		
			
				|  |  | +		val |= (tag - 1) << L2X0_AUX_CTRL_TAG_LATENCY_SHIFT;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	of_property_read_u32_array(np, "arm,data-latency",
 | 
	
		
			
				|  |  | +				   data, ARRAY_SIZE(data));
 | 
	
		
			
				|  |  | +	if (data[0] && data[1]) {
 | 
	
		
			
				|  |  | +		mask |= L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK |
 | 
	
		
			
				|  |  | +			L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK;
 | 
	
		
			
				|  |  | +		val |= ((data[0] - 1) << L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT) |
 | 
	
		
			
				|  |  | +		       ((data[1] - 1) << L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	of_property_read_u32(np, "arm,dirty-latency", &dirty);
 | 
	
		
			
				|  |  | +	if (dirty) {
 | 
	
		
			
				|  |  | +		mask |= L2X0_AUX_CTRL_DIRTY_LATENCY_MASK;
 | 
	
		
			
				|  |  | +		val |= (dirty - 1) << L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	*aux_val &= ~mask;
 | 
	
		
			
				|  |  | +	*aux_val |= val;
 | 
	
		
			
				|  |  | +	*aux_mask &= ~mask;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void __init pl310_of_setup(const struct device_node *np,
 | 
	
		
			
				|  |  | +				  u32 *aux_val, u32 *aux_mask)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	u32 data[3] = { 0, 0, 0 };
 | 
	
		
			
				|  |  | +	u32 tag[3] = { 0, 0, 0 };
 | 
	
		
			
				|  |  | +	u32 filter[2] = { 0, 0 };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag));
 | 
	
		
			
				|  |  | +	if (tag[0] && tag[1] && tag[2])
 | 
	
		
			
				|  |  | +		writel_relaxed(
 | 
	
		
			
				|  |  | +			((tag[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) |
 | 
	
		
			
				|  |  | +			((tag[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) |
 | 
	
		
			
				|  |  | +			((tag[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT),
 | 
	
		
			
				|  |  | +			l2x0_base + L2X0_TAG_LATENCY_CTRL);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	of_property_read_u32_array(np, "arm,data-latency",
 | 
	
		
			
				|  |  | +				   data, ARRAY_SIZE(data));
 | 
	
		
			
				|  |  | +	if (data[0] && data[1] && data[2])
 | 
	
		
			
				|  |  | +		writel_relaxed(
 | 
	
		
			
				|  |  | +			((data[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) |
 | 
	
		
			
				|  |  | +			((data[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) |
 | 
	
		
			
				|  |  | +			((data[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT),
 | 
	
		
			
				|  |  | +			l2x0_base + L2X0_DATA_LATENCY_CTRL);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	of_property_read_u32_array(np, "arm,filter-ranges",
 | 
	
		
			
				|  |  | +				   filter, ARRAY_SIZE(filter));
 | 
	
		
			
				|  |  | +	if (filter[1]) {
 | 
	
		
			
				|  |  | +		writel_relaxed(ALIGN(filter[0] + filter[1], SZ_1M),
 | 
	
		
			
				|  |  | +			       l2x0_base + L2X0_ADDR_FILTER_END);
 | 
	
		
			
				|  |  | +		writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L2X0_ADDR_FILTER_EN,
 | 
	
		
			
				|  |  | +			       l2x0_base + L2X0_ADDR_FILTER_START);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void __init pl310_save(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	u32 l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
 | 
	
		
			
				|  |  | +		L2X0_CACHE_ID_RTL_MASK;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	l2x0_saved_regs.tag_latency = readl_relaxed(l2x0_base +
 | 
	
		
			
				|  |  | +		L2X0_TAG_LATENCY_CTRL);
 | 
	
		
			
				|  |  | +	l2x0_saved_regs.data_latency = readl_relaxed(l2x0_base +
 | 
	
		
			
				|  |  | +		L2X0_DATA_LATENCY_CTRL);
 | 
	
		
			
				|  |  | +	l2x0_saved_regs.filter_end = readl_relaxed(l2x0_base +
 | 
	
		
			
				|  |  | +		L2X0_ADDR_FILTER_END);
 | 
	
		
			
				|  |  | +	l2x0_saved_regs.filter_start = readl_relaxed(l2x0_base +
 | 
	
		
			
				|  |  | +		L2X0_ADDR_FILTER_START);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) {
 | 
	
		
			
				|  |  | +		/*
 | 
	
		
			
				|  |  | +		 * From r2p0, there is Prefetch offset/control register
 | 
	
		
			
				|  |  | +		 */
 | 
	
		
			
				|  |  | +		l2x0_saved_regs.prefetch_ctrl = readl_relaxed(l2x0_base +
 | 
	
		
			
				|  |  | +			L2X0_PREFETCH_CTRL);
 | 
	
		
			
				|  |  | +		/*
 | 
	
		
			
				|  |  | +		 * From r3p0, there is Power control register
 | 
	
		
			
				|  |  | +		 */
 | 
	
		
			
				|  |  | +		if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0)
 | 
	
		
			
				|  |  | +			l2x0_saved_regs.pwr_ctrl = readl_relaxed(l2x0_base +
 | 
	
		
			
				|  |  | +				L2X0_POWER_CTRL);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void aurora_save(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	l2x0_saved_regs.ctrl = readl_relaxed(l2x0_base + L2X0_CTRL);
 | 
	
		
			
				|  |  | +	l2x0_saved_regs.aux_ctrl = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void l2x0_resume(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
 | 
	
		
			
				|  |  | +		/* restore aux ctrl and enable l2 */
 |