| 
					
				 | 
			
			
				@@ -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 */ 
			 |