Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F107179373
D22493.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D22493.diff
View Options
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_rng.c b/sys/arm/broadcom/bcm2835/bcm2835_rng.c
--- a/sys/arm/broadcom/bcm2835/bcm2835_rng.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_rng.c
@@ -69,21 +69,26 @@
#define RNG_RBG2X 0x00000002 /* RBG 2X SPEED */
#define RNG_RBGEN_BIT 0x00000001 /* Enable RNG bit */
-#define RNG_STATUS 0x04 /* RNG status register */
-#define RND_VAL_SHIFT 24 /* Shift for valid words */
-#define RND_VAL_MASK 0x000000ff /* Number valid words mask */
-#define RND_VAL_WARM_CNT 0x40000 /* RNG Warm Up count */
-#define RND_WARM_CNT 0xfffff /* RNG Warm Up Count mask */
+#define BCM2835_RNG_STATUS 0x04 /* BCM2835 RNG status register */
+#define BCM2838_RNG_STATUS 0x18 /* BCM2838 RNG status register */
-#define RNG_DATA 0x08 /* RNG Data Register */
+#define BCM2838_RNG_COUNT 0x24 /* How many values available */
+#define BCM2838_COUNT_VAL_MASK 0x000000ff
+
+#define BCM2835_RND_VAL_SHIFT 24 /* Shift for valid words */
+#define BCM2835_RND_VAL_MASK 0x000000ff /* Number valid words mask */
+#define BCM2835_RND_VAL_WARM_CNT 0x40000 /* RNG Warm Up count */
+#define BCM2835_RND_WARM_CNT 0xfffff /* RNG Warm Up Count mask */
+
+#define BCM2835_RNG_DATA 0x08 /* RNG Data Register */
+#define BCM2838_RNG_DATA 0x20
#define RNG_FF_THRES 0x0c
#define RNG_FF_THRES_MASK 0x0000001f
-#define RNG_INT_MASK 0x10
-#define RNG_INT_OFF_BIT 0x00000001
+#define BCM2835_RNG_INT_MASK 0x10
+#define BCM2835_RNG_INT_OFF_BIT 0x00000001
#define RNG_FF_DEFAULT 0x10 /* FIFO threshold default */
-
#define RNG_FIFO_WORDS (RNG_FF_DEFAULT / sizeof(uint32_t))
#define RNG_NUM_OSCILLATORS 6
@@ -91,11 +96,55 @@
#define RNG_CALLOUT_TICKS (hz * 4)
+struct bcm_rng_conf {
+ bus_size_t control_reg;
+ bus_size_t status_reg;
+ bus_size_t count_reg;
+ bus_size_t data_reg;
+ bus_size_t intr_mask_reg;
+ uint32_t intr_disable_bit;
+ uint32_t count_value_shift;
+ uint32_t count_value_mask;
+ uint32_t warmup_count;
+ bool allow_2x_mode;
+ bool can_diagnose;
+ /* XXX diag regs */
+};
+
+static const struct bcm_rng_conf bcm2835_rng_conf = {
+ .control_reg = RNG_CTRL,
+ .status_reg = BCM2835_RNG_STATUS,
+ .count_reg = BCM2835_RNG_STATUS, /* Same register */
+ .data_reg = BCM2835_RNG_DATA,
+ .intr_mask_reg = BCM2835_RNG_INT_MASK,
+ .intr_disable_bit = BCM2835_RNG_INT_OFF_BIT,
+ .count_value_shift = BCM2835_RND_VAL_SHIFT,
+ .count_value_mask = BCM2835_RND_VAL_MASK,
+ .warmup_count = BCM2835_RND_VAL_WARM_CNT,
+ .allow_2x_mode = true,
+ .can_diagnose = true
+};
+
+static const struct bcm_rng_conf bcm2838_rng_conf = {
+ .control_reg = RNG_CTRL,
+ .status_reg = BCM2838_RNG_STATUS,
+ .count_reg = BCM2838_RNG_COUNT,
+ .data_reg = BCM2838_RNG_DATA,
+ .intr_mask_reg = 0,
+ .intr_disable_bit = 0,
+ .count_value_shift = 0,
+ .count_value_mask = BCM2838_COUNT_VAL_MASK,
+ .warmup_count = 0,
+ .allow_2x_mode = false,
+ .can_diagnose = false
+};
+
struct bcm2835_rng_softc {
device_t sc_dev;
struct resource * sc_mem_res;
struct resource * sc_irq_res;
void * sc_intr_hdl;
+ struct bcm_rng_conf const* conf;
uint32_t sc_buf[RNG_FIFO_WORDS];
struct callout sc_rngto;
int sc_stall_count;
@@ -104,8 +153,15 @@
};
static struct ofw_compat_data compat_data[] = {
- {"broadcom,bcm2835-rng", 1},
- {"brcm,bcm2835-rng", 1},
+ {"broadcom,bcm2835-rng", (uintptr_t)&bcm2835_rng_conf},
+ {"brcm,bcm2835-rng", (uintptr_t)&bcm2835_rng_conf},
+
+ {"brcm,bcm2711-rng200", (uintptr_t)&bcm2838_rng_conf},
+ {"brcm,bcm2838-rng", (uintptr_t)&bcm2838_rng_conf},
+ {"brcm,bcm2838-rng200", (uintptr_t)&bcm2838_rng_conf},
+ {"brcm,bcm7211-rng", (uintptr_t)&bcm2838_rng_conf},
+ {"brcm,bcm7278-rng", (uintptr_t)&bcm2838_rng_conf},
+ {"brcm,iproc-rng200", (uintptr_t)&bcm2838_rng_conf},
{NULL, 0}
};
@@ -144,8 +200,12 @@
uint32_t comblk2_osc, comblk1_osc, jclk_byp_div, val;
int i;
+ if (!sc->conf->can_diagnose)
+ /* Not implemented. */
+ return;
+
/* Display RNG control register contents */
- val = bcm2835_rng_read4(sc, RNG_CTRL);
+ val = bcm2835_rng_read4(sc, sc->conf->control_reg);
sbuf_printf(sbp, "RNG_CTRL (%08x)\n", val);
comblk2_osc = (val & RNG_COMBLK2_OSC) >> RNG_COMBLK2_OSC_SHIFT;
@@ -181,20 +241,20 @@
sbuf_cat(sbp, " RNG_RBGEN_BIT: RBG enabled\n");
/* Display RNG status register contents */
- val = bcm2835_rng_read4(sc, RNG_STATUS);
+ val = bcm2835_rng_read4(sc, sc->conf->status_reg);
sbuf_printf(sbp, "RNG_CTRL (%08x)\n", val);
sbuf_printf(sbp, " RND_VAL: %02x\n",
- (val >> RND_VAL_SHIFT) & RND_VAL_MASK);
- sbuf_printf(sbp, " RND_WARM_CNT: %05x\n", val & RND_WARM_CNT);
+ (val >> sc->conf->count_value_shift) & sc->conf->count_value_mask);
+ sbuf_printf(sbp, " RND_WARM_CNT: %05x\n", val & sc->conf->warmup_count);
/* Display FIFO threshold register contents */
val = bcm2835_rng_read4(sc, RNG_FF_THRES);
sbuf_printf(sbp, "RNG_FF_THRES: %05x\n", val & RNG_FF_THRES_MASK);
/* Display interrupt mask register contents */
- val = bcm2835_rng_read4(sc, RNG_INT_MASK);
+ val = bcm2835_rng_read4(sc, sc->conf->intr_mask_reg);
sbuf_printf(sbp, "RNG_INT_MASK: interrupt %s\n",
- ((val & RNG_INT_OFF_BIT) != 0) ? "disabled" : "enabled");
+ ((val & sc->conf->intr_disable_bit) != 0) ? "disabled" : "enabled");
}
static void
@@ -203,9 +263,9 @@
uint32_t mask;
/* Set the interrupt off bit in the interrupt mask register */
- mask = bcm2835_rng_read4(sc, RNG_INT_MASK);
- mask |= RNG_INT_OFF_BIT;
- bcm2835_rng_write4(sc, RNG_INT_MASK, mask);
+ mask = bcm2835_rng_read4(sc, sc->conf->intr_mask_reg);
+ mask |= sc->conf->intr_disable_bit;
+ bcm2835_rng_write4(sc, sc->conf->intr_mask_reg, mask);
}
static void
@@ -214,17 +274,20 @@
uint32_t ctrl;
/* Disable the interrupt */
- bcm2835_rng_disable_intr(sc);
+ if (sc->conf->intr_mask_reg)
+ bcm2835_rng_disable_intr(sc);
/* Set the warmup count */
- bcm2835_rng_write4(sc, RNG_STATUS, RND_VAL_WARM_CNT);
+ if (sc->conf->warmup_count > 0)
+ bcm2835_rng_write4(sc, sc->conf->status_reg,
+ sc->conf->warmup_count);
/* Enable the RNG */
- ctrl = bcm2835_rng_read4(sc, RNG_CTRL);
+ ctrl = bcm2835_rng_read4(sc, sc->conf->control_reg);
ctrl |= RNG_RBGEN_BIT;
- if (sc->sc_rbg2x)
+ if (sc->sc_rbg2x && sc->conf->allow_2x_mode)
ctrl |= RNG_RBG2X;
- bcm2835_rng_write4(sc, RNG_CTRL, ctrl);
+ bcm2835_rng_write4(sc, sc->conf->control_reg, ctrl);
}
static void
@@ -233,16 +296,39 @@
uint32_t ctrl;
/* Disable the RNG */
- ctrl = bcm2835_rng_read4(sc, RNG_CTRL);
+ ctrl = bcm2835_rng_read4(sc, sc->conf->control_reg);
ctrl &= ~RNG_RBGEN_BIT;
- bcm2835_rng_write4(sc, RNG_CTRL, ctrl);
+ bcm2835_rng_write4(sc, sc->conf->control_reg, ctrl);
+}
+
+static void
+bcm2835_rng_enqueue_harvest(struct bcm2835_rng_softc *sc, uint32_t nread)
+{
+ char *sc_buf_chunk;
+ uint32_t chunk_size;
+ uint32_t cnt;
+
+ chunk_size = sizeof(((struct harvest_event *)0)->he_entropy);
+ cnt = nread * sizeof(uint32_t);
+ sc_buf_chunk = (void*)sc->sc_buf;
+
+ while (cnt > 0) {
+ uint32_t size;
+
+ size = MIN(cnt, chunk_size);
+
+ random_harvest_queue(sc_buf_chunk, size, RANDOM_PURE_BROADCOM);
+
+ sc_buf_chunk += size;
+ cnt -= size;
+ }
}
static void
bcm2835_rng_harvest(void *arg)
{
uint32_t *dest;
- uint32_t status;
+ uint32_t hwcount;
u_int cnt, nread, num_avail, num_words;
int seen_underrun, num_stalls;
struct bcm2835_rng_softc *sc = arg;
@@ -250,11 +336,13 @@
dest = sc->sc_buf;
nread = num_words = 0;
seen_underrun = num_stalls = 0;
+
for (cnt = sizeof(sc->sc_buf) / sizeof(uint32_t); cnt > 0;
cnt -= num_words) {
- /* Read status register to find out how many words available */
- status = bcm2835_rng_read4(sc, RNG_STATUS);
- num_avail = (status >> RND_VAL_SHIFT) & RND_VAL_MASK;
+ /* Read count register to find out how many words available */
+ hwcount = bcm2835_rng_read4(sc, sc->conf->count_reg);
+ num_avail = (hwcount >> sc->conf->count_value_shift) &
+ sc->conf->count_value_mask;
/* If we have none... */
if (num_avail == 0) {
@@ -282,15 +370,13 @@
/* Pull MIN(num_avail, cnt) words from the FIFO */
num_words = (num_avail > cnt) ? cnt : num_avail;
- bcm2835_rng_read_multi4(sc, RNG_DATA, dest,
+ bcm2835_rng_read_multi4(sc, sc->conf->data_reg, dest,
num_words);
dest += num_words;
nread += num_words;
}
- cnt = nread * sizeof(uint32_t);
- if (cnt > 0)
- random_harvest_queue(sc->sc_buf, cnt, RANDOM_PURE_BROADCOM);
+ bcm2835_rng_enqueue_harvest(sc, nread);
callout_reset(&sc->sc_rngto, RNG_CALLOUT_TICKS, bcm2835_rng_harvest, sc);
}
@@ -347,7 +433,7 @@
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
return (ENXIO);
- device_set_desc(dev, "Broadcom BCM2835 RNG");
+ device_set_desc(dev, "Broadcom BCM2835/BCM2838 RNG");
return (BUS_PROBE_DEFAULT);
}
@@ -363,13 +449,18 @@
error = 0;
sc = device_get_softc(dev);
sc->sc_dev = dev;
+
+ sc->conf = (void const*)ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+ KASSERT(sc->conf != NULL, ("bcm2835_rng_attach: sc->conf == NULL"));
+
sc->sc_stall_count = RNG_STALL_COUNT_DEFAULT;
/* Initialize callout */
callout_init(&sc->sc_rngto, CALLOUT_MPSAFE);
- TUNABLE_INT_FETCH("bcmrng.2xspeed", &sc->sc_rbg2x);
TUNABLE_INT_FETCH("bcmrng.stall_count", &sc->sc_stall_count);
+ if (sc->conf->allow_2x_mode)
+ TUNABLE_INT_FETCH("bcmrng.2xspeed", &sc->sc_rbg2x);
/* Allocate memory resources */
rid = 0;
@@ -402,9 +493,10 @@
SYSCTL_ADD_LONG(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
"underrun", CTLFLAG_RD, &sc->sc_underrun,
"Number of FIFO underruns");
- SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
- "2xspeed", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0,
- sysctl_bcm2835_rng_2xspeed, "I", "Enable RBG 2X SPEED");
+ if (sc->conf->allow_2x_mode)
+ SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
+ "2xspeed", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0,
+ sysctl_bcm2835_rng_2xspeed, "I", "Enable RBG 2X SPEED");
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
"stall_count", CTLFLAG_RW, &sc->sc_stall_count,
RNG_STALL_COUNT_DEFAULT, "Number of underruns to assume RNG stall");
@@ -414,7 +506,7 @@
sysctl_bcm2835_rng_dump, "S", "Dump RNG registers");
#endif
- /*
+ /*
* Schedule the initial harvesting one second from now, which should give the
* hardware RNG plenty of time to generate the first random bytes.
*/
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Jan 12, 7:59 AM (21 h, 16 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15763528
Default Alt Text
D22493.diff (10 KB)
Attached To
Mode
D22493: Support for bcm2838 RNG
Attached
Detach File
Event Timeline
Log In to Comment