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>
9 #include <linux/platform_device.h>
10 #include <linux/reset-controller.h>
11 #include <linux/spinlock.h>
13 #include <dt-bindings/reset/amlogic,meson-axg-audio-arb.h>
15 struct meson_audio_arb_data
{
16 struct reset_controller_dev rstc
;
19 const unsigned int *reset_bits
;
23 struct meson_audio_arb_match_data
{
24 const unsigned int *reset_bits
;
25 unsigned int reset_num
;
28 #define ARB_GENERAL_BIT 31
30 static const unsigned int axg_audio_arb_reset_bits
[] = {
31 [AXG_ARB_TODDR_A
] = 0,
32 [AXG_ARB_TODDR_B
] = 1,
33 [AXG_ARB_TODDR_C
] = 2,
34 [AXG_ARB_FRDDR_A
] = 4,
35 [AXG_ARB_FRDDR_B
] = 5,
36 [AXG_ARB_FRDDR_C
] = 6,
39 static const struct meson_audio_arb_match_data axg_audio_arb_match
= {
40 .reset_bits
= axg_audio_arb_reset_bits
,
41 .reset_num
= ARRAY_SIZE(axg_audio_arb_reset_bits
),
44 static const unsigned int sm1_audio_arb_reset_bits
[] = {
45 [AXG_ARB_TODDR_A
] = 0,
46 [AXG_ARB_TODDR_B
] = 1,
47 [AXG_ARB_TODDR_C
] = 2,
48 [AXG_ARB_FRDDR_A
] = 4,
49 [AXG_ARB_FRDDR_B
] = 5,
50 [AXG_ARB_FRDDR_C
] = 6,
51 [AXG_ARB_TODDR_D
] = 3,
52 [AXG_ARB_FRDDR_D
] = 7,
55 static const struct meson_audio_arb_match_data sm1_audio_arb_match
= {
56 .reset_bits
= sm1_audio_arb_reset_bits
,
57 .reset_num
= ARRAY_SIZE(sm1_audio_arb_reset_bits
),
60 static int meson_audio_arb_update(struct reset_controller_dev
*rcdev
,
61 unsigned long id
, bool assert)
64 struct meson_audio_arb_data
*arb
=
65 container_of(rcdev
, struct meson_audio_arb_data
, rstc
);
67 spin_lock(&arb
->lock
);
68 val
= readl(arb
->regs
);
71 val
&= ~BIT(arb
->reset_bits
[id
]);
73 val
|= BIT(arb
->reset_bits
[id
]);
75 writel(val
, arb
->regs
);
76 spin_unlock(&arb
->lock
);
81 static int meson_audio_arb_status(struct reset_controller_dev
*rcdev
,
85 struct meson_audio_arb_data
*arb
=
86 container_of(rcdev
, struct meson_audio_arb_data
, rstc
);
88 val
= readl(arb
->regs
);
90 return !(val
& BIT(arb
->reset_bits
[id
]));
93 static int meson_audio_arb_assert(struct reset_controller_dev
*rcdev
,
96 return meson_audio_arb_update(rcdev
, id
, true);
99 static int meson_audio_arb_deassert(struct reset_controller_dev
*rcdev
,
102 return meson_audio_arb_update(rcdev
, id
, false);
105 static const struct reset_control_ops meson_audio_arb_rstc_ops
= {
106 .assert = meson_audio_arb_assert
,
107 .deassert
= meson_audio_arb_deassert
,
108 .status
= meson_audio_arb_status
,
111 static const struct of_device_id meson_audio_arb_of_match
[] = {
113 .compatible
= "amlogic,meson-axg-audio-arb",
114 .data
= &axg_audio_arb_match
,
116 .compatible
= "amlogic,meson-sm1-audio-arb",
117 .data
= &sm1_audio_arb_match
,
121 MODULE_DEVICE_TABLE(of
, meson_audio_arb_of_match
);
123 static void meson_audio_arb_remove(struct platform_device
*pdev
)
125 struct meson_audio_arb_data
*arb
= platform_get_drvdata(pdev
);
127 /* Disable all access */
128 spin_lock(&arb
->lock
);
129 writel(0, arb
->regs
);
130 spin_unlock(&arb
->lock
);
133 static int meson_audio_arb_probe(struct platform_device
*pdev
)
135 struct device
*dev
= &pdev
->dev
;
136 const struct meson_audio_arb_match_data
*data
;
137 struct meson_audio_arb_data
*arb
;
140 data
= of_device_get_match_data(dev
);
144 arb
= devm_kzalloc(dev
, sizeof(*arb
), GFP_KERNEL
);
147 platform_set_drvdata(pdev
, arb
);
149 arb
->clk
= devm_clk_get_enabled(dev
, NULL
);
150 if (IS_ERR(arb
->clk
))
151 return dev_err_probe(dev
, PTR_ERR(arb
->clk
), "failed to get clock\n");
153 arb
->regs
= devm_platform_ioremap_resource(pdev
, 0);
154 if (IS_ERR(arb
->regs
))
155 return PTR_ERR(arb
->regs
);
157 spin_lock_init(&arb
->lock
);
158 arb
->reset_bits
= data
->reset_bits
;
159 arb
->rstc
.nr_resets
= data
->reset_num
;
160 arb
->rstc
.ops
= &meson_audio_arb_rstc_ops
;
161 arb
->rstc
.of_node
= dev
->of_node
;
162 arb
->rstc
.owner
= THIS_MODULE
;
166 * In the initial state, all memory interfaces are disabled
167 * and the general bit is on
169 writel(BIT(ARB_GENERAL_BIT
), arb
->regs
);
171 /* Register reset controller */
172 ret
= devm_reset_controller_register(dev
, &arb
->rstc
);
174 dev_err(dev
, "failed to register arb reset controller\n");
175 meson_audio_arb_remove(pdev
);
181 static struct platform_driver meson_audio_arb_pdrv
= {
182 .probe
= meson_audio_arb_probe
,
183 .remove_new
= meson_audio_arb_remove
,
185 .name
= "meson-audio-arb-reset",
186 .of_match_table
= meson_audio_arb_of_match
,
189 module_platform_driver(meson_audio_arb_pdrv
);
191 MODULE_DESCRIPTION("Amlogic A113 Audio Memory Arbiter");
192 MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
193 MODULE_LICENSE("GPL v2");