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