On Mon, Apr 26, 2010 at 05:04:49PM +0100, Stuart Henderson wrote:
> AR5424 14.2 phy 7.0 rf 10.2, WOR5_ETSIC
> 
> ar5212.c:ar5k_ar5212_reset() resets tx queues.
> I inserted a printf as follows...:
> 
>         /*
>          * Reset queues and start beacon timers at the end of the reset 
> routine
>          */
>         for (i = 0; i < hal->ah_capabilities.cap_queues.q_tx_num; i++) {
> /***/ printf("ar5212_ i=%u/%u\n", i, 
> hal->ah_capabilities.cap_queues.q_tx_num);
>                 AR5K_REG_WRITE_Q(AR5K_AR5212_DCU_QCUMASK(i), i);
>                 if (ar5k_ar5212_reset_tx_queue(hal, i) == AH_FALSE) {
>                         AR5K_PRINTF("failed to reset TX queue #%d\n", i);
>                         return (AH_FALSE);
>                 }
>         }
> 
> when I ifconfig ath0 up, I get:
> 
> ar5212_ i=0/10
> ar5212_ i=1/10
> ar5212_ i=2/10
> <hard lock, cannot enter DDB>

Thanks Stuart.

I took a look at ar5k_ar5212_reset_tx_queue() and there were a few bits
missing there from the linux driver.  Here's yet another patch with these
missing bits.

Usual disclaimer: this patch has been tested on my card only and may crash
your system.

For anyone testing it: feedback is welcome ;-)

--
Luis

