/*
 * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * 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 <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>

#include <linux/mmc/core.h>
#include <linux/mmc/card.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>

#include "gdm_sdio.h"
#include "gdm_wimax.h"
#include "sdio_boot.h"
#include "hci.h"

#define TYPE_A_HEADER_SIZE	4
#define TYPE_A_LOOKAHEAD_SIZE	16

#define MAX_NR_RX_BUF	4

#define SDU_TX_BUF_SIZE	2048
#define TX_BUF_SIZE	2048
#define TX_CHUNK_SIZE	(2048 - TYPE_A_HEADER_SIZE)
#define RX_BUF_SIZE	(25*1024)

#define TX_HZ		2000
#define TX_INTERVAL	(1000000/TX_HZ)

static int init_sdio(struct sdiowm_dev *sdev);
static void release_sdio(struct sdiowm_dev *sdev);

static struct sdio_tx *alloc_tx_struct(struct tx_cxt *tx)
{
	struct sdio_tx *t = kzalloc(sizeof(*t), GFP_ATOMIC);

	if (!t)
		return NULL;

	t->buf = kmalloc(TX_BUF_SIZE, GFP_ATOMIC);
	if (!t->buf) {
		kfree(t);
		return NULL;
	}

	t->tx_cxt = tx;

	return t;
}

static void free_tx_struct(struct sdio_tx *t)
{
	if (t) {
		kfree(t->buf);
		kfree(t);
	}
}

static struct sdio_rx *alloc_rx_struct(struct rx_cxt *rx)
{
	struct sdio_rx *r = kzalloc(sizeof(*r), GFP_ATOMIC);

	if (r)
		r->rx_cxt = rx;

	return r;
}

static void free_rx_struct(struct sdio_rx *r)
{
	kfree(r);
}

/* Before this function is called, spin lock should be locked. */
static struct sdio_tx *get_tx_struct(struct tx_cxt *tx, int *no_spc)
{
	struct sdio_tx *t;

	if (list_empty(&tx->free_list))
		return NULL;

	t = list_entry(tx->free_list.prev, struct sdio_tx, list);
	list_del(&t->list);

	*no_spc = list_empty(&tx->free_list) ? 1 : 0;

	return t;
}

/* Before this function is called, spin lock should be locked. */
static void put_tx_struct(struct tx_cxt *tx, struct sdio_tx *t)
{
	list_add_tail(&t->list, &tx->free_list);
}

/* Before this function is called, spin lock should be locked. */
static struct sdio_rx *get_rx_struct(struct rx_cxt *rx)
{
	struct sdio_rx *r;

	if (list_empty(&rx->free_list))
		return NULL;

	r = list_entry(rx->free_list.prev, struct sdio_rx, list);
	list_del(&r->list);

	return r;
}

/* Before this function is called, spin lock should be locked. */
static void put_rx_struct(struct rx_cxt *rx, struct sdio_rx *r)
{
	list_add_tail(&r->list, &rx->free_list);
}

static int init_sdio(struct sdiowm_dev *sdev)
{
	int ret = 0, i;
	struct tx_cxt *tx = &sdev->tx;
	struct rx_cxt *rx = &sdev->rx;
	struct sdio_tx *t;
	struct sdio_rx *r;

	INIT_LIST_HEAD(&tx->free_list);
	INIT_LIST_HEAD(&tx->sdu_list);
	INIT_LIST_HEAD(&tx->hci_list);

	spin_lock_init(&tx->lock);

	tx->sdu_buf = kmalloc(SDU_TX_BUF_SIZE, GFP_KERNEL);
	if (tx->sdu_buf == NULL)
		goto fail;

	for (i = 0; i < MAX_NR_SDU_BUF; i++) {
		t = alloc_tx_struct(tx);
		if (t == NULL) {
			ret = -ENOMEM;
			goto fail;
		}
		list_add(&t->list, &tx->free_list);
	}

	INIT_LIST_HEAD(&rx->free_list);
	INIT_LIST_HEAD(&rx->req_list);

	spin_lock_init(&rx->lock);

	for (i = 0; i < MAX_NR_RX_BUF; i++) {
		r = alloc_rx_struct(rx);
		if (r == NULL) {
			ret = -ENOMEM;
			goto fail;
		}
		list_add(&r->list, &rx->free_list);
	}

	rx->rx_buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL);
	if (rx->rx_buf == NULL)
		goto fail;

	return 0;

fail:
	release_sdio(sdev);
	return ret;
}

