Skip to content

Commit 4def478

Browse files
committed
Merge branch 'stmmac-dwmac-sun8i-Support-R40'
Chen-Yu Tsai says: ==================== net: stmmac: dwmac-sun8i: Support R40 This is a resend of the patches for net-next split out from my R40 Ethernet support v2 series, as requested by David Miller. The arm-soc bits will follow, once I rework the A64 system controller compatible. Patches 1, 2, and 3 clean up the dwmac-sun8i binding. Patch 4 adds device tree binding for Allwinner R40's Ethernet controller. Patch 5 converts regmap access of the syscon region in the dwmac-sun8i driver to regmap_field, in anticipation of different field widths on the R40. Patch 6 introduces custom plumbing in the dwmac-sun8i driver to fetch a regmap from another device, by looking up said device via a phandle, then getting the regmap associated with that device. Patch 7 adds support for different or absent TX/RX delay chain ranges to the dwmac-sun8i driver. Patch 8 adds support for the R40's ethernet controller. Excerpt from original cover letter: Changes since v1: - Default to fetching regmap from device pointed to by syscon phandle, and falling back to syscon API if that fails. - Dropped .syscon_from_dev field in device data as a result of the previous change. - Added a large comment block explaining the first change. - Simplified description of syscon property in sun8i-dwmac binding. - Regmap now only exposes the EMAC/GMAC register, but retains the offset within its address space. - Added patches for A64, which reuse the same sun8i-dwmac changes. This series adds support for the DWMAC based Ethernet controller found on the Allwinner R40 SoC. The controller is either a DWMAC clone or DWMAC core with its registers rearranged. This is already supported by the dwmac-sun8i driver. The glue layer control registers, unlike other sun8i family SoCs, is not in the system controller region, but in the clock control unit, like with the older A20 and A31 SoCs. While we reuse the bindings for dwmac-sun8i using a syscon phandle reference, we need some custom plumbing for the clock driver to export a regmap that only allows access to the GMAC register to the dwmac-sun8i driver. An alternative would be to allow drivers to register custom syscon devices with their own regmap and locking. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 62150df + 9bf5085 commit 4def478

File tree

2 files changed

+130
-30
lines changed

2 files changed

+130
-30
lines changed

Documentation/devicetree/bindings/net/dwmac-sun8i.txt

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Required properties:
77
- compatible: must be one of the following string:
88
"allwinner,sun8i-a83t-emac"
99
"allwinner,sun8i-h3-emac"
10+
"allwinner,sun8i-r40-gmac"
1011
"allwinner,sun8i-v3s-emac"
1112
"allwinner,sun50i-a64-emac"
1213
- reg: address and length of the register for the device.
@@ -20,18 +21,18 @@ Required properties:
2021
- phy-handle: See ethernet.txt
2122
- #address-cells: shall be 1
2223
- #size-cells: shall be 0
23-
- syscon: A phandle to the syscon of the SoC with one of the following
24-
compatible string:
25-
- allwinner,sun8i-h3-system-controller
26-
- allwinner,sun8i-v3s-system-controller
27-
- allwinner,sun50i-a64-system-controller
28-
- allwinner,sun8i-a83t-system-controller
24+
- syscon: A phandle to the device containing the EMAC or GMAC clock register
2925

3026
Optional properties:
31-
- allwinner,tx-delay-ps: TX clock delay chain value in ps. Range value is 0-700. Default is 0)
32-
- allwinner,rx-delay-ps: RX clock delay chain value in ps. Range value is 0-3100. Default is 0)
33-
Both delay properties need to be a multiple of 100. They control the delay for
34-
external PHY.
27+
- allwinner,tx-delay-ps: TX clock delay chain value in ps.
28+
Range is 0-700. Default is 0.
29+
Unavailable for allwinner,sun8i-r40-gmac
30+
- allwinner,rx-delay-ps: RX clock delay chain value in ps.
31+
Range is 0-3100. Default is 0.
32+
Range is 0-700 for allwinner,sun8i-r40-gmac
33+
Both delay properties need to be a multiple of 100. They control the
34+
clock delay for external RGMII PHY. They do not apply to the internal
35+
PHY or external non-RGMII PHYs.
3536

3637
Optional properties for the following compatibles:
3738
- "allwinner,sun8i-h3-emac",

drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c

