ath10k: add board data download from target

The QCA9887 stores its calibration data (board.bin) inside the EEPROM of
the target. This has to be downloaded manually to allow the device to
initialize correctly.

Signed-off-by: Sven Eckelmann <sven.eckelmann@open-mesh.com>
[kvalo@qca.qualcomm.com: handle -EOPNOTSUPP and s/fetch_board_data/fetch_cal_eeprom]
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
This commit is contained in:
Sven Eckelmann
2016-06-02 17:59:50 +03:00
committed by Kalle Valo
parent 6fd3dd7160
commit 6847f96733
5 changed files with 219 additions and 1 deletions

View File

@@ -2577,6 +2577,144 @@ static int ath10k_pci_hif_resume(struct ath10k *ar)
}
#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 = {
.tx_sg = ath10k_pci_hif_tx_sg,
.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,
.resume = ath10k_pci_hif_resume,
#endif
.fetch_cal_eeprom = ath10k_pci_hif_fetch_cal_eeprom,
};
/*