static int brcmf_usb_resetcfg(struct brcmf_usbdev_info *devinfo) { struct bootrom_id_le id; u32 loop_cnt; int err; brcmf_dbg(USB, "Enter\n"); loop_cnt = 0; do { mdelay(BRCMF_USB_RESET_GETVER_SPINWAIT); loop_cnt++; id.chip = cpu_to_le32(0xDEAD); /* Get the ID */ err = brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id, sizeof(id)); if ((err) && (err != -ETIMEDOUT)) return err; if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID)) break; } while (loop_cnt < BRCMF_USB_RESET_GETVER_LOOP_CNT); if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID)) { brcmf_dbg(USB, "postboot chip 0x%x/rev 0x%x\n", le32_to_cpu(id.chip), le32_to_cpu(id.chiprev)); brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id, sizeof(id)); return 0; } else { brcmf_err("Cannot talk to Dongle. Firmware is not UP, %d ms\n", BRCMF_USB_RESET_GETVER_SPINWAIT * loop_cnt); return -EINVAL; } }
static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo) { struct rdl_state_le state; brcmf_dbg(USB, "Enter\n"); if (!devinfo) return -EINVAL; if (devinfo->bus_pub.devid == 0xDEAD) return -EINVAL; /* Check we are runnable */ state.state = 0; brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state, sizeof(state)); /* Start the image */ if (state.state == cpu_to_le32(DL_RUNNABLE)) { if (brcmf_usb_dl_cmd(devinfo, DL_GO, &state, sizeof(state))) return -ENODEV; if (brcmf_usb_resetcfg(devinfo)) return -ENODEV; /* The Dongle may go for re-enumeration. */ } else { brcmf_err("Dongle not runnable\n"); return -EINVAL; } brcmf_dbg(USB, "Exit\n"); return 0; }
/** * brcmf_btcoex_is_sco_active() - check if SCO/eSCO is active * @ifp: interface * * return: true if SCO/eSCO session is active */ static bool brcmf_btcoex_is_sco_active(struct brcmf_if *ifp) { int ioc_res = 0; bool res = false; int sco_id_cnt = 0; u32 param27; int i; for (i = 0; i < BRCMF_BT_SCO_SAMPLES; i++) { ioc_res = brcmf_btcoex_params_read(ifp, 27, ¶m27); if (ioc_res < 0) { brcmf_err("ioc read btc params error\n"); break; } brcmf_dbg(INFO, "sample[%d], btc_params 27:%x\n", i, param27); if ((param27 & 0x6) == 2) { /* count both sco & esco */ sco_id_cnt++; } if (sco_id_cnt > 2) { brcmf_dbg(INFO, "sco/esco detected, pkt id_cnt:%d samples:%d\n", sco_id_cnt, i); res = true; break; } } brcmf_dbg(TRACE, "exit: result=%d\n", res); return res; }
int brcmf_proto_attach(struct brcmf_pub *drvr) { struct brcmf_proto *proto; proto = kzalloc(sizeof(*proto), GFP_ATOMIC); if (!proto) goto fail; drvr->proto = proto; /* BCDC protocol is only protocol supported for the moment */ if (brcmf_proto_bcdc_attach(drvr)) goto fail; if ((proto->hdrpush == NULL) || (proto->hdrpull == NULL) || (proto->query_dcmd == NULL) || (proto->set_dcmd == NULL)) { brcmf_err("Not all proto handlers have been installed\n"); goto fail; } return 0; fail: kfree(proto); drvr->proto = NULL; return -ENOMEM; }
static int mmc_submit_one(struct mmc_data *md, struct mmc_request *mr, struct mmc_command *mc, int sg_cnt, int req_sz, int func_blk_sz, u32 *addr, struct brcmf_sdio_dev *sdiodev, struct sdio_func *func, int write) { int ret; md->sg_len = sg_cnt; md->blocks = req_sz / func_blk_sz; mc->arg |= (*addr & 0x1FFFF) << 9; /* address */ mc->arg |= md->blocks & 0x1FF; /* block count */ /* incrementing addr for function 1 */ if (func->num == 1) *addr += req_sz; mmc_set_data_timeout(md, func->card); mmc_wait_for_req(func->card->host, mr); ret = mc->error ? mc->error : md->error; if (ret == -ENOMEDIUM) { brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM); } else if (ret != 0) { brcmf_err("CMD53 sg block %s failed %d\n", write ? "write" : "read", ret); ret = -EIO; } return ret; }
static int brcmf_usb_recv_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len) { int ret; u16 size; brcmf_dbg(USB, "Enter\n"); if ((devinfo == NULL) || (buf == NULL) || (len == 0) || (devinfo->ctl_urb == NULL)) return -EINVAL; size = len; devinfo->ctl_read.wLength = cpu_to_le16p(&size); devinfo->ctl_urb->transfer_buffer_length = size; devinfo->ctl_read.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; devinfo->ctl_read.bRequest = 1; usb_fill_control_urb(devinfo->ctl_urb, devinfo->usbdev, devinfo->ctl_in_pipe, (unsigned char *) &devinfo->ctl_read, buf, size, (usb_complete_t)brcmf_usb_ctlread_complete, devinfo); ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC); if (ret < 0) brcmf_err("usb_submit_urb failed %d\n", ret); return ret; }
static int brcmf_msgbuf_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, uint len) { struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd; struct sk_buff *skb = NULL; int timeout; int err; brcmf_dbg(MSGBUF, "ifidx=%d, cmd=%d, len=%d\n", ifidx, cmd, len); msgbuf->ctl_completed = false; err = brcmf_msgbuf_tx_ioctl(drvr, ifidx, cmd, buf, len); if (err) return err; timeout = brcmf_msgbuf_ioctl_resp_wait(msgbuf); if (!timeout) { brcmf_err("Timeout on response for query command\n"); return -EIO; } skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev, msgbuf->rx_pktids, msgbuf->ioctl_resp_pktid); if (msgbuf->ioctl_resp_ret_len != 0) { if (!skb) return -EBADF; memcpy(buf, skb->data, (len < msgbuf->ioctl_resp_ret_len) ? len : msgbuf->ioctl_resp_ret_len); } brcmu_pkt_buf_free_skb(skb); return msgbuf->ioctl_resp_status; }
s32 brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name, void *data, u32 len) { struct brcmf_pub *drvr = ifp->drvr; s32 err; u32 buflen; mutex_lock(&drvr->proto_block); buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len, drvr->proto_buf, sizeof(drvr->proto_buf)); if (buflen) { err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf, buflen, false); if (err == 0) memcpy(data, drvr->proto_buf, len); } else { err = -EPERM; brcmf_err("Creating bsscfg failed\n"); } brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len); brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n"); mutex_unlock(&drvr->proto_block); return err; }
static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev) { int err_ret; u32 fbraddr; u8 func; brcmf_dbg(SDIO, "\n"); /* Get the Card's common CIS address */ sdiodev->func_cis_ptr[0] = brcmf_sdioh_get_cisaddr(sdiodev, SDIO_CCCR_CIS); brcmf_dbg(SDIO, "Card's Common CIS Ptr = 0x%x\n", sdiodev->func_cis_ptr[0]); /* Get the Card's function CIS (for each function) */ for (fbraddr = SDIO_FBR_BASE(1), func = 1; func <= sdiodev->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) { sdiodev->func_cis_ptr[func] = brcmf_sdioh_get_cisaddr(sdiodev, SDIO_FBR_CIS + fbraddr); brcmf_dbg(SDIO, "Function %d CIS Ptr = 0x%x\n", func, sdiodev->func_cis_ptr[func]); } /* Enable Function 1 */ err_ret = sdio_enable_func(sdiodev->func[1]); if (err_ret) brcmf_err("Failed to enable F1 Err: 0x%08x\n", err_ret); return false; }
void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev) { struct device *dev = sdiodev->dev; struct device_node *np = dev->of_node; int irq; u32 irqf; u32 val; if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac")) return; sdiodev->pdata = devm_kzalloc(dev, sizeof(*sdiodev->pdata), GFP_KERNEL); if (!sdiodev->pdata) return; irq = irq_of_parse_and_map(np, 0); if (irq < 0) { brcmf_err("interrupt could not be mapped: err=%d\n", irq); devm_kfree(dev, sdiodev->pdata); return; } irqf = irqd_get_trigger_type(irq_get_irq_data(irq)); sdiodev->pdata->oob_irq_supported = true; sdiodev->pdata->oob_irq_nr = irq; sdiodev->pdata->oob_irq_flags = irqf; if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0) sdiodev->pdata->drive_strength = val; }
static s32 brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set) { struct brcmf_pub *drvr = ifp->drvr; s32 err; if (drvr->bus_if->state != BRCMF_BUS_DATA) { brcmf_err("bus is down. we have nothing to do.\n"); return -EIO; } if (data != NULL) len = min_t(uint, len, BRCMF_DCMD_MAXLEN); if (set) err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd, data, len); else err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len); if (err >= 0) err = 0; else brcmf_dbg(FIL, "Failed err=%d\n", err); return err; }
int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func, uint regaddr, u8 *byte) { int err_ret; brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr); brcmf_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait); if (brcmf_pm_resume_error(sdiodev)) return -EIO; if (rw && func == 0) { /* handle F0 separately */ err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte); } else { if (rw) /* CMD52 Write */ sdio_writeb(sdiodev->func[func], *byte, regaddr, &err_ret); else if (func == 0) { *byte = sdio_f0_readb(sdiodev->func[func], regaddr, &err_ret); } else { *byte = sdio_readb(sdiodev->func[func], regaddr, &err_ret); } } if (err_ret) brcmf_err("Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n", rw ? "write" : "read", func, regaddr, *byte, err_ret); return err_ret; }
static int brcmf_pcie_attach_bus(struct device *dev) { int ret; /* Attach to the common driver interface */ ret = brcmf_attach(dev); if (ret) { brcmf_err("brcmf_attach failed\n"); } else { ret = brcmf_bus_start(dev); if (ret) brcmf_err("dongle is not responding\n"); } return ret; }
static int brcmf_net_p2p_attach(struct brcmf_if *ifp) { struct net_device *ndev; brcmf_dbg(TRACE, "Enter, bsscfgidx=%d mac=%pM\n", ifp->bsscfgidx, ifp->mac_addr); ndev = ifp->ndev; ndev->netdev_ops = &brcmf_netdev_ops_p2p; /* set the mac address */ memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN); if (register_netdev(ndev) != 0) { brcmf_err("couldn't register the p2p net device\n"); goto fail; } brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name); return 0; fail: ifp->drvr->iflist[ifp->bsscfgidx] = NULL; ndev->netdev_ops = NULL; free_netdev(ndev); return -EBADE; }
static struct brcmf_usbreq * brcmf_usbdev_qinit(struct list_head *q, int qsize) { int i; struct brcmf_usbreq *req, *reqs; reqs = kcalloc(qsize, sizeof(struct brcmf_usbreq), GFP_ATOMIC); if (reqs == NULL) return NULL; req = reqs; for (i = 0; i < qsize; i++) { req->urb = usb_alloc_urb(0, GFP_ATOMIC); if (!req->urb) goto fail; INIT_LIST_HEAD(&req->list); list_add_tail(&req->list, q); req++; } return reqs; fail: brcmf_err("fail!\n"); while (!list_empty(q)) { req = list_entry(q->next, struct brcmf_usbreq, list); if (req) usb_free_urb(req->urb); list_del(q->next); } return NULL; }
s32 brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data, u32 len) { struct brcmf_pub *drvr = ifp->drvr; s32 err; u32 buflen; mutex_lock(&drvr->proto_block); brcmf_dbg(FIL, "name=%s, len=%d\n", name, len); brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n"); buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf, sizeof(drvr->proto_buf)); if (buflen) { err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf, buflen, true); } else { err = -EPERM; brcmf_err("Creating iovar failed\n"); } mutex_unlock(&drvr->proto_block); return err; }
static int brcmf_usb_send_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len) { int ret; u16 size; brcmf_dbg(USB, "Enter\n"); if (devinfo == NULL || buf == NULL || len == 0 || devinfo->ctl_urb == NULL) return -EINVAL; size = len; devinfo->ctl_write.wLength = cpu_to_le16p(&size); devinfo->ctl_urb->transfer_buffer_length = size; devinfo->ctl_urb_status = 0; devinfo->ctl_urb_actual_length = 0; usb_fill_control_urb(devinfo->ctl_urb, devinfo->usbdev, devinfo->ctl_out_pipe, (unsigned char *) &devinfo->ctl_write, buf, size, (usb_complete_t)brcmf_usb_ctlwrite_complete, devinfo); ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC); if (ret < 0) brcmf_err("usb_submit_urb failed %d\n", ret); return ret; }
/** * brcmf_fweh_handle_if_event() - handle IF event. * * @drvr: driver information object. * @item: queue entry. * @ifpp: interface object (may change upon ADD action). */ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, struct brcmf_event_msg *emsg, void *data) { struct brcmf_if_event *ifevent = data; struct brcmf_if *ifp; bool is_p2pdev; int err = 0; brcmf_dbg(EVENT, "action: %u ifidx: %u bsscfgidx: %u flags: %u role: %u\n", ifevent->action, ifevent->ifidx, ifevent->bsscfgidx, ifevent->flags, ifevent->role); /* The P2P Device interface event must not be ignored contrary to what * firmware tells us. Older firmware uses p2p noif, with sta role. * This should be accepted when p2pdev_setup is ongoing. TDLS setup will * use the same ifevent and should be ignored. */ is_p2pdev = ((ifevent->flags & BRCMF_E_IF_FLAG_NOIF) && (ifevent->role == BRCMF_E_IF_ROLE_P2P_CLIENT || ((ifevent->role == BRCMF_E_IF_ROLE_STA) && (drvr->fweh.p2pdev_setup_ongoing)))); if (!is_p2pdev && (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) { brcmf_dbg(EVENT, "event can be ignored\n"); return; } if (ifevent->ifidx >= BRCMF_MAX_IFS) { brcmf_err("invalid interface index: %u\n", ifevent->ifidx); return; } ifp = drvr->iflist[ifevent->bsscfgidx]; if (ifevent->action == BRCMF_E_IF_ADD) { brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname, emsg->addr); ifp = brcmf_add_if(drvr, ifevent->bsscfgidx, ifevent->ifidx, is_p2pdev, emsg->ifname, emsg->addr); if (IS_ERR(ifp)) return; if (!is_p2pdev) brcmf_fws_add_interface(ifp); if (!drvr->fweh.evt_handler[BRCMF_E_IF]) if (brcmf_net_attach(ifp, false) < 0) return; } if (ifp && ifevent->action == BRCMF_E_IF_CHANGE) brcmf_fws_reset_interface(ifp); err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data); if (ifp && ifevent->action == BRCMF_E_IF_DEL) { bool armed = brcmf_cfg80211_vif_event_armed(drvr->config); /* Default handling in case no-one waits for this event */ if (!armed) brcmf_remove_interface(ifp, false); } }
struct brcmf_fw_request * brcmf_fw_alloc_request(u32 chip, u32 chiprev, struct brcmf_firmware_mapping mapping_table[], u32 table_size, struct brcmf_fw_name *fwnames, u32 n_fwnames) { struct brcmf_fw_request *fwreq; char chipname[12]; const char *mp_path; u32 i, j; char end; size_t reqsz; for (i = 0; i < table_size; i++) { if (mapping_table[i].chipid == chip && mapping_table[i].revmask & BIT(chiprev)) break; } if (i == table_size) { brcmf_err("Unknown chipid %d [%d]\n", chip, chiprev); return NULL; } reqsz = sizeof(*fwreq) + n_fwnames * sizeof(struct brcmf_fw_item); fwreq = kzalloc(reqsz, GFP_KERNEL); if (!fwreq) return NULL; brcmf_chip_name(chip, chiprev, chipname, sizeof(chipname)); brcmf_info("using %s for chip %s\n", mapping_table[i].fw_base, chipname); mp_path = brcmf_mp_global.firmware_path; end = mp_path[strlen(mp_path) - 1]; fwreq->n_items = n_fwnames; for (j = 0; j < n_fwnames; j++) { fwreq->items[j].path = fwnames[j].path; /* check if firmware path is provided by module parameter */ if (brcmf_mp_global.firmware_path[0] != '\0') { strlcpy(fwnames[j].path, mp_path, BRCMF_FW_NAME_LEN); if (end != '/') { strlcat(fwnames[j].path, "/", BRCMF_FW_NAME_LEN); } } strlcat(fwnames[j].path, mapping_table[i].fw_base, BRCMF_FW_NAME_LEN); strlcat(fwnames[j].path, fwnames[j].extension, BRCMF_FW_NAME_LEN); fwreq->items[j].path = fwnames[j].path; } return fwreq; }
static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev, uint regaddr, u8 *byte) { struct sdio_func *sdfunc = sdiodev->func[0]; int err_ret; /* * Can only directly write to some F0 registers. * Handle F2 enable/disable and Abort command * as a special case. */ if (regaddr == SDIO_CCCR_IOEx) { sdfunc = sdiodev->func[2]; if (sdfunc) { if (*byte & SDIO_FUNC_ENABLE_2) { /* Enable Function 2 */ err_ret = sdio_enable_func(sdfunc); if (err_ret) brcmf_err("enable F2 failed:%d\n", err_ret); } else { /* Disable Function 2 */ err_ret = sdio_disable_func(sdfunc); if (err_ret) brcmf_err("Disable F2 failed:%d\n", err_ret); } } } else if ((regaddr == SDIO_CCCR_ABORT) || (regaddr == SDIO_CCCR_IENx)) { sdfunc = kmemdup(sdiodev->func[0], sizeof(struct sdio_func), GFP_KERNEL); if (!sdfunc) return -ENOMEM; sdfunc->num = 0; sdio_writeb(sdfunc, *byte, regaddr, &err_ret); kfree(sdfunc); } else if (regaddr < 0xF0) { brcmf_err("F0 Wr:0x%02x: write disallowed\n", regaddr); err_ret = -EPERM; } else { sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret); } return err_ret; }
char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx) { if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) { brcmf_err("ifidx %d out of range\n", ifidx); return "<if_bad>"; } if (drvr->iflist[ifidx] == NULL) { brcmf_err("null i/f %d\n", ifidx); return "<if_null>"; } if (drvr->iflist[ifidx]->ndev) return drvr->iflist[ifidx]->ndev->name; return "<if_none>"; }
void brcmf_sdio_register(void) { int ret; ret = sdio_register_driver(&brcmf_sdmmc_driver); if (ret) brcmf_err("sdio_register_driver failed: %d\n", ret); }
static int brcmf_pcie_get_resource(struct brcmf_pciedev_info *devinfo) { struct pci_dev *pdev; int err; phys_addr_t bar0_addr, bar1_addr; ulong bar1_size; pdev = devinfo->pdev; err = pci_enable_device(pdev); if (err) { brcmf_err("pci_enable_device failed err=%d\n", err); return err; } pci_set_master(pdev); /* Bar-0 mapped address */ bar0_addr = pci_resource_start(pdev, 0); /* Bar-1 mapped address */ bar1_addr = pci_resource_start(pdev, 2); /* read Bar-1 mapped memory range */ bar1_size = pci_resource_len(pdev, 2); if ((bar1_size == 0) || (bar1_addr == 0)) { brcmf_err("BAR1 Not enabled, device size=%ld, addr=%#016llx\n", bar1_size, (unsigned long long)bar1_addr); return -EINVAL; } devinfo->regs = ioremap_nocache(bar0_addr, BRCMF_PCIE_REG_MAP_SIZE); devinfo->tcm = ioremap_nocache(bar1_addr, BRCMF_PCIE_TCM_MAP_SIZE); devinfo->tcm_size = BRCMF_PCIE_TCM_MAP_SIZE; if (!devinfo->regs || !devinfo->tcm) { brcmf_err("ioremap() failed (%p,%p)\n", devinfo->regs, devinfo->tcm); return -EINVAL; } brcmf_dbg(PCIE, "Phys addr : reg space = %p base addr %#016llx\n", devinfo->regs, (unsigned long long)bar0_addr); brcmf_dbg(PCIE, "Phys addr : mem space = %p base addr %#016llx\n", devinfo->tcm, (unsigned long long)bar1_addr); return 0; }
void brcmf_pcie_register(void) { int err; brcmf_dbg(PCIE, "Enter\n"); err = pci_register_driver(&brcmf_pciedrvr); if (err) brcmf_err("PCIE driver registration failed, err=%d\n", err); }
void brcmf_usb_register(void) { int ret; brcmf_dbg(USB, "Enter\n"); ret = usb_register(&brcmf_usbdrvr); if (ret) brcmf_err("usb_register failed %d\n", ret); }
static int brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev) { int err = 0; u8 clkval, clkset; /* Try forcing SDIO core to do ALPAvail request only */ clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ; brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); if (err) { brcmf_err("error writing for HT off\n"); return err; } /* If register supported, wait for ALPAvail and then force ALP */ /* This may take up to 15 milliseconds */ clkval = brcmf_sdio_regrb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, NULL); if ((clkval & ~SBSDIO_AVBITS) != clkset) { brcmf_err("ChipClkCSR access: wrote 0x%02x read 0x%02x\n", clkset, clkval); return -EACCES; } SPINWAIT(((clkval = brcmf_sdio_regrb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, NULL)), !SBSDIO_ALPAV(clkval)), PMU_MAX_TRANSITION_DLY); if (!SBSDIO_ALPAV(clkval)) { brcmf_err("timeout on ALPAV wait, clkval 0x%02x\n", clkval); return -EBUSY; } clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP; brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); udelay(65); /* Also, disable the extra SDIO pull-ups */ brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL); return 0; }
static void brcmf_c_pktfilter_offload_enable(struct brcmf_if *ifp, char *arg, int enable, int master_mode) { unsigned long res; char *argv; char *arg_save = NULL, *arg_org = NULL; s32 err; struct brcmf_pkt_filter_enable_le enable_parm; arg_save = kstrdup(arg, GFP_ATOMIC); if (!arg_save) goto fail; arg_org = arg_save; argv = strsep(&arg_save, " "); if (argv == NULL) { brcmf_err("No args provided\n"); goto fail; } /* Parse packet filter id. */ enable_parm.id = 0; if (!kstrtoul(argv, 0, &res)) enable_parm.id = cpu_to_le32((u32)res); /* Enable/disable the specified filter. */ enable_parm.enable = cpu_to_le32(enable); err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_enable", &enable_parm, sizeof(enable_parm)); if (err) brcmf_err("Set pkt_filter_enable error (%d)\n", err); /* Control the master mode */ err = brcmf_fil_iovar_int_set(ifp, "pkt_filter_mode", master_mode); if (err) brcmf_err("Set pkt_filter_mode error (%d)\n", err); fail: kfree(arg_org); }
static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo) { struct brcmf_bus *bus = NULL; struct brcmf_usbdev *bus_pub = NULL; struct device *dev = devinfo->dev; int ret; brcmf_dbg(USB, "Enter\n"); bus_pub = brcmf_usb_attach(devinfo, BRCMF_USB_NRXQ, BRCMF_USB_NTXQ); if (!bus_pub) return -ENODEV; bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC); if (!bus) { ret = -ENOMEM; goto fail; } bus->dev = dev; bus_pub->bus = bus; bus->bus_priv.usb = bus_pub; dev_set_drvdata(dev, bus); bus->ops = &brcmf_usb_bus_ops; bus->proto_type = BRCMF_PROTO_BCDC; bus->always_use_fws_queue = true; #ifdef CONFIG_PM bus->wowl_supported = true; #endif if (!brcmf_usb_dlneeded(devinfo)) { ret = brcmf_usb_bus_setup(devinfo); if (ret) goto fail; /* we are done */ mutex_unlock(&devinfo->dev_init_lock); return 0; } bus->chip = bus_pub->devid; bus->chiprev = bus_pub->chiprev; /* request firmware here */ ret = brcmf_fw_get_firmwares(dev, 0, brcmf_usb_get_fwname(devinfo), NULL, brcmf_usb_probe_phase2); if (ret) { brcmf_err("firmware request failed: %d\n", ret); goto fail; } return 0; fail: /* Release resources in reverse order */ kfree(bus); brcmf_usb_detach(devinfo); return ret; }
static int brcmf_pcie_get_fwnames(struct brcmf_pciedev_info *devinfo) { char *fw_name; char *nvram_name; uint fw_len, nv_len; char end; brcmf_dbg(PCIE, "Enter, chip 0x%04x chiprev %d\n", devinfo->ci->chip, devinfo->ci->chiprev); switch (devinfo->ci->chip) { case BRCM_CC_43602_CHIP_ID: fw_name = BRCMF_PCIE_43602_FW_NAME; nvram_name = BRCMF_PCIE_43602_NVRAM_NAME; break; case BRCM_CC_4354_CHIP_ID: fw_name = BRCMF_PCIE_4354_FW_NAME; nvram_name = BRCMF_PCIE_4354_NVRAM_NAME; break; case BRCM_CC_4356_CHIP_ID: fw_name = BRCMF_PCIE_4356_FW_NAME; nvram_name = BRCMF_PCIE_4356_NVRAM_NAME; break; case BRCM_CC_43567_CHIP_ID: case BRCM_CC_43569_CHIP_ID: case BRCM_CC_43570_CHIP_ID: fw_name = BRCMF_PCIE_43570_FW_NAME; nvram_name = BRCMF_PCIE_43570_NVRAM_NAME; break; default: brcmf_err("Unsupported chip 0x%04x\n", devinfo->ci->chip); return -ENODEV; } fw_len = sizeof(devinfo->fw_name) - 1; nv_len = sizeof(devinfo->nvram_name) - 1; /* check if firmware path is provided by module parameter */ if (brcmf_firmware_path[0] != '\0') { strncpy(devinfo->fw_name, brcmf_firmware_path, fw_len); strncpy(devinfo->nvram_name, brcmf_firmware_path, nv_len); fw_len -= strlen(devinfo->fw_name); nv_len -= strlen(devinfo->nvram_name); end = brcmf_firmware_path[strlen(brcmf_firmware_path) - 1]; if (end != '/') { strncat(devinfo->fw_name, "/", fw_len); strncat(devinfo->nvram_name, "/", nv_len); fw_len--; nv_len--; } } strncat(devinfo->fw_name, fw_name, fw_len); strncat(devinfo->nvram_name, nvram_name, nv_len); return 0; }
int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, uint rw, uint func, uint addr, u32 *word, uint nbytes) { int err_ret = -EIO; if (func == 0) { brcmf_err("Only CMD52 allowed to F0\n"); return -EINVAL; } brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", rw, func, addr, nbytes); brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait); if (brcmf_pm_resume_error(sdiodev)) return -EIO; if (rw) { /* CMD52 Write */ if (nbytes == 4) sdio_writel(sdiodev->func[func], *word, addr, &err_ret); else if (nbytes == 2) sdio_writew(sdiodev->func[func], (*word & 0xFFFF), addr, &err_ret); else brcmf_err("Invalid nbytes: %d\n", nbytes); } else { /* CMD52 Read */ if (nbytes == 4) *word = sdio_readl(sdiodev->func[func], addr, &err_ret); else if (nbytes == 2) *word = sdio_readw(sdiodev->func[func], addr, &err_ret) & 0xFFFF; else brcmf_err("Invalid nbytes: %d\n", nbytes); } if (err_ret) brcmf_err("Failed to %s word, Err: 0x%08x\n", rw ? "write" : "read", err_ret); return err_ret; }