2009-07-17 18:56:39

by Kalle Valo

[permalink] [raw]
Subject: [RFC PATCH v2 0/8] wl1251 sdio interface

Here is v2 of Bob's wl1251 sdio patches. I have now rebased them on
top of wl1251/wl1271 split patches. Only compile-tested because I
don't have working test setup right now (neither spi or sdio), but I
should have access to one in two weeks.

We should get the patches into wireless-testing soon because there is
quite a lot of interest for wl1251 sdio support, sdio is more widely
used than spi. I would like to get the patches into 2.6.32 if at all
possible.

v2:
o rebase to current wireless-testing (after wl1251/wl1271 split)

---

Bob Copeland (7):
wl1251: add sdio support
wl1251: split spi interface into separate module
wl1251: move module probe methods into spi.c
wl1251: make wl1251_set_partition bus agnostic
wl1251: introduce wl1251_if_operations struct
wl1251: use wiphy_dev instead of wl->spi->dev
wl1251: separate bus i/o code into io.c

Kalle Valo (1):
wl1251: remove fixed address support from spi commands


drivers/net/wireless/wl12xx/Kconfig | 28 ++-
drivers/net/wireless/wl12xx/Makefile | 5
drivers/net/wireless/wl12xx/wl1251.h | 14 +
drivers/net/wireless/wl12xx/wl1251_acx.c | 3
drivers/net/wireless/wl12xx/wl1251_boot.c | 1
drivers/net/wireless/wl12xx/wl1251_cmd.c | 11 -
drivers/net/wireless/wl12xx/wl1251_event.c | 4
drivers/net/wireless/wl12xx/wl1251_io.c | 181 ++++++++++++++++
drivers/net/wireless/wl12xx/wl1251_io.h | 64 ++++++
drivers/net/wireless/wl12xx/wl1251_main.c | 162 +++------------
drivers/net/wireless/wl12xx/wl1251_ops.c | 5
drivers/net/wireless/wl12xx/wl1251_ps.c | 3
drivers/net/wireless/wl12xx/wl1251_rx.c | 7 -
drivers/net/wireless/wl12xx/wl1251_sdio.c | 188 +++++++++++++++++
drivers/net/wireless/wl12xx/wl1251_spi.c | 310 +++++++++++-----------------
drivers/net/wireless/wl12xx/wl1251_spi.h | 54 -----
drivers/net/wireless/wl12xx/wl1251_tx.c | 62 +++---
17 files changed, 678 insertions(+), 424 deletions(-)
create mode 100644 drivers/net/wireless/wl12xx/wl1251_io.c
create mode 100644 drivers/net/wireless/wl12xx/wl1251_io.h
create mode 100644 drivers/net/wireless/wl12xx/wl1251_sdio.c



2009-07-17 18:56:34

by Kalle Valo

[permalink] [raw]
Subject: [RFC PATCH v2 7/8] wl1251: split spi interface into separate module

From: Bob Copeland <[email protected]>

This creates a module called wl1251_spi.ko which contains just the
SPI-specific code. The core remains in the module wl1251.ko.

Signed-off-by: Bob Copeland <[email protected]>
Signed-off-by: Kalle Valo <[email protected]>
---

drivers/net/wireless/wl12xx/Kconfig | 17 ++++++++++++++---
drivers/net/wireless/wl12xx/Makefile | 2 ++
drivers/net/wireless/wl12xx/wl1251.h | 2 +-
drivers/net/wireless/wl12xx/wl1251_main.c | 9 +++++++++
drivers/net/wireless/wl12xx/wl1251_spi.c | 15 ++++++++++-----
5 files changed, 36 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig
index 82a0f97..e47d076 100644
--- a/drivers/net/wireless/wl12xx/Kconfig
+++ b/drivers/net/wireless/wl12xx/Kconfig
@@ -7,12 +7,23 @@ menuconfig WL12XX

config WL1251
tristate "TI wl1251 support"
- depends on WL12XX && SPI_MASTER && GENERIC_HARDIRQS
+ depends on WL12XX && GENERIC_HARDIRQS
select FW_LOADER
select CRC7
---help---
This module adds support for wireless adapters based on
TI wl1251 chipset.

- If you choose to build a module, it'll be called wl1251. Say N if
- unsure.
+ If you choose to build a module, it'll be called wl1251. Say
+ N if unsure.
+
+config WL1251_SPI
+ tristate "TI wl1251 SPI support"
+ depends on WL1251 && SPI_MASTER
+ ---help---
+ This module adds support for the SPI interface of adapters using
+ TI wl1251 chipset. Select this if your platform is using
+ the SPI bus.
+
+ If you choose to build a module, it'll be called wl1251_spi.
+ Say N if unsure.
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile
index a978567..f92fe87 100644
--- a/drivers/net/wireless/wl12xx/Makefile
+++ b/drivers/net/wireless/wl12xx/Makefile
@@ -2,4 +2,6 @@ wl1251-objs = wl1251_main.o wl1251_spi.o wl1251_event.o \
wl1251_tx.o wl1251_rx.o wl1251_ps.o wl1251_cmd.o \
wl1251_acx.o wl1251_boot.o wl1251_init.o \
wl1251_ops.o wl1251_debugfs.o wl1251_io.o
+
obj-$(CONFIG_WL1251) += wl1251.o
+obj-$(CONFIG_WL1251_SPI) += wl1251_spi.o
diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h
index df4c06d..ebe2c70 100644
--- a/drivers/net/wireless/wl12xx/wl1251.h
+++ b/drivers/net/wireless/wl12xx/wl1251.h
@@ -291,7 +291,7 @@ struct wl1251 {
struct ieee80211_hw *hw;
bool mac80211_registered;

- struct spi_device *spi;
+ void *if_priv;
const struct wl1251_if_operations *if_ops;

void (*set_power)(bool enable);
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
index 62b84fc..c5c94b2 100644
--- a/drivers/net/wireless/wl12xx/wl1251_main.c
+++ b/drivers/net/wireless/wl12xx/wl1251_main.c
@@ -69,6 +69,7 @@ irqreturn_t wl1251_irq(int irq, void *cookie)

return IRQ_HANDLED;
}
+EXPORT_SYMBOL_GPL(wl1251_irq);

static int wl1251_fetch_firmware(struct wl1251 *wl)
{
@@ -1253,6 +1254,7 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
out:
return ret;
}
+EXPORT_SYMBOL_GPL(wl1251_init_ieee80211);

#define WL1251_DEFAULT_CHANNEL 1
struct ieee80211_hw *wl1251_alloc_hw(void)
@@ -1325,6 +1327,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void)

return hw;
}
+EXPORT_SYMBOL_GPL(wl1251_alloc_hw);

int wl1251_free_hw(struct wl1251 *wl)
{
@@ -1347,3 +1350,9 @@ int wl1251_free_hw(struct wl1251 *wl)

return 0;
}
+EXPORT_SYMBOL_GPL(wl1251_free_hw);
+
+MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kalle Valo <[email protected]>");
+MODULE_AUTHOR("Luciano Coelho <[email protected]>");
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c
index 13e7a72..464b802 100644
--- a/drivers/net/wireless/wl12xx/wl1251_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1251_spi.c
@@ -31,6 +31,11 @@
#include "reg.h"
#include "wl1251_spi.h"

+static struct spi_device *wl_to_spi(struct wl1251 *wl)
+{
+ return wl->if_priv;
+}
+
static void wl1251_spi_reset(struct wl1251 *wl)
{
u8 *cmd;
@@ -52,7 +57,7 @@ static void wl1251_spi_reset(struct wl1251 *wl)
t.len = WSPI_INIT_CMD_LEN;
spi_message_add_tail(&t, &m);

- spi_sync(wl->spi, &m);
+ spi_sync(wl_to_spi(wl), &m);

wl1251_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);
}
@@ -106,7 +111,7 @@ static void wl1251_spi_wake(struct wl1251 *wl)
t.len = WSPI_INIT_CMD_LEN;
spi_message_add_tail(&t, &m);

- spi_sync(wl->spi, &m);
+ spi_sync(wl_to_spi(wl), &m);

wl1251_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN);
}
@@ -149,7 +154,7 @@ static void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf,
t[2].len = len;
spi_message_add_tail(&t[2], &m);

- spi_sync(wl->spi, &m);
+ spi_sync(wl_to_spi(wl), &m);

/* FIXME: check busy words */

@@ -182,7 +187,7 @@ static void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf,
t[1].len = len;
spi_message_add_tail(&t[1], &m);

- spi_sync(wl->spi, &m);
+ spi_sync(wl_to_spi(wl), &m);

wl1251_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
wl1251_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
@@ -215,7 +220,7 @@ static int __devinit wl1251_spi_probe(struct spi_device *spi)

SET_IEEE80211_DEV(hw, &spi->dev);
dev_set_drvdata(&spi->dev, wl);
- wl->spi = spi;
+ wl->if_priv = spi;
wl->if_ops = &wl1251_spi_ops;

