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