Hi tech@,

the diff below adds support for the Intel Centrino Wireless-N 2230 
card found in my Lenovo E330 to iwn(4). 

iwn0 at pci2 dev 0 function 0 "Intel Centrino Wireless-N 2230" rev 0xc4: msi, 
MIMO 2T2R, BGN, address 60:6c:66:3b:ea:39

This is the 0x0888 version.

I've got most changes from
https://github.com/seanbruno/freebsd-iwl/commit/53e6056c2df7355650abab77068943ac097a70c6#diff-7a5322b995ac8545b4f5d9096c3b5a5aR5445
 
which (i think) mostly landed in freebsd as part of
http://svnweb.freebsd.org/base?view=revision&revision=258035

This is the only iwn(4) device i have, so hopefully i did not broke 
another supported device.
Any feedback and tests are welcome.

Regards,
Fabian Raetz


Index: if_iwn.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwn.c,v
retrieving revision 1.127
diff -u -p -r1.127 if_iwn.c
--- if_iwn.c    6 Dec 2013 21:03:04 -0000       1.127
+++ if_iwn.c    30 Dec 2013 17:48:59 -0000
@@ -94,6 +94,8 @@ static const struct pci_matchid iwn_devi
        { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_130_2 },
        { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6235_1 },
        { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_6235_2 },
+       { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_2x30_1 },
+       { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_WL_2x30_2 },
 };
 
 int            iwn_match(struct device *, void *, void *);
@@ -244,6 +246,7 @@ int         iwn5000_send_calibration(struct iwn
 int            iwn5000_send_wimax_coex(struct iwn_softc *);
 int            iwn5000_crystal_calib(struct iwn_softc *);
 int            iwn5000_temp_offset_calib(struct iwn_softc *);
+int            iwn5000_temp_offset_calibv2(struct iwn_softc *);
 int            iwn4965_post_alive(struct iwn_softc *);
 int            iwn5000_post_alive(struct iwn_softc *);
 int            iwn4965_load_bootcode(struct iwn_softc *, const uint8_t *,
@@ -651,6 +654,11 @@ iwn5000_attach(struct iwn_softc *sc, pci
                } else
                        sc->fwname = "iwn-6005";
                break;
+       case IWN_HW_REV_TYPE_2030:
+               sc->limits = &iwn2030_sensitivity_limits;
+               sc->fwname = "iwn-2030";
+        sc->sc_flags |= IWN_FLAG_ADV_BT_COEX;
+        break;
        default:
                printf(": adapter type %d not supported\n", sc->hw_type);
                return ENOTSUP;
@@ -1529,6 +1537,14 @@ iwn5000_read_eeprom(struct iwn_softc *sc
            hdr.version, hdr.pa_type, letoh16(hdr.volt)));
        sc->calib_ver = hdr.version;
 
+       if (sc->hw_type == IWN_HW_REV_TYPE_2030) {
+        sc->eeprom_voltage = letoh16(hdr.volt);
+        iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2);
+        sc->eeprom_temp_high = letoh16(val);
+        iwn_read_prom_data(sc, base + IWN5000_EEPROM_VOLT, &val, 2);
+        sc->eeprom_temp = letoh16(val);
+    }
+
        if (sc->hw_type == IWN_HW_REV_TYPE_5150) {
                /* Compute temperature offset. */
                iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2);
