1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2023 Nuvoton Technology Corp.
4  */
5 
6 #include <dm.h>
7 #include <reset-uclass.h>
8 #include <asm/io.h>
9 #include <dm/device_compat.h>
10 
11 struct npcm_reset_priv {
12 	void __iomem *base;
13 };
14 
npcm_reset_request(struct reset_ctl * rst)15 static int npcm_reset_request(struct reset_ctl *rst)
16 {
17 	return 0;
18 }
19 
npcm_reset_free(struct reset_ctl * rst)20 static int npcm_reset_free(struct reset_ctl *rst)
21 {
22 	return 0;
23 }
24 
npcm_reset_assert(struct reset_ctl * rst)25 static int npcm_reset_assert(struct reset_ctl *rst)
26 {
27 	struct npcm_reset_priv *priv = dev_get_priv(rst->dev);
28 	u32 val;
29 
30 	debug("%s: id 0x%lx, data %ld\n", __func__, rst->id, rst->data);
31 	val = readl(priv->base + rst->id);
32 	val |= BIT(rst->data);
33 	writel(val, priv->base + rst->id);
34 
35 	return 0;
36 }
37 
npcm_reset_deassert(struct reset_ctl * rst)38 static int npcm_reset_deassert(struct reset_ctl *rst)
39 {
40 	struct npcm_reset_priv *priv = dev_get_priv(rst->dev);
41 	u32 val;
42 
43 	debug("%s: id 0x%lx, data %ld\n", __func__, rst->id, rst->data);
44 	val = readl(priv->base + rst->id);
45 	val &= ~BIT(rst->data);
46 	writel(val, priv->base + rst->id);
47 
48 	return 0;
49 }
50 
npcm_reset_xlate(struct reset_ctl * rst,struct ofnode_phandle_args * args)51 static int npcm_reset_xlate(struct reset_ctl *rst,
52 			    struct ofnode_phandle_args *args)
53 {
54 	if (args->args_count != 2) {
55 		dev_err(rst->dev, "Invalid args_count: %d\n", args->args_count);
56 		return -EINVAL;
57 	}
58 
59 	/* Use id field as register offset and data field as reset bit positiion */
60 	rst->id = args->args[0];
61 	rst->data = args->args[1];
62 
63 	return 0;
64 }
65 
npcm_reset_probe(struct udevice * dev)66 static int npcm_reset_probe(struct udevice *dev)
67 {
68 	struct npcm_reset_priv *priv = dev_get_priv(dev);
69 
70 	priv->base = dev_remap_addr(dev);
71 	if (!priv->base)
72 		return -EINVAL;
73 
74 	return 0;
75 }
76 
npcm_reset_bind(struct udevice * dev)77 static int npcm_reset_bind(struct udevice *dev)
78 {
79 	void __iomem *reg_base;
80 	u32 *rcr_values;
81 	int num_fields;
82 	u32 reg, val;
83 	int ret, i;
84 
85 	reg_base = dev_remap_addr(dev);
86 	if (!reg_base)
87 		return -EINVAL;
88 
89 	/*
90 	 * Set RCR initial value
91 	 * The rcr-initial-values cell is <reg_offset val>
92 	 */
93 	num_fields = dev_read_size(dev, "rcr-initial-values");
94 	if (num_fields < 2)
95 		return 0;
96 
97 	num_fields /= sizeof(u32);
98 	if (num_fields % 2)
99 		return -EINVAL;
100 
101 	num_fields = num_fields / 2;
102 	rcr_values = malloc(num_fields * 2 * sizeof(u32));
103 	if (!rcr_values)
104 		return -ENOMEM;
105 
106 	ret = dev_read_u32_array(dev, "rcr-initial-values", rcr_values,
107 				 num_fields * 2);
108 	if (ret < 0) {
109 		free(rcr_values);
110 		return -EINVAL;
111 	}
112 
113 	for (i = 0; i < num_fields; i++) {
114 		reg = rcr_values[2 * i];
115 		val = rcr_values[2 * i + 1];
116 		writel(val, reg_base + reg);
117 	}
118 	free(rcr_values);
119 
120 	return 0;
121 }
122 
123 static const struct udevice_id npcm_reset_ids[] = {
124 	{ .compatible = "nuvoton,npcm845-reset" },
125 	{ .compatible = "nuvoton,npcm750-reset" },
126 	{ }
127 };
128 
129 struct reset_ops npcm_reset_ops = {
130 	.request = npcm_reset_request,
131 	.rfree = npcm_reset_free,
132 	.rst_assert = npcm_reset_assert,
133 	.rst_deassert = npcm_reset_deassert,
134 	.of_xlate = npcm_reset_xlate,
135 };
136 
137 U_BOOT_DRIVER(npcm_reset) = {
138 	.name = "npcm_reset",
139 	.id = UCLASS_RESET,
140 	.of_match = npcm_reset_ids,
141 	.bind = npcm_reset_bind,
142 	.probe = npcm_reset_probe,
143 	.ops = &npcm_reset_ops,
144 	.priv_auto = sizeof(struct npcm_reset_priv),
145 };
146