1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
3 * Copyright (c) 2018 Synopsys, Inc. and/or its affiliates.
4 * stmmac HW Interface Handling
9 #include "stmmac_ptp.h"
11 static u32
stmmac_get_id(struct stmmac_priv
*priv
, u32 id_reg
)
13 u32 reg
= readl(priv
->ioaddr
+ id_reg
);
16 dev_info(priv
->device
, "Version ID not available\n");
20 dev_info(priv
->device
, "User ID: 0x%x, Synopsys ID: 0x%x\n",
21 (unsigned int)(reg
& GENMASK(15, 8)) >> 8,
22 (unsigned int)(reg
& GENMASK(7, 0)));
23 return reg
& GENMASK(7, 0);
26 static u32
stmmac_get_dev_id(struct stmmac_priv
*priv
, u32 id_reg
)
28 u32 reg
= readl(priv
->ioaddr
+ id_reg
);
31 dev_info(priv
->device
, "Version ID not available\n");
35 return (reg
& GENMASK(15, 8)) >> 8;
38 static void stmmac_dwmac_mode_quirk(struct stmmac_priv
*priv
)
40 struct mac_device_info
*mac
= priv
->hw
;
42 if (priv
->chain_mode
) {
43 dev_info(priv
->device
, "Chain mode enabled\n");
44 priv
->mode
= STMMAC_CHAIN_MODE
;
45 mac
->mode
= &chain_mode_ops
;
47 dev_info(priv
->device
, "Ring mode enabled\n");
48 priv
->mode
= STMMAC_RING_MODE
;
49 mac
->mode
= &ring_mode_ops
;
53 static int stmmac_dwmac1_quirks(struct stmmac_priv
*priv
)
55 struct mac_device_info
*mac
= priv
->hw
;
57 if (priv
->plat
->enh_desc
) {
58 dev_info(priv
->device
, "Enhanced/Alternate descriptors\n");
60 /* GMAC older than 3.50 has no extended descriptors */
61 if (priv
->synopsys_id
>= DWMAC_CORE_3_50
) {
62 dev_info(priv
->device
, "Enabled extended descriptors\n");
63 priv
->extend_desc
= 1;
65 dev_warn(priv
->device
, "Extended descriptors not supported\n");
68 mac
->desc
= &enh_desc_ops
;
70 dev_info(priv
->device
, "Normal descriptors\n");
71 mac
->desc
= &ndesc_ops
;
74 stmmac_dwmac_mode_quirk(priv
);
78 static int stmmac_dwmac4_quirks(struct stmmac_priv
*priv
)
80 stmmac_dwmac_mode_quirk(priv
);
84 static int stmmac_dwxlgmac_quirks(struct stmmac_priv
*priv
)
86 priv
->hw
->xlgmac
= true;
90 static const struct stmmac_hwif_entry
{
96 const struct stmmac_regs_off regs
;
100 const void *hwtimestamp
;
104 int (*setup
)(struct stmmac_priv
*priv
);
105 int (*quirks
)(struct stmmac_priv
*priv
);
107 /* NOTE: New HW versions shall go to the end of this table */
114 .ptp_off
= PTP_GMAC3_X_OFFSET
,
115 .mmc_off
= MMC_GMAC3_X_OFFSET
,
118 .dma
= &dwmac100_dma_ops
,
119 .mac
= &dwmac100_ops
,
120 .hwtimestamp
= &stmmac_ptp
,
123 .mmc
= &dwmac_mmc_ops
,
124 .setup
= dwmac100_setup
,
125 .quirks
= stmmac_dwmac1_quirks
,
132 .ptp_off
= PTP_GMAC3_X_OFFSET
,
133 .mmc_off
= MMC_GMAC3_X_OFFSET
,
136 .dma
= &dwmac1000_dma_ops
,
137 .mac
= &dwmac1000_ops
,
138 .hwtimestamp
= &stmmac_ptp
,
141 .mmc
= &dwmac_mmc_ops
,
142 .setup
= dwmac1000_setup
,
143 .quirks
= stmmac_dwmac1_quirks
,
150 .ptp_off
= PTP_GMAC4_OFFSET
,
151 .mmc_off
= MMC_GMAC4_OFFSET
,
153 .desc
= &dwmac4_desc_ops
,
154 .dma
= &dwmac4_dma_ops
,
156 .hwtimestamp
= &stmmac_ptp
,
158 .tc
= &dwmac510_tc_ops
,
159 .mmc
= &dwmac_mmc_ops
,
160 .setup
= dwmac4_setup
,
161 .quirks
= stmmac_dwmac4_quirks
,
166 .min_id
= DWMAC_CORE_4_00
,
168 .ptp_off
= PTP_GMAC4_OFFSET
,
169 .mmc_off
= MMC_GMAC4_OFFSET
,
171 .desc
= &dwmac4_desc_ops
,
172 .dma
= &dwmac4_dma_ops
,
173 .mac
= &dwmac410_ops
,
174 .hwtimestamp
= &stmmac_ptp
,
175 .mode
= &dwmac4_ring_mode_ops
,
176 .tc
= &dwmac510_tc_ops
,
177 .mmc
= &dwmac_mmc_ops
,
178 .setup
= dwmac4_setup
,
184 .min_id
= DWMAC_CORE_4_10
,
186 .ptp_off
= PTP_GMAC4_OFFSET
,
187 .mmc_off
= MMC_GMAC4_OFFSET
,
189 .desc
= &dwmac4_desc_ops
,
190 .dma
= &dwmac410_dma_ops
,
191 .mac
= &dwmac410_ops
,
192 .hwtimestamp
= &stmmac_ptp
,
193 .mode
= &dwmac4_ring_mode_ops
,
194 .tc
= &dwmac510_tc_ops
,
195 .mmc
= &dwmac_mmc_ops
,
196 .setup
= dwmac4_setup
,
202 .min_id
= DWMAC_CORE_5_10
,
204 .ptp_off
= PTP_GMAC4_OFFSET
,
205 .mmc_off
= MMC_GMAC4_OFFSET
,
207 .desc
= &dwmac4_desc_ops
,
208 .dma
= &dwmac410_dma_ops
,
209 .mac
= &dwmac510_ops
,
210 .hwtimestamp
= &stmmac_ptp
,
211 .mode
= &dwmac4_ring_mode_ops
,
212 .tc
= &dwmac510_tc_ops
,
213 .mmc
= &dwmac_mmc_ops
,
214 .setup
= dwmac4_setup
,
220 .min_id
= DWXGMAC_CORE_2_10
,
221 .dev_id
= DWXGMAC_ID
,
223 .ptp_off
= PTP_XGMAC_OFFSET
,
224 .mmc_off
= MMC_XGMAC_OFFSET
,
226 .desc
= &dwxgmac210_desc_ops
,
227 .dma
= &dwxgmac210_dma_ops
,
228 .mac
= &dwxgmac210_ops
,
229 .hwtimestamp
= &stmmac_ptp
,
231 .tc
= &dwmac510_tc_ops
,
232 .mmc
= &dwxgmac_mmc_ops
,
233 .setup
= dwxgmac2_setup
,
239 .min_id
= DWXLGMAC_CORE_2_00
,
240 .dev_id
= DWXLGMAC_ID
,
242 .ptp_off
= PTP_XGMAC_OFFSET
,
243 .mmc_off
= MMC_XGMAC_OFFSET
,
245 .desc
= &dwxgmac210_desc_ops
,
246 .dma
= &dwxgmac210_dma_ops
,
247 .mac
= &dwxlgmac2_ops
,
248 .hwtimestamp
= &stmmac_ptp
,
250 .tc
= &dwmac510_tc_ops
,
251 .mmc
= &dwxgmac_mmc_ops
,
252 .setup
= dwxlgmac2_setup
,
253 .quirks
= stmmac_dwxlgmac_quirks
,
257 int stmmac_hwif_init(struct stmmac_priv
*priv
)
259 bool needs_xgmac
= priv
->plat
->has_xgmac
;
260 bool needs_gmac4
= priv
->plat
->has_gmac4
;
261 bool needs_gmac
= priv
->plat
->has_gmac
;
262 const struct stmmac_hwif_entry
*entry
;
263 struct mac_device_info
*mac
;
264 bool needs_setup
= true;
269 id
= stmmac_get_id(priv
, GMAC_VERSION
);
270 } else if (needs_gmac4
|| needs_xgmac
) {
271 id
= stmmac_get_id(priv
, GMAC4_VERSION
);
273 dev_id
= stmmac_get_dev_id(priv
, GMAC4_VERSION
);
278 /* Save ID for later use */
279 priv
->synopsys_id
= id
;
281 /* Lets assume some safe values first */
282 priv
->ptpaddr
= priv
->ioaddr
+
283 (needs_gmac4
? PTP_GMAC4_OFFSET
: PTP_GMAC3_X_OFFSET
);
284 priv
->mmcaddr
= priv
->ioaddr
+
285 (needs_gmac4
? MMC_GMAC4_OFFSET
: MMC_GMAC3_X_OFFSET
);
287 /* Check for HW specific setup first */
288 if (priv
->plat
->setup
) {
289 mac
= priv
->plat
->setup(priv
);
292 mac
= devm_kzalloc(priv
->device
, sizeof(*mac
), GFP_KERNEL
);
298 /* Fallback to generic HW */
299 for (i
= ARRAY_SIZE(stmmac_hw
) - 1; i
>= 0; i
--) {
300 entry
= &stmmac_hw
[i
];
302 if (needs_gmac
^ entry
->gmac
)
304 if (needs_gmac4
^ entry
->gmac4
)
306 if (needs_xgmac
^ entry
->xgmac
)
308 /* Use synopsys_id var because some setups can override this */
309 if (priv
->synopsys_id
< entry
->min_id
)
311 if (needs_xgmac
&& (dev_id
^ entry
->dev_id
))
314 /* Only use generic HW helpers if needed */
315 mac
->desc
= mac
->desc
? : entry
->desc
;
316 mac
->dma
= mac
->dma
? : entry
->dma
;
317 mac
->mac
= mac
->mac
? : entry
->mac
;
318 mac
->ptp
= mac
->ptp
? : entry
->hwtimestamp
;
319 mac
->mode
= mac
->mode
? : entry
->mode
;
320 mac
->tc
= mac
->tc
? : entry
->tc
;
321 mac
->mmc
= mac
->mmc
? : entry
->mmc
;
324 priv
->ptpaddr
= priv
->ioaddr
+ entry
->regs
.ptp_off
;
325 priv
->mmcaddr
= priv
->ioaddr
+ entry
->regs
.mmc_off
;
329 ret
= entry
->setup(priv
);
334 /* Save quirks, if needed for posterior use */
335 priv
->hwif_quirks
= entry
->quirks
;
339 dev_err(priv
->device
, "Failed to find HW IF (id=0x%x, gmac=%d/%d)\n",
340 id
, needs_gmac
, needs_gmac4
);