Merge branch 'spi/next' into next

* spi/next: (15 commits)
  spi: spi-fsl-qspi: Introduce variable to fix different invalid master Id
  dt-bindings: spi: spi-fsl-qspi: Add bindings of ls1088a and ls1012a
  spi: spi-fsl-qspi: dynamically alloc AHB memory for QSPI
  spi: spi-nxp-fspi: Enable the Octal Mode in MCR0
  MLK-21960-2: spi: fspi: dynamically alloc AHB memory
  ...
This commit is contained in:
Dong Aisheng 2019-12-02 18:05:29 +08:00
commit b822384c41
6 changed files with 220 additions and 54 deletions

View File

@ -10,6 +10,8 @@ Required properties:
- "fsl,imx35-cspi" for SPI compatible with the one integrated on i.MX35
- "fsl,imx51-ecspi" for SPI compatible with the one integrated on i.MX51
- "fsl,imx53-ecspi" for SPI compatible with the one integrated on i.MX53 and later Soc
- "fsl,imx6ul-ecspi" ERR009165 fixed on i.MX6UL and later Soc
(https://www.nxp.com/docs/en/errata/IMX6DQCE.pdf)
- "fsl,imx8mq-ecspi" for SPI compatible with the one integrated on i.MX8M
- reg : Offset and length of the register set for the device
- interrupts : Should contain CSPI/eCSPI interrupt

View File

@ -6,6 +6,8 @@ Required properties:
"fsl,ls1021a-qspi", "fsl,ls2080a-qspi"
or
"fsl,ls1043a-qspi" followed by "fsl,ls1021a-qspi"
"fsl,ls1012a-qspi" followed by "fsl,ls1021a-qspi"
"fsl,ls1088a-qspi" followed by "fsl,ls2080a-qspi"
- reg : the first contains the register location and length,
the second contains the memory mapping address and length
- reg-names: Should contain the reg names "QuadSPI" and "QuadSPI-memory"

View File

@ -124,8 +124,6 @@ struct fsl_lpspi_data {
bool usedma;
struct completion dma_rx_completion;
struct completion dma_tx_completion;
int chipselect[0];
};
static const struct of_device_id fsl_lpspi_dt_ids[] = {
@ -230,10 +228,8 @@ static int lpspi_unprepare_xfer_hardware(struct spi_controller *controller)
static int fsl_lpspi_prepare_message(struct spi_controller *controller,
struct spi_message *msg)
{
struct fsl_lpspi_data *fsl_lpspi =
spi_controller_get_devdata(controller);
struct spi_device *spi = msg->spi;
int gpio = fsl_lpspi->chipselect[spi->chip_select];
int gpio = controller->cs_gpios[spi->chip_select];
if (gpio_is_valid(gpio))
gpio_direction_output(gpio, spi->mode & SPI_CS_HIGH ? 0 : 1);
@ -841,10 +837,15 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
struct spi_imx_master *lpspi_platform_info =
dev_get_platdata(&pdev->dev);
struct resource *res;
int i, ret, irq;
int i, ret, irq, num_cs;
u32 temp;
bool is_slave;
if (!np && !lpspi_platform_info) {
dev_err(&pdev->dev, "can't get the platform data\n");
return -EINVAL;
}
is_slave = of_property_read_bool((&pdev->dev)->of_node, "spi-slave");
if (is_slave)
controller = spi_alloc_slave(&pdev->dev,
@ -858,30 +859,42 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, controller);
ret = of_property_read_u32(np, "fsl,spi-num-chipselects", &num_cs);
if (ret < 0) {
if (lpspi_platform_info) {
num_cs = lpspi_platform_info->num_chipselect;
controller->num_chipselect = num_cs;
}
} else {
controller->num_chipselect = num_cs;
}
fsl_lpspi = spi_controller_get_devdata(controller);
fsl_lpspi->dev = &pdev->dev;
fsl_lpspi->is_slave = is_slave;
if (!fsl_lpspi->is_slave) {
controller->cs_gpios = devm_kzalloc(&controller->dev,
sizeof(int) * controller->num_chipselect, GFP_KERNEL);
for (i = 0; i < controller->num_chipselect; i++) {
int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
if (!gpio_is_valid(cs_gpio) && lpspi_platform_info)
cs_gpio = lpspi_platform_info->chipselect[i];
fsl_lpspi->chipselect[i] = cs_gpio;
controller->cs_gpios[i] = cs_gpio;
if (!gpio_is_valid(cs_gpio))
continue;
ret = devm_gpio_request(&pdev->dev,
fsl_lpspi->chipselect[i],
controller->cs_gpios[i],
DRIVER_NAME);
if (ret) {
dev_err(&pdev->dev, "can't get cs gpios\n");
goto out_controller_put;
}
}
controller->cs_gpios = fsl_lpspi->chipselect;
controller->prepare_message = fsl_lpspi_prepare_message;
}

View File

@ -63,6 +63,11 @@
#define QUADSPI_IPCR 0x08
#define QUADSPI_IPCR_SEQID(x) ((x) << 24)
#define QUADSPI_BUF0CR 0x10
#define QUADSPI_BUF1CR 0x14
#define QUADSPI_BUF2CR 0x18
#define QUADSPI_BUFXCR_INVALID_MSTRID 0xe
#define QUADSPI_BUF3CR 0x1c
#define QUADSPI_BUF3CR_ALLMST_MASK BIT(31)
#define QUADSPI_BUF3CR_ADATSZ(x) ((x) << 8)
@ -181,9 +186,12 @@
*/
#define QUADSPI_QUIRK_BASE_INTERNAL BIT(4)
#define QUADSPI_MIN_IOMAP SZ_4M
struct fsl_qspi_devtype_data {
unsigned int rxfifo;
unsigned int txfifo;
int invalid_mstrid;
unsigned int ahb_buf_size;
unsigned int quirks;
bool little_endian;
@ -192,6 +200,7 @@ struct fsl_qspi_devtype_data {
static const struct fsl_qspi_devtype_data vybrid_data = {
.rxfifo = SZ_128,
.txfifo = SZ_64,
.invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID,
.ahb_buf_size = SZ_1K,
.quirks = QUADSPI_QUIRK_SWAP_ENDIAN,
.little_endian = true,
@ -200,6 +209,7 @@ static const struct fsl_qspi_devtype_data vybrid_data = {
static const struct fsl_qspi_devtype_data imx6sx_data = {
.rxfifo = SZ_128,
.txfifo = SZ_512,
.invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID,
.ahb_buf_size = SZ_1K,
.quirks = QUADSPI_QUIRK_4X_INT_CLK | QUADSPI_QUIRK_TKT245618,
.little_endian = true,
@ -208,6 +218,7 @@ static const struct fsl_qspi_devtype_data imx6sx_data = {
static const struct fsl_qspi_devtype_data imx7d_data = {
.rxfifo = SZ_128,
.txfifo = SZ_512,
.invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID,
.ahb_buf_size = SZ_1K,
.quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK,
.little_endian = true,
@ -216,6 +227,7 @@ static const struct fsl_qspi_devtype_data imx7d_data = {
static const struct fsl_qspi_devtype_data imx6ul_data = {
.rxfifo = SZ_128,
.txfifo = SZ_512,
.invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID,
.ahb_buf_size = SZ_1K,
.quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK,
.little_endian = true,
@ -224,6 +236,7 @@ static const struct fsl_qspi_devtype_data imx6ul_data = {
static const struct fsl_qspi_devtype_data ls1021a_data = {
.rxfifo = SZ_128,
.txfifo = SZ_64,
.invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID,
.ahb_buf_size = SZ_1K,
.quirks = 0,
.little_endian = false,
@ -233,6 +246,7 @@ static const struct fsl_qspi_devtype_data ls2080a_data = {
.rxfifo = SZ_128,
.txfifo = SZ_64,
.ahb_buf_size = SZ_1K,
.invalid_mstrid = 0x0,
.quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_BASE_INTERNAL,
.little_endian = true,
};
@ -241,6 +255,9 @@ struct fsl_qspi {
void __iomem *iobase;
void __iomem *ahb_addr;
u32 memmap_phy;
u32 memmap_phy_size;
u32 memmap_start;
u32 memmap_len;
struct clk *clk, *clk_en;
struct device *dev;
struct completion c;
@ -519,11 +536,34 @@ static void fsl_qspi_select_mem(struct fsl_qspi *q, struct spi_device *spi)
fsl_qspi_invalidate(q);
}
static void fsl_qspi_read_ahb(struct fsl_qspi *q, const struct spi_mem_op *op)
static int fsl_qspi_read_ahb(struct fsl_qspi *q, const struct spi_mem_op *op)
{
u32 start = op->addr.val + q->selected * q->memmap_phy_size / 4;
u32 len = op->data.nbytes;
/* if necessary, ioremap before AHB read */
if ((!q->ahb_addr) || start < q->memmap_start ||
start + len > q->memmap_start + q->memmap_len) {
if (q->ahb_addr) {
iounmap(q->ahb_addr);
}
q->memmap_start = start;
q->memmap_len = len > QUADSPI_MIN_IOMAP ?
len : QUADSPI_MIN_IOMAP;
q->ahb_addr = ioremap_wc(q->memmap_phy + q->memmap_start,
q->memmap_len);
if (!q->ahb_addr) {
dev_err(q->dev, "failed to alloc memory\n");
return -ENOMEM;
}
}
memcpy_fromio(op->data.buf.in,
q->ahb_addr + q->selected * q->devtype_data->ahb_buf_size,
op->data.nbytes);
q->ahb_addr + start - q->memmap_start, len);
return 0;
}
static void fsl_qspi_fill_txfifo(struct fsl_qspi *q,
@ -615,6 +655,7 @@ static int fsl_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
void __iomem *base = q->iobase;
u32 addr_offset = 0;
int err = 0;
int invalid_mstrid = q->devtype_data->invalid_mstrid;
mutex_lock(&q->lock);
@ -628,7 +669,7 @@ static int fsl_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
addr_offset = q->memmap_phy;
qspi_writel(q,
q->selected * q->devtype_data->ahb_buf_size + addr_offset,
q->selected * q->memmap_phy_size / 4 + addr_offset,
base + QUADSPI_SFAR);
qspi_writel(q, qspi_readl(q, base + QUADSPI_MCR) |
@ -638,6 +679,10 @@ static int fsl_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
qspi_writel(q, QUADSPI_SPTRCLR_BFPTRC | QUADSPI_SPTRCLR_IPPTRC,
base + QUADSPI_SPTRCLR);
qspi_writel(q, invalid_mstrid, base + QUADSPI_BUF0CR);
qspi_writel(q, invalid_mstrid, base + QUADSPI_BUF1CR);
qspi_writel(q, invalid_mstrid, base + QUADSPI_BUF2CR);
fsl_qspi_prepare_lut(q, op);
/*
@ -647,7 +692,7 @@ static int fsl_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
*/
if (op->data.nbytes > (q->devtype_data->rxfifo - 4) &&
op->data.dir == SPI_MEM_DATA_IN) {
fsl_qspi_read_ahb(q, op);
err = fsl_qspi_read_ahb(q, op);
} else {
qspi_writel(q, QUADSPI_RBCT_WMRK_MASK |
QUADSPI_RBCT_RXBRD_USEIPS, base + QUADSPI_RBCT);
@ -735,16 +780,16 @@ static int fsl_qspi_default_setup(struct fsl_qspi *q)
* In HW there can be a maximum of four chips on two buses with
* two chip selects on each bus. We use four chip selects in SW
* to differentiate between the four chips.
* We use ahb_buf_size for each chip and set SFA1AD, SFA2AD, SFB1AD,
* SFB2AD accordingly.
* We divide the total memory region size equally for each chip
* and set SFA1AD, SFA2AD, SFB1AD, SFB2AD accordingly.
*/
qspi_writel(q, q->devtype_data->ahb_buf_size + addr_offset,
qspi_writel(q, q->memmap_phy_size / 4 + addr_offset,
base + QUADSPI_SFA1AD);
qspi_writel(q, q->devtype_data->ahb_buf_size * 2 + addr_offset,
qspi_writel(q, q->memmap_phy_size / 4 * 2 + addr_offset,
base + QUADSPI_SFA2AD);
qspi_writel(q, q->devtype_data->ahb_buf_size * 3 + addr_offset,
qspi_writel(q, q->memmap_phy_size / 4 * 3 + addr_offset,
base + QUADSPI_SFB1AD);
qspi_writel(q, q->devtype_data->ahb_buf_size * 4 + addr_offset,
qspi_writel(q, q->memmap_phy_size / 4 * 4 + addr_offset,
base + QUADSPI_SFB2AD);
q->selected = -1;
@ -831,13 +876,8 @@ static int fsl_qspi_probe(struct platform_device *pdev)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"QuadSPI-memory");
q->ahb_addr = devm_ioremap_resource(dev, res);
if (IS_ERR(q->ahb_addr)) {
ret = PTR_ERR(q->ahb_addr);
goto err_put_ctrl;
}
q->memmap_phy = res->start;
q->memmap_phy_size = resource_size(res);
/* find the clocks */
q->clk_en = devm_clk_get(dev, "qspi_en");
@ -911,6 +951,9 @@ static int fsl_qspi_remove(struct platform_device *pdev)
mutex_destroy(&q->lock);
if (q->ahb_addr)
iounmap(q->ahb_addr);
return 0;
}

View File

@ -57,6 +57,7 @@ enum spi_imx_devtype {
IMX35_CSPI, /* CSPI on all i.mx except above */
IMX51_ECSPI, /* ECSPI on i.mx51 */
IMX53_ECSPI, /* ECSPI on i.mx53 and later */
IMX6UL_ECSPI, /* ERR009165 fix from i.mx6ul */
};
struct spi_imx_data;
@ -128,7 +129,8 @@ static inline int is_imx35_cspi(struct spi_imx_data *d)
static inline int is_imx51_ecspi(struct spi_imx_data *d)
{
return d->devtype_data->devtype == IMX51_ECSPI;
return d->devtype_data->devtype == IMX51_ECSPI ||
d->devtype_data->devtype == IMX6UL_ECSPI;
}
static inline int is_imx53_ecspi(struct spi_imx_data *d)
@ -478,10 +480,17 @@ static void mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int enable)
static void mx51_ecspi_trigger(struct spi_imx_data *spi_imx)
{
u32 reg;
reg = readl(spi_imx->base + MX51_ECSPI_CTRL);
reg |= MX51_ECSPI_CTRL_XCH;
u32 reg = readl(spi_imx->base + MX51_ECSPI_CTRL);
/*
* To workaround ERR008517, SDMA script need use XCH instead of SMC
* just like PIO mode and it fix on i.mx6ul
*/
if (!spi_imx->usedma)
reg |= MX51_ECSPI_CTRL_XCH;
else if (spi_imx->devtype_data->devtype == IMX6UL_ECSPI)
reg |= MX51_ECSPI_CTRL_SMC;
else
reg &= ~MX51_ECSPI_CTRL_SMC;
writel(reg, spi_imx->base + MX51_ECSPI_CTRL);
}
@ -585,8 +594,16 @@ static int mx51_ecspi_prepare_transfer(struct spi_imx_data *spi_imx,
ctrl |= mx51_ecspi_clkdiv(spi_imx, t->speed_hz, &clk);
spi_imx->spi_bus_clk = clk;
if (spi_imx->usedma)
ctrl |= MX51_ECSPI_CTRL_SMC;
/*
* ERR009165: work in XHC mode instead of SMC as PIO on the chips
* before i.mx6ul.
*/
if (spi_imx->usedma) {
if (spi_imx->devtype_data->devtype == IMX6UL_ECSPI)
ctrl |= MX51_ECSPI_CTRL_SMC;
else
ctrl &= ~MX51_ECSPI_CTRL_SMC;
}
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
@ -612,12 +629,16 @@ static int mx51_ecspi_prepare_transfer(struct spi_imx_data *spi_imx,
static void mx51_setup_wml(struct spi_imx_data *spi_imx)
{
u32 tx_wml = 0;
if (spi_imx->devtype_data->devtype == IMX6UL_ECSPI)
tx_wml = spi_imx->wml;
/*
* Configure the DMA register: setup the watermark
* and enable DMA request.
*/
writel(MX51_ECSPI_DMA_RX_WML(spi_imx->wml - 1) |
MX51_ECSPI_DMA_TX_WML(spi_imx->wml) |
MX51_ECSPI_DMA_TX_WML(tx_wml) |
MX51_ECSPI_DMA_RXT_WML(spi_imx->wml) |
MX51_ECSPI_DMA_TEDEN | MX51_ECSPI_DMA_RXDEN |
MX51_ECSPI_DMA_RXTDEN, spi_imx->base + MX51_ECSPI_DMA);
@ -1009,6 +1030,22 @@ static struct spi_imx_devtype_data imx53_ecspi_devtype_data = {
.devtype = IMX53_ECSPI,
};
static struct spi_imx_devtype_data imx6ul_ecspi_devtype_data = {
.intctrl = mx51_ecspi_intctrl,
.prepare_message = mx51_ecspi_prepare_message,
.prepare_transfer = mx51_ecspi_prepare_transfer,
.trigger = mx51_ecspi_trigger,
.rx_available = mx51_ecspi_rx_available,
.reset = mx51_ecspi_reset,
.setup_wml = mx51_setup_wml,
.fifo_size = 64,
.has_dmamode = true,
.dynamic_burst = true,
.has_slavemode = true,
.disable = mx51_ecspi_disable,
.devtype = IMX6UL_ECSPI,
};
static const struct platform_device_id spi_imx_devtype[] = {
{
.name = "imx1-cspi",
@ -1031,6 +1068,9 @@ static const struct platform_device_id spi_imx_devtype[] = {
}, {
.name = "imx53-ecspi",
.driver_data = (kernel_ulong_t) &imx53_ecspi_devtype_data,
}, {
.name = "imx6ul-ecspi",
.driver_data = (kernel_ulong_t) &imx6ul_ecspi_devtype_data,
}, {
/* sentinel */
}
@ -1044,6 +1084,7 @@ static const struct of_device_id spi_imx_dt_ids[] = {
{ .compatible = "fsl,imx35-cspi", .data = &imx35_cspi_devtype_data, },
{ .compatible = "fsl,imx51-ecspi", .data = &imx51_ecspi_devtype_data, },
{ .compatible = "fsl,imx53-ecspi", .data = &imx53_ecspi_devtype_data, },
{ .compatible = "fsl,imx6ul-ecspi", .data = &imx6ul_ecspi_devtype_data, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, spi_imx_dt_ids);
@ -1265,10 +1306,6 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx,
{
int ret;
/* use pio mode for i.mx6dl chip TKT238285 */
if (of_machine_is_compatible("fsl,imx6dl"))
return 0;
spi_imx->wml = spi_imx->devtype_data->fifo_size / 2;
/* Prepare for TX DMA: */
@ -1396,6 +1433,8 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
transfer_timeout = spi_imx_calculate_timeout(spi_imx, transfer->len);
spi_imx->devtype_data->trigger(spi_imx);
/* Wait SDMA to finish the data transfer.*/
timeout = wait_for_completion_timeout(&spi_imx->dma_tx_completion,
transfer_timeout);
@ -1539,13 +1578,13 @@ spi_imx_prepare_message(struct spi_master *master, struct spi_message *msg)
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
int ret;
ret = clk_enable(spi_imx->clk_per);
ret = clk_prepare_enable(spi_imx->clk_per);
if (ret)
return ret;
ret = clk_enable(spi_imx->clk_ipg);
ret = clk_prepare_enable(spi_imx->clk_ipg);
if (ret) {
clk_disable(spi_imx->clk_per);
clk_disable_unprepare(spi_imx->clk_per);
return ret;
}
@ -1563,8 +1602,8 @@ spi_imx_unprepare_message(struct spi_master *master, struct spi_message *msg)
{
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
clk_disable(spi_imx->clk_ipg);
clk_disable(spi_imx->clk_per);
clk_disable_unprepare(spi_imx->clk_ipg);
clk_disable_unprepare(spi_imx->clk_per);
return 0;
}
@ -1752,8 +1791,8 @@ static int spi_imx_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "probed\n");
clk_disable(spi_imx->clk_ipg);
clk_disable(spi_imx->clk_per);
clk_disable_unprepare(spi_imx->clk_ipg);
clk_disable_unprepare(spi_imx->clk_per);
return ret;
out_spi_bitbang:
@ -1795,11 +1834,31 @@ static int spi_imx_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int spi_imx_suspend(struct device *dev)
{
pinctrl_pm_select_sleep_state(dev);
return 0;
}
static int spi_imx_resume(struct device *dev)
{
pinctrl_pm_select_default_state(dev);
return 0;
}
static SIMPLE_DEV_PM_OPS(imx_spi_pm, spi_imx_suspend, spi_imx_resume);
#define IMX_SPI_PM (&imx_spi_pm)
#else
#define IMX_SPI_PM NULL
#endif
static struct platform_driver spi_imx_driver = {
.driver = {
.name = DRIVER_NAME,
.of_match_table = spi_imx_dt_ids,
},
.pm = IMX_SPI_PM,
},
.id_table = spi_imx_devtype,
.probe = spi_imx_probe,
.remove = spi_imx_remove,

View File

@ -307,6 +307,7 @@
#define POLL_TOUT 5000
#define NXP_FSPI_MAX_CHIPSELECT 4
#define NXP_FSPI_MIN_IOMAP SZ_4M
struct nxp_fspi_devtype_data {
unsigned int rxfifo;
@ -324,11 +325,29 @@ static const struct nxp_fspi_devtype_data lx2160a_data = {
.little_endian = true, /* little-endian */
};
static const struct nxp_fspi_devtype_data imx8mm_data = {
.rxfifo = SZ_512, /* (64 * 64 bits) */
.txfifo = SZ_1K, /* (128 * 64 bits) */
.ahb_buf_size = SZ_2K, /* (256 * 64 bits) */
.quirks = 0,
.little_endian = true, /* little-endian */
};
static const struct nxp_fspi_devtype_data imx8qxp_data = {
.rxfifo = SZ_512, /* (64 * 64 bits) */
.txfifo = SZ_1K, /* (128 * 64 bits) */
.ahb_buf_size = SZ_2K, /* (256 * 64 bits) */
.quirks = 0,
.little_endian = true, /* little-endian */
};
struct nxp_fspi {
void __iomem *iobase;
void __iomem *ahb_addr;
u32 memmap_phy;
u32 memmap_phy_size;
u32 memmap_start;
u32 memmap_len;
struct clk *clk, *clk_en;
struct device *dev;
struct completion c;
@ -641,12 +660,35 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi)
f->selected = spi->chip_select;
}
static void nxp_fspi_read_ahb(struct nxp_fspi *f, const struct spi_mem_op *op)
static int nxp_fspi_read_ahb(struct nxp_fspi *f, const struct spi_mem_op *op)
{
u32 start = op->addr.val;
u32 len = op->data.nbytes;
/* if necessary, ioremap before AHB read */
if ((!f->ahb_addr) || start < f->memmap_start ||
start + len > f->memmap_start + f->memmap_len) {
if (f->ahb_addr)
iounmap(f->ahb_addr);
f->memmap_start = start;
f->memmap_len = len > NXP_FSPI_MIN_IOMAP ?
len : NXP_FSPI_MIN_IOMAP;
f->ahb_addr = ioremap_wc(f->memmap_phy + f->memmap_start,
f->memmap_len);
if (!f->ahb_addr) {
dev_err(f->dev, "failed to alloc memory\n");
return -ENOMEM;
}
}
/* Read out the data directly from the AHB buffer. */
memcpy_fromio(op->data.buf.in, (f->ahb_addr + op->addr.val), len);
memcpy_fromio(op->data.buf.in,
f->ahb_addr + start - f->memmap_start, len);
return 0;
}
static void nxp_fspi_fill_txfifo(struct nxp_fspi *f,
@ -806,7 +848,7 @@ static int nxp_fspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
*/
if (op->data.nbytes > (f->devtype_data->rxfifo - 4) &&
op->data.dir == SPI_MEM_DATA_IN) {
nxp_fspi_read_ahb(f, op);
err = nxp_fspi_read_ahb(f, op);
} else {
if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT)
nxp_fspi_fill_txfifo(f, op);
@ -871,8 +913,9 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f)
fspi_writel(f, FSPI_DLLBCR_OVRDEN, base + FSPI_DLLBCR);
/* enable module */
fspi_writel(f, FSPI_MCR0_AHB_TIMEOUT(0xFF) | FSPI_MCR0_IP_TIMEOUT(0xFF),
base + FSPI_MCR0);
fspi_writel(f, FSPI_MCR0_AHB_TIMEOUT(0xFF) |
FSPI_MCR0_IP_TIMEOUT(0xFF) | (u32) FSPI_MCR0_OCTCOMB_EN,
base + FSPI_MCR0);
/*
* Disable same device enable bit and configure all slave devices
@ -976,9 +1019,8 @@ static int nxp_fspi_probe(struct platform_device *pdev)
/* find the resources - controller memory mapped space */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fspi_mmap");
f->ahb_addr = devm_ioremap_resource(dev, res);
if (IS_ERR(f->ahb_addr)) {
ret = PTR_ERR(f->ahb_addr);
if (IS_ERR(res)) {
ret = PTR_ERR(res);
goto err_put_ctrl;
}
@ -1057,6 +1099,9 @@ static int nxp_fspi_remove(struct platform_device *pdev)
mutex_destroy(&f->lock);
if (f->ahb_addr)
iounmap(f->ahb_addr);
return 0;
}
@ -1076,6 +1121,8 @@ static int nxp_fspi_resume(struct device *dev)
static const struct of_device_id nxp_fspi_dt_ids[] = {
{ .compatible = "nxp,lx2160a-fspi", .data = (void *)&lx2160a_data, },
{ .compatible = "nxp,imx8mm-fspi", .data = (void *)&imx8mm_data, },
{ .compatible = "nxp,imx8qxp-fspi", .data = (void *)&imx8qxp_data, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, nxp_fspi_dt_ids);