Commit | Line | Data |
---|---|---|
f6f64ed8 CYT |
1 | /* |
2 | * Copyright (c) 2017 Chen-Yu Tsai. All rights reserved. | |
3 | * | |
4 | * This software is licensed under the terms of the GNU General Public | |
5 | * License version 2, as published by the Free Software Foundation, and | |
6 | * may be copied, distributed, and modified under those terms. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, | |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | * GNU General Public License for more details. | |
12 | */ | |
13 | ||
14 | #include <linux/clk-provider.h> | |
15 | #include <linux/clk/sunxi-ng.h> | |
62e59c4e | 16 | #include <linux/io.h> |
f6f64ed8 CYT |
17 | |
18 | #include "ccu_common.h" | |
19 | ||
20 | /** | |
21 | * sunxi_ccu_set_mmc_timing_mode: Configure the MMC clock timing mode | |
22 | * @clk: clock to be configured | |
23 | * @new_mode: true for new timing mode introduced in A83T and later | |
24 | * | |
25 | * Returns 0 on success, -ENOTSUPP if the clock does not support | |
26 | * switching modes. | |
27 | */ | |
28 | int sunxi_ccu_set_mmc_timing_mode(struct clk *clk, bool new_mode) | |
29 | { | |
30 | struct clk_hw *hw = __clk_get_hw(clk); | |
31 | struct ccu_common *cm = hw_to_ccu_common(hw); | |
32 | unsigned long flags; | |
33 | u32 val; | |
34 | ||
35 | if (!(cm->features & CCU_FEATURE_MMC_TIMING_SWITCH)) | |
36 | return -ENOTSUPP; | |
37 | ||
38 | spin_lock_irqsave(cm->lock, flags); | |
39 | ||
40 | val = readl(cm->base + cm->reg); | |
41 | if (new_mode) | |
42 | val |= CCU_MMC_NEW_TIMING_MODE; | |
43 | else | |
44 | val &= ~CCU_MMC_NEW_TIMING_MODE; | |
45 | writel(val, cm->base + cm->reg); | |
46 | ||
47 | spin_unlock_irqrestore(cm->lock, flags); | |
48 | ||
49 | return 0; | |
50 | } | |
51 | EXPORT_SYMBOL_GPL(sunxi_ccu_set_mmc_timing_mode); | |
52 | ||
53 | /** | |
54 | * sunxi_ccu_set_mmc_timing_mode: Get the current MMC clock timing mode | |
55 | * @clk: clock to query | |
56 | * | |
57 | * Returns 0 if the clock is in old timing mode, > 0 if it is in | |
58 | * new timing mode, and -ENOTSUPP if the clock does not support | |
59 | * this function. | |
60 | */ | |
61 | int sunxi_ccu_get_mmc_timing_mode(struct clk *clk) | |
62 | { | |
63 | struct clk_hw *hw = __clk_get_hw(clk); | |
64 | struct ccu_common *cm = hw_to_ccu_common(hw); | |
65 | ||
66 | if (!(cm->features & CCU_FEATURE_MMC_TIMING_SWITCH)) | |
67 | return -ENOTSUPP; | |
68 | ||
69 | return !!(readl(cm->base + cm->reg) & CCU_MMC_NEW_TIMING_MODE); | |
70 | } | |
71 | EXPORT_SYMBOL_GPL(sunxi_ccu_get_mmc_timing_mode); |