xref: /openbmc/linux/drivers/clk/sunxi-ng/ccu_mmc_timing.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
19c92ab61SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2f6f64ed8SChen-Yu Tsai /*
3f6f64ed8SChen-Yu Tsai  * Copyright (c) 2017 Chen-Yu Tsai. All rights reserved.
4f6f64ed8SChen-Yu Tsai  */
5f6f64ed8SChen-Yu Tsai 
6f6f64ed8SChen-Yu Tsai #include <linux/clk-provider.h>
7f6f64ed8SChen-Yu Tsai #include <linux/clk/sunxi-ng.h>
862e59c4eSStephen Boyd #include <linux/io.h>
9f6f64ed8SChen-Yu Tsai 
10f6f64ed8SChen-Yu Tsai #include "ccu_common.h"
11f6f64ed8SChen-Yu Tsai 
12f6f64ed8SChen-Yu Tsai /**
135dc64702SRandy Dunlap  * sunxi_ccu_set_mmc_timing_mode - Configure the MMC clock timing mode
14f6f64ed8SChen-Yu Tsai  * @clk: clock to be configured
15f6f64ed8SChen-Yu Tsai  * @new_mode: true for new timing mode introduced in A83T and later
16f6f64ed8SChen-Yu Tsai  *
175dc64702SRandy Dunlap  * Return: %0 on success, %-ENOTSUPP if the clock does not support
18f6f64ed8SChen-Yu Tsai  * switching modes.
19f6f64ed8SChen-Yu Tsai  */
sunxi_ccu_set_mmc_timing_mode(struct clk * clk,bool new_mode)20f6f64ed8SChen-Yu Tsai int sunxi_ccu_set_mmc_timing_mode(struct clk *clk, bool new_mode)
21f6f64ed8SChen-Yu Tsai {
22f6f64ed8SChen-Yu Tsai 	struct clk_hw *hw = __clk_get_hw(clk);
23f6f64ed8SChen-Yu Tsai 	struct ccu_common *cm = hw_to_ccu_common(hw);
24f6f64ed8SChen-Yu Tsai 	unsigned long flags;
25f6f64ed8SChen-Yu Tsai 	u32 val;
26f6f64ed8SChen-Yu Tsai 
27f6f64ed8SChen-Yu Tsai 	if (!(cm->features & CCU_FEATURE_MMC_TIMING_SWITCH))
28f6f64ed8SChen-Yu Tsai 		return -ENOTSUPP;
29f6f64ed8SChen-Yu Tsai 
30f6f64ed8SChen-Yu Tsai 	spin_lock_irqsave(cm->lock, flags);
31f6f64ed8SChen-Yu Tsai 
32f6f64ed8SChen-Yu Tsai 	val = readl(cm->base + cm->reg);
33f6f64ed8SChen-Yu Tsai 	if (new_mode)
34f6f64ed8SChen-Yu Tsai 		val |= CCU_MMC_NEW_TIMING_MODE;
35f6f64ed8SChen-Yu Tsai 	else
36f6f64ed8SChen-Yu Tsai 		val &= ~CCU_MMC_NEW_TIMING_MODE;
37f6f64ed8SChen-Yu Tsai 	writel(val, cm->base + cm->reg);
38f6f64ed8SChen-Yu Tsai 
39f6f64ed8SChen-Yu Tsai 	spin_unlock_irqrestore(cm->lock, flags);
40f6f64ed8SChen-Yu Tsai 
41f6f64ed8SChen-Yu Tsai 	return 0;
42f6f64ed8SChen-Yu Tsai }
43f6f64ed8SChen-Yu Tsai EXPORT_SYMBOL_GPL(sunxi_ccu_set_mmc_timing_mode);
44f6f64ed8SChen-Yu Tsai 
45f6f64ed8SChen-Yu Tsai /**
46*075d9ca5SZhang Jianhua  * sunxi_ccu_get_mmc_timing_mode: Get the current MMC clock timing mode
47f6f64ed8SChen-Yu Tsai  * @clk: clock to query
48f6f64ed8SChen-Yu Tsai  *
495dc64702SRandy Dunlap  * Return: %0 if the clock is in old timing mode, > %0 if it is in
505dc64702SRandy Dunlap  * new timing mode, and %-ENOTSUPP if the clock does not support
51f6f64ed8SChen-Yu Tsai  * this function.
52f6f64ed8SChen-Yu Tsai  */
sunxi_ccu_get_mmc_timing_mode(struct clk * clk)53f6f64ed8SChen-Yu Tsai int sunxi_ccu_get_mmc_timing_mode(struct clk *clk)
54f6f64ed8SChen-Yu Tsai {
55f6f64ed8SChen-Yu Tsai 	struct clk_hw *hw = __clk_get_hw(clk);
56f6f64ed8SChen-Yu Tsai 	struct ccu_common *cm = hw_to_ccu_common(hw);
57f6f64ed8SChen-Yu Tsai 
58f6f64ed8SChen-Yu Tsai 	if (!(cm->features & CCU_FEATURE_MMC_TIMING_SWITCH))
59f6f64ed8SChen-Yu Tsai 		return -ENOTSUPP;
60f6f64ed8SChen-Yu Tsai 
61f6f64ed8SChen-Yu Tsai 	return !!(readl(cm->base + cm->reg) & CCU_MMC_NEW_TIMING_MODE);
62f6f64ed8SChen-Yu Tsai }
63f6f64ed8SChen-Yu Tsai EXPORT_SYMBOL_GPL(sunxi_ccu_get_mmc_timing_mode);
64