Lines Matching refs:wdev
169 bool wfx_api_older_than(struct wfx_dev *wdev, int major, int minor) in wfx_api_older_than() argument
171 if (wdev->hw_caps.api_version_major < major) in wfx_api_older_than()
173 if (wdev->hw_caps.api_version_major > major) in wfx_api_older_than()
175 if (wdev->hw_caps.api_version_minor < minor) in wfx_api_older_than()
187 int wfx_send_pds(struct wfx_dev *wdev, u8 *buf, size_t len) in wfx_send_pds() argument
192 dev_err(wdev->dev, "PDS: malformed file (legacy format?)\n"); in wfx_send_pds()
199 dev_err(wdev->dev, "PDS:%d: corrupted file\n", chunk_num); in wfx_send_pds()
203 dev_info(wdev->dev, "PDS:%d: skip unknown data\n", chunk_num); in wfx_send_pds()
207 dev_warn(wdev->dev, "PDS:%d: unexpectedly large chunk\n", chunk_num); in wfx_send_pds()
209 dev_warn(wdev->dev, "PDS:%d: unexpected content\n", chunk_num); in wfx_send_pds()
211 ret = wfx_hif_configuration(wdev, buf + 4, chunk_len - 4); in wfx_send_pds()
213 dev_err(wdev->dev, "PDS:%d: invalid data (unsupported options?)\n", chunk_num); in wfx_send_pds()
217 dev_err(wdev->dev, "PDS:%d: chip didn't reply (corrupted file?)\n", chunk_num); in wfx_send_pds()
221 dev_err(wdev->dev, "PDS:%d: chip returned an unknown error\n", chunk_num); in wfx_send_pds()
232 static int wfx_send_pdata_pds(struct wfx_dev *wdev) in wfx_send_pdata_pds() argument
238 ret = request_firmware(&pds, wdev->pdata.file_pds, wdev->dev); in wfx_send_pdata_pds()
240 dev_err(wdev->dev, "can't load antenna parameters (PDS file %s). The device may be unstable.\n", in wfx_send_pdata_pds()
241 wdev->pdata.file_pds); in wfx_send_pdata_pds()
249 ret = wfx_send_pds(wdev, tmp_buf, pds->size); in wfx_send_pdata_pds()
258 struct wfx_dev *wdev = data; in wfx_free_common() local
260 mutex_destroy(&wdev->tx_power_loop_info_lock); in wfx_free_common()
261 mutex_destroy(&wdev->rx_stats_lock); in wfx_free_common()
262 mutex_destroy(&wdev->scan_lock); in wfx_free_common()
263 mutex_destroy(&wdev->conf_mutex); in wfx_free_common()
264 ieee80211_free_hw(wdev->hw); in wfx_free_common()
271 struct wfx_dev *wdev; in wfx_init_common() local
320 wdev = hw->priv; in wfx_init_common()
321 wdev->hw = hw; in wfx_init_common()
322 wdev->dev = dev; in wfx_init_common()
323 wdev->hwbus_ops = hwbus_ops; in wfx_init_common()
324 wdev->hwbus_priv = hwbus_priv; in wfx_init_common()
325 memcpy(&wdev->pdata, pdata, sizeof(*pdata)); in wfx_init_common()
326 of_property_read_string(dev->of_node, "silabs,antenna-config-file", &wdev->pdata.file_pds); in wfx_init_common()
327 wdev->pdata.gpio_wakeup = devm_gpiod_get_optional(dev, "wakeup", GPIOD_OUT_LOW); in wfx_init_common()
328 if (IS_ERR(wdev->pdata.gpio_wakeup)) in wfx_init_common()
331 if (wdev->pdata.gpio_wakeup) in wfx_init_common()
332 gpiod_set_consumer_name(wdev->pdata.gpio_wakeup, "wfx wakeup"); in wfx_init_common()
334 mutex_init(&wdev->conf_mutex); in wfx_init_common()
335 mutex_init(&wdev->scan_lock); in wfx_init_common()
336 mutex_init(&wdev->rx_stats_lock); in wfx_init_common()
337 mutex_init(&wdev->tx_power_loop_info_lock); in wfx_init_common()
338 init_completion(&wdev->firmware_ready); in wfx_init_common()
339 INIT_DELAYED_WORK(&wdev->cooling_timeout_work, wfx_cooling_timeout_work); in wfx_init_common()
340 skb_queue_head_init(&wdev->tx_pending); in wfx_init_common()
341 init_waitqueue_head(&wdev->tx_dequeue); in wfx_init_common()
342 wfx_init_hif_cmd(&wdev->hif_cmd); in wfx_init_common()
344 if (devm_add_action_or_reset(dev, wfx_free_common, wdev)) in wfx_init_common()
347 return wdev; in wfx_init_common()
354 int wfx_probe(struct wfx_dev *wdev) in wfx_probe() argument
363 gpio_saved = wdev->pdata.gpio_wakeup; in wfx_probe()
364 wdev->pdata.gpio_wakeup = NULL; in wfx_probe()
365 wdev->poll_irq = true; in wfx_probe()
367 wdev->bh_wq = alloc_workqueue("wfx_bh_wq", WQ_HIGHPRI, 0); in wfx_probe()
368 if (!wdev->bh_wq) in wfx_probe()
371 wfx_bh_register(wdev); in wfx_probe()
373 err = wfx_init_device(wdev); in wfx_probe()
377 wfx_bh_poll_irq(wdev); in wfx_probe()
378 err = wait_for_completion_timeout(&wdev->firmware_ready, 1 * HZ); in wfx_probe()
380 dev_err(wdev->dev, "timeout while waiting for startup indication\n"); in wfx_probe()
386 dev_info(wdev->dev, "started firmware %d.%d.%d \"%s\" (API: %d.%d, keyset: %02X, caps: 0x%.8X)\n", in wfx_probe()
387 wdev->hw_caps.firmware_major, wdev->hw_caps.firmware_minor, in wfx_probe()
388 wdev->hw_caps.firmware_build, wdev->hw_caps.firmware_label, in wfx_probe()
389 wdev->hw_caps.api_version_major, wdev->hw_caps.api_version_minor, in wfx_probe()
390 wdev->keyset, wdev->hw_caps.link_mode); in wfx_probe()
391 snprintf(wdev->hw->wiphy->fw_version, in wfx_probe()
392 sizeof(wdev->hw->wiphy->fw_version), in wfx_probe()
394 wdev->hw_caps.firmware_major, in wfx_probe()
395 wdev->hw_caps.firmware_minor, in wfx_probe()
396 wdev->hw_caps.firmware_build); in wfx_probe()
398 if (wfx_api_older_than(wdev, 1, 0)) { in wfx_probe()
399 dev_err(wdev->dev, "unsupported firmware API version (expect 1 while firmware returns %d)\n", in wfx_probe()
400 wdev->hw_caps.api_version_major); in wfx_probe()
405 if (wdev->hw_caps.link_mode == SEC_LINK_ENFORCED) { in wfx_probe()
406 dev_err(wdev->dev, "chip require secure_link, but can't negotiate it\n"); in wfx_probe()
410 if (wdev->hw_caps.region_sel_mode) { in wfx_probe()
411 wdev->hw->wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS; in wfx_probe()
412 wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[11].flags |= in wfx_probe()
414 wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[12].flags |= in wfx_probe()
416 wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[13].flags |= in wfx_probe()
420 dev_dbg(wdev->dev, "sending configuration file %s\n", wdev->pdata.file_pds); in wfx_probe()
421 err = wfx_send_pdata_pds(wdev); in wfx_probe()
425 wdev->poll_irq = false; in wfx_probe()
426 err = wdev->hwbus_ops->irq_subscribe(wdev->hwbus_priv); in wfx_probe()
430 err = wfx_hif_use_multi_tx_conf(wdev, true); in wfx_probe()
432 dev_err(wdev->dev, "misconfigured IRQ?\n"); in wfx_probe()
434 wdev->pdata.gpio_wakeup = gpio_saved; in wfx_probe()
435 if (wdev->pdata.gpio_wakeup) { in wfx_probe()
436 dev_dbg(wdev->dev, "enable 'quiescent' power mode with wakeup GPIO and PDS file %s\n", in wfx_probe()
437 wdev->pdata.file_pds); in wfx_probe()
438 gpiod_set_value_cansleep(wdev->pdata.gpio_wakeup, 1); in wfx_probe()
439 wfx_control_reg_write(wdev, 0); in wfx_probe()
440 wfx_hif_set_operational_mode(wdev, HIF_OP_POWER_MODE_QUIESCENT); in wfx_probe()
442 wfx_hif_set_operational_mode(wdev, HIF_OP_POWER_MODE_DOZE); in wfx_probe()
445 for (i = 0; i < ARRAY_SIZE(wdev->addresses); i++) { in wfx_probe()
446 eth_zero_addr(wdev->addresses[i].addr); in wfx_probe()
447 err = of_get_mac_address(wdev->dev->of_node, wdev->addresses[i].addr); in wfx_probe()
449 wdev->addresses[i].addr[ETH_ALEN - 1] += i; in wfx_probe()
451 ether_addr_copy(wdev->addresses[i].addr, wdev->hw_caps.mac_addr[i]); in wfx_probe()
452 if (!is_valid_ether_addr(wdev->addresses[i].addr)) { in wfx_probe()
453 dev_warn(wdev->dev, "using random MAC address\n"); in wfx_probe()
454 eth_random_addr(wdev->addresses[i].addr); in wfx_probe()
456 dev_info(wdev->dev, "MAC address %d: %pM\n", i, wdev->addresses[i].addr); in wfx_probe()
458 wdev->hw->wiphy->n_addresses = ARRAY_SIZE(wdev->addresses); in wfx_probe()
459 wdev->hw->wiphy->addresses = wdev->addresses; in wfx_probe()
461 if (!wfx_api_older_than(wdev, 3, 8)) in wfx_probe()
462 wdev->hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; in wfx_probe()
464 err = ieee80211_register_hw(wdev->hw); in wfx_probe()
468 err = wfx_debug_init(wdev); in wfx_probe()
475 ieee80211_unregister_hw(wdev->hw); in wfx_probe()
477 wdev->hwbus_ops->irq_unsubscribe(wdev->hwbus_priv); in wfx_probe()
479 wfx_bh_unregister(wdev); in wfx_probe()
480 destroy_workqueue(wdev->bh_wq); in wfx_probe()
484 void wfx_release(struct wfx_dev *wdev) in wfx_release() argument
486 ieee80211_unregister_hw(wdev->hw); in wfx_release()
487 wfx_hif_shutdown(wdev); in wfx_release()
488 wdev->hwbus_ops->irq_unsubscribe(wdev->hwbus_priv); in wfx_release()
489 wfx_bh_unregister(wdev); in wfx_release()
490 destroy_workqueue(wdev->bh_wq); in wfx_release()