@@ -2095,7 +2111,8 @@ iwn5000_rx_calib_results(struct iwn_soft
 
        switch (calib->code) {
        case IWN5000_PHY_CALIB_DC:
-               if (sc->hw_type == IWN_HW_REV_TYPE_5150)
+               if (sc->hw_type == IWN_HW_REV_TYPE_5150 ||
+            sc->hw_type == IWN_HW_REV_TYPE_2030)
                        idx = 0;
                break;
        case IWN5000_PHY_CALIB_LO:
@@ -4161,28 +4178,51 @@ iwn_send_advanced_btcoex(struct iwn_soft
                0xc0004000, 0x00004000, 0xf0005000, 0xf0005000,
        };
        struct iwn6000_btcoex_config btconfig;
+    struct iwn2000_btcoex_config btconfig2k;
        struct iwn_btcoex_priotable btprio;
        struct iwn_btcoex_prot btprot;
        int error, i;
 
        memset(&btconfig, 0, sizeof btconfig);
-       btconfig.flags = IWN_BT_FLAG_COEX6000_CHAN_INHIBITION |
-           (IWN_BT_FLAG_COEX6000_MODE_3W << IWN_BT_FLAG_COEX6000_MODE_SHIFT) |
-           IWN_BT_FLAG_SYNC_2_BT_DISABLE;
-       btconfig.max_kill = 5;
-       btconfig.bt3_t7_timer = 1;
-       btconfig.kill_ack = htole32(0xffff0000);
-       btconfig.kill_cts = htole32(0xffff0000);
-       btconfig.sample_time = 2;
-       btconfig.bt3_t2_timer = 0xc;
-       for (i = 0; i < 12; i++)
-               btconfig.lookup_table[i] = htole32(btcoex_3wire[i]);
-       btconfig.valid = htole16(0xff);
-       btconfig.prio_boost = 0xf0;
-       DPRINTF(("configuring advanced bluetooth coexistence\n"));
-       error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig, sizeof(btconfig), 1);
-       if (error != 0)
-               return (error);
+    memset(&btconfig2k, 0, sizeof btconfig2k);
+
+    if (sc->hw_type == IWN_HW_REV_TYPE_2030) {
+        btconfig2k.flags = IWN_BT_FLAG_COEX6000_CHAN_INHIBITION |
+            (IWN_BT_FLAG_COEX6000_MODE_3W << IWN_BT_FLAG_COEX6000_MODE_SHIFT) |
+            IWN_BT_FLAG_SYNC_2_BT_DISABLE;
+        btconfig2k.max_kill = 5;
+        btconfig2k.bt3_t7_timer = 1;
+        btconfig2k.kill_ack = htole32(0xffff0000);
+        btconfig2k.kill_cts = htole32(0xffff0000);
+        btconfig2k.sample_time = 2;
+        btconfig2k.bt3_t2_timer = 0xc;
+        for (i = 0; i < 12; i++)
+            btconfig2k.lookup_table[i] = htole32(btcoex_3wire[i]);
+        btconfig2k.valid = htole16(0xff);
+        btconfig2k.prio_boost = htole32(0xf0);
+        DPRINTF(("configuring advanced bluetooth coexistence\n"));
+        error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig2k, sizeof(btconfig2k), 
1);
+        if (error != 0)
+            return (error);
+    } else {
+        btconfig.flags = IWN_BT_FLAG_COEX6000_CHAN_INHIBITION |
+            (IWN_BT_FLAG_COEX6000_MODE_3W << IWN_BT_FLAG_COEX6000_MODE_SHIFT) |
+            IWN_BT_FLAG_SYNC_2_BT_DISABLE;
+        btconfig.max_kill = 5;
+        btconfig.bt3_t7_timer = 1;
+        btconfig.kill_ack = htole32(0xffff0000);
+        btconfig.kill_cts = htole32(0xffff0000);
+        btconfig.sample_time = 2;
+        btconfig.bt3_t2_timer = 0xc;
+        for (i = 0; i < 12; i++)
+            btconfig.lookup_table[i] = htole32(btcoex_3wire[i]);
+        btconfig.valid = htole16(0xff);
+        btconfig.prio_boost = 0xf0;
+        DPRINTF(("configuring advanced bluetooth coexistence\n"));
+        error = iwn_cmd(sc, IWN_CMD_BT_COEX, &btconfig, sizeof(btconfig), 1);
+        if (error != 0)
+            return (error);
+    }
 
        memset(&btprio, 0, sizeof btprio);
        btprio.calib_init1 = 0x6;
@@ -4233,14 +4273,21 @@ iwn_config(struct iwn_softc *sc)
        uint16_t rxchain;
        int error;
 
