Skip to content

Commit 4d0c216

Browse files
smaeulvinodkoul
authored andcommitted
phy: allwinner: phy-sun6i-mipi-dphy: Add the A100 DPHY variant
A100 features an updated DPHY, which moves PLL control inside the DPHY register space (previously the PLL was controlled from the CCU). It also requires a modified analog power-on sequence. This "combo PHY" can also be used as an LVDS PHY, but that is not yet supported by the driver. Signed-off-by: Samuel Holland <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]>
1 parent 3fd490a commit 4d0c216

File tree

1 file changed

+142
-1
lines changed

1 file changed

+142
-1
lines changed

drivers/phy/allwinner/phy-sun6i-mipi-dphy.c

Lines changed: 142 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,19 @@
7070

7171
#define SUN6I_DPHY_ANA0_REG 0x4c
7272
#define SUN6I_DPHY_ANA0_REG_PWS BIT(31)
73+
#define SUN6I_DPHY_ANA0_REG_PWEND BIT(30)
74+
#define SUN6I_DPHY_ANA0_REG_PWENC BIT(29)
7375
#define SUN6I_DPHY_ANA0_REG_DMPC BIT(28)
7476
#define SUN6I_DPHY_ANA0_REG_DMPD(n) (((n) & 0xf) << 24)
77+
#define SUN6I_DPHY_ANA0_REG_SRXDT(n) (((n) & 0xf) << 20)
78+
#define SUN6I_DPHY_ANA0_REG_SRXCK(n) (((n) & 0xf) << 16)
79+
#define SUN6I_DPHY_ANA0_REG_SDIV2 BIT(15)
7580
#define SUN6I_DPHY_ANA0_REG_SLV(n) (((n) & 7) << 12)
7681
#define SUN6I_DPHY_ANA0_REG_DEN(n) (((n) & 0xf) << 8)
82+
#define SUN6I_DPHY_ANA0_REG_PLR(n) (((n) & 0xf) << 4)
7783
#define SUN6I_DPHY_ANA0_REG_SFB(n) (((n) & 3) << 2)
84+
#define SUN6I_DPHY_ANA0_REG_RSD BIT(1)
85+
#define SUN6I_DPHY_ANA0_REG_SELSCK BIT(0)
7886

7987
#define SUN6I_DPHY_ANA1_REG 0x50
8088
#define SUN6I_DPHY_ANA1_REG_VTTMODE BIT(31)
@@ -97,8 +105,13 @@
97105
#define SUN6I_DPHY_ANA3_EN_LDOR BIT(18)
98106

99107
#define SUN6I_DPHY_ANA4_REG 0x5c
108+
#define SUN6I_DPHY_ANA4_REG_EN_MIPI BIT(31)
109+
#define SUN6I_DPHY_ANA4_REG_EN_COMTEST BIT(30)
110+
#define SUN6I_DPHY_ANA4_REG_COMTEST(n) (((n) & 3) << 28)
111+
#define SUN6I_DPHY_ANA4_REG_IB(n) (((n) & 3) << 25)
100112
#define SUN6I_DPHY_ANA4_REG_DMPLVC BIT(24)
101113
#define SUN6I_DPHY_ANA4_REG_DMPLVD(n) (((n) & 0xf) << 20)
114+
#define SUN6I_DPHY_ANA4_REG_VTT_SET(n) (((n) & 0x7) << 17)
102115
#define SUN6I_DPHY_ANA4_REG_CKDV(n) (((n) & 0x1f) << 12)
103116
#define SUN6I_DPHY_ANA4_REG_TMSC(n) (((n) & 3) << 10)
104117
#define SUN6I_DPHY_ANA4_REG_TMSD(n) (((n) & 3) << 8)
@@ -109,6 +122,56 @@
109122

110123
#define SUN6I_DPHY_DBG5_REG 0xf4
111124

