summaryrefslogtreecommitdiff
path: root/sys/src/9/port/flashif.h
blob: 213a8c201bb5f8417dc912351cb5bbf045c84abc (plain)
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
typedef struct Flash Flash;
typedef struct Flashchip Flashchip;
typedef struct Flashpart Flashpart;
typedef struct Flashregion Flashregion;

/*
 * logical partitions
 */
enum {
	Maxflashpart = 8
};

struct Flashpart {
	char*	name;
	ulong	start;
	ulong	end;
};

enum {
	Maxflashregion = 4
};

/*
 * physical erase block regions
 */
struct Flashregion {
	int	n;		/* number of blocks in region */
	ulong	start;		/* physical base address (allowing for banks) */
	ulong	end;
	ulong	erasesize;
	ulong	eraseshift;	/* log2(erasesize) */
	ulong	pagesize;	/* if non-0, size of pages within erase block */
	ulong	pageshift;	/* log2(pagesize) */
	ulong	spares;		/* spare bytes per page, for ecc, etc. */
};

/*
 * one of a set of chips in a given region
 */
struct Flashchip {
	int	nr;
	Flashregion regions[Maxflashregion];

	uchar	id;		/* flash manufacturer ID */
	ushort	devid;		/* flash device ID */
	int	width;		/* bytes per flash line */
	int	maxwb;		/* max write buffer size */
	ulong	devsize;	/* physical device size */
	int	alg;		/* programming algorithm (if CFI) */
	int	protect;	/* software protection */
};

/*
 * structure defining a contiguous region of flash memory
 */
struct Flash {
	QLock;			/* interlock on flash operations */
	Flash*	next;

	/* following are filled in before calling Flash.reset */
	char*	type;
	void*	addr;
	ulong	size;
	int	xip;		/* executing in place: don't query */
	int	(*reset)(Flash*);

	/* following are filled in by the reset routine */
	int	(*eraseall)(Flash*);
	int	(*erasezone)(Flash*, Flashregion*, ulong);
	/* (optional) reads of correct width and alignment */
	int	(*read)(Flash*, ulong, void*, long);
	/* writes of correct width and alignment */
	int	(*write)(Flash*, ulong, void*, long);
	int	(*suspend)(Flash*);
	int	(*resume)(Flash*);
	int	(*attach)(Flash*);

	/* following might be filled in by either archflashreset or reset routine */
	int	nr;
	Flashregion regions[Maxflashregion];

	uchar	id;		/* flash manufacturer ID */
	ushort	devid;		/* flash device ID */
	int	width;		/* bytes per flash line */
	int	interleave;	/* addresses are interleaved across set of chips */
	int	bshift;		/* byte addresses are shifted */
	ulong	cmask;		/* command mask for interleaving */
	int	maxwb;		/* max write buffer size */
	ulong	devsize;	/* physical device size */
	int	alg;		/* programming algorithm (if CFI) */
	void*	data;		/* flash type routines' private storage, or nil */
	Flashpart part[Maxflashpart];	/* logical partitions */
	int	protect;	/* software protection */
	char*	sort;		/* "nand", "nor", "serial", nil (unspecified) */
};

/*
 * called by link routine of driver for specific flash type: arguments are
 * conventional name for card type/model, and card driver's reset routine.
 */
void	addflashcard(char*, int (*)(Flash*));

/*
 * called by devflash.c:/^flashreset; if flash exists,
 * sets type, address, and size in bytes of flash
 * and returns 0; returns -1 if flash doesn't exist
 */
int	archflashreset(int, Flash*);

/*
 * enable/disable write protect
 */
void	archflashwp(Flash*, int);

/*
 * flash access taking width and interleave into account
 */
int	flashget(Flash*, ulong);
void	flashput(Flash*, ulong, int);

/*
 * Architecture specific routines for managing nand devices
 */

/*
 * do any device spcific initialisation
 */
void archnand_init(Flash*);

/*
 * if claim is 1, claim device exclusively, and enable it (power it up)
 * if claim is 0, release, and disable it (power it down)
 * claiming may be as simple as a qlock per device
 */
void archnand_claim(Flash*, int claim);

/*
 * set command latch enable (CLE) and address latch enable (ALE)
 * appropriately
 */
void archnand_setCLEandALE(Flash*, int cle, int ale);

/*
 * write a sequence of bytes to the device
 */
void archnand_write(Flash*, void *buf, int len);

/*
 * read a sequence of bytes from the device
 * if buf is 0, throw away the data
 */
void archnand_read(Flash*, void *buf, int len);