博客
关于我
OK335xS UART device registe hacking
阅读量:792 次
发布时间:2023-02-22

本文共 4732 字,大约阅读时间需要 15 分钟。

OK335xS UART设备注册代码跟踪

作为OK335xS Linux内核开发者,在理解UART设备注册过程时,我选择了函数调用线路图进行标记,以便更直观地进行阅读和分析。通过使用vim和ctags工具,我对代码进行了详细的跟踪和解读。

一、板级文件分析

在板级文件中,MACHINE_START和MACHINE_END宏定义用于定义机器启动和结束 macros。以下是板级文件中关键的初始化设置:

MACHINE_START(AM335XEVM, "am335xevm")
.atag_offset = 0x100,
.map_io = am335x_evm_map_io,
.init_early = am33xx_init_early,
.init_irq = ti81xx_init_irq,
.handle_irq = omap3_intc_handle_irq,
.timer = &omap3_am33xx_timer,
.init_machine = am335x_evm_init,
MACHINE_END
MACHINE_START(AM335XIAEVM, "am335xiaevm")
.atag_offset = 0x100,
.map_io = am335x_evm_map_io,
.init_early = am33xx_init_early,
.init_irq = ti81xx_init_irq,
.timer = &omap3_am33xx_timer,
.init_machine = am335x_evm_init,
MACHINE_END

二、am33xx_init_early函数分析

am33xx_init_early函数是内核初始化的一个重要步骤,主要完成以下任务:

void __init am33xx_init_early(void)
{
omap2_set_globals_am33xx();
omap3xxx_check_revision();
am33xx_check_features();
omap_common_init_early();
am33xx_voltagedomains_init();
omap44xx_prminst_init();
am33xx_powerdomains_init();
omap44xx_cminst_init();
am33xx_clockdomains_init();
am33xx_hwmod_init();
omap_hwmod_init_postsetup();
omap3xxx_clk_init();
}

在这个过程中, omap2_set_globals_am33xx()用于设置全局配置, omap3xxx_check_revision()用于检查处理器版本, am33xx_check_features()用于检测硬件功能等。

三、am335x_evm_init函数分析

am335x_evm_init函数是板级初始化函数,主要负责板级硬件的初始化配置:

static void __init am335x_evm_init(void)
{
am33xx_cpuidle_init();
am33xx_mux_init(board_mux);
omap_serial_init();
am335x_evm_i2c_init();
omap_sdrc_init(NULL, NULL);
usb_musb_init(&musb_board_data);
omap_board_config = am335x_evm_config;
omap_board_config_size = ARRAY_SIZE(am335x_evm_config);
if (clk_add_alias("pruss", NULL, "pruss_uart_gclk", NULL))
pr_warn("failed to create an alias: icss_uart_gclk --> pruss\n");
if (clk_add_alias("sgx_ck", NULL, "gfx_fclk", NULL))
pr_warn("failed to create an alias: gfx_fclk --> sgx_ck\n");
printk("zengjf test code 1.\n");
}

omap_serial_init()函数负责初始化串口设备,am335x_evm_i2c_init()函数负责初始化I2C总线。

UART设备注册流程

UART设备的注册过程主要通过 omap_hwmod_register()函数完成。以下是相关代码片段:

int __init omap_hwmod_register(struct omap_hwmod **ohs)
{
int r, i;
if (!ohs)
return 0;
i = 0;
do {
r = _register(ohs[i]);
WARN(r, "omap_hwmod: %s: _register returned %d\n", ohs[i]->name, r);
} while (ohs[++i]);
return 0;
}
static int __init _register(struct omap_hwmod *oh)
{
int ms_id;
if (!oh || !oh->name || !oh->class || !oh->class->name ||
(oh->_state != _HWMOD_STATE_UNKNOWN))
return -EINVAL;
pr_debug("omap_hwmod: %s: registering\n", oh->name);
if (_lookup(oh->name))
return -EEXIST;
ms_id = _find_mpu_port_index(oh);
if (!IS_ERR_VALUE(ms_id))
oh->_mpu_port_index = ms_id;
else
oh->_int_flags |= _HWMOD_NO_MPU_PORT;
list_add_tail(&oh->node, &omap_hwmod_list);
spin_lock_init(&oh->_lock);
oh->_state = _HWMOD_STATE_REGISTERED;
if (!strcmp(oh->name, MPU_INITIATOR_NAME))
mpu_oh = oh;
return 0;
}

