// SPDX-License-Identifier: GPL-2.0
/*
* ARM PL35X NAND flash controller driver
*
* Copyright (C) 2017 Xilinx, Inc
* Author:
* Miquel Raynal <miquel.raynal@bootlin.com>
* Original work (rewritten):
* Punnaiah Choudary Kalluri <punnaia@xilinx.com>
* Naga Sureshkumar Relli <nagasure@xilinx.com>
*/
#include <linux/amba/bus.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/iopoll.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/clk.h>
#define PL35X_NANDC_DRIVER_NAME "pl35x-nand-controller"
/* SMC controller status register (RO) */
#define PL35X_SMC_MEMC_STATUS 0x0
#define PL35X_SMC_MEMC_STATUS_RAW_INT_STATUS1 BIT(6)
/* SMC clear config register (WO) */
#define PL35X_SMC_MEMC_CFG_CLR 0xC
#define PL35X_SMC_MEMC_CFG_CLR_INT_DIS_1 BIT(1)
#define PL35X_SMC_MEMC_CFG_CLR_INT_CLR_1 BIT(4)
#define PL35X_SMC_MEMC_CFG_CLR_ECC_INT_DIS_1 BIT(6)
/* SMC direct command register (WO) */
#define PL35X_SMC_DIRECT_CMD 0x10
#define PL35X_SMC_DIRECT_CMD_NAND_CS (0x4 << 23)
#define PL35X_SMC_DIRECT_CMD_UPD_REGS (0x2 << 21)
/* SMC set cycles register (WO) */
#define PL35X_SMC_CYCLES 0x14
#define PL35X_SMC_NAND_TRC_CYCLES(x) ((x) << 0)
#define PL35X_SMC_NAND_TWC_CYCLES(x) ((x) << 4)
#define PL35X_SMC_NAND_TREA_CYCLES(x) ((x) << 8)
#define PL35X_SMC_NAND_TWP_CYCLES(x) ((x) << 11)
#define PL35X_SMC_NAND_TCLR_CYCLES(x) ((x) << 14)
#define PL35X_SMC_NAND_TAR_CYCLES(x) ((x) << 17)
#define PL35X_SMC_NAND_TRR_CYCLES(x) ((x) << 20)
/* SMC set opmode register (WO) */
#define PL35X_SMC_OPMODE 0x18
#define PL35X_SMC_OPMODE_BW_8 0
#define PL35X_SMC_OPMODE_BW_16 1
/* SMC ECC status register (RO) */
#define PL35X_SMC_ECC_STATUS 0x400
#define PL35X_SMC_ECC_STATUS_ECC_BUSY BIT(6)
/* SMC ECC configuration register */
#define PL35X_SMC_ECC_CFG 0x404
#define PL35X_SMC_ECC_CFG_MODE_MASK 0xC
#define PL35X_SMC_ECC_CFG_MODE_BYPASS 0
#define PL35X_SMC_ECC_CFG_MODE_APB BIT(2)
#define PL35X_SMC_ECC_CFG_MODE_MEM BIT(3)
#define PL35X_SMC_ECC_CFG_PGSIZE_MASK 0x3
/* SMC ECC command 1 register */
#define PL35X_SMC_ECC_CMD1 0x408
#define PL35X_SMC_ECC_CMD1_WRITE(x) ((x) << 0)
#define PL35X_SMC_ECC_CMD1_READ(x) ((x) << 8)
#define PL35X_SMC_ECC_CMD1_READ_END(x) ((x) << 16)
#define PL35X_SMC_ECC_CMD1_READ_END_VALID(x) ((x) << 24)
/* SMC ECC command 2 register */
#define PL35X_SMC_ECC_CMD2 0x40C
#define PL35X_SMC_ECC_CMD2_WRITE_COL_CHG(x) ((x) << 0)
#define PL35X_SMC_ECC_CMD2_READ_COL_CHG(x) ((x) << 8)
#define PL35X_SMC_ECC_CMD2_READ_COL_CHG_END(x) ((x) << 16)
#define PL35X_SMC_ECC_CMD2_READ_COL_CHG_END_VALID(x) ((x) << 24)
/* SMC ECC value registers (RO) */
#define PL35X_SMC_ECC_VALUE(x) (0x418 + (4 * (x)))
#define PL35X_SMC_ECC_VALUE_IS_CORRECTABLE(x) ((x) & BIT(27))
#define PL35X_SMC_ECC_VALUE_HAS_FAILED(x) ((x) & BIT(28))
#define PL35X_SMC_ECC_VALUE_IS_VALID(x) ((x) & BIT(30))
/* NAND AXI interface */
#define PL35X_SMC_CMD_PHASE 0
#define PL35X_SMC_CMD_PHASE_CMD0(x) ((x) << 3)
#define PL35X_SMC_CMD_PHASE_CMD1(x) ((x) << 11)
#define PL35X_SMC_CMD_PHASE_CMD1_VALID BIT(20)
#define PL35X_SMC_CMD_PHASE_ADDR(pos, x) ((x) << (8 * (pos)))
#define PL35X_SMC_CMD_PHASE_NADDRS(x) ((x) << 21)
#define PL35X_SMC_DATA_PHASE BIT(19)
#define PL35X_SMC_DATA_PHASE_ECC_LAST BIT(10)
#define PL35X_SMC_DATA_PHASE_CLEAR_CS BIT(21)
#define PL35X_NAND_MAX_CS 1
#define PL35X_NAND_LAST_XFER_SZ 4
#define TO_CYCLES(ps, period_ns) (DIV_ROUND_UP((ps) / 1000, period_ns))
#define PL35X_NAND_ECC_BITS_MASK 0xFFF
#define PL35X_NAND_ECC_BYTE_OFF_MASK 0x1FF
#define PL35X_NAND_ECC_BIT_OFF_MASK 0x7
struct pl35x_nand_timings {
unsigned int t_rc:4;
unsigned int t_wc:4;
unsigned int t_rea:3;
unsigned int t_wp:3;
unsigned int t_clr:3;
unsigned int t_ar:3;
unsigned int t_rr:4;
unsigned int rsvd:8;
};
struct pl35x_nand {
struct list_head node;
struct nand_chip chip;
unsigned int cs;
unsigned int addr_cycles;
u32 ecc_cfg;
u32 timings;
};
/**
* struct pl35x_nandc - NAND flash controller driver structure
* @dev: Kernel device
* @conf_regs: SMC configuration registers for command phase
* @io_regs: NAND data registers for data phase
* @controller: Core NAND controller structure
* @chips: List of connected NAND chips
* @selected_chip: NAND chip currently selected by the controller
* @assigned_cs: List of assigned CS
* @ecc_buf: Temporary buffer to extract ECC bytes
*/
struct pl35x_nandc {
struct device *dev;
void __iomem *conf_regs;
void __iomem *io_regs;
struct nand_controller controller;
struct list_head chips;
struct nand_chip *selected_chip;
unsigned long assigned_cs;
u8 *ecc_buf;
};
static inline struct pl35x_nandc *to_pl35x_nandc(struct nand_controller *ctrl)
{
return container_of(ctrl, struct pl35x_nandc, controller);
}
static inline struct pl35x_nand *to_pl35x_nand(struct nand_chip *chip)
{
return container_of(chip, struct pl35x_nand, chip);
}
static int pl35x_ecc_ooblayout16_ecc(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobregion)
{
struct nand_chip *chip = mtd_to_nand(mtd);
if (section >= chip->ecc.steps)
return -ERANGE;
oobregion->offset = (section * chip->ecc.bytes);
oobregion->length = chip->ecc.bytes;
return 0;
}
static int pl35x_ecc_ooblayout16_free(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobregion)
{
struct nand_chip *chip = mtd_to_nand(mtd);
if (section >=