mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-22 12:14:01 +08:00
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) <sernia.zhou@foxmail.com> Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com> Link: https://lore.kernel.org/r/20200630163852.47267-4-zhouyanjie@wanyeetech.com Signed-off-by: Stephen Boyd <sboyd@kernel.org>
This commit is contained in:
parent
beb61eb068
commit
810797c145
@ -48,8 +48,87 @@
|
||||
#define USBPCR_SIDDQ BIT(21)
|
||||
#define USBPCR_OTG_DISABLE BIT(20)
|
||||
|
||||
/* bits within the USBPCR1 register */
|
||||
#define USBPCR1_REFCLKSEL_SHIFT 26
|
||||
#define USBPCR1_REFCLKSEL_MASK (0x3 << USBPCR1_REFCLKSEL_SHIFT)
|
||||
#define USBPCR1_REFCLKSEL_CORE (0x2 << USBPCR1_REFCLKSEL_SHIFT)
|
||||
#define USBPCR1_REFCLKDIV_SHIFT 24
|
||||
#define USBPCR1_REFCLKDIV_MASK (0x3 << USBPCR1_REFCLKDIV_SHIFT)
|
||||
#define USBPCR1_REFCLKDIV_48 (0x2 << USBPCR1_REFCLKDIV_SHIFT)
|
||||
#define USBPCR1_REFCLKDIV_24 (0x1 << USBPCR1_REFCLKDIV_SHIFT)
|
||||
#define USBPCR1_REFCLKDIV_12 (0x0 << USBPCR1_REFCLKDIV_SHIFT)
|
||||
|
||||
static struct ingenic_cgu *cgu;
|
||||
|
||||
static unsigned long x1000_otg_phy_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
u32 usbpcr1;
|
||||
unsigned refclk_div;
|
||||
|
||||
usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
|
||||
refclk_div = usbpcr1 & USBPCR1_REFCLKDIV_MASK;
|
||||
|
||||
switch (refclk_div) {
|
||||
case USBPCR1_REFCLKDIV_12:
|
||||
return 12000000;
|
||||
|
||||
case USBPCR1_REFCLKDIV_24:
|
||||
return 24000000;
|
||||
|
||||
case USBPCR1_REFCLKDIV_48:
|
||||
return 48000000;
|
||||
}
|
||||
|
||||
return parent_rate;
|
||||
}
|
||||
|
||||
static long x1000_otg_phy_round_rate(struct clk_hw *hw, unsigned long req_rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
if (req_rate < 18000000)
|
||||
return 12000000;
|
||||
|
||||
if (req_rate < 36000000)
|
||||
return 24000000;
|
||||
|
||||
return 48000000;
|
||||
}
|
||||
|
||||
static int x1000_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 usbpcr1, div_bits;
|
||||
|
||||
switch (req_rate) {
|
||||
case 12000000:
|
||||
div_bits = USBPCR1_REFCLKDIV_12;
|
||||
break;
|
||||
|
||||
case 24000000:
|
||||
div_bits = USBPCR1_REFCLKDIV_24;
|
||||
break;
|
||||
|
||||
case 48000000:
|
||||
div_bits = USBPCR1_REFCLKDIV_48;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&cgu->lock, flags);
|
||||
|
||||
usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
|
||||
usbpcr1 &= ~USBPCR1_REFCLKDIV_MASK;
|
||||
usbpcr1 |= div_bits;
|
||||
writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
|
||||
|
||||
spin_unlock_irqrestore(&cgu->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int x1000_usb_phy_enable(struct clk_hw *hw)
|
||||
{
|
||||
void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
|
||||
@ -80,6 +159,10 @@ static int x1000_usb_phy_is_enabled(struct clk_hw *hw)
|
||||
}
|
||||
|
||||
static const struct clk_ops x1000_otg_phy_ops = {
|
||||
.recalc_rate = x1000_otg_phy_recalc_rate,
|
||||
.round_rate = x1000_otg_phy_round_rate,
|
||||
.set_rate = x1000_otg_phy_set_rate,
|
||||
|
||||
.enable = x1000_usb_phy_enable,
|
||||
.disable = x1000_usb_phy_disable,
|
||||
.is_enabled = x1000_usb_phy_is_enabled,
|
||||
@ -144,7 +227,6 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
/* Custom (SoC-specific) OTG PHY */
|
||||
|
||||
[X1000_CLK_OTGPHY] = {
|
||||
|
Loading…
Reference in New Issue
Block a user