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); 4589c1e2daSStephen Warren 4640a475e8SSimon Glass ret = dev_read_phandle_with_args(dev, "resets", "#reset-cells", 0, 4789c1e2daSStephen Warren index, &args); 4889c1e2daSStephen Warren if (ret) { 4940a475e8SSimon Glass debug("%s: fdtdec_parse_phandle_with_args() failed: %d\n", 5089c1e2daSStephen Warren __func__, ret); 5189c1e2daSStephen Warren return ret; 5289c1e2daSStephen Warren } 5389c1e2daSStephen Warren 5440a475e8SSimon Glass ret = uclass_get_device_by_ofnode(UCLASS_RESET, args.node, 5589c1e2daSStephen Warren &dev_reset); 5689c1e2daSStephen Warren if (ret) { 5740a475e8SSimon Glass debug("%s: uclass_get_device_by_ofnode() failed: %d\n", 5889c1e2daSStephen Warren __func__, ret); 5940a475e8SSimon Glass debug("%s %d\n", ofnode_get_name(args.node), args.args[0]); 6089c1e2daSStephen Warren return ret; 6189c1e2daSStephen Warren } 6289c1e2daSStephen Warren ops = reset_dev_ops(dev_reset); 6389c1e2daSStephen Warren 6489c1e2daSStephen Warren reset_ctl->dev = dev_reset; 6589c1e2daSStephen Warren if (ops->of_xlate) 6689c1e2daSStephen Warren ret = ops->of_xlate(reset_ctl, &args); 6789c1e2daSStephen Warren else 6889c1e2daSStephen Warren ret = reset_of_xlate_default(reset_ctl, &args); 6989c1e2daSStephen Warren if (ret) { 7089c1e2daSStephen Warren debug("of_xlate() failed: %d\n", ret); 7189c1e2daSStephen Warren return ret; 7289c1e2daSStephen Warren } 7389c1e2daSStephen Warren 7489c1e2daSStephen Warren ret = ops->request(reset_ctl); 7589c1e2daSStephen Warren if (ret) { 7689c1e2daSStephen Warren debug("ops->request() failed: %d\n", ret); 7789c1e2daSStephen Warren return ret; 7889c1e2daSStephen Warren } 7989c1e2daSStephen Warren 8089c1e2daSStephen Warren return 0; 8189c1e2daSStephen Warren } 8289c1e2daSStephen Warren 8389c1e2daSStephen Warren int reset_get_by_name(struct udevice *dev, const char *name, 8489c1e2daSStephen Warren struct reset_ctl *reset_ctl) 8589c1e2daSStephen Warren { 8689c1e2daSStephen Warren int index; 8789c1e2daSStephen Warren 8889c1e2daSStephen Warren debug("%s(dev=%p, name=%s, reset_ctl=%p)\n", __func__, dev, name, 8989c1e2daSStephen Warren reset_ctl); 9089c1e2daSStephen Warren 9140a475e8SSimon Glass index = dev_read_stringlist_search(dev, "reset-names", name); 9289c1e2daSStephen Warren if (index < 0) { 93b02e4044SSimon Glass debug("fdt_stringlist_search() failed: %d\n", index); 9489c1e2daSStephen Warren return index; 9589c1e2daSStephen Warren } 9689c1e2daSStephen Warren 9789c1e2daSStephen Warren return reset_get_by_index(dev, index, reset_ctl); 9889c1e2daSStephen Warren } 9989c1e2daSStephen Warren 100*9bd5cdf6SPatrice Chotard int reset_request(struct reset_ctl *reset_ctl) 101*9bd5cdf6SPatrice Chotard { 102*9bd5cdf6SPatrice Chotard struct reset_ops *ops = reset_dev_ops(reset_ctl->dev); 103*9bd5cdf6SPatrice Chotard 104*9bd5cdf6SPatrice Chotard debug("%s(reset_ctl=%p)\n", __func__, reset_ctl); 105*9bd5cdf6SPatrice Chotard 106*9bd5cdf6SPatrice Chotard return ops->request(reset_ctl); 107*9bd5cdf6SPatrice Chotard } 108*9bd5cdf6SPatrice Chotard 10989c1e2daSStephen Warren int reset_free(struct reset_ctl *reset_ctl) 11089c1e2daSStephen Warren { 11189c1e2daSStephen Warren struct reset_ops *ops = reset_dev_ops(reset_ctl->dev); 11289c1e2daSStephen Warren 11389c1e2daSStephen Warren debug("%s(reset_ctl=%p)\n", __func__, reset_ctl); 11489c1e2daSStephen Warren 11589c1e2daSStephen Warren return ops->free(reset_ctl); 11689c1e2daSStephen Warren } 11789c1e2daSStephen Warren 11889c1e2daSStephen Warren int reset_assert(struct reset_ctl *reset_ctl) 11989c1e2daSStephen Warren { 12089c1e2daSStephen Warren struct reset_ops *ops = reset_dev_ops(reset_ctl->dev); 12189c1e2daSStephen Warren 12289c1e2daSStephen Warren debug("%s(reset_ctl=%p)\n", __func__, reset_ctl); 12389c1e2daSStephen Warren 12489c1e2daSStephen Warren return ops->rst_assert(reset_ctl); 12589c1e2daSStephen Warren } 12689c1e2daSStephen Warren 12789c1e2daSStephen Warren int reset_deassert(struct reset_ctl *reset_ctl) 12889c1e2daSStephen Warren { 12989c1e2daSStephen Warren struct reset_ops *ops = reset_dev_ops(reset_ctl->dev); 13089c1e2daSStephen Warren 13189c1e2daSStephen Warren debug("%s(reset_ctl=%p)\n", __func__, reset_ctl); 13289c1e2daSStephen Warren 13389c1e2daSStephen Warren return ops->rst_deassert(reset_ctl); 13489c1e2daSStephen Warren } 13589c1e2daSStephen Warren 13689c1e2daSStephen Warren UCLASS_DRIVER(reset) = { 13789c1e2daSStephen Warren .id = UCLASS_RESET, 13889c1e2daSStephen Warren .name = "reset", 13989c1e2daSStephen Warren }; 140