source: rtems/bsps/sparc/shared/time/grctm.c @ 11f3b9a

5
Last change on this file since 11f3b9a was 11f3b9a, checked in by Sebastian Huber <sebastian.huber@…>, on 11/26/18 at 14:55:38

bsps/sparc: Add grlib_malloc(), grlib_calloc()

This avoids a dependency to errno in device driver code.

  • Property mode set to 100644
File size: 8.2 KB
Line 
1/*  GRCTM - CCSDS Time Manager - register driver interface.
2 *
3 *  COPYRIGHT (c) 2009.
4 *  Cobham Gaisler AB.
5 *
6 *  The license and distribution terms for this file may be
7 *  found in the file LICENSE in this distribution or at
8 *  http://www.rtems.org/license/LICENSE.
9 */
10
11#include <drvmgr/drvmgr.h>
12#include <drvmgr/ambapp_bus.h>
13#include <stdlib.h>
14#include <string.h>
15
16#include <bsp/grctm.h>
17
18#include <grlib_impl.h>
19
20/* Private structure of GRCTM driver */
21struct grctm_priv {
22        struct drvmgr_dev *dev;
23        struct grctm_regs *regs;
24        int open;
25
26        grctm_isr_t user_isr;
27        void *user_isr_arg;
28
29        struct grctm_stats stats;
30};
31
32void grctm_isr(void *data);
33
34struct amba_drv_info grctm_drv_info;
35
36void *grctm_open(int minor)
37{
38        struct grctm_priv *priv;
39        struct drvmgr_dev *dev;
40
41        /* Get Device from Minor */
42        if ( drvmgr_get_dev(&grctm_drv_info.general, minor, &dev) ) {
43                return NULL;
44        }
45
46        priv = dev->priv;
47        if ( (priv == NULL) || priv->open )
48                return NULL;
49
50        /* Set initial state of software */
51        priv->open = 1;
52
53        /* Clear Statistics */
54        grctm_clr_stats(priv);
55        priv->user_isr = NULL;
56        priv->user_isr_arg = NULL;
57
58        return priv;
59}
60
61void grctm_close(void *grctm)
62{
63        struct grctm_priv *priv = (struct grctm_priv *)grctm;
64
65        if ( priv->open == 0 )
66                return;
67
68        /* Reset Hardware */
69        grctm_reset(priv);
70
71        priv->open = 0;
72}
73
74/* Hardware Reset of GRCTM */
75int grctm_reset(void *grctm)
76{
77        struct grctm_priv *priv = grctm;
78        struct grctm_regs *r = priv->regs;
79
80        r->grr = 0x55000001;
81
82        int i = 1000;
83        while ((r->grr & 1) && i > 0) {
84                i--;
85        }
86
87        return i ? 0 : -1;
88}
89
90void grctm_int_enable(void *grctm)
91{
92        struct grctm_priv *priv = (struct grctm_priv *)grctm;
93
94        /* Register and Enable Interrupt at Interrupt controller */
95        drvmgr_interrupt_register(priv->dev, 0, "grctm", grctm_isr, priv);
96}
97
98void grctm_int_disable(void *grctm)
99{
100        struct grctm_priv *priv = (struct grctm_priv *)grctm;
101
102        /* Enable Interrupt at Interrupt controller */
103        drvmgr_interrupt_unregister(priv->dev, 0, grctm_isr, priv);
104}
105
106void grctm_clr_stats(void *grctm)
107{
108        struct grctm_priv *priv = (struct grctm_priv *)grctm;
109
110        memset(&priv->stats, 0, sizeof(priv->stats));
111}
112
113void grctm_get_stats(void *grctm, struct grctm_stats *stats)
114{
115        struct grctm_priv *priv = (struct grctm_priv *)grctm;
116
117        memcpy(stats, &priv->stats, sizeof(priv->stats));
118}
119
120/* Enable external synchronisation (from grctm) */
121void grctm_enable_ext_sync(void *grctm)
122{
123        struct grctm_priv *priv = grctm;
124
125        priv->regs->gcr |= 0x55<<24 | 1<<9;
126}
127
128/* Disable external synchronisation (from grctm) */
129void grctm_disable_ext_sync(void *grctm)
130{
131        struct grctm_priv *priv = grctm;
132
133        priv->regs->gcr &= ~((0xAA<<24) | 1<<9);
134}
135
136/* Enable TimeWire synchronisation */
137void grctm_enable_tw_sync(void *grctm)
138{
139        struct grctm_priv *priv = grctm;
140
141        priv->regs->gcr |= 0x55<<24 | 1<<8;
142}
143
144/* Disable TimeWire synchronisation */
145void grctm_disable_tw_sync(void *grctm)
146{
147        struct grctm_priv *priv = grctm;
148
149        priv->regs->gcr &= ~((0xAA<<24) | 1<<8);
150}
151
152/* Disable frequency synthesizer from driving ET */
153void grctm_disable_fs(void *grctm)
154{
155        struct grctm_priv *priv = grctm;
156
157        priv->regs->gcr |= 0x55<<24 | 1<<7;
158}
159
160/* Enable frequency synthesizer to drive ET */
161void grctm_enable_fs(void *grctm)
162{
163        struct grctm_priv *priv = grctm;
164
165        priv->regs->gcr &= ~((0xAA<<24) | 1<<7);
166}
167
168/* Return elapsed coarse time */
169unsigned int grctm_get_et_coarse(void *grctm)
170{
171        struct grctm_priv *priv = grctm;
172
173        return priv->regs->etcr;
174}
175
176/* Return elapsed fine time */
177unsigned int grctm_get_et_fine(void *grctm)
178{
179        struct grctm_priv *priv = grctm;
180
181        return (priv->regs->etfr & 0xffffff00) >> 8;
182}
183
184/* Return elapsed time (coarse and fine) */
185unsigned long long grctm_get_et(void *grctm)
186{
187        return (((unsigned long)grctm_get_et_coarse(grctm)) << 24) | grctm_get_et_fine(grctm);
188}
189
190
191/* Return 1 if specified datation has been latched */
192int grctm_is_dat_latched(void *grctm, int dat)
193{
194        struct grctm_priv *priv = grctm;
195
196        return (priv->regs->gsr >> dat) & 1;
197}
198
199/* Set triggering edge of datation input */
200void grctm_set_dat_edge(void *grctm, int dat, int edge)
201{
202        struct grctm_priv *priv = grctm;
203
204        priv->regs->gcr &= ~((0xAA<<24) | 1 << (10+dat));
205        priv->regs->gcr |= 0x55<<24 | (edge&1) << (10+dat);
206}
207
208/* Return latched datation coarse time */
209unsigned int grctm_get_dat_coarse(void *grctm, int dat)
210{
211        struct grctm_priv *priv = grctm;
212
213        switch (dat) {
214        case 0 : return priv->regs->dcr0;
215        case 1 : return priv->regs->dcr1;
216        case 2 : return priv->regs->dcr2;
217        default: return -1;
218        }
219}
220
221/* Return latched datation fine time */
222unsigned int grctm_get_dat_fine(void *grctm, int dat)
223{
224        struct grctm_priv *priv = grctm;
225
226        switch (dat) {
227        case 0 : return (priv->regs->dfr0 & 0xffffff00) >> 8;
228        case 1 : return (priv->regs->dfr1 & 0xffffff00) >> 8;
229        case 2 : return (priv->regs->dfr2 & 0xffffff00) >> 8;
230        default: return -1;
231        }
232}
233
234
235/* Return latched datation ET */
236unsigned long long grctm_get_dat_et(void *grctm, int dat)
237{
238        return (((unsigned long)grctm_get_dat_coarse(grctm, dat)) << 24) |
239                grctm_get_dat_fine(grctm, dat);
240}
241
242
243/* Return current pulse configuration */
244unsigned int grctm_get_pulse_reg(void *grctm, int pulse)
245{
246        struct grctm_priv *priv = grctm;
247
248        return priv->regs->pdr[pulse];
249}
250
251/* Set pulse register */
252void grctm_set_pulse_reg(void *grctm, int pulse, unsigned int val)
253{
254        struct grctm_priv *priv = grctm;
255
256        priv->regs->pdr[pulse] = val;
257}
258
259/* Configure pulse: pp = period, pw = width, pl = level, en = enable */
260void grctm_cfg_pulse(void *grctm, int pulse, int pp, int pw, int pl, int en)
261{
262        grctm_set_pulse_reg(grctm, pulse, (pp&0xf)<<20 | (pw&0xf)<<16 | (pl&1)<<10 | (en&1)<<1);
263}
264
265/* Enable pulse output */
266void grctm_enable_pulse(void *grctm, int pulse)
267{
268        struct grctm_priv *priv = grctm;
269
270        priv->regs->pdr[pulse] |= 0x2;
271}
272
273/* Disable pulse output */
274void grctm_disable_pulse(void *grctm, int pulse)
275{
276        struct grctm_priv *priv = grctm;
277
278        priv->regs->pdr[pulse] &= ~0x2;
279}
280
281/* Clear interrupts */
282void grctm_clear_irqs(void *grctm, int irqs)
283{
284        struct grctm_priv *priv = grctm;
285
286        priv->regs->picr = irqs;
287}
288
289/* Enable interrupts */
290void grctm_enable_irqs(void *grctm, int irqs)
291{
292        struct grctm_priv *priv = grctm;
293
294        priv->regs->imr  = irqs;
295}
296
297/* Set Frequency synthesizer increment */
298void grctm_set_fs_incr(void *grctm, int incr)
299{
300        struct grctm_priv *priv = grctm;
301
302        priv->regs->fsir  = incr;
303}
304
305/* Set ET increment */
306void grctm_set_et_incr(void *grctm, int incr)
307{
308        struct grctm_priv *priv = grctm;
309
310        priv->regs->etir  = incr;
311}
312
313
314void grctm_isr(void *data)
315{
316        struct grctm_priv *priv = data;
317        struct grctm_stats *stats = &priv->stats;
318        unsigned int pimr = priv->regs->pimr;
319
320        if ( pimr == 0 )
321                return;
322
323        stats->nirqs++;
324        if (pimr & PULSE0_IRQ )
325                stats->pulse++;
326
327        /* Let user Handle Interrupt */
328        if ( priv->user_isr )
329                priv->user_isr(pimr, priv->user_isr_arg);
330}
331
332struct grctm_regs *grctm_get_regs(void *grctm)
333{
334        struct grctm_priv *priv = (struct grctm_priv *)grctm;
335
336        return priv->regs;
337}
338
339void grctm_int_register(void *grctm, grctm_isr_t func, void *data)
340{
341        struct grctm_priv *priv = (struct grctm_priv *)grctm;
342
343        priv->user_isr = func;
344        priv->user_isr_arg = data;
345}
346
347/*** INTERFACE TO DRIVER MANAGER ***/
348
349static int grctm_init2(struct drvmgr_dev *dev)
350{
351        struct amba_dev_info *ambadev;
352        struct ambapp_core *pnpinfo;
353        struct grctm_priv *priv;
354        struct grctm_regs *regs;
355
356        priv = grlib_calloc(1, sizeof(*priv));
357        if ( priv == NULL )
358                return -1;
359        priv->dev = dev;
360        dev->priv = priv;
361
362        /* Get device information from AMBA PnP information */
363        ambadev = (struct amba_dev_info *)dev->businfo;
364        if ( ambadev == NULL ) {
365                return -1;
366        }
367        pnpinfo = &ambadev->info;
368        regs = (struct grctm_regs *)pnpinfo->ahb_slv->start[0];
369
370        priv->regs = regs;
371
372        grctm_reset(priv);
373
374        return 0;
375}
376
377struct drvmgr_drv_ops grctm_ops =
378{
379        {NULL, grctm_init2, NULL, NULL},
380        NULL,
381        NULL
382};
383
384struct amba_dev_id grctm_ids[] =
385{
386        {VENDOR_GAISLER, GAISLER_GRCTM},
387        {0, 0}  /* Mark end of table */
388};
389
390struct amba_drv_info grctm_drv_info =
391{
392        {
393                DRVMGR_OBJ_DRV,                 /* Driver */
394                NULL,                           /* Next driver */
395                NULL,                           /* Device list */
396                DRIVER_AMBAPP_GAISLER_GRCTM_ID, /* Driver ID */
397                "GRCTM_DRV",                    /* Driver Name */
398                DRVMGR_BUS_TYPE_AMBAPP,         /* Bus Type */
399                &grctm_ops,
400                NULL,                           /* Funcs */
401                0,                              /* No devices yet */
402                0,
403        },
404        &grctm_ids[0]
405};
406
407/* Register the grctm Driver */
408void grctm_register(void)
409{
410        drvmgr_drv_register(&grctm_drv_info.general);
411}
Note: See TracBrowser for help on using the repository browser.