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

4.115
Last change on this file since e53daed was 5823bae8, checked in by Daniel Hellstrom <daniel@…>, on 02/27/15 at 13:03:15

LEON: move driver headers to bsp/ directory

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