/* This is the only SPI value that we need to set here, the rest


2009-07-19 13:04:20

by Luciano Coelho

[permalink] [raw]
Subject: Re: [RFC PATCH v2 0/8] wl1251 sdio interface

ext Kalle Valo wrote:
> Kalle Valo <[email protected]> writes:
>
>
>> Here is v2 of Bob's wl1251 sdio patches. I have now rebased them on
>> top of wl1251/wl1271 split patches. Only compile-tested because I
>> don't have working test setup right now (neither spi or sdio), but I
>> should have access to one in two weeks.
>>
>
> I forgot to mention that wl1251 most probably is still broken regards to
> bssid handling. I will fix this after my (current) vacation, unless
> someone else is faster. To get wl1251 temporarily working, this patch
> must be reverted:
>

Wow! This is just what I needed to know. I have been struggling the
whole of last week trying to figure out why the wl1271 driver that I'm
planning to submit doesn't work with the latest wireless-testing. I've
been using the wl1251 from wireless-testing as a reference and I was
running out of ideas as to why wl1251 was working and my version of the
wl1271 wasn't. So, it's very good to know that wl1251 isn't working
either :)

This is the only thing that is currently preventing me from submitting
the wl1271 code. Obviously I want to make sure that it works before
sending it for inclusion in wireless-testing...

> commit cc3ec8cb518534c1c593e5f2682710d33c903627
> Author: Johannes Berg <[email protected]>
> Date: Thu May 14 13:10:14 2009 +0200
>
> mac80211: fix managed mode BSSID handling
>
> Currently, we will ask the driver to configure right away
> when somebody changes the desired BSSID. That's totally
> strange because then we will configure the driver without
> even knowing whether the BSS exists. Change this to only
> configure the BSSID when associated, and configure a zero
> BSSID when not associated.
>
> Oddly enough I can't find this patch anymore in wireless-testing, I
> could only find a revert. I don't know what happened to it.
>

The original patch *is* there, but it has been reverted. In any case, I
noticed that the change introduced by this patch is there, so I guess
some other patch has replaced it later.

Now I need to read the archives of the linux-wireless mailing list to
figure out exactly what has changed and what I need to do to get wl1271
to work with the new API. Or is anyone willing to give me a brief
summary of what the driver is expected to do with the new API? (yeah,
it's a sunny Sunday and I'm a bit lazy today :P)

--
Cheers,
Luca.


2009-07-17 18:58:21

by Kalle Valo

[permalink] [raw]
Subject: [RFC PATCH v2 2/8] wl1251: separate bus i/o code into io.c

From: Bob Copeland <[email protected]>

In order to eventually support wl1251 spi and sdio interfaces, move
the register and memory transfer functions to a common file. Also
rename wl1251_spi_mem_{read,write} to indicate its common usage.
We still use spi_read internally until SDIO interface is introduced
so nothing functional should change here.

Signed-off-by: Bob Copeland <[email protected]>
Signed-off-by: Kalle Valo <[email protected]>
---

drivers/net/wireless/wl12xx/Makefile | 2 -
drivers/net/wireless/wl12xx/wl1251_acx.c | 2 -
drivers/net/wireless/wl12xx/wl1251_boot.c | 2 -
drivers/net/wireless/wl12xx/wl1251_cmd.c | 10 ++-
drivers/net/wireless/wl12xx/wl1251_event.c | 4 +
drivers/net/wireless/wl12xx/wl1251_io.c | 86 ++++++++++++++++++++++++++++
drivers/net/wireless/wl12xx/wl1251_io.h | 54 ++++++++++++++++++
drivers/net/wireless/wl12xx/wl1251_main.c | 3 +
drivers/net/wireless/wl12xx/wl1251_ops.c | 6 +-
drivers/net/wireless/wl12xx/wl1251_ps.c | 3 +
drivers/net/wireless/wl12xx/wl1251_rx.c | 7 +-
drivers/net/wireless/wl12xx/wl1251_spi.c | 81 --------------------------
drivers/net/wireless/wl12xx/wl1251_spi.h | 30 ----------
drivers/net/wireless/wl12xx/wl1251_tx.c | 61 ++++++++++----------
14 files changed, 192 insertions(+), 159 deletions(-)
create mode 100644 drivers/net/wireless/wl12xx/wl1251_io.c
create mode 100644 drivers/net/wireless/wl12xx/wl1251_io.h

diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile
index d5595a8..a978567 100644
--- a/drivers/net/wireless/wl12xx/Makefile
+++ b/drivers/net/wireless/wl12xx/Makefile
@@ -1,5 +1,5 @@
wl1251-objs = wl1251_main.o wl1251_spi.o wl1251_event.o \
wl1251_tx.o wl1251_rx.o wl1251_ps.o wl1251_cmd.o \
wl1251_acx.o wl1251_boot.o wl1251_init.o \
- wl1251_ops.o wl1251_debugfs.o
+ wl1251_ops.o wl1251_debugfs.o wl1251_io.o
obj-$(CONFIG_WL1251) += wl1251.o
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.c b/drivers/net/wireless/wl12xx/wl1251_acx.c
index 5a8d21c..b89fa23 100644
--- a/drivers/net/wireless/wl12xx/wl1251_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1251_acx.c
@@ -6,7 +6,7 @@

#include "wl1251.h"
#include "reg.h"
-#include "wl1251_spi.h"
+#include "wl1251_cmd.h"
#include "wl1251_ps.h"

int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod,
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c
index d8a155d..5702398 100644
--- a/drivers/net/wireless/wl12xx/wl1251_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1251_boot.c
@@ -25,7 +25,7 @@

#include "reg.h"
#include "wl1251_boot.h"
-#include "wl1251_spi.h"
+#include "wl1251_io.h"
#include "wl1251_event.h"

static void wl1251_boot_enable_interrupts(struct wl1251 *wl)
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.c b/drivers/net/wireless/wl12xx/wl1251_cmd.c
index dc04d1f..2c30c70 100644
--- a/drivers/net/wireless/wl12xx/wl1251_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1251_cmd.c
@@ -6,7 +6,7 @@

#include "wl1251.h"
#include "reg.h"
-#include "wl1251_spi.h"
+#include "wl1251_io.h"
#include "wl1251_ps.h"
#include "wl1251_acx.h"

@@ -31,7 +31,7 @@ int wl1251_cmd_send(struct wl1251 *wl, u16 id, void *buf, size_t len)

WARN_ON(len % 4 != 0);

- wl1251_spi_mem_write(wl, wl->cmd_box_addr, buf, len);
+ wl1251_mem_write(wl, wl->cmd_box_addr, buf, len);

wl1251_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD);

@@ -86,7 +86,7 @@ int wl1251_cmd_test(struct wl1251 *wl, void *buf, size_t buf_len, u8 answer)
* The answer would be a wl1251_command, where the
* parameter array contains the actual answer.
*/
- wl1251_spi_mem_read(wl, wl->cmd_box_addr, buf, buf_len);
+ wl1251_mem_read(wl, wl->cmd_box_addr, buf, buf_len);

cmd_answer = buf;

@@ -125,7 +125,7 @@ int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len)
}

/* the interrogate command got in, we can read the answer */
- wl1251_spi_mem_read(wl, wl->cmd_box_addr, buf, len);
+ wl1251_mem_read(wl, wl->cmd_box_addr, buf, len);

acx = buf;
if (acx->cmd.status != CMD_STATUS_SUCCESS)
@@ -379,7 +379,7 @@ int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer,
}

/* the read command got in, we can now read the answer */
- wl1251_spi_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd));
+ wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd));

if (cmd->header.status != CMD_STATUS_SUCCESS)
wl1251_error("error in read command result: %d",
diff --git a/drivers/net/wireless/wl12xx/wl1251_event.c b/drivers/net/wireless/wl12xx/wl1251_event.c
index 1a0a0bc..1b4f8d2 100644
--- a/drivers/net/wireless/wl12xx/wl1251_event.c
+++ b/drivers/net/wireless/wl12xx/wl1251_event.c
@@ -24,7 +24,7 @@

#include "wl1251.h"
#include "reg.h"
-#include "wl1251_spi.h"
+#include "wl1251_io.h"
#include "wl1251_event.h"
#include "wl1251_ps.h"

@@ -112,7 +112,7 @@ int wl1251_event_handle(struct wl1251 *wl, u8 mbox_num)
return -EINVAL;

/* first we read the mbox descriptor */
- wl1251_spi_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox,
+ wl1251_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox,
sizeof(struct event_mailbox));

/* process the descriptor */
diff --git a/drivers/net/wireless/wl12xx/wl1251_io.c b/drivers/net/wireless/wl12xx/wl1251_io.c
new file mode 100644
index 0000000..1fa2674
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1251_io.c
@@ -0,0 +1,86 @@
+/*
+ * This file is part of wl12xx
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Contact: Kalle Valo <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "wl1251.h"
+#include "reg.h"
+#include "wl1251_io.h"
+
+static int wl1251_translate_reg_addr(struct wl1251 *wl, int addr)
+{
+ /* If the address is lower than REGISTERS_BASE, it means that this is
+ * a chip-specific register address, so look it up in the registers
+ * table */
+ if (addr < REGISTERS_BASE) {
+ /* Make sure we don't go over the table */
+ if (addr >= ACX_REG_TABLE_LEN) {
+ wl1251_error("address out of range (%d)", addr);
+ return -EINVAL;
+ }
+ addr = wl->chip.acx_reg_table[addr];
+ }
+
+ return addr - wl->physical_reg_addr + wl->virtual_reg_addr;
+}
+
+static int wl1251_translate_mem_addr(struct wl1251 *wl, int addr)
+{
+ return addr - wl->physical_mem_addr + wl->virtual_mem_addr;
+}
+
+void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len)
+{
+ int physical;
+
+ physical = wl1251_translate_mem_addr(wl, addr);
+
+ wl1251_spi_read(wl, physical, buf, len);
+}
+
+void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len)
+{
+ int physical;
+
+ physical = wl1251_translate_mem_addr(wl, addr);
+
+ wl1251_spi_write(wl, physical, buf, len);
+}
+
+u32 wl1251_mem_read32(struct wl1251 *wl, int addr)
+{
+ return wl1251_read32(wl, wl1251_translate_mem_addr(wl, addr));
+}
+
+void wl1251_mem_write32(struct wl1251 *wl, int addr, u32 val)
+{
+ wl1251_write32(wl, wl1251_translate_mem_addr(wl, addr), val);
+}
+
+u32 wl1251_reg_read32(struct wl1251 *wl, int addr)
+{
+ return wl1251_read32(wl, wl1251_translate_reg_addr(wl, addr));
+}
+
+void wl1251_reg_write32(struct wl1251 *wl, int addr, u32 val)
+{
+ wl1251_write32(wl, wl1251_translate_reg_addr(wl, addr), val);
+}
diff --git a/drivers/net/wireless/wl12xx/wl1251_io.h b/drivers/net/wireless/wl12xx/wl1251_io.h
new file mode 100644
index 0000000..e2bb954
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1251_io.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of wl12xx
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#ifndef __WL1251_IO_H__
+#define __WL1251_IO_H__
+
+#include "wl1251.h"
+#include "wl1251_spi.h"
+
+/* Raw target IO, address is not translated */
+void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf, size_t len);
+void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf, size_t len);
+
+static inline u32 wl1251_read32(struct wl1251 *wl, int addr)
+{
+ u32 response;
+
+ wl1251_spi_read(wl, addr, &response, sizeof(u32));
+
+ return response;
+}
+
+static inline void wl1251_write32(struct wl1251 *wl, int addr, u32 val)
+{
+ wl1251_spi_write(wl, addr, &val, sizeof(u32));
+}
+
+/* Memory target IO, address is translated to partition 0 */
+void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len);
+void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len);
+u32 wl1251_mem_read32(struct wl1251 *wl, int addr);
+void wl1251_mem_write32(struct wl1251 *wl, int addr, u32 val);
+/* Registers IO */
+u32 wl1251_reg_read32(struct wl1251 *wl, int addr);
+void wl1251_reg_write32(struct wl1251 *wl, int addr, u32 val);
+
+#endif
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
index cf5e054..2967e19 100644
--- a/drivers/net/wireless/wl12xx/wl1251_main.c
+++ b/drivers/net/wireless/wl12xx/wl1251_main.c
@@ -35,6 +35,7 @@
#include "wl12xx_80211.h"
#include "reg.h"
#include "wl1251_ops.h"
+#include "wl1251_io.h"
#include "wl1251_spi.h"
#include "wl1251_event.h"
#include "wl1251_tx.h"
@@ -932,7 +933,7 @@ static int wl1251_hw_scan(struct wl1251 *wl, u8 *ssid, size_t len,
if (ret < 0)
wl1251_error("SCAN failed");

- wl1251_spi_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params));
+ wl1251_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params));

if (params->header.status != CMD_STATUS_SUCCESS) {
wl1251_error("TEST command answer error: %d",
diff --git a/drivers/net/wireless/wl12xx/wl1251_ops.c b/drivers/net/wireless/wl12xx/wl1251_ops.c
index 96a45f5..0c169ec 100644
--- a/drivers/net/wireless/wl12xx/wl1251_ops.c
+++ b/drivers/net/wireless/wl12xx/wl1251_ops.c
@@ -26,7 +26,7 @@

#include "wl1251_ops.h"
#include "reg.h"
-#include "wl1251_spi.h"
+#include "wl1251_io.h"
#include "wl1251_boot.h"
#include "wl1251_event.h"
#include "wl1251_acx.h"
@@ -130,7 +130,7 @@ static int wl1251_upload_firmware(struct wl1251 *wl)
p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
p, addr);
- wl1251_spi_mem_write(wl, addr, p, CHUNK_SIZE);
+ wl1251_mem_write(wl, addr, p, CHUNK_SIZE);

chunk_num++;
}
@@ -140,7 +140,7 @@ static int wl1251_upload_firmware(struct wl1251 *wl)
p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x",
fw_data_len % CHUNK_SIZE, p, addr);
- wl1251_spi_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE);
+ wl1251_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE);

return 0;
}
diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.c b/drivers/net/wireless/wl12xx/wl1251_ps.c
index 68ff7f1..0581677 100644
--- a/drivers/net/wireless/wl12xx/wl1251_ps.c
+++ b/drivers/net/wireless/wl12xx/wl1251_ps.c
@@ -23,7 +23,8 @@

#include "reg.h"
#include "wl1251_ps.h"
-#include "wl1251_spi.h"
+#include "wl1251_cmd.h"
+#include "wl1251_io.h"

#define WL1251_WAKEUP_TIMEOUT 2000

diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.c b/drivers/net/wireless/wl12xx/wl1251_rx.c
index 0dbb483..af81879 100644
--- a/drivers/net/wireless/wl12xx/wl1251_rx.c
+++ b/drivers/net/wireless/wl12xx/wl1251_rx.c
@@ -27,8 +27,9 @@

