Skip to content

Commit 6d6818a

Browse files
LaurentiuM1234pH5
authored andcommitted
reset: imx8mp-audiomix: Switch to using regmap API
Switch to using the regmap API to allow performing register operations under the same lock. This is needed for cases such as i.MX8ULP's SIM LPAV where clock gating, reset control and MUX-ing is performed via the same register (i.e. SYSCTRL0) and different subsystem APIs. Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de> Reviewed-by: Frank Li <Frank.Li@nxp.com> Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
1 parent 2122120 commit 6d6818a

1 file changed

Lines changed: 57 additions & 35 deletions

File tree

drivers/reset/reset-imx8mp-audiomix.c

Lines changed: 57 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/module.h>
1313
#include <linux/of.h>
1414
#include <linux/of_address.h>
15+
#include <linux/regmap.h>
1516
#include <linux/reset-controller.h>
1617

1718
#define IMX8MP_AUDIOMIX_EARC_RESET_OFFSET 0x200
@@ -43,8 +44,7 @@ static const struct imx8mp_reset_map reset_map[] = {
4344

4445
struct imx8mp_audiomix_reset {
4546
struct reset_controller_dev rcdev;
46-
spinlock_t lock; /* protect register read-modify-write cycle */
47-
void __iomem *base;
47+
struct regmap *regmap;
4848
};
4949

5050
static struct imx8mp_audiomix_reset *to_imx8mp_audiomix_reset(struct reset_controller_dev *rcdev)
@@ -56,26 +56,14 @@ static int imx8mp_audiomix_update(struct reset_controller_dev *rcdev,
5656
unsigned long id, bool assert)
5757
{
5858
struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev);
59-
void __iomem *reg_addr = priv->base;
60-
unsigned int mask, offset, active_low;
61-
unsigned long reg, flags;
59+
unsigned int mask, offset, active_low, val;
6260

6361
mask = reset_map[id].mask;
6462
offset = reset_map[id].offset;
6563
active_low = reset_map[id].active_low;
64+
val = (active_low ^ assert) ? mask : ~mask;
6665

67-
spin_lock_irqsave(&priv->lock, flags);
68-
69-
reg = readl(reg_addr + offset);
70-
if (active_low ^ assert)
71-
reg |= mask;
72-
else
73-
reg &= ~mask;
74-
writel(reg, reg_addr + offset);
75-
76-
spin_unlock_irqrestore(&priv->lock, flags);
77-
78-
return 0;
66+
return regmap_update_bits(priv->regmap, offset, mask, val);
7967
}
8068

8169
static int imx8mp_audiomix_reset_assert(struct reset_controller_dev *rcdev,
@@ -95,6 +83,52 @@ static const struct reset_control_ops imx8mp_audiomix_reset_ops = {
9583
.deassert = imx8mp_audiomix_reset_deassert,
9684
};
9785

86+
static const struct regmap_config regmap_config = {
87+
.reg_bits = 32,
88+
.val_bits = 32,
89+
.reg_stride = 4,
90+
};
91+
92+
/* assumption: registered only if not using parent regmap */
93+
static void imx8mp_audiomix_reset_iounmap(void *data)
94+
{
95+
void __iomem *base = (void __iomem *)data;
96+
97+
iounmap(base);
98+
}
99+
100+
static int imx8mp_audiomix_reset_get_regmap(struct imx8mp_audiomix_reset *priv)
101+
{
102+
void __iomem *base;
103+
struct device *dev;
104+
int ret;
105+
106+
dev = priv->rcdev.dev;
107+
108+
/* try to use the parent's regmap */
109+
priv->regmap = dev_get_regmap(dev->parent, NULL);
110+
if (priv->regmap)
111+
return 0;
112+
113+
/* ... if that's not possible then initialize the regmap right now */
114+
base = of_iomap(dev->parent->of_node, 0);
115+
if (!base)
116+
return dev_err_probe(dev, -ENOMEM, "failed to iomap address space\n");
117+
118+
ret = devm_add_action_or_reset(dev,
119+
imx8mp_audiomix_reset_iounmap,
120+
(void __force *)base);
121+
if (ret)
122+
return dev_err_probe(dev, ret, "failed to register action\n");
123+
124+
priv->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
125+
if (IS_ERR(priv->regmap))
126+
return dev_err_probe(dev, PTR_ERR(priv->regmap),
127+
"failed to initialize regmap\n");
128+
129+
return 0;
130+
}
131+
98132
static int imx8mp_audiomix_reset_probe(struct auxiliary_device *adev,
99133
const struct auxiliary_device_id *id)
100134
{
@@ -106,36 +140,25 @@ static int imx8mp_audiomix_reset_probe(struct auxiliary_device *adev,
106140
if (!priv)
107141
return -ENOMEM;
108142

109-
spin_lock_init(&priv->lock);
110-
111143
priv->rcdev.owner = THIS_MODULE;
112144
priv->rcdev.nr_resets = ARRAY_SIZE(reset_map);
113145
priv->rcdev.ops = &imx8mp_audiomix_reset_ops;
114146
priv->rcdev.of_node = dev->parent->of_node;
115147
priv->rcdev.dev = dev;
116148
priv->rcdev.of_reset_n_cells = 1;
117-
priv->base = of_iomap(dev->parent->of_node, 0);
118-
if (!priv->base)
119-
return -ENOMEM;
120149

121150
dev_set_drvdata(dev, priv);
122151

152+
ret = imx8mp_audiomix_reset_get_regmap(priv);
153+
if (ret)
154+
return dev_err_probe(dev, ret, "failed to get regmap\n");
155+
123156
ret = devm_reset_controller_register(dev, &priv->rcdev);
124157
if (ret)
125-
goto out_unmap;
158+
return dev_err_probe(dev, ret,
159+
"failed to register reset controller\n");
126160

127161
return 0;
128-
129-
out_unmap:
130-
iounmap(priv->base);
131-
return ret;
132-
}
133-
134-
static void imx8mp_audiomix_reset_remove(struct auxiliary_device *adev)
135-
{
136-
struct imx8mp_audiomix_reset *priv = dev_get_drvdata(&adev->dev);
137-
138-
iounmap(priv->base);
139162
}
140163

141164
static const struct auxiliary_device_id imx8mp_audiomix_reset_ids[] = {
@@ -148,7 +171,6 @@ MODULE_DEVICE_TABLE(auxiliary, imx8mp_audiomix_reset_ids);
148171

149172
static struct auxiliary_driver imx8mp_audiomix_reset_driver = {
150173
.probe = imx8mp_audiomix_reset_probe,
151-
.remove = imx8mp_audiomix_reset_remove,
152174
.id_table = imx8mp_audiomix_reset_ids,
153175
};
154176

0 commit comments

Comments
 (0)