Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 236dd4d1 authored by Anton Vorontsov's avatar Anton Vorontsov Committed by Greg Kroah-Hartman
Browse files

USB: Driver for Freescale QUICC Engine USB Host Controller



This patch adds support for the FHCI USB controller, as found
in the Freescale MPC836x and MPC832x processors. It can support
Full or Low speed modes.

Quite a lot the hardware is doing by itself (SOF generation, CRC
generation and checking), though scheduling and retransmission is on
software's shoulders.

This controller does not integrate the root hub, so this driver also
fakes one-port hub. External hub is required to support more than
one device.

Signed-off-by: default avatarAnton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent fc91be2a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ obj-$(CONFIG_USB_EHCI_HCD) += host/
obj-$(CONFIG_USB_ISP116X_HCD)	+= host/
obj-$(CONFIG_USB_OHCI_HCD)	+= host/
obj-$(CONFIG_USB_UHCI_HCD)	+= host/
obj-$(CONFIG_USB_FHCI_HCD)	+= host/
obj-$(CONFIG_USB_SL811_HCD)	+= host/
obj-$(CONFIG_USB_U132_HCD)	+= host/
obj-$(CONFIG_USB_R8A66597_HCD)	+= host/
+17 −0
Original line number Diff line number Diff line
@@ -239,6 +239,23 @@ config USB_UHCI_HCD
	  To compile this driver as a module, choose M here: the
	  module will be called uhci-hcd.

config USB_FHCI_HCD
	tristate "Freescale QE USB Host Controller support"
	depends on USB && OF_GPIO && QE_GPIO && QUICC_ENGINE
	select FSL_GTM
	select QE_USB
	help
	  This driver enables support for Freescale QE USB Host Controller
	  (as found on MPC8360 and MPC8323 processors), the driver supports
	  Full and Low Speed USB.

config FHCI_DEBUG
	bool "Freescale QE USB Host Controller debug support"
	depends on USB_FHCI_HCD && DEBUG_FS
	help
	  Say "y" to see some FHCI debug information and statistics
	  throught debugfs.

config USB_U132_HCD
	tristate "Elan U132 Adapter Host Controller"
	depends on USB && USB_FTDI_ELAN
+6 −0
Original line number Diff line number Diff line
@@ -7,6 +7,11 @@ ifeq ($(CONFIG_USB_DEBUG),y)
endif

isp1760-objs := isp1760-hcd.o isp1760-if.o
fhci-objs := fhci-hcd.o fhci-hub.o fhci-q.o fhci-mem.o \
	     fhci-tds.o fhci-sched.o
ifeq ($(CONFIG_FHCI_DEBUG),y)
fhci-objs += fhci-dbg.o
endif

obj-$(CONFIG_USB_WHCI_HCD)	+= whci/

@@ -17,6 +22,7 @@ obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
obj-$(CONFIG_USB_ISP116X_HCD)	+= isp116x-hcd.o
obj-$(CONFIG_USB_OHCI_HCD)	+= ohci-hcd.o
obj-$(CONFIG_USB_UHCI_HCD)	+= uhci-hcd.o
obj-$(CONFIG_USB_FHCI_HCD)	+= fhci.o
obj-$(CONFIG_USB_SL811_HCD)	+= sl811-hcd.o
obj-$(CONFIG_USB_SL811_CS)	+= sl811_cs.o
obj-$(CONFIG_USB_U132_HCD)	+= u132-hcd.o
+139 −0
Original line number Diff line number Diff line
/*
 * Freescale QUICC Engine USB Host Controller Driver
 *
 * Copyright (c) Freescale Semicondutor, Inc. 2006.
 *               Shlomi Gridish <gridish@freescale.com>
 *               Jerry Huang <Chang-Ming.Huang@freescale.com>
 * Copyright (c) Logic Product Development, Inc. 2007
 *               Peter Barada <peterb@logicpd.com>
 * Copyright (c) MontaVista Software, Inc. 2008.
 *               Anton Vorontsov <avorontsov@ru.mvista.com>
 *
 * This program is free software; you can redistribute  it and/or modify it
 * under  the terms of  the GNU General  Public License as published by the
 * Free Software Foundation;  either version 2 of the  License, or (at your
 * option) any later version.
 */

