summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/include/asm/arch-lpc32xx/i2c.h37
-rw-r--r--board/ge/bx50v3/bx50v3.c6
-rw-r--r--cmd/i2c.c10
-rw-r--r--common/fdt_support.c10
-rw-r--r--configs/A10-OLinuXino-Lime_defconfig4
-rw-r--r--configs/A20-OLinuXino-Lime2_defconfig4
-rw-r--r--configs/A20-OLinuXino-Lime_defconfig4
-rw-r--r--configs/A20-OLinuXino_MICRO_defconfig4
-rw-r--r--doc/device-tree-bindings/net/fixed-link.txt30
-rw-r--r--drivers/i2c/Kconfig14
-rw-r--r--drivers/i2c/lpc32xx_i2c.c236
-rw-r--r--drivers/i2c/omap24xx_i2c.c66
-rw-r--r--drivers/i2c/omap24xx_i2c.h10
-rw-r--r--drivers/net/bcm-sf2-eth-gmac.c113
-rw-r--r--drivers/net/bcm-sf2-eth.h4
-rw-r--r--drivers/net/phy/Kconfig10
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/fixed.c82
-rw-r--r--drivers/net/phy/phy.c23
-rw-r--r--drivers/net/sunxi_emac.c19
-rw-r--r--include/phy.h3
-rw-r--r--net/link_local.c2
22 files changed, 519 insertions, 173 deletions
diff --git a/arch/arm/include/asm/arch-lpc32xx/i2c.h b/arch/arm/include/asm/arch-lpc32xx/i2c.h
new file mode 100644
index 00000000000..5301d4c1b0f
--- /dev/null
+++ b/arch/arm/include/asm/arch-lpc32xx/i2c.h
@@ -0,0 +1,37 @@
+#ifndef _LPC32XX_I2C_H
+#define _LPC32XX_I2C_H
+
+#include <common.h>
+#include <asm/types.h>
+
+/* i2c register set */
+struct lpc32xx_i2c_base {
+ union {
+ u32 rx;
+ u32 tx;
+ };
+ u32 stat;
+ u32 ctrl;
+ u32 clk_hi;
+ u32 clk_lo;
+ u32 adr;
+ u32 rxfl;
+ u32 txfl;
+ u32 rxb;
+ u32 txb;
+ u32 stx;
+ u32 stxfl;
+};
+
+#ifdef CONFIG_DM_I2C
+enum {
+ I2C_0, I2C_1, I2C_2,
+};
+
+struct lpc32xx_i2c_dev {
+ struct lpc32xx_i2c_base *base;
+ int index;
+ uint speed;
+};
+#endif /* CONFIG_DM_I2C */
+#endif /* _LPC32XX_I2C_H */
diff --git a/board/ge/bx50v3/bx50v3.c b/board/ge/bx50v3/bx50v3.c
index 2fc1144cdae..0acf655c0e5 100644
--- a/board/ge/bx50v3/bx50v3.c
+++ b/board/ge/bx50v3/bx50v3.c
@@ -103,8 +103,9 @@ static void setup_iomux_enet(void)
/* Reset AR8033 PHY */
gpio_direction_output(IMX_GPIO_NR(1, 28), 0);
- udelay(500);
+ mdelay(10);
gpio_set_value(IMX_GPIO_NR(1, 28), 1);
+ mdelay(1);
}
static iomux_v3_cfg_t const usdhc2_pads[] = {
@@ -306,7 +307,8 @@ static int mx6_rgmii_rework(struct phy_device *phydev)
/* set debug port address: SerDes Test and System Mode Control */
phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05);
/* enable rgmii tx clock delay */
- phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100);
+ /* set the reserved bits to avoid board specific voltage peak issue*/
+ phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x3D47);
return 0;
}
diff --git a/cmd/i2c.c b/cmd/i2c.c
index 473153fbd47..3dd7c6ba4de 100644
--- a/cmd/i2c.c
+++ b/cmd/i2c.c
@@ -151,6 +151,16 @@ static int cmd_i2c_set_bus_num(unsigned int busnum)
static int i2c_get_cur_bus(struct udevice **busp)
{
+#ifdef CONFIG_I2C_SET_DEFAULT_BUS_NUM
+ if (!i2c_cur_bus) {
+ if (cmd_i2c_set_bus_num(CONFIG_I2C_DEFAULT_BUS_NUMBER)) {
+ printf("Default I2C bus %d not found\n",
+ CONFIG_I2C_DEFAULT_BUS_NUMBER);
+ return -ENODEV;
+ }
+ }
+#endif
+
if (!i2c_cur_bus) {
puts("No I2C bus selected\n");
return -ENODEV;
diff --git a/common/fdt_support.c b/common/fdt_support.c
index 55d4d6f6d44..c6a76b7ad29 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -482,7 +482,6 @@ void fdt_fixup_ethernet(void *fdt)
/* Cycle through all aliases */
for (prop = 0; ; prop++) {
const char *name;
- int len = strlen("ethernet");
/* FDT might have been edited, recompute the offset */
offset = fdt_first_property_offset(fdt,
@@ -495,8 +494,13 @@ void fdt_fixup_ethernet(void *fdt)
break;
path = fdt_getprop_by_offset(fdt, offset, &name, NULL);
- if (!strncmp(name, "ethernet", len)) {
- i = trailing_strtol(name);
+ if (!strncmp(name, "ethernet", 8)) {
+ /* Treat plain "ethernet" same as "ethernet0". */
+ if (!strcmp(name, "ethernet"))
+ i = 0;
+ else
+ i = trailing_strtol(name);
+
if (i != -1) {
if (i == 0)
strcpy(mac, "ethaddr");
diff --git a/configs/A10-OLinuXino-Lime_defconfig b/configs/A10-OLinuXino-Lime_defconfig
index 1cd3f1fd98b..6634139ab86 100644
--- a/configs/A10-OLinuXino-Lime_defconfig
+++ b/configs/A10-OLinuXino-Lime_defconfig
@@ -14,6 +14,10 @@ CONFIG_SPL_I2C_SUPPORT=y
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_FLASH is not set
# CONFIG_CMD_FPGA is not set
+CONFIG_NET_ETHADDR_EEPROM=y
+CONFIG_NET_ETHADDR_EEPROM_I2C=y
+CONFIG_NET_ETHADDR_EEPROM_I2C_BUS=1
+CONFIG_I2C1_ENABLE=y
# CONFIG_SPL_DOS_PARTITION is not set
# CONFIG_SPL_ISO_PARTITION is not set
# CONFIG_SPL_EFI_PARTITION is not set
diff --git a/configs/A20-OLinuXino-Lime2_defconfig b/configs/A20-OLinuXino-Lime2_defconfig
index a4ade72d4a3..4c720b31095 100644
--- a/configs/A20-OLinuXino-Lime2_defconfig
+++ b/configs/A20-OLinuXino-Lime2_defconfig
@@ -21,6 +21,10 @@ CONFIG_CMD_USB_MASS_STORAGE=y
# CONFIG_SPL_PARTITION_UUIDS is not set
CONFIG_DFU_RAM=y
CONFIG_ETH_DESIGNWARE=y
+CONFIG_NET_ETHADDR_EEPROM=y
+CONFIG_NET_ETHADDR_EEPROM_I2C=y
+CONFIG_NET_ETHADDR_EEPROM_I2C_BUS=1
+CONFIG_I2C1_ENABLE=y
CONFIG_AXP_ALDO3_VOLT=2800
CONFIG_AXP_ALDO4_VOLT=2800
CONFIG_USB_EHCI_HCD=y
diff --git a/configs/A20-OLinuXino-Lime_defconfig b/configs/A20-OLinuXino-Lime_defconfig
index 4fe4e4acf78..564ae256a35 100644
--- a/configs/A20-OLinuXino-Lime_defconfig
+++ b/configs/A20-OLinuXino-Lime_defconfig
@@ -16,6 +16,10 @@ CONFIG_SPL_I2C_SUPPORT=y
# CONFIG_SPL_ISO_PARTITION is not set
# CONFIG_SPL_EFI_PARTITION is not set
CONFIG_ETH_DESIGNWARE=y
+CONFIG_NET_ETHADDR_EEPROM=y
+CONFIG_NET_ETHADDR_EEPROM_I2C=y
+CONFIG_NET_ETHADDR_EEPROM_I2C_BUS=1
+CONFIG_I2C1_ENABLE=y
CONFIG_AXP_ALDO3_VOLT=2800
CONFIG_AXP_ALDO4_VOLT=2800
CONFIG_USB_EHCI_HCD=y
diff --git a/configs/A20-OLinuXino_MICRO_defconfig b/configs/A20-OLinuXino_MICRO_defconfig
index e1d91e3b085..93be13b4077 100644
--- a/configs/A20-OLinuXino_MICRO_defconfig
+++ b/configs/A20-OLinuXino_MICRO_defconfig
@@ -19,6 +19,10 @@ CONFIG_SPL_I2C_SUPPORT=y
# CONFIG_SPL_ISO_PARTITION is not set
# CONFIG_SPL_EFI_PARTITION is not set
CONFIG_ETH_DESIGNWARE=y
+CONFIG_NET_ETHADDR_EEPROM=y
+CONFIG_NET_ETHADDR_EEPROM_I2C=y
+CONFIG_NET_ETHADDR_EEPROM_I2C_BUS=1
+CONFIG_I2C1_ENABLE=y
CONFIG_AXP_ALDO3_VOLT=2800
CONFIG_AXP_ALDO4_VOLT=2800
CONFIG_USB_EHCI_HCD=y
diff --git a/doc/device-tree-bindings/net/fixed-link.txt b/doc/device-tree-bindings/net/fixed-link.txt
new file mode 100644
index 00000000000..5829bd81a22
--- /dev/null
+++ b/doc/device-tree-bindings/net/fixed-link.txt
@@ -0,0 +1,30 @@
+Fixed link Device Tree binding
+------------------------------
+
+Some Ethernet MACs have a "fixed link", and are not connected to a
+normal MDIO-managed PHY device. For those situations, a Device Tree
+binding allows to describe a "fixed link".
+
+Such a fixed link situation is described by creating a 'fixed-link'
+sub-node of the Ethernet MAC device node, with the following
+properties:
+
+* 'speed' (integer, mandatory), to indicate the link speed. Accepted
+ values are 10, 100 and 1000
+* 'full-duplex' (boolean, optional), to indicate that full duplex is
+ used. When absent, half duplex is assumed.
+* 'pause' (boolean, optional), to indicate that pause should be
+ enabled.
+* 'asym-pause' (boolean, optional), to indicate that asym_pause should
+ be enabled.
+
+Examples:
+
+ethernet@0 {
+ ...
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
+ ...
+};
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 8ac7aaf2d23..4e9afc120a3 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -49,6 +49,20 @@ config I2C_CROS_EC_LDO
avoid duplicating the logic in the TPS65090 regulator driver for
enabling/disabling an LDO.
+config I2C_SET_DEFAULT_BUS_NUM
+ bool "Set default I2C bus number"
+ depends on DM_I2C
+ help
+ Set default number of I2C bus to be accessed. This option provides
+ behaviour similar to old (i.e. pre DM) I2C bus driver.
+
+config I2C_DEFAULT_BUS_NUMBER
+ hex "I2C default bus number"
+ depends on I2C_SET_DEFAULT_BUS_NUM
+ default 0x0
+ help
+ Number of default I2C bus to use
+
config DM_I2C_GPIO
bool "Enable Driver Model for software emulated I2C bus driver"
depends on DM_I2C && DM_GPIO
diff --git a/drivers/i2c/lpc32xx_i2c.c b/drivers/i2c/lpc32xx_i2c.c
index b0167ab3dce..661d03147a4 100644
--- a/drivers/i2c/lpc32xx_i2c.c
+++ b/drivers/i2c/lpc32xx_i2c.c
@@ -5,9 +5,6 @@
* Written-by: Albert ARIBAUD - 3ADEV <albert.aribaud@3adev.fr>
*
* SPDX-License-Identifier: GPL-2.0+
- *
- * NOTE: This driver should be converted to driver model before June 2017.
- * Please see doc/driver-model/i2c-howto.txt for instructions.
*/
#include <common.h>
@@ -15,6 +12,9 @@
#include <i2c.h>
#include <linux/errno.h>
#include <asm/arch/clk.h>
+#include <asm/arch/i2c.h>
+#include <dm.h>
+#include <mapmem.h>
/*
* Provide default speed and slave if target did not
@@ -28,25 +28,6 @@
#define CONFIG_SYS_I2C_LPC32XX_SLAVE 0
#endif
-/* i2c register set */
-struct lpc32xx_i2c_registers {
- union {
- u32 rx;
- u32 tx;
- };
- u32 stat;
- u32 ctrl;
- u32 clk_hi;
- u32 clk_lo;
- u32 adr;
- u32 rxfl;
- u32 txfl;
- u32 rxb;
- u32 txb;
- u32 stx;
- u32 stxfl;
-};
-
/* TX register fields */
#define LPC32XX_I2C_TX_START 0x00000100
#define LPC32XX_I2C_TX_STOP 0x00000200
@@ -61,15 +42,17 @@ struct lpc32xx_i2c_registers {
#define LPC32XX_I2C_STAT_NAI 0x00000004
#define LPC32XX_I2C_STAT_TDI 0x00000001
-static struct lpc32xx_i2c_registers *lpc32xx_i2c[] = {
- (struct lpc32xx_i2c_registers *)I2C1_BASE,
- (struct lpc32xx_i2c_registers *)I2C2_BASE,
- (struct lpc32xx_i2c_registers *)(USB_BASE + 0x300)
+#ifndef CONFIG_DM_I2C
+static struct lpc32xx_i2c_base *lpc32xx_i2c[] = {
+ (struct lpc32xx_i2c_base *)I2C1_BASE,
+ (struct lpc32xx_i2c_base *)I2C2_BASE,
+ (struct lpc32xx_i2c_base *)(USB_BASE + 0x300)
};
+#endif
/* Set I2C bus speed */
-static unsigned int lpc32xx_i2c_set_bus_speed(struct i2c_adapter *adap,
- unsigned int speed)
+static unsigned int __i2c_set_bus_speed(struct lpc32xx_i2c_base *base,
+ unsigned int speed, unsigned int chip)
{
int half_period;
@@ -77,7 +60,7 @@ static unsigned int lpc32xx_i2c_set_bus_speed(struct i2c_adapter *adap,
return -EINVAL;
/* OTG I2C clock source and CLK registers are different */
- if (adap->hwadapnr == 2) {
+ if (chip == 2) {
half_period = (get_periph_clk_rate() / speed) / 2;
if (half_period > 0xFF)
return -EINVAL;
@@ -87,38 +70,35 @@ static unsigned int lpc32xx_i2c_set_bus_speed(struct i2c_adapter *adap,
return -EINVAL;
}
- writel(half_period, &lpc32xx_i2c[adap->hwadapnr]->clk_hi);
- writel(half_period, &lpc32xx_i2c[adap->hwadapnr]->clk_lo);
+ writel(half_period, &base->clk_hi);
+ writel(half_period, &base->clk_lo);
return 0;
}
/* I2C init called by cmd_i2c when doing 'i2c reset'. */
-static void _i2c_init(struct i2c_adapter *adap,
- int requested_speed, int slaveadd)
+static void __i2c_init(struct lpc32xx_i2c_base *base,
+ int requested_speed, int slaveadd, unsigned int chip)
{
- struct lpc32xx_i2c_registers *i2c = lpc32xx_i2c[adap->hwadapnr];
-
/* soft reset (auto-clears) */
- writel(LPC32XX_I2C_SOFT_RESET, &i2c->ctrl);
+ writel(LPC32XX_I2C_SOFT_RESET, &base->ctrl);
/* set HI and LO periods for half of the default speed */
- lpc32xx_i2c_set_bus_speed(adap, requested_speed);
+ __i2c_set_bus_speed(base, requested_speed, chip);
}
/* I2C probe called by cmd_i2c when doing 'i2c probe'. */
-static int lpc32xx_i2c_probe(struct i2c_adapter *adap, u8 dev)
+static int __i2c_probe_chip(struct lpc32xx_i2c_base *base, u8 dev)
{
- struct lpc32xx_i2c_registers *i2c = lpc32xx_i2c[adap->hwadapnr];
int stat;
/* Soft-reset the controller */
- writel(LPC32XX_I2C_SOFT_RESET, &i2c->ctrl);
- while (readl(&i2c->ctrl) & LPC32XX_I2C_SOFT_RESET)
+ writel(LPC32XX_I2C_SOFT_RESET, &base->ctrl);
+ while (readl(&base->ctrl) & LPC32XX_I2C_SOFT_RESET)
;
/* Addre slave for write with start before and stop after */
writel((dev<<1) | LPC32XX_I2C_TX_START | LPC32XX_I2C_TX_STOP,
- &i2c->tx);
+ &base->tx);
/* wait for end of transation */
- while (!((stat = readl(&i2c->stat)) & LPC32XX_I2C_STAT_TDI))
+ while (!((stat = readl(&base->stat)) & LPC32XX_I2C_STAT_TDI))
;
/* was there no acknowledge? */
return (stat & LPC32XX_I2C_STAT_NAI) ? -1 : 0;
@@ -128,20 +108,19 @@ static int lpc32xx_i2c_probe(struct i2c_adapter *adap, u8 dev)
* I2C read called by cmd_i2c when doing 'i2c read' and by cmd_eeprom.c
* Begin write, send address byte(s), begin read, receive data bytes, end.
*/
-static int lpc32xx_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr,
- int alen, u8 *data, int length)
+static int __i2c_read(struct lpc32xx_i2c_base *base, u8 dev, uint addr,
+ int alen, u8 *data, int length)
{
- struct lpc32xx_i2c_registers *i2c = lpc32xx_i2c[adap->hwadapnr];
int stat, wlen;
/* Soft-reset the controller */
- writel(LPC32XX_I2C_SOFT_RESET, &i2c->ctrl);
- while (readl(&i2c->ctrl) & LPC32XX_I2C_SOFT_RESET)
+ writel(LPC32XX_I2C_SOFT_RESET, &base->ctrl);
+ while (readl(&base->ctrl) & LPC32XX_I2C_SOFT_RESET)
;
/* do we need to write an address at all? */
if (alen) {
/* Address slave in write mode */
- writel((dev<<1) | LPC32XX_I2C_TX_START, &i2c->tx);
+ writel((dev<<1) | LPC32XX_I2C_TX_START, &base->tx);
/* write address bytes */
while (alen--) {
/* compute address byte + stop for the last one */
@@ -149,44 +128,44 @@ static int lpc32xx_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr,
if (!alen)
a |= LPC32XX_I2C_TX_STOP;
/* Send address byte */
- writel(a, &i2c->tx);
+ writel(a, &base->tx);
}
/* wait for end of transation */
- while (!((stat = readl(&i2c->stat)) & LPC32XX_I2C_STAT_TDI))
+ while (!((stat = readl(&base->stat)) & LPC32XX_I2C_STAT_TDI))
;
/* clear end-of-transaction flag */
- writel(1, &i2c->stat);
+ writel(1, &base->stat);
}
/* do we have to read data at all? */
if (length) {
/* Address slave in read mode */
- writel(1 | (dev<<1) | LPC32XX_I2C_TX_START, &i2c->tx);
+ writel(1 | (dev<<1) | LPC32XX_I2C_TX_START, &base->tx);
wlen = length;
/* get data */
while (length | wlen) {
/* read status for TFF and RFE */
- stat = readl(&i2c->stat);
+ stat = readl(&base->stat);
/* must we, can we write a trigger byte? */
if ((wlen > 0)
& (!(stat & LPC32XX_I2C_STAT_TFF))) {
wlen--;
/* write trigger byte + stop if last */
writel(wlen ? 0 :
- LPC32XX_I2C_TX_STOP, &i2c->tx);
+ LPC32XX_I2C_TX_STOP, &base->tx);
}
/* must we, can we read a data byte? */
if ((length > 0)
& (!(stat & LPC32XX_I2C_STAT_RFE))) {
length--;
/* read byte */
- *(data++) = readl(&i2c->rx);
+ *(data++) = readl(&base->rx);
}
}
/* wait for end of transation */
- while (!((stat = readl(&i2c->stat)) & LPC32XX_I2C_STAT_TDI))
+ while (!((stat = readl(&base->stat)) & LPC32XX_I2C_STAT_TDI))
;
/* clear end-of-transaction flag */
- writel(1, &i2c->stat);
+ writel(1, &base->stat);
}
/* success */
return 0;
@@ -196,38 +175,37 @@ static int lpc32xx_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr,
* I2C write called by cmd_i2c when doing 'i2c write' and by cmd_eeprom.c
* Begin write, send address byte(s), send data bytes, end.
*/
-static int lpc32xx_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr,
- int alen, u8 *data, int length)
+static int __i2c_write(struct lpc32xx_i2c_base *base, u8 dev, uint addr,
+ int alen, u8 *data, int length)
{
- struct lpc32xx_i2c_registers *i2c = lpc32xx_i2c[adap->hwadapnr];
int stat;
/* Soft-reset the controller */
- writel(LPC32XX_I2C_SOFT_RESET, &i2c->ctrl);
- while (readl(&i2c->ctrl) & LPC32XX_I2C_SOFT_RESET)
+ writel(LPC32XX_I2C_SOFT_RESET, &base->ctrl);
+ while (readl(&base->ctrl) & LPC32XX_I2C_SOFT_RESET)
;
/* do we need to write anything at all? */
if (alen | length)
/* Address slave in write mode */
- writel((dev<<1) | LPC32XX_I2C_TX_START, &i2c->tx);
+ writel((dev<<1) | LPC32XX_I2C_TX_START, &base->tx);
else
return 0;
/* write address bytes */
while (alen) {
/* wait for transmit fifo not full */
- stat = readl(&i2c->stat);
+ stat = readl(&base->stat);
if (!(stat & LPC32XX_I2C_STAT_TFF)) {
alen--;
int a = (addr >> (8 * alen)) & 0xff;
if (!(alen | length))
a |= LPC32XX_I2C_TX_STOP;
/* Send address byte */
- writel(a, &i2c->tx);
+ writel(a, &base->tx);
}
}
while (length) {
/* wait for transmit fifo not full */
- stat = readl(&i2c->stat);
+ stat = readl(&base->stat);
if (!(stat & LPC32XX_I2C_STAT_TFF)) {
/* compute data byte, add stop if length==0 */
length--;
@@ -235,34 +213,146 @@ static int lpc32xx_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr,
if (!length)
d |= LPC32XX_I2C_TX_STOP;
/* Send data byte */
- writel(d, &i2c->tx);
+ writel(d, &base->tx);
}
}
/* wait for end of transation */
- while (!((stat = readl(&i2c->stat)) & LPC32XX_I2C_STAT_TDI))
+ while (!((stat = readl(&base->stat)) & LPC32XX_I2C_STAT_TDI))
;
/* clear end-of-transaction flag */
- writel(1, &i2c->stat);
+ writel(1, &base->stat);
return 0;
}
-U_BOOT_I2C_ADAP_COMPLETE(lpc32xx_0, _i2c_init, lpc32xx_i2c_probe,
+#ifndef CONFIG_DM_I2C
+static void lpc32xx_i2c_init(struct i2c_adapter *adap,
+ int requested_speed, int slaveadd)
+{
+ __i2c_init(lpc32xx_i2c[adap->hwadapnr], requested_speed, slaveadd,
+ adap->hwadapnr);
+}
+
+static int lpc32xx_i2c_probe_chip(struct i2c_adapter *adap, u8 dev)
+{
+ return __i2c_probe_chip(lpc32xx_i2c[adap->hwadapnr], dev);
+}
+
+static int lpc32xx_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr,
+ int alen, u8 *data, int length)
+{
+ return __i2c_read(lpc32xx_i2c[adap->hwadapnr], dev, addr,
+ alen, data, length);
+}
+
+static int lpc32xx_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr,
+ int alen, u8 *data, int length)
+{
+ return __i2c_write(lpc32xx_i2c[adap->hwadapnr], dev, addr,
+ alen, data, length);
+}
+
+static unsigned int lpc32xx_i2c_set_bus_speed(struct i2c_adapter *adap,
+ unsigned int speed)
+{
+ return __i2c_set_bus_speed(lpc32xx_i2c[adap->hwadapnr], speed,
+ adap->hwadapnr);
+}
+
+U_BOOT_I2C_ADAP_COMPLETE(lpc32xx_0, lpc32xx_i2c_init, lpc32xx_i2c_probe_chip,
lpc32xx_i2c_read, lpc32xx_i2c_write,
lpc32xx_i2c_set_bus_speed,
CONFIG_SYS_I2C_LPC32XX_SPEED,
CONFIG_SYS_I2C_LPC32XX_SLAVE,
0)
-U_BOOT_I2C_ADAP_COMPLETE(lpc32xx_1, _i2c_init, lpc32xx_i2c_probe,
+U_BOOT_I2C_ADAP_COMPLETE(lpc32xx_1, lpc32xx_i2c_init, lpc32xx_i2c_probe_chip,
lpc32xx_i2c_read, lpc32xx_i2c_write,
lpc32xx_i2c_set_bus_speed,
CONFIG_SYS_I2C_LPC32XX_SPEED,
CONFIG_SYS_I2C_LPC32XX_SLAVE,
1)
-U_BOOT_I2C_ADAP_COMPLETE(lpc32xx_2, _i2c_init, NULL,
+U_BOOT_I2C_ADAP_COMPLETE(lpc32xx_2, lpc32xx_i2c_init, NULL,
lpc32xx_i2c_read, lpc32xx_i2c_write,
lpc32xx_i2c_set_bus_speed,
100000,
0,
2)
+#else /* CONFIG_DM_I2C */
+static int lpc32xx_i2c_probe(struct udevice *bus)
+{
+ struct lpc32xx_i2c_dev *dev = dev_get_platdata(bus);
+ bus->seq = dev->index;
+
+ __i2c_init(dev->base, dev->speed, 0, dev->index);
+ return 0;
+}
+
+static int lpc32xx_i2c_probe_chip(struct udevice *bus, u32 chip_addr,
+ u32 chip_flags)
+{
+ struct lpc32xx_i2c_dev *dev = dev_get_platdata(bus);
+ return __i2c_probe_chip(dev->base, chip_addr);
+}
+
+static int lpc32xx_i2c_xfer(struct udevice *bus, struct i2c_msg *msg,
+ int nmsgs)
+{
+ struct lpc32xx_i2c_dev *dev = dev_get_platdata(bus);
+ struct i2c_msg *dmsg, *omsg, dummy;
+ uint i = 0, address = 0;
+
+ memset(&dummy, 0, sizeof(struct i2c_msg));
+
+ /* We expect either two messages (one with an offset and one with the
+ * actual data) or one message (just data)
+ */
+ if (nmsgs > 2 || nmsgs == 0) {
+ debug("%s: Only one or two messages are supported.", __func__);
+ return -1;
+ }
+
+ omsg = nmsgs == 1 ? &dummy : msg;
+ dmsg = nmsgs == 1 ? msg : msg + 1;
+
+ /* the address is expected to be a uint, not a array. */
+ address = omsg->buf[0];
+ for (i = 1; i < omsg->len; i++)
+ address = (address << 8) + omsg->buf[i];
+
+ if (dmsg->flags & I2C_M_RD)
+ return __i2c_read(dev->base, dmsg->addr, address,
+ omsg->len, dmsg->buf, dmsg->len);
+ else
+ return __i2c_write(dev->base, dmsg->addr, address,
+ omsg->len, dmsg->buf, dmsg->len);
+}
+
+static int lpc32xx_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
+{
+ struct lpc32xx_i2c_dev *dev = dev_get_platdata(bus);
+ return __i2c_set_bus_speed(dev->base, speed, dev->index);
+}
+
+static int lpc32xx_i2c_reset(struct udevice *bus)
+{
+ struct lpc32xx_i2c_dev *dev = dev_get_platdata(bus);
+
+ __i2c_init(dev->base, dev->speed, 0, dev->index);
+ return 0;
+}
+
+static const struct dm_i2c_ops lpc32xx_i2c_ops = {
+ .xfer = lpc32xx_i2c_xfer,
+ .probe_chip = lpc32xx_i2c_probe_chip,
+ .deblock = lpc32xx_i2c_reset,
+ .set_bus_speed = lpc32xx_i2c_set_bus_speed,
+};
+
+U_BOOT_DRIVER(i2c_lpc32xx) = {
+ .id = UCLASS_I2C,
+ .name = "i2c_lpc32xx",
+ .probe = lpc32xx_i2c_probe,
+ .ops = &lpc32xx_i2c_ops,
+};
+#endif /* CONFIG_DM_I2C */
diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
index 00063431040..26996e9db93 100644
--- a/drivers/i2c/omap24xx_i2c.c
+++ b/drivers/i2c/omap24xx_i2c.c
@@ -64,36 +64,52 @@ struct omap_i2c {
static int omap24_i2c_findpsc(u32 *pscl, u32 *psch, uint speed)
{
- unsigned int sampleclk, prescaler;
- int fsscll, fssclh;
+ unsigned long internal_clk = 0, fclk;
+ unsigned int prescaler;
- speed <<= 1;
- prescaler = 0;
/*
- * some divisors may cause a precission loss, but shouldn't
- * be a big thing, because i2c_clk is then allready very slow.
+ * This method is only called for Standard and Fast Mode speeds
+ *
+ * For some TI SoCs it is explicitly written in TRM (e,g, SPRUHZ6G,
+ * page 5685, Table 24-7)
+ * that the internal I2C clock (after prescaler) should be between
+ * 7-12 MHz (at least for Fast Mode (FS)).
+ *
+ * Such approach is used in v4.9 Linux kernel in:
+ * ./drivers/i2c/busses/i2c-omap.c (omap_i2c_init function).
*/
- while (prescaler <= 0xFF) {
- sampleclk = I2C_IP_CLK / (prescaler+1);
- fsscll = sampleclk / speed;
- fssclh = fsscll;
- fsscll -= I2C_FASTSPEED_SCLL_TRIM;
- fssclh -= I2C_FASTSPEED_SCLH_TRIM;
-
- if (((fsscll > 0) && (fssclh > 0)) &&
- ((fsscll <= (255-I2C_FASTSPEED_SCLL_TRIM)) &&
- (fssclh <= (255-I2C_FASTSPEED_SCLH_TRIM)))) {
- if (pscl)
- *pscl = fsscll;
- if (psch)
- *psch = fssclh;
-
- return prescaler;
- }
- prescaler++;
+ speed /= 1000; /* convert speed to kHz */
+
+ if (speed > 100)
+ internal_clk = 9600;
+ else
+ internal_clk = 4000;
+
+ fclk = I2C_IP_CLK / 1000;
+ prescaler = fclk / internal_clk;
+ prescaler = prescaler - 1;
+
+ if (speed > 100) {
+ unsigned long scl;
+
+ /* Fast mode */
+ scl = internal_clk / speed;
+ *pscl = scl - (scl / 3) - I2C_FASTSPEED_SCLL_TRIM;
+ *psch = (scl / 3) - I2C_FASTSPEED_SCLH_TRIM;
+ } else {
+ /* Standard mode */
+ *pscl = internal_clk / (speed * 2) - I2C_FASTSPEED_SCLL_TRIM;
+ *psch = internal_clk / (speed * 2) - I2C_FASTSPEED_SCLH_TRIM;
}
- return -1;
+
+ debug("%s: speed [kHz]: %d psc: 0x%x sscl: 0x%x ssch: 0x%x\n",
+ __func__, speed, prescaler, *pscl, *psch);
+
+ if (*pscl <= 0 || *psch <= 0 || prescaler <= 0)
+ return -EINVAL;
+
+ return prescaler;
}
/*
diff --git a/drivers/i2c/omap24xx_i2c.h b/drivers/i2c/omap24xx_i2c.h
index 3dae295e55e..8a4ae9847c5 100644
--- a/drivers/i2c/omap24xx_i2c.h
+++ b/drivers/i2c/omap24xx_i2c.h
@@ -121,17 +121,17 @@
* scll_trim = 7
* sclh_trim = 5
*
- * The linux 2.6.30 kernel uses
- * scll_trim = 6
- * sclh_trim = 6
+ * The linux 4.9 kernel uses
+ * scll_trim = 7
+ * sclh_trim = 5
*
* These are the trim values for standard and fast speed
*/
#ifndef I2C_FASTSPEED_SCLL_TRIM
-#define I2C_FASTSPEED_SCLL_TRIM 6
+#define I2C_FASTSPEED_SCLL_TRIM 7
#endif
#ifndef I2C_FASTSPEED_SCLH_TRIM
-#define I2C_FASTSPEED_SCLH_TRIM 6
+#define I2C_FASTSPEED_SCLH_TRIM 5
#endif
/* These are the trim values for high speed */
diff --git a/drivers/net/bcm-sf2-eth-gmac.c b/drivers/net/bcm-sf2-eth-gmac.c
index f2853cfad25..9ff72fa1edc 100644
--- a/drivers/net/bcm-sf2-eth-gmac.c
+++ b/drivers/net/bcm-sf2-eth-gmac.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Broadcom Corporation.
+ * Copyright 2014-2017 Broadcom.
*
* SPDX-License-Identifier: GPL-2.0+
*/
@@ -28,6 +28,10 @@
} \
}
+#define RX_BUF_SIZE_ALIGNED ALIGN(RX_BUF_SIZE, ARCH_DMA_MINALIGN)
+#define TX_BUF_SIZE_ALIGNED ALIGN(TX_BUF_SIZE, ARCH_DMA_MINALIGN)
+#define DESCP_SIZE_ALIGNED ALIGN(sizeof(dma64dd_t), ARCH_DMA_MINALIGN)
+
static int gmac_disable_dma(struct eth_dma *dma, int dir);
static int gmac_enable_dma(struct eth_dma *dma, int dir);
@@ -114,7 +118,7 @@ static void dma_tx_dump(struct eth_dma *dma)
printf("TX Buffers:\n");
/* Initialize TX DMA descriptor table */
for (i = 0; i < TX_BUF_NUM; i++) {
- bufp = (uint8_t *)(dma->tx_buf + i * TX_BUF_SIZE);
+ bufp = (uint8_t *)(dma->tx_buf + i * TX_BUF_SIZE_ALIGNED);
printf("buf%d:0x%x; ", i, (uint32_t)bufp);
}
printf("\n");
@@ -145,7 +149,7 @@ static void dma_rx_dump(struct eth_dma *dma)
printf("RX Buffers:\n");
for (i = 0; i < RX_BUF_NUM; i++) {
- bufp = dma->rx_buf + i * RX_BUF_SIZE;
+ bufp = dma->rx_buf + i * RX_BUF_SIZE_ALIGNED;
printf("buf%d:0x%x; ", i, (uint32_t)bufp);
}
printf("\n");
@@ -163,15 +167,15 @@ static int dma_tx_init(struct eth_dma *dma)
/* clear descriptor memory */
memset((void *)(dma->tx_desc_aligned), 0,
- TX_BUF_NUM * sizeof(dma64dd_t));
- memset(dma->tx_buf, 0, TX_BUF_NUM * TX_BUF_SIZE);
+ TX_BUF_NUM * DESCP_SIZE_ALIGNED);
+ memset(dma->tx_buf, 0, TX_BUF_NUM * TX_BUF_SIZE_ALIGNED);
/* Initialize TX DMA descriptor table */
for (i = 0; i < TX_BUF_NUM; i++) {
descp = (dma64dd_t *)(dma->tx_desc_aligned) + i;
- bufp = dma->tx_buf + i * TX_BUF_SIZE;
+ bufp = dma->tx_buf + i * TX_BUF_SIZE_ALIGNED;
/* clear buffer memory */
- memset((void *)bufp, 0, TX_BUF_SIZE);
+ memset((void *)bufp, 0, TX_BUF_SIZE_ALIGNED);
ctrl = 0;
/* if last descr set endOfTable */
@@ -187,10 +191,11 @@ static int dma_tx_init(struct eth_dma *dma)
descp = dma->tx_desc_aligned;
bufp = dma->tx_buf;
flush_dcache_range((unsigned long)descp,
- (unsigned long)(descp +
- sizeof(dma64dd_t) * TX_BUF_NUM));
- flush_dcache_range((unsigned long)(bufp),
- (unsigned long)(bufp + TX_BUF_SIZE * TX_BUF_NUM));
+ (unsigned long)descp +
+ DESCP_SIZE_ALIGNED * TX_BUF_NUM);
+ flush_dcache_range((unsigned long)bufp,
+ (unsigned long)bufp +
+ TX_BUF_SIZE_ALIGNED * TX_BUF_NUM);
/* initialize the DMA channel */
writel((uint32_t)(dma->tx_desc_aligned), GMAC0_DMA_TX_ADDR_LOW_ADDR);
@@ -215,20 +220,20 @@ static int dma_rx_init(struct eth_dma *dma)
/* clear descriptor memory */
memset((void *)(dma->rx_desc_aligned), 0,
- RX_BUF_NUM * sizeof(dma64dd_t));
+ RX_BUF_NUM * DESCP_SIZE_ALIGNED);
/* clear buffer memory */
- memset(dma->rx_buf, 0, RX_BUF_NUM * RX_BUF_SIZE);
+ memset(dma->rx_buf, 0, RX_BUF_NUM * RX_BUF_SIZE_ALIGNED);
/* Initialize RX DMA descriptor table */
for (i = 0; i < RX_BUF_NUM; i++) {
descp = (dma64dd_t *)(dma->rx_desc_aligned) + i;
- bufp = dma->rx_buf + i * RX_BUF_SIZE;
+ bufp = dma->rx_buf + i * RX_BUF_SIZE_ALIGNED;
ctrl = 0;
/* if last descr set endOfTable */
if (i == (RX_BUF_NUM - 1))
ctrl = D64_CTRL1_EOT;
descp->ctrl1 = ctrl;
- descp->ctrl2 = RX_BUF_SIZE;
+ descp->ctrl2 = RX_BUF_SIZE_ALIGNED;
descp->addrlow = (uint32_t)bufp;
descp->addrhigh = 0;
@@ -240,10 +245,11 @@ static int dma_rx_init(struct eth_dma *dma)
bufp = dma->rx_buf;
/* flush descriptor and buffer */
flush_dcache_range((unsigned long)descp,
- (unsigned long)(descp +
- sizeof(dma64dd_t) * RX_BUF_NUM));
+ (unsigned long)descp +
+ DESCP_SIZE_ALIGNED * RX_BUF_NUM);
flush_dcache_range((unsigned long)(bufp),
- (unsigned long)(bufp + RX_BUF_SIZE * RX_BUF_NUM));
+ (unsigned long)bufp +
+ RX_BUF_SIZE_ALIGNED * RX_BUF_NUM);
/* initailize the DMA channel */
writel((uint32_t)descp, GMAC0_DMA_RX_ADDR_LOW_ADDR);
@@ -292,14 +298,12 @@ static int dma_deinit(struct eth_dma *dma)
free(dma->tx_buf);
dma->tx_buf = NULL;
- free(dma->tx_desc);
- dma->tx_desc = NULL;
+ free(dma->tx_desc_aligned);
dma->tx_desc_aligned = NULL;
free(dma->rx_buf);
dma->rx_buf = NULL;
- free(dma->rx_desc);
- dma->rx_desc = NULL;
+ free(dma->rx_desc_aligned);
dma->rx_desc_aligned = NULL;
return 0;
@@ -307,7 +311,7 @@ static int dma_deinit(struct eth_dma *dma)
int gmac_tx_packet(struct eth_dma *dma, void *packet, int length)
{
- uint8_t *bufp = dma->tx_buf + dma->cur_tx_index * TX_BUF_SIZE;
+ uint8_t *bufp = dma->tx_buf + dma->cur_tx_index * TX_BUF_SIZE_ALIGNED;
/* kick off the dma */
size_t len = length;
@@ -348,10 +352,11 @@ int gmac_tx_packet(struct eth_dma *dma, void *packet, int length)
descp->ctrl2 = ctrl;
/* flush descriptor and buffer */
- flush_dcache_range((unsigned long)descp,
- (unsigned long)(descp + sizeof(dma64dd_t)));
+ flush_dcache_range((unsigned long)dma->tx_desc_aligned,
+ (unsigned long)dma->tx_desc_aligned +
+ DESCP_SIZE_ALIGNED * TX_BUF_NUM);
flush_dcache_range((unsigned long)bufp,
- (unsigned long)(bufp + TX_BUF_SIZE));
+ (unsigned long)bufp + TX_BUF_SIZE_ALIGNED);
/* now update the dma last descriptor */
writel(last_desc, GMAC0_DMA_TX_PTR_ADDR);
@@ -426,14 +431,15 @@ int gmac_check_rx_done(struct eth_dma *dma, uint8_t *buf)
;
/* get the packet pointer that corresponds to the rx descriptor */
- bufp = dma->rx_buf + index * RX_BUF_SIZE;
+ bufp = dma->rx_buf + index * RX_BUF_SIZE_ALIGNED;
descp = (dma64dd_t *)(dma->rx_desc_aligned) + index;
/* flush descriptor and buffer */
- flush_dcache_range((unsigned long)descp,
- (unsigned long)(descp + sizeof(dma64dd_t)));
+ flush_dcache_range((unsigned long)dma->rx_desc_aligned,
+ (unsigned long)dma->rx_desc_aligned +
+ DESCP_SIZE_ALIGNED * RX_BUF_NUM);
flush_dcache_range((unsigned long)bufp,
- (unsigned long)(bufp + RX_BUF_SIZE));
+ (unsigned long)bufp + RX_BUF_SIZE_ALIGNED);
buflen = (descp->ctrl2 & D64_CTRL2_BC_MASK);
@@ -457,12 +463,13 @@ int gmac_check_rx_done(struct eth_dma *dma, uint8_t *buf)
memcpy(buf, datap, rcvlen);
/* update descriptor that is being added back on ring */
- descp->ctrl2 = RX_BUF_SIZE;
+ descp->ctrl2 = RX_BUF_SIZE_ALIGNED;
descp->addrlow = (uint32_t)bufp;
descp->addrhigh = 0;
/* flush descriptor */
- flush_dcache_range((unsigned long)descp,
- (unsigned long)(descp + sizeof(dma64dd_t)));
+ flush_dcache_range((unsigned long)dma->rx_desc_aligned,
+ (unsigned long)dma->rx_desc_aligned +
+ DESCP_SIZE_ALIGNED * RX_BUF_NUM);
/* set the lastdscr for the rx ring */
writel(((uint32_t)descp) & D64_XP_LD_MASK, GMAC0_DMA_RX_PTR_ADDR);
@@ -573,7 +580,7 @@ static int gmac_enable_dma(struct eth_dma *dma, int dir)
* set the lastdscr for the rx ring
*/
writel(((uint32_t)(dma->rx_desc_aligned) +
- (RX_BUF_NUM - 1) * RX_BUF_SIZE) &
+ (RX_BUF_NUM - 1) * RX_BUF_SIZE_ALIGNED) &
D64_XP_LD_MASK, GMAC0_DMA_RX_PTR_ADDR);
}
@@ -893,54 +900,52 @@ int gmac_add(struct eth_device *dev)
void *tmp;
/*
- * Desc has to be 16-byte aligned ?
- * If it is 8-byte aligned by malloc, fail Tx
+ * Desc has to be 16-byte aligned. But for dcache flush it must be
+ * aligned to ARCH_DMA_MINALIGN.
*/
- tmp = malloc(sizeof(dma64dd_t) * TX_BUF_NUM + 8);
+ tmp = memalign(ARCH_DMA_MINALIGN, DESCP_SIZE_ALIGNED * TX_BUF_NUM);
if (tmp == NULL) {
printf("%s: Failed to allocate TX desc Buffer\n", __func__);
return -1;
}
- dma->tx_desc = (void *)tmp;
- dma->tx_desc_aligned = (void *)(((uint32_t)tmp) & (~0xf));
+ dma->tx_desc_aligned = (void *)tmp;
debug("TX Descriptor Buffer: %p; length: 0x%x\n",
- dma->tx_desc_aligned, sizeof(dma64dd_t) * TX_BUF_NUM);
+ dma->tx_desc_aligned, DESCP_SIZE_ALIGNED * TX_BUF_NUM);
- tmp = malloc(TX_BUF_SIZE * TX_BUF_NUM);
+ tmp = memalign(ARCH_DMA_MINALIGN, TX_BUF_SIZE_ALIGNED * TX_BUF_NUM);
if (tmp == NULL) {
printf("%s: Failed to allocate TX Data Buffer\n", __func__);
- free(dma->tx_desc);
+ free(dma->tx_desc_aligned);
return -1;
}
dma->tx_buf = (uint8_t *)tmp;
debug("TX Data Buffer: %p; length: 0x%x\n",
- dma->tx_buf, TX_BUF_SIZE * TX_BUF_NUM);
+ dma->tx_buf, TX_BUF_SIZE_ALIGNED * TX_BUF_NUM);
- /* Desc has to be 16-byte aligned ? */
- tmp = malloc(sizeof(dma64dd_t) * RX_BUF_NUM + 8);
+ /* Desc has to be 16-byte aligned */
+ tmp = memalign(ARCH_DMA_MINALIGN, DESCP_SIZE_ALIGNED * RX_BUF_NUM);
if (tmp == NULL) {
printf("%s: Failed to allocate RX Descriptor\n", __func__);
- free(dma->tx_desc);
+ free(dma->tx_desc_aligned);
free(dma->tx_buf);
return -1;
}
- dma->rx_desc = tmp;
- dma->rx_desc_aligned = (void *)(((uint32_t)tmp) & (~0xf));
+ dma->rx_desc_aligned = (void *)tmp;
debug("RX Descriptor Buffer: %p, length: 0x%x\n",
- dma->rx_desc_aligned, sizeof(dma64dd_t) * RX_BUF_NUM);
+ dma->rx_desc_aligned, DESCP_SIZE_ALIGNED * RX_BUF_NUM);
- tmp = malloc(RX_BUF_SIZE * RX_BUF_NUM);
+ tmp = memalign(ARCH_DMA_MINALIGN, RX_BUF_SIZE_ALIGNED * RX_BUF_NUM);
if (tmp == NULL) {
printf("%s: Failed to allocate RX Data Buffer\n", __func__);
- free(dma->tx_desc);
+ free(dma->tx_desc_aligned);
free(dma->tx_buf);
- free(dma->rx_desc);
+ free(dma->rx_desc_aligned);
return -1;
}
- dma->rx_buf = tmp;
+ dma->rx_buf = (uint8_t *)tmp;
debug("RX Data Buffer: %p; length: 0x%x\n",
- dma->rx_buf, RX_BUF_SIZE * RX_BUF_NUM);
+ dma->rx_buf, RX_BUF_SIZE_ALIGNED * RX_BUF_NUM);
g_dmactrlflags = 0;
diff --git a/drivers/net/bcm-sf2-eth.h b/drivers/net/bcm-sf2-eth.h
index 6104affc51c..c4e2e010034 100644
--- a/drivers/net/bcm-sf2-eth.h
+++ b/drivers/net/bcm-sf2-eth.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Broadcom Corporation.
+ * Copyright 2014-2017 Broadcom.
*
* SPDX-License-Identifier: GPL-2.0+
*/
@@ -30,8 +30,6 @@ enum {
struct eth_dma {
void *tx_desc_aligned;
void *rx_desc_aligned;
- void *tx_desc;
- void *rx_desc;
uint8_t *tx_buf;
uint8_t *rx_buf;
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 1d514e92d3b..e562a8ac1a7 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -90,4 +90,14 @@ config PHY_VITESSE
config PHY_XILINX
bool "Xilinx Ethernet PHYs support"
+config PHY_FIXED
+ bool "Fixed-Link PHY"
+ depends on DM_ETH
+ help
+ Fixed PHY is used for having a 'fixed-link' to another MAC with a direct
+ connection (MII, RGMII, ...).
+ There is nothing like autoneogation and so
+ on, the link is always up with fixed speed and fixed duplex-setting.
+ More information: doc/device-tree-bindings/net/fixed-link.txt
+
endif #PHYLIB
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index d37297122ad..88c00a5cd35 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -28,3 +28,4 @@ obj-$(CONFIG_PHY_TI) += ti.o
obj-$(CONFIG_PHY_XILINX) += xilinx_phy.o
obj-$(CONFIG_PHY_VITESSE) += vitesse.o
obj-$(CONFIG_PHY_MSCC) += mscc.o
+obj-$(CONFIG_PHY_FIXED) += fixed.o
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
new file mode 100644
index 00000000000..df8235645ef
--- /dev/null
+++ b/drivers/net/phy/fixed.c
@@ -0,0 +1,82 @@
+/*
+ * Fixed-Link phy
+ *
+ * Copyright 2017 Bernecker & Rainer Industrieelektronik GmbH
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+#include <common.h>
+#include <phy.h>
+#include <dm.h>
+#include <fdt_support.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int fixedphy_probe(struct phy_device *phydev)
+{
+ struct fixed_link *priv;
+ int ofnode = phydev->addr;
+ u32 val;
+
+ /* check for mandatory properties within fixed-link node */
+ val = fdt_getprop_u32_default_node(gd->fdt_blob,
+ ofnode, 0, "speed", 0);
+ if (val != SPEED_10 && val != SPEED_100 && val != SPEED_1000) {
+ printf("ERROR: no/invalid speed given in fixed-link node!");
+ return -EINVAL;
+ }
+
+ priv = malloc(sizeof(*priv));
+ if (!priv)
+ return -ENOMEM;
+ memset(priv, 0, sizeof(*priv));
+
+ phydev->priv = priv;
+ phydev->addr = 0;
+
+ priv->link_speed = val;
+ priv->duplex = fdtdec_get_bool(gd->fdt_blob, ofnode, "full-duplex");
+ priv->pause = fdtdec_get_bool(gd->fdt_blob, ofnode, "pause");
+ priv->asym_pause = fdtdec_get_bool(gd->fdt_blob, ofnode, "asym-pause");
+
+ /* fixed-link phy must not be reset by core phy code */
+ phydev->flags |= PHY_FLAG_BROKEN_RESET;
+
+ return 0;
+}
+
+int fixedphy_startup(struct phy_device *phydev)
+{
+ struct fixed_link *priv = phydev->priv;
+
+ phydev->asym_pause = priv->asym_pause;
+ phydev->pause = priv->pause;
+ phydev->duplex = priv->duplex;
+ phydev->speed = priv->link_speed;
+ phydev->link = 1;
+
+ return 0;
+}
+
+int fixedphy_shutdown(struct phy_device *phydev)
+{
+ return 0;
+}
+
+static struct phy_driver fixedphy_driver = {
+ .uid = PHY_FIXED_ID,
+ .mask = 0xffffffff,
+ .name = "Fixed PHY",
+ .features = PHY_GBIT_FEATURES | SUPPORTED_MII,
+ .probe = fixedphy_probe,
+ .startup = fixedphy_startup,
+ .shutdown = fixedphy_shutdown,
+};
+
+int phy_fixed_init(void)
+{
+ phy_register(&fixedphy_driver);
+ return 0;
+}
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 8db65749b11..8bacd991ad5 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -515,7 +515,9 @@ int phy_init(void)
#ifdef CONFIG_PHY_MSCC
phy_mscc_init();
#endif
-
+#ifdef CONFIG_PHY_FIXED
+ phy_fixed_init();
+#endif
return 0;
}
@@ -854,9 +856,24 @@ struct phy_device *phy_connect(struct mii_dev *bus, int addr,
struct eth_device *dev, phy_interface_t interface)
#endif
{
- struct phy_device *phydev;
+ struct phy_device *phydev = NULL;
+#ifdef CONFIG_PHY_FIXED
+ int sn;
+ const char *name;
+ sn = fdt_first_subnode(gd->fdt_blob, dev->of_offset);
+ while (sn > 0) {
+ name = fdt_get_name(gd->fdt_blob, sn, NULL);
+ if (name != NULL && strcmp(name, "fixed-link") == 0) {
+ phydev = phy_device_create(bus,
+ sn, PHY_FIXED_ID, interface);
+ break;
+ }
+ sn = fdt_next_subnode(gd->fdt_blob, sn);
+ }
+#endif
+ if (phydev == NULL)
+ phydev = phy_find_by_mask(bus, 1 << addr, interface);
- phydev = phy_find_by_mask(bus, 1 << addr, interface);
if (phydev)
phy_connect_dev(phydev, dev);
else
diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c
index 11cd0ea0688..99339db4bf5 100644
--- a/drivers/net/sunxi_emac.c
+++ b/drivers/net/sunxi_emac.c
@@ -327,6 +327,20 @@ static void emac_reset(struct emac_eth_dev *priv)
udelay(200);
}
+static int _sunxi_write_hwaddr(struct emac_eth_dev *priv, u8 *enetaddr)
+{
+ struct emac_regs *regs = priv->regs;
+ u32 enetaddr_lo, enetaddr_hi;
+
+ enetaddr_lo = enetaddr[2] | (enetaddr[1] << 8) | (enetaddr[0] << 16);
+ enetaddr_hi = enetaddr[5] | (enetaddr[4] << 8) | (enetaddr[3] << 16);
+
+ writel(enetaddr_hi, &regs->mac_a1);
+ writel(enetaddr_lo, &regs->mac_a0);
+
+ return 0;
+}
+
static int _sunxi_emac_eth_init(struct emac_eth_dev *priv, u8 *enetaddr)
{
struct emac_regs *regs = priv->regs;
@@ -350,10 +364,7 @@ static int _sunxi_emac_eth_init(struct emac_eth_dev *priv, u8 *enetaddr)
/* Set up EMAC */
emac_setup(priv);
- writel(enetaddr[0] << 16 | enetaddr[1] << 8 | enetaddr[2],
- &regs->mac_a1);
- writel(enetaddr[3] << 16 | enetaddr[4] << 8 | enetaddr[5],
- &regs->mac_a0);
+ _sunxi_write_hwaddr(priv, enetaddr);
mdelay(1);
diff --git a/include/phy.h b/include/phy.h
index 5477496e0e4..f5fdc04b6ed 100644
--- a/include/phy.h
+++ b/include/phy.h
@@ -15,6 +15,8 @@
#include <linux/ethtool.h>
#include <linux/mdio.h>
+#define PHY_FIXED_ID 0xa5a55a5a
+
#define PHY_MAX_ADDR 32
#define PHY_FLAG_BROKEN_RESET (1 << 0) /* soft reset not supported */
@@ -267,6 +269,7 @@ int phy_ti_init(void);
int phy_vitesse_init(void);
int phy_xilinx_init(void);
int phy_mscc_init(void);
+int phy_fixed_init(void);
int board_phy_config(struct phy_device *phydev);
int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id);
diff --git a/net/link_local.c b/net/link_local.c
index 27851b6b813..dfd240dfbcf 100644
--- a/net/link_local.c
+++ b/net/link_local.c
@@ -111,7 +111,7 @@ void link_local_start(void)
net_set_state(NETLOOP_FAIL);
return;
}
- net_netmask.s_addr = IN_CLASSB_NET;
+ net_netmask.s_addr = htonl(IN_CLASSB_NET);
seed = seed_mac();
if (ip.s_addr == 0)