3 * (C) COPYRIGHT 2011-2015 ARM Limited. All rights reserved.
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
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.
19 #include <mali_kbase.h>
20 #include "mali_kbase_cpu_vexpress.h"
22 #define HZ_IN_MHZ (1000000)
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)
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)
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)
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)
53 #define IS_SINGLE_BIT_SET(val, pos) (val&(1<<pos))
55 #define CPU_CLOCK_SPEED_UNDEFINED (0)
57 static u32 cpu_clock_speed = CPU_CLOCK_SPEED_UNDEFINED;
59 static DEFINE_RAW_SPINLOCK(syscfg_lock);
61 * kbase_get_vendor_specific_cpu_clock_speed -Retrieves the CPU clock speed
62 * @cpu_clock - the value of CPU clock speed in MHz
64 * Returns 0 on success, error code otherwise.
66 * The implementation is platform specific.
68 int kbase_get_vexpress_cpu_clock_speed(u32 *cpu_clock)
76 void __iomem *syscfg_reg = NULL;
77 void __iomem *scc_reg = NULL;
79 if (CPU_CLOCK_SPEED_UNDEFINED != cpu_clock_speed) {
80 *cpu_clock = cpu_clock_speed;
84 /* Init the value in case something goes wrong */
87 /* Map CPU register into virtual memory */
88 syscfg_reg = ioremap(MOTHERBOARD_SYS_CFG_START, 0x1000);
89 if (syscfg_reg == NULL) {
91 goto syscfg_reg_map_failed;
94 scc_reg = ioremap(CORETILE_EXPRESS_A9X4_SCC_START, 0x1000);
95 if (scc_reg == NULL) {
97 goto scc_reg_map_failed;
100 raw_spin_lock(&syscfg_lock);
102 /* Read SYS regs - OSC2 */
103 reg_val = readl(syscfg_reg + SYS_CFGCTRL_OFFSET);
105 /* Check if there is any other undergoing request */
106 if (reg_val & SYS_CFGCTRL_START_BIT_VALUE) {
108 goto ongoing_request;
110 /* Reset the CGFGSTAT reg */
111 writel(0, (syscfg_reg + SYS_CFGSTAT_OFFSET));
113 writel(SYS_CFGCTRL_START_BIT_VALUE | READ_REG_BIT_VALUE |
114 DCC_DEFAULT_BIT_VALUE |
115 SYS_CFG_OSC_FUNC_BIT_VALUE |
116 SITE_DEFAULT_BIT_VALUE |
117 BOARD_STACK_POS_DEFAULT_BIT_VALUE |
118 DEVICE_DEFAULT_BIT_VALUE,
119 (syscfg_reg + SYS_CFGCTRL_OFFSET));
120 /* Wait for the transaction to complete */
121 while (!(readl(syscfg_reg + SYS_CFGSTAT_OFFSET) &
122 SYS_CFG_COMPLETE_BIT_VALUE))
124 /* Read SYS_CFGSTAT Register to get the status of submitted
126 reg_val = readl(syscfg_reg + SYS_CFGSTAT_OFFSET);
128 if (reg_val & SYS_CFG_ERROR_BIT_VALUE) {
129 /* Error while setting register */
134 osc2_value = readl(syscfg_reg + SYS_CFGDATA_OFFSET);
135 /* Read the SCC CFGRW0 register */
136 reg_val = readl(scc_reg);
139 * Select the appropriate feed:
142 * CFGRW0[2] - FACLK (CLK)B FROM AXICLK PLL)
144 /* Calculate the FCLK */
145 if (IS_SINGLE_BIT_SET(reg_val, 0)) {
146 /* CFGRW0[0] - CLKOB */
148 pa_divide = ((reg_val & (FEED_REG_BIT_MASK <<
149 FCLK_PA_DIVIDE_BIT_SHIFT)) >>
150 FCLK_PA_DIVIDE_BIT_SHIFT);
152 pb_divide = ((reg_val & (FEED_REG_BIT_MASK <<
153 FCLK_PB_DIVIDE_BIT_SHIFT)) >>
154 FCLK_PB_DIVIDE_BIT_SHIFT);
155 *cpu_clock = osc2_value * (pa_divide + 1) / (pb_divide + 1);
156 } else if (IS_SINGLE_BIT_SET(reg_val, 1)) {
157 /* CFGRW0[1] - CLKOC */
159 pa_divide = ((reg_val & (FEED_REG_BIT_MASK <<
160 FCLK_PA_DIVIDE_BIT_SHIFT)) >>
161 FCLK_PA_DIVIDE_BIT_SHIFT);
163 pc_divide = ((reg_val & (FEED_REG_BIT_MASK <<
164 FCLK_PC_DIVIDE_BIT_SHIFT)) >>
165 FCLK_PC_DIVIDE_BIT_SHIFT);
166 *cpu_clock = osc2_value * (pa_divide + 1) / (pc_divide + 1);
167 } else if (IS_SINGLE_BIT_SET(reg_val, 2)) {
168 /* CFGRW0[2] - FACLK */
170 pa_divide = ((reg_val & (FEED_REG_BIT_MASK <<
171 AXICLK_PA_DIVIDE_BIT_SHIFT)) >>
172 AXICLK_PA_DIVIDE_BIT_SHIFT);
174 pb_divide = ((reg_val & (FEED_REG_BIT_MASK <<
175 AXICLK_PB_DIVIDE_BIT_SHIFT)) >>
176 AXICLK_PB_DIVIDE_BIT_SHIFT);
177 *cpu_clock = osc2_value * (pa_divide + 1) / (pb_divide + 1);
184 raw_spin_unlock(&syscfg_lock);
185 *cpu_clock /= HZ_IN_MHZ;
188 cpu_clock_speed = *cpu_clock;
195 syscfg_reg_map_failed:
200 u32 kbase_get_platform_logic_tile_type(void)
202 void __iomem *syscfg_reg = NULL;
205 syscfg_reg = ioremap(VE_MOTHERBOARD_PERIPHERALS_SMB_CS7 + VE_SYS_PROC_ID1_OFFSET, 4);
207 sys_procid1 = (NULL != syscfg_reg) ? readl(syscfg_reg) : 0;
209 return sys_procid1 & VE_LOGIC_TILE_HBI_MASK;