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