Chinaunix首页 | 论坛 | 博客
  • 博客访问: 383097
  • 博文数量: 149
  • 博客积分: 25
  • 博客等级: 民兵
  • 技术积分: 220
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-27 14:53
文章分类

全部博文(149)

文章存档

2016年(3)

2015年(2)

2014年(144)

我的朋友

分类: 嵌入式

2014-09-26 09:37:16

在解读OK6410官方提供的LED驱动程序源码的过程中,发现很多没见过的宏和函数。例如S3C64XX_GPM(0)、S3C64XX_GPM_OUTPUT(0)、__raw_writel(tmp,S3C64XX_GPMPUD)、__raw_writel(tmp,S3C64XX_GPMCON)等。而这些都包含在一些头文件里面。另一方面,我们自己动手编写LED的驱动程序也必须知道相关的头文件有哪些,对我们有哪些用。因此,我觉得在自己动手编写LED驱动程序之前对相关头文件进行简单的分析是非常有必要的。以下是我自己结合源码分析得出的一些结论,如有不正确的地方,希望能够得到指正。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define DEVICE_NAME    "leds"
#define LED_MAJOR 231


static unsigned long led_table [] = {
       S3C64XX_GPM(0),
       S3C64XX_GPM(1),
       S3C64XX_GPM(2),
       S3C64XX_GPM(3),
};

static unsigned int led_cfg_table [] = {
    S3C64XX_GPM_OUTPUT(0),
    S3C64XX_GPM_OUTPUT(1),
    S3C64XX_GPM_OUTPUT(2),
    S3C64XX_GPM_OUTPUT(3),
};

