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 committed by Daniel Beer
parent 9497265e72
commit 1be4ed0679
9 changed files with 401 additions and 2 deletions

View File

@ -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 \

View File

@ -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
View 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
};

View File

@ -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
};

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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';
}

View File

@ -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