lkml.org 
[lkml]   [2019]   [Mar]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RESEND PATCH 5/7] bus: domainsctrl: Add driver for STM32 ETZPC controller
    Date
    STM32 Extended TrustZone Protection Controller (ETZPC) got 3 domains:
    - secure: hardware blocks are only accessible by software running on trust
    zone.
    - non-secure: hardware blocks are accessible by non-secure software (i.e.
    linux kernel).
    - coprocessor: hardware blocks are only accessible by the corpocessor.

    Each hardware block status is defined by a 2 bits field and all of
    them are packed into 32 bits registers. ETZPC can manage up to 94
    hardware blocks.

    Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
    ---
    drivers/bus/domains/Kconfig | 7 ++
    drivers/bus/domains/Makefile | 1 +
    drivers/bus/domains/stm32-etzpc.c | 140 ++++++++++++++++++++++++++
    include/dt-bindings/bus/domains/stm32-etzpc.h | 25 +++++
    4 files changed, 173 insertions(+)
    create mode 100644 drivers/bus/domains/stm32-etzpc.c
    create mode 100644 include/dt-bindings/bus/domains/stm32-etzpc.h

    diff --git a/drivers/bus/domains/Kconfig b/drivers/bus/domains/Kconfig
    index 5ba15f750bee..7afd209e8c4f 100644
    --- a/drivers/bus/domains/Kconfig
    +++ b/drivers/bus/domains/Kconfig
    @@ -4,4 +4,11 @@ config DOMAINS_CONTROLLERS
    bool "Support of bus domains controllers"
    depends on OF

    +config STM32_ETZPC
    + bool "STM32 ETZPC Domain Controller"
    + depends on DOMAINS_CONTROLLERS && MACH_STM32MP157
    + help
    + Select y to enable STM32 Extended TrustZone Protection
    + Controller (ETZPC)
    +
    endmenu
    diff --git a/drivers/bus/domains/Makefile b/drivers/bus/domains/Makefile
    index 262338b7cad5..8000de6023a5 100644
    --- a/drivers/bus/domains/Makefile
    +++ b/drivers/bus/domains/Makefile
    @@ -1 +1,2 @@
    obj-$(CONFIG_DOMAINS_CONTROLLERS) += domainsctrl.o
    +obj-$(CONFIG_STM32_ETZPC) += stm32-etzpc.o
    diff --git a/drivers/bus/domains/stm32-etzpc.c b/drivers/bus/domains/stm32-etzpc.c
    new file mode 100644
    index 000000000000..8a03128a8715
    --- /dev/null
    +++ b/drivers/bus/domains/stm32-etzpc.c
    @@ -0,0 +1,140 @@
    +// SPDX-License-Identifier: GPL-2.0
    +/*
    + * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
    + * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
    + */
    +
    +#include <linux/device.h>
    +#include <linux/domainsctrl.h>
    +#include <linux/err.h>
    +#include <linux/init.h>
    +#include <linux/kernel.h>
    +#include <linux/module.h>
    +#include <linux/of.h>
    +#include <linux/platform_device.h>
    +#include <linux/regmap.h>
    +
    +#include <dt-bindings/bus/domains/stm32-etzpc.h>
    +
    +#define ETZPC_DECPROT 0x010
    +#define ETZPC_NUM_LOCKS 94
    +
    +struct stm32_etzpc {
    + struct regmap_field *fields[ETZPC_NUM_LOCKS];
    +};
    +
    +static int stm32_etzpc_set_config(struct device *dev,
    + struct of_phandle_args *out_args)
    +{
    + struct stm32_etzpc *etzpc = dev_get_drvdata(dev);
    + int index = out_args->args[0];
    + unsigned int value = out_args->args[1];
    + u32 status;
    +
    + if (out_args->args_count != 2)
    + return -EINVAL;
    +
    + if (index >= ETZPC_NUM_LOCKS)
    + return -EINVAL;
    +
    + if (value > STM32_ETZPC_NON_SECURE)
    + return -EINVAL;
    +
    + regmap_field_force_write(etzpc->fields[index], value);
    +
    + /* Hardware could denied the new value, read it back to check it */
    + regmap_field_read(etzpc->fields[index], &status);
    +
    + if (value != status) {
    + dev_info(dev, "failed to set configuration: index %d, value %d\n",
    + index, value);
    + return -EINVAL;
    + }
    +
    + return 0;
    +}
    +
    +static struct domains_ctrl_ops stm32_etzpc_ops = {
    + .set_config = stm32_etzpc_set_config,
    +};
    +
    +static const struct regmap_config stm32_etzpc_regmap_cfg = {
    + .reg_bits = 32,
    + .val_bits = 32,
    + .reg_stride = sizeof(u32),
    + .max_register = 0x3FF,
    + .fast_io = true,
    +};
    +
    +static int stm32_etzpc_probe(struct platform_device *pdev)
    +{
    + struct stm32_etzpc *etzpc;
    + struct resource *res;
    + void __iomem *mmio;
    + struct regmap *regmap;
    + int i;
    +
    + etzpc = devm_kzalloc(&pdev->dev, sizeof(*etzpc), GFP_KERNEL);
    + if (!etzpc)
    + return -ENOMEM;
    +
    + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    + mmio = devm_ioremap_resource(&pdev->dev, res);
    + if (IS_ERR(mmio))
    + return PTR_ERR(mmio);
    +
    + regmap = devm_regmap_init_mmio(&pdev->dev, mmio,
    + &stm32_etzpc_regmap_cfg);
    +
    + for (i = 0; i < ETZPC_NUM_LOCKS; i++) {
    + struct reg_field field;
    +
    + /*
    + * Each hardware block status is defined by
    + * a 2 bits field and all of them are packed into
    + * 32 bits registers. Do some computation to get
    + * register offset and the shift.
    + */
    + field.reg = ETZPC_DECPROT + (i >> 4) * sizeof(u32);
    + field.lsb = (i % 0x10) << 1;
    + field.msb = field.lsb + 1;
    +
    + etzpc->fields[i] = devm_regmap_field_alloc(&pdev->dev,
    + regmap, field);
    + }
    +
    + platform_set_drvdata(pdev, etzpc);
    +
    + return domainsctrl_register(&pdev->dev, &stm32_etzpc_ops);
    +}
    +
    +static int stm32_etzpc_remove(struct platform_device *pdev)
    +{
    + domainsctrl_unregister(&pdev->dev);
    +
    + return 0;
    +}
    +
    +static const struct of_device_id stm32_etzpc_of_match[] = {
    + { .compatible = "st,stm32-etzpc" },
    + { /* end node */ }
    +};
    +MODULE_DEVICE_TABLE(of, stm32_etzpc_of_match);
    +
    +static struct platform_driver stm32_etzpc_driver = {
    + .probe = stm32_etzpc_probe,
    + .remove = stm32_etzpc_remove,
    + .driver = {
    + .name = "stm32-etzpc",
    + .of_match_table = stm32_etzpc_of_match,
    + },
    +};
    +
    +static int __init stm32_etzpc_init(void)
    +{
    + return platform_driver_register(&stm32_etzpc_driver);
    +}
    +arch_initcall(stm32_etzpc_init);
    +
    +MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
    +MODULE_DESCRIPTION("STMicroelectronics STM32 Bus Dommains Controller");
    diff --git a/include/dt-bindings/bus/domains/stm32-etzpc.h b/include/dt-bindings/bus/domains/stm32-etzpc.h
    new file mode 100644
    index 000000000000..93190fa29a9c
    --- /dev/null
    +++ b/include/dt-bindings/bus/domains/stm32-etzpc.h
    @@ -0,0 +1,25 @@
    +/* SPDX-License-Identifier: GPL-2.0 */
    +/*
    + * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
    + * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
    + */
    +
    +#ifndef _STM32_ETZPC_H_
    +#define _STM32_ETZPC_H_
    +
    +/* ETZPC domains: secure, non-secure or coprocessor*/
    +#define STM32_ETZPC_SECURE 1
    +#define STM32_ETPCZ_COPRO 2
    +#define STM32_ETZPC_NON_SECURE 3
    +
    +/* ETZPC hard blaokcs index */
    +#define STM32_ETZPC_USART1 3
    +#define STM32_ETZPC_SPI6 4
    +#define STM32_ETZPC_I2C4 5
    +#define STM32_ETZPC_RNG1 7
    +#define STM32_ETZPC_HASH1 8
    +#define STM32_ETZPC_CRYP1 9
    +#define STM32_ETZPC_I2C6 12
    +#define STM32_ETZPC_CEC 38
    +
    +#endif /* _STM32_ETZPC_H_ */
    --
    2.15.0
    \
     
     \ /
      Last update: 2019-03-18 11:07    [W:7.795 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site