/* Marvell 88E1310 */ static int m88e1310_config(struct phy_device *phydev) { u16 reg; /* LED link and activity */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0003); reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_LED_CTRL); reg = (reg & ~0xf) | 0x1; phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_LED_CTRL, reg); /* Set LED2/INT to INT mode, low active */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0003); reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_IRQ_EN); reg = (reg & 0x77ff) | 0x0880; phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_IRQ_EN, reg); /* Set RGMII delay */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0002); reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_RGMII_CTRL); reg |= 0x0030; phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_RGMII_CTRL, reg); /* Ensure to return to page 0 */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0000); genphy_config_aneg(phydev); phy_reset(phydev); return 0; }
static int mvphy_reset_88e1116(phy_handle_t *ph) { uint16_t reg; /* make sure that this PHY uses page 0 (copper) */ phy_write(ph, MVPHY_EADR, 0); reg = phy_read(ph, MVPHY_PSC); reg &= ~MV_PSC_POWER_DOWN; /* Disable energy detect mode */ reg &= ~MV_PSC_EN_DETECT_MASK; reg |= MV_PSC_AUTO_X_MODE; reg |= MV_PSC_ASSERT_CRS_TX; reg &= ~MV_PSC_POL_REVERSE; phy_write(ph, MVPHY_PSC, reg); phy_write(ph, MVPHY_EADR, 2); PHY_SET(ph, MVPHY_PSC, MV_PSC_RGMII_POWER_UP); /* page 3 is led control */ phy_write(ph, MVPHY_EADR, 3); phy_write(ph, MVPHY_PSC, MV_PSC_LED_LOS_CTRL(1) | /* link/act */ MV_PSC_LED_INIT_CTRL(8) | /* 10 Mbps */ MV_PSC_LED_STA1_CTRL(7) | /* 100 Mbps */ MV_PSC_LED_STA0_CTRL(7)); /* 1000 Mbps */ phy_write(ph, MVPHY_INTEN, 0); phy_write(ph, MVPHY_EADR, 0); return (phy_reset(ph)); }
/* Marvell 88E1145 */ static int m88e1145_config(struct phy_device *phydev) { int reg; /* Errata E0, E1 */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_PAGE, 0x001b); phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_CAL_OV, 0x418f); phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_PAGE, 0x0016); phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_CAL_OV, 0xa2da); phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1xxx_PHY_SCR, MIIM_88E1xxx_PHY_MDI_X_AUTO); reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR); if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) reg |= MIIM_M88E1145_RGMII_RX_DELAY | MIIM_M88E1145_RGMII_TX_DELAY; phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR, reg); genphy_config_aneg(phydev); phy_reset(phydev); return 0; }
static int mvphy_reset_88e3016(phy_handle_t *ph) { uint16_t reg; int rv; rv = phy_reset(ph); reg = phy_read(ph, MVPHY_PSC); reg |= MV_PSC_AUTO_MDIX; reg &= ~(MV_PSC_EN_DETECT | MV_PSC_DIS_SCRAMBLER); reg |= MV_PSC_LPNP; /* enable class A driver for Yukon FE+ A0. */ PHY_SET(ph, MII_VENDOR(12), 0x0001); phy_write(ph, MVPHY_PSC, reg); /* LED2 = ACT blink, LED1 = LINK), LED0 = SPEED */ phy_write(ph, MVPHY_LED_PSEL, MV_LED_PSEL_LED2(MV_LED_PSEL_ACT_BL) | MV_LED_PSEL_LED1(MV_LED_PSEL_LINK) | MV_LED_PSEL_LED0(MV_LED_PSEL_SPEED)); /* calibration, values not documented */ phy_write(ph, MVPHY_PAGE_ADDR, 17); phy_write(ph, MVPHY_PAGE_DATA, 0x3f60); /* Normal BMCR reset now */ return (rv); }
static void pic32_eth_stop(struct udevice *dev) { struct pic32eth_dev *priv = dev_get_priv(dev); struct pic32_ectl_regs *ectl_p = priv->ectl_regs; struct pic32_emac_regs *emac_p = priv->emac_regs; /* Reset the phy if the controller is enabled */ if (readl(&ectl_p->con1.raw) & ETHCON_ON) phy_reset(priv->phydev); /* Shut down the PHY */ phy_shutdown(priv->phydev); /* Stop rx/tx */ writel(ETHCON_TXRTS | ETHCON_RXEN, &ectl_p->con1.clr); mdelay(10); /* reset MAC */ writel(EMAC_SOFTRESET, &emac_p->cfg1.raw); /* clear reset */ writel(0, &emac_p->cfg1.raw); mdelay(10); /* disable controller */ writel(ETHCON_ON, &ectl_p->con1.clr); mdelay(10); /* wait until everything is down */ wait_for_bit_le32(&ectl_p->stat.raw, ETHSTAT_BUSY, false, 2 * CONFIG_SYS_HZ, false); /* clear any existing interrupt event */ writel(0xffffffff, &ectl_p->irq.clr); }
static int mvphy_reset_88e1112(phy_handle_t *ph) { uint16_t reg, page; if (phy_read(ph, MVPHY_EPSS) & MV_EPSS_FCRESOL) { /* interface indicates fiber */ PHY_CLR(ph, MVPHY_PSC, MV_PSC_AUTO_X_MODE); page = phy_read(ph, MVPHY_EADR); /* Go into locked 1000BASE-X mode */ page = phy_read(ph, MVPHY_EADR); phy_write(ph, MVPHY_EADR, 2); reg = phy_read(ph, MVPHY_PSC); reg &= ~MV_PSC_MODE_MASK; reg |= MV_PSC_MODE_1000BASEX; phy_write(ph, MVPHY_PSC, reg); phy_write(ph, MVPHY_EADR, page); } else { reg = phy_read(ph, MVPHY_PSC); /* Disable energy detect mode */ reg &= ~MV_PSC_EN_DETECT_MASK; reg |= MV_PSC_AUTO_X_MODE; reg |= MV_PSC_ASSERT_CRS_TX; reg &= ~MV_PSC_POL_REVERSE; phy_write(ph, MVPHY_PSC, reg); } return (phy_reset(ph)); }
/* Broadcom BCM5461S */ static int bcm5461_config(struct phy_device *phydev) { genphy_config_aneg(phydev); phy_reset(phydev); return 0; }
static void lan9118_reset(DeviceState *d) { lan9118_state *s = LAN9118(d); s->irq_cfg &= (IRQ_TYPE | IRQ_POL); s->int_sts = 0; s->int_en = 0; s->fifo_int = 0x48000000; s->rx_cfg = 0; s->tx_cfg = 0; s->hw_cfg = s->mode_16bit ? 0x00050000 : 0x00050004; s->pmt_ctrl &= 0x45; s->gpio_cfg = 0; s->txp->fifo_used = 0; s->txp->state = TX_IDLE; s->txp->cmd_a = 0xffffffffu; s->txp->cmd_b = 0xffffffffu; s->txp->len = 0; s->txp->fifo_used = 0; s->tx_fifo_size = 4608; s->tx_status_fifo_used = 0; s->rx_status_fifo_size = 704; s->rx_fifo_size = 2640; s->rx_fifo_used = 0; s->rx_status_fifo_size = 176; s->rx_status_fifo_used = 0; s->rxp_offset = 0; s->rxp_size = 0; s->rxp_pad = 0; s->rx_packet_size_tail = s->rx_packet_size_head; s->rx_packet_size[s->rx_packet_size_head] = 0; s->mac_cmd = 0; s->mac_data = 0; s->afc_cfg = 0; s->e2p_cmd = 0; s->e2p_data = 0; s->free_timer_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / 40; ptimer_stop(s->timer); ptimer_set_count(s->timer, 0xffff); s->gpt_cfg = 0xffff; s->mac_cr = MAC_CR_PRMS; s->mac_hashh = 0; s->mac_hashl = 0; s->mac_mii_acc = 0; s->mac_mii_data = 0; s->mac_flow = 0; s->read_word_n = 0; s->write_word_n = 0; phy_reset(s); s->eeprom_writable = 0; lan9118_reload_eeprom(s); }
/* Marvell 88E1149S */ static int m88e1149_config(struct phy_device *phydev) { phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1149_PHY_PAGE, 0x1f); phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x200c); phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1149_PHY_PAGE, 0x5); phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x0); phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100); genphy_config_aneg(phydev); phy_reset(phydev); return 0; }
static int mvphy_reset_88e1118(phy_handle_t *ph) { uint16_t reg; reg = phy_read(ph, MVPHY_PSC); /* Disable energy detect mode */ reg &= ~MV_PSC_EN_DETECT_MASK; reg |= MV_PSC_AUTO_X_MODE; reg |= MV_PSC_ASSERT_CRS_TX; reg &= ~MV_PSC_POL_REVERSE; phy_write(ph, MVPHY_PSC, reg); return (phy_reset(ph)); }
static int mvphy_reset_88e3082(phy_handle_t *ph) { uint16_t reg; int rv; rv = phy_reset(ph); reg = phy_read(ph, MVPHY_PSC); reg |= (MV_PSC_AUTO_X_MODE >> 1); reg |= MV_PSC_ASSERT_CRS_TX; reg &= ~MV_PSC_POL_REVERSE; phy_write(ph, MVPHY_PSC, reg); return (rv); }
static int mvphy_reset(phy_handle_t *ph) { uint16_t reg; reg = phy_read(ph, MVPHY_PSC); reg &= ~MV_PSC_AUTO_X_MODE; reg |= MV_PSC_ASSERT_CRS_TX; reg &= ~MV_PSC_POL_REVERSE; phy_write(ph, MVPHY_PSC, reg); PHY_SET(ph, MVPHY_EPSC, MV_EPSC_TX_CLK_25); /* Normal BMCR reset now */ return (phy_reset(ph)); }
int main() { // Initialize the platform platform_init(); // Configure periodic sending soft_timer_init(); soft_timer_set_handler(&tim, tx, NULL); soft_timer_start(&tim, soft_timer_s_to_ticks(1), 1); printf("PHY SimpleTX test\n"); phy_reset(PHY); phy_set_channel(PHY, 15); platform_run(); return 0; }
/** @brief Initialize ethernet * * This function will initialize ethernet, set up clocks, and initialize DMA. * * @param[in] phy phy id * @param[in] clock enum eth_clk Core clock speed */ void eth_init(uint8_t phy, enum eth_clk clock) { ETH_MACMIIAR = clock; phy_reset(phy); ETH_MACCR = ETH_MACCR_CSTF | ETH_MACCR_FES | ETH_MACCR_DM | ETH_MACCR_APCS | ETH_MACCR_RD; ETH_MACFFR = ETH_MACFFR_RA | ETH_MACFFR_PM; ETH_MACHTHR = 0; /* pass all frames */ ETH_MACHTLR = 0; ETH_MACFCR = (0x100 << ETH_MACFCR_PT_SHIFT); ETH_MACVLANTR = 0; ETH_DMAOMR = ETH_DMAOMR_DTCEFD | ETH_DMAOMR_RSF | ETH_DMAOMR_DFRF | ETH_DMAOMR_TSF | ETH_DMAOMR_FEF | ETH_DMAOMR_OSF; ETH_DMABMR = ETH_DMABMR_AAB | ETH_DMABMR_FB | (32 << ETH_DMABMR_RDP_SHIFT) | (32 << ETH_DMABMR_PBL_SHIFT) | ETH_DMABMR_PM_2_1 | ETH_DMABMR_USP; }
/* Marvell 88E1118 */ static int m88e1118_config(struct phy_device *phydev) { /* Change Page Number */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0002); /* Delay RGMII TX and RX */ phy_write(phydev, MDIO_DEVAD_NONE, 0x15, 0x1070); /* Change Page Number */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0003); /* Adjust LED control */ phy_write(phydev, MDIO_DEVAD_NONE, 0x10, 0x021e); /* Change Page Number */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000); genphy_config_aneg(phydev); phy_reset(phydev); return 0; }
static void do_phy_write(Ftgmac100State *s, int reg, uint32_t val) { PHY_DEBUG("PHY: write 0x%04x @%d\n", val, reg); if (reg > 31) { /* we only advertise one phy */ return; } switch (reg) { case 0: /* Basic Control */ if (val & 0x8000) { phy_reset(s); } else { s->phy_control = val & 0x7980; /* Complete autonegotiation immediately. */ if (val & 0x1000) { s->phy_status |= 0x0020; } } break; case 4: /* Auto-neg advertisement */ s->phy_advertise = (val & 0x2d7f) | 0x80; break; case 30: /* Interrupt mask */ s->phy_int_mask = val & 0xff; phy_update_irq(s); break; case 17: case 18: case 27: case 31: qemu_log_mask(LOG_UNIMP, "%s: reg %d not implemented\n", __func__, reg); break; default: qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset %d\n", __func__, reg); break; } }
static void ftgmac100_reset(DeviceState *d) { Ftgmac100State *s = FTGMAC100(d); /* Reset the FTGMAC100 */ s->isr = 0; s->ier = 0; s->rx_enabled = 0; s->maccr = 0; s->rx_ring = 0; s->rx_descriptor = 0; s->rbsr = 0x640; /* HW default according to u-boot driver */ s->tx_ring = 0; s->tx_descriptor = 0; s->phycr = 0; s->phydata = 0; s->aptcr = 0; /* We also reset the PHY */ phy_reset(s); }
static int mvphy_reset_88e1011(phy_handle_t *ph) { uint16_t reg; if (phy_read(ph, MVPHY_EPSS) & MV_EPSS_FCRESOL) { /* interface indicates fiber */ PHY_CLR(ph, MVPHY_PSC, MV_PSC_AUTO_X_MODE); } else { reg = phy_read(ph, MVPHY_PSC); reg &= ~MV_PSC_AUTO_X_MODE; reg |= MV_PSC_ASSERT_CRS_TX; reg &= ~MV_PSC_POL_REVERSE; phy_write(ph, MVPHY_PSC, reg); } /* force TX CLOCK to 25 MHz */ PHY_SET(ph, MVPHY_EPSC, MV_EPSC_TX_CLK_25); return (phy_reset(ph)); }
/* Initialize pins in complex peripheral */ void init_eth(void) { int phy_pins[] = { PHY_CRSDV, PHY_RXD0, PHY_RXD1, PHY_REFCLK, PHY_TXEN, PHY_TXD0, PHY_TXD1, PHY_MDIO, PHY_MDC }; /* Initialize all pins that belongs to RMII */ for (int i = 0; i < sizeof(phy_pins) / sizeof(phy_pins[0]); i++) { pin_clock_enable(phy_pins[i]); pin_af_pushpull(phy_pins[i]); pin_speed_high(phy_pins[i]); pin_af_map(phy_pins[i], GPIO_AF_ETH); } pin_input(PHY_INTRP); pin_pull_up(PHY_INTRP); pin_set(PHY_RST, true); pin_output_pushpull(PHY_RST); /* Reset the connected PHY by signal */ pin_set(PHY_RST, false); for (int i = 0; i < 10000; i++) { __asm volatile ("nop"); } pin_set(PHY_RST, true); for (int i = 0; i < 10000; i++) { __asm volatile ("nop"); } /* Initialize phy over SNI */ phy_reset(1); /* out of scope of this example */ /* Initialize ethernet MAC */ eth_init(); /* out of scope of this example */ }
static int ns83840_reset(phy_handle_t *ph) { /* first do an ordinary reset */ if (phy_reset(ph) != DDI_SUCCESS) { return (DDI_FAILURE); } /* * As per INTEL "PRO/100B Adapter Software Technical Reference * Manual", set bit 10 of MII register 23. National * Semiconductor documentation shows this as "reserved, write * to as zero". We also set the "CIM_DIS" bit, also as * requested by the PRO/100B doc, to disable the carrier * integrity monitor. (That should only ever be used by * repeaters.) * * NetBSD also sets bit 8, without any explanation, so we'll * follow suit. */ PHY_SET(ph, MII_VENDOR(7), (1<<10) | (1<<8) | (1<<5)); return (DDI_SUCCESS); }
/* Marvell 88E1111S */ static int m88e1111s_config(struct phy_device *phydev) { int reg; if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { reg = phy_read(phydev, MDIO_DEVAD_NONE, 0x1b); reg = (reg & 0xfff0) | 0xb; phy_write(phydev, MDIO_DEVAD_NONE, 0x1b, reg); } else { phy_write(phydev, MDIO_DEVAD_NONE, 0x1b, 0x1f); } phy_write(phydev, MDIO_DEVAD_NONE, 0x14, 0x0cd2); genphy_config_aneg(phydev); phy_reset(phydev); return 0; }
static int exynos_pcie_establish_link(struct exynos_pcie *ep) { struct dw_pcie *pci = ep->pci; struct pcie_port *pp = &pci->pp; struct device *dev = pci->dev; if (dw_pcie_link_up(pci)) { dev_err(dev, "Link already up\n"); return 0; } exynos_pcie_assert_core_reset(ep); phy_reset(ep->phy); exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_PWR_RESET); phy_power_on(ep->phy); phy_init(ep->phy); exynos_pcie_deassert_core_reset(ep); dw_pcie_setup_rc(pp); exynos_pcie_assert_reset(ep); /* assert LTSSM enable */ exynos_pcie_writel(ep->mem_res->elbi_base, PCIE_ELBI_LTSSM_ENABLE, PCIE_APP_LTSSM_ENABLE); /* check if the link is up or not */ if (!dw_pcie_wait_for_link(pci)) return 0; phy_power_off(ep->phy); return -ETIMEDOUT; }
void reset() { phy_reset(); // device reset - the RST bit is self-clearing ioreg(reg::CTRL, ioreg(reg::CTRL) | CTRL_RST); for (int timeout = 0; ; ++timeout) { REQUIRE(timeout < 1000 && "Failed to reset i825x device"); delay_microseconds(2); // Need to delay at least 1us before reading status after a reset if (!(ioreg(reg::CTRL) & CTRL_RST)) { break; } } // LRST->0 enables auto-negotiation, clear ILOS and disable VLAN Mode Enable ioreg(reg::CTRL, (ioreg(reg::CTRL) & ~(CTRL_LRST | CTRL_ILOS | CTRL_VME)) | CTRL_ASDE | CTRL_SLU); // TODO: Reset flow control // TODO: Clear statistics counters // Program the Receive Address Register ioreg(reg::RAL0, (mac_addr_[0]) | (mac_addr_[1] << 8) | (mac_addr_[2] << 16) | (mac_addr_[3] << 24)); ioreg(reg::RAH0, (mac_addr_[4]) | (mac_addr_[5] << 8) | RAH_AV); // Initialize the MTA (Multicast Table Array) to 0 for (int i = 0; i < 128; i++) { ioreg(static_cast<reg>(static_cast<uint32_t>(reg::MTA) + i * 4), 0); } // Program the Interrupt Mask Set/Read (IMS) register ioreg(reg::IMC, ~0U); // Inhibit interrupts ioreg(reg::ICR, ~0U); // Clear pending interrupts ioreg(reg::IMS, ICR_TXDW | ICR_LSC | ICR_RXDMT0 | ICR_RXT0); // Enable interrupts // Program the Receive Descriptor Base Address const uint64_t rx_desc_phys = virt_to_phys((const void*)&rx_desc_[0]); ioreg(reg::RDBAL0, static_cast<uint32_t>(rx_desc_phys)); ioreg(reg::RDBAH0, static_cast<uint32_t>(rx_desc_phys>>32)); // Set the Receive Descriptor Length (RDLEN) register to the size (in bytes) of the descriptor ring. ioreg(reg::RDLEN0, sizeof(rx_desc_)); // Initialize Receive Descriptor Head and Tail registers ioreg(reg::RDH0, 0); ioreg(reg::RDT0, num_rx_descriptors-1); memset((void*)rx_desc_, 0, sizeof(rx_desc_)); for (uint32_t i = 0; i < num_rx_descriptors; ++i) { rx_desc_[i].buffer_addr = virt_to_phys(rx_buffer_[i]); rx_desc_[i].status = 0; } // Enable RX ioreg(reg::RCTL, RCTL_EN | RCTL_SBP // recieve everyting | RCTL_UPE // even | RCTL_MPE // bad packets | RCTL_BAM // and multicast.. | RCTL_SZ_2048); rx_head_ = 0; // Enable TX memset((void*)tx_desc_, 0, sizeof(tx_desc_)); const uint64_t tx_desc_phys = virt_to_phys((const void*)&tx_desc_[0]); REQUIRE((tx_desc_phys & 15) == 0); ioreg(reg::TDBAL0, static_cast<uint32_t>(tx_desc_phys)); ioreg(reg::TDBAH0, static_cast<uint32_t>(tx_desc_phys>>32)); ioreg(reg::TDLEN0, sizeof(tx_desc_)); static_assert(sizeof(tx_desc_) % 128 == 0, ""); static_assert(sizeof(tx_desc_) >= 128, ""); // Set the transmit descriptor write-back policy ioreg(reg::TXDCTL0, (ioreg(reg::TXDCTL0) & TXDCTL_WTHRESH) | TXDCTL_FULL_TX_DESC_WB/* | TXDCTL_COUNT_DESC*/); ioreg(reg::TDH0, 0); ioreg(reg::TDT0, 0); ioreg(reg::TCTL, ioreg(reg::TCTL) | TCTL_EN | TCTL_PSP); tx_tail_ = 0; }
/* Marvell 88E1111S */ static int m88e1111s_config(struct phy_device *phydev) { int reg; if (phy_interface_is_rgmii(phydev)) { reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR); if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)) { reg |= (MIIM_88E1111_RX_DELAY | MIIM_88E1111_TX_DELAY); } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { reg &= ~MIIM_88E1111_TX_DELAY; reg |= MIIM_88E1111_RX_DELAY; } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { reg &= ~MIIM_88E1111_RX_DELAY; reg |= MIIM_88E1111_TX_DELAY; } phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR, reg); reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR); reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK); if (reg & MIIM_88E1111_HWCFG_FIBER_COPPER_RES) reg |= MIIM_88E1111_HWCFG_MODE_FIBER_RGMII; else reg |= MIIM_88E1111_HWCFG_MODE_COPPER_RGMII; phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR, reg); } if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR); reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK); reg |= MIIM_88E1111_HWCFG_MODE_SGMII_NO_CLK; reg |= MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO; phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR, reg); } if (phydev->interface == PHY_INTERFACE_MODE_RTBI) { reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR); reg |= (MIIM_88E1111_RX_DELAY | MIIM_88E1111_TX_DELAY); phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR, reg); reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR); reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK | MIIM_88E1111_HWCFG_FIBER_COPPER_RES); reg |= 0x7 | MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO; phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR, reg); /* soft reset */ phy_reset(phydev); reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR); reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK | MIIM_88E1111_HWCFG_FIBER_COPPER_RES); reg |= MIIM_88E1111_HWCFG_MODE_COPPER_RTBI | MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO; phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR, reg); } /* soft reset */ phy_reset(phydev); genphy_config_aneg(phydev); genphy_restart_aneg(phydev); return 0; }
static int m88e1518_config(struct phy_device *phydev) { u16 reg; /* * As per Marvell Release Notes - Alaska 88E1510/88E1518/88E1512 * /88E1514 Rev A0, Errata Section 3.1 */ /* EEE initialization */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x00ff); phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x214B); phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2144); phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x0C28); phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2146); phy_write(phydev, MDIO_DEVAD_NONE, 17, 0xB233); phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x214D); phy_write(phydev, MDIO_DEVAD_NONE, 17, 0xCC0C); phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2159); phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000); /* SGMII-to-Copper mode initialization */ if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { /* Select page 18 */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 18); /* In reg 20, write MODE[2:0] = 0x1 (SGMII to Copper) */ m88e1518_phy_writebits(phydev, MIIM_88E151x_GENERAL_CTRL, 0, 3, MIIM_88E151x_MODE_SGMII); /* PHY reset is necessary after changing MODE[2:0] */ m88e1518_phy_writebits(phydev, MIIM_88E151x_GENERAL_CTRL, MIIM_88E151x_RESET_OFFS, 1, 1); /* Reset page selection */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0); udelay(100); } if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR); reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK); reg |= MIIM_88E1111_HWCFG_MODE_SGMII_NO_CLK; reg |= MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO; phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR, reg); } if (phy_interface_is_rgmii(phydev)) { phy_write(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE, 2); reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E151x_PHY_MSCR); reg &= ~MIIM_88E151x_RGMII_RXTX_DELAY; if (phydev->interface == PHY_INTERFACE_MODE_RGMII || phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) reg |= MIIM_88E151x_RGMII_RXTX_DELAY; else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) reg |= MIIM_88E151x_RGMII_RX_DELAY; else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) reg |= MIIM_88E151x_RGMII_TX_DELAY; phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E151x_PHY_MSCR, reg); phy_write(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE, 0); } /* soft reset */ phy_reset(phydev); genphy_config_aneg(phydev); genphy_restart_aneg(phydev); return 0; }
/* * mac hw init is done here */ static int enet_hw_init(struct net_device *dev) { struct tangox_enet_priv *priv; unsigned int val = 0; if(phy_reset(dev)) return -EBUSY; priv = netdev_priv(dev); /* set pad_mode according to rgmii or not*/ val = enet_readb(priv->enet_mac_base + 0x400) & 0xf0; if(priv->rgmii) enet_writeb(priv->enet_mac_base + 0x400, val | 0x01); /* software reset IP */ enet_writeb(priv->enet_mac_base + 0x424, 0); udelay(10); enet_writeb(priv->enet_mac_base + 0x424, 1); /*set threshold for internal clock 0x1*/ enet_writeb(ENET_IC_THRESHOLD(priv->enet_mac_base), 1); /*set Random seed 0x8*/ enet_writeb(ENET_RANDOM_SEED(priv->enet_mac_base), 0x08); /*set TX single deferral params 0xc*/ enet_writeb(ENET_TX_SDP(priv->enet_mac_base), 0xc); /*set slot time 0x7f for 10/100Mbps*/ enet_writeb(ENET_SLOT_TIME(priv->enet_mac_base), 0x7f); /*set Threshold for partial full 0x7f */ enet_writeb(ENET_PF_THRESHOLD(priv->enet_mac_base), 0x7f); /* configure TX DMA Channels */ val = enet_readl(ENET_TXC_CR(priv->enet_mac_base)); val |= TCR_RS | TCR_LE | TCR_TFI(1) | /*TCR_DIE |*/ TCR_BTS(2); val |= TCR_DM; enet_writel(ENET_TXC_CR(priv->enet_mac_base), val); val = enet_readl(ENET_TXC_CR(priv->enet_mac_base)); /* configure RX DMA Channels */ val = enet_readl(ENET_RXC_CR(priv->enet_mac_base)); val |= (RCR_RS | RCR_LE | RCR_RFI(1) | RCR_BTS(2) | RCR_FI | RCR_DIE /* | RCR_EN*/); val |= RCR_DM; val |= RX_BUF_SIZE << 16; enet_writel(ENET_RXC_CR(priv->enet_mac_base), val); /* configure MAC ctrller */ val = enet_readb(ENET_TX_CTL1(priv->enet_mac_base)); val |= (TX_RETRY_EN | TX_PAD_EN | TX_APPEND_FCS); enet_writeb(ENET_TX_CTL1(priv->enet_mac_base), (unsigned char)val); /* set retry 5 time when collision occurs*/ enet_writeb(ENET_TX_CTL2(priv->enet_mac_base), 5); val = enet_readb(ENET_RX_CTL(priv->enet_mac_base)); val |= (RX_RUNT | RX_PAD_STRIP | RX_SEND_CRC | RX_PAUSE_EN| RX_AF_EN); enet_writeb(ENET_RX_CTL(priv->enet_mac_base), (unsigned char)val); #ifdef ENABLE_MULTICAST /* clear internal multicast address table */ enet_writeb(ENET_MC_INIT(priv->enet_mac_base), 0x00); while(enet_readb(ENET_MC_INIT(priv->enet_mac_base))); DBG("Internal multicast address table is cleared\n"); #endif /* unicast */ /* Threshold for internal clock*/ /* threshold for partial empty*/ /* threshold for partial full */ /* buffer size for transmit must be 1 from the doc however, it's said that using 0xff ??*/ enet_writeb(ENET_TX_BUFSIZE(priv->enet_mac_base), 0xff); /* fifo control */ /*MAC mode*/ enet_mac_config(dev); /* check gmii mode support */ priv->mii.supports_gmii = mii_check_gmii_support(&priv->mii); DBG("gmii support=0x%x id=0x%x\n", priv->mii.supports_gmii, priv->mii.phy_id); return 0; }
static char *radio_pkt(uint8_t channel, uint8_t tx_power) { static phy_packet_t tx_pkt = { .data = tx_pkt.raw_data, .length = 125, }; uint16_t i; for (i = 0; i < 125; i++) { tx_pkt.data[i] = i; } int success; char *ret = NULL; xQueueReceive(radio_queue, &success, 0); // cleanup queue phy_idle(platform_phy); /* * config radio */ if (phy_set_channel(platform_phy, channel)) ON_ERROR("err_set_channel", radio_cleanup); if (phy_set_power(platform_phy, tx_power)) ON_ERROR("err_set_power", radio_cleanup); /* * Send packet * * No interlocking because * Current queue is EVENT_QUEUE_APPLI * phy_ handlers are executed by EVENT_QUEUE_NETWORK */ if (phy_tx_now(platform_phy, &tx_pkt, radio_rx_tx_done)) ON_ERROR("err_tx", radio_cleanup); if (pdTRUE != xQueueReceive(radio_queue, &success, ONE_SECOND) || !success) ON_ERROR("tx_failed", radio_cleanup); // SUCCESS radio_cleanup: phy_reset(platform_phy); return ret; } static char *radio_ping_pong(uint8_t channel, uint8_t tx_power) { char *ret = NULL; int success; static phy_packet_t tx_pkt = { .data = tx_pkt.raw_data, .length = sizeof(RADIO_TX_STR), .raw_data = RADIO_TX_STR, }; static phy_packet_t rx_pkt = {.data = rx_pkt.raw_data}; xQueueReceive(radio_queue, &success, 0); // cleanup queue phy_idle(platform_phy); /* config radio */ if (phy_set_channel(platform_phy, channel)) ON_ERROR("err_set_channel", ping_pong_cleanup); if (phy_set_power(platform_phy, tx_power)) ON_ERROR("err_set_power", ping_pong_cleanup); /* * Send packet * * No interlocking because * Current queue is EVENT_QUEUE_APPLI * phy_ handlers are executed by EVENT_QUEUE_NETWORK */ if (phy_tx_now(platform_phy, &tx_pkt, radio_rx_tx_done)) ON_ERROR("err_tx", ping_pong_cleanup); if (pdTRUE != xQueueReceive(radio_queue, &success, ONE_SECOND) || !success) ON_ERROR("tx_failed", ping_pong_cleanup); /* * Wait for answer */ memset(rx_pkt.raw_data, 0, sizeof(rx_pkt.raw_data)); phy_rx_now(platform_phy, &rx_pkt, radio_rx_tx_done); if (pdTRUE != xQueueReceive(radio_queue, &success, ONE_SECOND) || !success) ON_ERROR("rx_timeout", ping_pong_cleanup); // Packet reception if (strcmp("RX_PKT_HELLO_WORLD", (char *)rx_pkt.raw_data)) ON_ERROR("wrong_packet_received", ping_pong_cleanup); // SUCCESS ret = NULL; ping_pong_cleanup: phy_reset(platform_phy); return ret; } #ifdef IOTLAB_M3 //////// static int test_flash_nand() { static uint8_t buf_EE[256] = {[0 ... 255] = 0xEE}; static uint8_t buf[256] = {[0 ... 255] = 0x00}; // Write subsector 200 and re-read it n25xxx_write_enable(); n25xxx_erase_subsector(0x00c80000); n25xxx_write_enable(); n25xxx_write_page(0x00c80000, buf_EE); n25xxx_read(0x00c80000, buf, sizeof(buf)); n25xxx_write_enable(); n25xxx_erase_subsector(0x00c80000); // check read values return memcmp(buf_EE, buf, sizeof(buf)); } //////// static int cmd_get_light(char *command) { if (strcmp(command, "get_light")) return 1; printf("ACK get_light %f lux\n", isl29020_read_sample()); return 0; } static int cmd_get_pressure(char *command) { if (strcmp(command, "get_pressure")) return 1; uint32_t pressure; lps331ap_read_pres(&pressure); printf("ACK get_pressure %f mbar\n", pressure / 4096.0); return 0; } static int cmd_test_flash_nand(char *command) { if (strcmp(command, "test_flash")) return 1; if (test_flash_nand()) printf("NACK test_flash read_different_write\n"); else printf("ACK test_flash\n"); return 0; } #endif // IOTLAB_M3 /* Leds Commands */ static int cmd_leds_on(char *command) { uint8_t leds = 0; if (1 != sscanf(command, "leds_on %u", &leds)) return 1; leds_on(leds); printf("ACK leds_on %x\n", leds); return 0; } static int cmd_leds_off(char *command) { uint8_t leds = 0; if (1 != sscanf(command, "leds_off %u", &leds)) return 1; leds_off(leds); printf("ACK leds_off %x\n", leds); return 0; }
static int mvphy_reset_88e1149(phy_handle_t *ph) { uint16_t reg; int rv; /* make sure that this PHY uses page 0 (copper) */ phy_write(ph, MVPHY_EADR, 0); reg = phy_read(ph, MVPHY_PSC); /* Disable energy detect mode */ reg &= ~MV_PSC_EN_DETECT_MASK; reg |= MV_PSC_AUTO_X_MODE; reg |= MV_PSC_DOWNSHIFT_EN; reg &= ~MV_PSC_POL_REVERSE; phy_write(ph, MVPHY_PSC, reg); rv = phy_reset(ph); phy_write(ph, MVPHY_EADR, 2); PHY_SET(ph, MVPHY_PSC, MV_PSC_RGMII_POWER_UP); /* * Fix for signal amplitude in 10BASE-T, undocumented. * This is from the Marvell reference source code. */ phy_write(ph, MVPHY_EADR, 255); phy_write(ph, 0x18, 0xaa99); phy_write(ph, 0x17, 0x2011); if (MII_PHY_REV(ph->phy_id) == 0) { /* * EC_U: IEEE A/B 1000BASE-T symmetry failure * * EC_U is rev 0, Ultra 2 is rev 1 (at least the * unit I have), so we trigger on revid. */ phy_write(ph, 0x18, 0xa204); phy_write(ph, 0x17, 0x2002); } /* page 3 is led control */ phy_write(ph, MVPHY_EADR, 3); phy_write(ph, MVPHY_PSC, MV_PSC_LED_LOS_CTRL(1) | /* link/act */ MV_PSC_LED_INIT_CTRL(8) | /* 10 Mbps */ MV_PSC_LED_STA1_CTRL(7) | /* 100 Mbps */ MV_PSC_LED_STA0_CTRL(7)); /* 1000 Mbps */ phy_write(ph, MVPHY_INTEN, 0); phy_write(ph, MVPHY_EADR, 0); /* * Weird... undocumented logic in the Intel e1000g driver. * I'm not sure what these values really do. */ phy_write(ph, MVPHY_PAGE_ADDR, 3); phy_write(ph, MVPHY_PAGE_DATA, 0); return (rv); }