Skip to content

Commit a393bda

Browse files
committed
Merge tag 'reset-for-v6.20' of https://git.pengutronix.de/git/pza/linux into soc/drivers
Reset controller updates for v6.20 * Add a compatible to the reset-gpio driver, suppress the sysfs bind attributes, and propagate GPIO API errors. * Add support for the i.MX8ULP SIM LPAV reset controller. * Add RZ/G3S USBPHY suspend/resume support. * Enable reset-k230 by default on ARCH_CANAAN * Add support for the SpacemiT K3 SoC reset controller. * Merge the 'spacemit-clkrst-v6.20-3' tag, shared with the clk tree, as a dependency for the SpacemiT changes. * tag 'reset-for-v6.20' of https://git.pengutronix.de/git/pza/linux: reset: spacemit: Add SpacemiT K3 reset driver reset: spacemit: Extract common K1 reset code reset: Create subdirectory for SpacemiT drivers dt-bindings: soc: spacemit: Add K3 reset support and IDs reset: canaan: k230: drop OF dependency and enable by default reset: rzg2l-usbphy-ctrl: Add suspend/resume support reset: rzg2l-usbphy-ctrl: Propagate the return value of regmap_field_update_bits() reset: gpio: check the return value of gpiod_set_value_cansleep() reset: imx8mp-audiomix: Support i.MX8ULP SIM LPAV reset: imx8mp-audiomix: Extend the driver usage reset: imx8mp-audiomix: Switch to using regmap API reset: imx8mp-audiomix: Drop unneeded macros reset: gpio: suppress bind attributes in sysfs clk: spacemit: k3: extract common header reset: spacemit: fix auxiliary device id clk: spacemit: prepare common ccu header reset: gpio: add the "compatible" property Signed-off-by: Arnd Bergmann <arnd@arndb.de>
2 parents 5b303a0 + 938ce3b commit a393bda

17 files changed

Lines changed: 1103 additions & 195 deletions

File tree

Documentation/devicetree/bindings/soc/spacemit/spacemit,k1-syscon.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ maintainers:
1010
- Haylen Chu <heylenay@4d2.org>
1111

1212
description:
13-
System controllers found on SpacemiT K1 SoC, which are capable of
13+
System controllers found on SpacemiT K1/K3 SoC, which are capable of
1414
clock, reset and power-management functions.
1515

1616
properties:
@@ -46,6 +46,12 @@ properties:
4646

4747
"#reset-cells":
4848
const: 1
49+
description: |
50+
ID of the reset controller line. Valid IDs are defined in corresponding
51+
files:
52+
53+
For SpacemiT K1, see include/dt-bindings/clock/spacemit,k1-syscon.h
54+
For SpacemiT K3, see include/dt-bindings/reset/spacemit,k3-resets.h
4955
5056
required:
5157
- compatible

drivers/reset/Kconfig

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ config RESET_K210
161161
config RESET_K230
162162
tristate "Reset controller driver for Canaan Kendryte K230 SoC"
163163
depends on ARCH_CANAAN || COMPILE_TEST
164-
depends on OF
164+
default ARCH_CANAAN
165165
help
166166
Support for the Canaan Kendryte K230 RISC-V SoC reset controller.
167167
Say Y if you want to control reset signals provided by this
@@ -299,15 +299,6 @@ config RESET_SOCFPGA
299299
This enables the reset driver for the SoCFPGA ARMv7 platforms. This
300300
driver gets initialized early during platform init calls.
301301

302-
config RESET_SPACEMIT
303-
tristate "SpacemiT reset driver"
304-
depends on ARCH_SPACEMIT || COMPILE_TEST
305-
select AUXILIARY_BUS
306-
default ARCH_SPACEMIT
307-
help
308-
This enables the reset controller driver for SpacemiT SoCs,
309-
including the K1.
310-
311302
config RESET_SUNPLUS
312303
bool "Sunplus SoCs Reset Driver" if COMPILE_TEST
313304
default ARCH_SUNPLUS
@@ -406,9 +397,10 @@ config RESET_ZYNQMP
406397
This enables the reset controller driver for Xilinx ZynqMP SoCs.
407398

