1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2021 Pali Roh��r <pali@kernel.org> 4 * Copyright (C) 2024 Marek Beh��n <kabel@kernel.org> 5 */ 6 7#include <common.h> 8#include <dm.h> 9#include <dm/lists.h> 10#include <regmap.h> 11#include <reset-uclass.h> 12#include <syscon.h> 13#include <sysreset.h> 14#include <asm/io.h> 15 16#define MVEBU_SOC_CONTROL_1_REG 0x4 17 18#if defined(CONFIG_ARMADA_375) 19# define MVEBU_RSTOUTN_MASK_REG 0x54 20# define MVEBU_SYS_SOFT_RST_REG 0x58 21#else 22# define MVEBU_RSTOUTN_MASK_REG 0x60 23# define MVEBU_SYS_SOFT_RST_REG 0x64 24#endif 25 26#define MVEBU_GLOBAL_SOFT_RST_BIT BIT(0) 27 28#define MVEBU_PCIE_ID 0 29 30#if IS_ENABLED(CONFIG_ARMADA_32BIT_SYSCON_RESET) 31 32static int mvebu_reset_of_xlate(struct reset_ctl *rst, 33 struct ofnode_phandle_args *args) 34{ 35 if (args->args_count < 2) 36 return -EINVAL; 37 38 rst->id = args->args[0]; 39 rst->data = args->args[1]; 40 41 /* Currently only PCIe is implemented */ 42 if (rst->id != MVEBU_PCIE_ID) 43 return -EINVAL; 44 45 /* Four PCIe enable bits are shared across more PCIe links */ 46 if (!(rst->data >= 0 && rst->data <= 3)) 47 return -EINVAL; 48 49 return 0; 50} 51 52static int mvebu_reset_request(struct reset_ctl *rst) 53{ 54 return 0; 55} 56 57static int mvebu_reset_free(struct reset_ctl *rst) 58{ 59 return 0; 60} 61 62static int mvebu_reset_assert(struct reset_ctl *rst) 63{ 64 struct regmap *regmap = syscon_get_regmap(rst->dev->parent); 65 66 return regmap_update_bits(regmap, MVEBU_SOC_CONTROL_1_REG, 67 BIT(rst->data), 0); 68} 69 70static int mvebu_reset_deassert(struct reset_ctl *rst) 71{ 72 struct regmap *regmap = syscon_get_regmap(rst->dev->parent); 73 74 return regmap_update_bits(regmap, MVEBU_SOC_CONTROL_1_REG, 75 BIT(rst->data), BIT(rst->data)); 76} 77 78static int mvebu_reset_status(struct reset_ctl *rst) 79{ 80 struct regmap *regmap = syscon_get_regmap(rst->dev->parent); 81 uint val; 82 int ret; 83 84 ret = regmap_read(regmap, MVEBU_SOC_CONTROL_1_REG, &val); 85 if (ret < 0) 86 return ret; 87 88 return !(val & BIT(rst->data)); 89} 90 91static const struct reset_ops mvebu_reset_ops = { 92 .of_xlate = mvebu_reset_of_xlate, 93 .request = mvebu_reset_request, 94 .rfree = mvebu_reset_free, 95 .rst_assert = mvebu_reset_assert, 96 .rst_deassert = mvebu_reset_deassert, 97 .rst_status = mvebu_reset_status, 98}; 99 100U_BOOT_DRIVER(mvebu_reset) = { 101 .name = "mvebu-reset", 102 .id = UCLASS_RESET, 103 .ops = &mvebu_reset_ops, 104}; 105 106#endif /* IS_ENABLED(CONFIG_ARMADA_32BIT_SYSCON_RESET) */ 107 108#if IS_ENABLED(CONFIG_ARMADA_32BIT_SYSCON_SYSRESET) 109 110static int mvebu_sysreset_request(struct udevice *dev, enum sysreset_t type) 111{ 112 struct regmap *regmap = syscon_get_regmap(dev->parent); 113 uint bit; 114 115 if (type != SYSRESET_COLD) 116 return -EPROTONOSUPPORT; 117 118 bit = MVEBU_GLOBAL_SOFT_RST_BIT; 119 120 regmap_update_bits(regmap, MVEBU_RSTOUTN_MASK_REG, bit, bit); 121 regmap_update_bits(regmap, MVEBU_SYS_SOFT_RST_REG, bit, bit); 122 123 /* Loop while waiting for the reset */ 124 while (1) 125 ; 126 127 return 0; 128} 129 130static struct sysreset_ops mvebu_sysreset_ops = { 131 .request = mvebu_sysreset_request, 132}; 133 134U_BOOT_DRIVER(mvebu_sysreset) = { 135 .name = "mvebu-sysreset", 136 .id = UCLASS_SYSRESET, 137 .ops = &mvebu_sysreset_ops, 138}; 139 140#endif /* IS_ENABLED(CONFIG_ARMADA_32BIT_SYSCON_SYSRESET) */ 141 142static int mvebu_syscon_bind(struct udevice *dev) 143{ 144 int ret = 0; 145 146 /* bind also mvebu-reset, with the same ofnode */ 147 if (IS_ENABLED(CONFIG_ARMADA_32BIT_SYSCON_RESET)) { 148 ret = device_bind_driver_to_node(dev, "mvebu-reset", 149 "mvebu-reset", dev_ofnode(dev), 150 NULL); 151 if (ret < 0) 152 return ret; 153 } 154 155 /* bind also mvebu-sysreset, with the same ofnode */ 156 if (IS_ENABLED(CONFIG_ARMADA_32BIT_SYSCON_SYSRESET)) { 157 ret = device_bind_driver_to_node(dev, "mvebu-sysreset", 158 "mvebu-sysreset", 159 dev_ofnode(dev), NULL); 160 if (ret < 0) 161 return ret; 162 } 163 164 return ret; 165} 166 167static const struct udevice_id mvebu_syscon_of_match[] = { 168 { .compatible = "marvell,armada-370-xp-system-controller" }, 169 { .compatible = "marvell,armada-375-system-controller" }, 170 { .compatible = "marvell,armada-380-system-controller" }, 171 { .compatible = "marvell,armada-390-system-controller" }, 172 { }, 173}; 174 175U_BOOT_DRIVER(mvebu_syscon) = { 176 .name = "mvebu-system-controller", 177 .id = UCLASS_SYSCON, 178 .of_match = mvebu_syscon_of_match, 179 .bind = mvebu_syscon_bind, 180}; 181