/** * We have a top-level GPIO device with no actual GPIOs. It has a child * device for each Sunxi bank. */ static int gpio_sunxi_bind(struct udevice *parent) { struct sunxi_gpio_platdata *plat = parent->platdata; struct sunxi_gpio_reg *ctlr; int bank; int ret; /* If this is a child device, there is nothing to do here */ if (plat) return 0; ctlr = (struct sunxi_gpio_reg *)fdtdec_get_addr(gd->fdt_blob, parent->of_offset, "reg"); for (bank = 0; bank < SUNXI_GPIO_BANKS; bank++) { struct sunxi_gpio_platdata *plat; struct udevice *dev; plat = calloc(1, sizeof(*plat)); if (!plat) return -ENOMEM; plat->regs = &ctlr->gpio_bank[bank]; plat->bank_name = gpio_bank_name(bank); plat->gpio_count = SUNXI_GPIOS_PER_BANK; ret = device_bind(parent, parent->driver, plat->bank_name, plat, -1, &dev); if (ret) return ret; dev->of_offset = parent->of_offset; } return 0; }
/** * We have a top-level GPIO device with no actual GPIOs. It has a child * device for each Sunxi bank. */ static int gpio_sunxi_bind(struct udevice *parent) { struct sunxi_gpio_soc_data *soc_data = (struct sunxi_gpio_soc_data *)dev_get_driver_data(parent); struct sunxi_gpio_platdata *plat = parent->platdata; struct sunxi_gpio_reg *ctlr; int bank, ret; /* If this is a child device, there is nothing to do here */ if (plat) return 0; ctlr = (struct sunxi_gpio_reg *)devfdt_get_addr(parent); for (bank = 0; bank < soc_data->no_banks; bank++) { struct sunxi_gpio_platdata *plat; struct udevice *dev; plat = calloc(1, sizeof(*plat)); if (!plat) return -ENOMEM; plat->regs = &ctlr->gpio_bank[bank]; plat->bank_name = gpio_bank_name(soc_data->start + bank); plat->gpio_count = SUNXI_GPIOS_PER_BANK; ret = device_bind(parent, parent->driver, plat->bank_name, plat, -1, &dev); if (ret) return ret; dev_set_of_offset(dev, dev_of_offset(parent)); } return 0; }
int lists_bind_fdt(struct udevice *parent, const void *blob, int offset, struct udevice **devp) { struct driver *driver = ll_entry_start(struct driver, driver); const int n_ents = ll_entry_count(struct driver, driver); const struct udevice_id *id; struct driver *entry; struct udevice *dev; bool found = false; const char *name; int result = 0; int ret = 0; dm_dbg("bind node %s\n", fdt_get_name(blob, offset, NULL)); if (devp) *devp = NULL; for (entry = driver; entry != driver + n_ents; entry++) { ret = driver_check_compatible(blob, offset, entry->of_match, &id); name = fdt_get_name(blob, offset, NULL); if (ret == -ENOENT) { continue; } else if (ret == -ENODEV) { dm_dbg("Device '%s' has no compatible string\n", name); break; } else if (ret) { dm_warn("Device tree error at offset %d\n", offset); result = ret; break; } dm_dbg(" - found match at '%s'\n", entry->name); ret = device_bind(parent, entry, name, NULL, offset, &dev); if (ret) { dm_warn("Error binding driver '%s': %d\n", entry->name, ret); return ret; } else { dev->driver_data = id->data; found = true; if (devp) *devp = dev; } break; } if (!found && !result && ret != -ENODEV) { dm_dbg("No match for node '%s'\n", fdt_get_name(blob, offset, NULL)); } return result; }
static int gpio_dwapb_bind(struct udevice *dev) { struct gpio_dwapb_platdata *plat = dev_get_platdata(dev); const void *blob = gd->fdt_blob; struct udevice *subdev; fdt_addr_t base; int ret, node, bank = 0; /* If this is a child device, there is nothing to do here */ if (plat) return 0; base = fdtdec_get_addr(blob, dev_of_offset(dev), "reg"); if (base == FDT_ADDR_T_NONE) { debug("Can't get the GPIO register base address\n"); return -ENXIO; } for (node = fdt_first_subnode(blob, dev_of_offset(dev)); node > 0; node = fdt_next_subnode(blob, node)) { if (!fdtdec_get_bool(blob, node, "gpio-controller")) continue; plat = NULL; plat = calloc(1, sizeof(*plat)); if (!plat) return -ENOMEM; plat->base = base; plat->bank = bank; plat->pins = fdtdec_get_int(blob, node, "snps,nr-gpios", 0); plat->name = fdt_stringlist_get(blob, node, "bank-name", 0, NULL); if (ret) goto err; ret = device_bind(dev, dev->driver, plat->name, plat, -1, &subdev); if (ret) goto err; dev_set_of_offset(subdev, node); bank++; } return 0; err: free(plat); return ret; }
static int gpio_dwapb_bind(struct udevice *dev) { struct gpio_dwapb_platdata *plat = dev_get_platdata(dev); struct udevice *subdev; fdt_addr_t base; int ret, bank = 0; ofnode node; /* If this is a child device, there is nothing to do here */ if (plat) return 0; base = dev_read_addr(dev); if (base == FDT_ADDR_T_NONE) { debug("Can't get the GPIO register base address\n"); return -ENXIO; } for (node = dev_read_first_subnode(dev); ofnode_valid(node); node = dev_read_next_subnode(node)) { if (!ofnode_read_bool(node, "gpio-controller")) continue; plat = devm_kcalloc(dev, 1, sizeof(*plat), GFP_KERNEL); if (!plat) return -ENOMEM; plat->base = base; plat->bank = bank; plat->pins = ofnode_read_u32_default(node, "snps,nr-gpios", 0); if (ofnode_read_string_index(node, "bank-name", 0, &plat->name)) { /* * Fall back to node name. This means accessing pins * via bank name won't work. */ plat->name = ofnode_get_name(node); } ret = device_bind(dev, dev->driver, plat->name, plat, -1, &subdev); if (ret) return ret; dev->node = node; bank++; } return 0; }
/** * We have a top-level GPIO device with no actual GPIOs. It has a child * device for each Exynos GPIO bank. */ static int gpio_exynos_bind(struct udevice *parent) { struct exynos_gpio_platdata *plat = parent->platdata; struct s5p_gpio_bank *bank, *base; const void *blob = gd->fdt_blob; int node; /* If this is a child device, there is nothing to do here */ if (plat) return 0; base = (struct s5p_gpio_bank *)fdtdec_get_addr(gd->fdt_blob, parent->of_offset, "reg"); for (node = fdt_first_subnode(blob, parent->of_offset), bank = base; node > 0; node = fdt_next_subnode(blob, node), bank++) { struct exynos_gpio_platdata *plat; struct udevice *dev; fdt_addr_t reg; int ret; if (!fdtdec_get_bool(blob, node, "gpio-controller")) continue; plat = calloc(1, sizeof(*plat)); if (!plat) return -ENOMEM; reg = fdtdec_get_addr(blob, node, "reg"); if (reg != FDT_ADDR_T_NONE) bank = (struct s5p_gpio_bank *)((ulong)base + reg); plat->bank = bank; plat->bank_name = fdt_get_name(blob, node, NULL); debug("dev at %p: %s\n", bank, plat->bank_name); ret = device_bind(parent, parent->driver, plat->bank_name, plat, -1, &dev); if (ret) return ret; dev->of_offset = node; } return 0; }
int device_bind_driver(struct udevice *parent, const char *drv_name, const char *dev_name, struct udevice **devp) { struct driver *drv; int ret; drv = lists_driver_lookup_name(drv_name); if (!drv) { printf("Cannot find driver '%s'\n", drv_name); return -ENOENT; } ret = device_bind(parent, drv, dev_name, NULL, -1, devp); if (ret) { printf("Cannot create device named '%s' (err=%d)\n", dev_name, ret); return ret; } return 0; }
int lists_bind_fdt(struct udevice *parent, const void *blob, int offset) { struct driver *driver = ll_entry_start(struct driver, driver); const int n_ents = ll_entry_count(struct driver, driver); struct driver *entry; struct udevice *dev; const char *name; int result = 0; int ret; dm_dbg("bind node %s\n", fdt_get_name(blob, offset, NULL)); for (entry = driver; entry != driver + n_ents; entry++) { ret = driver_check_compatible(blob, offset, entry->of_match); if (ret == -ENOENT) { continue; } else if (ret == -ENODEV) { break; } else if (ret) { dm_warn("Device tree error at offset %d\n", offset); if (!result || ret != -ENOENT) result = ret; break; } name = fdt_get_name(blob, offset, NULL); dm_dbg(" - found match at '%s'\n", entry->name); ret = device_bind(parent, entry, name, NULL, offset, &dev); if (ret) { dm_warn("No match for driver '%s'\n", entry->name); if (!result || ret != -ENOENT) result = ret; } } return result; }