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