summaryrefslogtreecommitdiff
path: root/cpu/mpc824x/drivers/i2c/i2c.h
blob: 48a401d9076400cc708ce5adbfaa37b7652c7648 (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
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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
#ifndef I2C_H
#define I2C_H

/****************************************************
 *
 * Copyright Motrola 1999
 *
 ****************************************************/
#define get_eumbbar() CFG_EUMB_ADDR

#define I2CADR    0x00003000
#define I2CFDR    0x00003004
#define I2CCR     0x00003008
#define I2CSR     0x0000300C
#define I2CDR     0x00003010

typedef enum _i2cstatus
{
 I2CSUCCESS     = 0x3000,
 I2CADDRESS,
 I2CERROR,
 I2CBUFFFULL,
 I2CBUFFEMPTY,
 I2CXMITERROR,
 I2CRCVERROR,
 I2CBUSBUSY,
 I2CALOSS,
 I2CNOEVENT,
} I2CStatus;

typedef enum i2c_control
{
 MEN  = 0x00000080,
 MIEN = 0x00000040,
 MSTA = 0x00000020,
 MTX  = 0x00000010,
 TXAK = 0x00000008,
 RSTA = 0x00000004,
} I2C_CONTROL;

typedef enum i2c_status
{
  MCF   =  0x00000080,
  MAAS  =  0x00000040,
  MBB   =  0x00000020,
  MAL   =  0x00000010,
  SRW   =  0x00000004,
  MIF   =  0x00000002,
  RXAK  =  0x00000001,
} I2C_STATUS;

typedef struct _i2c_ctrl
{
	unsigned int reserved0 : 24;
	unsigned int men       : 1;
	unsigned int mien      : 1;
	unsigned int msta      : 1;
	unsigned int mtx       : 1;
	unsigned int txak      : 1;
	unsigned int rsta      : 1;
	unsigned int reserved1 : 2;
} I2C_CTRL;

typedef struct _i2c_stat
{
	unsigned int rsrv0    : 24;
	unsigned int mcf      : 1;
	unsigned int maas     : 1;
	unsigned int mbb      : 1;
	unsigned int mal      : 1;
	unsigned int rsrv1    : 1;
	unsigned int srw      : 1;
	unsigned int mif      : 1;
	unsigned int rxak     : 1;
} I2C_STAT;

typedef enum _i2c_mode
{
	RCV =  0,
	XMIT = 1,
} I2C_MODE;

/******************** App. API ********************
 * The application API is for user level application
 * to use the funcitonality provided by I2C driver
 *
 * Note: Its App.s responsibility to swap the data
 *       byte. In our API, we just transfer whatever
 *       we are given
 **************************************************/
/**
 * Note:
 *
 * In all following functions,
 * the caller shall pass the configured embedded utility memory
 * block base, EUMBBAR.
 **/

/* Send a buffer of data to the intended rcv_addr.
 * If stop_flag is set, after the whole buffer
 * is sent, generate a STOP signal provided that the
 * receiver doesn't signal the STOP in the middle.
 * I2C is the master performing transmitting. If
 * no STOP signal is generated at the end of current
 * transaction, the master can generate a START signal
 * to another slave addr.
 *
 * return I2CSUCCESS if no error.
 */
static I2CStatus I2C_put( unsigned int  eumbbar,
						  unsigned char rcv_addr,    /* receiver's address */
			      unsigned char *buffer_ptr, /* pointer of data to be sent */
					      unsigned int  length,      /* number of byte of in the buffer */
					      unsigned int  stop_flag,   /* 1 - signal STOP when buffer is empty
									  * 0 - no STOP signal when buffer is empty
												  */
						  unsigned int  is_cnt );    /* 1 - this is a restart, don't check MBB
						      * 0 - this is a new start, check MBB
													  */

/* Receive a buffer of data from the desired sender_addr
 * If stop_flag is set, when the buffer is full and the
 * sender does not signal STOP, generate a STOP signal.
 * I2C is the master performing receiving. If no STOP signal
 * is generated, the master can generate a START signal
 * to another slave addr.
 *
 * return I2CSUCCESS if no error.
 */
static I2CStatus I2C_get( unsigned int  eumbbar,
						  unsigned char sender_addr, /* sender's address */
					      unsigned char *buffer_ptr, /* pointer of receiving buffer */
					  unsigned int  length,      /* length of the receiving buffer */
					      unsigned int  stop_flag,   /* 1 - signal STOP when buffer is full
									  * 0 - no STOP signal when buffer is full
												      */
						  unsigned int  is_cnt );    /* 1 - this is a restart, don't check MBB
						      * 0 - this is a new start, check MBB
													  */

#if 0 /* the I2C_write and I2C_read functions are not active */
/* Send a buffer of data to the requiring master.
 * If stop_flag is set, after the whole buffer is sent,
 * generate a STOP signal provided that the requiring
 * receiver doesn't signal the STOP in the middle.
 * I2C is the slave performing transmitting.
 *
 * return I2CSUCCESS if no error.
 *
 * Note: due to the Kahlua design, slave transmitter
 *       shall not signal STOP since there is no way
 *       for master to detect it, causing I2C bus hung.
 *
 *       For the above reason, the stop_flag is always
 *       set, i.e., 1.
 *
 *       programmer shall use the timer on Kahlua to
 *       control the interval of data byte at the
 *       master side.
 */
static I2CStatus I2C_write( unsigned int eumbbar,
						    unsigned char *buffer_ptr, /* pointer of data to be sent */
						unsigned int  length,      /* number of byte of in the buffer */
						unsigned int  stop_flag ); /* 1 - signal STOP when buffer is empty
											* 0 - no STOP signal when buffer is empty
												    */

 /* Receive a buffer of data from the sending master.
 * If stop_flag is set, when the buffer is full and the
 * sender does not signal STOP, generate a STOP signal.
 * I2C is the slave performing receiving.
 *
 * return I2CSUCCESS if no error.
 */
static I2CStatus I2C_read(unsigned int  eumbbar,
						  unsigned char *buffer_ptr, /* pointer of receiving buffer */
					      unsigned int  length,      /* length of the receiving buffer */
					  unsigned int  stop_flag ); /* 1 - signal STOP when buffer is full
									  * 0 - no STOP signal when buffer is full
												      */
#endif /* of if0 for turning off I2C_read & I2C_write */

/* if interrupt is not used, this is the timer event handler.
 * After each fixed time interval, this function can be called
 * to check the I2C status and call appropriate function to
 * handle the status event.
 */
static I2CStatus I2C_Timer_Event( unsigned int eumbbar, I2CStatus (*handler)( unsigned int ) );

/********************* Kernel API ************************
 * Kernel APIs are functions I2C driver provides to the
 * O.S.
 *********************************************************/

/******************* device I/O function ***************/

/*  Generate a START signal in the desired mode.
 *  I2C is the master.
 *
 * return I2CSUCCESS if no error.
 *        I2CERROR   if i2c unit is not enabled.
 *        I2CBUSBUSY if bus cannot be granted
 */
static I2CStatus I2C_Start( unsigned int  eumbbar,
						    unsigned char slave_addr, /* address of the receiver */
				I2C_MODE     mode,       /* XMIT(1) - put (write)
										  * RCV(0)  - get (read)
													  */
						    unsigned int is_cnt ); /* 1 - this is a restart, don't check MBB
													* 0 - this is a new start, check MBB
						    */

/* Generate a STOP signal to terminate the transaction. */
static I2CStatus I2C_Stop( unsigned int eumbbar );

/*  Do a one-byte master transmit.
 *
 *  return I2CBUFFEMPTY if this is the last byte.
 *  Otherwise return I2CSUCCESS
 */
static I2CStatus I2C_Master_Xmit( unsigned int eumbbar );

/*  Do a one-byte master receive.
 *
 *  return I2CBUFFFULL if this is the last byte.
 *  Otherwise return I2CSUCCESS
 */
static I2CStatus I2C_Master_Rcv( unsigned int eumbbar );

/*  Do a one-byte slave transmit.
 *
 *  return I2CBUFFEMPTY if this is the last byte.
 *  Otherwise return I2CSUCCESS
 *
 */
static I2CStatus I2C_Slave_Xmit( unsigned int eumbbar );

/* Do a one-byte slave receive.
 *
 *  return I2CBUFFFULL if this is the last byte.
 *  Otherwise return I2CSUCCESS
 */
static I2CStatus I2C_Slave_Rcv( unsigned int eumbbar  );

/* Process slave address phase.
 *
 * return I2CADDRESS if this is slave receiver's address phase
 * Otherwise return the result of slave xmit one byte.
 */
static I2CStatus I2C_Slave_Addr( unsigned int eumbbar );

/******************* Device Control Fucntion ****************/
/*  Initialize I2C unit with desired frequency divider,
 *  driver's slave address w/o interrupt enabled.
 *
 *  This function must be called before I2C unit can
 *  be used.
 */
static I2CStatus I2C_Init( unsigned int  eumbbar,
						   unsigned char fdr,       /* frequency divider */
			       unsigned char addr,      /* driver's address used for receiving */
					   unsigned int en_int);    /* 1 - enable I2C interrupt
									 * 0 - disable I2C interrup
												 */

/* I2C interrupt service routine.
 *
 * return I2CADDRESS if it is receiver's (either master or slave) address phase.
 * return the result of xmit or receive one byte
 */
static I2CStatus I2C_ISR(unsigned int eumbbar  );

/* Set I2C Status, i.e., write to I2CSR */
static void I2C_Set_Stat( unsigned int eumbbar, I2C_STAT stat );

/* Query I2C Status, i.e., read I2CSR */
static I2C_STAT I2C_Get_Stat( unsigned int eumbbar );

/* Change I2C Control bits, i.e., write to I2CCR */
static void I2C_Set_Ctrl( unsigned int eumbbar, I2C_CTRL ); /* new control value */

/* Query I2C Control bits, i.e., read I2CCR */
static I2C_CTRL I2C_Get_Ctrl( unsigned int eumbbar );

/* This function performs the work for I2C_do_transaction.  The work is
 * split into this function to enable I2C_do_transaction to first transmit
 * the data address to the I2C slave device without putting the data address
 * into the first byte of the buffer.
 *
 * en_int controls interrupt/polling mode
 * act is the type of transaction
 * i2c_addr is the I2C address of the slave device
 * len is the length of data to send or receive
 * buffer is the address of the data buffer
 * stop = I2C_NO_STOP, don't signal STOP at end of transaction
 *        I2C_STOP, signal STOP at end of transaction
 * retry is the timeout retry value, currently ignored
 * rsta = I2C_NO_RESTART, this is not continuation of existing transaction
 *        I2C_RESTART, this is a continuation of existing transaction
 */
static I2C_Status I2C_do_buffer( I2C_INTERRUPT_MODE en_int,
				 I2C_TRANSACTION_MODE act,
				 unsigned char i2c_addr,
				 int len,
				 unsigned char *buffer,
				 I2C_STOP_MODE stop,
				 int retry,
				 I2C_RESTART_MODE rsta);
#endif