1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) 2024 Christian Marangi */ 3 4 #include <linux/kernel.h> 5 #include <linux/module.h> 6 #include <linux/bitfield.h> 7 #include <linux/delay.h> 8 #include <linux/hw_random.h> 9 #include <linux/interrupt.h> 10 #include <linux/io.h> 11 #include <linux/iopoll.h> 12 #include <linux/platform_device.h> 13 14 #define TRNG_IP_RDY 0x800 15 #define CNT_TRANS GENMASK(15, 8) 16 #define SAMPLE_RDY BIT(0) 17 #define TRNG_NS_SEK_AND_DAT_EN 0x804 18 #define RNG_EN BIT(31) /* referenced as ring_en */ 19 #define RAW_DATA_EN BIT(16) 20 #define TRNG_HEALTH_TEST_SW_RST 0x808 21 #define SW_RST BIT(0) /* Active High */ 22 #define TRNG_INTR_EN 0x818 23 #define INTR_MASK BIT(16) 24 #define CONTINUOUS_HEALTH_INITR_EN BIT(2) 25 #define SW_STARTUP_INITR_EN BIT(1) 26 #define RST_STARTUP_INITR_EN BIT(0) 27 /* Notice that Health Test are done only out of Reset and with RNG_EN */ 28 #define TRNG_HEALTH_TEST_STATUS 0x824 29 #define CONTINUOUS_HEALTH_AP_TEST_FAIL BIT(23) 30 #define CONTINUOUS_HEALTH_RC_TEST_FAIL BIT(22) 31 #define SW_STARTUP_TEST_DONE BIT(21) 32 #define SW_STARTUP_AP_TEST_FAIL BIT(20) 33 #define SW_STARTUP_RC_TEST_FAIL BIT(19) 34 #define RST_STARTUP_TEST_DONE BIT(18) 35 #define RST_STARTUP_AP_TEST_FAIL BIT(17) 36 #define RST_STARTUP_RC_TEST_FAIL BIT(16) 37 #define RAW_DATA_VALID BIT(7) 38 39 #define TRNG_RAW_DATA_OUT 0x828 40 41 #define TRNG_CNT_TRANS_VALID 0x80 42 #define BUSY_LOOP_SLEEP 10 43 #define BUSY_LOOP_TIMEOUT (BUSY_LOOP_SLEEP * 10000) 44 45 struct airoha_trng { 46 void __iomem *base; 47 struct hwrng rng; 48 struct device *dev; 49 50 struct completion rng_op_done; 51 }; 52 53 static int airoha_trng_irq_mask(struct airoha_trng *trng) 54 { 55 u32 val; 56 57 val = readl(trng->base + TRNG_INTR_EN); 58 val |= INTR_MASK; 59 writel(val, trng->base + TRNG_INTR_EN); 60 61 return 0; 62 } 63 64 static int airoha_trng_irq_unmask(struct airoha_trng *trng) 65 { 66 u32 val; 67 68 val = readl(trng->base + TRNG_INTR_EN); 69 val &= ~INTR_MASK; 70 writel(val, trng->base + TRNG_INTR_EN); 71 72 return 0; 73 } 74 75 static int airoha_trng_init(struct hwrng *rng) 76 { 77 struct airoha_trng *trng = container_of(rng, struct airoha_trng, rng); 78 int ret; 79 u32 val; 80 81 val = readl(trng->base + TRNG_NS_SEK_AND_DAT_EN); 82 val |= RNG_EN; 83 writel(val, trng->base + TRNG_NS_SEK_AND_DAT_EN); 84 85 /* Set out of SW Reset */ 86 airoha_trng_irq_unmask(trng); 87 writel(0, trng->base + TRNG_HEALTH_TEST_SW_RST); 88 89 ret = wait_for_completion_timeout(&trng->rng_op_done, BUSY_LOOP_TIMEOUT); 90 if (ret <= 0) { 91 dev_err(trng->dev, "Timeout waiting for Health Check\n"); 92 airoha_trng_irq_mask(trng); 93 return -ENODEV; 94 } 95 96 /* Check if Health Test Failed */ 97 val = readl(trng->base + TRNG_HEALTH_TEST_STATUS); 98 if (val & (RST_STARTUP_AP_TEST_FAIL | RST_STARTUP_RC_TEST_FAIL)) { 99 dev_err(trng->dev, "Health Check fail: %s test fail\n", 100 val & RST_STARTUP_AP_TEST_FAIL ? "AP" : "RC"); 101 return -ENODEV; 102 } 103 104 /* Check if IP is ready */ 105 ret = readl_poll_timeout(trng->base + TRNG_IP_RDY, val, 106 val & SAMPLE_RDY, 10, 1000); 107 if (ret < 0) { 108 dev_err(trng->dev, "Timeout waiting for IP ready"); 109 return -ENODEV; 110 } 111 112 /* CNT_TRANS must be 0x80 for IP to be considered ready */ 113 ret = readl_poll_timeout(trng->base + TRNG_IP_RDY, val, 114 FIELD_GET(CNT_TRANS, val) == TRNG_CNT_TRANS_VALID, 115 10, 1000); 116 if (ret < 0) { 117 dev_err(trng->dev, "Timeout waiting for IP ready"); 118 return -ENODEV; 119 } 120 121 return 0; 122 } 123 124 static void airoha_trng_cleanup(struct hwrng *rng) 125 { 126 struct airoha_trng *trng = container_of(rng, struct airoha_trng, rng); 127 u32 val; 128 129 val = readl(trng->base + TRNG_NS_SEK_AND_DAT_EN); 130 val &= ~RNG_EN; 131 writel(val, trng->base + TRNG_NS_SEK_AND_DAT_EN); 132 133 /* Put it in SW Reset */ 134 writel(SW_RST, trng->base + TRNG_HEALTH_TEST_SW_RST); 135 } 136 137 static int airoha_trng_read(struct hwrng *rng, void *buf, size_t max, bool wait) 138 { 139 struct airoha_trng *trng = container_of(rng, struct airoha_trng, rng); 140 u32 *data = buf; 141 u32 status; 142 int ret; 143 144 ret = readl_poll_timeout(trng->base + TRNG_HEALTH_TEST_STATUS, status, 145 status & RAW_DATA_VALID, 10, 1000); 146 if (ret < 0) { 147 dev_err(trng->dev, "Timeout waiting for TRNG RAW Data valid\n"); 148 return ret; 149 } 150 151 *data = readl(trng->base + TRNG_RAW_DATA_OUT); 152 153 return 4; 154 } 155 156 static irqreturn_t airoha_trng_irq(int irq, void *priv) 157 { 158 struct airoha_trng *trng = (struct airoha_trng *)priv; 159 160 airoha_trng_irq_mask(trng); 161 /* Just complete the task, we will read the value later */ 162 complete(&trng->rng_op_done); 163 164 return IRQ_HANDLED; 165 } 166 167 static int airoha_trng_probe(struct platform_device *pdev) 168 { 169 struct device *dev = &pdev->dev; 170 struct airoha_trng *trng; 171 int irq, ret; 172 u32 val; 173 174 trng = devm_kzalloc(dev, sizeof(*trng), GFP_KERNEL); 175 if (!trng) 176 return -ENOMEM; 177 178 trng->base = devm_platform_ioremap_resource(pdev, 0); 179 if (IS_ERR(trng->base)) 180 return PTR_ERR(trng->base); 181 182 irq = platform_get_irq(pdev, 0); 183 if (irq < 0) 184 return irq; 185 186 airoha_trng_irq_mask(trng); 187 ret = devm_request_irq(&pdev->dev, irq, airoha_trng_irq, 0, 188 pdev->name, (void *)trng); 189 if (ret) 190 return ret; 191 192 init_completion(&trng->rng_op_done); 193 194 /* Enable interrupt for SW reset Health Check */ 195 val = readl(trng->base + TRNG_INTR_EN); 196 val |= RST_STARTUP_INITR_EN; 197 writel(val, trng->base + TRNG_INTR_EN); 198 199 /* Set output to raw data */ 200 val = readl(trng->base + TRNG_NS_SEK_AND_DAT_EN); 201 val |= RAW_DATA_EN; 202 writel(val, trng->base + TRNG_NS_SEK_AND_DAT_EN); 203 204 /* Put it in SW Reset */ 205 writel(SW_RST, trng->base + TRNG_HEALTH_TEST_SW_RST); 206 207 trng->dev = dev; 208 trng->rng.name = pdev->name; 209 trng->rng.init = airoha_trng_init; 210 trng->rng.cleanup = airoha_trng_cleanup; 211 trng->rng.read = airoha_trng_read; 212 trng->rng.quality = 900; 213 214 ret = devm_hwrng_register(dev, &trng->rng); 215 if (ret) { 216 dev_err(dev, "failed to register rng device: %d\n", ret); 217 return ret; 218 } 219 220 return 0; 221 } 222 223 static const struct of_device_id airoha_trng_of_match[] = { 224 { .compatible = "airoha,en7581-trng", }, 225 {}, 226 }; 227 MODULE_DEVICE_TABLE(of, airoha_trng_of_match); 228 229 static struct platform_driver airoha_trng_driver = { 230 .driver = { 231 .name = "airoha-trng", 232 .of_match_table = airoha_trng_of_match, 233 }, 234 .probe = airoha_trng_probe, 235 }; 236 237 module_platform_driver(airoha_trng_driver); 238 239 MODULE_LICENSE("GPL"); 240 MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>"); 241 MODULE_DESCRIPTION("Airoha True Random Number Generator driver"); 242