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
2324struct 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+
4796struct 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
53102static 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
84122static 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+
101185static 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
144221static 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};
150232MODULE_DEVICE_TABLE (auxiliary , imx8mp_audiomix_reset_ids );
151233
152234static 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