static int serio_bind_driver(struct serio *serio, struct serio_driver *drv) { int error; if (serio_match_port(drv->id_table, serio)) { serio->dev.driver = &drv->driver; if (serio_connect_driver(serio, drv)) { serio->dev.driver = NULL; return -ENODEV; } error = device_bind_driver(&serio->dev); if (error) { dev_warn(&serio->dev, "device_bind_driver() failed for %s (%s) and %s, error: %d\n", serio->phys, serio->name, drv->description, error); serio_disconnect_driver(serio); serio->dev.driver = NULL; return error; } } return 0; }
static int do_devs_build(struct platform_driver * drv) { int ret = 0; int lnk_err = 0; outputs = platform_device_alloc(do4_dev_out_name,0); if(outputs) { outputs->dev.release = do_dev_release; // Release-Function platform_device_add(outputs); platform_set_drvdata(outputs, &do4_O_Outputs);// dem DO-Platform Device die Datenstruktur mitgeben outputs->dev.driver = &drv->driver; lnk_err = device_bind_driver(&outputs->dev); do4_sysfs_dev_add(&outputs->dev); // DO-Devices-SYSFS erzeugen } else { // Resource-Meldung! printk(KERN_ERR "%s %s(): %s %s error!\n",__FILE__, __FUNCTION__,"Resource ",do4_dev_out_name); ret = -ENOMEM; } if(ret) { if( outputs) { platform_set_drvdata(outputs,NULL); // DO-Platform-Device Datenzeiger aufheben platform_device_unregister(outputs); // DO-Platform-Device entfernen do4_sysfs_dev_del(&outputs->dev); // DO-Devices-SYSFS entfernen } } return ret; }
/** * device_attach - try to attach device to a driver. * @dev: device. * * Walk the list of drivers that the bus has and call * driver_probe_device() for each pair. If a compatible * pair is found, break out and return. * * Returns 1 if the device was bound to a driver; * 0 if no matching driver was found; * -ENODEV if the device is not registered. * * When called for a USB interface, @dev->parent lock must be held. */ int device_attach(struct device *dev) { int ret = 0; device_lock(dev); if (dev->driver) { if (klist_node_attached(&dev->p->knode_driver)) { ret = 1; goto out_unlock; } ret = device_bind_driver(dev); if (ret == 0) ret = 1; else { dev->driver = NULL; ret = 0; } } else { pm_runtime_get_noresume(dev); ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); pm_runtime_put_sync(dev); } out_unlock: device_unlock(dev); return ret; }
static int rk3036_clk_bind(struct udevice *dev) { int ret; struct udevice *sys_child; struct sysreset_reg *priv; /* The reset driver does not have a device node, so bind it here */ ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", &sys_child); if (ret) { debug("Warning: No sysreset driver: ret=%d\n", ret); } else { priv = malloc(sizeof(struct sysreset_reg)); priv->glb_srst_fst_value = offsetof(struct rk3036_cru, cru_glb_srst_fst_value); priv->glb_srst_snd_value = offsetof(struct rk3036_cru, cru_glb_srst_snd_value); sys_child->priv = priv; } #if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP) ret = offsetof(struct rk3036_cru, cru_softrst_con[0]); ret = rockchip_reset_bind(dev, ret, 9); if (ret) debug("Warning: software reset driver bind faile\n"); #endif return 0; }
static int qemu_cpu_fixup(void) { int ret; int cpu_num; int cpu_online; struct udevice *dev, *pdev; struct cpu_platdata *plat; char *cpu; /* first we need to find '/cpus' */ for (device_find_first_child(dm_root(), &pdev); pdev; device_find_next_child(&pdev)) { if (!strcmp(pdev->name, "cpus")) break; } if (!pdev) { printf("unable to find cpus device\n"); return -ENODEV; } /* calculate cpus that are already bound */ cpu_num = 0; for (uclass_find_first_device(UCLASS_CPU, &dev); dev; uclass_find_next_device(&dev)) { cpu_num++; } /* get actual cpu number */ cpu_online = qemu_fwcfg_online_cpus(); if (cpu_online < 0) { printf("unable to get online cpu number: %d\n", cpu_online); return cpu_online; } /* bind addtional cpus */ dev = NULL; for (; cpu_num < cpu_online; cpu_num++) { /* * allocate device name here as device_bind_driver() does * not copy device name, 8 bytes are enough for * sizeof("cpu@") + 3 digits cpu number + '\0' */ cpu = malloc(8); if (!cpu) { printf("unable to allocate device name\n"); return -ENOMEM; } sprintf(cpu, "cpu@%d", cpu_num); ret = device_bind_driver(pdev, "cpu_qemu", cpu, &dev); if (ret) { printf("binding cpu@%d failed: %d\n", cpu_num, ret); return ret; } plat = dev_get_parent_platdata(dev); plat->cpu_id = cpu_num; } return 0; }
static int i2c_bind_driver(struct udevice *bus, uint chip_addr, struct udevice **devp) { struct dm_i2c_chip chip; char name[30], *str; struct udevice *dev; int ret; snprintf(name, sizeof(name), "generic_%x", chip_addr); str = strdup(name); ret = device_bind_driver(bus, "i2c_generic_chip_drv", str, &dev); debug("%s: device_bind_driver: ret=%d\n", __func__, ret); if (ret) goto err_bind; /* Tell the device what we know about it */ memset(&chip, '\0', sizeof(chip)); chip.chip_addr = chip_addr; chip.offset_len = 1; /* we assume */ ret = device_probe_child(dev, &chip); debug("%s: device_probe_child: ret=%d\n", __func__, ret); if (ret) goto err_probe; *devp = dev; return 0; err_probe: device_unbind(dev); err_bind: free(str); return ret; }
int board_late_init(void) { #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT) watchdog_dev = NULL; if (uclass_get_device_by_seq(UCLASS_WDT, 0, &watchdog_dev)) { debug("Watchdog: Not found by seq!\n"); if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) { puts("Watchdog: Not found!\n"); return 0; } } wdt_start(watchdog_dev, 0, 0); puts("Watchdog: Started\n"); #endif /* !CONFIG_SPL_BUILD && CONFIG_WDT */ #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SYSRESET_MICROBLAZE) int ret; ret = device_bind_driver(gd->dm_root, "mb_soft_reset", "reset_soft", NULL); if (ret) printf("Warning: No reset driver: ret=%d\n", ret); #endif return 0; }
static void serio_bind_driver(struct serio *serio, struct serio_driver *drv) { int error; down_write(&serio_bus.subsys.rwsem); if (serio_match_port(drv->id_table, serio)) { serio->dev.driver = &drv->driver; if (serio_connect_driver(serio, drv)) { serio->dev.driver = NULL; goto out; } error = device_bind_driver(&serio->dev); if (error) { printk(KERN_WARNING "serio: device_bind_driver() failed " "for %s (%s) and %s, error: %d\n", serio->phys, serio->name, drv->description, error); serio_disconnect_driver(serio); serio->dev.driver = NULL; goto out; } } out: up_write(&serio_bus.subsys.rwsem); }
/** * phy_attach - attach a network device to a particular PHY device * @dev: network device to attach * @phy_id: PHY device to attach * @flags: PHY device's dev_flags * @interface: PHY device's interface * * Description: Called by drivers to attach to a particular PHY * device. The phy_device is found, and properly hooked up * to the phy_driver. If no driver is attached, then the * genphy_driver is used. The phy_device is given a ptr to * the attaching device, and given a callback for link status * change. The phy_device is returned to the attaching driver. */ struct phy_device *phy_attach(struct net_device *dev, const char *phy_id, u32 flags, phy_interface_t interface) { struct bus_type *bus = &mdio_bus_type; struct phy_device *phydev; struct device *d; /* Search the list of PHY devices on the mdio bus for the * PHY with the requested name */ d = bus_find_device(bus, NULL, (void *)phy_id, phy_compare_id); if (d) { phydev = to_phy_device(d); } else { printk(KERN_ERR "%s not found\n", phy_id); return ERR_PTR(-ENODEV); } /* Assume that if there is no driver, that it doesn't * exist, and we should use the genphy driver. */ if (NULL == d->driver) { int err; d->driver = &genphy_driver.driver; err = d->driver->probe(d); if (err >= 0) err = device_bind_driver(d); if (err) return ERR_PTR(err); } if (phydev->attached_dev) { printk(KERN_ERR "%s: %s already attached\n", dev->name, phy_id); return ERR_PTR(-EBUSY); } phydev->attached_dev = dev; phydev->dev_flags = flags; phydev->interface = interface; /* Do initial configuration here, now that * we have certain key parameters * (dev_flags and interface) */ if (phydev->drv->config_init) { int err; err = phydev->drv->config_init(phydev); if (err < 0) return ERR_PTR(err); } return phydev; }
/** * device_attach - try to attach device to a driver. * @dev: device. * * Walk the list of drivers that the bus has and call * driver_probe_device() for each pair. If a compatible * pair is found, break out and return. * * Returns 1 if the device was bound to a driver; * 0 if no matching device was found; error code otherwise. * * When called for a USB interface, @dev->parent->sem must be held. */ int device_attach(struct device * dev) { int ret = 0; down(&dev->sem); if (dev->driver) { device_bind_driver(dev); ret = 1; } else ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); up(&dev->sem); return ret; }
static void gameport_bind_driver(struct gameport *gameport, struct gameport_driver *drv) { down_write(&gameport_bus.subsys.rwsem); gameport->dev.driver = &drv->driver; if (drv->connect(gameport, drv)) { gameport->dev.driver = NULL; goto out; } device_bind_driver(&gameport->dev); out: up_write(&gameport_bus.subsys.rwsem); }
static void serio_bind_driver(struct serio *serio, struct serio_driver *drv) { down_write(&serio_bus.subsys.rwsem); if (serio_match_port(drv->id_table, serio)) { serio->dev.driver = &drv->driver; if (serio_connect_driver(serio, drv)) { serio->dev.driver = NULL; goto out; } device_bind_driver(&serio->dev); } out: up_write(&serio_bus.subsys.rwsem); }
int axp_gpio_init(void) { struct udevice *dev; int ret; ret = pmic_bus_init(); if (ret) return ret; /* There is no devicetree support for the axp yet, so bind directly */ ret = device_bind_driver(dm_root(), "gpio_axp", "AXP-gpio", &dev); if (ret) return ret; return 0; }
void sunxi_musb_board_init(void) { #ifdef CONFIG_USB_MUSB_HOST struct udevice *dev; /* * Bind the driver directly for now as musb linux kernel support is * still pending upstream so our dts files do not have the necessary * nodes yet. TODO: Remove this as soon as the dts nodes are in place * and bind by compatible instead. */ device_bind_driver(dm_root(), "sunxi-musb", "sunxi-musb", &dev); #else musb_register(&musb_plat, NULL, (void *)SUNXI_USB0_BASE); #endif }
struct phy_device *phy_attach(struct net_device *dev, const char *phy_id, u32 flags) { struct bus_type *bus = &mdio_bus_type; struct phy_device *phydev; struct device *d; /* Search the list of PHY devices on the mdio bus for the * PHY with the requested name */ d = bus_find_device(bus, NULL, (void *)phy_id, phy_compare_id); if (d) { phydev = to_phy_device(d); } else { printk(KERN_ERR "%s not found\n", phy_id); return ERR_PTR(-ENODEV); } /* Assume that if there is no driver, that it doesn't * exist, and we should use the genphy driver. */ if (NULL == d->driver) { int err; down_write(&d->bus->subsys.rwsem); d->driver = &genphy_driver.driver; err = d->driver->probe(d); if (err < 0) return ERR_PTR(err); device_bind_driver(d); up_write(&d->bus->subsys.rwsem); } if (phydev->attached_dev) { printk(KERN_ERR "%s: %s already attached\n", dev->name, phy_id); return ERR_PTR(-EBUSY); } phydev->attached_dev = dev; phydev->dev_flags = flags; return phydev; }
/** * driver_probe_device - attempt to bind device & driver. * @drv: driver. * @dev: device. * * First, we call the bus's match function, if one present, which * should compare the device IDs the driver supports with the * device IDs of the device. Note we don't do this ourselves * because we don't know the format of the ID structures, nor what * is to be considered a match and what is not. * * This function returns 1 if a match is found, an error if one * occurs (that is not -ENODEV or -ENXIO), and 0 otherwise. * * This function must be called with @dev->sem held. When called * for a USB interface, @dev->parent->sem must be held as well. */ int driver_probe_device(struct device_driver * drv, struct device * dev) { int ret = 0; if (drv->bus->match && !drv->bus->match(dev, drv)) goto Done; pr_debug("%s: Matched Device %s with Driver %s\n", drv->bus->name, dev->bus_id, drv->name); dev->driver = drv; if (dev->bus->probe) { ret = dev->bus->probe(dev); if (ret) { dev->driver = NULL; goto ProbeFailed; } } else if (drv->probe) { ret = drv->probe(dev); if (ret) { dev->driver = NULL; goto ProbeFailed; } } device_bind_driver(dev); ret = 1; pr_debug("%s: Bound Device %s to Driver %s\n", drv->bus->name, dev->bus_id, drv->name); goto Done; ProbeFailed: if (ret == -ENODEV || ret == -ENXIO) { /* Driver matched, but didn't support device * or device not found. * Not an error; keep going. */ ret = 0; } else { /* driver matched but the probe failed */ printk(KERN_WARNING "%s: probe of %s failed with error %d\n", drv->name, dev->bus_id, ret); } Done: return ret; }
/** * device_attach - try to attach device to a driver. * @dev: device. * * Walk the list of drivers that the bus has and call * driver_probe_device() for each pair. If a compatible * pair is found, break out and return. * * Returns 1 if the device was bound to a driver; * 0 if no matching device was found; * -ENODEV if the device is not registered. * * When called for a USB interface, @dev->parent->sem must be held. */ int device_attach(struct device *dev) { int ret = 0; down(&dev->sem); if (dev->driver) { ret = device_bind_driver(dev); if (ret == 0) ret = 1; else { dev->driver = NULL; ret = 0; } } else { ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); } up(&dev->sem); return ret; }
/** * device_attach - try to attach device to a driver. * @dev: device. * * Walk the list of drivers that the bus has and call * driver_probe_device() for each pair. If a compatible * pair is found, break out and return. * * Returns 1 if the device was bound to a driver; * 0 if no matching device was found; * -ENODEV if the device is not registered. * * When called for a USB interface, @dev->parent->sem must be held. */ int device_attach(struct device *dev) /* 将设备绑定到它的驱动程序上*/ { int ret = 0; down(&dev->sem); if (dev->driver) { /* 如果dev->driver不为空,表明当前设备dev已经和它的驱动程序进行了绑定*/ ret = device_bind_driver(dev);/* 则调用该函数在sysfs文件树中建立与其驱动程序之间的互联关系 */ if (ret == 0) ret = 1; else { dev->driver = NULL; /* 否则设置设备的驱动为空 */ ret = 0; } } else { /* 否则dev->driver = NULL,则表明当前设备对象dev还没有和它的驱动程序绑定,此时需要遍 历dev所在总线dev->bus上挂载的所有驱动程序对象 */ ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); /* 遍历挂在总线上的所有驱动对象drv,调用__device_attach进行绑定*/ } up(&dev->sem); return ret; }
/** * usb_driver_claim_interface - bind a driver to an interface * @driver: the driver to be bound * @iface: the interface to which it will be bound; must be in the * usb device's active configuration * @priv: driver data associated with that interface * * This is used by usb device drivers that need to claim more than one * interface on a device when probing (audio and acm are current examples). * No device driver should directly modify internal usb_interface or * usb_device structure members. * * Few drivers should need to use this routine, since the most natural * way to bind to an interface is to return the private data from * the driver's probe() method. * * Callers must own the device lock and the driver model's usb_bus_type.subsys * writelock. So driver probe() entries don't need extra locking, * but other call contexts may need to explicitly claim those locks. */ int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv) { struct device *dev = &iface->dev; if (dev->driver) return -EBUSY; dev->driver = &driver->driver; usb_set_intfdata(iface, priv); iface->condition = USB_INTERFACE_BOUND; mark_active(iface); /* if interface was already added, bind now; else let * the future device_add() bind it, bypassing probe() */ if (device_is_registered(dev)) device_bind_driver(dev); return 0; }
/// MBUS-DEVICE erzeugen int mbus_build(struct platform_driver * drv, unsigned char instance) { int ret = 0; int lnk_err; unsigned char mbus_slvs; DEBUG(MCT_DEBUG_LEVEL1, "%s %s()\n",__FILE__, __FUNCTION__); /// OVERLOAD SecAddr[1-3] for(mbus_slvs= 0; mbus_slvs < MBUS_SLVS; mbus_slvs++) { ret= mbus_if_secaddr_by_macaddr(&la.l2.slvs[mbus_slvs].sec_addr[1]); } pdev = platform_device_alloc(MBUS_DEVICE_INTERFACE,instance); pdev->dev.release = mbus_dev_release; platform_device_add(pdev); // MBUS-Platf.Dev registrieren platform_set_drvdata(pdev,&la); // MBUS-Platf.Dev. Datenzeiger pdev->dev.driver = &drv->driver; lnk_err = device_bind_driver(&pdev->dev); // symbolischen Link ret= mbus_if_create_bin_file(&pdev->dev.kobj); return ret; };
/** * device_attach - try to attach device to a driver. * @dev: device. * * Walk the list of drivers that the bus has and call * driver_probe_device() for each pair. If a compatible * pair is found, break out and return. * * Returns 1 if the device was bound to a driver; * 0 if no matching driver was found; * -ENODEV if the device is not registered. * * When called for a USB interface, @dev->parent->mutex must be held. */ int device_attach(struct device *dev) { int ret = 0; mutex_lock(&dev->mutex); if (dev->driver) { ret = device_bind_driver(dev); if (ret == 0) ret = 1; else { dev->driver = NULL; ret = 0; } } else { pm_runtime_get_noresume(dev); ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); pm_runtime_put_sync(dev); } mutex_unlock(&dev->mutex); return ret; }
static int i2c_bind_driver(struct udevice *bus, uint chip_addr, uint offset_len, struct udevice **devp) { struct dm_i2c_chip *chip; char name[30], *str; struct udevice *dev; int ret; snprintf(name, sizeof(name), "generic_%x", chip_addr); str = strdup(name); if (!str) return -ENOMEM; ret = device_bind_driver(bus, "i2c_generic_chip_drv", str, &dev); debug("%s: device_bind_driver: ret=%d\n", __func__, ret); if (ret) goto err_bind; /* Tell the device what we know about it */ chip = dev_get_parent_platdata(dev); chip->chip_addr = chip_addr; chip->offset_len = offset_len; ret = device_probe(dev); debug("%s: device_probe: ret=%d\n", __func__, ret); if (ret) goto err_probe; *devp = dev; return 0; err_probe: /* * If the device failed to probe, unbind it. There is nothing there * on the bus so we don't want to leave it lying around */ device_unbind(dev); err_bind: free(str); return ret; }
int blk_create_device(struct udevice *parent, const char *drv_name, const char *name, int if_type, int devnum, int blksz, lbaint_t size, struct udevice **devp) { struct blk_desc *desc; struct udevice *dev; int ret; ret = device_bind_driver(parent, drv_name, name, &dev); if (ret) return ret; desc = dev_get_uclass_platdata(dev); desc->if_type = if_type; desc->blksz = blksz; desc->lba = size / blksz; desc->part_type = PART_TYPE_UNKNOWN; desc->bdev = dev; desc->devnum = devnum; *devp = dev; return 0; }
static int gameport_bind_driver(struct gameport *gameport, struct gameport_driver *drv) { int error; gameport->dev.driver = &drv->driver; if (drv->connect(gameport, drv)) { gameport->dev.driver = NULL; return -ENODEV; } error = device_bind_driver(&gameport->dev); if (error) { dev_warn(&gameport->dev, "device_bind_driver() failed for %s (%s) and %s, error: %d\n", gameport->phys, gameport->name, drv->description, error); drv->disconnect(gameport); gameport->dev.driver = NULL; return error; } return 0; }
/// MODBUS-DEVICE erzeugen int modbus_build(struct platform_driver * drv,unsigned char slot) { int ret = 0; int lnk_err; char slotstr[2] = {0x00,0x00}; DEBUG(MCT_DEBUG_LEVEL1, "%s %s()\n",__FILE__, __FUNCTION__); /// Overload MODBUS-Addr la.l2.slvs[MODBUS_SLV_0].pri_addr += (slot*10); /// INTERFACE-NAME strcpy(dio42_dev_if_modbus,MODBUS_DEVICE_INTERFACE); slotstr[0]= slot +0x30; strcat(dio42_dev_if_modbus,slotstr); pdev = platform_device_alloc(dio42_dev_if_modbus,0); pdev->dev.release = modbus_dev_release; platform_device_add(pdev); // MODBUS-Platf.Dev registrieren platform_set_drvdata(pdev,&la); // MODBUS-Platf.Dev. Datenzeiger pdev->dev.driver = &drv->driver; lnk_err = device_bind_driver(&pdev->dev); // symbolischen Link ret= modbus_if_create_bin_file(&pdev->dev.kobj); return ret; };
/* Set up the display ready for use */ static int video_post_probe(struct udevice *dev) { struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); struct video_priv *priv = dev_get_uclass_priv(dev); char name[30], drv[15], *str; const char *drv_name = drv; struct udevice *cons; int ret; /* Set up the line and display size */ priv->fb = map_sysmem(plat->base, plat->size); priv->line_length = priv->xsize * VNBYTES(priv->bpix); priv->fb_size = priv->line_length * priv->ysize; /* Set up colours - we could in future support other colours */ #ifdef CONFIG_SYS_WHITE_ON_BLACK priv->colour_fg = 0xffffff; #else priv->colour_bg = 0xffffff; #endif video_clear(dev); /* * Create a text console device. For now we always do this, although * it might be useful to support only bitmap drawing on the device * for boards that don't need to display text. We create a TrueType * console if enabled, a rotated console if the video driver requests * it, otherwise a normal console. * * The console can be override by setting vidconsole_drv_name before * probing this video driver, or in the probe() method. * * TrueType does not support rotation at present so fall back to the * rotated console in that case. */ if (!priv->rot && IS_ENABLED(CONFIG_CONSOLE_TRUETYPE)) { snprintf(name, sizeof(name), "%s.vidconsole_tt", dev->name); strcpy(drv, "vidconsole_tt"); } else { snprintf(name, sizeof(name), "%s.vidconsole%d", dev->name, priv->rot); snprintf(drv, sizeof(drv), "vidconsole%d", priv->rot); } str = strdup(name); if (!str) return -ENOMEM; if (priv->vidconsole_drv_name) drv_name = priv->vidconsole_drv_name; ret = device_bind_driver(dev, drv_name, str, &cons); if (ret) { debug("%s: Cannot bind console driver\n", __func__); return ret; } ret = device_probe(cons); if (ret) { debug("%s: Cannot probe console driver\n", __func__); return ret; } return 0; };
/*----------------------------------------------------------------------------- * This func is used to create all the necessary stuff, bind * the fixed phy driver and register all it on the mdio_bus_type. * speed is either 10 or 100, duplex is boolean. * number is used to create multiple fixed PHYs, so that several devices can * utilize them simultaneously. *-----------------------------------------------------------------------------*/ static int fixed_mdio_register_device(int number, int speed, int duplex) { struct mii_bus *new_bus; struct fixed_info *fixed; struct phy_device *phydev; int err = 0; struct device* dev = kzalloc(sizeof(struct device), GFP_KERNEL); if (NULL == dev) return -ENOMEM; new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL); if (NULL == new_bus) { kfree(dev); return -ENOMEM; } fixed = kzalloc(sizeof(struct fixed_info), GFP_KERNEL); if (NULL == fixed) { kfree(dev); kfree(new_bus); return -ENOMEM; } fixed->regs = kzalloc(MII_REGS_NUM*sizeof(int), GFP_KERNEL); fixed->regs_num = MII_REGS_NUM; fixed->phy_status.speed = speed; fixed->phy_status.duplex = duplex; fixed->phy_status.link = 1; new_bus->name = "Fixed MII Bus", new_bus->read = &fixed_mii_read, new_bus->write = &fixed_mii_write, new_bus->reset = &fixed_mii_reset, /*set up workspace*/ fixed_mdio_update_regs(fixed); new_bus->priv = fixed; new_bus->dev = dev; dev_set_drvdata(dev, new_bus); /* create phy_device and register it on the mdio bus */ phydev = phy_device_create(new_bus, 0, 0); /* Put the phydev pointer into the fixed pack so that bus read/write code could be able to access for instance attached netdev. Well it doesn't have to do so, only in case of utilizing user-specified link-update... */ fixed->phydev = phydev; if(NULL == phydev) { err = -ENOMEM; goto device_create_fail; } phydev->irq = -1; phydev->dev.bus = &mdio_bus_type; if(number) snprintf(phydev->dev.bus_id, BUS_ID_SIZE, "fixed_%d@%d:%d", number, speed, duplex); else snprintf(phydev->dev.bus_id, BUS_ID_SIZE, "fixed@%d:%d", speed, duplex); phydev->bus = new_bus; err = device_register(&phydev->dev); if(err) { printk(KERN_ERR "Phy %s failed to register\n", phydev->dev.bus_id); goto bus_register_fail; } /* the mdio bus has phy_id match... In order not to do it artificially, we are binding the driver here by hand; it will be the same for all the fixed phys anyway. */ down_write(&phydev->dev.bus->subsys.rwsem); phydev->dev.driver = &fixed_mdio_driver.driver; err = phydev->dev.driver->probe(&phydev->dev); if(err < 0) { printk(KERN_ERR "Phy %s: problems with fixed driver\n",phydev->dev.bus_id); up_write(&phydev->dev.bus->subsys.rwsem); goto probe_fail; } device_bind_driver(&phydev->dev); up_write(&phydev->dev.bus->subsys.rwsem); return 0; probe_fail: device_unregister(&phydev->dev); bus_register_fail: kfree(phydev); device_create_fail: kfree(dev); kfree(new_bus); kfree(fixed); return err; }
int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode, const char *drv_name, const char *dev_name, struct udevice **busp, struct spi_slave **devp) { struct udevice *bus, *dev; struct dm_spi_slave_platdata *plat; bool created = false; int ret; ret = uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus); if (ret) { printf("Invalid bus %d (err=%d)\n", busnum, ret); return ret; } ret = spi_find_chip_select(bus, cs, &dev); /* * If there is no such device, create one automatically. This means * that we don't need a device tree node or platform data for the * SPI flash chip - we will bind to the correct driver. */ if (ret == -ENODEV && drv_name) { debug("%s: Binding new device '%s', busnum=%d, cs=%d, driver=%s\n", __func__, dev_name, busnum, cs, drv_name); ret = device_bind_driver(bus, drv_name, dev_name, &dev); if (ret) return ret; plat = dev_get_parent_platdata(dev); plat->cs = cs; plat->max_hz = speed; plat->mode = mode; created = true; } else if (ret) { printf("Invalid chip select %d:%d (err=%d)\n", busnum, cs, ret); return ret; } if (!device_active(dev)) { struct spi_slave *slave; ret = device_probe(dev); if (ret) goto err; slave = dev_get_parent_priv(dev); slave->dev = dev; } plat = dev_get_parent_platdata(dev); if (!speed) { speed = plat->max_hz; mode = plat->mode; } ret = spi_set_speed_mode(bus, speed, mode); if (ret) goto err; *busp = bus; *devp = dev_get_parent_priv(dev); debug("%s: bus=%p, slave=%p\n", __func__, bus, *devp); return 0; err: debug("%s: Error path, created=%d, device '%s'\n", __func__, created, dev->name); if (created) { device_remove(dev); device_unbind(dev); } return ret; }