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