diff options
author | Damien Bergamini <damien@cvs.openbsd.org> | 2011-01-01 10:48:32 +0000 |
---|---|---|
committer | Damien Bergamini <damien@cvs.openbsd.org> | 2011-01-01 10:48:32 +0000 |
commit | e75566f559b3be4c3b3772259d5427922b30eda3 (patch) | |
tree | 3adb81bbc7a66fc1035ffd26913367e5d5ae6a6d | |
parent | a415c202b77edd9c5b7b38e1bff0cb700ce1416c (diff) |
add code to read OTPROM on the AR9485
-rw-r--r-- | sys/dev/ic/ar5008.c | 18 | ||||
-rw-r--r-- | sys/dev/ic/ar9003.c | 124 | ||||
-rw-r--r-- | sys/dev/ic/ar9003reg.h | 17 | ||||
-rw-r--r-- | sys/dev/ic/ar9380.c | 4 | ||||
-rw-r--r-- | sys/dev/ic/ar9380reg.h | 3 | ||||
-rw-r--r-- | sys/dev/ic/athnvar.h | 3 |
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 *); |