diff options
author | Jeff Garzik <jeff@garzik.org> | 2006-08-19 17:46:13 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-08-19 17:46:13 -0400 |
commit | a513c315f95c6d73041436fd1598d51722bd6264 (patch) | |
tree | 505f9a15c1771756cf21011e3f291b81c86cb3df /drivers | |
parent | fd6746daade513bf7f887625c107878b6aacccfd (diff) | |
parent | 113b898e38cb20e80847c24154ce62273b948c6a (diff) |
Merge branch 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6 into upstream
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/ray_cs.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_chip.c | 62 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_chip.h | 15 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_def.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_mac.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_mac.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_rf.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_rf.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_rf_al2230.c | 155 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_rf_al7230b.c | 274 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_usb.c | 120 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_usb.h | 1 |
13 files changed, 575 insertions, 77 deletions
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 61b83a5e737a..8e112d139e29 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c | |||
@@ -52,8 +52,8 @@ | |||
52 | #include <pcmcia/ds.h> | 52 | #include <pcmcia/ds.h> |
53 | #include <pcmcia/mem_op.h> | 53 | #include <pcmcia/mem_op.h> |
54 | 54 | ||
55 | #include <net/ieee80211.h> | ||
56 | #include <linux/wireless.h> | 55 | #include <linux/wireless.h> |
56 | #include <net/iw_handler.h> | ||
57 | 57 | ||
58 | #include <asm/io.h> | 58 | #include <asm/io.h> |
59 | #include <asm/system.h> | 59 | #include <asm/system.h> |
diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile index 500314fc74d2..6603ad5be63d 100644 --- a/drivers/net/wireless/zd1211rw/Makefile +++ b/drivers/net/wireless/zd1211rw/Makefile | |||
@@ -3,6 +3,7 @@ obj-$(CONFIG_ZD1211RW) += zd1211rw.o | |||
3 | zd1211rw-objs := zd_chip.o zd_ieee80211.o \ | 3 | zd1211rw-objs := zd_chip.o zd_ieee80211.o \ |
4 | zd_mac.o zd_netdev.o \ | 4 | zd_mac.o zd_netdev.o \ |
5 | zd_rf_al2230.o zd_rf_rf2959.o \ | 5 | zd_rf_al2230.o zd_rf_rf2959.o \ |
6 | zd_rf_al7230b.o \ | ||
6 | zd_rf.o zd_usb.o zd_util.o | 7 | zd_rf.o zd_usb.o zd_util.o |
7 | 8 | ||
8 | ifeq ($(CONFIG_ZD1211RW_DEBUG),y) | 9 | ifeq ($(CONFIG_ZD1211RW_DEBUG),y) |
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index da9d06bdb818..58419985e00f 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c | |||
@@ -42,12 +42,11 @@ void zd_chip_init(struct zd_chip *chip, | |||
42 | 42 | ||
43 | void zd_chip_clear(struct zd_chip *chip) | 43 | void zd_chip_clear(struct zd_chip *chip) |
44 | { | 44 | { |
45 | mutex_lock(&chip->mutex); | 45 | ZD_ASSERT(!mutex_is_locked(&chip->mutex)); |
46 | zd_usb_clear(&chip->usb); | 46 | zd_usb_clear(&chip->usb); |
47 | zd_rf_clear(&chip->rf); | 47 | zd_rf_clear(&chip->rf); |
48 | mutex_unlock(&chip->mutex); | ||
49 | mutex_destroy(&chip->mutex); | 48 | mutex_destroy(&chip->mutex); |
50 | memset(chip, 0, sizeof(*chip)); | 49 | ZD_MEMCLEAR(chip, sizeof(*chip)); |
51 | } | 50 | } |
52 | 51 | ||
53 | static int scnprint_mac_oui(const u8 *addr, char *buffer, size_t size) | 52 | static int scnprint_mac_oui(const u8 *addr, char *buffer, size_t size) |
@@ -68,10 +67,11 @@ static int scnprint_id(struct zd_chip *chip, char *buffer, size_t size) | |||
68 | i += scnprint_mac_oui(chip->e2p_mac, buffer+i, size-i); | 67 | i += scnprint_mac_oui(chip->e2p_mac, buffer+i, size-i); |
69 | i += scnprintf(buffer+i, size-i, " "); | 68 | i += scnprintf(buffer+i, size-i, " "); |
70 | i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i); | 69 | i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i); |
71 | i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c", chip->pa_type, | 70 | i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c%c", chip->pa_type, |
72 | chip->patch_cck_gain ? 'g' : '-', | 71 | chip->patch_cck_gain ? 'g' : '-', |
73 | chip->patch_cr157 ? '7' : '-', | 72 | chip->patch_cr157 ? '7' : '-', |
74 | chip->patch_6m_band_edge ? '6' : '-'); | 73 | chip->patch_6m_band_edge ? '6' : '-', |
74 | chip->new_phy_layout ? 'N' : '-'); | ||
75 | return i; | 75 | return i; |
76 | } | 76 | } |
77 | 77 | ||
@@ -330,13 +330,14 @@ static int read_pod(struct zd_chip *chip, u8 *rf_type) | |||
330 | chip->patch_cck_gain = (value >> 8) & 0x1; | 330 | chip->patch_cck_gain = (value >> 8) & 0x1; |
331 | chip->patch_cr157 = (value >> 13) & 0x1; | 331 | chip->patch_cr157 = (value >> 13) & 0x1; |
332 | chip->patch_6m_band_edge = (value >> 21) & 0x1; | 332 | chip->patch_6m_band_edge = (value >> 21) & 0x1; |
333 | chip->new_phy_layout = (value >> 31) & 0x1; | ||
333 | 334 | ||
334 | dev_dbg_f(zd_chip_dev(chip), | 335 | dev_dbg_f(zd_chip_dev(chip), |
335 | "RF %s %#01x PA type %#01x patch CCK %d patch CR157 %d " | 336 | "RF %s %#01x PA type %#01x patch CCK %d patch CR157 %d " |
336 | "patch 6M %d\n", | 337 | "patch 6M %d new PHY %d\n", |
337 | zd_rf_name(*rf_type), *rf_type, | 338 | zd_rf_name(*rf_type), *rf_type, |
338 | chip->pa_type, chip->patch_cck_gain, | 339 | chip->pa_type, chip->patch_cck_gain, |
339 | chip->patch_cr157, chip->patch_6m_band_edge); | 340 | chip->patch_cr157, chip->patch_6m_band_edge, chip->new_phy_layout); |
340 | return 0; | 341 | return 0; |
341 | error: | 342 | error: |
342 | *rf_type = 0; | 343 | *rf_type = 0; |
@@ -344,6 +345,7 @@ error: | |||
344 | chip->patch_cck_gain = 0; | 345 | chip->patch_cck_gain = 0; |
345 | chip->patch_cr157 = 0; | 346 | chip->patch_cr157 = 0; |
346 | chip->patch_6m_band_edge = 0; | 347 | chip->patch_6m_band_edge = 0; |
348 | chip->new_phy_layout = 0; | ||
347 | return r; | 349 | return r; |
348 | } | 350 | } |
349 | 351 | ||
@@ -717,7 +719,7 @@ static int zd1211b_hw_reset_phy(struct zd_chip *chip) | |||
717 | { CR21, 0x0e }, { CR22, 0x23 }, { CR23, 0x90 }, | 719 | { CR21, 0x0e }, { CR22, 0x23 }, { CR23, 0x90 }, |
718 | { CR24, 0x14 }, { CR25, 0x40 }, { CR26, 0x10 }, | 720 | { CR24, 0x14 }, { CR25, 0x40 }, { CR26, 0x10 }, |
719 | { CR27, 0x10 }, { CR28, 0x7f }, { CR29, 0x80 }, | 721 | { CR27, 0x10 }, { CR28, 0x7f }, { CR29, 0x80 }, |
720 | { CR30, 0x49 }, /* jointly decoder, no ASIC */ | 722 | { CR30, 0x4b }, /* ASIC/FWT, no jointly decoder */ |
721 | { CR31, 0x60 }, { CR32, 0x43 }, { CR33, 0x08 }, | 723 | { CR31, 0x60 }, { CR32, 0x43 }, { CR33, 0x08 }, |
722 | { CR34, 0x06 }, { CR35, 0x0a }, { CR36, 0x00 }, | 724 | { CR34, 0x06 }, { CR35, 0x0a }, { CR36, 0x00 }, |
723 | { CR37, 0x00 }, { CR38, 0x38 }, { CR39, 0x0c }, | 725 | { CR37, 0x00 }, { CR38, 0x38 }, { CR39, 0x0c }, |
@@ -807,7 +809,6 @@ static int zd1211_hw_init_hmac(struct zd_chip *chip) | |||
807 | { CR_ACK_TIMEOUT_EXT, 0x80 }, | 809 | { CR_ACK_TIMEOUT_EXT, 0x80 }, |
808 | { CR_ADDA_PWR_DWN, 0x00 }, | 810 | { CR_ADDA_PWR_DWN, 0x00 }, |
809 | { CR_ACK_TIME_80211, 0x100 }, | 811 | { CR_ACK_TIME_80211, 0x100 }, |
810 | { CR_IFS_VALUE, 0x547c032 }, | ||
811 | { CR_RX_PE_DELAY, 0x70 }, | 812 | { CR_RX_PE_DELAY, 0x70 }, |
812 | { CR_PS_CTRL, 0x10000000 }, | 813 | { CR_PS_CTRL, 0x10000000 }, |
813 | { CR_RTS_CTS_RATE, 0x02030203 }, | 814 | { CR_RTS_CTS_RATE, 0x02030203 }, |
@@ -854,11 +855,10 @@ static int zd1211b_hw_init_hmac(struct zd_chip *chip) | |||
854 | { CR_ACK_TIMEOUT_EXT, 0x80 }, | 855 | { CR_ACK_TIMEOUT_EXT, 0x80 }, |
855 | { CR_ADDA_PWR_DWN, 0x00 }, | 856 | { CR_ADDA_PWR_DWN, 0x00 }, |
856 | { CR_ACK_TIME_80211, 0x100 }, | 857 | { CR_ACK_TIME_80211, 0x100 }, |
857 | { CR_IFS_VALUE, 0x547c032 }, | ||
858 | { CR_RX_PE_DELAY, 0x70 }, | 858 | { CR_RX_PE_DELAY, 0x70 }, |
859 | { CR_PS_CTRL, 0x10000000 }, | 859 | { CR_PS_CTRL, 0x10000000 }, |
860 | { CR_RTS_CTS_RATE, 0x02030203 }, | 860 | { CR_RTS_CTS_RATE, 0x02030203 }, |
861 | { CR_RX_THRESHOLD, 0x000c0640 }, | 861 | { CR_RX_THRESHOLD, 0x000c0eff, }, |
862 | { CR_AFTER_PNP, 0x1 }, | 862 | { CR_AFTER_PNP, 0x1 }, |
863 | { CR_WEP_PROTECT, 0x114 }, | 863 | { CR_WEP_PROTECT, 0x114 }, |
864 | }; | 864 | }; |
@@ -970,10 +970,15 @@ static int hw_init(struct zd_chip *chip) | |||
970 | r = hw_init_hmac(chip); | 970 | r = hw_init_hmac(chip); |
971 | if (r) | 971 | if (r) |
972 | return r; | 972 | return r; |
973 | r = set_beacon_interval(chip, 100); | 973 | |
974 | /* Although the vendor driver defaults to a different value during | ||
975 | * init, it overwrites the IFS value with the following every time | ||
976 | * the channel changes. We should aim to be more intelligent... */ | ||
977 | r = zd_iowrite32_locked(chip, IFS_VALUE_DEFAULT, CR_IFS_VALUE); | ||
974 | if (r) | 978 | if (r) |
975 | return r; | 979 | return r; |
976 | return 0; | 980 | |
981 | return set_beacon_interval(chip, 100); | ||
977 | } | 982 | } |
978 | 983 | ||
979 | #ifdef DEBUG | 984 | #ifdef DEBUG |
@@ -1613,3 +1618,34 @@ int zd_rfwritev_locked(struct zd_chip *chip, | |||
1613 | 1618 | ||
1614 | return 0; | 1619 | return 0; |
1615 | } | 1620 | } |
1621 | |||
1622 | /* | ||
1623 | * We can optionally program the RF directly through CR regs, if supported by | ||
1624 | * the hardware. This is much faster than the older method. | ||
1625 | */ | ||
1626 | int zd_rfwrite_cr_locked(struct zd_chip *chip, u32 value) | ||
1627 | { | ||
1628 | struct zd_ioreq16 ioreqs[] = { | ||
1629 | { CR244, (value >> 16) & 0xff }, | ||
1630 | { CR243, (value >> 8) & 0xff }, | ||
1631 | { CR242, value & 0xff }, | ||
1632 | }; | ||
1633 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
1634 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
1635 | } | ||
1636 | |||
1637 | int zd_rfwritev_cr_locked(struct zd_chip *chip, | ||
1638 | const u32 *values, unsigned int count) | ||
1639 | { | ||
1640 | int r; | ||
1641 | unsigned int i; | ||
1642 | |||
1643 | for (i = 0; i < count; i++) { | ||
1644 | r = zd_rfwrite_cr_locked(chip, values[i]); | ||
1645 | if (r) | ||
1646 | return r; | ||
1647 | } | ||
1648 | |||
1649 | return 0; | ||
1650 | } | ||
1651 | |||
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index 069d2b467339..4b1250859897 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h | |||
@@ -473,7 +473,15 @@ | |||
473 | 473 | ||
474 | #define CR_ACK_TIMEOUT_EXT CTL_REG(0x0690) | 474 | #define CR_ACK_TIMEOUT_EXT CTL_REG(0x0690) |
475 | #define CR_BCN_FIFO_SEMAPHORE CTL_REG(0x0694) | 475 | #define CR_BCN_FIFO_SEMAPHORE CTL_REG(0x0694) |
476 | |||
476 | #define CR_IFS_VALUE CTL_REG(0x0698) | 477 | #define CR_IFS_VALUE CTL_REG(0x0698) |
478 | #define IFS_VALUE_DIFS_SH 0 | ||
479 | #define IFS_VALUE_EIFS_SH 12 | ||
480 | #define IFS_VALUE_SIFS_SH 24 | ||
481 | #define IFS_VALUE_DEFAULT (( 50 << IFS_VALUE_DIFS_SH) | \ | ||
482 | (1148 << IFS_VALUE_EIFS_SH) | \ | ||
483 | ( 10 << IFS_VALUE_SIFS_SH)) | ||
484 | |||
477 | #define CR_RX_TIME_OUT CTL_REG(0x069C) | 485 | #define CR_RX_TIME_OUT CTL_REG(0x069C) |
478 | #define CR_TOTAL_RX_FRM CTL_REG(0x06A0) | 486 | #define CR_TOTAL_RX_FRM CTL_REG(0x06A0) |
479 | #define CR_CRC32_CNT CTL_REG(0x06A4) | 487 | #define CR_CRC32_CNT CTL_REG(0x06A4) |
@@ -630,6 +638,7 @@ enum { | |||
630 | LOAD_CODE_SIZE = 0xe, /* words */ | 638 | LOAD_CODE_SIZE = 0xe, /* words */ |
631 | LOAD_VECT_SIZE = 0x10000 - 0xfff7, /* words */ | 639 | LOAD_VECT_SIZE = 0x10000 - 0xfff7, /* words */ |
632 | EEPROM_REGS_OFFSET = LOAD_CODE_SIZE + LOAD_VECT_SIZE, | 640 | EEPROM_REGS_OFFSET = LOAD_CODE_SIZE + LOAD_VECT_SIZE, |
641 | EEPROM_REGS_SIZE = 0x7e, /* words */ | ||
633 | E2P_BASE_OFFSET = EEPROM_START_OFFSET + | 642 | E2P_BASE_OFFSET = EEPROM_START_OFFSET + |
634 | EEPROM_REGS_OFFSET, | 643 | EEPROM_REGS_OFFSET, |
635 | }; | 644 | }; |
@@ -655,7 +664,7 @@ struct zd_chip { | |||
655 | /* SetPointOFDM in the vendor driver */ | 664 | /* SetPointOFDM in the vendor driver */ |
656 | u8 ofdm_cal_values[3][E2P_CHANNEL_COUNT]; | 665 | u8 ofdm_cal_values[3][E2P_CHANNEL_COUNT]; |
657 | u8 pa_type:4, patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1, | 666 | u8 pa_type:4, patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1, |
658 | is_zd1211b:1; | 667 | new_phy_layout:1, is_zd1211b:1; |
659 | }; | 668 | }; |
660 | 669 | ||
661 | static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb) | 670 | static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb) |
@@ -739,8 +748,12 @@ static inline int zd_rfwrite_locked(struct zd_chip *chip, u32 value, u8 bits) | |||
739 | return zd_usb_rfwrite(&chip->usb, value, bits); | 748 | return zd_usb_rfwrite(&chip->usb, value, bits); |
740 | } | 749 | } |
741 | 750 | ||
751 | int zd_rfwrite_cr_locked(struct zd_chip *chip, u32 value); | ||
752 | |||
742 | int zd_rfwritev_locked(struct zd_chip *chip, | 753 | int zd_rfwritev_locked(struct zd_chip *chip, |
743 | const u32* values, unsigned int count, u8 bits); | 754 | const u32* values, unsigned int count, u8 bits); |
755 | int zd_rfwritev_cr_locked(struct zd_chip *chip, | ||
756 | const u32* values, unsigned int count); | ||
744 | 757 | ||
745 | /* Locking functions for reading and writing registers. | 758 | /* Locking functions for reading and writing registers. |
746 | * The different parameters are intentional. | 759 | * The different parameters are intentional. |
diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h index 465906812fc4..a13ec72eb304 100644 --- a/drivers/net/wireless/zd1211rw/zd_def.h +++ b/drivers/net/wireless/zd1211rw/zd_def.h | |||
@@ -45,4 +45,10 @@ do { \ | |||
45 | # define ZD_ASSERT(x) do { } while (0) | 45 | # define ZD_ASSERT(x) do { } while (0) |
46 | #endif | 46 | #endif |
47 | 47 | ||
48 | #ifdef DEBUG | ||
49 | # define ZD_MEMCLEAR(pointer, size) memset((pointer), 0xff, (size)) | ||
50 | #else | ||
51 | # define ZD_MEMCLEAR(pointer, size) do { } while (0) | ||
52 | #endif | ||
53 | |||
48 | #endif /* _ZD_DEF_H */ | 54 | #endif /* _ZD_DEF_H */ |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index d6f3e02a0b54..0eda534a648c 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -127,11 +127,9 @@ out: | |||
127 | 127 | ||
128 | void zd_mac_clear(struct zd_mac *mac) | 128 | void zd_mac_clear(struct zd_mac *mac) |
129 | { | 129 | { |
130 | /* Aquire the lock. */ | ||
131 | spin_lock(&mac->lock); | ||
132 | spin_unlock(&mac->lock); | ||
133 | zd_chip_clear(&mac->chip); | 130 | zd_chip_clear(&mac->chip); |
134 | memset(mac, 0, sizeof(*mac)); | 131 | ZD_ASSERT(!spin_is_locked(&mac->lock)); |
132 | ZD_MEMCLEAR(mac, sizeof(struct zd_mac)); | ||
135 | } | 133 | } |
136 | 134 | ||
137 | static int reset_mode(struct zd_mac *mac) | 135 | static int reset_mode(struct zd_mac *mac) |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index 71e382c589ee..082bcf8ec8dc 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h | |||
@@ -121,9 +121,9 @@ enum mac_flags { | |||
121 | }; | 121 | }; |
122 | 122 | ||
123 | struct zd_mac { | 123 | struct zd_mac { |
124 | struct net_device *netdev; | ||
125 | struct zd_chip chip; | 124 | struct zd_chip chip; |
126 | spinlock_t lock; | 125 | spinlock_t lock; |
126 | struct net_device *netdev; | ||
127 | /* Unlocked reading possible */ | 127 | /* Unlocked reading possible */ |
128 | struct iw_statistics iw_stats; | 128 | struct iw_statistics iw_stats; |
129 | u8 qual_average; | 129 | u8 qual_average; |
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c index d3770d2c61bc..f50cff3db916 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf.c +++ b/drivers/net/wireless/zd1211rw/zd_rf.c | |||
@@ -56,7 +56,7 @@ void zd_rf_init(struct zd_rf *rf) | |||
56 | 56 | ||
57 | void zd_rf_clear(struct zd_rf *rf) | 57 | void zd_rf_clear(struct zd_rf *rf) |
58 | { | 58 | { |
59 | memset(rf, 0, sizeof(*rf)); | 59 | ZD_MEMCLEAR(rf, sizeof(*rf)); |
60 | } | 60 | } |
61 | 61 | ||
62 | int zd_rf_init_hw(struct zd_rf *rf, u8 type) | 62 | int zd_rf_init_hw(struct zd_rf *rf, u8 type) |
@@ -76,6 +76,11 @@ int zd_rf_init_hw(struct zd_rf *rf, u8 type) | |||
76 | if (r) | 76 | if (r) |
77 | return r; | 77 | return r; |
78 | break; | 78 | break; |
79 | case AL7230B_RF: | ||
80 | r = zd_rf_init_al7230b(rf); | ||
81 | if (r) | ||
82 | return r; | ||
83 | break; | ||
79 | default: | 84 | default: |
80 | dev_err(zd_chip_dev(chip), | 85 | dev_err(zd_chip_dev(chip), |
81 | "RF %s %#x is not supported\n", zd_rf_name(type), type); | 86 | "RF %s %#x is not supported\n", zd_rf_name(type), type); |
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h index ea30f693fcc8..676b3734f1ed 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf.h +++ b/drivers/net/wireless/zd1211rw/zd_rf.h | |||
@@ -78,5 +78,6 @@ int zd_switch_radio_off(struct zd_rf *rf); | |||
78 | 78 | ||
79 | int zd_rf_init_rf2959(struct zd_rf *rf); | 79 | int zd_rf_init_rf2959(struct zd_rf *rf); |
80 | int zd_rf_init_al2230(struct zd_rf *rf); | 80 | int zd_rf_init_al2230(struct zd_rf *rf); |
81 | int zd_rf_init_al7230b(struct zd_rf *rf); | ||
81 | 82 | ||
82 | #endif /* _ZD_RF_H */ | 83 | #endif /* _ZD_RF_H */ |
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c index 0948b25f660d..25323a13a3db 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c +++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include "zd_usb.h" | 21 | #include "zd_usb.h" |
22 | #include "zd_chip.h" | 22 | #include "zd_chip.h" |
23 | 23 | ||
24 | static const u32 al2230_table[][3] = { | 24 | static const u32 zd1211_al2230_table[][3] = { |
25 | RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, }, | 25 | RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, }, |
26 | RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, }, | 26 | RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, }, |
27 | RF_CHANNEL( 3) = { 0x03e790, 0x033331, 0x00000d, }, | 27 | RF_CHANNEL( 3) = { 0x03e790, 0x033331, 0x00000d, }, |
@@ -38,6 +38,53 @@ static const u32 al2230_table[][3] = { | |||
38 | RF_CHANNEL(14) = { 0x03e7c0, 0x066661, 0x00000d, }, | 38 | RF_CHANNEL(14) = { 0x03e7c0, 0x066661, 0x00000d, }, |
39 | }; | 39 | }; |
40 | 40 | ||
41 | static const u32 zd1211b_al2230_table[][3] = { | ||
42 | RF_CHANNEL( 1) = { 0x09efc0, 0x8cccc0, 0xb00000, }, | ||
43 | RF_CHANNEL( 2) = { 0x09efc0, 0x8cccd0, 0xb00000, }, | ||
44 | RF_CHANNEL( 3) = { 0x09e7c0, 0x8cccc0, 0xb00000, }, | ||
45 | RF_CHANNEL( 4) = { 0x09e7c0, 0x8cccd0, 0xb00000, }, | ||
46 | RF_CHANNEL( 5) = { 0x05efc0, 0x8cccc0, 0xb00000, }, | ||
47 | RF_CHANNEL( 6) = { 0x05efc0, 0x8cccd0, 0xb00000, }, | ||
48 | RF_CHANNEL( 7) = { 0x05e7c0, 0x8cccc0, 0xb00000, }, | ||
49 | RF_CHANNEL( 8) = { 0x05e7c0, 0x8cccd0, 0xb00000, }, | ||
50 | RF_CHANNEL( 9) = { 0x0defc0, 0x8cccc0, 0xb00000, }, | ||
51 | RF_CHANNEL(10) = { 0x0defc0, 0x8cccd0, 0xb00000, }, | ||
52 | RF_CHANNEL(11) = { 0x0de7c0, 0x8cccc0, 0xb00000, }, | ||
53 | RF_CHANNEL(12) = { 0x0de7c0, 0x8cccd0, 0xb00000, }, | ||
54 | RF_CHANNEL(13) = { 0x03efc0, 0x8cccc0, 0xb00000, }, | ||
55 | RF_CHANNEL(14) = { 0x03e7c0, 0x866660, 0xb00000, }, | ||
56 | }; | ||
57 | |||
58 | static const struct zd_ioreq16 zd1211b_ioreqs_shared_1[] = { | ||
59 | { CR240, 0x57 }, { CR9, 0xe0 }, | ||
60 | }; | ||
61 | |||
62 | static int zd1211b_al2230_finalize_rf(struct zd_chip *chip) | ||
63 | { | ||
64 | int r; | ||
65 | static const struct zd_ioreq16 ioreqs[] = { | ||
66 | { CR80, 0x30 }, { CR81, 0x30 }, { CR79, 0x58 }, | ||
67 | { CR12, 0xf0 }, { CR77, 0x1b }, { CR78, 0x58 }, | ||
68 | { CR203, 0x06 }, | ||
69 | { }, | ||
70 | |||
71 | { CR240, 0x80 }, | ||
72 | }; | ||
73 | |||
74 | r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
75 | if (r) | ||
76 | return r; | ||
77 | |||
78 | /* related to antenna selection? */ | ||
79 | if (chip->new_phy_layout) { | ||
80 | r = zd_iowrite16_locked(chip, 0xe1, CR9); | ||
81 | if (r) | ||
82 | return r; | ||
83 | } | ||
84 | |||
85 | return zd_iowrite16_locked(chip, 0x06, CR203); | ||
86 | } | ||
87 | |||
41 | static int zd1211_al2230_init_hw(struct zd_rf *rf) | 88 | static int zd1211_al2230_init_hw(struct zd_rf *rf) |
42 | { | 89 | { |
43 | int r; | 90 | int r; |
@@ -139,7 +186,7 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf) | |||
139 | { CR47, 0x1e }, | 186 | { CR47, 0x1e }, |
140 | 187 | ||
141 | /* ZD1211B 05.06.10 */ | 188 | /* ZD1211B 05.06.10 */ |
142 | { CR48, 0x00 }, { CR49, 0x00 }, { CR51, 0x01 }, | 189 | { CR48, 0x06 }, { CR49, 0xf9 }, { CR51, 0x01 }, |
143 | { CR52, 0x80 }, { CR53, 0x7e }, { CR65, 0x00 }, | 190 | { CR52, 0x80 }, { CR53, 0x7e }, { CR65, 0x00 }, |
144 | { CR66, 0x00 }, { CR67, 0x00 }, { CR68, 0x00 }, | 191 | { CR66, 0x00 }, { CR67, 0x00 }, { CR68, 0x00 }, |
145 | { CR69, 0x28 }, | 192 | { CR69, 0x28 }, |
@@ -172,79 +219,78 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf) | |||
172 | { CR137, 0x50 }, /* 5614 */ | 219 | { CR137, 0x50 }, /* 5614 */ |
173 | { CR138, 0xa8 }, | 220 | { CR138, 0xa8 }, |
174 | { CR144, 0xac }, /* 5621 */ | 221 | { CR144, 0xac }, /* 5621 */ |
175 | { CR150, 0x0d }, { CR252, 0x00 }, { CR253, 0x00 }, | 222 | { CR150, 0x0d }, { CR252, 0x34 }, { CR253, 0x34 }, |
176 | }; | 223 | }; |
177 | 224 | ||
178 | static const u32 rv1[] = { | 225 | static const u32 rv1[] = { |
179 | /* channel 1 */ | 226 | 0x8cccd0, |
180 | 0x03f790, | 227 | 0x481dc0, |
181 | 0x033331, | 228 | 0xcfff00, |
182 | 0x00000d, | 229 | 0x25a000, |
183 | 230 | ||
184 | 0x0b3331, | 231 | /* To improve AL2230 yield, improve phase noise, 4713 */ |
185 | 0x03b812, | 232 | 0x25a000, |
186 | 0x00fff3, | 233 | 0xa3b2f0, |
187 | 0x0005a4, | 234 | |
188 | 0x0f4dc5, /* fix freq shift 0x044dc5 */ | 235 | 0x6da010, /* Reg6 update for MP versio */ |
189 | 0x0805b6, | 236 | 0xe36280, /* Modified by jxiao for Bor-Chin on 2004/08/02 */ |
190 | 0x0146c7, | 237 | 0x116000, |
191 | 0x000688, | 238 | 0x9dc020, /* External control TX power (CR31) */ |
192 | 0x0403b9, /* External control TX power (CR31) */ | 239 | 0x5ddb00, /* RegA update for MP version */ |
193 | 0x00dbba, | 240 | 0xd99000, /* RegB update for MP version */ |
194 | 0x00099b, | 241 | 0x3ffbd0, /* RegC update for MP version */ |
195 | 0x0bdffc, | 242 | 0xb00000, /* RegD update for MP version */ |
196 | 0x00000d, | 243 | |
197 | 0x00580f, | 244 | /* improve phase noise and remove phase calibration,4713 */ |
245 | 0xf01a00, | ||
198 | }; | 246 | }; |
199 | 247 | ||
200 | static const struct zd_ioreq16 ioreqs2[] = { | 248 | static const struct zd_ioreq16 ioreqs2[] = { |
201 | { CR47, 0x1e }, { CR_RFCFG, 0x03 }, | 249 | { CR251, 0x2f }, /* shdnb(PLL_ON)=0 */ |
250 | { CR251, 0x7f }, /* shdnb(PLL_ON)=1 */ | ||
202 | }; | 251 | }; |
203 | 252 | ||
204 | static const u32 rv2[] = { | 253 | static const u32 rv2[] = { |
205 | 0x00880f, | 254 | /* To improve AL2230 yield, 4713 */ |
206 | 0x00080f, | 255 | 0xf01b00, |
256 | 0xf01e00, | ||
257 | 0xf01a00, | ||
207 | }; | 258 | }; |
208 | 259 | ||
209 | static const struct zd_ioreq16 ioreqs3[] = { | 260 | static const struct zd_ioreq16 ioreqs3[] = { |
210 | { CR_RFCFG, 0x00 }, { CR47, 0x1e }, { CR251, 0x7f }, | 261 | /* related to 6M band edge patching, happens unconditionally */ |
211 | }; | 262 | { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, |
212 | |||
213 | static const u32 rv3[] = { | ||
214 | 0x00d80f, | ||
215 | 0x00780f, | ||
216 | 0x00580f, | ||
217 | }; | ||
218 | |||
219 | static const struct zd_ioreq16 ioreqs4[] = { | ||
220 | { CR138, 0x28 }, { CR203, 0x06 }, | ||
221 | }; | 263 | }; |
222 | 264 | ||
265 | r = zd_iowrite16a_locked(chip, zd1211b_ioreqs_shared_1, | ||
266 | ARRAY_SIZE(zd1211b_ioreqs_shared_1)); | ||
267 | if (r) | ||
268 | return r; | ||
223 | r = zd_iowrite16a_locked(chip, ioreqs1, ARRAY_SIZE(ioreqs1)); | 269 | r = zd_iowrite16a_locked(chip, ioreqs1, ARRAY_SIZE(ioreqs1)); |
224 | if (r) | 270 | if (r) |
225 | return r; | 271 | return r; |
226 | r = zd_rfwritev_locked(chip, rv1, ARRAY_SIZE(rv1), RF_RV_BITS); | 272 | r = zd_rfwritev_cr_locked(chip, zd1211b_al2230_table[0], 3); |
227 | if (r) | 273 | if (r) |
228 | return r; | 274 | return r; |
229 | r = zd_iowrite16a_locked(chip, ioreqs2, ARRAY_SIZE(ioreqs2)); | 275 | r = zd_rfwritev_cr_locked(chip, rv1, ARRAY_SIZE(rv1)); |
230 | if (r) | 276 | if (r) |
231 | return r; | 277 | return r; |
232 | r = zd_rfwritev_locked(chip, rv2, ARRAY_SIZE(rv2), RF_RV_BITS); | 278 | r = zd_iowrite16a_locked(chip, ioreqs2, ARRAY_SIZE(ioreqs2)); |
233 | if (r) | 279 | if (r) |
234 | return r; | 280 | return r; |
235 | r = zd_iowrite16a_locked(chip, ioreqs3, ARRAY_SIZE(ioreqs3)); | 281 | r = zd_rfwritev_cr_locked(chip, rv2, ARRAY_SIZE(rv2)); |
236 | if (r) | 282 | if (r) |
237 | return r; | 283 | return r; |
238 | r = zd_rfwritev_locked(chip, rv3, ARRAY_SIZE(rv3), RF_RV_BITS); | 284 | r = zd_iowrite16a_locked(chip, ioreqs3, ARRAY_SIZE(ioreqs3)); |
239 | if (r) | 285 | if (r) |
240 | return r; | 286 | return r; |
241 | return zd_iowrite16a_locked(chip, ioreqs4, ARRAY_SIZE(ioreqs4)); | 287 | return zd1211b_al2230_finalize_rf(chip); |
242 | } | 288 | } |
243 | 289 | ||
244 | static int al2230_set_channel(struct zd_rf *rf, u8 channel) | 290 | static int zd1211_al2230_set_channel(struct zd_rf *rf, u8 channel) |
245 | { | 291 | { |
246 | int r; | 292 | int r; |
247 | const u32 *rv = al2230_table[channel-1]; | 293 | const u32 *rv = zd1211_al2230_table[channel-1]; |
248 | struct zd_chip *chip = zd_rf_to_chip(rf); | 294 | struct zd_chip *chip = zd_rf_to_chip(rf); |
249 | static const struct zd_ioreq16 ioreqs[] = { | 295 | static const struct zd_ioreq16 ioreqs[] = { |
250 | { CR138, 0x28 }, | 296 | { CR138, 0x28 }, |
@@ -257,6 +303,24 @@ static int al2230_set_channel(struct zd_rf *rf, u8 channel) | |||
257 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | 303 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); |
258 | } | 304 | } |
259 | 305 | ||
306 | static int zd1211b_al2230_set_channel(struct zd_rf *rf, u8 channel) | ||
307 | { | ||
308 | int r; | ||
309 | const u32 *rv = zd1211b_al2230_table[channel-1]; | ||
310 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
311 | |||
312 | r = zd_iowrite16a_locked(chip, zd1211b_ioreqs_shared_1, | ||
313 | ARRAY_SIZE(zd1211b_ioreqs_shared_1)); | ||
314 | if (r) | ||
315 | return r; | ||
316 | |||
317 | r = zd_rfwritev_cr_locked(chip, rv, 3); | ||
318 | if (r) | ||
319 | return r; | ||
320 | |||
321 | return zd1211b_al2230_finalize_rf(chip); | ||
322 | } | ||
323 | |||
260 | static int zd1211_al2230_switch_radio_on(struct zd_rf *rf) | 324 | static int zd1211_al2230_switch_radio_on(struct zd_rf *rf) |
261 | { | 325 | { |
262 | struct zd_chip *chip = zd_rf_to_chip(rf); | 326 | struct zd_chip *chip = zd_rf_to_chip(rf); |
@@ -294,13 +358,14 @@ int zd_rf_init_al2230(struct zd_rf *rf) | |||
294 | { | 358 | { |
295 | struct zd_chip *chip = zd_rf_to_chip(rf); | 359 | struct zd_chip *chip = zd_rf_to_chip(rf); |
296 | 360 | ||
297 | rf->set_channel = al2230_set_channel; | ||
298 | rf->switch_radio_off = al2230_switch_radio_off; | 361 | rf->switch_radio_off = al2230_switch_radio_off; |
299 | if (chip->is_zd1211b) { | 362 | if (chip->is_zd1211b) { |
300 | rf->init_hw = zd1211b_al2230_init_hw; | 363 | rf->init_hw = zd1211b_al2230_init_hw; |
364 | rf->set_channel = zd1211b_al2230_set_channel; | ||
301 | rf->switch_radio_on = zd1211b_al2230_switch_radio_on; | 365 | rf->switch_radio_on = zd1211b_al2230_switch_radio_on; |
302 | } else { | 366 | } else { |
303 | rf->init_hw = zd1211_al2230_init_hw; | 367 | rf->init_hw = zd1211_al2230_init_hw; |
368 | rf->set_channel = zd1211_al2230_set_channel; | ||
304 | rf->switch_radio_on = zd1211_al2230_switch_radio_on; | 369 | rf->switch_radio_on = zd1211_al2230_switch_radio_on; |
305 | } | 370 | } |
306 | rf->patch_6m_band_edge = 1; | 371 | rf->patch_6m_band_edge = 1; |
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c new file mode 100644 index 000000000000..a289f95187ec --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c | |||
@@ -0,0 +1,274 @@ | |||
1 | /* zd_rf_al7230b.c: Functions for the AL7230B RF controller | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation; either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | |||
20 | #include "zd_rf.h" | ||
21 | #include "zd_usb.h" | ||
22 | #include "zd_chip.h" | ||
23 | |||
24 | static const u32 chan_rv[][2] = { | ||
25 | RF_CHANNEL( 1) = { 0x09ec00, 0x8cccc8 }, | ||
26 | RF_CHANNEL( 2) = { 0x09ec00, 0x8cccd8 }, | ||
27 | RF_CHANNEL( 3) = { 0x09ec00, 0x8cccc0 }, | ||
28 | RF_CHANNEL( 4) = { 0x09ec00, 0x8cccd0 }, | ||
29 | RF_CHANNEL( 5) = { 0x05ec00, 0x8cccc8 }, | ||
30 | RF_CHANNEL( 6) = { 0x05ec00, 0x8cccd8 }, | ||
31 | RF_CHANNEL( 7) = { 0x05ec00, 0x8cccc0 }, | ||
32 | RF_CHANNEL( 8) = { 0x05ec00, 0x8cccd0 }, | ||
33 | RF_CHANNEL( 9) = { 0x0dec00, 0x8cccc8 }, | ||
34 | RF_CHANNEL(10) = { 0x0dec00, 0x8cccd8 }, | ||
35 | RF_CHANNEL(11) = { 0x0dec00, 0x8cccc0 }, | ||
36 | RF_CHANNEL(12) = { 0x0dec00, 0x8cccd0 }, | ||
37 | RF_CHANNEL(13) = { 0x03ec00, 0x8cccc8 }, | ||
38 | RF_CHANNEL(14) = { 0x03ec00, 0x866660 }, | ||
39 | }; | ||
40 | |||
41 | static const u32 std_rv[] = { | ||
42 | 0x4ff821, | ||
43 | 0xc5fbfc, | ||
44 | 0x21ebfe, | ||
45 | 0xafd401, /* freq shift 0xaad401 */ | ||
46 | 0x6cf56a, | ||
47 | 0xe04073, | ||
48 | 0x193d76, | ||
49 | 0x9dd844, | ||
50 | 0x500007, | ||
51 | 0xd8c010, | ||
52 | }; | ||
53 | |||
54 | static int al7230b_init_hw(struct zd_rf *rf) | ||
55 | { | ||
56 | int i, r; | ||
57 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
58 | |||
59 | /* All of these writes are identical to AL2230 unless otherwise | ||
60 | * specified */ | ||
61 | static const struct zd_ioreq16 ioreqs_1[] = { | ||
62 | /* This one is 7230-specific, and happens before the rest */ | ||
63 | { CR240, 0x57 }, | ||
64 | { }, | ||
65 | |||
66 | { CR15, 0x20 }, { CR23, 0x40 }, { CR24, 0x20 }, | ||
67 | { CR26, 0x11 }, { CR28, 0x3e }, { CR29, 0x00 }, | ||
68 | { CR44, 0x33 }, | ||
69 | /* This value is different for 7230 (was: 0x2a) */ | ||
70 | { CR106, 0x22 }, | ||
71 | { CR107, 0x1a }, { CR109, 0x09 }, { CR110, 0x27 }, | ||
72 | { CR111, 0x2b }, { CR112, 0x2b }, { CR119, 0x0a }, | ||
73 | /* This happened further down in AL2230, | ||
74 | * and the value changed (was: 0xe0) */ | ||
75 | { CR122, 0xfc }, | ||
76 | { CR10, 0x89 }, | ||
77 | /* for newest (3rd cut) AL2300 */ | ||
78 | { CR17, 0x28 }, | ||
79 | { CR26, 0x93 }, { CR34, 0x30 }, | ||
80 | /* for newest (3rd cut) AL2300 */ | ||
81 | { CR35, 0x3e }, | ||
82 | { CR41, 0x24 }, { CR44, 0x32 }, | ||
83 | /* for newest (3rd cut) AL2300 */ | ||
84 | { CR46, 0x96 }, | ||
85 | { CR47, 0x1e }, { CR79, 0x58 }, { CR80, 0x30 }, | ||
86 | { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 }, | ||
87 | { CR92, 0x0a }, { CR99, 0x28 }, | ||
88 | /* This value is different for 7230 (was: 0x00) */ | ||
89 | { CR100, 0x02 }, | ||
90 | { CR101, 0x13 }, { CR102, 0x27 }, | ||
91 | /* This value is different for 7230 (was: 0x24) */ | ||
92 | { CR106, 0x22 }, | ||
93 | /* This value is different for 7230 (was: 0x2a) */ | ||
94 | { CR107, 0x3f }, | ||
95 | { CR109, 0x09 }, | ||
96 | /* This value is different for 7230 (was: 0x13) */ | ||
97 | { CR110, 0x1f }, | ||
98 | { CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 }, | ||
99 | { CR114, 0x27 }, | ||
100 | /* for newest (3rd cut) AL2300 */ | ||
101 | { CR115, 0x24 }, | ||
102 | /* This value is different for 7230 (was: 0x24) */ | ||
103 | { CR116, 0x3f }, | ||
104 | /* This value is different for 7230 (was: 0xf4) */ | ||
105 | { CR117, 0xfa }, | ||
106 | { CR118, 0xfc }, { CR119, 0x10 }, { CR120, 0x4f }, | ||
107 | { CR121, 0x77 }, { CR137, 0x88 }, | ||
108 | /* This one is 7230-specific */ | ||
109 | { CR138, 0xa8 }, | ||
110 | /* This value is different for 7230 (was: 0xff) */ | ||
111 | { CR252, 0x34 }, | ||
112 | /* This value is different for 7230 (was: 0xff) */ | ||
113 | { CR253, 0x34 }, | ||
114 | |||
115 | /* PLL_OFF */ | ||
116 | { CR251, 0x2f }, | ||
117 | }; | ||
118 | |||
119 | static const struct zd_ioreq16 ioreqs_2[] = { | ||
120 | /* PLL_ON */ | ||
121 | { CR251, 0x3f }, | ||
122 | { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, | ||
123 | { CR38, 0x38 }, { CR136, 0xdf }, | ||
124 | }; | ||
125 | |||
126 | r = zd_iowrite16a_locked(chip, ioreqs_1, ARRAY_SIZE(ioreqs_1)); | ||
127 | if (r) | ||
128 | return r; | ||
129 | |||
130 | r = zd_rfwrite_cr_locked(chip, 0x09ec04); | ||
131 | if (r) | ||
132 | return r; | ||
133 | r = zd_rfwrite_cr_locked(chip, 0x8cccc8); | ||
134 | if (r) | ||
135 | return r; | ||
136 | |||
137 | for (i = 0; i < ARRAY_SIZE(std_rv); i++) { | ||
138 | r = zd_rfwrite_cr_locked(chip, std_rv[i]); | ||
139 | if (r) | ||
140 | return r; | ||
141 | } | ||
142 | |||
143 | r = zd_rfwrite_cr_locked(chip, 0x3c9000); | ||
144 | if (r) | ||
145 | return r; | ||
146 | r = zd_rfwrite_cr_locked(chip, 0xbfffff); | ||
147 | if (r) | ||
148 | return r; | ||
149 | r = zd_rfwrite_cr_locked(chip, 0x700000); | ||
150 | if (r) | ||
151 | return r; | ||
152 | r = zd_rfwrite_cr_locked(chip, 0xf15d58); | ||
153 | if (r) | ||
154 | return r; | ||
155 | |||
156 | r = zd_iowrite16a_locked(chip, ioreqs_2, ARRAY_SIZE(ioreqs_2)); | ||
157 | if (r) | ||
158 | return r; | ||
159 | |||
160 | r = zd_rfwrite_cr_locked(chip, 0xf15d59); | ||
161 | if (r) | ||
162 | return r; | ||
163 | r = zd_rfwrite_cr_locked(chip, 0xf15d5c); | ||
164 | if (r) | ||
165 | return r; | ||
166 | r = zd_rfwrite_cr_locked(chip, 0xf15d58); | ||
167 | if (r) | ||
168 | return r; | ||
169 | |||
170 | r = zd_iowrite16_locked(chip, 0x06, CR203); | ||
171 | if (r) | ||
172 | return r; | ||
173 | r = zd_iowrite16_locked(chip, 0x80, CR240); | ||
174 | if (r) | ||
175 | return r; | ||
176 | |||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static int al7230b_set_channel(struct zd_rf *rf, u8 channel) | ||
181 | { | ||
182 | int i, r; | ||
183 | const u32 *rv = chan_rv[channel-1]; | ||
184 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
185 | |||
186 | struct zd_ioreq16 ioreqs_1[] = { | ||
187 | { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, | ||
188 | { CR38, 0x38 }, { CR136, 0xdf }, | ||
189 | }; | ||
190 | |||
191 | struct zd_ioreq16 ioreqs_2[] = { | ||
192 | /* PLL_ON */ | ||
193 | { CR251, 0x3f }, | ||
194 | { CR203, 0x06 }, { CR240, 0x08 }, | ||
195 | }; | ||
196 | |||
197 | r = zd_iowrite16_locked(chip, 0x57, CR240); | ||
198 | if (r) | ||
199 | return r; | ||
200 | |||
201 | /* PLL_OFF */ | ||
202 | r = zd_iowrite16_locked(chip, 0x2f, CR251); | ||
203 | if (r) | ||
204 | return r; | ||
205 | |||
206 | for (i = 0; i < ARRAY_SIZE(std_rv); i++) { | ||
207 | r = zd_rfwrite_cr_locked(chip, std_rv[i]); | ||
208 | if (r) | ||
209 | return r; | ||
210 | } | ||
211 | |||
212 | r = zd_rfwrite_cr_locked(chip, 0x3c9000); | ||
213 | if (r) | ||
214 | return r; | ||
215 | r = zd_rfwrite_cr_locked(chip, 0xf15d58); | ||
216 | if (r) | ||
217 | return r; | ||
218 | |||
219 | r = zd_iowrite16a_locked(chip, ioreqs_1, ARRAY_SIZE(ioreqs_1)); | ||
220 | if (r) | ||
221 | return r; | ||
222 | |||
223 | for (i = 0; i < 2; i++) { | ||
224 | r = zd_rfwrite_cr_locked(chip, rv[i]); | ||
225 | if (r) | ||
226 | return r; | ||
227 | } | ||
228 | |||
229 | r = zd_rfwrite_cr_locked(chip, 0x3c9000); | ||
230 | if (r) | ||
231 | return r; | ||
232 | |||
233 | return zd_iowrite16a_locked(chip, ioreqs_2, ARRAY_SIZE(ioreqs_2)); | ||
234 | } | ||
235 | |||
236 | static int al7230b_switch_radio_on(struct zd_rf *rf) | ||
237 | { | ||
238 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
239 | static const struct zd_ioreq16 ioreqs[] = { | ||
240 | { CR11, 0x00 }, | ||
241 | { CR251, 0x3f }, | ||
242 | }; | ||
243 | |||
244 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
245 | } | ||
246 | |||
247 | static int al7230b_switch_radio_off(struct zd_rf *rf) | ||
248 | { | ||
249 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
250 | static const struct zd_ioreq16 ioreqs[] = { | ||
251 | { CR11, 0x04 }, | ||
252 | { CR251, 0x2f }, | ||
253 | }; | ||
254 | |||
255 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
256 | } | ||
257 | |||
258 | int zd_rf_init_al7230b(struct zd_rf *rf) | ||
259 | { | ||
260 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
261 | |||
262 | if (chip->is_zd1211b) { | ||
263 | dev_err(zd_chip_dev(chip), "AL7230B is currently not " | ||
264 | "supported for ZD1211B devices\n"); | ||
265 | return -ENODEV; | ||
266 | } | ||
267 | |||
268 | rf->init_hw = al7230b_init_hw; | ||
269 | rf->set_channel = al7230b_set_channel; | ||
270 | rf->switch_radio_on = al7230b_switch_radio_on; | ||
271 | rf->switch_radio_off = al7230b_switch_radio_off; | ||
272 | rf->patch_6m_band_edge = 1; | ||
273 | return 0; | ||
274 | } | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 96551da769fc..47489fe8ab52 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <asm/unaligned.h> | 18 | #include <asm/unaligned.h> |
19 | #include <linux/kernel.h> | ||
19 | #include <linux/init.h> | 20 | #include <linux/init.h> |
20 | #include <linux/module.h> | 21 | #include <linux/module.h> |
21 | #include <linux/firmware.h> | 22 | #include <linux/firmware.h> |
@@ -40,10 +41,16 @@ static struct usb_device_id usb_ids[] = { | |||
40 | { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 }, | 41 | { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 }, |
41 | { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 }, | 42 | { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 }, |
42 | { USB_DEVICE(0x079b, 0x004a), .driver_info = DEVICE_ZD1211 }, | 43 | { USB_DEVICE(0x079b, 0x004a), .driver_info = DEVICE_ZD1211 }, |
44 | { USB_DEVICE(0x1740, 0x2000), .driver_info = DEVICE_ZD1211 }, | ||
45 | { USB_DEVICE(0x157e, 0x3204), .driver_info = DEVICE_ZD1211 }, | ||
46 | { USB_DEVICE(0x0586, 0x3402), .driver_info = DEVICE_ZD1211 }, | ||
43 | /* ZD1211B */ | 47 | /* ZD1211B */ |
44 | { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, | 48 | { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, |
45 | { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, | 49 | { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, |
46 | { USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B }, | 50 | { USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B }, |
51 | { USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B }, | ||
52 | /* "Driverless" devices that need ejecting */ | ||
53 | { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, | ||
47 | {} | 54 | {} |
48 | }; | 55 | }; |
49 | 56 | ||
@@ -265,6 +272,39 @@ static char *get_fw_name(char *buffer, size_t size, u8 device_type, | |||
265 | return buffer; | 272 | return buffer; |
266 | } | 273 | } |
267 | 274 | ||
275 | static int handle_version_mismatch(struct usb_device *udev, u8 device_type, | ||
276 | const struct firmware *ub_fw) | ||
277 | { | ||
278 | const struct firmware *ur_fw = NULL; | ||
279 | int offset; | ||
280 | int r = 0; | ||
281 | char fw_name[128]; | ||
282 | |||
283 | r = request_fw_file(&ur_fw, | ||
284 | get_fw_name(fw_name, sizeof(fw_name), device_type, "ur"), | ||
285 | &udev->dev); | ||
286 | if (r) | ||
287 | goto error; | ||
288 | |||
289 | r = upload_code(udev, ur_fw->data, ur_fw->size, FW_START_OFFSET, | ||
290 | REBOOT); | ||
291 | if (r) | ||
292 | goto error; | ||
293 | |||
294 | offset = ((EEPROM_REGS_OFFSET + EEPROM_REGS_SIZE) * sizeof(u16)); | ||
295 | r = upload_code(udev, ub_fw->data + offset, ub_fw->size - offset, | ||
296 | E2P_BASE_OFFSET + EEPROM_REGS_SIZE, REBOOT); | ||
297 | |||
298 | /* At this point, the vendor driver downloads the whole firmware | ||
299 | * image, hacks around with version IDs, and uploads it again, | ||
300 | * completely overwriting the boot code. We do not do this here as | ||
301 | * it is not required on any tested devices, and it is suspected to | ||
302 | * cause problems. */ | ||
303 | error: | ||
304 | release_firmware(ur_fw); | ||
305 | return r; | ||
306 | } | ||
307 | |||
268 | static int upload_firmware(struct usb_device *udev, u8 device_type) | 308 | static int upload_firmware(struct usb_device *udev, u8 device_type) |
269 | { | 309 | { |
270 | int r; | 310 | int r; |
@@ -284,15 +324,17 @@ static int upload_firmware(struct usb_device *udev, u8 device_type) | |||
284 | 324 | ||
285 | fw_bcdDevice = get_word(ub_fw->data, EEPROM_REGS_OFFSET); | 325 | fw_bcdDevice = get_word(ub_fw->data, EEPROM_REGS_OFFSET); |
286 | 326 | ||
287 | /* FIXME: do we have any reason to perform the kludge that the vendor | ||
288 | * driver does when there is a version mismatch? (their driver uploads | ||
289 | * different firmwares and stuff) | ||
290 | */ | ||
291 | if (fw_bcdDevice != bcdDevice) { | 327 | if (fw_bcdDevice != bcdDevice) { |
292 | dev_info(&udev->dev, | 328 | dev_info(&udev->dev, |
293 | "firmware device id %#06x and actual device id " | 329 | "firmware version %#06x and device bootcode version " |
294 | "%#06x differ, continuing anyway\n", | 330 | "%#06x differ\n", fw_bcdDevice, bcdDevice); |
295 | fw_bcdDevice, bcdDevice); | 331 | if (bcdDevice <= 0x4313) |
332 | dev_warn(&udev->dev, "device has old bootcode, please " | ||
333 | "report success or failure\n"); | ||
334 | |||
335 | r = handle_version_mismatch(udev, device_type, ub_fw); | ||
336 | if (r) | ||
337 | goto error; | ||
296 | } else { | 338 | } else { |
297 | dev_dbg_f(&udev->dev, | 339 | dev_dbg_f(&udev->dev, |
298 | "firmware device id %#06x is equal to the " | 340 | "firmware device id %#06x is equal to the " |
@@ -622,7 +664,7 @@ resubmit: | |||
622 | usb_submit_urb(urb, GFP_ATOMIC); | 664 | usb_submit_urb(urb, GFP_ATOMIC); |
623 | } | 665 | } |
624 | 666 | ||
625 | struct urb *alloc_urb(struct zd_usb *usb) | 667 | static struct urb *alloc_urb(struct zd_usb *usb) |
626 | { | 668 | { |
627 | struct usb_device *udev = zd_usb_to_usbdev(usb); | 669 | struct usb_device *udev = zd_usb_to_usbdev(usb); |
628 | struct urb *urb; | 670 | struct urb *urb; |
@@ -646,7 +688,7 @@ struct urb *alloc_urb(struct zd_usb *usb) | |||
646 | return urb; | 688 | return urb; |
647 | } | 689 | } |
648 | 690 | ||
649 | void free_urb(struct urb *urb) | 691 | static void free_urb(struct urb *urb) |
650 | { | 692 | { |
651 | if (!urb) | 693 | if (!urb) |
652 | return; | 694 | return; |
@@ -866,7 +908,7 @@ void zd_usb_clear(struct zd_usb *usb) | |||
866 | { | 908 | { |
867 | usb_set_intfdata(usb->intf, NULL); | 909 | usb_set_intfdata(usb->intf, NULL); |
868 | usb_put_intf(usb->intf); | 910 | usb_put_intf(usb->intf); |
869 | memset(usb, 0, sizeof(*usb)); | 911 | ZD_MEMCLEAR(usb, sizeof(*usb)); |
870 | /* FIXME: usb_interrupt, usb_tx, usb_rx? */ | 912 | /* FIXME: usb_interrupt, usb_tx, usb_rx? */ |
871 | } | 913 | } |
872 | 914 | ||
@@ -912,6 +954,55 @@ static void print_id(struct usb_device *udev) | |||
912 | #define print_id(udev) do { } while (0) | 954 | #define print_id(udev) do { } while (0) |
913 | #endif | 955 | #endif |
914 | 956 | ||
957 | static int eject_installer(struct usb_interface *intf) | ||
958 | { | ||
959 | struct usb_device *udev = interface_to_usbdev(intf); | ||
960 | struct usb_host_interface *iface_desc = &intf->altsetting[0]; | ||
961 | struct usb_endpoint_descriptor *endpoint; | ||
962 | unsigned char *cmd; | ||
963 | u8 bulk_out_ep; | ||
964 | int r; | ||
965 | |||
966 | /* Find bulk out endpoint */ | ||
967 | endpoint = &iface_desc->endpoint[1].desc; | ||
968 | if ((endpoint->bEndpointAddress & USB_TYPE_MASK) == USB_DIR_OUT && | ||
969 | (endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == | ||
970 | USB_ENDPOINT_XFER_BULK) { | ||
971 | bulk_out_ep = endpoint->bEndpointAddress; | ||
972 | } else { | ||
973 | dev_err(&udev->dev, | ||
974 | "zd1211rw: Could not find bulk out endpoint\n"); | ||
975 | return -ENODEV; | ||
976 | } | ||
977 | |||
978 | cmd = kzalloc(31, GFP_KERNEL); | ||
979 | if (cmd == NULL) | ||
980 | return -ENODEV; | ||
981 | |||
982 | /* USB bulk command block */ | ||
983 | cmd[0] = 0x55; /* bulk command signature */ | ||
984 | cmd[1] = 0x53; /* bulk command signature */ | ||
985 | cmd[2] = 0x42; /* bulk command signature */ | ||
986 | cmd[3] = 0x43; /* bulk command signature */ | ||
987 | cmd[14] = 6; /* command length */ | ||
988 | |||
989 | cmd[15] = 0x1b; /* SCSI command: START STOP UNIT */ | ||
990 | cmd[19] = 0x2; /* eject disc */ | ||
991 | |||
992 | dev_info(&udev->dev, "Ejecting virtual installer media...\n"); | ||
993 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, bulk_out_ep), | ||
994 | cmd, 31, NULL, 2000); | ||
995 | kfree(cmd); | ||
996 | if (r) | ||
997 | return r; | ||
998 | |||
999 | /* At this point, the device disconnects and reconnects with the real | ||
1000 | * ID numbers. */ | ||
1001 | |||
1002 | usb_set_intfdata(intf, NULL); | ||
1003 | return 0; | ||
1004 | } | ||
1005 | |||
915 | static int probe(struct usb_interface *intf, const struct usb_device_id *id) | 1006 | static int probe(struct usb_interface *intf, const struct usb_device_id *id) |
916 | { | 1007 | { |
917 | int r; | 1008 | int r; |
@@ -920,6 +1011,9 @@ static int probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
920 | 1011 | ||
921 | print_id(udev); | 1012 | print_id(udev); |
922 | 1013 | ||
1014 | if (id->driver_info & DEVICE_INSTALLER) | ||
1015 | return eject_installer(intf); | ||
1016 | |||
923 | switch (udev->speed) { | 1017 | switch (udev->speed) { |
924 | case USB_SPEED_LOW: | 1018 | case USB_SPEED_LOW: |
925 | case USB_SPEED_FULL: | 1019 | case USB_SPEED_FULL: |
@@ -985,6 +1079,11 @@ static void disconnect(struct usb_interface *intf) | |||
985 | struct zd_mac *mac = zd_netdev_mac(netdev); | 1079 | struct zd_mac *mac = zd_netdev_mac(netdev); |
986 | struct zd_usb *usb = &mac->chip.usb; | 1080 | struct zd_usb *usb = &mac->chip.usb; |
987 | 1081 | ||
1082 | /* Either something really bad happened, or we're just dealing with | ||
1083 | * a DEVICE_INSTALLER. */ | ||
1084 | if (netdev == NULL) | ||
1085 | return; | ||
1086 | |||
988 | dev_dbg_f(zd_usb_dev(usb), "\n"); | 1087 | dev_dbg_f(zd_usb_dev(usb), "\n"); |
989 | 1088 | ||
990 | zd_netdev_disconnect(netdev); | 1089 | zd_netdev_disconnect(netdev); |
@@ -1000,7 +1099,6 @@ static void disconnect(struct usb_interface *intf) | |||
1000 | */ | 1099 | */ |
1001 | usb_reset_device(interface_to_usbdev(intf)); | 1100 | usb_reset_device(interface_to_usbdev(intf)); |
1002 | 1101 | ||
1003 | /* If somebody still waits on this lock now, this is an error. */ | ||
1004 | zd_netdev_free(netdev); | 1102 | zd_netdev_free(netdev); |
1005 | dev_dbg(&intf->dev, "disconnected\n"); | 1103 | dev_dbg(&intf->dev, "disconnected\n"); |
1006 | } | 1104 | } |
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h index d6420283bd5a..92746f76239a 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.h +++ b/drivers/net/wireless/zd1211rw/zd_usb.h | |||
@@ -30,6 +30,7 @@ | |||
30 | enum devicetype { | 30 | enum devicetype { |
31 | DEVICE_ZD1211 = 0, | 31 | DEVICE_ZD1211 = 0, |
32 | DEVICE_ZD1211B = 1, | 32 | DEVICE_ZD1211B = 1, |
33 | DEVICE_INSTALLER = 2, | ||
33 | }; | 34 | }; |
34 | 35 | ||
35 | enum endpoints { | 36 | enum endpoints { |