| .. | .. | 
|---|
| 25 | 25 |  #include <linux/of.h> | 
|---|
| 26 | 26 |  #include <linux/of_platform.h> | 
|---|
| 27 | 27 |  #include <linux/slab.h> | 
|---|
 | 28 | +#include <linux/static_key.h>  | 
|---|
| 28 | 29 |  #include <linux/list.h> | 
|---|
| 29 | 30 |  #include <linux/log2.h> | 
|---|
| 30 | 31 |   | 
|---|
| .. | .. | 
|---|
| 207 | 208 |   | 
|---|
| 208 | 209 |  struct brcmnand_host; | 
|---|
| 209 | 210 |   | 
|---|
 | 211 | +static DEFINE_STATIC_KEY_FALSE(brcmnand_soc_has_ops_key);  | 
|---|
 | 212 | +  | 
|---|
| 210 | 213 |  struct brcmnand_controller { | 
|---|
| 211 | 214 |  	struct device		*dev; | 
|---|
| 212 | 215 |  	struct nand_controller	controller; | 
|---|
| .. | .. | 
|---|
| 265 | 268 |  	const unsigned int	*page_sizes; | 
|---|
| 266 | 269 |  	unsigned int		page_size_shift; | 
|---|
| 267 | 270 |  	unsigned int		max_oob; | 
|---|
 | 271 | +	u32			ecc_level_shift;  | 
|---|
| 268 | 272 |  	u32			features; | 
|---|
| 269 | 273 |   | 
|---|
| 270 | 274 |  	/* for low-power standby/resume only */ | 
|---|
| .. | .. | 
|---|
| 589 | 593 |  	INTFC_CTLR_READY		= BIT(31), | 
|---|
| 590 | 594 |  }; | 
|---|
| 591 | 595 |   | 
|---|
 | 596 | +/***********************************************************************  | 
|---|
 | 597 | + * NAND ACC CONTROL bitfield  | 
|---|
 | 598 | + *  | 
|---|
 | 599 | + * Some bits have remained constant throughout hardware revision, while  | 
|---|
 | 600 | + * others have shifted around.  | 
|---|
 | 601 | + ***********************************************************************/  | 
|---|
 | 602 | +  | 
|---|
 | 603 | +/* Constant for all versions (where supported) */  | 
|---|
 | 604 | +enum {  | 
|---|
 | 605 | +	/* See BRCMNAND_HAS_CACHE_MODE */  | 
|---|
 | 606 | +	ACC_CONTROL_CACHE_MODE				= BIT(22),  | 
|---|
 | 607 | +  | 
|---|
 | 608 | +	/* See BRCMNAND_HAS_PREFETCH */  | 
|---|
 | 609 | +	ACC_CONTROL_PREFETCH				= BIT(23),  | 
|---|
 | 610 | +  | 
|---|
 | 611 | +	ACC_CONTROL_PAGE_HIT				= BIT(24),  | 
|---|
 | 612 | +	ACC_CONTROL_WR_PREEMPT				= BIT(25),  | 
|---|
 | 613 | +	ACC_CONTROL_PARTIAL_PAGE			= BIT(26),  | 
|---|
 | 614 | +	ACC_CONTROL_RD_ERASED				= BIT(27),  | 
|---|
 | 615 | +	ACC_CONTROL_FAST_PGM_RDIN			= BIT(28),  | 
|---|
 | 616 | +	ACC_CONTROL_WR_ECC				= BIT(30),  | 
|---|
 | 617 | +	ACC_CONTROL_RD_ECC				= BIT(31),  | 
|---|
 | 618 | +};  | 
|---|
 | 619 | +  | 
|---|
 | 620 | +#define	ACC_CONTROL_ECC_SHIFT			16  | 
|---|
 | 621 | +/* Only for v7.2 */  | 
|---|
 | 622 | +#define	ACC_CONTROL_ECC_EXT_SHIFT		13  | 
|---|
 | 623 | +  | 
|---|
 | 624 | +static inline bool brcmnand_non_mmio_ops(struct brcmnand_controller *ctrl)  | 
|---|
 | 625 | +{  | 
|---|
 | 626 | +	return static_branch_unlikely(&brcmnand_soc_has_ops_key);  | 
|---|
 | 627 | +}  | 
|---|
 | 628 | +  | 
