aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/mtd/fsmc.h
blob: 5d2556700ec26b22162598fa3ebac55f9d6783ce (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*
 * incude/mtd/fsmc.h
 *
 * ST Microelectronics
 * Flexible Static Memory Controller (FSMC)
 * platform data interface and header file
 *
 * Copyright © 2010 ST Microelectronics
 * Vipin Kumar <vipin.kumar@st.com>
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2. This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

#ifndef __MTD_FSMC_H
#define __MTD_FSMC_H

#include <linux/platform_device.h>
#include <linux/mtd/physmap.h>
#include <linux/types.h>
#include <linux/mtd/partitions.h>
#include <asm/param.h>

#define FSMC_NAND_BW8		1
#define FSMC_NAND_BW16		2

/*
 * The placement of the Command Latch Enable (CLE) and
 * Address Latch Enable (ALE) is twised around in the
 * SPEAR310 implementation.
 */
#if defined(CONFIG_MACH_SPEAR310)
#define PLAT_NAND_CLE		(1 << 17)
#define PLAT_NAND_ALE		(1 << 16)
#else
#define PLAT_NAND_CLE		(1 << 16)
#define PLAT_NAND_ALE		(1 << 17)
#endif

#define FSMC_MAX_NOR_BANKS	4
#define FSMC_MAX_NAND_BANKS	4

#define FSMC_FLASH_WIDTH8	1
#define FSMC_FLASH_WIDTH16	2

struct fsmc_nor_bank_regs {
	uint32_t ctrl;
	uint32_t ctrl_tim;
};

/* ctrl register definitions */
#define BANK_ENABLE		(1 << 0)
#define MUXED			(1 << 1)
#define NOR_DEV			(2 << 2)
#define WIDTH_8			(0 << 4)
#define WIDTH_16		(1 << 4)
#define RSTPWRDWN		(1 << 6)
#define WPROT			(1 << 7)
#define WRT_ENABLE		(1 << 12)
#define WAIT_ENB		(1 << 13)

/* ctrl_tim register definitions */

struct fsms_nand_bank_regs {
	uint32_t pc;
	uint32_t sts;
	uint32_t comm;
	uint32_t attrib;
	uint32_t ioata;
	uint32_t ecc1;
	uint32_t ecc2;
	uint32_t ecc3;
};

#define FSMC_NOR_REG_SIZE	0x40

struct fsmc_regs {
	struct fsmc_nor_bank_regs nor_bank_regs[FSMC_MAX_NOR_BANKS];
	uint8_t reserved_1[0x40 - 0x20];
	struct fsms_nand_bank_regs bank_regs[FSMC_MAX_NAND_BANKS];
	uint8_t reserved_2[0xfe0 - 0xc0];
	uint32_t peripid0;			/* 0xfe0 */
	uint32_t peripid1;			/* 0xfe4 */
	uint32_t peripid2;			/* 0xfe8 */
	uint32_t peripid3;			/* 0xfec */
	uint32_t pcellid0;			/* 0xff0 */
	uint32_t pcellid1;			/* 0xff4 */
	uint32_t pcellid2;			/* 0xff8 */
	uint32_t pcellid3;			/* 0xffc */
};

#define FSMC_BUSY_WAIT_TIMEOUT	(1 * HZ)

/* pc register definitions */
#define FSMC_RESET		(1 << 0)
#define FSMC_WAITON		(1 << 1)
#define FSMC_ENABLE		(1 << 2)
#define FSMC_DEVTYPE_NAND	(1 << 3)
#define FSMC_DEVWID_8		(0 << 4)
#define FSMC_DEVWID_16		(1 << 4)
#define FSMC_ECCEN		(1 << 6)
#define FSMC_ECCPLEN_512	(0 << 7)
#define FSMC_ECCPLEN_256	(1 << 7)
#define FSMC_TCLR_1		(1 << 9)
#define FSMC_TAR_1		(1 << 13)

/* sts register definitions */
#define FSMC_CODE_RDY		(1 << 15)

/* comm register definitions */
#define FSMC_TSET_0		(0 << 0)
#define FSMC_TWAIT_6		(6 << 8)
#define FSMC_THOLD_4		(4 << 16)
#define FSMC_THIZ_1		(1 << 24)

/* peripid2 register definitions */
#define FSMC_REVISION_MSK	(0xf)
#define FSMC_REVISION_SHFT	(0x4)

#define FSMC_VER1		1
#define FSMC_VER2		2
#define FSMC_VER3		3
#define FSMC_VER4		4
#define FSMC_VER5		5
#define FSMC_VER6		6
#define FSMC_VER7		7
#define FSMC_VER8		8

static inline uint32_t get_fsmc_version(struct fsmc_regs *regs)
{
	return (readl(&regs->peripid2) >> FSMC_REVISION_SHFT) &
				FSMC_REVISION_MSK;
}

/*
 * There are 13 bytes of ecc for every 512 byte block in FSMC version 8
 * and it has to be read consecutively and immediately after the 512
 * byte data block for hardware to generate the error bit offsets
 * Managing the ecc bytes in the following way is easier. This way is
 * similar to oobfree structure maintained already in u-boot nand driver
 */
#define MAX_ECCPLACE_ENTRIES	32

struct fsmc_nand_eccplace {
	uint8_t offset;
	uint8_t length;
};

struct fsmc_eccplace {
	struct fsmc_nand_eccplace eccplace[MAX_ECCPLACE_ENTRIES];
};

/**
 * fsmc_nand_platform_data - platform specific NAND controller config
 * @partitions: partition table for the platform, use a default fallback
 * if this is NULL
 * @nr_partitions: the number of partitions in the previous entry
 * @options: different options for the driver
 * @width: bus width
 * @bank: default bank
 * @select_bank: callback to select a certain bank, this is
 * platform-specific. If the controller only supports one bank
 * this may be set to NULL
 */
struct fsmc_nand_platform_data {
	struct mtd_partition	*partitions;
	unsigned int		nr_partitions;
	unsigned int		options;
	unsigned int		width;
	unsigned int		bank;
	void			(*select_bank)(uint32_t bank, uint32_t busw);
};

extern int __init fsmc_nor_init(struct platform_device *pdev,
		unsigned long base, uint32_t bank, uint32_t width);
extern void __init fsmc_init_board_info(struct platform_device *pdev,
		struct mtd_partition *partitions, unsigned int nr_partitions,
		unsigned int width);

#endif /* __MTD_FSMC_H */