0
0
Fork 0
hgicf/utils/if_sdio.c

1018 lines
27 KiB
C
Raw Normal View History

2023-05-16 09:13:19 +00:00
#ifdef __RTOS__
#include <linux/types.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/semaphore.h>
#include <linux/skbuff.h>
#include "porting/sdio.h"
#else
#include <linux/version.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/semaphore.h>
#include <linux/mmc/card.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/sd.h>
#include <linux/netdevice.h>
#define sdio_func_t sdio_func
#define mmc_command_t mmc_command
#define sdio_device_id_t sdio_device_id
#define sdio_driver_t sdio_driver
#define vendor_id vendor
#define device_id device
#define f_num num
#endif
#include "../hgic_def.h"
#include "utils.h"
#define SDIO_BLOCK_SIZE 64
#define SDIO_DATA_ADDR 0x0
#define SDIO_TRANS_COUNT_ADDR 0x1C
#define SDIO_INIT_STATUS_ADDR 0x04
#define SDIO_INIT_STATUS_ADDR2 0x48
#define SDIO_TRANS_COUNT_ADDR2 0x49
2023-10-12 23:37:43 +00:00
#define SDIO_BUSY_ADDR2 0x4c
#define HGIC_PKT_MAX_LEN (8*1024)
#define SDIO_INIT_STATUS_DATA_READY BIT(0)
#define SDIO_INIT_STATUS_BUSY BIT(3)
2023-05-16 09:13:19 +00:00
#define SDIO_STATUS_STOP BIT(0)
#define SDIO_STATUS_ERROR BIT(1)
#define SDIO_TX_HEADROM (4)
2023-10-12 23:37:43 +00:00
static hgic_probe probe_hdl = NULL;
static u32 max_pkt_len = HGIC_PKT_MAX_LEN;
2023-05-16 09:13:19 +00:00
struct hgic_sdio {
struct sdio_func_t *func;
u32 status;
u32 data_addr; /*sdio data register address*/
u32 trans_cnt_addr; /*sdio data length register address*/
u32 int_status_addr; /*interrupt status register address*/
struct hgic_bus bus;
2023-10-12 23:37:43 +00:00
u8 rx_retry;
u8 busypd;
struct completion busy;
u8 *rxbuf;
2023-05-16 09:13:19 +00:00
};
const struct sdio_device_id_t hgic_sdio_wdev_ids[] = {
2023-10-12 23:37:43 +00:00
{SDIO_DEVICE(HGIC_VENDOR_ID, HGIC_WLAN_4002)},
{SDIO_DEVICE(HGIC_VENDOR_ID, HGIC_WLAN_4104)},
{SDIO_DEVICE(HGIC_VENDOR_ID, HGIC_WLAN_8400)},
2023-05-16 09:13:19 +00:00
{ /* end: all zeroes */ },
};
#ifndef __RTOS__
#ifndef SDIO_BUS_WIDTH_MASK
#define SDIO_BUS_WIDTH_MASK 3
#endif
#ifndef mmc_card_highspeed
#define mmc_card_highspeed mmc_card_hs
#endif
#ifndef mmc_card_set_highspeed
#define mmc_card_set_highspeed(func)
#endif
#define FUNC_DEV(f) (&((f)->dev))
#define SDIO_CAP_IRQ(func) ((func)->card->host->caps & MMC_CAP_SDIO_IRQ)
#define SDIO_CAP_POLL(func) ((func)->card->host->caps & MMC_CAP_NEEDS_POLL)
#define HOST_SPI_CRC(func, crc) (func)->card->host->use_spi_crc=crc
2023-10-12 23:44:32 +00:00
#define mmc_card_disable_cd(c) (1)
2023-05-16 09:13:19 +00:00
#define hgic_card_disable_cd(func) mmc_card_disable_cd((func)->card)
#define hgic_card_set_highspeed(func) mmc_card_set_highspeed((func)->card)
#define hgic_host_is_spi(func) mmc_host_is_spi((func)->card->host)
#define hgic_card_cccr_widebus(func) ((func)->card->cccr.low_speed && !(func)->card->cccr.wide_bus)
#define hgic_card_cccr_highspeed(func) ((func)->card->cccr.high_speed)
#define hgic_host_highspeed(func) ((func)->card->host->caps & MMC_CAP_SD_HIGHSPEED)
#define hgic_host_supp_4bit(func) ((func)->card->host->caps & MMC_CAP_4_BIT_DATA)
#define hgic_card_highspeed(func) mmc_card_highspeed((func)->card)
#define hgic_func_rca(func) ((func)->card->rca)
#define hgic_card_max_clock(func) ((func)->card->cis.max_dtr)
#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,10,14)
#define hgic_card_ocr(func) ((func)->card->host->ocr)
#else
#define hgic_card_ocr(func) ((func)->card->ocr)
#endif
static inline void hgic_mmc_set_timing(struct sdio_func_t *func, unsigned int timing)
{
func->card->host->ios.timing = timing;
func->card->host->ops->set_ios(func->card->host, &func->card->host->ios);
}
static inline void hgic_mmc_set_bus_width(struct sdio_func_t *func, unsigned int width)
{
func->card->host->ios.bus_width = width;
func->card->host->ops->set_ios(func->card->host, &func->card->host->ios);
}
static inline void hgic_mmc_set_clock(struct sdio_func_t *func, unsigned int hz)
{
if (func->card->host->f_max && hz > func->card->host->f_max) {
hz = func->card->host->f_max;
}
func->card->host->ios.clock = hz;
func->card->host->ops->set_ios(func->card->host, &func->card->host->ios);
}
static inline int hgic_mmc_send_cmd(struct sdio_func_t *func, struct mmc_command_t *cmd, int retries)
{
return mmc_wait_for_cmd(func->card->host, cmd, retries);
}
2023-10-12 23:37:43 +00:00
static inline void hgic_mmc_set_blk_size(struct sdio_func_t *func, unsigned int blk_size)
{
func->card->host->max_blk_size = blk_size;
func->card->host->ops->set_ios(func->card->host, &func->card->host->ios);
}
2023-05-16 09:13:19 +00:00
#endif
static int hgic_mmc_io_rw_direct(struct sdio_func_t *func, int write, unsigned fn,
unsigned addr, u8 in, u8 *out)
{
struct mmc_command_t cmd = {0};
int err;
/* sanity check */
if (addr & ~0x1FFFF) {
return -EINVAL;
}
cmd.opcode = SD_IO_RW_DIRECT;
cmd.arg = write ? 0x80000000 : 0x00000000;
cmd.arg |= fn << 28;
cmd.arg |= (write && out) ? 0x08000000 : 0x00000000;
cmd.arg |= addr << 9;
cmd.arg |= in;
cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC;
err = hgic_mmc_send_cmd(func, &cmd, 0);
if (err) {
return err;
}
if (hgic_host_is_spi(func)) {
/* host driver already reported errors */
} else {
if (cmd.resp[0] & R5_ERROR) {
return -EIO;
}
if (cmd.resp[0] & R5_FUNCTION_NUMBER) {
return -EINVAL;
}
if (cmd.resp[0] & R5_OUT_OF_RANGE) {
return -ERANGE;
}
}
if (out) {
if (hgic_host_is_spi(func)) {
*out = (cmd.resp[0] >> 8) & 0xFF;
} else {
*out = cmd.resp[0] & 0xFF;
}
}
return 0;
}
static int hgic_sdio_reset(struct sdio_func_t *func)
{
int ret;
u8 abort;
/* SDIO Simplified Specification V2.0, 4.4 Reset for SDIO */
ret = hgic_mmc_io_rw_direct(func, 0, 0, SDIO_CCCR_ABORT, 0, &abort);
if (ret) {
abort = 0x08;
} else {
abort |= 0x08;
}
ret = hgic_mmc_io_rw_direct(func, 1, 0, SDIO_CCCR_ABORT, abort, NULL);
return ret;
}
static int hgic_sdio_go_idle(struct sdio_func_t *func)
{
int err;
struct mmc_command_t cmd = {0};
cmd.opcode = MMC_GO_IDLE_STATE;
cmd.arg = 0;
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_NONE | MMC_CMD_BC;
err = hgic_mmc_send_cmd(func, &cmd, 0);
msleep(1);
HOST_SPI_CRC(func, 0);
return err;
}
static int hgic_mmc_send_if_cond(struct sdio_func_t *func, u32 ocr)
{
struct mmc_command_t cmd = {0};
int err;
static const u8 test_pattern = 0xAA;
u8 result_pattern;
/*
* To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND
* before SD_APP_OP_COND. This command will harmlessly fail for
* SD 1.0 cards.
*/
cmd.opcode = SD_SEND_IF_COND;
cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern;
cmd.flags = MMC_RSP_SPI_R7 | MMC_RSP_R7 | MMC_CMD_BCR;
err = hgic_mmc_send_cmd(func, &cmd, 0);
if (err) {
return err;
}
if (hgic_host_is_spi(func)) {
result_pattern = cmd.resp[1] & 0xFF;
} else {
result_pattern = cmd.resp[0] & 0xFF;
}
if (result_pattern != test_pattern) {
return -EIO;
}
return 0;
}
static int hgic_send_io_op_cond(struct sdio_func_t *func, u32 ocr, u32 *rocr)
{
struct mmc_command_t cmd = {0};
int i, err = 0;
BUG_ON(!func);
cmd.opcode = SD_IO_SEND_OP_COND;
cmd.arg = ocr;
cmd.flags = MMC_RSP_SPI_R4 | MMC_RSP_R4 | MMC_CMD_BCR;
for (i = 10; i; i--) {
err = hgic_mmc_send_cmd(func, &cmd, 3);
if (err) {
break;
}
/* if we're just probing, do a single pass */
if (ocr == 0) {
break;
}
/* otherwise wait until reset completes */
if (hgic_host_is_spi(func)) {
/*
* Both R1_SPI_IDLE and MMC_CARD_BUSY indicate
* an initialized card under SPI, but some cards
* (Marvell's) only behave when looking at this
* one.
*/
if (cmd.resp[1] & MMC_CARD_BUSY) {
break;
}
} else {
if (cmd.resp[0] & MMC_CARD_BUSY) {
break;
}
}
err = -ETIMEDOUT;
mdelay(10);
}
if (rocr) {
*rocr = cmd.resp[hgic_host_is_spi(func) ? 1 : 0];
}
return err;
}
static int hgic_sdio_get_card_addr(struct sdio_func_t *func, u32 *rca)
{
int err;
struct mmc_command_t cmd = {0};
cmd.opcode = SD_SEND_RELATIVE_ADDR;
cmd.arg = 0;
cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
err = hgic_mmc_send_cmd(func, &cmd, 3);
if (err) {
return err;
}
*rca = cmd.resp[0] >> 16;
return 0;
}
static u32 hgic_sdio_set_highspeed(struct sdio_func_t *func, int enable)
{
int ret;
u8 speed;
if (!hgic_host_highspeed(func)) {
return 0;
}
if (!hgic_card_cccr_highspeed(func)) {
return 0;
}
ret = hgic_mmc_io_rw_direct(func, 0, 0, SDIO_CCCR_SPEED, 0, &speed);
if (ret) {
return ret;
}
if (enable) {
speed |= SDIO_SPEED_EHS;
} else {
speed &= ~SDIO_SPEED_EHS;
}
ret = hgic_mmc_io_rw_direct(func, 1, 0, SDIO_CCCR_SPEED, speed, NULL);
if (ret) {
return ret;
}
hgic_card_set_highspeed(func);
return 1;
}
static int hgic_sdio_disable_cd(struct sdio_func_t *func)
{
int ret;
u8 ctrl;
if (!hgic_card_disable_cd(func)) {
return 0;
}
ret = hgic_mmc_io_rw_direct(func, 0, 0, SDIO_CCCR_IF, 0, &ctrl);
if (ret) {
return ret;
}
ctrl |= SDIO_BUS_CD_DISABLE;
return hgic_mmc_io_rw_direct(func, 1, 0, SDIO_CCCR_IF, ctrl, NULL);
}
static int hgic_sdio_set_wire_width(struct sdio_func_t *func)
{
int ret;
u8 ctrl;
if (!hgic_host_supp_4bit(func)) {
return 0;
}
if (hgic_card_cccr_widebus(func)) {
return 0;
}
ret = hgic_mmc_io_rw_direct(func, 0, 0, SDIO_CCCR_IF, 0, &ctrl);
if (ret) {
return ret;
}
/* set as 4-bit bus width */
ctrl &= ~ SDIO_BUS_WIDTH_MASK;
ctrl |= SDIO_BUS_WIDTH_4BIT;
ret = hgic_mmc_io_rw_direct(func, 1, 0, SDIO_CCCR_IF, ctrl, NULL);
if (ret) {
return ret;
}
hgic_mmc_set_bus_width(func, MMC_BUS_WIDTH_4);
return 1;
}
2023-10-12 23:37:43 +00:00
static u32 hgic_sdio_select_card(struct sdio_func_t *func, u32 rca)
2023-05-16 09:13:19 +00:00
{
int err;
struct mmc_command_t cmd = {0};
cmd.opcode = MMC_SELECT_CARD;
if (func) {
2023-10-12 23:37:43 +00:00
cmd.arg = rca << 16;
2023-05-16 09:13:19 +00:00
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
} else {
cmd.arg = 0;
cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
}
err = hgic_mmc_send_cmd(func, &cmd, 3);
if (err) {
return err;
}
return 0;
}
static int hgic_sdio_int_enable(struct sdio_func_t *func, u8 enable)
{
u8 temp;
u8 dat;
if (enable) {
dat = (1 << func->f_num) | 0x1;
} else {
dat = 0x1;
}
return hgic_mmc_io_rw_direct(func, 1, 0, SDIO_CCCR_IENx, dat, &temp);
}
static int hgic_mmc_spi_set_crc(struct sdio_func_t *func, int use_crc)
{
struct mmc_command_t cmd = {0};
int err;
cmd.opcode = MMC_SPI_CRC_ON_OFF;
cmd.flags = MMC_RSP_SPI_R1;
cmd.arg = use_crc;
err = hgic_mmc_send_cmd(func, &cmd, 0);
if (!err) {
HOST_SPI_CRC(func, use_crc);
}
return err;
}
static int hgic_sdio_reinit_card(struct sdio_func_t *func)
{
2023-10-12 23:37:43 +00:00
#ifdef CONFIG_SDIO_REINIT
2023-05-16 09:13:19 +00:00
int i = 3;
u32 ocr = 0;
2023-10-12 23:37:43 +00:00
u32 rca = 0;
2023-05-16 09:13:19 +00:00
int retry = 0;
struct hgic_sdio *sdiodev = sdio_get_drvdata(func);
hgic_enter();
__RETRY:
if (!sdiodev ||
test_bit(HGIC_BUS_FLAGS_DISABLE_REINIT, &sdiodev->bus.flags) ||
test_bit(HGIC_BUS_FLAGS_SLEEP, &sdiodev->bus.flags)) {
hgic_err("leave, can not reinit\r\n");
return -1;
}
if (retry++ > 2) {
hgic_err("leave, reinit fail\r\n");
return -1;
}
2023-10-12 23:37:43 +00:00
i = 5;
2023-05-16 09:13:19 +00:00
ocr = 0;
2023-10-12 23:37:43 +00:00
rca = 0;
2023-05-16 09:13:19 +00:00
hgic_mmc_set_clock(func, 400000);
hgic_mmc_set_timing(func, MMC_TIMING_LEGACY);
hgic_mmc_set_bus_width(func, MMC_BUS_WIDTH_1);
2023-10-12 23:37:43 +00:00
if (!hgic_sdio_get_card_addr(func, (u32 *)&rca)) {
hgic_sdio_select_card(func, rca);
}
2023-05-16 09:13:19 +00:00
hgic_sdio_reset(func);
hgic_sdio_go_idle(func);
hgic_mmc_send_if_cond(func, ocr);
if (hgic_send_io_op_cond(func, 0, (u32 *)&ocr)) {
goto __RETRY;
}
2023-10-12 23:37:43 +00:00
if (hgic_send_io_op_cond(func, ocr, (u32 *)&ocr)) {
2023-05-16 09:13:19 +00:00
goto __RETRY;
}
if (hgic_host_is_spi(func)) {
if (hgic_mmc_spi_set_crc(func, 1)) {
goto __RETRY;
}
} else {
if (hgic_sdio_get_card_addr(func, (u32 *)&rca)) {
goto __RETRY;
}
2023-10-12 23:37:43 +00:00
if (hgic_sdio_select_card(func, rca)) {
2023-05-16 09:13:19 +00:00
goto __RETRY;
}
if (hgic_sdio_disable_cd(func) < 0) {
goto __RETRY;
}
}
if (hgic_sdio_set_highspeed(func, 1) < 0) {
goto __RETRY;
}
hgic_mmc_set_clock(func, hgic_card_highspeed(func) ? 50000000 : hgic_card_max_clock(func));
hgic_mmc_set_timing(func, MMC_TIMING_SD_HS);
2023-10-12 23:37:43 +00:00
hgic_mmc_set_blk_size(func, SDIO_BLOCK_SIZE);
2023-05-16 09:13:19 +00:00
if (hgic_sdio_set_wire_width(func) < 0) {
goto __RETRY;
}
if (sdio_set_block_size(func, SDIO_BLOCK_SIZE)) {
goto __RETRY;
}
if (hgic_sdio_int_enable(func, 1)) {
goto __RETRY;
}
if (sdio_enable_func(func)) {
goto __RETRY;
}
2023-10-12 23:37:43 +00:00
2023-05-16 09:13:19 +00:00
#ifndef __RTOS__
if (func->card->host->sdio_irq_thread) {
wake_up_process(func->card->host->sdio_irq_thread);
}
2023-10-12 23:37:43 +00:00
#endif
hgic_leave();
2023-05-16 09:13:19 +00:00
#endif
return 0;
}
static int hgic_sdio_reinit(void *bus)
{
int ret = 0;
struct hgic_sdio *sdiodev = container_of(bus, struct hgic_sdio, bus);
sdio_claim_host(sdiodev->func);
ret = hgic_sdio_reinit_card(sdiodev->func);
sdio_release_host(sdiodev->func);
return ret;
}
static int hgic_sdio_readb(struct sdio_func_t *func, u32 addr, int *err)
{
u8 val = 0;
int retry = 2;
val = sdio_readb(func, addr, err);
2023-10-12 23:37:43 +00:00
//if (val == 0) {
// *err = -1;
//}
2023-05-16 09:13:19 +00:00
while (*err && retry-- > 0) {
val = sdio_readb(func, addr, err);
}
return val;
}
static void hgic_sdio_writeb(struct sdio_func_t *func, u8 b, u32 addr, int *err)
{
int retry = 4;
do {
sdio_writeb(func, b, addr, err);
} while (*err && retry-- > 0);
}
static int hgic_sdio_copy_fromio(struct sdio_func_t *func, u8 *dest, u32 addr, int count)
{
int err = 0;
err = sdio_memcpy_fromio(func, dest, addr, count);
if (err) {
hgic_err("err=%d\r\n", err);
hgic_sdio_reinit_card(func);
}
return err;
}
static int hgic_sdio_copy_toio(struct sdio_func_t *func, u32 addr, u8 *src, int count)
{
int err = 0;
err = sdio_memcpy_toio(func, addr, src, count);
if (err) {
hgic_err("err=%d\r\n", err);
if (!hgic_sdio_reinit_card(func)) {
err = sdio_memcpy_toio(func, addr, src, count);
}
}
return err;
}
static int hgic_sdio_abort(struct sdio_func_t *func)
{
int err_ret = 0;
struct sdio_func_t func0;
memcpy(&func0, func, sizeof(func0));
func0.f_num = 0;
hgic_sdio_writeb(&func0, 1, 6, &err_ret);
return err_ret;
}
2023-10-12 23:37:43 +00:00
2023-05-16 09:13:19 +00:00
static int hgic_sdio_read_cccr(struct sdio_func_t *func, u8 *pending)
{
int ret = 0;
struct sdio_func_t func0;
memcpy(&func0, func, sizeof(func0));
func0.f_num = 0;
*pending = hgic_sdio_readb(&func0, 0x5, &ret);
return ret;
}
2023-10-12 23:37:43 +00:00
static u32 hgic_sdio_get_datalen(struct hgic_sdio *sdiodev, u8 addr)
2023-05-16 09:13:19 +00:00
{
int err = 0;
u32 len = 0;
u8 ret = 0;
ret = hgic_sdio_readb(sdiodev->func, addr, &err);
2023-10-12 23:37:43 +00:00
if (err) {
return 0xffffffff;
}
2023-05-16 09:13:19 +00:00
len = ret;
ret = hgic_sdio_readb(sdiodev->func, addr + 1, &err);
2023-10-12 23:37:43 +00:00
if (err) {
return 0xffffffff;
}
2023-05-16 09:13:19 +00:00
len |= ret << 8;
2023-10-12 23:37:43 +00:00
return len;
}
static u32 hgic_sdio_data_len(struct hgic_sdio *sdiodev)
{
int ret = 0;
u32 len = 0;
if (!test_bit(HGIC_BUS_FLAGS_INBOOT, &sdiodev->bus.flags)) {
if(sdiodev->bus.dev_id == HGIC_WLAN_4002){
len = hgic_sdio_get_datalen(sdiodev, SDIO_TRANS_COUNT_ADDR2);
}else{
len = sdio_readb(sdiodev->func, SDIO_TRANS_COUNT_ADDR2, &ret);
len = len * SDIO_BLOCK_SIZE;
}
}
if (len == 0 || len == 0xffffffff) {
len = hgic_sdio_get_datalen(sdiodev, sdiodev->trans_cnt_addr);
}
2023-05-16 09:13:19 +00:00
if (len == 0) {
if (test_bit(HGIC_BUS_FLAGS_INBOOT, &sdiodev->bus.flags)) {
len = 16;
} else {
len = 0xFFFFFFFF;
hgic_err("get len error\r\n");
}
}
return len;
}
2023-10-12 23:37:43 +00:00
static u32 hgic_sdio_int_status(struct hgic_sdio *sdiodev, struct sdio_func_t *func)
2023-05-16 09:13:19 +00:00
{
int ret = 0;
u8 pending = 0;
u8 int_status1 = 0;
u8 int_status2 = 0;
ret = hgic_sdio_read_cccr(func, &pending);
if (!ret && (pending & 02)) {
2023-10-12 23:37:43 +00:00
int_status1 = hgic_sdio_readb(func, sdiodev->int_status_addr, &ret);
2023-05-16 09:13:19 +00:00
if (!ret && !int_status1 && !test_bit(HGIC_BUS_FLAGS_INBOOT, &sdiodev->bus.flags)) {
int_status2 = hgic_sdio_readb(func, SDIO_INIT_STATUS_ADDR2, &ret);
if (int_status1 != int_status2) {
hgic_err("INTID(%x:%x)\r\n", int_status1, int_status2);
int_status1 = int_status2;
}
}
2023-10-12 23:37:43 +00:00
if (!int_status1) {
hgic_sdio_abort(func);
}
2023-05-16 09:13:19 +00:00
}
return int_status1;
}
static void hgic_sdio_interrupt(struct sdio_func_t *func)
{
int ret = 0;
u32 len = 0;
int read_more = 0;
2023-10-12 23:37:43 +00:00
u32 int_status;
2023-05-16 09:13:19 +00:00
struct hgic_sdio *sdiodev = sdio_get_drvdata(func);
2023-10-12 23:37:43 +00:00
if (sdiodev == NULL || (sdiodev->status & SDIO_STATUS_STOP)) {
2023-05-16 09:13:19 +00:00
return;
}
read_more = sdiodev->rx_retry;
do {
2023-10-12 23:37:43 +00:00
int_status = hgic_sdio_int_status(sdiodev, func);
if (int_status & SDIO_INIT_STATUS_DATA_READY) {
2023-05-16 09:13:19 +00:00
read_more = sdiodev->rx_retry;
len = hgic_sdio_data_len(sdiodev);
if (len == 0xFFFFFFFF) {
hgic_err("data len error\r\n");
hgic_sdio_abort(func);
hgic_sdio_reinit_card(func);
return;
} else if (len > 0) {
2023-10-12 23:37:43 +00:00
if (len > max_pkt_len){
hgic_err("len error: %d, max:%d\r\n", len, max_pkt_len);
2023-05-16 09:13:19 +00:00
hgic_sdio_abort(func);
return;
}
2023-10-12 23:37:43 +00:00
ret = hgic_sdio_copy_fromio(sdiodev->func, sdiodev->rxbuf, sdiodev->data_addr, len);
2023-05-16 09:13:19 +00:00
if (ret) {
hgic_err("sdio_copy_fromio err!, ret:%d\r\n", ret);
return;
}
2023-10-12 23:37:43 +00:00
ret = sdiodev->bus.rx_packet(sdiodev->bus.bus_priv, sdiodev->rxbuf, len);
2023-05-16 09:13:19 +00:00
if (ret) {
hgic_sdio_abort(func);
}
} else {
hgic_sdio_abort(func);
}
2023-10-12 23:37:43 +00:00
}
if ((int_status & SDIO_INIT_STATUS_BUSY) && sdiodev->busypd) {
//printk("*\r\n");
complete(&sdiodev->busy);
}
if (int_status == 0 && read_more > 0) {
2023-05-16 09:13:19 +00:00
udelay(20);
}
} while (!ret && read_more-- > 0);
}
2023-10-12 23:37:43 +00:00
static int hgic_sdio_is_busy(struct hgic_sdio *sdiodev)
{
int err = 0;
u8 val = 0;
val = hgic_sdio_readb(sdiodev->func, SDIO_BUSY_ADDR2, &err);
if(err) hgic_sdio_reinit_card(sdiodev->func);
return (err || (val & 0x01)) ? 1 : 0;
}
2023-05-16 09:13:19 +00:00
static int hgic_sdio_tx_packet(void *bus, struct sk_buff *skb)
{
int ret = 0;
2023-10-12 23:37:43 +00:00
int busy = 1;
struct list_head *head;
2023-05-16 09:13:19 +00:00
struct hgic_sdio *sdiodev = container_of(bus, struct hgic_sdio, bus);
int len = skb->len > SDIO_BLOCK_SIZE ? ALIGN(skb->len, SDIO_BLOCK_SIZE) : ALIGN(skb->len, 4);
2023-10-12 23:37:43 +00:00
#ifndef __RTOS__
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0)
head = &sdiodev->func->card->host->wq.head;
#else
head = &sdiodev->func->card->host->wq.task_list;
#endif
if (!list_empty(head) /*|| (!SDIO_CAP_IRQ(sdiodev->func) && time_after(jiffies, sdiodev->last_rxtick + msecs_to_jiffies(100)))*/) {
schedule();
}
#endif
2023-05-16 09:13:19 +00:00
sdio_claim_host(sdiodev->func);
if ((sdiodev->status & SDIO_STATUS_STOP) || test_bit(HGIC_BUS_FLAGS_SLEEP, &sdiodev->bus.flags)) {
sdiodev->bus.tx_complete(sdiodev->bus.bus_priv, skb, 0);
sdio_release_host(sdiodev->func);
return -1;
}
2023-10-12 23:37:43 +00:00
while (busy && !test_bit(HGIC_BUS_FLAGS_SOFTFC, &sdiodev->bus.flags)) {
busy = hgic_sdio_is_busy(sdiodev);
if (busy) {
sdiodev->busypd = 1;
sdio_release_host(sdiodev->func);
wait_for_completion_timeout(&sdiodev->busy, msecs_to_jiffies(10));
sdio_claim_host(sdiodev->func);
sdiodev->busypd = 0;
if ((sdiodev->status & SDIO_STATUS_STOP) || test_bit(HGIC_BUS_FLAGS_SLEEP, &sdiodev->bus.flags)) {
sdiodev->bus.tx_complete(sdiodev->bus.bus_priv, skb, 0);
sdio_release_host(sdiodev->func);
return -1;
}
}
}
2023-05-16 09:13:19 +00:00
ret = hgic_sdio_copy_toio(sdiodev->func, sdiodev->data_addr, skb->data, len);
sdio_release_host(sdiodev->func);
sdiodev->bus.tx_complete(sdiodev->bus.bus_priv, skb, !ret);
return ret;
}
static int hgic_sdio_enable(struct sdio_func_t *func)
{
int ret;
hgic_dbg("Enter\n");
sdio_claim_host(func);
2023-10-12 23:37:43 +00:00
hgic_mmc_set_blk_size(func, SDIO_BLOCK_SIZE);
2023-05-16 09:13:19 +00:00
ret = sdio_set_block_size(func, SDIO_BLOCK_SIZE);
if (ret) {
hgic_err("Set sdio block size %d failed: %d)\n", SDIO_BLOCK_SIZE, ret);
goto out;
}
ret = sdio_claim_irq(func, hgic_sdio_interrupt);
if (ret) {
hgic_err("Set sdio interrupte handle failed: %d\n", ret);
goto out;
}
ret = sdio_enable_func(func);
if (ret) {
2023-10-12 23:37:43 +00:00
sdio_release_irq(func);
2023-05-16 09:13:19 +00:00
hgic_err("enable sdio function failed: %d)\n", ret);
goto out;
}
hgic_dbg("ok\n");
out:
sdio_release_host(func);
return ret;
}
2023-10-12 23:37:43 +00:00
static int hgic_sdio_probe(struct sdio_func_t *func, const struct sdio_device_id_t *id)
2023-05-16 09:13:19 +00:00
{
int ret = 0;
struct hgic_sdio *sdiodev = NULL;
hgic_dbg("Enter, func->num:%d, devid:%x\r\n", func->f_num, func->device_id);
if (func->f_num != 1) {
return -ENODEV;
}
sdiodev = kzalloc(sizeof(struct hgic_sdio), GFP_KERNEL);
if (!sdiodev) {
return -ENOMEM;
}
2023-10-12 23:37:43 +00:00
sdiodev->rxbuf = kmalloc(max_pkt_len, GFP_KERNEL);
if (sdiodev->rxbuf == NULL) {
hgic_err("alloc rxbuf fail, size:%d\r\n", max_pkt_len);
goto __failed;
}
2023-05-16 09:13:19 +00:00
hgic_dbg("new sdio card: vendor:%x, id:%x\n", id->vendor_id, id->device_id);
sdiodev->func = func;
sdiodev->data_addr = SDIO_DATA_ADDR;
sdiodev->trans_cnt_addr = SDIO_TRANS_COUNT_ADDR;
sdiodev->int_status_addr = SDIO_INIT_STATUS_ADDR;
2023-10-12 23:37:43 +00:00
//sdiodev->status = SDIO_STATUS_STOP;
sdiodev->bus.type = HGIC_BUS_SDIO;
sdiodev->bus.drv_tx_headroom = SDIO_TX_HEADROM;
sdiodev->bus.tx_packet = hgic_sdio_tx_packet;
#ifdef CONFIG_SDIO_REINIT
sdiodev->bus.reinit = hgic_sdio_reinit;
#endif
sdiodev->bus.bootdl_pktlen = 32704;
sdiodev->bus.bootdl_cksum = HGIC_BUS_BOOTDL_CHECK_0XFD;
sdiodev->bus.probe = probe_hdl;
2023-05-16 09:13:19 +00:00
sdiodev->bus.dev_id = id->device_id;
sdiodev->bus.blk_size = SDIO_BLOCK_SIZE;
2023-10-12 23:37:43 +00:00
sdiodev->rx_retry = SDIO_CAP_IRQ(func) ? 0 : 5;
init_completion(&sdiodev->busy);
2023-05-16 09:13:19 +00:00
if (!SDIO_CAP_POLL(func)) {
set_bit(HGIC_BUS_FLAGS_NOPOLL, &sdiodev->bus.flags);
}
2023-10-12 23:37:43 +00:00
2023-05-16 09:13:19 +00:00
if (hgic_host_is_spi(func)) {
sdiodev->bus.bootdl_pktlen = 4096;
}
2023-10-12 23:37:43 +00:00
sdiodev->bus.probe(FUNC_DEV(func), &sdiodev->bus);
2023-05-16 09:13:19 +00:00
if (sdiodev->bus.bus_priv == NULL) {
hgic_err("err\r\n");
goto __failed;
}
sdio_set_drvdata(func, sdiodev);
ret = hgic_sdio_enable(func);
if (ret) {
goto __failed;
}
2023-10-12 23:37:43 +00:00
//sdiodev->status &= ~SDIO_STATUS_STOP;
if (sdiodev->bus.probe_post) {
sdiodev->bus.probe_post(sdiodev->bus.bus_priv);
}
2023-05-16 09:13:19 +00:00
hgic_dbg("ok\n");
return ret;
__failed:
hgic_dbg("failed\n");
sdio_set_drvdata(func, NULL);
2023-10-12 23:37:43 +00:00
if (sdiodev->bus.remove) {
sdiodev->bus.remove(sdiodev->bus.bus_priv);
}
if (sdiodev->rxbuf) {
kfree(sdiodev->rxbuf);
}
2023-05-16 09:13:19 +00:00
kfree(sdiodev);
hgic_dbg("failed 2\n");
return ret;
}
2023-10-12 23:37:43 +00:00
static void hgic_sdio_remove(struct sdio_func_t *func)
2023-05-16 09:13:19 +00:00
{
struct hgic_sdio *sdiodev = NULL;
hgic_dbg("Enter\n");
sdiodev = (struct hgic_sdio *)sdio_get_drvdata(func);
if (sdiodev) {
set_bit(HGIC_BUS_FLAGS_DISABLE_REINIT, &sdiodev->bus.flags);
sdiodev->status |= SDIO_STATUS_STOP;
hgic_dbg("remove ... 1\n");
sdio_claim_host(func);
sdio_release_irq(func);
sdio_release_host(func);
hgic_dbg("remove ... 2\n");
2023-10-12 23:37:43 +00:00
if (sdiodev->bus.remove) {
sdiodev->bus.remove(sdiodev->bus.bus_priv);
}
2023-05-16 09:13:19 +00:00
hgic_dbg("remove ... 3\n");
sdio_claim_host(func);
2023-10-12 23:37:43 +00:00
#ifdef __RTOS__
deinit_completion(&sdiodev->busy);
#endif
if (sdiodev->rxbuf) {
kfree(sdiodev->rxbuf);
}
2023-05-16 09:13:19 +00:00
sdio_set_drvdata(func, NULL);
kfree(sdiodev);
sdio_release_host(func);
hgic_dbg("remove ... 4\n");
}
hgic_dbg("Leave\n");
}
#ifdef CONFIG_PM
static int hgic_sdio_suspend(struct device *dev)
{
int ret = 0;
struct sdio_func_t *func = dev_to_sdio_func(dev);
struct hgic_sdio *sdiodev = (struct hgic_sdio *)sdio_get_drvdata(func);
2023-10-12 23:37:43 +00:00
if (sdiodev->bus.suspend) {
ret = sdiodev->bus.suspend(sdiodev->bus.bus_priv);
}
2023-05-16 09:13:19 +00:00
return ret;
}
static int hgic_sdio_resume(struct device *dev)
{
int ret = 0;
struct sdio_func_t *func = dev_to_sdio_func(dev);
struct hgic_sdio *sdiodev = (struct hgic_sdio *)sdio_get_drvdata(func);
2023-10-12 23:37:43 +00:00
if (sdiodev->bus.resume) {
ret = sdiodev->bus.resume(sdiodev->bus.bus_priv);
}
2023-05-16 09:13:19 +00:00
return ret;
}
static const struct dev_pm_ops hgic_sdio_pm_ops = {
.suspend = hgic_sdio_suspend,
.resume = hgic_sdio_resume,
};
#endif
2023-10-12 23:37:43 +00:00
2023-05-16 09:13:19 +00:00
#ifdef SDIO_DRIVER_EXT
extern struct sdio_driver_t hgic_sdio_driver;
#else
static struct sdio_driver_t hgic_sdio_driver = {
.name = "hgic_sdio_wlan",
.id_table = hgic_sdio_wdev_ids,
.probe = hgic_sdio_probe,
.remove = hgic_sdio_remove,
#ifdef CONFIG_PM
.drv = {
.pm = &hgic_sdio_pm_ops,
2023-10-12 23:37:43 +00:00
},
2023-05-16 09:13:19 +00:00
#endif
};
#endif
2023-10-12 23:37:43 +00:00
int __init hgic_sdio_init(hgic_probe probe, u32 max_pkt)
2023-05-16 09:13:19 +00:00
{
int ret;
2023-10-12 23:37:43 +00:00
hgic_dbg("Enter, max_pkt_len = %d\n", max_pkt_len);
probe_hdl = probe;
if(max_pkt > HGIC_PKT_MAX_LEN){
max_pkt_len = max_pkt;
}
2023-05-16 09:13:19 +00:00
ret = sdio_register_driver(&hgic_sdio_driver);
hgic_dbg("Leave\n");
return ret;
}
void __exit hgic_sdio_exit(void)
{
hgic_dbg("Enter\n");
sdio_unregister_driver(&hgic_sdio_driver);
hgic_dbg("Leave\n");
}