在学习开发板时对引脚的控制做了相关的笔记。
关于linux下引脚的配置首先粘贴几个内核中的数据结构:
Kernel/arch/arm/mach-omap2/Board-am335xevm.c
/* module pin mux structure */
struct pinmux_config {
const char *string_name; /* signal name format */
int val; /* Options for the mux register value */
};
Kernel/arch/arm/mach-omap2/Mux.h
/**
* struct omap_mux - data for omap mux register offset and it's value
* @reg_offset: mux register offset from the mux base
* @gpio: GPIO number
* @muxnames: available signal modes for a ball
* @balls: available balls on the package
* @partition: mux partition
*/
struct omap_mux {
u16 reg_offset;
u16 gpio;
#ifdef CONFIG_OMAP_MUX
char *muxnames[OMAP_MUX_NR_MODES];
#ifdef CONFIG_DEBUG_FS
char *balls[OMAP_MUX_NR_SIDES];
#endif
#endif
};
/**
* struct mux_partition - contain partition related information
* @name: name of the current partition
* @flags: flags specific to this partition
* @phys: physical address
* @size: partition size
* @base: virtual address after ioremap
* @muxmodes: list of nodes that belong to a partition
* @node: list node for the partitions linked list
*/
struct omap_mux_partition {
const char *name;
u32 flags;
u32 phys;
u32 size;
void __iomem *base;
struct list_head muxmodes;
struct list_head node;
};
与硬件相关的初始化,通过这个函数我们可以找到很多我们要使用的驱动的引脚初始化的位置与函数:
Kernel/arch/arm/mach-omap2/Board-am335xevm.c
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);
setup_pin_mux(tsc_gpio_pin_mux);
omap_board_config = am335x_evm_config;
omap_board_config_size = ARRAY_SIZE(am335x_evm_config);
/*\B8\F9\BE\DD\C4诤舜\AB\B2尉\F6\B6\A8\CA欠\F1使\D3玫\E7\D7\E8\C6\C1*/
#ifndef CONFIG_ANDROID
if(screen_type == SCREEN_TYPE_R)
_configure_device(EVM_SK, mfd_dev_cfg, PROFILE_NONE);//\B5\E7\D7\E8\C6\C1\BA\CDad一\C6\F0注\B2\E1
else
_configure_device(EVM_SK, ad_dev_cfg, PROFILE_NONE);//\CF\D6\D4\DA使\D3玫\E7\C8\DD\C6\C1\A3\AC\BD\F6注\B2\E1ad
#endif
/*main setup*/
setup_ok335x();//这是我用的开发板的函数
/*create /proc/boardname to export info to userspace*/
proc_init();
/* Create an alias for icss clock */
if (clk_add_alias("pruss", NULL, "pruss_uart_gclk", NULL))
pr_warn("failed to create an alias: icss_uart_gclk --> pruss\n");
/* Create an alias for gfx/sgx clock */
if (clk_add_alias("sgx_ck", NULL, "gfx_fclk", NULL))
pr_warn("failed to create an alias: gfx_fclk --> sgx_ck\n");
}
接下来是一些用到的mux引脚设置函数:
Kernel/arch/arm/mach-omap2/Mux.c
int omap_mux_init_signal(const char *muxname, int val)
{
struct omap_mux_partition *partition = NULL;
struct omap_mux *mux = NULL;
u16 old_mode;
int mux_mode;
mux_mode = omap_mux_get_by_name(muxname, &partition, &mux);
if (mux_mode < 0)
return mux_mode;
old_mode = omap_mux_read(partition, mux->reg_offset);
mux_mode |= val;
pr_debug("%s: Setting signal %s 0x%04x -> 0x%04x\n",
__func__, muxname, old_mode, mux_mode);
omap_mux_write(partition, mux_mode, mux->reg_offset);
return 0;
}
Kernel/arch/arm/mach-omap2/Board-am335xevm.c
/*
* @pin_mux - single module pin-mux structure which defines pin-mux
* details for all its pins.
*/
static void setup_pin_mux(struct pinmux_config *pin_mux)
{
int i;
for (i = 0; pin_mux->string_name != NULL; pin_mux++)
{
omap_mux_init_signal(pin_mux->string_name, pin_mux->val);
}
}
Kernel/arch/arm/mach-omap2/Devices.c
int __init am33xx_register_ecap(int id, struct pwmss_platform_data *pdata)
{
struct platform_device *pdev;
struct omap_hwmod *oh;
char *oh_name = "ecap";
char dev_name[PWM_STR_LEN];
sprintf(dev_name, "ecap.%d", id);
oh = omap_hwmod_lookup(dev_name);
if (!oh) {
pr_err("Could not look up %s hwmod\n", dev_name);
return -ENODEV;
}
pdev = omap_device_build(oh_name, id, oh, pdata,
sizeof(*pdata), NULL, 0, 0);
if (IS_ERR(pdev)) {
WARN(1, "Can't build omap_device for %s:%s.\n",
dev_name, oh->name);
return PTR_ERR(pdev);
}
return 0;
}
int __init am33xx_register_ehrpwm(int id, struct pwmss_platform_data *pdata)
{
struct platform_device *pdev;
struct omap_hwmod *oh;
char *oh_name = "ehrpwm";
char dev_name[PWM_STR_LEN];
sprintf(dev_name, "ehrpwm.%d", id);
oh = omap_hwmod_lookup(dev_name);
if (!oh) {
pr_err("Could not look up %s hwmod\n", dev_name);
return -ENODEV;
}
pdev = omap_device_build(oh_name, id, oh, pdata,
sizeof(*pdata), NULL, 0, 0);
if (IS_ERR(pdev)) {
WARN(1, "Can't build omap_device for %s:%s.\n",
dev_name, oh->name);
return PTR_ERR(pdev);
}
return 0;
}
下面我就以一个例子记录一下引脚的配置方法,例子摘自我买的一块开发板中关于pwm控制蜂鸣器的初始化代码:
Kernel/arch/arm/mach-omap2/Board-am335xevm.c
/*pwm for buzzer*/
static void buzzer_init(int evm_id, int profile)
{
#if defined(CONFIG_1)
setup_pin_mux(ecap0_pin_mux);
am33xx_register_ecap(0, &pwm_pdata[0]);
#elif defined(CONFIG_2)
setup_pin_mux(ehrpwm1a_pin_mux);
am33xx_register_ehrpwm(1, &pwm_pdata[1]);
#endif
}
http://blog.chinaunix.net/uid-12077574-id-3527526.html