1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2024 Samsung Electronics Co., Ltd. 4 * Author: Michal Wilczynski <m.wilczynski@samsung.com> 5 */ 6 7 #include <linux/of.h> 8 #include <linux/platform_device.h> 9 #include <linux/reset-controller.h> 10 #include <linux/regmap.h> 11 12 #include <dt-bindings/reset/thead,th1520-reset.h> 13 14 /* register offset in VOSYS_REGMAP */ 15 #define TH1520_GPU_RST_CFG 0x0 16 #define TH1520_GPU_RST_CFG_MASK GENMASK(1, 0) 17 #define TH1520_DPU_RST_CFG 0x4 18 #define TH1520_DSI0_RST_CFG 0x8 19 #define TH1520_DSI1_RST_CFG 0xc 20 #define TH1520_HDMI_RST_CFG 0x14 21 22 /* register values */ 23 #define TH1520_GPU_SW_GPU_RST BIT(0) 24 #define TH1520_GPU_SW_CLKGEN_RST BIT(1) 25 #define TH1520_DPU_SW_DPU_HRST BIT(0) 26 #define TH1520_DPU_SW_DPU_ARST BIT(1) 27 #define TH1520_DPU_SW_DPU_CRST BIT(2) 28 #define TH1520_DSI_SW_DSI_PRST BIT(0) 29 #define TH1520_HDMI_SW_MAIN_RST BIT(0) 30 #define TH1520_HDMI_SW_PRST BIT(1) 31 32 struct th1520_reset_priv { 33 struct reset_controller_dev rcdev; 34 struct regmap *map; 35 }; 36 37 struct th1520_reset_map { 38 u32 bit; 39 u32 reg; 40 }; 41 42 static const struct th1520_reset_map th1520_resets[] = { 43 [TH1520_RESET_ID_GPU] = { 44 .bit = TH1520_GPU_SW_GPU_RST, 45 .reg = TH1520_GPU_RST_CFG, 46 }, 47 [TH1520_RESET_ID_GPU_CLKGEN] = { 48 .bit = TH1520_GPU_SW_CLKGEN_RST, 49 .reg = TH1520_GPU_RST_CFG, 50 }, 51 [TH1520_RESET_ID_DPU_AHB] = { 52 .bit = TH1520_DPU_SW_DPU_HRST, 53 .reg = TH1520_DPU_RST_CFG, 54 }, 55 [TH1520_RESET_ID_DPU_AXI] = { 56 .bit = TH1520_DPU_SW_DPU_ARST, 57 .reg = TH1520_DPU_RST_CFG, 58 }, 59 [TH1520_RESET_ID_DPU_CORE] = { 60 .bit = TH1520_DPU_SW_DPU_CRST, 61 .reg = TH1520_DPU_RST_CFG, 62 }, 63 [TH1520_RESET_ID_DSI0_APB] = { 64 .bit = TH1520_DSI_SW_DSI_PRST, 65 .reg = TH1520_DSI0_RST_CFG, 66 }, 67 [TH1520_RESET_ID_DSI1_APB] = { 68 .bit = TH1520_DSI_SW_DSI_PRST, 69 .reg = TH1520_DSI1_RST_CFG, 70 }, 71 [TH1520_RESET_ID_HDMI] = { 72 .bit = TH1520_HDMI_SW_MAIN_RST, 73 .reg = TH1520_HDMI_RST_CFG, 74 }, 75 [TH1520_RESET_ID_HDMI_APB] = { 76 .bit = TH1520_HDMI_SW_PRST, 77 .reg = TH1520_HDMI_RST_CFG, 78 }, 79 }; 80 81 static inline struct th1520_reset_priv * 82 to_th1520_reset(struct reset_controller_dev *rcdev) 83 { 84 return container_of(rcdev, struct th1520_reset_priv, rcdev); 85 } 86 87 static int th1520_reset_assert(struct reset_controller_dev *rcdev, 88 unsigned long id) 89 { 90 struct th1520_reset_priv *priv = to_th1520_reset(rcdev); 91 const struct th1520_reset_map *reset; 92 93 reset = &th1520_resets[id]; 94 95 return regmap_update_bits(priv->map, reset->reg, reset->bit, 0); 96 } 97 98 static int th1520_reset_deassert(struct reset_controller_dev *rcdev, 99 unsigned long id) 100 { 101 struct th1520_reset_priv *priv = to_th1520_reset(rcdev); 102 const struct th1520_reset_map *reset; 103 104 reset = &th1520_resets[id]; 105 106 return regmap_update_bits(priv->map, reset->reg, reset->bit, 107 reset->bit); 108 } 109 110 static const struct reset_control_ops th1520_reset_ops = { 111 .assert = th1520_reset_assert, 112 .deassert = th1520_reset_deassert, 113 }; 114 115 static const struct regmap_config th1520_reset_regmap_config = { 116 .reg_bits = 32, 117 .val_bits = 32, 118 .reg_stride = 4, 119 }; 120 121 static int th1520_reset_probe(struct platform_device *pdev) 122 { 123 struct device *dev = &pdev->dev; 124 struct th1520_reset_priv *priv; 125 void __iomem *base; 126 int ret; 127 128 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 129 if (!priv) 130 return -ENOMEM; 131 132 base = devm_platform_ioremap_resource(pdev, 0); 133 if (IS_ERR(base)) 134 return PTR_ERR(base); 135 136 priv->map = devm_regmap_init_mmio(dev, base, 137 &th1520_reset_regmap_config); 138 if (IS_ERR(priv->map)) 139 return PTR_ERR(priv->map); 140 141 /* Initialize GPU resets to asserted state */ 142 ret = regmap_update_bits(priv->map, TH1520_GPU_RST_CFG, 143 TH1520_GPU_RST_CFG_MASK, 0); 144 if (ret) 145 return ret; 146 147 priv->rcdev.owner = THIS_MODULE; 148 priv->rcdev.nr_resets = ARRAY_SIZE(th1520_resets); 149 priv->rcdev.ops = &th1520_reset_ops; 150 priv->rcdev.of_node = dev->of_node; 151 152 return devm_reset_controller_register(dev, &priv->rcdev); 153 } 154 155 static const struct of_device_id th1520_reset_match[] = { 156 { .compatible = "thead,th1520-reset" }, 157 { /* sentinel */ } 158 }; 159 MODULE_DEVICE_TABLE(of, th1520_reset_match); 160 161 static struct platform_driver th1520_reset_driver = { 162 .driver = { 163 .name = "th1520-reset", 164 .of_match_table = th1520_reset_match, 165 }, 166 .probe = th1520_reset_probe, 167 }; 168 module_platform_driver(th1520_reset_driver); 169 170 MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@samsung.com>"); 171 MODULE_DESCRIPTION("T-HEAD TH1520 SoC reset controller"); 172 MODULE_LICENSE("GPL"); 173