使用writel将4位写入ioremap映射的内存地址

Chu*_*uen 2 c kernel-module linux-kernel gpio ioremap

我是内核编程的新手,现在尝试将一些值写入设备驱动程序中的32位GPIO寄存器。I / O被ioremap()设置为内存地址。问题是,我不知道如何writel()/ writeb()/ writew()该地址写入位。

供应商文件说该寄存器已打开0xE5200000。我要写入的[0:3]位是这些位,其余的28位(这些[4:31]位)保留为零。

这是到目前为止我编写的设备驱动程序代码的一部分:

#define TCON_ADDR 0xE250000 // The address as provided by the vendor
static void *TIMER_CON_ADDR;
// I have to map and write to the address when the device is opened
static int on_dev_open(struct inode *inode, struct file *file) {
    unsigned int data;
    TIMER_CON_ADDR = ioremap(TCON_ADDR, 4); // Map the [0:4] bits to TIMER_CON_ADDR
    data = 4; // 0100 in binary
    writel(data, TIMER_CON_ADDR); // Write 0100 to TIMER_CON_ADDR
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

上面的代码可能对所有人来说都是胡言乱语,但是我对write(l|w|b)and 并不熟悉ioremap()

所以我的问题是:

  1. 我是否将[0:4]位正确映射到TIMER_CON_ADDR?
  2. 如果没有,我该如何正确映射它们?
  3. 正确映射4位之后,如何使用任何write(1|w|b)函数以0100正确的顺序将位()写入TIMER_CON_ADDR?
  4. 什么是write(l|w|b)引擎盖写位下怎么办?
  5. 我有什么想念的信息吗?

感谢您提前提供的所有帮助。

fgh*_*ghj 5

  1. 我是否将[0:4]位正确映射到TIMER_CON_ADDR?

不,您写入32位,writel 写入4个字节,4 * 8 = 32位

  1. 如果没有,我该如何正确映射它们?

无法映射4位,最少8位= 1字节,但是如果使用32位寄存器,则需要映射32位= 4字节。也不要忘记检查和处理错误。

  1. 正确映射4位之后,如何使用任何write(1|w|b)函数以0100正确的顺序将位()写入TIMER_CON_ADDR?

您需要使用readl,充满内核的示例,只需grepdriverslinux内核源代码树的子目录中运行即可。总体思路读/写:

u32 reg = readl(TIMER_CON_ADDR);
reg &= ~0xfu;
reg |= 4;
writel(reg, TIMER_CON_ADDR);
Run Code Online (Sandbox Code Playgroud)
  1. 什么是write(l|w|b)引擎盖写位下怎么办?

看一下源代码,它只是简单的C函数,例如:

static inline void __raw_writel(u32 value, volatile void __iomem *addr)
{
    *(volatile u32 __force *)addr = value;
}
Run Code Online (Sandbox Code Playgroud)

主要思想是告诉编译器不应删除您的内存读取/写入

  1. 我有什么想念的信息吗?

阅读类似驱动程序的源代码,它已经包含了几乎所有此类简单驱动程序的解决方案。