This patch series includes firmware loading enhancements for
Redpine 9113 chipset. The older method is not being used by any
Redpine chipset. There is no firmware image submitted to upstream
yet. We will submit 9113's firmware image once these changes are
accepted.
Amitkumar Karwar (1):
rsi: define RSI_USB_BUF_SIZE macro
Prameela Rani Garnepudi (10):
rsi: Rename file rsi_91x_pkt.c to rsi_91x_hal.c
rsi: Changes to sdio reads and writes
rsi: Changes in USB read and write operations
rsi: use macros in USB specific code
rsi: Handle usb multi-byte write failure case properly
rsi: Add usb multi-byte read operation
rsi: Add host interface operations as separate structure.
rsi: Add new host interface operations
rsi: Add new firmware loading method
rsi: Remove old firmware loading method
drivers/net/wireless/rsi/Makefile | 2 +-
drivers/net/wireless/rsi/rsi_91x_hal.c | 740 ++++++++++++++++++++++++++++
drivers/net/wireless/rsi/rsi_91x_pkt.c | 215 --------
drivers/net/wireless/rsi/rsi_91x_sdio.c | 211 +++++++-
drivers/net/wireless/rsi/rsi_91x_sdio_ops.c | 190 +------
drivers/net/wireless/rsi/rsi_91x_usb.c | 166 ++++++-
drivers/net/wireless/rsi/rsi_91x_usb_ops.c | 125 -----
drivers/net/wireless/rsi/rsi_common.h | 3 +-
drivers/net/wireless/rsi/rsi_hal.h | 81 +++
drivers/net/wireless/rsi/rsi_main.h | 36 +-
drivers/net/wireless/rsi/rsi_sdio.h | 6 +-
drivers/net/wireless/rsi/rsi_usb.h | 5 +-
12 files changed, 1205 insertions(+), 575 deletions(-)
create mode 100644 drivers/net/wireless/rsi/rsi_91x_hal.c
delete mode 100644 drivers/net/wireless/rsi/rsi_91x_pkt.c
create mode 100644 drivers/net/wireless/rsi/rsi_hal.h
--
2.7.4
amit karwar <[email protected]> writes:
> On Wed, May 24, 2017 at 1:57 PM, Kalle Valo <[email protected]> wrote:
>> Amitkumar Karwar <[email protected]> writes:
>>
>>> From: Prameela Rani Garnepudi <[email protected]>
>>>
>>> The older firmware loading method has been deprecated and not in use
>>> for any chipets. New method is introduced which works based on soft
>>> boot loader. In this method, complete RAM image and FLASH image are
>>> present in the flash. Before loading the functional firmware, host
>>> issues boot loader commands to verify whether firmware to load is
>>> different from the current functional firmware. If not, firmware
>>> upgrade progresses and boot loader will switch to the new functional
>>> firmware.
>>>
>>> "rs9113_wlan_qspi.rps" is the firmware filename used in this patch.
>>
>> I don't know if you saw the discussion with the wil6210 firmware, but
>> the linux-firmware maintainers prefer to have a subdirectory for
>> firmware files. I'm planning to apply this series now, but you can send
>> a followup patch ASAP which changes the rsi driver to use a subdirectory
>> for the firmware files?
>
> I have just sent a follow up patch.
Thanks, I saw that. Will apply it shortly.
--
Kalle Valo
From: Prameela Rani Garnepudi <[email protected]>
In function usb_write_register_multiple, if any intermediate block transfer
is failed, further operations should be terminated. 'else' is removed, as
there is no significance for it after return.
Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
v3: Same as earlier. Below patch has been dropped in this
series(Kalle Valo/Arend van Spriel)
[v2 05/11] rsi: Remove unnecessary buffer allocation
---
drivers/net/wireless/rsi/rsi_91x_usb.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index 9e1359a..a900a72 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -316,11 +316,12 @@ int rsi_usb_write_register_multiple(struct rsi_hw *adapter,
rsi_dbg(ERR_ZONE,
"Reg write failed with error code :%d\n",
status);
- } else {
- count -= transfer;
- data += transfer;
- addr += transfer;
+ kfree(buf);
+ return status;
}
+ count -= transfer;
+ data += transfer;
+ addr += transfer;
}
kfree(buf);
--
2.7.4
From: Prameela Rani Garnepudi <[email protected]>
Host interface operations are currently function pointers in rsi_hw
structure. As more host interface operations are going to be introduced,
separate structure is added for these for convenience.
Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
v3: Same as earlier
---
drivers/net/wireless/rsi/rsi_91x_hal.c | 16 +++++++---------
drivers/net/wireless/rsi/rsi_91x_sdio.c | 11 +++++++++--
drivers/net/wireless/rsi/rsi_91x_usb.c | 9 ++++++++-
drivers/net/wireless/rsi/rsi_main.h | 18 ++++++++++++++++--
4 files changed, 40 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c
index 02920c9..8fbf904 100644
--- a/drivers/net/wireless/rsi/rsi_91x_hal.c
+++ b/drivers/net/wireless/rsi/rsi_91x_hal.c
@@ -100,9 +100,8 @@ int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb)
(skb->priority & 0xf) |
(tx_params->sta_id << 8));
- status = adapter->host_intf_write_pkt(common->priv,
- skb->data,
- skb->len);
+ status = adapter->host_intf_ops->write_pkt(common->priv, skb->data,
+ skb->len);
if (status)
rsi_dbg(ERR_ZONE, "%s: Failed to write pkt\n",
__func__);
@@ -148,9 +147,9 @@ int rsi_send_mgmt_pkt(struct rsi_common *common,
}
skb_push(skb, extnd_size);
skb->data[extnd_size + 4] = extnd_size;
- status = adapter->host_intf_write_pkt(common->priv,
- (u8 *)skb->data,
- skb->len);
+ status = adapter->host_intf_ops->write_pkt(common->priv,
+ (u8 *)skb->data,
+ skb->len);
if (status) {
rsi_dbg(ERR_ZONE,
"%s: Failed to write the packet\n", __func__);
@@ -203,9 +202,8 @@ int rsi_send_mgmt_pkt(struct rsi_common *common,
msg[7] |= cpu_to_le16(vap_id << 8);
- status = adapter->host_intf_write_pkt(common->priv,
- (u8 *)msg,
- skb->len);
+ status = adapter->host_intf_ops->write_pkt(common->priv, (u8 *)msg,
+ skb->len);
if (status)
rsi_dbg(ERR_ZONE, "%s: Failed to write the packet\n", __func__);
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index 39d94b3..bdbec8b 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -676,8 +676,6 @@ static int rsi_init_sdio_interface(struct rsi_hw *adapter,
}
sdio_release_host(pfunction);
- adapter->host_intf_write_pkt = rsi_sdio_host_intf_write_pkt;
- adapter->host_intf_read_pkt = rsi_sdio_host_intf_read_pkt;
adapter->determine_event_timeout = rsi_sdio_determine_event_timeout;
adapter->check_hw_queue_status = rsi_sdio_read_buffer_status_register;
@@ -691,6 +689,13 @@ static int rsi_init_sdio_interface(struct rsi_hw *adapter,
return status;
}
+static struct rsi_host_intf_ops sdio_host_intf_ops = {
+ .write_pkt = rsi_sdio_host_intf_write_pkt,
+ .read_pkt = rsi_sdio_host_intf_read_pkt,
+ .read_reg_multiple = rsi_sdio_read_register_multiple,
+ .write_reg_multiple = rsi_sdio_write_register_multiple,
+};
+
/**
* rsi_probe() - This function is called by kernel when the driver provided
* Vendor and device IDs are matched. All the initialization
@@ -713,6 +718,8 @@ static int rsi_probe(struct sdio_func *pfunction,
__func__);
return 1;
}
+ adapter->rsi_host_intf = RSI_HOST_INTF_SDIO;
+ adapter->host_intf_ops = &sdio_host_intf_ops;
if (rsi_init_sdio_interface(adapter, pfunction)) {
rsi_dbg(ERR_ZONE, "%s: Failed to init sdio interface\n",
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index 31f96f0..9000e09 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -392,6 +392,12 @@ static int rsi_usb_host_intf_write_pkt(struct rsi_hw *adapter,
len);
}
+static struct rsi_host_intf_ops usb_host_intf_ops = {
+ .write_pkt = rsi_usb_host_intf_write_pkt,
+ .read_reg_multiple = rsi_usb_read_register_multiple,
+ .write_reg_multiple = rsi_usb_write_register_multiple,
+};
+
/**
* rsi_deinit_usb_interface() - This function deinitializes the usb interface.
* @adapter: Pointer to the adapter structure.
@@ -457,9 +463,10 @@ static int rsi_init_usb_interface(struct rsi_hw *adapter,
/* Initializing function callbacks */
adapter->rx_urb_submit = rsi_rx_urb_submit;
- adapter->host_intf_write_pkt = rsi_usb_host_intf_write_pkt;
adapter->check_hw_queue_status = rsi_usb_check_queue_status;
adapter->determine_event_timeout = rsi_usb_event_timeout;
+ adapter->rsi_host_intf = RSI_HOST_INTF_USB;
+ adapter->host_intf_ops = &usb_host_intf_ops;
rsi_init_event(&rsi_dev->rx_thread.event);
status = rsi_create_kthread(common, &rsi_dev->rx_thread,
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index 1d5904b..7fdeda7 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -209,6 +209,11 @@ struct rsi_common {
u8 ant_in_use;
};
+enum host_intf {
+ RSI_HOST_INTF_SDIO = 0,
+ RSI_HOST_INTF_USB
+};
+
struct rsi_hw {
struct rsi_common *priv;
struct ieee80211_hw *hw;
@@ -219,16 +224,25 @@ struct rsi_hw {
struct device *device;
u8 sc_nvifs;
+ enum host_intf rsi_host_intf;
#ifdef CONFIG_RSI_DEBUGFS
struct rsi_debugfs *dfsentry;
u8 num_debugfs_entries;
#endif
u8 dfs_region;
void *rsi_dev;
- int (*host_intf_read_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
- int (*host_intf_write_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
+ struct rsi_host_intf_ops *host_intf_ops;
int (*check_hw_queue_status)(struct rsi_hw *adapter, u8 q_num);
int (*rx_urb_submit)(struct rsi_hw *adapter);
int (*determine_event_timeout)(struct rsi_hw *adapter);
};
+
+struct rsi_host_intf_ops {
+ int (*read_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
+ int (*write_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
+ int (*read_reg_multiple)(struct rsi_hw *adapter, u32 addr,
+ u8 *data, u16 count);
+ int (*write_reg_multiple)(struct rsi_hw *adapter, u32 addr,
+ u8 *data, u16 count);
+};
#endif
--
2.7.4
RSI_USB_BUF_SIZE macro is used instead of hardcoding a buffer
size to 4096.
Signed-off-by: Amitkumar Karwar <[email protected]>
---
v3: Newly added patch in v3
---
drivers/net/wireless/rsi/rsi_91x_usb.c | 4 ++--
drivers/net/wireless/rsi/rsi_usb.h | 2 ++
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index cc8deec..be8487c 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -293,12 +293,12 @@ int rsi_usb_write_register_multiple(struct rsi_hw *adapter,
u8 transfer;
int status = 0;
- buf = kzalloc(4096, GFP_KERNEL);
+ buf = kzalloc(RSI_USB_BUF_SIZE, GFP_KERNEL);
if (!buf)
return -ENOMEM;
while (count) {
- transfer = (u8)(min_t(u32, count, 4096));
+ transfer = (u8)(min_t(u32, count, RSI_USB_BUF_SIZE));
memcpy(buf, data, transfer);
status = usb_control_msg(dev->usbdev,
usb_sndctrlpipe(dev->usbdev, 0),
diff --git a/drivers/net/wireless/rsi/rsi_usb.h b/drivers/net/wireless/rsi/rsi_usb.h
index ebea0c4..48c9211 100644
--- a/drivers/net/wireless/rsi/rsi_usb.h
+++ b/drivers/net/wireless/rsi/rsi_usb.h
@@ -35,6 +35,8 @@
#define MGMT_EP 1
#define DATA_EP 2
+#define RSI_USB_BUF_SIZE 4096
+
struct rsi_91x_usbdev {
struct rsi_thread rx_thread;
u8 endpoint;
--
2.7.4
From: Prameela Rani Garnepudi <[email protected]>
The older firmware loading method has been deprecated and not in use
for any chipets. New method is introduced which works based on soft
boot loader. In this method, complete RAM image and FLASH image are
present in the flash. Before loading the functional firmware, host
issues boot loader commands to verify whether firmware to load is
different from the current functional firmware. If not, firmware
upgrade progresses and boot loader will switch to the new functional
firmware.
"rs9113_wlan_qspi.rps" is the firmware filename used in this patch.
Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
v3: Included new firmware name in commit description(Kalle Valo)
---
drivers/net/wireless/rsi/rsi_91x_hal.c | 527 ++++++++++++++++++++++++++++++++
drivers/net/wireless/rsi/rsi_91x_sdio.c | 11 +-
drivers/net/wireless/rsi/rsi_91x_usb.c | 16 +-
drivers/net/wireless/rsi/rsi_hal.h | 81 +++++
drivers/net/wireless/rsi/rsi_main.h | 10 +
5 files changed, 635 insertions(+), 10 deletions(-)
create mode 100644 drivers/net/wireless/rsi/rsi_hal.h
diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c
index 8fbf904..d49dbaa 100644
--- a/drivers/net/wireless/rsi/rsi_91x_hal.c
+++ b/drivers/net/wireless/rsi/rsi_91x_hal.c
@@ -14,7 +14,16 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <linux/firmware.h>
#include "rsi_mgmt.h"
+#include "rsi_hal.h"
+#include "rsi_sdio.h"
+
+/* FLASH Firmware */
+static struct ta_metadata metadata_flash_content[] = {
+ {"flash_content", 0x00010000},
+ {"rs9113_wlan_qspi.rps", 0x00010000},
+};
/**
* rsi_send_data_pkt() - This function sends the recieved data packet from
@@ -211,3 +220,521 @@ int rsi_send_mgmt_pkt(struct rsi_common *common,
rsi_indicate_tx_status(common->priv, skb, status);
return status;
}
+
+static void bl_cmd_timeout(unsigned long priv)
+{
+ struct rsi_hw *adapter = (struct rsi_hw *)priv;
+
+ adapter->blcmd_timer_expired = true;
+ del_timer(&adapter->bl_cmd_timer);
+}
+
+static int bl_start_cmd_timer(struct rsi_hw *adapter, u32 timeout)
+{
+ init_timer(&adapter->bl_cmd_timer);
+ adapter->bl_cmd_timer.data = (unsigned long)adapter;
+ adapter->bl_cmd_timer.function = (void *)&bl_cmd_timeout;
+ adapter->bl_cmd_timer.expires = (msecs_to_jiffies(timeout) + jiffies);
+
+ adapter->blcmd_timer_expired = false;
+ add_timer(&adapter->bl_cmd_timer);
+
+ return 0;
+}
+
+static int bl_stop_cmd_timer(struct rsi_hw *adapter)
+{
+ adapter->blcmd_timer_expired = false;
+ if (timer_pending(&adapter->bl_cmd_timer))
+ del_timer(&adapter->bl_cmd_timer);
+
+ return 0;
+}
+
+static int bl_write_cmd(struct rsi_hw *adapter, u8 cmd, u8 exp_resp,
+ u16 *cmd_resp)
+{
+ struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+ u32 regin_val = 0, regout_val = 0;
+ u32 regin_input = 0;
+ u8 output = 0;
+ int status;
+
+ regin_input = (REGIN_INPUT | adapter->priv->coex_mode);
+
+ while (!adapter->blcmd_timer_expired) {
+ regin_val = 0;
+ status = hif_ops->master_reg_read(adapter, SWBL_REGIN,
+ ®in_val, 2);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %0x REGIN reading failed..\n",
+ __func__, cmd);
+ return status;
+ }
+ mdelay(1);
+ if ((regin_val >> 12) != REGIN_VALID)
+ break;
+ }
+ if (adapter->blcmd_timer_expired) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %0x REGIN reading timed out..\n",
+ __func__, cmd);
+ return -ETIMEDOUT;
+ }
+
+ rsi_dbg(INFO_ZONE,
+ "Issuing write to Regin val:%0x sending cmd:%0x\n",
+ regin_val, (cmd | regin_input << 8));
+ status = hif_ops->master_reg_write(adapter, SWBL_REGIN,
+ (cmd | regin_input << 8), 2);
+ if (status < 0)
+ return status;
+ mdelay(1);
+
+ if (cmd == LOAD_HOSTED_FW || cmd == JUMP_TO_ZERO_PC) {
+ /* JUMP_TO_ZERO_PC doesn't expect
+ * any response. So return from here
+ */
+ return 0;
+ }
+
+ while (!adapter->blcmd_timer_expired) {
+ regout_val = 0;
+ status = hif_ops->master_reg_read(adapter, SWBL_REGOUT,
+ ®out_val, 2);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %0x REGOUT reading failed..\n",
+ __func__, cmd);
+ return status;
+ }
+ mdelay(1);
+ if ((regout_val >> 8) == REGOUT_VALID)
+ break;
+ }
+ if (adapter->blcmd_timer_expired) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %0x REGOUT reading timed out..\n",
+ __func__, cmd);
+ return status;
+ }
+
+ *cmd_resp = ((u16 *)®out_val)[0] & 0xffff;
+
+ output = ((u8 *)®out_val)[0] & 0xff;
+
+ status = hif_ops->master_reg_write(adapter, SWBL_REGOUT,
+ (cmd | REGOUT_INVALID << 8), 2);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %0x REGOUT writing failed..\n",
+ __func__, cmd);
+ return status;
+ }
+ mdelay(1);
+
+ if (output != exp_resp) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Recvd resp %x for cmd %0x\n",
+ __func__, output, cmd);
+ return -EINVAL;
+ }
+ rsi_dbg(INFO_ZONE,
+ "%s: Recvd Expected resp %x for cmd %0x\n",
+ __func__, output, cmd);
+
+ return 0;
+}
+
+static int bl_cmd(struct rsi_hw *adapter, u8 cmd, u8 exp_resp, char *str)
+{
+ u16 regout_val = 0;
+ u32 timeout;
+ int status;
+
+ if ((cmd == EOF_REACHED) || (cmd == PING_VALID) || (cmd == PONG_VALID))
+ timeout = BL_BURN_TIMEOUT;
+ else
+ timeout = BL_CMD_TIMEOUT;
+
+ bl_start_cmd_timer(adapter, timeout);
+ status = bl_write_cmd(adapter, cmd, exp_resp, ®out_val);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %s (%0x) writing failed..\n",
+ __func__, str, cmd);
+ return status;
+ }
+ bl_stop_cmd_timer(adapter);
+ return 0;
+}
+
+#define CHECK_SUM_OFFSET 20
+#define LEN_OFFSET 8
+#define ADDR_OFFSET 16
+static int bl_write_header(struct rsi_hw *adapter, u8 *flash_content,
+ u32 content_size)
+{
+ struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+ struct bl_header bl_hdr;
+ u32 write_addr, write_len;
+ int status;
+
+ bl_hdr.flags = 0;
+ bl_hdr.image_no = cpu_to_le32(adapter->priv->coex_mode);
+ bl_hdr.check_sum = cpu_to_le32(
+ *(u32 *)&flash_content[CHECK_SUM_OFFSET]);
+ bl_hdr.flash_start_address = cpu_to_le32(
+ *(u32 *)&flash_content[ADDR_OFFSET]);
+ bl_hdr.flash_len = cpu_to_le32(*(u32 *)&flash_content[LEN_OFFSET]);
+ write_len = sizeof(struct bl_header);
+
+ if (adapter->rsi_host_intf == RSI_HOST_INTF_USB) {
+ write_addr = PING_BUFFER_ADDRESS;
+ status = hif_ops->write_reg_multiple(adapter, write_addr,
+ (u8 *)&bl_hdr, write_len);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to load Version/CRC structure\n",
+ __func__);
+ return status;
+ }
+ } else {
+ write_addr = PING_BUFFER_ADDRESS >> 16;
+ status = hif_ops->master_access_msword(adapter, write_addr);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to set ms word to common reg\n",
+ __func__);
+ return status;
+ }
+ write_addr = RSI_SD_REQUEST_MASTER |
+ (PING_BUFFER_ADDRESS & 0xFFFF);
+ status = hif_ops->write_reg_multiple(adapter, write_addr,
+ (u8 *)&bl_hdr, write_len);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to load Version/CRC structure\n",
+ __func__);
+ return status;
+ }
+ }
+ return 0;
+}
+
+static u32 read_flash_capacity(struct rsi_hw *adapter)
+{
+ u32 flash_sz = 0;
+
+ if ((adapter->host_intf_ops->master_reg_read(adapter, FLASH_SIZE_ADDR,
+ &flash_sz, 2)) < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Flash size reading failed..\n",
+ __func__);
+ return 0;
+ }
+ rsi_dbg(INIT_ZONE, "Flash capacity: %d KiloBytes\n", flash_sz);
+
+ return (flash_sz * 1024); /* Return size in kbytes */
+}
+
+static int ping_pong_write(struct rsi_hw *adapter, u8 cmd, u8 *addr, u32 size)
+{
+ struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+ u32 block_size = adapter->block_size;
+ u32 cmd_addr;
+ u16 cmd_resp, cmd_req;
+ u8 *str;
+ int status;
+
+ if (cmd == PING_WRITE) {
+ cmd_addr = PING_BUFFER_ADDRESS;
+ cmd_resp = PONG_AVAIL;
+ cmd_req = PING_VALID;
+ str = "PING_VALID";
+ } else {
+ cmd_addr = PONG_BUFFER_ADDRESS;
+ cmd_resp = PING_AVAIL;
+ cmd_req = PONG_VALID;
+ str = "PONG_VALID";
+ }
+
+ status = hif_ops->load_data_master_write(adapter, cmd_addr, size,
+ block_size, addr);
+ if (status) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to write blk at addr %0x\n",
+ __func__, *addr);
+ return status;
+ }
+
+ status = bl_cmd(adapter, cmd_req, cmd_resp, str);
+ if (status) {
+ bl_stop_cmd_timer(adapter);
+ return status;
+ }
+ return 0;
+}
+
+static int auto_fw_upgrade(struct rsi_hw *adapter, u8 *flash_content,
+ u32 content_size)
+{
+ u8 cmd, *temp_flash_content;
+ u32 temp_content_size, num_flash, index;
+ u32 flash_start_address;
+ int status;
+
+ temp_flash_content = flash_content;
+
+ if (content_size > MAX_FLASH_FILE_SIZE) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Flash Content size is more than 400K %u\n",
+ __func__, MAX_FLASH_FILE_SIZE);
+ return -EINVAL;
+ }
+
+ flash_start_address = *(u32 *)&flash_content[FLASH_START_ADDRESS];
+ rsi_dbg(INFO_ZONE, "flash start address: %08x\n", flash_start_address);
+
+ if (flash_start_address < FW_IMAGE_MIN_ADDRESS) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Fw image Flash Start Address is less than 64K\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (flash_start_address % FLASH_SECTOR_SIZE) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Flash Start Address is not multiple of 4K\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if ((flash_start_address + content_size) > adapter->flash_capacity) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Flash Content will cross max flash size\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ temp_content_size = content_size;
+ num_flash = content_size / FLASH_WRITE_CHUNK_SIZE;
+
+ rsi_dbg(INFO_ZONE, "content_size: %d, num_flash: %d\n",
+ content_size, num_flash);
+
+ for (index = 0; index <= num_flash; index++) {
+ rsi_dbg(INFO_ZONE, "flash index: %d\n", index);
+ if (index != num_flash) {
+ content_size = FLASH_WRITE_CHUNK_SIZE;
+ rsi_dbg(INFO_ZONE, "QSPI content_size:%d\n",
+ content_size);
+ } else {
+ content_size =
+ temp_content_size % FLASH_WRITE_CHUNK_SIZE;
+ rsi_dbg(INFO_ZONE,
+ "Writing last sector content_size:%d\n",
+ content_size);
+ if (!content_size) {
+ rsi_dbg(INFO_ZONE, "instruction size zero\n");
+ break;
+ }
+ }
+
+ if (index % 2)
+ cmd = PING_WRITE;
+ else
+ cmd = PONG_WRITE;
+
+ status = ping_pong_write(adapter, cmd, flash_content,
+ content_size);
+ if (status) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to load %d block\n",
+ __func__, index);
+ return status;
+ }
+
+ rsi_dbg(INFO_ZONE,
+ "%s: Successfully loaded %d instructions\n",
+ __func__, index);
+ flash_content += content_size;
+ }
+
+ status = bl_cmd(adapter, EOF_REACHED, FW_LOADING_SUCCESSFUL,
+ "EOF_REACHED");
+ if (status) {
+ bl_stop_cmd_timer(adapter);
+ return status;
+ }
+ rsi_dbg(INFO_ZONE, "FW loading is done and FW is running..\n");
+ return 0;
+}
+
+static int rsi_load_firmware(struct rsi_hw *adapter)
+{
+ struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+ const struct firmware *fw_entry = NULL;
+ u32 regout_val = 0, content_size;
+ u16 tmp_regout_val = 0;
+ u8 *flash_content = NULL;
+ struct ta_metadata *metadata_p;
+ int status;
+
+ bl_start_cmd_timer(adapter, BL_CMD_TIMEOUT);
+
+ while (!adapter->blcmd_timer_expired) {
+ status = hif_ops->master_reg_read(adapter, SWBL_REGOUT,
+ ®out_val, 2);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: REGOUT read failed\n", __func__);
+ return status;
+ }
+ mdelay(1);
+ if ((regout_val >> 8) == REGOUT_VALID)
+ break;
+ }
+ if (adapter->blcmd_timer_expired) {
+ rsi_dbg(ERR_ZONE, "%s: REGOUT read timedout\n", __func__);
+ rsi_dbg(ERR_ZONE,
+ "%s: Soft boot loader not present\n", __func__);
+ return -ETIMEDOUT;
+ }
+ bl_stop_cmd_timer(adapter);
+
+ rsi_dbg(INFO_ZONE, "Received Board Version Number: %x\n",
+ (regout_val & 0xff));
+
+ status = hif_ops->master_reg_write(adapter, SWBL_REGOUT,
+ (REGOUT_INVALID | REGOUT_INVALID << 8),
+ 2);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "%s: REGOUT writing failed..\n", __func__);
+ return status;
+ }
+ mdelay(1);
+
+ status = bl_cmd(adapter, CONFIG_AUTO_READ_MODE, CMD_PASS,
+ "AUTO_READ_CMD");
+ if (status < 0)
+ return status;
+
+ adapter->flash_capacity = read_flash_capacity(adapter);
+ if (adapter->flash_capacity <= 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to read flash size from EEPROM\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ metadata_p = &metadata_flash_content[adapter->priv->coex_mode];
+
+ rsi_dbg(INIT_ZONE, "%s: Loading file %s\n", __func__, metadata_p->name);
+ adapter->fw_file_name = metadata_p->name;
+
+ status = request_firmware(&fw_entry, metadata_p->name, adapter->device);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to open file %s\n",
+ __func__, metadata_p->name);
+ return status;
+ }
+ flash_content = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
+ if (!flash_content) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to copy firmware\n", __func__);
+ status = -EIO;
+ goto fail;
+ }
+ content_size = fw_entry->size;
+ rsi_dbg(INFO_ZONE, "FW Length = %d bytes\n", content_size);
+
+ status = bl_write_header(adapter, flash_content, content_size);
+ if (status) {
+ rsi_dbg(ERR_ZONE,
+ "%s: RPS Image header loading failed\n",
+ __func__);
+ goto fail;
+ }
+
+ bl_start_cmd_timer(adapter, BL_CMD_TIMEOUT);
+ status = bl_write_cmd(adapter, CHECK_CRC, CMD_PASS, &tmp_regout_val);
+ if (status) {
+ bl_stop_cmd_timer(adapter);
+ rsi_dbg(ERR_ZONE,
+ "%s: CHECK_CRC Command writing failed..\n",
+ __func__);
+ if ((tmp_regout_val & 0xff) == CMD_FAIL) {
+ rsi_dbg(ERR_ZONE,
+ "CRC Fail.. Proceeding to Upgrade mode\n");
+ goto fw_upgrade;
+ }
+ }
+ bl_stop_cmd_timer(adapter);
+
+ status = bl_cmd(adapter, POLLING_MODE, CMD_PASS, "POLLING_MODE");
+ if (status)
+ goto fail;
+
+load_image_cmd:
+ status = bl_cmd(adapter, LOAD_HOSTED_FW, LOADING_INITIATED,
+ "LOAD_HOSTED_FW");
+ if (status)
+ goto fail;
+ rsi_dbg(INFO_ZONE, "Load Image command passed..\n");
+ goto success;
+
+fw_upgrade:
+ status = bl_cmd(adapter, BURN_HOSTED_FW, SEND_RPS_FILE, "FW_UPGRADE");
+ if (status)
+ goto fail;
+
+ rsi_dbg(INFO_ZONE, "Burn Command Pass.. Upgrading the firmware\n");
+
+ status = auto_fw_upgrade(adapter, flash_content, content_size);
+ if (status == 0) {
+ rsi_dbg(ERR_ZONE, "Firmware upgradation Done\n");
+ goto load_image_cmd;
+ }
+ rsi_dbg(ERR_ZONE, "Firmware upgrade failed\n");
+
+ status = bl_cmd(adapter, CONFIG_AUTO_READ_MODE, CMD_PASS,
+ "AUTO_READ_MODE");
+ if (status)
+ goto fail;
+
+success:
+ rsi_dbg(ERR_ZONE, "***** Firmware Loading successful *****\n");
+ kfree(flash_content);
+ release_firmware(fw_entry);
+ return 0;
+
+fail:
+ rsi_dbg(ERR_ZONE, "##### Firmware loading failed #####\n");
+ kfree(flash_content);
+ release_firmware(fw_entry);
+ return status;
+}
+
+int rsi_hal_device_init(struct rsi_hw *adapter)
+{
+ struct rsi_common *common = adapter->priv;
+
+ common->coex_mode = 1;
+ adapter->device_model = RSI_DEV_9113;
+
+ switch (adapter->device_model) {
+ case RSI_DEV_9113:
+ if (rsi_load_firmware(adapter)) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to load TA instructions\n",
+ __func__);
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rsi_hal_device_init);
+
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index b397e2c..2ef844a 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include "rsi_sdio.h"
#include "rsi_common.h"
+#include "rsi_hal.h"
/**
* rsi_sdio_set_cmd52_arg() - This function prepares cmd 52 read/write arg.
@@ -365,6 +366,7 @@ static int rsi_setblocklength(struct rsi_hw *adapter, u32 length)
status = sdio_set_block_size(dev->pfunction, length);
dev->pfunction->max_blksize = 256;
+ adapter->block_size = dev->pfunction->max_blksize;
rsi_dbg(INFO_ZONE,
"%s: Operational blk length is %d\n", __func__, length);
@@ -868,6 +870,7 @@ static int rsi_init_sdio_interface(struct rsi_hw *adapter,
static struct rsi_host_intf_ops sdio_host_intf_ops = {
.write_pkt = rsi_sdio_host_intf_write_pkt,
.read_pkt = rsi_sdio_host_intf_read_pkt,
+ .master_access_msword = rsi_sdio_master_access_msword,
.read_reg_multiple = rsi_sdio_read_register_multiple,
.write_reg_multiple = rsi_sdio_write_register_multiple,
.master_reg_read = rsi_sdio_master_reg_read,
@@ -906,13 +909,19 @@ static int rsi_probe(struct sdio_func *pfunction,
goto fail;
}
- if (rsi_sdio_device_init(adapter->priv)) {
+ if (rsi_hal_device_init(adapter)) {
rsi_dbg(ERR_ZONE, "%s: Failed in device init\n", __func__);
sdio_claim_host(pfunction);
sdio_disable_func(pfunction);
sdio_release_host(pfunction);
goto fail;
}
+ rsi_dbg(INFO_ZONE, "===> RSI Device Init Done <===\n");
+
+ if (rsi_sdio_master_access_msword(adapter, MISC_CFG_BASE_ADDR)) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to set ms word reg\n", __func__);
+ return -EIO;
+ }
sdio_claim_host(pfunction);
if (sdio_claim_irq(pfunction, rsi_handle_interrupt)) {
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index b10b145..72c7f3a 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -17,6 +17,7 @@
#include <linux/module.h>
#include "rsi_usb.h"
+#include "rsi_hal.h"
/**
* rsi_usb_card_write() - This function writes to the USB Card.
@@ -525,6 +526,7 @@ static int rsi_init_usb_interface(struct rsi_hw *adapter,
}
rsi_dev->rx_usb_urb[0]->transfer_buffer = adapter->priv->rx_data_pkt;
rsi_dev->tx_blk_size = 252;
+ adapter->block_size = rsi_dev->tx_blk_size;
/* Initializing function callbacks */
adapter->rx_urb_submit = rsi_rx_urb_submit;
@@ -583,6 +585,7 @@ static int rsi_probe(struct usb_interface *pfunction,
__func__);
return -ENOMEM;
}
+ adapter->rsi_host_intf = RSI_HOST_INTF_USB;
status = rsi_init_usb_interface(adapter, pfunction);
if (status) {
@@ -596,25 +599,20 @@ static int rsi_probe(struct usb_interface *pfunction,
dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
status = rsi_usb_reg_read(dev->usbdev, FW_STATUS_REG, &fw_status, 2);
- if (status)
+ if (status < 0)
goto err1;
else
fw_status &= 1;
if (!fw_status) {
- status = rsi_usb_device_init(adapter->priv);
+ rsi_dbg(INIT_ZONE, "Loading firmware...\n");
+ status = rsi_hal_device_init(adapter);
if (status) {
rsi_dbg(ERR_ZONE, "%s: Failed in device init\n",
__func__);
goto err1;
}
-
- status = rsi_usb_reg_write(dev->usbdev,
- USB_INTERNAL_REG_1,
- RSI_USB_READY_MAGIC_NUM, 1);
- if (status)
- goto err1;
- rsi_dbg(INIT_ZONE, "%s: Performed device init\n", __func__);
+ rsi_dbg(INIT_ZONE, "%s: Device Init Done\n", __func__);
}
status = rsi_rx_urb_submit(adapter);
diff --git a/drivers/net/wireless/rsi/rsi_hal.h b/drivers/net/wireless/rsi/rsi_hal.h
new file mode 100644
index 0000000..b95200d
--- /dev/null
+++ b/drivers/net/wireless/rsi/rsi_hal.h
@@ -0,0 +1,81 @@
+/**
+ * Copyright (c) 2017 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __RSI_HAL_H__
+#define __RSI_HAL_H__
+
+#define FLASH_WRITE_CHUNK_SIZE (4 * 1024)
+#define FLASH_SECTOR_SIZE (4 * 1024)
+
+#define FLASH_SIZE_ADDR 0x04000016
+#define PING_BUFFER_ADDRESS 0x19000
+#define PONG_BUFFER_ADDRESS 0x1a000
+#define SWBL_REGIN 0x41050034
+#define SWBL_REGOUT 0x4105003c
+#define PING_WRITE 0x1
+#define PONG_WRITE 0x2
+
+#define BL_CMD_TIMEOUT 2000
+#define BL_BURN_TIMEOUT (50 * 1000)
+
+#define REGIN_VALID 0xA
+#define REGIN_INPUT 0xA0
+#define REGOUT_VALID 0xAB
+#define REGOUT_INVALID (~0xAB)
+#define CMD_PASS 0xAA
+#define CMD_FAIL 0xCC
+
+#define LOAD_HOSTED_FW 'A'
+#define BURN_HOSTED_FW 'B'
+#define PING_VALID 'I'
+#define PONG_VALID 'O'
+#define PING_AVAIL 'I'
+#define PONG_AVAIL 'O'
+#define EOF_REACHED 'E'
+#define CHECK_CRC 'K'
+#define POLLING_MODE 'P'
+#define CONFIG_AUTO_READ_MODE 'R'
+#define JUMP_TO_ZERO_PC 'J'
+#define FW_LOADING_SUCCESSFUL 'S'
+#define LOADING_INITIATED '1'
+
+/* Boot loader commands */
+#define SEND_RPS_FILE '2'
+
+#define FW_IMAGE_MIN_ADDRESS (68 * 1024)
+#define MAX_FLASH_FILE_SIZE (400 * 1024) //400K
+#define FLASH_START_ADDRESS 16
+
+#define COMMON_HAL_CARD_READY_IND 0x0
+
+#define COMMAN_HAL_WAIT_FOR_CARD_READY 1
+
+struct bl_header {
+ __le32 flags;
+ __le32 image_no;
+ __le32 check_sum;
+ __le32 flash_start_address;
+ __le32 flash_len;
+} __packed;
+
+struct ta_metadata {
+ char *name;
+ unsigned int address;
+};
+
+int rsi_hal_device_init(struct rsi_hw *adapter);
+
+#endif
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index 2ac5bcf..ea4fc22 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -82,6 +82,8 @@ extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...);
((_q) == VI_Q) ? IEEE80211_AC_VI : \
IEEE80211_AC_VO)
+#define RSI_DEV_9113 1
+
struct version_info {
u16 major;
u16 minor;
@@ -204,6 +206,7 @@ struct rsi_common {
struct cqm_info cqm_info;
bool hw_data_qs_blocked;
+ u8 coex_mode;
int tx_power;
u8 ant_in_use;
@@ -216,6 +219,7 @@ enum host_intf {
struct rsi_hw {
struct rsi_common *priv;
+ u8 device_model;
struct ieee80211_hw *hw;
struct ieee80211_vif *vifs[RSI_MAX_VIFS];
struct ieee80211_tx_queue_params edca_params[NUM_EDCA_QUEUES];
@@ -225,10 +229,15 @@ struct rsi_hw {
u8 sc_nvifs;
enum host_intf rsi_host_intf;
+ u16 block_size;
#ifdef CONFIG_RSI_DEBUGFS
struct rsi_debugfs *dfsentry;
u8 num_debugfs_entries;
#endif
+ char *fw_file_name;
+ struct timer_list bl_cmd_timer;
+ bool blcmd_timer_expired;
+ u32 flash_capacity;
u8 dfs_region;
void *rsi_dev;
struct rsi_host_intf_ops *host_intf_ops;
@@ -240,6 +249,7 @@ struct rsi_hw {
struct rsi_host_intf_ops {
int (*read_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
int (*write_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
+ int (*master_access_msword)(struct rsi_hw *adapter, u16 ms_word);
int (*read_reg_multiple)(struct rsi_hw *adapter, u32 addr,
u8 *data, u16 count);
int (*write_reg_multiple)(struct rsi_hw *adapter, u32 addr,
--
2.7.4
amit karwar <[email protected]> wrote:
> From: Prameela Rani Garnepudi <[email protected]>
>
> The file rsi_91x_hal.c is going to contain device specific code i.e new
> firmware loading method for RS9113 chipset. As the file rsi_91x_pkt.c
> contains code to prepare device specific descriptors for transmit packet,
> this file is renamed to rsi_91x_hal.c which is more relevant as per it's
> functionality.
>
> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
> Signed-off-by: Amitkumar Karwar <[email protected]>
11 patches applied to wireless-drivers-next.git, thanks.
d7af6bb7e527 rsi: Rename file rsi_91x_pkt.c to rsi_91x_hal.c
897d341dee4f rsi: Changes to sdio reads and writes
7bdead7ae944 rsi: define RSI_USB_BUF_SIZE macro
2fbbe5179ebe rsi: Changes in USB read and write operations
4b1fc881173e rsi: use macros in USB specific code
ea3336ac0094 rsi: Handle usb multi-byte write failure case properly
88fa51e1b33c rsi: Add usb multi-byte read operation
a2ce952c8e09 rsi: Add host interface operations as separate structure.
b97e9b94ad75 rsi: Add new host interface operations
b78e91bcfb33 rsi: Add new firmware loading method
5578b1ffdc30 rsi: Remove old firmware loading method
--
https://patchwork.kernel.org/patch/9728767/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
From: Prameela Rani Garnepudi <[email protected]>
USB multibyte read will be used in the new firmware loading method
for RS9113 chipset.
Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
v3: Use RSI_USB_BUF_SIZE macro for 4096
---
drivers/net/wireless/rsi/rsi_91x_usb.c | 40 ++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index a900a72..31f96f0 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -276,6 +276,46 @@ static int rsi_rx_urb_submit(struct rsi_hw *adapter)
return status;
}
+static int rsi_usb_read_register_multiple(struct rsi_hw *adapter, u32 addr,
+ u8 *data, u16 count)
+{
+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
+ u8 *buf;
+ u16 transfer;
+ int status;
+
+ if (!addr)
+ return -EINVAL;
+
+ buf = kzalloc(RSI_USB_BUF_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ while (count) {
+ transfer = min_t(u16, count, RSI_USB_BUF_SIZE);
+ status = usb_control_msg(dev->usbdev,
+ usb_rcvctrlpipe(dev->usbdev, 0),
+ USB_VENDOR_REGISTER_READ,
+ RSI_USB_REQ_IN,
+ ((addr & 0xffff0000) >> 16),
+ (addr & 0xffff), (void *)buf,
+ transfer, USB_CTRL_GET_TIMEOUT);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "Reg read failed with error code :%d\n",
+ status);
+ kfree(buf);
+ return status;
+ }
+ memcpy(data, buf, transfer);
+ count -= transfer;
+ data += transfer;
+ addr += transfer;
+ }
+ kfree(buf);
+ return 0;
+}
+
/**
* rsi_usb_write_register_multiple() - This function writes multiple bytes of
* information to multiple registers.
--
2.7.4
Amitkumar Karwar <[email protected]> writes:
> From: Prameela Rani Garnepudi <[email protected]>
>
> The older firmware loading method has been deprecated and not in use
> for any chipets. New method is introduced which works based on soft
> boot loader. In this method, complete RAM image and FLASH image are
> present in the flash. Before loading the functional firmware, host
> issues boot loader commands to verify whether firmware to load is
> different from the current functional firmware. If not, firmware
> upgrade progresses and boot loader will switch to the new functional
> firmware.
>
> "rs9113_wlan_qspi.rps" is the firmware filename used in this patch.
I don't know if you saw the discussion with the wil6210 firmware, but
the linux-firmware maintainers prefer to have a subdirectory for
firmware files. I'm planning to apply this series now, but you can send
a followup patch ASAP which changes the rsi driver to use a subdirectory
for the firmware files?
Normally these kind of breaks in user space interface are not allowed,
and instead the requirement is that the driver has a transition period
from the old firmware interface to the new one. But I'm making an
exception here as, to my knowledge, the upstream rsi driver is not that
widely used and I want to get the driver development going on again.
--
Kalle Valo
From: Prameela Rani Garnepudi <[email protected]>
The file rsi_91x_hal.c is going to contain device specific code i.e new
firmware loading method for RS9113 chipset. As the file rsi_91x_pkt.c
contains code to prepare device specific descriptors for transmit packet,
this file is renamed to rsi_91x_hal.c which is more relevant as per it's
functionality.
Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
v3: Same as earlier
---
drivers/net/wireless/rsi/Makefile | 2 +-
drivers/net/wireless/rsi/{rsi_91x_pkt.c => rsi_91x_hal.c} | 0
2 files changed, 1 insertion(+), 1 deletion(-)
rename drivers/net/wireless/rsi/{rsi_91x_pkt.c => rsi_91x_hal.c} (100%)
diff --git a/drivers/net/wireless/rsi/Makefile b/drivers/net/wireless/rsi/Makefile
index 25828b6..a475c81 100644
--- a/drivers/net/wireless/rsi/Makefile
+++ b/drivers/net/wireless/rsi/Makefile
@@ -2,7 +2,7 @@ rsi_91x-y += rsi_91x_main.o
rsi_91x-y += rsi_91x_core.o
rsi_91x-y += rsi_91x_mac80211.o
rsi_91x-y += rsi_91x_mgmt.o
-rsi_91x-y += rsi_91x_pkt.o
+rsi_91x-y += rsi_91x_hal.o
rsi_91x-$(CONFIG_RSI_DEBUGFS) += rsi_91x_debugfs.o
rsi_usb-y += rsi_91x_usb.o rsi_91x_usb_ops.o
diff --git a/drivers/net/wireless/rsi/rsi_91x_pkt.c b/drivers/net/wireless/rsi/rsi_91x_hal.c
similarity index 100%
rename from drivers/net/wireless/rsi/rsi_91x_pkt.c
rename to drivers/net/wireless/rsi/rsi_91x_hal.c
--
2.7.4
From: Prameela Rani Garnepudi <[email protected]>
The older firmware loading method is not usable by any Redpine chipset.
Hence removing that part of the code. Older firmware image with
rsi_91x.fw name is deprecated
Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
v3: Included the name of older firmware which won't be used anymore in
commit description(Kalle Valo)
---
drivers/net/wireless/rsi/rsi_91x_sdio_ops.c | 187 ----------------------------
drivers/net/wireless/rsi/rsi_91x_usb.c | 6 +-
drivers/net/wireless/rsi/rsi_91x_usb_ops.c | 126 -------------------
drivers/net/wireless/rsi/rsi_common.h | 3 +-
drivers/net/wireless/rsi/rsi_sdio.h | 1 -
drivers/net/wireless/rsi/rsi_usb.h | 3 -
6 files changed, 3 insertions(+), 323 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
index 225042f..df2a63b 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
@@ -60,171 +60,6 @@ int rsi_sdio_master_access_msword(struct rsi_hw *adapter, u16 ms_word)
}
/**
- * rsi_copy_to_card() - This function includes the actual funtionality of
- * copying the TA firmware to the card.Basically this
- * function includes opening the TA file,reading the
- * TA file and writing their values in blocks of data.
- * @common: Pointer to the driver private structure.
- * @fw: Pointer to the firmware value to be written.
- * @len: length of firmware file.
- * @num_blocks: Number of blocks to be written to the card.
- *
- * Return: 0 on success and -1 on failure.
- */
-static int rsi_copy_to_card(struct rsi_common *common,
- const u8 *fw,
- u32 len,
- u16 num_blocks)
-{
- struct rsi_hw *adapter = common->priv;
- struct rsi_91x_sdiodev *dev =
- (struct rsi_91x_sdiodev *)adapter->rsi_dev;
- u32 indx, ii;
- u16 block_size = dev->tx_blk_size;
- u32 lsb_address;
- __le32 data[] = { TA_HOLD_THREAD_VALUE, TA_SOFT_RST_CLR,
- TA_PC_ZERO, TA_RELEASE_THREAD_VALUE };
- u32 address[] = { TA_HOLD_THREAD_REG, TA_SOFT_RESET_REG,
- TA_TH0_PC_REG, TA_RELEASE_THREAD_REG };
- u32 base_address;
- u16 msb_address;
-
- base_address = TA_LOAD_ADDRESS;
- msb_address = base_address >> 16;
-
- for (indx = 0, ii = 0; ii < num_blocks; ii++, indx += block_size) {
- lsb_address = ((u16) base_address | RSI_SD_REQUEST_MASTER);
- if (rsi_sdio_write_register_multiple(adapter,
- lsb_address,
- (u8 *)(fw + indx),
- block_size)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to load %s blk\n", __func__,
- FIRMWARE_RSI9113);
- return -1;
- }
- rsi_dbg(INIT_ZONE, "%s: loading block: %d\n", __func__, ii);
- base_address += block_size;
- if ((base_address >> 16) != msb_address) {
- msb_address += 1;
- if (rsi_sdio_master_access_msword(adapter,
- msb_address)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to set ms word reg\n",
- __func__);
- return -1;
- }
- }
- }
-
- if (len % block_size) {
- lsb_address = ((u16) base_address | RSI_SD_REQUEST_MASTER);
- if (rsi_sdio_write_register_multiple(adapter,
- lsb_address,
- (u8 *)(fw + indx),
- len % block_size)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to load f/w\n", __func__);
- return -1;
- }
- }
- rsi_dbg(INIT_ZONE,
- "%s: Succesfully loaded TA instructions\n", __func__);
-
- if (rsi_sdio_master_access_msword(adapter, TA_BASE_ADDR)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to set ms word to common reg\n",
- __func__);
- return -1;
- }
-
- for (ii = 0; ii < ARRAY_SIZE(data); ii++) {
- /* Bringing TA out of reset */
- if (rsi_sdio_write_register_multiple(adapter,
- (address[ii] |
- RSI_SD_REQUEST_MASTER),
- (u8 *)&data[ii],
- 4)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to hold TA threads\n", __func__);
- return -1;
- }
- }
-
- rsi_dbg(INIT_ZONE, "%s: loaded firmware\n", __func__);
- return 0;
-}
-
-/**
- * rsi_load_ta_instructions() - This function includes the actual funtionality
- * of loading the TA firmware.This function also
- * includes opening the TA file,reading the TA
- * file and writing their value in blocks of data.
- * @common: Pointer to the driver private structure.
- *
- * Return: status: 0 on success, -1 on failure.
- */
-static int rsi_load_ta_instructions(struct rsi_common *common)
-{
- struct rsi_hw *adapter = common->priv;
- struct rsi_91x_sdiodev *dev =
- (struct rsi_91x_sdiodev *)adapter->rsi_dev;
- u32 len;
- u16 num_blocks;
- const u8 *fw;
- const struct firmware *fw_entry = NULL;
- u16 block_size = dev->tx_blk_size;
- int status = 0;
- u32 base_address;
- u16 msb_address;
-
- if (rsi_sdio_master_access_msword(adapter, TA_BASE_ADDR)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to set ms word to common reg\n",
- __func__);
- return -1;
- }
- base_address = TA_LOAD_ADDRESS;
- msb_address = (base_address >> 16);
-
- if (rsi_sdio_master_access_msword(adapter, msb_address)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to set ms word reg\n", __func__);
- return -1;
- }
-
- status = request_firmware(&fw_entry, FIRMWARE_RSI9113, adapter->device);
- if (status < 0) {
- rsi_dbg(ERR_ZONE, "%s Firmware file %s not found\n",
- __func__, FIRMWARE_RSI9113);
- return status;
- }
-
- /* Copy firmware into DMA-accessible memory */
- fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
- if (!fw) {
- status = -ENOMEM;
- goto out;
- }
- len = fw_entry->size;
-
- if (len % 4)
- len += (4 - (len % 4));
-
- num_blocks = (len / block_size);
-
- rsi_dbg(INIT_ZONE, "%s: Instruction size:%d\n", __func__, len);
- rsi_dbg(INIT_ZONE, "%s: num blocks: %d\n", __func__, num_blocks);
-
- status = rsi_copy_to_card(common, fw, len, num_blocks);
- kfree(fw);
-
-out:
- release_firmware(fw_entry);
- return status;
-}
-
-/**
* rsi_process_pkt() - This Function reads rx_blocks register and figures out
* the size of the rx pkt.
* @common: Pointer to the driver private structure.
@@ -471,28 +306,6 @@ void rsi_interrupt_handler(struct rsi_hw *adapter)
}
/**
- * rsi_device_init() - This Function Initializes The HAL.
- * @common: Pointer to the driver private structure.
- *
- * Return: 0 on success, -1 on failure.
- */
-int rsi_sdio_device_init(struct rsi_common *common)
-{
- if (rsi_load_ta_instructions(common))
- return -1;
-
- if (rsi_sdio_master_access_msword(common->priv, MISC_CFG_BASE_ADDR)) {
- rsi_dbg(ERR_ZONE, "%s: Unable to set ms word reg\n",
- __func__);
- return -1;
- }
- rsi_dbg(INIT_ZONE,
- "%s: Setting ms word to 0x41050000\n", __func__);
-
- return 0;
-}
-
-/**
* rsi_sdio_read_buffer_status_register() - This function is used to the read
* buffer status register and set
* relevant fields in
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index 72c7f3a..f5de693 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -327,10 +327,8 @@ static int rsi_usb_read_register_multiple(struct rsi_hw *adapter, u32 addr,
*
* Return: status: 0 on success, a negative error code on failure.
*/
-int rsi_usb_write_register_multiple(struct rsi_hw *adapter,
- u32 addr,
- u8 *data,
- u16 count)
+static int rsi_usb_write_register_multiple(struct rsi_hw *adapter, u32 addr,
+ u8 *data, u16 count)
{
struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
u8 *buf;
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb_ops.c b/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
index 1c3e654..d3e0a07 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
@@ -19,67 +19,6 @@
#include "rsi_usb.h"
/**
- * rsi_copy_to_card() - This function includes the actual funtionality of
- * copying the TA firmware to the card.Basically this
- * function includes opening the TA file,reading the TA
- * file and writing their values in blocks of data.
- * @common: Pointer to the driver private structure.
- * @fw: Pointer to the firmware value to be written.
- * @len: length of firmware file.
- * @num_blocks: Number of blocks to be written to the card.
- *
- * Return: 0 on success and -1 on failure.
- */
-static int rsi_copy_to_card(struct rsi_common *common,
- const u8 *fw,
- u32 len,
- u16 num_blocks)
-{
- struct rsi_hw *adapter = common->priv;
- struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
- u32 indx, ii;
- u16 block_size = dev->tx_blk_size;
- u32 lsb_address;
- u32 base_address;
-
- base_address = TA_LOAD_ADDRESS;
-
- for (indx = 0, ii = 0; ii < num_blocks; ii++, indx += block_size) {
- lsb_address = base_address;
- if (rsi_usb_write_register_multiple(adapter,
- lsb_address,
- (u8 *)(fw + indx),
- block_size)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to load %s blk\n", __func__,
- FIRMWARE_RSI9113);
- return -EIO;
- }
- rsi_dbg(INIT_ZONE, "%s: loading block: %d\n", __func__, ii);
- base_address += block_size;
- }
-
- if (len % block_size) {
- lsb_address = base_address;
- if (rsi_usb_write_register_multiple(adapter,
- lsb_address,
- (u8 *)(fw + indx),
- len % block_size)) {
- rsi_dbg(ERR_ZONE,
- "%s: Unable to load %s blk\n", __func__,
- FIRMWARE_RSI9113);
- return -EIO;
- }
- }
- rsi_dbg(INIT_ZONE,
- "%s: Succesfully loaded %s instructions\n", __func__,
- FIRMWARE_RSI9113);
-
- rsi_dbg(INIT_ZONE, "%s: loaded firmware\n", __func__);
- return 0;
-}
-
-/**
* rsi_usb_rx_thread() - This is a kernel thread to receive the packets from
* the USB device.
* @common: Pointer to the driver private structure.
@@ -119,68 +58,3 @@ void rsi_usb_rx_thread(struct rsi_common *common)
complete_and_exit(&dev->rx_thread.completion, 0);
}
-
-/**
- * rsi_load_ta_instructions() - This function includes the actual funtionality
- * of loading the TA firmware.This function also
- * includes opening the TA file,reading the TA
- * file and writing their value in blocks of data.
- * @common: Pointer to the driver private structure.
- *
- * Return: status: 0 on success, -1 on failure.
- */
-static int rsi_load_ta_instructions(struct rsi_common *common)
-{
- struct rsi_hw *adapter = common->priv;
- struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
- const struct firmware *fw_entry = NULL;
- u16 block_size = dev->tx_blk_size;
- const u8 *fw;
- u16 num_blocks;
- u32 len;
- int status = 0;
-
- status = request_firmware(&fw_entry, FIRMWARE_RSI9113, adapter->device);
- if (status < 0) {
- rsi_dbg(ERR_ZONE, "%s Firmware file %s not found\n",
- __func__, FIRMWARE_RSI9113);
- return status;
- }
-
- /* Copy firmware into DMA-accessible memory */
- fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
- if (!fw) {
- status = -ENOMEM;
- goto out;
- }
- len = fw_entry->size;
-
- if (len % 4)
- len += (4 - (len % 4));
-
- num_blocks = (len / block_size);
-
- rsi_dbg(INIT_ZONE, "%s: Instruction size:%d\n", __func__, len);
- rsi_dbg(INIT_ZONE, "%s: num blocks: %d\n", __func__, num_blocks);
-
- status = rsi_copy_to_card(common, fw, len, num_blocks);
- kfree(fw);
-
-out:
- release_firmware(fw_entry);
- return status;
-}
-
-/**
- * rsi_device_init() - This Function Initializes The HAL.
- * @common: Pointer to the driver private structure.
- *
- * Return: 0 on success, -1 on failure.
- */
-int rsi_usb_device_init(struct rsi_common *common)
-{
- if (rsi_load_ta_instructions(common))
- return -EIO;
-
- return 0;
- }
diff --git a/drivers/net/wireless/rsi/rsi_common.h b/drivers/net/wireless/rsi/rsi_common.h
index d3fbe33..4434969 100644
--- a/drivers/net/wireless/rsi/rsi_common.h
+++ b/drivers/net/wireless/rsi/rsi_common.h
@@ -20,8 +20,7 @@
#include <linux/kthread.h>
#define EVENT_WAIT_FOREVER 0
-#define TA_LOAD_ADDRESS 0x00
-#define FIRMWARE_RSI9113 "rsi_91x.fw"
+#define FIRMWARE_RSI9113 "rs9113_wlan_qspi.rps"
#define QUEUE_NOT_FULL 1
#define QUEUE_FULL 0
diff --git a/drivers/net/wireless/rsi/rsi_sdio.h b/drivers/net/wireless/rsi/rsi_sdio.h
index 7ae6d51..9fb73f6 100644
--- a/drivers/net/wireless/rsi/rsi_sdio.h
+++ b/drivers/net/wireless/rsi/rsi_sdio.h
@@ -116,7 +116,6 @@ struct rsi_91x_sdiodev {
void rsi_interrupt_handler(struct rsi_hw *adapter);
int rsi_init_sdio_slave_regs(struct rsi_hw *adapter);
-int rsi_sdio_device_init(struct rsi_common *common);
int rsi_sdio_read_register(struct rsi_hw *adapter, u32 addr, u8 *data);
int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter, u8 *pkt, u32 length);
int rsi_sdio_write_register(struct rsi_hw *adapter, u8 function,
diff --git a/drivers/net/wireless/rsi/rsi_usb.h b/drivers/net/wireless/rsi/rsi_usb.h
index d1e01bc..59513ac 100644
--- a/drivers/net/wireless/rsi/rsi_usb.h
+++ b/drivers/net/wireless/rsi/rsi_usb.h
@@ -63,8 +63,5 @@ static inline int rsi_usb_event_timeout(struct rsi_hw *adapter)
return EVENT_WAIT_FOREVER;
}
-int rsi_usb_device_init(struct rsi_common *common);
-int rsi_usb_write_register_multiple(struct rsi_hw *adapter, u32 addr,
- u8 *data, u16 count);
void rsi_usb_rx_thread(struct rsi_common *common);
#endif
--
2.7.4
From: Prameela Rani Garnepudi <[email protected]>
For USB vendor read and write operations new macros added to avoid
redundant usage of long or'ed macros. Also for timeouts standard USB
macros are used.
Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
v3: Same as v2 04/11
---
drivers/net/wireless/rsi/rsi_91x_usb.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index 5f6c700..9e1359a 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -141,6 +141,9 @@ static int rsi_find_bulk_in_and_out_endpoints(struct usb_interface *interface,
return 0;
}
+#define RSI_USB_REQ_OUT (USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE)
+#define RSI_USB_REQ_IN (USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE)
+
/* rsi_usb_reg_read() - This function reads data from given register address.
* @usbdev: Pointer to the usb_device structure.
* @reg: Address of the register to be read.
@@ -164,11 +167,11 @@ static int rsi_usb_reg_read(struct usb_device *usbdev,
status = usb_control_msg(usbdev,
usb_rcvctrlpipe(usbdev, 0),
USB_VENDOR_REGISTER_READ,
- USB_TYPE_VENDOR,
+ RSI_USB_REQ_IN,
((reg & 0xffff0000) >> 16), (reg & 0xffff),
(void *)buf,
len,
- HZ * 5);
+ USB_CTRL_GET_TIMEOUT);
*value = (buf[0] | (buf[1] << 8));
if (status < 0) {
@@ -211,12 +214,12 @@ static int rsi_usb_reg_write(struct usb_device *usbdev,
status = usb_control_msg(usbdev,
usb_sndctrlpipe(usbdev, 0),
USB_VENDOR_REGISTER_WRITE,
- USB_TYPE_VENDOR,
+ RSI_USB_REQ_OUT,
((reg & 0xffff0000) >> 16),
(reg & 0xffff),
(void *)usb_reg_buf,
len,
- HZ * 5);
+ USB_CTRL_SET_TIMEOUT);
if (status < 0) {
rsi_dbg(ERR_ZONE,
"%s: Reg write failed with error code :%d\n",
@@ -303,12 +306,12 @@ int rsi_usb_write_register_multiple(struct rsi_hw *adapter,
status = usb_control_msg(dev->usbdev,
usb_sndctrlpipe(dev->usbdev, 0),
USB_VENDOR_REGISTER_WRITE,
- USB_TYPE_VENDOR,
+ RSI_USB_REQ_OUT,
((addr & 0xffff0000) >> 16),
(addr & 0xffff),
(void *)buf,
transfer,
- HZ * 5);
+ USB_CTRL_SET_TIMEOUT);
if (status < 0) {
rsi_dbg(ERR_ZONE,
"Reg write failed with error code :%d\n",
--
2.7.4
From: Prameela Rani Garnepudi <[email protected]>
USB read and write registers maximum size is limited 2^16. More than
this size is not used in the driver.
Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
v3: Same as v2 03/11
---
drivers/net/wireless/rsi/rsi_91x_usb.c | 6 +++---
drivers/net/wireless/rsi/rsi_91x_usb_ops.c | 9 +++++----
drivers/net/wireless/rsi/rsi_usb.h | 2 +-
3 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index be8487c..5f6c700 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -286,11 +286,11 @@ static int rsi_rx_urb_submit(struct rsi_hw *adapter)
int rsi_usb_write_register_multiple(struct rsi_hw *adapter,
u32 addr,
u8 *data,
- u32 count)
+ u16 count)
{
struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
u8 *buf;
- u8 transfer;
+ u16 transfer;
int status = 0;
buf = kzalloc(RSI_USB_BUF_SIZE, GFP_KERNEL);
@@ -298,7 +298,7 @@ int rsi_usb_write_register_multiple(struct rsi_hw *adapter,
return -ENOMEM;
while (count) {
- transfer = (u8)(min_t(u32, count, RSI_USB_BUF_SIZE));
+ transfer = min_t(u16, count, RSI_USB_BUF_SIZE);
memcpy(buf, data, transfer);
status = usb_control_msg(dev->usbdev,
usb_sndctrlpipe(dev->usbdev, 0),
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb_ops.c b/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
index de49008..1c3e654 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
@@ -33,12 +33,12 @@
static int rsi_copy_to_card(struct rsi_common *common,
const u8 *fw,
u32 len,
- u32 num_blocks)
+ u16 num_blocks)
{
struct rsi_hw *adapter = common->priv;
struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
u32 indx, ii;
- u32 block_size = dev->tx_blk_size;
+ u16 block_size = dev->tx_blk_size;
u32 lsb_address;
u32 base_address;
@@ -134,9 +134,10 @@ static int rsi_load_ta_instructions(struct rsi_common *common)
struct rsi_hw *adapter = common->priv;
struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
const struct firmware *fw_entry = NULL;
- u32 block_size = dev->tx_blk_size;
+ u16 block_size = dev->tx_blk_size;
const u8 *fw;
- u32 num_blocks, len;
+ u16 num_blocks;
+ u32 len;
int status = 0;
status = request_firmware(&fw_entry, FIRMWARE_RSI9113, adapter->device);
diff --git a/drivers/net/wireless/rsi/rsi_usb.h b/drivers/net/wireless/rsi/rsi_usb.h
index 48c9211..d1e01bc 100644
--- a/drivers/net/wireless/rsi/rsi_usb.h
+++ b/drivers/net/wireless/rsi/rsi_usb.h
@@ -65,6 +65,6 @@ static inline int rsi_usb_event_timeout(struct rsi_hw *adapter)
int rsi_usb_device_init(struct rsi_common *common);
int rsi_usb_write_register_multiple(struct rsi_hw *adapter, u32 addr,
- u8 *data, u32 count);
+ u8 *data, u16 count);
void rsi_usb_rx_thread(struct rsi_common *common);
#endif
--
2.7.4
On Wed, May 24, 2017 at 1:57 PM, Kalle Valo <[email protected]> wrote:
> Amitkumar Karwar <[email protected]> writes:
>
>> From: Prameela Rani Garnepudi <[email protected]>
>>
>> The older firmware loading method has been deprecated and not in use
>> for any chipets. New method is introduced which works based on soft
>> boot loader. In this method, complete RAM image and FLASH image are
>> present in the flash. Before loading the functional firmware, host
>> issues boot loader commands to verify whether firmware to load is
>> different from the current functional firmware. If not, firmware
>> upgrade progresses and boot loader will switch to the new functional
>> firmware.
>>
>> "rs9113_wlan_qspi.rps" is the firmware filename used in this patch.
>
> I don't know if you saw the discussion with the wil6210 firmware, but
> the linux-firmware maintainers prefer to have a subdirectory for
> firmware files. I'm planning to apply this series now, but you can send
> a followup patch ASAP which changes the rsi driver to use a subdirectory
> for the firmware files?
I have just sent a follow up patch.
> Normally these kind of breaks in user space interface are not allowed,
> and instead the requirement is that the driver has a transition period
> from the old firmware interface to the new one. But I'm making an
> exception here as, to my knowledge, the upstream rsi driver is not that
> widely used and I want to get the driver development going on again.
>
Right. Driver is not currently much used.
Thanks for accepting the changes.
Regards,
Amitkumar Karwar
From: Prameela Rani Garnepudi <[email protected]>
Host interface opearation master_reg_read, master_reg_write and
load_data_master_write are added. These functions are needed for the
new firmware loading method. As part of this, the function
master_access_msword is moved from rsi_91x_sdio_ops.c to rsi_91x_sdio.c.
Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
v3: Same as earlier
---
drivers/net/wireless/rsi/rsi_91x_sdio.c | 179 ++++++++++++++++++++++++++++
drivers/net/wireless/rsi/rsi_91x_sdio_ops.c | 3 +-
drivers/net/wireless/rsi/rsi_91x_usb.c | 65 ++++++++++
drivers/net/wireless/rsi/rsi_main.h | 8 ++
drivers/net/wireless/rsi/rsi_sdio.h | 1 +
5 files changed, 254 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index bdbec8b..b397e2c 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -552,6 +552,182 @@ int rsi_sdio_write_register_multiple(struct rsi_hw *adapter,
return status;
}
+static int rsi_sdio_load_data_master_write(struct rsi_hw *adapter,
+ u32 base_address,
+ u32 instructions_sz,
+ u16 block_size,
+ u8 *ta_firmware)
+{
+ u32 num_blocks, offset, i;
+ u16 msb_address, lsb_address;
+ u8 temp_buf[block_size];
+ int status;
+
+ num_blocks = instructions_sz / block_size;
+ msb_address = base_address >> 16;
+
+ rsi_dbg(INFO_ZONE, "ins_size: %d, num_blocks: %d\n",
+ instructions_sz, num_blocks);
+
+ /* Loading DM ms word in the sdio slave */
+ status = rsi_sdio_master_access_msword(adapter, msb_address);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to set ms word reg\n", __func__);
+ return status;
+ }
+
+ for (offset = 0, i = 0; i < num_blocks; i++, offset += block_size) {
+ memset(temp_buf, 0, block_size);
+ memcpy(temp_buf, ta_firmware + offset, block_size);
+ lsb_address = (u16)base_address;
+ status = rsi_sdio_write_register_multiple
+ (adapter,
+ lsb_address | RSI_SD_REQUEST_MASTER,
+ temp_buf, block_size);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "%s: failed to write\n", __func__);
+ return status;
+ }
+ rsi_dbg(INFO_ZONE, "%s: loading block: %d\n", __func__, i);
+ base_address += block_size;
+
+ if ((base_address >> 16) != msb_address) {
+ msb_address += 1;
+
+ /* Loading DM ms word in the sdio slave */
+ status = rsi_sdio_master_access_msword(adapter,
+ msb_address);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to set ms word reg\n",
+ __func__);
+ return status;
+ }
+ }
+ }
+
+ if (instructions_sz % block_size) {
+ memset(temp_buf, 0, block_size);
+ memcpy(temp_buf, ta_firmware + offset,
+ instructions_sz % block_size);
+ lsb_address = (u16)base_address;
+ status = rsi_sdio_write_register_multiple
+ (adapter,
+ lsb_address | RSI_SD_REQUEST_MASTER,
+ temp_buf,
+ instructions_sz % block_size);
+ if (status < 0)
+ return status;
+ rsi_dbg(INFO_ZONE,
+ "Written Last Block in Address 0x%x Successfully\n",
+ offset | RSI_SD_REQUEST_MASTER);
+ }
+ return 0;
+}
+
+#define FLASH_SIZE_ADDR 0x04000016
+static int rsi_sdio_master_reg_read(struct rsi_hw *adapter, u32 addr,
+ u32 *read_buf, u16 size)
+{
+ u32 addr_on_bus, *data;
+ u32 align[2] = {};
+ u16 ms_addr;
+ int status;
+
+ data = PTR_ALIGN(&align[0], 8);
+
+ ms_addr = (addr >> 16);
+ status = rsi_sdio_master_access_msword(adapter, ms_addr);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to set ms word to common reg\n",
+ __func__);
+ return status;
+ }
+ addr &= 0xFFFF;
+
+ addr_on_bus = (addr & 0xFF000000);
+ if ((addr_on_bus == (FLASH_SIZE_ADDR & 0xFF000000)) ||
+ (addr_on_bus == 0x0))
+ addr_on_bus = (addr & ~(0x3));
+ else
+ addr_on_bus = addr;
+
+ /* Bring TA out of reset */
+ status = rsi_sdio_read_register_multiple
+ (adapter,
+ (addr_on_bus | RSI_SD_REQUEST_MASTER),
+ (u8 *)data, 4);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE, "%s: AHB register read failed\n", __func__);
+ return status;
+ }
+ if (size == 2) {
+ if ((addr & 0x3) == 0)
+ *read_buf = *data;
+ else
+ *read_buf = (*data >> 16);
+ *read_buf = (*read_buf & 0xFFFF);
+ } else if (size == 1) {
+ if ((addr & 0x3) == 0)
+ *read_buf = *data;
+ else if ((addr & 0x3) == 1)
+ *read_buf = (*data >> 8);
+ else if ((addr & 0x3) == 2)
+ *read_buf = (*data >> 16);
+ else
+ *read_buf = (*data >> 24);
+ *read_buf = (*read_buf & 0xFF);
+ } else {
+ *read_buf = *data;
+ }
+
+ return 0;
+}
+
+static int rsi_sdio_master_reg_write(struct rsi_hw *adapter,
+ unsigned long addr,
+ unsigned long data, u16 size)
+{
+ unsigned long data1[2], *data_aligned;
+ int status;
+
+ data_aligned = PTR_ALIGN(&data1[0], 8);
+
+ if (size == 2) {
+ *data_aligned = ((data << 16) | (data & 0xFFFF));
+ } else if (size == 1) {
+ u32 temp_data = data & 0xFF;
+
+ *data_aligned = ((temp_data << 24) | (temp_data << 16) |
+ (temp_data << 8) | temp_data);
+ } else {
+ *data_aligned = data;
+ }
+ size = 4;
+
+ status = rsi_sdio_master_access_msword(adapter, (addr >> 16));
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to set ms word to common reg\n",
+ __func__);
+ return -EIO;
+ }
+ addr = addr & 0xFFFF;
+
+ /* Bring TA out of reset */
+ status = rsi_sdio_write_register_multiple
+ (adapter,
+ (addr | RSI_SD_REQUEST_MASTER),
+ (u8 *)data_aligned, size);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to do AHB reg write\n", __func__);
+ return status;
+ }
+ return 0;
+}
+
/**
* rsi_sdio_host_intf_write_pkt() - This function writes the packet to device.
* @adapter: Pointer to the adapter structure.
@@ -694,6 +870,9 @@ static struct rsi_host_intf_ops sdio_host_intf_ops = {
.read_pkt = rsi_sdio_host_intf_read_pkt,
.read_reg_multiple = rsi_sdio_read_register_multiple,
.write_reg_multiple = rsi_sdio_write_register_multiple,
+ .master_reg_read = rsi_sdio_master_reg_read,
+ .master_reg_write = rsi_sdio_master_reg_write,
+ .load_data_master_write = rsi_sdio_load_data_master_write,
};
/**
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
index 7c9cf01..225042f 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
@@ -27,8 +27,7 @@
*
* Return: status: 0 on success, -1 on failure.
*/
-static int rsi_sdio_master_access_msword(struct rsi_hw *adapter,
- u16 ms_word)
+int rsi_sdio_master_access_msword(struct rsi_hw *adapter, u16 ms_word)
{
u8 byte;
u8 function = 0;
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index 9000e09..b10b145 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -392,10 +392,75 @@ static int rsi_usb_host_intf_write_pkt(struct rsi_hw *adapter,
len);
}
+static int rsi_usb_master_reg_read(struct rsi_hw *adapter, u32 reg,
+ u32 *value, u16 len)
+{
+ struct usb_device *usbdev =
+ ((struct rsi_91x_usbdev *)adapter->rsi_dev)->usbdev;
+
+ return rsi_usb_reg_read(usbdev, reg, (u16 *)value, len);
+}
+
+static int rsi_usb_master_reg_write(struct rsi_hw *adapter,
+ unsigned long reg,
+ unsigned long value, u16 len)
+{
+ struct usb_device *usbdev =
+ ((struct rsi_91x_usbdev *)adapter->rsi_dev)->usbdev;
+
+ return rsi_usb_reg_write(usbdev, reg, value, len);
+}
+
+static int rsi_usb_load_data_master_write(struct rsi_hw *adapter,
+ u32 base_address,
+ u32 instructions_sz, u16 block_size,
+ u8 *ta_firmware)
+{
+ u16 num_blocks;
+ u32 cur_indx, i;
+ u8 temp_buf[256];
+ int status;
+
+ num_blocks = instructions_sz / block_size;
+ rsi_dbg(INFO_ZONE, "num_blocks: %d\n", num_blocks);
+
+ for (cur_indx = 0, i = 0; i < num_blocks; i++, cur_indx += block_size) {
+ memset(temp_buf, 0, block_size);
+ memcpy(temp_buf, ta_firmware + cur_indx, block_size);
+ status = rsi_usb_write_register_multiple(adapter, base_address,
+ (u8 *)(temp_buf),
+ block_size);
+ if (status < 0)
+ return status;
+
+ rsi_dbg(INFO_ZONE, "%s: loading block: %d\n", __func__, i);
+ base_address += block_size;
+ }
+
+ if (instructions_sz % block_size) {
+ memset(temp_buf, 0, block_size);
+ memcpy(temp_buf, ta_firmware + cur_indx,
+ instructions_sz % block_size);
+ status = rsi_usb_write_register_multiple
+ (adapter, base_address,
+ (u8 *)temp_buf,
+ instructions_sz % block_size);
+ if (status < 0)
+ return status;
+ rsi_dbg(INFO_ZONE,
+ "Written Last Block in Address 0x%x Successfully\n",
+ cur_indx);
+ }
+ return 0;
+}
+
static struct rsi_host_intf_ops usb_host_intf_ops = {
.write_pkt = rsi_usb_host_intf_write_pkt,
.read_reg_multiple = rsi_usb_read_register_multiple,
.write_reg_multiple = rsi_usb_write_register_multiple,
+ .master_reg_read = rsi_usb_master_reg_read,
+ .master_reg_write = rsi_usb_master_reg_write,
+ .load_data_master_write = rsi_usb_load_data_master_write,
};
/**
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index 7fdeda7..2ac5bcf 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -244,5 +244,13 @@ struct rsi_host_intf_ops {
u8 *data, u16 count);
int (*write_reg_multiple)(struct rsi_hw *adapter, u32 addr,
u8 *data, u16 count);
+ int (*master_reg_read)(struct rsi_hw *adapter, u32 addr,
+ u32 *read_buf, u16 size);
+ int (*master_reg_write)(struct rsi_hw *adapter,
+ unsigned long addr, unsigned long data,
+ u16 size);
+ int (*load_data_master_write)(struct rsi_hw *adapter, u32 addr,
+ u32 instructions_size, u16 block_size,
+ u8 *fw);
};
#endif
diff --git a/drivers/net/wireless/rsi/rsi_sdio.h b/drivers/net/wireless/rsi/rsi_sdio.h
index a82bc4c..7ae6d51 100644
--- a/drivers/net/wireless/rsi/rsi_sdio.h
+++ b/drivers/net/wireless/rsi/rsi_sdio.h
@@ -123,6 +123,7 @@ int rsi_sdio_write_register(struct rsi_hw *adapter, u8 function,
u32 addr, u8 *data);
int rsi_sdio_write_register_multiple(struct rsi_hw *adapter, u32 addr,
u8 *data, u16 count);
+int rsi_sdio_master_access_msword(struct rsi_hw *adapter, u16 ms_word);
void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit);
int rsi_sdio_determine_event_timeout(struct rsi_hw *adapter);
int rsi_sdio_read_buffer_status_register(struct rsi_hw *adapter, u8 q_num);
--
2.7.4
From: Prameela Rani Garnepudi <[email protected]>
SDIO read or write maximum size is limited to 2^16. This is done to make
the host interface operations common for SDIO and USB.
Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
v3: Same as earlier
---
drivers/net/wireless/rsi/rsi_91x_sdio.c | 10 +++++-----
drivers/net/wireless/rsi/rsi_91x_sdio_ops.c | 8 ++++----
drivers/net/wireless/rsi/rsi_sdio.h | 4 ++--
3 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index 8428858..39d94b3 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -487,8 +487,8 @@ void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit)
*/
static int rsi_sdio_read_register_multiple(struct rsi_hw *adapter,
u32 addr,
- u32 count,
- u8 *data)
+ u8 *data,
+ u16 count)
{
struct rsi_91x_sdiodev *dev =
(struct rsi_91x_sdiodev *)adapter->rsi_dev;
@@ -518,7 +518,7 @@ static int rsi_sdio_read_register_multiple(struct rsi_hw *adapter,
int rsi_sdio_write_register_multiple(struct rsi_hw *adapter,
u32 addr,
u8 *data,
- u32 count)
+ u16 count)
{
struct rsi_91x_sdiodev *dev =
(struct rsi_91x_sdiodev *)adapter->rsi_dev;
@@ -614,8 +614,8 @@ int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter,
status = rsi_sdio_read_register_multiple(adapter,
length,
- length, /*num of bytes*/
- (u8 *)pkt);
+ (u8 *)pkt,
+ length); /*num of bytes*/
if (status)
rsi_dbg(ERR_ZONE, "%s: Failed to read frame: %d\n", __func__,
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
index 40d7231..7c9cf01 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
@@ -75,13 +75,13 @@ static int rsi_sdio_master_access_msword(struct rsi_hw *adapter,
static int rsi_copy_to_card(struct rsi_common *common,
const u8 *fw,
u32 len,
- u32 num_blocks)
+ u16 num_blocks)
{
struct rsi_hw *adapter = common->priv;
struct rsi_91x_sdiodev *dev =
(struct rsi_91x_sdiodev *)adapter->rsi_dev;
u32 indx, ii;
- u32 block_size = dev->tx_blk_size;
+ u16 block_size = dev->tx_blk_size;
u32 lsb_address;
__le32 data[] = { TA_HOLD_THREAD_VALUE, TA_SOFT_RST_CLR,
TA_PC_ZERO, TA_RELEASE_THREAD_VALUE };
@@ -171,10 +171,10 @@ static int rsi_load_ta_instructions(struct rsi_common *common)
struct rsi_91x_sdiodev *dev =
(struct rsi_91x_sdiodev *)adapter->rsi_dev;
u32 len;
- u32 num_blocks;
+ u16 num_blocks;
const u8 *fw;
const struct firmware *fw_entry = NULL;
- u32 block_size = dev->tx_blk_size;
+ u16 block_size = dev->tx_blk_size;
int status = 0;
u32 base_address;
u16 msb_address;
diff --git a/drivers/net/wireless/rsi/rsi_sdio.h b/drivers/net/wireless/rsi/rsi_sdio.h
index c7e8f2b..a82bc4c 100644
--- a/drivers/net/wireless/rsi/rsi_sdio.h
+++ b/drivers/net/wireless/rsi/rsi_sdio.h
@@ -110,7 +110,7 @@ struct rsi_91x_sdiodev {
u8 sdio_clock_speed;
u32 cardcapability;
u8 prev_desc[16];
- u32 tx_blk_size;
+ u16 tx_blk_size;
u8 write_fail;
};
@@ -122,7 +122,7 @@ int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter, u8 *pkt, u32 length);
int rsi_sdio_write_register(struct rsi_hw *adapter, u8 function,
u32 addr, u8 *data);
int rsi_sdio_write_register_multiple(struct rsi_hw *adapter, u32 addr,
- u8 *data, u32 count);
+ u8 *data, u16 count);
void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit);
int rsi_sdio_determine_event_timeout(struct rsi_hw *adapter);
int rsi_sdio_read_buffer_status_register(struct rsi_hw *adapter, u8 q_num);
--
2.7.4