File indexing completed on 2025-05-11 08:24:07
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 #include <bsp.h>
0032 #include <rtems/libio.h>
0033 #include <stdlib.h>
0034 #include <assert.h>
0035 #include <rtems/bspIo.h>
0036 #include <string.h>
0037 #include <stdio.h>
0038
0039 #include <drvmgr/drvmgr.h>
0040 #include <grlib/ambapp_bus.h>
0041 #include <grlib/spictrl.h>
0042 #include <grlib/ambapp.h>
0043
0044 #include <rtems/libi2c.h>
0045
0046 #include <grlib/grlib_impl.h>
0047
0048
0049
0050 #ifdef DEBUG
0051 #define DBG(x...) printk(x)
0052 #define STATIC
0053 #else
0054 #define DBG(x...)
0055 #define STATIC static
0056 #endif
0057
0058
0059 #define SPICTRL_CAP_SSSZ_BIT 24
0060 #define SPICTRL_CAP_AMODE_BIT 18
0061 #define SPICTRL_CAP_ASELA_BIT 17
0062 #define SPICTRL_CAP_SSEN_BIT 16
0063 #define SPICTRL_CAP_FDEPTH_BIT 8
0064 #define SPICTRL_CAP_REV_BIT 0
0065
0066 #define SPICTRL_CAP_SSSZ (0xff << SPICTRL_CAP_SSSZ_BIT)
0067 #define SPICTRL_CAP_AMODE (1<<SPICTRL_CAP_AMODE_BIT)
0068 #define SPICTRL_CAP_ASELA (1<<SPICTRL_CAP_ASELA_BIT)
0069 #define SPICTRL_CAP_SSEN (1 << SPICTRL_CAP_SSEN_BIT)
0070 #define SPICTRL_CAP_FDEPTH (0xff << SPICTRL_CAP_FDEPTH_BIT)
0071 #define SPICTRL_CAP_REV (0xff << SPICTRL_CAP_REV_BIT)
0072
0073
0074 #define SPICTRL_MODE_AMEN_BIT 31
0075 #define SPICTRL_MODE_LOOP_BIT 30
0076 #define SPICTRL_MODE_CPOL_BIT 29
0077 #define SPICTRL_MODE_CPHA_BIT 28
0078 #define SPICTRL_MODE_DIV16_BIT 27
0079 #define SPICTRL_MODE_REV_BIT 26
0080 #define SPICTRL_MODE_MS_BIT 25
0081 #define SPICTRL_MODE_EN_BIT 24
0082 #define SPICTRL_MODE_LEN_BIT 20
0083 #define SPICTRL_MODE_PM_BIT 16
0084 #define SPICTRL_MODE_ASEL_BIT 14
0085 #define SPICTRL_MODE_FACT_BIT 13
0086 #define SPICTRL_MODE_CG_BIT 7
0087 #define SPICTRL_MODE_TAC_BIT 4
0088
0089 #define SPICTRL_MODE_AMEN (1 << SPICTRL_MODE_AMEN_BIT)
0090 #define SPICTRL_MODE_LOOP (1 << SPICTRL_MODE_LOOP_BIT)
0091 #define SPICTRL_MODE_CPOL (1 << SPICTRL_MODE_CPOL_BIT)
0092 #define SPICTRL_MODE_CPHA (1 << SPICTRL_MODE_CPHA_BIT)
0093 #define SPICTRL_MODE_DIV16 (1 << SPICTRL_MODE_DIV16_BIT)
0094 #define SPICTRL_MODE_REV (1 << SPICTRL_MODE_REV_BIT)
0095 #define SPICTRL_MODE_MS (1 << SPICTRL_MODE_MS_BIT)
0096 #define SPICTRL_MODE_EN (1 << SPICTRL_MODE_EN_BIT)
0097 #define SPICTRL_MODE_LEN (0xf << SPICTRL_MODE_LEN_BIT)
0098 #define SPICTRL_MODE_PM (0xf << SPICTRL_MODE_PM_BIT)
0099 #define SPICTRL_MODE_ASEL (1 << SPICTRL_MODE_ASEL_BIT)
0100 #define SPICTRL_MODE_FACT (1 << SPICTRL_MODE_FACT_BIT)
0101 #define SPICTRL_MODE_CG (0x1f << SPICTRL_MODE_CG_BIT)
0102 #define SPICTRL_MODE_TAC (0x1 << SPICTRL_MODE_TAC_BIT)
0103
0104
0105 #define SPICTRL_EVENT_AT_BIT 15
0106 #define SPICTRL_EVENT_LT_BIT 14
0107 #define SPICTRL_EVENT_OV_BIT 12
0108 #define SPICTRL_EVENT_UN_BIT 11
0109 #define SPICTRL_EVENT_MME_BIT 10
0110 #define SPICTRL_EVENT_NE_BIT 9
0111 #define SPICTRL_EVENT_NF_BIT 8
0112
0113 #define SPICTRL_EVENT_AT (1 << SPICTRL_EVENT_AT_BIT)
0114 #define SPICTRL_EVENT_LT (1 << SPICTRL_EVENT_LT_BIT)
0115 #define SPICTRL_EVENT_OV (1 << SPICTRL_EVENT_OV_BIT)
0116 #define SPICTRL_EVENT_UN (1 << SPICTRL_EVENT_UN_BIT)
0117 #define SPICTRL_EVENT_MME (1 << SPICTRL_EVENT_MME_BIT)
0118 #define SPICTRL_EVENT_NE (1 << SPICTRL_EVENT_NE_BIT)
0119 #define SPICTRL_EVENT_NF (1 << SPICTRL_EVENT_NF_BIT)
0120
0121
0122 #define SPICTRL_MASK_ATE_BIT 15
0123 #define SPICTRL_MASK_LTE_BIT 14
0124 #define SPICTRL_MASK_OVE_BIT 12
0125 #define SPICTRL_MASK_UNE_BIT 11
0126 #define SPICTRL_MASK_MMEE_BIT 10
0127 #define SPICTRL_MASK_NEE_BIT 9
0128 #define SPICTRL_MASK_NFE_BIT 8
0129
0130 #define SPICTRL_MASK_ATE (1 << SPICTRL_MASK_ATE_BIT)
0131 #define SPICTRL_MASK_LTE (1 << SPICTRL_MASK_LTE_BIT)
0132 #define SPICTRL_MASK_OVE (1 << SPICTRL_MASK_OVE_BIT)
0133 #define SPICTRL_MASK_UNE (1 << SPICTRL_MASK_UNE_BIT)
0134 #define SPICTRL_MASK_MMEE (1 << SPICTRL_MASK_MMEE_BIT)
0135 #define SPICTRL_MASK_NEE (1 << SPICTRL_MASK_NEE_BIT)
0136 #define SPICTRL_MASK_NFE (1 << SPICTRL_MASK_NFE_BIT)
0137
0138
0139 #define SPICTRL_CMD_LST_BIT 22
0140 #define SPICTRL_CMD_LST (1 << SPICTRL_CMD_LST_BIT)
0141
0142
0143 #define SPICTRL_TX_TDATA_BIT 0
0144 #define SPICTRL_TX_TDATA 0xffffffff
0145
0146
0147 #define SPICTRL_RX_RDATA_BIT 0
0148 #define SPICTRL_RX_RDATA 0xffffffff
0149
0150
0151
0152
0153 #define SPICTRL_AMCFG_ERPT_BIT 6
0154 #define SPICTRL_AMCFG_SEQ_BIT 5
0155 #define SPICTRL_AMCFG_STRICT_BIT 4
0156 #define SPICTRL_AMCFG_OVTB_BIT 3
0157 #define SPICTRL_AMCFG_OVDB_BIT 2
0158 #define SPICTRL_AMCFG_ACT_BIT 1
0159 #define SPICTRL_AMCFG_EACT_BIT 0
0160
0161 #define SPICTRL_AMCFG_ERPT (1<<SPICTRL_AMCFG_ERPT_BIT)
0162 #define SPICTRL_AMCFG_SEQ (1<<SPICTRL_AMCFG_SEQ_BIT)
0163 #define SPICTRL_AMCFG_STRICT (1<<SPICTRL_AMCFG_STRICT_BIT)
0164 #define SPICTRL_AMCFG_OVTB (1<<SPICTRL_AMCFG_OVTB_BIT)
0165 #define SPICTRL_AMCFG_OVDB (1<<SPICTRL_AMCFG_OVDB_BIT)
0166 #define SPICTRL_AMCFG_ACT (1<<SPICTRL_AMCFG_ACT_BIT)
0167 #define SPICTRL_AMCFG_EACT (1<<SPICTRL_AMCFG_EACT_BIT)
0168
0169 struct spictrl_priv {
0170 rtems_libi2c_bus_t i2clib_desc;
0171 struct drvmgr_dev *dev;
0172 struct spictrl_regs *regs;
0173 int irq;
0174 int minor;
0175 unsigned int core_freq_hz;
0176
0177
0178 int fdepth;
0179 int bits_per_char;
0180 int lsb_first;
0181 int txshift;
0182 int rxshift;
0183 unsigned int idle_char;
0184 int (*slvSelFunc)(void *regs, uint32_t addr, int select);
0185
0186
0187 int periodic_started;
0188 struct spictrl_ioctl_config periodic_cfg;
0189 };
0190
0191
0192
0193 int spictrl_device_init(struct spictrl_priv *priv);
0194
0195 int spictrl_init2(struct drvmgr_dev *dev);
0196 int spictrl_init3(struct drvmgr_dev *dev);
0197
0198 struct drvmgr_drv_ops spictrl_ops =
0199 {
0200 .init = {NULL, spictrl_init2, spictrl_init3, NULL},
0201 .remove = NULL,
0202 .info = NULL
0203 };
0204
0205 struct amba_dev_id spictrl_ids[] =
0206 {
0207 {VENDOR_GAISLER, GAISLER_SPICTRL},
0208 {0, 0}
0209 };
0210
0211 struct amba_drv_info spictrl_drv_info =
0212 {
0213 {
0214 DRVMGR_OBJ_DRV,
0215 NULL,
0216 NULL,
0217 DRIVER_AMBAPP_GAISLER_SPICTRL_ID,
0218 "SPICTRL_DRV",
0219 DRVMGR_BUS_TYPE_AMBAPP,
0220 &spictrl_ops,
0221 NULL,
0222 0,
0223 0,
0224 },
0225 &spictrl_ids[0]
0226 };
0227
0228 void spictrl_register_drv (void)
0229 {
0230 DBG("Registering SPICTRL driver\n");
0231 drvmgr_drv_register(&spictrl_drv_info.general);
0232 }
0233
0234 int spictrl_init2(struct drvmgr_dev *dev)
0235 {
0236 struct spictrl_priv *priv;
0237
0238 DBG("SPICTRL[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
0239
0240 priv = dev->priv = grlib_calloc(1, sizeof(*priv));
0241 if ( !priv )
0242 return DRVMGR_NOMEM;
0243 priv->dev = dev;
0244
0245
0246
0247 return DRVMGR_OK;
0248 }
0249
0250 int spictrl_init3(struct drvmgr_dev *dev)
0251 {
0252 struct spictrl_priv *priv;
0253 char prefix[32];
0254 char devName[48];
0255 int rc;
0256
0257 priv = (struct spictrl_priv *)dev->priv;
0258
0259
0260
0261
0262 rc = rtems_libi2c_initialize();
0263 if (rc != 0) {
0264 DBG("SPICTRL: rtems_libi2c_initialize failed, exiting...\n");
0265 free(dev->priv);
0266 dev->priv = NULL;
0267 return DRVMGR_FAIL;
0268 }
0269
0270
0271
0272
0273
0274
0275 if ( drvmgr_freq_get(dev, DEV_APB_SLV, &priv->core_freq_hz) ) {
0276 return DRVMGR_FAIL;
0277 }
0278
0279 if ( spictrl_device_init(priv) ) {
0280 free(dev->priv);
0281 dev->priv = NULL;
0282 return DRVMGR_FAIL;
0283 }
0284
0285
0286 prefix[0] = '\0';
0287 if ( drvmgr_get_dev_prefix(dev, prefix) ) {
0288
0289
0290
0291 sprintf(devName, "/dev/spi%d", dev->minor_drv+1);
0292 } else {
0293
0294
0295
0296 sprintf(devName, "/dev/%sspi%d", prefix, dev->minor_bus+1);
0297 }
0298
0299
0300 rc = rtems_libi2c_register_bus(devName, &priv->i2clib_desc);
0301 if (rc < 0) {
0302 DBG("SPICTRL: rtems_libi2c_register_bus(%s) failed\n", devName);
0303 free(dev->priv);
0304 dev->priv = NULL;
0305 return DRVMGR_FAIL;
0306 }
0307 priv->minor = rc;
0308
0309 return DRVMGR_OK;
0310 }
0311
0312
0313
0314 STATIC rtems_status_code spictrl_libi2c_send_addr(rtems_libi2c_bus_t *bushdl,
0315 uint32_t addr, int rw);
0316
0317
0318
0319
0320 static int spictrl_set_freq(struct spictrl_priv *priv, unsigned int freq)
0321 {
0322 unsigned int core_freq_hz = priv->core_freq_hz;
0323 unsigned int lowest_freq_possible;
0324 unsigned int div, div16, pm, fact;
0325
0326
0327 lowest_freq_possible = core_freq_hz / (16 * 4 * (0xf + 1));
0328
0329 if ( freq < lowest_freq_possible ) {
0330 DBG("SPICTRL: TOO LOW FREQ %u, CORE FREQ %u, LOWEST FREQ %u\n",
0331 freq, core_freq_hz, lowest_freq_possible);
0332 return -1;
0333 }
0334
0335 div = ((core_freq_hz / 2) + (freq-1)) / freq;
0336 DBG("SPICTRL: DIV=%d, FREQ=%d\n", div, freq);
0337
0338
0339 if ( div > 16 ) {
0340 div = (div + (16 - 1)) / 16;
0341 div16 = 1;
0342 } else {
0343 div16 = 0;
0344 }
0345
0346 if ( div > 0xf ) {
0347 fact = 0;
0348 div = (div + (2 - 1)) / 2;
0349 } else {
0350 fact = 1;
0351 }
0352
0353 pm = div-1;
0354
0355
0356 priv->regs->mode =
0357 (priv->regs->mode & ~(SPICTRL_MODE_PM|SPICTRL_MODE_DIV16|SPICTRL_MODE_FACT)) |
0358 (pm << SPICTRL_MODE_PM_BIT) | (div16 << SPICTRL_MODE_DIV16_BIT) |
0359 (fact << SPICTRL_MODE_FACT_BIT);
0360
0361 DBG("SPICTRL: Effective bit rate %u (requested %u), PM: %x, FACT: %d, div16: %x, core_freq: %u\n",
0362 core_freq_hz / (2 * (fact ? 1 : 2) * (div) * (div16 ? 16 : 1)),
0363 freq, pm, fact, div16, core_freq_hz);
0364
0365 return 0;
0366 }
0367
0368
0369 static int spictrl_start_periodic(struct spictrl_priv *priv)
0370 {
0371 struct spictrl_ioctl_config *cfg = &priv->periodic_cfg;
0372 unsigned int am_cfg;
0373
0374
0375 priv->regs->event = 0xffffffff;
0376
0377
0378 priv->regs->mode |= SPICTRL_MODE_EN | SPICTRL_MODE_MS;
0379
0380
0381 priv->regs->am_period = cfg->period;
0382
0383
0384 am_cfg = (cfg->period_flags & 0x1f8) >> 1;
0385 priv->regs->am_cfg = am_cfg;
0386
0387
0388 if ( cfg->period_flags & SPICTRL_PERIOD_FLAGS_EACT ) {
0389
0390 priv->regs->am_cfg = am_cfg | SPICTRL_AMCFG_EACT;
0391 } else {
0392
0393 priv->regs->am_cfg = am_cfg | SPICTRL_AMCFG_ACT;
0394 }
0395
0396 return 0;
0397 }
0398
0399
0400 static void spictrl_stop_periodic(struct spictrl_priv *priv)
0401 {
0402 priv->regs->am_cfg = 0;
0403 }
0404
0405
0406
0407
0408
0409 static inline unsigned int spictrl_status(struct spictrl_priv *priv)
0410 {
0411 return priv->regs->event;
0412 }
0413
0414 static int spictrl_read_periodic(
0415 struct spictrl_priv *priv,
0416 struct spictrl_period_io *rarg)
0417 {
0418 int i, rxi, rxshift, bits_per_char, reg;
0419 unsigned int rx_word, mask;
0420 void *rxbuf;
0421
0422 if ( rarg->options & 0x1 ) {
0423
0424 for (i=0; i<4; i++) {
0425 rarg->masks[i] = priv->regs->am_mask[i];
0426 }
0427 }
0428
0429 if ( rarg->options & 0x2 ) {
0430
0431
0432
0433
0434
0435 if ( !priv->periodic_started )
0436 return -1;
0437
0438 rxshift = priv->rxshift;
0439 bits_per_char = priv->bits_per_char;
0440 rx_word = 0;
0441
0442 rxbuf = rarg->data;
0443 if ( !rxbuf ) {
0444
0445 return -1;
0446 }
0447
0448
0449 while ( (priv->regs->event & SPICTRL_EVENT_NE) == 0 ) {
0450 ;
0451 }
0452
0453 rxi = 0;
0454 for (i=0; i<4; i++) {
0455 mask = rarg->masks[i];
0456 reg = 0;
0457 while ( mask ) {
0458 if ( mask & 1 ) {
0459
0460 rx_word = priv->regs->am_rx[i*32 + reg] >> rxshift;
0461
0462 if ( bits_per_char <= 8 ) {
0463 *((unsigned char *)rxbuf + rxi) = rx_word;
0464 } else if ( bits_per_char <= 16 ) {
0465 *((unsigned short *)rxbuf + rxi) = rx_word;
0466 } else {
0467 *((unsigned int *)rxbuf + rxi) = rx_word;
0468 }
0469 rxi++;
0470 }
0471
0472 mask = mask>>1;
0473 reg++;
0474 }
0475 }
0476 }
0477
0478 return 0;
0479 }
0480
0481 static int spictrl_write_periodic(
0482 struct spictrl_priv *priv,
0483 struct spictrl_period_io *warg)
0484 {
0485 int i, txi, txshift, bits_per_char, reg;
0486 unsigned int tx_word, mask;
0487 void *txbuf;
0488
0489 if ( warg->options & 0x2 ) {
0490
0491
0492 priv->regs->mode |= SPICTRL_MODE_EN;
0493
0494
0495
0496
0497
0498 txshift = priv->txshift;
0499 bits_per_char = priv->bits_per_char;
0500 tx_word = 0;
0501
0502 txbuf = warg->data;
0503 if ( !txbuf ) {
0504
0505
0506
0507 tx_word = priv->idle_char << txshift;
0508 }
0509
0510 txi = 0;
0511 for (i=0; i<4; i++) {
0512 mask = warg->masks[i];
0513 reg = 0;
0514 while ( mask ) {
0515 if ( mask & 1 ) {
0516 if ( txbuf ) {
0517 if ( bits_per_char <= 8 ) {
0518 tx_word = *((unsigned char *)txbuf + txi);
0519 } else if ( bits_per_char <= 16 ) {
0520 tx_word = *((unsigned short *)txbuf + txi);
0521 } else {
0522 tx_word = *((unsigned int *)txbuf + txi);
0523 }
0524 tx_word = tx_word << txshift;
0525 txi++;
0526 }
0527
0528
0529 DBG("WRITE 0x%08x to 0x%08x\n", tx_word, &priv->regs->am_tx[i*32 + reg]);
0530 priv->regs->am_tx[i*32 + reg] = tx_word;
0531 }
0532
0533 mask = mask>>1;
0534 reg++;
0535 }
0536 }
0537 }
0538
0539 if ( warg->options & 0x1 ) {
0540
0541 for (i=0; i<4; i++) {
0542 DBG("WRITE 0x%08x to 0x%08x (MSK%d)\n", warg->masks[i], &priv->regs->am_mask[i], i);
0543 priv->regs->am_mask[i] = warg->masks[i];
0544 }
0545 }
0546
0547 return 0;
0548 }
0549
0550 static int spictrl_read_write(
0551 struct spictrl_priv *priv,
0552 void *rxbuf,
0553 void *txbuf,
0554 int len)
0555 {
0556 unsigned int tx_word, rx_word, tmp;
0557 int txshift = priv->txshift;
0558 int rxshift = priv->rxshift;
0559 int txi, rxi, bits_per_char;
0560 int length;
0561
0562
0563
0564
0565 if ( priv->periodic_cfg.periodic_mode ) {
0566 return -1;
0567 }
0568
0569 bits_per_char = priv->bits_per_char;
0570 tx_word = 0;
0571 if ( !txbuf ) {
0572 tx_word = priv->idle_char << txshift;
0573 }
0574
0575
0576 priv->regs->event = 0xffffffff;
0577
0578
0579 priv->regs->mode |= SPICTRL_MODE_EN | SPICTRL_MODE_MS;
0580
0581 length = len;
0582 if ( bits_per_char > 8 ) {
0583 length = length / 2;
0584 if ( bits_per_char > 16 )
0585 length = length / 2;
0586 }
0587 DBG("SPICTRL: LENGTH = %d, Bits/Char: %d, Shift: %d, %d\n", length, bits_per_char, txshift, rxshift);
0588
0589 txi=0;
0590 rxi=0;
0591 while ( (rxi < length) || (txi < length) ) {
0592
0593 if ( length > txi ) {
0594 if ( txbuf ) {
0595 if ( bits_per_char <= 8 ) {
0596 tx_word = *((unsigned char *)txbuf + txi);
0597 } else if ( bits_per_char <= 16 ) {
0598 tx_word = *((unsigned short *)txbuf + txi);
0599 } else {
0600 tx_word = *((unsigned int *)txbuf + txi);
0601 }
0602 tx_word = tx_word << txshift;
0603 }
0604
0605
0606 while ( (priv->regs->event & SPICTRL_EVENT_NF) == 0 ) {
0607
0608
0609 }
0610
0611 DBG("SPICTRL: Writing 0x%x\n", tx_word);
0612
0613
0614 priv->regs->tx = tx_word;
0615 txi++;
0616 }
0617
0618
0619 while ( priv->regs->event & SPICTRL_EVENT_NE ) {
0620
0621 tmp = priv->regs->rx;
0622 DBG("SPICTRL: Read 0x%x\n", tmp);
0623
0624 if ( rxbuf && (length > rxi) ) {
0625
0626 rx_word = (tmp >> rxshift);
0627
0628 DBG("SPICTRL: Receiving 0x%x (0x%x, %d)\n", rx_word, tmp, rxshift);
0629
0630 if ( bits_per_char <= 8 ) {
0631 *((unsigned char *)rxbuf + rxi) = rx_word;
0632 } else if ( bits_per_char <= 16 ) {
0633 *((unsigned short *)rxbuf + rxi) = rx_word;
0634 } else {
0635 *((unsigned int *)rxbuf + rxi) = rx_word;
0636 }
0637
0638 }
0639 rxi++;
0640 }
0641 }
0642
0643 return len;
0644 }
0645
0646
0647 STATIC rtems_status_code spictrl_libi2c_init(rtems_libi2c_bus_t *bushdl)
0648 {
0649 struct spictrl_priv *priv = (struct spictrl_priv *)bushdl;
0650
0651 DBG("SPICTRL: spictrl_libi2c_init\n");
0652
0653
0654 priv->regs->mode = SPICTRL_MODE_MS;
0655
0656
0657 priv->regs->mask = 0;
0658
0659
0660 priv->regs->slvsel = 0xffffffff;
0661
0662
0663 priv->regs->event = 0xffffffff;
0664
0665 return 0;
0666 }
0667
0668
0669 STATIC rtems_status_code spictrl_libi2c_send_start(rtems_libi2c_bus_t *bushdl)
0670 {
0671 DBG("SPICTRL: spictrl_libi2c_send_start\n");
0672
0673 return 0;
0674 }
0675
0676
0677 STATIC rtems_status_code spictrl_libi2c_send_stop(rtems_libi2c_bus_t *bushdl)
0678 {
0679 struct spictrl_priv *priv = (struct spictrl_priv *)bushdl;
0680
0681 priv->regs->slvsel = 0xffffffff;
0682
0683 if ( priv->slvSelFunc ) {
0684
0685 return priv->slvSelFunc(priv->regs, -1, 0);
0686 }
0687
0688 DBG("SPICTRL: spictrl_libi2c_send_stop\n");
0689 return 0;
0690 }
0691
0692
0693 STATIC rtems_status_code spictrl_libi2c_send_addr(rtems_libi2c_bus_t *bushdl,
0694 uint32_t addr, int rw)
0695 {
0696 struct spictrl_priv *priv = (struct spictrl_priv *)bushdl;
0697
0698 DBG("SPICTRL: spictrl_libi2c_send_addr, %d\n", addr);
0699
0700 if ( priv->slvSelFunc ) {
0701
0702 return priv->slvSelFunc(priv->regs, addr, 1);
0703 } else if ( priv->regs->capability & SPICTRL_CAP_SSEN ) {
0704 int slaves;
0705
0706
0707 slaves = (priv->regs->capability & SPICTRL_CAP_SSSZ) >> SPICTRL_CAP_SSSZ_BIT;
0708
0709 if ( addr > slaves )
0710 return -1;
0711
0712 if ( (priv->regs->capability & SPICTRL_CAP_ASELA) &&
0713 (priv->periodic_cfg.period_flags & SPICTRL_PERIOD_FLAGS_ASEL) ) {
0714
0715
0716
0717
0718
0719 priv->regs->am_slvsel = ~(1<<(addr-1));
0720 priv->regs->slvsel = priv->periodic_cfg.period_slvsel;
0721
0722 priv->regs->mode |= SPICTRL_MODE_ASEL;
0723 } else {
0724
0725 priv->regs->slvsel = ~(1<<(addr-1));
0726 }
0727 }
0728
0729 return 0;
0730 }
0731
0732
0733 STATIC int spictrl_libi2c_read_bytes(rtems_libi2c_bus_t *bushdl,
0734 unsigned char *bytes, int nbytes)
0735 {
0736 struct spictrl_priv *priv = (struct spictrl_priv *)bushdl;
0737 int ret;
0738
0739 DBG("SPICTRL: spictrl_libi2c_read_bytes %d\n", nbytes);
0740 ret = spictrl_read_write(priv, bytes, NULL, nbytes);
0741 if ( ret < 0 ) {
0742 printk("SPICTRL: Error Reading\n");
0743 }
0744 #ifdef DEBUG
0745 else {
0746 int i;
0747 for(i=0; i<nbytes; i+=16) {
0748 DBG("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x ",
0749 bytes[0+i], bytes[1+i], bytes[2+i], bytes[3+i], bytes[4+i], bytes[5+i], bytes[6+i], bytes[7+i]);
0750 DBG("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
0751 bytes[8+i], bytes[9+i], bytes[10+i], bytes[11+i], bytes[12+i], bytes[13+i], bytes[14+i], bytes[15+i]);
0752 }
0753 }
0754 #endif
0755 return ret;
0756 }
0757
0758
0759 STATIC int spictrl_libi2c_write_bytes(rtems_libi2c_bus_t *bushdl,
0760 unsigned char *bytes, int nbytes)
0761 {
0762 struct spictrl_priv *priv = (struct spictrl_priv *)bushdl;
0763
0764 #ifdef DEBUG
0765 int i;
0766 DBG("SPICTRL: spictrl_libi2c_write_bytes: %d\n", nbytes);
0767
0768 for(i=0; i<nbytes; i+=16) {
0769 DBG("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x ",
0770 bytes[0+i], bytes[1+i], bytes[2+i], bytes[3+i], bytes[4+i], bytes[5+i], bytes[6+i], bytes[7+i]);
0771 DBG("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
0772 bytes[8+i], bytes[9+i], bytes[10+i], bytes[11+i], bytes[12+i], bytes[13+i], bytes[14+i], bytes[15+i]);
0773 }
0774 #endif
0775
0776 return spictrl_read_write(priv, NULL, bytes, nbytes);
0777 }
0778
0779
0780 STATIC int spictrl_libi2c_ioctl(
0781 rtems_libi2c_bus_t * bushdl,
0782 int cmd,
0783 void *buffer)
0784 {
0785 struct spictrl_priv *priv = (struct spictrl_priv *)bushdl;
0786 int ret;
0787
0788 DBG("SPICTRL: spictrl_libi2c_ioctl(%d, 0x%x)\n", cmd, (unsigned int)buffer);
0789
0790 switch (cmd) {
0791 case RTEMS_LIBI2C_IOCTL_SET_TFRMODE:
0792 {
0793 rtems_libi2c_tfr_mode_t *trf_mode = buffer;
0794 unsigned int mode;
0795
0796
0797 priv->regs->mode &= ~SPICTRL_MODE_EN;
0798
0799
0800 if ( spictrl_set_freq(priv, trf_mode->baudrate) ) {
0801
0802 return -1;
0803 }
0804
0805
0806 mode = (priv->regs->mode &
0807 ~(SPICTRL_MODE_CPOL|SPICTRL_MODE_CPHA|SPICTRL_MODE_REV|SPICTRL_MODE_LEN));
0808 if ( trf_mode->clock_inv )
0809 mode |= SPICTRL_MODE_CPOL;
0810 if ( trf_mode->clock_phs )
0811 mode |= SPICTRL_MODE_CPHA;
0812 if ( trf_mode->lsb_first == 0 )
0813 mode |= SPICTRL_MODE_REV;
0814
0815 if ( (trf_mode->bits_per_char < 4) ||
0816 ((trf_mode->bits_per_char > 16) && (trf_mode->bits_per_char != 32)) )
0817 return -1;
0818 if ( trf_mode->bits_per_char == 32 ) {
0819 priv->txshift = 0;
0820 priv->rxshift = 0;
0821 } else {
0822 mode |= (trf_mode->bits_per_char-1) << SPICTRL_MODE_LEN_BIT;
0823 if ( trf_mode->lsb_first == 0 ) {
0824
0825 priv->txshift = 32 - trf_mode->bits_per_char;
0826 priv->rxshift = 16;
0827 } else {
0828
0829 priv->txshift = 0;
0830 priv->rxshift = 16 - trf_mode->bits_per_char;
0831 }
0832 }
0833
0834 priv->bits_per_char = trf_mode->bits_per_char;
0835 priv->lsb_first = trf_mode->lsb_first;
0836 priv->idle_char = trf_mode->idle_char;
0837
0838
0839 priv->regs->mode = mode;
0840
0841 return 0;
0842 }
0843
0844 case RTEMS_LIBI2C_IOCTL_READ_WRITE:
0845 {
0846 rtems_libi2c_read_write_t *arg = buffer;
0847
0848 DBG("SPICTRL: IOCTL READ/WRITE, RX: 0x%x, TX: 0x%x, len: %d\n", arg->rd_buf, arg->wr_buf, arg->byte_cnt);
0849 #ifdef DEBUG
0850
0851 if ( arg->wr_buf ) {
0852 unsigned char *bytes = (unsigned char *)arg->wr_buf;
0853 int i;
0854 for(i=0; i<arg->byte_cnt; i+=16) {
0855 DBG("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x ",
0856 bytes[0+i], bytes[1+i], bytes[2+i], bytes[3+i], bytes[4+i], bytes[5+i], bytes[6+i], bytes[7+i]);
0857 DBG("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
0858 bytes[8+i], bytes[9+i], bytes[10+i], bytes[11+i], bytes[12+i], bytes[13+i], bytes[14+i], bytes[15+i]);
0859 }
0860 }
0861 #endif
0862
0863 ret = spictrl_read_write(priv, arg->rd_buf, (unsigned char *)arg->wr_buf,
0864 arg->byte_cnt);
0865 #ifdef DEBUG
0866
0867 if ( arg->rd_buf ) {
0868 unsigned char *bytes = (unsigned char *)arg->rd_buf;
0869 int i;
0870 for(i=0; i<arg->byte_cnt; i+=16) {
0871 DBG("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x ",
0872 bytes[0+i], bytes[1+i], bytes[2+i], bytes[3+i], bytes[4+i], bytes[5+i], bytes[6+i], bytes[7+i]);
0873 DBG("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
0874 bytes[8+i], bytes[9+i], bytes[10+i], bytes[11+i], bytes[12+i], bytes[13+i], bytes[14+i], bytes[15+i]);
0875 }
0876 }
0877 #endif
0878 return ret;
0879 }
0880
0881
0882 case SPICTRL_IOCTL_CONFIG:
0883 {
0884 struct spictrl_ioctl_config *cfg;
0885
0886 DBG("SPICTRL: Configuring Periodic mode\n");
0887
0888 if ( priv->periodic_started ) {
0889 DBG("SPICTRL: Periodic mode already started, too late to configure\n");
0890 return -1;
0891 }
0892
0893 cfg = buffer;
0894 if ( cfg == NULL ) {
0895 memset(&priv->periodic_cfg, 0, sizeof(priv->periodic_cfg));
0896 } else {
0897 priv->periodic_cfg = *cfg;
0898 }
0899 cfg = &priv->periodic_cfg;
0900 if ( cfg->periodic_mode ) {
0901
0902 priv->regs->mode |= SPICTRL_MODE_AMEN;
0903
0904
0905 if ( (priv->regs->mode & SPICTRL_MODE_AMEN) == 0 ) {
0906 priv->periodic_cfg.periodic_mode = 0;
0907 DBG("SPICTRL: Periodic mode not supported by hardware\n");
0908 return -1;
0909 }
0910 } else {
0911
0912 priv->regs->mode &= ~SPICTRL_MODE_AMEN;
0913 }
0914 priv->periodic_started = 0;
0915
0916
0917 priv->regs->mode = (priv->regs->mode & ~(SPICTRL_MODE_CG|SPICTRL_MODE_TAC)) |
0918 (cfg->clock_gap << SPICTRL_MODE_CG_BIT) |
0919 (cfg->flags & SPICTRL_MODE_TAC);
0920 return 0;
0921 }
0922 case SPICTRL_IOCTL_PERIOD_START:
0923 {
0924 if ( !priv->periodic_cfg.periodic_mode || priv->periodic_started ) {
0925 return -1;
0926 }
0927 if ( spictrl_start_periodic(priv) == 0 ) {
0928 priv->periodic_started = 1;
0929 return 0;
0930 } else
0931 return -1;
0932 }
0933 case SPICTRL_IOCTL_PERIOD_STOP:
0934 {
0935 if ( !priv->periodic_cfg.periodic_mode || !priv->periodic_started ) {
0936 return -1;
0937 }
0938 spictrl_stop_periodic(priv);
0939 priv->periodic_started = 0;
0940 return 0;
0941 }
0942 case SPICTRL_IOCTL_STATUS:
0943 {
0944 if ( !buffer )
0945 return 0;
0946 *(unsigned int *)buffer = spictrl_status(priv);
0947 return 0;
0948 }
0949
0950 case SPICTRL_IOCTL_PERIOD_WRITE:
0951 {
0952 if ( !priv->periodic_cfg.periodic_mode || !buffer ) {
0953 return -1;
0954 }
0955 if ( spictrl_write_periodic(priv, (struct spictrl_period_io *)
0956 buffer) == 0 ) {
0957 return 0;
0958 } else
0959 return -1;
0960 }
0961
0962 case SPICTRL_IOCTL_PERIOD_READ:
0963 {
0964 if ( !priv->periodic_cfg.periodic_mode || !buffer ) {
0965 return -1;
0966 }
0967 if ( spictrl_read_periodic(priv, (struct spictrl_period_io *)
0968 buffer) == 0 ) {
0969 return 0;
0970 } else
0971 return -1;
0972 }
0973
0974 case SPICTRL_IOCTL_REGS:
0975 {
0976
0977 if ( !buffer ) {
0978 return -1;
0979 }
0980 *(struct spictrl_regs **)buffer = priv->regs;
0981 return 0;
0982 }
0983
0984 default:
0985
0986 return -1;
0987 }
0988
0989 return 0;
0990 }
0991
0992 STATIC rtems_libi2c_bus_ops_t spictrl_libi2c_ops =
0993 {
0994 .init = spictrl_libi2c_init,
0995 .send_start = spictrl_libi2c_send_start,
0996 .send_stop = spictrl_libi2c_send_stop,
0997 .send_addr = spictrl_libi2c_send_addr,
0998 .read_bytes = spictrl_libi2c_read_bytes,
0999 .write_bytes = spictrl_libi2c_write_bytes,
1000 .ioctl = spictrl_libi2c_ioctl
1001 };
1002
1003 int spictrl_device_init(struct spictrl_priv *priv)
1004 {
1005 struct amba_dev_info *ambadev;
1006 struct ambapp_core *pnpinfo;
1007 union drvmgr_key_value *value;
1008
1009
1010 ambadev = (struct amba_dev_info *)priv->dev->businfo;
1011 if ( ambadev == NULL ) {
1012 return -1;
1013 }
1014 pnpinfo = &ambadev->info;
1015 priv->irq = pnpinfo->irq;
1016 priv->regs = (struct spictrl_regs *)pnpinfo->apb_slv->start;
1017 priv->fdepth = (priv->regs->capability & SPICTRL_CAP_FDEPTH) >> SPICTRL_CAP_FDEPTH_BIT;
1018
1019 DBG("SPCTRL: 0x%x irq %d, FIFO: %d\n", (unsigned int)priv->regs, priv->irq, priv->fdepth);
1020
1021
1022 priv->regs->mask = 0;
1023
1024
1025 priv->regs->mode = 0;
1026
1027
1028 value = drvmgr_dev_key_get(priv->dev, "slvSelFunc", DRVMGR_KT_POINTER);
1029 if ( value ) {
1030 priv->slvSelFunc = value->ptr;
1031 }
1032
1033
1034 priv->i2clib_desc.ops = &spictrl_libi2c_ops;
1035 priv->i2clib_desc.size = sizeof(spictrl_libi2c_ops);
1036 return 0;
1037 }