Lines Matching +full:sun6i +full:- +full:a31 +full:- +full:hwspinlock

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * sun6i_hwspinlock.c - hardware spinlock driver for sun6i compatible Allwinner SoCs
10 #include <linux/hwspinlock.h>
24 #define SPINLOCK_BASE_ID 0 /* there is only one hwspinlock device per SoC */
41 struct sun6i_hwspinlock_data *priv = seqf->private; in hwlocks_supported_show()
43 seq_printf(seqf, "%d\n", priv->nlocks); in hwlocks_supported_show()
51 priv->debugfs = debugfs_create_dir(DRIVER_NAME, NULL); in sun6i_hwspinlock_debugfs_init()
52 debugfs_create_file("supported", 0444, priv->debugfs, priv, &hwlocks_supported_fops); in sun6i_hwspinlock_debugfs_init()
63 static int sun6i_hwspinlock_trylock(struct hwspinlock *lock) in sun6i_hwspinlock_trylock()
65 void __iomem *lock_addr = lock->priv; in sun6i_hwspinlock_trylock()
70 static void sun6i_hwspinlock_unlock(struct hwspinlock *lock) in sun6i_hwspinlock_unlock()
72 void __iomem *lock_addr = lock->priv; in sun6i_hwspinlock_unlock()
86 debugfs_remove_recursive(priv->debugfs); in sun6i_hwspinlock_disable()
87 clk_disable_unprepare(priv->ahb_clk); in sun6i_hwspinlock_disable()
88 reset_control_assert(priv->reset); in sun6i_hwspinlock_disable()
94 struct hwspinlock *hwlock; in sun6i_hwspinlock_probe()
103 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); in sun6i_hwspinlock_probe()
105 return -ENOMEM; in sun6i_hwspinlock_probe()
107 priv->ahb_clk = devm_clk_get(&pdev->dev, "ahb"); in sun6i_hwspinlock_probe()
108 if (IS_ERR(priv->ahb_clk)) { in sun6i_hwspinlock_probe()
109 err = PTR_ERR(priv->ahb_clk); in sun6i_hwspinlock_probe()
110 dev_err(&pdev->dev, "unable to get AHB clock (%d)\n", err); in sun6i_hwspinlock_probe()
114 priv->reset = devm_reset_control_get(&pdev->dev, "ahb"); in sun6i_hwspinlock_probe()
115 if (IS_ERR(priv->reset)) in sun6i_hwspinlock_probe()
116 return dev_err_probe(&pdev->dev, PTR_ERR(priv->reset), in sun6i_hwspinlock_probe()
119 err = reset_control_deassert(priv->reset); in sun6i_hwspinlock_probe()
121 dev_err(&pdev->dev, "deassert reset control failure (%d)\n", err); in sun6i_hwspinlock_probe()
125 err = clk_prepare_enable(priv->ahb_clk); in sun6i_hwspinlock_probe()
127 dev_err(&pdev->dev, "unable to prepare AHB clk (%d)\n", err); in sun6i_hwspinlock_probe()
132 * bit 28 and 29 represents the hwspinlock setup in sun6i_hwspinlock_probe()
149 priv->nlocks = 1 << (4 + num_banks); in sun6i_hwspinlock_probe()
152 err = -EINVAL; in sun6i_hwspinlock_probe()
153 dev_err(&pdev->dev, "unsupported hwspinlock setup (%d)\n", num_banks); in sun6i_hwspinlock_probe()
157 priv->bank = devm_kzalloc(&pdev->dev, struct_size(priv->bank, lock, priv->nlocks), in sun6i_hwspinlock_probe()
159 if (!priv->bank) { in sun6i_hwspinlock_probe()
160 err = -ENOMEM; in sun6i_hwspinlock_probe()
164 for (i = 0; i < priv->nlocks; ++i) { in sun6i_hwspinlock_probe()
165 hwlock = &priv->bank->lock[i]; in sun6i_hwspinlock_probe()
166 hwlock->priv = io_base + SPINLOCK_LOCK_REGN + sizeof(u32) * i; in sun6i_hwspinlock_probe()
169 /* failure of debugfs is considered non-fatal */ in sun6i_hwspinlock_probe()
171 if (IS_ERR(priv->debugfs)) in sun6i_hwspinlock_probe()
172 priv->debugfs = NULL; in sun6i_hwspinlock_probe()
174 err = devm_add_action_or_reset(&pdev->dev, sun6i_hwspinlock_disable, priv); in sun6i_hwspinlock_probe()
176 dev_err(&pdev->dev, "failed to add hwspinlock disable action\n"); in sun6i_hwspinlock_probe()
182 return devm_hwspin_lock_register(&pdev->dev, priv->bank, &sun6i_hwspinlock_ops, in sun6i_hwspinlock_probe()
183 SPINLOCK_BASE_ID, priv->nlocks); in sun6i_hwspinlock_probe()
186 clk_disable_unprepare(priv->ahb_clk); in sun6i_hwspinlock_probe()
188 reset_control_assert(priv->reset); in sun6i_hwspinlock_probe()
194 { .compatible = "allwinner,sun6i-a31-hwspinlock", },
209 MODULE_DESCRIPTION("SUN6I hardware spinlock driver");