/*
 * Copyright (c) 2016 Intel Corporation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <device.h>
#include <drivers/ioapic.h>
#include <init.h>
#include <nanokernel.h>
#include <spi.h>
#include <gpio.h>

#include "qm_scss.h"
#include "qm_spi.h"

struct pending_transfer {
	struct device *dev;
	qm_spi_async_transfer_t xfer;
	int counter;
};

static struct pending_transfer pending_transfers[QM_SPI_NUM];

struct spi_qmsi_config {
	qm_spi_t spi;
	char *cs_port;
	uint32_t cs_pin;
};

struct spi_qmsi_runtime {
	struct device *gpio_cs;
	device_sync_call_t sync;
	qm_spi_config_t cfg;
	qm_rc_t rc;
	bool loopback;
};

static inline qm_spi_bmode_t config_to_bmode(uint8_t mode)
{
	switch (mode) {
	case SPI_MODE_CPHA:
		return QM_SPI_BMODE_1;
	case SPI_MODE_CPOL:
		return QM_SPI_BMODE_2;
	case SPI_MODE_CPOL | SPI_MODE_CPHA:
		return QM_SPI_BMODE_3;
	default:
		return QM_SPI_BMODE_0;
	}
}

static void spi_control_cs(struct device *dev, bool active)
{
	struct spi_qmsi_runtime *context = dev->driver_data;
	struct spi_qmsi_config *config = dev->config->config_info;
	struct device *gpio = context->gpio_cs;

	if (!gpio)
		return;

	gpio_pin_write(gpio, config->cs_pin, !active);
}

static int spi_qmsi_configure(struct device *dev,
				struct spi_config *config)
{
	struct spi_qmsi_runtime *context = dev->driver_data;
	qm_spi_config_t *cfg = &context->cfg;

	cfg->frame_size = SPI_WORD_SIZE_GET(config->config) - 1;
	cfg->bus_mode = config_to_bmode(SPI_MODE(config->config));
	/* As loopback is implemented inside the controller,
	 * the bus mode doesn't matter.
	 */
	context->loopback = SPI_MODE(config->config) & SPI_MODE_LOOP;
	cfg->clk_divider = config->max_sys_freq;

	/* Will set the configuration before the transfer starts */
	return DEV_OK;
}

static void pending_transfer_complete(uint32_t id, qm_rc_t rc)
{
	struct pending_transfer *pending = &pending_transfers[id];
	struct device *dev = pending->dev;
	struct spi_qmsi_runtime *context;
	qm_spi_config_t *cfg;

	if (!dev)
		return;

	context = dev->driver_data;
	cfg = &context->cfg;

	pending->counter++;

	/*
	 * When it is TX/RX transfer this function will be called twice.
	*/
	if (cfg->transfer_mode == QM_SPI_TMOD_TX_RX && pending->counter == 1)
		return;

	spi_control_cs(dev, false);

	pending->dev = NULL;
	pending->counter = 0;
	context->rc = rc;
	device_sync_call_complete(&context->sync);
}

static void spi_qmsi_tx_callback(uint32_t id, uint32_t len)
{
	pending_transfer_complete(id, QM_RC_OK);
}

static void spi_qmsi_rx_callback(uint32_t id, uint32_t len)
{
	pending_transfer_complete(id, QM_RC_OK);
}

static void spi_qmsi_err_callback(uint32_t id, qm_rc_t err)
{
	pending_transfer_complete(id, err);
}

static int spi_qmsi_slave_select(struct device *dev, uint32_t slave)
{
	struct spi_qmsi_config *spi_config = dev->config->config_info;
	qm_spi_t spi = spi_config->spi;

	return qm_spi_slave_select(spi, 1 << (slave - 1)) ? DEV_FAIL : DEV_OK;
}

static inline uint8_t frame_size_to_dfs(qm_spi_frame_size_t frame_size)
{
	if (frame_size <= QM_SPI_FRAME_SIZE_8_BIT)
		return 1;
	if (frame_size <= QM_SPI_FRAME_SIZE_16_BIT)
		return 2;
	if (frame_size <= QM_SPI_FRAME_SIZE_32_BIT)
		return 4;

	/* This should never happen, it will crash later on. */
	return 0;
}

static int spi_qmsi_transceive(struct device *dev,
			     uint8_t *tx_buf, uint32_t tx_buf_len,
			     uint8_t *rx_buf, uint32_t rx_buf_len)
{
	struct spi_qmsi_config *spi_config = dev->config->config_info;
	qm_spi_t spi = spi_config->spi;
	struct spi_qmsi_runtime *context = dev->driver_data;
	qm_spi_config_t *cfg = &context->cfg;
	uint8_t dfs = frame_size_to_dfs(cfg->frame_size);
	qm_spi_async_transfer_t *xfer;
	qm_rc_t rc;

	if (pending_transfers[spi].dev)
		return DEV_USED;

	pending_transfers[spi].dev = dev;
	xfer = &pending_transfers[spi].xfer;

	xfer->rx = rx_buf;
	xfer->rx_len = rx_buf_len / dfs;
	xfer->tx = tx_buf;
	xfer->tx_len = tx_buf_len / dfs;
	xfer->id = spi;
	xfer->tx_callback = spi_qmsi_tx_callback;
	xfer->rx_callback = spi_qmsi_rx_callback;
	xfer->err_callback = spi_qmsi_err_callback;

	if (tx_buf_len == 0)
		cfg->transfer_mode = QM_SPI_TMOD_RX;
	else if (rx_buf_len == 0)
		cfg->transfer_mode = QM_SPI_TMOD_TX;
	else {
		/* FIXME: QMSI expects rx_buf_len and tx_buf_len to
		 * have the same size.
		 */
		cfg->transfer_mode = QM_SPI_TMOD_TX_RX;
	}

	if (context->loopback)
		QM_SPI[spi]->ctrlr0 |= BIT(11);

	rc = qm_spi_set_config(spi, cfg);
	if (rc != QM_RC_OK)
		return DEV_INVALID_CONF;

	spi_control_cs(dev, true);

	rc = qm_spi_irq_transfer(spi, xfer);
	if (rc != QM_RC_OK) {
		spi_control_cs(dev, false);
		return DEV_FAIL;
	}

	device_sync_call_wait(&context->sync);

	return context->rc ? DEV_FAIL : DEV_OK;
}