#include "wl1251.h"
#include "reg.h"
-#include "wl1251_spi.h"
+#include "wl1251_io.h"
#include "wl1251_rx.h"
+#include "wl1251_cmd.h"
#include "wl1251_acx.h"

static void wl1251_rx_header(struct wl1251 *wl,
@@ -40,7 +41,7 @@ static void wl1251_rx_header(struct wl1251 *wl,
if (wl->rx_current_buffer)
rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size;

- wl1251_spi_mem_read(wl, rx_packet_ring_addr, desc, sizeof(*desc));
+ wl1251_mem_read(wl, rx_packet_ring_addr, desc, sizeof(*desc));
}

static void wl1251_rx_status(struct wl1251 *wl,
@@ -136,7 +137,7 @@ static void wl1251_rx_body(struct wl1251 *wl,
}

rx_buffer = skb_put(skb, length);
- wl1251_spi_mem_read(wl, rx_packet_ring_addr, rx_buffer, length);
+ wl1251_mem_read(wl, rx_packet_ring_addr, rx_buffer, length);

/* The actual lenght doesn't include the target's alignment */
skb->len = desc->length - PLCP_HEADER_LENGTH;
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c
index c2b813f..031a3ba 100644
--- a/drivers/net/wireless/wl12xx/wl1251_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1251_spi.c
@@ -29,29 +29,6 @@
#include "reg.h"
#include "wl1251_spi.h"

-static int wl1251_translate_reg_addr(struct wl1251 *wl, int addr)
-{
- /* If the address is lower than REGISTERS_BASE, it means that this is
- * a chip-specific register address, so look it up in the registers
- * table */
- if (addr < REGISTERS_BASE) {
- /* Make sure we don't go over the table */
- if (addr >= ACX_REG_TABLE_LEN) {
- wl1251_error("address out of range (%d)", addr);
- return -EINVAL;
- }
- addr = wl->chip.acx_reg_table[addr];
- }
-
- return addr - wl->physical_reg_addr + wl->virtual_reg_addr;
-}
-
-static int wl1251_translate_mem_addr(struct wl1251 *wl, int addr)
-{
- return addr - wl->physical_mem_addr + wl->virtual_mem_addr;
-}
-
-
void wl1251_spi_reset(struct wl1251 *wl)
{
u8 *cmd;
@@ -323,61 +300,3 @@ void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf, size_t len)
wl1251_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
wl1251_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
}
-
-void wl1251_spi_mem_read(struct wl1251 *wl, int addr, void *buf,
- size_t len)
-{
- int physical;
-
- physical = wl1251_translate_mem_addr(wl, addr);
-
- wl1251_spi_read(wl, physical, buf, len);
-}
-
-void wl1251_spi_mem_write(struct wl1251 *wl, int addr, void *buf,
- size_t len)
-{
- int physical;
-
- physical = wl1251_translate_mem_addr(wl, addr);
-
- wl1251_spi_write(wl, physical, buf, len);
-}
-
-void wl1251_spi_reg_read(struct wl1251 *wl, int addr, void *buf, size_t len)
-{
- int physical;
-
- physical = wl1251_translate_reg_addr(wl, addr);
-
- wl1251_spi_read(wl, physical, buf, len);
-}
-
-void wl1251_spi_reg_write(struct wl1251 *wl, int addr, void *buf, size_t len)
-{
- int physical;
-
- physical = wl1251_translate_reg_addr(wl, addr);
-
- wl1251_spi_write(wl, physical, buf, len);
-}
-
-u32 wl1251_mem_read32(struct wl1251 *wl, int addr)
-{
- return wl1251_read32(wl, wl1251_translate_mem_addr(wl, addr));
-}
-
-void wl1251_mem_write32(struct wl1251 *wl, int addr, u32 val)
-{
- wl1251_write32(wl, wl1251_translate_mem_addr(wl, addr), val);
-}
-
-u32 wl1251_reg_read32(struct wl1251 *wl, int addr)
-{
- return wl1251_read32(wl, wl1251_translate_reg_addr(wl, addr));
-}
-
-void wl1251_reg_write32(struct wl1251 *wl, int addr, u32 val)
-{
- wl1251_write32(wl, wl1251_translate_reg_addr(wl, addr), val);
-}
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.h b/drivers/net/wireless/wl12xx/wl1251_spi.h
index 7076352..ca9a851 100644
--- a/drivers/net/wireless/wl12xx/wl1251_spi.h
+++ b/drivers/net/wireless/wl12xx/wl1251_spi.h
@@ -69,23 +69,6 @@
((WL1251_BUSY_WORD_LEN - 4) / sizeof(u32))
#define HW_ACCESS_WSPI_INIT_CMD_MASK 0

-
-/* Raw target IO, address is not translated */
-void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf, size_t len);
-void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf, size_t len);
-
-/* Memory target IO, address is tranlated to partition 0 */
-void wl1251_spi_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len);
-void wl1251_spi_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len);
-u32 wl1251_mem_read32(struct wl1251 *wl, int addr);
-void wl1251_mem_write32(struct wl1251 *wl, int addr, u32 val);
-
-/* Registers IO */
-void wl1251_spi_reg_read(struct wl1251 *wl, int addr, void *buf, size_t len);
-void wl1251_spi_reg_write(struct wl1251 *wl, int addr, void *buf, size_t len);
-u32 wl1251_reg_read32(struct wl1251 *wl, int addr);
-void wl1251_reg_write32(struct wl1251 *wl, int addr, u32 val);
-
/* INIT and RESET words */
void wl1251_spi_reset(struct wl1251 *wl);
void wl1251_spi_init(struct wl1251 *wl);
@@ -93,17 +76,4 @@ int wl1251_set_partition(struct wl1251 *wl,
u32 part_start, u32 part_size,
u32 reg_start, u32 reg_size);

-static inline u32 wl1251_read32(struct wl1251 *wl, int addr)
-{
- wl1251_spi_read(wl, addr, &wl->buffer_32, sizeof(wl->buffer_32));
-
- return wl->buffer_32;
-}
-
-static inline void wl1251_write32(struct wl1251 *wl, int addr, u32 val)
-{
- wl->buffer_32 = val;
- wl1251_spi_write(wl, addr, &wl->buffer_32, sizeof(wl->buffer_32));
-}
-
#endif /* __WL1251_SPI_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl12xx/wl1251_tx.c
index 2652a22..7ddc9a3 100644
--- a/drivers/net/wireless/wl12xx/wl1251_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1251_tx.c
@@ -30,6 +30,7 @@
#include "wl1251_spi.h"
#include "wl1251_tx.h"
#include "wl1251_ps.h"
+#include "wl1251_io.h"

static bool wl1251_tx_double_buffer_busy(struct wl1251 *wl, u32 data_out_count)
{
@@ -235,7 +236,7 @@ static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb,
else
addr = wl->data_path->tx_packet_ring_addr;

- wl1251_spi_mem_write(wl, addr, skb->data, len);
+ wl1251_mem_write(wl, addr, skb->data, len);

wl1251_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u rate 0x%x",
tx_hdr->id, skb, tx_hdr->length, tx_hdr->rate);
@@ -451,7 +452,7 @@ void wl1251_tx_complete(struct wl1251 *wl)
return;

/* First we read the result */
- wl1251_spi_mem_read(wl, wl->data_path->tx_complete_addr,
+ wl1251_mem_read(wl, wl->data_path->tx_complete_addr,
result, sizeof(result));

result_index = wl->next_tx_complete;
@@ -482,41 +483,41 @@ void wl1251_tx_complete(struct wl1251 *wl)
*/
if (result_index > wl->next_tx_complete) {
/* Only 1 write is needed */
- wl1251_spi_mem_write(wl,
- wl->data_path->tx_complete_addr +
- (wl->next_tx_complete *
- sizeof(struct tx_result)),
- &result[wl->next_tx_complete],
- num_complete *
- sizeof(struct tx_result));
+ wl1251_mem_write(wl,
+ wl->data_path->tx_complete_addr +
+ (wl->next_tx_complete *
+ sizeof(struct tx_result)),
+ &result[wl->next_tx_complete],
+ num_complete *
+ sizeof(struct tx_result));


} else if (result_index < wl->next_tx_complete) {
/* 2 writes are needed */
- wl1251_spi_mem_write(wl,
- wl->data_path->tx_complete_addr +
- (wl->next_tx_complete *
- sizeof(struct tx_result)),
- &result[wl->next_tx_complete],
- (FW_TX_CMPLT_BLOCK_SIZE -
- wl->next_tx_complete) *
- sizeof(struct tx_result));
-
- wl1251_spi_mem_write(wl,
- wl->data_path->tx_complete_addr,
- result,
- (num_complete -
- FW_TX_CMPLT_BLOCK_SIZE +
- wl->next_tx_complete) *
- sizeof(struct tx_result));
+ wl1251_mem_write(wl,
+ wl->data_path->tx_complete_addr +
+ (wl->next_tx_complete *
+ sizeof(struct tx_result)),
+ &result[wl->next_tx_complete],
+ (FW_TX_CMPLT_BLOCK_SIZE -
+ wl->next_tx_complete) *
+ sizeof(struct tx_result));
+
+ wl1251_mem_write(wl,
+ wl->data_path->tx_complete_addr,
+ result,
+ (num_complete -
+ FW_TX_CMPLT_BLOCK_SIZE +
+ wl->next_tx_complete) *
+ sizeof(struct tx_result));

} else {
/* We have to write the whole array */
- wl1251_spi_mem_write(wl,
- wl->data_path->tx_complete_addr,
- result,
- FW_TX_CMPLT_BLOCK_SIZE *
- sizeof(struct tx_result));
+ wl1251_mem_write(wl,
+ wl->data_path->tx_complete_addr,
+ result,
+ FW_TX_CMPLT_BLOCK_SIZE *
+ sizeof(struct tx_result));
}

}


2009-07-17 18:56:03

by Kalle Valo

[permalink] [raw]
Subject: [RFC PATCH v2 1/8] wl1251: remove fixed address support from spi commands

From: Kalle Valo <[email protected]>

The fixed addresses are not used in wl1251, only in wl1271. So it can
be safely removed.

Signed-off-by: Kalle Valo <[email protected]>
---

drivers/net/wireless/wl12xx/wl1251_spi.c | 26 ++++++++------------------
drivers/net/wireless/wl12xx/wl1251_spi.h | 18 ++++++------------
2 files changed, 14 insertions(+), 30 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c
index c5da79d..c2b813f 100644
--- a/drivers/net/wireless/wl12xx/wl1251_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1251_spi.c
@@ -255,8 +255,7 @@ int wl1251_set_partition(struct wl1251 *wl,
return 0;
}

-void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf,
- size_t len, bool fixed)
+void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf, size_t len)
{
struct spi_transfer t[3];
struct spi_message m;
@@ -271,9 +270,6 @@ void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf,
*cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
*cmd |= addr & WSPI_CMD_BYTE_ADDR;

- if (fixed)
- *cmd |= WSPI_CMD_FIXED;
-
spi_message_init(&m);
memset(t, 0, sizeof(t));

@@ -298,8 +294,7 @@ void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf,
wl1251_dump(DEBUG_SPI, "spi_read buf <- ", buf, len);
}

