source: rtems/c/src/lib/libbsp/sparc/shared/spw/grspw_router.c @ 3bb4122

4.115
Last change on this file since 3bb4122 was 3bb4122, checked in by Daniel Hellstrom <daniel@…>, on 02/23/15 at 12:02:39

LEON: added new drivers to the LEON2/LEON3 BSPs

Most drivers use the Driver Manager for device probing, they
work on AMBA-over-PCI systems if PCI is big-endian.

New APIs:

  • GPIO Library, interfaced to GRGPIO
  • GENIRQ, Generic interrupt service implementation helper

New GRLIB Drivers:

  • ACTEL 1553 RT, user interface is similar to 1553 BRM driver
  • GR1553 (1553 BC, RT and BM core)
  • AHBSTAT (AHB error status core)
  • GRADCDAC (Core interfacing to ADC/DAC hardware)
  • GRGPIO (GPIO port accessed from GPIO Library)
  • MCTRL (Memory controller settings configuration)
  • GRETH (10/100/1000 Ethernet driver using Driver manager)
  • GRPWM (Pulse Width Modulation core)
  • SPICTRL (SPI master interface)
  • GRSPW_ROUTER (SpaceWire? Router AMBA configuration interface)
  • GRCTM (SpaceCraft? on-board Time Management core)
  • SPWCUC (Time distribution over SpaceWire?)
  • GRTC (SpaceCraft? up-link Tele core)
  • GRTM (SpaceCraft? down-link Tele Metry core)

GR712RC ASIC specific interfaces:

  • GRASCS
  • CANMUX (select between OCCAN and SATCAN)
  • SATCAN
  • SLINK
  • Property mode set to 100644