static void release_sdio(struct sdiowm_dev *sdev)
{
	struct tx_cxt	*tx = &sdev->tx;
	struct rx_cxt	*rx = &sdev->rx;
	struct sdio_tx	*t, *t_next;
	struct sdio_rx	*r, *r_next;

	kfree(tx->sdu_buf);

	list_for_each_entry_safe(t, t_next, &tx->free_list, list) {
		list_del(&t->list);
		free_tx_struct(t);
	}

	list_for_each_entry_safe(t, t_next, &tx->sdu_list, list) {
		list_del(&t->list);
		free_tx_struct(t);
	}

	list_for_each_entry_safe(t, t_next, &tx->hci_list, list) {
		list_del(&t->list);
		free_tx_struct(t);
	}

	kfree(rx->rx_buf);

	list_for_each_entry_safe(r, r_next, &rx->free_list, list) {
		list_del(&r->list);
		free_rx_struct(r);
	}

	list_for_each_entry_safe(r, r_next, &rx->req_list, list) {
		list_del(&r->list);
		free_rx_struct(r);
	}
}

static void send_sdio_pkt(struct sdio_func *func, u8 *data, int len)
{
	int n, blocks, ret, remain;

	sdio_claim_host(func);

	blocks = len / func->cur_blksize;
	n = blocks * func->cur_blksize;
	if (blocks) {
		ret = sdio_memcpy_toio(func, 0, data, n);
		if (ret < 0) {
			if (ret != -ENOMEDIUM)
				dev_err(&func->dev,
					"gdmwms: %s error: ret = %d\n",
					__func__, ret);
			goto end_io;
		}
	}

	remain = len - n;
	remain = (remain + 3) & ~3;

	if (remain) {
		ret = sdio_memcpy_toio(func, 0, data + n, remain);
		if (ret < 0) {
			if (ret != -ENOMEDIUM)
				dev_err(&func->dev,
					"gdmwms: %s error: ret = %d\n",
					__func__, ret);
			goto end_io;
		}
	}

end_io:
	sdio_release_host(func);
}

static void send_sdu(struct sdio_func *func, struct tx_cxt *tx)
{
	struct list_head *l, *next;
	struct hci_s *hci;
	struct sdio_tx *t;
	int pos, len, i, estlen, aggr_num = 0, aggr_len;
	u8 *buf;
	unsigned long flags;

	spin_lock_irqsave(&tx->lock, flags);

	pos = TYPE_A_HEADER_SIZE + HCI_HEADER_SIZE;
	list_for_each_entry(t, &tx->sdu_list, list) {
		estlen = ((t->len + 3) & ~3) + 4;
		if ((pos + estlen) > SDU_TX_BUF_SIZE)
			break;

		aggr_num++;
		memcpy(tx->sdu_buf + pos, t->buf, t->len);
		memset(tx->sdu_buf + pos + t->len, 0, estlen - t->len);
		pos += estlen;
	}
	aggr_len = pos;

	hci = (struct hci_s *)(tx->sdu_buf + TYPE_A_HEADER_SIZE);
	hci->cmd_evt = H2B(WIMAX_TX_SDU_AGGR);
	hci->length = H2B(aggr_len - TYPE_A_HEADER_SIZE - HCI_HEADER_SIZE);

	spin_unlock_irqrestore(&tx->lock, flags);

	print_hex_dump_debug("sdio_send: ", DUMP_PREFIX_NONE, 16, 1,
			     tx->sdu_buf + TYPE_A_HEADER_SIZE,
			     aggr_len - TYPE_A_HEADER_SIZE, false);

	for (pos = TYPE_A_HEADER_SIZE; pos < aggr_len; pos += TX_CHUNK_SIZE) {
		len = aggr_len - pos;
		len = len > TX_CHUNK_SIZE ? TX_CHUNK_SIZE : len;
		buf = tx->sdu_buf + pos - TYPE_A_HEADER_SIZE;

		buf[0] = len & 0xff;
		buf[1] = (len >> 8) & 0xff;
		buf[2] = (len >> 16) & 0xff;
		buf[3] = (pos + len) >= aggr_len ? 0 : 1;
		send_sdio_pkt(func, buf, len + TYPE_A_HEADER_SIZE);
	}

	spin_lock_irqsave(&tx->lock, flags);

	for (l = tx->sdu_list.next, i = 0; i < aggr_num; i++, l = next) {
		next = l->next;
		t = list_entry(l, struct sdio_tx, list);
		if (t->callback)
			t->callback(t->cb_data);

		list_del(l);
		put_tx_struct(t->tx_cxt, t);
	}

	do_gettimeofday(&tx->sdu_stamp);
	spin_unlock_irqrestore(&tx->lock, flags);
}

