Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:56

0001 /* I2C bus driver for mpc8540-based boards */
0002 
0003 /*
0004  * Authorship
0005  * ----------
0006  * This software ('mvme3100' RTEMS BSP) was created by
0007  *
0008  *     Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
0009  *     Stanford Linear Accelerator Center, Stanford University.
0010  *
0011  * Acknowledgement of sponsorship
0012  * ------------------------------
0013  * The 'mvme3100' BSP was produced by
0014  *     the Stanford Linear Accelerator Center, Stanford University,
0015  *     under Contract DE-AC03-76SFO0515 with the Department of Energy.
0016  *
0017  * Government disclaimer of liability
0018  * ----------------------------------
0019  * Neither the United States nor the United States Department of Energy,
0020  * nor any of their employees, makes any warranty, express or implied, or
0021  * assumes any legal liability or responsibility for the accuracy,
0022  * completeness, or usefulness of any data, apparatus, product, or process
0023  * disclosed, or represents that its use would not infringe privately owned
0024  * rights.
0025  *
0026  * Stanford disclaimer of liability
0027  * --------------------------------
0028  * Stanford University makes no representations or warranties, express or
0029  * implied, nor assumes any liability for the use of this software.
0030  *
0031  * Stanford disclaimer of copyright
0032  * --------------------------------
0033  * Stanford University, owner of the copyright, hereby disclaims its
0034  * copyright and all other rights in this software.  Hence, anyone may
0035  * freely use it for any purpose without restriction.
0036  *
0037  * Maintenance of notices
0038  * ----------------------
0039  * In the interest of clarity regarding the origin and status of this
0040  * SLAC software, this and all the preceding Stanford University notices
0041  * are to remain affixed to any copy or derivative of this software made
0042  * or distributed by the recipient and are to be affixed to any copy of
0043  * software made or distributed by the recipient that contains a copy or
0044  * derivative of this software.
0045  *
0046  * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
0047  */
0048 
0049 /* Note: We maintain base address, IRQ etc. statically and
0050  *       globally. We don't bother creating driver-specific
0051  *       data or using the bus handle but simply assume
0052  *       this is the only 8540/i2c bus in the system.
0053  *       Proper support for multiple instances would not
0054  *       be very hard to add but I don't see the point...
0055  */
0056 
0057 #include <rtems.h>
0058 #include <bsp.h>
0059 #include <rtems/libi2c.h>
0060 #include <bsp/irq.h>
0061 #include <libcpu/spr.h>
0062 #include <libcpu/io.h>
0063 #include <rtems/bspIo.h>
0064 #include <rtems/score/sysstate.h>
0065 
0066 #include <bsp/mpc8540_i2c_busdrv.h>
0067 
0068 #define STATIC static
0069 
0070 /* I2C controller register definitions */
0071 #define I2CADR              0x3000
0072 #define I2CFDR              0x3004
0073 #define I2CCR               0x3008
0074 #define I2CCR_MEN               (1<<(7-0))
0075 #define I2CCR_MIEN              (1<<(7-1))
0076 #define I2CCR_MSTA              (1<<(7-2))
0077 #define I2CCR_MTX               (1<<(7-3))
0078 #define I2CCR_TXAK              (1<<(7-4))
0079 #define I2CCR_RSTA              (1<<(7-5))
0080 #define I2CCR_BCST              (1<<(7-7))
0081 #define I2CSR               0x300c
0082 #define I2CSR_MCF               (1<<(7-0))
0083 #define I2CSR_MAAS              (1<<(7-1))
0084 #define I2CSR_MBB               (1<<(7-2))
0085 #define I2CSR_MAL               (1<<(7-3))
0086 #define I2CSR_BCSTM             (1<<(7-4))
0087 #define I2CSR_SRW               (1<<(7-5))
0088 #define I2CSR_MIF               (1<<(7-6))
0089 #define I2CSR_RXAK              (1<<(7-7))
0090 #define I2CDR               0x3010
0091 #define I2CDFSRR            0x3014
0092 
0093 SPR_RO(TBRL)
0094 
0095 /********* Global Variables **********/
0096 
0097 /*
0098  * Semaphore for synchronizing accessing task
0099  * with the (slow) hardware operation.
0100  * Task takes semaphore and blocks, ISR releases.
0101  */
0102 static rtems_id syncsem = 0;
0103 
0104 static inline int ok_to_block(void)
0105 {
0106     return syncsem && _System_state_Is_up( _System_state_Get() );
0107 }
0108 
0109 /*
0110  * Wild guess for 0.2 s; this timeout is effective
0111  * in polling mode; during early init we don't know
0112  * the system clock rate yet - it's one of the things
0113  * we have to read from VPD -- via i2c.
0114  */
0115 
0116 static uint32_t poll_timeout = 333333333/8/5;
0117 
0118 /********* Primitives ****************/
0119 
0120 static inline uint8_t
0121 i2c_rd(unsigned reg)
0122 {
0123     return in_8( (volatile uint8_t *)(BSP_8540_CCSR_BASE + reg) );
0124 }
0125 
0126 static inline void
0127 i2c_wr(unsigned reg, uint8_t val)
0128 {
0129     out_8( (volatile uint8_t *)(BSP_8540_CCSR_BASE + reg), val );
0130 }
0131 
0132 static inline void
0133 i2c_set(unsigned reg, uint8_t val)
0134 {
0135     i2c_wr( reg, i2c_rd( reg ) | val );
0136 }
0137 
0138 static inline void
0139 i2c_clr(unsigned reg, uint8_t val)
0140 {
0141     i2c_wr( reg, i2c_rd( reg ) & ~val );
0142 }
0143 
0144 /********* Helper Routines ***********/
0145 
0146 /* Synchronize (wait) for a condition on the
0147  * i2c bus. Wait for START or STOP to be complete
0148  * or wait for a byte-transfer.
0149  * The latter is much slower (9 bit times vs. 1/2
0150  * in the former cases).
0151  *
0152  * If the system is up (and we may block) then
0153  * this routine attempts to block the current
0154  * task rather than busy-waiting.
0155  *
0156  * NOTE: waiting for START/STOP always requires
0157  *       polling.
0158  */
0159 
0160 /* wait until i2c status reg AND mask == cond */
0161 static rtems_status_code
0162 i2c_wait( uint8_t msk, uint8_t cond )
0163 {
0164 uint32_t          then;
0165 rtems_status_code sc;
0166 static int        warn = 0;
0167 
0168     if ( I2CSR_MIF == msk && ok_to_block() ) {
0169         /* block on semaphore only if system is up and sema initialized */
0170         sc = rtems_semaphore_obtain( syncsem, RTEMS_WAIT, 100 );
0171         if ( RTEMS_SUCCESSFUL != sc )
0172             return sc;
0173     } else {
0174         /* system not up (no SEMA yet ) or waiting on something other
0175          * than MIF
0176          */
0177         if ( I2CSR_MIF == msk && _System_state_Is_up( _System_state_Get() ) ) {
0178             if ( warn < 8 || ! (warn & 0x1f) )
0179                 printk("WARNING: i2c bus driver running in polled mode -- should initialize properly!\n");
0180             warn++;
0181         }
0182 
0183         then = _read_TBRL();
0184         do {
0185             /* poll for .2 seconds */
0186             if ( (_read_TBRL() - then) > poll_timeout )
0187                 return RTEMS_TIMEOUT;
0188         } while ( (msk & i2c_rd( I2CSR )) != cond );
0189     }
0190 
0191     return RTEMS_SUCCESSFUL;
0192 }
0193 
0194 /*
0195  * multi-byte transfer
0196  * - set transfer direction (master read or master write)
0197  * - transfer byte
0198  * - wait/synchronize
0199  * - check for ACK
0200  *
0201  * RETURNS: number of bytes transferred or negative error code.
0202  */
0203 
0204 STATIC int
0205 i2c_xfer(int rw, uint8_t *buf, int len)
0206 {
0207 int               i;
0208 rtems_status_code sc;
0209 
0210     if ( rw ) {
0211         i2c_clr( I2CCR, I2CCR_MTX );
0212     } else {
0213         i2c_set( I2CCR, I2CCR_MTX );
0214     }
0215 
0216     for ( i = 0; i< len; i++ ) {
0217         i2c_clr( I2CSR, I2CSR_MIF );
0218         /* Enable interrupts if necessary */
0219         if ( ok_to_block() )
0220             i2c_set( I2CCR, I2CCR_MIEN );
0221         if ( rw ) {
0222             buf[i] = i2c_rd( I2CDR );
0223         } else {
0224             i2c_wr( I2CDR, buf[i] );
0225         }
0226         if ( RTEMS_SUCCESSFUL != (sc = i2c_wait( I2CSR_MIF, I2CSR_MIF )) )
0227             return -sc;
0228         if ( (I2CSR_RXAK & i2c_rd( I2CSR )) ) {
0229             /* NO ACK */
0230             return -RTEMS_IO_ERROR;
0231         }
0232     }
0233 
0234     return i;
0235 }
0236 
0237 /*
0238  * This bus controller gives us lagging data, i.e.,
0239  * when we read a byte from the data reg then that
0240  * issues a read cycle on the bus and gives us the
0241  * byte from the *previous* read cycle :-(
0242  *
0243  * This makes it impossible to properly terminate
0244  * a read transaction w/o knowing ahead of time
0245  * how many bytes are going to be read (API decouples
0246  * 'START'/'STOP' from 'READ') since we would have to
0247  * set TXAK when reading the next-to-last byte
0248  * (i.e., when the last byte is read on the i2c bus).
0249  *
0250  * Hence, (if we are reading) we must do a dummy
0251  * read-cycle here -- hopefully
0252  * that has no side-effects! (i.e., EEPROM drivers should
0253  * reposition file pointers after issuing STOP)
0254  *
0255  */
0256 
0257 static void
0258 rd1byte_noack(void)
0259 {
0260 uint8_t dum;
0261 uint8_t ccr;
0262 
0263     /* If we are in reading state then read one more
0264      * byte w/o acknowledge
0265      */
0266 
0267     ccr = i2c_rd (I2CCR );
0268 
0269     if ( ! ( I2CCR_MTX & ccr ) ) {
0270         i2c_wr( I2CCR, ccr | I2CCR_TXAK );
0271         i2c_xfer(1, &dum, 1);
0272         /* restore original TXAK bit setting */
0273         i2c_clr( I2CCR, (I2CCR_TXAK & ccr) );
0274     }
0275 }
0276 
0277 
0278 /********* ISR ***********************/
0279 
0280 static void i2c_isr(rtems_irq_hdl_param arg)
0281 {
0282     /* disable irq */
0283     i2c_clr( I2CCR, I2CCR_MIEN );
0284     /* release task */
0285     rtems_semaphore_release( syncsem );
0286 }
0287 
0288 /********* IIC Bus Driver Ops ********/
0289 
0290 STATIC rtems_status_code
0291 i2c_init(rtems_libi2c_bus_t *bh)
0292 {
0293 rtems_status_code sc;
0294 
0295     /* compute more accurate timeout */
0296     if ( BSP_bus_frequency && BSP_time_base_divisor )
0297         poll_timeout = BSP_bus_frequency/BSP_time_base_divisor*1000/5;
0298 
0299     i2c_clr( I2CCR, I2CCR_MEN );
0300     i2c_set( I2CCR, I2CCR_MEN );
0301 
0302     i2c_wr( I2CADR, 0 );
0303 
0304     /* leave motload settings for divisor and filter registers */
0305 
0306     if ( SYSTEM_STATE_BEFORE_MULTITASKING <= _System_state_Get() && !syncsem ) {
0307         sc = rtems_semaphore_create(
0308                 rtems_build_name('i','2','c','b'),
0309                 0,
0310                 RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_LOCAL,
0311                 0,
0312                 &syncsem);
0313         if ( RTEMS_SUCCESSFUL == sc ) {
0314             rtems_irq_connect_data xxx;
0315             xxx.name   = BSP_I2C_IRQ;
0316             xxx.on     = 0;
0317             xxx.off    = 0;
0318             xxx.isOn   = 0;
0319             xxx.hdl    = i2c_isr;
0320             xxx.handle = 0;
0321             if ( ! BSP_install_rtems_irq_handler( &xxx ) ) {
0322                 printk("Unable to install i2c ISR -- falling back to polling mode\n");
0323                 rtems_semaphore_delete( syncsem );
0324                 /* fall back to polling mode */
0325                 syncsem = 0;
0326             }
0327         } else {
0328             syncsem = 0;
0329         }
0330     }
0331 
0332     return RTEMS_SUCCESSFUL;
0333 }
0334 
0335 STATIC rtems_status_code
0336 i2c_start(rtems_libi2c_bus_t *bh)
0337 {
0338 uint8_t           v;
0339 rtems_status_code sc = RTEMS_SUCCESSFUL;
0340 
0341     v = i2c_rd( I2CCR );
0342     if ( I2CCR_MSTA & v ) {
0343         /* RESTART */
0344         rd1byte_noack();
0345         v |= I2CCR_RSTA;
0346     } else {
0347         v |= I2CCR_MSTA;
0348     }
0349     i2c_wr( I2CCR, v );
0350 
0351     /* On MBB we can only poll-wait (no IRQ is generated)
0352      * and this is also much faster than reading a byte
0353      * (1/2-bit time) so the overhead of an IRQ may not
0354      * be justified.
0355      * OTOH, we can put this off into the 'send_addr' routine
0356      *
0357 
0358     sc = i2c_wait( I2CSR_MBB, I2CSR_MBB );
0359      */
0360 
0361     return sc;
0362 }
0363 
0364 STATIC rtems_status_code
0365 i2c_stop(rtems_libi2c_bus_t *bh)
0366 {
0367     rd1byte_noack();
0368 
0369     /* STOP */
0370     i2c_clr( I2CCR, I2CCR_TXAK | I2CCR_MSTA );
0371 
0372     /* FIXME: should we really spend 1/2 bit-time polling
0373      *        or should we just go ahead and hope noone
0374      *        else will get a chance to do something to
0375      *        the bus until the STOP completes?
0376      */
0377     return i2c_wait( I2CSR_MBB, 0 );
0378 }
0379 
0380 STATIC rtems_status_code
0381 i2c_send_addr(rtems_libi2c_bus_t *bh, uint32_t addr, int rw)
0382 {
0383 uint8_t           buf[2];
0384 int               l = 0;
0385 uint8_t           read_mask = rw ? 1 : 0;
0386 rtems_status_code sc;
0387 
0388     /* Make sure we are started; (i2c_start() didn't bother to wait
0389      * so we do it here - some time already has expired.
0390      */
0391     sc = i2c_wait( I2CSR_MBB, I2CSR_MBB );
0392 
0393     if ( RTEMS_SUCCESSFUL != sc )
0394         return sc;
0395 
0396     if ( addr > 0x7f ) {
0397         /* 10-bit request; 1st address byte is 0b11110<b9><b8><r/w> */
0398         buf[l] = 0xf0 | ((addr >> 7) & 0x06) | read_mask;
0399         read_mask = 0;
0400         l++;
0401         buf[l] = addr & 0xff;
0402     } else {
0403         buf[l] = (addr << 1) | read_mask;
0404         l++;
0405     }
0406 
0407     /*
0408      * After sending a an address for reading we must
0409      * read a dummy byte (this actually clocks the first real
0410      * byte on the i2c bus and makes it available in the
0411      * data register so that the first 'read_bytes' operation
0412      * obtains the byte we clock in here [and starts clocking
0413      * the second byte]) to overcome the pipeline
0414      * delay in the hardware (I don't like this design) :-(.
0415      */
0416     sc = i2c_xfer( 0, buf, l );
0417     if ( rw && l == sc ) {
0418         sc = i2c_xfer( 1, buf, 1 );
0419     }
0420     return sc >=0 ? RTEMS_SUCCESSFUL : -sc;
0421 }
0422 
0423 STATIC int
0424 i2c_read_bytes(rtems_libi2c_bus_t *bh, unsigned char *buf, int len)
0425 {
0426     return i2c_xfer( 1, buf, len );
0427 }
0428 
0429 STATIC int
0430 i2c_write_bytes(rtems_libi2c_bus_t *bh, unsigned char *buf, int len)
0431 {
0432     return i2c_xfer( 0, buf, len );
0433 }
0434 
0435 /********* Driver Glue Vars **********/
0436 
0437 static rtems_libi2c_bus_ops_t  myops = {
0438     init:            i2c_init,
0439     send_start:      i2c_start,
0440     send_stop:       i2c_stop,
0441     send_addr:       i2c_send_addr,
0442     read_bytes:      i2c_read_bytes,
0443     write_bytes:     i2c_write_bytes,
0444 };
0445 
0446 static rtems_libi2c_bus_t my_bus_tbl = {
0447     ops:    &myops,
0448     size:   sizeof(my_bus_tbl),
0449 };
0450 
0451 /********* Global Driver Handle ******/
0452 
0453 rtems_libi2c_bus_t *mpc8540_i2c_bus_descriptor = &my_bus_tbl;