blob: c70ef3a98507c67255a37d6130ad9872056b194e [file] [log] [blame]
Reut Zysman92bfac82017-04-05 18:18:50 +03001/*
2 * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14/*
15 * Secure-Processor-SubSystem (SPSS) utilities.
16 *
17 * This driver provides utilities for the Secure Processor (SP).
18 *
19 * The SP daemon needs to load different SPSS images based on:
20 *
21 * 1. Test/Production key used to sign the SPSS image (read fuses).
22 * 2. SPSS HW version (selected via Device Tree).
23 *
24 */
25
26#define pr_fmt(fmt) "spss_utils [%s]: " fmt, __func__
27
28#include <linux/kernel.h> /* min() */
29#include <linux/module.h> /* MODULE_LICENSE */
30#include <linux/device.h> /* class_create() */
31#include <linux/slab.h> /* kzalloc() */
32#include <linux/fs.h> /* file_operations */
33#include <linux/cdev.h> /* cdev_add() */
34#include <linux/errno.h> /* EINVAL, ETIMEDOUT */
35#include <linux/printk.h> /* pr_err() */
36#include <linux/bitops.h> /* BIT(x) */
37#include <linux/platform_device.h> /* platform_driver_register() */
38#include <linux/of.h> /* of_property_count_strings() */
39#include <linux/io.h> /* ioremap_nocache() */
40
41#include <soc/qcom/subsystem_restart.h>
42
43/* driver name */
44#define DEVICE_NAME "spss-utils"
45
46enum spss_firmware_type {
47 SPSS_FW_TYPE_DEV = 'd',
48 SPSS_FW_TYPE_TEST = 't',
49 SPSS_FW_TYPE_PROD = 'p',
50};
51
52static enum spss_firmware_type firmware_type = SPSS_FW_TYPE_TEST;
53static const char *dev_firmware_name;
54static const char *test_firmware_name;
55static const char *prod_firmware_name;
56static const char *firmware_name = "NA";
57static struct device *spss_dev;
58static u32 spss_debug_reg_addr; /* SP_SCSR_MBn_SP2CL_GPm(n,m) */
59
60/*==========================================================================*/
61/* Device Sysfs */
62/*==========================================================================*/
63
64static ssize_t firmware_name_show(struct device *dev,
65 struct device_attribute *attr,
66 char *buf)
67{
68 int ret;
69
70 if (!dev || !attr || !buf) {
71 pr_err("invalid param.\n");
72 return -EINVAL;
73 }
74
75 if (firmware_name == NULL)
76 ret = snprintf(buf, PAGE_SIZE, "%s\n", "unknown");
77 else
78 ret = snprintf(buf, PAGE_SIZE, "%s\n", firmware_name);
79
80 return ret;
81}
82
83static ssize_t firmware_name_store(struct device *dev,
84 struct device_attribute *attr,
85 const char *buf,
86 size_t size)
87{
88 pr_err("set firmware name is not allowed.\n");
89
90 return -EINVAL;
91}
92
93static DEVICE_ATTR(firmware_name, 0444,
94 firmware_name_show, firmware_name_store);
95
96static ssize_t test_fuse_state_show(struct device *dev,
97 struct device_attribute *attr,
98 char *buf)
99{
100 int ret;
101
102 if (!dev || !attr || !buf) {
103 pr_err("invalid param.\n");
104 return -EINVAL;
105 }
106
107 switch (firmware_type) {
108 case SPSS_FW_TYPE_DEV:
109 ret = snprintf(buf, PAGE_SIZE, "%s", "dev");
110 break;
111 case SPSS_FW_TYPE_TEST:
112 ret = snprintf(buf, PAGE_SIZE, "%s", "test");
113 break;
114 case SPSS_FW_TYPE_PROD:
115 ret = snprintf(buf, PAGE_SIZE, "%s", "prod");
116 break;
117 default:
118 return -EINVAL;
119 }
120
121 return ret;
122}
123
124static ssize_t test_fuse_state_store(struct device *dev,
125 struct device_attribute *attr,
126 const char *buf,
127 size_t size)
128{
129 pr_err("set test fuse state is not allowed.\n");
130
131 return -EINVAL;
132}
133
134static DEVICE_ATTR(test_fuse_state, 0444,
135 test_fuse_state_show, test_fuse_state_store);
136
137static ssize_t spss_debug_reg_show(struct device *dev,
138 struct device_attribute *attr,
139 char *buf)
140{
141 int ret;
142 void __iomem *spss_debug_reg = NULL;
143 u32 val1, val2;
144
145 if (!dev || !attr || !buf) {
146 pr_err("invalid param.\n");
147 return -EINVAL;
148 }
149
150 pr_debug("spss_debug_reg_addr [0x%x].\n", spss_debug_reg_addr);
151
152 spss_debug_reg = ioremap_nocache(spss_debug_reg_addr, sizeof(u32)*2);
153
154 if (!spss_debug_reg) {
155 pr_err("can't map debug reg addr.\n");
156 return -EFAULT;
157 }
158
159 val1 = readl_relaxed(spss_debug_reg);
160 val2 = readl_relaxed(((char *) spss_debug_reg) + sizeof(u32));
161
162 ret = snprintf(buf, PAGE_SIZE, "val1 [0x%x] val2 [0x%x]", val1, val2);
163
164 iounmap(spss_debug_reg);
165
166 return ret;
167}
168
169static ssize_t spss_debug_reg_store(struct device *dev,
170 struct device_attribute *attr,
171 const char *buf,
172 size_t size)
173{
174 pr_err("set debug reg is not allowed.\n");
175
176 return -EINVAL;
177}
178
179static DEVICE_ATTR(spss_debug_reg, 0444,
180 spss_debug_reg_show, spss_debug_reg_store);
181
182static int spss_create_sysfs(struct device *dev)
183{
184 int ret;
185
186 ret = device_create_file(dev, &dev_attr_firmware_name);
187 if (ret < 0) {
188 pr_err("failed to create sysfs file for firmware_name.\n");
189 return ret;
190 }
191
192 ret = device_create_file(dev, &dev_attr_test_fuse_state);
193 if (ret < 0) {
194 pr_err("failed to create sysfs file for test_fuse_state.\n");
195 device_remove_file(dev, &dev_attr_firmware_name);
196 return ret;
197 }
198
199 ret = device_create_file(dev, &dev_attr_spss_debug_reg);
200 if (ret < 0) {
201 pr_err("failed to create sysfs file for spss_debug_reg.\n");
202 device_remove_file(dev, &dev_attr_firmware_name);
203 device_remove_file(dev, &dev_attr_test_fuse_state);
204 return ret;
205 }
206
207 return 0;
208}
209
210/*==========================================================================*/
211/* Device Tree */
212/*==========================================================================*/
213
214/**
215 * spss_parse_dt() - Parse Device Tree info.
216 */
217static int spss_parse_dt(struct device_node *node)
218{
219 int ret;
220 u32 spss_fuse1_addr = 0;
221 u32 spss_fuse1_bit = 0;
222 u32 spss_fuse1_mask = 0;
223 void __iomem *spss_fuse1_reg = NULL;
224 u32 spss_fuse2_addr = 0;
225 u32 spss_fuse2_bit = 0;
226 u32 spss_fuse2_mask = 0;
227 void __iomem *spss_fuse2_reg = NULL;
228 u32 val1 = 0;
229 u32 val2 = 0;
230
231 ret = of_property_read_string(node, "qcom,spss-dev-firmware-name",
232 &dev_firmware_name);
233 if (ret < 0) {
234 pr_err("can't get dev fw name.\n");
235 return -EFAULT;
236 }
237
238 ret = of_property_read_string(node, "qcom,spss-test-firmware-name",
239 &test_firmware_name);
240 if (ret < 0) {
241 pr_err("can't get test fw name.\n");
242 return -EFAULT;
243 }
244
245 ret = of_property_read_string(node, "qcom,spss-prod-firmware-name",
246 &prod_firmware_name);
247 if (ret < 0) {
248 pr_err("can't get prod fw name.\n");
249 return -EFAULT;
250 }
251
252 ret = of_property_read_u32(node, "qcom,spss-fuse1-addr",
253 &spss_fuse1_addr);
254 if (ret < 0) {
255 pr_err("can't get fuse1 addr.\n");
256 return -EFAULT;
257 }
258
259 ret = of_property_read_u32(node, "qcom,spss-fuse2-addr",
260 &spss_fuse2_addr);
261 if (ret < 0) {
262 pr_err("can't get fuse2 addr.\n");
263 return -EFAULT;
264 }
265
266 ret = of_property_read_u32(node, "qcom,spss-fuse1-bit",
267 &spss_fuse1_bit);
268 if (ret < 0) {
269 pr_err("can't get fuse1 bit.\n");
270 return -EFAULT;
271 }
272
273 ret = of_property_read_u32(node, "qcom,spss-fuse2-bit",
274 &spss_fuse2_bit);
275 if (ret < 0) {
276 pr_err("can't get fuse2 bit.\n");
277 return -EFAULT;
278 }
279
280
281 spss_fuse1_mask = BIT(spss_fuse1_bit);
282 spss_fuse2_mask = BIT(spss_fuse2_bit);
283
284 pr_debug("spss fuse1 addr [0x%x] bit [%d] .\n",
285 (int) spss_fuse1_addr, (int) spss_fuse1_bit);
286 pr_debug("spss fuse2 addr [0x%x] bit [%d] .\n",
287 (int) spss_fuse2_addr, (int) spss_fuse2_bit);
288
289 spss_fuse1_reg = ioremap_nocache(spss_fuse1_addr, sizeof(u32));
290
291 if (!spss_fuse1_reg) {
292 pr_err("can't map fuse1 addr.\n");
293 return -EFAULT;
294 }
295
296 spss_fuse2_reg = ioremap_nocache(spss_fuse2_addr, sizeof(u32));
297
298 if (!spss_fuse2_reg) {
299 iounmap(spss_fuse1_reg);
300 pr_err("can't map fuse2 addr.\n");
301 return -EFAULT;
302 }
303
304 val1 = readl_relaxed(spss_fuse1_reg);
305 val2 = readl_relaxed(spss_fuse2_reg);
306
307 pr_debug("spss fuse1 value [0x%08x].\n", (int) val1);
308 pr_debug("spss fuse2 value [0x%08x].\n", (int) val2);
309
310 pr_debug("spss fuse1 mask [0x%08x].\n", (int) spss_fuse1_mask);
311 pr_debug("spss fuse2 mask [0x%08x].\n", (int) spss_fuse2_mask);
312
313 /**
314 * Set firmware_type based on fuses:
315 * SPSS_CONFIG_MODE 11: dev
316 * SPSS_CONFIG_MODE 01 or 10: test
317 * SPSS_CONFIG_MODE 00: prod
318 */
319 if ((val1 & spss_fuse1_mask) && (val2 & spss_fuse2_mask))
320 firmware_type = SPSS_FW_TYPE_DEV;
321 else if ((val1 & spss_fuse1_mask) || (val2 & spss_fuse2_mask))
322 firmware_type = SPSS_FW_TYPE_TEST;
323 else
324 firmware_type = SPSS_FW_TYPE_PROD;
325
326 iounmap(spss_fuse1_reg);
327 iounmap(spss_fuse2_reg);
328
329 ret = of_property_read_u32(node, "qcom,spss-debug-reg-addr",
330 &spss_debug_reg_addr);
331 if (ret < 0) {
332 pr_err("can't get debug regs addr.\n");
333 return ret;
334 }
335
336 return 0;
337}
338
339/**
340 * spss_probe() - initialization sequence
341 */
342static int spss_probe(struct platform_device *pdev)
343{
344 int ret = 0;
345 struct device_node *np = NULL;
346 struct device *dev = NULL;
347
348 if (!pdev) {
349 pr_err("invalid pdev.\n");
350 return -ENODEV;
351 }
352
353 np = pdev->dev.of_node;
354 if (!np) {
355 pr_err("invalid DT node.\n");
356 return -EINVAL;
357 }
358
359 dev = &pdev->dev;
360 spss_dev = dev;
361
362 if (dev == NULL) {
363 pr_err("invalid dev.\n");
364 return -EINVAL;
365 }
366
367 platform_set_drvdata(pdev, dev);
368
369 ret = spss_parse_dt(np);
370 if (ret < 0) {
371 pr_err("fail to parse device tree.\n");
372 return -EFAULT;
373 }
374
375 switch (firmware_type) {
376 case SPSS_FW_TYPE_DEV:
377 firmware_name = dev_firmware_name;
378 break;
379 case SPSS_FW_TYPE_TEST:
380 firmware_name = test_firmware_name;
381 break;
382 case SPSS_FW_TYPE_PROD:
383 firmware_name = prod_firmware_name;
384 break;
385 default:
386 return -EINVAL;
387 }
388
389 ret = subsystem_set_fwname("spss", firmware_name);
390 if (ret < 0) {
391 pr_err("fail to set fw name.\n");
392 return -EFAULT;
393 }
394
395 ret = spss_create_sysfs(dev);
396 if (ret < 0) {
397 pr_err("fail to create sysfs.\n");
398 return -EFAULT;
399 }
400
401 pr_info("Initialization completed ok, firmware_name [%s].\n",
402 firmware_name);
403
404 return 0;
405}
406
407static const struct of_device_id spss_match_table[] = {
408 { .compatible = "qcom,spss-utils", },
409 { },
410};
411
412static struct platform_driver spss_driver = {
413 .probe = spss_probe,
414 .driver = {
415 .name = DEVICE_NAME,
416 .owner = THIS_MODULE,
417 .of_match_table = of_match_ptr(spss_match_table),
418 },
419};
420
421/*==========================================================================*/
422/* Driver Init/Exit */
423/*==========================================================================*/
424static int __init spss_init(void)
425{
426 int ret = 0;
427
428 pr_info("spss-utils driver Ver 2.0 30-Mar-2017.\n");
429
430 ret = platform_driver_register(&spss_driver);
431 if (ret)
432 pr_err("register platform driver failed, ret [%d]\n", ret);
433
434 return ret;
435}
436late_initcall(spss_init); /* start after PIL driver */
437
438MODULE_LICENSE("GPL v2");
439MODULE_DESCRIPTION("Secure Processor Utilities");