File size: 12.9 KB
Line 
1/* GRSPW ROUTER APB-Register Driver.
2 *
3 * COPYRIGHT (c) 2010.
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.com/license/LICENSE.
9 */
10
11#include <rtems.h>
12#include <rtems/libio.h>
13#include <stdio.h>
14
15#include <drvmgr/drvmgr.h>
16#include <drvmgr/ambapp_bus.h>
17#include <grspw_router.h>
18
19#define ROUTER_DBG(args...)
20
21#define REG_READ(adr) (*(volatile unsigned int *)(adr))
22#define REG_WRITE(adr, value) (*(volatile unsigned int *)(adr) = (value))
23
24struct router_regs {
25        unsigned int resv1;             /* 0x000 */
26        unsigned int psetup[255];       /* 0x004 */
27        unsigned int resv2[32];         /* 0x400 */
28        unsigned int routes[224];       /* 0x480 */
29        unsigned int pctrl[32];         /* 0x800 */
30        unsigned int psts[32];          /* 0x880 */
31        unsigned int treload[32];       /* 0x900 */
32        unsigned int resv3[32];         /* 0x980 */
33        unsigned int cfgsts;            /* 0xA00 */
34        unsigned int timecode;          /* 0xA04 */
35        unsigned int ver;               /* 0xA08 */
36        unsigned int idiv;              /* 0xA0C */
37        unsigned int cfgwe;             /* 0xA10 */
38        unsigned int tprescaler;        /* 0xA14 */
39        unsigned int resv4[123];        /* 0xA18 */
40        unsigned int charo[31];         /* 0xC04 */
41        unsigned int resv5;             /* 0xC80 */
42        unsigned int chari[31];         /* 0xC84 */
43        unsigned int resv6;             /* 0xD00 */
44        unsigned int pkto[31];          /* 0xD04 */
45        unsigned int resv7;             /* 0xD80 */
46        unsigned int pkti[31];          /* 0xD84 */
47};
48
49struct router_priv {
50        char devName[32];
51        struct drvmgr_dev *dev;
52        struct router_regs *regs;
53        int minor;
54        int open;
55        struct router_hw_info hwinfo;
56        int nports;
57};
58
59static rtems_device_driver router_initialize(
60        rtems_device_major_number  major,
61        rtems_device_minor_number  minor,
62        void                    * arg
63        );
64
65static rtems_device_driver router_open(
66        rtems_device_major_number major,
67        rtems_device_minor_number minor,
68        void                    * arg
69        );
70
71static rtems_device_driver router_close(
72        rtems_device_major_number major,
73        rtems_device_minor_number minor,
74        void                    * arg
75        );
76
77static rtems_device_driver router_control(
78        rtems_device_major_number major,
79        rtems_device_minor_number minor,
80        void                    * arg
81        );
82
83#define ROUTER_DRIVER_TABLE_ENTRY \
84  { router_initialize, \
85    router_open, \
86    router_close, \
87    NULL, \
88    NULL, \
89    router_control }
90
91void router_hwinfo(struct router_priv *priv, struct router_hw_info *hwinfo);
92
93static rtems_driver_address_table router_driver = ROUTER_DRIVER_TABLE_ENTRY;
94static int router_driver_io_registered = 0;
95static rtems_device_major_number router_driver_io_major = 0;
96
97/******************* Driver manager interface ***********************/
98
99/* Driver prototypes */
100int router_register_io(rtems_device_major_number *m);
101
102int router_init2(struct drvmgr_dev *dev);
103
104struct drvmgr_drv_ops router_ops =
105{
106        .init = {NULL,  router_init2, NULL, NULL},
107        .remove = NULL,
108        .info = NULL
109};
110
111struct amba_dev_id router_ids[] =
112{
113        {VENDOR_GAISLER, GAISLER_SPW_ROUTER},
114        {0, 0}          /* Mark end of table */
115};
116
117struct amba_drv_info router_drv_info =
118{
119        {
120                DRVMGR_OBJ_DRV,                 /* Driver */
121                NULL,                           /* Next driver */
122                NULL,                           /* Device list */
123                DRIVER_AMBAPP_GAISLER_SPW_ROUTER_ID,/* Driver ID */
124                "ROUTER_DRV",                   /* Driver Name */
125                DRVMGR_BUS_TYPE_AMBAPP,         /* Bus Type */
126                &router_ops,
127                NULL,                           /* Funcs */
128                0,                              /* No devices yet */
129                sizeof(struct router_priv),     /* Let DRVMGR allocate for us */
130        },
131        &router_ids[0],
132};
133
134void router_register_drv (void)
135{
136        drvmgr_drv_register(&router_drv_info.general);
137}
138
139int router_init2(struct drvmgr_dev *dev)
140{
141        struct router_priv *priv = dev->priv;
142        struct amba_dev_info *ambadev;
143        struct ambapp_core *pnpinfo;
144        char prefix[32];
145        rtems_status_code status;
146
147        if ( priv == NULL )
148                return DRVMGR_NOMEM;
149        priv->dev = dev;
150
151        /* Do initialization */
152        if ( router_driver_io_registered == 0) {
153                /* Register the I/O driver only once for all cores */
154                if ( router_register_io(&router_driver_io_major) ) {
155                        /* Failed to register I/O driver */
156                        return DRVMGR_FAIL;
157                }
158
159                router_driver_io_registered = 1;
160        }
161
162        /* Get device information from AMBA PnP information */
163        ambadev = (struct amba_dev_info *)priv->dev->businfo;
164        if ( ambadev == NULL ) {
165                return DRVMGR_FAIL;
166        }
167        pnpinfo = &ambadev->info;
168        priv->regs = (struct router_regs *)pnpinfo->ahb_slv->start[0];
169        priv->minor = dev->minor_drv;
170
171        /* Register character device in registered region */
172        router_hwinfo(priv, &priv->hwinfo);
173        priv->open = 0;
174        priv->nports = priv->hwinfo.nports_spw + priv->hwinfo.nports_amba +
175                        priv->hwinfo.nports_fifo;
176        if ( (priv->nports < 2) || (priv->nports > 32) )
177                return DRVMGR_FAIL;
178
179        /* Get Filesystem name prefix */
180        prefix[0] = '\0';
181        if ( drvmgr_get_dev_prefix(dev, prefix) ) {
182                /* Failed to get prefix, make sure of a unique FS name
183                 * by using the driver minor.
184                 */
185                sprintf(priv->devName, "/dev/router%d", dev->minor_drv);
186        } else {
187                /* Got special prefix, this means we have a bus prefix
188                 * And we should use our "bus minor"
189                 */
190                sprintf(priv->devName, "/dev/%srouter%d", prefix, dev->minor_bus);
191        }
192
193        /* Register Device */
194        status = rtems_io_register_name(priv->devName, router_driver_io_major, dev->minor_drv);
195        if (status != RTEMS_SUCCESSFUL) {
196                return DRVMGR_FAIL;
197        }
198
199        return DRVMGR_OK;
200}
201
202int router_register_io(rtems_device_major_number *m)
203{
204        rtems_status_code r;
205
206        if ((r = rtems_io_register_driver(0, &router_driver, m)) == RTEMS_SUCCESSFUL) {
207                ROUTER_DBG("ROUTER driver successfully registered, major: %d\n", *m);
208        } else {
209                switch(r) {
210                case RTEMS_TOO_MANY:
211                        printk("ROUTER rtems_io_register_driver failed: RTEMS_TOO_MANY\n");
212                        return -1;
213                case RTEMS_INVALID_NUMBER: 
214                        printk("ROUTER rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n");
215                        return -1;
216                case RTEMS_RESOURCE_IN_USE:
217                        printk("ROUTER rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n");
218                        return -1;
219                default:
220                        printk("ROUTER rtems_io_register_driver failed\n");
221                        return -1;
222                }
223        }
224        return 0;
225}
226
227static rtems_device_driver router_initialize(
228        rtems_device_major_number major,
229        rtems_device_minor_number minor,
230        void *arg
231        )
232{
233        return RTEMS_SUCCESSFUL;
234}
235
236static rtems_device_driver router_open(
237        rtems_device_major_number major,
238        rtems_device_minor_number minor,
239        void                    * arg
240        )
241{
242        struct router_priv *priv;
243        struct drvmgr_dev *dev;
244
245        if ( drvmgr_get_dev(&router_drv_info.general, minor, &dev) ) {
246                ROUTER_DBG("Wrong minor %d\n", minor);
247                return RTEMS_INVALID_NAME;
248        }
249        priv = (struct router_priv *)dev->priv;
250
251        if ( !priv || priv->open ) {
252                return RTEMS_RESOURCE_IN_USE;
253        }
254
255        priv->open = 1;
256
257        return RTEMS_SUCCESSFUL;
258}
259
260static rtems_device_driver router_close(
261        rtems_device_major_number major,
262        rtems_device_minor_number minor,
263        void                    * arg
264        )
265{
266        struct router_priv *priv;
267        struct drvmgr_dev *dev;
268
269        if ( drvmgr_get_dev(&router_drv_info.general, minor, &dev) ) {
270                ROUTER_DBG("Wrong minor %d\n", minor);
271                return RTEMS_INVALID_NAME;
272        }
273        priv = (struct router_priv *)dev->priv;
274
275        priv->open = 0;
276
277        return RTEMS_SUCCESSFUL;
278}
279
280void router_hwinfo(struct router_priv *priv, struct router_hw_info *hwinfo)
281{
282        unsigned int tmp;
283
284        tmp = REG_READ(&priv->regs->cfgsts);
285        hwinfo->nports_spw   = (tmp >> 27) & 0x1f;
286        hwinfo->nports_amba  = (tmp >> 22) & 0x1f;
287        hwinfo->nports_fifo  = (tmp >> 17) & 0x1f;
288        hwinfo->timers_avail = (tmp >>  1) & 0x1;
289        hwinfo->pnp_avail    = (tmp >>  0) & 0x1;
290
291        tmp = REG_READ(&priv->regs->ver);
292        hwinfo->ver_major   = (tmp >> 24) & 0xff;
293        hwinfo->ver_minor   = (tmp >> 16) & 0xff;
294        hwinfo->ver_patch   = (tmp >>  8) & 0xff;
295        hwinfo->iid         = (tmp >>  0) & 0xff;
296}
297
298int router_config_set(struct router_priv *priv, struct router_config *cfg)
299{
300        int i;
301
302        if ( (cfg->flags & (ROUTER_FLG_TPRES|ROUTER_FLG_TRLD)) &&
303             !priv->hwinfo.timers_avail ) {
304                return RTEMS_NOT_IMPLEMENTED;
305        }
306
307        /* Write only configuration bits in Config register */
308        if ( cfg->flags & ROUTER_FLG_CFG ) {
309                REG_WRITE(&priv->regs->cfgsts, cfg->config & ~0x4);
310        }
311
312        /* Write Instance ID to Version Register */
313        if ( cfg->flags & ROUTER_FLG_IID ) {
314                REG_WRITE(&priv->regs->ver, cfg->iid);
315        }
316
317        /* Write startup-clock-divisor Register */
318        if ( cfg->flags & ROUTER_FLG_IDIV ) {
319                REG_WRITE(&priv->regs->idiv, cfg->idiv);
320        }
321
322        /* Write Timer Prescaler Register */
323        if ( cfg->flags & ROUTER_FLG_TPRES ) {
324                REG_WRITE(&priv->regs->tprescaler, cfg->timer_prescaler);
325        }
326
327        /* Write Timer Reload Register */
328        if ( cfg->flags & ROUTER_FLG_TRLD ) {
329                for (i=0; i<=priv->nports; i++)
330                        REG_WRITE(&priv->regs->treload[i], cfg->timer_reload[i]);
331        }
332
333        return 0;
334}
335
336int router_config_read(struct router_priv *priv, struct router_config *cfg)
337{
338        int i;
339
340        cfg->config = REG_READ(&priv->regs->cfgsts) & ~0xffff0007;
341        cfg->iid = REG_READ(&priv->regs->ver) & 0xff;
342        cfg->idiv = REG_READ(&priv->regs->idiv) & 0xff;
343        cfg->timer_prescaler = REG_READ(&priv->regs->tprescaler);
344        for (i=0; i<=priv->nports; i++)
345                cfg->timer_reload[i] = REG_READ(&priv->regs->treload[i]);
346
347        return 0;
348}
349
350int router_routes_set(struct router_priv *priv, struct router_routes *routes)
351{
352        int i;
353        for (i=0; i<224; i++)
354                REG_WRITE(&priv->regs->routes[i], routes->route[i]);
355        return 0;
356}
357
358int router_routes_read(struct router_priv *priv, struct router_routes *routes)
359{
360        int i;
361        for (i=0; i<224; i++)
362                routes->route[i] = REG_READ(&priv->regs->routes[i]);
363        return 0;
364}
365
366int router_ps_set(struct router_priv *priv, struct router_ps *ps)
367{
368        int i;
369        unsigned int *p = &ps->ps[0];
370        for (i=0; i<255; i++,p++)
371                REG_WRITE(&priv->regs->psetup[i], *p);
372        return 0;
373}
374
375int router_ps_read(struct router_priv *priv, struct router_ps *ps)
376{
377        int i;
378        unsigned int *p = &ps->ps[0];
379        for (i=0; i<255; i++,p++)
380                REG_WRITE(&priv->regs->psetup[i], *p);
381        return 0;
382}
383
384int router_we_set(struct router_priv *priv, int we)
385{
386        REG_WRITE(&priv->regs->cfgwe, we & 0x1);
387        return 0;
388}
389
390int router_port_ctrl(struct router_priv *priv, struct router_port *port)
391{
392        unsigned int ctrl, sts;
393
394        if ( port->port > priv->nports )
395                return RTEMS_INVALID_NAME;
396
397        ctrl = port->ctrl;
398        if ( port->flag & ROUTER_PORTFLG_GET_CTRL ) {
399                ctrl = REG_READ(&priv->regs->pctrl[port->port]);
400        }
401        sts = port->sts;
402        if ( port->flag & ROUTER_PORTFLG_GET_STS ) {
403                sts = REG_READ(&priv->regs->psts[port->port]);
404        }
405
406        if ( port->flag & ROUTER_PORTFLG_SET_CTRL ) {
407                REG_WRITE(&priv->regs->pctrl[port->port], port->ctrl);
408        }
409        if ( port->flag & ROUTER_PORTFLG_SET_STS ) {
410                REG_WRITE(&priv->regs->psts[port->port], port->sts);
411        }
412
413        port->ctrl = ctrl;
414        port->sts = sts;
415        return 0;
416}
417
418int router_cfgsts_set(struct router_priv *priv, unsigned int cfgsts)
419{
420        REG_WRITE(&priv->regs->cfgsts, cfgsts);
421        return 0;
422}
423
424int router_cfgsts_read(struct router_priv *priv, unsigned int *cfgsts)
425{
426        *cfgsts = REG_READ(&priv->regs->cfgsts);
427        return 0;
428}
429
430int router_tc_read(struct router_priv *priv, unsigned int *tc)
431{
432        *tc = REG_READ(&priv->regs->timecode);
433        return 0;
434}
435
436static rtems_device_driver router_control(
437        rtems_device_major_number major,
438        rtems_device_minor_number minor,
439        void                    * arg
440        )
441{
442        struct router_priv *priv;
443        struct drvmgr_dev *dev;
444        rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *) arg;
445        void *argp = (void *)ioarg->buffer;
446
447        if ( drvmgr_get_dev(&router_drv_info.general, minor, &dev) ) {
448                ROUTER_DBG("Wrong minor %d\n", minor);
449                return RTEMS_INVALID_NAME;
450        }
451        priv = (struct router_priv *)dev->priv;
452
453        ioarg->ioctl_return = 0;
454        switch (ioarg->command) {
455
456        /* Get Hardware support/information available */
457        case GRSPWR_IOCTL_HWINFO:
458        {
459                struct router_hw_info *hwinfo = argp;
460                router_hwinfo(priv, hwinfo);
461                break;
462        }
463
464        /* Set Router Configuration */
465        case GRSPWR_IOCTL_CFG_SET:
466        {
467                struct router_config *cfg = argp;
468                return router_config_set(priv, cfg);
469        }
470
471        /* Read Router Configuration */
472        case GRSPWR_IOCTL_CFG_GET:
473        {
474                struct router_config *cfg = argp;
475                router_config_read(priv, cfg);
476                break;
477        }
478
479        /* Routes */
480        case GRSPWR_IOCTL_ROUTES_SET:
481        {
482                struct router_routes *routes = argp;
483                return router_routes_set(priv, routes);
484        }
485
486        case GRSPWR_IOCTL_ROUTES_GET:
487        {
488                struct router_routes *routes = argp;
489                router_routes_read(priv, routes);
490                break;
491        }
492
493        /* Port Setup */
494        case GRSPWR_IOCTL_PS_SET:
495        {
496                struct router_ps *ps = argp;
497                return router_ps_set(priv, ps);
498        }
499
500        case GRSPWR_IOCTL_PS_GET:
501        {
502                struct router_ps *ps = argp;
503                router_ps_read(priv, ps);
504                break;
505        }
506
507        /* Set configuration write enable */
508        case GRSPWR_IOCTL_WE_SET:
509        {
510                return router_we_set(priv, (int)argp);
511        }
512
513        /* Set/Get Port Control/Status */
514        case GRSPWR_IOCTL_PORT:
515        {
516                struct router_port *port = argp;
517                int result;
518                if ( (result=router_port_ctrl(priv, port)) )
519                        return result;
520                break;
521        }
522
523        /* Set Router Configuration/Status Register */
524        case GRSPWR_IOCTL_CFGSTS_SET:
525        {
526                return router_cfgsts_set(priv, (int)argp);
527        }
528
529        /* Get Router Configuration/Status Register */
530        case GRSPWR_IOCTL_CFGSTS_GET:
531        {
532                unsigned int *cfgsts = argp;
533                router_cfgsts_read(priv, cfgsts);
534                break;
535        }
536
537        /* Get Current Time-Code Register */
538        case GRSPWR_IOCTL_TC_GET:
539        {
540                unsigned int *tc = argp;
541                router_tc_read(priv, tc);
542                break;
543        }
544
545        default: return RTEMS_NOT_IMPLEMENTED;
546        }
547
548        return 0;
549}
Note: See TracBrowser for help on using the repository browser.