#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/usb.h>
#include "../core/hcd.h"
#include "fhci.h"

void fhci_dbg_isr(struct fhci_hcd *fhci, int usb_er)
{
	int i;

	if (usb_er == -1) {
		fhci->usb_irq_stat[12]++;
		return;
	}

	for (i = 0; i < 12; ++i) {
		if (usb_er & (1 << i))
			fhci->usb_irq_stat[i]++;
	}
}

static int fhci_dfs_regs_show(struct seq_file *s, void *v)
{
	struct fhci_hcd *fhci = s->private;
	struct fhci_regs __iomem *regs = fhci->regs;

	seq_printf(s,
		"mode: 0x%x\n" "addr: 0x%x\n"
		"command: 0x%x\n" "ep0: 0x%x\n"
		"event: 0x%x\n" "mask: 0x%x\n"
		"status: 0x%x\n" "SOF timer: %d\n"
		"frame number: %d\n"
		"lines status: 0x%x\n",
		in_8(&regs->usb_mod), in_8(&regs->usb_addr),
		in_8(&regs->usb_comm), in_be16(&regs->usb_ep[0]),
		in_be16(&regs->usb_event), in_be16(&regs->usb_mask),
		in_8(&regs->usb_status), in_be16(&regs->usb_sof_tmr),
		in_be16(&regs->usb_frame_num),
		fhci_ioports_check_bus_state(fhci));

	return 0;
}

static int fhci_dfs_irq_stat_show(struct seq_file *s, void *v)
{
	struct fhci_hcd *fhci = s->private;
	int *usb_irq_stat = fhci->usb_irq_stat;

	seq_printf(s,
		"RXB: %d\n" "TXB: %d\n" "BSY: %d\n"
		"SOF: %d\n" "TXE0: %d\n" "TXE1: %d\n"
		"TXE2: %d\n" "TXE3: %d\n" "IDLE: %d\n"
		"RESET: %d\n" "SFT: %d\n" "MSF: %d\n"
		"IDLE_ONLY: %d\n",
		usb_irq_stat[0], usb_irq_stat[1], usb_irq_stat[2],
		usb_irq_stat[3], usb_irq_stat[4], usb_irq_stat[5],
		usb_irq_stat[6], usb_irq_stat[7], usb_irq_stat[8],
		usb_irq_stat[9], usb_irq_stat[10], usb_irq_stat[11],
		usb_irq_stat[12]);

	return 0;
}

static int fhci_dfs_regs_open(struct inode *inode, struct file *file)
{
	return single_open(file, fhci_dfs_regs_show, inode->i_private);
}

static int fhci_dfs_irq_stat_open(struct inode *inode, struct file *file)
{
	return single_open(file, fhci_dfs_irq_stat_show, inode->i_private);
}

static const struct file_operations fhci_dfs_regs_fops = {
	.open = fhci_dfs_regs_open,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
};

static const struct file_operations fhci_dfs_irq_stat_fops = {
	.open = fhci_dfs_irq_stat_open,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
};

void fhci_dfs_create(struct fhci_hcd *fhci)
{
	struct device *dev = fhci_to_hcd(fhci)->self.controller;

	fhci->dfs_root = debugfs_create_dir(dev->bus_id, NULL);
	if (!fhci->dfs_root) {
		WARN_ON(1);
		return;
	}

	fhci->dfs_regs = debugfs_create_file("regs", S_IFREG | S_IRUGO,
		fhci->dfs_root, fhci, &fhci_dfs_regs_fops);

	fhci->dfs_irq_stat = debugfs_create_file("irq_stat",
		S_IFREG | S_IRUGO, fhci->dfs_root, fhci,
		&fhci_dfs_irq_stat_fops);

	WARN_ON(!fhci->dfs_regs || !fhci->dfs_irq_stat);
}

void fhci_dfs_destroy(struct fhci_hcd *fhci)
{
	if (!fhci->dfs_root)
		return;

	if (fhci->dfs_irq_stat)
		debugfs_remove(fhci->dfs_irq_stat);

	if (fhci->dfs_regs)
		debugfs_remove(fhci->dfs_regs);

	debugfs_remove(fhci->dfs_root);
}
+836 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading