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 <dm/device-internal.h> 18#include <linux/bitops.h> 19#include <linux/err.h> 20 21struct mediatek_reset_priv { 22 struct regmap *regmap; 23 u32 regofs; 24 u32 nr_resets; 25}; 26 27static int mediatek_reset_assert(struct reset_ctl *reset_ctl) 28{ 29 struct mediatek_reset_priv *priv = dev_get_priv(reset_ctl->dev); 30 int id = reset_ctl->id; 31 32 if (id >= priv->nr_resets) 33 return -EINVAL; 34 35 return regmap_update_bits(priv->regmap, 36 priv->regofs + ((id / 32) << 2), BIT(id % 32), BIT(id % 32)); 37} 38 39static int mediatek_reset_deassert(struct reset_ctl *reset_ctl) 40{ 41 struct mediatek_reset_priv *priv = dev_get_priv(reset_ctl->dev); 42 int id = reset_ctl->id; 43 44 if (id >= priv->nr_resets) 45 return -EINVAL; 46 47 return regmap_update_bits(priv->regmap, 48 priv->regofs + ((id / 32) << 2), BIT(id % 32), 0); 49} 50 51struct reset_ops mediatek_reset_ops = { 52 .rst_assert = mediatek_reset_assert, 53 .rst_deassert = mediatek_reset_deassert, 54}; 55 56static int mediatek_reset_probe(struct udevice *dev) 57{ 58 struct mediatek_reset_priv *priv = dev_get_priv(dev); 59 60 if (!priv->regofs && !priv->nr_resets) 61 return -EINVAL; 62 63 priv->regmap = syscon_node_to_regmap(dev_ofnode(dev)); 64 if (IS_ERR(priv->regmap)) 65 return PTR_ERR(priv->regmap); 66 67 return 0; 68} 69 70int mediatek_reset_bind(struct udevice *pdev, u32 regofs, u32 num_regs) 71{ 72 struct udevice *rst_dev; 73 struct mediatek_reset_priv *priv; 74 int ret; 75 76 ret = device_bind_driver_to_node(pdev, "mediatek_reset", "reset", 77 dev_ofnode(pdev), &rst_dev); 78 if (ret) 79 return ret; 80 81 priv = malloc(sizeof(struct mediatek_reset_priv)); 82 if (!priv) 83 return -ENOMEM; 84 85 priv->regofs = regofs; 86 priv->nr_resets = num_regs * 32; 87 dev_set_priv(rst_dev, priv); 88 89 return 0; 90} 91 92U_BOOT_DRIVER(mediatek_reset) = { 93 .name = "mediatek_reset", 94 .id = UCLASS_RESET, 95 .probe = mediatek_reset_probe, 96 .ops = &mediatek_reset_ops, 97 .priv_auto = sizeof(struct mediatek_reset_priv), 98}; 99