Unverified Commit 3c708a0c authored by Mark Brown's avatar Mark Brown
Browse files

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
Loading
Loading
Loading
Loading
+45 −9
Original line number Diff line number Diff line
@@ -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:
+39 −2
Original line number Diff line number Diff line
@@ -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;