static void send_hci(struct sdio_func *func, struct tx_cxt *tx,
		     struct sdio_tx *t)
{
	unsigned long flags;

	print_hex_dump_debug("sdio_send: ", DUMP_PREFIX_NONE, 16, 1,
			     t->buf + TYPE_A_HEADER_SIZE,
			     t->len - TYPE_A_HEADER_SIZE, false);
	send_sdio_pkt(func, t->buf, t->len);

	spin_lock_irqsave(&tx->lock, flags);
	if (t->callback)
		t->callback(t->cb_data);
	free_tx_struct(t);
	spin_unlock_irqrestore(&tx->lock, flags);
}

static void do_tx(struct work_struct *work)
{
	struct sdiowm_dev *sdev = container_of(work, struct sdiowm_dev, ws);
	struct sdio_func *func = sdev->func;
	struct tx_cxt *tx = &sdev->tx;
	struct sdio_tx *t = NULL;
	struct timeval now, *before;
	int is_sdu = 0;
	long diff;
	unsigned long flags;

	spin_lock_irqsave(&tx->lock, flags);
	if (!tx->can_send) {
		spin_unlock_irqrestore(&tx->lock, flags);
		return;
	}

	if (!list_empty(&tx->hci_list)) {
		t = list_entry(tx->hci_list.next, struct sdio_tx, list);
		list_del(&t->list);
		is_sdu = 0;
	} else if (!tx->stop_sdu_tx && !list_empty(&tx->sdu_list)) {
		do_gettimeofday(&now);
		before = &tx->sdu_stamp;

		diff = (now.tv_sec - before->tv_sec) * 1000000 +
			(now.tv_usec - before->tv_usec);
		if (diff >= 0 && diff < TX_INTERVAL) {
			schedule_work(&sdev->ws);
			spin_unlock_irqrestore(&tx->lock, flags);
			return;
		}
		is_sdu = 1;
	}

	if (!is_sdu && t == NULL) {
		spin_unlock_irqrestore(&tx->lock, flags);
		return;
	}

	tx->can_send = 0;

	spin_unlock_irqrestore(&tx->lock, flags);

	if (is_sdu)
		send_sdu(func, tx);
	else
		send_hci(func, tx, t);
}

static int gdm_sdio_send(void *priv_dev, void *data, int len,
			 void (*cb)(void *data), void *cb_data)
{
	struct sdiowm_dev *sdev = priv_dev;
	struct tx_cxt *tx = &sdev->tx;
	struct sdio_tx *t;
	u8 *pkt = data;
	int no_spc = 0;
	u16 cmd_evt;
	unsigned long flags;

	BUG_ON(len > TX_BUF_SIZE - TYPE_A_HEADER_SIZE);

	spin_lock_irqsave(&tx->lock, flags);

	cmd_evt = (pkt[0] << 8) | pkt[1];
	if (cmd_evt == WIMAX_TX_SDU) {
		t = get_tx_struct(tx, &no_spc);
		if (t == NULL) {
			/* This case must not happen. */
			spin_unlock_irqrestore(&tx->lock, flags);
			return -ENOSPC;
		}
		list_add_tail(&t->list, &tx->sdu_list);

		memcpy(t->buf, data, len);

		t->len = len;
		t->callback = cb;
		t->cb_data = cb_data;
	} else {
		t = alloc_tx_struct(tx);
		if (t == NULL) {
			spin_unlock_irqrestore(&tx->lock, flags);
			return -ENOMEM;
		}
		list_add_tail(&t->list, &tx->hci_list);

		t->buf[0] = len & 0xff;
		t->buf[1] = (len >> 8) & 0xff;
		t->buf[2] = (len >> 16) & 0xff;
		t->buf[3] = 2;
		memcpy(t->buf + TYPE_A_HEADER_SIZE, data, len);

		t->len = len + TYPE_A_HEADER_SIZE;
		t->callback = cb;
		t->cb_data = cb_data;
	}

	if (tx->can_send)
		schedule_work(&sdev->ws);

	spin_unlock_irqrestore(&tx->lock, flags);

	if (no_spc)
		return -ENOSPC;

	return 0;
}

/*
 * Handle the HCI, WIMAX_SDU_TX_FLOW.
 */
