File indexing completed on 2025-05-11 08:24:05
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #include <string.h>
0032 #include <stdlib.h>
0033 #include <string.h>
0034
0035 #include <grlib/ambapp.h>
0036 #include <bsp.h>
0037
0038 #include <grlib/grlib_impl.h>
0039
0040 #define AMBA_CONF_AREA 0xff000
0041 #define AMBA_AHB_SLAVE_CONF_AREA (1 << 11)
0042 #define AMBA_APB_SLAVES 16
0043
0044
0045 static struct ambapp_dev *
0046 ambapp_alloc_dev_struct(const struct ambapp_context *ctx, int dev_type)
0047 {
0048 struct ambapp_dev *dev;
0049 size_t size = sizeof(*dev);
0050
0051 if (dev_type == DEV_APB_SLV)
0052 size += sizeof(struct ambapp_apb_info);
0053 else
0054 size += sizeof(struct ambapp_ahb_info);
0055 dev = (*ctx->alloc)(size);
0056 if (dev != NULL) {
0057 dev = memset(dev, 0, size);
0058 dev->dev_type = dev_type;
0059 }
0060 return dev;
0061 }
0062
0063 static unsigned int
0064 ambapp_addr_from (struct ambapp_mmap *mmaps, unsigned int address)
0065 {
0066
0067 if (!mmaps)
0068 return address;
0069
0070 while (mmaps->size) {
0071 if ((address >= mmaps->remote_adr) &&
0072 (address <= (mmaps->remote_adr + (mmaps->size - 1)))) {
0073 return (address - mmaps->remote_adr) + mmaps->local_adr;
0074 }
0075 mmaps++;
0076 }
0077 return 1;
0078 }
0079
0080 static void ambapp_ahb_dev_init(
0081 unsigned int ioarea,
0082 struct ambapp_mmap *mmaps,
0083 struct ambapp_pnp_ahb *ahb,
0084 struct ambapp_dev *dev,
0085 int ahbidx
0086 )
0087 {
0088 int bar;
0089 struct ambapp_ahb_info *ahb_info;
0090 unsigned int addr, mask, mbar;
0091
0092
0093 dev->vendor = ambapp_pnp_vendor(ahb->id);
0094 dev->device = ambapp_pnp_device(ahb->id);
0095 ahb_info = DEV_TO_AHB(dev);
0096 ahb_info->common.ver = ambapp_pnp_ver(ahb->id);
0097 ahb_info->common.irq = ambapp_pnp_irq(ahb->id);
0098 ahb_info->common.ahbidx = ahbidx;
0099 ahb_info->custom[0] = (unsigned int)ahb->custom[0];
0100 ahb_info->custom[1] = (unsigned int)ahb->custom[1];
0101 ahb_info->custom[2] = (unsigned int)ahb->custom[2];
0102
0103
0104 for (bar=0; bar<4; bar++) {
0105 mbar = ahb->mbar[bar];
0106 if (mbar == 0) {
0107 addr = 0;
0108 mask = 0;
0109 } else {
0110 addr = ambapp_pnp_start(mbar);
0111 if (ambapp_pnp_mbar_type(mbar) == AMBA_TYPE_AHBIO) {
0112
0113 addr = AMBA_TYPE_AHBIO_ADDR(addr, ioarea);
0114 mask = (((unsigned int)(ambapp_pnp_mbar_mask(~mbar) << 8) | 0xff)) + 1;
0115 } else {
0116
0117 addr = ambapp_addr_from(mmaps, addr);
0118 mask = (~((unsigned int)(ambapp_pnp_mbar_mask(mbar) << 20))) + 1;
0119 }
0120 }
0121 ahb_info->start[bar] = addr;
0122 ahb_info->mask[bar] = mask;
0123 ahb_info->type[bar] = ambapp_pnp_mbar_type(mbar);
0124 }
0125 }
0126
0127 static void ambapp_apb_dev_init(
0128 unsigned int base,
0129 struct ambapp_mmap *mmaps,
0130 struct ambapp_pnp_apb *apb,
0131 struct ambapp_dev *dev,
0132 int ahbidx
0133 )
0134 {
0135 struct ambapp_apb_info *apb_info;
0136
0137
0138 dev->vendor = ambapp_pnp_vendor(apb->id);
0139 dev->device = ambapp_pnp_device(apb->id);
0140 apb_info = DEV_TO_APB(dev);
0141 apb_info->common.ver = ambapp_pnp_ver(apb->id);
0142 apb_info->common.irq = ambapp_pnp_irq(apb->id);
0143 apb_info->common.ahbidx = ahbidx;
0144 apb_info->start = ambapp_pnp_apb_start(apb->iobar, base);
0145 apb_info->mask = ambapp_pnp_apb_mask(apb->iobar);
0146 }
0147
0148 static int ambapp_add_ahbbus(
0149 struct ambapp_bus *abus,
0150 unsigned int ioarea
0151 )
0152 {
0153 int i;
0154 for (i=0; i<AHB_BUS_MAX; i++) {
0155 if (abus->ahbs[i].ioarea == 0) {
0156 abus->ahbs[i].ioarea = ioarea;
0157 return i;
0158 } else if (abus->ahbs[i].ioarea == ioarea) {
0159
0160 return -1;
0161 }
0162 }
0163 return -1;
0164 }
0165
0166
0167 static int ambapp_scan2(
0168 struct ambapp_bus *abus,
0169 unsigned int ioarea,
0170 const struct ambapp_context *ctx,
0171 struct ambapp_dev *parent,
0172 struct ambapp_dev **root
0173 )
0174 {
0175 struct ambapp_pnp_ahb *ahb, ahb_buf;
0176 struct ambapp_pnp_apb *apb, apb_buf;
0177 struct ambapp_dev *dev, *prev, *prevapb, *apbdev;
0178 struct ambapp_ahb_info *ahb_info;
0179 int maxloops = 64;
0180 unsigned int apbbase, bridge_adr;
0181 int i, j, ahbidx;
0182
0183 *root = NULL;
0184
0185 if (parent) {
0186
0187 maxloops = 16;
0188 }
0189
0190 ahbidx = ambapp_add_ahbbus(abus, ioarea);
0191 if (ahbidx < 0) {
0192
0193 return 0;
0194 }
0195
0196 prev = parent;
0197
0198
0199 ahb = (struct ambapp_pnp_ahb *) (ioarea | AMBA_CONF_AREA);
0200 for (i = 0; i < maxloops; i++, ahb++) {
0201 (*ctx->copy_from_device)(&ahb_buf, ahb, sizeof(struct ambapp_pnp_ahb), abus);
0202 if (ahb_buf.id == 0)
0203 continue;
0204
0205
0206 dev = ambapp_alloc_dev_struct(ctx, DEV_AHB_MST);
0207 if (!dev)
0208 return -1;
0209
0210 ambapp_ahb_dev_init(ioarea, abus->mmaps, &ahb_buf, dev, ahbidx);
0211
0212 if (*root == NULL)
0213 *root = dev;
0214
0215 if (prev != parent)
0216 prev->next = dev;
0217 dev->prev = prev;
0218 prev = dev;
0219 }
0220
0221
0222 ahb = (struct ambapp_pnp_ahb *)
0223 (ioarea | AMBA_CONF_AREA | AMBA_AHB_SLAVE_CONF_AREA);
0224 for (i = 0; i < maxloops; i++, ahb++) {
0225 (*ctx->copy_from_device)(&ahb_buf, ahb, sizeof(struct ambapp_pnp_ahb), abus);
0226 if (ahb_buf.id == 0)
0227 continue;
0228
0229
0230 dev = ambapp_alloc_dev_struct(ctx, DEV_AHB_SLV);
0231 if (!dev)
0232 return -1;
0233
0234 ambapp_ahb_dev_init(ioarea, abus->mmaps, &ahb_buf, dev, ahbidx);
0235
0236 if (*root == NULL)
0237 *root = dev;
0238
0239 if (prev != parent)
0240 prev->next = dev;
0241 dev->prev = prev;
0242 prev = dev;
0243
0244 ahb_info = DEV_TO_AHB(dev);
0245
0246
0247 if (((dev->device == GAISLER_AHB2AHB) &&
0248 (dev->vendor == VENDOR_GAISLER) && (ahb_info->common.ver > 0)) ||
0249 ((dev->device == GAISLER_L2CACHE) &&
0250 (dev->vendor == VENDOR_GAISLER)) ||
0251 ((dev->device == GAISLER_GRIOMMU) &&
0252 (dev->vendor == VENDOR_GAISLER))) {
0253
0254
0255
0256 if (ahb_info->custom[1] != 0) {
0257 bridge_adr = ambapp_addr_from(abus->mmaps,
0258 ahb_info->custom[1]);
0259
0260 if (ambapp_scan2(abus, bridge_adr, ctx, dev,
0261 &dev->children))
0262 return -1;
0263 }
0264 } else if ((dev->device == GAISLER_APBMST) &&
0265 (dev->vendor == VENDOR_GAISLER)) {
0266
0267
0268
0269 prevapb = dev;
0270 apbbase = ahb_info->start[0];
0271
0272
0273 apb = (struct ambapp_pnp_apb *)
0274 (apbbase | AMBA_CONF_AREA);
0275 for (j=0; j<AMBA_APB_SLAVES; j++, apb++) {
0276 (*ctx->copy_from_device)(&apb_buf, apb, sizeof(*apb), abus);
0277 if (apb_buf.id == 0)
0278 continue;
0279
0280 apbdev = ambapp_alloc_dev_struct(ctx, DEV_APB_SLV);
0281 if (!apbdev)
0282 return -1;
0283
0284 ambapp_apb_dev_init(apbbase, abus->mmaps,
0285 &apb_buf, apbdev, ahbidx);
0286
0287 if (prevapb != dev)
0288 prevapb->next = apbdev;
0289 else
0290 dev->children = apbdev;
0291 apbdev->prev = prevapb;
0292 prevapb = apbdev;
0293 }
0294 }
0295 }
0296
0297
0298 abus->ahbs[ahbidx].dev = *root;
0299 abus->ahbs[ahbidx].bridge = parent;
0300
0301 return 0;
0302 }
0303
0304 static const struct ambapp_context default_ctx = {
0305 .copy_from_device = (ambapp_memcpy_t)memcpy,
0306 .alloc = rtems_malloc
0307 };
0308
0309
0310 int ambapp_scan(
0311 struct ambapp_bus *abus,
0312 unsigned int ioarea,
0313 const struct ambapp_context *ctx,
0314 struct ambapp_mmap *mmaps
0315 )
0316 {
0317
0318 memset(abus, 0, sizeof(*abus));
0319 abus->mmaps = mmaps;
0320
0321 if (ctx == NULL) {
0322 ctx = &default_ctx;
0323 }
0324
0325 return ambapp_scan2(abus, ioarea, ctx, NULL, &abus->root);
0326 }
0327
0328
0329 static int ambapp_dev_match_options(struct ambapp_dev *dev, unsigned int options, int vendor, int device)
0330 {
0331 if ((((options & (OPTIONS_ALL_DEVS)) == OPTIONS_ALL_DEVS) ||
0332 ((options & OPTIONS_AHB_MSTS) && (dev->dev_type == DEV_AHB_MST)) ||
0333 ((options & OPTIONS_AHB_SLVS) && (dev->dev_type == DEV_AHB_SLV)) ||
0334 ((options & OPTIONS_APB_SLVS) && (dev->dev_type == DEV_APB_SLV))) &&
0335 ((vendor == -1) || (vendor == dev->vendor)) &&
0336 ((device == -1) || (device == dev->device)) &&
0337 (((options & OPTIONS_ALL) == OPTIONS_ALL) ||
0338 ((options & OPTIONS_FREE) && DEV_IS_FREE(dev)) ||
0339 ((options & OPTIONS_ALLOCATED) && DEV_IS_ALLOCATED(dev)))) {
0340 return 1;
0341 }
0342 return 0;
0343 }
0344
0345
0346 static int ambapp_for_each_apb(
0347 struct ambapp_dev *dev,
0348 unsigned int options,
0349 int vendor,
0350 int device,
0351 ambapp_func_t func,
0352 void *arg)
0353 {
0354 int index, ret;
0355 struct ambapp_dev *apbslv;
0356
0357 ret = 0;
0358 if (dev->children && (dev->children->dev_type == DEV_APB_SLV)) {
0359
0360 index = 0;
0361 apbslv = dev->children;
0362 while (apbslv) {
0363 if (ambapp_dev_match_options(apbslv, options,
0364 vendor, device) == 1) {
0365 ret = func(apbslv, index, arg);
0366 if (ret != 0)
0367 break;
0368 }
0369 index++;
0370 apbslv = apbslv->next;
0371 }
0372 }
0373
0374 return ret;
0375 }
0376
0377
0378 static int ambapp_for_each_dev(
0379 struct ambapp_dev *root,
0380 unsigned int options,
0381 int vendor,
0382 int device,
0383 ambapp_func_t func,
0384 void *arg)
0385 {
0386 struct ambapp_dev *dev;
0387 int ahb_slave = 0;
0388 int index, ret;
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400 if (options & (OPTIONS_AHB_MSTS|OPTIONS_AHB_SLVS|OPTIONS_DEPTH_FIRST)) {
0401 index = 0;
0402 dev = root;
0403 while (dev) {
0404 if ((dev->dev_type == DEV_AHB_SLV) && !ahb_slave) {
0405
0406 ahb_slave = 1;
0407 index = 0;
0408 }
0409
0410
0411
0412
0413 if (ambapp_dev_match_options(dev, options, vendor, device) == 1) {
0414
0415 ret = func(dev, index, arg);
0416 if (ret != 0)
0417 return ret;
0418 }
0419
0420 if ((options & OPTIONS_DEPTH_FIRST) && (options & OPTIONS_APB_SLVS)) {
0421
0422
0423
0424 ret = ambapp_for_each_apb(dev, options, vendor, device, func, arg);
0425 if (ret != 0)
0426 return ret;
0427 }
0428
0429 if (options & OPTIONS_DEPTH_FIRST) {
0430 if (dev->children && (dev->children->dev_type != DEV_APB_SLV)) {
0431
0432 ret = ambapp_for_each_dev(dev->children, options, vendor, device,
0433 func, arg);
0434 if (ret != 0)
0435 return ret;
0436 }
0437 }
0438
0439 index++;
0440 dev = dev->next;
0441 }
0442 }
0443
0444
0445 if ((options & OPTIONS_APB_SLVS) && !(options & OPTIONS_DEPTH_FIRST)) {
0446 dev = root;
0447 while (dev) {
0448
0449
0450
0451 ret = ambapp_for_each_apb(dev, options, vendor, device, func, arg);
0452 if (ret != 0)
0453 return ret;
0454 dev = dev->next;
0455 }
0456 }
0457
0458
0459 if (!(options & OPTIONS_DEPTH_FIRST)) {
0460 dev = root;
0461 while (dev) {
0462 if (dev->children && (dev->children->dev_type != DEV_APB_SLV)) {
0463
0464 ret = ambapp_for_each_dev(dev->children, options, vendor, device,
0465 func, arg);
0466 if (ret != 0)
0467 return ret;
0468 }
0469 dev = dev->next;
0470 }
0471 }
0472
0473 return 0;
0474 }
0475
0476 int ambapp_for_each(
0477 struct ambapp_bus *abus,
0478 unsigned int options,
0479 int vendor,
0480 int device,
0481 ambapp_func_t func,
0482 void *arg)
0483 {
0484 return ambapp_for_each_dev(abus->root, options, vendor, device, func, arg);
0485 }