42
42
* This value is used for disabling properly EMAC
43
43
* and used as a good starting value in case of the
44
44
* boot process(uboot) leave some stuff.
45
+ * @syscon_field reg_field for the syscon's gmac register
45
46
* @soc_has_internal_phy: Does the MAC embed an internal PHY
46
47
* @support_mii: Does the MAC handle MII
47
48
* @support_rmii: Does the MAC handle RMII
48
49
* @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.
49
56
*/
50
57
struct emac_variant {
51
58
u32 default_syscon_value ;
59
+ const struct reg_field * syscon_field ;
52
60
bool soc_has_internal_phy ;
53
61
bool support_mii ;
54
62
bool support_rmii ;
55
63
bool support_rgmii ;
64
+ u8 rx_delay_max ;
65
+ u8 tx_delay_max ;
56
66
};
57
67
58
68
/* struct sunxi_priv_data - hold all sunxi private data
@@ -71,38 +81,70 @@ struct sunxi_priv_data {
71
81
struct regulator * regulator ;
72
82
struct reset_control * rst_ephy ;
73
83
const struct emac_variant * variant ;
74
- struct regmap * regmap ;
84
+ struct regmap_field * regmap_field ;
75
85
bool internal_phy_powered ;
76
86
void * mux_handle ;
77
87
};
78
88
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
+
79
103
static const struct emac_variant emac_variant_h3 = {
80
104
.default_syscon_value = 0x58000 ,
105
+ .syscon_field = & sun8i_syscon_reg_field ,
81
106
.soc_has_internal_phy = true,
82
107
.support_mii = true,
83
108
.support_rmii = true,
84
- .support_rgmii = true
109
+ .support_rgmii = true,
110
+ .rx_delay_max = 31 ,
111
+ .tx_delay_max = 7 ,
85
112
};
86
113
87
114
static const struct emac_variant emac_variant_v3s = {
88
115
.default_syscon_value = 0x38000 ,
116
+ .syscon_field = & sun8i_syscon_reg_field ,
89
117
.soc_has_internal_phy = true,
90
118
.support_mii = true
91
119
};
92
120
93
121
static const struct emac_variant emac_variant_a83t = {
94
122
.default_syscon_value = 0 ,
123
+ .syscon_field = & sun8i_syscon_reg_field ,
95
124
.soc_has_internal_phy = false,
96
125
.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 ,
98
137
};
99
138
100
139
static const struct emac_variant emac_variant_a64 = {
101
140
.default_syscon_value = 0 ,
141
+ .syscon_field = & sun8i_syscon_reg_field ,
102
142
.soc_has_internal_phy = false,
103
143
.support_mii = true,
104
144
.support_rmii = true,
105
- .support_rgmii = true
145
+ .support_rgmii = true,
146
+ .rx_delay_max = 31 ,
147
+ .tx_delay_max = 7 ,
106
148
};
107
149
108
150
#define EMAC_BASIC_CTL0 0x00
@@ -206,17 +248,14 @@ static const struct emac_variant emac_variant_a64 = {
206
248
#define SYSCON_RMII_EN BIT(13) /* 1: enable RMII (overrides EPIT) */
207
249
208
250
/* Generic system control EMAC_CLK bits */
209
- #define SYSCON_ETXDC_MASK GENMASK(2, 0)
210
251
#define SYSCON_ETXDC_SHIFT 10
211
- #define SYSCON_ERXDC_MASK GENMASK(4, 0)
212
252
#define SYSCON_ERXDC_SHIFT 5
213
253
/* EMAC PHY Interface Type */
214
254
#define SYSCON_EPIT BIT(2) /* 1: RGMII, 0: MII */
215
255
#define SYSCON_ETCS_MASK GENMASK(1, 0)
216
256
#define SYSCON_ETCS_MII 0x0
217
257
#define SYSCON_ETCS_EXT_GMII 0x1
218
258
#define SYSCON_ETCS_INT_GMII 0x2
219
- #define SYSCON_EMAC_REG 0x30
220
259
221
260
/* sun8i_dwmac_dma_reset() - reset the EMAC
222
261
* 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,
745
784
bool need_power_ephy = false;
746
785
747
786
if (current_child ^ desired_child ) {
748
- regmap_read (gmac -> regmap , SYSCON_EMAC_REG , & reg );
787
+ regmap_field_read (gmac -> regmap_field , & reg );
749
788
switch (desired_child ) {
750
789
case DWMAC_SUN8I_MDIO_MUX_INTERNAL_ID :
751
790
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,
763
802
desired_child );
764
803
return - EINVAL ;
765
804
}
766
- regmap_write (gmac -> regmap , SYSCON_EMAC_REG , val );
805
+ regmap_field_write (gmac -> regmap_field , val );
767
806
if (need_power_ephy ) {
768
807
ret = sun8i_dwmac_power_internal_phy (priv );
769
808
if (ret )
@@ -801,7 +840,7 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv)
801
840
int ret ;
802
841
u32 reg , val ;
803
842
804
- regmap_read (gmac -> regmap , SYSCON_EMAC_REG , & val );
843
+ regmap_field_read (gmac -> regmap_field , & val );
805
844
reg = gmac -> variant -> default_syscon_value ;
806
845
if (reg != val )
807
846
dev_warn (priv -> device ,
@@ -835,8 +874,9 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv)
835
874
}
836
875
val /= 100 ;
837
876
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 );
840
880
reg |= (val << SYSCON_ETXDC_SHIFT );
841
881
} else {
842
882
dev_err (priv -> device , "Invalid TX clock delay: %d\n" ,
@@ -852,8 +892,9 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv)
852
892
}
853
893
val /= 100 ;
854
894
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 );
857
898
reg |= (val << SYSCON_ERXDC_SHIFT );
858
899
} else {
859
900
dev_err (priv -> device , "Invalid RX clock delay: %d\n" ,
@@ -883,7 +924,7 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv)
883
924
return - EINVAL ;
884
925
}
885
926
886
- regmap_write (gmac -> regmap , SYSCON_EMAC_REG , reg );
927
+ regmap_field_write (gmac -> regmap_field , reg );
887
928
888
929
return 0 ;
889
930
}
@@ -892,7 +933,7 @@ static void sun8i_dwmac_unset_syscon(struct sunxi_priv_data *gmac)
892
933
{
893
934
u32 reg = gmac -> variant -> default_syscon_value ;
894
935
895
- regmap_write (gmac -> regmap , SYSCON_EMAC_REG , reg );
936
+ regmap_field_write (gmac -> regmap_field , reg );
896
937
}
897
938
898
939
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)
971
1012
return mac ;
972
1013
}
973
1014
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
+
974
1043
static int sun8i_dwmac_probe (struct platform_device * pdev )
975
1044
{
976
1045
struct plat_stmmacenet_data * plat_dat ;
@@ -980,6 +1049,7 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
980
1049
int ret ;
981
1050
struct stmmac_priv * priv ;
982
1051
struct net_device * ndev ;
1052
+ struct regmap * regmap ;
983
1053
984
1054
ret = stmmac_get_platform_resources (pdev , & stmmac_res );
985
1055
if (ret )
@@ -1014,14 +1084,41 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
1014
1084
gmac -> regulator = NULL ;
1015
1085
}
1016
1086
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 );
1021
1110
dev_err (& pdev -> dev , "Unable to map syscon: %d\n" , ret );
1022
1111
return ret ;
1023
1112
}
1024
1113
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
+
1025
1122
plat_dat -> interface = of_get_phy_mode (dev -> of_node );
1026
1123
1027
1124
/* platform data specifying hardware features and callbacks.
@@ -1078,6 +1175,8 @@ static const struct of_device_id sun8i_dwmac_match[] = {
1078
1175
.data = & emac_variant_v3s },
1079
1176
{ .compatible = "allwinner,sun8i-a83t-emac" ,
1080
1177
.data = & emac_variant_a83t },
1178
+ { .compatible = "allwinner,sun8i-r40-gmac" ,
1179
+ .data = & emac_variant_r40 },
1081
1180
{ .compatible = "allwinner,sun50i-a64-emac" ,
1082
1181
.data = & emac_variant_a64 },
1083
1182
{ }
0 commit comments