xref: /rk3399_rockchip-uboot/drivers/reset/reset-uclass.c (revision 3b9d1bdd4e5fe0c44e5d4d0a0916dbccc558749d)
189c1e2daSStephen Warren /*
289c1e2daSStephen Warren  * Copyright (c) 2016, NVIDIA CORPORATION.
389c1e2daSStephen Warren  *
489c1e2daSStephen Warren  * SPDX-License-Identifier: GPL-2.0
589c1e2daSStephen Warren  */
689c1e2daSStephen Warren 
789c1e2daSStephen Warren #include <common.h>
889c1e2daSStephen Warren #include <dm.h>
989c1e2daSStephen Warren #include <fdtdec.h>
1089c1e2daSStephen Warren #include <reset.h>
1189c1e2daSStephen Warren #include <reset-uclass.h>
1289c1e2daSStephen Warren 
1389c1e2daSStephen Warren DECLARE_GLOBAL_DATA_PTR;
1489c1e2daSStephen Warren 
1589c1e2daSStephen Warren static inline struct reset_ops *reset_dev_ops(struct udevice *dev)
1689c1e2daSStephen Warren {
1789c1e2daSStephen Warren 	return (struct reset_ops *)dev->driver->ops;
1889c1e2daSStephen Warren }
1989c1e2daSStephen Warren 
2089c1e2daSStephen Warren static int reset_of_xlate_default(struct reset_ctl *reset_ctl,
2140a475e8SSimon Glass 				  struct ofnode_phandle_args *args)
2289c1e2daSStephen Warren {
2389c1e2daSStephen Warren 	debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
2489c1e2daSStephen Warren 
2589c1e2daSStephen Warren 	if (args->args_count != 1) {
2689c1e2daSStephen Warren 		debug("Invaild args_count: %d\n", args->args_count);
2789c1e2daSStephen Warren 		return -EINVAL;
2889c1e2daSStephen Warren 	}
2989c1e2daSStephen Warren 
3089c1e2daSStephen Warren 	reset_ctl->id = args->args[0];
3189c1e2daSStephen Warren 
3289c1e2daSStephen Warren 	return 0;
3389c1e2daSStephen Warren }
3489c1e2daSStephen Warren 
3589c1e2daSStephen Warren int reset_get_by_index(struct udevice *dev, int index,
3689c1e2daSStephen Warren 		       struct reset_ctl *reset_ctl)
3789c1e2daSStephen Warren {
3840a475e8SSimon Glass 	struct ofnode_phandle_args args;
3989c1e2daSStephen Warren 	int ret;
4089c1e2daSStephen Warren 	struct udevice *dev_reset;
4189c1e2daSStephen Warren 	struct reset_ops *ops;
4289c1e2daSStephen Warren 
4389c1e2daSStephen Warren 	debug("%s(dev=%p, index=%d, reset_ctl=%p)\n", __func__, dev, index,
4489c1e2daSStephen Warren 	      reset_ctl);
45*3b9d1bddSPatrice Chotard 	reset_ctl->dev = NULL;
4689c1e2daSStephen Warren 
4740a475e8SSimon Glass 	ret = dev_read_phandle_with_args(dev, "resets", "#reset-cells", 0,
4889c1e2daSStephen Warren 					  index, &args);
4989c1e2daSStephen Warren 	if (ret) {
5040a475e8SSimon Glass 		debug("%s: fdtdec_parse_phandle_with_args() failed: %d\n",
5189c1e2daSStephen Warren 		      __func__, ret);
5289c1e2daSStephen Warren 		return ret;
5389c1e2daSStephen Warren 	}
5489c1e2daSStephen Warren 
5540a475e8SSimon Glass 	ret = uclass_get_device_by_ofnode(UCLASS_RESET, args.node,
5689c1e2daSStephen Warren 					  &dev_reset);
5789c1e2daSStephen Warren 	if (ret) {
5840a475e8SSimon Glass 		debug("%s: uclass_get_device_by_ofnode() failed: %d\n",
5989c1e2daSStephen Warren 		      __func__, ret);
6040a475e8SSimon Glass 		debug("%s %d\n", ofnode_get_name(args.node), args.args[0]);
6189c1e2daSStephen Warren 		return ret;
6289c1e2daSStephen Warren 	}
6389c1e2daSStephen Warren 	ops = reset_dev_ops(dev_reset);
6489c1e2daSStephen Warren 
6589c1e2daSStephen Warren 	reset_ctl->dev = dev_reset;
6689c1e2daSStephen Warren 	if (ops->of_xlate)
6789c1e2daSStephen Warren 		ret = ops->of_xlate(reset_ctl, &args);
6889c1e2daSStephen Warren 	else
6989c1e2daSStephen Warren 		ret = reset_of_xlate_default(reset_ctl, &args);
7089c1e2daSStephen Warren 	if (ret) {
7189c1e2daSStephen Warren 		debug("of_xlate() failed: %d\n", ret);
7289c1e2daSStephen Warren 		return ret;
7389c1e2daSStephen Warren 	}
7489c1e2daSStephen Warren 
7589c1e2daSStephen Warren 	ret = ops->request(reset_ctl);
7689c1e2daSStephen Warren 	if (ret) {
7789c1e2daSStephen Warren 		debug("ops->request() failed: %d\n", ret);
7889c1e2daSStephen Warren 		return ret;
7989c1e2daSStephen Warren 	}
8089c1e2daSStephen Warren 
8189c1e2daSStephen Warren 	return 0;
8289c1e2daSStephen Warren }
8389c1e2daSStephen Warren 
8489c1e2daSStephen Warren int reset_get_by_name(struct udevice *dev, const char *name,
8589c1e2daSStephen Warren 		     struct reset_ctl *reset_ctl)
8689c1e2daSStephen Warren {
8789c1e2daSStephen Warren 	int index;
8889c1e2daSStephen Warren 
8989c1e2daSStephen Warren 	debug("%s(dev=%p, name=%s, reset_ctl=%p)\n", __func__, dev, name,
9089c1e2daSStephen Warren 	      reset_ctl);
91*3b9d1bddSPatrice Chotard 	reset_ctl->dev = NULL;
9289c1e2daSStephen Warren 
9340a475e8SSimon Glass 	index = dev_read_stringlist_search(dev, "reset-names", name);
9489c1e2daSStephen Warren 	if (index < 0) {
95b02e4044SSimon Glass 		debug("fdt_stringlist_search() failed: %d\n", index);
9689c1e2daSStephen Warren 		return index;
9789c1e2daSStephen Warren 	}
9889c1e2daSStephen Warren 
9989c1e2daSStephen Warren 	return reset_get_by_index(dev, index, reset_ctl);
10089c1e2daSStephen Warren }
10189c1e2daSStephen Warren 
1029bd5cdf6SPatrice Chotard int reset_request(struct reset_ctl *reset_ctl)
1039bd5cdf6SPatrice Chotard {
1049bd5cdf6SPatrice Chotard 	struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
1059bd5cdf6SPatrice Chotard 
1069bd5cdf6SPatrice Chotard 	debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
1079bd5cdf6SPatrice Chotard 
1089bd5cdf6SPatrice Chotard 	return ops->request(reset_ctl);
1099bd5cdf6SPatrice Chotard }
1109bd5cdf6SPatrice Chotard 
11189c1e2daSStephen Warren int reset_free(struct reset_ctl *reset_ctl)
11289c1e2daSStephen Warren {
11389c1e2daSStephen Warren 	struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
11489c1e2daSStephen Warren 
11589c1e2daSStephen Warren 	debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
11689c1e2daSStephen Warren 
11789c1e2daSStephen Warren 	return ops->free(reset_ctl);
11889c1e2daSStephen Warren }
11989c1e2daSStephen Warren 
12089c1e2daSStephen Warren int reset_assert(struct reset_ctl *reset_ctl)
12189c1e2daSStephen Warren {
12289c1e2daSStephen Warren 	struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
12389c1e2daSStephen Warren 
12489c1e2daSStephen Warren 	debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
12589c1e2daSStephen Warren 
12689c1e2daSStephen Warren 	return ops->rst_assert(reset_ctl);
12789c1e2daSStephen Warren }
12889c1e2daSStephen Warren 
12989c1e2daSStephen Warren int reset_deassert(struct reset_ctl *reset_ctl)
13089c1e2daSStephen Warren {
13189c1e2daSStephen Warren 	struct reset_ops *ops = reset_dev_ops(reset_ctl->dev);
13289c1e2daSStephen Warren 
13389c1e2daSStephen Warren 	debug("%s(reset_ctl=%p)\n", __func__, reset_ctl);
13489c1e2daSStephen Warren 
13589c1e2daSStephen Warren 	return ops->rst_deassert(reset_ctl);
13689c1e2daSStephen Warren }
13789c1e2daSStephen Warren 
138*3b9d1bddSPatrice Chotard int reset_release_all(struct reset_ctl *reset_ctl, int count)
139*3b9d1bddSPatrice Chotard {
140*3b9d1bddSPatrice Chotard 	int i, ret;
141*3b9d1bddSPatrice Chotard 
142*3b9d1bddSPatrice Chotard 	for (i = 0; i < count; i++) {
143*3b9d1bddSPatrice Chotard 		debug("%s(reset_ctl[%d]=%p)\n", __func__, i, &reset_ctl[i]);
144*3b9d1bddSPatrice Chotard 
145*3b9d1bddSPatrice Chotard 		/* check if reset has been previously requested */
146*3b9d1bddSPatrice Chotard 		if (!reset_ctl[i].dev)
147*3b9d1bddSPatrice Chotard 			continue;
148*3b9d1bddSPatrice Chotard 
149*3b9d1bddSPatrice Chotard 		ret = reset_assert(&reset_ctl[i]);
150*3b9d1bddSPatrice Chotard 		if (ret)
151*3b9d1bddSPatrice Chotard 			return ret;
152*3b9d1bddSPatrice Chotard 
153*3b9d1bddSPatrice Chotard 		ret = reset_free(&reset_ctl[i]);
154*3b9d1bddSPatrice Chotard 		if (ret)
155*3b9d1bddSPatrice Chotard 			return ret;
156*3b9d1bddSPatrice Chotard 	}
157*3b9d1bddSPatrice Chotard 
158*3b9d1bddSPatrice Chotard 	return 0;
159*3b9d1bddSPatrice Chotard }
160*3b9d1bddSPatrice Chotard 
16189c1e2daSStephen Warren UCLASS_DRIVER(reset) = {
16289c1e2daSStephen Warren 	.id		= UCLASS_RESET,
16389c1e2daSStephen Warren 	.name		= "reset",
16489c1e2daSStephen Warren };
165