The Mail List discusses how writel is implemented. This function writes data to a register or memory address at the operating system layer with memory protection. In ARCH/alpha/kernel/IO. C
188 void writel(u32 b, volatile void __iomem *addr)
189 {
190 __raw_writel(b, addr);
191 mb();
192 }
This writel function is used to write a value to an address,I want to know the specific implementation details under this function, so I will continue to trace the code :__ Raw_writel (B, ADDR );
129 void __raw_writel(u32 b, volatile void __iomem *addr)
130 {
131 IO_CONCAT(__IO_PREFIX,writel)(b, addr);
132 }
Next, trace io_concat in the corresponding Io.H is defined as follows:
134 #define IO_CONCAT(a,b) _IO_CONCAT(a,b)
135 #define _IO_CONCAT(a,b) a ## _ ## b
This code was asked a few days ago to indicate the meaning of connecting strings on both sides.
Track_io_prefix is defined as follows:
501 #undef __IO_PREFIX
502 #define __IO_PREFIX apecs
This is the end, and I will be dizzy again. The problem is as follows: 1. How did I write data into the address? I extracted these separately,Pre-compile. After macro expansion, we found that:
void __raw_writel(u32 b, volatile void __iomem *addr)
{
apecs_writel(b, addr);
}
However, the apecs_writel function was not found in the kernel,Please help explain.
For the first question,
you should refer to the file "arch\alpha\kernle\Machvec_impl.h"
"~\Machve.h" "~\io.c" "~\io.h" "~\core_**.h".
as you have analysized before, in the file Machvec_impl.h and Machve.h,
DO_CIA_IO,IO,IO_LITE, these three macros implement the symbole
connection between ** arch and writel function, and the function
pointer initializations.
so, the details implementation to writel is to init the
alpha_machine_vector structure and the definition to the relevant
function pointer invoked to complete the low-level write operation.
.mv_writel =CAT(low,_writel),<---IO(CIA,cia)<-->cia_writel(b, addr); <---
|
writel(b, addr)-->__raw_writel(b, addr);--->cia_writel(b,addr)---------------
For the second quesiton,
mb()--->__asm__ __volatile__("mb": : :"memory");
so, it is a memory barrier for alpha architecture to ensure some
operations before some actions could be occured.
and, it is similiar with the barrier() in x86 platform/arm platform.
Continue to read the code and see definition _ IO _Which header file is included after the prefix. In which Header
Find the answer. For your apsec, see the following code snippet (Linux-2.6.28-rc4)
arch/alpha/include/asm/core_apecs.h
------------------------------------------
#undef __IO_PREFIX
#define __IO_PREFIX apecs
#define apecs_trivial_io_bw 0
#define apecs_trivial_io_lq 0
#define apecs_trivial_rw_bw 2
#define apecs_trivial_rw_lq 1
#define apecs_trivial_iounmap 1
#include <asm/io_trivial.h>
------------------------------------------
arch/alpha/include/asm/io_trivial.h
------------------------------------------
__EXTERN_INLINE void
IO_CONCAT(__IO_PREFIX,writel)(u32 b, volatile void __iomem *a)
{
*(volatile u32 __force *)a = b;
}
That is, a = B is finally passed through * (volatile u32 _ force;
To write data. If there is no OS and no MMU, when the Development Board runs naked, we only need one sentence for everything: * (unsigned long *) ADDR = value;