1 // SPDX-License-Identifier: GPL-2.0
3 * Amlogic AXG MIPI + PCIE analog PHY driver
5 * Copyright (C) 2019 Remi Pommarel <repk@triplefau.lt>
7 #include <linux/module.h>
8 #include <linux/phy/phy.h>
9 #include <linux/regmap.h>
10 #include <linux/platform_device.h>
11 #include <dt-bindings/phy/phy.h>
13 #define HHI_MIPI_CNTL0 0x00
14 #define HHI_MIPI_CNTL0_COMMON_BLOCK GENMASK(31, 28)
15 #define HHI_MIPI_CNTL0_ENABLE BIT(29)
16 #define HHI_MIPI_CNTL0_BANDGAP BIT(26)
17 #define HHI_MIPI_CNTL0_DECODE_TO_RTERM GENMASK(15, 12)
18 #define HHI_MIPI_CNTL0_OUTPUT_EN BIT(3)
20 #define HHI_MIPI_CNTL1 0x01
21 #define HHI_MIPI_CNTL1_CH0_CML_PDR_EN BIT(12)
22 #define HHI_MIPI_CNTL1_LP_ABILITY GENMASK(5, 4)
23 #define HHI_MIPI_CNTL1_LP_RESISTER BIT(3)
24 #define HHI_MIPI_CNTL1_INPUT_SETTING BIT(2)
25 #define HHI_MIPI_CNTL1_INPUT_SEL BIT(1)
26 #define HHI_MIPI_CNTL1_PRBS7_EN BIT(0)
28 #define HHI_MIPI_CNTL2 0x02
29 #define HHI_MIPI_CNTL2_CH_PU GENMASK(31, 25)
30 #define HHI_MIPI_CNTL2_CH_CTL GENMASK(24, 19)
31 #define HHI_MIPI_CNTL2_CH0_DIGDR_EN BIT(18)
32 #define HHI_MIPI_CNTL2_CH_DIGDR_EN BIT(17)
33 #define HHI_MIPI_CNTL2_LPULPS_EN BIT(16)
34 #define HHI_MIPI_CNTL2_CH_EN(n) BIT(15 - (n))
35 #define HHI_MIPI_CNTL2_CH0_LP_CTL GENMASK(10, 1)
37 struct phy_axg_mipi_pcie_analog_priv
{
40 struct regmap
*regmap
;
43 static const struct regmap_config phy_axg_mipi_pcie_analog_regmap_conf
= {
47 .max_register
= HHI_MIPI_CNTL2
,
50 static int phy_axg_mipi_pcie_analog_power_on(struct phy
*phy
)
52 struct phy_axg_mipi_pcie_analog_priv
*priv
= phy_get_drvdata(phy
);
54 /* MIPI not supported yet */
55 if (priv
->mode
!= PHY_TYPE_PCIE
)
58 regmap_update_bits(priv
->regmap
, HHI_MIPI_CNTL0
,
59 HHI_MIPI_CNTL0_BANDGAP
, HHI_MIPI_CNTL0_BANDGAP
);
61 regmap_update_bits(priv
->regmap
, HHI_MIPI_CNTL0
,
62 HHI_MIPI_CNTL0_ENABLE
, HHI_MIPI_CNTL0_ENABLE
);
66 static int phy_axg_mipi_pcie_analog_power_off(struct phy
*phy
)
68 struct phy_axg_mipi_pcie_analog_priv
*priv
= phy_get_drvdata(phy
);
70 /* MIPI not supported yet */
71 if (priv
->mode
!= PHY_TYPE_PCIE
)
74 regmap_update_bits(priv
->regmap
, HHI_MIPI_CNTL0
,
75 HHI_MIPI_CNTL0_BANDGAP
, 0);
76 regmap_update_bits(priv
->regmap
, HHI_MIPI_CNTL0
,
77 HHI_MIPI_CNTL0_ENABLE
, 0);
81 static int phy_axg_mipi_pcie_analog_init(struct phy
*phy
)
86 static int phy_axg_mipi_pcie_analog_exit(struct phy
*phy
)
91 static const struct phy_ops phy_axg_mipi_pcie_analog_ops
= {
92 .init
= phy_axg_mipi_pcie_analog_init
,
93 .exit
= phy_axg_mipi_pcie_analog_exit
,
94 .power_on
= phy_axg_mipi_pcie_analog_power_on
,
95 .power_off
= phy_axg_mipi_pcie_analog_power_off
,
99 static struct phy
*phy_axg_mipi_pcie_analog_xlate(struct device
*dev
,
100 struct of_phandle_args
*args
)
102 struct phy_axg_mipi_pcie_analog_priv
*priv
= dev_get_drvdata(dev
);
105 if (args
->args_count
!= 1) {
106 dev_err(dev
, "invalid number of arguments\n");
107 return ERR_PTR(-EINVAL
);
110 mode
= args
->args
[0];
112 /* MIPI mode is not supported yet */
113 if (mode
!= PHY_TYPE_PCIE
) {
114 dev_err(dev
, "invalid phy mode select argument\n");
115 return ERR_PTR(-EINVAL
);
122 static int phy_axg_mipi_pcie_analog_probe(struct platform_device
*pdev
)
124 struct phy_provider
*phy
;
125 struct device
*dev
= &pdev
->dev
;
126 struct phy_axg_mipi_pcie_analog_priv
*priv
;
127 struct device_node
*np
= dev
->of_node
;
129 struct resource
*res
;
133 priv
= devm_kmalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
137 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
138 base
= devm_ioremap_resource(dev
, res
);
140 dev_err(dev
, "failed to get regmap base\n");
141 return PTR_ERR(base
);
144 map
= devm_regmap_init_mmio(dev
, base
,
145 &phy_axg_mipi_pcie_analog_regmap_conf
);
147 dev_err(dev
, "failed to get HHI regmap\n");
152 priv
->phy
= devm_phy_create(dev
, np
, &phy_axg_mipi_pcie_analog_ops
);
153 if (IS_ERR(priv
->phy
)) {
154 ret
= PTR_ERR(priv
->phy
);
155 if (ret
!= -EPROBE_DEFER
)
156 dev_err(dev
, "failed to create PHY\n");
160 phy_set_drvdata(priv
->phy
, priv
);
161 dev_set_drvdata(dev
, priv
);
163 phy
= devm_of_phy_provider_register(dev
,
164 phy_axg_mipi_pcie_analog_xlate
);
166 return PTR_ERR_OR_ZERO(phy
);
169 static const struct of_device_id phy_axg_mipi_pcie_analog_of_match
[] = {
171 .compatible
= "amlogic,axg-mipi-pcie-analog-phy",
175 MODULE_DEVICE_TABLE(of
, phy_axg_mipi_pcie_analog_of_match
);
177 static struct platform_driver phy_axg_mipi_pcie_analog_driver
= {
178 .probe
= phy_axg_mipi_pcie_analog_probe
,
180 .name
= "phy-axg-mipi-pcie-analog",
181 .of_match_table
= phy_axg_mipi_pcie_analog_of_match
,
184 module_platform_driver(phy_axg_mipi_pcie_analog_driver
);
186 MODULE_AUTHOR("Remi Pommarel <repk@triplefau.lt>");
187 MODULE_DESCRIPTION("Amlogic AXG MIPI + PCIE analog PHY driver");
188 MODULE_LICENSE("GPL v2");