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 
mediatek_reset_request(struct reset_ctl * reset_ctl)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 
mediatek_reset_free(struct reset_ctl * reset_ctl)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 
mediatek_reset_assert(struct reset_ctl * reset_ctl)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 
mediatek_reset_deassert(struct reset_ctl * reset_ctl)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 
mediatek_reset_probe(struct udevice * dev)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 
mediatek_reset_bind(struct udevice * pdev,u32 regofs,u32 num_regs)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