File indexing completed on 2025-05-11 08:23:52
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 #include <stdio.h>
0037 #include <rtems.h>
0038 #include <libcpu/io.h>
0039 #include <sys/errno.h>
0040 #include <rtems/bspIo.h>
0041 #include <rtems/score/sysstate.h>
0042 #include <bsp/irq.h>
0043 #include <rtems/libi2c.h>
0044
0045 #include <sys/cdefs.h>
0046
0047 #include <bsp/gtintrreg.h>
0048 #include <bsp/gti2creg.h>
0049 #include <bsp/gti2c_busdrv.h>
0050
0051 #define ENABLE_IRQ_AT_PIC_HACK
0052 #undef DEBUG
0053
0054 #ifndef BSP_IRQ_MIN_PRIO
0055 #define BSP_IRQ_MIN_PRIO 1
0056 #endif
0057
0058 struct gti2c_softc {
0059 uint32_t sc_gt;
0060 uint32_t sc_cntl;
0061 int sc_inited;
0062 rtems_id sc_sync;
0063 int sc_irqs;
0064 };
0065
0066 #ifdef DEBUG
0067 #define STATIC
0068 #else
0069 #define STATIC static
0070 #endif
0071
0072 typedef struct {
0073 rtems_libi2c_bus_t bus_desc;
0074 struct gti2c_softc pvt;
0075 } gti2c_desc_rec, *gti2c_desc;
0076
0077 STATIC rtems_status_code
0078 gt_i2c_init(rtems_libi2c_bus_t *bh);
0079 STATIC rtems_status_code
0080 gt_i2c_send_start(rtems_libi2c_bus_t *bh);
0081 STATIC rtems_status_code
0082 gt_i2c_send_stop(rtems_libi2c_bus_t *bh);
0083 STATIC rtems_status_code
0084 gt_i2c_send_addr(rtems_libi2c_bus_t *bh, uint32_t addr, int rw);
0085 STATIC int
0086 gt_i2c_read_bytes(rtems_libi2c_bus_t *bh, unsigned char *buf, int len);
0087 STATIC int
0088 gt_i2c_write_bytes(rtems_libi2c_bus_t *bh, unsigned char *buf, int len);
0089
0090 static rtems_libi2c_bus_ops_t myops = {
0091 init: gt_i2c_init,
0092 send_start: gt_i2c_send_start,
0093 send_stop: gt_i2c_send_stop,
0094 send_addr: gt_i2c_send_addr,
0095 read_bytes: gt_i2c_read_bytes,
0096 write_bytes: gt_i2c_write_bytes,
0097 };
0098
0099 static gti2c_desc_rec my_bus_tbl = {
0100 {
0101 ops: &myops,
0102 size: sizeof(my_bus_tbl),
0103 },
0104 {
0105 sc_gt: BSP_MV64x60_BASE,
0106 sc_cntl: I2C_Control_TWSIEn,
0107 sc_inited: 0,
0108 sc_sync: 0
0109 }
0110 };
0111
0112
0113 static inline uint32_t
0114 gt_read(uint32_t base, uint32_t off)
0115 {
0116 return in_le32((volatile uint32_t*)(base+off));
0117 }
0118
0119 static inline void
0120 gt_write(uint32_t base, uint32_t off, uint32_t val)
0121 {
0122 out_le32((volatile uint32_t*)(base+off), val);
0123 }
0124
0125
0126 static inline void
0127 disable_irq(struct gti2c_softc *sc)
0128 {
0129 uint32_t v = gt_read(sc->sc_gt, I2C_REG_Control);
0130 gt_write(sc->sc_gt, I2C_REG_Control, v & ~I2C_Control_IntEn);
0131 }
0132
0133
0134 static rtems_status_code
0135 gt_i2c_wait(struct gti2c_softc *sc, uint32_t control, uint32_t desired_status)
0136 {
0137 uint32_t status;
0138 rtems_status_code rval;
0139
0140 control |= I2C_Control_IntEn;
0141
0142 gt_write(sc->sc_gt, I2C_REG_Control, control | sc->sc_cntl);
0143
0144 if ( sc->sc_inited ) {
0145
0146 #ifdef ENABLE_IRQ_AT_PIC_HACK
0147 BSP_enable_irq_at_pic(BSP_IRQ_I2C);
0148 #endif
0149
0150 rval = rtems_semaphore_obtain(sc->sc_sync, RTEMS_WAIT, 100);
0151
0152 if ( RTEMS_SUCCESSFUL != rval )
0153 return rval;
0154 } else {
0155 uint32_t then, now;
0156
0157
0158 if ( _System_state_Is_up(_System_state_Get()) ) {
0159 printk("WARNING: gti2c running in polled mode -- should initialize properly!\n");
0160 }
0161
0162 asm volatile("mftb %0":"=r"(then));
0163
0164 do {
0165 asm volatile("mftb %0":"=r"(now));
0166
0167 if ( now - then > (uint32_t)100000000/4/5 )
0168 return RTEMS_TIMEOUT;
0169 } while ( ! (I2C_Control_IFlg & gt_read(sc->sc_gt, I2C_REG_Control)) );
0170 }
0171
0172 status = gt_read(sc->sc_gt, I2C_REG_Status);
0173
0174 if ( status != desired_status && (status!=I2C_Status_ReStarted || desired_status!=I2C_Status_Started) )
0175 return RTEMS_IO_ERROR;
0176
0177 return RTEMS_SUCCESSFUL;
0178 }
0179
0180 static void
0181 gt_i2c_intr(void *arg)
0182 {
0183 struct gti2c_softc * const sc = &my_bus_tbl.pvt;
0184 uint32_t v;
0185
0186 v = gt_read(sc->sc_gt, I2C_REG_Control);
0187 if ((v & I2C_Control_IFlg) == 0) {
0188 printk("gt_i2c_intr: IRQ but IFlg not set??\n");
0189 return;
0190 }
0191 gt_write(sc->sc_gt, I2C_REG_Control, v & ~(I2C_Control_IntEn));
0192 #if 0
0193 gt_read(sc->sc_gt, I2C_REG_Control);
0194 asm volatile("sync");
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207 {unsigned from,to;
0208 asm volatile("mftb %0":"=r"(from));
0209 while ( in_le32((volatile uint32_t*)0xf100000c) & 0x20 )
0210 ;
0211 asm volatile("mftb %0":"=r"(to));
0212 printk("I2C IRQ remained asserted for %i TB ticks!\n",to-from);
0213 }
0214 #endif
0215 #ifdef ENABLE_IRQ_AT_PIC_HACK
0216 BSP_disable_irq_at_pic(BSP_IRQ_I2C);
0217 #endif
0218
0219 sc->sc_irqs++;
0220
0221 rtems_semaphore_release(sc->sc_sync);
0222 }
0223
0224 STATIC rtems_status_code
0225 gt_i2c_init(rtems_libi2c_bus_t *bh)
0226 {
0227 struct gti2c_softc * const sc = &((gti2c_desc)bh)->pvt;
0228 unsigned m,n,N;
0229
0230 disable_irq(sc);
0231
0232
0233 gt_write(sc->sc_gt, I2C_REG_SoftReset, 0);
0234 gt_write(sc->sc_gt, I2C_REG_SlaveAddr, 0);
0235 gt_write(sc->sc_gt, I2C_REG_ExtSlaveAddr, 0);
0236
0237
0238
0239
0240
0241 n = 0, N=1<<n;
0242 do {
0243 n++, N<<=1;
0244
0245 m = BSP_bus_frequency / 10 / 62500 / N;
0246 } while ( m > 16 );
0247
0248
0249 if ( n > 8 ) {
0250 n = 8; m = 16;
0251 }
0252 if ( 0 == m )
0253 m = 1;
0254
0255 gt_write(sc->sc_gt, I2C_REG_BaudRate, I2C_BaudRate(m-1, n-1));
0256
0257 if ( !sc->sc_inited ) {
0258
0259 if ( _System_state_Is_up(_System_state_Get()) ) {
0260 rtems_irq_connect_data ii = {
0261 name: BSP_IRQ_I2C,
0262 hdl: gt_i2c_intr,
0263 on: 0,
0264 off: 0,
0265 isOn: 0
0266 };
0267 rtems_status_code err;
0268
0269 err = rtems_semaphore_create(
0270 rtems_build_name('g','i','2','c'),
0271 0,
0272 RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_LOCAL,
0273 0,
0274 &sc->sc_sync);
0275 if ( err ) {
0276 sc->sc_sync = 0;
0277 return err;
0278 }
0279 if ( !BSP_install_rtems_irq_handler(&ii) ) {
0280 fprintf(stderr,"Unable to install interrupt handler\n");
0281 rtems_semaphore_delete(sc->sc_sync);
0282 return RTEMS_INTERNAL_ERROR;
0283 }
0284 BSP_irq_set_priority(BSP_IRQ_I2C, BSP_IRQ_MIN_PRIO);
0285 sc->sc_inited = 1;
0286 } else {
0287 }
0288 } else {
0289 rtems_semaphore_flush(sc->sc_sync);
0290 }
0291 return RTEMS_SUCCESSFUL;
0292 }
0293
0294 STATIC rtems_status_code
0295 gt_i2c_send_start(rtems_libi2c_bus_t *bh)
0296 {
0297 struct gti2c_softc * const sc = &((gti2c_desc)bh)->pvt;
0298
0299 return gt_i2c_wait(sc, I2C_Control_Start, I2C_Status_Started);
0300 }
0301
0302 STATIC rtems_status_code
0303 gt_i2c_send_stop(rtems_libi2c_bus_t *bh)
0304 {
0305 struct gti2c_softc * const sc = &((gti2c_desc)bh)->pvt;
0306 uint32_t data;
0307
0308 data = gt_read(sc->sc_gt, I2C_REG_Status);
0309 if ( I2C_Status_Started == data || I2C_Status_ReStarted == data ) {
0310
0311
0312
0313
0314
0315 gt_i2c_send_addr(bh, 8, 1);
0316 data = gt_read(sc->sc_gt, I2C_REG_Status);
0317 }
0318
0319 if ( I2C_Status_AddrReadAck == data ) {
0320
0321
0322
0323
0324
0325 gt_i2c_read_bytes(bh, (unsigned char *)&data, 1);
0326 }
0327
0328 gt_write(sc->sc_gt, I2C_REG_Control, I2C_Control_Stop | sc->sc_cntl);
0329
0330
0331 return RTEMS_SUCCESSFUL;
0332 }
0333
0334 STATIC rtems_status_code
0335 gt_i2c_send_addr(rtems_libi2c_bus_t *bh, uint32_t addr, int rw)
0336 {
0337 struct gti2c_softc * const sc = &((gti2c_desc)bh)->pvt;
0338 uint32_t data, wanted_status;
0339 uint8_t read_mask = rw ? 1 : 0;
0340 rtems_status_code error;
0341
0342 if (read_mask) {
0343 wanted_status = I2C_Status_AddrReadAck;
0344 } else {
0345 wanted_status = I2C_Status_AddrWriteAck;
0346 }
0347
0348
0349
0350 data = read_mask;
0351 if (addr > 0x7f) {
0352
0353
0354
0355
0356 data |= 0xf0 | ((addr & 0x300) >> 7);
0357 gt_write(sc->sc_gt, I2C_REG_Data, data);
0358 error = gt_i2c_wait(sc, 0, wanted_status);
0359 if (error)
0360 return error;
0361
0362
0363
0364
0365 if (read_mask) {
0366 wanted_status = I2C_Status_2ndAddrReadAck;
0367 } else {
0368 wanted_status = I2C_Status_2ndAddrWriteAck;
0369 }
0370 data = (uint8_t) addr;
0371 } else {
0372 data |= (addr << 1);
0373 }
0374
0375 gt_write(sc->sc_gt, I2C_REG_Data, data);
0376 return gt_i2c_wait(sc, 0, wanted_status);
0377 }
0378
0379 STATIC int
0380 gt_i2c_read_bytes(rtems_libi2c_bus_t *bh, unsigned char *buf, int len)
0381 {
0382 struct gti2c_softc * const sc = &((gti2c_desc)bh)->pvt;
0383 rtems_status_code error;
0384 register unsigned char *p=buf;
0385
0386 while ( len-- > 0 ) {
0387 error = gt_i2c_wait(
0388 sc,
0389 len ? I2C_Control_ACK : 0,
0390 len ? I2C_Status_MasterReadAck : I2C_Status_MasterReadNoAck);
0391 if ( error ) {
0392 return -error;
0393 }
0394 *p++ = gt_read(sc->sc_gt, I2C_REG_Data);
0395 }
0396
0397 return p-buf;
0398 }
0399
0400 STATIC int
0401 gt_i2c_write_bytes(rtems_libi2c_bus_t *bh, unsigned char *buf, int len)
0402 {
0403 struct gti2c_softc * const sc = &((gti2c_desc)bh)->pvt;
0404 int rval = 0;
0405 rtems_status_code error;
0406
0407 while ( len-- > 0 ) {
0408 gt_write(sc->sc_gt, I2C_REG_Data, buf[rval]);
0409 error = gt_i2c_wait(sc, 0, I2C_Status_MasterWriteAck);
0410 if ( error ) {
0411 return -error;
0412 }
0413 rval++;
0414 }
0415
0416 return rval;
0417 }
0418
0419 rtems_libi2c_bus_t *gt64260_i2c_bus_descriptor = &my_bus_tbl.bus_desc;
0420
0421 #ifdef DEBUG_MODULAR
0422
0423 void
0424 _cexpModuleInitialize(void *arg)
0425 {
0426 gt_i2c_init(>64260_i2c_bus_descriptor->bus_desc);
0427 }
0428
0429 int
0430 _cexpModuleFinalize(void * arg)
0431 {
0432 struct gti2c_softc * const sc = >64260_i2c_bus_descriptor->pvt;
0433
0434 rtems_irq_connect_data ii = {
0435 name: BSP_IRQ_I2C,
0436 hdl: gt_i2c_intr,
0437 on: noop,
0438 off: noop,
0439 isOn: inoop
0440 };
0441
0442 rtems_semaphore_delete(sc->sc_sync);
0443
0444 return !BSP_remove_rtems_irq_handler(&ii);
0445 }
0446
0447 #endif