1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2013 STMicroelectronics Limited 4 * Author: Stephen Gallimore <stephen.gallimore@st.com> 5 * 6 * Inspired by mach-imx/src.c 7 */ 8 #include <linux/kernel.h> 9 #include <linux/platform_device.h> 10 #include <linux/module.h> 11 #include <linux/err.h> 12 #include <linux/types.h> 13 #include <linux/of_device.h> 14 #include <linux/regmap.h> 15 #include <linux/mfd/syscon.h> 16 17 #include "reset-syscfg.h" 18 19 /** 20 * struct syscfg_reset_channel - Reset channel regmap configuration 21 * 22 * @reset: regmap field for the channel's reset bit. 23 * @ack: regmap field for the channel's ack bit (optional). 24 */ 25 struct syscfg_reset_channel { 26 struct regmap_field *reset; 27 struct regmap_field *ack; 28 }; 29 30 /** 31 * struct syscfg_reset_controller - A reset controller which groups together 32 * a set of related reset bits, which may be located in different system 33 * configuration registers. 34 * 35 * @rst: base reset controller structure. 36 * @active_low: are the resets in this controller active low, i.e. clearing 37 * the reset bit puts the hardware into reset. 38 * @channels: An array of reset channels for this controller. 39 */ 40 struct syscfg_reset_controller { 41 struct reset_controller_dev rst; 42 bool active_low; 43 struct syscfg_reset_channel *channels; 44 }; 45 46 #define to_syscfg_reset_controller(_rst) \ 47 container_of(_rst, struct syscfg_reset_controller, rst) 48 49 static int syscfg_reset_program_hw(struct reset_controller_dev *rcdev, 50 unsigned long idx, int assert) 51 { 52 struct syscfg_reset_controller *rst = to_syscfg_reset_controller(rcdev); 53 const struct syscfg_reset_channel *ch; 54 u32 ctrl_val = rst->active_low ? !assert : !!assert; 55 int err; 56 57 if (idx >= rcdev->nr_resets) 58 return -EINVAL; 59 60 ch = &rst->channels[idx]; 61 62 err = regmap_field_write(ch->reset, ctrl_val); 63 if (err) 64 return err; 65 66 if (ch->ack) { 67 u32 ack_val; 68 69 err = regmap_field_read_poll_timeout(ch->ack, ack_val, (ack_val == ctrl_val), 70 100, USEC_PER_SEC); 71 if (err) 72 return err; 73 } 74 75 return 0; 76 } 77 78 static int syscfg_reset_assert(struct reset_controller_dev *rcdev, 79 unsigned long idx) 80 { 81 return syscfg_reset_program_hw(rcdev, idx, true); 82 } 83 84 static int syscfg_reset_deassert(struct reset_controller_dev *rcdev, 85 unsigned long idx) 86 { 87 return syscfg_reset_program_hw(rcdev, idx, false); 88 } 89 90 static int syscfg_reset_dev(struct reset_controller_dev *rcdev, 91 unsigned long idx) 92 { 93 int err; 94 95 err = syscfg_reset_assert(rcdev, idx); 96 if (err) 97 return err; 98 99 return syscfg_reset_deassert(rcdev, idx); 100 } 101 102 static int syscfg_reset_status(struct reset_controller_dev *rcdev, 103 unsigned long idx) 104 { 105 struct syscfg_reset_controller *rst = to_syscfg_reset_controller(rcdev); 106 const struct syscfg_reset_channel *ch; 107 u32 ret_val = 0; 108 int err; 109 110 if (idx >= rcdev->nr_resets) 111 return -EINVAL; 112 113 ch = &rst->channels[idx]; 114 if (ch->ack) 115 err = regmap_field_read(ch->ack, &ret_val); 116 else 117 err = regmap_field_read(ch->reset, &ret_val); 118 if (err) 119 return err; 120 121 return rst->active_low ? !ret_val : !!ret_val; 122 } 123 124 static const struct reset_control_ops syscfg_reset_ops = { 125 .reset = syscfg_reset_dev, 126 .assert = syscfg_reset_assert, 127 .deassert = syscfg_reset_deassert, 128 .status = syscfg_reset_status, 129 }; 130 131 static int syscfg_reset_controller_register(struct device *dev, 132 const struct syscfg_reset_controller_data *data) 133 { 134 struct syscfg_reset_controller *rc; 135 int i, err; 136 137 rc = devm_kzalloc(dev, sizeof(*rc), GFP_KERNEL); 138 if (!rc) 139 return -ENOMEM; 140 141 rc->channels = devm_kcalloc(dev, data->nr_channels, 142 sizeof(*rc->channels), GFP_KERNEL); 143 if (!rc->channels) 144 return -ENOMEM; 145 146 rc->rst.ops = &syscfg_reset_ops; 147 rc->rst.of_node = dev->of_node; 148 rc->rst.nr_resets = data->nr_channels; 149 rc->active_low = data->active_low; 150 151 for (i = 0; i < data->nr_channels; i++) { 152 struct regmap *map; 153 struct regmap_field *f; 154 const char *compatible = data->channels[i].compatible; 155 156 map = syscon_regmap_lookup_by_compatible(compatible); 157 if (IS_ERR(map)) 158 return PTR_ERR(map); 159 160 f = devm_regmap_field_alloc(dev, map, data->channels[i].reset); 161 if (IS_ERR(f)) 162 return PTR_ERR(f); 163 164 rc->channels[i].reset = f; 165 166 if (!data->wait_for_ack) 167 continue; 168 169 f = devm_regmap_field_alloc(dev, map, data->channels[i].ack); 170 if (IS_ERR(f)) 171 return PTR_ERR(f); 172 173 rc->channels[i].ack = f; 174 } 175 176 err = reset_controller_register(&rc->rst); 177 if (!err) 178 dev_info(dev, "registered\n"); 179 180 return err; 181 } 182 183 int syscfg_reset_probe(struct platform_device *pdev) 184 { 185 struct device *dev = pdev ? &pdev->dev : NULL; 186 const struct of_device_id *match; 187 188 if (!dev || !dev->driver) 189 return -ENODEV; 190 191 match = of_match_device(dev->driver->of_match_table, dev); 192 if (!match || !match->data) 193 return -EINVAL; 194 195 return syscfg_reset_controller_register(dev, match->data); 196 } 197