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

txx9ndfmc.c (11554B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * TXx9 NAND flash memory controller driver
      4 * Based on RBTX49xx patch from CELF patch archive.
      5 *
      6 * (C) Copyright TOSHIBA CORPORATION 2004-2007
      7 * All Rights Reserved.
      8 */
      9#include <linux/err.h>
     10#include <linux/init.h>
     11#include <linux/slab.h>
     12#include <linux/module.h>
     13#include <linux/platform_device.h>
     14#include <linux/delay.h>
     15#include <linux/mtd/mtd.h>
     16#include <linux/mtd/rawnand.h>
     17#include <linux/mtd/partitions.h>
     18#include <linux/io.h>
     19#include <linux/platform_data/txx9/ndfmc.h>
     20
     21/* TXX9 NDFMC Registers */
     22#define TXX9_NDFDTR	0x00
     23#define TXX9_NDFMCR	0x04
     24#define TXX9_NDFSR	0x08
     25#define TXX9_NDFISR	0x0c
     26#define TXX9_NDFIMR	0x10
     27#define TXX9_NDFSPR	0x14
     28#define TXX9_NDFRSTR	0x18	/* not TX4939 */
     29
     30/* NDFMCR : NDFMC Mode Control */
     31#define TXX9_NDFMCR_WE	0x80
     32#define TXX9_NDFMCR_ECC_ALL	0x60
     33#define TXX9_NDFMCR_ECC_RESET	0x60
     34#define TXX9_NDFMCR_ECC_READ	0x40
     35#define TXX9_NDFMCR_ECC_ON	0x20
     36#define TXX9_NDFMCR_ECC_OFF	0x00
     37#define TXX9_NDFMCR_CE	0x10
     38#define TXX9_NDFMCR_BSPRT	0x04	/* TX4925/TX4926 only */
     39#define TXX9_NDFMCR_ALE	0x02
     40#define TXX9_NDFMCR_CLE	0x01
     41/* TX4939 only */
     42#define TXX9_NDFMCR_X16	0x0400
     43#define TXX9_NDFMCR_DMAREQ_MASK	0x0300
     44#define TXX9_NDFMCR_DMAREQ_NODMA	0x0000
     45#define TXX9_NDFMCR_DMAREQ_128	0x0100
     46#define TXX9_NDFMCR_DMAREQ_256	0x0200
     47#define TXX9_NDFMCR_DMAREQ_512	0x0300
     48#define TXX9_NDFMCR_CS_MASK	0x0c
     49#define TXX9_NDFMCR_CS(ch)	((ch) << 2)
     50
     51/* NDFMCR : NDFMC Status */
     52#define TXX9_NDFSR_BUSY	0x80
     53/* TX4939 only */
     54#define TXX9_NDFSR_DMARUN	0x40
     55
     56/* NDFMCR : NDFMC Reset */
     57#define TXX9_NDFRSTR_RST	0x01
     58
     59struct txx9ndfmc_priv {
     60	struct platform_device *dev;
     61	struct nand_chip chip;
     62	int cs;
     63	const char *mtdname;
     64};
     65
     66#define MAX_TXX9NDFMC_DEV	4
     67struct txx9ndfmc_drvdata {
     68	struct mtd_info *mtds[MAX_TXX9NDFMC_DEV];
     69	void __iomem *base;
     70	unsigned char hold;	/* in gbusclock */
     71	unsigned char spw;	/* in gbusclock */
     72	struct nand_controller controller;
     73};
     74
     75static struct platform_device *mtd_to_platdev(struct mtd_info *mtd)
     76{
     77	struct nand_chip *chip = mtd_to_nand(mtd);
     78	struct txx9ndfmc_priv *txx9_priv = nand_get_controller_data(chip);
     79	return txx9_priv->dev;
     80}
     81
     82static void __iomem *ndregaddr(struct platform_device *dev, unsigned int reg)
     83{
     84	struct txx9ndfmc_drvdata *drvdata = platform_get_drvdata(dev);
     85	struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev);
     86
     87	return drvdata->base + (reg << plat->shift);
     88}
     89
     90static u32 txx9ndfmc_read(struct platform_device *dev, unsigned int reg)
     91{
     92	return __raw_readl(ndregaddr(dev, reg));
     93}
     94
     95static void txx9ndfmc_write(struct platform_device *dev,
     96			    u32 val, unsigned int reg)
     97{
     98	__raw_writel(val, ndregaddr(dev, reg));
     99}
    100
    101static uint8_t txx9ndfmc_read_byte(struct nand_chip *chip)
    102{
    103	struct platform_device *dev = mtd_to_platdev(nand_to_mtd(chip));
    104
    105	return txx9ndfmc_read(dev, TXX9_NDFDTR);
    106}
    107
    108static void txx9ndfmc_write_buf(struct nand_chip *chip, const uint8_t *buf,
    109				int len)
    110{
    111	struct platform_device *dev = mtd_to_platdev(nand_to_mtd(chip));
    112	void __iomem *ndfdtr = ndregaddr(dev, TXX9_NDFDTR);
    113	u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR);
    114
    115	txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_WE, TXX9_NDFMCR);
    116	while (len--)
    117		__raw_writel(*buf++, ndfdtr);
    118	txx9ndfmc_write(dev, mcr, TXX9_NDFMCR);
    119}
    120
    121static void txx9ndfmc_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
    122{
    123	struct platform_device *dev = mtd_to_platdev(nand_to_mtd(chip));
    124	void __iomem *ndfdtr = ndregaddr(dev, TXX9_NDFDTR);
    125
    126	while (len--)
    127		*buf++ = __raw_readl(ndfdtr);
    128}
    129
    130static void txx9ndfmc_cmd_ctrl(struct nand_chip *chip, int cmd,
    131			       unsigned int ctrl)
    132{
    133	struct txx9ndfmc_priv *txx9_priv = nand_get_controller_data(chip);
    134	struct platform_device *dev = txx9_priv->dev;
    135	struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev);
    136
    137	if (ctrl & NAND_CTRL_CHANGE) {
    138		u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR);
    139
    140		mcr &= ~(TXX9_NDFMCR_CLE | TXX9_NDFMCR_ALE | TXX9_NDFMCR_CE);
    141		mcr |= ctrl & NAND_CLE ? TXX9_NDFMCR_CLE : 0;
    142		mcr |= ctrl & NAND_ALE ? TXX9_NDFMCR_ALE : 0;
    143		/* TXX9_NDFMCR_CE bit is 0:high 1:low */
    144		mcr |= ctrl & NAND_NCE ? TXX9_NDFMCR_CE : 0;
    145		if (txx9_priv->cs >= 0 && (ctrl & NAND_NCE)) {
    146			mcr &= ~TXX9_NDFMCR_CS_MASK;
    147			mcr |= TXX9_NDFMCR_CS(txx9_priv->cs);
    148		}
    149		txx9ndfmc_write(dev, mcr, TXX9_NDFMCR);
    150	}
    151	if (cmd != NAND_CMD_NONE)
    152		txx9ndfmc_write(dev, cmd & 0xff, TXX9_NDFDTR);
    153	if (plat->flags & NDFMC_PLAT_FLAG_DUMMYWRITE) {
    154		/* dummy write to update external latch */
    155		if ((ctrl & NAND_CTRL_CHANGE) && cmd == NAND_CMD_NONE)
    156			txx9ndfmc_write(dev, 0, TXX9_NDFDTR);
    157	}
    158}
    159
    160static int txx9ndfmc_dev_ready(struct nand_chip *chip)
    161{
    162	struct platform_device *dev = mtd_to_platdev(nand_to_mtd(chip));
    163
    164	return !(txx9ndfmc_read(dev, TXX9_NDFSR) & TXX9_NDFSR_BUSY);
    165}
    166
    167static int txx9ndfmc_calculate_ecc(struct nand_chip *chip, const uint8_t *dat,
    168				   uint8_t *ecc_code)
    169{
    170	struct platform_device *dev = mtd_to_platdev(nand_to_mtd(chip));
    171	int eccbytes;
    172	u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR);
    173
    174	mcr &= ~TXX9_NDFMCR_ECC_ALL;
    175	txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_OFF, TXX9_NDFMCR);
    176	txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_READ, TXX9_NDFMCR);
    177	for (eccbytes = chip->ecc.bytes; eccbytes > 0; eccbytes -= 3) {
    178		ecc_code[1] = txx9ndfmc_read(dev, TXX9_NDFDTR);
    179		ecc_code[0] = txx9ndfmc_read(dev, TXX9_NDFDTR);
    180		ecc_code[2] = txx9ndfmc_read(dev, TXX9_NDFDTR);
    181		ecc_code += 3;
    182	}
    183	txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_OFF, TXX9_NDFMCR);
    184	return 0;
    185}
    186
    187static int txx9ndfmc_correct_data(struct nand_chip *chip, unsigned char *buf,
    188				  unsigned char *read_ecc,
    189				  unsigned char *calc_ecc)
    190{
    191	int eccsize;
    192	int corrected = 0;
    193	int stat;
    194
    195	for (eccsize = chip->ecc.size; eccsize > 0; eccsize -= 256) {
    196		stat = rawnand_sw_hamming_correct(chip, buf, read_ecc,
    197						  calc_ecc);
    198		if (stat < 0)
    199			return stat;
    200		corrected += stat;
    201		buf += 256;
    202		read_ecc += 3;
    203		calc_ecc += 3;
    204	}
    205	return corrected;
    206}
    207
    208static void txx9ndfmc_enable_hwecc(struct nand_chip *chip, int mode)
    209{
    210	struct platform_device *dev = mtd_to_platdev(nand_to_mtd(chip));
    211	u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR);
    212
    213	mcr &= ~TXX9_NDFMCR_ECC_ALL;
    214	txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_RESET, TXX9_NDFMCR);
    215	txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_OFF, TXX9_NDFMCR);
    216	txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_ON, TXX9_NDFMCR);
    217}
    218
    219static void txx9ndfmc_initialize(struct platform_device *dev)
    220{
    221	struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev);
    222	struct txx9ndfmc_drvdata *drvdata = platform_get_drvdata(dev);
    223	int tmout = 100;
    224
    225	if (plat->flags & NDFMC_PLAT_FLAG_NO_RSTR)
    226		; /* no NDFRSTR.  Write to NDFSPR resets the NDFMC. */
    227	else {
    228		/* reset NDFMC */
    229		txx9ndfmc_write(dev,
    230				txx9ndfmc_read(dev, TXX9_NDFRSTR) |
    231				TXX9_NDFRSTR_RST,
    232				TXX9_NDFRSTR);
    233		while (txx9ndfmc_read(dev, TXX9_NDFRSTR) & TXX9_NDFRSTR_RST) {
    234			if (--tmout == 0) {
    235				dev_err(&dev->dev, "reset failed.\n");
    236				break;
    237			}
    238			udelay(1);
    239		}
    240	}
    241	/* setup Hold Time, Strobe Pulse Width */
    242	txx9ndfmc_write(dev, (drvdata->hold << 4) | drvdata->spw, TXX9_NDFSPR);
    243	txx9ndfmc_write(dev,
    244			(plat->flags & NDFMC_PLAT_FLAG_USE_BSPRT) ?
    245			TXX9_NDFMCR_BSPRT : 0, TXX9_NDFMCR);
    246}
    247
    248#define TXX9NDFMC_NS_TO_CYC(gbusclk, ns) \
    249	DIV_ROUND_UP((ns) * DIV_ROUND_UP(gbusclk, 1000), 1000000)
    250
    251static int txx9ndfmc_attach_chip(struct nand_chip *chip)
    252{
    253	struct mtd_info *mtd = nand_to_mtd(chip);
    254
    255	if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
    256		return 0;
    257
    258	chip->ecc.strength = 1;
    259
    260	if (mtd->writesize >= 512) {
    261		chip->ecc.size = 512;
    262		chip->ecc.bytes = 6;
    263	} else {
    264		chip->ecc.size = 256;
    265		chip->ecc.bytes = 3;
    266	}
    267
    268	chip->ecc.calculate = txx9ndfmc_calculate_ecc;
    269	chip->ecc.correct = txx9ndfmc_correct_data;
    270	chip->ecc.hwctl = txx9ndfmc_enable_hwecc;
    271
    272	return 0;
    273}
    274
    275static const struct nand_controller_ops txx9ndfmc_controller_ops = {
    276	.attach_chip = txx9ndfmc_attach_chip,
    277};
    278
    279static int __init txx9ndfmc_probe(struct platform_device *dev)
    280{
    281	struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev);
    282	int hold, spw;
    283	int i;
    284	struct txx9ndfmc_drvdata *drvdata;
    285	unsigned long gbusclk = plat->gbus_clock;
    286
    287	drvdata = devm_kzalloc(&dev->dev, sizeof(*drvdata), GFP_KERNEL);
    288	if (!drvdata)
    289		return -ENOMEM;
    290	drvdata->base = devm_platform_ioremap_resource(dev, 0);
    291	if (IS_ERR(drvdata->base))
    292		return PTR_ERR(drvdata->base);
    293
    294	hold = plat->hold ?: 20; /* tDH */
    295	spw = plat->spw ?: 90; /* max(tREADID, tWP, tRP) */
    296
    297	hold = TXX9NDFMC_NS_TO_CYC(gbusclk, hold);
    298	spw = TXX9NDFMC_NS_TO_CYC(gbusclk, spw);
    299	if (plat->flags & NDFMC_PLAT_FLAG_HOLDADD)
    300		hold -= 2;	/* actual hold time : (HOLD + 2) BUSCLK */
    301	spw -= 1;	/* actual wait time : (SPW + 1) BUSCLK */
    302	hold = clamp(hold, 1, 15);
    303	drvdata->hold = hold;
    304	spw = clamp(spw, 1, 15);
    305	drvdata->spw = spw;
    306	dev_info(&dev->dev, "CLK:%ldMHz HOLD:%d SPW:%d\n",
    307		 (gbusclk + 500000) / 1000000, hold, spw);
    308
    309	nand_controller_init(&drvdata->controller);
    310	drvdata->controller.ops = &txx9ndfmc_controller_ops;
    311
    312	platform_set_drvdata(dev, drvdata);
    313	txx9ndfmc_initialize(dev);
    314
    315	for (i = 0; i < MAX_TXX9NDFMC_DEV; i++) {
    316		struct txx9ndfmc_priv *txx9_priv;
    317		struct nand_chip *chip;
    318		struct mtd_info *mtd;
    319
    320		if (!(plat->ch_mask & (1 << i)))
    321			continue;
    322		txx9_priv = kzalloc(sizeof(struct txx9ndfmc_priv),
    323				    GFP_KERNEL);
    324		if (!txx9_priv)
    325			continue;
    326		chip = &txx9_priv->chip;
    327		mtd = nand_to_mtd(chip);
    328		mtd->dev.parent = &dev->dev;
    329
    330		chip->legacy.read_byte = txx9ndfmc_read_byte;
    331		chip->legacy.read_buf = txx9ndfmc_read_buf;
    332		chip->legacy.write_buf = txx9ndfmc_write_buf;
    333		chip->legacy.cmd_ctrl = txx9ndfmc_cmd_ctrl;
    334		chip->legacy.dev_ready = txx9ndfmc_dev_ready;
    335		chip->legacy.chip_delay = 100;
    336		chip->controller = &drvdata->controller;
    337
    338		nand_set_controller_data(chip, txx9_priv);
    339		txx9_priv->dev = dev;
    340
    341		if (plat->ch_mask != 1) {
    342			txx9_priv->cs = i;
    343			txx9_priv->mtdname = kasprintf(GFP_KERNEL, "%s.%u",
    344						       dev_name(&dev->dev), i);
    345		} else {
    346			txx9_priv->cs = -1;
    347			txx9_priv->mtdname = kstrdup(dev_name(&dev->dev),
    348						     GFP_KERNEL);
    349		}
    350		if (!txx9_priv->mtdname) {
    351			kfree(txx9_priv);
    352			dev_err(&dev->dev, "Unable to allocate MTD name.\n");
    353			continue;
    354		}
    355		if (plat->wide_mask & (1 << i))
    356			chip->options |= NAND_BUSWIDTH_16;
    357
    358		if (nand_scan(chip, 1)) {
    359			kfree(txx9_priv->mtdname);
    360			kfree(txx9_priv);
    361			continue;
    362		}
    363		mtd->name = txx9_priv->mtdname;
    364
    365		mtd_device_register(mtd, NULL, 0);
    366		drvdata->mtds[i] = mtd;
    367	}
    368
    369	return 0;
    370}
    371
    372static int __exit txx9ndfmc_remove(struct platform_device *dev)
    373{
    374	struct txx9ndfmc_drvdata *drvdata = platform_get_drvdata(dev);
    375	int ret, i;
    376
    377	if (!drvdata)
    378		return 0;
    379	for (i = 0; i < MAX_TXX9NDFMC_DEV; i++) {
    380		struct mtd_info *mtd = drvdata->mtds[i];
    381		struct nand_chip *chip;
    382		struct txx9ndfmc_priv *txx9_priv;
    383
    384		if (!mtd)
    385			continue;
    386		chip = mtd_to_nand(mtd);
    387		txx9_priv = nand_get_controller_data(chip);
    388
    389		ret = mtd_device_unregister(nand_to_mtd(chip));
    390		WARN_ON(ret);
    391		nand_cleanup(chip);
    392		kfree(txx9_priv->mtdname);
    393		kfree(txx9_priv);
    394	}
    395	return 0;
    396}
    397
    398#ifdef CONFIG_PM
    399static int txx9ndfmc_resume(struct platform_device *dev)
    400{
    401	if (platform_get_drvdata(dev))
    402		txx9ndfmc_initialize(dev);
    403	return 0;
    404}
    405#else
    406#define txx9ndfmc_resume NULL
    407#endif
    408
    409static struct platform_driver txx9ndfmc_driver = {
    410	.remove		= __exit_p(txx9ndfmc_remove),
    411	.resume		= txx9ndfmc_resume,
    412	.driver		= {
    413		.name	= "txx9ndfmc",
    414	},
    415};
    416
    417module_platform_driver_probe(txx9ndfmc_driver, txx9ndfmc_probe);
    418
    419MODULE_LICENSE("GPL");
    420MODULE_DESCRIPTION("TXx9 SoC NAND flash controller driver");
    421MODULE_ALIAS("platform:txx9ndfmc");