Lines Matching +full:ar9331 +full:- +full:switch
6 * SPDX-License-Identifier: GPL-2.0+
75 /* ETH Configuration 0 - 5 */
153 * Switch and MDIO access
157 struct ar7xxx_eth_priv *priv = bus->priv; in ag7xxx_switch_read()
158 void __iomem *regs = priv->phyregs; in ag7xxx_switch_read()
180 struct ar7xxx_eth_priv *priv = bus->priv; in ag7xxx_switch_write()
181 void __iomem *regs = priv->phyregs; in ag7xxx_switch_write()
196 struct ar7xxx_eth_priv *priv = bus->priv; in ag7xxx_switch_reg_read()
204 if (priv->model == AG7XXX_MODEL_AG933X) { in ag7xxx_switch_reg_read()
207 } else if (priv->model == AG7XXX_MODEL_AG934X) { in ag7xxx_switch_reg_read()
211 return -EINVAL; in ag7xxx_switch_reg_read()
236 struct ar7xxx_eth_priv *priv = bus->priv; in ag7xxx_switch_reg_write()
243 if (priv->model == AG7XXX_MODEL_AG933X) { in ag7xxx_switch_reg_write()
246 } else if (priv->model == AG7XXX_MODEL_AG934X) { in ag7xxx_switch_reg_write()
250 return -EINVAL; in ag7xxx_switch_reg_write()
260 * The switch on AR933x has some special register behavior, which in ag7xxx_switch_reg_write()
267 if ((priv->model == AG7XXX_MODEL_AG933X) && (reg == 0x98)) { in ag7xxx_switch_reg_write()
314 return -ETIMEDOUT; in ag7xxx_mdio_rw()
347 curr = &priv->tx_mac_descrtable[i]; in ag7xxx_dma_clean_tx()
348 next = &priv->tx_mac_descrtable[(i + 1) % CONFIG_TX_DESCR_NUM]; in ag7xxx_dma_clean_tx()
350 curr->data_addr = virt_to_phys(&priv->txbuffs[i * CONFIG_ETH_BUFSIZE]); in ag7xxx_dma_clean_tx()
351 curr->config = AG7XXX_DMADESC_IS_EMPTY; in ag7xxx_dma_clean_tx()
352 curr->next_desc = virt_to_phys(next); in ag7xxx_dma_clean_tx()
355 priv->tx_currdescnum = 0; in ag7xxx_dma_clean_tx()
358 start = (u32)(&priv->tx_mac_descrtable[0]); in ag7xxx_dma_clean_tx()
359 end = start + sizeof(priv->tx_mac_descrtable); in ag7xxx_dma_clean_tx()
371 curr = &priv->rx_mac_descrtable[i]; in ag7xxx_dma_clean_rx()
372 next = &priv->rx_mac_descrtable[(i + 1) % CONFIG_RX_DESCR_NUM]; in ag7xxx_dma_clean_rx()
374 curr->data_addr = virt_to_phys(&priv->rxbuffs[i * CONFIG_ETH_BUFSIZE]); in ag7xxx_dma_clean_rx()
375 curr->config = AG7XXX_DMADESC_IS_EMPTY; in ag7xxx_dma_clean_rx()
376 curr->next_desc = virt_to_phys(next); in ag7xxx_dma_clean_rx()
379 priv->rx_currdescnum = 0; in ag7xxx_dma_clean_rx()
382 start = (u32)(&priv->rx_mac_descrtable[0]); in ag7xxx_dma_clean_rx()
383 end = start + sizeof(priv->rx_mac_descrtable); in ag7xxx_dma_clean_rx()
387 start = (u32)&priv->rxbuffs; in ag7xxx_dma_clean_rx()
388 end = start + sizeof(priv->rxbuffs); in ag7xxx_dma_clean_rx()
401 curr = &priv->tx_mac_descrtable[priv->tx_currdescnum]; in ag7xxx_eth_send()
408 if (!(curr->config & AG7XXX_DMADESC_IS_EMPTY)) { in ag7xxx_eth_send()
410 return -EPERM; in ag7xxx_eth_send()
414 memcpy(phys_to_virt(curr->data_addr), packet, length); in ag7xxx_eth_send()
415 curr->config = length & AG7XXX_DMADESC_PKT_SIZE_MASK; in ag7xxx_eth_send()
421 start = (u32)phys_to_virt(curr->data_addr); in ag7xxx_eth_send()
427 priv->regs + AG7XXX_ETH_DMA_TX_CTRL); in ag7xxx_eth_send()
429 /* Switch to next TX descriptor. */ in ag7xxx_eth_send()
430 priv->tx_currdescnum = (priv->tx_currdescnum + 1) % CONFIG_TX_DESCR_NUM; in ag7xxx_eth_send()
441 curr = &priv->rx_mac_descrtable[priv->rx_currdescnum]; in ag7xxx_eth_recv()
449 if (curr->config & AG7XXX_DMADESC_IS_EMPTY) in ag7xxx_eth_recv()
450 return -EAGAIN; in ag7xxx_eth_recv()
452 length = curr->config & AG7XXX_DMADESC_PKT_SIZE_MASK; in ag7xxx_eth_recv()
455 start = (u32)phys_to_virt(curr->data_addr); in ag7xxx_eth_recv()
460 *packetp = phys_to_virt(curr->data_addr); in ag7xxx_eth_recv()
471 curr = &priv->rx_mac_descrtable[priv->rx_currdescnum]; in ag7xxx_eth_free_pkt()
473 curr->config = AG7XXX_DMADESC_IS_EMPTY; in ag7xxx_eth_free_pkt()
480 /* Switch to next RX descriptor. */ in ag7xxx_eth_free_pkt()
481 priv->rx_currdescnum = (priv->rx_currdescnum + 1) % CONFIG_RX_DESCR_NUM; in ag7xxx_eth_free_pkt()
497 writel(virt_to_phys(&priv->tx_mac_descrtable[priv->tx_currdescnum]), in ag7xxx_eth_start()
498 priv->regs + AG7XXX_ETH_DMA_TX_DESC); in ag7xxx_eth_start()
499 writel(virt_to_phys(&priv->rx_mac_descrtable[priv->rx_currdescnum]), in ag7xxx_eth_start()
500 priv->regs + AG7XXX_ETH_DMA_RX_DESC); in ag7xxx_eth_start()
502 priv->regs + AG7XXX_ETH_DMA_RX_CTRL); in ag7xxx_eth_start()
512 writel(0, priv->regs + AG7XXX_ETH_DMA_TX_CTRL); in ag7xxx_eth_stop()
513 wait_for_bit_le32(priv->regs + AG7XXX_ETH_DMA_TX_CTRL, ~0, 0, in ag7xxx_eth_stop()
517 writel(0, priv->regs + AG7XXX_ETH_DMA_RX_CTRL); in ag7xxx_eth_stop()
518 wait_for_bit_le32(priv->regs + AG7XXX_ETH_DMA_RX_CTRL, ~0, 0, in ag7xxx_eth_stop()
529 unsigned char *mac = pdata->enetaddr; in ag7xxx_eth_write_hwaddr()
535 writel(macid_lo, priv->regs + AG7XXX_ETH_ADDR1); in ag7xxx_eth_write_hwaddr()
536 writel(macid_hi, priv->regs + AG7XXX_ETH_ADDR2); in ag7xxx_eth_write_hwaddr()
546 setbits_be32(priv->regs + AG7XXX_ETH_CFG1, in ag7xxx_hw_setup()
553 priv->regs + AG7XXX_ETH_CFG1); in ag7xxx_hw_setup()
555 if (priv->interface == PHY_INTERFACE_MODE_RMII) in ag7xxx_hw_setup()
560 clrsetbits_be32(priv->regs + AG7XXX_ETH_CFG2, in ag7xxx_hw_setup()
565 writel(0xfff0000, priv->regs + AG7XXX_ETH_FIFO_CFG_1); in ag7xxx_hw_setup()
566 writel(0x1fff, priv->regs + AG7XXX_ETH_FIFO_CFG_2); in ag7xxx_hw_setup()
568 writel(0x1f00, priv->regs + AG7XXX_ETH_FIFO_CFG_0); in ag7xxx_hw_setup()
569 setbits_be32(priv->regs + AG7XXX_ETH_FIFO_CFG_4, 0x3ffff); in ag7xxx_hw_setup()
570 writel(0x10ffff, priv->regs + AG7XXX_ETH_FIFO_CFG_1); in ag7xxx_hw_setup()
571 writel(0xaaa0555, priv->regs + AG7XXX_ETH_FIFO_CFG_2); in ag7xxx_hw_setup()
572 writel(0x7eccf, priv->regs + AG7XXX_ETH_FIFO_CFG_5); in ag7xxx_hw_setup()
573 writel(0x1f00140, priv->regs + AG7XXX_ETH_FIFO_CFG_3); in ag7xxx_hw_setup()
580 switch (freq / 1000000) { in ag7xxx_mii_get_div()
596 if (priv->model == AG7XXX_MODEL_AG933X) { in ag7xxx_mii_setup()
597 /* Unit 0 is PHY-less on AR9331, see datasheet Figure 2-3 */ in ag7xxx_mii_setup()
598 if (priv->interface == PHY_INTERFACE_MODE_RMII) in ag7xxx_mii_setup()
602 if (priv->model == AG7XXX_MODEL_AG934X) { in ag7xxx_mii_setup()
604 priv->regs + AG7XXX_ETH_MII_MGMT_CFG); in ag7xxx_mii_setup()
605 writel(0x4, priv->regs + AG7XXX_ETH_MII_MGMT_CFG); in ag7xxx_mii_setup()
611 priv->regs + AG7XXX_ETH_MII_MGMT_CFG); in ag7xxx_mii_setup()
612 writel(div, priv->regs + AG7XXX_ETH_MII_MGMT_CFG); in ag7xxx_mii_setup()
614 /* Check the switch */ in ag7xxx_mii_setup()
615 ret = ag7xxx_switch_reg_read(priv->bus, 0x10c, ®); in ag7xxx_mii_setup()
625 return -EINVAL; in ag7xxx_mii_setup()
632 /* Configure switch port 4 (GMAC0) */ in ag933x_phy_setup_wan()
633 return ag7xxx_mdio_write(priv->bus, 4, 0, MII_BMCR, 0x9000); in ag933x_phy_setup_wan()
642 /* Reset the switch */ in ag933x_phy_setup_lan()
643 ret = ag7xxx_switch_reg_read(priv->bus, 0, ®); in ag933x_phy_setup_lan()
647 ret = ag7xxx_switch_reg_write(priv->bus, 0, reg); in ag933x_phy_setup_lan()
652 ret = ag7xxx_switch_reg_read(priv->bus, 0, ®); in ag933x_phy_setup_lan()
657 /* Configure switch ports 0...3 (GMAC1) */ in ag933x_phy_setup_lan()
659 ret = ag7xxx_mdio_write(priv->bus, 0x4, 0, MII_BMCR, 0x9000); in ag933x_phy_setup_lan()
665 ret = ag7xxx_switch_reg_write(priv->bus, 0x78, BIT(8)); in ag933x_phy_setup_lan()
670 ret = ag7xxx_switch_reg_write(priv->bus, i * 0x100, BIT(9)); in ag933x_phy_setup_lan()
676 ret = ag7xxx_switch_reg_write(priv->bus, 0x38, 0xc000050e); in ag933x_phy_setup_lan()
681 ret = ag7xxx_switch_reg_write(priv->bus, 0x104, 0x4004); in ag933x_phy_setup_lan()
686 ret = ag7xxx_switch_reg_write(priv->bus, 0x70, 0xfa50); in ag933x_phy_setup_lan()
691 ret = ag7xxx_switch_reg_read(priv->bus, 0x5c, ®); in ag933x_phy_setup_lan()
695 ret = ag7xxx_switch_reg_write(priv->bus, 0x5c, reg); in ag933x_phy_setup_lan()
707 ret = ag7xxx_mdio_write(priv->bus, port, 0, MII_ADVERTISE, in ag933x_phy_setup_reset_set()
713 if (priv->model == AG7XXX_MODEL_AG934X) { in ag933x_phy_setup_reset_set()
714 ret = ag7xxx_mdio_write(priv->bus, port, 0, MII_CTRL1000, in ag933x_phy_setup_reset_set()
720 return ag7xxx_mdio_write(priv->bus, port, 0, MII_BMCR, in ag933x_phy_setup_reset_set()
730 ret = ag7xxx_mdio_read(priv->bus, port, 0, MII_BMCR); in ag933x_phy_setup_reset_fin()
744 if (priv->model == AG7XXX_MODEL_AG933X) in ag933x_phy_setup_common()
746 else if (priv->model == AG7XXX_MODEL_AG934X) in ag933x_phy_setup_common()
749 return -EINVAL; in ag933x_phy_setup_common()
751 if (priv->interface == PHY_INTERFACE_MODE_RMII) { in ag933x_phy_setup_common()
761 ret = ag7xxx_mdio_read(priv->bus, phymax, 0, MII_MIPSCR); in ag933x_phy_setup_common()
768 /* Switch ports */ in ag933x_phy_setup_common()
783 ret = ag7xxx_mdio_read(priv->bus, i, 0, MII_MIPSCR); in ag933x_phy_setup_common()
797 ret = ag7xxx_switch_reg_write(priv->bus, 0x624, 0x7f7f7f7f); in ag934x_phy_setup()
800 ret = ag7xxx_switch_reg_write(priv->bus, 0x10, 0x40000000); in ag934x_phy_setup()
803 ret = ag7xxx_switch_reg_write(priv->bus, 0x4, 0x07600000); in ag934x_phy_setup()
806 ret = ag7xxx_switch_reg_write(priv->bus, 0xc, 0x01000000); in ag934x_phy_setup()
809 ret = ag7xxx_switch_reg_write(priv->bus, 0x7c, 0x0000007e); in ag934x_phy_setup()
814 ret = ag7xxx_switch_reg_read(priv->bus, 0, ®); in ag934x_phy_setup()
819 ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1d, 0x0); in ag934x_phy_setup()
822 ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1e, 0x02ea); in ag934x_phy_setup()
825 ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1d, 0x3d); in ag934x_phy_setup()
828 ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1e, 0x68a0); in ag934x_phy_setup()
834 ret = ag7xxx_switch_reg_read(priv->bus, 0x66c, ®); in ag934x_phy_setup()
838 ret = ag7xxx_switch_reg_write(priv->bus, 0x66c, reg); in ag934x_phy_setup()
857 if (priv->model == AG7XXX_MODEL_AG933X) { in ag7xxx_mac_probe()
858 if (priv->interface == PHY_INTERFACE_MODE_RMII) in ag7xxx_mac_probe()
862 } else if (priv->model == AG7XXX_MODEL_AG934X) { in ag7xxx_mac_probe()
865 return -EINVAL; in ag7xxx_mac_probe()
880 return -ENOMEM; in ag7xxx_mdio_probe()
882 bus->read = ag7xxx_mdio_read; in ag7xxx_mdio_probe()
883 bus->write = ag7xxx_mdio_write; in ag7xxx_mdio_probe()
884 snprintf(bus->name, sizeof(bus->name), dev->name); in ag7xxx_mdio_probe()
886 bus->priv = (void *)priv; in ag7xxx_mdio_probe()
895 offset = fdtdec_lookup_phandle(gd->fdt_blob, dev_of_offset(dev), "phy"); in ag7xxx_get_phy_iface_offset()
898 return -EINVAL; in ag7xxx_get_phy_iface_offset()
901 offset = fdt_parent_offset(gd->fdt_blob, offset); in ag7xxx_get_phy_iface_offset()
905 return -EINVAL; in ag7xxx_get_phy_iface_offset()
908 offset = fdt_parent_offset(gd->fdt_blob, offset); in ag7xxx_get_phy_iface_offset()
912 return -EINVAL; in ag7xxx_get_phy_iface_offset()
929 phyreg = fdtdec_get_int(gd->fdt_blob, ret, "reg", -1); in ag7xxx_eth_probe()
931 iobase = map_physmem(pdata->iobase, 0x200, MAP_NOCACHE); in ag7xxx_eth_probe()
936 priv->regs = iobase; in ag7xxx_eth_probe()
937 priv->phyregs = phyiobase; in ag7xxx_eth_probe()
938 priv->interface = pdata->phy_interface; in ag7xxx_eth_probe()
939 priv->model = dev_get_driver_data(dev); in ag7xxx_eth_probe()
945 priv->bus = miiphy_get_dev_by_name(dev->name); in ag7xxx_eth_probe()
957 free(priv->phydev); in ag7xxx_eth_remove()
958 mdio_unregister(priv->bus); in ag7xxx_eth_remove()
959 mdio_free(priv->bus); in ag7xxx_eth_remove()
979 pdata->iobase = devfdt_get_addr(dev); in ag7xxx_eth_ofdata_to_platdata()
980 pdata->phy_interface = -1; in ag7xxx_eth_ofdata_to_platdata()
987 phy_mode = fdt_getprop(gd->fdt_blob, ret, "phy-mode", NULL); in ag7xxx_eth_ofdata_to_platdata()
989 pdata->phy_interface = phy_get_interface_by_name(phy_mode); in ag7xxx_eth_ofdata_to_platdata()
990 if (pdata->phy_interface == -1) { in ag7xxx_eth_ofdata_to_platdata()
992 return -EINVAL; in ag7xxx_eth_ofdata_to_platdata()
999 { .compatible = "qca,ag933x-mac", .data = AG7XXX_MODEL_AG933X },
1000 { .compatible = "qca,ag934x-mac", .data = AG7XXX_MODEL_AG934X },