2 * Copyright 2014 Google, Inc
3 * Author: Alexandru M Stan <amstan@chromium.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <linux/slab.h>
17 #include <linux/clk-provider.h>
20 struct rockchip_mmc_clock
{
27 #define to_mmc_clock(_hw) container_of(_hw, struct rockchip_mmc_clock, hw)
29 #define RK3288_MMC_CLKGEN_DIV 2
31 static unsigned long rockchip_mmc_recalc(struct clk_hw
*hw
,
32 unsigned long parent_rate
)
34 return parent_rate
/ RK3288_MMC_CLKGEN_DIV
;
37 #define ROCKCHIP_MMC_DELAY_SEL BIT(10)
38 #define ROCKCHIP_MMC_DEGREE_MASK 0x3
39 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 2
40 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
42 #define PSECS_PER_SEC 1000000000000LL
45 * Each fine delay is between 40ps-80ps. Assume each fine delay is 60ps to
46 * simplify calculations. So 45degs could be anywhere between 33deg and 66deg.
48 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
50 static int rockchip_mmc_get_phase(struct clk_hw
*hw
)
52 struct rockchip_mmc_clock
*mmc_clock
= to_mmc_clock(hw
);
53 unsigned long rate
= clk_get_rate(hw
->clk
);
58 raw_value
= readl(mmc_clock
->reg
) >> (mmc_clock
->shift
);
60 degrees
= (raw_value
& ROCKCHIP_MMC_DEGREE_MASK
) * 90;
62 if (raw_value
& ROCKCHIP_MMC_DELAY_SEL
) {
63 /* degrees/delaynum * 10000 */
64 unsigned long factor
= (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC
/ 10) *
65 36 * (rate
/ 1000000);
67 delay_num
= (raw_value
& ROCKCHIP_MMC_DELAYNUM_MASK
);
68 delay_num
>>= ROCKCHIP_MMC_DELAYNUM_OFFSET
;
69 degrees
+= delay_num
* factor
/ 10000;
75 static int rockchip_mmc_set_phase(struct clk_hw
*hw
, int degrees
)
77 struct rockchip_mmc_clock
*mmc_clock
= to_mmc_clock(hw
);
78 unsigned long rate
= clk_get_rate(hw
->clk
);
79 u8 nineties
, remainder
;
84 /* allow 22 to be 22.5 */
86 /* floor to 22.5 increment */
87 degrees
-= ((degrees
) * 10 % 225) / 10;
89 nineties
= degrees
/ 90;
91 remainder
= (degrees
% 90) / 22;
93 delay
= PSECS_PER_SEC
;
97 do_div(delay
, ROCKCHIP_MMC_DELAY_ELEMENT_PSEC
);
100 delay_num
= (u8
) min(delay
, 255ULL);
102 raw_value
= delay_num
? ROCKCHIP_MMC_DELAY_SEL
: 0;
103 raw_value
|= delay_num
<< ROCKCHIP_MMC_DELAYNUM_OFFSET
;
104 raw_value
|= nineties
;
105 writel(HIWORD_UPDATE(raw_value
, 0x07ff, mmc_clock
->shift
), mmc_clock
->reg
);
107 pr_debug("%s->set_phase(%d) delay_nums=%u reg[0x%p]=0x%03x actual_degrees=%d\n",
108 __clk_get_name(hw
->clk
), degrees
, delay_num
,
109 mmc_clock
->reg
, raw_value
>>(mmc_clock
->shift
),
110 rockchip_mmc_get_phase(hw
)
116 static const struct clk_ops rockchip_mmc_clk_ops
= {
117 .recalc_rate
= rockchip_mmc_recalc
,
118 .get_phase
= rockchip_mmc_get_phase
,
119 .set_phase
= rockchip_mmc_set_phase
,
122 struct clk
*rockchip_clk_register_mmc(const char *name
,
123 const char **parent_names
, u8 num_parents
,
124 void __iomem
*reg
, int shift
)
126 struct clk_init_data init
;
127 struct rockchip_mmc_clock
*mmc_clock
;
130 mmc_clock
= kmalloc(sizeof(*mmc_clock
), GFP_KERNEL
);
134 init
.num_parents
= num_parents
;
135 init
.parent_names
= parent_names
;
136 init
.ops
= &rockchip_mmc_clk_ops
;
138 mmc_clock
->hw
.init
= &init
;
139 mmc_clock
->reg
= reg
;
140 mmc_clock
->shift
= shift
;
145 clk
= clk_register(NULL
, &mmc_clock
->hw
);