使用gpio-cfg.h中提供的函数来操作gpio
在使用之前先得搞清楚gpio如何初始化的
参阅 arch/arm/mach-s3c64xx/gpiolib.c
gpio的信息分别保存在 gpio_4bit, gpio_4bit2, gpio_2bit三个结构体数组中
gpio_4bit是指gpio的每个端口在con中占4bit
gpio_4bit2是指gpio的每个端口在con中占4bit,如果gpio端口多的花,一个con寄存器不够用,得有两个
gpio_2bit是指gpio的每个端口在con中占2bit
gpio_4bit, gpio_4bit2, gpio_2bit三个结构体如下
struct s3c_gpio_chip {
struct gpio_chip chip;
struct s3c_gpio_cfg *config;
struct s3c_gpio_pm *pm;
void __iomem *base;
int irq_base;
int group;
spinlock_t lock;
#ifdef CONFIG_PM
u32 pm_save[4];
#endif
};
gpio_4bit 包含 GPA GPB GPC GPD GPE GPG GPM
gpio_4bit2 包含 GPH GPK GPL
gpio_2bit 包含 GPF GPI GPJ GPN GPO GPP GPQ
内核调用s3c64xx_gpiolib_init函数来初始化gpio信息
在s3c64xx_gpiolib_init函数中,又调用了三次s3c64xx_gpiolib_add函数,将三组gpio加入信息表
函数s3c64xx_gpiolib_add循环遍历数组,调用s3c_gpiolib_add函数添加每个gpio端口
s3c_gpiolib_add函数定义在arch/arm/plat-samsung/gpio.c中
该函数对gpio数据进行检验,之后调用s3c_gpiolib_track将gpio信息保存在数组s3c_gpios中
s3c_gpios数组是一个关键数据,
使用前包含如下头文件
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
可以使用的函数
int s3c_gpio_cfgpin(unsigned int pin, unsigned int to); //设置单一io
unsigned s3c_gpio_getcfg(unsigned int pin);//获取io口的配置
int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr, unsigned int cfg); //设置一组io
int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull); //设置单一io的上拉电阻
s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin);//获取io口的上拉电阻配置
int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr, unsigned int cfg, s3c_gpio_pull_t pull);//设置一组io(包括上拉电阻)
这里有个问题,我们可以发现它并没有提供setpin函数,这就需要我们自己添加了
我这里抛砖引玉,加个
附个patch
diff --git a/arch/arm/mach-s3c64xx/gpiolib.c b/arch/arm/mach-s3c64xx/gpiolib.c
index 92b0908..2aed1f1 100644
--- a/arch/arm/mach-s3c64xx/gpiolib.c
+++ b/arch/arm/mach-s3c64xx/gpiolib.c
@@ -54,6 +54,7 @@ static struct s3c_gpio_cfg gpio_4bit_cfg_noint = {
.get_config = s3c_gpio_getcfg_s3c64xx_4bit,
.set_pull = s3c_gpio_setpull_updown,
.get_pull = s3c_gpio_getpull_updown,
+ .set_pin = s3c_gpio_setpin_s3c64xx,
};
static struct s3c_gpio_cfg gpio_4bit_cfg_eint0111 = {
@@ -62,6 +63,7 @@ static struct s3c_gpio_cfg gpio_4bit_cfg_eint0111 = {
.get_config = s3c_gpio_getcfg_s3c64xx_4bit,
.set_pull = s3c_gpio_setpull_updown,
.get_pull = s3c_gpio_getpull_updown,
+ .set_pin = s3c_gpio_setpin_s3c64xx,
};
static struct s3c_gpio_cfg gpio_4bit_cfg_eint0011 = {
@@ -70,6 +72,7 @@ static struct s3c_gpio_cfg gpio_4bit_cfg_eint0011 = {
.set_config = s3c_gpio_setcfg_s3c64xx_4bit,
.set_pull = s3c_gpio_setpull_updown,
.get_pull = s3c_gpio_getpull_updown,
+ .set_pin = s3c_gpio_setpin_s3c64xx,
};
static int s3c64xx_gpio2int_gpm(struct gpio_chip *chip, unsigned pin)
@@ -177,6 +180,7 @@ static struct s3c_gpio_cfg gpio_2bit_cfg_noint = {
.get_config = s3c_gpio_getcfg_s3c24xx,
.set_pull = s3c_gpio_setpull_updown,
.get_pull = s3c_gpio_getpull_updown,
+ .set_pin = s3c_gpio_setpin_s3c64xx,
};
static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = {
@@ -185,6 +189,7 @@ static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = {
.get_config = s3c_gpio_getcfg_s3c24xx,
.set_pull = s3c_gpio_setpull_updown,
.get_pull = s3c_gpio_getpull_updown,
+ .set_pin = s3c_gpio_setpin_s3c64xx,
};
static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = {
@@ -193,6 +198,7 @@ static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = {
.get_config = s3c_gpio_getcfg_s3c24xx,
.set_pull = s3c_gpio_setpull_updown,
.get_pull = s3c_gpio_getpull_updown,
+ .set_pin = s3c_gpio_setpin_s3c64xx,
};
static struct s3c_gpio_chip gpio_2bit[] = {
diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c
index 1c0b040..6cce8bb 100644
--- a/arch/arm/plat-samsung/gpio-config.c
+++ b/arch/arm/plat-samsung/gpio-config.c
@@ -130,6 +130,24 @@ s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
}
EXPORT_SYMBOL(s3c_gpio_getpull);
+int s3c_gpio_setpin(unsigned int pin, int value)
+{
+ struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
+ unsigned long flags;
+ int offset, ret;
+
+ if (chip) {
+ offset = pin - chip->chip.base;
+ s3c_gpio_lock(chip, flags);
+ ret = s3c_gpio_do_setpin(chip, offset, value);
+ s3c_gpio_unlock(chip, flags);
+ return ret;
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(s3c_gpio_setpin);
+
#ifdef CONFIG_S3C_GPIO_CFG_S3C24XX
int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
unsigned int off, unsigned int cfg)
@@ -249,6 +267,18 @@ unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
return S3C_GPIO_SPECIAL(con);
}
+int s3c_gpio_setpin_s3c64xx(struct s3c_gpio_chip *chip,
+ unsigned int off, int val)
+{
+ void __iomem *reg = chip->base + 4;
+ u32 data;
+
+ data = __raw_readl(reg);
+ data &= ~(0x1 << off);
+ data |= (val & 0x1) << off;
+ __raw_writel(data, reg);
+ return 0;
+}
#endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */
#ifdef CONFIG_S3C_GPIO_PULL_UPDOWN
diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
index 5603db0..776b762 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
@@ -48,6 +48,11 @@ static inline s3c_gpio_pull_t s3c_gpio_do_getpull(struct s3c_gpio_chip *chip,
return chip->config->get_pull(chip, off);
}
+static inline int s3c_gpio_do_setpin(struct s3c_gpio_chip *chip,
+ unsigned int off, int val)
+{
+ return (chip->config->set_pin)(chip, off, val);
+}
/**
* s3c_gpio_setcfg_s3c24xx - S3C24XX style GPIO configuration.
* @chip: The gpio chip that is being configured.
@@ -138,6 +143,9 @@ extern int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
extern unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
unsigned int off);
+extern int s3c_gpio_setpin_s3c64xx(struct s3c_gpio_chip *chip,
+ unsigned int off, int val);
+
/* Pull-{up,down} resistor controls.
*
* S3C2410,S3C2440,S3C24A0 = Pull-UP,
@@ -158,6 +166,7 @@ extern unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
extern int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
unsigned int off, s3c_gpio_pull_t pull);
+
/**
* s3c_gpio_setpull_1down() - Pull configuration for choice of down or none
* @chip: The gpio chip that is being configured
diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg.h b/arch/arm/plat-samsung/include/plat/gpio-cfg.h
index e4b5cf1..6feef63 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-cfg.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-cfg.h
@@ -59,6 +59,8 @@ struct s3c_gpio_cfg {
unsigned (*get_config)(struct s3c_gpio_chip *chip, unsigned offs);
int (*set_config)(struct s3c_gpio_chip *chip, unsigned offs,
unsigned config);
+ int (*set_pin)(struct s3c_gpio_chip *chip, unsigned offs,
+ int value);
};
#define S3C_GPIO_SPECIAL_MARK (0xfffffff0)
@@ -172,6 +174,15 @@ extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin);
extern int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
unsigned int cfg, s3c_gpio_pull_t pull);
+/**
+ * s3c_gpio_setpin() - set output value.
+ * @pin: The gpio number.
+ * @value: The value.
+ *
+ */
+extern int s3c_gpio_setpin(unsigned int pin, int value);
+
+
static inline int s3c_gpio_cfgrange_nopull(unsigned int pin, unsigned int size,
unsigned int cfg)
{
diff --git a/drivers/char/mini6410_leds.c b/drivers/char/mini6410_leds.c
index d3ab414..7132857 100644
--- a/drivers/char/mini6410_leds.c
+++ b/drivers/char/mini6410_leds.c
@@ -35,21 +35,16 @@
static long sbc2440_leds_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
switch(cmd) {
- unsigned tmp;
- case 0:
- case 1:
- if (arg > 4) {
+ case 0:
+ case 1:
+ break;
+ default:
return -EINVAL;
- }
- tmp = readl(S3C64XX_GPKDAT);
- tmp &= ~(1 << (4 + arg));
- tmp |= ( (!cmd) << (4 + arg) );
- writel(tmp, S3C64XX_GPKDAT);
- //printk (DEVICE_NAME": %d %d\n", arg, cmd);
- return 0;
- default:
+ }
+ if (arg > 4) {
return -EINVAL;
}
+ return s3c_gpio_setpin(S3C64XX_GPK(4 + arg), !cmd);
}
static struct file_operations dev_fops = {
@@ -67,17 +62,16 @@ static int __init dev_init(void)
{
int ret;
- ret = s3c_gpio_cfgall_range(S3C64XX_GPK(4), 4, S3C_GPIO_OUTPUT, S3C_GPIO_PULL_UP);
+ ret = s3c_gpio_cfgpin_range(S3C64XX_GPK(4), 4, S3C_GPIO_OUTPUT);
if (ret) {
printk (DEVICE_NAME"\t failed\n");
return ret;
}
-
ret = misc_register(&misc);
- printk (DEVICE_NAME"\tinitialized\n");
+ printk (DEVICE_NAME"\t loaded \n");
return ret;
}