xref: /linux/drivers/net/wireless/intersil/p54/p54spi.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
12b27bdccSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2d3466830SKalle Valo /*
3d3466830SKalle Valo  * Copyright (C) 2008 Christian Lamparter <chunkeey@web.de>
4d3466830SKalle Valo  * Copyright 2008       Johannes Berg <johannes@sipsolutions.net>
5d3466830SKalle Valo  *
6d3466830SKalle Valo  * This driver is a port from stlc45xx:
7d3466830SKalle Valo  *	Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
8d3466830SKalle Valo  */
9d3466830SKalle Valo 
10d3466830SKalle Valo #include <linux/module.h>
11d3466830SKalle Valo #include <linux/platform_device.h>
12d3466830SKalle Valo #include <linux/interrupt.h>
13d3466830SKalle Valo #include <linux/firmware.h>
14d3466830SKalle Valo #include <linux/delay.h>
15d3466830SKalle Valo #include <linux/irq.h>
16d3466830SKalle Valo #include <linux/spi/spi.h>
17d3466830SKalle Valo #include <linux/etherdevice.h>
18d3466830SKalle Valo #include <linux/gpio.h>
19d3466830SKalle Valo #include <linux/slab.h>
20d3466830SKalle Valo 
21d3466830SKalle Valo #include "p54spi.h"
22d3466830SKalle Valo #include "p54.h"
23d3466830SKalle Valo 
24d3466830SKalle Valo #include "lmac.h"
25d3466830SKalle Valo 
26d3466830SKalle Valo #ifdef CONFIG_P54_SPI_DEFAULT_EEPROM
27d3466830SKalle Valo #include "p54spi_eeprom.h"
28d3466830SKalle Valo #endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */
29d3466830SKalle Valo 
30d3466830SKalle Valo MODULE_FIRMWARE("3826.arm");
318d0c7e19SJuerg Haefliger MODULE_FIRMWARE("3826.eeprom");
32d3466830SKalle Valo 
33d3466830SKalle Valo /* gpios should be handled in board files and provided via platform data,
34d3466830SKalle Valo  * but because it's currently impossible for p54spi to have a header file
35d3466830SKalle Valo  * in include/linux, let's use module paramaters for now
36d3466830SKalle Valo  */
37d3466830SKalle Valo 
38d3466830SKalle Valo static int p54spi_gpio_power = 97;
39d3466830SKalle Valo module_param(p54spi_gpio_power, int, 0444);
40d3466830SKalle Valo MODULE_PARM_DESC(p54spi_gpio_power, "gpio number for power line");
41d3466830SKalle Valo 
42d3466830SKalle Valo static int p54spi_gpio_irq = 87;
43d3466830SKalle Valo module_param(p54spi_gpio_irq, int, 0444);
44d3466830SKalle Valo MODULE_PARM_DESC(p54spi_gpio_irq, "gpio number for irq line");
45d3466830SKalle Valo 
p54spi_spi_read(struct p54s_priv * priv,u8 address,void * buf,size_t len)46d3466830SKalle Valo static void p54spi_spi_read(struct p54s_priv *priv, u8 address,
47d3466830SKalle Valo 			      void *buf, size_t len)
48d3466830SKalle Valo {
49d3466830SKalle Valo 	struct spi_transfer t[2];
50d3466830SKalle Valo 	struct spi_message m;
51d3466830SKalle Valo 	__le16 addr;
52d3466830SKalle Valo 
53d3466830SKalle Valo 	/* We first push the address */
54d3466830SKalle Valo 	addr = cpu_to_le16(address << 8 | SPI_ADRS_READ_BIT_15);
55d3466830SKalle Valo 
56d3466830SKalle Valo 	spi_message_init(&m);
57d3466830SKalle Valo 	memset(t, 0, sizeof(t));
58d3466830SKalle Valo 
59d3466830SKalle Valo 	t[0].tx_buf = &addr;
60d3466830SKalle Valo 	t[0].len = sizeof(addr);
61d3466830SKalle Valo 	spi_message_add_tail(&t[0], &m);
62d3466830SKalle Valo 
63d3466830SKalle Valo 	t[1].rx_buf = buf;
64d3466830SKalle Valo 	t[1].len = len;
65d3466830SKalle Valo 	spi_message_add_tail(&t[1], &m);
66d3466830SKalle Valo 
67d3466830SKalle Valo 	spi_sync(priv->spi, &m);
68d3466830SKalle Valo }
69d3466830SKalle Valo 
70d3466830SKalle Valo 
p54spi_spi_write(struct p54s_priv * priv,u8 address,const void * buf,size_t len)71d3466830SKalle Valo static void p54spi_spi_write(struct p54s_priv *priv, u8 address,
72d3466830SKalle Valo 			     const void *buf, size_t len)
73d3466830SKalle Valo {
74d3466830SKalle Valo 	struct spi_transfer t[3];
75d3466830SKalle Valo 	struct spi_message m;
76d3466830SKalle Valo 	__le16 addr;
77d3466830SKalle Valo 
78d3466830SKalle Valo 	/* We first push the address */
79d3466830SKalle Valo 	addr = cpu_to_le16(address << 8);
80d3466830SKalle Valo 
81d3466830SKalle Valo 	spi_message_init(&m);
82d3466830SKalle Valo 	memset(t, 0, sizeof(t));
83d3466830SKalle Valo 
84d3466830SKalle Valo 	t[0].tx_buf = &addr;
85d3466830SKalle Valo 	t[0].len = sizeof(addr);
86d3466830SKalle Valo 	spi_message_add_tail(&t[0], &m);
87d3466830SKalle Valo 
88d3466830SKalle Valo 	t[1].tx_buf = buf;
89d3466830SKalle Valo 	t[1].len = len & ~1;
90d3466830SKalle Valo 	spi_message_add_tail(&t[1], &m);
91d3466830SKalle Valo 
92d3466830SKalle Valo 	if (len % 2) {
93d3466830SKalle Valo 		__le16 last_word;
94d3466830SKalle Valo 		last_word = cpu_to_le16(((u8 *)buf)[len - 1]);
95d3466830SKalle Valo 
96d3466830SKalle Valo 		t[2].tx_buf = &last_word;
97d3466830SKalle Valo 		t[2].len = sizeof(last_word);
98d3466830SKalle Valo 		spi_message_add_tail(&t[2], &m);
99d3466830SKalle Valo 	}
100d3466830SKalle Valo 
101d3466830SKalle Valo 	spi_sync(priv->spi, &m);
102d3466830SKalle Valo }
103d3466830SKalle Valo 
p54spi_read32(struct p54s_priv * priv,u8 addr)104d3466830SKalle Valo static u32 p54spi_read32(struct p54s_priv *priv, u8 addr)
105d3466830SKalle Valo {
106d3466830SKalle Valo 	__le32 val;
107d3466830SKalle Valo 
108d3466830SKalle Valo 	p54spi_spi_read(priv, addr, &val, sizeof(val));
109d3466830SKalle Valo 
110d3466830SKalle Valo 	return le32_to_cpu(val);
111d3466830SKalle Valo }
112d3466830SKalle Valo 
p54spi_write16(struct p54s_priv * priv,u8 addr,__le16 val)113d3466830SKalle Valo static inline void p54spi_write16(struct p54s_priv *priv, u8 addr, __le16 val)
114d3466830SKalle Valo {
115d3466830SKalle Valo 	p54spi_spi_write(priv, addr, &val, sizeof(val));
116d3466830SKalle Valo }
117d3466830SKalle Valo 
p54spi_write32(struct p54s_priv * priv,u8 addr,__le32 val)118d3466830SKalle Valo static inline void p54spi_write32(struct p54s_priv *priv, u8 addr, __le32 val)
119d3466830SKalle Valo {
120d3466830SKalle Valo 	p54spi_spi_write(priv, addr, &val, sizeof(val));
121d3466830SKalle Valo }
122d3466830SKalle Valo 
p54spi_wait_bit(struct p54s_priv * priv,u16 reg,u32 bits)123d3466830SKalle Valo static int p54spi_wait_bit(struct p54s_priv *priv, u16 reg, u32 bits)
124d3466830SKalle Valo {
125d3466830SKalle Valo 	int i;
126d3466830SKalle Valo 
127d3466830SKalle Valo 	for (i = 0; i < 2000; i++) {
128d3466830SKalle Valo 		u32 buffer = p54spi_read32(priv, reg);
129d3466830SKalle Valo 		if ((buffer & bits) == bits)
130d3466830SKalle Valo 			return 1;
131d3466830SKalle Valo 	}
132d3466830SKalle Valo 	return 0;
133d3466830SKalle Valo }
134d3466830SKalle Valo 
p54spi_spi_write_dma(struct p54s_priv * priv,__le32 base,const void * buf,size_t len)135d3466830SKalle Valo static int p54spi_spi_write_dma(struct p54s_priv *priv, __le32 base,
136d3466830SKalle Valo 				const void *buf, size_t len)
137d3466830SKalle Valo {
138d3466830SKalle Valo 	if (!p54spi_wait_bit(priv, SPI_ADRS_DMA_WRITE_CTRL, HOST_ALLOWED)) {
139d3466830SKalle Valo 		dev_err(&priv->spi->dev, "spi_write_dma not allowed "
140d3466830SKalle Valo 			"to DMA write.\n");
141d3466830SKalle Valo 		return -EAGAIN;
142d3466830SKalle Valo 	}
143d3466830SKalle Valo 
144d3466830SKalle Valo 	p54spi_write16(priv, SPI_ADRS_DMA_WRITE_CTRL,
145d3466830SKalle Valo 		       cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE));
146d3466830SKalle Valo 
147d3466830SKalle Valo 	p54spi_write16(priv, SPI_ADRS_DMA_WRITE_LEN, cpu_to_le16(len));
148d3466830SKalle Valo 	p54spi_write32(priv, SPI_ADRS_DMA_WRITE_BASE, base);
149d3466830SKalle Valo 	p54spi_spi_write(priv, SPI_ADRS_DMA_DATA, buf, len);
150d3466830SKalle Valo 	return 0;
151d3466830SKalle Valo }
152d3466830SKalle Valo 
p54spi_request_firmware(struct ieee80211_hw * dev)153d3466830SKalle Valo static int p54spi_request_firmware(struct ieee80211_hw *dev)
154d3466830SKalle Valo {
155d3466830SKalle Valo 	struct p54s_priv *priv = dev->priv;
156d3466830SKalle Valo 	int ret;
157d3466830SKalle Valo 
158d3466830SKalle Valo 	/* FIXME: should driver use it's own struct device? */
159d3466830SKalle Valo 	ret = request_firmware(&priv->firmware, "3826.arm", &priv->spi->dev);
160d3466830SKalle Valo 
161d3466830SKalle Valo 	if (ret < 0) {
162d3466830SKalle Valo 		dev_err(&priv->spi->dev, "request_firmware() failed: %d", ret);
163d3466830SKalle Valo 		return ret;
164d3466830SKalle Valo 	}
165d3466830SKalle Valo 
166d3466830SKalle Valo 	ret = p54_parse_firmware(dev, priv->firmware);
167d3466830SKalle Valo 	if (ret) {
16883781f01SChristophe JAILLET 		/* the firmware is released by the caller */
169d3466830SKalle Valo 		return ret;
170d3466830SKalle Valo 	}
171d3466830SKalle Valo 
172d3466830SKalle Valo 	return 0;
173d3466830SKalle Valo }
174d3466830SKalle Valo 
p54spi_request_eeprom(struct ieee80211_hw * dev)175d3466830SKalle Valo static int p54spi_request_eeprom(struct ieee80211_hw *dev)
176d3466830SKalle Valo {
177d3466830SKalle Valo 	struct p54s_priv *priv = dev->priv;
178d3466830SKalle Valo 	const struct firmware *eeprom;
179d3466830SKalle Valo 	int ret;
180d3466830SKalle Valo 
181d3466830SKalle Valo 	/* allow users to customize their eeprom.
182d3466830SKalle Valo 	 */
183d3466830SKalle Valo 
184d3466830SKalle Valo 	ret = request_firmware_direct(&eeprom, "3826.eeprom", &priv->spi->dev);
185d3466830SKalle Valo 	if (ret < 0) {
186d3466830SKalle Valo #ifdef CONFIG_P54_SPI_DEFAULT_EEPROM
187d3466830SKalle Valo 		dev_info(&priv->spi->dev, "loading default eeprom...\n");
188d3466830SKalle Valo 		ret = p54_parse_eeprom(dev, (void *) p54spi_eeprom,
189d3466830SKalle Valo 				       sizeof(p54spi_eeprom));
190d3466830SKalle Valo #else
191d3466830SKalle Valo 		dev_err(&priv->spi->dev, "Failed to request user eeprom\n");
192d3466830SKalle Valo #endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */
193d3466830SKalle Valo 	} else {
194d3466830SKalle Valo 		dev_info(&priv->spi->dev, "loading user eeprom...\n");
195d3466830SKalle Valo 		ret = p54_parse_eeprom(dev, (void *) eeprom->data,
196d3466830SKalle Valo 				       (int)eeprom->size);
197d3466830SKalle Valo 		release_firmware(eeprom);
198d3466830SKalle Valo 	}
199d3466830SKalle Valo 	return ret;
200d3466830SKalle Valo }
201d3466830SKalle Valo 
p54spi_upload_firmware(struct ieee80211_hw * dev)202d3466830SKalle Valo static int p54spi_upload_firmware(struct ieee80211_hw *dev)
203d3466830SKalle Valo {
204d3466830SKalle Valo 	struct p54s_priv *priv = dev->priv;
205d3466830SKalle Valo 	unsigned long fw_len, _fw_len;
206d3466830SKalle Valo 	unsigned int offset = 0;
207d3466830SKalle Valo 	int err = 0;
208d3466830SKalle Valo 	u8 *fw;
209d3466830SKalle Valo 
210d3466830SKalle Valo 	fw_len = priv->firmware->size;
211d3466830SKalle Valo 	fw = kmemdup(priv->firmware->data, fw_len, GFP_KERNEL);
212d3466830SKalle Valo 	if (!fw)
213d3466830SKalle Valo 		return -ENOMEM;
214d3466830SKalle Valo 
215d3466830SKalle Valo 	/* stop the device */
216d3466830SKalle Valo 	p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16(
217d3466830SKalle Valo 		       SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_HOST_RESET |
218d3466830SKalle Valo 		       SPI_CTRL_STAT_START_HALTED));
219d3466830SKalle Valo 
220d3466830SKalle Valo 	msleep(TARGET_BOOT_SLEEP);
221d3466830SKalle Valo 
222d3466830SKalle Valo 	p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16(
223d3466830SKalle Valo 		       SPI_CTRL_STAT_HOST_OVERRIDE |
224d3466830SKalle Valo 		       SPI_CTRL_STAT_START_HALTED));
225d3466830SKalle Valo 
226d3466830SKalle Valo 	msleep(TARGET_BOOT_SLEEP);
227d3466830SKalle Valo 
228d3466830SKalle Valo 	while (fw_len > 0) {
229d3466830SKalle Valo 		_fw_len = min_t(long, fw_len, SPI_MAX_PACKET_SIZE);
230d3466830SKalle Valo 
231d3466830SKalle Valo 		err = p54spi_spi_write_dma(priv, cpu_to_le32(
232d3466830SKalle Valo 					   ISL38XX_DEV_FIRMWARE_ADDR + offset),
233d3466830SKalle Valo 					   (fw + offset), _fw_len);
234d3466830SKalle Valo 		if (err < 0)
235d3466830SKalle Valo 			goto out;
236d3466830SKalle Valo 
237d3466830SKalle Valo 		fw_len -= _fw_len;
238d3466830SKalle Valo 		offset += _fw_len;
239d3466830SKalle Valo 	}
240d3466830SKalle Valo 
241d3466830SKalle Valo 	BUG_ON(fw_len != 0);
242d3466830SKalle Valo 
243d3466830SKalle Valo 	/* enable host interrupts */
244d3466830SKalle Valo 	p54spi_write32(priv, SPI_ADRS_HOST_INT_EN,
245d3466830SKalle Valo 		       cpu_to_le32(SPI_HOST_INTS_DEFAULT));
246d3466830SKalle Valo 
247d3466830SKalle Valo 	/* boot the device */
248d3466830SKalle Valo 	p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16(
249d3466830SKalle Valo 		       SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_HOST_RESET |
250d3466830SKalle Valo 		       SPI_CTRL_STAT_RAM_BOOT));
251d3466830SKalle Valo 
252d3466830SKalle Valo 	msleep(TARGET_BOOT_SLEEP);
253d3466830SKalle Valo 
254d3466830SKalle Valo 	p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16(
255d3466830SKalle Valo 		       SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_RAM_BOOT));
256d3466830SKalle Valo 	msleep(TARGET_BOOT_SLEEP);
257d3466830SKalle Valo 
258d3466830SKalle Valo out:
259d3466830SKalle Valo 	kfree(fw);
260d3466830SKalle Valo 	return err;
261d3466830SKalle Valo }
262d3466830SKalle Valo 
p54spi_power_off(struct p54s_priv * priv)263d3466830SKalle Valo static void p54spi_power_off(struct p54s_priv *priv)
264d3466830SKalle Valo {
265d3466830SKalle Valo 	disable_irq(gpio_to_irq(p54spi_gpio_irq));
266d3466830SKalle Valo 	gpio_set_value(p54spi_gpio_power, 0);
267d3466830SKalle Valo }
268d3466830SKalle Valo 
p54spi_power_on(struct p54s_priv * priv)269d3466830SKalle Valo static void p54spi_power_on(struct p54s_priv *priv)
270d3466830SKalle Valo {
271d3466830SKalle Valo 	gpio_set_value(p54spi_gpio_power, 1);
272d3466830SKalle Valo 	enable_irq(gpio_to_irq(p54spi_gpio_irq));
273d3466830SKalle Valo 
274d3466830SKalle Valo 	/* need to wait a while before device can be accessed, the length
275d3466830SKalle Valo 	 * is just a guess
276d3466830SKalle Valo 	 */
277d3466830SKalle Valo 	msleep(10);
278d3466830SKalle Valo }
279d3466830SKalle Valo 
p54spi_int_ack(struct p54s_priv * priv,u32 val)280d3466830SKalle Valo static inline void p54spi_int_ack(struct p54s_priv *priv, u32 val)
281d3466830SKalle Valo {
282d3466830SKalle Valo 	p54spi_write32(priv, SPI_ADRS_HOST_INT_ACK, cpu_to_le32(val));
283d3466830SKalle Valo }
284d3466830SKalle Valo 
p54spi_wakeup(struct p54s_priv * priv)285d3466830SKalle Valo static int p54spi_wakeup(struct p54s_priv *priv)
286d3466830SKalle Valo {
287d3466830SKalle Valo 	/* wake the chip */
288d3466830SKalle Valo 	p54spi_write32(priv, SPI_ADRS_ARM_INTERRUPTS,
289d3466830SKalle Valo 		       cpu_to_le32(SPI_TARGET_INT_WAKEUP));
290d3466830SKalle Valo 
291d3466830SKalle Valo 	/* And wait for the READY interrupt */
292d3466830SKalle Valo 	if (!p54spi_wait_bit(priv, SPI_ADRS_HOST_INTERRUPTS,
293d3466830SKalle Valo 			     SPI_HOST_INT_READY)) {
294d3466830SKalle Valo 		dev_err(&priv->spi->dev, "INT_READY timeout\n");
295d3466830SKalle Valo 		return -EBUSY;
296d3466830SKalle Valo 	}
297d3466830SKalle Valo 
298d3466830SKalle Valo 	p54spi_int_ack(priv, SPI_HOST_INT_READY);
299d3466830SKalle Valo 	return 0;
300d3466830SKalle Valo }
301d3466830SKalle Valo 
p54spi_sleep(struct p54s_priv * priv)302d3466830SKalle Valo static inline void p54spi_sleep(struct p54s_priv *priv)
303d3466830SKalle Valo {
304d3466830SKalle Valo 	p54spi_write32(priv, SPI_ADRS_ARM_INTERRUPTS,
305d3466830SKalle Valo 		       cpu_to_le32(SPI_TARGET_INT_SLEEP));
306d3466830SKalle Valo }
307d3466830SKalle Valo 
p54spi_int_ready(struct p54s_priv * priv)308d3466830SKalle Valo static void p54spi_int_ready(struct p54s_priv *priv)
309d3466830SKalle Valo {
310d3466830SKalle Valo 	p54spi_write32(priv, SPI_ADRS_HOST_INT_EN, cpu_to_le32(
311d3466830SKalle Valo 		       SPI_HOST_INT_UPDATE | SPI_HOST_INT_SW_UPDATE));
312d3466830SKalle Valo 
313d3466830SKalle Valo 	switch (priv->fw_state) {
314d3466830SKalle Valo 	case FW_STATE_BOOTING:
315d3466830SKalle Valo 		priv->fw_state = FW_STATE_READY;
316d3466830SKalle Valo 		complete(&priv->fw_comp);
317d3466830SKalle Valo 		break;
318d3466830SKalle Valo 	case FW_STATE_RESETTING:
319d3466830SKalle Valo 		priv->fw_state = FW_STATE_READY;
320d3466830SKalle Valo 		/* TODO: reinitialize state */
321d3466830SKalle Valo 		break;
322d3466830SKalle Valo 	default:
323d3466830SKalle Valo 		break;
324d3466830SKalle Valo 	}
325d3466830SKalle Valo }
326d3466830SKalle Valo 
p54spi_rx(struct p54s_priv * priv)327d3466830SKalle Valo static int p54spi_rx(struct p54s_priv *priv)
328d3466830SKalle Valo {
329d3466830SKalle Valo 	struct sk_buff *skb;
330d3466830SKalle Valo 	u16 len;
331d3466830SKalle Valo 	u16 rx_head[2];
332d3466830SKalle Valo #define READAHEAD_SZ (sizeof(rx_head)-sizeof(u16))
333d3466830SKalle Valo 
334d3466830SKalle Valo 	if (p54spi_wakeup(priv) < 0)
335d3466830SKalle Valo 		return -EBUSY;
336d3466830SKalle Valo 
337d3466830SKalle Valo 	/* Read data size and first data word in one SPI transaction
338d3466830SKalle Valo 	 * This is workaround for firmware/DMA bug,
339d3466830SKalle Valo 	 * when first data word gets lost under high load.
340d3466830SKalle Valo 	 */
341d3466830SKalle Valo 	p54spi_spi_read(priv, SPI_ADRS_DMA_DATA, rx_head, sizeof(rx_head));
342d3466830SKalle Valo 	len = rx_head[0];
343d3466830SKalle Valo 
344d3466830SKalle Valo 	if (len == 0) {
345d3466830SKalle Valo 		p54spi_sleep(priv);
346d3466830SKalle Valo 		dev_err(&priv->spi->dev, "rx request of zero bytes\n");
347d3466830SKalle Valo 		return 0;
348d3466830SKalle Valo 	}
349d3466830SKalle Valo 
350d3466830SKalle Valo 	/* Firmware may insert up to 4 padding bytes after the lmac header,
351d3466830SKalle Valo 	 * but it does not amend the size of SPI data transfer.
352d3466830SKalle Valo 	 * Such packets has correct data size in header, thus referencing
353d3466830SKalle Valo 	 * past the end of allocated skb. Reserve extra 4 bytes for this case
354d3466830SKalle Valo 	 */
355d3466830SKalle Valo 	skb = dev_alloc_skb(len + 4);
356d3466830SKalle Valo 	if (!skb) {
357d3466830SKalle Valo 		p54spi_sleep(priv);
358d3466830SKalle Valo 		dev_err(&priv->spi->dev, "could not alloc skb");
359d3466830SKalle Valo 		return -ENOMEM;
360d3466830SKalle Valo 	}
361d3466830SKalle Valo 
362d3466830SKalle Valo 	if (len <= READAHEAD_SZ) {
36359ae1d12SJohannes Berg 		skb_put_data(skb, rx_head + 1, len);
364d3466830SKalle Valo 	} else {
36559ae1d12SJohannes Berg 		skb_put_data(skb, rx_head + 1, READAHEAD_SZ);
366d3466830SKalle Valo 		p54spi_spi_read(priv, SPI_ADRS_DMA_DATA,
367d3466830SKalle Valo 				skb_put(skb, len - READAHEAD_SZ),
368d3466830SKalle Valo 				len - READAHEAD_SZ);
369d3466830SKalle Valo 	}
370d3466830SKalle Valo 	p54spi_sleep(priv);
371d3466830SKalle Valo 	/* Put additional bytes to compensate for the possible
372d3466830SKalle Valo 	 * alignment-caused truncation
373d3466830SKalle Valo 	 */
374d3466830SKalle Valo 	skb_put(skb, 4);
375d3466830SKalle Valo 
376d3466830SKalle Valo 	if (p54_rx(priv->hw, skb) == 0)
377d3466830SKalle Valo 		dev_kfree_skb(skb);
378d3466830SKalle Valo 
379d3466830SKalle Valo 	return 0;
380d3466830SKalle Valo }
381d3466830SKalle Valo 
382d3466830SKalle Valo 
p54spi_interrupt(int irq,void * config)383d3466830SKalle Valo static irqreturn_t p54spi_interrupt(int irq, void *config)
384d3466830SKalle Valo {
385d3466830SKalle Valo 	struct spi_device *spi = config;
386d3466830SKalle Valo 	struct p54s_priv *priv = spi_get_drvdata(spi);
387d3466830SKalle Valo 
388d3466830SKalle Valo 	ieee80211_queue_work(priv->hw, &priv->work);
389d3466830SKalle Valo 
390d3466830SKalle Valo 	return IRQ_HANDLED;
391d3466830SKalle Valo }
392d3466830SKalle Valo 
p54spi_tx_frame(struct p54s_priv * priv,struct sk_buff * skb)393d3466830SKalle Valo static int p54spi_tx_frame(struct p54s_priv *priv, struct sk_buff *skb)
394d3466830SKalle Valo {
395d3466830SKalle Valo 	struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
396d3466830SKalle Valo 	int ret = 0;
397d3466830SKalle Valo 
398d3466830SKalle Valo 	if (p54spi_wakeup(priv) < 0)
399d3466830SKalle Valo 		return -EBUSY;
400d3466830SKalle Valo 
401d3466830SKalle Valo 	ret = p54spi_spi_write_dma(priv, hdr->req_id, skb->data, skb->len);
402d3466830SKalle Valo 	if (ret < 0)
403d3466830SKalle Valo 		goto out;
404d3466830SKalle Valo 
405d3466830SKalle Valo 	if (!p54spi_wait_bit(priv, SPI_ADRS_HOST_INTERRUPTS,
406d3466830SKalle Valo 			     SPI_HOST_INT_WR_READY)) {
407d3466830SKalle Valo 		dev_err(&priv->spi->dev, "WR_READY timeout\n");
408d3466830SKalle Valo 		ret = -EAGAIN;
409d3466830SKalle Valo 		goto out;
410d3466830SKalle Valo 	}
411d3466830SKalle Valo 
412d3466830SKalle Valo 	p54spi_int_ack(priv, SPI_HOST_INT_WR_READY);
413d3466830SKalle Valo 
414d3466830SKalle Valo 	if (FREE_AFTER_TX(skb))
415d3466830SKalle Valo 		p54_free_skb(priv->hw, skb);
416d3466830SKalle Valo out:
417d3466830SKalle Valo 	p54spi_sleep(priv);
418d3466830SKalle Valo 	return ret;
419d3466830SKalle Valo }
420d3466830SKalle Valo 
p54spi_wq_tx(struct p54s_priv * priv)421d3466830SKalle Valo static int p54spi_wq_tx(struct p54s_priv *priv)
422d3466830SKalle Valo {
423d3466830SKalle Valo 	struct p54s_tx_info *entry;
424d3466830SKalle Valo 	struct sk_buff *skb;
425d3466830SKalle Valo 	struct ieee80211_tx_info *info;
426d3466830SKalle Valo 	struct p54_tx_info *minfo;
427d3466830SKalle Valo 	struct p54s_tx_info *dinfo;
428d3466830SKalle Valo 	unsigned long flags;
429d3466830SKalle Valo 	int ret = 0;
430d3466830SKalle Valo 
431d3466830SKalle Valo 	spin_lock_irqsave(&priv->tx_lock, flags);
432d3466830SKalle Valo 
433d3466830SKalle Valo 	while (!list_empty(&priv->tx_pending)) {
434d3466830SKalle Valo 		entry = list_entry(priv->tx_pending.next,
435d3466830SKalle Valo 				   struct p54s_tx_info, tx_list);
436d3466830SKalle Valo 
437d3466830SKalle Valo 		list_del_init(&entry->tx_list);
438d3466830SKalle Valo 
439d3466830SKalle Valo 		spin_unlock_irqrestore(&priv->tx_lock, flags);
440d3466830SKalle Valo 
441d3466830SKalle Valo 		dinfo = container_of((void *) entry, struct p54s_tx_info,
442d3466830SKalle Valo 				     tx_list);
443d3466830SKalle Valo 		minfo = container_of((void *) dinfo, struct p54_tx_info,
444d3466830SKalle Valo 				     data);
445d3466830SKalle Valo 		info = container_of((void *) minfo, struct ieee80211_tx_info,
446d3466830SKalle Valo 				    rate_driver_data);
447d3466830SKalle Valo 		skb = container_of((void *) info, struct sk_buff, cb);
448d3466830SKalle Valo 
449d3466830SKalle Valo 		ret = p54spi_tx_frame(priv, skb);
450d3466830SKalle Valo 
451d3466830SKalle Valo 		if (ret < 0) {
452d3466830SKalle Valo 			p54_free_skb(priv->hw, skb);
453d3466830SKalle Valo 			return ret;
454d3466830SKalle Valo 		}
455d3466830SKalle Valo 
456d3466830SKalle Valo 		spin_lock_irqsave(&priv->tx_lock, flags);
457d3466830SKalle Valo 	}
458d3466830SKalle Valo 	spin_unlock_irqrestore(&priv->tx_lock, flags);
459d3466830SKalle Valo 	return ret;
460d3466830SKalle Valo }
461d3466830SKalle Valo 
p54spi_op_tx(struct ieee80211_hw * dev,struct sk_buff * skb)462d3466830SKalle Valo static void p54spi_op_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
463d3466830SKalle Valo {
464d3466830SKalle Valo 	struct p54s_priv *priv = dev->priv;
465d3466830SKalle Valo 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
466d3466830SKalle Valo 	struct p54_tx_info *mi = (struct p54_tx_info *) info->rate_driver_data;
467d3466830SKalle Valo 	struct p54s_tx_info *di = (struct p54s_tx_info *) mi->data;
468d3466830SKalle Valo 	unsigned long flags;
469d3466830SKalle Valo 
470d3466830SKalle Valo 	BUILD_BUG_ON(sizeof(*di) > sizeof((mi->data)));
471d3466830SKalle Valo 
472d3466830SKalle Valo 	spin_lock_irqsave(&priv->tx_lock, flags);
473d3466830SKalle Valo 	list_add_tail(&di->tx_list, &priv->tx_pending);
474d3466830SKalle Valo 	spin_unlock_irqrestore(&priv->tx_lock, flags);
475d3466830SKalle Valo 
476d3466830SKalle Valo 	ieee80211_queue_work(priv->hw, &priv->work);
477d3466830SKalle Valo }
478d3466830SKalle Valo 
p54spi_work(struct work_struct * work)479d3466830SKalle Valo static void p54spi_work(struct work_struct *work)
480d3466830SKalle Valo {
481d3466830SKalle Valo 	struct p54s_priv *priv = container_of(work, struct p54s_priv, work);
482d3466830SKalle Valo 	u32 ints;
483d3466830SKalle Valo 	int ret;
484d3466830SKalle Valo 
485d3466830SKalle Valo 	mutex_lock(&priv->mutex);
486d3466830SKalle Valo 
487d3466830SKalle Valo 	if (priv->fw_state == FW_STATE_OFF)
488d3466830SKalle Valo 		goto out;
489d3466830SKalle Valo 
490d3466830SKalle Valo 	ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS);
491d3466830SKalle Valo 
492d3466830SKalle Valo 	if (ints & SPI_HOST_INT_READY) {
493d3466830SKalle Valo 		p54spi_int_ready(priv);
494d3466830SKalle Valo 		p54spi_int_ack(priv, SPI_HOST_INT_READY);
495d3466830SKalle Valo 	}
496d3466830SKalle Valo 
497d3466830SKalle Valo 	if (priv->fw_state != FW_STATE_READY)
498d3466830SKalle Valo 		goto out;
499d3466830SKalle Valo 
500d3466830SKalle Valo 	if (ints & SPI_HOST_INT_UPDATE) {
501d3466830SKalle Valo 		p54spi_int_ack(priv, SPI_HOST_INT_UPDATE);
502d3466830SKalle Valo 		ret = p54spi_rx(priv);
503d3466830SKalle Valo 		if (ret < 0)
504d3466830SKalle Valo 			goto out;
505d3466830SKalle Valo 	}
506d3466830SKalle Valo 	if (ints & SPI_HOST_INT_SW_UPDATE) {
507d3466830SKalle Valo 		p54spi_int_ack(priv, SPI_HOST_INT_SW_UPDATE);
508d3466830SKalle Valo 		ret = p54spi_rx(priv);
509d3466830SKalle Valo 		if (ret < 0)
510d3466830SKalle Valo 			goto out;
511d3466830SKalle Valo 	}
512d3466830SKalle Valo 
513d3466830SKalle Valo 	ret = p54spi_wq_tx(priv);
514d3466830SKalle Valo out:
515d3466830SKalle Valo 	mutex_unlock(&priv->mutex);
516d3466830SKalle Valo }
517d3466830SKalle Valo 
p54spi_op_start(struct ieee80211_hw * dev)518d3466830SKalle Valo static int p54spi_op_start(struct ieee80211_hw *dev)
519d3466830SKalle Valo {
520d3466830SKalle Valo 	struct p54s_priv *priv = dev->priv;
521*a37f6947SWolfram Sang 	long time_left;
522d3466830SKalle Valo 	int ret = 0;
523d3466830SKalle Valo 
524d3466830SKalle Valo 	if (mutex_lock_interruptible(&priv->mutex)) {
525d3466830SKalle Valo 		ret = -EINTR;
526d3466830SKalle Valo 		goto out;
527d3466830SKalle Valo 	}
528d3466830SKalle Valo 
529d3466830SKalle Valo 	priv->fw_state = FW_STATE_BOOTING;
530d3466830SKalle Valo 
531d3466830SKalle Valo 	p54spi_power_on(priv);
532d3466830SKalle Valo 
533d3466830SKalle Valo 	ret = p54spi_upload_firmware(dev);
534d3466830SKalle Valo 	if (ret < 0) {
535d3466830SKalle Valo 		p54spi_power_off(priv);
536d3466830SKalle Valo 		goto out_unlock;
537d3466830SKalle Valo 	}
538d3466830SKalle Valo 
539d3466830SKalle Valo 	mutex_unlock(&priv->mutex);
540d3466830SKalle Valo 
541*a37f6947SWolfram Sang 	time_left = msecs_to_jiffies(2000);
542*a37f6947SWolfram Sang 	time_left = wait_for_completion_interruptible_timeout(&priv->fw_comp,
543*a37f6947SWolfram Sang 							      time_left);
544*a37f6947SWolfram Sang 	if (!time_left) {
545d3466830SKalle Valo 		dev_err(&priv->spi->dev, "firmware boot failed");
546d3466830SKalle Valo 		p54spi_power_off(priv);
547d3466830SKalle Valo 		ret = -1;
548d3466830SKalle Valo 		goto out;
549d3466830SKalle Valo 	}
550d3466830SKalle Valo 
551d3466830SKalle Valo 	if (mutex_lock_interruptible(&priv->mutex)) {
552d3466830SKalle Valo 		ret = -EINTR;
553d3466830SKalle Valo 		p54spi_power_off(priv);
554d3466830SKalle Valo 		goto out;
555d3466830SKalle Valo 	}
556d3466830SKalle Valo 
557d3466830SKalle Valo 	WARN_ON(priv->fw_state != FW_STATE_READY);
558d3466830SKalle Valo 
559d3466830SKalle Valo out_unlock:
560d3466830SKalle Valo 	mutex_unlock(&priv->mutex);
561d3466830SKalle Valo 
562d3466830SKalle Valo out:
563d3466830SKalle Valo 	return ret;
564d3466830SKalle Valo }
565d3466830SKalle Valo 
p54spi_op_stop(struct ieee80211_hw * dev)566d3466830SKalle Valo static void p54spi_op_stop(struct ieee80211_hw *dev)
567d3466830SKalle Valo {
568d3466830SKalle Valo 	struct p54s_priv *priv = dev->priv;
569d3466830SKalle Valo 	unsigned long flags;
570d3466830SKalle Valo 
571d3466830SKalle Valo 	mutex_lock(&priv->mutex);
572d3466830SKalle Valo 	WARN_ON(priv->fw_state != FW_STATE_READY);
573d3466830SKalle Valo 
574d3466830SKalle Valo 	p54spi_power_off(priv);
575d3466830SKalle Valo 	spin_lock_irqsave(&priv->tx_lock, flags);
576d3466830SKalle Valo 	INIT_LIST_HEAD(&priv->tx_pending);
577d3466830SKalle Valo 	spin_unlock_irqrestore(&priv->tx_lock, flags);
578d3466830SKalle Valo 
579d3466830SKalle Valo 	priv->fw_state = FW_STATE_OFF;
580d3466830SKalle Valo 	mutex_unlock(&priv->mutex);
581d3466830SKalle Valo 
582d3466830SKalle Valo 	cancel_work_sync(&priv->work);
583d3466830SKalle Valo }
584d3466830SKalle Valo 
p54spi_probe(struct spi_device * spi)585d3466830SKalle Valo static int p54spi_probe(struct spi_device *spi)
586d3466830SKalle Valo {
587d3466830SKalle Valo 	struct p54s_priv *priv = NULL;
588d3466830SKalle Valo 	struct ieee80211_hw *hw;
589d3466830SKalle Valo 	int ret = -EINVAL;
590d3466830SKalle Valo 
591d3466830SKalle Valo 	hw = p54_init_common(sizeof(*priv));
592d3466830SKalle Valo 	if (!hw) {
593d3466830SKalle Valo 		dev_err(&spi->dev, "could not alloc ieee80211_hw");
594d3466830SKalle Valo 		return -ENOMEM;
595d3466830SKalle Valo 	}
596d3466830SKalle Valo 
597d3466830SKalle Valo 	priv = hw->priv;
598d3466830SKalle Valo 	priv->hw = hw;
599d3466830SKalle Valo 	spi_set_drvdata(spi, priv);
600d3466830SKalle Valo 	priv->spi = spi;
601d3466830SKalle Valo 
602d3466830SKalle Valo 	spi->bits_per_word = 16;
603d3466830SKalle Valo 	spi->max_speed_hz = 24000000;
604d3466830SKalle Valo 
605d3466830SKalle Valo 	ret = spi_setup(spi);
606d3466830SKalle Valo 	if (ret < 0) {
607d3466830SKalle Valo 		dev_err(&priv->spi->dev, "spi_setup failed");
608d3466830SKalle Valo 		goto err_free;
609d3466830SKalle Valo 	}
610d3466830SKalle Valo 
611d3466830SKalle Valo 	ret = gpio_request(p54spi_gpio_power, "p54spi power");
612d3466830SKalle Valo 	if (ret < 0) {
613d3466830SKalle Valo 		dev_err(&priv->spi->dev, "power GPIO request failed: %d", ret);
614d3466830SKalle Valo 		goto err_free;
615d3466830SKalle Valo 	}
616d3466830SKalle Valo 
617d3466830SKalle Valo 	ret = gpio_request(p54spi_gpio_irq, "p54spi irq");
618d3466830SKalle Valo 	if (ret < 0) {
619d3466830SKalle Valo 		dev_err(&priv->spi->dev, "irq GPIO request failed: %d", ret);
620d3466830SKalle Valo 		goto err_free_gpio_power;
621d3466830SKalle Valo 	}
622d3466830SKalle Valo 
623d3466830SKalle Valo 	gpio_direction_output(p54spi_gpio_power, 0);
624d3466830SKalle Valo 	gpio_direction_input(p54spi_gpio_irq);
625d3466830SKalle Valo 
626d3466830SKalle Valo 	ret = request_irq(gpio_to_irq(p54spi_gpio_irq),
627d3466830SKalle Valo 			  p54spi_interrupt, 0, "p54spi",
628d3466830SKalle Valo 			  priv->spi);
629d3466830SKalle Valo 	if (ret < 0) {
630d3466830SKalle Valo 		dev_err(&priv->spi->dev, "request_irq() failed");
631d3466830SKalle Valo 		goto err_free_gpio_irq;
632d3466830SKalle Valo 	}
633d3466830SKalle Valo 
634d3466830SKalle Valo 	irq_set_irq_type(gpio_to_irq(p54spi_gpio_irq), IRQ_TYPE_EDGE_RISING);
635d3466830SKalle Valo 
636d3466830SKalle Valo 	disable_irq(gpio_to_irq(p54spi_gpio_irq));
637d3466830SKalle Valo 
638d3466830SKalle Valo 	INIT_WORK(&priv->work, p54spi_work);
639d3466830SKalle Valo 	init_completion(&priv->fw_comp);
640d3466830SKalle Valo 	INIT_LIST_HEAD(&priv->tx_pending);
641d3466830SKalle Valo 	mutex_init(&priv->mutex);
642d3466830SKalle Valo 	spin_lock_init(&priv->tx_lock);
643d3466830SKalle Valo 	SET_IEEE80211_DEV(hw, &spi->dev);
644d3466830SKalle Valo 	priv->common.open = p54spi_op_start;
645d3466830SKalle Valo 	priv->common.stop = p54spi_op_stop;
646d3466830SKalle Valo 	priv->common.tx = p54spi_op_tx;
647d3466830SKalle Valo 
648d3466830SKalle Valo 	ret = p54spi_request_firmware(hw);
649d3466830SKalle Valo 	if (ret < 0)
650d3466830SKalle Valo 		goto err_free_common;
651d3466830SKalle Valo 
652d3466830SKalle Valo 	ret = p54spi_request_eeprom(hw);
653d3466830SKalle Valo 	if (ret)
654d3466830SKalle Valo 		goto err_free_common;
655d3466830SKalle Valo 
656d3466830SKalle Valo 	ret = p54_register_common(hw, &priv->spi->dev);
657d3466830SKalle Valo 	if (ret)
658d3466830SKalle Valo 		goto err_free_common;
659d3466830SKalle Valo 
660d3466830SKalle Valo 	return 0;
661d3466830SKalle Valo 
662d3466830SKalle Valo err_free_common:
66383781f01SChristophe JAILLET 	release_firmware(priv->firmware);
664d3466830SKalle Valo 	free_irq(gpio_to_irq(p54spi_gpio_irq), spi);
665d3466830SKalle Valo err_free_gpio_irq:
666d3466830SKalle Valo 	gpio_free(p54spi_gpio_irq);
667d3466830SKalle Valo err_free_gpio_power:
668d3466830SKalle Valo 	gpio_free(p54spi_gpio_power);
669d3466830SKalle Valo err_free:
670d3466830SKalle Valo 	p54_free_common(priv->hw);
671d3466830SKalle Valo 	return ret;
672d3466830SKalle Valo }
673d3466830SKalle Valo 
p54spi_remove(struct spi_device * spi)674a0386bbaSUwe Kleine-König static void p54spi_remove(struct spi_device *spi)
675d3466830SKalle Valo {
676d3466830SKalle Valo 	struct p54s_priv *priv = spi_get_drvdata(spi);
677d3466830SKalle Valo 
678d3466830SKalle Valo 	p54_unregister_common(priv->hw);
679d3466830SKalle Valo 
680d3466830SKalle Valo 	free_irq(gpio_to_irq(p54spi_gpio_irq), spi);
681d3466830SKalle Valo 
682d3466830SKalle Valo 	gpio_free(p54spi_gpio_power);
683d3466830SKalle Valo 	gpio_free(p54spi_gpio_irq);
684d3466830SKalle Valo 	release_firmware(priv->firmware);
685d3466830SKalle Valo 
686d3466830SKalle Valo 	mutex_destroy(&priv->mutex);
687d3466830SKalle Valo 
688d3466830SKalle Valo 	p54_free_common(priv->hw);
689d3466830SKalle Valo }
690d3466830SKalle Valo 
691d3466830SKalle Valo 
692d3466830SKalle Valo static struct spi_driver p54spi_driver = {
693d3466830SKalle Valo 	.driver = {
694d3466830SKalle Valo 		.name		= "p54spi",
695d3466830SKalle Valo 	},
696d3466830SKalle Valo 
697d3466830SKalle Valo 	.probe		= p54spi_probe,
698d3466830SKalle Valo 	.remove		= p54spi_remove,
699d3466830SKalle Valo };
700d3466830SKalle Valo 
701d3466830SKalle Valo module_spi_driver(p54spi_driver);
702d3466830SKalle Valo 
703714ea2f1SBreno Leitao MODULE_DESCRIPTION("Prism54 SPI wireless driver");
704d3466830SKalle Valo MODULE_LICENSE("GPL");
705d3466830SKalle Valo MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>");
706d3466830SKalle Valo MODULE_ALIAS("spi:cx3110x");
707d3466830SKalle Valo MODULE_ALIAS("spi:p54spi");
708d3466830SKalle Valo MODULE_ALIAS("spi:stlc45xx");
709