static void ehci_update_endpt2_dev_n_port(struct usb_device *udev, struct QH *qh) { struct usb_device *ttdev; int parent_devnum; if (udev->speed != USB_SPEED_LOW && udev->speed != USB_SPEED_FULL) return; /* * For full / low speed devices we need to get the devnum and portnr of * the tt, so of the first upstream usb-2 hub, there may be usb-1 hubs * in the tree before that one! */ #ifdef CONFIG_DM_USB /* * When called from usb-uclass.c: usb_scan_device() udev->dev points * to the parent udevice, not the actual udevice belonging to the * udev as the device is not instantiated yet. So when searching * for the first usb-2 parent start with udev->dev not * udev->dev->parent . */ struct udevice *parent; struct usb_device *uparent; ttdev = udev; parent = udev->dev; uparent = dev_get_parent_priv(parent); while (uparent->speed != USB_SPEED_HIGH) { struct udevice *dev = parent; if (device_get_uclass_id(dev->parent) != UCLASS_USB_HUB) { printf("ehci: Error cannot find high-speed parent of usb-1 device\n"); return; } ttdev = dev_get_parent_priv(dev); parent = dev->parent; uparent = dev_get_parent_priv(parent); } parent_devnum = uparent->devnum; #else ttdev = udev; while (ttdev->parent && ttdev->parent->speed != USB_SPEED_HIGH) ttdev = ttdev->parent; if (!ttdev->parent) return; parent_devnum = ttdev->parent->devnum; #endif qh->qh_endpt2 |= cpu_to_hc32(QH_ENDPT2_PORTNUM(ttdev->portnr) | QH_ENDPT2_HUBADDR(parent_devnum)); }
int mcs7830_write_hwaddr(struct udevice *dev) { struct usb_device *udev = dev_get_parent_priv(dev); struct eth_pdata *pdata = dev_get_platdata(dev); return mcs7830_write_mac_common(udev, pdata->enetaddr); }
int dm_spi_claim_bus(struct udevice *dev) { struct udevice *bus = dev->parent; struct dm_spi_ops *ops = spi_get_ops(bus); struct dm_spi_bus *spi = dev_get_uclass_priv(bus); struct spi_slave *slave = dev_get_parent_priv(dev); int speed; int ret; speed = slave->max_hz; if (spi->max_hz) { if (speed) speed = min(speed, (int)spi->max_hz); else speed = spi->max_hz; } if (!speed) speed = 100000; if (speed != slave->speed) { ret = spi_set_speed_mode(bus, speed, slave->mode); if (ret) return ret; slave->speed = speed; } return ops->claim_bus ? ops->claim_bus(dev) : 0; }
static int fsl_qspi_child_pre_probe(struct udevice *dev) { struct spi_slave *slave = dev_get_parent_priv(dev); slave->max_write_size = TX_BUFFER_SIZE; return 0; }
static int testbus_child_pre_probe(struct udevice *dev) { struct dm_test_parent_data *parent_data = dev_get_parent_priv(dev); parent_data->flag += FLAG_CHILD_PROBED; return 0; }
/* Test that the bus can store data about each child */ static int test_bus_parent_data(struct unit_test_state *uts) { struct dm_test_parent_data *parent_data; struct udevice *bus, *dev; struct uclass *uc; int value; ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); /* Check that parent data is allocated */ ut_assertok(device_find_child_by_seq(bus, 0, true, &dev)); ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); ut_assertok(device_get_child_by_seq(bus, 0, &dev)); parent_data = dev_get_parent_priv(dev); ut_assert(NULL != parent_data); /* Check that it starts at 0 and goes away when device is removed */ parent_data->sum += 5; ut_asserteq(5, parent_data->sum); device_remove(dev); ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); /* Check that we can do this twice */ ut_assertok(device_get_child_by_seq(bus, 0, &dev)); parent_data = dev_get_parent_priv(dev); ut_assert(NULL != parent_data); parent_data->sum += 5; ut_asserteq(5, parent_data->sum); /* Add parent data to all children */ ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); value = 5; uclass_foreach_dev(dev, uc) { /* Ignore these if they are not on this bus */ if (dev->parent != bus) { ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); continue; } ut_assertok(device_probe(dev)); parent_data = dev_get_parent_priv(dev); parent_data->sum = value; value += 5; } /* Check it is still there */ value = 5; uclass_foreach_dev(dev, uc) { /* Ignore these if they are not on this bus */ if (dev->parent != bus) continue; parent_data = dev_get_parent_priv(dev); ut_asserteq(value, parent_data->sum); value += 5; } return 0; }
static int zynqmp_qspi_child_pre_probe(struct udevice *bus) { struct spi_slave *slave = dev_get_parent_priv(bus); struct zynqmp_qspi_priv *priv = dev_get_priv(bus->parent); slave->option = priv->is_dual; slave->bytemode = SPI_4BYTE_MODE; return 0; }
static int testbus_child_post_remove(struct udevice *dev) { struct dm_test_parent_data *parent_data = dev_get_parent_priv(dev); struct dm_test_state *dms = test_state; parent_data->flag += FLAG_CHILD_REMOVED; if (dms) dms->removed = dev; return 0; }
static int spi_flash_std_probe(struct udevice *dev) { struct spi_slave *slave = dev_get_parent_priv(dev); struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); struct spi_flash *flash; flash = dev_get_uclass_priv(dev); flash->dev = dev; flash->spi = slave; debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs); return spi_flash_probe_slave(flash); }
static int zynq_qspi_child_pre_probe(struct udevice *bus) { struct spi_slave *slave = dev_get_parent_priv(bus); struct zynq_qspi_priv *priv = dev_get_priv(bus->parent); slave->option = priv->is_dual; slave->dio = priv->is_dio; slave->op_mode_rx = SPI_OPM_RX_QOF; slave->op_mode_tx = SPI_OPM_TX_QPP; return 0; }
/* Compatibility function - to be removed */ struct spi_slave *spi_setup_slave_fdt(const void *blob, int node, int bus_node) { struct udevice *bus, *dev; int ret; ret = uclass_get_device_by_of_offset(UCLASS_SPI, bus_node, &bus); if (ret) return NULL; ret = device_get_child_by_of_offset(bus, node, &dev); if (ret) return NULL; return dev_get_parent_priv(dev); }
int zynqmp_qspi_xfer(struct udevice *dev, unsigned int bitlen, const void *dout, void *din, unsigned long flags) { struct udevice *bus = dev->parent; struct zynqmp_qspi_priv *priv = dev_get_priv(bus); struct spi_slave *slave = dev_get_parent_priv(dev); debug("%s: priv: 0x%08lx bitlen: %d dout: 0x%08lx ", __func__, (unsigned long)priv, bitlen, (unsigned long)dout); debug("din: 0x%08lx flags: 0x%lx\n", (unsigned long)din, flags); priv->tx_buf = dout; priv->rx_buf = din; priv->len = bitlen / 8; /* * Festering sore. * Assume that the beginning of a transfer with bits to * transmit must contain a device command. */ if (dout && flags & SPI_XFER_BEGIN) priv->is_inst = 1; else priv->is_inst = 0; if (flags & SPI_XFER_END) priv->cs_change = 1; else priv->cs_change = 0; if (flags & SPI_XFER_U_PAGE) priv->u_page = 1; else priv->u_page = 0; priv->stripe = 0; priv->bus = 0; if (priv->is_dual == SF_DUAL_PARALLEL_FLASH) { if (flags & SPI_XFER_MASK) priv->bus = (flags & SPI_XFER_MASK) >> 8; if (flags & SPI_XFER_STRIPE) priv->stripe = 1; } priv->dummy_bytes = slave->dummy_bytes; zynqmp_qspi_transfer(priv); return 0; }
/* Test that the bus ops are called when a child is probed/removed */ static int dm_test_bus_parent_ops(struct unit_test_state *uts) { struct dm_test_parent_data *parent_data; struct dm_test_state *dms = uts->priv; struct udevice *bus, *dev; struct uclass *uc; test_state = dms; ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); uclass_foreach_dev(dev, uc) { /* Ignore these if they are not on this bus */ if (dev->parent != bus) continue; ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); ut_assertok(device_probe(dev)); parent_data = dev_get_parent_priv(dev); ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag); } uclass_foreach_dev(dev, uc) { /* Ignore these if they are not on this bus */ if (dev->parent != bus) continue; parent_data = dev_get_parent_priv(dev); ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag); ut_assertok(device_remove(dev)); ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); ut_asserteq_ptr(dms->removed, dev); } test_state = NULL; return 0; }
static int mcs7830_eth_probe(struct udevice *dev) { struct usb_device *udev = dev_get_parent_priv(dev); struct mcs7830_private *priv = dev_get_priv(dev); struct eth_pdata *pdata = dev_get_platdata(dev); struct ueth_data *ueth = &priv->ueth; if (mcs7830_basic_reset(udev, priv)) return 0; if (mcs7830_read_mac(udev, pdata->enetaddr)) return 0; return usb_ether_register(dev, ueth, MCS7830_RX_URB_SIZE); }
/* * st33zp24_spi_send * Send byte to TPM register according to the ST33ZP24 SPI protocol. * @param: tpm, the chip description * @param: tpm_register, the tpm tis register where the data should be written * @param: tpm_data, the tpm_data to write inside the tpm_register * @param: tpm_size, The length of the data * @return: should be zero if success else a negative error code. */ static int st33zp24_spi_write(struct udevice *dev, u8 tpm_register, const u8 *tpm_data, size_t tpm_size) { int total_length = 0, ret; struct spi_slave *slave = dev_get_parent_priv(dev); struct st33zp24_spi_phy *phy = dev_get_platdata(dev); u8 *tx_buf = (u8 *)phy->tx_buf; u8 *rx_buf = phy->rx_buf; tx_buf[total_length++] = TPM_WRITE_DIRECTION | LOCALITY0; tx_buf[total_length++] = tpm_register; if (tpm_size > 0 && tpm_register == TPM_DATA_FIFO) { tx_buf[total_length++] = tpm_size >> 8; tx_buf[total_length++] = tpm_size; }
static int spi_child_pre_probe(struct udevice *dev) { struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); struct spi_slave *slave = dev_get_parent_priv(dev); /* * This is needed because we pass struct spi_slave around the place * instead slave->dev (a struct udevice). So we have to have some * way to access the slave udevice given struct spi_slave. Once we * change the SPI API to use udevice instead of spi_slave, we can * drop this. */ slave->dev = dev; slave->max_hz = plat->max_hz; slave->mode = plat->mode; slave->wordlen = SPI_DEFAULT_WORDLEN; return 0; }
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; }
int usb_ether_register(struct udevice *dev, struct ueth_data *ueth, int rxsize) { struct usb_device *udev = dev_get_parent_priv(dev); struct usb_interface_descriptor *iface_desc; bool ep_in_found = false, ep_out_found = false; struct usb_interface *iface; const int ifnum = 0; /* Always use interface 0 */ int ret, i; iface = &udev->config.if_desc[ifnum]; iface_desc = &udev->config.if_desc[ifnum].desc; /* Initialize the ueth_data structure with some useful info */ ueth->ifnum = ifnum; ueth->subclass = iface_desc->bInterfaceSubClass; ueth->protocol = iface_desc->bInterfaceProtocol; /* * We are expecting a minimum of 3 endpoints - in, out (bulk), and int. * We will ignore any others. */ for (i = 0; i < iface_desc->bNumEndpoints; i++) { int ep_addr = iface->ep_desc[i].bEndpointAddress; /* is it an BULK endpoint? */ if ((iface->ep_desc[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { if (ep_addr & USB_DIR_IN && !ep_in_found) { ueth->ep_in = ep_addr & USB_ENDPOINT_NUMBER_MASK; ep_in_found = true; } else if (!(ep_addr & USB_DIR_IN) && !ep_out_found) { ueth->ep_out = ep_addr & USB_ENDPOINT_NUMBER_MASK; ep_out_found = true; } } /* is it an interrupt endpoint? */ if ((iface->ep_desc[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) { ueth->ep_int = iface->ep_desc[i].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; ueth->irqinterval = iface->ep_desc[i].bInterval; } } debug("Endpoints In %d Out %d Int %d\n", ueth->ep_in, ueth->ep_out, ueth->ep_int); /* Do some basic sanity checks, and bail if we find a problem */ if (!ueth->ep_in || !ueth->ep_out || !ueth->ep_int) { debug("%s: %s: Cannot find endpoints\n", __func__, dev->name); return -ENXIO; } ueth->rxsize = rxsize; ueth->rxbuf = memalign(ARCH_DMA_MINALIGN, rxsize); if (!ueth->rxbuf) return -ENOMEM; ret = usb_set_interface(udev, iface_desc->bInterfaceNumber, ifnum); if (ret) { debug("%s: %s: Cannot set interface: %d\n", __func__, dev->name, ret); return ret; } ueth->pusb_dev = udev; return 0; }
static int mcs7830_eth_start(struct udevice *dev) { struct usb_device *udev = dev_get_parent_priv(dev); return mcs7830_init_common(udev); }
/** * Setup an xHCI virtual device for a Set Address command * * @param udev pointer to the Device Data Structure * @return returns negative value on failure else 0 on success */ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, struct usb_device *udev, int hop_portnr) { struct xhci_virt_device *virt_dev; struct xhci_ep_ctx *ep0_ctx; struct xhci_slot_ctx *slot_ctx; u32 port_num = 0; u64 trb_64 = 0; int slot_id = udev->slot_id; int speed = udev->speed; int route = 0; #if CONFIG_IS_ENABLED(DM_USB) struct usb_device *dev = udev; struct usb_hub_device *hub; #endif virt_dev = ctrl->devs[slot_id]; BUG_ON(!virt_dev); /* Extract the EP0 and Slot Ctrl */ ep0_ctx = xhci_get_ep_ctx(ctrl, virt_dev->in_ctx, 0); slot_ctx = xhci_get_slot_ctx(ctrl, virt_dev->in_ctx); /* Only the control endpoint is valid - one endpoint context */ slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1)); #if CONFIG_IS_ENABLED(DM_USB) /* Calculate the route string for this device */ port_num = dev->portnr; while (!usb_hub_is_root_hub(dev->dev)) { hub = dev_get_uclass_priv(dev->dev); /* * Each hub in the topology is expected to have no more than * 15 ports in order for the route string of a device to be * unique. SuperSpeed hubs are restricted to only having 15 * ports, but FS/LS/HS hubs are not. The xHCI specification * says that if the port number the device is greater than 15, * that portion of the route string shall be set to 15. */ if (port_num > 15) port_num = 15; route |= port_num << (hub->hub_depth * 4); dev = dev_get_parent_priv(dev->dev); port_num = dev->portnr; dev = dev_get_parent_priv(dev->dev->parent); } debug("route string %x\n", route); #endif slot_ctx->dev_info |= route; switch (speed) { case USB_SPEED_SUPER: slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SS); break; case USB_SPEED_HIGH: slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_HS); break; case USB_SPEED_FULL: slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_FS); break; case USB_SPEED_LOW: slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_LS); break; default: /* Speed was set earlier, this shouldn't happen. */ BUG(); } #if CONFIG_IS_ENABLED(DM_USB) /* Set up TT fields to support FS/LS devices */ if (speed == USB_SPEED_LOW || speed == USB_SPEED_FULL) { struct udevice *parent = udev->dev; dev = udev; do { port_num = dev->portnr; dev = dev_get_parent_priv(parent); if (usb_hub_is_root_hub(dev->dev)) break; parent = dev->dev->parent; } while (dev->speed != USB_SPEED_HIGH); if (!usb_hub_is_root_hub(dev->dev)) { hub = dev_get_uclass_priv(dev->dev); if (hub->tt.multi) slot_ctx->dev_info |= cpu_to_le32(DEV_MTT); slot_ctx->tt_info |= cpu_to_le32(TT_PORT(port_num)); slot_ctx->tt_info |= cpu_to_le32(TT_SLOT(dev->slot_id)); } } #endif port_num = hop_portnr; debug("port_num = %d\n", port_num); slot_ctx->dev_info2 |= cpu_to_le32(((port_num & ROOT_HUB_PORT_MASK) << ROOT_HUB_PORT_SHIFT)); /* Step 4 - ring already allocated */ /* Step 5 */ ep0_ctx->ep_info2 = cpu_to_le32(CTRL_EP << EP_TYPE_SHIFT); debug("SPEED = %d\n", speed); switch (speed) { case USB_SPEED_SUPER: ep0_ctx->ep_info2 |= cpu_to_le32(((512 & MAX_PACKET_MASK) << MAX_PACKET_SHIFT)); debug("Setting Packet size = 512bytes\n"); break; case USB_SPEED_HIGH: /* USB core guesses at a 64-byte max packet first for FS devices */ case USB_SPEED_FULL: ep0_ctx->ep_info2 |= cpu_to_le32(((64 & MAX_PACKET_MASK) << MAX_PACKET_SHIFT)); debug("Setting Packet size = 64bytes\n"); break; case USB_SPEED_LOW: ep0_ctx->ep_info2 |= cpu_to_le32(((8 & MAX_PACKET_MASK) << MAX_PACKET_SHIFT)); debug("Setting Packet size = 8bytes\n"); break; default: /* New speed? */ BUG(); } /* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */ ep0_ctx->ep_info2 |= cpu_to_le32(((0 & MAX_BURST_MASK) << MAX_BURST_SHIFT) | ((3 & ERROR_COUNT_MASK) << ERROR_COUNT_SHIFT)); trb_64 = (uintptr_t)virt_dev->eps[0].ring->first_seg->trbs; ep0_ctx->deq = cpu_to_le64(trb_64 | virt_dev->eps[0].ring->cycle_state); /* * xHCI spec 6.2.3: * software shall set 'Average TRB Length' to 8 for control endpoints. */ ep0_ctx->tx_info = cpu_to_le32(EP_AVG_TRB_LENGTH(8)); /* Steps 7 and 8 were done in xhci_alloc_virt_device() */ xhci_flush_cache((uintptr_t)ep0_ctx, sizeof(struct xhci_ep_ctx)); xhci_flush_cache((uintptr_t)slot_ctx, sizeof(struct xhci_slot_ctx)); }
int hub_port_reset(struct udevice *dev, int port, unsigned short *portstat) { struct usb_device *udev = dev_get_parent_priv(dev); return legacy_hub_port_reset(udev, port, portstat); }
int usb_hub_scan(struct udevice *hub) { struct usb_device *udev = dev_get_parent_priv(hub); return usb_hub_configure(udev); }