uboot/drivers/reset/reset-mediatek.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2018 MediaTek Inc.
   4 *
   5 * Author: Ryder Lee <ryder.lee@mediatek.com>
   6 *         Weijie Gao <weijie.gao@mediatek.com>
   7 */
   8
   9#include <common.h>
  10#include <dm.h>
  11#include <log.h>
  12#include <malloc.h>
  13#include <dm/lists.h>
  14#include <regmap.h>
  15#include <reset-uclass.h>
  16#include <syscon.h>
  17#include <linux/bitops.h>
  18#include <linux/err.h>
  19
  20struct mediatek_reset_priv {
  21        struct regmap *regmap;
  22        u32 regofs;
  23        u32 nr_resets;
  24};
  25
  26static int mediatek_reset_request(struct reset_ctl *reset_ctl)
  27{
  28        return 0;
  29}
  30
  31static int mediatek_reset_free(struct reset_ctl *reset_ctl)
  32{
  33        return 0;
  34}
  35
  36static int mediatek_reset_assert(struct reset_ctl *reset_ctl)
  37{
  38        struct mediatek_reset_priv *priv = dev_get_priv(reset_ctl->dev);
  39        int id = reset_ctl->id;
  40
  41        if (id >= priv->nr_resets)
  42                return -EINVAL;
  43
  44        return regmap_update_bits(priv->regmap,
  45                priv->regofs + ((id / 32) << 2), BIT(id % 32), BIT(id % 32));
  46}
  47
  48static int mediatek_reset_deassert(struct reset_ctl *reset_ctl)
  49{
  50        struct mediatek_reset_priv *priv = dev_get_priv(reset_ctl->dev);
  51        int id = reset_ctl->id;
  52
  53        if (id >= priv->nr_resets)
  54                return -EINVAL;
  55
  56        return regmap_update_bits(priv->regmap,
  57                priv->regofs + ((id / 32) << 2), BIT(id % 32), 0);
  58}
  59
  60struct reset_ops mediatek_reset_ops = {
  61        .request = mediatek_reset_request,
  62        .rfree = mediatek_reset_free,
  63        .rst_assert = mediatek_reset_assert,
  64        .rst_deassert = mediatek_reset_deassert,
  65};
  66
  67static int mediatek_reset_probe(struct udevice *dev)
  68{
  69        struct mediatek_reset_priv *priv = dev_get_priv(dev);
  70
  71        if (!priv->regofs && !priv->nr_resets)
  72                return -EINVAL;
  73
  74        priv->regmap = syscon_node_to_regmap(dev_ofnode(dev));
  75        if (IS_ERR(priv->regmap))
  76                return PTR_ERR(priv->regmap);
  77
  78        return 0;
  79}
  80
  81int mediatek_reset_bind(struct udevice *pdev, u32 regofs, u32 num_regs)
  82{
  83        struct udevice *rst_dev;
  84        struct mediatek_reset_priv *priv;
  85        int ret;
  86
  87        ret = device_bind_driver_to_node(pdev, "mediatek_reset", "reset",
  88                                         dev_ofnode(pdev), &rst_dev);
  89        if (ret)
  90                return ret;
  91
  92        priv = malloc(sizeof(struct mediatek_reset_priv));
  93        priv->regofs = regofs;
  94        priv->nr_resets = num_regs * 32;
  95        rst_dev->priv = priv;
  96
  97        return 0;
  98}
  99
 100U_BOOT_DRIVER(mediatek_reset) = {
 101        .name = "mediatek_reset",
 102        .id = UCLASS_RESET,
 103        .probe = mediatek_reset_probe,
 104        .ops = &mediatek_reset_ops,
 105        .priv_auto_alloc_size = sizeof(struct mediatek_reset_priv),
 106};
 107