uboot/drivers/power/regulator/npcm8xx_regulator.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2022 Nuvoton Technology Corp.
   4 */
   5
   6#include <common.h>
   7#include <dm.h>
   8#include <asm/io.h>
   9#include <dm/device_compat.h>
  10#include <power/regulator.h>
  11
  12#define REG_VSRCR       0xf08000e8      /* Voltage Supply Control Register */
  13
  14/* Supported voltage levels (uV) */
  15static const u32 volts_type1[] = { 3300000, 1800000 };
  16static const u32 volts_type2[] = { 1000000, 1800000 };
  17#define VOLT_LEV0       0
  18#define VOLT_LEV1       1
  19
  20struct volt_supply {
  21        char *name;
  22        const u32 *volts;
  23        u32 reg_shift;  /* Register bit offset for setting voltage */
  24};
  25
  26static const struct volt_supply npcm8xx_volt_supps[] = {
  27        {"v1", volts_type1, 0},
  28        {"v2", volts_type1, 1},
  29        {"v3", volts_type1, 2},
  30        {"v4", volts_type1, 3},
  31        {"v5", volts_type1, 4},
  32        {"v6", volts_type1, 5},
  33        {"v7", volts_type1, 6},
  34        {"v8", volts_type1, 7},
  35        {"v9", volts_type1, 8},
  36        {"v10", volts_type1, 9},
  37        {"v11", volts_type2, 10},
  38        {"v12", volts_type1, 11},
  39        {"v13", volts_type1, 12},
  40        {"v14", volts_type2, 13},
  41        {"vsif", volts_type1, 14},
  42        {"vr2", volts_type1, 30},
  43};
  44
  45static const struct volt_supply *npcm8xx_volt_supply_get(const char *name)
  46{
  47        int i;
  48
  49        for (i = 0; i < ARRAY_SIZE(npcm8xx_volt_supps); i++) {
  50                if (!strcmp(npcm8xx_volt_supps[i].name, name))
  51                        return &npcm8xx_volt_supps[i];
  52        }
  53
  54        return NULL;
  55}
  56
  57static int npcm8xx_regulator_set_value(struct udevice *dev, int uV)
  58{
  59        struct dm_regulator_uclass_plat *uc_pdata;
  60        const struct volt_supply *supp;
  61        u32 val, level;
  62
  63        uc_pdata = dev_get_uclass_plat(dev);
  64        if (!uc_pdata)
  65                return -ENXIO;
  66
  67        dev_dbg(dev, "%s set_value: %d\n", uc_pdata->name, uV);
  68        supp = npcm8xx_volt_supply_get(uc_pdata->name);
  69        if (!supp)
  70                return -ENOENT;
  71
  72        if (uV == supp->volts[VOLT_LEV0])
  73                level = VOLT_LEV0;
  74        else if (uV == supp->volts[VOLT_LEV1])
  75                level = VOLT_LEV1;
  76        else
  77                return -EINVAL;
  78
  79        /* Set voltage level */
  80        val = readl(REG_VSRCR);
  81        val &= ~BIT(supp->reg_shift);
  82        val |= level << supp->reg_shift;
  83        writel(val, REG_VSRCR);
  84
  85        return 0;
  86}
  87
  88static int npcm8xx_regulator_get_value(struct udevice *dev)
  89{
  90        struct dm_regulator_uclass_plat *uc_pdata;
  91        const struct volt_supply *supp;
  92        u32 val;
  93
  94        uc_pdata = dev_get_uclass_plat(dev);
  95        if (!uc_pdata)
  96                return -ENXIO;
  97
  98        supp = npcm8xx_volt_supply_get(uc_pdata->name);
  99        if (!supp)
 100                return -ENOENT;
 101
 102        val = readl(REG_VSRCR) & BIT(supp->reg_shift);
 103
 104        dev_dbg(dev, "%s get_value: %d\n", uc_pdata->name,
 105                val ? supp->volts[VOLT_LEV1] : supp->volts[VOLT_LEV0]);
 106
 107        return val ? supp->volts[VOLT_LEV1] : supp->volts[VOLT_LEV0];
 108}
 109
 110static int npcm8xx_regulator_set_enable(struct udevice *dev, bool enable)
 111{
 112        /* Always on */
 113        return 0;
 114}
 115
 116static const struct dm_regulator_ops npcm8xx_regulator_ops = {
 117        .set_value      = npcm8xx_regulator_set_value,
 118        .get_value      = npcm8xx_regulator_get_value,
 119        .set_enable     = npcm8xx_regulator_set_enable,
 120};
 121
 122static const struct udevice_id npcm8xx_regulator_ids[] = {
 123        { .compatible = "regulator-npcm845" },
 124        { },
 125};
 126
 127U_BOOT_DRIVER(regulator_npcm8xx) = {
 128        .name = "regulator_npcm845",
 129        .id = UCLASS_REGULATOR,
 130        .ops = &npcm8xx_regulator_ops,
 131        .of_match = npcm8xx_regulator_ids,
 132};
 133