|
|
|
|
@@ -23,6 +23,7 @@
|
|
|
|
|
#include <asm/io.h>
|
|
|
|
|
#include <asm/global_data.h>
|
|
|
|
|
#include <asm/gpio.h>
|
|
|
|
|
#include <reset.h>
|
|
|
|
|
|
|
|
|
|
/* Registers */
|
|
|
|
|
#define RAVB_REG_CCC 0x000
|
|
|
|
|
@@ -30,6 +31,7 @@
|
|
|
|
|
#define RAVB_REG_CSR 0x00C
|
|
|
|
|
#define RAVB_REG_APSR 0x08C
|
|
|
|
|
#define RAVB_REG_RCR 0x090
|
|
|
|
|
#define RAVB_REG_RTC 0x0B4
|
|
|
|
|
#define RAVB_REG_TGC 0x300
|
|
|
|
|
#define RAVB_REG_TCCR 0x304
|
|
|
|
|
#define RAVB_REG_RIC0 0x360
|
|
|
|
|
@@ -43,6 +45,7 @@
|
|
|
|
|
#define RAVB_REG_GECMR 0x5b0
|
|
|
|
|
#define RAVB_REG_MAHR 0x5c0
|
|
|
|
|
#define RAVB_REG_MALR 0x5c8
|
|
|
|
|
#define RAVB_REG_CSR0 0x800
|
|
|
|
|
|
|
|
|
|
#define CCC_OPC_CONFIG BIT(0)
|
|
|
|
|
#define CCC_OPC_OPERATION BIT(1)
|
|
|
|
|
@@ -64,14 +67,24 @@
|
|
|
|
|
#define PIR_MDC BIT(0)
|
|
|
|
|
|
|
|
|
|
#define ECMR_TRCCM BIT(26)
|
|
|
|
|
#define ECMR_RCPT BIT(25)
|
|
|
|
|
#define ECMR_RZPF BIT(20)
|
|
|
|
|
#define ECMR_PFR BIT(18)
|
|
|
|
|
#define ECMR_RXF BIT(17)
|
|
|
|
|
#define ECMR_TXF BIT(16)
|
|
|
|
|
#define ECMR_RE BIT(6)
|
|
|
|
|
#define ECMR_TE BIT(5)
|
|
|
|
|
#define ECMR_DM BIT(1)
|
|
|
|
|
#define ECMR_PRM BIT(0)
|
|
|
|
|
#define ECMR_CHG_DM (ECMR_TRCCM | ECMR_RZPF | ECMR_PFR | ECMR_RXF)
|
|
|
|
|
|
|
|
|
|
#define CSR0_RPE BIT(5)
|
|
|
|
|
#define CSR0_TPE BIT(4)
|
|
|
|
|
|
|
|
|
|
#define GECMR_SPEED_10M (0 << 4)
|
|
|
|
|
#define GECMR_SPEED_100M (1 << 4)
|
|
|
|
|
#define GECMR_SPEED_1G (2 << 4)
|
|
|
|
|
|
|
|
|
|
/* DMA Descriptors */
|
|
|
|
|
#define RAVB_NUM_BASE_DESC 16
|
|
|
|
|
#define RAVB_NUM_TX_DESC 8
|
|
|
|
|
@@ -107,6 +120,13 @@
|
|
|
|
|
|
|
|
|
|
#define RAVB_TX_TIMEOUT_MS 1000
|
|
|
|
|
|
|
|
|
|
struct ravb_device_ops {
|
|
|
|
|
void (*mac_init)(struct udevice *dev);
|
|
|
|
|
void (*dmac_init)(struct udevice *dev);
|
|
|
|
|
void (*config)(struct udevice *dev);
|
|
|
|
|
bool has_reset;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct ravb_desc {
|
|
|
|
|
u32 ctrl;
|
|
|
|
|
u32 dptr;
|
|
|
|
|
@@ -130,6 +150,7 @@ struct ravb_priv {
|
|
|
|
|
struct mii_dev *bus;
|
|
|
|
|
void __iomem *iobase;
|
|
|
|
|
struct clk_bulk clks;
|
|
|
|
|
struct reset_ctl rst;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static inline void ravb_flush_dcache(u32 addr, u32 len)
|
|
|
|
|
@@ -181,7 +202,7 @@ static int ravb_recv(struct udevice *dev, int flags, uchar **packetp)
|
|
|
|
|
{
|
|
|
|
|
struct ravb_priv *eth = dev_get_priv(dev);
|
|
|
|
|
struct ravb_rxdesc *desc = ð->rx_desc[eth->rx_desc_idx];
|
|
|
|
|
int len;
|
|
|
|
|
int len = 0;
|
|
|
|
|
u8 *packet;
|
|
|
|
|
|
|
|
|
|
/* Check if the rx descriptor is ready */
|
|
|
|
|
@@ -190,12 +211,11 @@ static int ravb_recv(struct udevice *dev, int flags, uchar **packetp)
|
|
|
|
|
return -EAGAIN;
|
|
|
|
|
|
|
|
|
|
/* Check for errors */
|
|
|
|
|
if (desc->data.ctrl & RAVB_RX_DESC_MSC_RX_ERR_MASK) {
|
|
|
|
|
if (desc->data.ctrl & RAVB_RX_DESC_MSC_RX_ERR_MASK)
|
|
|
|
|
desc->data.ctrl &= ~RAVB_RX_DESC_MSC_MASK;
|
|
|
|
|
return -EAGAIN;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
len = desc->data.ctrl & RAVB_DESC_DS_MASK;
|
|
|
|
|
|
|
|
|
|
len = desc->data.ctrl & RAVB_DESC_DS_MASK;
|
|
|
|
|
packet = (u8 *)(uintptr_t)desc->data.dptr;
|
|
|
|
|
ravb_invalidate_dcache((uintptr_t)packet, len);
|
|
|
|
|
|
|
|
|
|
@@ -349,10 +369,13 @@ static int ravb_write_hwaddr(struct udevice *dev)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* E-MAC init function */
|
|
|
|
|
static int ravb_mac_init(struct ravb_priv *eth)
|
|
|
|
|
static void ravb_mac_init(struct udevice *dev)
|
|
|
|
|
{
|
|
|
|
|
/* Disable MAC Interrupt */
|
|
|
|
|
writel(0, eth->iobase + RAVB_REG_ECSIPR);
|
|
|
|
|
struct ravb_device_ops *device_ops =
|
|
|
|
|
(struct ravb_device_ops *)dev_get_driver_data(dev);
|
|
|
|
|
struct ravb_priv *eth = dev_get_priv(dev);
|
|
|
|
|
|
|
|
|
|
device_ops->mac_init(dev);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Set receive frame length
|
|
|
|
|
@@ -363,19 +386,33 @@ static int ravb_mac_init(struct ravb_priv *eth)
|
|
|
|
|
* largest frames add the CRC length to the maximum Rx descriptor size.
|
|
|
|
|
*/
|
|
|
|
|
writel(RFLR_RFL_MIN + ETH_FCS_LEN, eth->iobase + RAVB_REG_RFLR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
static void ravb_mac_init_rcar(struct udevice *dev)
|
|
|
|
|
{
|
|
|
|
|
struct ravb_priv *eth = dev_get_priv(dev);
|
|
|
|
|
|
|
|
|
|
/* Disable MAC Interrupt */
|
|
|
|
|
writel(0, eth->iobase + RAVB_REG_ECSIPR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ravb_mac_init_rzg2l(struct udevice *dev)
|
|
|
|
|
{
|
|
|
|
|
struct ravb_priv *eth = dev_get_priv(dev);
|
|
|
|
|
|
|
|
|
|
setbits_32(eth->iobase + RAVB_REG_ECMR,
|
|
|
|
|
ECMR_PRM | ECMR_RXF | ECMR_TXF | ECMR_RCPT |
|
|
|
|
|
ECMR_TE | ECMR_RE | ECMR_RZPF |
|
|
|
|
|
(eth->phydev->duplex ? ECMR_DM : 0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* AVB-DMAC init function */
|
|
|
|
|
static int ravb_dmac_init(struct udevice *dev)
|
|
|
|
|
{
|
|
|
|
|
struct ravb_device_ops *device_ops =
|
|
|
|
|
(struct ravb_device_ops *)dev_get_driver_data(dev);
|
|
|
|
|
struct ravb_priv *eth = dev_get_priv(dev);
|
|
|
|
|
struct eth_pdata *pdata = dev_get_plat(dev);
|
|
|
|
|
int ret = 0;
|
|
|
|
|
int mode = 0;
|
|
|
|
|
unsigned int delay;
|
|
|
|
|
bool explicit_delay = false;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
/* Set CONFIG mode */
|
|
|
|
|
ret = ravb_reset(dev);
|
|
|
|
|
@@ -391,6 +428,18 @@ static int ravb_dmac_init(struct udevice *dev)
|
|
|
|
|
/* Set little endian */
|
|
|
|
|
clrbits_le32(eth->iobase + RAVB_REG_CCC, CCC_BOC);
|
|
|
|
|
|
|
|
|
|
device_ops->dmac_init(dev);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ravb_dmac_init_rcar(struct udevice *dev)
|
|
|
|
|
{
|
|
|
|
|
struct ravb_priv *eth = dev_get_priv(dev);
|
|
|
|
|
struct eth_pdata *pdata = dev_get_plat(dev);
|
|
|
|
|
int mode = 0;
|
|
|
|
|
unsigned int delay;
|
|
|
|
|
bool explicit_delay = false;
|
|
|
|
|
|
|
|
|
|
/* AVB rx set */
|
|
|
|
|
writel(0x18000001, eth->iobase + RAVB_REG_RCR);
|
|
|
|
|
|
|
|
|
|
@@ -400,7 +449,7 @@ static int ravb_dmac_init(struct udevice *dev)
|
|
|
|
|
/* Delay CLK: 2ns (not applicable on R-Car E3/D3) */
|
|
|
|
|
if ((renesas_get_cpu_type() == RENESAS_CPU_TYPE_R8A77990) ||
|
|
|
|
|
(renesas_get_cpu_type() == RENESAS_CPU_TYPE_R8A77995))
|
|
|
|
|
return 0;
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (!dev_read_u32(dev, "rx-internal-delay-ps", &delay)) {
|
|
|
|
|
/* Valid values are 0 and 1800, according to DT bindings */
|
|
|
|
|
@@ -429,28 +478,45 @@ static int ravb_dmac_init(struct udevice *dev)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
writel(mode, eth->iobase + RAVB_REG_APSR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
static void ravb_dmac_init_rzg2l(struct udevice *dev)
|
|
|
|
|
{
|
|
|
|
|
struct ravb_priv *eth = dev_get_priv(dev);
|
|
|
|
|
|
|
|
|
|
/* Set Max Frame Length (RTC) */
|
|
|
|
|
writel(0x7ffc0000 | RFLR_RFL_MIN, eth->iobase + RAVB_REG_RTC);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int ravb_config(struct udevice *dev)
|
|
|
|
|
{
|
|
|
|
|
struct ravb_device_ops *device_ops =
|
|
|
|
|
(struct ravb_device_ops *)dev_get_driver_data(dev);
|
|
|
|
|
struct ravb_priv *eth = dev_get_priv(dev);
|
|
|
|
|
struct phy_device *phy = eth->phydev;
|
|
|
|
|
u32 mask = ECMR_CHG_DM | ECMR_RE | ECMR_TE;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
/* Configure AVB-DMAC register */
|
|
|
|
|
ravb_dmac_init(dev);
|
|
|
|
|
|
|
|
|
|
/* Configure E-MAC registers */
|
|
|
|
|
ravb_mac_init(eth);
|
|
|
|
|
ravb_mac_init(dev);
|
|
|
|
|
ravb_write_hwaddr(dev);
|
|
|
|
|
|
|
|
|
|
ret = phy_startup(phy);
|
|
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
device_ops->config(dev);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ravb_config_rcar(struct udevice *dev)
|
|
|
|
|
{
|
|
|
|
|
struct ravb_priv *eth = dev_get_priv(dev);
|
|
|
|
|
struct phy_device *phy = eth->phydev;
|
|
|
|
|
u32 mask = ECMR_CHG_DM | ECMR_RE | ECMR_TE;
|
|
|
|
|
|
|
|
|
|
/* Set the transfer speed */
|
|
|
|
|
if (phy->speed == 100)
|
|
|
|
|
writel(0, eth->iobase + RAVB_REG_GECMR);
|
|
|
|
|
@@ -462,8 +528,22 @@ static int ravb_config(struct udevice *dev)
|
|
|
|
|
mask |= ECMR_DM;
|
|
|
|
|
|
|
|
|
|
writel(mask, eth->iobase + RAVB_REG_ECMR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
static void ravb_config_rzg2l(struct udevice *dev)
|
|
|
|
|
{
|
|
|
|
|
struct ravb_priv *eth = dev_get_priv(dev);
|
|
|
|
|
struct phy_device *phy = eth->phydev;
|
|
|
|
|
|
|
|
|
|
writel(CSR0_TPE | CSR0_RPE, eth->iobase + RAVB_REG_CSR0);
|
|
|
|
|
|
|
|
|
|
/* Set the transfer speed */
|
|
|
|
|
if (phy->speed == 10)
|
|
|
|
|
writel(GECMR_SPEED_10M, eth->iobase + RAVB_REG_GECMR);
|
|
|
|
|
else if (phy->speed == 100)
|
|
|
|
|
writel(GECMR_SPEED_100M, eth->iobase + RAVB_REG_GECMR);
|
|
|
|
|
else if (phy->speed == 1000)
|
|
|
|
|
writel(GECMR_SPEED_1G, eth->iobase + RAVB_REG_GECMR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int ravb_start(struct udevice *dev)
|
|
|
|
|
@@ -581,6 +661,8 @@ static int ravb_bb_miiphy_write(struct mii_dev *miidev, int addr,
|
|
|
|
|
|
|
|
|
|
static int ravb_probe(struct udevice *dev)
|
|
|
|
|
{
|
|
|
|
|
struct ravb_device_ops *device_ops =
|
|
|
|
|
(struct ravb_device_ops *)dev_get_driver_data(dev);
|
|
|
|
|
struct eth_pdata *pdata = dev_get_plat(dev);
|
|
|
|
|
struct ravb_priv *eth = dev_get_priv(dev);
|
|
|
|
|
struct mii_dev *mdiodev;
|
|
|
|
|
@@ -616,16 +698,32 @@ static int ravb_probe(struct udevice *dev)
|
|
|
|
|
if (ret)
|
|
|
|
|
goto err_clk_enable;
|
|
|
|
|
|
|
|
|
|
if (device_ops->has_reset) {
|
|
|
|
|
ret = reset_get_by_index(dev, 0, ð->rst);
|
|
|
|
|
if (ret < 0)
|
|
|
|
|
goto err_clk_enable;
|
|
|
|
|
|
|
|
|
|
ret = reset_deassert(ð->rst);
|
|
|
|
|
if (ret < 0)
|
|
|
|
|
goto err_reset_deassert;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = ravb_reset(dev);
|
|
|
|
|
if (ret)
|
|
|
|
|
goto err_clk_enable;
|
|
|
|
|
goto err_ravb_reset;
|
|
|
|
|
|
|
|
|
|
ret = ravb_phy_config(dev);
|
|
|
|
|
if (ret)
|
|
|
|
|
goto err_clk_enable;
|
|
|
|
|
goto err_ravb_reset;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
err_ravb_reset:
|
|
|
|
|
if (device_ops->has_reset)
|
|
|
|
|
reset_assert(ð->rst);
|
|
|
|
|
err_reset_deassert:
|
|
|
|
|
if (device_ops->has_reset)
|
|
|
|
|
reset_free(ð->rst);
|
|
|
|
|
err_clk_enable:
|
|
|
|
|
mdio_unregister(mdiodev);
|
|
|
|
|
err_mdio_register:
|
|
|
|
|
@@ -639,8 +737,14 @@ err_clk_get:
|
|
|
|
|
|
|
|
|
|
static int ravb_remove(struct udevice *dev)
|
|
|
|
|
{
|
|
|
|
|
struct ravb_device_ops *device_ops =
|
|
|
|
|
(struct ravb_device_ops *)dev_get_driver_data(dev);
|
|
|
|
|
struct ravb_priv *eth = dev_get_priv(dev);
|
|
|
|
|
|
|
|
|
|
if (device_ops->has_reset) {
|
|
|
|
|
reset_assert(ð->rst);
|
|
|
|
|
reset_free(ð->rst);
|
|
|
|
|
}
|
|
|
|
|
clk_release_bulk(ð->clks);
|
|
|
|
|
|
|
|
|
|
free(eth->phydev);
|
|
|
|
|
@@ -675,9 +779,32 @@ int ravb_of_to_plat(struct udevice *dev)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const struct ravb_device_ops ravb_device_ops_rcar = {
|
|
|
|
|
.mac_init = ravb_mac_init_rcar,
|
|
|
|
|
.dmac_init = ravb_dmac_init_rcar,
|
|
|
|
|
.config = ravb_config_rcar,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const struct ravb_device_ops ravb_device_ops_rzg2l = {
|
|
|
|
|
.mac_init = ravb_mac_init_rzg2l,
|
|
|
|
|
.dmac_init = ravb_dmac_init_rzg2l,
|
|
|
|
|
.config = ravb_config_rzg2l,
|
|
|
|
|
.has_reset = true,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const struct udevice_id ravb_ids[] = {
|
|
|
|
|
{ .compatible = "renesas,etheravb-rcar-gen3" },
|
|
|
|
|
{ .compatible = "renesas,etheravb-rcar-gen4" },
|
|
|
|
|
{
|
|
|
|
|
.compatible = "renesas,etheravb-rcar-gen3",
|
|
|
|
|
.data = (ulong)&ravb_device_ops_rcar,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.compatible = "renesas,etheravb-rcar-gen4",
|
|
|
|
|
.data = (ulong)&ravb_device_ops_rcar,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.compatible = "renesas,rzg2l-gbeth",
|
|
|
|
|
.data = (ulong)&ravb_device_ops_rzg2l,
|
|
|
|
|
},
|
|
|
|
|
{ }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|