diff options
Diffstat (limited to 'drivers/net/wireless/libertas/if_spi.c')
-rw-r--r-- | drivers/net/wireless/libertas/if_spi.c | 158 |
1 files changed, 82 insertions, 76 deletions
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 07311e71af9..6564282ce47 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -19,7 +19,6 @@ #include <linux/moduleparam.h> #include <linux/firmware.h> -#include <linux/gpio.h> #include <linux/jiffies.h> #include <linux/kthread.h> #include <linux/list.h> @@ -44,20 +43,13 @@ struct if_spi_card { struct lbs_private *priv; struct libertas_spi_platform_data *pdata; - char helper_fw_name[FIRMWARE_NAME_MAX]; - char main_fw_name[FIRMWARE_NAME_MAX]; + char helper_fw_name[IF_SPI_FW_NAME_MAX]; + char main_fw_name[IF_SPI_FW_NAME_MAX]; /* The card ID and card revision, as reported by the hardware. */ u16 card_id; u8 card_rev; - /* Pin number for our GPIO chip-select. */ - /* TODO: Once the generic SPI layer has some additional features, we - * should take this out and use the normal chip select here. - * We need support for chip select delays, and not dropping chipselect - * after each word. */ - int gpio_cs; - /* The last time that we initiated an SPU operation */ unsigned long prev_xfer_time; @@ -119,9 +111,6 @@ static struct chip_ident chip_id_to_device_name[] = { * First we have to put a SPU register name on the bus. Then we can * either read from or write to that register. * - * For 16-bit transactions, byte order on the bus is big-endian. - * We don't have to worry about that here, though. - * The translation takes place in the SPI routines. */ static void spu_transaction_init(struct if_spi_card *card) @@ -133,12 +122,10 @@ static void spu_transaction_init(struct if_spi_card *card) * If not, we have to busy-wait to be on the safe side. */ ndelay(400); } - gpio_set_value(card->gpio_cs, 0); /* assert CS */ } static void spu_transaction_finish(struct if_spi_card *card) { - gpio_set_value(card->gpio_cs, 1); /* drop CS */ card->prev_xfer_time = jiffies; } @@ -147,7 +134,14 @@ static void spu_transaction_finish(struct if_spi_card *card) static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len) { int err = 0; - u16 reg_out = reg | IF_SPI_WRITE_OPERATION_MASK; + u16 reg_out = cpu_to_le16(reg | IF_SPI_WRITE_OPERATION_MASK); + struct spi_message m; + struct spi_transfer reg_trans; + struct spi_transfer data_trans; + + spi_message_init(&m); + memset(®_trans, 0, sizeof(reg_trans)); + memset(&data_trans, 0, sizeof(data_trans)); /* You must give an even number of bytes to the SPU, even if it * doesn't care about the last one. */ @@ -156,29 +150,26 @@ static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len) spu_transaction_init(card); /* write SPU register index */ - err = spi_write(card->spi, (u8 *)®_out, sizeof(u16)); - if (err) - goto out; + reg_trans.tx_buf = ®_out; + reg_trans.len = sizeof(reg_out); - err = spi_write(card->spi, buf, len); + data_trans.tx_buf = buf; + data_trans.len = len; -out: + spi_message_add_tail(®_trans, &m); + spi_message_add_tail(&data_trans, &m); + + err = spi_sync(card->spi, &m); spu_transaction_finish(card); return err; } static inline int spu_write_u16(struct if_spi_card *card, u16 reg, u16 val) { - return spu_write(card, reg, (u8 *)&val, sizeof(u16)); -} + u16 buff; -static inline int spu_write_u32(struct if_spi_card *card, u16 reg, u32 val) -{ - /* The lower 16 bits are written first. */ - u16 out[2]; - out[0] = val & 0xffff; - out[1] = (val & 0xffff0000) >> 16; - return spu_write(card, reg, (u8 *)&out, sizeof(u32)); + buff = cpu_to_le16(val); + return spu_write(card, reg, (u8 *)&buff, sizeof(u16)); } static inline int spu_reg_is_port_reg(u16 reg) @@ -195,10 +186,13 @@ static inline int spu_reg_is_port_reg(u16 reg) static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len) { - unsigned int i, delay; + unsigned int delay; int err = 0; - u16 zero = 0; - u16 reg_out = reg | IF_SPI_READ_OPERATION_MASK; + u16 reg_out = cpu_to_le16(reg | IF_SPI_READ_OPERATION_MASK); + struct spi_message m; + struct spi_transfer reg_trans; + struct spi_transfer dummy_trans; + struct spi_transfer data_trans; /* You must take an even number of bytes from the SPU, even if you * don't care about the last one. */ @@ -206,29 +200,34 @@ static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len) spu_transaction_init(card); + spi_message_init(&m); + memset(®_trans, 0, sizeof(reg_trans)); + memset(&dummy_trans, 0, sizeof(dummy_trans)); + memset(&data_trans, 0, sizeof(data_trans)); + /* write SPU register index */ - err = spi_write(card->spi, (u8 *)®_out, sizeof(u16)); - if (err) - goto out; + reg_trans.tx_buf = ®_out; + reg_trans.len = sizeof(reg_out); + spi_message_add_tail(®_trans, &m); delay = spu_reg_is_port_reg(reg) ? card->spu_port_delay : card->spu_reg_delay; if (card->use_dummy_writes) { /* Clock in dummy cycles while the SPU fills the FIFO */ - for (i = 0; i < delay / 16; ++i) { - err = spi_write(card->spi, (u8 *)&zero, sizeof(u16)); - if (err) - return err; - } + dummy_trans.len = delay / 8; + spi_message_add_tail(&dummy_trans, &m); } else { /* Busy-wait while the SPU fills the FIFO */ - ndelay(100 + (delay * 10)); + reg_trans.delay_usecs = + DIV_ROUND_UP((100 + (delay * 10)), 1000); } /* read in data */ - err = spi_read(card->spi, buf, len); + data_trans.rx_buf = buf; + data_trans.len = len; + spi_message_add_tail(&data_trans, &m); -out: + err = spi_sync(card->spi, &m); spu_transaction_finish(card); return err; } @@ -236,18 +235,25 @@ out: /* Read 16 bits from an SPI register */ static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val) { - return spu_read(card, reg, (u8 *)val, sizeof(u16)); + u16 buf; + int ret; + + ret = spu_read(card, reg, (u8 *)&buf, sizeof(buf)); + if (ret == 0) + *val = le16_to_cpup(&buf); + return ret; } /* Read 32 bits from an SPI register. * The low 16 bits are read first. */ static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val) { - u16 buf[2]; + u32 buf; int err; - err = spu_read(card, reg, (u8 *)buf, sizeof(u32)); + + err = spu_read(card, reg, (u8 *)&buf, sizeof(buf)); if (!err) - *val = buf[0] | (buf[1] << 16); + *val = le32_to_cpup(&buf); return err; } @@ -731,7 +737,7 @@ static int if_spi_c2h_data(struct if_spi_card *card) goto out; } else if (len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { lbs_pr_err("%s: error: card has %d bytes of data, but " - "our maximum skb size is %u\n", + "our maximum skb size is %lu\n", __func__, len, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE); err = -EINVAL; goto out; @@ -806,7 +812,6 @@ out: static void if_spi_e2h(struct if_spi_card *card) { int err = 0; - unsigned long flags; u32 cause; struct lbs_private *priv = card->priv; @@ -814,10 +819,14 @@ static void if_spi_e2h(struct if_spi_card *card) if (err) goto out; - spin_lock_irqsave(&priv->driver_lock, flags); - lbs_queue_event(priv, cause & 0xff); - spin_unlock_irqrestore(&priv->driver_lock, flags); + /* re-enable the card event interrupt */ + spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, + ~IF_SPI_HICU_CARD_EVENT); + + /* generate a card interrupt */ + spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, IF_SPI_CIC_HOST_EVENT); + lbs_queue_event(priv, cause & 0xff); out: if (err) lbs_pr_err("%s: error %d\n", __func__, err); @@ -862,7 +871,12 @@ static int lbs_spi_thread(void *data) err = if_spi_c2h_data(card); if (err) goto err; - if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY) { + + /* workaround: in PS mode, the card does not set the Command + * Download Ready bit, but it sets TX Download Ready. */ + if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY || + (card->priv->psstate != PS_STATE_FULL_POWER && + (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) { /* This means two things. First of all, * if there was a previous command sent, the card has * successfully received it. @@ -1006,9 +1020,9 @@ static int if_spi_calculate_fw_names(u16 card_id, lbs_pr_err("Unsupported chip_id: 0x%02x\n", card_id); return -EAFNOSUPPORT; } - snprintf(helper_fw, FIRMWARE_NAME_MAX, "libertas/gspi%d_hlp.bin", + snprintf(helper_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d_hlp.bin", chip_id_to_device_name[i].name); - snprintf(main_fw, FIRMWARE_NAME_MAX, "libertas/gspi%d.bin", + snprintf(main_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d.bin", chip_id_to_device_name[i].name); return 0; } @@ -1020,6 +1034,7 @@ static int __devinit if_spi_probe(struct spi_device *spi) struct libertas_spi_platform_data *pdata = spi->dev.platform_data; int err = 0; u32 scratch; + struct sched_param param = { .sched_priority = 1 }; lbs_deb_enter(LBS_DEB_SPI); @@ -1043,7 +1058,6 @@ static int __devinit if_spi_probe(struct spi_device *spi) spi_set_drvdata(spi, card); card->pdata = pdata; card->spi = spi; - card->gpio_cs = pdata->gpio_cs; card->prev_xfer_time = jiffies; sema_init(&card->spi_ready, 0); @@ -1052,26 +1066,18 @@ static int __devinit if_spi_probe(struct spi_device *spi) INIT_LIST_HEAD(&card->data_packet_list); spin_lock_init(&card->buffer_lock); - /* set up GPIO CS line. TODO: use regular CS line */ - err = gpio_request(card->gpio_cs, "if_spi_gpio_chip_select"); - if (err) - goto free_card; - err = gpio_direction_output(card->gpio_cs, 1); - if (err) - goto free_gpio; - /* Initialize the SPI Interface Unit */ err = spu_init(card, pdata->use_dummy_writes); if (err) - goto free_gpio; + goto free_card; err = spu_get_chip_revision(card, &card->card_id, &card->card_rev); if (err) - goto free_gpio; + goto free_card; /* Firmware load */ err = spu_read_u32(card, IF_SPI_SCRATCH_4_REG, &scratch); if (err) - goto free_gpio; + goto free_card; if (scratch == SUCCESSFUL_FW_DOWNLOAD_MAGIC) lbs_deb_spi("Firmware is already loaded for " "Marvell WLAN 802.11 adapter\n"); @@ -1079,7 +1085,7 @@ static int __devinit if_spi_probe(struct spi_device *spi) err = if_spi_calculate_fw_names(card->card_id, card->helper_fw_name, card->main_fw_name); if (err) - goto free_gpio; + goto free_card; lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter " "(chip_id = 0x%04x, chip_rev = 0x%02x) " @@ -1090,23 +1096,23 @@ static int __devinit if_spi_probe(struct spi_device *spi) spi->max_speed_hz); err = if_spi_prog_helper_firmware(card); if (err) - goto free_gpio; + goto free_card; err = if_spi_prog_main_firmware(card); if (err) - goto free_gpio; + goto free_card; lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n"); } err = spu_set_interrupt_mode(card, 0, 1); if (err) - goto free_gpio; + goto free_card; /* Register our card with libertas. * This will call alloc_etherdev */ priv = lbs_add_card(card, &spi->dev); if (!priv) { err = -ENOMEM; - goto free_gpio; + goto free_card; } card->priv = priv; priv->card = card; @@ -1123,6 +1129,9 @@ static int __devinit if_spi_probe(struct spi_device *spi) lbs_pr_err("error creating SPI thread: err=%d\n", err); goto remove_card; } + if (sched_setscheduler(card->spi_thread, SCHED_FIFO, ¶m)) + lbs_pr_err("Error setting scheduler, using default.\n"); + err = request_irq(spi->irq, if_spi_host_interrupt, IRQF_TRIGGER_FALLING, "libertas_spi", card); if (err) { @@ -1148,8 +1157,6 @@ terminate_thread: if_spi_terminate_spi_thread(card); remove_card: lbs_remove_card(priv); /* will call free_netdev */ -free_gpio: - gpio_free(card->gpio_cs); free_card: free_if_spi_card(card); out: @@ -1170,7 +1177,6 @@ static int __devexit libertas_spi_remove(struct spi_device *spi) free_irq(spi->irq, card); if_spi_terminate_spi_thread(card); lbs_remove_card(priv); /* will call free_netdev */ - gpio_free(card->gpio_cs); if (card->pdata->teardown) card->pdata->teardown(spi); free_if_spi_card(card); |