0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/module.h>
0009 #include <linux/of_device.h>
0010 #include <linux/of_net.h>
0011 #include <linux/stmmac.h>
0012
0013 #include "stmmac_platform.h"
0014 #include "dwmac4.h"
0015
0016 #define REG_ETHER_CONTROL 0x52D4
0017 #define ETHER_ETH_CONTROL_RESET BIT(17)
0018
0019 #define REG_ETHER_CLOCK_SEL 0x52D0
0020 #define ETHER_CLK_SEL_TX_CLK_EN BIT(0)
0021 #define ETHER_CLK_SEL_RX_CLK_EN BIT(1)
0022 #define ETHER_CLK_SEL_RMII_CLK_EN BIT(2)
0023 #define ETHER_CLK_SEL_RMII_CLK_RST BIT(3)
0024 #define ETHER_CLK_SEL_DIV_SEL_2 BIT(4)
0025 #define ETHER_CLK_SEL_DIV_SEL_20 0
0026 #define ETHER_CLK_SEL_FREQ_SEL_125M (BIT(9) | BIT(8))
0027 #define ETHER_CLK_SEL_FREQ_SEL_50M BIT(9)
0028 #define ETHER_CLK_SEL_FREQ_SEL_25M BIT(8)
0029 #define ETHER_CLK_SEL_FREQ_SEL_2P5M 0
0030 #define ETHER_CLK_SEL_TX_CLK_EXT_SEL_IN 0
0031 #define ETHER_CLK_SEL_TX_CLK_EXT_SEL_TXC BIT(10)
0032 #define ETHER_CLK_SEL_TX_CLK_EXT_SEL_DIV BIT(11)
0033 #define ETHER_CLK_SEL_RX_CLK_EXT_SEL_IN 0
0034 #define ETHER_CLK_SEL_RX_CLK_EXT_SEL_RXC BIT(12)
0035 #define ETHER_CLK_SEL_RX_CLK_EXT_SEL_DIV BIT(13)
0036 #define ETHER_CLK_SEL_TX_CLK_O_TX_I 0
0037 #define ETHER_CLK_SEL_TX_CLK_O_RMII_I BIT(14)
0038 #define ETHER_CLK_SEL_TX_O_E_N_IN BIT(15)
0039 #define ETHER_CLK_SEL_RMII_CLK_SEL_IN 0
0040 #define ETHER_CLK_SEL_RMII_CLK_SEL_RX_C BIT(16)
0041
0042 #define ETHER_CLK_SEL_RX_TX_CLK_EN (ETHER_CLK_SEL_RX_CLK_EN | ETHER_CLK_SEL_TX_CLK_EN)
0043
0044 #define ETHER_CONFIG_INTF_MII 0
0045 #define ETHER_CONFIG_INTF_RGMII BIT(0)
0046 #define ETHER_CONFIG_INTF_RMII BIT(2)
0047
0048 struct visconti_eth {
0049 void __iomem *reg;
0050 u32 phy_intf_sel;
0051 struct clk *phy_ref_clk;
0052 struct device *dev;
0053 spinlock_t lock;
0054 };
0055
0056 static void visconti_eth_fix_mac_speed(void *priv, unsigned int speed)
0057 {
0058 struct visconti_eth *dwmac = priv;
0059 struct net_device *netdev = dev_get_drvdata(dwmac->dev);
0060 unsigned int val, clk_sel_val = 0;
0061 unsigned long flags;
0062
0063 spin_lock_irqsave(&dwmac->lock, flags);
0064
0065
0066 val = readl(dwmac->reg + MAC_CTRL_REG);
0067 val &= ~(GMAC_CONFIG_PS | GMAC_CONFIG_FES);
0068
0069 switch (speed) {
0070 case SPEED_1000:
0071 if (dwmac->phy_intf_sel == ETHER_CONFIG_INTF_RGMII)
0072 clk_sel_val = ETHER_CLK_SEL_FREQ_SEL_125M;
0073 break;
0074 case SPEED_100:
0075 if (dwmac->phy_intf_sel == ETHER_CONFIG_INTF_RGMII)
0076 clk_sel_val = ETHER_CLK_SEL_FREQ_SEL_25M;
0077 if (dwmac->phy_intf_sel == ETHER_CONFIG_INTF_RMII)
0078 clk_sel_val = ETHER_CLK_SEL_DIV_SEL_2;
0079 val |= GMAC_CONFIG_PS | GMAC_CONFIG_FES;
0080 break;
0081 case SPEED_10:
0082 if (dwmac->phy_intf_sel == ETHER_CONFIG_INTF_RGMII)
0083 clk_sel_val = ETHER_CLK_SEL_FREQ_SEL_2P5M;
0084 if (dwmac->phy_intf_sel == ETHER_CONFIG_INTF_RMII)
0085 clk_sel_val = ETHER_CLK_SEL_DIV_SEL_20;
0086 val |= GMAC_CONFIG_PS;
0087 break;
0088 default:
0089
0090 netdev_err(netdev, "Unsupported speed request (%d)", speed);
0091 spin_unlock_irqrestore(&dwmac->lock, flags);
0092 return;
0093 }
0094
0095 writel(val, dwmac->reg + MAC_CTRL_REG);
0096
0097
0098 val = readl(dwmac->reg + REG_ETHER_CLOCK_SEL);
0099 val &= ~(ETHER_CLK_SEL_RMII_CLK_EN | ETHER_CLK_SEL_RX_TX_CLK_EN);
0100 val |= ETHER_CLK_SEL_TX_O_E_N_IN;
0101 writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);
0102
0103
0104 switch (dwmac->phy_intf_sel) {
0105 case ETHER_CONFIG_INTF_RGMII:
0106 val = clk_sel_val | ETHER_CLK_SEL_RX_CLK_EXT_SEL_RXC;
0107 writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);
0108
0109 val |= ETHER_CLK_SEL_RX_TX_CLK_EN;
0110 writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);
0111
0112 val &= ~ETHER_CLK_SEL_TX_O_E_N_IN;
0113 writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);
0114 break;
0115 case ETHER_CONFIG_INTF_RMII:
0116 val = clk_sel_val | ETHER_CLK_SEL_RX_CLK_EXT_SEL_DIV |
0117 ETHER_CLK_SEL_TX_CLK_EXT_SEL_DIV | ETHER_CLK_SEL_TX_O_E_N_IN |
0118 ETHER_CLK_SEL_RMII_CLK_SEL_RX_C;
0119 writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);
0120
0121 val |= ETHER_CLK_SEL_RMII_CLK_RST;
0122 writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);
0123
0124 val |= ETHER_CLK_SEL_RMII_CLK_EN | ETHER_CLK_SEL_RX_TX_CLK_EN;
0125 writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);
0126 break;
0127 case ETHER_CONFIG_INTF_MII:
0128 default:
0129 val = clk_sel_val | ETHER_CLK_SEL_RX_CLK_EXT_SEL_RXC |
0130 ETHER_CLK_SEL_TX_CLK_EXT_SEL_TXC | ETHER_CLK_SEL_TX_O_E_N_IN;
0131 writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);
0132
0133 val |= ETHER_CLK_SEL_RX_TX_CLK_EN;
0134 writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);
0135 break;
0136 }
0137
0138 spin_unlock_irqrestore(&dwmac->lock, flags);
0139 }
0140
0141 static int visconti_eth_init_hw(struct platform_device *pdev, struct plat_stmmacenet_data *plat_dat)
0142 {
0143 struct visconti_eth *dwmac = plat_dat->bsp_priv;
0144 unsigned int reg_val, clk_sel_val;
0145
0146 switch (plat_dat->phy_interface) {
0147 case PHY_INTERFACE_MODE_RGMII:
0148 case PHY_INTERFACE_MODE_RGMII_ID:
0149 case PHY_INTERFACE_MODE_RGMII_RXID:
0150 case PHY_INTERFACE_MODE_RGMII_TXID:
0151 dwmac->phy_intf_sel = ETHER_CONFIG_INTF_RGMII;
0152 break;
0153 case PHY_INTERFACE_MODE_MII:
0154 dwmac->phy_intf_sel = ETHER_CONFIG_INTF_MII;
0155 break;
0156 case PHY_INTERFACE_MODE_RMII:
0157 dwmac->phy_intf_sel = ETHER_CONFIG_INTF_RMII;
0158 break;
0159 default:
0160 dev_err(&pdev->dev, "Unsupported phy-mode (%d)\n", plat_dat->phy_interface);
0161 return -EOPNOTSUPP;
0162 }
0163
0164 reg_val = dwmac->phy_intf_sel;
0165 writel(reg_val, dwmac->reg + REG_ETHER_CONTROL);
0166
0167
0168 clk_sel_val = ETHER_CLK_SEL_FREQ_SEL_125M;
0169 writel(clk_sel_val, dwmac->reg + REG_ETHER_CLOCK_SEL);
0170
0171 writel((clk_sel_val | ETHER_CLK_SEL_RMII_CLK_EN | ETHER_CLK_SEL_RX_TX_CLK_EN),
0172 dwmac->reg + REG_ETHER_CLOCK_SEL);
0173
0174
0175 reg_val |= ETHER_ETH_CONTROL_RESET;
0176 writel(reg_val, dwmac->reg + REG_ETHER_CONTROL);
0177
0178 return 0;
0179 }
0180
0181 static int visconti_eth_clock_probe(struct platform_device *pdev,
0182 struct plat_stmmacenet_data *plat_dat)
0183 {
0184 struct visconti_eth *dwmac = plat_dat->bsp_priv;
0185 int err;
0186
0187 dwmac->phy_ref_clk = devm_clk_get(&pdev->dev, "phy_ref_clk");
0188 if (IS_ERR(dwmac->phy_ref_clk))
0189 return dev_err_probe(&pdev->dev, PTR_ERR(dwmac->phy_ref_clk),
0190 "phy_ref_clk clock not found.\n");
0191
0192 err = clk_prepare_enable(dwmac->phy_ref_clk);
0193 if (err < 0) {
0194 dev_err(&pdev->dev, "failed to enable phy_ref clock: %d\n", err);
0195 return err;
0196 }
0197
0198 return 0;
0199 }
0200
0201 static int visconti_eth_clock_remove(struct platform_device *pdev)
0202 {
0203 struct visconti_eth *dwmac = get_stmmac_bsp_priv(&pdev->dev);
0204 struct net_device *ndev = platform_get_drvdata(pdev);
0205 struct stmmac_priv *priv = netdev_priv(ndev);
0206
0207 clk_disable_unprepare(dwmac->phy_ref_clk);
0208 clk_disable_unprepare(priv->plat->stmmac_clk);
0209
0210 return 0;
0211 }
0212
0213 static int visconti_eth_dwmac_probe(struct platform_device *pdev)
0214 {
0215 struct plat_stmmacenet_data *plat_dat;
0216 struct stmmac_resources stmmac_res;
0217 struct visconti_eth *dwmac;
0218 int ret;
0219
0220 ret = stmmac_get_platform_resources(pdev, &stmmac_res);
0221 if (ret)
0222 return ret;
0223
0224 plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
0225 if (IS_ERR(plat_dat))
0226 return PTR_ERR(plat_dat);
0227
0228 dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
0229 if (!dwmac) {
0230 ret = -ENOMEM;
0231 goto remove_config;
0232 }
0233
0234 spin_lock_init(&dwmac->lock);
0235 dwmac->reg = stmmac_res.addr;
0236 dwmac->dev = &pdev->dev;
0237 plat_dat->bsp_priv = dwmac;
0238 plat_dat->fix_mac_speed = visconti_eth_fix_mac_speed;
0239
0240 ret = visconti_eth_clock_probe(pdev, plat_dat);
0241 if (ret)
0242 goto remove_config;
0243
0244 visconti_eth_init_hw(pdev, plat_dat);
0245
0246 plat_dat->dma_cfg->aal = 1;
0247
0248 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
0249 if (ret)
0250 goto remove;
0251
0252 return ret;
0253
0254 remove:
0255 visconti_eth_clock_remove(pdev);
0256 remove_config:
0257 stmmac_remove_config_dt(pdev, plat_dat);
0258
0259 return ret;
0260 }
0261
0262 static int visconti_eth_dwmac_remove(struct platform_device *pdev)
0263 {
0264 struct net_device *ndev = platform_get_drvdata(pdev);
0265 struct stmmac_priv *priv = netdev_priv(ndev);
0266 int err;
0267
0268 err = stmmac_pltfr_remove(pdev);
0269 if (err < 0)
0270 dev_err(&pdev->dev, "failed to remove platform: %d\n", err);
0271
0272 err = visconti_eth_clock_remove(pdev);
0273 if (err < 0)
0274 dev_err(&pdev->dev, "failed to remove clock: %d\n", err);
0275
0276 stmmac_remove_config_dt(pdev, priv->plat);
0277
0278 return err;
0279 }
0280
0281 static const struct of_device_id visconti_eth_dwmac_match[] = {
0282 { .compatible = "toshiba,visconti-dwmac" },
0283 { }
0284 };
0285 MODULE_DEVICE_TABLE(of, visconti_eth_dwmac_match);
0286
0287 static struct platform_driver visconti_eth_dwmac_driver = {
0288 .probe = visconti_eth_dwmac_probe,
0289 .remove = visconti_eth_dwmac_remove,
0290 .driver = {
0291 .name = "visconti-eth-dwmac",
0292 .of_match_table = visconti_eth_dwmac_match,
0293 },
0294 };
0295 module_platform_driver(visconti_eth_dwmac_driver);
0296
0297 MODULE_AUTHOR("Toshiba");
0298 MODULE_DESCRIPTION("Toshiba Visconti Ethernet DWMAC glue driver");
0299 MODULE_AUTHOR("Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp");
0300 MODULE_LICENSE("GPL v2");