Add MediaTek MT7986 SPI NAND support

Merge series from Xiangsheng Hou <xiangsheng.hou@mediatek.com>:

This patch series split from bellow series which pick-up spi relevant patches
https://lore.kernel.org/all/20230130030656.12127-1-xiangsheng.hou@mediatek.com.
This series add MediaTek MT7986 SPI NAND controller support, add read latch
latency, smaple delay adjust and add optional nfi_hclk.
This commit is contained in:
Mark Brown 2023-02-09 19:17:56 +00:00
commit 3c708a0c4c
No known key found for this signature in database
GPG key ID: 24D68B725D5487D0
2 changed files with 84 additions and 11 deletions

View file

@ -18,14 +18,12 @@ description: |
using the accompanying ECC engine. There should be only one spi
slave device following generic spi bindings.
allOf:
- $ref: /schemas/spi/spi-controller.yaml#
properties:
compatible:
enum:
- mediatek,mt7622-snand
- mediatek,mt7629-snand
- mediatek,mt7986-snand
reg:
items:
@ -36,19 +34,20 @@ properties:
- description: NFI interrupt
clocks:
items:
- description: clock used for the controller
- description: clock used for the SPI bus
minItems: 2
maxItems: 3
clock-names:
items:
- const: nfi_clk
- const: pad_clk
minItems: 2
maxItems: 3
nand-ecc-engine:
description: device-tree node of the accompanying ECC engine.
$ref: /schemas/types.yaml#/definitions/phandle
mediatek,rx-latch-latency-ns:
description: Data read latch latency, unit is nanoseconds.
required:
- compatible
- reg
@ -57,6 +56,43 @@ required:
- clock-names
- nand-ecc-engine
allOf:
- $ref: /schemas/spi/spi-controller.yaml#
- if:
properties:
compatible:
enum:
- mediatek,mt7622-snand
- mediatek,mt7629-snand
then:
properties:
clocks:
items:
- description: clock used for the controller
- description: clock used for the SPI bus
clock-names:
items:
- const: nfi_clk
- const: pad_clk
- if:
properties:
compatible:
enum:
- mediatek,mt7986-snand
then:
properties:
clocks:
items:
- description: clock used for the controller
- description: clock used for the SPI bus
- description: clock used for the AHB bus
clock-names:
items:
- const: nfi_clk
- const: pad_clk
- const: nfi_hclk
unevaluatedProperties: false
examples:

View file

@ -195,6 +195,8 @@
#define DATA_READ_MODE_X4 2
#define DATA_READ_MODE_DUAL 5
#define DATA_READ_MODE_QUAD 6
#define DATA_READ_LATCH_LAT GENMASK(9, 8)
#define DATA_READ_LATCH_LAT_S 8
#define PG_LOAD_CUSTOM_EN BIT(7)
#define DATARD_CUSTOM_EN BIT(6)
#define CS_DESELECT_CYC_S 0
@ -205,6 +207,9 @@
#define SNF_DLY_CTL3 0x548
#define SFCK_SAM_DLY_S 0
#define SFCK_SAM_DLY GENMASK(5, 0)
#define SFCK_SAM_DLY_TOTAL 9
#define SFCK_SAM_DLY_RANGE 47
#define SNF_STA_CTL1 0x550
#define CUS_PG_DONE BIT(28)
@ -297,6 +302,7 @@ struct mtk_snand {
struct device *dev;
struct clk *nfi_clk;
struct clk *pad_clk;
struct clk *nfi_hclk;
void __iomem *nfi_base;
int irq;
struct completion op_done;
@ -1339,7 +1345,16 @@ static int mtk_snand_enable_clk(struct mtk_snand *ms)
dev_err(ms->dev, "unable to enable pad clk\n");
goto err1;
}
ret = clk_prepare_enable(ms->nfi_hclk);
if (ret) {
dev_err(ms->dev, "unable to enable nfi hclk\n");
goto err2;
}
return 0;
err2:
clk_disable_unprepare(ms->pad_clk);
err1:
clk_disable_unprepare(ms->nfi_clk);
return ret;
@ -1347,6 +1362,7 @@ static int mtk_snand_enable_clk(struct mtk_snand *ms)
static void mtk_snand_disable_clk(struct mtk_snand *ms)
{
clk_disable_unprepare(ms->nfi_hclk);
clk_disable_unprepare(ms->pad_clk);
clk_disable_unprepare(ms->nfi_clk);
}
@ -1357,6 +1373,8 @@ static int mtk_snand_probe(struct platform_device *pdev)
const struct of_device_id *dev_id;
struct spi_controller *ctlr;
struct mtk_snand *ms;
unsigned long spi_freq;
u32 val = 0;
int ret;
dev_id = of_match_node(mtk_snand_ids, np);
@ -1401,6 +1419,13 @@ static int mtk_snand_probe(struct platform_device *pdev)
goto release_ecc;
}
ms->nfi_hclk = devm_clk_get_optional(&pdev->dev, "nfi_hclk");
if (IS_ERR(ms->nfi_hclk)) {
ret = PTR_ERR(ms->nfi_hclk);
dev_err(&pdev->dev, "unable to get nfi_hclk, err = %d\n", ret);
goto release_ecc;
}
ret = mtk_snand_enable_clk(ms);
if (ret)
goto release_ecc;
@ -1428,10 +1453,22 @@ static int mtk_snand_probe(struct platform_device *pdev)
// switch to SNFI mode
nfi_write32(ms, SNF_CFG, SPI_MODE);
ret = of_property_read_u32(np, "rx-sample-delay-ns", &val);
if (!ret)
nfi_rmw32(ms, SNF_DLY_CTL3, SFCK_SAM_DLY,
val * SFCK_SAM_DLY_RANGE / SFCK_SAM_DLY_TOTAL);
ret = of_property_read_u32(np, "mediatek,rx-latch-latency-ns", &val);
if (!ret) {
spi_freq = clk_get_rate(ms->pad_clk);
val = DIV_ROUND_CLOSEST(val, NSEC_PER_SEC / spi_freq);
nfi_rmw32(ms, SNF_MISC_CTL, DATA_READ_LATCH_LAT,
val << DATA_READ_LATCH_LAT_S);
}
// setup an initial page format for ops matching page_cache_op template
// before ECC is called.
ret = mtk_snand_setup_pagefmt(ms, ms->caps->sector_size,
ms->caps->spare_sizes[0]);
ret = mtk_snand_setup_pagefmt(ms, SZ_2K, SZ_64);
if (ret) {
dev_err(ms->dev, "failed to set initial page format\n");
goto disable_clk;