source: rtems/bsps/powerpc/mvme3100/i2c/mpc8540_i2c.c @ 65f868c

5
Last change on this file since 65f868c was a2dad96, checked in by Sebastian Huber <sebastian.huber@…>, on 04/23/18 at 07:45:28

bsps: Move I2C drivers to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 11.5 KB
Line 
1/* I2C bus driver for mpc8540-based boards */
2
3/*
4 * Authorship
5 * ----------
6 * This software ('mvme3100' RTEMS BSP) was created by
7 *
8 *     Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
9 *         Stanford Linear Accelerator Center, Stanford University.
10 *
11 * Acknowledgement of sponsorship
12 * ------------------------------
13 * The 'mvme3100' BSP was produced by
14 *     the Stanford Linear Accelerator Center, Stanford University,
15 *         under Contract DE-AC03-76SFO0515 with the Department of Energy.
16 *
17 * Government disclaimer of liability
18 * ----------------------------------
19 * Neither the United States nor the United States Department of Energy,
20 * nor any of their employees, makes any warranty, express or implied, or
21 * assumes any legal liability or responsibility for the accuracy,
22 * completeness, or usefulness of any data, apparatus, product, or process
23 * disclosed, or represents that its use would not infringe privately owned
24 * rights.
25 *
26 * Stanford disclaimer of liability
27 * --------------------------------
28 * Stanford University makes no representations or warranties, express or
29 * implied, nor assumes any liability for the use of this software.
30 *
31 * Stanford disclaimer of copyright
32 * --------------------------------
33 * Stanford University, owner of the copyright, hereby disclaims its
34 * copyright and all other rights in this software.  Hence, anyone may
35 * freely use it for any purpose without restriction.
36 *
37 * Maintenance of notices
38 * ----------------------
39 * In the interest of clarity regarding the origin and status of this
40 * SLAC software, this and all the preceding Stanford University notices
41 * are to remain affixed to any copy or derivative of this software made
42 * or distributed by the recipient and are to be affixed to any copy of
43 * software made or distributed by the recipient that contains a copy or
44 * derivative of this software.
45 *
46 * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
47 */
48
49/* Note: We maintain base address, IRQ etc. statically and
50 *       globally. We don't bother creating driver-specific
51 *       data or using the bus handle but simply assume
52 *       this is the only 8540/i2c bus in the system.
53 *       Proper support for multiple instances would not
54 *       be very hard to add but I don't see the point...
55 */
56
57#include <rtems.h>
58#include <bsp.h>
59#include <rtems/libi2c.h>
60#include <bsp/irq.h>
61#include <libcpu/spr.h>
62#include <libcpu/io.h>
63#include <rtems/bspIo.h>
64#include <rtems/score/sysstate.h>
65
66#include <bsp/mpc8540_i2c_busdrv.h>
67
68#define STATIC static
69
70/* I2C controller register definitions */
71#define I2CADR                          0x3000
72#define I2CFDR                          0x3004
73#define I2CCR                           0x3008
74#define I2CCR_MEN                               (1<<(7-0))
75#define I2CCR_MIEN                              (1<<(7-1))
76#define I2CCR_MSTA                              (1<<(7-2))
77#define I2CCR_MTX                               (1<<(7-3))
78#define I2CCR_TXAK                              (1<<(7-4))
79#define I2CCR_RSTA                              (1<<(7-5))
80#define I2CCR_BCST                              (1<<(7-7))
81#define I2CSR                           0x300c
82#define I2CSR_MCF                               (1<<(7-0))
83#define I2CSR_MAAS                              (1<<(7-1))
84#define I2CSR_MBB                               (1<<(7-2))
85#define I2CSR_MAL                               (1<<(7-3))
86#define I2CSR_BCSTM                             (1<<(7-4))
87#define I2CSR_SRW                               (1<<(7-5))
88#define I2CSR_MIF                               (1<<(7-6))
89#define I2CSR_RXAK                              (1<<(7-7))
90#define I2CDR                           0x3010
91#define I2CDFSRR                        0x3014
92
93SPR_RO(TBRL)
94
95/********* Global Variables **********/
96
97/*
98 * Semaphore for synchronizing accessing task
99 * with the (slow) hardware operation.
100 * Task takes semaphore and blocks, ISR releases.
101 */
102static rtems_id syncsem = 0;
103
104static inline int ok_to_block(void)
105{
106        return syncsem && _System_state_Is_up( _System_state_Get() );
107}
108
109/*
110 * Wild guess for 0.2 s; this timeout is effective
111 * in polling mode; during early init we don't know
112 * the system clock rate yet - it's one of the things
113 * we have to read from VPD -- via i2c.
114 */
115
116static uint32_t poll_timeout = 333333333/8/5;
117
118/********* Primitives ****************/
119
120static inline uint8_t
121i2c_rd(unsigned reg)
122{
123        return in_8( (volatile uint8_t *)(BSP_8540_CCSR_BASE + reg) );
124}
125
126static inline void
127i2c_wr(unsigned reg, uint8_t val)
128{
129        out_8( (volatile uint8_t *)(BSP_8540_CCSR_BASE + reg), val );
130}
131
132static inline void
133i2c_set(unsigned reg, uint8_t val)
134{
135        i2c_wr( reg, i2c_rd( reg ) | val );
136}
137
138static inline void
139i2c_clr(unsigned reg, uint8_t val)
140{
141        i2c_wr( reg, i2c_rd( reg ) & ~val );
142}
143
144/********* Helper Routines ***********/
145
146/* Synchronize (wait) for a condition on the
147 * i2c bus. Wait for START or STOP to be complete
148 * or wait for a byte-transfer.
149 * The latter is much slower (9 bit times vs. 1/2
150 * in the former cases).
151 *
152 * If the system is up (and we may block) then
153 * this routine attempts to block the current
154 * task rather than busy-waiting.
155 *
156 * NOTE: waiting for START/STOP always requires
157 *       polling.
158 */
159
160/* wait until i2c status reg AND mask == cond */
161static rtems_status_code
162i2c_wait( uint8_t msk, uint8_t cond )
163{
164uint32_t              then;
165rtems_status_code sc;
166static int        warn = 0;
167
168        if ( I2CSR_MIF == msk && ok_to_block() ) {
169                /* block on semaphore only if system is up and sema initialized */
170                sc = rtems_semaphore_obtain( syncsem, RTEMS_WAIT, 100 );
171                if ( RTEMS_SUCCESSFUL != sc )
172                        return sc;
173        } else {
174                /* system not up (no SEMA yet ) or waiting on something other
175                 * than MIF
176                 */
177                if ( I2CSR_MIF == msk && _System_state_Is_up( _System_state_Get() ) ) {
178                        if ( warn < 8 || ! (warn & 0x1f) )
179                                printk("WARNING: i2c bus driver running in polled mode -- should initialize properly!\n");
180                        warn++;
181                }
182
183                then = _read_TBRL();
184                do {
185                        /* poll for .2 seconds */
186                        if ( (_read_TBRL() - then) > poll_timeout )
187                                return RTEMS_TIMEOUT;
188                } while ( (msk & i2c_rd( I2CSR )) != cond );
189        }
190
191        return RTEMS_SUCCESSFUL;
192}
193
194/*
195 * multi-byte transfer
196 * - set transfer direction (master read or master write)
197 * - transfer byte
198 * - wait/synchronize
199 * - check for ACK
200 *
201 * RETURNS: number of bytes transferred or negative error code.
202 */
203
204STATIC int
205i2c_xfer(int rw, uint8_t *buf, int len)
206{
207int               i;
208rtems_status_code sc;
209
210        if ( rw ) {
211                i2c_clr( I2CCR, I2CCR_MTX );
212        } else {
213                i2c_set( I2CCR, I2CCR_MTX );
214        }
215
216        for ( i = 0; i< len; i++ ) {
217                i2c_clr( I2CSR, I2CSR_MIF );
218                /* Enable interrupts if necessary */
219                if ( ok_to_block() )
220                        i2c_set( I2CCR, I2CCR_MIEN );
221                if ( rw ) {
222                        buf[i] = i2c_rd( I2CDR );
223                } else {
224                        i2c_wr( I2CDR, buf[i] );
225                }
226                if ( RTEMS_SUCCESSFUL != (sc = i2c_wait( I2CSR_MIF, I2CSR_MIF )) )
227                        return -sc;
228                if ( (I2CSR_RXAK & i2c_rd( I2CSR )) ) {
229                        /* NO ACK */
230                        return -RTEMS_IO_ERROR;
231                }
232        }
233
234        return i;
235}
236
237/*
238 * This bus controller gives us lagging data, i.e.,
239 * when we read a byte from the data reg then that
240 * issues a read cycle on the bus and gives us the
241 * byte from the *previous* read cycle :-(
242 *
243 * This makes it impossible to properly terminate
244 * a read transaction w/o knowing ahead of time
245 * how many bytes are going to be read (API decouples
246 * 'START'/'STOP' from 'READ') since we would have to
247 * set TXAK when reading the next-to-last byte
248 * (i.e., when the last byte is read on the i2c bus).
249 *
250 * Hence, (if we are reading) we must do a dummy
251 * read-cycle here -- hopefully
252 * that has no side-effects! (i.e., EEPROM drivers should
253 * reposition file pointers after issuing STOP)
254 *
255 */
256
257static void
258rd1byte_noack(void)
259{
260uint8_t dum;
261uint8_t ccr;
262
263        /* If we are in reading state then read one more
264         * byte w/o acknowledge
265         */
266
267        ccr = i2c_rd (I2CCR );
268
269        if ( ! ( I2CCR_MTX & ccr ) ) {
270                i2c_wr( I2CCR, ccr | I2CCR_TXAK );
271                i2c_xfer(1, &dum, 1);
272                /* restore original TXAK bit setting */
273                i2c_clr( I2CCR, (I2CCR_TXAK & ccr) );
274        }
275}
276
277
278/********* ISR ***********************/
279
280static void i2c_isr(rtems_irq_hdl_param arg)
281{
282        /* disable irq */
283        i2c_clr( I2CCR, I2CCR_MIEN );
284        /* release task */
285        rtems_semaphore_release( syncsem );
286}
287
288/********* IIC Bus Driver Ops ********/
289
290STATIC rtems_status_code
291i2c_init(rtems_libi2c_bus_t *bh)
292{
293rtems_status_code sc;
294
295        /* compute more accurate timeout */
296        if ( BSP_bus_frequency && BSP_time_base_divisor )
297                poll_timeout = BSP_bus_frequency/BSP_time_base_divisor*1000/5;
298
299        i2c_clr( I2CCR, I2CCR_MEN );
300        i2c_set( I2CCR, I2CCR_MEN );
301
302        i2c_wr( I2CADR, 0 );
303
304        /* leave motload settings for divisor and filter registers */
305
306        if ( SYSTEM_STATE_BEFORE_MULTITASKING <= _System_state_Get() && !syncsem ) {
307                sc = rtems_semaphore_create(
308                                rtems_build_name('i','2','c','b'),
309                                0,
310                                RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_LOCAL,
311                                0,
312                                &syncsem);
313                if ( RTEMS_SUCCESSFUL == sc ) {
314                        rtems_irq_connect_data xxx;
315                        xxx.name   = BSP_I2C_IRQ;
316                        xxx.on     = 0;
317                        xxx.off    = 0;
318                        xxx.isOn   = 0;
319                        xxx.hdl    = i2c_isr;
320                        xxx.handle = 0;
321                        if ( ! BSP_install_rtems_irq_handler( &xxx ) ) {
322                                printk("Unable to install i2c ISR -- falling back to polling mode\n");
323                                rtems_semaphore_delete( syncsem );
324                                /* fall back to polling mode */
325                                syncsem = 0;
326                        }
327                } else {
328                        syncsem = 0;
329                }
330        }
331
332        return RTEMS_SUCCESSFUL;
333}
334
335STATIC rtems_status_code
336i2c_start(rtems_libi2c_bus_t *bh)
337{
338uint8_t           v;
339rtems_status_code sc = RTEMS_SUCCESSFUL;
340
341        v = i2c_rd( I2CCR );
342        if ( I2CCR_MSTA & v ) {
343                /* RESTART */
344                rd1byte_noack();
345                v |= I2CCR_RSTA;
346        } else {
347                v |= I2CCR_MSTA;
348        }
349        i2c_wr( I2CCR, v );
350
351        /* On MBB we can only poll-wait (no IRQ is generated)
352         * and this is also much faster than reading a byte
353         * (1/2-bit time) so the overhead of an IRQ may not
354         * be justified.
355         * OTOH, we can put this off into the 'send_addr' routine
356         *
357
358        sc = i2c_wait( I2CSR_MBB, I2CSR_MBB );
359         */
360
361        return sc;
362}
363
364STATIC rtems_status_code
365i2c_stop(rtems_libi2c_bus_t *bh)
366{
367        rd1byte_noack();
368
369        /* STOP */
370        i2c_clr( I2CCR, I2CCR_TXAK | I2CCR_MSTA );
371
372        /* FIXME: should we really spend 1/2 bit-time polling
373         *        or should we just go ahead and hope noone
374         *        else will get a chance to do something to
375         *        the bus until the STOP completes?
376         */
377        return i2c_wait( I2CSR_MBB, 0 );
378}
379
380STATIC rtems_status_code
381i2c_send_addr(rtems_libi2c_bus_t *bh, uint32_t addr, int rw)
382{
383uint8_t           buf[2];
384int               l = 0;
385uint8_t           read_mask = rw ? 1 : 0;
386rtems_status_code sc;
387
388        /* Make sure we are started; (i2c_start() didn't bother to wait
389         * so we do it here - some time already has expired.
390         */
391        sc = i2c_wait( I2CSR_MBB, I2CSR_MBB );
392
393        if ( RTEMS_SUCCESSFUL != sc )
394                return sc;
395
396        if ( addr > 0x7f ) {
397                /* 10-bit request; 1st address byte is 0b11110<b9><b8><r/w> */
398                buf[l] = 0xf0 | ((addr >> 7) & 0x06) | read_mask;
399                read_mask = 0;
400                l++;
401                buf[l] = addr & 0xff;
402        } else {
403                buf[l] = (addr << 1) | read_mask;
404                l++;
405        }
406
407        /*
408         * After sending a an address for reading we must
409         * read a dummy byte (this actually clocks the first real
410         * byte on the i2c bus and makes it available in the
411         * data register so that the first 'read_bytes' operation
412         * obtains the byte we clock in here [and starts clocking
413         * the second byte]) to overcome the pipeline
414         * delay in the hardware (I don't like this design) :-(.
415         */
416        sc = i2c_xfer( 0, buf, l );
417        if ( rw && l == sc ) {
418                sc = i2c_xfer( 1, buf, 1 );
419        }
420        return sc >=0 ? RTEMS_SUCCESSFUL : -sc;
421}
422
423STATIC int
424i2c_read_bytes(rtems_libi2c_bus_t *bh, unsigned char *buf, int len)
425{
426        return i2c_xfer( 1, buf, len );
427}
428
429STATIC int
430i2c_write_bytes(rtems_libi2c_bus_t *bh, unsigned char *buf, int len)
431{
432        return i2c_xfer( 0, buf, len );
433}
434
435/********* Driver Glue Vars **********/
436
437static rtems_libi2c_bus_ops_t  myops = {
438        init:            i2c_init,
439        send_start:      i2c_start,
440        send_stop:       i2c_stop,
441        send_addr:       i2c_send_addr,
442        read_bytes:      i2c_read_bytes,
443        write_bytes:     i2c_write_bytes,
444};
445
446static rtems_libi2c_bus_t my_bus_tbl = {
447        ops:    &myops,
448        size:   sizeof(my_bus_tbl),
449};
450
451/********* Global Driver Handle ******/
452
453rtems_libi2c_bus_t *mpc8540_i2c_bus_descriptor = &my_bus_tbl;
Note: See TracBrowser for help on using the repository browser.