static int control_sdu_tx_flow(struct sdiowm_dev *sdev, u8 *hci_data, int len)
{
	struct tx_cxt *tx = &sdev->tx;
	u16 cmd_evt;
	unsigned long flags;

	spin_lock_irqsave(&tx->lock, flags);

	cmd_evt = (hci_data[0] << 8) | (hci_data[1]);
	if (cmd_evt != WIMAX_SDU_TX_FLOW)
		goto out;

	if (hci_data[4] == 0) {
		dev_dbg(&sdev->func->dev, "WIMAX ==> STOP SDU TX\n");
		tx->stop_sdu_tx = 1;
	} else if (hci_data[4] == 1) {
		dev_dbg(&sdev->func->dev, "WIMAX ==> START SDU TX\n");
		tx->stop_sdu_tx = 0;
		if (tx->can_send)
			schedule_work(&sdev->ws);
		/*
		 * If free buffer for sdu tx doesn't exist, then tx queue
		 * should not be woken. For this reason, don't pass the command,
		 * START_SDU_TX.
		 */
		if (list_empty(&tx->free_list))
			len = 0;
	}

out:
	spin_unlock_irqrestore(&tx->lock, flags);
	return len;
}

static void gdm_sdio_irq(struct sdio_func *func)
{
	struct phy_dev *phy_dev = sdio_get_drvdata(func);
	struct sdiowm_dev *sdev = phy_dev->priv_dev;
	struct tx_cxt *tx = &sdev->tx;
	struct rx_cxt *rx = &sdev->rx;
	struct sdio_rx *r;
	unsigned long flags;
	u8 val, hdr[TYPE_A_LOOKAHEAD_SIZE], *buf;
	u32 len, blocks, n;
	int ret, remain;

	/* Check interrupt */
	val = sdio_readb(func, 0x13, &ret);
	if (val & 0x01)
		sdio_writeb(func, 0x01, 0x13, &ret);	/* clear interrupt */
	else
		return;

	ret = sdio_memcpy_fromio(func, hdr, 0x0, TYPE_A_LOOKAHEAD_SIZE);
	if (ret) {
		dev_err(&func->dev,
			"Cannot read from function %d\n", func->num);
		goto done;
	}

	len = (hdr[2] << 16) | (hdr[1] << 8) | hdr[0];
	if (len > (RX_BUF_SIZE - TYPE_A_HEADER_SIZE)) {
		dev_err(&func->dev, "Too big Type-A size: %d\n", len);
		goto done;
	}

	if (hdr[3] == 1) {	/* Ack */
		u32 *ack_seq = (u32 *)&hdr[4];

		spin_lock_irqsave(&tx->lock, flags);
		tx->can_send = 1;

		if (!list_empty(&tx->sdu_list) || !list_empty(&tx->hci_list))
			schedule_work(&sdev->ws);
		spin_unlock_irqrestore(&tx->lock, flags);
		dev_dbg(&func->dev, "Ack... %0x\n", ntohl(*ack_seq));
		goto done;
	}

	memcpy(rx->rx_buf, hdr + TYPE_A_HEADER_SIZE,
	       TYPE_A_LOOKAHEAD_SIZE - TYPE_A_HEADER_SIZE);

	buf = rx->rx_buf + TYPE_A_LOOKAHEAD_SIZE - TYPE_A_HEADER_SIZE;
	remain = len - TYPE_A_LOOKAHEAD_SIZE + TYPE_A_HEADER_SIZE;
	if (remain <= 0)
		goto end_io;

	blocks = remain / func->cur_blksize;

	if (blocks) {
		n = blocks * func->cur_blksize;
		ret = sdio_memcpy_fromio(func, buf, 0x0, n);
		if (ret) {
			dev_err(&func->dev,
				"Cannot read from function %d\n", func->num);
			goto done;
		}
		buf += n;
		remain -= n;
	}

	if (remain) {
		ret = sdio_memcpy_fromio(func, buf, 0x0, remain);
		if (ret) {
			dev_err(&func->dev,
				"Cannot read from function %d\n", func->num);
			goto done;
		}
	}

end_io:
	print_hex_dump_debug("sdio_receive: ", DUMP_PREFIX_NONE, 16, 1,
			     rx->rx_buf, len, false);
	len = control_sdu_tx_flow(sdev, rx->rx_buf, len);

	spin_lock_irqsave(&rx->lock, flags);

	if (!list_empty(&rx->req_list)) {
		r = list_entry(rx->req_list.next, struct sdio_rx, list);
		spin_unlock_irqrestore(&rx->lock, flags);
		if (r->callback)
			r->callback(r->cb_data, rx->rx_buf, len);
		spin_lock_irqsave(&rx->lock, flags);
		list_del(&r->list);
		put_rx_struct(rx, r);
	}

	spin_unlock_irqrestore(&rx->lock, flags);

done:
	sdio_writeb(func, 0x00, 0x10, &ret);	/* PCRRT */
	if (!phy_dev->netdev)
		register_wimax_device(phy_dev, &func->dev);
}

