Lines Matching +full:meson +full:- +full:gxbb +full:- +full:dwmac
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Amlogic Meson8b, Meson8m2 and GXBB DWMAC glue layer
10 #include <linux/clk-provider.h>
60 /* An internal counter based on the "timing-adjustment" clock. The counter is
74 int (*set_phy_mode)(struct meson8b_dwmac *dwmac);
96 static void meson8b_dwmac_mask_bits(struct meson8b_dwmac *dwmac, u32 reg, in meson8b_dwmac_mask_bits() argument
101 data = readl(dwmac->regs + reg); in meson8b_dwmac_mask_bits()
105 writel(data, dwmac->regs + reg); in meson8b_dwmac_mask_bits()
108 static struct clk *meson8b_dwmac_register_clk(struct meson8b_dwmac *dwmac, in meson8b_dwmac_register_clk() argument
118 snprintf(clk_name, sizeof(clk_name), "%s#%s", dev_name(dwmac->dev), in meson8b_dwmac_register_clk()
127 hw->init = &init; in meson8b_dwmac_register_clk()
129 return devm_clk_register(dwmac->dev, hw); in meson8b_dwmac_register_clk()
132 static int meson8b_init_rgmii_tx_clk(struct meson8b_dwmac *dwmac) in meson8b_init_rgmii_tx_clk() argument
135 struct device *dev = dwmac->dev; in meson8b_init_rgmii_tx_clk()
154 return -ENOMEM; in meson8b_init_rgmii_tx_clk()
156 clk_configs->m250_mux.reg = dwmac->regs + PRG_ETH0; in meson8b_init_rgmii_tx_clk()
157 clk_configs->m250_mux.shift = __ffs(PRG_ETH0_CLK_M250_SEL_MASK); in meson8b_init_rgmii_tx_clk()
158 clk_configs->m250_mux.mask = PRG_ETH0_CLK_M250_SEL_MASK >> in meson8b_init_rgmii_tx_clk()
159 clk_configs->m250_mux.shift; in meson8b_init_rgmii_tx_clk()
160 clk = meson8b_dwmac_register_clk(dwmac, "m250_sel", mux_parents, in meson8b_init_rgmii_tx_clk()
162 &clk_configs->m250_mux.hw); in meson8b_init_rgmii_tx_clk()
166 parent_data.hw = &clk_configs->m250_mux.hw; in meson8b_init_rgmii_tx_clk()
167 clk_configs->m250_div.reg = dwmac->regs + PRG_ETH0; in meson8b_init_rgmii_tx_clk()
168 clk_configs->m250_div.shift = PRG_ETH0_CLK_M250_DIV_SHIFT; in meson8b_init_rgmii_tx_clk()
169 clk_configs->m250_div.width = PRG_ETH0_CLK_M250_DIV_WIDTH; in meson8b_init_rgmii_tx_clk()
170 clk_configs->m250_div.table = div_table; in meson8b_init_rgmii_tx_clk()
171 clk_configs->m250_div.flags = CLK_DIVIDER_ALLOW_ZERO | in meson8b_init_rgmii_tx_clk()
173 clk = meson8b_dwmac_register_clk(dwmac, "m250_div", &parent_data, 1, in meson8b_init_rgmii_tx_clk()
175 &clk_configs->m250_div.hw); in meson8b_init_rgmii_tx_clk()
179 parent_data.hw = &clk_configs->m250_div.hw; in meson8b_init_rgmii_tx_clk()
180 clk_configs->fixed_div2.mult = 1; in meson8b_init_rgmii_tx_clk()
181 clk_configs->fixed_div2.div = 2; in meson8b_init_rgmii_tx_clk()
182 clk = meson8b_dwmac_register_clk(dwmac, "fixed_div2", &parent_data, 1, in meson8b_init_rgmii_tx_clk()
184 &clk_configs->fixed_div2.hw); in meson8b_init_rgmii_tx_clk()
188 parent_data.hw = &clk_configs->fixed_div2.hw; in meson8b_init_rgmii_tx_clk()
189 clk_configs->rgmii_tx_en.reg = dwmac->regs + PRG_ETH0; in meson8b_init_rgmii_tx_clk()
190 clk_configs->rgmii_tx_en.bit_idx = PRG_ETH0_RGMII_TX_CLK_EN; in meson8b_init_rgmii_tx_clk()
191 clk = meson8b_dwmac_register_clk(dwmac, "rgmii_tx_en", &parent_data, 1, in meson8b_init_rgmii_tx_clk()
193 &clk_configs->rgmii_tx_en.hw); in meson8b_init_rgmii_tx_clk()
197 dwmac->rgmii_tx_clk = clk; in meson8b_init_rgmii_tx_clk()
202 static int meson8b_set_phy_mode(struct meson8b_dwmac *dwmac) in meson8b_set_phy_mode() argument
204 switch (dwmac->phy_mode) { in meson8b_set_phy_mode()
210 meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, in meson8b_set_phy_mode()
215 /* disable RGMII mode -> enables RMII mode */ in meson8b_set_phy_mode()
216 meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, in meson8b_set_phy_mode()
220 dev_err(dwmac->dev, "fail to set phy-mode %s\n", in meson8b_set_phy_mode()
221 phy_modes(dwmac->phy_mode)); in meson8b_set_phy_mode()
222 return -EINVAL; in meson8b_set_phy_mode()
228 static int meson_axg_set_phy_mode(struct meson8b_dwmac *dwmac) in meson_axg_set_phy_mode() argument
230 switch (dwmac->phy_mode) { in meson_axg_set_phy_mode()
236 meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, in meson_axg_set_phy_mode()
241 /* disable RGMII mode -> enables RMII mode */ in meson_axg_set_phy_mode()
242 meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, in meson_axg_set_phy_mode()
247 dev_err(dwmac->dev, "fail to set phy-mode %s\n", in meson_axg_set_phy_mode()
248 phy_modes(dwmac->phy_mode)); in meson_axg_set_phy_mode()
249 return -EINVAL; in meson_axg_set_phy_mode()
255 static int meson8b_devm_clk_prepare_enable(struct meson8b_dwmac *dwmac, in meson8b_devm_clk_prepare_enable() argument
264 devm_add_action_or_reset(dwmac->dev, in meson8b_devm_clk_prepare_enable()
266 dwmac->rgmii_tx_clk); in meson8b_devm_clk_prepare_enable()
271 static int meson8b_init_prg_eth(struct meson8b_dwmac *dwmac) in meson8b_init_prg_eth() argument
277 dwmac->tx_delay_ns >> 1); in meson8b_init_prg_eth()
279 if (dwmac->rx_delay_ns == 2) in meson8b_init_prg_eth()
284 switch (dwmac->phy_mode) { in meson8b_init_prg_eth()
299 dev_err(dwmac->dev, "unsupported phy-mode %s\n", in meson8b_init_prg_eth()
300 phy_modes(dwmac->phy_mode)); in meson8b_init_prg_eth()
301 return -EINVAL; in meson8b_init_prg_eth()
305 if (!dwmac->timing_adj_clk) { in meson8b_init_prg_eth()
306 dev_err(dwmac->dev, in meson8b_init_prg_eth()
307 "The timing-adjustment clock is mandatory for the RX delay re-timing\n"); in meson8b_init_prg_eth()
308 return -EINVAL; in meson8b_init_prg_eth()
312 ret = meson8b_devm_clk_prepare_enable(dwmac, in meson8b_init_prg_eth()
313 dwmac->timing_adj_clk); in meson8b_init_prg_eth()
315 dev_err(dwmac->dev, in meson8b_init_prg_eth()
316 "Failed to enable the timing-adjustment clock\n"); in meson8b_init_prg_eth()
321 meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TXDLY_MASK | in meson8b_init_prg_eth()
326 if (phy_interface_mode_is_rgmii(dwmac->phy_mode)) { in meson8b_init_prg_eth()
327 /* only relevant for RMII mode -> disable in RGMII mode */ in meson8b_init_prg_eth()
328 meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, in meson8b_init_prg_eth()
333 * a register) based on the line-speed (125MHz for Gbit speeds, in meson8b_init_prg_eth()
336 ret = clk_set_rate(dwmac->rgmii_tx_clk, 125 * 1000 * 1000); in meson8b_init_prg_eth()
338 dev_err(dwmac->dev, in meson8b_init_prg_eth()
343 ret = meson8b_devm_clk_prepare_enable(dwmac, in meson8b_init_prg_eth()
344 dwmac->rgmii_tx_clk); in meson8b_init_prg_eth()
346 dev_err(dwmac->dev, in meson8b_init_prg_eth()
352 meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, in meson8b_init_prg_eth()
358 meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TX_AND_PHY_REF_CLK, in meson8b_init_prg_eth()
368 struct meson8b_dwmac *dwmac; in meson8b_dwmac_probe() local
379 dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); in meson8b_dwmac_probe()
380 if (!dwmac) { in meson8b_dwmac_probe()
381 ret = -ENOMEM; in meson8b_dwmac_probe()
385 dwmac->data = (const struct meson8b_dwmac_data *) in meson8b_dwmac_probe()
386 of_device_get_match_data(&pdev->dev); in meson8b_dwmac_probe()
387 if (!dwmac->data) { in meson8b_dwmac_probe()
388 ret = -EINVAL; in meson8b_dwmac_probe()
391 dwmac->regs = devm_platform_ioremap_resource(pdev, 1); in meson8b_dwmac_probe()
392 if (IS_ERR(dwmac->regs)) { in meson8b_dwmac_probe()
393 ret = PTR_ERR(dwmac->regs); in meson8b_dwmac_probe()
397 dwmac->dev = &pdev->dev; in meson8b_dwmac_probe()
398 ret = of_get_phy_mode(pdev->dev.of_node, &dwmac->phy_mode); in meson8b_dwmac_probe()
400 dev_err(&pdev->dev, "missing phy-mode property\n"); in meson8b_dwmac_probe()
405 if (of_property_read_u32(pdev->dev.of_node, "amlogic,tx-delay-ns", in meson8b_dwmac_probe()
406 &dwmac->tx_delay_ns)) in meson8b_dwmac_probe()
407 dwmac->tx_delay_ns = 2; in meson8b_dwmac_probe()
410 if (of_property_read_u32(pdev->dev.of_node, "amlogic,rx-delay-ns", in meson8b_dwmac_probe()
411 &dwmac->rx_delay_ns)) in meson8b_dwmac_probe()
412 dwmac->rx_delay_ns = 0; in meson8b_dwmac_probe()
414 if (dwmac->rx_delay_ns != 0 && dwmac->rx_delay_ns != 2) { in meson8b_dwmac_probe()
415 dev_err(&pdev->dev, in meson8b_dwmac_probe()
417 ret = -EINVAL; in meson8b_dwmac_probe()
421 dwmac->timing_adj_clk = devm_clk_get_optional(dwmac->dev, in meson8b_dwmac_probe()
422 "timing-adjustment"); in meson8b_dwmac_probe()
423 if (IS_ERR(dwmac->timing_adj_clk)) { in meson8b_dwmac_probe()
424 ret = PTR_ERR(dwmac->timing_adj_clk); in meson8b_dwmac_probe()
428 ret = meson8b_init_rgmii_tx_clk(dwmac); in meson8b_dwmac_probe()
432 ret = dwmac->data->set_phy_mode(dwmac); in meson8b_dwmac_probe()
436 ret = meson8b_init_prg_eth(dwmac); in meson8b_dwmac_probe()
440 plat_dat->bsp_priv = dwmac; in meson8b_dwmac_probe()
442 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); in meson8b_dwmac_probe()
464 .compatible = "amlogic,meson8b-dwmac",
468 .compatible = "amlogic,meson8m2-dwmac",
472 .compatible = "amlogic,meson-gxbb-dwmac",
476 .compatible = "amlogic,meson-axg-dwmac",
480 .compatible = "amlogic,meson-g12a-dwmac",
491 .name = "meson8b-dwmac",
499 MODULE_DESCRIPTION("Amlogic Meson8b, Meson8m2 and GXBB DWMAC glue layer");