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 18 /* register values */ 19 #define TH1520_GPU_SW_GPU_RST BIT(0) 20 #define TH1520_GPU_SW_CLKGEN_RST BIT(1) 21 22 struct th1520_reset_priv { 23 struct reset_controller_dev rcdev; 24 struct regmap *map; 25 }; 26 27 struct th1520_reset_map { 28 u32 bit; 29 u32 reg; 30 }; 31 32 static const struct th1520_reset_map th1520_resets[] = { 33 [TH1520_RESET_ID_GPU] = { 34 .bit = TH1520_GPU_SW_GPU_RST, 35 .reg = TH1520_GPU_RST_CFG, 36 }, 37 [TH1520_RESET_ID_GPU_CLKGEN] = { 38 .bit = TH1520_GPU_SW_CLKGEN_RST, 39 .reg = TH1520_GPU_RST_CFG, 40 } 41 }; 42 43 static inline struct th1520_reset_priv * 44 to_th1520_reset(struct reset_controller_dev *rcdev) 45 { 46 return container_of(rcdev, struct th1520_reset_priv, rcdev); 47 } 48 49 static int th1520_reset_assert(struct reset_controller_dev *rcdev, 50 unsigned long id) 51 { 52 struct th1520_reset_priv *priv = to_th1520_reset(rcdev); 53 const struct th1520_reset_map *reset; 54 55 reset = &th1520_resets[id]; 56 57 return regmap_update_bits(priv->map, reset->reg, reset->bit, 0); 58 } 59 60 static int th1520_reset_deassert(struct reset_controller_dev *rcdev, 61 unsigned long id) 62 { 63 struct th1520_reset_priv *priv = to_th1520_reset(rcdev); 64 const struct th1520_reset_map *reset; 65 66 reset = &th1520_resets[id]; 67 68 return regmap_update_bits(priv->map, reset->reg, reset->bit, 69 reset->bit); 70 } 71 72 static const struct reset_control_ops th1520_reset_ops = { 73 .assert = th1520_reset_assert, 74 .deassert = th1520_reset_deassert, 75 }; 76 77 static const struct regmap_config th1520_reset_regmap_config = { 78 .reg_bits = 32, 79 .val_bits = 32, 80 .reg_stride = 4, 81 .fast_io = true, 82 }; 83 84 static int th1520_reset_probe(struct platform_device *pdev) 85 { 86 struct device *dev = &pdev->dev; 87 struct th1520_reset_priv *priv; 88 void __iomem *base; 89 int ret; 90 91 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 92 if (!priv) 93 return -ENOMEM; 94 95 base = devm_platform_ioremap_resource(pdev, 0); 96 if (IS_ERR(base)) 97 return PTR_ERR(base); 98 99 priv->map = devm_regmap_init_mmio(dev, base, 100 &th1520_reset_regmap_config); 101 if (IS_ERR(priv->map)) 102 return PTR_ERR(priv->map); 103 104 /* Initialize GPU resets to asserted state */ 105 ret = regmap_update_bits(priv->map, TH1520_GPU_RST_CFG, 106 TH1520_GPU_RST_CFG_MASK, 0); 107 if (ret) 108 return ret; 109 110 priv->rcdev.owner = THIS_MODULE; 111 priv->rcdev.nr_resets = ARRAY_SIZE(th1520_resets); 112 priv->rcdev.ops = &th1520_reset_ops; 113 priv->rcdev.of_node = dev->of_node; 114 115 return devm_reset_controller_register(dev, &priv->rcdev); 116 } 117 118 static const struct of_device_id th1520_reset_match[] = { 119 { .compatible = "thead,th1520-reset" }, 120 { /* sentinel */ } 121 }; 122 MODULE_DEVICE_TABLE(of, th1520_reset_match); 123 124 static struct platform_driver th1520_reset_driver = { 125 .driver = { 126 .name = "th1520-reset", 127 .of_match_table = th1520_reset_match, 128 }, 129 .probe = th1520_reset_probe, 130 }; 131 module_platform_driver(th1520_reset_driver); 132 133 MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@samsung.com>"); 134 MODULE_DESCRIPTION("T-HEAD TH1520 SoC reset controller"); 135 MODULE_LICENSE("GPL"); 136