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

5
Last change on this file since e4633241 was 9ed3266, checked in by Joel Sherrill <joel@…>, on 04/23/17 at 16:47:53

amba/ahbstat.c: Include <rtems/bspIo.h>

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