cregit-Linux how code gets into the kernel

Release 4.11 drivers/mtd/maps/physmap_of_versatile.c

Directory: drivers/mtd/maps
/*
 * Versatile OF physmap driver add-on
 *
 * Copyright (c) 2016, Linaro Limited
 * Author: Linus Walleij <linus.walleij@linaro.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */
#include <linux/export.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/mtd/map.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/bitops.h>
#include "physmap_of_versatile.h"


static struct regmap *syscon_regmap;


enum versatile_flashprot {
	
INTEGRATOR_AP_FLASHPROT,
	
INTEGRATOR_CP_FLASHPROT,
	
VERSATILE_FLASHPROT,
	
REALVIEW_FLASHPROT,
};


static const struct of_device_id syscon_match[] = {
	{
		.compatible = "arm,integrator-ap-syscon",
		.data = (void *)INTEGRATOR_AP_FLASHPROT,
        },
	{
		.compatible = "arm,integrator-cp-syscon",
		.data = (void *)INTEGRATOR_CP_FLASHPROT,
        },
	{
		.compatible = "arm,core-module-versatile",
		.data = (void *)VERSATILE_FLASHPROT,
        },
	{
		.compatible = "arm,realview-eb-syscon",
		.data = (void *)REALVIEW_FLASHPROT,
        },
	{
		.compatible = "arm,realview-pb1176-syscon",
		.data = (void *)REALVIEW_FLASHPROT,
        },
	{
		.compatible = "arm,realview-pb11mp-syscon",
		.data = (void *)REALVIEW_FLASHPROT,
        },
	{
		.compatible = "arm,realview-pba8-syscon",
		.data = (void *)REALVIEW_FLASHPROT,
        },
	{
		.compatible = "arm,realview-pbx-syscon",
		.data = (void *)REALVIEW_FLASHPROT,
        },
	{},
};

/*
 * Flash protection handling for the Integrator/AP
 */

#define INTEGRATOR_SC_CTRLS_OFFSET	0x08

#define INTEGRATOR_SC_CTRLC_OFFSET	0x0C

#define INTEGRATOR_SC_CTRL_FLVPPEN	BIT(1)

#define INTEGRATOR_SC_CTRL_FLWP		BIT(2)


#define INTEGRATOR_EBI_CSR1_OFFSET	0x04
/* The manual says bit 2, the code says bit 3, trust the code */

#define INTEGRATOR_EBI_WRITE_ENABLE	BIT(3)

#define INTEGRATOR_EBI_LOCK_OFFSET	0x20

#define INTEGRATOR_EBI_LOCK_VAL		0xA05F


static const struct of_device_id ebi_match[] = {
	{ .compatible = "arm,external-bus-interface"},
	{ },
};


static int ap_flash_init(struct platform_device *pdev) { struct device_node *ebi; static void __iomem *ebi_base; u32 val; int ret; /* Look up the EBI */ ebi = of_find_matching_node(NULL, ebi_match); if (!ebi) { return -ENODEV; } ebi_base = of_iomap(ebi, 0); if (!ebi_base) return -ENODEV; /* Clear VPP and write protection bits */ ret = regmap_write(syscon_regmap, INTEGRATOR_SC_CTRLC_OFFSET, INTEGRATOR_SC_CTRL_FLVPPEN | INTEGRATOR_SC_CTRL_FLWP); if (ret) dev_err(&pdev->dev, "error clearing Integrator VPP/WP\n"); /* Unlock the EBI */ writel(INTEGRATOR_EBI_LOCK_VAL, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET); /* Enable write cycles on the EBI, CSR1 (flash) */ val = readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET); val |= INTEGRATOR_EBI_WRITE_ENABLE; writel(val, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET); /* Lock the EBI again */ writel(0, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET); iounmap(ebi_base); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Walleij146100.00%1100.00%
Total146100.00%1100.00%


