// SPDX-License-Identifier: GPL-2.0-or-later
/*
* dwmac-sun8i.c - Allwinner sun8i DWMAC specific glue layer
*
* Copyright (C) 2017 Corentin Labbe <clabbe.montjoie@gmail.com>
*/
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/mdio-mux.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/regmap.h>
#include <linux/stmmac.h>
#include "stmmac.h"
#include "stmmac_platform.h"
/* General notes on dwmac-sun8i:
* Locking: no locking is necessary in this file because all necessary locking
* is done in the "stmmac files"
*/
/* struct emac_variant - Describe dwmac-sun8i hardware variant
* @default_syscon_value: The default value of the EMAC register in syscon
* This value is used for disabling properly EMAC
* and used as a good starting value in case of the
* boot process(uboot) leave some stuff.
* @syscon_field reg_field for the syscon's gmac register
* @soc_has_internal_phy: Does the MAC embed an internal PHY
* @support_mii: Does the MAC handle MII
* @support_rmii: Does the MAC handle RMII
* @support_rgmii: Does the MAC handle RGMII
*
* @rx_delay_max: Maximum raw value for RX delay chain
* @tx_delay_max: Maximum raw value for TX delay chain
* These two also indicate the bitmask for
* the RX and TX delay chain registers. A
* value of zero indicates this is not supported.
*/
struct emac_variant {
u32 default_syscon_value;
const struct reg_field *syscon_field;
bool soc_has_internal_phy;
bool support_mii;
bool support_rmii;
bool support_rgmii;
u8 rx_delay_max;
u8 tx_delay_max;
};
/* struct sunxi_priv_data - hold all sunxi private data
* @tx_clk: reference to MAC TX clock
* @ephy_clk: reference to the optional EPHY clock for the internal PHY
* @regulator: reference to the optional regulator
* @rst_ephy: reference to the optional EPHY reset for the internal PHY
* @variant: reference to the current board variant
* @regmap: regmap for using the syscon
* @internal_phy_powered: Does the internal PHY is enabled
* @mux_handle: Internal pointer used by mdio-mux lib
*/
struct sunxi_priv_data {
struct clk *tx_clk;
struct clk *ephy_clk;
struct regulator *regulator;
struct reset_control *rst_ephy;
const struct emac_variant *variant;
struct regmap_field *regmap_field;
bool internal_phy_powered;
void *mux_handle;
};
/* EMAC clock register @ 0x30 in the "system control" address range */
static const struct reg_field sun8i_syscon_reg_field = {
.reg = 0x30,
.lsb = 0,
.msb = 31,
};
/* EMAC clock register @ 0x164 in the CCU address range */
static const struct reg_field sun8i_ccu_reg_field = {
.reg = 0x164,
.lsb = 0,
.msb = 31,
};
static const struct emac_variant emac_variant_h3 = {
.default_syscon_value = 0x58000,
.syscon_field = &sun8i_syscon_reg_field,
.soc_has_internal_phy = true,
.support_mii = true,
.support_rmii = true,
.support_rgmii = true,
.rx_delay_max = 31,
.tx_delay_max = 7,
};
static const struct emac_variant emac_variant_v3s = {
.default_syscon_value = 0x38000,
.syscon_field = &sun8i_syscon_reg_field,
.soc_has_internal_phy = true,
.support_mii = true
};