Commit 3c708a0c authored by Mark Brown's avatar Mark Brown

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.
parents 50a6620d 351c02cb
...@@ -18,14 +18,12 @@ description: | ...@@ -18,14 +18,12 @@ description: |
using the accompanying ECC engine. There should be only one spi using the accompanying ECC engine. There should be only one spi
slave device following generic spi bindings. slave device following generic spi bindings.
allOf:
- $ref: /schemas/spi/spi-controller.yaml#
properties: properties:
compatible: compatible:
enum: enum:
- mediatek,mt7622-snand - mediatek,mt7622-snand
- mediatek,mt7629-snand - mediatek,mt7629-snand
- mediatek,mt7986-snand
reg: reg:
items: items:
...@@ -36,19 +34,20 @@ properties: ...@@ -36,19 +34,20 @@ properties:
- description: NFI interrupt - description: NFI interrupt
clocks: clocks:
items: minItems: 2
- description: clock used for the controller maxItems: 3
- description: clock used for the SPI bus
clock-names: clock-names:
items: minItems: 2
- const: nfi_clk maxItems: 3
- const: pad_clk
nand-ecc-engine: nand-ecc-engine:
description: device-tree node of the accompanying ECC engine. description: device-tree node of the accompanying ECC engine.
$ref: /schemas/types.yaml#/definitions/phandle $ref: /schemas/types.yaml#/definitions/phandle
mediatek,rx-latch-latency-ns:
description: Data read latch latency, unit is nanoseconds.
required: required:
- compatible - compatible
- reg - reg
...@@ -57,6 +56,43 @@ required: ...@@ -57,6 +56,43 @@ required:
- clock-names - clock-names
- nand-ecc-engine - 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 unevaluatedProperties: false
examples: examples:
......
...@@ -195,6 +195,8 @@ ...@@ -195,6 +195,8 @@
#define DATA_READ_MODE_X4 2 #define DATA_READ_MODE_X4 2
#define DATA_READ_MODE_DUAL 5 #define DATA_READ_MODE_DUAL 5
#define DATA_READ_MODE_QUAD 6 #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 PG_LOAD_CUSTOM_EN BIT(7)
#define DATARD_CUSTOM_EN BIT(6) #define DATARD_CUSTOM_EN BIT(6)
#define CS_DESELECT_CYC_S 0 #define CS_DESELECT_CYC_S 0
...@@ -205,6 +207,9 @@ ...@@ -205,6 +207,9 @@
#define SNF_DLY_CTL3 0x548 #define SNF_DLY_CTL3 0x548
#define SFCK_SAM_DLY_S 0 #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 SNF_STA_CTL1 0x550
#define CUS_PG_DONE BIT(28) #define CUS_PG_DONE BIT(28)
...@@ -297,6 +302,7 @@ struct mtk_snand { ...@@ -297,6 +302,7 @@ struct mtk_snand {
struct device *dev; struct device *dev;
struct clk *nfi_clk; struct clk *nfi_clk;
struct clk *pad_clk; struct clk *pad_clk;
struct clk *nfi_hclk;
void __iomem *nfi_base; void __iomem *nfi_base;
int irq; int irq;
struct completion op_done; struct completion op_done;
...@@ -1339,7 +1345,16 @@ static int mtk_snand_enable_clk(struct mtk_snand *ms) ...@@ -1339,7 +1345,16 @@ static int mtk_snand_enable_clk(struct mtk_snand *ms)
dev_err(ms->dev, "unable to enable pad clk\n"); dev_err(ms->dev, "unable to enable pad clk\n");
goto err1; 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; return 0;
err2:
clk_disable_unprepare(ms->pad_clk);
err1: err1:
clk_disable_unprepare(ms->nfi_clk); clk_disable_unprepare(ms->nfi_clk);
return ret; return ret;
...@@ -1347,6 +1362,7 @@ static int mtk_snand_enable_clk(struct mtk_snand *ms) ...@@ -1347,6 +1362,7 @@ static int mtk_snand_enable_clk(struct mtk_snand *ms)
static void mtk_snand_disable_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->pad_clk);
clk_disable_unprepare(ms->nfi_clk); clk_disable_unprepare(ms->nfi_clk);
} }
...@@ -1357,6 +1373,8 @@ static int mtk_snand_probe(struct platform_device *pdev) ...@@ -1357,6 +1373,8 @@ static int mtk_snand_probe(struct platform_device *pdev)
const struct of_device_id *dev_id; const struct of_device_id *dev_id;
struct spi_controller *ctlr; struct spi_controller *ctlr;
struct mtk_snand *ms; struct mtk_snand *ms;
unsigned long spi_freq;
u32 val = 0;
int ret; int ret;
dev_id = of_match_node(mtk_snand_ids, np); dev_id = of_match_node(mtk_snand_ids, np);
...@@ -1401,6 +1419,13 @@ static int mtk_snand_probe(struct platform_device *pdev) ...@@ -1401,6 +1419,13 @@ static int mtk_snand_probe(struct platform_device *pdev)
goto release_ecc; 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); ret = mtk_snand_enable_clk(ms);
if (ret) if (ret)
goto release_ecc; goto release_ecc;
...@@ -1428,10 +1453,22 @@ static int mtk_snand_probe(struct platform_device *pdev) ...@@ -1428,10 +1453,22 @@ static int mtk_snand_probe(struct platform_device *pdev)
// switch to SNFI mode // switch to SNFI mode
nfi_write32(ms, SNF_CFG, SPI_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 // setup an initial page format for ops matching page_cache_op template
// before ECC is called. // before ECC is called.
ret = mtk_snand_setup_pagefmt(ms, ms->caps->sector_size, ret = mtk_snand_setup_pagefmt(ms, SZ_2K, SZ_64);
ms->caps->spare_sizes[0]);
if (ret) { if (ret) {
dev_err(ms->dev, "failed to set initial page format\n"); dev_err(ms->dev, "failed to set initial page format\n");
goto disable_clk; goto disable_clk;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment