source: rtems/bsps/sparc/shared/spw/spwtdp.c @ 6dc0b5f

5
Last change on this file since 6dc0b5f was 6dc0b5f, checked in by Javier Jalle <javier.jalle@…>, on 07/21/17 at 12:18:50

leon, spwtdp: Initial driver commit

  • Property mode set to 100644
File size: 24.1 KB
Line 
1/*  SPWTDP - SpaceWire Time Distribution Protocol. The driver provides
2 *  device discovery and interrupt management.
3 *
4 *  COPYRIGHT (c) 2017.
5 *  Cobham Gaisler AB
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.rtems.com/license/LICENSE.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <stddef.h>
16#include <rtems.h>
17#include <rtems/bspIo.h>
18#include <drvmgr/drvmgr.h>
19#include <ambapp.h>
20#include <drvmgr/ambapp_bus.h>
21#include <bsp.h>
22#include <bsp/spwtdp.h>
23
24/* Use interrupt lock privmitives compatible with SMP defined in
25 * RTEMS 4.11.99 and higher.
26 */
27#if (((__RTEMS_MAJOR__ << 16) | (__RTEMS_MINOR__ << 8) | __RTEMS_REVISION__) >= 0x040b63)
28
29/* map via rtems_interrupt_lock_* API: */
30#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock)
31#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name)
32#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level)
33#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level)
34#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level)
35#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level)
36#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k
37#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k)
38
39#else
40
41/* maintain single-core compatibility with older versions of RTEMS: */
42#define SPIN_DECLARE(name)
43#define SPIN_INIT(lock, name)
44#define SPIN_LOCK(lock, level)
45#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_disable(level)
46#define SPIN_UNLOCK(lock, level)
47#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_enable(level)
48#define SPIN_IRQFLAGS(k) rtems_interrupt_level k
49#define SPIN_ISR_IRQFLAGS(k)
50
51#ifdef RTEMS_SMP
52#error SMP mode not compatible with these interrupt lock primitives
53#endif
54
55#endif
56
57/*#define STATIC*/
58#define STATIC static
59
60/*#define INLINE*/
61#define INLINE inline
62
63/*#define UNUSED*/
64#define UNUSED __attribute__((unused))
65
66#define DEBUG 1
67
68#ifdef DEBUG
69#define DBG(x...) printf(x)
70#else
71#define DBG(x...)
72#endif
73
74/* Memory and HW Registers Access routines. All 32-bit access routines */
75#define REG_WRITE(addr, val) \
76        (*(volatile unsigned int *)(addr) = (unsigned int)(val))
77#define REG_READ(addr) (*(volatile unsigned int *)(addr))
78
79/*
80 * Configuration register definitions
81 * DEFINED in header
82 */
83
84/*
85 * Control register definitions
86 * DEFINED in header
87 */
88
89/*
90 * TSTX Control register definitions
91 */
92#define TSTXCTRL_TSTC (0xff<<TSTXCTRL_TSTC_BIT)
93#define ETCTRL_PF (0xffff<<ETCTRL_PF_BIT)
94
95#define TSTXCTRL_TSTC_BIT 24
96#define ETCTRL_PF_BIT 0
97
98#define DEVNAME_LEN 11
99/* Private structure of SPWTDP driver. */
100struct spwtdp_priv {
101        char devname[DEVNAME_LEN];
102        struct drvmgr_dev *dev; /* Device */
103        struct spwtdp_regs *regs;
104        int open;
105        int index;
106        int initiator; /* Initiator configured */
107        int target; /* Target configured */
108        int freq; /* Frequency configured */
109
110        /* Spin-lock ISR protection */
111        SPIN_DECLARE(devlock);
112
113        /* Driver semaphore */
114        rtems_id sem;
115        spwtdp_isr_t isr;
116        void * isr_arg;
117};
118int spwtdp_count = 0;
119static struct spwtdp_priv *priv_tab[SPWTDP_MAX];
120
121
122STATIC void spwtdp_isr(void *data);
123STATIC int spwtdp_hw_reset(struct spwtdp_priv *priv);
124STATIC int spwtdp_init2(struct drvmgr_dev *dev);
125
126struct drvmgr_drv_ops spwtdp_ops =
127{
128        {NULL, spwtdp_init2, NULL, NULL},
129        NULL,
130        NULL
131};
132
133struct amba_dev_id spwtdp_ids[] =
134{
135        {VENDOR_GAISLER, GAISLER_SPWTDP},
136        {0, 0}  /* Mark end of table */
137};
138
139struct amba_drv_info spwtdp_drv_info =
140{
141        {
142                DRVMGR_OBJ_DRV,                 /* Driver */
143                NULL,                           /* Next driver */
144                NULL,                           /* Device list */
145                DRIVER_AMBAPP_GAISLER_SPWTDP_ID,/* Driver ID */
146                "SPWTDP_DRV",                   /* Driver Name */
147                DRVMGR_BUS_TYPE_AMBAPP,         /* Bus Type */
148                &spwtdp_ops,
149                NULL,                           /* Funcs */
150                0,                              /* No devices yet */
151                sizeof(struct spwtdp_priv),     /* Let DrvMgr allocate priv */
152        },
153        &spwtdp_ids[0]
154};
155
156/* Register the SPWTDP Driver */
157void spwtdp_register_drv(void)
158{
159        DBG("Registering SPWTDP driver\n");
160        drvmgr_drv_register(&spwtdp_drv_info.general);
161}
162
163STATIC int spwtdp_init(struct spwtdp_priv *priv)
164{
165        struct amba_dev_info *ainfo = priv->dev->businfo;
166        struct ambapp_apb_info *apb;
167
168        /* Get device information from AMBA PnP information */
169        if (ainfo == NULL) {
170                return -1;
171        }
172        apb = ainfo->info.apb_slv;
173        priv->regs = (struct spwtdp_regs *)apb->start;
174
175        spwtdp_hw_reset(priv);
176        /* Only support 56 bits counter */
177        if (REG_READ(&priv->regs->dat_ctrl) != 0x2f00) {
178                DBG("SPWTDP only supports 56 bit precission counters.\n");
179                return -1;
180        }
181        DBG("SPWTDP driver initialized\n");
182
183        return 0;
184}
185
186/*** INTERFACE TO DRIVER MANAGER ***/
187STATIC int spwtdp_init2(struct drvmgr_dev *dev)
188{
189        int status;
190        struct spwtdp_priv *priv;
191
192        DBG("SPWTDP[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
193
194        if (spwtdp_count >= SPWTDP_MAX)
195                return DRVMGR_ENORES;
196
197        priv = dev->priv;
198        if (priv == NULL)
199                return DRVMGR_NOMEM;
200
201        /* Register device */
202        priv->dev = dev;
203        priv->index = spwtdp_count;
204        priv_tab[priv->index] = priv;
205        snprintf(priv->devname, DEVNAME_LEN, "spwtdp%01u", priv->index);
206        spwtdp_count++;
207
208        /* Initialize Semaphore */
209        if (rtems_semaphore_create(
210                rtems_build_name('S', 'T', 'P', '0' + priv->index), 1,
211                RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | \
212                RTEMS_NO_INHERIT_PRIORITY | RTEMS_LOCAL | \
213                RTEMS_NO_PRIORITY_CEILING, 0, &priv->sem) != RTEMS_SUCCESSFUL) {
214                priv->sem = RTEMS_ID_NONE;
215                return DRVMGR_FAIL;
216        }
217
218        /* Initialize SPWTDP Hardware */
219        status = spwtdp_init(priv);
220        if (status) {
221                printk("Failed to initialize spwtdp driver %d\n", status);
222                return -1;
223        }
224
225        return DRVMGR_OK;
226}
227
228/* Hardware Reset of SPWTDP */
229STATIC int spwtdp_hw_reset(struct spwtdp_priv *priv)
230{
231        int i = 1000;
232        SPIN_IRQFLAGS(irqflags);
233
234        SPIN_LOCK_IRQ(&priv->devlock, irqflags);
235
236        /* Clear interrupts */
237        REG_WRITE(&priv->regs->ists, SPWTDP_IRQ_WCLEAR);
238
239        /* Reset the SPWTDP core */
240        REG_WRITE(&priv->regs->conf[0], CONF0_RS);
241
242        /* Wait for reset */
243        while ((REG_READ(&priv->regs->conf[0]) & CONF0_RS) && (i > 0)) {
244                i--;
245        }
246
247        SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
248
249        return ((i > 0)? SPWTDP_ERR_OK : SPWTDP_ERR_ERROR);
250}
251
252int spwtdp_reset(void *spwtdp)
253{
254        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
255
256        /* Check priv and unregister isr */
257        int ret = spwtdp_isr_unregister(spwtdp);
258        if (ret != SPWTDP_ERR_OK)
259                return ret;
260
261        priv->initiator=0;
262        priv->target=0;
263        priv->freq=0;
264
265        return spwtdp_hw_reset(priv);
266}
267
268void *spwtdp_open(int dev_no)
269{
270        struct spwtdp_priv *priv;
271
272        if (dev_no >= spwtdp_count)
273                return NULL;
274
275        /* Get Device */
276        priv = priv_tab[dev_no];
277        if ((priv == NULL)||(priv->open == 1)) {
278                return NULL;
279        }
280
281        /* Set initial state of software */
282        priv->open = 1;
283
284        return priv;
285}
286
287int spwtdp_close(void *spwtdp)
288{
289        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
290
291        /* Check priv and reset core */
292        int ret = spwtdp_reset(spwtdp);
293        if (ret != SPWTDP_ERR_OK)
294                return ret;
295
296        priv->open = 0;
297        return SPWTDP_ERR_OK;
298}
299
300int spwtdp_freq_setup(void *spwtdp, uint32_t fsinc, uint32_t cv, uint8_t etinc)
301{
302        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
303
304        /* Check priv */
305        if (priv == NULL)
306                return SPWTDP_ERR_NOINIT;
307
308        if (priv->open == 0)
309                return SPWTDP_ERR_EINVAL;
310
311        /* Take SPWTDP lock - Wait until we get semaphore */
312        if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
313                != RTEMS_SUCCESSFUL)
314                return SPWTDP_ERR_ERROR;
315
316        REG_WRITE(&priv->regs->conf[1], fsinc & CONF1_FSINC);
317        REG_WRITE(&priv->regs->conf[2],
318                ((cv<<CONF2_CV_BIT) & CONF2_CV) |
319                ((uint32_t)etinc & CONF2_ETINC));
320
321        rtems_semaphore_release(priv->sem);
322        priv->freq = 1;
323
324        return SPWTDP_ERR_OK;
325}
326
327#define CONF0_INI_MASK (CONF0_EP|CONF0_ET|CONF0_SP|CONF0_SE|CONF0_LE| \
328                CONF0_TD)
329int spwtdp_initiator_conf(void *spwtdp, uint8_t mapping, uint32_t options)
330{
331        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
332
333        /* Check priv */
334        if (priv == NULL)
335                return SPWTDP_ERR_NOINIT;
336
337        if (priv->open == 0)
338                return SPWTDP_ERR_EINVAL;
339
340        /* Check if configured as target */
341        if (priv->target == 1)
342                return SPWTDP_ERR_EINVAL;
343
344        /* Take SPWTDP lock - Wait until we get semaphore */
345        if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
346                != RTEMS_SUCCESSFUL)
347                return SPWTDP_ERR_ERROR;
348
349        unsigned int conf0 = REG_READ(&priv->regs->conf[0]);
350        conf0 &= ~(CONF0_INI_MASK|CONF0_MAP);
351        REG_WRITE(&priv->regs->conf[0],
352                        conf0 | (options & CONF0_INI_MASK) |
353                        (((uint32_t)mapping << CONF0_MAP_BIT) & CONF0_MAP));
354
355        priv->initiator = 1;
356
357        rtems_semaphore_release(priv->sem);
358
359        return SPWTDP_ERR_OK;
360}
361
362#define CONF0_TAR_MASK (CONF0_JE|CONF0_ST|CONF0_EP|CONF0_ET|CONF0_SP| \
363                CONF0_SE|CONF0_LE|CONF0_TD|CONF0_ME)
364int spwtdp_target_conf(void *spwtdp, uint8_t mapping, uint32_t options)
365{
366        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
367
368        /* Check priv */
369        if (priv == NULL)
370                return SPWTDP_ERR_NOINIT;
371
372        if (priv->open == 0)
373                return SPWTDP_ERR_EINVAL;
374
375        /* Check if configured as initiator */
376        if (priv->initiator == 1)
377                return SPWTDP_ERR_EINVAL;
378
379        /* Take SPWTDP lock - Wait until we get semaphore */
380        if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
381                != RTEMS_SUCCESSFUL)
382                return SPWTDP_ERR_ERROR;
383
384        unsigned int conf0 = REG_READ(&priv->regs->conf[0]);
385        conf0 &= ~(CONF0_TAR_MASK|CONF0_MAP);
386        REG_WRITE(&priv->regs->conf[0],
387                        conf0 | (options & CONF0_TAR_MASK) |
388                        (((uint32_t)mapping << CONF0_MAP_BIT) & CONF0_MAP));
389
390        priv->initiator = 1;
391
392        rtems_semaphore_release(priv->sem);
393
394        return SPWTDP_ERR_OK;
395}
396
397int spwtdp_initiator_int_conf(void *spwtdp, uint8_t stm, uint8_t inrx,
398                              uint8_t intx)
399{
400        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
401
402        /* Check priv */
403        if (priv == NULL)
404                return SPWTDP_ERR_NOINIT;
405
406        if (priv->open == 0)
407                return SPWTDP_ERR_EINVAL;
408
409        /* Check if configured as initiator */
410        if (priv->initiator != 1)
411                return SPWTDP_ERR_EINVAL;
412
413        REG_WRITE(&priv->regs->conf[3],
414                        (((uint32_t)stm << CONF3_STM_BIT) & CONF3_STM) |
415                        (((uint32_t)inrx << CONF3_INRX_BIT) & CONF3_INRX) |
416                        (((uint32_t)intx << CONF3_INTX_BIT) & CONF3_INTX));
417
418        return SPWTDP_ERR_OK;
419}
420
421int spwtdp_target_int_conf(void *spwtdp, uint8_t inrx, uint8_t intx,
422                           uint32_t options)
423{
424        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
425
426        /* Check priv */
427        if (priv == NULL) {
428                return SPWTDP_ERR_NOINIT;
429        }
430
431        if (priv->open == 0)
432                return SPWTDP_ERR_EINVAL;
433
434        /* Check if configured as target */
435        if (priv->target != 1)
436                return SPWTDP_ERR_EINVAL;
437
438        REG_WRITE(&priv->regs->conf[3],
439                        (options & CONF3_DI) |
440                        (((uint32_t)inrx << CONF3_INRX_BIT) & CONF3_INRX) |
441                        (((uint32_t)intx << CONF3_INTX_BIT) & CONF3_INTX));
442
443        return SPWTDP_ERR_OK;
444}
445
446int spwtdp_initiator_enable(void *spwtdp)
447{
448        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
449
450        /* Check priv */
451        if (priv == NULL) {
452                return SPWTDP_ERR_NOINIT;
453        }
454
455        if (priv->open == 0)
456                return SPWTDP_ERR_EINVAL;
457
458        /* Check if configured as initiator */
459        if (priv->initiator != 1)
460                return SPWTDP_ERR_EINVAL;
461
462        /* Check if frequency is configured */
463        if (priv->freq != 1)
464                return SPWTDP_ERR_EINVAL;
465
466        /* Take SPWTDP lock - Wait until we get semaphore */
467        if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
468                != RTEMS_SUCCESSFUL)
469                return SPWTDP_ERR_ERROR;
470
471        unsigned int conf0 = REG_READ(&priv->regs->conf[0]);
472        REG_WRITE(&priv->regs->conf[0], conf0 | CONF0_TE);
473
474        rtems_semaphore_release(priv->sem);
475
476        return SPWTDP_ERR_OK;
477}
478
479int spwtdp_target_enable(void *spwtdp)
480{
481        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
482
483        /* Check priv */
484        if (priv == NULL)
485                return SPWTDP_ERR_NOINIT;
486
487        if (priv->open == 0)
488                return SPWTDP_ERR_EINVAL;
489
490        /* Check if configured as target */
491        if (priv->target != 1)
492                return SPWTDP_ERR_EINVAL;
493
494        /* Check if frequency is configured */
495        if (priv->freq != 1)
496                return SPWTDP_ERR_EINVAL;
497
498        /* Take SPWTDP lock - Wait until we get semaphore */
499        if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
500                != RTEMS_SUCCESSFUL)
501                return SPWTDP_ERR_ERROR;
502
503        unsigned int conf0 = REG_READ(&priv->regs->conf[0]);
504        REG_WRITE(&priv->regs->conf[0], conf0 | CONF0_RE);
505
506        rtems_semaphore_release(priv->sem);
507
508        return SPWTDP_ERR_OK;
509}
510
511int spwtdp_initiator_disable(void *spwtdp)
512{
513        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
514
515        /* Check priv */
516        if (priv == NULL)
517                return SPWTDP_ERR_NOINIT;
518
519        if (priv->open == 0)
520                return SPWTDP_ERR_EINVAL;
521
522        /* Take SPWTDP lock - Wait until we get semaphore */
523        if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
524                != RTEMS_SUCCESSFUL)
525                return SPWTDP_ERR_ERROR;
526
527        unsigned int conf0 = REG_READ(&priv->regs->conf[0]);
528        REG_WRITE(&priv->regs->conf[0], conf0 & ~(CONF0_TE));
529
530        rtems_semaphore_release(priv->sem);
531
532        return SPWTDP_ERR_OK;
533}
534
535int spwtdp_target_disable(void *spwtdp)
536{
537        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
538
539        /* Check priv */
540        if (priv == NULL)
541                return SPWTDP_ERR_NOINIT;
542
543        if (priv->open == 0)
544                return SPWTDP_ERR_EINVAL;
545
546        /* Take SPWTDP lock - Wait until we get semaphore */
547        if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
548                != RTEMS_SUCCESSFUL)
549                return SPWTDP_ERR_ERROR;
550
551        unsigned int conf0 = REG_READ(&priv->regs->conf[0]);
552        REG_WRITE(&priv->regs->conf[0], conf0 & ~(CONF0_RE));
553
554        rtems_semaphore_release(priv->sem);
555
556        return SPWTDP_ERR_OK;
557}
558
559/* Get and Clear status */
560int spwtdp_status(void *spwtdp, uint32_t *sts, uint32_t clrmask)
561{
562        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
563
564        if (priv == NULL) {
565                /* SPWTDP not initialized */
566                return SPWTDP_ERR_NOINIT;
567        }
568
569        unsigned int status = REG_READ(&priv->regs->stat[0]);
570        REG_WRITE(&priv->regs->stat[0], status & clrmask);
571
572        if (sts != NULL)
573                *sts = status;
574
575        return SPWTDP_ERR_OK;
576}
577
578/* Get and Clear interrupts */
579int spwtdp_interrupt_status(void *spwtdp, uint32_t *sts, uint32_t clrmask)
580{
581        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
582        SPIN_IRQFLAGS(irqflags);
583
584        if (priv == NULL) {
585                /* SPWTDP not initialized */
586                return SPWTDP_ERR_NOINIT;
587        }
588
589        SPIN_LOCK_IRQ(&priv->devlock, irqflags);
590        unsigned int status = REG_READ(&priv->regs->ists);
591        REG_WRITE(&priv->regs->ists, status & clrmask);
592        SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
593
594        if (sts != NULL)
595                *sts = status;
596
597        return SPWTDP_ERR_OK;
598}
599
600/* Unmask interrupts */
601int spwtdp_interrupt_unmask(void *spwtdp, uint32_t irqmask)
602{
603        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
604
605        if (priv == NULL) {
606                /* SPWTDP not initialized */
607                return SPWTDP_ERR_NOINIT;
608        }
609
610        if (priv->open == 0)
611                return SPWTDP_ERR_EINVAL;
612
613        unsigned int ctrl = REG_READ(&priv->regs->ien);
614        REG_WRITE(&priv->regs->ien, ctrl | irqmask);
615
616        return SPWTDP_ERR_OK;
617}
618
619/* Mask interrupts */
620int spwtdp_interrupt_mask(void *spwtdp, uint32_t irqmask)
621{
622        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
623
624        if (priv == NULL) {
625                /* SPWTDP not initialized */
626                return SPWTDP_ERR_NOINIT;
627        }
628
629        if (priv->open == 0)
630                return SPWTDP_ERR_EINVAL;
631
632        unsigned int ctrl = REG_READ(&priv->regs->ien);
633        REG_WRITE(&priv->regs->ien, ctrl & ~(irqmask));
634
635        return SPWTDP_ERR_OK;
636}
637
638int spwtdp_isr_register(void *spwtdp, spwtdp_isr_t func, void *data)
639{
640        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
641        SPIN_ISR_IRQFLAGS(irqflags);
642
643        if (priv == NULL) {
644                /* SPWTDP not initialized */
645                return SPWTDP_ERR_NOINIT;
646        }
647
648        if (priv->open == 0)
649                return SPWTDP_ERR_EINVAL;
650
651        /* Check isr */
652        if (func == NULL) {
653                /* No ISR */
654                return SPWTDP_ERR_EINVAL;
655        }
656
657        priv->isr = func;
658        priv->isr_arg = data;
659
660        /* Register and Enable Interrupt at Interrupt controller */
661        drvmgr_interrupt_register(priv->dev, 0, "spwtdp", spwtdp_isr, priv);
662
663        /* Enable AMBA Interrupts */
664        SPIN_LOCK(&priv->devlock, irqflags);
665        unsigned int cfg0 = REG_READ(&priv->regs->conf[0]);
666        REG_WRITE(&priv->regs->conf[0], cfg0 | CONF0_AE);
667        SPIN_UNLOCK(&priv->devlock, irqflags);
668
669        return SPWTDP_ERR_OK;
670}
671
672int spwtdp_isr_unregister(void *spwtdp)
673{
674        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
675        SPIN_ISR_IRQFLAGS(irqflags);
676
677        /* Disable IRQS (and check for priv!=NULL) */
678        int ret=spwtdp_interrupt_mask(spwtdp, SPWTDP_IRQ_WCLEAR);
679        if (ret != SPWTDP_ERR_OK)
680                return ret;
681
682        /* Disable AMBA Interrupts */
683        SPIN_LOCK(&priv->devlock, irqflags);
684        unsigned int cfg0 = REG_READ(&priv->regs->conf[0]);
685        REG_WRITE(&priv->regs->conf[0], cfg0 & ~(CONF0_AE));
686        SPIN_UNLOCK(&priv->devlock, irqflags);
687
688        /* Disable Interrupt at Interrupt controller */
689        drvmgr_interrupt_unregister(priv->dev, 0, spwtdp_isr, priv);
690
691        /* Unregister isr */
692        priv->isr = NULL;
693        priv->isr_arg = NULL;
694
695        return SPWTDP_ERR_OK;
696}
697
698STATIC void spwtdp_isr(void *arg)
699{
700        struct spwtdp_priv *priv = arg;
701        unsigned int ists = REG_READ(&priv->regs->ists);
702        SPIN_ISR_IRQFLAGS(irqflags);
703
704        /* Return if the SPWTDP didn't generate the IRQ */
705        if (ists == 0)
706                return;
707
708        SPIN_LOCK(&priv->devlock, irqflags);
709        REG_WRITE(&priv->regs->ists, ists); /* clear handled interrupt events */
710        SPIN_UNLOCK(&priv->devlock, irqflags);
711
712        /* Let user Handle Interrupt */
713        if (priv->isr!=NULL)
714                priv->isr(ists, priv->isr_arg);
715
716        return;
717}
718
719int spwtdp_dat_et_get(void * spwtdp, spwtdp_time_t * val)
720{
721        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
722
723        if (priv == NULL) {
724                /* SPWTDP not initialized */
725                return SPWTDP_ERR_NOINIT;
726        }
727
728        if (priv->open == 0)
729                return SPWTDP_ERR_EINVAL;
730
731        /* Check pointer */
732        if (val == NULL) {
733                return SPWTDP_ERR_EINVAL;
734        }
735
736        val->preamble = REG_READ(&priv->regs->dat_ctrl) & ETCTRL_PF;
737        unsigned int * buffer = (unsigned int *) val->data;
738        buffer[0] = REG_READ(&priv->regs->dat_et[0]);
739        buffer[1] = REG_READ(&priv->regs->dat_et[1]);
740        buffer[2] = REG_READ(&priv->regs->dat_et[2]);
741        buffer[3] = REG_READ(&priv->regs->dat_et[3]);
742        buffer[4] = REG_READ(&priv->regs->dat_et[4]);
743
744        return SPWTDP_ERR_OK;
745}
746
747int spwtdp_tsrx_et_get(void * spwtdp, spwtdp_time_t * val)
748{
749        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
750
751        if (priv == NULL) {
752                /* SPWTDP not initialized */
753                return SPWTDP_ERR_NOINIT;
754        }
755
756        if (priv->open == 0)
757                return SPWTDP_ERR_EINVAL;
758
759        /* Check pointer */
760        if (val == NULL) {
761                return SPWTDP_ERR_EINVAL;
762        }
763
764        val->preamble = REG_READ(&priv->regs->ts_rx_ctrl) & ETCTRL_PF;
765        unsigned int * buffer = (unsigned int *) val->data;
766        buffer[0] = REG_READ(&priv->regs->ts_rx_et[0]);
767        buffer[1] = REG_READ(&priv->regs->ts_rx_et[1]);
768        buffer[2] = REG_READ(&priv->regs->ts_rx_et[2]);
769        buffer[3] = REG_READ(&priv->regs->ts_rx_et[3]);
770        buffer[4] = REG_READ(&priv->regs->ts_rx_et[4]);
771
772        return SPWTDP_ERR_OK;
773}
774
775int spwtdp_tstx_et_get(void * spwtdp, spwtdp_time_t * val)
776{
777        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
778
779        if (priv == NULL) {
780                /* SPWTDP not initialized */
781                return SPWTDP_ERR_NOINIT;
782        }
783
784        if (priv->open == 0)
785                return SPWTDP_ERR_EINVAL;
786
787        /* Check pointer */
788        if (val == NULL) {
789                return SPWTDP_ERR_EINVAL;
790        }
791
792        val->preamble = REG_READ(&priv->regs->ts_tx_ctrl) & ETCTRL_PF;
793        unsigned int * buffer = (unsigned int *) val->data;
794        buffer[0] = REG_READ(&priv->regs->ts_tx_et[0]);
795        buffer[1] = REG_READ(&priv->regs->ts_tx_et[1]);
796        buffer[2] = REG_READ(&priv->regs->ts_tx_et[2]);
797        buffer[3] = REG_READ(&priv->regs->ts_tx_et[3]);
798        buffer[4] = REG_READ(&priv->regs->ts_tx_et[4]);
799
800        return SPWTDP_ERR_OK;
801}
802
803int spwtdp_lat_et_get(void * spwtdp, spwtdp_time_t * val)
804{
805        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
806
807        if (priv == NULL) {
808                /* SPWTDP not initialized */
809                return SPWTDP_ERR_NOINIT;
810        }
811
812        if (priv->open == 0)
813                return SPWTDP_ERR_EINVAL;
814
815        /* Check pointer */
816        if (val == NULL) {
817                return SPWTDP_ERR_EINVAL;
818        }
819
820        val->preamble = REG_READ(&priv->regs->lat_ctrl) & ETCTRL_PF;
821        unsigned int * buffer = (unsigned int *) val->data;
822        buffer[0] = REG_READ(&priv->regs->lat_et[0]);
823        buffer[1] = REG_READ(&priv->regs->lat_et[1]);
824        buffer[2] = REG_READ(&priv->regs->lat_et[2]);
825        buffer[3] = REG_READ(&priv->regs->lat_et[3]);
826        buffer[4] = REG_READ(&priv->regs->lat_et[4]);
827
828        return SPWTDP_ERR_OK;
829}
830
831int spwtdp_cmd_et_get(void * spwtdp, spwtdp_time_t * val)
832{
833        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
834
835        if (priv == NULL) {
836                /* SPWTDP not initialized */
837                return SPWTDP_ERR_NOINIT;
838        }
839
840        if (priv->open == 0)
841                return SPWTDP_ERR_EINVAL;
842
843        /* Check pointer */
844        if (val == NULL) {
845                return SPWTDP_ERR_EINVAL;
846        }
847
848        val->preamble = REG_READ(&priv->regs->cmd_ctrl) & ETCTRL_PF;
849        unsigned int * buffer = (unsigned int *) val->data;
850        buffer[0] = REG_READ(&priv->regs->cmd_et[0]);
851        buffer[1] = REG_READ(&priv->regs->cmd_et[1]);
852        buffer[2] = REG_READ(&priv->regs->cmd_et[2]);
853        buffer[3] = REG_READ(&priv->regs->cmd_et[3]);
854        buffer[4] = REG_READ(&priv->regs->cmd_et[4]);
855
856        return SPWTDP_ERR_OK;
857}
858
859int spwtdp_initiator_tstx_conf(void * spwtdp, uint8_t tstc)
860{
861        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
862
863        if (priv == NULL) {
864                /* SPWTDP not initialized */
865                return SPWTDP_ERR_NOINIT;
866        }
867
868        if (priv->open == 0)
869                return SPWTDP_ERR_EINVAL;
870
871        /* Check if configured as initiator */
872        if (priv->initiator != 1)
873                return SPWTDP_ERR_EINVAL;
874
875        REG_WRITE(&priv->regs->ts_tx_ctrl,
876                  (((uint32_t)tstc) << TSTXCTRL_TSTC_BIT) & TSTXCTRL_TSTC);
877
878        return SPWTDP_ERR_OK;
879}
880
881int spwtdp_initiator_cmd_et_set(void *spwtdp, spwtdp_time_t val)
882{
883        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
884
885        if (priv == NULL) {
886                /* SPWTDP not initialized */
887                return SPWTDP_ERR_NOINIT;
888        }
889
890        if (priv->open == 0)
891                return SPWTDP_ERR_EINVAL;
892
893        /* Check if configured as initiator */
894        if (priv->initiator != 1)
895                return SPWTDP_ERR_EINVAL;
896
897        unsigned int * buffer = (unsigned int *) val.data;
898        REG_WRITE(&priv->regs->lat_et[0], buffer[0]);
899        REG_WRITE(&priv->regs->lat_et[1], buffer[1]);
900        REG_WRITE(&priv->regs->lat_et[2], buffer[2]);
901        REG_WRITE(&priv->regs->lat_et[3], buffer[3]);
902        REG_WRITE(&priv->regs->lat_et[4], buffer[4]);
903
904
905        /* Take SPWTDP lock - Wait until we get semaphore */
906        if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
907                != RTEMS_SUCCESSFUL)
908                return SPWTDP_ERR_ERROR;
909
910        /* Signal new command */
911        unsigned int ctrl = REG_READ(&priv->regs->cmd_ctrl);
912        REG_WRITE(&priv->regs->cmd_ctrl, ctrl | CTRL_NC);
913
914        rtems_semaphore_release(priv->sem);
915
916        return SPWTDP_ERR_OK;
917}
918
919int spwtdp_initiator_cmd_spwtc_set(void *spwtdp, uint8_t spwtc)
920{
921        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
922
923        if (priv == NULL) {
924                /* SPWTDP not initialized */
925                return SPWTDP_ERR_NOINIT;
926        }
927
928        if (priv->open == 0)
929                return SPWTDP_ERR_EINVAL;
930
931        /* Check if configured as initiator */
932        if (priv->initiator != 1)
933                return SPWTDP_ERR_EINVAL;
934
935        /* Take SPWTDP lock - Wait until we get semaphore */
936        if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
937                != RTEMS_SUCCESSFUL)
938                return SPWTDP_ERR_ERROR;
939
940        unsigned int ctrl = (REG_READ(&priv->regs->cmd_ctrl) &~ CTRL_SPWTC);
941        REG_WRITE(&priv->regs->cmd_ctrl,
942                  ctrl | (((uint32_t)spwtc << CTRL_SPWTC_BIT) & CTRL_SPWTC));
943
944        rtems_semaphore_release(priv->sem);
945
946        return SPWTDP_ERR_OK;
947}
948
949#define CTRL_TAR_MASK (CTRL_NC|CTRL_IS)
950int spwtdp_target_cmd_conf(void *spwtdp, uint8_t spwtc, uint16_t cpf,
951                           uint32_t options)
952{
953        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
954
955        if (priv == NULL) {
956                /* SPWTDP not initialized */
957                return SPWTDP_ERR_NOINIT;
958        }
959
960        if (priv->open == 0)
961                return SPWTDP_ERR_EINVAL;
962
963        /* Check if configured as target */
964        if (priv->target != 1)
965                return SPWTDP_ERR_EINVAL;
966
967        /* Take SPWTDP lock - Wait until we get semaphore */
968        if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
969                != RTEMS_SUCCESSFUL)
970                return SPWTDP_ERR_ERROR;
971
972        REG_WRITE(&priv->regs->cmd_ctrl,
973                        (options & CTRL_TAR_MASK) |
974                        ((cpf << CTRL_CPF_BIT) & CTRL_CPF) |
975                        (((uint32_t)spwtc << CTRL_SPWTC_BIT) & CTRL_SPWTC));
976
977        rtems_semaphore_release(priv->sem);
978
979        return SPWTDP_ERR_OK;
980}
981
982int spwtdp_precision_get(void *spwtdp, uint8_t *fine, uint8_t *coarse)
983{
984        struct spwtdp_priv *priv = (struct spwtdp_priv *)spwtdp;
985        int coarse_precision, fine_precision;
986
987        if (priv == NULL) {
988                /* SPWTDP not initialized */
989                return SPWTDP_ERR_NOINIT;
990        }
991
992        if (priv->open == 0)
993                return SPWTDP_ERR_EINVAL;
994
995        unsigned int preamble = REG_READ(&priv->regs->dat_ctrl);
996
997        if (preamble & 0x80) {
998                DBG("Pfield second extension set: unknown format");
999                return SPWTDP_ERR_ERROR;
1000        }
1001        if (!((preamble & 0x7000) == 0x2000 || (preamble & 0x7000) == 0x1000)) {
1002                DBG(" PField indicates not unsegmented code: unknown format");
1003                return SPWTDP_ERR_ERROR;
1004        }
1005        /*
1006         * coarse_precision = 32;
1007         * fine_precision = 24;
1008         */
1009        coarse_precision = ((preamble >> 10) & 0x3) + 1;
1010        if (preamble & 0x80)
1011                coarse_precision += (preamble >> 5) & 0x3;
1012        fine_precision = (preamble >> 8) & 0x3;
1013        if (preamble & 0x80)
1014                fine_precision += (preamble >> 2) & 0x7;
1015        if (coarse!=NULL)
1016                *coarse = coarse_precision;
1017        if (fine!=NULL)
1018                *fine = fine_precision;
1019
1020        return SPWTDP_ERR_OK;
1021}
1022
Note: See TracBrowser for help on using the repository browser.