Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 876fe76d authored by Paul Parsons's avatar Paul Parsons Committed by David Woodhouse
Browse files

mtd: maps: physmap: Add reference counter to set_vpp()



This patch is part of a set which fixes unnecessary flash erase and write errors
resulting from the MTD CFI driver turning off vpp while an erase is in progress.
This patch allows physmap_set_vpp() calls to be nested by adding a reference
counter.

omap1_set_vpp() already used a reference counter. Since it is called from
physmap_set_vpp(), omap1_set_vpp() can now be simplified.

simtec_nor_vpp() already disabled hard interrupts. Since it is called from
physmap_set_vpp(), simtec_nor_vpp() can now be simplified.

Signed-off-by: default avatarPaul Parsons <lost.distance@yahoo.com>
Signed-off-by: default avatarArtem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent e7d9377e
Loading
Loading
Loading
Loading
+6 −14
Original line number Original line Diff line number Diff line
@@ -15,20 +15,12 @@


void omap1_set_vpp(struct platform_device *pdev, int enable)
void omap1_set_vpp(struct platform_device *pdev, int enable)
{
{
	static int count;
	u32 l;
	u32 l;


	if (enable) {
		if (count++ == 0) {
	l = omap_readl(EMIFS_CONFIG);
	l = omap_readl(EMIFS_CONFIG);
	if (enable)
		l |= OMAP_EMIFS_CONFIG_WP;
		l |= OMAP_EMIFS_CONFIG_WP;
			omap_writel(l, EMIFS_CONFIG);
	else
		}
	} else {
		if (count && (--count == 0)) {
			l = omap_readl(EMIFS_CONFIG);
		l &= ~OMAP_EMIFS_CONFIG_WP;
		l &= ~OMAP_EMIFS_CONFIG_WP;
	omap_writel(l, EMIFS_CONFIG);
	omap_writel(l, EMIFS_CONFIG);
}
}
	}
}
+0 −3
Original line number Original line Diff line number Diff line
@@ -35,9 +35,7 @@
static void simtec_nor_vpp(struct platform_device *pdev, int vpp)
static void simtec_nor_vpp(struct platform_device *pdev, int vpp)
{
{
	unsigned int val;
	unsigned int val;
	unsigned long flags;


	local_irq_save(flags);
	val = __raw_readb(BAST_VA_CTRL3);
	val = __raw_readb(BAST_VA_CTRL3);


	printk(KERN_DEBUG "%s(%d)\n", __func__, vpp);
	printk(KERN_DEBUG "%s(%d)\n", __func__, vpp);
@@ -48,7 +46,6 @@ static void simtec_nor_vpp(struct platform_device *pdev, int vpp)
		val &= ~BAST_CPLD_CTRL3_ROMWEN;
		val &= ~BAST_CPLD_CTRL3_ROMWEN;


	__raw_writeb(val, BAST_VA_CTRL3);
	__raw_writeb(val, BAST_VA_CTRL3);
	local_irq_restore(flags);
}
}


static struct physmap_flash_data simtec_nor_pdata = {
static struct physmap_flash_data simtec_nor_pdata = {
+20 −2
Original line number Original line Diff line number Diff line
@@ -27,6 +27,8 @@ struct physmap_flash_info {
	struct mtd_info		*mtd[MAX_RESOURCES];
	struct mtd_info		*mtd[MAX_RESOURCES];
	struct mtd_info		*cmtd;
	struct mtd_info		*cmtd;
	struct map_info		map[MAX_RESOURCES];
	struct map_info		map[MAX_RESOURCES];
	spinlock_t		vpp_lock;
	int			vpp_refcnt;
};
};


static int physmap_flash_remove(struct platform_device *dev)
static int physmap_flash_remove(struct platform_device *dev)
@@ -63,12 +65,26 @@ static void physmap_set_vpp(struct map_info *map, int state)
{
{
	struct platform_device *pdev;
	struct platform_device *pdev;
	struct physmap_flash_data *physmap_data;
	struct physmap_flash_data *physmap_data;
	struct physmap_flash_info *info;
	unsigned long flags;


	pdev = (struct platform_device *)map->map_priv_1;
	pdev = (struct platform_device *)map->map_priv_1;
	physmap_data = pdev->dev.platform_data;
	physmap_data = pdev->dev.platform_data;


	if (physmap_data->set_vpp)
	if (!physmap_data->set_vpp)
		physmap_data->set_vpp(pdev, state);
		return;

	info = platform_get_drvdata(pdev);

	spin_lock_irqsave(&info->vpp_lock, flags);
	if (state) {
		if (++info->vpp_refcnt == 1)    /* first nested 'on' */
			physmap_data->set_vpp(pdev, 1);
	} else {
		if (--info->vpp_refcnt == 0)    /* last nested 'off' */
			physmap_data->set_vpp(pdev, 0);
	}
	spin_unlock_irqrestore(&info->vpp_lock, flags);
}
}


static const char *rom_probe_types[] = {
static const char *rom_probe_types[] = {
@@ -172,6 +188,8 @@ static int physmap_flash_probe(struct platform_device *dev)
	if (err)
	if (err)
		goto err_out;
		goto err_out;


	spin_lock_init(&info->vpp_lock);

	part_types = physmap_data->part_probe_types ? : part_probe_types;
	part_types = physmap_data->part_probe_types ? : part_probe_types;


	mtd_device_parse_register(info->cmtd, part_types, 0,
	mtd_device_parse_register(info->cmtd, part_types, 0,