125+
#define SUN50I_DPHY_TX_SLEW_REG0 0xf8
126+
#define SUN50I_DPHY_TX_SLEW_REG1 0xfc
127+
#define SUN50I_DPHY_TX_SLEW_REG2 0x100
128+
129+
#define SUN50I_DPHY_PLL_REG0 0x104
130+
#define SUN50I_DPHY_PLL_REG0_CP36_EN BIT(23)
131+
#define SUN50I_DPHY_PLL_REG0_LDO_EN BIT(22)
132+
#define SUN50I_DPHY_PLL_REG0_EN_LVS BIT(21)
133+
#define SUN50I_DPHY_PLL_REG0_PLL_EN BIT(20)
134+
#define SUN50I_DPHY_PLL_REG0_P(n) (((n) & 0xf) << 16)
135+
#define SUN50I_DPHY_PLL_REG0_N(n) (((n) & 0xff) << 8)
136+
#define SUN50I_DPHY_PLL_REG0_NDET BIT(7)
137+
#define SUN50I_DPHY_PLL_REG0_TDIV BIT(6)
138+
#define SUN50I_DPHY_PLL_REG0_M0(n) (((n) & 3) << 4)
139+
#define SUN50I_DPHY_PLL_REG0_M1(n) ((n) & 0xf)
140+
141+
#define SUN50I_DPHY_PLL_REG1 0x108
142+
#define SUN50I_DPHY_PLL_REG1_UNLOCK_MDSEL(n) (((n) & 3) << 14)
143+
#define SUN50I_DPHY_PLL_REG1_LOCKMDSEL BIT(13)
144+
#define SUN50I_DPHY_PLL_REG1_LOCKDET_EN BIT(12)
145+
#define SUN50I_DPHY_PLL_REG1_VSETA(n) (((n) & 0x7) << 9)
146+
#define SUN50I_DPHY_PLL_REG1_VSETD(n) (((n) & 0x7) << 6)
147+
#define SUN50I_DPHY_PLL_REG1_LPF_SW BIT(5)
148+
#define SUN50I_DPHY_PLL_REG1_ICP_SEL(n) (((n) & 3) << 3)
149+
#define SUN50I_DPHY_PLL_REG1_ATEST_SEL(n) (((n) & 3) << 1)
150+
#define SUN50I_DPHY_PLL_REG1_TEST_EN BIT(0)
151+
152+
#define SUN50I_DPHY_PLL_REG2 0x10c
153+
#define SUN50I_DPHY_PLL_REG2_SDM_EN BIT(31)
154+
#define SUN50I_DPHY_PLL_REG2_FF_EN BIT(30)
155+
#define SUN50I_DPHY_PLL_REG2_SS_EN BIT(29)
156+
#define SUN50I_DPHY_PLL_REG2_SS_FRAC(n) (((n) & 0x1ff) << 20)
157+
#define SUN50I_DPHY_PLL_REG2_SS_INT(n) (((n) & 0xff) << 12)
158+
#define SUN50I_DPHY_PLL_REG2_FRAC(n) ((n) & 0xfff)
159+
160+
#define SUN50I_COMBO_PHY_REG0 0x110
161+
#define SUN50I_COMBO_PHY_REG0_EN_TEST_COMBOLDO BIT(5)
162+
#define SUN50I_COMBO_PHY_REG0_EN_TEST_0P8 BIT(4)
163+
#define SUN50I_COMBO_PHY_REG0_EN_MIPI BIT(3)
164+
#define SUN50I_COMBO_PHY_REG0_EN_LVDS BIT(2)
165+
#define SUN50I_COMBO_PHY_REG0_EN_COMBOLDO BIT(1)
166+
#define SUN50I_COMBO_PHY_REG0_EN_CP BIT(0)
167+
168+
#define SUN50I_COMBO_PHY_REG1 0x114
169+
#define SUN50I_COMBO_PHY_REG2_REG_VREF1P6(n) (((n) & 0x7) << 4)
170+
#define SUN50I_COMBO_PHY_REG2_REG_VREF0P8(n) ((n) & 0x7)
171+
172+
#define SUN50I_COMBO_PHY_REG2 0x118
173+
#define SUN50I_COMBO_PHY_REG2_HS_STOP_DLY(n) ((n) & 0xff)
174+
112175
enum sun6i_dphy_direction {
113176
SUN6I_DPHY_DIRECTION_TX,
114177
SUN6I_DPHY_DIRECTION_RX,
@@ -196,6 +259,76 @@ static void sun6i_a31_mipi_dphy_tx_power_on(struct sun6i_dphy *dphy)
196259
udelay(1);
197260
}
198261

