/* disable the usb controller */ if (usb->port_status == FHCI_PORT_FULL ||
usb->port_status == FHCI_PORT_LOW)
fhci_device_disconnected_interrupt(fhci);
/* initialize the fhci_usb struct and the corresponding data staruct */ staticstruct fhci_usb *fhci_create_lld(struct fhci_hcd *fhci)
{ struct fhci_usb *usb;
/* allocate memory for SCC data structure */
usb = kzalloc(sizeof(*usb), GFP_KERNEL); if (!usb) return NULL;
ret = fhci_mem_init(fhci); if (ret) {
fhci_err(fhci, "failed to allocate memory\n"); goto err;
}
fhci->usb_lld = fhci_create_lld(fhci); if (!fhci->usb_lld) {
fhci_err(fhci, "low level driver config failed\n");
ret = -ENOMEM; goto err;
}
ret = fhci_usb_init(fhci); if (ret) {
fhci_err(fhci, "low level driver initialize failed\n"); goto err;
}
spin_lock_init(&fhci->lock);
/* connect the virtual root hub */
fhci->vroot_hub->dev_num = 1; /* this field may be needed to fix */
fhci->vroot_hub->hub.wHubStatus = 0;
fhci->vroot_hub->hub.wHubChange = 0;
fhci->vroot_hub->port.wPortStatus = 0;
fhci->vroot_hub->port.wPortChange = 0;
hcd->state = HC_STATE_RUNNING;
/* * From here on, hub_wq concurrently accesses the root * hub; drivers will be talking to enumerated devices. * (On restart paths, hub_wq already knows about the root * hub and could find work as soon as we wrote FLAG_CF.) * * Before this point the HC was idle/ready. After, hub_wq * and device drivers may start it running.
*/
fhci_usb_enable(fhci); return 0;
err:
fhci_mem_free(fhci); return ret;
}
switch (usb_pipetype(pipe)) { case PIPE_CONTROL: /* 1 td fro setup,1 for ack */
size = 2;
fallthrough; case PIPE_BULK: /* one td for every 4096 bytes(can be up to 8k) */
size += urb->transfer_buffer_length / 4096; /* ...add for any remaining bytes... */ if ((urb->transfer_buffer_length % 4096) != 0)
size++; /* ..and maybe a zero length packet to wrap it up */ if (size == 0)
size++; elseif ((urb->transfer_flags & URB_ZERO_PACKET) != 0
&& (urb->transfer_buffer_length
% usb_maxpacket(urb->dev, pipe)) != 0)
size++; break; case PIPE_ISOCHRONOUS:
size = urb->number_of_packets; if (size <= 0) return -EINVAL; for (i = 0; i < urb->number_of_packets; i++) {
urb->iso_frame_desc[i].actual_length = 0;
urb->iso_frame_desc[i].status = (u32) (-EXDEV);
} break; case PIPE_INTERRUPT:
size = 1;
}
/* allocate the private part of the URB */
urb_priv = kzalloc(sizeof(*urb_priv), mem_flags); if (!urb_priv) return -ENOMEM;
/* allocate the private part of the URB */
urb_priv->tds = kcalloc(size, sizeof(*urb_priv->tds), mem_flags); if (!urb_priv->tds) {
kfree(urb_priv); return -ENOMEM;
}
spin_lock_irqsave(&fhci->lock, flags);
ret = usb_hcd_link_urb_to_ep(hcd, urb); if (ret) goto err;
/* fill the private part of the URB */
urb_priv->num_of_tds = size;
/* FHCI registers. */
ret = of_address_to_resource(node, 0, &usb_regs); if (ret) {
dev_err(dev, "could not get regs\n"); goto err_regs;
}
hcd->regs = ioremap(usb_regs.start, resource_size(&usb_regs)); if (!hcd->regs) {
dev_err(dev, "could not ioremap regs\n");
ret = -ENOMEM; goto err_regs;
}
fhci->regs = hcd->regs;
/* Parameter RAM. */
iprop = of_get_property(node, "reg", &size); if (!iprop || size < sizeof(*iprop) * 4) {
dev_err(dev, "can't get pram offset\n");
ret = -EINVAL; goto err_pram;
}
pram_addr = cpm_muram_alloc(FHCI_PRAM_SIZE, 64); if (IS_ERR_VALUE(pram_addr)) {
dev_err(dev, "failed to allocate usb pram\n");
ret = -ENOMEM; goto err_pram;
}
/* GPIOs and pins */ for (i = 0; i < NUM_GPIOS; i++) { if (i < GPIO_SPEED)
fhci->gpiods[i] = devm_gpiod_get_index(dev,
NULL, i, GPIOD_IN);
else
fhci->gpiods[i] = devm_gpiod_get_index_optional(dev,
NULL, i, GPIOD_OUT_LOW);
if (IS_ERR(fhci->gpiods[i])) {
dev_err(dev, "incorrect GPIO%d: %ld\n",
i, PTR_ERR(fhci->gpiods[i])); goto err_gpios;
} if (!fhci->gpiods[i]) {
dev_info(dev, "assuming board doesn't have " "%s gpio\n", i == GPIO_SPEED ? "speed" : "power");
}
}
for (j = 0; j < NUM_PINS; j++) {
fhci->pins[j] = qe_pin_request(dev, j); if (IS_ERR(fhci->pins[j])) {
ret = PTR_ERR(fhci->pins[j]);
dev_err(dev, "can't get pin %d: %d\n", j, ret); goto err_pins;
}
}
/* Frame limit timer and its interrupt. */
fhci->timer = gtm_get_timer16(); if (IS_ERR(fhci->timer)) {
ret = PTR_ERR(fhci->timer);
dev_err(dev, "failed to request qe timer: %i", ret); goto err_get_timer;
}
ret = request_irq(fhci->timer->irq, fhci_frame_limit_timer_irq,
0, "qe timer (usb)", hcd); if (ret) {
dev_err(dev, "failed to request timer irq"); goto err_timer_irq;
}
/* USB Host interrupt. */
usb_irq = irq_of_parse_and_map(node, 0); if (!usb_irq) {
dev_err(dev, "could not get usb irq\n");
ret = -EINVAL; goto err_usb_irq;
}
/* Clocks. */
sprop = of_get_property(node, "fsl,fullspeed-clock", NULL); if (sprop) {
fhci->fullspeed_clk = qe_clock_source(sprop); if (fhci->fullspeed_clk == QE_CLK_DUMMY) {
dev_err(dev, "wrong fullspeed-clock\n");
ret = -EINVAL; goto err_clocks;
}
}
sprop = of_get_property(node, "fsl,lowspeed-clock", NULL); if (sprop) {
fhci->lowspeed_clk = qe_clock_source(sprop); if (fhci->lowspeed_clk == QE_CLK_DUMMY) {
dev_err(dev, "wrong lowspeed-clock\n");
ret = -EINVAL; goto err_clocks;
}
}
if (fhci->fullspeed_clk == QE_CLK_NONE &&
fhci->lowspeed_clk == QE_CLK_NONE) {
dev_err(dev, "no clocks specified\n");
ret = -EINVAL; goto err_clocks;
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.18Bemerkung:
(vorverarbeitet am 2026-04-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.