我所理解的linux kernel的移植
阿新 • • 發佈:2019-02-02
從林納斯.託瓦茲(Linus B. Torvalds)執掌的網站www.kernel.org下載linux核心,比如:linux-4.9.30.tar.gz,解壓:tar zxf linux-4.9.30.tar.gz,進入目錄:cd linux-4.9.30,配置:make ARCH=arm64 menuconfig,編譯:make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image,結果完全無警告、無錯誤地編譯通過了,說明它是一個完整的原始碼,但卻無法拷貝至手機、機頂盒或開發板中使用,因為還未為其移植”驅動程式”。
kernel是一套完整的原始碼,就象一張”會計報表”一樣,為”驅動程式”留有很多空格,用於填寫資料(函式指標)。比如,gpio驅動,核心定義一個struct gpio_chip,如下:
struct gpio_chip {
const char *label;
struct gpio_device *gpiodev;
struct device *parent;
struct module *owner;
int (*request)(struct gpio_chip *chip,
unsigned offset);
void (*free)(struct gpio_chip *chip,
unsigned offset);
int (*get_direction)(struct gpio_chip *chip,
unsigned offset);
int (*direction_input)(struct gpio_chip *chip,
unsigned offset);
int (*direction_output)(struct gpio_chip *chip,
unsigned offset, int value);
int (*get)(struct gpio_chip *chip,
unsigned offset);
void (*set)(struct gpio_chip *chip,
unsigned offset, int value);
void (*set_multiple)(struct gpio_chip *chip,
unsigned long *mask,
unsigned long *bits);
int (*set_debounce)(struct gpio_chip *chip,
unsigned offset,
unsigned debounce);
int (*set_single_ended)(struct gpio_chip *chip,
unsigned offset,
enum single_ended_mode mode);
#ifdef CONFIG_AMLOGIC_PINCTRL
int (*set_pull)(struct gpio_chip *chip,
unsigned int offset, int value);
#endif
int (*to_irq)(struct gpio_chip *chip,
unsigned offset);
void (*dbg_show)(struct seq_file *s,
struct gpio_chip *chip);
int base;
u16 ngpio;
const char *const *names;
bool can_sleep;
bool irq_not_threaded;
#if IS_ENABLED(CONFIG_GPIO_GENERIC)
unsigned long (*read_reg)(void __iomem *reg);
void (*write_reg)(void __iomem *reg, unsigned long data);
unsigned long (*pin2mask)(struct gpio_chip *gc, unsigned int pin);
void __iomem *reg_dat;
void __iomem *reg_set;
void __iomem *reg_clr;
void __iomem *reg_dir;
int bgpio_bits;
spinlock_t bgpio_lock;
unsigned long bgpio_data;
unsigned long bgpio_dir;
#endif
#ifdef CONFIG_GPIOLIB_IRQCHIP
/*
* With CONFIG_GPIOLIB_IRQCHIP we get an irqchip inside the gpiolib
* to handle IRQs for most practical cases.
*/
struct irq_chip *irqchip;
struct irq_domain *irqdomain;
unsigned int irq_base;
irq_flow_handler_t irq_handler;
unsigned int irq_default_type;
int irq_parent;
bool irq_need_valid_mask;
unsigned long *irq_valid_mask;
struct lock_class_key *lock_key;
#endif
#if defined(CONFIG_OF_GPIO)
/*
* If CONFIG_OF is enabled, then all GPIO controllers described in the
* device tree automatically may have an OF translation
*/
struct device_node *of_node;
int of_gpio_n_cells;
int (*of_xlate)(struct gpio_chip *gc,
const struct of_phandle_args *gpiospec, u32 *flags);
#endif
};
結構中的(*request)、(*free)、(*get_direction)、(*direction_input)等在移植前都是”空指標”,能被編譯但卻無法使用,需要我們根據具體的SOC晶片的資料編寫一個個具體的、能工作的函式,並將函式的指標”填充”到gpio_chip結構中去,再呼叫gpiochip_add()函式一下,核心和應用程式就可以呼叫我們編寫的驅動程式了。
domain->chip.label = domain->data->name;
/* domain->chip.dev = pc->dev; */
domain->chip.parent = pc->dev;
domain->chip.request = meson_gpio_request;
domain->chip.free = meson_gpio_free;
domain->chip.direction_input = meson_gpio_direction_input;
domain->chip.direction_output = meson_gpio_direction_output;
domain->chip.get = meson_gpio_get;
domain->chip.set = meson_gpio_set;
domain->chip.set_pull = meson_gpio_pull_set;
domain->chip.base = domain->data->pin_base;
domain->chip.ngpio = domain->data->num_pins;
domain->chip.can_sleep = false;
domain->chip.of_node = domain->of_node;
domain->chip.of_gpio_n_cells = 2;
ret = gpiochip_add(&domain->chip);
上面這段程式就是填充的過程。
以此來推,其它驅動也是”類似”填充的。