|---|
| 592 | 629 |  static inline u32 nand_readreg(struct brcmnand_controller *ctrl, u32 offs) | 
|---|
| 593 | 630 |  { | 
|---|
 | 631 | +	if (brcmnand_non_mmio_ops(ctrl))  | 
|---|
 | 632 | +		return brcmnand_soc_read(ctrl->soc, offs);  | 
|---|
| 594 | 633 |  	return brcmnand_readl(ctrl->nand_base + offs); | 
|---|
| 595 | 634 |  } | 
|---|
| 596 | 635 |   | 
|---|
| 597 | 636 |  static inline void nand_writereg(struct brcmnand_controller *ctrl, u32 offs, | 
|---|
| 598 | 637 |  				 u32 val) | 
|---|
| 599 | 638 |  { | 
|---|
| 600 |  | -	brcmnand_writel(val, ctrl->nand_base + offs);  | 
|---|
 | 639 | +	if (brcmnand_non_mmio_ops(ctrl))  | 
|---|
 | 640 | +		brcmnand_soc_write(ctrl->soc, val, offs);  | 
|---|
 | 641 | +	else  | 
|---|
 | 642 | +		brcmnand_writel(val, ctrl->nand_base + offs);  | 
|---|
| 601 | 643 |  } | 
|---|
| 602 | 644 |   | 
|---|
| 603 | 645 |  static int brcmnand_revision_init(struct brcmnand_controller *ctrl) | 
|---|
| .. | .. | 
|---|
| 716 | 758 |  	else if (of_property_read_bool(ctrl->dev->of_node, "brcm,nand-has-wp")) | 
|---|
| 717 | 759 |  		ctrl->features |= BRCMNAND_HAS_WP; | 
|---|
| 718 | 760 |   | 
|---|
 | 761 | +	/* v7.2 has different ecc level shift in the acc register */  | 
|---|
 | 762 | +	if (ctrl->nand_version == 0x0702)  | 
|---|
 | 763 | +		ctrl->ecc_level_shift = ACC_CONTROL_ECC_EXT_SHIFT;  | 
|---|
 | 764 | +	else  | 
|---|
 | 765 | +		ctrl->ecc_level_shift = ACC_CONTROL_ECC_SHIFT;  | 
|---|
 | 766 | +  | 
