mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-16 17:58:23 +00:00
83d290c56f
When U-Boot started using SPDX tags we were among the early adopters and there weren't a lot of other examples to borrow from. So we picked the area of the file that usually had a full license text and replaced it with an appropriate SPDX-License-Identifier: entry. Since then, the Linux Kernel has adopted SPDX tags and they place it as the very first line in a file (except where shebangs are used, then it's second line) and with slightly different comment styles than us. In part due to community overlap, in part due to better tag visibility and in part for other minor reasons, switch over to that style. This commit changes all instances where we have a single declared license in the tag as both the before and after are identical in tag contents. There's also a few places where I found we did not have a tag and have introduced one. Signed-off-by: Tom Rini <trini@konsulko.com>
279 lines
6.1 KiB
C
279 lines
6.1 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* (C) Copyright 2014
|
|
* Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
|
|
*/
|
|
|
|
#include <common.h>
|
|
|
|
#include <miiphy.h>
|
|
|
|
enum {
|
|
MIICMD_SET,
|
|
MIICMD_MODIFY,
|
|
MIICMD_VERIFY_VALUE,
|
|
MIICMD_WAIT_FOR_VALUE,
|
|
};
|
|
|
|
struct mii_setupcmd {
|
|
u8 token;
|
|
u8 reg;
|
|
u16 data;
|
|
u16 mask;
|
|
u32 timeout;
|
|
};
|
|
|
|
/*
|
|
* verify we are talking to a 88e1518
|
|
*/
|
|
struct mii_setupcmd verify_88e1518[] = {
|
|
{ MIICMD_SET, 22, 0x0000 },
|
|
{ MIICMD_VERIFY_VALUE, 2, 0x0141, 0xffff },
|
|
{ MIICMD_VERIFY_VALUE, 3, 0x0dd0, 0xfff0 },
|
|
};
|
|
|
|
/*
|
|
* workaround for erratum mentioned in 88E1518 release notes
|
|
*/
|
|
struct mii_setupcmd fixup_88e1518[] = {
|
|
{ MIICMD_SET, 22, 0x00ff },
|
|
{ MIICMD_SET, 17, 0x214b },
|
|
{ MIICMD_SET, 16, 0x2144 },
|
|
{ MIICMD_SET, 17, 0x0c28 },
|
|
{ MIICMD_SET, 16, 0x2146 },
|
|
{ MIICMD_SET, 17, 0xb233 },
|
|
{ MIICMD_SET, 16, 0x214d },
|
|
{ MIICMD_SET, 17, 0xcc0c },
|
|
{ MIICMD_SET, 16, 0x2159 },
|
|
{ MIICMD_SET, 22, 0x00fb },
|
|
{ MIICMD_SET, 7, 0xc00d },
|
|
{ MIICMD_SET, 22, 0x0000 },
|
|
};
|
|
|
|
/*
|
|
* default initialization:
|
|
* - set RGMII receive timing to "receive clock transition when data stable"
|
|
* - set RGMII transmit timing to "transmit clock internally delayed"
|
|
* - set RGMII output impedance target to 78,8 Ohm
|
|
* - run output impedance calibration
|
|
* - set autonegotiation advertise to 1000FD only
|
|
*/
|
|
struct mii_setupcmd default_88e1518[] = {
|
|
{ MIICMD_SET, 22, 0x0002 },
|
|
{ MIICMD_MODIFY, 21, 0x0030, 0x0030 },
|
|
{ MIICMD_MODIFY, 25, 0x0000, 0x0003 },
|
|
{ MIICMD_MODIFY, 24, 0x8000, 0x8000 },
|
|
{ MIICMD_WAIT_FOR_VALUE, 24, 0x4000, 0x4000, 2000 },
|
|
{ MIICMD_SET, 22, 0x0000 },
|
|
{ MIICMD_MODIFY, 4, 0x0000, 0x01e0 },
|
|
{ MIICMD_MODIFY, 9, 0x0200, 0x0300 },
|
|
};
|
|
|
|
/*
|
|
* turn off CLK125 for PHY daughterboard
|
|
*/
|
|
struct mii_setupcmd ch1fix_88e1518[] = {
|
|
{ MIICMD_SET, 22, 0x0002 },
|
|
{ MIICMD_MODIFY, 16, 0x0006, 0x0006 },
|
|
{ MIICMD_SET, 22, 0x0000 },
|
|
};
|
|
|
|
/*
|
|
* perform copper software reset
|
|
*/
|
|
struct mii_setupcmd swreset_88e1518[] = {
|
|
{ MIICMD_SET, 22, 0x0000 },
|
|
{ MIICMD_MODIFY, 0, 0x8000, 0x8000 },
|
|
{ MIICMD_WAIT_FOR_VALUE, 0, 0x0000, 0x8000, 2000 },
|
|
};
|
|
|
|
/*
|
|
* special one for 88E1514:
|
|
* Force SGMII to Copper mode
|
|
*/
|
|
struct mii_setupcmd mii_to_copper_88e1514[] = {
|
|
{ MIICMD_SET, 22, 0x0012 },
|
|
{ MIICMD_MODIFY, 20, 0x0001, 0x0007 },
|
|
{ MIICMD_MODIFY, 20, 0x8000, 0x8000 },
|
|
{ MIICMD_SET, 22, 0x0000 },
|
|
};
|
|
|
|
/*
|
|
* turn off SGMII auto-negotiation
|
|
*/
|
|
struct mii_setupcmd sgmii_autoneg_off_88e1518[] = {
|
|
{ MIICMD_SET, 22, 0x0001 },
|
|
{ MIICMD_MODIFY, 0, 0x0000, 0x1000 },
|
|
{ MIICMD_MODIFY, 0, 0x8000, 0x8000 },
|
|
{ MIICMD_SET, 22, 0x0000 },
|
|
};
|
|
|
|
/*
|
|
* invert LED2 polarity
|
|
*/
|
|
struct mii_setupcmd invert_led2_88e1514[] = {
|
|
{ MIICMD_SET, 22, 0x0003 },
|
|
{ MIICMD_MODIFY, 17, 0x0030, 0x0010 },
|
|
{ MIICMD_SET, 22, 0x0000 },
|
|
};
|
|
|
|
static int process_setupcmd(const char *bus, unsigned char addr,
|
|
struct mii_setupcmd *setupcmd)
|
|
{
|
|
int res;
|
|
u8 reg = setupcmd->reg;
|
|
u16 data = setupcmd->data;
|
|
u16 mask = setupcmd->mask;
|
|
u32 timeout = setupcmd->timeout;
|
|
u16 orig_data;
|
|
unsigned long start;
|
|
|
|
debug("mii %s:%u reg %2u ", bus, addr, reg);
|
|
|
|
switch (setupcmd->token) {
|
|
case MIICMD_MODIFY:
|
|
res = miiphy_read(bus, addr, reg, &orig_data);
|
|
if (res)
|
|
break;
|
|
debug("is %04x. (value %04x mask %04x) ", orig_data, data,
|
|
mask);
|
|
data = (orig_data & ~mask) | (data & mask);
|
|
/* fallthrough */
|
|
case MIICMD_SET:
|
|
debug("=> %04x\n", data);
|
|
res = miiphy_write(bus, addr, reg, data);
|
|
break;
|
|
case MIICMD_VERIFY_VALUE:
|
|
res = miiphy_read(bus, addr, reg, &orig_data);
|
|
if (res)
|
|
break;
|
|
if ((orig_data & mask) != (data & mask))
|
|
res = -1;
|
|
debug("(value %04x mask %04x) == %04x? %s\n", data, mask,
|
|
orig_data, res ? "FAIL" : "PASS");
|
|
break;
|
|
case MIICMD_WAIT_FOR_VALUE:
|
|
res = -1;
|
|
start = get_timer(0);
|
|
while ((res != 0) && (get_timer(start) < timeout)) {
|
|
res = miiphy_read(bus, addr, reg, &orig_data);
|
|
if (res)
|
|
continue;
|
|
if ((orig_data & mask) != (data & mask))
|
|
res = -1;
|
|
}
|
|
debug("(value %04x mask %04x) == %04x? %s after %lu ms\n", data,
|
|
mask, orig_data, res ? "FAIL" : "PASS",
|
|
get_timer(start));
|
|
break;
|
|
default:
|
|
res = -1;
|
|
break;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int process_setup(const char *bus, unsigned char addr,
|
|
struct mii_setupcmd *setupcmd, unsigned int count)
|
|
{
|
|
int res = 0;
|
|
unsigned int k;
|
|
|
|
for (k = 0; k < count; ++k) {
|
|
res = process_setupcmd(bus, addr, &setupcmd[k]);
|
|
if (res) {
|
|
printf("mii cmd %u on bus %s addr %u failed, aborting setup\n",
|
|
setupcmd[k].token, bus, addr);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
int setup_88e1518(const char *bus, unsigned char addr)
|
|
{
|
|
int res;
|
|
|
|
res = process_setup(bus, addr,
|
|
verify_88e1518, ARRAY_SIZE(verify_88e1518));
|
|
if (res)
|
|
return res;
|
|
|
|
res = process_setup(bus, addr,
|
|
fixup_88e1518, ARRAY_SIZE(fixup_88e1518));
|
|
if (res)
|
|
return res;
|
|
|
|
res = process_setup(bus, addr,
|
|
default_88e1518, ARRAY_SIZE(default_88e1518));
|
|
if (res)
|
|
return res;
|
|
|
|
if (addr) {
|
|
res = process_setup(bus, addr,
|
|
ch1fix_88e1518, ARRAY_SIZE(ch1fix_88e1518));
|
|
if (res)
|
|
return res;
|
|
}
|
|
|
|
res = process_setup(bus, addr,
|
|
swreset_88e1518, ARRAY_SIZE(swreset_88e1518));
|
|
if (res)
|
|
return res;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int setup_88e1514(const char *bus, unsigned char addr)
|
|
{
|
|
int res;
|
|
|
|
res = process_setup(bus, addr,
|
|
verify_88e1518, ARRAY_SIZE(verify_88e1518));
|
|
if (res)
|
|
return res;
|
|
|
|
res = process_setup(bus, addr,
|
|
fixup_88e1518, ARRAY_SIZE(fixup_88e1518));
|
|
if (res)
|
|
return res;
|
|
|
|
res = process_setup(bus, addr,
|
|
mii_to_copper_88e1514,
|
|
ARRAY_SIZE(mii_to_copper_88e1514));
|
|
if (res)
|
|
return res;
|
|
|
|
res = process_setup(bus, addr,
|
|
sgmii_autoneg_off_88e1518,
|
|
ARRAY_SIZE(sgmii_autoneg_off_88e1518));
|
|
if (res)
|
|
return res;
|
|
|
|
res = process_setup(bus, addr,
|
|
invert_led2_88e1514,
|
|
ARRAY_SIZE(invert_led2_88e1514));
|
|
if (res)
|
|
return res;
|
|
|
|
res = process_setup(bus, addr,
|
|
default_88e1518, ARRAY_SIZE(default_88e1518));
|
|
if (res)
|
|
return res;
|
|
|
|
if (addr) {
|
|
res = process_setup(bus, addr,
|
|
ch1fix_88e1518, ARRAY_SIZE(ch1fix_88e1518));
|
|
if (res)
|
|
return res;
|
|
}
|
|
|
|
res = process_setup(bus, addr,
|
|
swreset_88e1518, ARRAY_SIZE(swreset_88e1518));
|
|
if (res)
|
|
return res;
|
|
|
|
return 0;
|
|
}
|