static int s3c6410_leds_ioctl(
    struct inode *inode,
    struct file *file,
    unsigned int cmd,
    unsigned long arg)
{
    unsigned long tmp;
    switch(cmd) {
    case 0:
    case 1:
        if (arg > 4) {
            return -EINVAL;
        }
        tmp = __raw_readl(S3C64XX_GPMDAT);
        if(cmd)
            tmp &= (~(1<         else
            tmp |= (1<         __raw_writel(tmp,S3C64XX_GPMDAT);
//        gpio_set_value(led_table[arg], !cmd);
        return 0;
    default:
        return -EINVAL;
    }
}


static struct file_operations s3c6410_leds_fops = {
    .owner    =    THIS_MODULE,
    .ioctl    =    s3c6410_leds_ioctl,
};

static struct cdev cdev_leds;
struct class * my_class;

static int __init s3c6410_leds_init(void)
{
    int ret;
    unsigned long tmp;
    int i;
    dev_t devno;
    printk(KERN_NOTICE "enter s3c6410_leds_init\n");


    devno = MKDEV(LED_MAJOR,0);

    ret = register_chrdev_region(devno,1,DEVICE_NAME);
    ret = 0;
    if(ret<0)
    {
        printk(KERN_NOTICE "can not register led device");
        return ret;
    }
    
    cdev_init(&cdev_leds,&s3c6410_leds_fops);
    cdev_leds.owner = THIS_MODULE;

    ret =cdev_add(&cdev_leds,devno,1);
    if(ret)
    {
        printk(KERN_NOTICE "can not add leds device");
        return ret;
    }

    my_class = class_create(THIS_MODULE,"my_class");
    if(IS_ERR(my_class))
    {
        printk("Err: Failed in creating class\n");
        return -1;    
    }

    device_create(my_class,NULL,MKDEV(LED_MAJOR,0),NULL,DEVICE_NAME);

    //gpm0-3 pull up
    tmp = __raw_readl(S3C64XX_GPMPUD);
    tmp &= (~0xFF);
    tmp |= 0xaa;
    __raw_writel(tmp,S3C64XX_GPMPUD);

    //gpm0-3 output mode
    tmp = __raw_readl(S3C64XX_GPMCON);
    tmp &= (~0xFFFF);
    tmp |= 0x1111;
    __raw_writel(tmp,S3C64XX_GPMCON);
    
    //gpm0-3 output 0
    tmp = __raw_readl(S3C64XX_GPMDAT);
    tmp |= 0x10;
    __raw_writel(tmp,S3C64XX_GPMDAT);

    //printk("S3C64XX_GPMCON is %x\n",__raw_readl(S3C64XX_GPMCON));
    //printk("S3C64XX_GPMDAT is %x\n",__raw_readl(S3C64XX_GPMDAT));
    //printk("S3C64XX_GPMPUD is %x\n",__raw_readl(S3C64XX_GPMPUD));

    printk(DEVICE_NAME " initialized\n");

    return 0;
}

static void __exit s3c6410_leds_exit(void)
{
    cdev_del(&cdev_leds);

    unregister_chrdev_region(MKDEV(LED_MAJOR,0),1);

    printk(KERN_NOTICE "s3c2440_leds_exit\n");
}


module_init(s3c6410_leds_init);
module_exit(s3c6410_leds_exit);

MODULE_LICENSE("GPL");

一、模块相关头文件:

1、#include :在编写任何模块都需要包含此头文件。该头文件自动包含了 头文件,该头文件包含了宏MODULE_LICENSE("GPL")的定义。
2、#include :此头文件也是必须的,module_init()与module_exit()宏就是定义在它里面的。而且正是这个头文件定义了初始化函数加__init和推出函数加__exit的作用(static int __init s3c6410_leds_init(void)和static void __exit s3c6410_leds_exit(void))
3、#include :此头文件也是常用头文件,如果需要使用printk函数,则必须包含此头文件。另外该头文件还包含了头文件,而这个头文件定义许多常用的数据类型,其中就包括设备号类型dev_t。如下:
#ifndef _LINUX_TYPES_H
#define _LINUX_TYPES_H

#ifdef    __KERNEL__

#define DECLARE_BITMAP(name,bits) \
    unsigned long name[BITS_TO_LONGS(bits)]

#endif

#include
#include

#ifndef __KERNEL_STRICT_NAMES

typedef __u32 __kernel_dev_t;

typedef __kernel_fd_set        fd_set;
typedef __kernel_dev_t        dev_t;
typedef __kernel_ino_t        ino_t;
typedef __kernel_mode_t        mode_t;
typedef __kernel_nlink_t    nlink_t;
typedef __kernel_off_t        off_t;
typedef __kernel_pid_t        pid_t;
typedef __kernel_daddr_t    daddr_t;
typedef __kernel_key_t        key_t;
typedef __kernel_suseconds_t    suseconds_t;
typedef __kernel_timer_t    timer_t;
typedef __kernel_clockid_t    clockid_t;
typedef __kernel_mqd_t        mqd_t;

#ifdef __KERNEL__
typedef _Bool            bool;

typedef __kernel_uid32_t    uid_t;
typedef __kernel_gid32_t    gid_t;
typedef __kernel_uid16_t        uid16_t;
typedef __kernel_gid16_t        gid16_t;

typedef unsigned long        uintptr_t;

#ifdef CONFIG_UID16
/* This is defined by include/asm-{arch}/posix_types.h */
typedef __kernel_old_uid_t    old_uid_t;
typedef __kernel_old_gid_t    old_gid_t;
#endif /* CONFIG_UID16 */

/* libc5 includes this file to define uid_t, thus uid_t can never change
 * when it is included by non-kernel code
 */
#else
typedef __kernel_uid_t        uid_t;
typedef __kernel_gid_t        gid_t;
#endif /* __KERNEL__ */

#if defined(__GNUC__)
typedef __kernel_loff_t        loff_t;
#endif

/*
 * The following typedefs are also protected by individual ifdefs for
 * historical reasons:
 */
#ifndef _SIZE_T
#define _SIZE_T
typedef __kernel_size_t        size_t;
#endif

#ifndef _SSIZE_T
#define _SSIZE_T
typedef __kernel_ssize_t    ssize_t;
#endif

#ifndef _PTRDIFF_T
#define _PTRDIFF_T
typedef __kernel_ptrdiff_t    ptrdiff_t;
#endif

#ifndef _TIME_T
#define _TIME_T
typedef __kernel_time_t        time_t;
#endif

#ifndef _CLOCK_T
#define _CLOCK_T
typedef __kernel_clock_t    clock_t;
#endif

#ifndef _CADDR_T
#define _CADDR_T
typedef __kernel_caddr_t    caddr_t;
#endif

/* bsd */
typedef unsigned char        u_char;
typedef unsigned short        u_short;
typedef unsigned int        u_int;
typedef unsigned long        u_long;

/* sysv */
typedef unsigned char        unchar;
typedef unsigned short        ushort;
typedef unsigned int        uint;
typedef unsigned long        ulong;

#ifndef __BIT_TYPES_DEFINED__
#define __BIT_TYPES_DEFINED__

typedef        __u8        u_int8_t;
typedef        __s8        int8_t;
typedef        __u16        u_int16_t;
typedef        __s16        int16_t;
typedef        __u32        u_int32_t;
typedef        __s32        int32_t;

#endif /* !(__BIT_TYPES_DEFINED__) */

typedef        __u8        uint8_t;
typedef        __u16        uint16_t;
typedef        __u32        uint32_t;

#if defined(__GNUC__)
typedef        __u64        uint64_t;
typedef        __u64        u_int64_t;
typedef        __s64        int64_t;
#endif

/* this is a special 64bit data type that is 8-byte aligned */
#define aligned_u64 __u64 __attribute__((aligned(8)))
#define aligned_be64 __be64 __attribute__((aligned(8)))
#define aligned_le64 __le64 __attribute__((aligned(8)))

/**
 * The type used for indexing onto a disc or disc partition.
 *
 * Linux always considers sectors to be 512 bytes long independently
 * of the devices real block size.
 */
#ifdef CONFIG_LBD
typedef u64 sector_t;
#else
typedef unsigned long sector_t;
#endif

/*
 * The type of the inode's block count.
 */
#ifdef CONFIG_LSF
typedef u64 blkcnt_t;
#else
typedef unsigned long blkcnt_t;
#endif

/*
 * The type of an index into the pagecache.  Use a #define so asm/types.h
 * can override it.
 */
#ifndef pgoff_t
#define pgoff_t unsigned long
#endif

#endif /* __KERNEL_STRICT_NAMES */

/*
 * Below are truly Linux-specific types that should never collide with
 * any application/library that wants linux/types.h.
 */

#ifdef __CHECKER__
#define __bitwise__ __attribute__((bitwise))
#else
#define __bitwise__
#endif
#ifdef __CHECK_ENDIAN__
#define __bitwise __bitwise__
#else
#define __bitwise
#endif

typedef __u16 __bitwise __le16;
typedef __u16 __bitwise __be16;
typedef __u32 __bitwise __le32;
typedef __u32 __bitwise __be32;
#if defined(__GNUC__)
typedef __u64 __bitwise __le64;
typedef __u64 __bitwise __be64;
#endif
typedef __u16 __bitwise __sum16;
typedef __u32 __bitwise __wsum;

#ifdef __KERNEL__
typedef unsigned __bitwise__ gfp_t;
typedef unsigned __bitwise__ fmode_t;

#ifdef CONFIG_PHYS_ADDR_T_64BIT
typedef u64 phys_addr_t;
#else
typedef u32 phys_addr_t;
#endif

typedef phys_addr_t resource_size_t;

struct ustat {
    __kernel_daddr_t    f_tfree;
    __kernel_ino_t        f_tinode;
    char            f_fname[6];
    char            f_fpack[6];
};

#endif    /* __KERNEL__ */
#endif /* _LINUX_TYPES_H */

二、字符设备驱动相关头文件:
1、#include :该头文件包含了常用的数据结构,当然也包括三种最重要的:struct file、struct file_operation、struct inode。另外该头文件还包含了头文件。
2、#include :该头文件定义了struct cdev数据结构,也包含了字符设备操作的相关函数:
#ifndef _LINUX_CDEV_H
#define _LINUX_CDEV_H

#include
#include
#include

struct file_operations;
struct inode;
struct module;

struct cdev {
    struct kobject kobj;
    struct module *owner;
    const struct file_operations *ops;
    struct list_head list;
    dev_t dev;
    unsigned int count;
};

void cdev_init(struct cdev *, const struct file_operations *);

struct cdev *cdev_alloc(void);

void cdev_put(struct cdev *p);

int cdev_add(struct cdev *, dev_t, unsigned);

void cdev_del(struct cdev *);

void cd_forget(struct inode *);

extern struct backing_dev_info directly_mappable_cdev_bdi;
#endif
3、:包含自动创建设备文件的相关函数的申明:原函数中-class_create(THIS_MODULE,"my_class")、device_create(my_class,NULL,MKDEV(LED_MAJOR,0),NULL,DEVICE_NAME)。
三、s3c64xx  GPIO操作相关头文件:
1、#include :此头文件包含了对S3C64xx 各个GPIO的宏定义,并包含了各个端口的读写函数,如下:
/* linux/arch/arm/mach-s3c6400/include/mach/gpio.h
 *
 * Copyright 2008 Openmoko, Inc.
 * Copyright 2008 Simtec Electronics
 *    
 *    Ben Dooks
 *
 * S3C6400 - GPIO lib support
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
*/

#define gpio_get_value    __gpio_get_value
#define gpio_set_value    __gpio_set_value
#define gpio_cansleep    __gpio_cansleep
#define gpio_to_irq    __gpio_to_irq

/* GPIO bank sizes */
#define S3C64XX_GPIO_A_NR    (8)
#define S3C64XX_GPIO_B_NR    (7)
#define S3C64XX_GPIO_C_NR    (8)
#define S3C64XX_GPIO_D_NR    (5)
#define S3C64XX_GPIO_E_NR    (5)
#define S3C64XX_GPIO_F_NR    (16)
#define S3C64XX_GPIO_G_NR    (7)
#define S3C64XX_GPIO_H_NR    (10)
#define S3C64XX_GPIO_I_NR    (16)
#define S3C64XX_GPIO_J_NR    (12)
#define S3C64XX_GPIO_K_NR    (16)
#define S3C64XX_GPIO_L_NR    (15)
#define S3C64XX_GPIO_M_NR    (6)
#define S3C64XX_GPIO_N_NR    (16)
#define S3C64XX_GPIO_O_NR    (16)
#define S3C64XX_GPIO_P_NR    (15)
#define S3C64XX_GPIO_Q_NR    (9)

/* GPIO bank numbes */

/* CONFIG_S3C_GPIO_SPACE allows the user to select extra
 * space for debugging purposes so that any accidental
 * change from one gpio bank to another can be caught.
*/

#define S3C64XX_GPIO_NEXT(__gpio) \
    ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)

enum s3c_gpio_number {
    S3C64XX_GPIO_A_START = 0,
    S3C64XX_GPIO_B_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_A),
    S3C64XX_GPIO_C_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_B),
    S3C64XX_GPIO_D_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_C),
    S3C64XX_GPIO_E_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_D),
    S3C64XX_GPIO_F_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_E),
    S3C64XX_GPIO_G_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_F),
    S3C64XX_GPIO_H_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_G),
    S3C64XX_GPIO_I_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_H),
    S3C64XX_GPIO_J_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_I),
    S3C64XX_GPIO_K_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_J),
    S3C64XX_GPIO_L_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_K),
    S3C64XX_GPIO_M_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_L),
    S3C64XX_GPIO_N_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_M),
    S3C64XX_GPIO_O_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_N),
    S3C64XX_GPIO_P_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_O),
    S3C64XX_GPIO_Q_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_P),
};

