一、S3C2440
在Linux下对于移植USB到开发板的主要步骤是设置UPLL、CLKDIVN和MISCCR三个寄存器(前两个寄存器用于设置时钟,MISCCR用于设置双USB host;2440中一个usb接口是双功能的,可配置为device和host),然后在menuconfig中选中支持USB选项。关于配置2440的USB时钟,我有点困惑; 网上大部分的做法是先将频率设成96M,然后再降为48M输给USB HOST,我是直接就将96M送给了USB HOST,网上的做法也可以,但在我这边用网上的做法有时会出现-62的错误提示。datasheet上的说法是:若CLKCON中的第三位为0,则输出到usb
host的时钟等于UCLL;若为1,则输出到usb host的时钟为UPLL/2。
1、时钟的计算
UPLL生成96MHz or 48MHz供USB HOST使用!
Upll = (m * Fin) / (p * 2^s);
其中:
m = MDIV + 8,
p = PDIV + 2,
s = SDIV,
MDIV、PDIV和SDIV都是设到寄存器UPLL中的数值;这些数值的选取可从datasheet中找到;
eg:
MDIV:0x38 PDIV:0x2 SDIV:0x1 Fin:12MHz
由公式计算得到:
m=64, p=4, s=1
UPLL = (64 * 12) / (4 * 2^1) = 96MHz
接下来就是设置CLKDIVN寄存器,我的做法是不设,默认为0,即输出到usb host为96MHz;
2、具体编程实例(mach-smdk2440.c)
#include <mach/regs-clock.h>
static struct s3c2410_hcd_info s3c2410_usb_info={
.port[0]={ .flags = S3C_HCDFLG_USED },
.port[1]={ .flags = S3C_HCDFLG_USED },
};
static int s3c2410_usb_init(void)
{
unsigned long upllvalue = (0x38 << 12)|(0x02<<4)|(0x01);
printk("Initial S3C2410 USB Control......\n");
/*以下2选1*/
s3c_device_usb.dev.platform_data = &s3c2410_usb_info; /* 2.6.30.4 */
s3c_device_usbgadget.dev.platform_data = &s3c2410_usb_info; /* 2.6.38.8 */
while(upllvalue != __raw_readl(S3C2410_UPLLCON))
{
__raw_writel(upllvalue,S3C2410_UPLLCON);
mdelay(1);
}
return 0;
}
#include <mach/regs-clock.h>
static struct s3c2410_hcd_info s3c2410_usb_info={
.port[0]={ .flags = S3C_HCDFLG_USED },
.port[1]={ .flags = S3C_HCDFLG_USED },
};
static int s3c2410_usb_init(void)
{
unsigned long upllvalue = (0x38 << 12)|(0x02<<4)|(0x01);
printk("Initial S3C2410 USB Control......\n");
/*以下2选1*/
s3c_device_usb.dev.platform_data = &s3c2410_usb_info; /* 2.6.30.4 */
s3c_device_usbgadget.dev.platform_data = &s3c2410_usb_info; /* 2.6.38.8 */
while(upllvalue != __raw_readl(S3C2410_UPLLCON))
{
__raw_writel(upllvalue,S3C2410_UPLLCON);
mdelay(1);
}
return 0;
}