aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/p54/p54spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/p54/p54spi.c')
-rw-r--r--drivers/net/wireless/p54/p54spi.c152
1 files changed, 52 insertions, 100 deletions
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c
index 72c7dbd39d0..de15171e2cd 100644
--- a/drivers/net/wireless/p54/p54spi.c
+++ b/drivers/net/wireless/p54/p54spi.c
@@ -29,18 +29,20 @@
#include <linux/spi/spi.h>
#include <linux/etherdevice.h>
#include <linux/gpio.h>
+#include <linux/slab.h>
#include "p54spi.h"
-#include "p54spi_eeprom.h"
#include "p54.h"
-#include "p54common.h"
+#include "lmac.h"
+
+#ifdef CONFIG_P54_SPI_DEFAULT_EEPROM
+#include "p54spi_eeprom.h"
+#endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */
MODULE_FIRMWARE("3826.arm");
-MODULE_ALIAS("stlc45xx");
-/*
- * gpios should be handled in board files and provided via platform data,
+/* gpios should be handled in board files and provided via platform data,
* but because it's currently impossible for p54spi to have a header file
* in include/linux, let's use module paramaters for now
*/
@@ -111,15 +113,6 @@ static void p54spi_spi_write(struct p54s_priv *priv, u8 address,
spi_sync(priv->spi, &m);
}
-static u16 p54spi_read16(struct p54s_priv *priv, u8 addr)
-{
- __le16 val;
-
- p54spi_spi_read(priv, addr, &val, sizeof(val));
-
- return le16_to_cpu(val);
-}
-
static u32 p54spi_read32(struct p54s_priv *priv, u8 addr)
{
__le32 val;
@@ -139,37 +132,12 @@ static inline void p54spi_write32(struct p54s_priv *priv, u8 addr, __le32 val)
p54spi_spi_write(priv, addr, &val, sizeof(val));
}
-struct p54spi_spi_reg {
- u16 address; /* __le16 ? */
- u16 length;
- char *name;
-};
-
-static const struct p54spi_spi_reg p54spi_registers_array[] =
-{
- { SPI_ADRS_ARM_INTERRUPTS, 32, "ARM_INT " },
- { SPI_ADRS_ARM_INT_EN, 32, "ARM_INT_ENA " },
- { SPI_ADRS_HOST_INTERRUPTS, 32, "HOST_INT " },
- { SPI_ADRS_HOST_INT_EN, 32, "HOST_INT_ENA" },
- { SPI_ADRS_HOST_INT_ACK, 32, "HOST_INT_ACK" },
- { SPI_ADRS_GEN_PURP_1, 32, "GP1_COMM " },
- { SPI_ADRS_GEN_PURP_2, 32, "GP2_COMM " },
- { SPI_ADRS_DEV_CTRL_STAT, 32, "DEV_CTRL_STA" },
- { SPI_ADRS_DMA_DATA, 16, "DMA_DATA " },
- { SPI_ADRS_DMA_WRITE_CTRL, 16, "DMA_WR_CTRL " },
- { SPI_ADRS_DMA_WRITE_LEN, 16, "DMA_WR_LEN " },
- { SPI_ADRS_DMA_WRITE_BASE, 32, "DMA_WR_BASE " },
- { SPI_ADRS_DMA_READ_CTRL, 16, "DMA_RD_CTRL " },
- { SPI_ADRS_DMA_READ_LEN, 16, "DMA_RD_LEN " },
- { SPI_ADRS_DMA_WRITE_BASE, 32, "DMA_RD_BASE " }
-};
-
-static int p54spi_wait_bit(struct p54s_priv *priv, u16 reg, __le32 bits)
+static int p54spi_wait_bit(struct p54s_priv *priv, u16 reg, u32 bits)
{
int i;
for (i = 0; i < 2000; i++) {
- __le32 buffer = p54spi_read32(priv, reg);
+ u32 buffer = p54spi_read32(priv, reg);
if ((buffer & bits) == bits)
return 1;
}
@@ -179,8 +147,7 @@ static int p54spi_wait_bit(struct p54s_priv *priv, u16 reg, __le32 bits)
static int p54spi_spi_write_dma(struct p54s_priv *priv, __le32 base,
const void *buf, size_t len)
{
- if (!p54spi_wait_bit(priv, SPI_ADRS_DMA_WRITE_CTRL,
- cpu_to_le32(HOST_ALLOWED))) {
+ if (!p54spi_wait_bit(priv, SPI_ADRS_DMA_WRITE_CTRL, HOST_ALLOWED)) {
dev_err(&priv->spi->dev, "spi_write_dma not allowed "
"to DMA write.\n");
return -EAGAIN;
@@ -223,15 +190,18 @@ static int p54spi_request_eeprom(struct ieee80211_hw *dev)
const struct firmware *eeprom;
int ret;
- /*
- * allow users to customize their eeprom.
+ /* allow users to customize their eeprom.
*/
ret = request_firmware(&eeprom, "3826.eeprom", &priv->spi->dev);
if (ret < 0) {
+#ifdef CONFIG_P54_SPI_DEFAULT_EEPROM
dev_info(&priv->spi->dev, "loading default eeprom...\n");
ret = p54_parse_eeprom(dev, (void *) p54spi_eeprom,
sizeof(p54spi_eeprom));
+#else
+ dev_err(&priv->spi->dev, "Failed to request user eeprom\n");
+#endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */
} else {
dev_info(&priv->spi->dev, "loading user eeprom...\n");
ret = p54_parse_eeprom(dev, (void *) eeprom->data,
@@ -313,8 +283,7 @@ static void p54spi_power_on(struct p54s_priv *priv)
gpio_set_value(p54spi_gpio_power, 1);
enable_irq(gpio_to_irq(p54spi_gpio_irq));
- /*
- * need to wait a while before device can be accessed, the lenght
+ /* need to wait a while before device can be accessed, the length
* is just a guess
*/
msleep(10);
@@ -333,7 +302,7 @@ static int p54spi_wakeup(struct p54s_priv *priv)
/* And wait for the READY interrupt */
if (!p54spi_wait_bit(priv, SPI_ADRS_HOST_INTERRUPTS,
- cpu_to_le32(SPI_HOST_INT_READY))) {
+ SPI_HOST_INT_READY)) {
dev_err(&priv->spi->dev, "INT_READY timeout\n");
return -EBUSY;
}
@@ -393,7 +362,8 @@ static int p54spi_rx(struct p54s_priv *priv)
/* Firmware may insert up to 4 padding bytes after the lmac header,
* but it does not amend the size of SPI data transfer.
* Such packets has correct data size in header, thus referencing
- * past the end of allocated skb. Reserve extra 4 bytes for this case */
+ * past the end of allocated skb. Reserve extra 4 bytes for this case
+ */
skb = dev_alloc_skb(len + 4);
if (!skb) {
p54spi_sleep(priv);
@@ -411,7 +381,8 @@ static int p54spi_rx(struct p54s_priv *priv)
}
p54spi_sleep(priv);
/* Put additional bytes to compensate for the possible
- * alignment-caused truncation */
+ * alignment-caused truncation
+ */
skb_put(skb, 4);
if (p54_rx(priv->hw, skb) == 0)
@@ -424,9 +395,9 @@ static int p54spi_rx(struct p54s_priv *priv)
static irqreturn_t p54spi_interrupt(int irq, void *config)
{
struct spi_device *spi = config;
- struct p54s_priv *priv = dev_get_drvdata(&spi->dev);
+ struct p54s_priv *priv = spi_get_drvdata(spi);
- queue_work(priv->hw->workqueue, &priv->work);
+ ieee80211_queue_work(priv->hw, &priv->work);
return IRQ_HANDLED;
}
@@ -444,7 +415,7 @@ static int p54spi_tx_frame(struct p54s_priv *priv, struct sk_buff *skb)
goto out;
if (!p54spi_wait_bit(priv, SPI_ADRS_HOST_INTERRUPTS,
- cpu_to_le32(SPI_HOST_INT_WR_READY))) {
+ SPI_HOST_INT_WR_READY)) {
dev_err(&priv->spi->dev, "WR_READY timeout\n");
ret = -EAGAIN;
goto out;
@@ -514,7 +485,7 @@ static void p54spi_op_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
list_add_tail(&di->tx_list, &priv->tx_pending);
spin_unlock_irqrestore(&priv->tx_lock, flags);
- queue_work(priv->hw->workqueue, &priv->work);
+ ieee80211_queue_work(priv->hw, &priv->work);
}
static void p54spi_work(struct work_struct *work)
@@ -609,15 +580,9 @@ static void p54spi_op_stop(struct ieee80211_hw *dev)
struct p54s_priv *priv = dev->priv;
unsigned long flags;
- if (mutex_lock_interruptible(&priv->mutex)) {
- /* FIXME: how to handle this error? */
- return;
- }
-
+ mutex_lock(&priv->mutex);
WARN_ON(priv->fw_state != FW_STATE_READY);
- cancel_work_sync(&priv->work);
-
p54spi_power_off(priv);
spin_lock_irqsave(&priv->tx_lock, flags);
INIT_LIST_HEAD(&priv->tx_pending);
@@ -625,9 +590,11 @@ static void p54spi_op_stop(struct ieee80211_hw *dev)
priv->fw_state = FW_STATE_OFF;
mutex_unlock(&priv->mutex);
+
+ cancel_work_sync(&priv->work);
}
-static int __devinit p54spi_probe(struct spi_device *spi)
+static int p54spi_probe(struct spi_device *spi)
{
struct p54s_priv *priv = NULL;
struct ieee80211_hw *hw;
@@ -641,7 +608,7 @@ static int __devinit p54spi_probe(struct spi_device *spi)
priv = hw->priv;
priv->hw = hw;
- dev_set_drvdata(&spi->dev, priv);
+ spi_set_drvdata(spi, priv);
priv->spi = spi;
spi->bits_per_word = 16;
@@ -650,34 +617,33 @@ static int __devinit p54spi_probe(struct spi_device *spi)
ret = spi_setup(spi);
if (ret < 0) {
dev_err(&priv->spi->dev, "spi_setup failed");
- goto err_free_common;
+ goto err_free;
}
ret = gpio_request(p54spi_gpio_power, "p54spi power");
if (ret < 0) {
dev_err(&priv->spi->dev, "power GPIO request failed: %d", ret);
- goto err_free_common;
+ goto err_free;
}
ret = gpio_request(p54spi_gpio_irq, "p54spi irq");
if (ret < 0) {
dev_err(&priv->spi->dev, "irq GPIO request failed: %d", ret);
- goto err_free_common;
+ goto err_free_gpio_power;
}
gpio_direction_output(p54spi_gpio_power, 0);
gpio_direction_input(p54spi_gpio_irq);
ret = request_irq(gpio_to_irq(p54spi_gpio_irq),
- p54spi_interrupt, IRQF_DISABLED, "p54spi",
+ p54spi_interrupt, 0, "p54spi",
priv->spi);
if (ret < 0) {
dev_err(&priv->spi->dev, "request_irq() failed");
- goto err_free_common;
+ goto err_free_gpio_irq;
}
- set_irq_type(gpio_to_irq(p54spi_gpio_irq),
- IRQ_TYPE_EDGE_RISING);
+ irq_set_irq_type(gpio_to_irq(p54spi_gpio_irq), IRQ_TYPE_EDGE_RISING);
disable_irq(gpio_to_irq(p54spi_gpio_irq));
@@ -685,6 +651,7 @@ static int __devinit p54spi_probe(struct spi_device *spi)
init_completion(&priv->fw_comp);
INIT_LIST_HEAD(&priv->tx_pending);
mutex_init(&priv->mutex);
+ spin_lock_init(&priv->tx_lock);
SET_IEEE80211_DEV(hw, &spi->dev);
priv->common.open = p54spi_op_start;
priv->common.stop = p54spi_op_stop;
@@ -705,15 +672,21 @@ static int __devinit p54spi_probe(struct spi_device *spi)
return 0;
err_free_common:
+ free_irq(gpio_to_irq(p54spi_gpio_irq), spi);
+err_free_gpio_irq:
+ gpio_free(p54spi_gpio_irq);
+err_free_gpio_power:
+ gpio_free(p54spi_gpio_power);
+err_free:
p54_free_common(priv->hw);
return ret;
}
-static int __devexit p54spi_remove(struct spi_device *spi)
+static int p54spi_remove(struct spi_device *spi)
{
- struct p54s_priv *priv = dev_get_drvdata(&spi->dev);
+ struct p54s_priv *priv = spi_get_drvdata(spi);
- ieee80211_unregister_hw(priv->hw);
+ p54_unregister_common(priv->hw);
free_irq(gpio_to_irq(p54spi_gpio_irq), spi);
@@ -724,7 +697,6 @@ static int __devexit p54spi_remove(struct spi_device *spi)
mutex_destroy(&priv->mutex);
p54_free_common(priv->hw);
- ieee80211_free_hw(priv->hw);
return 0;
}
@@ -732,38 +704,18 @@ static int __devexit p54spi_remove(struct spi_device *spi)
static struct spi_driver p54spi_driver = {
.driver = {
- /* use cx3110x name because board-n800.c uses that for the
- * SPI port */
- .name = "cx3110x",
- .bus = &spi_bus_type,
+ .name = "p54spi",
.owner = THIS_MODULE,
},
.probe = p54spi_probe,
- .remove = __devexit_p(p54spi_remove),
+ .remove = p54spi_remove,
};
-static int __init p54spi_init(void)
-{
- int ret;
-
- ret = spi_register_driver(&p54spi_driver);
- if (ret < 0) {
- printk(KERN_ERR "failed to register SPI driver: %d", ret);
- goto out;
- }
-
-out:
- return ret;
-}
-
-static void __exit p54spi_exit(void)
-{
- spi_unregister_driver(&p54spi_driver);
-}
-
-module_init(p54spi_init);
-module_exit(p54spi_exit);
+module_spi_driver(p54spi_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>");
+MODULE_ALIAS("spi:cx3110x");
+MODULE_ALIAS("spi:p54spi");
+MODULE_ALIAS("spi:stlc45xx");