From 4ca0ac69e8861650b6068548435064edb1dfa236 Mon Sep 17 00:00:00 2001 From: Anilkumar Kolli Date: Mon, 23 Mar 2020 15:04:05 +0530 Subject: [PATCH 161/164] ath11k: Add reg read/write/window select ops Add support for bus read/write/window selection ops for target access. Signed-off-by: Govind Singh Signed-off-by: Anilkumar Kolli --- drivers/net/wireless/ath/ath11k/core.h | 1 + drivers/net/wireless/ath/ath11k/pci.c | 46 ++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/pci.h | 10 ++++++++ 3 files changed, 57 insertions(+) --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -796,6 +796,7 @@ struct ath11k_base { bool m3_fw_support; bool mhi_support; bool fixed_mem_region; + bool use_register_windowing; /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); }; --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c @@ -214,11 +214,53 @@ static const struct service_to_pipe targ }, }; +static inline void ath11k_pci_select_window(struct ath11k_pci *ar_pci, u32 offset) +{ + u32 window = (offset >> WINDOW_SHIFT) & WINDOW_VALUE_MASK; + + if (window != ar_pci->register_window) { + iowrite32(WINDOW_ENABLE_BIT | window, + ar_pci->mem + WINDOW_REG_ADDRESS); + ar_pci->register_window = window; + } +} + static inline struct ath11k_pci *ath11k_pci_priv(struct ath11k_base *ab) { return (struct ath11k_pci *)ab->drv_priv; } +static void ath11k_pci_write32(struct ath11k_base *ab, u32 offset, u32 value) +{ + struct ath11k_pci *ar_pci = ath11k_pci_priv(ab); + + if (ab->use_register_windowing) { + spin_lock_bh(&ar_pci->window_lock); + ath11k_pci_select_window(ar_pci, offset); + iowrite32(value, ar_pci->mem + WINDOW_START + (offset & WINDOW_RANGE_MASK)); + spin_unlock_bh(&ar_pci->window_lock); + } else { + iowrite32(value, ar_pci->mem + offset); + } +} + +static u32 ath11k_pci_read32(struct ath11k_base *ab, u32 offset) +{ + struct ath11k_pci *ar_pci = ath11k_pci_priv(ab); + u32 val; + + if (ab->use_register_windowing) { + spin_lock_bh(&ar_pci->window_lock); + ath11k_pci_select_window(ar_pci, offset); + val = ioread32(ar_pci->mem + WINDOW_START + (offset & WINDOW_RANGE_MASK)); + spin_unlock_bh(&ar_pci->window_lock); + } else { + val = ioread32(ar_pci->mem + offset); + } + + return val; +} + int ath11k_pci_get_msi_irq(struct device *dev, unsigned int vector) { struct pci_dev *pci_dev = to_pci_dev(dev); @@ -560,6 +602,8 @@ static int ath11k_pci_start(struct ath11 static const struct ath11k_hif_ops ath11k_pci_hif_ops = { .start = ath11k_pci_start, .stop = ath11k_pci_stop, + .read32 = ath11k_pci_read32, + .write32 = ath11k_pci_write32, .power_down = ath11k_pci_power_down, .power_up = ath11k_pci_power_up, }; @@ -607,6 +651,8 @@ static int ath11k_pci_probe(struct pci_d ab->m3_fw_support = true; ab->mhi_support = true; ab->fixed_mem_region = false; + ab->use_register_windowing = true; + spin_lock_init(&ar_pci->window_lock); ret = ath11k_pci_claim(ar_pci, pdev); if (ret) { --- a/drivers/net/wireless/ath/ath11k/pci.h +++ b/drivers/net/wireless/ath/ath11k/pci.h @@ -15,6 +15,14 @@ #define PCI_DMA_MASK_64_BIT 64 #define PCI_DMA_MASK_32_BIT 32 +#define MAX_UNWINDOWED_ADDRESS 0x80000 +#define WINDOW_ENABLE_BIT 0x40000000 +#define WINDOW_REG_ADDRESS 0x310C +#define WINDOW_SHIFT 19 +#define WINDOW_VALUE_MASK 0x3F +#define WINDOW_START MAX_UNWINDOWED_ADDRESS +#define WINDOW_RANGE_MASK 0x7FFFF + struct ath11k_msi_user { char *name; int num_vectors; @@ -39,6 +47,8 @@ struct ath11k_pci { u32 msi_ep_base_data; struct mhi_controller *mhi_ctrl; unsigned long mhi_state; + u32 register_window; + spinlock_t window_lock; }; int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ar_pci, char *user_name,