while (max >= sizeof(u32)) { /* check for data */ if (readl(trng->mem + STATUS_REG) == TRNG_NEW_RAND_AVAILABLE) {
*(u32 *)buf = readl(trng->mem + RAND_REG); /* * Inform the trng of the read * and re-enable it to produce a new random number
*/
writel(HOST_TO_TRNG_READ, trng->mem + CONTROL_REG);
writel(HOST_TO_TRNG_ENABLE, trng->mem + CONTROL_REG);
ret += sizeof(u32);
buf += sizeof(u32);
max -= sizeof(u32);
} else { break;
}
} return ret;
}
trng = devm_kzalloc(dev, sizeof(*trng), GFP_KERNEL); if (!trng) return -ENOMEM;
trng->mem = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(trng->mem)) return PTR_ERR(trng->mem);
/* * the trng needs to be reset first which might not happen in time, * hence we incorporate a small delay to ensure proper behaviour
*/
writel(HOST_TO_TRNG_RESET, trng->mem + CONTROL_REG);
usleep_range(100, 200);
if (readl(trng->mem + STATUS_REG) != TRNG_ACK_RESET) { /* * there is a small chance the trng is just not ready yet, * so we try one more time. If the second time fails, we give up
*/
usleep_range(100, 200); if (readl(trng->mem + STATUS_REG) != TRNG_ACK_RESET) {
dev_err(dev, "failed to reset the trng ip\n"); return -ENODEV;
}
}
/* * once again, to ensure proper behaviour we sleep * for a while after zeroizing the trng
*/
writel(HOST_TO_TRNG_RELEASE_RESET, trng->mem + CONTROL_REG);
writel(HOST_TO_TRNG_ENABLE, trng->mem + CONTROL_REG);
writel(HOST_TO_TRNG_ZEROIZE, trng->mem + CONTROL_REG);
msleep(20);
if (readl(trng->mem + STATUS_REG) != TRNG_SUCCESSFUL_STARTUP) { /* diagnose the reason for the failure */ if (readl(trng->mem + STATUS_REG) == TRNG_FAILED_STARTUP) {
dev_err(dev, "trng ip startup-tests failed\n"); return -ENODEV;
}
dev_err(dev, "startup-tests yielded no response\n"); return -ENODEV;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.