xref: /OK3568_Linux_fs/buildroot/package/rockchip/npu_powerctrl_combine/npu_powerctrl_combine.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2 // Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
3 
4 #include <stdio.h>
5 #include <errno.h>
6 #include <string.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include <unistd.h>
11 
12 #include <npu_powerctrl.h>
13 
14 #define VERSION "V1.1 for power combine board"
15 #define FNAME_SIZE 50
16 #define GPIO_BASE_PATH "/sys/class/gpio"
17 #define GPIO_EXPORT_PATH GPIO_BASE_PATH "/export"
18 #define GPIO_UNEXPORT_PATH GPIO_BASE_PATH "/unexport"
19 #define CLKEN_24M_PATH "/sys/kernel/debug/clk/clk_wifi_pmu/clk_enable_count"
20 #define CLKEN_32k_PATH "/sys/kernel/debug/clk/rk808-clkout2/clk_enable_count"
21 #define PCIE_RESET_EP "/sys/devices/platform/f8000000.pcie/pcie_reset_ep"
22 #define ACM_HIGHSPEED_ID "/sys/bus/platform/devices/fe380000.usb/usb*/*/idProduct"
23 #define ACM_FULLSPEED_ID "/sys/bus/platform/devices/fe3a0000.usb/usb*/*/idProduct"
24 
25 #define CPU_RESET_NPU_GPIO 	"32" //GPIO1_PA0
26 #define NPU_PMU_SLEEP_GPIO 	"35" //GPIO1_A3
27 #define CPU_INT_NPU_GPIO 	"36" //GPIO1_A4
28 
29 #define NPU_VDD_EN1_GPIO 	"4"  //GPIO0_PA4
30 #define NPU_VDD_EN4_GPIO 	"54" //GPIO1_PC6  vdd_cpp/vdd
31 
32 static char gpio_list[][4] = {NPU_VDD_EN1_GPIO, NPU_VDD_EN4_GPIO, CPU_RESET_NPU_GPIO, \
33 	NPU_PMU_SLEEP_GPIO, CPU_INT_NPU_GPIO};
34 
sysfs_write(char * path,char * val)35 static int sysfs_write(char *path, char *val) {
36 	char buf[80];
37 	int len;
38 	int fd = open(path, O_WRONLY);
39 
40 	if (fd < 0) {
41 		strerror_r(errno, buf, sizeof(buf));
42 		printf("Error opening %s value=%s:%s\n", path, val, buf);
43 		return -1;
44 	}
45 
46 	len = write(fd, val, sizeof(val));
47 	if (len < 0) {
48 		strerror_r(errno, buf, sizeof(buf));
49 		printf("Error writing to %s value=%s: %s\n", path, val, buf);
50 		return -1;
51 	}
52 
53 	close(fd);
54 	return 0;
55 }
56 
sysfs_read(char * path,char * val)57 static void sysfs_read(char *path, char *val)
58 {
59 	char buf[80];
60 	int len;
61 	int fd = open(path, O_RDONLY);
62 
63 	if (fd < 0) {
64 		strerror_r(errno, buf, sizeof(buf));
65 		printf("Error opening %s value=%s:%s\n", path, val, buf);
66 		return;
67 	}
68 
69 	len = read(fd, val, 1);
70 	if (len < 0) {
71 		strerror_r(errno, buf, sizeof(buf));
72 		printf("Error reading to %s value=%s: %s\n", path, val, buf);
73 	}
74 
75 	close(fd);
76 }
77 
clk_enable(char * enable)78 static int clk_enable(char *enable) {
79 	char val;
80 
81 	sysfs_read(CLKEN_24M_PATH, &val);
82 	if (*enable == val)
83 		return 0;
84 
85 	printf("set clk_en  %c to %s\n", val, enable);
86 	sysfs_write(CLKEN_24M_PATH, enable);
87 	return 0;
88 }
89 
request_gpio(char * gpio_num)90 static int request_gpio(char *gpio_num) {
91 	int ret;
92 	ret = sysfs_write(GPIO_EXPORT_PATH, gpio_num);
93 	return ret;
94 }
95 
free_gpio(char * gpio_num)96 static void free_gpio(char *gpio_num) {
97 	sysfs_write(GPIO_UNEXPORT_PATH, gpio_num);
98 }
99 
set_gpio_dir(char * gpio_num,char * dir)100 static void set_gpio_dir(char *gpio_num, char *dir) {
101 	char gpio_dir_name[FNAME_SIZE];
102 
103 	snprintf(gpio_dir_name, sizeof(gpio_dir_name), "%s/gpio%s/direction",
104 			GPIO_BASE_PATH, gpio_num);
105 	sysfs_write(gpio_dir_name, dir);
106 }
107 
get_gpio(char * gpio_number)108 static int get_gpio(char *gpio_number) {
109 	char gpio_name[FNAME_SIZE];
110 	char value;
111 
112 	snprintf(gpio_name, sizeof(gpio_name), "%s/gpio%s/value",
113 			GPIO_BASE_PATH, gpio_number);
114 
115 	sysfs_read(gpio_name, &value);
116 	if (value == 48 || value == 49)
117 		value -= 48;
118 	else
119 		value = -1;
120 	return (int)value;
121 }
122 
set_gpio(char * gpio_number,char * val)123 static int set_gpio(char *gpio_number, char *val) {
124 	char gpio_val_name[FNAME_SIZE];
125 
126 	snprintf(gpio_val_name, sizeof(gpio_val_name), "%s/gpio%s/value",
127 			GPIO_BASE_PATH, gpio_number);
128 	sysfs_write(gpio_val_name, val);
129 	return 0;
130 }
131 
npu_power_gpio_init(void)132 void npu_power_gpio_init(void) {
133 	int ret, index = 0, gpio_cnt = sizeof(gpio_list)/sizeof(int);
134 
135 	printf("version: %s\n", VERSION);
136 	while (index != gpio_cnt) {
137 		printf("init gpio: %s\n", gpio_list[index]);
138 		ret = request_gpio(gpio_list[index]);
139 		if (ret) {
140 			return;
141 		}
142 		set_gpio_dir(gpio_list[index], "out");
143 		index ++;
144 	}
145 	set_gpio_dir(NPU_PMU_SLEEP_GPIO, "in");
146 }
147 
npu_power_gpio_exit(void)148 void npu_power_gpio_exit(void) {
149 	int index = 0, gpio_cnt = sizeof(gpio_list)/sizeof(int);
150 
151 	while (index != gpio_cnt) {
152 		printf("init gpio: %s\n", gpio_list[index]);
153 		free_gpio(gpio_list[index]);
154 		index ++;
155 	}
156 }
157 
npu_reset(void)158 void npu_reset(void) {
159 	//sysfs_write("/sys/power/wake_lock", "npu_lock");
160 	sysfs_write(CLKEN_32k_PATH, "1");
161 	clk_enable("0");
162 	set_gpio(NPU_VDD_EN1_GPIO, "0");
163 	set_gpio(NPU_VDD_EN4_GPIO, "0");
164 	set_gpio(CPU_RESET_NPU_GPIO, "0");
165 	usleep(2000);
166 
167 	/*power en*/
168 	set_gpio(NPU_VDD_EN1_GPIO, "1");
169 	usleep(2000);
170 	clk_enable("1");
171 	set_gpio(NPU_VDD_EN4_GPIO, "1");
172 
173 	usleep(25000);
174 	set_gpio(CPU_RESET_NPU_GPIO, "1");
175 }
176 
npu_poweroff(void)177 void npu_poweroff(void) {
178 	set_gpio(NPU_VDD_EN1_GPIO, "0");
179 	set_gpio(NPU_VDD_EN4_GPIO, "0");
180 	clk_enable("0");
181 	//sysfs_write("/sys/power/wake_unlock", "npu_lock");
182 }
183 
disconnect_usb_acm(void)184 int disconnect_usb_acm(void)
185 {
186 	FILE *stream;
187 	char buf[100];
188 	int idx = 0, path_idx=0;
189 
190 	memset( buf,'\0',sizeof(buf) );
191 	stream = popen( "cat " ACM_HIGHSPEED_ID, "r" );
192 	if (!stream) {
193 		path_idx=1;
194 		stream = popen( "cat " ACM_FULLSPEED_ID, "r" );
195 		if (!stream)
196 			return -1;
197 	}
198 	fread( buf, sizeof(char), sizeof(buf), stream);
199 	pclose( stream );
200 	printf("ACM idProduct: %s", buf);
201 	if (!strncmp(buf, "1005", 4)) {
202 		if (path_idx)
203 			stream = popen("find /sys/bus/platform/devices/fe3a0000.usb/usb*/*/ -name remove", "r" );
204 		else
205 			stream = popen("find /sys/bus/platform/devices/fe380000.usb/usb*/*/ -name remove", "r" );
206 		fread( buf, sizeof(char), sizeof(buf), stream);
207 		printf("usb remove patch is %s", buf);
208 		/* The path string adds end character */
209 		while(idx < 100) {
210 			if (buf[idx] == '\n') {
211 				buf[idx] = '\0';
212 				break;
213 			}
214 			idx ++;
215 		}
216 		sysfs_write(buf, "0");
217 		pclose( stream );
218 		return 0;
219 	}
220 	return -1;
221 
222 }
223 
npu_suspend(void)224 int npu_suspend(void) {
225 	int retry=100;
226 	int is_pcie;
227 
228 	if (get_gpio(NPU_PMU_SLEEP_GPIO)) {
229 		printf("It is sleeping state, noting to do!\n");
230 		return 0;
231 	}
232 
233 	is_pcie = access(PCIE_RESET_EP, R_OK);
234 	if (!is_pcie) {
235 		sysfs_write(PCIE_RESET_EP, "2");
236 		disconnect_usb_acm();
237 	}
238 
239 	set_gpio(CPU_INT_NPU_GPIO, "1");
240 	usleep(20000);
241 	set_gpio(CPU_INT_NPU_GPIO, "0");
242 
243 	/*wait for npu enter sleep*/
244 	while (--retry) {
245 		if (get_gpio(NPU_PMU_SLEEP_GPIO)) {
246 			usleep(10000);
247 			set_gpio(NPU_VDD_EN4_GPIO, "0");
248 			clk_enable("0");
249 			/* wait 1s for usb disconnect */
250 			sleep(1);
251 			//sysfs_write("/sys/power/wake_unlock", "npu_lock");
252 			break;
253 		}
254 		usleep(10000);
255 	}
256 
257 	if (!retry) {
258 		printf("npu suspend timeout in one second\n");
259 		return -1;
260 	}
261 	return 0;
262 }
263 
npu_resume(void)264 int npu_resume(void) {
265 	int retry=100;
266 	int is_pcie;
267 
268 	if (!get_gpio(NPU_PMU_SLEEP_GPIO)) {
269 		printf("It is awakening state, noting to do!\n");
270 		return 0;
271 	}
272 
273 	clk_enable("1");
274 	set_gpio(NPU_VDD_EN4_GPIO, "1");
275 
276 	usleep(10000);
277 
278 	set_gpio(CPU_INT_NPU_GPIO, "1");
279 	usleep(20000);
280 	set_gpio(CPU_INT_NPU_GPIO, "0");
281 
282 	/*wait for npu wakeup*/
283 	while (--retry) {
284 		if (!get_gpio(NPU_PMU_SLEEP_GPIO)) {
285 		//	sysfs_write("/sys/power/wake_lock", "npu_lock");
286 			break;
287 		}
288 		usleep(10000);
289 	}
290 
291 	is_pcie = access(PCIE_RESET_EP, R_OK);
292 	if (!is_pcie)
293 		sysfs_write(PCIE_RESET_EP, "1");
294 
295 	if (!retry) {
296 		printf("npu resume timeout in one second\n");
297 		return -1;
298 	}
299 	//waiting for userspase wakup
300 	/*usleep(500000);*/
301 	/*set_gpio(CPU_INT_NPU_GPIO, "0");*/
302 
303 	return 0;
304 }
305