UART 的platform_device
1、/kernel/arch/arm/mach-s5pv210/mach-smdkv210.c
static struct s3c2410_uartcfg
smdkv210_uartcfgs[] __initdata = {
[0] = {
.hwport
= 0,
.flags
= 0,
.ucon
= S5PV210_UCON_DEFAULT,
.ulcon
= S5PV210_ULCON_DEFAULT,
.ufcon
= S5PV210_UFCON_DEFAULT,
},
[1] = {
.hwport
= 1,
.flags
= 0,
.ucon
= S5PV210_UCON_DEFAULT,
.ulcon
= S5PV210_ULCON_DEFAULT,
.ufcon
= S5PV210_UFCON_DEFAULT,
},
[2] = {
.hwport
= 2,
.flags
= 0,
.ucon
= S5PV210_UCON_DEFAULT,
.ulcon
= S5PV210_ULCON_DEFAULT,
.ufcon
= S5PV210_UFCON_DEFAULT,
},
[3] = {
.hwport
= 3,
.flags
= 0,
.ucon
= S5PV210_UCON_DEFAULT,
.ulcon
= S5PV210_ULCON_DEFAULT,
.ufcon
= S5PV210_UFCON_DEFAULT,
},
};
下面是具体过程:
MACHINE_START(SMDKV210, "SMDKV210")
.phys_io
= S3C_PA_UART & 0xfff00000,
.io_pg_offst
= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params
= S5P_PA_SDRAM + 0x100,
.init_irq
= s5pv210_init_irq,
.map_io= smdkv210_map_io,
.init_machine
= smdkv210_machine_init,
.timer
= &s5p_systimer,
MACHINE_END
static void __init
smdkv210_map_io(void)
{
s5p_init_io(NULL, 0, S5P_VA_CHIPID);
s3c24xx_init_clocks(24000000);
s3c24xx_init_uarts(
smdkv210_uartcfgs, ARRAY_SIZE(
smdkv210_uartcfgs));
s5pv210_reserve_bootmem();
}
2、
static struct cpu_table
cpu_ids[] __initdata = {
{
.idcode
= 0x43110000,
.idmask
= 0xfffff000,
.map_io
= s5pv210_map_io,
.init_clocks
= s5pv210_init_clocks,
.init_uarts
=
s5pv210_init_uarts,
.init
= s5pv210_init,
.name
= name_s5pv210,
},
};
void __init
s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no)
/* 3 */
{
if (cpu == NULL)
return;
if (cpu->init_uarts == NULL) {
printk(KERN_ERR "s3c24xx_init_uarts: cpu has no uart init\n");
} else
(cpu->init_uarts)(cfg, no);//这里最终会调用上面的
s5pv210_init_uarts
}
#define
s5pv210_init_uarts
s5pv210_common_init_uarts
void __init
s5pv210_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
{
......
//关于
s5p_uart_resources可参考:
UART的资源(struct resource)
s3c24xx_init_uartdevs("s5pv210-uart",
s5p_uart_resources, cfg, no);
}
3、这里很重要
static int
nr_uarts __initdata = 0;//全局变量-------表示uart数
static struct s3c2410_uartcfg
uart_cfgs[CONFIG_SERIAL_SAMSUNG_UARTS];//全局变量
regs-serial.h中
/* s3c24xx_uart_devs
*
this is exported from the core as we cannot use driver_register(), or platform_add_device() before the console_initcall()
*/
extern struct platform_device *
s3c24xx_uart_devs[4];
/* s3c24xx_init_uartdevs
*
* copy the specified platform data and configuration into our central
* set of devices, before the data is thrown away after the init process.
*
* This also fills in the array passed to the serial driver for the
* early initialisation of the console.
*/
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;
memcpy(cfgptr, cfg, sizeof(struct s3c2410_uartcfg) * no);
for (uart = 0; uart < no; uart++, cfg++, cfgptr++) {
resp = res + cfgptr->hwport;
s3c24xx_uart_devs[uart] = platdev;//保存到
platform_device中
platdev->name = name;
platdev->resource = resp->resources;
platdev->num_resources = resp->nr_resources;
platdev->dev.platform_data = cfgptr;
}
nr_uarts = no;
}
static int __init
s3c_arch_init(void)
{
.....
ret =
platform_add_devices(
s3c24xx_uart_devs, nr_uarts);//注册
platform_device
}
arch_initcall(
s3c_arch_init);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
原文出处:http://fangjian0518.blog.163.com/blog/static/55919656201152535253959/
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define S5PV210_UART_DEFAULT_INFO(fifo_size)
\
.name
= "Samsung S5PV210 UART0",
\
.type
= PORT_S3C6400,
\
.fifosize
= fifo_size,
\
.has_divslot
= 1,
\
.rx_fifomask
= S5PV210_UFSTAT_RXMASK,
\
.rx_fifoshift
= S5PV210_UFSTAT_RXSHIFT,
\
.rx_fifofull
= S5PV210_UFSTAT_RXFULL,
\
.tx_fifofull
= S5PV210_UFSTAT_TXFULL,
\
.tx_fifomask
= S5PV210_UFSTAT_TXMASK,
\
.tx_fifoshift
= S5PV210_UFSTAT_TXSHIFT,
\
.get_clksrc
= s5pv210_serial_getsource,
\
.set_clksrc
= s5pv210_serial_setsource,
\
.reset_port
= s5pv210_serial_resetport
static struct s3c24xx_uart_info s5p_port_fifo256 = {
S5PV210_UART_DEFAULT_INFO(256),
};
static struct s3c24xx_uart_info s5p_port_fifo64 = {
S5PV210_UART_DEFAULT_INFO(64),
};
static struct s3c24xx_uart_info s5p_port_fifo16 = {
S5PV210_UART_DEFAULT_INFO(16),
};
static struct s3c24xx_uart_info *s5p_uart_inf[] = {
[0] = &s5p_port_fifo256,
[1] = &s5p_port_fifo64,
[2] = &s5p_port_fifo16,
[3] = &s5p_port_fifo16,
};
/* device management */
static int
s5p_serial_probe(struct platform_device *pdev)
{
return s3c24xx_serial_probe(pdev, s5p_uart_inf[pdev->id]);
}
static struct platform_driver
s5p_serial_drv = {
.probe
=
s5p_serial_probe,
.remove
= __devexit_p(s3c24xx_serial_remove),
.driver
= {
.name
= "
s5pv210-uart",
.owner
= THIS_MODULE,
},
};
static int __init s5pv210_serial_console_init(void)
{
return s3c24xx_serial_initconsole(&s5p_serial_drv, s5p_uart_inf);
}
console_initcall(s5pv210_serial_console_init);
static int __init
s5p_serial_init(void)
{
return
platform_driver_register(&s5p_serial_drv);//注册
platform_driver
}
module_init(
s5p_serial_init);
原文出处:http://fangjian0518.blog.163.com/blog/static/55919656201152535253959/