diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/core/ofnode.c | 36 | ||||
-rw-r--r-- | drivers/cpu/bmips_cpu.c | 33 | ||||
-rw-r--r-- | drivers/misc/swap_case.c | 36 | ||||
-rw-r--r-- | drivers/mmc/exynos_dw_mmc.c | 37 | ||||
-rw-r--r-- | drivers/pci/pci-emul-uclass.c | 24 | ||||
-rw-r--r-- | drivers/pci/pci-uclass.c | 83 | ||||
-rw-r--r-- | drivers/pci/pci_sandbox.c | 78 | ||||
-rw-r--r-- | drivers/ram/bmips_ram.c | 8 | ||||
-rw-r--r-- | drivers/serial/serial.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/gadget_chips.h | 8 |
10 files changed, 293 insertions, 52 deletions
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 29375397e0..0cfb0fbabb 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -623,6 +623,42 @@ fail: return ret; } +int ofnode_read_pci_vendev(ofnode node, u16 *vendor, u16 *device) +{ + const char *list, *end; + int len; + + list = ofnode_get_property(node, "compatible", &len); + if (!list) + return -ENOENT; + + end = list + len; + while (list < end) { + len = strlen(list); + if (len >= strlen("pciVVVV,DDDD")) { + char *s = strstr(list, "pci"); + + /* + * check if the string is something like pciVVVV,DDDD.RR + * or just pciVVVV,DDDD + */ + if (s && s[7] == ',' && + (s[12] == '.' || s[12] == 0)) { + s += 3; + *vendor = simple_strtol(s, NULL, 16); + + s += 5; + *device = simple_strtol(s, NULL, 16); + + return 0; + } + } + list += (len + 1); + } + + return -ENOENT; +} + int ofnode_read_addr_cells(ofnode node) { if (ofnode_is_np(node)) diff --git a/drivers/cpu/bmips_cpu.c b/drivers/cpu/bmips_cpu.c index 78560b0fb4..fc047473f5 100644 --- a/drivers/cpu/bmips_cpu.c +++ b/drivers/cpu/bmips_cpu.c @@ -66,6 +66,10 @@ #define STRAPBUS_63268_FCVO_SHIFT 21 #define STRAPBUS_63268_FCVO_MASK (0xf << STRAPBUS_63268_FCVO_SHIFT) +#define REG_BCM6838_OTP_BRCMBITS0 0x440 +#define VIPER_6838_FREQ_SHIFT 18 +#define VIPER_6838_FREQ_MASK (0x7 << VIPER_6838_FREQ_SHIFT) + struct bmips_cpu_priv; struct bmips_cpu_hw { @@ -272,6 +276,26 @@ static ulong bcm63268_get_cpu_freq(struct bmips_cpu_priv *priv) } } +static ulong bcm6838_get_cpu_freq(struct bmips_cpu_priv *priv) +{ + unsigned int mips_viper_freq; + + mips_viper_freq = readl_be(priv->regs + REG_BCM6838_OTP_BRCMBITS0); + mips_viper_freq = (mips_viper_freq & VIPER_6838_FREQ_MASK) + >> VIPER_6838_FREQ_SHIFT; + + switch (mips_viper_freq) { + case 0x0: + return 600000000; + case 0x1: + return 400000000; + case 0x2: + return 240000000; + default: + return 0; + } +} + static int bcm6328_get_cpu_count(struct bmips_cpu_priv *priv) { u32 val = readl_be(priv->regs + REG_BCM6328_OTP); @@ -346,6 +370,12 @@ static const struct bmips_cpu_hw bmips_cpu_bcm63268 = { .get_cpu_count = bcm6358_get_cpu_count, }; +static const struct bmips_cpu_hw bmips_cpu_bcm6838 = { + .get_cpu_desc = bmips_short_cpu_desc, + .get_cpu_freq = bcm6838_get_cpu_freq, + .get_cpu_count = bcm6358_get_cpu_count, +}; + /* Generic CPU Ops */ static int bmips_cpu_get_desc(struct udevice *dev, char *buf, int size) { @@ -444,6 +474,9 @@ static const struct udevice_id bmips_cpu_ids[] = { }, { .compatible = "brcm,bcm63268-cpu", .data = (ulong)&bmips_cpu_bcm63268, + }, { + .compatible = "brcm,bcm6838-cpu", + .data = (ulong)&bmips_cpu_bcm6838, }, { /* sentinel */ } }; diff --git a/drivers/misc/swap_case.c b/drivers/misc/swap_case.c index b777404c09..bffb809f14 100644 --- a/drivers/misc/swap_case.c +++ b/drivers/misc/swap_case.c @@ -118,6 +118,27 @@ static int sandbox_swap_case_read_config(struct udevice *emul, uint offset, *valuep = result; break; } + case PCI_CAPABILITY_LIST: + *valuep = PCI_CAP_ID_PM_OFFSET; + break; + case PCI_CAP_ID_PM_OFFSET: + *valuep = (PCI_CAP_ID_EXP_OFFSET << 8) | PCI_CAP_ID_PM; + break; + case PCI_CAP_ID_EXP_OFFSET: + *valuep = (PCI_CAP_ID_MSIX_OFFSET << 8) | PCI_CAP_ID_EXP; + break; + case PCI_CAP_ID_MSIX_OFFSET: + *valuep = PCI_CAP_ID_MSIX; + break; + case PCI_EXT_CAP_ID_ERR_OFFSET: + *valuep = (PCI_EXT_CAP_ID_VC_OFFSET << 20) | PCI_EXT_CAP_ID_ERR; + break; + case PCI_EXT_CAP_ID_VC_OFFSET: + *valuep = (PCI_EXT_CAP_ID_DSN_OFFSET << 20) | PCI_EXT_CAP_ID_VC; + break; + case PCI_EXT_CAP_ID_DSN_OFFSET: + *valuep = PCI_EXT_CAP_ID_DSN; + break; } return 0; @@ -142,6 +163,8 @@ static int sandbox_swap_case_write_config(struct udevice *emul, uint offset, debug("w bar %d=%lx\n", barnum, value); *bar = value; + /* space indicator (bit#0) is read-only */ + *bar |= barinfo[barnum].type; break; } } @@ -157,11 +180,11 @@ static int sandbox_swap_case_find_bar(struct udevice *emul, unsigned int addr, for (barnum = 0; barnum < ARRAY_SIZE(barinfo); barnum++) { unsigned int size = barinfo[barnum].size; + u32 base = plat->bar[barnum] & ~PCI_BASE_ADDRESS_SPACE; - if (addr >= plat->bar[barnum] && - addr < plat->bar[barnum] + size) { + if (addr >= base && addr < base + size) { *barnump = barnum; - *offsetp = addr - plat->bar[barnum]; + *offsetp = addr - base; return 0; } } @@ -283,3 +306,10 @@ U_BOOT_DRIVER(sandbox_swap_case_emul) = { .priv_auto_alloc_size = sizeof(struct swap_case_priv), .platdata_auto_alloc_size = sizeof(struct swap_case_platdata), }; + +static struct pci_device_id sandbox_swap_case_supported[] = { + { PCI_VDEVICE(SANDBOX, SANDBOX_PCI_DEVICE_ID), SWAP_CASE_DRV_DATA }, + {}, +}; + +U_BOOT_PCI_DEVICE(sandbox_swap_case_emul, sandbox_swap_case_supported); diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c index 865fdf4dbb..435ccac594 100644 --- a/drivers/mmc/exynos_dw_mmc.c +++ b/drivers/mmc/exynos_dw_mmc.c @@ -46,8 +46,12 @@ struct dwmci_exynos_priv_data { */ static void exynos_dwmci_clksel(struct dwmci_host *host) { +#ifdef CONFIG_DM_MMC + struct dwmci_exynos_priv_data *priv = + container_of(host, struct dwmci_exynos_priv_data, host); +#else struct dwmci_exynos_priv_data *priv = host->priv; - +#endif dwmci_writel(host, DWMCI_CLKSEL, priv->sdr_timing); } @@ -146,17 +150,11 @@ static int do_dwmci_init(struct dwmci_host *host) } static int exynos_dwmci_get_config(const void *blob, int node, - struct dwmci_host *host) + struct dwmci_host *host, + struct dwmci_exynos_priv_data *priv) { int err = 0; u32 base, timing[3]; - struct dwmci_exynos_priv_data *priv; - - priv = malloc(sizeof(struct dwmci_exynos_priv_data)); - if (!priv) { - pr_err("dwmci_exynos_priv_data malloc fail!\n"); - return -ENOMEM; - } /* Extract device id for each mmc channel */ host->dev_id = pinmux_decode_periph_id(blob, node); @@ -167,7 +165,6 @@ static int exynos_dwmci_get_config(const void *blob, int node, if (host->dev_index > 4) { printf("DWMMC%d: Can't get the dev index\n", host->dev_index); - free(priv); return -EINVAL; } @@ -178,7 +175,6 @@ static int exynos_dwmci_get_config(const void *blob, int node, base = fdtdec_get_addr(blob, node, "reg"); if (!base) { printf("DWMMC%d: Can't get base address\n", host->dev_index); - free(priv); return -EINVAL; } host->ioaddr = (void *)base; @@ -188,7 +184,6 @@ static int exynos_dwmci_get_config(const void *blob, int node, if (err) { printf("DWMMC%d: Can't get sdr-timings for devider\n", host->dev_index); - free(priv); return -EINVAL; } @@ -208,14 +203,13 @@ static int exynos_dwmci_get_config(const void *blob, int node, host->bus_hz = fdtdec_get_int(blob, node, "bus_hz", 0); host->div = fdtdec_get_int(blob, node, "div", 0); - host->priv = priv; - return 0; } static int exynos_dwmci_process_node(const void *blob, int node_list[], int count) { + struct dwmci_exynos_priv_data *priv; struct dwmci_host *host; int i, node, err; @@ -224,11 +218,20 @@ static int exynos_dwmci_process_node(const void *blob, if (node <= 0) continue; host = &dwmci_host[i]; - err = exynos_dwmci_get_config(blob, node, host); + + priv = malloc(sizeof(struct dwmci_exynos_priv_data)); + if (!priv) { + pr_err("dwmci_exynos_priv_data malloc fail!\n"); + return -ENOMEM; + } + + err = exynos_dwmci_get_config(blob, node, host, priv); if (err) { printf("%s: failed to decode dev %d\n", __func__, i); + free(priv); return err; } + host->priv = priv; do_dwmci_init(host); } @@ -266,7 +269,8 @@ static int exynos_dwmmc_probe(struct udevice *dev) struct dwmci_host *host = &priv->host; int err; - err = exynos_dwmci_get_config(gd->fdt_blob, dev_of_offset(dev), host); + err = exynos_dwmci_get_config(gd->fdt_blob, dev_of_offset(dev), host, + priv); if (err) return err; err = do_dwmci_init(host); @@ -291,6 +295,7 @@ static int exynos_dwmmc_bind(struct udevice *dev) static const struct udevice_id exynos_dwmmc_ids[] = { { .compatible = "samsung,exynos4412-dw-mshc" }, + { .compatible = "samsung,exynos-dwmmc" }, { } }; diff --git a/drivers/pci/pci-emul-uclass.c b/drivers/pci/pci-emul-uclass.c index 79e2c1420e..3822758354 100644 --- a/drivers/pci/pci-emul-uclass.c +++ b/drivers/pci/pci-emul-uclass.c @@ -11,33 +11,39 @@ #include <pci.h> #include <dm/lists.h> -struct sandbox_pci_priv { +struct sandbox_pci_emul_priv { int dev_count; }; int sandbox_pci_get_emul(struct udevice *bus, pci_dev_t find_devfn, - struct udevice **emulp) + struct udevice **containerp, struct udevice **emulp) { struct udevice *dev; int ret; - ret = pci_bus_find_devfn(bus, find_devfn, &dev); + *containerp = NULL; + ret = pci_bus_find_devfn(bus, PCI_MASK_BUS(find_devfn), &dev); if (ret) { debug("%s: Could not find emulator for dev %x\n", __func__, find_devfn); return ret; } + *containerp = dev; - ret = device_find_first_child(dev, emulp); - if (ret) - return ret; + if (device_get_uclass_id(dev) == UCLASS_PCI_GENERIC) { + ret = device_find_first_child(dev, emulp); + if (ret) + return ret; + } else { + *emulp = dev; + } return *emulp ? 0 : -ENODEV; } static int sandbox_pci_emul_post_probe(struct udevice *dev) { - struct sandbox_pci_priv *priv = dev->uclass->priv; + struct sandbox_pci_emul_priv *priv = dev->uclass->priv; priv->dev_count++; sandbox_set_enable_pci_map(true); @@ -47,7 +53,7 @@ static int sandbox_pci_emul_post_probe(struct udevice *dev) static int sandbox_pci_emul_pre_remove(struct udevice *dev) { - struct sandbox_pci_priv *priv = dev->uclass->priv; + struct sandbox_pci_emul_priv *priv = dev->uclass->priv; priv->dev_count--; sandbox_set_enable_pci_map(priv->dev_count > 0); @@ -60,5 +66,5 @@ UCLASS_DRIVER(pci_emul) = { .name = "pci_emul", .post_probe = sandbox_pci_emul_post_probe, .pre_remove = sandbox_pci_emul_pre_remove, - .priv_auto_alloc_size = sizeof(struct sandbox_pci_priv), + .priv_auto_alloc_size = sizeof(struct sandbox_pci_emul_priv), }; diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 46e9c71bdf..e9671d9b76 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -690,7 +690,7 @@ static int pci_find_and_bind_driver(struct udevice *parent, if (ret) goto error; debug("%s: Match found: %s\n", __func__, drv->name); - dev->driver_data = find_id->driver_data; + dev->driver_data = id->driver_data; *devp = dev; return 0; } @@ -745,6 +745,8 @@ int pci_bind_bus_devices(struct udevice *bus) struct udevice *dev; ulong class; + if (!PCI_FUNC(bdf)) + found_multi = false; if (PCI_FUNC(bdf) && !found_multi) continue; /* Check only the first access, we don't expect problems */ @@ -987,19 +989,18 @@ static int pci_uclass_child_post_bind(struct udevice *dev) if (!dev_of_valid(dev)) return 0; - /* - * We could read vendor, device, class if available. But for now we - * just check the address. - */ pplat = dev_get_parent_platdata(dev); + + /* Extract vendor id and device id if available */ + ofnode_read_pci_vendev(dev_ofnode(dev), &pplat->vendor, &pplat->device); + + /* Extract the devfn from fdt_pci_addr */ ret = ofnode_read_pci_addr(dev_ofnode(dev), FDT_PCI_SPACE_CONFIG, "reg", &addr); - if (ret) { if (ret != -ENOENT) return -EINVAL; } else { - /* extract the devfn from fdt_pci_addr */ pplat->devfn = addr.phys_hi & 0xff00; } @@ -1319,6 +1320,74 @@ void *dm_pci_map_bar(struct udevice *dev, int bar, int flags) return dm_pci_bus_to_virt(dev, pci_bus_addr, flags, 0, MAP_NOCACHE); } +int dm_pci_find_capability(struct udevice *dev, int cap) +{ + u16 status; + u8 header_type; + int ttl = PCI_FIND_CAP_TTL; + u8 id; + u16 ent; + u8 pos; + + dm_pci_read_config16(dev, PCI_STATUS, &status); + if (!(status & PCI_STATUS_CAP_LIST)) + return 0; + + dm_pci_read_config8(dev, PCI_HEADER_TYPE, &header_type); + if ((header_type & 0x7f) == PCI_HEADER_TYPE_CARDBUS) + pos = PCI_CB_CAPABILITY_LIST; + else + pos = PCI_CAPABILITY_LIST; + + dm_pci_read_config8(dev, pos, &pos); + while (ttl--) { + if (pos < PCI_STD_HEADER_SIZEOF) + break; + pos &= ~3; + dm_pci_read_config16(dev, pos, &ent); + + id = ent & 0xff; + if (id == 0xff) + break; + if (id == cap) + return pos; + pos = (ent >> 8); + } + + return 0; +} + +int dm_pci_find_ext_capability(struct udevice *dev, int cap) +{ + u32 header; + int ttl; + int pos = PCI_CFG_SPACE_SIZE; + + /* minimum 8 bytes per capability */ + ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8; + + dm_pci_read_config32(dev, pos, &header); + /* + * If we have no capabilities, this is indicated by cap ID, + * cap version and next pointer all being 0. + */ + if (header == 0) + return 0; + + while (ttl--) { + if (PCI_EXT_CAP_ID(header) == cap) + return pos; + + pos = PCI_EXT_CAP_NEXT(header); + if (pos < PCI_CFG_SPACE_SIZE) + break; + + dm_pci_read_config32(dev, pos, &header); + } + + return 0; +} + UCLASS_DRIVER(pci) = { .id = UCLASS_PCI, .name = "pci", diff --git a/drivers/pci/pci_sandbox.c b/drivers/pci/pci_sandbox.c index 67cd733e61..119a98d061 100644 --- a/drivers/pci/pci_sandbox.c +++ b/drivers/pci/pci_sandbox.c @@ -10,15 +10,27 @@ #include <inttypes.h> #include <pci.h> +#define FDT_DEV_INFO_CELLS 4 +#define FDT_DEV_INFO_SIZE (FDT_DEV_INFO_CELLS * sizeof(u32)) + +#define SANDBOX_PCI_DEVFN(d, f) ((d << 3) | f) + +struct sandbox_pci_priv { + struct { + u16 vendor; + u16 device; + } vendev[256]; +}; + static int sandbox_pci_write_config(struct udevice *bus, pci_dev_t devfn, uint offset, ulong value, enum pci_size_t size) { struct dm_pci_emul_ops *ops; - struct udevice *emul; + struct udevice *container, *emul; int ret; - ret = sandbox_pci_get_emul(bus, devfn, &emul); + ret = sandbox_pci_get_emul(bus, devfn, &container, &emul); if (ret) return ret == -ENODEV ? 0 : ret; ops = pci_get_emul_ops(emul); @@ -33,14 +45,31 @@ static int sandbox_pci_read_config(struct udevice *bus, pci_dev_t devfn, enum pci_size_t size) { struct dm_pci_emul_ops *ops; - struct udevice *emul; + struct udevice *container, *emul; + struct sandbox_pci_priv *priv = dev_get_priv(bus); int ret; /* Prepare the default response */ *valuep = pci_get_ff(size); - ret = sandbox_pci_get_emul(bus, devfn, &emul); - if (ret) - return ret == -ENODEV ? 0 : ret; + ret = sandbox_pci_get_emul(bus, devfn, &container, &emul); + if (ret) { + if (!container) { + u16 vendor, device; + + devfn = SANDBOX_PCI_DEVFN(PCI_DEV(devfn), + PCI_FUNC(devfn)); + vendor = priv->vendev[devfn].vendor; + device = priv->vendev[devfn].device; + if (offset == PCI_VENDOR_ID && vendor) + *valuep = vendor; + else if (offset == PCI_DEVICE_ID && device) + *valuep = device; + + return 0; + } else { + return ret == -ENODEV ? 0 : ret; + } + } ops = pci_get_emul_ops(emul); if (!ops || !ops->read_config) return -ENOSYS; @@ -48,6 +77,41 @@ static int sandbox_pci_read_config(struct udevice *bus, pci_dev_t devfn, return ops->read_config(emul, offset, valuep, size); } +static int sandbox_pci_probe(struct udevice *dev) +{ + struct sandbox_pci_priv *priv = dev_get_priv(dev); + const fdt32_t *cell; + u8 pdev, pfn, devfn; + int len; + + cell = ofnode_get_property(dev_ofnode(dev), "sandbox,dev-info", &len); + if (!cell) + return 0; + + if ((len % FDT_DEV_INFO_SIZE) == 0) { + int num = len / FDT_DEV_INFO_SIZE; + int i; + + for (i = 0; i < num; i++) { + debug("dev info #%d: %02x %02x %04x %04x\n", i, + fdt32_to_cpu(cell[0]), fdt32_to_cpu(cell[1]), + fdt32_to_cpu(cell[2]), fdt32_to_cpu(cell[3])); + + pdev = fdt32_to_cpu(cell[0]); + pfn = fdt32_to_cpu(cell[1]); + if (pdev > 31 || pfn > 7) + continue; + devfn = SANDBOX_PCI_DEVFN(pdev, pfn); + priv->vendev[devfn].vendor = fdt32_to_cpu(cell[2]); + priv->vendev[devfn].device = fdt32_to_cpu(cell[3]); + + cell += FDT_DEV_INFO_CELLS; + } + } + + return 0; +} + static const struct dm_pci_ops sandbox_pci_ops = { .read_config = sandbox_pci_read_config, .write_config = sandbox_pci_write_config, @@ -63,6 +127,8 @@ U_BOOT_DRIVER(pci_sandbox) = { .id = UCLASS_PCI, .of_match = sandbox_pci_ids, .ops = &sandbox_pci_ops, + .probe = sandbox_pci_probe, + .priv_auto_alloc_size = sizeof(struct sandbox_pci_priv), /* Attach an emulator if we can */ .child_post_bind = dm_scan_fdt_dev, diff --git a/drivers/ram/bmips_ram.c b/drivers/ram/bmips_ram.c index cc37dfa08c..b5f19c983c 100644 --- a/drivers/ram/bmips_ram.c +++ b/drivers/ram/bmips_ram.c @@ -43,6 +43,7 @@ struct bmips_ram_hw { struct bmips_ram_priv { void __iomem *regs; + u32 force_size; const struct bmips_ram_hw *hw; }; @@ -104,7 +105,10 @@ static int bmips_ram_get_info(struct udevice *dev, struct ram_info *info) const struct bmips_ram_hw *hw = priv->hw; info->base = 0x80000000; - info->size = hw->get_ram_size(priv); + if (priv->force_size) + info->size = priv->force_size; + else + info->size = hw->get_ram_size(priv); return 0; } @@ -155,6 +159,8 @@ static int bmips_ram_probe(struct udevice *dev) if (!priv->regs) return -EINVAL; + dev_read_u32(dev, "force-size", &priv->force_size); + priv->hw = hw; return 0; diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c index 63b232b536..c489deac2b 100644 --- a/drivers/serial/serial.c +++ b/drivers/serial/serial.c @@ -109,7 +109,6 @@ U_BOOT_ENV_CALLBACK(baudrate, on_baudrate); __attribute__((weak, alias("serial_null"))); serial_initfunc(atmel_serial_initialize); -serial_initfunc(au1x00_serial_initialize); serial_initfunc(mcf_serial_initialize); serial_initfunc(mpc85xx_serial_initialize); serial_initfunc(mpc8xx_serial_initialize); @@ -164,7 +163,6 @@ void serial_register(struct serial_device *dev) void serial_initialize(void) { atmel_serial_initialize(); - au1x00_serial_initialize(); mcf_serial_initialize(); mpc85xx_serial_initialize(); mpc8xx_serial_initialize(); diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index f320708431..b9b081999a 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h @@ -149,14 +149,6 @@ #define gadget_is_dwc3(g) 0 #endif - - -/* - * CONFIG_USB_GADGET_SX2 - * CONFIG_USB_GADGET_AU1X00 - * ... - */ - /** * usb_gadget_controller_number - support bcdDevice id convention * @gadget: the controller being driven |