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