Skip to content

Commit c0a0203

Browse files
Csókás, Bencebroonie
authored andcommitted
spi: atmel-quadspi: Create atmel_qspi_ops to support newer SoC families
Refactor the code to introduce an ops struct, to prepare for merging support for later SoCs, such as SAMA7G5. This code was based on the vendor's kernel (linux4microchip). Cc'ing original contributors. Signed-off-by: Csókás, Bence <csokas.bence@prolan.hu> Link: https://patch.msgid.link/20241128174316.3209354-2-csokas.bence@prolan.hu Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 3f3b063 commit c0a0203

File tree

1 file changed

+77
-34
lines changed

1 file changed

+77
-34
lines changed

drivers/spi/atmel-quadspi.c

Lines changed: 77 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -138,25 +138,38 @@
138138
#define QSPI_WPSR_WPVSRC_MASK GENMASK(15, 8)
139139
#define QSPI_WPSR_WPVSRC(src) (((src) << 8) & QSPI_WPSR_WPVSRC)
140140

141+
#define ATMEL_QSPI_TIMEOUT 1000 /* ms */
142+
141143
struct atmel_qspi_caps {
142144
bool has_qspick;
143145
bool has_ricr;
144146
};
145147

148+
struct atmel_qspi_ops;
149+
146150
struct atmel_qspi {
147151
void __iomem *regs;
148152
void __iomem *mem;
149153
struct clk *pclk;
150154
struct clk *qspick;
151155
struct platform_device *pdev;
152156
const struct atmel_qspi_caps *caps;
157+
const struct atmel_qspi_ops *ops;
153158
resource_size_t mmap_size;
154159
u32 pending;
160+
u32 irq_mask;
155161
u32 mr;
156162
u32 scr;
157163
struct completion cmd_completion;
158164
};
159165

166+
struct atmel_qspi_ops {
167+
int (*set_cfg)(struct atmel_qspi *aq, const struct spi_mem_op *op,
168+
u32 *offset);
169+
int (*transfer)(struct spi_mem *mem, const struct spi_mem_op *op,
170+
u32 offset);
171+
};
172+
160173
struct atmel_qspi_mode {
161174
u8 cmd_buswidth;
162175
u8 addr_buswidth;
@@ -404,10 +417,60 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq,
404417
return 0;
405418
}
406419

