u-boot/drivers/net/phy/mv88e6352.c
Tom Rini 83d290c56f SPDX: Convert all of our single license tags to Linux Kernel style
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>
2018-05-07 09:34:12 -04:00

301 lines
6.1 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2012
* Valentin Lontgchamp, Keymile AG, valentin.longchamp@keymile.com
*/
#include <common.h>
#include <miiphy.h>
#include <linux/errno.h>
#include <mv88e6352.h>
#define SMI_HDR ((0x8 | 0x1) << 12)
#define SMI_BUSY_MASK (0x8000)
#define SMIRD_OP (0x2 << 10)
#define SMIWR_OP (0x1 << 10)
#define SMI_MASK 0x1f
#define PORT_SHIFT 5
#define COMMAND_REG 0
#define DATA_REG 1
/* global registers */
#define GLOBAL 0x1b
#define GLOBAL_STATUS 0x00
#define PPU_STATE 0x8000
#define GLOBAL_CTRL 0x04
#define SW_RESET 0x8000
#define PPU_ENABLE 0x4000
static int sw_wait_rdy(const char *devname, u8 phy_addr)
{
u16 command;
u32 timeout = 100;
int ret;
/* wait till the SMI is not busy */
do {
/* read command register */
ret = miiphy_read(devname, phy_addr, COMMAND_REG, &command);
if (ret < 0) {
printf("%s: Error reading command register\n",
__func__);
return ret;
}
if (timeout-- == 0) {
printf("Err..(%s) SMI busy timeout\n", __func__);
return -EFAULT;
}
} while (command & SMI_BUSY_MASK);
return 0;
}
static int sw_reg_read(const char *devname, u8 phy_addr, u8 port,
u8 reg, u16 *data)
{
int ret;
u16 command;
ret = sw_wait_rdy(devname, phy_addr);
if (ret)
return ret;
command = SMI_HDR | SMIRD_OP | ((port&SMI_MASK) << PORT_SHIFT) |
(reg & SMI_MASK);
debug("%s: write to command: %#x\n", __func__, command);
ret = miiphy_write(devname, phy_addr, COMMAND_REG, command);
if (ret)
return ret;
ret = sw_wait_rdy(devname, phy_addr);
if (ret)
return ret;
ret = miiphy_read(devname, phy_addr, DATA_REG, data);
return ret;
}
static int sw_reg_write(const char *devname, u8 phy_addr, u8 port,
u8 reg, u16 data)
{
int ret;
u16 value;
ret = sw_wait_rdy(devname, phy_addr);
if (ret)
return ret;
debug("%s: write to data: %#x\n", __func__, data);
ret = miiphy_write(devname, phy_addr, DATA_REG, data);
if (ret)
return ret;
value = SMI_HDR | SMIWR_OP | ((port & SMI_MASK) << PORT_SHIFT) |
(reg & SMI_MASK);
debug("%s: write to command: %#x\n", __func__, value);
ret = miiphy_write(devname, phy_addr, COMMAND_REG, value);
if (ret)
return ret;
ret = sw_wait_rdy(devname, phy_addr);
if (ret)
return ret;
return 0;
}
static int ppu_enable(const char *devname, u8 phy_addr)
{
int i, ret = 0;
u16 reg;
ret = sw_reg_read(devname, phy_addr, GLOBAL, GLOBAL_CTRL, &reg);
if (ret) {
printf("%s: Error reading global ctrl reg\n", __func__);
return ret;
}
reg |= PPU_ENABLE;
ret = sw_reg_write(devname, phy_addr, GLOBAL, GLOBAL_CTRL, reg);
if (ret) {
printf("%s: Error writing global ctrl reg\n", __func__);
return ret;
}
for (i = 0; i < 1000; i++) {
sw_reg_read(devname, phy_addr, GLOBAL, GLOBAL_STATUS,
&reg);
if ((reg & 0xc000) == 0xc000)
return 0;
udelay(1000);
}
return -ETIMEDOUT;
}
static int ppu_disable(const char *devname, u8 phy_addr)
{
int i, ret = 0;
u16 reg;
ret = sw_reg_read(devname, phy_addr, GLOBAL, GLOBAL_CTRL, &reg);
if (ret) {
printf("%s: Error reading global ctrl reg\n", __func__);
return ret;
}
reg &= ~PPU_ENABLE;
ret = sw_reg_write(devname, phy_addr, GLOBAL, GLOBAL_CTRL, reg);
if (ret) {
printf("%s: Error writing global ctrl reg\n", __func__);
return ret;
}
for (i = 0; i < 1000; i++) {
sw_reg_read(devname, phy_addr, GLOBAL, GLOBAL_STATUS,
&reg);
if ((reg & 0xc000) != 0xc000)
return 0;
udelay(1000);
}
return -ETIMEDOUT;
}
int mv88e_sw_program(const char *devname, u8 phy_addr,
struct mv88e_sw_reg *regs, int regs_nb)
{
int i, ret = 0;
/* first we need to disable the PPU */
ret = ppu_disable(devname, phy_addr);
if (ret) {
printf("%s: Error disabling PPU\n", __func__);
return ret;
}
for (i = 0; i < regs_nb; i++) {
ret = sw_reg_write(devname, phy_addr, regs[i].port,
regs[i].reg, regs[i].value);
if (ret) {
printf("%s: Error configuring switch\n", __func__);
ppu_enable(devname, phy_addr);
return ret;
}
}
/* re-enable the PPU */
ret = ppu_enable(devname, phy_addr);
if (ret) {
printf("%s: Error enabling PPU\n", __func__);
return ret;
}
return 0;
}
int mv88e_sw_reset(const char *devname, u8 phy_addr)
{
int i, ret = 0;
u16 reg;
ret = sw_reg_read(devname, phy_addr, GLOBAL, GLOBAL_CTRL, &reg);
if (ret) {
printf("%s: Error reading global ctrl reg\n", __func__);
return ret;
}
reg = SW_RESET | PPU_ENABLE | 0x0400;
ret = sw_reg_write(devname, phy_addr, GLOBAL, GLOBAL_CTRL, reg);
if (ret) {
printf("%s: Error writing global ctrl reg\n", __func__);
return ret;
}
for (i = 0; i < 1000; i++) {
sw_reg_read(devname, phy_addr, GLOBAL, GLOBAL_STATUS,
&reg);
if ((reg & 0xc800) != 0xc800)
return 0;
udelay(1000);
}
return -ETIMEDOUT;
}
int do_mvsw_reg_read(const char *name, int argc, char * const argv[])
{
u16 value = 0, phyaddr, reg, port;
int ret;
phyaddr = simple_strtoul(argv[1], NULL, 10);
port = simple_strtoul(argv[2], NULL, 10);
reg = simple_strtoul(argv[3], NULL, 10);
ret = sw_reg_read(name, phyaddr, port, reg, &value);
printf("%#x\n", value);
return ret;
}
int do_mvsw_reg_write(const char *name, int argc, char * const argv[])
{
u16 value = 0, phyaddr, reg, port;
int ret;
phyaddr = simple_strtoul(argv[1], NULL, 10);
port = simple_strtoul(argv[2], NULL, 10);
reg = simple_strtoul(argv[3], NULL, 10);
value = simple_strtoul(argv[4], NULL, 16);
ret = sw_reg_write(name, phyaddr, port, reg, value);
return ret;
}
int do_mvsw_reg(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
int ret;
const char *cmd, *ethname;
if (argc < 2)
return cmd_usage(cmdtp);
cmd = argv[1];
--argc;
++argv;
if (strcmp(cmd, "read") == 0) {
if (argc < 5)
return cmd_usage(cmdtp);
ethname = argv[1];
--argc;
++argv;
ret = do_mvsw_reg_read(ethname, argc, argv);
} else if (strcmp(cmd, "write") == 0) {
if (argc < 6)
return cmd_usage(cmdtp);
ethname = argv[1];
--argc;
++argv;
ret = do_mvsw_reg_write(ethname, argc, argv);
} else
return cmd_usage(cmdtp);
return ret;
}
U_BOOT_CMD(
mvsw_reg, 7, 1, do_mvsw_reg,
"marvell 88e6352 switch register access",
"write ethname phyaddr port reg value\n"
"mvsw_reg read ethname phyaddr port reg\n"
);