红联Linux门户
Linux帮助

Linux 2.6.21 读核笔记 at91_i2c篇

发布时间:2007-05-26 00:26:14来源:红联作者:Quickgram
在linux 2.6.21 在at91rm9200(Atmel)的使用过程中,好像i2c不太灵光,有的时候不太可靠!
读写几千次就会出现错误,一致没有明白问题出在哪。但有些需要注意的地方:

A.at91rm9200 datasheet Page396 要求如下:
• Program the PIO controller to:
- Dedicate TWD and TWCK as peripheral lines.
- Define TWD and TWCK as open-drain.
那么在linux 2.6.21 kernel里是如何实现的呢?
2.6.21于2.4.18有很多体系上的不同,例如初始化这部分 2.4.18放在kernel_source_root/drivers/i2c/里面,而2.6.21放在了kernel_source_root/Arch/arm/Mach-at91/At91rm9200_devices.c里面实现。

/* --------------------------------------------------------------------
* TWI (i2c)
* -------------------------------------------------------------------- */

#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)

static struct resource twi_resources[] = {
[0] = {
.start = AT91RM9200_BASE_TWI,
.end = AT91RM9200_BASE_TWI + SZ_16K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = AT91RM9200_ID_TWI,
.end = AT91RM9200_ID_TWI,
.flags = IORESOURCE_IRQ,
},
};

static struct platform_device at91rm9200_twi_device = {
.name = "at91_i2c",
.id = -1,
.resource = twi_resources,
.num_resources = ARRAY_SIZE(twi_resources),
};

void __init at91_add_device_i2c(void)
{
/* pins used for TWI interface */
at91_set_A_periph(AT91_PIN_PA25, 0); /* TWD */
at91_set_multi_drive(AT91_PIN_PA25, 1);

at91_set_A_periph(AT91_PIN_PA26, 0); /* TWCK */
at91_set_multi_drive(AT91_PIN_PA26, 1);

platform_device_register(&at91rm9200_twi_device);
}
#else
void __init at91_add_device_i2c(void) {}
#endif

函数at91_add_device_i2c()完成了at91 i2c的初始化,我们再近一步给出两个函数的定义

/*
* mux the pin to the "A" internal peripheral role.
*/
int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup)
{
void __iomem *pio = pin_to_controller(pin);
unsigned mask = pin_to_mask(pin);

if (!pio)
return -EINVAL;

__raw_writel(mask, pio + PIO_IDR);
__raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
__raw_writel(mask, pio + PIO_ASR);
__raw_writel(mask, pio + PIO_PDR);
return 0;
}
很明显:at91_set_A_periph把引脚赋予了PeriphA功能,同时由use_pullup给出标志。

int __init_or_module at91_set_multi_drive(unsigned pin, int is_on)
{
void __iomem *pio = pin_to_controller(pin);
unsigned mask = pin_to_mask(pin);

if (!pio)
return -EINVAL;

__raw_writel(mask, pio + (is_on ? PIO_MDER : PIO_MDDR));
return 0;
}
而at91_set_multi_drive(unsigned pin, int is_on)则设置该引脚是否多功能使能.
文章评论

共有 17 条评论

  1. 124.146.51.* 于 2007-07-18 17:51:28发表:

    http://631dee292820bcb238e9cd68a69d0f78-t.xkktxb.org 631dee292820bcb238e9cd68a69d0f78 http://631dee292820bcb238e9cd68a69d0f78-b1.xkktxb.org 631dee292820bcb238e9cd68a69d0f78 http://631dee292820bcb238e9cd68a69d0f78-b3.xkktxb.org 8d1f2bfe3cbc5359328d95464cab8b7c

  2. 201.242.206.* 于 2007-07-06 00:43:09发表:

    http://4ed2437c3a3a0d8c59efa548c2f3b81c-t.lwgmrw.org 4ed2437c3a3a0d8c59efa548c2f3b81c http://4ed2437c3a3a0d8c59efa548c2f3b81c-b1.lwgmrw.org 4ed2437c3a3a0d8c59efa548c2f3b81c http://4ed2437c3a3a0d8c59efa548c2f3b81c-b3.lwgmrw.org 7323937625928ec2c2b389a5c949efe8

  3. 寂寞男孩 于 2007-05-26 13:38:11发表:

    :ha3nd

  4. 寂寞男孩 于 2007-05-26 13:38:06发表:

    :0L

  5. 寂寞男孩 于 2007-05-26 13:38:02发表:

    :0(1