18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci *
38c2ecf20Sopenharmony_ci * SuperH FLCTL nand controller
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright © 2008 Renesas Solutions Corp.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#ifndef __SH_FLCTL_H__
98c2ecf20Sopenharmony_ci#define __SH_FLCTL_H__
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/completion.h>
128c2ecf20Sopenharmony_ci#include <linux/mtd/mtd.h>
138c2ecf20Sopenharmony_ci#include <linux/mtd/rawnand.h>
148c2ecf20Sopenharmony_ci#include <linux/mtd/partitions.h>
158c2ecf20Sopenharmony_ci#include <linux/pm_qos.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci/* FLCTL registers */
188c2ecf20Sopenharmony_ci#define FLCMNCR(f)		(f->reg + 0x0)
198c2ecf20Sopenharmony_ci#define FLCMDCR(f)		(f->reg + 0x4)
208c2ecf20Sopenharmony_ci#define FLCMCDR(f)		(f->reg + 0x8)
218c2ecf20Sopenharmony_ci#define FLADR(f)		(f->reg + 0xC)
228c2ecf20Sopenharmony_ci#define FLADR2(f)		(f->reg + 0x3C)
238c2ecf20Sopenharmony_ci#define FLDATAR(f)		(f->reg + 0x10)
248c2ecf20Sopenharmony_ci#define FLDTCNTR(f)		(f->reg + 0x14)
258c2ecf20Sopenharmony_ci#define FLINTDMACR(f)		(f->reg + 0x18)
268c2ecf20Sopenharmony_ci#define FLBSYTMR(f)		(f->reg + 0x1C)
278c2ecf20Sopenharmony_ci#define FLBSYCNT(f)		(f->reg + 0x20)
288c2ecf20Sopenharmony_ci#define FLDTFIFO(f)		(f->reg + 0x24)
298c2ecf20Sopenharmony_ci#define FLECFIFO(f)		(f->reg + 0x28)
308c2ecf20Sopenharmony_ci#define FLTRCR(f)		(f->reg + 0x2C)
318c2ecf20Sopenharmony_ci#define FLHOLDCR(f)		(f->reg + 0x38)
328c2ecf20Sopenharmony_ci#define	FL4ECCRESULT0(f)	(f->reg + 0x80)
338c2ecf20Sopenharmony_ci#define	FL4ECCRESULT1(f)	(f->reg + 0x84)
348c2ecf20Sopenharmony_ci#define	FL4ECCRESULT2(f)	(f->reg + 0x88)
358c2ecf20Sopenharmony_ci#define	FL4ECCRESULT3(f)	(f->reg + 0x8C)
368c2ecf20Sopenharmony_ci#define	FL4ECCCR(f)		(f->reg + 0x90)
378c2ecf20Sopenharmony_ci#define	FL4ECCCNT(f)		(f->reg + 0x94)
388c2ecf20Sopenharmony_ci#define	FLERRADR(f)		(f->reg + 0x98)
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci/* FLCMNCR control bits */
418c2ecf20Sopenharmony_ci#define _4ECCCNTEN	(0x1 << 24)
428c2ecf20Sopenharmony_ci#define _4ECCEN		(0x1 << 23)
438c2ecf20Sopenharmony_ci#define _4ECCCORRECT	(0x1 << 22)
448c2ecf20Sopenharmony_ci#define SHBUSSEL	(0x1 << 20)
458c2ecf20Sopenharmony_ci#define SEL_16BIT	(0x1 << 19)
468c2ecf20Sopenharmony_ci#define SNAND_E		(0x1 << 18)	/* SNAND (0=512 1=2048)*/
478c2ecf20Sopenharmony_ci#define QTSEL_E		(0x1 << 17)
488c2ecf20Sopenharmony_ci#define ENDIAN		(0x1 << 16)	/* 1 = little endian */
498c2ecf20Sopenharmony_ci#define FCKSEL_E	(0x1 << 15)
508c2ecf20Sopenharmony_ci#define ACM_SACCES_MODE	(0x01 << 10)
518c2ecf20Sopenharmony_ci#define NANWF_E		(0x1 << 9)
528c2ecf20Sopenharmony_ci#define SE_D		(0x1 << 8)	/* Spare area disable */
538c2ecf20Sopenharmony_ci#define	CE1_ENABLE	(0x1 << 4)	/* Chip Enable 1 */
548c2ecf20Sopenharmony_ci#define	CE0_ENABLE	(0x1 << 3)	/* Chip Enable 0 */
558c2ecf20Sopenharmony_ci#define	TYPESEL_SET	(0x1 << 0)
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci/*
588c2ecf20Sopenharmony_ci * Clock settings using the PULSEx registers from FLCMNCR
598c2ecf20Sopenharmony_ci *
608c2ecf20Sopenharmony_ci * Some hardware uses bits called PULSEx instead of FCKSEL_E and QTSEL_E
618c2ecf20Sopenharmony_ci * to control the clock divider used between the High-Speed Peripheral Clock
628c2ecf20Sopenharmony_ci * and the FLCTL internal clock. If so, use CLK_8_BIT_xxx for connecting 8 bit
638c2ecf20Sopenharmony_ci * and CLK_16_BIT_xxx for connecting 16 bit bus bandwith NAND chips. For the 16
648c2ecf20Sopenharmony_ci * bit version the divider is seperate for the pulse width of high and low
658c2ecf20Sopenharmony_ci * signals.
668c2ecf20Sopenharmony_ci */
678c2ecf20Sopenharmony_ci#define PULSE3	(0x1 << 27)
688c2ecf20Sopenharmony_ci#define PULSE2	(0x1 << 17)
698c2ecf20Sopenharmony_ci#define PULSE1	(0x1 << 15)
708c2ecf20Sopenharmony_ci#define PULSE0	(0x1 << 9)
718c2ecf20Sopenharmony_ci#define CLK_8B_0_5			PULSE1
728c2ecf20Sopenharmony_ci#define CLK_8B_1			0x0
738c2ecf20Sopenharmony_ci#define CLK_8B_1_5			(PULSE1 | PULSE2)
748c2ecf20Sopenharmony_ci#define CLK_8B_2			PULSE0
758c2ecf20Sopenharmony_ci#define CLK_8B_3			(PULSE0 | PULSE1 | PULSE2)
768c2ecf20Sopenharmony_ci#define CLK_8B_4			(PULSE0 | PULSE2)
778c2ecf20Sopenharmony_ci#define CLK_16B_6L_2H			PULSE0
788c2ecf20Sopenharmony_ci#define CLK_16B_9L_3H			(PULSE0 | PULSE1 | PULSE2)
798c2ecf20Sopenharmony_ci#define CLK_16B_12L_4H			(PULSE0 | PULSE2)
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci/* FLCMDCR control bits */
828c2ecf20Sopenharmony_ci#define ADRCNT2_E	(0x1 << 31)	/* 5byte address enable */
838c2ecf20Sopenharmony_ci#define ADRMD_E		(0x1 << 26)	/* Sector address access */
848c2ecf20Sopenharmony_ci#define CDSRC_E		(0x1 << 25)	/* Data buffer selection */
858c2ecf20Sopenharmony_ci#define DOSR_E		(0x1 << 24)	/* Status read check */
868c2ecf20Sopenharmony_ci#define SELRW		(0x1 << 21)	/*  0:read 1:write */
878c2ecf20Sopenharmony_ci#define DOADR_E		(0x1 << 20)	/* Address stage execute */
888c2ecf20Sopenharmony_ci#define ADRCNT_1	(0x00 << 18)	/* Address data bytes: 1byte */
898c2ecf20Sopenharmony_ci#define ADRCNT_2	(0x01 << 18)	/* Address data bytes: 2byte */
908c2ecf20Sopenharmony_ci#define ADRCNT_3	(0x02 << 18)	/* Address data bytes: 3byte */
918c2ecf20Sopenharmony_ci#define ADRCNT_4	(0x03 << 18)	/* Address data bytes: 4byte */
928c2ecf20Sopenharmony_ci#define DOCMD2_E	(0x1 << 17)	/* 2nd cmd stage execute */
938c2ecf20Sopenharmony_ci#define DOCMD1_E	(0x1 << 16)	/* 1st cmd stage execute */
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci/* FLINTDMACR control bits */
968c2ecf20Sopenharmony_ci#define ESTERINTE	(0x1 << 24)	/* ECC error interrupt enable */
978c2ecf20Sopenharmony_ci#define AC1CLR		(0x1 << 19)	/* ECC FIFO clear */
988c2ecf20Sopenharmony_ci#define AC0CLR		(0x1 << 18)	/* Data FIFO clear */
998c2ecf20Sopenharmony_ci#define DREQ0EN		(0x1 << 16)	/* FLDTFIFODMA Request Enable */
1008c2ecf20Sopenharmony_ci#define ECERB		(0x1 << 9)	/* ECC error */
1018c2ecf20Sopenharmony_ci#define STERB		(0x1 << 8)	/* Status error */
1028c2ecf20Sopenharmony_ci#define STERINTE	(0x1 << 4)	/* Status error enable */
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci/* FLTRCR control bits */
1058c2ecf20Sopenharmony_ci#define TRSTRT		(0x1 << 0)	/* translation start */
1068c2ecf20Sopenharmony_ci#define TREND		(0x1 << 1)	/* translation end */
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci/*
1098c2ecf20Sopenharmony_ci * FLHOLDCR control bits
1108c2ecf20Sopenharmony_ci *
1118c2ecf20Sopenharmony_ci * HOLDEN: Bus Occupancy Enable (inverted)
1128c2ecf20Sopenharmony_ci * Enable this bit when the external bus might be used in between transfers.
1138c2ecf20Sopenharmony_ci * If not set and the bus gets used by other modules, a deadlock occurs.
1148c2ecf20Sopenharmony_ci */
1158c2ecf20Sopenharmony_ci#define HOLDEN		(0x1 << 0)
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci/* FL4ECCCR control bits */
1188c2ecf20Sopenharmony_ci#define	_4ECCFA		(0x1 << 2)	/* 4 symbols correct fault */
1198c2ecf20Sopenharmony_ci#define	_4ECCEND	(0x1 << 1)	/* 4 symbols end */
1208c2ecf20Sopenharmony_ci#define	_4ECCEXST	(0x1 << 0)	/* 4 symbols exist */
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci#define LOOP_TIMEOUT_MAX	0x00010000
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_cienum flctl_ecc_res_t {
1258c2ecf20Sopenharmony_ci	FL_SUCCESS,
1268c2ecf20Sopenharmony_ci	FL_REPAIRABLE,
1278c2ecf20Sopenharmony_ci	FL_ERROR,
1288c2ecf20Sopenharmony_ci	FL_TIMEOUT
1298c2ecf20Sopenharmony_ci};
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_cistruct dma_chan;
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_cistruct sh_flctl {
1348c2ecf20Sopenharmony_ci	struct nand_chip	chip;
1358c2ecf20Sopenharmony_ci	struct platform_device	*pdev;
1368c2ecf20Sopenharmony_ci	struct dev_pm_qos_request pm_qos;
1378c2ecf20Sopenharmony_ci	void __iomem		*reg;
1388c2ecf20Sopenharmony_ci	resource_size_t		fifo;
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	uint8_t	done_buff[2048 + 64];	/* max size 2048 + 64 */
1418c2ecf20Sopenharmony_ci	int	read_bytes;
1428c2ecf20Sopenharmony_ci	unsigned int index;
1438c2ecf20Sopenharmony_ci	int	seqin_column;		/* column in SEQIN cmd */
1448c2ecf20Sopenharmony_ci	int	seqin_page_addr;	/* page_addr in SEQIN cmd */
1458c2ecf20Sopenharmony_ci	uint32_t seqin_read_cmd;		/* read cmd in SEQIN cmd */
1468c2ecf20Sopenharmony_ci	int	erase1_page_addr;	/* page_addr in ERASE1 cmd */
1478c2ecf20Sopenharmony_ci	uint32_t erase_ADRCNT;		/* bits of FLCMDCR in ERASE1 cmd */
1488c2ecf20Sopenharmony_ci	uint32_t rw_ADRCNT;	/* bits of FLCMDCR in READ WRITE cmd */
1498c2ecf20Sopenharmony_ci	uint32_t flcmncr_base;	/* base value of FLCMNCR */
1508c2ecf20Sopenharmony_ci	uint32_t flintdmacr_base;	/* irq enable bits */
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	unsigned page_size:1;	/* NAND page size (0 = 512, 1 = 2048) */
1538c2ecf20Sopenharmony_ci	unsigned hwecc:1;	/* Hardware ECC (0 = disabled, 1 = enabled) */
1548c2ecf20Sopenharmony_ci	unsigned holden:1;	/* Hardware has FLHOLDCR and HOLDEN is set */
1558c2ecf20Sopenharmony_ci	unsigned qos_request:1;	/* QoS request to prevent deep power shutdown */
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	/* DMA related objects */
1588c2ecf20Sopenharmony_ci	struct dma_chan		*chan_fifo0_rx;
1598c2ecf20Sopenharmony_ci	struct dma_chan		*chan_fifo0_tx;
1608c2ecf20Sopenharmony_ci	struct completion	dma_complete;
1618c2ecf20Sopenharmony_ci};
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_cistruct sh_flctl_platform_data {
1648c2ecf20Sopenharmony_ci	struct mtd_partition	*parts;
1658c2ecf20Sopenharmony_ci	int			nr_parts;
1668c2ecf20Sopenharmony_ci	unsigned long		flcmncr_val;
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	unsigned has_hwecc:1;
1698c2ecf20Sopenharmony_ci	unsigned use_holden:1;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	unsigned int            slave_id_fifo0_tx;
1728c2ecf20Sopenharmony_ci	unsigned int            slave_id_fifo0_rx;
1738c2ecf20Sopenharmony_ci};
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_cistatic inline struct sh_flctl *mtd_to_flctl(struct mtd_info *mtdinfo)
1768c2ecf20Sopenharmony_ci{
1778c2ecf20Sopenharmony_ci	return container_of(mtd_to_nand(mtdinfo), struct sh_flctl, chip);
1788c2ecf20Sopenharmony_ci}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci#endif	/* __SH_FLCTL_H__ */
181