/* S3C64XX GPIO number definitions. */

#define S3C64XX_GPA(_nr)    (S3C64XX_GPIO_A_START + (_nr))
#define S3C64XX_GPB(_nr)    (S3C64XX_GPIO_B_START + (_nr))
#define S3C64XX_GPC(_nr)    (S3C64XX_GPIO_C_START + (_nr))
#define S3C64XX_GPD(_nr)    (S3C64XX_GPIO_D_START + (_nr))
#define S3C64XX_GPE(_nr)    (S3C64XX_GPIO_E_START + (_nr))
#define S3C64XX_GPF(_nr)    (S3C64XX_GPIO_F_START + (_nr))
#define S3C64XX_GPG(_nr)    (S3C64XX_GPIO_G_START + (_nr))
#define S3C64XX_GPH(_nr)    (S3C64XX_GPIO_H_START + (_nr))
#define S3C64XX_GPI(_nr)    (S3C64XX_GPIO_I_START + (_nr))
#define S3C64XX_GPJ(_nr)    (S3C64XX_GPIO_J_START + (_nr))
#define S3C64XX_GPK(_nr)    (S3C64XX_GPIO_K_START + (_nr))
#define S3C64XX_GPL(_nr)    (S3C64XX_GPIO_L_START + (_nr))
#define S3C64XX_GPM(_nr)    (S3C64XX_GPIO_M_START + (_nr))
#define S3C64XX_GPN(_nr)    (S3C64XX_GPIO_N_START + (_nr))
#define S3C64XX_GPO(_nr)    (S3C64XX_GPIO_O_START + (_nr))
#define S3C64XX_GPP(_nr)    (S3C64XX_GPIO_P_START + (_nr))
#define S3C64XX_GPQ(_nr)    (S3C64XX_GPIO_Q_START + (_nr))

