cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ams-delta.c (11478B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 *  Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
      4 *
      5 *  Derived from drivers/mtd/nand/toto.c (removed in v2.6.28)
      6 *    Copyright (c) 2003 Texas Instruments
      7 *    Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de>
      8 *
      9 *  Converted to platform driver by Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
     10 *  Partially stolen from plat_nand.c
     11 *
     12 *  Overview:
     13 *   This is a device driver for the NAND flash device found on the
     14 *   Amstrad E3 (Delta).
     15 */
     16
     17#include <linux/slab.h>
     18#include <linux/module.h>
     19#include <linux/delay.h>
     20#include <linux/gpio/consumer.h>
     21#include <linux/mtd/mtd.h>
     22#include <linux/mtd/nand-gpio.h>
     23#include <linux/mtd/rawnand.h>
     24#include <linux/mtd/partitions.h>
     25#include <linux/of_device.h>
     26#include <linux/platform_device.h>
     27#include <linux/sizes.h>
     28
     29/*
     30 * MTD structure for E3 (Delta)
     31 */
     32struct gpio_nand {
     33	struct nand_controller	base;
     34	struct nand_chip	nand_chip;
     35	struct gpio_desc	*gpiod_rdy;
     36	struct gpio_desc	*gpiod_nce;
     37	struct gpio_desc	*gpiod_nre;
     38	struct gpio_desc	*gpiod_nwp;
     39	struct gpio_desc	*gpiod_nwe;
     40	struct gpio_desc	*gpiod_ale;
     41	struct gpio_desc	*gpiod_cle;
     42	struct gpio_descs	*data_gpiods;
     43	bool			data_in;
     44	unsigned int		tRP;
     45	unsigned int		tWP;
     46	u8			(*io_read)(struct gpio_nand *this);
     47	void			(*io_write)(struct gpio_nand *this, u8 byte);
     48};
     49
     50static void gpio_nand_write_commit(struct gpio_nand *priv)
     51{
     52	gpiod_set_value(priv->gpiod_nwe, 1);
     53	ndelay(priv->tWP);
     54	gpiod_set_value(priv->gpiod_nwe, 0);
     55}
     56
     57static void gpio_nand_io_write(struct gpio_nand *priv, u8 byte)
     58{
     59	struct gpio_descs *data_gpiods = priv->data_gpiods;
     60	DECLARE_BITMAP(values, BITS_PER_TYPE(byte)) = { byte, };
     61
     62	gpiod_set_raw_array_value(data_gpiods->ndescs, data_gpiods->desc,
     63				  data_gpiods->info, values);
     64
     65	gpio_nand_write_commit(priv);
     66}
     67
     68static void gpio_nand_dir_output(struct gpio_nand *priv, u8 byte)
     69{
     70	struct gpio_descs *data_gpiods = priv->data_gpiods;
     71	DECLARE_BITMAP(values, BITS_PER_TYPE(byte)) = { byte, };
     72	int i;
     73
     74	for (i = 0; i < data_gpiods->ndescs; i++)
     75		gpiod_direction_output_raw(data_gpiods->desc[i],
     76					   test_bit(i, values));
     77
     78	gpio_nand_write_commit(priv);
     79
     80	priv->data_in = false;
     81}
     82
     83static u8 gpio_nand_io_read(struct gpio_nand *priv)
     84{
     85	u8 res;
     86	struct gpio_descs *data_gpiods = priv->data_gpiods;
     87	DECLARE_BITMAP(values, BITS_PER_TYPE(res)) = { 0, };
     88
     89	gpiod_set_value(priv->gpiod_nre, 1);
     90	ndelay(priv->tRP);
     91
     92	gpiod_get_raw_array_value(data_gpiods->ndescs, data_gpiods->desc,
     93				  data_gpiods->info, values);
     94
     95	gpiod_set_value(priv->gpiod_nre, 0);
     96
     97	res = values[0];
     98	return res;
     99}
    100
    101static void gpio_nand_dir_input(struct gpio_nand *priv)
    102{
    103	struct gpio_descs *data_gpiods = priv->data_gpiods;
    104	int i;
    105
    106	for (i = 0; i < data_gpiods->ndescs; i++)
    107		gpiod_direction_input(data_gpiods->desc[i]);
    108
    109	priv->data_in = true;
    110}
    111
    112static void gpio_nand_write_buf(struct gpio_nand *priv, const u8 *buf, int len)
    113{
    114	int i = 0;
    115
    116	if (len > 0 && priv->data_in)
    117		gpio_nand_dir_output(priv, buf[i++]);
    118
    119	while (i < len)
    120		priv->io_write(priv, buf[i++]);
    121}
    122
    123static void gpio_nand_read_buf(struct gpio_nand *priv, u8 *buf, int len)
    124{
    125	int i;
    126
    127	if (priv->data_gpiods && !priv->data_in)
    128		gpio_nand_dir_input(priv);
    129
    130	for (i = 0; i < len; i++)
    131		buf[i] = priv->io_read(priv);
    132}
    133
    134static void gpio_nand_ctrl_cs(struct gpio_nand *priv, bool assert)
    135{
    136	gpiod_set_value(priv->gpiod_nce, assert);
    137}
    138
    139static int gpio_nand_exec_op(struct nand_chip *this,
    140			     const struct nand_operation *op, bool check_only)
    141{
    142	struct gpio_nand *priv = nand_get_controller_data(this);
    143	const struct nand_op_instr *instr;
    144	int ret = 0;
    145
    146	if (check_only)
    147		return 0;
    148
    149	gpio_nand_ctrl_cs(priv, 1);
    150
    151	for (instr = op->instrs; instr < op->instrs + op->ninstrs; instr++) {
    152		switch (instr->type) {
    153		case NAND_OP_CMD_INSTR:
    154			gpiod_set_value(priv->gpiod_cle, 1);
    155			gpio_nand_write_buf(priv, &instr->ctx.cmd.opcode, 1);
    156			gpiod_set_value(priv->gpiod_cle, 0);
    157			break;
    158
    159		case NAND_OP_ADDR_INSTR:
    160			gpiod_set_value(priv->gpiod_ale, 1);
    161			gpio_nand_write_buf(priv, instr->ctx.addr.addrs,
    162					    instr->ctx.addr.naddrs);
    163			gpiod_set_value(priv->gpiod_ale, 0);
    164			break;
    165
    166		case NAND_OP_DATA_IN_INSTR:
    167			gpio_nand_read_buf(priv, instr->ctx.data.buf.in,
    168					   instr->ctx.data.len);
    169			break;
    170
    171		case NAND_OP_DATA_OUT_INSTR:
    172			gpio_nand_write_buf(priv, instr->ctx.data.buf.out,
    173					    instr->ctx.data.len);
    174			break;
    175
    176		case NAND_OP_WAITRDY_INSTR:
    177			ret = priv->gpiod_rdy ?
    178			      nand_gpio_waitrdy(this, priv->gpiod_rdy,
    179						instr->ctx.waitrdy.timeout_ms) :
    180			      nand_soft_waitrdy(this,
    181						instr->ctx.waitrdy.timeout_ms);
    182			break;
    183		}
    184
    185		if (ret)
    186			break;
    187	}
    188
    189	gpio_nand_ctrl_cs(priv, 0);
    190
    191	return ret;
    192}
    193
    194static int gpio_nand_setup_interface(struct nand_chip *this, int csline,
    195				     const struct nand_interface_config *cf)
    196{
    197	struct gpio_nand *priv = nand_get_controller_data(this);
    198	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(cf);
    199	struct device *dev = &nand_to_mtd(this)->dev;
    200
    201	if (IS_ERR(sdr))
    202		return PTR_ERR(sdr);
    203
    204	if (csline == NAND_DATA_IFACE_CHECK_ONLY)
    205		return 0;
    206
    207	if (priv->gpiod_nre) {
    208		priv->tRP = DIV_ROUND_UP(sdr->tRP_min, 1000);
    209		dev_dbg(dev, "using %u ns read pulse width\n", priv->tRP);
    210	}
    211
    212	priv->tWP = DIV_ROUND_UP(sdr->tWP_min, 1000);
    213	dev_dbg(dev, "using %u ns write pulse width\n", priv->tWP);
    214
    215	return 0;
    216}
    217
    218static int gpio_nand_attach_chip(struct nand_chip *chip)
    219{
    220	if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT &&
    221	    chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN)
    222		chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
    223
    224	return 0;
    225}
    226
    227static const struct nand_controller_ops gpio_nand_ops = {
    228	.exec_op = gpio_nand_exec_op,
    229	.attach_chip = gpio_nand_attach_chip,
    230	.setup_interface = gpio_nand_setup_interface,
    231};
    232
    233/*
    234 * Main initialization routine
    235 */
    236static int gpio_nand_probe(struct platform_device *pdev)
    237{
    238	struct gpio_nand_platdata *pdata = dev_get_platdata(&pdev->dev);
    239	const struct mtd_partition *partitions = NULL;
    240	int num_partitions = 0;
    241	struct gpio_nand *priv;
    242	struct nand_chip *this;
    243	struct mtd_info *mtd;
    244	int (*probe)(struct platform_device *pdev, struct gpio_nand *priv);
    245	int err = 0;
    246
    247	if (pdata) {
    248		partitions = pdata->parts;
    249		num_partitions = pdata->num_parts;
    250	}
    251
    252	/* Allocate memory for MTD device structure and private data */
    253	priv = devm_kzalloc(&pdev->dev, sizeof(struct gpio_nand),
    254			    GFP_KERNEL);
    255	if (!priv)
    256		return -ENOMEM;
    257
    258	this = &priv->nand_chip;
    259
    260	mtd = nand_to_mtd(this);
    261	mtd->dev.parent = &pdev->dev;
    262
    263	nand_set_controller_data(this, priv);
    264	nand_set_flash_node(this, pdev->dev.of_node);
    265
    266	priv->gpiod_rdy = devm_gpiod_get_optional(&pdev->dev, "rdy", GPIOD_IN);
    267	if (IS_ERR(priv->gpiod_rdy)) {
    268		err = PTR_ERR(priv->gpiod_rdy);
    269		dev_warn(&pdev->dev, "RDY GPIO request failed (%d)\n", err);
    270		return err;
    271	}
    272
    273	platform_set_drvdata(pdev, priv);
    274
    275	/* Set chip enabled but write protected */
    276	priv->gpiod_nwp = devm_gpiod_get_optional(&pdev->dev, "nwp",
    277						  GPIOD_OUT_HIGH);
    278	if (IS_ERR(priv->gpiod_nwp)) {
    279		err = PTR_ERR(priv->gpiod_nwp);
    280		dev_err(&pdev->dev, "NWP GPIO request failed (%d)\n", err);
    281		return err;
    282	}
    283
    284	priv->gpiod_nce = devm_gpiod_get_optional(&pdev->dev, "nce",
    285						  GPIOD_OUT_LOW);
    286	if (IS_ERR(priv->gpiod_nce)) {
    287		err = PTR_ERR(priv->gpiod_nce);
    288		dev_err(&pdev->dev, "NCE GPIO request failed (%d)\n", err);
    289		return err;
    290	}
    291
    292	priv->gpiod_nre = devm_gpiod_get_optional(&pdev->dev, "nre",
    293						  GPIOD_OUT_LOW);
    294	if (IS_ERR(priv->gpiod_nre)) {
    295		err = PTR_ERR(priv->gpiod_nre);
    296		dev_err(&pdev->dev, "NRE GPIO request failed (%d)\n", err);
    297		return err;
    298	}
    299
    300	priv->gpiod_nwe = devm_gpiod_get_optional(&pdev->dev, "nwe",
    301						  GPIOD_OUT_LOW);
    302	if (IS_ERR(priv->gpiod_nwe)) {
    303		err = PTR_ERR(priv->gpiod_nwe);
    304		dev_err(&pdev->dev, "NWE GPIO request failed (%d)\n", err);
    305		return err;
    306	}
    307
    308	priv->gpiod_ale = devm_gpiod_get(&pdev->dev, "ale", GPIOD_OUT_LOW);
    309	if (IS_ERR(priv->gpiod_ale)) {
    310		err = PTR_ERR(priv->gpiod_ale);
    311		dev_err(&pdev->dev, "ALE GPIO request failed (%d)\n", err);
    312		return err;
    313	}
    314
    315	priv->gpiod_cle = devm_gpiod_get(&pdev->dev, "cle", GPIOD_OUT_LOW);
    316	if (IS_ERR(priv->gpiod_cle)) {
    317		err = PTR_ERR(priv->gpiod_cle);
    318		dev_err(&pdev->dev, "CLE GPIO request failed (%d)\n", err);
    319		return err;
    320	}
    321
    322	/* Request array of data pins, initialize them as input */
    323	priv->data_gpiods = devm_gpiod_get_array_optional(&pdev->dev, "data",
    324							  GPIOD_IN);
    325	if (IS_ERR(priv->data_gpiods)) {
    326		err = PTR_ERR(priv->data_gpiods);
    327		dev_err(&pdev->dev, "data GPIO request failed: %d\n", err);
    328		return err;
    329	}
    330	if (priv->data_gpiods) {
    331		if (!priv->gpiod_nwe) {
    332			dev_err(&pdev->dev,
    333				"mandatory NWE pin not provided by platform\n");
    334			return -ENODEV;
    335		}
    336
    337		priv->io_read = gpio_nand_io_read;
    338		priv->io_write = gpio_nand_io_write;
    339		priv->data_in = true;
    340	}
    341
    342	if (pdev->id_entry)
    343		probe = (void *) pdev->id_entry->driver_data;
    344	else
    345		probe = of_device_get_match_data(&pdev->dev);
    346	if (probe)
    347		err = probe(pdev, priv);
    348	if (err)
    349		return err;
    350
    351	if (!priv->io_read || !priv->io_write) {
    352		dev_err(&pdev->dev, "incomplete device configuration\n");
    353		return -ENODEV;
    354	}
    355
    356	/* Initialize the NAND controller object embedded in gpio_nand. */
    357	priv->base.ops = &gpio_nand_ops;
    358	nand_controller_init(&priv->base);
    359	this->controller = &priv->base;
    360
    361	/*
    362	 * FIXME: We should release write protection only after nand_scan() to
    363	 * be on the safe side but we can't do that until we have a generic way
    364	 * to assert/deassert WP from the core.  Even if the core shouldn't
    365	 * write things in the nand_scan() path, it should have control on this
    366	 * pin just in case we ever need to disable write protection during
    367	 * chip detection/initialization.
    368	 */
    369	/* Release write protection */
    370	gpiod_set_value(priv->gpiod_nwp, 0);
    371
    372	/*
    373	 * This driver assumes that the default ECC engine should be TYPE_SOFT.
    374	 * Set ->engine_type before registering the NAND devices in order to
    375	 * provide a driver specific default value.
    376	 */
    377	this->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
    378
    379	/* Scan to find existence of the device */
    380	err = nand_scan(this, 1);
    381	if (err)
    382		return err;
    383
    384	/* Register the partitions */
    385	err = mtd_device_register(mtd, partitions, num_partitions);
    386	if (err)
    387		goto err_nand_cleanup;
    388
    389	return 0;
    390
    391err_nand_cleanup:
    392	nand_cleanup(this);
    393
    394	return err;
    395}
    396
    397/*
    398 * Clean up routine
    399 */
    400static int gpio_nand_remove(struct platform_device *pdev)
    401{
    402	struct gpio_nand *priv = platform_get_drvdata(pdev);
    403	struct mtd_info *mtd = nand_to_mtd(&priv->nand_chip);
    404	int ret;
    405
    406	/* Apply write protection */
    407	gpiod_set_value(priv->gpiod_nwp, 1);
    408
    409	/* Unregister device */
    410	ret = mtd_device_unregister(mtd);
    411	WARN_ON(ret);
    412	nand_cleanup(mtd_to_nand(mtd));
    413
    414	return 0;
    415}
    416
    417#ifdef CONFIG_OF
    418static const struct of_device_id gpio_nand_of_id_table[] = {
    419	{
    420		/* sentinel */
    421	},
    422};
    423MODULE_DEVICE_TABLE(of, gpio_nand_of_id_table);
    424#endif
    425
    426static const struct platform_device_id gpio_nand_plat_id_table[] = {
    427	{
    428		.name	= "ams-delta-nand",
    429	}, {
    430		/* sentinel */
    431	},
    432};
    433MODULE_DEVICE_TABLE(platform, gpio_nand_plat_id_table);
    434
    435static struct platform_driver gpio_nand_driver = {
    436	.probe		= gpio_nand_probe,
    437	.remove		= gpio_nand_remove,
    438	.id_table	= gpio_nand_plat_id_table,
    439	.driver		= {
    440		.name	= "ams-delta-nand",
    441		.of_match_table = of_match_ptr(gpio_nand_of_id_table),
    442	},
    443};
    444
    445module_platform_driver(gpio_nand_driver);
    446
    447MODULE_LICENSE("GPL v2");
    448MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>");
    449MODULE_DESCRIPTION("Glue layer for NAND flash on Amstrad E3 (Delta)");