Lines changed: 119 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,27 @@
4242
* This value is used for disabling properly EMAC
4343
* and used as a good starting value in case of the
4444
* boot process(uboot) leave some stuff.
45+
* @syscon_field reg_field for the syscon's gmac register
4546
* @soc_has_internal_phy: Does the MAC embed an internal PHY
4647
* @support_mii: Does the MAC handle MII
4748
* @support_rmii: Does the MAC handle RMII
4849
* @support_rgmii: Does the MAC handle RGMII
50+
*
51+
* @rx_delay_max: Maximum raw value for RX delay chain
52+
* @tx_delay_max: Maximum raw value for TX delay chain
53+
* These two also indicate the bitmask for
54+
* the RX and TX delay chain registers. A
55+
* value of zero indicates this is not supported.
4956
*/
5057
struct emac_variant {
5158
u32 default_syscon_value;
59+
const struct reg_field *syscon_field;
5260
bool soc_has_internal_phy;
5361
bool support_mii;
5462
bool support_rmii;
5563
bool support_rgmii;
64+
u8 rx_delay_max;
65+
u8 tx_delay_max;
5666
};
5767

5868
/* struct sunxi_priv_data - hold all sunxi private data
@@ -71,38 +81,70 @@ struct sunxi_priv_data {
7181
struct regulator *regulator;
7282
struct reset_control *rst_ephy;
7383
const struct emac_variant *variant;
74-
struct regmap *regmap;
84+
struct regmap_field *regmap_field;
7585
bool internal_phy_powered;
7686
void *mux_handle;
7787
};
7888

89+
/* EMAC clock register @ 0x30 in the "system control" address range */
90+
static const struct reg_field sun8i_syscon_reg_field = {
91+
.reg = 0x30,
92+
.lsb = 0,
93+
.msb = 31,
94+
};
95+
96+
/* EMAC clock register @ 0x164 in the CCU address range */
97+
static const struct reg_field sun8i_ccu_reg_field = {
98+
.reg = 0x164,
99+
.lsb = 0,
100+
.msb = 31,
101+
};
102+
79103
static const struct emac_variant emac_variant_h3 = {
80104
.default_syscon_value = 0x58000,
105+
.syscon_field = &sun8i_syscon_reg_field,
81106
.soc_has_internal_phy = true,
82107
.support_mii = true,
83108
.support_rmii = true,
84-
.support_rgmii = true
109+
.support_rgmii = true,
110+
.rx_delay_max = 31,
111+
.tx_delay_max = 7,
85112
};
86113

87114
static const struct emac_variant emac_variant_v3s = {
88115
.default_syscon_value = 0x38000,
116+
.syscon_field = &sun8i_syscon_reg_field,
89117
.soc_has_internal_phy = true,
90118
.support_mii = true
91119
};
92120

93121
static const struct emac_variant emac_variant_a83t = {
94122
.default_syscon_value = 0,
123+
.syscon_field = &sun8i_syscon_reg_field,
95124
.soc_has_internal_phy = false,
96125
.support_mii = true,
97-
.support_rgmii = true
126+
.support_rgmii = true,
127+
.rx_delay_max = 31,
128+
.tx_delay_max = 7,
129+
};
130+
131+
static const struct emac_variant emac_variant_r40 = {
132+
.default_syscon_value = 0,
133+
.syscon_field = &sun8i_ccu_reg_field,
134+
.support_mii = true,
135+
.support_rgmii = true,
136+
.rx_delay_max = 7,
98137
};
99138

100139
static const struct emac_variant emac_variant_a64 = {
101140
.default_syscon_value = 0,
141+
.syscon_field = &sun8i_syscon_reg_field,
102142
.soc_has_internal_phy = false,
103143
.support_mii = true,
104144
.support_rmii = true,
105-
.support_rgmii = true
145+
.support_rgmii = true,
146+
.rx_delay_max = 31,
147+
.tx_delay_max = 7,
106148
};
107149