/* the end of the S3C64XX specific gpios */
#define S3C64XX_GPIO_END    (S3C64XX_GPQ(S3C64XX_GPIO_Q_NR) + 1)
#define S3C_GPIO_END        S3C64XX_GPIO_END

/* define the number of gpios we need to the one after the GPQ() range */
#define ARCH_NR_GPIOS    (S3C64XX_GPQ(S3C64XX_GPIO_Q_NR) + 1)

#include
上面的头文件包含了头文件,该头文件包含了GPIO的数据读写函数,如下:
#ifndef _ASM_GENERIC_GPIO_H
#define _ASM_GENERIC_GPIO_H

#include
#include

#ifdef CONFIG_GPIOLIB

#include

/* Platforms may implement their GPIO interface with library code,
 * at a small performance cost for non-inlined operations and some
 * extra memory (for code and for per-GPIO table entries).
 *
 * While the GPIO programming interface defines valid GPIO numbers
 * to be in the range 0..MAX_INT, this library restricts them to the
 * smaller range 0..ARCH_NR_GPIOS-1.
 */

#ifndef ARCH_NR_GPIOS
#define ARCH_NR_GPIOS        256
#endif

static inline int gpio_is_valid(int number)
{
    /* only some non-negative numbers are valid */
    return ((unsigned)number) < ARCH_NR_GPIOS;
}

struct seq_file;
struct module;

