1 /*
2  * Copyright (c) 2020 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/sys/printk.h>
9 #include <zephyr/drivers/peci.h>
10 #include <soc.h>
11 
12 #define TASK_STACK_SIZE         1024
13 #define PRIORITY                7
14 
15 /* PECI Host address */
16 #define PECI_HOST_ADDR          0x30u
17 /* PECI Host bitrate 1Mbps */
18 #define PECI_HOST_BITRATE       1000u
19 
20 #define PECI_CONFIGINDEX_TJMAX  16u
21 #define PECI_CONFIGHOSTID       0u
22 #define PECI_CONFIGPARAM        0u
23 
24 #define PECI_SAFE_TEMP          72
25 
26 static const struct device *const peci_dev = DEVICE_DT_GET(DT_ALIAS(peci_0));
27 static bool peci_initialized;
28 static uint8_t cpu_tjmax;
29 static uint8_t rx_fcs;
30 static void monitor_temperature_func(void *dummy1, void *dummy2, void *dummy3);
31 
32 static struct k_thread temp_id;
33 K_THREAD_STACK_DEFINE(temp_stack, TASK_STACK_SIZE);
34 
peci_ping(void)35 int peci_ping(void)
36 {
37 	int ret;
38 	struct peci_msg packet;
39 
40 	printk("%s\n", __func__);
41 
42 	packet.addr = PECI_HOST_ADDR;
43 	packet.cmd_code = PECI_CMD_PING;
44 	packet.tx_buffer.buf = NULL;
45 	packet.tx_buffer.len = PECI_PING_WR_LEN;
46 	packet.rx_buffer.buf = NULL;
47 	packet.rx_buffer.len = PECI_PING_RD_LEN;
48 
49 	ret = peci_transfer(peci_dev, &packet);
50 	if (ret) {
51 		printk("ping failed %d\n", ret);
52 		return ret;
53 	}
54 
55 	return 0;
56 }
57 
peci_get_tjmax(uint8_t * tjmax)58 int peci_get_tjmax(uint8_t *tjmax)
59 {
60 	int ret;
61 	int retries = 3;
62 	uint8_t peci_resp;
63 	struct peci_msg packet;
64 
65 	uint8_t peci_resp_buf[PECI_RD_PKG_LEN_DWORD+1];
66 	uint8_t peci_req_buf[] = { PECI_CONFIGHOSTID,
67 				PECI_CONFIGINDEX_TJMAX,
68 				PECI_CONFIGPARAM & 0x00FF,
69 				(PECI_CONFIGPARAM & 0xFF00) >> 8,
70 	};
71 
72 	packet.tx_buffer.buf = peci_req_buf;
73 	packet.tx_buffer.len = PECI_RD_PKG_WR_LEN;
74 	packet.rx_buffer.buf = peci_resp_buf;
75 	packet.rx_buffer.len = PECI_RD_PKG_LEN_DWORD;
76 
77 	do {
78 		rx_fcs = 0;
79 		packet.addr = PECI_HOST_ADDR;
80 		packet.cmd_code = PECI_CMD_RD_PKG_CFG0;
81 
82 		ret = peci_transfer(peci_dev, &packet);
83 
84 		for (int i = 0; i < PECI_RD_PKG_LEN_DWORD; i++) {
85 			printk("%02x\n", packet.rx_buffer.buf[i]);
86 		}
87 
88 		peci_resp = packet.rx_buffer.buf[0];
89 		rx_fcs = packet.rx_buffer.buf[PECI_RD_PKG_LEN_DWORD];
90 		k_sleep(K_MSEC(1));
91 		printk("\npeci_resp %x\n", peci_resp);
92 		retries--;
93 	} while ((peci_resp != PECI_CC_RSP_SUCCESS) && (retries > 0));
94 
95 	*tjmax = packet.rx_buffer.buf[3];
96 
97 	return 0;
98 }
99 
peci_get_temp(int * temperature)100 int peci_get_temp(int *temperature)
101 {
102 	int16_t raw_cpu_temp;
103 	int ret;
104 	struct peci_msg packet = {0};
105 
106 	uint8_t peci_resp_buf[PECI_GET_TEMP_RD_LEN+1];
107 
108 	rx_fcs = 0;
109 	packet.tx_buffer.buf = NULL;
110 	packet.tx_buffer.len = PECI_GET_TEMP_WR_LEN;
111 	packet.rx_buffer.buf = peci_resp_buf;
112 	packet.rx_buffer.len = PECI_GET_TEMP_RD_LEN;
113 
114 	packet.addr = PECI_HOST_ADDR;
115 	packet.cmd_code = PECI_CMD_GET_TEMP0;
116 
117 	ret = peci_transfer(peci_dev, &packet);
118 	if (ret) {
119 		printk("Get temp failed %d\n", ret);
120 		return ret;
121 	}
122 
123 	rx_fcs = packet.rx_buffer.buf[PECI_GET_TEMP_RD_LEN];
124 	printk("R FCS %x\n", rx_fcs);
125 	printk("Temp bytes: %02x", packet.rx_buffer.buf[0]);
126 	printk("%02x\n", packet.rx_buffer.buf[1]);
127 
128 	raw_cpu_temp = (int16_t)(packet.rx_buffer.buf[0] |
129 			(int16_t)((packet.rx_buffer.buf[1] << 8) & 0xFF00));
130 
131 	if (raw_cpu_temp == 0x8000) {
132 		printk("Invalid temp %x\n", raw_cpu_temp);
133 		*temperature = PECI_SAFE_TEMP;
134 		return -1;
135 	}
136 
137 	raw_cpu_temp = (raw_cpu_temp >> 6) | 0x7E00;
138 	*temperature = raw_cpu_temp + cpu_tjmax;
139 
140 	return 0;
141 }
142 
read_temp(void)143 void read_temp(void)
144 {
145 	int ret;
146 	int temp;
147 
148 	ret = peci_get_temp(&temp);
149 
150 	if (!ret) {
151 		printk("Temperature %d C\n", temp);
152 	}
153 }
154 
get_max_temp(void)155 void get_max_temp(void)
156 {
157 	int ret;
158 
159 	ret = peci_get_tjmax(&cpu_tjmax);
160 	if (ret) {
161 		printk("Fail to obtain maximum temperature: %d\n", ret);
162 	} else {
163 		printk("Maximum temperature: %u\n", cpu_tjmax);
164 	}
165 }
166 
monitor_temperature_func(void * dummy1,void * dummy2,void * dummy3)167 static void monitor_temperature_func(void *dummy1, void *dummy2, void *dummy3)
168 {
169 	while (true) {
170 		k_sleep(K_MSEC(1000));
171 		if (peci_initialized) {
172 			read_temp();
173 		}
174 	}
175 }
176 
main(void)177 int main(void)
178 {
179 	int ret;
180 
181 	printk("PECI sample test\n");
182 
183 	k_thread_create(&temp_id, temp_stack, TASK_STACK_SIZE,
184 		monitor_temperature_func, NULL, NULL, NULL, PRIORITY,
185 		K_INHERIT_PERMS, K_FOREVER);
186 
187 	if (!device_is_ready(peci_dev)) {
188 		printk("Err: PECI device is not ready\n");
189 		return 0;
190 	}
191 
192 	ret = peci_config(peci_dev, 1000u);
193 	if (ret) {
194 		printk("Err: Fail to configure bitrate\n");
195 		return 0;
196 	}
197 
198 	peci_enable(peci_dev);
199 
200 	cpu_tjmax = 100;
201 
202 	get_max_temp();
203 	printk("Start thread...\n");
204 	k_thread_start(&temp_id);
205 
206 	peci_initialized = true;
207 	return 0;
208 }
209