diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2012-03-14 05:47:40 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2012-03-15 05:40:44 -0400 |
commit | ec139b67ad00647239b804d6f15315b83dba9a58 (patch) | |
tree | af2ccd153e4a00c57b3e0b9f7d0c00a8bebb1cf5 /drivers/spi/spi-sh-hspi.c | |
parent | 6ea41a2bee0aa540425e118133b4c97ce5f0806d (diff) |
spi: sh-hspi: convert to using core message queue
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/spi/spi-sh-hspi.c')
-rw-r--r-- | drivers/spi/spi-sh-hspi.c | 152 |
1 files changed, 55 insertions, 97 deletions
diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c index 8356ec8cfda2..42906731c40d 100644 --- a/drivers/spi/spi-sh-hspi.c +++ b/drivers/spi/spi-sh-hspi.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/timer.h> | 27 | #include <linux/timer.h> |
28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
29 | #include <linux/list.h> | 29 | #include <linux/list.h> |
30 | #include <linux/workqueue.h> | ||
31 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
32 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
33 | #include <linux/pm_runtime.h> | 32 | #include <linux/pm_runtime.h> |
@@ -50,11 +49,7 @@ | |||
50 | struct hspi_priv { | 49 | struct hspi_priv { |
51 | void __iomem *addr; | 50 | void __iomem *addr; |
52 | struct spi_master *master; | 51 | struct spi_master *master; |
53 | struct list_head queue; | ||
54 | struct workqueue_struct *workqueue; | ||
55 | struct work_struct ws; | ||
56 | struct device *dev; | 52 | struct device *dev; |
57 | spinlock_t lock; | ||
58 | }; | 53 | }; |
59 | 54 | ||
60 | /* | 55 | /* |
@@ -148,88 +143,82 @@ static int hspi_pop(struct hspi_priv *hspi, struct spi_message *msg, | |||
148 | return 0; | 143 | return 0; |
149 | } | 144 | } |
150 | 145 | ||
151 | static void hspi_work(struct work_struct *work) | 146 | /* |
147 | * spi master function | ||
148 | */ | ||
149 | static int hspi_prepare_transfer(struct spi_master *master) | ||
152 | { | 150 | { |
153 | struct hspi_priv *hspi = container_of(work, struct hspi_priv, ws); | 151 | struct hspi_priv *hspi = spi_master_get_devdata(master); |
154 | struct sh_hspi_info *info = hspi2info(hspi); | ||
155 | struct spi_message *msg; | ||
156 | struct spi_transfer *t; | ||
157 | unsigned long flags; | ||
158 | u32 data; | ||
159 | int ret; | ||
160 | |||
161 | dev_dbg(hspi->dev, "%s\n", __func__); | ||
162 | 152 | ||
163 | /************************ pm enable ************************/ | ||
164 | pm_runtime_get_sync(hspi->dev); | 153 | pm_runtime_get_sync(hspi->dev); |
154 | return 0; | ||
155 | } | ||
165 | 156 | ||
166 | /* setup first of all in under pm_runtime */ | 157 | static int hspi_unprepare_transfer(struct spi_master *master) |
167 | data = SH_HSPI_CLK_DIVC(info->flags); | 158 | { |
159 | struct hspi_priv *hspi = spi_master_get_devdata(master); | ||
168 | 160 | ||
169 | if (info->flags & SH_HSPI_FBS) | 161 | pm_runtime_put_sync(hspi->dev); |
170 | data |= 1 << 7; | 162 | return 0; |
171 | if (info->flags & SH_HSPI_CLKP_HIGH) | 163 | } |
172 | data |= 1 << 6; | ||
173 | if (info->flags & SH_HSPI_IDIV_DIV128) | ||
174 | data |= 1 << 5; | ||
175 | 164 | ||
176 | hspi_write(hspi, SPCR, data); | 165 | static int hspi_transfer_one_message(struct spi_master *master, |
177 | hspi_write(hspi, SPSR, 0x0); | 166 | struct spi_message *msg) |
178 | hspi_write(hspi, SPSCR, 0x1); /* master mode */ | 167 | { |
168 | struct hspi_priv *hspi = spi_master_get_devdata(master); | ||
169 | struct spi_transfer *t; | ||
170 | int ret; | ||
179 | 171 | ||
180 | while (1) { | 172 | dev_dbg(hspi->dev, "%s\n", __func__); |
181 | msg = NULL; | ||
182 | 173 | ||
183 | /************************ spin lock ************************/ | 174 | ret = 0; |
184 | spin_lock_irqsave(&hspi->lock, flags); | 175 | list_for_each_entry(t, &msg->transfers, transfer_list) { |
185 | if (!list_empty(&hspi->queue)) { | 176 | if (t->tx_buf) { |
186 | msg = list_entry(hspi->queue.next, | 177 | ret = hspi_push(hspi, msg, t); |
187 | struct spi_message, queue); | 178 | if (ret < 0) |
188 | list_del_init(&msg->queue); | 179 | goto error; |
189 | } | 180 | } |
190 | spin_unlock_irqrestore(&hspi->lock, flags); | 181 | if (t->rx_buf) { |
191 | /************************ spin unlock ************************/ | 182 | ret = hspi_pop(hspi, msg, t); |
192 | if (!msg) | 183 | if (ret < 0) |
193 | break; | 184 | goto error; |
194 | |||
195 | ret = 0; | ||
196 | list_for_each_entry(t, &msg->transfers, transfer_list) { | ||
197 | if (t->tx_buf) { | ||
198 | ret = hspi_push(hspi, msg, t); | ||
199 | if (ret < 0) | ||
200 | goto error; | ||
201 | } | ||
202 | if (t->rx_buf) { | ||
203 | ret = hspi_pop(hspi, msg, t); | ||
204 | if (ret < 0) | ||
205 | goto error; | ||
206 | } | ||
207 | msg->actual_length += t->len; | ||
208 | } | 185 | } |
209 | error: | 186 | msg->actual_length += t->len; |
210 | msg->status = ret; | ||
211 | msg->complete(msg->context); | ||
212 | } | 187 | } |
188 | error: | ||
213 | 189 | ||
214 | pm_runtime_put_sync(hspi->dev); | 190 | msg->status = ret; |
215 | /************************ pm disable ************************/ | 191 | spi_finalize_current_message(master); |
216 | 192 | ||
217 | return; | 193 | return ret; |
218 | } | 194 | } |
219 | 195 | ||
220 | /* | ||
221 | * spi master function | ||
222 | */ | ||
223 | static int hspi_setup(struct spi_device *spi) | 196 | static int hspi_setup(struct spi_device *spi) |
224 | { | 197 | { |
225 | struct hspi_priv *hspi = spi_master_get_devdata(spi->master); | 198 | struct hspi_priv *hspi = spi_master_get_devdata(spi->master); |
226 | struct device *dev = hspi->dev; | 199 | struct device *dev = hspi->dev; |
200 | struct sh_hspi_info *info = hspi2info(hspi); | ||
201 | u32 data; | ||
227 | 202 | ||
228 | if (8 != spi->bits_per_word) { | 203 | if (8 != spi->bits_per_word) { |
229 | dev_err(dev, "bits_per_word should be 8\n"); | 204 | dev_err(dev, "bits_per_word should be 8\n"); |
230 | return -EIO; | 205 | return -EIO; |
231 | } | 206 | } |
232 | 207 | ||
208 | /* setup first of all in under pm_runtime */ | ||
209 | data = SH_HSPI_CLK_DIVC(info->flags); | ||
210 | |||
211 | if (info->flags & SH_HSPI_FBS) | ||
212 | data |= 1 << 7; | ||
213 | if (info->flags & SH_HSPI_CLKP_HIGH) | ||
214 | data |= 1 << 6; | ||
215 | if (info->flags & SH_HSPI_IDIV_DIV128) | ||
216 | data |= 1 << 5; | ||
217 | |||
218 | hspi_write(hspi, SPCR, data); | ||
219 | hspi_write(hspi, SPSR, 0x0); | ||
220 | hspi_write(hspi, SPSCR, 0x1); /* master mode */ | ||
221 | |||
233 | dev_dbg(dev, "%s setup\n", spi->modalias); | 222 | dev_dbg(dev, "%s setup\n", spi->modalias); |
234 | 223 | ||
235 | return 0; | 224 | return 0; |
@@ -243,26 +232,6 @@ static void hspi_cleanup(struct spi_device *spi) | |||
243 | dev_dbg(dev, "%s cleanup\n", spi->modalias); | 232 | dev_dbg(dev, "%s cleanup\n", spi->modalias); |
244 | } | 233 | } |
245 | 234 | ||
246 | static int hspi_transfer(struct spi_device *spi, struct spi_message *msg) | ||
247 | { | ||
248 | struct hspi_priv *hspi = spi_master_get_devdata(spi->master); | ||
249 | unsigned long flags; | ||
250 | |||
251 | /************************ spin lock ************************/ | ||
252 | spin_lock_irqsave(&hspi->lock, flags); | ||
253 | |||
254 | msg->actual_length = 0; | ||
255 | msg->status = -EINPROGRESS; | ||
256 | list_add_tail(&msg->queue, &hspi->queue); | ||
257 | |||
258 | spin_unlock_irqrestore(&hspi->lock, flags); | ||
259 | /************************ spin unlock ************************/ | ||
260 | |||
261 | queue_work(hspi->workqueue, &hspi->ws); | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static int __devinit hspi_probe(struct platform_device *pdev) | 235 | static int __devinit hspi_probe(struct platform_device *pdev) |
267 | { | 236 | { |
268 | struct resource *res; | 237 | struct resource *res; |
@@ -296,27 +265,19 @@ static int __devinit hspi_probe(struct platform_device *pdev) | |||
296 | ret = -ENOMEM; | 265 | ret = -ENOMEM; |
297 | goto error1; | 266 | goto error1; |
298 | } | 267 | } |
299 | hspi->workqueue = create_singlethread_workqueue(dev_name(&pdev->dev)); | ||
300 | if (!hspi->workqueue) { | ||
301 | dev_err(&pdev->dev, "create workqueue error\n"); | ||
302 | ret = -EBUSY; | ||
303 | goto error2; | ||
304 | } | ||
305 | |||
306 | spin_lock_init(&hspi->lock); | ||
307 | INIT_LIST_HEAD(&hspi->queue); | ||
308 | INIT_WORK(&hspi->ws, hspi_work); | ||
309 | 268 | ||
310 | master->num_chipselect = 1; | 269 | master->num_chipselect = 1; |
311 | master->bus_num = pdev->id; | 270 | master->bus_num = pdev->id; |
312 | master->setup = hspi_setup; | 271 | master->setup = hspi_setup; |
313 | master->transfer = hspi_transfer; | ||
314 | master->cleanup = hspi_cleanup; | 272 | master->cleanup = hspi_cleanup; |
315 | master->mode_bits = SPI_CPOL | SPI_CPHA; | 273 | master->mode_bits = SPI_CPOL | SPI_CPHA; |
274 | master->prepare_transfer_hardware = hspi_prepare_transfer; | ||
275 | master->transfer_one_message = hspi_transfer_one_message; | ||
276 | master->unprepare_transfer_hardware = hspi_unprepare_transfer; | ||
316 | ret = spi_register_master(master); | 277 | ret = spi_register_master(master); |
317 | if (ret < 0) { | 278 | if (ret < 0) { |
318 | dev_err(&pdev->dev, "spi_register_master error.\n"); | 279 | dev_err(&pdev->dev, "spi_register_master error.\n"); |
319 | goto error3; | 280 | goto error2; |
320 | } | 281 | } |
321 | 282 | ||
322 | pm_runtime_enable(&pdev->dev); | 283 | pm_runtime_enable(&pdev->dev); |
@@ -325,8 +286,6 @@ static int __devinit hspi_probe(struct platform_device *pdev) | |||
325 | 286 | ||
326 | return 0; | 287 | return 0; |
327 | 288 | ||
328 | error3: | ||
329 | destroy_workqueue(hspi->workqueue); | ||
330 | error2: | 289 | error2: |
331 | devm_iounmap(hspi->dev, hspi->addr); | 290 | devm_iounmap(hspi->dev, hspi->addr); |
332 | error1: | 291 | error1: |
@@ -342,7 +301,6 @@ static int __devexit hspi_remove(struct platform_device *pdev) | |||
342 | pm_runtime_disable(&pdev->dev); | 301 | pm_runtime_disable(&pdev->dev); |
343 | 302 | ||
344 | spi_unregister_master(hspi->master); | 303 | spi_unregister_master(hspi->master); |
345 | destroy_workqueue(hspi->workqueue); | ||
346 | devm_iounmap(hspi->dev, hspi->addr); | 304 | devm_iounmap(hspi->dev, hspi->addr); |
347 | 305 | ||
348 | return 0; | 306 | return 0; |