-void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf,
- size_t len, bool fixed)
+void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf, size_t len)
{
struct spi_transfer t[2];
struct spi_message m;
@@ -312,9 +307,6 @@ void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf,
*cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
*cmd |= addr & WSPI_CMD_BYTE_ADDR;

- if (fixed)
- *cmd |= WSPI_CMD_FIXED;
-
spi_message_init(&m);
memset(t, 0, sizeof(t));

@@ -339,7 +331,7 @@ void wl1251_spi_mem_read(struct wl1251 *wl, int addr, void *buf,

physical = wl1251_translate_mem_addr(wl, addr);

- wl1251_spi_read(wl, physical, buf, len, false);
+ wl1251_spi_read(wl, physical, buf, len);
}

void wl1251_spi_mem_write(struct wl1251 *wl, int addr, void *buf,
@@ -349,27 +341,25 @@ void wl1251_spi_mem_write(struct wl1251 *wl, int addr, void *buf,

physical = wl1251_translate_mem_addr(wl, addr);

- wl1251_spi_write(wl, physical, buf, len, false);
+ wl1251_spi_write(wl, physical, buf, len);
}

-void wl1251_spi_reg_read(struct wl1251 *wl, int addr, void *buf, size_t len,
- bool fixed)
+void wl1251_spi_reg_read(struct wl1251 *wl, int addr, void *buf, size_t len)
{
int physical;

physical = wl1251_translate_reg_addr(wl, addr);

- wl1251_spi_read(wl, physical, buf, len, fixed);
+ wl1251_spi_read(wl, physical, buf, len);
}

-void wl1251_spi_reg_write(struct wl1251 *wl, int addr, void *buf, size_t len,
- bool fixed)
+void wl1251_spi_reg_write(struct wl1251 *wl, int addr, void *buf, size_t len)
{
int physical;

physical = wl1251_translate_reg_addr(wl, addr);

- wl1251_spi_write(wl, physical, buf, len, fixed);
+ wl1251_spi_write(wl, physical, buf, len);
}

u32 wl1251_mem_read32(struct wl1251 *wl, int addr)
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.h b/drivers/net/wireless/wl12xx/wl1251_spi.h
index 6e8daf4..7076352 100644
--- a/drivers/net/wireless/wl12xx/wl1251_spi.h
+++ b/drivers/net/wireless/wl12xx/wl1251_spi.h
@@ -71,10 +71,8 @@


/* Raw target IO, address is not translated */
-void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf,
- size_t len, bool fixed);
-void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf,
- size_t len, bool fixed);
+void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf, size_t len);
+void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf, size_t len);

/* Memory target IO, address is tranlated to partition 0 */
void wl1251_spi_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len);
@@ -83,10 +81,8 @@ u32 wl1251_mem_read32(struct wl1251 *wl, int addr);
void wl1251_mem_write32(struct wl1251 *wl, int addr, u32 val);

/* Registers IO */
-void wl1251_spi_reg_read(struct wl1251 *wl, int addr, void *buf, size_t len,
- bool fixed);
-void wl1251_spi_reg_write(struct wl1251 *wl, int addr, void *buf, size_t len,
- bool fixed);
+void wl1251_spi_reg_read(struct wl1251 *wl, int addr, void *buf, size_t len);
+void wl1251_spi_reg_write(struct wl1251 *wl, int addr, void *buf, size_t len);
u32 wl1251_reg_read32(struct wl1251 *wl, int addr);
void wl1251_reg_write32(struct wl1251 *wl, int addr, u32 val);

@@ -99,8 +95,7 @@ int wl1251_set_partition(struct wl1251 *wl,

static inline u32 wl1251_read32(struct wl1251 *wl, int addr)
{
- wl1251_spi_read(wl, addr, &wl->buffer_32,
- sizeof(wl->buffer_32), false);
+ wl1251_spi_read(wl, addr, &wl->buffer_32, sizeof(wl->buffer_32));

return wl->buffer_32;
}
@@ -108,8 +103,7 @@ static inline u32 wl1251_read32(struct wl1251 *wl, int addr)
static inline void wl1251_write32(struct wl1251 *wl, int addr, u32 val)
{
wl->buffer_32 = val;
- wl1251_spi_write(wl, addr, &wl->buffer_32,
- sizeof(wl->buffer_32), false);
+ wl1251_spi_write(wl, addr, &wl->buffer_32, sizeof(wl->buffer_32));
}

#endif /* __WL1251_SPI_H__ */


2009-07-17 18:58:20

by Kalle Valo

[permalink] [raw]
Subject: [RFC PATCH v2 4/8] wl1251: introduce wl1251_if_operations struct

From: Bob Copeland <[email protected]>

Introduce an ops struct with read, write, and reset functions to
abstract away the details of the wl1251 bus interface. Doing this
will allow SDIO to coexist with SPI by supplying its own I/O
routines.

Signed-off-by: Bob Copeland <[email protected]>
Signed-off-by: Kalle Valo <[email protected]>
---

drivers/net/wireless/wl12xx/wl1251.h | 7 +++++++
drivers/net/wireless/wl12xx/wl1251_boot.c | 1 +
drivers/net/wireless/wl12xx/wl1251_io.c | 4 ++--
drivers/net/wireless/wl12xx/wl1251_io.h | 9 ++-------
drivers/net/wireless/wl12xx/wl1251_main.c | 6 ++++--
drivers/net/wireless/wl12xx/wl1251_ops.c | 1 +
drivers/net/wireless/wl12xx/wl1251_spi.c | 23 +++++++++++++++++++----
drivers/net/wireless/wl12xx/wl1251_spi.h | 3 ---
8 files changed, 36 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h
index 665aca0..284bb50 100644
--- a/drivers/net/wireless/wl12xx/wl1251.h
+++ b/drivers/net/wireless/wl12xx/wl1251.h
@@ -281,11 +281,18 @@ struct wl1251_debugfs {
struct dentry *excessive_retries;
};

+struct wl1251_if_operations {
+ void (*read)(struct wl1251 *wl, int addr, void *buf, size_t len);
+ void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len);
+ void (*reset)(struct wl1251 *wl);
+};
+
struct wl1251 {
struct ieee80211_hw *hw;
bool mac80211_registered;

struct spi_device *spi;
+ struct wl1251_if_operations *if_ops;

void (*set_power)(bool enable);
int irq;
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c
index 5702398..5c6f327 100644
--- a/drivers/net/wireless/wl12xx/wl1251_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1251_boot.c
@@ -26,6 +26,7 @@
#include "reg.h"
#include "wl1251_boot.h"
#include "wl1251_io.h"
+#include "wl1251_spi.h"
#include "wl1251_event.h"

static void wl1251_boot_enable_interrupts(struct wl1251 *wl)
diff --git a/drivers/net/wireless/wl12xx/wl1251_io.c b/drivers/net/wireless/wl12xx/wl1251_io.c
index 1fa2674..bc95785 100644
--- a/drivers/net/wireless/wl12xx/wl1251_io.c
+++ b/drivers/net/wireless/wl12xx/wl1251_io.c
@@ -53,7 +53,7 @@ void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len)

physical = wl1251_translate_mem_addr(wl, addr);

- wl1251_spi_read(wl, physical, buf, len);
+ wl->if_ops->read(wl, physical, buf, len);
}

void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len)
@@ -62,7 +62,7 @@ void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len)

physical = wl1251_translate_mem_addr(wl, addr);

- wl1251_spi_write(wl, physical, buf, len);
+ wl->if_ops->write(wl, physical, buf, len);
}

u32 wl1251_mem_read32(struct wl1251 *wl, int addr)
diff --git a/drivers/net/wireless/wl12xx/wl1251_io.h b/drivers/net/wireless/wl12xx/wl1251_io.h
index e2bb954..1fa2ab1 100644
--- a/drivers/net/wireless/wl12xx/wl1251_io.h
+++ b/drivers/net/wireless/wl12xx/wl1251_io.h
@@ -22,24 +22,19 @@
#define __WL1251_IO_H__

#include "wl1251.h"
-#include "wl1251_spi.h"
-
-/* Raw target IO, address is not translated */
-void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf, size_t len);
-void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf, size_t len);

static inline u32 wl1251_read32(struct wl1251 *wl, int addr)
{
u32 response;

- wl1251_spi_read(wl, addr, &response, sizeof(u32));
+ wl->if_ops->read(wl, addr, &response, sizeof(u32));

return response;
}

static inline void wl1251_write32(struct wl1251 *wl, int addr, u32 val)
{
- wl1251_spi_write(wl, addr, &val, sizeof(u32));
+ wl->if_ops->write(wl, addr, &val, sizeof(u32));
}

/* Memory target IO, address is translated to partition 0 */
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
index d9c5d8a..238b4a8 100644
--- a/drivers/net/wireless/wl12xx/wl1251_main.c
+++ b/drivers/net/wireless/wl12xx/wl1251_main.c
@@ -168,8 +168,7 @@ static int wl1251_chip_wakeup(struct wl1251 *wl)

wl1251_power_on(wl);
msleep(wl->chip.power_on_sleep);
- wl1251_spi_reset(wl);
- wl1251_spi_init(wl);
+ wl->if_ops->reset(wl);

/* We don't need a real memory partition here, because we only want
* to use the registers at this point. */
@@ -1247,6 +1246,8 @@ static int wl1251_init_ieee80211(struct wl1251 *wl)
return 0;
}

+extern struct wl1251_if_operations wl1251_spi_ops;
+
#define WL1251_DEFAULT_CHANNEL 1
static int __devinit wl1251_probe(struct spi_device *spi)
{
@@ -1274,6 +1275,7 @@ static int __devinit wl1251_probe(struct spi_device *spi)
wl->hw = hw;
dev_set_drvdata(&spi->dev, wl);
wl->spi = spi;
+ wl->if_ops = &wl1251_spi_ops;

wl->data_in_count = 0;

diff --git a/drivers/net/wireless/wl12xx/wl1251_ops.c b/drivers/net/wireless/wl12xx/wl1251_ops.c
index 0c169ec..966c919 100644
--- a/drivers/net/wireless/wl12xx/wl1251_ops.c
+++ b/drivers/net/wireless/wl12xx/wl1251_ops.c
@@ -27,6 +27,7 @@
#include "wl1251_ops.h"
#include "reg.h"
#include "wl1251_io.h"
+#include "wl1251_spi.h"
#include "wl1251_boot.h"
#include "wl1251_event.h"
#include "wl1251_acx.h"
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c
index 031a3ba..61a0852 100644
--- a/drivers/net/wireless/wl12xx/wl1251_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1251_spi.c
@@ -29,7 +29,7 @@
#include "reg.h"
#include "wl1251_spi.h"

-void wl1251_spi_reset(struct wl1251 *wl)
+static void wl1251_spi_reset(struct wl1251 *wl)
{
u8 *cmd;
struct spi_transfer t;
@@ -55,7 +55,7 @@ void wl1251_spi_reset(struct wl1251 *wl)
wl1251_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);
}

-void wl1251_spi_init(struct wl1251 *wl)
+static void wl1251_spi_init(struct wl1251 *wl)
{
u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd;
struct spi_transfer t;
@@ -109,6 +109,13 @@ void wl1251_spi_init(struct wl1251 *wl)
wl1251_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN);
}

+static void wl1251_spi_reset_wake(struct wl1251 *wl)
+{
+ wl1251_spi_reset(wl);
+ wl1251_spi_init(wl);
+}
+
+
/* Set the SPI partitions to access the chip addresses
*
* There are two VIRTUAL (SPI) partitions (the memory partition and the
@@ -232,7 +239,8 @@ int wl1251_set_partition(struct wl1251 *wl,
return 0;
}

-void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf, size_t len)
+static void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf,
+ size_t len)
{
struct spi_transfer t[3];
struct spi_message m;
@@ -271,7 +279,8 @@ void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf, size_t len)
wl1251_dump(DEBUG_SPI, "spi_read buf <- ", buf, len);
}

-void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf, size_t len)
+static void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf,
+ size_t len)
{
struct spi_transfer t[2];
struct spi_message m;
@@ -300,3 +309,9 @@ void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf, size_t len)
wl1251_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
wl1251_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
}
+
+const struct wl1251_if_operations wl1251_spi_ops = {
+ .read = wl1251_spi_read,
+ .write = wl1251_spi_write,
+ .reset = wl1251_spi_reset_wake,
+};
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.h b/drivers/net/wireless/wl12xx/wl1251_spi.h
index ca9a851..7c6da21 100644
--- a/drivers/net/wireless/wl12xx/wl1251_spi.h
+++ b/drivers/net/wireless/wl12xx/wl1251_spi.h
@@ -69,9 +69,6 @@
((WL1251_BUSY_WORD_LEN - 4) / sizeof(u32))
#define HW_ACCESS_WSPI_INIT_CMD_MASK 0

-/* INIT and RESET words */
-void wl1251_spi_reset(struct wl1251 *wl);
-void wl1251_spi_init(struct wl1251 *wl);
int wl1251_set_partition(struct wl1251 *wl,
u32 part_start, u32 part_size,
u32 reg_start, u32 reg_size);