+    /* Set radio temperature sensor offset. */
        if (sc->hw_type == IWN_HW_REV_TYPE_6005) {
-               /* Set radio temperature sensor offset. */
                error = iwn5000_temp_offset_calib(sc);
                if (error != 0) {
                        printf("%s: could not set temperature offset\n",
                            sc->sc_dev.dv_xname);
                        return error;
                }
+       } else if (sc->hw_type == IWN_HW_REV_TYPE_2030) {
+               error = iwn5000_temp_offset_calibv2(sc);
+               if (error != 0) {
+                       printf("%s: could not set temperature offset v2\n",
+                           sc->sc_dev.dv_xname);
+                       return error;
+               }
        }
 
        if (sc->hw_type == IWN_HW_REV_TYPE_6050 ||
@@ -5005,6 +5052,33 @@ iwn5000_temp_offset_calib(struct iwn_sof
        return iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0);
 }
 
+int
+iwn5000_temp_offset_calibv2(struct iwn_softc *sc)
+{
+    struct iwn5000_phy_calib_temp_offsetv2 cmd;
+
+    memset(&cmd, 0, sizeof cmd);
+    cmd.code = IWN5000_PHY_CALIB_TEMP_OFFSET;
+       cmd.ngroups = 1;
+       cmd.isvalid = 1;
+       if (sc->eeprom_temp != 0) {
+               cmd.offset_low = htole16(sc->eeprom_temp);
+               cmd.offset_high = htole16(sc->eeprom_temp_high);
+    }
+       else {
+               cmd.offset_low = htole16(IWN_DEFAULT_TEMP_OFFSET);
+               cmd.offset_high = htole16(IWN_DEFAULT_TEMP_OFFSET);
+    }
+    cmd.burnt_voltage_ref = htole16(sc->eeprom_voltage);
+
+       DPRINTF(("setting radio sensor low offset to %d, high offset to %d, 
voltage to %d\n", 
+                letoh16(cmd.offset_low),
+                letoh16(cmd.offset_high),
+                letoh16(cmd.burnt_voltage_ref)));
+
+    return iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0);
+}
+
 /*
  * This function is called after the runtime firmware notifies us of its
  * readiness (called in a process context).
@@ -5681,6 +5755,9 @@ iwn5000_nic_config(struct iwn_softc *sc)
        }
        if (sc->hw_type == IWN_HW_REV_TYPE_6005)
                IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_6050_1X2);
+
+    if (sc->hw_type == IWN_HW_REV_TYPE_2030)
+        IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_REG_BIT_RADIO_IQ_INVERT);
        return 0;
 }
 
Index: if_iwnreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwnreg.h,v
retrieving revision 1.45
diff -u -p -r1.45 if_iwnreg.h
--- if_iwnreg.h 26 Nov 2013 20:33:17 -0000      1.45
+++ if_iwnreg.h 30 Dec 2013 17:49:01 -0000
@@ -205,6 +205,7 @@
 #define IWN_HW_REV_TYPE_6000   7
 #define IWN_HW_REV_TYPE_6050   8
 #define IWN_HW_REV_TYPE_6005   11
+#define IWN_HW_REV_TYPE_2030   12
 
 /* Possible flags for register IWN_GIO_CHICKEN. */
 #define IWN_GIO_CHICKEN_L1A_NO_L0S_RX  (1 << 23)
@@ -219,6 +220,7 @@
 #define IWN_GP_DRIVER_RADIO_2X2_IPA    (2 << 0)
 #define IWN_GP_DRIVER_CALIB_VER6       (1 << 2)
 #define IWN_GP_DRIVER_6050_1X2         (1 << 3)
+#define IWN_GP_DRIVER_REG_BIT_RADIO_IQ_INVERT   (0x00000080)
 
 /* Possible flags for register IWN_UCODE_GP1_CLR. */
 #define IWN_UCODE_GP1_RFKILL           (1 << 1)
@@ -878,6 +880,28 @@ struct iwn6000_btcoex_config {
        uint16_t        rx_prio_boost;
 } __packed;
 