static int spi_qmsi_suspend(struct device *dev)
{
	/* FIXME */
	return 0;
}

static int spi_qmsi_resume(struct device *dev)
{
	/* FIXME */
	return 0;
}

static struct spi_driver_api spi_qmsi_api = {
	.configure = spi_qmsi_configure,
	.slave_select = spi_qmsi_slave_select,
	.transceive = spi_qmsi_transceive,
	.suspend = spi_qmsi_suspend,
	.resume = spi_qmsi_resume,
};

static struct device *gpio_cs_init(struct spi_qmsi_config *config)
{
	struct device *gpio;

	if (!config->cs_port)
		return NULL;

	gpio = device_get_binding(config->cs_port);
	if (!gpio)
		return NULL;

	gpio_pin_configure(gpio, config->cs_pin, GPIO_DIR_OUT);
	gpio_pin_write(gpio, config->cs_pin, 1);

	return gpio;
}

static int spi_qmsi_init(struct device *dev)
{
	struct spi_qmsi_config *spi_config = dev->config->config_info;
	struct spi_qmsi_runtime *context = dev->driver_data;

	dev->driver_api = &spi_qmsi_api;

	switch (spi_config->spi) {
	case QM_SPI_MST_0:
		IRQ_CONNECT(CONFIG_SPI_QMSI_PORT_0_IRQ,
			    CONFIG_SPI_QMSI_PORT_0_PRI, qm_spi_master_0_isr,
			    0, IOAPIC_LEVEL | IOAPIC_HIGH);
		irq_enable(CONFIG_SPI_QMSI_PORT_0_IRQ);
		clk_periph_enable(CLK_PERIPH_CLK | CLK_PERIPH_SPI_M0_REGISTER);
		QM_SCSS_INT->int_spi_mst_0_mask &= ~BIT(0);
		break;
	case QM_SPI_MST_1:
		IRQ_CONNECT(CONFIG_SPI_QMSI_PORT_1_IRQ,
			    CONFIG_SPI_QMSI_PORT_1_PRI, qm_spi_master_1_isr,
			    0, IOAPIC_LEVEL | IOAPIC_HIGH);
		irq_enable(CONFIG_SPI_QMSI_PORT_1_IRQ);
		clk_periph_enable(CLK_PERIPH_CLK | CLK_PERIPH_SPI_M1_REGISTER);
		QM_SCSS_INT->int_spi_mst_1_mask &= ~BIT(0);
		break;
	default:
		return DEV_FAIL;
	}

	context->gpio_cs = gpio_cs_init(spi_config);

	device_sync_call_init(&context->sync);

	return DEV_OK;
}

#ifdef CONFIG_SPI_QMSI_PORT_0
static struct spi_qmsi_config spi_qmsi_mst_0_config = {
	.spi = QM_SPI_MST_0,
#ifdef CONFIG_SPI_QMSI_CS_GPIO
	.cs_port = CONFIG_SPI_QMSI_PORT_0_CS_GPIO_PORT,
	.cs_pin = CONFIG_SPI_QMSI_PORT_0_CS_GPIO_PIN,
#endif
};

static struct spi_qmsi_runtime spi_qmsi_mst_0_runtime;

DEVICE_INIT(spi_master_0, CONFIG_SPI_QMSI_PORT_0_DRV_NAME,
	    spi_qmsi_init, &spi_qmsi_mst_0_runtime, &spi_qmsi_mst_0_config,
	    SECONDARY, CONFIG_SPI_QMSI_INIT_PRIORITY);


#endif /* CONFIG_SPI_QMSI_PORT_0 */
#ifdef CONFIG_SPI_QMSI_PORT_1

static struct spi_qmsi_config spi_qmsi_mst_1_config = {
	.spi = QM_SPI_MST_1,
#ifdef CONFIG_SPI_QMSI_CS_GPIO
	.cs_port = CONFIG_SPI_QMSI_PORT_1_CS_GPIO_PORT,
	.cs_pin = CONFIG_SPI_QMSI_PORT_1_CS_GPIO_PIN,
#endif
};

static struct spi_qmsi_runtime spi_qmsi_mst_1_runtime;

DEVICE_INIT(spi_master_1, CONFIG_SPI_QMSI_PORT_1_DRV_NAME,
	    spi_qmsi_init, &spi_qmsi_mst_1_runtime, &spi_qmsi_mst_1_config,
	    SECONDARY, CONFIG_SPI_QMSI_INIT_PRIORITY);

#endif /* CONFIG_SPI_QMSI_PORT_1 */
