hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/nvmem/sunxi_sid.c
....@@ -1,18 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0+
12 /*
23 * Allwinner sunXi SoCs Security ID support.
34 *
45 * Copyright (c) 2013 Oliver Schinagl <oliver@schinagl.nl>
56 * Copyright (C) 2014 Maxime Ripard <maxime.ripard@free-electrons.com>
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation; either version 2 of the License, or
10
- * (at your option) any later version.
11
- *
12
- * This program is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- * GNU General Public License for more details.
167 */
178
189 #include <linux/device.h>
....@@ -35,13 +26,6 @@
3526 #define SUN8I_SID_OP_LOCK (0xAC << 8)
3627 #define SUN8I_SID_READ BIT(1)
3728
38
-static struct nvmem_config econfig = {
39
- .name = "sunxi-sid",
40
- .read_only = true,
41
- .stride = 4,
42
- .word_size = 1,
43
-};
44
-
4529 struct sunxi_sid_cfg {
4630 u32 value_offset;
4731 u32 size;
....@@ -53,33 +37,12 @@
5337 u32 value_offset;
5438 };
5539
56
-/* We read the entire key, due to a 32 bit read alignment requirement. Since we
57
- * want to return the requested byte, this results in somewhat slower code and
58
- * uses 4 times more reads as needed but keeps code simpler. Since the SID is
59
- * only very rarely probed, this is not really an issue.
60
- */
61
-static u8 sunxi_sid_read_byte(const struct sunxi_sid *sid,
62
- const unsigned int offset)
63
-{
64
- u32 sid_key;
65
-
66
- sid_key = ioread32be(sid->base + round_down(offset, 4));
67
- sid_key >>= (offset % 4) * 8;
68
-
69
- return sid_key; /* Only return the last byte */
70
-}
71
-
7240 static int sunxi_sid_read(void *context, unsigned int offset,
7341 void *val, size_t bytes)
7442 {
7543 struct sunxi_sid *sid = context;
76
- u8 *buf = val;
7744
78
- /* Offset the read operation to the real position of SID */
79
- offset += sid->value_offset;
80
-
81
- while (bytes--)
82
- *buf++ = sunxi_sid_read_byte(sid, offset++);
45
+ memcpy_fromio(val, sid->base + sid->value_offset + offset, bytes);
8346
8447 return 0;
8548 }
....@@ -115,35 +78,33 @@
11578 * to be not reliable at all.
11679 * Read by the registers instead.
11780 */
118
-static int sun8i_sid_read_byte_by_reg(const struct sunxi_sid *sid,
119
- const unsigned int offset,
120
- u8 *out)
121
-{
122
- u32 word;
123
- int ret;
124
-
125
- ret = sun8i_sid_register_readout(sid, offset & ~0x03, &word);
126
-
127
- if (ret)
128
- return ret;
129
-
130
- *out = (word >> ((offset & 0x3) * 8)) & 0xff;
131
-
132
- return 0;
133
-}
134
-
13581 static int sun8i_sid_read_by_reg(void *context, unsigned int offset,
13682 void *val, size_t bytes)
13783 {
13884 struct sunxi_sid *sid = context;
139
- u8 *buf = val;
85
+ u32 word;
14086 int ret;
14187
142
- while (bytes--) {
143
- ret = sun8i_sid_read_byte_by_reg(sid, offset++, buf++);
88
+ /* .stride = 4 so offset is guaranteed to be aligned */
89
+ while (bytes >= 4) {
90
+ ret = sun8i_sid_register_readout(sid, offset, val);
14491 if (ret)
14592 return ret;
93
+
94
+ val += 4;
95
+ offset += 4;
96
+ bytes -= 4;
14697 }
98
+
99
+ if (!bytes)
100
+ return 0;
101
+
102
+ /* Handle any trailing bytes */
103
+ ret = sun8i_sid_register_readout(sid, offset, &word);
104
+ if (ret)
105
+ return ret;
106
+
107
+ memcpy(val, &word, bytes);
147108
148109 return 0;
149110 }
....@@ -152,9 +113,10 @@
152113 {
153114 struct device *dev = &pdev->dev;
154115 struct resource *res;
116
+ struct nvmem_config *nvmem_cfg;
155117 struct nvmem_device *nvmem;
156118 struct sunxi_sid *sid;
157
- int ret, i, size;
119
+ int size;
158120 char *randomness;
159121 const struct sunxi_sid_cfg *cfg;
160122
....@@ -174,43 +136,37 @@
174136
175137 size = cfg->size;
176138
177
- econfig.size = size;
178
- econfig.dev = dev;
139
+ nvmem_cfg = devm_kzalloc(dev, sizeof(*nvmem_cfg), GFP_KERNEL);
140
+ if (!nvmem_cfg)
141
+ return -ENOMEM;
142
+
143
+ nvmem_cfg->dev = dev;
144
+ nvmem_cfg->name = "sunxi-sid";
145
+ nvmem_cfg->read_only = true;
146
+ nvmem_cfg->size = cfg->size;
147
+ nvmem_cfg->word_size = 1;
148
+ nvmem_cfg->stride = 4;
149
+ nvmem_cfg->priv = sid;
179150 if (cfg->need_register_readout)
180
- econfig.reg_read = sun8i_sid_read_by_reg;
151
+ nvmem_cfg->reg_read = sun8i_sid_read_by_reg;
181152 else
182
- econfig.reg_read = sunxi_sid_read;
183
- econfig.priv = sid;
184
- nvmem = nvmem_register(&econfig);
153
+ nvmem_cfg->reg_read = sunxi_sid_read;
154
+
155
+ nvmem = devm_nvmem_register(dev, nvmem_cfg);
185156 if (IS_ERR(nvmem))
186157 return PTR_ERR(nvmem);
187158
188159 randomness = kzalloc(size, GFP_KERNEL);
189
- if (!randomness) {
190
- ret = -EINVAL;
191
- goto err_unreg_nvmem;
192
- }
160
+ if (!randomness)
161
+ return -ENOMEM;
193162
194
- for (i = 0; i < size; i++)
195
- econfig.reg_read(sid, i, &randomness[i], 1);
196
-
163
+ nvmem_cfg->reg_read(sid, 0, randomness, size);
197164 add_device_randomness(randomness, size);
198165 kfree(randomness);
199166
200167 platform_set_drvdata(pdev, nvmem);
201168
202169 return 0;
203
-
204
-err_unreg_nvmem:
205
- nvmem_unregister(nvmem);
206
- return ret;
207
-}
208
-
209
-static int sunxi_sid_remove(struct platform_device *pdev)
210
-{
211
- struct nvmem_device *nvmem = platform_get_drvdata(pdev);
212
-
213
- return nvmem_unregister(nvmem);
214170 }
215171
216172 static const struct sunxi_sid_cfg sun4i_a10_cfg = {
....@@ -230,6 +186,12 @@
230186 static const struct sunxi_sid_cfg sun50i_a64_cfg = {
231187 .value_offset = 0x200,
232188 .size = 0x100,
189
+ .need_register_readout = true,
190
+};
191
+
192
+static const struct sunxi_sid_cfg sun50i_h6_cfg = {
193
+ .value_offset = 0x200,
194
+ .size = 0x200,
233195 };
234196
235197 static const struct of_device_id sunxi_sid_of_match[] = {
....@@ -239,13 +201,13 @@
239201 { .compatible = "allwinner,sun8i-h3-sid", .data = &sun8i_h3_cfg },
240202 { .compatible = "allwinner,sun50i-a64-sid", .data = &sun50i_a64_cfg },
241203 { .compatible = "allwinner,sun50i-h5-sid", .data = &sun50i_a64_cfg },
204
+ { .compatible = "allwinner,sun50i-h6-sid", .data = &sun50i_h6_cfg },
242205 {/* sentinel */},
243206 };
244207 MODULE_DEVICE_TABLE(of, sunxi_sid_of_match);
245208
246209 static struct platform_driver sunxi_sid_driver = {
247210 .probe = sunxi_sid_probe,
248
- .remove = sunxi_sid_remove,
249211 .driver = {
250212 .name = "eeprom-sunxi-sid",
251213 .of_match_table = sunxi_sid_of_match,