wl12xx sdio 接口

1. init/exit:

    static int __init wl1271_init(void)
    {
        int ret;
        ret = sdio_register_driver(&wl1271_sdio_driver);    //注册SDIO 驱动
        if (ret < 0) {
            wl1271_error("failed to register sdio driver: %d", ret);
            goto out;
        }
    out:
        return ret;
    }
    static void __exit wl1271_exit(void)
    {
        sdio_unregister_driver(&wl1271_sdio_driver);      //注销SDIO驱动
        wl1271_notice("unloaded");
    }
wl1271_sdio_driver 内容:

    static struct sdio_driver wl1271_sdio_driver = {
        .name = "wl1271_sdio",
        .id_table = wl1271_devices,              //设备信息
        .probe = wl1271_probe,                    //注册驱动后会自动运行wl1271_probe().
        .remove = __devexit_p(wl1271_remove),
        .drv = {
            .pm = &wl1271_sdio_pm_ops,     //电源管理相关
        },
    };

wl1271_devices:

    static const struct sdio_device_id wl1271_devices[] = {
        { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) },
        {}
    };
    MODULE_DEVICE_TABLE(sdio, wl1271_devices);
wl1271_sdio_pm_ops:
    static const struct dev_pm_ops wl1271_sdio_pm_ops = {
        .suspend = wl1271_suspend,
        .resume = wl1271_resume,
    };
2.  wl1271_probe():
    static int __devinit wl1271_probe(struct sdio_func *func,
                      const struct sdio_device_id *id)
    {
        struct ieee80211_hw *hw;                          //802.11 phy configuration and hardware info.
        const struct wl12xx_platform_data *wlan_data;     //wl1271 platform data
        struct wl1271 *wl;
        int ret;
        /* We are only able to handle the wlan function */
        if (func->num != 0x02)
            return -ENODEV;
        hw = wl1271_alloc_hw();              // alloc 802.11 phy memory.
        if (IS_ERR(hw))
            return PTR_ERR(hw);
        wl = hw->priv;
        wl->if_priv = func;
        wl->if_ops = &sdio_ops;          //sdio_ops 赋给 wl->if_ops
        /* Grab access to FN0 for ELP reg. */
        func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
        wlan_data = wl12xx_get_platform_data();     //从内核获取wl12xx platform data
        if (IS_ERR(wlan_data)) {
            ret = PTR_ERR(wlan_data);
            wl1271_error("missing wlan platform data: %d", ret);
            goto out_free;
        }
        wl->irq = wlan_data->irq;                           //获取中断号
        wl->ref_clock = wlan_data->board_ref_clock;         //获取时钟频率
        ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl);   //注册中断处理函数wl1271_irq()
        if (ret < 0) {
            wl1271_error("request_irq() failed: %d", ret);
            goto out_free;
        }
        set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);        //设置中断触发方式,上升沿触发
        disable_irq(wl->irq);             //disable 中断
        ret = wl1271_init_ieee80211(wl);             //初始化 802.11 phy hw
        if (ret)
            goto out_irq;
        ret = wl1271_register_hw(wl);        //注册 802.11 phy hw
        if (ret)
            goto out_irq;
        sdio_set_drvdata(func, wl);            //把wl地址赋给func->p->driver_data.
        /* Tell PM core that we don't need the card to be powered now */
        pm_runtime_put_noidle(&func->dev);     
        wl1271_notice("initialized");
        return 0;
     out_irq:
        free_irq(wl->irq, wl);
     out_free:
        wl1271_free_hw(wl);
        return ret;
    }
3. struct wl1271_if_operations sdio_ops :
    static struct wl1271_if_operations sdio_ops = {
        .read = wl1271_sdio_raw_read,     //读
        .write = wl1271_sdio_raw_write,   //写
        .reset = wl1271_sdio_reset,
        .init = wl1271_sdio_init,
        .power = wl1271_sdio_set_power,   //开关电源
        .dev = wl1271_sdio_wl_to_dev,    //获得device
        .enable_irq = wl1271_sdio_enable_interrupts,   
        .disable_irq = wl1271_sdio_disable_interrupts
    };
a. wl1271_sdio_raw_read():
    static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,
                     size_t len, bool fixed)
    {
        int ret;
        struct sdio_func *func = wl_to_func(wl);     //获得sdio_func 函数
        sdio_claim_host(func);   //现获取host
        if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
            ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret);                //sdio 读操作
            wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x",
                     addr, ((u8 *)buf)[0]);
        } else {
            if (fixed)
                ret = sdio_readsb(func, buf, addr, len);
            else
                ret = sdio_memcpy_fromio(func, buf, addr, len);   
            wl1271_debug(DEBUG_SDIO, "sdio read 53 addr 0x%x, %zu bytes",
                     addr, len);
            wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len);
        }
        sdio_release_host(func);   //完事再释放host
        if (ret)
            wl1271_error("sdio read failed (%d)", ret);
    }
b. wl1271_sdio_raw_write() ,内容和read差不多。
    static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf,
                      size_t len, bool fixed)
    {
        int ret;
        struct sdio_func *func = wl_to_func(wl);
        sdio_claim_host(func);
        if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
            sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret);
            wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x",
                     addr, ((u8 *)buf)[0]);
        } else {
            wl1271_debug(DEBUG_SDIO, "sdio write 53 addr 0x%x, %zu bytes",
                     addr, len);
            wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len);
            if (fixed)
                ret = sdio_writesb(func, addr, buf, len);
            else
                ret = sdio_memcpy_toio(func, addr, buf, len);
        }
        sdio_release_host(func);
        if (ret)
            wl1271_error("sdio write failed (%d)", ret);
    }
c. wl1271_sdio_set_power() :
    static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
    {
        if (enable)
            return wl1271_sdio_power_on(wl);
        else
            return wl1271_sdio_power_off(wl);
    }

    static int wl1271_sdio_power_on(struct wl1271 *wl)   // power on
    {
        struct sdio_func *func = wl_to_func(wl);
        int ret;
        /* Power up the card */
        ret = pm_runtime_get_sync(&func->dev);
        if (ret < 0)
            goto out;
        sdio_claim_host(func);
        sdio_enable_func(func);
        sdio_release_host(func);
    out:
        return ret;
    }
    static int wl1271_sdio_power_off(struct wl1271 *wl)
    {
        struct sdio_func *func = wl_to_func(wl);
        sdio_claim_host(func);
        sdio_disable_func(func);
        sdio_release_host(func);
        /* Power down the card */
        return pm_runtime_put_sync(&func->dev);   //power off
    }
d. wl1271_sdio_wl_to_dev():
    static struct device *wl1271_sdio_wl_to_dev(struct wl1271 *wl)
    {
        return &(wl_to_func(wl)->dev);
    }

    static inline struct sdio_func *wl_to_func(struct wl1271 *wl)
    {
        return wl->if_priv;
    }
e. wl1271_sdio_disable_interrupts()/wl1271_sdio_enable_interrupts():
    static void wl1271_sdio_disable_interrupts(struct wl1271 *wl)
    {
        disable_irq(wl->irq);
    }
    static void wl1271_sdio_enable_interrupts(struct wl1271 *wl)
    {
        enable_irq(wl->irq);
    }

这就是wl1271的 sdio 操作部分的代码了,很简单。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值