sdio.c 7.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
/*
 * This file is part of wl1271
 *
 * Copyright (C) 2009-2010 Nokia Corporation
 *
 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include <linux/irq.h>
#include <linux/module.h>
#include <linux/crc7.h>
#include <linux/vmalloc.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/card.h>
31
#include <linux/gpio.h>
32
#include <linux/wl12xx.h>
O
Ohad Ben-Cohen 已提交
33
#include <linux/pm_runtime.h>
34

S
Shahar Levi 已提交
35
#include "wl12xx.h"
36
#include "wl12xx_80211.h"
S
Shahar Levi 已提交
37
#include "io.h"
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76

#ifndef SDIO_VENDOR_ID_TI
#define SDIO_VENDOR_ID_TI		0x0097
#endif

#ifndef SDIO_DEVICE_ID_TI_WL1271
#define SDIO_DEVICE_ID_TI_WL1271	0x4076
#endif

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);

static inline struct sdio_func *wl_to_func(struct wl1271 *wl)
{
	return wl->if_priv;
}

static struct device *wl1271_sdio_wl_to_dev(struct wl1271 *wl)
{
	return &(wl_to_func(wl)->dev);
}

static irqreturn_t wl1271_irq(int irq, void *cookie)
{
	struct wl1271 *wl = cookie;
	unsigned long flags;

	wl1271_debug(DEBUG_IRQ, "IRQ");

	/* complete the ELP completion */
	spin_lock_irqsave(&wl->wl_lock, flags);
	if (wl->elp_compl) {
		complete(wl->elp_compl);
		wl->elp_compl = NULL;
	}

77 78 79
	if (!test_and_set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags))
		ieee80211_queue_work(wl->hw, &wl->irq_work);
	set_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags);
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
	spin_unlock_irqrestore(&wl->wl_lock, flags);

	return IRQ_HANDLED;
}

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);
}

static void wl1271_sdio_reset(struct wl1271 *wl)
{
}

static void wl1271_sdio_init(struct wl1271 *wl)
{
}

static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,
T
Teemu Paasikivi 已提交
104
				 size_t len, bool fixed)
105 106 107 108
{
	int ret;
	struct sdio_func *func = wl_to_func(wl);

109 110
	sdio_claim_host(func);

111 112
	if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
		((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret);
T
Teemu Paasikivi 已提交
113
		wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x",
114 115 116 117 118 119 120
			     addr, ((u8 *)buf)[0]);
	} else {
		if (fixed)
			ret = sdio_readsb(func, buf, addr, len);
		else
			ret = sdio_memcpy_fromio(func, buf, addr, len);

121
		wl1271_debug(DEBUG_SDIO, "sdio read 53 addr 0x%x, %zu bytes",
122
			     addr, len);
T
Teemu Paasikivi 已提交
123
		wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len);
124 125
	}

126 127
	sdio_release_host(func);

128 129 130 131 132
	if (ret)
		wl1271_error("sdio read failed (%d)", ret);
}

static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf,
T
Teemu Paasikivi 已提交
133
				  size_t len, bool fixed)
134 135 136 137
{
	int ret;
	struct sdio_func *func = wl_to_func(wl);

138 139
	sdio_claim_host(func);

140 141
	if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
		sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret);
T
Teemu Paasikivi 已提交
142
		wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x",
143 144
			     addr, ((u8 *)buf)[0]);
	} else {
145
		wl1271_debug(DEBUG_SDIO, "sdio write 53 addr 0x%x, %zu bytes",
146
			     addr, len);
T
Teemu Paasikivi 已提交
147
		wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len);
148 149 150 151 152 153

		if (fixed)
			ret = sdio_writesb(func, addr, buf, len);
		else
			ret = sdio_memcpy_toio(func, addr, buf, len);
	}
154 155 156

	sdio_release_host(func);

157 158
	if (ret)
		wl1271_error("sdio write failed (%d)", ret);
159 160
}

161
static int wl1271_sdio_power_on(struct wl1271 *wl)
162 163
{
	struct sdio_func *func = wl_to_func(wl);
O
Ohad Ben-Cohen 已提交
164 165 166 167 168 169
	int ret;

	/* Power up the card */
	ret = pm_runtime_get_sync(&func->dev);
	if (ret < 0)
		goto out;
170

171 172 173
	sdio_claim_host(func);
	sdio_enable_func(func);
	sdio_release_host(func);
174

O
Ohad Ben-Cohen 已提交
175 176
out:
	return ret;
177 178
}

