Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:07

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*  SPWTDP - SpaceWire Time Distribution Protocol. The driver provides
0004  *  device discovery and interrupt management.
0005  *
0006  *  COPYRIGHT (c) 2017.
0007  *  Cobham Gaisler AB
0008  *
0009  * Redistribution and use in source and binary forms, with or without
0010  * modification, are permitted provided that the following conditions
0011  * are met:
0012  * 1. Redistributions of source code must retain the above copyright
0013  *    notice, this list of conditions and the following disclaimer.
0014  * 2. Redistributions in binary form must reproduce the above copyright
0015  *    notice, this list of conditions and the following disclaimer in the
0016  *    documentation and/or other materials provided with the distribution.
0017  *
0018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0021  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0022  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0023  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0024  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0026  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0027  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0028  * POSSIBILITY OF SUCH DAMAGE.
0029  *
0030  */
0031 
0032 #include <stdio.h>
0033 #include <stdlib.h>
0034 #include <stddef.h>
0035 #include <rtems.h>
0036 #include <rtems/bspIo.h>
0037 #include <drvmgr/drvmgr.h>
0038 #include <grlib/ambapp.h>
0039 #include <grlib/ambapp_bus.h>
0040 #include <bsp.h>
0041 #include <grlib/spwtdp.h>
0042 
0043 #include <grlib/grlib_impl.h>
0044 
0045 /*#define STATIC*/
0046 #define STATIC static
0047 
0048 /*#define INLINE*/
0049 #define INLINE inline
0050 
0051 /*#define UNUSED*/
0052 #define UNUSED __attribute__((unused))
0053 
0054 #define DEBUG 1
0055 
0056 #ifdef DEBUG
0057 #define DBG(x...) printf(x)
0058 #else
0059 #define DBG(x...) 
0060 #endif
0061 
0062 /* Memory and HW Registers Access routines. All 32-bit access routines */
0063 #define REG_WRITE(addr, val) \
0064     (*(volatile unsigned int *)(addr) = (unsigned int)(val))
0065 #define REG_READ(addr) (*(volatile unsigned int *)(addr))
0066 
0067 /*
0068  * Configuration register definitions
0069  * DEFINED in header
0070  */
0071 
0072 /*
0073  * Control register definitions
0074  * DEFINED in header
0075  */
0076 
0077 /*
0078  * TSTX Control register definitions
0079  */
0080 #define TSTXCTRL_TSTC (0xff<<TSTXCTRL_TSTC_BIT)
0081 #define ETCTRL_PF (0xffff<<ETCTRL_PF_BIT)
0082 
0083 #define TSTXCTRL_TSTC_BIT 24
0084 #define ETCTRL_PF_BIT 0
0085 
0086 #define DEVNAME_LEN 11
0087 /* Private structure of SPWTDP driver. */
0088 struct spwtdp_priv {
0089     char devname[DEVNAME_LEN];
0090     struct drvmgr_dev *dev; /* Device */
0091     struct spwtdp_regs *regs;
0092     int open;
0093     int index;
0094     int initiator; /* Initiator configured */
0095     int target; /* Target configured */
0096     int freq; /* Frequency configured */
0097 
0098     /* Spin-lock ISR protection */
0099     SPIN_DECLARE(devlock);
0100 
0101     /* Driver semaphore */
0102     rtems_id sem;
0103     spwtdp_isr_t isr;
0104     void * isr_arg;
0105 };
0106 int spwtdp_count = 0;
0107 static struct spwtdp_priv *priv_tab[SPWTDP_MAX];
0108 
0109 
0110 STATIC void spwtdp_isr(void *data);
0111 STATIC int spwtdp_hw_reset(struct spwtdp_priv *priv);
0112 STATIC int spwtdp_init2(struct drvmgr_dev *dev);
0113 
0114 struct drvmgr_drv_ops spwtdp_ops =
0115 {
0116     {NULL, spwtdp_init2, NULL, NULL},
0117     NULL,
0118     NULL
0119 };
0120 
0121 struct amba_dev_id spwtdp_ids[] =
0122 {
0123     {VENDOR_GAISLER, GAISLER_SPWTDP},
0124     {0, 0}  /* Mark end of table */
0125 };
0126 
0127 struct amba_drv_info spwtdp_drv_info =
0128 {
0129     {
0130         DRVMGR_OBJ_DRV,         /* Driver */
0131         NULL,               /* Next driver */
0132         NULL,               /* Device list */
0133         DRIVER_AMBAPP_GAISLER_SPWTDP_ID,/* Driver ID */
0134         "SPWTDP_DRV",           /* Driver Name */
0135         DRVMGR_BUS_TYPE_AMBAPP,     /* Bus Type */
0136         &spwtdp_ops,
0137         NULL,               /* Funcs */
0138         0,              /* No devices yet */
0139         sizeof(struct spwtdp_priv), /* Let DrvMgr allocate priv */
0140     },
0141     &spwtdp_ids[0]
0142 };
0143 
0144 /* Register the SPWTDP Driver */
0145 void spwtdp_register_drv(void)
0146 {
0147     DBG("Registering SPWTDP driver\n");
0148     drvmgr_drv_register(&spwtdp_drv_info.general);
0149 }
0150 
0151 STATIC int spwtdp_init(struct spwtdp_priv *priv)
0152 {
0153     struct amba_dev_info *ainfo = priv->dev->businfo;
0154     struct ambapp_apb_info *apb;
0155 
0156     /* Get device information from AMBA PnP information */
0157     if (ainfo == NULL) {
0158         return -1;
0159     }
0160     apb = ainfo->info.apb_slv;
0161     priv->regs = (struct spwtdp_regs *)apb->start;
0162 
0163     spwtdp_hw_reset(priv);
0164     /* Only support 56 bits counter */
0165     if (REG_READ(&priv->regs->dat_ctrl) != 0x2f00) {
0166         DBG("SPWTDP only supports 56 bit precission counters.\n");
0167         return -1;
0168     }
0169     DBG("SPWTDP driver initialized\n");
0170 
0171     return 0;
0172 }
0173 
0174 /*** INTERFACE TO DRIVER MANAGER ***/
0175 STATIC int spwtdp_init2(struct drvmgr_dev *dev)
0176 {
0177     int status;
0178     struct spwtdp_priv *priv;
0179 
0180     DBG("SPWTDP[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
0181 
0182     if (spwtdp_count >= SPWTDP_MAX)
0183         return DRVMGR_ENORES;
0184 
0185     priv = dev->priv;
0186     if (priv == NULL)
0187         return DRVMGR_NOMEM;
0188 
0189     /* Register device */
0190     priv->dev = dev;
0191     priv->index = spwtdp_count;
0192     priv_tab[priv->index] = priv;
0193     snprintf(priv->devname, DEVNAME_LEN, "spwtdp%01u", priv->index);
0194     spwtdp_count++;
0195 
0196     /* Initialize Semaphore */
0197     if (rtems_semaphore_create(
0198         rtems_build_name('S', 'T', 'P', '0' + priv->index), 1,
0199         RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | \
0200         RTEMS_NO_INHERIT_PRIORITY | RTEMS_LOCAL | \
0201         RTEMS_NO_PRIORITY_CEILING, 0, &priv->sem) != RTEMS_SUCCESSFUL) {
0202         priv->sem = RTEMS_ID_NONE;
0203         return DRVMGR_FAIL;
0204     }
0205 
0206     /* Initialize SPWTDP Hardware */
0207     status = spwtdp_init(priv);
0208     if (status) {
0209         printk("Failed to initialize spwtdp driver %d\n", status);
0210         return -1;
0211     }
0212 
0213     return DRVMGR_OK;
0214 }
0215 
0216 /* Hardware Reset of SPWTDP */
0217 STATIC int spwtdp_hw_reset(struct spwtdp_priv *priv)
0218 {
0219     int i = 1000;
0220     SPIN_IRQFLAGS(irqflags);
0221 
0222     SPIN_LOCK_IRQ(&priv->devlock, irqflags);
0223 
0224     /* Clear interrupts */
0225     REG_WRITE(&priv->regs->ists, SPWTDP_IRQ_WCLEAR);
0226 
0227     /* Reset the SPWTDP core */
0228     REG_WRITE(&priv->regs->conf[0], CONF0_RS);
0229 
0230     /* Wait for reset */
0231     while ((REG_READ(&priv->regs->conf[0]) & CONF0_RS) && (i > 0)) {
0232         i--;
0233     }
0234 
0235     SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0236 
0237     return ((i > 0)? SPWTDP_ERR_OK : SPWTDP_ERR_ERROR);
0238 }
0239 
0240 int spwtdp_reset(void *spwtdp)
0241 {
0242     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0243 
0244     /* Check priv and unregister isr */
0245     int ret = spwtdp_isr_unregister(spwtdp);
0246     if (ret != SPWTDP_ERR_OK)
0247         return ret;
0248 
0249     priv->initiator=0;
0250     priv->target=0;
0251     priv->freq=0;
0252 
0253     return spwtdp_hw_reset(priv);
0254 }
0255 
0256 void *spwtdp_open(int dev_no)
0257 {
0258     struct spwtdp_priv *priv;
0259 
0260     if (dev_no >= spwtdp_count)
0261         return NULL;
0262 
0263     /* Get Device */
0264     priv = priv_tab[dev_no];
0265     if ((priv == NULL)||(priv->open == 1)) {
0266         return NULL;
0267     }
0268 
0269     /* Set initial state of software */
0270     priv->open = 1;
0271 
0272     return priv;
0273 }
0274 
0275 int spwtdp_close(void *spwtdp)
0276 {
0277     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0278 
0279     /* Check priv and reset core */
0280     int ret = spwtdp_reset(spwtdp);
0281     if (ret != SPWTDP_ERR_OK)
0282         return ret;
0283 
0284     priv->open = 0;
0285     return SPWTDP_ERR_OK;
0286 }
0287 
0288 int spwtdp_freq_setup(void *spwtdp, uint32_t fsinc, uint32_t cv, uint8_t etinc)
0289 {
0290     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0291 
0292     /* Check priv */
0293     if (priv == NULL)
0294         return SPWTDP_ERR_NOINIT;
0295 
0296     if (priv->open == 0)
0297         return SPWTDP_ERR_EINVAL;
0298 
0299     /* Take SPWTDP lock - Wait until we get semaphore */
0300     if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
0301         != RTEMS_SUCCESSFUL)
0302         return SPWTDP_ERR_ERROR;
0303 
0304     REG_WRITE(&priv->regs->conf[1], fsinc & CONF1_FSINC);
0305     REG_WRITE(&priv->regs->conf[2],
0306         ((cv<<CONF2_CV_BIT) & CONF2_CV) |
0307         ((uint32_t)etinc & CONF2_ETINC));
0308 
0309     rtems_semaphore_release(priv->sem);
0310     priv->freq = 1;
0311 
0312     return SPWTDP_ERR_OK;
0313 }
0314 
0315 #define CONF0_INI_MASK (CONF0_EP|CONF0_ET|CONF0_SP|CONF0_SE|CONF0_LE| \
0316         CONF0_TD)
0317 int spwtdp_initiator_conf(void *spwtdp, uint8_t mapping, uint32_t options)
0318 {
0319     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0320 
0321     /* Check priv */
0322     if (priv == NULL)
0323         return SPWTDP_ERR_NOINIT;
0324 
0325     if (priv->open == 0)
0326         return SPWTDP_ERR_EINVAL;
0327 
0328     /* Check if configured as target */
0329     if (priv->target == 1)
0330         return SPWTDP_ERR_EINVAL;
0331 
0332     /* Take SPWTDP lock - Wait until we get semaphore */
0333     if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
0334         != RTEMS_SUCCESSFUL)
0335         return SPWTDP_ERR_ERROR;
0336 
0337     unsigned int conf0 = REG_READ(&priv->regs->conf[0]);
0338     conf0 &= ~(CONF0_INI_MASK|CONF0_MAP);
0339     REG_WRITE(&priv->regs->conf[0],
0340             conf0 | (options & CONF0_INI_MASK) |
0341             (((uint32_t)mapping << CONF0_MAP_BIT) & CONF0_MAP));
0342 
0343     priv->initiator = 1;
0344 
0345     rtems_semaphore_release(priv->sem);
0346 
0347     return SPWTDP_ERR_OK;
0348 }
0349 
0350 #define CONF0_TAR_MASK (CONF0_JE|CONF0_ST|CONF0_EP|CONF0_ET|CONF0_SP| \
0351         CONF0_SE|CONF0_LE|CONF0_TD|CONF0_ME)
0352 int spwtdp_target_conf(void *spwtdp, uint8_t mapping, uint32_t options)
0353 {
0354     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0355 
0356     /* Check priv */
0357     if (priv == NULL)
0358         return SPWTDP_ERR_NOINIT;
0359 
0360     if (priv->open == 0)
0361         return SPWTDP_ERR_EINVAL;
0362 
0363     /* Check if configured as initiator */
0364     if (priv->initiator == 1)
0365         return SPWTDP_ERR_EINVAL;
0366 
0367     /* Take SPWTDP lock - Wait until we get semaphore */
0368     if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
0369         != RTEMS_SUCCESSFUL)
0370         return SPWTDP_ERR_ERROR;
0371 
0372     unsigned int conf0 = REG_READ(&priv->regs->conf[0]);
0373     conf0 &= ~(CONF0_TAR_MASK|CONF0_MAP);
0374     REG_WRITE(&priv->regs->conf[0],
0375             conf0 | (options & CONF0_TAR_MASK) |
0376             (((uint32_t)mapping << CONF0_MAP_BIT) & CONF0_MAP));
0377 
0378     priv->initiator = 1;
0379 
0380     rtems_semaphore_release(priv->sem);
0381 
0382     return SPWTDP_ERR_OK;
0383 }
0384 
0385 int spwtdp_initiator_int_conf(void *spwtdp, uint8_t stm, uint8_t inrx,
0386                   uint8_t intx)
0387 {
0388     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0389 
0390     /* Check priv */
0391     if (priv == NULL)
0392         return SPWTDP_ERR_NOINIT;
0393 
0394     if (priv->open == 0)
0395         return SPWTDP_ERR_EINVAL;
0396 
0397     /* Check if configured as initiator */
0398     if (priv->initiator != 1)
0399         return SPWTDP_ERR_EINVAL;
0400 
0401     REG_WRITE(&priv->regs->conf[3],
0402             (((uint32_t)stm << CONF3_STM_BIT) & CONF3_STM) |
0403             (((uint32_t)inrx << CONF3_INRX_BIT) & CONF3_INRX) |
0404             (((uint32_t)intx << CONF3_INTX_BIT) & CONF3_INTX));
0405 
0406     return SPWTDP_ERR_OK;
0407 }
0408 
0409 int spwtdp_target_int_conf(void *spwtdp, uint8_t inrx, uint8_t intx,
0410                uint32_t options)
0411 {
0412     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0413 
0414     /* Check priv */
0415     if (priv == NULL) {
0416         return SPWTDP_ERR_NOINIT;
0417     }
0418 
0419     if (priv->open == 0)
0420         return SPWTDP_ERR_EINVAL;
0421 
0422     /* Check if configured as target */
0423     if (priv->target != 1)
0424         return SPWTDP_ERR_EINVAL;
0425 
0426     REG_WRITE(&priv->regs->conf[3],
0427             (options & CONF3_DI) |
0428             (((uint32_t)inrx << CONF3_INRX_BIT) & CONF3_INRX) |
0429             (((uint32_t)intx << CONF3_INTX_BIT) & CONF3_INTX));
0430 
0431     return SPWTDP_ERR_OK;
0432 }
0433 
0434 int spwtdp_initiator_enable(void *spwtdp)
0435 {
0436     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0437 
0438     /* Check priv */
0439     if (priv == NULL) {
0440         return SPWTDP_ERR_NOINIT;
0441     }
0442 
0443     if (priv->open == 0)
0444         return SPWTDP_ERR_EINVAL;
0445 
0446     /* Check if configured as initiator */
0447     if (priv->initiator != 1)
0448         return SPWTDP_ERR_EINVAL;
0449 
0450     /* Check if frequency is configured */
0451     if (priv->freq != 1)
0452         return SPWTDP_ERR_EINVAL;
0453 
0454     /* Take SPWTDP lock - Wait until we get semaphore */
0455     if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
0456         != RTEMS_SUCCESSFUL)
0457         return SPWTDP_ERR_ERROR;
0458 
0459     unsigned int conf0 = REG_READ(&priv->regs->conf[0]);
0460     REG_WRITE(&priv->regs->conf[0], conf0 | CONF0_TE);
0461 
0462     rtems_semaphore_release(priv->sem);
0463 
0464     return SPWTDP_ERR_OK;
0465 }
0466 
0467 int spwtdp_target_enable(void *spwtdp)
0468 {
0469     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0470 
0471     /* Check priv */
0472     if (priv == NULL)
0473         return SPWTDP_ERR_NOINIT;
0474 
0475     if (priv->open == 0)
0476         return SPWTDP_ERR_EINVAL;
0477 
0478     /* Check if configured as target */
0479     if (priv->target != 1)
0480         return SPWTDP_ERR_EINVAL;
0481 
0482     /* Check if frequency is configured */
0483     if (priv->freq != 1)
0484         return SPWTDP_ERR_EINVAL;
0485 
0486     /* Take SPWTDP lock - Wait until we get semaphore */
0487     if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
0488         != RTEMS_SUCCESSFUL)
0489         return SPWTDP_ERR_ERROR;
0490 
0491     unsigned int conf0 = REG_READ(&priv->regs->conf[0]);
0492     REG_WRITE(&priv->regs->conf[0], conf0 | CONF0_RE);
0493 
0494     rtems_semaphore_release(priv->sem);
0495 
0496     return SPWTDP_ERR_OK;
0497 }
0498 
0499 int spwtdp_initiator_disable(void *spwtdp)
0500 {
0501     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0502 
0503     /* Check priv */
0504     if (priv == NULL)
0505         return SPWTDP_ERR_NOINIT;
0506 
0507     if (priv->open == 0)
0508         return SPWTDP_ERR_EINVAL;
0509 
0510     /* Take SPWTDP lock - Wait until we get semaphore */
0511     if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
0512         != RTEMS_SUCCESSFUL)
0513         return SPWTDP_ERR_ERROR;
0514 
0515     unsigned int conf0 = REG_READ(&priv->regs->conf[0]);
0516     REG_WRITE(&priv->regs->conf[0], conf0 & ~(CONF0_TE));
0517 
0518     rtems_semaphore_release(priv->sem);
0519 
0520     return SPWTDP_ERR_OK;
0521 }
0522 
0523 int spwtdp_target_disable(void *spwtdp)
0524 {
0525     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0526 
0527     /* Check priv */
0528     if (priv == NULL)
0529         return SPWTDP_ERR_NOINIT;
0530 
0531     if (priv->open == 0)
0532         return SPWTDP_ERR_EINVAL;
0533 
0534     /* Take SPWTDP lock - Wait until we get semaphore */
0535     if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
0536         != RTEMS_SUCCESSFUL)
0537         return SPWTDP_ERR_ERROR;
0538 
0539     unsigned int conf0 = REG_READ(&priv->regs->conf[0]);
0540     REG_WRITE(&priv->regs->conf[0], conf0 & ~(CONF0_RE));
0541 
0542     rtems_semaphore_release(priv->sem);
0543 
0544     return SPWTDP_ERR_OK;
0545 }
0546 
0547 /* Get and Clear status */
0548 int spwtdp_status(void *spwtdp, uint32_t *sts, uint32_t clrmask)
0549 {
0550     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0551 
0552     if (priv == NULL) {
0553         /* SPWTDP not initialized */
0554         return SPWTDP_ERR_NOINIT;
0555     }
0556 
0557     unsigned int status = REG_READ(&priv->regs->stat[0]);
0558     REG_WRITE(&priv->regs->stat[0], status & clrmask);
0559 
0560     if (sts != NULL)
0561         *sts = status;
0562 
0563     return SPWTDP_ERR_OK;
0564 }
0565 
0566 /* Get and Clear interrupts */
0567 int spwtdp_interrupt_status(void *spwtdp, uint32_t *sts, uint32_t clrmask)
0568 {
0569     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0570     SPIN_IRQFLAGS(irqflags);
0571 
0572     if (priv == NULL) {
0573         /* SPWTDP not initialized */
0574         return SPWTDP_ERR_NOINIT;
0575     }
0576 
0577     SPIN_LOCK_IRQ(&priv->devlock, irqflags);
0578     unsigned int status = REG_READ(&priv->regs->ists);
0579     REG_WRITE(&priv->regs->ists, status & clrmask);
0580     SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
0581 
0582     if (sts != NULL)
0583         *sts = status;
0584 
0585     return SPWTDP_ERR_OK;
0586 }
0587 
0588 /* Unmask interrupts */
0589 int spwtdp_interrupt_unmask(void *spwtdp, uint32_t irqmask)
0590 {
0591     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0592 
0593     if (priv == NULL) {
0594         /* SPWTDP not initialized */
0595         return SPWTDP_ERR_NOINIT;
0596     }
0597 
0598     if (priv->open == 0)
0599         return SPWTDP_ERR_EINVAL;
0600 
0601     unsigned int ctrl = REG_READ(&priv->regs->ien);
0602     REG_WRITE(&priv->regs->ien, ctrl | irqmask);
0603 
0604     return SPWTDP_ERR_OK;
0605 }
0606 
0607 /* Mask interrupts */
0608 int spwtdp_interrupt_mask(void *spwtdp, uint32_t irqmask)
0609 {
0610     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0611 
0612     if (priv == NULL) {
0613         /* SPWTDP not initialized */
0614         return SPWTDP_ERR_NOINIT;
0615     }
0616 
0617     if (priv->open == 0)
0618         return SPWTDP_ERR_EINVAL;
0619 
0620     unsigned int ctrl = REG_READ(&priv->regs->ien);
0621     REG_WRITE(&priv->regs->ien, ctrl & ~(irqmask));
0622 
0623     return SPWTDP_ERR_OK;
0624 }
0625 
0626 int spwtdp_isr_register(void *spwtdp, spwtdp_isr_t func, void *data)
0627 {
0628     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0629     SPIN_ISR_IRQFLAGS(irqflags);
0630 
0631     if (priv == NULL) {
0632         /* SPWTDP not initialized */
0633         return SPWTDP_ERR_NOINIT;
0634     }
0635 
0636     if (priv->open == 0)
0637         return SPWTDP_ERR_EINVAL;
0638 
0639     /* Check isr */
0640     if (func == NULL) {
0641         /* No ISR */
0642         return SPWTDP_ERR_EINVAL;
0643     }
0644 
0645     priv->isr = func;
0646     priv->isr_arg = data;
0647 
0648     /* Register and Enable Interrupt at Interrupt controller */
0649     drvmgr_interrupt_register(priv->dev, 0, "spwtdp", spwtdp_isr, priv);
0650 
0651     /* Enable AMBA Interrupts */
0652     SPIN_LOCK(&priv->devlock, irqflags);
0653     unsigned int cfg0 = REG_READ(&priv->regs->conf[0]);
0654     REG_WRITE(&priv->regs->conf[0], cfg0 | CONF0_AE);
0655     SPIN_UNLOCK(&priv->devlock, irqflags);
0656 
0657     return SPWTDP_ERR_OK;
0658 }
0659 
0660 int spwtdp_isr_unregister(void *spwtdp)
0661 {
0662     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0663     SPIN_ISR_IRQFLAGS(irqflags);
0664 
0665     /* Disable IRQS (and check for priv!=NULL) */
0666     int ret=spwtdp_interrupt_mask(spwtdp, SPWTDP_IRQ_WCLEAR);
0667     if (ret != SPWTDP_ERR_OK)
0668         return ret;
0669 
0670     /* Disable AMBA Interrupts */
0671     SPIN_LOCK(&priv->devlock, irqflags);
0672     unsigned int cfg0 = REG_READ(&priv->regs->conf[0]);
0673     REG_WRITE(&priv->regs->conf[0], cfg0 & ~(CONF0_AE));
0674     SPIN_UNLOCK(&priv->devlock, irqflags);
0675 
0676     /* Disable Interrupt at Interrupt controller */
0677     drvmgr_interrupt_unregister(priv->dev, 0, spwtdp_isr, priv);
0678 
0679     /* Unregister isr */
0680     priv->isr = NULL;
0681     priv->isr_arg = NULL;
0682 
0683     return SPWTDP_ERR_OK;
0684 }
0685 
0686 STATIC void spwtdp_isr(void *arg)
0687 {
0688     struct spwtdp_priv *priv = arg;
0689     unsigned int ists = REG_READ(&priv->regs->ists);
0690     SPIN_ISR_IRQFLAGS(irqflags);
0691 
0692     /* Return if the SPWTDP didn't generate the IRQ */
0693     if (ists == 0)
0694         return;
0695 
0696     SPIN_LOCK(&priv->devlock, irqflags);
0697     REG_WRITE(&priv->regs->ists, ists); /* clear handled interrupt events */
0698     SPIN_UNLOCK(&priv->devlock, irqflags);
0699 
0700     /* Let user Handle Interrupt */
0701     if (priv->isr!=NULL)
0702         priv->isr(ists, priv->isr_arg);
0703 
0704     return;
0705 }
0706 
0707 int spwtdp_dat_et_get(void * spwtdp, spwtdp_time_t * val)
0708 {
0709     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0710 
0711     if (priv == NULL) {
0712         /* SPWTDP not initialized */
0713         return SPWTDP_ERR_NOINIT;
0714     }
0715 
0716     if (priv->open == 0)
0717         return SPWTDP_ERR_EINVAL;
0718 
0719     /* Check pointer */
0720     if (val == NULL) {
0721         return SPWTDP_ERR_EINVAL;
0722     }
0723 
0724     val->preamble = REG_READ(&priv->regs->dat_ctrl) & ETCTRL_PF;
0725     unsigned int * buffer = (unsigned int *) val->data;
0726     buffer[0] = REG_READ(&priv->regs->dat_et[0]);
0727     buffer[1] = REG_READ(&priv->regs->dat_et[1]);
0728     buffer[2] = REG_READ(&priv->regs->dat_et[2]);
0729     buffer[3] = REG_READ(&priv->regs->dat_et[3]);
0730     buffer[4] = REG_READ(&priv->regs->dat_et[4]);
0731 
0732     return SPWTDP_ERR_OK;
0733 }
0734 
0735 int spwtdp_tsrx_et_get(void * spwtdp, spwtdp_time_t * val)
0736 {
0737     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0738 
0739     if (priv == NULL) {
0740         /* SPWTDP not initialized */
0741         return SPWTDP_ERR_NOINIT;
0742     }
0743 
0744     if (priv->open == 0)
0745         return SPWTDP_ERR_EINVAL;
0746 
0747     /* Check pointer */
0748     if (val == NULL) {
0749         return SPWTDP_ERR_EINVAL;
0750     }
0751 
0752     val->preamble = REG_READ(&priv->regs->ts_rx_ctrl) & ETCTRL_PF;
0753     unsigned int * buffer = (unsigned int *) val->data;
0754     buffer[0] = REG_READ(&priv->regs->ts_rx_et[0]);
0755     buffer[1] = REG_READ(&priv->regs->ts_rx_et[1]);
0756     buffer[2] = REG_READ(&priv->regs->ts_rx_et[2]);
0757     buffer[3] = REG_READ(&priv->regs->ts_rx_et[3]);
0758     buffer[4] = REG_READ(&priv->regs->ts_rx_et[4]);
0759 
0760     return SPWTDP_ERR_OK;
0761 }
0762 
0763 int spwtdp_tstx_et_get(void * spwtdp, spwtdp_time_t * val)
0764 {
0765     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0766 
0767     if (priv == NULL) {
0768         /* SPWTDP not initialized */
0769         return SPWTDP_ERR_NOINIT;
0770     }
0771 
0772     if (priv->open == 0)
0773         return SPWTDP_ERR_EINVAL;
0774 
0775     /* Check pointer */
0776     if (val == NULL) {
0777         return SPWTDP_ERR_EINVAL;
0778     }
0779 
0780     val->preamble = REG_READ(&priv->regs->ts_tx_ctrl) & ETCTRL_PF;
0781     unsigned int * buffer = (unsigned int *) val->data;
0782     buffer[0] = REG_READ(&priv->regs->ts_tx_et[0]);
0783     buffer[1] = REG_READ(&priv->regs->ts_tx_et[1]);
0784     buffer[2] = REG_READ(&priv->regs->ts_tx_et[2]);
0785     buffer[3] = REG_READ(&priv->regs->ts_tx_et[3]);
0786     buffer[4] = REG_READ(&priv->regs->ts_tx_et[4]);
0787 
0788     return SPWTDP_ERR_OK;
0789 }
0790 
0791 int spwtdp_lat_et_get(void * spwtdp, spwtdp_time_t * val)
0792 {
0793     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0794 
0795     if (priv == NULL) {
0796         /* SPWTDP not initialized */
0797         return SPWTDP_ERR_NOINIT;
0798     }
0799 
0800     if (priv->open == 0)
0801         return SPWTDP_ERR_EINVAL;
0802 
0803     /* Check pointer */
0804     if (val == NULL) {
0805         return SPWTDP_ERR_EINVAL;
0806     }
0807 
0808     val->preamble = REG_READ(&priv->regs->lat_ctrl) & ETCTRL_PF;
0809     unsigned int * buffer = (unsigned int *) val->data;
0810     buffer[0] = REG_READ(&priv->regs->lat_et[0]);
0811     buffer[1] = REG_READ(&priv->regs->lat_et[1]);
0812     buffer[2] = REG_READ(&priv->regs->lat_et[2]);
0813     buffer[3] = REG_READ(&priv->regs->lat_et[3]);
0814     buffer[4] = REG_READ(&priv->regs->lat_et[4]);
0815 
0816     return SPWTDP_ERR_OK;
0817 }
0818 
0819 int spwtdp_cmd_et_get(void * spwtdp, spwtdp_time_t * val)
0820 {
0821     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0822 
0823     if (priv == NULL) {
0824         /* SPWTDP not initialized */
0825         return SPWTDP_ERR_NOINIT;
0826     }
0827 
0828     if (priv->open == 0)
0829         return SPWTDP_ERR_EINVAL;
0830 
0831     /* Check pointer */
0832     if (val == NULL) {
0833         return SPWTDP_ERR_EINVAL;
0834     }
0835 
0836     val->preamble = REG_READ(&priv->regs->cmd_ctrl) & ETCTRL_PF;
0837     unsigned int * buffer = (unsigned int *) val->data;
0838     buffer[0] = REG_READ(&priv->regs->cmd_et[0]);
0839     buffer[1] = REG_READ(&priv->regs->cmd_et[1]);
0840     buffer[2] = REG_READ(&priv->regs->cmd_et[2]);
0841     buffer[3] = REG_READ(&priv->regs->cmd_et[3]);
0842     buffer[4] = REG_READ(&priv->regs->cmd_et[4]);
0843 
0844     return SPWTDP_ERR_OK;
0845 }
0846 
0847 int spwtdp_initiator_tstx_conf(void * spwtdp, uint8_t tstc)
0848 {
0849     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0850 
0851     if (priv == NULL) {
0852         /* SPWTDP not initialized */
0853         return SPWTDP_ERR_NOINIT;
0854     }
0855 
0856     if (priv->open == 0)
0857         return SPWTDP_ERR_EINVAL;
0858 
0859     /* Check if configured as initiator */
0860     if (priv->initiator != 1)
0861         return SPWTDP_ERR_EINVAL;
0862 
0863     REG_WRITE(&priv->regs->ts_tx_ctrl,
0864           (((uint32_t)tstc) << TSTXCTRL_TSTC_BIT) & TSTXCTRL_TSTC);
0865 
0866     return SPWTDP_ERR_OK;
0867 }
0868 
0869 int spwtdp_initiator_cmd_et_set(void *spwtdp, spwtdp_time_t val)
0870 {
0871     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0872 
0873     if (priv == NULL) {
0874         /* SPWTDP not initialized */
0875         return SPWTDP_ERR_NOINIT;
0876     }
0877 
0878     if (priv->open == 0)
0879         return SPWTDP_ERR_EINVAL;
0880 
0881     /* Check if configured as initiator */
0882     if (priv->initiator != 1)
0883         return SPWTDP_ERR_EINVAL;
0884 
0885     unsigned int * buffer = (unsigned int *) val.data;
0886     REG_WRITE(&priv->regs->lat_et[0], buffer[0]);
0887     REG_WRITE(&priv->regs->lat_et[1], buffer[1]);
0888     REG_WRITE(&priv->regs->lat_et[2], buffer[2]);
0889     REG_WRITE(&priv->regs->lat_et[3], buffer[3]);
0890     REG_WRITE(&priv->regs->lat_et[4], buffer[4]);
0891 
0892 
0893     /* Take SPWTDP lock - Wait until we get semaphore */
0894     if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
0895         != RTEMS_SUCCESSFUL)
0896         return SPWTDP_ERR_ERROR;
0897 
0898     /* Signal new command */
0899     unsigned int ctrl = REG_READ(&priv->regs->cmd_ctrl);
0900     REG_WRITE(&priv->regs->cmd_ctrl, ctrl | CTRL_NC);
0901 
0902     rtems_semaphore_release(priv->sem);
0903 
0904     return SPWTDP_ERR_OK;
0905 }
0906 
0907 int spwtdp_initiator_cmd_spwtc_set(void *spwtdp, uint8_t spwtc)
0908 {
0909     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0910 
0911     if (priv == NULL) {
0912         /* SPWTDP not initialized */
0913         return SPWTDP_ERR_NOINIT;
0914     }
0915 
0916     if (priv->open == 0)
0917         return SPWTDP_ERR_EINVAL;
0918 
0919     /* Check if configured as initiator */
0920     if (priv->initiator != 1)
0921         return SPWTDP_ERR_EINVAL;
0922 
0923     /* Take SPWTDP lock - Wait until we get semaphore */
0924     if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
0925         != RTEMS_SUCCESSFUL)
0926         return SPWTDP_ERR_ERROR;
0927 
0928     unsigned int ctrl = (REG_READ(&priv->regs->cmd_ctrl) &~ CTRL_SPWTC);
0929     REG_WRITE(&priv->regs->cmd_ctrl,
0930           ctrl | (((uint32_t)spwtc << CTRL_SPWTC_BIT) & CTRL_SPWTC));
0931 
0932     rtems_semaphore_release(priv->sem);
0933 
0934     return SPWTDP_ERR_OK;
0935 }
0936 
0937 #define CTRL_TAR_MASK (CTRL_NC|CTRL_IS)
0938 int spwtdp_target_cmd_conf(void *spwtdp, uint8_t spwtc, uint16_t cpf,
0939                uint32_t options)
0940 {
0941     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0942 
0943     if (priv == NULL) {
0944         /* SPWTDP not initialized */
0945         return SPWTDP_ERR_NOINIT;
0946     }
0947 
0948     if (priv->open == 0)
0949         return SPWTDP_ERR_EINVAL;
0950 
0951     /* Check if configured as target */
0952     if (priv->target != 1)
0953         return SPWTDP_ERR_EINVAL;
0954 
0955     /* Take SPWTDP lock - Wait until we get semaphore */
0956     if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
0957         != RTEMS_SUCCESSFUL)
0958         return SPWTDP_ERR_ERROR;
0959 
0960     REG_WRITE(&priv->regs->cmd_ctrl, 
0961             (options & CTRL_TAR_MASK) |
0962             ((cpf << CTRL_CPF_BIT) & CTRL_CPF) |
0963             (((uint32_t)spwtc << CTRL_SPWTC_BIT) & CTRL_SPWTC));
0964 
0965     rtems_semaphore_release(priv->sem);
0966 
0967     return SPWTDP_ERR_OK;
0968 }
0969 
0970 int spwtdp_precision_get(void *spwtdp, uint8_t *fine, uint8_t *coarse)
0971 {
0972     struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
0973     int coarse_precision, fine_precision;
0974 
0975     if (priv == NULL) {
0976         /* SPWTDP not initialized */
0977         return SPWTDP_ERR_NOINIT;
0978     }
0979 
0980     if (priv->open == 0)
0981         return SPWTDP_ERR_EINVAL;
0982 
0983     unsigned int preamble = REG_READ(&priv->regs->dat_ctrl);
0984 
0985     if (preamble & 0x80) {
0986         DBG("Pfield second extension set: unknown format");
0987         return SPWTDP_ERR_ERROR;
0988     }
0989     if (!((preamble & 0x7000) == 0x2000 || (preamble & 0x7000) == 0x1000)) {
0990         DBG(" PField indicates not unsegmented code: unknown format");
0991         return SPWTDP_ERR_ERROR;
0992     }
0993     /*
0994      * coarse_precision = 32;
0995      * fine_precision = 24;
0996      */
0997     coarse_precision = ((preamble >> 10) & 0x3) + 1;
0998     if (preamble & 0x80)
0999         coarse_precision += (preamble >> 5) & 0x3;
1000     fine_precision = (preamble >> 8) & 0x3;
1001     if (preamble & 0x80)
1002         fine_precision += (preamble >> 2) & 0x7;
1003     if (coarse!=NULL)
1004         *coarse = coarse_precision;
1005     if (fine!=NULL)
1006         *fine = fine_precision;
1007 
1008     return SPWTDP_ERR_OK;
1009 }
1010