/**
 * struct gpio_chip - abstract a GPIO controller
 * @label: for diagnostics
 * @dev: optional device providing the GPIOs
 * @owner: helps prevent removal of modules exporting active GPIOs
 * @request: optional hook for chip-specific activation, such as
 *    enabling module power and clock; may sleep
 * @free: optional hook for chip-specific deactivation, such as
 *    disabling module power and clock; may sleep
 * @direction_input: configures signal "offset" as input, or returns error
 * @get: returns value for signal "offset"; for output signals this
 *    returns either the value actually sensed, or zero
 * @direction_output: configures signal "offset" as output, or returns error
 * @set: assigns output value for signal "offset"
 * @to_irq: optional hook supporting non-static gpio_to_irq() mappings;
 *    implementation may not sleep
 * @dbg_show: optional routine to show contents in debugfs; default code
 *    will be used when this is omitted, but custom code can show extra
 *    state (such as pullup/pulldown configuration).
 * @base: identifies the first GPIO number handled by this chip; or, if
 *    negative during registration, requests dynamic ID allocation.
 * @ngpio: the number of GPIOs handled by this controller; the last GPIO
 *    handled is (base + ngpio - 1).
 * @can_sleep: flag must be set iff get()/set() methods sleep, as they
 *    must while accessing GPIO expander chips over I2C or SPI
 *
 * A gpio_chip can help platforms abstract various sources of GPIOs so
 * they can all be accessed through a common programing interface.
 * Example sources would be SOC controllers, FPGAs, multifunction
 * chips, dedicated GPIO expanders, and so on.
 *
 * Each chip controls a number of signals, identified in method calls
 * by "offset" values in the range 0..(@ngpio - 1).  When those signals
 * are referenced through calls like gpio_get_value(gpio), the offset
 * is calculated by subtracting @base from the gpio number.
 */
struct gpio_chip {
    const char        *label;
    struct device        *dev;
    struct module        *owner;

    int            (*request)(struct gpio_chip *chip,
                        unsigned offset);
    void            (*free)(struct gpio_chip *chip,
                        unsigned offset);

    int            (*direction_input)(struct gpio_chip *chip,
                        unsigned offset);
    int            (*get)(struct gpio_chip *chip,
                        unsigned offset);
    int            (*direction_output)(struct gpio_chip *chip,
                        unsigned offset, int value);
    void            (*set)(struct gpio_chip *chip,
                        unsigned offset, int value);

    int            (*to_irq)(struct gpio_chip *chip,
                        unsigned offset);

    void            (*dbg_show)(struct seq_file *s,
                        struct gpio_chip *chip);
    int            base;
    u16            ngpio;
    unsigned        can_sleep:1;
    unsigned        exported:1;
};

extern const char *gpiochip_is_requested(struct gpio_chip *chip,
            unsigned offset);
extern int __must_check gpiochip_reserve(int start, int ngpio);

/* add/remove chips */
extern int gpiochip_add(struct gpio_chip *chip);
extern int __must_check gpiochip_remove(struct gpio_chip *chip);


/* Always use the library code for GPIO management calls,
 * or when sleeping may be involved.
 */
extern int gpio_request(unsigned gpio, const char *label);
extern void gpio_free(unsigned gpio);

extern int gpio_direction_input(unsigned gpio);
extern int gpio_direction_output(unsigned gpio, int value);

extern int gpio_get_value_cansleep(unsigned gpio);
extern void gpio_set_value_cansleep(unsigned gpio, int value);


/* A platform's code may want to inline the I/O calls when
 * the GPIO is constant and refers to some always-present controller,
 * giving direct access to chip registers and tight bitbanging loops.
 */
extern int __gpio_get_value(unsigned gpio);
extern void __gpio_set_value(unsigned gpio, int value);

extern int __gpio_cansleep(unsigned gpio);

extern int __gpio_to_irq(unsigned gpio);

#ifdef CONFIG_GPIO_SYSFS

/*
 * A sysfs interface can be exported by individual drivers if they want,
 * but more typically is configured entirely from userspace.
 */
extern int gpio_export(unsigned gpio, bool direction_may_change);
extern void gpio_unexport(unsigned gpio);

#endif    /* CONFIG_GPIO_SYSFS */

#else    /* !CONFIG_HAVE_GPIO_LIB */

static inline int gpio_is_valid(int number)
{
    /* only non-negative numbers are valid */
    return number >= 0;
}

/* platforms that don't directly support access to GPIOs through I2C, SPI,
 * or other blocking infrastructure can use these wrappers.
 */

static inline int gpio_cansleep(unsigned gpio)
{
    return 0;
}

static inline int gpio_get_value_cansleep(unsigned gpio)
{
    might_sleep();
    return gpio_get_value(gpio);
}

static inline void gpio_set_value_cansleep(unsigned gpio, int value)
{
    might_sleep();
    gpio_set_value(gpio, value);
}

#endif /* !CONFIG_HAVE_GPIO_LIB */

#ifndef CONFIG_GPIO_SYSFS

/* sysfs support is only available with gpiolib, where it's optional */

static inline int gpio_export(unsigned gpio, bool direction_may_change)
{
    return -ENOSYS;
}

static inline void gpio_unexport(unsigned gpio)
{
}
#endif    /* CONFIG_GPIO_SYSFS */
#endif /* _ASM_GENERIC_GPIO_H */

2、#include :定义了GPIO相关的数据宏:
/* linux/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h
 *
 * Copyright 2008 Openmoko, Inc.
 * Copyright 2008 Simtec Electronics
 *      Ben Dooks
 *     
 *
 * S3C64XX - GPIO register definitions
 */

#ifndef __ASM_PLAT_S3C64XX_REGS_GPIO_H
#define __ASM_PLAT_S3C64XX_REGS_GPIO_H __FILE__

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include #include
#include
#include
#include
#include