108150
#define EMAC_BASIC_CTL0 0x00
@@ -206,17 +248,14 @@ static const struct emac_variant emac_variant_a64 = {
206248
#define SYSCON_RMII_EN BIT(13) /* 1: enable RMII (overrides EPIT) */
207249

208250
/* Generic system control EMAC_CLK bits */
209-
#define SYSCON_ETXDC_MASK GENMASK(2, 0)
210251
#define SYSCON_ETXDC_SHIFT 10
211-
#define SYSCON_ERXDC_MASK GENMASK(4, 0)
212252
#define SYSCON_ERXDC_SHIFT 5
213253
/* EMAC PHY Interface Type */
214254
#define SYSCON_EPIT BIT(2) /* 1: RGMII, 0: MII */
215255
#define SYSCON_ETCS_MASK GENMASK(1, 0)
216256
#define SYSCON_ETCS_MII 0x0
217257
#define SYSCON_ETCS_EXT_GMII 0x1
218258
#define SYSCON_ETCS_INT_GMII 0x2
219-
#define SYSCON_EMAC_REG 0x30
220259

221260
/* sun8i_dwmac_dma_reset() - reset the EMAC
222261
* Called from stmmac via stmmac_dma_ops->reset
@@ -745,7 +784,7 @@ static int mdio_mux_syscon_switch_fn(int current_child, int desired_child,
745784
bool need_power_ephy = false;
746785

747786
if (current_child ^ desired_child) {
748-
regmap_read(gmac->regmap, SYSCON_EMAC_REG, &reg);
787+
regmap_field_read(gmac->regmap_field, &reg);
749788
switch (desired_child) {
750789
case DWMAC_SUN8I_MDIO_MUX_INTERNAL_ID:
751790
dev_info(priv->device, "Switch mux to internal PHY");
@@ -763,7 +802,7 @@ static int mdio_mux_syscon_switch_fn(int current_child, int desired_child,
763802
desired_child);
764803
return -EINVAL;
765804
}
766-
regmap_write(gmac->regmap, SYSCON_EMAC_REG, val);
805+
regmap_field_write(gmac->regmap_field, val);
767806
if (need_power_ephy) {
768807
ret = sun8i_dwmac_power_internal_phy(priv);
769808
if (ret)
@@ -801,7 +840,7 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv)
801840
int ret;
802841
u32 reg, val;
803842

804-
regmap_read(gmac->regmap, SYSCON_EMAC_REG, &val);
843+
regmap_field_read(gmac->regmap_field, &val);
805844
reg = gmac->variant->default_syscon_value;
806845
if (reg != val)
807846
dev_warn(priv->device,
@@ -835,8 +874,9 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv)
835874
}
836875
val /= 100;
837876
dev_dbg(priv->device, "set tx-delay to %x\n", val);
838-
if (val <= SYSCON_ETXDC_MASK) {
839-
reg &= ~(SYSCON_ETXDC_MASK << SYSCON_ETXDC_SHIFT);
877+
if (val <= gmac->variant->tx_delay_max) {
878+
reg &= ~(gmac->variant->tx_delay_max <<
879+
SYSCON_ETXDC_SHIFT);
840880
reg |= (val << SYSCON_ETXDC_SHIFT);
841881
} else {
842882
dev_err(priv->device, "Invalid TX clock delay: %d\n",
@@ -852,8 +892,9 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv)
852892
}
853893
val /= 100;
854894
dev_dbg(priv->device, "set rx-delay to %x\n", val);
855-
if (val <= SYSCON_ERXDC_MASK) {
856-
reg &= ~(SYSCON_ERXDC_MASK << SYSCON_ERXDC_SHIFT);
895+
if (val <= gmac->variant->rx_delay_max) {
896+
reg &= ~(gmac->variant->rx_delay_max <<
897+
SYSCON_ERXDC_SHIFT);
857898
reg |= (val << SYSCON_ERXDC_SHIFT);
858899
} else {
859900
dev_err(priv->device, "Invalid RX clock delay: %d\n",
@@ -883,7 +924,7 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv)
883924
return -EINVAL;
884925
}
885926

886-
regmap_write(gmac->regmap, SYSCON_EMAC_REG, reg);
927+
regmap_field_write(gmac->regmap_field, reg);
887928

888929
return 0;
889930
}
@@ -892,7 +933,7 @@ static void sun8i_dwmac_unset_syscon(struct sunxi_priv_data *gmac)
892933
{
893934
u32 reg = gmac->variant->default_syscon_value;
894935

895-
regmap_write(gmac->regmap, SYSCON_EMAC_REG, reg);
936+
regmap_field_write(gmac->regmap_field, reg);
896937
}
897938

898939
static void sun8i_dwmac_exit(struct platform_device *pdev, void *priv)
@@ -971,6 +1012,34 @@ static struct mac_device_info *sun8i_dwmac_setup(void *ppriv)
9711012
return mac;
9721013
}
9731014

1015+
static struct regmap *sun8i_dwmac_get_syscon_from_dev(struct device_node *node)
1016+
{
1017+
struct device_node *syscon_node;
1018+
struct platform_device *syscon_pdev;
1019+
struct regmap *regmap = NULL;
1020+
1021+
syscon_node = of_parse_phandle(node, "syscon", 0);
1022+
if (!syscon_node)
1023+
return ERR_PTR(-ENODEV);
1024+
1025+
syscon_pdev = of_find_device_by_node(syscon_node);
1026+
if (!syscon_pdev) {
1027+
/* platform device might not be probed yet */
1028+
regmap = ERR_PTR(-EPROBE_DEFER);
1029+
goto out_put_node;
1030+
}
1031+
1032+
/* If no regmap is found then the other device driver is at fault */
1033+
regmap = dev_get_regmap(&syscon_pdev->dev, NULL);
1034+
if (!regmap)
1035+
regmap = ERR_PTR(-EINVAL);
1036+
1037+
platform_device_put(syscon_pdev);
1038+
out_put_node:
1039+
of_node_put(syscon_node);
1040+
return regmap;
1041+
}
1042+
9741043
static int sun8i_dwmac_probe(struct platform_device *pdev)
9751044
{
9761045
struct plat_stmmacenet_data *plat_dat;
@@ -980,6 +1049,7 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
9801049
int ret;
9811050
struct stmmac_priv *priv;
9821051
struct net_device *ndev;
1052+
struct regmap *regmap;
9831053

9841054
ret = stmmac_get_platform_resources(pdev, &stmmac_res);
9851055
if (ret)
@@ -1014,14 +1084,41 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
10141084
gmac->regulator = NULL;
10151085
}
10161086