420+
static int atmel_qspi_wait_for_completion(struct atmel_qspi *aq, u32 irq_mask)
421+
{
422+
int err = 0;
423+
u32 sr;
424+
425+
/* Poll INSTRuction End status */
426+
sr = atmel_qspi_read(aq, QSPI_SR);
427+
if ((sr & irq_mask) == irq_mask)
428+
return 0;
429+
430+
/* Wait for INSTRuction End interrupt */
431+
reinit_completion(&aq->cmd_completion);
432+
aq->pending = sr & irq_mask;
433+
aq->irq_mask = irq_mask;
434+
atmel_qspi_write(irq_mask, aq, QSPI_IER);
435+
if (!wait_for_completion_timeout(&aq->cmd_completion,
436+
msecs_to_jiffies(ATMEL_QSPI_TIMEOUT)))
437+
err = -ETIMEDOUT;
438+
atmel_qspi_write(irq_mask, aq, QSPI_IDR);
439+
440+
return err;
441+
}
442+
443+
static int atmel_qspi_transfer(struct spi_mem *mem,
444+
const struct spi_mem_op *op, u32 offset)
445+
{
446+
struct atmel_qspi *aq = spi_controller_get_devdata(mem->spi->controller);
447+
448+
/* Skip to the final steps if there is no data */
449+
if (!op->data.nbytes)
450+
return atmel_qspi_wait_for_completion(aq,
451+
QSPI_SR_CMD_COMPLETED);
452+
453+
/* Dummy read of QSPI_IFR to synchronize APB and AHB accesses */
454+
(void)atmel_qspi_read(aq, QSPI_IFR);
455+
456+
/* Send/Receive data */
457+
if (op->data.dir == SPI_MEM_DATA_IN)
458+
memcpy_fromio(op->data.buf.in, aq->mem + offset,
459+
op->data.nbytes);
460+
else
461+
memcpy_toio(aq->mem + offset, op->data.buf.out,
462+
op->data.nbytes);
463+
464+
/* Release the chip-select */
465+
atmel_qspi_write(QSPI_CR_LASTXFER, aq, QSPI_CR);
466+
467+
return atmel_qspi_wait_for_completion(aq, QSPI_SR_CMD_COMPLETED);
468+
}
469+
407470
static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
408471
{
409472
struct atmel_qspi *aq = spi_controller_get_devdata(mem->spi->controller);
410-
u32 sr, offset;
473+
u32 offset;
411474
int err;
412475

413476
/*
@@ -416,46 +479,20 @@ static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
416479
* when the flash memories overrun the controller's memory space.
417480
*/
418481
if (op->addr.val + op->data.nbytes > aq->mmap_size)
419-
return -ENOTSUPP;
482+
return -EOPNOTSUPP;
483+
484+
if (op->addr.nbytes > 4)
485+
return -EOPNOTSUPP;
420486

421487
err = pm_runtime_resume_and_get(&aq->pdev->dev);
422488
if (err < 0)
423489
return err;
424490

425-
err = atmel_qspi_set_cfg(aq, op, &offset);
491+
err = aq->ops->set_cfg(aq, op, &offset);
426492
if (err)
427493
goto pm_runtime_put;
428494

429-
/* Skip to the final steps if there is no data */
430-
if (op->data.nbytes) {
431-
/* Dummy read of QSPI_IFR to synchronize APB and AHB accesses */
432-
(void)atmel_qspi_read(aq, QSPI_IFR);
433-
434-
/* Send/Receive data */
435-
if (op->data.dir == SPI_MEM_DATA_IN)
436-
memcpy_fromio(op->data.buf.in, aq->mem + offset,
437-
op->data.nbytes);
438-
else
439-
memcpy_toio(aq->mem + offset, op->data.buf.out,
440-
op->data.nbytes);
441-
442-
/* Release the chip-select */
443-
atmel_qspi_write(QSPI_CR_LASTXFER, aq, QSPI_CR);
444-
}
445-
446-
/* Poll INSTRuction End status */
447-
sr = atmel_qspi_read(aq, QSPI_SR);
448-
if ((sr & QSPI_SR_CMD_COMPLETED) == QSPI_SR_CMD_COMPLETED)
449-
goto pm_runtime_put;
450-
451-
/* Wait for INSTRuction End interrupt */
452-
reinit_completion(&aq->cmd_completion);
453-
aq->pending = sr & QSPI_SR_CMD_COMPLETED;
454-
atmel_qspi_write(QSPI_SR_CMD_COMPLETED, aq, QSPI_IER);
455-
if (!wait_for_completion_timeout(&aq->cmd_completion,
456-
msecs_to_jiffies(1000)))
457-
err = -ETIMEDOUT;
458-
atmel_qspi_write(QSPI_SR_CMD_COMPLETED, aq, QSPI_IDR);
495+
err = aq->ops->transfer(mem, op, offset);
459496

460497
pm_runtime_put:
461498
pm_runtime_mark_last_busy(&aq->pdev->dev);
@@ -599,12 +636,17 @@ static irqreturn_t atmel_qspi_interrupt(int irq, void *dev_id)
599636
return IRQ_NONE;
600637

601638
aq->pending |= pending;
602-
if ((aq->pending & QSPI_SR_CMD_COMPLETED) == QSPI_SR_CMD_COMPLETED)
639+
if ((aq->pending & aq->irq_mask) == aq->irq_mask)
603640
complete(&aq->cmd_completion);
604641

605642
return IRQ_HANDLED;
606643
}
607644

645+
static const struct atmel_qspi_ops atmel_qspi_ops = {
646+
.set_cfg = atmel_qspi_set_cfg,
647+
.transfer = atmel_qspi_transfer,
648+
};
649+
608650
static int atmel_qspi_probe(struct platform_device *pdev)
609651
{
610652
struct spi_controller *ctrl;
@@ -629,6 +671,7 @@ static int atmel_qspi_probe(struct platform_device *pdev)
629671

630672
init_completion(&aq->cmd_completion);
631673
aq->pdev = pdev;
674+
aq->ops = &atmel_qspi_ops;
632675

633676
/* Map the registers */
634677
aq->regs = devm_platform_ioremap_resource_byname(pdev, "qspi_base");

0 commit comments

Comments
 (0)