1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 // Copyright (c) 2018 BayLibre, SAS.
3 // Author: Jerome Brunet <jbrunet@baylibre.com>
7 #include <linux/module.h>
8 #include <linux/of_platform.h>
9 #include <linux/reset-controller.h>
10 #include <linux/spinlock.h>
12 #include <dt-bindings/reset/amlogic,meson-axg-audio-arb.h>
14 struct meson_audio_arb_data
{
15 struct reset_controller_dev rstc
;
18 const unsigned int *reset_bits
;
22 struct meson_audio_arb_match_data
{
23 const unsigned int *reset_bits
;
24 unsigned int reset_num
;
27 #define ARB_GENERAL_BIT 31
29 static const unsigned int axg_audio_arb_reset_bits
[] = {
30 [AXG_ARB_TODDR_A
] = 0,
31 [AXG_ARB_TODDR_B
] = 1,
32 [AXG_ARB_TODDR_C
] = 2,
33 [AXG_ARB_FRDDR_A
] = 4,
34 [AXG_ARB_FRDDR_B
] = 5,
35 [AXG_ARB_FRDDR_C
] = 6,
38 static const struct meson_audio_arb_match_data axg_audio_arb_match
= {
39 .reset_bits
= axg_audio_arb_reset_bits
,
40 .reset_num
= ARRAY_SIZE(axg_audio_arb_reset_bits
),
43 static const unsigned int sm1_audio_arb_reset_bits
[] = {
44 [AXG_ARB_TODDR_A
] = 0,
45 [AXG_ARB_TODDR_B
] = 1,
46 [AXG_ARB_TODDR_C
] = 2,
47 [AXG_ARB_FRDDR_A
] = 4,
48 [AXG_ARB_FRDDR_B
] = 5,
49 [AXG_ARB_FRDDR_C
] = 6,
50 [AXG_ARB_TODDR_D
] = 3,
51 [AXG_ARB_FRDDR_D
] = 7,
54 static const struct meson_audio_arb_match_data sm1_audio_arb_match
= {
55 .reset_bits
= sm1_audio_arb_reset_bits
,
56 .reset_num
= ARRAY_SIZE(sm1_audio_arb_reset_bits
),
59 static int meson_audio_arb_update(struct reset_controller_dev
*rcdev
,
60 unsigned long id
, bool assert)
63 struct meson_audio_arb_data
*arb
=
64 container_of(rcdev
, struct meson_audio_arb_data
, rstc
);
66 spin_lock(&arb
->lock
);
67 val
= readl(arb
->regs
);
70 val
&= ~BIT(arb
->reset_bits
[id
]);
72 val
|= BIT(arb
->reset_bits
[id
]);
74 writel(val
, arb
->regs
);
75 spin_unlock(&arb
->lock
);
80 static int meson_audio_arb_status(struct reset_controller_dev
*rcdev
,
84 struct meson_audio_arb_data
*arb
=
85 container_of(rcdev
, struct meson_audio_arb_data
, rstc
);
87 val
= readl(arb
->regs
);
89 return !(val
& BIT(arb
->reset_bits
[id
]));
92 static int meson_audio_arb_assert(struct reset_controller_dev
*rcdev
,
95 return meson_audio_arb_update(rcdev
, id
, true);
98 static int meson_audio_arb_deassert(struct reset_controller_dev
*rcdev
,
101 return meson_audio_arb_update(rcdev
, id
, false);
104 static const struct reset_control_ops meson_audio_arb_rstc_ops
= {
105 .assert = meson_audio_arb_assert
,
106 .deassert
= meson_audio_arb_deassert
,
107 .status
= meson_audio_arb_status
,
110 static const struct of_device_id meson_audio_arb_of_match
[] = {
112 .compatible
= "amlogic,meson-axg-audio-arb",
113 .data
= &axg_audio_arb_match
,
115 .compatible
= "amlogic,meson-sm1-audio-arb",
116 .data
= &sm1_audio_arb_match
,
120 MODULE_DEVICE_TABLE(of
, meson_audio_arb_of_match
);
122 static int meson_audio_arb_remove(struct platform_device
*pdev
)
124 struct meson_audio_arb_data
*arb
= platform_get_drvdata(pdev
);
126 /* Disable all access */
127 spin_lock(&arb
->lock
);
128 writel(0, arb
->regs
);
129 spin_unlock(&arb
->lock
);
131 clk_disable_unprepare(arb
->clk
);
136 static int meson_audio_arb_probe(struct platform_device
*pdev
)
138 struct device
*dev
= &pdev
->dev
;
139 const struct meson_audio_arb_match_data
*data
;
140 struct meson_audio_arb_data
*arb
;
141 struct resource
*res
;
144 data
= of_device_get_match_data(dev
);
148 arb
= devm_kzalloc(dev
, sizeof(*arb
), GFP_KERNEL
);
151 platform_set_drvdata(pdev
, arb
);
153 arb
->clk
= devm_clk_get(dev
, NULL
);
154 if (IS_ERR(arb
->clk
)) {
155 if (PTR_ERR(arb
->clk
) != -EPROBE_DEFER
)
156 dev_err(dev
, "failed to get clock\n");
157 return PTR_ERR(arb
->clk
);
160 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
161 arb
->regs
= devm_ioremap_resource(dev
, res
);
162 if (IS_ERR(arb
->regs
))
163 return PTR_ERR(arb
->regs
);
165 spin_lock_init(&arb
->lock
);
166 arb
->reset_bits
= data
->reset_bits
;
167 arb
->rstc
.nr_resets
= data
->reset_num
;
168 arb
->rstc
.ops
= &meson_audio_arb_rstc_ops
;
169 arb
->rstc
.of_node
= dev
->of_node
;
170 arb
->rstc
.owner
= THIS_MODULE
;
174 * In the initial state, all memory interfaces are disabled
175 * and the general bit is on
177 ret
= clk_prepare_enable(arb
->clk
);
179 dev_err(dev
, "failed to enable arb clock\n");
182 writel(BIT(ARB_GENERAL_BIT
), arb
->regs
);
184 /* Register reset controller */
185 ret
= devm_reset_controller_register(dev
, &arb
->rstc
);
187 dev_err(dev
, "failed to register arb reset controller\n");
188 meson_audio_arb_remove(pdev
);
194 static struct platform_driver meson_audio_arb_pdrv
= {
195 .probe
= meson_audio_arb_probe
,
196 .remove
= meson_audio_arb_remove
,
198 .name
= "meson-audio-arb-reset",
199 .of_match_table
= meson_audio_arb_of_match
,
202 module_platform_driver(meson_audio_arb_pdrv
);
204 MODULE_DESCRIPTION("Amlogic A113 Audio Memory Arbiter");
205 MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
206 MODULE_LICENSE("GPL v2");