static int gdm_sdio_receive(void *priv_dev,
			    void (*cb)(void *cb_data, void *data, int len),
			    void *cb_data)
{
	struct sdiowm_dev *sdev = priv_dev;
	struct rx_cxt *rx = &sdev->rx;
	struct sdio_rx *r;
	unsigned long flags;

	spin_lock_irqsave(&rx->lock, flags);
	r = get_rx_struct(rx);
	if (r == NULL) {
		spin_unlock_irqrestore(&rx->lock, flags);
		return -ENOMEM;
	}

	r->callback = cb;
	r->cb_data = cb_data;

	list_add_tail(&r->list, &rx->req_list);
	spin_unlock_irqrestore(&rx->lock, flags);

	return 0;
}

static int sdio_wimax_probe(struct sdio_func *func,
			    const struct sdio_device_id *id)
{
	int ret;
	struct phy_dev *phy_dev = NULL;
	struct sdiowm_dev *sdev = NULL;

	dev_info(&func->dev, "Found GDM SDIO VID = 0x%04x PID = 0x%04x...\n",
		 func->vendor, func->device);
	dev_info(&func->dev, "GCT WiMax driver version %s\n", DRIVER_VERSION);

	sdio_claim_host(func);
	sdio_enable_func(func);
	sdio_claim_irq(func, gdm_sdio_irq);

	ret = sdio_boot(func);
	if (ret)
		return ret;

	phy_dev = kzalloc(sizeof(*phy_dev), GFP_KERNEL);
	if (phy_dev == NULL) {
		ret = -ENOMEM;
		goto out;
	}
	sdev = kzalloc(sizeof(*sdev), GFP_KERNEL);
	if (sdev == NULL) {
		ret = -ENOMEM;
		goto out;
	}

	phy_dev->priv_dev = (void *)sdev;
	phy_dev->send_func = gdm_sdio_send;
	phy_dev->rcv_func = gdm_sdio_receive;

	ret = init_sdio(sdev);
	if (ret < 0)
		goto out;

	sdev->func = func;

	sdio_writeb(func, 1, 0x14, &ret);	/* Enable interrupt */
	sdio_release_host(func);

	INIT_WORK(&sdev->ws, do_tx);

	sdio_set_drvdata(func, phy_dev);
out:
	if (ret) {
		kfree(phy_dev);
		kfree(sdev);
	}

	return ret;
}

static void sdio_wimax_remove(struct sdio_func *func)
{
	struct phy_dev *phy_dev = sdio_get_drvdata(func);
	struct sdiowm_dev *sdev = phy_dev->priv_dev;

	cancel_work_sync(&sdev->ws);
	if (phy_dev->netdev)
		unregister_wimax_device(phy_dev);
	sdio_claim_host(func);
	sdio_release_irq(func);
	sdio_disable_func(func);
	sdio_release_host(func);
	release_sdio(sdev);

	kfree(sdev);
	kfree(phy_dev);
}

static const struct sdio_device_id sdio_wimax_ids[] = {
	{ SDIO_DEVICE(0x0296, 0x5347) },
	{0}
};

MODULE_DEVICE_TABLE(sdio, sdio_wimax_ids);

static struct sdio_driver sdio_wimax_driver = {
	.probe		= sdio_wimax_probe,
	.remove		= sdio_wimax_remove,
	.name		= "sdio_wimax",
	.id_table	= sdio_wimax_ids,
};

static int __init sdio_gdm_wimax_init(void)
{
	return sdio_register_driver(&sdio_wimax_driver);
}

static void __exit sdio_gdm_wimax_exit(void)
{
	sdio_unregister_driver(&sdio_wimax_driver);
}

module_init(sdio_gdm_wimax_init);
module_exit(sdio_gdm_wimax_exit);

MODULE_VERSION(DRIVER_VERSION);
MODULE_DESCRIPTION("GCT WiMax SDIO Device Driver");
MODULE_AUTHOR("Ethan Park");
MODULE_LICENSE("GPL");