static void ap_flash_set_vpp(struct map_info *map, int on) { int ret; if (on) { ret = regmap_write(syscon_regmap, INTEGRATOR_SC_CTRLS_OFFSET, INTEGRATOR_SC_CTRL_FLVPPEN | INTEGRATOR_SC_CTRL_FLWP); if (ret) pr_err("error enabling AP VPP\n"); } else { ret = regmap_write(syscon_regmap, INTEGRATOR_SC_CTRLC_OFFSET, INTEGRATOR_SC_CTRL_FLVPPEN | INTEGRATOR_SC_CTRL_FLWP); if (ret) pr_err("error disabling AP VPP\n"); } }

Contributors

PersonTokensPropCommitsCommitProp
Linus Walleij70100.00%1100.00%
Total70100.00%1100.00%

/* * Flash protection handling for the Integrator/CP */ #define INTCP_FLASHPROG_OFFSET 0x04 #define CINTEGRATOR_FLVPPEN BIT(0) #define CINTEGRATOR_FLWREN BIT(1) #define CINTEGRATOR_FLMASK BIT(0)|BIT(1)
static void cp_flash_set_vpp(struct map_info *map, int on) { int ret; if (on) { ret = regmap_update_bits(syscon_regmap, INTCP_FLASHPROG_OFFSET, CINTEGRATOR_FLMASK, CINTEGRATOR_FLVPPEN | CINTEGRATOR_FLWREN); if (ret) pr_err("error setting CP VPP\n"); } else { ret = regmap_update_bits(syscon_regmap, INTCP_FLASHPROG_OFFSET, CINTEGRATOR_FLMASK, 0); if (ret) pr_err("error setting CP VPP\n"); } }

Contributors

PersonTokensPropCommitsCommitProp
Linus Walleij72100.00%1100.00%
Total72100.00%1100.00%

/* * Flash protection handling for the Versatiles and RealViews */ #define VERSATILE_SYS_FLASH_OFFSET 0x4C
static void versatile_flash_set_vpp(struct map_info *map, int on) { int ret; ret = regmap_update_bits(syscon_regmap, VERSATILE_SYS_FLASH_OFFSET, 0x01, !!on); if (ret) pr_err("error setting Versatile VPP\n"); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Walleij41100.00%1100.00%
Total41100.00%1100.00%


int of_flash_probe_versatile(struct platform_device *pdev, struct device_node *np, struct map_info *map) { struct device_node *sysnp; const struct of_device_id *devid; struct regmap *rmap; static enum versatile_flashprot versatile_flashprot; int ret; /* Not all flash chips use this protection line */ if (!of_device_is_compatible(np, "arm,versatile-flash")) return 0; /* For first chip probed, look up the syscon regmap */ if (!syscon_regmap) { sysnp = of_find_matching_node_and_match(NULL, syscon_match, &devid); if (!sysnp) return -ENODEV; versatile_flashprot = (enum versatile_flashprot)devid->data; rmap = syscon_node_to_regmap(sysnp); if (IS_ERR(rmap)) return PTR_ERR(rmap); syscon_regmap = rmap; } switch (versatile_flashprot) { case INTEGRATOR_AP_FLASHPROT: ret = ap_flash_init(pdev); if (ret) return ret; map->set_vpp = ap_flash_set_vpp; dev_info(&pdev->dev, "Integrator/AP flash protection\n"); break; case INTEGRATOR_CP_FLASHPROT: map->set_vpp = cp_flash_set_vpp; dev_info(&pdev->dev, "Integrator/CP flash protection\n"); break; case VERSATILE_FLASHPROT: case REALVIEW_FLASHPROT: map->set_vpp = versatile_flash_set_vpp; dev_info(&pdev->dev, "versatile/realview flash protection\n"); break; default: dev_info(&pdev->dev, "device marked as Versatile flash " "but no system controller was found\n"); break; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Walleij220100.00%1100.00%
Total220100.00%1100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Linus Walleij80899.63%150.00%
Arnd Bergmann30.37%150.00%
Total811100.00%2100.00%
Directory: drivers/mtd/maps
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.