|---|
| 719 | 767 |  	return 0; | 
|---|
| 720 | 768 |  } | 
|---|
| 721 | 769 |   | 
|---|
| .. | .. | 
|---|
| 763 | 811 |   | 
|---|
| 764 | 812 |  static inline u32 brcmnand_read_fc(struct brcmnand_controller *ctrl, int word) | 
|---|
| 765 | 813 |  { | 
|---|
 | 814 | +	if (brcmnand_non_mmio_ops(ctrl))  | 
|---|
 | 815 | +		return brcmnand_soc_read(ctrl->soc, BRCMNAND_NON_MMIO_FC_ADDR);  | 
|---|
| 766 | 816 |  	return __raw_readl(ctrl->nand_fc + word * 4); | 
|---|
| 767 | 817 |  } | 
|---|
| 768 | 818 |   | 
|---|
| 769 | 819 |  static inline void brcmnand_write_fc(struct brcmnand_controller *ctrl, | 
|---|
| 770 | 820 |  				     int word, u32 val) | 
|---|
| 771 | 821 |  { | 
|---|
| 772 |  | -	__raw_writel(val, ctrl->nand_fc + word * 4);  | 
|---|
 | 822 | +	if (brcmnand_non_mmio_ops(ctrl))  | 
|---|
 | 823 | +		brcmnand_soc_write(ctrl->soc, val, BRCMNAND_NON_MMIO_FC_ADDR);  | 
|---|
 | 824 | +	else  | 
|---|
 | 825 | +		__raw_writel(val, ctrl->nand_fc + word * 4);  | 
|---|
| 773 | 826 |  } | 
|---|
| 774 | 827 |   | 
|---|
| 775 | 828 |  static inline void edu_writel(struct brcmnand_controller *ctrl, | 
|---|
| .. | .. | 
|---|
| 899 | 952 |  	return 0; | 
|---|
| 900 | 953 |  } | 
|---|
| 901 | 954 |   | 
|---|
| 902 |  | -/***********************************************************************  | 
|---|
| 903 |  | - * NAND ACC CONTROL bitfield  | 
|---|
| 904 |  | - *  | 
|---|
| 905 |  | - * Some bits have remained constant throughout hardware revision, while  | 
|---|
| 906 |  | - * others have shifted around.  | 
|---|
| 907 |  | - ***********************************************************************/  | 
|---|
| 908 |  | -  | 
|---|
| 909 |  | -/* Constant for all versions (where supported) */  | 
|---|
| 910 |  | -enum {  | 
|---|
| 911 |  | -	/* See BRCMNAND_HAS_CACHE_MODE */  | 
|---|
| 912 |  | -	ACC_CONTROL_CACHE_MODE				= BIT(22),  | 
|---|
| 913 |  | -  | 
|---|
| 914 |  | -	/* See BRCMNAND_HAS_PREFETCH */  | 
|---|
| 915 |  | -	ACC_CONTROL_PREFETCH				= BIT(23),  | 
|---|
| 916 |  | -  | 
|---|
| 917 |  | -	ACC_CONTROL_PAGE_HIT				= BIT(24),  | 
|---|
| 918 |  | -	ACC_CONTROL_WR_PREEMPT				= BIT(25),  | 
|---|
| 919 |  | -	ACC_CONTROL_PARTIAL_PAGE			= BIT(26),  | 
|---|
| 920 |  | -	ACC_CONTROL_RD_ERASED				= BIT(27),  | 
|---|
| 921 |  | -	ACC_CONTROL_FAST_PGM_RDIN			= BIT(28),  | 
|---|
| 922 |  | -	ACC_CONTROL_WR_ECC				= BIT(30),  | 
|---|
| 923 |  | -	ACC_CONTROL_RD_ECC				= BIT(31),  | 
|---|
| 924 |  | -};  | 
|---|
| 925 |  | -  | 
|---|
| 926 | 955 |  static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl) | 
|---|
| 927 | 956 |  { | 
|---|
| 928 | 957 |  	if (ctrl->nand_version == 0x0702) | 
|---|
| .. | .. | 
|---|
| 935 | 964 |  		return GENMASK(4, 0); | 
|---|
| 936 | 965 |  } | 
|---|
| 937 | 966 |   | 
|---|
| 938 |  | -#define NAND_ACC_CONTROL_ECC_SHIFT	16  | 
|---|
| 939 |  | -#define NAND_ACC_CONTROL_ECC_EXT_SHIFT	13  | 
|---|
| 940 |  | -  | 
|---|
| 941 | 967 |  static inline u32 brcmnand_ecc_level_mask(struct brcmnand_controller *ctrl) | 
|---|
| 942 | 968 |  { | 
|---|
| 943 | 969 |  	u32 mask = (ctrl->nand_version >= 0x0600) ? 0x1f : 0x0f; | 
|---|
| 944 | 970 |   | 
|---|
| 945 |  | -	mask <<= NAND_ACC_CONTROL_ECC_SHIFT;  | 
|---|
 | 971 | +	mask <<= ACC_CONTROL_ECC_SHIFT;  | 
|---|
| 946 | 972 |   | 
|---|
| 947 | 973 |  	/* v7.2 includes additional ECC levels */ | 
|---|
| 948 |  | -	if (ctrl->nand_version >= 0x0702)  | 
|---|
| 949 |  | -		mask |= 0x7 << NAND_ACC_CONTROL_ECC_EXT_SHIFT;  | 
|---|
 | 974 | +	if (ctrl->nand_version == 0x0702)  | 
|---|
 | 975 | +		mask |= 0x7 << ACC_CONTROL_ECC_EXT_SHIFT;  | 
|---|
| 950 | 976 |   | 
|---|
| 951 | 977 |  	return mask; | 
|---|
| 952 | 978 |  } | 
|---|
| .. | .. | 
|---|
| 960 | 986 |   | 
|---|
| 961 | 987 |  	if (en) { | 
|---|
| 962 | 988 |  		acc_control |= ecc_flags; /* enable RD/WR ECC */ | 
|---|
| 963 |  | -		acc_control |= host->hwcfg.ecc_level  | 
|---|
| 964 |  | -			       << NAND_ACC_CONTROL_ECC_SHIFT;  | 
|---|
 | 989 | +		acc_control &= ~brcmnand_ecc_level_mask(ctrl);  | 
|---|
 | 990 | +		acc_control |= host->hwcfg.ecc_level << ctrl->ecc_level_shift;  | 
|---|
| 965 | 991 |  	} else { | 
|---|
| 966 | 992 |  		acc_control &= ~ecc_flags; /* disable RD/WR ECC */ | 
|---|
| 967 | 993 |  		acc_control &= ~brcmnand_ecc_level_mask(ctrl); | 
|---|
| .. | .. | 
|---|
| 1039 | 1065 |   | 
|---|
| 1040 | 1066 |  		cpu_relax(); | 
|---|
| 1041 | 1067 |  	} while (time_after(limit, jiffies)); | 
|---|
 | 1068 | +  | 
