Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 // Copyright (c) 2020 Silex Insight
0003 
0004 #include <linux/delay.h>
0005 #include <linux/hw_random.h>
0006 #include <linux/io.h>
0007 #include <linux/iopoll.h>
0008 #include <linux/kernel.h>
0009 #include <linux/mod_devicetable.h>
0010 #include <linux/module.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/workqueue.h>
0013 
0014 #define BA431_RESET_DELAY           1 /* usec */
0015 #define BA431_RESET_READ_STATUS_TIMEOUT     1000 /* usec */
0016 #define BA431_RESET_READ_STATUS_INTERVAL    10 /* usec */
0017 #define BA431_READ_RETRY_INTERVAL       1 /* usec */
0018 
0019 #define BA431_REG_CTRL              0x00
0020 #define BA431_REG_FIFO_LEVEL            0x04
0021 #define BA431_REG_STATUS            0x30
0022 #define BA431_REG_FIFODATA          0x80
0023 
0024 #define BA431_CTRL_ENABLE           BIT(0)
0025 #define BA431_CTRL_SOFTRESET            BIT(8)
0026 
0027 #define BA431_STATUS_STATE_MASK         (BIT(1) | BIT(2) | BIT(3))
0028 #define BA431_STATUS_STATE_OFFSET       1
0029 
0030 enum ba431_state {
0031     BA431_STATE_RESET,
0032     BA431_STATE_STARTUP,
0033     BA431_STATE_FIFOFULLON,
0034     BA431_STATE_FIFOFULLOFF,
0035     BA431_STATE_RUNNING,
0036     BA431_STATE_ERROR
0037 };
0038 
0039 struct ba431_trng {
0040     struct device *dev;
0041     void __iomem *base;
0042     struct hwrng rng;
0043     atomic_t reset_pending;
0044     struct work_struct reset_work;
0045 };
0046 
0047 static inline u32 ba431_trng_read_reg(struct ba431_trng *ba431, u32 reg)
0048 {
0049     return ioread32(ba431->base + reg);
0050 }
0051 
0052 static inline void ba431_trng_write_reg(struct ba431_trng *ba431, u32 reg,
0053                     u32 val)
0054 {
0055     iowrite32(val, ba431->base + reg);
0056 }
0057 
0058 static inline enum ba431_state ba431_trng_get_state(struct ba431_trng *ba431)
0059 {
0060     u32 status = ba431_trng_read_reg(ba431, BA431_REG_STATUS);
0061 
0062     return (status & BA431_STATUS_STATE_MASK) >> BA431_STATUS_STATE_OFFSET;
0063 }
0064 
0065 static int ba431_trng_is_in_error(struct ba431_trng *ba431)
0066 {
0067     enum ba431_state state = ba431_trng_get_state(ba431);
0068 
0069     if ((state < BA431_STATE_STARTUP) ||
0070         (state >= BA431_STATE_ERROR))
0071         return 1;
0072 
0073     return 0;
0074 }
0075 
0076 static int ba431_trng_reset(struct ba431_trng *ba431)
0077 {
0078     int ret;
0079 
0080     /* Disable interrupts, random generation and enable the softreset */
0081     ba431_trng_write_reg(ba431, BA431_REG_CTRL, BA431_CTRL_SOFTRESET);
0082     udelay(BA431_RESET_DELAY);
0083     ba431_trng_write_reg(ba431, BA431_REG_CTRL, BA431_CTRL_ENABLE);
0084 
0085     /* Wait until the state changed */
0086     if (readx_poll_timeout(ba431_trng_is_in_error, ba431, ret, !ret,
0087                    BA431_RESET_READ_STATUS_INTERVAL,
0088                    BA431_RESET_READ_STATUS_TIMEOUT)) {
0089         dev_err(ba431->dev, "reset failed (state: %d)\n",
0090             ba431_trng_get_state(ba431));
0091         return -ETIMEDOUT;
0092     }
0093 
0094     dev_info(ba431->dev, "reset done\n");
0095 
0096     return 0;
0097 }
0098 
0099 static void ba431_trng_reset_work(struct work_struct *work)
0100 {
0101     struct ba431_trng *ba431 = container_of(work, struct ba431_trng,
0102                         reset_work);
0103     ba431_trng_reset(ba431);
0104     atomic_set(&ba431->reset_pending, 0);
0105 }
0106 
0107 static void ba431_trng_schedule_reset(struct ba431_trng *ba431)
0108 {
0109     if (atomic_cmpxchg(&ba431->reset_pending, 0, 1))
0110         return;
0111 
0112     schedule_work(&ba431->reset_work);
0113 }
0114 
0115 static int ba431_trng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
0116 {
0117     struct ba431_trng *ba431 = container_of(rng, struct ba431_trng, rng);
0118     u32 *data = buf;
0119     unsigned int level, i;
0120     int n = 0;
0121 
0122     while (max > 0) {
0123         level = ba431_trng_read_reg(ba431, BA431_REG_FIFO_LEVEL);
0124         if (!level) {
0125             if (ba431_trng_is_in_error(ba431)) {
0126                 ba431_trng_schedule_reset(ba431);
0127                 break;
0128             }
0129 
0130             if (!wait)
0131                 break;
0132 
0133             udelay(BA431_READ_RETRY_INTERVAL);
0134             continue;
0135         }
0136 
0137         i = level;
0138         do {
0139             data[n++] = ba431_trng_read_reg(ba431,
0140                             BA431_REG_FIFODATA);
0141             max -= sizeof(*data);
0142         } while (--i && (max > 0));
0143 
0144         if (ba431_trng_is_in_error(ba431)) {
0145             n -= (level - i);
0146             ba431_trng_schedule_reset(ba431);
0147             break;
0148         }
0149     }
0150 
0151     n *= sizeof(data);
0152     return (n || !wait) ? n : -EIO;
0153 }
0154 
0155 static void ba431_trng_cleanup(struct hwrng *rng)
0156 {
0157     struct ba431_trng *ba431 = container_of(rng, struct ba431_trng, rng);
0158 
0159     ba431_trng_write_reg(ba431, BA431_REG_CTRL, 0);
0160     cancel_work_sync(&ba431->reset_work);
0161 }
0162 
0163 static int ba431_trng_init(struct hwrng *rng)
0164 {
0165     struct ba431_trng *ba431 = container_of(rng, struct ba431_trng, rng);
0166 
0167     return ba431_trng_reset(ba431);
0168 }
0169 
0170 static int ba431_trng_probe(struct platform_device *pdev)
0171 {
0172     struct ba431_trng *ba431;
0173     int ret;
0174 
0175     ba431 = devm_kzalloc(&pdev->dev, sizeof(*ba431), GFP_KERNEL);
0176     if (!ba431)
0177         return -ENOMEM;
0178 
0179     ba431->dev = &pdev->dev;
0180 
0181     ba431->base = devm_platform_ioremap_resource(pdev, 0);
0182     if (IS_ERR(ba431->base))
0183         return PTR_ERR(ba431->base);
0184 
0185     atomic_set(&ba431->reset_pending, 0);
0186     INIT_WORK(&ba431->reset_work, ba431_trng_reset_work);
0187     ba431->rng.name = pdev->name;
0188     ba431->rng.init = ba431_trng_init;
0189     ba431->rng.cleanup = ba431_trng_cleanup;
0190     ba431->rng.read = ba431_trng_read;
0191 
0192     platform_set_drvdata(pdev, ba431);
0193 
0194     ret = devm_hwrng_register(&pdev->dev, &ba431->rng);
0195     if (ret) {
0196         dev_err(&pdev->dev, "BA431 registration failed (%d)\n", ret);
0197         return ret;
0198     }
0199 
0200     dev_info(&pdev->dev, "BA431 TRNG registered\n");
0201 
0202     return 0;
0203 }
0204 
0205 static const struct of_device_id ba431_trng_dt_ids[] = {
0206     { .compatible = "silex-insight,ba431-rng", .data = NULL },
0207     { /* sentinel */ }
0208 };
0209 MODULE_DEVICE_TABLE(of, ba431_trng_dt_ids);
0210 
0211 static struct platform_driver ba431_trng_driver = {
0212     .driver = {
0213         .name = "ba431-rng",
0214         .of_match_table = ba431_trng_dt_ids,
0215     },
0216     .probe = ba431_trng_probe,
0217 };
0218 
0219 module_platform_driver(ba431_trng_driver);
0220 
0221 MODULE_AUTHOR("Olivier Sobrie <olivier@sobrie.be>");
0222 MODULE_DESCRIPTION("TRNG driver for Silex Insight BA431");
0223 MODULE_LICENSE("GPL");