/*
 * Probing flash chips with QINFO records.
 * (C) 2008 Korolev Alexey <akorolev@infradead.org>
 * (C) 2008 Vasiliy Leonenko <vasiliy.leonenko@gmail.com>
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/interrupt.h>

#include <linux/mtd/xip.h>
#include <linux/mtd/map.h>
#include <linux/mtd/pfow.h>
#include <linux/mtd/qinfo.h>

static int lpddr_chip_setup(struct map_info *map, struct lpddr_private *lpddr);
struct mtd_info *lpddr_probe(struct map_info *map);
static struct lpddr_private *lpddr_probe_chip(struct map_info *map);
static int lpddr_pfow_present(struct map_info *map,
			struct lpddr_private *lpddr);

static struct qinfo_query_info qinfo_array[] = {
	/* General device info */
	{0, 0, "DevSizeShift", "Device size 2^n bytes"},
	{0, 3, "BufSizeShift", "Program buffer size 2^n bytes"},
	/* Erase block information */
	{1, 1, "TotalBlocksNum", "Total number of blocks"},
	{1, 2, "UniformBlockSizeShift", "Uniform block size 2^n bytes"},
	/* Partition information */
	{2, 1, "HWPartsNum", "Number of hardware partitions"},
	/* Optional features */
	{5, 1, "SuspEraseSupp", "Suspend erase supported"},
	/* Operation typical time */
	{10, 0, "SingleWordProgTime", "Single word program 2^n u-sec"},
	{10, 1, "ProgBufferTime", "Program buffer write 2^n u-sec"},
	{10, 2, "BlockEraseTime", "Block erase 2^n m-sec"},
	{10, 3, "FullChipEraseTime", "Full chip erase 2^n m-sec"},
};

static long lpddr_get_qinforec_pos(struct map_info *map, char *id_str)
{
	int qinfo_lines = sizeof(qinfo_array)/sizeof(struct qinfo_query_info);
	int i;
	int bankwidth = map_bankwidth(map) * 8;
	int major, minor;

	for (i = 0; i < qinfo_lines; i++) {
		if (strcmp(id_str, qinfo_array[i].id_str) == 0) {
			major = qinfo_array[i].major & ((1 << bankwidth) - 1);
			minor = qinfo_array[i].minor & ((1 << bankwidth) - 1);
			return minor | (major << bankwidth);
		}
	}
	printk(KERN_ERR"%s qinfo id string is wrong! \n", map->name);
	BUG();
	return -1;
}

static uint16_t lpddr_info_query(struct map_info *map, char *id_str)
{
	unsigned int dsr, val;
	int bits_per_chip = map_bankwidth(map) * 8;
	unsigned long adr = lpddr_get_qinforec_pos(map, id_str);
	int attempts = 20;

	/* Write a request for the PFOW record */
	map_write(map, CMD(LPDDR_INFO_QUERY),
			map->pfow_base + PFOW_COMMAND_CODE);
	map_write(map, CMD(adr & ((1 << bits_per_chip) - 1)),
			map->pfow_base + PFOW_COMMAND_ADDRESS_L);
	map_write(map, CMD(adr >> bits_per_chip),
			map->pfow_base + PFOW_COMMAND_ADDRESS_H);
	map_write(map, CMD(LPDDR_START_EXECUTION),
			map->pfow_base + PFOW_COMMAND_EXECUTE);

	while ((attempts--) > 0) {
		dsr = CMDVAL(map_read(map, map->pfow_base + PFOW_DSR));
		if (dsr & DSR_READY_STATUS)
			break;
		udelay(10);
	}

	val = CMDVAL(map_read(map, map->pfow_base + PFOW_COMMAND_DATA));
	return val;
}

static int lpddr_pfow_present(struct map_info *map, struct lpddr_private *lpddr)
{
	map_word pfow_val[4];

	/* Check identification string */
	pfow_val[0] = map_read(map, map->pfow_base + PFOW_QUERY_STRING_P);
	pfow_val[1] = map_read(map, map->pfow_base + PFOW_QUERY_STRING_F);
	pfow_val[2] = map_read(map, map->pfow_base + PFOW_QUERY_STRING_O);
	pfow_val[3] = map_read(map, map->pfow_base + PFOW_QUERY_STRING_W);

	if (!map_word_equal(map, CMD('P'), pfow_val[0]))
		goto out;

	if (!map_word_equal(map, CMD('F'), pfow_val[1]))
		goto out;

	if (!map_word_equal(map, CMD('O'), pfow_val[2]))
		goto out;

	if (!map_word_equal(map, CMD('W'), pfow_val[3]))
		goto out;

	return 1;	/* "PFOW" is found */
out:
	printk(KERN_WARNING"%s: PFOW string at 0x%lx is not found \n",
					map->name, map->pfow_base);
	return 0;
}