179
static int wl1271_sdio_power_off(struct wl1271 *wl)
180 181 182 183 184 185
{
	struct sdio_func *func = wl_to_func(wl);

	sdio_claim_host(func);
	sdio_disable_func(func);
	sdio_release_host(func);
186

O
Ohad Ben-Cohen 已提交
187 188
	/* Power down the card */
	return pm_runtime_put_sync(&func->dev);
189 190
}

191
static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
192
{
193
	if (enable)
194
		return wl1271_sdio_power_on(wl);
195
	else
196
		return wl1271_sdio_power_off(wl);
197 198
}

199 200 201 202 203
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,
204
	.power		= wl1271_sdio_set_power,
205 206 207 208 209 210 211 212 213
	.dev		= wl1271_sdio_wl_to_dev,
	.enable_irq	= wl1271_sdio_enable_interrupts,
	.disable_irq	= wl1271_sdio_disable_interrupts
};

static int __devinit wl1271_probe(struct sdio_func *func,
				  const struct sdio_device_id *id)
{
	struct ieee80211_hw *hw;
214
	const struct wl12xx_platform_data *wlan_data;
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
	struct wl1271 *wl;
	int ret;

	/* We are only able to handle the wlan function */
	if (func->num != 0x02)
		return -ENODEV;

	hw = wl1271_alloc_hw();
	if (IS_ERR(hw))
		return PTR_ERR(hw);

	wl = hw->priv;

	wl->if_priv = func;
	wl->if_ops = &sdio_ops;

	/* Grab access to FN0 for ELP reg. */
	func->card->quirks |= MMC_QUIRK_LENIENT_FN0;

234 235 236 237
	wlan_data = wl12xx_get_platform_data();
	if (IS_ERR(wlan_data)) {
		ret = PTR_ERR(wlan_data);
		wl1271_error("missing wlan platform data: %d", ret);
238 239 240
		goto out_free;
	}

241
	wl->irq = wlan_data->irq;
242
	wl->ref_clock = wlan_data->board_ref_clock;
243

244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
	ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl);
	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);

	ret = wl1271_init_ieee80211(wl);
	if (ret)
		goto out_irq;

	ret = wl1271_register_hw(wl);
	if (ret)
		goto out_irq;

262 263
	sdio_set_drvdata(func, wl);

O
Ohad Ben-Cohen 已提交
264 265 266
	/* Tell PM core that we don't need the card to be powered now */
	pm_runtime_put_noidle(&func->dev);

267 268 269 270 271 272 273 274 275
	wl1271_notice("initialized");

	return 0;

 out_irq:
	free_irq(wl->irq, wl);


 out_free:
276
	wl1271_free_hw(wl);
277 278 279 280 281 282 283 284

	return ret;
}

static void __devexit wl1271_remove(struct sdio_func *func)
{
	struct wl1271 *wl = sdio_get_drvdata(func);

O
Ohad Ben-Cohen 已提交
285 286 287
	/* Undo decrement done above in wl1271_probe */
	pm_runtime_get_noresume(&func->dev);

288
	wl1271_unregister_hw(wl);
289
	free_irq(wl->irq, wl);
290
	wl1271_free_hw(wl);
291 292
}

293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
static int wl1271_suspend(struct device *dev)
{
	/* Tell MMC/SDIO core it's OK to power down the card
	 * (if it isn't already), but not to remove it completely */
	return 0;
}

static int wl1271_resume(struct device *dev)
{
	return 0;
}

static const struct dev_pm_ops wl1271_sdio_pm_ops = {
	.suspend	= wl1271_suspend,
	.resume		= wl1271_resume,
};

310
static struct sdio_driver wl1271_sdio_driver = {
311
	.name		= "wl1271_sdio",
312 313 314
	.id_table	= wl1271_devices,
	.probe		= wl1271_probe,
	.remove		= __devexit_p(wl1271_remove),
315 316 317
	.drv = {
		.pm = &wl1271_sdio_pm_ops,
	},
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
};

static int __init wl1271_init(void)
{
	int ret;

	ret = sdio_register_driver(&wl1271_sdio_driver);
	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);

	wl1271_notice("unloaded");
}

module_init(wl1271_init);
module_exit(wl1271_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
MODULE_FIRMWARE(WL1271_FW_NAME);
348
MODULE_FIRMWARE(WL1271_AP_FW_NAME);