Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

reset: make shared pulsed reset controls re-triggerable

The current reset framework API does not allow to release what is done by
reset_control_reset(), IOW decrement triggered_count. Add the new
reset_control_rearm() call to do so.

When reset_control_reset() has been called once, the counter
triggered_count, in the reset framework, is incremented i.e the resource
under the reset is in-use and the reset should not be done again.
reset_control_rearm() would be the way to state that the resource is
no longer used and, that from the caller's perspective, the reset can be
fired again if necessary.

Signed-off-by: Amjad Ouled-Ameur <aouledameur@baylibre.com>
Reported-by: Jerome Brunet <jbrunet@baylibre.com>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>

authored by

Amjad Ouled-Ameur and committed by
Philipp Zabel
557acb3d 3650b228

+74
+73
drivers/reset/core.c
··· 208 208 return 0; 209 209 } 210 210 211 + static int reset_control_array_rearm(struct reset_control_array *resets) 212 + { 213 + struct reset_control *rstc; 214 + int i; 215 + 216 + for (i = 0; i < resets->num_rstcs; i++) { 217 + rstc = resets->rstc[i]; 218 + 219 + if (!rstc) 220 + continue; 221 + 222 + if (WARN_ON(IS_ERR(rstc))) 223 + return -EINVAL; 224 + 225 + if (rstc->shared) { 226 + if (WARN_ON(atomic_read(&rstc->deassert_count) != 0)) 227 + return -EINVAL; 228 + } else { 229 + if (!rstc->acquired) 230 + return -EPERM; 231 + } 232 + } 233 + 234 + for (i = 0; i < resets->num_rstcs; i++) { 235 + rstc = resets->rstc[i]; 236 + 237 + if (rstc && rstc->shared) 238 + WARN_ON(atomic_dec_return(&rstc->triggered_count) < 0); 239 + } 240 + 241 + return 0; 242 + } 243 + 211 244 static int reset_control_array_assert(struct reset_control_array *resets) 212 245 { 213 246 int ret, i; ··· 357 324 return ret; 358 325 } 359 326 EXPORT_SYMBOL_GPL(reset_control_reset); 327 + 328 + /** 329 + * reset_control_rearm - allow shared reset line to be re-triggered" 330 + * @rstc: reset controller 331 + * 332 + * On a shared reset line the actual reset pulse is only triggered once for the 333 + * lifetime of the reset_control instance, except if this call is used. 334 + * 335 + * Calls to this function must be balanced with calls to reset_control_reset, 336 + * a warning is thrown in case triggered_count ever dips below 0. 337 + * 338 + * Consumers must not use reset_control_(de)assert on shared reset lines when 339 + * reset_control_reset or reset_control_rearm have been used. 340 + * 341 + * If rstc is NULL the function will just return 0. 342 + */ 343 + int reset_control_rearm(struct reset_control *rstc) 344 + { 345 + if (!rstc) 346 + return 0; 347 + 348 + if (WARN_ON(IS_ERR(rstc))) 349 + return -EINVAL; 350 + 351 + if (reset_control_is_array(rstc)) 352 + return reset_control_array_rearm(rstc_to_array(rstc)); 353 + 354 + if (rstc->shared) { 355 + if (WARN_ON(atomic_read(&rstc->deassert_count) != 0)) 356 + return -EINVAL; 357 + 358 + WARN_ON(atomic_dec_return(&rstc->triggered_count) < 0); 359 + } else { 360 + if (!rstc->acquired) 361 + return -EPERM; 362 + } 363 + 364 + return 0; 365 + } 366 + EXPORT_SYMBOL_GPL(reset_control_rearm); 360 367 361 368 /** 362 369 * reset_control_assert - asserts the reset line
+1
include/linux/reset.h
··· 13 13 #ifdef CONFIG_RESET_CONTROLLER 14 14 15 15 int reset_control_reset(struct reset_control *rstc); 16 + int reset_control_rearm(struct reset_control *rstc); 16 17 int reset_control_assert(struct reset_control *rstc); 17 18 int reset_control_deassert(struct reset_control *rstc); 18 19 int reset_control_status(struct reset_control *rstc);