[RFC 1/3] MPC8544DS Basic Port
Kumar Gala
galak at kernel.crashing.org
Thu Mar 8 15:35:54 EST 2007
On Mar 7, 2007, at 3:14 PM, Jon Loeliger wrote:
> arch/powerpc/platforms/85xx/Kconfig | 18 +
> arch/powerpc/platforms/85xx/Makefile | 1
> arch/powerpc/platforms/85xx/mpc8544_ds.c | 424 +++++++++++++++++++
> +++++++++++
> 3 files changed, 442 insertions(+), 1 deletions(-)
>
>
>
> diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/
> platforms/85xx/Kconfig
> index eb661cc..5221664 100644
> --- a/arch/powerpc/platforms/85xx/Kconfig
> +++ b/arch/powerpc/platforms/85xx/Kconfig
> @@ -20,6 +20,8 @@ config MPC8560_ADS
> config MPC85xx_CDS
> bool "Freescale MPC85xx CDS"
> select DEFAULT_UIMAGE
> + select FSL_PCIE
> + select PPC_I8259
> help
> This option enables support for the MPC85xx CDS board
CDS changes in ds patch :)
>
> @@ -30,6 +32,14 @@ config MPC85xx_MDS
> help
> This option enables support for the MPC85xx MDS board
>
> +config MPC8544_DS
> + bool "Freescale MPC8544/MPC8533 DS"
> + select PPC_I8259
> + select DEFAULT_UIMAGE
> + select FSL_PCIE
> + help
> + This option enables support for the MPC8544/MPC8533 DS board
> +
> endchoice
>
> config MPC8540
> @@ -43,11 +53,17 @@ config MPC8560
> select PPC_INDIRECT_PCI
> default y if MPC8560_ADS
>
> +config MPC8544
> + bool
> + select SERIAL_8250_SHARE_IRQ
hmm, seems like we need this for all 85xx.
> + default y if MPC8544_DS
> +
> config MPC85xx
> bool
> select PPC_UDBG_16550
> select PPC_INDIRECT_PCI
> - default y if MPC8540_ADS || MPC85xx_CDS || MPC8560_ADS ||
> MPC85xx_MDS
> + default y if MPC8540_ADS || MPC85xx_CDS || MPC8560_ADS \
> + || MPC85xx_MDS || MPC8544_DS
>
> config PPC_INDIRECT_PCI_BE
> bool
> diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/
> platforms/85xx/Makefile
> index 4e63917..4e02cbb 100644
> --- a/arch/powerpc/platforms/85xx/Makefile
> +++ b/arch/powerpc/platforms/85xx/Makefile
> @@ -5,4 +5,5 @@ obj-$(CONFIG_PPC_85xx) += misc.o pci.o
> obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o
> obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o
> obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o
> +obj-$(CONFIG_MPC8544_DS) += mpc8544_ds.o
> obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o
> diff --git a/arch/powerpc/platforms/85xx/mpc8544_ds.c b/arch/
> powerpc/platforms/85xx/mpc8544_ds.c
> new file mode 100644
> index 0000000..035a762
> --- /dev/null
> +++ b/arch/powerpc/platforms/85xx/mpc8544_ds.c
> @@ -0,0 +1,424 @@
> +/*
> + * MPC8544 DS Board Setup
> + *
> + * Author Xianghua Xiao (x.xiao at freescale.com)
> + * Copyright 2007 Freescale Semiconductor Inc.
> + *
> + * This program is free software; you can redistribute it and/or
> modify it
> + * under the terms of the GNU General Public License as
> published by the
> + * Free Software Foundation; either version 2 of the License, or
> (at your
> + * option) any later version.
> + */
> +
> +#include <linux/stddef.h>
> +#include <linux/kernel.h>
> +#include <linux/pci.h>
> +#include <linux/kdev_t.h>
> +#include <linux/delay.h>
> +#include <linux/seq_file.h>
> +
> +#include <asm/system.h>
> +#include <asm/time.h>
> +#include <asm/machdep.h>
> +#include <asm/pci-bridge.h>
> +#include <asm/mpc85xx.h>
> +#include <mm/mmu_decl.h>
> +#include <asm/prom.h>
> +#include <asm/udbg.h>
> +#include <asm/mpic.h>
> +#include <asm/i8259.h>
> +
> +#include <sysdev/fsl_soc.h>
> +#include "mpc85xx.h"
> +
> +#undef DEBUG
> +
> +#ifdef DEBUG
> +#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt,
> __FUNCTION__, ## args)
> +#else
> +#define DBG(fmt, args...)
> +#endif
> +
> +#ifndef CONFIG_PCI
> +unsigned long isa_io_base = 0;
> +unsigned long isa_mem_base = 0;
> +unsigned long pci_dram_offset = 0;
> +#endif
> +
> +#ifdef CONFIG_PCI
> +int mpc85xx_exclude_device(u_char bus, u_char devfn)
> +{
> + if (bus == 2 && PCI_SLOT(devfn) == 0x1d)
> + return PCIBIOS_DEVICE_NOT_FOUND;
> + else
> + return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static void mpc8544_8259_cascade(unsigned int irq, struct irq_desc
> *desc)
> +{
> + unsigned int cascade_irq = i8259_irq();
> + if (cascade_irq != NO_IRQ)
> + generic_handle_irq(cascade_irq);
> + desc->chip->eoi(irq);
> +}
> +#endif /* CONFIG_PCI */
> +
> +void __init mpc8544_ds_pic_init(void)
> +{
> + struct mpic *mpic;
> + struct resource r;
> + struct device_node *np = NULL;
> +#ifdef CONFIG_PPC_I8259
> + struct device_node *cascade_node = NULL;
> + int cascade_irq;
> +#endif
> +
> + np = of_find_node_by_type(np, "open-pic");
> +
> + if (np == NULL) {
> + printk(KERN_ERR "Could not find open-pic node\n");
> + return;
> + }
> +
> + if (of_address_to_resource(np, 0, &r)) {
> + printk(KERN_ERR "Failed to map mpic register space\n");
> + of_node_put(np);
> + return;
> + }
> +
> + /* Alloc mpic structure and per isu has 16 INT entries. */
> + mpic = mpic_alloc(np, r.start,
> + MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
> + 16, NR_IRQS - 10, " OPENPIC ");
Should we must make this 64 instead of NR_IRQS - 10.
> + BUG_ON(mpic == NULL);
> +
> + /* Return the mpic node */
> +
> + mpic_assign_isu(mpic, 0, r.start + 0x10000);
> +
> + /* 48 Internal Interrupts */
> + mpic_assign_isu(mpic, 1, r.start + 0x10200);
> + mpic_assign_isu(mpic, 2, r.start + 0x10400);
> + mpic_assign_isu(mpic, 3, r.start + 0x10600);
> +
> + /* 16 External interrupts
> + * Moving them from [0 - 15] to [64 - 79]
> + */
> + mpic_assign_isu(mpic, 4, r.start + 0x10000);
> +
FYI, I'm going to rework the irq numbering so we stop doing this
reordering.
> + mpic_init(mpic);
> +
> +#ifdef CONFIG_PPC_I8259
> + /* Initialize the i8259 controller */
> + for_each_node_by_type(np, "interrupt-controller")
> + if (device_is_compatible(np, "chrp,iic")) {
> + cascade_node = np;
> + break;
> + }
> +
> + if (cascade_node == NULL) {
> + printk(KERN_DEBUG "Could not find i8259 PIC\n");
> + return;
> + }
> +
> + cascade_irq = irq_of_parse_and_map(cascade_node, 0);
> + if (cascade_irq == NO_IRQ) {
> + printk(KERN_ERR "Failed to map cascade interrupt\n");
> + return;
> + }
> +
> + DBG("mpc8544ds: cascade mapped to irq %d\n", cascade_irq);
> +
> + i8259_init(cascade_node, 0);
> + of_node_put(cascade_node);
> +
> + set_irq_chained_handler(cascade_irq, mpc8544_8259_cascade);
> +#endif /* CONFIG_PPC_I8259 */
> +}
> +
> +#ifdef CONFIG_PCI
> +enum pirq { PIRQA = 8, PIRQB, PIRQC, PIRQD, PIRQE, PIRQF, PIRQG,
> PIRQH };
> +const unsigned char uli1575_irq_route_table[16] = {
> +/* Value in table -- IRQ number */
> + 0, /* 0: Reserved */
> + 0x8, /* 1: 0b1000 */
> + 0, /* 2: Reserved */
> + 0x2, /* 3: 0b0010 */
> + 0x4, /* 4: 0b0100 */
> + 0x5, /* 5: 0b0101 */
> + 0x7, /* 6: 0b0111 */
> + 0x6, /* 7: 0b0110 */
> + 0, /* 8: Reserved */
> + 0x1, /* 9: 0b0001 */
> + 0x3, /* 10: 0b0011 */
> + 0x9, /* 11: 0b1001 */
> + 0xb, /* 12: 0b1011 */
> + 0, /* 13: Reserved */
> + 0xd, /* 14, 0b1101 */
> + 0xf, /* 15, 0b1111 */
> +};
> +
The comments seem a bit silly for numbers in binary.
> +static int __devinit
> +get_pci_irq_from_of(struct pci_controller *hose, int slot, int pin)
> +{
> + struct of_irq oirq;
> + u32 laddr[3];
> + struct device_node *hosenode = hose ? hose->arch_data : NULL;
> +
> + if (!hosenode)
> + return -EINVAL;
> +
> + laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(slot, 0) << 8);
> + laddr[1] = laddr[2] = 0;
> + of_irq_map_raw(hosenode, &pin, 1, laddr, &oirq);
> + DBG("mpc8544_ds: pci irq addr %x, slot %d, pin %d, irq %d\n",
> + laddr[0], slot, pin, oirq.specifier[0]);
> + return oirq.specifier[0];
> +}
> +
> +/*8259*/
> +static void __devinit quirk_uli1575(struct pci_dev *dev)
> +{
> + unsigned short temp;
> + struct pci_controller *hose = pci_bus_to_host(dev->bus);
> + unsigned char irq2pin[16];
> + unsigned long pirq_map_word = 0;
> + u32 irq;
> + int i;
> +
> + /*
> + * ULI1575 interrupts route setup
> + */
> + memset(irq2pin, 0, 16); /* Initialize default value 0 */
> +
> + /*
> + * PIRQE -> PIRQF mapping set manually
> + *
> + * IRQ pin IRQ#
> + * PIRQE ---- 9
> + * PIRQF ---- 10
> + * PIRQG ---- 11
> + * PIRQH ---- 12
> + */
> + for (i = 0; i < 4; i++)
> + irq2pin[i + 9] = PIRQE + i;
> +
> + /* Set IRQ-PIRQ Mapping to ULI1575 */
> + for (i = 0; i < 16; i++)
> + if (irq2pin[i])
> + pirq_map_word |= (uli1575_irq_route_table[i] & 0xf)
> + << ((irq2pin[i] - PIRQA) * 4);
> +
> + /* ULI1575 IRQ mapping conf register default value is 0xb9317542 */
> + DBG("Setup ULI1575 IRQ mapping configuration register value = 0x%x
> \n",
> + pirq_map_word);
> + pci_write_config_dword(dev, 0x48, pirq_map_word);
> +
> +#define ULI1575_SET_DEV_IRQ(slot, pin,
> reg) \
> + do { \
> + int irq; \
> + irq = get_pci_irq_from_of(hose, slot, pin); \
> + if (irq > 0 && irq < 16) { \
> + pci_write_config_byte(dev, reg, irq2pin[irq]); \
> + } \
> + else \
> + printk(KERN_WARNING "ULI1575 device" \
> + "(slot %d, pin %d) irq %d is invalid.\n", \
> + slot, pin, irq); \
> + } while(0)
> +
> + /* USB 1.1 OHCI controller 1, slot 28, pin 1 */
> + ULI1575_SET_DEV_IRQ(28, 1, 0x86);
> +
> + /* USB 1.1 OHCI controller 2, slot 28, pin 2 */
> + ULI1575_SET_DEV_IRQ(28, 2, 0x87);
> +
> + /* USB 1.1 OHCI controller 3, slot 28, pin 3 */
> + ULI1575_SET_DEV_IRQ(28, 3, 0x88);
> +
> + /* USB 2.0 controller, slot 28, pin 4 */
> + irq = get_pci_irq_from_of(hose, 28, 4);
> + if (irq >= 0 && irq <= 15)
> + pci_write_config_dword(dev, 0x74, uli1575_irq_route_table[irq]);
> +
> + /* Audio controller, slot 29, pin 1 */
> + ULI1575_SET_DEV_IRQ(29, 1, 0x8a);
> +
> + /* Modem controller, slot 29, pin 2 */
> + ULI1575_SET_DEV_IRQ(29, 2, 0x8b);
> +
> + /* HD audio controller, slot 29, pin 3 */
> + ULI1575_SET_DEV_IRQ(29, 3, 0x8c);
> +
> + /* SMB interrupt: slot 30, pin 1 */
> + ULI1575_SET_DEV_IRQ(30, 1, 0x8e);
> +
> + /* PMU ACPI SCI interrupt: slot 30, pin 2 */
> + ULI1575_SET_DEV_IRQ(30, 2, 0x8f);
> +
> + /* Serial ATA interrupt: slot 31, pin 1 */
> + ULI1575_SET_DEV_IRQ(31, 1, 0x8d);
> +
> + /* Primary PATA IDE IRQ: 14
> + * Secondary PATA IDE IRQ: 15
> + */
> + pci_write_config_byte(dev, 0x44, 0x30 | uli1575_irq_route_table
> [14]);
> + pci_write_config_byte(dev, 0x75, uli1575_irq_route_table[15]);
> +
> + /* Set IRQ14 and IRQ15 to legacy IRQs */
> + pci_read_config_word(dev, 0x46, &temp);
> + temp |= 0xc000;
> + pci_write_config_word(dev, 0x46, temp);
> +
> + /* Set i8259 interrupt trigger
> + * IRQ 3: Level
> + * IRQ 4: Level
> + * IRQ 5: Level
> + * IRQ 6: Level
> + * IRQ 7: Level
> + * IRQ 9: Level
> + * IRQ 10: Level
> + * IRQ 11: Level
> + * IRQ 12: Level
> + * IRQ 14: Edge
> + * IRQ 15: Edge
> + */
> + outb(0xfa, 0x4d0);
> + outb(0x1e, 0x4d1);
> +
> +#undef ULI1575_SET_DEV_IRQ
> +}
> +
> +/* SATA */
> +static void __devinit quirk_uli5288(struct pci_dev *dev)
> +{
> + unsigned char c;
> +
> + pci_read_config_byte(dev, 0x83, &c);
> + c |= 0x80; /* read/write lock */
> + pci_write_config_byte(dev, 0x83, c);
> +
> + pci_write_config_byte(dev, 0x09, 0x01); /* Base class code:
> storage */
> + pci_write_config_byte(dev, 0x0a, 0x06); /* IDE disk */
> +
> + pci_read_config_byte(dev, 0x83, &c);
> + c &= 0x7f;
> + pci_write_config_byte(dev, 0x83, c);
> +
> + pci_read_config_byte(dev, 0x84, &c);
> + c |= 0x01; /* emulated PATA mode enabled */
> + pci_write_config_byte(dev, 0x84, c);
> +}
> +
> +/* PATA */
> +static void __devinit quirk_uli5229(struct pci_dev *dev)
> +{
> + unsigned short temp;
> + pci_write_config_word(dev, 0x04, 0x0405); /* MEM IO MSI */
> + pci_write_config_byte(dev, 0x09, 0x8a);
> + dev->class &= ~0x5;
> + pci_read_config_word(dev, 0x4a, &temp);
> + temp |= 0x1000; /* Enable Native IRQ 14/15 */
> + pci_write_config_word(dev, 0x4a, temp);
> +}
> +
> +/*Bridge*/
> +static void __devinit early_uli5249(struct pci_dev *dev)
> +{
> + unsigned char temp;
> + pci_write_config_word(dev, 0x04, 0x0007); /* mem access */
> + pci_read_config_byte(dev, 0x7c, &temp);
> + pci_write_config_byte(dev, 0x7c, 0x80); /* R/W lock control */
> + pci_write_config_byte(dev, 0x09, 0x01); /* set as pci-pci bridge */
> + pci_write_config_byte(dev, 0x7c, temp); /* restore pci bus debug
> control */
> + dev->class |= 0x1;
> +}
> +
> +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_uli1575);
> +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288);
> +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229);
> +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, 0x5249, early_uli5249);
> +#endif /* CONFIG_PCI */
> +
> +/*
> + * Setup the architecture
> + */
> +static void __init mpc8544_ds_setup_arch(void)
> +{
> +#ifdef CONFIG_PCI
> + struct device_node *np;
> +#endif
> +
> + if (ppc_md.progress)
> + ppc_md.progress("mpc8544_ds_setup_arch()", 0);
> +
> +#ifdef CONFIG_PCI
> + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
> + add_bridge(np);
> + ppc_md.pci_exclude_device = mpc85xx_exclude_device;
> +#endif
> +
> + printk("MPC8544 DS board from Freescale Semiconductor\n");
> +}
> +
> +void __init mpc8544_ds_pcibios_fixup_bus(struct pci_bus *bus)
> +{
> + if (bus->self && bus->self->vendor == 0x10b9
> + && bus->self->device == 0x5249) {
> + bus->parent->resource[0]->end = bus->parent->resource[0]->start
> + + 0xffff;
> + if (bus->resource[1] && bus->parent->resource[1])
> + bus->parent->resource[1]->end +=
> + bus->resource[1]->end + 1 + 0x100000
> + - bus->resource[1]->start;
> + }
> +}
> +
> +void mpc8544_ds_show_cpuinfo(struct seq_file *m)
> +{
> + struct device_node *root;
> + uint memsize = total_memory;
> + const char *model = "";
> + uint svid = mfspr(SPRN_SVR);
> +
> + seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
> +
> + root = of_find_node_by_path("/");
> + if (root)
> + model = get_property(root, "model", NULL);
> + seq_printf(m, "Machine\t\t: %s\n", model);
> + of_node_put(root);
> +
> + seq_printf(m, "SVR\t\t: 0x%x\n", svid);
> + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
> +}
Is this providing any info we really need? Been removing other
cpuinfo since they aren't too terrible useful.
> +
> +/*
> + * Called very early, device-tree isn't unflattened
> + */
> +static int __init mpc8544_ds_probe(void)
> +{
> + char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
> + "model", NULL);
> + if (model == NULL)
> + return 0;
> + if (strcmp(model, "MPC8544DS"))
> + return 0;
> +
> + DBG("MPC8544DS found\n");
> +
should use of_flat_dt_is_compatible() see other 85xx boards.
> + return 1;
> +}
> +
> +define_machine(mpc8544_ds) {
> + .name = "MPC8544 DS",
> + .probe = mpc8544_ds_probe,
> + .setup_arch = mpc8544_ds_setup_arch,
> + .init_IRQ = mpc8544_ds_pic_init,
> + .show_cpuinfo = mpc8544_ds_show_cpuinfo,
> + .pcibios_fixup_bus = mpc8544_ds_pcibios_fixup_bus,
> + .get_irq = mpic_get_irq,
> + .restart = mpc85xx_restart,
> + .calibrate_decr = generic_calibrate_decr,
> + .progress = udbg_progress,
> +};
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev at ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
More information about the Linuxppc-dev
mailing list