static int cis820x_ack_interrupt(struct phy_device *phydev) { int err = phy_read(phydev, MII_CIS8201_ISTAT); return (err < 0) ? err : 0; }
static irqreturn_t dmfe_interrupt(int irq, void *dev_id) /* for kernel 2.6.20*/ #endif #endif { struct net_device *dev = dev_id; board_info_t *db; int int_status,i; u8 reg_save; DMFE_DBUG(0, "dmfe_interrupt()", 0); /* A real interrupt coming */ db = netdev_priv(dev); spin_lock(&db->lock); /* Save previous register address */ reg_save = inb(db->io_addr); /* Disable all interrupt */ iow(db, DM9KS_IMR, DM9KS_DISINTR); /* Got DM9000/DM9010 interrupt status */ int_status = ior(db, DM9KS_ISR); /* Got ISR */ iow(db, DM9KS_ISR, int_status); /* Clear ISR status */ /* Link status change */ if (int_status & DM9KS_LINK_INTR) { netif_stop_queue(dev); for(i=0; i<500; i++) /*wait link OK, waiting time =0.5s */ { phy_read(db,0x1); if(phy_read(db,0x1) & 0x4) /*Link OK*/ { /* wait for detected Speed */ for(i=0; i<200;i++) udelay(1000); /* set media speed */ if(phy_read(db,0)&0x2000) db->Speed =100; else db->Speed =10; break; } udelay(1000); } netif_wake_queue(dev); //printk("[INTR]i=%d speed=%d\n",i, (int)(db->Speed)); } /* Received the coming packet */ if (int_status & DM9KS_RX_INTR) dmfe_packet_receive(dev); /* Trnasmit Interrupt check */ if (int_status & DM9KS_TX_INTR) dmfe_tx_done(0); if (db->cont_rx_pkt_cnt>=CONT_RX_PKT_CNT) { iow(db, DM9KS_IMR, 0xa2); } else { /* Re-enable interrupt mask */ iow(db, DM9KS_IMR, DM9KS_REGFF); } /* Restore previous register address */ outb(reg_save, db->io_addr); spin_unlock(&db->lock); #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) return IRQ_HANDLED; #endif }
/* marvell_read_status * * Generic status code does not detect Fiber correctly! * Description: * Check the link, then figure out the current state * by comparing what we advertise with what the link partner * advertises. Start by checking the gigabit possibilities, * then move on to 10/100. */ static int marvell_read_status(struct phy_device *phydev) { int adv; int err; int lpa; int status = 0; /* Update the link, but return if there * was an error */ err = genphy_update_link(phydev); if (err) return err; if (AUTONEG_ENABLE == phydev->autoneg) { status = phy_read(phydev, MII_M1011_PHY_STATUS); if (status < 0) return status; lpa = phy_read(phydev, MII_LPA); if (lpa < 0) return lpa; adv = phy_read(phydev, MII_ADVERTISE); if (adv < 0) return adv; lpa &= adv; if (status & MII_M1011_PHY_STATUS_FULLDUPLEX) phydev->duplex = DUPLEX_FULL; else phydev->duplex = DUPLEX_HALF; status = status & MII_M1011_PHY_STATUS_SPD_MASK; phydev->pause = phydev->asym_pause = 0; switch (status) { case MII_M1011_PHY_STATUS_1000: phydev->speed = SPEED_1000; break; case MII_M1011_PHY_STATUS_100: phydev->speed = SPEED_100; break; default: phydev->speed = SPEED_10; break; } if (phydev->duplex == DUPLEX_FULL) { phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0; phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0; } } else { int bmcr = phy_read(phydev, MII_BMCR); if (bmcr < 0) return bmcr; if (bmcr & BMCR_FULLDPLX) phydev->duplex = DUPLEX_FULL; else phydev->duplex = DUPLEX_HALF; if (bmcr & BMCR_SPEED1000) phydev->speed = SPEED_1000; else if (bmcr & BMCR_SPEED100) phydev->speed = SPEED_100; else phydev->speed = SPEED_10; phydev->pause = phydev->asym_pause = 0; } return 0; }
static int m88e1318_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol) { int err, oldpage, temp; oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE); if (wol->wolopts & WAKE_MAGIC) { /* Explicitly switch to page 0x00, just to be sure */ err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x00); if (err < 0) return err; /* Enable the WOL interrupt */ temp = phy_read(phydev, MII_88E1318S_PHY_CSIER); temp |= MII_88E1318S_PHY_CSIER_WOL_EIE; err = phy_write(phydev, MII_88E1318S_PHY_CSIER, temp); if (err < 0) return err; err = phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_88E1318S_PHY_LED_PAGE); if (err < 0) return err; /* Setup LED[2] as interrupt pin (active low) */ temp = phy_read(phydev, MII_88E1318S_PHY_LED_TCR); temp &= ~MII_88E1318S_PHY_LED_TCR_FORCE_INT; temp |= MII_88E1318S_PHY_LED_TCR_INTn_ENABLE; temp |= MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW; err = phy_write(phydev, MII_88E1318S_PHY_LED_TCR, temp); if (err < 0) return err; err = phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_88E1318S_PHY_WOL_PAGE); if (err < 0) return err; /* Store the device address for the magic packet */ err = phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD2, ((phydev->attached_dev->dev_addr[5] << 8) | phydev->attached_dev->dev_addr[4])); if (err < 0) return err; err = phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD1, ((phydev->attached_dev->dev_addr[3] << 8) | phydev->attached_dev->dev_addr[2])); if (err < 0) return err; err = phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD0, ((phydev->attached_dev->dev_addr[1] << 8) | phydev->attached_dev->dev_addr[0])); if (err < 0) return err; /* Clear WOL status and enable magic packet matching */ temp = phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL); temp |= MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS; temp |= MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE; err = phy_write(phydev, MII_88E1318S_PHY_WOL_CTRL, temp); if (err < 0) return err; } else { err = phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_88E1318S_PHY_WOL_PAGE); if (err < 0) return err; /* Clear WOL status and disable magic packet matching */ temp = phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL); temp |= MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS; temp &= ~MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE; err = phy_write(phydev, MII_88E1318S_PHY_WOL_CTRL, temp); if (err < 0) return err; } err = phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage); if (err < 0) return err; return 0; }
static void __init lager_add_rsnd_device(void) { struct platform_device_info cardinfo = { .parent = &platform_bus, .name = "asoc-simple-card", .id = -1, .data = &rsnd_card_info, .size_data = sizeof(struct asoc_simple_card_info), .dma_mask = DMA_BIT_MASK(32), }; i2c_register_board_info(2, i2c2_devices, ARRAY_SIZE(i2c2_devices)); platform_device_register_resndata( &platform_bus, "rcar_sound", -1, rsnd_resources, ARRAY_SIZE(rsnd_resources), &rsnd_info, sizeof(rsnd_info)); platform_device_register_full(&cardinfo); } /* SDHI0 */ static struct sh_mobile_sdhi_info sdhi0_info __initdata = { .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD, .tmio_caps2 = MMC_CAP2_NO_MULTI_READ, .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE, }; static struct resource sdhi0_resources[] __initdata = { DEFINE_RES_MEM(0xee100000, 0x200), DEFINE_RES_IRQ(gic_spi(165)), }; /* SDHI2 */ static struct sh_mobile_sdhi_info sdhi2_info __initdata = { .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD, .tmio_caps2 = MMC_CAP2_NO_MULTI_READ, .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE, }; static struct resource sdhi2_resources[] __initdata = { DEFINE_RES_MEM(0xee140000, 0x100), DEFINE_RES_IRQ(gic_spi(167)), }; /* Internal PCI1 */ static const struct resource pci1_resources[] __initconst = { DEFINE_RES_MEM(0xee0b0000, 0x10000), /* CFG */ DEFINE_RES_MEM(0xee0a0000, 0x10000), /* MEM */ DEFINE_RES_IRQ(gic_spi(112)), }; static const struct platform_device_info pci1_info __initconst = { .parent = &platform_bus, .name = "pci-rcar-gen2", .id = 1, .res = pci1_resources, .num_res = ARRAY_SIZE(pci1_resources), .dma_mask = DMA_BIT_MASK(32), }; static void __init lager_add_usb1_device(void) { platform_device_register_full(&pci1_info); } /* Internal PCI2 */ static const struct resource pci2_resources[] __initconst = { DEFINE_RES_MEM(0xee0d0000, 0x10000), /* CFG */ DEFINE_RES_MEM(0xee0c0000, 0x10000), /* MEM */ DEFINE_RES_IRQ(gic_spi(113)), }; static const struct platform_device_info pci2_info __initconst = { .parent = &platform_bus, .name = "pci-rcar-gen2", .id = 2, .res = pci2_resources, .num_res = ARRAY_SIZE(pci2_resources), .dma_mask = DMA_BIT_MASK(32), }; static void __init lager_add_usb2_device(void) { platform_device_register_full(&pci2_info); } static const struct pinctrl_map lager_pinctrl_map[] = { /* DU (CN10: ARGB0, CN13: LVDS) */ PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7790", "pfc-r8a7790", "du_rgb666", "du"), PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7790", "pfc-r8a7790", "du_sync_1", "du"), PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7790", "pfc-r8a7790", "du_clk_out_0", "du"), /* I2C2 */ PIN_MAP_MUX_GROUP_DEFAULT("i2c-rcar.2", "pfc-r8a7790", "i2c2", "i2c2"), /* QSPI */ PIN_MAP_MUX_GROUP_DEFAULT("qspi.0", "pfc-r8a7790", "qspi_ctrl", "qspi"), PIN_MAP_MUX_GROUP_DEFAULT("qspi.0", "pfc-r8a7790", "qspi_data4", "qspi"), /* SCIF0 (CN19: DEBUG SERIAL0) */ PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.6", "pfc-r8a7790", "scif0_data", "scif0"), /* SCIF1 (CN20: DEBUG SERIAL1) */ PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.7", "pfc-r8a7790", "scif1_data", "scif1"), /* SDHI0 */ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7790", "sdhi0_data4", "sdhi0"), PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7790", "sdhi0_ctrl", "sdhi0"), PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7790", "sdhi0_cd", "sdhi0"), /* SDHI2 */ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-r8a7790", "sdhi2_data4", "sdhi2"), PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-r8a7790", "sdhi2_ctrl", "sdhi2"), PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-r8a7790", "sdhi2_cd", "sdhi2"), /* SSI (CN17: sound) */ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7790", "ssi0129_ctrl", "ssi"), PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7790", "ssi0_data", "ssi"), PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7790", "ssi1_data", "ssi"), PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7790", "audio_clk_a", "audio_clk"), /* MMCIF1 */ PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.1", "pfc-r8a7790", "mmc1_data8", "mmc1"), PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.1", "pfc-r8a7790", "mmc1_ctrl", "mmc1"), /* Ether */ PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-ether", "pfc-r8a7790", "eth_link", "eth"), PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-ether", "pfc-r8a7790", "eth_mdio", "eth"), PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-ether", "pfc-r8a7790", "eth_rmii", "eth"), PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-ether", "pfc-r8a7790", "intc_irq0", "intc"), /* VIN0 */ PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.0", "pfc-r8a7790", "vin0_data24", "vin0"), PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.0", "pfc-r8a7790", "vin0_sync", "vin0"), PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.0", "pfc-r8a7790", "vin0_field", "vin0"), PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.0", "pfc-r8a7790", "vin0_clkenb", "vin0"), PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.0", "pfc-r8a7790", "vin0_clk", "vin0"), /* VIN1 */ PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.1", "pfc-r8a7790", "vin1_data8", "vin1"), PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.1", "pfc-r8a7790", "vin1_clk", "vin1"), /* USB0 */ PIN_MAP_MUX_GROUP_DEFAULT("renesas_usbhs", "pfc-r8a7790", "usb0_ovc_vbus", "usb0"), /* USB1 */ PIN_MAP_MUX_GROUP_DEFAULT("pci-rcar-gen2.1", "pfc-r8a7790", "usb1", "usb1"), /* USB2 */ PIN_MAP_MUX_GROUP_DEFAULT("pci-rcar-gen2.2", "pfc-r8a7790", "usb2", "usb2"), }; static void __init lager_add_standard_devices(void) { int fixed_regulator_idx = 0; int gpio_regulator_idx = 0; r8a7790_clock_init(); pinctrl_register_mappings(lager_pinctrl_map, ARRAY_SIZE(lager_pinctrl_map)); r8a7790_pinmux_init(); r8a7790_add_standard_devices(); platform_device_register_data(&platform_bus, "leds-gpio", -1, &lager_leds_pdata, sizeof(lager_leds_pdata)); platform_device_register_data(&platform_bus, "gpio-keys", -1, &lager_keys_pdata, sizeof(lager_keys_pdata)); regulator_register_always_on(fixed_regulator_idx++, "fixed-3.3V", fixed3v3_power_consumers, ARRAY_SIZE(fixed3v3_power_consumers), 3300000); platform_device_register_resndata(&platform_bus, "sh_mmcif", 1, mmcif1_resources, ARRAY_SIZE(mmcif1_resources), &mmcif1_pdata, sizeof(mmcif1_pdata)); platform_device_register_full(ðer_info); lager_add_du_device(); platform_device_register_resndata(&platform_bus, "qspi", 0, qspi_resources, ARRAY_SIZE(qspi_resources), &qspi_pdata, sizeof(qspi_pdata)); spi_register_board_info(spi_info, ARRAY_SIZE(spi_info)); platform_device_register_data(&platform_bus, "reg-fixed-voltage", fixed_regulator_idx++, &vcc_sdhi0_info, sizeof(struct fixed_voltage_config)); platform_device_register_data(&platform_bus, "reg-fixed-voltage", fixed_regulator_idx++, &vcc_sdhi2_info, sizeof(struct fixed_voltage_config)); platform_device_register_data(&platform_bus, "gpio-regulator", gpio_regulator_idx++, &vccq_sdhi0_info, sizeof(struct gpio_regulator_config)); platform_device_register_data(&platform_bus, "gpio-regulator", gpio_regulator_idx++, &vccq_sdhi2_info, sizeof(struct gpio_regulator_config)); lager_add_camera1_device(); platform_device_register_full(&sata1_info); platform_device_register_resndata(&platform_bus, "usb_phy_rcar_gen2", -1, usbhs_phy_resources, ARRAY_SIZE(usbhs_phy_resources), &usbhs_phy_pdata, sizeof(usbhs_phy_pdata)); lager_register_usbhs(); lager_add_usb1_device(); lager_add_usb2_device(); lager_add_rsnd_device(); platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 0, sdhi0_resources, ARRAY_SIZE(sdhi0_resources), &sdhi0_info, sizeof(struct sh_mobile_sdhi_info)); platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 2, sdhi2_resources, ARRAY_SIZE(sdhi2_resources), &sdhi2_info, sizeof(struct sh_mobile_sdhi_info)); } /* * Ether LEDs on the Lager board are named LINK and ACTIVE which corresponds * to non-default 01 setting of the Micrel KSZ8041 PHY control register 1 bits * 14-15. We have to set them back to 01 from the default 00 value each time * the PHY is reset. It's also important because the PHY's LED0 signal is * connected to SoC's ETH_LINK signal and in the PHY's default mode it will * bounce on and off after each packet, which we apparently want to avoid. */ static int lager_ksz8041_fixup(struct phy_device *phydev) { u16 phyctrl1 = phy_read(phydev, 0x1e); phyctrl1 &= ~0xc000; phyctrl1 |= 0x4000; return phy_write(phydev, 0x1e, phyctrl1); } static void __init lager_init(void) { lager_add_standard_devices(); irq_set_irq_type(irq_pin(0), IRQ_TYPE_LEVEL_LOW); if (IS_ENABLED(CONFIG_PHYLIB)) phy_register_fixup_for_id("r8a7790-ether-ff:01", lager_ksz8041_fixup); }
static int m88e1111_config_init(struct phy_device *phydev) { int err; int temp; if (phy_interface_is_rgmii(phydev)) { temp = phy_read(phydev, MII_M1111_PHY_EXT_CR); if (temp < 0) return temp; if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY); } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { temp &= ~MII_M1111_TX_DELAY; temp |= MII_M1111_RX_DELAY; } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { temp &= ~MII_M1111_RX_DELAY; temp |= MII_M1111_TX_DELAY; } err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp); if (err < 0) return err; temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); if (temp < 0) return temp; temp &= ~(MII_M1111_HWCFG_MODE_MASK); if (temp & MII_M1111_HWCFG_FIBER_COPPER_RES) temp |= MII_M1111_HWCFG_MODE_FIBER_RGMII; else temp |= MII_M1111_HWCFG_MODE_COPPER_RGMII; err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); if (err < 0) return err; } if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); if (temp < 0) return temp; temp &= ~(MII_M1111_HWCFG_MODE_MASK); temp |= MII_M1111_HWCFG_MODE_SGMII_NO_CLK; temp |= MII_M1111_HWCFG_FIBER_COPPER_AUTO; err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); if (err < 0) return err; } if (phydev->interface == PHY_INTERFACE_MODE_RTBI) { temp = phy_read(phydev, MII_M1111_PHY_EXT_CR); if (temp < 0) return temp; temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY); err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp); if (err < 0) return err; temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); if (temp < 0) return temp; temp &= ~(MII_M1111_HWCFG_MODE_MASK | MII_M1111_HWCFG_FIBER_COPPER_RES); temp |= 0x7 | MII_M1111_HWCFG_FIBER_COPPER_AUTO; err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); if (err < 0) return err; /* soft reset */ err = phy_write(phydev, MII_BMCR, BMCR_RESET); if (err < 0) return err; do temp = phy_read(phydev, MII_BMCR); while (temp & BMCR_RESET); temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); if (temp < 0) return temp; temp &= ~(MII_M1111_HWCFG_MODE_MASK | MII_M1111_HWCFG_FIBER_COPPER_RES); temp |= MII_M1111_HWCFG_MODE_COPPER_RTBI | MII_M1111_HWCFG_FIBER_COPPER_AUTO; err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); if (err < 0) return err; } err = marvell_of_reg_init(phydev); if (err < 0) return err; return phy_write(phydev, MII_BMCR, BMCR_RESET); }
static u8 ns_exp_read(struct phy_device *phydev, u16 reg) { phy_write(phydev, NS_EXP_MEM_ADD, reg); return phy_read(phydev, NS_EXP_MEM_DATA); }
/* 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 vsc824x_ack_interrupt(struct phy_device *phydev) { int err = phy_read(phydev, MII_VSC8244_ISTAT); return (err < 0) ? err : 0; }
static int ksz9021_phy_extended_read(struct phy_device *phydev, u32 regnum) { phy_write(phydev, MII_KSZ9021_EXTREG, regnum); return phy_read(phydev, MII_KSZ9021_EXTREG_READ); }
/** * Resets the PHY on the NIC10e 66 * * Revision 2 of the NIC10e board requires a special reset sequence for * the Broadcom BCM8727 PHY device if the SPI-ROM is installed. A normal * reset sequence will prevent the PHY device from working properly. * * Revision 1 of the NIC10e board does not have the SPI-ROM and revision 3 * uses a Vitesse device. Both the revision 1 and revision 3 boards can * use the standard PHY reset code. * * @param phydev - pointer to phy device data structure * * @return 0 for success, -1 on error. */ static int nic10e_phy_reset(struct phy_device *phydev) { int reg; int timeout = 500; int devad = MDIO_DEVAD_NONE; debug("In %s\n", __func__); /* If it's 10G, we need to issue reset through one of the MMDs */ if (!is_10g_interface(phydev->interface)) { printf("%s: Error: phy not 10G interface\n", __func__); return -1; } if (!phydev->mmds) gen10g_discover_mmds(phydev); devad = ffs(phydev->mmds); reg = phy_read(phydev, devad, MII_BMCR); if (reg < 0) { debug("PHY status read failed\n"); return -1; } /* The below sequence comes from the BCM8727 data sheet when the * PMD Adaptive Equalizer is to be configured. * */ reg |= BMCR_RESET; /* The BCM8727 PHY does not recover after a reset command if the SPI-ROM * is installed. */ if (gd->arch.board_desc.rev_major == 2) { debug("Not resetting PHY due to PHY brokeness\n"); return 0; /* For the BCM8727 with the SPI-ROM turn on the SPI interface */ if (phy_write(phydev, devad, BCM8727_MISC_CTRL2, 1) < 0) return -1; } debug("Resetting phy at %d %d\n", phydev->addr, devad); /* Issue soft reset */ if (phy_write(phydev, devad, MII_BMCR, reg) < 0) return -1; if (gd->arch.board_desc.rev_major == 2) { /* General control status register global reset */ if (phy_write(phydev, devad, BCM8727_GEN_CTRL_STAT, 1) < 0) return -1; /* 78 MHz uC clock * Force 8051 SPI port reboot at next reset, * Soft reset the microcontroller */ if (phy_write(phydev, devad, BCM8727_GEN_CTRL_STAT, 0x18c) < 0) return -1; /* Enable microcode upload from external SPI-ROM */ if (phy_write(phydev, devad, BCM8727_MISC_CTRL2, 1) < 0) return -1; /* refclk derived from REFCLK input * 78MHz * Force an 8051 SPI port reboot at next reset * Soft reset of internal logic (register values retained) */ if (phy_write(phydev, devad, BCM8727_GEN_CTRL_STAT, 0x018a) < 0) return -1; /* Take internal logic out of reset */ if (phy_write(phydev, devad, BCM8727_GEN_CTRL_STAT, 0x0188) < 0) return -1; /* Give time to load firmware, spec says 100ms */ mdelay(100); /* Disable serial boot and put SPI eeprom in tri-state mode */ if (phy_write(phydev, devad, BCM8727_MISC_CTRL2, 0) < 0) return -1; } /* * Poll the control register for the reset bit to go to 0 (it is * auto-clearing). This should happen within 0.5 seconds per the * IEEE spec. */ while ((reg & BMCR_RESET) && timeout--) { reg = phy_read(phydev, devad, MII_BMCR); if (reg < 0) { debug("PHY status read failed\n"); return -1; } mdelay(1); } if (reg & BMCR_RESET) { puts("PHY reset timed out\n"); return -1; } return 0; }
static void tc_handle_link_change(struct net_device *dev) { struct tc35815_local *lp = netdev_priv(dev); struct phy_device *phydev = dev->phydev; unsigned long flags; int status_change = 0; spin_lock_irqsave(&lp->lock, flags); if (phydev->link && (lp->speed != phydev->speed || lp->duplex != phydev->duplex)) { struct tc35815_regs __iomem *tr = (struct tc35815_regs __iomem *)dev->base_addr; u32 reg; reg = tc_readl(&tr->MAC_Ctl); reg |= MAC_HaltReq; tc_writel(reg, &tr->MAC_Ctl); if (phydev->duplex == DUPLEX_FULL) reg |= MAC_FullDup; else reg &= ~MAC_FullDup; tc_writel(reg, &tr->MAC_Ctl); reg &= ~MAC_HaltReq; tc_writel(reg, &tr->MAC_Ctl); /* * TX4939 PCFG.SPEEDn bit will be changed on * NETDEV_CHANGE event. */ /* * WORKAROUND: enable LostCrS only if half duplex * operation. * (TX4939 does not have EnLCarr) */ if (phydev->duplex == DUPLEX_HALF && lp->chiptype != TC35815_TX4939) tc_writel(tc_readl(&tr->Tx_Ctl) | Tx_EnLCarr, &tr->Tx_Ctl); lp->speed = phydev->speed; lp->duplex = phydev->duplex; status_change = 1; } if (phydev->link != lp->link) { if (phydev->link) { /* delayed promiscuous enabling */ if (dev->flags & IFF_PROMISC) tc35815_set_multicast_list(dev); } else { lp->speed = 0; lp->duplex = -1; } lp->link = phydev->link; status_change = 1; } spin_unlock_irqrestore(&lp->lock, flags); if (status_change && netif_msg_link(lp)) { phy_print_status(phydev); pr_debug("%s: MII BMCR %04x BMSR %04x LPA %04x\n", dev->name, phy_read(phydev, MII_BMCR), phy_read(phydev, MII_BMSR), phy_read(phydev, MII_LPA)); } }
/** * genphy_read_status - check the link status and update current link state * @phydev: target phy_device struct * * Description: Check the link, then figure out the current state * by comparing what we advertise with what the link partner * advertises. Start by checking the gigabit possibilities, * then move on to 10/100. */ int genphy_read_status(struct phy_device *phydev) { int adv; int err; int lpa; int lpagb = 0; /* Update the link, but return if there * was an error */ err = genphy_update_link(phydev); if (err) return err; if (AUTONEG_ENABLE == phydev->autoneg) { if (phydev->supported & (SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)) { lpagb = phy_read(phydev, MII_STAT1000); if (lpagb < 0) return lpagb; adv = phy_read(phydev, MII_CTRL1000); if (adv < 0) return adv; lpagb &= adv << 2; } lpa = phy_read(phydev, MII_LPA); if (lpa < 0) return lpa; adv = phy_read(phydev, MII_ADVERTISE); if (adv < 0) return adv; lpa &= adv; phydev->speed = SPEED_10; phydev->duplex = DUPLEX_HALF; phydev->pause = phydev->asym_pause = 0; if (lpagb & (LPA_1000FULL | LPA_1000HALF)) { phydev->speed = SPEED_1000; if (lpagb & LPA_1000FULL) phydev->duplex = DUPLEX_FULL; } else if (lpa & (LPA_100FULL | LPA_100HALF)) { phydev->speed = SPEED_100; if (lpa & LPA_100FULL) phydev->duplex = DUPLEX_FULL; } else if (lpa & LPA_10FULL) phydev->duplex = DUPLEX_FULL; if (phydev->duplex == DUPLEX_FULL){ phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0; phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0; } } else { int bmcr = phy_read(phydev, MII_BMCR); if (bmcr < 0) return bmcr; if (bmcr & BMCR_FULLDPLX) phydev->duplex = DUPLEX_FULL; else phydev->duplex = DUPLEX_HALF; if (bmcr & BMCR_SPEED1000) phydev->speed = SPEED_1000; else if (bmcr & BMCR_SPEED100) phydev->speed = SPEED_100; else phydev->speed = SPEED_10; phydev->pause = phydev->asym_pause = 0; } return 0; }
static int dp83867_config(struct phy_device *phydev) { struct dp83867_private *dp83867; unsigned int val, delay, cfg2; int ret; if (!phydev->priv) { dp83867 = kzalloc(sizeof(*dp83867), GFP_KERNEL); if (!dp83867) return -ENOMEM; phydev->priv = dp83867; ret = dp83867_of_init(phydev); if (ret) goto err_out; } else { dp83867 = (struct dp83867_private *)phydev->priv; } /* Restart the PHY. */ val = phy_read(phydev, MDIO_DEVAD_NONE, DP83867_CTRL); phy_write(phydev, MDIO_DEVAD_NONE, DP83867_CTRL, val | DP83867_SW_RESTART); if (phy_interface_is_rgmii(phydev)) { ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL, (DP83867_MDI_CROSSOVER_AUTO << DP83867_MDI_CROSSOVER) | (dp83867->fifo_depth << DP83867_PHYCR_FIFO_DEPTH_SHIFT)); if (ret) goto err_out; } else if (phy_interface_is_sgmii(phydev)) { phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, (BMCR_ANENABLE | BMCR_FULLDPLX | BMCR_SPEED1000)); cfg2 = phy_read(phydev, phydev->addr, MII_DP83867_CFG2); cfg2 &= MII_DP83867_CFG2_MASK; cfg2 |= (MII_DP83867_CFG2_SPEEDOPT_10EN | MII_DP83867_CFG2_SGMII_AUTONEGEN | MII_DP83867_CFG2_SPEEDOPT_ENH | MII_DP83867_CFG2_SPEEDOPT_CNT | MII_DP83867_CFG2_SPEEDOPT_INTLOW); phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_CFG2, cfg2); phy_write_mmd_indirect(phydev, DP83867_RGMIICTL, DP83867_DEVADDR, phydev->addr, 0x0); phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL, DP83867_PHYCTRL_SGMIIEN | (DP83867_MDI_CROSSOVER_MDIX << DP83867_MDI_CROSSOVER) | (dp83867->fifo_depth << DP83867_PHYCTRL_RXFIFO_SHIFT) | (dp83867->fifo_depth << DP83867_PHYCTRL_TXFIFO_SHIFT)); phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_BISCR, 0x0); } if (phy_interface_is_rgmii(phydev)) { val = phy_read_mmd_indirect(phydev, DP83867_RGMIICTL, DP83867_DEVADDR, phydev->addr); if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) val |= (DP83867_RGMII_TX_CLK_DELAY_EN | DP83867_RGMII_RX_CLK_DELAY_EN); if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) val |= DP83867_RGMII_TX_CLK_DELAY_EN; if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) val |= DP83867_RGMII_RX_CLK_DELAY_EN; phy_write_mmd_indirect(phydev, DP83867_RGMIICTL, DP83867_DEVADDR, phydev->addr, val); delay = (dp83867->rx_id_delay | (dp83867->tx_id_delay << DP83867_RGMII_TX_CLK_DELAY_SHIFT)); phy_write_mmd_indirect(phydev, DP83867_RGMIIDCTL, DP83867_DEVADDR, phydev->addr, delay); if (dp83867->io_impedance >= 0) { val = phy_read_mmd_indirect(phydev, DP83867_IO_MUX_CFG, DP83867_DEVADDR, phydev->addr); val &= ~DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL; val |= dp83867->io_impedance & DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL; phy_write_mmd_indirect(phydev, DP83867_IO_MUX_CFG, DP83867_DEVADDR, phydev->addr, val); } } genphy_config_aneg(phydev); return 0; err_out: kfree(dp83867); return ret; }
static int tlk106_config_intr(struct phy_device *phydev) { int temp, rc; if(PHY_INTERRUPT_ENABLED == phydev->interrupts) { temp = phy_read(phydev, TLK106_PHYSCR); temp |= 0x0010; /* Set Interrupt Pin as Active Low */ temp |= 0x0002; /* Enable Interrupts */ temp |= 0x0001; /* Enable Interrupt Output Pin */ rc = phy_write(phydev, TLK106_PHYSCR, temp); if(rc < 0) { return(rc); } temp = phy_read(phydev, TLK106_MISR1); temp |= 0x0020; /* Enable Interrupt for Change of Link Status */ temp |= 0x0010; /* Enable Interrupt for Change of Speed */ temp |= 0x0008; /* Enable Interrupt for Change of Duplex Mode */ temp |= 0x0004; /* Enable Interrupt for Auto Negotiation Completed */ temp |= 0x0002; /* Enable Interrupt for False Carrier Counter Register half-full event */ temp |= 0x0001; /* Enable Interrupt for Receiver Error Counter Register half-full event */ rc = phy_write(phydev, TLK106_MISR1, temp); if(rc < 0) { return(rc); } temp = phy_read(phydev, TLK106_MISR2); temp |= 0x0040; /* Enable Interrupt for Auto-Negotiation error event */ temp |= 0x0020; /* Enable Interrupt for Page receive event */ temp |= 0x0010; /* Enable Interrupt for Loopback FIFO overflow/underflow event */ temp |= 0x0008; /* Enable Interrupt for Change of MDI/X status */ temp |= 0x0004; /* Enable Interrupt for Sleep mode event */ temp |= 0x0002; /* Enable Interrupt for Change of polarity status */ temp |= 0x0001; /* Enable Interrupt for Jabber detection event */ rc = phy_write(phydev, TLK106_MISR2, temp); if(rc < 0) { return(rc); } } else { temp = phy_read(phydev, TLK106_PHYSCR); temp |= 0x0010; /* Set Interrupt Pin as Active Low */ temp &= ~0x0002; /* Disable Interrupts */ temp &= ~0x0001; /* Disable Interrupt Output Pin */ rc = phy_write(phydev, TLK106_PHYSCR, temp); if(rc < 0) { return(rc); } temp = phy_read(phydev, TLK106_MISR1); temp &= ~0x0020; /* Disable Interrupt for Change of Link Status */ temp &= ~0x0010; /* Disable Interrupt for Change of Speed */ temp &= ~0x0008; /* Disable Interrupt for Change of Duplex Mode */ temp &= ~0x0004; /* Disable Interrupt for Auto Negotiation Completed */ temp &= ~0x0002; /* Disable Interrupt for False Carrier Counter Register half-full event */ temp &= ~0x0001; /* Disable Interrupt for Receiver Error Counter Register half-full event */ rc = phy_write(phydev, TLK106_MISR1, temp); if(rc < 0) { return(rc); } temp = phy_read(phydev, TLK106_MISR2); temp &= ~0x0040; /* Disable Interrupt for Auto-Negotiation error event */ temp &= ~0x0020; /* Disable Interrupt for Page receive event */ temp &= ~0x0010; /* Disable Interrupt for Loopback FIFO overflow/underflow event */ temp &= ~0x0008; /* Disable Interrupt for Change of MDI/X status */ temp &= ~0x0004; /* Disable Interrupt for Sleep mode event */ temp &= ~0x0002; /* Disable Interrupt for Change of polarity status */ temp &= ~0x0001; /* Disable Interrupt for Jabber detection event */ rc = phy_write(phydev, TLK106_MISR2, temp); if(rc < 0) { return(rc); } } return(0); }
// // Initialize the interface - performed at system startup // This function must set up the interface, including arranging to // handle interrupts, etc, so that it may be "started" cheaply later. // static bool fec_eth_init(struct cyg_netdevtab_entry *tab) { struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance; struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private; volatile EPPC *eppc = (volatile EPPC *)eppc_base(); volatile struct fec *fec = (volatile struct fec *)((unsigned char *)eppc + FEC_OFFSET); unsigned short phy_state = 0; int cache_state; int i; unsigned long proc_rev; bool esa_ok, phy_ok; int phy_timeout = 5*1000; // Wait 5 seconds max for link to clear // Ensure consistent state between cache and what the FEC sees HAL_DCACHE_IS_ENABLED(cache_state); HAL_DCACHE_SYNC(); HAL_DCACHE_DISABLE(); qi->fec = fec; fec_eth_stop(sc); // Make sure it's not running yet #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED #ifdef _FEC_USE_INTS // Set up to handle interrupts cyg_drv_interrupt_create(FEC_ETH_INT, CYGARC_SIU_PRIORITY_HIGH, (cyg_addrword_t)sc, // Data item passed to interrupt handler (cyg_ISR_t *)fec_eth_isr, (cyg_DSR_t *)eth_drv_dsr, &fec_eth_interrupt_handle, &fec_eth_interrupt); cyg_drv_interrupt_attach(fec_eth_interrupt_handle); cyg_drv_interrupt_acknowledge(FEC_ETH_INT); cyg_drv_interrupt_unmask(FEC_ETH_INT); #else // _FEC_USE_INTS // Hack - use a thread to simulate interrupts cyg_thread_create(1, // Priority fec_fake_int, // entry (cyg_addrword_t)sc, // entry parameter "CS8900 int", // Name &fec_fake_int_stack[0], // Stack STACK_SIZE, // Size &fec_fake_int_thread_handle, // Handle &fec_fake_int_thread_data // Thread data structure ); cyg_thread_resume(fec_fake_int_thread_handle); // Start it #endif #endif // Set up parallel port for connection to ethernet tranceiver eppc->pio_pdpar = 0x1FFF; CYGARC_MFSPR( CYGARC_REG_PVR, proc_rev ); #define PROC_REVB 0x0020 if ((proc_rev & 0x0000FFFF) == PROC_REVB) { eppc->pio_pddir = 0x1C58; } else { eppc->pio_pddir = 0x1FFF; } // Get physical device address #ifdef CYGPKG_REDBOOT esa_ok = flash_get_config("fec_esa", enaddr, CONFIG_ESA); #else esa_ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET, "fec_esa", enaddr, CONFIG_ESA); #endif if (!esa_ok) { // Can't figure out ESA os_printf("FEC_ETH - Warning! ESA unknown\n"); memcpy(&enaddr, &_default_enaddr, sizeof(enaddr)); } // Configure the device if (!fec_eth_reset(sc, enaddr, 0)) { return false; } // Reset PHY (transceiver) eppc->pip_pbdat &= ~0x00004000; // Reset PHY chip CYGACC_CALL_IF_DELAY_US(10000); // 10ms eppc->pip_pbdat |= 0x00004000; // Enable PHY chip // Enable transceiver (PHY) phy_ok = 0; phy_write(PHY_BMCR, 0, PHY_BMCR_RESET); for (i = 0; i < 10; i++) { phy_ok = phy_read(PHY_BMCR, 0, &phy_state); if (!phy_ok) break; if (!(phy_state & PHY_BMCR_RESET)) break; } if (!phy_ok || (phy_state & PHY_BMCR_RESET)) { os_printf("FEC: Can't get PHY unit to reset: %x\n", phy_state); return false; } fec->iEvent = 0xFFFFFFFF; // Clear all interrupts phy_write(PHY_BMCR, 0, PHY_BMCR_AUTO_NEG|PHY_BMCR_RESTART); while (phy_timeout-- >= 0) { int ev = fec->iEvent; unsigned short state; fec->iEvent = ev; if (ev & iEvent_MII) { phy_ok = phy_read(PHY_BMSR, 0, &state); if (phy_ok && (state & PHY_BMSR_AUTO_NEG)) { // os_printf("State: %x\n", state); break; } else { CYGACC_CALL_IF_DELAY_US(1000); // 1ms } } } if (phy_timeout <= 0) { os_printf("** FEC Warning: PHY auto-negotiation failed\n"); } // Initialize upper level driver (sc->funs->eth_drv->init)(sc, (unsigned char *)&enaddr); return true; }
static int m88e1145_config_init(struct phy_device *phydev) { int err; /* Take care of errata E0 & E1 */ err = phy_write(phydev, 0x1d, 0x001b); if (err < 0) return err; err = phy_write(phydev, 0x1e, 0x418f); if (err < 0) return err; err = phy_write(phydev, 0x1d, 0x0016); if (err < 0) return err; err = phy_write(phydev, 0x1e, 0xa2da); if (err < 0) return err; if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR); if (temp < 0) return temp; temp |= (MII_M1145_RGMII_RX_DELAY | MII_M1145_RGMII_TX_DELAY); err = phy_write(phydev, MII_M1145_PHY_EXT_CR, temp); if (err < 0) return err; if (phydev->dev_flags & M1145_DEV_FLAGS_RESISTANCE) { err = phy_write(phydev, 0x1d, 0x0012); if (err < 0) return err; temp = phy_read(phydev, 0x1e); if (temp < 0) return temp; temp &= 0xf03f; temp |= 2 << 9; /* 36 ohm */ temp |= 2 << 6; /* 39 ohm */ err = phy_write(phydev, 0x1e, temp); if (err < 0) return err; err = phy_write(phydev, 0x1d, 0x3); if (err < 0) return err; err = phy_write(phydev, 0x1e, 0x8000); if (err < 0) return err; } } 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; }
static int lan87xx_phy_ack_interrupt(struct phy_device *phydev) { int rc = phy_read(phydev, LAN87XX_INTERRUPT_SOURCE); return rc < 0 ? rc : 0; }
static int marvell_config_aneg(struct phy_device *phydev) { int err; /* The Marvell PHY has an errata which requires * that certain registers get written in order * to restart autonegotiation */ err = phy_write(phydev, MII_BMCR, BMCR_RESET); if (err < 0) return err; err = phy_write(phydev, 0x1d, 0x1f); if (err < 0) return err; err = phy_write(phydev, 0x1e, 0x200c); if (err < 0) return err; err = phy_write(phydev, 0x1d, 0x5); if (err < 0) return err; err = phy_write(phydev, 0x1e, 0); if (err < 0) return err; err = phy_write(phydev, 0x1e, 0x100); if (err < 0) return err; err = marvell_set_polarity(phydev, phydev->mdix); if (err < 0) return err; err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL, MII_M1111_PHY_LED_DIRECT); if (err < 0) return err; err = genphy_config_aneg(phydev); if (err < 0) return err; if (phydev->autoneg != AUTONEG_ENABLE) { int bmcr; /* * A write to speed/duplex bits (that is performed by * genphy_config_aneg() call above) must be followed by * a software reset. Otherwise, the write has no effect. */ bmcr = phy_read(phydev, MII_BMCR); if (bmcr < 0) return bmcr; err = phy_write(phydev, MII_BMCR, bmcr | BMCR_RESET); if (err < 0) return err; } return 0; }
int bcm_phy_read_shadow(struct phy_device *phydev, u16 shadow) { phy_write(phydev, MII_BCM54XX_SHD, MII_BCM54XX_SHD_VAL(shadow)); return MII_BCM54XX_SHD_DATA(phy_read(phydev, MII_BCM54XX_SHD)); }
static int m88e1145_config_init(struct phy_device *phydev) { int err; int temp; /* Take care of errata E0 & E1 */ err = phy_write(phydev, 0x1d, 0x001b); if (err < 0) return err; err = phy_write(phydev, 0x1e, 0x418f); if (err < 0) return err; err = phy_write(phydev, 0x1d, 0x0016); if (err < 0) return err; err = phy_write(phydev, 0x1e, 0xa2da); if (err < 0) return err; if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR); if (temp < 0) return temp; temp |= (MII_M1145_RGMII_RX_DELAY | MII_M1145_RGMII_TX_DELAY); err = phy_write(phydev, MII_M1145_PHY_EXT_CR, temp); if (err < 0) return err; if (phydev->dev_flags & MARVELL_PHY_M1145_FLAGS_RESISTANCE) { err = phy_write(phydev, 0x1d, 0x0012); if (err < 0) return err; temp = phy_read(phydev, 0x1e); if (temp < 0) return temp; temp &= 0xf03f; temp |= 2 << 9; /* 36 ohm */ temp |= 2 << 6; /* 39 ohm */ err = phy_write(phydev, 0x1e, temp); if (err < 0) return err; err = phy_write(phydev, 0x1d, 0x3); if (err < 0) return err; err = phy_write(phydev, 0x1e, 0x8000); if (err < 0) return err; } } if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { temp = phy_read(phydev, MII_M1145_PHY_EXT_SR); if (temp < 0) return temp; temp &= ~MII_M1145_HWCFG_MODE_MASK; temp |= MII_M1145_HWCFG_MODE_SGMII_NO_CLK; temp |= MII_M1145_HWCFG_FIBER_COPPER_AUTO; err = phy_write(phydev, MII_M1145_PHY_EXT_SR, temp); if (err < 0) return err; } err = marvell_of_reg_init(phydev); if (err < 0) return err; return 0; }
static int m88e1116r_config_init(struct phy_device *phydev) { int temp; int err; temp = phy_read(phydev, MII_BMCR); temp |= BMCR_RESET; err = phy_write(phydev, MII_BMCR, temp); if (err < 0) return err; mdelay(500); err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0); if (err < 0) return err; temp = phy_read(phydev, MII_M1011_PHY_SCR); temp |= (7 << 12); /* max number of gigabit attempts */ temp |= (1 << 11); /* enable downshift */ temp |= MII_M1011_PHY_SCR_AUTO_CROSS; err = phy_write(phydev, MII_M1011_PHY_SCR, temp); if (err < 0) return err; err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 2); if (err < 0) return err; temp = phy_read(phydev, MII_M1116R_CONTROL_REG_MAC); temp &= ~(1 << 5); /* @@ NetModule, da, set correct mode for ZE7000 board */ temp |= (1 << 4); err = phy_write(phydev, MII_M1116R_CONTROL_REG_MAC, temp); if (err < 0) return err; /* @@ NetModule, da, LED settings */ err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 3); if (err < 0) return err; temp = 0x1040; err = phy_write(phydev, 16, temp); if (err < 0) return err; temp = 0x4405; err = phy_write(phydev, 17, temp); if (err < 0) return err; err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0); if (err < 0) return err; temp = phy_read(phydev, MII_BMCR); temp |= BMCR_RESET; err = phy_write(phydev, MII_BMCR, temp); if (err < 0) return err; mdelay(500); return 0; }
static int marvell_aneg_done(struct phy_device *phydev) { int retval = phy_read(phydev, MII_M1011_PHY_STATUS); return (retval < 0) ? retval : (retval & MII_M1011_PHY_STATUS_RESOLVED); }
static int lxt973a2_read_status(struct phy_device *phydev) { int adv; int err; int lpa; int lpagb = 0; /* Update the link, but return if there was an error */ err = lxt973a2_update_link(phydev); if (err) return err; if (AUTONEG_ENABLE == phydev->autoneg) { int retry = 1; adv = phy_read(phydev, MII_ADVERTISE); if (adv < 0) return adv; do { lpa = phy_read(phydev, MII_LPA); if (lpa < 0) return lpa; /* If both registers are equal, it is suspect but not * impossible, hence a new try */ } while (lpa == adv && retry--); lpa &= adv; phydev->speed = SPEED_10; phydev->duplex = DUPLEX_HALF; phydev->pause = phydev->asym_pause = 0; if (lpagb & (LPA_1000FULL | LPA_1000HALF)) { phydev->speed = SPEED_1000; if (lpagb & LPA_1000FULL) phydev->duplex = DUPLEX_FULL; } else if (lpa & (LPA_100FULL | LPA_100HALF)) { phydev->speed = SPEED_100; if (lpa & LPA_100FULL) phydev->duplex = DUPLEX_FULL; } else { if (lpa & LPA_10FULL) phydev->duplex = DUPLEX_FULL; } if (phydev->duplex == DUPLEX_FULL) { phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0; phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0; } } else { int bmcr = phy_read(phydev, MII_BMCR); if (bmcr < 0) return bmcr; if (bmcr & BMCR_FULLDPLX) phydev->duplex = DUPLEX_FULL; else phydev->duplex = DUPLEX_HALF; if (bmcr & BMCR_SPEED1000) phydev->speed = SPEED_1000; else if (bmcr & BMCR_SPEED100) phydev->speed = SPEED_100; else phydev->speed = SPEED_10; phydev->pause = phydev->asym_pause = 0; } return 0; }
static int xilinxphy_read_status(struct phy_device *phydev) { int err; int status = 0; /* Update the link, but return if there * was an error */ err = genphy_update_link(phydev); if (err) return err; if (AUTONEG_ENABLE == phydev->autoneg) { status = phy_read(phydev, MII_LPA); if (status & MII_PHY_STATUS_FULLDUPLEX) phydev->duplex = DUPLEX_FULL; else phydev->duplex = DUPLEX_HALF; switch (status & MII_PHY_STATUS_SPD_MASK) { case MII_PHY_STATUS_1000: phydev->speed = SPEED_1000; break; case MII_PHY_STATUS_100: phydev->speed = SPEED_100; break; default: phydev->speed = SPEED_10; break; } } else { int bmcr = phy_read(phydev, MII_BMCR); if (bmcr < 0) return bmcr; if (bmcr & BMCR_FULLDPLX) phydev->duplex = DUPLEX_FULL; else phydev->duplex = DUPLEX_HALF; if (bmcr & BMCR_SPEED1000) phydev->speed = SPEED_1000; else if (bmcr & BMCR_SPEED100) phydev->speed = SPEED_100; else phydev->speed = SPEED_10; } /* For 1000BASE-X Phy Mode the speed/duplex will always be * 1000Mbps/fullduplex */ if (phydev->dev_flags == XAE_PHY_TYPE_1000BASE_X) { phydev->duplex = DUPLEX_FULL; phydev->speed = SPEED_1000; } return 0; }
static int smsc_phy_ack_interrupt(struct phy_device *phydev) { int rc = phy_read (phydev, MII_LAN83C185_ISF); return rc < 0 ? rc : 0; }
int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum) { /* extended registers */ phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_CTRL, regnum); return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_DATAR); }
/* Set PHY operationg mode */ static void set_PHY_mode(board_info_t *db) { #ifndef DM8606 u16 phy_reg0 = 0x1000;/* Auto-negotiation*/ u16 phy_reg4 = 0x01e1; if ( !(db->op_mode & DM9KS_AUTO) ) // op_mode didn't auto sense */ { switch(db->op_mode) { case DM9KS_10MHD: phy_reg4 = 0x21; phy_reg0 = 0x1000; break; case DM9KS_10MFD: phy_reg4 = 0x41; phy_reg0 = 0x1100; break; case DM9KS_100MHD: phy_reg4 = 0x81; phy_reg0 = 0x3000; break; case DM9KS_100MFD: phy_reg4 = 0x101; phy_reg0 = 0x3100; break; default: break; } // end of switch } // end of if #ifdef FLOW_CONTROL phy_write(db, 4, phy_reg4|(1<<10)); #else phy_write(db, 4, phy_reg4); #endif //end of FLOW_CONTROL phy_write(db, 0, phy_reg0|0x200); #else /* Fiber mode */ phy_write(db, 16, 0x4014); phy_write(db, 0, 0x2100); #endif //end of DM8606 if (db->chip_revision == 0x1A) { //set 10M TX idle =65mA (TX 100% utility is 160mA) phy_write(db,20, phy_read(db,20)|(1<<11)|(1<<10)); //:fix harmonic //For short code: //PHY_REG 27 (1Bh) <- 0000h phy_write(db, 27, 0x0000); //PHY_REG 27 (1Bh) <- AA00h phy_write(db, 27, 0xaa00); //PHY_REG 27 (1Bh) <- 0017h phy_write(db, 27, 0x0017); //PHY_REG 27 (1Bh) <- AA17h phy_write(db, 27, 0xaa17); //PHY_REG 27 (1Bh) <- 002Fh phy_write(db, 27, 0x002f); //PHY_REG 27 (1Bh) <- AA2Fh phy_write(db, 27, 0xaa2f); //PHY_REG 27 (1Bh) <- 0037h phy_write(db, 27, 0x0037); //PHY_REG 27 (1Bh) <- AA37h phy_write(db, 27, 0xaa37); //PHY_REG 27 (1Bh) <- 0040h phy_write(db, 27, 0x0040); //PHY_REG 27 (1Bh) <- AA40h phy_write(db, 27, 0xaa40); //For long code: //PHY_REG 27 (1Bh) <- 0050h phy_write(db, 27, 0x0050); //PHY_REG 27 (1Bh) <- AA50h phy_write(db, 27, 0xaa50); //PHY_REG 27 (1Bh) <- 006Bh phy_write(db, 27, 0x006b); //PHY_REG 27 (1Bh) <- AA6Bh phy_write(db, 27, 0xaa6b); //PHY_REG 27 (1Bh) <- 007Dh phy_write(db, 27, 0x007d); //PHY_REG 27 (1Bh) <- AA7Dh phy_write(db, 27, 0xaa7d); //PHY_REG 27 (1Bh) <- 008Dh phy_write(db, 27, 0x008d); //PHY_REG 27 (1Bh) <- AA8Dh phy_write(db, 27, 0xaa8d); //PHY_REG 27 (1Bh) <- 009Ch phy_write(db, 27, 0x009c); //PHY_REG 27 (1Bh) <- AA9Ch phy_write(db, 27, 0xaa9c); //PHY_REG 27 (1Bh) <- 00A3h phy_write(db, 27, 0x00a3); //PHY_REG 27 (1Bh) <- AAA3h phy_write(db, 27, 0xaaa3); //PHY_REG 27 (1Bh) <- 00B1h phy_write(db, 27, 0x00b1); //PHY_REG 27 (1Bh) <- AAB1h phy_write(db, 27, 0xaab1); //PHY_REG 27 (1Bh) <- 00C0h phy_write(db, 27, 0x00c0); //PHY_REG 27 (1Bh) <- AAC0h phy_write(db, 27, 0xaac0); //PHY_REG 27 (1Bh) <- 00D2h phy_write(db, 27, 0x00d2); //PHY_REG 27 (1Bh) <- AAD2h phy_write(db, 27, 0xaad2); //PHY_REG 27 (1Bh) <- 00E0h phy_write(db, 27, 0x00e0); //PHY_REG 27 (1Bh) <- AAE0h phy_write(db, 27, 0xaae0); //PHY_REG 27 (1Bh) <- 0000h phy_write(db, 27, 0x0000); } }