source: rtems/c/src/lib/libbsp/sparc/shared/amba/ahbstat.c @ 4a7d1026

4.11
Last change on this file since 4a7d1026 was 4a7d1026, checked in by Daniel Hellstrom <daniel@…>, on Apr 13, 2015 at 8:25:52 AM

sparc bsps: updated license to rtems.org

  • Property mode set to 100644
File size: 4.9 KB
Line 
1/*  AHB Status register driver
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 <stdint.h>
12#include <drvmgr/drvmgr.h>
13#include <drvmgr/ambapp_bus.h>
14
15#include <bsp/ahbstat.h>
16
17void ahbstat_isr(void *arg);
18
19/* AHB fail interrupt callback to user. This function is declared weak so that
20 * the user can define a function pointer variable containing the address
21 * responsible for handling errors
22 *
23 * minor              Index of AHBSTAT hardware
24 * regs               Register address of AHBSTAT
25 * status             AHBSTAT status register at IRQ
26 * failing_address    AHBSTAT Failing address register at IRQ
27 *
28 * * User return
29 *  0: print error onto terminal with printk and reenable AHBSTAT
30 *  1: just re-enable AHBSTAT
31 *  2: just print error
32 *  3: do nothing, let user do custom handling
33 */
34int (*ahbstat_error)(
35        int minor,
36        struct ahbstat_regs *regs,
37        uint32_t status,
38        uint32_t failing_address
39        ) __attribute__((weak)) = NULL;
40
41#define AHBSTAT_STS_CE_BIT 9
42#define AHBSTAT_STS_NE_BIT 8
43#define AHBSTAT_STS_HW_BIT 7
44#define AHBSTAT_STS_HM_BIT 3
45#define AHBSTAT_STS_HS_BIT 0
46
47#define AHBSTAT_STS_CE (1 << AHBSTAT_STS_CE_BIT)
48#define AHBSTAT_STS_NE (1 << AHBSTAT_STS_NE_BIT)
49#define AHBSTAT_STS_HW (1 << AHBSTAT_STS_HW_BIT)
50#define AHBSTAT_STS_HM (0xf << AHBSTAT_STS_HM_BIT)
51#define AHBSTAT_STS_HS (0x7 << AHBSTAT_STS_HS_BIT)
52
53struct ahbstat_priv {
54        struct drvmgr_dev *dev;
55        struct ahbstat_regs *regs;
56        int minor;
57        uint32_t last_status;
58        uint32_t last_address;
59};
60
61static int ahbstat_init2(struct drvmgr_dev *dev);
62
63struct drvmgr_drv_ops ahbstat_ops =
64{
65        .init = {NULL, ahbstat_init2, NULL, NULL},
66        .remove = NULL,
67        .info = NULL
68};
69
70struct amba_dev_id ahbstat_ids[] =
71{
72        {VENDOR_GAISLER, GAISLER_AHBSTAT},
73        {0, 0}          /* Mark end of table */
74};
75
76struct amba_drv_info ahbstat_drv_info =
77{
78        {
79                DRVMGR_OBJ_DRV,                 /* Driver */
80                NULL,                           /* Next driver */
81                NULL,                           /* Device list */
82                DRIVER_AMBAPP_GAISLER_AHBSTAT_ID,/* Driver ID */
83                "AHBSTAT_DRV",                  /* Driver Name */
84                DRVMGR_BUS_TYPE_AMBAPP,         /* Bus Type */
85                &ahbstat_ops,
86                NULL,                           /* Funcs */
87                0,                              /* No devices yet */
88                sizeof(struct ahbstat_priv),
89        },
90        &ahbstat_ids[0]
91};
92
93void ahbstat_register_drv (void)
94{
95        drvmgr_drv_register(&ahbstat_drv_info.general);
96}
97
98static int ahbstat_init2(struct drvmgr_dev *dev)
99{
100        struct ahbstat_priv *priv;
101        struct amba_dev_info *ambadev;
102
103        priv = dev->priv;
104        if (!priv)
105                return DRVMGR_NOMEM;
106        priv->dev = dev;
107
108        /* Get device information from AMBA PnP information */
109        ambadev = (struct amba_dev_info *)dev->businfo;
110        if (ambadev == NULL)
111                return DRVMGR_FAIL;
112        priv->regs = (struct ahbstat_regs *)ambadev->info.apb_slv->start;
113        priv->minor = dev->minor_drv;
114
115        /* Initialize hardware */
116        priv->regs->status = 0;
117
118        /* Install IRQ handler */
119        drvmgr_interrupt_register(dev, 0, "ahbstat", ahbstat_isr, priv);
120
121        return DRVMGR_OK;
122}
123
124void ahbstat_isr(void *arg)
125{
126        struct ahbstat_priv *priv = arg;
127        uint32_t fadr, status;
128        int rc;
129
130        /* Get hardware status */
131        status = priv->regs->status;
132        if ((status & AHBSTAT_STS_NE) == 0)
133                return;
134
135        /* IRQ generated by AHBSTAT core... handle it here */
136
137        /* Get Failing address */
138        fadr = priv->regs->failing;
139
140        priv->last_status = status;
141        priv->last_address = fadr;
142
143        /* Let user handle error, default to print the error and reenable HW
144         *
145         * User return
146         *  0: print error and reenable AHBSTAT
147         *  1: just reenable AHBSTAT
148         *  2: just print error reenable
149         *  3: do nothing
150         */
151        rc = 0;
152        if (ahbstat_error != NULL)
153                rc = ahbstat_error(priv->minor, priv->regs, status, fadr);
154
155        if ((rc & 0x1) == 0) {
156                printk("\n### AHBSTAT: %s %s error of size %lu by master %d"
157                        " at 0x%08lx\n",
158                        status & AHBSTAT_STS_CE ? "single" : "non-correctable",
159                        status & AHBSTAT_STS_HW ? "write" : "read",
160                        (status & AHBSTAT_STS_HS) >> AHBSTAT_STS_HS_BIT,
161                        (status & AHBSTAT_STS_HM) >> AHBSTAT_STS_HM_BIT,
162                        fadr);
163        }
164
165        if ((rc & 0x2) == 0) {
166                /* Trigger new interrupts */
167                priv->regs->status = 0;
168        }
169}
170
171/* Get Last received AHB Error
172 *
173 * Return
174 *   0: No error received
175 *   1: Error Received, last status and address stored into argument pointers
176 *  -1: No such AHBSTAT device
177 */
178int ahbstat_last_error(int minor, uint32_t *status, uint32_t *address)
179{
180        struct drvmgr_dev *dev;
181        struct ahbstat_priv *priv;
182
183        if (drvmgr_get_dev(&ahbstat_drv_info.general, minor, &dev)) {
184                return -1;
185        }
186        priv = (struct ahbstat_priv *)dev->priv;
187
188        *status = priv->last_status;
189        *address = priv->last_address;
190
191        return (priv->last_status & AHBSTAT_STS_NE) >> AHBSTAT_STS_NE_BIT;
192}
193
194/* Get AHBSTAT registers address from minor. NULL returned if no such device */
195struct ahbstat_regs *ahbstat_get_regs(int minor)
196{
197        struct drvmgr_dev *dev;
198        struct ahbstat_priv *priv;
199
200        if (drvmgr_get_dev(&ahbstat_drv_info.general, minor, &dev)) {
201                return NULL;
202        }
203        priv = (struct ahbstat_priv *)dev->priv;
204
205        return priv->regs;
206}
Note: See TracBrowser for help on using the repository browser.