From f94c5f3b28e967c73c49dcda43b4b458f5b79e73 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Mon, 22 Jan 2018 12:59:17 +0300 Subject: sandbox: add gpio support with libftdi1 Signed-off-by: Antony Pavlov Signed-off-by: Sascha Hauer --- arch/sandbox/Kconfig | 1 + arch/sandbox/Makefile | 6 +- arch/sandbox/mach-sandbox/include/mach/linux.h | 12 ++ arch/sandbox/os/Makefile | 3 + arch/sandbox/os/ftdi.c | 154 +++++++++++++++++++++++++ 5 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 arch/sandbox/os/ftdi.c (limited to 'arch') diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig index 9c72673bde..3f1cefb837 100644 --- a/arch/sandbox/Kconfig +++ b/arch/sandbox/Kconfig @@ -1,6 +1,7 @@ config SANDBOX bool select OFTREE + select GPIOLIB default y config ARCH_TEXT_BASE diff --git a/arch/sandbox/Makefile b/arch/sandbox/Makefile index 9d545c3b71..85c70b5e80 100644 --- a/arch/sandbox/Makefile +++ b/arch/sandbox/Makefile @@ -41,9 +41,13 @@ ifeq ($(CONFIG_DRIVER_VIDEO_SDL),y) SDL_LIBS := $(shell pkg-config sdl --libs) endif +ifeq ($(CONFIG_GPIO_LIBFTDI1),y) +FTDI1_LIBS := $(shell pkg-config libftdi1 --libs) +endif + cmd_barebox__ = $(CC) -o $@ -Wl,-T,$(barebox-lds) \ -Wl,--start-group $(barebox-common) -Wl,--end-group \ - -lrt -lpthread $(SDL_LIBS) + -lrt -lpthread $(SDL_LIBS) $(FTDI1_LIBS) common-y += $(BOARD) arch/sandbox/os/ diff --git a/arch/sandbox/mach-sandbox/include/mach/linux.h b/arch/sandbox/mach-sandbox/include/mach/linux.h index 1327a56cab..52360f8771 100644 --- a/arch/sandbox/mach-sandbox/include/mach/linux.h +++ b/arch/sandbox/mach-sandbox/include/mach/linux.h @@ -38,4 +38,16 @@ void sdl_get_bitfield_rgba(struct fb_bitfield *r, struct fb_bitfield *g, struct fb_bitfield *b, struct fb_bitfield *a); void sdl_setpixel(int x, int y, uint8_t r, uint8_t g, uint8_t b, uint8_t a); +struct ft2232_bitbang; +struct ft2232_bitbang *barebox_libftdi1_open(int vendor_id, int device_id, + const char *serial); +void barebox_libftdi1_gpio_direction(struct ft2232_bitbang *ftbb, + unsigned off, unsigned dir); +int barebox_libftdi1_gpio_get_value(struct ft2232_bitbang *ftbb, + unsigned off); +void barebox_libftdi1_gpio_set_value(struct ft2232_bitbang *ftbb, + unsigned off, unsigned val); +int barebox_libftdi1_update(struct ft2232_bitbang *ftbb); +void barebox_libftdi1_close(void); + #endif /* __ASM_ARCH_LINUX_H */ diff --git a/arch/sandbox/os/Makefile b/arch/sandbox/os/Makefile index 537f848e06..75baa34a83 100644 --- a/arch/sandbox/os/Makefile +++ b/arch/sandbox/os/Makefile @@ -17,3 +17,6 @@ obj-y = common.o tap.o CFLAGS_sdl.o = $(shell pkg-config sdl --cflags) obj-$(CONFIG_DRIVER_VIDEO_SDL) += sdl.o + +CFLAGS_ftdi.o = $(shell pkg-config libftdi1 --cflags) +obj-$(CONFIG_GPIO_LIBFTDI1) += ftdi.o diff --git a/arch/sandbox/os/ftdi.c b/arch/sandbox/os/ftdi.c new file mode 100644 index 0000000000..6485d5cfab --- /dev/null +++ b/arch/sandbox/os/ftdi.c @@ -0,0 +1,154 @@ +/* + * sandbox barebox libftdi1 support + * + * Copyright (C) 2016, 2017 Antony Pavlov + * + * 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. + * + */ + +#include +#include + +#define GPIOF_DIR_OUT (0 << 0) +#define GPIOF_DIR_IN (1 << 0) + +#define BIT(nr) (1UL << (nr)) + +struct ft2232_bitbang { + struct ftdi_context *ftdi; + uint8_t odata; + uint8_t dir; +}; + +static struct ft2232_bitbang ftbb; + +static inline int ftdi_flush(struct ftdi_context *ftdi) +{ + uint8_t buf[1]; + int ret; + + buf[0] = SEND_IMMEDIATE; + + ret = ftdi_write_data(ftdi, buf, 1); + + return ret; +} + +static int ftdi_get_high_byte_data(struct ftdi_context *ftdi, uint8_t *data) +{ + uint8_t obuf; + int ret; + + obuf = GET_BITS_HIGH; + ret = ftdi_write_data(ftdi, &obuf, 1); + + ret = ftdi_read_data(ftdi, data, 1); + + return ret; +} + +static int ftdi_set_high_byte_data_dir(struct ft2232_bitbang *ftbb) +{ + uint8_t buf[3]; + int ret; + + buf[0] = SET_BITS_HIGH; + buf[1] = ftbb->odata; + buf[2] = ftbb->dir; + + ret = ftdi_write_data(ftbb->ftdi, buf, 3); + ftdi_flush(ftbb->ftdi); + + return ret; +} + +int barebox_libftdi1_update(struct ft2232_bitbang *ftbb) +{ + return ftdi_set_high_byte_data_dir(ftbb); +} + +void barebox_libftdi1_gpio_direction(struct ft2232_bitbang *ftbb, + unsigned off, unsigned dir) +{ + switch (dir) { + case GPIOF_DIR_IN: + ftbb->dir &= ~BIT(off); + break; + case GPIOF_DIR_OUT: + ftbb->dir |= BIT(off); + break; + default: + printf("%s:%d: invalid dir argument\n", __FILE__, __LINE__); + } +} + +int barebox_libftdi1_gpio_get_value(struct ft2232_bitbang *ftbb, unsigned off) +{ + uint8_t data; + + ftdi_get_high_byte_data(ftbb->ftdi, &data); + + return !!(data & BIT(off)); +} + +void barebox_libftdi1_gpio_set_value(struct ft2232_bitbang *ftbb, + unsigned off, unsigned val) +{ + if (val) + ftbb->odata |= BIT(off); + else + ftbb->odata &= ~BIT(off); +} + +struct ft2232_bitbang *barebox_libftdi1_open(int id_vendor, int id_product, + const char *serial) +{ + struct ftdi_context *ftdi; + int ret; + + ftdi = ftdi_new(); + if (!ftdi) { + fprintf(stderr, "ftdi_new failed\n"); + goto error; + } + + ret = ftdi_usb_open_desc(ftdi, id_vendor, id_product, NULL, serial); + if (ret < 0 && ret != -5) { + fprintf(stderr, "unable to open ftdi device: %d (%s)\n", + ret, ftdi_get_error_string(ftdi)); + goto error; + } + + ftdi_set_interface(ftdi, INTERFACE_A); + ftdi_set_bitmode(ftdi, 0x00, BITMODE_MPSSE); + + ftbb.ftdi = ftdi; + + /* reset pins to default neutral state */ + ftbb.dir = 0; + ftbb.odata = 0; + ftdi_set_high_byte_data_dir(&ftbb); + + return &ftbb; + +error: + return NULL; +} + +void barebox_libftdi1_close(void) +{ + struct ftdi_context *ftdi = ftbb.ftdi; + + ftdi_set_interface(ftdi, INTERFACE_ANY); + ftdi_usb_close(ftdi); + ftdi_free(ftdi); +} -- cgit v1.2.3