1017-
gmac->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
1018-
"syscon");
1019-
if (IS_ERR(gmac->regmap)) {
1020-
ret = PTR_ERR(gmac->regmap);
1087+
/* The "GMAC clock control" register might be located in the
1088+
* CCU address range (on the R40), or the system control address
1089+
* range (on most other sun8i and later SoCs).
1090+
*
1091+
* The former controls most if not all clocks in the SoC. The
1092+
* latter has an SoC identification register, and on some SoCs,
1093+
* controls to map device specific SRAM to either the intended
1094+
* peripheral, or the CPU address space.
1095+
*
1096+
* In either case, there should be a coordinated and restricted
1097+
* method of accessing the register needed here. This is done by
1098+
* having the device export a custom regmap, instead of a generic
1099+
* syscon, which grants all access to all registers.
1100+
*
1101+
* To support old device trees, we fall back to using the syscon
1102+
* interface if possible.
1103+
*/
1104+
regmap = sun8i_dwmac_get_syscon_from_dev(pdev->dev.of_node);
1105+
if (IS_ERR(regmap))
1106+
regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
1107+
"syscon");
1108+
if (IS_ERR(regmap)) {
1109+
ret = PTR_ERR(regmap);
10211110
dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
10221111
return ret;
10231112
}
10241113

1114+
gmac->regmap_field = devm_regmap_field_alloc(dev, regmap,
1115+
*gmac->variant->syscon_field);
1116+
if (IS_ERR(gmac->regmap_field)) {
1117+
ret = PTR_ERR(gmac->regmap_field);
1118+
dev_err(dev, "Unable to map syscon register: %d\n", ret);
1119+
return ret;
1120+
}
1121+
10251122
plat_dat->interface = of_get_phy_mode(dev->of_node);
10261123

10271124
/* platform data specifying hardware features and callbacks.
@@ -1078,6 +1175,8 @@ static const struct of_device_id sun8i_dwmac_match[] = {
10781175
.data = &emac_variant_v3s },
10791176
{ .compatible = "allwinner,sun8i-a83t-emac",
10801177
.data = &emac_variant_a83t },
1178+
{ .compatible = "allwinner,sun8i-r40-gmac",
1179+
.data = &emac_variant_r40 },
10811180
{ .compatible = "allwinner,sun50i-a64-emac",
10821181
.data = &emac_variant_a64 },
10831182
{ }

0 commit comments

Comments
 (0)