aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2009-06-04 15:57:03 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-06-10 13:27:50 -0400
commit4d1d49858c0a5a4fb1be4bc7972754cd640245ba (patch)
treefc481d282b7c7e45972b9d3b6cd2e903cac409e6 /drivers
parent582241a08409c89b086774c60b55c1a1706a7e5d (diff)
net/libertas: remove GPIO-CS handling in SPI interface code
This removes the dependency on GPIO framework and lets the SPI host driver handle the chip select. The SPI host driver is required to keep the CS active for the entire message unless cs_change says otherwise. This patch collects the two/three single SPI transfers into a message. Also the delay in read path in case use_dummy_writes are not used is moved into the SPI host driver. Tested-by: Mike Rapoport <mike@compulab.co.il> Tested-by: Andrey Yurovsky <andrey@cozybit.com> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Acked-by: Dan Williams <dcbw@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/Kconfig2
-rw-r--r--drivers/net/wireless/libertas/if_spi.c92
2 files changed, 45 insertions, 49 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index daf4c805be58..fb7541c28e58 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -153,7 +153,7 @@ config LIBERTAS_SDIO
153 153
154config LIBERTAS_SPI 154config LIBERTAS_SPI
155 tristate "Marvell Libertas 8686 SPI 802.11b/g cards" 155 tristate "Marvell Libertas 8686 SPI 802.11b/g cards"
156 depends on LIBERTAS && SPI && GENERIC_GPIO 156 depends on LIBERTAS && SPI
157 ---help--- 157 ---help---
158 A driver for Marvell Libertas 8686 SPI devices. 158 A driver for Marvell Libertas 8686 SPI devices.
159 159
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index ea23c5de1420..f8c2898d82b0 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -19,7 +19,6 @@
19 19
20#include <linux/moduleparam.h> 20#include <linux/moduleparam.h>
21#include <linux/firmware.h> 21#include <linux/firmware.h>
22#include <linux/gpio.h>
23#include <linux/jiffies.h> 22#include <linux/jiffies.h>
24#include <linux/kthread.h> 23#include <linux/kthread.h>
25#include <linux/list.h> 24#include <linux/list.h>
@@ -51,13 +50,6 @@ struct if_spi_card {
51 u16 card_id; 50 u16 card_id;
52 u8 card_rev; 51 u8 card_rev;
53 52
54 /* Pin number for our GPIO chip-select. */
55 /* TODO: Once the generic SPI layer has some additional features, we
56 * should take this out and use the normal chip select here.
57 * We need support for chip select delays, and not dropping chipselect
58 * after each word. */
59 int gpio_cs;
60
61 /* The last time that we initiated an SPU operation */ 53 /* The last time that we initiated an SPU operation */
62 unsigned long prev_xfer_time; 54 unsigned long prev_xfer_time;
63 55
@@ -130,12 +122,10 @@ static void spu_transaction_init(struct if_spi_card *card)
130 * If not, we have to busy-wait to be on the safe side. */ 122 * If not, we have to busy-wait to be on the safe side. */
131 ndelay(400); 123 ndelay(400);
132 } 124 }
133 gpio_set_value(card->gpio_cs, 0); /* assert CS */
134} 125}
135 126
136static void spu_transaction_finish(struct if_spi_card *card) 127static void spu_transaction_finish(struct if_spi_card *card)
137{ 128{
138 gpio_set_value(card->gpio_cs, 1); /* drop CS */
139 card->prev_xfer_time = jiffies; 129 card->prev_xfer_time = jiffies;
140} 130}
141 131
@@ -145,6 +135,13 @@ static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len)
145{ 135{
146 int err = 0; 136 int err = 0;
147 u16 reg_out = cpu_to_le16(reg | IF_SPI_WRITE_OPERATION_MASK); 137 u16 reg_out = cpu_to_le16(reg | IF_SPI_WRITE_OPERATION_MASK);
138 struct spi_message m;
139 struct spi_transfer reg_trans;
140 struct spi_transfer data_trans;
141
142 spi_message_init(&m);
143 memset(&reg_trans, 0, sizeof(reg_trans));
144 memset(&data_trans, 0, sizeof(data_trans));
148 145
149 /* You must give an even number of bytes to the SPU, even if it 146 /* You must give an even number of bytes to the SPU, even if it
150 * doesn't care about the last one. */ 147 * doesn't care about the last one. */
@@ -153,13 +150,16 @@ static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len)
153 spu_transaction_init(card); 150 spu_transaction_init(card);
154 151
155 /* write SPU register index */ 152 /* write SPU register index */
156 err = spi_write(card->spi, (u8 *)&reg_out, sizeof(u16)); 153 reg_trans.tx_buf = &reg_out;
157 if (err) 154 reg_trans.len = sizeof(reg_out);
158 goto out;
159 155
160 err = spi_write(card->spi, buf, len); 156 data_trans.tx_buf = buf;
157 data_trans.len = len;
161 158
162out: 159 spi_message_add_tail(&reg_trans, &m);
160 spi_message_add_tail(&data_trans, &m);
161
162 err = spi_sync(card->spi, &m);
163 spu_transaction_finish(card); 163 spu_transaction_finish(card);
164 return err; 164 return err;
165} 165}
@@ -186,10 +186,13 @@ static inline int spu_reg_is_port_reg(u16 reg)
186 186
187static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len) 187static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len)
188{ 188{
189 unsigned int i, delay; 189 unsigned int delay;
190 int err = 0; 190 int err = 0;
191 u16 zero = 0;
192 u16 reg_out = cpu_to_le16(reg | IF_SPI_READ_OPERATION_MASK); 191 u16 reg_out = cpu_to_le16(reg | IF_SPI_READ_OPERATION_MASK);
192 struct spi_message m;
193 struct spi_transfer reg_trans;
194 struct spi_transfer dummy_trans;
195 struct spi_transfer data_trans;
193 196
194 /* You must take an even number of bytes from the SPU, even if you 197 /* You must take an even number of bytes from the SPU, even if you
195 * don't care about the last one. */ 198 * don't care about the last one. */
@@ -197,29 +200,34 @@ static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len)
197 200
198 spu_transaction_init(card); 201 spu_transaction_init(card);
199 202
203 spi_message_init(&m);
204 memset(&reg_trans, 0, sizeof(reg_trans));
205 memset(&dummy_trans, 0, sizeof(dummy_trans));
206 memset(&data_trans, 0, sizeof(data_trans));
207
200 /* write SPU register index */ 208 /* write SPU register index */
201 err = spi_write(card->spi, (u8 *)&reg_out, sizeof(u16)); 209 reg_trans.tx_buf = &reg_out;
202 if (err) 210 reg_trans.len = sizeof(reg_out);
203 goto out; 211 spi_message_add_tail(&reg_trans, &m);
204 212
205 delay = spu_reg_is_port_reg(reg) ? card->spu_port_delay : 213 delay = spu_reg_is_port_reg(reg) ? card->spu_port_delay :
206 card->spu_reg_delay; 214 card->spu_reg_delay;
207 if (card->use_dummy_writes) { 215 if (card->use_dummy_writes) {
208 /* Clock in dummy cycles while the SPU fills the FIFO */ 216 /* Clock in dummy cycles while the SPU fills the FIFO */
209 for (i = 0; i < delay / 16; ++i) { 217 dummy_trans.len = delay / 8;
210 err = spi_write(card->spi, (u8 *)&zero, sizeof(u16)); 218 spi_message_add_tail(&dummy_trans, &m);
211 if (err)
212 return err;
213 }
214 } else { 219 } else {
215 /* Busy-wait while the SPU fills the FIFO */ 220 /* Busy-wait while the SPU fills the FIFO */
216 ndelay(100 + (delay * 10)); 221 reg_trans.delay_usecs =
222 DIV_ROUND_UP((100 + (delay * 10)), 1000);
217 } 223 }
218 224
219 /* read in data */ 225 /* read in data */
220 err = spi_read(card->spi, buf, len); 226 data_trans.rx_buf = buf;
227 data_trans.len = len;
228 spi_message_add_tail(&data_trans, &m);
221 229
222out: 230 err = spi_sync(card->spi, &m);
223 spu_transaction_finish(card); 231 spu_transaction_finish(card);
224 return err; 232 return err;
225} 233}
@@ -1049,7 +1057,6 @@ static int __devinit if_spi_probe(struct spi_device *spi)
1049 spi_set_drvdata(spi, card); 1057 spi_set_drvdata(spi, card);
1050 card->pdata = pdata; 1058 card->pdata = pdata;
1051 card->spi = spi; 1059 card->spi = spi;
1052 card->gpio_cs = pdata->gpio_cs;
1053 card->prev_xfer_time = jiffies; 1060 card->prev_xfer_time = jiffies;
1054 1061
1055 sema_init(&card->spi_ready, 0); 1062 sema_init(&card->spi_ready, 0);
@@ -1058,26 +1065,18 @@ static int __devinit if_spi_probe(struct spi_device *spi)
1058 INIT_LIST_HEAD(&card->data_packet_list); 1065 INIT_LIST_HEAD(&card->data_packet_list);
1059 spin_lock_init(&card->buffer_lock); 1066 spin_lock_init(&card->buffer_lock);
1060 1067
1061 /* set up GPIO CS line. TODO: use regular CS line */
1062 err = gpio_request(card->gpio_cs, "if_spi_gpio_chip_select");
1063 if (err)
1064 goto free_card;
1065 err = gpio_direction_output(card->gpio_cs, 1);
1066 if (err)
1067 goto free_gpio;
1068
1069 /* Initialize the SPI Interface Unit */ 1068 /* Initialize the SPI Interface Unit */
1070 err = spu_init(card, pdata->use_dummy_writes); 1069 err = spu_init(card, pdata->use_dummy_writes);
1071 if (err) 1070 if (err)
1072 goto free_gpio; 1071 goto free_card;
1073 err = spu_get_chip_revision(card, &card->card_id, &card->card_rev); 1072 err = spu_get_chip_revision(card, &card->card_id, &card->card_rev);
1074 if (err) 1073 if (err)
1075 goto free_gpio; 1074 goto free_card;
1076 1075
1077 /* Firmware load */ 1076 /* Firmware load */
1078 err = spu_read_u32(card, IF_SPI_SCRATCH_4_REG, &scratch); 1077 err = spu_read_u32(card, IF_SPI_SCRATCH_4_REG, &scratch);
1079 if (err) 1078 if (err)
1080 goto free_gpio; 1079 goto free_card;
1081 if (scratch == SUCCESSFUL_FW_DOWNLOAD_MAGIC) 1080 if (scratch == SUCCESSFUL_FW_DOWNLOAD_MAGIC)
1082 lbs_deb_spi("Firmware is already loaded for " 1081 lbs_deb_spi("Firmware is already loaded for "
1083 "Marvell WLAN 802.11 adapter\n"); 1082 "Marvell WLAN 802.11 adapter\n");
@@ -1085,7 +1084,7 @@ static int __devinit if_spi_probe(struct spi_device *spi)
1085 err = if_spi_calculate_fw_names(card->card_id, 1084 err = if_spi_calculate_fw_names(card->card_id,
1086 card->helper_fw_name, card->main_fw_name); 1085 card->helper_fw_name, card->main_fw_name);
1087 if (err) 1086 if (err)
1088 goto free_gpio; 1087 goto free_card;
1089 1088
1090 lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter " 1089 lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter "
1091 "(chip_id = 0x%04x, chip_rev = 0x%02x) " 1090 "(chip_id = 0x%04x, chip_rev = 0x%02x) "
@@ -1096,23 +1095,23 @@ static int __devinit if_spi_probe(struct spi_device *spi)
1096 spi->max_speed_hz); 1095 spi->max_speed_hz);
1097 err = if_spi_prog_helper_firmware(card); 1096 err = if_spi_prog_helper_firmware(card);
1098 if (err) 1097 if (err)
1099 goto free_gpio; 1098 goto free_card;
1100 err = if_spi_prog_main_firmware(card); 1099 err = if_spi_prog_main_firmware(card);
1101 if (err) 1100 if (err)
1102 goto free_gpio; 1101 goto free_card;
1103 lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n"); 1102 lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n");
1104 } 1103 }
1105 1104
1106 err = spu_set_interrupt_mode(card, 0, 1); 1105 err = spu_set_interrupt_mode(card, 0, 1);
1107 if (err) 1106 if (err)
1108 goto free_gpio; 1107 goto free_card;
1109 1108
1110 /* Register our card with libertas. 1109 /* Register our card with libertas.
1111 * This will call alloc_etherdev */ 1110 * This will call alloc_etherdev */
1112 priv = lbs_add_card(card, &spi->dev); 1111 priv = lbs_add_card(card, &spi->dev);
1113 if (!priv) { 1112 if (!priv) {
1114 err = -ENOMEM; 1113 err = -ENOMEM;
1115 goto free_gpio; 1114 goto free_card;
1116 } 1115 }
1117 card->priv = priv; 1116 card->priv = priv;
1118 priv->card = card; 1117 priv->card = card;
@@ -1157,8 +1156,6 @@ terminate_thread:
1157 if_spi_terminate_spi_thread(card); 1156 if_spi_terminate_spi_thread(card);
1158remove_card: 1157remove_card:
1159 lbs_remove_card(priv); /* will call free_netdev */ 1158 lbs_remove_card(priv); /* will call free_netdev */
1160free_gpio:
1161 gpio_free(card->gpio_cs);
1162free_card: 1159free_card:
1163 free_if_spi_card(card); 1160 free_if_spi_card(card);
1164out: 1161out:
@@ -1179,7 +1176,6 @@ static int __devexit libertas_spi_remove(struct spi_device *spi)
1179 free_irq(spi->irq, card); 1176 free_irq(spi->irq, card);
1180 if_spi_terminate_spi_thread(card); 1177 if_spi_terminate_spi_thread(card);
1181 lbs_remove_card(priv); /* will call free_netdev */ 1178 lbs_remove_card(priv); /* will call free_netdev */
1182 gpio_free(card->gpio_cs);
1183 if (card->pdata->teardown) 1179 if (card->pdata->teardown)
1184 card->pdata->teardown(spi); 1180 card->pdata->teardown(spi);
1185 free_if_spi_card(card); 1181 free_if_spi_card(card);