mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-29 10:08:59 +00:00
230 lines
8.3 KiB
Diff
230 lines
8.3 KiB
Diff
|
From 474b608dee5e6285dd1981b00ab568a2f7f15fd0 Mon Sep 17 00:00:00 2001
|
||
|
From: Samuel Holland <samuel@sholland.org>
|
||
|
Date: Wed, 10 Aug 2022 23:02:06 -0500
|
||
|
Subject: [PATCH 106/117] 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.
|
||
|
|
||
|
Cover-letter:
|
||
|
phy: allwinner: phy-sun6i-mipi-dphy: Add the A100 DPHY
|
||
|
This series adds support for the updated DPHY found in a couple of
|
||
|
recent Allwinner SoCs. The first three patches fix an omission in the
|
||
|
existing binding. The remaining patches add the new hardware variant.
|
||
|
END
|
||
|
|
||
|
Series-to: Kishon Vijay Abraham I <kishon@ti.com>
|
||
|
Series-to: Vinod Koul <vkoul@kernel.org>
|
||
|
Series-to: Chen-Yu Tsai <wens@csie.org>
|
||
|
Series-to: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||
|
Series-to: Maxime Ripard <mripard@kernel.org>
|
||
|
Series-cc: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
|
||
|
|
||
|
Signed-off-by: Samuel Holland <samuel@sholland.org>
|
||
|
---
|
||
|
drivers/phy/allwinner/phy-sun6i-mipi-dphy.c | 143 +++++++++++++++++++-
|
||
|
1 file changed, 142 insertions(+), 1 deletion(-)
|
||
|
|
||
|
--- a/drivers/phy/allwinner/phy-sun6i-mipi-dphy.c
|
||
|
+++ b/drivers/phy/allwinner/phy-sun6i-mipi-dphy.c
|
||
|
@@ -70,11 +70,19 @@
|
||
|
|
||
|
#define SUN6I_DPHY_ANA0_REG 0x4c
|
||
|
#define SUN6I_DPHY_ANA0_REG_PWS BIT(31)
|
||
|
+#define SUN6I_DPHY_ANA0_REG_PWEND BIT(30)
|
||
|
+#define SUN6I_DPHY_ANA0_REG_PWENC BIT(29)
|
||
|
#define SUN6I_DPHY_ANA0_REG_DMPC BIT(28)
|
||
|
#define SUN6I_DPHY_ANA0_REG_DMPD(n) (((n) & 0xf) << 24)
|
||
|
+#define SUN6I_DPHY_ANA0_REG_SRXDT(n) (((n) & 0xf) << 20)
|
||
|
+#define SUN6I_DPHY_ANA0_REG_SRXCK(n) (((n) & 0xf) << 16)
|
||
|
+#define SUN6I_DPHY_ANA0_REG_SDIV2 BIT(15)
|
||
|
#define SUN6I_DPHY_ANA0_REG_SLV(n) (((n) & 7) << 12)
|
||
|
#define SUN6I_DPHY_ANA0_REG_DEN(n) (((n) & 0xf) << 8)
|
||
|
+#define SUN6I_DPHY_ANA0_REG_PLR(n) (((n) & 0xf) << 4)
|
||
|
#define SUN6I_DPHY_ANA0_REG_SFB(n) (((n) & 3) << 2)
|
||
|
+#define SUN6I_DPHY_ANA0_REG_RSD BIT(1)
|
||
|
+#define SUN6I_DPHY_ANA0_REG_SELSCK BIT(0)
|
||
|
|
||
|
#define SUN6I_DPHY_ANA1_REG 0x50
|
||
|
#define SUN6I_DPHY_ANA1_REG_VTTMODE BIT(31)
|
||
|
@@ -97,8 +105,13 @@
|
||
|
#define SUN6I_DPHY_ANA3_EN_LDOR BIT(18)
|
||
|
|
||
|
#define SUN6I_DPHY_ANA4_REG 0x5c
|
||
|
+#define SUN6I_DPHY_ANA4_REG_EN_MIPI BIT(31)
|
||
|
+#define SUN6I_DPHY_ANA4_REG_EN_COMTEST BIT(30)
|
||
|
+#define SUN6I_DPHY_ANA4_REG_COMTEST(n) (((n) & 3) << 28)
|
||
|
+#define SUN6I_DPHY_ANA4_REG_IB(n) (((n) & 3) << 25)
|
||
|
#define SUN6I_DPHY_ANA4_REG_DMPLVC BIT(24)
|
||
|
#define SUN6I_DPHY_ANA4_REG_DMPLVD(n) (((n) & 0xf) << 20)
|
||
|
+#define SUN6I_DPHY_ANA4_REG_VTT_SET(n) (((n) & 0x7) << 17)
|
||
|
#define SUN6I_DPHY_ANA4_REG_CKDV(n) (((n) & 0x1f) << 12)
|
||
|
#define SUN6I_DPHY_ANA4_REG_TMSC(n) (((n) & 3) << 10)
|
||
|
#define SUN6I_DPHY_ANA4_REG_TMSD(n) (((n) & 3) << 8)
|
||
|
@@ -109,6 +122,56 @@
|
||
|
|
||
|
#define SUN6I_DPHY_DBG5_REG 0xf4
|
||
|
|
||
|
+#define SUN50I_DPHY_TX_SLEW_REG0 0xf8
|
||
|
+#define SUN50I_DPHY_TX_SLEW_REG1 0xfc
|
||
|
+#define SUN50I_DPHY_TX_SLEW_REG2 0x100
|
||
|
+
|
||
|
+#define SUN50I_DPHY_PLL_REG0 0x104
|
||
|
+#define SUN50I_DPHY_PLL_REG0_CP36_EN BIT(23)
|
||
|
+#define SUN50I_DPHY_PLL_REG0_LDO_EN BIT(22)
|
||
|
+#define SUN50I_DPHY_PLL_REG0_EN_LVS BIT(21)
|
||
|
+#define SUN50I_DPHY_PLL_REG0_PLL_EN BIT(20)
|
||
|
+#define SUN50I_DPHY_PLL_REG0_P(n) (((n) & 0xf) << 16)
|
||
|
+#define SUN50I_DPHY_PLL_REG0_N(n) (((n) & 0xff) << 8)
|
||
|
+#define SUN50I_DPHY_PLL_REG0_NDET BIT(7)
|
||
|
+#define SUN50I_DPHY_PLL_REG0_TDIV BIT(6)
|
||
|
+#define SUN50I_DPHY_PLL_REG0_M0(n) (((n) & 3) << 4)
|
||
|
+#define SUN50I_DPHY_PLL_REG0_M1(n) ((n) & 0xf)
|
||
|
+
|
||
|
+#define SUN50I_DPHY_PLL_REG1 0x108
|
||
|
+#define SUN50I_DPHY_PLL_REG1_UNLOCK_MDSEL(n) (((n) & 3) << 14)
|
||
|
+#define SUN50I_DPHY_PLL_REG1_LOCKMDSEL BIT(13)
|
||
|
+#define SUN50I_DPHY_PLL_REG1_LOCKDET_EN BIT(12)
|
||
|
+#define SUN50I_DPHY_PLL_REG1_VSETA(n) (((n) & 0x7) << 9)
|
||
|
+#define SUN50I_DPHY_PLL_REG1_VSETD(n) (((n) & 0x7) << 6)
|
||
|
+#define SUN50I_DPHY_PLL_REG1_LPF_SW BIT(5)
|
||
|
+#define SUN50I_DPHY_PLL_REG1_ICP_SEL(n) (((n) & 3) << 3)
|
||
|
+#define SUN50I_DPHY_PLL_REG1_ATEST_SEL(n) (((n) & 3) << 1)
|
||
|
+#define SUN50I_DPHY_PLL_REG1_TEST_EN BIT(0)
|
||
|
+
|
||
|
+#define SUN50I_DPHY_PLL_REG2 0x10c
|
||
|
+#define SUN50I_DPHY_PLL_REG2_SDM_EN BIT(31)
|
||
|
+#define SUN50I_DPHY_PLL_REG2_FF_EN BIT(30)
|
||
|
+#define SUN50I_DPHY_PLL_REG2_SS_EN BIT(29)
|
||
|
+#define SUN50I_DPHY_PLL_REG2_SS_FRAC(n) (((n) & 0x1ff) << 20)
|
||
|
+#define SUN50I_DPHY_PLL_REG2_SS_INT(n) (((n) & 0xff) << 12)
|
||
|
+#define SUN50I_DPHY_PLL_REG2_FRAC(n) ((n) & 0xfff)
|
||
|
+
|
||
|
+#define SUN50I_COMBO_PHY_REG0 0x110
|
||
|
+#define SUN50I_COMBO_PHY_REG0_EN_TEST_COMBOLDO BIT(5)
|
||
|
+#define SUN50I_COMBO_PHY_REG0_EN_TEST_0P8 BIT(4)
|
||
|
+#define SUN50I_COMBO_PHY_REG0_EN_MIPI BIT(3)
|
||
|
+#define SUN50I_COMBO_PHY_REG0_EN_LVDS BIT(2)
|
||
|
+#define SUN50I_COMBO_PHY_REG0_EN_COMBOLDO BIT(1)
|
||
|
+#define SUN50I_COMBO_PHY_REG0_EN_CP BIT(0)
|
||
|
+
|
||
|
+#define SUN50I_COMBO_PHY_REG1 0x114
|
||
|
+#define SUN50I_COMBO_PHY_REG2_REG_VREF1P6(n) (((n) & 0x7) << 4)
|
||
|
+#define SUN50I_COMBO_PHY_REG2_REG_VREF0P8(n) ((n) & 0x7)
|
||
|
+
|
||
|
+#define SUN50I_COMBO_PHY_REG2 0x118
|
||
|
+#define SUN50I_COMBO_PHY_REG2_HS_STOP_DLY(n) ((n) & 0xff)
|
||
|
+
|
||
|
enum sun6i_dphy_direction {
|
||
|
SUN6I_DPHY_DIRECTION_TX,
|
||
|
SUN6I_DPHY_DIRECTION_RX,
|
||
|
@@ -196,6 +259,76 @@ static void sun6i_a31_mipi_dphy_tx_power
|
||
|
udelay(1);
|
||
|
}
|
||
|
|
||
|
+static void sun50i_a100_mipi_dphy_tx_power_on(struct sun6i_dphy *dphy)
|
||
|
+{
|
||
|
+ unsigned long mipi_symbol_rate = dphy->config.hs_clk_rate;
|
||
|
+ unsigned int div, n;
|
||
|
+
|
||
|
+ regmap_write(dphy->regs, SUN6I_DPHY_ANA4_REG,
|
||
|
+ SUN6I_DPHY_ANA4_REG_IB(2) |
|
||
|
+ SUN6I_DPHY_ANA4_REG_DMPLVD(4) |
|
||
|
+ SUN6I_DPHY_ANA4_REG_VTT_SET(3) |
|
||
|
+ SUN6I_DPHY_ANA4_REG_CKDV(3) |
|
||
|
+ SUN6I_DPHY_ANA4_REG_TMSD(1) |
|
||
|
+ SUN6I_DPHY_ANA4_REG_TMSC(1) |
|
||
|
+ SUN6I_DPHY_ANA4_REG_TXPUSD(2) |
|
||
|
+ SUN6I_DPHY_ANA4_REG_TXPUSC(3) |
|
||
|
+ SUN6I_DPHY_ANA4_REG_TXDNSD(2) |
|
||
|
+ SUN6I_DPHY_ANA4_REG_TXDNSC(3));
|
||
|
+
|
||
|
+ regmap_update_bits(dphy->regs, SUN6I_DPHY_ANA2_REG,
|
||
|
+ SUN6I_DPHY_ANA2_EN_CK_CPU,
|
||
|
+ SUN6I_DPHY_ANA2_EN_CK_CPU);
|
||
|
+
|
||
|
+ regmap_update_bits(dphy->regs, SUN6I_DPHY_ANA2_REG,
|
||
|
+ SUN6I_DPHY_ANA2_REG_ENIB,
|
||
|
+ SUN6I_DPHY_ANA2_REG_ENIB);
|
||
|
+
|
||
|
+ regmap_write(dphy->regs, SUN6I_DPHY_ANA3_REG,
|
||
|
+ SUN6I_DPHY_ANA3_EN_LDOR |
|
||
|
+ SUN6I_DPHY_ANA3_EN_LDOC |
|
||
|
+ SUN6I_DPHY_ANA3_EN_LDOD);
|
||
|
+
|
||
|
+ regmap_write(dphy->regs, SUN6I_DPHY_ANA0_REG,
|
||
|
+ SUN6I_DPHY_ANA0_REG_PLR(4) |
|
||
|
+ SUN6I_DPHY_ANA0_REG_SFB(1));
|
||
|
+
|
||
|
+ regmap_write(dphy->regs, SUN50I_COMBO_PHY_REG0,
|
||
|
+ SUN50I_COMBO_PHY_REG0_EN_CP);
|
||
|
+
|
||
|
+ /* Choose a divider to limit the VCO frequency to around 2 GHz. */
|
||
|
+ div = 16 >> order_base_2(DIV_ROUND_UP(mipi_symbol_rate, 264000000));
|
||
|
+ n = mipi_symbol_rate * div / 24000000;
|
||
|
+
|
||
|
+ regmap_write(dphy->regs, SUN50I_DPHY_PLL_REG0,
|
||
|
+ SUN50I_DPHY_PLL_REG0_CP36_EN |
|
||
|
+ SUN50I_DPHY_PLL_REG0_LDO_EN |
|
||
|
+ SUN50I_DPHY_PLL_REG0_EN_LVS |
|
||
|
+ SUN50I_DPHY_PLL_REG0_PLL_EN |
|
||
|
+ SUN50I_DPHY_PLL_REG0_NDET |
|
||
|
+ SUN50I_DPHY_PLL_REG0_P((div - 1) % 8) |
|
||
|
+ SUN50I_DPHY_PLL_REG0_N(n) |
|
||
|
+ SUN50I_DPHY_PLL_REG0_M0((div - 1) / 8) |
|
||
|
+ SUN50I_DPHY_PLL_REG0_M1(2));
|
||
|
+
|
||
|
+ /* Disable sigma-delta modulation. */
|
||
|
+ regmap_write(dphy->regs, SUN50I_DPHY_PLL_REG2, 0);
|
||
|
+
|
||
|
+ regmap_update_bits(dphy->regs, SUN6I_DPHY_ANA4_REG,
|
||
|
+ SUN6I_DPHY_ANA4_REG_EN_MIPI,
|
||
|
+ SUN6I_DPHY_ANA4_REG_EN_MIPI);
|
||
|
+
|
||
|
+ regmap_update_bits(dphy->regs, SUN50I_COMBO_PHY_REG0,
|
||
|
+ SUN50I_COMBO_PHY_REG0_EN_MIPI |
|
||
|
+ SUN50I_COMBO_PHY_REG0_EN_COMBOLDO,
|
||
|
+ SUN50I_COMBO_PHY_REG0_EN_MIPI |
|
||
|
+ SUN50I_COMBO_PHY_REG0_EN_COMBOLDO);
|
||
|
+
|
||
|
+ regmap_write(dphy->regs, SUN50I_COMBO_PHY_REG2,
|
||
|
+ SUN50I_COMBO_PHY_REG2_HS_STOP_DLY(20));
|
||
|
+ udelay(1);
|
||
|
+}
|
||
|
+
|
||
|
static int sun6i_dphy_tx_power_on(struct sun6i_dphy *dphy)
|
||
|
{
|
||
|
u8 lanes_mask = GENMASK(dphy->config.lanes - 1, 0);
|
||
|
@@ -408,7 +541,7 @@ static const struct regmap_config sun6i_
|
||
|
.reg_bits = 32,
|
||
|
.val_bits = 32,
|
||
|
.reg_stride = 4,
|
||
|
- .max_register = SUN6I_DPHY_DBG5_REG,
|
||
|
+ .max_register = SUN50I_COMBO_PHY_REG2,
|
||
|
.name = "mipi-dphy",
|
||
|
};
|
||
|
|
||
|
@@ -483,11 +616,19 @@ static const struct sun6i_dphy_variant s
|
||
|
.supports_rx = true,
|
||
|
};
|
||
|
|
||
|
+static const struct sun6i_dphy_variant sun50i_a100_mipi_dphy_variant = {
|
||
|
+ .tx_power_on = sun50i_a100_mipi_dphy_tx_power_on,
|
||
|
+};
|
||
|
+
|
||
|
static const struct of_device_id sun6i_dphy_of_table[] = {
|
||
|
{
|
||
|
.compatible = "allwinner,sun6i-a31-mipi-dphy",
|
||
|
.data = &sun6i_a31_mipi_dphy_variant,
|
||
|
},
|
||
|
+ {
|
||
|
+ .compatible = "allwinner,sun50i-a100-mipi-dphy",
|
||
|
+ .data = &sun50i_a100_mipi_dphy_variant,
|
||
|
+ },
|
||
|
{ }
|
||
|
};
|
||
|
MODULE_DEVICE_TABLE(of, sun6i_dphy_of_table);
|