Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Architecture specific OF callbacks.
0004  */
0005 #include <linux/export.h>
0006 #include <linux/io.h>
0007 #include <linux/interrupt.h>
0008 #include <linux/list.h>
0009 #include <linux/of.h>
0010 #include <linux/of_fdt.h>
0011 #include <linux/of_address.h>
0012 #include <linux/of_platform.h>
0013 #include <linux/of_irq.h>
0014 #include <linux/libfdt.h>
0015 #include <linux/slab.h>
0016 #include <linux/pci.h>
0017 #include <linux/of_pci.h>
0018 #include <linux/initrd.h>
0019 
0020 #include <asm/irqdomain.h>
0021 #include <asm/hpet.h>
0022 #include <asm/apic.h>
0023 #include <asm/io_apic.h>
0024 #include <asm/pci_x86.h>
0025 #include <asm/setup.h>
0026 #include <asm/i8259.h>
0027 #include <asm/prom.h>
0028 
0029 __initdata u64 initial_dtb;
0030 char __initdata cmd_line[COMMAND_LINE_SIZE];
0031 
0032 int __initdata of_ioapic;
0033 
0034 void __init early_init_dt_add_memory_arch(u64 base, u64 size)
0035 {
0036     BUG();
0037 }
0038 
0039 void __init add_dtb(u64 data)
0040 {
0041     initial_dtb = data + offsetof(struct setup_data, data);
0042 }
0043 
0044 /*
0045  * CE4100 ids. Will be moved to machine_device_initcall() once we have it.
0046  */
0047 static struct of_device_id __initdata ce4100_ids[] = {
0048     { .compatible = "intel,ce4100-cp", },
0049     { .compatible = "isa", },
0050     { .compatible = "pci", },
0051     {},
0052 };
0053 
0054 static int __init add_bus_probe(void)
0055 {
0056     if (!of_have_populated_dt())
0057         return 0;
0058 
0059     return of_platform_bus_probe(NULL, ce4100_ids, NULL);
0060 }
0061 device_initcall(add_bus_probe);
0062 
0063 #ifdef CONFIG_PCI
0064 struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
0065 {
0066     struct device_node *np;
0067 
0068     for_each_node_by_type(np, "pci") {
0069         const void *prop;
0070         unsigned int bus_min;
0071 
0072         prop = of_get_property(np, "bus-range", NULL);
0073         if (!prop)
0074             continue;
0075         bus_min = be32_to_cpup(prop);
0076         if (bus->number == bus_min)
0077             return np;
0078     }
0079     return NULL;
0080 }
0081 
0082 static int x86_of_pci_irq_enable(struct pci_dev *dev)
0083 {
0084     u32 virq;
0085     int ret;
0086     u8 pin;
0087 
0088     ret = pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
0089     if (ret)
0090         return ret;
0091     if (!pin)
0092         return 0;
0093 
0094     virq = of_irq_parse_and_map_pci(dev, 0, 0);
0095     if (virq == 0)
0096         return -EINVAL;
0097     dev->irq = virq;
0098     return 0;
0099 }
0100 
0101 static void x86_of_pci_irq_disable(struct pci_dev *dev)
0102 {
0103 }
0104 
0105 void x86_of_pci_init(void)
0106 {
0107     pcibios_enable_irq = x86_of_pci_irq_enable;
0108     pcibios_disable_irq = x86_of_pci_irq_disable;
0109 }
0110 #endif
0111 
0112 static void __init dtb_setup_hpet(void)
0113 {
0114 #ifdef CONFIG_HPET_TIMER
0115     struct device_node *dn;
0116     struct resource r;
0117     int ret;
0118 
0119     dn = of_find_compatible_node(NULL, NULL, "intel,ce4100-hpet");
0120     if (!dn)
0121         return;
0122     ret = of_address_to_resource(dn, 0, &r);
0123     if (ret) {
0124         WARN_ON(1);
0125         return;
0126     }
0127     hpet_address = r.start;
0128 #endif
0129 }
0130 
0131 #ifdef CONFIG_X86_LOCAL_APIC
0132 
0133 static void __init dtb_cpu_setup(void)
0134 {
0135     struct device_node *dn;
0136     u32 apic_id, version;
0137 
0138     version = GET_APIC_VERSION(apic_read(APIC_LVR));
0139     for_each_of_cpu_node(dn) {
0140         apic_id = of_get_cpu_hwid(dn, 0);
0141         if (apic_id == ~0U) {
0142             pr_warn("%pOF: missing local APIC ID\n", dn);
0143             continue;
0144         }
0145         generic_processor_info(apic_id, version);
0146     }
0147 }
0148 
0149 static void __init dtb_lapic_setup(void)
0150 {
0151     struct device_node *dn;
0152     struct resource r;
0153     unsigned long lapic_addr = APIC_DEFAULT_PHYS_BASE;
0154     int ret;
0155 
0156     dn = of_find_compatible_node(NULL, NULL, "intel,ce4100-lapic");
0157     if (dn) {
0158         ret = of_address_to_resource(dn, 0, &r);
0159         if (WARN_ON(ret))
0160             return;
0161         lapic_addr = r.start;
0162     }
0163 
0164     /* Did the boot loader setup the local APIC ? */
0165     if (!boot_cpu_has(X86_FEATURE_APIC)) {
0166         if (apic_force_enable(lapic_addr))
0167             return;
0168     }
0169     smp_found_config = 1;
0170     pic_mode = 1;
0171     register_lapic_address(lapic_addr);
0172 }
0173 
0174 #endif /* CONFIG_X86_LOCAL_APIC */
0175 
0176 #ifdef CONFIG_X86_IO_APIC
0177 static unsigned int ioapic_id;
0178 
0179 struct of_ioapic_type {
0180     u32 out_type;
0181     u32 is_level;
0182     u32 active_low;
0183 };
0184 
0185 static struct of_ioapic_type of_ioapic_type[] =
0186 {
0187     {
0188         .out_type   = IRQ_TYPE_EDGE_FALLING,
0189         .is_level   = 0,
0190         .active_low = 1,
0191     },
0192     {
0193         .out_type   = IRQ_TYPE_LEVEL_HIGH,
0194         .is_level   = 1,
0195         .active_low = 0,
0196     },
0197     {
0198         .out_type   = IRQ_TYPE_LEVEL_LOW,
0199         .is_level   = 1,
0200         .active_low = 1,
0201     },
0202     {
0203         .out_type   = IRQ_TYPE_EDGE_RISING,
0204         .is_level   = 0,
0205         .active_low = 0,
0206     },
0207 };
0208 
0209 static int dt_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
0210                   unsigned int nr_irqs, void *arg)
0211 {
0212     struct irq_fwspec *fwspec = (struct irq_fwspec *)arg;
0213     struct of_ioapic_type *it;
0214     struct irq_alloc_info tmp;
0215     int type_index;
0216 
0217     if (WARN_ON(fwspec->param_count < 2))
0218         return -EINVAL;
0219 
0220     type_index = fwspec->param[1];
0221     if (type_index >= ARRAY_SIZE(of_ioapic_type))
0222         return -EINVAL;
0223 
0224     it = &of_ioapic_type[type_index];
0225     ioapic_set_alloc_attr(&tmp, NUMA_NO_NODE, it->is_level, it->active_low);
0226     tmp.devid = mpc_ioapic_id(mp_irqdomain_ioapic_idx(domain));
0227     tmp.ioapic.pin = fwspec->param[0];
0228 
0229     return mp_irqdomain_alloc(domain, virq, nr_irqs, &tmp);
0230 }
0231 
0232 static const struct irq_domain_ops ioapic_irq_domain_ops = {
0233     .alloc      = dt_irqdomain_alloc,
0234     .free       = mp_irqdomain_free,
0235     .activate   = mp_irqdomain_activate,
0236     .deactivate = mp_irqdomain_deactivate,
0237 };
0238 
0239 static void __init dtb_add_ioapic(struct device_node *dn)
0240 {
0241     struct resource r;
0242     int ret;
0243     struct ioapic_domain_cfg cfg = {
0244         .type = IOAPIC_DOMAIN_DYNAMIC,
0245         .ops = &ioapic_irq_domain_ops,
0246         .dev = dn,
0247     };
0248 
0249     ret = of_address_to_resource(dn, 0, &r);
0250     if (ret) {
0251         printk(KERN_ERR "Can't obtain address from device node %pOF.\n", dn);
0252         return;
0253     }
0254     mp_register_ioapic(++ioapic_id, r.start, gsi_top, &cfg);
0255 }
0256 
0257 static void __init dtb_ioapic_setup(void)
0258 {
0259     struct device_node *dn;
0260 
0261     for_each_compatible_node(dn, NULL, "intel,ce4100-ioapic")
0262         dtb_add_ioapic(dn);
0263 
0264     if (nr_ioapics) {
0265         of_ioapic = 1;
0266         return;
0267     }
0268     printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
0269 }
0270 #else
0271 static void __init dtb_ioapic_setup(void) {}
0272 #endif
0273 
0274 static void __init dtb_apic_setup(void)
0275 {
0276 #ifdef CONFIG_X86_LOCAL_APIC
0277     dtb_lapic_setup();
0278     dtb_cpu_setup();
0279 #endif
0280     dtb_ioapic_setup();
0281 }
0282 
0283 #ifdef CONFIG_OF_EARLY_FLATTREE
0284 static void __init x86_flattree_get_config(void)
0285 {
0286     u32 size, map_len;
0287     void *dt;
0288 
0289     if (!initial_dtb)
0290         return;
0291 
0292     map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), (u64)128);
0293 
0294     dt = early_memremap(initial_dtb, map_len);
0295     size = fdt_totalsize(dt);
0296     if (map_len < size) {
0297         early_memunmap(dt, map_len);
0298         dt = early_memremap(initial_dtb, size);
0299         map_len = size;
0300     }
0301 
0302     early_init_dt_verify(dt);
0303     unflatten_and_copy_device_tree();
0304     early_memunmap(dt, map_len);
0305 }
0306 #else
0307 static inline void x86_flattree_get_config(void) { }
0308 #endif
0309 
0310 void __init x86_dtb_init(void)
0311 {
0312     x86_flattree_get_config();
0313 
0314     if (!of_have_populated_dt())
0315         return;
0316 
0317     dtb_setup_hpet();
0318     dtb_apic_setup();
0319 }