hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/char/hw_random/atmel-rng.c
....@@ -14,13 +14,21 @@
1414 #include <linux/clk.h>
1515 #include <linux/io.h>
1616 #include <linux/hw_random.h>
17
+#include <linux/of_device.h>
1718 #include <linux/platform_device.h>
1819
1920 #define TRNG_CR 0x00
21
+#define TRNG_MR 0x04
2022 #define TRNG_ISR 0x1c
2123 #define TRNG_ODATA 0x50
2224
2325 #define TRNG_KEY 0x524e4700 /* RNG */
26
+
27
+#define TRNG_HALFR BIT(0) /* generate RN every 168 cycles */
28
+
29
+struct atmel_trng_data {
30
+ bool has_half_rate;
31
+};
2432
2533 struct atmel_trng {
2634 struct clk *clk;
....@@ -62,21 +70,31 @@
6270 static int atmel_trng_probe(struct platform_device *pdev)
6371 {
6472 struct atmel_trng *trng;
65
- struct resource *res;
73
+ const struct atmel_trng_data *data;
6674 int ret;
6775
6876 trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL);
6977 if (!trng)
7078 return -ENOMEM;
7179
72
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
73
- trng->base = devm_ioremap_resource(&pdev->dev, res);
80
+ trng->base = devm_platform_ioremap_resource(pdev, 0);
7481 if (IS_ERR(trng->base))
7582 return PTR_ERR(trng->base);
7683
7784 trng->clk = devm_clk_get(&pdev->dev, NULL);
7885 if (IS_ERR(trng->clk))
7986 return PTR_ERR(trng->clk);
87
+ data = of_device_get_match_data(&pdev->dev);
88
+ if (!data)
89
+ return -ENODEV;
90
+
91
+ if (data->has_half_rate) {
92
+ unsigned long rate = clk_get_rate(trng->clk);
93
+
94
+ /* if peripheral clk is above 100MHz, set HALFR */
95
+ if (rate > 100000000)
96
+ writel(TRNG_HALFR, trng->base + TRNG_MR);
97
+ }
8098
8199 ret = clk_prepare_enable(trng->clk);
82100 if (ret)
....@@ -86,7 +104,7 @@
86104 trng->rng.name = pdev->name;
87105 trng->rng.read = atmel_trng_read;
88106
89
- ret = hwrng_register(&trng->rng);
107
+ ret = devm_hwrng_register(&pdev->dev, &trng->rng);
90108 if (ret)
91109 goto err_register;
92110
....@@ -96,6 +114,7 @@
96114
97115 err_register:
98116 clk_disable_unprepare(trng->clk);
117
+ atmel_trng_disable(trng);
99118 return ret;
100119 }
101120
....@@ -103,7 +122,6 @@
103122 {
104123 struct atmel_trng *trng = platform_get_drvdata(pdev);
105124
106
- hwrng_unregister(&trng->rng);
107125
108126 atmel_trng_disable(trng);
109127 clk_disable_unprepare(trng->clk);
....@@ -142,9 +160,24 @@
142160 };
143161 #endif /* CONFIG_PM */
144162
163
+static const struct atmel_trng_data at91sam9g45_config = {
164
+ .has_half_rate = false,
165
+};
166
+
167
+static const struct atmel_trng_data sam9x60_config = {
168
+ .has_half_rate = true,
169
+};
170
+
145171 static const struct of_device_id atmel_trng_dt_ids[] = {
146
- { .compatible = "atmel,at91sam9g45-trng" },
147
- { /* sentinel */ }
172
+ {
173
+ .compatible = "atmel,at91sam9g45-trng",
174
+ .data = &at91sam9g45_config,
175
+ }, {
176
+ .compatible = "microchip,sam9x60-trng",
177
+ .data = &sam9x60_config,
178
+ }, {
179
+ /* sentinel */
180
+ }
148181 };
149182 MODULE_DEVICE_TABLE(of, atmel_trng_dt_ids);
150183