1f26c8a8eSSimon Glass /* 2f26c8a8eSSimon Glass * Copyright (C) 2015 Google, Inc 3f26c8a8eSSimon Glass * Written by Simon Glass <sjg@chromium.org> 4f26c8a8eSSimon Glass * 5f26c8a8eSSimon Glass * SPDX-License-Identifier: GPL-2.0+ 6f26c8a8eSSimon Glass */ 7f26c8a8eSSimon Glass 8f26c8a8eSSimon Glass #include <common.h> 9f26c8a8eSSimon Glass #include <clk.h> 10f26c8a8eSSimon Glass #include <dm.h> 11f26c8a8eSSimon Glass #include <errno.h> 12f26c8a8eSSimon Glass #include <dm/lists.h> 13f26c8a8eSSimon Glass #include <dm/root.h> 14f26c8a8eSSimon Glass 15e70cc438SSimon Glass DECLARE_GLOBAL_DATA_PTR; 16e70cc438SSimon Glass 17f26c8a8eSSimon Glass ulong clk_get_rate(struct udevice *dev) 18f26c8a8eSSimon Glass { 19f26c8a8eSSimon Glass struct clk_ops *ops = clk_get_ops(dev); 20f26c8a8eSSimon Glass 21f26c8a8eSSimon Glass if (!ops->get_rate) 22f26c8a8eSSimon Glass return -ENOSYS; 23f26c8a8eSSimon Glass 24f26c8a8eSSimon Glass return ops->get_rate(dev); 25f26c8a8eSSimon Glass } 26f26c8a8eSSimon Glass 27f26c8a8eSSimon Glass ulong clk_set_rate(struct udevice *dev, ulong rate) 28f26c8a8eSSimon Glass { 29f26c8a8eSSimon Glass struct clk_ops *ops = clk_get_ops(dev); 30f26c8a8eSSimon Glass 31f26c8a8eSSimon Glass if (!ops->set_rate) 32f26c8a8eSSimon Glass return -ENOSYS; 33f26c8a8eSSimon Glass 34f26c8a8eSSimon Glass return ops->set_rate(dev, rate); 35f26c8a8eSSimon Glass } 36f26c8a8eSSimon Glass 37f0e07516SMasahiro Yamada int clk_enable(struct udevice *dev, int periph) 38f0e07516SMasahiro Yamada { 39f0e07516SMasahiro Yamada struct clk_ops *ops = clk_get_ops(dev); 40f0e07516SMasahiro Yamada 41f0e07516SMasahiro Yamada if (!ops->enable) 42f0e07516SMasahiro Yamada return -ENOSYS; 43f0e07516SMasahiro Yamada 44f0e07516SMasahiro Yamada return ops->enable(dev, periph); 45f0e07516SMasahiro Yamada } 46f0e07516SMasahiro Yamada 47f26c8a8eSSimon Glass ulong clk_get_periph_rate(struct udevice *dev, int periph) 48f26c8a8eSSimon Glass { 49f26c8a8eSSimon Glass struct clk_ops *ops = clk_get_ops(dev); 50f26c8a8eSSimon Glass 51f26c8a8eSSimon Glass if (!ops->get_periph_rate) 52f26c8a8eSSimon Glass return -ENOSYS; 53f26c8a8eSSimon Glass 54f26c8a8eSSimon Glass return ops->get_periph_rate(dev, periph); 55f26c8a8eSSimon Glass } 56f26c8a8eSSimon Glass 57f26c8a8eSSimon Glass ulong clk_set_periph_rate(struct udevice *dev, int periph, ulong rate) 58f26c8a8eSSimon Glass { 59f26c8a8eSSimon Glass struct clk_ops *ops = clk_get_ops(dev); 60f26c8a8eSSimon Glass 61f26c8a8eSSimon Glass if (!ops->set_periph_rate) 62f26c8a8eSSimon Glass return -ENOSYS; 63f26c8a8eSSimon Glass 64f26c8a8eSSimon Glass return ops->set_periph_rate(dev, periph, rate); 65f26c8a8eSSimon Glass } 66f26c8a8eSSimon Glass 67e70cc438SSimon Glass #if CONFIG_IS_ENABLED(OF_CONTROL) 68e70cc438SSimon Glass int clk_get_by_index(struct udevice *dev, int index, struct udevice **clk_devp) 69e70cc438SSimon Glass { 70e70cc438SSimon Glass int ret; 71*a4b10c08SSimon Glass #ifdef CONFIG_SPL_BUILD 72*a4b10c08SSimon Glass u32 cell[2]; 73*a4b10c08SSimon Glass 74*a4b10c08SSimon Glass if (index != 0) 75*a4b10c08SSimon Glass return -ENOSYS; 76*a4b10c08SSimon Glass assert(*clk_devp); 77*a4b10c08SSimon Glass ret = uclass_get_device(UCLASS_CLK, 0, clk_devp); 78*a4b10c08SSimon Glass if (ret) 79*a4b10c08SSimon Glass return ret; 80*a4b10c08SSimon Glass ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "clocks", 81*a4b10c08SSimon Glass cell, 2); 82*a4b10c08SSimon Glass if (ret) 83*a4b10c08SSimon Glass return ret; 84*a4b10c08SSimon Glass return cell[1]; 85*a4b10c08SSimon Glass #else 86*a4b10c08SSimon Glass struct fdtdec_phandle_args args; 87e70cc438SSimon Glass 88e70cc438SSimon Glass assert(*clk_devp); 89e70cc438SSimon Glass ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset, 90e70cc438SSimon Glass "clocks", "#clock-cells", 0, index, 91e70cc438SSimon Glass &args); 92e70cc438SSimon Glass if (ret) { 93e70cc438SSimon Glass debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n", 94e70cc438SSimon Glass __func__, ret); 95e70cc438SSimon Glass return ret; 96e70cc438SSimon Glass } 97e70cc438SSimon Glass 98e70cc438SSimon Glass ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, clk_devp); 99e70cc438SSimon Glass if (ret) { 100e70cc438SSimon Glass debug("%s: uclass_get_device_by_of_offset failed: err=%d\n", 101e70cc438SSimon Glass __func__, ret); 102e70cc438SSimon Glass return ret; 103e70cc438SSimon Glass } 104e70cc438SSimon Glass return args.args_count > 0 ? args.args[0] : 0; 105*a4b10c08SSimon Glass #endif 106e70cc438SSimon Glass } 107e70cc438SSimon Glass #endif 108e70cc438SSimon Glass 109f26c8a8eSSimon Glass UCLASS_DRIVER(clk) = { 110f26c8a8eSSimon Glass .id = UCLASS_CLK, 111f26c8a8eSSimon Glass .name = "clk", 112f26c8a8eSSimon Glass }; 113