uboot/cmd/clk.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2013 Xilinx, Inc.
   4 */
   5#include <common.h>
   6#include <command.h>
   7#include <clk.h>
   8#if defined(CONFIG_DM) && defined(CONFIG_CLK)
   9#include <dm.h>
  10#include <dm/device.h>
  11#include <dm/root.h>
  12#include <dm/device-internal.h>
  13#include <linux/clk-provider.h>
  14#endif
  15
  16#if defined(CONFIG_DM) && defined(CONFIG_CLK)
  17static void show_clks(struct udevice *dev, int depth, int last_flag)
  18{
  19        int i, is_last;
  20        struct udevice *child;
  21        struct clk *clkp, *parent;
  22        u32 rate;
  23
  24        clkp = dev_get_clk_ptr(dev);
  25        if (device_get_uclass_id(dev) == UCLASS_CLK && clkp) {
  26                parent = clk_get_parent(clkp);
  27                if (!IS_ERR(parent) && depth == -1)
  28                        return;
  29                depth++;
  30                rate = clk_get_rate(clkp);
  31
  32                printf(" %-12u  %8d        ", rate, clkp->enable_count);
  33
  34                for (i = depth; i >= 0; i--) {
  35                        is_last = (last_flag >> i) & 1;
  36                        if (i) {
  37                                if (is_last)
  38                                        printf("    ");
  39                                else
  40                                        printf("|   ");
  41                        } else {
  42                                if (is_last)
  43                                        printf("`-- ");
  44                                else
  45                                        printf("|-- ");
  46                        }
  47                }
  48
  49                printf("%s\n", dev->name);
  50        }
  51
  52        list_for_each_entry(child, &dev->child_head, sibling_node) {
  53                if (child == dev)
  54                        continue;
  55
  56                is_last = list_is_last(&child->sibling_node, &dev->child_head);
  57                show_clks(child, depth, (last_flag << 1) | is_last);
  58        }
  59}
  60
  61int __weak soc_clk_dump(void)
  62{
  63        struct udevice *dev;
  64        struct uclass *uc;
  65        int ret;
  66
  67        ret = uclass_get(UCLASS_CLK, &uc);
  68        if (ret)
  69                return ret;
  70
  71        printf(" Rate               Usecnt      Name\n");
  72        printf("------------------------------------------\n");
  73
  74        uclass_foreach_dev(dev, uc)
  75                show_clks(dev, -1, 0);
  76
  77        return 0;
  78}
  79#else
  80int __weak soc_clk_dump(void)
  81{
  82        puts("Not implemented\n");
  83        return 1;
  84}
  85#endif
  86
  87static int do_clk_dump(struct cmd_tbl *cmdtp, int flag, int argc,
  88                       char *const argv[])
  89{
  90        int ret;
  91
  92        ret = soc_clk_dump();
  93        if (ret < 0) {
  94                printf("Clock dump error %d\n", ret);
  95                ret = CMD_RET_FAILURE;
  96        }
  97
  98        return ret;
  99}
 100
 101#if CONFIG_IS_ENABLED(DM) && CONFIG_IS_ENABLED(CLK)
 102struct udevice *clk_lookup(const char *name)
 103{
 104        int i = 0;
 105        struct udevice *dev;
 106
 107        do {
 108                uclass_get_device(UCLASS_CLK, i++, &dev);
 109                if (!strcmp(name, dev->name))
 110                        return dev;
 111        } while (dev);
 112
 113        return NULL;
 114}
 115
 116static int do_clk_setfreq(struct cmd_tbl *cmdtp, int flag, int argc,
 117                          char *const argv[])
 118{
 119        struct clk *clk = NULL;
 120        s32 freq;
 121        struct udevice *dev;
 122
 123        freq = dectoul(argv[2], NULL);
 124
 125        dev = clk_lookup(argv[1]);
 126
 127        if (dev)
 128                clk = dev_get_clk_ptr(dev);
 129
 130        if (!clk) {
 131                printf("clock '%s' not found.\n", argv[1]);
 132                return -EINVAL;
 133        }
 134
 135        freq = clk_set_rate(clk, freq);
 136        if (freq < 0) {
 137                printf("set_rate failed: %d\n", freq);
 138                return CMD_RET_FAILURE;
 139        }
 140
 141        printf("set_rate returns %u\n", freq);
 142        return 0;
 143}
 144#endif
 145
 146static struct cmd_tbl cmd_clk_sub[] = {
 147        U_BOOT_CMD_MKENT(dump, 1, 1, do_clk_dump, "", ""),
 148#if CONFIG_IS_ENABLED(DM) && CONFIG_IS_ENABLED(CLK)
 149        U_BOOT_CMD_MKENT(setfreq, 3, 1, do_clk_setfreq, "", ""),
 150#endif
 151};
 152
 153static int do_clk(struct cmd_tbl *cmdtp, int flag, int argc,
 154                  char *const argv[])
 155{
 156        struct cmd_tbl *c;
 157
 158        if (argc < 2)
 159                return CMD_RET_USAGE;
 160
 161        /* Strip off leading 'clk' command argument */
 162        argc--;
 163        argv++;
 164
 165        c = find_cmd_tbl(argv[0], &cmd_clk_sub[0], ARRAY_SIZE(cmd_clk_sub));
 166
 167        if (c)
 168                return c->cmd(cmdtp, flag, argc, argv);
 169        else
 170                return CMD_RET_USAGE;
 171}
 172
 173#ifdef CONFIG_SYS_LONGHELP
 174static char clk_help_text[] =
 175        "dump - Print clock frequencies\n"
 176        "setfreq [clk] [freq] - Set clock frequency";
 177#endif
 178
 179U_BOOT_CMD(clk, 4, 1, do_clk, "CLK sub-system", clk_help_text);
 180