diff options
-rw-r--r-- | drivers/net/wireless/Kconfig | 2 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_spi.c | 92 | ||||
-rw-r--r-- | include/linux/spi/libertas_spi.h | 3 |
3 files changed, 45 insertions, 52 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 | ||
154 | config LIBERTAS_SPI | 154 | config 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 | ||
136 | static void spu_transaction_finish(struct if_spi_card *card) | 127 | static 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(®_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 *)®_out, sizeof(u16)); | 153 | reg_trans.tx_buf = ®_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 | ||
162 | out: | 159 | spi_message_add_tail(®_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 | ||
187 | static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len) | 187 | static 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(®_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 *)®_out, sizeof(u16)); | 209 | reg_trans.tx_buf = ®_out; |
202 | if (err) | 210 | reg_trans.len = sizeof(reg_out); |
203 | goto out; | 211 | spi_message_add_tail(®_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 | ||
222 | out: | 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); |
1158 | remove_card: | 1157 | remove_card: |
1159 | lbs_remove_card(priv); /* will call free_netdev */ | 1158 | lbs_remove_card(priv); /* will call free_netdev */ |
1160 | free_gpio: | ||
1161 | gpio_free(card->gpio_cs); | ||
1162 | free_card: | 1159 | free_card: |
1163 | free_if_spi_card(card); | 1160 | free_if_spi_card(card); |
1164 | out: | 1161 | out: |
@@ -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); |
diff --git a/include/linux/spi/libertas_spi.h b/include/linux/spi/libertas_spi.h index 79506f5f9e67..1b5d5384fcd3 100644 --- a/include/linux/spi/libertas_spi.h +++ b/include/linux/spi/libertas_spi.h | |||
@@ -22,9 +22,6 @@ struct libertas_spi_platform_data { | |||
22 | * speed, you may want to use 0 here. */ | 22 | * speed, you may want to use 0 here. */ |
23 | u16 use_dummy_writes; | 23 | u16 use_dummy_writes; |
24 | 24 | ||
25 | /* GPIO number to use as chip select */ | ||
26 | u16 gpio_cs; | ||
27 | |||
28 | /* Board specific setup/teardown */ | 25 | /* Board specific setup/teardown */ |
29 | int (*setup)(struct spi_device *spi); | 26 | int (*setup)(struct spi_device *spi); |
30 | int (*teardown)(struct spi_device *spi); | 27 | int (*teardown)(struct spi_device *spi); |