408399
source "drivers/reset/amlogic/Kconfig"
400+
source "drivers/reset/hisilicon/Kconfig"
401+
source "drivers/reset/spacemit/Kconfig"
409402
source "drivers/reset/starfive/Kconfig"
410403
source "drivers/reset/sti/Kconfig"
411-
source "drivers/reset/hisilicon/Kconfig"
412404
source "drivers/reset/tegra/Kconfig"
413405

414406
endif

drivers/reset/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
obj-y += core.o
33
obj-y += amlogic/
44
obj-y += hisilicon/
5+
obj-y += spacemit/
56
obj-y += starfive/
67
obj-y += sti/
78
obj-y += tegra/
@@ -38,7 +39,6 @@ obj-$(CONFIG_RESET_RZV2H_USB2PHY) += reset-rzv2h-usb2phy.o
3839
obj-$(CONFIG_RESET_SCMI) += reset-scmi.o
3940
obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
4041
obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
41-
obj-$(CONFIG_RESET_SPACEMIT) += reset-spacemit.o
4242
obj-$(CONFIG_RESET_SUNPLUS) += reset-sunplus.o
4343
obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
4444
obj-$(CONFIG_RESET_TH1520) += reset-th1520.o

drivers/reset/core.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -868,11 +868,11 @@ static int reset_add_gpio_aux_device(struct device *parent,
868868
*/
869869
static int __reset_add_reset_gpio_device(const struct of_phandle_args *args)
870870
{
871-
struct property_entry properties[2] = { };
871+
struct property_entry properties[3] = { };
872872
unsigned int offset, of_flags, lflags;
873873
struct reset_gpio_lookup *rgpio_dev;
874874
struct device *parent;
875-
int id, ret;
875+
int id, ret, prop = 0;
876876

877877
/*
878878
* Currently only #gpio-cells=2 is supported with the meaning of:
@@ -923,7 +923,8 @@ static int __reset_add_reset_gpio_device(const struct of_phandle_args *args)
923923

924924
lflags = GPIO_PERSISTENT | (of_flags & GPIO_ACTIVE_LOW);
925925
parent = gpio_device_to_device(gdev);
926-
properties[0] = PROPERTY_ENTRY_GPIO("reset-gpios", parent->fwnode, offset, lflags);
926+
properties[prop++] = PROPERTY_ENTRY_STRING("compatible", "reset-gpio");
927+
properties[prop++] = PROPERTY_ENTRY_GPIO("reset-gpios", parent->fwnode, offset, lflags);
927928

928929
id = ida_alloc(&reset_gpio_ida, GFP_KERNEL);
929930
if (id < 0)

drivers/reset/reset-gpio.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,15 @@ static int reset_gpio_assert(struct reset_controller_dev *rc, unsigned long id)
2222
{
2323
struct reset_gpio_priv *priv = rc_to_reset_gpio(rc);
2424

25-
gpiod_set_value_cansleep(priv->reset, 1);
26-
27-
return 0;
25+
return gpiod_set_value_cansleep(priv->reset, 1);
2826
}
2927

3028
static int reset_gpio_deassert(struct reset_controller_dev *rc,
3129
unsigned long id)
3230
{
3331
struct reset_gpio_priv *priv = rc_to_reset_gpio(rc);
3432

35-
gpiod_set_value_cansleep(priv->reset, 0);
36-
37-
return 0;
33+
return gpiod_set_value_cansleep(priv->reset, 0);
3834
}
3935

4036
static int reset_gpio_status(struct reset_controller_dev *rc, unsigned long id)
@@ -111,6 +107,7 @@ static struct auxiliary_driver reset_gpio_driver = {
111107
.id_table = reset_gpio_ids,
112108
.driver = {
113109
.name = "reset-gpio",
110+
.suppress_bind_attrs = true,
114111
},
115112
};
116113
module_auxiliary_driver(reset_gpio_driver);

drivers/reset/reset-imx8mp-audiomix.c

Lines changed: 125 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,51 +3,100 @@
33
* Copyright 2024 NXP
44
*/
55

6+
#include <dt-bindings/reset/fsl,imx8ulp-sim-lpav.h>
67
#include <dt-bindings/reset/imx8mp-reset-audiomix.h>
78

89
#include <linux/auxiliary_bus.h>
10+
#include <linux/bits.h>
911
#include <linux/device.h>
1012
#include <linux/io.h>
1113
#include <linux/module.h>
1214
#include <linux/of.h>
1315
#include <linux/of_address.h>
16+
#include <linux/regmap.h>
1417
#include <linux/reset-controller.h>
1518

1619
#define IMX8MP_AUDIOMIX_EARC_RESET_OFFSET 0x200
17-
#define IMX8MP_AUDIOMIX_EARC_RESET_MASK BIT(0)
18-
#define IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK BIT(1)
19-
2020
#define IMX8MP_AUDIOMIX_DSP_RUNSTALL_OFFSET 0x108
21-
#define IMX8MP_AUDIOMIX_DSP_RUNSTALL_MASK BIT(5)
21+
22+
#define IMX8ULP_SIM_LPAV_SYSCTRL0_OFFSET 0x8
2223

2324
struct imx8mp_reset_map {
2425
unsigned int offset;
2526
unsigned int mask;
2627
bool active_low;
2728
};
2829

29-
static const struct imx8mp_reset_map reset_map[] = {
30+
struct imx8mp_reset_info {
31+
const struct imx8mp_reset_map *map;
32+
int num_lines;
33+
};
34+
35+
static const struct imx8mp_reset_map imx8mp_reset_map[] = {
3036
[IMX8MP_AUDIOMIX_EARC_RESET] = {
3137
.offset = IMX8MP_AUDIOMIX_EARC_RESET_OFFSET,
32-
.mask = IMX8MP_AUDIOMIX_EARC_RESET_MASK,
38+
.mask = BIT(0),
3339
.active_low = true,
3440
},
3541
[IMX8MP_AUDIOMIX_EARC_PHY_RESET] = {
3642
.offset = IMX8MP_AUDIOMIX_EARC_RESET_OFFSET,
37-
.mask = IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK,
43+
.mask = BIT(1),
3844
.active_low = true,
3945
},
4046
[IMX8MP_AUDIOMIX_DSP_RUNSTALL] = {
4147
.offset = IMX8MP_AUDIOMIX_DSP_RUNSTALL_OFFSET,
42-
.mask = IMX8MP_AUDIOMIX_DSP_RUNSTALL_MASK,
48+
.mask = BIT(5),
4349
.active_low = false,
4450
},
4551
};
4652

53+
static const struct imx8mp_reset_info imx8mp_reset_info = {
54+
.map = imx8mp_reset_map,
55+
.num_lines = ARRAY_SIZE(imx8mp_reset_map),
56+
};
57+
58+
static const struct imx8mp_reset_map imx8ulp_reset_map[] = {
59+
[IMX8ULP_SIM_LPAV_HIFI4_DSP_DBG_RST] = {
60+
.offset = IMX8ULP_SIM_LPAV_SYSCTRL0_OFFSET,
61+
.mask = BIT(25),
62+
.active_low = false,
63+
},
64+
[IMX8ULP_SIM_LPAV_HIFI4_DSP_RST] = {
65+
.offset = IMX8ULP_SIM_LPAV_SYSCTRL0_OFFSET,
66+
.mask = BIT(16),
67+
.active_low = false,
68+
},
69+
[IMX8ULP_SIM_LPAV_HIFI4_DSP_STALL] = {
70+
.offset = IMX8ULP_SIM_LPAV_SYSCTRL0_OFFSET,
71+
.mask = BIT(13),
72+
.active_low = false,
73+
},
74+
[IMX8ULP_SIM_LPAV_DSI_RST_BYTE_N] = {
75+
.offset = IMX8ULP_SIM_LPAV_SYSCTRL0_OFFSET,
76+
.mask = BIT(5),
77+
.active_low = true,
78+
},
79+
[IMX8ULP_SIM_LPAV_DSI_RST_ESC_N] = {
80+
.offset = IMX8ULP_SIM_LPAV_SYSCTRL0_OFFSET,
81+
.mask = BIT(4),
82+
.active_low = true,
83+
},
84+
[IMX8ULP_SIM_LPAV_DSI_RST_DPI_N] = {
85+
.offset = IMX8ULP_SIM_LPAV_SYSCTRL0_OFFSET,
86+
.mask = BIT(3),
87+
.active_low = true,
88+
},
89+
};
90+
91+
static const struct imx8mp_reset_info imx8ulp_reset_info = {
92+
.map = imx8ulp_reset_map,
93+
.num_lines = ARRAY_SIZE(imx8ulp_reset_map),
94+
};
95+
4796
struct imx8mp_audiomix_reset {
4897
struct reset_controller_dev rcdev;
49-
spinlock_t lock; /* protect register read-modify-write cycle */
50-
void __iomem *base;
98+
struct regmap *regmap;
99+
const struct imx8mp_reset_map *map;
51100
};
52101

53102
static struct imx8mp_audiomix_reset *to_imx8mp_audiomix_reset(struct reset_controller_dev *rcdev)
@@ -59,26 +108,15 @@ static int imx8mp_audiomix_update(struct reset_controller_dev *rcdev,
59108
unsigned long id, bool assert)
60109
{
61110
struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev);
62-
void __iomem *reg_addr = priv->base;
63-
unsigned int mask, offset, active_low;
64-
unsigned long reg, flags;
111+
const struct imx8mp_reset_map *reset_map = priv->map;
112+
unsigned int mask, offset, active_low, val;
65113

66114
mask = reset_map[id].mask;
67115
offset = reset_map[id].offset;
68116
active_low = reset_map[id].active_low;
117+
val = (active_low ^ assert) ? mask : ~mask;
69118

70-
spin_lock_irqsave(&priv->lock, flags);
71-
72-
reg = readl(reg_addr + offset);
73-
if (active_low ^ assert)
74-
reg |= mask;
75-
else
76-
reg &= ~mask;
77-
writel(reg, reg_addr + offset);
78-
79-
spin_unlock_irqrestore(&priv->lock, flags);
80-
81-
return 0;
119+
return regmap_update_bits(priv->regmap, offset, mask, val);
82120
}
83121

84122
static int imx8mp_audiomix_reset_assert(struct reset_controller_dev *rcdev,
@@ -98,60 +136,103 @@ static const struct reset_control_ops imx8mp_audiomix_reset_ops = {
98136
.deassert = imx8mp_audiomix_reset_deassert,
99137
};
100138

139+
static const struct regmap_config regmap_config = {
140+
.reg_bits = 32,
141+
.val_bits = 32,
142+
.reg_stride = 4,
143+
};
144+
145+
/* assumption: registered only if not using parent regmap */
146+
static void imx8mp_audiomix_reset_iounmap(void *data)
147+
{
148+
void __iomem *base = (void __iomem *)data;
149+
150+
iounmap(base);
151+
}
152+
153+
static int imx8mp_audiomix_reset_get_regmap(struct imx8mp_audiomix_reset *priv)
154+
{
155+
void __iomem *base;
156+
struct device *dev;
157+
int ret;
158+
159+
dev = priv->rcdev.dev;
160+
161+
/* try to use the parent's regmap */
162+
priv->regmap = dev_get_regmap(dev->parent, NULL);
163+
if (priv->regmap)
164+
return 0;
165+
166+
/* ... if that's not possible then initialize the regmap right now */
167+
base = of_iomap(dev->parent->of_node, 0);
168+
if (!base)
169+
return dev_err_probe(dev, -ENOMEM, "failed to iomap address space\n");
170+
171+
ret = devm_add_action_or_reset(dev,
172+
imx8mp_audiomix_reset_iounmap,
173+
(void __force *)base);
174+
if (ret)
175+
return dev_err_probe(dev, ret, "failed to register action\n");
176+
177+
priv->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
178+
if (IS_ERR(priv->regmap))
179+
return dev_err_probe(dev, PTR_ERR(priv->regmap),
180+
"failed to initialize regmap\n");
181+
182+
return 0;
183+
}
184+
101185
static int imx8mp_audiomix_reset_probe(struct auxiliary_device *adev,
102186
const struct auxiliary_device_id *id)
103187
{
188+
const struct imx8mp_reset_info *rinfo;
104189
struct imx8mp_audiomix_reset *priv;
105190
struct device *dev = &adev->dev;
106191
int ret;
107192

193+
rinfo = (void *)id->driver_data;
194+
108195
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
109196
if (!priv)
110197
return -ENOMEM;
111198

112-
spin_lock_init(&priv->lock);
113-
114199
priv->rcdev.owner = THIS_MODULE;
115-
priv->rcdev.nr_resets = ARRAY_SIZE(reset_map);
200+
priv->map = rinfo->map;
201+
priv->rcdev.nr_resets = rinfo->num_lines;
116202
priv->rcdev.ops = &imx8mp_audiomix_reset_ops;
117203
priv->rcdev.of_node = dev->parent->of_node;
118204
priv->rcdev.dev = dev;
119205
priv->rcdev.of_reset_n_cells = 1;
120-
priv->base = of_iomap(dev->parent->of_node, 0);
121-
if (!priv->base)
122-
return -ENOMEM;
123206

124207
dev_set_drvdata(dev, priv);
125208

209+
ret = imx8mp_audiomix_reset_get_regmap(priv);
210+
if (ret)
211+
return dev_err_probe(dev, ret, "failed to get regmap\n");
212+
126213
ret = devm_reset_controller_register(dev, &priv->rcdev);
127214
if (ret)
128-
goto out_unmap;
215+
return dev_err_probe(dev, ret,
216+
"failed to register reset controller\n");
129217

130218
return 0;
131-
132-
out_unmap:
133-
iounmap(priv->base);
134-
return ret;
135-
}
136-
137-
static void imx8mp_audiomix_reset_remove(struct auxiliary_device *adev)
138-
{
139-
struct imx8mp_audiomix_reset *priv = dev_get_drvdata(&adev->dev);
140-
141-
iounmap(priv->base);
142219
}
143220

144221
static const struct auxiliary_device_id imx8mp_audiomix_reset_ids[] = {
145222
{
146223
.name = "clk_imx8mp_audiomix.reset",
224+
.driver_data = (kernel_ulong_t)&imx8mp_reset_info,
225+
},
226+
{
227+
.name = "clk_imx8ulp_sim_lpav.reset",
228+
.driver_data = (kernel_ulong_t)&imx8ulp_reset_info,
147229
},
148230
{ }
149231
};
150232
MODULE_DEVICE_TABLE(auxiliary, imx8mp_audiomix_reset_ids);
151233

152234
static struct auxiliary_driver imx8mp_audiomix_reset_driver = {
153235
.probe = imx8mp_audiomix_reset_probe,
154-
.remove = imx8mp_audiomix_reset_remove,
155236
.id_table = imx8mp_audiomix_reset_ids,
156237
};
157238

0 commit comments

Comments
 (0)