ath10k: platform driver for WCN3990 SNOC WLAN module
WCN3990 is integrated 802.11ac chipset with SNOC bus interface. Add snoc layer driver registration and associated ops. CRs-Fixed: 1112488 Change-Id: I6106c617514609bd3fe41d9bbfbd34bf0588ef36 Signed-off-by: Govind Singh <govinds@codeaurora.org> Signed-off-by: Sarada Prasanna Garnayak <sgarna@codeaurora.org>
This commit is contained in:
parent
314869eb56
commit
3a27615253
3 changed files with 388 additions and 0 deletions
|
@ -0,0 +1,16 @@
|
|||
* Qualcomm Technologies, Inc. WCN3990 chipset WLAN platform Driver
|
||||
|
||||
This driver adds support for the Integrated WCN3990 WLAN module, WCN3990
|
||||
is integrated 802.11ac chipset with SNOC bus interface. It also add support
|
||||
for SNOC bus registration, copy engine configuration for the WCN3990 chipset,
|
||||
shadow register configuration, create host to target communication interface
|
||||
to interact with WLAN firmware, WLAN module interface control and data
|
||||
receive(RX)/transmit(TX) control.
|
||||
|
||||
Required properties:
|
||||
- compatible: "qcom,wcn3990-wifi";
|
||||
|
||||
Example:
|
||||
qcom,msm_ath10k@18000000 {
|
||||
compatible = "qcom,wcn3990-wifi";
|
||||
};
|
169
drivers/net/wireless/ath/ath10k/snoc.c
Normal file
169
drivers/net/wireless/ath/ath10k/snoc.c
Normal file
|
@ -0,0 +1,169 @@
|
|||
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include "debug.h"
|
||||
#include "hif.h"
|
||||
#include "htc.h"
|
||||
#include "ce.h"
|
||||
#include "snoc.h"
|
||||
#include <soc/qcom/icnss.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
void ath10k_snoc_write32(void *ar, u32 offset, u32 value)
|
||||
{
|
||||
}
|
||||
|
||||
u32 ath10k_snoc_read32(void *ar, u32 offset)
|
||||
{
|
||||
u32 val = 0;
|
||||
return val;
|
||||
}
|
||||
|
||||
static int ath10k_snoc_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
|
||||
struct ath10k_hif_sg_item *items, int n_items)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u16 ath10k_snoc_hif_get_free_queue_number(struct ath10k *ar, u8 pipe)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath10k_snoc_hif_send_complete_check(struct ath10k *ar, u8 pipe,
|
||||
int force)
|
||||
{
|
||||
}
|
||||
|
||||
static int ath10k_snoc_hif_map_service_to_pipe(struct ath10k *ar,
|
||||
u16 service_id,
|
||||
u8 *ul_pipe, u8 *dl_pipe)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath10k_snoc_hif_get_default_pipe(struct ath10k *ar,
|
||||
u8 *ul_pipe, u8 *dl_pipe)
|
||||
{
|
||||
}
|
||||
|
||||
static void ath10k_snoc_hif_stop(struct ath10k *ar)
|
||||
{
|
||||
}
|
||||
|
||||
static void ath10k_snoc_hif_power_down(struct ath10k *ar)
|
||||
{
|
||||
}
|
||||
|
||||
static int ath10k_snoc_hif_start(struct ath10k *ar)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_snoc_hif_power_up(struct ath10k *ar)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ath10k_hif_ops ath10k_snoc_hif_ops = {
|
||||
.tx_sg = ath10k_snoc_hif_tx_sg,
|
||||
.start = ath10k_snoc_hif_start,
|
||||
.stop = ath10k_snoc_hif_stop,
|
||||
.map_service_to_pipe = ath10k_snoc_hif_map_service_to_pipe,
|
||||
.get_default_pipe = ath10k_snoc_hif_get_default_pipe,
|
||||
.send_complete_check = ath10k_snoc_hif_send_complete_check,
|
||||
.get_free_queue_number = ath10k_snoc_hif_get_free_queue_number,
|
||||
.power_up = ath10k_snoc_hif_power_up,
|
||||
.power_down = ath10k_snoc_hif_power_down,
|
||||
.read32 = ath10k_snoc_read32,
|
||||
.write32 = ath10k_snoc_write32,
|
||||
};
|
||||
|
||||
static int ath10k_snoc_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ath10k *ar;
|
||||
struct ath10k_snoc *ar_snoc;
|
||||
enum ath10k_hw_rev hw_rev;
|
||||
struct device *dev;
|
||||
|
||||
dev = &pdev->dev;
|
||||
hw_rev = ATH10K_HW_WCN3990;
|
||||
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(37));
|
||||
ar = ath10k_core_create(sizeof(*ar_snoc), dev, ATH10K_BUS_SNOC,
|
||||
hw_rev, &ath10k_snoc_hif_ops);
|
||||
if (!ar) {
|
||||
dev_err(dev, "failed to allocate core\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "%s:WCN3990 probed\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_snoc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ath10k *ar = platform_get_drvdata(pdev);
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
|
||||
if (!ar)
|
||||
return -EINVAL;
|
||||
|
||||
if (!ar_snoc)
|
||||
return -EINVAL;
|
||||
|
||||
ath10k_core_destroy(ar);
|
||||
ath10k_dbg(ar, ATH10K_DBG_SNOC, "%s:WCN3990 removed\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id ath10k_snoc_dt_match[] = {
|
||||
{.compatible = "qcom,wcn3990-wifi"},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ath10k_snoc_dt_match);
|
||||
|
||||
static struct platform_driver ath10k_snoc_driver = {
|
||||
.probe = ath10k_snoc_probe,
|
||||
.remove = ath10k_snoc_remove,
|
||||
.driver = {
|
||||
.name = "ath10k_snoc",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = ath10k_snoc_dt_match,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init ath10k_snoc_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = platform_driver_register(&ath10k_snoc_driver);
|
||||
if (ret)
|
||||
pr_err("failed to register ath10k snoc driver: %d\n",
|
||||
ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
module_init(ath10k_snoc_init);
|
||||
|
||||
static void __exit ath10k_snoc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ath10k_snoc_driver);
|
||||
}
|
||||
module_exit(ath10k_snoc_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("Driver support for Atheros WCN3990 SNOC devices");
|
203
drivers/net/wireless/ath/ath10k/snoc.h
Normal file
203
drivers/net/wireless/ath/ath10k/snoc.h
Normal file
|
@ -0,0 +1,203 @@
|
|||
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _SNOC_H_
|
||||
#define _SNOC_H_
|
||||
|
||||
#include "hw.h"
|
||||
#include "ce.h"
|
||||
#include "pci.h"
|
||||
#define ATH10K_SNOC_RX_POST_RETRY_MS 50
|
||||
|
||||
/* struct snoc_state: SNOC target state
|
||||
* @pipe_cfg_addr: pipe configuration address
|
||||
* @svc_to_pipe_map: pipe services
|
||||
*/
|
||||
struct snoc_state {
|
||||
u32 pipe_cfg_addr;
|
||||
u32 svc_to_pipe_map;
|
||||
};
|
||||
|
||||
/* struct ath10k_snoc_pipe: SNOC pipe configuration
|
||||
* @ath10k_ce_pipe: pipe handle
|
||||
* @pipe_num: pipe number
|
||||
* @hif_ce_state: pointer to ce state
|
||||
* @buf_sz: buffer size
|
||||
* @pipe_lock: pipe lock
|
||||
* @ar_snoc: snoc private structure
|
||||
* @intr: tasklet structure
|
||||
*/
|
||||
|
||||
struct ath10k_snoc_pipe {
|
||||
struct ath10k_ce_pipe *ce_hdl;
|
||||
u8 pipe_num;
|
||||
struct ath10k *hif_ce_state;
|
||||
size_t buf_sz;
|
||||
/* protect ce info */
|
||||
spinlock_t pipe_lock;
|
||||
struct ath10k_snoc *ar_snoc;
|
||||
struct tasklet_struct intr;
|
||||
};
|
||||
|
||||
/* struct ath10k_snoc_supp_chip: supported chip set
|
||||
* @dev_id: device id
|
||||
* @rev_id: revison id
|
||||
*/
|
||||
struct ath10k_snoc_supp_chip {
|
||||
u32 dev_id;
|
||||
u32 rev_id;
|
||||
};
|
||||
|
||||
/* struct ath10k_snoc_info: SNOC info struct
|
||||
* @v_addr: base virtual address
|
||||
* @p_addr: base physical address
|
||||
* @chip_id: chip id
|
||||
* @chip_family: chip family
|
||||
* @board_id: board id
|
||||
* @soc_id: soc id
|
||||
* @fw_version: fw version
|
||||
*/
|
||||
struct ath10k_snoc_info {
|
||||
void __iomem *v_addr;
|
||||
phys_addr_t p_addr;
|
||||
u32 chip_id;
|
||||
u32 chip_family;
|
||||
u32 board_id;
|
||||
u32 soc_id;
|
||||
u32 fw_version;
|
||||
};
|
||||
|
||||
/* struct ath10k_target_info: SNOC target info
|
||||
* @target_version: target version
|
||||
* @target_type: target type
|
||||
* @target_revision: target revision
|
||||
* @soc_version: target soc version
|
||||
*/
|
||||
struct ath10k_target_info {
|
||||
u32 target_version;
|
||||
u32 target_type;
|
||||
u32 target_revision;
|
||||
u32 soc_version;
|
||||
};
|
||||
|
||||
/* struct ath10k_snoc: SNOC info struct
|
||||
* @dev: device structure
|
||||
* @ar:ath10k base structure
|
||||
* @mem: mem base virtual address
|
||||
* @mem_pa: mem base physical address
|
||||
* @target_info: snoc target info
|
||||
* @mem_len: mempry map length
|
||||
* @intr_tq: rx tasklet handle
|
||||
* @pipe_info: pipe info struct
|
||||
* @ce_lock: protect ce structures
|
||||
* @ce_states: maps ce id to ce state
|
||||
* @rx_post_retry: rx buffer post processing timer
|
||||
* @vaddr_rri_on_ddr: virtual address for RRI
|
||||
* @is_driver_probed: flag to indicate driver state
|
||||
*/
|
||||
struct ath10k_snoc {
|
||||
struct device *dev;
|
||||
struct ath10k *ar;
|
||||
void __iomem *mem;
|
||||
dma_addr_t mem_pa;
|
||||
struct ath10k_target_info target_info;
|
||||
size_t mem_len;
|
||||
struct tasklet_struct intr_tq;
|
||||
struct ath10k_snoc_pipe pipe_info[CE_COUNT_MAX];
|
||||
/* protects CE info */
|
||||
spinlock_t ce_lock;
|
||||
struct ath10k_ce_pipe ce_states[CE_COUNT_MAX];
|
||||
struct timer_list rx_post_retry;
|
||||
u32 *vaddr_rri_on_ddr;
|
||||
bool is_driver_probed;
|
||||
};
|
||||
|
||||
/* struct ath10k_ce_tgt_pipe_cfg: target pipe configuration
|
||||
* @pipe_num: pipe number
|
||||
* @pipe_dir: pipe direction
|
||||
* @nentries: entries in pipe
|
||||
* @nbytes_max: pipe max size
|
||||
* @flags: pipe flags
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct ath10k_ce_tgt_pipe_cfg {
|
||||
u32 pipe_num;
|
||||
u32 pipe_dir;
|
||||
u32 nentries;
|
||||
u32 nbytes_max;
|
||||
u32 flags;
|
||||
u32 reserved;
|
||||
};
|
||||
|
||||
/* struct ath10k_ce_svc_pipe_cfg: service pipe configuration
|
||||
* @service_id: target version
|
||||
* @pipe_dir: pipe direction
|
||||
* @pipe_num: pipe number
|
||||
*/
|
||||
struct ath10k_ce_svc_pipe_cfg {
|
||||
u32 service_id;
|
||||
u32 pipe_dir;
|
||||
u32 pipe_num;
|
||||
};
|
||||
|
||||
/* struct ath10k_shadow_reg_cfg: shadow register configuration
|
||||
* @ce_id: copy engine id
|
||||
* @reg_offset: offset to copy engine
|
||||
*/
|
||||
struct ath10k_shadow_reg_cfg {
|
||||
u16 ce_id;
|
||||
u16 reg_offset;
|
||||
};
|
||||
|
||||
/* struct ath10k_wlan_enable_cfg: wlan enable configuration
|
||||
* @num_ce_tgt_cfg: no of ce target configuration
|
||||
* @ce_tgt_cfg: target ce configuration
|
||||
* @num_ce_svc_pipe_cfg: no of ce service configuration
|
||||
* @ce_svc_cfg: ce service configuration
|
||||
* @num_shadow_reg_cfg: no of shadow registers
|
||||
* @shadow_reg_cfg: shadow register configuration
|
||||
*/
|
||||
struct ath10k_wlan_enable_cfg {
|
||||
u32 num_ce_tgt_cfg;
|
||||
struct ath10k_ce_tgt_pipe_cfg *ce_tgt_cfg;
|
||||
u32 num_ce_svc_pipe_cfg;
|
||||
struct ath10k_ce_svc_pipe_cfg *ce_svc_cfg;
|
||||
u32 num_shadow_reg_cfg;
|
||||
struct ath10k_shadow_reg_cfg *shadow_reg_cfg;
|
||||
};
|
||||
|
||||
/* enum ath10k_driver_mode: ath10k driver mode
|
||||
* @ATH10K_MISSION: mission mode
|
||||
* @ATH10K_FTM: ftm mode
|
||||
* @ATH10K_EPPING: epping mode
|
||||
* @ATH10K_OFF: off mode
|
||||
*/
|
||||
enum ath10k_driver_mode {
|
||||
ATH10K_MISSION,
|
||||
ATH10K_FTM,
|
||||
ATH10K_EPPING,
|
||||
ATH10K_OFF
|
||||
};
|
||||
|
||||
static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar)
|
||||
{
|
||||
return (struct ath10k_snoc *)ar->drv_priv;
|
||||
}
|
||||
|
||||
void ath10k_snoc_write32(void *ar, u32 offset, u32 value);
|
||||
void ath10k_snoc_soc_write32(struct ath10k *ar, u32 addr, u32 val);
|
||||
void ath10k_snoc_reg_write32(struct ath10k *ar, u32 addr, u32 val);
|
||||
u32 ath10k_snoc_read32(void *ar, u32 offset);
|
||||
u32 ath10k_snoc_soc_read32(struct ath10k *ar, u32 addr);
|
||||
u32 ath10k_snoc_reg_read32(struct ath10k *ar, u32 addr);
|
||||
|
||||
#endif /* _SNOC_H_ */
|
Loading…
Add table
Reference in a new issue