mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-16 18:04:48 +00:00
drivers: misc: Add socfpga_dtreg driver for Intel SoCFPGA
Add socfpga_dtreg driver enablement for Intel SoCFPGA. Signed-off-by: Wan Yee Lau <wan.yee.lau@intel.com> Reviewed-by: Tien Fong Chee <tien.fong.chee@intel.com>
This commit is contained in:
parent
86fd291a79
commit
3f190c55a4
5 changed files with 205 additions and 0 deletions
|
@ -1116,6 +1116,8 @@ config ARCH_SOCFPGA
|
|||
select SPL_LIBGENERIC_SUPPORT
|
||||
select SPL_OF_CONTROL
|
||||
select SPL_SEPARATE_BSS if TARGET_SOCFPGA_SOC64
|
||||
select SPL_DRIVERS_MISC if TARGET_SOCFPGA_SOC64
|
||||
select SPL_SOCFPGA_DT_REG if TARGET_SOCFPGA_SOC64
|
||||
select SPL_SERIAL
|
||||
select SPL_SYSRESET
|
||||
select SPL_WATCHDOG
|
||||
|
|
80
doc/device-tree-bindings/misc/socfpga_dtreg.txt
Normal file
80
doc/device-tree-bindings/misc/socfpga_dtreg.txt
Normal file
|
@ -0,0 +1,80 @@
|
|||
* Firewall and privilege register settings in device tree
|
||||
|
||||
Required properties:
|
||||
--------------------
|
||||
|
||||
- compatible: should contain "intel,socfpga-dtreg"
|
||||
- reg: Physical base address and size of block register.
|
||||
- intel,offset-settings: 32-bit offset address of block register,
|
||||
followed by 32-bit value settings and
|
||||
the masking bits, only masking bit
|
||||
set to 1 allows modification.
|
||||
|
||||
The device tree node which describes secure and privilege register access
|
||||
configuration in compile time.
|
||||
|
||||
Most of these registers are expected to work except for the case which some
|
||||
registers configuration are required for granting access to some other
|
||||
registers, for example CCU registers have to be properly configured before
|
||||
allowing register configuration access to fpga2sdram firewall as shown in
|
||||
below example.
|
||||
|
||||
Some registers depend on runtime data for proper configuration are expected
|
||||
to be part of driver that generating these data for example configuration for
|
||||
soc_noc_fw_ddr_mpu_inst_0_ddr_scr block register depend on DDR size parsed from
|
||||
memory device tree node.
|
||||
|
||||
Please refer details of tested examples below for both fpga2sdram and QoS
|
||||
configuration with default reset value and the comments.
|
||||
|
||||
Example:
|
||||
--------
|
||||
|
||||
Configuration for multiple dtreg node support in device tree:
|
||||
|
||||
socfpga_dtreg0: socfpga-dtreg0 {
|
||||
compatible = "intel,socfpga-dtreg";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
bootph-all;
|
||||
|
||||
coh_cpu0_bypass_OC_Firewall_main_Firewall@f7100200 {
|
||||
reg = <0xf7100200 0x00000014>;
|
||||
intel,offset-settings =
|
||||
/*
|
||||
* Disable ocram security at CCU for
|
||||
* non secure access
|
||||
*/
|
||||
<0x0000004 0x8000ffff 0xe007ffff>,
|
||||
<0x0000008 0x8000ffff 0xe007ffff>,
|
||||
<0x000000c 0x8000ffff 0xe007ffff>,
|
||||
<0x0000010 0x8000ffff 0xe007ffff>;
|
||||
bootph-all;
|
||||
};
|
||||
};
|
||||
|
||||
socfpga_dtreg1: socfpga-dtreg1 {
|
||||
compatible = "intel,socfpga-dtreg";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
bootph-all;
|
||||
|
||||
soc_noc_fw_mpfe_csr_inst_0_mpfe_scr@f8020000 {
|
||||
reg = <0xf8020000 0x0000001c>;
|
||||
intel,offset-settings =
|
||||
/* Disable MPFE firewall for SMMU */
|
||||
<0x00000000 0x00010101 0x00010101>,
|
||||
/*
|
||||
* Disable MPFE firewall for HMC
|
||||
* adapter
|
||||
*/
|
||||
<0x00000004 0x00000001 0x00010101>;
|
||||
bootph-all;
|
||||
};
|
||||
};
|
||||
|
||||
To call the nodes use:
|
||||
|
||||
ret = uclass_get_device_by_name(UCLASS_NOP, "socfpga-dtreg0", &dev);
|
||||
ret = uclass_get_device_by_name(UCLASS_NOP, "socfpga-dtreg1", &dev);
|
||||
|
|
@ -689,4 +689,11 @@ config SL28CPLD
|
|||
the base driver which provides common access methods for the
|
||||
sub-drivers.
|
||||
|
||||
config SPL_SOCFPGA_DT_REG
|
||||
bool "Enable register setting from device tree in SPL"
|
||||
depends on SPL
|
||||
help
|
||||
Enable register setting from device tree. This also
|
||||
provides user a clean interface and all register settings are
|
||||
centralized in one place, device tree.
|
||||
endmenu
|
||||
|
|
|
@ -90,3 +90,4 @@ obj-$(CONFIG_K3_AVS0) += k3_avs.o
|
|||
obj-$(CONFIG_ESM_K3) += k3_esm.o
|
||||
obj-$(CONFIG_ESM_PMIC) += esm_pmic.o
|
||||
obj-$(CONFIG_SL28CPLD) += sl28cpld.o
|
||||
obj-$(CONFIG_SPL_SOCFPGA_SEC_REG) += socfpga_dtreg.o
|
||||
|
|
115
drivers/misc/socfpga_dtreg.c
Normal file
115
drivers/misc/socfpga_dtreg.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2024 Intel Corporation <www.intel.com>
|
||||
*/
|
||||
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
#define NUMBER_OF_ELEMENTS 3
|
||||
|
||||
static int socfpga_dtreg_probe(struct udevice *dev)
|
||||
{
|
||||
const fdt32_t *list;
|
||||
fdt_addr_t offset, base;
|
||||
fdt_val_t val, read_val, mask, set_mask;
|
||||
int size, i;
|
||||
u32 blk_sz, reg;
|
||||
ofnode node;
|
||||
const char *name = NULL;
|
||||
|
||||
debug("%s(dev=%p)\n", __func__, dev);
|
||||
|
||||
if (!dev_has_ofnode(dev))
|
||||
return 0;
|
||||
|
||||
dev_for_each_subnode(node, dev) {
|
||||
name = ofnode_get_name(node);
|
||||
if (!name)
|
||||
return -EINVAL;
|
||||
|
||||
if (ofnode_read_u32_index(node, "reg", 1, &blk_sz))
|
||||
return -EINVAL;
|
||||
|
||||
base = ofnode_get_addr(node);
|
||||
if (base == FDT_ADDR_T_NONE)
|
||||
return -EINVAL;
|
||||
|
||||
debug("%s(node_offset 0x%lx node_name %s ", __func__,
|
||||
node.of_offset, name);
|
||||
debug("node addr 0x%llx blk sz 0x%x)\n", base, blk_sz);
|
||||
|
||||
list = ofnode_read_prop(node, "intel,offset-settings", &size);
|
||||
if (!list)
|
||||
return -EINVAL;
|
||||
|
||||
debug("%s(intel,offset-settings property size=%x)\n", __func__,
|
||||
size);
|
||||
size /= sizeof(*list) * NUMBER_OF_ELEMENTS;
|
||||
|
||||
/*
|
||||
* First element: offset
|
||||
* Second element: val
|
||||
* Third element: mask
|
||||
*/
|
||||
for (i = 0; i < size; i++) {
|
||||
offset = fdt32_to_cpu(*list++);
|
||||
val = fdt32_to_cpu(*list++);
|
||||
|
||||
/* Reads the masking bit value from the list */
|
||||
mask = fdt32_to_cpu(*list++);
|
||||
|
||||
/*
|
||||
* Reads out the offsets, value and masking bits
|
||||
* Ex: <0x00000000 0x00000230 0xffffffff>
|
||||
*/
|
||||
debug("%s(intel,offset-settings 0x%llx : 0x%llx : 0x%llx)\n",
|
||||
__func__, offset, val, mask);
|
||||
|
||||
if (blk_sz < offset + SZ_4) {
|
||||
printf("%s: Overflow as offset 0x%llx or reg",
|
||||
__func__, offset);
|
||||
printf(" write is more than block size 0x%x\n",
|
||||
blk_sz);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mask != 0) {
|
||||
if (mask == 0xffffffff) {
|
||||
reg = base + offset;
|
||||
writel(val, (uintptr_t)reg);
|
||||
} else {
|
||||
/* Mask the value with the masking bits */
|
||||
set_mask = val & mask;
|
||||
|
||||
reg = base + offset;
|
||||
|
||||
/* Clears and sets specific bits in the register */
|
||||
clrsetbits_le32((uintptr_t)reg, mask, set_mask);
|
||||
}
|
||||
}
|
||||
|
||||
read_val = readl((uintptr_t)reg);
|
||||
|
||||
/* Reads out the register, masked value and the read value */
|
||||
debug("%s(reg 0x%x = wr : 0x%llx rd : 0x%llx)\n",
|
||||
__func__, reg, set_mask, read_val);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static const struct udevice_id socfpga_dtreg_ids[] = {
|
||||
{.compatible = "intel,socfpga-dtreg"},
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(socfpga_dtreg) = {
|
||||
.name = "socfpga-dtreg",
|
||||
.id = UCLASS_NOP,
|
||||
.of_match = socfpga_dtreg_ids,
|
||||
.probe = socfpga_dtreg_probe,
|
||||
};
|
Loading…
Add table
Reference in a new issue