blob: 3d1885750aae8a282ef35f7d62b8053db7bd0533 [file] [log] [blame]
Thomas Gleixner3c910ec2019-06-01 10:09:00 +02001// SPDX-License-Identifier: GPL-2.0-only
Martin Blumenstingl566e8252016-09-06 23:38:46 +02002/*
Martin Blumenstingl76766932018-03-30 01:00:35 +02003 * Amlogic Meson8b, Meson8m2 and GXBB DWMAC glue layer
Martin Blumenstingl566e8252016-09-06 23:38:46 +02004 *
5 * Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Martin Blumenstingl566e8252016-09-06 23:38:46 +02006 */
7
Martin Blumenstingl3649abe2020-05-12 23:10:58 +02008#include <linux/bitfield.h>
Martin Blumenstingl566e8252016-09-06 23:38:46 +02009#include <linux/clk.h>
10#include <linux/clk-provider.h>
11#include <linux/device.h>
12#include <linux/ethtool.h>
13#include <linux/io.h>
14#include <linux/ioport.h>
15#include <linux/module.h>
Yixun Lanefacb562018-04-28 10:21:11 +000016#include <linux/of_device.h>
Martin Blumenstingl566e8252016-09-06 23:38:46 +020017#include <linux/of_net.h>
18#include <linux/mfd/syscon.h>
19#include <linux/platform_device.h>
20#include <linux/stmmac.h>
21
22#include "stmmac_platform.h"
Zhuo Wang2dce31f2022-11-23 15:12:18 +080023#if IS_ENABLED(CONFIG_AMLOGIC_ETH_PRIVE)
Zhuo Wang0c6d34d2022-12-16 14:40:19 +080024#ifdef CONFIG_PM_SLEEP
Zhuo Wang2dce31f2022-11-23 15:12:18 +080025#include <linux/amlogic/scpi_protocol.h>
Shunzhou Jiangc7ada762023-02-15 16:56:31 +080026#ifdef MBOX_NEW_VERSION
27#include <linux/amlogic/aml_mbox.h>
28#endif
Zhuo Wang2dce31f2022-11-23 15:12:18 +080029#include <linux/input.h>
30#include <linux/amlogic/pm.h>
Zhuo Wang0c6d34d2022-12-16 14:40:19 +080031#include <linux/arm-smccc.h>
32#endif
Zhuo Wang2dce31f2022-11-23 15:12:18 +080033#include <linux/amlogic/aml_phy_debug.h>
34#endif
Martin Blumenstingl566e8252016-09-06 23:38:46 +020035
36#define PRG_ETH0 0x0
37
38#define PRG_ETH0_RGMII_MODE BIT(0)
39
Yixun Lanefacb562018-04-28 10:21:11 +000040#define PRG_ETH0_EXT_PHY_MODE_MASK GENMASK(2, 0)
41#define PRG_ETH0_EXT_RGMII_MODE 1
42#define PRG_ETH0_EXT_RMII_MODE 4
43
Martin Blumenstingl566e8252016-09-06 23:38:46 +020044/* mux to choose between fclk_div2 (bit unset) and mpll2 (bit set) */
Martin Blumenstingl566e8252016-09-06 23:38:46 +020045#define PRG_ETH0_CLK_M250_SEL_MASK GENMASK(4, 4)
46
Martin Blumenstingl889df202020-05-12 23:10:59 +020047/* TX clock delay in ns = "8ns / 4 * tx_dly_val" (where 8ns are exactly one
48 * cycle of the 125MHz RGMII TX clock):
49 * 0ns = 0x0, 2ns = 0x1, 4ns = 0x2, 6ns = 0x3
50 */
Martin Blumenstingl566e8252016-09-06 23:38:46 +020051#define PRG_ETH0_TXDLY_MASK GENMASK(6, 5)
Martin Blumenstingl566e8252016-09-06 23:38:46 +020052
53/* divider for the result of m250_sel */
54#define PRG_ETH0_CLK_M250_DIV_SHIFT 7
55#define PRG_ETH0_CLK_M250_DIV_WIDTH 3
56
Martin Blumenstingl4f6a71b2018-01-15 18:10:13 +010057#define PRG_ETH0_RGMII_TX_CLK_EN 10
Martin Blumenstingl566e8252016-09-06 23:38:46 +020058
59#define PRG_ETH0_INVERTED_RMII_CLK BIT(11)
60#define PRG_ETH0_TX_AND_PHY_REF_CLK BIT(12)
61
Martin Blumenstinglc92d1d22020-05-12 23:11:00 +020062/* Bypass (= 0, the signal from the GPIO input directly connects to the
63 * internal sampling) or enable (= 1) the internal logic for RXEN and RXD[3:0]
64 * timing tuning.
65 */
66#define PRG_ETH0_ADJ_ENABLE BIT(13)
67/* Controls whether the RXEN and RXD[3:0] signals should be aligned with the
68 * input RX rising/falling edge and sent to the Ethernet internals. This sets
69 * the automatically delay and skew automatically (internally).
70 */
71#define PRG_ETH0_ADJ_SETUP BIT(14)
72/* An internal counter based on the "timing-adjustment" clock. The counter is
73 * cleared on both, the falling and rising edge of the RX_CLK. This selects the
74 * delay (= the counter value) when to start sampling RXEN and RXD[3:0].
75 */
76#define PRG_ETH0_ADJ_DELAY GENMASK(19, 15)
77/* Adjusts the skew between each bit of RXEN and RXD[3:0]. If a signal has a
78 * large input delay, the bit for that signal (RXEN = bit 0, RXD[3] = bit 1,
79 * ...) can be configured to be 1 to compensate for a delay of about 1ns.
80 */
81#define PRG_ETH0_ADJ_SKEW GENMASK(24, 20)
82
Martin Blumenstinglde94fc12021-01-06 14:42:51 +010083#define PRG_ETH1 0x4
84
85/* Defined for adding a delay to the input RX_CLK for better timing.
86 * Each step is 200ps. These bits are used with external RGMII PHYs
87 * because RGMII RX only has the small window. cfg_rxclk_dly can
88 * adjust the window between RX_CLK and RX_DATA and improve the stability
89 * of "rx data valid".
90 */
91#define PRG_ETH1_CFG_RXCLK_DLY GENMASK(19, 16)
92
Yixun Lanefacb562018-04-28 10:21:11 +000093struct meson8b_dwmac;
94
95struct meson8b_dwmac_data {
96 int (*set_phy_mode)(struct meson8b_dwmac *dwmac);
Martin Blumenstinglde94fc12021-01-06 14:42:51 +010097 bool has_prg_eth1_rgmii_rx_delay;
Zhuo Wang2dce31f2022-11-23 15:12:18 +080098#if IS_ENABLED(CONFIG_AMLOGIC_ETH_PRIVE)
Zhuo Wang0c6d34d2022-12-16 14:40:19 +080099#ifdef CONFIG_PM_SLEEP
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800100 int (*suspend)(struct meson8b_dwmac *dwmac);
101 void (*resume)(struct meson8b_dwmac *dwmac);
102#endif
Zhuo Wang0c6d34d2022-12-16 14:40:19 +0800103#endif
Yixun Lanefacb562018-04-28 10:21:11 +0000104};
105
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200106struct meson8b_dwmac {
Yixun Lanefacb562018-04-28 10:21:11 +0000107 struct device *dev;
108 void __iomem *regs;
109
110 const struct meson8b_dwmac_data *data;
111 phy_interface_t phy_mode;
112 struct clk *rgmii_tx_clk;
113 u32 tx_delay_ns;
Martin Blumenstingl140ddf02021-01-06 14:42:49 +0100114 u32 rx_delay_ps;
Martin Blumenstingle4227bf2020-05-12 23:11:01 +0200115 struct clk *timing_adj_clk;
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800116#if IS_ENABLED(CONFIG_AMLOGIC_ETH_PRIVE)
Zhuo Wang0c6d34d2022-12-16 14:40:19 +0800117#ifdef CONFIG_PM_SLEEP
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800118 struct input_dev *input_dev;
Shunzhou Jiangc7ada762023-02-15 16:56:31 +0800119 struct mbox_chan *mbox_chan;
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800120#endif
Zhuo Wang0c6d34d2022-12-16 14:40:19 +0800121#endif
Martin Blumenstingl80767592018-02-17 15:08:20 +0100122};
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200123
Martin Blumenstingl80767592018-02-17 15:08:20 +0100124struct meson8b_dwmac_clk_configs {
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200125 struct clk_mux m250_mux;
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200126 struct clk_divider m250_div;
Martin Blumenstingl4f6a71b2018-01-15 18:10:13 +0100127 struct clk_fixed_factor fixed_div2;
Martin Blumenstingl4f6a71b2018-01-15 18:10:13 +0100128 struct clk_gate rgmii_tx_en;
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200129};
130
131static void meson8b_dwmac_mask_bits(struct meson8b_dwmac *dwmac, u32 reg,
132 u32 mask, u32 value)
133{
134 u32 data;
135
136 data = readl(dwmac->regs + reg);
137 data &= ~mask;
138 data |= (value & mask);
139
140 writel(data, dwmac->regs + reg);
141}
142
Martin Blumenstingl11184a52018-02-17 15:08:18 +0100143static struct clk *meson8b_dwmac_register_clk(struct meson8b_dwmac *dwmac,
144 const char *name_suffix,
Martin Blumenstingl52660c02020-06-25 20:21:42 +0200145 const struct clk_parent_data *parents,
Martin Blumenstingl11184a52018-02-17 15:08:18 +0100146 int num_parents,
147 const struct clk_ops *ops,
148 struct clk_hw *hw)
149{
Martin Blumenstingl52660c02020-06-25 20:21:42 +0200150 struct clk_init_data init = { };
Martin Blumenstingl11184a52018-02-17 15:08:18 +0100151 char clk_name[32];
152
Martin Blumenstinglb7563712018-02-17 15:08:19 +0100153 snprintf(clk_name, sizeof(clk_name), "%s#%s", dev_name(dwmac->dev),
Martin Blumenstingl11184a52018-02-17 15:08:18 +0100154 name_suffix);
155
156 init.name = clk_name;
157 init.ops = ops;
158 init.flags = CLK_SET_RATE_PARENT;
Martin Blumenstingl52660c02020-06-25 20:21:42 +0200159 init.parent_data = parents;
Martin Blumenstingl11184a52018-02-17 15:08:18 +0100160 init.num_parents = num_parents;
161
162 hw->init = &init;
163
Martin Blumenstinglb7563712018-02-17 15:08:19 +0100164 return devm_clk_register(dwmac->dev, hw);
Martin Blumenstingl11184a52018-02-17 15:08:18 +0100165}
166
Martin Blumenstingl37512b42018-01-15 18:10:12 +0100167static int meson8b_init_rgmii_tx_clk(struct meson8b_dwmac *dwmac)
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200168{
Martin Blumenstingl11184a52018-02-17 15:08:18 +0100169 struct clk *clk;
Martin Blumenstinglb7563712018-02-17 15:08:19 +0100170 struct device *dev = dwmac->dev;
Martin Blumenstingl52660c02020-06-25 20:21:42 +0200171 static const struct clk_parent_data mux_parents[] = {
172 { .fw_name = "clkin0", },
Martin Blumenstinglf87777a2020-12-19 14:50:36 +0100173 { .index = -1, },
Martin Blumenstingl52660c02020-06-25 20:21:42 +0200174 };
Martin Blumenstinglbd6f4852019-12-26 20:01:01 +0100175 static const struct clk_div_table div_table[] = {
176 { .div = 2, .val = 2, },
177 { .div = 3, .val = 3, },
178 { .div = 4, .val = 4, },
179 { .div = 5, .val = 5, },
180 { .div = 6, .val = 6, },
181 { .div = 7, .val = 7, },
Marc Zyngierf0212a52020-04-18 19:14:57 +0100182 { /* end of array */ }
Martin Blumenstinglbd6f4852019-12-26 20:01:01 +0100183 };
Martin Blumenstingl52660c02020-06-25 20:21:42 +0200184 struct meson8b_dwmac_clk_configs *clk_configs;
185 struct clk_parent_data parent_data = { };
Martin Blumenstingl80767592018-02-17 15:08:20 +0100186
187 clk_configs = devm_kzalloc(dev, sizeof(*clk_configs), GFP_KERNEL);
188 if (!clk_configs)
189 return -ENOMEM;
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200190
Martin Blumenstingl80767592018-02-17 15:08:20 +0100191 clk_configs->m250_mux.reg = dwmac->regs + PRG_ETH0;
Martin Blumenstingl82ca4c92020-12-05 22:32:07 +0100192 clk_configs->m250_mux.shift = __ffs(PRG_ETH0_CLK_M250_SEL_MASK);
193 clk_configs->m250_mux.mask = PRG_ETH0_CLK_M250_SEL_MASK >>
194 clk_configs->m250_mux.shift;
Martin Blumenstingl52660c02020-06-25 20:21:42 +0200195 clk = meson8b_dwmac_register_clk(dwmac, "m250_sel", mux_parents,
196 ARRAY_SIZE(mux_parents), &clk_mux_ops,
Martin Blumenstingl80767592018-02-17 15:08:20 +0100197 &clk_configs->m250_mux.hw);
Martin Blumenstingl11184a52018-02-17 15:08:18 +0100198 if (WARN_ON(IS_ERR(clk)))
199 return PTR_ERR(clk);
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200200
Martin Blumenstingl52660c02020-06-25 20:21:42 +0200201 parent_data.hw = &clk_configs->m250_mux.hw;
Martin Blumenstingl80767592018-02-17 15:08:20 +0100202 clk_configs->m250_div.reg = dwmac->regs + PRG_ETH0;
203 clk_configs->m250_div.shift = PRG_ETH0_CLK_M250_DIV_SHIFT;
204 clk_configs->m250_div.width = PRG_ETH0_CLK_M250_DIV_WIDTH;
Martin Blumenstinglbd6f4852019-12-26 20:01:01 +0100205 clk_configs->m250_div.table = div_table;
206 clk_configs->m250_div.flags = CLK_DIVIDER_ALLOW_ZERO |
207 CLK_DIVIDER_ROUND_CLOSEST;
Martin Blumenstingl52660c02020-06-25 20:21:42 +0200208 clk = meson8b_dwmac_register_clk(dwmac, "m250_div", &parent_data, 1,
Martin Blumenstingl11184a52018-02-17 15:08:18 +0100209 &clk_divider_ops,
Martin Blumenstingl80767592018-02-17 15:08:20 +0100210 &clk_configs->m250_div.hw);
Martin Blumenstingl11184a52018-02-17 15:08:18 +0100211 if (WARN_ON(IS_ERR(clk)))
212 return PTR_ERR(clk);
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200213
Martin Blumenstingl52660c02020-06-25 20:21:42 +0200214 parent_data.hw = &clk_configs->m250_div.hw;
Martin Blumenstingl80767592018-02-17 15:08:20 +0100215 clk_configs->fixed_div2.mult = 1;
216 clk_configs->fixed_div2.div = 2;
Martin Blumenstingl52660c02020-06-25 20:21:42 +0200217 clk = meson8b_dwmac_register_clk(dwmac, "fixed_div2", &parent_data, 1,
Martin Blumenstingl11184a52018-02-17 15:08:18 +0100218 &clk_fixed_factor_ops,
Martin Blumenstingl80767592018-02-17 15:08:20 +0100219 &clk_configs->fixed_div2.hw);
Martin Blumenstingl11184a52018-02-17 15:08:18 +0100220 if (WARN_ON(IS_ERR(clk)))
221 return PTR_ERR(clk);
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200222
Martin Blumenstingl52660c02020-06-25 20:21:42 +0200223 parent_data.hw = &clk_configs->fixed_div2.hw;
Martin Blumenstingl80767592018-02-17 15:08:20 +0100224 clk_configs->rgmii_tx_en.reg = dwmac->regs + PRG_ETH0;
225 clk_configs->rgmii_tx_en.bit_idx = PRG_ETH0_RGMII_TX_CLK_EN;
Martin Blumenstingl52660c02020-06-25 20:21:42 +0200226 clk = meson8b_dwmac_register_clk(dwmac, "rgmii_tx_en", &parent_data, 1,
Martin Blumenstingl11184a52018-02-17 15:08:18 +0100227 &clk_gate_ops,
Martin Blumenstingl80767592018-02-17 15:08:20 +0100228 &clk_configs->rgmii_tx_en.hw);
Martin Blumenstingl11184a52018-02-17 15:08:18 +0100229 if (WARN_ON(IS_ERR(clk)))
230 return PTR_ERR(clk);
Martin Blumenstingl4f6a71b2018-01-15 18:10:13 +0100231
Martin Blumenstingl11184a52018-02-17 15:08:18 +0100232 dwmac->rgmii_tx_clk = clk;
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200233
234 return 0;
235}
236
Yixun Lanefacb562018-04-28 10:21:11 +0000237static int meson8b_set_phy_mode(struct meson8b_dwmac *dwmac)
238{
239 switch (dwmac->phy_mode) {
240 case PHY_INTERFACE_MODE_RGMII:
241 case PHY_INTERFACE_MODE_RGMII_RXID:
242 case PHY_INTERFACE_MODE_RGMII_ID:
243 case PHY_INTERFACE_MODE_RGMII_TXID:
244 /* enable RGMII mode */
245 meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
246 PRG_ETH0_RGMII_MODE,
247 PRG_ETH0_RGMII_MODE);
248 break;
249 case PHY_INTERFACE_MODE_RMII:
250 /* disable RGMII mode -> enables RMII mode */
251 meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
252 PRG_ETH0_RGMII_MODE, 0);
253 break;
254 default:
255 dev_err(dwmac->dev, "fail to set phy-mode %s\n",
256 phy_modes(dwmac->phy_mode));
257 return -EINVAL;
258 }
259
260 return 0;
261}
262
263static int meson_axg_set_phy_mode(struct meson8b_dwmac *dwmac)
264{
265 switch (dwmac->phy_mode) {
266 case PHY_INTERFACE_MODE_RGMII:
267 case PHY_INTERFACE_MODE_RGMII_RXID:
268 case PHY_INTERFACE_MODE_RGMII_ID:
269 case PHY_INTERFACE_MODE_RGMII_TXID:
270 /* enable RGMII mode */
271 meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
272 PRG_ETH0_EXT_PHY_MODE_MASK,
273 PRG_ETH0_EXT_RGMII_MODE);
274 break;
275 case PHY_INTERFACE_MODE_RMII:
276 /* disable RGMII mode -> enables RMII mode */
277 meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
278 PRG_ETH0_EXT_PHY_MODE_MASK,
279 PRG_ETH0_EXT_RMII_MODE);
280 break;
281 default:
282 dev_err(dwmac->dev, "fail to set phy-mode %s\n",
283 phy_modes(dwmac->phy_mode));
284 return -EINVAL;
285 }
286
287 return 0;
288}
289
Martin Blumenstingla54dc4a2020-05-12 23:11:02 +0200290static int meson8b_devm_clk_prepare_enable(struct meson8b_dwmac *dwmac,
291 struct clk *clk)
292{
293 int ret;
294
295 ret = clk_prepare_enable(clk);
296 if (ret)
297 return ret;
298
Rasmus Villemoese7871b9a2022-11-04 09:30:04 +0100299 return devm_add_action_or_reset(dwmac->dev,
300 (void(*)(void *))clk_disable_unprepare,
301 clk);
Martin Blumenstingla54dc4a2020-05-12 23:11:02 +0200302}
303
Martin Blumenstingl79852442021-01-06 14:42:50 +0100304static int meson8b_init_rgmii_delays(struct meson8b_dwmac *dwmac)
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200305{
Martin Blumenstinglde94fc12021-01-06 14:42:51 +0100306 u32 tx_dly_config, rx_adj_config, cfg_rxclk_dly, delay_config;
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200307 int ret;
Martin Blumenstingl9308c4762020-05-12 23:11:03 +0200308
Martin Blumenstinglde94fc12021-01-06 14:42:51 +0100309 rx_adj_config = 0;
310 cfg_rxclk_dly = 0;
Martin Blumenstingl9308c4762020-05-12 23:11:03 +0200311 tx_dly_config = FIELD_PREP(PRG_ETH0_TXDLY_MASK,
312 dwmac->tx_delay_ns >> 1);
313
Martin Blumenstinglde94fc12021-01-06 14:42:51 +0100314 if (dwmac->data->has_prg_eth1_rgmii_rx_delay)
315 cfg_rxclk_dly = FIELD_PREP(PRG_ETH1_CFG_RXCLK_DLY,
316 dwmac->rx_delay_ps / 200);
317 else if (dwmac->rx_delay_ps == 2000)
318 rx_adj_config = PRG_ETH0_ADJ_ENABLE | PRG_ETH0_ADJ_SETUP;
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200319
320 switch (dwmac->phy_mode) {
321 case PHY_INTERFACE_MODE_RGMII:
Martin Blumenstinglde94fc12021-01-06 14:42:51 +0100322 delay_config = tx_dly_config | rx_adj_config;
Martin Blumenstingl9308c4762020-05-12 23:11:03 +0200323 break;
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200324 case PHY_INTERFACE_MODE_RGMII_RXID:
Martin Blumenstingl9308c4762020-05-12 23:11:03 +0200325 delay_config = tx_dly_config;
Martin Blumenstinglde94fc12021-01-06 14:42:51 +0100326 cfg_rxclk_dly = 0;
Martin Blumenstingl9308c4762020-05-12 23:11:03 +0200327 break;
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200328 case PHY_INTERFACE_MODE_RGMII_TXID:
Martin Blumenstinglde94fc12021-01-06 14:42:51 +0100329 delay_config = rx_adj_config;
Martin Blumenstingl9308c4762020-05-12 23:11:03 +0200330 break;
331 case PHY_INTERFACE_MODE_RGMII_ID:
332 case PHY_INTERFACE_MODE_RMII:
333 delay_config = 0;
Martin Blumenstinglde94fc12021-01-06 14:42:51 +0100334 cfg_rxclk_dly = 0;
Martin Blumenstingl9308c4762020-05-12 23:11:03 +0200335 break;
336 default:
337 dev_err(dwmac->dev, "unsupported phy-mode %s\n",
338 phy_modes(dwmac->phy_mode));
339 return -EINVAL;
Tom Rix1c5825e2020-11-01 06:07:20 -0800340 }
Martin Blumenstingl9308c4762020-05-12 23:11:03 +0200341
Martin Blumenstingl02582282021-01-06 14:42:48 +0100342 if (delay_config & PRG_ETH0_ADJ_ENABLE) {
Martin Blumenstingl9308c4762020-05-12 23:11:03 +0200343 if (!dwmac->timing_adj_clk) {
344 dev_err(dwmac->dev,
345 "The timing-adjustment clock is mandatory for the RX delay re-timing\n");
346 return -EINVAL;
347 }
348
349 /* The timing adjustment logic is driven by a separate clock */
350 ret = meson8b_devm_clk_prepare_enable(dwmac,
351 dwmac->timing_adj_clk);
352 if (ret) {
353 dev_err(dwmac->dev,
354 "Failed to enable the timing-adjustment clock\n");
355 return ret;
356 }
357 }
358
359 meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TXDLY_MASK |
360 PRG_ETH0_ADJ_ENABLE | PRG_ETH0_ADJ_SETUP |
361 PRG_ETH0_ADJ_DELAY | PRG_ETH0_ADJ_SKEW,
362 delay_config);
363
Martin Blumenstinglde94fc12021-01-06 14:42:51 +0100364 meson8b_dwmac_mask_bits(dwmac, PRG_ETH1, PRG_ETH1_CFG_RXCLK_DLY,
365 cfg_rxclk_dly);
366
Martin Blumenstingl79852442021-01-06 14:42:50 +0100367 return 0;
368}
369
370static int meson8b_init_prg_eth(struct meson8b_dwmac *dwmac)
371{
372 int ret;
373
Martin Blumenstingl9308c4762020-05-12 23:11:03 +0200374 if (phy_interface_mode_is_rgmii(dwmac->phy_mode)) {
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200375 /* only relevant for RMII mode -> disable in RGMII mode */
376 meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
377 PRG_ETH0_INVERTED_RMII_CLK, 0);
378
Martin Blumenstingl4f6a71b2018-01-15 18:10:13 +0100379 /* Configure the 125MHz RGMII TX clock, the IP block changes
380 * the output automatically (= without us having to configure
381 * a register) based on the line-speed (125MHz for Gbit speeds,
382 * 25MHz for 100Mbit/s and 2.5MHz for 10Mbit/s).
383 */
Martin Blumenstingl11184a52018-02-17 15:08:18 +0100384 ret = clk_set_rate(dwmac->rgmii_tx_clk, 125 * 1000 * 1000);
Martin Blumenstingl37512b42018-01-15 18:10:12 +0100385 if (ret) {
Martin Blumenstinglb7563712018-02-17 15:08:19 +0100386 dev_err(dwmac->dev,
Martin Blumenstingl4f6a71b2018-01-15 18:10:13 +0100387 "failed to set RGMII TX clock\n");
Martin Blumenstingl37512b42018-01-15 18:10:12 +0100388 return ret;
389 }
390
Martin Blumenstingla54dc4a2020-05-12 23:11:02 +0200391 ret = meson8b_devm_clk_prepare_enable(dwmac,
392 dwmac->rgmii_tx_clk);
Martin Blumenstingl37512b42018-01-15 18:10:12 +0100393 if (ret) {
Martin Blumenstinglb7563712018-02-17 15:08:19 +0100394 dev_err(dwmac->dev,
Martin Blumenstingl4f6a71b2018-01-15 18:10:13 +0100395 "failed to enable the RGMII TX clock\n");
Martin Blumenstingl37512b42018-01-15 18:10:12 +0100396 return ret;
397 }
Martin Blumenstingl9308c4762020-05-12 23:11:03 +0200398 } else {
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200399 /* invert internal clk_rmii_i to generate 25/2.5 tx_rx_clk */
400 meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
401 PRG_ETH0_INVERTED_RMII_CLK,
402 PRG_ETH0_INVERTED_RMII_CLK);
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200403 }
404
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200405 /* enable TX_CLK and PHY_REF_CLK generator */
406 meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TX_AND_PHY_REF_CLK,
407 PRG_ETH0_TX_AND_PHY_REF_CLK);
408
409 return 0;
410}
411
Zhuo Wang3c574422022-04-26 10:07:38 +0800412#if IS_ENABLED(CONFIG_AMLOGIC_ETH_PRIVE)
Zhuo Wang0c6d34d2022-12-16 14:40:19 +0800413#ifdef CONFIG_PM_SLEEP
Zhuo Wangac9ba3d2023-03-16 05:49:04 +0000414static bool mac_wol_enable;
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800415void set_wol_notify_bl31(u32 enable_bl31)
416{
417 struct arm_smccc_res res;
418
419 arm_smccc_smc(0x8200009D, enable_bl31,
420 0, 0, 0, 0, 0, 0, &res);
421}
422
Shunzhou Jiangc7ada762023-02-15 16:56:31 +0800423static void set_wol_notify_bl30(struct meson8b_dwmac *dwmac, u32 enable_bl30)
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800424{
Shunzhou Jiangc7ada762023-02-15 16:56:31 +0800425 #ifdef MBOX_NEW_VERSION
426 aml_mbox_transfer_data(dwmac->mbox_chan, MBOX_CMD_SET_ETHERNET_WOL,
427 &enable_bl30, 4, NULL, 0, MBOX_SYNC);
428 #else
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800429 scpi_set_ethernet_wol(enable_bl30);
Shunzhou Jiangc7ada762023-02-15 16:56:31 +0800430 #endif
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800431}
Zhuo Wangac9ba3d2023-03-16 05:49:04 +0000432
433void set_device_init_flag(struct device *pdev, bool enable)
434{
435 if (enable == mac_wol_enable)
436 return;
437
438 device_init_wakeup(pdev, enable);
439 mac_wol_enable = enable;
440}
Zhuo Wang0c6d34d2022-12-16 14:40:19 +0800441#endif
Zhuo Wangc4abb042023-03-10 09:10:40 +0000442unsigned int internal_phy;
Zhuo Wangdf720f82022-02-17 11:44:09 +0800443static int aml_custom_setting(struct platform_device *pdev, struct meson8b_dwmac *dwmac)
444{
445 struct device_node *np = pdev->dev.of_node;
Zhuo Wang6a70e072023-02-06 16:19:32 +0800446 struct net_device *ndev = platform_get_drvdata(pdev);
Zhuo Wangdf720f82022-02-17 11:44:09 +0800447 unsigned int mc_val = 0;
xiangyang.yan14aafb22023-04-19 14:54:21 +0800448 unsigned int cali_val = 0;
Zhuo Wangdf720f82022-02-17 11:44:09 +0800449
450 pr_info("aml_cust_setting\n");
451
452 if (of_property_read_u32(np, "mc_val", &mc_val) == 0) {
453 pr_info("cover mc_val as 0x%x\n", mc_val);
454 writel(mc_val, dwmac->regs + PRG_ETH0);
455 }
456
Zhuo Wangc4abb042023-03-10 09:10:40 +0000457 if (of_property_read_u32(np, "internal_phy", &internal_phy) != 0)
458 pr_info("use default internal_phy as 0\n");
459
Zhuo Wang6a70e072023-02-06 16:19:32 +0800460 ndev->wol_enabled = true;
Zhuo Wangac9ba3d2023-03-16 05:49:04 +0000461#ifdef CONFIG_PM_SLEEP
462 if (of_property_read_u32(np, "mac_wol", &wol_switch_from_user) == 0)
463 pr_info("feature mac_wol\n");
464#endif
465
xiangyang.yan14aafb22023-04-19 14:54:21 +0800466 /*internal_phy 1:inphy;2:exphy; 0 as default*/
467 if (internal_phy == 2) {
468 if (of_property_read_u32(np, "cali_val", &cali_val) != 0)
469 pr_err("set default cali_val as 0\n");
470 writel(cali_val, dwmac->regs + PRG_ETH1);
471 }
472
Zhuo Wangdf720f82022-02-17 11:44:09 +0800473 return 0;
474}
475#endif
476
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200477static int meson8b_dwmac_probe(struct platform_device *pdev)
478{
479 struct plat_stmmacenet_data *plat_dat;
480 struct stmmac_resources stmmac_res;
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200481 struct meson8b_dwmac *dwmac;
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800482#if IS_ENABLED(CONFIG_AMLOGIC_ETH_PRIVE)
Zhuo Wang0c6d34d2022-12-16 14:40:19 +0800483#ifdef CONFIG_PM_SLEEP
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800484 struct input_dev *input_dev;
485#endif
Zhuo Wang0c6d34d2022-12-16 14:40:19 +0800486#endif
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200487 int ret;
488
489 ret = stmmac_get_platform_resources(pdev, &stmmac_res);
490 if (ret)
491 return ret;
492
Michael Walle83216e32021-04-12 19:47:17 +0200493 plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200494 if (IS_ERR(plat_dat))
495 return PTR_ERR(plat_dat);
496
497 dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
Johan Hovoldd2ed0a72016-11-30 15:29:55 +0100498 if (!dwmac) {
499 ret = -ENOMEM;
500 goto err_remove_config_dt;
501 }
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200502
Yixun Lanefacb562018-04-28 10:21:11 +0000503 dwmac->data = (const struct meson8b_dwmac_data *)
504 of_device_get_match_data(&pdev->dev);
Christophe JAILLET760a6ed2018-06-11 19:52:27 +0200505 if (!dwmac->data) {
506 ret = -EINVAL;
507 goto err_remove_config_dt;
508 }
YueHaibing999232a2019-08-21 21:51:30 +0800509 dwmac->regs = devm_platform_ioremap_resource(pdev, 1);
Johan Hovoldd2ed0a72016-11-30 15:29:55 +0100510 if (IS_ERR(dwmac->regs)) {
511 ret = PTR_ERR(dwmac->regs);
512 goto err_remove_config_dt;
513 }
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200514
Martin Blumenstinglb7563712018-02-17 15:08:19 +0100515 dwmac->dev = &pdev->dev;
Andrew Lunn0c65b2b2019-11-04 02:40:33 +0100516 ret = of_get_phy_mode(pdev->dev.of_node, &dwmac->phy_mode);
517 if (ret) {
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200518 dev_err(&pdev->dev, "missing phy-mode property\n");
Johan Hovoldd2ed0a72016-11-30 15:29:55 +0100519 goto err_remove_config_dt;
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200520 }
521
Martin Blumenstinglb7652342017-01-22 23:02:46 +0100522 /* use 2ns as fallback since this value was previously hardcoded */
523 if (of_property_read_u32(pdev->dev.of_node, "amlogic,tx-delay-ns",
524 &dwmac->tx_delay_ns))
525 dwmac->tx_delay_ns = 2;
526
Martin Blumenstingl140ddf02021-01-06 14:42:49 +0100527 /* RX delay defaults to 0ps since this is what many boards use */
528 if (of_property_read_u32(pdev->dev.of_node, "rx-internal-delay-ps",
529 &dwmac->rx_delay_ps)) {
530 if (!of_property_read_u32(pdev->dev.of_node,
531 "amlogic,rx-delay-ns",
532 &dwmac->rx_delay_ps))
533 /* convert ns to ps */
534 dwmac->rx_delay_ps *= 1000;
535 }
Martin Blumenstingl9308c4762020-05-12 23:11:03 +0200536
Martin Blumenstinglde94fc12021-01-06 14:42:51 +0100537 if (dwmac->data->has_prg_eth1_rgmii_rx_delay) {
Martin Blumenstingl9e8789c82021-01-19 21:24:24 +0100538 if (dwmac->rx_delay_ps > 3000 || dwmac->rx_delay_ps % 200) {
Martin Blumenstinglde94fc12021-01-06 14:42:51 +0100539 dev_err(dwmac->dev,
Martin Blumenstingl9e8789c82021-01-19 21:24:24 +0100540 "The RGMII RX delay range is 0..3000ps in 200ps steps");
Martin Blumenstinglde94fc12021-01-06 14:42:51 +0100541 ret = -EINVAL;
542 goto err_remove_config_dt;
543 }
544 } else {
Martin Blumenstingl9e8789c82021-01-19 21:24:24 +0100545 if (dwmac->rx_delay_ps != 0 && dwmac->rx_delay_ps != 2000) {
Martin Blumenstinglde94fc12021-01-06 14:42:51 +0100546 dev_err(dwmac->dev,
Martin Blumenstingl9e8789c82021-01-19 21:24:24 +0100547 "The only allowed RGMII RX delays values are: 0ps, 2000ps");
Martin Blumenstinglde94fc12021-01-06 14:42:51 +0100548 ret = -EINVAL;
549 goto err_remove_config_dt;
550 }
Martin Blumenstingl9308c4762020-05-12 23:11:03 +0200551 }
552
Martin Blumenstingle4227bf2020-05-12 23:11:01 +0200553 dwmac->timing_adj_clk = devm_clk_get_optional(dwmac->dev,
554 "timing-adjustment");
555 if (IS_ERR(dwmac->timing_adj_clk)) {
556 ret = PTR_ERR(dwmac->timing_adj_clk);
557 goto err_remove_config_dt;
558 }
559
Martin Blumenstingl79852442021-01-06 14:42:50 +0100560 ret = meson8b_init_rgmii_delays(dwmac);
561 if (ret)
562 goto err_remove_config_dt;
563
Martin Blumenstingl37512b42018-01-15 18:10:12 +0100564 ret = meson8b_init_rgmii_tx_clk(dwmac);
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200565 if (ret)
Johan Hovoldd2ed0a72016-11-30 15:29:55 +0100566 goto err_remove_config_dt;
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200567
Yixun Lanefacb562018-04-28 10:21:11 +0000568 ret = dwmac->data->set_phy_mode(dwmac);
569 if (ret)
570 goto err_remove_config_dt;
571
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200572 ret = meson8b_init_prg_eth(dwmac);
573 if (ret)
Johan Hovoldd2ed0a72016-11-30 15:29:55 +0100574 goto err_remove_config_dt;
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200575
576 plat_dat->bsp_priv = dwmac;
577
Johan Hovold5cc70bb2016-11-30 15:29:53 +0100578 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
579 if (ret)
Martin Blumenstingl11184a52018-02-17 15:08:18 +0100580 goto err_remove_config_dt;
Zhuo Wang3c574422022-04-26 10:07:38 +0800581#if IS_ENABLED(CONFIG_AMLOGIC_ETH_PRIVE)
Zhuo Wangdf720f82022-02-17 11:44:09 +0800582 aml_custom_setting(pdev, dwmac);
Zhuo Wang0c6d34d2022-12-16 14:40:19 +0800583#ifdef CONFIG_PM_SLEEP
Zhuo Wangac9ba3d2023-03-16 05:49:04 +0000584 device_init_wakeup(&pdev->dev, wol_switch_from_user);
585 mac_wol_enable = wol_switch_from_user;
586
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800587 /*input device to send virtual pwr key for android*/
588 input_dev = input_allocate_device();
589 if (!input_dev) {
590 pr_err("[abner test]input_allocate_device failed: %d\n", ret);
591 return -EINVAL;
592 }
593 set_bit(EV_KEY, input_dev->evbit);
594 set_bit(KEY_POWER, input_dev->keybit);
595 set_bit(133, input_dev->keybit);
596
597 input_dev->name = "input_ethrcu";
598 input_dev->phys = "input_ethrcu/input0";
599 input_dev->dev.parent = &pdev->dev;
600 input_dev->id.bustype = BUS_ISA;
601 input_dev->id.vendor = 0x0001;
602 input_dev->id.product = 0x0001;
603 input_dev->id.version = 0x0100;
604 input_dev->rep[REP_DELAY] = 0xffffffff;
605 input_dev->rep[REP_PERIOD] = 0xffffffff;
606 input_dev->keycodesize = sizeof(unsigned short);
607 input_dev->keycodemax = 0x1ff;
608 ret = input_register_device(input_dev);
609 if (ret < 0) {
610 pr_err("[abner test]input_register_device failed: %d\n", ret);
611 input_free_device(input_dev);
612 return -EINVAL;
613 }
614 dwmac->input_dev = input_dev;
Shunzhou Jiangc7ada762023-02-15 16:56:31 +0800615
616#ifdef MBOX_NEW_VERSION
617 dwmac->mbox_chan = aml_mbox_request_channel_byidx(&pdev->dev, 0);
618#endif
Zhuo Wang0c6d34d2022-12-16 14:40:19 +0800619#endif
Zhuo Wangdf720f82022-02-17 11:44:09 +0800620#endif
Johan Hovold5cc70bb2016-11-30 15:29:53 +0100621 return 0;
622
Johan Hovoldd2ed0a72016-11-30 15:29:55 +0100623err_remove_config_dt:
624 stmmac_remove_config_dt(pdev, plat_dat);
Johan Hovold5cc70bb2016-11-30 15:29:53 +0100625
626 return ret;
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200627}
628
yao zhang1208adc62023-02-08 18:42:09 +0800629#if IS_ENABLED(CONFIG_AMLOGIC_ETH_PRIVE)
630#ifdef CONFIG_PM_SLEEP
xiangyang.yan2da0dff2023-02-07 11:31:18 +0800631static void meson8b_dwmac_shutdown(struct platform_device *pdev)
632{
633 struct net_device *ndev = platform_get_drvdata(pdev);
634 struct stmmac_priv *priv = netdev_priv(ndev);
635 struct meson8b_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev);
636 int ret;
637
Zhuo Wangac9ba3d2023-03-16 05:49:04 +0000638 if (wol_switch_from_user) {
639 set_wol_notify_bl31(0);
Shunzhou Jiangc7ada762023-02-15 16:56:31 +0800640 set_wol_notify_bl30(dwmac, 0);
Zhuo Wangac9ba3d2023-03-16 05:49:04 +0000641 set_device_init_flag(&pdev->dev, 0);
642 }
643
xiangyang.yan2da0dff2023-02-07 11:31:18 +0800644 pr_info("aml_eth_shutdown\n");
645 ret = stmmac_suspend(priv->device);
Zhuo Wangc4abb042023-03-10 09:10:40 +0000646 if (internal_phy != 2) {
647 if (dwmac->data->suspend)
648 ret = dwmac->data->suspend(dwmac);
649 }
xiangyang.yan2da0dff2023-02-07 11:31:18 +0800650}
651
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800652static int dwmac_suspend(struct meson8b_dwmac *dwmac)
653{
654 pr_info("disable analog\n");
655 writel(0x00000000, phy_analog_config_addr + 0x0);
656 writel(0x003e0000, phy_analog_config_addr + 0x4);
657 writel(0x12844008, phy_analog_config_addr + 0x8);
658 writel(0x0800a40c, phy_analog_config_addr + 0xc);
659 writel(0x00000000, phy_analog_config_addr + 0x10);
660 writel(0x031d161c, phy_analog_config_addr + 0x14);
661 writel(0x00001683, phy_analog_config_addr + 0x18);
Zhuo Wang91ff7382023-06-20 17:46:37 +0800662 if (phy_pll_mode == 1)
663 writel(0x608200a0, phy_analog_config_addr + 0x44);
664 else
665 writel(0x09c0040a, phy_analog_config_addr + 0x44);
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800666 return 0;
667}
668
669static void dwmac_resume(struct meson8b_dwmac *dwmac)
670{
671 pr_info("recover analog\n");
Zhuo Wang91ff7382023-06-20 17:46:37 +0800672 if (phy_pll_mode == 1) {
673 writel(0x608200a0, phy_analog_config_addr + 0x44);
674 writel(0xea002000, phy_analog_config_addr + 0x48);
675 writel(0x00000150, phy_analog_config_addr + 0x4c);
676 writel(0x00000000, phy_analog_config_addr + 0x50);
677 writel(0x708200a0, phy_analog_config_addr + 0x44);
678 usleep_range(100, 200);
679 writel(0x508200a0, phy_analog_config_addr + 0x44);
680 writel(0x00000110, phy_analog_config_addr + 0x4c);
681 } else {
682 writel(0x19c0040a, phy_analog_config_addr + 0x44);
683 }
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800684 writel(0x0, phy_analog_config_addr + 0x4);
685}
686
687int backup_adv;
Zhuo Wangc4abb042023-03-10 09:10:40 +0000688int without_reset;
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800689static int meson8b_suspend(struct device *dev)
690{
691 struct net_device *ndev = dev_get_drvdata(dev);
692 struct stmmac_priv *priv = netdev_priv(ndev);
693 struct meson8b_dwmac *dwmac = priv->plat->bsp_priv;
694 struct phy_device *phydev = ndev->phydev;
695
696 int ret;
697
Zhuo Wangc4abb042023-03-10 09:10:40 +0000698 /*open wol, shutdown phy when not link*/
699 if ((wol_switch_from_user) && phydev->link) {
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800700 set_wol_notify_bl31(true);
Shunzhou Jiangc7ada762023-02-15 16:56:31 +0800701 set_wol_notify_bl30(dwmac, true);
Zhuo Wangac9ba3d2023-03-16 05:49:04 +0000702 set_device_init_flag(dev, true);
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800703 priv->wolopts = 0x1 << 5;
Zhuo Wang90e11992023-04-12 13:47:29 +0800704 /*our phy not support wol by now*/
705 phydev->irq_suspended = 0;
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800706 /*phy is 100M, change to 10M*/
Zhuo Wangac9ba3d2023-03-16 05:49:04 +0000707 if (phydev->speed != 10) {
708 pr_info("link 100M -> 10M\n");
709 backup_adv = phy_read(phydev, MII_ADVERTISE);
710 phy_write(phydev, MII_ADVERTISE, 0x61);
711 mii_lpa_to_linkmode_lpa_t(phydev->advertising, 0x61);
712 genphy_restart_aneg(phydev);
713 msleep(3000);
714 }
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800715 ret = stmmac_suspend(dev);
Zhuo Wangc4abb042023-03-10 09:10:40 +0000716 without_reset = 1;
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800717 } else {
718 set_wol_notify_bl31(false);
Shunzhou Jiangc7ada762023-02-15 16:56:31 +0800719 set_wol_notify_bl30(dwmac, false);
Zhuo Wangac9ba3d2023-03-16 05:49:04 +0000720 set_device_init_flag(dev, false);
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800721
722 ret = stmmac_suspend(dev);
Zhuo Wangc4abb042023-03-10 09:10:40 +0000723 if (internal_phy != 2) {
724 if (dwmac->data->suspend)
725 ret = dwmac->data->suspend(dwmac);
726 }
727 without_reset = 0;
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800728 }
729
730 return ret;
731}
732
733static int meson8b_resume(struct device *dev)
734{
735 struct net_device *ndev = dev_get_drvdata(dev);
736 struct stmmac_priv *priv = netdev_priv(ndev);
737 struct meson8b_dwmac *dwmac = priv->plat->bsp_priv;
738 int ret;
739 struct phy_device *phydev = ndev->phydev;
740
Zhuo Wang6a70e072023-02-06 16:19:32 +0800741 priv->wolopts = 0;
742
Zhuo Wangc4abb042023-03-10 09:10:40 +0000743 if ((wol_switch_from_user) && (without_reset)) {
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800744 ret = stmmac_resume(dev);
745
746 if (get_resume_method() == ETH_PHY_WAKEUP) {
747 pr_info("evan---wol rx--KEY_POWER\n");
748 input_event(dwmac->input_dev,
749 EV_KEY, KEY_POWER, 1);
750 input_sync(dwmac->input_dev);
751 input_event(dwmac->input_dev,
752 EV_KEY, KEY_POWER, 0);
753 input_sync(dwmac->input_dev);
754 }
755
Zhuo Wangac9ba3d2023-03-16 05:49:04 +0000756 if (backup_adv != 0) {
757 phy_write(phydev, MII_ADVERTISE, backup_adv);
758 mii_lpa_to_linkmode_lpa_t(phydev->advertising, backup_adv);
759 genphy_restart_aneg(phydev);
760 backup_adv = 0;
761 }
762 /*RTC wait linkup*/
763 pr_info("eth hold wakelock 5s\n");
764 pm_wakeup_event(dev, 5000);
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800765 } else {
Zhuo Wangc4abb042023-03-10 09:10:40 +0000766 if (internal_phy != 2) {
767 if (dwmac->data->resume)
768 dwmac->data->resume(dwmac);
769 }
Zhuo Wang90e11992023-04-12 13:47:29 +0800770 /*our phy not support wol by now*/
771 phydev->irq_suspended = 0;
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800772 ret = stmmac_resume(dev);
Zhuo Wangc4abb042023-03-10 09:10:40 +0000773 pr_info("wzh %s\n", __func__);
774 stmmac_global_err(priv);
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800775 }
776 return ret;
777}
778
779static int meson8b_dwmac_remove(struct platform_device *pdev)
780{
781 struct net_device *ndev = platform_get_drvdata(pdev);
782 struct stmmac_priv *priv = netdev_priv(ndev);
783 int err;
784
785 struct meson8b_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev);
786
787 input_unregister_device(dwmac->input_dev);
788
789 err = stmmac_dvr_remove(&pdev->dev);
790 if (err < 0)
791 dev_err(&pdev->dev, "failed to remove platform: %d\n", err);
792
793 stmmac_remove_config_dt(pdev, priv->plat);
794
795 return err;
796}
797
798static SIMPLE_DEV_PM_OPS(meson8b_pm_ops,
799 meson8b_suspend, meson8b_resume);
800#endif
Zhuo Wang0c6d34d2022-12-16 14:40:19 +0800801#endif
Yixun Lanefacb562018-04-28 10:21:11 +0000802static const struct meson8b_dwmac_data meson8b_dwmac_data = {
803 .set_phy_mode = meson8b_set_phy_mode,
Martin Blumenstinglde94fc12021-01-06 14:42:51 +0100804 .has_prg_eth1_rgmii_rx_delay = false,
Yixun Lanefacb562018-04-28 10:21:11 +0000805};
806
807static const struct meson8b_dwmac_data meson_axg_dwmac_data = {
808 .set_phy_mode = meson_axg_set_phy_mode,
Martin Blumenstinglde94fc12021-01-06 14:42:51 +0100809 .has_prg_eth1_rgmii_rx_delay = false,
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800810#if IS_ENABLED(CONFIG_AMLOGIC_ETH_PRIVE)
Zhuo Wang0c6d34d2022-12-16 14:40:19 +0800811#ifdef CONFIG_PM_SLEEP
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800812 .suspend = dwmac_suspend,
813 .resume = dwmac_resume,
814#endif
Zhuo Wang0c6d34d2022-12-16 14:40:19 +0800815#endif
Martin Blumenstinglde94fc12021-01-06 14:42:51 +0100816};
817
818static const struct meson8b_dwmac_data meson_g12a_dwmac_data = {
819 .set_phy_mode = meson_axg_set_phy_mode,
820 .has_prg_eth1_rgmii_rx_delay = true,
Yixun Lanefacb562018-04-28 10:21:11 +0000821};
822
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200823static const struct of_device_id meson8b_dwmac_match[] = {
Yixun Lanefacb562018-04-28 10:21:11 +0000824 {
825 .compatible = "amlogic,meson8b-dwmac",
826 .data = &meson8b_dwmac_data,
827 },
828 {
829 .compatible = "amlogic,meson8m2-dwmac",
830 .data = &meson8b_dwmac_data,
831 },
832 {
833 .compatible = "amlogic,meson-gxbb-dwmac",
834 .data = &meson8b_dwmac_data,
835 },
836 {
837 .compatible = "amlogic,meson-axg-dwmac",
838 .data = &meson_axg_dwmac_data,
839 },
Martin Blumenstingla4f63342020-06-20 21:26:41 +0200840 {
841 .compatible = "amlogic,meson-g12a-dwmac",
Martin Blumenstinglde94fc12021-01-06 14:42:51 +0100842 .data = &meson_g12a_dwmac_data,
Martin Blumenstingla4f63342020-06-20 21:26:41 +0200843 },
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200844 { }
845};
846MODULE_DEVICE_TABLE(of, meson8b_dwmac_match);
847
848static struct platform_driver meson8b_dwmac_driver = {
849 .probe = meson8b_dwmac_probe,
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800850#if IS_ENABLED(CONFIG_AMLOGIC_ETH_PRIVE)
Zhuo Wang0c6d34d2022-12-16 14:40:19 +0800851#ifdef CONFIG_PM_SLEEP
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800852 .remove = meson8b_dwmac_remove,
Zhuo Wang0c6d34d2022-12-16 14:40:19 +0800853#endif
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800854#else
Martin Blumenstingl11184a52018-02-17 15:08:18 +0100855 .remove = stmmac_pltfr_remove,
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800856#endif
yao zhang1208adc62023-02-08 18:42:09 +0800857#if IS_ENABLED(CONFIG_AMLOGIC_ETH_PRIVE)
858#ifdef CONFIG_PM_SLEEP
xiangyang.yan2da0dff2023-02-07 11:31:18 +0800859 .shutdown = meson8b_dwmac_shutdown,
yao zhang1208adc62023-02-08 18:42:09 +0800860#endif
861#endif
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200862 .driver = {
863 .name = "meson8b-dwmac",
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800864#if IS_ENABLED(CONFIG_AMLOGIC_ETH_PRIVE)
Zhuo Wang0c6d34d2022-12-16 14:40:19 +0800865#ifdef CONFIG_PM_SLEEP
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800866 .pm = &meson8b_pm_ops,
Zhuo Wang0c6d34d2022-12-16 14:40:19 +0800867#endif
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800868#else
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200869 .pm = &stmmac_pltfr_pm_ops,
Zhuo Wang2dce31f2022-11-23 15:12:18 +0800870#endif
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200871 .of_match_table = meson8b_dwmac_match,
872 },
873};
874module_platform_driver(meson8b_dwmac_driver);
875
876MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
Martin Blumenstingl76766932018-03-30 01:00:35 +0200877MODULE_DESCRIPTION("Amlogic Meson8b, Meson8m2 and GXBB DWMAC glue layer");
Martin Blumenstingl566e8252016-09-06 23:38:46 +0200878MODULE_LICENSE("GPL v2");