Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.4.
  1/*
  2 * This file is part of wl1251
  3 *
  4 * Copyright (C) 2008 Nokia Corporation
  5 *
  6 * This program is free software; you can redistribute it and/or
  7 * modify it under the terms of the GNU General Public License
  8 * version 2 as published by the Free Software Foundation.
  9 *
 10 * This program is distributed in the hope that it will be useful, but
 11 * WITHOUT ANY WARRANTY; without even the implied warranty of
 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13 * General Public License for more details.
 14 *
 15 * You should have received a copy of the GNU General Public License
 16 * along with this program; if not, write to the Free Software
 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 18 * 02110-1301 USA
 19 *
 20 */
 21
 22#include <linux/interrupt.h>
 23#include <linux/irq.h>
 24#include <linux/module.h>
 25#include <linux/slab.h>
 26#include <linux/crc7.h>
 27#include <linux/spi/spi.h>
 28#include <linux/wl12xx.h>
 29
 30#include "wl1251.h"
 31#include "reg.h"
 32#include "spi.h"
 33
 34static irqreturn_t wl1251_irq(int irq, void *cookie)
 35{
 36	struct wl1251 *wl;
 37
 38	wl1251_debug(DEBUG_IRQ, "IRQ");
 39
 40	wl = cookie;
 41
 42	ieee80211_queue_work(wl->hw, &wl->irq_work);
 43
 44	return IRQ_HANDLED;
 45}
 46
 47static struct spi_device *wl_to_spi(struct wl1251 *wl)
 48{
 49	return wl->if_priv;
 50}
 51
 52static void wl1251_spi_reset(struct wl1251 *wl)
 53{
 54	u8 *cmd;
 55	struct spi_transfer t;
 56	struct spi_message m;
 57
 58	cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
 59	if (!cmd) {
 60		wl1251_error("could not allocate cmd for spi reset");
 61		return;
 62	}
 63
 64	memset(&t, 0, sizeof(t));
 65	spi_message_init(&m);
 66
 67	memset(cmd, 0xff, WSPI_INIT_CMD_LEN);
 68
 69	t.tx_buf = cmd;
 70	t.len = WSPI_INIT_CMD_LEN;
 71	spi_message_add_tail(&t, &m);
 72
 73	spi_sync(wl_to_spi(wl), &m);
 74
 75	wl1251_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);
 76}
 77
 78static void wl1251_spi_wake(struct wl1251 *wl)
 79{
 80	u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd;
 81	struct spi_transfer t;
 82	struct spi_message m;
 83
 84	cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
 85	if (!cmd) {
 86		wl1251_error("could not allocate cmd for spi init");
 87		return;
 88	}
 89
 90	memset(crc, 0, sizeof(crc));
 91	memset(&t, 0, sizeof(t));
 92	spi_message_init(&m);
 93
 94	/*
 95	 * Set WSPI_INIT_COMMAND
 96	 * the data is being send from the MSB to LSB
 97	 */
 98	cmd[2] = 0xff;
 99	cmd[3] = 0xff;
100	cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX;
101	cmd[0] = 0;
102	cmd[7] = 0;
103	cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3;
104	cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN;
105
106	if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0)
107		cmd[5] |=  WSPI_INIT_CMD_DIS_FIXEDBUSY;
108	else
109		cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY;
110
111	cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS
112		| WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS;
113
114	crc[0] = cmd[1];
115	crc[1] = cmd[0];
116	crc[2] = cmd[7];
117	crc[3] = cmd[6];
118	crc[4] = cmd[5];
119
120	cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1;
121	cmd[4] |= WSPI_INIT_CMD_END;
122
123	t.tx_buf = cmd;
124	t.len = WSPI_INIT_CMD_LEN;
125	spi_message_add_tail(&t, &m);
126
127	spi_sync(wl_to_spi(wl), &m);
128
129	wl1251_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN);
130}
131
132static void wl1251_spi_reset_wake(struct wl1251 *wl)
133{
134	wl1251_spi_reset(wl);
135	wl1251_spi_wake(wl);
136}
137
138static void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf,
139			    size_t len)
140{
141	struct spi_transfer t[3];
142	struct spi_message m;
143	u8 *busy_buf;
144	u32 *cmd;
145
146	cmd = &wl->buffer_cmd;
147	busy_buf = wl->buffer_busyword;
148
149	*cmd = 0;
150	*cmd |= WSPI_CMD_READ;
151	*cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
152	*cmd |= addr & WSPI_CMD_BYTE_ADDR;
153
154	spi_message_init(&m);
155	memset(t, 0, sizeof(t));
156
157	t[0].tx_buf = cmd;
158	t[0].len = 4;
159	spi_message_add_tail(&t[0], &m);
160
161	/* Busy and non busy words read */
162	t[1].rx_buf = busy_buf;
163	t[1].len = WL1251_BUSY_WORD_LEN;
164	spi_message_add_tail(&t[1], &m);
165
166	t[2].rx_buf = buf;
167	t[2].len = len;
168	spi_message_add_tail(&t[2], &m);
169
170	spi_sync(wl_to_spi(wl), &m);
171
172	/* FIXME: check busy words */
173
174	wl1251_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd));
175	wl1251_dump(DEBUG_SPI, "spi_read buf <- ", buf, len);
176}
177
178static void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf,
179			     size_t len)
180{
181	struct spi_transfer t[2];
182	struct spi_message m;
183	u32 *cmd;
184
185	cmd = &wl->buffer_cmd;
186
187	*cmd = 0;
188	*cmd |= WSPI_CMD_WRITE;
189	*cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
190	*cmd |= addr & WSPI_CMD_BYTE_ADDR;
191
192	spi_message_init(&m);
193	memset(t, 0, sizeof(t));
194
195	t[0].tx_buf = cmd;
196	t[0].len = sizeof(*cmd);
197	spi_message_add_tail(&t[0], &m);
198
199	t[1].tx_buf = buf;
200	t[1].len = len;
201	spi_message_add_tail(&t[1], &m);
202
203	spi_sync(wl_to_spi(wl), &m);
204
205	wl1251_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
206	wl1251_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
207}
208
209static void wl1251_spi_enable_irq(struct wl1251 *wl)
210{
211	return enable_irq(wl->irq);
212}
213
214static void wl1251_spi_disable_irq(struct wl1251 *wl)
215{
216	return disable_irq(wl->irq);
217}
218
219static int wl1251_spi_set_power(struct wl1251 *wl, bool enable)
220{
221	if (wl->set_power)
222		wl->set_power(enable);
223
224	return 0;
225}
226
227static const struct wl1251_if_operations wl1251_spi_ops = {
228	.read = wl1251_spi_read,
229	.write = wl1251_spi_write,
230	.reset = wl1251_spi_reset_wake,
231	.enable_irq = wl1251_spi_enable_irq,
232	.disable_irq = wl1251_spi_disable_irq,
233	.power = wl1251_spi_set_power,
234};
235
236static int __devinit wl1251_spi_probe(struct spi_device *spi)
237{
238	struct wl12xx_platform_data *pdata;
239	struct ieee80211_hw *hw;
240	struct wl1251 *wl;
241	int ret;
242
243	pdata = spi->dev.platform_data;
244	if (!pdata) {
245		wl1251_error("no platform data");
246		return -ENODEV;
247	}
248
249	hw = wl1251_alloc_hw();
250	if (IS_ERR(hw))
251		return PTR_ERR(hw);
252
253	wl = hw->priv;
254
255	SET_IEEE80211_DEV(hw, &spi->dev);
256	dev_set_drvdata(&spi->dev, wl);
257	wl->if_priv = spi;
258	wl->if_ops = &wl1251_spi_ops;
259
260	/* This is the only SPI value that we need to set here, the rest
261	 * comes from the board-peripherals file */
262	spi->bits_per_word = 32;
263
264	ret = spi_setup(spi);
265	if (ret < 0) {
266		wl1251_error("spi_setup failed");
267		goto out_free;
268	}
269
270	wl->set_power = pdata->set_power;
271	if (!wl->set_power) {
272		wl1251_error("set power function missing in platform data");
273		return -ENODEV;
274	}
275
276	wl->irq = spi->irq;
277	if (wl->irq < 0) {
278		wl1251_error("irq missing in platform data");
279		return -ENODEV;
280	}
281
282	wl->use_eeprom = pdata->use_eeprom;
283
284	ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl);
285	if (ret < 0) {
286		wl1251_error("request_irq() failed: %d", ret);
287		goto out_free;
288	}
289
290	irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
291
292	disable_irq(wl->irq);
293
294	ret = wl1251_init_ieee80211(wl);
295	if (ret)
296		goto out_irq;
297
298	return 0;
299
300 out_irq:
301	free_irq(wl->irq, wl);
302
303 out_free:
304	ieee80211_free_hw(hw);
305
306	return ret;
307}
308
309static int __devexit wl1251_spi_remove(struct spi_device *spi)
310{
311	struct wl1251 *wl = dev_get_drvdata(&spi->dev);
312
313	free_irq(wl->irq, wl);
314	wl1251_free_hw(wl);
315
316	return 0;
317}
318
319static struct spi_driver wl1251_spi_driver = {
320	.driver = {
321		.name		= DRIVER_NAME,
322		.bus		= &spi_bus_type,
323		.owner		= THIS_MODULE,
324	},
325
326	.probe		= wl1251_spi_probe,
327	.remove		= __devexit_p(wl1251_spi_remove),
328};
329
330static int __init wl1251_spi_init(void)
331{
332	int ret;
333
334	ret = spi_register_driver(&wl1251_spi_driver);
335	if (ret < 0) {
336		wl1251_error("failed to register spi driver: %d", ret);
337		goto out;
338	}
339
340out:
341	return ret;
342}
343
344static void __exit wl1251_spi_exit(void)
345{
346	spi_unregister_driver(&wl1251_spi_driver);
347
348	wl1251_notice("unloaded");
349}
350
351module_init(wl1251_spi_init);
352module_exit(wl1251_spi_exit);
353
354MODULE_LICENSE("GPL");
355MODULE_AUTHOR("Kalle Valo <kvalo@adurom.com>");
356MODULE_ALIAS("spi:wl1251");