staging: wfx: add support for start-up indication
Once firmware is loaded, it send a first indication to host. This indication signalize that host can start to communicate with firmware. In add, it contains information about chip and firmware (MAC addresses, firmware version, etc...). Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com> Link: https://lore.kernel.org/r/20190919142527.31797-10-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
1cc298c915
commit
185c106f79
|
@ -7,6 +7,7 @@ wfx-y := \
|
|||
bh.o \
|
||||
hwio.o \
|
||||
fwio.o \
|
||||
hif_rx.o \
|
||||
main.o \
|
||||
debug.o
|
||||
wfx-$(CONFIG_SPI) += bus_spi.o
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "wfx.h"
|
||||
#include "hwio.h"
|
||||
#include "traces.h"
|
||||
#include "hif_rx.h"
|
||||
#include "hif_api_cmd.h"
|
||||
|
||||
static void device_wakeup(struct wfx_dev *wdev)
|
||||
|
@ -107,7 +108,8 @@ static int rx_helper(struct wfx_dev *wdev, size_t read_len, int *is_cnf)
|
|||
}
|
||||
|
||||
skb_put(skb, hif->len);
|
||||
dev_kfree_skb(skb); /* FIXME: handle received data */
|
||||
// wfx_handle_rx takes care on SKB livetime
|
||||
wfx_handle_rx(wdev, skb);
|
||||
|
||||
return piggyback;
|
||||
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Implementation of chip-to-host event (aka indications) of WFxxx Split Mac
|
||||
* (WSM) API.
|
||||
*
|
||||
* Copyright (c) 2017-2019, Silicon Laboratories, Inc.
|
||||
* Copyright (c) 2010, ST-Ericsson
|
||||
*/
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/etherdevice.h>
|
||||
|
||||
#include "hif_rx.h"
|
||||
#include "wfx.h"
|
||||
#include "hif_api_cmd.h"
|
||||
|
||||
static int hif_startup_indication(struct wfx_dev *wdev, struct hif_msg *hif, void *buf)
|
||||
{
|
||||
struct hif_ind_startup *body = buf;
|
||||
|
||||
if (body->status || body->firmware_type > 4) {
|
||||
dev_err(wdev->dev, "received invalid startup indication");
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(&wdev->hw_caps, body, sizeof(struct hif_ind_startup));
|
||||
le32_to_cpus(&wdev->hw_caps.status);
|
||||
le16_to_cpus(&wdev->hw_caps.hardware_id);
|
||||
le16_to_cpus(&wdev->hw_caps.num_inp_ch_bufs);
|
||||
le16_to_cpus(&wdev->hw_caps.size_inp_ch_buf);
|
||||
|
||||
complete(&wdev->firmware_ready);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
int msg_id;
|
||||
int (*handler)(struct wfx_dev *wdev, struct hif_msg *hif, void *buf);
|
||||
} hif_handlers[] = {
|
||||
{ HIF_IND_ID_STARTUP, hif_startup_indication },
|
||||
};
|
||||
|
||||
void wfx_handle_rx(struct wfx_dev *wdev, struct sk_buff *skb)
|
||||
{
|
||||
int i;
|
||||
struct hif_msg *hif = (struct hif_msg *) skb->data;
|
||||
int hif_id = hif->id;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hif_handlers); i++) {
|
||||
if (hif_handlers[i].msg_id == hif_id) {
|
||||
if (hif_handlers[i].handler)
|
||||
hif_handlers[i].handler(wdev, hif, hif->body);
|
||||
goto free;
|
||||
}
|
||||
}
|
||||
dev_err(wdev->dev, "unsupported HIF ID %02x\n", hif_id);
|
||||
free:
|
||||
dev_kfree_skb(skb);
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Implementation of chip-to-host event (aka indications) of WFxxx Split Mac
|
||||
* (WSM) API.
|
||||
*
|
||||
* Copyright (c) 2017-2019, Silicon Laboratories, Inc.
|
||||
* Copyright (c) 2010, ST-Ericsson
|
||||
* Copyright (C) 2010, ST-Ericsson SA
|
||||
*/
|
||||
#ifndef WFX_HIF_RX_H
|
||||
#define WFX_HIF_RX_H
|
||||
|
||||
struct wfx_dev;
|
||||
struct sk_buff;
|
||||
|
||||
void wfx_handle_rx(struct wfx_dev *wdev, struct sk_buff *skb);
|
||||
|
||||
#endif
|
|
@ -12,6 +12,7 @@
|
|||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
|
@ -87,6 +88,9 @@ struct wfx_dev *wfx_init_common(struct device *dev,
|
|||
wdev->hwbus_ops = hwbus_ops;
|
||||
wdev->hwbus_priv = hwbus_priv;
|
||||
memcpy(&wdev->pdata, pdata, sizeof(*pdata));
|
||||
|
||||
init_completion(&wdev->firmware_ready);
|
||||
|
||||
return wdev;
|
||||
}
|
||||
|
||||
|
@ -96,7 +100,9 @@ void wfx_free_common(struct wfx_dev *wdev)
|
|||
|
||||
int wfx_probe(struct wfx_dev *wdev)
|
||||
{
|
||||
int i;
|
||||
int err;
|
||||
const void *macaddr;
|
||||
|
||||
wfx_bh_register(wdev);
|
||||
|
||||
|
@ -104,6 +110,45 @@ int wfx_probe(struct wfx_dev *wdev)
|
|||
if (err)
|
||||
goto err1;
|
||||
|
||||
err = wait_for_completion_interruptible_timeout(&wdev->firmware_ready, 10 * HZ);
|
||||
if (err <= 0) {
|
||||
if (err == 0) {
|
||||
dev_err(wdev->dev, "timeout while waiting for startup indication. IRQ configuration error?\n");
|
||||
err = -ETIMEDOUT;
|
||||
} else if (err == -ERESTARTSYS) {
|
||||
dev_info(wdev->dev, "probe interrupted by user\n");
|
||||
}
|
||||
goto err1;
|
||||
}
|
||||
|
||||
// FIXME: fill wiphy::hw_version
|
||||
dev_info(wdev->dev, "started firmware %d.%d.%d \"%s\" (API: %d.%d, keyset: %02X, caps: 0x%.8X)\n",
|
||||
wdev->hw_caps.firmware_major, wdev->hw_caps.firmware_minor,
|
||||
wdev->hw_caps.firmware_build, wdev->hw_caps.firmware_label,
|
||||
wdev->hw_caps.api_version_major, wdev->hw_caps.api_version_minor,
|
||||
wdev->keyset, *((u32 *) &wdev->hw_caps.capabilities));
|
||||
|
||||
if (wfx_api_older_than(wdev, 1, 0)) {
|
||||
dev_err(wdev->dev, "unsupported firmware API version (expect 1 while firmware returns %d)\n",
|
||||
wdev->hw_caps.api_version_major);
|
||||
err = -ENOTSUPP;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wdev->addresses); i++) {
|
||||
eth_zero_addr(wdev->addresses[i].addr);
|
||||
macaddr = of_get_mac_address(wdev->dev->of_node);
|
||||
if (macaddr) {
|
||||
ether_addr_copy(wdev->addresses[i].addr, macaddr);
|
||||
wdev->addresses[i].addr[ETH_ALEN - 1] += i;
|
||||
}
|
||||
ether_addr_copy(wdev->addresses[i].addr, wdev->hw_caps.mac_addr[i]);
|
||||
if (!is_valid_ether_addr(wdev->addresses[i].addr)) {
|
||||
dev_warn(wdev->dev, "using random MAC address\n");
|
||||
eth_random_addr(wdev->addresses[i].addr);
|
||||
}
|
||||
dev_info(wdev->dev, "MAC address %d: %pM\n", i, wdev->addresses[i].addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
#ifndef WFX_H
|
||||
#define WFX_H
|
||||
|
||||
#include <linux/completion.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "bh.h"
|
||||
#include "main.h"
|
||||
#include "hif_api_general.h"
|
||||
|
@ -19,10 +22,12 @@ struct hwbus_ops;
|
|||
struct wfx_dev {
|
||||
struct wfx_platform_data pdata;
|
||||
struct device *dev;
|
||||
struct mac_address addresses[2];
|
||||
const struct hwbus_ops *hwbus_ops;
|
||||
void *hwbus_priv;
|
||||
|
||||
u8 keyset;
|
||||
struct completion firmware_ready;
|
||||
struct hif_ind_startup hw_caps;
|
||||
struct wfx_hif hif;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue