]> Git Repo - u-boot.git/blob - drivers/phy/meson-axg-mipi-pcie-analog.c
Restore patch series "arm: dts: am62-beagleplay: Fix Beagleplay Ethernet"
[u-boot.git] / drivers / phy / meson-axg-mipi-pcie-analog.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Amlogic AXG MIPI + PCIE analog PHY driver
4  *
5  * Copyright (C) 2019 Remi Pommarel <[email protected]>
6  * Copyright (C) 2020 BayLibre, SAS
7  * Author: Neil Armstrong <[email protected]>
8  */
9
10 #include <log.h>
11 #include <malloc.h>
12 #include <asm/io.h>
13 #include <bitfield.h>
14 #include <dm.h>
15 #include <errno.h>
16 #include <generic-phy.h>
17 #include <regmap.h>
18 #include <syscon.h>
19 #include <linux/delay.h>
20 #include <power/regulator.h>
21 #include <reset.h>
22 #include <clk.h>
23 #include <phy-mipi-dphy.h>
24
25 #include <linux/bitops.h>
26 #include <linux/compat.h>
27 #include <linux/bitfield.h>
28
29 #define HHI_MIPI_CNTL0 0x00
30 #define         HHI_MIPI_CNTL0_COMMON_BLOCK     GENMASK(31, 28)
31 #define         HHI_MIPI_CNTL0_ENABLE           BIT(29)
32 #define         HHI_MIPI_CNTL0_BANDGAP          BIT(26)
33 #define         HHI_MIPI_CNTL0_DIF_REF_CTL1     GENMASK(25, 16)
34 #define         HHI_MIPI_CNTL0_DIF_REF_CTL0     GENMASK(15, 0)
35
36 #define HHI_MIPI_CNTL1 0x04
37 #define         HHI_MIPI_CNTL1_CH0_CML_PDR_EN   BIT(12)
38 #define         HHI_MIPI_CNTL1_LP_ABILITY       GENMASK(5, 4)
39 #define         HHI_MIPI_CNTL1_LP_RESISTER      BIT(3)
40 #define         HHI_MIPI_CNTL1_INPUT_SETTING    BIT(2)
41 #define         HHI_MIPI_CNTL1_INPUT_SEL        BIT(1)
42 #define         HHI_MIPI_CNTL1_PRBS7_EN         BIT(0)
43
44 #define HHI_MIPI_CNTL2 0x08
45 #define         HHI_MIPI_CNTL2_CH_PU            GENMASK(31, 25)
46 #define         HHI_MIPI_CNTL2_CH_CTL           GENMASK(24, 19)
47 #define         HHI_MIPI_CNTL2_CH0_DIGDR_EN     BIT(18)
48 #define         HHI_MIPI_CNTL2_CH_DIGDR_EN      BIT(17)
49 #define         HHI_MIPI_CNTL2_LPULPS_EN        BIT(16)
50 #define         HHI_MIPI_CNTL2_CH_EN            GENMASK(15, 11)
51 #define         HHI_MIPI_CNTL2_CH0_LP_CTL       GENMASK(10, 1)
52
53 #define DSI_LANE_0              (1 << 4)
54 #define DSI_LANE_1              (1 << 3)
55 #define DSI_LANE_CLK            (1 << 2)
56 #define DSI_LANE_2              (1 << 1)
57 #define DSI_LANE_3              (1 << 0)
58 #define DSI_LANE_MASK           (0x1F)
59
60 struct phy_meson_axg_mipi_pcie_analog_priv {
61         struct regmap *regmap;
62         struct phy_configure_opts_mipi_dphy config;
63         bool dsi_configured;
64         bool dsi_enabled;
65         bool powered;
66 };
67
68 static void phy_bandgap_enable(struct phy_meson_axg_mipi_pcie_analog_priv *priv)
69 {
70         regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
71                         HHI_MIPI_CNTL0_BANDGAP, HHI_MIPI_CNTL0_BANDGAP);
72
73         regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
74                         HHI_MIPI_CNTL0_ENABLE, HHI_MIPI_CNTL0_ENABLE);
75 }
76
77 static void phy_bandgap_disable(struct phy_meson_axg_mipi_pcie_analog_priv *priv)
78 {
79         regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
80                         HHI_MIPI_CNTL0_BANDGAP, 0);
81         regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
82                         HHI_MIPI_CNTL0_ENABLE, 0);
83 }
84
85 static void phy_dsi_analog_enable(struct phy_meson_axg_mipi_pcie_analog_priv *priv)
86 {
87         u32 reg;
88
89         regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
90                            HHI_MIPI_CNTL0_DIF_REF_CTL1,
91                            FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL1, 0x1b8));
92         regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
93                            BIT(31), BIT(31));
94         regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
95                            HHI_MIPI_CNTL0_DIF_REF_CTL0,
96                            FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL0, 0x8));
97
98         regmap_write(priv->regmap, HHI_MIPI_CNTL1, 0x001e);
99
100         regmap_write(priv->regmap, HHI_MIPI_CNTL2,
101                      (0x26e0 << 16) | (0x459 << 0));
102
103         reg = DSI_LANE_CLK;
104         switch (priv->config.lanes) {
105         case 4:
106                 reg |= DSI_LANE_3;
107                 fallthrough;
108         case 3:
109                 reg |= DSI_LANE_2;
110                 fallthrough;
111         case 2:
112                 reg |= DSI_LANE_1;
113                 fallthrough;
114         case 1:
115                 reg |= DSI_LANE_0;
116                 break;
117         default:
118                 reg = 0;
119         }
120
121         regmap_update_bits(priv->regmap, HHI_MIPI_CNTL2,
122                            HHI_MIPI_CNTL2_CH_EN,
123                            FIELD_PREP(HHI_MIPI_CNTL2_CH_EN, reg));
124
125         priv->dsi_enabled = true;
126 }
127
128 static void phy_dsi_analog_disable(struct phy_meson_axg_mipi_pcie_analog_priv *priv)
129 {
130         regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
131                         HHI_MIPI_CNTL0_DIF_REF_CTL1,
132                         FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL1, 0));
133         regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, BIT(31), 0);
134         regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
135                         HHI_MIPI_CNTL0_DIF_REF_CTL1, 0);
136
137         regmap_write(priv->regmap, HHI_MIPI_CNTL1, 0x6);
138
139         regmap_write(priv->regmap, HHI_MIPI_CNTL2, 0x00200000);
140
141         priv->dsi_enabled = false;
142 }
143
144 static int phy_meson_axg_mipi_pcie_analog_configure(struct phy *phy, void *params)
145 {
146         struct udevice *dev = phy->dev;
147         struct phy_meson_axg_mipi_pcie_analog_priv *priv = dev_get_priv(dev);
148         struct phy_configure_opts_mipi_dphy *config = params;
149         int ret;
150
151         ret = phy_mipi_dphy_config_validate(config);
152         if (ret)
153                 return ret;
154
155         memcpy(&priv->config, config, sizeof(priv->config));
156
157         priv->dsi_configured = true;
158
159         /* If PHY was already powered on, setup the DSI analog part */
160         if (priv->powered) {
161                 /* If reconfiguring, disable & reconfigure */
162                 if (priv->dsi_enabled)
163                         phy_dsi_analog_disable(priv);
164
165                 udelay(100);
166
167                 phy_dsi_analog_enable(priv);
168         }
169
170         return 0;
171 }
172
173 static int phy_meson_axg_mipi_pcie_analog_power_on(struct phy *phy)
174 {
175         struct udevice *dev = phy->dev;
176         struct phy_meson_axg_mipi_pcie_analog_priv *priv = dev_get_priv(dev);
177
178         phy_bandgap_enable(priv);
179
180         if (priv->dsi_configured)
181                 phy_dsi_analog_enable(priv);
182
183         priv->powered = true;
184
185         return 0;
186 }
187
188 static int phy_meson_axg_mipi_pcie_analog_power_off(struct phy *phy)
189 {
190         struct udevice *dev = phy->dev;
191         struct phy_meson_axg_mipi_pcie_analog_priv *priv = dev_get_priv(dev);
192
193         phy_bandgap_disable(priv);
194
195         if (priv->dsi_enabled)
196                 phy_dsi_analog_disable(priv);
197
198         priv->powered = false;
199
200         return 0;
201 }
202
203 struct phy_ops meson_axg_mipi_pcie_analog_ops = {
204         .power_on = phy_meson_axg_mipi_pcie_analog_power_on,
205         .power_off = phy_meson_axg_mipi_pcie_analog_power_off,
206         .configure = phy_meson_axg_mipi_pcie_analog_configure,
207 };
208
209 int meson_axg_mipi_pcie_analog_probe(struct udevice *dev)
210 {
211         struct phy_meson_axg_mipi_pcie_analog_priv *priv = dev_get_priv(dev);
212
213         priv->regmap = syscon_node_to_regmap(dev_ofnode(dev_get_parent(dev)));
214         if (IS_ERR(priv->regmap))
215                 return PTR_ERR(priv->regmap);
216
217         return 0;
218 }
219
220 static const struct udevice_id meson_axg_mipi_pcie_analog_ids[] = {
221         { .compatible = "amlogic,axg-mipi-pcie-analog-phy" },
222         { }
223 };
224
225 U_BOOT_DRIVER(meson_axg_mipi_pcie_analog) = {
226         .name = "meson_axg_mipi_pcie_analog",
227         .id = UCLASS_PHY,
228         .of_match = meson_axg_mipi_pcie_analog_ids,
229         .probe = meson_axg_mipi_pcie_analog_probe,
230         .ops = &meson_axg_mipi_pcie_analog_ops,
231         .priv_auto = sizeof(struct phy_meson_axg_mipi_pcie_analog_priv),
232 };
This page took 0.037499 seconds and 4 git commands to generate.