linux/arch/x86/kernel/devicetree.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Architecture specific OF callbacks.
   4 */
   5#include <linux/export.h>
   6#include <linux/io.h>
   7#include <linux/interrupt.h>
   8#include <linux/list.h>
   9#include <linux/of.h>
  10#include <linux/of_fdt.h>
  11#include <linux/of_address.h>
  12#include <linux/of_platform.h>
  13#include <linux/of_irq.h>
  14#include <linux/libfdt.h>
  15#include <linux/slab.h>
  16#include <linux/pci.h>
  17#include <linux/of_pci.h>
  18#include <linux/initrd.h>
  19
  20#include <asm/irqdomain.h>
  21#include <asm/hpet.h>
  22#include <asm/apic.h>
  23#include <asm/io_apic.h>
  24#include <asm/pci_x86.h>
  25#include <asm/setup.h>
  26#include <asm/i8259.h>
  27#include <asm/prom.h>
  28
  29__initdata u64 initial_dtb;
  30char __initdata cmd_line[COMMAND_LINE_SIZE];
  31
  32int __initdata of_ioapic;
  33
  34void __init early_init_dt_add_memory_arch(u64 base, u64 size)
  35{
  36        BUG();
  37}
  38
  39void __init add_dtb(u64 data)
  40{
  41        initial_dtb = data + offsetof(struct setup_data, data);
  42}
  43
  44/*
  45 * CE4100 ids. Will be moved to machine_device_initcall() once we have it.
  46 */
  47static struct of_device_id __initdata ce4100_ids[] = {
  48        { .compatible = "intel,ce4100-cp", },
  49        { .compatible = "isa", },
  50        { .compatible = "pci", },
  51        {},
  52};
  53
  54static int __init add_bus_probe(void)
  55{
  56        if (!of_have_populated_dt())
  57                return 0;
  58
  59        return of_platform_bus_probe(NULL, ce4100_ids, NULL);
  60}
  61device_initcall(add_bus_probe);
  62
  63#ifdef CONFIG_PCI
  64struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
  65{
  66        struct device_node *np;
  67
  68        for_each_node_by_type(np, "pci") {
  69                const void *prop;
  70                unsigned int bus_min;
  71
  72                prop = of_get_property(np, "bus-range", NULL);
  73                if (!prop)
  74                        continue;
  75                bus_min = be32_to_cpup(prop);
  76                if (bus->number == bus_min)
  77                        return np;
  78        }
  79        return NULL;
  80}
  81
  82static int x86_of_pci_irq_enable(struct pci_dev *dev)
  83{
  84        u32 virq;
  85        int ret;
  86        u8 pin;
  87
  88        ret = pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
  89        if (ret)
  90                return ret;
  91        if (!pin)
  92                return 0;
  93
  94        virq = of_irq_parse_and_map_pci(dev, 0, 0);
  95        if (virq == 0)
  96                return -EINVAL;
  97        dev->irq = virq;
  98        return 0;
  99}
 100
 101static void x86_of_pci_irq_disable(struct pci_dev *dev)
 102{
 103}
 104
 105void x86_of_pci_init(void)
 106{
 107        pcibios_enable_irq = x86_of_pci_irq_enable;
 108        pcibios_disable_irq = x86_of_pci_irq_disable;
 109}
 110#endif
 111
 112static void __init dtb_setup_hpet(void)
 113{
 114#ifdef CONFIG_HPET_TIMER
 115        struct device_node *dn;
 116        struct resource r;
 117        int ret;
 118
 119        dn = of_find_compatible_node(NULL, NULL, "intel,ce4100-hpet");
 120        if (!dn)
 121                return;
 122        ret = of_address_to_resource(dn, 0, &r);
 123        if (ret) {
 124                WARN_ON(1);
 125                return;
 126        }
 127        hpet_address = r.start;
 128#endif
 129}
 130
 131#ifdef CONFIG_X86_LOCAL_APIC
 132
 133static void __init dtb_cpu_setup(void)
 134{
 135        struct device_node *dn;
 136        u32 apic_id, version;
 137
 138        version = GET_APIC_VERSION(apic_read(APIC_LVR));
 139        for_each_of_cpu_node(dn) {
 140                apic_id = of_get_cpu_hwid(dn, 0);
 141                if (apic_id == ~0U) {
 142                        pr_warn("%pOF: missing local APIC ID\n", dn);
 143                        continue;
 144                }
 145                generic_processor_info(apic_id, version);
 146        }
 147}
 148
 149static void __init dtb_lapic_setup(void)
 150{
 151        struct device_node *dn;
 152        struct resource r;
 153        unsigned long lapic_addr = APIC_DEFAULT_PHYS_BASE;
 154        int ret;
 155
 156        dn = of_find_compatible_node(NULL, NULL, "intel,ce4100-lapic");
 157        if (dn) {
 158                ret = of_address_to_resource(dn, 0, &r);
 159                if (WARN_ON(ret))
 160                        return;
 161                lapic_addr = r.start;
 162        }
 163
 164        /* Did the boot loader setup the local APIC ? */
 165        if (!boot_cpu_has(X86_FEATURE_APIC)) {
 166                if (apic_force_enable(lapic_addr))
 167                        return;
 168        }
 169        smp_found_config = 1;
 170        pic_mode = 1;
 171        register_lapic_address(lapic_addr);
 172}
 173
 174#endif /* CONFIG_X86_LOCAL_APIC */
 175
 176#ifdef CONFIG_X86_IO_APIC
 177static unsigned int ioapic_id;
 178
 179struct of_ioapic_type {
 180        u32 out_type;
 181        u32 is_level;
 182        u32 active_low;
 183};
 184
 185static struct of_ioapic_type of_ioapic_type[] =
 186{
 187        {
 188                .out_type       = IRQ_TYPE_EDGE_FALLING,
 189                .is_level       = 0,
 190                .active_low     = 1,
 191        },
 192        {
 193                .out_type       = IRQ_TYPE_LEVEL_HIGH,
 194                .is_level       = 1,
 195                .active_low     = 0,
 196        },
 197        {
 198                .out_type       = IRQ_TYPE_LEVEL_LOW,
 199                .is_level       = 1,
 200                .active_low     = 1,
 201        },
 202        {
 203                .out_type       = IRQ_TYPE_EDGE_RISING,
 204                .is_level       = 0,
 205                .active_low     = 0,
 206        },
 207};
 208
 209static int dt_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
 210                              unsigned int nr_irqs, void *arg)
 211{
 212        struct irq_fwspec *fwspec = (struct irq_fwspec *)arg;
 213        struct of_ioapic_type *it;
 214        struct irq_alloc_info tmp;
 215        int type_index;
 216
 217        if (WARN_ON(fwspec->param_count < 2))
 218                return -EINVAL;
 219
 220        type_index = fwspec->param[1];
 221        if (type_index >= ARRAY_SIZE(of_ioapic_type))
 222                return -EINVAL;
 223
 224        it = &of_ioapic_type[type_index];
 225        ioapic_set_alloc_attr(&tmp, NUMA_NO_NODE, it->is_level, it->active_low);
 226        tmp.devid = mpc_ioapic_id(mp_irqdomain_ioapic_idx(domain));
 227        tmp.ioapic.pin = fwspec->param[0];
 228
 229        return mp_irqdomain_alloc(domain, virq, nr_irqs, &tmp);
 230}
 231
 232static const struct irq_domain_ops ioapic_irq_domain_ops = {
 233        .alloc          = dt_irqdomain_alloc,
 234        .free           = mp_irqdomain_free,
 235        .activate       = mp_irqdomain_activate,
 236        .deactivate     = mp_irqdomain_deactivate,
 237};
 238
 239static void __init dtb_add_ioapic(struct device_node *dn)
 240{
 241        struct resource r;
 242        int ret;
 243        struct ioapic_domain_cfg cfg = {
 244                .type = IOAPIC_DOMAIN_DYNAMIC,
 245                .ops = &ioapic_irq_domain_ops,
 246                .dev = dn,
 247        };
 248
 249        ret = of_address_to_resource(dn, 0, &r);
 250        if (ret) {
 251                printk(KERN_ERR "Can't obtain address from device node %pOF.\n", dn);
 252                return;
 253        }
 254        mp_register_ioapic(++ioapic_id, r.start, gsi_top, &cfg);
 255}
 256
 257static void __init dtb_ioapic_setup(void)
 258{
 259        struct device_node *dn;
 260
 261        for_each_compatible_node(dn, NULL, "intel,ce4100-ioapic")
 262                dtb_add_ioapic(dn);
 263
 264        if (nr_ioapics) {
 265                of_ioapic = 1;
 266                return;
 267        }
 268        printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
 269}
 270#else
 271static void __init dtb_ioapic_setup(void) {}
 272#endif
 273
 274static void __init dtb_apic_setup(void)
 275{
 276#ifdef CONFIG_X86_LOCAL_APIC
 277        dtb_lapic_setup();
 278        dtb_cpu_setup();
 279#endif
 280        dtb_ioapic_setup();
 281}
 282
 283#ifdef CONFIG_OF_EARLY_FLATTREE
 284static void __init x86_flattree_get_config(void)
 285{
 286        u32 size, map_len;
 287        void *dt;
 288
 289        if (!initial_dtb)
 290                return;
 291
 292        map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), (u64)128);
 293
 294        dt = early_memremap(initial_dtb, map_len);
 295        size = fdt_totalsize(dt);
 296        if (map_len < size) {
 297                early_memunmap(dt, map_len);
 298                dt = early_memremap(initial_dtb, size);
 299                map_len = size;
 300        }
 301
 302        early_init_dt_verify(dt);
 303        unflatten_and_copy_device_tree();
 304        early_memunmap(dt, map_len);
 305}
 306#else
 307static inline void x86_flattree_get_config(void) { }
 308#endif
 309
 310void __init x86_dtb_init(void)
 311{
 312        x86_flattree_get_config();
 313
 314        if (!of_have_populated_dt())
 315                return;
 316
 317        dtb_setup_hpet();
 318        dtb_apic_setup();
 319}
 320