mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 02:24:24 +02:00
wifi: wilc1000: Add WILC3000 support
Add support for the WILC3000 chip. The chip is similar to WILC1000, except that the register layout is slightly different and it does not support WPA3/SAE. Reviewed-by: Alexis Lothoré <alexis.lothore@bootlin.com> Tested-by: Alexis Lothoré <alexis.lothore@bootlin.com> Tested-on: WILC1000SD 07 SDIO WILC_WIFI_FW_REL_16_1_2 Tested-on: WILC1000SD 07 SPI WILC_WIFI_FW_REL_16_1_2 Tested-on: WILC3000 A SDIO WILC_WIFI_FW_REL_16_1_1 Tested-on: WILC3000 A SPI WILC_WIFI_FW_REL_16_1_1 Signed-off-by: Ajay Singh <ajay.kathat@microchip.com> Signed-off-by: Marek Vasut <marex@denx.de> Signed-off-by: Kalle Valo <kvalo@kernel.org> Link: https://patch.msgid.link/20241004114551.40236-7-marex@denx.de
This commit is contained in:
parent
fbdf0c5248
commit
e1408c115e
|
|
@ -1855,7 +1855,9 @@ EXPORT_SYMBOL_GPL(wilc_cfg80211_init);
|
|||
|
||||
int wilc_cfg80211_register(struct wilc *wilc)
|
||||
{
|
||||
wilc->wiphy->features |= NL80211_FEATURE_SAE;
|
||||
/* WPA3/SAE supported only on WILC1000 */
|
||||
if (is_wilc1000(wilc->chipid))
|
||||
wilc->wiphy->features |= NL80211_FEATURE_SAE;
|
||||
|
||||
return wiphy_register(wilc->wiphy);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,12 @@
|
|||
#define __WILC1000_FW(api) WILC1000_FW_PREFIX #api ".bin"
|
||||
#define WILC1000_FW(api) __WILC1000_FW(api)
|
||||
|
||||
#define WILC3000_API_VER 1
|
||||
|
||||
#define WILC3000_FW_PREFIX "atmel/wilc3000_wifi_firmware-"
|
||||
#define __WILC3000_FW(api) WILC3000_FW_PREFIX #api ".bin"
|
||||
#define WILC3000_FW(api) __WILC3000_FW(api)
|
||||
|
||||
static irqreturn_t isr_uh_routine(int irq, void *user_data)
|
||||
{
|
||||
struct wilc *wilc = user_data;
|
||||
|
|
@ -196,19 +202,23 @@ static int wilc_wlan_get_firmware(struct net_device *dev)
|
|||
struct wilc_vif *vif = netdev_priv(dev);
|
||||
struct wilc *wilc = vif->wilc;
|
||||
const struct firmware *wilc_fw;
|
||||
char *firmware;
|
||||
int ret;
|
||||
|
||||
if (!is_wilc1000(wilc->chipid))
|
||||
if (is_wilc1000(wilc->chipid))
|
||||
firmware = WILC1000_FW(WILC1000_API_VER);
|
||||
else if (is_wilc3000(wilc->chipid))
|
||||
firmware = WILC3000_FW(WILC3000_API_VER);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
netdev_info(dev, "WILC1000 loading firmware [%s]\n",
|
||||
WILC1000_FW(WILC1000_API_VER));
|
||||
netdev_info(dev, "WILC%d loading firmware [%s]\n",
|
||||
is_wilc1000(wilc->chipid) ? 1000 : 3000,
|
||||
firmware);
|
||||
|
||||
ret = request_firmware(&wilc_fw, WILC1000_FW(WILC1000_API_VER),
|
||||
wilc->dev);
|
||||
ret = request_firmware(&wilc_fw, firmware, wilc->dev);
|
||||
if (ret != 0) {
|
||||
netdev_err(dev, "%s - firmware not available\n",
|
||||
WILC1000_FW(WILC1000_API_VER));
|
||||
netdev_err(dev, "%s - firmware not available\n", firmware);
|
||||
return -EINVAL;
|
||||
}
|
||||
wilc->firmware = wilc_fw;
|
||||
|
|
@ -233,7 +243,7 @@ static int wilc_start_firmware(struct net_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int wilc1000_firmware_download(struct net_device *dev)
|
||||
static int wilc_firmware_download(struct net_device *dev)
|
||||
{
|
||||
struct wilc_vif *vif = netdev_priv(dev);
|
||||
struct wilc *wilc = vif->wilc;
|
||||
|
|
@ -528,7 +538,7 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
|
|||
if (ret)
|
||||
goto fail_irq_enable;
|
||||
|
||||
ret = wilc1000_firmware_download(dev);
|
||||
ret = wilc_firmware_download(dev);
|
||||
if (ret)
|
||||
goto fail_irq_enable;
|
||||
|
||||
|
|
@ -1014,3 +1024,4 @@ EXPORT_SYMBOL_GPL(wilc_netdev_ifc_init);
|
|||
MODULE_DESCRIPTION("Atmel WILC1000 core wireless driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_FIRMWARE(WILC1000_FW(WILC1000_API_VER));
|
||||
MODULE_FIRMWARE(WILC3000_FW(WILC3000_API_VER));
|
||||
|
|
|
|||
|
|
@ -810,13 +810,19 @@ static int wilc_sdio_read_int(struct wilc *wilc, u32 *int_status)
|
|||
cmd.address = WILC_SDIO_EXT_IRQ_FLAG_REG;
|
||||
} else {
|
||||
cmd.function = 0;
|
||||
cmd.address = WILC_SDIO_IRQ_FLAG_REG;
|
||||
cmd.address = is_wilc1000(wilc->chipid) ?
|
||||
WILC1000_SDIO_IRQ_FLAG_REG :
|
||||
WILC3000_SDIO_IRQ_FLAG_REG;
|
||||
}
|
||||
cmd.raw = 0;
|
||||
cmd.read_write = 0;
|
||||
cmd.data = 0;
|
||||
wilc_sdio_cmd52(wilc, &cmd);
|
||||
irq_flags = cmd.data;
|
||||
|
||||
if (sdio_priv->irq_gpio)
|
||||
irq_flags &= is_wilc1000(wilc->chipid) ? 0x1f : 0x0f;
|
||||
|
||||
tmp |= FIELD_PREP(IRG_FLAGS_MASK, cmd.data);
|
||||
|
||||
if (FIELD_GET(UNHANDLED_IRQ_MASK, irq_flags))
|
||||
|
|
@ -838,22 +844,56 @@ static int wilc_sdio_clear_int_ext(struct wilc *wilc, u32 val)
|
|||
if (sdio_priv->irq_gpio)
|
||||
reg = val & (BIT(MAX_NUM_INT) - 1);
|
||||
|
||||
/* select VMM table 0 */
|
||||
if (val & SEL_VMM_TBL0)
|
||||
reg |= BIT(5);
|
||||
/* select VMM table 1 */
|
||||
if (val & SEL_VMM_TBL1)
|
||||
reg |= BIT(6);
|
||||
/* enable VMM */
|
||||
if (val & EN_VMM)
|
||||
reg |= BIT(7);
|
||||
if (is_wilc1000(wilc->chipid)) {
|
||||
/* select VMM table 0 */
|
||||
if (val & SEL_VMM_TBL0)
|
||||
reg |= BIT(5);
|
||||
/* select VMM table 1 */
|
||||
if (val & SEL_VMM_TBL1)
|
||||
reg |= BIT(6);
|
||||
/* enable VMM */
|
||||
if (val & EN_VMM)
|
||||
reg |= BIT(7);
|
||||
} else {
|
||||
if (sdio_priv->irq_gpio && reg) {
|
||||
struct sdio_cmd52 cmd;
|
||||
|
||||
cmd.read_write = 1;
|
||||
cmd.function = 0;
|
||||
cmd.raw = 0;
|
||||
cmd.address = WILC3000_SDIO_IRQ_FLAG_REG;
|
||||
cmd.data = reg;
|
||||
|
||||
ret = wilc_sdio_cmd52(wilc, &cmd);
|
||||
if (ret) {
|
||||
dev_err(&func->dev,
|
||||
"Failed cmd52, set 0xfe data (%d) ...\n",
|
||||
__LINE__);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
reg = 0;
|
||||
/* select VMM table 0 */
|
||||
if (val & SEL_VMM_TBL0)
|
||||
reg |= BIT(0);
|
||||
/* select VMM table 1 */
|
||||
if (val & SEL_VMM_TBL1)
|
||||
reg |= BIT(1);
|
||||
/* enable VMM */
|
||||
if (val & EN_VMM)
|
||||
reg |= BIT(2);
|
||||
}
|
||||
|
||||
if (reg) {
|
||||
struct sdio_cmd52 cmd;
|
||||
|
||||
cmd.read_write = 1;
|
||||
cmd.function = 0;
|
||||
cmd.raw = 0;
|
||||
cmd.address = WILC_SDIO_IRQ_CLEAR_FLAG_REG;
|
||||
cmd.address = is_wilc1000(wilc->chipid) ?
|
||||
WILC1000_SDIO_IRQ_CLEAR_FLAG_REG :
|
||||
WILC3000_SDIO_VMM_TBL_CTRL_REG;
|
||||
cmd.data = reg;
|
||||
|
||||
ret = wilc_sdio_cmd52(wilc, &cmd);
|
||||
|
|
|
|||
|
|
@ -1233,7 +1233,7 @@ static int wilc_validate_chipid(struct wilc *wilc)
|
|||
dev_err(&spi->dev, "Fail cmd read chip id...\n");
|
||||
return ret;
|
||||
}
|
||||
if (!is_wilc1000(chipid)) {
|
||||
if (!is_wilc1000(chipid) && !is_wilc3000(chipid)) {
|
||||
dev_err(&spi->dev, "Unknown chip id 0x%x\n", chipid);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -541,7 +541,7 @@ static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc)
|
|||
return rqe;
|
||||
}
|
||||
|
||||
static int chip_allow_sleep(struct wilc *wilc)
|
||||
static int chip_allow_sleep_wilc1000(struct wilc *wilc)
|
||||
{
|
||||
u32 reg = 0;
|
||||
const struct wilc_hif_func *hif_func = wilc->hif_func;
|
||||
|
|
@ -601,7 +601,41 @@ static int chip_allow_sleep(struct wilc *wilc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int chip_wakeup(struct wilc *wilc)
|
||||
static int chip_allow_sleep_wilc3000(struct wilc *wilc)
|
||||
{
|
||||
u32 reg = 0;
|
||||
int ret;
|
||||
const struct wilc_hif_func *hif_func = wilc->hif_func;
|
||||
|
||||
if (wilc->io_type == WILC_HIF_SDIO) {
|
||||
ret = hif_func->hif_read_reg(wilc, WILC_SDIO_WAKEUP_REG, ®);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = hif_func->hif_write_reg(wilc, WILC_SDIO_WAKEUP_REG,
|
||||
reg & ~WILC_SDIO_WAKEUP_BIT);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
ret = hif_func->hif_read_reg(wilc, WILC_SPI_WAKEUP_REG, ®);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = hif_func->hif_write_reg(wilc, WILC_SPI_WAKEUP_REG,
|
||||
reg & ~WILC_SPI_WAKEUP_BIT);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int chip_allow_sleep(struct wilc *wilc)
|
||||
{
|
||||
if (is_wilc1000(wilc->chipid))
|
||||
return chip_allow_sleep_wilc1000(wilc);
|
||||
else
|
||||
return chip_allow_sleep_wilc3000(wilc);
|
||||
}
|
||||
|
||||
static int chip_wakeup_wilc1000(struct wilc *wilc)
|
||||
{
|
||||
u32 ret = 0;
|
||||
u32 clk_status_val = 0, trials = 0;
|
||||
|
|
@ -613,15 +647,15 @@ static int chip_wakeup(struct wilc *wilc)
|
|||
if (wilc->io_type == WILC_HIF_SDIO) {
|
||||
wakeup_reg = WILC_SDIO_WAKEUP_REG;
|
||||
wakeup_bit = WILC_SDIO_WAKEUP_BIT;
|
||||
clk_status_reg = WILC_SDIO_CLK_STATUS_REG;
|
||||
clk_status_bit = WILC_SDIO_CLK_STATUS_BIT;
|
||||
clk_status_reg = WILC1000_SDIO_CLK_STATUS_REG;
|
||||
clk_status_bit = WILC1000_SDIO_CLK_STATUS_BIT;
|
||||
from_host_to_fw_reg = WILC_SDIO_HOST_TO_FW_REG;
|
||||
from_host_to_fw_bit = WILC_SDIO_HOST_TO_FW_BIT;
|
||||
} else {
|
||||
wakeup_reg = WILC_SPI_WAKEUP_REG;
|
||||
wakeup_bit = WILC_SPI_WAKEUP_BIT;
|
||||
clk_status_reg = WILC_SPI_CLK_STATUS_REG;
|
||||
clk_status_bit = WILC_SPI_CLK_STATUS_BIT;
|
||||
clk_status_reg = WILC1000_SPI_CLK_STATUS_REG;
|
||||
clk_status_bit = WILC1000_SPI_CLK_STATUS_BIT;
|
||||
from_host_to_fw_reg = WILC_SPI_HOST_TO_FW_REG;
|
||||
from_host_to_fw_bit = WILC_SPI_HOST_TO_FW_BIT;
|
||||
}
|
||||
|
|
@ -663,6 +697,74 @@ static int chip_wakeup(struct wilc *wilc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int chip_wakeup_wilc3000(struct wilc *wilc)
|
||||
{
|
||||
u32 wakeup_reg_val, clk_status_reg_val, trials = 0;
|
||||
u32 wakeup_reg, wakeup_bit;
|
||||
u32 clk_status_reg, clk_status_bit;
|
||||
int wake_seq_trials = 5;
|
||||
const struct wilc_hif_func *hif_func = wilc->hif_func;
|
||||
|
||||
if (wilc->io_type == WILC_HIF_SDIO) {
|
||||
wakeup_reg = WILC_SDIO_WAKEUP_REG;
|
||||
wakeup_bit = WILC_SDIO_WAKEUP_BIT;
|
||||
clk_status_reg = WILC3000_SDIO_CLK_STATUS_REG;
|
||||
clk_status_bit = WILC3000_SDIO_CLK_STATUS_BIT;
|
||||
} else {
|
||||
wakeup_reg = WILC_SPI_WAKEUP_REG;
|
||||
wakeup_bit = WILC_SPI_WAKEUP_BIT;
|
||||
clk_status_reg = WILC3000_SPI_CLK_STATUS_REG;
|
||||
clk_status_bit = WILC3000_SPI_CLK_STATUS_BIT;
|
||||
}
|
||||
|
||||
hif_func->hif_read_reg(wilc, wakeup_reg, &wakeup_reg_val);
|
||||
do {
|
||||
hif_func->hif_write_reg(wilc, wakeup_reg, wakeup_reg_val |
|
||||
wakeup_bit);
|
||||
/* Check the clock status */
|
||||
hif_func->hif_read_reg(wilc, clk_status_reg,
|
||||
&clk_status_reg_val);
|
||||
|
||||
/* In case of clocks off, wait 1ms, and check it again.
|
||||
* if still off, wait for another 1ms, for a total wait of 3ms.
|
||||
* If still off, redo the wake up sequence
|
||||
*/
|
||||
while ((clk_status_reg_val & clk_status_bit) == 0 &&
|
||||
(++trials % 4) != 0) {
|
||||
/* Wait for the chip to stabilize*/
|
||||
usleep_range(1000, 1100);
|
||||
|
||||
/* Make sure chip is awake. This is an extra step that
|
||||
* can be removed later to avoid the bus access
|
||||
* overhead
|
||||
*/
|
||||
hif_func->hif_read_reg(wilc, clk_status_reg,
|
||||
&clk_status_reg_val);
|
||||
}
|
||||
/* in case of failure, Reset the wakeup bit to introduce a new
|
||||
* edge on the next loop
|
||||
*/
|
||||
if ((clk_status_reg_val & clk_status_bit) == 0) {
|
||||
hif_func->hif_write_reg(wilc, wakeup_reg,
|
||||
wakeup_reg_val & (~wakeup_bit));
|
||||
/* added wait before wakeup sequence retry */
|
||||
usleep_range(200, 300);
|
||||
}
|
||||
} while ((clk_status_reg_val & clk_status_bit) == 0 && wake_seq_trials-- > 0);
|
||||
if (!wake_seq_trials)
|
||||
dev_err(wilc->dev, "clocks still OFF. Wake up failed\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int chip_wakeup(struct wilc *wilc)
|
||||
{
|
||||
if (is_wilc1000(wilc->chipid))
|
||||
return chip_wakeup_wilc1000(wilc);
|
||||
else
|
||||
return chip_wakeup_wilc3000(wilc);
|
||||
}
|
||||
|
||||
static inline int acquire_bus(struct wilc *wilc, enum bus_acquire acquire)
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
@ -695,7 +797,9 @@ int host_wakeup_notify(struct wilc *wilc)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
wilc->hif_func->hif_write_reg(wilc, WILC_CORTUS_INTERRUPT_2, 1);
|
||||
wilc->hif_func->hif_write_reg(wilc, is_wilc1000(wilc->chipid) ?
|
||||
WILC1000_CORTUS_INTERRUPT_2 :
|
||||
WILC3000_CORTUS_INTERRUPT_2, 1);
|
||||
return release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(host_wakeup_notify);
|
||||
|
|
@ -707,7 +811,9 @@ int host_sleep_notify(struct wilc *wilc)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
wilc->hif_func->hif_write_reg(wilc, WILC_CORTUS_INTERRUPT_1, 1);
|
||||
wilc->hif_func->hif_write_reg(wilc, is_wilc1000(wilc->chipid) ?
|
||||
WILC1000_CORTUS_INTERRUPT_1 :
|
||||
WILC3000_CORTUS_INTERRUPT_1, 1);
|
||||
return release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(host_sleep_notify);
|
||||
|
|
@ -842,19 +948,45 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
|
|||
if (ret)
|
||||
break;
|
||||
|
||||
ret = func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x2);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
do {
|
||||
ret = func->hif_read_reg(wilc, WILC_HOST_VMM_CTL, ®);
|
||||
if (is_wilc1000(wilc->chipid)) {
|
||||
ret = func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x2);
|
||||
if (ret)
|
||||
break;
|
||||
if (FIELD_GET(WILC_VMM_ENTRY_AVAILABLE, reg)) {
|
||||
entries = FIELD_GET(WILC_VMM_ENTRY_COUNT, reg);
|
||||
|
||||
do {
|
||||
ret = func->hif_read_reg(wilc, WILC_HOST_VMM_CTL, ®);
|
||||
if (ret)
|
||||
break;
|
||||
if (FIELD_GET(WILC_VMM_ENTRY_AVAILABLE, reg)) {
|
||||
entries = FIELD_GET(WILC_VMM_ENTRY_COUNT, reg);
|
||||
break;
|
||||
}
|
||||
} while (--timeout);
|
||||
} else {
|
||||
ret = func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
} while (--timeout);
|
||||
|
||||
/* interrupt firmware */
|
||||
ret = func->hif_write_reg(wilc, WILC_CORTUS_INTERRUPT_BASE, 1);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
do {
|
||||
ret = func->hif_read_reg(wilc, WILC_CORTUS_INTERRUPT_BASE, ®);
|
||||
if (ret)
|
||||
break;
|
||||
if (reg == 0) {
|
||||
/* Get the entries */
|
||||
ret = func->hif_read_reg(wilc, WILC_HOST_VMM_CTL, ®);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
entries = FIELD_GET(WILC_VMM_ENTRY_COUNT, reg);
|
||||
break;
|
||||
}
|
||||
} while (--timeout);
|
||||
}
|
||||
if (timeout <= 0) {
|
||||
ret = func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x0);
|
||||
break;
|
||||
|
|
@ -1212,6 +1344,9 @@ int wilc_wlan_start(struct wilc *wilc)
|
|||
if (wilc->io_type == WILC_HIF_SDIO && wilc->dev_irq_num)
|
||||
reg |= WILC_HAVE_SDIO_IRQ_GPIO;
|
||||
|
||||
if (is_wilc3000(wilc->chipid))
|
||||
reg |= WILC_HAVE_SLEEP_CLK_SRC_RTC;
|
||||
|
||||
ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_1, reg);
|
||||
if (ret)
|
||||
goto release;
|
||||
|
|
@ -1462,21 +1597,25 @@ int wilc_get_chipid(struct wilc *wilc)
|
|||
u32 rfrevid = 0;
|
||||
|
||||
if (wilc->chipid == 0) {
|
||||
wilc->hif_func->hif_read_reg(wilc, WILC_CHIPID, &chipid);
|
||||
wilc->hif_func->hif_read_reg(wilc, WILC_RF_REVISION_ID,
|
||||
&rfrevid);
|
||||
if (!is_wilc1000(chipid)) {
|
||||
wilc->chipid = 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
if (chipid == WILC_1000_BASE_ID_2A) { /* 0x1002A0 */
|
||||
if (rfrevid != 0x1)
|
||||
chipid = WILC_1000_BASE_ID_2A_REV1;
|
||||
} else if (chipid == WILC_1000_BASE_ID_2B) { /* 0x1002B0 */
|
||||
if (rfrevid == 0x4)
|
||||
chipid = WILC_1000_BASE_ID_2B_REV1;
|
||||
else if (rfrevid != 0x3)
|
||||
chipid = WILC_1000_BASE_ID_2B_REV2;
|
||||
wilc->hif_func->hif_read_reg(wilc, WILC3000_CHIP_ID, &chipid);
|
||||
if (!is_wilc3000(chipid)) {
|
||||
wilc->hif_func->hif_read_reg(wilc, WILC_CHIPID, &chipid);
|
||||
wilc->hif_func->hif_read_reg(wilc, WILC_RF_REVISION_ID,
|
||||
&rfrevid);
|
||||
|
||||
if (!is_wilc1000(chipid)) {
|
||||
wilc->chipid = 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
if (chipid == WILC_1000_BASE_ID_2A) { /* 0x1002A0 */
|
||||
if (rfrevid != 0x1)
|
||||
chipid = WILC_1000_BASE_ID_2A_REV1;
|
||||
} else if (chipid == WILC_1000_BASE_ID_2B) { /* 0x1002B0 */
|
||||
if (rfrevid == 0x4)
|
||||
chipid = WILC_1000_BASE_ID_2B_REV1;
|
||||
else if (rfrevid != 0x3)
|
||||
chipid = WILC_1000_BASE_ID_2B_REV2;
|
||||
}
|
||||
}
|
||||
|
||||
wilc->chipid = chipid;
|
||||
|
|
@ -1526,6 +1665,21 @@ static int init_chip(struct net_device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
if (is_wilc3000(wilc->chipid)) {
|
||||
ret = wilc->hif_func->hif_read_reg(wilc, WILC3000_BOOTROM_STATUS, ®);
|
||||
if (ret) {
|
||||
netdev_err(dev, "failed to read WILC3000 BootROM status register\n");
|
||||
goto release;
|
||||
}
|
||||
|
||||
ret = wilc->hif_func->hif_write_reg(wilc, WILC3000_CORTUS_BOOT_REGISTER_2,
|
||||
WILC_CORTUS_BOOT_FROM_IRAM);
|
||||
if (ret) {
|
||||
netdev_err(dev, "failed to write WILC3000 Boot register\n");
|
||||
goto release;
|
||||
}
|
||||
}
|
||||
|
||||
release:
|
||||
rv = release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
|
||||
|
||||
|
|
@ -1607,7 +1761,7 @@ int wilc_wlan_init(struct net_device *dev)
|
|||
if (ret)
|
||||
goto fail;
|
||||
|
||||
if (!is_wilc1000(wilc->chipid)) {
|
||||
if (!is_wilc1000(wilc->chipid) && !is_wilc3000(wilc->chipid)) {
|
||||
netdev_err(dev, "Unsupported chipid: %x\n", wilc->chipid);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
|
|
|
|||
|
|
@ -96,8 +96,14 @@
|
|||
#define WILC_SPI_WAKEUP_REG 0x1
|
||||
#define WILC_SPI_WAKEUP_BIT BIT(1)
|
||||
|
||||
#define WILC_SPI_CLK_STATUS_REG 0x0f
|
||||
#define WILC_SPI_CLK_STATUS_BIT BIT(2)
|
||||
/* WILC1000 specific */
|
||||
#define WILC1000_SPI_CLK_STATUS_REG 0x0f
|
||||
#define WILC1000_SPI_CLK_STATUS_BIT BIT(2)
|
||||
|
||||
/* WILC3000 specific */
|
||||
#define WILC3000_SPI_CLK_STATUS_REG 0x13
|
||||
#define WILC3000_SPI_CLK_STATUS_BIT BIT(2)
|
||||
|
||||
#define WILC_SPI_HOST_TO_FW_REG 0x0b
|
||||
#define WILC_SPI_HOST_TO_FW_BIT BIT(0)
|
||||
|
||||
|
|
@ -123,14 +129,24 @@
|
|||
#define WILC_SDIO_WAKEUP_REG 0xf0
|
||||
#define WILC_SDIO_WAKEUP_BIT BIT(0)
|
||||
|
||||
#define WILC_SDIO_CLK_STATUS_REG 0xf1
|
||||
#define WILC_SDIO_CLK_STATUS_BIT BIT(0)
|
||||
/* WILC1000 */
|
||||
#define WILC1000_SDIO_CLK_STATUS_REG 0xf1
|
||||
#define WILC1000_SDIO_CLK_STATUS_BIT BIT(0)
|
||||
|
||||
#define WILC1000_SDIO_IRQ_FLAG_REG 0xf7
|
||||
#define WILC1000_SDIO_IRQ_CLEAR_FLAG_REG 0xf8
|
||||
|
||||
/* WILC3000 specific */
|
||||
#define WILC3000_SDIO_CLK_STATUS_REG 0xf0 /* clk & wakeup are on same reg */
|
||||
#define WILC3000_SDIO_CLK_STATUS_BIT BIT(4)
|
||||
|
||||
#define WILC3000_SDIO_VMM_TBL_CTRL_REG 0xf1
|
||||
#define WILC3000_SDIO_IRQ_FLAG_REG 0xfe
|
||||
|
||||
/* Common vendor specific CCCR register */
|
||||
#define WILC_SDIO_INTERRUPT_DATA_SZ_REG 0xf2 /* Read size (2 bytes) */
|
||||
|
||||
#define WILC_SDIO_VMM_TBL_CTRL_REG 0xf6
|
||||
#define WILC_SDIO_IRQ_FLAG_REG 0xf7
|
||||
#define WILC_SDIO_IRQ_CLEAR_FLAG_REG 0xf8
|
||||
|
||||
#define WILC_SDIO_HOST_TO_FW_REG 0xfa
|
||||
#define WILC_SDIO_HOST_TO_FW_BIT BIT(0)
|
||||
|
|
@ -172,8 +188,11 @@
|
|||
#define WILC_HAVE_USE_IRQ_AS_HOST_WAKE BIT(8)
|
||||
|
||||
#define WILC_CORTUS_INTERRUPT_BASE 0x10A8
|
||||
#define WILC_CORTUS_INTERRUPT_1 (WILC_CORTUS_INTERRUPT_BASE + 0x4)
|
||||
#define WILC_CORTUS_INTERRUPT_2 (WILC_CORTUS_INTERRUPT_BASE + 0x8)
|
||||
#define WILC1000_CORTUS_INTERRUPT_1 (WILC_CORTUS_INTERRUPT_BASE + 0x4)
|
||||
#define WILC3000_CORTUS_INTERRUPT_1 (WILC_CORTUS_INTERRUPT_BASE + 0x14)
|
||||
|
||||
#define WILC1000_CORTUS_INTERRUPT_2 (WILC_CORTUS_INTERRUPT_BASE + 0x8)
|
||||
#define WILC3000_CORTUS_INTERRUPT_2 (WILC_CORTUS_INTERRUPT_BASE + 0x18)
|
||||
|
||||
/* tx control register 1 to 4 for RX */
|
||||
#define WILC_REG_4_TO_1_RX 0x1e1c
|
||||
|
|
@ -183,6 +202,9 @@
|
|||
|
||||
#define WILC_CORTUS_RESET_MUX_SEL 0x1118
|
||||
#define WILC_CORTUS_BOOT_REGISTER 0xc0000
|
||||
#define WILC3000_BOOTROM_STATUS 0x207ac
|
||||
#define WILC3000_CORTUS_BOOT_REGISTER_2 0x4f0000
|
||||
#define WILC3000_CHIP_ID 0x3b0000
|
||||
|
||||
#define WILC_CORTUS_BOOT_FROM_IRAM 0x71
|
||||
|
||||
|
|
@ -195,6 +217,8 @@
|
|||
#define WILC_1000_BASE_ID_2B_REV1 (WILC_1000_BASE_ID_2B + 1)
|
||||
#define WILC_1000_BASE_ID_2B_REV2 (WILC_1000_BASE_ID_2B + 2)
|
||||
|
||||
#define WILC_3000_BASE_ID 0x300000
|
||||
|
||||
#define WILC_CHIP_REV_FIELD GENMASK(11, 0)
|
||||
|
||||
/********************************************
|
||||
|
|
@ -413,6 +437,11 @@ static inline bool is_wilc1000(u32 id)
|
|||
return (id & (~WILC_CHIP_REV_FIELD)) == WILC_1000_BASE_ID;
|
||||
}
|
||||
|
||||
static inline bool is_wilc3000(u32 id)
|
||||
{
|
||||
return (id & (~WILC_CHIP_REV_FIELD)) == WILC_3000_BASE_ID;
|
||||
}
|
||||
|
||||
int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
|
||||
u32 buffer_size);
|
||||
int wilc_wlan_start(struct wilc *wilc);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user