X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fopenwrt.git;a=blobdiff_plain;f=target%2Flinux%2Fmediatek%2Ffiles%2Fdrivers%2Fnet%2Fphy%2Fmtk%2Fmt753x%2Fmt753x_mdio.c;fp=target%2Flinux%2Fmediatek%2Ffiles%2Fdrivers%2Fnet%2Fphy%2Fmtk%2Fmt753x%2Fmt753x_mdio.c;h=0000000000000000000000000000000000000000;hp=3e2e6d68aed46e91c5e0eeb8e5d226590ac3da62;hb=ec6f80663ed80e50844d0c032121e0bec46ff297;hpb=2c530fcb972c112e7a2b10f9c21ac6d276624b5e diff --git a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_mdio.c b/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_mdio.c deleted file mode 100644 index 3e2e6d68ae..0000000000 --- a/target/linux/mediatek/files/drivers/net/phy/mtk/mt753x/mt753x_mdio.c +++ /dev/null @@ -1,597 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2018 MediaTek Inc. - * Author: Weijie Gao - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mt753x.h" -#include "mt753x_swconfig.h" -#include "mt753x_regs.h" -#include "mt753x_nl.h" -#include "mt7530.h" -#include "mt7531.h" - -static u32 mt753x_id; -struct list_head mt753x_devs; -static DEFINE_MUTEX(mt753x_devs_lock); - -static struct mt753x_sw_id *mt753x_sw_ids[] = { - &mt7530_id, - &mt7531_id, -}; - -u32 mt753x_reg_read(struct gsw_mt753x *gsw, u32 reg) -{ - u32 high, low; - - mutex_lock(&gsw->host_bus->mdio_lock); - - gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f, - (reg & MT753X_REG_PAGE_ADDR_M) >> MT753X_REG_PAGE_ADDR_S); - - low = gsw->host_bus->read(gsw->host_bus, gsw->smi_addr, - (reg & MT753X_REG_ADDR_M) >> MT753X_REG_ADDR_S); - - high = gsw->host_bus->read(gsw->host_bus, gsw->smi_addr, 0x10); - - mutex_unlock(&gsw->host_bus->mdio_lock); - - return (high << 16) | (low & 0xffff); -} - -void mt753x_reg_write(struct gsw_mt753x *gsw, u32 reg, u32 val) -{ - mutex_lock(&gsw->host_bus->mdio_lock); - - gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x1f, - (reg & MT753X_REG_PAGE_ADDR_M) >> MT753X_REG_PAGE_ADDR_S); - - gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, - (reg & MT753X_REG_ADDR_M) >> MT753X_REG_ADDR_S, val & 0xffff); - - gsw->host_bus->write(gsw->host_bus, gsw->smi_addr, 0x10, val >> 16); - - mutex_unlock(&gsw->host_bus->mdio_lock); -} - -/* Indirect MDIO clause 22/45 access */ -static int mt753x_mii_rw(struct gsw_mt753x *gsw, int phy, int reg, u16 data, - u32 cmd, u32 st) -{ - ktime_t timeout; - u32 val, timeout_us; - int ret = 0; - - timeout_us = 100000; - timeout = ktime_add_us(ktime_get(), timeout_us); - while (1) { - val = mt753x_reg_read(gsw, PHY_IAC); - - if ((val & PHY_ACS_ST) == 0) - break; - - if (ktime_compare(ktime_get(), timeout) > 0) - return -ETIMEDOUT; - } - - val = (st << MDIO_ST_S) | - ((cmd << MDIO_CMD_S) & MDIO_CMD_M) | - ((phy << MDIO_PHY_ADDR_S) & MDIO_PHY_ADDR_M) | - ((reg << MDIO_REG_ADDR_S) & MDIO_REG_ADDR_M); - - if (cmd == MDIO_CMD_WRITE || cmd == MDIO_CMD_ADDR) - val |= data & MDIO_RW_DATA_M; - - mt753x_reg_write(gsw, PHY_IAC, val | PHY_ACS_ST); - - timeout_us = 100000; - timeout = ktime_add_us(ktime_get(), timeout_us); - while (1) { - val = mt753x_reg_read(gsw, PHY_IAC); - - if ((val & PHY_ACS_ST) == 0) - break; - - if (ktime_compare(ktime_get(), timeout) > 0) - return -ETIMEDOUT; - } - - if (cmd == MDIO_CMD_READ || cmd == MDIO_CMD_READ_C45) { - val = mt753x_reg_read(gsw, PHY_IAC); - ret = val & MDIO_RW_DATA_M; - } - - return ret; -} - -int mt753x_mii_read(struct gsw_mt753x *gsw, int phy, int reg) -{ - int val; - - if (phy < MT753X_NUM_PHYS) - phy = (gsw->phy_base + phy) & MT753X_SMI_ADDR_MASK; - - mutex_lock(&gsw->mii_lock); - val = mt753x_mii_rw(gsw, phy, reg, 0, MDIO_CMD_READ, MDIO_ST_C22); - mutex_unlock(&gsw->mii_lock); - - return val; -} - -void mt753x_mii_write(struct gsw_mt753x *gsw, int phy, int reg, u16 val) -{ - if (phy < MT753X_NUM_PHYS) - phy = (gsw->phy_base + phy) & MT753X_SMI_ADDR_MASK; - - mutex_lock(&gsw->mii_lock); - mt753x_mii_rw(gsw, phy, reg, val, MDIO_CMD_WRITE, MDIO_ST_C22); - mutex_unlock(&gsw->mii_lock); -} - -int mt753x_mmd_read(struct gsw_mt753x *gsw, int addr, int devad, u16 reg) -{ - int val; - - if (addr < MT753X_NUM_PHYS) - addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK; - - mutex_lock(&gsw->mii_lock); - mt753x_mii_rw(gsw, addr, devad, reg, MDIO_CMD_ADDR, MDIO_ST_C45); - val = mt753x_mii_rw(gsw, addr, devad, 0, MDIO_CMD_READ_C45, - MDIO_ST_C45); - mutex_unlock(&gsw->mii_lock); - - return val; -} - -void mt753x_mmd_write(struct gsw_mt753x *gsw, int addr, int devad, u16 reg, - u16 val) -{ - if (addr < MT753X_NUM_PHYS) - addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK; - - mutex_lock(&gsw->mii_lock); - mt753x_mii_rw(gsw, addr, devad, reg, MDIO_CMD_ADDR, MDIO_ST_C45); - mt753x_mii_rw(gsw, addr, devad, val, MDIO_CMD_WRITE, MDIO_ST_C45); - mutex_unlock(&gsw->mii_lock); -} - -int mt753x_mmd_ind_read(struct gsw_mt753x *gsw, int addr, int devad, u16 reg) -{ - u16 val; - - if (addr < MT753X_NUM_PHYS) - addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK; - - mutex_lock(&gsw->mii_lock); - - mt753x_mii_rw(gsw, addr, MII_MMD_ACC_CTL_REG, - (MMD_ADDR << MMD_CMD_S) | - ((devad << MMD_DEVAD_S) & MMD_DEVAD_M), - MDIO_CMD_WRITE, MDIO_ST_C22); - - mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, reg, - MDIO_CMD_WRITE, MDIO_ST_C22); - - mt753x_mii_rw(gsw, addr, MII_MMD_ACC_CTL_REG, - (MMD_DATA << MMD_CMD_S) | - ((devad << MMD_DEVAD_S) & MMD_DEVAD_M), - MDIO_CMD_WRITE, MDIO_ST_C22); - - val = mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, 0, - MDIO_CMD_READ, MDIO_ST_C22); - - mutex_unlock(&gsw->mii_lock); - - return val; -} - -void mt753x_mmd_ind_write(struct gsw_mt753x *gsw, int addr, int devad, u16 reg, - u16 val) -{ - if (addr < MT753X_NUM_PHYS) - addr = (gsw->phy_base + addr) & MT753X_SMI_ADDR_MASK; - - mutex_lock(&gsw->mii_lock); - - mt753x_mii_rw(gsw, addr, MII_MMD_ACC_CTL_REG, - (MMD_ADDR << MMD_CMD_S) | - ((devad << MMD_DEVAD_S) & MMD_DEVAD_M), - MDIO_CMD_WRITE, MDIO_ST_C22); - - mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, reg, - MDIO_CMD_WRITE, MDIO_ST_C22); - - mt753x_mii_rw(gsw, addr, MII_MMD_ACC_CTL_REG, - (MMD_DATA << MMD_CMD_S) | - ((devad << MMD_DEVAD_S) & MMD_DEVAD_M), - MDIO_CMD_WRITE, MDIO_ST_C22); - - mt753x_mii_rw(gsw, addr, MII_MMD_ADDR_DATA_REG, val, - MDIO_CMD_WRITE, MDIO_ST_C22); - - mutex_unlock(&gsw->mii_lock); -} - -static inline int mt753x_get_duplex(const struct device_node *np) -{ - return of_property_read_bool(np, "full-duplex"); -} - -static void mt753x_load_port_cfg(struct gsw_mt753x *gsw) -{ - struct device_node *port_np; - struct device_node *fixed_link_node; - struct mt753x_port_cfg *port_cfg; - u32 port; - - for_each_child_of_node(gsw->dev->of_node, port_np) { - if (!of_device_is_compatible(port_np, "mediatek,mt753x-port")) - continue; - - if (!of_device_is_available(port_np)) - continue; - - if (of_property_read_u32(port_np, "reg", &port)) - continue; - - switch (port) { - case 5: - port_cfg = &gsw->port5_cfg; - break; - case 6: - port_cfg = &gsw->port6_cfg; - break; - default: - continue; - } - - if (port_cfg->enabled) { - dev_info(gsw->dev, "duplicated node for port%d\n", - port_cfg->phy_mode); - continue; - } - - port_cfg->np = port_np; - - if (of_get_phy_mode(port_np, &port_cfg->phy_mode) < 0) { - dev_info(gsw->dev, "incorrect phy-mode %d\n", port); - continue; - } - - fixed_link_node = of_get_child_by_name(port_np, "fixed-link"); - if (fixed_link_node) { - u32 speed; - - port_cfg->force_link = 1; - port_cfg->duplex = mt753x_get_duplex(fixed_link_node); - - if (of_property_read_u32(fixed_link_node, "speed", - &speed)) { - speed = 0; - continue; - } - - of_node_put(fixed_link_node); - - switch (speed) { - case 10: - port_cfg->speed = MAC_SPD_10; - break; - case 100: - port_cfg->speed = MAC_SPD_100; - break; - case 1000: - port_cfg->speed = MAC_SPD_1000; - break; - case 2500: - port_cfg->speed = MAC_SPD_2500; - break; - default: - dev_info(gsw->dev, "incorrect speed %d\n", - speed); - continue; - } - } - - port_cfg->enabled = 1; - } -} - -static void mt753x_add_gsw(struct gsw_mt753x *gsw) -{ - mutex_lock(&mt753x_devs_lock); - gsw->id = mt753x_id++; - INIT_LIST_HEAD(&gsw->list); - list_add_tail(&gsw->list, &mt753x_devs); - mutex_unlock(&mt753x_devs_lock); -} - -static void mt753x_remove_gsw(struct gsw_mt753x *gsw) -{ - mutex_lock(&mt753x_devs_lock); - list_del(&gsw->list); - mutex_unlock(&mt753x_devs_lock); -} - - -struct gsw_mt753x *mt753x_get_gsw(u32 id) -{ - struct gsw_mt753x *dev; - - mutex_lock(&mt753x_devs_lock); - - list_for_each_entry(dev, &mt753x_devs, list) { - if (dev->id == id) - return dev; - } - - mutex_unlock(&mt753x_devs_lock); - - return NULL; -} - -struct gsw_mt753x *mt753x_get_first_gsw(void) -{ - struct gsw_mt753x *dev; - - mutex_lock(&mt753x_devs_lock); - - list_for_each_entry(dev, &mt753x_devs, list) - return dev; - - mutex_unlock(&mt753x_devs_lock); - - return NULL; -} - -void mt753x_put_gsw(void) -{ - mutex_unlock(&mt753x_devs_lock); -} - -void mt753x_lock_gsw(void) -{ - mutex_lock(&mt753x_devs_lock); -} - -static int mt753x_hw_reset(struct gsw_mt753x *gsw) -{ - struct device_node *np = gsw->dev->of_node; - struct reset_control *rstc; - int mcm; - int ret = -EINVAL; - - mcm = of_property_read_bool(np, "mediatek,mcm"); - if (mcm) { - rstc = devm_reset_control_get(gsw->dev, "mcm"); - ret = IS_ERR(rstc); - if (IS_ERR(rstc)) { - dev_err(gsw->dev, "Missing reset ctrl of switch\n"); - return ret; - } - - reset_control_assert(rstc); - msleep(30); - reset_control_deassert(rstc); - - gsw->reset_pin = -1; - return 0; - } - - gsw->reset_pin = of_get_named_gpio(np, "reset-gpios", 0); - if (gsw->reset_pin < 0) { - dev_err(gsw->dev, "Missing reset pin of switch\n"); - return ret; - } - - ret = devm_gpio_request(gsw->dev, gsw->reset_pin, "mt753x-reset"); - if (ret) { - dev_info(gsw->dev, "Failed to request gpio %d\n", - gsw->reset_pin); - return ret; - } - - gpio_direction_output(gsw->reset_pin, 0); - msleep(30); - gpio_set_value(gsw->reset_pin, 1); - msleep(500); - - return 0; -} - -static irqreturn_t mt753x_irq_handler(int irq, void *dev) -{ - struct gsw_mt753x *gsw = dev; - - disable_irq_nosync(gsw->irq); - - schedule_work(&gsw->irq_worker); - - return IRQ_HANDLED; -} - -static int mt753x_probe(struct platform_device *pdev) -{ - struct gsw_mt753x *gsw; - struct mt753x_sw_id *sw; - struct device_node *np = pdev->dev.of_node; - struct device_node *mdio; - struct mii_bus *mdio_bus; - int ret = -EINVAL; - struct chip_rev rev; - struct mt753x_mapping *map; - int i; - - mdio = of_parse_phandle(np, "mediatek,mdio", 0); - if (!mdio) - return -EINVAL; - - mdio_bus = of_mdio_find_bus(mdio); - if (!mdio_bus) - return -EPROBE_DEFER; - - gsw = devm_kzalloc(&pdev->dev, sizeof(struct gsw_mt753x), GFP_KERNEL); - if (!gsw) - return -ENOMEM; - - gsw->host_bus = mdio_bus; - gsw->dev = &pdev->dev; - mutex_init(&gsw->mii_lock); - - /* Switch hard reset */ - if (mt753x_hw_reset(gsw)) - goto fail; - - /* Fetch the SMI address dirst */ - if (of_property_read_u32(np, "mediatek,smi-addr", &gsw->smi_addr)) - gsw->smi_addr = MT753X_DFL_SMI_ADDR; - - /* Get LAN/WAN port mapping */ - map = mt753x_find_mapping(np); - if (map) { - mt753x_apply_mapping(gsw, map); - gsw->global_vlan_enable = 1; - dev_info(gsw->dev, "LAN/WAN VLAN setting=%s\n", map->name); - } - - /* Load MAC port configurations */ - mt753x_load_port_cfg(gsw); - - /* Check for valid switch and then initialize */ - for (i = 0; i < ARRAY_SIZE(mt753x_sw_ids); i++) { - if (!mt753x_sw_ids[i]->detect(gsw, &rev)) { - sw = mt753x_sw_ids[i]; - - gsw->name = rev.name; - gsw->model = sw->model; - - dev_info(gsw->dev, "Switch is MediaTek %s rev %d", - gsw->name, rev.rev); - - /* Initialize the switch */ - ret = sw->init(gsw); - if (ret) - goto fail; - - break; - } - } - - if (i >= ARRAY_SIZE(mt753x_sw_ids)) { - dev_err(gsw->dev, "No mt753x switch found\n"); - goto fail; - } - - gsw->irq = platform_get_irq(pdev, 0); - if (gsw->irq >= 0) { - ret = devm_request_irq(gsw->dev, gsw->irq, mt753x_irq_handler, - 0, dev_name(gsw->dev), gsw); - if (ret) { - dev_err(gsw->dev, "Failed to request irq %d\n", - gsw->irq); - goto fail; - } - - INIT_WORK(&gsw->irq_worker, mt753x_irq_worker); - } - - platform_set_drvdata(pdev, gsw); - - gsw->phy_status_poll = of_property_read_bool(gsw->dev->of_node, - "mediatek,phy-poll"); - - mt753x_add_gsw(gsw); - - mt753x_swconfig_init(gsw); - - if (sw->post_init) - sw->post_init(gsw); - - if (gsw->irq >= 0) - mt753x_irq_enable(gsw); - - return 0; - -fail: - devm_kfree(&pdev->dev, gsw); - - return ret; -} - -static int mt753x_remove(struct platform_device *pdev) -{ - struct gsw_mt753x *gsw = platform_get_drvdata(pdev); - - if (gsw->irq >= 0) - cancel_work_sync(&gsw->irq_worker); - - if (gsw->reset_pin >= 0) - devm_gpio_free(&pdev->dev, gsw->reset_pin); - -#ifdef CONFIG_SWCONFIG - mt753x_swconfig_destroy(gsw); -#endif - - mt753x_remove_gsw(gsw); - - platform_set_drvdata(pdev, NULL); - - return 0; -} - -static const struct of_device_id mt753x_ids[] = { - { .compatible = "mediatek,mt753x" }, - { }, -}; - -MODULE_DEVICE_TABLE(of, mt753x_ids); - -static struct platform_driver mt753x_driver = { - .probe = mt753x_probe, - .remove = mt753x_remove, - .driver = { - .name = "mt753x", - .of_match_table = mt753x_ids, - }, -}; - -static int __init mt753x_init(void) -{ - int ret; - - INIT_LIST_HEAD(&mt753x_devs); - ret = platform_driver_register(&mt753x_driver); - - mt753x_nl_init(); - - return ret; -} -module_init(mt753x_init); - -static void __exit mt753x_exit(void) -{ - mt753x_nl_exit(); - - platform_driver_unregister(&mt753x_driver); -} -module_exit(mt753x_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Weijie Gao "); -MODULE_DESCRIPTION("Driver for MediaTek MT753x Gigabit Switch");