[3bb4122] | 1 | /* GR1553B driver, used by BC, RT and/or BM 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 |
---|
[4a7d1026] | 8 | * http://www.rtems.org/license/LICENSE. |
---|
[3bb4122] | 9 | */ |
---|
| 10 | |
---|
| 11 | #include <stdlib.h> |
---|
[31720925] | 12 | #include <grlib/ambapp_bus.h> |
---|
[3bb4122] | 13 | |
---|
[31720925] | 14 | #include <grlib/gr1553b.h> |
---|
[3bb4122] | 15 | |
---|
[31720925] | 16 | #include <grlib/grlib_impl.h> |
---|
[11f3b9a] | 17 | |
---|
[3bb4122] | 18 | /* Driver Manager interface for BC, RT, BM, BRM, BC-BM and RT-BM */ |
---|
| 19 | |
---|
| 20 | #define GR1553B_WRITE_REG(adr, val) *(volatile uint32_t *)(adr) = (val) |
---|
| 21 | #define GR1553B_READ_REG(adr) (*(volatile uint32_t *)(adr)) |
---|
| 22 | |
---|
| 23 | #define FEAT_BC 0x1 |
---|
| 24 | #define FEAT_RT 0x2 |
---|
| 25 | #define FEAT_BM 0x4 |
---|
| 26 | |
---|
| 27 | #define ALLOC_BC 0x1 |
---|
| 28 | #define ALLOC_RT 0x2 |
---|
| 29 | #define ALLOC_BM 0x4 |
---|
| 30 | |
---|
| 31 | struct gr1553_device { |
---|
| 32 | struct drvmgr_dev *dev; |
---|
| 33 | int features; |
---|
| 34 | int alloc; |
---|
| 35 | }; |
---|
| 36 | |
---|
| 37 | struct gr1553_device_feature { |
---|
| 38 | struct gr1553_device_feature *next; |
---|
| 39 | struct gr1553_device *dev; |
---|
| 40 | int minor; |
---|
| 41 | }; |
---|
| 42 | |
---|
| 43 | /* Device lists */ |
---|
[b787bead] | 44 | static struct gr1553_device_feature *gr1553_bm_root = NULL; |
---|
| 45 | static struct gr1553_device_feature *gr1553_rt_root = NULL; |
---|
| 46 | static struct gr1553_device_feature *gr1553_bc_root = NULL; |
---|
[3bb4122] | 47 | |
---|
| 48 | /* Driver registered */ |
---|
[b787bead] | 49 | static int gr1553_driver_registerd = 0; |
---|
[3bb4122] | 50 | |
---|
| 51 | /* Add 'feat' to linked list pointed to by 'root'. A minor is also assigned. */ |
---|
[b787bead] | 52 | static void gr1553_list_add |
---|
[3bb4122] | 53 | ( |
---|
| 54 | struct gr1553_device_feature **root, |
---|
| 55 | struct gr1553_device_feature *feat |
---|
| 56 | ) |
---|
| 57 | { |
---|
| 58 | int minor; |
---|
| 59 | struct gr1553_device_feature *curr; |
---|
| 60 | |
---|
| 61 | if ( *root == NULL ) { |
---|
| 62 | *root = feat; |
---|
| 63 | feat->next = NULL; |
---|
| 64 | feat->minor = 0; |
---|
| 65 | return; |
---|
| 66 | } |
---|
| 67 | |
---|
| 68 | minor = 0; |
---|
| 69 | retry_new_minor: |
---|
| 70 | curr = *root; |
---|
| 71 | while ( curr->next ) { |
---|
| 72 | if ( curr->minor == minor ) { |
---|
| 73 | minor++; |
---|
| 74 | goto retry_new_minor; |
---|
| 75 | } |
---|
| 76 | curr = curr->next; |
---|
| 77 | } |
---|
| 78 | |
---|
| 79 | feat->next = NULL; |
---|
| 80 | feat->minor = minor; |
---|
| 81 | curr->next = feat; |
---|
| 82 | } |
---|
| 83 | |
---|
[b787bead] | 84 | static struct gr1553_device_feature *gr1553_list_find |
---|
[3bb4122] | 85 | ( |
---|
| 86 | struct gr1553_device_feature *root, |
---|
| 87 | int minor |
---|
| 88 | ) |
---|
| 89 | { |
---|
| 90 | struct gr1553_device_feature *curr = root; |
---|
| 91 | while ( curr ) { |
---|
| 92 | if ( curr->minor == minor ) { |
---|
| 93 | return curr; |
---|
| 94 | } |
---|
| 95 | curr = curr->next; |
---|
| 96 | } |
---|
| 97 | return NULL; |
---|
| 98 | } |
---|
| 99 | |
---|
| 100 | struct drvmgr_dev **gr1553_bc_open(int minor) |
---|
| 101 | { |
---|
| 102 | struct gr1553_device_feature *feat; |
---|
| 103 | |
---|
| 104 | feat = gr1553_list_find(gr1553_bc_root, minor); |
---|
| 105 | if ( feat == NULL ) |
---|
| 106 | return NULL; |
---|
| 107 | |
---|
| 108 | /* Only possible to allocate is RT and BC is free, |
---|
| 109 | * this is beacuse it is not possible to use the |
---|
| 110 | * RT and the BC at the same time. |
---|
| 111 | */ |
---|
| 112 | if ( feat->dev->alloc & (ALLOC_BC|ALLOC_RT) ) |
---|
| 113 | return NULL; |
---|
| 114 | |
---|
| 115 | /* Alloc BC device */ |
---|
| 116 | feat->dev->alloc |= ALLOC_BC; |
---|
| 117 | |
---|
| 118 | return &feat->dev->dev; |
---|
| 119 | } |
---|
| 120 | |
---|
| 121 | void gr1553_bc_close(struct drvmgr_dev **dev) |
---|
| 122 | { |
---|
| 123 | struct gr1553_device *d = (struct gr1553_device *)dev; |
---|
| 124 | |
---|
| 125 | d->alloc &= ~ALLOC_BC; |
---|
| 126 | } |
---|
| 127 | |
---|
| 128 | struct drvmgr_dev **gr1553_rt_open(int minor) |
---|
| 129 | { |
---|
| 130 | struct gr1553_device_feature *feat; |
---|
| 131 | |
---|
| 132 | feat = gr1553_list_find(gr1553_rt_root, minor); |
---|
| 133 | if ( feat == NULL ) |
---|
| 134 | return NULL; |
---|
| 135 | |
---|
| 136 | /* Only possible to allocate is RT and BC is free, |
---|
| 137 | * this is beacuse it is not possible to use the |
---|
| 138 | * RT and the BC at the same time. |
---|
| 139 | */ |
---|
| 140 | if ( feat->dev->alloc & (ALLOC_BC|ALLOC_RT) ) |
---|
| 141 | return NULL; |
---|
| 142 | |
---|
| 143 | /* Alloc RT device */ |
---|
| 144 | feat->dev->alloc |= ALLOC_RT; |
---|
| 145 | |
---|
| 146 | return &feat->dev->dev; |
---|
| 147 | } |
---|
| 148 | |
---|
| 149 | void gr1553_rt_close(struct drvmgr_dev **dev) |
---|
| 150 | { |
---|
| 151 | struct gr1553_device *d = (struct gr1553_device *)dev; |
---|
| 152 | |
---|
| 153 | d->alloc &= ~ALLOC_RT; |
---|
| 154 | } |
---|
| 155 | |
---|
| 156 | struct drvmgr_dev **gr1553_bm_open(int minor) |
---|
| 157 | { |
---|
| 158 | struct gr1553_device_feature *feat; |
---|
| 159 | |
---|
| 160 | feat = gr1553_list_find(gr1553_bm_root, minor); |
---|
| 161 | if ( feat == NULL ) |
---|
| 162 | return NULL; |
---|
| 163 | |
---|
| 164 | /* Only possible to allocate is RT and BC is free, |
---|
| 165 | * this is beacuse it is not possible to use the |
---|
| 166 | * RT and the BC at the same time. |
---|
| 167 | */ |
---|
| 168 | if ( feat->dev->alloc & ALLOC_BM ) |
---|
| 169 | return NULL; |
---|
| 170 | |
---|
| 171 | /* Alloc BM device */ |
---|
| 172 | feat->dev->alloc |= ALLOC_BM; |
---|
| 173 | |
---|
| 174 | return &feat->dev->dev; |
---|
| 175 | } |
---|
| 176 | |
---|
| 177 | void gr1553_bm_close(struct drvmgr_dev **dev) |
---|
| 178 | { |
---|
| 179 | struct gr1553_device *d = (struct gr1553_device *)dev; |
---|
| 180 | |
---|
| 181 | d->alloc &= ~ALLOC_BM; |
---|
| 182 | } |
---|
| 183 | |
---|
[b787bead] | 184 | static int gr1553_init2(struct drvmgr_dev *dev) |
---|
[3bb4122] | 185 | { |
---|
| 186 | struct amba_dev_info *ambadev; |
---|
| 187 | struct ambapp_core *pnpinfo; |
---|
| 188 | struct gr1553b_regs *regs; |
---|
| 189 | |
---|
| 190 | /* Get device information from AMBA PnP information */ |
---|
| 191 | ambadev = (struct amba_dev_info *)dev->businfo; |
---|
| 192 | if ( ambadev == NULL ) { |
---|
| 193 | return DRVMGR_FAIL; |
---|
| 194 | } |
---|
| 195 | pnpinfo = &ambadev->info; |
---|
[360fb2f] | 196 | if ( pnpinfo->apb_slv == NULL ) |
---|
| 197 | return DRVMGR_EIO; |
---|
[3bb4122] | 198 | regs = (struct gr1553b_regs *)pnpinfo->apb_slv->start; |
---|
| 199 | |
---|
| 200 | /* Stop IRQ */ |
---|
| 201 | GR1553B_WRITE_REG(®s->imask, 0); |
---|
| 202 | GR1553B_WRITE_REG(®s->irq, 0xffffffff); |
---|
| 203 | /* Stop BC if not already stopped (just in case) */ |
---|
| 204 | GR1553B_WRITE_REG(®s->bc_ctrl, 0x15520204); |
---|
| 205 | /* Stop RT rx (just in case) */ |
---|
| 206 | GR1553B_WRITE_REG(®s->rt_cfg, 0x15530000); |
---|
| 207 | /* Stop BM logging (just in case) */ |
---|
| 208 | GR1553B_WRITE_REG(®s->bm_ctrl, 0); |
---|
| 209 | |
---|
| 210 | return DRVMGR_OK; |
---|
| 211 | } |
---|
| 212 | |
---|
| 213 | /* Register the different functionalities that the |
---|
| 214 | * core supports. |
---|
| 215 | */ |
---|
[b787bead] | 216 | static int gr1553_init3(struct drvmgr_dev *dev) |
---|
[3bb4122] | 217 | { |
---|
| 218 | struct amba_dev_info *ambadev; |
---|
| 219 | struct ambapp_core *pnpinfo; |
---|
| 220 | struct gr1553_device *priv; |
---|
| 221 | struct gr1553_device_feature *feat; |
---|
| 222 | struct gr1553b_regs *regs; |
---|
| 223 | |
---|
[11f3b9a] | 224 | priv = grlib_malloc(sizeof(*priv)); |
---|
[3bb4122] | 225 | if ( priv == NULL ) |
---|
| 226 | return DRVMGR_NOMEM; |
---|
| 227 | priv->dev = dev; |
---|
| 228 | priv->alloc = 0; |
---|
| 229 | priv->features = 0; |
---|
| 230 | dev->priv = NULL; /* Let higher level driver handle this */ |
---|
| 231 | |
---|
| 232 | /* Get device information from AMBA PnP information */ |
---|
| 233 | ambadev = (struct amba_dev_info *)dev->businfo; |
---|
| 234 | pnpinfo = &ambadev->info; |
---|
| 235 | regs = (struct gr1553b_regs *)pnpinfo->apb_slv->start; |
---|
| 236 | |
---|
| 237 | if ( GR1553B_READ_REG(®s->bm_stat) & GR1553B_BM_STAT_BMSUP ) { |
---|
| 238 | priv->features |= FEAT_BM; |
---|
[11f3b9a] | 239 | feat = grlib_malloc(sizeof(*feat)); |
---|
[3bb4122] | 240 | feat->dev = priv; |
---|
| 241 | /* Init Minor and Next */ |
---|
| 242 | gr1553_list_add(&gr1553_bm_root, feat); |
---|
| 243 | } |
---|
| 244 | |
---|
| 245 | if ( GR1553B_READ_REG(®s->bc_stat) & GR1553B_BC_STAT_BCSUP ) { |
---|
| 246 | priv->features |= FEAT_BC; |
---|
[11f3b9a] | 247 | feat = grlib_malloc(sizeof(*feat)); |
---|
[3bb4122] | 248 | feat->dev = priv; |
---|
| 249 | /* Init Minor and Next */ |
---|
| 250 | gr1553_list_add(&gr1553_bc_root, feat); |
---|
| 251 | } |
---|
| 252 | |
---|
| 253 | if ( GR1553B_READ_REG(®s->rt_stat) & GR1553B_RT_STAT_RTSUP ) { |
---|
| 254 | priv->features |= FEAT_RT; |
---|
[11f3b9a] | 255 | feat = grlib_malloc(sizeof(*feat)); |
---|
[3bb4122] | 256 | feat->dev = priv; |
---|
| 257 | /* Init Minor and Next */ |
---|
| 258 | gr1553_list_add(&gr1553_rt_root, feat); |
---|
| 259 | } |
---|
| 260 | |
---|
[360fb2f] | 261 | if ( priv->features == 0 ) { |
---|
| 262 | /* no features in HW should never happen.. an I/O error? */ |
---|
| 263 | free(priv); |
---|
| 264 | return DRVMGR_EIO; |
---|
| 265 | } |
---|
| 266 | |
---|
[3bb4122] | 267 | return DRVMGR_OK; |
---|
| 268 | } |
---|
| 269 | |
---|
| 270 | struct drvmgr_drv_ops gr1553_ops = |
---|
| 271 | { |
---|
| 272 | {NULL, gr1553_init2, gr1553_init3, NULL}, |
---|
| 273 | NULL, |
---|
| 274 | NULL |
---|
| 275 | }; |
---|
| 276 | |
---|
| 277 | struct amba_dev_id gr1553_ids[] = |
---|
| 278 | { |
---|
| 279 | {VENDOR_GAISLER, GAISLER_GR1553B}, |
---|
| 280 | {0, 0} /* Mark end of table */ |
---|
| 281 | }; |
---|
| 282 | |
---|
| 283 | struct amba_drv_info gr1553_drv_info = |
---|
| 284 | { |
---|
| 285 | { |
---|
| 286 | DRVMGR_OBJ_DRV, /* Driver */ |
---|
| 287 | NULL, /* Next driver */ |
---|
| 288 | NULL, /* Device list */ |
---|
| 289 | DRIVER_AMBAPP_GAISLER_GR1553B_ID,/* Driver ID */ |
---|
| 290 | "GR1553_DRV", /* Driver Name */ |
---|
| 291 | DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ |
---|
| 292 | &gr1553_ops, |
---|
| 293 | NULL, /* Funcs */ |
---|
| 294 | 0, /* No devices yet */ |
---|
| 295 | 0, |
---|
| 296 | }, |
---|
| 297 | &gr1553_ids[0] |
---|
| 298 | }; |
---|
| 299 | |
---|
| 300 | /* Multiple drivers may call this function. The drivers that depends on |
---|
| 301 | * this driver: |
---|
| 302 | * - BM driver |
---|
| 303 | * - BC driver |
---|
| 304 | * - RT driver |
---|
| 305 | */ |
---|
| 306 | void gr1553_register(void) |
---|
| 307 | { |
---|
| 308 | if ( gr1553_driver_registerd == 0 ) { |
---|
| 309 | gr1553_driver_registerd = 1; |
---|
| 310 | drvmgr_drv_register(&gr1553_drv_info.general); |
---|
| 311 | } |
---|
| 312 | } |
---|