|---|
 | 1069 | +	/*  | 
|---|
 | 1070 | +	 * do a final check after time out in case the CPU was busy and the driver  | 
|---|
 | 1071 | +	 * did not get enough time to perform the polling to avoid false alarms  | 
|---|
 | 1072 | +	 */  | 
|---|
 | 1073 | +	val = brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS);  | 
|---|
 | 1074 | +	if ((val & mask) == expected_val)  | 
|---|
 | 1075 | +		return 0;  | 
|---|
| 1042 | 1076 |   | 
|---|
| 1043 | 1077 |  	dev_warn(ctrl->dev, "timeout on status poll (expected %x got %x)\n", | 
|---|
| 1044 | 1078 |  		 expected_val, val & mask); | 
|---|
| .. | .. | 
|---|
| 1429 | 1463 |  			     const u8 *oob, int sas, int sector_1k) | 
|---|
| 1430 | 1464 |  { | 
|---|
| 1431 | 1465 |  	int tbytes = sas << sector_1k; | 
|---|
| 1432 |  | -	int j;  | 
|---|
 | 1466 | +	int j, k = 0;  | 
|---|
 | 1467 | +	u32 last = 0xffffffff;  | 
|---|
 | 1468 | +	u8 *plast = (u8 *)&last;  | 
|---|
| 1433 | 1469 |   | 
|---|
| 1434 | 1470 |  	/* Adjust OOB values for 1K sector size */ | 
|---|
| 1435 | 1471 |  	if (sector_1k && (i & 0x01)) | 
|---|
| 1436 | 1472 |  		tbytes = max(0, tbytes - (int)ctrl->max_oob); | 
|---|
| 1437 | 1473 |  	tbytes = min_t(int, tbytes, ctrl->max_oob); | 
|---|
| 1438 | 1474 |   | 
|---|
| 1439 |  | -	for (j = 0; j < tbytes; j += 4)  | 
|---|
 | 1475 | +	/*  | 
|---|
 | 1476 | +	 * tbytes may not be multiple of words. Make sure we don't read out of  | 
|---|
 | 1477 | +	 * the boundary and stop at last word.  | 
|---|
 | 1478 | +	 */  | 
|---|
 | 1479 | +	for (j = 0; (j + 3) < tbytes; j += 4)  | 
|---|
| 1440 | 1480 |  		oob_reg_write(ctrl, j, | 
|---|
| 1441 | 1481 |  				(oob[j + 0] << 24) | | 
|---|
| 1442 | 1482 |  				(oob[j + 1] << 16) | | 
|---|
| 1443 | 1483 |  				(oob[j + 2] <<  8) | | 
|---|
| 1444 | 1484 |  				(oob[j + 3] <<  0)); | 
|---|
 | 1485 | +  | 
|---|
 | 1486 | +	/* handle the remaing bytes */  | 
|---|
 | 1487 | +	while (j < tbytes)  | 
|---|
 | 1488 | +		plast[k++] = oob[j++];  | 
|---|
 | 1489 | +  | 
|---|
 | 1490 | +	if (tbytes & 0x3)  | 
|---|
 | 1491 | +		oob_reg_write(ctrl, (tbytes & ~0x3), (__force u32)cpu_to_be32(last));  | 
|---|
 | 1492 | +  | 
|---|
| 1445 | 1493 |  	return tbytes; | 
|---|
| 1446 | 1494 |  } | 
|---|
| 1447 | 1495 |   | 
|---|
| .. | .. | 
|---|
| 1543 | 1591 |   | 
|---|
| 1544 | 1592 |  	dev_dbg(ctrl->dev, "send native cmd %d addr 0x%llx\n", cmd, cmd_addr); | 
|---|
| 1545 | 1593 |   | 
|---|
| 1546 |  | -	BUG_ON(ctrl->cmd_pending != 0);  | 
|---|
 | 1594 | +	/*  | 
|---|
 | 1595 | +	 * If we came here through _panic_write and there is a pending  | 
|---|
 | 1596 | +	 * command, try to wait for it. If it times out, rather than  | 
|---|
 | 1597 | +	 * hitting BUG_ON, just return so we don't crash while crashing.  | 
|---|
 | 1598 | +	 */  | 
