Lines Matching +full:cryptocell +full:- +full:713 +full:- +full:trng
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2019-2020 ARM Limited or its affiliates. */
23 #define CC_REG_HIGH(name) (CC_REG_LOW(name) + name ## _BIT_SIZE - 1)
33 * - of a power-of-2 size (limitation of circ_buf.h macros)
34 * - at least 6, the size generated in the EHR according to HW implementation
38 /* The timeout for the TRNG operation should be calculated with the formula:
41 * - SAMPLE_CNT is input value from the characterisation process
42 * - all the rest are constants
59 * Value of 0 indicates non-valid rosc
68 /* pending_hw - 1 when HW is pending, 0 when it is idle */
79 iowrite32(val, (drvdata->cc_base + reg)); in cc_iowrite()
83 return ioread32(drvdata->cc_base + reg); in cc_ioread()
109 struct device *dev = &(drvdata->pdev->dev); in cc_trng_pm_init()
114 /* set us as active - note we won't do PM ops until cc_trng_pm_go()! */ in cc_trng_pm_init()
120 struct device *dev = &(drvdata->pdev->dev); in cc_trng_pm_go()
128 struct device *dev = &(drvdata->pdev->dev); in cc_trng_pm_fini()
136 struct device *dev = &(drvdata->pdev->dev); in cc_trng_parse_sampling_ratio()
137 struct device_node *np = drvdata->pdev->dev.of_node; in cc_trng_parse_sampling_ratio()
141 int ret = -EINVAL; in cc_trng_parse_sampling_ratio()
143 rc = of_property_read_u32_array(np, "arm,rosc-ratio", in cc_trng_parse_sampling_ratio()
144 drvdata->smpl_ratio, in cc_trng_parse_sampling_ratio()
147 /* arm,rosc-ratio was not found in device tree */ in cc_trng_parse_sampling_ratio()
154 i, drvdata->smpl_ratio[i]); in cc_trng_parse_sampling_ratio()
156 if (drvdata->smpl_ratio[i] > 0) in cc_trng_parse_sampling_ratio()
165 struct device *dev = &(drvdata->pdev->dev); in cc_trng_change_rosc()
167 dev_dbg(dev, "cctrng change rosc (was %d)\n", drvdata->active_rosc); in cc_trng_change_rosc()
168 drvdata->active_rosc += 1; in cc_trng_change_rosc()
170 while (drvdata->active_rosc < CC_TRNG_NUM_OF_ROSCS) { in cc_trng_change_rosc()
171 if (drvdata->smpl_ratio[drvdata->active_rosc] > 0) in cc_trng_change_rosc()
174 drvdata->active_rosc += 1; in cc_trng_change_rosc()
176 return -EINVAL; in cc_trng_change_rosc()
185 max_cycles = CCTRNG_TIMEOUT(drvdata->smpl_ratio[drvdata->active_rosc]); in cc_trng_enable_rnd_source()
200 *idx &= (CCTRNG_DATA_BUF_WORDS - 1); in circ_idx_inc()
205 return CIRC_SPACE(drvdata->circ.head, in circ_buf_space()
206 drvdata->circ.tail, CCTRNG_DATA_BUF_WORDS); in circ_buf_space()
214 struct cctrng_drvdata *drvdata = (struct cctrng_drvdata *)rng->priv; in cctrng_read()
215 struct device *dev = &(drvdata->pdev->dev); in cctrng_read()
216 u32 *buf = (u32 *)drvdata->circ.buf; in cctrng_read()
222 if (!spin_trylock(&drvdata->read_lock)) { in cctrng_read()
229 cnt_w = CIRC_CNT_TO_END(drvdata->circ.head, in cctrng_read()
230 drvdata->circ.tail, CCTRNG_DATA_BUF_WORDS); in cctrng_read()
232 memcpy(data, &(buf[drvdata->circ.tail]), size); in cctrng_read()
234 circ_idx_inc(&drvdata->circ.tail, size); in cctrng_read()
236 left = max - copied; in cctrng_read()
238 cnt_w = CIRC_CNT(drvdata->circ.head, in cctrng_read()
239 drvdata->circ.tail, CCTRNG_DATA_BUF_WORDS); in cctrng_read()
241 memcpy(data, &(buf[drvdata->circ.tail]), size); in cctrng_read()
243 circ_idx_inc(&drvdata->circ.tail, size); in cctrng_read()
246 spin_unlock(&drvdata->read_lock); in cctrng_read()
249 if (atomic_cmpxchg(&drvdata->pending_hw, 0, 1) == 0) { in cctrng_read()
250 /* re-check space in buffer to avoid potential race */ in cctrng_read()
265 schedule_work(&drvdata->startwork); in cctrng_read()
267 atomic_set(&drvdata->pending_hw, 0); in cctrng_read()
278 struct device *dev = &(drvdata->pdev->dev); in cc_trng_hw_trigger()
296 drvdata->smpl_ratio[drvdata->active_rosc]); in cc_trng_hw_trigger()
301 } while (tmp_smpl_cnt != drvdata->smpl_ratio[drvdata->active_rosc]); in cc_trng_hw_trigger()
308 cc_iowrite(drvdata, CC_TRNG_CONFIG_REG_OFFSET, drvdata->active_rosc); in cc_trng_hw_trigger()
310 /* Debug Control register: set to 0 - no bypasses */ in cc_trng_hw_trigger()
322 struct device *dev = &(drvdata->pdev->dev); in cc_trng_compwork_handler()
358 u32 *buf = (u32 *)drvdata->circ.buf; in cc_trng_compwork_handler()
360 buf[drvdata->circ.head] = cc_ioread(drvdata, in cc_trng_compwork_handler()
366 if (buf[drvdata->circ.head] == 0) { in cc_trng_compwork_handler()
368 drvdata->active_rosc); in cc_trng_compwork_handler()
372 circ_idx_inc(&drvdata->circ.head, 1<<2); in cc_trng_compwork_handler()
375 atomic_set(&drvdata->pending_hw, 0); in cc_trng_compwork_handler()
379 if (atomic_cmpxchg(&drvdata->pending_hw, 0, 1) == 0) { in cc_trng_compwork_handler()
380 /* Re-enable rnd source */ in cc_trng_compwork_handler()
394 /* trigger trng hw with next rosc */ in cc_trng_compwork_handler()
397 atomic_set(&drvdata->pending_hw, 0); in cc_trng_compwork_handler()
405 struct device *dev = &(drvdata->pdev->dev); in cc_isr()
419 /* clear interrupt - must be before processing events */ in cc_isr()
422 /* RNG interrupt - most probable */ in cc_isr()
424 /* Mask RNG interrupts - will be unmasked in deferred work */ in cc_isr()
436 schedule_work(&drvdata->compwork); in cc_isr()
454 drvdata->active_rosc = 0; in cc_trng_startwork_handler()
461 struct device *dev = &pdev->dev; in cctrng_probe()
468 BUILD_BUG_ON((CCTRNG_DATA_BUF_WORDS & (CCTRNG_DATA_BUF_WORDS-1)) != 0); in cctrng_probe()
472 return -ENOMEM; in cctrng_probe()
474 drvdata->rng.name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL); in cctrng_probe()
475 if (!drvdata->rng.name) in cctrng_probe()
476 return -ENOMEM; in cctrng_probe()
478 drvdata->rng.read = cctrng_read; in cctrng_probe()
479 drvdata->rng.priv = (unsigned long)drvdata; in cctrng_probe()
480 drvdata->rng.quality = CC_TRNG_QUALITY; in cctrng_probe()
483 drvdata->pdev = pdev; in cctrng_probe()
485 drvdata->circ.buf = (char *)drvdata->data_buf; in cctrng_probe()
487 drvdata->cc_base = devm_platform_ioremap_resource(pdev, 0); in cctrng_probe()
488 if (IS_ERR(drvdata->cc_base)) in cctrng_probe()
489 return dev_err_probe(dev, PTR_ERR(drvdata->cc_base), "Failed to ioremap registers"); in cctrng_probe()
501 drvdata->clk = devm_clk_get_optional_enabled(dev, NULL); in cctrng_probe()
502 if (IS_ERR(drvdata->clk)) in cctrng_probe()
503 return dev_err_probe(dev, PTR_ERR(drvdata->clk), in cctrng_probe()
506 INIT_WORK(&drvdata->compwork, cc_trng_compwork_handler); in cctrng_probe()
507 INIT_WORK(&drvdata->startwork, cc_trng_startwork_handler); in cctrng_probe()
508 spin_lock_init(&drvdata->read_lock); in cctrng_probe()
537 atomic_set(&drvdata->pending_hw, 1); in cctrng_probe()
540 rc = devm_hwrng_register(dev, &drvdata->rng); in cctrng_probe()
547 drvdata->active_rosc = 0; in cctrng_probe()
550 /* All set, we can allow auto-suspend */ in cctrng_probe()
566 struct device *dev = &pdev->dev; in cctrng_remove()
583 clk_disable_unprepare(drvdata->clk); in cctrng_suspend()
616 rc = clk_prepare_enable(drvdata->clk); in cctrng_resume()
622 /* wait for Cryptocell reset completion */ in cctrng_resume()
624 dev_err(dev, "Cryptocell reset not completed"); in cctrng_resume()
625 clk_disable_unprepare(drvdata->clk); in cctrng_resume()
626 return -EBUSY; in cctrng_resume()
643 { .compatible = "arm,cryptocell-713-trng", },
644 { .compatible = "arm,cryptocell-703-trng", },
662 MODULE_DESCRIPTION("ARM CryptoCell TRNG Driver");