* the access attempt is considered to have failed,
* and we will print an error.
*/
-static u32 rt2400pci_bbp_check(struct rt2x00_dev *rt2x00dev)
-{
- u32 reg;
- unsigned int i;
-
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, BBPCSR, ®);
- if (!rt2x00_get_field32(reg, BBPCSR_BUSY))
- break;
- udelay(REGISTER_BUSY_DELAY);
- }
-
- return reg;
-}
+#define WAIT_FOR_BBP(__dev, __reg) \
+ rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))
+#define WAIT_FOR_RF(__dev, __reg) \
+ rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))
static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
mutex_lock(&rt2x00dev->csr_mutex);
/*
- * Wait until the BBP becomes ready.
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the new data into the register.
*/
- reg = rt2400pci_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, BBPCSR_BUSY))
- goto exit_fail;
-
- /*
- * Write the data into the BBP.
- */
- reg = 0;
- rt2x00_set_field32(®, BBPCSR_VALUE, value);
- rt2x00_set_field32(®, BBPCSR_REGNUM, word);
- rt2x00_set_field32(®, BBPCSR_BUSY, 1);
- rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1);
-
- rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
-
- mutex_unlock(&rt2x00dev->csr_mutex);
-
- return;
+ if (WAIT_FOR_BBP(rt2x00dev, ®)) {
+ reg = 0;
+ rt2x00_set_field32(®, BBPCSR_VALUE, value);
+ rt2x00_set_field32(®, BBPCSR_REGNUM, word);
+ rt2x00_set_field32(®, BBPCSR_BUSY, 1);
+ rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1);
+
+ rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
+ }
-exit_fail:
mutex_unlock(&rt2x00dev->csr_mutex);
-
- ERROR(rt2x00dev, "BBPCSR register busy. Write failed.\n");
}
static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev,
mutex_lock(&rt2x00dev->csr_mutex);
/*
- * Wait until the BBP becomes ready.
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the read request into the register.
+ * After the data has been written, we wait until hardware
+ * returns the correct value, if at any time the register
+ * doesn't become available in time, reg will be 0xffffffff
+ * which means we return 0xff to the caller.
*/
- reg = rt2400pci_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, BBPCSR_BUSY))
- goto exit_fail;
+ if (WAIT_FOR_BBP(rt2x00dev, ®)) {
+ reg = 0;
+ rt2x00_set_field32(®, BBPCSR_REGNUM, word);
+ rt2x00_set_field32(®, BBPCSR_BUSY, 1);
+ rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0);
- /*
- * Write the request into the BBP.
- */
- reg = 0;
- rt2x00_set_field32(®, BBPCSR_REGNUM, word);
- rt2x00_set_field32(®, BBPCSR_BUSY, 1);
- rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0);
+ rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
- rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
-
- /*
- * Wait until the BBP becomes ready.
- */
- reg = rt2400pci_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, BBPCSR_BUSY))
- goto exit_fail;
+ WAIT_FOR_BBP(rt2x00dev, ®);
+ }
*value = rt2x00_get_field32(reg, BBPCSR_VALUE);
mutex_unlock(&rt2x00dev->csr_mutex);
-
- return;
-
-exit_fail:
- mutex_unlock(&rt2x00dev->csr_mutex);
-
- ERROR(rt2x00dev, "BBPCSR register busy. Read failed.\n");
- *value = 0xff;
}
static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u32 value)
{
u32 reg;
- unsigned int i;
if (!word)
return;
mutex_lock(&rt2x00dev->csr_mutex);
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, RFCSR, ®);
- if (!rt2x00_get_field32(reg, RFCSR_BUSY))
- goto rf_write;
- udelay(REGISTER_BUSY_DELAY);
+ /*
+ * Wait until the RF becomes available, afterwards we
+ * can safely write the new data into the register.
+ */
+ if (WAIT_FOR_RF(rt2x00dev, ®)) {
+ reg = 0;
+ rt2x00_set_field32(®, RFCSR_VALUE, value);
+ rt2x00_set_field32(®, RFCSR_NUMBER_OF_BITS, 20);
+ rt2x00_set_field32(®, RFCSR_IF_SELECT, 0);
+ rt2x00_set_field32(®, RFCSR_BUSY, 1);
+
+ rt2x00pci_register_write(rt2x00dev, RFCSR, reg);
+ rt2x00_rf_write(rt2x00dev, word, value);
}
- mutex_unlock(&rt2x00dev->csr_mutex);
- ERROR(rt2x00dev, "RFCSR register busy. Write failed.\n");
- return;
-
-rf_write:
- reg = 0;
- rt2x00_set_field32(®, RFCSR_VALUE, value);
- rt2x00_set_field32(®, RFCSR_NUMBER_OF_BITS, 20);
- rt2x00_set_field32(®, RFCSR_IF_SELECT, 0);
- rt2x00_set_field32(®, RFCSR_BUSY, 1);
-
- rt2x00pci_register_write(rt2x00dev, RFCSR, reg);
- rt2x00_rf_write(rt2x00dev, word, value);
-
mutex_unlock(&rt2x00dev->csr_mutex);
}
* the access attempt is considered to have failed,
* and we will print an error.
*/
-static u32 rt2500pci_bbp_check(struct rt2x00_dev *rt2x00dev)
-{
- u32 reg;
- unsigned int i;
-
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, BBPCSR, ®);
- if (!rt2x00_get_field32(reg, BBPCSR_BUSY))
- break;
- udelay(REGISTER_BUSY_DELAY);
- }
-
- return reg;
-}
+#define WAIT_FOR_BBP(__dev, __reg) \
+ rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))
+#define WAIT_FOR_RF(__dev, __reg) \
+ rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))
static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
mutex_lock(&rt2x00dev->csr_mutex);
/*
- * Wait until the BBP becomes ready.
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the new data into the register.
*/
- reg = rt2500pci_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, BBPCSR_BUSY))
- goto exit_fail;
-
- /*
- * Write the data into the BBP.
- */
- reg = 0;
- rt2x00_set_field32(®, BBPCSR_VALUE, value);
- rt2x00_set_field32(®, BBPCSR_REGNUM, word);
- rt2x00_set_field32(®, BBPCSR_BUSY, 1);
- rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1);
-
- rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
-
- mutex_unlock(&rt2x00dev->csr_mutex);
-
- return;
+ if (WAIT_FOR_BBP(rt2x00dev, ®)) {
+ reg = 0;
+ rt2x00_set_field32(®, BBPCSR_VALUE, value);
+ rt2x00_set_field32(®, BBPCSR_REGNUM, word);
+ rt2x00_set_field32(®, BBPCSR_BUSY, 1);
+ rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1);
+
+ rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
+ }
-exit_fail:
mutex_unlock(&rt2x00dev->csr_mutex);
-
- ERROR(rt2x00dev, "BBPCSR register busy. Write failed.\n");
}
static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev,
mutex_lock(&rt2x00dev->csr_mutex);
/*
- * Wait until the BBP becomes ready.
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the read request into the register.
+ * After the data has been written, we wait until hardware
+ * returns the correct value, if at any time the register
+ * doesn't become available in time, reg will be 0xffffffff
+ * which means we return 0xff to the caller.
*/
- reg = rt2500pci_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, BBPCSR_BUSY))
- goto exit_fail;
+ if (WAIT_FOR_BBP(rt2x00dev, ®)) {
+ reg = 0;
+ rt2x00_set_field32(®, BBPCSR_REGNUM, word);
+ rt2x00_set_field32(®, BBPCSR_BUSY, 1);
+ rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0);
- /*
- * Write the request into the BBP.
- */
- reg = 0;
- rt2x00_set_field32(®, BBPCSR_REGNUM, word);
- rt2x00_set_field32(®, BBPCSR_BUSY, 1);
- rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0);
+ rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
- rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
-
- /*
- * Wait until the BBP becomes ready.
- */
- reg = rt2500pci_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, BBPCSR_BUSY))
- goto exit_fail;
+ WAIT_FOR_BBP(rt2x00dev, ®);
+ }
*value = rt2x00_get_field32(reg, BBPCSR_VALUE);
mutex_unlock(&rt2x00dev->csr_mutex);
-
- return;
-
-exit_fail:
- mutex_unlock(&rt2x00dev->csr_mutex);
-
- ERROR(rt2x00dev, "BBPCSR register busy. Read failed.\n");
- *value = 0xff;
}
static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u32 value)
{
u32 reg;
- unsigned int i;
if (!word)
return;
mutex_lock(&rt2x00dev->csr_mutex);
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, RFCSR, ®);
- if (!rt2x00_get_field32(reg, RFCSR_BUSY))
- goto rf_write;
- udelay(REGISTER_BUSY_DELAY);
+ /*
+ * Wait until the RF becomes available, afterwards we
+ * can safely write the new data into the register.
+ */
+ if (WAIT_FOR_RF(rt2x00dev, ®)) {
+ reg = 0;
+ rt2x00_set_field32(®, RFCSR_VALUE, value);
+ rt2x00_set_field32(®, RFCSR_NUMBER_OF_BITS, 20);
+ rt2x00_set_field32(®, RFCSR_IF_SELECT, 0);
+ rt2x00_set_field32(®, RFCSR_BUSY, 1);
+
+ rt2x00pci_register_write(rt2x00dev, RFCSR, reg);
+ rt2x00_rf_write(rt2x00dev, word, value);
}
- mutex_unlock(&rt2x00dev->csr_mutex);
- ERROR(rt2x00dev, "RFCSR register busy. Write failed.\n");
- return;
-
-rf_write:
- reg = 0;
- rt2x00_set_field32(®, RFCSR_VALUE, value);
- rt2x00_set_field32(®, RFCSR_NUMBER_OF_BITS, 20);
- rt2x00_set_field32(®, RFCSR_IF_SELECT, 0);
- rt2x00_set_field32(®, RFCSR_BUSY, 1);
-
- rt2x00pci_register_write(rt2x00dev, RFCSR, reg);
- rt2x00_rf_write(rt2x00dev, word, value);
-
mutex_unlock(&rt2x00dev->csr_mutex);
}
__le16 reg;
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
USB_VENDOR_REQUEST_IN, offset,
- ®, sizeof(u16), REGISTER_TIMEOUT);
+ ®, sizeof(reg), REGISTER_TIMEOUT);
*value = le16_to_cpu(reg);
}
__le16 reg;
rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
USB_VENDOR_REQUEST_IN, offset,
- ®, sizeof(u16), REGISTER_TIMEOUT);
+ ®, sizeof(reg), REGISTER_TIMEOUT);
*value = le16_to_cpu(reg);
}
__le16 reg = cpu_to_le16(value);
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
USB_VENDOR_REQUEST_OUT, offset,
- ®, sizeof(u16), REGISTER_TIMEOUT);
+ ®, sizeof(reg), REGISTER_TIMEOUT);
}
static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
__le16 reg = cpu_to_le16(value);
rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
USB_VENDOR_REQUEST_OUT, offset,
- ®, sizeof(u16), REGISTER_TIMEOUT);
+ ®, sizeof(reg), REGISTER_TIMEOUT);
}
static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
REGISTER_TIMEOUT16(length));
}
-static u16 rt2500usb_bbp_check(struct rt2x00_dev *rt2x00dev)
+static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ struct rt2x00_field16 field,
+ u16 *reg)
{
- u16 reg;
unsigned int i;
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2500usb_register_read_lock(rt2x00dev, PHY_CSR8, ®);
- if (!rt2x00_get_field16(reg, PHY_CSR8_BUSY))
- break;
+ rt2500usb_register_read_lock(rt2x00dev, offset, reg);
+ if (!rt2x00_get_field16(*reg, field))
+ return 1;
udelay(REGISTER_BUSY_DELAY);
}
- return reg;
+ ERROR(rt2x00dev, "Indirect register access failed: "
+ "offset=0x%.08x, value=0x%.08x\n", offset, *reg);
+ *reg = ~0;
+
+ return 0;
}
+#define WAIT_FOR_BBP(__dev, __reg) \
+ rt2500usb_regbusy_read((__dev), PHY_CSR8, PHY_CSR8_BUSY, (__reg))
+#define WAIT_FOR_RF(__dev, __reg) \
+ rt2500usb_regbusy_read((__dev), PHY_CSR10, PHY_CSR10_RF_BUSY, (__reg))
+
static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
{
mutex_lock(&rt2x00dev->csr_mutex);
/*
- * Wait until the BBP becomes ready.
- */
- reg = rt2500usb_bbp_check(rt2x00dev);
- if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
- goto exit_fail;
-
- /*
- * Write the data into the BBP.
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the new data into the register.
*/
- reg = 0;
- rt2x00_set_field16(®, PHY_CSR7_DATA, value);
- rt2x00_set_field16(®, PHY_CSR7_REG_ID, word);
- rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 0);
-
- rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
-
- mutex_unlock(&rt2x00dev->csr_mutex);
+ if (WAIT_FOR_BBP(rt2x00dev, ®)) {
+ reg = 0;
+ rt2x00_set_field16(®, PHY_CSR7_DATA, value);
+ rt2x00_set_field16(®, PHY_CSR7_REG_ID, word);
+ rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 0);
- return;
+ rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
+ }
-exit_fail:
mutex_unlock(&rt2x00dev->csr_mutex);
-
- ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n");
}
static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
mutex_lock(&rt2x00dev->csr_mutex);
/*
- * Wait until the BBP becomes ready.
- */
- reg = rt2500usb_bbp_check(rt2x00dev);
- if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
- goto exit_fail;
-
- /*
- * Write the request into the BBP.
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the read request into the register.
+ * After the data has been written, we wait until hardware
+ * returns the correct value, if at any time the register
+ * doesn't become available in time, reg will be 0xffffffff
+ * which means we return 0xff to the caller.
*/
- reg = 0;
- rt2x00_set_field16(®, PHY_CSR7_REG_ID, word);
- rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 1);
+ if (WAIT_FOR_BBP(rt2x00dev, ®)) {
+ reg = 0;
+ rt2x00_set_field16(®, PHY_CSR7_REG_ID, word);
+ rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 1);
- rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
+ rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
- /*
- * Wait until the BBP becomes ready.
- */
- reg = rt2500usb_bbp_check(rt2x00dev);
- if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
- goto exit_fail;
+ if (WAIT_FOR_BBP(rt2x00dev, ®))
+ rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®);
+ }
- rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®);
*value = rt2x00_get_field16(reg, PHY_CSR7_DATA);
mutex_unlock(&rt2x00dev->csr_mutex);
-
- return;
-
-exit_fail:
- mutex_unlock(&rt2x00dev->csr_mutex);
-
- ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n");
- *value = 0xff;
}
static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u32 value)
{
u16 reg;
- unsigned int i;
if (!word)
return;
mutex_lock(&rt2x00dev->csr_mutex);
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2500usb_register_read_lock(rt2x00dev, PHY_CSR10, ®);
- if (!rt2x00_get_field16(reg, PHY_CSR10_RF_BUSY))
- goto rf_write;
- udelay(REGISTER_BUSY_DELAY);
- }
-
- mutex_unlock(&rt2x00dev->csr_mutex);
- ERROR(rt2x00dev, "PHY_CSR10 register busy. Write failed.\n");
- return;
-
-rf_write:
- reg = 0;
- rt2x00_set_field16(®, PHY_CSR9_RF_VALUE, value);
- rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg);
+ /*
+ * Wait until the RF becomes available, afterwards we
+ * can safely write the new data into the register.
+ */
+ if (WAIT_FOR_RF(rt2x00dev, ®)) {
+ reg = 0;
+ rt2x00_set_field16(®, PHY_CSR9_RF_VALUE, value);
+ rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg);
- reg = 0;
- rt2x00_set_field16(®, PHY_CSR10_RF_VALUE, value >> 16);
- rt2x00_set_field16(®, PHY_CSR10_RF_NUMBER_OF_BITS, 20);
- rt2x00_set_field16(®, PHY_CSR10_RF_IF_SELECT, 0);
- rt2x00_set_field16(®, PHY_CSR10_RF_BUSY, 1);
+ reg = 0;
+ rt2x00_set_field16(®, PHY_CSR10_RF_VALUE, value >> 16);
+ rt2x00_set_field16(®, PHY_CSR10_RF_NUMBER_OF_BITS, 20);
+ rt2x00_set_field16(®, PHY_CSR10_RF_IF_SELECT, 0);
+ rt2x00_set_field16(®, PHY_CSR10_RF_BUSY, 1);
- rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg);
- rt2x00_rf_write(rt2x00dev, word, value);
+ rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg);
+ rt2x00_rf_write(rt2x00dev, word, value);
+ }
mutex_unlock(&rt2x00dev->csr_mutex);
}
#include "rt2x00.h"
#include "rt2x00pci.h"
+/*
+ * Register access.
+ */
+int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ const struct rt2x00_field32 field,
+ u32 *reg)
+{
+ unsigned int i;
+
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+ rt2x00pci_register_read(rt2x00dev, offset, reg);
+ if (!rt2x00_get_field32(*reg, field))
+ return 1;
+ udelay(REGISTER_BUSY_DELAY);
+ }
+
+ ERROR(rt2x00dev, "Indirect register access failed: "
+ "offset=0x%.08x, value=0x%.08x\n", offset, *reg);
+ *reg = ~0;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read);
+
/*
* TX data handlers.
*/
memcpy_toio(rt2x00dev->csr.base + offset, value, length);
}
+/**
+ * rt2x00pci_regbusy_read - Read from register with busy check
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @field: Field to check if register is busy
+ * @reg: Pointer to where register contents should be stored
+ *
+ * This function will read the given register, and checks if the
+ * register is busy. If it is, it will sleep for a couple of
+ * microseconds before reading the register again. If the register
+ * is not read after a certain timeout, this function will return
+ * FALSE.
+ */
+int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ const struct rt2x00_field32 field,
+ u32 *reg);
+
/**
* rt2x00pci_write_tx_data - Initialize data for TX operation
* @entry: The entry where the frame is located
* the access attempt is considered to have failed,
* and we will print an error.
*/
-static u32 rt61pci_bbp_check(struct rt2x00_dev *rt2x00dev)
-{
- u32 reg;
- unsigned int i;
-
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, PHY_CSR3, ®);
- if (!rt2x00_get_field32(reg, PHY_CSR3_BUSY))
- break;
- udelay(REGISTER_BUSY_DELAY);
- }
-
- return reg;
-}
+#define WAIT_FOR_BBP(__dev, __reg) \
+ rt2x00pci_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg))
+#define WAIT_FOR_RF(__dev, __reg) \
+ rt2x00pci_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg))
+#define WAIT_FOR_MCU(__dev, __reg) \
+ rt2x00pci_regbusy_read((__dev), H2M_MAILBOX_CSR, \
+ H2M_MAILBOX_CSR_OWNER, (__reg))
static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
mutex_lock(&rt2x00dev->csr_mutex);
/*
- * Wait until the BBP becomes ready.
- */
- reg = rt61pci_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
- goto exit_fail;
-
- /*
- * Write the data into the BBP.
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the new data into the register.
*/
- reg = 0;
- rt2x00_set_field32(®, PHY_CSR3_VALUE, value);
- rt2x00_set_field32(®, PHY_CSR3_REGNUM, word);
- rt2x00_set_field32(®, PHY_CSR3_BUSY, 1);
- rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0);
-
- rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg);
- mutex_unlock(&rt2x00dev->csr_mutex);
+ if (WAIT_FOR_BBP(rt2x00dev, ®)) {
+ reg = 0;
+ rt2x00_set_field32(®, PHY_CSR3_VALUE, value);
+ rt2x00_set_field32(®, PHY_CSR3_REGNUM, word);
+ rt2x00_set_field32(®, PHY_CSR3_BUSY, 1);
+ rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0);
- return;
+ rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg);
+ }
-exit_fail:
mutex_unlock(&rt2x00dev->csr_mutex);
-
- ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n");
}
static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev,
mutex_lock(&rt2x00dev->csr_mutex);
/*
- * Wait until the BBP becomes ready.
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the read request into the register.
+ * After the data has been written, we wait until hardware
+ * returns the correct value, if at any time the register
+ * doesn't become available in time, reg will be 0xffffffff
+ * which means we return 0xff to the caller.
*/
- reg = rt61pci_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
- goto exit_fail;
+ if (WAIT_FOR_BBP(rt2x00dev, ®)) {
+ reg = 0;
+ rt2x00_set_field32(®, PHY_CSR3_REGNUM, word);
+ rt2x00_set_field32(®, PHY_CSR3_BUSY, 1);
+ rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1);
- /*
- * Write the request into the BBP.
- */
- reg = 0;
- rt2x00_set_field32(®, PHY_CSR3_REGNUM, word);
- rt2x00_set_field32(®, PHY_CSR3_BUSY, 1);
- rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1);
+ rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg);
- rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg);
-
- /*
- * Wait until the BBP becomes ready.
- */
- reg = rt61pci_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
- goto exit_fail;
+ WAIT_FOR_BBP(rt2x00dev, ®);
+ }
*value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
- mutex_unlock(&rt2x00dev->csr_mutex);
-
- return;
-exit_fail:
mutex_unlock(&rt2x00dev->csr_mutex);
-
- ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
- *value = 0xff;
}
static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u32 value)
{
u32 reg;
- unsigned int i;
if (!word)
return;
mutex_lock(&rt2x00dev->csr_mutex);
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, PHY_CSR4, ®);
- if (!rt2x00_get_field32(reg, PHY_CSR4_BUSY))
- goto rf_write;
- udelay(REGISTER_BUSY_DELAY);
- }
-
- mutex_unlock(&rt2x00dev->csr_mutex);
- ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n");
- return;
-
-rf_write:
- reg = 0;
- rt2x00_set_field32(®, PHY_CSR4_VALUE, value);
- rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, 21);
- rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0);
- rt2x00_set_field32(®, PHY_CSR4_BUSY, 1);
+ /*
+ * Wait until the RF becomes available, afterwards we
+ * can safely write the new data into the register.
+ */
+ if (WAIT_FOR_RF(rt2x00dev, ®)) {
+ reg = 0;
+ rt2x00_set_field32(®, PHY_CSR4_VALUE, value);
+ rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, 21);
+ rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0);
+ rt2x00_set_field32(®, PHY_CSR4_BUSY, 1);
- rt2x00pci_register_write(rt2x00dev, PHY_CSR4, reg);
- rt2x00_rf_write(rt2x00dev, word, value);
+ rt2x00pci_register_write(rt2x00dev, PHY_CSR4, reg);
+ rt2x00_rf_write(rt2x00dev, word, value);
+ }
mutex_unlock(&rt2x00dev->csr_mutex);
}
mutex_lock(&rt2x00dev->csr_mutex);
- rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CSR, ®);
-
- if (rt2x00_get_field32(reg, H2M_MAILBOX_CSR_OWNER))
- goto exit_fail;
-
- rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1);
- rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token);
- rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0);
- rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1);
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg);
-
- rt2x00pci_register_read(rt2x00dev, HOST_CMD_CSR, ®);
- rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command);
- rt2x00_set_field32(®, HOST_CMD_CSR_INTERRUPT_MCU, 1);
- rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg);
-
- mutex_unlock(&rt2x00dev->csr_mutex);
+ /*
+ * Wait until the MCU becomes available, afterwards we
+ * can safely write the new data into the register.
+ */
+ if (WAIT_FOR_MCU(rt2x00dev, ®)) {
+ rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1);
+ rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token);
+ rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0);
+ rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1);
+ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg);
- return;
+ rt2x00pci_register_read(rt2x00dev, HOST_CMD_CSR, ®);
+ rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command);
+ rt2x00_set_field32(®, HOST_CMD_CSR_INTERRUPT_MCU, 1);
+ rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg);
+ }
-exit_fail:
mutex_unlock(&rt2x00dev->csr_mutex);
- ERROR(rt2x00dev,
- "mcu request error. Request 0x%02x failed for token 0x%02x.\n",
- command, token);
}
#endif /* CONFIG_RT2X00_LIB_LEDS */
__le32 reg;
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
USB_VENDOR_REQUEST_IN, offset,
- ®, sizeof(u32), REGISTER_TIMEOUT);
+ ®, sizeof(reg), REGISTER_TIMEOUT);
*value = le32_to_cpu(reg);
}
__le32 reg;
rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
USB_VENDOR_REQUEST_IN, offset,
- ®, sizeof(u32), REGISTER_TIMEOUT);
+ ®, sizeof(reg), REGISTER_TIMEOUT);
*value = le32_to_cpu(reg);
}
__le32 reg = cpu_to_le32(value);
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
USB_VENDOR_REQUEST_OUT, offset,
- ®, sizeof(u32), REGISTER_TIMEOUT);
+ ®, sizeof(reg), REGISTER_TIMEOUT);
}
static inline void rt73usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
__le32 reg = cpu_to_le32(value);
rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
USB_VENDOR_REQUEST_OUT, offset,
- ®, sizeof(u32), REGISTER_TIMEOUT);
+ ®, sizeof(reg), REGISTER_TIMEOUT);
}
static inline void rt73usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
REGISTER_TIMEOUT32(length));
}
-static u32 rt73usb_bbp_check(struct rt2x00_dev *rt2x00dev)
+static int rt73usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ struct rt2x00_field32 field,
+ u32 *reg)
{
- u32 reg;
unsigned int i;
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt73usb_register_read_lock(rt2x00dev, PHY_CSR3, ®);
- if (!rt2x00_get_field32(reg, PHY_CSR3_BUSY))
- break;
+ rt73usb_register_read_lock(rt2x00dev, offset, reg);
+ if (!rt2x00_get_field32(*reg, field))
+ return 1;
udelay(REGISTER_BUSY_DELAY);
}
- return reg;
+ ERROR(rt2x00dev, "Indirect register access failed: "
+ "offset=0x%.08x, value=0x%.08x\n", offset, *reg);
+ *reg = ~0;
+
+ return 0;
}
+#define WAIT_FOR_BBP(__dev, __reg) \
+ rt73usb_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg))
+#define WAIT_FOR_RF(__dev, __reg) \
+ rt73usb_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg))
+
static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
{
mutex_lock(&rt2x00dev->csr_mutex);
/*
- * Wait until the BBP becomes ready.
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the new data into the register.
*/
- reg = rt73usb_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
- goto exit_fail;
-
- /*
- * Write the data into the BBP.
- */
- reg = 0;
- rt2x00_set_field32(®, PHY_CSR3_VALUE, value);
- rt2x00_set_field32(®, PHY_CSR3_REGNUM, word);
- rt2x00_set_field32(®, PHY_CSR3_BUSY, 1);
- rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0);
-
- rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
- mutex_unlock(&rt2x00dev->csr_mutex);
-
- return;
+ if (WAIT_FOR_BBP(rt2x00dev, ®)) {
+ reg = 0;
+ rt2x00_set_field32(®, PHY_CSR3_VALUE, value);
+ rt2x00_set_field32(®, PHY_CSR3_REGNUM, word);
+ rt2x00_set_field32(®, PHY_CSR3_BUSY, 1);
+ rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0);
+
+ rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
+ }
-exit_fail:
mutex_unlock(&rt2x00dev->csr_mutex);
-
- ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n");
}
static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
mutex_lock(&rt2x00dev->csr_mutex);
/*
- * Wait until the BBP becomes ready.
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the read request into the register.
+ * After the data has been written, we wait until hardware
+ * returns the correct value, if at any time the register
+ * doesn't become available in time, reg will be 0xffffffff
+ * which means we return 0xff to the caller.
*/
- reg = rt73usb_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
- goto exit_fail;
+ if (WAIT_FOR_BBP(rt2x00dev, ®)) {
+ reg = 0;
+ rt2x00_set_field32(®, PHY_CSR3_REGNUM, word);
+ rt2x00_set_field32(®, PHY_CSR3_BUSY, 1);
+ rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1);
- /*
- * Write the request into the BBP.
- */
- reg = 0;
- rt2x00_set_field32(®, PHY_CSR3_REGNUM, word);
- rt2x00_set_field32(®, PHY_CSR3_BUSY, 1);
- rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1);
+ rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
- rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
-
- /*
- * Wait until the BBP becomes ready.
- */
- reg = rt73usb_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
- goto exit_fail;
+ WAIT_FOR_BBP(rt2x00dev, ®);
+ }
*value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
- mutex_unlock(&rt2x00dev->csr_mutex);
-
- return;
-exit_fail:
mutex_unlock(&rt2x00dev->csr_mutex);
-
- ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
- *value = 0xff;
}
static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u32 value)
{
u32 reg;
- unsigned int i;
if (!word)
return;
mutex_lock(&rt2x00dev->csr_mutex);
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt73usb_register_read_lock(rt2x00dev, PHY_CSR4, ®);
- if (!rt2x00_get_field32(reg, PHY_CSR4_BUSY))
- goto rf_write;
- udelay(REGISTER_BUSY_DELAY);
- }
-
- mutex_unlock(&rt2x00dev->csr_mutex);
- ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n");
- return;
-
-rf_write:
- reg = 0;
- rt2x00_set_field32(®, PHY_CSR4_VALUE, value);
-
/*
- * RF5225 and RF2527 contain 21 bits per RF register value,
- * all others contain 20 bits.
+ * Wait until the RF becomes available, afterwards we
+ * can safely write the new data into the register.
*/
- rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS,
- 20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
- rt2x00_rf(&rt2x00dev->chip, RF2527)));
- rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0);
- rt2x00_set_field32(®, PHY_CSR4_BUSY, 1);
-
- rt73usb_register_write_lock(rt2x00dev, PHY_CSR4, reg);
- rt2x00_rf_write(rt2x00dev, word, value);
+ if (WAIT_FOR_RF(rt2x00dev, ®)) {
+ reg = 0;
+ rt2x00_set_field32(®, PHY_CSR4_VALUE, value);
+ /*
+ * RF5225 and RF2527 contain 21 bits per RF register value,
+ * all others contain 20 bits.
+ */
+ rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS,
+ 20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
+ rt2x00_rf(&rt2x00dev->chip, RF2527)));
+ rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0);
+ rt2x00_set_field32(®, PHY_CSR4_BUSY, 1);
+
+ rt73usb_register_write_lock(rt2x00dev, PHY_CSR4, reg);
+ rt2x00_rf_write(rt2x00dev, word, value);
+ }
mutex_unlock(&rt2x00dev->csr_mutex);
}