UART设备初始化

UART设备的初始化主要通过 omap_serial_init_port()和 omap_serial_early_init()函数完成。以下是相关代码片段:

void __init omap_serial_init(void)
{
omap_serial_board_init(NULL);
}
void __init omap_serial_board_init(struct omap_uart_port_info *info)
{
struct omap_uart_state *uart;
struct omap_board_data bdata;
list_for_each_entry(uart, &uart_list, node) {
bdata.id = uart->num;
bdata.flags = 0;
bdata.pads = NULL;
bdata.pads_cnt = 0;
if (cpu_is_omap44xx() || (cpu_is_omap34xx() && !cpu_is_am33xx()))
omap_serial_fill_default_pads(&bdata);
if (!info)
omap_serial_init_port(&bdata, NULL);
else
omap_serial_init_port(&bdata, &info[uart->num]);
}
}

平台设备构建

平台设备构建主要通过 omap_device_build()函数完成。以下是相关代码片段:

struct platform_device *omap_device_build(const char *pdev_name, int pdev_id,
struct omap_hwmod *oh, void *pdata, int pdata_len,
struct omap_device_pm_latency *pm_lats, int pm_lats_cnt,
int is_early_device)
{
struct omap_hwmod *ohs[] = { oh };
if (!oh)
return ERR_PTR(-EINVAL);
return omap_device_build_ss(pdev_name, pdev_id, ohs, 1, pdata,
pdata_len, pm_lats, pm_lats_cnt, is_early_device);
}

早期设备注册

早期设备注册主要通过 omap_early_device_register()函数完成:

static int omap_early_device_register(struct platform_device *pdev)
{
struct platform_device *devices[1];
devices[0] = pdev;
early_platform_add_devices(devices, 1);
return 0;
}

通过以上代码分析,可以清晰地看到OK335xS UART设备注册的整体流程和关键函数的作用。

转载地址:http://atsfk.baihongyu.com/

你可能感兴趣的文章
Objective-C实现置换密码加解密算法(附完整源码)
查看>>
Objective-C实现翻转图像augmentation算法(附完整源码)
查看>>
Objective-C实现老鼠迷宫算法(附完整源码)
查看>>
Objective-C实现聚类基本K均值算法(附完整源码)
查看>>
Objective-C实现自动查找和检索加密密钥算法(附完整源码)
查看>>
Objective-C实现自旋锁(附完整源码)
查看>>
Objective-C实现莫尔斯电码算法(附完整源码)
查看>>
Objective-C实现莱布尼兹级数求解π的近似值(附完整源码)
查看>>
Objective-C实现获取 Collatz 序列长度算法(附完整源码)
查看>>
Objective-C实现获取CPU温度(附完整源码)
查看>>
Objective-C实现获取daily horoscope每日星座运势算法(附完整源码)
查看>>
Objective-C实现获取GPU显卡信息(附完整源码)
查看>>
Objective-C实现获取HID设备列表 (附完整源码)
查看>>
Objective-C实现获取PE文件特征(附完整源码)
查看>>
Objective-C实现获取文件大小(字节数) (附完整源码)
查看>>
Objective-C实现获取文件头的50个字符(附完整源码)
查看>>
Objective-C实现获取文件最后修改时间(附完整源码)
查看>>
Objective-C实现获取文件末的50个字符(附完整源码)
查看>>
Objective-C实现获取本机ip及mac地址(附完整源码)
查看>>
Objective-C实现获取本机系统版本(附完整源码)
查看>>