/* Base addresses for each of the banks */

#define S3C64XX_GPA_BASE    (S3C64XX_VA_GPIO + 0x0000)
#define S3C64XX_GPB_BASE    (S3C64XX_VA_GPIO + 0x0020)
#define S3C64XX_GPC_BASE    (S3C64XX_VA_GPIO + 0x0040)
#define S3C64XX_GPD_BASE    (S3C64XX_VA_GPIO + 0x0060)
#define S3C64XX_GPE_BASE    (S3C64XX_VA_GPIO + 0x0080)
#define S3C64XX_GPF_BASE    (S3C64XX_VA_GPIO + 0x00A0)
#define S3C64XX_GPG_BASE    (S3C64XX_VA_GPIO + 0x00C0)
#define S3C64XX_GPH_BASE    (S3C64XX_VA_GPIO + 0x00E0)
#define S3C64XX_GPI_BASE    (S3C64XX_VA_GPIO + 0x0100)
#define S3C64XX_GPJ_BASE    (S3C64XX_VA_GPIO + 0x0120)
#define S3C64XX_GPK_BASE    (S3C64XX_VA_GPIO + 0x0800)
#define S3C64XX_GPL_BASE    (S3C64XX_VA_GPIO + 0x0810)
#define S3C64XX_GPM_BASE    (S3C64XX_VA_GPIO + 0x0820)
#define S3C64XX_GPN_BASE    (S3C64XX_VA_GPIO + 0x0830)
#define S3C64XX_GPO_BASE    (S3C64XX_VA_GPIO + 0x0140)
#define S3C64XX_GPP_BASE    (S3C64XX_VA_GPIO + 0x0160)
#define S3C64XX_GPQ_BASE    (S3C64XX_VA_GPIO + 0x0180)
#define S3C64XX_SPC_BASE    (S3C64XX_VA_GPIO + 0x01A0)
#define S3C64XX_MEM0CONSTOP    (S3C64XX_VA_GPIO + 0x01B0)
#define S3C64XX_MEM1CONSTOP    (S3C64XX_VA_GPIO + 0x01B4)
#define S3C64XX_MEM0CONSLP0    (S3C64XX_VA_GPIO + 0x01C0)
#define S3C64XX_MEM0CONSLP1    (S3C64XX_VA_GPIO + 0x01C4)
#define S3C64XX_MEM1CONSLP    (S3C64XX_VA_GPIO + 0x01C8)
#define S3C64XX_MEM0DRVCON    (S3C64XX_VA_GPIO + 0x01D0)
#define S3C64XX_MEM1DRVCON    (S3C64XX_VA_GPIO + 0x01D4)
#define S3C64XX_EINT0CON0    (S3C64XX_VA_GPIO + 0x0900)
#define S3C64XX_EINT0CON1    (S3C64XX_VA_GPIO + 0x0904)
#define S3C64XX_EINT0FLTCON0    (S3C64XX_VA_GPIO + 0x0910)
#define S3C64XX_EINT0FLTCON1    (S3C64XX_VA_GPIO + 0x0914)
#define S3C64XX_EINT0FLTCON2    (S3C64XX_VA_GPIO + 0x0918)
#define S3C64XX_EINT0FLTCON3    (S3C64XX_VA_GPIO + 0x091C)
#define S3C64XX_EINT0MASK    (S3C64XX_VA_GPIO + 0x0920)
#define S3C64XX_EINT0PEND    (S3C64XX_VA_GPIO + 0x0924)
#define S3C64XX_SPCONSLP    (S3C64XX_VA_GPIO + 0x0880)
#define S3C64XX_SLPEN        (S3C64XX_VA_GPIO + 0x0930)
#define S3C64XX_EINT12CON    (S3C64XX_VA_GPIO + 0x0200)
#define S3C64XX_EINT34CON    (S3C64XX_VA_GPIO + 0x0204)
#define S3C64XX_EINT56CON    (S3C64XX_VA_GPIO + 0x0208)
#define S3C64XX_EINT78CON    (S3C64XX_VA_GPIO + 0x020C)
#define S3C64XX_EINT9CON    (S3C64XX_VA_GPIO + 0x0210)
#define S3C64XX_EINT12FLTCON    (S3C64XX_VA_GPIO + 0x0220)
#define S3C64XX_EINT34FLTCON    (S3C64XX_VA_GPIO + 0x0224)
#define S3C64XX_EINT56FLTCON    (S3C64XX_VA_GPIO + 0x0228)
#define S3C64XX_EINT78FLTCON    (S3C64XX_VA_GPIO + 0x022C)
#define S3C64XX_EINT9FLTCON    (S3C64XX_VA_GPIO + 0x0230)
#define S3C64XX_EINT12MASK    (S3C64XX_VA_GPIO + 0x0240)
#define S3C64XX_EINT34MASK    (S3C64XX_VA_GPIO + 0x0244)
#define S3C64XX_EINT56MASK    (S3C64XX_VA_GPIO + 0x0248)
#define S3C64XX_EINT78MASK    (S3C64XX_VA_GPIO + 0x024C)
#define S3C64XX_EINT9MASK    (S3C64XX_VA_GPIO + 0x0250)
#define S3C64XX_EINT12PEND    (S3C64XX_VA_GPIO + 0x0260)
#define S3C64XX_EINT34PEND    (S3C64XX_VA_GPIO + 0x0264)
#define S3C64XX_EINT56PEND    (S3C64XX_VA_GPIO + 0x0268)
#define S3C64XX_EINT78PEND    (S3C64XX_VA_GPIO + 0x026C)
#define S3C64XX_EINT9PEND    (S3C64XX_VA_GPIO + 0x0270)
#define S3C64XX_PRIORITY    (S3C64XX_VA_GPIO + 0x0280)
#define S3C64XX_SERVICE        (S3C64XX_VA_GPIO + 0x0284)
#define S3C64XX_SERVICEPEND    (S3C64XX_VA_GPIO + 0x0288)

