diff options
Diffstat (limited to 'drivers/mtd/nand/raw/atmel/nand-controller.c')
| -rw-r--r-- | drivers/mtd/nand/raw/atmel/nand-controller.c | 175 | 
1 files changed, 81 insertions, 94 deletions
diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index 12f6753d47ae..a068b214ebaa 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -52,7 +52,6 @@  #include <linux/dma-mapping.h>  #include <linux/dmaengine.h>  #include <linux/genalloc.h> -#include <linux/gpio.h>  #include <linux/gpio/consumer.h>  #include <linux/interrupt.h>  #include <linux/mfd/syscon.h> @@ -129,6 +128,11 @@  #define DEFAULT_TIMEOUT_MS			1000  #define MIN_DMA_LEN				128 +static bool atmel_nand_avoid_dma __read_mostly; + +MODULE_PARM_DESC(avoiddma, "Avoid using DMA"); +module_param_named(avoiddma, atmel_nand_avoid_dma, bool, 0400); +  enum atmel_nand_rb_type {  	ATMEL_NAND_NO_RB,  	ATMEL_NAND_NATIVE_RB, @@ -197,7 +201,7 @@ struct atmel_nand_controller_ops {  	int (*remove)(struct atmel_nand_controller *nc);  	void (*nand_init)(struct atmel_nand_controller *nc,  			  struct atmel_nand *nand); -	int (*ecc_init)(struct atmel_nand *nand); +	int (*ecc_init)(struct nand_chip *chip);  	int (*setup_data_interface)(struct atmel_nand *nand, int csline,  				    const struct nand_data_interface *conf);  }; @@ -211,7 +215,7 @@ struct atmel_nand_controller_caps {  };  struct atmel_nand_controller { -	struct nand_hw_control base; +	struct nand_controller base;  	const struct atmel_nand_controller_caps *caps;  	struct device *dev;  	struct regmap *smc; @@ -222,7 +226,7 @@ struct atmel_nand_controller {  };  static inline struct atmel_nand_controller * -to_nand_controller(struct nand_hw_control *ctl) +to_nand_controller(struct nand_controller *ctl)  {  	return container_of(ctl, struct atmel_nand_controller, base);  } @@ -234,7 +238,7 @@ struct atmel_smc_nand_controller {  };  static inline struct atmel_smc_nand_controller * -to_smc_nand_controller(struct nand_hw_control *ctl) +to_smc_nand_controller(struct nand_controller *ctl)  {  	return container_of(to_nand_controller(ctl),  			    struct atmel_smc_nand_controller, base); @@ -258,7 +262,7 @@ struct atmel_hsmc_nand_controller {  };  static inline struct atmel_hsmc_nand_controller * -to_hsmc_nand_controller(struct nand_hw_control *ctl) +to_hsmc_nand_controller(struct nand_controller *ctl)  {  	return container_of(to_nand_controller(ctl),  			    struct atmel_hsmc_nand_controller, base); @@ -1128,9 +1132,8 @@ static int atmel_nand_pmecc_init(struct nand_chip *chip)  	return 0;  } -static int atmel_nand_ecc_init(struct atmel_nand *nand) +static int atmel_nand_ecc_init(struct nand_chip *chip)  { -	struct nand_chip *chip = &nand->base;  	struct atmel_nand_controller *nc;  	int ret; @@ -1165,12 +1168,11 @@ static int atmel_nand_ecc_init(struct atmel_nand *nand)  	return 0;  } -static int atmel_hsmc_nand_ecc_init(struct atmel_nand *nand) +static int atmel_hsmc_nand_ecc_init(struct nand_chip *chip)  { -	struct nand_chip *chip = &nand->base;  	int ret; -	ret = atmel_nand_ecc_init(nand); +	ret = atmel_nand_ecc_init(chip);  	if (ret)  		return ret; @@ -1553,23 +1555,7 @@ static void atmel_hsmc_nand_init(struct atmel_nand_controller *nc,  	chip->select_chip = atmel_hsmc_nand_select_chip;  } -static int atmel_nand_detect(struct atmel_nand *nand) -{ -	struct nand_chip *chip = &nand->base; -	struct mtd_info *mtd = nand_to_mtd(chip); -	struct atmel_nand_controller *nc; -	int ret; - -	nc = to_nand_controller(chip->controller); - -	ret = nand_scan_ident(mtd, nand->numcs, NULL); -	if (ret) -		dev_err(nc->dev, "nand_scan_ident() failed: %d\n", ret); - -	return ret; -} - -static int atmel_nand_unregister(struct atmel_nand *nand) +static int atmel_nand_controller_remove_nand(struct atmel_nand *nand)  {  	struct nand_chip *chip = &nand->base;  	struct mtd_info *mtd = nand_to_mtd(chip); @@ -1585,60 +1571,6 @@ static int atmel_nand_unregister(struct atmel_nand *nand)  	return 0;  } -static int atmel_nand_register(struct atmel_nand *nand) -{ -	struct nand_chip *chip = &nand->base; -	struct mtd_info *mtd = nand_to_mtd(chip); -	struct atmel_nand_controller *nc; -	int ret; - -	nc = to_nand_controller(chip->controller); - -	if (nc->caps->legacy_of_bindings || !nc->dev->of_node) { -		/* -		 * We keep the MTD name unchanged to avoid breaking platforms -		 * where the MTD cmdline parser is used and the bootloader -		 * has not been updated to use the new naming scheme. -		 */ -		mtd->name = "atmel_nand"; -	} else if (!mtd->name) { -		/* -		 * If the new bindings are used and the bootloader has not been -		 * updated to pass a new mtdparts parameter on the cmdline, you -		 * should define the following property in your nand node: -		 * -		 *	label = "atmel_nand"; -		 * -		 * This way, mtd->name will be set by the core when -		 * nand_set_flash_node() is called. -		 */ -		mtd->name = devm_kasprintf(nc->dev, GFP_KERNEL, -					   "%s:nand.%d", dev_name(nc->dev), -					   nand->cs[0].id); -		if (!mtd->name) { -			dev_err(nc->dev, "Failed to allocate mtd->name\n"); -			return -ENOMEM; -		} -	} - -	ret = nand_scan_tail(mtd); -	if (ret) { -		dev_err(nc->dev, "nand_scan_tail() failed: %d\n", ret); -		return ret; -	} - -	ret = mtd_device_register(mtd, NULL, 0); -	if (ret) { -		dev_err(nc->dev, "Failed to register mtd device: %d\n", ret); -		nand_cleanup(chip); -		return ret; -	} - -	list_add_tail(&nand->node, &nc->chips); - -	return 0; -} -  static struct atmel_nand *atmel_nand_create(struct atmel_nand_controller *nc,  					    struct device_node *np,  					    int reg_cells) @@ -1750,6 +1682,8 @@ static int  atmel_nand_controller_add_nand(struct atmel_nand_controller *nc,  			       struct atmel_nand *nand)  { +	struct nand_chip *chip = &nand->base; +	struct mtd_info *mtd = nand_to_mtd(chip);  	int ret;  	/* No card inserted, skip this NAND. */ @@ -1760,15 +1694,22 @@ atmel_nand_controller_add_nand(struct atmel_nand_controller *nc,  	nc->caps->ops->nand_init(nc, nand); -	ret = atmel_nand_detect(nand); -	if (ret) +	ret = nand_scan(mtd, nand->numcs); +	if (ret) { +		dev_err(nc->dev, "NAND scan failed: %d\n", ret);  		return ret; +	} -	ret = nc->caps->ops->ecc_init(nand); -	if (ret) +	ret = mtd_device_register(mtd, NULL, 0); +	if (ret) { +		dev_err(nc->dev, "Failed to register mtd device: %d\n", ret); +		nand_cleanup(chip);  		return ret; +	} + +	list_add_tail(&nand->node, &nc->chips); -	return atmel_nand_register(nand); +	return 0;  }  static int @@ -1778,7 +1719,7 @@ atmel_nand_controller_remove_nands(struct atmel_nand_controller *nc)  	int ret;  	list_for_each_entry_safe(nand, tmp, &nc->chips, node) { -		ret = atmel_nand_unregister(nand); +		ret = atmel_nand_controller_remove_nand(nand);  		if (ret)  			return ret;  	} @@ -1953,6 +1894,51 @@ static const struct of_device_id atmel_matrix_of_ids[] = {  	{ /* sentinel */ },  }; +static int atmel_nand_attach_chip(struct nand_chip *chip) +{ +	struct atmel_nand_controller *nc = to_nand_controller(chip->controller); +	struct atmel_nand *nand = to_atmel_nand(chip); +	struct mtd_info *mtd = nand_to_mtd(chip); +	int ret; + +	ret = nc->caps->ops->ecc_init(chip); +	if (ret) +		return ret; + +	if (nc->caps->legacy_of_bindings || !nc->dev->of_node) { +		/* +		 * We keep the MTD name unchanged to avoid breaking platforms +		 * where the MTD cmdline parser is used and the bootloader +		 * has not been updated to use the new naming scheme. +		 */ +		mtd->name = "atmel_nand"; +	} else if (!mtd->name) { +		/* +		 * If the new bindings are used and the bootloader has not been +		 * updated to pass a new mtdparts parameter on the cmdline, you +		 * should define the following property in your nand node: +		 * +		 *	label = "atmel_nand"; +		 * +		 * This way, mtd->name will be set by the core when +		 * nand_set_flash_node() is called. +		 */ +		mtd->name = devm_kasprintf(nc->dev, GFP_KERNEL, +					   "%s:nand.%d", dev_name(nc->dev), +					   nand->cs[0].id); +		if (!mtd->name) { +			dev_err(nc->dev, "Failed to allocate mtd->name\n"); +			return -ENOMEM; +		} +	} + +	return 0; +} + +static const struct nand_controller_ops atmel_nand_controller_ops = { +	.attach_chip = atmel_nand_attach_chip, +}; +  static int atmel_nand_controller_init(struct atmel_nand_controller *nc,  				struct platform_device *pdev,  				const struct atmel_nand_controller_caps *caps) @@ -1961,7 +1947,8 @@ static int atmel_nand_controller_init(struct atmel_nand_controller *nc,  	struct device_node *np = dev->of_node;  	int ret; -	nand_hw_control_init(&nc->base); +	nand_controller_init(&nc->base); +	nc->base.ops = &atmel_nand_controller_ops;  	INIT_LIST_HEAD(&nc->chips);  	nc->dev = dev;  	nc->caps = caps; @@ -1977,7 +1964,7 @@ static int atmel_nand_controller_init(struct atmel_nand_controller *nc,  		return ret;  	} -	if (nc->caps->has_dma) { +	if (nc->caps->has_dma && !atmel_nand_avoid_dma) {  		dma_cap_mask_t mask;  		dma_cap_zero(mask); @@ -2045,7 +2032,7 @@ atmel_smc_nand_controller_init(struct atmel_smc_nand_controller *nc)  		return ret;  	} -	nc->ebi_csa_offs = (unsigned int)match->data; +	nc->ebi_csa_offs = (uintptr_t)match->data;  	/*  	 * The at91sam9263 has 2 EBIs, if the NAND controller is under EBI1 @@ -2214,9 +2201,9 @@ atmel_hsmc_nand_controller_init(struct atmel_hsmc_nand_controller *nc)  		return -ENOMEM;  	} -	nc->sram.virt = gen_pool_dma_alloc(nc->sram.pool, -					    ATMEL_NFC_SRAM_SIZE, -					    &nc->sram.dma); +	nc->sram.virt = (void __iomem *)gen_pool_dma_alloc(nc->sram.pool, +							   ATMEL_NFC_SRAM_SIZE, +							   &nc->sram.dma);  	if (!nc->sram.virt) {  		dev_err(nc->base.dev,  			"Could not allocate memory from the NFC SRAM pool\n");  |