+/* Structure for enhanced command IWN_CMD_BLUETOOTH for 2000 Series. */
+struct iwn2000_btcoex_config {
+       uint8_t         flags; /* Cf Flags in iwn6000_btcoex_config */
+       uint8_t         lead_time;
+       uint8_t         max_kill;
+       uint8_t         bt3_t7_timer;
+       uint32_t        kill_ack;
+       uint32_t        kill_cts;
+       uint8_t         sample_time;
+       uint8_t         bt3_t2_timer;
+       uint16_t        bt4_reaction;
+       uint32_t        lookup_table[12];
+       uint16_t        bt4_decision;
+       uint16_t        valid;
+    
+       uint32_t        prio_boost; /* size change prior to 
iwn6000_btcoex_config */
+    uint8_t     reserved; /* added prior to iwn6000_btcoex_config */
+
+       uint8_t         tx_prio_boost;
+       uint16_t        rx_prio_boost;
+} __packed;
+
 /* Structure for command IWN_CMD_BT_COEX_PRIOTABLE */
 struct iwn_btcoex_priotable {
        uint8_t         calib_init1;
@@ -998,6 +1022,17 @@ struct iwn5000_phy_calib_temp_offset {
        uint16_t        reserved;
 } __packed;
 
+struct iwn5000_phy_calib_temp_offsetv2 {
+       uint8_t         code;
+       uint8_t         group;
+       uint8_t         ngroups;
+       uint8_t         isvalid;
+       int16_t         offset_high;
+       int16_t         offset_low;
+       int16_t         burnt_voltage_ref;
+       int16_t     reserved;
+} __packed;
+
 struct iwn_phy_calib_gain {
        uint8_t code;
        uint8_t group;
@@ -1718,6 +1753,19 @@ static const struct iwn_sensitivity_limi
         97,
        100
 };
+
+/* Get value from linux kernel 3.2.+ in 
Drivers/net/wireless/iwlwifi/iwl-2000.c */
+static const struct iwn_sensitivity_limits iwn2030_sensitivity_limits = {
+       105, 110,
+       128, 232,
+        80, 145,
+       128, 232,
+       125, 175,
+       160, 310,
+        97,
+        97,
+       110
+ };
 
 /* Map TID to TX scheduler's FIFO. */
 static const uint8_t iwn_tid2fifo[] = {
Index: if_iwnvar.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwnvar.h,v
retrieving revision 1.26
diff -u -p -r1.26 if_iwnvar.h
--- if_iwnvar.h 30 Nov 2013 19:41:21 -0000      1.26
+++ if_iwnvar.h 30 Dec 2013 17:49:01 -0000
@@ -274,6 +274,7 @@ struct iwn_softc {
        char                    eeprom_domain[4];
        uint32_t                eeprom_crystal;
        int16_t                 eeprom_temp;
+       int16_t                 eeprom_temp_high;
        int16_t                 eeprom_voltage;
        int8_t                  maxpwr2GHz;
        int8_t                  maxpwr5GHz;
Index: pcidevs
===================================================================
RCS file: /cvs/src/sys/dev/pci/pcidevs,v
retrieving revision 1.1701
diff -u -p -r1.1701 pcidevs
--- pcidevs     29 Dec 2013 00:55:06 -0000      1.1701
+++ pcidevs     30 Dec 2013 17:49:03 -0000
@@ -2808,6 +2808,8 @@ product INTEL WL_6235_1           0x088e  Centrino
 product INTEL WL_6235_2                0x088f  Centrino Advanced-N 6235
 product INTEL WL_6150_1                0x0885  WiFi Link 6150
 product INTEL WL_6150_2                0x0886  WiFi Link 6150
+product INTEL WL_2x30_1            0x0887  Centrino Wireless-N 2230
+product INTEL WL_2x30_2            0x0888  Centrino Wireless-N 2230
 product INTEL WL_130_1         0x0896  WiFi Link 130
 product INTEL WL_130_2         0x0897  WiFi Link 130
 product INTEL WL_100_1         0x08ae  WiFi Link 100

Reply via email to