Path: blob/main/sys/contrib/dev/broadcom/brcm80211/brcmfmac/pcie.c
178665 views
// SPDX-License-Identifier: ISC1/*2* Copyright (c) 2014 Broadcom Corporation3*/45#include <linux/kernel.h>6#include <linux/module.h>7#include <linux/firmware.h>8#include <linux/pci.h>9#include <linux/vmalloc.h>10#include <linux/delay.h>11#include <linux/interrupt.h>12#include <linux/bcma/bcma.h>13#include <linux/sched.h>14#include <linux/sched/signal.h>15#include <linux/kthread.h>16#include <linux/io.h>17#include <linux/random.h>18#include <linux/unaligned.h>1920#include <soc.h>21#include <chipcommon.h>22#include <brcmu_utils.h>23#include <brcmu_wifi.h>24#include <brcm_hw_ids.h>2526/* Custom brcmf_err() that takes bus arg and passes it further */27#define brcmf_err(bus, fmt, ...) \28do { \29if (IS_ENABLED(CONFIG_BRCMDBG) || \30IS_ENABLED(CONFIG_BRCM_TRACING) || \31net_ratelimit()) \32__brcmf_err(bus, __func__, fmt, ##__VA_ARGS__); \33} while (0)3435#include "debug.h"36#include "bus.h"37#include "commonring.h"38#include "msgbuf.h"39#include "pcie.h"40#include "firmware.h"41#include "chip.h"42#include "core.h"43#include "common.h"444546enum brcmf_pcie_state {47BRCMFMAC_PCIE_STATE_DOWN,48BRCMFMAC_PCIE_STATE_UP49};5051BRCMF_FW_DEF(43602, "brcmfmac43602-pcie");52BRCMF_FW_DEF(4350, "brcmfmac4350-pcie");53BRCMF_FW_DEF(4350C, "brcmfmac4350c2-pcie");54BRCMF_FW_CLM_DEF(4355, "brcmfmac4355-pcie");55BRCMF_FW_CLM_DEF(4355C1, "brcmfmac4355c1-pcie");56BRCMF_FW_CLM_DEF(4356, "brcmfmac4356-pcie");57BRCMF_FW_CLM_DEF(43570, "brcmfmac43570-pcie");58BRCMF_FW_DEF(4358, "brcmfmac4358-pcie");59BRCMF_FW_DEF(4359, "brcmfmac4359-pcie");60BRCMF_FW_DEF(4359C, "brcmfmac4359c-pcie");61BRCMF_FW_CLM_DEF(4364B2, "brcmfmac4364b2-pcie");62BRCMF_FW_CLM_DEF(4364B3, "brcmfmac4364b3-pcie");63BRCMF_FW_DEF(4365B, "brcmfmac4365b-pcie");64BRCMF_FW_DEF(4365C, "brcmfmac4365c-pcie");65BRCMF_FW_DEF(4366B, "brcmfmac4366b-pcie");66BRCMF_FW_DEF(4366C, "brcmfmac4366c-pcie");67BRCMF_FW_DEF(4371, "brcmfmac4371-pcie");68BRCMF_FW_CLM_DEF(43752, "brcmfmac43752-pcie");69BRCMF_FW_CLM_DEF(4377B3, "brcmfmac4377b3-pcie");70BRCMF_FW_CLM_DEF(4378B1, "brcmfmac4378b1-pcie");71BRCMF_FW_CLM_DEF(4378B3, "brcmfmac4378b3-pcie");72BRCMF_FW_CLM_DEF(4387C2, "brcmfmac4387c2-pcie");73BRCMF_FW_CLM_DEF(54591, "brcmfmac54591-pcie");7475/* firmware config files */76MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.txt");77MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.txt");7879/* per-board firmware binaries */80MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.bin");81MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.clm_blob");82MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.txcap_blob");8384static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {85BRCMF_FW_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602),86BRCMF_FW_ENTRY(BRCM_CC_43465_CHIP_ID, 0xFFFFFFF0, 4366C),87BRCMF_FW_ENTRY(BRCM_CC_4350_CHIP_ID, 0x000000FF, 4350C),88BRCMF_FW_ENTRY(BRCM_CC_4350_CHIP_ID, 0xFFFFFF00, 4350),89BRCMF_FW_ENTRY(BRCM_CC_43525_CHIP_ID, 0xFFFFFFF0, 4365C),90BRCMF_FW_ENTRY(BRCM_CC_4355_CHIP_ID, 0x000007FF, 4355),91BRCMF_FW_ENTRY(BRCM_CC_4355_CHIP_ID, 0x00002000, 54591),92BRCMF_FW_ENTRY(BRCM_CC_4355_CHIP_ID, 0xFFFFF800, 4355C1), /* rev ID 12/C2 seen */93BRCMF_FW_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356),94BRCMF_FW_ENTRY(BRCM_CC_43567_CHIP_ID, 0xFFFFFFFF, 43570),95BRCMF_FW_ENTRY(BRCM_CC_43569_CHIP_ID, 0xFFFFFFFF, 43570),96BRCMF_FW_ENTRY(BRCM_CC_43570_CHIP_ID, 0xFFFFFFFF, 43570),97BRCMF_FW_ENTRY(BRCM_CC_4358_CHIP_ID, 0xFFFFFFFF, 4358),98BRCMF_FW_ENTRY(BRCM_CC_4359_CHIP_ID, 0x000001FF, 4359),99BRCMF_FW_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFE00, 4359C),100BRCMF_FW_ENTRY(BRCM_CC_4364_CHIP_ID, 0x0000000F, 4364B2), /* 3 */101BRCMF_FW_ENTRY(BRCM_CC_4364_CHIP_ID, 0xFFFFFFF0, 4364B3), /* 4 */102BRCMF_FW_ENTRY(BRCM_CC_4365_CHIP_ID, 0x0000000F, 4365B),103BRCMF_FW_ENTRY(BRCM_CC_4365_CHIP_ID, 0xFFFFFFF0, 4365C),104BRCMF_FW_ENTRY(BRCM_CC_4366_CHIP_ID, 0x0000000F, 4366B),105BRCMF_FW_ENTRY(BRCM_CC_4366_CHIP_ID, 0xFFFFFFF0, 4366C),106BRCMF_FW_ENTRY(BRCM_CC_43664_CHIP_ID, 0xFFFFFFF0, 4366C),107BRCMF_FW_ENTRY(BRCM_CC_43666_CHIP_ID, 0xFFFFFFF0, 4366C),108BRCMF_FW_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371),109BRCMF_FW_ENTRY(BRCM_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752),110BRCMF_FW_ENTRY(BRCM_CC_4377_CHIP_ID, 0xFFFFFFFF, 4377B3), /* revision ID 4 */111BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0x0000000F, 4378B1), /* revision ID 3 */112BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0xFFFFFFE0, 4378B3), /* revision ID 5 */113BRCMF_FW_ENTRY(BRCM_CC_4387_CHIP_ID, 0xFFFFFFFF, 4387C2), /* revision ID 7 */114};115116#define BRCMF_PCIE_FW_UP_TIMEOUT 5000 /* msec */117118#define BRCMF_PCIE_REG_MAP_SIZE (32 * 1024)119120/* backplane addres space accessed by BAR0 */121#define BRCMF_PCIE_BAR0_WINDOW 0x80122#define BRCMF_PCIE_BAR0_REG_SIZE 0x1000123#define BRCMF_PCIE_BAR0_WRAPPERBASE 0x70124125#define BRCMF_PCIE_BAR0_WRAPBASE_DMP_OFFSET 0x1000126#define BRCMF_PCIE_BARO_PCIE_ENUM_OFFSET 0x2000127128#define BRCMF_PCIE_ARMCR4REG_BANKIDX 0x40129#define BRCMF_PCIE_ARMCR4REG_BANKPDA 0x4C130131#define BRCMF_PCIE_REG_INTSTATUS 0x90132#define BRCMF_PCIE_REG_INTMASK 0x94133#define BRCMF_PCIE_REG_SBMBX 0x98134135#define BRCMF_PCIE_REG_LINK_STATUS_CTRL 0xBC136137#define BRCMF_PCIE_PCIE2REG_INTMASK 0x24138#define BRCMF_PCIE_PCIE2REG_MAILBOXINT 0x48139#define BRCMF_PCIE_PCIE2REG_MAILBOXMASK 0x4C140#define BRCMF_PCIE_PCIE2REG_CONFIGADDR 0x120141#define BRCMF_PCIE_PCIE2REG_CONFIGDATA 0x124142#define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0 0x140143#define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1 0x144144145#define BRCMF_PCIE_64_PCIE2REG_INTMASK 0xC14146#define BRCMF_PCIE_64_PCIE2REG_MAILBOXINT 0xC30147#define BRCMF_PCIE_64_PCIE2REG_MAILBOXMASK 0xC34148#define BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0 0xA20149#define BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1 0xA24150151#define BRCMF_PCIE2_INTA 0x01152#define BRCMF_PCIE2_INTB 0x02153154#define BRCMF_PCIE_INT_0 0x01155#define BRCMF_PCIE_INT_1 0x02156#define BRCMF_PCIE_INT_DEF (BRCMF_PCIE_INT_0 | \157BRCMF_PCIE_INT_1)158159#define BRCMF_PCIE_MB_INT_FN0_0 0x0100160#define BRCMF_PCIE_MB_INT_FN0_1 0x0200161#define BRCMF_PCIE_MB_INT_D2H0_DB0 0x10000162#define BRCMF_PCIE_MB_INT_D2H0_DB1 0x20000163#define BRCMF_PCIE_MB_INT_D2H1_DB0 0x40000164#define BRCMF_PCIE_MB_INT_D2H1_DB1 0x80000165#define BRCMF_PCIE_MB_INT_D2H2_DB0 0x100000166#define BRCMF_PCIE_MB_INT_D2H2_DB1 0x200000167#define BRCMF_PCIE_MB_INT_D2H3_DB0 0x400000168#define BRCMF_PCIE_MB_INT_D2H3_DB1 0x800000169170#define BRCMF_PCIE_MB_INT_FN0 (BRCMF_PCIE_MB_INT_FN0_0 | \171BRCMF_PCIE_MB_INT_FN0_1)172#define BRCMF_PCIE_MB_INT_D2H_DB (BRCMF_PCIE_MB_INT_D2H0_DB0 | \173BRCMF_PCIE_MB_INT_D2H0_DB1 | \174BRCMF_PCIE_MB_INT_D2H1_DB0 | \175BRCMF_PCIE_MB_INT_D2H1_DB1 | \176BRCMF_PCIE_MB_INT_D2H2_DB0 | \177BRCMF_PCIE_MB_INT_D2H2_DB1 | \178BRCMF_PCIE_MB_INT_D2H3_DB0 | \179BRCMF_PCIE_MB_INT_D2H3_DB1)180181#define BRCMF_PCIE_64_MB_INT_D2H0_DB0 0x1182#define BRCMF_PCIE_64_MB_INT_D2H0_DB1 0x2183#define BRCMF_PCIE_64_MB_INT_D2H1_DB0 0x4184#define BRCMF_PCIE_64_MB_INT_D2H1_DB1 0x8185#define BRCMF_PCIE_64_MB_INT_D2H2_DB0 0x10186#define BRCMF_PCIE_64_MB_INT_D2H2_DB1 0x20187#define BRCMF_PCIE_64_MB_INT_D2H3_DB0 0x40188#define BRCMF_PCIE_64_MB_INT_D2H3_DB1 0x80189#define BRCMF_PCIE_64_MB_INT_D2H4_DB0 0x100190#define BRCMF_PCIE_64_MB_INT_D2H4_DB1 0x200191#define BRCMF_PCIE_64_MB_INT_D2H5_DB0 0x400192#define BRCMF_PCIE_64_MB_INT_D2H5_DB1 0x800193#define BRCMF_PCIE_64_MB_INT_D2H6_DB0 0x1000194#define BRCMF_PCIE_64_MB_INT_D2H6_DB1 0x2000195#define BRCMF_PCIE_64_MB_INT_D2H7_DB0 0x4000196#define BRCMF_PCIE_64_MB_INT_D2H7_DB1 0x8000197198#define BRCMF_PCIE_64_MB_INT_D2H_DB (BRCMF_PCIE_64_MB_INT_D2H0_DB0 | \199BRCMF_PCIE_64_MB_INT_D2H0_DB1 | \200BRCMF_PCIE_64_MB_INT_D2H1_DB0 | \201BRCMF_PCIE_64_MB_INT_D2H1_DB1 | \202BRCMF_PCIE_64_MB_INT_D2H2_DB0 | \203BRCMF_PCIE_64_MB_INT_D2H2_DB1 | \204BRCMF_PCIE_64_MB_INT_D2H3_DB0 | \205BRCMF_PCIE_64_MB_INT_D2H3_DB1 | \206BRCMF_PCIE_64_MB_INT_D2H4_DB0 | \207BRCMF_PCIE_64_MB_INT_D2H4_DB1 | \208BRCMF_PCIE_64_MB_INT_D2H5_DB0 | \209BRCMF_PCIE_64_MB_INT_D2H5_DB1 | \210BRCMF_PCIE_64_MB_INT_D2H6_DB0 | \211BRCMF_PCIE_64_MB_INT_D2H6_DB1 | \212BRCMF_PCIE_64_MB_INT_D2H7_DB0 | \213BRCMF_PCIE_64_MB_INT_D2H7_DB1)214215#define BRCMF_PCIE_SHARED_VERSION_7 7216#define BRCMF_PCIE_MIN_SHARED_VERSION 5217#define BRCMF_PCIE_MAX_SHARED_VERSION BRCMF_PCIE_SHARED_VERSION_7218#define BRCMF_PCIE_SHARED_VERSION_MASK 0x00FF219#define BRCMF_PCIE_SHARED_DMA_INDEX 0x10000220#define BRCMF_PCIE_SHARED_DMA_2B_IDX 0x100000221#define BRCMF_PCIE_SHARED_HOSTRDY_DB1 0x10000000222223#define BRCMF_PCIE_FLAGS_HTOD_SPLIT 0x4000224#define BRCMF_PCIE_FLAGS_DTOH_SPLIT 0x8000225226#define BRCMF_SHARED_MAX_RXBUFPOST_OFFSET 34227#define BRCMF_SHARED_RING_BASE_OFFSET 52228#define BRCMF_SHARED_RX_DATAOFFSET_OFFSET 36229#define BRCMF_SHARED_CONSOLE_ADDR_OFFSET 20230#define BRCMF_SHARED_HTOD_MB_DATA_ADDR_OFFSET 40231#define BRCMF_SHARED_DTOH_MB_DATA_ADDR_OFFSET 44232#define BRCMF_SHARED_RING_INFO_ADDR_OFFSET 48233#define BRCMF_SHARED_DMA_SCRATCH_LEN_OFFSET 52234#define BRCMF_SHARED_DMA_SCRATCH_ADDR_OFFSET 56235#define BRCMF_SHARED_DMA_RINGUPD_LEN_OFFSET 64236#define BRCMF_SHARED_DMA_RINGUPD_ADDR_OFFSET 68237238#define BRCMF_RING_H2D_RING_COUNT_OFFSET 0239#define BRCMF_RING_D2H_RING_COUNT_OFFSET 1240#define BRCMF_RING_H2D_RING_MEM_OFFSET 4241#define BRCMF_RING_H2D_RING_STATE_OFFSET 8242243#define BRCMF_RING_MEM_BASE_ADDR_OFFSET 8244#define BRCMF_RING_MAX_ITEM_OFFSET 4245#define BRCMF_RING_LEN_ITEMS_OFFSET 6246#define BRCMF_RING_MEM_SZ 16247#define BRCMF_RING_STATE_SZ 8248249#define BRCMF_DEF_MAX_RXBUFPOST 255250251#define BRCMF_CONSOLE_BUFADDR_OFFSET 8252#define BRCMF_CONSOLE_BUFSIZE_OFFSET 12253#define BRCMF_CONSOLE_WRITEIDX_OFFSET 16254255#define BRCMF_DMA_D2H_SCRATCH_BUF_LEN 8256#define BRCMF_DMA_D2H_RINGUPD_BUF_LEN 1024257258#define BRCMF_D2H_DEV_D3_ACK 0x00000001259#define BRCMF_D2H_DEV_DS_ENTER_REQ 0x00000002260#define BRCMF_D2H_DEV_DS_EXIT_NOTE 0x00000004261#define BRCMF_D2H_DEV_FWHALT 0x10000000262263#define BRCMF_H2D_HOST_D3_INFORM 0x00000001264#define BRCMF_H2D_HOST_DS_ACK 0x00000002265#define BRCMF_H2D_HOST_D0_INFORM_IN_USE 0x00000008266#define BRCMF_H2D_HOST_D0_INFORM 0x00000010267268#define BRCMF_PCIE_MBDATA_TIMEOUT msecs_to_jiffies(2000)269270#define BRCMF_PCIE_CFGREG_STATUS_CMD 0x4271#define BRCMF_PCIE_CFGREG_PM_CSR 0x4C272#define BRCMF_PCIE_CFGREG_MSI_CAP 0x58273#define BRCMF_PCIE_CFGREG_MSI_ADDR_L 0x5C274#define BRCMF_PCIE_CFGREG_MSI_ADDR_H 0x60275#define BRCMF_PCIE_CFGREG_MSI_DATA 0x64276#define BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL 0xBC277#define BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL2 0xDC278#define BRCMF_PCIE_CFGREG_RBAR_CTRL 0x228279#define BRCMF_PCIE_CFGREG_PML1_SUB_CTRL1 0x248280#define BRCMF_PCIE_CFGREG_REG_BAR2_CONFIG 0x4E0281#define BRCMF_PCIE_CFGREG_REG_BAR3_CONFIG 0x4F4282#define BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB 3283284/* Magic number at a magic location to find RAM size */285#define BRCMF_RAMSIZE_MAGIC 0x534d4152 /* SMAR */286#define BRCMF_RAMSIZE_OFFSET 0x6c287288289struct brcmf_pcie_console {290u32 base_addr;291u32 buf_addr;292u32 bufsize;293u32 read_idx;294u8 log_str[256];295u8 log_idx;296};297298struct brcmf_pcie_shared_info {299u32 tcm_base_address;300u32 flags;301struct brcmf_pcie_ringbuf *commonrings[BRCMF_NROF_COMMON_MSGRINGS];302struct brcmf_pcie_ringbuf *flowrings;303u16 max_rxbufpost;304u16 max_flowrings;305u16 max_submissionrings;306u16 max_completionrings;307u32 rx_dataoffset;308u32 htod_mb_data_addr;309u32 dtoh_mb_data_addr;310u32 ring_info_addr;311struct brcmf_pcie_console console;312void *scratch;313dma_addr_t scratch_dmahandle;314void *ringupd;315dma_addr_t ringupd_dmahandle;316u8 version;317};318319#define BRCMF_OTP_MAX_PARAM_LEN 16320321struct brcmf_otp_params {322char module[BRCMF_OTP_MAX_PARAM_LEN];323char vendor[BRCMF_OTP_MAX_PARAM_LEN];324char version[BRCMF_OTP_MAX_PARAM_LEN];325bool valid;326};327328struct brcmf_pciedev_info {329enum brcmf_pcie_state state;330bool in_irq;331struct pci_dev *pdev;332char fw_name[BRCMF_FW_NAME_LEN];333char nvram_name[BRCMF_FW_NAME_LEN];334char clm_name[BRCMF_FW_NAME_LEN];335char txcap_name[BRCMF_FW_NAME_LEN];336const struct firmware *clm_fw;337const struct firmware *txcap_fw;338const struct brcmf_pcie_reginfo *reginfo;339void __iomem *regs;340void __iomem *tcm;341u32 ram_base;342u32 ram_size;343struct brcmf_chip *ci;344u32 coreid;345struct brcmf_pcie_shared_info shared;346wait_queue_head_t mbdata_resp_wait;347bool mbdata_completed;348bool irq_allocated;349bool wowl_enabled;350u8 dma_idx_sz;351void *idxbuf;352u32 idxbuf_sz;353dma_addr_t idxbuf_dmahandle;354u16 (*read_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset);355void (*write_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset,356u16 value);357struct brcmf_mp_device *settings;358struct brcmf_otp_params otp;359bool fwseed;360#ifdef DEBUG361u32 console_interval;362bool console_active;363struct timer_list timer;364#endif365};366367struct brcmf_pcie_ringbuf {368struct brcmf_commonring commonring;369dma_addr_t dma_handle;370u32 w_idx_addr;371u32 r_idx_addr;372struct brcmf_pciedev_info *devinfo;373u8 id;374};375376/**377* struct brcmf_pcie_dhi_ringinfo - dongle/host interface shared ring info378*379* @ringmem: dongle memory pointer to ring memory location380* @h2d_w_idx_ptr: h2d ring write indices dongle memory pointers381* @h2d_r_idx_ptr: h2d ring read indices dongle memory pointers382* @d2h_w_idx_ptr: d2h ring write indices dongle memory pointers383* @d2h_r_idx_ptr: d2h ring read indices dongle memory pointers384* @h2d_w_idx_hostaddr: h2d ring write indices host memory pointers385* @h2d_r_idx_hostaddr: h2d ring read indices host memory pointers386* @d2h_w_idx_hostaddr: d2h ring write indices host memory pointers387* @d2h_r_idx_hostaddr: d2h ring reaD indices host memory pointers388* @max_flowrings: maximum number of tx flow rings supported.389* @max_submissionrings: maximum number of submission rings(h2d) supported.390* @max_completionrings: maximum number of completion rings(d2h) supported.391*/392struct brcmf_pcie_dhi_ringinfo {393__le32 ringmem;394__le32 h2d_w_idx_ptr;395__le32 h2d_r_idx_ptr;396__le32 d2h_w_idx_ptr;397__le32 d2h_r_idx_ptr;398struct msgbuf_buf_addr h2d_w_idx_hostaddr;399struct msgbuf_buf_addr h2d_r_idx_hostaddr;400struct msgbuf_buf_addr d2h_w_idx_hostaddr;401struct msgbuf_buf_addr d2h_r_idx_hostaddr;402__le16 max_flowrings;403__le16 max_submissionrings;404__le16 max_completionrings;405};406407static const u32 brcmf_ring_max_item[BRCMF_NROF_COMMON_MSGRINGS] = {408BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM,409BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM,410BRCMF_D2H_MSGRING_CONTROL_COMPLETE_MAX_ITEM,411BRCMF_D2H_MSGRING_TX_COMPLETE_MAX_ITEM,412BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM413};414415static const u32 brcmf_ring_itemsize_pre_v7[BRCMF_NROF_COMMON_MSGRINGS] = {416BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE,417BRCMF_H2D_MSGRING_RXPOST_SUBMIT_ITEMSIZE,418BRCMF_D2H_MSGRING_CONTROL_COMPLETE_ITEMSIZE,419BRCMF_D2H_MSGRING_TX_COMPLETE_ITEMSIZE_PRE_V7,420BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE_PRE_V7421};422423static const u32 brcmf_ring_itemsize[BRCMF_NROF_COMMON_MSGRINGS] = {424BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE,425BRCMF_H2D_MSGRING_RXPOST_SUBMIT_ITEMSIZE,426BRCMF_D2H_MSGRING_CONTROL_COMPLETE_ITEMSIZE,427BRCMF_D2H_MSGRING_TX_COMPLETE_ITEMSIZE,428BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE429};430431struct brcmf_pcie_reginfo {432u32 intmask;433u32 mailboxint;434u32 mailboxmask;435u32 h2d_mailbox_0;436u32 h2d_mailbox_1;437u32 int_d2h_db;438u32 int_fn0;439};440441static const struct brcmf_pcie_reginfo brcmf_reginfo_default = {442.intmask = BRCMF_PCIE_PCIE2REG_INTMASK,443.mailboxint = BRCMF_PCIE_PCIE2REG_MAILBOXINT,444.mailboxmask = BRCMF_PCIE_PCIE2REG_MAILBOXMASK,445.h2d_mailbox_0 = BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0,446.h2d_mailbox_1 = BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1,447.int_d2h_db = BRCMF_PCIE_MB_INT_D2H_DB,448.int_fn0 = BRCMF_PCIE_MB_INT_FN0,449};450451static const struct brcmf_pcie_reginfo brcmf_reginfo_64 = {452.intmask = BRCMF_PCIE_64_PCIE2REG_INTMASK,453.mailboxint = BRCMF_PCIE_64_PCIE2REG_MAILBOXINT,454.mailboxmask = BRCMF_PCIE_64_PCIE2REG_MAILBOXMASK,455.h2d_mailbox_0 = BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0,456.h2d_mailbox_1 = BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1,457.int_d2h_db = BRCMF_PCIE_64_MB_INT_D2H_DB,458.int_fn0 = 0,459};460461static void brcmf_pcie_setup(struct device *dev, int ret,462struct brcmf_fw_request *fwreq);463static struct brcmf_fw_request *464brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo);465static void466brcmf_pcie_fwcon_timer(struct brcmf_pciedev_info *devinfo, bool active);467static void brcmf_pcie_debugfs_create(struct device *dev);468469#if defined(__FreeBSD__)470#define VPAA(_x, _a) (void __iomem *)((uintptr_t)(_x) + (_a))471#endif472473static u16474brcmf_pcie_read_reg16(struct brcmf_pciedev_info *devinfo, u32 reg_offset)475{476#if defined(__linux__)477void __iomem *address = devinfo->regs + reg_offset;478#elif defined(__FreeBSD__)479void __iomem *address = VPAA(devinfo->regs, reg_offset);480#endif481482return ioread16(address);483}484485static u32486brcmf_pcie_read_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset)487{488#if defined(__linux__)489void __iomem *address = devinfo->regs + reg_offset;490#elif defined(__FreeBSD__)491void __iomem *address = VPAA(devinfo->regs, reg_offset);492#endif493494return (ioread32(address));495}496497498static void499brcmf_pcie_write_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset,500u32 value)501{502#if defined(__linux__)503void __iomem *address = devinfo->regs + reg_offset;504#elif defined(__FreeBSD__)505void __iomem *address = VPAA(devinfo->regs, reg_offset);506#endif507508iowrite32(value, address);509}510511512static u8513brcmf_pcie_read_tcm8(struct brcmf_pciedev_info *devinfo, u32 mem_offset)514{515#if defined(__linux__)516void __iomem *address = devinfo->tcm + mem_offset;517#elif defined(__FreeBSD__)518void __iomem *address = VPAA(devinfo->tcm, mem_offset);519#endif520521return (ioread8(address));522}523524525static u16526brcmf_pcie_read_tcm16(struct brcmf_pciedev_info *devinfo, u32 mem_offset)527{528#if defined(__linux__)529void __iomem *address = devinfo->tcm + mem_offset;530#elif defined(__FreeBSD__)531void __iomem *address = VPAA(devinfo->tcm, mem_offset);532#endif533534return (ioread16(address));535}536537538static void539brcmf_pcie_write_tcm16(struct brcmf_pciedev_info *devinfo, u32 mem_offset,540u16 value)541{542#if defined(__linux__)543void __iomem *address = devinfo->tcm + mem_offset;544#elif defined(__FreeBSD__)545void __iomem *address = VPAA(devinfo->tcm, mem_offset);546#endif547548iowrite16(value, address);549}550551552static u16553brcmf_pcie_read_idx(struct brcmf_pciedev_info *devinfo, u32 mem_offset)554{555#if defined(__linux__)556u16 *address = devinfo->idxbuf + mem_offset;557#elif defined(__FreeBSD__)558u16 *address = (void *)((uintptr_t)devinfo->idxbuf + mem_offset);559#endif560561return (*(address));562}563564565static void566brcmf_pcie_write_idx(struct brcmf_pciedev_info *devinfo, u32 mem_offset,567u16 value)568{569#if defined(__linux__)570u16 *address = devinfo->idxbuf + mem_offset;571#elif defined(__FreeBSD__)572u16 *address = (void *)((uintptr_t)devinfo->idxbuf + mem_offset);573#endif574575*(address) = value;576}577578579static u32580brcmf_pcie_read_tcm32(struct brcmf_pciedev_info *devinfo, u32 mem_offset)581{582#if defined(__linux__)583void __iomem *address = devinfo->tcm + mem_offset;584#elif defined(__FreeBSD__)585void __iomem *address = VPAA(devinfo->tcm, mem_offset);586#endif587588return (ioread32(address));589}590591592static void593brcmf_pcie_write_tcm32(struct brcmf_pciedev_info *devinfo, u32 mem_offset,594u32 value)595{596#if defined(__linux__)597void __iomem *address = devinfo->tcm + mem_offset;598#elif defined(__FreeBSD__)599void __iomem *address = VPAA(devinfo->tcm, mem_offset);600#endif601602iowrite32(value, address);603}604605606static u32607brcmf_pcie_read_ram32(struct brcmf_pciedev_info *devinfo, u32 mem_offset)608{609#if defined(__linux__)610void __iomem *addr = devinfo->tcm + devinfo->ci->rambase + mem_offset;611#elif defined(__FreeBSD__)612void __iomem *addr = VPAA(devinfo->tcm, devinfo->ci->rambase + mem_offset);613#endif614615return (ioread32(addr));616}617618619static void620brcmf_pcie_write_ram32(struct brcmf_pciedev_info *devinfo, u32 mem_offset,621u32 value)622{623#if defined(__linux__)624void __iomem *addr = devinfo->tcm + devinfo->ci->rambase + mem_offset;625#elif defined(__FreeBSD__)626void __iomem *addr = VPAA(devinfo->tcm, devinfo->ci->rambase + mem_offset);627#endif628629iowrite32(value, addr);630}631632633static void634brcmf_pcie_copy_dev_tomem(struct brcmf_pciedev_info *devinfo, u32 mem_offset,635void *dstaddr, u32 len)636{637#if defined(__linux__)638void __iomem *address = devinfo->tcm + mem_offset;639#elif defined(__FreeBSD__)640u8 __iomem *address = (void *)((uintptr_t)devinfo->tcm + mem_offset);641#endif642__le32 *dst32;643__le16 *dst16;644u8 *dst8;645646if (((ulong)address & 4) || ((ulong)dstaddr & 4) || (len & 4)) {647if (((ulong)address & 2) || ((ulong)dstaddr & 2) || (len & 2)) {648dst8 = (u8 *)dstaddr;649while (len) {650*dst8 = ioread8(address);651address++;652dst8++;653len--;654}655} else {656len = len / 2;657dst16 = (__le16 *)dstaddr;658while (len) {659*dst16 = cpu_to_le16(ioread16(address));660address += 2;661dst16++;662len--;663}664}665} else {666len = len / 4;667dst32 = (__le32 *)dstaddr;668while (len) {669*dst32 = cpu_to_le32(ioread32(address));670address += 4;671dst32++;672len--;673}674}675}676677678#define READCC32(devinfo, reg) brcmf_pcie_read_reg32(devinfo, \679CHIPCREGOFFS(reg))680#define WRITECC32(devinfo, reg, value) brcmf_pcie_write_reg32(devinfo, \681CHIPCREGOFFS(reg), value)682683684static void685brcmf_pcie_select_core(struct brcmf_pciedev_info *devinfo, u16 coreid)686{687const struct pci_dev *pdev = devinfo->pdev;688struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);689struct brcmf_core *core;690u32 bar0_win;691692core = brcmf_chip_get_core(devinfo->ci, coreid);693if (core) {694bar0_win = core->base;695pci_write_config_dword(pdev, BRCMF_PCIE_BAR0_WINDOW, bar0_win);696if (pci_read_config_dword(pdev, BRCMF_PCIE_BAR0_WINDOW,697&bar0_win) == 0) {698if (bar0_win != core->base) {699bar0_win = core->base;700pci_write_config_dword(pdev,701BRCMF_PCIE_BAR0_WINDOW,702bar0_win);703}704}705} else {706brcmf_err(bus, "Unsupported core selected %x\n", coreid);707}708}709710711static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo)712{713struct brcmf_core *core;714static const u16 cfg_offset[] = {715BRCMF_PCIE_CFGREG_STATUS_CMD,716BRCMF_PCIE_CFGREG_PM_CSR,717BRCMF_PCIE_CFGREG_MSI_CAP,718BRCMF_PCIE_CFGREG_MSI_ADDR_L,719BRCMF_PCIE_CFGREG_MSI_ADDR_H,720BRCMF_PCIE_CFGREG_MSI_DATA,721BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL2,722BRCMF_PCIE_CFGREG_RBAR_CTRL,723BRCMF_PCIE_CFGREG_PML1_SUB_CTRL1,724BRCMF_PCIE_CFGREG_REG_BAR2_CONFIG,725BRCMF_PCIE_CFGREG_REG_BAR3_CONFIG726};727u32 i;728u32 val;729u32 lsc;730731if (!devinfo->ci)732return;733734/* Disable ASPM */735brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);736pci_read_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,737&lsc);738val = lsc & (~BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB);739pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,740val);741742/* Watchdog reset */743brcmf_pcie_select_core(devinfo, BCMA_CORE_CHIPCOMMON);744WRITECC32(devinfo, watchdog, 4);745#if defined(__linux__)746msleep(100);747#elif defined(__FreeBSD__)748linux_msleep(100);749#endif750751/* Restore ASPM */752brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);753pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,754lsc);755756core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2);757if (core->rev <= 13) {758for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) {759brcmf_pcie_write_reg32(devinfo,760BRCMF_PCIE_PCIE2REG_CONFIGADDR,761cfg_offset[i]);762val = brcmf_pcie_read_reg32(devinfo,763BRCMF_PCIE_PCIE2REG_CONFIGDATA);764brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n",765cfg_offset[i], val);766brcmf_pcie_write_reg32(devinfo,767BRCMF_PCIE_PCIE2REG_CONFIGDATA,768val);769}770}771}772773774static void brcmf_pcie_attach(struct brcmf_pciedev_info *devinfo)775{776u32 config;777778/* BAR1 window may not be sized properly */779brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);780brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);781config = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA);782brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, config);783784device_wakeup_enable(&devinfo->pdev->dev);785}786787788static int brcmf_pcie_enter_download_state(struct brcmf_pciedev_info *devinfo)789{790if (devinfo->ci->chip == BRCM_CC_43602_CHIP_ID) {791brcmf_pcie_select_core(devinfo, BCMA_CORE_ARM_CR4);792brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKIDX,7935);794brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKPDA,7950);796brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKIDX,7977);798brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKPDA,7990);800}801return 0;802}803804805static int brcmf_pcie_exit_download_state(struct brcmf_pciedev_info *devinfo,806u32 resetintr)807{808struct brcmf_core *core;809810if (devinfo->ci->chip == BRCM_CC_43602_CHIP_ID) {811core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_INTERNAL_MEM);812brcmf_chip_resetcore(core, 0, 0, 0);813}814815if (!brcmf_chip_set_active(devinfo->ci, resetintr))816return -EIO;817return 0;818}819820821static int822brcmf_pcie_send_mb_data(struct brcmf_pciedev_info *devinfo, u32 htod_mb_data)823{824struct brcmf_pcie_shared_info *shared;825struct brcmf_core *core;826u32 addr;827u32 cur_htod_mb_data;828u32 i;829830shared = &devinfo->shared;831addr = shared->htod_mb_data_addr;832cur_htod_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);833834if (cur_htod_mb_data != 0)835brcmf_dbg(PCIE, "MB transaction is already pending 0x%04x\n",836cur_htod_mb_data);837838i = 0;839while (cur_htod_mb_data != 0) {840#if defined(__linux__)841msleep(10);842#elif defined(__FreeBSD__)843linux_msleep(10);844#endif845i++;846if (i > 100)847return -EIO;848cur_htod_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);849}850851brcmf_pcie_write_tcm32(devinfo, addr, htod_mb_data);852pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_SBMBX, 1);853854/* Send mailbox interrupt twice as a hardware workaround */855core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2);856if (core->rev <= 13)857pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_SBMBX, 1);858859return 0;860}861862863static void brcmf_pcie_handle_mb_data(struct brcmf_pciedev_info *devinfo)864{865struct brcmf_pcie_shared_info *shared;866u32 addr;867u32 dtoh_mb_data;868869shared = &devinfo->shared;870addr = shared->dtoh_mb_data_addr;871dtoh_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);872873if (!dtoh_mb_data)874return;875876brcmf_pcie_write_tcm32(devinfo, addr, 0);877878brcmf_dbg(PCIE, "D2H_MB_DATA: 0x%04x\n", dtoh_mb_data);879if (dtoh_mb_data & BRCMF_D2H_DEV_DS_ENTER_REQ) {880brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP REQ\n");881brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_DS_ACK);882brcmf_dbg(PCIE, "D2H_MB_DATA: sent DEEP SLEEP ACK\n");883}884if (dtoh_mb_data & BRCMF_D2H_DEV_DS_EXIT_NOTE)885brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP EXIT\n");886if (dtoh_mb_data & BRCMF_D2H_DEV_D3_ACK) {887brcmf_dbg(PCIE, "D2H_MB_DATA: D3 ACK\n");888devinfo->mbdata_completed = true;889wake_up(&devinfo->mbdata_resp_wait);890}891if (dtoh_mb_data & BRCMF_D2H_DEV_FWHALT) {892brcmf_dbg(PCIE, "D2H_MB_DATA: FW HALT\n");893brcmf_fw_crashed(&devinfo->pdev->dev);894}895}896897898static void brcmf_pcie_bus_console_init(struct brcmf_pciedev_info *devinfo)899{900struct brcmf_pcie_shared_info *shared;901struct brcmf_pcie_console *console;902u32 addr;903904shared = &devinfo->shared;905console = &shared->console;906addr = shared->tcm_base_address + BRCMF_SHARED_CONSOLE_ADDR_OFFSET;907console->base_addr = brcmf_pcie_read_tcm32(devinfo, addr);908909addr = console->base_addr + BRCMF_CONSOLE_BUFADDR_OFFSET;910console->buf_addr = brcmf_pcie_read_tcm32(devinfo, addr);911addr = console->base_addr + BRCMF_CONSOLE_BUFSIZE_OFFSET;912console->bufsize = brcmf_pcie_read_tcm32(devinfo, addr);913914brcmf_dbg(FWCON, "Console: base %x, buf %x, size %d\n",915console->base_addr, console->buf_addr, console->bufsize);916}917918/**919* brcmf_pcie_bus_console_read - reads firmware messages920*921* @devinfo: pointer to the device data structure922* @error: specifies if error has occurred (prints messages unconditionally)923*/924static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo,925bool error)926{927struct pci_dev *pdev = devinfo->pdev;928struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);929struct brcmf_pcie_console *console;930u32 addr;931u8 ch;932u32 newidx;933934if (!error && !BRCMF_FWCON_ON())935return;936937console = &devinfo->shared.console;938if (!console->base_addr)939return;940addr = console->base_addr + BRCMF_CONSOLE_WRITEIDX_OFFSET;941newidx = brcmf_pcie_read_tcm32(devinfo, addr);942while (newidx != console->read_idx) {943addr = console->buf_addr + console->read_idx;944ch = brcmf_pcie_read_tcm8(devinfo, addr);945console->read_idx++;946if (console->read_idx == console->bufsize)947console->read_idx = 0;948if (ch == '\r')949continue;950console->log_str[console->log_idx] = ch;951console->log_idx++;952if ((ch != '\n') &&953(console->log_idx == (sizeof(console->log_str) - 2))) {954ch = '\n';955console->log_str[console->log_idx] = ch;956console->log_idx++;957}958if (ch == '\n') {959console->log_str[console->log_idx] = 0;960if (error)961__brcmf_err(bus, __func__, "CONSOLE: %s",962console->log_str);963else964pr_debug("CONSOLE: %s", console->log_str);965console->log_idx = 0;966}967}968}969970971static void brcmf_pcie_intr_disable(struct brcmf_pciedev_info *devinfo)972{973brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask, 0);974}975976977static void brcmf_pcie_intr_enable(struct brcmf_pciedev_info *devinfo)978{979brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask,980devinfo->reginfo->int_d2h_db |981devinfo->reginfo->int_fn0);982}983984static void brcmf_pcie_hostready(struct brcmf_pciedev_info *devinfo)985{986if (devinfo->shared.flags & BRCMF_PCIE_SHARED_HOSTRDY_DB1)987brcmf_pcie_write_reg32(devinfo,988devinfo->reginfo->h2d_mailbox_1, 1);989}990991static irqreturn_t brcmf_pcie_quick_check_isr(int irq, void *arg)992{993struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;994995if (brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint)) {996brcmf_pcie_intr_disable(devinfo);997brcmf_dbg(PCIE, "Enter\n");998return IRQ_WAKE_THREAD;999}1000return IRQ_NONE;1001}100210031004static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg)1005{1006struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;1007u32 status;10081009devinfo->in_irq = true;1010status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint);1011brcmf_dbg(PCIE, "Enter %x\n", status);1012if (status) {1013brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint,1014status);1015if (status & devinfo->reginfo->int_fn0)1016brcmf_pcie_handle_mb_data(devinfo);1017if (status & devinfo->reginfo->int_d2h_db) {1018if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)1019brcmf_proto_msgbuf_rx_trigger(1020&devinfo->pdev->dev);1021}1022}1023brcmf_pcie_bus_console_read(devinfo, false);1024if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)1025brcmf_pcie_intr_enable(devinfo);1026devinfo->in_irq = false;1027return IRQ_HANDLED;1028}102910301031static int brcmf_pcie_request_irq(struct brcmf_pciedev_info *devinfo)1032{1033struct pci_dev *pdev = devinfo->pdev;1034struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);10351036brcmf_pcie_intr_disable(devinfo);10371038brcmf_dbg(PCIE, "Enter\n");10391040pci_enable_msi(pdev);1041if (request_threaded_irq(pdev->irq, brcmf_pcie_quick_check_isr,1042brcmf_pcie_isr_thread, IRQF_SHARED,1043"brcmf_pcie_intr", devinfo)) {1044pci_disable_msi(pdev);1045brcmf_err(bus, "Failed to request IRQ %d\n", pdev->irq);1046return -EIO;1047}1048devinfo->irq_allocated = true;1049return 0;1050}105110521053static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo)1054{1055struct pci_dev *pdev = devinfo->pdev;1056struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);1057u32 status;1058u32 count;10591060if (!devinfo->irq_allocated)1061return;10621063brcmf_pcie_intr_disable(devinfo);1064free_irq(pdev->irq, devinfo);1065pci_disable_msi(pdev);10661067#if defined(__linux__)1068msleep(50);1069#elif defined(__FreeBSD__)1070linux_msleep(50);1071#endif1072count = 0;1073while ((devinfo->in_irq) && (count < 20)) {1074#if defined(__linux__)1075msleep(50);1076#elif defined(__FreeBSD__)1077linux_msleep(50);1078#endif1079count++;1080}1081if (devinfo->in_irq)1082brcmf_err(bus, "Still in IRQ (processing) !!!\n");10831084status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint);1085brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint, status);10861087devinfo->irq_allocated = false;1088}108910901091static int brcmf_pcie_ring_mb_write_rptr(void *ctx)1092{1093struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;1094struct brcmf_pciedev_info *devinfo = ring->devinfo;1095struct brcmf_commonring *commonring = &ring->commonring;10961097if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)1098return -EIO;10991100brcmf_dbg(PCIE, "W r_ptr %d (%d), ring %d\n", commonring->r_ptr,1101commonring->w_ptr, ring->id);11021103devinfo->write_ptr(devinfo, ring->r_idx_addr, commonring->r_ptr);11041105return 0;1106}110711081109static int brcmf_pcie_ring_mb_write_wptr(void *ctx)1110{1111struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;1112struct brcmf_pciedev_info *devinfo = ring->devinfo;1113struct brcmf_commonring *commonring = &ring->commonring;11141115if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)1116return -EIO;11171118brcmf_dbg(PCIE, "W w_ptr %d (%d), ring %d\n", commonring->w_ptr,1119commonring->r_ptr, ring->id);11201121devinfo->write_ptr(devinfo, ring->w_idx_addr, commonring->w_ptr);11221123return 0;1124}112511261127static int brcmf_pcie_ring_mb_ring_bell(void *ctx)1128{1129struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;1130struct brcmf_pciedev_info *devinfo = ring->devinfo;11311132if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)1133return -EIO;11341135brcmf_dbg(PCIE, "RING !\n");1136/* Any arbitrary value will do, lets use 1 */1137brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->h2d_mailbox_0, 1);11381139return 0;1140}114111421143static int brcmf_pcie_ring_mb_update_rptr(void *ctx)1144{1145struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;1146struct brcmf_pciedev_info *devinfo = ring->devinfo;1147struct brcmf_commonring *commonring = &ring->commonring;11481149if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)1150return -EIO;11511152commonring->r_ptr = devinfo->read_ptr(devinfo, ring->r_idx_addr);11531154brcmf_dbg(PCIE, "R r_ptr %d (%d), ring %d\n", commonring->r_ptr,1155commonring->w_ptr, ring->id);11561157return 0;1158}115911601161static int brcmf_pcie_ring_mb_update_wptr(void *ctx)1162{1163struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;1164struct brcmf_pciedev_info *devinfo = ring->devinfo;1165struct brcmf_commonring *commonring = &ring->commonring;11661167if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)1168return -EIO;11691170commonring->w_ptr = devinfo->read_ptr(devinfo, ring->w_idx_addr);11711172brcmf_dbg(PCIE, "R w_ptr %d (%d), ring %d\n", commonring->w_ptr,1173commonring->r_ptr, ring->id);11741175return 0;1176}117711781179static void *1180brcmf_pcie_init_dmabuffer_for_device(struct brcmf_pciedev_info *devinfo,1181u32 size, u32 tcm_dma_phys_addr,1182dma_addr_t *dma_handle)1183{1184void *ring;1185u64 address;11861187ring = dma_alloc_coherent(&devinfo->pdev->dev, size, dma_handle,1188GFP_KERNEL);1189if (!ring)1190return NULL;11911192address = (u64)*dma_handle;1193brcmf_pcie_write_tcm32(devinfo, tcm_dma_phys_addr,1194address & 0xffffffff);1195brcmf_pcie_write_tcm32(devinfo, tcm_dma_phys_addr + 4, address >> 32);11961197return (ring);1198}119912001201static struct brcmf_pcie_ringbuf *1202brcmf_pcie_alloc_dma_and_ring(struct brcmf_pciedev_info *devinfo, u32 ring_id,1203u32 tcm_ring_phys_addr)1204{1205void *dma_buf;1206dma_addr_t dma_handle;1207struct brcmf_pcie_ringbuf *ring;1208u32 size;1209u32 addr;1210const u32 *ring_itemsize_array;12111212if (devinfo->shared.version < BRCMF_PCIE_SHARED_VERSION_7)1213ring_itemsize_array = brcmf_ring_itemsize_pre_v7;1214else1215ring_itemsize_array = brcmf_ring_itemsize;12161217size = brcmf_ring_max_item[ring_id] * ring_itemsize_array[ring_id];1218dma_buf = brcmf_pcie_init_dmabuffer_for_device(devinfo, size,1219tcm_ring_phys_addr + BRCMF_RING_MEM_BASE_ADDR_OFFSET,1220&dma_handle);1221if (!dma_buf)1222return NULL;12231224addr = tcm_ring_phys_addr + BRCMF_RING_MAX_ITEM_OFFSET;1225brcmf_pcie_write_tcm16(devinfo, addr, brcmf_ring_max_item[ring_id]);1226addr = tcm_ring_phys_addr + BRCMF_RING_LEN_ITEMS_OFFSET;1227brcmf_pcie_write_tcm16(devinfo, addr, ring_itemsize_array[ring_id]);12281229ring = kzalloc(sizeof(*ring), GFP_KERNEL);1230if (!ring) {1231dma_free_coherent(&devinfo->pdev->dev, size, dma_buf,1232dma_handle);1233return NULL;1234}1235brcmf_commonring_config(&ring->commonring, brcmf_ring_max_item[ring_id],1236ring_itemsize_array[ring_id], dma_buf);1237ring->dma_handle = dma_handle;1238ring->devinfo = devinfo;1239brcmf_commonring_register_cb(&ring->commonring,1240brcmf_pcie_ring_mb_ring_bell,1241brcmf_pcie_ring_mb_update_rptr,1242brcmf_pcie_ring_mb_update_wptr,1243brcmf_pcie_ring_mb_write_rptr,1244brcmf_pcie_ring_mb_write_wptr, ring);12451246return (ring);1247}124812491250static void brcmf_pcie_release_ringbuffer(struct device *dev,1251struct brcmf_pcie_ringbuf *ring)1252{1253void *dma_buf;1254u32 size;12551256if (!ring)1257return;12581259dma_buf = ring->commonring.buf_addr;1260if (dma_buf) {1261size = ring->commonring.depth * ring->commonring.item_len;1262dma_free_coherent(dev, size, dma_buf, ring->dma_handle);1263}1264kfree(ring);1265}126612671268static void brcmf_pcie_release_ringbuffers(struct brcmf_pciedev_info *devinfo)1269{1270u32 i;12711272for (i = 0; i < BRCMF_NROF_COMMON_MSGRINGS; i++) {1273brcmf_pcie_release_ringbuffer(&devinfo->pdev->dev,1274devinfo->shared.commonrings[i]);1275devinfo->shared.commonrings[i] = NULL;1276}1277kfree(devinfo->shared.flowrings);1278devinfo->shared.flowrings = NULL;1279if (devinfo->idxbuf) {1280dma_free_coherent(&devinfo->pdev->dev,1281devinfo->idxbuf_sz,1282devinfo->idxbuf,1283devinfo->idxbuf_dmahandle);1284devinfo->idxbuf = NULL;1285}1286}128712881289static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)1290{1291struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev);1292struct brcmf_pcie_ringbuf *ring;1293struct brcmf_pcie_ringbuf *rings;1294u32 d2h_w_idx_ptr;1295u32 d2h_r_idx_ptr;1296u32 h2d_w_idx_ptr;1297u32 h2d_r_idx_ptr;1298u32 ring_mem_ptr;1299u32 i;1300u64 address;1301u32 bufsz;1302u8 idx_offset;1303struct brcmf_pcie_dhi_ringinfo ringinfo;1304u16 max_flowrings;1305u16 max_submissionrings;1306u16 max_completionrings;13071308#if defined(__linux__)1309memcpy_fromio(&ringinfo, devinfo->tcm + devinfo->shared.ring_info_addr,1310#elif defined(__FreeBSD__)1311memcpy_fromio(&ringinfo, (void *)((uintptr_t)devinfo->tcm + devinfo->shared.ring_info_addr),1312#endif1313sizeof(ringinfo));1314if (devinfo->shared.version >= 6) {1315max_submissionrings = le16_to_cpu(ringinfo.max_submissionrings);1316max_flowrings = le16_to_cpu(ringinfo.max_flowrings);1317max_completionrings = le16_to_cpu(ringinfo.max_completionrings);1318} else {1319max_submissionrings = le16_to_cpu(ringinfo.max_flowrings);1320max_flowrings = max_submissionrings -1321BRCMF_NROF_H2D_COMMON_MSGRINGS;1322max_completionrings = BRCMF_NROF_D2H_COMMON_MSGRINGS;1323}1324if (max_flowrings > 512) {1325brcmf_err(bus, "invalid max_flowrings(%d)\n", max_flowrings);1326return -EIO;1327}13281329if (devinfo->dma_idx_sz != 0) {1330bufsz = (max_submissionrings + max_completionrings) *1331devinfo->dma_idx_sz * 2;1332devinfo->idxbuf = dma_alloc_coherent(&devinfo->pdev->dev, bufsz,1333&devinfo->idxbuf_dmahandle,1334GFP_KERNEL);1335if (!devinfo->idxbuf)1336devinfo->dma_idx_sz = 0;1337}13381339if (devinfo->dma_idx_sz == 0) {1340d2h_w_idx_ptr = le32_to_cpu(ringinfo.d2h_w_idx_ptr);1341d2h_r_idx_ptr = le32_to_cpu(ringinfo.d2h_r_idx_ptr);1342h2d_w_idx_ptr = le32_to_cpu(ringinfo.h2d_w_idx_ptr);1343h2d_r_idx_ptr = le32_to_cpu(ringinfo.h2d_r_idx_ptr);1344idx_offset = sizeof(u32);1345devinfo->write_ptr = brcmf_pcie_write_tcm16;1346devinfo->read_ptr = brcmf_pcie_read_tcm16;1347brcmf_dbg(PCIE, "Using TCM indices\n");1348} else {1349memset(devinfo->idxbuf, 0, bufsz);1350devinfo->idxbuf_sz = bufsz;1351idx_offset = devinfo->dma_idx_sz;1352devinfo->write_ptr = brcmf_pcie_write_idx;1353devinfo->read_ptr = brcmf_pcie_read_idx;13541355h2d_w_idx_ptr = 0;1356address = (u64)devinfo->idxbuf_dmahandle;1357ringinfo.h2d_w_idx_hostaddr.low_addr =1358cpu_to_le32(address & 0xffffffff);1359ringinfo.h2d_w_idx_hostaddr.high_addr =1360cpu_to_le32(address >> 32);13611362h2d_r_idx_ptr = h2d_w_idx_ptr +1363max_submissionrings * idx_offset;1364address += max_submissionrings * idx_offset;1365ringinfo.h2d_r_idx_hostaddr.low_addr =1366cpu_to_le32(address & 0xffffffff);1367ringinfo.h2d_r_idx_hostaddr.high_addr =1368cpu_to_le32(address >> 32);13691370d2h_w_idx_ptr = h2d_r_idx_ptr +1371max_submissionrings * idx_offset;1372address += max_submissionrings * idx_offset;1373ringinfo.d2h_w_idx_hostaddr.low_addr =1374cpu_to_le32(address & 0xffffffff);1375ringinfo.d2h_w_idx_hostaddr.high_addr =1376cpu_to_le32(address >> 32);13771378d2h_r_idx_ptr = d2h_w_idx_ptr +1379max_completionrings * idx_offset;1380address += max_completionrings * idx_offset;1381ringinfo.d2h_r_idx_hostaddr.low_addr =1382cpu_to_le32(address & 0xffffffff);1383ringinfo.d2h_r_idx_hostaddr.high_addr =1384cpu_to_le32(address >> 32);13851386#if defined(__linux__)1387memcpy_toio(devinfo->tcm + devinfo->shared.ring_info_addr,1388#elif defined(__FreeBSD__)1389memcpy_toio((void *)((uintptr_t)devinfo->tcm + devinfo->shared.ring_info_addr),1390#endif1391&ringinfo, sizeof(ringinfo));1392brcmf_dbg(PCIE, "Using host memory indices\n");1393}13941395ring_mem_ptr = le32_to_cpu(ringinfo.ringmem);13961397for (i = 0; i < BRCMF_NROF_H2D_COMMON_MSGRINGS; i++) {1398ring = brcmf_pcie_alloc_dma_and_ring(devinfo, i, ring_mem_ptr);1399if (!ring)1400goto fail;1401ring->w_idx_addr = h2d_w_idx_ptr;1402ring->r_idx_addr = h2d_r_idx_ptr;1403ring->id = i;1404devinfo->shared.commonrings[i] = ring;14051406h2d_w_idx_ptr += idx_offset;1407h2d_r_idx_ptr += idx_offset;1408ring_mem_ptr += BRCMF_RING_MEM_SZ;1409}14101411for (i = BRCMF_NROF_H2D_COMMON_MSGRINGS;1412i < BRCMF_NROF_COMMON_MSGRINGS; i++) {1413ring = brcmf_pcie_alloc_dma_and_ring(devinfo, i, ring_mem_ptr);1414if (!ring)1415goto fail;1416ring->w_idx_addr = d2h_w_idx_ptr;1417ring->r_idx_addr = d2h_r_idx_ptr;1418ring->id = i;1419devinfo->shared.commonrings[i] = ring;14201421d2h_w_idx_ptr += idx_offset;1422d2h_r_idx_ptr += idx_offset;1423ring_mem_ptr += BRCMF_RING_MEM_SZ;1424}14251426devinfo->shared.max_flowrings = max_flowrings;1427devinfo->shared.max_submissionrings = max_submissionrings;1428devinfo->shared.max_completionrings = max_completionrings;1429rings = kcalloc(max_flowrings, sizeof(*ring), GFP_KERNEL);1430if (!rings)1431goto fail;14321433brcmf_dbg(PCIE, "Nr of flowrings is %d\n", max_flowrings);14341435for (i = 0; i < max_flowrings; i++) {1436ring = &rings[i];1437ring->devinfo = devinfo;1438ring->id = i + BRCMF_H2D_MSGRING_FLOWRING_IDSTART;1439brcmf_commonring_register_cb(&ring->commonring,1440brcmf_pcie_ring_mb_ring_bell,1441brcmf_pcie_ring_mb_update_rptr,1442brcmf_pcie_ring_mb_update_wptr,1443brcmf_pcie_ring_mb_write_rptr,1444brcmf_pcie_ring_mb_write_wptr,1445ring);1446ring->w_idx_addr = h2d_w_idx_ptr;1447ring->r_idx_addr = h2d_r_idx_ptr;1448h2d_w_idx_ptr += idx_offset;1449h2d_r_idx_ptr += idx_offset;1450}1451devinfo->shared.flowrings = rings;14521453return 0;14541455fail:1456brcmf_err(bus, "Allocating ring buffers failed\n");1457brcmf_pcie_release_ringbuffers(devinfo);1458return -ENOMEM;1459}146014611462static void1463brcmf_pcie_release_scratchbuffers(struct brcmf_pciedev_info *devinfo)1464{1465if (devinfo->shared.scratch)1466dma_free_coherent(&devinfo->pdev->dev,1467BRCMF_DMA_D2H_SCRATCH_BUF_LEN,1468devinfo->shared.scratch,1469devinfo->shared.scratch_dmahandle);1470if (devinfo->shared.ringupd)1471dma_free_coherent(&devinfo->pdev->dev,1472BRCMF_DMA_D2H_RINGUPD_BUF_LEN,1473devinfo->shared.ringupd,1474devinfo->shared.ringupd_dmahandle);1475}14761477static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)1478{1479struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev);1480u64 address;1481u32 addr;14821483devinfo->shared.scratch =1484dma_alloc_coherent(&devinfo->pdev->dev,1485BRCMF_DMA_D2H_SCRATCH_BUF_LEN,1486&devinfo->shared.scratch_dmahandle,1487GFP_KERNEL);1488if (!devinfo->shared.scratch)1489goto fail;14901491addr = devinfo->shared.tcm_base_address +1492BRCMF_SHARED_DMA_SCRATCH_ADDR_OFFSET;1493address = (u64)devinfo->shared.scratch_dmahandle;1494brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);1495brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);1496addr = devinfo->shared.tcm_base_address +1497BRCMF_SHARED_DMA_SCRATCH_LEN_OFFSET;1498brcmf_pcie_write_tcm32(devinfo, addr, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);14991500devinfo->shared.ringupd =1501dma_alloc_coherent(&devinfo->pdev->dev,1502BRCMF_DMA_D2H_RINGUPD_BUF_LEN,1503&devinfo->shared.ringupd_dmahandle,1504GFP_KERNEL);1505if (!devinfo->shared.ringupd)1506goto fail;15071508addr = devinfo->shared.tcm_base_address +1509BRCMF_SHARED_DMA_RINGUPD_ADDR_OFFSET;1510address = (u64)devinfo->shared.ringupd_dmahandle;1511brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);1512brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);1513addr = devinfo->shared.tcm_base_address +1514BRCMF_SHARED_DMA_RINGUPD_LEN_OFFSET;1515brcmf_pcie_write_tcm32(devinfo, addr, BRCMF_DMA_D2H_RINGUPD_BUF_LEN);1516return 0;15171518fail:1519brcmf_err(bus, "Allocating scratch buffers failed\n");1520brcmf_pcie_release_scratchbuffers(devinfo);1521return -ENOMEM;1522}152315241525static void brcmf_pcie_down(struct device *dev)1526{1527struct brcmf_bus *bus_if = dev_get_drvdata(dev);1528struct brcmf_pciedev *pcie_bus_dev = bus_if->bus_priv.pcie;1529struct brcmf_pciedev_info *devinfo = pcie_bus_dev->devinfo;15301531brcmf_pcie_fwcon_timer(devinfo, false);1532}15331534static int brcmf_pcie_preinit(struct device *dev)1535{1536struct brcmf_bus *bus_if = dev_get_drvdata(dev);1537struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;15381539brcmf_dbg(PCIE, "Enter\n");15401541brcmf_pcie_intr_enable(buspub->devinfo);1542brcmf_pcie_hostready(buspub->devinfo);15431544return 0;1545}15461547static int brcmf_pcie_tx(struct device *dev, struct sk_buff *skb)1548{1549return 0;1550}155115521553static int brcmf_pcie_tx_ctlpkt(struct device *dev, unsigned char *msg,1554uint len)1555{1556return 0;1557}155815591560static int brcmf_pcie_rx_ctlpkt(struct device *dev, unsigned char *msg,1561uint len)1562{1563return 0;1564}156515661567static void brcmf_pcie_wowl_config(struct device *dev, bool enabled)1568{1569struct brcmf_bus *bus_if = dev_get_drvdata(dev);1570struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;1571struct brcmf_pciedev_info *devinfo = buspub->devinfo;15721573brcmf_dbg(PCIE, "Configuring WOWL, enabled=%d\n", enabled);1574devinfo->wowl_enabled = enabled;1575}157615771578static size_t brcmf_pcie_get_ramsize(struct device *dev)1579{1580struct brcmf_bus *bus_if = dev_get_drvdata(dev);1581struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;1582struct brcmf_pciedev_info *devinfo = buspub->devinfo;15831584return devinfo->ci->ramsize - devinfo->ci->srsize;1585}158615871588static int brcmf_pcie_get_memdump(struct device *dev, void *data, size_t len)1589{1590struct brcmf_bus *bus_if = dev_get_drvdata(dev);1591struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;1592struct brcmf_pciedev_info *devinfo = buspub->devinfo;15931594brcmf_dbg(PCIE, "dump at 0x%08X: len=%zu\n", devinfo->ci->rambase, len);1595brcmf_pcie_copy_dev_tomem(devinfo, devinfo->ci->rambase, data, len);1596return 0;1597}15981599static int brcmf_pcie_get_blob(struct device *dev, const struct firmware **fw,1600enum brcmf_blob_type type)1601{1602struct brcmf_bus *bus_if = dev_get_drvdata(dev);1603struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;1604struct brcmf_pciedev_info *devinfo = buspub->devinfo;16051606switch (type) {1607case BRCMF_BLOB_CLM:1608*fw = devinfo->clm_fw;1609devinfo->clm_fw = NULL;1610break;1611case BRCMF_BLOB_TXCAP:1612*fw = devinfo->txcap_fw;1613devinfo->txcap_fw = NULL;1614break;1615default:1616return -ENOENT;1617}16181619if (!*fw)1620return -ENOENT;16211622return 0;1623}16241625static int brcmf_pcie_reset(struct device *dev)1626{1627struct brcmf_bus *bus_if = dev_get_drvdata(dev);1628struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;1629struct brcmf_pciedev_info *devinfo = buspub->devinfo;1630struct brcmf_fw_request *fwreq;1631int err;16321633brcmf_pcie_intr_disable(devinfo);16341635brcmf_pcie_bus_console_read(devinfo, true);16361637brcmf_detach(dev);16381639brcmf_pcie_release_irq(devinfo);1640brcmf_pcie_release_scratchbuffers(devinfo);1641brcmf_pcie_release_ringbuffers(devinfo);1642brcmf_pcie_reset_device(devinfo);16431644fwreq = brcmf_pcie_prepare_fw_request(devinfo);1645if (!fwreq) {1646dev_err(dev, "Failed to prepare FW request\n");1647return -ENOMEM;1648}16491650err = brcmf_fw_get_firmwares(dev, fwreq, brcmf_pcie_setup);1651if (err) {1652dev_err(dev, "Failed to prepare FW request\n");1653kfree(fwreq);1654}16551656return err;1657}16581659static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {1660.preinit = brcmf_pcie_preinit,1661.txdata = brcmf_pcie_tx,1662.stop = brcmf_pcie_down,1663.txctl = brcmf_pcie_tx_ctlpkt,1664.rxctl = brcmf_pcie_rx_ctlpkt,1665.wowl_config = brcmf_pcie_wowl_config,1666.get_ramsize = brcmf_pcie_get_ramsize,1667.get_memdump = brcmf_pcie_get_memdump,1668.get_blob = brcmf_pcie_get_blob,1669.reset = brcmf_pcie_reset,1670.debugfs_create = brcmf_pcie_debugfs_create,1671};167216731674static void1675#if defined(__linux__)1676brcmf_pcie_adjust_ramsize(struct brcmf_pciedev_info *devinfo, u8 *data,1677#elif defined(__FreeBSD__)1678brcmf_pcie_adjust_ramsize(struct brcmf_pciedev_info *devinfo, const u8 *data,1679#endif1680u32 data_len)1681{1682#if defined(__linux__)1683__le32 *field;1684#elif defined(__FreeBSD__)1685const __le32 *field;1686#endif1687u32 newsize;16881689if (data_len < BRCMF_RAMSIZE_OFFSET + 8)1690return;16911692#if defined(__linux__)1693field = (__le32 *)&data[BRCMF_RAMSIZE_OFFSET];1694#elif defined(__FreeBSD__)1695field = (const __le32 *)&data[BRCMF_RAMSIZE_OFFSET];1696#endif1697if (le32_to_cpup(field) != BRCMF_RAMSIZE_MAGIC)1698return;1699field++;1700newsize = le32_to_cpup(field);17011702brcmf_dbg(PCIE, "Found ramsize info in FW, adjusting to 0x%x\n",1703newsize);1704devinfo->ci->ramsize = newsize;1705}170617071708static int1709brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,1710u32 sharedram_addr)1711{1712struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev);1713struct brcmf_pcie_shared_info *shared;1714u32 addr;17151716shared = &devinfo->shared;1717shared->tcm_base_address = sharedram_addr;17181719shared->flags = brcmf_pcie_read_tcm32(devinfo, sharedram_addr);1720shared->version = (u8)(shared->flags & BRCMF_PCIE_SHARED_VERSION_MASK);1721brcmf_dbg(PCIE, "PCIe protocol version %d\n", shared->version);1722if ((shared->version > BRCMF_PCIE_MAX_SHARED_VERSION) ||1723(shared->version < BRCMF_PCIE_MIN_SHARED_VERSION)) {1724brcmf_err(bus, "Unsupported PCIE version %d\n",1725shared->version);1726return -EINVAL;1727}17281729/* check firmware support dma indicies */1730if (shared->flags & BRCMF_PCIE_SHARED_DMA_INDEX) {1731if (shared->flags & BRCMF_PCIE_SHARED_DMA_2B_IDX)1732devinfo->dma_idx_sz = sizeof(u16);1733else1734devinfo->dma_idx_sz = sizeof(u32);1735}17361737addr = sharedram_addr + BRCMF_SHARED_MAX_RXBUFPOST_OFFSET;1738shared->max_rxbufpost = brcmf_pcie_read_tcm16(devinfo, addr);1739if (shared->max_rxbufpost == 0)1740shared->max_rxbufpost = BRCMF_DEF_MAX_RXBUFPOST;17411742addr = sharedram_addr + BRCMF_SHARED_RX_DATAOFFSET_OFFSET;1743shared->rx_dataoffset = brcmf_pcie_read_tcm32(devinfo, addr);17441745addr = sharedram_addr + BRCMF_SHARED_HTOD_MB_DATA_ADDR_OFFSET;1746shared->htod_mb_data_addr = brcmf_pcie_read_tcm32(devinfo, addr);17471748addr = sharedram_addr + BRCMF_SHARED_DTOH_MB_DATA_ADDR_OFFSET;1749shared->dtoh_mb_data_addr = brcmf_pcie_read_tcm32(devinfo, addr);17501751addr = sharedram_addr + BRCMF_SHARED_RING_INFO_ADDR_OFFSET;1752shared->ring_info_addr = brcmf_pcie_read_tcm32(devinfo, addr);17531754brcmf_dbg(PCIE, "max rx buf post %d, rx dataoffset %d\n",1755shared->max_rxbufpost, shared->rx_dataoffset);17561757brcmf_pcie_bus_console_init(devinfo);1758brcmf_pcie_bus_console_read(devinfo, false);17591760return 0;1761}17621763struct brcmf_random_seed_footer {1764__le32 length;1765__le32 magic;1766};17671768#define BRCMF_RANDOM_SEED_MAGIC 0xfeedc0de1769#define BRCMF_RANDOM_SEED_LENGTH 0x10017701771static noinline_for_stack void1772brcmf_pcie_provide_random_bytes(struct brcmf_pciedev_info *devinfo, u32 address)1773{1774u8 randbuf[BRCMF_RANDOM_SEED_LENGTH];17751776get_random_bytes(randbuf, BRCMF_RANDOM_SEED_LENGTH);1777#if defined(__linux__)1778memcpy_toio(devinfo->tcm + address, randbuf, BRCMF_RANDOM_SEED_LENGTH);1779#elif defined(__FreeBSD__)1780memcpy_toio((void *)((uintptr_t)devinfo->tcm + address), randbuf, BRCMF_RANDOM_SEED_LENGTH);1781#endif1782}17831784static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,1785const struct firmware *fw, void *nvram,1786u32 nvram_len)1787{1788struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev);1789u32 sharedram_addr;1790u32 sharedram_addr_written;1791u32 loop_counter;1792int err;1793u32 address;1794u32 resetintr;17951796brcmf_dbg(PCIE, "Halt ARM.\n");1797err = brcmf_pcie_enter_download_state(devinfo);1798if (err)1799return err;18001801brcmf_dbg(PCIE, "Download FW %s\n", devinfo->fw_name);1802#if defined(__linux__)1803memcpy_toio(devinfo->tcm + devinfo->ci->rambase,1804(void *)fw->data, fw->size);1805#elif defined(__FreeBSD__)1806memcpy_toio((void *)((uintptr_t)devinfo->tcm + devinfo->ci->rambase),1807fw->data, fw->size);1808#endif18091810resetintr = get_unaligned_le32(fw->data);1811release_firmware(fw);18121813/* reset last 4 bytes of RAM address. to be used for shared1814* area. This identifies when FW is running1815*/1816brcmf_pcie_write_ram32(devinfo, devinfo->ci->ramsize - 4, 0);18171818if (nvram) {1819brcmf_dbg(PCIE, "Download NVRAM %s\n", devinfo->nvram_name);1820address = devinfo->ci->rambase + devinfo->ci->ramsize -1821nvram_len;1822#if defined(__linux__)1823memcpy_toio(devinfo->tcm + address, nvram, nvram_len);1824#elif defined(__FreeBSD__)1825memcpy_toio((void *)((uintptr_t)devinfo->tcm + address), nvram, nvram_len);1826#endif1827brcmf_fw_nvram_free(nvram);18281829if (devinfo->fwseed) {1830size_t rand_len = BRCMF_RANDOM_SEED_LENGTH;1831struct brcmf_random_seed_footer footer = {1832.length = cpu_to_le32(rand_len),1833.magic = cpu_to_le32(BRCMF_RANDOM_SEED_MAGIC),1834};18351836/* Some chips/firmwares expect a buffer of random1837* data to be present before NVRAM1838*/1839brcmf_dbg(PCIE, "Download random seed\n");18401841address -= sizeof(footer);1842#if defined(__linux__)1843memcpy_toio(devinfo->tcm + address, &footer,1844#elif defined(__FreeBSD__)1845memcpy_toio((void *)((uintptr_t)devinfo->tcm + address), &footer,1846#endif1847sizeof(footer));18481849address -= rand_len;1850brcmf_pcie_provide_random_bytes(devinfo, address);1851}1852} else {1853brcmf_dbg(PCIE, "No matching NVRAM file found %s\n",1854devinfo->nvram_name);1855}18561857sharedram_addr_written = brcmf_pcie_read_ram32(devinfo,1858devinfo->ci->ramsize -18594);1860brcmf_dbg(PCIE, "Bring ARM in running state\n");1861err = brcmf_pcie_exit_download_state(devinfo, resetintr);1862if (err)1863return err;18641865brcmf_dbg(PCIE, "Wait for FW init\n");1866sharedram_addr = sharedram_addr_written;1867loop_counter = BRCMF_PCIE_FW_UP_TIMEOUT / 50;1868while ((sharedram_addr == sharedram_addr_written) && (loop_counter)) {1869#if defined(__linux__)1870msleep(50);1871#elif defined(__FreeBSD__)1872linux_msleep(50);1873#endif1874sharedram_addr = brcmf_pcie_read_ram32(devinfo,1875devinfo->ci->ramsize -18764);1877loop_counter--;1878}1879if (sharedram_addr == sharedram_addr_written) {1880brcmf_err(bus, "FW failed to initialize\n");1881return -ENODEV;1882}1883if (sharedram_addr < devinfo->ci->rambase ||1884sharedram_addr >= devinfo->ci->rambase + devinfo->ci->ramsize) {1885brcmf_err(bus, "Invalid shared RAM address 0x%08x\n",1886sharedram_addr);1887return -ENODEV;1888}1889brcmf_dbg(PCIE, "Shared RAM addr: 0x%08x\n", sharedram_addr);18901891return (brcmf_pcie_init_share_ram_info(devinfo, sharedram_addr));1892}189318941895static int brcmf_pcie_get_resource(struct brcmf_pciedev_info *devinfo)1896{1897struct pci_dev *pdev = devinfo->pdev;1898struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);1899int err;1900phys_addr_t bar0_addr, bar1_addr;1901ulong bar1_size;19021903err = pci_enable_device(pdev);1904if (err) {1905brcmf_err(bus, "pci_enable_device failed err=%d\n", err);1906return err;1907}19081909pci_set_master(pdev);19101911/* Bar-0 mapped address */1912bar0_addr = pci_resource_start(pdev, 0);1913/* Bar-1 mapped address */1914bar1_addr = pci_resource_start(pdev, 2);1915/* read Bar-1 mapped memory range */1916bar1_size = pci_resource_len(pdev, 2);1917if ((bar1_size == 0) || (bar1_addr == 0)) {1918brcmf_err(bus, "BAR1 Not enabled, device size=%ld, addr=%#016llx\n",1919bar1_size, (unsigned long long)bar1_addr);1920return -EINVAL;1921}19221923devinfo->regs = ioremap(bar0_addr, BRCMF_PCIE_REG_MAP_SIZE);1924devinfo->tcm = ioremap(bar1_addr, bar1_size);19251926if (!devinfo->regs || !devinfo->tcm) {1927brcmf_err(bus, "ioremap() failed (%p,%p)\n", devinfo->regs,1928devinfo->tcm);1929return -EINVAL;1930}1931brcmf_dbg(PCIE, "Phys addr : reg space = %p base addr %#016llx\n",1932devinfo->regs, (unsigned long long)bar0_addr);1933brcmf_dbg(PCIE, "Phys addr : mem space = %p base addr %#016llx size 0x%x\n",1934devinfo->tcm, (unsigned long long)bar1_addr,1935(unsigned int)bar1_size);19361937return 0;1938}193919401941static void brcmf_pcie_release_resource(struct brcmf_pciedev_info *devinfo)1942{1943if (devinfo->tcm)1944iounmap(devinfo->tcm);1945if (devinfo->regs)1946iounmap(devinfo->regs);19471948pci_disable_device(devinfo->pdev);1949}195019511952static u32 brcmf_pcie_buscore_prep_addr(const struct pci_dev *pdev, u32 addr)1953{1954u32 ret_addr;19551956ret_addr = addr & (BRCMF_PCIE_BAR0_REG_SIZE - 1);1957addr &= ~(BRCMF_PCIE_BAR0_REG_SIZE - 1);1958pci_write_config_dword(pdev, BRCMF_PCIE_BAR0_WINDOW, addr);19591960return ret_addr;1961}196219631964static u32 brcmf_pcie_buscore_read32(void *ctx, u32 addr)1965{1966struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;19671968addr = brcmf_pcie_buscore_prep_addr(devinfo->pdev, addr);1969return brcmf_pcie_read_reg32(devinfo, addr);1970}197119721973static void brcmf_pcie_buscore_write32(void *ctx, u32 addr, u32 value)1974{1975struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;19761977addr = brcmf_pcie_buscore_prep_addr(devinfo->pdev, addr);1978brcmf_pcie_write_reg32(devinfo, addr, value);1979}198019811982static int brcmf_pcie_buscoreprep(void *ctx)1983{1984return brcmf_pcie_get_resource(ctx);1985}198619871988static int brcmf_pcie_buscore_reset(void *ctx, struct brcmf_chip *chip)1989{1990struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;1991struct brcmf_core *core;1992u32 val, reg;19931994devinfo->ci = chip;1995brcmf_pcie_reset_device(devinfo);19961997/* reginfo is not ready yet */1998core = brcmf_chip_get_core(chip, BCMA_CORE_PCIE2);1999if (core->rev >= 64)2000reg = BRCMF_PCIE_64_PCIE2REG_MAILBOXINT;2001else2002reg = BRCMF_PCIE_PCIE2REG_MAILBOXINT;20032004val = brcmf_pcie_read_reg32(devinfo, reg);2005if (val != 0xffffffff)2006brcmf_pcie_write_reg32(devinfo, reg, val);20072008return 0;2009}201020112012static void brcmf_pcie_buscore_activate(void *ctx, struct brcmf_chip *chip,2013u32 rstvec)2014{2015struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;20162017brcmf_pcie_write_tcm32(devinfo, 0, rstvec);2018}201920202021static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {2022.prepare = brcmf_pcie_buscoreprep,2023.reset = brcmf_pcie_buscore_reset,2024.activate = brcmf_pcie_buscore_activate,2025.read32 = brcmf_pcie_buscore_read32,2026.write32 = brcmf_pcie_buscore_write32,2027};20282029#define BRCMF_OTP_SYS_VENDOR 0x152030#define BRCMF_OTP_BRCM_CIS 0x8020312032#define BRCMF_OTP_VENDOR_HDR 0x0000000820332034static int2035brcmf_pcie_parse_otp_sys_vendor(struct brcmf_pciedev_info *devinfo,2036u8 *data, size_t size)2037{2038int idx = 4;2039const char *chip_params;2040const char *board_params;2041const char *p;20422043/* 4-byte header and two empty strings */2044if (size < 6)2045return -EINVAL;20462047if (get_unaligned_le32(data) != BRCMF_OTP_VENDOR_HDR)2048return -EINVAL;20492050chip_params = &data[idx];20512052/* Skip first string, including terminator */2053idx += strnlen(chip_params, size - idx) + 1;2054if (idx >= size)2055return -EINVAL;20562057board_params = &data[idx];20582059/* Skip to terminator of second string */2060idx += strnlen(board_params, size - idx);2061if (idx >= size)2062return -EINVAL;20632064/* At this point both strings are guaranteed NUL-terminated */2065brcmf_dbg(PCIE, "OTP: chip_params='%s' board_params='%s'\n",2066chip_params, board_params);20672068p = skip_spaces(board_params);2069while (*p) {2070char tag = *p++;2071const char *end;2072size_t len;20732074if (*p++ != '=') /* implicit NUL check */2075return -EINVAL;20762077/* *p might be NUL here, if so end == p and len == 0 */2078end = strchrnul(p, ' ');2079len = end - p;20802081/* leave 1 byte for NUL in destination string */2082if (len > (BRCMF_OTP_MAX_PARAM_LEN - 1))2083return -EINVAL;20842085/* Copy len characters plus a NUL terminator */2086switch (tag) {2087case 'M':2088strscpy(devinfo->otp.module, p, len + 1);2089break;2090case 'V':2091strscpy(devinfo->otp.vendor, p, len + 1);2092break;2093case 'm':2094strscpy(devinfo->otp.version, p, len + 1);2095break;2096}20972098/* Skip to next arg, if any */2099p = skip_spaces(end);2100}21012102brcmf_dbg(PCIE, "OTP: module=%s vendor=%s version=%s\n",2103devinfo->otp.module, devinfo->otp.vendor,2104devinfo->otp.version);21052106if (!devinfo->otp.module[0] ||2107!devinfo->otp.vendor[0] ||2108!devinfo->otp.version[0])2109return -EINVAL;21102111devinfo->otp.valid = true;2112return 0;2113}21142115static int2116brcmf_pcie_parse_otp(struct brcmf_pciedev_info *devinfo, u8 *otp, size_t size)2117{2118int p = 0;2119int ret = -EINVAL;21202121brcmf_dbg(PCIE, "parse_otp size=%zd\n", size);21222123while (p < (size - 1)) {2124u8 type = otp[p];2125u8 length = otp[p + 1];21262127if (type == 0)2128break;21292130if ((p + 2 + length) > size)2131break;21322133switch (type) {2134case BRCMF_OTP_SYS_VENDOR:2135brcmf_dbg(PCIE, "OTP @ 0x%x (%d): SYS_VENDOR\n",2136p, length);2137ret = brcmf_pcie_parse_otp_sys_vendor(devinfo,2138&otp[p + 2],2139length);2140break;2141case BRCMF_OTP_BRCM_CIS:2142brcmf_dbg(PCIE, "OTP @ 0x%x (%d): BRCM_CIS\n",2143p, length);2144break;2145default:2146brcmf_dbg(PCIE, "OTP @ 0x%x (%d): Unknown type 0x%x\n",2147p, length, type);2148break;2149}21502151p += 2 + length;2152}21532154return ret;2155}21562157static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo)2158{2159const struct pci_dev *pdev = devinfo->pdev;2160struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);2161u32 coreid, base, words, idx, sromctl;2162u16 *otp;2163struct brcmf_core *core;2164int ret;21652166switch (devinfo->ci->chip) {2167case BRCM_CC_4355_CHIP_ID:2168coreid = BCMA_CORE_CHIPCOMMON;2169base = 0x8c0;2170words = 0xb2;2171break;2172case BRCM_CC_4364_CHIP_ID:2173coreid = BCMA_CORE_CHIPCOMMON;2174base = 0x8c0;2175words = 0x1a0;2176break;2177case BRCM_CC_4377_CHIP_ID:2178case BRCM_CC_4378_CHIP_ID:2179coreid = BCMA_CORE_GCI;2180base = 0x1120;2181words = 0x170;2182break;2183case BRCM_CC_4387_CHIP_ID:2184coreid = BCMA_CORE_GCI;2185base = 0x113c;2186words = 0x170;2187break;2188default:2189/* OTP not supported on this chip */2190return 0;2191}21922193core = brcmf_chip_get_core(devinfo->ci, coreid);2194if (!core) {2195brcmf_err(bus, "No OTP core\n");2196return -ENODEV;2197}21982199if (coreid == BCMA_CORE_CHIPCOMMON) {2200/* Chips with OTP accessed via ChipCommon need additional2201* handling to access the OTP2202*/2203brcmf_pcie_select_core(devinfo, coreid);2204sromctl = READCC32(devinfo, sromcontrol);22052206if (!(sromctl & BCMA_CC_SROM_CONTROL_OTP_PRESENT)) {2207/* Chip lacks OTP, try without it... */2208brcmf_err(bus,2209"OTP unavailable, using default firmware\n");2210return 0;2211}22122213/* Map OTP to shadow area */2214WRITECC32(devinfo, sromcontrol,2215sromctl | BCMA_CC_SROM_CONTROL_OTPSEL);2216}22172218otp = kcalloc(words, sizeof(u16), GFP_KERNEL);2219if (!otp)2220return -ENOMEM;22212222/* Map bus window to SROM/OTP shadow area in core */2223base = brcmf_pcie_buscore_prep_addr(devinfo->pdev, base + core->base);22242225brcmf_dbg(PCIE, "OTP data:\n");2226for (idx = 0; idx < words; idx++) {2227otp[idx] = brcmf_pcie_read_reg16(devinfo, base + 2 * idx);2228brcmf_dbg(PCIE, "[%8x] 0x%04x\n", base + 2 * idx, otp[idx]);2229}22302231if (coreid == BCMA_CORE_CHIPCOMMON) {2232brcmf_pcie_select_core(devinfo, coreid);2233WRITECC32(devinfo, sromcontrol, sromctl);2234}22352236ret = brcmf_pcie_parse_otp(devinfo, (u8 *)otp, 2 * words);2237kfree(otp);22382239return ret;2240}22412242#define BRCMF_PCIE_FW_CODE 02243#define BRCMF_PCIE_FW_NVRAM 12244#define BRCMF_PCIE_FW_CLM 22245#define BRCMF_PCIE_FW_TXCAP 322462247static void brcmf_pcie_setup(struct device *dev, int ret,2248struct brcmf_fw_request *fwreq)2249{2250const struct firmware *fw;2251void *nvram;2252struct brcmf_bus *bus;2253struct brcmf_pciedev *pcie_bus_dev;2254struct brcmf_pciedev_info *devinfo;2255struct brcmf_commonring **flowrings;2256u32 i, nvram_len;22572258bus = dev_get_drvdata(dev);2259pcie_bus_dev = bus->bus_priv.pcie;2260devinfo = pcie_bus_dev->devinfo;22612262/* check firmware loading result */2263if (ret)2264goto fail;22652266brcmf_pcie_attach(devinfo);22672268fw = fwreq->items[BRCMF_PCIE_FW_CODE].binary;2269nvram = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.data;2270nvram_len = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.len;2271devinfo->clm_fw = fwreq->items[BRCMF_PCIE_FW_CLM].binary;2272devinfo->txcap_fw = fwreq->items[BRCMF_PCIE_FW_TXCAP].binary;2273kfree(fwreq);22742275ret = brcmf_chip_get_raminfo(devinfo->ci);2276if (ret) {2277brcmf_err(bus, "Failed to get RAM info\n");2278release_firmware(fw);2279brcmf_fw_nvram_free(nvram);2280goto fail;2281}22822283/* Some of the firmwares have the size of the memory of the device2284* defined inside the firmware. This is because part of the memory in2285* the device is shared and the devision is determined by FW. Parse2286* the firmware and adjust the chip memory size now.2287*/2288#if defined(__linux__)2289brcmf_pcie_adjust_ramsize(devinfo, (u8 *)fw->data, fw->size);2290#elif defined(__FreeBSD__)2291brcmf_pcie_adjust_ramsize(devinfo, fw->data, fw->size);2292#endif22932294ret = brcmf_pcie_download_fw_nvram(devinfo, fw, nvram, nvram_len);2295if (ret)2296goto fail;22972298devinfo->state = BRCMFMAC_PCIE_STATE_UP;22992300ret = brcmf_pcie_init_ringbuffers(devinfo);2301if (ret)2302goto fail;23032304ret = brcmf_pcie_init_scratchbuffers(devinfo);2305if (ret)2306goto fail;23072308brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);2309ret = brcmf_pcie_request_irq(devinfo);2310if (ret)2311goto fail;23122313/* hook the commonrings in the bus structure. */2314for (i = 0; i < BRCMF_NROF_COMMON_MSGRINGS; i++)2315bus->msgbuf->commonrings[i] =2316&devinfo->shared.commonrings[i]->commonring;23172318flowrings = kcalloc(devinfo->shared.max_flowrings, sizeof(*flowrings),2319GFP_KERNEL);2320if (!flowrings)2321goto fail;23222323for (i = 0; i < devinfo->shared.max_flowrings; i++)2324flowrings[i] = &devinfo->shared.flowrings[i].commonring;2325bus->msgbuf->flowrings = flowrings;23262327bus->msgbuf->rx_dataoffset = devinfo->shared.rx_dataoffset;2328bus->msgbuf->max_rxbufpost = devinfo->shared.max_rxbufpost;2329bus->msgbuf->max_flowrings = devinfo->shared.max_flowrings;23302331init_waitqueue_head(&devinfo->mbdata_resp_wait);23322333ret = brcmf_attach(&devinfo->pdev->dev);2334if (ret)2335goto fail;23362337brcmf_pcie_bus_console_read(devinfo, false);23382339brcmf_pcie_fwcon_timer(devinfo, true);23402341return;23422343fail:2344brcmf_err(bus, "Dongle setup failed\n");2345brcmf_pcie_bus_console_read(devinfo, true);2346brcmf_fw_crashed(dev);2347device_release_driver(dev);2348}23492350static struct brcmf_fw_request *2351brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)2352{2353struct brcmf_fw_request *fwreq;2354struct brcmf_fw_name fwnames[] = {2355{ ".bin", devinfo->fw_name },2356{ ".txt", devinfo->nvram_name },2357{ ".clm_blob", devinfo->clm_name },2358{ ".txcap_blob", devinfo->txcap_name },2359};23602361fwreq = brcmf_fw_alloc_request(devinfo->ci->chip, devinfo->ci->chiprev,2362brcmf_pcie_fwnames,2363ARRAY_SIZE(brcmf_pcie_fwnames),2364fwnames, ARRAY_SIZE(fwnames));2365if (!fwreq)2366return NULL;23672368fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY;2369fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;2370fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;2371fwreq->items[BRCMF_PCIE_FW_CLM].type = BRCMF_FW_TYPE_BINARY;2372fwreq->items[BRCMF_PCIE_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL;2373fwreq->items[BRCMF_PCIE_FW_TXCAP].type = BRCMF_FW_TYPE_BINARY;2374fwreq->items[BRCMF_PCIE_FW_TXCAP].flags = BRCMF_FW_REQF_OPTIONAL;2375/* NVRAM reserves PCI domain 0 for Broadcom's SDK faked bus */2376fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus) + 1;2377fwreq->bus_nr = devinfo->pdev->bus->number;23782379/* Apple platforms with fancy firmware/NVRAM selection */2380if (devinfo->settings->board_type &&2381devinfo->settings->antenna_sku &&2382devinfo->otp.valid) {2383const struct brcmf_otp_params *otp = &devinfo->otp;2384struct device *dev = &devinfo->pdev->dev;2385const char **bt = fwreq->board_types;23862387brcmf_dbg(PCIE, "Apple board: %s\n",2388devinfo->settings->board_type);23892390/* Example: apple,shikoku-RASP-m-6.11-X3 */2391bt[0] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s-%s-%s-%s",2392devinfo->settings->board_type,2393otp->module, otp->vendor, otp->version,2394devinfo->settings->antenna_sku);2395bt[1] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s-%s-%s",2396devinfo->settings->board_type,2397otp->module, otp->vendor, otp->version);2398bt[2] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s-%s",2399devinfo->settings->board_type,2400otp->module, otp->vendor);2401bt[3] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s",2402devinfo->settings->board_type,2403otp->module);2404bt[4] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s",2405devinfo->settings->board_type,2406devinfo->settings->antenna_sku);2407bt[5] = devinfo->settings->board_type;24082409if (!bt[0] || !bt[1] || !bt[2] || !bt[3] || !bt[4]) {2410kfree(fwreq);2411return NULL;2412}2413} else {2414brcmf_dbg(PCIE, "Board: %s\n", devinfo->settings->board_type);2415fwreq->board_types[0] = devinfo->settings->board_type;2416}24172418return fwreq;2419}24202421#ifdef DEBUG2422static void2423brcmf_pcie_fwcon_timer(struct brcmf_pciedev_info *devinfo, bool active)2424{2425if (!active) {2426if (devinfo->console_active) {2427timer_delete_sync(&devinfo->timer);2428devinfo->console_active = false;2429}2430return;2431}24322433/* don't start the timer */2434if (devinfo->state != BRCMFMAC_PCIE_STATE_UP ||2435!devinfo->console_interval || !BRCMF_FWCON_ON())2436return;24372438if (!devinfo->console_active) {2439devinfo->timer.expires = jiffies + devinfo->console_interval;2440add_timer(&devinfo->timer);2441devinfo->console_active = true;2442} else {2443/* Reschedule the timer */2444mod_timer(&devinfo->timer, jiffies + devinfo->console_interval);2445}2446}24472448static void2449brcmf_pcie_fwcon(struct timer_list *t)2450{2451struct brcmf_pciedev_info *devinfo = timer_container_of(devinfo, t,2452timer);24532454if (!devinfo->console_active)2455return;24562457brcmf_pcie_bus_console_read(devinfo, false);24582459/* Reschedule the timer if console interval is not zero */2460mod_timer(&devinfo->timer, jiffies + devinfo->console_interval);2461}24622463static int brcmf_pcie_console_interval_get(void *data, u64 *val)2464{2465struct brcmf_pciedev_info *devinfo = data;24662467*val = devinfo->console_interval;24682469return 0;2470}24712472static int brcmf_pcie_console_interval_set(void *data, u64 val)2473{2474struct brcmf_pciedev_info *devinfo = data;24752476if (val > MAX_CONSOLE_INTERVAL)2477return -EINVAL;24782479devinfo->console_interval = val;24802481if (!val && devinfo->console_active)2482brcmf_pcie_fwcon_timer(devinfo, false);2483else if (val)2484brcmf_pcie_fwcon_timer(devinfo, true);24852486return 0;2487}24882489DEFINE_SIMPLE_ATTRIBUTE(brcmf_pcie_console_interval_fops,2490brcmf_pcie_console_interval_get,2491brcmf_pcie_console_interval_set,2492"%llu\n");24932494static void brcmf_pcie_debugfs_create(struct device *dev)2495{2496struct brcmf_bus *bus_if = dev_get_drvdata(dev);2497struct brcmf_pub *drvr = bus_if->drvr;2498struct brcmf_pciedev *pcie_bus_dev = bus_if->bus_priv.pcie;2499struct brcmf_pciedev_info *devinfo = pcie_bus_dev->devinfo;2500struct dentry *dentry = brcmf_debugfs_get_devdir(drvr);25012502if (IS_ERR_OR_NULL(dentry))2503return;25042505devinfo->console_interval = BRCMF_CONSOLE;25062507debugfs_create_file("console_interval", 0644, dentry, devinfo,2508&brcmf_pcie_console_interval_fops);2509}25102511#else2512void brcmf_pcie_fwcon_timer(struct brcmf_pciedev_info *devinfo, bool active)2513{2514}25152516static void brcmf_pcie_debugfs_create(struct device *dev)2517{2518}2519#endif25202521struct brcmf_pcie_drvdata {2522enum brcmf_fwvendor vendor;2523bool fw_seed;2524};25252526enum {2527BRCMF_DRVDATA_CYW,2528BRCMF_DRVDATA_BCA,2529BRCMF_DRVDATA_WCC,2530BRCMF_DRVDATA_WCC_SEED,2531};25322533static const struct brcmf_pcie_drvdata drvdata[] = {2534[BRCMF_DRVDATA_CYW] = {2535.vendor = BRCMF_FWVENDOR_CYW,2536.fw_seed = false,2537},2538[BRCMF_DRVDATA_BCA] = {2539.vendor = BRCMF_FWVENDOR_BCA,2540.fw_seed = false,2541},2542[BRCMF_DRVDATA_WCC] = {2543.vendor = BRCMF_FWVENDOR_WCC,2544.fw_seed = false,2545},2546[BRCMF_DRVDATA_WCC_SEED] = {2547.vendor = BRCMF_FWVENDOR_WCC,2548.fw_seed = true,2549},2550};25512552/* Forward declaration for pci_match_id() call */2553static const struct pci_device_id brcmf_pcie_devid_table[];25542555static int2556brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)2557{2558int ret;2559struct brcmf_fw_request *fwreq;2560struct brcmf_pciedev_info *devinfo;2561struct brcmf_pciedev *pcie_bus_dev;2562struct brcmf_core *core;2563struct brcmf_bus *bus;25642565if (!id) {2566id = pci_match_id(brcmf_pcie_devid_table, pdev);2567if (!id) {2568pci_err(pdev, "Error could not find pci_device_id for %x:%x\n", pdev->vendor, pdev->device);2569return -ENODEV;2570}2571}25722573brcmf_dbg(PCIE, "Enter %x:%x\n", pdev->vendor, pdev->device);25742575ret = -ENOMEM;2576devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);2577if (devinfo == NULL)2578return ret;25792580devinfo->pdev = pdev;2581pcie_bus_dev = NULL;2582devinfo->ci = brcmf_chip_attach(devinfo, pdev->device,2583&brcmf_pcie_buscore_ops);2584if (IS_ERR(devinfo->ci)) {2585ret = PTR_ERR(devinfo->ci);2586devinfo->ci = NULL;2587goto fail;2588}25892590core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2);2591if (core->rev >= 64)2592devinfo->reginfo = &brcmf_reginfo_64;2593else2594devinfo->reginfo = &brcmf_reginfo_default;25952596pcie_bus_dev = kzalloc(sizeof(*pcie_bus_dev), GFP_KERNEL);2597if (pcie_bus_dev == NULL) {2598ret = -ENOMEM;2599goto fail;2600}26012602devinfo->settings = brcmf_get_module_param(&devinfo->pdev->dev,2603BRCMF_BUSTYPE_PCIE,2604devinfo->ci->chip,2605devinfo->ci->chiprev);2606if (!devinfo->settings) {2607ret = -ENOMEM;2608goto fail;2609}2610ret = PTR_ERR_OR_ZERO(devinfo->settings);2611if (ret < 0)2612goto fail;26132614bus = kzalloc(sizeof(*bus), GFP_KERNEL);2615if (!bus) {2616ret = -ENOMEM;2617goto fail;2618}2619bus->msgbuf = kzalloc(sizeof(*bus->msgbuf), GFP_KERNEL);2620if (!bus->msgbuf) {2621ret = -ENOMEM;2622kfree(bus);2623goto fail;2624}26252626/* hook it all together. */2627pcie_bus_dev->devinfo = devinfo;2628pcie_bus_dev->bus = bus;2629bus->dev = &pdev->dev;2630bus->bus_priv.pcie = pcie_bus_dev;2631bus->ops = &brcmf_pcie_bus_ops;2632bus->proto_type = BRCMF_PROTO_MSGBUF;2633bus->chip = devinfo->coreid;2634bus->wowl_supported = pci_pme_capable(pdev, PCI_D3hot);2635bus->fwvid = drvdata[id->driver_data].vendor;2636devinfo->fwseed = drvdata[id->driver_data].fw_seed;2637dev_set_drvdata(&pdev->dev, bus);26382639ret = brcmf_alloc(&devinfo->pdev->dev, devinfo->settings);2640if (ret)2641goto fail_bus;26422643/* otp read operation */2644switch (bus->fwvid) {2645case BRCMF_FWVENDOR_WCC:2646case BRCMF_FWVENDOR_BCA:2647ret = brcmf_pcie_read_otp(devinfo);2648if (ret) {2649brcmf_err(bus, "failed to parse OTP\n");2650goto fail_brcmf;2651}2652break;2653case BRCMF_FWVENDOR_CYW:2654default:2655break;2656}26572658#ifdef DEBUG2659/* Set up the fwcon timer */2660timer_setup(&devinfo->timer, brcmf_pcie_fwcon, 0);2661#endif26622663fwreq = brcmf_pcie_prepare_fw_request(devinfo);2664if (!fwreq) {2665ret = -ENOMEM;2666goto fail_brcmf;2667}26682669ret = brcmf_fw_get_firmwares(bus->dev, fwreq, brcmf_pcie_setup);2670if (ret < 0) {2671kfree(fwreq);2672goto fail_brcmf;2673}2674return 0;26752676fail_brcmf:2677brcmf_free(&devinfo->pdev->dev);2678fail_bus:2679kfree(bus->msgbuf);2680kfree(bus);2681fail:2682brcmf_err(NULL, "failed %x:%x\n", pdev->vendor, pdev->device);2683brcmf_pcie_release_resource(devinfo);2684if (devinfo->ci)2685brcmf_chip_detach(devinfo->ci);2686if (devinfo->settings)2687brcmf_release_module_param(devinfo->settings);2688kfree(pcie_bus_dev);2689kfree(devinfo);2690return ret;2691}269226932694static void2695brcmf_pcie_remove(struct pci_dev *pdev)2696{2697struct brcmf_pciedev_info *devinfo;2698struct brcmf_bus *bus;26992700brcmf_dbg(PCIE, "Enter\n");27012702bus = dev_get_drvdata(&pdev->dev);2703if (bus == NULL)2704return;27052706devinfo = bus->bus_priv.pcie->devinfo;2707brcmf_pcie_bus_console_read(devinfo, false);2708brcmf_pcie_fwcon_timer(devinfo, false);27092710devinfo->state = BRCMFMAC_PCIE_STATE_DOWN;2711if (devinfo->ci)2712brcmf_pcie_intr_disable(devinfo);27132714brcmf_detach(&pdev->dev);2715brcmf_free(&pdev->dev);27162717kfree(bus->bus_priv.pcie);2718kfree(bus->msgbuf->flowrings);2719kfree(bus->msgbuf);2720kfree(bus);27212722brcmf_pcie_release_irq(devinfo);2723brcmf_pcie_release_scratchbuffers(devinfo);2724brcmf_pcie_release_ringbuffers(devinfo);2725brcmf_pcie_reset_device(devinfo);2726brcmf_pcie_release_resource(devinfo);2727release_firmware(devinfo->clm_fw);2728release_firmware(devinfo->txcap_fw);27292730if (devinfo->ci)2731brcmf_chip_detach(devinfo->ci);2732if (devinfo->settings)2733brcmf_release_module_param(devinfo->settings);27342735kfree(devinfo);2736dev_set_drvdata(&pdev->dev, NULL);2737}273827392740#ifdef CONFIG_PM274127422743static int brcmf_pcie_pm_enter_D3(struct device *dev)2744{2745struct brcmf_pciedev_info *devinfo;2746struct brcmf_bus *bus;27472748brcmf_dbg(PCIE, "Enter\n");27492750bus = dev_get_drvdata(dev);2751devinfo = bus->bus_priv.pcie->devinfo;27522753brcmf_pcie_fwcon_timer(devinfo, false);2754brcmf_bus_change_state(bus, BRCMF_BUS_DOWN);27552756devinfo->mbdata_completed = false;2757brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D3_INFORM);27582759wait_event_timeout(devinfo->mbdata_resp_wait, devinfo->mbdata_completed,2760BRCMF_PCIE_MBDATA_TIMEOUT);2761if (!devinfo->mbdata_completed) {2762brcmf_err(bus, "Timeout on response for entering D3 substate\n");2763brcmf_bus_change_state(bus, BRCMF_BUS_UP);2764return -EIO;2765}27662767devinfo->state = BRCMFMAC_PCIE_STATE_DOWN;27682769return 0;2770}277127722773static int brcmf_pcie_pm_leave_D3(struct device *dev)2774{2775struct brcmf_pciedev_info *devinfo;2776struct brcmf_bus *bus;2777struct pci_dev *pdev;2778int err;27792780brcmf_dbg(PCIE, "Enter\n");27812782bus = dev_get_drvdata(dev);2783devinfo = bus->bus_priv.pcie->devinfo;2784brcmf_dbg(PCIE, "Enter, dev=%p, bus=%p\n", dev, bus);27852786/* Check if device is still up and running, if so we are ready */2787if (brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->intmask) != 0) {2788brcmf_dbg(PCIE, "Try to wakeup device....\n");2789if (brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D0_INFORM))2790goto cleanup;2791brcmf_dbg(PCIE, "Hot resume, continue....\n");2792devinfo->state = BRCMFMAC_PCIE_STATE_UP;2793brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);2794brcmf_bus_change_state(bus, BRCMF_BUS_UP);2795brcmf_pcie_intr_enable(devinfo);2796brcmf_pcie_hostready(devinfo);2797brcmf_pcie_fwcon_timer(devinfo, true);2798return 0;2799}28002801cleanup:2802brcmf_chip_detach(devinfo->ci);2803devinfo->ci = NULL;2804pdev = devinfo->pdev;2805brcmf_pcie_remove(pdev);28062807err = brcmf_pcie_probe(pdev, NULL);2808if (err)2809__brcmf_err(NULL, __func__, "probe after resume failed, err=%d\n", err);28102811return err;2812}281328142815static const struct dev_pm_ops brcmf_pciedrvr_pm = {2816.suspend = brcmf_pcie_pm_enter_D3,2817.resume = brcmf_pcie_pm_leave_D3,2818.freeze = brcmf_pcie_pm_enter_D3,2819.restore = brcmf_pcie_pm_leave_D3,2820};282128222823#endif /* CONFIG_PM */282428252826#define BRCMF_PCIE_DEVICE(dev_id, fw_vend) \2827{ \2828BRCM_PCIE_VENDOR_ID_BROADCOM, (dev_id), \2829PCI_ANY_ID, PCI_ANY_ID, \2830PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, \2831BRCMF_DRVDATA_ ## fw_vend \2832}2833#define BRCMF_PCIE_DEVICE_SUB(dev_id, subvend, subdev, fw_vend) \2834{ \2835BRCM_PCIE_VENDOR_ID_BROADCOM, (dev_id), \2836(subvend), (subdev), \2837PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, \2838BRCMF_DRVDATA_ ## fw_vend \2839}28402841static const struct pci_device_id brcmf_pcie_devid_table[] = {2842BRCMF_PCIE_DEVICE(BRCM_PCIE_4350_DEVICE_ID, WCC),2843BRCMF_PCIE_DEVICE_SUB(0x4355, BRCM_PCIE_VENDOR_ID_BROADCOM, 0x4355, WCC),2844BRCMF_PCIE_DEVICE(BRCM_PCIE_4354_RAW_DEVICE_ID, WCC),2845BRCMF_PCIE_DEVICE(BRCM_PCIE_4355_DEVICE_ID, WCC_SEED),2846BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID, WCC),2847BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID, WCC),2848BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID, WCC),2849BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_RAW_DEVICE_ID, WCC),2850BRCMF_PCIE_DEVICE(BRCM_PCIE_4358_DEVICE_ID, WCC),2851BRCMF_PCIE_DEVICE(BRCM_PCIE_4359_DEVICE_ID, WCC),2852BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_DEVICE_ID, WCC),2853BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID, WCC),2854BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID, WCC),2855BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_RAW_DEVICE_ID, WCC),2856BRCMF_PCIE_DEVICE(BRCM_PCIE_4364_DEVICE_ID, WCC_SEED),2857BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_DEVICE_ID, BCA),2858BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_2G_DEVICE_ID, BCA),2859BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_5G_DEVICE_ID, BCA),2860BRCMF_PCIE_DEVICE_SUB(0x4365, BRCM_PCIE_VENDOR_ID_BROADCOM, 0x4365, BCA),2861BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_DEVICE_ID, BCA),2862BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_2G_DEVICE_ID, BCA),2863BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID, BCA),2864BRCMF_PCIE_DEVICE(BRCM_PCIE_4371_DEVICE_ID, WCC),2865BRCMF_PCIE_DEVICE(BRCM_PCIE_43596_DEVICE_ID, CYW),2866BRCMF_PCIE_DEVICE(BRCM_PCIE_4377_DEVICE_ID, WCC_SEED),2867BRCMF_PCIE_DEVICE(BRCM_PCIE_4378_DEVICE_ID, WCC_SEED),2868BRCMF_PCIE_DEVICE(BRCM_PCIE_4387_DEVICE_ID, WCC_SEED),2869BRCMF_PCIE_DEVICE(BRCM_PCIE_43752_DEVICE_ID, WCC_SEED),2870BRCMF_PCIE_DEVICE(CY_PCIE_54591_DEVICE_ID, CYW),2871{ /* end: all zeroes */ }2872};287328742875MODULE_DEVICE_TABLE(pci, brcmf_pcie_devid_table);287628772878static struct pci_driver brcmf_pciedrvr = {2879.name = KBUILD_MODNAME,2880.id_table = brcmf_pcie_devid_table,2881.probe = brcmf_pcie_probe,2882.remove = brcmf_pcie_remove,2883#ifdef CONFIG_PM2884.driver.pm = &brcmf_pciedrvr_pm,2885#endif2886.driver.coredump = brcmf_dev_coredump,2887};288828892890int brcmf_pcie_register(void)2891{2892brcmf_dbg(PCIE, "Enter\n");2893return pci_register_driver(&brcmf_pciedrvr);2894}289528962897void brcmf_pcie_exit(void)2898{2899brcmf_dbg(PCIE, "Enter\n");2900pci_unregister_driver(&brcmf_pciedrvr);2901}290229032904