提交 9c94e0a6 编写于 作者: T Tom Rini

Merge branch 'master' of git://git.denx.de/u-boot-net

......@@ -123,6 +123,8 @@ config SANDBOX
imply DM_SOUND
imply PCI_SANDBOX_EP
imply PCH
imply PHYLIB
imply DM_MDIO
config SH
bool "SuperH architecture"
......
......@@ -64,6 +64,7 @@
/* MCUSS Range */
<0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>,
<0x00 0x40200000 0x00 0x40200000 0x00 0x00900100>,
<0x00 0x40f00000 0x00 0x40f00000 0x00 0x00020000>,
<0x00 0x42040000 0x00 0x42040000 0x00 0x03ac2400>,
<0x00 0x45100000 0x00 0x45100000 0x00 0x00c24000>,
<0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>,
......@@ -75,6 +76,7 @@
#size-cells = <2>;
ranges = <0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>, /* MCU NAVSS*/
<0x00 0x40200000 0x00 0x40200000 0x00 0x00900100>, /* First peripheral window */
<0x00 0x40f00000 0x00 0x40f00000 0x00 0x00020000>, /* CTRL_MMR0 */
<0x00 0x42040000 0x00 0x42040000 0x00 0x03ac2400>, /* WKUP */
<0x00 0x45100000 0x00 0x45100000 0x00 0x00c24000>, /* MMRs, remaining NAVSS */
<0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>, /* CPSW */
......
......@@ -5,6 +5,7 @@
#include <dt-bindings/pinctrl/k3.h>
#include <dt-bindings/dma/k3-udma.h>
#include <dt-bindings/net/ti-dp83867.h>
/ {
chosen {
......@@ -13,6 +14,7 @@
aliases {
serial2 = &main_uart0;
ethernet0 = &cpsw_port1;
};
};
......@@ -110,6 +112,116 @@
dma-coherent;
};
};
mcu_conf: scm_conf@40f00000 {
compatible = "syscon";
reg = <0x0 0x40f00000 0x0 0x20000>;
};
mcu_cpsw: cpsw_nuss@046000000 {
compatible = "ti,am654-cpsw-nuss";
#address-cells = <2>;
#size-cells = <2>;
reg = <0x0 0x46000000 0x0 0x200000>;
reg-names = "cpsw_nuss";
ranges;
dma-coherent;
clocks = <&k3_clks 5 10>;
clock-names = "fck";
power-domains = <&k3_pds 5>;
ti,psil-base = <0x7000>;
dmas = <&mcu_udmap &mcu_cpsw 0 UDMA_DIR_TX>,
<&mcu_udmap &mcu_cpsw 1 UDMA_DIR_TX>,
<&mcu_udmap &mcu_cpsw 2 UDMA_DIR_TX>,
<&mcu_udmap &mcu_cpsw 3 UDMA_DIR_TX>,
<&mcu_udmap &mcu_cpsw 4 UDMA_DIR_TX>,
<&mcu_udmap &mcu_cpsw 5 UDMA_DIR_TX>,
<&mcu_udmap &mcu_cpsw 6 UDMA_DIR_TX>,
<&mcu_udmap &mcu_cpsw 7 UDMA_DIR_TX>,
<&mcu_udmap &mcu_cpsw 0 UDMA_DIR_RX>;
dma-names = "tx0", "tx1", "tx2", "tx3",
"tx4", "tx5", "tx6", "tx7",
"rx";
ports {
#address-cells = <1>;
#size-cells = <0>;
host: host@0 {
reg = <0>;
ti,label = "host";
};
cpsw_port1: port@1 {
reg = <1>;
ti,mac-only;
ti,label = "port1";
ti,syscon-efuse = <&mcu_conf 0x200>;
};
};
davinci_mdio: mdio {
#address-cells = <1>;
#size-cells = <0>;
bus_freq = <1000000>;
};
ti,psil-config0 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
ti,psil-config1 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
ti,psil-config2 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
ti,psil-config3 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
ti,psil-config4 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
ti,psil-config5 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
ti,psil-config6 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
ti,psil-config7 {
linux,udma-mode = <UDMA_PKT_MODE>;
statictr-type = <PSIL_STATIC_TR_NONE>;
ti,needs-epib;
ti,psd-size = <16>;
};
};
};
&cbass_wakeup {
......@@ -189,6 +301,32 @@
u-boot,dm-spl;
};
&wkup_pmx0 {
mcu_cpsw_pins_default: mcu_cpsw_pins_default {
pinctrl-single,pins = <
AM65X_WKUP_IOPAD(0x0058, PIN_OUTPUT, 0) /* (N4) MCU_RGMII1_TX_CTL */
AM65X_WKUP_IOPAD(0x005c, PIN_INPUT, 0) /* (N5) MCU_RGMII1_RX_CTL */
AM65X_WKUP_IOPAD(0x0060, PIN_OUTPUT, 0) /* (M2) MCU_RGMII1_TD3 */
AM65X_WKUP_IOPAD(0x0064, PIN_OUTPUT, 0) /* (M3) MCU_RGMII1_TD2 */
AM65X_WKUP_IOPAD(0x0068, PIN_OUTPUT, 0) /* (M4) MCU_RGMII1_TD1 */
AM65X_WKUP_IOPAD(0x006c, PIN_OUTPUT, 0) /* (M5) MCU_RGMII1_TD0 */
AM65X_WKUP_IOPAD(0x0078, PIN_INPUT, 0) /* (L2) MCU_RGMII1_RD3 */
AM65X_WKUP_IOPAD(0x007c, PIN_INPUT, 0) /* (L5) MCU_RGMII1_RD2 */
AM65X_WKUP_IOPAD(0x0080, PIN_INPUT, 0) /* (M6) MCU_RGMII1_RD1 */
AM65X_WKUP_IOPAD(0x0084, PIN_INPUT, 0) /* (L6) MCU_RGMII1_RD0 */
AM65X_WKUP_IOPAD(0x0070, PIN_INPUT, 0) /* (N1) MCU_RGMII1_TXC */
AM65X_WKUP_IOPAD(0x0074, PIN_INPUT, 0) /* (M1) MCU_RGMII1_RXC */
>;
};
mcu_mdio_pins_default: mcu_mdio1_pins_default {
pinctrl-single,pins = <
AM65X_WKUP_IOPAD(0x008c, PIN_OUTPUT, 0) /* (L1) MCU_MDIO0_MDC */
AM65X_WKUP_IOPAD(0x0088, PIN_INPUT, 0) /* (L4) MCU_MDIO0_MDIO */
>;
};
};
&main_uart0 {
u-boot,dm-spl;
pinctrl-names = "default";
......@@ -212,3 +350,35 @@
pinctrl-0 = <&main_mmc1_pins_default>;
sdhci-caps-mask = <0x7 0x0>;
};
&mcu_cpsw {
pinctrl-names = "default";
pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>;
};
&davinci_mdio {
phy0: ethernet-phy@0 {
reg = <0>;
/* TODO: phy reset: TCA9555RTWR(i2c:0x21)[p04].GPIO_MCU_RGMII_RSTN */
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
};
};
&cpsw_port1 {
phy-mode = "rgmii-id";
phy-handle = <&phy0>;
};
&mcu_cpsw {
reg = <0x0 0x46000000 0x0 0x200000>,
<0x0 0x40f00200 0x0 0x2>;
reg-names = "cpsw_nuss", "mac_efuse";
cpsw-phy-sel@40f04040 {
compatible = "ti,am654-cpsw-phy-sel";
reg= <0x0 0x40f04040 0x0 0x4>;
reg-names = "gmii-sel";
};
};
......@@ -823,6 +823,10 @@
dmas = <&dma 0>, <&dma 1>, <&dma 2>;
dma-names = "m2m", "tx0", "rx0";
};
mdio-test {
compatible = "sandbox,mdio";
};
};
#include "sandbox_pmic.dtsi"
......@@ -203,6 +203,11 @@ static int do_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (argc < 2)
return CMD_RET_USAGE;
#ifdef CONFIG_DM_MDIO
/* probe DM MII device before any operation so they are all accesible */
dm_mdio_probe_devices();
#endif
/*
* We use the last specified parameters, unless new ones are
* entered.
......
......@@ -12,25 +12,11 @@
#include <command.h>
#include <miiphy.h>
typedef struct _MII_reg_desc_t {
ushort regno;
char * name;
} MII_reg_desc_t;
static const MII_reg_desc_t reg_0_5_desc_tbl[] = {
{ MII_BMCR, "PHY control register" },
{ MII_BMSR, "PHY status register" },
{ MII_PHYSID1, "PHY ID 1 register" },
{ MII_PHYSID2, "PHY ID 2 register" },
{ MII_ADVERTISE, "Autonegotiation advertisement register" },
{ MII_LPA, "Autonegotiation partner abilities register" },
};
typedef struct _MII_field_desc_t {
ushort hi;
ushort lo;
ushort mask;
char * name;
const char *name;
} MII_field_desc_t;
static const MII_field_desc_t reg_0_desc_tbl[] = {
......@@ -87,7 +73,7 @@ static const MII_field_desc_t reg_4_desc_tbl[] = {
{ 7, 7, 0x01, "100BASE-TX able" },
{ 6, 6, 0x01, "10BASE-T full duplex able" },
{ 5, 5, 0x01, "10BASE-T able" },
{ 4, 0, 0x1f, "xxx to do" },
{ 4, 0, 0x1f, "selector" },
};
static const MII_field_desc_t reg_5_desc_tbl[] = {
......@@ -102,50 +88,91 @@ static const MII_field_desc_t reg_5_desc_tbl[] = {
{ 7, 7, 0x01, "100BASE-TX able" },
{ 6, 6, 0x01, "10BASE-T full duplex able" },
{ 5, 5, 0x01, "10BASE-T able" },
{ 4, 0, 0x1f, "xxx to do" },
{ 4, 0, 0x1f, "partner selector" },
};
typedef struct _MII_field_desc_and_len_t {
static const MII_field_desc_t reg_9_desc_tbl[] = {
{ 15, 13, 0x07, "test mode" },
{ 12, 12, 0x01, "manual master/slave enable" },
{ 11, 11, 0x01, "manual master/slave value" },
{ 10, 10, 0x01, "multi/single port" },
{ 9, 9, 0x01, "1000BASE-T full duplex able" },
{ 8, 8, 0x01, "1000BASE-T half duplex able" },
{ 7, 7, 0x01, "automatic TDR on link down" },
{ 6, 6, 0x7f, "(reserved)" },
};
static const MII_field_desc_t reg_10_desc_tbl[] = {
{ 15, 15, 0x01, "master/slave config fault" },
{ 14, 14, 0x01, "master/slave config result" },
{ 13, 13, 0x01, "local receiver status OK" },
{ 12, 12, 0x01, "remote receiver status OK" },
{ 11, 11, 0x01, "1000BASE-T full duplex able" },
{ 10, 10, 0x01, "1000BASE-T half duplex able" },
{ 9, 8, 0x03, "(reserved)" },
{ 7, 0, 0xff, "1000BASE-T idle error counter"},
};
typedef struct _MII_reg_desc_t {
ushort regno;
const MII_field_desc_t *pdesc;
ushort len;
} MII_field_desc_and_len_t;
static const MII_field_desc_and_len_t desc_and_len_tbl[] = {
{ reg_0_desc_tbl, ARRAY_SIZE(reg_0_desc_tbl) },
{ reg_1_desc_tbl, ARRAY_SIZE(reg_1_desc_tbl) },
{ reg_2_desc_tbl, ARRAY_SIZE(reg_2_desc_tbl) },
{ reg_3_desc_tbl, ARRAY_SIZE(reg_3_desc_tbl) },
{ reg_4_desc_tbl, ARRAY_SIZE(reg_4_desc_tbl) },
{ reg_5_desc_tbl, ARRAY_SIZE(reg_5_desc_tbl) },
const char *name;
} MII_reg_desc_t;
static const MII_reg_desc_t mii_reg_desc_tbl[] = {
{ MII_BMCR, reg_0_desc_tbl, ARRAY_SIZE(reg_0_desc_tbl),
"PHY control register" },
{ MII_BMSR, reg_1_desc_tbl, ARRAY_SIZE(reg_1_desc_tbl),
"PHY status register" },
{ MII_PHYSID1, reg_2_desc_tbl, ARRAY_SIZE(reg_2_desc_tbl),
"PHY ID 1 register" },
{ MII_PHYSID2, reg_3_desc_tbl, ARRAY_SIZE(reg_3_desc_tbl),
"PHY ID 2 register" },
{ MII_ADVERTISE, reg_4_desc_tbl, ARRAY_SIZE(reg_4_desc_tbl),
"Autonegotiation advertisement register" },
{ MII_LPA, reg_5_desc_tbl, ARRAY_SIZE(reg_5_desc_tbl),
"Autonegotiation partner abilities register" },
{ MII_CTRL1000, reg_9_desc_tbl, ARRAY_SIZE(reg_9_desc_tbl),
"1000BASE-T control register" },
{ MII_STAT1000, reg_10_desc_tbl, ARRAY_SIZE(reg_10_desc_tbl),
"1000BASE-T status register" },
};
static void dump_reg(
ushort regval,
const MII_reg_desc_t *prd,
const MII_field_desc_and_len_t *pdl);
static int special_field(
ushort regno,
const MII_field_desc_t *pdesc,
ushort regval);
static void MII_dump_0_to_5(
ushort regvals[6],
uchar reglo,
uchar reghi)
const MII_reg_desc_t *prd);
static bool special_field(ushort regno, const MII_field_desc_t *pdesc,
ushort regval);
static void MII_dump(const ushort *regvals, uchar reglo, uchar reghi)
{
ulong i;
for (i = 0; i < 6; i++) {
if ((reglo <= i) && (i <= reghi))
dump_reg(regvals[i], &reg_0_5_desc_tbl[i],
&desc_and_len_tbl[i]);
for (i = 0; i < ARRAY_SIZE(mii_reg_desc_tbl); i++) {
const uchar reg = mii_reg_desc_tbl[i].regno;
if (reg >= reglo && reg <= reghi)
dump_reg(regvals[reg - reglo], &mii_reg_desc_tbl[i]);
}
}
/* Print out field position, value, name */
static void dump_field(const MII_field_desc_t *pdesc, ushort regval)
{
if (pdesc->hi == pdesc->lo)
printf("%2u ", pdesc->lo);
else
printf("%2u-%2u", pdesc->hi, pdesc->lo);
printf(" = %5u %s", (regval >> pdesc->lo) & pdesc->mask,
pdesc->name);
}
static void dump_reg(
ushort regval,
const MII_reg_desc_t *prd,
const MII_field_desc_and_len_t *pdl)
const MII_reg_desc_t *prd)
{
ulong i;
ushort mask_in_place;
......@@ -154,8 +181,8 @@ static void dump_reg(
printf("%u. (%04hx) -- %s --\n",
prd->regno, regval, prd->name);
for (i = 0; i < pdl->len; i++) {
pdesc = &pdl->pdesc[i];
for (i = 0; i < prd->len; i++) {
pdesc = &prd->pdesc[i];
mask_in_place = pdesc->mask << pdesc->lo;
......@@ -164,17 +191,8 @@ static void dump_reg(
regval & mask_in_place,
prd->regno);
if (special_field(prd->regno, pdesc, regval)) {
}
else {
if (pdesc->hi == pdesc->lo)
printf("%2u ", pdesc->lo);
else
printf("%2u-%2u", pdesc->hi, pdesc->lo);
printf(" = %5u %s",
(regval & mask_in_place) >> pdesc->lo,
pdesc->name);
}
if (!special_field(prd->regno, pdesc, regval))
dump_field(pdesc, regval);
printf("\n");
}
......@@ -190,11 +208,11 @@ static void dump_reg(
** 5.4-0
*/
static int special_field(
ushort regno,
const MII_field_desc_t *pdesc,
ushort regval)
static bool special_field(ushort regno, const MII_field_desc_t *pdesc,
ushort regval)
{
const ushort sel_bits = (regval >> pdesc->lo) & pdesc->mask;
if ((regno == MII_BMCR) && (pdesc->lo == 6)) {
ushort speed_bits = regval & (BMCR_SPEED1000 | BMCR_SPEED100);
printf("%2u,%2u = b%u%u speed selection = %s Mbps",
......@@ -208,34 +226,26 @@ static int special_field(
}
else if ((regno == MII_BMCR) && (pdesc->lo == 8)) {
printf("%2u = %5u duplex = %s",
pdesc->lo,
(regval >> pdesc->lo) & 1,
((regval >> pdesc->lo) & 1) ? "full" : "half");
dump_field(pdesc, regval);
printf(" = %s", ((regval >> pdesc->lo) & 1) ? "full" : "half");
return 1;
}
else if ((regno == MII_ADVERTISE) && (pdesc->lo == 0)) {
ushort sel_bits = (regval >> pdesc->lo) & pdesc->mask;
printf("%2u-%2u = %5u selector = %s",
pdesc->hi, pdesc->lo, sel_bits,
sel_bits == PHY_ANLPAR_PSB_802_3 ?
"IEEE 802.3" :
sel_bits == PHY_ANLPAR_PSB_802_9 ?
"IEEE 802.9 ISLAN-16T" :
"???");
dump_field(pdesc, regval);
printf(" = %s",
sel_bits == PHY_ANLPAR_PSB_802_3 ? "IEEE 802.3 CSMA/CD" :
sel_bits == PHY_ANLPAR_PSB_802_9 ?
"IEEE 802.9 ISLAN-16T" : "???");
return 1;
}
else if ((regno == MII_LPA) && (pdesc->lo == 0)) {
ushort sel_bits = (regval >> pdesc->lo) & pdesc->mask;
printf("%2u-%2u = %u selector = %s",
pdesc->hi, pdesc->lo, sel_bits,
sel_bits == PHY_ANLPAR_PSB_802_3 ?
"IEEE 802.3" :
sel_bits == PHY_ANLPAR_PSB_802_9 ?
"IEEE 802.9 ISLAN-16T" :
"???");
dump_field(pdesc, regval);
printf(" = %s",
sel_bits == PHY_ANLPAR_PSB_802_3 ? "IEEE 802.3 CSMA/CD" :
sel_bits == PHY_ANLPAR_PSB_802_9 ?
"IEEE 802.9 ISLAN-16T" : "???");
return 1;
}
......@@ -406,17 +416,16 @@ static int do_mii(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
}
} else if (strncmp(op, "du", 2) == 0) {
ushort regs[6];
ushort regs[MII_STAT1000 + 1]; /* Last reg is 0x0a */
int ok = 1;
if ((reglo > 5) || (reghi > 5)) {
printf(
"The MII dump command only formats the "
"standard MII registers, 0-5.\n");
if (reglo > MII_STAT1000 || reghi > MII_STAT1000) {
printf("The MII dump command only formats the standard MII registers, 0-5, 9-a.\n");
return 1;
}
for (addr = addrlo; addr <= addrhi; addr++) {
for (reg = reglo; reg < reghi + 1; reg++) {
if (miiphy_read(devname, addr, reg, &regs[reg]) != 0) {
for (reg = reglo; reg <= reghi; reg++) {
if (miiphy_read(devname, addr, reg,
&regs[reg - reglo]) != 0) {
ok = 0;
printf(
"Error reading from the PHY addr=%02x reg=%02x\n",
......@@ -425,7 +434,7 @@ static int do_mii(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
}
if (ok)
MII_dump_0_to_5(regs, reglo, reghi);
MII_dump(regs, reglo, reghi);
printf("\n");
}
} else if (strncmp(op, "de", 2) == 0) {
......
......@@ -44,6 +44,7 @@ CONFIG_SPL_MULTI_DTB_FIT_NO_COMPRESSION=y
CONFIG_ENV_IS_IN_FAT=y
CONFIG_ENV_FAT_INTERFACE="mmc"
CONFIG_ENV_FAT_DEVICE_AND_PART="1:1"
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_DM=y
CONFIG_SPL_DM=y
CONFIG_SPL_DM_SEQ_ALIAS=y
......@@ -58,6 +59,11 @@ CONFIG_K3_SEC_PROXY=y
CONFIG_DM_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_K3_ARASAN=y
CONFIG_PHY_TI=y
CONFIG_PHY_FIXED=y
CONFIG_DM_ETH=y
CONFIG_TI_AM65_CPSW_NUSS=y
CONFIG_PHY=y
CONFIG_PINCTRL=y
# CONFIG_PINCTRL_GENERIC is not set
CONFIG_SPL_PINCTRL=y
......
......@@ -11,6 +11,29 @@ config DM_ETH
This is currently implemented in net/eth-uclass.c
Look in include/net.h for details.
config DM_MDIO
bool "Enable Driver Model for MDIO devices"
depends on DM_ETH && PHYLIB
help
Enable driver model for MDIO devices
Adds UCLASS_MDIO DM class supporting MDIO buses that are probed as
stand-alone devices. Useful in particular for systems that support
DM_ETH and have a stand-alone MDIO hardware block shared by multiple
Ethernet interfaces.
This is currently implemented in net/mdio-uclass.c
Look in include/miiphy.h for details.
config MDIO_SANDBOX
depends on DM_MDIO && SANDBOX
default y
bool "Sandbox: Mocked MDIO driver"
help
This driver implements dummy read/write/reset MDIO functions mimicking
a bus with a single PHY.
This driver is used in for testing in test/dm/mdio.c
menuconfig NETDEVICES
bool "Network device support"
depends on NET
......
......@@ -77,3 +77,4 @@ obj-y += ti/
obj-$(CONFIG_MEDIATEK_ETH) += mtk_eth.o
obj-y += mscc_eswitch/
obj-$(CONFIG_HIGMACV300_ETH) += higmacv300.o
obj-$(CONFIG_MDIO_SANDBOX) += mdio_sandbox.o
......@@ -613,10 +613,12 @@ static int macb_phy_init(struct macb_device *macb, const char *name)
/* First check for GMAC and that it is GiB capable */
if (gem_is_gigabit_capable(macb)) {
lpa = macb_mdio_read(macb, MII_STAT1000);
lpa = macb_mdio_read(macb, MII_LPA);
if (lpa & (LPA_1000FULL | LPA_1000HALF)) {
duplex = ((lpa & LPA_1000FULL) ? 1 : 0);
if (lpa & (LPA_1000FULL | LPA_1000HALF | LPA_1000XFULL |
LPA_1000XHALF)) {
duplex = ((lpa & (LPA_1000FULL | LPA_1000XFULL)) ?
1 : 0);
printf("%s: link up, 1000Mbps %s-duplex (lpa: 0x%04x)\n",
name,
......
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2019
* Alex Marginean, NXP
*/
#include <dm.h>
#include <errno.h>
#include <miiphy.h>
#define SANDBOX_PHY_ADDR 5
#define SANDBOX_PHY_REG 0
struct mdio_sandbox_priv {
int enabled;
u16 reg;
};
static int mdio_sandbox_read(struct udevice *dev, int addr, int devad, int reg)
{
struct mdio_sandbox_priv *priv = dev_get_priv(dev);
if (!priv->enabled)
return -ENODEV;
if (addr != SANDBOX_PHY_ADDR)
return -ENODEV;
if (devad != MDIO_DEVAD_NONE)
return -ENODEV;
if (reg != SANDBOX_PHY_REG)
return -ENODEV;
return priv->reg;
}
static int mdio_sandbox_write(struct udevice *dev, int addr, int devad, int reg,
u16 val)
{
struct mdio_sandbox_priv *priv = dev_get_priv(dev);
if (!priv->enabled)
return -ENODEV;
if (addr != SANDBOX_PHY_ADDR)
return -ENODEV;
if (devad != MDIO_DEVAD_NONE)
return -ENODEV;
if (reg != SANDBOX_PHY_REG)
return -ENODEV;
priv->reg = val;
return 0;
}
static int mdio_sandbox_reset(struct udevice *dev)
{
struct mdio_sandbox_priv *priv = dev_get_priv(dev);
priv->reg = 0;
return 0;
}
static const struct mdio_ops mdio_sandbox_ops = {
.read = mdio_sandbox_read,
.write = mdio_sandbox_write,
.reset = mdio_sandbox_reset,
};
static int mdio_sandbox_probe(struct udevice *dev)
{
struct mdio_sandbox_priv *priv = dev_get_priv(dev);
priv->enabled = 1;
return 0;
}
static const struct udevice_id mdio_sandbox_ids[] = {
{ .compatible = "sandbox,mdio" },
{ }
};
U_BOOT_DRIVER(mdio_sandbox) = {
.name = "mdio_sandbox",
.id = UCLASS_MDIO,
.of_match = mdio_sandbox_ids,
.probe = mdio_sandbox_probe,
.ops = &mdio_sandbox_ops,
.priv_auto_alloc_size = sizeof(struct mdio_sandbox_priv),
};
obj-$(CONFIG_MSCC_OCELOT_SWITCH) += ocelot_switch.o mscc_xfer.o mscc_mac_table.o
obj-$(CONFIG_MSCC_LUTON_SWITCH) += luton_switch.o mscc_xfer.o mscc_mac_table.o
obj-$(CONFIG_MSCC_JR2_SWITCH) += jr2_switch.o mscc_xfer.o
obj-$(CONFIG_MSCC_SERVALT_SWITCH) += servalt_switch.o mscc_xfer.o
obj-$(CONFIG_MSCC_SERVAL_SWITCH) += serval_switch.o mscc_xfer.o mscc_mac_table.o
obj-$(CONFIG_MSCC_OCELOT_SWITCH) += ocelot_switch.o mscc_xfer.o mscc_mac_table.o mscc_miim.o
obj-$(CONFIG_MSCC_LUTON_SWITCH) += luton_switch.o mscc_xfer.o mscc_mac_table.o mscc_miim.o
obj-$(CONFIG_MSCC_JR2_SWITCH) += jr2_switch.o mscc_xfer.o mscc_miim.o
obj-$(CONFIG_MSCC_SERVALT_SWITCH) += servalt_switch.o mscc_xfer.o mscc_miim.o
obj-$(CONFIG_MSCC_SERVAL_SWITCH) += serval_switch.o mscc_xfer.o mscc_mac_table.o mscc_miim.o
......@@ -17,20 +17,7 @@
#include <dt-bindings/mscc/jr2_data.h>
#include "mscc_xfer.h"
#define GCB_MIIM_MII_STATUS 0x0
#define GCB_MIIM_STAT_BUSY BIT(3)
#define GCB_MIIM_MII_CMD 0x8
#define GCB_MIIM_MII_CMD_SCAN BIT(0)
#define GCB_MIIM_MII_CMD_OPR_WRITE BIT(1)
#define GCB_MIIM_MII_CMD_OPR_READ BIT(2)
#define GCB_MIIM_MII_CMD_SINGLE_SCAN BIT(3)
#define GCB_MIIM_MII_CMD_WRDATA(x) ((x) << 4)
#define GCB_MIIM_MII_CMD_REGAD(x) ((x) << 20)
#define GCB_MIIM_MII_CMD_PHYAD(x) ((x) << 25)
#define GCB_MIIM_MII_CMD_VLD BIT(31)
#define GCB_MIIM_DATA 0xC
#define GCB_MIIM_DATA_ERROR (0x3 << 16)
#include "mscc_miim.h"
#define ANA_AC_RAM_CTRL_RAM_INIT 0x94358
#define ANA_AC_STAT_GLOBAL_CFG_PORT_RESET 0x94370
......@@ -279,13 +266,6 @@ struct jr2_private {
struct jr2_phy_port_t ports[MAX_PORT];
};
struct jr2_miim_dev {
void __iomem *regs;
phys_addr_t miim_base;
unsigned long miim_size;
struct mii_dev *bus;
};
static const unsigned long jr2_regs_qs[] = {
[MSCC_QS_XTR_RD] = 0x8,
[MSCC_QS_XTR_FLUSH] = 0x18,
......@@ -294,99 +274,9 @@ static const unsigned long jr2_regs_qs[] = {
[MSCC_QS_INJ_CTRL] = 0x34,
};
static struct jr2_miim_dev miim[JR2_MIIM_BUS_COUNT];
static struct mscc_miim_dev miim[JR2_MIIM_BUS_COUNT];
static int miim_count = -1;
static int mscc_miim_wait_ready(struct jr2_miim_dev *miim)
{
unsigned long deadline;
u32 val;
deadline = timer_get_us() + 250000;
do {
val = readl(miim->regs + GCB_MIIM_MII_STATUS);
} while (timer_get_us() <= deadline && (val & GCB_MIIM_STAT_BUSY));
if (val & GCB_MIIM_STAT_BUSY)
return -ETIMEDOUT;
return 0;
}
static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg)
{
struct jr2_miim_dev *miim = (struct jr2_miim_dev *)bus->priv;
u32 val;
int ret;
ret = mscc_miim_wait_ready(miim);
if (ret)
goto out;
writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
miim->regs + GCB_MIIM_MII_CMD);
ret = mscc_miim_wait_ready(miim);
if (ret)
goto out;
val = readl(miim->regs + GCB_MIIM_DATA);
if (val & GCB_MIIM_DATA_ERROR) {
ret = -EIO;
goto out;
}
ret = val & 0xFFFF;
out:
return ret;
}
static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
u16 val)
{
struct jr2_miim_dev *miim = (struct jr2_miim_dev *)bus->priv;
int ret;
ret = mscc_miim_wait_ready(miim);
if (ret < 0)
goto out;
writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
out:
return ret;
}
static struct mii_dev *jr2_mdiobus_init(phys_addr_t miim_base,
unsigned long miim_size)
{
struct mii_dev *bus;
bus = mdio_alloc();
if (!bus)
return NULL;
++miim_count;
sprintf(bus->name, "miim-bus%d", miim_count);
miim[miim_count].regs = ioremap(miim_base, miim_size);
miim[miim_count].miim_base = miim_base;
miim[miim_count].miim_size = miim_size;
bus->priv = &miim[miim_count];
bus->read = mscc_miim_read;
bus->write = mscc_miim_write;
if (mdio_register(bus))
return NULL;
miim[miim_count].bus = bus;
return bus;
}
static void jr2_cpu_capture_setup(struct jr2_private *priv)
{
/* ASM: No preamble and IFH prefix on CPU injected frames */
......@@ -973,7 +863,7 @@ static int jr2_probe(struct udevice *dev)
}
/* Initialize miim buses */
memset(&miim, 0x0, sizeof(struct jr2_miim_dev) * JR2_MIIM_BUS_COUNT);
memset(&miim, 0x0, sizeof(struct mscc_miim_dev) * JR2_MIIM_BUS_COUNT);
/* iterate all the ports and find out on which bus they are */
i = 0;
......@@ -1008,7 +898,8 @@ static int jr2_probe(struct udevice *dev)
/* If the bus is new then create a new bus */
if (!get_mdiobus(addr_base, addr_size))
priv->bus[miim_count] =
jr2_mdiobus_init(addr_base, addr_size);
mscc_mdiobus_init(miim, &miim_count, addr_base,
addr_size);
/* Connect mdio bus with the port */
bus = get_mdiobus(addr_base, addr_size);
......
......@@ -17,18 +17,7 @@
#include "mscc_xfer.h"
#include "mscc_mac_table.h"
#define GCB_MIIM_MII_STATUS 0x0
#define GCB_MIIM_STAT_BUSY BIT(3)
#define GCB_MIIM_MII_CMD 0x8
#define GCB_MIIM_MII_CMD_OPR_WRITE BIT(1)
#define GCB_MIIM_MII_CMD_OPR_READ BIT(2)
#define GCB_MIIM_MII_CMD_WRDATA(x) ((x) << 4)
#define GCB_MIIM_MII_CMD_REGAD(x) ((x) << 20)
#define GCB_MIIM_MII_CMD_PHYAD(x) ((x) << 25)
#define GCB_MIIM_MII_CMD_VLD BIT(31)
#define GCB_MIIM_DATA 0xC
#define GCB_MIIM_DATA_ERROR (0x2 << 16)
#include "mscc_miim.h"
#define ANA_PORT_VLAN_CFG(x) (0x00 + 0x80 * (x))
#define ANA_PORT_VLAN_CFG_AWARE_ENA BIT(20)
......@@ -189,13 +178,6 @@ struct luton_private {
struct luton_phy_port_t ports[MAX_PORT];
};
struct mscc_miim_dev {
void __iomem *regs;
phys_addr_t miim_base;
unsigned long miim_size;
struct mii_dev *bus;
};
static const unsigned long luton_regs_qs[] = {
[MSCC_QS_XTR_RD] = 0x18,
[MSCC_QS_XTR_FLUSH] = 0x28,
......@@ -213,84 +195,6 @@ static const unsigned long luton_regs_ana_table[] = {
static struct mscc_miim_dev miim[LUTON_MIIM_BUS_COUNT];
static int miim_count = -1;
static int mscc_miim_wait_ready(struct mscc_miim_dev *miim)
{
return wait_for_bit_le32(miim->regs + GCB_MIIM_MII_STATUS,
GCB_MIIM_STAT_BUSY, false, 250, false);
}
static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg)
{
struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
u32 val;
int ret;
ret = mscc_miim_wait_ready(miim);
if (ret)
goto out;
writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
miim->regs + GCB_MIIM_MII_CMD);
ret = mscc_miim_wait_ready(miim);
if (ret)
goto out;
val = readl(miim->regs + GCB_MIIM_DATA);
if (val & GCB_MIIM_DATA_ERROR) {
ret = -EIO;
goto out;
}
ret = val & 0xFFFF;
out:
return ret;
}
static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
u16 val)
{
struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
int ret;
ret = mscc_miim_wait_ready(miim);
if (ret < 0)
goto out;
writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
out:
return ret;
}
static struct mii_dev *serval_mdiobus_init(phys_addr_t miim_base,
unsigned long miim_size)
{
struct mii_dev *bus;
bus = mdio_alloc();
if (!bus)
return NULL;
++miim_count;
sprintf(bus->name, "miim-bus%d", miim_count);
miim[miim_count].regs = ioremap(miim_base, miim_size);
miim[miim_count].miim_base = miim_base;
miim[miim_count].miim_size = miim_size;
bus->priv = &miim[miim_count];
bus->read = mscc_miim_read;
bus->write = mscc_miim_write;
if (mdio_register(bus))
return NULL;
miim[miim_count].bus = bus;
return bus;
}
static void luton_stop(struct udevice *dev)
{
struct luton_private *priv = dev_get_priv(dev);
......@@ -760,7 +664,8 @@ static int luton_probe(struct udevice *dev)
/* If the bus is new then create a new bus */
if (!get_mdiobus(addr_base, addr_size))
priv->bus[miim_count] =
serval_mdiobus_init(addr_base, addr_size);
mscc_mdiobus_init(miim, &miim_count, addr_base,
addr_size);
/* Connect mdio bus with the port */
bus = get_mdiobus(addr_base, addr_size);
......
......@@ -72,3 +72,31 @@ int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
out:
return ret;
}
struct mii_dev *mscc_mdiobus_init(struct mscc_miim_dev *miim, int *miim_count,
phys_addr_t miim_base,
unsigned long miim_size)
{
struct mii_dev *bus;
bus = mdio_alloc();
if (!bus)
return NULL;
*miim_count += 1;
sprintf(bus->name, "miim-bus%d", *miim_count);
miim[*miim_count].regs = ioremap(miim_base, miim_size);
miim[*miim_count].miim_base = miim_base;
miim[*miim_count].miim_size = miim_size;
bus->priv = &miim[*miim_count];
bus->read = mscc_miim_read;
bus->write = mscc_miim_write;
if (mdio_register(bus))
return NULL;
miim[*miim_count].bus = bus;
return bus;
}
......@@ -3,10 +3,22 @@
* Copyright (c) 2018 Microsemi Corporation
*/
#ifndef _MSCC_MIIM_H_
#define _MSCC_MIIM_H_
struct mscc_miim_dev {
void __iomem *regs;
void __iomem *phy_regs;
phys_addr_t miim_base;
unsigned long miim_size;
struct mii_dev *bus;
};
int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg);
int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg, u16 val);
struct mii_dev *mscc_mdiobus_init(struct mscc_miim_dev *miim, int *miim_count,
phys_addr_t miim_base,
unsigned long miim_size);
#endif /* _MSCC_MIIM_H_ */
......@@ -17,6 +17,7 @@
#include "mscc_xfer.h"
#include "mscc_mac_table.h"
#include "mscc_miim.h"
#define PHY_CFG 0x0
#define PHY_CFG_ENA 0xF
......@@ -25,20 +26,6 @@
#define PHY_STAT 0x4
#define PHY_STAT_SUPERVISOR_COMPLETE BIT(0)
#define GCB_MIIM_MII_STATUS 0x0
#define GCB_MIIM_STAT_BUSY BIT(3)
#define GCB_MIIM_MII_CMD 0x8
#define GCB_MIIM_MII_CMD_SCAN BIT(0)
#define GCB_MIIM_MII_CMD_OPR_WRITE BIT(1)
#define GCB_MIIM_MII_CMD_OPR_READ BIT(2)
#define GCB_MIIM_MII_CMD_SINGLE_SCAN BIT(3)
#define GCB_MIIM_MII_CMD_WRDATA(x) ((x) << 4)
#define GCB_MIIM_MII_CMD_REGAD(x) ((x) << 20)
#define GCB_MIIM_MII_CMD_PHYAD(x) ((x) << 25)
#define GCB_MIIM_MII_CMD_VLD BIT(31)
#define GCB_MIIM_DATA 0xC
#define GCB_MIIM_DATA_ERROR (0x3 << 16)
#define ANA_PORT_VLAN_CFG(x) (0x7000 + 0x100 * (x))
#define ANA_PORT_VLAN_CFG_AWARE_ENA BIT(20)
#define ANA_PORT_VLAN_CFG_POP_CNT(x) ((x) << 18)
......@@ -173,13 +160,6 @@ struct ocelot_private {
struct ocelot_phy_port_t ports[MAX_PORT];
};
struct mscc_miim_dev {
void __iomem *regs;
phys_addr_t miim_base;
unsigned long miim_size;
struct mii_dev *bus;
};
static struct mscc_miim_dev miim[OCELOT_MIIM_BUS_COUNT];
static int miim_count = -1;
......@@ -209,85 +189,6 @@ static void mscc_phy_reset(void)
}
}
static int mscc_miim_wait_ready(struct mscc_miim_dev *miim)
{
return wait_for_bit_le32(miim->regs + GCB_MIIM_MII_STATUS,
GCB_MIIM_STAT_BUSY, false, 250, false);
}
static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg)
{
struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
u32 val;
int ret;
ret = mscc_miim_wait_ready(miim);
if (ret)
goto out;
writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
miim->regs + GCB_MIIM_MII_CMD);
ret = mscc_miim_wait_ready(miim);
if (ret)
goto out;
val = readl(miim->regs + GCB_MIIM_DATA);
if (val & GCB_MIIM_DATA_ERROR) {
ret = -EIO;
goto out;
}
ret = val & 0xFFFF;
out:
return ret;
}
static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
u16 val)
{
struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
int ret;
ret = mscc_miim_wait_ready(miim);
if (ret < 0)
goto out;
writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
out:
return ret;
}
static struct mii_dev *ocelot_mdiobus_init(phys_addr_t miim_base,
unsigned long miim_size)
{
struct mii_dev *bus;
bus = mdio_alloc();
if (!bus)
return NULL;
++miim_count;
sprintf(bus->name, "miim-bus%d", miim_count);
miim[miim_count].regs = ioremap(miim_base, miim_size);
miim[miim_count].miim_base = miim_base;
miim[miim_count].miim_size = miim_size;
bus->priv = &miim[miim_count];
bus->read = mscc_miim_read;
bus->write = mscc_miim_write;
if (mdio_register(bus))
return NULL;
miim[miim_count].bus = bus;
return bus;
}
__weak void mscc_switch_reset(void)
{
}
......@@ -682,7 +583,8 @@ static int ocelot_probe(struct udevice *dev)
/* If the bus is new then create a new bus */
if (!get_mdiobus(addr_base, addr_size))
priv->bus[miim_count] =
ocelot_mdiobus_init(addr_base, addr_size);
mscc_mdiobus_init(miim, &miim_count, addr_base,
addr_size);
/* Connect mdio bus with the port */
bus = get_mdiobus(addr_base, addr_size);
......
......@@ -17,18 +17,7 @@
#include "mscc_xfer.h"
#include "mscc_mac_table.h"
#define GCB_MIIM_MII_STATUS 0x0
#define GCB_MIIM_STAT_BUSY BIT(3)
#define GCB_MIIM_MII_CMD 0x8
#define GCB_MIIM_MII_CMD_OPR_WRITE BIT(1)
#define GCB_MIIM_MII_CMD_OPR_READ BIT(2)
#define GCB_MIIM_MII_CMD_WRDATA(x) ((x) << 4)
#define GCB_MIIM_MII_CMD_REGAD(x) ((x) << 20)
#define GCB_MIIM_MII_CMD_PHYAD(x) ((x) << 25)
#define GCB_MIIM_MII_CMD_VLD BIT(31)
#define GCB_MIIM_DATA 0xC
#define GCB_MIIM_DATA_ERROR (0x2 << 16)
#include "mscc_miim.h"
#define ANA_PORT_VLAN_CFG(x) (0xc000 + 0x100 * (x))
#define ANA_PORT_VLAN_CFG_AWARE_ENA BIT(20)
......@@ -156,13 +145,6 @@ struct serval_private {
struct serval_phy_port_t ports[MAX_PORT];
};
struct mscc_miim_dev {
void __iomem *regs;
phys_addr_t miim_base;
unsigned long miim_size;
struct mii_dev *bus;
};
static const unsigned long serval_regs_qs[] = {
[MSCC_QS_XTR_RD] = 0x8,
[MSCC_QS_XTR_FLUSH] = 0x18,
......@@ -180,84 +162,6 @@ static const unsigned long serval_regs_ana_table[] = {
static struct mscc_miim_dev miim[SERVAL_MIIM_BUS_COUNT];
static int miim_count = -1;
static int mscc_miim_wait_ready(struct mscc_miim_dev *miim)
{
return wait_for_bit_le32(miim->regs + GCB_MIIM_MII_STATUS,
GCB_MIIM_STAT_BUSY, false, 250, false);
}
static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg)
{
struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
u32 val;
int ret;
ret = mscc_miim_wait_ready(miim);
if (ret)
goto out;
writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
miim->regs + GCB_MIIM_MII_CMD);
ret = mscc_miim_wait_ready(miim);
if (ret)
goto out;
val = readl(miim->regs + GCB_MIIM_DATA);
if (val & GCB_MIIM_DATA_ERROR) {
ret = -EIO;
goto out;
}
ret = val & 0xFFFF;
out:
return ret;
}
static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
u16 val)
{
struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
int ret;
ret = mscc_miim_wait_ready(miim);
if (ret < 0)
goto out;
writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
out:
return ret;
}
static struct mii_dev *serval_mdiobus_init(phys_addr_t miim_base,
unsigned long miim_size)
{
struct mii_dev *bus;
bus = mdio_alloc();
if (!bus)
return NULL;
++miim_count;
sprintf(bus->name, "miim-bus%d", miim_count);
miim[miim_count].regs = ioremap(miim_base, miim_size);
miim[miim_count].miim_base = miim_base;
miim[miim_count].miim_size = miim_size;
bus->priv = &miim[miim_count];
bus->read = mscc_miim_read;
bus->write = mscc_miim_write;
if (mdio_register(bus))
return NULL;
miim[miim_count].bus = bus;
return bus;
}
static void serval_cpu_capture_setup(struct serval_private *priv)
{
int i;
......@@ -356,8 +260,6 @@ static void serdes_write(void __iomem *base, u32 addr)
do {
data = readl(base + HSIO_MCB_SERDES1G_CFG);
} while (data & HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT);
mdelay(100);
}
static void serdes1g_setup(void __iomem *base, uint32_t addr,
......@@ -636,7 +538,8 @@ static int serval_probe(struct udevice *dev)
/* If the bus is new then create a new bus */
if (!get_mdiobus(addr_base, addr_size))
priv->bus[miim_count] =
serval_mdiobus_init(addr_base, addr_size);
mscc_mdiobus_init(miim, &miim_count, addr_base,
addr_size);
/* Connect mdio bus with the port */
bus = get_mdiobus(addr_base, addr_size);
......
......@@ -16,18 +16,7 @@
#include <wait_bit.h>
#include "mscc_xfer.h"
#define GCB_MIIM_MII_STATUS 0x0
#define GCB_MIIM_STAT_BUSY BIT(3)
#define GCB_MIIM_MII_CMD 0x8
#define GCB_MIIM_MII_CMD_OPR_WRITE BIT(1)
#define GCB_MIIM_MII_CMD_OPR_READ BIT(2)
#define GCB_MIIM_MII_CMD_WRDATA(x) ((x) << 4)
#define GCB_MIIM_MII_CMD_REGAD(x) ((x) << 20)
#define GCB_MIIM_MII_CMD_PHYAD(x) ((x) << 25)
#define GCB_MIIM_MII_CMD_VLD BIT(31)
#define GCB_MIIM_DATA 0xC
#define GCB_MIIM_DATA_ERROR (0x3 << 16)
#include "mscc_miim.h"
#define PHY_CFG 0x0
#define PHY_CFG_ENA 0x3
......@@ -134,13 +123,6 @@ struct servalt_private {
struct servalt_phy_port_t ports[MAX_PORT];
};
struct mscc_miim_dev {
void __iomem *regs;
phys_addr_t miim_base;
unsigned long miim_size;
struct mii_dev *bus;
};
static const unsigned long servalt_regs_qs[] = {
[MSCC_QS_XTR_RD] = 0x8,
[MSCC_QS_XTR_FLUSH] = 0x18,
......@@ -152,85 +134,6 @@ static const unsigned long servalt_regs_qs[] = {
static struct mscc_miim_dev miim[SERVALT_MIIM_BUS_COUNT];
static int miim_count = -1;
static int mscc_miim_wait_ready(struct mscc_miim_dev *miim)
{
return wait_for_bit_le32(miim->regs + GCB_MIIM_MII_STATUS,
GCB_MIIM_STAT_BUSY, false, 250, false);
}
static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg)
{
struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
u32 val;
int ret;
ret = mscc_miim_wait_ready(miim);
if (ret)
goto out;
writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
miim->regs + GCB_MIIM_MII_CMD);
ret = mscc_miim_wait_ready(miim);
if (ret)
goto out;
val = readl(miim->regs + GCB_MIIM_DATA);
if (val & GCB_MIIM_DATA_ERROR) {
ret = -EIO;
goto out;
}
ret = val & 0xFFFF;
out:
return ret;
}
static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
u16 val)
{
struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
int ret;
ret = mscc_miim_wait_ready(miim);
if (ret < 0)
goto out;
writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
out:
return ret;
}
static struct mii_dev *servalt_mdiobus_init(phys_addr_t miim_base,
unsigned long miim_size)
{
struct mii_dev *bus;
bus = mdio_alloc();
if (!bus)
return NULL;
++miim_count;
sprintf(bus->name, "miim-bus%d", miim_count);
miim[miim_count].regs = ioremap(miim_base, miim_size);
miim[miim_count].miim_base = miim_base;
miim[miim_count].miim_size = miim_size;
bus->priv = &miim[miim_count];
bus->read = mscc_miim_read;
bus->write = mscc_miim_write;
if (mdio_register(bus))
return NULL;
miim[miim_count].bus = bus;
return bus;
}
static void mscc_phy_reset(void)
{
writel(0, BASE_DEVCPU_GCB + GCB_PHY_CFG + PHY_CFG);
......@@ -564,7 +467,8 @@ static int servalt_probe(struct udevice *dev)
/* If the bus is new then create a new bus */
if (!get_mdiobus(addr_base, addr_size))
priv->bus[miim_count] =
servalt_mdiobus_init(addr_base, addr_size);
mscc_mdiobus_init(miim, &miim_count, addr_base,
addr_size);
/* Connect mdio bus with the port */
bus = get_mdiobus(addr_base, addr_size);
......
......@@ -176,8 +176,13 @@ void cs4340_upload_firmware(struct phy_device *phydev)
printf("MMC read: dev # %u, block # %u, count %u ...\n",
dev, blk, cnt);
mmc_init(mmc);
#ifdef CONFIG_BLK
(void)blk_dread(mmc_get_blk_desc(mmc), blk, cnt,
addr);
#else
(void)mmc->block_dev.block_read(&mmc->block_dev, blk, cnt,
addr);
#endif
}
#endif
......
......@@ -103,7 +103,7 @@ struct dp83867_private {
int io_impedance;
bool rxctrl_strap_quirk;
int port_mirroring;
int clk_output_sel;
unsigned int clk_output_sel;
};
static int dp83867_config_port_mirroring(struct phy_device *phydev)
......@@ -136,17 +136,11 @@ static int dp83867_of_init(struct phy_device *phydev)
ofnode node;
u16 val;
/* Optional configuration */
node = phy_get_ofnode(phydev);
if (!ofnode_valid(node))
return -EINVAL;
/*
* Keep the default value if ti,clk-output-sel is not set
* or to high
*/
/* Keep the default value if ti,clk-output-sel is not set */
dp83867->clk_output_sel =
ofnode_read_u32_default(node, "ti,clk-output-sel",
DP83867_CLK_O_SEL_REF_CLK);
......@@ -162,14 +156,14 @@ static int dp83867_of_init(struct phy_device *phydev)
dp83867->rxctrl_strap_quirk = true;
dp83867->rx_id_delay = ofnode_read_u32_default(node,
"ti,rx-internal-delay",
-1);
DEFAULT_RX_ID_DELAY);
dp83867->tx_id_delay = ofnode_read_u32_default(node,
"ti,tx-internal-delay",
-1);
DEFAULT_TX_ID_DELAY);
dp83867->fifo_depth = ofnode_read_u32_default(node, "ti,fifo-depth",
-1);
DEFAULT_FIFO_DEPTH);
if (ofnode_read_bool(node, "enet-phy-lane-swap"))
dp83867->port_mirroring = DP83867_PORT_MIRRORING_EN;
......
......@@ -18,3 +18,11 @@ config DRIVER_TI_KEYSTONE_NET
bool "TI Keystone 2 Ethernet"
help
This driver supports the TI Keystone 2 Ethernet subsystem
config TI_AM65_CPSW_NUSS
bool "TI K3 AM65x MCU CPSW Nuss Ethernet controller driver"
depends on ARCH_K3
select PHYLIB
help
This driver supports TI K3 MCU CPSW Nuss Ethernet controller
in Texas Instruments K3 AM65x SoCs.
......@@ -5,3 +5,4 @@
obj-$(CONFIG_DRIVER_TI_CPSW) += cpsw.o cpsw-common.o cpsw_mdio.o
obj-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o
obj-$(CONFIG_DRIVER_TI_KEYSTONE_NET) += keystone_net.o cpsw_mdio.o
obj-$(CONFIG_TI_AM65_CPSW_NUSS) += am65-cpsw-nuss.o cpsw_mdio.o
此差异已折叠。
......@@ -125,7 +125,7 @@ u32 cpsw_mdio_get_alive(struct mii_dev *bus)
return val & GENMASK(15, 0);
}
struct mii_dev *cpsw_mdio_init(const char *name, u32 mdio_base,
struct mii_dev *cpsw_mdio_init(const char *name, phys_addr_t mdio_base,
u32 bus_freq, int fck_freq)
{
struct cpsw_mdio *cpsw_mdio;
......@@ -144,7 +144,7 @@ struct mii_dev *cpsw_mdio_init(const char *name, u32 mdio_base,
return NULL;
}
cpsw_mdio->regs = (struct cpsw_mdio_regs *)mdio_base;
cpsw_mdio->regs = (struct cpsw_mdio_regs *)(uintptr_t)mdio_base;
if (!bus_freq || !fck_freq)
cpsw_mdio->div = CPSW_MDIO_DIV_DEF;
......
......@@ -10,7 +10,7 @@
struct cpsw_mdio;
struct mii_dev *cpsw_mdio_init(const char *name, u32 mdio_base,
struct mii_dev *cpsw_mdio_init(const char *name, phys_addr_t mdio_base,
u32 bus_freq, int fck_freq);
void cpsw_mdio_free(struct mii_dev *bus);
u32 cpsw_mdio_get_alive(struct mii_dev *bus);
......
......@@ -58,6 +58,7 @@ enum uclass_id {
UCLASS_LPC, /* x86 'low pin count' interface */
UCLASS_MAILBOX, /* Mailbox controller */
UCLASS_MASS_STORAGE, /* Mass storage device */
UCLASS_MDIO, /* MDIO bus */
UCLASS_MISC, /* Miscellaneous device */
UCLASS_MMC, /* SD / MMC card or chip */
UCLASS_MOD_EXP, /* RSA Mod Exp device */
......
......@@ -118,4 +118,53 @@ int bb_miiphy_write(struct mii_dev *miidev, int addr, int devad, int reg,
#define ESTATUS_1000XF 0x8000
#define ESTATUS_1000XH 0x4000
#ifdef CONFIG_DM_MDIO
/**
* struct mdio_perdev_priv - Per-device class data for MDIO DM
*
* @mii_bus: Supporting MII legacy bus
*/
struct mdio_perdev_priv {
struct mii_dev *mii_bus;
};
/**
* struct mdio_ops - MDIO bus operations
*
* @read: Read from a PHY register
* @write: Write to a PHY register
* @reset: Reset the MDIO bus, NULL if not supported
*/
struct mdio_ops {
int (*read)(struct udevice *mdio_dev, int addr, int devad, int reg);
int (*write)(struct udevice *mdio_dev, int addr, int devad, int reg,
u16 val);
int (*reset)(struct udevice *mdio_dev);
};
#define mdio_get_ops(dev) ((struct mdio_ops *)(dev)->driver->ops)
/**
* dm_mdio_probe_devices - Call probe on all MII devices, currently used for
* MDIO console commands.
*/
void dm_mdio_probe_devices(void);
/**
* dm_mdio_phy_connect - Wrapper over phy_connect for DM MDIO
*
* @dev: mdio dev
* @addr: PHY address on MDIO bus
* @ethdev: ethernet device to connect to the PHY
* @interface: MAC-PHY protocol
*
* @return pointer to phy_device, or 0 on error
*/
struct phy_device *dm_mdio_phy_connect(struct udevice *dev, int addr,
struct udevice *ethdev,
phy_interface_t interface);
#endif
#endif
......@@ -15,6 +15,7 @@ obj-$(CONFIG_NET) += eth-uclass.o
else
obj-$(CONFIG_NET) += eth_legacy.o
endif
obj-$(CONFIG_DM_MDIO) += mdio-uclass.o
obj-$(CONFIG_NET) += eth_common.o
obj-$(CONFIG_CMD_LINK_LOCAL) += link_local.o
obj-$(CONFIG_NET) += net.o
......
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2019
* Alex Marginean, NXP
*/
#include <common.h>
#include <dm.h>
#include <miiphy.h>
#include <dm/device-internal.h>
#include <dm/uclass-internal.h>
void dm_mdio_probe_devices(void)
{
struct udevice *it;
struct uclass *uc;
uclass_get(UCLASS_MDIO, &uc);
uclass_foreach_dev(it, uc) {
device_probe(it);
}
}
static int dm_mdio_post_bind(struct udevice *dev)
{
/*
* MDIO command doesn't like spaces in names, don't allow them to keep
* it happy
*/
if (strchr(dev->name, ' ')) {
debug("\nError: MDIO device name \"%s\" has a space!\n",
dev->name);
return -EINVAL;
}
return 0;
}
/*
* Following read/write/reset functions are registered with legacy MII code.
* These are called for PHY operations by upper layers and we further call the
* DM MDIO driver functions.
*/
static int mdio_read(struct mii_dev *mii_bus, int addr, int devad, int reg)
{
struct udevice *dev = mii_bus->priv;
return mdio_get_ops(dev)->read(dev, addr, devad, reg);
}
static int mdio_write(struct mii_dev *mii_bus, int addr, int devad, int reg,
u16 val)
{
struct udevice *dev = mii_bus->priv;
return mdio_get_ops(dev)->write(dev, addr, devad, reg, val);
}
static int mdio_reset(struct mii_dev *mii_bus)
{
struct udevice *dev = mii_bus->priv;
if (mdio_get_ops(dev)->reset)
return mdio_get_ops(dev)->reset(dev);
else
return 0;
}
static int dm_mdio_post_probe(struct udevice *dev)
{
struct mdio_perdev_priv *pdata = dev_get_uclass_priv(dev);
pdata->mii_bus = mdio_alloc();
pdata->mii_bus->read = mdio_read;
pdata->mii_bus->write = mdio_write;
pdata->mii_bus->reset = mdio_reset;
pdata->mii_bus->priv = dev;
strncpy(pdata->mii_bus->name, dev->name, MDIO_NAME_LEN);
return mdio_register(pdata->mii_bus);
}
static int dm_mdio_pre_remove(struct udevice *dev)
{
struct mdio_perdev_priv *pdata = dev_get_uclass_priv(dev);
struct mdio_ops *ops = mdio_get_ops(dev);
if (ops->reset)
ops->reset(dev);
mdio_unregister(pdata->mii_bus);
mdio_free(pdata->mii_bus);
return 0;
}
struct phy_device *dm_mdio_phy_connect(struct udevice *dev, int addr,
struct udevice *ethdev,
phy_interface_t interface)
{
struct mdio_perdev_priv *pdata = dev_get_uclass_priv(dev);
if (device_probe(dev))
return 0;
return phy_connect(pdata->mii_bus, addr, ethdev, interface);
}
UCLASS_DRIVER(mdio) = {
.id = UCLASS_MDIO,
.name = "mdio",
.post_bind = dm_mdio_post_bind,
.post_probe = dm_mdio_post_probe,
.pre_remove = dm_mdio_pre_remove,
.per_device_auto_alloc_size = sizeof(struct mdio_perdev_priv),
};
......@@ -62,4 +62,5 @@ obj-$(CONFIG_SOUND) += sound.o
obj-$(CONFIG_TEE) += tee.o
obj-$(CONFIG_VIRTIO_SANDBOX) += virtio.o
obj-$(CONFIG_DMA) += dma.o
obj-$(CONFIG_DM_MDIO) += mdio.o
endif
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2019
* Alex Marginean, NXP
*/
#include <common.h>
#include <dm.h>
#include <dm/test.h>
#include <misc.h>
#include <test/ut.h>
#include <miiphy.h>
/* macros copied over from mdio_sandbox.c */
#define SANDBOX_PHY_ADDR 5
#define SANDBOX_PHY_REG 0
#define TEST_REG_VALUE 0xabcd
static int dm_test_mdio(struct unit_test_state *uts)
{
struct uclass *uc;
struct udevice *dev;
struct mdio_ops *ops;
u16 reg;
ut_assertok(uclass_get(UCLASS_MDIO, &uc));
ut_assertok(uclass_get_device_by_name(UCLASS_MDIO, "mdio-test", &dev));
ops = mdio_get_ops(dev);
ut_assertnonnull(ops);
ut_assertnonnull(ops->read);
ut_assertnonnull(ops->write);
ut_assertok(ops->write(dev, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE,
SANDBOX_PHY_REG, TEST_REG_VALUE));
reg = ops->read(dev, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE,
SANDBOX_PHY_REG);
ut_asserteq(reg, TEST_REG_VALUE);
ut_assert(ops->read(dev, SANDBOX_PHY_ADDR + 1, MDIO_DEVAD_NONE,
SANDBOX_PHY_REG) != 0);
ut_assertok(ops->reset(dev));
reg = ops->read(dev, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE,
SANDBOX_PHY_REG);
ut_asserteq(reg, 0);
return 0;
}
DM_TEST(dm_test_mdio, DM_TESTF_SCAN_FDT);
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册