diff options
Diffstat (limited to 'meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src')
7 files changed, 0 insertions, 1117 deletions
diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/Makefile b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/Makefile deleted file mode 100644 index 102ac4e..0000000 --- a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2014-present Facebook. All Rights Reserved. -all: spi-bb mdio-bb - -spi-bb: spi_bb.o bitbang.o gpio.o - $(CC) -o $@ $^ $(LDFLAGS) - -mdio-bb: mdio_bb.o bitbang.o gpio.o - $(CC) -o $@ $^ $(LDFLAGS) - -.PHONY: clean - -clean: - rm -rf *.o spi-bb mdio-bb diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.c b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.c deleted file mode 100644 index cf7dcd3..0000000 --- a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright 2014-present Facebook. All Rights Reserved. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -//#define DEBUG -//#define VERBOSE - -#include "bitbang.h" - -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include "facebook/log.h" - -#define NANOSEC_IN_SEC (1000 * 1000 * 1000) - -#define BITBANG_FREQ_MAX (500 * 1000 * 1000) /* 500M Hz */ -#define BITBANG_FREQ_DEFAULT (1 * 1000 * 1000) /* 1M Hz */ - -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) - -struct bitbang_handle { - bitbang_init_st bbh_init; - uint32_t bbh_half_clk; /* ns per clock cycle */ -}; - -void bitbang_init_default(bitbang_init_st *init) -{ - memset(init, sizeof(*init), 0); - init->bbi_clk_start = BITBANG_PIN_HIGH; - init->bbi_data_out = BITBANG_CLK_EDGE_FALLING; - init->bbi_data_in = BITBANG_CLK_EDGE_RISING; - init->bbi_freq = BITBANG_FREQ_DEFAULT; -} - -bitbang_handle_st* bitbang_open(const bitbang_init_st *init) -{ - bitbang_handle_st *hdl; - - if (!init || !init->bbi_pin_f - || !init->bbi_freq || init->bbi_freq > BITBANG_FREQ_MAX) { - LOG_ERR(EINVAL, "Invalid init structure"); - return NULL; - } - - hdl = calloc(1, sizeof(*hdl)); - if (!hdl) { - return NULL; - } - - hdl->bbh_init = *init; - hdl->bbh_half_clk = NANOSEC_IN_SEC / init->bbi_freq / 2; - - LOG_DBG("Bitbang open with initial %s, data out at %s, data in at %s, " - "freq at %uHz, half clk %uns", - (init->bbi_clk_start == BITBANG_PIN_LOW) ? "LOW" : "HIGH", - (init->bbi_data_out == BITBANG_CLK_EDGE_RISING) - ? "RISING" : "FALLING", - (init->bbi_data_in == BITBANG_CLK_EDGE_RISING) - ? "RISING" : "FALLING", - init->bbi_freq, hdl->bbh_half_clk); - - return hdl; -} - -void bitbang_close(bitbang_handle_st *hdl) -{ - free(hdl); -} - -/* - * The threshold (ns) to use spin instead of nanosleep(). - * Before adding the high resolution timer support, either spin or nanosleep() - * will not bring the process wakeup within 10ms. It turns out the system time - * update is also controlled by HZ (100). - * After I added the high resolution timer support, the spin works as the - * system time is updated more frequently. However, nanosleep() solution is - * still noticable slower comparing with spin. There could be some kernel - * scheduling tweak missing. Did not get time on that yet. - * For now, use 10ms as the threshold to determine if spin or nanosleep() - * is used. - */ -#define BITBANG_SPIN_THRESHOLD (10 * 1000 * 1000) - -static int sleep_ns(uint32_t clk) -{ - struct timespec req, rem; - int rc = 0; - if (clk <= BITBANG_SPIN_THRESHOLD) { - struct timespec orig; - rc = clock_gettime(CLOCK_MONOTONIC, &req); - orig = req; - while (!rc && clk) { - uint32_t tmp; - rc = clock_gettime(CLOCK_MONOTONIC, &rem); - tmp = (rem.tv_sec - req.tv_sec) * NANOSEC_IN_SEC; - if (rem.tv_nsec >= req.tv_nsec) { - tmp += rem.tv_nsec - req.tv_nsec; - } else { - tmp -= req.tv_nsec - rem.tv_nsec; - } - if (tmp >= clk) { - break; - } - clk -= tmp; - req = rem; - } - } else { - req.tv_sec = 0; - req.tv_nsec = clk; - while ((rc = nanosleep(&req, &rem)) == -1 && errno == EINTR) { - req = rem; - } - } - if (rc == -1) { - rc = errno; - LOG_ERR(rc, "Failed to sleep %u nanoseconds", clk); - } - return rc; -} - -int bitbang_io(const bitbang_handle_st *hdl, bitbang_io_st *io) -{ - int rc = 0; - uint32_t clk = hdl->bbh_half_clk; - const struct { - bitbang_pin_value_en value; - bitbang_clk_edge_en edge; - } clks[] = { - {BITBANG_PIN_HIGH, BITBANG_CLK_EDGE_FALLING}, - {BITBANG_PIN_LOW, BITBANG_CLK_EDGE_RISING}, - }; - int clk_idx; - int n_clk = 0; - int n_bits = 0; - const uint8_t *dout = io->bbio_dout; - uint8_t *din = io->bbio_din; - int bit_pos = 7; - bitbang_pin_func pin_f = hdl->bbh_init.bbi_pin_f; - void *context = hdl->bbh_init.bbi_context; - - if ((io->bbio_in_bits == 0 && io->bbio_din) - || (io->bbio_in_bits > 0 && !io->bbio_din)) { - rc = EINVAL; - LOG_ERR(rc, "Incorrect in bits and in buffer"); - goto out; - } - - if ((io->bbio_out_bits == 0 && io->bbio_dout) - || (io->bbio_out_bits > 0 && !io->bbio_dout)) { - rc = EINVAL; - LOG_ERR(rc, "Incorrect out bits and out buffer"); - goto out; - } - - if (io->bbio_in_bits == 0 && io->bbio_out_bits == 0) { - rc = EINVAL; - LOG_ERR(rc, "Both in and out bits are 0"); - goto out; - } - - if (hdl->bbh_init.bbi_clk_start == BITBANG_PIN_HIGH) { - clk_idx = 0; - } else { - clk_idx = 1; - } - - /* set the CLK pin start position */ - pin_f(BITBANG_CLK_PIN, clks[clk_idx].value, context); - - /* clear the first byte of din */ - if (din && io->bbio_in_bits) { - memset(din, 0, (io->bbio_in_bits + 7) / 8); - } - - do { - if ((rc = sleep_ns(clk))) { - goto out; - } - - /* output first */ - if (hdl->bbh_init.bbi_data_out == clks[clk_idx].edge) { - if (dout && n_bits < io->bbio_out_bits) { - pin_f(BITBANG_DATA_OUT, (*dout >> bit_pos) & 0x1, context); - } - } - - /* then, input */ - if (hdl->bbh_init.bbi_data_in == clks[clk_idx].edge) { - if (din && n_bits < io->bbio_in_bits) { - *din |= (pin_f(BITBANG_DATA_IN, 0, context) & 0x1) << bit_pos; - } - } - - if (++n_clk % 2 == 0) { - /* one bit for every 2 half clks */ - n_bits ++; - if (bit_pos == 0) { - if (dout) { - dout++; - } - if (din) { - din++; - } - bit_pos = 7; - } else { - bit_pos --; - } - } - clk_idx = 1 - clk_idx; - pin_f(BITBANG_CLK_PIN, clks[clk_idx].value, context); - } while (n_bits < MAX(io->bbio_in_bits, io->bbio_out_bits)); - - out: - - return -rc; -} diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.h b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.h deleted file mode 100644 index 0f21a49..0000000 --- a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/bitbang.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2014-present Facebook. All Rights Reserved. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#ifndef BITBANG_H -#define BITBANG_H - -#include <stdint.h> - -typedef enum { - BITBANG_CLK_PIN, - BITBANG_DATA_IN, - BITBANG_DATA_OUT, -} bitbang_pin_type_en; - -typedef enum { - BITBANG_PIN_LOW = 0, - BITBANG_PIN_HIGH = 1, -} bitbang_pin_value_en; - -typedef enum { - BITBANG_CLK_EDGE_RISING, - BITBANG_CLK_EDGE_FALLING, -} bitbang_clk_edge_en; - -typedef bitbang_pin_value_en (* bitbang_pin_func)( - bitbang_pin_type_en pin, bitbang_pin_value_en value, void *context); - -typedef struct { - bitbang_pin_value_en bbi_clk_start; - bitbang_clk_edge_en bbi_data_out; - bitbang_clk_edge_en bbi_data_in; - uint32_t bbi_freq; - bitbang_pin_func bbi_pin_f; - void *bbi_context; -} bitbang_init_st; - -typedef struct bitbang_handle bitbang_handle_st; - -void bitbang_init_default(bitbang_init_st *init); -bitbang_handle_st* bitbang_open(const bitbang_init_st *init); -void bitbang_close(bitbang_handle_st *hdl); - -typedef struct { - uint32_t bbio_in_bits; - uint32_t bbio_out_bits; - uint8_t *bbio_dout; - uint8_t *bbio_din; -} bitbang_io_st; - -int bitbang_io(const bitbang_handle_st *hdl, bitbang_io_st *io); - -#endif diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.c b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.c deleted file mode 100644 index 026aebc..0000000 --- a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2014-present Facebook. All Rights Reserved. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -//#define DEBUG -//#define VERBOSE - -#include "gpio.h" - -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/errno.h> - -#include "facebook/log.h" - -void gpio_init_default(gpio_st *g) { - g->gs_gpio = -1; - g->gs_fd = -1; -} - -int gpio_open(gpio_st *g, int gpio) -{ - char buf[128]; - int rc; - - snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%u/value", gpio); - rc = open(buf, O_RDWR); - if (rc == -1) { - rc = errno; - LOG_ERR(rc, "Failed to open %s", buf); - return -rc; - } - g->gs_fd = rc; - g->gs_gpio = gpio; - return 0; -} - -void gpio_close(gpio_st *g) -{ - if (g && g->gs_fd != -1) { - close(g->gs_fd); - } - gpio_init_default(g); -} - -gpio_value_en gpio_read(gpio_st *g) -{ - char buf[32] = {0}; - gpio_value_en v; - lseek(g->gs_fd, 0, SEEK_SET); - read(g->gs_fd, buf, sizeof(buf)); - v = atoi(buf) ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW; - LOG_VER("read gpio=%d value=%d %d", g->gs_gpio, atoi(buf), v); - return v; -} - -void gpio_write(gpio_st *g, gpio_value_en v) -{ - lseek(g->gs_fd, 0, SEEK_SET); - write(g->gs_fd, (v == GPIO_VALUE_HIGH) ? "1" : "0", 1); - LOG_VER("write gpio=%d value=%d", g->gs_gpio, v); -} - -int gpio_change_direction(gpio_st *g, gpio_direction_en dir) -{ - char buf[128]; - char *val; - int fd = -1; - int rc = 0; - - snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%u/direction", g->gs_gpio); - fd = open(buf, O_WRONLY); - if (fd == -1) { - rc = errno; - LOG_ERR(rc, "Failed to open %s", buf); - return -rc; - } - - val = (dir == GPIO_DIRECTION_IN) ? "in" : "out"; - write(fd, val, strlen(val)); - - LOG_VER("change gpio=%d direction=%s", g->gs_gpio, val); - - out: - if (fd != -1) { - close(fd); - } - return -rc; -} diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.h b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.h deleted file mode 100644 index 3303986..0000000 --- a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/gpio.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2014-present Facebook. All Rights Reserved. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#ifndef GPIO_H -#define GPIO_H - -typedef struct { - int gs_gpio; - int gs_fd; -} gpio_st; - -typedef enum { - GPIO_DIRECTION_IN, - GPIO_DIRECTION_OUT, -} gpio_direction_en; - -typedef enum { - GPIO_VALUE_LOW = 0, - GPIO_VALUE_HIGH = 1, -} gpio_value_en; - -int gpio_open(gpio_st* g, int gpio); -void gpio_close(gpio_st *g); -gpio_value_en gpio_read(gpio_st *g); -void gpio_write(gpio_st *g, gpio_value_en v); -int gpio_change_direction(gpio_st *g, gpio_direction_en dir); - -#endif diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/mdio_bb.c b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/mdio_bb.c deleted file mode 100644 index ef0c567..0000000 --- a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/mdio_bb.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright 2014-present Facebook. All Rights Reserved. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -//#define DEBUG -//#define VERBOSE - -#include "bitbang.h" -#include "gpio.h" - -#include <stdlib.h> -#include <unistd.h> - -#include "facebook/log.h" - - -typedef struct { - gpio_st m_mdc; - gpio_st m_mdio; -} mdio_context_st; - -/* - * 32b preamble, 2b start of frame, 2b operation code, - * 5b phy addr, 5b register addr, 2b turnaround, 16b data - */ -#define N_BITS (32 + 2 + 2 + 5 + 5 + 2 + 16) -#define N_BYTES (N_BITS + 7 / 8) - -#define START_OF_FRAME 0x1 -#define OP_READ 0x2 -#define OP_WRITE 0x1 -#define TURNAROUND 0x2 /* TA for write, for read, phy sends out TA */ - -void usage() -{ - fprintf(stderr, - "Usage:\n" - "mdio-bb: -c <GPIO for MDC> [-C <HIGH|low>]\n" - " -d <GPIO for MDIO> [-O <rising|FALLING>]\n" - " [-I <RISING|falling>] [-p] [-b]\n" - " <read|write> <phy address> <register address>\n" - " [value to write]\n"); -} - -bitbang_pin_value_en mdio_pin_f( - bitbang_pin_type_en pin, bitbang_pin_value_en value, void *context) -{ - mdio_context_st *ctx = (mdio_context_st *)context; - gpio_st *gpio; - bitbang_pin_value_en res; - - switch (pin) { - case BITBANG_CLK_PIN: - gpio = &ctx->m_mdc; - break; - case BITBANG_DATA_IN: - case BITBANG_DATA_OUT: - gpio = &ctx->m_mdio; - break; - } - if (pin == BITBANG_DATA_IN) { - res = gpio_read(gpio) ? BITBANG_PIN_HIGH : BITBANG_PIN_LOW; - } else { - res = value; - gpio_write(gpio, ((res == BITBANG_PIN_HIGH) - ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW)); - } - return res; -} - -int main(int argc, char* const argv[]) -{ - int opt; - int mdc = -1, mdio = -1; - bitbang_pin_value_en mdc_start = BITBANG_PIN_HIGH; - bitbang_clk_edge_en out_edge = BITBANG_CLK_EDGE_FALLING; - bitbang_clk_edge_en in_edge = BITBANG_CLK_EDGE_RISING; - int is_write; - uint32_t phy_addr; - uint32_t reg_addr; - uint32_t data; /* data to write/read*/ - uint8_t buf[N_BYTES]; - uint8_t *buf_p; - mdio_context_st ctx; - bitbang_init_st init; - bitbang_handle_st *hdl = NULL; - bitbang_io_st io; - int n_bits; - int i; - int rc = 0; - int preamble = 0; - int binary = 0; - - while ((opt = getopt(argc, argv, "bc:C:d:D:p")) != -1) { - switch (opt) { - case 'b': - binary = 1; - break; - case 'c': - mdc = atoi(optarg); - break; - case 'C': - if (!strcasecmp(optarg, "high")) { - mdc_start = BITBANG_PIN_HIGH; - } else if (!strcasecmp(optarg, "low")) { - mdc_start = BITBANG_PIN_LOW; - } else { - usage(); - exit(-1); - } - break; - case 'd': - mdio = atoi(optarg); - break; - case 'I': - if (!strcasecmp(optarg, "rising")) { - in_edge = BITBANG_CLK_EDGE_RISING; - } if (!strcasecmp(optarg, "falling")) { - in_edge = BITBANG_CLK_EDGE_FALLING; - } else { - usage(); - exit(-1); - } - break; - case 'O': - if (!strcasecmp(optarg, "rising")) { - out_edge = BITBANG_CLK_EDGE_RISING; - } if (!strcasecmp(optarg, "falling")) { - out_edge = BITBANG_CLK_EDGE_FALLING; - } else { - usage(); - exit(-1); - } - break; - case 'p': - preamble = 1; - break; - default: - usage(); - exit(-1); - } - } - - if (mdc < 0 || mdio < 0) { - usage(); - exit(-1); - } - - if (optind + 2 >= argc) { - usage(); - exit(-1); - } - - /* read or write */ - if (!strcasecmp(argv[optind], "read")) { - is_write = 0; - } else if (!strcasecmp(argv[optind], "write")) { - is_write = 1; - } else { - usage(); - exit(-1); - } - - /* phy address, 5 bits only, so must be <= 0x1f */ - phy_addr = strtoul(argv[optind + 1], NULL, 0); - if (phy_addr > 0x1f) { - usage(); - exit(-1); - } - - /* register address, 5 bits only, so must be <= 0x1f */ - reg_addr = strtoul(argv[optind + 2], NULL, 0); - if (reg_addr > 0x1f) { - usage(); - exit(-1); - } - - /* data */ - if (is_write) { - if ((!binary && (optind + 4 != argc)) || - (binary && (optind + 3 != argc))) { - usage(); - exit(-1); - } - if (binary) { - uint16_t temp = 0; - if (fread(&temp, sizeof(temp), 1, stdin) != 1) { - usage(); - exit(-1); - } - data = htons(temp); - } else { - data = strtoul(argv[optind + 3], NULL, 0); - } - if (data > 0xFFFF) { - usage(); - exit(-1); - } - } else { - if ((!binary && (optind + 3 != argc)) || - (binary && (optind + 2 != argc))) { - usage(); - exit(-1); - } - } - - /* open all gpio */ - memset(&ctx, sizeof(ctx), 0); - gpio_init_default(&ctx.m_mdc); - gpio_init_default(&ctx.m_mdio); - if (gpio_open(&ctx.m_mdc, mdc) || gpio_open(&ctx.m_mdio, mdio)) { - goto out; - } - - if (gpio_change_direction(&ctx.m_mdc, GPIO_DIRECTION_OUT) - || gpio_change_direction(&ctx.m_mdio, GPIO_DIRECTION_OUT)) { - goto out; - } - - bitbang_init_default(&init); - init.bbi_clk_start = mdc_start; - init.bbi_data_out = out_edge; - init.bbi_data_in = in_edge; - init.bbi_freq = 1000 * 1000; /* 1M Hz */ - init.bbi_pin_f = mdio_pin_f; - init.bbi_context = &ctx; - hdl = bitbang_open(&init); - if (!hdl) { - goto out; - } - - if (is_write) { - buf[0] = (data >> 8) & 0xFF; - buf[1] = data & 0xFF; - io.bbio_out_bits = 16; - io.bbio_dout = buf; - io.bbio_in_bits = 0; - io.bbio_din = NULL; - } else { - io.bbio_in_bits = 16; - io.bbio_din = buf; - io.bbio_out_bits = 0; - io.bbio_dout = NULL; - } - - /* preamble, 32b */ - buf_p = buf; - n_bits = 0; - if (preamble) { - /* 32 bit of 1 for preamble */ - for (i = 0; i < 4; i++) { - *buf_p++ = 0xFF; - } - n_bits += 32; - } - - /* - * MDIO transaction header is: - * 2b START, 2b OPER CODE, 5b PHY ADDR, 5b register addr, 2b TURNROUND - */ - *buf_p++ = (START_OF_FRAME << 6) | (((is_write) ? OP_WRITE : OP_READ) << 4) - | ((phy_addr >> 1) & 0xF); - *buf_p++ = ((phy_addr & 0x1) << 7) | ((reg_addr & 0x1F) << 2) | TURNAROUND; - if (is_write) { - *buf_p++ = (data >> 8) & 0xFF; - *buf_p++ = data & 0xFF; - /* total # of bits is transaction header + 2 bytes to write */ - n_bits += 2 + 2 + 5 + 5 + 2 + 16; - } else { - /* for read, master does not send TR, so, n_bits should not include TR */ - n_bits += 2 + 2 + 5 + 5; - } - - memset(&io, sizeof(io), 0); - io.bbio_out_bits = n_bits; - io.bbio_dout = buf; - io.bbio_in_bits = 0; - io.bbio_din = NULL; - - rc = bitbang_io(hdl, &io); - if (rc != 0) { - goto out; - } - - /* for read, need to do another io for (2b TR + 16b data) reading */ - if (!is_write) { - /* first, change the MDIO to input */ - gpio_change_direction(&ctx.m_mdio, GPIO_DIRECTION_IN); - /* then, run the clock for read */ - memset(&io, sizeof(io), 0); - io.bbio_out_bits = 0; - io.bbio_dout = NULL;; - io.bbio_in_bits = 18; - io.bbio_din = buf; - - rc = bitbang_io(hdl, &io); - if (rc != 0) { - goto out; - } - - data = ((buf[0] << 2) | (buf[1] >> 6)) & 0xFF; - data <<= 8; - data |= ((buf[1] << 2) | (buf[2] >> 6)) & 0xFF; - } - - if (binary) { - if (!is_write) { - uint16_t temp = ntohs(data); - fwrite(&temp, sizeof(temp), 1, stdout); - } - } else { - printf("%s: 0x%02x\n", (is_write) ? "Wrote" : "Read", data); - } - - out: - if (hdl) { - bitbang_close(hdl); - } - gpio_close(&ctx.m_mdc); - gpio_close(&ctx.m_mdio); - - return 0; -} diff --git a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/spi_bb.c b/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/spi_bb.c deleted file mode 100644 index ce366a5..0000000 --- a/meta-facebook/meta-wedge/recipes-wedge/bitbang/files/src/spi_bb.c +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright 2014-present Facebook. All Rights Reserved. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -//#define DEBUG -//#define VERBOSE - -#include "bitbang.h" -#include "gpio.h" - -#include <stdlib.h> -#include <unistd.h> - -#include "facebook/log.h" - -void usage() -{ - fprintf(stderr, - "Usage:\n" - "spi-bb: -s <GPIO for CS> [-S <HIGH|low>]\n" - " -c <GPIO for CLK> [-C <HIGH|low>]\n" - " -o <GPIO for MOSI> [-O <rising|FALLING>]\n" - " -i <GPIO for MISO> [-I <RISING|falling>]\n" - " [-b]\n" - " < [-r <number of bits to read>]\n" - " [-w <number of bits to write> <byte 1> [... byte N]>\n\n" - "Note: If both '-r' and '-w' are provided, 'write' will be performed\n" - " before 'read'.\n"); -} - -typedef struct { - gpio_st sc_clk; - gpio_st sc_mosi; - gpio_st sc_miso; -} spi_context_st; - -bitbang_pin_value_en spi_pin_f( - bitbang_pin_type_en pin, bitbang_pin_value_en value, void *context) -{ - spi_context_st *ctx = (spi_context_st *)context; - gpio_st *gpio; - bitbang_pin_value_en res; - - switch (pin) { - case BITBANG_CLK_PIN: - gpio = &ctx->sc_clk; - break; - case BITBANG_DATA_IN: - gpio = &ctx->sc_miso; - break; - case BITBANG_DATA_OUT: - gpio = &ctx->sc_mosi; - break; - } - if (pin == BITBANG_DATA_IN) { - res = gpio_read(gpio) ? BITBANG_PIN_HIGH : BITBANG_PIN_LOW; - } else { - res = value; - gpio_write(gpio, ((res == BITBANG_PIN_HIGH) - ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW)); - } - return res; -} - -int main(int argc, char * const argv[]) -{ - bitbang_init_st init; - bitbang_handle_st *hdl = NULL; - int cs = -1, clk = -1, in = -1, out = -1; - gpio_st cs_gpio; - int opt; - int is_write = 0; - int is_read = 0; - int read_bits = 0; - int write_bits = 0; - int read_bytes = 0; - int write_bytes = 0; - int i; - uint8_t *read_buf = NULL;; - uint8_t *write_buf = NULL;; - bitbang_clk_edge_en dout_edge = BITBANG_CLK_EDGE_FALLING; - bitbang_clk_edge_en din_edge = BITBANG_CLK_EDGE_RISING; - bitbang_pin_value_en clk_start = BITBANG_PIN_HIGH; - bitbang_pin_value_en cs_value = BITBANG_PIN_HIGH; - spi_context_st ctx; - bitbang_io_st io; - int rc = 0; - int binary = 0; - - memset(&ctx, sizeof(ctx), 0); - gpio_init_default(&ctx.sc_clk); - gpio_init_default(&ctx.sc_mosi); - gpio_init_default(&ctx.sc_miso); - gpio_init_default(&cs_gpio); - - while ((opt = getopt(argc, argv, "bs:S:c:C:o:O:i:I:w:r:")) != -1) { - switch (opt) { - case 'b': - binary = 1; - break; - case 's': - cs = atoi(optarg); - break; - case 'S': - if (!strcmp(optarg, "high")) { - cs_value = BITBANG_PIN_HIGH; - } else if (!strcmp(optarg, "low")) { - cs_value = BITBANG_PIN_LOW; - } else { - usage(); - exit(-1); - } - break; - case 'c': - clk = atoi(optarg); - break; - case 'C': - if (!strcasecmp(optarg, "high")) { - clk_start = BITBANG_PIN_HIGH; - } else if (!strcasecmp(optarg, "low")) { - clk_start = BITBANG_PIN_LOW; - } else { - usage(); - exit(-1); - } - break; - case 'o': - out = atoi(optarg); - break; - case 'O': - if (!strcasecmp(optarg, "rising")) { - dout_edge = BITBANG_CLK_EDGE_RISING; - } else if (!strcasecmp(optarg, "falling")) { - dout_edge = BITBANG_CLK_EDGE_FALLING; - } else { - usage(); - exit(-1); - } - break; - case 'i': - in = atoi(optarg); - break; - case 'I': - if (!strcasecmp(optarg, "rising")) { - din_edge = BITBANG_CLK_EDGE_RISING; - } else if (!strcasecmp(optarg, "falling")) { - din_edge = BITBANG_CLK_EDGE_FALLING; - } else { - usage(); - exit(-1); - } - break; - case 'w': - is_write = 1; - write_bits = atoi(optarg); - if (write_bits <= 0) { - usage(); - exit(-1); - } - break; - case 'r': - is_read = 1; - read_bits = atoi(optarg); - if (read_bits <= 0) { - usage(); - exit(-1); - } - break; - default: - usage(); - exit(-1); - } - } - - if (clk < 0 || in < 0 || out < 0) { - usage(); - exit(-1); - } - - if ((!is_read && !is_write)) { - usage(); - exit(-1); - } - - write_bytes = ((write_bits + 7) / 8); - if (write_bytes) { - write_buf = calloc(write_bytes, sizeof(uint8_t)); - if (!write_buf) { - goto out; - } - if (binary) { - size_t written_bytes; - written_bytes = fread(write_buf, sizeof(*write_buf), write_bytes, stdin); - if( written_bytes != write_bytes ) { - goto out; - } - } else { - for (i = 0; i < write_bytes && i + optind < argc; i++) { - write_buf[i] = strtoul(argv[i + optind], NULL, 0); - } - } - } - - read_bytes = ((read_bits + 7) / 8); - if (read_bytes) { - read_buf = calloc(read_bytes, sizeof(uint8_t)); - if (!read_buf) { - goto out; - } - } - - if (gpio_open(&ctx.sc_clk, clk) || gpio_open(&ctx.sc_miso, in) - || gpio_open(&ctx.sc_mosi, out)) { - goto out; - } - - /* change GPIO directions, only MISO is input, all others are output */ - if (gpio_change_direction(&ctx.sc_clk, GPIO_DIRECTION_OUT) - || gpio_change_direction(&ctx.sc_miso, GPIO_DIRECTION_IN) - || gpio_change_direction(&ctx.sc_mosi, GPIO_DIRECTION_OUT)) { - goto out; - } - - if (cs != -1) { - if (gpio_open(&cs_gpio, cs)) { - goto out; - } - if (gpio_change_direction(&cs_gpio, GPIO_DIRECTION_OUT)) { - goto out; - } - } - - bitbang_init_default(&init); - init.bbi_clk_start = clk_start; - init.bbi_data_out = dout_edge; - init.bbi_data_in = din_edge; - init.bbi_freq = 1000 * 1000; /* 1M Hz */ - init.bbi_pin_f = spi_pin_f; - init.bbi_context = &ctx; - - hdl = bitbang_open(&init); - if (!hdl) { - goto out; - } - - if (cs != -1) { - /* have chip select */ - gpio_write(&cs_gpio, ((cs_value == BITBANG_PIN_HIGH) - ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW)); - } - - memset(&io, sizeof(io), 0); - io.bbio_in_bits = read_bits; - io.bbio_din = read_buf; - io.bbio_out_bits = write_bits; - io.bbio_dout = write_buf; - - rc = bitbang_io(hdl, &io); - if (rc != 0) { - goto out; - } - - if (binary) { - fwrite(read_buf, sizeof(*read_buf), read_bytes, stdout); - } else { - if (write_bits) { - printf("Wrote %u bits:", write_bits); - for (i = 0; i < write_bytes; i++) { - printf(" %02x", write_buf[i]); - } - printf("\n"); - } - - if (read_bits) { - printf("Read %u bits:", read_bits); - for (i = 0; i < read_bytes; i++) { - printf(" %02x", read_buf[i]); - } - printf("\n"); - } - } - - out: - if (hdl) { - bitbang_close(hdl); - } - gpio_close(&ctx.sc_clk); - gpio_close(&ctx.sc_miso); - gpio_close(&ctx.sc_mosi); - if (cs != -1) { - /* reset have chip select */ - gpio_write(&cs_gpio, ((cs_value == BITBANG_PIN_HIGH) - ? GPIO_VALUE_LOW : GPIO_VALUE_HIGH)); - gpio_close(&cs_gpio); - } - - if (read_buf) { - free(read_buf); - } - if (write_buf) { - free(write_buf); - } - return rc; -} |