Commit 1399fb87 authored by Govind Singh's avatar Govind Singh Committed by Kalle Valo

ath11k: register MHI controller device for QCA6390

Modem Host Interface (MHI) is a communication protocol to communicate with
external Qualcomm modems and Wi-Fi chipsets over high speed peripheral buses.
Even though MHI doesn’t dictate underlying physical layer, protocol and MHI
stack is structured for PCI based devices.

Register directly with MHI subsystem as a MHI device driver for firmware
download to QCA6390.

Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.1.0.1-01238-QCAHKSWPL_SILICONZ-2
Signed-off-by: default avatarGovind Singh <govinds@codeaurora.org>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/1597309466-19688-9-git-send-email-kvalo@codeaurora.org
parent b8246f88
......@@ -21,6 +21,9 @@ config ATH11K_AHB
config ATH11K_PCI
tristate "Atheros ath11k PCI support"
depends on ATH11K && PCI
select MHI_BUS
select QRTR
select QRTR_MHI
help
This module adds support for PCIE bus
......
......@@ -28,7 +28,7 @@ obj-$(CONFIG_ATH11K_AHB) += ath11k_ahb.o
ath11k_ahb-y += ahb.o
obj-$(CONFIG_ATH11K_PCI) += ath11k_pci.o
ath11k_pci-y += pci.o
ath11k_pci-y += mhi.o pci.o
# for tracing framework to find trace.h
CFLAGS_trace.o := -I$(src)
......@@ -72,6 +72,7 @@
#define ATH11K_BOARD_API2_FILE "board-2.bin"
#define ATH11K_DEFAULT_BOARD_FILE "board.bin"
#define ATH11K_DEFAULT_CAL_FILE "caldata.bin"
#define ATH11K_AMSS_FILE "amss.bin"
enum ath11k_hw_rate_cck {
ATH11K_HW_RATE_CCK_LP_11M = 0,
......
This diff is collapsed.
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
*/
#ifndef _ATH11K_MHI_H
#define _ATH11K_MHI_H
#include "pci.h"
enum ath11k_mhi_state {
ATH11K_MHI_INIT,
ATH11K_MHI_DEINIT,
ATH11K_MHI_POWER_ON,
ATH11K_MHI_POWER_OFF,
ATH11K_MHI_FORCE_POWER_OFF,
ATH11K_MHI_SUSPEND,
ATH11K_MHI_RESUME,
ATH11K_MHI_TRIGGER_RDDM,
ATH11K_MHI_RDDM,
ATH11K_MHI_RDDM_DONE,
};
int ath11k_mhi_start(struct ath11k_pci *ar_pci);
void ath11k_mhi_stop(struct ath11k_pci *ar_pci);
int ath11k_mhi_register(struct ath11k_pci *ar_pci);
void ath11k_mhi_unregister(struct ath11k_pci *ar_pci);
#endif
......@@ -9,6 +9,8 @@
#include "pci.h"
#include "core.h"
#include "hif.h"
#include "mhi.h"
#include "debug.h"
#define ATH11K_PCI_BAR_NUM 0
......@@ -34,6 +36,40 @@ static const struct ath11k_msi_config msi_config = {
},
};
int ath11k_pci_get_msi_irq(struct device *dev, unsigned int vector)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
return pci_irq_vector(pci_dev, vector);
}
int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ab_pci, char *user_name,
int *num_vectors, u32 *user_base_data,
u32 *base_vector)
{
struct ath11k_base *ab = ab_pci->ab;
int idx;
for (idx = 0; idx < msi_config.total_users; idx++) {
if (strcmp(user_name, msi_config.users[idx].name) == 0) {
*num_vectors = msi_config.users[idx].num_vectors;
*user_base_data = msi_config.users[idx].base_vector
+ ab_pci->msi_ep_base_data;
*base_vector = msi_config.users[idx].base_vector;
ath11k_dbg(ab, ATH11K_DBG_PCI, "Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n",
user_name, *num_vectors, *user_base_data,
*base_vector);
return 0;
}
}
ath11k_err(ab, "Failed to find MSI assignment for %s!\n", user_name);
return -EINVAL;
}
static int ath11k_pci_enable_msi(struct ath11k_pci *ab_pci)
{
struct ath11k_base *ab = ab_pci->ab;
......@@ -161,6 +197,32 @@ static void ath11k_pci_free_region(struct ath11k_pci *ab_pci)
pci_disable_device(pci_dev);
}
static int ath11k_pci_power_up(struct ath11k_base *ab)
{
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
int ret;
ret = ath11k_mhi_start(ab_pci);
if (ret) {
ath11k_err(ab, "failed to start mhi: %d\n", ret);
return ret;
}
return 0;
}
static void ath11k_pci_power_down(struct ath11k_base *ab)
{
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
ath11k_mhi_stop(ab_pci);
}
static __maybe_unused const struct ath11k_hif_ops ath11k_pci_hif_ops = {
.power_down = ath11k_pci_power_down,
.power_up = ath11k_pci_power_up,
};
static int ath11k_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *pci_dev)
{
......@@ -212,6 +274,12 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
if (ret)
goto err_pci_disable_msi;
ret = ath11k_mhi_register(ab_pci);
if (ret) {
ath11k_err(ab, "failed to register mhi: %d\n", ret);
goto err_pci_disable_msi;
}
return 0;
err_pci_disable_msi:
......@@ -232,16 +300,25 @@ static void ath11k_pci_remove(struct pci_dev *pdev)
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);
ath11k_mhi_unregister(ab_pci);
ath11k_pci_disable_msi(ab_pci);
ath11k_pci_free_region(ab_pci);
ath11k_core_free(ab);
}
static void ath11k_pci_shutdown(struct pci_dev *pdev)
{
struct ath11k_base *ab = pci_get_drvdata(pdev);
ath11k_pci_power_down(ab);
}
static struct pci_driver ath11k_pci_driver = {
.name = "ath11k_pci",
.id_table = ath11k_pci_id_table,
.probe = ath11k_pci_probe,
.remove = ath11k_pci_remove,
.shutdown = ath11k_pci_shutdown,
};
static int ath11k_pci_init(void)
......
......@@ -2,6 +2,10 @@
/*
* Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
*/
#ifndef _ATH11K_PCI_H
#define _ATH11K_PCI_H
#include <linux/mhi.h>
#include "core.h"
......@@ -21,10 +25,20 @@ struct ath11k_pci {
struct pci_dev *pdev;
struct ath11k_base *ab;
u16 dev_id;
char amss_path[100];
u32 msi_ep_base_data;
struct mhi_controller *mhi_ctrl;
unsigned long mhi_state;
};
static inline struct ath11k_pci *ath11k_pci_priv(struct ath11k_base *ab)
{
return (struct ath11k_pci *)ab->drv_priv;
}
int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ar_pci, char *user_name,
int *num_vectors, u32 *user_base_data,
u32 *base_vector);
int ath11k_pci_get_msi_irq(struct device *dev, unsigned int vector);
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment