Index: sys/arm/allwinner/a10_crypto.h =================================================================== --- sys/arm/allwinner/a10_crypto.h +++ sys/arm/allwinner/a10_crypto.h @@ -0,0 +1,135 @@ +/*- + * Copyright (c) 2016 Ganbold Tsagaankhuu + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef A10_CRYPTO_H_ +#define A10_CRYPTO_H_ + +#define A10_SS_CTL 0x00 +#define A10_SS_KEY0 0x04 +#define A10_SS_KEY1 0x08 +#define A10_SS_KEY2 0x0C +#define A10_SS_KEY3 0x10 +#define A10_SS_KEY4 0x14 +#define A10_SS_KEY5 0x18 +#define A10_SS_KEY6 0x1C +#define A10_SS_KEY7 0x20 + +#define A10_SS_IV0 0x24 +#define A10_SS_IV1 0x28 +#define A10_SS_IV2 0x2C +#define A10_SS_IV3 0x30 + +#define A10_SS_FCSR 0x44 + +#define A10_SS_MD0 0x4C +#define A10_SS_MD1 0x50 +#define A10_SS_MD2 0x54 +#define A10_SS_MD3 0x58 +#define A10_SS_MD4 0x5C + +#define A10_SS_RXFIFO 0x200 +#define A10_SS_TXFIFO 0x204 + +/* A10_SS_CTL values */ + +/* PRNG generator mode - bit 15 */ +#define A10_SS_PRNG_ONESHOT (0 << 15) +#define A10_SS_PRNG_CONTINUE (1 << 15) + +/* IV mode for hash */ +#define A10_SS_IV_ARBITRARY (1 << 14) + +/* SS operation mode - bits 12-13 */ +#define A10_SS_ECB (0 << 12) +#define A10_SS_CBC (1 << 12) +#define A10_SS_CTS (3 << 12) + +/* Counter width for CNT mode - bits 10-11 */ +#define A10_SS_CNT_16BITS (0 << 10) +#define A10_SS_CNT_32BITS (1 << 10) +#define A10_SS_CNT_64BITS (2 << 10) + +/* Key size for AES - bits 8-9 */ +#define A10_SS_AES_128BITS (0 << 8) +#define A10_SS_AES_192BITS (1 << 8) +#define A10_SS_AES_256BITS (2 << 8) + +/* Operation direction - bit 7 */ +#define A10_SS_ENCRYPTION (0 << 7) +#define A10_SS_DECRYPTION (1 << 7) + +/* SS Method - bits 4-6 */ +#define A10_SS_OP_AES (0 << 4) +#define A10_SS_OP_DES (1 << 4) +#define A10_SS_OP_3DES (2 << 4) +#define A10_SS_OP_SHA1 (3 << 4) +#define A10_SS_OP_MD5 (4 << 4) +#define A10_SS_OP_PRNG (5 << 4) + +/* Data end bit - bit 2 */ +#define A10_SS_DATA_END (1 << 2) + +/* PRNG start bit - bit 1 */ +#define A10_SS_PRNG_START (1 << 1) + +/* SS Enable bit - bit 0 */ +#define A10_SS_DISABLED (0 << 0) +#define A10_SS_ENABLED (1 << 0) + +/* A10_SS_FCSR configuration values */ +/* RX FIFO status - bit 30 */ +#define A10_SS_RXFIFO_FREE (1 << 30) + +/* RX FIFO empty spaces - bits 24-29 */ +#define A10_SS_RXFIFO_SPACES(val) (((val) >> 24) & 0x3f) + +/* TX FIFO status - bit 22 */ +#define A10_SS_TXFIFO_AVAILABLE (1 << 22) + +/* TX FIFO available spaces - bits 16-21 */ +#define A10_SS_TXFIFO_SPACES(val) (((val) >> 16) & 0x3f) + +#define A10_SS_RX_MAX 32 +#define A10_SS_RX_DEFAULT A10_SS_RX_MAX +#define A10_SS_TX_MAX 33 + +#define A10_SS_RXFIFO_EMP_INT_PENDING (1 << 10) +#define A10_SS_TXFIFO_AVA_INT_PENDING (1 << 8) +#define A10_SS_RXFIFO_EMP_INT_ENABLE (1 << 2) +#define A10_SS_TXFIFO_AVA_INT_ENABLE (1 << 0) + +#define A10_SS_SEED_LEN_BITS 192 +#define A10_SS_SEED_LEN (A10_SS_SEED_LEN_BITS / 8) + +#define A10_SS_DATA_LEN_BITS 160 +#define A10_SS_DATA_LEN (A10_SS_DATA_LEN_BITS / 8) + +#define A10_SS_FIFO_WORDS (A10_SS_SEED_LEN / sizeof(uint32_t)) + +#define DIE_ID_START_BIT 16 +#define DIE_ID_MASK 0x07 + +#endif Index: sys/arm/allwinner/a10_crypto.c =================================================================== --- sys/arm/allwinner/a10_crypto.c +++ sys/arm/allwinner/a10_crypto.c @@ -0,0 +1,268 @@ +/*- + * Copyright (c) 2016 Ganbold Tsagaankhuu + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Allwinner A10/A20 Security System/Crypto accelerator + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +static struct ofw_compat_data compat_data[] = { + { "allwinner,sun4i-a10-crypto", 1 }, + { NULL, 0 } +}; + +struct a10_crypto_softc { + device_t dev; + struct resource *res; + struct callout co; + int ticks; + uint32_t sc_seed[A10_SS_FIFO_WORDS]; + uint32_t sc_buf[A10_SS_FIFO_WORDS]; +}; + +static struct resource_spec a10_crypto_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { -1, 0 } +}; + +#define RD4(sc, reg) bus_read_4((sc)->res, (reg)) +#define WR4(sc, reg, val) bus_write_4((sc)->res, (reg), (val)) + +static void +a10_rng_start(struct a10_crypto_softc *sc) +{ + uint32_t prng_mode; + int i; + + prng_mode = A10_SS_OP_PRNG | A10_SS_PRNG_CONTINUE | A10_SS_ENABLED; + + /* Write PRNG mode */ + WR4(sc, A10_SS_CTL, prng_mode); + + /* Write the seed */ + for (i = 0; i < A10_SS_FIFO_WORDS; i++) + WR4(sc, A10_SS_KEY0 + i * 4, sc->sc_seed[i]); + + /* Start PRNG */ + WR4(sc, A10_SS_CTL, prng_mode | A10_SS_PRNG_START); +} + +static void +a10_rng_stop(struct a10_crypto_softc *sc) +{ + uint32_t ctrl; + + /* Disable PRNG */ + ctrl = RD4(sc, A10_SS_CTL); + ctrl &= ~A10_SS_PRNG_START; + WR4(sc, A10_SS_CTL, ctrl); + + /* Disable and flush FIFO */ + WR4(sc, A10_SS_CTL, A10_SS_DISABLED); +} + +static void +a10_rng_harvest(void *arg) +{ + struct a10_crypto_softc *sc = arg; + uint32_t val; + int i; + + /* Start PRNG */ + a10_rng_start(sc); + + /* Read random data */ + bus_read_multi_4(sc->res, A10_SS_TXFIFO, sc->sc_buf, + A10_SS_DATA_LEN / sizeof(uint32_t)); + + /* Update the seed */ + for (i = 0; i < A10_SS_FIFO_WORDS; i++) { + val = RD4(sc, A10_SS_KEY0 + i * 4); + sc->sc_seed[i] = val; + } + + /* Disable and flush FIFO */ + WR4(sc, A10_SS_CTL, A10_SS_DISABLED); + + random_harvest_queue(sc->sc_buf, sizeof(sc->sc_buf), + sizeof(sc->sc_buf) * NBBY / 2, RANDOM_PURE_ALLWINNER); + + callout_reset(&sc->co, sc->ticks, a10_rng_harvest, sc); +} + +static int +a10_crypto_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "A10/A20 Security System/Crypto accelerator"); + return (BUS_PROBE_DEFAULT); +} + +static int +a10_crypto_attach(device_t dev) +{ + struct a10_crypto_softc *sc; + hwreset_t rst_ahb; + clk_t clk_ss, clk_gate; + int err, i; + uint32_t val = 0; + + sc = device_get_softc(dev); + clk_ss = clk_gate = NULL; + rst_ahb = NULL; + + if (bus_alloc_resources(dev, a10_crypto_spec, &sc->res) != 0) { + device_printf(dev, "cannot allocate resources for device\n"); + return (ENXIO); + } + + /* De-assert reset */ + if (hwreset_get_by_ofw_name(dev, 0, "ahb", &rst_ahb) == 0) { + err = hwreset_deassert(rst_ahb); + if (err != 0) { + device_printf(dev, "cannot de-assert reset\n"); + goto error; + } + } + + /* Get clocks and enable them */ + err = clk_get_by_ofw_name(dev, 0, "ahb", &clk_gate); + if (err != 0) { + device_printf(dev, "Cannot get gate clock\n"); + goto error; + } + err = clk_get_by_ofw_name(dev, 0, "mod", &clk_ss); + if (err != 0) { + device_printf(dev, "Cannot get SS clock\n"); + goto error; + } + err = clk_enable(clk_gate); + if (err != 0) { + device_printf(dev, "Cannot enable clk gate\n"); + goto error; + } + err = clk_enable(clk_ss); + if (err != 0) { + device_printf(dev, "Cannot enable SS clock\n"); + goto error; + } + + /* + * "Die Bonding ID" + */ + WR4(sc, A10_SS_CTL, A10_SS_ENABLED); + val = RD4(sc, A10_SS_CTL); + val >>= DIE_ID_START_BIT; + val &= DIE_ID_MASK; + device_printf(dev, "Die ID %d\n", val); + WR4(sc, A10_SS_CTL, 0); + + /* Install a periodic collector for the RNG */ + if (hz > 100) + sc->ticks = hz / 100; + else + sc->ticks = 1; + + /* Generate the seed fist */ + for (i = 0; i < A10_SS_FIFO_WORDS; i++) + sc->sc_seed[i] = arc4random(); + + callout_init(&sc->co, 1); + callout_reset(&sc->co, sc->ticks, a10_rng_harvest, sc); + + return (0); + +error: + if (clk_gate != NULL) + clk_release(clk_gate); + if (clk_ss != NULL) + clk_release(clk_ss); + if (rst_ahb != NULL) + hwreset_release(rst_ahb); + bus_release_resources(dev, a10_crypto_spec, &sc->res); + return (ENXIO); +} + +static int +a10_crypto_detach(device_t dev) +{ + struct a10_crypto_softc *sc = device_get_softc(dev); + + a10_rng_stop(sc); + callout_drain(&sc->co); + + bus_release_resources(dev, a10_crypto_spec, &sc->res); + + return (0); +} + +static device_method_t a10_crypto_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, a10_crypto_probe), + DEVMETHOD(device_attach, a10_crypto_attach), + DEVMETHOD(device_detach, a10_crypto_detach), + + DEVMETHOD_END +}; + +static driver_t a10_crypto_driver = { + "a10_crypto", + a10_crypto_methods, + sizeof(struct a10_crypto_softc), +}; + +static devclass_t a10_crypto_devclass; + +DRIVER_MODULE(a10_crypto, simplebus, a10_crypto_driver, a10_crypto_devclass, 0, 0); +MODULE_VERSION(a10_crypto, 1); +MODULE_DEPEND(a10_crypto, crypto, 1, 1, 1); +MODULE_DEPEND(a10_crypto, randomdev, 1, 1, 1); Index: sys/arm/allwinner/files.allwinner =================================================================== --- sys/arm/allwinner/files.allwinner +++ sys/arm/allwinner/files.allwinner @@ -29,6 +29,7 @@ arm/allwinner/aw_sid.c standard arm/allwinner/aw_thermal.c standard dev/iicbus/sy8106a.c optional sy8106a +arm/allwinner/a10_crypto.c optional a10_crypto random #arm/allwinner/console.c standard arm/allwinner/a10_fb.c optional vt Index: sys/arm/conf/ALLWINNER =================================================================== --- sys/arm/conf/ALLWINNER +++ sys/arm/conf/ALLWINNER @@ -86,6 +86,10 @@ device axp81x # AXP813/818 Power Management Unit device sy8106a # SY8106A Buck Regulator +device a10_crypto +device crypto +device cryptodev + # GPIO device gpio device gpioled Index: sys/arm/conf/ALLWINNER_UP =================================================================== --- sys/arm/conf/ALLWINNER_UP +++ sys/arm/conf/ALLWINNER_UP @@ -70,6 +70,10 @@ device pcf8563 # RTC +device a10_crypto +device crypto +device cryptodev + # GPIO device gpio device gpioled Index: sys/dev/random/random_harvestq.c =================================================================== --- sys/dev/random/random_harvestq.c +++ sys/dev/random/random_harvestq.c @@ -280,6 +280,8 @@ "PURE_RDRAND", "PURE_NEHEMIAH", "PURE_RNDTEST", + "PURE_VIRTIO", + "PURE_ALLWINNER", /* "ENTROPYSOURCE" */ }; Index: sys/sys/random.h =================================================================== --- sys/sys/random.h +++ sys/sys/random.h @@ -90,6 +90,7 @@ RANDOM_PURE_NEHEMIAH, RANDOM_PURE_RNDTEST, RANDOM_PURE_VIRTIO, + RANDOM_PURE_ALLWINNER, RANDOM_PURE_BROADCOM, ENTROPYSOURCE };