diff options
54 files changed, 1456 insertions, 557 deletions
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile index b703c3c..1cc4a96 100644 --- a/arch/arm/mach-rockchip/Makefile +++ b/arch/arm/mach-rockchip/Makefile @@ -11,7 +11,6 @@ else obj-$(CONFIG_ROCKCHIP_RK3288) += board.o endif obj-y += rk_timer.o -obj-y += rk_early_print.o obj-$(CONFIG_$(SPL_)ROCKCHIP_COMMON) += common.o obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288/ obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036/ diff --git a/arch/arm/mach-rockchip/rk3036-board-spl.c b/arch/arm/mach-rockchip/rk3036-board-spl.c index 3a1491c..8015481 100644 --- a/arch/arm/mach-rockchip/rk3036-board-spl.c +++ b/arch/arm/mach-rockchip/rk3036-board-spl.c @@ -5,6 +5,7 @@ */ #include <common.h> +#include <debug_uart.h> #include <asm/io.h> #include <asm/arch/grf_rk3036.h> #include <asm/arch/hardware.h> @@ -34,7 +35,7 @@ void board_init_f(ulong dummy) GPIO1C2_MASK << GPIO1C2_SHIFT, GPIO1C3_UART2_SOUT << GPIO1C3_SHIFT | GPIO1C2_UART2_SIN << GPIO1C2_SHIFT); - rk_uart_init((void *)DEBUG_UART_BASE); + debug_uart_init(); #endif rockchip_timer_init(); sdram_init(); @@ -53,3 +54,9 @@ void board_init_r(gd_t *id, ulong dest_addr) while (1) ; } + +void hang(void) +{ + while (1) + ; +} diff --git a/arch/arm/mach-rockchip/rk_early_print.c b/arch/arm/mach-rockchip/rk_early_print.c deleted file mode 100644 index a1c14b0..0000000 --- a/arch/arm/mach-rockchip/rk_early_print.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * (C) Copyright 2015 Rockchip Electronics Co., Ltd - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <asm/io.h> -#include <asm/arch/uart.h> -#include <common.h> - -static struct rk_uart *uart_ptr; - -static void uart_wrtie_byte(char byte) -{ - writel(byte, &uart_ptr->rbr); - while (!(readl(&uart_ptr->lsr) & 0x40)) - ; -} - -void print(char *s) -{ - while (*s) { - if (*s == '\n') - uart_wrtie_byte('\r'); - uart_wrtie_byte(*s); - s++; - } -} - -void print_hex(unsigned int n) -{ - int i; - int temp; - - uart_wrtie_byte('0'); - uart_wrtie_byte('x'); - - for (i = 8; i > 0; i--) { - temp = (n >> (i - 1) * 4) & 0x0f; - if (temp < 10) - uart_wrtie_byte((char)(temp + '0')); - else - uart_wrtie_byte((char)(temp - 10 + 'a')); - } - uart_wrtie_byte('\n'); - uart_wrtie_byte('\r'); -} - -/* - * TODO: since rk3036 only 4K sram to use in SPL, for saving space, - * we implement uart driver this way, we should convert this to use - * ns16550 driver in future, which support DEBUG_UART in the standard way - */ -void rk_uart_init(void *base) -{ - uart_ptr = (struct rk_uart *)base; - writel(0x83, &uart_ptr->lcr); - writel(0x0d, &uart_ptr->rbr); - writel(0x03, &uart_ptr->lcr); - - /* fifo enable, sfe is shadow register of FCR[0] */ - writel(0x01, &uart_ptr->sfe); -} diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index fbfb204..48a387c 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -3,6 +3,7 @@ if TEGRA config TEGRA_COMMON bool "Tegra common options" select DM + select DM_ETH select DM_GPIO select DM_I2C select DM_KEYBOARD diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c index b76a731..528865f 100644 --- a/arch/sandbox/cpu/eth-raw-os.c +++ b/arch/sandbox/cpu/eth-raw-os.c @@ -76,6 +76,10 @@ static int _raw_packet_start(const char *ifname, unsigned char *ethmac, printf("Failed to set promiscuous mode: %d %s\n" "Falling back to the old \"flags\" way...\n", errno, strerror(errno)); + if (strlen(ifname) >= IFNAMSIZ) { + printf("Interface name %s is too long.\n", ifname); + return -EINVAL; + } strncpy(ifr.ifr_name, ifname, IFNAMSIZ); if (ioctl(priv->sd, SIOCGIFFLAGS, &ifr) < 0) { printf("Failed to read flags: %d %s\n", errno, diff --git a/arch/x86/cpu/baytrail/valleyview.c b/arch/x86/cpu/baytrail/valleyview.c index 9b30451..7299f2c 100644 --- a/arch/x86/cpu/baytrail/valleyview.c +++ b/arch/x86/cpu/baytrail/valleyview.c @@ -14,12 +14,12 @@ static struct pci_device_id mmc_supported[] = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VALLEYVIEW_SDIO }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VALLEYVIEW_SDCARD }, + {}, }; int cpu_mmc_init(bd_t *bis) { - return pci_mmc_init("ValleyView SDHCI", mmc_supported, - ARRAY_SIZE(mmc_supported)); + return pci_mmc_init("ValleyView SDHCI", mmc_supported); } #ifndef CONFIG_EFI_APP diff --git a/arch/x86/cpu/ivybridge/bd82x6x.c b/arch/x86/cpu/ivybridge/bd82x6x.c index 3e7a907..434dfd6 100644 --- a/arch/x86/cpu/ivybridge/bd82x6x.c +++ b/arch/x86/cpu/ivybridge/bd82x6x.c @@ -86,8 +86,10 @@ static int bd82x6x_probe(struct udevice *dev) debug("%s: Cannot find GMA node\n", __func__); return -EINVAL; } - ret = gma_func0_init(PCH_VIDEO_DEV, pci_bus_to_hose(0), blob, - gma_node); + ret = dm_pci_bus_find_bdf(PCH_VIDEO_DEV, &dev); + if (ret) + return ret; + ret = gma_func0_init(dev, blob, gma_node); if (ret) return ret; diff --git a/arch/x86/cpu/ivybridge/gma.c b/arch/x86/cpu/ivybridge/gma.c index 89d4a5e..85a09c6 100644 --- a/arch/x86/cpu/ivybridge/gma.c +++ b/arch/x86/cpu/ivybridge/gma.c @@ -728,8 +728,7 @@ static int int15_handler(void) return res; } -int gma_func0_init(pci_dev_t dev, struct pci_controller *hose, - const void *blob, int node) +int gma_func0_init(struct udevice *dev, const void *blob, int node) { #ifdef CONFIG_VIDEO ulong start; @@ -740,16 +739,16 @@ int gma_func0_init(pci_dev_t dev, struct pci_controller *hose, int ret; /* IGD needs to be Bus Master */ - reg32 = x86_pci_read_config32(dev, PCI_COMMAND); + dm_pci_read_config32(dev, PCI_COMMAND, ®32); reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO; - x86_pci_write_config32(dev, PCI_COMMAND, reg32); + dm_pci_write_config32(dev, PCI_COMMAND, reg32); /* Use write-combining for the graphics memory, 256MB */ - base = pci_read_bar32(hose, dev, 2); + base = dm_pci_read_bar32(dev, 2); mtrr_add_request(MTRR_TYPE_WRCOMB, base, 256 << 20); mtrr_commit(true); - gtt_bar = (void *)pci_read_bar32(pci_bus_to_hose(0), dev, 0); + gtt_bar = (void *)dm_pci_read_bar32(dev, 0); debug("GT bar %p\n", gtt_bar); ret = gma_pm_init_pre_vbios(gtt_bar); if (ret) @@ -757,8 +756,8 @@ int gma_func0_init(pci_dev_t dev, struct pci_controller *hose, #ifdef CONFIG_VIDEO start = get_timer(0); - ret = pci_run_vga_bios(dev, int15_handler, PCI_ROM_USE_NATIVE | - PCI_ROM_ALLOW_FALLBACK); + ret = dm_pci_run_vga_bios(dev, int15_handler, + PCI_ROM_USE_NATIVE | PCI_ROM_ALLOW_FALLBACK); debug("BIOS ran in %lums\n", get_timer(start)); #endif /* Post VBIOS init */ diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c index c2bf497..37ce394 100644 --- a/arch/x86/cpu/quark/quark.c +++ b/arch/x86/cpu/quark/quark.c @@ -19,6 +19,7 @@ static struct pci_device_id mmc_supported[] = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_SDIO }, + {}, }; /* @@ -337,8 +338,7 @@ int arch_early_init_r(void) int cpu_mmc_init(bd_t *bis) { - return pci_mmc_init("Quark SDHCI", mmc_supported, - ARRAY_SIZE(mmc_supported)); + return pci_mmc_init("Quark SDHCI", mmc_supported); } void cpu_irq_init(void) diff --git a/arch/x86/cpu/queensbay/topcliff.c b/arch/x86/cpu/queensbay/topcliff.c index 9faf1b9..b76dd7d 100644 --- a/arch/x86/cpu/queensbay/topcliff.c +++ b/arch/x86/cpu/queensbay/topcliff.c @@ -11,10 +11,10 @@ static struct pci_device_id mmc_supported[] = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_SDIO_0 }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_SDIO_1 }, + {}, }; int cpu_mmc_init(bd_t *bis) { - return pci_mmc_init("Topcliff SDHCI", mmc_supported, - ARRAY_SIZE(mmc_supported)); + return pci_mmc_init("Topcliff SDHCI", mmc_supported); } diff --git a/arch/x86/include/asm/arch-ivybridge/bd82x6x.h b/arch/x86/include/asm/arch-ivybridge/bd82x6x.h index 7786493..fcdf6e2 100644 --- a/arch/x86/include/asm/arch-ivybridge/bd82x6x.h +++ b/arch/x86/include/asm/arch-ivybridge/bd82x6x.h @@ -12,8 +12,7 @@ void bd82x6x_sata_enable(pci_dev_t dev, const void *blob, int node); void bd82x6x_pci_init(pci_dev_t dev); void bd82x6x_usb_ehci_init(pci_dev_t dev); void bd82x6x_usb_xhci_init(pci_dev_t dev); -int gma_func0_init(pci_dev_t dev, struct pci_controller *hose, - const void *blob, int node); +int gma_func0_init(struct udevice *dev, const void *blob, int node); int bd82x6x_init(void); /** diff --git a/arch/x86/lib/bios.c b/arch/x86/lib/bios.c index 1d75cfc..9324bdb 100644 --- a/arch/x86/lib/bios.c +++ b/arch/x86/lib/bios.c @@ -242,9 +242,10 @@ static void vbe_set_graphics(int vesa_mode, struct vbe_mode_info *mode_info) vbe_set_mode(mode_info); } -void bios_run_on_x86(pci_dev_t pcidev, unsigned long addr, int vesa_mode, +void bios_run_on_x86(struct udevice *dev, unsigned long addr, int vesa_mode, struct vbe_mode_info *mode_info) { + pci_dev_t pcidev = dm_pci_get_bdf(dev); u32 num_dev; num_dev = PCI_BUS(pcidev) << 8 | PCI_DEV(pcidev) << 3 | diff --git a/arch/x86/lib/bios_interrupts.c b/arch/x86/lib/bios_interrupts.c index 47d9f59..e8ca6e6 100644 --- a/arch/x86/lib/bios_interrupts.c +++ b/arch/x86/lib/bios_interrupts.c @@ -105,13 +105,15 @@ int int1a_handler(void) unsigned short func = (unsigned short)M.x86.R_EAX; int retval = 1; unsigned short devid, vendorid, devfn; + struct udevice *dev; /* Use short to get rid of gabage in upper half of 32-bit register */ short devindex; unsigned char bus; - pci_dev_t dev; + pci_dev_t bdf; u32 dword; u16 word; u8 byte, reg; + int ret; switch (func) { case 0xb101: /* PCIBIOS Check */ @@ -131,17 +133,20 @@ int int1a_handler(void) devid = M.x86.R_ECX; vendorid = M.x86.R_EDX; devindex = M.x86.R_ESI; - dev = pci_find_device(vendorid, devid, devindex); - if (dev != -1) { + bdf = -1; + ret = dm_pci_find_device(vendorid, devid, devindex, &dev); + if (!ret) { unsigned short busdevfn; + + bdf = dm_pci_get_bdf(dev); M.x86.R_EAX &= 0xffff00ff; /* Clear AH */ M.x86.R_EAX |= PCIBIOS_SUCCESSFUL; /* * busnum is an unsigned char; * devfn is an int, so we mask it off. */ - busdevfn = (PCI_BUS(dev) << 8) | PCI_DEV(dev) << 3 | - PCI_FUNC(dev); + busdevfn = (PCI_BUS(bdf) << 8) | PCI_DEV(bdf) << 3 | + PCI_FUNC(bdf); debug("0x%x: return 0x%x\n", func, busdevfn); M.x86.R_EBX = busdevfn; retval = 1; @@ -160,35 +165,40 @@ int int1a_handler(void) devfn = M.x86.R_EBX & 0xff; bus = M.x86.R_EBX >> 8; reg = M.x86.R_EDI; - dev = PCI_BDF(bus, devfn >> 3, devfn & 7); + bdf = PCI_BDF(bus, devfn >> 3, devfn & 7); + + ret = dm_pci_bus_find_bdf(bdf, &dev); + if (ret) { + debug("%s: Device %x not found\n", __func__, bdf); + break; + } switch (func) { case 0xb108: /* Read Config Byte */ - byte = x86_pci_read_config8(dev, reg); + dm_pci_read_config8(dev, reg, &byte); M.x86.R_ECX = byte; break; case 0xb109: /* Read Config Word */ - word = x86_pci_read_config16(dev, reg); + dm_pci_read_config16(dev, reg, &word); M.x86.R_ECX = word; break; case 0xb10a: /* Read Config Dword */ - dword = x86_pci_read_config32(dev, reg); + dm_pci_read_config32(dev, reg, &dword); M.x86.R_ECX = dword; break; case 0xb10b: /* Write Config Byte */ byte = M.x86.R_ECX; - x86_pci_write_config8(dev, reg, byte); + dm_pci_write_config8(dev, reg, byte); break; case 0xb10c: /* Write Config Word */ word = M.x86.R_ECX; - x86_pci_write_config16(dev, reg, word); + dm_pci_write_config16(dev, reg, word); break; case 0xb10d: /* Write Config Dword */ dword = M.x86.R_ECX; - x86_pci_write_config32(dev, reg, dword); + dm_pci_write_config32(dev, reg, dword); break; } - #ifdef CONFIG_REALMODE_DEBUG debug("0x%x: bus %d devfn 0x%x reg 0x%x val 0x%x\n", func, bus, devfn, reg, M.x86.R_ECX); diff --git a/board/compulab/trimslice/trimslice.c b/board/compulab/trimslice/trimslice.c index c9da80d..723293f 100644 --- a/board/compulab/trimslice/trimslice.c +++ b/board/compulab/trimslice/trimslice.c @@ -13,7 +13,6 @@ #include <asm/arch/pinmux.h> #include <asm/gpio.h> #include <i2c.h> -#include <netdev.h> void pin_mux_usb(void) { @@ -41,10 +40,3 @@ void pin_mux_mmc(void) /* For CD GPIO PP1 */ pinmux_tristate_disable(PMUX_PINGRP_DAP3); } - -#ifdef CONFIG_PCI -int board_eth_init(bd_t *bis) -{ - return pci_eth_init(bis); -} -#endif diff --git a/board/nvidia/cardhu/cardhu.c b/board/nvidia/cardhu/cardhu.c index 1540526..ba15e2e 100644 --- a/board/nvidia/cardhu/cardhu.c +++ b/board/nvidia/cardhu/cardhu.c @@ -13,7 +13,6 @@ #include <asm/gpio.h> #include "pinmux-config-cardhu.h" #include <i2c.h> -#include <netdev.h> #define PMU_I2C_ADDRESS 0x2D #define MAX_I2C_RETRY 3 @@ -129,9 +128,4 @@ int tegra_pcie_board_init(void) return 0; } - -int board_eth_init(bd_t *bis) -{ - return pci_eth_init(bis); -} #endif /* PCI */ diff --git a/board/nvidia/jetson-tk1/jetson-tk1.c b/board/nvidia/jetson-tk1/jetson-tk1.c index 52425a8..6f189aa 100644 --- a/board/nvidia/jetson-tk1/jetson-tk1.c +++ b/board/nvidia/jetson-tk1/jetson-tk1.c @@ -6,7 +6,6 @@ */ #include <common.h> -#include <netdev.h> #include <power/as3722.h> #include <asm/arch/gpio.h> @@ -73,9 +72,4 @@ int tegra_pcie_board_init(void) return 0; } - -int board_eth_init(bd_t *bis) -{ - return pci_eth_init(bis); -} #endif /* PCI */ diff --git a/board/nvidia/p2371-2180/p2371-2180.c b/board/nvidia/p2371-2180/p2371-2180.c index 57f577d8..0f587ea 100644 --- a/board/nvidia/p2371-2180/p2371-2180.c +++ b/board/nvidia/p2371-2180/p2371-2180.c @@ -6,7 +6,6 @@ */ #include <common.h> -#include <netdev.h> #include <i2c.h> #include <asm/arch/gpio.h> #include <asm/arch/pinmux.h> @@ -73,9 +72,4 @@ int tegra_pcie_board_init(void) return 0; } - -int board_eth_init(bd_t *bis) -{ - return pci_eth_init(bis); -} #endif /* PCI */ diff --git a/board/toradex/apalis_t30/apalis_t30.c b/board/toradex/apalis_t30/apalis_t30.c index 879006f..3f56971 100644 --- a/board/toradex/apalis_t30/apalis_t30.c +++ b/board/toradex/apalis_t30/apalis_t30.c @@ -14,7 +14,6 @@ #include <asm/io.h> #include <dm.h> #include <i2c.h> -#include <netdev.h> #include "pinmux-config-apalis_t30.h" @@ -92,9 +91,4 @@ int tegra_pcie_board_init(void) return 0; } - -int board_eth_init(bd_t *bis) -{ - return pci_eth_init(bis); -} #endif /* CONFIG_PCI_TEGRA */ diff --git a/common/cmd_pci.c b/common/cmd_pci.c index 4e0951f..8094d33 100644 --- a/common/cmd_pci.c +++ b/common/cmd_pci.c @@ -606,7 +606,7 @@ static int do_pci(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } #ifdef CONFIG_DM_PCI - ret = pci_bus_find_bdf(bdf, &dev); + ret = dm_pci_bus_find_bdf(bdf, &dev); if (ret) { printf("No such device\n"); return CMD_RET_FAILURE; diff --git a/common/cmd_scsi.c b/common/cmd_scsi.c index 31c4319..8695408 100644 --- a/common/cmd_scsi.c +++ b/common/cmd_scsi.c @@ -184,7 +184,7 @@ int scsi_get_disk_count(void) #if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) void scsi_init(void) { - int busdevfunc; + int busdevfunc = -1; int i; /* * Find a device from the list, this driver will support a single @@ -192,9 +192,21 @@ void scsi_init(void) */ for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) { /* get PCI Device ID */ +#ifdef CONFIG_DM_PCI + struct udevice *dev; + int ret; + + ret = dm_pci_find_device(scsi_device_list[i].vendor, + scsi_device_list[i].device, 0, &dev); + if (!ret) { + busdevfunc = dm_pci_get_bdf(dev); + break; + } +#else busdevfunc = pci_find_device(scsi_device_list[i].vendor, scsi_device_list[i].device, 0); +#endif if (busdevfunc != -1) break; } diff --git a/configs/evb-rk3036_defconfig b/configs/evb-rk3036_defconfig index 2e915ff..c196bd6 100644 --- a/configs/evb-rk3036_defconfig +++ b/configs/evb-rk3036_defconfig @@ -24,3 +24,9 @@ CONFIG_DM_MMC=y CONFIG_USE_PRIVATE_LIBGCC=y CONFIG_CMD_DHRYSTONE=y CONFIG_ERRNO_STR=y +CONFIG_DEBUG_UART=y +CONFIG_DEBUG_UART_NS16550=y +CONFIG_DEBUG_UART_BASE=0x20068000 +CONFIG_DEBUG_UART_CLOCK=24000000 +CONFIG_DEBUG_UART_SHIFT=2 +# CONFIG_SPL_SERIAL_PRESENT is not set diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c index 5efa821..d29642b 100644 --- a/drivers/block/ahci.c +++ b/drivers/block/ahci.c @@ -10,6 +10,7 @@ #include <common.h> #include <command.h> +#include <dm.h> #include <pci.h> #include <asm/processor.h> #include <asm/errno.h> @@ -168,9 +169,14 @@ int ahci_reset(void __iomem *base) static int ahci_host_init(struct ahci_probe_ent *probe_ent) { #ifndef CONFIG_SCSI_AHCI_PLAT +# ifdef CONFIG_DM_PCI + struct udevice *dev = probe_ent->dev; + struct pci_child_platdata *pplat = dev_get_parent_platdata(dev); +# else pci_dev_t pdev = probe_ent->dev; - u16 tmp16; unsigned short vendor; +# endif + u16 tmp16; #endif void __iomem *mmio = probe_ent->mmio_base; u32 tmp, cap_save, cmd; @@ -193,6 +199,14 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) writel_with_flush(0xf, mmio + HOST_PORTS_IMPL); #ifndef CONFIG_SCSI_AHCI_PLAT +# ifdef CONFIG_DM_PCI + if (pplat->vendor == PCI_VENDOR_ID_INTEL) { + u16 tmp16; + + dm_pci_read_config16(dev, 0x92, &tmp16); + dm_pci_write_config16(dev, 0x92, tmp16 | 0xf); + } +# else pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor); if (vendor == PCI_VENDOR_ID_INTEL) { @@ -201,6 +215,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) tmp16 |= 0xf; pci_write_config_word(pdev, 0x92, tmp16); } +# endif #endif probe_ent->cap = readl(mmio + HOST_CAP); probe_ent->port_map = readl(mmio + HOST_PORTS_IMPL); @@ -313,9 +328,15 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) tmp = readl(mmio + HOST_CTL); debug("HOST_CTL 0x%x\n", tmp); #ifndef CONFIG_SCSI_AHCI_PLAT +# ifdef CONFIG_DM_PCI + dm_pci_read_config16(dev, PCI_COMMAND, &tmp16); + tmp |= PCI_COMMAND_MASTER; + dm_pci_write_config16(dev, PCI_COMMAND, tmp16); +# else pci_read_config_word(pdev, PCI_COMMAND, &tmp16); tmp |= PCI_COMMAND_MASTER; pci_write_config_word(pdev, PCI_COMMAND, tmp16); +# endif #endif return 0; } @@ -324,7 +345,11 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent) static void ahci_print_info(struct ahci_probe_ent *probe_ent) { #ifndef CONFIG_SCSI_AHCI_PLAT +# ifdef CONFIG_DM_PCI + struct udevice *dev = probe_ent->dev; +# else pci_dev_t pdev = probe_ent->dev; +# endif u16 cc; #endif void __iomem *mmio = probe_ent->mmio_base; @@ -350,7 +375,11 @@ static void ahci_print_info(struct ahci_probe_ent *probe_ent) #ifdef CONFIG_SCSI_AHCI_PLAT scc_s = "SATA"; #else +# ifdef CONFIG_DM_PCI + dm_pci_read_config16(dev, 0x0a, &cc); +# else pci_read_config_word(pdev, 0x0a, &cc); +# endif if (cc == 0x0101) scc_s = "IDE"; else if (cc == 0x0106) @@ -395,7 +424,11 @@ static void ahci_print_info(struct ahci_probe_ent *probe_ent) } #ifndef CONFIG_SCSI_AHCI_PLAT -static int ahci_init_one(pci_dev_t pdev) +# ifdef CONFIG_DM_PCI +static int ahci_init_one(struct udevice *dev) +# else +static int ahci_init_one(pci_dev_t dev) +# endif { u16 vendor; int rc; @@ -407,7 +440,7 @@ static int ahci_init_one(pci_dev_t pdev) } memset(probe_ent, 0, sizeof(struct ahci_probe_ent)); - probe_ent->dev = pdev; + probe_ent->dev = dev; probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY @@ -417,18 +450,31 @@ static int ahci_init_one(pci_dev_t pdev) probe_ent->pio_mask = 0x1f; probe_ent->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */ - probe_ent->mmio_base = pci_map_bar(pdev, PCI_BASE_ADDRESS_5, +#ifdef CONFIG_DM_PCI + probe_ent->mmio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_5, + PCI_REGION_MEM); + + /* Take from kernel: + * JMicron-specific fixup: + * make sure we're in AHCI mode + */ + dm_pci_read_config16(dev, PCI_VENDOR_ID, &vendor); + if (vendor == 0x197b) + dm_pci_write_config8(dev, 0x41, 0xa1); +#else + probe_ent->mmio_base = pci_map_bar(dev, PCI_BASE_ADDRESS_5, PCI_REGION_MEM); - debug("ahci mmio_base=0x%p\n", probe_ent->mmio_base); /* Take from kernel: * JMicron-specific fixup: * make sure we're in AHCI mode */ - pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor); + pci_read_config_word(dev, PCI_VENDOR_ID, &vendor); if (vendor == 0x197b) - pci_write_config_byte(pdev, 0x41, 0xa1); + pci_write_config_byte(dev, 0x41, 0xa1); +#endif + debug("ahci mmio_base=0x%p\n", probe_ent->mmio_base); /* initialize adapter */ rc = ahci_host_init(probe_ent); if (rc) @@ -915,7 +961,17 @@ void scsi_low_level_init(int busdevfunc) u32 linkmap; #ifndef CONFIG_SCSI_AHCI_PLAT +# ifdef CONFIG_DM_PCI + struct udevice *dev; + int ret; + + ret = dm_pci_bus_find_bdf(busdevfunc, &dev); + if (ret) + return; + ahci_init_one(dev); +# else ahci_init_one(busdevfunc); +# endif #endif linkmap = probe_ent->link_port_map; diff --git a/drivers/core/device.c b/drivers/core/device.c index 758f390..7a02a93 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -597,22 +597,31 @@ fdt_addr_t dev_get_addr(struct udevice *dev) * Use the full-fledged translate function for complex * bus setups. */ - return fdt_translate_address((void *)gd->fdt_blob, + addr = fdt_translate_address((void *)gd->fdt_blob, dev->of_offset, reg); + } else { + /* + * Use the "simple" translate function for less complex + * bus setups. + */ + addr = fdtdec_get_addr_size_auto_parent(gd->fdt_blob, + dev->parent->of_offset, + dev->of_offset, "reg", + 0, NULL); + if (CONFIG_IS_ENABLED(SIMPLE_BUS) && addr != FDT_ADDR_T_NONE) { + if (device_get_uclass_id(dev->parent) == + UCLASS_SIMPLE_BUS) + addr = simple_bus_translate(dev->parent, addr); + } } /* - * Use the "simple" translate function for less complex - * bus setups. + * Some platforms need a special address translation. Those + * platforms (e.g. mvebu in SPL) can configure a translation + * offset in the DM by calling dm_set_translation_offset() that + * will get added to all addresses returned by dev_get_addr(). */ - addr = fdtdec_get_addr_size_auto_parent(gd->fdt_blob, - dev->parent->of_offset, - dev->of_offset, "reg", - 0, NULL); - if (CONFIG_IS_ENABLED(SIMPLE_BUS) && addr != FDT_ADDR_T_NONE) { - if (device_get_uclass_id(dev->parent) == UCLASS_SIMPLE_BUS) - addr = simple_bus_translate(dev->parent, addr); - } + addr += dm_get_translation_offset(); return addr; #else diff --git a/drivers/core/root.c b/drivers/core/root.c index e7b1f24..13c2713 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -23,6 +23,10 @@ DECLARE_GLOBAL_DATA_PTR; +struct root_priv { + fdt_addr_t translation_offset; /* optional translation offset */ +}; + static const struct driver_info root_info = { .name = "root_driver", }; @@ -37,6 +41,22 @@ struct udevice *dm_root(void) return gd->dm_root; } +fdt_addr_t dm_get_translation_offset(void) +{ + struct udevice *root = dm_root(); + struct root_priv *priv = dev_get_priv(root); + + return priv->translation_offset; +} + +void dm_set_translation_offset(fdt_addr_t offs) +{ + struct udevice *root = dm_root(); + struct root_priv *priv = dev_get_priv(root); + + priv->translation_offset = offs; +} + #if defined(CONFIG_NEEDS_MANUAL_RELOC) void fix_drivers(void) { @@ -228,6 +248,7 @@ int dm_init_and_scan(bool pre_reloc_only) U_BOOT_DRIVER(root_driver) = { .name = "root_driver", .id = UCLASS_ROOT, + .priv_auto_alloc_size = sizeof(struct root_priv), }; /* This is the root uclass */ diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c index 37171bf..5fb7151 100644 --- a/drivers/mmc/pci_mmc.c +++ b/drivers/mmc/pci_mmc.c @@ -11,26 +11,25 @@ #include <sdhci.h> #include <asm/pci.h> -int pci_mmc_init(const char *name, struct pci_device_id *mmc_supported, - int num_ids) +int pci_mmc_init(const char *name, struct pci_device_id *mmc_supported) { struct sdhci_host *mmc_host; - pci_dev_t devbusfn; u32 iobase; int ret; int i; - for (i = 0; i < num_ids; i++) { - devbusfn = pci_find_devices(mmc_supported, i); - if (devbusfn == -1) - return -ENODEV; + for (i = 0; ; i++) { + struct udevice *dev; + ret = pci_find_device_id(mmc_supported, i, &dev); + if (ret) + return ret; mmc_host = malloc(sizeof(struct sdhci_host)); if (!mmc_host) return -ENOMEM; mmc_host->name = (char *)name; - pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &iobase); + dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0, &iobase); mmc_host->ioaddr = (void *)iobase; mmc_host->quirks = 0; ret = add_sdhci(mmc_host, 0, 0); diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 04114a1..0fccbc0 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -584,7 +584,7 @@ static int designware_eth_probe(struct udevice *dev) * or via a PCI bridge, fill in platdata before we probe the hardware. */ if (device_is_on_pci_bus(dev)) { - pci_dev_t bdf = pci_get_bdf(dev); + pci_dev_t bdf = dm_pci_get_bdf(dev); dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0, &iobase); iobase &= PCI_BASE_ADDRESS_MEM_MASK; diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 6124bf0..027f2bf 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -5628,8 +5628,8 @@ static int e1000_eth_probe(struct udevice *dev) int ret; hw->name = dev->name; - ret = e1000_init_one(hw, trailing_strtol(dev->name), pci_get_bdf(dev), - plat->enetaddr); + ret = e1000_init_one(hw, trailing_strtol(dev->name), + dm_pci_get_bdf(dev), plat->enetaddr); if (ret < 0) { printf(pr_fmt("failed to initialize card: %d\n"), ret); return ret; diff --git a/drivers/net/pch_gbe.c b/drivers/net/pch_gbe.c index dfc0100..1b4dd56 100644 --- a/drivers/net/pch_gbe.c +++ b/drivers/net/pch_gbe.c @@ -424,7 +424,7 @@ int pch_gbe_probe(struct udevice *dev) pci_dev_t devno; u32 iobase; - devno = pci_get_bdf(dev); + devno = dm_pci_get_bdf(dev); /* * The priv structure contains the descriptors and frame buffers which diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c index 19422c4..9e60adf 100644 --- a/drivers/net/rtl8169.c +++ b/drivers/net/rtl8169.c @@ -513,8 +513,13 @@ static void rtl_flush_buffer(void *buf, size_t size) /************************************************************************** RECV - Receive a frame ***************************************************************************/ -static int rtl_recv_common(pci_dev_t bdf, unsigned long dev_iobase, +#ifdef CONFIG_DM_ETH +static int rtl_recv_common(struct udevice *dev, unsigned long dev_iobase, + uchar **packetp) +#else +static int rtl_recv_common(pci_dev_t dev, unsigned long dev_iobase, uchar **packetp) +#endif { /* return true if there's an ethernet packet ready to read */ /* nic->packet should contain data on return */ @@ -545,9 +550,16 @@ static int rtl_recv_common(pci_dev_t bdf, unsigned long dev_iobase, else tpc->RxDescArray[cur_rx].status = cpu_to_le32(OWNbit + RX_BUF_SIZE); +#ifdef CONFIG_DM_ETH tpc->RxDescArray[cur_rx].buf_addr = cpu_to_le32( - pci_mem_to_phys(bdf, (pci_addr_t)(unsigned long) + dm_pci_mem_to_phys(dev, + (pci_addr_t)(unsigned long) + tpc->RxBufferRing[cur_rx])); +#else + tpc->RxDescArray[cur_rx].buf_addr = cpu_to_le32( + pci_mem_to_phys(dev, (pci_addr_t)(unsigned long) tpc->RxBufferRing[cur_rx])); +#endif rtl_flush_rx_desc(&tpc->RxDescArray[cur_rx]); #ifdef CONFIG_DM_ETH *packetp = rxdata; @@ -576,7 +588,7 @@ int rtl8169_eth_recv(struct udevice *dev, int flags, uchar **packetp) { struct rtl8169_private *priv = dev_get_priv(dev); - return rtl_recv_common(pci_get_bdf(dev), priv->iobase, packetp); + return rtl_recv_common(dev, priv->iobase, packetp); } #else static int rtl_recv(struct eth_device *dev) @@ -590,8 +602,13 @@ static int rtl_recv(struct eth_device *dev) /************************************************************************** SEND - Transmit a frame ***************************************************************************/ -static int rtl_send_common(pci_dev_t bdf, unsigned long dev_iobase, +#ifdef CONFIG_DM_ETH +static int rtl_send_common(struct udevice *dev, unsigned long dev_iobase, void *packet, int length) +#else +static int rtl_send_common(pci_dev_t dev, unsigned long dev_iobase, + void *packet, int length) +#endif { /* send the packet to destination */ @@ -618,8 +635,13 @@ static int rtl_send_common(pci_dev_t bdf, unsigned long dev_iobase, ptxb[len++] = '\0'; tpc->TxDescArray[entry].buf_Haddr = 0; +#ifdef CONFIG_DM_ETH tpc->TxDescArray[entry].buf_addr = cpu_to_le32( - pci_mem_to_phys(bdf, (pci_addr_t)(unsigned long)ptxb)); + dm_pci_mem_to_phys(dev, (pci_addr_t)(unsigned long)ptxb)); +#else + tpc->TxDescArray[entry].buf_addr = cpu_to_le32( + pci_mem_to_phys(dev, (pci_addr_t)(unsigned long)ptxb)); +#endif if (entry != (NUM_TX_DESC - 1)) { tpc->TxDescArray[entry].status = cpu_to_le32((OWNbit | FSbit | LSbit) | @@ -661,7 +683,7 @@ int rtl8169_eth_send(struct udevice *dev, void *packet, int length) { struct rtl8169_private *priv = dev_get_priv(dev); - return rtl_send_common(pci_get_bdf(dev), priv->iobase, packet, length); + return rtl_send_common(dev, priv->iobase, packet, length); } #else @@ -695,7 +717,11 @@ static void rtl8169_set_rx_mode(void) RTL_W32(MAR0 + 4, mc_filter[1]); } -static void rtl8169_hw_start(pci_dev_t bdf) +#ifdef CONFIG_DM_ETH +static void rtl8169_hw_start(struct udevice *dev) +#else +static void rtl8169_hw_start(pci_dev_t dev) +#endif { u32 i; @@ -740,11 +766,21 @@ static void rtl8169_hw_start(pci_dev_t bdf) tpc->cur_rx = 0; - RTL_W32(TxDescStartAddrLow, pci_mem_to_phys(bdf, +#ifdef CONFIG_DM_ETH + RTL_W32(TxDescStartAddrLow, dm_pci_mem_to_phys(dev, (pci_addr_t)(unsigned long)tpc->TxDescArray)); +#else + RTL_W32(TxDescStartAddrLow, pci_mem_to_phys(dev, + (pci_addr_t)(unsigned long)tpc->TxDescArray)); +#endif RTL_W32(TxDescStartAddrHigh, (unsigned long)0); +#ifdef CONFIG_DM_ETH + RTL_W32(RxDescStartAddrLow, dm_pci_mem_to_phys( + dev, (pci_addr_t)(unsigned long)tpc->RxDescArray)); +#else RTL_W32(RxDescStartAddrLow, pci_mem_to_phys( - bdf, (pci_addr_t)(unsigned long)tpc->RxDescArray)); + dev, (pci_addr_t)(unsigned long)tpc->RxDescArray)); +#endif RTL_W32(RxDescStartAddrHigh, (unsigned long)0); /* RTL-8169sc/8110sc or later version */ @@ -766,7 +802,11 @@ static void rtl8169_hw_start(pci_dev_t bdf) #endif } -static void rtl8169_init_ring(pci_dev_t bdf) +#ifdef CONFIG_DM_ETH +static void rtl8169_init_ring(struct udevice *dev) +#else +static void rtl8169_init_ring(pci_dev_t dev) +#endif { int i; @@ -794,8 +834,13 @@ static void rtl8169_init_ring(pci_dev_t bdf) cpu_to_le32(OWNbit + RX_BUF_SIZE); tpc->RxBufferRing[i] = &rxb[i * RX_BUF_SIZE]; +#ifdef CONFIG_DM_ETH + tpc->RxDescArray[i].buf_addr = cpu_to_le32(dm_pci_mem_to_phys( + dev, (pci_addr_t)(unsigned long)tpc->RxBufferRing[i])); +#else tpc->RxDescArray[i].buf_addr = cpu_to_le32(pci_mem_to_phys( - bdf, (pci_addr_t)(unsigned long)tpc->RxBufferRing[i])); + dev, (pci_addr_t)(unsigned long)tpc->RxBufferRing[i])); +#endif rtl_flush_rx_desc(&tpc->RxDescArray[i]); } @@ -804,7 +849,11 @@ static void rtl8169_init_ring(pci_dev_t bdf) #endif } -static void rtl8169_common_start(pci_dev_t bdf, unsigned char *enetaddr) +#ifdef CONFIG_DM_ETH +static void rtl8169_common_start(struct udevice *dev, unsigned char *enetaddr) +#else +static void rtl8169_common_start(pci_dev_t dev, unsigned char *enetaddr) +#endif { int i; @@ -813,8 +862,8 @@ static void rtl8169_common_start(pci_dev_t bdf, unsigned char *enetaddr) printf ("%s\n", __FUNCTION__); #endif - rtl8169_init_ring(bdf); - rtl8169_hw_start(bdf); + rtl8169_init_ring(dev); + rtl8169_hw_start(dev); /* Construct a perfect filter frame with the mac address as first match * and broadcast for all others */ for (i = 0; i < 192; i++) @@ -837,7 +886,7 @@ static int rtl8169_eth_start(struct udevice *dev) { struct eth_pdata *plat = dev_get_platdata(dev); - rtl8169_common_start(pci_get_bdf(dev), plat->enetaddr); + rtl8169_common_start(dev, plat->enetaddr); return 0; } @@ -1130,10 +1179,9 @@ static int rtl8169_eth_probe(struct udevice *dev) region = 1; break; } - pci_read_config32(pci_get_bdf(dev), PCI_BASE_ADDRESS_0 + region * 4, - &iobase); + dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0 + region * 4, &iobase); iobase &= ~0xf; - priv->iobase = (int)pci_mem_to_phys(pci_get_bdf(dev), iobase); + priv->iobase = (int)dm_pci_mem_to_phys(dev, iobase); ret = rtl_init(priv->iobase, dev->name, plat->enetaddr); if (ret < 0) { diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 6b761b4..f8be9bf 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -6,15 +6,16 @@ # ifneq ($(CONFIG_DM_PCI),) -obj-$(CONFIG_PCI) += pci-uclass.o +obj-y += pci_rom.o +obj-$(CONFIG_PCI) += pci-uclass.o pci_auto.o obj-$(CONFIG_DM_PCI_COMPAT) += pci_compat.o obj-$(CONFIG_PCI_SANDBOX) += pci_sandbox.o obj-$(CONFIG_SANDBOX) += pci-emul-uclass.o obj-$(CONFIG_X86) += pci_x86.o else -obj-$(CONFIG_PCI) += pci.o +obj-$(CONFIG_PCI) += pci.o pci_auto_old.o endif -obj-$(CONFIG_PCI) += pci_auto_common.o pci_auto_old.o pci_common.o pci_rom.o +obj-$(CONFIG_PCI) += pci_auto_common.o pci_common.o obj-$(CONFIG_FSL_PCI_INIT) += fsl_pci_init.o obj-$(CONFIG_PCI_INDIRECT_BRIDGE) += pci_indirect.o diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 5fe3072..685df9d 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -11,12 +11,14 @@ #include <fdtdec.h> #include <inttypes.h> #include <pci.h> +#include <asm/io.h> #include <dm/lists.h> #include <dm/root.h> #include <dm/device-internal.h> #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP) #include <asm/fsp/fsp_support.h> #endif +#include "pci_internal.h" DECLARE_GLOBAL_DATA_PTR; @@ -61,7 +63,7 @@ struct udevice *pci_get_controller(struct udevice *dev) return dev; } -pci_dev_t pci_get_bdf(struct udevice *dev) +pci_dev_t dm_pci_get_bdf(struct udevice *dev) { struct pci_child_platdata *pplat = dev_get_parent_platdata(dev); struct udevice *bus = dev->parent; @@ -128,7 +130,7 @@ int pci_bus_find_devfn(struct udevice *bus, pci_dev_t find_devfn, return -ENODEV; } -int pci_bus_find_bdf(pci_dev_t bdf, struct udevice **devp) +int dm_pci_bus_find_bdf(pci_dev_t bdf, struct udevice **devp) { struct udevice *bus; int ret; @@ -194,6 +196,65 @@ int pci_find_device_id(struct pci_device_id *ids, int index, return -ENODEV; } +static int dm_pci_bus_find_device(struct udevice *bus, unsigned int vendor, + unsigned int device, int *indexp, + struct udevice **devp) +{ + struct pci_child_platdata *pplat; + struct udevice *dev; + + for (device_find_first_child(bus, &dev); + dev; + device_find_next_child(&dev)) { + pplat = dev_get_parent_platdata(dev); + if (pplat->vendor == vendor && pplat->device == device) { + if (!(*indexp)--) { + *devp = dev; + return 0; + } + } + } + + return -ENODEV; +} + +int dm_pci_find_device(unsigned int vendor, unsigned int device, int index, + struct udevice **devp) +{ + struct udevice *bus; + + /* Scan all known buses */ + for (uclass_first_device(UCLASS_PCI, &bus); + bus; + uclass_next_device(&bus)) { + if (!dm_pci_bus_find_device(bus, vendor, device, &index, devp)) + return device_probe(*devp); + } + *devp = NULL; + + return -ENODEV; +} + +int dm_pci_find_class(uint find_class, int index, struct udevice **devp) +{ + struct udevice *dev; + + /* Scan all known buses */ + for (pci_find_first_device(&dev); + dev; + pci_find_next_device(&dev)) { + struct pci_child_platdata *pplat = dev_get_parent_platdata(dev); + + if (pplat->class == find_class && !index--) { + *devp = dev; + return device_probe(*devp); + } + } + *devp = NULL; + + return -ENODEV; +} + int pci_bus_write_config(struct udevice *bus, pci_dev_t bdf, int offset, unsigned long value, enum pci_size_t size) { @@ -225,7 +286,8 @@ int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value, for (bus = dev; device_is_on_pci_bus(bus);) bus = bus->parent; - return pci_bus_write_config(bus, pci_get_bdf(dev), offset, value, size); + return pci_bus_write_config(bus, dm_pci_get_bdf(dev), offset, value, + size); } @@ -290,7 +352,7 @@ int dm_pci_read_config(struct udevice *dev, int offset, unsigned long *valuep, for (bus = dev; device_is_on_pci_bus(bus);) bus = bus->parent; - return pci_bus_read_config(bus, pci_get_bdf(dev), offset, valuep, + return pci_bus_read_config(bus, dm_pci_get_bdf(dev), offset, valuep, size); } @@ -403,7 +465,7 @@ int pci_auto_config_devices(struct udevice *bus) int ret; debug("%s: device %s\n", __func__, dev->name); - ret = pciauto_config_device(hose, pci_get_bdf(dev)); + ret = dm_pciauto_config_device(dev); if (ret < 0) return ret; max_bus = ret; @@ -418,26 +480,16 @@ int pci_auto_config_devices(struct udevice *bus) return sub_bus; } -int dm_pci_hose_probe_bus(struct pci_controller *hose, pci_dev_t bdf) +int dm_pci_hose_probe_bus(struct udevice *bus) { - struct udevice *parent, *bus; int sub_bus; int ret; debug("%s\n", __func__); - parent = hose->bus; - - /* Find the bus within the parent */ - ret = pci_bus_find_devfn(parent, PCI_MASK_BUS(bdf), &bus); - if (ret) { - debug("%s: Cannot find device %x on bus %s: %d\n", __func__, - bdf, parent->name, ret); - return ret; - } sub_bus = pci_get_bus_max() + 1; debug("%s: bus = %d/%s\n", __func__, sub_bus, bus->name); - pciauto_prescan_setup_bridge(hose, bdf, sub_bus); + dm_pciauto_prescan_setup_bridge(bus, sub_bus); ret = device_probe(bus); if (ret) { @@ -451,7 +503,7 @@ int dm_pci_hose_probe_bus(struct pci_controller *hose, pci_dev_t bdf) return -EPIPE; } sub_bus = pci_get_bus_max(); - pciauto_postscan_setup_bridge(hose, bdf, sub_bus); + dm_pciauto_postscan_setup_bridge(bus, sub_bus); return sub_bus; } @@ -622,9 +674,7 @@ int pci_bind_bus_devices(struct udevice *bus) /* Find this device in the device tree */ ret = pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), &dev); - /* Search for a driver */ - - /* If nothing in the device tree, bind a generic device */ + /* If nothing in the device tree, bind a device */ if (ret == -ENODEV) { struct pci_device_id find_id; ulong val; @@ -1004,6 +1054,154 @@ int pci_get_regions(struct udevice *dev, struct pci_region **iop, return (*iop != NULL) + (*memp != NULL) + (*prefp != NULL); } +u32 dm_pci_read_bar32(struct udevice *dev, int barnum) +{ + u32 addr; + int bar; + + bar = PCI_BASE_ADDRESS_0 + barnum * 4; + dm_pci_read_config32(dev, bar, &addr); + if (addr & PCI_BASE_ADDRESS_SPACE_IO) + return addr & PCI_BASE_ADDRESS_IO_MASK; + else + return addr & PCI_BASE_ADDRESS_MEM_MASK; +} + +static int _dm_pci_bus_to_phys(struct udevice *ctlr, + pci_addr_t bus_addr, unsigned long flags, + unsigned long skip_mask, phys_addr_t *pa) +{ + struct pci_controller *hose = dev_get_uclass_priv(ctlr); + struct pci_region *res; + int i; + + for (i = 0; i < hose->region_count; i++) { + res = &hose->regions[i]; + + if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0) + continue; + + if (res->flags & skip_mask) + continue; + + if (bus_addr >= res->bus_start && + (bus_addr - res->bus_start) < res->size) { + *pa = (bus_addr - res->bus_start + res->phys_start); + return 0; + } + } + + return 1; +} + +phys_addr_t dm_pci_bus_to_phys(struct udevice *dev, pci_addr_t bus_addr, + unsigned long flags) +{ + phys_addr_t phys_addr = 0; + struct udevice *ctlr; + int ret; + + /* The root controller has the region information */ + ctlr = pci_get_controller(dev); + + /* + * if PCI_REGION_MEM is set we do a two pass search with preference + * on matches that don't have PCI_REGION_SYS_MEMORY set + */ + if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) { + ret = _dm_pci_bus_to_phys(ctlr, bus_addr, + flags, PCI_REGION_SYS_MEMORY, + &phys_addr); + if (!ret) + return phys_addr; + } + + ret = _dm_pci_bus_to_phys(ctlr, bus_addr, flags, 0, &phys_addr); + + if (ret) + puts("pci_hose_bus_to_phys: invalid physical address\n"); + + return phys_addr; +} + +int _dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr, + unsigned long flags, unsigned long skip_mask, + pci_addr_t *ba) +{ + struct pci_region *res; + struct udevice *ctlr; + pci_addr_t bus_addr; + int i; + struct pci_controller *hose; + + /* The root controller has the region information */ + ctlr = pci_get_controller(dev); + hose = dev_get_uclass_priv(ctlr); + + for (i = 0; i < hose->region_count; i++) { + res = &hose->regions[i]; + + if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0) + continue; + + if (res->flags & skip_mask) + continue; + + bus_addr = phys_addr - res->phys_start + res->bus_start; + + if (bus_addr >= res->bus_start && + (bus_addr - res->bus_start) < res->size) { + *ba = bus_addr; + return 0; + } + } + + return 1; +} + +pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr, + unsigned long flags) +{ + pci_addr_t bus_addr = 0; + int ret; + + /* + * if PCI_REGION_MEM is set we do a two pass search with preference + * on matches that don't have PCI_REGION_SYS_MEMORY set + */ + if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) { + ret = _dm_pci_phys_to_bus(dev, phys_addr, flags, + PCI_REGION_SYS_MEMORY, &bus_addr); + if (!ret) + return bus_addr; + } + + ret = _dm_pci_phys_to_bus(dev, phys_addr, flags, 0, &bus_addr); + + if (ret) + puts("pci_hose_phys_to_bus: invalid physical address\n"); + + return bus_addr; +} + +void *dm_pci_map_bar(struct udevice *dev, int bar, int flags) +{ + pci_addr_t pci_bus_addr; + u32 bar_response; + + /* read BAR address */ + dm_pci_read_config32(dev, bar, &bar_response); + pci_bus_addr = (pci_addr_t)(bar_response & ~0xf); + + /* + * Pass "0" as the length argument to pci_bus_to_virt. The arg + * isn't actualy used on any platform because u-boot assumes a static + * linear mapping. In the future, this could read the BAR size + * and pass that as the size if needed. + */ + return dm_pci_bus_to_virt(dev, pci_bus_addr, flags, 0, MAP_NOCACHE); +} + UCLASS_DRIVER(pci) = { .id = UCLASS_PCI, .name = "pci", diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 645ecd4..4619089 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -9,7 +9,10 @@ */ /* - * PCI routines + * Old PCI routines + * + * Do not change this file. Instead, convert your board to use CONFIG_DM_PCI + * and change pci-uclass.c. */ #include <common.h> diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c new file mode 100644 index 0000000..842eafc --- /dev/null +++ b/drivers/pci/pci_auto.c @@ -0,0 +1,386 @@ +/* + * PCI autoconfiguration library + * + * Author: Matt Porter <mporter@mvista.com> + * + * Copyright 2000 MontaVista Software Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <errno.h> +#include <pci.h> + +/* the user can define CONFIG_SYS_PCI_CACHE_LINE_SIZE to avoid problems */ +#ifndef CONFIG_SYS_PCI_CACHE_LINE_SIZE +#define CONFIG_SYS_PCI_CACHE_LINE_SIZE 8 +#endif + +void dm_pciauto_setup_device(struct udevice *dev, int bars_num, + struct pci_region *mem, + struct pci_region *prefetch, struct pci_region *io, + bool enum_only) +{ + u32 bar_response; + pci_size_t bar_size; + u16 cmdstat = 0; + int bar, bar_nr = 0; + u8 header_type; + int rom_addr; + pci_addr_t bar_value; + struct pci_region *bar_res; + int found_mem64 = 0; + u16 class; + + dm_pci_read_config16(dev, PCI_COMMAND, &cmdstat); + cmdstat = (cmdstat & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) | + PCI_COMMAND_MASTER; + + for (bar = PCI_BASE_ADDRESS_0; + bar < PCI_BASE_ADDRESS_0 + (bars_num * 4); bar += 4) { + /* Tickle the BAR and get the response */ + if (!enum_only) + dm_pci_write_config32(dev, bar, 0xffffffff); + dm_pci_read_config32(dev, bar, &bar_response); + + /* If BAR is not implemented go to the next BAR */ + if (!bar_response) + continue; + + found_mem64 = 0; + + /* Check the BAR type and set our address mask */ + if (bar_response & PCI_BASE_ADDRESS_SPACE) { + bar_size = ((~(bar_response & PCI_BASE_ADDRESS_IO_MASK)) + & 0xffff) + 1; + if (!enum_only) + bar_res = io; + + debug("PCI Autoconfig: BAR %d, I/O, size=0x%llx, ", + bar_nr, (unsigned long long)bar_size); + } else { + if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == + PCI_BASE_ADDRESS_MEM_TYPE_64) { + u32 bar_response_upper; + u64 bar64; + + if (!enum_only) { + dm_pci_write_config32(dev, bar + 4, + 0xffffffff); + } + dm_pci_read_config32(dev, bar + 4, + &bar_response_upper); + + bar64 = ((u64)bar_response_upper << 32) | + bar_response; + + bar_size = ~(bar64 & PCI_BASE_ADDRESS_MEM_MASK) + + 1; + if (!enum_only) + found_mem64 = 1; + } else { + bar_size = (u32)(~(bar_response & + PCI_BASE_ADDRESS_MEM_MASK) + 1); + } + if (!enum_only) { + if (prefetch && (bar_response & + PCI_BASE_ADDRESS_MEM_PREFETCH)) { + bar_res = prefetch; + } else { + bar_res = mem; + } + } + + debug("PCI Autoconfig: BAR %d, %s, size=0x%llx, ", + bar_nr, bar_res == prefetch ? "Prf" : "Mem", + (unsigned long long)bar_size); + } + + if (!enum_only && pciauto_region_allocate(bar_res, bar_size, + &bar_value) == 0) { + /* Write it out and update our limit */ + dm_pci_write_config32(dev, bar, (u32)bar_value); + + if (found_mem64) { + bar += 4; +#ifdef CONFIG_SYS_PCI_64BIT + dm_pci_write_config32(dev, bar, + (u32)(bar_value >> 32)); +#else + /* + * If we are a 64-bit decoder then increment to + * the upper 32 bits of the bar and force it to + * locate in the lower 4GB of memory. + */ + dm_pci_write_config32(dev, bar, 0x00000000); +#endif + } + } + + cmdstat |= (bar_response & PCI_BASE_ADDRESS_SPACE) ? + PCI_COMMAND_IO : PCI_COMMAND_MEMORY; + + debug("\n"); + + bar_nr++; + } + + if (!enum_only) { + /* Configure the expansion ROM address */ + dm_pci_read_config8(dev, PCI_HEADER_TYPE, &header_type); + header_type &= 0x7f; + if (header_type != PCI_HEADER_TYPE_CARDBUS) { + rom_addr = (header_type == PCI_HEADER_TYPE_NORMAL) ? + PCI_ROM_ADDRESS : PCI_ROM_ADDRESS1; + dm_pci_write_config32(dev, rom_addr, 0xfffffffe); + dm_pci_read_config32(dev, rom_addr, &bar_response); + if (bar_response) { + bar_size = -(bar_response & ~1); + debug("PCI Autoconfig: ROM, size=%#x, ", + (unsigned int)bar_size); + if (pciauto_region_allocate(mem, bar_size, + &bar_value) == 0) { + dm_pci_write_config32(dev, rom_addr, + bar_value); + } + cmdstat |= PCI_COMMAND_MEMORY; + debug("\n"); + } + } + } + + /* PCI_COMMAND_IO must be set for VGA device */ + dm_pci_read_config16(dev, PCI_CLASS_DEVICE, &class); + if (class == PCI_CLASS_DISPLAY_VGA) + cmdstat |= PCI_COMMAND_IO; + + dm_pci_write_config16(dev, PCI_COMMAND, cmdstat); + dm_pci_write_config8(dev, PCI_CACHE_LINE_SIZE, + CONFIG_SYS_PCI_CACHE_LINE_SIZE); + dm_pci_write_config8(dev, PCI_LATENCY_TIMER, 0x80); +} + +void dm_pciauto_prescan_setup_bridge(struct udevice *dev, int sub_bus) +{ + struct pci_region *pci_mem; + struct pci_region *pci_prefetch; + struct pci_region *pci_io; + u16 cmdstat, prefechable_64; + /* The root controller has the region information */ + struct pci_controller *ctlr_hose = pci_bus_to_hose(0); + + pci_mem = ctlr_hose->pci_mem; + pci_prefetch = ctlr_hose->pci_prefetch; + pci_io = ctlr_hose->pci_io; + + dm_pci_read_config16(dev, PCI_COMMAND, &cmdstat); + dm_pci_read_config16(dev, PCI_PREF_MEMORY_BASE, &prefechable_64); + prefechable_64 &= PCI_PREF_RANGE_TYPE_MASK; + + /* Configure bus number registers */ + dm_pci_write_config8(dev, PCI_PRIMARY_BUS, + PCI_BUS(dm_pci_get_bdf(dev))); + dm_pci_write_config8(dev, PCI_SECONDARY_BUS, sub_bus); + dm_pci_write_config8(dev, PCI_SUBORDINATE_BUS, 0xff); + + if (pci_mem) { + /* Round memory allocator to 1MB boundary */ + pciauto_region_align(pci_mem, 0x100000); + + /* + * Set up memory and I/O filter limits, assume 32-bit + * I/O space + */ + dm_pci_write_config16(dev, PCI_MEMORY_BASE, + (pci_mem->bus_lower & 0xfff00000) >> 16); + + cmdstat |= PCI_COMMAND_MEMORY; + } + + if (pci_prefetch) { + /* Round memory allocator to 1MB boundary */ + pciauto_region_align(pci_prefetch, 0x100000); + + /* + * Set up memory and I/O filter limits, assume 32-bit + * I/O space + */ + dm_pci_write_config16(dev, PCI_PREF_MEMORY_BASE, + (pci_prefetch->bus_lower & 0xfff00000) >> 16); + if (prefechable_64 == PCI_PREF_RANGE_TYPE_64) +#ifdef CONFIG_SYS_PCI_64BIT + dm_pci_write_config32(dev, PCI_PREF_BASE_UPPER32, + pci_prefetch->bus_lower >> 32); +#else + dm_pci_write_config32(dev, PCI_PREF_BASE_UPPER32, 0x0); +#endif + + cmdstat |= PCI_COMMAND_MEMORY; + } else { + /* We don't support prefetchable memory for now, so disable */ + dm_pci_write_config16(dev, PCI_PREF_MEMORY_BASE, 0x1000); + dm_pci_write_config16(dev, PCI_PREF_MEMORY_LIMIT, 0x0); + if (prefechable_64 == PCI_PREF_RANGE_TYPE_64) { + dm_pci_write_config16(dev, PCI_PREF_BASE_UPPER32, 0x0); + dm_pci_write_config16(dev, PCI_PREF_LIMIT_UPPER32, 0x0); + } + } + + if (pci_io) { + /* Round I/O allocator to 4KB boundary */ + pciauto_region_align(pci_io, 0x1000); + + dm_pci_write_config8(dev, PCI_IO_BASE, + (pci_io->bus_lower & 0x0000f000) >> 8); + dm_pci_write_config16(dev, PCI_IO_BASE_UPPER16, + (pci_io->bus_lower & 0xffff0000) >> 16); + + cmdstat |= PCI_COMMAND_IO; + } + + /* Enable memory and I/O accesses, enable bus master */ + dm_pci_write_config16(dev, PCI_COMMAND, cmdstat | PCI_COMMAND_MASTER); +} + +void dm_pciauto_postscan_setup_bridge(struct udevice *dev, int sub_bus) +{ + struct pci_region *pci_mem; + struct pci_region *pci_prefetch; + struct pci_region *pci_io; + + /* The root controller has the region information */ + struct pci_controller *ctlr_hose = pci_bus_to_hose(0); + + pci_mem = ctlr_hose->pci_mem; + pci_prefetch = ctlr_hose->pci_prefetch; + pci_io = ctlr_hose->pci_io; + + /* Configure bus number registers */ + dm_pci_write_config8(dev, PCI_SUBORDINATE_BUS, sub_bus); + + if (pci_mem) { + /* Round memory allocator to 1MB boundary */ + pciauto_region_align(pci_mem, 0x100000); + + dm_pci_write_config16(dev, PCI_MEMORY_LIMIT, + (pci_mem->bus_lower - 1) >> 16); + } + + if (pci_prefetch) { + u16 prefechable_64; + + dm_pci_read_config16(dev, PCI_PREF_MEMORY_LIMIT, + &prefechable_64); + prefechable_64 &= PCI_PREF_RANGE_TYPE_MASK; + + /* Round memory allocator to 1MB boundary */ + pciauto_region_align(pci_prefetch, 0x100000); + + dm_pci_write_config16(dev, PCI_PREF_MEMORY_LIMIT, + (pci_prefetch->bus_lower - 1) >> 16); + if (prefechable_64 == PCI_PREF_RANGE_TYPE_64) +#ifdef CONFIG_SYS_PCI_64BIT + dm_pci_write_config32(dev, PCI_PREF_LIMIT_UPPER32, + (pci_prefetch->bus_lower - 1) >> 32); +#else + dm_pci_write_config32(dev, PCI_PREF_LIMIT_UPPER32, 0x0); +#endif + } + + if (pci_io) { + /* Round I/O allocator to 4KB boundary */ + pciauto_region_align(pci_io, 0x1000); + + dm_pci_write_config8(dev, PCI_IO_LIMIT, + ((pci_io->bus_lower - 1) & 0x0000f000) >> 8); + dm_pci_write_config16(dev, PCI_IO_LIMIT_UPPER16, + ((pci_io->bus_lower - 1) & 0xffff0000) >> 16); + } +} + +/* + * HJF: Changed this to return int. I think this is required + * to get the correct result when scanning bridges + */ +int dm_pciauto_config_device(struct udevice *dev) +{ + struct pci_region *pci_mem; + struct pci_region *pci_prefetch; + struct pci_region *pci_io; + unsigned int sub_bus = PCI_BUS(dm_pci_get_bdf(dev)); + unsigned short class; + bool enum_only = false; + int n; + +#ifdef CONFIG_PCI_ENUM_ONLY + enum_only = true; +#endif + /* The root controller has the region information */ + struct pci_controller *ctlr_hose = pci_bus_to_hose(0); + + pci_mem = ctlr_hose->pci_mem; + pci_prefetch = ctlr_hose->pci_prefetch; + pci_io = ctlr_hose->pci_io; + + dm_pci_read_config16(dev, PCI_CLASS_DEVICE, &class); + + switch (class) { + case PCI_CLASS_BRIDGE_PCI: + debug("PCI Autoconfig: Found P2P bridge, device %d\n", + PCI_DEV(dm_pci_get_bdf(dev))); + + dm_pciauto_setup_device(dev, 2, pci_mem, pci_prefetch, pci_io, + enum_only); + + n = dm_pci_hose_probe_bus(dev); + if (n < 0) + return n; + sub_bus = (unsigned int)n; + break; + + case PCI_CLASS_BRIDGE_CARDBUS: + /* + * just do a minimal setup of the bridge, + * let the OS take care of the rest + */ + dm_pciauto_setup_device(dev, 0, pci_mem, pci_prefetch, pci_io, + enum_only); + + debug("PCI Autoconfig: Found P2CardBus bridge, device %d\n", + PCI_DEV(dm_pci_get_bdf(dev))); + + break; + +#if defined(CONFIG_PCIAUTO_SKIP_HOST_BRIDGE) + case PCI_CLASS_BRIDGE_OTHER: + debug("PCI Autoconfig: Skipping bridge device %d\n", + PCI_DEV(dm_pci_get_bdf(dev))); + break; +#endif +#if defined(CONFIG_MPC834x) && !defined(CONFIG_VME8349) + case PCI_CLASS_BRIDGE_OTHER: + /* + * The host/PCI bridge 1 seems broken in 8349 - it presents + * itself as 'PCI_CLASS_BRIDGE_OTHER' and appears as an _agent_ + * device claiming resources io/mem/irq.. we only allow for + * the PIMMR window to be allocated (BAR0 - 1MB size) + */ + debug("PCI Autoconfig: Broken bridge found, only minimal config\n"); + dm_pciauto_setup_device(dev, 0, hose->pci_mem, + hose->pci_prefetch, hose->pci_io, + enum_only); + break; +#endif + + case PCI_CLASS_PROCESSOR_POWERPC: /* an agent or end-point */ + debug("PCI AutoConfig: Found PowerPC device\n"); + + default: + dm_pciauto_setup_device(dev, 6, pci_mem, pci_prefetch, pci_io, + enum_only); + break; + } + + return sub_bus; +} diff --git a/drivers/pci/pci_auto_old.c b/drivers/pci/pci_auto_old.c index 932eab8..9126f78 100644 --- a/drivers/pci/pci_auto_old.c +++ b/drivers/pci/pci_auto_old.c @@ -1,7 +1,5 @@ /* - * arch/powerpc/kernel/pci_auto.c - * - * PCI autoconfiguration library + * PCI autoconfiguration library (legacy version, do not change) * * Author: Matt Porter <mporter@mvista.com> * @@ -14,6 +12,11 @@ #include <errno.h> #include <pci.h> +/* + * Do not change this file. Instead, convert your board to use CONFIG_DM_PCI + * and change pci_auto.c. + */ + /* the user can define CONFIG_SYS_PCI_CACHE_LINE_SIZE to avoid problems */ #ifndef CONFIG_SYS_PCI_CACHE_LINE_SIZE #define CONFIG_SYS_PCI_CACHE_LINE_SIZE 8 @@ -177,18 +180,9 @@ void pciauto_prescan_setup_bridge(struct pci_controller *hose, struct pci_region *pci_io; u16 cmdstat, prefechable_64; -#ifdef CONFIG_DM_PCI - /* The root controller has the region information */ - struct pci_controller *ctlr_hose = pci_bus_to_hose(0); - - pci_mem = ctlr_hose->pci_mem; - pci_prefetch = ctlr_hose->pci_prefetch; - pci_io = ctlr_hose->pci_io; -#else pci_mem = hose->pci_mem; pci_prefetch = hose->pci_prefetch; pci_io = hose->pci_io; -#endif pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat); pci_hose_read_config_word(hose, dev, PCI_PREF_MEMORY_BASE, @@ -196,15 +190,10 @@ void pciauto_prescan_setup_bridge(struct pci_controller *hose, prefechable_64 &= PCI_PREF_RANGE_TYPE_MASK; /* Configure bus number registers */ -#ifdef CONFIG_DM_PCI - pci_hose_write_config_byte(hose, dev, PCI_PRIMARY_BUS, PCI_BUS(dev)); - pci_hose_write_config_byte(hose, dev, PCI_SECONDARY_BUS, sub_bus); -#else pci_hose_write_config_byte(hose, dev, PCI_PRIMARY_BUS, PCI_BUS(dev) - hose->first_busno); pci_hose_write_config_byte(hose, dev, PCI_SECONDARY_BUS, sub_bus - hose->first_busno); -#endif pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, 0xff); if (pci_mem) { @@ -271,26 +260,13 @@ void pciauto_postscan_setup_bridge(struct pci_controller *hose, struct pci_region *pci_prefetch; struct pci_region *pci_io; -#ifdef CONFIG_DM_PCI - /* The root controller has the region information */ - struct pci_controller *ctlr_hose = pci_bus_to_hose(0); - - pci_mem = ctlr_hose->pci_mem; - pci_prefetch = ctlr_hose->pci_prefetch; - pci_io = ctlr_hose->pci_io; -#else pci_mem = hose->pci_mem; pci_prefetch = hose->pci_prefetch; pci_io = hose->pci_io; -#endif /* Configure bus number registers */ -#ifdef CONFIG_DM_PCI - pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, sub_bus); -#else pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, sub_bus - hose->first_busno); -#endif if (pci_mem) { /* Round memory allocator to 1MB boundary */ @@ -350,18 +326,9 @@ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev) unsigned short class; int n; -#ifdef CONFIG_DM_PCI - /* The root controller has the region information */ - struct pci_controller *ctlr_hose = pci_bus_to_hose(0); - - pci_mem = ctlr_hose->pci_mem; - pci_prefetch = ctlr_hose->pci_prefetch; - pci_io = ctlr_hose->pci_io; -#else pci_mem = hose->pci_mem; pci_prefetch = hose->pci_prefetch; pci_io = hose->pci_io; -#endif pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class); @@ -373,12 +340,6 @@ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev) pciauto_setup_device(hose, dev, 2, pci_mem, pci_prefetch, pci_io); -#ifdef CONFIG_DM_PCI - n = dm_pci_hose_probe_bus(hose, dev); - if (n < 0) - return n; - sub_bus = (unsigned int)n; -#else /* Passing in current_busno allows for sibling P2P bridges */ hose->current_busno++; pciauto_prescan_setup_bridge(hose, dev, hose->current_busno); @@ -393,7 +354,6 @@ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev) pciauto_postscan_setup_bridge(hose, dev, sub_bus); sub_bus = hose->current_busno; -#endif break; case PCI_CLASS_BRIDGE_CARDBUS: @@ -407,9 +367,7 @@ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev) debug("PCI Autoconfig: Found P2CardBus bridge, device %d\n", PCI_DEV(dev)); -#ifndef CONFIG_DM_PCI hose->current_busno++; -#endif break; #if defined(CONFIG_PCIAUTO_SKIP_HOST_BRIDGE) diff --git a/drivers/pci/pci_common.c b/drivers/pci/pci_common.c index 2a14902..1755914 100644 --- a/drivers/pci/pci_common.c +++ b/drivers/pci/pci_common.c @@ -79,48 +79,6 @@ const char *pci_class_str(u8 class) }; } -pci_dev_t pci_find_class(uint find_class, int index) -{ - int bus; - int devnum; - pci_dev_t bdf; - uint32_t class; - - for (bus = 0; bus <= pci_last_busno(); bus++) { - for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES - 1; devnum++) { - pci_read_config_dword(PCI_BDF(bus, devnum, 0), - PCI_CLASS_REVISION, &class); - if (class >> 16 == 0xffff) - continue; - - for (bdf = PCI_BDF(bus, devnum, 0); - bdf <= PCI_BDF(bus, devnum, - PCI_MAX_PCI_FUNCTIONS - 1); - bdf += PCI_BDF(0, 0, 1)) { - pci_read_config_dword(bdf, PCI_CLASS_REVISION, - &class); - class >>= 8; - - if (class != find_class) - continue; - /* - * Decrement the index. We want to return the - * correct device, so index is 0 for the first - * matching device, 1 for the second, etc. - */ - if (index) { - index--; - continue; - } - /* Return index'th controller. */ - return bdf; - } - } - } - - return -ENODEV; -} - __weak int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev) { /* @@ -141,6 +99,7 @@ __weak int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev) return 0; } +#if !defined(CONFIG_DM_PCI) || defined(CONFIG_DM_PCI_COMPAT) /* Get a virtual address associated with a BAR region */ void *pci_map_bar(pci_dev_t pdev, int bar, int flags) { @@ -363,3 +322,46 @@ pci_dev_t pci_hose_find_devices(struct pci_controller *hose, int busnum, return -1; } + +pci_dev_t pci_find_class(uint find_class, int index) +{ + int bus; + int devnum; + pci_dev_t bdf; + uint32_t class; + + for (bus = 0; bus <= pci_last_busno(); bus++) { + for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES - 1; devnum++) { + pci_read_config_dword(PCI_BDF(bus, devnum, 0), + PCI_CLASS_REVISION, &class); + if (class >> 16 == 0xffff) + continue; + + for (bdf = PCI_BDF(bus, devnum, 0); + bdf <= PCI_BDF(bus, devnum, + PCI_MAX_PCI_FUNCTIONS - 1); + bdf += PCI_BDF(0, 0, 1)) { + pci_read_config_dword(bdf, PCI_CLASS_REVISION, + &class); + class >>= 8; + + if (class != find_class) + continue; + /* + * Decrement the index. We want to return the + * correct device, so index is 0 for the first + * matching device, 1 for the second, etc. + */ + if (index) { + index--; + continue; + } + /* Return index'th controller. */ + return bdf; + } + } + } + + return -ENODEV; +} +#endif /* !CONFIG_DM_PCI || CONFIG_DM_PCI_COMPAT */ diff --git a/drivers/pci/pci_compat.c b/drivers/pci/pci_compat.c index 712c48f..dd15eb1 100644 --- a/drivers/pci/pci_compat.c +++ b/drivers/pci/pci_compat.c @@ -34,5 +34,5 @@ pci_dev_t pci_find_devices(struct pci_device_id *ids, int index) if (pci_find_device_id(ids, index, &dev)) return -1; - return pci_get_bdf(dev); + return dm_pci_get_bdf(dev); } diff --git a/drivers/pci/pci_internal.h b/drivers/pci/pci_internal.h new file mode 100644 index 0000000..0867575 --- /dev/null +++ b/drivers/pci/pci_internal.h @@ -0,0 +1,50 @@ +/* + * Internal PCI functions, not exported outside drivers/pci + * + * Copyright (c) 2015 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __pci_internal_h +#define __pci_internal_h + +/** + * dm_pciauto_prescan_setup_bridge() - Set up a bridge for scanning + * + * This gets a bridge ready so that its downstream devices can be scanned. + * It sets up the bus number and memory range registers. Once the scan is + * completed, dm_pciauto_postscan_setup_bridge() should be called. + * + * @dev: Bridge device to be scanned + * @sub_bus: Bus number of the 'other side' of the bridge + */ +void dm_pciauto_prescan_setup_bridge(struct udevice *dev, int sub_bus); + +/** + * dm_pciauto_postscan_setup_bridge() - Finish set up of a bridge after scanning + * + * This should be called after a bus scan is complete. It adjusts the memory + * ranges to fit with the devices actually found on the other side (downstream) + * of the bridge. + * + * @dev: Bridge device that was scanned + * @sub_bus: Bus number of the 'other side' of the bridge + */ +void dm_pciauto_postscan_setup_bridge(struct udevice *dev, int sub_bus); + +/** + * dm_pciauto_config_device() - Configure a PCI device ready for use + * + * If the device is a bridge, downstream devices will be probed. + * + * @dev: Device to configure + * @return the maximum PCI bus number found by this device. If there are no + * bridges, this just returns the device's bus number. If the device is a + * bridge then it will return a larger number, depending on the devices on + * that bridge. On error, returns a -ve error number. + */ +int dm_pciauto_config_device(struct udevice *dev); + +#endif diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index ad1167e..2cb81b66 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -25,6 +25,7 @@ #include <common.h> #include <bios_emul.h> +#include <dm.h> #include <errno.h> #include <malloc.h> #include <pci.h> @@ -33,12 +34,12 @@ #include <video_fb.h> #include <linux/screen_info.h> -__weak bool board_should_run_oprom(pci_dev_t dev) +__weak bool board_should_run_oprom(struct udevice *dev) { return true; } -static bool should_load_oprom(pci_dev_t dev) +static bool should_load_oprom(struct udevice *dev) { if (IS_ENABLED(CONFIG_ALWAYS_LOAD_OPROM)) return 1; @@ -53,21 +54,18 @@ __weak uint32_t board_map_oprom_vendev(uint32_t vendev) return vendev; } -static int pci_rom_probe(pci_dev_t dev, uint class, - struct pci_rom_header **hdrp) +static int pci_rom_probe(struct udevice *dev, struct pci_rom_header **hdrp) { + struct pci_child_platdata *pplat = dev_get_parent_platdata(dev); struct pci_rom_header *rom_header; struct pci_rom_data *rom_data; - u16 vendor, device; u16 rom_vendor, rom_device; u32 rom_class; u32 vendev; u32 mapped_vendev; u32 rom_address; - pci_read_config_word(dev, PCI_VENDOR_ID, &vendor); - pci_read_config_word(dev, PCI_DEVICE_ID, &device); - vendev = vendor << 16 | device; + vendev = pplat->vendor << 16 | pplat->device; mapped_vendev = board_map_oprom_vendev(vendev); if (vendev != mapped_vendev) debug("Device ID mapped to %#08x\n", mapped_vendev); @@ -76,15 +74,15 @@ static int pci_rom_probe(pci_dev_t dev, uint class, rom_address = CONFIG_VGA_BIOS_ADDR; #else - pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_address); + dm_pci_read_config32(dev, PCI_ROM_ADDRESS, &rom_address); if (rom_address == 0x00000000 || rom_address == 0xffffffff) { debug("%s: rom_address=%x\n", __func__, rom_address); return -ENOENT; } /* Enable expansion ROM address decoding. */ - pci_write_config_dword(dev, PCI_ROM_ADDRESS, - rom_address | PCI_ROM_ADDRESS_ENABLE); + dm_pci_write_config32(dev, PCI_ROM_ADDRESS, + rom_address | PCI_ROM_ADDRESS_ENABLE); #endif debug("Option ROM address %x\n", rom_address); rom_header = (struct pci_rom_header *)(unsigned long)rom_address; @@ -98,7 +96,7 @@ static int pci_rom_probe(pci_dev_t dev, uint class, le16_to_cpu(rom_header->signature)); #ifndef CONFIG_VGA_BIOS_ADDR /* Disable expansion ROM address decoding */ - pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address); + dm_pci_write_config32(dev, PCI_ROM_ADDRESS, rom_address); #endif return -EINVAL; } @@ -111,7 +109,7 @@ static int pci_rom_probe(pci_dev_t dev, uint class, rom_vendor, rom_device); /* If the device id is mapped, a mismatch is expected */ - if ((vendor != rom_vendor || device != rom_device) && + if ((pplat->vendor != rom_vendor || pplat->device != rom_device) && (vendev == mapped_vendev)) { printf("ID mismatch: vendor ID %04x, device ID %04x\n", rom_vendor, rom_device); @@ -122,9 +120,9 @@ static int pci_rom_probe(pci_dev_t dev, uint class, debug("PCI ROM image, Class Code %06x, Code Type %02x\n", rom_class, rom_data->type); - if (class != rom_class) { + if (pplat->class != rom_class) { debug("Class Code mismatch ROM %06x, dev %06x\n", - rom_class, class); + rom_class, pplat->class); } *hdrp = rom_header; @@ -251,27 +249,26 @@ void setup_video(struct screen_info *screen_info) screen_info->rsvd_pos = vesa->reserved_mask_pos; } -int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), int exec_method) +int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void), + int exec_method) { + struct pci_child_platdata *pplat = dev_get_parent_platdata(dev); struct pci_rom_header *rom, *ram; int vesa_mode = -1; - uint class; bool emulate; int ret; /* Only execute VGA ROMs */ - pci_read_config_dword(dev, PCI_REVISION_ID, &class); - if (((class >> 16) ^ PCI_CLASS_DISPLAY_VGA) & 0xff00) { - debug("%s: Class %#x, should be %#x\n", __func__, class, + if (((pplat->class >> 8) ^ PCI_CLASS_DISPLAY_VGA) & 0xff00) { + debug("%s: Class %#x, should be %#x\n", __func__, pplat->class, PCI_CLASS_DISPLAY_VGA); return -ENODEV; } - class >>= 8; if (!should_load_oprom(dev)) return -ENXIO; - ret = pci_rom_probe(dev, class, &rom); + ret = pci_rom_probe(dev, &rom); if (ret) return ret; @@ -314,12 +311,12 @@ int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), int exec_method) #ifdef CONFIG_BIOSEMU BE_VGAInfo *info; - ret = biosemu_setup(dev, &info); + ret = biosemu_setup(dm_pci_get_bdf(dev), &info); if (ret) return ret; biosemu_set_interrupt_handler(0x15, int15_handler); - ret = biosemu_run(dev, (uchar *)ram, 1 << 16, info, true, - vesa_mode, &mode_info); + ret = biosemu_run(dm_pci_get_bdf(dev), (uchar *)ram, 1 << 16, + info, true, vesa_mode, &mode_info); if (ret) return ret; #endif diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 1fc287e..04541c9 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -15,6 +15,26 @@ config REQUIRE_SERIAL_CONSOLE during serial port initialization (default y). Set this to n on boards which have no debug serial port whatsoever. +config SERIAL_PRESENT + bool "Provide a serial driver" + depends on DM_SERIAL + default y + help + In very space-constrained devices even the full UART driver is too + large. In this case the debug UART can still be used in some cases. + This option enables the full UART in U-Boot, so if is it disabled, + the full UART driver will be omitted, thus saving space. + +config SPL_SERIAL_PRESENT + bool "Provide a serial driver in SPL" + depends on DM_SERIAL + default y + help + In very space-constrained devices even the full UART driver is too + large. In this case the debug UART can still be used in some cases. + This option enables the full UART in SPL, so if is it disabled, + the full UART driver will be omitted, thus saving space. + config DM_SERIAL bool "Enable Driver Model for serial drivers" depends on DM diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 3fab3f1..021b211 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -368,7 +368,7 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev) /* try Processor Local Bus device first */ addr = dev_get_addr(dev); -#ifdef CONFIG_PCI +#if defined(CONFIG_PCI) && defined(CONFIG_DM_PCI) if (addr == FDT_ADDR_T_NONE) { /* then try pci device */ struct fdt_pci_addr pci_addr; @@ -389,8 +389,7 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev) return ret; } - ret = fdtdec_get_pci_bar32(gd->fdt_blob, dev->of_offset, - &pci_addr, &bar); + ret = fdtdec_get_pci_bar32(dev, &pci_addr, &bar); if (ret) return ret; @@ -440,6 +439,7 @@ static const struct udevice_id ns16550_serial_ids[] = { }; #endif +#if CONFIG_IS_ENABLED(SERIAL_PRESENT) U_BOOT_DRIVER(ns16550_serial) = { .name = "ns16550_serial", .id = UCLASS_SERIAL, @@ -453,4 +453,5 @@ U_BOOT_DRIVER(ns16550_serial) = { .ops = &ns16550_serial_ops, .flags = DM_FLAG_PRE_RELOC, }; +#endif #endif /* CONFIG_DM_SERIAL */ diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 4bf9a5c..1c447ff 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -204,7 +204,7 @@ void serial_stdio_init(void) { } -#ifdef CONFIG_DM_STDIO +#if defined(CONFIG_DM_STDIO) && CONFIG_IS_ENABLED(SERIAL_PRESENT) static void serial_stub_putc(struct stdio_dev *sdev, const char ch) { _serial_putc(sdev->priv, ch); @@ -287,6 +287,7 @@ static int on_baudrate(const char *name, const char *value, enum env_op op, } U_BOOT_ENV_CALLBACK(baudrate, on_baudrate); +#if CONFIG_IS_ENABLED(SERIAL_PRESENT) static int serial_post_probe(struct udevice *dev) { struct dm_serial_ops *ops = serial_get_ops(dev); @@ -356,3 +357,4 @@ UCLASS_DRIVER(serial) = { .pre_remove = serial_pre_remove, .per_device_auto_alloc_size = sizeof(struct serial_dev_priv), }; +#endif diff --git a/drivers/usb/eth/mcs7830.c b/drivers/usb/eth/mcs7830.c index bbdad8b..9d6cf8c 100644 --- a/drivers/usb/eth/mcs7830.c +++ b/drivers/usb/eth/mcs7830.c @@ -11,6 +11,7 @@ */ #include <common.h> +#include <dm.h> #include <errno.h> #include <linux/mii.h> #include <malloc.h> @@ -83,19 +84,23 @@ struct mcs7830_regs { * @mchash: shadow for the network adapter's multicast hash registers */ struct mcs7830_private { +#ifdef CONFIG_DM_ETH + uint8_t rx_buf[MCS7830_RX_URB_SIZE]; + struct ueth_data ueth; +#endif uint8_t config; uint8_t mchash[8]; }; /* * mcs7830_read_reg() - read a register of the network adapter - * @dev: network device to read from + * @udev: network device to read from * @idx: index of the register to start reading from * @size: number of bytes to read * @data: buffer to read into * Return: zero upon success, negative upon error */ -static int mcs7830_read_reg(struct ueth_data *dev, uint8_t idx, +static int mcs7830_read_reg(struct usb_device *udev, uint8_t idx, uint16_t size, void *data) { int len; @@ -103,8 +108,8 @@ static int mcs7830_read_reg(struct ueth_data *dev, uint8_t idx, debug("%s() idx=0x%04X sz=%d\n", __func__, idx, size); - len = usb_control_msg(dev->pusb_dev, - usb_rcvctrlpipe(dev->pusb_dev, 0), + len = usb_control_msg(udev, + usb_rcvctrlpipe(udev, 0), MCS7830_RD_BREQ, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, idx, buf, size, @@ -119,13 +124,13 @@ static int mcs7830_read_reg(struct ueth_data *dev, uint8_t idx, /* * mcs7830_write_reg() - write a register of the network adapter - * @dev: network device to write to + * @udev: network device to write to * @idx: index of the register to start writing to * @size: number of bytes to write * @data: buffer holding the data to write * Return: zero upon success, negative upon error */ -static int mcs7830_write_reg(struct ueth_data *dev, uint8_t idx, +static int mcs7830_write_reg(struct usb_device *udev, uint8_t idx, uint16_t size, void *data) { int len; @@ -134,8 +139,8 @@ static int mcs7830_write_reg(struct ueth_data *dev, uint8_t idx, debug("%s() idx=0x%04X sz=%d\n", __func__, idx, size); memcpy(buf, data, size); - len = usb_control_msg(dev->pusb_dev, - usb_sndctrlpipe(dev->pusb_dev, 0), + len = usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), MCS7830_WR_BREQ, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, idx, buf, size, @@ -149,12 +154,12 @@ static int mcs7830_write_reg(struct ueth_data *dev, uint8_t idx, /* * mcs7830_phy_emit_wait() - emit PHY read/write access, wait for its execution - * @dev: network device to talk to + * @udev: network device to talk to * @rwflag: PHY_CMD1_READ or PHY_CMD1_WRITE opcode * @index: number of the PHY register to read or write * Return: zero upon success, negative upon error */ -static int mcs7830_phy_emit_wait(struct ueth_data *dev, +static int mcs7830_phy_emit_wait(struct usb_device *udev, uint8_t rwflag, uint8_t index) { int rc; @@ -164,14 +169,14 @@ static int mcs7830_phy_emit_wait(struct ueth_data *dev, /* send the PHY read/write request */ cmd[0] = rwflag | PHY_CMD1_PHYADDR; cmd[1] = PHY_CMD2_PEND | (index & 0x1f); - rc = mcs7830_write_reg(dev, REG_PHY_CMD, sizeof(cmd), cmd); + rc = mcs7830_write_reg(udev, REG_PHY_CMD, sizeof(cmd), cmd); if (rc < 0) return rc; /* wait for the response to become available (usually < 1ms) */ retry = 10; do { - rc = mcs7830_read_reg(dev, REG_PHY_CMD, sizeof(cmd), cmd); + rc = mcs7830_read_reg(udev, REG_PHY_CMD, sizeof(cmd), cmd); if (rc < 0) return rc; if (cmd[1] & PHY_CMD2_READY) @@ -185,50 +190,51 @@ static int mcs7830_phy_emit_wait(struct ueth_data *dev, /* * mcs7830_read_phy() - read a PHY register of the network adapter - * @dev: network device to read from + * @udev: network device to read from * @index: index of the PHY register to read from * Return: non-negative 16bit register content, negative upon error */ -static int mcs7830_read_phy(struct ueth_data *dev, uint8_t index) +static int mcs7830_read_phy(struct usb_device *udev, uint8_t index) { int rc; uint16_t val; /* issue the PHY read request and wait for its execution */ - rc = mcs7830_phy_emit_wait(dev, PHY_CMD1_READ, index); + rc = mcs7830_phy_emit_wait(udev, PHY_CMD1_READ, index); if (rc < 0) return rc; /* fetch the PHY data which was read */ - rc = mcs7830_read_reg(dev, REG_PHY_DATA, sizeof(val), &val); + rc = mcs7830_read_reg(udev, REG_PHY_DATA, sizeof(val), &val); if (rc < 0) return rc; rc = le16_to_cpu(val); - debug("%s(%s, %d) => 0x%04X\n", __func__, dev->eth_dev.name, index, rc); + debug("%s(%d) => 0x%04X\n", __func__, index, rc); return rc; } /* * mcs7830_write_phy() - write a PHY register of the network adapter - * @dev: network device to write to + * @udev: network device to write to * @index: index of the PHY register to write to * @val: value to write to the PHY register * Return: zero upon success, negative upon error */ -static int mcs7830_write_phy(struct ueth_data *dev, uint8_t index, uint16_t val) +static int mcs7830_write_phy(struct usb_device *udev, uint8_t index, + uint16_t val) { int rc; - debug("%s(%s, %d, 0x%04X)\n", __func__, dev->eth_dev.name, index, val); + debug("%s(%d, 0x%04X)\n", __func__, index, val); /* setup the PHY data which is to get written */ val = cpu_to_le16(val); - rc = mcs7830_write_reg(dev, REG_PHY_DATA, sizeof(val), &val); + rc = mcs7830_write_reg(udev, REG_PHY_DATA, sizeof(val), &val); if (rc < 0) return rc; /* issue the PHY write request and wait for its execution */ - rc = mcs7830_phy_emit_wait(dev, PHY_CMD1_WRITE, index); + rc = mcs7830_phy_emit_wait(udev, PHY_CMD1_WRITE, index); if (rc < 0) return rc; @@ -237,21 +243,21 @@ static int mcs7830_write_phy(struct ueth_data *dev, uint8_t index, uint16_t val) /* * mcs7830_write_config() - write to the network adapter's config register - * @eth: network device to write to + * @udev: network device to write to + * @priv: private data * Return: zero upon success, negative upon error * * the data which gets written is taken from the shadow config register * within the device driver's private data */ -static int mcs7830_write_config(struct ueth_data *dev) +static int mcs7830_write_config(struct usb_device *udev, + struct mcs7830_private *priv) { - struct mcs7830_private *priv; int rc; debug("%s()\n", __func__); - priv = dev->dev_priv; - rc = mcs7830_write_reg(dev, REG_CONFIG, + rc = mcs7830_write_reg(udev, REG_CONFIG, sizeof(priv->config), &priv->config); if (rc < 0) { debug("writing config to adapter failed\n"); @@ -263,21 +269,21 @@ static int mcs7830_write_config(struct ueth_data *dev) /* * mcs7830_write_mchash() - write the network adapter's multicast filter - * @eth: network device to write to + * @udev: network device to write to + * @priv: private data * Return: zero upon success, negative upon error * * the data which gets written is taken from the shadow multicast hashes * within the device driver's private data */ -static int mcs7830_write_mchash(struct ueth_data *dev) +static int mcs7830_write_mchash(struct usb_device *udev, + struct mcs7830_private *priv) { - struct mcs7830_private *priv; int rc; debug("%s()\n", __func__); - priv = dev->dev_priv; - rc = mcs7830_write_reg(dev, REG_MULTICAST_HASH, + rc = mcs7830_write_reg(udev, REG_MULTICAST_HASH, sizeof(priv->mchash), &priv->mchash); if (rc < 0) { debug("writing multicast hash to adapter failed\n"); @@ -289,12 +295,12 @@ static int mcs7830_write_mchash(struct ueth_data *dev) /* * mcs7830_set_autoneg() - setup and trigger ethernet link autonegotiation - * @eth: network device to run link negotiation on + * @udev: network device to run link negotiation on * Return: zero upon success, negative upon error * * the routine advertises available media and starts autonegotiation */ -static int mcs7830_set_autoneg(struct ueth_data *dev) +static int mcs7830_set_autoneg(struct usb_device *udev) { int adv, flg; int rc; @@ -310,39 +316,39 @@ static int mcs7830_set_autoneg(struct ueth_data *dev) */ adv = ADVERTISE_PAUSE_CAP | ADVERTISE_ALL | ADVERTISE_CSMA; - rc = mcs7830_write_phy(dev, MII_ADVERTISE, adv); + rc = mcs7830_write_phy(udev, MII_ADVERTISE, adv); flg = 0; if (!rc) - rc = mcs7830_write_phy(dev, MII_BMCR, flg); + rc = mcs7830_write_phy(udev, MII_BMCR, flg); flg |= BMCR_ANENABLE; if (!rc) - rc = mcs7830_write_phy(dev, MII_BMCR, flg); + rc = mcs7830_write_phy(udev, MII_BMCR, flg); flg |= BMCR_ANRESTART; if (!rc) - rc = mcs7830_write_phy(dev, MII_BMCR, flg); + rc = mcs7830_write_phy(udev, MII_BMCR, flg); return rc; } /* * mcs7830_get_rev() - identify a network adapter's chip revision - * @eth: network device to identify + * @udev: network device to identify * Return: non-negative number, reflecting the revision number * * currently, only "rev C and higher" and "below rev C" are needed, so * the return value is #1 for "below rev C", and #2 for "rev C and above" */ -static int mcs7830_get_rev(struct ueth_data *dev) +static int mcs7830_get_rev(struct usb_device *udev) { uint8_t buf[2]; int rc; int rev; /* register 22 is readable in rev C and higher */ - rc = mcs7830_read_reg(dev, REG_FRAME_DROP_COUNTER, sizeof(buf), buf); + rc = mcs7830_read_reg(udev, REG_FRAME_DROP_COUNTER, sizeof(buf), buf); if (rc < 0) rev = 1; else @@ -353,19 +359,19 @@ static int mcs7830_get_rev(struct ueth_data *dev) /* * mcs7830_apply_fixup() - identify an adapter and potentially apply fixups - * @eth: network device to identify and apply fixups to + * @udev: network device to identify and apply fixups to * Return: zero upon success (no errors emitted from here) * * this routine identifies the network adapter's chip revision, and applies * fixups for known issues */ -static int mcs7830_apply_fixup(struct ueth_data *dev) +static int mcs7830_apply_fixup(struct usb_device *udev) { int rev; int i; uint8_t thr; - rev = mcs7830_get_rev(dev); + rev = mcs7830_get_rev(udev); debug("%s() rev=%d\n", __func__, rev); /* @@ -374,10 +380,10 @@ static int mcs7830_apply_fixup(struct ueth_data *dev) * exactly", the introductory comment says "rev C and above") */ if (rev == 2) { - debug("%s: applying rev C fixup\n", dev->eth_dev.name); + debug("%s: applying rev C fixup\n", __func__); thr = PAUSE_THRESHOLD_DEFAULT; for (i = 0; i < 2; i++) { - (void)mcs7830_write_reg(dev, REG_PAUSE_THRESHOLD, + (void)mcs7830_write_reg(udev, REG_PAUSE_THRESHOLD, sizeof(thr), &thr); mdelay(1); } @@ -395,13 +401,12 @@ static int mcs7830_apply_fixup(struct ueth_data *dev) * of the interface callbacks can exchange ethernet frames; link negotiation is * triggered from here already and continues in background */ -static int mcs7830_basic_reset(struct ueth_data *dev) +static int mcs7830_basic_reset(struct usb_device *udev, + struct mcs7830_private *priv) { - struct mcs7830_private *priv; int rc; debug("%s()\n", __func__); - priv = dev->dev_priv; /* * comment from the respective Linux driver, which @@ -411,25 +416,25 @@ static int mcs7830_basic_reset(struct ueth_data *dev) priv->config = CONF_TXENABLE; priv->config |= CONF_ALLMULTICAST; - rc = mcs7830_set_autoneg(dev); + rc = mcs7830_set_autoneg(udev); if (rc < 0) { error("setting autoneg failed\n"); return rc; } - rc = mcs7830_write_mchash(dev); + rc = mcs7830_write_mchash(udev, priv); if (rc < 0) { error("failed to set multicast hash\n"); return rc; } - rc = mcs7830_write_config(dev); + rc = mcs7830_write_config(udev, priv); if (rc < 0) { error("failed to set configuration\n"); return rc; } - rc = mcs7830_apply_fixup(dev); + rc = mcs7830_apply_fixup(udev); if (rc < 0) { error("fixup application failed\n"); return rc; @@ -440,51 +445,38 @@ static int mcs7830_basic_reset(struct ueth_data *dev) /* * mcs7830_read_mac() - read an ethernet adapter's MAC address - * @eth: network device to read from + * @udev: network device to read from + * @enetaddr: place to put ethernet MAC address * Return: zero upon success, negative upon error * * this routine fetches the MAC address stored within the ethernet adapter, * and stores it in the ethernet interface's data structure */ -static int mcs7830_read_mac(struct eth_device *eth) +static int mcs7830_read_mac(struct usb_device *udev, unsigned char enetaddr[]) { - struct ueth_data *dev; int rc; uint8_t buf[ETH_ALEN]; debug("%s()\n", __func__); - dev = eth->priv; - rc = mcs7830_read_reg(dev, REG_ETHER_ADDR, ETH_ALEN, buf); + rc = mcs7830_read_reg(udev, REG_ETHER_ADDR, ETH_ALEN, buf); if (rc < 0) { debug("reading MAC from adapter failed\n"); return rc; } - memcpy(ð->enetaddr[0], buf, ETH_ALEN); + memcpy(enetaddr, buf, ETH_ALEN); return 0; } -/* - * mcs7830_write_mac() - write an ethernet adapter's MAC address - * @eth: network device to write to - * Return: zero upon success, negative upon error - * - * this routine takes the MAC address from the ethernet interface's data - * structure, and writes it into the ethernet adapter such that subsequent - * exchange of ethernet frames uses this address - */ -static int mcs7830_write_mac(struct eth_device *eth) +static int mcs7830_write_mac_common(struct usb_device *udev, + unsigned char enetaddr[]) { - struct ueth_data *dev; int rc; debug("%s()\n", __func__); - dev = eth->priv; - if (sizeof(eth->enetaddr) != ETH_ALEN) - return -EINVAL; - rc = mcs7830_write_reg(dev, REG_ETHER_ADDR, ETH_ALEN, eth->enetaddr); + rc = mcs7830_write_reg(udev, REG_ETHER_ADDR, ETH_ALEN, enetaddr); if (rc < 0) { debug("writing MAC to adapter failed\n"); return rc; @@ -492,28 +484,16 @@ static int mcs7830_write_mac(struct eth_device *eth) return 0; } -/* - * mcs7830_init() - network interface's init callback - * @eth: network device to initialize - * @bd: board information - * Return: zero upon success, negative upon error - * - * after initial setup during probe() and get_info(), this init() callback - * ensures that the link is up and subsequent send() and recv() calls can - * exchange ethernet frames - */ -static int mcs7830_init(struct eth_device *eth, bd_t *bd) +static int mcs7830_init_common(struct usb_device *udev) { - struct ueth_data *dev; int timeout; int have_link; debug("%s()\n", __func__); - dev = eth->priv; timeout = 0; do { - have_link = mcs7830_read_phy(dev, MII_BMSR) & BMSR_LSTATUS; + have_link = mcs7830_read_phy(udev, MII_BMSR) & BMSR_LSTATUS; if (have_link) break; udelay(LINKSTATUS_TIMEOUT_RES * 1000); @@ -526,28 +506,18 @@ static int mcs7830_init(struct eth_device *eth, bd_t *bd) return 0; } -/* - * mcs7830_send() - network interface's send callback - * @eth: network device to send the frame from - * @packet: ethernet frame content - * @length: ethernet frame length - * Return: zero upon success, negative upon error - * - * this routine send an ethernet frame out of the network interface - */ -static int mcs7830_send(struct eth_device *eth, void *packet, int length) +static int mcs7830_send_common(struct ueth_data *ueth, void *packet, + int length) { - struct ueth_data *dev; + struct usb_device *udev = ueth->pusb_dev; int rc; int gotlen; /* there is a status byte after the ethernet frame */ ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, PKTSIZE + sizeof(uint8_t)); - dev = eth->priv; - memcpy(buf, packet, length); - rc = usb_bulk_msg(dev->pusb_dev, - usb_sndbulkpipe(dev->pusb_dev, dev->ep_out), + rc = usb_bulk_msg(udev, + usb_sndbulkpipe(udev, ueth->ep_out), &buf[0], length, &gotlen, USBCALL_TIMEOUT); debug("%s() TX want len %d, got len %d, rc %d\n", @@ -555,28 +525,17 @@ static int mcs7830_send(struct eth_device *eth, void *packet, int length) return rc; } -/* - * mcs7830_recv() - network interface's recv callback - * @eth: network device to receive frames from - * Return: zero upon success, negative upon error - * - * this routine checks for available ethernet frames that the network - * interface might have received, and notifies the network stack - */ -static int mcs7830_recv(struct eth_device *eth) +static int mcs7830_recv_common(struct ueth_data *ueth, uint8_t *buf) { - struct ueth_data *dev; - ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, MCS7830_RX_URB_SIZE); int rc, wantlen, gotlen; uint8_t sts; debug("%s()\n", __func__); - dev = eth->priv; /* fetch input data from the adapter */ wantlen = MCS7830_RX_URB_SIZE; - rc = usb_bulk_msg(dev->pusb_dev, - usb_rcvbulkpipe(dev->pusb_dev, dev->ep_in), + rc = usb_bulk_msg(ueth->pusb_dev, + usb_rcvbulkpipe(ueth->pusb_dev, ueth->ep_in), &buf[0], wantlen, &gotlen, USBCALL_TIMEOUT); debug("%s() RX want len %d, got len %d, rc %d\n", @@ -601,8 +560,7 @@ static int mcs7830_recv(struct eth_device *eth) if (sts == STAT_RX_FRAME_CORRECT) { debug("%s() got a frame, len=%d\n", __func__, gotlen); - net_process_received_packet(buf, gotlen); - return 0; + return gotlen; } debug("RX: frame error (sts 0x%02X, %s %s %s %s %s)\n", @@ -615,6 +573,61 @@ static int mcs7830_recv(struct eth_device *eth) return -EIO; } +#ifndef CONFIG_DM_ETH +/* + * mcs7830_init() - network interface's init callback + * @udev: network device to initialize + * @bd: board information + * Return: zero upon success, negative upon error + * + * after initial setup during probe() and get_info(), this init() callback + * ensures that the link is up and subsequent send() and recv() calls can + * exchange ethernet frames + */ +static int mcs7830_init(struct eth_device *eth, bd_t *bd) +{ + struct ueth_data *dev = eth->priv; + + return mcs7830_init_common(dev->pusb_dev); +} + +/* + * mcs7830_send() - network interface's send callback + * @eth: network device to send the frame from + * @packet: ethernet frame content + * @length: ethernet frame length + * Return: zero upon success, negative upon error + * + * this routine send an ethernet frame out of the network interface + */ +static int mcs7830_send(struct eth_device *eth, void *packet, int length) +{ + struct ueth_data *dev = eth->priv; + + return mcs7830_send_common(dev, packet, length); +} + +/* + * mcs7830_recv() - network interface's recv callback + * @eth: network device to receive frames from + * Return: zero upon success, negative upon error + * + * this routine checks for available ethernet frames that the network + * interface might have received, and notifies the network stack + */ +static int mcs7830_recv(struct eth_device *eth) +{ + ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, MCS7830_RX_URB_SIZE); + struct ueth_data *ueth = eth->priv; + int len; + + len = mcs7830_recv_common(ueth, buf); + if (len <= 0) + net_process_received_packet(buf, len); + + return 0; +} + /* * mcs7830_halt() - network interface's halt callback * @eth: network device to cease operation of @@ -629,6 +642,22 @@ static void mcs7830_halt(struct eth_device *eth) } /* + * mcs7830_write_mac() - write an ethernet adapter's MAC address + * @eth: network device to write to + * Return: zero upon success, negative upon error + * + * this routine takes the MAC address from the ethernet interface's data + * structure, and writes it into the ethernet adapter such that subsequent + * exchange of ethernet frames uses this address + */ +static int mcs7830_write_mac(struct eth_device *eth) +{ + struct ueth_data *ueth = eth->priv; + + return mcs7830_write_mac_common(ueth->pusb_dev, eth->enetaddr); +} + +/* * mcs7830_iface_idx - index of detected network interfaces * * this counter keeps track of identified supported interfaces, @@ -802,12 +831,111 @@ int mcs7830_eth_get_info(struct usb_device *dev, struct ueth_data *ss, eth->write_hwaddr = mcs7830_write_mac; eth->priv = ss; - if (mcs7830_basic_reset(ss)) + if (mcs7830_basic_reset(ss->pusb_dev, ss->dev_priv)) return 0; - if (mcs7830_read_mac(eth)) + if (mcs7830_read_mac(ss->pusb_dev, eth->enetaddr)) return 0; debug("MAC %pM\n", eth->enetaddr); return 1; } +#endif + + +#ifdef CONFIG_DM_ETH +static int mcs7830_eth_start(struct udevice *dev) +{ + struct usb_device *udev = dev_get_parent_priv(dev); + + return mcs7830_init_common(udev); +} + +void mcs7830_eth_stop(struct udevice *dev) +{ + debug("** %s()\n", __func__); +} + +int mcs7830_eth_send(struct udevice *dev, void *packet, int length) +{ + struct mcs7830_private *priv = dev_get_priv(dev); + struct ueth_data *ueth = &priv->ueth; + + return mcs7830_send_common(ueth, packet, length); +} + +int mcs7830_eth_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct mcs7830_private *priv = dev_get_priv(dev); + struct ueth_data *ueth = &priv->ueth; + int len; + + len = mcs7830_recv_common(ueth, priv->rx_buf); + *packetp = priv->rx_buf; + + return len; +} + +static int mcs7830_free_pkt(struct udevice *dev, uchar *packet, int packet_len) +{ + struct mcs7830_private *priv = dev_get_priv(dev); + + packet_len = ALIGN(packet_len, 4); + usb_ether_advance_rxbuf(&priv->ueth, sizeof(u32) + packet_len); + + return 0; +} + +int mcs7830_write_hwaddr(struct udevice *dev) +{ + struct usb_device *udev = dev_get_parent_priv(dev); + struct eth_pdata *pdata = dev_get_platdata(dev); + + return mcs7830_write_mac_common(udev, pdata->enetaddr); +} + +static int mcs7830_eth_probe(struct udevice *dev) +{ + struct usb_device *udev = dev_get_parent_priv(dev); + struct mcs7830_private *priv = dev_get_priv(dev); + struct eth_pdata *pdata = dev_get_platdata(dev); + struct ueth_data *ueth = &priv->ueth; + + if (mcs7830_basic_reset(udev, priv)) + return 0; + + if (mcs7830_read_mac(udev, pdata->enetaddr)) + return 0; + + return usb_ether_register(dev, ueth, MCS7830_RX_URB_SIZE); +} + +static const struct eth_ops mcs7830_eth_ops = { + .start = mcs7830_eth_start, + .send = mcs7830_eth_send, + .recv = mcs7830_eth_recv, + .free_pkt = mcs7830_free_pkt, + .stop = mcs7830_eth_stop, + .write_hwaddr = mcs7830_write_hwaddr, +}; + +U_BOOT_DRIVER(mcs7830_eth) = { + .name = "mcs7830_eth", + .id = UCLASS_ETH, + .probe = mcs7830_eth_probe, + .ops = &mcs7830_eth_ops, + .priv_auto_alloc_size = sizeof(struct mcs7830_private), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; + +static const struct usb_device_id mcs7830_eth_id_table[] = { + { USB_DEVICE(0x9710, 0x7832) }, /* Moschip 7832 */ + { USB_DEVICE(0x9710, 0x7830), }, /* Moschip 7830 */ + { USB_DEVICE(0x9710, 0x7730), }, /* Moschip 7730 */ + { USB_DEVICE(0x0df6, 0x0021), }, /* Sitecom LN 30 */ + { } /* Terminating entry */ +}; + +U_BOOT_USB_DEVICE(mcs7830_eth, mcs7830_eth_id_table); +#endif diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 0cb9fcc..cda1c6d 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -18,32 +18,34 @@ struct ehci_pci_priv { struct ehci_ctrl ehci; }; -static void ehci_pci_common_init(pci_dev_t pdev, struct ehci_hccr **ret_hccr, - struct ehci_hcor **ret_hcor) +#ifdef CONFIG_DM_USB + +static void ehci_pci_init(struct udevice *dev, struct ehci_hccr **ret_hccr, + struct ehci_hcor **ret_hcor) { struct ehci_hccr *hccr; struct ehci_hcor *hcor; - uint32_t cmd; + u32 cmd; - hccr = (struct ehci_hccr *)pci_map_bar(pdev, + hccr = (struct ehci_hccr *)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); - hcor = (struct ehci_hcor *)((uint32_t) hccr + + hcor = (struct ehci_hcor *)((uintptr_t) hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); debug("EHCI-PCI init hccr 0x%x and hcor 0x%x hc_length %d\n", - (uint32_t)hccr, (uint32_t)hcor, - (uint32_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase))); + (u32)hccr, (u32)hcor, + (u32)HC_LENGTH(ehci_readl(&hccr->cr_capbase))); *ret_hccr = hccr; *ret_hcor = hcor; /* enable busmaster */ - pci_read_config_dword(pdev, PCI_COMMAND, &cmd); + dm_pci_read_config32(dev, PCI_COMMAND, &cmd); cmd |= PCI_COMMAND_MASTER; - pci_write_config_dword(pdev, PCI_COMMAND, cmd); + dm_pci_write_config32(dev, PCI_COMMAND, cmd); } -#ifndef CONFIG_DM_USB +#else #ifdef CONFIG_PCI_EHCI_DEVICE static struct pci_device_id ehci_pci_ids[] = { @@ -55,6 +57,31 @@ static struct pci_device_id ehci_pci_ids[] = { }; #endif +static void ehci_pci_legacy_init(pci_dev_t pdev, struct ehci_hccr **ret_hccr, + struct ehci_hcor **ret_hcor) +{ + struct ehci_hccr *hccr; + struct ehci_hcor *hcor; + u32 cmd; + + hccr = (struct ehci_hccr *)pci_map_bar(pdev, + PCI_BASE_ADDRESS_0, PCI_REGION_MEM); + hcor = (struct ehci_hcor *)((uintptr_t) hccr + + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); + + debug("EHCI-PCI init hccr 0x%x and hcor 0x%x hc_length %d\n", + (u32)hccr, (u32)hcor, + (u32)HC_LENGTH(ehci_readl(&hccr->cr_capbase))); + + *ret_hccr = hccr; + *ret_hcor = hcor; + + /* enable busmaster */ + pci_read_config_dword(pdev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MASTER; + pci_write_config_dword(pdev, PCI_COMMAND, cmd); +} + /* * Create the appropriate control structures to manage * a new EHCI host controller. @@ -73,7 +100,7 @@ int ehci_hcd_init(int index, enum usb_init_type init, printf("EHCI host controller not found\n"); return -1; } - ehci_pci_common_init(pdev, ret_hccr, ret_hcor); + ehci_pci_legacy_init(pdev, ret_hccr, ret_hcor); return 0; } @@ -94,7 +121,7 @@ static int ehci_pci_probe(struct udevice *dev) struct ehci_hccr *hccr; struct ehci_hcor *hcor; - ehci_pci_common_init(pci_get_bdf(dev), &hccr, &hcor); + ehci_pci_init(dev, &hccr, &hcor); return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST); } diff --git a/drivers/video/vesa_fb.c b/drivers/video/vesa_fb.c index a19651f..021c1d6 100644 --- a/drivers/video/vesa_fb.c +++ b/drivers/video/vesa_fb.c @@ -19,8 +19,8 @@ GraphicDevice ctfb; void *video_hw_init(void) { GraphicDevice *gdev = &ctfb; + struct udevice *dev; int bits_per_pixel; - pci_dev_t dev; int ret; printf("Video: "); @@ -33,14 +33,14 @@ void *video_hw_init(void) return NULL; } if (vbe_get_video_info(gdev)) { - dev = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, 0); - if (dev < 0) { + ret = dm_pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, 0, &dev); + if (ret) { printf("no card detected\n"); return NULL; } bootstage_start(BOOTSTAGE_ID_ACCUM_LCD, "vesa display"); - ret = pci_run_vga_bios(dev, NULL, PCI_ROM_USE_NATIVE | - PCI_ROM_ALLOW_FALLBACK); + ret = dm_pci_run_vga_bios(dev, NULL, PCI_ROM_USE_NATIVE | + PCI_ROM_ALLOW_FALLBACK); bootstage_accum(BOOTSTAGE_ID_ACCUM_LCD); if (ret) { printf("failed to run video BIOS: %d\n", ret); diff --git a/include/ahci.h b/include/ahci.h index 0bdedac..a956c6f 100644 --- a/include/ahci.h +++ b/include/ahci.h @@ -145,7 +145,11 @@ struct ahci_ioports { }; struct ahci_probe_ent { +#ifdef CONFIG_DM_PCI + struct udevice *dev; +#else pci_dev_t dev; +#endif struct ahci_ioports port[AHCI_MAX_PORTS]; u32 n_ports; u32 hard_port_no; diff --git a/include/bios_emul.h b/include/bios_emul.h index 3643b82..80979ed 100644 --- a/include/bios_emul.h +++ b/include/bios_emul.h @@ -42,7 +42,7 @@ struct vbe_mode_info; int BootVideoCardBIOS(pci_dev_t pcidev, BE_VGAInfo **pVGAInfo, int cleanUp); /* Run a BIOS ROM natively (only supported on x86 machines) */ -void bios_run_on_x86(pci_dev_t pcidev, unsigned long addr, int vesa_mode, +void bios_run_on_x86(struct udevice *dev, unsigned long addr, int vesa_mode, struct vbe_mode_info *mode_info); /** diff --git a/include/configs/rk3036_common.h b/include/configs/rk3036_common.h index f753e68..d22ea74 100644 --- a/include/configs/rk3036_common.h +++ b/include/configs/rk3036_common.h @@ -24,6 +24,8 @@ #define CONFIG_SYS_TIMER_BASE 0x200440a0 /* TIMER5 */ #define CONFIG_SYS_TIMER_COUNTER (CONFIG_SYS_TIMER_BASE + 8) +#define CONFIG_SPL_SERIAL_SUPPORT + #define CONFIG_SYS_NS16550 #define CONFIG_SYS_NS16550_MEM32 diff --git a/include/dm/device.h b/include/dm/device.h index 7fb9935..d9fc7fb 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -776,4 +776,25 @@ static inline void devm_kfree(struct udevice *dev, void *ptr) #endif /* ! CONFIG_DEVRES */ +/** + * dm_set_translation_offset() - Set translation offset + * @offs: Translation offset + * + * Some platforms need a special address translation. Those + * platforms (e.g. mvebu in SPL) can configure a translation + * offset in the DM by calling this function. It will be + * added to all addresses returned in dev_get_addr(). + */ +void dm_set_translation_offset(fdt_addr_t offs); + +/** + * dm_get_translation_offset() - Get translation offset + * + * This function returns the translation offset that can + * be configured by calling dm_set_translation_offset(). + * + * @return translation offset for the device address (0 as default). + */ +fdt_addr_t dm_get_translation_offset(void); + #endif diff --git a/include/fdtdec.h b/include/fdtdec.h index d82dc35..7a1450c 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -445,32 +445,15 @@ int fdtdec_get_pci_vendev(const void *blob, int node, /** * Look at the pci address of a device node that represents a PCI device - * and parse the bus, device and function number from it. For some cases - * like the bus number encoded in reg property is not correct after pci - * enumeration, this function looks through the node's compatible strings - * to get these numbers extracted instead. - * - * @param blob FDT blob - * @param node node to examine - * @param addr pci address in the form of fdt_pci_addr - * @param bdf returns bus, device, function triplet - * @return 0 if ok, negative on error - */ -int fdtdec_get_pci_bdf(const void *blob, int node, - struct fdt_pci_addr *addr, pci_dev_t *bdf); - -/** - * Look at the pci address of a device node that represents a PCI device * and return base address of the pci device's registers. * - * @param blob FDT blob - * @param node node to examine + * @param dev device to examine * @param addr pci address in the form of fdt_pci_addr * @param bar returns base address of the pci device's registers * @return 0 if ok, negative on error */ -int fdtdec_get_pci_bar32(const void *blob, int node, - struct fdt_pci_addr *addr, u32 *bar); +int fdtdec_get_pci_bar32(struct udevice *dev, struct fdt_pci_addr *addr, + u32 *bar); /** * Look up a 32-bit integer property in a node and return it. The property diff --git a/include/mmc.h b/include/mmc.h index b89962a..9254b71 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -489,11 +489,9 @@ struct pci_device_id; * This finds all the matching PCI IDs and sets them up as MMC devices. * * @name: Name to use for devices - * @mmc_supported: PCI IDs to search for - * @num_ids: Number of elements in @mmc_supported + * @mmc_supported: PCI IDs to search for, terminated by {0, 0} */ -int pci_mmc_init(const char *name, struct pci_device_id *mmc_supported, - int num_ids); +int pci_mmc_init(const char *name, struct pci_device_id *mmc_supported); /* Set block count limit because of 16 bit register limit on some hardware*/ #ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT diff --git a/include/pci.h b/include/pci.h index 2adca85..cb2562f 100644 --- a/include/pci.h +++ b/include/pci.h @@ -621,6 +621,7 @@ static inline void pci_set_ops(struct pci_controller *hose, extern void pci_setup_indirect(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data); #endif +#if !defined(CONFIG_DM_PCI) || defined(CONFIG_DM_PCI_COMPAT) extern phys_addr_t pci_hose_bus_to_phys(struct pci_controller* hose, pci_addr_t addr, unsigned long flags); extern pci_addr_t pci_hose_phys_to_bus(struct pci_controller* hose, @@ -656,7 +657,6 @@ extern pci_addr_t pci_hose_phys_to_bus(struct pci_controller* hose, pci_bus_to_virt((dev), (addr), PCI_REGION_IO, (len), (map_flags)) /* For driver model these are defined in macros in pci_compat.c */ -#if !defined(CONFIG_DM_PCI) || defined(CONFIG_DM_PCI_COMPAT) extern int pci_hose_read_config_byte(struct pci_controller *hose, pci_dev_t dev, int where, u8 *val); extern int pci_hose_read_config_word(struct pci_controller *hose, @@ -862,12 +862,12 @@ struct dm_pci_ops { #define pci_get_ops(dev) ((struct dm_pci_ops *)(dev)->driver->ops) /** - * pci_get_bdf() - Get the BDF value for a device + * dm_pci_get_bdf() - Get the BDF value for a device * * @dev: Device to check * @return bus/device/function value (see PCI_BDF()) */ -pci_dev_t pci_get_bdf(struct udevice *dev); +pci_dev_t dm_pci_get_bdf(struct udevice *dev); /** * pci_bind_bus_devices() - scan a PCI bus and bind devices @@ -902,13 +902,13 @@ int pci_bind_bus_devices(struct udevice *bus); int pci_auto_config_devices(struct udevice *bus); /** - * pci_bus_find_bdf() - Find a device given its PCI bus address + * dm_pci_bus_find_bdf() - Find a device given its PCI bus address * * @bdf: PCI device address: bus, device and function -see PCI_BDF() * @devp: Returns the device for this address, if found * @return 0 if OK, -ENODEV if not found */ -int pci_bus_find_bdf(pci_dev_t bdf, struct udevice **devp); +int dm_pci_bus_find_bdf(pci_dev_t bdf, struct udevice **devp); /** * pci_bus_find_devfn() - Find a device on a bus @@ -995,7 +995,7 @@ int pci_find_device_id(struct pci_device_id *ids, int index, * @bdf: PCI bus address to scan (PCI_BUS(bdf) is the bus number) * @return 0 if OK, -ve on error */ -int dm_pci_hose_probe_bus(struct pci_controller *hose, pci_dev_t bdf); +int dm_pci_hose_probe_bus(struct udevice *bus); /** * pci_bus_read_config() - Read a configuration value from a device @@ -1167,6 +1167,96 @@ int pci_get_regions(struct udevice *dev, struct pci_region **iop, struct pci_region **memp, struct pci_region **prefp); /** + * dm_pci_read_bar32() - read a base address register from a device + * + * @dev: Device to check + * @barnum: Bar number to read (numbered from 0) + * @return: value of BAR + */ +u32 dm_pci_read_bar32(struct udevice *dev, int barnum); + +/** + * dm_pci_bus_to_phys() - convert a PCI bus address to a physical address + * + * @dev: Device containing the PCI address + * @addr: PCI address to convert + * @flags: Flags for the region type (PCI_REGION_...) + * @return physical address corresponding to that PCI bus address + */ +phys_addr_t dm_pci_bus_to_phys(struct udevice *dev, pci_addr_t addr, + unsigned long flags); + +/** + * dm_pci_phys_to_bus() - convert a physical address to a PCI bus address + * + * @dev: Device containing the bus address + * @addr: Physical address to convert + * @flags: Flags for the region type (PCI_REGION_...) + * @return PCI bus address corresponding to that physical address + */ +pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t addr, + unsigned long flags); + +/** + * dm_pci_map_bar() - get a virtual address associated with a BAR region + * + * Looks up a base address register and finds the physical memory address + * that corresponds to it + * + * @dev: Device to check + * @bar: Bar number to read (numbered from 0) + * @flags: Flags for the region type (PCI_REGION_...) + * @return: pointer to the virtual address to use + */ +void *dm_pci_map_bar(struct udevice *dev, int bar, int flags); + +#define dm_pci_virt_to_bus(dev, addr, flags) \ + dm_pci_phys_to_bus(dev, (virt_to_phys(addr)), (flags)) +#define dm_pci_bus_to_virt(dev, addr, flags, len, map_flags) \ + map_physmem(dm_pci_bus_to_phys(dev, (addr), (flags)), \ + (len), (map_flags)) + +#define dm_pci_phys_to_mem(dev, addr) \ + dm_pci_phys_to_bus((dev), (addr), PCI_REGION_MEM) +#define dm_pci_mem_to_phys(dev, addr) \ + dm_pci_bus_to_phys((dev), (addr), PCI_REGION_MEM) +#define dm_pci_phys_to_io(dev, addr) \ + dm_pci_phys_to_bus((dev), (addr), PCI_REGION_IO) +#define dm_pci_io_to_phys(dev, addr) \ + dm_pci_bus_to_phys((dev), (addr), PCI_REGION_IO) + +#define dm_pci_virt_to_mem(dev, addr) \ + dm_pci_virt_to_bus((dev), (addr), PCI_REGION_MEM) +#define dm_pci_mem_to_virt(dev, addr, len, map_flags) \ + dm_pci_bus_to_virt((dev), (addr), PCI_REGION_MEM, (len), (map_flags)) +#define dm_pci_virt_to_io(dev, addr) \ + dm_dm_pci_virt_to_bus((dev), (addr), PCI_REGION_IO) +#define dm_pci_io_to_virt(dev, addr, len, map_flags) \ + dm_dm_pci_bus_to_virt((dev), (addr), PCI_REGION_IO, (len), (map_flags)) + +/** + * dm_pci_find_device() - find a device by vendor/device ID + * + * @vendor: Vendor ID + * @device: Device ID + * @index: 0 to find the first match, 1 for second, etc. + * @devp: Returns pointer to the device, if found + * @return 0 if found, -ve on error + */ +int dm_pci_find_device(unsigned int vendor, unsigned int device, int index, + struct udevice **devp); + +/** + * dm_pci_find_class() - find a device by class + * + * @find_class: 3-byte (24-bit) class value to find + * @index: 0 to find the first match, 1 for second, etc. + * @devp: Returns pointer to the device, if found + * @return 0 if found, -ve on error + */ +int dm_pci_find_class(uint find_class, int index, struct udevice **devp); + +/** * struct dm_pci_emul_ops - PCI device emulator operations */ struct dm_pci_emul_ops { diff --git a/include/pci_rom.h b/include/pci_rom.h index 2f1665d..95c6d07 100644 --- a/include/pci_rom.h +++ b/include/pci_rom.h @@ -44,14 +44,14 @@ enum pci_rom_emul { }; /** - * pci_run_vga_bios() - Run the VGA BIOS in an x86 PC + * dm_pci_run_vga_bios() - Run the VGA BIOS in an x86 PC * * @dev: Video device containing the BIOS * @int15_handler: Function to call to handle int 0x15 * @exec_method: flags from enum pci_rom_emul */ -int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), - int exec_method); +int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void), + int exec_method); /** * board_map_oprom_vendev() - map several PCI IDs to the one the ROM expects diff --git a/lib/fdtdec.c b/lib/fdtdec.c index ae0b708..1093c30 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -5,6 +5,7 @@ #ifndef USE_HOSTCC #include <common.h> +#include <dm.h> #include <errno.h> #include <serial.h> #include <libfdt.h> @@ -190,7 +191,7 @@ fdt_addr_t fdtdec_get_addr(const void *blob, int node, return fdtdec_get_addr_size(blob, node, prop_name, NULL); } -#ifdef CONFIG_PCI +#if defined(CONFIG_PCI) && defined(CONFIG_DM_PCI) int fdtdec_get_pci_addr(const void *blob, int node, enum fdt_pci_space type, const char *prop_name, struct fdt_pci_addr *addr) { @@ -283,58 +284,10 @@ int fdtdec_get_pci_vendev(const void *blob, int node, u16 *vendor, u16 *device) return -ENOENT; } -int fdtdec_get_pci_bdf(const void *blob, int node, - struct fdt_pci_addr *addr, pci_dev_t *bdf) +int fdtdec_get_pci_bar32(struct udevice *dev, struct fdt_pci_addr *addr, + u32 *bar) { - u16 dt_vendor, dt_device, vendor, device; - int ret; - - /* get vendor id & device id from the compatible string */ - ret = fdtdec_get_pci_vendev(blob, node, &dt_vendor, &dt_device); - if (ret) - return ret; - - /* extract the bdf from fdt_pci_addr */ - *bdf = addr->phys_hi & 0xffff00; - - /* read vendor id & device id based on bdf */ - pci_read_config_word(*bdf, PCI_VENDOR_ID, &vendor); - pci_read_config_word(*bdf, PCI_DEVICE_ID, &device); - - /* - * Note there are two places in the device tree to fully describe - * a pci device: one is via compatible string with a format of - * "pciVVVV,DDDD" and the other one is the bdf numbers encoded in - * the device node's reg address property. We read the vendor id - * and device id based on bdf and compare the values with the - * "VVVV,DDDD". If they are the same, then we are good to use bdf - * to read device's bar. But if they are different, we have to rely - * on the vendor id and device id extracted from the compatible - * string and locate the real bdf by pci_find_device(). This is - * because normally we may only know device's device number and - * function number when writing device tree. The bus number is - * dynamically assigned during the pci enumeration process. - */ - if ((dt_vendor != vendor) || (dt_device != device)) { - *bdf = pci_find_device(dt_vendor, dt_device, 0); - if (*bdf == -1) - return -ENODEV; - } - - return 0; -} - -int fdtdec_get_pci_bar32(const void *blob, int node, - struct fdt_pci_addr *addr, u32 *bar) -{ - pci_dev_t bdf; int barnum; - int ret; - - /* get pci devices's bdf */ - ret = fdtdec_get_pci_bdf(blob, node, addr, &bdf); - if (ret) - return ret; /* extract the bar number from fdt_pci_addr */ barnum = addr->phys_hi & 0xff; @@ -342,7 +295,7 @@ int fdtdec_get_pci_bar32(const void *blob, int node, return -EINVAL; barnum = (barnum - PCI_BASE_ADDRESS_0) / 4; - *bar = pci_read_bar32(pci_bus_to_hose(PCI_BUS(bdf)), bdf, barnum); + *bar = dm_pci_read_bar32(dev, barnum); return 0; } diff --git a/test/dm/pci.c b/test/dm/pci.c index 3ab4ba8..a5b1290 100644 --- a/test/dm/pci.c +++ b/test/dm/pci.c @@ -35,20 +35,17 @@ DM_TEST(dm_test_pci_busnum, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); /* Test that we can use the swapcase device correctly */ static int dm_test_pci_swapcase(struct unit_test_state *uts) { - pci_dev_t pci_dev = PCI_BDF(0, 0x1f, 0); - struct pci_controller *hose; - struct udevice *bus, *swap; + struct udevice *emul, *swap; ulong io_addr, mem_addr; char *ptr; /* Check that asking for the device automatically fires up PCI */ - ut_assertok(uclass_get_device(UCLASS_PCI_EMUL, 0, &swap)); - - ut_assertok(uclass_get_device(UCLASS_PCI, 0, &bus)); - hose = dev_get_uclass_priv(bus); + ut_assertok(uclass_get_device(UCLASS_PCI_EMUL, 0, &emul)); + ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &swap)); + ut_assert(device_active(swap)); /* First test I/O */ - io_addr = pci_read_bar32(hose, pci_dev, 0); + io_addr = dm_pci_read_bar32(swap, 0); outb(2, io_addr); ut_asserteq(2, inb(io_addr)); @@ -56,7 +53,7 @@ static int dm_test_pci_swapcase(struct unit_test_state *uts) * Now test memory mapping - note we must unmap and remap to cause * the swapcase emulation to see our data and response. */ - mem_addr = pci_read_bar32(hose, pci_dev, 1); + mem_addr = dm_pci_read_bar32(swap, 1); ptr = map_sysmem(mem_addr, 20); strcpy(ptr, "This is a TesT"); unmap_sysmem(ptr); |