gpio driver Add gpio driver interface.

Signed-off-by: Jan Willeke <willeke@smartmote.de>
This commit is contained in:
Jan Willeke 2015-02-03 22:22:39 +01:00 提交者 Daniel Beer
父節點 9497265e72
當前提交 1be4ed0679
共有 9 個檔案被更改,包括 401 行新增2 行删除

查看文件

@ -145,6 +145,7 @@ OBJ=\
drivers/devicelist.o \
drivers/fet_olimex_db.o \
drivers/jtdev.o \
drivers/jtdev_gpio.o \
drivers/jtaglib.o \
drivers/pif.o \
drivers/loadbsl.o \

查看文件

@ -64,5 +64,6 @@ struct jtdev_func{
};
extern const struct jtdev_func jtdev_func_pif;
extern const struct jtdev_func jtdev_func_gpio;
#endif

263
drivers/jtdev_gpio.c Normal file
查看文件

@ -0,0 +1,263 @@
/* MSPDebug - gpio device interface
* Copyright (C) 2014 TTI GmbH - TGU Smartmote
* Author(s): Jan Willeke (willeke@smartmote.de)
*
* Linux /sys/class/gpio interface to msp430 jtag
* inspired by urjtag and jtdev.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdint.h>
#include "jtdev.h"
#include "output.h"
#if defined(__linux__) || \
( defined(__FreeBSD__) || defined(__DragonFly__) )
/*===== includes =============================================================*/
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include "gpio.h"
/* pin mapping */
enum {
GPIO_TDI = 0,
GPIO_TCK,
GPIO_TMS,
GPIO_TDO,
GPIO_REQUIRED
};
unsigned int jtag_gpios[4];
int fd_gpios[4];
static int
gpio_open ()
{
int i, ret;
/* Export all gpios */
for (i = 0; i < GPIO_REQUIRED; i++)
{
unsigned int gpio = jtag_gpios[i];
ret = gpio_export (gpio);
if (ret)
{
printf("gpio[%d] %u cannot be exported\n", i, gpio);
return -1;
}
gpio_set_dir (gpio, (i == GPIO_TDO) ? 0 : 1);
fd_gpios[i] = gpio_open_fd(gpio);
if (fd_gpios[i] < 0)
{
printf("gpio: cannot open gpio[%d] %u\n", i, gpio);
return -1;
}
}
return 0;
}
static int
gpio_parse_config (const char *params)
{
struct option{
char* name;
int num;
};
static const struct option ops[] = {
{"tms=",GPIO_TMS},
{"tdi=",GPIO_TDI},
{"tdo=",GPIO_TDO},
{"tck=",GPIO_TCK}
};
int i;
for( i = 0;i < 4; i++) {
char* help;
help = strstr(params,ops[i].name);
if (help)
jtag_gpios[ops[i].num] = atoi(help+4);
else
return -1;
printf("gpio %s %d\n", ops[i].name,jtag_gpios[ops[i].num]);
}
return 0;
}
static int jtgpio_open(struct jtdev *p, const char *device)
{
if (gpio_parse_config(device)){
printf("gpio: failed parsing parameters\n");
return -1;
}
return gpio_open();
}
static void jtgpio_close(struct jtdev *p)
{
int i;
printf("JTAG_CLOSE\n");
for (i = 0; i < GPIO_REQUIRED; i++)
{
if (fd_gpios[i])
close (fd_gpios[i]);
gpio_unexport (jtag_gpios[i]);
}
}
static void jtgpio_power_on(struct jtdev *p)
{
printf("JTAG_power on\n");
}
static void jtgpio_power_off(struct jtdev *p)
{
printf("JTAG_power off\n");
}
static void jtgpio_connect(struct jtdev *p)
{
printf("JTAG_connct \n");
}
static void jtgpio_release(struct jtdev *p)
{
printf("JTAG_release\n");
}
static void jtgpio_tck(struct jtdev *p, int out)
{
gpio_set_value_fd (fd_gpios[GPIO_TCK], out);
}
static void jtgpio_tms(struct jtdev *p, int out)
{
gpio_set_value_fd (fd_gpios[GPIO_TMS], out);
}
static void jtgpio_tdi(struct jtdev *p, int out)
{
gpio_set_value_fd (fd_gpios[GPIO_TDI], out);
}
static void jtgpio_rst(struct jtdev *p, int out)
{
printf("jtag_reset\n");
}
static void jtgpio_tst(struct jtdev *p, int out)
{
printf("jtag_test\n");
}
static int jtgpio_tdo_get(struct jtdev *p)
{
return gpio_get_value_fd (fd_gpios[GPIO_TDO],
jtag_gpios[GPIO_TDO]);
}
static void jtgpio_tclk(struct jtdev *p, int out)
{
gpio_set_value_fd (fd_gpios[GPIO_TDI], out);
}
static int jtgpio_tclk_get(struct jtdev *p)
{
return gpio_get_value_fd (fd_gpios[GPIO_TDI],
jtag_gpios[GPIO_TDI]);
}
static void jtgpio_tclk_strobe(struct jtdev *p, unsigned int count)
{
int i;
for (i=0;i<count;i++){
gpio_set_value_fd (fd_gpios[GPIO_TDI], 1);
gpio_set_value_fd (fd_gpios[GPIO_TDI], 0);
}
}
static void jtgpio_led_green(struct jtdev *p, int out)
{
printf("led green\n");
}
static void jtgpio_led_red(struct jtdev *p, int out)
{
printf("led red\n");
}
#else /* __linux__ */
static int jtgpio_open(struct jtdev *p, const char *device)
{
printc_err("jtdev: driver is not supported on this platform\n");
p->failed = 1;
return -1;
}
static void jtgpio_close(struct jtdev *p) { }
static void jtgpio_power_on(struct jtdev *p) { }
static void jtgpio_power_off(struct jtdev *p) { }
static void jtgpio_connect(struct jtdev *p) { }
static void jtgpio_release(struct jtdev *p) { }
static void jtgpio_tck(struct jtdev *p, int out) { }
static void jtgpio_tms(struct jtdev *p, int out) { }
static void jtgpio_tdi(struct jtdev *p, int out) { }
static void jtgpio_rst(struct jtdev *p, int out) { }
static void jtgpio_tst(struct jtdev *p, int out) { }
static int jtgpio_tdo_get(struct jtdev *p) { return 0; }
static void jtgpio_tclk(struct jtdev *p, int out) { }
static int jtgpio_tclk_get(struct jtdev *p) { return 0; }
static void jtgpio_tclk_strobe(struct jtdev *p, unsigned int count) { }
static void jtgpio_led_green(struct jtdev *p, int out) { }
static void jtgpio_led_red(struct jtdev *p, int out) { }
#endif
const struct jtdev_func jtdev_func_gpio = {
.jtdev_open = jtgpio_open,
.jtdev_close = jtgpio_close,
.jtdev_power_on = jtgpio_power_on,
.jtdev_power_off = jtgpio_power_off,
.jtdev_connect = jtgpio_connect,
.jtdev_release = jtgpio_release,
.jtdev_tck = jtgpio_tck,
.jtdev_tms = jtgpio_tms,
.jtdev_tdi = jtgpio_tdi,
.jtdev_rst = jtgpio_rst,
.jtdev_tst = jtgpio_tst,
.jtdev_tdo_get = jtgpio_tdo_get,
.jtdev_tclk = jtgpio_tclk,
.jtdev_tclk_get = jtgpio_tclk_get,
.jtdev_tclk_strobe = jtgpio_tclk_strobe,
.jtdev_led_green = jtgpio_led_green,
.jtdev_led_red = jtgpio_led_red
};