static int lpddr_chip_setup(struct map_info *map, struct lpddr_private *lpddr)
{

	lpddr->qinfo = kzalloc(sizeof(struct qinfo_chip), GFP_KERNEL);
	if (!lpddr->qinfo) {
		printk(KERN_WARNING "%s: no memory for LPDDR qinfo structure\n",
				map->name);
		return 0;
	}

	/* Get the ManuID */
	lpddr->ManufactId = CMDVAL(map_read(map, map->pfow_base + PFOW_MANUFACTURER_ID));
	/* Get the DeviceID */
	lpddr->DevId = CMDVAL(map_read(map, map->pfow_base + PFOW_DEVICE_ID));
	/* read parameters from chip qinfo table */
	lpddr->qinfo->DevSizeShift = lpddr_info_query(map, "DevSizeShift");
	lpddr->qinfo->TotalBlocksNum = lpddr_info_query(map, "TotalBlocksNum");
	lpddr->qinfo->BufSizeShift = lpddr_info_query(map, "BufSizeShift");
	lpddr->qinfo->HWPartsNum = lpddr_info_query(map, "HWPartsNum");
	lpddr->qinfo->UniformBlockSizeShift =
				lpddr_info_query(map, "UniformBlockSizeShift");
	lpddr->qinfo->SuspEraseSupp = lpddr_info_query(map, "SuspEraseSupp");
	lpddr->qinfo->SingleWordProgTime =
				lpddr_info_query(map, "SingleWordProgTime");
	lpddr->qinfo->ProgBufferTime = lpddr_info_query(map, "ProgBufferTime");
	lpddr->qinfo->BlockEraseTime = lpddr_info_query(map, "BlockEraseTime");
	return 1;
}
static struct lpddr_private *lpddr_probe_chip(struct map_info *map)
{
	struct lpddr_private lpddr;
	struct lpddr_private *retlpddr;
	int numvirtchips;


	if ((map->pfow_base + 0x1000) >= map->size) {
		printk(KERN_NOTICE"%s Probe at base (0x%08lx) past the end of"
				"the map(0x%08lx)\n", map->name,
				(unsigned long)map->pfow_base, map->size - 1);
		return NULL;
	}
	memset(&lpddr, 0, sizeof(struct lpddr_private));
	if (!lpddr_pfow_present(map, &lpddr))
		return NULL;

	if (!lpddr_chip_setup(map, &lpddr))
		return NULL;

	/* Ok so we found a chip */
	lpddr.chipshift = lpddr.qinfo->DevSizeShift;
	lpddr.numchips = 1;

	numvirtchips = lpddr.numchips * lpddr.qinfo->HWPartsNum;
	retlpddr = kzalloc(sizeof(struct lpddr_private) +
			numvirtchips * sizeof(struct flchip), GFP_KERNEL);
	if (!retlpddr)
		return NULL;

	memcpy(retlpddr, &lpddr, sizeof(struct lpddr_private));

	retlpddr->numchips = numvirtchips;
	retlpddr->chipshift = retlpddr->qinfo->DevSizeShift -
				__ffs(retlpddr->qinfo->HWPartsNum);

	return retlpddr;
}

struct mtd_info *lpddr_probe(struct map_info *map)
{
	struct mtd_info *mtd = NULL;
	struct lpddr_private *lpddr;

	/* First probe the map to see if we havecan open PFOW here */
	lpddr = lpddr_probe_chip(map);
	if (!lpddr)
		return NULL;

	map->fldrv_priv = lpddr;
	mtd = lpddr_cmdset(map);
	if (mtd) {
		if (mtd->size > map->size) {
			printk(KERN_WARNING "Reducing visibility of %ldKiB chip"
				"to %ldKiB\n", (unsigned long)mtd->size >> 10,
				(unsigned long)map->size >> 10);
			mtd->size = map->size;
		}
		return mtd;
	}

	kfree(lpddr->qinfo);
	kfree(lpddr);
	map->fldrv_priv = NULL;
	return NULL;
}

static struct mtd_chip_driver lpddr_chipdrv = {
	.probe		= lpddr_probe,
	.name		= "qinfo_probe",
	.module		= THIS_MODULE
};

static int __init lpddr_probe_init(void)
{
	register_mtd_chip_driver(&lpddr_chipdrv);
	return 0;
}

static void __exit lpddr_probe_exit(void)
{
	unregister_mtd_chip_driver(&lpddr_chipdrv);
}

module_init(lpddr_probe_init);
module_exit(lpddr_probe_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Vasiliy Leonenko <vasiliy.leonenko@gmail.com>");
MODULE_DESCRIPTION("Driver to probe qinfo flash chips");

