/*
 * 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/uaccess.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/usb.h>
#include <linux/unistd.h>
#include <linux/slab.h>
#include <linux/firmware.h>

#include <asm/byteorder.h>
#include "gdm_usb.h"
#include "usb_boot.h"

#define DN_KERNEL_MAGIC_NUMBER	0x10760001
#define DN_ROOTFS_MAGIC_NUMBER	0x10760002

#define DOWNLOAD_SIZE		1024

#define MAX_IMG_CNT		16
#define FW_DIR			"gdm72xx/"
#define FW_UIMG			"gdmuimg.bin"
#define FW_KERN			"zImage"
#define FW_FS			"ramdisk.jffs2"

struct dn_header {
	u32	magic_num;
	u32	file_size;
};

struct img_header {
	u32	magic_code;
	u32	count;
	u32	len;
	u32	offset[MAX_IMG_CNT];
	char	hostname[32];
	char	date[32];
};

struct fw_info {
	u32	id;
	u32	len;
	u32	kernel_len;
	u32	rootfs_len;
	u32	kernel_offset;
	u32	rootfs_offset;
	u32	fw_ver;
	u32	mac_ver;
	char	hostname[32];
	char	userid[16];
	char	date[32];
	char	user_desc[128];
};

static void array_le32_to_cpu(u32 *arr, int num)
{
	int i;
	for (i = 0; i < num; i++, arr++)
		*arr = __le32_to_cpu(*arr);
}

static u8 *tx_buf;

static int gdm_wibro_send(struct usb_device *usbdev, void *data, int len)
{
	int ret;
	int actual;

	ret = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), data, len,
			&actual, 1000);

	if (ret < 0) {
		dev_err(&usbdev->dev, "Error : usb_bulk_msg ( result = %d )\n",
			ret);
		return ret;
	}
	return 0;
}

static int gdm_wibro_recv(struct usb_device *usbdev, void *data, int len)
{
	int ret;
	int actual;

	ret = usb_bulk_msg(usbdev, usb_rcvbulkpipe(usbdev, 2), data, len,
			&actual, 5000);

	if (ret < 0) {
		dev_err(&usbdev->dev,
			"Error : usb_bulk_msg(recv) ( result = %d )\n", ret);
		return ret;
	}
	return 0;
}

static int download_image(struct usb_device *usbdev,
				const struct firmware *firm,
				loff_t pos, u32 img_len, u32 magic_num)
{
	struct dn_header h;
	int ret = 0;
	u32 size;

	size = ALIGN(img_len, DOWNLOAD_SIZE);
	h.magic_num = __cpu_to_be32(magic_num);
	h.file_size = __cpu_to_be32(size);

	ret = gdm_wibro_send(usbdev, &h, sizeof(h));
	if (ret < 0)
		return ret;

	while (img_len > 0) {
		if (img_len > DOWNLOAD_SIZE)
			size = DOWNLOAD_SIZE;
		else
			size = img_len;	/* the last chunk of data */

		memcpy(tx_buf, firm->data + pos, size);
		ret = gdm_wibro_send(usbdev, tx_buf, size);

		if (ret < 0)
			return ret;

		img_len -= size;
		pos += size;
	}

	return ret;
}

int usb_boot(struct usb_device *usbdev, u16 pid)
{
	int i, ret = 0;
	struct img_header hdr;
	struct fw_info fw_info;
	loff_t pos = 0;
	char *img_name = FW_DIR FW_UIMG;
	const struct firmware *firm;

	ret = request_firmware(&firm, img_name, &usbdev->dev);
	if (ret < 0) {
		dev_err(&usbdev->dev,
			"requesting firmware %s failed with error %d\n",
			img_name, ret);
		return ret;
	}

	tx_buf = kmalloc(DOWNLOAD_SIZE, GFP_KERNEL);
	if (tx_buf == NULL)
		return -ENOMEM;

	if (firm->size < sizeof(hdr)) {
		dev_err(&usbdev->dev, "Cannot read the image info.\n");
		ret = -EIO;
		goto out;
	}
	memcpy(&hdr, firm->data, sizeof(hdr));

	array_le32_to_cpu((u32 *)&hdr, 19);
#if 0
	if (hdr.magic_code != 0x10767fff) {
		dev_err(&usbdev->dev, "Invalid magic code 0x%08x\n",
			hdr.magic_code);
		ret = -EINVAL;
		goto out;
	}
#endif
	if (hdr.count > MAX_IMG_CNT) {
		dev_err(&usbdev->dev, "Too many images. %d\n", hdr.count);
		ret = -EINVAL;
		goto out;
	}

	for (i = 0; i < hdr.count; i++) {
		if (hdr.offset[i] > hdr.len) {
			dev_err(&usbdev->dev,
				"Invalid offset. Entry = %d Offset = 0x%08x Image length = 0x%08x\n",
				i, hdr.offset[i], hdr.len);
			ret = -EINVAL;
			goto out;
		}

		pos = hdr.offset[i];
		if (firm->size < sizeof(fw_info) + pos) {
			dev_err(&usbdev->dev, "Cannot read the FW info.\n");
			ret = -EIO;
			goto out;
		}
		memcpy(&fw_info, firm->data + pos, sizeof(fw_info));

		array_le32_to_cpu((u32 *)&fw_info, 8);
#if 0
		if ((fw_info.id & 0xfffff000) != 0x10767000) {
			dev_err(&usbdev->dev, "Invalid FW id. 0x%08x\n",
				fw_info.id);
			ret = -EIO;
			goto out;
		}
#endif

		if ((fw_info.id & 0xffff) != pid)
			continue;

		pos = hdr.offset[i] + fw_info.kernel_offset;
		if (firm->size < fw_info.kernel_len + pos) {
			dev_err(&usbdev->dev, "Kernel FW is too small.\n");
			goto out;
		}

		ret = download_image(usbdev, firm, pos,
				fw_info.kernel_len, DN_KERNEL_MAGIC_NUMBER);
		if (ret < 0)
			goto out;
		dev_info(&usbdev->dev, "GCT: Kernel download success.\n");

		pos = hdr.offset[i] + fw_info.rootfs_offset;
		if (firm->size < fw_info.rootfs_len + pos) {
			dev_err(&usbdev->dev, "Filesystem FW is too small.\n");
			goto out;
		}
		ret = download_image(usbdev, firm, pos, fw_info.rootfs_len,
				DN_ROOTFS_MAGIC_NUMBER);
		if (ret < 0)
			goto out;
		dev_info(&usbdev->dev, "GCT: Filesystem download success.\n");

		break;
	}

	if (i == hdr.count) {
		dev_err(&usbdev->dev, "Firmware for gsk%x is not installed.\n",
			pid);
		ret = -EINVAL;
	}
out:
	release_firmware(firm);
	kfree(tx_buf);
	return ret;
}

