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