|
@@ -90,6 +90,13 @@ static DEFINE_SPINLOCK(time_sync_lock);
|
|
|
#define HST_HANG_DATA_OFFSET ((3 * 1024 * 1024) - HANG_DATA_LENGTH)
|
|
|
#define HSP_HANG_DATA_OFFSET ((2 * 1024 * 1024) - HANG_DATA_LENGTH)
|
|
|
|
|
|
+#define AFC_SLOT_SIZE 0x1000
|
|
|
+#define AFC_MAX_SLOT 2
|
|
|
+#define AFC_MEM_SIZE (AFC_SLOT_SIZE * AFC_MAX_SLOT)
|
|
|
+#define AFC_AUTH_STATUS_OFFSET 1
|
|
|
+#define AFC_AUTH_SUCCESS 1
|
|
|
+#define AFC_AUTH_ERROR 0
|
|
|
+
|
|
|
static const struct mhi_channel_config cnss_mhi_channels[] = {
|
|
|
{
|
|
|
.num = 0,
|
|
@@ -4039,6 +4046,94 @@ int cnss_pci_qmi_send_put(struct cnss_pci_data *pci_priv)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+int cnss_send_buffer_to_afcmem(struct device *dev, char *afcdb, uint32_t len,
|
|
|
+ uint8_t slotid)
|
|
|
+{
|
|
|
+ struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
|
|
|
+ struct cnss_fw_mem *fw_mem;
|
|
|
+ void *mem = NULL;
|
|
|
+ int i, ret;
|
|
|
+ u32 *status;
|
|
|
+
|
|
|
+ if (!plat_priv)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ fw_mem = plat_priv->fw_mem;
|
|
|
+ if (slotid >= AFC_MAX_SLOT) {
|
|
|
+ cnss_pr_err("Invalid slot id %d\n", slotid);
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+ if (len > AFC_SLOT_SIZE) {
|
|
|
+ cnss_pr_err("len %d greater than slot size", len);
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < plat_priv->fw_mem_seg_len; i++) {
|
|
|
+ if (fw_mem[i].type == QMI_WLFW_AFC_MEM_V01) {
|
|
|
+ mem = fw_mem[i].va;
|
|
|
+ status = mem + (slotid * AFC_SLOT_SIZE);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!mem) {
|
|
|
+ cnss_pr_err("AFC mem is not available\n");
|
|
|
+ ret = -ENOMEM;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(mem + (slotid * AFC_SLOT_SIZE), afcdb, len);
|
|
|
+ if (len < AFC_SLOT_SIZE)
|
|
|
+ memset(mem + (slotid * AFC_SLOT_SIZE) + len,
|
|
|
+ 0, AFC_SLOT_SIZE - len);
|
|
|
+ status[AFC_AUTH_STATUS_OFFSET] = cpu_to_le32(AFC_AUTH_SUCCESS);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+err:
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(cnss_send_buffer_to_afcmem);
|
|
|
+
|
|
|
+int cnss_reset_afcmem(struct device *dev, uint8_t slotid)
|
|
|
+{
|
|
|
+ struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
|
|
|
+ struct cnss_fw_mem *fw_mem;
|
|
|
+ void *mem = NULL;
|
|
|
+ int i, ret;
|
|
|
+
|
|
|
+ if (!plat_priv)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ fw_mem = plat_priv->fw_mem;
|
|
|
+ if (slotid >= AFC_MAX_SLOT) {
|
|
|
+ cnss_pr_err("Invalid slot id %d\n", slotid);
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < plat_priv->fw_mem_seg_len; i++) {
|
|
|
+ if (fw_mem[i].type == QMI_WLFW_AFC_MEM_V01) {
|
|
|
+ mem = fw_mem[i].va;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!mem) {
|
|
|
+ cnss_pr_err("AFC mem is not available\n");
|
|
|
+ ret = -ENOMEM;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ memset(mem + (slotid * AFC_SLOT_SIZE), 0, AFC_SLOT_SIZE);
|
|
|
+ return 0;
|
|
|
+
|
|
|
+err:
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(cnss_reset_afcmem);
|
|
|
+
|
|
|
int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv)
|
|
|
{
|
|
|
struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
|