summaryrefslogtreecommitdiffstats
path: root/sys/dev/hifn/hifn7751.c
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2005-01-19 17:03:35 +0000
committersam <sam@FreeBSD.org>2005-01-19 17:03:35 +0000
commitd8d2e1377d2504ca7ce7668789ac9fd846369867 (patch)
tree82b13bea8e717b5f15afaf1b96a251a7bfddb027 /sys/dev/hifn/hifn7751.c
parent91cec8c109d11b0b969effab2c7e7eabd01ed8ae (diff)
downloadFreeBSD-src-d8d2e1377d2504ca7ce7668789ac9fd846369867.zip
FreeBSD-src-d8d2e1377d2504ca7ce7668789ac9fd846369867.tar.gz
Update support for 795x parts:
o rework pll setup code to follow h/w specification o add hint.hifn.X.pllconfig to specify reference clock setup requirements; default is pci66 which means the clock is derived from the PCI bus clock and the card resides in a 66MHz slot Tested on 7955 and 7956 cards; support for 7954 cards not enabled since we have no cards to test against. In collaboration with Poul-Henning Kamp. Reviewed by: phk MFC after: 1 week
Diffstat (limited to 'sys/dev/hifn/hifn7751.c')
-rw-r--r--sys/dev/hifn/hifn7751.c115
1 files changed, 112 insertions, 3 deletions
diff --git a/sys/dev/hifn/hifn7751.c b/sys/dev/hifn/hifn7751.c
index 2df4de7..a435494 100644
--- a/sys/dev/hifn/hifn7751.c
+++ b/sys/dev/hifn/hifn7751.c
@@ -249,6 +249,84 @@ default_harvest(struct rndtest_state *rsp, void *buf, u_int count)
random_harvest(buf, count, count*NBBY, 0, RANDOM_PURE);
}
+static u_int
+checkmaxmin(device_t dev, const char *what, u_int v, u_int min, u_int max)
+{
+ if (v > max) {
+ device_printf(dev, "Warning, %s %u out of range, "
+ "using max %u\n", what, v, max);
+ v = max;
+ } else if (v < min) {
+ device_printf(dev, "Warning, %s %u out of range, "
+ "using min %u\n", what, v, min);
+ v = min;
+ }
+ return v;
+}
+
+/*
+ * Select PLL configuration for 795x parts. This is complicated in
+ * that we cannot determine the optimal parameters without user input.
+ * The reference clock is derived from an external clock through a
+ * multiplier. The external clock is either the host bus (i.e. PCI)
+ * or an external clock generator. When using the PCI bus we assume
+ * the clock is either 33 or 66 MHz; for an external source we cannot
+ * tell the speed.
+ *
+ * PLL configuration is done with a string: "pci" for PCI bus, or "ext"
+ * for an external source, followed by the frequency. We calculate
+ * the appropriate multiplier and PLL register contents accordingly.
+ * When no configuration is given we default to "pci66" since that
+ * always will allow the card to work. If a card is using the PCI
+ * bus clock and in a 33MHz slot then it will be operating at half
+ * speed until the correct information is provided.
+ */
+static void
+hifn_getpllconfig(device_t dev, u_int *pll)
+{
+ const char *pllspec;
+ u_int freq, mul, fl, fh;
+ u_int32_t pllconfig;
+ char *nxt;
+
+ if (resource_string_value("hifn", device_get_unit(dev),
+ "pllconfig", &pllspec))
+ pllspec = "pci66";
+ fl = 33, fh = 66;
+ pllconfig = 0;
+ if (strncmp(pllspec, "ext", 3) == 0) {
+ pllspec += 3;
+ pllconfig |= HIFN_PLL_REF_SEL;
+ switch (pci_get_device(dev)) {
+ case PCI_PRODUCT_HIFN_7955:
+ case PCI_PRODUCT_HIFN_7956:
+ fl = 20, fh = 100;
+ break;
+#ifdef notyet
+ case PCI_PRODUCT_HIFN_7954:
+ fl = 20, fh = 66;
+ break;
+#endif
+ }
+ } else if (strncmp(pllspec, "pci", 3) == 0)
+ pllspec += 3;
+ freq = strtoul(pllspec, &nxt, 10);
+ if (nxt == pllspec)
+ freq = 66;
+ else
+ freq = checkmaxmin(dev, "frequency", freq, fl, fh);
+ /*
+ * Calculate multiplier. We target a Fck of 266 MHz,
+ * allowing only even values, possibly rounded down.
+ * Multipliers > 8 must set the charge pump current.
+ */
+ mul = checkmaxmin(dev, "PLL divisor", (266 / freq) &~ 1, 2, 12);
+ pllconfig |= (mul / 2 - 1) << HIFN_PLL_ND_SHIFT;
+ if (mul > 8)
+ pllconfig |= HIFN_PLL_IS;
+ *pll = pllconfig;
+}
+
/*
* Attach an interface that successfully probed.
*/
@@ -292,8 +370,15 @@ hifn_attach(device_t dev)
*/
if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&
(pci_get_device(dev) == PCI_PRODUCT_HIFN_7955 ||
- pci_get_device(dev) == PCI_PRODUCT_HIFN_7956))
+ pci_get_device(dev) == PCI_PRODUCT_HIFN_7956)) {
sc->sc_flags |= HIFN_IS_7956 | HIFN_HAS_AES;
+ /*
+ * Select PLL configuration. This depends on the
+ * bus and board design and must be manually configured
+ * if the default setting is unacceptable.
+ */
+ hifn_getpllconfig(dev, &sc->sc_pllconfig);
+ }
/*
* Configure support for memory-mapped access to
@@ -465,9 +550,15 @@ hifn_attach(device_t dev)
rbase = 'M';
rseg /= 1024;
}
- device_printf(sc->sc_dev, "%s, rev %u, %d%cB %cram\n",
+ device_printf(sc->sc_dev, "%s, rev %u, %d%cB %cram",
hifn_partname(sc), rev,
rseg, rbase, sc->sc_drammodel ? 'd' : 's');
+ if (sc->sc_flags & HIFN_IS_7956)
+ printf(", pll=0x%x<%s clk, %ux mult>",
+ sc->sc_pllconfig,
+ sc->sc_pllconfig & HIFN_PLL_REF_SEL ? "ext" : "pci",
+ 2 + 2*((sc->sc_pllconfig & HIFN_PLL_ND) >> 11));
+ printf("\n");
sc->sc_cid = crypto_get_driverid(0);
if (sc->sc_cid < 0) {
@@ -1089,10 +1180,28 @@ hifn_init_pci_registers(struct hifn_softc *sc)
if (sc->sc_flags & HIFN_IS_7956) {
+ u_int32_t pll;
+
WRITE_REG_0(sc, HIFN_0_PUCNFG, HIFN_PUCNFG_COMPSING |
HIFN_PUCNFG_TCALLPHASES |
HIFN_PUCNFG_TCDRVTOTEM | HIFN_PUCNFG_BUS32);
- WRITE_REG_1(sc, HIFN_1_PLL, HIFN_PLL_7956);
+
+ /* turn off the clocks and insure bypass is set */
+ pll = READ_REG_1(sc, HIFN_1_PLL);
+ pll = (pll &~ (HIFN_PLL_PK_CLK_SEL | HIFN_PLL_PE_CLK_SEL))
+ | HIFN_PLL_BP;
+ WRITE_REG_1(sc, HIFN_1_PLL, pll);
+ DELAY(10*1000); /* 10ms */
+ /* change configuration */
+ pll = (pll &~ HIFN_PLL_CONFIG) | sc->sc_pllconfig;
+ WRITE_REG_1(sc, HIFN_1_PLL, pll);
+ DELAY(10*1000); /* 10ms */
+ /* disable bypass */
+ pll &= ~HIFN_PLL_BP;
+ WRITE_REG_1(sc, HIFN_1_PLL, pll);
+ /* enable clocks with new configuration */
+ pll |= HIFN_PLL_PK_CLK_SEL | HIFN_PLL_PE_CLK_SEL;
+ WRITE_REG_1(sc, HIFN_1_PLL, pll);
} else {
WRITE_REG_0(sc, HIFN_0_PUCNFG, HIFN_PUCNFG_COMPSING |
HIFN_PUCNFG_DRFR_128 | HIFN_PUCNFG_TCALLPHASES |
OpenPOWER on IntegriCloud