/*
 * This file is part of the flashrom project.
 *
 * Copyright (C) 2018 Linaro Limited
 *
 * 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.
 */

/*
 * Bit bang driver for the 96Boards Developerbox (a.k.a. Synquacer E-series)
 * on-board debug UART.  The Developerbox implements its debug UART using a
 * CP2102N, a USB to UART bridge which also provides four GPIO pins. On
 * Developerbox these can be hooked up to the onboard SPI NOR FLASH and used
 * for emergency de-brick without any additional hardware programmer. Bit
 * banging over USB is extremely slow compared to a proper SPI programmer so
 * this is only practical as a de-brick tool.
 *
 * Schematic is available here:
 * https://www.96boards.org/documentation/enterprise/developerbox/hardware-docs/
 *
 * To prepare a Developerbox for programming via the debug UART, DSW4 must be
 * changed from the default 00000000 to 10001000 (i.e. DSW4-1 and DSW4-5
 * should be turned on).
 */

#include "platform.h"

#include <stdlib.h>
#include <libusb.h>
#include "programmer.h"
#include "spi.h"

/* Bit positions for each pin. */
#define DEVELOPERBOX_SPI_SCK	0
#define DEVELOPERBOX_SPI_CS	1
#define DEVELOPERBOX_SPI_MISO	2
#define DEVELOPERBOX_SPI_MOSI	3

/* Config request types */
#define REQTYPE_HOST_TO_DEVICE  0x40
#define REQTYPE_DEVICE_TO_HOST  0xc0

/* Config request codes */
#define CP210X_VENDOR_SPECIFIC  0xff

/* CP210X_VENDOR_SPECIFIC */
#define CP210X_WRITE_LATCH      0x37e1
#define CP210X_READ_LATCH       0x00c2

static const struct dev_entry devs_developerbox_spi[] = {
	{0x10c4, 0xea60, OK, "Silicon Labs", "CP2102N USB to UART Bridge Controller"},
	{0},
};

static struct libusb_context *usb_ctx;
static libusb_device_handle *cp210x_handle;

static int cp210x_gpio_get(void)
{
	int res;
	uint8_t gpio;

	res = libusb_control_transfer(cp210x_handle, REQTYPE_DEVICE_TO_HOST,
			CP210X_VENDOR_SPECIFIC, CP210X_READ_LATCH,
			0, &gpio, 1, 0);
	if (res < 0) {
		msg_perr("Failed to read GPIO pins (%s)\n", libusb_error_name(res));
		return 0;
	}

	return gpio;
}

static void cp210x_gpio_set(uint8_t val, uint8_t mask)
{
	int res;
	uint16_t gpio;

	gpio = ((val & 0xf) << 8) | (mask & 0xf);

	/* Set relay state on the card */
	res = libusb_control_transfer(cp210x_handle, REQTYPE_HOST_TO_DEVICE,
			CP210X_VENDOR_SPECIFIC, CP210X_WRITE_LATCH,
			gpio, NULL, 0, 0);
	if (res < 0)
		msg_perr("Failed to read GPIO pins (%s)\n", libusb_error_name(res));
}

static void cp210x_bitbang_set_cs(int val)
{
	cp210x_gpio_set(val << DEVELOPERBOX_SPI_CS, 1 << DEVELOPERBOX_SPI_CS);
}

static void cp210x_bitbang_set_sck(int val)
{
	cp210x_gpio_set(val << DEVELOPERBOX_SPI_SCK, 1 << DEVELOPERBOX_SPI_SCK);
}

static void cp210x_bitbang_set_mosi(int val)
{
	cp210x_gpio_set(val << DEVELOPERBOX_SPI_MOSI, 1 << DEVELOPERBOX_SPI_MOSI);
}

static int cp210x_bitbang_get_miso(void)
{
	return !!(cp210x_gpio_get() & (1 << DEVELOPERBOX_SPI_MISO));
}

static void cp210x_bitbang_set_sck_set_mosi(int sck, int mosi)
{
	cp210x_gpio_set(sck << DEVELOPERBOX_SPI_SCK | mosi << DEVELOPERBOX_SPI_MOSI,
			  1 << DEVELOPERBOX_SPI_SCK |    1 << DEVELOPERBOX_SPI_MOSI);
}

static const struct bitbang_spi_master bitbang_spi_master_cp210x = {
	.set_cs			= cp210x_bitbang_set_cs,
	.set_sck		= cp210x_bitbang_set_sck,
	.set_mosi		= cp210x_bitbang_set_mosi,
	.get_miso		= cp210x_bitbang_get_miso,
	.set_sck_set_mosi	= cp210x_bitbang_set_sck_set_mosi,
};

static int developerbox_spi_shutdown(void *data)
{
	libusb_close(cp210x_handle);
	libusb_exit(usb_ctx);

	return 0;
}

static int developerbox_spi_init(void)
{
	libusb_init(&usb_ctx);
	if (!usb_ctx) {
		msg_perr("Could not initialize libusb!\n");
		return 1;
	}

	char *serialno = extract_programmer_param("serial");
	if (serialno)
		msg_pdbg("Looking for serial number commencing %s\n", serialno);
	cp210x_handle = usb_dev_get_by_vid_pid_serial(usb_ctx,
			devs_developerbox_spi[0].vendor_id, devs_developerbox_spi[0].device_id, serialno);
	free(serialno);
	if (!cp210x_handle) {
		msg_perr("Could not find a Developerbox programmer on USB.\n");
		goto err_exit;
	}

	if (register_shutdown(developerbox_spi_shutdown, NULL))
		goto err_exit;

	if (register_spi_bitbang_master(&bitbang_spi_master_cp210x))
		goto err_exit;

	return 0;

err_exit:
	libusb_exit(usb_ctx);
	return 1;
}

const struct programmer_entry programmer_developerbox = {
	.name			= "developerbox",
	.type			= USB,
	.devs.dev		= devs_developerbox_spi,
	.init			= developerbox_spi_init,
	.map_flash_region	= fallback_map,
	.unmap_flash_region	= fallback_unmap,
	.delay			= internal_delay,
};
