u-boot的usb模块初始化

u-boot的USB模块在需要的时候才会进行初始化。也就是调用usb start命令时才会进行初始化。

以2013.01版本为例,说明下初始化的过程

首先是usb命令的定义

U_BOOT_CMD(
	usb,	5,	1,	do_usb,
	"USB sub-system",
	"start - start (scan) USB controller\n"
	"usb reset - reset (rescan) USB controller\n"
	"usb stop [f] - stop USB [f]=force stop\n"
	"usb tree - show USB device tree\n"
	"usb info [dev] - show available USB devices\n"
	"usb storage - show details of USB storage devices\n"
	"usb dev [dev] - show or set current USB storage device\n"
	"usb part [dev] - print partition table of one or all USB storage"
	" devices\n"
	"usb read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n"
	"    to memory address `addr'\n"
	"usb write addr blk# cnt - write `cnt' blocks starting at block `blk#'\n"
	"    from memory address `addr'"
);

可以看到usb命令的入口都是在do_usb函数实现

static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{

	int i;
	struct usb_device *dev = NULL;
	extern char usb_started;
#ifdef CONFIG_USB_STORAGE
	block_dev_desc_t *stor_dev;
#endif

	if (argc < 2)
		return CMD_RET_USAGE;

	if ((strncmp(argv[1], "reset", 5) == 0) ||
		 (strncmp(argv[1], "start", 5) == 0)) {
		bootstage_mark_name(BOOTSTAGE_ID_USB_START, "usb_start");
		usb_stop();
		printf("(Re)start USB...\n");
		if (usb_init() >= 0) {
#ifdef CONFIG_USB_STORAGE
			/* try to recognize storage devices immediately */
			usb_stor_curr_dev = usb_stor_scan(1);
#endif
#ifdef CONFIG_USB_HOST_ETHER
			/* try to recognize ethernet devices immediately */
			usb_ether_curr_dev = usb_host_eth_scan(1);
#endif
#ifdef CONFIG_USB_KEYBOARD
			drv_usb_kbd_init();
#endif
		}
		return 0;
	}

在进行usb start时会调用usb_init来初始化usb控制器,usb_init 作为一个设备抽象层初始化在common/usb.c中定义

int usb_init(void)
{
	void *ctrl;
	struct usb_device *dev;
	int i, start_index = 0;

	dev_index = 0;
	asynch_allowed = 1;
	usb_hub_reset();

	/* first make all devices unknown */
	for (i = 0; i < USB_MAX_DEVICE; i++) {
		memset(&usb_dev[i], 0, sizeof(struct usb_device));
		usb_dev[i].devnum = -1;
	}

	/* init low_level USB */
	for (i = 0; i < CONFIG_USB_MAX_CONTROLLER_COUNT; i++) {
		/* init low_level USB */
		printf("USB%d:   ", i);
		if (usb_lowlevel_init(i, &ctrl)) {
			puts("lowlevel init failed\n");
			continue;
		}
		/*
		 * lowlevel init is OK, now scan the bus for devices
		 * i.e. search HUBs and configure them
		 */
		start_index = dev_index;
		printf("scanning bus %d for devices... ", i);
		dev = usb_alloc_new_device(ctrl);
初始化的实质工作由具体的设备实现usb_lowlevel_init来负责,这个函数由具体的USB控制器规格来定义,P2020的USB控制器采用EHCI规格,usb_lowlevel_init由drivers/usb/host/ehci-hcd.c定义

if (ehci_hcd_init(index, &ehcic[index].hccr, &ehcic[index].hcor))
		return -1;

ehci_hcd_init由CPU级驱动来实现,定义在drivers/usb/host/ehci-fsl.c中

/*
 * Create the appropriate control structures to manage
 * a new EHCI host controller.
 *
 * Excerpts from linux ehci fsl driver.
 */
int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
	struct ehci_ctrl *ehci_ctrl = container_of(hccr,
					struct ehci_ctrl, hccr);
	struct usb_ehci *ehci;
	const char *phy_type = NULL;
	size_t len;
#ifdef CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
	char usb_phy[5];

	usb_phy[0] = '\0';
#endif

	ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB_ADDR;
	*hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
	*hcor = (struct ehci_hcor *)((uint32_t) *hccr +
			HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));

	/* Set to Host mode */
	setbits_le32(&ehci->usbmode, CM_HOST);

	out_be32(&ehci->snoop1, SNOOP_SIZE_2GB);
	out_be32(&ehci->snoop2, 0x80000000 | SNOOP_SIZE_2GB);

	/* Init phy */
	if (hwconfig_sub("usb1", "phy_type"))
		phy_type = hwconfig_subarg("usb1", "phy_type", &len);
	else
		phy_type = getenv("usb_phy_type");

	if (!phy_type) {
#ifdef CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
		/* if none specified assume internal UTMI */
		strcpy(usb_phy, "utmi");
		phy_type = usb_phy;
#else
		printf("WARNING: USB phy type not defined !!\n");
		return -1;
#endif
	}

	if (!strncmp(phy_type, "utmi", 4)) {
#if defined(CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY)
		setbits_be32(&ehci->control, PHY_CLK_SEL_UTMI);
		setbits_be32(&ehci->control, UTMI_PHY_EN);
		udelay(1000); /* delay required for PHY Clk to appear */
#endif
		out_le32(&(*hcor)->or_portsc[0], PORT_PTS_UTMI);
		setbits_be32(&ehci->control, USB_EN);
	} else {
		setbits_be32(&ehci->control, PHY_CLK_SEL_ULPI);
		clrsetbits_be32(&ehci->control, UTMI_PHY_EN, USB_EN);
		udelay(1000); /* delay required for PHY Clk to appear */
		if (!usb_phy_clk_valid(ehci))
			return -EINVAL;
		out_le32(&(*hcor)->or_portsc[0], PORT_PTS_ULPI);
	}

	out_be32(&ehci->prictrl, 0x0000000c);
	out_be32(&ehci->age_cnt_limit, 0x00000040);
	out_be32(&ehci->sictrl, 0x00000001);

	in_le32(&ehci->usbmode);

	/* enable/disable USB Erratum USB A-005275 workaround;
	* workaround can be disabled by mentioning "no_usb_hs_errata"
	* in hwconfig string
	*/
	if (!hwconfig("no_erratum_a005275")) {
		if (has_erratum_a005275())
			ehci_ctrl->has_fsl_erratum_a005275 = 1;
	} else {
		ehci_ctrl->has_fsl_erratum_a005275 = 0;
	}

	return 0;
}
这个版本的usb需要在环境变量中设置phy_type,P2020RDB-PC使用的ULPI类型的PHY芯片USB3300.

USB的协议实现在usb.c,主机控制器在drivers/usb/host/文件夹实现

整个usb部分由抽象层(usb.c),规格定义(ehci-hcd.c)和具体实现(ehci-fsl.c)来分工实现


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值