rsi: Add new host interface operations
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 <prameela.j04cs@gmail.com> Signed-off-by: Amitkumar Karwar <amit.karwar@redpinesignals.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
parent
a2ce952c8e
commit
b97e9b94ad
|
@ -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,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue