mirror of
https://git.codelinaro.org/clo/qsdk/oss/boot/u-boot-2016.git
synced 2026-03-14 21:10:27 +01:00
ipq40xx, ipq807x hardware share the qca8075 phy. So the qca8075 phy mdio, driver has been moved to common directory for use by both the hardware. Change-Id: Id6e9342438ffbdf8599860df6fbb39bba30429b3 Signed-off-by: Jaiganesh Narayanan <njaigane@codeaurora.org>
121 lines
2.6 KiB
C
121 lines
2.6 KiB
C
/*
|
|
* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 and
|
|
* only version 2 as published by the Free Software Foundation.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <miiphy.h>
|
|
#include <phy.h>
|
|
#include <asm/io.h>
|
|
#include <errno.h>
|
|
#include "ipq_mdio.h"
|
|
|
|
struct ipq_mdio_data {
|
|
struct mii_bus *bus;
|
|
int phy_irq[PHY_MAX_ADDR];
|
|
};
|
|
|
|
static int ipq_mdio_wait_busy(void)
|
|
{
|
|
int i;
|
|
u32 busy;
|
|
for (i = 0; i < IPQ_MDIO_RETRY; i++) {
|
|
udelay(IPQ_MDIO_DELAY);
|
|
busy = readl(IPQ_MDIO_BASE +
|
|
MDIO_CTRL_4_REG) &
|
|
MDIO_CTRL_4_ACCESS_BUSY;
|
|
|
|
if (!busy)
|
|
return 0;
|
|
udelay(IPQ_MDIO_DELAY);
|
|
}
|
|
printf("%s: MDIO operation timed out\n",
|
|
__func__);
|
|
return -ETIMEDOUT;
|
|
}
|
|
|
|
int ipq_mdio_write(int mii_id, int regnum, u16 value)
|
|
{
|
|
if (ipq_mdio_wait_busy())
|
|
return -ETIMEDOUT;
|
|
/* Issue the phy addreass and reg */
|
|
writel((mii_id << 8 | regnum),
|
|
IPQ_MDIO_BASE + MDIO_CTRL_1_REG);
|
|
|
|
/* Issue a write data */
|
|
writel(value, IPQ_MDIO_BASE + MDIO_CTRL_2_REG);
|
|
|
|
/* Issue write command */
|
|
writel((MDIO_CTRL_4_ACCESS_START |
|
|
MDIO_CTRL_4_ACCESS_CODE_WRITE),
|
|
(IPQ_MDIO_BASE + MDIO_CTRL_4_REG));
|
|
|
|
/* Wait for write complete */
|
|
|
|
if (ipq_mdio_wait_busy())
|
|
return -ETIMEDOUT;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int ipq_mdio_read(int mii_id, int regnum, ushort *data)
|
|
{
|
|
u32 val;
|
|
if (ipq_mdio_wait_busy())
|
|
return -ETIMEDOUT;
|
|
|
|
/* Issue the phy address and reg */
|
|
writel((mii_id << 8) | regnum,
|
|
IPQ_MDIO_BASE + MDIO_CTRL_1_REG);
|
|
|
|
/* issue read command */
|
|
writel((MDIO_CTRL_4_ACCESS_START |
|
|
MDIO_CTRL_4_ACCESS_CODE_READ),
|
|
(IPQ_MDIO_BASE + MDIO_CTRL_4_REG));
|
|
|
|
if (ipq_mdio_wait_busy())
|
|
return -ETIMEDOUT;
|
|
|
|
/* Read data */
|
|
val = readl(IPQ_MDIO_BASE + MDIO_CTRL_3_REG);
|
|
|
|
if (data != NULL)
|
|
*data = val;
|
|
|
|
return val;
|
|
}
|
|
|
|
int ipq_phy_write(struct mii_dev *bus,
|
|
int addr, int dev_addr,
|
|
int regnum, ushort value)
|
|
{
|
|
return ipq_mdio_write(addr, regnum, value);
|
|
}
|
|
|
|
int ipq_phy_read(struct mii_dev *bus,
|
|
int addr, int dev_addr, int regnum)
|
|
{
|
|
return ipq_mdio_read(addr, regnum, NULL);
|
|
}
|
|
|
|
int ipq_sw_mdio_init(const char *name)
|
|
{
|
|
struct mii_dev *bus = mdio_alloc();
|
|
if(!bus) {
|
|
printf("Failed to allocate IPQ MDIO bus\n");
|
|
return -1;
|
|
}
|
|
bus->read = ipq_phy_read;
|
|
bus->write = ipq_phy_write;
|
|
bus->reset = NULL;
|
|
sprintf(bus->name, name);
|
|
return mdio_register(bus);
|
|
}
|