分享

Pre-2.6.13 isp116x-hcd

 Archangel 2007-08-07


The first version of the driver was published on the linux-usb-devel mailing list on Jan 3, 2005. By now the driver is included in the 2.6.13 and later mainline kernels. A version for the 2.6.10 and a version for the 2.6.12 kernels are downloadable. These driver versions are not maintained; I have no intention to backport fixes or improvements to these past versions. Also, I have no plans to put up a driver for 2.6.11. If you happen to need to backport from a newer driver version then please be aware that through these kernel versions extensive USB core changes were made, which affected host controller drivers. I.e., USB host controller glue layer changed incompatibly from 2.6.10 to 2.6.11 as well as from 2.6.11 to 2.6.12.

Known bugs

Power switching of ports does not work. To avoid this bug, the ports should be always powered. I.e., in your platform-specific code you should define no_power_switching = 1

Platform support code

Here are a few recommendations about setting the members of the struct isp116x_platform_data, which you must define and initialize to reflect specifics of your platform. As a rule, set a struct member iff you know you need to set it.

int_act_high, int_edge_triggered
Whenever your platform supports level-triggered interrupts, use these. Success with configuring level-triggered interrupts has been reported even on platforms, which don‘t support level-triggered interrupts, but for which the 166 ns edge-triggered interrupt pulse is too short to be detected (like PXA255 SoC).
no_power_switching
Set this to 1 to avoid a bug in the driver.
reset
It has been recommended in the past to implement and use hardware reset as it is more thorough than the software reset. However, recently the software reset has been working too. Set it to NULL to use software reset.
clock
This hasn‘t been tested at all. Set to NULL.
delay
Read CAREFULLY the comments in both include/linux/usb_isp116x.h and drivers/usb/host/isp116x-hcd.c as wrong choice of the delay type or an incorrect implementation of the platform-specific delay function is the major source of problems when trying to get the driver working.

Here is an example platform code I used on my LH7A400 (a SoC with an ARM core) based boards; in my case it went into arch/arm/mach-lh7a40x/arch-lpd7a40x.c file.

#include <linux/usb_isp116x.h>
/* GPIO port A bit 2 is hardware reset for isp116x */
#define ISP116x_RESET_PORT       GPIO_PAD
#define ISP116x_RESET_DIR_PORT   GPIO_PADD
#define ISP116x_RESET_BIT        (1<<2)
/* Hardware reset */
static void isp116x_pfm_reset(struct device *dev, int set)
{
unsigned long flags;
local_irq_save(flags);
if (set) {
ISP116x_RESET_PORT &= ~ISP116x_RESET_BIT;
barrier();
ISP116x_RESET_DIR_PORT |= ISP116x_RESET_BIT;
} else {
ISP116x_RESET_PORT |= ISP116x_RESET_BIT;
barrier();
ISP116x_RESET_DIR_PORT |= ISP116x_RESET_BIT;
}
local_irq_restore(flags);
}
/* Platform delay */
static void isp116x_pfm_delay(struct device *dev, int delay)
{
/* On this platform, we work with 200MHz clock, giving
5 ns per instruction. The cycle below involves 2
instructions and we lose 2 more instruction times due
to pipeline flush at jump. I.e., we consume 20 ns
per cycle.
*/
int cyc = delay / 20;
__asm__ volatile ("0:\n"
"     subs  %0, %1, #1\n"
"     bge   0b\n"
:"=r" (cyc)
:"0"(cyc)
);
}
/* Define chip configuration */
static struct isp116x_platform_data isp116x_pfm_data = {
.sel15Kres = 1,
.remote_wakeup_enable = 1,
.no_power_switching = 1,
.reset = isp116x_pfm_reset,
.delay = isp116x_pfm_delay,
};
/* Define chip address and IRQ line */
static struct resource isp116x_pfm_resources[] = {
[0] = {			/// data (A0 = 0)
.start = USB_IO_PHYS,
.end = USB_IO_PHYS + 1,
.flags = IORESOURCE_MEM,
},
[1] = {			/// addr (A0 = 1)
.start = USB_IO_PHYS + 2,
.end = USB_IO_PHYS + 3,
.flags = IORESOURCE_MEM,
},
[2] = {
.start = IRQ_USB,
.end = IRQ_USB,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device isp116x_pfm_usbhost_device = {
.name = "isp116x-hcd",
.num_resources = ARRAY_SIZE(isp116x_pfm_resources),
.resource = isp116x_pfm_resources,
.dev.platform_data = &isp116x_pfm_data,
};
static struct platform_device *lpd7a40x_devs[] __initdata = {
...
&isp116x_pfm_usbhost_device,
};

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多