File indexing completed on 2025-05-11 08:24:06
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 #include <bsp.h>
0034 #include <stdlib.h>
0035 #include <stdio.h>
0036 #include <string.h>
0037 #include <grlib/ambapp.h>
0038 #include <rtems/libi2c.h>
0039 #include <drvmgr/drvmgr.h>
0040 #include <grlib/ambapp_bus.h>
0041
0042 #include <grlib/i2cmst.h>
0043
0044 #include <grlib/grlib_impl.h>
0045
0046
0047
0048
0049 #ifdef DEBUG
0050 #define DBG(args...) printk(args)
0051 #else
0052 #define DBG(args...)
0053 #endif
0054
0055
0056
0057
0058
0059 typedef struct gr_i2cmst_prv {
0060 rtems_libi2c_bus_t i2clib_desc;
0061 struct drvmgr_dev *dev;
0062 gr_i2cmst_regs_t *reg_ptr;
0063 unsigned int sysfreq;
0064 int minor;
0065 unsigned char sendstart;
0066
0067
0068 } gr_i2cmst_prv_t;
0069
0070
0071 static int gr_i2cmst_calc_scaler(int sysfreq)
0072 {
0073 return sysfreq/500 - 1;
0074 }
0075
0076
0077 static int gr_i2cmst_wait(gr_i2cmst_prv_t *prv_ptr, uint8_t expected_sts)
0078 {
0079 uint32_t tout = 0;
0080 int current_sts;
0081
0082 DBG("(gr_i2cmst_wait called...");
0083
0084 do {
0085 if (tout++ > 1000000) {
0086 DBG("gr_i2cmst_wait: TIMEOUT\n");
0087 return RTEMS_TIMEOUT;
0088 }
0089 } while (prv_ptr->reg_ptr->cmdsts & GRI2C_STS_TIP);
0090
0091 current_sts = prv_ptr->reg_ptr->cmdsts & ~GRI2C_STS_IF & ~GRI2C_STS_BUSY;
0092
0093 if (current_sts != expected_sts) {
0094 #if defined(DEBUG)
0095 if (prv_ptr->reg_ptr->cmdsts & GRI2C_STS_RXACK) {
0096 DBG("Transfer NAKed..");
0097 }
0098 if (prv_ptr->reg_ptr->cmdsts & GRI2C_STS_AL) {
0099 DBG("arbitration lost..");
0100 }
0101 if (prv_ptr->reg_ptr->cmdsts & GRI2C_STS_TIP) {
0102 DBG("transfer still in progress, huh?..");
0103 }
0104 DBG("exited with IO error..)");
0105 #endif
0106 DBG("gr_i2cmst_wait: IO-ERROR\n");
0107 return RTEMS_IO_ERROR;
0108 }
0109
0110 DBG("exited...)");
0111
0112 return RTEMS_SUCCESSFUL;
0113 }
0114
0115
0116 static rtems_status_code gr_i2cmst_init(rtems_libi2c_bus_t *bushdl)
0117 {
0118 gr_i2cmst_prv_t *prv_ptr = (gr_i2cmst_prv_t *)bushdl;
0119
0120 DBG("gr_i2cmst_init called...");
0121
0122
0123 prv_ptr->reg_ptr->ctrl = 0;
0124
0125
0126 prv_ptr->reg_ptr->prescl = gr_i2cmst_calc_scaler(prv_ptr->sysfreq);
0127
0128
0129 prv_ptr->reg_ptr->ctrl = GRI2C_CTRL_EN;
0130
0131
0132 prv_ptr->sendstart = 0;
0133
0134 DBG("exited\n");
0135
0136 return RTEMS_SUCCESSFUL;
0137 }
0138
0139 static rtems_status_code gr_i2cmst_send_start(rtems_libi2c_bus_t *bushdl)
0140 {
0141 gr_i2cmst_prv_t *prv_ptr = (gr_i2cmst_prv_t *)bushdl;
0142
0143 DBG("gr_i2cmst_send_start called...");
0144
0145
0146
0147 prv_ptr->sendstart = GRI2C_CMD_STA;
0148
0149 DBG("exited\n");
0150
0151 return RTEMS_SUCCESSFUL;
0152 }
0153
0154 static rtems_status_code gr_i2cmst_send_stop(rtems_libi2c_bus_t *bushdl)
0155 {
0156 gr_i2cmst_prv_t *prv_ptr = (gr_i2cmst_prv_t *)bushdl;
0157
0158 DBG("gr_i2cmst_send_stop called...");
0159
0160 prv_ptr->reg_ptr->cmdsts = GRI2C_CMD_STO;
0161
0162 DBG("exited\n");
0163
0164 return RTEMS_SUCCESSFUL;
0165 }
0166
0167 static rtems_status_code gr_i2cmst_send_addr(rtems_libi2c_bus_t *bushdl,
0168 uint32_t addr, int rw)
0169 {
0170 gr_i2cmst_prv_t *prv_ptr = (gr_i2cmst_prv_t *)bushdl;
0171 uint8_t addr_byte;
0172 rtems_status_code rc;
0173
0174 DBG("gr_i2cmst_send_addr called, addr = 0x%x, rw = %d...",
0175 addr, rw);
0176
0177
0178 if (addr > 0x7f) {
0179 addr_byte = ((addr >> 7) & 0x06) | (rw ? 1 : 0);
0180
0181 prv_ptr->reg_ptr->tdrd = addr_byte;
0182 prv_ptr->reg_ptr->cmdsts = GRI2C_CMD_WR | prv_ptr->sendstart;
0183 prv_ptr->sendstart = 0;
0184
0185
0186 rc = gr_i2cmst_wait(prv_ptr, GRI2C_STATUS_IDLE);
0187 if (rc != RTEMS_SUCCESSFUL) {
0188
0189 DBG("exited with error\n");
0190
0191 return -rc;
0192 }
0193 }
0194
0195
0196
0197 rc = RTEMS_SUCCESSFUL;
0198 if (addr <= 0x7f || rw == 0) {
0199 addr_byte = (addr << 1) | (rw ? 1 : 0);
0200
0201 prv_ptr->reg_ptr->tdrd = addr_byte;
0202 prv_ptr->reg_ptr->cmdsts = GRI2C_CMD_WR | prv_ptr->sendstart;
0203 prv_ptr->sendstart = 0;
0204
0205
0206 rc = gr_i2cmst_wait(prv_ptr, GRI2C_STATUS_IDLE);
0207 if (rc != RTEMS_SUCCESSFUL) {
0208 DBG("exited with error\n");
0209 return -rc;
0210 }
0211 }
0212
0213 DBG("exited\n");
0214 return rc;
0215 }
0216
0217
0218 static int gr_i2cmst_read_bytes(rtems_libi2c_bus_t *bushdl,
0219 unsigned char *bytes, int nbytes)
0220 {
0221 gr_i2cmst_prv_t *prv_ptr = (gr_i2cmst_prv_t *)bushdl;
0222 unsigned char *buf = bytes;
0223 rtems_status_code rc;
0224 unsigned char expected_sts = GRI2C_STATUS_IDLE;
0225
0226 DBG("gr_i2cmst_read_bytes called, nbytes = %d...", nbytes);
0227
0228 while (nbytes-- > 0) {
0229 if (nbytes == 0) {
0230
0231 prv_ptr->reg_ptr->cmdsts = (GRI2C_CMD_RD | GRI2C_CMD_ACK |
0232 prv_ptr->sendstart);
0233 expected_sts = GRI2C_STS_RXACK;
0234 } else {
0235 prv_ptr->reg_ptr->cmdsts = GRI2C_CMD_RD | prv_ptr->sendstart;
0236 }
0237 prv_ptr->sendstart = 0;
0238
0239 rc = gr_i2cmst_wait(prv_ptr, expected_sts);
0240 if (rc != RTEMS_SUCCESSFUL) {
0241 DBG("exited with error\n");
0242 return -rc;
0243 }
0244 *buf++ = prv_ptr->reg_ptr->tdrd;
0245 }
0246
0247 DBG("exited\n");
0248
0249 return buf - bytes;
0250 }
0251
0252 static int gr_i2cmst_write_bytes(rtems_libi2c_bus_t *bushdl,
0253 unsigned char *bytes, int nbytes)
0254 {
0255 gr_i2cmst_prv_t *prv_ptr = (gr_i2cmst_prv_t *)bushdl;
0256 unsigned char *buf = bytes;
0257 rtems_status_code rc;
0258
0259 DBG("gr_i2cmst_write_bytes called, nbytes = %d...", nbytes);
0260
0261 while (nbytes-- > 0) {
0262
0263 DBG("writing byte 0x%02X...", *buf);
0264
0265 prv_ptr->reg_ptr->tdrd = *buf++;
0266 prv_ptr->reg_ptr->cmdsts = GRI2C_CMD_WR | prv_ptr->sendstart;
0267 prv_ptr->sendstart = 0;
0268
0269
0270 rc = gr_i2cmst_wait(prv_ptr, GRI2C_STATUS_IDLE);
0271
0272 if (rc != RTEMS_SUCCESSFUL) {
0273 DBG("exited with error\n");
0274 return -rc;
0275 }
0276 }
0277
0278 DBG("exited\n");
0279
0280 return buf - bytes;
0281 }
0282
0283 static rtems_libi2c_bus_ops_t gr_i2cmst_ops = {
0284 init: gr_i2cmst_init,
0285 send_start: gr_i2cmst_send_start,
0286 send_stop: gr_i2cmst_send_stop,
0287 send_addr: gr_i2cmst_send_addr,
0288 read_bytes: gr_i2cmst_read_bytes,
0289 write_bytes: gr_i2cmst_write_bytes,
0290 };
0291
0292
0293 static int i2cmst_device_init(gr_i2cmst_prv_t *priv)
0294 {
0295 struct amba_dev_info *ambadev;
0296 struct ambapp_core *pnpinfo;
0297
0298
0299 ambadev = (struct amba_dev_info *)priv->dev->businfo;
0300 if ( ambadev == NULL ) {
0301 return -1;
0302 }
0303 pnpinfo = &ambadev->info;
0304 priv->reg_ptr = (gr_i2cmst_regs_t *)pnpinfo->apb_slv->start;
0305
0306
0307 priv->reg_ptr->ctrl = 0;
0308
0309 priv->i2clib_desc.ops = &gr_i2cmst_ops;
0310 priv->i2clib_desc.size = sizeof(gr_i2cmst_ops);
0311 return 0;
0312 }
0313
0314
0315
0316
0317 int i2cmst_init2(struct drvmgr_dev *dev);
0318 int i2cmst_init3(struct drvmgr_dev *dev);
0319
0320 struct drvmgr_drv_ops i2cmst_ops =
0321 {
0322 .init = {NULL, i2cmst_init2, i2cmst_init3, NULL},
0323 .remove = NULL,
0324 .info = NULL
0325 };
0326
0327 struct amba_dev_id i2cmst_ids[] =
0328 {
0329 {VENDOR_GAISLER, GAISLER_I2CMST},
0330 {0, 0}
0331 };
0332
0333 struct amba_drv_info i2cmst_drv_info =
0334 {
0335 {
0336 DRVMGR_OBJ_DRV,
0337 NULL,
0338 NULL,
0339 DRIVER_AMBAPP_GAISLER_I2CMST_ID,
0340 "I2CMST_DRV",
0341 DRVMGR_BUS_TYPE_AMBAPP,
0342 &i2cmst_ops,
0343 NULL,
0344 0,
0345 0,
0346 },
0347 &i2cmst_ids[0]
0348 };
0349
0350 void i2cmst_register_drv (void)
0351 {
0352 DBG("Registering I2CMST driver\n");
0353 drvmgr_drv_register(&i2cmst_drv_info.general);
0354 }
0355
0356
0357 int i2cmst_init2(struct drvmgr_dev *dev)
0358 {
0359 gr_i2cmst_prv_t *priv;
0360
0361 DBG("I2CMST[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
0362
0363 priv = dev->priv = grlib_calloc(1, sizeof(*priv));
0364 if ( !priv )
0365 return DRVMGR_NOMEM;
0366 priv->dev = dev;
0367
0368
0369
0370 return DRVMGR_OK;
0371 }
0372
0373
0374 int i2cmst_init3(struct drvmgr_dev *dev)
0375 {
0376 gr_i2cmst_prv_t *priv;
0377 char prefix[32];
0378 char devName[50];
0379 int rc;
0380
0381 priv = (gr_i2cmst_prv_t *)dev->priv;
0382
0383
0384
0385
0386 rc = rtems_libi2c_initialize();
0387 if (rc != 0) {
0388 DBG("I2CMST: rtems_libi2c_initialize failed, exiting...\n");
0389 free(dev->priv);
0390 dev->priv = NULL;
0391 return DRVMGR_FAIL;
0392 }
0393
0394
0395
0396
0397
0398
0399 if ( drvmgr_freq_get(dev, DEV_APB_SLV, &priv->sysfreq) ) {
0400 return DRVMGR_FAIL;
0401 }
0402 priv->sysfreq = priv->sysfreq / 1000;
0403
0404 if ( i2cmst_device_init(priv) ) {
0405 free(dev->priv);
0406 dev->priv = NULL;
0407 return DRVMGR_FAIL;
0408 }
0409
0410
0411 prefix[0] = '\0';
0412 if ( drvmgr_get_dev_prefix(dev, prefix) ) {
0413
0414
0415
0416 sprintf(devName, "/dev/i2c%d", dev->minor_drv+1);
0417 } else {
0418
0419
0420
0421 sprintf(devName, "/dev/%si2c%d", prefix, dev->minor_bus+1);
0422 }
0423
0424
0425 rc = rtems_libi2c_register_bus(devName, &priv->i2clib_desc);
0426 if (rc < 0) {
0427 DBG("I2CMST: rtems_libi2c_register_bus(%s) failed, exiting..\n", devName);
0428 free(dev->priv);
0429 dev->priv = NULL;
0430 return DRVMGR_FAIL;
0431 }
0432 priv->minor = rc;
0433
0434 return DRVMGR_OK;
0435 }