Index: sys/dev/ic/ar5212.c
===================================================================
RCS file: /home/miguel/openbsd-cvsroot//src/sys/dev/ic/ar5212.c,v
retrieving revision 1.51
diff -u -p -r1.51 ar5212.c
--- sys/dev/ic/ar5212.c 2 Jun 2009 12:39:02 -0000       1.51
+++ sys/dev/ic/ar5212.c 26 Apr 2010 19:40:18 -0000
@@ -30,6 +30,7 @@ HAL_BOOL       ar5k_ar5212_nic_wakeup(struct 
 u_int16_t       ar5k_ar5212_radio_revision(struct ath_hal *, HAL_CHIP);
 void            ar5k_ar5212_fill(struct ath_hal *);
 HAL_BOOL        ar5k_ar5212_txpower(struct ath_hal *, HAL_CHANNEL *, u_int);
+void            ar5k_ar5212_hw_set_sleep_clock(struct ath_hal *, HAL_BOOL);
 
 /*
  * Initial register setting for the AR5212
@@ -234,9 +235,17 @@ ar5k_ar5212_attach(u_int16_t device, voi
                hal->ah_phy_spending = AR5K_AR5212_PHY_SPENDING_AR5424;
                hal->ah_radio_5ghz_revision = hal->ah_radio_2ghz_revision =
                    AR5K_SREV_VER_AR5413;
-       } else if (srev == AR5K_SREV_VER_AR2425) {
+       } else if (hal->ah_mac_version == (AR5K_SREV_VER_AR2425 >> 4) ||
+               hal->ah_mac_version == (AR5K_SREV_VER_AR2417 >> 4) ||
+               hal->ah_phy_revision == (AR5K_SREV_PHY_2425)) {
                hal->ah_radio = AR5K_AR2425;
-               hal->ah_phy_spending = AR5K_AR5212_PHY_SPENDING_AR5112;
+               hal->ah_single_chip = AH_TRUE;
+               hal->ah_radio_5ghz_revision= AR5K_SREV_RAD_2425;
+       } else if ((hal->ah_mac_version == (AR5K_SREV_VER_AR2424 >> 4)) ||
+               (hal->ah_phy_revision == AR5K_SREV_PHY_5413)) {
+               hal->ah_radio = AR5K_AR5413;
+               hal->ah_single_chip = AH_TRUE;
+               hal->ah_radio_5ghz_revision = AR5K_SREV_RAD_5413;
        } else if (hal->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) {
                hal->ah_radio = AR5K_AR5111;
                hal->ah_phy_spending = AR5K_AR5212_PHY_SPENDING_AR5111;
@@ -262,6 +271,12 @@ ar5k_ar5212_attach(u_int16_t device, voi
        }
        hal->ah_phy = AR5K_AR5212_PHY(0);
 
+       /* Enable pci core retry fix on Hainan (5213A) and later chips */
+       if (srev >= AR5K_SREV_VER_AR5213A) {
+               AR5K_REG_ENABLE_BITS(AR5K_AR5212_PCICFG,
+                       AR5K_AR5212_PCICFG_RETRY_FIX);
+       }
+
        if (hal->ah_pci_express == AH_TRUE) {
                /* PCI-Express based devices need some extra initialization */
                ar5k_write_ini(hal, ar5212_pcie, nitems(ar5212_pcie), 0);
@@ -312,7 +327,7 @@ ar5k_ar5212_nic_reset(struct ath_hal *ha
 HAL_BOOL
 ar5k_ar5212_nic_wakeup(struct ath_hal *hal, u_int16_t flags)
 {
-       u_int32_t turbo, mode, clock;
+       u_int32_t turbo, mode, clock, bus_flags;
 
        turbo = 0;
        mode = 0;
@@ -335,7 +350,10 @@ ar5k_ar5212_nic_wakeup(struct ath_hal *h
                clock |= AR5K_AR5212_PHY_PLL_44MHZ;
        } else if (flags & IEEE80211_CHAN_5GHZ) {
                mode |= AR5K_AR5212_PHY_MODE_FREQ_5GHZ;
-               clock |= AR5K_AR5212_PHY_PLL_40MHZ;
+               if (hal->ah_radio == AR5K_AR5413)
+                       clock |= AR5K_AR5212_PHY_PLL_40MHZ_5413;
+               else
+                       clock |= AR5K_AR5212_PHY_PLL_40MHZ;
        } else {
                AR5K_PRINT("invalid radio frequency mode\n");
                return (AH_FALSE);
@@ -361,23 +379,30 @@ ar5k_ar5212_nic_wakeup(struct ath_hal *h
         * Reset and wakeup the device
         */
 
-       /* ...reset chipset and PCI device (if not PCI-E) */
-       if (hal->ah_pci_express == AH_FALSE &&
-           ar5k_ar5212_nic_reset(hal, AR5K_AR5212_RC_CHIP) == AH_FALSE) {
-               AR5K_PRINT("failed to reset the AR5212 + PCI chipset\n");
+       /* Wakeup the device */
+       if (ar5k_ar5212_set_power(hal,
+               HAL_PM_AWAKE, AH_TRUE, 0) == AH_FALSE) {
+               AR5K_PRINT("failed to wakeup the AR5212 chipset\n");
+               return (AH_FALSE);
+       }
+
+       /* ...reset chipset and PCI device */
+       bus_flags = (hal->ah_pci_express != AH_FALSE) ? 0 : AR5K_AR5212_RC_PCI;
+       if (ar5k_ar5212_nic_reset(hal, bus_flags) == AH_FALSE) {
+               AR5K_PRINT("failed to reset the AR5212 chipset\n");
                return (AH_FALSE);
        }
 
-       /* ...wakeup */
+       /* ...wakeup again */
        if (ar5k_ar5212_set_power(hal,
                HAL_PM_AWAKE, AH_TRUE, 0) == AH_FALSE) {
-               AR5K_PRINT("failed to resume the AR5212 (again)\n");
+               AR5K_PRINT("failed to wakeup (again) the AR5212 chipset\n");
                return (AH_FALSE);
        }
 
        /* ...final warm reset */
        if (ar5k_ar5212_nic_reset(hal, 0) == AH_FALSE) {
-               AR5K_PRINT("failed to warm reset the AR5212\n");
+               AR5K_PRINT("failed to reset (again) the AR5212 chipset\n");
                return (AH_FALSE);
        }
 
@@ -485,12 +510,13 @@ ar5k_ar5212_reset(struct ath_hal *hal, H
         */
        if (chanchange == AH_TRUE) {
                s_seq = AR5K_REG_READ(AR5K_AR5212_DCU_SEQNUM(0));
-               s_ant = AR5K_REG_READ(AR5K_AR5212_DEFAULT_ANTENNA);
        } else {
                s_seq = 0;
-               s_ant = 1;
        }
 
+       /* Save default antenna */
+       s_ant = AR5K_REG_READ(AR5K_AR5212_DEFAULT_ANTENNA);
+
        s_led[0] = AR5K_REG_READ(AR5K_AR5212_PCICFG) &
            AR5K_AR5212_PCICFG_LEDSTATE;
        s_led[1] = AR5K_REG_READ(AR5K_AR5212_GPIOCR);
@@ -544,6 +570,8 @@ ar5k_ar5212_reset(struct ath_hal *hal, H
                return (AH_FALSE);
        }
 
+       ar5k_ar5212_hw_set_sleep_clock(hal, AH_FALSE);
+
        /* PHY access enable */
        AR5K_REG_WRITE(AR5K_AR5212_PHY(0), AR5K_AR5212_PHY_SHIFT_5GHZ);
 
@@ -572,11 +600,12 @@ ar5k_ar5212_reset(struct ath_hal *hal, H
                    nitems(ar2413_mode), mode);
                break;
        case AR5K_AR2425:
-               AR5K_REG_WRITE(AR5K_AR5212_PHY(648), 0x018830c6);
                if (mode == AR5K_INI_VAL_11B)
                        mode = AR5K_INI_VAL_11G;
                ar5k_write_mode(hal, ar2425_mode,
                    nitems(ar2425_mode), mode);
+               AR5K_REG_WRITE(AR5K_AR5212_PHY_AGC, 0x00004000);
+               AR5K_REG_WRITE(0xa274, 0x081b7caa);
                break;
        default:
                AR5K_PRINTF("invalid radio: %d\n", hal->ah_radio);
@@ -1150,9 +1179,17 @@ ar5k_ar5212_reset_tx_queue(struct ath_ha
        /*
         * Set misc registers
         */
+       /* Enable DCU early termination for this queue */
        AR5K_REG_WRITE(AR5K_AR5212_QCU_MISC(queue),
            AR5K_AR5212_QCU_MISC_DCU_EARLY);
 
+       /* Enable DCU to wait for next fragment from QCU */
+       AR5K_REG_WRITE(AR5K_AR5212_DCU_MISC(queue),
+           AR5K_AR5212_QCU_MISC_DCU_EARLY);
+
+       AR5K_REG_WRITE(AR5K_AR5212_DCU_MISC(queue),
+           AR5K_AR5212_DCU_MISC_SEQNUM_CTL);
+
        if (tq->tqi_cbr_period) {
                AR5K_REG_WRITE(AR5K_AR5212_QCU_CBRCFG(queue),
                    AR5K_REG_SM(tq->tqi_cbr_period,
@@ -1207,26 +1244,27 @@ ar5k_ar5212_reset_tx_queue(struct ath_ha
 
                AR5K_REG_ENABLE_BITS(AR5K_AR5212_DCU_MISC(queue),
                    (AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
-                   AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_GLOBAL) |
+                   AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_S) |
+                   AR5K_AR5212_DCU_MISC_ARBLOCK_IGNORE |
                    AR5K_AR5212_DCU_MISC_POST_FR_BKOFF_DIS |
                    AR5K_AR5212_DCU_MISC_BCN_ENABLE);
-
-               AR5K_REG_WRITE(AR5K_AR5212_QCU_RDYTIMECFG(queue),
-                   ((AR5K_TUNE_BEACON_INTERVAL -
-                   (AR5K_TUNE_SW_BEACON_RESP - AR5K_TUNE_DMA_BEACON_RESP) -
-                   AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
-                   AR5K_AR5212_QCU_RDYTIMECFG_ENABLE);
                break;
 
        case HAL_TX_QUEUE_CAB:
                AR5K_REG_ENABLE_BITS(AR5K_AR5212_QCU_MISC(queue),
-                   AR5K_AR5212_QCU_MISC_FRSHED_DBA_GT |
+                   AR5K_AR5212_QCU_MISC_FRSHED_BCN_SENT_GT |
                    AR5K_AR5212_QCU_MISC_CBREXP |
                    AR5K_AR5212_QCU_MISC_CBREXP_BCN);
 
+               AR5K_REG_WRITE(AR5K_AR5212_QCU_RDYTIMECFG(queue),
+                   ((AR5K_TUNE_BEACON_INTERVAL -
+                   (AR5K_TUNE_SW_BEACON_RESP - AR5K_TUNE_DMA_BEACON_RESP) -
+                   AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
+                   AR5K_AR5212_QCU_RDYTIMECFG_ENABLE);
+
                AR5K_REG_ENABLE_BITS(AR5K_AR5212_DCU_MISC(queue),
                    (AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
-                   AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_GLOBAL));
+                   AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_S));
                break;
 
        case HAL_TX_QUEUE_PSPOLL:
@@ -3034,3 +3072,75 @@ ar5k_ar5212_set_txpower_limit(struct ath
        AR5K_PRINTF("changing txpower to %d\n", power);
        return (ar5k_ar5212_txpower(hal, channel, power));
 }
+
+/*
+ * If there is an external 32KHz crystal available, use it
+ * as ref. clock instead of 32/40MHz clock and baseband clocks
+ * to save power during sleep or restore normal 32/40MHz
+ * operation.
+ *
+ * XXX: When operating on 32KHz certain PHY registers (27 - 31,
+ *      123 - 127) require delay on access.
+ */
+void
+ar5k_ar5212_hw_set_sleep_clock(struct ath_hal *hal, HAL_BOOL enable)
+{
+       struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
+       u_int32_t scal, spending, usec32;
+
+       /* Only set 32KHz settings if we have an external
+        * 32KHz crystal present */
+       if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) ||
+               AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) &&
+               enable) {
+               /* TODO */
+       } else {
+               /* Disable sleep clock operation and
+                * restore default parameters */
+               AR5K_REG_DISABLE_BITS(AR5K_AR5212_PCICFG,
+                       AR5K_AR5212_PCICFG_SLEEP_CLOCK_EN);
+
+               AR5K_REG_WRITE_BITS(AR5K_AR5212_PCICFG,
+                       AR5K_AR5212_PCICFG_SLEEP_CLOCK_RATE, 0);
+
+               AR5K_REG_WRITE(AR5K_AR5212_PHY_SCR, 0x1f);
+               AR5K_REG_WRITE(AR5K_AR5212_PHY_SLMT,
+                       AR5K_AR5212_PHY_SLMT_32MHZ);
+
+               if (hal->ah_mac_version == (AR5K_SREV_VER_AR2417 >> 4))
+                       scal = AR5K_AR5212_PHY_SCAL_32MHZ_2417;
+               else if (ee->ee_is_hb63 == AH_TRUE)
+                       scal = AR5K_AR5212_PHY_SCAL_32MHZ_HB63;
+               else
+                       scal = AR5K_AR5212_PHY_SCAL_32MHZ;
+
+               AR5K_REG_WRITE(AR5K_AR5212_PHY_SCAL, scal);
+
+               AR5K_REG_WRITE(AR5K_AR5212_PHY_SCLOCK,
+                       AR5K_AR5212_PHY_SCLOCK_32MHZ);
+               AR5K_REG_WRITE(AR5K_AR5212_PHY_SDELAY,
+                       AR5K_AR5212_PHY_SCLOCK_32MHZ);
+
+               if ((hal->ah_radio == AR5K_AR5112) ||
+                   (hal->ah_radio == AR5K_AR5413) ||
+                   (hal->ah_mac_version == (AR5K_SREV_VER_AR2417 >> 4)))
+                       spending = 0x14;
+               else
+                       spending = 0x18;
+
+               AR5K_REG_WRITE(AR5K_AR5212_PHY_SPENDING, spending);
+
+               if ((hal->ah_radio == AR5K_AR5112) ||
+                   (hal->ah_radio == AR5K_AR5413))
+                       usec32 = 39;
+               else
+                       usec32 = 31;
+
+               AR5K_REG_WRITE_BITS(AR5K_AR5212_USEC,
+                       AR5K_AR5212_USEC_32, usec32);
+
+               AR5K_REG_WRITE_BITS(AR5K_AR5212_TSF_PARM,
+                       AR5K_AR5212_TSF_PARM_INC, 1);
+       }
+}
+
Index: sys/dev/ic/ar5212reg.h
===================================================================
RCS file: /home/miguel/openbsd-cvsroot//src/sys/dev/ic/ar5212reg.h,v
retrieving revision 1.12
diff -u -p -r1.12 ar5212reg.h
--- sys/dev/ic/ar5212reg.h      30 Jul 2008 07:15:39 -0000      1.12
+++ sys/dev/ic/ar5212reg.h      26 Apr 2010 19:27:11 -0000
@@ -456,6 +456,7 @@
  */
 #define AR5K_AR5212_DCU_MISC(_n)               AR5K_AR5212_DCU(_n, 0x1100)
 #define        AR5K_AR5212_DCU_MISC_BACKOFF            0x000007ff
+#define AR5K_AR5212_DCU_MISC_FRAG_WAIT         0x00000100
 #define AR5K_AR5212_DCU_MISC_BACKOFF_FRAG      0x00000200
 #define        AR5K_AR5212_DCU_MISC_HCFPOLL_ENABLE     0x00000800
 #define        AR5K_AR5212_DCU_MISC_BACKOFF_PERSIST    0x00001000
@@ -589,34 +590,38 @@ typedef enum {
 /*
  * PCI configuration register
  */
-#define AR5K_AR5212_PCICFG             0x4010
-#define AR5K_AR5212_PCICFG_CLKRUNEN    0x00000004
-#define AR5K_AR5212_PCICFG_EESIZE      0x00000018
-#define AR5K_AR5212_PCICFG_EESIZE_S    3
-#define AR5K_AR5212_PCICFG_EESIZE_4K   0
-#define AR5K_AR5212_PCICFG_EESIZE_8K   1
-#define AR5K_AR5212_PCICFG_EESIZE_16K  2
-#define AR5K_AR5212_PCICFG_EESIZE_FAIL 3
-#define AR5K_AR5212_PCICFG_LED         0x00000060
-#define AR5K_AR5212_PCICFG_LED_NONE    0x00000000
-#define AR5K_AR5212_PCICFG_LED_PEND    0x00000020
-#define AR5K_AR5212_PCICFG_LED_ASSOC   0x00000040
-#define        AR5K_AR5212_PCICFG_BUS_SEL      0x00000380
-#define        AR5K_AR5212_PCICFG_CBEFIX_DIS   0x00000400
-#define AR5K_AR5212_PCICFG_SL_INTEN    0x00000800
-#define AR5K_AR5212_PCICFG_SL_INPEN    0x00002800
-#define AR5K_AR5212_PCICFG_SPWR_DN     0x00010000
-#define AR5K_AR5212_PCICFG_LEDMODE     0x000e0000
-#define AR5K_AR5212_PCICFG_LEDMODE_PROP        0x00000000
-#define AR5K_AR5212_PCICFG_LEDMODE_PROM        0x00020000
-#define AR5K_AR5212_PCICFG_LEDMODE_PWR 0x00040000
-#define AR5K_AR5212_PCICFG_LEDMODE_RAND        0x00060000
-#define AR5K_AR5212_PCICFG_LEDBLINK    0x00700000
-#define AR5K_AR5212_PCICFG_LEDBLINK_S  20
-#define AR5K_AR5212_PCICFG_LEDSLOW     0x00800000
+#define AR5K_AR5212_PCICFG                     0x4010
+#define AR5K_AR5212_PCICFG_SLEEP_CLOCK_EN      0x00000002 /* Enable sleep 
clock */
+#define AR5K_AR5212_PCICFG_CLKRUNEN            0x00000004
+#define AR5K_AR5212_PCICFG_EESIZE              0x00000018
+#define AR5K_AR5212_PCICFG_EESIZE_S            3
+#define AR5K_AR5212_PCICFG_EESIZE_4K           0
+#define AR5K_AR5212_PCICFG_EESIZE_8K           1
+#define AR5K_AR5212_PCICFG_EESIZE_16K          2
+#define AR5K_AR5212_PCICFG_EESIZE_FAIL         3
+#define AR5K_AR5212_PCICFG_LED                 0x00000060
+#define AR5K_AR5212_PCICFG_LED_NONE            0x00000000
+#define AR5K_AR5212_PCICFG_LED_PEND            0x00000020
+#define AR5K_AR5212_PCICFG_LED_ASSOC           0x00000040
+#define AR5K_AR5212_PCICFG_BUS_SEL             0x00000380
+#define AR5K_AR5212_PCICFG_CBEFIX_DIS          0x00000400
+#define AR5K_AR5212_PCICFG_SL_INTEN            0x00000800
+#define AR5K_AR5212_PCICFG_SL_INPEN            0x00002800
+#define AR5K_AR5212_PCICFG_RETRY_FIX           0x00001000 /* Enable pci core 
retry fix */
+#define AR5K_AR5212_PCICFG_SPWR_DN             0x00010000
+#define AR5K_AR5212_PCICFG_LEDMODE             0x000e0000
+#define AR5K_AR5212_PCICFG_LEDMODE_PROP                0x00000000
+#define AR5K_AR5212_PCICFG_LEDMODE_PROM                0x00020000
+#define AR5K_AR5212_PCICFG_LEDMODE_PWR         0x00040000
+#define AR5K_AR5212_PCICFG_LEDMODE_RAND                0x00060000
+#define AR5K_AR5212_PCICFG_LEDBLINK            0x00700000
+#define AR5K_AR5212_PCICFG_LEDBLINK_S          20
+#define AR5K_AR5212_PCICFG_LEDSLOW             0x00800000
 #define AR5K_AR5212_PCICFG_LEDSTATE                                    \
        (AR5K_AR5212_PCICFG_LED | AR5K_AR5212_PCICFG_LEDMODE |          \
        AR5K_AR5212_PCICFG_LEDBLINK | AR5K_AR5212_PCICFG_LEDSLOW)
+#define AR5K_AR5212_PCICFG_SLEEP_CLOCK_RATE    0x03000000 /* Sleep clock rate 
*/
+#define AR5K_AR5212_PCICFG_SLEEP_CLOCK_RATE_S  24
 
 /*
  * "General Purpose Input/Output" (GPIO) control register
@@ -993,7 +998,7 @@ typedef enum {
  * TSF parameter register
  */
 #define AR5K_AR5212_TSF_PARM           0x8104
-#define AR5K_AR5212_TSF_PARM_INC_M     0x000000ff
+#define AR5K_AR5212_TSF_PARM_INC       0x000000ff
 #define AR5K_AR5212_TSF_PARM_INC_S     0
 
 /*
@@ -1099,12 +1104,15 @@ typedef enum {
 #define AR5K_AR5212_PHY_SLMT_32MHZ     0x0000007f
 #define AR5K_AR5212_PHY_SCAL           0x9878
 #define AR5K_AR5212_PHY_SCAL_32MHZ     0x0000000e
+#define AR5K_AR5212_PHY_SCAL_32MHZ_2417        0x0000000a
+#define AR5K_AR5212_PHY_SCAL_32MHZ_HB63        0x00000032
 
 /*
  * PHY PLL control register
  */
 #define        AR5K_AR5212_PHY_PLL             0x987c
 #define        AR5K_AR5212_PHY_PLL_40MHZ       0x000000aa
+#define        AR5K_AR5212_PHY_PLL_40MHZ_5413  0x00000004
 #define        AR5K_AR5212_PHY_PLL_44MHZ       0x000000ab
 #define AR5K_AR5212_PHY_PLL_AR5111     0x00000000
 #define AR5K_AR5212_PHY_PLL_AR5112     0x00000040
Index: sys/dev/ic/ar5212var.h
===================================================================
RCS file: /home/miguel/openbsd-cvsroot//src/sys/dev/ic/ar5212var.h,v
retrieving revision 1.15
diff -u -p -r1.15 ar5212var.h
--- sys/dev/ic/ar5212var.h      30 Jul 2008 07:15:39 -0000      1.15
+++ sys/dev/ic/ar5212var.h      25 Apr 2010 12:28:03 -0000
@@ -309,8 +309,6 @@ extern ar5k_attach_t ar5k_ar5212_attach;
        { 0x13fc,       0x00000000 },   \
        { 0x143c,       0x00000000 },   \
        { 0x147c,       0x00000000 },   \
-       { 0x143c,       0x00000000 },   \
-       { 0x147c,       0x00000000 },   \
        { 0x8004,       0x00000000 },   \
        { 0x8008,       0x00000000 },   \
        { 0x800c,       0x00000000 },   \
@@ -325,14 +323,7 @@ extern ar5k_attach_t ar5k_ar5212_attach;
        { 0x8048,       0x00000000 },   \
        { 0x8054,       0x00000000 },   \
        { 0x8058,       0x00000000 },   \
-       { 0x8080,       0x00000000 },   \
        { 0x805c,       0x000fc78f },   \
-       { 0x8084,       0x00000000 },   \
-       { 0x8088,       0x00000000 },   \
-       { 0x808c,       0x00000000 },   \
-       { 0x8090,       0x00000000 },   \
-       { 0x8094,       0x00000000 },   \
-       { 0x8098,       0x00000000 },   \
        { 0x80c0,       0x2a82301a },   \
        { 0x80c4,       0x05dc01e0 },   \
        { 0x80c8,       0x1f402710 },   \
@@ -431,22 +422,23 @@ extern ar5k_attach_t ar5k_ar5212_attach;
        { 0xa210,       0x00806333 },   \
        { 0xa214,       0x00106c10 },   \
        { 0xa218,       0x009c4060 },   \
-       { 0xa21c,       0x1483800a },   \
-       { 0xa220,       0x01831061 },   \
+       { 0xa220,       0x018830c6 },   \
        { 0xa224,       0x00000400 },   \
        { 0xa22c,       0x00000000 },   \
        { 0xa234,       0x20202020 },   \
-       { 0x9938,       0x20202020 },   \
+       { 0xa238,       0x20202020 },   \
        { 0xa240,       0x38490a20 },   \
        { 0xa244,       0x00007bb6 },   \
        { 0xa248,       0x0fff3ffc },   \
+       { 0x9b00,       0x00000000 },   \
+       { 0x9b28,       0x0000000c },   \
+       { 0x9b38,       0x00000012 },   \
+       { 0x9b64,       0x00000021 },   \
+       { 0x9b8c,       0x0000002d },   \
+       { 0x9b9c,       0x00000033 },   \
 }
 
 #define AR5K_AR5212_MODE       {               \
-       { 0xa200,\
-           { 0x00000008, 0x00000008, 0x0000000b, 0x0000000e, 0x0000000e } },\
-       { 0x9800,\
-           { 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 } },\
        { 0x1040,\
            { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },\
        { 0x1044,\
Index: sys/dev/ic/ar5xxx.c
===================================================================
RCS file: /home/miguel/openbsd-cvsroot//src/sys/dev/ic/ar5xxx.c,v
retrieving revision 1.55
diff -u -p -r1.55 ar5xxx.c
--- sys/dev/ic/ar5xxx.c 23 Sep 2009 18:03:30 -0000      1.55
+++ sys/dev/ic/ar5xxx.c 25 Apr 2010 12:28:03 -0000
@@ -87,6 +87,7 @@ u_int32_t      ar5k_ar5110_chan2athchan(HAL_
 HAL_BOOL        ar5k_ar5111_channel(struct ath_hal *, HAL_CHANNEL *);
 HAL_BOOL        ar5k_ar5111_chan2athchan(u_int, struct ar5k_athchan_2ghz *);
 HAL_BOOL        ar5k_ar5112_channel(struct ath_hal *, HAL_CHANNEL *);
+HAL_BOOL        ar5k_ar2425_channel(struct ath_hal *, HAL_CHANNEL *);
 HAL_BOOL        ar5k_check_channel(struct ath_hal *, u_int16_t, u_int flags);
 
 HAL_BOOL        ar5k_ar5111_rfregs(struct ath_hal *, HAL_CHANNEL *, u_int);
@@ -892,6 +893,12 @@ ar5k_eeprom_init(struct ath_hal *hal)
        if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
                AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
                AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
+
+               /* XXX: Don't know which versions include these two */
+               AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC2, ee_misc2);
+
+               if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3)
+                       AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC3, ee_misc3);
        }
 
        if (hal->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
@@ -904,6 +911,12 @@ ar5k_eeprom_init(struct ath_hal *hal)
                ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
        }
 
+       AR5K_EEPROM_READ(AR5K_EEPROM_IS_HB63, val);
+       if ((hal->ah_mac_version == (AR5K_SREV_VER_AR2425 >> 4)) && val)
+               ee->ee_is_hb63 = AH_TRUE;
+       else
+               ee->ee_is_hb63 = AH_FALSE;
+
        /*
         * Get conformance test limit values
         */
@@ -1127,6 +1140,8 @@ ar5k_channel(struct ath_hal *hal, HAL_CH
                ret = ar5k_ar5110_channel(hal, channel);
        else if (hal->ah_radio == AR5K_AR5111)
                ret = ar5k_ar5111_channel(hal, channel);
+       else if (hal->ah_radio == AR5K_AR2425)
+               ret = ar5k_ar2425_channel(hal, channel);
        else
                ret = ar5k_ar5112_channel(hal, channel);
 
@@ -1286,6 +1301,44 @@ ar5k_ar5112_channel(struct ath_hal *hal,
 
        return (AH_TRUE);
 }
+
+HAL_BOOL
+ar5k_ar2425_channel(struct ath_hal *hal, HAL_CHANNEL *channel)
+{
+       u_int32_t data, data0, data2;
+       u_int16_t c;
+
+       data = data0 = data2 = 0;
+       c = channel->c_channel + hal->ah_chanoff;
+
+       /*
+        * Set the channel on the AR2425
+        */
+       if (c < 4800) {
+               data0 = ar5k_bitswap((c - 2272), 8);
+               data2 = 0;
+       } else if ((c - (c % 5)) != 2 || c > 5435) {
+               if (!(c % 20) && c < 5120)
+                       data0 = ar5k_bitswap(((c - 4800) / 20 << 2), 8);
+               else if (!(c % 10))
+                       data0 = ar5k_bitswap(((c - 4800) / 10 << 1), 8);
+               else if (!(c % 5))
+                       data0 = ar5k_bitswap((c - 4800) / 5, 8);
+               else
+                       return (AH_FALSE);
+               data2 = ar5k_bitswap(1, 2);
+       } else {
+               data0 = ar5k_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
+               data2 = ar5k_bitswap(0, 2);
+       }
+
+       data = (data0 << 4) | (data2 << 2) | 0x1001;
+
+       AR5K_PHY_WRITE(0x27, data & 0xff);
+       AR5K_PHY_WRITE(0x36, (data >> 8) & 0x7f);
+ 
+       return (AH_TRUE);
+ }
 
 u_int
 ar5k_rfregs_op(u_int32_t *rf, u_int32_t offset, u_int32_t reg, u_int32_t bits,
Index: sys/dev/ic/ar5xxx.h
===================================================================
RCS file: /home/miguel/openbsd-cvsroot//src/sys/dev/ic/ar5xxx.h,v
retrieving revision 1.48
diff -u -p -r1.48 ar5xxx.h
--- sys/dev/ic/ar5xxx.h 20 Apr 2010 22:05:41 -0000      1.48
+++ sys/dev/ic/ar5xxx.h 25 Apr 2010 12:28:03 -0000
@@ -645,6 +645,8 @@ struct ar5k_gain {
 #define AR5K_EEPROM_INFO_CKSUM         0xffff
 #define AR5K_EEPROM_INFO(_n)           (AR5K_EEPROM_INFO_BASE + (_n))
 
+#define AR5K_EEPROM_IS_HB63            0x000b  /* Talon detect */
+
 #define AR5K_EEPROM_VERSION            AR5K_EEPROM_INFO(1)
 #define AR5K_EEPROM_VERSION_3_0                0x3000
 #define AR5K_EEPROM_VERSION_3_1                0x3001
@@ -695,12 +697,15 @@ struct ar5k_gain {
 #define AR5K_EEPROM_OBDB1_2GHZ 0x00ed
 
 /* Misc values available since EEPROM 4.0 */
-#define AR5K_EEPROM_MISC0              0x00c4
-#define AR5K_EEPROM_EARSTART(_v)       ((_v) & 0xfff)
-#define AR5K_EEPROM_EEMAP(_v)          (((_v) >> 14) & 0x3)
-#define AR5K_EEPROM_MISC1              0x00c5
-#define AR5K_EEPROM_TARGET_PWRSTART(_v)        ((_v) & 0xfff)
-#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v)        (((_v) >> 14) & 0x1)
+#define AR5K_EEPROM_MISC0                      0x00c4
+#define AR5K_EEPROM_EARSTART(_v)               ((_v) & 0xfff)
+#define AR5K_EEPROM_EEMAP(_v)                  (((_v) >> 14) & 0x3)
+#define AR5K_EEPROM_MISC1                      0x00c5
+#define AR5K_EEPROM_TARGET_PWRSTART(_v)                ((_v) & 0xfff)
+#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v)                (((_v) >> 14) & 0x1)
+#define AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(_v)    (((_v) >> 15) & 0x1)
+#define AR5K_EEPROM_MISC2                      0x00c6
+#define AR5K_EEPROM_MISC3                      0x00c7
 
 /* Some EEPROM defines */
 #define AR5K_EEPROM_EEP_SCALE          100
@@ -749,8 +754,11 @@ struct ar5k_eeprom_info {
        u_int16_t       ee_version;
        u_int16_t       ee_header;
        u_int16_t       ee_ant_gain;
+       HAL_BOOL        ee_is_hb63;
        u_int16_t       ee_misc0;
        u_int16_t       ee_misc1;
+       u_int16_t       ee_misc2;
+       u_int16_t       ee_misc3;
        u_int16_t       ee_cck_ofdm_gain_delta;
        u_int16_t       ee_cck_ofdm_power_delta;
        u_int16_t       ee_scaled_cck_delta;
@@ -1259,7 +1267,8 @@ struct ar5k_srev_name {
 #define AR5K_SREV_VER_AR5414   0xa5
 #define AR5K_SREV_VER_AR5416   0xc0    /* PCI-Express */
 #define AR5K_SREV_VER_AR5418   0xca    /* PCI-Express */
-#define AR5K_SREV_VER_AR2425   0xe2    /* PCI-Express */
+#define AR5K_SREV_VER_AR2425   0xe0    /* Swan */
+#define AR5K_SREV_VER_AR2417   0xf0    /* Nala */
 #define AR5K_SREV_VER_UNSUPP   0xff
 
 #define AR5K_SREV_RAD_5110     0x00
@@ -1271,10 +1280,15 @@ struct ar5k_srev_name {
 #define AR5K_SREV_RAD_2112     0x40
 #define AR5K_SREV_RAD_2112A    0x45
 #define AR5K_SREV_RAD_SC0      0x56
+#define AR5K_SREV_RAD_5413     0x60
 #define AR5K_SREV_RAD_SC1      0x63
 #define AR5K_SREV_RAD_SC2      0xa2
+#define AR5K_SREV_RAD_2425     0xa2
 #define AR5K_SREV_RAD_5133     0xc0
 #define AR5K_SREV_RAD_UNSUPP   0xff
+
+#define AR5K_SREV_PHY_5413     0x61
+#define AR5K_SREV_PHY_2425     0x70
 
 #define AR5K_DEVID_AR2413      0x001a
 #define AR5K_DEVID_AR5413      0x001b

Reply via email to