diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/sata_sil.c | 11 | ||||
-rw-r--r-- | drivers/ata/sata_sil.h | 6 | ||||
-rw-r--r-- | drivers/clk/owl/clk_owl.c | 9 | ||||
-rw-r--r-- | drivers/clk/owl/clk_owl.h | 2 | ||||
-rw-r--r-- | drivers/core/dump.c | 55 | ||||
-rw-r--r-- | drivers/gpio/Kconfig | 20 | ||||
-rw-r--r-- | drivers/gpio/gpio-uclass.c | 46 | ||||
-rw-r--r-- | drivers/net/Kconfig | 7 | ||||
-rw-r--r-- | drivers/net/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/dwmac_s700.c | 67 | ||||
-rw-r--r-- | drivers/net/phy/Kconfig | 9 | ||||
-rw-r--r-- | drivers/net/phy/realtek.c | 55 | ||||
-rw-r--r-- | drivers/net/smc911x.c | 60 |
13 files changed, 319 insertions, 29 deletions
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index 6896fa8771..d5ba94c172 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -27,7 +27,11 @@ #include "sata_sil.h" +#ifdef CONFIG_DM_PCI +#define virt_to_bus(devno, v) dm_pci_virt_to_mem(devno, (void *) (v)) +#else #define virt_to_bus(devno, v) pci_virt_to_mem(devno, (void *) (v)) +#endif /* just compatible ahci_ops */ struct sil_ops { @@ -608,13 +612,18 @@ static int sil_init_sata(struct udevice *uc_dev, int dev) /* Save the private struct to block device struct */ #if !CONFIG_IS_ENABLED(BLK) sata_dev_desc[dev].priv = (void *)sata; + sata->devno = sata_info.devno; #else priv->sil_sata_desc[dev] = sata; priv->port_num = dev; +#ifdef CONFIG_DM_PCI + sata->devno = uc_dev->parent; +#else + sata->devno = sata_info.devno; +#endif /* CONFIG_DM_PCI */ #endif sata->id = dev; sata->port = port; - sata->devno = sata_info.devno; sprintf(sata->name, "SATA#%d", dev); sil_cmd_soft_reset(sata); tmp = readl(port + PORT_SSTATUS); diff --git a/drivers/ata/sata_sil.h b/drivers/ata/sata_sil.h index ef41e8259a..a300c0c388 100644 --- a/drivers/ata/sata_sil.h +++ b/drivers/ata/sata_sil.h @@ -21,7 +21,11 @@ struct sil_sata { u16 pio; u16 mwdma; u16 udma; - pci_dev_t devno; +#ifdef CONFIG_DM_PCI + struct udevice *devno; +#else + pci_dev_t devno; +#endif int wcache; int flush; int flush_ext; diff --git a/drivers/clk/owl/clk_owl.c b/drivers/clk/owl/clk_owl.c index 9715fce162..1999c87a33 100644 --- a/drivers/clk/owl/clk_owl.c +++ b/drivers/clk/owl/clk_owl.c @@ -87,6 +87,11 @@ int owl_clk_enable(struct clk *clk) /* Enable UART3 interface clock */ setbits_le32(priv->base + CMU_DEVCLKEN1, CMU_DEVCLKEN1_UART3); break; + case CLK_RMII_REF: + case CLK_ETHERNET: + setbits_le32(priv->base + CMU_DEVCLKEN1, CMU_DEVCLKEN1_ETH); + setbits_le32(priv->base + CMU_ETHERNETPLL, 5); + break; default: return -EINVAL; } @@ -112,6 +117,10 @@ int owl_clk_disable(struct clk *clk) /* Disable UART3 interface clock */ clrbits_le32(priv->base + CMU_DEVCLKEN1, CMU_DEVCLKEN1_UART3); break; + case CLK_RMII_REF: + case CLK_ETHERNET: + clrbits_le32(priv->base + CMU_DEVCLKEN1, CMU_DEVCLKEN1_ETH); + break; default: return -EINVAL; } diff --git a/drivers/clk/owl/clk_owl.h b/drivers/clk/owl/clk_owl.h index cf896bdb98..a01f81a6a7 100644 --- a/drivers/clk/owl/clk_owl.h +++ b/drivers/clk/owl/clk_owl.h @@ -62,6 +62,4 @@ struct owl_clk_priv { #define CMU_DEVCLKEN1_UART5 BIT(21) #define CMU_DEVCLKEN1_UART3 BIT(11) -#define CMU_DEVCLKEN1_ETH_S700 BIT(23) - #endif diff --git a/drivers/core/dump.c b/drivers/core/dump.c index cb8a25b9ad..6debaf97a1 100644 --- a/drivers/core/dump.c +++ b/drivers/core/dump.c @@ -97,7 +97,7 @@ void dm_dump_uclass(void) } } -void dm_dump_drivers(void) +void dm_dump_driver_compat(void) { struct driver *d = ll_entry_start(struct driver, driver); const int n_ents = ll_entry_count(struct driver, driver); @@ -120,3 +120,56 @@ void dm_dump_drivers(void) printf("%-20.20s %s\n", "", match->compatible); } } + +void dm_dump_drivers(void) +{ + struct driver *d = ll_entry_start(struct driver, driver); + const int n_ents = ll_entry_count(struct driver, driver); + struct driver *entry; + struct udevice *udev; + struct uclass *uc; + int i; + + puts("Driver uid uclass Devices\n"); + puts("----------------------------------------------------------\n"); + + for (entry = d; entry < d + n_ents; entry++) { + uclass_get(entry->id, &uc); + + printf("%-25.25s %-3.3d %-20.20s ", entry->name, entry->id, + uc ? uc->uc_drv->name : "<no uclass>"); + + if (!uc) { + puts("\n"); + continue; + } + + i = 0; + uclass_foreach_dev(udev, uc) { + if (udev->driver != entry) + continue; + if (i) + printf("%-51.51s", ""); + + printf("%-25.25s\n", udev->name); + i++; + } + if (!i) + puts("<none>\n"); + } +} + +void dm_dump_static_driver_info(void) +{ + struct driver_info *drv = ll_entry_start(struct driver_info, + driver_info); + const int n_ents = ll_entry_count(struct driver_info, driver_info); + struct driver_info *entry; + + puts("Driver Address\n"); + puts("---------------------------------\n"); + for (entry = drv; entry != drv + n_ents; entry++) { + printf("%-25.25s @%08lx\n", entry->name, + (ulong)map_to_sysmem(entry->platdata)); + } +} diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index af608b7b0e..0e8ad9530d 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -46,6 +46,26 @@ config GPIO_HOG is a mechanism providing automatic GPIO request and config- uration as part of the gpio-controller's driver probe function. +config DM_GPIO_LOOKUP_LABEL + bool "Enable searching for gpio labelnames" + depends on DM_GPIO + help + This option enables searching for gpio names in + the defined gpio labels, if the search for the + gpio bank name failed. This makes sense if you use + different gpios on different hardware versions + for the same functionality in board code. + +config SPL_DM_GPIO_LOOKUP_LABEL + bool "Enable searching for gpio labelnames" + depends on DM_GPIO && SPL_DM && SPL_GPIO_SUPPORT + help + This option enables searching for gpio names in + the defined gpio labels, if the search for the + gpio bank name failed. This makes sense if you use + different gpios on different hardware versions + for the same functionality in board code. + config ALTERA_PIO bool "Altera PIO driver" depends on DM_GPIO diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index f016532354..ab17fa8a5d 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -68,6 +68,45 @@ static int gpio_to_device(unsigned int gpio, struct gpio_desc *desc) return ret ? ret : -ENOENT; } +#if CONFIG_IS_ENABLED(DM_GPIO_LOOKUP_LABEL) +/** + * dm_gpio_lookup_label() - look for name in gpio device + * + * search in uc_priv, if there is a gpio with labelname same + * as name. + * + * @name: name which is searched + * @uc_priv: gpio_dev_priv pointer. + * @offset: gpio offset within the device + * @return: 0 if found, -ENOENT if not. + */ +static int dm_gpio_lookup_label(const char *name, + struct gpio_dev_priv *uc_priv, ulong *offset) +{ + int len; + int i; + + *offset = -1; + len = strlen(name); + for (i = 0; i < uc_priv->gpio_count; i++) { + if (!uc_priv->name[i]) + continue; + if (!strncmp(name, uc_priv->name[i], len)) { + *offset = i; + return 0; + } + } + return -ENOENT; +} +#else +static int +dm_gpio_lookup_label(const char *name, struct gpio_dev_priv *uc_priv, + ulong *offset) +{ + return -ENOENT; +} +#endif + int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc) { struct gpio_dev_priv *uc_priv = NULL; @@ -96,6 +135,13 @@ int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc) if (!strict_strtoul(name + len, 10, &offset)) break; } + + /* + * if we did not found a gpio through its bank + * name, we search for a valid gpio label. + */ + if (!dm_gpio_lookup_label(name, uc_priv, &offset)) + break; } if (!dev) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 1566b3bda1..ec3fb49832 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -238,6 +238,13 @@ config ETH_DESIGNWARE_SOCFPGA Altera system manager to correctly interface with the PHY. This code handles those SoC specifics. +config ETH_DESIGNWARE_S700 + bool "Actins S700 glue driver for Synopsys Designware Ethernet MAC" + depends on DM_ETH && ETH_DESIGNWARE + help + This provides glue layer to use Synopsys Designware Ethernet MAC + present on Actions S700 SoC. + config ETHOC bool "OpenCores 10/100 Mbps Ethernet MAC" help diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 383ed1c64f..1ecdc40b8f 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_CS8900) += cs8900.o obj-$(CONFIG_TULIP) += dc2114x.o obj-$(CONFIG_ETH_DESIGNWARE) += designware.o obj-$(CONFIG_ETH_DESIGNWARE_SOCFPGA) += dwmac_socfpga.o +obj-$(CONFIG_ETH_DESIGNWARE_S700) += dwmac_s700.o obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o obj-$(CONFIG_DNET) += dnet.o obj-$(CONFIG_DM_ETH_PHY) += eth-phy-uclass.o diff --git a/drivers/net/dwmac_s700.c b/drivers/net/dwmac_s700.c new file mode 100644 index 0000000000..9d3f3ac5d9 --- /dev/null +++ b/drivers/net/dwmac_s700.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Amit Singh Tomar <amittomer25@gmail.com> + * + * Actions DWMAC specific glue layer + */ + +#include <common.h> +#include <asm/io.h> +#include <dm.h> +#include <clk.h> +#include <phy.h> +#include <regmap.h> +#include <reset.h> +#include <syscon.h> +#include "designware.h" +#include <asm/arch-owl/regs_s700.h> +#include <linux/bitops.h> + +/* pin control for MAC */ +#define RMII_TXD01_MFP_CTL0 (0x0 << 16) +#define RMII_RXD01_MFP_CTL0 (0x0 << 8) +#define RMII_TXEN_TXER_MFP_CTL0 (0x0 << 13) +#define RMII_REF_CLK_MFP_CTL0 (0x0 << 6) +#define CLKO_25M_EN_MFP_CTL3 BIT(30) + +DECLARE_GLOBAL_DATA_PTR; + +static void dwmac_board_setup(void) +{ + clrbits_le32(MFP_CTL0, (RMII_TXD01_MFP_CTL0 | RMII_RXD01_MFP_CTL0 | + RMII_TXEN_TXER_MFP_CTL0 | RMII_REF_CLK_MFP_CTL0)); + + setbits_le32(MFP_CTL3, CLKO_25M_EN_MFP_CTL3); +} + +static int dwmac_s700_probe(struct udevice *dev) +{ + dwmac_board_setup(); + + /* This is undocumented, phy interface select register */ + writel(0x4, 0xe024c0a0); + + return designware_eth_probe(dev); +} + +static int dwmac_s700_ofdata_to_platdata(struct udevice *dev) +{ + return designware_eth_ofdata_to_platdata(dev); +} + +static const struct udevice_id dwmac_s700_ids[] = { + {.compatible = "actions,s700-ethernet"}, + { } +}; + +U_BOOT_DRIVER(dwmac_s700) = { + .name = "dwmac_s700", + .id = UCLASS_ETH, + .of_match = dwmac_s700_ids, + .ofdata_to_platdata = dwmac_s700_ofdata_to_platdata, + .probe = dwmac_s700_probe, + .ops = &designware_eth_ops, + .priv_auto_alloc_size = sizeof(struct dw_eth_dev), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index b0bd762ac3..4e1a93be22 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -235,6 +235,15 @@ config RTL8211F_PHY_FORCE_EEE_RXC_ON Default n, which means that the PHY state is not changed. To work around the issues, change this setting to y. +config RTL8201F_PHY_S700_RMII_TIMINGS + bool "Ethernet PHY RTL8201F: adjust RMII Tx Interface timings" + depends on PHY_REALTEK + help + This provides an option to configure specific timing requirements (needed + for proper PHY operations) for the PHY module present on ACTION SEMI S700 + based cubieboard7. Exact timing requiremnets seems to be SoC specific + (and it's undocumented) that comes from vendor code itself. + config PHY_SMSC bool "Microchip(SMSC) Ethernet PHYs support" diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index b4612c1cfd..b1b1fa5080 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -14,6 +14,7 @@ #define PHY_RTL8211x_FORCE_MASTER BIT(1) #define PHY_RTL8211E_PINE64_GIGABIT_FIX BIT(2) #define PHY_RTL8211F_FORCE_EEE_RXC_ON BIT(3) +#define PHY_RTL8201F_S700_RMII_TIMINGS BIT(4) #define PHY_AUTONEGOTIATE_TIMEOUT 5000 @@ -60,6 +61,15 @@ #define MIIM_RTL8211F_RX_DELAY 0x8 #define MIIM_RTL8211F_LCR 0x10 +#define RTL8201F_RMSR 0x10 + +#define RMSR_RX_TIMING_SHIFT BIT(2) +#define RMSR_RX_TIMING_MASK GENMASK(7, 4) +#define RMSR_RX_TIMING_VAL 0x4 +#define RMSR_TX_TIMING_SHIFT BIT(3) +#define RMSR_TX_TIMING_MASK GENMASK(11, 8) +#define RMSR_TX_TIMING_VAL 0x5 + static int rtl8211f_phy_extread(struct phy_device *phydev, int addr, int devaddr, int regnum) { @@ -114,6 +124,15 @@ static int rtl8211f_probe(struct phy_device *phydev) return 0; } +static int rtl8210f_probe(struct phy_device *phydev) +{ +#ifdef CONFIG_RTL8201F_PHY_S700_RMII_TIMINGS + phydev->flags |= PHY_RTL8201F_S700_RMII_TIMINGS; +#endif + + return 0; +} + /* RealTek RTL8211x */ static int rtl8211x_config(struct phy_device *phydev) { @@ -159,6 +178,29 @@ static int rtl8211x_config(struct phy_device *phydev) return 0; } +/* RealTek RTL8201F */ +static int rtl8201f_config(struct phy_device *phydev) +{ + unsigned int reg; + + if (phydev->flags & PHY_RTL8201F_S700_RMII_TIMINGS) { + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, + 7); + reg = phy_read(phydev, MDIO_DEVAD_NONE, RTL8201F_RMSR); + reg &= ~(RMSR_RX_TIMING_MASK | RMSR_TX_TIMING_MASK); + /* Set the needed Rx/Tx Timings for proper PHY operation */ + reg |= (RMSR_RX_TIMING_VAL << RMSR_RX_TIMING_SHIFT) + | (RMSR_TX_TIMING_VAL << RMSR_TX_TIMING_SHIFT); + phy_write(phydev, MDIO_DEVAD_NONE, RTL8201F_RMSR, reg); + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, + 0); + } + + genphy_config_aneg(phydev); + + return 0; +} + static int rtl8211f_config(struct phy_device *phydev) { u16 reg; @@ -398,12 +440,25 @@ static struct phy_driver RTL8211F_driver = { .writeext = &rtl8211f_phy_extwrite, }; +/* Support for RTL8201F PHY */ +static struct phy_driver RTL8201F_driver = { + .name = "RealTek RTL8201F 10/100Mbps Ethernet", + .uid = 0x1cc816, + .mask = 0xffffff, + .features = PHY_BASIC_FEATURES, + .probe = &rtl8210f_probe, + .config = &rtl8201f_config, + .startup = &rtl8211e_startup, + .shutdown = &genphy_shutdown, +}; + int phy_realtek_init(void) { phy_register(&RTL8211B_driver); phy_register(&RTL8211E_driver); phy_register(&RTL8211F_driver); phy_register(&RTL8211DN_driver); + phy_register(&RTL8201F_driver); return 0; } diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 9d2790e561..053ff9f4ff 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -187,6 +187,26 @@ static void smc911x_handle_mac_address(struct smc911x_priv *priv) printf(DRIVERNAME ": MAC %pM\n", m); } +static bool smc911x_read_mac_address(struct smc911x_priv *priv) +{ + u32 addrh, addrl; + + /* address is obtained from optional eeprom */ + addrh = smc911x_get_mac_csr(priv, ADDRH); + addrl = smc911x_get_mac_csr(priv, ADDRL); + if (addrl == 0xffffffff && addrh == 0x0000ffff) + return false; + + priv->enetaddr[0] = addrl; + priv->enetaddr[1] = addrl >> 8; + priv->enetaddr[2] = addrl >> 16; + priv->enetaddr[3] = addrl >> 24; + priv->enetaddr[4] = addrh; + priv->enetaddr[5] = addrh >> 8; + + return true; +} + static int smc911x_eth_phy_read(struct smc911x_priv *priv, u8 phy, u8 reg, u16 *val) { @@ -471,7 +491,6 @@ static int smc911x_recv(struct eth_device *dev) int smc911x_initialize(u8 dev_num, int base_addr) { - unsigned long addrl, addrh; struct smc911x_priv *priv; int ret; @@ -489,18 +508,8 @@ int smc911x_initialize(u8 dev_num, int base_addr) goto err_detect; } - addrh = smc911x_get_mac_csr(priv, ADDRH); - addrl = smc911x_get_mac_csr(priv, ADDRL); - if (!(addrl == 0xffffffff && addrh == 0x0000ffff)) { - /* address is obtained from optional eeprom */ - priv->enetaddr[0] = addrl; - priv->enetaddr[1] = addrl >> 8; - priv->enetaddr[2] = addrl >> 16; - priv->enetaddr[3] = addrl >> 24; - priv->enetaddr[4] = addrh; - priv->enetaddr[5] = addrh >> 8; + if (smc911x_read_mac_address(priv)) memcpy(priv->dev.enetaddr, priv->enetaddr, 6); - } priv->dev.init = smc911x_init; priv->dev.halt = smc911x_halt; @@ -565,6 +574,19 @@ static int smc911x_recv(struct udevice *dev, int flags, uchar **packetp) return ret ? ret : -EAGAIN; } +static int smc911x_read_rom_hwaddr(struct udevice *dev) +{ + struct smc911x_priv *priv = dev_get_priv(dev); + struct eth_pdata *pdata = dev_get_platdata(dev); + + if (!smc911x_read_mac_address(priv)) + return -ENODEV; + + memcpy(pdata->enetaddr, priv->enetaddr, sizeof(pdata->enetaddr)); + + return 0; +} + static int smc911x_bind(struct udevice *dev) { return device_set_name(dev, dev->name); @@ -573,7 +595,6 @@ static int smc911x_bind(struct udevice *dev) static int smc911x_probe(struct udevice *dev) { struct smc911x_priv *priv = dev_get_priv(dev); - unsigned long addrh, addrl; int ret; /* Try to detect chip. Will fail if not present. */ @@ -581,17 +602,7 @@ static int smc911x_probe(struct udevice *dev) if (ret) return ret; - addrh = smc911x_get_mac_csr(priv, ADDRH); - addrl = smc911x_get_mac_csr(priv, ADDRL); - if (!(addrl == 0xffffffff && addrh == 0x0000ffff)) { - /* address is obtained from optional eeprom */ - priv->enetaddr[0] = addrl; - priv->enetaddr[1] = addrl >> 8; - priv->enetaddr[2] = addrl >> 16; - priv->enetaddr[3] = addrl >> 24; - priv->enetaddr[4] = addrh; - priv->enetaddr[5] = addrh >> 8; - } + smc911x_read_rom_hwaddr(dev); return 0; } @@ -612,6 +623,7 @@ static const struct eth_ops smc911x_ops = { .send = smc911x_send, .recv = smc911x_recv, .stop = smc911x_stop, + .read_rom_hwaddr = smc911x_read_rom_hwaddr, }; static const struct udevice_id smc911x_ids[] = { |