声明:移植参考了很多网友的资料,目前已经在我的ok6410上跑起来了,可能好有一些bug,欢迎指教!
过程如下:
一、基本配置:
1、修改主目录下Makefile
ARCH ?= arm
CROSS_COMPILE ?= /usr/local/arm/4.5.1/bin/arm-linux-
2、
arch/arm/mach-s3c64xx目录下
cp mach-mini6410.c mach-ok6410.c
修改其内容:替换
:1,$s/mini6410/ok6410/g
:1,$s/MINI6410/OK6410/g
修改mach-ok6410的mtd_partition ok6410_nand_part[] 函数 此函数实现分区
static struct mtd_partition ok6410_nand_part[] = {
[0] = {
.name = "Bootloader",
.size = (2*SZ_1M),
.offset = 0,
.mask_flags = MTD_CAP_NANDFLASH,
},
[1] = {
.name = "Kernel",
.size = (5*SZ_1M),
.offset = (2*SZ_1M),
.mask_flags = MTD_CAP_NANDFLASH,
},
[2] = {
.name = "FileSystem",
.size = (200*SZ_1M),
.offset = (7*SZ_1M) ,
},
[3] = {
.name = "User",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL,
}
};
接着修改arch/arm/mach-s3c64xx/下Kconfig,添加以下内容:
config MACH_OK6410
bool "OK6410"
select CPU_S3C6410
select S3C64XX_SETUP_FB_24BPP
select S3C64XX_SETUP_SDHCI
select S3C_DEV_FB
select S3C_DEV_HSMMC
select S3C_DEV_HSMMC1
select S3C_DEV_NAND
select S3C_DEV_USB_HOST
select SAMSUNG_DEV_ADC
select SAMSUNG_DEV_TS
help
Machine support for the FOXLINX OK6410
接着修改arch/arm/mach-s3c64xx/下Makefile,添加以下内容:
obj-$(CONFIG_MACH_OK6410) += mach-ok6410.o
3、再修改arch/arm/tools/mach-types文件,加入OK6410的mach-type,这个必须和U-BOOT中的MACH-TYPE一致,这里选用smdk6410的mach-type:1626。如下:
ok6410 MACH_OK6410 OK6410 1626
4、编译 在主目录下 make menuconfig
基本配置完成 可以make zImage
2、LEDheA按键驱动移植网上很多,基本和内核关系不大。在此请参考其他资料!
3、LCD驱动
在arch/arm/mach-s3c64xx/mach-ok6410.c中添加平台信息,如下:
static struct s3c_fb_pd_win ok6410_lcd_type0_fb_win = {
.max_bpp = 32,
.default_bpp = 16,
.xres = 480,
.yres = 272,
};
static struct fb_videomode ok6410_lcd_type0_timing = {
/* 4.3" 480x272 */
.left_margin = 2, //3,
.right_margin = 2,
.upper_margin = 2,//1,
.lower_margin = 2,//1,
.hsync_len = 41,//40,
.vsync_len = 10,//1,
.xres = 480,
.yres = 272,
};
pixclock = 1000000 / DCLK = 1000000 / 9 = 111111
left_margin = Thb = 2
right_margin = Thf = 2
hsync_len = Thp = 41
upper_margin = Tvb = 2
lower_margin = Tvf = 2
vsync_len = Tvp = 10
xres = Thd = 480
Yres = Tvd = 272
在static struct platform_device *ok6410_devices[] __initdata函数中添加:
&s3c_device_fb,
&ok6410_lcd_powerdev,
-
然后将飞凌3.0.1内核中的drviers/video/samsung拷贝到drviers/video/目录下
-
修改drviers/video/的Kconfig文件,在文件中加入
source "drivers/video/samsung/Kconfig"
3、修改drivers/video/Makefile文件:
obj-$(CONFIG_FB_S3C_EXT) += samsung/
4、在arch/arm/plat-samsung/include/plat/map-base.h里面添加
#define S3C_VA_LCD S3C_ADDR(0x01100000) /* LCD */
5、在include/generated/atuoconf.h里面添加
#define CONFIG_FB_S3C_EXT_NUM 4
6、
把drivers/video/samsung/s3cfb_fimd4x.c里面的
s3c6410_pm_do_save(s3c_lcd_save, ARRAY_SIZE(s3c_lcd_save));
改成s3c_pm_do_save(s3c_lcd_save, ARRAY_SIZE(s3c_lcd_save));
s3c6410_pm_do_restore(s3c_lcd_save, ARRAY_SIZE(s3c_lcd_save));
改成s3c_pm_do_restore(s3c_lcd_save, ARRAY_SIZE(s3c_lcd_save));
make menuconfig,重点设置如下:
触摸屏:
在arch/arm/mach-s3c64xx/mach-smdk6410.c
注销掉头文件 #include<plat/ts.h>
添加头文件 #include<mach/ts.h>
从飞凌官方3.0.1中 arch/arm/mach-s3c64xx/ 拷贝文件sev-ts.c到arch/arm/mach-s3c64xx/
cp arch/arm/mach-s3c64xx/include/mach/ts.h到3.9.7相应目录
在arch/arm/mach-s3c64xx/Makefile
obj-$(CONFIG_TOUCHSCREEN_S3C) += dev-ts.o
在里面 添加宏定义arch/arm/mach-s3c64xx/dev-ts.c
#define SZ_256 0x00000100
在arch/arm/mach-s3c64xx/mach-smdk6410.c static void __init smdk6410_machine_init函数中
修改如下:
// s3c24xx_ts_set_platdata(NULL);
s3c_ts_set_platdata(&s3c_ts_platform);
增加结构体
static struct s3c_ts_mach_info s3c_ts_platform __initdata = {
.delay = 10000,
.presc = 49,
.oversampling_shift = 2,
.resol_bit = 12,
.s3c_adc_con = ADC_TYPE_2,
};
把飞凌官方的linux-3.0.1的s3c-tc.c拷贝到drivers/input/touchscreen/
修改 drivers/input/touchscreen/Makefile
obj-$(CONFIG_TOUCHSCREEN_S3C) += s3c-ts.o
修改 drivers/input/tourch/screen/Kconfig
config TOUCHSCREEN_S3C
tristate "S3C touchscreen driver"
depends on ARCH_S3C2410 || ARCH_S3C64XX || ARCH_S5P64XX || ARCH_S5PC1XX
default y
help
Say Y here to enable the driver for the touchscreen on the
S3C SMDK board.
注释掉arch/arm/plat-samsung/devs.c里面大概1223到1277行的如下代码:
/* Touchscreen */
//#ifdef CONFIG_PLAT_S3C24XX
/*static struct resource s3c_ts_resource[] = {
[0] = DEFINE_RES_MEM(S3C24XX_PA_ADC, S3C24XX_SZ_ADC),
[1] = DEFINE_RES_IRQ(IRQ_TC),
};
struct platform_device s3c_device_ts = {
.name = "s3c2410-ts",
.id = -1,
.dev.parent = &s3c_device_adc.dev,
.num_resources = ARRAY_SIZE(s3c_ts_resource),
.resource = s3c_ts_resource,
};
void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *hard_s3c2410ts_info)
{
s3c_set_platdata(hard_s3c2410ts_info,
sizeof(struct s3c2410_ts_mach_info), &s3c_device_ts);
}
*/
//#endif /* CONFIG_PLAT_S3C24XX */
/*#ifdef CONFIG_SAMSUNG_DEV_TS
static struct resource s3c_ts_resource[] = {
[0] = DEFINE_RES_MEM(SAMSUNG_PA_ADC, SZ_256),
[1] = DEFINE_RES_IRQ(IRQ_TC),
};
*/
/*static struct s3c2410_ts_mach_info default_ts_data __initdata = {
.delay = 10000,
.presc = 49,
.oversampling_shift = 2,
};
struct platform_device s3c_device_ts = {
.name = "s3c64xx-ts",
.id = -1,
.num_resources = ARRAY_SIZE(s3c_ts_resource),
.resource = s3c_ts_resource,
};
void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *pd)
{
if (!pd)
pd = &default_ts_data;
s3c_set_platdata(pd, sizeof(struct s3c2410_ts_mach_info),
&s3c_device_ts);
}
*/
//#endif /* CONFIG_SAMSUNG_DEV_TS */
在arch/arm/plat-samsung/include/plat/regs-adc.h的后面添加以下代码:
#define S3C_ADCREG(x) (x)
#define S3C_ADCCON S3C_ADCREG(0x00)
#define S3C_ADCTSC S3C_ADCREG(0x04)
#define S3C_ADCDLY S3C_ADCREG(0x08)
#define S3C_ADCDAT0 S3C_ADCREG(0x0C)
#define S3C_ADCDAT1 S3C_ADCREG(0x10)
#define S3C_ADCUPDN S3C_ADCREG(0x14)
#define S3C_ADCCLRINT S3C_ADCREG(0x18)
#define S3C_ADCMUX S3C_ADCREG(0x1C)
#define S3C_ADCCLRWK S3C_ADCREG(0x20)
/* ADCCON Register Bits */
#define S3C_ADCCON_RESSEL_10BIT (0x0<<16)
#define S3C_ADCCON_RESSEL_12BIT (0x1<<16)
#define S3C_ADCCON_ECFLG (1<<15)
#define S3C_ADCCON_PRSCEN (1<<14)
#define S3C_ADCCON_PRSCVL(x) (((x)&0xFF)<<6)
#define S3C_ADCCON_PRSCVLMASK (0xFF<<6)
#define S3C_ADCCON_SELMUX(x) (((x)&0x7)<<3)
#define S3C_ADCCON_SELMUX_1(x) (((x)&0xF)<<0)
#define S3C_ADCCON_MUXMASK (0x7<<3)
#define S3C_ADCCON_RESSEL_10BIT_1 (0x0<<3)
#define S3C_ADCCON_RESSEL_12BIT_1 (0x1<<3)
#define S3C_ADCCON_STDBM (1<<2)
#define S3C_ADCCON_READ_START (1<<1)
#define S3C_ADCCON_ENABLE_START (1<<0)
#define S3C_ADCCON_STARTMASK (0x3<<0)
/* ADCTSC Register Bits */
#define S3C_ADCTSC_UD_SEN (1<<8)
#define S3C_ADCTSC_YM_SEN (1<<7)
#define S3C_ADCTSC_YP_SEN (1<<6)
#define S3C_ADCTSC_XM_SEN (1<<5)
#define S3C_ADCTSC_XP_SEN (1<<4)
#define S3C_ADCTSC_PULL_UP_DISABLE (1<<3)
#define S3C_ADCTSC_AUTO_PST (1<<2)
#define S3C_ADCTSC_XY_PST(x) (((x)&0x3)<<0)
/* ADCDAT0 Bits */
#define S3C_ADCDAT0_UPDOWN (1<<15)
#define S3C_ADCDAT0_AUTO_PST (1<<14)
#define S3C_ADCDAT0_XY_PST (0x3<<12)
#define S3C_ADCDAT0_XPDATA_MASK (0x03FF)
#define S3C_ADCDAT0_XPDATA_MASK_12BIT (0x0FFF)
/* ADCDAT1 Bits */
#define S3C_ADCDAT1_UPDOWN (1<<15)
#define S3C_ADCDAT1_AUTO_PST (1<<14)
#define S3C_ADCDAT1_XY_PST (0x3<<12)
#define S3C_ADCDAT1_YPDATA_MASK (0x03FF)
#define S3C_ADCDAT1_YPDATA_MASK_12BIT (0x0FFF)
#endif /* __ASM_ARCH_REGS_ADC_H */
make zImage
四、DM9000网卡移植
1、在arch/arm/mach-s3c64xx/mach-ok6410.c中添加以下平台信息:
/* Ethernet */
#ifdef CONFIG_DM9000
#define S3C64XX_PA_DM9000 (0x18000000)
#define S3C64XX_SZ_DM9000 SZ_1M
#define S3C64XX_VA_DM9000 S3C_ADDR(0x03b00300)
static struct resource ok6410_dm9000_resources[] = {
[0] = {
.start= S3C64XX_PA_DM9000,
.end= S3C64XX_PA_DM9000 + 3,
.flags= IORESOURCE_MEM,
},
[1] = {
.start= S3C64XX_PA_DM9000 + 4,
.end= S3C64XX_PA_DM9000 + S3C64XX_SZ_DM9000 - 1,
.flags= IORESOURCE_MEM,
},
[2] = {
.start= IRQ_EINT(7),
.end= IRQ_EINT(7),
.flags= IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
},
};
static struct dm9000_plat_data ok6410_dm9000_platdata = {
.flags= DM9000_PLATF_16BITONLY,
.dev_addr= { 0x08, 0x90, 0x00, 0xa0, 0x90, 0x90 },
};
static struct platform_device ok6410_device_dm9000 = {
.name= "dm9000",
.id= 0,
.num_resources= ARRAY_SIZE(ok6410_dm9000_resources),
.resource= ok6410_dm9000_resources,
.dev= {
.platform_data = &ok6410_dm9000_platdata,
}
};
#endif //#ifdef CONFIG_DM9000
屏蔽掉如下:
/* DM9000AEP 10/100 ethernet controller */
/*
static struct resource ok6410_dm9k_resource[] = {
[0] = DEFINE_RES_MEM(S3C64XX_PA_XM0CSN1, 2),
[1] = DEFINE_RES_MEM(S3C64XX_PA_XM0CSN1 + 4, 2),
[2] = DEFINE_RES_NAMED(S3C_EINT(7), 1, NULL, IORESOURCE_IRQ \
| IORESOURCE_IRQ_HIGHLEVEL),
};
static struct dm9000_plat_data ok6410_dm9k_pdata = {
.flags = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
};
static struct platform_device ok6410_device_eth = {
.name = "dm9000",
.id = -1,
.num_resources = ARRAY_SIZE(ok6410_dm9k_resource),
.resource = ok6410_dm9k_resource,
.dev = {
.platform_data = &ok6410_dm9k_pdata,
},
};
*/
在static struct platform_device *ok6410_devices[] __initdata函数中:
屏蔽掉
//&ok6410_device_eth,
添加
#ifdef CONFIG_DM9000
&ok6410_device_dm9000,
#endif
遇到的错误:
1、 ipv6 之类的:
在make menuconfig中配置ipv6 我这里选择关掉
2、上面关掉之后 不在出现ipv6 not ready错误
但是 usb1-2:device descriptor read/64 error -62还是存在,这里是由于时序配置不对引起的,
修改drivers/usb/host/ohci-s3c2410.c如下:由linux-3.0.1参考 具体修改处可使用Araxis Merge工具 对比发现:
/*
* OHCI HCD (Host Controller Driver) for USB.
*
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
* (C) Copyright 2002 Hewlett-Packard Company
*
* USB Bus Glue for Samsung S3C2410
*
* Written by Christopher Hoover <ch@hpl.hp.com>
* Based on fragments of previous driver by Russell King et al.
*
* Modified for S3C2410 from ohci-sa1111.c, ohci-omap.c and ohci-lh7a40.c
* by Ben Dooks, <ben@simtec.co.uk>
* Copyright (C) 2004 Simtec Electronics
*
* Thanks to basprog@mail.ru for updates to newer kernels
*
* This file is licenced under the GPL.
*/
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <plat/usb-control.h>
#define valid_port(idx) ((idx) == 1 || (idx) == 2)
extern void s3c_otg_phy_config(int enable);
/* clock device associated with the hcd */
static struct clk *clk;
static struct clk *otg_clk, *usb_clk;
/* forward definitions */
static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc);
/* conversion functions */
static struct s3c2410_hcd_info *to_s3c2410_info(struct usb_hcd *hcd)
{
return hcd->self.controller->platform_data;
}
static void s3c2410_start_hc(struct platform_device *dev, struct usb_hcd *hcd)
{
struct s3c2410_hcd_info *info = dev->dev.platform_data;
dev_dbg(&dev->dev, "s3c2410_start_hc:\n");
// gjl
clk_enable(otg_clk);
s3c_otg_phy_config(1);
clk_enable(usb_clk);
mdelay(2); /* let the bus clock stabilise */
clk_enable(clk);
if (info != NULL) {
info->hcd = hcd;
info->report_oc = s3c2410_hcd_oc;
if (info->enable_oc != NULL)
(info->enable_oc)(info, 1);
}
}
static void s3c2410_stop_hc(struct platform_device *dev)
{
struct s3c2410_hcd_info *info = dev->dev.platform_data;
dev_dbg(&dev->dev, "s3c2410_stop_hc:\n");
if (info != NULL) {
info->report_oc = NULL;
info->hcd = NULL;
if (info->enable_oc != NULL)
(info->enable_oc)(info, 0);
}
clk_disable(clk);
clk_disable(usb_clk);
clk_disable(otg_clk);
}
/* ohci_s3c2410_hub_status_data
*
* update the status data from the hub with anything that
* has been detected by our system
*/
static int
ohci_s3c2410_hub_status_data(struct usb_hcd *hcd, char *buf)
{
struct s3c2410_hcd_info *info = to_s3c2410_info(hcd);
struct s3c2410_hcd_port *port;
int orig;
int portno;
orig = ohci_hub_status_data(hcd, buf);
if (info == NULL)
return orig;
port = &info->port[0];
/* mark any changed port as changed */
for (portno = 0; portno < 2; port++, portno++) {
if (port->oc_changed == 1 &&
port->flags & S3C_HCDFLG_USED) {
dev_dbg(hcd->self.controller,
"oc change on port %d\n", portno);
if (orig < 1)
orig = 1;
buf[0] |= 1<<(portno+1);
}
}
return orig;
}
/* s3c2410_usb_set_power
*
* configure the power on a port, by calling the platform device
* routine registered with the platform device
*/
static void s3c2410_usb_set_power(struct s3c2410_hcd_info *info,
int port, int to)
{
if (info == NULL)
return;
if (info->power_control != NULL) {
info->port[port-1].power = to;
(info->power_control)(port-1, to);
}
}
/* ohci_s3c2410_hub_control
*
* look at control requests to the hub, and see if we need
* to take any action or over-ride the results from the
* request.
*/
static int ohci_s3c2410_hub_control(
struct usb_hcd *hcd,
u16 typeReq,
u16 wValue,
u16 wIndex,
char *buf,
u16 wLength)
{
struct s3c2410_hcd_info *info = to_s3c2410_info(hcd);
struct usb_hub_descriptor *desc;
int ret = -EINVAL;
u32 *data = (u32 *)buf;
dev_dbg(hcd->self.controller,
"s3c2410_hub_control(%p,0x%04x,0x%04x,0x%04x,%p,%04x)\n",
hcd, typeReq, wValue, wIndex, buf, wLength);
/* if we are only an humble host without any special capabilities
* process the request straight away and exit */
if (info == NULL) {
ret = ohci_hub_control(hcd, typeReq, wValue,
wIndex, buf, wLength);
goto out;
}
/* check the request to see if it needs handling */
switch (typeReq) {
case SetPortFeature:
if (wValue == USB_PORT_FEAT_POWER) {
dev_dbg(hcd->self.controller, "SetPortFeat: POWER\n");
s3c2410_usb_set_power(info, wIndex, 1);
goto out;
}
break;
case ClearPortFeature:
switch (wValue) {
case USB_PORT_FEAT_C_OVER_CURRENT:
dev_dbg(hcd->self.controller,
"ClearPortFeature: C_OVER_CURRENT\n");
if (valid_port(wIndex)) {
info->port[wIndex-1].oc_changed = 0;
info->port[wIndex-1].oc_status = 0;
}
goto out;
case USB_PORT_FEAT_OVER_CURRENT:
dev_dbg(hcd->self.controller,
"ClearPortFeature: OVER_CURRENT\n");
if (valid_port(wIndex))
info->port[wIndex-1].oc_status = 0;
goto out;
case USB_PORT_FEAT_POWER:
dev_dbg(hcd->self.controller,
"ClearPortFeature: POWER\n");
if (valid_port(wIndex)) {
s3c2410_usb_set_power(info, wIndex, 0);
return 0;
}
}
break;
}
ret = ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
if (ret)
goto out;
switch (typeReq) {
case GetHubDescriptor:
/* update the hub's descriptor */
desc = (struct usb_hub_descriptor *)buf;
if (info->power_control == NULL)
return ret;
dev_dbg(hcd->self.controller, "wHubCharacteristics 0x%04x\n",
desc->wHubCharacteristics);
/* remove the old configurations for power-switching, and
* over-current protection, and insert our new configuration
*/
desc->wHubCharacteristics &= ~cpu_to_le16(HUB_CHAR_LPSM);
desc->wHubCharacteristics |= cpu_to_le16(0x0001);
if (info->enable_oc) {
desc->wHubCharacteristics &= ~cpu_to_le16(
HUB_CHAR_OCPM);
desc->wHubCharacteristics |= cpu_to_le16(
0x0008 |
0x0001);
}
dev_dbg(hcd->self.controller, "wHubCharacteristics after 0x%04x\n",
desc->wHubCharacteristics);
return ret;
case GetPortStatus:
/* check port status */
dev_dbg(hcd->self.controller, "GetPortStatus(%d)\n", wIndex);
if (valid_port(wIndex)) {
if (info->port[wIndex-1].oc_changed)
*data |= cpu_to_le32(RH_PS_OCIC);
if (info->port[wIndex-1].oc_status)
*data |= cpu_to_le32(RH_PS_POCI);
}
}
out:
return ret;
}
/* s3c2410_hcd_oc
*
* handle an over-current report
*/
static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc)
{
struct s3c2410_hcd_port *port;
struct usb_hcd *hcd;
unsigned long flags;
int portno;
if (info == NULL)
return;
port = &info->port[0];
hcd = info->hcd;
local_irq_save(flags);
for (portno = 0; portno < 2; port++, portno++) {
if (port_oc & (1<<portno) &&
port->flags & S3C_HCDFLG_USED) {
port->oc_status = 1;
port->oc_changed = 1;
/* ok, once over-current is detected,
the port needs to be powered down */
s3c2410_usb_set_power(info, portno+1, 0);
}
}
local_irq_restore(flags);
}
/* may be called without controller electrically present */
/* may be called with controller, bus, and devices active */
/*
* usb_hcd_s3c2410_remove - shutdown processing for HCD
* @dev: USB Host Controller being removed
* Context: !in_interrupt()
*
* Reverses the effect of usb_hcd_3c2410_probe(), first invoking
* the HCD's stop() method. It is always called from a thread
* context, normally "rmmod", "apmd", or something similar.
*
*/
static void
usb_hcd_s3c2410_remove(struct usb_hcd *hcd, struct platform_device *dev)
{
usb_remove_hcd(hcd);
s3c2410_stop_hc(dev);
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
}
/**
* usb_hcd_s3c2410_probe - initialize S3C2410-based HCDs
* Context: !in_interrupt()
*
* Allocates basic resources for this USB host controller, and
* then invokes the start() method for the HCD associated with it
* through the hotplug entry's driver_data.
*
*/
static int usb_hcd_s3c2410_probe(const struct hc_driver *driver,
struct platform_device *dev)
{
struct usb_hcd *hcd = NULL;
int retval;
s3c2410_usb_set_power(dev->dev.platform_data, 1, 1);
s3c2410_usb_set_power(dev->dev.platform_data, 2, 1);
hcd = usb_create_hcd(driver, &dev->dev, "s3c24xx");
if (hcd == NULL)
return -ENOMEM;
hcd->rsrc_start = dev->resource[0].start;
hcd->rsrc_len = resource_size(&dev->resource[0]);
printk("gjl usb_hcd_s3c2410_probe here 000!\n");
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
dev_err(&dev->dev, "request_mem_region failed\n");
retval = -EBUSY;
goto err_put;
}
printk("gjl usb_hcd_s3c2410_probe here 11111!\n");
clk = clk_get(&dev->dev, "usb-host");
if (IS_ERR(clk)) {
dev_err(&dev->dev, "cannot get usb-host clock\n");
retval = PTR_ERR(clk);
goto err_mem;
}
usb_clk = clk_get(&dev->dev, "usb-bus-host");
if (IS_ERR(usb_clk)) {
dev_err(&dev->dev, "cannot get usb-bus-host clock\n");
retval = PTR_ERR(usb_clk);
goto err_clk;
}
// gjl
otg_clk = clk_get(&dev->dev, "otg");
if (IS_ERR(otg_clk)) {
dev_err(&dev->dev, "cannot get otg clock\n");
retval = -ENOENT;
goto err_otg;
}
s3c2410_start_hc(dev, hcd);
hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
if (!hcd->regs) {
dev_err(&dev->dev, "ioremap failed\n");
retval = -ENOMEM;
goto err_ioremap;
}
ohci_hcd_init(hcd_to_ohci(hcd));
retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED);
if (retval != 0)
goto err_ioremap;
return 0;
err_ioremap:
s3c2410_stop_hc(dev);
iounmap(hcd->regs);
clk_put(usb_clk);
err_otg: // gjl
clk_put(otg_clk);
err_clk:
clk_put(clk);
err_mem:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err_put:
usb_put_hcd(hcd);
return retval;
}
/*-------------------------------------------------------------------------*/
static int
ohci_s3c2410_start(struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
int ret;
ret = ohci_init(ohci);
if (ret < 0)
return ret;
ret = ohci_run(ohci);
if (ret < 0) {
err("can't start %s", hcd->self.bus_name);
ohci_stop(hcd);
return ret;
}
return 0;
}
static const struct hc_driver ohci_s3c2410_hc_driver = {
.description = hcd_name,
.product_desc = "S3C24XX OHCI",
.hcd_priv_size = sizeof(struct ohci_hcd),
/*
* generic hardware linkage
*/
.irq = ohci_irq,
.flags = HCD_USB11 | HCD_MEMORY,
/*
* basic lifecycle operations
*/
.start = ohci_s3c2410_start,
.stop = ohci_stop,
.shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources
*/
.urb_enqueue = ohci_urb_enqueue,
.urb_dequeue = ohci_urb_dequeue,
.endpoint_disable = ohci_endpoint_disable,
/*
* scheduling support
*/
.get_frame_number = ohci_get_frame,
/*
* root hub support
*/
.hub_status_data = ohci_s3c2410_hub_status_data,
.hub_control = ohci_s3c2410_hub_control,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
#endif
.start_port_reset = ohci_start_port_reset,
};
/* device driver */
static int __devinit ohci_hcd_s3c2410_drv_probe(struct platform_device *pdev)
{
return usb_hcd_s3c2410_probe(&ohci_s3c2410_hc_driver, pdev);
}
static int __devexit ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
usb_hcd_s3c2410_remove(hcd, pdev);
return 0;
}
static struct platform_driver ohci_hcd_s3c2410_driver = {
.probe = ohci_hcd_s3c2410_drv_probe,
.remove = __devexit_p(ohci_hcd_s3c2410_drv_remove),
.shutdown = usb_hcd_platform_shutdown,
/*.suspend = ohci_hcd_s3c2410_drv_suspend, */
/*.resume = ohci_hcd_s3c2410_drv_resume, */
.driver = {
.owner = THIS_MODULE,
.name = "s3c2410-ohci",
},
};
MODULE_ALIAS("platform:s3c2410-ohci");
只是个别函数定义与linux-3.0.1不同
五、搭建NFS根文件系统
先是建立文件系统
5.1.1、使用脚本creat_rootfs.sh建立根目录,内容如下:
#!/bin/sh
echo "------Create rootfs directons start...--------"
mkdir rootfs
cd rootfs
echo "--------Create root,dev....----------"
mkdir root dev etc boot tmp var sys proc lib mnt home usr
mkdir etc/init.d etc/rc.d etc/sysconfig
mkdir usr/sbin usr/bin usr/lib usr/modules
echo "make node in dev/console lib/null"
mknod -m 600 dev/console c 5 1
mknod -m 600 dev/null c 1 3
mkdir mnt/etc mnt/jffs2 mnt/yaffs mnt/data mnt/temp
mkdir var/lib var/lock var/run var/tmp
chmod 777 tmp
chmod 777 var/tmp
echo "-------make direction done---------"
修改出行 chmod +x creat_rootfs.sh
执行 ./creat_rootfs.sh
5.1.2、etc/inittab 系统init进程配置文件,并更改权限 chmod +x inittab
::sysinit:/etc/init.d/rcS
::askfirst:-/bin/sh #没有这就不行,就不能打开console控制台。
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff –a
5.1.3、 etc/init.d/rcS系统启动加载项文件,并更改权限chmod +x etc/init.d/rcS
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
runlevel=S
prevlevel=N
umask 022
export PATH runlevel prevlevel
mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts #用于telnet登录时使用
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
mkdir -p /var/lock
/bin/hostname -F /etc/sysconfig/HOSTNAME
5.1.4、 etc/fstab 系统挂载文件系统列表文件
#device mount-point type option dump fsck order
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
mdev /dev ramfs defaults 0 0
none /var ramfs defaults 0 0
none /tmp ramfs defaults 0 0
5.1.5、 etc/profile用户环境配置文件
# Ash profile
# vim: syntax= sh
# No core file by defaults
# ulimit - S - c 0> / dev/ null 2> & 1
USER="id -un"
LOGNAME=$USER
PS1="[\u@\h \w]#" #\w 目录将显示全路径
PATH=$PATH
HOSTNAME= '/bin/hostname'
alias cls="clear"
export USER LOGNAME PS1 PATH
5.1.6、 把主机的passwd shadow 文件拷贝到/etc下
# cd rootfs
# cp /etc/passwd etc/
# cp /etc/group etc/
# cp /etc/shadow etc/
5.1.7、修改
etc/sysconfig/HOSTNAME的内容为自己名字:这里是gallup
cp -ra /usr/local/arm/4.5.1/arm-none-linux-gnueabi/lib/* lib/
5.1.9 最后:chmod -R 777 rootfs,否则可能会出现
Starting pid 768, console /dev/console: '/etc/init.d/rcS'
5.2、接着使用文件系统工具
5.2.1、下载传说中的瑞士军刀busybox ,目前最新版为1.21
git clone https://github.com/dzo/busybox
5.2.2、修改busybox根目录下Makefile:
CROSS_COMPILE ?=/usr/local/arm/4.4.3/bin/arm-linux-
ARCH ?= arm
5.2.3、make menuconfig
make
make instll
5.2.4配置内核:
5.2.5、遇到的错误:
解决方法:在busybox配置中选中如下: