static int wl1271_chip_wakeup(struct wl1271 *wl) { struct wl1271_partition_set partition; int ret; msleep(WL1271_PRE_POWER_ON_SLEEP); ret = wl1271_power_on(wl); if (ret) return ret; msleep(WL1271_POWER_ON_SLEEP); /* We don't need a real memory partition here, because we only want * to use the registers at this point. */ memset(&partition, 0, sizeof(partition)); partition.reg.start = REGISTERS_BASE; partition.reg.size = REGISTERS_DOWN_SIZE; wl1271_set_partition(wl, &partition); /* ELP module wake up */ wl1271_fw_wakeup(wl); /* whal_FwCtrl_BootSm() */ /* 0. read chip id from CHIP_ID */ wl->chip.id = wl1271_read32(wl, CHIP_ID_B); /* 1. check if chip id is valid */ switch (wl->chip.id) { case CHIP_ID_1271_PG10: wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete", wl->chip.id); break; case CHIP_ID_1271_PG20: wl1271_notice("chip id 0x%x (1271 PG20)", wl->chip.id); break; case CHIP_ID_1283_PG20: wl1271_notice("chip id 0x%x (1283 PG20)", wl->chip.id); break; case CHIP_ID_1283_PG10: default: wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); return -ENODEV; } return ret; }
int wl1271_plt_stop(struct wl1271 *wl) { int ret = 0; mutex_lock(&wl->mutex); wl1271_notice("power down"); if (wl->state != WL1271_STATE_PLT) { wl1271_error("cannot power down because not in PLT " "state: %d", wl->state); ret = -EBUSY; goto out; } wl1271_disable_interrupts(wl); wl1271_power_off(wl); wl->state = WL1271_STATE_OFF; out: mutex_unlock(&wl->mutex); return ret; }
int wl1271_plt_start(struct wl1271 *wl) { int ret; mutex_lock(&wl->mutex); wl1271_notice("power up"); if (wl->state != WL1271_STATE_OFF) { wl1271_error("cannot go into PLT state because not " "in off state: %d", wl->state); ret = -EBUSY; goto out; } wl->state = WL1271_STATE_PLT; ret = wl1271_chip_wakeup(wl); if (ret < 0) goto out; ret = wl1271_boot(wl); if (ret < 0) goto out; wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver); ret = wl1271_plt_init(wl); if (ret < 0) goto out; out: mutex_unlock(&wl->mutex); return ret; }
static int wl1271_register_hw(struct wl1271 *wl) { int ret; if (wl->mac80211_registered) return 0; SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); ret = ieee80211_register_hw(wl->hw); if (ret < 0) { wl1271_error("unable to register mac80211 hw: %d", ret); return ret; } wl->mac80211_registered = true; wl1271_notice("loaded"); return 0; }
int wl1271_cmd_cal(struct wl1271 *wl) { int ret; wl1271_notice("performing tx calibration"); ret = wl1271_cmd_cal_channel_tune(wl); if (ret < 0) return ret; ret = wl1271_cmd_cal_update_ref_point(wl); if (ret < 0) return ret; ret = wl1271_cmd_cal_p2g(wl); if (ret < 0) return ret; return ret; }
int wl1271_cmd_cal(struct wl1271 *wl) { /* * FIXME: we must make sure that we're not sleeping when calibration * is done */ int ret; wl1271_notice("performing tx calibration"); ret = wl1271_cmd_cal_channel_tune(wl); if (ret < 0) return ret; ret = wl1271_cmd_cal_update_ref_point(wl); if (ret < 0) return ret; ret = wl1271_cmd_cal_p2g(wl); if (ret < 0) return ret; return ret; }
static void __exit wl1271_exit(void) { sdio_unregister_driver(&wl1271_sdio_driver); wl1271_notice("unloaded"); }
static int __devinit wl1271_probe(struct sdio_func *func, const struct sdio_device_id *id) { struct ieee80211_hw *hw; struct wl1271 *wl; int ret; /* We are only able to handle the wlan function */ if (func->num != 0x02) return -ENODEV; hw = wl1271_alloc_hw(); if (IS_ERR(hw)) return PTR_ERR(hw); wl = hw->priv; wl->if_priv = func; wl->if_ops = &sdio_ops; /* Grab access to FN0 for ELP reg. */ func->card->quirks |= MMC_QUIRK_LENIENT_FN0; wl->irq = gpio_to_irq(RX71_WL1271_IRQ_GPIO); if (wl->irq < 0) { ret = wl->irq; wl1271_error("could not get irq!"); goto out_free; } ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); if (ret < 0) { wl1271_error("request_irq() failed: %d", ret); goto out_free; } set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); disable_irq(wl->irq); ret = wl1271_init_ieee80211(wl); if (ret) goto out_irq; ret = wl1271_register_hw(wl); if (ret) goto out_irq; sdio_set_drvdata(func, wl); wl1271_notice("initialized"); return 0; out_irq: free_irq(wl->irq, wl); out_free: wl1271_free_hw(wl); return ret; }
static int __devinit wl1271_probe(struct spi_device *spi) { struct wl12xx_platform_data *pdata; struct ieee80211_hw *hw; struct wl1271 *wl; int ret, i; static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; pdata = spi->dev.platform_data; if (!pdata) { wl1271_error("no platform data"); return -ENODEV; } hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); if (!hw) { wl1271_error("could not alloc ieee80211_hw"); return -ENOMEM; } wl = hw->priv; memset(wl, 0, sizeof(*wl)); wl->hw = hw; dev_set_drvdata(&spi->dev, wl); wl->spi = spi; skb_queue_head_init(&wl->tx_queue); INIT_WORK(&wl->filter_work, wl1271_filter_work); wl->channel = WL1271_DEFAULT_CHANNEL; wl->scanning = false; wl->default_key = 0; wl->listen_int = 1; wl->rx_counter = 0; wl->rx_config = WL1271_DEFAULT_RX_CONFIG; wl->rx_filter = WL1271_DEFAULT_RX_FILTER; wl->elp = false; wl->psm = 0; wl->psm_requested = false; wl->tx_queue_stopped = false; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) wl->tx_frames[i] = NULL; spin_lock_init(&wl->wl_lock); memcpy(wl->mac_addr, nokia_oui, 3); get_random_bytes(wl->mac_addr + 3, 3); wl->state = WL1271_STATE_OFF; mutex_init(&wl->mutex); wl->rx_descriptor = kmalloc(sizeof(*wl->rx_descriptor), GFP_KERNEL); if (!wl->rx_descriptor) { wl1271_error("could not allocate memory for rx descriptor"); ret = -ENOMEM; goto out_free; } spi->bits_per_word = 32; ret = spi_setup(spi); if (ret < 0) { wl1271_error("spi_setup failed"); goto out_free; } wl->set_power = pdata->set_power; if (!wl->set_power) { wl1271_error("set power function missing in platform data"); ret = -ENODEV; goto out_free; } wl->irq = spi->irq; if (wl->irq < 0) { wl1271_error("irq missing in platform data"); ret = -ENODEV; goto out_free; } ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); if (ret < 0) { wl1271_error("request_irq() failed: %d", ret); goto out_free; } set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); disable_irq(wl->irq); ret = platform_device_register(&wl1271_device); if (ret) { wl1271_error("couldn't register platform device"); goto out_irq; } dev_set_drvdata(&wl1271_device.dev, wl); ret = wl1271_init_ieee80211(wl); if (ret) goto out_platform; ret = wl1271_register_hw(wl); if (ret) goto out_platform; wl1271_debugfs_init(wl); wl1271_notice("initialized"); return 0; out_platform: platform_device_unregister(&wl1271_device); out_irq: free_irq(wl->irq, wl); out_free: kfree(wl->rx_descriptor); wl->rx_descriptor = NULL; ieee80211_free_hw(hw); return ret; }
static int __devinit wl1271_probe(struct spi_device *spi) { struct wl12xx_platform_data *pdata; struct ieee80211_hw *hw; struct wl1271 *wl; unsigned long irqflags; int ret; pdata = spi->dev.platform_data; if (!pdata) { wl1271_error("no platform data"); return -ENODEV; } hw = wl1271_alloc_hw(); if (IS_ERR(hw)) return PTR_ERR(hw); wl = hw->priv; dev_set_drvdata(&spi->dev, wl); wl->if_priv = spi; wl->if_ops = &spi_ops; /* This is the only SPI value that we need to set here, the rest * comes from the board-peripherals file */ spi->bits_per_word = 32; ret = spi_setup(spi); if (ret < 0) { wl1271_error("spi_setup failed"); goto out_free; } wl->set_power = pdata->set_power; if (!wl->set_power) { wl1271_error("set power function missing in platform data"); ret = -ENODEV; goto out_free; } wl->ref_clock = pdata->board_ref_clock; wl->tcxo_clock = pdata->board_tcxo_clock; wl->platform_quirks = pdata->platform_quirks; if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) irqflags = IRQF_TRIGGER_RISING; else irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; wl->irq = spi->irq; if (wl->irq < 0) { wl1271_error("irq missing in platform data"); ret = -ENODEV; goto out_free; } ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, irqflags, DRIVER_NAME, wl); if (ret < 0) { wl1271_error("request_irq() failed: %d", ret); goto out_free; } disable_irq(wl->irq); ret = wl1271_init_ieee80211(wl); if (ret) goto out_irq; ret = wl1271_register_hw(wl); if (ret) goto out_irq; wl1271_notice("initialized"); return 0; out_irq: free_irq(wl->irq, wl); out_free: wl1271_free_hw(wl); return ret; }
static int __devinit wl1271_probe(struct sdio_func *func, const struct sdio_device_id *id) { struct ieee80211_hw *hw; const struct wl12xx_platform_data *wlan_data; struct wl1271 *wl; unsigned long irqflags; mmc_pm_flag_t mmcflags; int ret; /* We are only able to handle the wlan function */ if (func->num != 0x02) return -ENODEV; hw = wl1271_alloc_hw(); if (IS_ERR(hw)) return PTR_ERR(hw); wl = hw->priv; wl->if_priv = func; wl->if_ops = &sdio_ops; /* Grab access to FN0 for ELP reg. */ func->card->quirks |= MMC_QUIRK_LENIENT_FN0; /* Use block mode for transferring over one block size of data */ func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; wlan_data = wl12xx_get_platform_data(); if (IS_ERR(wlan_data)) { ret = PTR_ERR(wlan_data); wl1271_error("missing wlan platform data: %d", ret); goto out_free; } wl->irq = wlan_data->irq; wl->ref_clock = wlan_data->board_ref_clock; wl->tcxo_clock = wlan_data->board_tcxo_clock; wl->platform_quirks = wlan_data->platform_quirks; if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) irqflags = IRQF_TRIGGER_RISING; else irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, irqflags, DRIVER_NAME, wl); if (ret < 0) { wl1271_error("request_irq() failed: %d", ret); goto out_free; } enable_irq_wake(wl->irq); device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 1); disable_irq(wl->irq); /* if sdio can keep power while host is suspended, enable wow */ mmcflags = sdio_get_host_pm_caps(func); wl1271_debug(DEBUG_SDIO, "sdio PM caps = 0x%x", mmcflags); if (mmcflags & MMC_PM_KEEP_POWER) hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY; ret = wl1271_init_ieee80211(wl); if (ret) goto out_irq; ret = wl1271_register_hw(wl); if (ret) goto out_irq; sdio_set_drvdata(func, wl); /* Tell PM core that we don't need the card to be powered now */ pm_runtime_put_noidle(&func->dev); wl->set_power = wlan_data->set_power; wl1271_notice("initialized"); return 0; out_irq: free_irq(wl->irq, wl); out_free: wl1271_free_hw(wl); return ret; }
static int __devinit wl1271_probe(struct sdio_func *func, const struct sdio_device_id *id) { struct ieee80211_hw *hw; const struct wl12xx_platform_data *wlan_data; struct wl1271 *wl; int ret; /* We are only able to handle the wlan function */ if (func->num != 0x02) return -ENODEV; hw = wl1271_alloc_hw(); if (IS_ERR(hw)) return PTR_ERR(hw); wl = hw->priv; wl->if_priv = func; wl->if_ops = &sdio_ops; /* Grab access to FN0 for ELP reg. */ func->card->quirks |= MMC_QUIRK_LENIENT_FN0; wlan_data = wl12xx_get_platform_data(); if (IS_ERR(wlan_data)) { ret = PTR_ERR(wlan_data); wl1271_error("missing wlan platform data: %d", ret); goto out_free; } wl->irq = wlan_data->irq; wl->ref_clock = wlan_data->board_ref_clock; ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); if (ret < 0) { wl1271_error("request_irq() failed: %d", ret); goto out_free; } set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); disable_irq(wl->irq); ret = wl1271_init_ieee80211(wl); if (ret) goto out_irq; ret = wl1271_register_hw(wl); if (ret) goto out_irq; sdio_set_drvdata(func, wl); /* Tell PM core that we don't need the card to be powered now */ pm_runtime_put_noidle(&func->dev); wl1271_notice("initialized"); return 0; out_irq: free_irq(wl->irq, wl); out_free: wl1271_free_hw(wl); return ret; }
static int __devinit wl1271_probe(struct spi_device *spi) { struct wl12xx_platform_data *pdata; struct ieee80211_hw *hw; struct wl1271 *wl; int ret; pdata = spi->dev.platform_data; if (!pdata) { wl1271_error("no platform data"); return -ENODEV; } hw = wl1271_alloc_hw(); if (IS_ERR(hw)) return PTR_ERR(hw); wl = hw->priv; dev_set_drvdata(&spi->dev, wl); wl->if_priv = spi; wl->if_ops = &spi_ops; /* This is the only SPI value that we need to set here, the rest * comes from the board-peripherals file */ spi->bits_per_word = 32; ret = spi_setup(spi); if (ret < 0) { wl1271_error("spi_setup failed"); goto out_free; } wl->set_power = pdata->set_power; if (!wl->set_power) { wl1271_error("set power function missing in platform data"); ret = -ENODEV; goto out_free; } wl->ref_clock = pdata->board_ref_clock; wl->irq = spi->irq; if (wl->irq < 0) { wl1271_error("irq missing in platform data"); ret = -ENODEV; goto out_free; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) ret = compat_request_threaded_irq(&wl->irq_compat, wl->irq, wl1271_hardirq, wl1271_irq, IRQF_TRIGGER_RISING, DRIVER_NAME, wl); #else ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) IRQF_TRIGGER_RISING, #else IRQF_TRIGGER_HIGH | IRQF_ONESHOT, #endif DRIVER_NAME, wl); #endif if (ret < 0) { wl1271_error("request_irq() failed: %d", ret); goto out_free; } disable_irq(wl->irq); ret = wl1271_init_ieee80211(wl); if (ret) goto out_irq; ret = wl1271_register_hw(wl); if (ret) goto out_irq; wl1271_notice("initialized"); return 0; out_irq: #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) compat_free_threaded_irq(&wl->irq_compat); #else free_irq(wl->irq, wl); #endif out_free: wl1271_free_hw(wl); return ret; }