diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2009-06-04 15:57:03 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-06-10 13:27:50 -0400 |
commit | 4d1d49858c0a5a4fb1be4bc7972754cd640245ba (patch) | |
tree | fc481d282b7c7e45972b9d3b6cd2e903cac409e6 /drivers | |
parent | 582241a08409c89b086774c60b55c1a1706a7e5d (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/Kconfig | 2 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_spi.c | 92 |
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 | ||
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); |