Skip to content

Commit 810797c

Browse files
XBurstbebarino
authored andcommitted
clk: X1000: Add support for calculat REFCLK of USB PHY.
Add functions for calculat the rate of REFCLK, which is needed by USB PHY in Ingenic X1000 SoC. Tested-by: 周正 (Zhou Zheng) <[email protected]> Signed-off-by: 周琰杰 (Zhou Yanjie) <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Stephen Boyd <[email protected]>
1 parent beb61eb commit 810797c

File tree

1 file changed

+83
-1
lines changed

1 file changed

+83
-1
lines changed

drivers/clk/ingenic/x1000-cgu.c

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,87 @@
4848
#define USBPCR_SIDDQ BIT(21)
4949
#define USBPCR_OTG_DISABLE BIT(20)
5050

51+
/* bits within the USBPCR1 register */
52+
#define USBPCR1_REFCLKSEL_SHIFT 26
53+
#define USBPCR1_REFCLKSEL_MASK (0x3 << USBPCR1_REFCLKSEL_SHIFT)
54+
#define USBPCR1_REFCLKSEL_CORE (0x2 << USBPCR1_REFCLKSEL_SHIFT)
55+
#define USBPCR1_REFCLKDIV_SHIFT 24
56+
#define USBPCR1_REFCLKDIV_MASK (0x3 << USBPCR1_REFCLKDIV_SHIFT)
57+
#define USBPCR1_REFCLKDIV_48 (0x2 << USBPCR1_REFCLKDIV_SHIFT)
58+
#define USBPCR1_REFCLKDIV_24 (0x1 << USBPCR1_REFCLKDIV_SHIFT)
59+
#define USBPCR1_REFCLKDIV_12 (0x0 << USBPCR1_REFCLKDIV_SHIFT)
60+
5161
static struct ingenic_cgu *cgu;
5262

63+
static unsigned long x1000_otg_phy_recalc_rate(struct clk_hw *hw,
64+
unsigned long parent_rate)
65+
{
66+
u32 usbpcr1;
67+
unsigned refclk_div;
68+
69+
usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
70+
refclk_div = usbpcr1 & USBPCR1_REFCLKDIV_MASK;
71+
72+
switch (refclk_div) {
73+
case USBPCR1_REFCLKDIV_12:
74+
return 12000000;
75+
76+
case USBPCR1_REFCLKDIV_24:
77+
return 24000000;
78+
79+
case USBPCR1_REFCLKDIV_48:
80+
return 48000000;
81+
}
82+
83+
return parent_rate;
84+
}
85+
86+
static long x1000_otg_phy_round_rate(struct clk_hw *hw, unsigned long req_rate,
87+
unsigned long *parent_rate)
88+
{
89+
if (req_rate < 18000000)
90+
return 12000000;
91+
92+
if (req_rate < 36000000)
93+
return 24000000;
94+
95+
return 48000000;
96+
}
97+
98+
static int x1000_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate,
99+
unsigned long parent_rate)
100+
{
101+
unsigned long flags;
102+
u32 usbpcr1, div_bits;
103+
104+
switch (req_rate) {
105+
case 12000000:
106+
div_bits = USBPCR1_REFCLKDIV_12;
107+
break;
108+
109+
case 24000000:
110+
div_bits = USBPCR1_REFCLKDIV_24;
111+
break;
112+
113+
case 48000000:
114+
div_bits = USBPCR1_REFCLKDIV_48;
115+
break;
116+
117+
default:
118+
return -EINVAL;
119+
}
120+
121+
spin_lock_irqsave(&cgu->lock, flags);
122+
123+
usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
124+
usbpcr1 &= ~USBPCR1_REFCLKDIV_MASK;
125+
usbpcr1 |= div_bits;
126+
writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
127+
128+
spin_unlock_irqrestore(&cgu->lock, flags);
129+
return 0;
130+
}
131+
53132
static int x1000_usb_phy_enable(struct clk_hw *hw)
54133
{
55134
void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
@@ -80,6 +159,10 @@ static int x1000_usb_phy_is_enabled(struct clk_hw *hw)
80159
}
81160

82161
static const struct clk_ops x1000_otg_phy_ops = {
162+
.recalc_rate = x1000_otg_phy_recalc_rate,
163+
.round_rate = x1000_otg_phy_round_rate,
164+
.set_rate = x1000_otg_phy_set_rate,
165+
83166
.enable = x1000_usb_phy_enable,
84167
.disable = x1000_usb_phy_disable,
85168
.is_enabled = x1000_usb_phy_is_enabled,
@@ -144,7 +227,6 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
144227
},
145228
},
146229

147-
148230
/* Custom (SoC-specific) OTG PHY */
149231

150232
[X1000_CLK_OTGPHY] = {

0 commit comments

Comments
 (0)