1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * sys_info.c
4  *
5  * System information functions
6  *
7  * Copyright (C) 2011, Texas Instruments, Incorporated - https://www.ti.com/
8  *
9  * Derived from Beagle Board and 3430 SDP code by
10  *      Richard Woodruff <r-woodruff2@ti.com>
11  *      Syed Mohammed Khasim <khasim@ti.com>
12  */
13 
14 #include <init.h>
15 #include <asm/io.h>
16 #include <asm/arch/sys_proto.h>
17 #include <asm/arch/cpu.h>
18 #include <asm/arch/clock.h>
19 #include <power/tps65910.h>
20 #include <linux/compiler.h>
21 
22 struct ctrl_stat *cstat = (struct ctrl_stat *)CTRL_BASE;
23 
24 /**
25  * get_cpu_rev(void) - extract rev info
26  */
get_cpu_rev(void)27 u32 get_cpu_rev(void)
28 {
29 	u32 id;
30 	u32 rev;
31 
32 	id = readl(DEVICE_ID);
33 	rev = (id >> 28) & 0xff;
34 
35 	return rev;
36 }
37 
38 /**
39  * get_cpu_type(void) - extract cpu info
40  */
get_cpu_type(void)41 u32 get_cpu_type(void)
42 {
43 	u32 id = 0;
44 	u32 partnum;
45 
46 	id = readl(DEVICE_ID);
47 	partnum = (id >> 12) & 0xffff;
48 
49 	return partnum;
50 }
51 
52 /**
53  * get_sysboot_value(void) - return SYS_BOOT[4:0]
54  */
get_sysboot_value(void)55 u32 get_sysboot_value(void)
56 {
57 	return readl(&cstat->statusreg) & SYSBOOT_MASK;
58 }
59 
get_sys_clk_index(void)60 u32 get_sys_clk_index(void)
61 {
62 	struct ctrl_stat *ctrl = (struct ctrl_stat *)CTRL_BASE;
63 	u32 ind = readl(&ctrl->statusreg);
64 
65 #ifdef CONFIG_AM43XX
66 	u32 src;
67 	src = (ind & CTRL_CRYSTAL_FREQ_SRC_MASK) >> CTRL_CRYSTAL_FREQ_SRC_SHIFT;
68 	if (src == CTRL_CRYSTAL_FREQ_SRC_EFUSE) /* Value read from EFUSE */
69 		return ((ind & CTRL_CRYSTAL_FREQ_SELECTION_MASK) >>
70 			CTRL_CRYSTAL_FREQ_SELECTION_SHIFT);
71 	else /* Value read from SYS BOOT pins */
72 #endif
73 		return ((ind & CTRL_SYSBOOT_15_14_MASK) >>
74 			CTRL_SYSBOOT_15_14_SHIFT);
75 }
76 
77 #ifdef CONFIG_DISPLAY_CPUINFO
78 static char *cpu_revs[] = {
79 		"1.0",
80 		"2.0",
81 		"2.1"};
82 
83 static char *cpu_revs_am43xx[] = {
84 		"1.0",
85 		"1.1",
86 		"1.2"};
87 
88 static char *dev_types[] = {
89 		"TST",
90 		"EMU",
91 		"HS",
92 		"GP"};
93 
94 /**
95  * Print CPU information
96  */
print_cpuinfo(void)97 int print_cpuinfo(void)
98 {
99 	char *cpu_s, *sec_s, *rev_s;
100 	char **cpu_rev_arr = cpu_revs;
101 
102 	switch (get_cpu_type()) {
103 	case AM335X:
104 		cpu_s = "AM335X";
105 		break;
106 	case TI81XX:
107 		cpu_s = "TI81XX";
108 		break;
109 	case AM437X:
110 		cpu_s = "AM437X";
111 		cpu_rev_arr = cpu_revs_am43xx;
112 		break;
113 	default:
114 		cpu_s = "Unknown CPU type";
115 		break;
116 	}
117 
118 	if (get_cpu_rev() < ARRAY_SIZE(cpu_revs))
119 		rev_s = cpu_rev_arr[get_cpu_rev()];
120 	else
121 		rev_s = "?";
122 
123 	if (get_device_type() < ARRAY_SIZE(dev_types))
124 		sec_s = dev_types[get_device_type()];
125 	else
126 		sec_s = "?";
127 
128 	printf("CPU  : %s-%s rev %s\n", cpu_s, sec_s, rev_s);
129 
130 	return 0;
131 }
132 #endif	/* CONFIG_DISPLAY_CPUINFO */
133 
134 #ifdef CONFIG_AM33XX
am335x_get_efuse_mpu_max_freq(struct ctrl_dev * cdev)135 int am335x_get_efuse_mpu_max_freq(struct ctrl_dev *cdev)
136 {
137 	int sil_rev;
138 
139 	sil_rev = readl(&cdev->deviceid) >> 28;
140 
141 	if (sil_rev == 0) {
142 		/* No efuse in PG 1.0. Use max speed */
143 		return MPUPLL_M_720;
144 	} else if (sil_rev >= 1) {
145 		/* Check what the efuse says our max speed is. */
146 		int efuse_arm_mpu_max_freq, package_type;
147 		efuse_arm_mpu_max_freq = readl(&cdev->efuse_sma);
148 		package_type = (efuse_arm_mpu_max_freq & PACKAGE_TYPE_MASK) >>
149 				PACKAGE_TYPE_SHIFT;
150 
151 		/* PG 2.0, efuse may not be set. */
152 		if (package_type == PACKAGE_TYPE_UNDEFINED || package_type ==
153 		    PACKAGE_TYPE_RESERVED)
154 			return MPUPLL_M_800;
155 
156 		switch ((efuse_arm_mpu_max_freq & DEVICE_ID_MASK)) {
157 		case AM335X_ZCZ_1000:
158 			return MPUPLL_M_1000;
159 		case AM335X_ZCZ_800:
160 			return MPUPLL_M_800;
161 		case AM335X_ZCZ_720:
162 			return MPUPLL_M_720;
163 		case AM335X_ZCZ_600:
164 		case AM335X_ZCE_600:
165 			return MPUPLL_M_600;
166 		case AM335X_ZCZ_300:
167 		case AM335X_ZCE_300:
168 			return MPUPLL_M_300;
169 		}
170 	}
171 
172 	/* unknown, use the PG1.0 max */
173 	return MPUPLL_M_720;
174 }
175 
am335x_get_mpu_vdd(int sil_rev,int frequency)176 int am335x_get_mpu_vdd(int sil_rev, int frequency)
177 {
178 	int sel_mask = am335x_get_tps65910_mpu_vdd(sil_rev, frequency);
179 
180 	switch (sel_mask) {
181 	case TPS65910_OP_REG_SEL_1_3_2_5:
182 		return 1325000;
183 	case TPS65910_OP_REG_SEL_1_2_0:
184 		return 1200000;
185 	case TPS65910_OP_REG_SEL_1_1_0:
186 		return 1100000;
187 	default:
188 		return 1262500;
189 	}
190 }
191 
am335x_get_tps65910_mpu_vdd(int sil_rev,int frequency)192 int am335x_get_tps65910_mpu_vdd(int sil_rev, int frequency)
193 {
194 	/* For PG2.0 and later, we have one set of values. */
195 	if (sil_rev >= 1) {
196 		switch (frequency) {
197 		case MPUPLL_M_1000:
198 			return TPS65910_OP_REG_SEL_1_3_2_5;
199 		case MPUPLL_M_800:
200 			return TPS65910_OP_REG_SEL_1_2_6;
201 		case MPUPLL_M_720:
202 			return TPS65910_OP_REG_SEL_1_2_0;
203 		case MPUPLL_M_600:
204 		case MPUPLL_M_500:
205 		case MPUPLL_M_300:
206 			return TPS65910_OP_REG_SEL_1_1_0;
207 		}
208 	}
209 
210 	/* Default to PG1.0 values. */
211 	return TPS65910_OP_REG_SEL_1_2_6;
212 }
213 #endif
214