#include <asm/ti-common/keystone_serdes.h>
unsigned int emac_open;
+static struct mii_dev *mdio_bus;
static unsigned int sys_has_mdio = 1;
#ifdef KEYSTONE2_EMAC_GIG_ENABLE
static int gen_get_link_speed(int phy_addr);
-/* EMAC Addresses */
-static volatile struct mdio_regs *adap_mdio =
- (struct mdio_regs *)EMAC_MDIO_BASE_ADDR;
-
int keystone2_eth_read_mac_addr(struct eth_device *dev)
{
struct eth_priv_t *eth_priv;
return 0;
}
-static void keystone2_mdio_reset(void)
+/* MDIO */
+
+static int keystone2_mdio_reset(struct mii_dev *bus)
{
- u_int32_t clkdiv;
+ u_int32_t clkdiv;
+ struct mdio_regs *adap_mdio = bus->priv;
clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
- writel((clkdiv & 0xffff) |
- MDIO_CONTROL_ENABLE |
- MDIO_CONTROL_FAULT |
- MDIO_CONTROL_FAULT_ENABLE,
+ writel((clkdiv & 0xffff) | MDIO_CONTROL_ENABLE |
+ MDIO_CONTROL_FAULT | MDIO_CONTROL_FAULT_ENABLE,
&adap_mdio->control);
while (readl(&adap_mdio->control) & MDIO_CONTROL_IDLE)
;
+
+ return 0;
}
-/* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */
-int keystone2_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data)
+/**
+ * keystone2_mdio_read - read a PHY register via MDIO interface.
+ * Blocks until operation is complete.
+ */
+static int keystone2_mdio_read(struct mii_dev *bus,
+ int addr, int devad, int reg)
{
- int tmp;
+ int tmp;
+ struct mdio_regs *adap_mdio = bus->priv;
while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO)
;
- writel(MDIO_USERACCESS0_GO |
- MDIO_USERACCESS0_WRITE_READ |
- ((reg_num & 0x1f) << 21) |
- ((phy_addr & 0x1f) << 16),
+ writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_READ |
+ ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16),
&adap_mdio->useraccess0);
/* Wait for command to complete */
while ((tmp = readl(&adap_mdio->useraccess0)) & MDIO_USERACCESS0_GO)
;
- if (tmp & MDIO_USERACCESS0_ACK) {
- *data = tmp & 0xffff;
- return 0;
- }
+ if (tmp & MDIO_USERACCESS0_ACK)
+ return tmp & 0xffff;
- *data = -1;
return -1;
}
-/*
- * Write to a PHY register via MDIO inteface.
+/**
+ * keystone2_mdio_write - write to a PHY register via MDIO interface.
* Blocks until operation is complete.
*/
-int keystone2_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data)
+static int keystone2_mdio_write(struct mii_dev *bus,
+ int addr, int devad, int reg, u16 val)
{
+ struct mdio_regs *adap_mdio = bus->priv;
+
while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO)
;
- writel(MDIO_USERACCESS0_GO |
- MDIO_USERACCESS0_WRITE_WRITE |
- ((reg_num & 0x1f) << 21) |
- ((phy_addr & 0x1f) << 16) |
- (data & 0xffff),
- &adap_mdio->useraccess0);
+ writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_WRITE |
+ ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16) |
+ (val & 0xffff), &adap_mdio->useraccess0);
/* Wait for command to complete */
while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO)
/* PHY functions for a generic PHY */
static int gen_get_link_speed(int phy_addr)
{
- u_int16_t tmp;
+ u_int16_t tmp;
- if ((!keystone2_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp)) &&
- (tmp & 0x04)) {
+ tmp = mdio_bus->read(mdio_bus, phy_addr,
+ MDIO_DEVAD_NONE, MII_STATUS_REG);
+ if (tmp & 0x04)
return 0;
- }
return -1;
}
struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
if (sys_has_mdio) {
- if (keystone2_eth_phy_read(eth_priv->phy_addr, 0, &data) ||
- !(data & (1 << 6))) /* speed selection MSB */
+ data = keystone2_mdio_read(mdio_bus, eth_priv->phy_addr,
+ MDIO_DEVAD_NONE, 0);
+ /* speed selection MSB */
+ if (!(data & (1 << 6)))
return;
}
hw_config_streaming_switch();
if (sys_has_mdio) {
- keystone2_mdio_reset();
+ keystone2_mdio_reset(mdio_bus);
link = keystone_get_link_status(dev);
if (link == 0) {
*/
int keystone2_emac_initialize(struct eth_priv_t *eth_priv)
{
+ int res;
struct eth_device *dev;
dev = malloc(sizeof(struct eth_device));
eth_register(dev);
+ /* Register MDIO bus if it's not registered yet */
+ if (!mdio_bus) {
+ mdio_bus = mdio_alloc();
+ mdio_bus->read = keystone2_mdio_read;
+ mdio_bus->write = keystone2_mdio_write;
+ mdio_bus->reset = keystone2_mdio_reset;
+ mdio_bus->priv = (void *)EMAC_MDIO_BASE_ADDR;
+ sprintf(mdio_bus->name, "ethernet-mdio");
+
+ res = mdio_register(mdio_bus);
+ if (res)
+ return res;
+ }
+
return 0;
}