static int __init gpio_test_init(void) { const struct wl12xx_platform_data *wlan_data; wlan_data = wl12xx_get_platform_data(); bt_enable_pin = wlan_data->bt_enable_gpio; /* Default to alpha EVM in case the element is not initialized */ if (! bt_enable_pin) { pr_info("BT Enable pin is not initialized, defaulting to EVM Rev 1.0A.\n"); bt_enable_pin = GPIO_TO_PIN(1, 31); } /* Select pad conf register based on EVM board rev */ if ( bt_enable_pin == GPIO_TO_PIN(3, 21) ) selected_pad = AM33XX_CONTROL_PADCONF_MCASP0_AHCLKX_OFFSET; else selected_pad = AM33XX_CONTROL_PADCONF_GPMC_CSN2_OFFSET; printk("Gpio value is :%d\n", bt_enable_pin); gpio_direction_output(bt_enable_pin, 0); msleep(1); printk("WL1271: BT Enable\n"); gpio_direction_output(bt_enable_pin, 1); /* Enable pullup on the enable pin for keeping BT active during suspend */ pad_mux_value = readl(AM33XX_CTRL_REGADDR(selected_pad)); pad_mux_value &= (~AM33XX_PULL_DISA); writel(pad_mux_value, AM33XX_CTRL_REGADDR(selected_pad)); return 0; }
static struct wl12xx_platform_data *get_platform_data(struct device *dev) { struct wl12xx_platform_data *pdata; struct device_node __maybe_unused *np; pdata = wl12xx_get_platform_data(); if (!IS_ERR(pdata)) return kmemdup(pdata, sizeof(*pdata), GFP_KERNEL); #ifdef CONFIG_OF /* first, try looking for "upstream" dt */ pdata = wlcore_probe_of(dev); if (pdata) return pdata; /* if not found, look for our deprecated dt */ np = of_find_matching_node(NULL, wlcore_of_match); if (!np) { dev_err(dev, "No platform data set\n"); return NULL; } pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); if (!pdata) { dev_err(dev, "Can't allocate platform data\n"); return NULL; } if (of_property_read_u32(np, "irq", &pdata->irq)) { u32 gpio; if (!of_property_read_u32(np, "gpio", &gpio) && !gpio_request_one(gpio, GPIOF_IN, "wlcore_irq")) pdata->gpio = gpio; } /* Optional fields */ pdata->use_eeprom = of_property_read_bool(np, "use-eeprom"); of_property_read_u32(np, "board-ref-clock", &pdata->board_ref_clock); of_property_read_u32(np, "board-tcxo-clock", &pdata->board_tcxo_clock); of_property_read_u32(np, "platform-quirks", &pdata->platform_quirks); #endif if (IS_ERR(pdata)) return NULL; return pdata; }
static int wl1271_probe(struct sdio_func *func, const struct sdio_device_id *id) { struct wlcore_platdev_data pdev_data; struct wl12xx_sdio_glue *glue; struct resource res[1]; mmc_pm_flag_t mmcflags; int ret = -ENOMEM; const char *chip_family; /* We are only able to handle the wlan function */ if (func->num != 0x02) return -ENODEV; memset(&pdev_data, 0x00, sizeof(pdev_data)); pdev_data.if_ops = &sdio_ops; glue = kzalloc(sizeof(*glue), GFP_KERNEL); if (!glue) { dev_err(&func->dev, "can't allocate glue\n"); goto out; } glue->dev = &func->dev; /* 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; pdev_data.pdata = wl12xx_get_platform_data(); if (IS_ERR(pdev_data.pdata)) { ret = PTR_ERR(pdev_data.pdata); dev_err(glue->dev, "missing wlan platform data: %d\n", ret); goto out_free_glue; } /* if sdio can keep power while host is suspended, enable wow */ mmcflags = sdio_get_host_pm_caps(func); dev_dbg(glue->dev, "sdio PM caps = 0x%x\n", mmcflags); if (mmcflags & MMC_PM_KEEP_POWER) pdev_data.pdata->pwr_in_suspend = true; sdio_set_drvdata(func, glue); /* Tell PM core that we don't need the card to be powered now */ pm_runtime_put_noidle(&func->dev); /* * Due to a hardware bug, we can't differentiate wl18xx from * wl12xx, because both report the same device ID. The only * way to differentiate is by checking the SDIO revision, * which is 3.00 on the wl18xx chips. */ if (func->card->cccr.sdio_vsn == SDIO_SDIO_REV_3_00) chip_family = "wl18xx"; else chip_family = "wl12xx"; glue->core = platform_device_alloc(chip_family, PLATFORM_DEVID_AUTO); if (!glue->core) { dev_err(glue->dev, "can't allocate platform_device"); ret = -ENOMEM; goto out_free_glue; } glue->core->dev.parent = &func->dev; memset(res, 0x00, sizeof(res)); res[0].start = pdev_data.pdata->irq; res[0].flags = IORESOURCE_IRQ; res[0].name = "irq"; ret = platform_device_add_resources(glue->core, res, ARRAY_SIZE(res)); if (ret) { dev_err(glue->dev, "can't add resources\n"); goto out_dev_put; } ret = platform_device_add_data(glue->core, &pdev_data, sizeof(pdev_data)); if (ret) { dev_err(glue->dev, "can't add platform data\n"); goto out_dev_put; } ret = platform_device_add(glue->core); if (ret) { dev_err(glue->dev, "can't add platform device\n"); goto out_dev_put; } return 0; out_dev_put: platform_device_put(glue->core); out_free_glue: kfree(glue); out: 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; 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; if (wl->ref_clock < 0) wl->ref_clock = wlan_data->board_ref_clock; if (wl->tcxo_clock < 0) 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; } disable_irq(wl->irq); sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); 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); mmc_power_save_host(func->card->host); return 0; out_irq: free_irq(wl->irq, wl); out_free: wl1271_free_hw(wl); return ret; }
static int wl1251_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) { int ret, t; struct wl1251 *wl; struct ieee80211_hw *hw; struct wl1251_sdio *wl_sdio; const struct wl12xx_platform_data *wl12xx_board_data; hw = wl1251_alloc_hw(); if (IS_ERR(hw)) return PTR_ERR(hw); wl = hw->priv; wl_sdio = kzalloc(sizeof(*wl_sdio), GFP_KERNEL); if (wl_sdio == NULL) { ret = -ENOMEM; goto out_free_hw; } sdio_claim_host(func); ret = sdio_enable_func(func); if (ret) goto release; sdio_set_block_size(func, 512); sdio_release_host(func); SET_IEEE80211_DEV(hw, &func->dev); wl_sdio->func = func; wl->if_priv = wl_sdio; wl->if_ops = &wl1251_sdio_ops; wl12xx_board_data = wl12xx_get_platform_data(); if (!IS_ERR(wl12xx_board_data)) { wl->set_power = wl12xx_board_data->set_power; wl->irq = wl12xx_board_data->irq; wl->use_eeprom = wl12xx_board_data->use_eeprom; } if (force_nvs_file) wl->use_eeprom = false; wl->dump_eeprom = dump_eeprom; if (wl->irq) { irq_set_status_flags(wl->irq, IRQ_NOAUTOEN); ret = request_threaded_irq(wl->irq, NULL, wl1251_irq, IRQF_ONESHOT, "wl1251", wl); if (ret < 0) { wl1251_error("request_irq() failed: %d", ret); goto disable; } irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq; wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq; wl1251_info("using dedicated interrupt line"); } else { wl1251_sdio_ops.enable_irq = wl1251_sdio_enable_irq; wl1251_sdio_ops.disable_irq = wl1251_sdio_disable_irq; wl1251_info("using SDIO interrupt"); } ret = wl1251_init_ieee80211(wl); if (ret) goto out_free_irq; sdio_set_drvdata(func, wl); for (t = 0; t < ARRAY_SIZE(wl1251_attrs); t++) { ret = device_create_file(&func->dev, &wl1251_attrs[t]); if (ret) { while (--t >= 0) device_remove_file(&func->dev, &wl1251_attrs[t]); goto out_free_irq; } } /* Tell PM core that we don't need the card to be powered now */ pm_runtime_put_noidle(&func->dev); return ret; out_free_irq: if (wl->irq) free_irq(wl->irq, wl); disable: sdio_claim_host(func); sdio_disable_func(func); release: sdio_release_host(func); kfree(wl_sdio); out_free_hw: wl1251_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 sdio_func *func, const struct sdio_device_id *id) { const struct wl12xx_platform_data *wlan_data; struct wl1271 *wl; struct wl1271_test *wl_test; int ret = 0; /* wl1271 has 2 sdio functions we handle just the wlan part */ if (func->num != 0x02) return -ENODEV; wl_test = kzalloc(sizeof(struct wl1271_test), GFP_KERNEL); if (!wl_test) { dev_err(&func->dev, "Could not allocate memory\n"); return -ENOMEM; } wl = &wl_test->wl; 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); dev_err(&func->dev, "missing wlan platform data: %d\n", 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; sdio_set_drvdata(func, wl_test); /* power up the device */ ret = wl1271_chip_wakeup(wl); if (ret) { dev_err(&func->dev, "could not wake up chip\n"); goto out_free; } if (wl->fw == NULL) { ret = wl1271_fetch_firmware(wl); if (ret < 0) { dev_err(&func->dev, "firmware fetch error\n"); goto out_off; } } /* fetch NVS */ if (wl->nvs == NULL) { ret = wl1271_fetch_nvs(wl); if (ret < 0) { dev_err(&func->dev, "NVS fetch error\n"); goto out_off; } } ret = wl1271_load_firmware(wl); if (ret < 0) { dev_err(&func->dev, "firmware load error: %d\n", ret); goto out_free; } dev_info(&func->dev, "initialized\n"); /* I/O testing will be done in the tester thread */ wl_test->test_task = kthread_run(tester, wl, "sdio_tester"); if (IS_ERR(wl_test->test_task)) { dev_err(&func->dev, "unable to create kernel thread\n"); ret = PTR_ERR(wl_test->test_task); goto out_free; } return 0; out_off: /* power off the chip */ wl1271_power_off(wl); out_free: kfree(wl_test); return ret; }