/*#define GDM7205_PADDING		256 */
#define DOWNLOAD_CHUCK			2048
#define KERNEL_TYPE_STRING		"linux"
#define FS_TYPE_STRING			"rootfs"

static int em_wait_ack(struct usb_device *usbdev, int send_zlp)
{
	int ack;
	int ret = -1;

	if (send_zlp) {
		/*Send ZLP*/
		ret = gdm_wibro_send(usbdev, NULL, 0);
		if (ret < 0)
			goto out;
	}

	/*Wait for ACK*/
	ret = gdm_wibro_recv(usbdev, &ack, sizeof(ack));
	if (ret < 0)
		goto out;
out:
	return ret;
}

static int em_download_image(struct usb_device *usbdev, const char *img_name,
				char *type_string)
{
	char *buf = NULL;
	loff_t pos = 0;
	int ret = 0;
	int len;
	int img_len;
	const struct firmware *firm;
	#if defined(GDM7205_PADDING)
	const int pad_size = GDM7205_PADDING;
	#else
	const int pad_size = 0;
	#endif

	ret = request_firmware(&firm, img_name, &usbdev->dev);
	if (ret < 0) {
		dev_err(&usbdev->dev,
			"requesting firmware %s failed with error %d\n",
			img_name, ret);
		return ret;
	}

	buf = kmalloc(DOWNLOAD_CHUCK + pad_size, GFP_KERNEL);
	if (buf == NULL)
		return -ENOMEM;

	strcpy(buf+pad_size, type_string);
	ret = gdm_wibro_send(usbdev, buf, strlen(type_string)+pad_size);
	if (ret < 0)
		goto out;

	img_len = firm->size;

	if (img_len <= 0) {
		ret = -1;
		goto out;
	}

	while (img_len > 0) {
		if (img_len > DOWNLOAD_CHUCK)
			len = DOWNLOAD_CHUCK;
		else
			len = img_len; /* the last chunk of data */

		memcpy(buf+pad_size, firm->data + pos, len);
		ret = gdm_wibro_send(usbdev, buf, len+pad_size);

		if (ret < 0)
			goto out;

		img_len -= DOWNLOAD_CHUCK;
		pos += DOWNLOAD_CHUCK;

		ret = em_wait_ack(usbdev, ((len+pad_size) % 512 == 0));
		if (ret < 0)
			goto out;
	}

	ret = em_wait_ack(usbdev, 1);
	if (ret < 0)
		goto out;

out:
	release_firmware(firm);
	kfree(buf);

	return ret;
}

static int em_fw_reset(struct usb_device *usbdev)
{
	int ret;

	/*Send ZLP*/
	ret = gdm_wibro_send(usbdev, NULL, 0);
	return ret;
}

int usb_emergency(struct usb_device *usbdev)
{
	int ret;
	const char *kern_name = FW_DIR FW_KERN;
	const char *fs_name = FW_DIR FW_FS;

	ret = em_download_image(usbdev, kern_name, KERNEL_TYPE_STRING);
	if (ret < 0)
		return ret;
	dev_err(&usbdev->dev, "GCT Emergency: Kernel download success.\n");

	ret = em_download_image(usbdev, fs_name, FS_TYPE_STRING);
	if (ret < 0)
		return ret;
	dev_info(&usbdev->dev, "GCT Emergency: Filesystem download success.\n");

	ret = em_fw_reset(usbdev);

	return ret;
}
