hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/firmware/meson/meson_sm.c
....@@ -1,15 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Amlogic Secure Monitor driver
34 *
45 * Copyright (C) 2016 Endless Mobile, Inc.
56 * Author: Carlo Caione <carlo@endlessm.com>
6
- *
7
- * This program is free software; you can redistribute it and/or
8
- * modify it under the terms of the GNU General Public License
9
- * version 2 as published by the Free Software Foundation.
10
- *
11
- * You should have received a copy of the GNU General Public License
12
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
137 */
148
159 #define pr_fmt(fmt) "meson-sm: " fmt
....@@ -24,6 +18,7 @@
2418 #include <linux/printk.h>
2519 #include <linux/types.h>
2620 #include <linux/sizes.h>
21
+ #include <linux/slab.h>
2722
2823 #include <linux/firmware/meson/meson_sm.h>
2924
....@@ -40,7 +35,7 @@
4035 struct meson_sm_cmd cmd[];
4136 };
4237
43
-struct meson_sm_chip gxbb_chip = {
38
+static const struct meson_sm_chip gxbb_chip = {
4439 .shmem_size = SZ_4K,
4540 .cmd_shmem_in_base = 0x82000020,
4641 .cmd_shmem_out_base = 0x82000021,
....@@ -48,6 +43,9 @@
4843 CMD(SM_EFUSE_READ, 0x82000030),
4944 CMD(SM_EFUSE_WRITE, 0x82000031),
5045 CMD(SM_EFUSE_USER_MAX, 0x82000033),
46
+ CMD(SM_GET_CHIP_ID, 0x82000044),
47
+ CMD(SM_A1_PWRC_SET, 0x82000093),
48
+ CMD(SM_A1_PWRC_GET, 0x82000095),
5149 { /* sentinel */ },
5250 },
5351 };
....@@ -57,8 +55,6 @@
5755 void __iomem *sm_shmem_in_base;
5856 void __iomem *sm_shmem_out_base;
5957 };
60
-
61
-static struct meson_sm_firmware fw;
6258
6359 static u32 meson_sm_get_cmd(const struct meson_sm_chip *chip,
6460 unsigned int cmd_index)
....@@ -94,6 +90,7 @@
9490 /**
9591 * meson_sm_call - generic SMC32 call to the secure-monitor
9692 *
93
+ * @fw: Pointer to secure-monitor firmware
9794 * @cmd_index: Index of the SMC32 function ID
9895 * @ret: Returned value
9996 * @arg0: SMC32 Argument 0
....@@ -104,15 +101,15 @@
104101 *
105102 * Return: 0 on success, a negative value on error
106103 */
107
-int meson_sm_call(unsigned int cmd_index, u32 *ret, u32 arg0,
108
- u32 arg1, u32 arg2, u32 arg3, u32 arg4)
104
+int meson_sm_call(struct meson_sm_firmware *fw, unsigned int cmd_index,
105
+ u32 *ret, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
109106 {
110107 u32 cmd, lret;
111108
112
- if (!fw.chip)
109
+ if (!fw->chip)
113110 return -ENOENT;
114111
115
- cmd = meson_sm_get_cmd(fw.chip, cmd_index);
112
+ cmd = meson_sm_get_cmd(fw->chip, cmd_index);
116113 if (!cmd)
117114 return -EINVAL;
118115
....@@ -128,6 +125,7 @@
128125 /**
129126 * meson_sm_call_read - retrieve data from secure-monitor
130127 *
128
+ * @fw: Pointer to secure-monitor firmware
131129 * @buffer: Buffer to store the retrieved data
132130 * @bsize: Size of the buffer
133131 * @cmd_index: Index of the SMC32 function ID
....@@ -141,22 +139,23 @@
141139 * When 0 is returned there is no guarantee about the amount of
142140 * data read and bsize bytes are copied in buffer.
143141 */
144
-int meson_sm_call_read(void *buffer, unsigned int bsize, unsigned int cmd_index,
145
- u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
142
+int meson_sm_call_read(struct meson_sm_firmware *fw, void *buffer,
143
+ unsigned int bsize, unsigned int cmd_index, u32 arg0,
144
+ u32 arg1, u32 arg2, u32 arg3, u32 arg4)
146145 {
147146 u32 size;
148147 int ret;
149148
150
- if (!fw.chip)
149
+ if (!fw->chip)
151150 return -ENOENT;
152151
153
- if (!fw.chip->cmd_shmem_out_base)
152
+ if (!fw->chip->cmd_shmem_out_base)
154153 return -EINVAL;
155154
156
- if (bsize > fw.chip->shmem_size)
155
+ if (bsize > fw->chip->shmem_size)
157156 return -EINVAL;
158157
159
- if (meson_sm_call(cmd_index, &size, arg0, arg1, arg2, arg3, arg4) < 0)
158
+ if (meson_sm_call(fw, cmd_index, &size, arg0, arg1, arg2, arg3, arg4) < 0)
160159 return -EINVAL;
161160
162161 if (size > bsize)
....@@ -168,7 +167,7 @@
168167 size = bsize;
169168
170169 if (buffer)
171
- memcpy(buffer, fw.sm_shmem_out_base, size);
170
+ memcpy(buffer, fw->sm_shmem_out_base, size);
172171
173172 return ret;
174173 }
....@@ -177,6 +176,7 @@
177176 /**
178177 * meson_sm_call_write - send data to secure-monitor
179178 *
179
+ * @fw: Pointer to secure-monitor firmware
180180 * @buffer: Buffer containing data to send
181181 * @size: Size of the data to send
182182 * @cmd_index: Index of the SMC32 function ID
....@@ -188,23 +188,24 @@
188188 *
189189 * Return: size of sent data on success, a negative value on error
190190 */
191
-int meson_sm_call_write(void *buffer, unsigned int size, unsigned int cmd_index,
192
- u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
191
+int meson_sm_call_write(struct meson_sm_firmware *fw, void *buffer,
192
+ unsigned int size, unsigned int cmd_index, u32 arg0,
193
+ u32 arg1, u32 arg2, u32 arg3, u32 arg4)
193194 {
194195 u32 written;
195196
196
- if (!fw.chip)
197
+ if (!fw->chip)
197198 return -ENOENT;
198199
199
- if (size > fw.chip->shmem_size)
200
+ if (size > fw->chip->shmem_size)
200201 return -EINVAL;
201202
202
- if (!fw.chip->cmd_shmem_in_base)
203
+ if (!fw->chip->cmd_shmem_in_base)
203204 return -EINVAL;
204205
205
- memcpy(fw.sm_shmem_in_base, buffer, size);
206
+ memcpy(fw->sm_shmem_in_base, buffer, size);
206207
207
- if (meson_sm_call(cmd_index, &written, arg0, arg1, arg2, arg3, arg4) < 0)
208
+ if (meson_sm_call(fw, cmd_index, &written, arg0, arg1, arg2, arg3, arg4) < 0)
208209 return -EINVAL;
209210
210211 if (!written)
....@@ -214,6 +215,67 @@
214215 }
215216 EXPORT_SYMBOL(meson_sm_call_write);
216217
218
+/**
219
+ * meson_sm_get - get pointer to meson_sm_firmware structure.
220
+ *
221
+ * @sm_node: Pointer to the secure-monitor Device Tree node.
222
+ *
223
+ * Return: NULL is the secure-monitor device is not ready.
224
+ */
225
+struct meson_sm_firmware *meson_sm_get(struct device_node *sm_node)
226
+{
227
+ struct platform_device *pdev = of_find_device_by_node(sm_node);
228
+
229
+ if (!pdev)
230
+ return NULL;
231
+
232
+ return platform_get_drvdata(pdev);
233
+}
234
+EXPORT_SYMBOL_GPL(meson_sm_get);
235
+
236
+#define SM_CHIP_ID_LENGTH 119
237
+#define SM_CHIP_ID_OFFSET 4
238
+#define SM_CHIP_ID_SIZE 12
239
+
240
+static ssize_t serial_show(struct device *dev, struct device_attribute *attr,
241
+ char *buf)
242
+{
243
+ struct platform_device *pdev = to_platform_device(dev);
244
+ struct meson_sm_firmware *fw;
245
+ uint8_t *id_buf;
246
+ int ret;
247
+
248
+ fw = platform_get_drvdata(pdev);
249
+
250
+ id_buf = kmalloc(SM_CHIP_ID_LENGTH, GFP_KERNEL);
251
+ if (!id_buf)
252
+ return -ENOMEM;
253
+
254
+ ret = meson_sm_call_read(fw, id_buf, SM_CHIP_ID_LENGTH, SM_GET_CHIP_ID,
255
+ 0, 0, 0, 0, 0);
256
+ if (ret < 0) {
257
+ kfree(id_buf);
258
+ return ret;
259
+ }
260
+
261
+ ret = sprintf(buf, "%12phN\n", &id_buf[SM_CHIP_ID_OFFSET]);
262
+
263
+ kfree(id_buf);
264
+
265
+ return ret;
266
+}
267
+
268
+static DEVICE_ATTR_RO(serial);
269
+
270
+static struct attribute *meson_sm_sysfs_attributes[] = {
271
+ &dev_attr_serial.attr,
272
+ NULL,
273
+};
274
+
275
+static const struct attribute_group meson_sm_sysfs_attr_group = {
276
+ .attrs = meson_sm_sysfs_attributes,
277
+};
278
+
217279 static const struct of_device_id meson_sm_ids[] = {
218280 { .compatible = "amlogic,meson-gxbb-sm", .data = &gxbb_chip },
219281 { /* sentinel */ },
....@@ -221,31 +283,45 @@
221283
222284 static int __init meson_sm_probe(struct platform_device *pdev)
223285 {
286
+ struct device *dev = &pdev->dev;
224287 const struct meson_sm_chip *chip;
288
+ struct meson_sm_firmware *fw;
225289
226
- chip = of_match_device(meson_sm_ids, &pdev->dev)->data;
290
+ fw = devm_kzalloc(dev, sizeof(*fw), GFP_KERNEL);
291
+ if (!fw)
292
+ return -ENOMEM;
293
+
294
+ chip = of_match_device(meson_sm_ids, dev)->data;
295
+ if (!chip)
296
+ return -EINVAL;
227297
228298 if (chip->cmd_shmem_in_base) {
229
- fw.sm_shmem_in_base = meson_sm_map_shmem(chip->cmd_shmem_in_base,
230
- chip->shmem_size);
231
- if (WARN_ON(!fw.sm_shmem_in_base))
299
+ fw->sm_shmem_in_base = meson_sm_map_shmem(chip->cmd_shmem_in_base,
300
+ chip->shmem_size);
301
+ if (WARN_ON(!fw->sm_shmem_in_base))
232302 goto out;
233303 }
234304
235305 if (chip->cmd_shmem_out_base) {
236
- fw.sm_shmem_out_base = meson_sm_map_shmem(chip->cmd_shmem_out_base,
237
- chip->shmem_size);
238
- if (WARN_ON(!fw.sm_shmem_out_base))
306
+ fw->sm_shmem_out_base = meson_sm_map_shmem(chip->cmd_shmem_out_base,
307
+ chip->shmem_size);
308
+ if (WARN_ON(!fw->sm_shmem_out_base))
239309 goto out_in_base;
240310 }
241311
242
- fw.chip = chip;
312
+ fw->chip = chip;
313
+
314
+ platform_set_drvdata(pdev, fw);
315
+
243316 pr_info("secure-monitor enabled\n");
317
+
318
+ if (sysfs_create_group(&pdev->dev.kobj, &meson_sm_sysfs_attr_group))
319
+ goto out_in_base;
244320
245321 return 0;
246322
247323 out_in_base:
248
- iounmap(fw.sm_shmem_in_base);
324
+ iounmap(fw->sm_shmem_in_base);
249325 out:
250326 return -EINVAL;
251327 }
....@@ -257,3 +333,4 @@
257333 },
258334 };
259335 module_platform_driver_probe(meson_sm_driver, meson_sm_probe);
336
+MODULE_LICENSE("GPL v2");