/* values for S3C_EXTINT0 */
#define S3C64XX_EXTINT_LOWLEV     (0x00)
#define S3C64XX_EXTINT_HILEV     (0x01)
#define S3C64XX_EXTINT_FALLEDGE     (0x02)
#define S3C64XX_EXTINT_RISEEDGE     (0x04)
#define S3C64XX_EXTINT_BOTHEDGE     (0x06)

#endif /* __ASM_PLAT_S3C64XX_REGS_GPIO_H */

由上可知此头文件包含了------->系列头文件,而这些头文件里面定义了对应GPIO的一系列数据宏,例如 里面定义的是led程序中用到的GPM端口相关的数据宏,如下:
/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-m.h
 *
 * Copyright 2008 Openmoko, Inc.
 * Copyright 2008 Simtec Electronics
 *  Ben Dooks
 * 
 *
 * GPIO Bank M register and configuration definitions
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
*/

#define S3C64XX_GPMCON          (S3C64XX_GPM_BASE + 0x00)
#define S3C64XX_GPMDAT          (S3C64XX_GPM_BASE + 0x04)
#define S3C64XX_GPMPUD          (S3C64XX_GPM_BASE + 0x08)

#define S3C64XX_GPM_CONMASK(__gpio) (0x3 << ((__gpio) * 2))
#define S3C64XX_GPM_INPUT(__gpio)   (0x0 << ((__gpio) * 2))
#define S3C64XX_GPM_OUTPUT(__gpio)  (0x1 << ((__gpio) * 2))

#define S3C64XX_GPM0_HOSTIF_CS      (0x02 << 0)
#define S3C64XX_GPM0_EINT23      (0x03 << 0)
#define S3C64XX_GPM0_RESERVED1      (0x04 << 0)
#define S3C64XX_GPM0_DATA_CF10      (0x05 << 0)
#define S3C64XX_GPM0_CE_CF0      (0x06 << 0)
#define S3C64XX_GPM0_RESERVED2      (0x07 << 0)

#define S3C64XX_GPM1_HOSTIF_CS_M      (0x02 << 0)
#define S3C64XX_GPM1_EINT24      (0x03 << 0)
#define S3C64XX_GPM1_RESERVED1      (0x04 << 0)
#define S3C64XX_GPM1_DATA_CF11      (0x05 << 0)
#define S3C64XX_GPM1_CE_CF1      (0x06 << 0)
#define S3C64XX_GPM1_RESERVED2      (0x07 << 0)

#define S3C64XX_GPM2_HOSTIF_IF_CS_S      (0x02 << 0)
#define S3C64XX_GPM2_EINT25      (0x03 << 0)
#define S3C64XX_GPM2_HOSTIF_MDP_VSYNC      (0x04 << 0)
#define S3C64XX_GPM2_DATA_CF12      (0x05 << 0)
#define S3C64XX_GPM2_IORD_CF      (0x06 << 0)
#define S3C64XX_GPM2_RESERVED2      (0x07 << 0)

#define S3C64XX_GPM3_HOSTIF_WE      (0x02 << 0)
#define S3C64XX_GPM3_EINT26      (0x03 << 0)
#define S3C64XX_GPM3_RESERVED1      (0x04 << 0)
#define S3C64XX_GPM3_DATA_CF13      (0x05 << 0)
#define S3C64XX_GPM3_IOWR_CF      (0x06 << 0)
#define S3C64XX_GPM3_RESERVED2      (0x07 << 0)

#define S3C64XX_GPM4_HOSTIF_OE      (0x02 << 0)
#define S3C64XX_GPM4_EINT27      (0x03 << 0)
#define S3C64XX_GPM4_RESERVED1      (0x04 << 0)
#define S3C64XX_GPM4_DATA_CF14      (0x05 << 0)
#define S3C64XX_GPM4_IORDY_CF      (0x06 << 0)
#define S3C64XX_GPM4_RESERVED2      (0x07 << 0)

