1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 264fb65baSAtsushi Nemoto /* 364fb65baSAtsushi Nemoto * TXx9 NAND flash memory controller driver 464fb65baSAtsushi Nemoto * Based on RBTX49xx patch from CELF patch archive. 564fb65baSAtsushi Nemoto * 664fb65baSAtsushi Nemoto * (C) Copyright TOSHIBA CORPORATION 2004-2007 764fb65baSAtsushi Nemoto * All Rights Reserved. 864fb65baSAtsushi Nemoto */ 9b0de774cSThierry Reding #include <linux/err.h> 1064fb65baSAtsushi Nemoto #include <linux/init.h> 1164fb65baSAtsushi Nemoto #include <linux/slab.h> 1264fb65baSAtsushi Nemoto #include <linux/module.h> 1364fb65baSAtsushi Nemoto #include <linux/platform_device.h> 1464fb65baSAtsushi Nemoto #include <linux/delay.h> 1564fb65baSAtsushi Nemoto #include <linux/mtd/mtd.h> 16d4092d76SBoris Brezillon #include <linux/mtd/rawnand.h> 1764fb65baSAtsushi Nemoto #include <linux/mtd/partitions.h> 1864fb65baSAtsushi Nemoto #include <linux/io.h> 19dc2865acSBoris Brezillon #include <linux/platform_data/txx9/ndfmc.h> 2064fb65baSAtsushi Nemoto 2164fb65baSAtsushi Nemoto /* TXX9 NDFMC Registers */ 2264fb65baSAtsushi Nemoto #define TXX9_NDFDTR 0x00 2364fb65baSAtsushi Nemoto #define TXX9_NDFMCR 0x04 2464fb65baSAtsushi Nemoto #define TXX9_NDFSR 0x08 2564fb65baSAtsushi Nemoto #define TXX9_NDFISR 0x0c 2664fb65baSAtsushi Nemoto #define TXX9_NDFIMR 0x10 2764fb65baSAtsushi Nemoto #define TXX9_NDFSPR 0x14 2864fb65baSAtsushi Nemoto #define TXX9_NDFRSTR 0x18 /* not TX4939 */ 2964fb65baSAtsushi Nemoto 3064fb65baSAtsushi Nemoto /* NDFMCR : NDFMC Mode Control */ 3164fb65baSAtsushi Nemoto #define TXX9_NDFMCR_WE 0x80 3264fb65baSAtsushi Nemoto #define TXX9_NDFMCR_ECC_ALL 0x60 3364fb65baSAtsushi Nemoto #define TXX9_NDFMCR_ECC_RESET 0x60 3464fb65baSAtsushi Nemoto #define TXX9_NDFMCR_ECC_READ 0x40 3564fb65baSAtsushi Nemoto #define TXX9_NDFMCR_ECC_ON 0x20 3664fb65baSAtsushi Nemoto #define TXX9_NDFMCR_ECC_OFF 0x00 3764fb65baSAtsushi Nemoto #define TXX9_NDFMCR_CE 0x10 3864fb65baSAtsushi Nemoto #define TXX9_NDFMCR_BSPRT 0x04 /* TX4925/TX4926 only */ 3964fb65baSAtsushi Nemoto #define TXX9_NDFMCR_ALE 0x02 4064fb65baSAtsushi Nemoto #define TXX9_NDFMCR_CLE 0x01 4164fb65baSAtsushi Nemoto /* TX4939 only */ 4264fb65baSAtsushi Nemoto #define TXX9_NDFMCR_X16 0x0400 4364fb65baSAtsushi Nemoto #define TXX9_NDFMCR_DMAREQ_MASK 0x0300 4464fb65baSAtsushi Nemoto #define TXX9_NDFMCR_DMAREQ_NODMA 0x0000 4564fb65baSAtsushi Nemoto #define TXX9_NDFMCR_DMAREQ_128 0x0100 4664fb65baSAtsushi Nemoto #define TXX9_NDFMCR_DMAREQ_256 0x0200 4764fb65baSAtsushi Nemoto #define TXX9_NDFMCR_DMAREQ_512 0x0300 4864fb65baSAtsushi Nemoto #define TXX9_NDFMCR_CS_MASK 0x0c 4964fb65baSAtsushi Nemoto #define TXX9_NDFMCR_CS(ch) ((ch) << 2) 5064fb65baSAtsushi Nemoto 5164fb65baSAtsushi Nemoto /* NDFMCR : NDFMC Status */ 5264fb65baSAtsushi Nemoto #define TXX9_NDFSR_BUSY 0x80 5364fb65baSAtsushi Nemoto /* TX4939 only */ 5464fb65baSAtsushi Nemoto #define TXX9_NDFSR_DMARUN 0x40 5564fb65baSAtsushi Nemoto 5664fb65baSAtsushi Nemoto /* NDFMCR : NDFMC Reset */ 5764fb65baSAtsushi Nemoto #define TXX9_NDFRSTR_RST 0x01 5864fb65baSAtsushi Nemoto 5964fb65baSAtsushi Nemoto struct txx9ndfmc_priv { 6064fb65baSAtsushi Nemoto struct platform_device *dev; 6164fb65baSAtsushi Nemoto struct nand_chip chip; 6264fb65baSAtsushi Nemoto int cs; 6381933046SDavid Woodhouse const char *mtdname; 6464fb65baSAtsushi Nemoto }; 6564fb65baSAtsushi Nemoto 6664fb65baSAtsushi Nemoto #define MAX_TXX9NDFMC_DEV 4 6764fb65baSAtsushi Nemoto struct txx9ndfmc_drvdata { 6864fb65baSAtsushi Nemoto struct mtd_info *mtds[MAX_TXX9NDFMC_DEV]; 6964fb65baSAtsushi Nemoto void __iomem *base; 7064fb65baSAtsushi Nemoto unsigned char hold; /* in gbusclock */ 7164fb65baSAtsushi Nemoto unsigned char spw; /* in gbusclock */ 72a001058aSMiquel Raynal struct nand_controller controller; 7364fb65baSAtsushi Nemoto }; 7464fb65baSAtsushi Nemoto 7564fb65baSAtsushi Nemoto static struct platform_device *mtd_to_platdev(struct mtd_info *mtd) 7664fb65baSAtsushi Nemoto { 774bd4ebccSBoris BREZILLON struct nand_chip *chip = mtd_to_nand(mtd); 78d699ed25SBoris BREZILLON struct txx9ndfmc_priv *txx9_priv = nand_get_controller_data(chip); 7964fb65baSAtsushi Nemoto return txx9_priv->dev; 8064fb65baSAtsushi Nemoto } 8164fb65baSAtsushi Nemoto 8264fb65baSAtsushi Nemoto static void __iomem *ndregaddr(struct platform_device *dev, unsigned int reg) 8364fb65baSAtsushi Nemoto { 8464fb65baSAtsushi Nemoto struct txx9ndfmc_drvdata *drvdata = platform_get_drvdata(dev); 85453810b7SJingoo Han struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev); 8664fb65baSAtsushi Nemoto 8764fb65baSAtsushi Nemoto return drvdata->base + (reg << plat->shift); 8864fb65baSAtsushi Nemoto } 8964fb65baSAtsushi Nemoto 9064fb65baSAtsushi Nemoto static u32 txx9ndfmc_read(struct platform_device *dev, unsigned int reg) 9164fb65baSAtsushi Nemoto { 9264fb65baSAtsushi Nemoto return __raw_readl(ndregaddr(dev, reg)); 9364fb65baSAtsushi Nemoto } 9464fb65baSAtsushi Nemoto 9564fb65baSAtsushi Nemoto static void txx9ndfmc_write(struct platform_device *dev, 9664fb65baSAtsushi Nemoto u32 val, unsigned int reg) 9764fb65baSAtsushi Nemoto { 9864fb65baSAtsushi Nemoto __raw_writel(val, ndregaddr(dev, reg)); 9964fb65baSAtsushi Nemoto } 10064fb65baSAtsushi Nemoto 1017e534323SBoris Brezillon static uint8_t txx9ndfmc_read_byte(struct nand_chip *chip) 10264fb65baSAtsushi Nemoto { 1037e534323SBoris Brezillon struct platform_device *dev = mtd_to_platdev(nand_to_mtd(chip)); 10464fb65baSAtsushi Nemoto 10564fb65baSAtsushi Nemoto return txx9ndfmc_read(dev, TXX9_NDFDTR); 10664fb65baSAtsushi Nemoto } 10764fb65baSAtsushi Nemoto 108c0739d85SBoris Brezillon static void txx9ndfmc_write_buf(struct nand_chip *chip, const uint8_t *buf, 10964fb65baSAtsushi Nemoto int len) 11064fb65baSAtsushi Nemoto { 111c0739d85SBoris Brezillon struct platform_device *dev = mtd_to_platdev(nand_to_mtd(chip)); 11264fb65baSAtsushi Nemoto void __iomem *ndfdtr = ndregaddr(dev, TXX9_NDFDTR); 11364fb65baSAtsushi Nemoto u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR); 11464fb65baSAtsushi Nemoto 11564fb65baSAtsushi Nemoto txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_WE, TXX9_NDFMCR); 11664fb65baSAtsushi Nemoto while (len--) 11764fb65baSAtsushi Nemoto __raw_writel(*buf++, ndfdtr); 11864fb65baSAtsushi Nemoto txx9ndfmc_write(dev, mcr, TXX9_NDFMCR); 11964fb65baSAtsushi Nemoto } 12064fb65baSAtsushi Nemoto 1217e534323SBoris Brezillon static void txx9ndfmc_read_buf(struct nand_chip *chip, uint8_t *buf, int len) 12264fb65baSAtsushi Nemoto { 1237e534323SBoris Brezillon struct platform_device *dev = mtd_to_platdev(nand_to_mtd(chip)); 12464fb65baSAtsushi Nemoto void __iomem *ndfdtr = ndregaddr(dev, TXX9_NDFDTR); 12564fb65baSAtsushi Nemoto 12664fb65baSAtsushi Nemoto while (len--) 12764fb65baSAtsushi Nemoto *buf++ = __raw_readl(ndfdtr); 12864fb65baSAtsushi Nemoto } 12964fb65baSAtsushi Nemoto 1300f808c16SBoris Brezillon static void txx9ndfmc_cmd_ctrl(struct nand_chip *chip, int cmd, 13164fb65baSAtsushi Nemoto unsigned int ctrl) 13264fb65baSAtsushi Nemoto { 133d699ed25SBoris BREZILLON struct txx9ndfmc_priv *txx9_priv = nand_get_controller_data(chip); 13464fb65baSAtsushi Nemoto struct platform_device *dev = txx9_priv->dev; 135453810b7SJingoo Han struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev); 13664fb65baSAtsushi Nemoto 13764fb65baSAtsushi Nemoto if (ctrl & NAND_CTRL_CHANGE) { 13864fb65baSAtsushi Nemoto u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR); 13964fb65baSAtsushi Nemoto 14064fb65baSAtsushi Nemoto mcr &= ~(TXX9_NDFMCR_CLE | TXX9_NDFMCR_ALE | TXX9_NDFMCR_CE); 14164fb65baSAtsushi Nemoto mcr |= ctrl & NAND_CLE ? TXX9_NDFMCR_CLE : 0; 14264fb65baSAtsushi Nemoto mcr |= ctrl & NAND_ALE ? TXX9_NDFMCR_ALE : 0; 14364fb65baSAtsushi Nemoto /* TXX9_NDFMCR_CE bit is 0:high 1:low */ 14464fb65baSAtsushi Nemoto mcr |= ctrl & NAND_NCE ? TXX9_NDFMCR_CE : 0; 14564fb65baSAtsushi Nemoto if (txx9_priv->cs >= 0 && (ctrl & NAND_NCE)) { 14664fb65baSAtsushi Nemoto mcr &= ~TXX9_NDFMCR_CS_MASK; 14764fb65baSAtsushi Nemoto mcr |= TXX9_NDFMCR_CS(txx9_priv->cs); 14864fb65baSAtsushi Nemoto } 14964fb65baSAtsushi Nemoto txx9ndfmc_write(dev, mcr, TXX9_NDFMCR); 15064fb65baSAtsushi Nemoto } 15164fb65baSAtsushi Nemoto if (cmd != NAND_CMD_NONE) 15264fb65baSAtsushi Nemoto txx9ndfmc_write(dev, cmd & 0xff, TXX9_NDFDTR); 15364fb65baSAtsushi Nemoto if (plat->flags & NDFMC_PLAT_FLAG_DUMMYWRITE) { 15464fb65baSAtsushi Nemoto /* dummy write to update external latch */ 15564fb65baSAtsushi Nemoto if ((ctrl & NAND_CTRL_CHANGE) && cmd == NAND_CMD_NONE) 15664fb65baSAtsushi Nemoto txx9ndfmc_write(dev, 0, TXX9_NDFDTR); 15764fb65baSAtsushi Nemoto } 15864fb65baSAtsushi Nemoto } 15964fb65baSAtsushi Nemoto 16050a487e7SBoris Brezillon static int txx9ndfmc_dev_ready(struct nand_chip *chip) 16164fb65baSAtsushi Nemoto { 16250a487e7SBoris Brezillon struct platform_device *dev = mtd_to_platdev(nand_to_mtd(chip)); 16364fb65baSAtsushi Nemoto 16464fb65baSAtsushi Nemoto return !(txx9ndfmc_read(dev, TXX9_NDFSR) & TXX9_NDFSR_BUSY); 16564fb65baSAtsushi Nemoto } 16664fb65baSAtsushi Nemoto 167af37d2c3SBoris Brezillon static int txx9ndfmc_calculate_ecc(struct nand_chip *chip, const uint8_t *dat, 16864fb65baSAtsushi Nemoto uint8_t *ecc_code) 16964fb65baSAtsushi Nemoto { 170af37d2c3SBoris Brezillon struct platform_device *dev = mtd_to_platdev(nand_to_mtd(chip)); 171c0cbfd0eSAtsushi Nemoto int eccbytes; 17264fb65baSAtsushi Nemoto u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR); 17364fb65baSAtsushi Nemoto 17464fb65baSAtsushi Nemoto mcr &= ~TXX9_NDFMCR_ECC_ALL; 17564fb65baSAtsushi Nemoto txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_OFF, TXX9_NDFMCR); 17664fb65baSAtsushi Nemoto txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_READ, TXX9_NDFMCR); 177c0cbfd0eSAtsushi Nemoto for (eccbytes = chip->ecc.bytes; eccbytes > 0; eccbytes -= 3) { 17864fb65baSAtsushi Nemoto ecc_code[1] = txx9ndfmc_read(dev, TXX9_NDFDTR); 17964fb65baSAtsushi Nemoto ecc_code[0] = txx9ndfmc_read(dev, TXX9_NDFDTR); 18064fb65baSAtsushi Nemoto ecc_code[2] = txx9ndfmc_read(dev, TXX9_NDFDTR); 181c0cbfd0eSAtsushi Nemoto ecc_code += 3; 182c0cbfd0eSAtsushi Nemoto } 18364fb65baSAtsushi Nemoto txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_OFF, TXX9_NDFMCR); 18464fb65baSAtsushi Nemoto return 0; 18564fb65baSAtsushi Nemoto } 18664fb65baSAtsushi Nemoto 18700da2ea9SBoris Brezillon static int txx9ndfmc_correct_data(struct nand_chip *chip, unsigned char *buf, 18800da2ea9SBoris Brezillon unsigned char *read_ecc, 18900da2ea9SBoris Brezillon unsigned char *calc_ecc) 190c0cbfd0eSAtsushi Nemoto { 191c0cbfd0eSAtsushi Nemoto int eccsize; 192c0cbfd0eSAtsushi Nemoto int corrected = 0; 193c0cbfd0eSAtsushi Nemoto int stat; 194c0cbfd0eSAtsushi Nemoto 195c0cbfd0eSAtsushi Nemoto for (eccsize = chip->ecc.size; eccsize > 0; eccsize -= 256) { 196e7f466c5SMiquel Raynal stat = rawnand_sw_hamming_correct(chip, buf, read_ecc, 197e7f466c5SMiquel Raynal calc_ecc); 198c0cbfd0eSAtsushi Nemoto if (stat < 0) 199c0cbfd0eSAtsushi Nemoto return stat; 200c0cbfd0eSAtsushi Nemoto corrected += stat; 201c0cbfd0eSAtsushi Nemoto buf += 256; 202c0cbfd0eSAtsushi Nemoto read_ecc += 3; 203c0cbfd0eSAtsushi Nemoto calc_ecc += 3; 204c0cbfd0eSAtsushi Nemoto } 205c0cbfd0eSAtsushi Nemoto return corrected; 206c0cbfd0eSAtsushi Nemoto } 207c0cbfd0eSAtsushi Nemoto 208ec47636cSBoris Brezillon static void txx9ndfmc_enable_hwecc(struct nand_chip *chip, int mode) 20964fb65baSAtsushi Nemoto { 210ec47636cSBoris Brezillon struct platform_device *dev = mtd_to_platdev(nand_to_mtd(chip)); 21164fb65baSAtsushi Nemoto u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR); 21264fb65baSAtsushi Nemoto 21364fb65baSAtsushi Nemoto mcr &= ~TXX9_NDFMCR_ECC_ALL; 21464fb65baSAtsushi Nemoto txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_RESET, TXX9_NDFMCR); 21564fb65baSAtsushi Nemoto txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_OFF, TXX9_NDFMCR); 21664fb65baSAtsushi Nemoto txx9ndfmc_write(dev, mcr | TXX9_NDFMCR_ECC_ON, TXX9_NDFMCR); 21764fb65baSAtsushi Nemoto } 21864fb65baSAtsushi Nemoto 21964fb65baSAtsushi Nemoto static void txx9ndfmc_initialize(struct platform_device *dev) 22064fb65baSAtsushi Nemoto { 221453810b7SJingoo Han struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev); 22264fb65baSAtsushi Nemoto struct txx9ndfmc_drvdata *drvdata = platform_get_drvdata(dev); 22364fb65baSAtsushi Nemoto int tmout = 100; 22464fb65baSAtsushi Nemoto 22564fb65baSAtsushi Nemoto if (plat->flags & NDFMC_PLAT_FLAG_NO_RSTR) 22664fb65baSAtsushi Nemoto ; /* no NDFRSTR. Write to NDFSPR resets the NDFMC. */ 22764fb65baSAtsushi Nemoto else { 22864fb65baSAtsushi Nemoto /* reset NDFMC */ 22964fb65baSAtsushi Nemoto txx9ndfmc_write(dev, 23064fb65baSAtsushi Nemoto txx9ndfmc_read(dev, TXX9_NDFRSTR) | 23164fb65baSAtsushi Nemoto TXX9_NDFRSTR_RST, 23264fb65baSAtsushi Nemoto TXX9_NDFRSTR); 23364fb65baSAtsushi Nemoto while (txx9ndfmc_read(dev, TXX9_NDFRSTR) & TXX9_NDFRSTR_RST) { 23464fb65baSAtsushi Nemoto if (--tmout == 0) { 23564fb65baSAtsushi Nemoto dev_err(&dev->dev, "reset failed.\n"); 23664fb65baSAtsushi Nemoto break; 23764fb65baSAtsushi Nemoto } 23864fb65baSAtsushi Nemoto udelay(1); 23964fb65baSAtsushi Nemoto } 24064fb65baSAtsushi Nemoto } 24164fb65baSAtsushi Nemoto /* setup Hold Time, Strobe Pulse Width */ 24264fb65baSAtsushi Nemoto txx9ndfmc_write(dev, (drvdata->hold << 4) | drvdata->spw, TXX9_NDFSPR); 24364fb65baSAtsushi Nemoto txx9ndfmc_write(dev, 24464fb65baSAtsushi Nemoto (plat->flags & NDFMC_PLAT_FLAG_USE_BSPRT) ? 24564fb65baSAtsushi Nemoto TXX9_NDFMCR_BSPRT : 0, TXX9_NDFMCR); 24664fb65baSAtsushi Nemoto } 24764fb65baSAtsushi Nemoto 24864fb65baSAtsushi Nemoto #define TXX9NDFMC_NS_TO_CYC(gbusclk, ns) \ 24964fb65baSAtsushi Nemoto DIV_ROUND_UP((ns) * DIV_ROUND_UP(gbusclk, 1000), 1000000) 25064fb65baSAtsushi Nemoto 251ee1af829SMiquel Raynal static int txx9ndfmc_attach_chip(struct nand_chip *chip) 252c0cbfd0eSAtsushi Nemoto { 253ee1af829SMiquel Raynal struct mtd_info *mtd = nand_to_mtd(chip); 254c0cbfd0eSAtsushi Nemoto 2553c3bbf01SMiquel Raynal if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST) 2563c3bbf01SMiquel Raynal return 0; 2573c3bbf01SMiquel Raynal 2583c3bbf01SMiquel Raynal chip->ecc.strength = 1; 2593c3bbf01SMiquel Raynal 260c0cbfd0eSAtsushi Nemoto if (mtd->writesize >= 512) { 26124ac9a94SRalf Rösch chip->ecc.size = 512; 26224ac9a94SRalf Rösch chip->ecc.bytes = 6; 263abe23d1cSMiquel Raynal } else { 264abe23d1cSMiquel Raynal chip->ecc.size = 256; 265abe23d1cSMiquel Raynal chip->ecc.bytes = 3; 266c0cbfd0eSAtsushi Nemoto } 267abe23d1cSMiquel Raynal 2683c3bbf01SMiquel Raynal chip->ecc.calculate = txx9ndfmc_calculate_ecc; 2693c3bbf01SMiquel Raynal chip->ecc.correct = txx9ndfmc_correct_data; 2703c3bbf01SMiquel Raynal chip->ecc.hwctl = txx9ndfmc_enable_hwecc; 2713c3bbf01SMiquel Raynal 272ee1af829SMiquel Raynal return 0; 273c0cbfd0eSAtsushi Nemoto } 274ee1af829SMiquel Raynal 275ee1af829SMiquel Raynal static const struct nand_controller_ops txx9ndfmc_controller_ops = { 276ee1af829SMiquel Raynal .attach_chip = txx9ndfmc_attach_chip, 277ee1af829SMiquel Raynal }; 278c0cbfd0eSAtsushi Nemoto 27964fb65baSAtsushi Nemoto static int __init txx9ndfmc_probe(struct platform_device *dev) 28064fb65baSAtsushi Nemoto { 281453810b7SJingoo Han struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev); 28264fb65baSAtsushi Nemoto int hold, spw; 28364fb65baSAtsushi Nemoto int i; 28464fb65baSAtsushi Nemoto struct txx9ndfmc_drvdata *drvdata; 28564fb65baSAtsushi Nemoto unsigned long gbusclk = plat->gbus_clock; 28664fb65baSAtsushi Nemoto 28764fb65baSAtsushi Nemoto drvdata = devm_kzalloc(&dev->dev, sizeof(*drvdata), GFP_KERNEL); 28864fb65baSAtsushi Nemoto if (!drvdata) 28964fb65baSAtsushi Nemoto return -ENOMEM; 290524bd02aSCai Huoqing drvdata->base = devm_platform_ioremap_resource(dev, 0); 291b0de774cSThierry Reding if (IS_ERR(drvdata->base)) 292b0de774cSThierry Reding return PTR_ERR(drvdata->base); 29364fb65baSAtsushi Nemoto 29464fb65baSAtsushi Nemoto hold = plat->hold ?: 20; /* tDH */ 29564fb65baSAtsushi Nemoto spw = plat->spw ?: 90; /* max(tREADID, tWP, tRP) */ 29664fb65baSAtsushi Nemoto 29764fb65baSAtsushi Nemoto hold = TXX9NDFMC_NS_TO_CYC(gbusclk, hold); 29864fb65baSAtsushi Nemoto spw = TXX9NDFMC_NS_TO_CYC(gbusclk, spw); 29964fb65baSAtsushi Nemoto if (plat->flags & NDFMC_PLAT_FLAG_HOLDADD) 30064fb65baSAtsushi Nemoto hold -= 2; /* actual hold time : (HOLD + 2) BUSCLK */ 30164fb65baSAtsushi Nemoto spw -= 1; /* actual wait time : (SPW + 1) BUSCLK */ 30264fb65baSAtsushi Nemoto hold = clamp(hold, 1, 15); 30364fb65baSAtsushi Nemoto drvdata->hold = hold; 30464fb65baSAtsushi Nemoto spw = clamp(spw, 1, 15); 30564fb65baSAtsushi Nemoto drvdata->spw = spw; 30664fb65baSAtsushi Nemoto dev_info(&dev->dev, "CLK:%ldMHz HOLD:%d SPW:%d\n", 30764fb65baSAtsushi Nemoto (gbusclk + 500000) / 1000000, hold, spw); 30864fb65baSAtsushi Nemoto 309a001058aSMiquel Raynal nand_controller_init(&drvdata->controller); 310ee1af829SMiquel Raynal drvdata->controller.ops = &txx9ndfmc_controller_ops; 31164fb65baSAtsushi Nemoto 31264fb65baSAtsushi Nemoto platform_set_drvdata(dev, drvdata); 31364fb65baSAtsushi Nemoto txx9ndfmc_initialize(dev); 31464fb65baSAtsushi Nemoto 31564fb65baSAtsushi Nemoto for (i = 0; i < MAX_TXX9NDFMC_DEV; i++) { 31664fb65baSAtsushi Nemoto struct txx9ndfmc_priv *txx9_priv; 31764fb65baSAtsushi Nemoto struct nand_chip *chip; 31864fb65baSAtsushi Nemoto struct mtd_info *mtd; 31964fb65baSAtsushi Nemoto 32064fb65baSAtsushi Nemoto if (!(plat->ch_mask & (1 << i))) 32164fb65baSAtsushi Nemoto continue; 32264fb65baSAtsushi Nemoto txx9_priv = kzalloc(sizeof(struct txx9ndfmc_priv), 32364fb65baSAtsushi Nemoto GFP_KERNEL); 324844a72c5SJingoo Han if (!txx9_priv) 32564fb65baSAtsushi Nemoto continue; 32664fb65baSAtsushi Nemoto chip = &txx9_priv->chip; 327a3f54377SBoris BREZILLON mtd = nand_to_mtd(chip); 328693ad872SFrans Klaver mtd->dev.parent = &dev->dev; 32964fb65baSAtsushi Nemoto 330716bbbabSBoris Brezillon chip->legacy.read_byte = txx9ndfmc_read_byte; 331716bbbabSBoris Brezillon chip->legacy.read_buf = txx9ndfmc_read_buf; 332716bbbabSBoris Brezillon chip->legacy.write_buf = txx9ndfmc_write_buf; 333bf6065c6SBoris Brezillon chip->legacy.cmd_ctrl = txx9ndfmc_cmd_ctrl; 3348395b753SBoris Brezillon chip->legacy.dev_ready = txx9ndfmc_dev_ready; 3353cece3abSBoris Brezillon chip->legacy.chip_delay = 100; 336a001058aSMiquel Raynal chip->controller = &drvdata->controller; 33764fb65baSAtsushi Nemoto 338d699ed25SBoris BREZILLON nand_set_controller_data(chip, txx9_priv); 33964fb65baSAtsushi Nemoto txx9_priv->dev = dev; 34064fb65baSAtsushi Nemoto 34164fb65baSAtsushi Nemoto if (plat->ch_mask != 1) { 34264fb65baSAtsushi Nemoto txx9_priv->cs = i; 34381933046SDavid Woodhouse txx9_priv->mtdname = kasprintf(GFP_KERNEL, "%s.%u", 34464fb65baSAtsushi Nemoto dev_name(&dev->dev), i); 34564fb65baSAtsushi Nemoto } else { 34664fb65baSAtsushi Nemoto txx9_priv->cs = -1; 347272023dfSAtsushi Nemoto txx9_priv->mtdname = kstrdup(dev_name(&dev->dev), 348272023dfSAtsushi Nemoto GFP_KERNEL); 349272023dfSAtsushi Nemoto } 350272023dfSAtsushi Nemoto if (!txx9_priv->mtdname) { 351272023dfSAtsushi Nemoto kfree(txx9_priv); 352272023dfSAtsushi Nemoto dev_err(&dev->dev, "Unable to allocate MTD name.\n"); 353272023dfSAtsushi Nemoto continue; 35464fb65baSAtsushi Nemoto } 35564fb65baSAtsushi Nemoto if (plat->wide_mask & (1 << i)) 35664fb65baSAtsushi Nemoto chip->options |= NAND_BUSWIDTH_16; 35764fb65baSAtsushi Nemoto 35800ad378fSBoris Brezillon if (nand_scan(chip, 1)) { 359272023dfSAtsushi Nemoto kfree(txx9_priv->mtdname); 36064fb65baSAtsushi Nemoto kfree(txx9_priv); 36164fb65baSAtsushi Nemoto continue; 36264fb65baSAtsushi Nemoto } 36364fb65baSAtsushi Nemoto mtd->name = txx9_priv->mtdname; 36464fb65baSAtsushi Nemoto 36529597ca1SRafał Miłecki mtd_device_register(mtd, NULL, 0); 36664fb65baSAtsushi Nemoto drvdata->mtds[i] = mtd; 36764fb65baSAtsushi Nemoto } 36864fb65baSAtsushi Nemoto 36964fb65baSAtsushi Nemoto return 0; 37064fb65baSAtsushi Nemoto } 37164fb65baSAtsushi Nemoto 37264fb65baSAtsushi Nemoto static int __exit txx9ndfmc_remove(struct platform_device *dev) 37364fb65baSAtsushi Nemoto { 37464fb65baSAtsushi Nemoto struct txx9ndfmc_drvdata *drvdata = platform_get_drvdata(dev); 375f6fc7597SMiquel Raynal int ret, i; 37664fb65baSAtsushi Nemoto 37764fb65baSAtsushi Nemoto if (!drvdata) 37864fb65baSAtsushi Nemoto return 0; 37964fb65baSAtsushi Nemoto for (i = 0; i < MAX_TXX9NDFMC_DEV; i++) { 38064fb65baSAtsushi Nemoto struct mtd_info *mtd = drvdata->mtds[i]; 38164fb65baSAtsushi Nemoto struct nand_chip *chip; 38264fb65baSAtsushi Nemoto struct txx9ndfmc_priv *txx9_priv; 38364fb65baSAtsushi Nemoto 38464fb65baSAtsushi Nemoto if (!mtd) 38564fb65baSAtsushi Nemoto continue; 3864bd4ebccSBoris BREZILLON chip = mtd_to_nand(mtd); 387d699ed25SBoris BREZILLON txx9_priv = nand_get_controller_data(chip); 38864fb65baSAtsushi Nemoto 389f6fc7597SMiquel Raynal ret = mtd_device_unregister(nand_to_mtd(chip)); 390f6fc7597SMiquel Raynal WARN_ON(ret); 391f6fc7597SMiquel Raynal nand_cleanup(chip); 39281933046SDavid Woodhouse kfree(txx9_priv->mtdname); 39364fb65baSAtsushi Nemoto kfree(txx9_priv); 39464fb65baSAtsushi Nemoto } 39564fb65baSAtsushi Nemoto return 0; 39664fb65baSAtsushi Nemoto } 39764fb65baSAtsushi Nemoto 39864fb65baSAtsushi Nemoto #ifdef CONFIG_PM 39964fb65baSAtsushi Nemoto static int txx9ndfmc_resume(struct platform_device *dev) 40064fb65baSAtsushi Nemoto { 40164fb65baSAtsushi Nemoto if (platform_get_drvdata(dev)) 40264fb65baSAtsushi Nemoto txx9ndfmc_initialize(dev); 40364fb65baSAtsushi Nemoto return 0; 40464fb65baSAtsushi Nemoto } 40564fb65baSAtsushi Nemoto #else 40664fb65baSAtsushi Nemoto #define txx9ndfmc_resume NULL 40764fb65baSAtsushi Nemoto #endif 40864fb65baSAtsushi Nemoto 40964fb65baSAtsushi Nemoto static struct platform_driver txx9ndfmc_driver = { 41064fb65baSAtsushi Nemoto .remove = __exit_p(txx9ndfmc_remove), 41164fb65baSAtsushi Nemoto .resume = txx9ndfmc_resume, 41264fb65baSAtsushi Nemoto .driver = { 41364fb65baSAtsushi Nemoto .name = "txx9ndfmc", 41464fb65baSAtsushi Nemoto }, 41564fb65baSAtsushi Nemoto }; 41664fb65baSAtsushi Nemoto 4173a2a13faSJingoo Han module_platform_driver_probe(txx9ndfmc_driver, txx9ndfmc_probe); 41864fb65baSAtsushi Nemoto 41964fb65baSAtsushi Nemoto MODULE_LICENSE("GPL"); 42064fb65baSAtsushi Nemoto MODULE_DESCRIPTION("TXx9 SoC NAND flash controller driver"); 42164fb65baSAtsushi Nemoto MODULE_ALIAS("platform:txx9ndfmc"); 422