/* SPDX-License-Identifier: GPL-2.0 */
|
#ifndef __WCN_BUS_H__
|
#define __WCN_BUS_H__
|
|
#define CHN_MAX_NUM 32
|
|
#ifdef CONFIG_WCN_SDIO
|
#define PUB_HEAD_RSV 4
|
#else
|
#define PUB_HEAD_RSV 0
|
#endif
|
|
enum wcn_hw_type {
|
HW_TYPE_SDIO = 0,
|
HW_TYPE_PCIE,
|
HW_TYPE_SIPC,
|
HW_TYPE_USB,
|
HW_TYPE_UNKNOWN
|
};
|
|
enum wcn_vendor_id {
|
/* NOT pull chipen, NOT reset sdio after resume. */
|
WCN_VENDOR_DEFAULT = 0,
|
/* PULL chipen after resume. */
|
WCN_VENDOR_RESUME_POWER_DOWN,
|
/* NOT pull chipen, reset sdio after resume. */
|
WCN_VENDOR_RESUME_KEEPPWR_RESETSDIO,
|
|
WCN_VENDOR_MAX = 8
|
};
|
|
enum slp_subsys {
|
PACKER_TX = 0,
|
PACKER_RX,
|
PACKER_DT_TX,
|
PACKER_DT_RX,
|
DT_WRITEL,
|
DT_READL,
|
DT_WRITE,
|
DT_READ,
|
WIFI,
|
DOWNLOAD,
|
DBG_TOOL,
|
SUBSYS_MAX,
|
};
|
|
struct mbuf_t {
|
struct mbuf_t *next;
|
unsigned char *buf;
|
unsigned long phy;
|
unsigned short len;
|
unsigned short rsvd;
|
unsigned int seq;
|
};
|
|
struct mchn_ops_t {
|
int channel;
|
/* hardware interface type */
|
int hif_type;
|
/* inout=1 tx side, inout=0 rx side */
|
int inout;
|
/* set callback pop_link/push_link frequency */
|
int intr_interval;
|
/* data buffer size */
|
int buf_size;
|
/* mbuf pool size */
|
int pool_size;
|
/* The large number of trans */
|
int once_max_trans;
|
/* rx side threshold */
|
int rx_threshold;
|
/* tx timeout */
|
int timeout;
|
/* callback in top tophalf */
|
int cb_in_irq;
|
/* pending link num */
|
int max_pending;
|
/*
|
* pop link list, (1)chn id, (2)mbuf link head
|
* (3) mbuf link tail (4)number of node
|
*/
|
int (*pop_link)(int, struct mbuf_t *, struct mbuf_t *, int);
|
/* ap don't need to implementation */
|
int (*push_link)(int, struct mbuf_t **, struct mbuf_t **, int *);
|
/* (1)channel id (2)trans time, -1 express timeout */
|
int (*tx_complete)(int, int);
|
int (*power_notify)(int, int);
|
};
|
|
struct sdio_puh_t {
|
#ifdef CONFIG_SDIOM
|
unsigned int pad:7;
|
#else
|
unsigned int pad:6;
|
unsigned int check_sum:1;
|
#endif
|
unsigned int len:16;
|
unsigned int eof:1;
|
unsigned int subtype:4;
|
unsigned int type:4;
|
}; /* 32bits public header */
|
|
struct bus_puh_t {
|
#ifdef CONFIG_SDIOM
|
unsigned int pad:7;
|
#else
|
unsigned int pad:6;
|
unsigned int check_sum:1;
|
#endif
|
unsigned int len:16;
|
unsigned int eof:1;
|
unsigned int subtype:4;
|
unsigned int type:4;
|
}; /* 32bits public header */
|
|
struct sprdwcn_bus_ops {
|
int (*preinit)(void);
|
void (*deinit)(void);
|
|
int (*chn_init)(struct mchn_ops_t *ops);
|
int (*chn_deinit)(struct mchn_ops_t *ops);
|
|
/*
|
* For sdio:
|
* list_alloc and list_free only tx available.
|
* TX: module manage buf, RX: SDIO unified manage buf
|
*/
|
int (*list_alloc)(int chn, struct mbuf_t **head,
|
struct mbuf_t **tail, int *num);
|
int (*list_free)(int chn, struct mbuf_t *head,
|
struct mbuf_t *tail, int num);
|
|
/* For sdio: TX(send data) and RX(give back list to SDIO) */
|
int (*push_list)(int chn, struct mbuf_t *head,
|
struct mbuf_t *tail, int num);
|
int (*push_list_direct)(int chn, struct mbuf_t *head,
|
struct mbuf_t *tail, int num);
|
unsigned char (*get_wl_wake_host_en)(void);
|
unsigned char (*get_tx_mode)(void);
|
unsigned char (*get_rx_mode)(void);
|
unsigned char (*get_irq_type)(void);
|
unsigned int (*get_blk_size)(void);
|
|
/*
|
* for pcie
|
* push link list, Using a blocking mode,
|
* Timeout wait for tx_complete
|
*/
|
int (*push_link_wait_complete)(int chn, struct mbuf_t *head,
|
struct mbuf_t *tail, int num,
|
int timeout);
|
int (*hw_pop_link)(int chn, void *head, void *tail, int num);
|
int (*hw_tx_complete)(int chn, int timeout);
|
int (*hw_req_push_link)(int chn, int need);
|
|
int (*direct_read)(unsigned int addr, void *buf, unsigned int len);
|
int (*direct_write)(unsigned int addr, void *buf, unsigned int len);
|
|
int (*readbyte)(unsigned int addr, unsigned char *val);
|
int (*writebyte)(unsigned int addr, unsigned char val);
|
|
int (*write_l)(unsigned int system_addr, void *buf);
|
int (*read_l)(unsigned int system_addr, void *buf);
|
|
unsigned int (*get_carddump_status)(void);
|
void (*set_carddump_status)(unsigned int flag);
|
unsigned long long (*get_rx_total_cnt)(void);
|
|
/* for runtime */
|
int (*runtime_get)(void);
|
int (*runtime_put)(void);
|
|
int (*rescan)(void);
|
void (*register_rescan_cb)(void *);
|
void (*remove_card)(void);
|
/* for module to know hif_type */
|
int (*get_hif_type)(void);
|
int (*driver_register)(void);
|
void (*driver_unregister)(void);
|
/* for usb check cp status */
|
int (*check_cp_ready)(unsigned int addr, int timeout);
|
};
|
|
extern void module_bus_init(void);
|
extern void module_bus_deinit(void);
|
extern struct sprdwcn_bus_ops *get_wcn_bus_ops(void);
|
|
static inline
|
int sprdwcn_bus_get_hif_type(void)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->get_hif_type)
|
return 0;
|
|
return bus_ops->get_hif_type();
|
}
|
|
static inline
|
int sprdwcn_bus_preinit(void)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->preinit)
|
return 0;
|
|
return bus_ops->preinit();
|
}
|
|
static inline
|
void sprdwcn_bus_deinit(void)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->deinit)
|
return;
|
|
bus_ops->deinit();
|
}
|
|
static inline
|
int sprdwcn_bus_chn_init(struct mchn_ops_t *ops)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->chn_init)
|
return 0;
|
|
return bus_ops->chn_init(ops);
|
}
|
|
static inline
|
int sprdwcn_bus_chn_deinit(struct mchn_ops_t *ops)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->chn_deinit)
|
return 0;
|
|
return bus_ops->chn_deinit(ops);
|
}
|
|
static inline
|
int sprdwcn_bus_list_alloc(int chn, struct mbuf_t **head,
|
struct mbuf_t **tail, int *num)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->list_alloc)
|
return 0;
|
|
return bus_ops->list_alloc(chn, head, tail, num);
|
}
|
|
static inline
|
int sprdwcn_bus_list_free(int chn, struct mbuf_t *head,
|
struct mbuf_t *tail, int num)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->list_free)
|
return 0;
|
|
return bus_ops->list_free(chn, head, tail, num);
|
}
|
|
static inline
|
int sprdwcn_bus_push_list(int chn, struct mbuf_t *head,
|
struct mbuf_t *tail, int num)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->push_list)
|
return 0;
|
|
return bus_ops->push_list(chn, head, tail, num);
|
}
|
|
static inline
|
int sprdwcn_bus_push_list_direct(int chn, struct mbuf_t *head,
|
struct mbuf_t *tail, int num)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->push_list_direct)
|
return 0;
|
|
return bus_ops->push_list_direct(chn, head, tail, num);
|
}
|
|
static inline
|
int sprdwcn_bus_push_link_wait_complete(int chn, struct mbuf_t *head,
|
struct mbuf_t *tail, int num,
|
int timeout)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->push_link_wait_complete)
|
return 0;
|
|
return bus_ops->push_link_wait_complete(chn, head,
|
tail, num, timeout);
|
}
|
|
static inline
|
int sprdwcn_bus_hw_pop_link(int chn, void *head, void *tail, int num)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->hw_pop_link)
|
return 0;
|
|
return bus_ops->hw_pop_link(chn, head, tail, num);
|
}
|
|
static inline
|
int sprdwcn_bus_hw_tx_complete(int chn, int timeout)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->hw_tx_complete)
|
return 0;
|
|
return bus_ops->hw_tx_complete(chn, timeout);
|
}
|
|
static inline
|
int sprdwcn_bus_hw_req_push_link(int chn, int need)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->hw_req_push_link)
|
return 0;
|
|
return bus_ops->hw_req_push_link(chn, need);
|
}
|
|
static inline
|
int sprdwcn_bus_direct_read(unsigned int addr,
|
void *buf, unsigned int len)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->direct_read)
|
return 0;
|
|
return bus_ops->direct_read(addr, buf, len);
|
}
|
|
static inline
|
int sprdwcn_bus_direct_write(unsigned int addr,
|
void *buf, unsigned int len)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->direct_write)
|
return 0;
|
|
return bus_ops->direct_write(addr, buf, len);
|
}
|
|
static inline
|
int sprdwcn_bus_reg_read(unsigned int addr,
|
void *buf, unsigned int len)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->read_l)
|
return 0;
|
|
return bus_ops->read_l(addr, buf);
|
}
|
|
static inline
|
int sprdwcn_bus_reg_write(unsigned int addr,
|
void *buf, unsigned int len)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->write_l)
|
return 0;
|
|
return bus_ops->write_l(addr, buf);
|
}
|
|
static inline
|
int sprdwcn_bus_aon_readb(unsigned int addr, unsigned char *val)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->readbyte)
|
return 0;
|
|
return bus_ops->readbyte(addr, val);
|
}
|
|
static inline
|
int sprdwcn_bus_aon_writeb(unsigned int addr, unsigned char val)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->writebyte)
|
return 0;
|
|
return bus_ops->writebyte(addr, val);
|
}
|
|
static inline
|
unsigned int sprdwcn_bus_get_carddump_status(void)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->get_carddump_status)
|
return 0;
|
|
return bus_ops->get_carddump_status();
|
}
|
|
static inline
|
void sprdwcn_bus_set_carddump_status(unsigned int flag)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->set_carddump_status)
|
return;
|
|
bus_ops->set_carddump_status(flag);
|
}
|
|
static inline
|
unsigned long long sprdwcn_bus_get_rx_total_cnt(void)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->get_rx_total_cnt)
|
return 0;
|
|
return bus_ops->get_rx_total_cnt();
|
}
|
|
static inline
|
int sprdwcn_bus_runtime_get(void)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->runtime_get)
|
return 0;
|
|
return bus_ops->runtime_get();
|
}
|
|
static inline
|
int sprdwcn_bus_runtime_put(void)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->runtime_put)
|
return 0;
|
|
return bus_ops->runtime_put();
|
}
|
|
static inline
|
int sprdwcn_bus_rescan(void)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->rescan)
|
return 0;
|
|
return bus_ops->rescan();
|
}
|
|
static inline
|
void sprdwcn_bus_register_rescan_cb(void *func)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->register_rescan_cb)
|
return;
|
|
bus_ops->register_rescan_cb(func);
|
}
|
|
static inline
|
void sprdwcn_bus_remove_card(void)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->remove_card)
|
return;
|
|
bus_ops->remove_card();
|
}
|
|
static inline
|
unsigned char sprdwcn_bus_get_wl_wake_host_en(void)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->get_wl_wake_host_en)
|
return 0;
|
|
return bus_ops->get_wl_wake_host_en();
|
}
|
|
static inline
|
unsigned char sprdwcn_bus_get_tx_mode(void)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->get_tx_mode)
|
return 0;
|
|
return bus_ops->get_tx_mode();
|
}
|
|
static inline
|
unsigned char sprdwcn_bus_get_rx_mode(void)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->get_rx_mode)
|
return 0;
|
|
return bus_ops->get_rx_mode();
|
}
|
|
static inline
|
unsigned char sprdwcn_bus_get_irq_type(void)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->get_irq_type)
|
return 0;
|
|
return bus_ops->get_irq_type();
|
}
|
|
static inline
|
unsigned int sprdwcn_bus_get_blk_size(void)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->get_blk_size)
|
return 0;
|
|
return bus_ops->get_blk_size();
|
}
|
|
static inline
|
int sprdwcn_bus_driver_register(void)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->driver_register)
|
return 0;
|
|
return bus_ops->driver_register();
|
}
|
|
static inline
|
void sprdwcn_bus_driver_unregister(void)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->driver_unregister)
|
return;
|
|
bus_ops->driver_unregister();
|
}
|
|
static inline
|
int sprdwcn_check_cp_ready(unsigned int addr, int timeout)
|
{
|
struct sprdwcn_bus_ops *bus_ops = get_wcn_bus_ops();
|
|
if (!bus_ops || !bus_ops->check_cp_ready)
|
return 0;
|
|
return bus_ops->check_cp_ready(addr, timeout);
|
}
|
|
static inline
|
int wcn_bus_init(void)
|
{
|
module_bus_init();
|
return 0;
|
}
|
|
static inline
|
void wcn_bus_deinit(void)
|
{
|
module_bus_deinit();
|
}
|
|
#endif
|