cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

intel-ixp4xx-eb.c (11514B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Intel IXP4xx Expansion Bus Controller
      4 * Copyright (C) 2021 Linaro Ltd.
      5 *
      6 * Author: Linus Walleij <linus.walleij@linaro.org>
      7 */
      8
      9#include <linux/bitfield.h>
     10#include <linux/bits.h>
     11#include <linux/err.h>
     12#include <linux/init.h>
     13#include <linux/log2.h>
     14#include <linux/mfd/syscon.h>
     15#include <linux/module.h>
     16#include <linux/of.h>
     17#include <linux/of_platform.h>
     18#include <linux/platform_device.h>
     19#include <linux/regmap.h>
     20
     21#define IXP4XX_EXP_NUM_CS		8
     22
     23#define IXP4XX_EXP_TIMING_CS0		0x00
     24#define IXP4XX_EXP_TIMING_CS1		0x04
     25#define IXP4XX_EXP_TIMING_CS2		0x08
     26#define IXP4XX_EXP_TIMING_CS3		0x0c
     27#define IXP4XX_EXP_TIMING_CS4		0x10
     28#define IXP4XX_EXP_TIMING_CS5		0x14
     29#define IXP4XX_EXP_TIMING_CS6		0x18
     30#define IXP4XX_EXP_TIMING_CS7		0x1c
     31
     32/* Bits inside each CS timing register */
     33#define IXP4XX_EXP_TIMING_STRIDE	0x04
     34#define IXP4XX_EXP_CS_EN		BIT(31)
     35#define IXP456_EXP_PAR_EN		BIT(30) /* Only on IXP45x and IXP46x */
     36#define IXP4XX_EXP_T1_MASK		GENMASK(28, 27)
     37#define IXP4XX_EXP_T1_SHIFT		28
     38#define IXP4XX_EXP_T2_MASK		GENMASK(27, 26)
     39#define IXP4XX_EXP_T2_SHIFT		26
     40#define IXP4XX_EXP_T3_MASK		GENMASK(25, 22)
     41#define IXP4XX_EXP_T3_SHIFT		22
     42#define IXP4XX_EXP_T4_MASK		GENMASK(21, 20)
     43#define IXP4XX_EXP_T4_SHIFT		20
     44#define IXP4XX_EXP_T5_MASK		GENMASK(19, 16)
     45#define IXP4XX_EXP_T5_SHIFT		16
     46#define IXP4XX_EXP_CYC_TYPE_MASK	GENMASK(15, 14)
     47#define IXP4XX_EXP_CYC_TYPE_SHIFT	14
     48#define IXP4XX_EXP_SIZE_MASK		GENMASK(13, 10)
     49#define IXP4XX_EXP_SIZE_SHIFT		10
     50#define IXP4XX_EXP_CNFG_0		BIT(9) /* Always zero */
     51#define IXP43X_EXP_SYNC_INTEL		BIT(8) /* Only on IXP43x */
     52#define IXP43X_EXP_EXP_CHIP		BIT(7) /* Only on IXP43x */
     53#define IXP4XX_EXP_BYTE_RD16		BIT(6)
     54#define IXP4XX_EXP_HRDY_POL		BIT(5) /* Only on IXP42x */
     55#define IXP4XX_EXP_MUX_EN		BIT(4)
     56#define IXP4XX_EXP_SPLT_EN		BIT(3)
     57#define IXP4XX_EXP_WORD			BIT(2) /* Always zero */
     58#define IXP4XX_EXP_WR_EN		BIT(1)
     59#define IXP4XX_EXP_BYTE_EN		BIT(0)
     60#define IXP42X_RESERVED			(BIT(30)|IXP4XX_EXP_CNFG_0|BIT(8)|BIT(7)|IXP4XX_EXP_WORD)
     61#define IXP43X_RESERVED			(BIT(30)|IXP4XX_EXP_CNFG_0|BIT(5)|IXP4XX_EXP_WORD)
     62
     63#define IXP4XX_EXP_CNFG0		0x20
     64#define IXP4XX_EXP_CNFG0_MEM_MAP	BIT(31)
     65#define IXP4XX_EXP_CNFG1		0x24
     66
     67#define IXP4XX_EXP_BOOT_BASE		0x00000000
     68#define IXP4XX_EXP_NORMAL_BASE		0x50000000
     69#define IXP4XX_EXP_STRIDE		0x01000000
     70
     71/* Fuses on the IXP43x */
     72#define IXP43X_EXP_UNIT_FUSE_RESET	0x28
     73#define IXP43x_EXP_FUSE_SPEED_MASK	GENMASK(23, 22)
     74
     75/* Number of device tree values in "reg" */
     76#define IXP4XX_OF_REG_SIZE		3
     77
     78struct ixp4xx_eb {
     79	struct device *dev;
     80	struct regmap *rmap;
     81	u32 bus_base;
     82	bool is_42x;
     83	bool is_43x;
     84};
     85
     86struct ixp4xx_exp_tim_prop {
     87	const char *prop;
     88	u32 max;
     89	u32 mask;
     90	u16 shift;
     91};
     92
     93static const struct ixp4xx_exp_tim_prop ixp4xx_exp_tim_props[] = {
     94	{
     95		.prop = "intel,ixp4xx-eb-t1",
     96		.max = 3,
     97		.mask = IXP4XX_EXP_T1_MASK,
     98		.shift = IXP4XX_EXP_T1_SHIFT,
     99	},
    100	{
    101		.prop = "intel,ixp4xx-eb-t2",
    102		.max = 3,
    103		.mask = IXP4XX_EXP_T2_MASK,
    104		.shift = IXP4XX_EXP_T2_SHIFT,
    105	},
    106	{
    107		.prop = "intel,ixp4xx-eb-t3",
    108		.max = 15,
    109		.mask = IXP4XX_EXP_T3_MASK,
    110		.shift = IXP4XX_EXP_T3_SHIFT,
    111	},
    112	{
    113		.prop = "intel,ixp4xx-eb-t4",
    114		.max = 3,
    115		.mask = IXP4XX_EXP_T4_MASK,
    116		.shift = IXP4XX_EXP_T4_SHIFT,
    117	},
    118	{
    119		.prop = "intel,ixp4xx-eb-t5",
    120		.max = 15,
    121		.mask = IXP4XX_EXP_T5_MASK,
    122		.shift = IXP4XX_EXP_T5_SHIFT,
    123	},
    124	{
    125		.prop = "intel,ixp4xx-eb-byte-access-on-halfword",
    126		.max = 1,
    127		.mask = IXP4XX_EXP_BYTE_RD16,
    128	},
    129	{
    130		.prop = "intel,ixp4xx-eb-hpi-hrdy-pol-high",
    131		.max = 1,
    132		.mask = IXP4XX_EXP_HRDY_POL,
    133	},
    134	{
    135		.prop = "intel,ixp4xx-eb-mux-address-and-data",
    136		.max = 1,
    137		.mask = IXP4XX_EXP_MUX_EN,
    138	},
    139	{
    140		.prop = "intel,ixp4xx-eb-ahb-split-transfers",
    141		.max = 1,
    142		.mask = IXP4XX_EXP_SPLT_EN,
    143	},
    144	{
    145		.prop = "intel,ixp4xx-eb-write-enable",
    146		.max = 1,
    147		.mask = IXP4XX_EXP_WR_EN,
    148	},
    149	{
    150		.prop = "intel,ixp4xx-eb-byte-access",
    151		.max = 1,
    152		.mask = IXP4XX_EXP_BYTE_EN,
    153	},
    154};
    155
    156static void ixp4xx_exp_setup_chipselect(struct ixp4xx_eb *eb,
    157					struct device_node *np,
    158					u32 cs_index,
    159					u32 cs_size)
    160{
    161	u32 cs_cfg;
    162	u32 val;
    163	u32 cur_cssize;
    164	u32 cs_order;
    165	int ret;
    166	int i;
    167
    168	if (eb->is_42x && (cs_index > 7)) {
    169		dev_err(eb->dev,
    170			"invalid chipselect %u, we only support 0-7\n",
    171			cs_index);
    172		return;
    173	}
    174	if (eb->is_43x && (cs_index > 3)) {
    175		dev_err(eb->dev,
    176			"invalid chipselect %u, we only support 0-3\n",
    177			cs_index);
    178		return;
    179	}
    180
    181	/* Several chip selects can be joined into one device */
    182	if (cs_size > IXP4XX_EXP_STRIDE)
    183		cur_cssize = IXP4XX_EXP_STRIDE;
    184	else
    185		cur_cssize = cs_size;
    186
    187
    188	/*
    189	 * The following will read/modify/write the configuration for one
    190	 * chipselect, attempting to leave the boot defaults in place unless
    191	 * something is explicitly defined.
    192	 */
    193	regmap_read(eb->rmap, IXP4XX_EXP_TIMING_CS0 +
    194		    IXP4XX_EXP_TIMING_STRIDE * cs_index, &cs_cfg);
    195	dev_info(eb->dev, "CS%d at %#08x, size %#08x, config before: %#08x\n",
    196		 cs_index, eb->bus_base + IXP4XX_EXP_STRIDE * cs_index,
    197		 cur_cssize, cs_cfg);
    198
    199	/* Size set-up first align to 2^9 .. 2^24 */
    200	cur_cssize = roundup_pow_of_two(cur_cssize);
    201	if (cur_cssize < 512)
    202		cur_cssize = 512;
    203	cs_order = ilog2(cur_cssize);
    204	if (cs_order < 9 || cs_order > 24) {
    205		dev_err(eb->dev, "illegal size order %d\n", cs_order);
    206		return;
    207	}
    208	dev_dbg(eb->dev, "CS%d size order: %d\n", cs_index, cs_order);
    209	cs_cfg &= ~(IXP4XX_EXP_SIZE_MASK);
    210	cs_cfg |= ((cs_order - 9) << IXP4XX_EXP_SIZE_SHIFT);
    211
    212	for (i = 0; i < ARRAY_SIZE(ixp4xx_exp_tim_props); i++) {
    213		const struct ixp4xx_exp_tim_prop *ip = &ixp4xx_exp_tim_props[i];
    214
    215		/* All are regular u32 values */
    216		ret = of_property_read_u32(np, ip->prop, &val);
    217		if (ret)
    218			continue;
    219
    220		/* Handle bools (single bits) first */
    221		if (ip->max == 1) {
    222			if (val)
    223				cs_cfg |= ip->mask;
    224			else
    225				cs_cfg &= ~ip->mask;
    226			dev_info(eb->dev, "CS%d %s %s\n", cs_index,
    227				 val ? "enabled" : "disabled",
    228				 ip->prop);
    229			continue;
    230		}
    231
    232		if (val > ip->max) {
    233			dev_err(eb->dev,
    234				"CS%d too high value for %s: %u, capped at %u\n",
    235				cs_index, ip->prop, val, ip->max);
    236			val = ip->max;
    237		}
    238		/* This assumes max value fills all the assigned bits (and it does) */
    239		cs_cfg &= ~ip->mask;
    240		cs_cfg |= (val << ip->shift);
    241		dev_info(eb->dev, "CS%d set %s to %u\n", cs_index, ip->prop, val);
    242	}
    243
    244	ret = of_property_read_u32(np, "intel,ixp4xx-eb-cycle-type", &val);
    245	if (!ret) {
    246		if (val > 3) {
    247			dev_err(eb->dev, "illegal cycle type %d\n", val);
    248			return;
    249		}
    250		dev_info(eb->dev, "CS%d set cycle type %d\n", cs_index, val);
    251		cs_cfg &= ~IXP4XX_EXP_CYC_TYPE_MASK;
    252		cs_cfg |= val << IXP4XX_EXP_CYC_TYPE_SHIFT;
    253	}
    254
    255	if (eb->is_42x)
    256		cs_cfg &= ~IXP42X_RESERVED;
    257	if (eb->is_43x) {
    258		cs_cfg &= ~IXP43X_RESERVED;
    259		/*
    260		 * This bit for Intel strata flash is currently unused, but let's
    261		 * report it if we find one.
    262		 */
    263		if (cs_cfg & IXP43X_EXP_SYNC_INTEL)
    264			dev_info(eb->dev, "claims to be Intel strata flash\n");
    265	}
    266	cs_cfg |= IXP4XX_EXP_CS_EN;
    267
    268	regmap_write(eb->rmap,
    269		     IXP4XX_EXP_TIMING_CS0 + IXP4XX_EXP_TIMING_STRIDE * cs_index,
    270		     cs_cfg);
    271	dev_info(eb->dev, "CS%d wrote %#08x into CS config\n", cs_index, cs_cfg);
    272
    273	/*
    274	 * If several chip selects are joined together into one big
    275	 * device area, we call ourselves recursively for each successive
    276	 * chip select. For a 32MB flash chip this results in two calls
    277	 * for example.
    278	 */
    279	if (cs_size > IXP4XX_EXP_STRIDE)
    280		ixp4xx_exp_setup_chipselect(eb, np,
    281					    cs_index + 1,
    282					    cs_size - IXP4XX_EXP_STRIDE);
    283}
    284
    285static void ixp4xx_exp_setup_child(struct ixp4xx_eb *eb,
    286				   struct device_node *np)
    287{
    288	u32 cs_sizes[IXP4XX_EXP_NUM_CS];
    289	int num_regs;
    290	u32 csindex;
    291	u32 cssize;
    292	int ret;
    293	int i;
    294
    295	num_regs = of_property_count_elems_of_size(np, "reg", IXP4XX_OF_REG_SIZE);
    296	if (num_regs <= 0)
    297		return;
    298	dev_dbg(eb->dev, "child %s has %d register sets\n",
    299		of_node_full_name(np), num_regs);
    300
    301	for (csindex = 0; csindex < IXP4XX_EXP_NUM_CS; csindex++)
    302		cs_sizes[csindex] = 0;
    303
    304	for (i = 0; i < num_regs; i++) {
    305		u32 rbase, rsize;
    306
    307		ret = of_property_read_u32_index(np, "reg",
    308						 i * IXP4XX_OF_REG_SIZE, &csindex);
    309		if (ret)
    310			break;
    311		ret = of_property_read_u32_index(np, "reg",
    312						 i * IXP4XX_OF_REG_SIZE + 1, &rbase);
    313		if (ret)
    314			break;
    315		ret = of_property_read_u32_index(np, "reg",
    316						 i * IXP4XX_OF_REG_SIZE + 2, &rsize);
    317		if (ret)
    318			break;
    319
    320		if (csindex >= IXP4XX_EXP_NUM_CS) {
    321			dev_err(eb->dev, "illegal CS %d\n", csindex);
    322			continue;
    323		}
    324		/*
    325		 * The memory window always starts from CS base so we need to add
    326		 * the start and size to get to the size from the start of the CS
    327		 * base. For example if CS0 is at 0x50000000 and the reg is
    328		 * <0 0xe40000 0x40000> the size is e80000.
    329		 *
    330		 * Roof this if we have several regs setting the same CS.
    331		 */
    332		cssize = rbase + rsize;
    333		dev_dbg(eb->dev, "CS%d size %#08x\n", csindex, cssize);
    334		if (cs_sizes[csindex] < cssize)
    335			cs_sizes[csindex] = cssize;
    336	}
    337
    338	for (csindex = 0; csindex < IXP4XX_EXP_NUM_CS; csindex++) {
    339		cssize = cs_sizes[csindex];
    340		if (!cssize)
    341			continue;
    342		/* Just this one, so set it up and return */
    343		ixp4xx_exp_setup_chipselect(eb, np, csindex, cssize);
    344	}
    345}
    346
    347static int ixp4xx_exp_probe(struct platform_device *pdev)
    348{
    349	struct device *dev = &pdev->dev;
    350	struct device_node *np = dev->of_node;
    351	struct ixp4xx_eb *eb;
    352	struct device_node *child;
    353	bool have_children = false;
    354	u32 val;
    355	int ret;
    356
    357	eb = devm_kzalloc(dev, sizeof(*eb), GFP_KERNEL);
    358	if (!eb)
    359		return -ENOMEM;
    360
    361	eb->dev = dev;
    362	eb->is_42x = of_device_is_compatible(np, "intel,ixp42x-expansion-bus-controller");
    363	eb->is_43x = of_device_is_compatible(np, "intel,ixp43x-expansion-bus-controller");
    364
    365	eb->rmap = syscon_node_to_regmap(np);
    366	if (IS_ERR(eb->rmap))
    367		return dev_err_probe(dev, PTR_ERR(eb->rmap), "no regmap\n");
    368
    369	/* We check that the regmap work only on first read */
    370	ret = regmap_read(eb->rmap, IXP4XX_EXP_CNFG0, &val);
    371	if (ret)
    372		return dev_err_probe(dev, ret, "cannot read regmap\n");
    373	if (val & IXP4XX_EXP_CNFG0_MEM_MAP)
    374		eb->bus_base = IXP4XX_EXP_BOOT_BASE;
    375	else
    376		eb->bus_base = IXP4XX_EXP_NORMAL_BASE;
    377	dev_info(dev, "expansion bus at %08x\n", eb->bus_base);
    378
    379	if (eb->is_43x) {
    380		/* Check some fuses */
    381		regmap_read(eb->rmap, IXP43X_EXP_UNIT_FUSE_RESET, &val);
    382		switch (FIELD_GET(IXP43x_EXP_FUSE_SPEED_MASK, val)) {
    383		case 0:
    384			dev_info(dev, "IXP43x at 533 MHz\n");
    385			break;
    386		case 1:
    387			dev_info(dev, "IXP43x at 400 MHz\n");
    388			break;
    389		case 2:
    390			dev_info(dev, "IXP43x at 667 MHz\n");
    391			break;
    392		default:
    393			dev_info(dev, "IXP43x unknown speed\n");
    394			break;
    395		}
    396	}
    397
    398	/* Walk over the child nodes and see what chipselects we use */
    399	for_each_available_child_of_node(np, child) {
    400		ixp4xx_exp_setup_child(eb, child);
    401		/* We have at least one child */
    402		have_children = true;
    403	}
    404
    405	if (have_children)
    406		return of_platform_default_populate(np, NULL, dev);
    407
    408	return 0;
    409}
    410
    411static const struct of_device_id ixp4xx_exp_of_match[] = {
    412	{ .compatible = "intel,ixp42x-expansion-bus-controller", },
    413	{ .compatible = "intel,ixp43x-expansion-bus-controller", },
    414	{ .compatible = "intel,ixp45x-expansion-bus-controller", },
    415	{ .compatible = "intel,ixp46x-expansion-bus-controller", },
    416	{ }
    417};
    418
    419static struct platform_driver ixp4xx_exp_driver = {
    420	.probe = ixp4xx_exp_probe,
    421	.driver = {
    422		.name = "intel-extbus",
    423		.of_match_table = ixp4xx_exp_of_match,
    424	},
    425};
    426module_platform_driver(ixp4xx_exp_driver);
    427MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
    428MODULE_DESCRIPTION("Intel IXP4xx external bus driver");
    429MODULE_LICENSE("GPL");