^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: (GPL-2.0 OR MIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) // Copyright (c) 2018 BayLibre, SAS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // Author: Jerome Brunet <jbrunet@baylibre.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/reset-controller.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <dt-bindings/reset/amlogic,meson-axg-audio-arb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) struct meson_audio_arb_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) struct reset_controller_dev rstc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) void __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) const unsigned int *reset_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct meson_audio_arb_match_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) const unsigned int *reset_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) unsigned int reset_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define ARB_GENERAL_BIT 31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static const unsigned int axg_audio_arb_reset_bits[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) [AXG_ARB_TODDR_A] = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) [AXG_ARB_TODDR_B] = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) [AXG_ARB_TODDR_C] = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) [AXG_ARB_FRDDR_A] = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) [AXG_ARB_FRDDR_B] = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) [AXG_ARB_FRDDR_C] = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static const struct meson_audio_arb_match_data axg_audio_arb_match = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) .reset_bits = axg_audio_arb_reset_bits,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) .reset_num = ARRAY_SIZE(axg_audio_arb_reset_bits),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static const unsigned int sm1_audio_arb_reset_bits[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) [AXG_ARB_TODDR_A] = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) [AXG_ARB_TODDR_B] = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) [AXG_ARB_TODDR_C] = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) [AXG_ARB_FRDDR_A] = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) [AXG_ARB_FRDDR_B] = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) [AXG_ARB_FRDDR_C] = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) [AXG_ARB_TODDR_D] = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) [AXG_ARB_FRDDR_D] = 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static const struct meson_audio_arb_match_data sm1_audio_arb_match = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) .reset_bits = sm1_audio_arb_reset_bits,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) .reset_num = ARRAY_SIZE(sm1_audio_arb_reset_bits),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static int meson_audio_arb_update(struct reset_controller_dev *rcdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) unsigned long id, bool assert)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct meson_audio_arb_data *arb =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) container_of(rcdev, struct meson_audio_arb_data, rstc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) spin_lock(&arb->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) val = readl(arb->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (assert)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) val &= ~BIT(arb->reset_bits[id]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) val |= BIT(arb->reset_bits[id]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) writel(val, arb->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) spin_unlock(&arb->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static int meson_audio_arb_status(struct reset_controller_dev *rcdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned long id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct meson_audio_arb_data *arb =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) container_of(rcdev, struct meson_audio_arb_data, rstc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) val = readl(arb->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return !(val & BIT(arb->reset_bits[id]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static int meson_audio_arb_assert(struct reset_controller_dev *rcdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) unsigned long id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return meson_audio_arb_update(rcdev, id, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static int meson_audio_arb_deassert(struct reset_controller_dev *rcdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) unsigned long id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return meson_audio_arb_update(rcdev, id, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static const struct reset_control_ops meson_audio_arb_rstc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) .assert = meson_audio_arb_assert,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .deassert = meson_audio_arb_deassert,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .status = meson_audio_arb_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static const struct of_device_id meson_audio_arb_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .compatible = "amlogic,meson-axg-audio-arb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .data = &axg_audio_arb_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .compatible = "amlogic,meson-sm1-audio-arb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .data = &sm1_audio_arb_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) MODULE_DEVICE_TABLE(of, meson_audio_arb_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static int meson_audio_arb_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct meson_audio_arb_data *arb = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* Disable all access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) spin_lock(&arb->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) writel(0, arb->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) spin_unlock(&arb->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) clk_disable_unprepare(arb->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static int meson_audio_arb_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) const struct meson_audio_arb_match_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct meson_audio_arb_data *arb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) data = of_device_get_match_data(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) arb = devm_kzalloc(dev, sizeof(*arb), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (!arb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) platform_set_drvdata(pdev, arb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) arb->clk = devm_clk_get(dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (IS_ERR(arb->clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (PTR_ERR(arb->clk) != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) dev_err(dev, "failed to get clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return PTR_ERR(arb->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) arb->regs = devm_ioremap_resource(dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (IS_ERR(arb->regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return PTR_ERR(arb->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) spin_lock_init(&arb->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) arb->reset_bits = data->reset_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) arb->rstc.nr_resets = data->reset_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) arb->rstc.ops = &meson_audio_arb_rstc_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) arb->rstc.of_node = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) arb->rstc.owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * Enable general :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * In the initial state, all memory interfaces are disabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * and the general bit is on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) ret = clk_prepare_enable(arb->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) dev_err(dev, "failed to enable arb clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) writel(BIT(ARB_GENERAL_BIT), arb->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /* Register reset controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) ret = devm_reset_controller_register(dev, &arb->rstc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) dev_err(dev, "failed to register arb reset controller\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) meson_audio_arb_remove(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static struct platform_driver meson_audio_arb_pdrv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) .probe = meson_audio_arb_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) .remove = meson_audio_arb_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) .name = "meson-audio-arb-reset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .of_match_table = meson_audio_arb_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) module_platform_driver(meson_audio_arb_pdrv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) MODULE_DESCRIPTION("Amlogic A113 Audio Memory Arbiter");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) MODULE_LICENSE("GPL v2");