uboot/arch/mips/mach-mtmips/mt7620/sysc.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 * Misc driver for manipulating System control registers
   8 */
   9
  10#include <dm.h>
  11#include <misc.h>
  12#include <asm/io.h>
  13#include <asm/addrspace.h>
  14#include <dm/device_compat.h>
  15#include <mach/mt7620-sysc.h>
  16#include "mt7620.h"
  17
  18struct mt7620_sysc_priv {
  19        void __iomem *base;
  20};
  21
  22static int mt7620_sysc_read(struct udevice *dev, int offset, void *buf,
  23                            int size)
  24{
  25        struct mt7620_sysc_priv *priv = dev_get_priv(dev);
  26        u32 val;
  27
  28        if (offset % sizeof(u32) || size != sizeof(u32) ||
  29            offset >= SYSCTL_SIZE)
  30                return -EINVAL;
  31
  32        val = readl(priv->base + offset);
  33
  34        if (buf)
  35                *(u32 *)buf = val;
  36
  37        return 0;
  38}
  39
  40static int mt7620_sysc_write(struct udevice *dev, int offset, const void *buf,
  41                             int size)
  42{
  43        struct mt7620_sysc_priv *priv = dev_get_priv(dev);
  44        u32 val;
  45
  46        if (offset % sizeof(u32) || size != sizeof(u32) ||
  47            offset >= SYSCTL_SIZE || !buf)
  48                return -EINVAL;
  49
  50        val = *(u32 *)buf;
  51        writel(val, priv->base + offset);
  52
  53        return 0;
  54}
  55
  56static int mt7620_sysc_ioctl(struct udevice *dev, unsigned long request,
  57                             void *buf)
  58{
  59        struct mt7620_sysc_priv *priv = dev_get_priv(dev);
  60        struct mt7620_sysc_chip_rev *chip_rev;
  61        struct mt7620_sysc_clks *clks;
  62        u32 val, shift;
  63
  64        if (!buf)
  65                return -EINVAL;
  66
  67        switch (request) {
  68        case MT7620_SYSC_IOCTL_GET_CLK:
  69                clks = buf;
  70                mt7620_get_clks(&clks->cpu_clk, &clks->sys_clk,
  71                                &clks->xtal_clk);
  72
  73                val = readl(priv->base + SYSCTL_CLKCFG0_REG);
  74                if (val & PERI_CLK_SEL)
  75                        clks->peri_clk = clks->xtal_clk;
  76                else
  77                        clks->peri_clk = 40000000;
  78
  79                return 0;
  80
  81        case MT7620_SYSC_IOCTL_GET_CHIP_REV:
  82                chip_rev = buf;
  83
  84                val = readl(priv->base + SYSCTL_CHIP_REV_ID_REG);
  85
  86                chip_rev->bga = !!(val & PKG_ID);
  87                chip_rev->ver = (val & VER_M) >> VER_S;
  88                chip_rev->eco = (val & ECO_M) >> ECO_S;
  89
  90                return 0;
  91
  92        case MT7620_SYSC_IOCTL_SET_GE1_MODE:
  93        case MT7620_SYSC_IOCTL_SET_GE2_MODE:
  94                val = *(u32 *)buf;
  95
  96                if (val > MT7620_SYSC_GE_ESW_PHY)
  97                        return -EINVAL;
  98
  99                if (request == MT7620_SYSC_IOCTL_SET_GE1_MODE)
 100                        shift = GE1_MODE_S;
 101                else
 102                        shift = GE2_MODE_S;
 103
 104                clrsetbits_32(priv->base + SYSCTL_SYSCFG1_REG,
 105                              GE_MODE_M << shift, val << shift);
 106
 107                return 0;
 108
 109        case MT7620_SYSC_IOCTL_SET_USB_MODE:
 110                val = *(u32 *)buf;
 111
 112                if (val == MT7620_SYSC_USB_DEVICE_MODE)
 113                        val = 0;
 114                else if (val == MT7620_SYSC_USB_HOST_MODE)
 115                        val = USB0_HOST_MODE;
 116
 117                clrsetbits_32(priv->base + SYSCTL_SYSCFG1_REG,
 118                              USB0_HOST_MODE, val);
 119
 120                return 0;
 121
 122        case MT7620_SYSC_IOCTL_SET_PCIE_MODE:
 123                val = *(u32 *)buf;
 124
 125                if (val == MT7620_SYSC_PCIE_EP_MODE)
 126                        val = 0;
 127                else if (val == MT7620_SYSC_PCIE_RC_MODE)
 128                        val = PCIE_RC_MODE;
 129
 130                clrsetbits_32(priv->base + SYSCTL_SYSCFG1_REG,
 131                              PCIE_RC_MODE, val);
 132
 133                return 0;
 134
 135        default:
 136                return -EINVAL;
 137        }
 138}
 139
 140static int mt7620_sysc_probe(struct udevice *dev)
 141{
 142        struct mt7620_sysc_priv *priv = dev_get_priv(dev);
 143
 144        priv->base = dev_remap_addr_index(dev, 0);
 145        if (!priv->base) {
 146                dev_err(dev, "failed to map sysc registers\n");
 147                return -EINVAL;
 148        }
 149
 150        return 0;
 151}
 152
 153static struct misc_ops mt7620_sysc_ops = {
 154        .read = mt7620_sysc_read,
 155        .write = mt7620_sysc_write,
 156        .ioctl = mt7620_sysc_ioctl,
 157};
 158
 159static const struct udevice_id mt7620_sysc_ids[] = {
 160        { .compatible = "mediatek,mt7620-sysc" },
 161        { }
 162};
 163
 164U_BOOT_DRIVER(mt7620_sysc) = {
 165        .name           = "mt7620_sysc",
 166        .id             = UCLASS_MISC,
 167        .of_match       = mt7620_sysc_ids,
 168        .probe          = mt7620_sysc_probe,
 169        .ops            = &mt7620_sysc_ops,
 170        .priv_auto      = sizeof(struct mt7620_sysc_priv),
 171        .flags = DM_FLAG_PRE_RELOC,
 172};
 173