|
@@ -2577,6 +2577,144 @@ static int ath10k_pci_hif_resume(struct ath10k *ar)
|
|
|
}
|
|
}
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
|
|
+static bool ath10k_pci_validate_cal(void *data, size_t size)
|
|
|
|
|
+{
|
|
|
|
|
+ __le16 *cal_words = data;
|
|
|
|
|
+ u16 checksum = 0;
|
|
|
|
|
+ size_t i;
|
|
|
|
|
+
|
|
|
|
|
+ if (size % 2 != 0)
|
|
|
|
|
+ return false;
|
|
|
|
|
+
|
|
|
|
|
+ for (i = 0; i < size / 2; i++)
|
|
|
|
|
+ checksum ^= le16_to_cpu(cal_words[i]);
|
|
|
|
|
+
|
|
|
|
|
+ return checksum == 0xffff;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void ath10k_pci_enable_eeprom(struct ath10k *ar)
|
|
|
|
|
+{
|
|
|
|
|
+ /* Enable SI clock */
|
|
|
|
|
+ ath10k_pci_soc_write32(ar, CLOCK_CONTROL_OFFSET, 0x0);
|
|
|
|
|
+
|
|
|
|
|
+ /* Configure GPIOs for I2C operation */
|
|
|
|
|
+ ath10k_pci_write32(ar,
|
|
|
|
|
+ GPIO_BASE_ADDRESS + GPIO_PIN0_OFFSET +
|
|
|
|
|
+ 4 * QCA9887_1_0_I2C_SDA_GPIO_PIN,
|
|
|
|
|
+ SM(QCA9887_1_0_I2C_SDA_PIN_CONFIG,
|
|
|
|
|
+ GPIO_PIN0_CONFIG) |
|
|
|
|
|
+ SM(1, GPIO_PIN0_PAD_PULL));
|
|
|
|
|
+
|
|
|
|
|
+ ath10k_pci_write32(ar,
|
|
|
|
|
+ GPIO_BASE_ADDRESS + GPIO_PIN0_OFFSET +
|
|
|
|
|
+ 4 * QCA9887_1_0_SI_CLK_GPIO_PIN,
|
|
|
|
|
+ SM(QCA9887_1_0_SI_CLK_PIN_CONFIG, GPIO_PIN0_CONFIG) |
|
|
|
|
|
+ SM(1, GPIO_PIN0_PAD_PULL));
|
|
|
|
|
+
|
|
|
|
|
+ ath10k_pci_write32(ar,
|
|
|
|
|
+ GPIO_BASE_ADDRESS +
|
|
|
|
|
+ QCA9887_1_0_GPIO_ENABLE_W1TS_LOW_ADDRESS,
|
|
|
|
|
+ 1u << QCA9887_1_0_SI_CLK_GPIO_PIN);
|
|
|
|
|
+
|
|
|
|
|
+ /* In Swift ASIC - EEPROM clock will be (110MHz/512) = 214KHz */
|
|
|
|
|
+ ath10k_pci_write32(ar,
|
|
|
|
|
+ SI_BASE_ADDRESS + SI_CONFIG_OFFSET,
|
|
|
|
|
+ SM(1, SI_CONFIG_ERR_INT) |
|
|
|
|
|
+ SM(1, SI_CONFIG_BIDIR_OD_DATA) |
|
|
|
|
|
+ SM(1, SI_CONFIG_I2C) |
|
|
|
|
|
+ SM(1, SI_CONFIG_POS_SAMPLE) |
|
|
|
|
|
+ SM(1, SI_CONFIG_INACTIVE_DATA) |
|
|
|
|
|
+ SM(1, SI_CONFIG_INACTIVE_CLK) |
|
|
|
|
|
+ SM(8, SI_CONFIG_DIVIDER));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int ath10k_pci_read_eeprom(struct ath10k *ar, u16 addr, u8 *out)
|
|
|
|
|
+{
|
|
|
|
|
+ u32 reg;
|
|
|
|
|
+ int wait_limit;
|
|
|
|
|
+
|
|
|
|
|
+ /* set device select byte and for the read operation */
|
|
|
|
|
+ reg = QCA9887_EEPROM_SELECT_READ |
|
|
|
|
|
+ SM(addr, QCA9887_EEPROM_ADDR_LO) |
|
|
|
|
|
+ SM(addr >> 8, QCA9887_EEPROM_ADDR_HI);
|
|
|
|
|
+ ath10k_pci_write32(ar, SI_BASE_ADDRESS + SI_TX_DATA0_OFFSET, reg);
|
|
|
|
|
+
|
|
|
|
|
+ /* write transmit data, transfer length, and START bit */
|
|
|
|
|
+ ath10k_pci_write32(ar, SI_BASE_ADDRESS + SI_CS_OFFSET,
|
|
|
|
|
+ SM(1, SI_CS_START) | SM(1, SI_CS_RX_CNT) |
|
|
|
|
|
+ SM(4, SI_CS_TX_CNT));
|
|
|
|
|
+
|
|
|
|
|
+ /* wait max 1 sec */
|
|
|
|
|
+ wait_limit = 100000;
|
|
|
|
|
+
|
|
|
|
|
+ /* wait for SI_CS_DONE_INT */
|
|
|
|
|
+ do {
|
|
|
|
|
+ reg = ath10k_pci_read32(ar, SI_BASE_ADDRESS + SI_CS_OFFSET);
|
|
|
|
|
+ if (MS(reg, SI_CS_DONE_INT))
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ wait_limit--;
|
|
|
|
|
+ udelay(10);
|
|
|
|
|
+ } while (wait_limit > 0);
|
|
|
|
|
+
|
|
|
|
|
+ if (!MS(reg, SI_CS_DONE_INT)) {
|
|
|
|
|
+ ath10k_err(ar, "timeout while reading device EEPROM at %04x\n",
|
|
|
|
|
+ addr);
|
|
|
|
|
+ return -ETIMEDOUT;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* clear SI_CS_DONE_INT */
|
|
|
|
|
+ ath10k_pci_write32(ar, SI_BASE_ADDRESS + SI_CS_OFFSET, reg);
|
|
|
|
|
+
|
|
|
|
|
+ if (MS(reg, SI_CS_DONE_ERR)) {
|
|
|
|
|
+ ath10k_err(ar, "failed to read device EEPROM at %04x\n", addr);
|
|
|
|
|
+ return -EIO;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* extract receive data */
|
|
|
|
|
+ reg = ath10k_pci_read32(ar, SI_BASE_ADDRESS + SI_RX_DATA0_OFFSET);
|
|
|
|
|
+ *out = reg;
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int ath10k_pci_hif_fetch_cal_eeprom(struct ath10k *ar, void **data,
|
|
|
|
|
+ size_t *data_len)
|
|
|
|
|
+{
|
|
|
|
|
+ u8 *caldata = NULL;
|
|
|
|
|
+ size_t calsize, i;
|
|
|
|
|
+ int ret;
|
|
|
|
|
+
|
|
|
|
|
+ if (!QCA_REV_9887(ar))
|
|
|
|
|
+ return -EOPNOTSUPP;
|
|
|
|
|
+
|
|
|
|
|
+ calsize = ar->hw_params.cal_data_len;
|
|
|
|
|
+ caldata = kmalloc(calsize, GFP_KERNEL);
|
|
|
|
|
+ if (!caldata)
|
|
|
|
|
+ return -ENOMEM;
|
|
|
|
|
+
|
|
|
|
|
+ ath10k_pci_enable_eeprom(ar);
|
|
|
|
|
+
|
|
|
|
|
+ for (i = 0; i < calsize; i++) {
|
|
|
|
|
+ ret = ath10k_pci_read_eeprom(ar, i, &caldata[i]);
|
|
|
|
|
+ if (ret)
|
|
|
|
|
+ goto err_free;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!ath10k_pci_validate_cal(caldata, calsize))
|
|
|
|
|
+ goto err_free;
|
|
|
|
|
+
|
|
|
|
|
+ *data = caldata;
|
|
|
|
|
+ *data_len = calsize;
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+
|
|
|
|
|
+err_free:
|
|
|
|
|
+ kfree(data);
|
|
|
|
|
+
|
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
|
|
static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
|
|
|
.tx_sg = ath10k_pci_hif_tx_sg,
|
|
.tx_sg = ath10k_pci_hif_tx_sg,
|
|
|
.diag_read = ath10k_pci_hif_diag_read,
|
|
.diag_read = ath10k_pci_hif_diag_read,
|
|
@@ -2596,6 +2734,7 @@ static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
|
|
|
.suspend = ath10k_pci_hif_suspend,
|
|
.suspend = ath10k_pci_hif_suspend,
|
|
|
.resume = ath10k_pci_hif_resume,
|
|
.resume = ath10k_pci_hif_resume,
|
|
|
#endif
|
|
#endif
|
|
|
|
|
+ .fetch_cal_eeprom = ath10k_pci_hif_fetch_cal_eeprom,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
/*
|