mirror of https://github.com/torvalds/linux.git
spi: airoha: add support of en7523 SoC (for 6.19)
Merge series from Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>: Airoha EN7523 snfi controller almost identical to AN7581 one, so the same driver can be used. The only known difference appears in the very specific boot conditions, when attached serial console force EN7523 SoC boots in undocumented (reserved) mode. In this mode dma reading of the flash works incorrectly. This patch series: * add support of EN7523 SoC * add spinand node to en7523 dts (so spinand flash finally becomes usable) * updates dt-bindings to mark driver as compatible with en7523 * disable dma usage to prevent possible data damage if booting in reserved mode was detected.
This commit is contained in:
commit
a9277a860a
|
|
@ -14,7 +14,12 @@ allOf:
|
|||
|
||||
properties:
|
||||
compatible:
|
||||
const: airoha,en7581-snand
|
||||
oneOf:
|
||||
- const: airoha,en7581-snand
|
||||
- items:
|
||||
- enum:
|
||||
- airoha,en7523-snand
|
||||
- const: airoha,en7581-snand
|
||||
|
||||
reg:
|
||||
items:
|
||||
|
|
|
|||
|
|
@ -1013,6 +1013,11 @@ static const struct spi_controller_mem_ops airoha_snand_mem_ops = {
|
|||
.dirmap_write = airoha_snand_dirmap_write,
|
||||
};
|
||||
|
||||
static const struct spi_controller_mem_ops airoha_snand_nodma_mem_ops = {
|
||||
.supports_op = airoha_snand_supports_op,
|
||||
.exec_op = airoha_snand_exec_op,
|
||||
};
|
||||
|
||||
static int airoha_snand_setup(struct spi_device *spi)
|
||||
{
|
||||
struct airoha_snand_ctrl *as_ctrl;
|
||||
|
|
@ -1057,7 +1062,9 @@ static int airoha_snand_probe(struct platform_device *pdev)
|
|||
struct airoha_snand_ctrl *as_ctrl;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct spi_controller *ctrl;
|
||||
bool dma_enable = true;
|
||||
void __iomem *base;
|
||||
u32 sfc_strap;
|
||||
int err;
|
||||
|
||||
ctrl = devm_spi_alloc_host(dev, sizeof(*as_ctrl));
|
||||
|
|
@ -1092,12 +1099,28 @@ static int airoha_snand_probe(struct platform_device *pdev)
|
|||
return dev_err_probe(dev, PTR_ERR(as_ctrl->spi_clk),
|
||||
"unable to get spi clk\n");
|
||||
|
||||
if (device_is_compatible(dev, "airoha,en7523-snand")) {
|
||||
err = regmap_read(as_ctrl->regmap_ctrl,
|
||||
REG_SPI_CTRL_SFC_STRAP, &sfc_strap);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!(sfc_strap & 0x04)) {
|
||||
dma_enable = false;
|
||||
dev_warn(dev, "Detected booting in RESERVED mode (UART_TXD was short to GND).\n");
|
||||
dev_warn(dev, "This mode is known for incorrect DMA reading of some flashes.\n");
|
||||
dev_warn(dev, "Much slower PIO mode will be used to prevent flash data damage.\n");
|
||||
dev_warn(dev, "Unplug UART cable and power cycle board to get full performance.\n");
|
||||
}
|
||||
}
|
||||
|
||||
err = dma_set_mask(as_ctrl->dev, DMA_BIT_MASK(32));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ctrl->num_chipselect = 2;
|
||||
ctrl->mem_ops = &airoha_snand_mem_ops;
|
||||
ctrl->mem_ops = dma_enable ? &airoha_snand_mem_ops
|
||||
: &airoha_snand_nodma_mem_ops;
|
||||
ctrl->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
ctrl->mode_bits = SPI_RX_DUAL;
|
||||
ctrl->setup = airoha_snand_setup;
|
||||
|
|
|
|||
|
|
@ -138,30 +138,24 @@ static int stm32_sai_set_sync(struct stm32_sai_data *sai_client,
|
|||
if (!pdev) {
|
||||
dev_err(&sai_client->pdev->dev,
|
||||
"Device not found for node %pOFn\n", np_provider);
|
||||
of_node_put(np_provider);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
sai_provider = platform_get_drvdata(pdev);
|
||||
put_device(&pdev->dev);
|
||||
if (!sai_provider) {
|
||||
dev_err(&sai_client->pdev->dev,
|
||||
"SAI sync provider data not found\n");
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Configure sync client */
|
||||
ret = stm32_sai_sync_conf_client(sai_client, synci);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
return ret;
|
||||
|
||||
/* Configure sync provider */
|
||||
ret = stm32_sai_sync_conf_provider(sai_provider, synco);
|
||||
|
||||
error:
|
||||
put_device(&pdev->dev);
|
||||
of_node_put(np_provider);
|
||||
return ret;
|
||||
return stm32_sai_sync_conf_provider(sai_provider, synco);
|
||||
}
|
||||
|
||||
static int stm32_sai_get_parent_clk(struct stm32_sai_data *sai)
|
||||
|
|
|
|||
|
|
@ -1586,7 +1586,8 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,
|
|||
dev_err(&pdev->dev,
|
||||
"External synchro not supported\n");
|
||||
of_node_put(args.np);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto err_put_sync_provider;
|
||||
}
|
||||
sai->sync = SAI_SYNC_EXTERNAL;
|
||||
|
||||
|
|
@ -1595,7 +1596,8 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,
|
|||
(sai->synci > (SAI_GCR_SYNCIN_MAX + 1))) {
|
||||
dev_err(&pdev->dev, "Wrong SAI index\n");
|
||||
of_node_put(args.np);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto err_put_sync_provider;
|
||||
}
|
||||
|
||||
if (of_property_match_string(args.np, "compatible",
|
||||
|
|
@ -1609,7 +1611,8 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,
|
|||
if (!sai->synco) {
|
||||
dev_err(&pdev->dev, "Unknown SAI sub-block\n");
|
||||
of_node_put(args.np);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto err_put_sync_provider;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1619,13 +1622,15 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,
|
|||
|
||||
of_node_put(args.np);
|
||||
sai->sai_ck = devm_clk_get(&pdev->dev, "sai_ck");
|
||||
if (IS_ERR(sai->sai_ck))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(sai->sai_ck),
|
||||
if (IS_ERR(sai->sai_ck)) {
|
||||
ret = dev_err_probe(&pdev->dev, PTR_ERR(sai->sai_ck),
|
||||
"Missing kernel clock sai_ck\n");
|
||||
goto err_put_sync_provider;
|
||||
}
|
||||
|
||||
ret = clk_prepare(sai->pdata->pclk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto err_put_sync_provider;
|
||||
|
||||
if (STM_SAI_IS_F4(sai->pdata))
|
||||
return 0;
|
||||
|
|
@ -1634,14 +1639,23 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,
|
|||
if (of_property_present(np, "#clock-cells")) {
|
||||
ret = stm32_sai_add_mclk_provider(sai);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto err_unprepare_pclk;
|
||||
} else {
|
||||
sai->sai_mclk = devm_clk_get_optional(&pdev->dev, "MCLK");
|
||||
if (IS_ERR(sai->sai_mclk))
|
||||
return PTR_ERR(sai->sai_mclk);
|
||||
if (IS_ERR(sai->sai_mclk)) {
|
||||
ret = PTR_ERR(sai->sai_mclk);
|
||||
goto err_unprepare_pclk;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_unprepare_pclk:
|
||||
clk_unprepare(sai->pdata->pclk);
|
||||
err_put_sync_provider:
|
||||
of_node_put(sai->np_sync_provider);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stm32_sai_sub_probe(struct platform_device *pdev)
|
||||
|
|
@ -1688,26 +1702,34 @@ static int stm32_sai_sub_probe(struct platform_device *pdev)
|
|||
IRQF_SHARED, dev_name(&pdev->dev), sai);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "IRQ request returned %d\n", ret);
|
||||
return ret;
|
||||
goto err_unprepare_pclk;
|
||||
}
|
||||
|
||||
if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
|
||||
conf = &stm32_sai_pcm_config_spdif;
|
||||
|
||||
ret = snd_dmaengine_pcm_register(&pdev->dev, conf, 0);
|
||||
if (ret)
|
||||
return dev_err_probe(&pdev->dev, ret, "Could not register pcm dma\n");
|
||||
if (ret) {
|
||||
ret = dev_err_probe(&pdev->dev, ret, "Could not register pcm dma\n");
|
||||
goto err_unprepare_pclk;
|
||||
}
|
||||
|
||||
ret = snd_soc_register_component(&pdev->dev, &stm32_component,
|
||||
&sai->cpu_dai_drv, 1);
|
||||
if (ret) {
|
||||
snd_dmaengine_pcm_unregister(&pdev->dev);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
goto err_deregister_pcm_dma;
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_deregister_pcm_dma:
|
||||
snd_dmaengine_pcm_unregister(&pdev->dev);
|
||||
err_unprepare_pclk:
|
||||
clk_unprepare(sai->pdata->pclk);
|
||||
of_node_put(sai->np_sync_provider);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void stm32_sai_sub_remove(struct platform_device *pdev)
|
||||
|
|
@ -1718,6 +1740,7 @@ static void stm32_sai_sub_remove(struct platform_device *pdev)
|
|||
snd_dmaengine_pcm_unregister(&pdev->dev);
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
of_node_put(sai->np_sync_provider);
|
||||
}
|
||||
|
||||
static int stm32_sai_sub_suspend(struct device *dev)
|
||||
|
|
|
|||
Loading…
Reference in New Issue