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 内容:
wl1271_devices: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_sdio_pm_ops: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);
2. wl1271_probe():static const struct dev_pm_ops wl1271_sdio_pm_ops = { .suspend = wl1271_suspend, .resume = wl1271_resume, };
3. struct wl1271_if_operations sdio_ops :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; }
a. wl1271_sdio_raw_read():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 };
b. wl1271_sdio_raw_write() ,内容和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); }
c. wl1271_sdio_set_power() :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); }
d. wl1271_sdio_wl_to_dev():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 }
e. wl1271_sdio_disable_interrupts()/wl1271_sdio_enable_interrupts():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; }
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 操作部分的代码了,很简单。