uboot/drivers/clk/mtmips/clk-mt7620.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
   4 *
   5 * Author: Weijie Gao <weijie.gao@mediatek.com>
   6 */
   7
   8#include <clk-uclass.h>
   9#include <dm.h>
  10#include <dm/device_compat.h>
  11#include <dt-bindings/clock/mt7620-clk.h>
  12#include <misc.h>
  13#include <mach/mt7620-sysc.h>
  14
  15/* CLKCFG1 */
  16#define CLKCFG1_REG                     0x30
  17
  18#define CLK_SRC_CPU                     -1
  19#define CLK_SRC_CPU_D2                  -2
  20#define CLK_SRC_SYS                     -3
  21#define CLK_SRC_XTAL                    -4
  22#define CLK_SRC_PERI                    -5
  23
  24struct mt7620_clk_priv {
  25        struct udevice *dev;
  26        struct udevice *sysc;
  27        struct mt7620_sysc_clks clks;
  28};
  29
  30static const int mt7620_clks[] = {
  31        [CLK_SYS] = CLK_SRC_SYS,
  32        [CLK_CPU] = CLK_SRC_CPU,
  33        [CLK_XTAL] = CLK_SRC_XTAL,
  34        [CLK_MIPS_CNT] = CLK_SRC_CPU_D2,
  35        [CLK_UARTF] = CLK_SRC_PERI,
  36        [CLK_UARTL] = CLK_SRC_PERI,
  37        [CLK_SPI] = CLK_SRC_SYS,
  38        [CLK_I2C] = CLK_SRC_PERI,
  39        [CLK_I2S] = CLK_SRC_PERI,
  40};
  41
  42static ulong mt7620_clk_get_rate(struct clk *clk)
  43{
  44        struct mt7620_clk_priv *priv = dev_get_priv(clk->dev);
  45
  46        if (clk->id >= ARRAY_SIZE(mt7620_clks))
  47                return 0;
  48
  49        switch (mt7620_clks[clk->id]) {
  50        case CLK_SRC_CPU:
  51                return priv->clks.cpu_clk;
  52        case CLK_SRC_CPU_D2:
  53                return priv->clks.cpu_clk / 2;
  54        case CLK_SRC_SYS:
  55                return priv->clks.sys_clk;
  56        case CLK_SRC_XTAL:
  57                return priv->clks.xtal_clk;
  58        case CLK_SRC_PERI:
  59                return priv->clks.peri_clk;
  60        default:
  61                return mt7620_clks[clk->id];
  62        }
  63}
  64
  65static int mt7620_clkcfg1_rmw(struct mt7620_clk_priv *priv, u32 clr, u32 set)
  66{
  67        u32 val;
  68        int ret;
  69
  70        ret = misc_read(priv->sysc, CLKCFG1_REG, &val, sizeof(val));
  71        if (ret) {
  72                dev_err(priv->dev, "mt7620_clk: failed to read CLKCFG1\n");
  73                return ret;
  74        }
  75
  76        val &= ~clr;
  77        val |= set;
  78
  79        ret = misc_write(priv->sysc, CLKCFG1_REG, &val, sizeof(val));
  80        if (ret) {
  81                dev_err(priv->dev, "mt7620_clk: failed to write CLKCFG1\n");
  82                return ret;
  83        }
  84
  85        return 0;
  86}
  87
  88static int mt7620_clk_enable(struct clk *clk)
  89{
  90        struct mt7620_clk_priv *priv = dev_get_priv(clk->dev);
  91
  92        if (clk->id > 30)
  93                return -1;
  94
  95        return mt7620_clkcfg1_rmw(priv, 0, BIT(clk->id));
  96}
  97
  98static int mt7620_clk_disable(struct clk *clk)
  99{
 100        struct mt7620_clk_priv *priv = dev_get_priv(clk->dev);
 101
 102        if (clk->id > 30)
 103                return -1;
 104
 105        return mt7620_clkcfg1_rmw(priv, BIT(clk->id), 0);
 106}
 107
 108const struct clk_ops mt7620_clk_ops = {
 109        .enable = mt7620_clk_enable,
 110        .disable = mt7620_clk_disable,
 111        .get_rate = mt7620_clk_get_rate,
 112};
 113
 114static int mt7620_clk_probe(struct udevice *dev)
 115{
 116        struct mt7620_clk_priv *priv = dev_get_priv(dev);
 117        struct ofnode_phandle_args sysc_args;
 118        int ret;
 119
 120        ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), "mediatek,sysc", NULL,
 121                                             0, 0, &sysc_args);
 122        if (ret) {
 123                dev_err(dev, "mt7620_clk: sysc property not found\n");
 124                return ret;
 125        }
 126
 127        ret = uclass_get_device_by_ofnode(UCLASS_MISC, sysc_args.node,
 128                                          &priv->sysc);
 129        if (ret) {
 130                dev_err(dev, "mt7620_clk: failed to sysc device\n");
 131                return ret;
 132        }
 133
 134        ret = misc_ioctl(priv->sysc, MT7620_SYSC_IOCTL_GET_CLK,
 135                         &priv->clks);
 136        if (ret) {
 137                dev_err(dev, "mt7620_clk: failed to get base clocks\n");
 138                return ret;
 139        }
 140
 141        priv->dev = dev;
 142
 143        return 0;
 144}
 145
 146static const struct udevice_id mt7620_clk_ids[] = {
 147        { .compatible = "mediatek,mt7620-clk" },
 148        { }
 149};
 150
 151U_BOOT_DRIVER(mt7620_clk) = {
 152        .name = "mt7620-clk",
 153        .id = UCLASS_CLK,
 154        .of_match = mt7620_clk_ids,
 155        .probe = mt7620_clk_probe,
 156        .priv_auto = sizeof(struct mt7620_clk_priv),
 157        .ops = &mt7620_clk_ops,
 158        .flags = DM_FLAG_PRE_RELOC,
 159};
 160