262+
static void sun50i_a100_mipi_dphy_tx_power_on(struct sun6i_dphy *dphy)
263+
{
264+
unsigned long mipi_symbol_rate = dphy->config.hs_clk_rate;
265+
unsigned int div, n;
266+
267+
regmap_write(dphy->regs, SUN6I_DPHY_ANA4_REG,
268+
SUN6I_DPHY_ANA4_REG_IB(2) |
269+
SUN6I_DPHY_ANA4_REG_DMPLVD(4) |
270+
SUN6I_DPHY_ANA4_REG_VTT_SET(3) |
271+
SUN6I_DPHY_ANA4_REG_CKDV(3) |
272+
SUN6I_DPHY_ANA4_REG_TMSD(1) |
273+
SUN6I_DPHY_ANA4_REG_TMSC(1) |
274+
SUN6I_DPHY_ANA4_REG_TXPUSD(2) |
275+
SUN6I_DPHY_ANA4_REG_TXPUSC(3) |
276+
SUN6I_DPHY_ANA4_REG_TXDNSD(2) |
277+
SUN6I_DPHY_ANA4_REG_TXDNSC(3));
278+
279+
regmap_update_bits(dphy->regs, SUN6I_DPHY_ANA2_REG,
280+
SUN6I_DPHY_ANA2_EN_CK_CPU,
281+
SUN6I_DPHY_ANA2_EN_CK_CPU);
282+
283+
regmap_update_bits(dphy->regs, SUN6I_DPHY_ANA2_REG,
284+
SUN6I_DPHY_ANA2_REG_ENIB,
285+
SUN6I_DPHY_ANA2_REG_ENIB);
286+
287+
regmap_write(dphy->regs, SUN6I_DPHY_ANA3_REG,
288+
SUN6I_DPHY_ANA3_EN_LDOR |
289+
SUN6I_DPHY_ANA3_EN_LDOC |
290+
SUN6I_DPHY_ANA3_EN_LDOD);
291+
292+
regmap_write(dphy->regs, SUN6I_DPHY_ANA0_REG,
293+
SUN6I_DPHY_ANA0_REG_PLR(4) |
294+
SUN6I_DPHY_ANA0_REG_SFB(1));
295+
296+
regmap_write(dphy->regs, SUN50I_COMBO_PHY_REG0,
297+
SUN50I_COMBO_PHY_REG0_EN_CP);
298+
299+
/* Choose a divider to limit the VCO frequency to around 2 GHz. */
300+
div = 16 >> order_base_2(DIV_ROUND_UP(mipi_symbol_rate, 264000000));
301+
n = mipi_symbol_rate * div / 24000000;
302+
303+
regmap_write(dphy->regs, SUN50I_DPHY_PLL_REG0,
304+
SUN50I_DPHY_PLL_REG0_CP36_EN |
305+
SUN50I_DPHY_PLL_REG0_LDO_EN |
306+
SUN50I_DPHY_PLL_REG0_EN_LVS |
307+
SUN50I_DPHY_PLL_REG0_PLL_EN |
308+
SUN50I_DPHY_PLL_REG0_NDET |
309+
SUN50I_DPHY_PLL_REG0_P((div - 1) % 8) |
310+
SUN50I_DPHY_PLL_REG0_N(n) |
311+
SUN50I_DPHY_PLL_REG0_M0((div - 1) / 8) |
312+
SUN50I_DPHY_PLL_REG0_M1(2));
313+
314+
/* Disable sigma-delta modulation. */
315+
regmap_write(dphy->regs, SUN50I_DPHY_PLL_REG2, 0);
316+
317+
regmap_update_bits(dphy->regs, SUN6I_DPHY_ANA4_REG,
318+
SUN6I_DPHY_ANA4_REG_EN_MIPI,
319+
SUN6I_DPHY_ANA4_REG_EN_MIPI);
320+
321+
regmap_update_bits(dphy->regs, SUN50I_COMBO_PHY_REG0,
322+
SUN50I_COMBO_PHY_REG0_EN_MIPI |
323+
SUN50I_COMBO_PHY_REG0_EN_COMBOLDO,
324+
SUN50I_COMBO_PHY_REG0_EN_MIPI |
325+
SUN50I_COMBO_PHY_REG0_EN_COMBOLDO);
326+
327+
regmap_write(dphy->regs, SUN50I_COMBO_PHY_REG2,
328+
SUN50I_COMBO_PHY_REG2_HS_STOP_DLY(20));
329+
udelay(1);
330+
}
331+
199332
static int sun6i_dphy_tx_power_on(struct sun6i_dphy *dphy)
200333
{
201334
u8 lanes_mask = GENMASK(dphy->config.lanes - 1, 0);
@@ -408,7 +541,7 @@ static const struct regmap_config sun6i_dphy_regmap_config = {
408541
.reg_bits = 32,
409542
.val_bits = 32,
410543
.reg_stride = 4,
411-
.max_register = SUN6I_DPHY_DBG5_REG,
544+
.max_register = SUN50I_COMBO_PHY_REG2,
412545
.name = "mipi-dphy",
413546
};
414547

@@ -484,11 +617,19 @@ static const struct sun6i_dphy_variant sun6i_a31_mipi_dphy_variant = {
484617
.rx_supported = true,
485618
};
486619

620+
static const struct sun6i_dphy_variant sun50i_a100_mipi_dphy_variant = {
621+
.tx_power_on = sun50i_a100_mipi_dphy_tx_power_on,
622+
};
623+
487624
static const struct of_device_id sun6i_dphy_of_table[] = {
488625
{
489626
.compatible = "allwinner,sun6i-a31-mipi-dphy",
490627
.data = &sun6i_a31_mipi_dphy_variant,
491628
},
629+
{
630+
.compatible = "allwinner,sun50i-a100-mipi-dphy",
631+
.data = &sun50i_a100_mipi_dphy_variant,
632+
},
492633
{ }
493634
};
494635
MODULE_DEVICE_TABLE(of, sun6i_dphy_of_table);

0 commit comments

Comments
 (0)