|---|
 | 1599 | +	if (oops_in_progress) {  | 
|---|
 | 1600 | +		if (ctrl->cmd_pending &&  | 
|---|
 | 1601 | +			bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY, NAND_CTRL_RDY, 0))  | 
|---|
 | 1602 | +			return;  | 
|---|
 | 1603 | +	} else  | 
|---|
 | 1604 | +		BUG_ON(ctrl->cmd_pending != 0);  | 
|---|
| 1547 | 1605 |  	ctrl->cmd_pending = cmd; | 
|---|
| 1548 | 1606 |   | 
|---|
| 1549 | 1607 |  	ret = bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY, NAND_CTRL_RDY, 0); | 
|---|
| .. | .. | 
|---|
| 2483 | 2541 |  	tmp &= ~brcmnand_ecc_level_mask(ctrl); | 
|---|
| 2484 | 2542 |  	tmp &= ~brcmnand_spare_area_mask(ctrl); | 
|---|
| 2485 | 2543 |  	if (ctrl->nand_version >= 0x0302) { | 
|---|
| 2486 |  | -		tmp |= cfg->ecc_level << NAND_ACC_CONTROL_ECC_SHIFT;  | 
|---|
 | 2544 | +		tmp |= cfg->ecc_level << ctrl->ecc_level_shift;  | 
|---|
| 2487 | 2545 |  		tmp |= cfg->spare_area_size; | 
|---|
| 2488 | 2546 |  	} | 
|---|
| 2489 | 2547 |  	nand_writereg(ctrl, acc_control_offs, tmp); | 
|---|
| .. | .. | 
|---|
| 2534 | 2592 |  	struct nand_chip *chip = &host->chip; | 
|---|
| 2535 | 2593 |  	const struct nand_ecc_props *requirements = | 
|---|
| 2536 | 2594 |  		nanddev_get_ecc_requirements(&chip->base); | 
|---|
 | 2595 | +	struct nand_memory_organization *memorg =  | 
|---|
 | 2596 | +		nanddev_get_memorg(&chip->base);  | 
|---|
| 2537 | 2597 |  	struct brcmnand_controller *ctrl = host->ctrl; | 
|---|
| 2538 | 2598 |  	struct brcmnand_cfg *cfg = &host->hwcfg; | 
|---|
| 2539 | 2599 |  	char msg[128]; | 
|---|
| .. | .. | 
|---|
| 2555 | 2615 |  	if (cfg->spare_area_size > ctrl->max_oob) | 
|---|
| 2556 | 2616 |  		cfg->spare_area_size = ctrl->max_oob; | 
|---|
| 2557 | 2617 |  	/* | 
|---|
| 2558 |  | -	 * Set oobsize to be consistent with controller's spare_area_size, as  | 
|---|
| 2559 |  | -	 * the rest is inaccessible.  | 
|---|
 | 2618 | +	 * Set mtd and memorg oobsize to be consistent with controller's  | 
|---|
 | 2619 | +	 * spare_area_size, as the rest is inaccessible.  | 
|---|
| 2560 | 2620 |  	 */ | 
|---|
| 2561 | 2621 |  	mtd->oobsize = cfg->spare_area_size * (mtd->writesize >> FC_SHIFT); | 
|---|
 | 2622 | +	memorg->oobsize = mtd->oobsize;  | 
|---|
| 2562 | 2623 |   | 
|---|
| 2563 | 2624 |  	cfg->device_size = mtd->size; | 
|---|
| 2564 | 2625 |  	cfg->block_size = mtd->erasesize; | 
|---|
| .. | .. | 
|---|
| 2950 | 3011 |  	dev_set_drvdata(dev, ctrl); | 
|---|
| 2951 | 3012 |  	ctrl->dev = dev; | 
|---|
| 2952 | 3013 |   | 
|---|
 | 3014 | +	/* Enable the static key if the soc provides I/O operations indicating  | 
|---|
 | 3015 | +	 * that a non-memory mapped IO access path must be used  | 
|---|
 | 3016 | +	 */  | 
|---|
 | 3017 | +	if (brcmnand_soc_has_ops(ctrl->soc))  | 
|---|
 | 3018 | +		static_branch_enable(&brcmnand_soc_has_ops_key);  | 
|---|
 | 3019 | +  | 
|---|
| 2953 | 3020 |  	init_completion(&ctrl->done); | 
|---|
| 2954 | 3021 |  	init_completion(&ctrl->dma_done); | 
|---|
| 2955 | 3022 |  	init_completion(&ctrl->edu_done); | 
|---|