#define S3C64XX_GPM5_HOSTIF_INTR      (0x02 << 0)
#define S3C64XX_GPM5_CF_DATA_DIR      (0x03 << 0)
#define S3C64XX_GPM5_RESERVED1      (0x04 << 0)
#define S3C64XX_GPM5_DATA_CF15      (0x05 << 0)
#define S3C64XX_GPM5_RESERVED2      (0x06 << 0)
#define S3C64XX_GPM5_RESERVED3      (0x07 << 0)

3、#include :此头文件包含了GPIO的各种配置函数,例如设置输入输出方式,上拉电阻使能等等:

/* linux/arch/arm/plat-s3c/include/plat/gpio-cfg.h
 *
 * Copyright 2008 Openmoko, Inc.
 * Copyright 2008 Simtec Electronics
 *    
 *    Ben Dooks
 *
 * S3C Platform - GPIO pin configuration
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
*/

/* This file contains the necessary definitions to get the basic gpio
 * pin configuration done such as setting a pin to input or output or
 * changing the pull-{up,down} configurations.
 */

/* Note, this interface is being added to the s3c64xx arch first and will
 * be added to the s3c24xx systems later.
 */

#ifndef __PLAT_GPIO_CFG_H
#define __PLAT_GPIO_CFG_H __FILE__

typedef unsigned int __bitwise__ s3c_gpio_pull_t;

/* forward declaration if gpio-core.h hasn't been included */
struct s3c_gpio_chip;

/**
 * struct s3c_gpio_cfg GPIO configuration
 * @cfg_eint: Configuration setting when used for external interrupt source
 * @get_pull: Read the current pull configuration for the GPIO
 * @set_pull: Set the current pull configuraiton for the GPIO
 * @set_config: Set the current configuration for the GPIO
 * @get_config: Read the current configuration for the GPIO
 *
 * Each chip can have more than one type of GPIO bank available and some
 * have different capabilites even when they have the same control register
 * layouts. Provide an point to vector control routine and provide any
 * per-bank configuration information that other systems such as the
 * external interrupt code will need.
 */
struct s3c_gpio_cfg {
    unsigned int    cfg_eint;

    s3c_gpio_pull_t    (*get_pull)(struct s3c_gpio_chip *chip, unsigned offs);
    int        (*set_pull)(struct s3c_gpio_chip *chip, unsigned offs,
                    s3c_gpio_pull_t pull);

    unsigned (*get_config)(struct s3c_gpio_chip *chip, unsigned offs);
    int     (*set_config)(struct s3c_gpio_chip *chip, unsigned offs,
                   unsigned config);
};

#define S3C_GPIO_SPECIAL_MARK    (0xfffffff0)
#define S3C_GPIO_SPECIAL(x)    (S3C_GPIO_SPECIAL_MARK | (x))

/* Defines for generic pin configurations */
#define S3C_GPIO_INPUT    (S3C_GPIO_SPECIAL(0))
#define S3C_GPIO_OUTPUT    (S3C_GPIO_SPECIAL(1))
#define S3C_GPIO_SFN(x)    (S3C_GPIO_SPECIAL(x))

#define s3c_gpio_is_cfg_special(_cfg) \
    (((_cfg) & S3C_GPIO_SPECIAL_MARK) == S3C_GPIO_SPECIAL_MARK)

/**
 * s3c_gpio_cfgpin() - Change the GPIO function of a pin.
 * @pin pin The pin number to configure.
 * @pin to The configuration for the pin's function.
 *
 * Configure which function is actually connected to the external
 * pin, such as an gpio input, output or some form of special function
 * connected to an internal peripheral block.
 */
extern int s3c_gpio_cfgpin(unsigned int pin, unsigned int to);

/* Define values for the pull-{up,down} available for each gpio pin.
 *
 * These values control the state of the weak pull-{up,down} resistors
 * available on most pins on the S3C series. Not all chips support both
 * up or down settings, and it may be dependant on the chip that is being
 * used to whether the particular mode is available.
 */
#define S3C_GPIO_PULL_NONE    ((__force s3c_gpio_pull_t)0x00)
#define S3C_GPIO_PULL_DOWN    ((__force s3c_gpio_pull_t)0x01)
#define S3C_GPIO_PULL_UP    ((__force s3c_gpio_pull_t)0x02)

/**
 * s3c_gpio_setpull() - set the state of a gpio pin pull resistor
 * @pin: The pin number to configure the pull resistor.
 * @pull: The configuration for the pull resistor.
 *
 * This function sets the state of the pull-{up,down} resistor for the
 * specified pin. It will return 0 if successfull, or a negative error
 * code if the pin cannot support the requested pull setting.
*/
extern int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull);

/**
 * s3c_gpio_getpull() - get the pull resistor state of a gpio pin
 * @pin: The pin number to get the settings for
 *
 * Read the pull resistor value for the specified pin.
*/
extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin);

#endif /* __PLAT_GPIO_CFG_H */







阅读(1810) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~