查看文件

@ -330,6 +330,8 @@ static int pif_erase( device_t dev_base,
}
/*----------------------------------------------------------------------------*/
static device_t pif_open(const struct device_args *args)
{
struct pif_device *dev;
@ -370,6 +372,49 @@ static device_t pif_open(const struct device_args *args)
return &dev->base;
}
/*----------------------------------------------------------------------------*/
static device_t gpio_open(const struct device_args *args)
{
struct pif_device *dev;
if (!(args->flags & DEVICE_FLAG_TTY)) {
printc_err("gpio: this driver does not support raw USB access\n");
return NULL;
}
if (!(args->flags & DEVICE_FLAG_JTAG)) {
printc_err("gpio: this driver does not support Spy-Bi-Wire\n");
return NULL;
}
dev = malloc(sizeof(*dev));
if (!dev) {
printc_err("gpio: malloc: %s\n", last_error());
return NULL;
}
memset(dev, 0, sizeof(*dev));
dev->base.type = &device_pif;
dev->base.max_breakpoints = 0;
(&dev->jtag)->f = &jtdev_func_gpio;
if ((&dev->jtag)->f->jtdev_open(&dev->jtag, args->path) < 0) {
printc_err("gpio: can't open port\n");
free(dev);
return NULL;
}
if (init_device(&dev->jtag) < 0) {
printc_err("gpio: initialization failed\n");
free(dev);
return NULL;
}
return &dev->base;
}
/*----------------------------------------------------------------------------*/
static void pif_destroy(device_t dev_base)
{
@ -396,3 +441,17 @@ const struct device_class device_pif = {
.poll = pif_poll,
.erase = pif_erase
};
const struct device_class device_gpio = {
.name = "gpio",
.help = "/sys/class/gpio direct connect",
.open = gpio_open,
.destroy = pif_destroy,
.readmem = pif_readmem,
.writemem = pif_writemem,
.getregs = pif_getregs,
.setregs = pif_setregs,
.ctl = pif_ctl,
.poll = pif_poll,
.erase = pif_erase
};

查看文件

@ -32,5 +32,7 @@
/* pif implementation */
extern const struct device_class device_pif;
/* share wiht gpio implementation */
extern const struct device_class device_gpio;
#endif

查看文件

@ -199,6 +199,13 @@ only tty access is supported. Currently, this driver is only supported
on Linux, FreeBSD and DragonFly BSD. A parallel port device (ppdev on
Linux, ppi on FreeBSD and DragonFly BSD) must be specified via the
\fB-d\fR option.
.IP "\fBgpio\fR"
Connect to system gpios. JTAG mode must be used, and
only tty access is supported. Currently, this driver is only supported
on Linux, FreeBSD and DragonFly BSD. The gpios to used must defined using
a string like "tdi=7 tdo=8 tms=9 tck=4" via the
\fB-d\fR option. (dont forget the quotes)
.IP "\fBload-bsl\fR"
Connect to a USB bootloader. The stub bootloader will be used to load a
fuller-featured bootloader into RAM for execution.

查看文件

@ -87,6 +87,7 @@ static const struct device_class *const driver_table[] = {
&device_tilib,
&device_goodfet,
&device_pif,
&device_gpio,
&device_loadbsl,
&device_ezfet,
&device_rom_bsl

查看文件

@ -158,4 +158,67 @@ int gpio_get_value ( unsigned int gpio )
return ( ch != '0' );
}
/**
* Opens GPIO (input/output) pin file descriptor
* @param gpio GPIO number
* @return file descriptor, -1 if fails
*/
int gpio_open_fd ( unsigned int gpio ) {
int fd;
char buf[MAX_BUF];
snprintf ( buf, MAX_BUF, SYSFS_GPIO_DIR "/gpio%d/value", gpio );
fd = open ( buf, O_RDWR );
if ( fd < 0 )
{
perror ( "gpio/get-value" );
return -1;
}
return fd;
}
/**
* Sets GPIO (output) value with given file descriptor
* @param file descriptor
* @param gpio GPIO number
* @return 0 if OK, -1 if fails
*/
int gpio_set_value_fd (int fd, int value)
{
ssize_t ret;
char gpio_value = value + '0';
ret = write (fd, &gpio_value, 1);
if (ret != 1)
{
printf("Error setting value gpio\n");
return -1;
}
return 0;
}
/**
* Read state of GPIO (input) pin, with file descriptor
* @param file descriptor
* @param gpio GPIO number
* @return 0 if LO, 1 if HI, -1 if fails
*/
int gpio_get_value_fd (int fd, unsigned int gpio)
{
ssize_t ret;
char value;
ret = pread (fd, &value, 1, 0);
if (ret != 1)
{
printf("Error getting value of gpio %u\n", gpio);
return -1;
}
return value == '1';
}

查看文件

@ -17,6 +17,8 @@ int gpio_export ( unsigned int gpio );
int gpio_unexport ( unsigned int gpio );
int gpio_set_dir ( unsigned int gpio, unsigned int out_flag );
int gpio_set_value ( unsigned int gpio, unsigned int value );
int gpio_set_value_fd (int fd, int value);
int gpio_get_value ( unsigned int gpio );
#endif
int gpio_get_value_fd (int fd, unsigned int gpio);
int gpio_open_fd (unsigned int gpio);
#endif