Example #1
0
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;
}
Example #3
0
/*
 * 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);
}
Example #5
0
/*
 * 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;
}