void fhci_host_transmit_actual_frame(struct fhci_usb *usb) { u16 tb_ptr; u16 td_status; struct usb_td __iomem *td; struct endpoint *ep = usb->ep0; tb_ptr = in_be16(&ep->ep_pram_ptr->tx_bd_ptr); td = cpm_muram_addr(tb_ptr); if (in_be32(&td->buf_ptr) == DUMMY_BD_BUFFER) { struct usb_td __iomem *old_td = td; ep->already_pushed_dummy_bd = false; td_status = in_be16(&td->status); /* gets the next TD in the ring */ td = next_bd(ep->td_base, td, td_status); tb_ptr = cpm_muram_offset(td); out_be16(&ep->ep_pram_ptr->tx_bd_ptr, tb_ptr); /* start transmit only if we have something in the TDs */ if (in_be16(&td->status) & TD_R) out_8(&usb->fhci->regs->usb_comm, USB_CMD_STR_FIFO); if (in_be32(&ep->conf_td->buf_ptr) == DUMMY_BD_BUFFER) { out_be32(&old_td->buf_ptr, 0); ep->conf_td = next_bd(ep->td_base, ep->conf_td, td_status); } else { out_be32(&old_td->buf_ptr, DUMMY2_BD_BUFFER); } } }
/** * cpm_muram_alloc - allocate the requested size worth of multi-user ram * @size: number of bytes to allocate * @align: requested alignment, in bytes * * This function returns an offset into the muram area. * Use cpm_dpram_addr() to get the virtual address of the area. * Use cpm_muram_free() to free the allocation. */ unsigned long cpm_muram_alloc(unsigned long size, unsigned long align) { unsigned long start; unsigned long flags; spin_lock_irqsave(&cpm_muram_lock, flags); cpm_muram_info.alignment = align; start = rh_alloc(&cpm_muram_info, size, "commproc"); memset(cpm_muram_addr(start), 0, size); spin_unlock_irqrestore(&cpm_muram_lock, flags); return start; }
/* * Flush all transmitted packets from TDs in the actual frame. * This routine is called when something wrong with the controller and * we want to get rid of the actual frame and start again next frame */ void fhci_flush_actual_frame(struct fhci_usb *usb) { u8 mode; u16 tb_ptr; u16 extra_data; u16 td_status; u32 buf_ptr; struct usb_td __iomem *td; struct endpoint *ep = usb->ep0; /* disable the USB controller */ mode = in_8(&usb->fhci->regs->usb_mod); out_8(&usb->fhci->regs->usb_mod, mode & ~USB_MODE_EN); tb_ptr = in_be16(&ep->ep_pram_ptr->tx_bd_ptr); td = cpm_muram_addr(tb_ptr); td_status = in_be16(&td->status); buf_ptr = in_be32(&td->buf_ptr); extra_data = in_be16(&td->extra); do { if (td_status & TD_R) { out_be16(&td->status, (td_status & ~TD_R) | TD_TO); } else { out_be32(&td->buf_ptr, 0); ep->already_pushed_dummy_bd = false; break; } /* advance the TD pointer */ td = next_bd(ep->td_base, td, td_status); td_status = in_be16(&td->status); buf_ptr = in_be32(&td->buf_ptr); extra_data = in_be16(&td->extra); } while ((td_status & TD_R) || buf_ptr); fhci_td_transaction_confirm(usb); out_be16(&ep->ep_pram_ptr->tx_bd_ptr, in_be16(&ep->ep_pram_ptr->tx_base)); out_be32(&ep->ep_pram_ptr->tx_state, 0); out_be16(&ep->ep_pram_ptr->tx_cnt, 0); ep->empty_td = ep->td_base; ep->conf_td = ep->td_base; usb->actual_frame->frame_status = FRAME_TIMER_END_TRANSMISSION; /* reset the event register */ out_be16(&usb->fhci->regs->usb_event, 0xffff); /* enable the USB controller */ out_8(&usb->fhci->regs->usb_mod, mode | USB_MODE_EN); }
void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port, struct device_node *np) { void __iomem *pram; unsigned long offset; struct resource res; unsigned long len; /* Don't remap parameter RAM if it has already been initialized * during console setup. */ if (IS_SMC(port) && port->smcup) return port->smcup; else if (!IS_SMC(port) && port->sccup) return port->sccup; if (of_address_to_resource(np, 1, &res)) return NULL; len = 1 + res.end - res.start; pram = ioremap(res.start, len); if (!pram) return NULL; if (!IS_SMC(port)) return pram; if (len != 2) { printk(KERN_WARNING "cpm_uart[%d]: device tree references " "SMC pram, using boot loader/wrapper pram mapping. " "Please fix your device tree to reference the pram " "base register instead.\n", port->port.line); return pram; } offset = cpm_dpalloc(PROFF_SMC_SIZE, 64); out_be16(pram, offset); iounmap(pram); return cpm_muram_addr(offset); }
/* * create the endpoint structure * * arguments: * usb A pointer to the data structure of the USB * data_mem The data memory partition(BUS) * ring_len TD ring length */ u32 fhci_create_ep(struct fhci_usb *usb, enum fhci_mem_alloc data_mem, u32 ring_len) { struct endpoint *ep; struct usb_td __iomem *td; unsigned long ep_offset; char *err_for = "enpoint PRAM"; int ep_mem_size; u32 i; /* we need at least 3 TDs in the ring */ if (!(ring_len > 2)) { fhci_err(usb->fhci, "illegal TD ring length parameters\n"); return -EINVAL; } ep = kzalloc(sizeof(*ep), GFP_KERNEL); if (!ep) return -ENOMEM; ep_mem_size = ring_len * sizeof(*td) + sizeof(struct fhci_ep_pram); ep_offset = cpm_muram_alloc(ep_mem_size, 32); if (IS_ERR_VALUE(ep_offset)) goto err; ep->td_base = cpm_muram_addr(ep_offset); /* zero all queue pointers */ if (cq_new(&ep->conf_frame_Q, ring_len + 2) || cq_new(&ep->empty_frame_Q, ring_len + 2) || cq_new(&ep->dummy_packets_Q, ring_len + 2)) { err_for = "frame_queues"; goto err; } for (i = 0; i < (ring_len + 1); i++) { struct packet *pkt; u8 *buff; pkt = kmalloc(sizeof(*pkt), GFP_KERNEL); if (!pkt) { err_for = "frame"; goto err; } buff = kmalloc(1028 * sizeof(*buff), GFP_KERNEL); if (!buff) { kfree(pkt); err_for = "buffer"; goto err; } cq_put(&ep->empty_frame_Q, pkt); cq_put(&ep->dummy_packets_Q, buff); } /* we put the endpoint parameter RAM right behind the TD ring */ ep->ep_pram_ptr = (void __iomem *)ep->td_base + sizeof(*td) * ring_len; ep->conf_td = ep->td_base; ep->empty_td = ep->td_base; ep->already_pushed_dummy_bd = false; /* initialize tds */ td = ep->td_base; for (i = 0; i < ring_len; i++) { out_be32(&td->buf_ptr, 0); out_be16(&td->status, 0); out_be16(&td->length, 0); out_be16(&td->extra, 0); td++; } td--; out_be16(&td->status, TD_W); /* for last TD set Wrap bit */ out_be16(&td->length, 0); /* endpoint structure has been created */ usb->ep0 = ep; return 0; err: fhci_ep0_free(usb); kfree(ep); fhci_err(usb->fhci, "no memory for the %s\n", err_for); return -ENOMEM; }