summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2011-01-01 10:48:32 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2011-01-01 10:48:32 +0000
commite75566f559b3be4c3b3772259d5427922b30eda3 (patch)
tree3adb81bbc7a66fc1035ffd26913367e5d5ae6a6d
parenta415c202b77edd9c5b7b38e1bff0cb700ce1416c (diff)
add code to read OTPROM on the AR9485
-rw-r--r--sys/dev/ic/ar5008.c18
-rw-r--r--sys/dev/ic/ar9003.c124
-rw-r--r--sys/dev/ic/ar9003reg.h17
-rw-r--r--sys/dev/ic/ar9380.c4
-rw-r--r--sys/dev/ic/ar9380reg.h3
-rw-r--r--sys/dev/ic/athnvar.h3
6 files changed, 139 insertions, 30 deletions
diff --git a/sys/dev/ic/ar5008.c b/sys/dev/ic/ar5008.c
index c6cbeaa228b..ae1e31ffa97 100644
--- a/sys/dev/ic/ar5008.c
+++ b/sys/dev/ic/ar5008.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar5008.c,v 1.17 2010/12/31 17:50:48 damien Exp $ */
+/* $OpenBSD: ar5008.c,v 1.18 2011/01/01 10:48:31 damien Exp $ */
/*-
* Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
@@ -66,7 +66,7 @@
#include <dev/ic/ar5008reg.h>
int ar5008_attach(struct athn_softc *);
-int ar5008_read_rom_word(struct athn_softc *, uint32_t, uint16_t *);
+int ar5008_read_eep_word(struct athn_softc *, uint32_t, uint16_t *);
int ar5008_read_rom(struct athn_softc *);
void ar5008_swap_rom(struct athn_softc *);
int ar5008_gpio_read(struct athn_softc *, int);
@@ -204,7 +204,7 @@ ar5008_attach(struct athn_softc *sc)
/* Read entire ROM content in memory. */
if ((error = ar5008_read_rom(sc)) != 0) {
- printf(": could not read ROM\n");
+ printf("%s: could not read ROM\n", sc->sc_dev.dv_xname);
return (error);
}
@@ -215,8 +215,8 @@ ar5008_attach(struct athn_softc *sc)
eep_ver = (base->version >> 12) & 0xf;
sc->eep_rev = (base->version & 0xfff);
if (eep_ver != AR_EEP_VER || sc->eep_rev == 0) {
- printf(": unsupported ROM version %d.%d\n", eep_ver,
- sc->eep_rev);
+ printf("%s: unsupported ROM version %d.%d\n",
+ sc->sc_dev.dv_xname, eep_ver, sc->eep_rev);
return (EINVAL);
}
@@ -258,10 +258,10 @@ ar5008_attach(struct athn_softc *sc)
}
/*
- * Read 16-bit value from ROM.
+ * Read 16-bit word from ROM.
*/
int
-ar5008_read_rom_word(struct athn_softc *sc, uint32_t addr, uint16_t *val)
+ar5008_read_eep_word(struct athn_softc *sc, uint32_t addr, uint16_t *val)
{
uint32_t reg;
int ntries;
@@ -289,7 +289,7 @@ ar5008_read_rom(struct athn_softc *sc)
int error;
/* Determine ROM endianness. */
- error = ar5008_read_rom_word(sc, AR_EEPROM_MAGIC_OFFSET, &magic);
+ error = ar5008_read_eep_word(sc, AR_EEPROM_MAGIC_OFFSET, &magic);
if (error != 0)
return (error);
if (magic != AR_EEPROM_MAGIC) {
@@ -312,7 +312,7 @@ ar5008_read_rom(struct athn_softc *sc)
eep = sc->eep;
end = sc->eep_base + sc->eep_size / sizeof(uint16_t);
for (addr = sc->eep_base; addr < end; addr++, eep++) {
- if ((error = ar5008_read_rom_word(sc, addr, eep)) != 0) {
+ if ((error = ar5008_read_eep_word(sc, addr, eep)) != 0) {
DPRINTF(("could not read ROM at 0x%x\n", addr));
return (error);
}
diff --git a/sys/dev/ic/ar9003.c b/sys/dev/ic/ar9003.c
index dab3f03a297..4c3da50dbb3 100644
--- a/sys/dev/ic/ar9003.c
+++ b/sys/dev/ic/ar9003.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar9003.c,v 1.20 2010/12/31 21:23:55 damien Exp $ */
+/* $OpenBSD: ar9003.c,v 1.21 2011/01/01 10:48:31 damien Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
@@ -66,8 +66,11 @@
#include <dev/ic/ar9003reg.h>
int ar9003_attach(struct athn_softc *);
-int ar9003_read_rom_word(struct athn_softc *, uint32_t, uint16_t *);
-int ar9003_read_rom_data(struct athn_softc *, uint32_t, void *, int);
+int ar9003_read_eep_word(struct athn_softc *, uint32_t, uint16_t *);
+int ar9003_read_eep_data(struct athn_softc *, uint32_t, void *, int);
+int ar9003_read_otp_word(struct athn_softc *, uint32_t, uint32_t *);
+int ar9003_read_otp_data(struct athn_softc *, uint32_t, void *, int);
+int ar9003_find_rom(struct athn_softc *);
int ar9003_restore_rom_block(struct athn_softc *, uint8_t, uint8_t,
const uint8_t *, int);
int ar9003_read_rom(struct athn_softc *);
@@ -208,9 +211,14 @@ ar9003_attach(struct athn_softc *sc)
else
athn_config_pcie(sc);
+ /* Determine ROM type and location. */
+ if ((error = ar9003_find_rom(sc)) != 0) {
+ printf("%s: could not find ROM\n", sc->sc_dev.dv_xname);
+ return (error);
+ }
/* Read entire ROM content in memory. */
if ((error = ar9003_read_rom(sc)) != 0) {
- printf(": could not read ROM\n");
+ printf("%s: could not read ROM\n", sc->sc_dev.dv_xname);
return (error);
}
@@ -223,10 +231,10 @@ ar9003_attach(struct athn_softc *sc)
}
/*
- * Read 16-bit value from ROM.
+ * Read 16-bit word from ROM.
*/
int
-ar9003_read_rom_word(struct athn_softc *sc, uint32_t addr, uint16_t *val)
+ar9003_read_eep_word(struct athn_softc *sc, uint32_t addr, uint16_t *val)
{
uint32_t reg;
int ntries;
@@ -250,7 +258,7 @@ ar9003_read_rom_word(struct athn_softc *sc, uint32_t addr, uint16_t *val)
* NB: The address may not be 16-bit aligned.
*/
int
-ar9003_read_rom_data(struct athn_softc *sc, uint32_t addr, void *buf, int len)
+ar9003_read_eep_data(struct athn_softc *sc, uint32_t addr, void *buf, int len)
{
uint8_t *dst = buf;
uint16_t val;
@@ -259,7 +267,7 @@ ar9003_read_rom_data(struct athn_softc *sc, uint32_t addr, void *buf, int len)
if (len > 0 && (addr & 1)) {
/* Deal with non-aligned reads. */
addr >>= 1;
- error = ar9003_read_rom_word(sc, addr, &val);
+ error = ar9003_read_eep_word(sc, addr, &val);
if (error != 0)
return (error);
*dst++ = val & 0xff;
@@ -268,14 +276,14 @@ ar9003_read_rom_data(struct athn_softc *sc, uint32_t addr, void *buf, int len)
} else
addr >>= 1;
for (; len >= 2; addr--, len -= 2) {
- error = ar9003_read_rom_word(sc, addr, &val);
+ error = ar9003_read_eep_word(sc, addr, &val);
if (error != 0)
return (error);
*dst++ = val >> 8;
*dst++ = val & 0xff;
}
if (len > 0) {
- error = ar9003_read_rom_word(sc, addr, &val);
+ error = ar9003_read_eep_word(sc, addr, &val);
if (error != 0)
return (error);
*dst++ = val >> 8;
@@ -283,6 +291,91 @@ ar9003_read_rom_data(struct athn_softc *sc, uint32_t addr, void *buf, int len)
return (0);
}
+/*
+ * Read 32-bit word from OTPROM.
+ */
+int
+ar9003_read_otp_word(struct athn_softc *sc, uint32_t addr, uint32_t *val)
+{
+ uint32_t reg;
+ int ntries;
+
+ reg = AR_READ(sc, AR_OTP_BASE(addr));
+ for (ntries = 0; ntries < 1000; ntries++) {
+ reg = AR_READ(sc, AR_OTP_STATUS);
+ if (MS(reg, AR_OTP_STATUS_TYPE) == AR_OTP_STATUS_VALID) {
+ *val = AR_READ(sc, AR_OTP_READ_DATA);
+ return (0);
+ }
+ DELAY(10);
+ }
+ return (ETIMEDOUT);
+}
+
+/*
+ * Read an arbitrary number of bytes at a specified address in OTPROM.
+ * NB: The address may not be 32-bit aligned.
+ */
+int
+ar9003_read_otp_data(struct athn_softc *sc, uint32_t addr, void *buf, int len)
+{
+ uint8_t *dst = buf;
+ uint32_t val;
+ int error;
+
+ /* NB: not optimal for non-aligned reads, but correct. */
+ for (; len > 0; addr--, len--) {
+ error = ar9003_read_otp_word(sc, addr >> 2, &val);
+ if (error != 0)
+ return (error);
+ *dst++ = (val >> ((addr & 3) * 8)) & 0xff;
+ }
+ return (0);
+}
+
+/*
+ * Determine if the chip has an external EEPROM or an OTPROM and its size.
+ */
+int
+ar9003_find_rom(struct athn_softc *sc)
+{
+ struct athn_ops *ops = &sc->ops;
+ uint32_t hdr;
+ int error;
+
+ /* Try EEPROM. */
+ ops->read_rom_data = ar9003_read_eep_data;
+
+ sc->eep_size = AR_SREV_9485(sc) ? 4096 : 1024;
+ sc->eep_base = sc->eep_size - 1;
+ error = ops->read_rom_data(sc, sc->eep_base, &hdr, sizeof(hdr));
+ if (error == 0 && hdr != 0 && hdr != 0xffffffff)
+ return (0);
+
+ sc->eep_size = 512;
+ sc->eep_base = sc->eep_size - 1;
+ error = ops->read_rom_data(sc, sc->eep_base, &hdr, sizeof(hdr));
+ if (error == 0 && hdr != 0 && hdr != 0xffffffff)
+ return (0);
+
+ /* Try OTPROM. */
+ ops->read_rom_data = ar9003_read_otp_data;
+
+ sc->eep_size = 1024;
+ sc->eep_base = sc->eep_size - 1;
+ error = ops->read_rom_data(sc, sc->eep_base, &hdr, sizeof(hdr));
+ if (error == 0 && hdr != 0 && hdr != 0xffffffff)
+ return (0);
+
+ sc->eep_size = 512;
+ sc->eep_base = sc->eep_size - 1;
+ error = ops->read_rom_data(sc, sc->eep_base, &hdr, sizeof(hdr));
+ if (error == 0 && hdr != 0 && hdr != 0xffffffff)
+ return (0);
+
+ return (EIO); /* Not found. */
+}
+
int
ar9003_restore_rom_block(struct athn_softc *sc, uint8_t alg, uint8_t ref,
const uint8_t *buf, int len)
@@ -334,6 +427,7 @@ ar9003_restore_rom_block(struct athn_softc *sc, uint8_t alg, uint8_t ref,
int
ar9003_read_rom(struct athn_softc *sc)
{
+ struct athn_ops *ops = &sc->ops;
uint8_t *buf, *ptr, alg, ref;
uint16_t sum, rsum;
uint32_t hdr;
@@ -353,7 +447,7 @@ ar9003_read_rom(struct athn_softc *sc)
addr = sc->eep_base;
for (i = 0; i < 100; i++) {
/* Read block header. */
- error = ar9003_read_rom_data(sc, addr, &hdr, sizeof(hdr));
+ error = ops->read_rom_data(sc, addr, &hdr, sizeof(hdr));
if (error != 0)
break;
if (hdr == 0 || hdr == 0xffffffff)
@@ -369,13 +463,13 @@ ar9003_read_rom(struct athn_softc *sc)
i, alg, ref, len));
/* Read block data (len <= 0x7ff). */
- error = ar9003_read_rom_data(sc, addr, buf, len);
+ error = ops->read_rom_data(sc, addr, buf, len);
if (error != 0)
break;
addr -= len;
/* Read block checksum. */
- error = ar9003_read_rom_data(sc, addr, &sum, sizeof(sum));
+ error = ops->read_rom_data(sc, addr, &sum, sizeof(sum));
if (error != 0)
break;
addr -= sizeof(sum);
@@ -396,7 +490,7 @@ ar9003_read_rom(struct athn_softc *sc)
#if BYTE_ORDER == BIG_ENDIAN
/* NB: ROM is always little endian. */
if (error == 0)
- sc->ops.swap_rom(sc);
+ ops->swap_rom(sc);
#endif
free(buf, M_DEVBUF);
return (error);
@@ -1218,6 +1312,8 @@ ar9003_intr(struct athn_softc *sc)
/* TBD */;
if (intr2 & AR_ISR_S2_TSFOOR)
/* TBD */;
+ if (intr2 & AR_ISR_S2_BB_WATCHDOG)
+ /* TBD */;
}
intr = AR_READ(sc, AR_ISR_RAC);
if (intr == AR_INTR_SPURIOUS)
diff --git a/sys/dev/ic/ar9003reg.h b/sys/dev/ic/ar9003reg.h
index 4dcd3e19417..bbd31dcb823 100644
--- a/sys/dev/ic/ar9003reg.h
+++ b/sys/dev/ic/ar9003reg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar9003reg.h,v 1.5 2010/11/10 21:06:44 damien Exp $ */
+/* $OpenBSD: ar9003reg.h,v 1.6 2011/01/01 10:48:31 damien Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
@@ -847,6 +847,21 @@
#define AR_PHY_65NM_CH0_THERM_START 0x20000000
#define AR_PHY_65NM_CH0_THERM_LOCAL 0x80000000
+/*
+ * OTP registers.
+ */
+#define AR_OTP_BASE(i) (0x14000 + (i) * 4)
+#define AR_OTP_STATUS 0x15f18
+#define AR_OTP_READ_DATA 0x15f1c
+
+/* Bits for AR_OTP_STATUS. */
+#define AR_OTP_STATUS_TYPE_M 0x00000007
+#define AR_OTP_STATUS_TYPE_S 0
+#define AR_OTP_STATUS_SM_BUSY 0x1
+#define AR_OTP_STATUS_ACCESS_BUSY 0x2
+#define AR_OTP_STATUS_VALID 0x4
+
+
#define AR9003_MAX_CHAINS 3
#define AR9003_TX_QDEPTH 8
diff --git a/sys/dev/ic/ar9380.c b/sys/dev/ic/ar9380.c
index f025e3eb1a6..0bac740a7bd 100644
--- a/sys/dev/ic/ar9380.c
+++ b/sys/dev/ic/ar9380.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar9380.c,v 1.9 2010/12/31 21:23:55 damien Exp $ */
+/* $OpenBSD: ar9380.c,v 1.10 2011/01/01 10:48:31 damien Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
@@ -101,8 +101,6 @@ void ar9003_get_ht_tpow(struct athn_softc *, struct ieee80211_channel *,
int
ar9380_attach(struct athn_softc *sc)
{
- sc->eep_base = AR9380_EEP_START_LOC;
- sc->eep_size = sizeof(struct ar9380_eeprom);
sc->ngpiopins = 17;
sc->ops.setup = ar9380_setup;
sc->ops.get_rom_template = ar9380_get_rom_template;
diff --git a/sys/dev/ic/ar9380reg.h b/sys/dev/ic/ar9380reg.h
index fc9136f7c28..e7b99064335 100644
--- a/sys/dev/ic/ar9380reg.h
+++ b/sys/dev/ic/ar9380reg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar9380reg.h,v 1.14 2010/12/31 21:23:55 damien Exp $ */
+/* $OpenBSD: ar9380reg.h,v 1.15 2011/01/01 10:48:31 damien Exp $ */
/*-
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
@@ -29,7 +29,6 @@
/*
* ROM layout used by AR9380.
*/
-#define AR9380_EEP_START_LOC 0x3ff
#define AR9380_NUM_5G_CAL_PIERS 8
#define AR9380_NUM_2G_CAL_PIERS 3
#define AR9380_NUM_5G_20_TARGET_POWERS 8
diff --git a/sys/dev/ic/athnvar.h b/sys/dev/ic/athnvar.h
index 6e073176944..38edda927db 100644
--- a/sys/dev/ic/athnvar.h
+++ b/sys/dev/ic/athnvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: athnvar.h,v 1.27 2010/12/31 21:23:55 damien Exp $ */
+/* $OpenBSD: athnvar.h,v 1.28 2011/01/01 10:48:31 damien Exp $ */
/*-
* Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
@@ -364,6 +364,7 @@ struct athn_ops {
struct ieee80211_channel *, struct ieee80211_channel *);
int (*set_synth)(struct athn_softc *, struct ieee80211_channel *,
struct ieee80211_channel *);
+ int (*read_rom_data)(struct athn_softc *, uint32_t, void *, int);
const uint8_t *
(*get_rom_template)(struct athn_softc *, uint8_t);
void (*swap_rom)(struct athn_softc *);