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

gpio.c (9989B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Updated, and converted to generic GPIO based driver by Russell King.
      4 *
      5 * Written by Ben Dooks <ben@simtec.co.uk>
      6 *   Based on 2.4 version by Mark Whittaker
      7 *
      8 * © 2004 Simtec Electronics
      9 *
     10 * Device driver for NAND flash that uses a memory mapped interface to
     11 * read/write the NAND commands and data, and GPIO pins for control signals
     12 * (the DT binding refers to this as "GPIO assisted NAND flash")
     13 */
     14
     15#include <linux/kernel.h>
     16#include <linux/err.h>
     17#include <linux/slab.h>
     18#include <linux/module.h>
     19#include <linux/platform_device.h>
     20#include <linux/gpio/consumer.h>
     21#include <linux/io.h>
     22#include <linux/mtd/mtd.h>
     23#include <linux/mtd/rawnand.h>
     24#include <linux/mtd/partitions.h>
     25#include <linux/mtd/nand-gpio.h>
     26#include <linux/of.h>
     27#include <linux/of_address.h>
     28#include <linux/delay.h>
     29
     30struct gpiomtd {
     31	struct nand_controller	base;
     32	void __iomem		*io;
     33	void __iomem		*io_sync;
     34	struct nand_chip	nand_chip;
     35	struct gpio_nand_platdata plat;
     36	struct gpio_desc *nce; /* Optional chip enable */
     37	struct gpio_desc *cle;
     38	struct gpio_desc *ale;
     39	struct gpio_desc *rdy;
     40	struct gpio_desc *nwp; /* Optional write protection */
     41};
     42
     43static inline struct gpiomtd *gpio_nand_getpriv(struct mtd_info *mtd)
     44{
     45	return container_of(mtd_to_nand(mtd), struct gpiomtd, nand_chip);
     46}
     47
     48
     49#ifdef CONFIG_ARM
     50/* gpio_nand_dosync()
     51 *
     52 * Make sure the GPIO state changes occur in-order with writes to NAND
     53 * memory region.
     54 * Needed on PXA due to bus-reordering within the SoC itself (see section on
     55 * I/O ordering in PXA manual (section 2.3, p35)
     56 */
     57static void gpio_nand_dosync(struct gpiomtd *gpiomtd)
     58{
     59	unsigned long tmp;
     60
     61	if (gpiomtd->io_sync) {
     62		/*
     63		 * Linux memory barriers don't cater for what's required here.
     64		 * What's required is what's here - a read from a separate
     65		 * region with a dependency on that read.
     66		 */
     67		tmp = readl(gpiomtd->io_sync);
     68		asm volatile("mov %1, %0\n" : "=r" (tmp) : "r" (tmp));
     69	}
     70}
     71#else
     72static inline void gpio_nand_dosync(struct gpiomtd *gpiomtd) {}
     73#endif
     74
     75static int gpio_nand_exec_instr(struct nand_chip *chip,
     76				const struct nand_op_instr *instr)
     77{
     78	struct gpiomtd *gpiomtd = gpio_nand_getpriv(nand_to_mtd(chip));
     79	unsigned int i;
     80
     81	switch (instr->type) {
     82	case NAND_OP_CMD_INSTR:
     83		gpio_nand_dosync(gpiomtd);
     84		gpiod_set_value(gpiomtd->cle, 1);
     85		gpio_nand_dosync(gpiomtd);
     86		writeb(instr->ctx.cmd.opcode, gpiomtd->io);
     87		gpio_nand_dosync(gpiomtd);
     88		gpiod_set_value(gpiomtd->cle, 0);
     89		return 0;
     90
     91	case NAND_OP_ADDR_INSTR:
     92		gpio_nand_dosync(gpiomtd);
     93		gpiod_set_value(gpiomtd->ale, 1);
     94		gpio_nand_dosync(gpiomtd);
     95		for (i = 0; i < instr->ctx.addr.naddrs; i++)
     96			writeb(instr->ctx.addr.addrs[i], gpiomtd->io);
     97		gpio_nand_dosync(gpiomtd);
     98		gpiod_set_value(gpiomtd->ale, 0);
     99		return 0;
    100
    101	case NAND_OP_DATA_IN_INSTR:
    102		gpio_nand_dosync(gpiomtd);
    103		if ((chip->options & NAND_BUSWIDTH_16) &&
    104		    !instr->ctx.data.force_8bit)
    105			ioread16_rep(gpiomtd->io, instr->ctx.data.buf.in,
    106				     instr->ctx.data.len / 2);
    107		else
    108			ioread8_rep(gpiomtd->io, instr->ctx.data.buf.in,
    109				    instr->ctx.data.len);
    110		return 0;
    111
    112	case NAND_OP_DATA_OUT_INSTR:
    113		gpio_nand_dosync(gpiomtd);
    114		if ((chip->options & NAND_BUSWIDTH_16) &&
    115		    !instr->ctx.data.force_8bit)
    116			iowrite16_rep(gpiomtd->io, instr->ctx.data.buf.out,
    117				      instr->ctx.data.len / 2);
    118		else
    119			iowrite8_rep(gpiomtd->io, instr->ctx.data.buf.out,
    120				     instr->ctx.data.len);
    121		return 0;
    122
    123	case NAND_OP_WAITRDY_INSTR:
    124		if (!gpiomtd->rdy)
    125			return nand_soft_waitrdy(chip, instr->ctx.waitrdy.timeout_ms);
    126
    127		return nand_gpio_waitrdy(chip, gpiomtd->rdy,
    128					 instr->ctx.waitrdy.timeout_ms);
    129
    130	default:
    131		return -EINVAL;
    132	}
    133
    134	return 0;
    135}
    136
    137static int gpio_nand_exec_op(struct nand_chip *chip,
    138			     const struct nand_operation *op,
    139			     bool check_only)
    140{
    141	struct gpiomtd *gpiomtd = gpio_nand_getpriv(nand_to_mtd(chip));
    142	unsigned int i;
    143	int ret = 0;
    144
    145	if (check_only)
    146		return 0;
    147
    148	gpio_nand_dosync(gpiomtd);
    149	gpiod_set_value(gpiomtd->nce, 0);
    150	for (i = 0; i < op->ninstrs; i++) {
    151		ret = gpio_nand_exec_instr(chip, &op->instrs[i]);
    152		if (ret)
    153			break;
    154
    155		if (op->instrs[i].delay_ns)
    156			ndelay(op->instrs[i].delay_ns);
    157	}
    158	gpio_nand_dosync(gpiomtd);
    159	gpiod_set_value(gpiomtd->nce, 1);
    160
    161	return ret;
    162}
    163
    164static int gpio_nand_attach_chip(struct nand_chip *chip)
    165{
    166	if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT &&
    167	    chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN)
    168		chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
    169
    170	return 0;
    171}
    172
    173static const struct nand_controller_ops gpio_nand_ops = {
    174	.exec_op = gpio_nand_exec_op,
    175	.attach_chip = gpio_nand_attach_chip,
    176};
    177
    178#ifdef CONFIG_OF
    179static const struct of_device_id gpio_nand_id_table[] = {
    180	{ .compatible = "gpio-control-nand" },
    181	{}
    182};
    183MODULE_DEVICE_TABLE(of, gpio_nand_id_table);
    184
    185static int gpio_nand_get_config_of(const struct device *dev,
    186				   struct gpio_nand_platdata *plat)
    187{
    188	u32 val;
    189
    190	if (!dev->of_node)
    191		return -ENODEV;
    192
    193	if (!of_property_read_u32(dev->of_node, "bank-width", &val)) {
    194		if (val == 2) {
    195			plat->options |= NAND_BUSWIDTH_16;
    196		} else if (val != 1) {
    197			dev_err(dev, "invalid bank-width %u\n", val);
    198			return -EINVAL;
    199		}
    200	}
    201
    202	if (!of_property_read_u32(dev->of_node, "chip-delay", &val))
    203		plat->chip_delay = val;
    204
    205	return 0;
    206}
    207
    208static struct resource *gpio_nand_get_io_sync_of(struct platform_device *pdev)
    209{
    210	struct resource *r;
    211	u64 addr;
    212
    213	if (of_property_read_u64(pdev->dev.of_node,
    214				       "gpio-control-nand,io-sync-reg", &addr))
    215		return NULL;
    216
    217	r = devm_kzalloc(&pdev->dev, sizeof(*r), GFP_KERNEL);
    218	if (!r)
    219		return NULL;
    220
    221	r->start = addr;
    222	r->end = r->start + 0x3;
    223	r->flags = IORESOURCE_MEM;
    224
    225	return r;
    226}
    227#else /* CONFIG_OF */
    228static inline int gpio_nand_get_config_of(const struct device *dev,
    229					  struct gpio_nand_platdata *plat)
    230{
    231	return -ENOSYS;
    232}
    233
    234static inline struct resource *
    235gpio_nand_get_io_sync_of(struct platform_device *pdev)
    236{
    237	return NULL;
    238}
    239#endif /* CONFIG_OF */
    240
    241static inline int gpio_nand_get_config(const struct device *dev,
    242				       struct gpio_nand_platdata *plat)
    243{
    244	int ret = gpio_nand_get_config_of(dev, plat);
    245
    246	if (!ret)
    247		return ret;
    248
    249	if (dev_get_platdata(dev)) {
    250		memcpy(plat, dev_get_platdata(dev), sizeof(*plat));
    251		return 0;
    252	}
    253
    254	return -EINVAL;
    255}
    256
    257static inline struct resource *
    258gpio_nand_get_io_sync(struct platform_device *pdev)
    259{
    260	struct resource *r = gpio_nand_get_io_sync_of(pdev);
    261
    262	if (r)
    263		return r;
    264
    265	return platform_get_resource(pdev, IORESOURCE_MEM, 1);
    266}
    267
    268static int gpio_nand_remove(struct platform_device *pdev)
    269{
    270	struct gpiomtd *gpiomtd = platform_get_drvdata(pdev);
    271	struct nand_chip *chip = &gpiomtd->nand_chip;
    272	int ret;
    273
    274	ret = mtd_device_unregister(nand_to_mtd(chip));
    275	WARN_ON(ret);
    276	nand_cleanup(chip);
    277
    278	/* Enable write protection and disable the chip */
    279	if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp))
    280		gpiod_set_value(gpiomtd->nwp, 0);
    281	if (gpiomtd->nce && !IS_ERR(gpiomtd->nce))
    282		gpiod_set_value(gpiomtd->nce, 0);
    283
    284	return 0;
    285}
    286
    287static int gpio_nand_probe(struct platform_device *pdev)
    288{
    289	struct gpiomtd *gpiomtd;
    290	struct nand_chip *chip;
    291	struct mtd_info *mtd;
    292	struct resource *res;
    293	struct device *dev = &pdev->dev;
    294	int ret = 0;
    295
    296	if (!dev->of_node && !dev_get_platdata(dev))
    297		return -EINVAL;
    298
    299	gpiomtd = devm_kzalloc(dev, sizeof(*gpiomtd), GFP_KERNEL);
    300	if (!gpiomtd)
    301		return -ENOMEM;
    302
    303	chip = &gpiomtd->nand_chip;
    304
    305	gpiomtd->io = devm_platform_ioremap_resource(pdev, 0);
    306	if (IS_ERR(gpiomtd->io))
    307		return PTR_ERR(gpiomtd->io);
    308
    309	res = gpio_nand_get_io_sync(pdev);
    310	if (res) {
    311		gpiomtd->io_sync = devm_ioremap_resource(dev, res);
    312		if (IS_ERR(gpiomtd->io_sync))
    313			return PTR_ERR(gpiomtd->io_sync);
    314	}
    315
    316	ret = gpio_nand_get_config(dev, &gpiomtd->plat);
    317	if (ret)
    318		return ret;
    319
    320	/* Just enable the chip */
    321	gpiomtd->nce = devm_gpiod_get_optional(dev, "nce", GPIOD_OUT_HIGH);
    322	if (IS_ERR(gpiomtd->nce))
    323		return PTR_ERR(gpiomtd->nce);
    324
    325	/* We disable write protection once we know probe() will succeed */
    326	gpiomtd->nwp = devm_gpiod_get_optional(dev, "nwp", GPIOD_OUT_LOW);
    327	if (IS_ERR(gpiomtd->nwp)) {
    328		ret = PTR_ERR(gpiomtd->nwp);
    329		goto out_ce;
    330	}
    331
    332	gpiomtd->ale = devm_gpiod_get(dev, "ale", GPIOD_OUT_LOW);
    333	if (IS_ERR(gpiomtd->ale)) {
    334		ret = PTR_ERR(gpiomtd->ale);
    335		goto out_ce;
    336	}
    337
    338	gpiomtd->cle = devm_gpiod_get(dev, "cle", GPIOD_OUT_LOW);
    339	if (IS_ERR(gpiomtd->cle)) {
    340		ret = PTR_ERR(gpiomtd->cle);
    341		goto out_ce;
    342	}
    343
    344	gpiomtd->rdy = devm_gpiod_get_optional(dev, "rdy", GPIOD_IN);
    345	if (IS_ERR(gpiomtd->rdy)) {
    346		ret = PTR_ERR(gpiomtd->rdy);
    347		goto out_ce;
    348	}
    349
    350	nand_controller_init(&gpiomtd->base);
    351	gpiomtd->base.ops = &gpio_nand_ops;
    352
    353	nand_set_flash_node(chip, pdev->dev.of_node);
    354	chip->options		= gpiomtd->plat.options;
    355	chip->controller	= &gpiomtd->base;
    356
    357	mtd			= nand_to_mtd(chip);
    358	mtd->dev.parent		= dev;
    359
    360	platform_set_drvdata(pdev, gpiomtd);
    361
    362	/* Disable write protection, if wired up */
    363	if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp))
    364		gpiod_direction_output(gpiomtd->nwp, 1);
    365
    366	/*
    367	 * This driver assumes that the default ECC engine should be TYPE_SOFT.
    368	 * Set ->engine_type before registering the NAND devices in order to
    369	 * provide a driver specific default value.
    370	 */
    371	chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
    372
    373	ret = nand_scan(chip, 1);
    374	if (ret)
    375		goto err_wp;
    376
    377	if (gpiomtd->plat.adjust_parts)
    378		gpiomtd->plat.adjust_parts(&gpiomtd->plat, mtd->size);
    379
    380	ret = mtd_device_register(mtd, gpiomtd->plat.parts,
    381				  gpiomtd->plat.num_parts);
    382	if (!ret)
    383		return 0;
    384
    385err_wp:
    386	if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp))
    387		gpiod_set_value(gpiomtd->nwp, 0);
    388out_ce:
    389	if (gpiomtd->nce && !IS_ERR(gpiomtd->nce))
    390		gpiod_set_value(gpiomtd->nce, 0);
    391
    392	return ret;
    393}
    394
    395static struct platform_driver gpio_nand_driver = {
    396	.probe		= gpio_nand_probe,
    397	.remove		= gpio_nand_remove,
    398	.driver		= {
    399		.name	= "gpio-nand",
    400		.of_match_table = of_match_ptr(gpio_nand_id_table),
    401	},
    402};
    403
    404module_platform_driver(gpio_nand_driver);
    405
    406MODULE_LICENSE("GPL");
    407MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
    408MODULE_DESCRIPTION("GPIO NAND Driver");