2009-07-17 18:56:16

by Kalle Valo

[permalink] [raw]
Subject: [RFC PATCH v2 6/8] wl1251: move module probe methods into spi.c

From: Bob Copeland <[email protected]>

This change moves all of the spi specific code from main.c into
spi.c. The module initialization code also moves, but common
code for initializing mac80211 etc. stays in main.c, as this will
eventually form a common library module also used by wl1251_sdio.

Signed-off-by: Bob Copeland <[email protected]>
Signed-off-by: Kalle Valo <[email protected]>
---

drivers/net/wireless/wl12xx/wl1251.h | 7 +
drivers/net/wireless/wl12xx/wl1251_acx.c | 1
drivers/net/wireless/wl12xx/wl1251_cmd.c | 1
drivers/net/wireless/wl12xx/wl1251_main.c | 148 ++++-------------------------
drivers/net/wireless/wl12xx/wl1251_spi.c | 125 ++++++++++++++++++++++++
drivers/net/wireless/wl12xx/wl1251_tx.c | 1
6 files changed, 151 insertions(+), 132 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h
index 284bb50..df4c06d 100644
--- a/drivers/net/wireless/wl12xx/wl1251.h
+++ b/drivers/net/wireless/wl12xx/wl1251.h
@@ -292,7 +292,7 @@ struct wl1251 {
bool mac80211_registered;

struct spi_device *spi;
- struct wl1251_if_operations *if_ops;
+ const struct wl1251_if_operations *if_ops;

void (*set_power)(bool enable);
int irq;
@@ -404,6 +404,11 @@ struct wl1251 {
int wl1251_plt_start(struct wl1251 *wl);
int wl1251_plt_stop(struct wl1251 *wl);

+irqreturn_t wl1251_irq(int irq, void *cookie);
+struct ieee80211_hw *wl1251_alloc_hw(void);
+int wl1251_free_hw(struct wl1251 *wl);
+int wl1251_init_ieee80211(struct wl1251 *wl);
+
#define DEFAULT_HW_GEN_MODULATION_TYPE CCK_LONG /* Long Preamble */
#define DEFAULT_HW_GEN_TX_RATE RATE_2MBPS
#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.c b/drivers/net/wireless/wl12xx/wl1251_acx.c
index b89fa23..b07747d 100644
--- a/drivers/net/wireless/wl12xx/wl1251_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1251_acx.c
@@ -2,7 +2,6 @@

#include <linux/module.h>
#include <linux/crc7.h>
-#include <linux/spi/spi.h>

#include "wl1251.h"
#include "reg.h"
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.c b/drivers/net/wireless/wl12xx/wl1251_cmd.c
index 2c30c70..dfbf681 100644
--- a/drivers/net/wireless/wl12xx/wl1251_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1251_cmd.c
@@ -2,7 +2,6 @@

#include <linux/module.h>
#include <linux/crc7.h>
-#include <linux/spi/spi.h>

#include "wl1251.h"
#include "reg.h"
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
index 238b4a8..62b84fc 100644
--- a/drivers/net/wireless/wl12xx/wl1251_main.c
+++ b/drivers/net/wireless/wl12xx/wl1251_main.c
@@ -26,17 +26,15 @@
#include <linux/firmware.h>
#include <linux/delay.h>
#include <linux/irq.h>
-#include <linux/spi/spi.h>
#include <linux/crc32.h>
#include <linux/etherdevice.h>
-#include <linux/spi/wl12xx.h>

#include "wl1251.h"
#include "wl12xx_80211.h"
#include "reg.h"
#include "wl1251_ops.h"
#include "wl1251_io.h"
-#include "wl1251_spi.h"
+#include "wl1251_cmd.h"
#include "wl1251_event.h"
#include "wl1251_tx.h"
#include "wl1251_rx.h"
@@ -59,7 +57,7 @@ static void wl1251_power_on(struct wl1251 *wl)
wl->set_power(true);
}

-static irqreturn_t wl1251_irq(int irq, void *cookie)
+irqreturn_t wl1251_irq(int irq, void *cookie)
{
struct wl1251 *wl;

@@ -1224,8 +1222,10 @@ static int wl1251_register_hw(struct wl1251 *wl)
return 0;
}

-static int wl1251_init_ieee80211(struct wl1251 *wl)
+int wl1251_init_ieee80211(struct wl1251 *wl)
{
+ int ret;
+
/* The tx descriptor buffer and the TKIP space */
wl->hw->extra_tx_headroom = sizeof(struct tx_double_buffer_desc)
+ WL1251_TKIP_IV_SPACE;
@@ -1241,41 +1241,37 @@ static int wl1251_init_ieee80211(struct wl1251 *wl)
wl->hw->wiphy->max_scan_ssids = 1;
wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz;

- SET_IEEE80211_DEV(wl->hw, &wl->spi->dev);
+ ret = wl1251_register_hw(wl);
+ if (ret)
+ goto out;

- return 0;
-}
+ wl1251_debugfs_init(wl);
+ wl1251_notice("initialized");

-extern struct wl1251_if_operations wl1251_spi_ops;
+ ret = 0;
+
+out:
+ return ret;
+}

#define WL1251_DEFAULT_CHANNEL 1
-static int __devinit wl1251_probe(struct spi_device *spi)
+struct ieee80211_hw *wl1251_alloc_hw(void)
{
- struct wl12xx_platform_data *pdata;
struct ieee80211_hw *hw;
struct wl1251 *wl;
- int ret, i;
+ int i;
static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};

- pdata = spi->dev.platform_data;
- if (!pdata) {
- wl1251_error("no platform data");
- return -ENODEV;
- }
-
hw = ieee80211_alloc_hw(sizeof(*wl), &wl1251_ops);
if (!hw) {
wl1251_error("could not alloc ieee80211_hw");
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
}

wl = hw->priv;
memset(wl, 0, sizeof(*wl));

wl->hw = hw;
- dev_set_drvdata(&spi->dev, wl);
- wl->spi = spi;
- wl->if_ops = &wl1251_spi_ops;

wl->data_in_count = 0;

@@ -1323,74 +1319,15 @@ static int __devinit wl1251_probe(struct spi_device *spi)
wl->rx_descriptor = kmalloc(sizeof(*wl->rx_descriptor), GFP_KERNEL);
if (!wl->rx_descriptor) {
wl1251_error("could not allocate memory for rx descriptor");
- ret = -ENOMEM;
- goto out_free;
+ ieee80211_free_hw(hw);
+ return ERR_PTR(-ENOMEM);
}

- /* 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) {
- wl1251_error("spi_setup failed");
- goto out_free;
- }
-
- wl->set_power = pdata->set_power;
- if (!wl->set_power) {
- wl1251_error("set power function missing in platform data");
- ret = -ENODEV;
- goto out_free;
- }
-
- wl->irq = spi->irq;
- if (wl->irq < 0) {
- wl1251_error("irq missing in platform data");
- ret = -ENODEV;
- goto out_free;
- }
-
- ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl);
- if (ret < 0) {
- wl1251_error("request_irq() failed: %d", ret);
- goto out_free;
- }
-
- set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
-
- disable_irq(wl->irq);
-
- ret = wl1251_init_ieee80211(wl);
- if (ret)
- goto out_irq;
-
- ret = wl1251_register_hw(wl);
- if (ret)
- goto out_irq;
-
- wl1251_debugfs_init(wl);
-
- wl1251_notice("initialized");
-
- return 0;
-
- out_irq:
- free_irq(wl->irq, wl);
-
- out_free:
- kfree(wl->rx_descriptor);
- wl->rx_descriptor = NULL;
-
- ieee80211_free_hw(hw);
-
- return ret;
+ return hw;
}

-static int __devexit wl1251_remove(struct spi_device *spi)
+int wl1251_free_hw(struct wl1251 *wl)
{
- struct wl1251 *wl = dev_get_drvdata(&spi->dev);
-
ieee80211_unregister_hw(wl->hw);

wl1251_debugfs_exit(wl);
@@ -1410,44 +1347,3 @@ static int __devexit wl1251_remove(struct spi_device *spi)

return 0;
}
-
-
-static struct spi_driver wl1251_spi_driver = {
- .driver = {
- /* FIXME: use wl12xx name to not break the user space */
- .name = "wl12xx",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- },
-
- .probe = wl1251_probe,
- .remove = __devexit_p(wl1251_remove),
-};
-
-static int __init wl1251_init(void)
-{
- int ret;
-
- ret = spi_register_driver(&wl1251_spi_driver);
- if (ret < 0) {
- wl1251_error("failed to register spi driver: %d", ret);
- goto out;
- }
-
-out:
- return ret;
-}
-
-static void __exit wl1251_exit(void)
-{
- spi_unregister_driver(&wl1251_spi_driver);
-
- wl1251_notice("unloaded");
-}
-
-module_init(wl1251_init);
-module_exit(wl1251_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kalle Valo <[email protected]>, "
- "Luciano Coelho <[email protected]>");
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c
index ceb237b..13e7a72 100644
--- a/drivers/net/wireless/wl12xx/wl1251_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1251_spi.c
@@ -21,9 +21,11 @@
*
*/

+#include <linux/irq.h>
#include <linux/module.h>
#include <linux/crc7.h>
#include <linux/spi/spi.h>
+#include <linux/spi/wl12xx.h>

#include "wl1251.h"
#include "reg.h"
@@ -55,7 +57,7 @@ static void wl1251_spi_reset(struct wl1251 *wl)
wl1251_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);
}

