253 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2023, STMicroelectronics - All Rights Reserved4 */5 6#include <linux/bitfield.h>7#include <linux/bits.h>8#include <linux/device.h>9#include <linux/err.h>10#include <linux/init.h>11#include <linux/io.h>12#include <linux/kernel.h>13#include <linux/module.h>14#include <linux/of.h>15#include <linux/of_platform.h>16#include <linux/platform_device.h>17#include <linux/types.h>18 19#include "stm32_firewall.h"20 21/*22 * RIFSC offset register23 */24#define RIFSC_RISC_SECCFGR0 0x1025#define RIFSC_RISC_PRIVCFGR0 0x3026#define RIFSC_RISC_PER0_CIDCFGR 0x10027#define RIFSC_RISC_PER0_SEMCR 0x10428#define RIFSC_RISC_HWCFGR2 0xFEC29 30/*31 * SEMCR register32 */33#define SEMCR_MUTEX BIT(0)34 35/*36 * HWCFGR2 register37 */38#define HWCFGR2_CONF1_MASK GENMASK(15, 0)39#define HWCFGR2_CONF2_MASK GENMASK(23, 16)40#define HWCFGR2_CONF3_MASK GENMASK(31, 24)41 42/*43 * RIFSC miscellaneous44 */45#define RIFSC_RISC_CFEN_MASK BIT(0)46#define RIFSC_RISC_SEM_EN_MASK BIT(1)47#define RIFSC_RISC_SCID_MASK GENMASK(6, 4)48#define RIFSC_RISC_SEML_SHIFT 1649#define RIFSC_RISC_SEMWL_MASK GENMASK(23, 16)50#define RIFSC_RISC_PER_ID_MASK GENMASK(31, 24)51 52#define RIFSC_RISC_PERx_CID_MASK (RIFSC_RISC_CFEN_MASK | \53 RIFSC_RISC_SEM_EN_MASK | \54 RIFSC_RISC_SCID_MASK | \55 RIFSC_RISC_SEMWL_MASK)56 57#define IDS_PER_RISC_SEC_PRIV_REGS 3258 59/* RIF miscellaneous */60/*61 * CIDCFGR register fields62 */63#define CIDCFGR_CFEN BIT(0)64#define CIDCFGR_SEMEN BIT(1)65#define CIDCFGR_SEMWL(x) BIT(RIFSC_RISC_SEML_SHIFT + (x))66 67#define SEMWL_SHIFT 1668 69/* Compartiment IDs */70#define RIF_CID0 0x071#define RIF_CID1 0x172 73static bool stm32_rifsc_is_semaphore_available(void __iomem *addr)74{75 return !(readl(addr) & SEMCR_MUTEX);76}77 78static int stm32_rif_acquire_semaphore(struct stm32_firewall_controller *stm32_firewall_controller,79 int id)80{81 void __iomem *addr = stm32_firewall_controller->mmio + RIFSC_RISC_PER0_SEMCR + 0x8 * id;82 83 writel(SEMCR_MUTEX, addr);84 85 /* Check that CID1 has the semaphore */86 if (stm32_rifsc_is_semaphore_available(addr) ||87 FIELD_GET(RIFSC_RISC_SCID_MASK, readl(addr)) != RIF_CID1)88 return -EACCES;89 90 return 0;91}92 93static void stm32_rif_release_semaphore(struct stm32_firewall_controller *stm32_firewall_controller,94 int id)95{96 void __iomem *addr = stm32_firewall_controller->mmio + RIFSC_RISC_PER0_SEMCR + 0x8 * id;97 98 if (stm32_rifsc_is_semaphore_available(addr))99 return;100 101 writel(SEMCR_MUTEX, addr);102 103 /* Ok if another compartment takes the semaphore before the check */104 WARN_ON(!stm32_rifsc_is_semaphore_available(addr) &&105 FIELD_GET(RIFSC_RISC_SCID_MASK, readl(addr)) == RIF_CID1);106}107 108static int stm32_rifsc_grant_access(struct stm32_firewall_controller *ctrl, u32 firewall_id)109{110 struct stm32_firewall_controller *rifsc_controller = ctrl;111 u32 reg_offset, reg_id, sec_reg_value, cid_reg_value;112 int rc;113 114 if (firewall_id >= rifsc_controller->max_entries) {115 dev_err(rifsc_controller->dev, "Invalid sys bus ID %u", firewall_id);116 return -EINVAL;117 }118 119 /*120 * RIFSC_RISC_PRIVCFGRx and RIFSC_RISC_SECCFGRx both handle configuration access for121 * 32 peripherals. On the other hand, there is one _RIFSC_RISC_PERx_CIDCFGR register122 * per peripheral123 */124 reg_id = firewall_id / IDS_PER_RISC_SEC_PRIV_REGS;125 reg_offset = firewall_id % IDS_PER_RISC_SEC_PRIV_REGS;126 sec_reg_value = readl(rifsc_controller->mmio + RIFSC_RISC_SECCFGR0 + 0x4 * reg_id);127 cid_reg_value = readl(rifsc_controller->mmio + RIFSC_RISC_PER0_CIDCFGR + 0x8 * firewall_id);128 129 /* First check conditions for semaphore mode, which doesn't take into account static CID. */130 if ((cid_reg_value & CIDCFGR_SEMEN) && (cid_reg_value & CIDCFGR_CFEN)) {131 if (cid_reg_value & BIT(RIF_CID1 + SEMWL_SHIFT)) {132 /* Static CID is irrelevant if semaphore mode */133 goto skip_cid_check;134 } else {135 dev_dbg(rifsc_controller->dev,136 "Invalid bus semaphore configuration: index %d\n", firewall_id);137 return -EACCES;138 }139 }140 141 /*142 * Skip CID check if CID filtering isn't enabled or filtering is enabled on CID0, which143 * corresponds to whatever CID.144 */145 if (!(cid_reg_value & CIDCFGR_CFEN) ||146 FIELD_GET(RIFSC_RISC_SCID_MASK, cid_reg_value) == RIF_CID0)147 goto skip_cid_check;148 149 /* Coherency check with the CID configuration */150 if (FIELD_GET(RIFSC_RISC_SCID_MASK, cid_reg_value) != RIF_CID1) {151 dev_dbg(rifsc_controller->dev, "Invalid CID configuration for peripheral: %d\n",152 firewall_id);153 return -EACCES;154 }155 156skip_cid_check:157 /* Check security configuration */158 if (sec_reg_value & BIT(reg_offset)) {159 dev_dbg(rifsc_controller->dev,160 "Invalid security configuration for peripheral: %d\n", firewall_id);161 return -EACCES;162 }163 164 /*165 * If the peripheral is in semaphore mode, take the semaphore so that166 * the CID1 has the ownership.167 */168 if ((cid_reg_value & CIDCFGR_SEMEN) && (cid_reg_value & CIDCFGR_CFEN)) {169 rc = stm32_rif_acquire_semaphore(rifsc_controller, firewall_id);170 if (rc) {171 dev_err(rifsc_controller->dev,172 "Couldn't acquire semaphore for peripheral: %d\n", firewall_id);173 return rc;174 }175 }176 177 return 0;178}179 180static void stm32_rifsc_release_access(struct stm32_firewall_controller *ctrl, u32 firewall_id)181{182 stm32_rif_release_semaphore(ctrl, firewall_id);183}184 185static int stm32_rifsc_probe(struct platform_device *pdev)186{187 struct stm32_firewall_controller *rifsc_controller;188 struct device_node *np = pdev->dev.of_node;189 u32 nb_risup, nb_rimu, nb_risal;190 struct resource *res;191 void __iomem *mmio;192 int rc;193 194 rifsc_controller = devm_kzalloc(&pdev->dev, sizeof(*rifsc_controller), GFP_KERNEL);195 if (!rifsc_controller)196 return -ENOMEM;197 198 mmio = devm_platform_get_and_ioremap_resource(pdev, 0, &res);199 if (IS_ERR(mmio))200 return PTR_ERR(mmio);201 202 rifsc_controller->dev = &pdev->dev;203 rifsc_controller->mmio = mmio;204 rifsc_controller->name = dev_driver_string(rifsc_controller->dev);205 rifsc_controller->type = STM32_PERIPHERAL_FIREWALL | STM32_MEMORY_FIREWALL;206 rifsc_controller->grant_access = stm32_rifsc_grant_access;207 rifsc_controller->release_access = stm32_rifsc_release_access;208 209 /* Get number of RIFSC entries*/210 nb_risup = readl(rifsc_controller->mmio + RIFSC_RISC_HWCFGR2) & HWCFGR2_CONF1_MASK;211 nb_rimu = readl(rifsc_controller->mmio + RIFSC_RISC_HWCFGR2) & HWCFGR2_CONF2_MASK;212 nb_risal = readl(rifsc_controller->mmio + RIFSC_RISC_HWCFGR2) & HWCFGR2_CONF3_MASK;213 rifsc_controller->max_entries = nb_risup + nb_rimu + nb_risal;214 215 platform_set_drvdata(pdev, rifsc_controller);216 217 rc = stm32_firewall_controller_register(rifsc_controller);218 if (rc) {219 dev_err(rifsc_controller->dev, "Couldn't register as a firewall controller: %d",220 rc);221 return rc;222 }223 224 rc = stm32_firewall_populate_bus(rifsc_controller);225 if (rc) {226 dev_err(rifsc_controller->dev, "Couldn't populate RIFSC bus: %d",227 rc);228 return rc;229 }230 231 /* Populate all allowed nodes */232 return of_platform_populate(np, NULL, NULL, &pdev->dev);233}234 235static const struct of_device_id stm32_rifsc_of_match[] = {236 { .compatible = "st,stm32mp25-rifsc" },237 {}238};239MODULE_DEVICE_TABLE(of, stm32_rifsc_of_match);240 241static struct platform_driver stm32_rifsc_driver = {242 .probe = stm32_rifsc_probe,243 .driver = {244 .name = "stm32-rifsc",245 .of_match_table = stm32_rifsc_of_match,246 },247};248module_platform_driver(stm32_rifsc_driver);249 250MODULE_AUTHOR("Gatien Chevallier <gatien.chevallier@foss.st.com>");251MODULE_DESCRIPTION("STMicroelectronics RIFSC driver");252MODULE_LICENSE("GPL");253