1738b0ca5SMason Yang // SPDX-License-Identifier: GPL-2.0 2738b0ca5SMason Yang /* 3738b0ca5SMason Yang * Copyright (C) 2019 Macronix International Co., Ltd. 4738b0ca5SMason Yang * 5738b0ca5SMason Yang * Author: 6738b0ca5SMason Yang * Mason Yang <masonccyang@mxic.com.tw> 7738b0ca5SMason Yang */ 8738b0ca5SMason Yang 9738b0ca5SMason Yang #include <linux/clk.h> 10738b0ca5SMason Yang #include <linux/io.h> 11738b0ca5SMason Yang #include <linux/iopoll.h> 12738b0ca5SMason Yang #include <linux/interrupt.h> 13738b0ca5SMason Yang #include <linux/module.h> 14738b0ca5SMason Yang #include <linux/mtd/mtd.h> 15*e5acf9c8SMiquel Raynal #include <linux/mtd/nand-ecc-sw-hamming.h> 16738b0ca5SMason Yang #include <linux/mtd/rawnand.h> 17738b0ca5SMason Yang #include <linux/platform_device.h> 18738b0ca5SMason Yang 19738b0ca5SMason Yang #include "internals.h" 20738b0ca5SMason Yang 21738b0ca5SMason Yang #define HC_CFG 0x0 22738b0ca5SMason Yang #define HC_CFG_IF_CFG(x) ((x) << 27) 23738b0ca5SMason Yang #define HC_CFG_DUAL_SLAVE BIT(31) 24738b0ca5SMason Yang #define HC_CFG_INDIVIDUAL BIT(30) 25738b0ca5SMason Yang #define HC_CFG_NIO(x) (((x) / 4) << 27) 26738b0ca5SMason Yang #define HC_CFG_TYPE(s, t) ((t) << (23 + ((s) * 2))) 27738b0ca5SMason Yang #define HC_CFG_TYPE_SPI_NOR 0 28738b0ca5SMason Yang #define HC_CFG_TYPE_SPI_NAND 1 29738b0ca5SMason Yang #define HC_CFG_TYPE_SPI_RAM 2 30738b0ca5SMason Yang #define HC_CFG_TYPE_RAW_NAND 3 31738b0ca5SMason Yang #define HC_CFG_SLV_ACT(x) ((x) << 21) 32738b0ca5SMason Yang #define HC_CFG_CLK_PH_EN BIT(20) 33738b0ca5SMason Yang #define HC_CFG_CLK_POL_INV BIT(19) 34738b0ca5SMason Yang #define HC_CFG_BIG_ENDIAN BIT(18) 35738b0ca5SMason Yang #define HC_CFG_DATA_PASS BIT(17) 36738b0ca5SMason Yang #define HC_CFG_IDLE_SIO_LVL(x) ((x) << 16) 37738b0ca5SMason Yang #define HC_CFG_MAN_START_EN BIT(3) 38738b0ca5SMason Yang #define HC_CFG_MAN_START BIT(2) 39738b0ca5SMason Yang #define HC_CFG_MAN_CS_EN BIT(1) 40738b0ca5SMason Yang #define HC_CFG_MAN_CS_ASSERT BIT(0) 41738b0ca5SMason Yang 42738b0ca5SMason Yang #define INT_STS 0x4 43738b0ca5SMason Yang #define INT_STS_EN 0x8 44738b0ca5SMason Yang #define INT_SIG_EN 0xc 45738b0ca5SMason Yang #define INT_STS_ALL GENMASK(31, 0) 46738b0ca5SMason Yang #define INT_RDY_PIN BIT(26) 47738b0ca5SMason Yang #define INT_RDY_SR BIT(25) 48738b0ca5SMason Yang #define INT_LNR_SUSP BIT(24) 49738b0ca5SMason Yang #define INT_ECC_ERR BIT(17) 50738b0ca5SMason Yang #define INT_CRC_ERR BIT(16) 51738b0ca5SMason Yang #define INT_LWR_DIS BIT(12) 52738b0ca5SMason Yang #define INT_LRD_DIS BIT(11) 53738b0ca5SMason Yang #define INT_SDMA_INT BIT(10) 54738b0ca5SMason Yang #define INT_DMA_FINISH BIT(9) 55738b0ca5SMason Yang #define INT_RX_NOT_FULL BIT(3) 56738b0ca5SMason Yang #define INT_RX_NOT_EMPTY BIT(2) 57738b0ca5SMason Yang #define INT_TX_NOT_FULL BIT(1) 58738b0ca5SMason Yang #define INT_TX_EMPTY BIT(0) 59738b0ca5SMason Yang 60738b0ca5SMason Yang #define HC_EN 0x10 61738b0ca5SMason Yang #define HC_EN_BIT BIT(0) 62738b0ca5SMason Yang 63738b0ca5SMason Yang #define TXD(x) (0x14 + ((x) * 4)) 64738b0ca5SMason Yang #define RXD 0x24 65738b0ca5SMason Yang 66738b0ca5SMason Yang #define SS_CTRL(s) (0x30 + ((s) * 4)) 67738b0ca5SMason Yang #define LRD_CFG 0x44 68738b0ca5SMason Yang #define LWR_CFG 0x80 69738b0ca5SMason Yang #define RWW_CFG 0x70 70738b0ca5SMason Yang #define OP_READ BIT(23) 71738b0ca5SMason Yang #define OP_DUMMY_CYC(x) ((x) << 17) 72738b0ca5SMason Yang #define OP_ADDR_BYTES(x) ((x) << 14) 73738b0ca5SMason Yang #define OP_CMD_BYTES(x) (((x) - 1) << 13) 74738b0ca5SMason Yang #define OP_OCTA_CRC_EN BIT(12) 75738b0ca5SMason Yang #define OP_DQS_EN BIT(11) 76738b0ca5SMason Yang #define OP_ENHC_EN BIT(10) 77738b0ca5SMason Yang #define OP_PREAMBLE_EN BIT(9) 78738b0ca5SMason Yang #define OP_DATA_DDR BIT(8) 79738b0ca5SMason Yang #define OP_DATA_BUSW(x) ((x) << 6) 80738b0ca5SMason Yang #define OP_ADDR_DDR BIT(5) 81738b0ca5SMason Yang #define OP_ADDR_BUSW(x) ((x) << 3) 82738b0ca5SMason Yang #define OP_CMD_DDR BIT(2) 83738b0ca5SMason Yang #define OP_CMD_BUSW(x) (x) 84738b0ca5SMason Yang #define OP_BUSW_1 0 85738b0ca5SMason Yang #define OP_BUSW_2 1 86738b0ca5SMason Yang #define OP_BUSW_4 2 87738b0ca5SMason Yang #define OP_BUSW_8 3 88738b0ca5SMason Yang 89738b0ca5SMason Yang #define OCTA_CRC 0x38 90738b0ca5SMason Yang #define OCTA_CRC_IN_EN(s) BIT(3 + ((s) * 16)) 91738b0ca5SMason Yang #define OCTA_CRC_CHUNK(s, x) ((fls((x) / 32)) << (1 + ((s) * 16))) 92738b0ca5SMason Yang #define OCTA_CRC_OUT_EN(s) BIT(0 + ((s) * 16)) 93738b0ca5SMason Yang 94738b0ca5SMason Yang #define ONFI_DIN_CNT(s) (0x3c + (s)) 95738b0ca5SMason Yang 96738b0ca5SMason Yang #define LRD_CTRL 0x48 97738b0ca5SMason Yang #define RWW_CTRL 0x74 98738b0ca5SMason Yang #define LWR_CTRL 0x84 99738b0ca5SMason Yang #define LMODE_EN BIT(31) 100738b0ca5SMason Yang #define LMODE_SLV_ACT(x) ((x) << 21) 101738b0ca5SMason Yang #define LMODE_CMD1(x) ((x) << 8) 102738b0ca5SMason Yang #define LMODE_CMD0(x) (x) 103738b0ca5SMason Yang 104738b0ca5SMason Yang #define LRD_ADDR 0x4c 105738b0ca5SMason Yang #define LWR_ADDR 0x88 106738b0ca5SMason Yang #define LRD_RANGE 0x50 107738b0ca5SMason Yang #define LWR_RANGE 0x8c 108738b0ca5SMason Yang 109738b0ca5SMason Yang #define AXI_SLV_ADDR 0x54 110738b0ca5SMason Yang 111738b0ca5SMason Yang #define DMAC_RD_CFG 0x58 112738b0ca5SMason Yang #define DMAC_WR_CFG 0x94 113738b0ca5SMason Yang #define DMAC_CFG_PERIPH_EN BIT(31) 114738b0ca5SMason Yang #define DMAC_CFG_ALLFLUSH_EN BIT(30) 115738b0ca5SMason Yang #define DMAC_CFG_LASTFLUSH_EN BIT(29) 116738b0ca5SMason Yang #define DMAC_CFG_QE(x) (((x) + 1) << 16) 117738b0ca5SMason Yang #define DMAC_CFG_BURST_LEN(x) (((x) + 1) << 12) 118738b0ca5SMason Yang #define DMAC_CFG_BURST_SZ(x) ((x) << 8) 119738b0ca5SMason Yang #define DMAC_CFG_DIR_READ BIT(1) 120738b0ca5SMason Yang #define DMAC_CFG_START BIT(0) 121738b0ca5SMason Yang 122738b0ca5SMason Yang #define DMAC_RD_CNT 0x5c 123738b0ca5SMason Yang #define DMAC_WR_CNT 0x98 124738b0ca5SMason Yang 125738b0ca5SMason Yang #define SDMA_ADDR 0x60 126738b0ca5SMason Yang 127738b0ca5SMason Yang #define DMAM_CFG 0x64 128738b0ca5SMason Yang #define DMAM_CFG_START BIT(31) 129738b0ca5SMason Yang #define DMAM_CFG_CONT BIT(30) 130738b0ca5SMason Yang #define DMAM_CFG_SDMA_GAP(x) (fls((x) / 8192) << 2) 131738b0ca5SMason Yang #define DMAM_CFG_DIR_READ BIT(1) 132738b0ca5SMason Yang #define DMAM_CFG_EN BIT(0) 133738b0ca5SMason Yang 134738b0ca5SMason Yang #define DMAM_CNT 0x68 135738b0ca5SMason Yang 136738b0ca5SMason Yang #define LNR_TIMER_TH 0x6c 137738b0ca5SMason Yang 138738b0ca5SMason Yang #define RDM_CFG0 0x78 139738b0ca5SMason Yang #define RDM_CFG0_POLY(x) (x) 140738b0ca5SMason Yang 141738b0ca5SMason Yang #define RDM_CFG1 0x7c 142738b0ca5SMason Yang #define RDM_CFG1_RDM_EN BIT(31) 143738b0ca5SMason Yang #define RDM_CFG1_SEED(x) (x) 144738b0ca5SMason Yang 145738b0ca5SMason Yang #define LWR_SUSP_CTRL 0x90 146738b0ca5SMason Yang #define LWR_SUSP_CTRL_EN BIT(31) 147738b0ca5SMason Yang 148738b0ca5SMason Yang #define DMAS_CTRL 0x9c 149738b0ca5SMason Yang #define DMAS_CTRL_EN BIT(31) 150738b0ca5SMason Yang #define DMAS_CTRL_DIR_READ BIT(30) 151738b0ca5SMason Yang 152738b0ca5SMason Yang #define DATA_STROB 0xa0 153738b0ca5SMason Yang #define DATA_STROB_EDO_EN BIT(2) 154738b0ca5SMason Yang #define DATA_STROB_INV_POL BIT(1) 155738b0ca5SMason Yang #define DATA_STROB_DELAY_2CYC BIT(0) 156738b0ca5SMason Yang 157738b0ca5SMason Yang #define IDLY_CODE(x) (0xa4 + ((x) * 4)) 158738b0ca5SMason Yang #define IDLY_CODE_VAL(x, v) ((v) << (((x) % 4) * 8)) 159738b0ca5SMason Yang 160738b0ca5SMason Yang #define GPIO 0xc4 161738b0ca5SMason Yang #define GPIO_PT(x) BIT(3 + ((x) * 16)) 162738b0ca5SMason Yang #define GPIO_RESET(x) BIT(2 + ((x) * 16)) 163738b0ca5SMason Yang #define GPIO_HOLDB(x) BIT(1 + ((x) * 16)) 164738b0ca5SMason Yang #define GPIO_WPB(x) BIT((x) * 16) 165738b0ca5SMason Yang 166738b0ca5SMason Yang #define HC_VER 0xd0 167738b0ca5SMason Yang 168738b0ca5SMason Yang #define HW_TEST(x) (0xe0 + ((x) * 4)) 169738b0ca5SMason Yang 170738b0ca5SMason Yang #define MXIC_NFC_MAX_CLK_HZ 50000000 171738b0ca5SMason Yang #define IRQ_TIMEOUT 1000 172738b0ca5SMason Yang 173738b0ca5SMason Yang struct mxic_nand_ctlr { 174738b0ca5SMason Yang struct clk *ps_clk; 175738b0ca5SMason Yang struct clk *send_clk; 176738b0ca5SMason Yang struct clk *send_dly_clk; 177738b0ca5SMason Yang struct completion complete; 178738b0ca5SMason Yang void __iomem *regs; 179738b0ca5SMason Yang struct nand_controller controller; 180738b0ca5SMason Yang struct device *dev; 181738b0ca5SMason Yang struct nand_chip chip; 182738b0ca5SMason Yang }; 183738b0ca5SMason Yang 184738b0ca5SMason Yang static int mxic_nfc_clk_enable(struct mxic_nand_ctlr *nfc) 185738b0ca5SMason Yang { 186738b0ca5SMason Yang int ret; 187738b0ca5SMason Yang 188738b0ca5SMason Yang ret = clk_prepare_enable(nfc->ps_clk); 189738b0ca5SMason Yang if (ret) 190738b0ca5SMason Yang return ret; 191738b0ca5SMason Yang 192738b0ca5SMason Yang ret = clk_prepare_enable(nfc->send_clk); 193738b0ca5SMason Yang if (ret) 194738b0ca5SMason Yang goto err_ps_clk; 195738b0ca5SMason Yang 196738b0ca5SMason Yang ret = clk_prepare_enable(nfc->send_dly_clk); 197738b0ca5SMason Yang if (ret) 198738b0ca5SMason Yang goto err_send_dly_clk; 199738b0ca5SMason Yang 200738b0ca5SMason Yang return ret; 201738b0ca5SMason Yang 202738b0ca5SMason Yang err_send_dly_clk: 203738b0ca5SMason Yang clk_disable_unprepare(nfc->send_clk); 204738b0ca5SMason Yang err_ps_clk: 205738b0ca5SMason Yang clk_disable_unprepare(nfc->ps_clk); 206738b0ca5SMason Yang 207738b0ca5SMason Yang return ret; 208738b0ca5SMason Yang } 209738b0ca5SMason Yang 210738b0ca5SMason Yang static void mxic_nfc_clk_disable(struct mxic_nand_ctlr *nfc) 211738b0ca5SMason Yang { 212738b0ca5SMason Yang clk_disable_unprepare(nfc->send_clk); 213738b0ca5SMason Yang clk_disable_unprepare(nfc->send_dly_clk); 214738b0ca5SMason Yang clk_disable_unprepare(nfc->ps_clk); 215738b0ca5SMason Yang } 216738b0ca5SMason Yang 217738b0ca5SMason Yang static void mxic_nfc_set_input_delay(struct mxic_nand_ctlr *nfc, u8 idly_code) 218738b0ca5SMason Yang { 219738b0ca5SMason Yang writel(IDLY_CODE_VAL(0, idly_code) | 220738b0ca5SMason Yang IDLY_CODE_VAL(1, idly_code) | 221738b0ca5SMason Yang IDLY_CODE_VAL(2, idly_code) | 222738b0ca5SMason Yang IDLY_CODE_VAL(3, idly_code), 223738b0ca5SMason Yang nfc->regs + IDLY_CODE(0)); 224738b0ca5SMason Yang writel(IDLY_CODE_VAL(4, idly_code) | 225738b0ca5SMason Yang IDLY_CODE_VAL(5, idly_code) | 226738b0ca5SMason Yang IDLY_CODE_VAL(6, idly_code) | 227738b0ca5SMason Yang IDLY_CODE_VAL(7, idly_code), 228738b0ca5SMason Yang nfc->regs + IDLY_CODE(1)); 229738b0ca5SMason Yang } 230738b0ca5SMason Yang 231738b0ca5SMason Yang static int mxic_nfc_clk_setup(struct mxic_nand_ctlr *nfc, unsigned long freq) 232738b0ca5SMason Yang { 233738b0ca5SMason Yang int ret; 234738b0ca5SMason Yang 235738b0ca5SMason Yang ret = clk_set_rate(nfc->send_clk, freq); 236738b0ca5SMason Yang if (ret) 237738b0ca5SMason Yang return ret; 238738b0ca5SMason Yang 239738b0ca5SMason Yang ret = clk_set_rate(nfc->send_dly_clk, freq); 240738b0ca5SMason Yang if (ret) 241738b0ca5SMason Yang return ret; 242738b0ca5SMason Yang 243738b0ca5SMason Yang /* 244738b0ca5SMason Yang * A constant delay range from 0x0 ~ 0x1F for input delay, 245738b0ca5SMason Yang * the unit is 78 ps, the max input delay is 2.418 ns. 246738b0ca5SMason Yang */ 247738b0ca5SMason Yang mxic_nfc_set_input_delay(nfc, 0xf); 248738b0ca5SMason Yang 249738b0ca5SMason Yang /* 250738b0ca5SMason Yang * Phase degree = 360 * freq * output-delay 251738b0ca5SMason Yang * where output-delay is a constant value 1 ns in FPGA. 252738b0ca5SMason Yang * 253738b0ca5SMason Yang * Get Phase degree = 360 * freq * 1 ns 254738b0ca5SMason Yang * = 360 * freq * 1 sec / 1000000000 255738b0ca5SMason Yang * = 9 * freq / 25000000 256738b0ca5SMason Yang */ 257738b0ca5SMason Yang ret = clk_set_phase(nfc->send_dly_clk, 9 * freq / 25000000); 258738b0ca5SMason Yang if (ret) 259738b0ca5SMason Yang return ret; 260738b0ca5SMason Yang 261738b0ca5SMason Yang return 0; 262738b0ca5SMason Yang } 263738b0ca5SMason Yang 264738b0ca5SMason Yang static int mxic_nfc_set_freq(struct mxic_nand_ctlr *nfc, unsigned long freq) 265738b0ca5SMason Yang { 266738b0ca5SMason Yang int ret; 267738b0ca5SMason Yang 268738b0ca5SMason Yang if (freq > MXIC_NFC_MAX_CLK_HZ) 269738b0ca5SMason Yang freq = MXIC_NFC_MAX_CLK_HZ; 270738b0ca5SMason Yang 271738b0ca5SMason Yang mxic_nfc_clk_disable(nfc); 272738b0ca5SMason Yang ret = mxic_nfc_clk_setup(nfc, freq); 273738b0ca5SMason Yang if (ret) 274738b0ca5SMason Yang return ret; 275738b0ca5SMason Yang 276738b0ca5SMason Yang ret = mxic_nfc_clk_enable(nfc); 277738b0ca5SMason Yang if (ret) 278738b0ca5SMason Yang return ret; 279738b0ca5SMason Yang 280738b0ca5SMason Yang return 0; 281738b0ca5SMason Yang } 282738b0ca5SMason Yang 283738b0ca5SMason Yang static irqreturn_t mxic_nfc_isr(int irq, void *dev_id) 284738b0ca5SMason Yang { 285738b0ca5SMason Yang struct mxic_nand_ctlr *nfc = dev_id; 286738b0ca5SMason Yang u32 sts; 287738b0ca5SMason Yang 288738b0ca5SMason Yang sts = readl(nfc->regs + INT_STS); 289738b0ca5SMason Yang if (sts & INT_RDY_PIN) 290738b0ca5SMason Yang complete(&nfc->complete); 291738b0ca5SMason Yang else 292738b0ca5SMason Yang return IRQ_NONE; 293738b0ca5SMason Yang 294738b0ca5SMason Yang return IRQ_HANDLED; 295738b0ca5SMason Yang } 296738b0ca5SMason Yang 297738b0ca5SMason Yang static void mxic_nfc_hw_init(struct mxic_nand_ctlr *nfc) 298738b0ca5SMason Yang { 299738b0ca5SMason Yang writel(HC_CFG_NIO(8) | HC_CFG_TYPE(1, HC_CFG_TYPE_RAW_NAND) | 300738b0ca5SMason Yang HC_CFG_SLV_ACT(0) | HC_CFG_MAN_CS_EN | 301738b0ca5SMason Yang HC_CFG_IDLE_SIO_LVL(1), nfc->regs + HC_CFG); 302738b0ca5SMason Yang writel(INT_STS_ALL, nfc->regs + INT_STS_EN); 303738b0ca5SMason Yang writel(INT_RDY_PIN, nfc->regs + INT_SIG_EN); 304738b0ca5SMason Yang writel(0x0, nfc->regs + ONFI_DIN_CNT(0)); 305738b0ca5SMason Yang writel(0, nfc->regs + LRD_CFG); 306738b0ca5SMason Yang writel(0, nfc->regs + LRD_CTRL); 307738b0ca5SMason Yang writel(0x0, nfc->regs + HC_EN); 308738b0ca5SMason Yang } 309738b0ca5SMason Yang 310738b0ca5SMason Yang static void mxic_nfc_cs_enable(struct mxic_nand_ctlr *nfc) 311738b0ca5SMason Yang { 312738b0ca5SMason Yang writel(readl(nfc->regs + HC_CFG) | HC_CFG_MAN_CS_EN, 313738b0ca5SMason Yang nfc->regs + HC_CFG); 314738b0ca5SMason Yang writel(HC_CFG_MAN_CS_ASSERT | readl(nfc->regs + HC_CFG), 315738b0ca5SMason Yang nfc->regs + HC_CFG); 316738b0ca5SMason Yang } 317738b0ca5SMason Yang 318738b0ca5SMason Yang static void mxic_nfc_cs_disable(struct mxic_nand_ctlr *nfc) 319738b0ca5SMason Yang { 320738b0ca5SMason Yang writel(~HC_CFG_MAN_CS_ASSERT & readl(nfc->regs + HC_CFG), 321738b0ca5SMason Yang nfc->regs + HC_CFG); 322738b0ca5SMason Yang } 323738b0ca5SMason Yang 324738b0ca5SMason Yang static int mxic_nfc_wait_ready(struct nand_chip *chip) 325738b0ca5SMason Yang { 326738b0ca5SMason Yang struct mxic_nand_ctlr *nfc = nand_get_controller_data(chip); 327738b0ca5SMason Yang int ret; 328738b0ca5SMason Yang 329738b0ca5SMason Yang ret = wait_for_completion_timeout(&nfc->complete, 330738b0ca5SMason Yang msecs_to_jiffies(IRQ_TIMEOUT)); 331738b0ca5SMason Yang if (!ret) { 332738b0ca5SMason Yang dev_err(nfc->dev, "nand device timeout\n"); 333738b0ca5SMason Yang return -ETIMEDOUT; 334738b0ca5SMason Yang } 335738b0ca5SMason Yang 336738b0ca5SMason Yang return 0; 337738b0ca5SMason Yang } 338738b0ca5SMason Yang 339738b0ca5SMason Yang static int mxic_nfc_data_xfer(struct mxic_nand_ctlr *nfc, const void *txbuf, 340738b0ca5SMason Yang void *rxbuf, unsigned int len) 341738b0ca5SMason Yang { 342738b0ca5SMason Yang unsigned int pos = 0; 343738b0ca5SMason Yang 344738b0ca5SMason Yang while (pos < len) { 345738b0ca5SMason Yang unsigned int nbytes = len - pos; 346738b0ca5SMason Yang u32 data = 0xffffffff; 347738b0ca5SMason Yang u32 sts; 348738b0ca5SMason Yang int ret; 349738b0ca5SMason Yang 350738b0ca5SMason Yang if (nbytes > 4) 351738b0ca5SMason Yang nbytes = 4; 352738b0ca5SMason Yang 353738b0ca5SMason Yang if (txbuf) 354738b0ca5SMason Yang memcpy(&data, txbuf + pos, nbytes); 355738b0ca5SMason Yang 356738b0ca5SMason Yang ret = readl_poll_timeout(nfc->regs + INT_STS, sts, 357738b0ca5SMason Yang sts & INT_TX_EMPTY, 0, USEC_PER_SEC); 358738b0ca5SMason Yang if (ret) 359738b0ca5SMason Yang return ret; 360738b0ca5SMason Yang 361738b0ca5SMason Yang writel(data, nfc->regs + TXD(nbytes % 4)); 362738b0ca5SMason Yang 363738b0ca5SMason Yang ret = readl_poll_timeout(nfc->regs + INT_STS, sts, 364738b0ca5SMason Yang sts & INT_TX_EMPTY, 0, USEC_PER_SEC); 365738b0ca5SMason Yang if (ret) 366738b0ca5SMason Yang return ret; 367738b0ca5SMason Yang 368738b0ca5SMason Yang ret = readl_poll_timeout(nfc->regs + INT_STS, sts, 369738b0ca5SMason Yang sts & INT_RX_NOT_EMPTY, 0, 370738b0ca5SMason Yang USEC_PER_SEC); 371738b0ca5SMason Yang if (ret) 372738b0ca5SMason Yang return ret; 373738b0ca5SMason Yang 374738b0ca5SMason Yang data = readl(nfc->regs + RXD); 375738b0ca5SMason Yang if (rxbuf) { 376738b0ca5SMason Yang data >>= (8 * (4 - nbytes)); 377738b0ca5SMason Yang memcpy(rxbuf + pos, &data, nbytes); 378738b0ca5SMason Yang } 379738b0ca5SMason Yang if (readl(nfc->regs + INT_STS) & INT_RX_NOT_EMPTY) 380738b0ca5SMason Yang dev_warn(nfc->dev, "RX FIFO not empty\n"); 381738b0ca5SMason Yang 382738b0ca5SMason Yang pos += nbytes; 383738b0ca5SMason Yang } 384738b0ca5SMason Yang 385738b0ca5SMason Yang return 0; 386738b0ca5SMason Yang } 387738b0ca5SMason Yang 388738b0ca5SMason Yang static int mxic_nfc_exec_op(struct nand_chip *chip, 389738b0ca5SMason Yang const struct nand_operation *op, bool check_only) 390738b0ca5SMason Yang { 391738b0ca5SMason Yang struct mxic_nand_ctlr *nfc = nand_get_controller_data(chip); 392738b0ca5SMason Yang const struct nand_op_instr *instr = NULL; 393738b0ca5SMason Yang int ret = 0; 394738b0ca5SMason Yang unsigned int op_id; 395738b0ca5SMason Yang 396ce446b4bSBoris Brezillon if (check_only) 397ce446b4bSBoris Brezillon return 0; 398ce446b4bSBoris Brezillon 399738b0ca5SMason Yang mxic_nfc_cs_enable(nfc); 400738b0ca5SMason Yang init_completion(&nfc->complete); 401738b0ca5SMason Yang for (op_id = 0; op_id < op->ninstrs; op_id++) { 402738b0ca5SMason Yang instr = &op->instrs[op_id]; 403738b0ca5SMason Yang 404738b0ca5SMason Yang switch (instr->type) { 405738b0ca5SMason Yang case NAND_OP_CMD_INSTR: 406738b0ca5SMason Yang writel(0, nfc->regs + HC_EN); 407738b0ca5SMason Yang writel(HC_EN_BIT, nfc->regs + HC_EN); 408738b0ca5SMason Yang writel(OP_CMD_BUSW(OP_BUSW_8) | OP_DUMMY_CYC(0x3F) | 409738b0ca5SMason Yang OP_CMD_BYTES(0), nfc->regs + SS_CTRL(0)); 410738b0ca5SMason Yang 411738b0ca5SMason Yang ret = mxic_nfc_data_xfer(nfc, 412738b0ca5SMason Yang &instr->ctx.cmd.opcode, 413738b0ca5SMason Yang NULL, 1); 414738b0ca5SMason Yang break; 415738b0ca5SMason Yang 416738b0ca5SMason Yang case NAND_OP_ADDR_INSTR: 417738b0ca5SMason Yang writel(OP_ADDR_BUSW(OP_BUSW_8) | OP_DUMMY_CYC(0x3F) | 418738b0ca5SMason Yang OP_ADDR_BYTES(instr->ctx.addr.naddrs), 419738b0ca5SMason Yang nfc->regs + SS_CTRL(0)); 420738b0ca5SMason Yang ret = mxic_nfc_data_xfer(nfc, 421738b0ca5SMason Yang instr->ctx.addr.addrs, NULL, 422738b0ca5SMason Yang instr->ctx.addr.naddrs); 423738b0ca5SMason Yang break; 424738b0ca5SMason Yang 425738b0ca5SMason Yang case NAND_OP_DATA_IN_INSTR: 426738b0ca5SMason Yang writel(0x0, nfc->regs + ONFI_DIN_CNT(0)); 427738b0ca5SMason Yang writel(OP_DATA_BUSW(OP_BUSW_8) | OP_DUMMY_CYC(0x3F) | 428738b0ca5SMason Yang OP_READ, nfc->regs + SS_CTRL(0)); 429738b0ca5SMason Yang ret = mxic_nfc_data_xfer(nfc, NULL, 430738b0ca5SMason Yang instr->ctx.data.buf.in, 431738b0ca5SMason Yang instr->ctx.data.len); 432738b0ca5SMason Yang break; 433738b0ca5SMason Yang 434738b0ca5SMason Yang case NAND_OP_DATA_OUT_INSTR: 435738b0ca5SMason Yang writel(instr->ctx.data.len, 436738b0ca5SMason Yang nfc->regs + ONFI_DIN_CNT(0)); 437738b0ca5SMason Yang writel(OP_DATA_BUSW(OP_BUSW_8) | OP_DUMMY_CYC(0x3F), 438738b0ca5SMason Yang nfc->regs + SS_CTRL(0)); 439738b0ca5SMason Yang ret = mxic_nfc_data_xfer(nfc, 440738b0ca5SMason Yang instr->ctx.data.buf.out, NULL, 441738b0ca5SMason Yang instr->ctx.data.len); 442738b0ca5SMason Yang break; 443738b0ca5SMason Yang 444738b0ca5SMason Yang case NAND_OP_WAITRDY_INSTR: 445738b0ca5SMason Yang ret = mxic_nfc_wait_ready(chip); 446738b0ca5SMason Yang break; 447738b0ca5SMason Yang } 448738b0ca5SMason Yang } 449738b0ca5SMason Yang mxic_nfc_cs_disable(nfc); 450738b0ca5SMason Yang 451738b0ca5SMason Yang return ret; 452738b0ca5SMason Yang } 453738b0ca5SMason Yang 4544c46667bSMiquel Raynal static int mxic_nfc_setup_interface(struct nand_chip *chip, int chipnr, 4554c46667bSMiquel Raynal const struct nand_interface_config *conf) 456738b0ca5SMason Yang { 457738b0ca5SMason Yang struct mxic_nand_ctlr *nfc = nand_get_controller_data(chip); 458738b0ca5SMason Yang const struct nand_sdr_timings *sdr; 459738b0ca5SMason Yang unsigned long freq; 460738b0ca5SMason Yang int ret; 461738b0ca5SMason Yang 462738b0ca5SMason Yang sdr = nand_get_sdr_timings(conf); 463738b0ca5SMason Yang if (IS_ERR(sdr)) 464738b0ca5SMason Yang return PTR_ERR(sdr); 465738b0ca5SMason Yang 466738b0ca5SMason Yang if (chipnr == NAND_DATA_IFACE_CHECK_ONLY) 467738b0ca5SMason Yang return 0; 468738b0ca5SMason Yang 469738b0ca5SMason Yang freq = NSEC_PER_SEC / (sdr->tRC_min / 1000); 470738b0ca5SMason Yang 471738b0ca5SMason Yang ret = mxic_nfc_set_freq(nfc, freq); 472738b0ca5SMason Yang if (ret) 473738b0ca5SMason Yang dev_err(nfc->dev, "set freq:%ld failed\n", freq); 474738b0ca5SMason Yang 475738b0ca5SMason Yang if (sdr->tRC_min < 30000) 476738b0ca5SMason Yang writel(DATA_STROB_EDO_EN, nfc->regs + DATA_STROB); 477738b0ca5SMason Yang 478738b0ca5SMason Yang return 0; 479738b0ca5SMason Yang } 480738b0ca5SMason Yang 481738b0ca5SMason Yang static const struct nand_controller_ops mxic_nand_controller_ops = { 482738b0ca5SMason Yang .exec_op = mxic_nfc_exec_op, 4834c46667bSMiquel Raynal .setup_interface = mxic_nfc_setup_interface, 484738b0ca5SMason Yang }; 485738b0ca5SMason Yang 486738b0ca5SMason Yang static int mxic_nfc_probe(struct platform_device *pdev) 487738b0ca5SMason Yang { 488738b0ca5SMason Yang struct device_node *nand_np, *np = pdev->dev.of_node; 489738b0ca5SMason Yang struct mtd_info *mtd; 490738b0ca5SMason Yang struct mxic_nand_ctlr *nfc; 491738b0ca5SMason Yang struct nand_chip *nand_chip; 492738b0ca5SMason Yang int err; 493738b0ca5SMason Yang int irq; 494738b0ca5SMason Yang 495738b0ca5SMason Yang nfc = devm_kzalloc(&pdev->dev, sizeof(struct mxic_nand_ctlr), 496738b0ca5SMason Yang GFP_KERNEL); 497738b0ca5SMason Yang if (!nfc) 498738b0ca5SMason Yang return -ENOMEM; 499738b0ca5SMason Yang 500738b0ca5SMason Yang nfc->ps_clk = devm_clk_get(&pdev->dev, "ps"); 501738b0ca5SMason Yang if (IS_ERR(nfc->ps_clk)) 502738b0ca5SMason Yang return PTR_ERR(nfc->ps_clk); 503738b0ca5SMason Yang 504738b0ca5SMason Yang nfc->send_clk = devm_clk_get(&pdev->dev, "send"); 505738b0ca5SMason Yang if (IS_ERR(nfc->send_clk)) 506738b0ca5SMason Yang return PTR_ERR(nfc->send_clk); 507738b0ca5SMason Yang 508738b0ca5SMason Yang nfc->send_dly_clk = devm_clk_get(&pdev->dev, "send_dly"); 509738b0ca5SMason Yang if (IS_ERR(nfc->send_dly_clk)) 510738b0ca5SMason Yang return PTR_ERR(nfc->send_dly_clk); 511738b0ca5SMason Yang 512738b0ca5SMason Yang nfc->regs = devm_platform_ioremap_resource(pdev, 0); 513738b0ca5SMason Yang if (IS_ERR(nfc->regs)) 514738b0ca5SMason Yang return PTR_ERR(nfc->regs); 515738b0ca5SMason Yang 516738b0ca5SMason Yang nand_chip = &nfc->chip; 517738b0ca5SMason Yang mtd = nand_to_mtd(nand_chip); 518738b0ca5SMason Yang mtd->dev.parent = &pdev->dev; 519738b0ca5SMason Yang 520738b0ca5SMason Yang for_each_child_of_node(np, nand_np) 521738b0ca5SMason Yang nand_set_flash_node(nand_chip, nand_np); 522738b0ca5SMason Yang 523738b0ca5SMason Yang nand_chip->priv = nfc; 524738b0ca5SMason Yang nfc->dev = &pdev->dev; 525738b0ca5SMason Yang nfc->controller.ops = &mxic_nand_controller_ops; 526738b0ca5SMason Yang nand_controller_init(&nfc->controller); 527738b0ca5SMason Yang nand_chip->controller = &nfc->controller; 528738b0ca5SMason Yang 529738b0ca5SMason Yang irq = platform_get_irq(pdev, 0); 53021777bc9SYueHaibing if (irq < 0) 531738b0ca5SMason Yang return irq; 532738b0ca5SMason Yang 533738b0ca5SMason Yang mxic_nfc_hw_init(nfc); 534738b0ca5SMason Yang 535738b0ca5SMason Yang err = devm_request_irq(&pdev->dev, irq, mxic_nfc_isr, 536738b0ca5SMason Yang 0, "mxic-nfc", nfc); 537738b0ca5SMason Yang if (err) 538738b0ca5SMason Yang goto fail; 539738b0ca5SMason Yang 540738b0ca5SMason Yang err = nand_scan(nand_chip, 1); 541738b0ca5SMason Yang if (err) 542738b0ca5SMason Yang goto fail; 543738b0ca5SMason Yang 544738b0ca5SMason Yang err = mtd_device_register(mtd, NULL, 0); 545738b0ca5SMason Yang if (err) 546738b0ca5SMason Yang goto fail; 547738b0ca5SMason Yang 548738b0ca5SMason Yang platform_set_drvdata(pdev, nfc); 549738b0ca5SMason Yang return 0; 550738b0ca5SMason Yang 551738b0ca5SMason Yang fail: 552738b0ca5SMason Yang mxic_nfc_clk_disable(nfc); 553738b0ca5SMason Yang return err; 554738b0ca5SMason Yang } 555738b0ca5SMason Yang 556738b0ca5SMason Yang static int mxic_nfc_remove(struct platform_device *pdev) 557738b0ca5SMason Yang { 558738b0ca5SMason Yang struct mxic_nand_ctlr *nfc = platform_get_drvdata(pdev); 5598fd507bbSMiquel Raynal struct nand_chip *chip = &nfc->chip; 5608fd507bbSMiquel Raynal int ret; 561738b0ca5SMason Yang 5628fd507bbSMiquel Raynal ret = mtd_device_unregister(nand_to_mtd(chip)); 5638fd507bbSMiquel Raynal WARN_ON(ret); 5648fd507bbSMiquel Raynal nand_cleanup(chip); 5658fd507bbSMiquel Raynal 566738b0ca5SMason Yang mxic_nfc_clk_disable(nfc); 567738b0ca5SMason Yang return 0; 568738b0ca5SMason Yang } 569738b0ca5SMason Yang 570738b0ca5SMason Yang static const struct of_device_id mxic_nfc_of_ids[] = { 571738b0ca5SMason Yang { .compatible = "mxic,multi-itfc-v009-nand-controller", }, 572738b0ca5SMason Yang {}, 573738b0ca5SMason Yang }; 574738b0ca5SMason Yang MODULE_DEVICE_TABLE(of, mxic_nfc_of_ids); 575738b0ca5SMason Yang 576738b0ca5SMason Yang static struct platform_driver mxic_nfc_driver = { 577738b0ca5SMason Yang .probe = mxic_nfc_probe, 578738b0ca5SMason Yang .remove = mxic_nfc_remove, 579738b0ca5SMason Yang .driver = { 580738b0ca5SMason Yang .name = "mxic-nfc", 581738b0ca5SMason Yang .of_match_table = mxic_nfc_of_ids, 582738b0ca5SMason Yang }, 583738b0ca5SMason Yang }; 584738b0ca5SMason Yang module_platform_driver(mxic_nfc_driver); 585738b0ca5SMason Yang 586738b0ca5SMason Yang MODULE_AUTHOR("Mason Yang <masonccyang@mxic.com.tw>"); 587738b0ca5SMason Yang MODULE_DESCRIPTION("Macronix raw NAND controller driver"); 588738b0ca5SMason Yang MODULE_LICENSE("GPL v2"); 589