xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/midgard/platform/vexpress/mali_kbase_cpu_vexpress.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  *
3  * (C) COPYRIGHT 2011-2016 ARM Limited. All rights reserved.
4  *
5  * This program is free software and is provided to you under the terms of the
6  * GNU General Public License version 2 as published by the Free Software
7  * Foundation, and any use by you of this program is subject to the terms
8  * of such GNU licence.
9  *
10  * A copy of the licence is included with the program, and can also be obtained
11  * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
12  * Boston, MA  02110-1301, USA.
13  *
14  */
15 
16 
17 
18 #include <linux/io.h>
19 #include <mali_kbase.h>
20 #include "mali_kbase_cpu_vexpress.h"
21 
22 #define HZ_IN_MHZ (1000000)
23 
24 #define CORETILE_EXPRESS_A9X4_SCC_START	(0x100E2000)
25 #define MOTHERBOARD_SYS_CFG_START	(0x10000000)
26 #define SYS_CFGDATA_OFFSET		(0x000000A0)
27 #define SYS_CFGCTRL_OFFSET		(0x000000A4)
28 #define SYS_CFGSTAT_OFFSET		(0x000000A8)
29 
30 #define SYS_CFGCTRL_START_BIT_VALUE		(1 << 31)
31 #define READ_REG_BIT_VALUE			(0 << 30)
32 #define DCC_DEFAULT_BIT_VALUE			(0 << 26)
33 #define SYS_CFG_OSC_FUNC_BIT_VALUE		(1 << 20)
34 #define SITE_DEFAULT_BIT_VALUE			(1 << 16)
35 #define BOARD_STACK_POS_DEFAULT_BIT_VALUE	(0 << 12)
36 #define DEVICE_DEFAULT_BIT_VALUE		(2 <<  0)
37 #define SYS_CFG_COMPLETE_BIT_VALUE		(1 <<  0)
38 #define SYS_CFG_ERROR_BIT_VALUE			(1 <<  1)
39 
40 #define FEED_REG_BIT_MASK			(0x0F)
41 #define FCLK_PA_DIVIDE_BIT_SHIFT		(0x03)
42 #define FCLK_PB_DIVIDE_BIT_SHIFT		(0x07)
43 #define FCLK_PC_DIVIDE_BIT_SHIFT		(0x0B)
44 #define AXICLK_PA_DIVIDE_BIT_SHIFT		(0x0F)
45 #define AXICLK_PB_DIVIDE_BIT_SHIFT		(0x13)
46 
47 /* the following three values used for reading
48  * HBI value of the LogicTile daughterboard */
49 #define VE_MOTHERBOARD_PERIPHERALS_SMB_CS7 (0x10000000)
50 #define VE_SYS_PROC_ID1_OFFSET (0x00000088)
51 #define VE_LOGIC_TILE_HBI_MASK (0x00000FFF)
52 
53 #define IS_SINGLE_BIT_SET(val, pos) (val&(1<<pos))
54 
55 /**
56  * Values used for determining the GPU frequency based on the LogicTile type
57  * Used by the function kbase_get_platform_logic_tile_type
58  */
59 #define VE_VIRTEX6_GPU_FREQ_MIN 5000
60 #define VE_VIRTEX6_GPU_FREQ_MAX 5000
61 #define VE_VIRTEX7_GPU_FREQ_MIN 40000
62 #define VE_VIRTEX7_GPU_FREQ_MAX 40000
63 #define VE_DEFAULT_GPU_FREQ_MIN 5000
64 #define VE_DEFAULT_GPU_FREQ_MAX 5000
65 
66 
67 #define CPU_CLOCK_SPEED_UNDEFINED (0)
68 
69 static u32 cpu_clock_speed = CPU_CLOCK_SPEED_UNDEFINED;
70 
71 static DEFINE_RAW_SPINLOCK(syscfg_lock);
72 /**
73  * kbase_get_vendor_specific_cpu_clock_speed -Retrieves the CPU clock speed
74  * @cpu_clock - the value of CPU clock speed in MHz
75  *
76  * Returns 0 on success, error code otherwise.
77  *
78  * The implementation is platform specific.
79 */
kbase_get_vexpress_cpu_clock_speed(u32 * cpu_clock)80 int kbase_get_vexpress_cpu_clock_speed(u32 *cpu_clock)
81 {
82 	int err = 0;
83 	u32 reg_val = 0;
84 	u32 osc2_value = 0;
85 	u32 pa_divide = 0;
86 	u32 pb_divide = 0;
87 	u32 pc_divide = 0;
88 	void __iomem *syscfg_reg = NULL;
89 	void __iomem *scc_reg = NULL;
90 
91 	if (CPU_CLOCK_SPEED_UNDEFINED != cpu_clock_speed) {
92 		*cpu_clock = cpu_clock_speed;
93 		return 0;
94 	}
95 
96 	/* Init the value in case something goes wrong */
97 	*cpu_clock = 0;
98 
99 	/* Map CPU register into virtual memory */
100 	syscfg_reg = ioremap(MOTHERBOARD_SYS_CFG_START, 0x1000);
101 	if (syscfg_reg == NULL) {
102 		err = -EIO;
103 		goto syscfg_reg_map_failed;
104 	}
105 
106 	scc_reg = ioremap(CORETILE_EXPRESS_A9X4_SCC_START, 0x1000);
107 	if (scc_reg == NULL) {
108 		err = -EIO;
109 		goto scc_reg_map_failed;
110 	}
111 
112 	raw_spin_lock(&syscfg_lock);
113 
114 	/* Read SYS regs - OSC2 */
115 	reg_val = readl(syscfg_reg + SYS_CFGCTRL_OFFSET);
116 
117 	/* Check if there is any other undergoing request */
118 	if (reg_val & SYS_CFGCTRL_START_BIT_VALUE) {
119 		err = -EBUSY;
120 		goto ongoing_request;
121 	}
122 	/* Reset the CGFGSTAT reg */
123 	writel(0, (syscfg_reg + SYS_CFGSTAT_OFFSET));
124 
125 	writel(SYS_CFGCTRL_START_BIT_VALUE | READ_REG_BIT_VALUE |
126 			DCC_DEFAULT_BIT_VALUE |
127 			SYS_CFG_OSC_FUNC_BIT_VALUE |
128 			SITE_DEFAULT_BIT_VALUE |
129 			BOARD_STACK_POS_DEFAULT_BIT_VALUE |
130 			DEVICE_DEFAULT_BIT_VALUE,
131 			(syscfg_reg + SYS_CFGCTRL_OFFSET));
132 	/* Wait for the transaction to complete */
133 	while (!(readl(syscfg_reg + SYS_CFGSTAT_OFFSET) &
134 			SYS_CFG_COMPLETE_BIT_VALUE))
135 		;
136 	/* Read SYS_CFGSTAT Register to get the status of submitted
137 	 * transaction */
138 	reg_val = readl(syscfg_reg + SYS_CFGSTAT_OFFSET);
139 
140 	if (reg_val & SYS_CFG_ERROR_BIT_VALUE) {
141 		/* Error while setting register */
142 		err = -EIO;
143 		goto set_reg_error;
144 	}
145 
146 	osc2_value = readl(syscfg_reg + SYS_CFGDATA_OFFSET);
147 	/* Read the SCC CFGRW0 register */
148 	reg_val = readl(scc_reg);
149 
150 	/*
151 	 * Select the appropriate feed:
152 	 * CFGRW0[0] - CLKOB
153 	 * CFGRW0[1] - CLKOC
154 	 * CFGRW0[2] - FACLK (CLK)B FROM AXICLK PLL)
155 	 */
156 	/* Calculate the  FCLK */
157 	if (IS_SINGLE_BIT_SET(reg_val, 0)) {
158 		/* CFGRW0[0] - CLKOB */
159 		/* CFGRW0[6:3] */
160 		pa_divide = ((reg_val & (FEED_REG_BIT_MASK <<
161 				FCLK_PA_DIVIDE_BIT_SHIFT)) >>
162 				FCLK_PA_DIVIDE_BIT_SHIFT);
163 		/* CFGRW0[10:7] */
164 		pb_divide = ((reg_val & (FEED_REG_BIT_MASK <<
165 				FCLK_PB_DIVIDE_BIT_SHIFT)) >>
166 				FCLK_PB_DIVIDE_BIT_SHIFT);
167 		*cpu_clock = osc2_value * (pa_divide + 1) / (pb_divide + 1);
168 	} else if (IS_SINGLE_BIT_SET(reg_val, 1)) {
169 		/* CFGRW0[1] - CLKOC */
170 		/* CFGRW0[6:3] */
171 		pa_divide = ((reg_val & (FEED_REG_BIT_MASK <<
172 				FCLK_PA_DIVIDE_BIT_SHIFT)) >>
173 				FCLK_PA_DIVIDE_BIT_SHIFT);
174 		/* CFGRW0[14:11] */
175 		pc_divide = ((reg_val & (FEED_REG_BIT_MASK <<
176 				FCLK_PC_DIVIDE_BIT_SHIFT)) >>
177 				FCLK_PC_DIVIDE_BIT_SHIFT);
178 		*cpu_clock = osc2_value * (pa_divide + 1) / (pc_divide + 1);
179 	} else if (IS_SINGLE_BIT_SET(reg_val, 2)) {
180 		/* CFGRW0[2] - FACLK */
181 		/* CFGRW0[18:15] */
182 		pa_divide = ((reg_val & (FEED_REG_BIT_MASK <<
183 				AXICLK_PA_DIVIDE_BIT_SHIFT)) >>
184 				AXICLK_PA_DIVIDE_BIT_SHIFT);
185 		/* CFGRW0[22:19] */
186 		pb_divide = ((reg_val & (FEED_REG_BIT_MASK <<
187 				AXICLK_PB_DIVIDE_BIT_SHIFT)) >>
188 				AXICLK_PB_DIVIDE_BIT_SHIFT);
189 		*cpu_clock = osc2_value * (pa_divide + 1) / (pb_divide + 1);
190 	} else {
191 		err = -EIO;
192 	}
193 
194 set_reg_error:
195 ongoing_request:
196 	raw_spin_unlock(&syscfg_lock);
197 	*cpu_clock /= HZ_IN_MHZ;
198 
199 	if (!err)
200 		cpu_clock_speed = *cpu_clock;
201 
202 	iounmap(scc_reg);
203 
204 scc_reg_map_failed:
205 	iounmap(syscfg_reg);
206 
207 syscfg_reg_map_failed:
208 
209 	return err;
210 }
211 
212 /**
213  * kbase_get_platform_logic_tile_type -  determines which LogicTile type
214  * is used by Versatile Express
215  *
216  * When platform_config build parameter is specified as vexpress, i.e.,
217  * platform_config=vexpress, GPU frequency may vary dependent on the
218  * particular platform. The GPU frequency depends on the LogicTile type.
219  *
220  * This function determines which LogicTile type is used by the platform by
221  * reading the HBI value of the daughterboard which holds the LogicTile:
222  *
223  * 0x217 HBI0217 Virtex-6
224  * 0x192 HBI0192 Virtex-5
225  * 0x247 HBI0247 Virtex-7
226  *
227  * Return: HBI value of the logic tile daughterboard, zero if not accessible
228  */
kbase_get_platform_logic_tile_type(void)229 static u32 kbase_get_platform_logic_tile_type(void)
230 {
231 	void __iomem *syscfg_reg = NULL;
232 	u32 sys_procid1 = 0;
233 
234 	syscfg_reg = ioremap(VE_MOTHERBOARD_PERIPHERALS_SMB_CS7 + VE_SYS_PROC_ID1_OFFSET, 4);
235 	if (NULL != syscfg_reg) {
236 		sys_procid1 = readl(syscfg_reg);
237 		iounmap(syscfg_reg);
238 	}
239 
240 	return sys_procid1 & VE_LOGIC_TILE_HBI_MASK;
241 }
242 
kbase_get_platform_min_freq(void)243 u32 kbase_get_platform_min_freq(void)
244 {
245 	u32 ve_logic_tile = kbase_get_platform_logic_tile_type();
246 
247 	switch (ve_logic_tile) {
248 	case 0x217:
249 		/* Virtex 6, HBI0217 */
250 		return VE_VIRTEX6_GPU_FREQ_MIN;
251 	case 0x247:
252 		/* Virtex 7, HBI0247 */
253 		return VE_VIRTEX7_GPU_FREQ_MIN;
254 	default:
255 		/* all other logic tiles, i.e., Virtex 5 HBI0192
256 		 * or unsuccessful reading from the platform -
257 		 * fall back to some default value */
258 		return VE_DEFAULT_GPU_FREQ_MIN;
259 	}
260 }
261 
kbase_get_platform_max_freq(void)262 u32 kbase_get_platform_max_freq(void)
263 {
264 	u32 ve_logic_tile = kbase_get_platform_logic_tile_type();
265 
266 	switch (ve_logic_tile) {
267 	case 0x217:
268 		/* Virtex 6, HBI0217 */
269 		return VE_VIRTEX6_GPU_FREQ_MAX;
270 	case 0x247:
271 		/* Virtex 7, HBI0247 */
272 		return VE_VIRTEX7_GPU_FREQ_MAX;
273 	default:
274 		/* all other logic tiles, i.e., Virtex 5 HBI0192
275 		 * or unsuccessful reading from the platform -
276 		 * fall back to some default value */
277 		return VE_DEFAULT_GPU_FREQ_MAX;
278 	}
279 }
280