/*
 * 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 = ARRAY_SIZE(qinfo_array);
	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)
		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");

