sdio.c (7828B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * wl12xx SDIO routines 4 * 5 * Copyright (C) 2005 Texas Instruments Incorporated 6 * Copyright (C) 2008 Google Inc 7 * Copyright (C) 2009 Bob Copeland (me@bobcopeland.com) 8 */ 9#include <linux/interrupt.h> 10#include <linux/module.h> 11#include <linux/mod_devicetable.h> 12#include <linux/mmc/sdio_func.h> 13#include <linux/mmc/sdio_ids.h> 14#include <linux/platform_device.h> 15#include <linux/wl12xx.h> 16#include <linux/irq.h> 17#include <linux/pm_runtime.h> 18#include <linux/of.h> 19#include <linux/of_irq.h> 20 21#include "wl1251.h" 22 23struct wl1251_sdio { 24 struct sdio_func *func; 25 u32 elp_val; 26}; 27 28static struct sdio_func *wl_to_func(struct wl1251 *wl) 29{ 30 struct wl1251_sdio *wl_sdio = wl->if_priv; 31 return wl_sdio->func; 32} 33 34static void wl1251_sdio_interrupt(struct sdio_func *func) 35{ 36 struct wl1251 *wl = sdio_get_drvdata(func); 37 38 wl1251_debug(DEBUG_IRQ, "IRQ"); 39 40 /* FIXME should be synchronous for sdio */ 41 ieee80211_queue_work(wl->hw, &wl->irq_work); 42} 43 44static const struct sdio_device_id wl1251_devices[] = { 45 { SDIO_DEVICE(SDIO_VENDOR_ID_TI_WL1251, SDIO_DEVICE_ID_TI_WL1251) }, 46 {} 47}; 48MODULE_DEVICE_TABLE(sdio, wl1251_devices); 49 50 51static void wl1251_sdio_read(struct wl1251 *wl, int addr, 52 void *buf, size_t len) 53{ 54 int ret; 55 struct sdio_func *func = wl_to_func(wl); 56 57 sdio_claim_host(func); 58 ret = sdio_memcpy_fromio(func, buf, addr, len); 59 if (ret) 60 wl1251_error("sdio read failed (%d)", ret); 61 sdio_release_host(func); 62} 63 64static void wl1251_sdio_write(struct wl1251 *wl, int addr, 65 void *buf, size_t len) 66{ 67 int ret; 68 struct sdio_func *func = wl_to_func(wl); 69 70 sdio_claim_host(func); 71 ret = sdio_memcpy_toio(func, addr, buf, len); 72 if (ret) 73 wl1251_error("sdio write failed (%d)", ret); 74 sdio_release_host(func); 75} 76 77static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val) 78{ 79 int ret = 0; 80 struct wl1251_sdio *wl_sdio = wl->if_priv; 81 struct sdio_func *func = wl_sdio->func; 82 83 /* 84 * The hardware only supports RAW (read after write) access for 85 * reading, regular sdio_readb won't work here (it interprets 86 * the unused bits of CMD52 as write data even if we send read 87 * request). 88 */ 89 sdio_claim_host(func); 90 *val = sdio_writeb_readb(func, wl_sdio->elp_val, addr, &ret); 91 sdio_release_host(func); 92 93 if (ret) 94 wl1251_error("sdio_readb failed (%d)", ret); 95} 96 97static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val) 98{ 99 int ret = 0; 100 struct wl1251_sdio *wl_sdio = wl->if_priv; 101 struct sdio_func *func = wl_sdio->func; 102 103 sdio_claim_host(func); 104 sdio_writeb(func, val, addr, &ret); 105 sdio_release_host(func); 106 107 if (ret) 108 wl1251_error("sdio_writeb failed (%d)", ret); 109 else 110 wl_sdio->elp_val = val; 111} 112 113static void wl1251_sdio_reset(struct wl1251 *wl) 114{ 115} 116 117static void wl1251_sdio_enable_irq(struct wl1251 *wl) 118{ 119 struct sdio_func *func = wl_to_func(wl); 120 121 sdio_claim_host(func); 122 sdio_claim_irq(func, wl1251_sdio_interrupt); 123 sdio_release_host(func); 124} 125 126static void wl1251_sdio_disable_irq(struct wl1251 *wl) 127{ 128 struct sdio_func *func = wl_to_func(wl); 129 130 sdio_claim_host(func); 131 sdio_release_irq(func); 132 sdio_release_host(func); 133} 134 135/* Interrupts when using dedicated WLAN_IRQ pin */ 136static irqreturn_t wl1251_line_irq(int irq, void *cookie) 137{ 138 struct wl1251 *wl = cookie; 139 140 ieee80211_queue_work(wl->hw, &wl->irq_work); 141 142 return IRQ_HANDLED; 143} 144 145static void wl1251_enable_line_irq(struct wl1251 *wl) 146{ 147 return enable_irq(wl->irq); 148} 149 150static void wl1251_disable_line_irq(struct wl1251 *wl) 151{ 152 return disable_irq(wl->irq); 153} 154 155static int wl1251_sdio_set_power(struct wl1251 *wl, bool enable) 156{ 157 struct sdio_func *func = wl_to_func(wl); 158 int ret; 159 160 if (enable) { 161 ret = pm_runtime_get_sync(&func->dev); 162 if (ret < 0) { 163 pm_runtime_put_sync(&func->dev); 164 goto out; 165 } 166 167 sdio_claim_host(func); 168 sdio_enable_func(func); 169 sdio_release_host(func); 170 } else { 171 sdio_claim_host(func); 172 sdio_disable_func(func); 173 sdio_release_host(func); 174 175 ret = pm_runtime_put_sync(&func->dev); 176 if (ret < 0) 177 goto out; 178 } 179 180out: 181 return ret; 182} 183 184static struct wl1251_if_operations wl1251_sdio_ops = { 185 .read = wl1251_sdio_read, 186 .write = wl1251_sdio_write, 187 .write_elp = wl1251_sdio_write_elp, 188 .read_elp = wl1251_sdio_read_elp, 189 .reset = wl1251_sdio_reset, 190 .power = wl1251_sdio_set_power, 191}; 192 193static int wl1251_sdio_probe(struct sdio_func *func, 194 const struct sdio_device_id *id) 195{ 196 int ret; 197 struct wl1251 *wl; 198 struct ieee80211_hw *hw; 199 struct wl1251_sdio *wl_sdio; 200 const struct wl1251_platform_data *wl1251_board_data; 201 struct device_node *np = func->dev.of_node; 202 203 hw = wl1251_alloc_hw(); 204 if (IS_ERR(hw)) 205 return PTR_ERR(hw); 206 207 wl = hw->priv; 208 209 wl_sdio = kzalloc(sizeof(*wl_sdio), GFP_KERNEL); 210 if (wl_sdio == NULL) { 211 ret = -ENOMEM; 212 goto out_free_hw; 213 } 214 215 sdio_claim_host(func); 216 ret = sdio_enable_func(func); 217 if (ret) 218 goto release; 219 220 sdio_set_block_size(func, 512); 221 sdio_release_host(func); 222 223 SET_IEEE80211_DEV(hw, &func->dev); 224 wl_sdio->func = func; 225 wl->if_priv = wl_sdio; 226 wl->if_ops = &wl1251_sdio_ops; 227 228 wl1251_board_data = wl1251_get_platform_data(); 229 if (!IS_ERR(wl1251_board_data)) { 230 wl->irq = wl1251_board_data->irq; 231 wl->use_eeprom = wl1251_board_data->use_eeprom; 232 } else if (np) { 233 wl->use_eeprom = of_property_read_bool(np, "ti,wl1251-has-eeprom"); 234 wl->irq = of_irq_get(np, 0); 235 if (wl->irq == -EPROBE_DEFER) { 236 ret = -EPROBE_DEFER; 237 goto disable; 238 } 239 } 240 241 if (wl->irq) { 242 irq_set_status_flags(wl->irq, IRQ_NOAUTOEN); 243 ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl); 244 if (ret < 0) { 245 wl1251_error("request_irq() failed: %d", ret); 246 goto disable; 247 } 248 249 irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); 250 251 wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq; 252 wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq; 253 254 wl1251_info("using dedicated interrupt line"); 255 } else { 256 wl1251_sdio_ops.enable_irq = wl1251_sdio_enable_irq; 257 wl1251_sdio_ops.disable_irq = wl1251_sdio_disable_irq; 258 259 wl1251_info("using SDIO interrupt"); 260 } 261 262 ret = wl1251_init_ieee80211(wl); 263 if (ret) 264 goto out_free_irq; 265 266 sdio_set_drvdata(func, wl); 267 268 /* Tell PM core that we don't need the card to be powered now */ 269 pm_runtime_put_noidle(&func->dev); 270 271 return ret; 272 273out_free_irq: 274 if (wl->irq) 275 free_irq(wl->irq, wl); 276disable: 277 sdio_claim_host(func); 278 sdio_disable_func(func); 279release: 280 sdio_release_host(func); 281 kfree(wl_sdio); 282out_free_hw: 283 wl1251_free_hw(wl); 284 return ret; 285} 286 287static void wl1251_sdio_remove(struct sdio_func *func) 288{ 289 struct wl1251 *wl = sdio_get_drvdata(func); 290 struct wl1251_sdio *wl_sdio = wl->if_priv; 291 292 /* Undo decrement done above in wl1251_probe */ 293 pm_runtime_get_noresume(&func->dev); 294 295 if (wl->irq) 296 free_irq(wl->irq, wl); 297 wl1251_free_hw(wl); 298 kfree(wl_sdio); 299 300 sdio_claim_host(func); 301 sdio_release_irq(func); 302 sdio_disable_func(func); 303 sdio_release_host(func); 304} 305 306static int wl1251_suspend(struct device *dev) 307{ 308 /* 309 * Tell MMC/SDIO core it's OK to power down the card 310 * (if it isn't already), but not to remove it completely. 311 */ 312 return 0; 313} 314 315static int wl1251_resume(struct device *dev) 316{ 317 return 0; 318} 319 320static const struct dev_pm_ops wl1251_sdio_pm_ops = { 321 .suspend = wl1251_suspend, 322 .resume = wl1251_resume, 323}; 324 325static struct sdio_driver wl1251_sdio_driver = { 326 .name = "wl1251_sdio", 327 .id_table = wl1251_devices, 328 .probe = wl1251_sdio_probe, 329 .remove = wl1251_sdio_remove, 330 .drv.pm = &wl1251_sdio_pm_ops, 331}; 332 333static int __init wl1251_sdio_init(void) 334{ 335 int err; 336 337 err = sdio_register_driver(&wl1251_sdio_driver); 338 if (err) 339 wl1251_error("failed to register sdio driver: %d", err); 340 return err; 341} 342 343static void __exit wl1251_sdio_exit(void) 344{ 345 sdio_unregister_driver(&wl1251_sdio_driver); 346 wl1251_notice("unloaded"); 347} 348 349module_init(wl1251_sdio_init); 350module_exit(wl1251_sdio_exit); 351 352MODULE_LICENSE("GPL"); 353MODULE_AUTHOR("Kalle Valo <kvalo@adurom.com>");