diff options
-rw-r--r-- | arch/arm/include/asm/arch-lpc32xx/i2c.h | 37 | ||||
-rw-r--r-- | board/ge/bx50v3/bx50v3.c | 6 | ||||
-rw-r--r-- | cmd/i2c.c | 10 | ||||
-rw-r--r-- | common/fdt_support.c | 10 | ||||
-rw-r--r-- | configs/A10-OLinuXino-Lime_defconfig | 4 | ||||
-rw-r--r-- | configs/A20-OLinuXino-Lime2_defconfig | 4 | ||||
-rw-r--r-- | configs/A20-OLinuXino-Lime_defconfig | 4 | ||||
-rw-r--r-- | configs/A20-OLinuXino_MICRO_defconfig | 4 | ||||
-rw-r--r-- | doc/device-tree-bindings/net/fixed-link.txt | 30 | ||||
-rw-r--r-- | drivers/i2c/Kconfig | 14 | ||||
-rw-r--r-- | drivers/i2c/lpc32xx_i2c.c | 236 | ||||
-rw-r--r-- | drivers/i2c/omap24xx_i2c.c | 66 | ||||
-rw-r--r-- | drivers/i2c/omap24xx_i2c.h | 10 | ||||
-rw-r--r-- | drivers/net/bcm-sf2-eth-gmac.c | 113 | ||||
-rw-r--r-- | drivers/net/bcm-sf2-eth.h | 4 | ||||
-rw-r--r-- | drivers/net/phy/Kconfig | 10 | ||||
-rw-r--r-- | drivers/net/phy/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/phy/fixed.c | 82 | ||||
-rw-r--r-- | drivers/net/phy/phy.c | 23 | ||||
-rw-r--r-- | drivers/net/sunxi_emac.c | 19 | ||||
-rw-r--r-- | include/phy.h | 3 | ||||
-rw-r--r-- | net/link_local.c | 2 |
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, ®s->mac_a1); + writel(enetaddr_lo, ®s->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], - ®s->mac_a1); - writel(enetaddr[3] << 16 | enetaddr[4] << 8 | enetaddr[5], - ®s->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) |