brintos

brintos / linux-shallow public Read only

0
0
Text · 5.7 KiB · 2e77911 Raw
243 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Versatile OF physmap driver add-on4 *5 * Copyright (c) 2016, Linaro Limited6 * Author: Linus Walleij <linus.walleij@linaro.org>7 */8#include <linux/export.h>9#include <linux/io.h>10#include <linux/of.h>11#include <linux/of_address.h>12#include <linux/mtd/map.h>13#include <linux/mfd/syscon.h>14#include <linux/platform_device.h>15#include <linux/regmap.h>16#include <linux/bitops.h>17#include "physmap-versatile.h"18 19static struct regmap *syscon_regmap;20 21enum versatile_flashprot {22	INTEGRATOR_AP_FLASHPROT,23	INTEGRATOR_CP_FLASHPROT,24	VERSATILE_FLASHPROT,25	REALVIEW_FLASHPROT,26};27 28static const struct of_device_id syscon_match[] = {29	{30		.compatible = "arm,integrator-ap-syscon",31		.data = (void *)INTEGRATOR_AP_FLASHPROT,32	},33	{34		.compatible = "arm,integrator-cp-syscon",35		.data = (void *)INTEGRATOR_CP_FLASHPROT,36	},37	{38		.compatible = "arm,core-module-versatile",39		.data = (void *)VERSATILE_FLASHPROT,40	},41	{42		.compatible = "arm,realview-eb-syscon",43		.data = (void *)REALVIEW_FLASHPROT,44	},45	{46		.compatible = "arm,realview-pb1176-syscon",47		.data = (void *)REALVIEW_FLASHPROT,48	},49	{50		.compatible = "arm,realview-pb11mp-syscon",51		.data = (void *)REALVIEW_FLASHPROT,52	},53	{54		.compatible = "arm,realview-pba8-syscon",55		.data = (void *)REALVIEW_FLASHPROT,56	},57	{58		.compatible = "arm,realview-pbx-syscon",59		.data = (void *)REALVIEW_FLASHPROT,60	},61	{},62};63 64/*65 * Flash protection handling for the Integrator/AP66 */67#define INTEGRATOR_SC_CTRLS_OFFSET	0x0868#define INTEGRATOR_SC_CTRLC_OFFSET	0x0C69#define INTEGRATOR_SC_CTRL_FLVPPEN	BIT(1)70#define INTEGRATOR_SC_CTRL_FLWP		BIT(2)71 72#define INTEGRATOR_EBI_CSR1_OFFSET	0x0473/* The manual says bit 2, the code says bit 3, trust the code */74#define INTEGRATOR_EBI_WRITE_ENABLE	BIT(3)75#define INTEGRATOR_EBI_LOCK_OFFSET	0x2076#define INTEGRATOR_EBI_LOCK_VAL		0xA05F77 78static const struct of_device_id ebi_match[] = {79	{ .compatible = "arm,external-bus-interface"},80	{ },81};82 83static int ap_flash_init(struct platform_device *pdev)84{85	struct device_node *ebi;86	void __iomem *ebi_base;87	u32 val;88	int ret;89 90	/* Look up the EBI */91	ebi = of_find_matching_node(NULL, ebi_match);92	if (!ebi) {93		return -ENODEV;94	}95	ebi_base = of_iomap(ebi, 0);96	of_node_put(ebi);97	if (!ebi_base)98		return -ENODEV;99 100	/* Clear VPP and write protection bits */101	ret = regmap_write(syscon_regmap,102		INTEGRATOR_SC_CTRLC_OFFSET,103		INTEGRATOR_SC_CTRL_FLVPPEN | INTEGRATOR_SC_CTRL_FLWP);104	if (ret)105		dev_err(&pdev->dev, "error clearing Integrator VPP/WP\n");106 107	/* Unlock the EBI */108	writel(INTEGRATOR_EBI_LOCK_VAL, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET);109 110	/* Enable write cycles on the EBI, CSR1 (flash) */111	val = readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET);112	val |= INTEGRATOR_EBI_WRITE_ENABLE;113	writel(val, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET);114 115	/* Lock the EBI again */116	writel(0, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET);117	iounmap(ebi_base);118 119	return 0;120}121 122static void ap_flash_set_vpp(struct map_info *map, int on)123{124	int ret;125 126	if (on) {127		ret = regmap_write(syscon_regmap,128			INTEGRATOR_SC_CTRLS_OFFSET,129			INTEGRATOR_SC_CTRL_FLVPPEN | INTEGRATOR_SC_CTRL_FLWP);130		if (ret)131			pr_err("error enabling AP VPP\n");132	} else {133		ret = regmap_write(syscon_regmap,134			INTEGRATOR_SC_CTRLC_OFFSET,135			INTEGRATOR_SC_CTRL_FLVPPEN | INTEGRATOR_SC_CTRL_FLWP);136		if (ret)137			pr_err("error disabling AP VPP\n");138	}139}140 141/*142 * Flash protection handling for the Integrator/CP143 */144 145#define INTCP_FLASHPROG_OFFSET		0x04146#define CINTEGRATOR_FLVPPEN		BIT(0)147#define CINTEGRATOR_FLWREN		BIT(1)148#define CINTEGRATOR_FLMASK		BIT(0)|BIT(1)149 150static void cp_flash_set_vpp(struct map_info *map, int on)151{152	int ret;153 154	if (on) {155		ret = regmap_update_bits(syscon_regmap,156				INTCP_FLASHPROG_OFFSET,157				CINTEGRATOR_FLMASK,158				CINTEGRATOR_FLVPPEN | CINTEGRATOR_FLWREN);159		if (ret)160			pr_err("error setting CP VPP\n");161	} else {162		ret = regmap_update_bits(syscon_regmap,163				INTCP_FLASHPROG_OFFSET,164				CINTEGRATOR_FLMASK,165				0);166		if (ret)167			pr_err("error setting CP VPP\n");168	}169}170 171/*172 * Flash protection handling for the Versatiles and RealViews173 */174 175#define VERSATILE_SYS_FLASH_OFFSET            0x4C176 177static void versatile_flash_set_vpp(struct map_info *map, int on)178{179	int ret;180 181	ret = regmap_update_bits(syscon_regmap, VERSATILE_SYS_FLASH_OFFSET,182				 0x01, !!on);183	if (ret)184		pr_err("error setting Versatile VPP\n");185}186 187int of_flash_probe_versatile(struct platform_device *pdev,188			     struct device_node *np,189			     struct map_info *map)190{191	struct device_node *sysnp;192	const struct of_device_id *devid;193	struct regmap *rmap;194	static enum versatile_flashprot versatile_flashprot;195	int ret;196 197	/* Not all flash chips use this protection line */198	if (!of_device_is_compatible(np, "arm,versatile-flash"))199		return 0;200 201	/* For first chip probed, look up the syscon regmap */202	if (!syscon_regmap) {203		sysnp = of_find_matching_node_and_match(NULL,204							syscon_match,205							&devid);206		if (!sysnp)207			return -ENODEV;208 209		versatile_flashprot = (uintptr_t)devid->data;210		rmap = syscon_node_to_regmap(sysnp);211		of_node_put(sysnp);212		if (IS_ERR(rmap))213			return PTR_ERR(rmap);214 215		syscon_regmap = rmap;216	}217 218	switch (versatile_flashprot) {219	case INTEGRATOR_AP_FLASHPROT:220		ret = ap_flash_init(pdev);221		if (ret)222			return ret;223		map->set_vpp = ap_flash_set_vpp;224		dev_info(&pdev->dev, "Integrator/AP flash protection\n");225		break;226	case INTEGRATOR_CP_FLASHPROT:227		map->set_vpp = cp_flash_set_vpp;228		dev_info(&pdev->dev, "Integrator/CP flash protection\n");229		break;230	case VERSATILE_FLASHPROT:231	case REALVIEW_FLASHPROT:232		map->set_vpp = versatile_flash_set_vpp;233		dev_info(&pdev->dev, "versatile/realview flash protection\n");234		break;235	default:236		dev_info(&pdev->dev, "device marked as Versatile flash "237			 "but no system controller was found\n");238		break;239	}240 241	return 0;242}243