s3c6410的UART设备驱动(5)
2014-01-26 16:03
288 查看
原文地址:s3c6410的UART设备驱动(5)作者:晃煽褐疟犯
s3c6410的UART设备驱动(1)的链接
s3c6410的UART设备驱动(2)的链接
s3c6410的UART设备驱动(3)的链接地址
s3c6410的UART设备驱动(4)的链接地址
上一篇中说到了这个函数,源码如下:
static int
s3c6400_serial_probe(struct platform_device *dev)
{
dbg("s3c6400_serial_probe:
dev=%pn", dev);
return s3c24xx_serial_probe(dev,
&s3c6400_uart_inf);
}
现在接着往下说:
int s3c24xx_serial_probe(struct
platform_device *dev,
struct s3c24xx_uart_info *info)
{
struct s3c24xx_uart_port *ourport;
int ret;
dbg("s3c24xx_serial_probe(%p, %p)
%dn", dev, info, probe_index);
ourport = &s3c24xx_serial_ports[probe_index];
probe_index++;
如下,在Samsung.c
(linux2.6.28driversserial)文件中有如下定义:在struct s3c24xx_uart_port结构体重有struct
uart_port结构体。
static struct
s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS]
= {
[0] = {
.port = {
.lock =
__SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock),
.iotype = UPIO_MEM,
.irq = IRQ_S3CUART_RX0,
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops,
.flags = UPF_BOOT_AUTOCONF,
.line = 0,
}
},
[1] = {
.port = {
.lock =
__SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[1].port.lock),
.iotype = UPIO_MEM,
.irq = IRQ_S3CUART_RX1,
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops,
.flags = UPF_BOOT_AUTOCONF,
.line = 1,
}
},
#if CONFIG_SERIAL_SAMSUNG_UARTS > 2
[2] = {
.port = {
.lock =
__SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[2].port.lock),
.iotype = UPIO_MEM,
.irq = IRQ_S3CUART_RX2,
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops,
.flags = UPF_BOOT_AUTOCONF,
.line = 2,
}
},
#endif
#if CONFIG_SERIAL_SAMSUNG_UARTS > 3
[3] = {
.port = {
.lock =
__SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[3].port.lock),
.iotype = UPIO_MEM,
.irq = IRQ_S3CUART_RX3,
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops,
//---->modify by phantom
///#ifdef TE6410
#if 1
.flags = UPF_BOOT_AUTOCONF | UPF_CONS_FLOW,
#else
.flags = UPF_BOOT_AUTOCONF,
#endif
//<----
.line = 3,
}
}
#endif
};
dbg("%s: initialising port
%p...n", __func__, ourport);
ret =
s3c24xx_serial_init_port(ourport, info, dev);
if (ret < 0)
goto probe_err;
此函数传入的参数中有个struct platform_device结构体,在那里定义的呢?
在Dev-uart.c
(linux2.6.28archarmplat-s3c64xx)中有如下定义:
static struct platform_device s3c24xx_uart_device0 = {
.id = 0,
};
static struct platform_device s3c24xx_uart_device1 = {
.id = 1,
};
static struct platform_device s3c24xx_uart_device2 = {
.id = 2,
};
static struct platform_device s3c24xx_uart_device3 = {
.id = 3,
};
struct platform_device *s3c24xx_uart_src[4] = {
&s3c24xx_uart_device0,
&s3c24xx_uart_device1,
&s3c24xx_uart_device2,
&s3c24xx_uart_device3,
};
static int s3c24xx_serial_init_port(struct
s3c24xx_uart_port *ourport,
struct
s3c24xx_uart_info *info,
struct platform_device *platdev)
{
struct uart_port *port =
&ourport->port;
struct s3c2410_uartcfg *cfg;
struct resource *res;
int ret;
dbg("s3c24xx_serial_init_port: port=%p,
platdev=%pn", port, platdev);
if (platdev == NULL)
return -ENODEV;
cfg =
s3c24xx_dev_to_cfg(&platdev->dev);
#define s3c24xx_dev_to_cfg(__dev) (struct
s3c2410_uartcfg
*)((__dev)->platform_data)
这里有关的一个结构体是:
struct s3c2410_uartcfg {
unsigned char hwport;
unsigned char unused;
unsigned short flags;
#if !defined(CONFIG_CPU_S3C6400) &&
!defined(CONFIG_CPU_S3C6410) &&
!defined(CONFIG_CPU_S5PC100)
upf_t
uart_f
4000
lags;
#else
unsigned long uart_flags;
#endif
unsigned long ucon;
unsigned long ulcon;
unsigned long ufcon;
struct s3c24xx_uart_clksrc *clocks;
unsigned int
clocks_size;
};
这个结构体的实例在:Mach-smdk6410.c
(linux2.6.28archarmmach-s3c6410)文件中,
static struct
s3c2410_uartcfg smdk6410_uartcfgs[] __initdata = {
[0] = {
.hwport = 0,
.flags = 0,
.ucon =
S3C64XX_UCON_DEFAULT,
.ulcon =
S3C64XX_ULCON_DEFAULT,
.ufcon =
S3C64XX_UFCON_DEFAULT,
},
[1] = {
.hwport = 1,
.flags = 0,
.ucon =
S3C64XX_UCON_DEFAULT,
.ulcon =
S3C64XX_ULCON_DEFAULT,
.ufcon =
S3C64XX_UFCON_DEFAULT,
},
[2] = {
.hwport = 2,
.flags = 0,
.ucon =
S3C64XX_UCON_DEFAULT,
.ulcon =
S3C64XX_ULCON_DEFAULT,
.ufcon =
S3C64XX_UFCON_DEFAULT,
},
[3] = {
.hwport = 3,
.flags = 0,
.ucon =
S3C64XX_UCON_DEFAULT,
.ulcon =
S3C64XX_ULCON_DEFAULT,
.ufcon =
S3C64XX_UFCON_DEFAULT,
},
};
if (port->mapbase != 0)
return 0;
if (cfg->hwport >
CONFIG_SERIAL_SAMSUNG_UARTS) {
.......
}
port->dev =
&platdev->dev;
ourport->info = info;
ourport->port.fifosize =
info->fifosize;
dbg("s3c24xx_serial_init_port: %p (hw
%d)...n", port,
cfg->hwport);
port->uartclk = 1;
if (cfg->uart_flags & UPF_CONS_FLOW)
{
.......
}
res = platform_get_resource(platdev,
IORESOURCE_MEM, 0);
if (res == NULL) {
printk(KERN_ERR "failed to find memory resource
for uartn");
return -EINVAL;
}
大家应该都知道在struct platform_device结构体中有个struct resource*
resource指针,可以存放相应的资源。但是在上面的static
struct platform_device
s3c24xx_uart_device2结构中并没有有关资源的赋值,那在那里赋的值呢?
static struct
platform_device s3c24xx_uart_device2 = {
.id= 2,
};
struct platform_device {
const char * name;
int id;
struct device dev;
u32 num_resources;
struct resource* resource;
};
在Dev-uart.c
(linux2.6.28archarmplat-s3c64xx)文件中有下面这两个结构,我们只列出了其中的一部分。
struct
s3c24xx_uart_resources s3c64xx_uart_resources[] __initdata =
{
[0] = {
.resources=
s3c64xx_uart0_resource,
.nr_resources= ARRAY_SIZE(s3c64xx_uart0_resource),
}
static struct resource s3c64xx_uart0_resource[] =
{
[0] = {
.start = S3C_PA_UART0,
.end = S3C_PA_UART0 + S3C_SZ_UART,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_S3CUART_RX0,
.end = IRQ_S3CUART_RX0,
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = IRQ_S3CUART_TX0,
.end = IRQ_S3CUART_TX0,
.flags = IORESOURCE_IRQ,
},
[3] = {
.start = IRQ_S3CUART_ERR0,
.end = IRQ_S3CUART_ERR0,
.flags = IORESOURCE_IRQ,
}
};
那么这些结构怎样联系起来的呢?
在S3c6400-init.c
(linux2.6.28archarmplat-s3c64xx)文件中有如下函数:
void __init s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg,
int no)
{
s3c24xx_init_uartdevs("s3c6400-uart",
s3c64xx_uart_resources, cfg, no);
}
注:这个函数是在系统初始化是执行的。
void __init
s3c24xx_init_uartdevs(char *name,
struct s3c24xx_uart_resources
*res,
struct s3c2410_uartcfg *cfg,
int no)
{
struct platform_device *platdev;
struct s3c2410_uartcfg *cfgptr = uart_cfgs;
struct s3c24xx_uart_resources *resp;
int uart;
//printk("iiiiiiiiiiiiiiiiiiii=%dn",no);
memcpy(cfgptr, cfg, sizeof(struct s3c2410_uartcfg) * no);
for (uart = 0; uart < no;
uart++,
cfg++,
cfgptr++) {
platdev = s3c24xx_uart_src[cfgptr->hwport];
resp = res + cfgptr->hwport;
s3c24xx_uart_devs[uart] = platdev;
platdev->name =
name;
platdev->resource =
resp->resources;
platdev->num_resources =
resp->nr_resources;
platdev->dev.platform_data =
cfgptr;
看到这些应该,明白了吧!
}
nr_uarts = no;
}此函数到此结束
dbg("resource %p (%lx..%lx)n",
res, res->start, res->end);
port->mapbase = res->start;
port->membase = S3C_VA_UART +
res->start - (S3C_PA_UART &
0xfff00000);
ret = platform_get_irq(platdev,
0);这个应该不用说了。
if (ret < 0)
port->irq = 0;
else {
port->irq = ret;
ourport->rx_irq = ret;
ourport->tx_irq = ret + 1;
}
ret = platform_get_irq(platdev, 1);
if (ret > 0)
ourport->tx_irq = ret;
ourport->clk =
clk_get(&platdev->dev,
"uart");
dbg("port: map=x, mem=x, irq=%d (%d,%d),
clock=%ldn",
port->mapbase,
port->membase, port->irq,
ourport->rx_irq,
ourport->tx_irq,
port->uartclk);
s3c24xx_serial_resetport(port,
cfg);
return 0;
}s3c24xx_serial_init_port函数到这里就完了。下面接着分析s3c24xx_serial_probe函数:
dbg("%s: adding portn",
__func__);
uart_add_one_port(&s3c24xx_uart_drv,
&ourport->port);
这个函数应该很面熟,上一篇说过。
platform_set_drvdata(dev,
&ourport->port);是个宏,展开后为:
#define
platform_set_drvdata(_dev,data)dev_set_drvdata(&(_dev)->dev,
(data))
static inline void
dev_set_drvdata(struct device *dev, void *data)
{
dev->driver_data = data;
}
应该明白了吧。
ret = device_create_file(&dev->dev,
&dev_attr_clock_source);与sysfs文件系统有关。
if (ret < 0)
printk(KERN_ERR "%s: failed to add clksrc
attr.n", __func__);
ret = s3c24xx_serial_cpufreq_register(ourport);
if (ret < 0)
dev_err(&dev->dev,
"failed to add cpufreq
notifiern");
return 0;
probe_err:
return ret;
}
好了,终于走完了这个函数的旅途,但以后的还很长啊!再接再厉!
android基础(对话框风格Activity实现)
s3c6410的UART设备驱动(1)的链接
s3c6410的UART设备驱动(2)的链接
s3c6410的UART设备驱动(3)的链接地址
s3c6410的UART设备驱动(4)的链接地址
上一篇中说到了这个函数,源码如下:
static int
s3c6400_serial_probe(struct platform_device *dev)
{
dbg("s3c6400_serial_probe:
dev=%pn", dev);
return s3c24xx_serial_probe(dev,
&s3c6400_uart_inf);
}
现在接着往下说:
int s3c24xx_serial_probe(struct
platform_device *dev,
struct s3c24xx_uart_info *info)
{
struct s3c24xx_uart_port *ourport;
int ret;
dbg("s3c24xx_serial_probe(%p, %p)
%dn", dev, info, probe_index);
ourport = &s3c24xx_serial_ports[probe_index];
probe_index++;
如下,在Samsung.c
(linux2.6.28driversserial)文件中有如下定义:在struct s3c24xx_uart_port结构体重有struct
uart_port结构体。
static struct
s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS]
= {
[0] = {
.port = {
.lock =
__SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock),
.iotype = UPIO_MEM,
.irq = IRQ_S3CUART_RX0,
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops,
.flags = UPF_BOOT_AUTOCONF,
.line = 0,
}
},
[1] = {
.port = {
.lock =
__SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[1].port.lock),
.iotype = UPIO_MEM,
.irq = IRQ_S3CUART_RX1,
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops,
.flags = UPF_BOOT_AUTOCONF,
.line = 1,
}
},
#if CONFIG_SERIAL_SAMSUNG_UARTS > 2
[2] = {
.port = {
.lock =
__SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[2].port.lock),
.iotype = UPIO_MEM,
.irq = IRQ_S3CUART_RX2,
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops,
.flags = UPF_BOOT_AUTOCONF,
.line = 2,
}
},
#endif
#if CONFIG_SERIAL_SAMSUNG_UARTS > 3
[3] = {
.port = {
.lock =
__SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[3].port.lock),
.iotype = UPIO_MEM,
.irq = IRQ_S3CUART_RX3,
.uartclk = 0,
.fifosize = 16,
.ops = &s3c24xx_serial_ops,
//---->modify by phantom
///#ifdef TE6410
#if 1
.flags = UPF_BOOT_AUTOCONF | UPF_CONS_FLOW,
#else
.flags = UPF_BOOT_AUTOCONF,
#endif
//<----
.line = 3,
}
}
#endif
};
dbg("%s: initialising port
%p...n", __func__, ourport);
ret =
s3c24xx_serial_init_port(ourport, info, dev);
if (ret < 0)
goto probe_err;
此函数传入的参数中有个struct platform_device结构体,在那里定义的呢?
在Dev-uart.c
(linux2.6.28archarmplat-s3c64xx)中有如下定义:
static struct platform_device s3c24xx_uart_device0 = {
.id = 0,
};
static struct platform_device s3c24xx_uart_device1 = {
.id = 1,
};
static struct platform_device s3c24xx_uart_device2 = {
.id = 2,
};
static struct platform_device s3c24xx_uart_device3 = {
.id = 3,
};
struct platform_device *s3c24xx_uart_src[4] = {
&s3c24xx_uart_device0,
&s3c24xx_uart_device1,
&s3c24xx_uart_device2,
&s3c24xx_uart_device3,
};
static int s3c24xx_serial_init_port(struct
s3c24xx_uart_port *ourport,
struct
s3c24xx_uart_info *info,
struct platform_device *platdev)
{
struct uart_port *port =
&ourport->port;
struct s3c2410_uartcfg *cfg;
struct resource *res;
int ret;
dbg("s3c24xx_serial_init_port: port=%p,
platdev=%pn", port, platdev);
if (platdev == NULL)
return -ENODEV;
cfg =
s3c24xx_dev_to_cfg(&platdev->dev);
#define s3c24xx_dev_to_cfg(__dev) (struct
s3c2410_uartcfg
*)((__dev)->platform_data)
这里有关的一个结构体是:
struct s3c2410_uartcfg {
unsigned char hwport;
unsigned char unused;
unsigned short flags;
#if !defined(CONFIG_CPU_S3C6400) &&
!defined(CONFIG_CPU_S3C6410) &&
!defined(CONFIG_CPU_S5PC100)
upf_t
uart_f
4000
lags;
#else
unsigned long uart_flags;
#endif
unsigned long ucon;
unsigned long ulcon;
unsigned long ufcon;
struct s3c24xx_uart_clksrc *clocks;
unsigned int
clocks_size;
};
这个结构体的实例在:Mach-smdk6410.c
(linux2.6.28archarmmach-s3c6410)文件中,
static struct
s3c2410_uartcfg smdk6410_uartcfgs[] __initdata = {
[0] = {
.hwport = 0,
.flags = 0,
.ucon =
S3C64XX_UCON_DEFAULT,
.ulcon =
S3C64XX_ULCON_DEFAULT,
.ufcon =
S3C64XX_UFCON_DEFAULT,
},
[1] = {
.hwport = 1,
.flags = 0,
.ucon =
S3C64XX_UCON_DEFAULT,
.ulcon =
S3C64XX_ULCON_DEFAULT,
.ufcon =
S3C64XX_UFCON_DEFAULT,
},
[2] = {
.hwport = 2,
.flags = 0,
.ucon =
S3C64XX_UCON_DEFAULT,
.ulcon =
S3C64XX_ULCON_DEFAULT,
.ufcon =
S3C64XX_UFCON_DEFAULT,
},
[3] = {
.hwport = 3,
.flags = 0,
.ucon =
S3C64XX_UCON_DEFAULT,
.ulcon =
S3C64XX_ULCON_DEFAULT,
.ufcon =
S3C64XX_UFCON_DEFAULT,
},
};
if (port->mapbase != 0)
return 0;
if (cfg->hwport >
CONFIG_SERIAL_SAMSUNG_UARTS) {
.......
}
port->dev =
&platdev->dev;
ourport->info = info;
ourport->port.fifosize =
info->fifosize;
dbg("s3c24xx_serial_init_port: %p (hw
%d)...n", port,
cfg->hwport);
port->uartclk = 1;
if (cfg->uart_flags & UPF_CONS_FLOW)
{
.......
}
res = platform_get_resource(platdev,
IORESOURCE_MEM, 0);
if (res == NULL) {
printk(KERN_ERR "failed to find memory resource
for uartn");
return -EINVAL;
}
大家应该都知道在struct platform_device结构体中有个struct resource*
resource指针,可以存放相应的资源。但是在上面的static
struct platform_device
s3c24xx_uart_device2结构中并没有有关资源的赋值,那在那里赋的值呢?
static struct
platform_device s3c24xx_uart_device2 = {
.id= 2,
};
struct platform_device {
const char * name;
int id;
struct device dev;
u32 num_resources;
struct resource* resource;
};
在Dev-uart.c
(linux2.6.28archarmplat-s3c64xx)文件中有下面这两个结构,我们只列出了其中的一部分。
struct
s3c24xx_uart_resources s3c64xx_uart_resources[] __initdata =
{
[0] = {
.resources=
s3c64xx_uart0_resource,
.nr_resources= ARRAY_SIZE(s3c64xx_uart0_resource),
}
static struct resource s3c64xx_uart0_resource[] =
{
[0] = {
.start = S3C_PA_UART0,
.end = S3C_PA_UART0 + S3C_SZ_UART,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_S3CUART_RX0,
.end = IRQ_S3CUART_RX0,
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = IRQ_S3CUART_TX0,
.end = IRQ_S3CUART_TX0,
.flags = IORESOURCE_IRQ,
},
[3] = {
.start = IRQ_S3CUART_ERR0,
.end = IRQ_S3CUART_ERR0,
.flags = IORESOURCE_IRQ,
}
};
那么这些结构怎样联系起来的呢?
在S3c6400-init.c
(linux2.6.28archarmplat-s3c64xx)文件中有如下函数:
void __init s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg,
int no)
{
s3c24xx_init_uartdevs("s3c6400-uart",
s3c64xx_uart_resources, cfg, no);
}
注:这个函数是在系统初始化是执行的。
void __init
s3c24xx_init_uartdevs(char *name,
struct s3c24xx_uart_resources
*res,
struct s3c2410_uartcfg *cfg,
int no)
{
struct platform_device *platdev;
struct s3c2410_uartcfg *cfgptr = uart_cfgs;
struct s3c24xx_uart_resources *resp;
int uart;
//printk("iiiiiiiiiiiiiiiiiiii=%dn",no);
memcpy(cfgptr, cfg, sizeof(struct s3c2410_uartcfg) * no);
for (uart = 0; uart < no;
uart++,
cfg++,
cfgptr++) {
platdev = s3c24xx_uart_src[cfgptr->hwport];
resp = res + cfgptr->hwport;
s3c24xx_uart_devs[uart] = platdev;
platdev->name =
name;
platdev->resource =
resp->resources;
platdev->num_resources =
resp->nr_resources;
platdev->dev.platform_data =
cfgptr;
看到这些应该,明白了吧!
}
nr_uarts = no;
}此函数到此结束
dbg("resource %p (%lx..%lx)n",
res, res->start, res->end);
port->mapbase = res->start;
port->membase = S3C_VA_UART +
res->start - (S3C_PA_UART &
0xfff00000);
ret = platform_get_irq(platdev,
0);这个应该不用说了。
if (ret < 0)
port->irq = 0;
else {
port->irq = ret;
ourport->rx_irq = ret;
ourport->tx_irq = ret + 1;
}
ret = platform_get_irq(platdev, 1);
if (ret > 0)
ourport->tx_irq = ret;
ourport->clk =
clk_get(&platdev->dev,
"uart");
dbg("port: map=x, mem=x, irq=%d (%d,%d),
clock=%ldn",
port->mapbase,
port->membase, port->irq,
ourport->rx_irq,
ourport->tx_irq,
port->uartclk);
s3c24xx_serial_resetport(port,
cfg);
return 0;
}s3c24xx_serial_init_port函数到这里就完了。下面接着分析s3c24xx_serial_probe函数:
dbg("%s: adding portn",
__func__);
uart_add_one_port(&s3c24xx_uart_drv,
&ourport->port);
这个函数应该很面熟,上一篇说过。
platform_set_drvdata(dev,
&ourport->port);是个宏,展开后为:
#define
platform_set_drvdata(_dev,data)dev_set_drvdata(&(_dev)->dev,
(data))
static inline void
dev_set_drvdata(struct device *dev, void *data)
{
dev->driver_data = data;
}
应该明白了吧。
ret = device_create_file(&dev->dev,
&dev_attr_clock_source);与sysfs文件系统有关。
if (ret < 0)
printk(KERN_ERR "%s: failed to add clksrc
attr.n", __func__);
ret = s3c24xx_serial_cpufreq_register(ourport);
if (ret < 0)
dev_err(&dev->dev,
"failed to add cpufreq
notifiern");
return 0;
probe_err:
return ret;
}
好了,终于走完了这个函数的旅途,但以后的还很长啊!再接再厉!
android基础(对话框风格Activity实现)
相关文章推荐
- s3c6410的UART设备驱动(1)
- s3c6410的UART设备驱动(4)
- s3c6410的UART设备驱动(2)
- s3c6410的UART设备驱动(5)
- s3c6410的UART设备驱动(1)
- s3c6410的UART设备驱动(3)
- s3c6410的UART设备驱动(2)
- s3c6410的UART设备驱动(4)
- s3c6410的UART设备驱动(5)
- s3c6410的UART设备驱动(3)
- s3c6410的UART设备驱动(5)
- linux设备模型之uart驱动架构分析
- linux设备模型之uart驱动架构分析
- linux终端设备uart驱动分析
- linux设备模型之uart驱动架构分析
- [转]linux设备模型之uart驱动架构分析(开始做驱动!!)
- linux设备模型之uart驱动架构分析
- linux设备模型之uart驱动架构分析
- linux设备模型之uart驱动架构分析
- linux终端设备uart驱动分析