File indexing completed on 2025-05-11 08:23:56
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
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
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
0096
0097
0098
0099
0100
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
0111
0112
0113
0114
0115
0116 static uint32_t poll_timeout = 333333333/8/5;
0117
0118
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
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
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
0170 sc = rtems_semaphore_obtain( syncsem, RTEMS_WAIT, 100 );
0171 if ( RTEMS_SUCCESSFUL != sc )
0172 return sc;
0173 } else {
0174
0175
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
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
0196
0197
0198
0199
0200
0201
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
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
0230 return -RTEMS_IO_ERROR;
0231 }
0232 }
0233
0234 return i;
0235 }
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257 static void
0258 rd1byte_noack(void)
0259 {
0260 uint8_t dum;
0261 uint8_t ccr;
0262
0263
0264
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
0273 i2c_clr( I2CCR, (I2CCR_TXAK & ccr) );
0274 }
0275 }
0276
0277
0278
0279
0280 static void i2c_isr(rtems_irq_hdl_param arg)
0281 {
0282
0283 i2c_clr( I2CCR, I2CCR_MIEN );
0284
0285 rtems_semaphore_release( syncsem );
0286 }
0287
0288
0289
0290 STATIC rtems_status_code
0291 i2c_init(rtems_libi2c_bus_t *bh)
0292 {
0293 rtems_status_code sc;
0294
0295
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
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
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
0344 rd1byte_noack();
0345 v |= I2CCR_RSTA;
0346 } else {
0347 v |= I2CCR_MSTA;
0348 }
0349 i2c_wr( I2CCR, v );
0350
0351
0352
0353
0354
0355
0356
0357
0358
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
0370 i2c_clr( I2CCR, I2CCR_TXAK | I2CCR_MSTA );
0371
0372
0373
0374
0375
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
0389
0390
0391 sc = i2c_wait( I2CSR_MBB, I2CSR_MBB );
0392
0393 if ( RTEMS_SUCCESSFUL != sc )
0394 return sc;
0395
0396 if ( addr > 0x7f ) {
0397
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
0409
0410
0411
0412
0413
0414
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
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
0452
0453 rtems_libi2c_bus_t *mpc8540_i2c_bus_descriptor = &my_bus_tbl;