1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2020 NXP
4  *
5  */
6 
7 #include <common.h>
8 #include <hang.h>
9 #include <malloc.h>
10 #include <asm/io.h>
11 #include <dm.h>
12 #include <asm/arch/s400_api.h>
13 #include <misc.h>
14 
15 DECLARE_GLOBAL_DATA_PTR;
16 
ahab_release_rdc(u8 core_id,bool xrdc,u32 * response)17 int ahab_release_rdc(u8 core_id, bool xrdc, u32 *response)
18 {
19 	struct udevice *dev = gd->arch.s400_dev;
20 	int size = sizeof(struct imx8ulp_s400_msg);
21 	struct imx8ulp_s400_msg msg;
22 	int ret;
23 
24 	if (!dev) {
25 		printf("s400 dev is not initialized\n");
26 		return -ENODEV;
27 	}
28 
29 	msg.version = AHAB_VERSION;
30 	msg.tag = AHAB_CMD_TAG;
31 	msg.size = 2;
32 	msg.command = AHAB_RELEASE_RDC_REQ_CID;
33 	if (xrdc)
34 		msg.data[0] = (0x78 << 8) | core_id;
35 	else
36 		msg.data[0] = (0x74 << 8) | core_id;
37 
38 	ret = misc_call(dev, false, &msg, size, &msg, size);
39 	if (ret)
40 		printf("Error: %s: ret %d, core id %u, response 0x%x\n",
41 		       __func__, ret, core_id, msg.data[0]);
42 
43 	if (response)
44 		*response = msg.data[0];
45 
46 	return ret;
47 }
48 
ahab_auth_oem_ctnr(ulong ctnr_addr,u32 * response)49 int ahab_auth_oem_ctnr(ulong ctnr_addr, u32 *response)
50 {
51 	struct udevice *dev = gd->arch.s400_dev;
52 	int size = sizeof(struct imx8ulp_s400_msg);
53 	struct imx8ulp_s400_msg msg;
54 	int ret;
55 
56 	if (!dev) {
57 		printf("s400 dev is not initialized\n");
58 		return -ENODEV;
59 	}
60 
61 	msg.version = AHAB_VERSION;
62 	msg.tag = AHAB_CMD_TAG;
63 	msg.size = 3;
64 	msg.command = AHAB_AUTH_OEM_CTNR_CID;
65 	msg.data[0] = upper_32_bits(ctnr_addr);
66 	msg.data[1] = lower_32_bits(ctnr_addr);
67 
68 	ret = misc_call(dev, false, &msg, size, &msg, size);
69 	if (ret)
70 		printf("Error: %s: ret %d, cntr_addr 0x%lx, response 0x%x\n",
71 		       __func__, ret, ctnr_addr, msg.data[0]);
72 
73 	if (response)
74 		*response = msg.data[0];
75 
76 	return ret;
77 }
78 
ahab_release_container(u32 * response)79 int ahab_release_container(u32 *response)
80 {
81 	struct udevice *dev = gd->arch.s400_dev;
82 	int size = sizeof(struct imx8ulp_s400_msg);
83 	struct imx8ulp_s400_msg msg;
84 	int ret;
85 
86 	if (!dev) {
87 		printf("s400 dev is not initialized\n");
88 		return -ENODEV;
89 	}
90 
91 	msg.version = AHAB_VERSION;
92 	msg.tag = AHAB_CMD_TAG;
93 	msg.size = 1;
94 	msg.command = AHAB_RELEASE_CTNR_CID;
95 
96 	ret = misc_call(dev, false, &msg, size, &msg, size);
97 	if (ret)
98 		printf("Error: %s: ret %d, response 0x%x\n",
99 		       __func__, ret, msg.data[0]);
100 
101 	if (response)
102 		*response = msg.data[0];
103 
104 	return ret;
105 }
106 
ahab_verify_image(u32 img_id,u32 * response)107 int ahab_verify_image(u32 img_id, u32 *response)
108 {
109 	struct udevice *dev = gd->arch.s400_dev;
110 	int size = sizeof(struct imx8ulp_s400_msg);
111 	struct imx8ulp_s400_msg msg;
112 	int ret;
113 
114 	if (!dev) {
115 		printf("s400 dev is not initialized\n");
116 		return -ENODEV;
117 	}
118 
119 	msg.version = AHAB_VERSION;
120 	msg.tag = AHAB_CMD_TAG;
121 	msg.size = 2;
122 	msg.command = AHAB_VERIFY_IMG_CID;
123 	msg.data[0] = 1 << img_id;
124 
125 	ret = misc_call(dev, false, &msg, size, &msg, size);
126 	if (ret)
127 		printf("Error: %s: ret %d, img_id %u, response 0x%x\n",
128 		       __func__, ret, img_id, msg.data[0]);
129 
130 	if (response)
131 		*response = msg.data[0];
132 
133 	return ret;
134 }
135 
ahab_forward_lifecycle(u16 life_cycle,u32 * response)136 int ahab_forward_lifecycle(u16 life_cycle, u32 *response)
137 {
138 	struct udevice *dev = gd->arch.s400_dev;
139 	int size = sizeof(struct imx8ulp_s400_msg);
140 	struct imx8ulp_s400_msg msg;
141 	int ret;
142 
143 	if (!dev) {
144 		printf("s400 dev is not initialized\n");
145 		return -ENODEV;
146 	}
147 
148 	msg.version = AHAB_VERSION;
149 	msg.tag = AHAB_CMD_TAG;
150 	msg.size = 2;
151 	msg.command = AHAB_FWD_LIFECYCLE_UP_REQ_CID;
152 	msg.data[0] = life_cycle;
153 
154 	ret = misc_call(dev, false, &msg, size, &msg, size);
155 	if (ret)
156 		printf("Error: %s: ret %d, life_cycle 0x%x, response 0x%x\n",
157 		       __func__, ret, life_cycle, msg.data[0]);
158 
159 	if (response)
160 		*response = msg.data[0];
161 
162 	return ret;
163 }
164 
ahab_read_common_fuse(u16 fuse_id,u32 * fuse_words,u32 fuse_num,u32 * response)165 int ahab_read_common_fuse(u16 fuse_id, u32 *fuse_words, u32 fuse_num, u32 *response)
166 {
167 	struct udevice *dev = gd->arch.s400_dev;
168 	int size = sizeof(struct imx8ulp_s400_msg);
169 	struct imx8ulp_s400_msg msg;
170 	int ret;
171 
172 	if (!dev) {
173 		printf("s400 dev is not initialized\n");
174 		return -ENODEV;
175 	}
176 
177 	if (!fuse_words) {
178 		printf("Invalid parameters for fuse read\n");
179 		return -EINVAL;
180 	}
181 
182 	if ((fuse_id != 1 && fuse_num != 1) ||
183 	    (fuse_id == 1 && fuse_num != 4)) {
184 		printf("Invalid fuse number parameter\n");
185 		return -EINVAL;
186 	}
187 
188 	msg.version = AHAB_VERSION;
189 	msg.tag = AHAB_CMD_TAG;
190 	msg.size = 2;
191 	msg.command = AHAB_READ_FUSE_REQ_CID;
192 	msg.data[0] = fuse_id;
193 
194 	ret = misc_call(dev, false, &msg, size, &msg, size);
195 	if (ret)
196 		printf("Error: %s: ret %d, fuse_id 0x%x, response 0x%x\n",
197 		       __func__, ret, fuse_id, msg.data[0]);
198 
199 	if (response)
200 		*response = msg.data[0];
201 
202 	fuse_words[0] = msg.data[1];
203 	if (fuse_id == 1) {
204 		/* OTP_UNIQ_ID */
205 		fuse_words[1] = msg.data[2];
206 		fuse_words[2] = msg.data[3];
207 		fuse_words[3] = msg.data[4];
208 	}
209 
210 	return ret;
211 }
212 
ahab_write_fuse(u16 fuse_id,u32 fuse_val,bool lock,u32 * response)213 int ahab_write_fuse(u16 fuse_id, u32 fuse_val, bool lock, u32 *response)
214 {
215 	struct udevice *dev = gd->arch.s400_dev;
216 	int size = sizeof(struct imx8ulp_s400_msg);
217 	struct imx8ulp_s400_msg msg;
218 	int ret;
219 
220 	if (!dev) {
221 		printf("s400 dev is not initialized\n");
222 		return -ENODEV;
223 	}
224 
225 	msg.version = AHAB_VERSION;
226 	msg.tag = AHAB_CMD_TAG;
227 	msg.size = 3;
228 	msg.command = AHAB_WRITE_FUSE_REQ_CID;
229 	msg.data[0] = (32 << 16) | (fuse_id << 5);
230 	if (lock)
231 		msg.data[0] |= (1 << 31);
232 
233 	msg.data[1] = fuse_val;
234 
235 	ret = misc_call(dev, false, &msg, size, &msg, size);
236 	if (ret)
237 		printf("Error: %s: ret %d, fuse_id 0x%x, response 0x%x\n",
238 		       __func__, ret, fuse_id, msg.data[0]);
239 
240 	if (response)
241 		*response = msg.data[0];
242 
243 	return ret;
244 }
245