|
48 | 48 | #define USBPCR_SIDDQ BIT(21)
|
49 | 49 | #define USBPCR_OTG_DISABLE BIT(20)
|
50 | 50 |
|
| 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 | + |
51 | 61 | static struct ingenic_cgu *cgu;
|
52 | 62 |
|
| 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 | + |
53 | 132 | static int x1000_usb_phy_enable(struct clk_hw *hw)
|
54 | 133 | {
|
55 | 134 | void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
|
@@ -80,6 +159,10 @@ static int x1000_usb_phy_is_enabled(struct clk_hw *hw)
|
80 | 159 | }
|
81 | 160 |
|
82 | 161 | 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 | + |
83 | 166 | .enable = x1000_usb_phy_enable,
|
84 | 167 | .disable = x1000_usb_phy_disable,
|
85 | 168 | .is_enabled = x1000_usb_phy_is_enabled,
|
@@ -144,7 +227,6 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
|
144 | 227 | },
|
145 | 228 | },
|
146 | 229 |
|
147 |
| - |
148 | 230 | /* Custom (SoC-specific) OTG PHY */
|
149 | 231 |
|
150 | 232 | [X1000_CLK_OTGPHY] = {
|
|
0 commit comments