-static void wl1251_spi_init(struct wl1251 *wl)
+static void wl1251_spi_wake(struct wl1251 *wl)
{
u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd;
struct spi_transfer t;
@@ -112,7 +114,7 @@ static void wl1251_spi_init(struct wl1251 *wl)
static void wl1251_spi_reset_wake(struct wl1251 *wl)
{
wl1251_spi_reset(wl);
- wl1251_spi_init(wl);
+ wl1251_spi_wake(wl);
}

static void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf,
@@ -191,3 +193,122 @@ const struct wl1251_if_operations wl1251_spi_ops = {
.write = wl1251_spi_write,
.reset = wl1251_spi_reset_wake,
};
+
+static int __devinit wl1251_spi_probe(struct spi_device *spi)
+{
+ struct wl12xx_platform_data *pdata;
+ struct ieee80211_hw *hw;
+ struct wl1251 *wl;
+ int ret;
+
+ pdata = spi->dev.platform_data;
+ if (!pdata) {
+ wl1251_error("no platform data");
+ return -ENODEV;
+ }
+
+ hw = wl1251_alloc_hw();
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+
+ wl = hw->priv;
+
+ SET_IEEE80211_DEV(hw, &spi->dev);
+ dev_set_drvdata(&spi->dev, wl);
+ wl->spi = spi;
+ wl->if_ops = &wl1251_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) {
+ wl1251_error("spi_setup failed");
+ goto out_free;
+ }
+
+ wl->set_power = pdata->set_power;
+ if (!wl->set_power) {
+ wl1251_error("set power function missing in platform data");
+ return -ENODEV;
+ }
+
+ wl->irq = spi->irq;
+ if (wl->irq < 0) {
+ wl1251_error("irq missing in platform data");
+ return -ENODEV;
+ }
+
+ ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl);
+ if (ret < 0) {
+ wl1251_error("request_irq() failed: %d", ret);
+ goto out_free;
+ }
+
+ set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
+
+ disable_irq(wl->irq);
+
+ ret = wl1251_init_ieee80211(wl);
+ if (ret)
+ goto out_irq;
+
+ return 0;
+
+ out_irq:
+ free_irq(wl->irq, wl);
+
+ out_free:
+ ieee80211_free_hw(hw);
+
+ return ret;
+}
+
+static int __devexit wl1251_spi_remove(struct spi_device *spi)
+{
+ struct wl1251 *wl = dev_get_drvdata(&spi->dev);
+
+ wl1251_free_hw(wl);
+
+ return 0;
+}
+
+static struct spi_driver wl1251_spi_driver = {
+ .driver = {
+ .name = "wl12xx",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+
+ .probe = wl1251_spi_probe,
+ .remove = __devexit_p(wl1251_spi_remove),
+};
+
+static int __init wl1251_spi_init(void)
+{
+ int ret;
+
+ ret = spi_register_driver(&wl1251_spi_driver);
+ if (ret < 0) {
+ wl1251_error("failed to register spi driver: %d", ret);
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+static void __exit wl1251_spi_exit(void)
+{
+ spi_unregister_driver(&wl1251_spi_driver);
+
+ wl1251_notice("unloaded");
+}
+
+module_init(wl1251_spi_init);
+module_exit(wl1251_spi_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kalle Valo <[email protected]>");
+MODULE_AUTHOR("Luciano Coelho <[email protected]>");
diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl12xx/wl1251_tx.c
index 7ddc9a3..f20bab6 100644
--- a/drivers/net/wireless/wl12xx/wl1251_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1251_tx.c
@@ -27,7 +27,6 @@

#include "wl1251.h"
#include "reg.h"
-#include "wl1251_spi.h"
#include "wl1251_tx.h"
#include "wl1251_ps.h"
#include "wl1251_io.h"


2009-07-18 05:33:22

by Bob Copeland

[permalink] [raw]
Subject: Re: [RFC PATCH v2 0/8] wl1251 sdio interface

On Fri, Jul 17, 2009 at 10:04:47PM +0300, Kalle Valo wrote:
> Kalle Valo <[email protected]> writes:
>
> > Here is v2 of Bob's wl1251 sdio patches. I have now rebased them on
> > top of wl1251/wl1271 split patches. Only compile-tested because I
> > don't have working test setup right now (neither spi or sdio), but I
> > should have access to one in two weeks.

Ok, my first tests with this have mixed results -- wpa_supplicant
didn't associate, but I could do a scan. There were a few sdio
transfer errors. So I'll try going back to the earlier version and see
how they compare.

Meanwhile, this patch (or something like it) would be good:

>From 742f257a955fa9e637f7bcb62a73a110718fb247 Mon Sep 17 00:00:00 2001
From: Bob Copeland <[email protected]>
Date: Fri, 17 Jul 2009 23:53:15 -0400
Subject: [PATCH] wl12xx: make irq handling interface specific

Due to the differences in interrupt handling between SPI and SDIO, the
relevant code needs to be interface specific. This patch pushes
the irq code down into _spi.c and _sdio.c, and adds enable/disable
callbacks (no-ops for the SDIO case, but not needed there).

This fixes the following warning:

[ 566.343887] ------------[ cut here ]------------
[ 566.349105] WARNING: at kernel/irq/manage.c:222 __enable_irq+0x3c/0x6c()
[ 566.356735] Unbalanced enable for IRQ 0
[ 566.361099] Modules linked in: msm_wifi wl12xx_sdio wl12xx mac80211 cfg80211 rfkill_backport lib80211_crypt_ccmp lib80211_crypt_wep lib80211_crypt_tkip lib80211
[ 566.381240] [<c025acec>] (dump_stack+0x0/0x14) from [<c004b610>] (warn_slowpath+0x70/0x8c)
[ 566.391860] [<c004b5a0>] (warn_slowpath+0x0/0x8c) from [<c0077c10>] (__enable_irq+0x3c/0x6c)
[ 566.402572] r3:00000000 r2:c02cad13
[ 566.407516] r7:00001002 r6:00000000 r5:c0310be4 r4:c0310be4
[ 566.415786] [<c0077bd4>] (__enable_irq+0x0/0x6c) from [<c0077fd0>] (enable_irq+0x38/0x64)
[ 566.425826] r5:c0310be4 r4:a0000013
[ 566.430709] [<c0077f98>] (enable_irq+0x0/0x64) from [<bf0dfa78>] (wl12xx_boot_run_firmware+0xfc/0x170 [wl12xx])
[ 566.442947] r7:00001002 r6:c440a9fc r5:00000072 r4:c440a9e0
[ 566.450851] [<bf0df97c>] (wl12xx_boot_run_firmware+0x0/0x170 [wl12xx]) from [<bf0e05f0>] (wl1251_boot+0xd4/0x108 [wl12xx])
[ 566.464492] r5:00000000 r4:c440a9e0
[ 566.469466] [<bf0e051c>] (wl1251_boot+0x0/0x108 [wl12xx]) from [<bf0dd27c>] (wl12xx_op_start+0x54/0xb8 [wl12xx])
[ 566.482162] r5:00000000 r4:c440a9e0
[ 566.487472] [<bf0dd228>] (wl12xx_op_start+0x0/0xb8 [wl12xx]) from [<bf0b96dc>] (ieee80211_open+0x2dc/0x720 [mac80211])
[ 566.500594] r7:00001002 r6:c4950800 r5:c440a220 r4:00000000
[ 566.508865] [<bf0b9400>] (ieee80211_open+0x0/0x720 [mac80211]) from [<c01f1edc>] (dev_open+0x9c/0xfc)
[ 566.520705] [<c01f1e40>] (dev_open+0x0/0xfc) from [<c01f17dc>] (dev_change_flags+0x98/0x170)
[ 566.531417] r5:00000041 r4:c4950800
[ 566.536330] [<c01f1744>] (dev_change_flags+0x0/0x170) from [<c023041c>] (devinet_ioctl+0x3a8/0x784)
[ 566.547683] r7:c128e380 r6:00000001 r5:00008914 r4:00000000
[ 566.555587] [<c0230074>] (devinet_ioctl+0x0/0x784) from [<c02318cc>] (inet_ioctl+0xdc/0x114)
[ 566.566299] [<c02317f0>] (inet_ioctl+0x0/0x114) from [<c01e1a60>] (sock_ioctl+0x1f0/0x248)
[ 566.576827] r5:00008914 r4:c572c1a0
[ 566.581771] [<c01e1870>] (sock_ioctl+0x0/0x248) from [<c00b23a0>] (vfs_ioctl+0x34/0x94)
[ 566.592086] r7:c572c1a0 r6:bee497e8 r5:00008914 r4:c572c1a0
[ 566.599990] [<c00b236c>] (vfs_ioctl+0x0/0x94) from [<c00b2a28>] (do_vfs_ioctl+0x52c/0x584)
[ 566.610549] r7:c572c1a0 r6:00008914 r5:c572c1a0 r4:c3201228
[ 566.618453] [<c00b24fc>] (do_vfs_ioctl+0x0/0x584) from [<c00b2ac0>] (sys_ioctl+0x40/0x64)
[ 566.628890] [<c00b2a80>] (sys_ioctl+0x0/0x64) from [<c0021da0>] (ret_fast_syscall+0x0/0x2c)
[ 566.639541] r7:00000036 r6:00000000 r5:00000004 r4:001a11f3
[ 566.647445] ---[ end trace 15c26ef7dd5e7b03 ]---

Signed-off-by: Bob Copeland <[email protected]>
---
drivers/net/wireless/wl12xx/wl1251.h | 5 ++++-
drivers/net/wireless/wl12xx/wl1251_boot.c | 7 +------
drivers/net/wireless/wl12xx/wl1251_main.c | 26 +++++++++-----------------
drivers/net/wireless/wl12xx/wl1251_sdio.c | 7 ++++++-
drivers/net/wireless/wl12xx/wl1251_spi.c | 17 +++++++++++++++++
5 files changed, 37 insertions(+), 25 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h
index ebe2c70..20d77fe 100644
--- a/drivers/net/wireless/wl12xx/wl1251.h
+++ b/drivers/net/wireless/wl12xx/wl1251.h
@@ -295,6 +295,8 @@ struct wl1251 {
const struct wl1251_if_operations *if_ops;

void (*set_power)(bool enable);
+ void (*enable_irq)(int irq);
+ void (*disable_irq)(int irq);
int irq;

enum wl1251_state state;
@@ -404,10 +406,11 @@ struct wl1251 {
int wl1251_plt_start(struct wl1251 *wl);
int wl1251_plt_stop(struct wl1251 *wl);

-irqreturn_t wl1251_irq(int irq, void *cookie);
struct ieee80211_hw *wl1251_alloc_hw(void);
int wl1251_free_hw(struct wl1251 *wl);
int wl1251_init_ieee80211(struct wl1251 *wl);
+void wl1251_enable_interrupts(struct wl1251 *wl);
+void wl1251_disable_interrupts(struct wl1251 *wl);

#define DEFAULT_HW_GEN_MODULATION_TYPE CCK_LONG /* Long Preamble */
#define DEFAULT_HW_GEN_TX_RATE RATE_2MBPS
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c
index 5c6f327..8b50d44 100644
--- a/drivers/net/wireless/wl12xx/wl1251_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1251_boot.c
@@ -29,11 +29,6 @@
#include "wl1251_spi.h"
#include "wl1251_event.h"

-static void wl1251_boot_enable_interrupts(struct wl1251 *wl)
-{
- enable_irq(wl->irq);
-}
-
void wl1251_boot_target_enable_interrupts(struct wl1251 *wl)
{
wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask));
@@ -278,7 +273,7 @@ int wl1251_boot_run_firmware(struct wl1251 *wl)
*/

/* enable gpio interrupts */
- wl1251_boot_enable_interrupts(wl);
+ wl1251_enable_interrupts(wl);

wl->chip.op_target_enable_interrupts(wl);

diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
index c5c94b2..094247c 100644
--- a/drivers/net/wireless/wl12xx/wl1251_main.c
+++ b/drivers/net/wireless/wl12xx/wl1251_main.c
@@ -42,9 +42,16 @@
#include "wl1251_init.h"
#include "wl1251_debugfs.h"

-static void wl1251_disable_interrupts(struct wl1251 *wl)
+void wl1251_enable_interrupts(struct wl1251 *wl)
{
- disable_irq(wl->irq);
+ if (wl->enable_irq)
+ wl->enable_irq(wl->irq);
+}
+
+void wl1251_disable_interrupts(struct wl1251 *wl)
+{
+ if (wl->disable_irq)
+ wl->disable_irq(wl->irq);
}

static void wl1251_power_off(struct wl1251 *wl)
@@ -57,20 +64,6 @@ static void wl1251_power_on(struct wl1251 *wl)
wl->set_power(true);
}

-irqreturn_t wl1251_irq(int irq, void *cookie)
-{
- struct wl1251 *wl;
-
- wl1251_debug(DEBUG_IRQ, "IRQ");
-
- wl = cookie;
-
- schedule_work(&wl->irq_work);
-
- return IRQ_HANDLED;
-}
-EXPORT_SYMBOL_GPL(wl1251_irq);
-
static int wl1251_fetch_firmware(struct wl1251 *wl)
{
const struct firmware *fw;
@@ -1335,7 +1328,6 @@ int wl1251_free_hw(struct wl1251 *wl)

wl1251_debugfs_exit(wl);

- free_irq(wl->irq, wl);
kfree(wl->target_mem_map);
kfree(wl->data_path);
kfree(wl->fw);
diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c
index f1d9e76..66961e3 100644
--- a/drivers/net/wireless/wl12xx/wl1251_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c
@@ -50,7 +50,12 @@ static struct sdio_func *wl_to_func(struct wl1251 *wl)

static void wl1251_sdio_interrupt(struct sdio_func *func)
{
- wl1251_irq(0, sdio_get_drvdata(func));
+ struct wl1251 *wl = sdio_get_drvdata(func);
+
+ wl1251_debug(DEBUG_IRQ, "IRQ");
+
+ /* FIXME should be synchronous for sdio */
+ schedule_work(&wl->irq_work);
}

static const struct sdio_device_id wl1251_devices[] = {
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c
index 464b802..a835d56 100644
--- a/drivers/net/wireless/wl12xx/wl1251_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1251_spi.c
@@ -31,6 +31,19 @@
#include "reg.h"
#include "wl1251_spi.h"

+static irqreturn_t wl1251_irq(int irq, void *cookie)
+{
+ struct wl1251 *wl;
+
+ wl1251_debug(DEBUG_IRQ, "IRQ");
+
+ wl = cookie;
+
+ schedule_work(&wl->irq_work);
+
+ return IRQ_HANDLED;
+}
+
static struct spi_device *wl_to_spi(struct wl1251 *wl)
{
return wl->if_priv;
@@ -255,6 +268,9 @@ static int __devinit wl1251_spi_probe(struct spi_device *spi)

disable_irq(wl->irq);

+ wl->enable_irq = enable_irq;
+ wl->disable_irq = disable_irq;
+
ret = wl1251_init_ieee80211(wl);
if (ret)
goto out_irq;
@@ -274,6 +290,7 @@ static int __devexit wl1251_spi_remove(struct spi_device *spi)
{
struct wl1251 *wl = dev_get_drvdata(&spi->dev);

+ free_irq(wl->irq, wl);
wl1251_free_hw(wl);

return 0;
--
1.6.2.5


--
Bob Copeland %% http://www.bobcopeland.com


2009-07-17 18:56:03

by Kalle Valo

[permalink] [raw]
Subject: [RFC PATCH v2 8/8] wl1251: add sdio support

From: Bob Copeland <[email protected]>

This adds the wl1251_sdio module, enabling the SDIO interface for
wl1251, as used by the Google G1 phone and others.

Signed-off-by: Bob Copeland <[email protected]>
---

drivers/net/wireless/wl12xx/Kconfig | 11 ++
drivers/net/wireless/wl12xx/Makefile | 1
drivers/net/wireless/wl12xx/wl1251_sdio.c | 188 +++++++++++++++++++++++++++++
3 files changed, 200 insertions(+), 0 deletions(-)
create mode 100644 drivers/net/wireless/wl12xx/wl1251_sdio.c

diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig
index e47d076..3c8b2cd 100644
--- a/drivers/net/wireless/wl12xx/Kconfig
+++ b/drivers/net/wireless/wl12xx/Kconfig
@@ -27,3 +27,14 @@ config WL1251_SPI

If you choose to build a module, it'll be called wl1251_spi.
Say N if unsure.
+
+config WL1251_SDIO
+ tristate "TI wl1251 SDIO support"
+ depends on WL1251 && MMC
+ ---help---
+ This module adds support for the SDIO interface of adapters using
+ TI wl1251 chipset. Select this if your platform is using
+ the SDIO bus.
+
+ If you choose to build a module, it'll be called
+ wl1251_sdio. Say N if unsure.
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile
index f92fe87..f3a7630 100644
--- a/drivers/net/wireless/wl12xx/Makefile
+++ b/drivers/net/wireless/wl12xx/Makefile
@@ -5,3 +5,4 @@ wl1251-objs = wl1251_main.o wl1251_spi.o wl1251_event.o \

obj-$(CONFIG_WL1251) += wl1251.o
obj-$(CONFIG_WL1251_SPI) += wl1251_spi.o
+obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o
diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c
new file mode 100644
index 0000000..f1d9e76
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c
@@ -0,0 +1,188 @@
+/*
+ * wl12xx SDIO routines
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * Copyright (C) 2005 Texas Instruments Incorporated
+ * Copyright (C) 2008 Google Inc
+ * Copyright (C) 2009 Bob Copeland ([email protected])
+ */
+#include <linux/module.h>
+#include <linux/crc7.h>
+#include <linux/mod_devicetable.h>
+#include <linux/irq.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/platform_device.h>
+
+#include "wl1251.h"
+#include "wl12xx_80211.h"
+#include "reg.h"
+#include "wl1251_ps.h"
+#include "wl1251_io.h"
+#include "wl1251_tx.h"
+#include "wl1251_debugfs.h"
+
+#ifndef SDIO_VENDOR_ID_TI
+#define SDIO_VENDOR_ID_TI 0x104c
+#endif
+
+#ifndef SDIO_DEVICE_ID_TI_WL1251
+#define SDIO_DEVICE_ID_TI_WL1251 0x9066
+#endif
+
+static struct sdio_func *wl_to_func(struct wl1251 *wl)
+{
+ return wl->if_priv;
+}
+
+static void wl1251_sdio_interrupt(struct sdio_func *func)
+{
+ wl1251_irq(0, sdio_get_drvdata(func));
+}
+
+static const struct sdio_device_id wl1251_devices[] = {
+ { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1251) },
+ {}
+};
+MODULE_DEVICE_TABLE(sdio, wl1251_devices);
+
+
+void wl1251_sdio_read(struct wl1251 *wl, int addr, void *buf, size_t len)
+{
+ int ret;
+ struct sdio_func *func = wl_to_func(wl);
+
+ sdio_claim_host(func);
+ ret = sdio_memcpy_fromio(func, buf, addr, len);
+ if (ret)
+ wl1251_error("sdio read failed (%d)", ret);
+ sdio_release_host(func);
+}
+
+void wl1251_sdio_write(struct wl1251 *wl, int addr, void *buf, size_t len)
+{
+ int ret;
+ struct sdio_func *func = wl_to_func(wl);
+
+ sdio_claim_host(func);
+ ret = sdio_memcpy_toio(func, addr, buf, len);
+ if (ret)
+ wl1251_error("sdio write failed (%d)", ret);
+ sdio_release_host(func);
+}
+
+void wl1251_sdio_reset(struct wl1251 *wl)
+{
+}
+
+void wl1251_sdio_set_power(bool enable)
+{
+}
+
+struct wl1251_if_operations wl1251_sdio_ops = {
+ .read = wl1251_sdio_read,
+ .write = wl1251_sdio_write,
+ .reset = wl1251_sdio_reset,
+};
+
+int wl1251_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
+{
+ int ret;
+ struct wl1251 *wl;
+ struct ieee80211_hw *hw;
+
+ hw = wl1251_alloc_hw();
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+
+ wl = hw->priv;
+
+ sdio_claim_host(func);
+ ret = sdio_enable_func(func);
+ if (ret)
+ goto release;
+
+ sdio_set_block_size(func, 512);
+
+ SET_IEEE80211_DEV(hw, &func->dev);
+ wl->if_priv = func;
+ wl->if_ops = &wl1251_sdio_ops;
+ wl->set_power = wl1251_sdio_set_power;
+
+ sdio_release_host(func);
+ ret = wl1251_init_ieee80211(wl);
+ sdio_claim_host(func);
+ if (ret)
+ goto disable;
+
+ ret = sdio_claim_irq(func, wl1251_sdio_interrupt);
+ if (ret)
+ goto no_irq;
+
+ sdio_release_host(func);
+ sdio_set_drvdata(func, wl);
+ return ret;
+
+no_irq:
+ wl1251_free_hw(wl);
+disable:
+ sdio_disable_func(func);
+release:
+ sdio_release_host(func);
+ return ret;
+}
+
+static void __devexit wl1251_sdio_remove(struct sdio_func *func)
+{
+ struct wl1251 *wl = sdio_get_drvdata(func);
+
+ wl1251_free_hw(wl);
+
+ sdio_claim_host(func);
+ sdio_release_irq(func);
+ sdio_disable_func(func);
+ sdio_release_host(func);
+}
+
+static struct sdio_driver wl1251_sdio_driver = {
+ .name = "wl1251_sdio",
+ .id_table = wl1251_devices,
+ .probe = wl1251_sdio_probe,
+ .remove = __devexit_p(wl1251_sdio_remove),
+};
+
+static int __init wl1251_sdio_init(void)
+{
+ int err;
+
+ err = sdio_register_driver(&wl1251_sdio_driver);
+ if (err)
+ wl1251_error("failed to register sdio driver: %d", err);
+ return err;
+}
+
+static void __exit wl1251_sdio_exit(void)
+{
+ sdio_unregister_driver(&wl1251_sdio_driver);
+ wl1251_notice("unloaded");
+}
+
+module_init(wl1251_sdio_init);
+module_exit(wl1251_sdio_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kalle Valo <[email protected]>");
+MODULE_AUTHOR("Luciano Coelho <[email protected]>");


2009-07-17 18:56:15

by Kalle Valo

[permalink] [raw]
Subject: [RFC PATCH v2 3/8] wl1251: use wiphy_dev instead of wl->spi->dev

From: Bob Copeland <[email protected]>

Remove a dependency on the bus-specific struct device by using wiphy_dev
when requesting firmware.

Signed-off-by: Bob Copeland <[email protected]>
Signed-off-by: Kalle Valo <[email protected]>
---

drivers/net/wireless/wl12xx/wl1251_main.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
index 2967e19..d9c5d8a 100644
--- a/drivers/net/wireless/wl12xx/wl1251_main.c
+++ b/drivers/net/wireless/wl12xx/wl1251_main.c
@@ -75,9 +75,10 @@ static irqreturn_t wl1251_irq(int irq, void *cookie)
static int wl1251_fetch_firmware(struct wl1251 *wl)
{
const struct firmware *fw;
+ struct device *dev = wiphy_dev(wl->hw->wiphy);
int ret;

- ret = request_firmware(&fw, wl->chip.fw_filename, &wl->spi->dev);
+ ret = request_firmware(&fw, wl->chip.fw_filename, dev);

if (ret < 0) {
wl1251_error("could not get firmware: %d", ret);
@@ -113,9 +114,10 @@ out:
static int wl1251_fetch_nvs(struct wl1251 *wl)
{
const struct firmware *fw;
+ struct device *dev = wiphy_dev(wl->hw->wiphy);
int ret;

- ret = request_firmware(&fw, wl->chip.nvs_filename, &wl->spi->dev);
+ ret = request_firmware(&fw, wl->chip.nvs_filename, dev);

if (ret < 0) {
wl1251_error("could not get nvs file: %d", ret);


2009-07-17 19:04:51

by Kalle Valo

[permalink] [raw]
Subject: Re: [RFC PATCH v2 0/8] wl1251 sdio interface

Kalle Valo <[email protected]> writes:

> Here is v2 of Bob's wl1251 sdio patches. I have now rebased them on
> top of wl1251/wl1271 split patches. Only compile-tested because I
> don't have working test setup right now (neither spi or sdio), but I
> should have access to one in two weeks.

I forgot to mention that wl1251 most probably is still broken regards to
bssid handling. I will fix this after my (current) vacation, unless
someone else is faster. To get wl1251 temporarily working, this patch
must be reverted:

commit cc3ec8cb518534c1c593e5f2682710d33c903627
Author: Johannes Berg <[email protected]>
Date: Thu May 14 13:10:14 2009 +0200

mac80211: fix managed mode BSSID handling

Currently, we will ask the driver to configure right away
when somebody changes the desired BSSID. That's totally
strange because then we will configure the driver without
even knowing whether the BSS exists. Change this to only
configure the BSSID when associated, and configure a zero
BSSID when not associated.

Oddly enough I can't find this patch anymore in wireless-testing, I
could only find a revert. I don't know what happened to it.

--
Kalle Valo

2009-07-17 19:20:33

by Bob Copeland

[permalink] [raw]
Subject: Re: [RFC PATCH v2 0/8] wl1251 sdio interface

On Fri, 17 Jul 2009 22:04:47 +0300, Kalle Valo wrote
> Kalle Valo <[email protected]> writes:
> I forgot to mention that wl1251 most probably is still broken regards to
> bssid handling. I will fix this after my (current) vacation, unless
> someone else is faster. To get wl1251 temporarily working, this patch
> must be reverted:

Thanks Kalle,

I'll take a look at doing this conversion too.

--
Bob Copeland %% http://www.bobcopeland.com



2009-07-17 18:56:03

by Kalle Valo

[permalink] [raw]
Subject: [RFC PATCH v2 5/8] wl1251: make wl1251_set_partition bus agnostic

From: Bob Copeland <[email protected]>

The same partition setting code can be used for both SPI and SDIO
modes, if we remove the spi-specific commands and use the more
generic buffer write routines. Do that and move it to io.c
since it deals with register/memory address offsets.

Signed-off-by: Bob Copeland <[email protected]>
Signed-off-by: Kalle Valo <[email protected]>
---

drivers/net/wireless/wl12xx/wl1251_io.c | 95 +++++++++++++++++++++++
drivers/net/wireless/wl12xx/wl1251_io.h | 15 ++++
drivers/net/wireless/wl12xx/wl1251_spi.c | 124 ------------------------------
drivers/net/wireless/wl12xx/wl1251_spi.h | 15 ----
4 files changed, 110 insertions(+), 139 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1251_io.c b/drivers/net/wireless/wl12xx/wl1251_io.c
index bc95785..db2cfbf 100644
--- a/drivers/net/wireless/wl12xx/wl1251_io.c
+++ b/drivers/net/wireless/wl12xx/wl1251_io.c
@@ -84,3 +84,98 @@ void wl1251_reg_write32(struct wl1251 *wl, int addr, u32 val)
{
wl1251_write32(wl, wl1251_translate_reg_addr(wl, addr), val);
}
+
+/* Set the partitions to access the chip addresses.
+ *
+ * There are two VIRTUAL partitions (the memory partition and the
+ * registers partition), which are mapped to two different areas of the
+ * PHYSICAL (hardware) memory. This function also makes other checks to
+ * ensure that the partitions are not overlapping. In the diagram below, the
+ * memory partition comes before the register partition, but the opposite is
+ * also supported.
+ *
+ * PHYSICAL address
+ * space
+ *
+ * | |
+ * ...+----+--> mem_start
+ * VIRTUAL address ... | |
+ * space ... | | [PART_0]
+ * ... | |
+ * 0x00000000 <--+----+... ...+----+--> mem_start + mem_size
+ * | | ... | |
+ * |MEM | ... | |
+ * | | ... | |
+ * part_size <--+----+... | | {unused area)
+ * | | ... | |
+ * |REG | ... | |
+ * part_size | | ... | |
+ * + <--+----+... ...+----+--> reg_start
+ * reg_size ... | |
+ * ... | | [PART_1]
+ * ... | |
+ * ...+----+--> reg_start + reg_size
+ * | |
+ *
+ */
+void wl1251_set_partition(struct wl1251 *wl,
+ u32 mem_start, u32 mem_size,
+ u32 reg_start, u32 reg_size)
+{
+ struct wl1251_partition partition[2];
+
+ wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
+ mem_start, mem_size);
+ wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
+ reg_start, reg_size);
+
+ /* Make sure that the two partitions together don't exceed the
+ * address range */
+ if ((mem_size + reg_size) > HW_ACCESS_MEMORY_MAX_RANGE) {
+ wl1251_debug(DEBUG_SPI, "Total size exceeds maximum virtual"
+ " address range. Truncating partition[0].");
+ mem_size = HW_ACCESS_MEMORY_MAX_RANGE - reg_size;
+ wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
+ mem_start, mem_size);
+ wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
+ reg_start, reg_size);
+ }
+
+ if ((mem_start < reg_start) &&
+ ((mem_start + mem_size) > reg_start)) {
+ /* Guarantee that the memory partition doesn't overlap the
+ * registers partition */
+ wl1251_debug(DEBUG_SPI, "End of partition[0] is "
+ "overlapping partition[1]. Adjusted.");
+ mem_size = reg_start - mem_start;
+ wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
+ mem_start, mem_size);
+ wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
+ reg_start, reg_size);
+ } else if ((reg_start < mem_start) &&
+ ((reg_start + reg_size) > mem_start)) {
+ /* Guarantee that the register partition doesn't overlap the
+ * memory partition */
+ wl1251_debug(DEBUG_SPI, "End of partition[1] is"
+ " overlapping partition[0]. Adjusted.");
+ reg_size = mem_start - reg_start;
+ wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
+ mem_start, mem_size);
+ wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
+ reg_start, reg_size);
+ }
+
+ partition[0].start = mem_start;
+ partition[0].size = mem_size;
+ partition[1].start = reg_start;
+ partition[1].size = reg_size;
+
+ wl->physical_mem_addr = mem_start;
+ wl->physical_reg_addr = reg_start;
+
+ wl->virtual_mem_addr = 0;
+ wl->virtual_reg_addr = mem_size;
+
+ wl->if_ops->write(wl, HW_ACCESS_PART0_SIZE_ADDR, partition,
+ sizeof(partition));
+}
diff --git a/drivers/net/wireless/wl12xx/wl1251_io.h b/drivers/net/wireless/wl12xx/wl1251_io.h
index 1fa2ab1..b89d2ac 100644
--- a/drivers/net/wireless/wl12xx/wl1251_io.h
+++ b/drivers/net/wireless/wl12xx/wl1251_io.h
@@ -23,6 +23,17 @@

#include "wl1251.h"

+#define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0
+
+#define HW_ACCESS_PART0_SIZE_ADDR 0x1FFC0
+#define HW_ACCESS_PART0_START_ADDR 0x1FFC4
+#define HW_ACCESS_PART1_SIZE_ADDR 0x1FFC8
+#define HW_ACCESS_PART1_START_ADDR 0x1FFCC
+
+#define HW_ACCESS_REGISTER_SIZE 4
+
+#define HW_ACCESS_PRAM_MAX_RANGE 0x3c000
+
static inline u32 wl1251_read32(struct wl1251 *wl, int addr)
{
u32 response;
@@ -46,4 +57,8 @@ void wl1251_mem_write32(struct wl1251 *wl, int addr, u32 val);
u32 wl1251_reg_read32(struct wl1251 *wl, int addr);
void wl1251_reg_write32(struct wl1251 *wl, int addr, u32 val);

+void wl1251_set_partition(struct wl1251 *wl,
+ u32 part_start, u32 part_size,
+ u32 reg_start, u32 reg_size);
+
#endif
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c
index 61a0852..ceb237b 100644
--- a/drivers/net/wireless/wl12xx/wl1251_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1251_spi.c
@@ -115,130 +115,6 @@ static void wl1251_spi_reset_wake(struct wl1251 *wl)
wl1251_spi_init(wl);
}

-
-/* Set the SPI partitions to access the chip addresses
- *
- * There are two VIRTUAL (SPI) partitions (the memory partition and the
- * registers partition), which are mapped to two different areas of the
- * PHYSICAL (hardware) memory. This function also makes other checks to
- * ensure that the partitions are not overlapping. In the diagram below, the
- * memory partition comes before the register partition, but the opposite is
- * also supported.
- *
- * PHYSICAL address
- * space
- *
- * | |
- * ...+----+--> mem_start
- * VIRTUAL address ... | |
- * space ... | | [PART_0]
- * ... | |
- * 0x00000000 <--+----+... ...+----+--> mem_start + mem_size
- * | | ... | |
- * |MEM | ... | |
- * | | ... | |
- * part_size <--+----+... | | {unused area)
- * | | ... | |
- * |REG | ... | |
- * part_size | | ... | |
- * + <--+----+... ...+----+--> reg_start
- * reg_size ... | |
- * ... | | [PART_1]
- * ... | |
- * ...+----+--> reg_start + reg_size
- * | |
- *
- */
-int wl1251_set_partition(struct wl1251 *wl,
- u32 mem_start, u32 mem_size,
- u32 reg_start, u32 reg_size)
-{
- struct wl1251_partition *partition;
- struct spi_transfer t;
- struct spi_message m;
- size_t len, cmd_len;
- u32 *cmd;
- int addr;
-
- cmd_len = sizeof(u32) + 2 * sizeof(struct wl1251_partition);
- cmd = kzalloc(cmd_len, GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
-
- spi_message_init(&m);
- memset(&t, 0, sizeof(t));
-
- partition = (struct wl1251_partition *) (cmd + 1);
- addr = HW_ACCESS_PART0_SIZE_ADDR;
- len = 2 * sizeof(struct wl1251_partition);
-
- *cmd |= WSPI_CMD_WRITE;
- *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
- *cmd |= addr & WSPI_CMD_BYTE_ADDR;
-
- wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
- mem_start, mem_size);
- wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
- reg_start, reg_size);
-
- /* Make sure that the two partitions together don't exceed the
- * address range */
- if ((mem_size + reg_size) > HW_ACCESS_MEMORY_MAX_RANGE) {
- wl1251_debug(DEBUG_SPI, "Total size exceeds maximum virtual"
- " address range. Truncating partition[0].");
- mem_size = HW_ACCESS_MEMORY_MAX_RANGE - reg_size;
- wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
- mem_start, mem_size);
- wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
- reg_start, reg_size);
- }
-
- if ((mem_start < reg_start) &&
- ((mem_start + mem_size) > reg_start)) {
- /* Guarantee that the memory partition doesn't overlap the
- * registers partition */
- wl1251_debug(DEBUG_SPI, "End of partition[0] is "
- "overlapping partition[1]. Adjusted.");
- mem_size = reg_start - mem_start;
- wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
- mem_start, mem_size);
- wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
- reg_start, reg_size);
- } else if ((reg_start < mem_start) &&
- ((reg_start + reg_size) > mem_start)) {
- /* Guarantee that the register partition doesn't overlap the
- * memory partition */
- wl1251_debug(DEBUG_SPI, "End of partition[1] is"
- " overlapping partition[0]. Adjusted.");
- reg_size = mem_start - reg_start;
- wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
- mem_start, mem_size);
- wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
- reg_start, reg_size);
- }
-
- partition[0].start = mem_start;
- partition[0].size = mem_size;
- partition[1].start = reg_start;
- partition[1].size = reg_size;
-
- wl->physical_mem_addr = mem_start;
- wl->physical_reg_addr = reg_start;
-
- wl->virtual_mem_addr = 0;
- wl->virtual_reg_addr = mem_size;
-
- t.tx_buf = cmd;
- t.len = cmd_len;
- spi_message_add_tail(&t, &m);
-
- spi_sync(wl->spi, &m);
-
- kfree(cmd);
-
- return 0;
-}
-
static void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf,
size_t len)
{
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.h b/drivers/net/wireless/wl12xx/wl1251_spi.h
index 7c6da21..cb0c228 100644
--- a/drivers/net/wireless/wl12xx/wl1251_spi.h
+++ b/drivers/net/wireless/wl12xx/wl1251_spi.h
@@ -29,17 +29,6 @@
#include "wl1251_acx.h"
#include "reg.h"

-#define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0
-
-#define HW_ACCESS_PART0_SIZE_ADDR 0x1FFC0
-#define HW_ACCESS_PART0_START_ADDR 0x1FFC4
-#define HW_ACCESS_PART1_SIZE_ADDR 0x1FFC8
-#define HW_ACCESS_PART1_START_ADDR 0x1FFCC
-
-#define HW_ACCESS_REGISTER_SIZE 4
-
-#define HW_ACCESS_PRAM_MAX_RANGE 0x3c000
-
#define WSPI_CMD_READ 0x40000000
#define WSPI_CMD_WRITE 0x00000000
#define WSPI_CMD_FIXED 0x20000000
@@ -69,8 +58,4 @@
((WL1251_BUSY_WORD_LEN - 4) / sizeof(u32))
#define HW_ACCESS_WSPI_INIT_CMD_MASK 0

-int wl1251_set_partition(struct wl1251 *wl,
- u32 part_start, u32 part_size,
- u32 reg_start, u32 reg_size);
-
#endif /* __WL1251_SPI_H__ */