summaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi-mem.c')
-rw-r--r--drivers/spi/spi-mem.c63
1 files changed, 42 insertions, 21 deletions
diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
index 967f581bca4f..7916e655afc8 100644
--- a/drivers/spi/spi-mem.c
+++ b/drivers/spi/spi-mem.c
@@ -213,6 +213,44 @@ bool spi_mem_supports_op(struct spi_mem *mem, const struct spi_mem_op *op)
213} 213}
214EXPORT_SYMBOL_GPL(spi_mem_supports_op); 214EXPORT_SYMBOL_GPL(spi_mem_supports_op);
215 215
216static int spi_mem_access_start(struct spi_mem *mem)
217{
218 struct spi_controller *ctlr = mem->spi->controller;
219
220 /*
221 * Flush the message queue before executing our SPI memory
222 * operation to prevent preemption of regular SPI transfers.
223 */
224 spi_flush_queue(ctlr);
225
226 if (ctlr->auto_runtime_pm) {
227 int ret;
228
229 ret = pm_runtime_get_sync(ctlr->dev.parent);
230 if (ret < 0) {
231 dev_err(&ctlr->dev, "Failed to power device: %d\n",
232 ret);
233 return ret;
234 }
235 }
236
237 mutex_lock(&ctlr->bus_lock_mutex);
238 mutex_lock(&ctlr->io_mutex);
239
240 return 0;
241}
242
243static void spi_mem_access_end(struct spi_mem *mem)
244{
245 struct spi_controller *ctlr = mem->spi->controller;
246
247 mutex_unlock(&ctlr->io_mutex);
248 mutex_unlock(&ctlr->bus_lock_mutex);
249
250 if (ctlr->auto_runtime_pm)
251 pm_runtime_put(ctlr->dev.parent);
252}
253
216/** 254/**
217 * spi_mem_exec_op() - Execute a memory operation 255 * spi_mem_exec_op() - Execute a memory operation
218 * @mem: the SPI memory 256 * @mem: the SPI memory
@@ -242,30 +280,13 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
242 return -ENOTSUPP; 280 return -ENOTSUPP;
243 281
244 if (ctlr->mem_ops) { 282 if (ctlr->mem_ops) {
245 /* 283 ret = spi_mem_access_start(mem);
246 * Flush the message queue before executing our SPI memory 284 if (ret)
247 * operation to prevent preemption of regular SPI transfers. 285 return ret;
248 */
249 spi_flush_queue(ctlr);
250
251 if (ctlr->auto_runtime_pm) {
252 ret = pm_runtime_get_sync(ctlr->dev.parent);
253 if (ret < 0) {
254 dev_err(&ctlr->dev,
255 "Failed to power device: %d\n",
256 ret);
257 return ret;
258 }
259 }
260 286
261 mutex_lock(&ctlr->bus_lock_mutex);
262 mutex_lock(&ctlr->io_mutex);
263 ret = ctlr->mem_ops->exec_op(mem, op); 287 ret = ctlr->mem_ops->exec_op(mem, op);
264 mutex_unlock(&ctlr->io_mutex);
265 mutex_unlock(&ctlr->bus_lock_mutex);
266 288
267 if (ctlr->auto_runtime_pm) 289 spi_mem_access_end(mem);
268 pm_runtime_put(ctlr->dev.parent);
269 290
270 /* 291 /*
271 * Some controllers only optimize specific paths (typically the 292 * Some controllers only optimize specific paths (typically the