OK6410A 开发板 (三) 23 u-boot-2021.01 boot 解析 U-boot 镜像运行部分 DM 的一次实例分析 - 串口

串口相关的 UCLASS DRIVER DEVICE

UCLASS

./drivers/serial/serial-uclass.c L504
504 UCLASS_DRIVER(serial) = {                                                        
505     .id     = UCLASS_SERIAL,                                                     
506     .name       = "serial",                                                      
507     .flags      = DM_UC_FLAG_SEQ_ALIAS,                                          
508     .post_probe = serial_post_probe,                                             
509     .pre_remove = serial_pre_remove,                                             
510     .per_device_auto_alloc_size = sizeof(struct serial_dev_priv),                
511 };

DRIVER

./drivers/serial/s3c64xx_serial.c L218

static const struct udevice_id s3c64xx_serial_ids[] = {                             
    { .compatible = "samsung,ok6410-uart" },                                        
    { }                                                                             
};

U_BOOT_DRIVER(serial_s3c64xx) = {                                                   
    .name   = "serial_s3c64xx",                                                     
    .id = UCLASS_SERIAL,                                                            
    .of_match = s3c64xx_serial_ids,                                                 
    .ofdata_to_platdata = s3c64xx_serial_ofdata_to_platdata,                        
    .platdata_auto_alloc_size = sizeof(struct s3c64xx_serial_platdata),             
    .probe = s3c64xx_serial_probe,                                                  
    .ops    = &s3c64xx_serial_ops,                                                  
    .flags = DM_FLAG_PRE_RELOC,                                                     
};

DEVICE

arch/arm/dts/s3c64xx-ok6410a.dts L54
    serial0@7F005000 {                                                              
        compatible = "samsung,ok6410-uart";                                         
        reg = <0x7F005000 0x400>;                                                   
        interrupt-parent = <&gic>;                                                  
        interrupts = <0 37 0>;                                                      
        id = <0>;                                                                   
    };

初始化过程中的绑定
  • initf_dm 中串口 UCLASS DRIVER DEVICE 的 绑定
initf_dm
	dm_init_and_scan
		dm_extended_scan_fdt
			dm_scan_fdt
				dm_scan_fdt_node
					for_each_node // node serial0@7F005000
						lists_bind_fdt
							driver_check_compatible
								strcmp(of_match->compatible, compat)
							device_bind_with_driver_data
								device_bind_common
									dev = calloc(1, sizeof(struct udevice));
									dev->driver = drv;
									dev->uclass = uc;
									uclass_bind_device(dev);
									if (drv->bind) drv->bind(dev);
init_baud_rate
serial_init
	serial_find_console_or_panic
		serial_check_stdout
			fdtdec_get_chosen_prop
			uclass_get_device_by_of_offset
				uclass_get_device_tail
					device_probe
						device_ofdata_to_platdata
							if (drv->ofdata_to_platdata && (CONFIG_IS_ENABLED(OF_PLATDATA) || dev_has_of_node(dev)))
								drv->ofdata_to_platdata(dev);
						if (drv->probe) drv->probe(dev);/即s3c64xx_serial_probe
							s3c64xx_serial_init
								uart->UFCON = 0;
				
	serial_setbrg

  • initr_dm 中串口 UCLASS DRIVER DEVICE 的 绑定
initr_dm
serial_initialize
	serial_init

极度类似 initf_dm

消费者
  • UCLASS 提供的 API
消费者调用的 是 UCLASS(./drivers/serial/serial-uclass.c) 中提供的 api
为下面 的函数
serial_init(void)
serial_initialize(void)
serial_putc(char ch)
serial_puts(const char *str)
serial_getc(void)
serial_tstc(void)
serial_setbrg(void)
serial_getconfig(struct udevice *dev, uint *config)
serial_setconfig(struct udevice *dev, uint config)
serial_getinfo(struct udevice *dev, struct serial_device_info *info)
serial_stdio_init(void)
  • 初始化阶段的消费者
board_init_f
	serial_init
		serial_setbrg
	display_options
		printf
			puts
				serial_puts
			
board_init_r
	serial_initialize
		serial_init
			serial_setbrg
	stdio_add_devices
		serial_stdio_init
	console_init_r
		print_pre_console_buffer(flushpoint);
			puts
				console_puts
					stdio_devices[file]->puts(stdio_devices[file], s);/ 即 stdio_serial_puts
						serial_puts
			

run_main_loop
	main_loop
		cli_loop
			...
				getcmd_getch
					serial_getc


printf                                              // lib/vsprintf.c
    puts                                            // common/console.c
        fputs                                       // common/console.c
            console_puts                	    // common/console.c
                stdio_devices[file]->puts(stdio_devices[file], s);/ 即 stdio_serial_puts
					serial_puts(s);


DRIVER
  • driver的实现

static const struct udevice_id s3c64xx_serial_ids[] = {                          
    { .compatible = "samsung,ok6410-uart" },                                     
    { }                                                                          
};

s3c64xx_serial_probe
	s3c64xx_serial_init

static const struct dm_serial_ops s3c64xx_serial_ops = {                            
    .putc = s3c64xx_serial_putc,                                                    
    .pending = s3c64xx_serial_pending,                                              
    .getc = s3c64xx_serial_getc,                                                    
    .setbrg = s3c64xx_serial_setbrg,                                                
};



U_BOOT_DRIVER(serial_s3c64xx) = {                                                   
    .name   = "serial_s3c64xx",                                                     
    .id = UCLASS_SERIAL,                                                            
    .of_match = s3c64xx_serial_ids,                                                 
    .ofdata_to_platdata = s3c64xx_serial_ofdata_to_platdata,                        
    .platdata_auto_alloc_size = sizeof(struct s3c64xx_serial_platdata),             
    .probe = s3c64xx_serial_probe,                                                  
    .ops    = &s3c64xx_serial_ops,                                                  
    .flags = DM_FLAG_PRE_RELOC,                                                     
};

  • 与uclass的关系
serial_getc // UCLASS 提供的 API
	_serial_getc(gd->cur_serial_dev);
		__serial_getc(dev);
			struct dm_serial_ops *ops = serial_get_ops(dev);
			ops->getc(dev); / 即 s3c64xx_serial_getc
				struct s3c64xx_serial_platdata *plat = dev->platdata;
				struct s3c64xx_uart *const uart = plat->reg;
				while (!(uart->UTRSTAT & 0x1));
				return uart->URXH & 0xff;
	
其他
initf_dm 过程中匹配成功的
- found match at 's3c64xx_gpio': 'samsung,s3c6410-pinctrl' matches 'samsung,s3c6410-pinctrl'
- found match at 's3c6410_clock': 'samsung,s3c6410-clk' matches 'samsung,s3c6410-clk'
- found match at 'serial_s3c64xx': 'samsung,ok6410-uart' matches 'samsung,ok6410-uart'
initr_dm 过程中匹配成功的
- found match at 's3c64xx_gpio': 'samsung,s3c6410-pinctrl' matches 'samsung,s3c6410-pinctrl'
- found match at 's3c6410_clock': 'samsung,s3c6410-clk' matches 'samsung,s3c6410-clk'
- found match at 'serial_s3c64xx': 'samsung,ok6410-uart' matches 'samsung,ok6410-uart'
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值