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, 2189c1e2daSStephen Warren struct fdtdec_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 { 3889c1e2daSStephen Warren struct fdtdec_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 4689c1e2daSStephen Warren ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset, 4789c1e2daSStephen Warren "resets", "#reset-cells", 0, 4889c1e2daSStephen Warren index, &args); 4989c1e2daSStephen Warren if (ret) { 5089c1e2daSStephen Warren debug("%s: fdtdec_parse_phandle_with_args failed: %d\n", 5189c1e2daSStephen Warren __func__, ret); 5289c1e2daSStephen Warren return ret; 5389c1e2daSStephen Warren } 5489c1e2daSStephen Warren 5589c1e2daSStephen Warren ret = uclass_get_device_by_of_offset(UCLASS_RESET, args.node, 5689c1e2daSStephen Warren &dev_reset); 5789c1e2daSStephen Warren if (ret) { 5889c1e2daSStephen Warren debug("%s: uclass_get_device_by_of_offset failed: %d\n", 5989c1e2daSStephen Warren __func__, ret); 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 91*b02e4044SSimon Glass index = fdt_stringlist_search(gd->fdt_blob, dev->of_offset, 92*b02e4044SSimon Glass "reset-names", name); 9389c1e2daSStephen Warren if (index < 0) { 94*b02e4044SSimon Glass debug("fdt_stringlist_search() failed: %d\n", index); 9589c1e2daSStephen Warren return index; 9689c1e2daSStephen Warren } 9789c1e2daSStephen Warren 9889c1e2daSStephen Warren return reset_get_by_index(dev, index, reset_ctl); 9989c1e2daSStephen Warren } 10089c1e2daSStephen Warren 10189c1e2daSStephen Warren int reset_free(struct reset_ctl *reset_ctl) 10289c1e2daSStephen Warren { 10389c1e2daSStephen Warren struct reset_ops *ops = reset_dev_ops(reset_ctl->dev); 10489c1e2daSStephen Warren 10589c1e2daSStephen Warren debug("%s(reset_ctl=%p)\n", __func__, reset_ctl); 10689c1e2daSStephen Warren 10789c1e2daSStephen Warren return ops->free(reset_ctl); 10889c1e2daSStephen Warren } 10989c1e2daSStephen Warren 11089c1e2daSStephen Warren int reset_assert(struct reset_ctl *reset_ctl) 11189c1e2daSStephen Warren { 11289c1e2daSStephen Warren struct reset_ops *ops = reset_dev_ops(reset_ctl->dev); 11389c1e2daSStephen Warren 11489c1e2daSStephen Warren debug("%s(reset_ctl=%p)\n", __func__, reset_ctl); 11589c1e2daSStephen Warren 11689c1e2daSStephen Warren return ops->rst_assert(reset_ctl); 11789c1e2daSStephen Warren } 11889c1e2daSStephen Warren 11989c1e2daSStephen Warren int reset_deassert(struct reset_ctl *reset_ctl) 12089c1e2daSStephen Warren { 12189c1e2daSStephen Warren struct reset_ops *ops = reset_dev_ops(reset_ctl->dev); 12289c1e2daSStephen Warren 12389c1e2daSStephen Warren debug("%s(reset_ctl=%p)\n", __func__, reset_ctl); 12489c1e2daSStephen Warren 12589c1e2daSStephen Warren return ops->rst_deassert(reset_ctl); 12689c1e2daSStephen Warren } 12789c1e2daSStephen Warren 12889c1e2daSStephen Warren UCLASS_DRIVER(reset) = { 12989c1e2daSStephen Warren .id = UCLASS_RESET, 13089c1e2daSStephen Warren .name = "reset", 13189c1e2daSStephen Warren }; 132